From 68e6552d0735efbbbcafbd9bf83347a0627976a9 Mon Sep 17 00:00:00 2001 From: PuqiAR Date: Thu, 23 Jul 2026 22:50:37 +0800 Subject: [PATCH] =?UTF-8?q?Rewrite:=20C++=20=E2=86=92=20Rust,=20Lexer=20+?= =?UTF-8?q?=20Error=20system=20complete?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 全量 Rust 重写 Fig 编译器前端。 Lexer: 43 个测试,千行压力测试通过,完整 UTF-8 支持(中文标识符/字符串),运算符最长匹配打表,单行/多行注释 + 错误恢复。 Error System: Diagnostic trait + Warning/Error/Critical 三级严重度,源码上下文渲染(Unicode 波浪线、中英双语 i18n),SourcePosition/SourceRange 为 LSP 准备,Related 关联信息,thrower 宏追踪编译器源码位置。 Build: cargo + build.rs(git hash + 编译时间戳)。 删除全部 C++ 源码。 --- .ci/Dockerfile | 33 - .clang-format | 213 - .gitea/workflows/build.yml | 365 - .gitignore | 6 +- Cargo.lock | 7 + Cargo.toml | 6 + README.md | 187 +- README_zh-CN.md | 187 +- build.rs | 63 + compile_flags.txt | 3 - src/Ast/Ast.hpp | 33 - src/Ast/Base.hpp | 167 - src/Ast/Expr/CallExpr.hpp | 61 - src/Ast/Expr/IdentiExpr.hpp | 32 - src/Ast/Expr/IndexExpr.hpp | 35 - src/Ast/Expr/InfixExpr.hpp | 39 - src/Ast/Expr/LambdaExpr.hpp | 70 - src/Ast/Expr/LiteralExpr.hpp | 27 - src/Ast/Expr/MemberExpr.hpp | 35 - src/Ast/Expr/NewExpr.hpp | 50 - src/Ast/Expr/PostfixExpr.hpp | 35 - src/Ast/Expr/PrefixExpr.hpp | 39 - src/Ast/Expr/TernaryExpr.hpp | 35 - src/Ast/Operator.cpp | 193 - src/Ast/Operator.hpp | 96 - src/Ast/Stmt/ControlFlowStmts.hpp | 72 - src/Ast/Stmt/ExprStmt.hpp | 35 - src/Ast/Stmt/FnDefStmt.hpp | 51 - src/Ast/Stmt/ForStmt.hpp | 32 - src/Ast/Stmt/IfStmt.hpp | 69 - src/Ast/Stmt/ImplStmt.hpp | 32 - src/Ast/Stmt/ImportStmt.hpp | 33 - src/Ast/Stmt/InterfaceDefStmt.hpp | 39 - src/Ast/Stmt/StructDefStmt.hpp | 59 - src/Ast/Stmt/VarDecl.hpp | 47 - src/Ast/Stmt/WhileStmt.hpp | 37 - src/Ast/TypeExpr.hpp | 100 - src/Bytecode/Bytecode.hpp | 122 - src/Bytecode/Disassembler.cpp | 102 - src/Bytecode/Disassembler.hpp | 35 - src/Compiler/Compiler.hpp | 64 - src/Core/Core.hpp | 13 - src/Core/CoreIO.cpp | 49 - src/Core/CoreIO.hpp | 20 - src/Core/CoreInfos.hpp | 143 - src/Core/RuntimeTime.cpp | 25 - src/Core/RuntimeTime.hpp | 17 - src/Core/SourceLocations.hpp | 59 - src/Deps/Deps.hpp | 34 - src/Deps/DynArray/DynArray.hpp | 14 - src/Deps/HashMap/HashMap.hpp | 20 - src/Deps/String/CharUtils.hpp | 130 - src/Deps/String/String.hpp | 1074 - src/Deps/String/StringTest.cpp | 144 - src/Error/Diagnostics.hpp | 47 - src/Error/Error.cpp | 200 - src/Error/Error.hpp | 185 - src/LSP/LSPServer.hpp | 180 - src/Lexer/Lexer.cpp | 328 - src/Lexer/Lexer.hpp | 189 - src/Lexer/LexerTest.cpp | 44 - src/Object/FunctionObject.hpp | 40 - src/Object/InstanceObject.hpp | 16 - src/Object/Object.cpp | 67 - src/Object/Object.hpp | 14 - src/Object/ObjectBase.hpp | 283 - src/Object/ObjectTest.cpp | 20 - src/Object/StringObject.hpp | 29 - src/Object/StructObject.hpp | 52 - src/Parser/ExprParser.cpp | 549 - src/Parser/Parser.cpp | 37 - src/Parser/Parser.hpp | 305 - src/Parser/ParserTest.cpp | 42 - src/Parser/StmtParser.cpp | 1239 - src/Parser/TypeExprParser.cpp | 201 - src/Repl/Repl.hpp | 311 - src/Repl/ReplTest.cpp | 10 - src/Sema/Analyzer.hpp | 32 - src/Sema/Environment.hpp | 63 - src/Sema/Type.hpp | 36 - src/SourceManager/SourceManager.hpp | 146 - src/Token/Token.cpp | 96 - src/Token/Token.hpp | 168 - src/Utils/Arena.hpp | 115 - src/Utils/ArgParser/ArgParser.hpp | 336 - src/Utils/ConsoleSize.hpp | 88 - src/Utils/json/json.hpp | 25526 ---------------- src/Utils/magic_enum/magic_enum.hpp | 1508 - src/Utils/magic_enum/magic_enum_all.hpp | 44 - .../magic_enum/magic_enum_containers.hpp | 1174 - src/Utils/magic_enum/magic_enum_flags.hpp | 222 - src/Utils/magic_enum/magic_enum_format.hpp | 114 - src/Utils/magic_enum/magic_enum_fuse.hpp | 89 - src/Utils/magic_enum/magic_enum_iostream.hpp | 117 - src/Utils/magic_enum/magic_enum_switch.hpp | 195 - src/Utils/magic_enum/magic_enum_utility.hpp | 138 - src/VM/Entry.cpp | 199 - src/VM/Entry.hpp | 26 - src/VM/VM.cpp | 442 - src/VM/VM.hpp | 411 - src/VM/__VMTest.cpp | 5 - src/core/build_info.rs | 48 + src/core/colors.rs | 32 + src/core/mod.rs | 18 + src/core/source.rs | 124 + .../definitions/invalid_escape_sequence.rs | 63 + .../definitions/invalid_number_literal.rs | 72 + src/error/definitions/mod.rs | 12 + src/error/definitions/unexpected_character.rs | 90 + src/error/definitions/unterminated_comment.rs | 83 + .../unterminated_string_literal.rs | 83 + src/error/diagnostic.rs | 137 + src/error/hint.rs | 13 + src/error/mod.rs | 11 + src/error/report.rs | 536 + src/lexer/lexer.rs | 942 + src/lexer/mod.rs | 10 + src/main.cpp | 101 - src/main.rs | 14 + src/token/mod.rs | 231 + tests/Compiler/test_basic.fig | 9 - tests/Parser/parser_comprehensive_test.fig | 232 - tests/Sema/err_control_flow.fig | 3 - tests/Sema/err_redeclare.fig | 4 - tests/Sema/err_struct_field.fig | 4 - tests/Sema/err_undeclared.fig | 4 - xmake.lua | 71 - 127 files changed, 2624 insertions(+), 40689 deletions(-) delete mode 100644 .ci/Dockerfile delete mode 100644 .clang-format delete mode 100644 .gitea/workflows/build.yml create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 build.rs delete mode 100644 compile_flags.txt delete mode 100644 src/Ast/Ast.hpp delete mode 100644 src/Ast/Base.hpp delete mode 100644 src/Ast/Expr/CallExpr.hpp delete mode 100644 src/Ast/Expr/IdentiExpr.hpp delete mode 100644 src/Ast/Expr/IndexExpr.hpp delete mode 100644 src/Ast/Expr/InfixExpr.hpp delete mode 100644 src/Ast/Expr/LambdaExpr.hpp delete mode 100644 src/Ast/Expr/LiteralExpr.hpp delete mode 100644 src/Ast/Expr/MemberExpr.hpp delete mode 100644 src/Ast/Expr/NewExpr.hpp delete mode 100644 src/Ast/Expr/PostfixExpr.hpp delete mode 100644 src/Ast/Expr/PrefixExpr.hpp delete mode 100644 src/Ast/Expr/TernaryExpr.hpp delete mode 100644 src/Ast/Operator.cpp delete mode 100644 src/Ast/Operator.hpp delete mode 100644 src/Ast/Stmt/ControlFlowStmts.hpp delete mode 100644 src/Ast/Stmt/ExprStmt.hpp delete mode 100644 src/Ast/Stmt/FnDefStmt.hpp delete mode 100644 src/Ast/Stmt/ForStmt.hpp delete mode 100644 src/Ast/Stmt/IfStmt.hpp delete mode 100644 src/Ast/Stmt/ImplStmt.hpp delete mode 100644 src/Ast/Stmt/ImportStmt.hpp delete mode 100644 src/Ast/Stmt/InterfaceDefStmt.hpp delete mode 100644 src/Ast/Stmt/StructDefStmt.hpp delete mode 100644 src/Ast/Stmt/VarDecl.hpp delete mode 100644 src/Ast/Stmt/WhileStmt.hpp delete mode 100644 src/Ast/TypeExpr.hpp delete mode 100644 src/Bytecode/Bytecode.hpp delete mode 100644 src/Bytecode/Disassembler.cpp delete mode 100644 src/Bytecode/Disassembler.hpp delete mode 100644 src/Compiler/Compiler.hpp delete mode 100644 src/Core/Core.hpp delete mode 100644 src/Core/CoreIO.cpp delete mode 100644 src/Core/CoreIO.hpp delete mode 100644 src/Core/CoreInfos.hpp delete mode 100644 src/Core/RuntimeTime.cpp delete mode 100644 src/Core/RuntimeTime.hpp delete mode 100644 src/Core/SourceLocations.hpp delete mode 100644 src/Deps/Deps.hpp delete mode 100644 src/Deps/DynArray/DynArray.hpp delete mode 100644 src/Deps/HashMap/HashMap.hpp delete mode 100644 src/Deps/String/CharUtils.hpp delete mode 100644 src/Deps/String/String.hpp delete mode 100644 src/Deps/String/StringTest.cpp delete mode 100644 src/Error/Diagnostics.hpp delete mode 100644 src/Error/Error.cpp delete mode 100644 src/Error/Error.hpp delete mode 100644 src/LSP/LSPServer.hpp delete mode 100644 src/Lexer/Lexer.cpp delete mode 100644 src/Lexer/Lexer.hpp delete mode 100644 src/Lexer/LexerTest.cpp delete mode 100644 src/Object/FunctionObject.hpp delete mode 100644 src/Object/InstanceObject.hpp delete mode 100644 src/Object/Object.cpp delete mode 100644 src/Object/Object.hpp delete mode 100644 src/Object/ObjectBase.hpp delete mode 100644 src/Object/ObjectTest.cpp delete mode 100644 src/Object/StringObject.hpp delete mode 100644 src/Object/StructObject.hpp delete mode 100644 src/Parser/ExprParser.cpp delete mode 100644 src/Parser/Parser.cpp delete mode 100644 src/Parser/Parser.hpp delete mode 100644 src/Parser/ParserTest.cpp delete mode 100644 src/Parser/StmtParser.cpp delete mode 100644 src/Parser/TypeExprParser.cpp delete mode 100644 src/Repl/Repl.hpp delete mode 100644 src/Repl/ReplTest.cpp delete mode 100644 src/Sema/Analyzer.hpp delete mode 100644 src/Sema/Environment.hpp delete mode 100644 src/Sema/Type.hpp delete mode 100644 src/SourceManager/SourceManager.hpp delete mode 100644 src/Token/Token.cpp delete mode 100644 src/Token/Token.hpp delete mode 100644 src/Utils/Arena.hpp delete mode 100644 src/Utils/ArgParser/ArgParser.hpp delete mode 100644 src/Utils/ConsoleSize.hpp delete mode 100644 src/Utils/json/json.hpp delete mode 100644 src/Utils/magic_enum/magic_enum.hpp delete mode 100644 src/Utils/magic_enum/magic_enum_all.hpp delete mode 100644 src/Utils/magic_enum/magic_enum_containers.hpp delete mode 100644 src/Utils/magic_enum/magic_enum_flags.hpp delete mode 100644 src/Utils/magic_enum/magic_enum_format.hpp delete mode 100644 src/Utils/magic_enum/magic_enum_fuse.hpp delete mode 100644 src/Utils/magic_enum/magic_enum_iostream.hpp delete mode 100644 src/Utils/magic_enum/magic_enum_switch.hpp delete mode 100644 src/Utils/magic_enum/magic_enum_utility.hpp delete mode 100644 src/VM/Entry.cpp delete mode 100644 src/VM/Entry.hpp delete mode 100644 src/VM/VM.cpp delete mode 100644 src/VM/VM.hpp delete mode 100644 src/VM/__VMTest.cpp create mode 100644 src/core/build_info.rs create mode 100644 src/core/colors.rs create mode 100644 src/core/mod.rs create mode 100644 src/core/source.rs create mode 100644 src/error/definitions/invalid_escape_sequence.rs create mode 100644 src/error/definitions/invalid_number_literal.rs create mode 100644 src/error/definitions/mod.rs create mode 100644 src/error/definitions/unexpected_character.rs create mode 100644 src/error/definitions/unterminated_comment.rs create mode 100644 src/error/definitions/unterminated_string_literal.rs create mode 100644 src/error/diagnostic.rs create mode 100644 src/error/hint.rs create mode 100644 src/error/mod.rs create mode 100644 src/error/report.rs create mode 100644 src/lexer/lexer.rs create mode 100644 src/lexer/mod.rs delete mode 100644 src/main.cpp create mode 100644 src/main.rs create mode 100644 src/token/mod.rs delete mode 100644 tests/Compiler/test_basic.fig delete mode 100644 tests/Parser/parser_comprehensive_test.fig delete mode 100644 tests/Sema/err_control_flow.fig delete mode 100644 tests/Sema/err_redeclare.fig delete mode 100644 tests/Sema/err_struct_field.fig delete mode 100644 tests/Sema/err_undeclared.fig delete mode 100644 xmake.lua diff --git a/.ci/Dockerfile b/.ci/Dockerfile deleted file mode 100644 index 9523d19..0000000 --- a/.ci/Dockerfile +++ /dev/null @@ -1,33 +0,0 @@ -FROM ubuntu:24.04 - -# 1. 设置镜像源(可选,用于加速) -RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list && \ - sed -i 's/security.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list - -# 2. 一次性安装所有依赖(工具链、库、CI工具) -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - wget gnupg ca-certificates \ - clang-19 lld-19 libc++-19-dev libc++abi-19-dev \ - mingw-w64 g++-mingw-w64 \ - git tar curl \ - python3 python3-pip python3.12-venv libpython3.12 \ - && rm -rf /var/lib/apt/lists/* && \ - update-alternatives --install /usr/bin/clang clang /usr/bin/clang-19 100 && \ - update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-19 100 && \ - ln -sf /usr/bin/ld.lld-19 /usr/bin/ld.lld - -# 3. 安装xmake -RUN wget -O /usr/local/bin/xmake \ - https://git.fig-lang.cn/PuqiAR/xmake-binary-copy/raw/commit/989d1f2dabb0bc8d5981a5f900c2cf7c2ac78ee4/xmake-bundle-v3.0.5.linux.x86_64 && \ - chmod +x /usr/local/bin/xmake - -# 4. 创建非root用户 -RUN useradd -m -s /bin/bash builder -USER builder -WORKDIR /home/builder - -RUN xmake --version | head -1 && \ - clang++ --version | head -1 && \ - git --version && \ - echo "✅ 核心工具就绪" \ No newline at end of file diff --git a/.clang-format b/.clang-format deleted file mode 100644 index 44e8d27..0000000 --- a/.clang-format +++ /dev/null @@ -1,213 +0,0 @@ -# 语言: None, Cpp, Java, JavaScript, ObjC, Proto, TableGen, TextProto -Language: Cpp -# BasedOnStyle: LLVM - -# 访问说明符(public、private等)的偏移 -AccessModifierOffset: -4 - -# 开括号(开圆括号、开尖括号、开方括号)后的对齐: Align, DontAlign, AlwaysBreak(总是在开括号后换行) -AlignAfterOpenBracket: AlwaysBreak - -# 连续赋值时,对齐所有等号 -AlignConsecutiveAssignments: true - -# 连续声明时,对齐所有声明的变量名 -AlignConsecutiveDeclarations: true - -# 右对齐逃脱换行(使用反斜杠换行)的反斜杠 -AlignEscapedNewlines: Right - -# 水平对齐二元和三元表达式的操作数 -AlignOperands: true - -# 对齐连续的尾随的注释 -AlignTrailingComments: true - -# 允许函数声明的所有参数在放在下一行 -AllowAllParametersOfDeclarationOnNextLine: true - -# 允许短的块放在同一行 -AllowShortBlocksOnASingleLine: true - -# 允许短的case标签放在同一行 -AllowShortCaseLabelsOnASingleLine: true - -# 允许短的函数放在同一行: None, InlineOnly(定义在类中), Empty(空函数), Inline(定义在类中,空函数), All -AllowShortFunctionsOnASingleLine: Empty - -# 允许短的if语句保持在同一行 -AllowShortIfStatementsOnASingleLine: false - -# 允许短的循环保持在同一行 -AllowShortLoopsOnASingleLine: false - -# 总是在返回类型后换行: None, All, TopLevel(顶级函数,不包括在类中的函数), -# AllDefinitions(所有的定义,不包括声明), TopLevelDefinitions(所有的顶级函数的定义) -AlwaysBreakAfterReturnType: None - -# 总是在多行string字面量前换行 -AlwaysBreakBeforeMultilineStrings: false - -# 总是在template声明后换行 -AlwaysBreakTemplateDeclarations: true - -# false表示函数实参要么都在同一行,要么都各自一行 -BinPackArguments: false - -# false表示所有形参要么都在同一行,要么都各自一行 -BinPackParameters: false - -# 大括号换行,只有当BreakBeforeBraces设置为Custom时才有效 -BraceWrapping: - # class定义后面 - AfterClass: true - # 控制语句后面 - AfterControlStatement: true - # enum定义后面 - AfterEnum: true - # 函数定义后面 - AfterFunction: true - # 命名空间定义后面 - AfterNamespace: true - # struct定义后面 - AfterStruct: true - # union定义后面 - AfterUnion: true - # extern之后 - AfterExternBlock: false - # catch之前 - BeforeCatch: true - # else之前 - BeforeElse: true - # 缩进大括号 - IndentBraces: false - # 分离空函数 - SplitEmptyFunction: true - # 分离空语句 - SplitEmptyRecord: false - # 分离空命名空间 - SplitEmptyNamespace: false - -# 在二元运算符前换行: None(在操作符后换行), NonAssignment(在非赋值的操作符前换行), All(在操作符前换行) -BreakBeforeBinaryOperators: NonAssignment - -# 在大括号前换行: Attach(始终将大括号附加到周围的上下文), Linux(除函数、命名空间和类定义,与Attach类似), -# Mozilla(除枚举、函数、记录定义,与Attach类似), Stroustrup(除函数定义、catch、else,与Attach类似), -# Allman(总是在大括号前换行), GNU(总是在大括号前换行,并对于控制语句的大括号增加额外的缩进), WebKit(在函数前换行), Custom -# 注:这里认为语句块也属于函数 -BreakBeforeBraces: Custom - -# 在三元运算符前换行 -BreakBeforeTernaryOperators: false - -# 在构造函数的初始化列表的冒号后换行 -BreakConstructorInitializers: AfterColon - -#BreakInheritanceList: AfterColon - -BreakStringLiterals: false - -# 每行字符的限制,0表示没有限制 -ColumnLimit: 100 -CompactNamespaces: true - -# 构造函数的初始化列表要么都在同一行,要么都各自一行 -ConstructorInitializerAllOnOneLineOrOnePerLine: true - -# 构造函数的初始化列表的缩进宽度 -ConstructorInitializerIndentWidth: 4 - -# 延续的行的缩进宽度 -ContinuationIndentWidth: 4 - -# 去除C++11的列表初始化的大括号{后和}前的空格 -Cpp11BracedListStyle: true - -# 继承最常用的指针和引用的对齐方式 -DerivePointerAlignment: false - -# 固定命名空间注释 -FixNamespaceComments: true - -# 缩进case标签 -IndentCaseLabels: true - -IndentPPDirectives: BeforeHash - -# 缩进宽度 -IndentWidth: 4 - -# 函数返回类型换行时,缩进函数声明或函数定义的函数名 -IndentWrappedFunctionNames: false - -# 保留在块开始处的空行 -KeepEmptyLinesAtTheStartOfBlocks: false - -# 连续空行的最大数量 -MaxEmptyLinesToKeep: 1 - -# 命名空间的缩进: None, Inner(缩进嵌套的命名空间中的内容), All -NamespaceIndentation: All - -# 指针和引用的对齐: Left, Right, Middle -PointerAlignment: Right - -# 允许重新排版注释 -ReflowComments: true - -# 允许排序#include -SortIncludes: true - -# 允许排序 using 声明 -SortUsingDeclarations: false - -# 在C风格类型转换后添加空格 -SpaceAfterCStyleCast: true -# true -> (int) 0.1 false-> (int)0.1 - -# 在Template 关键字后面添加空格 -SpaceAfterTemplateKeyword: true - -# 在赋值运算符之前添加空格 -SpaceBeforeAssignmentOperators: true - -# SpaceBeforeCpp11BracedList: true - -# SpaceBeforeCtorInitializerColon: true - -# SpaceBeforeInheritanceColon: true - -# 开圆括号之前添加一个空格: Never, ControlStatements, Always -SpaceBeforeParens: ControlStatements - -# SpaceBeforeRangeBasedForLoopColon: true - -# 在空的圆括号中添加空格 -SpaceInEmptyParentheses: false - -# 在尾随的评论前添加的空格数(只适用于//) -SpacesBeforeTrailingComments: 1 - -# 在尖括号的<后和>前添加空格 -SpacesInAngles: false - -# 在C风格类型转换的括号中添加空格 -SpacesInCStyleCastParentheses: false - -# 在容器(ObjC和JavaScript的数组和字典等)字面量中添加空格 -SpacesInContainerLiterals: true - -# 在圆括号的(后和)前添加空格 -SpacesInParentheses: false - -# 在方括号的[后和]前添加空格,lamda表达式和未指明大小的数组的声明不受影响 -SpacesInSquareBrackets: false - -# 标准: Cpp03, Cpp11, Auto -Standard: Auto - -# tab宽度 -TabWidth: 4 - -# 使用tab字符: Never, ForIndentation, ForContinuationAndIndentation, Always -UseTab: Never \ No newline at end of file diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml deleted file mode 100644 index 62b6286..0000000 --- a/.gitea/workflows/build.yml +++ /dev/null @@ -1,365 +0,0 @@ -name: Release Build -on: - push: - tags: ["*"] - workflow_dispatch: - inputs: - version: - description: "版本号 (例如: v1.0.0)" - required: true - default: "dev-build" - -jobs: - build-linux-x64: - runs-on: ubuntu - container: - image: git.fig-lang.cn/puqiar/fig-ci:base-latest - options: --network=host - - steps: - - name: 验证构建环境 - run: | - echo "=== 环境验证开始 ===" - xmake --version - clang++ --version | head -1 - echo "=== 环境验证通过 ===" - - - name: 检出代码 - run: | - git clone https://git.fig-lang.cn/${{ github.repository }} . - git checkout ${{ github.ref }} - - - name: 设置版本和提交信息 - run: | - if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then - VERSION="${{ inputs.version }}" - else - VERSION="${{ github.ref_name }}" - fi - echo "构建版本: $VERSION" - echo "VERSION=$VERSION" >> $GITHUB_ENV - - # 拿提交消息 - COMMIT_MSG=$(git log -3 --pretty=%B) - echo "COMMIT_MSG<> $GITHUB_ENV - echo "$COMMIT_MSG" >> $GITHUB_ENV - echo "EOF" >> $GITHUB_ENV - - - name: 构建项目 (Linux) - run: | - echo "开始构建Linux版本..." - xmake f -p linux -a x86_64 -m release -y - xmake build -j$(nproc) Fig - echo "Linux构建成功。" - - # 🔧 新增:构建Linux平台安装器 - - name: 构建Linux安装器 - run: | - echo "开始构建Linux安装器..." - - cd Installer/ConsoleInstaller - - python3 -m venv venv - . venv/bin/activate - - pip config set global.index-url https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple - - # 安装依赖并构建 - pip install --upgrade pip - pip install -r requirements.txt - python3 -m PyInstaller -F -n FigSetup-Linux --distpath ./dist/linux main.py - echo "Linux安装器构建完成" - - - name: 打包Linux发布文件 - run: | - VERSION="${{ env.VERSION }}" - PACKAGE_NAME="Fig-${VERSION}-linux-x86_64" - mkdir -p "${PACKAGE_NAME}" - cp build/linux/x86_64/release/Fig "${PACKAGE_NAME}/" - if [ -d "src/Module/Library" ]; then - cp -r src/Module/Library "${PACKAGE_NAME}/" - echo "已包含Library目录。" - fi - tar -czf "${PACKAGE_NAME}.tar.gz" "${PACKAGE_NAME}" - sha256sum "${PACKAGE_NAME}.tar.gz" > "${PACKAGE_NAME}.sha256" - echo "Linux打包完成: ${PACKAGE_NAME}.tar.gz" - - - name: 发布Linux版本到Gitea - env: - GITEA_TOKEN: ${{ secrets.CI_TOKEN }} - run: | - VERSION="${{ env.VERSION }}" - if [ -z "$VERSION" ]; then - VERSION="${{ github.ref_name }}" - fi - COMMIT_MSG="${{ env.COMMIT_MSG }}" - API="https://git.fig-lang.cn/api/v1/repos/${{ github.repository }}" - - echo "正在检查版本 $VERSION 的发布状态..." - - # 准备 JSON 数据 - VERSION="$VERSION" COMMIT_MSG="$COMMIT_MSG" python3 -c "import json, os; print(json.dumps({'tag_name': os.environ.get('VERSION', ''), 'name': 'Fig ' + os.environ.get('VERSION', ''), 'body': os.environ.get('COMMIT_MSG', ''), 'draft': False, 'prerelease': False}))" > release_body.json - - # 1. 尝试获取已有发布 - RESPONSE_TAG=$(curl -sS -H "Authorization: token $GITEA_TOKEN" "$API/releases/tags/$VERSION" 2>/dev/null || echo '{"id":0}') - RELEASE_ID=$(echo "$RESPONSE_TAG" | grep -o '"id":[0-9]*' | head -1 | cut -d':' -f2) - - if [ -n "$RELEASE_ID" ] && [ "$RELEASE_ID" != "0" ]; then - echo "✅ 找到已有发布 (ID: $RELEASE_ID),正在更新说明..." - curl -sS -X PATCH -H "Authorization: token $GITEA_TOKEN" \ - -H "Content-Type: application/json" \ - -d @release_body.json \ - "$API/releases/$RELEASE_ID" > /dev/null - else - echo "未找到已有发布,准备创建新发布..." - RESPONSE=$(curl -sS -X POST -H "Authorization: token $GITEA_TOKEN" \ - -H "Content-Type: application/json" \ - -d @release_body.json \ - "$API/releases" 2>/dev/null || echo '{"id":0}') - - RELEASE_ID=$(echo "$RESPONSE" | grep -o '"id":[0-9]*' | head -1 | cut -d':' -f2) - - if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "0" ]; then - # 再次尝试获取,防止并发冲突 - RESPONSE_TAG=$(curl -sS -H "Authorization: token $GITEA_TOKEN" "$API/releases/tags/$VERSION" 2>/dev/null || echo '{"id":0}') - RELEASE_ID=$(echo "$RESPONSE_TAG" | grep -o '"id":[0-9]*' | head -1 | cut -d':' -f2) - fi - fi - - if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "0" ]; then - echo "❌ 错误:无法获取或创建发布 ID" - exit 1 - fi - - echo "✅ 使用发布 ID: $RELEASE_ID 进行上传" - - # 上传资产 - PACKAGE_ZIP="Fig-$VERSION-linux-x86_64.tar.gz" - PACKAGE_SHA="Fig-$VERSION-linux-x86_64.sha256" - - echo "正在上传 $PACKAGE_ZIP ..." - curl -sS -X POST -H "Authorization: token $GITEA_TOKEN" \ - -H "Content-Type: application/octet-stream" \ - --data-binary "@$PACKAGE_ZIP" \ - "$API/releases/$RELEASE_ID/assets?name=$PACKAGE_ZIP" > /dev/null - - echo "正在上传 $PACKAGE_SHA ..." - curl -sS -X POST -H "Authorization: token $GITEA_TOKEN" \ - -H "Content-Type: text/plain" \ - --data-binary "@$PACKAGE_SHA" \ - "$API/releases/$RELEASE_ID/assets?name=$PACKAGE_SHA" > /dev/null - - # 🔧 上传Linux安装器 - INSTALLER="Installer/ConsoleInstaller/dist/linux/FigSetup-Linux" - if [ -f "$INSTALLER" ]; then - echo "正在上传Linux安装器..." - curl -sS -X POST -H "Authorization: token $GITEA_TOKEN" \ - -H "Content-Type: application/octet-stream" \ - --data-binary "@$INSTALLER" \ - "$API/releases/$RELEASE_ID/assets?name=FigSetup-Linux" > /dev/null - fi - - echo "✅ Linux版本发布完成!" - - build-windows-x64: - runs-on: windows - - steps: - - name: 验证Windows工具链 - run: | - Set-ExecutionPolicy Bypass -Scope Process -Force - # 检查 xmake - if (Get-Command xmake -ErrorAction SilentlyContinue) { - Write-Host '✅ xmake 已安装' - xmake --version - } else { Write-Host '警告: xmake 未找到' } - # 检查 clang++ - if (Get-Command clang++ -ErrorAction SilentlyContinue) { - Write-Host '✅ clang++ 已安装' - clang++ --version - } else { Write-Host '警告: clang++ 未找到' } - - - name: 检出代码 - run: | - $env:Path = "C:\Program Files\Git\cmd;$env:Path" - git clone https://git.fig-lang.cn/$env:GITHUB_REPOSITORY . - git checkout ${{ github.ref }} - - - name: 设置版本和提交信息 - run: | - [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 - if ($env:GITHUB_EVENT_NAME -eq 'workflow_dispatch') { - $VERSION = $env:INPUT_VERSION - if (-not $VERSION) { $VERSION = $env:VERSION_INPUT } - if (-not $VERSION) { $VERSION = "dev-build" } - } else { - $VERSION = "${{ github.ref_name }}" - } - Write-Host "构建版本: $VERSION" - - # 确保无 BOM 的 UTF8 - [System.IO.File]::AppendAllText($env:GITHUB_ENV, "VERSION=$VERSION`n") - - # 提交消息 - $COMMIT_MSG = git log -3 --pretty=%B - [System.IO.File]::AppendAllText($env:GITHUB_ENV, "COMMIT_MSG< Fig Logo @@ -13,183 +11,22 @@ [English](./README.md) | [中文](./README_zh-CN.md) ![License](https://img.shields.io/badge/license-MIT-blue) -![Status](https://img.shields.io/badge/status-0.5.0--alpha-yellow) -![C++](https://img.shields.io/badge/C++-99.5%25-blue) -![xmake](https://img.shields.io/badge/xmake-build-green) -![LLVM](https://img.shields.io/badge/LLVM-clang%2021.1.8-purple) +![Status](https://img.shields.io/badge/status-0.6.0--alpha-yellow) +![Rust](https://img.shields.io/badge/Rust-100%25-orange) +![cargo](https://img.shields.io/badge/cargo-build-green) ![Platform](https://img.shields.io/badge/Windows%20·%20Linux%20·%20macOS-lightgrey) -![Performance](https://img.shields.io/badge/fib(30)-~28ms%20(i5--13490f)-brightgreen) -**Fig** is a programming language that blends dynamic typing with optional static type annotations, built on reference-based value semantics. It offers the flexibility of scripting languages while providing optional type constraints for more robust code. +**Fig** is a programming language that blends dynamic typing with optional static type annotations, built on reference-based value semantics. -> ⚠️ **Fig is currently at version 0.5.0-alpha, and its syntax and APIs are subject to change.** Feel free to try it out and provide feedback, but do not use it in production environments. +> **v0.6.0 — Rust rewrite in progress.** -```fig -// Get a feel for Fig -var flexible = 10 // dynamic type, can be any value -flexible = "hello" // works +## Progress -var fixed := 20 // fixed to Int type -// fixed = 3.14 // error! type mismatch - -func greet(name) => "Hello, " + name + "!" -println(greet("Fig")) // output: Hello, Fig! ``` - -## ✨ Key Features - -### 🎭 Dynamic & Static Blending -Variables are dynamic by default (`Any` type), but you can lock their type using `:=` or `: Type` for static safety. - -```fig -var any; // type is Any -any = 42; // now points to an Int -any = [1,2,3]; // now points to a List - -var safe := 100; // inferred as Int, can only be assigned Int values -safe = 200; // ✅ -// safe = "oops" // ❌ compile error +Lexer ████████████████████ 100% (43 tests, all pass) +Parser ░░░░░░░░░░░░░░░░░░░░ 0% +Analyzer ░░░░░░░░░░░░░░░░░░░░ 0% +Compiler ░░░░░░░░░░░░░░░░░░░░ 0% +VM ░░░░░░░░░░░░░░░░░░░░ 0% +LSP ░░░░░░░░░░░░░░░░░░░░ 0% ``` - -### 🔗 Reference-Based Value Semantics -All objects are immutable; variables are just "names" that refer to objects. Multiple variables can share the same object, and modifications to complex types (like lists) are visible to all references—this is the essence of references. - -```fig -var a := [1, 2, 3]; -var b := a; // b and a refer to the same list -a[0] = 99; // modify the list content -println(b) // output: [99, 2, 3] — b sees the change - -// Need a true copy? Use deep copy (syntax may change) -var c := new List{a}; // deep copy of a -c[0] = 0; -println(a) // still [99, 2, 3] -``` - -### 🏗 Object-Oriented Features (OOP) -Fig provides lightweight OOP support based on structs, with polymorphism via interfaces. - -- **Structs as classes**: defined with `struct`, can have fields and methods. -- **Access control**: `public` keyword; fields are private by default. -- **Concise construction**: - ```fig - var p1 := new Point{1, 2}; // positional - var p2 := new Point{x: 2, y: 3}; // named - var x := 5, y := 10; - var p3 := new Point{y, x}; // shorthand, auto field matching - ``` -- **Interfaces and implementations**: - ```fig - interface Drawable { draw() -> String; } - struct Circle { radius: Double } - impl Drawable for Circle { - draw() => "⚪ radius: " + radius; - } - ``` -- **No inheritance, polymorphism via interfaces** (currently implicit `this`, may change to explicit `self.xxx` in the future). - -### 🧩 Functional Features -Functions are first-class citizens, with support for closures and concise arrow syntax. - -```fig -func multiplier(factor) { - return func (n) => n * factor; // closure (upvalue) -} - -var double = multiplier(2); -println(double(5)) // output: 10 -``` - -### ⚡ High Performance -**Recursive fib(30) takes only 28ms** (i5-13490f, Windows 11, DDR4 2667, clang 21.1.8, libc++, C++23) — excellent performance among dynamic languages. - -Fig achieves high performance through a series of low-level optimizations: -- **Register-based VM**: replaces the tree-walk interpreter, dramatically improving execution speed. -- **FastCall optimization**: global ordinary functions can be called directly as prototypes, avoiding runtime unwrapping overhead (traditional calls require checking if an object is a function and unwrapping it). -- **Window Slicing** (originated from Lua): a stack sliding window technique that efficiently manages function calls and closures (upvalues), reducing memory allocations. -- **Upvalue mechanism**: lightweight closure implementation, making functional programming performant. -- **Computed Goto**: leverages GCC/Clang extensions to speed up bytecode dispatch. -- **NaN-Boxing**: efficient storage and type tagging to boost dynamic typing performance. - -#### Performance Comparison -Rough comparison of recursive fib(30) execution times (environment may vary, for reference only): - -| Language Type | Language | Time (ms) | Notes | -|---------------|----------------|-----------|-------| -| AOT compiled | C (clang -O2) | ~0.05 | Nanoseconds, as a speed reference | -| AOT compiled | Rust (--release) | ~0.06 | Same as above | -| **Dynamic** | **Fig** | **~28** | **Register VM + optimizations** | -| Dynamic | Lua 5.4 | ~35 | Classic dynamic language | -| Dynamic | Python 3.11 | ~450 | CPython | -| Dynamic | Node.js 20 | ~60 | V8 engine | -| Dynamic | Ruby 3.2 | ~800 | CRuby | - -*Fig performs admirably among dynamic languages, approaching Lua and Node.js, and significantly outperforming Python and Ruby.* - -## 🚀 Quick Start - -### Installation - -#### Option 1: Download Pre-built Binaries -Download the binary for your platform from the [main repository Releases](https://git.fig-lang.cn/PuqiAR/Fig/releases) or the [GitHub mirror](https://github.com/PuqiAR/Fig/releases), extract it, and add it to your PATH. - -#### Option 2: Build from Source with xmake -```bash -# Clone the main repository (GitHub is a mirror) -git clone https://git.fig-lang.cn/PuqiAR/Fig.git -cd Fig - -# Install xmake if you haven't: https://xmake.io - -# Build (must use clang because computed goto requires compiler support) -xmake f --toolchain=clang -xmake - -# After building, the binary is in the build/ directory -``` - -### Run Your First Fig Program -Create a file `hello.fig`: -```fig -import std.io; // io module must be imported; println and others reside here -println("Hello, Fig!"); -``` -Run it: -```bash -./build/fig hello.fig -``` -Or if you added `fig` to your PATH: -```bash -fig hello.fig -``` - -## 📊 Current Status & Roadmap - -| Status | Module | Description | -|--------|----------------------------|-------------| -| ✅ | Frontend | Lexer, parser, AST, semantic analysis | -| ✅ | Core semantics | Variables, functions, closures, structs, interfaces, type system | -| ✅ | Built-in types | 13 built-in types (Any, Null, Int, String, Bool, Double, Function, StructType, StructInstance, List, Map, Module, InterfaceType) | -| 🚧 | Register VM | Original tree-walk interpreter deprecated; VM in development | -| 🚧 | Garbage Collection | Basic GC implemented, optimizing | -| 📝 | Standard Library | IO preliminarily available; more libraries to come | -| 📝 | FFI | Foreign function interface (C ABI) | -| 📝 | LSP | Language Server Protocol support | - -## 📚 Documentation & Community - -- **Documentation**: Check the [`/docs`](./docs) directory (continuously updated) -- **Example Code**: [`/ExampleCodes`](./ExampleCodes) contains various usage demonstrations -- **Contributing**: Issues and PRs are welcome at the main repository - - Report bugs - - Discuss features - - Improve documentation -- **License**: MIT © PuqiAR -- **Author**: PuqiAR · [im@puqiar.top](mailto:im@puqiar.top) -- **Links**: - - [Main Repository](https://git.fig-lang.cn/PuqiAR/Fig) - - [GitHub Mirror](https://github.com/PuqiAR/Fig) - ---- - -**Fig** is evolving rapidly. If you're intrigued, give it a try or join us in shaping its future! \ No newline at end of file diff --git a/README_zh-CN.md b/README_zh-CN.md index e5fdba2..7bb9fc4 100644 --- a/README_zh-CN.md +++ b/README_zh-CN.md @@ -1,7 +1,5 @@ # Fig -## tmd赶工代码质量太差了暑假我要重构 - Fig Logo @@ -13,183 +11,22 @@ [English](./README.md) | [中文](./README_zh-CN.md) ![License](https://img.shields.io/badge/license-MIT-blue) -![Status](https://img.shields.io/badge/status-0.5.0--alpha-yellow) -![C++](https://img.shields.io/badge/C++-99.5%25-blue) -![xmake](https://img.shields.io/badge/xmake-构建-green) -![LLVM](https://img.shields.io/badge/LLVM-clang%2021.1.8-purple) +![Status](https://img.shields.io/badge/status-0.6.0--alpha-yellow) +![Rust](https://img.shields.io/badge/Rust-100%25-orange) +![cargo](https://img.shields.io/badge/cargo-构建-green) ![Platform](https://img.shields.io/badge/Windows%20·%20Linux%20·%20macOS-lightgrey) -![Performance](https://img.shields.io/badge/fib(30)-~28ms%20(i5--13490f)-brightgreen) -**Fig** 是一门动态类型与静态类型注解混合的编程语言,采用基于引用的值语义。它既保留了脚本语言的灵活性,又提供了可选的类型约束,让代码更健壮。 +**Fig** 是一门动态类型与静态类型注解混合的编程语言,采用基于引用的值语义。 -> ⚠️ **Fig 当前为 0.5.0-alpha 版本,语法和 API 仍可能发生变动。** 欢迎试用和反馈,但请勿用于生产环境。 +> **v0.6.0 — Rust 重写进行中。** -```fig -// 试试 Fig 的感觉 -var flexible = 10 // 动态类型,可以是任意值 -flexible = "hello" // 没问题 +## 进度 -var fixed := 20 // 固定为 Int 类型 -// fixed = 3.14 // 错误!类型不匹配 - -func greet(name) => "Hello, " + name + "!" -println(greet("Fig")) // 输出: Hello, Fig! ``` - -## ✨ 核心特性 - -### 🎭 动态与静态的融合 -变量默认是动态的(`Any` 类型),但你可以随时用 `:=` 或 `: Type` 锁定类型,享受静态检查的安全感。 - -```fig -var any; // 类型为 Any -any = 42; // 现在指向 Int -any = [1,2,3]; // 现在指向 List - -var safe := 100; // 推断为 Int,之后只能赋 Int 值 -safe = 200; // ✅ -// safe = "oops" // ❌ 编译错误 +Lexer ████████████████████ 100% (43 测试, 全部通过) +Parser ░░░░░░░░░░░░░░░░░░░░ 0% +Analyzer ░░░░░░░░░░░░░░░░░░░░ 0% +Compiler ░░░░░░░░░░░░░░░░░░░░ 0% +VM ░░░░░░░░░░░░░░░░░░░░ 0% +LSP ░░░░░░░░░░░░░░░░░░░░ 0% ``` - -### 🔗 基于引用的值语义 -所有对象都是不可变的,变量只是指向对象的“名字”。多个变量可以共享同一个对象,修改操作会创建新对象,但复杂类型(如列表)的修改会反映在所有引用上——这正是引用的含义。 - -```fig -var a := [1, 2, 3]; -var b := a; // b 和 a 指向同一个列表 -a[0] = 99; // 修改列表内容 -println(b) // 输出: [99, 2, 3] —— 因为 b 也看到了变化 - -// 需要真正的副本?用深拷贝 (语法可能变动) -var c := new List{a}; // 深拷贝 a -c[0] = 0; -println(a) // 仍是 [99, 2, 3] -``` - -### 🏗 面向对象特性 (OOP) -Fig 提供基于结构体的轻量面向对象支持,通过接口实现多态。 - -- **结构体即类**:用 `struct` 定义,可包含字段和方法 -- **访问控制**:`public` 关键字,默认为私有 -- **简洁构造**: - ```fig - var p1 := new Point{1, 2}; // 位置参数 - var p2 := new Point{x: 2, y: 3}; // 命名参数 - var x := 5, y := 10; - var p3 := new Point{y, x}; // 变量名简写,自动匹配字段 - ``` -- **接口与实现**: - ```fig - interface Drawable { draw() -> String; } - struct Circle { radius: Double } - impl Drawable for Circle { - draw() => "⚪ 半径: " + radius; - } - ``` -- **无继承,用接口实现多态**(当前为隐式 `this`,未来可能改为显式 `self.xxx`) - -### 🧩 函数式特性 -函数是一等公民,支持闭包和简洁的箭头语法。 - -```fig -func multiplier(factor) { - return func (n) => n * factor; // 闭包(upvalue) -} - -var double = multiplier(2); -println(double(5)) // 输出: 10 -``` - -### ⚡ 高性能实现 -**递归 fib(30) 仅需 28ms** (i5-13490f, Windows 11, DDR4 2667, clang 21.1.8, libc++, C++23) —— 在动态语言中表现优异。 - -Fig 通过一系列底层优化实现高性能: -- **寄存器虚拟机**:替代树遍历解释器,执行效率大幅提升。 -- **FastCall 优化**:全局普通函数直接调用原型(proto),避免运行时解包开销(传统调用需检查是否为函数对象并解包)。 -- **Window Slicing**(源自 Lua):栈滑动窗口技术,高效管理函数调用和闭包(upvalue),减少内存分配。 -- **Upvalue 机制**:轻量闭包实现,让函数式编程无性能负担。 -- **Computed Goto**:利用 GCC/Clang 扩展,加速字节码分发。 -- **NaN-Boxing**:高效存储和类型判断,提升动态类型性能。 - -#### 性能对比 -以下为递归计算 fib(30) 的粗略对比(不同环境可能存在差异,仅供参考): - -| 语言类型 | 语言 | 时间 (ms) | 备注 | -|--------|------|----------|------| -| AOT 编译 | C (clang -O2) | ~0.05 | 纳秒级,作为速度参照 | -| AOT 编译 | Rust (--release) | ~0.06 | 同上 | -| **动态语言** | **Fig** | **~28** | **寄存器 VM + 上述优化** | -| 动态语言 | Lua 5.4 | ~35 | 经典的动态语言 | -| 动态语言 | Python 3.11 | ~450 | CPython | -| 动态语言 | Node.js 20 | ~60 | V8 引擎 | -| 动态语言 | Ruby 3.2 | ~800 | CRuby | - -*Fig 在动态语言阵营中表现出色,接近 Lua 和 Node.js 的水平,远超 Python 和 Ruby。* - -## 🚀 快速上手 - -### 安装 - -#### 方法一:下载预编译二进制 -从 [主仓库 Releases](https://git.fig-lang.cn/PuqiAR/Fig/releases) 或 [GitHub 镜像](https://github.com/PuqiAR/Fig/releases) 下载对应平台的二进制,解压后加入 PATH。 - -#### 方法二:使用 xmake 从源码编译 -```bash -# 克隆主仓库(GitHub 为镜像) -git clone https://git.fig-lang.cn/PuqiAR/Fig.git -cd Fig - -# 安装 xmake(如未安装):https://xmake.io - -# 编译(必须用 clang,因为 computed goto 需要编译器支持) -xmake f --toolchain=clang -xmake - -# 编译完成后,二进制位于 build/ 目录下 -``` - -### 运行第一个 Fig 程序 -创建文件 `hello.fig`: -```fig -import std.io; // io 模块必须导入,println 等函数位于其中 -println("Hello, Fig!"); -``` -运行: -```bash -./build/fig hello.fig -``` -或已加入 PATH: -```bash -fig hello.fig -``` - -## 📊 当前状态与路线图 - -| 状态 | 模块 | 说明 | -|------|------|------| -| ✅ | 前端 | 词法/语法分析、AST、语义分析 | -| ✅ | 核心语义 | 变量、函数、闭包、结构体、接口、类型系统 | -| ✅ | 内置类型 | 13 种内置类型(Any, Null, Int, String, Bool, Double, Function, StructType, StructInstance, List, Map, Module, InterfaceType) | -| 🚧 | 寄存器虚拟机 | 原树遍历解释器已废弃,VM 开发中 | -| 🚧 | 垃圾回收 | 基础 GC 已实现,正在优化 | -| 📝 | 标准库 | IO 已初步可用,更多库待完善 | -| 📝 | FFI | 外部函数接口(C ABI) | -| 📝 | LSP | 语言服务器协议支持 | - -## 📚 文档与社区 - -- **文档**:查看 [`/docs`](./docs) 目录(持续更新) -- **示例代码**:[`/ExampleCodes`](./ExampleCodes) 包含各种用法演示 -- **贡献**:欢迎提交 Issue 或 PR(主仓库) - - 报告 bug - - 讨论特性 - - 改进文档 -- **许可证**:MIT © PuqiAR -- **作者**:PuqiAR · [im@puqiar.top](mailto:im@puqiar.top) -- **相关链接**: - - [主仓库](https://git.fig-lang.cn/PuqiAR/Fig) - - [GitHub 镜像](https://github.com/PuqiAR/Fig) - ---- - -**Fig** 还在快速迭代中,如果你对它感兴趣,不妨试一试,或者加入我们一起塑造它的未来! \ No newline at end of file diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..edccbe1 --- /dev/null +++ b/build.rs @@ -0,0 +1,63 @@ +use std::process::Command; + +fn main() { + let hash = Command::new("git") + .args(["rev-parse", "--short=7", "HEAD"]) + .output() + .ok() + .and_then(|o| String::from_utf8(o.stdout).ok()) + .unwrap_or_default() + .trim() + .to_string(); + + println!("cargo:rustc-env=GIT_HASH={}", hash); + println!("cargo:rustc-env=BUILD_TIME={}", chrono_build_time()); + + // 编译器 ID:macOS 上用 clang/LLVM,Linux 上用 GCC,Windows 上用 MSVC + #[cfg(target_os = "macos")] + { println!("cargo:rustc-env=FIG_COMPILER_ID=LLVM"); } + #[cfg(target_os = "linux")] + { println!("cargo:rustc-env=FIG_COMPILER_ID=GCC"); } + #[cfg(target_os = "windows")] + { println!("cargo:rustc-env=FIG_COMPILER_ID=MSVC"); } + #[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))] + { println!("cargo:rustc-env=FIG_COMPILER_ID=unknown"); } +} + +// chrono 还没引入,先用简单方式 +fn chrono_build_time() -> String { + // RFC 3339 without nanoseconds: "2026-07-23T13:14:00+08:00" + // 但纯 std 拿不到时区,用环境变量 SOURCE_DATE_EPOCH 或 UTC + let now = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap_or_default() + .as_secs(); + + let secs = now % 86400; + let days = now / 86400; + + // 简单计算 UTC 时间,避免引入 chrono + let hour = (secs / 3600) % 24; + let min = (secs / 60) % 60; + let sec = secs % 60; + + // 粗略日期计算(从 1970-01-01 开始) + let (y, mo, d) = civil_from_days(days as i64); + + format!("{y:04}-{mo:02}-{d:02} {hour:02}:{min:02}:{sec:02} UTC") +} + +// 从 Unix epoch 天数反算年月日 +fn civil_from_days(days: i64) -> (i64, u32, u32) { + let z = days + 719468; + let era = if z >= 0 { z } else { z - 146096 } / 146097; + let doe = (z - era * 146097) as u32; + let yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; + let y = yoe as i64 + era * 400; + let doy = doe - (365 * yoe + yoe / 4 - yoe / 100); + let mp = (5 * doy + 2) / 153; + let d = doy - (153 * mp + 2) / 5 + 1; + let m = if mp < 10 { mp + 3 } else { mp - 9 }; + let y = if m <= 2 { y + 1 } else { y }; + (y, m, d) +} diff --git a/compile_flags.txt b/compile_flags.txt deleted file mode 100644 index ee95ad3..0000000 --- a/compile_flags.txt +++ /dev/null @@ -1,3 +0,0 @@ --std=c++2b --static --stdlib=libc++ \ No newline at end of file diff --git a/src/Ast/Ast.hpp b/src/Ast/Ast.hpp deleted file mode 100644 index e8f5b58..0000000 --- a/src/Ast/Ast.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/*! - @file src/Ast/Ast.hpp - @brief Ast总链接 - @author PuqiAR (im@puqiar.top) - @date 2026-02-17 -*/ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include \ No newline at end of file diff --git a/src/Ast/Base.hpp b/src/Ast/Base.hpp deleted file mode 100644 index 9f98c1c..0000000 --- a/src/Ast/Base.hpp +++ /dev/null @@ -1,167 +0,0 @@ -/*! - @file src/Ast/Base.hpp - @brief AstNode基类定义 - @author PuqiAR (im@puqiar.top) - @date 2026-03-08 -*/ - -#pragma once -#include -#include -#include -#include - -namespace Fig -{ - enum class AstType : std::uint8_t - { - AstNode, - Program, - Expr, - Stmt, - BlockStmt, - - /* Expressions */ - IdentiExpr, - LiteralExpr, - PrefixExpr, - InfixExpr, - IndexExpr, - CallExpr, - MemberExpr, // obj.prop - NewExpr, // new Point{} - LambdaExpr, - TernaryExpr, // cond ? then : else - PostfixExpr, // expr++ / expr-- - - /* Statements */ - ExprStmt, - VarDecl, - IfStmt, - ElseIfStmt, - WhileStmt, - FnDefStmt, - StructDefStmt, - InterfaceDefStmt, - ImplStmt, // impl Document for File {} - ReturnStmt, - BreakStmt, - ContinueStmt, - ForStmt, // for loop - ImportStmt, // import - - /* Type Expressions */ - TypeExpr, - NamedTypeExpr, // 废弃,用 IdentiExpr/MemberExpr/ApplyExpr 替代 - NullableTypeExpr, // 废弃,用 NullableExpr 替代 - FnTypeExpr, - ApplyExpr, // 泛型实例化: List - NullableExpr, // 可空后缀: Int? - }; - - struct AstNode - { - AstType type = AstType::AstNode; - SourceLocation location; - - virtual String toString() const = 0; - virtual ~AstNode() {}; - }; - - struct Expr : public AstNode - { - // 语义分析后填充 - Type resolvedType; - - Expr() - { - type = AstType::Expr; - } - }; - - struct Stmt : public AstNode - { - bool isPublic = false; - Stmt() - { - type = AstType::Stmt; - } - }; - - struct Program final : public AstNode - { - DynArray nodes; - Program() - { - type = AstType::Program; - } - virtual String toString() const override - { - return ""; - } - }; - - struct BlockStmt final : public Stmt - { - DynArray nodes; - BlockStmt() - { - type = AstType::BlockStmt; - } - virtual String toString() const override - { - return ""; - } - }; - - // --- Type Expressions (inherit Expr — 类型即值) --- - - struct TypeExpr : public Expr - { - TypeExpr() { type = AstType::TypeExpr; } - virtual ~TypeExpr() = default; - }; - - // ApplyExpr: 泛型实例化,List → ApplyExpr(base, [Int]) - struct ApplyExpr final : public Expr - { - Expr *base; // 基础类型表达式 - DynArray args; // 泛型参数 - - ApplyExpr() { type = AstType::ApplyExpr; } - ApplyExpr(Expr *_base, DynArray _args, SourceLocation _loc) : - base(_base), args(std::move(_args)) - { - type = AstType::ApplyExpr; - location = std::move(_loc); - } - virtual String toString() const override - { - String s = base->toString() + "<"; - for (size_t i = 0; i < args.size(); ++i) - { - if (i) s += ", "; - s += args[i]->toString(); - } - s += ">"; - return s; - } - }; - - // NullableExpr: 可空后缀 Int? → NullableExpr(Int) - struct NullableExpr final : public Expr - { - Expr *inner; - - NullableExpr() { type = AstType::NullableExpr; } - NullableExpr(Expr *_inner, SourceLocation _loc) : inner(_inner) - { - type = AstType::NullableExpr; - location = std::move(_loc); - } - virtual String toString() const override - { - return inner->toString() + "?"; - } - }; -} // namespace Fig diff --git a/src/Ast/Expr/CallExpr.hpp b/src/Ast/Expr/CallExpr.hpp deleted file mode 100644 index 9e6fa6c..0000000 --- a/src/Ast/Expr/CallExpr.hpp +++ /dev/null @@ -1,61 +0,0 @@ -/*! - @file src/Ast/Expr/CallExpr.hpp - @brief CallExpr等定义 - @author PuqiAR (im@puqiar.top) - @date 2026-02-17 -*/ - -#pragma once - -#include -#include - -namespace Fig -{ - struct FnCallArgs - { - DynArray args; - - size_t size() const - { - return args.size(); - } - - String toString() const - { - String str = "("; - for (const Expr *expr : args) - { - if (expr != args.front()) - { - str += ", "; - } - str += expr->toString(); - } - str += ")"; - return str; - } - }; - - struct CallExpr final : public Expr - { - Expr *callee; - FnCallArgs args; - - CallExpr() - { - type = AstType::CallExpr; - } - - CallExpr(Expr *_callee, FnCallArgs _args, SourceLocation _location) : callee(_callee), args(std::move(_args)) - { - type = AstType::CallExpr; - location = std::move(_location); - } - - virtual String toString() const override - { - return std::format("", callee->toString(), args.toString()); - } - }; -} // namespace Fig \ No newline at end of file diff --git a/src/Ast/Expr/IdentiExpr.hpp b/src/Ast/Expr/IdentiExpr.hpp deleted file mode 100644 index 655972a..0000000 --- a/src/Ast/Expr/IdentiExpr.hpp +++ /dev/null @@ -1,32 +0,0 @@ -/*! - @file src/Ast/Expr/IdentiExpr.hpp - @brief 标识符表达式定义 -*/ - -#pragma once -#include -#include - -namespace Fig -{ - struct IdentiExpr final : public Expr - { - String name; - Symbol *resolvedSymbol = nullptr; // 语义分析后填充,Compiler 唯一的依赖 - - IdentiExpr() - { - type = AstType::IdentiExpr; - } - IdentiExpr(String _name, SourceLocation _location) : name(std::move(_name)) - { - type = AstType::IdentiExpr; - location = std::move(_location); - } - - virtual String toString() const override - { - return std::format("", name); - } - }; -} // namespace Fig diff --git a/src/Ast/Expr/IndexExpr.hpp b/src/Ast/Expr/IndexExpr.hpp deleted file mode 100644 index 581b2d5..0000000 --- a/src/Ast/Expr/IndexExpr.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/*! - @file src/Ast/Expr/IndexExpr.hpp - @brief IndexExpr定义 - @author PuqiAR (im@puqiar.top) - @date 2026-02-17 -*/ - -#pragma once - -#include - -namespace Fig -{ - struct IndexExpr final : public Expr - { - Expr *base; - Expr *index; - - IndexExpr() - { - type = AstType::IndexExpr; - } - - IndexExpr(Expr *_base, Expr *_index) : base(_base), index(_index) - { - type = AstType::IndexExpr; - location = base->location; - } - - virtual String toString() const override - { - return std::format("", base->toString(), index->toString()); - } - }; -}; // namespace Fig \ No newline at end of file diff --git a/src/Ast/Expr/InfixExpr.hpp b/src/Ast/Expr/InfixExpr.hpp deleted file mode 100644 index e26c855..0000000 --- a/src/Ast/Expr/InfixExpr.hpp +++ /dev/null @@ -1,39 +0,0 @@ -/*! - @file src/Ast/Expr/InfixExpr.hpp - @brief 中缀表达式定义 - @author PuqiAR (im@puqiar.top) - @date 2026-02-14 -*/ - -#pragma once - -#include -#include - -#include - -namespace Fig -{ - struct InfixExpr final : Expr - { - Expr *left; - BinaryOperator op; - Expr *right; - - InfixExpr() - { - type = AstType::InfixExpr; - } - InfixExpr(Expr *_left, BinaryOperator _op, Expr *_right) : - left(_left), op(_op), right(_right) - { - type = AstType::InfixExpr; - location = _left->location; - } - - virtual String toString() const override - { - return std::format("", left->toString(), magic_enum::enum_name(op), right->toString()); - } - }; -}; // namespace Fig \ No newline at end of file diff --git a/src/Ast/Expr/LambdaExpr.hpp b/src/Ast/Expr/LambdaExpr.hpp deleted file mode 100644 index 4e5f553..0000000 --- a/src/Ast/Expr/LambdaExpr.hpp +++ /dev/null @@ -1,70 +0,0 @@ -/*! - @file src/Ast/Expr/LambdaExpr.hpp - @brief Lambda表达式定义 -*/ - -#pragma once - -#include -#include - -namespace Fig -{ - struct LambdaExpr final : public Expr - { - // func (params) [-> return type] ([=> expr] / [ {stmt} ]) - - DynArray params; - Expr *returnType; - AstNode *body; // expr/blockstmt - bool isExprBody; - - DynArray upvalues; - - LambdaExpr() - { - type = AstType::LambdaExpr; - } - - LambdaExpr( - DynArray _params, - Expr *_returnType, - AstNode *_body, - bool _isExprBody, - SourceLocation _location) : - params(std::move(_params)), - returnType(_returnType), - body(_body), - isExprBody(_isExprBody) - { - type = AstType::LambdaExpr; - location = std::move(_location); - } - - virtual String toString() const override - { - String specifying = "toString(); - } - if (isExprBody) - { - specifying += ") => "; - specifying += body->toString(); - } - else - { - specifying += ") {"; - specifying += body->toString(); - specifying.push_back(U'}'); - } - specifying += "'>"; - return specifying; - } - }; -}; // namespace Fig \ No newline at end of file diff --git a/src/Ast/Expr/LiteralExpr.hpp b/src/Ast/Expr/LiteralExpr.hpp deleted file mode 100644 index 7c16e2b..0000000 --- a/src/Ast/Expr/LiteralExpr.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/*! - @file src/Ast/Expr/LiteralExpr.hpp - @brief 字面量表达式定义 -*/ - -#pragma once -#include -#include - -namespace Fig -{ - struct LiteralExpr final : public Expr - { - Token literal; - - LiteralExpr() { type = AstType::LiteralExpr; } - LiteralExpr(const Token &_literal, SourceLocation _location) : literal(_literal) - { - type = AstType::LiteralExpr; - location = std::move(_location); - } - - virtual String toString() const override { - return std::format("", magic_enum::enum_name(literal.type)); - } - }; -} diff --git a/src/Ast/Expr/MemberExpr.hpp b/src/Ast/Expr/MemberExpr.hpp deleted file mode 100644 index 92e31d5..0000000 --- a/src/Ast/Expr/MemberExpr.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/*! - @file src/Ast/Expr/MemberExpr.hpp - @brief 成员访问表达式定义:obj.member - @author PuqiAR (im@puqiar.top) - @date 2026-03-08 -*/ - -#pragma once - -#include - -namespace Fig -{ - struct MemberExpr final : public Expr - { - Expr *target; // 访问对象 - String name; // 成员名字 - - MemberExpr() - { - type = AstType::MemberExpr; - } - - MemberExpr(Expr *_t, String _n, SourceLocation _loc) : target(_t), name(std::move(_n)) - { - type = AstType::MemberExpr; - location = std::move(_loc); - } - - virtual String toString() const override - { - return std::format("", target->toString(), name); - } - }; -} // namespace Fig diff --git a/src/Ast/Expr/NewExpr.hpp b/src/Ast/Expr/NewExpr.hpp deleted file mode 100644 index b52bf1f..0000000 --- a/src/Ast/Expr/NewExpr.hpp +++ /dev/null @@ -1,50 +0,0 @@ -/*! - @file src/Ast/Expr/ObjectInitExpr.hpp - @brief 对象初始化表达式 AST 定义 - @author PuqiAR (im@puqiar.top) - @date 2026-03-08 -*/ - -#pragma once - -#include - -namespace Fig -{ - struct NewExpr final : public Expr - { - struct Arg - { - String name; - Expr *value; - }; - Expr *typeExpr; - DynArray args; - - NewExpr() - { - type = AstType::NewExpr; - } - NewExpr(Expr *_te, DynArray _args, SourceLocation _loc) : - typeExpr(_te), args(std::move(_args)) - { - type = AstType::NewExpr; - location = std::move(_loc); - } - - virtual String toString() const override - { - String res = "toString() + "{"; - for (size_t i = 0; i < args.size(); ++i) - { - if (!args[i].name.empty()) - res += args[i].name + ": "; - res += args[i].value->toString(); - if (i < args.size() - 1) - res += ", "; - } - res += "}'>"; - return res; - } - }; -} // namespace Fig diff --git a/src/Ast/Expr/PostfixExpr.hpp b/src/Ast/Expr/PostfixExpr.hpp deleted file mode 100644 index 6812e3e..0000000 --- a/src/Ast/Expr/PostfixExpr.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/*! - @file src/Ast/Expr/PostfixExpr.hpp - @brief expr++ / expr-- - @author PuqiAR (im@puqiar.top) - @date 2026-06-06 -*/ - -#pragma once - -#include -#include - -namespace Fig -{ - struct PostfixExpr final : public Expr - { - UnaryOperator op; - Expr *operand; - - PostfixExpr() { type = AstType::PostfixExpr; } - - PostfixExpr(UnaryOperator _op, Expr *_operand) : - op(_op), operand(_operand) - { - type = AstType::PostfixExpr; - location = _operand->location; - } - - virtual String toString() const override - { - return std::format("", - operand->toString(), magic_enum::enum_name(op)); - } - }; -} // namespace Fig diff --git a/src/Ast/Expr/PrefixExpr.hpp b/src/Ast/Expr/PrefixExpr.hpp deleted file mode 100644 index 88753ae..0000000 --- a/src/Ast/Expr/PrefixExpr.hpp +++ /dev/null @@ -1,39 +0,0 @@ -/*! - @file src/Ast/Expr/PrefixExpr.hpp - @brief 前缀表达式定义 - @author PuqiAR (im@puqiar.top) - @date 2026-02-14 -*/ - -#pragma once - -#include -#include - -#include - -namespace Fig -{ - struct PrefixExpr final : Expr - { - UnaryOperator op; - Expr *operand; - - PrefixExpr() - { - type = AstType::PrefixExpr; - } - - PrefixExpr(UnaryOperator _op, Expr *_operand) : - op(_op), operand(_operand) - { - type = AstType::PrefixExpr; - location = _operand->location; - } - - virtual String toString() const override - { - return std::format("", magic_enum::enum_name(op), operand->toString()); - } - }; -}; \ No newline at end of file diff --git a/src/Ast/Expr/TernaryExpr.hpp b/src/Ast/Expr/TernaryExpr.hpp deleted file mode 100644 index 8a32b99..0000000 --- a/src/Ast/Expr/TernaryExpr.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/*! - @file src/Ast/Expr/TernaryExpr.hpp - @brief cond ? then : else - @author PuqiAR (im@puqiar.top) - @date 2026-06-06 -*/ - -#pragma once - -#include - -namespace Fig -{ - struct TernaryExpr final : public Expr - { - Expr *cond; - Expr *thenExpr; - Expr *elseExpr; - - TernaryExpr() { type = AstType::TernaryExpr; } - - TernaryExpr(Expr *_cond, Expr *_then, Expr *_else, SourceLocation _loc) : - cond(_cond), thenExpr(_then), elseExpr(_else) - { - type = AstType::TernaryExpr; - location = std::move(_loc); - } - - virtual String toString() const override - { - return std::format("", - cond->toString(), thenExpr->toString(), elseExpr->toString()); - } - }; -} // namespace Fig diff --git a/src/Ast/Operator.cpp b/src/Ast/Operator.cpp deleted file mode 100644 index 67b8ee1..0000000 --- a/src/Ast/Operator.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/*! - @file src/Ast/Operator.cpp - @brief 运算符定义内函数实现 - @author PuqiAR (im@puqiar.top) - @date 2026-02-14 -*/ - -#include - -namespace Fig -{ - HashMap &GetUnaryOpMap() - { - static HashMap unaryOpMap{ - {TokenType::Tilde, UnaryOperator::BitNot}, - {TokenType::Minus, UnaryOperator::Negate}, - {TokenType::Not, UnaryOperator::Not}, - {TokenType::Ampersand, UnaryOperator::AddressOf}, - {TokenType::DoublePlus, UnaryOperator::Increment}, - {TokenType::DoubleMinus, UnaryOperator::Decrement}, - }; - return unaryOpMap; - } - - HashMap &GetBinaryOpMap() - { - static HashMap binaryOpMap{ - {TokenType::Plus, BinaryOperator::Add}, - {TokenType::Minus, BinaryOperator::Subtract}, - {TokenType::Asterisk, BinaryOperator::Multiply}, - {TokenType::Slash, BinaryOperator::Divide}, - {TokenType::Percent, BinaryOperator::Modulo}, - - {TokenType::Equal, BinaryOperator::Equal}, - {TokenType::NotEqual, BinaryOperator::NotEqual}, - {TokenType::Less, BinaryOperator::Less}, - {TokenType::Greater, BinaryOperator::Greater}, - {TokenType::LessEqual, BinaryOperator::LessEqual}, - {TokenType::GreaterEqual, BinaryOperator::GreaterEqual}, - - {TokenType::Is, BinaryOperator::Is}, - - {TokenType::And, BinaryOperator::LogicalAnd}, - {TokenType::Or, BinaryOperator::LogicalOr}, - {TokenType::DoubleAmpersand, BinaryOperator::LogicalAnd}, - {TokenType::DoublePipe, BinaryOperator::LogicalOr}, - - {TokenType::Power, BinaryOperator::Power}, - - {TokenType::Assign, BinaryOperator::Assign}, - {TokenType::PlusEqual, BinaryOperator::AddAssign}, - {TokenType::MinusEqual, BinaryOperator::SubAssign}, - {TokenType::AsteriskEqual, BinaryOperator::MultiplyAssign}, - {TokenType::SlashEqual, BinaryOperator::DivideAssign}, - {TokenType::PercentEqual, BinaryOperator::ModuloAssign}, - {TokenType::Caret, BinaryOperator::BitXor}, - {TokenType::CaretEqual, BinaryOperator::BitXorAssign}, - - {TokenType::Pipe, BinaryOperator::BitOr}, - {TokenType::Ampersand, BinaryOperator::BitAnd}, - {TokenType::ShiftLeft, BinaryOperator::ShiftLeft}, - {TokenType::ShiftRight, BinaryOperator::ShiftRight}, - - {TokenType::As, BinaryOperator::As}, - }; - return binaryOpMap; - } - - // 赋值 < 三元 < 逻辑或 < 逻辑与 < 位运算 < 比较 < 位移 < 加减 < 乘除 < 幂 < 一元 < 成员访问 < (后缀) - - /* - 暂划分: - 二元运算符:0 - 20000 - 一元运算符:20001 - 40000 - 后缀/成员/其他:40001 - 60001 - - */ - - HashMap &GetUnaryOpBindingPowerMap() - { - static HashMap unbpm{ - {UnaryOperator::BitNot, 20001}, - {UnaryOperator::Negate, 20001}, - {UnaryOperator::Not, 20001}, - {UnaryOperator::AddressOf, 20001}, - {UnaryOperator::Increment, 20001}, - {UnaryOperator::Decrement, 20001}, - }; - return unbpm; - } - - HashMap &GetBinaryOpBindingPowerMap() - { - static HashMap bnbpm{ - {BinaryOperator::Assign, 100}, - {BinaryOperator::AddAssign, 100}, - {BinaryOperator::SubAssign, 100}, - {BinaryOperator::MultiplyAssign, 100}, - {BinaryOperator::DivideAssign, 100}, - {BinaryOperator::ModuloAssign, 100}, - {BinaryOperator::BitXorAssign, 100}, - - {BinaryOperator::LogicalOr, 500}, - {BinaryOperator::LogicalAnd, 550}, - - {BinaryOperator::BitOr, 1000}, - {BinaryOperator::BitXor, 1100}, - {BinaryOperator::BitAnd, 1200}, - - {BinaryOperator::Equal, 2000}, - {BinaryOperator::NotEqual, 2000}, - - {BinaryOperator::Less, 2100}, - {BinaryOperator::LessEqual, 2100}, - {BinaryOperator::Greater, 2100}, - {BinaryOperator::GreaterEqual, 2100}, - - {BinaryOperator::Is, 2100}, - {BinaryOperator::As, 2100}, - - {BinaryOperator::ShiftLeft, 3000}, - {BinaryOperator::ShiftRight, 3000}, - - {BinaryOperator::Add, 4000}, - {BinaryOperator::Subtract, 4000}, - {BinaryOperator::Multiply, 4500}, - {BinaryOperator::Divide, 4500}, - {BinaryOperator::Modulo, 4500}, - - {BinaryOperator::Power, 5000}, - }; - return bnbpm; - } - - BindingPower GetUnaryOpRBp(UnaryOperator op) - { - return GetUnaryOpBindingPowerMap().at(op); - } - - BindingPower GetBinaryOpLBp(BinaryOperator op) - { - return GetBinaryOpBindingPowerMap().at(op); - } - - BindingPower GetBinaryOpRBp(BinaryOperator op) - { - switch (op) - { - /* - 右结合,左绑定力 >= 右 - a = b = c - a = (b = c) - */ - case BinaryOperator::Assign: - case BinaryOperator::AddAssign: - case BinaryOperator::SubAssign: - case BinaryOperator::MultiplyAssign: - case BinaryOperator::DivideAssign: - case BinaryOperator::ModuloAssign: - case BinaryOperator::BitXorAssign: - case BinaryOperator::Power: return GetBinaryOpLBp(op) - 1; - - case BinaryOperator::As: return GetBinaryOpLBp(op) + 1; - - default: - /* - 左结合, 左绑定力 < 右 - a * b * c - (a * b) * c - */ - return GetBinaryOpLBp(op) + 1; - } - } - - bool IsTokenOp(TokenType type, bool binary /* = true*/) - { - if (binary) - { - return GetBinaryOpMap().contains(type); - } - return GetUnaryOpMap().contains(type); - } - - UnaryOperator TokenToUnaryOp(const Token &token) - { - return GetUnaryOpMap().at(token.type); - } - BinaryOperator TokenToBinaryOp(const Token &token) - { - return GetBinaryOpMap().at(token.type); - } - -}; // namespace Fig \ No newline at end of file diff --git a/src/Ast/Operator.hpp b/src/Ast/Operator.hpp deleted file mode 100644 index f227d42..0000000 --- a/src/Ast/Operator.hpp +++ /dev/null @@ -1,96 +0,0 @@ -/*! - @file src/Ast/Operator.hpp - @brief 运算符定义 - @author PuqiAR (im@puqiar.top) - @date 2026-02-14 -*/ - -#pragma once - -#include - -#include -#include - -namespace Fig -{ - enum class UnaryOperator : std::uint8_t - { - BitNot, // 位运算取反 ~ - Negate, // 取反 - - Not, // 逻辑非 ! / not - AddressOf, // 取引用 & - Increment, // ++ - Decrement, // -- - - Count // 哨兵,(int) Count 获得运算符数量(注意,enum必须从 0 开始且不中断) - }; - enum class BinaryOperator : std::uint8_t - { - Add, // 加 + - Subtract, // 减 - - Multiply, // 乘 * - Divide, // 除 / - Modulo, // 取模 % - - Equal, // 等于 == - NotEqual, // 不等于 != - Less, // 小于 < - Greater, // 大于 > - LessEqual, // 小于等于 <= - GreaterEqual, // 大于等于 >= - - Is, // is操作符 - - LogicalAnd, // 逻辑与 && / and - LogicalOr, // 逻辑或 || / or - - Power, // 幂运算 ** - - Assign, // 赋值(修改) = - AddAssign, // += - SubAssign, // -= - MultiplyAssign, // *= - DivideAssign, // /= - ModuloAssign, // %= - BitXorAssign, // ^= - - // 位运算 - BitAnd, // 按位与 & - BitOr, // 按位或 | - BitXor, // 异或 ^ - ShiftLeft, // 左移 - ShiftRight, // 右移 - - As, // as - - // 成员访问 - MemberAccess, // . - - Count // 哨兵,(int) Count 获得运算符数量(注意,enum必须从 0 开始且不中断) - }; - - constexpr unsigned int GetOperatorsSize() - { - // 获取全部运算符的数量 - return static_cast(UnaryOperator::Count) + static_cast(BinaryOperator::Count); - } - - using BindingPower = unsigned int; - - HashMap &GetUnaryOpMap(); - HashMap &GetBinaryOpMap(); - - HashMap &GetUnaryOpBindingPowerMap(); - HashMap &GetBinaryOpBindingPowerMap(); - - BindingPower GetUnaryOpRBp(UnaryOperator); - - BindingPower GetBinaryOpLBp(BinaryOperator); - BindingPower GetBinaryOpRBp(BinaryOperator); - - bool IsTokenOp(TokenType type, bool binary = true); - - UnaryOperator TokenToUnaryOp(const Token &); - BinaryOperator TokenToBinaryOp(const Token &); -}; // namespace Fig \ No newline at end of file diff --git a/src/Ast/Stmt/ControlFlowStmts.hpp b/src/Ast/Stmt/ControlFlowStmts.hpp deleted file mode 100644 index d91b071..0000000 --- a/src/Ast/Stmt/ControlFlowStmts.hpp +++ /dev/null @@ -1,72 +0,0 @@ -/*! - @file src/Ast/Stmt/ControlFlowStmts - @brief 控制流语句 return, break, continue 定义 - @author PuqiAR (im@puqiar.top) - @date 2026-02-27 -*/ - -#pragma once - -#include - -namespace Fig -{ - struct ReturnStmt final : public Stmt - { - Expr *value; - - ReturnStmt() - { - type = AstType::ReturnStmt; - } - - ReturnStmt(Expr *_value, SourceLocation _location) : value(_value) - { - type = AstType::ReturnStmt; - location = std::move(_location); - } - - virtual String toString() const override - { - return std::format("", value->toString()); - } - }; - - struct BreakStmt final : public Stmt - { - BreakStmt() - { - type = AstType::BreakStmt; - } - - BreakStmt(SourceLocation _location) - { - type = AstType::BreakStmt; - location = std::move(_location); - } - - virtual String toString() const override - { - return ""; - } - }; - - struct ContinueStmt final : public Stmt - { - ContinueStmt() - { - type = AstType::ContinueStmt; - } - - ContinueStmt(SourceLocation _location) - { - type = AstType::ContinueStmt; - location = std::move(_location); - } - - virtual String toString() const override - { - return ""; - } - }; -}; // namespace Fig \ No newline at end of file diff --git a/src/Ast/Stmt/ExprStmt.hpp b/src/Ast/Stmt/ExprStmt.hpp deleted file mode 100644 index 9279779..0000000 --- a/src/Ast/Stmt/ExprStmt.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/*! - @file src/Ast/Stmt/ExprStmt.hpp - @brief ExprStmt定义 - @author PuqiAR (im@puqiar.top) - @date 2026-02-19 -*/ - -#pragma once - -#include - -namespace Fig -{ - struct ExprStmt final : public Stmt - { - Expr *expr; - - ExprStmt() - { - type = AstType::ExprStmt; - } - - ExprStmt(Expr *_expr) : - expr(_expr) - { - type = AstType::ExprStmt; - location = _expr->location; - } - - virtual String toString() const override - { - return std::format("", expr->toString()); - } - }; -} \ No newline at end of file diff --git a/src/Ast/Stmt/FnDefStmt.hpp b/src/Ast/Stmt/FnDefStmt.hpp deleted file mode 100644 index 7736bcc..0000000 --- a/src/Ast/Stmt/FnDefStmt.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/*! - @file src/Ast/Stmt/FnDefStmt.hpp - @brief 函数定义 AST 节点 -*/ - -#pragma once -#include -#include -#include - -namespace Fig -{ - struct Param : public AstNode { - String name; - Expr *typeSpecifier; - Expr *defaultValue; - Type resolvedType; - Param() { type = AstType::AstNode; } - virtual ~Param() = default; - }; - - struct PosParam final : public Param { - PosParam(String _n, Expr *_ts, Expr *_dv, SourceLocation _loc) { - name = std::move(_n); typeSpecifier = _ts; defaultValue = _dv; location = std::move(_loc); - } - virtual String toString() const override { return name; } - }; - - struct FnDefStmt final : public Stmt { - String name; - DynArray params; - Expr *returnTypeSpecifier; - BlockStmt *body; - Type resolvedReturnType; - Symbol *resolvedSymbol = nullptr; // 连接物理符号 - - int protoIndex = -1; // 在CompiledModule扁平化protos的下标 - DynArray upvalues; - - FnDefStmt() { type = AstType::FnDefStmt; } - FnDefStmt(bool _p, String _n, DynArray _pa, Expr *_rt, BlockStmt *_b, SourceLocation _loc) - : name(std::move(_n)), params(std::move(_pa)), returnTypeSpecifier(_rt), body(_b) - { - type = AstType::FnDefStmt; isPublic = _p; location = std::move(_loc); - } - - virtual String toString() const override { - return std::format("", name); - } - }; -} diff --git a/src/Ast/Stmt/ForStmt.hpp b/src/Ast/Stmt/ForStmt.hpp deleted file mode 100644 index 718d346..0000000 --- a/src/Ast/Stmt/ForStmt.hpp +++ /dev/null @@ -1,32 +0,0 @@ -/*! - @file src/Ast/Stmt/ForStmt.hpp - @brief for loop - @author PuqiAR (im@puqiar.top) - @date 2026-06-06 -*/ - -#pragma once - -#include - -namespace Fig -{ - struct ForStmt final : public Stmt - { - Stmt *init; - Expr *cond; - Expr *step; - BlockStmt *body; - - ForStmt() { type = AstType::ForStmt; } - - ForStmt(Stmt *_init, Expr *_cond, Expr *_step, BlockStmt *_body, SourceLocation _loc) : - init(_init), cond(_cond), step(_step), body(_body) - { - type = AstType::ForStmt; - location = std::move(_loc); - } - - virtual String toString() const override { return ""; } - }; -} // namespace Fig diff --git a/src/Ast/Stmt/IfStmt.hpp b/src/Ast/Stmt/IfStmt.hpp deleted file mode 100644 index 1aa6c21..0000000 --- a/src/Ast/Stmt/IfStmt.hpp +++ /dev/null @@ -1,69 +0,0 @@ -/*! - @file src/Ast/Stmt/IfStmt.hpp - @brief IfStmt定义 - @author PuqiAR (im@puqiar.top) - @date 2026-02-20 -*/ - -#pragma once - -#include - -namespace Fig -{ - struct ElseIfStmt final : public Stmt - { - Expr *cond; - BlockStmt *consequent; - - ElseIfStmt() - { - type = AstType::ElseIfStmt; - } - - ElseIfStmt(Expr *_cond, BlockStmt *_consequent, SourceLocation _location) : - cond(_cond), consequent(_consequent) - { - type = AstType::ElseIfStmt; - location = std::move(_location); - } - - virtual String toString() const override - { - return std::format("", cond->toString(), consequent->toString()); - } - }; - - struct IfStmt final : public Stmt - { - Expr *cond; - BlockStmt *consequent; - DynArray elifs; - BlockStmt *alternate; - - IfStmt() - { - type = AstType::IfStmt; - } - - IfStmt(Expr *_cond, - BlockStmt *_consequent, - DynArray _elifs, - BlockStmt *_alternate, - SourceLocation _location) : - cond(_cond), consequent(_consequent), elifs(std::move(_elifs)), alternate(_alternate) - { - type = AstType::IfStmt; - location = std::move(_location); - } - - virtual String toString() const override - { - return std::format("", - cond->toString(), - consequent->toString(), - elifs.size(), - alternate->toString()); - } - }; -}; // namespace Fig \ No newline at end of file diff --git a/src/Ast/Stmt/ImplStmt.hpp b/src/Ast/Stmt/ImplStmt.hpp deleted file mode 100644 index 12d9b3c..0000000 --- a/src/Ast/Stmt/ImplStmt.hpp +++ /dev/null @@ -1,32 +0,0 @@ -/*! - @file src/Ast/Stmt/ImplStmt.hpp - @brief 实现块 AST 节点 -*/ - -#pragma once -#include -#include - -namespace Fig -{ - struct ImplStmt final : public Stmt - { - Expr *interfaceType; - Expr *structType; - DynArray methods; - - ImplStmt(Expr *_it, Expr *_st, DynArray _m, SourceLocation _loc) : - interfaceType(_it), structType(_st), methods(std::move(_m)) - { - type = AstType::ImplStmt; - location = std::move(_loc); - } - - virtual String toString() const override - { - String detail = - (interfaceType ? interfaceType->toString() + " for " : "") + structType->toString(); - return std::format("", detail); - } - }; -} // namespace Fig diff --git a/src/Ast/Stmt/ImportStmt.hpp b/src/Ast/Stmt/ImportStmt.hpp deleted file mode 100644 index ec8230a..0000000 --- a/src/Ast/Stmt/ImportStmt.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/*! - @file src/Ast/Stmt/ImportStmt.hpp - @brief import - @author PuqiAR (im@puqiar.top) - @date 2026-06-06 -*/ - -#pragma once - -#include - -namespace Fig -{ - struct ImportStmt final : public Stmt - { - String path; - bool isFileImport; - - ImportStmt() { type = AstType::ImportStmt; } - - ImportStmt(String _path, bool _isFileImport, SourceLocation _loc) : - path(std::move(_path)), isFileImport(_isFileImport) - { - type = AstType::ImportStmt; - location = std::move(_loc); - } - - virtual String toString() const override - { - return std::format("", path, isFileImport ? " [file]" : ""); - } - }; -} // namespace Fig diff --git a/src/Ast/Stmt/InterfaceDefStmt.hpp b/src/Ast/Stmt/InterfaceDefStmt.hpp deleted file mode 100644 index f6e333f..0000000 --- a/src/Ast/Stmt/InterfaceDefStmt.hpp +++ /dev/null @@ -1,39 +0,0 @@ -/*! - @file src/Ast/Stmt/InterfaceDefStmt.hpp - @brief 接口定义 AST 节点 - @author PuqiAR (im@puqiar.top) - @date 2026-03-08 -*/ - -#pragma once - -#include - -namespace Fig -{ - struct InterfaceDefStmt final : public Stmt - { - struct Method - { - String name; - DynArray params; - Expr *retType; - SourceLocation location; - }; - - bool isPublic; - String name; - DynArray methods; - - InterfaceDefStmt() { type = AstType::InterfaceDefStmt; } - - InterfaceDefStmt(bool _p, String _n, DynArray _m, SourceLocation _loc) - : isPublic(_p), name(std::move(_n)), methods(std::move(_m)) - { - type = AstType::InterfaceDefStmt; - location = std::move(_loc); - } - - virtual String toString() const override { return ""; } - }; -} // namespace Fig diff --git a/src/Ast/Stmt/StructDefStmt.hpp b/src/Ast/Stmt/StructDefStmt.hpp deleted file mode 100644 index 56a2030..0000000 --- a/src/Ast/Stmt/StructDefStmt.hpp +++ /dev/null @@ -1,59 +0,0 @@ -/*! - @file src/Ast/Stmt/StructDefStmt.hpp - @brief 结构体定义 AST 节点 -*/ - -#pragma once -#include -#include - -namespace Fig -{ - struct StructDefStmt final : public Stmt - { - struct Field - { - bool isPublic; - bool typeInfer; - - String name; - Expr *type; - Expr *initExpr; - }; - bool isPublic; - String name; - DynArray typeParameters; - DynArray fields; - DynArray methods; - - StructDefStmt() - { - type = AstType::StructDefStmt; - } - StructDefStmt(bool _p, - String _n, - DynArray _tp, - DynArray _f, - DynArray _m, - SourceLocation _loc) : - isPublic(_p), - name(std::move(_n)), - typeParameters(std::move(_tp)), - fields(std::move(_f)), - methods(std::move(_m)) - { - type = AstType::StructDefStmt; - location = std::move(_loc); - } - - virtual String toString() const override - { - String detail = name; - if (!typeParameters.empty()) - { - detail += "<...>"; - } - return std::format("", detail); - } - }; -} // namespace Fig diff --git a/src/Ast/Stmt/VarDecl.hpp b/src/Ast/Stmt/VarDecl.hpp deleted file mode 100644 index 78a67e4..0000000 --- a/src/Ast/Stmt/VarDecl.hpp +++ /dev/null @@ -1,47 +0,0 @@ -/*! - @file src/Ast/Stmt/VarDecl.hpp - @brief VarDecl定义 - @author PuqiAR (im@puqiar.top) - @date 2026-02-17 -*/ - -#pragma once - -#include -#include - -namespace Fig -{ - struct VarDecl final : public Stmt - { - String name; - Expr *typeSpecifier; - bool isInfer; // 是否用了 := 类型推断 - Expr *initExpr; - - int localId = -1; - - VarDecl() - { - type = AstType::VarDecl; - } - - VarDecl(bool _isPublic, String _name, Expr *_typeSpecifier, bool _isInfer, Expr *_initExpr, SourceLocation _location) : - name(std::move(_name)), - typeSpecifier(_typeSpecifier), - isInfer(_isInfer), - initExpr(_initExpr) // location 指向关键字 var/const位置 - { - type = AstType::VarDecl; - isPublic = _isPublic; - location = std::move(_location); - } - - virtual String toString() const override - { - const String &typeSpecifierString = (typeSpecifier ? typeSpecifier->toString() : "Any"); - const String &initExprString = (initExpr ? initExpr->toString() : "(disprovided)"); - return std::format("", name, typeSpecifierString, initExprString); - } - }; -}; // namespace Fig \ No newline at end of file diff --git a/src/Ast/Stmt/WhileStmt.hpp b/src/Ast/Stmt/WhileStmt.hpp deleted file mode 100644 index 0a1bc31..0000000 --- a/src/Ast/Stmt/WhileStmt.hpp +++ /dev/null @@ -1,37 +0,0 @@ -/*! - @file src/Ast/Stmt/WhileStmt.hpp - @brief WhileStmt定义 - @author PuqiAR (im@puqiar.top) - @date 2026-02-24 -*/ - -#pragma once - -#include - -namespace Fig -{ - struct WhileStmt final : public Stmt - { - Expr *cond; - BlockStmt *body; - - WhileStmt() - { - type = AstType::WhileStmt; - } - - WhileStmt(Expr *_cond, BlockStmt *_body, SourceLocation _location) : - cond(_cond), - body(_body) - { - type = AstType::WhileStmt; - location = std::move(_location); - } - - virtual String toString() const override - { - return std::format("", cond->toString(), body->toString()); - } - }; -}; // namespace Fig \ No newline at end of file diff --git a/src/Ast/TypeExpr.hpp b/src/Ast/TypeExpr.hpp deleted file mode 100644 index 9615009..0000000 --- a/src/Ast/TypeExpr.hpp +++ /dev/null @@ -1,100 +0,0 @@ -/*! - @file src/Ast/TypeExpr.hpp - @brief 类型表达式 AST 定义:支持泛型与空安全 -*/ - -#pragma once - -#include - -namespace Fig -{ - struct NamedTypeExpr final : public TypeExpr - { - DynArray path; - DynArray arguments; - - NamedTypeExpr() - { - type = AstType::NamedTypeExpr; - } - NamedTypeExpr(DynArray _p, DynArray _args, SourceLocation _loc) : - path(std::move(_p)), arguments(std::move(_args)) - { - type = AstType::NamedTypeExpr; - location = std::move(_loc); - } - - virtual String toString() const override - { - String detail = ""; - for (size_t i = 0; i < path.size(); ++i) - { - detail += path[i]; - if (i < path.size() - 1) - detail += "."; - } - if (!arguments.empty()) - { - detail += "<"; - for (size_t i = 0; i < arguments.size(); ++i) - { - detail += arguments[i]->toString(); - if (i < arguments.size() - 1) - detail += ", "; - } - detail += ">"; - } - return std::format("", detail); - } - }; - - struct NullableTypeExpr final : public TypeExpr - { - Expr *inner; - - NullableTypeExpr(Expr *_inner, SourceLocation _loc) : inner(_inner) - { - type = AstType::NullableTypeExpr; - location = std::move(_loc); - } - - virtual String toString() const override - { - return std::format("", inner->toString()); - } - }; - - struct FnTypeExpr final : public TypeExpr - { - // func (paratypes...) -> return_type - - DynArray paraTypes; - Expr *returnType; - - FnTypeExpr(DynArray _paraTypes, Expr *_returnType) : - paraTypes(std::move(_paraTypes)), returnType(_returnType) - { - type = AstType::FnTypeExpr; - } - - virtual String toString() const override - { - String detail = "toString(); - } - detail += ") -> "; - detail += returnType->toString(); - detail += "'>"; - - return detail; - } - }; -} // namespace Fig diff --git a/src/Bytecode/Bytecode.hpp b/src/Bytecode/Bytecode.hpp deleted file mode 100644 index f71f016..0000000 --- a/src/Bytecode/Bytecode.hpp +++ /dev/null @@ -1,122 +0,0 @@ -/*! - @file src/Bytecode/Bytecode.hpp - @brief 字节码Bytecode定义 -*/ - -#pragma once - -#include -#include -#include - -#include - - -namespace Fig -{ - using Instruction = std::uint32_t; - - enum class OpCode : std::uint8_t - { - // 控制流 - Exit, // iAsBx, return sBx - Exit_MaxRecursionDepthExceeded, // iAsBx, fatal: 超出最大递归深度 - - // 常量加载 - LoadK, // iABx, R(A) = K(Bx) - LoadTrue, // iABC, R(A) = true - LoadFalse, // iABC, R(A) = false - LoadNull, // iABC, R(A) = null - - // 函数调用 - FastCall, // iABC, call Proto[A], args from R(B) - Call, // iABC, call R(A), args from R(B) - Return, // iABC, return R(A) - - // 闭包 - LoadFn, // iABx, R(A) = new Closure(Proto[Bx]) - - // 跳转 - Jmp, // iAsBx, PC += sBx - JmpIfFalse, // iAsBx, if !R(A) then PC += sBx - - // 寄存器移动 - Mov, // iABx, R(A) = R(Bx) - - // 算术运算 - Add, // iABC, R(A) = R(B) + R(C) - Sub, // iABC, R(A) = R(B) - R(C) - Mul, // iABC, R(A) = R(B) * R(C) - Div, // iABC, R(A) = R(B) / R(C) - Mod, // iABC, R(A) = R(B) % R(C) (WIP) - BitXor, // iABC, R(A) = R(B) ^ R(C) (WIP) - - // 快速整数算术(仅 int,无类型检查) - IntFastAdd, // iABC, R(A) = R(B) + R(C) (int) - IntFastSub, // iABC, R(A) = R(B) - R(C) (int) - IntFastMul, // iABC, R(A) = R(B) * R(C) (int) - // 结果可能为非整数 - IntFastDiv, // iABC, R(A) = (double)R(B) / R(C) (int) - - // 比较 - Equal, // iABC, R(A) = R(B) == R(C) - NotEqual, // iABC, R(A) = R(B) != R(C) - Greater, // iABC, R(A) = R(B) > R(C) - Less, // iABC, R(A) = R(B) < R(C) - GreaterEqual, // iABC, R(A) = R(B) >= R(C) - LessEqual, // iABC, R(A) = R(B) <= R(C) - - // 变量存取 - GetGlobal, // iABx, R(A) = G(Bx) - SetGlobal, // iABx, G(Bx) = R(A) - GetUpval, // iABC, R(A) = *Upval(B) - SetUpval, // iABC, *Upval(B) = R(A) - Copy, // iABC, R(A) = R(B) - - Count // 哨兵 - }; - - namespace Op - { - [[nodiscard]] inline constexpr Instruction iABx(OpCode op, std::uint8_t a, std::uint16_t bx) - { - return static_cast(op) | (static_cast(a) << 8) - | (static_cast(bx) << 16); - } - - [[nodiscard]] inline constexpr Instruction iABC(OpCode op, std::uint8_t a, std::uint8_t b, std::uint8_t c) - { - return static_cast(op) | (static_cast(a) << 8) - | (static_cast(b) << 16) | (static_cast(c) << 24); - } - - [[nodiscard]] inline constexpr Instruction iAsBx(OpCode op, std::uint8_t a, std::int16_t sbx) - { - return static_cast(op) | (static_cast(a) << 8) - | (static_cast(static_cast(sbx)) << 16); - } - } // namespace Op - - struct UpvalueInfo - { - uint8_t index; - bool isLocal; - }; - - struct Proto - { - String name; - DynArray code; - DynArray locations; - DynArray constants; - DynArray upvalues; - uint8_t maxRegisters = 0; - uint8_t numParams = 0; - }; - - struct CompiledModule - { - DynArray protos; - }; - -} // namespace Fig diff --git a/src/Bytecode/Disassembler.cpp b/src/Bytecode/Disassembler.cpp deleted file mode 100644 index d34f49a..0000000 --- a/src/Bytecode/Disassembler.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/*! - @file src/Bytecode/Disassembler.cpp - @brief 字节码反汇编器实现 -*/ - -#include - -#include -#include - -namespace Fig -{ - void Disassembler::DisassembleModule(const CompiledModule *module, std::ostream &stream) - { - if (!module) return; - stream << "--- Module Disassembly ---" << std::endl; - for (auto *proto : module->protos) - { - DisassembleProto(proto); - } - } - - void Disassembler::DisassembleProto(const Proto *proto, std::ostream &stream) - { - if (!proto) return; - - stream << std::format("\n--- Proto: {} (Regs: {}, Params: {}) ---\n", - proto->name, proto->maxRegisters, proto->numParams); - - for (size_t i = 0; i < proto->code.size(); ++i) - { - Instruction inst = proto->code[i]; - OpCode op = static_cast(inst & 0xFF); - uint8_t a = (inst >> 8) & 0xFF; - - stream << std::format("[{:04}] {:<12} ", i, magic_enum::enum_name(op)); - - Format fmt = GetFormat(op); - if (fmt == Format::ABC) - { - uint8_t b = (inst >> 16) & 0xFF; - uint8_t c = (inst >> 24) & 0xFF; - stream << std::format("A:{:<3} B:{:<3} C:{:<3}", a, b, c); - } - else if (fmt == Format::ABx) - { - uint16_t bx = (inst >> 16) & 0xFFFF; - stream << std::format("A:{:<3} Bx:{:<5}", a, bx); - - // 自动关联常量池 - if (op == OpCode::LoadK && bx < proto->constants.size()) - { - stream << std::format(" ; {}", proto->constants[bx].ToString()); - } - } - else if (fmt == Format::AsBx) - { - int16_t sbx = static_cast((inst >> 16) & 0xFFFF); - stream << std::format("A:{:<3} sBx:{:<5}", a, sbx); - - // 计算跳转绝对地址 - if (op == OpCode::Jmp || op == OpCode::JmpIfFalse) - { - stream << std::format(" ; to [{:04}]", i + sbx + 1); - } - } - stream << "\n"; - } - - if (!proto->constants.empty()) - { - stream << "Constants:\n"; - for (size_t i = 0; i < proto->constants.size(); ++i) - { - stream << std::format(" [{}] {}\n", i, proto->constants[i].ToString()); - } - } - stream << "--- End Disassembly ---\n"; - } - - Disassembler::Format Disassembler::GetFormat(OpCode op) - { - switch (op) - { - case OpCode::LoadK: - case OpCode::Mov: - case OpCode::GetGlobal: - case OpCode::SetGlobal: - case OpCode::LoadFn: - return Format::ABx; - - case OpCode::Exit: - case OpCode::Exit_MaxRecursionDepthExceeded: - case OpCode::Jmp: - case OpCode::JmpIfFalse: - return Format::AsBx; - - default: - return Format::ABC; - } - } -} // namespace Fig diff --git a/src/Bytecode/Disassembler.hpp b/src/Bytecode/Disassembler.hpp deleted file mode 100644 index 133f5ca..0000000 --- a/src/Bytecode/Disassembler.hpp +++ /dev/null @@ -1,35 +0,0 @@ -/*! - @file src/Bytecode/Disassembler.hpp - @brief 字节码反汇编器:物理还原指令语义 - @author PuqiAR (im@puqiar.top) - @date 2026-03-08 -*/ - -#pragma once - -#include -#include -#include - -namespace Fig -{ - class Disassembler - { - public: - // 反汇编整个模块 - static void DisassembleModule(const CompiledModule *module, std::ostream & = CoreIO::GetStdOut()); - - // 反汇编单个函数原型 - static void DisassembleProto(const Proto *proto, std::ostream & = CoreIO::GetStdOut()); - - private: - enum class Format - { - ABC, - ABx, - AsBx - }; - - static Format GetFormat(OpCode op); - }; -} // namespace Fig diff --git a/src/Compiler/Compiler.hpp b/src/Compiler/Compiler.hpp deleted file mode 100644 index 19ce883..0000000 --- a/src/Compiler/Compiler.hpp +++ /dev/null @@ -1,64 +0,0 @@ -/*! - @file src/Compiler/Compiler.hpp - @brief 编译器定义:物理直连 Bootstrapper -*/ - -#pragma once - -#include -#include -#include -#include - -namespace Fig -{ - using Register = std::uint8_t; - - class Compiler - { - private: - static constexpr Register MAX_REGISTERS = 250; - static constexpr Register NO_REG = 255; - - struct FuncState - { - Proto *proto; - Register freereg; - FuncState *enclosing; - HashMap constantMap; - - FuncState(Proto *p, FuncState *e) - : proto(p), freereg(p->numParams), enclosing(e) {} - }; - - FuncState *current = nullptr; - CompiledModule *module = nullptr; - SourceManager &manager; - Diagnostics &diag; - - HashMap globalIDMap; - int getGlobalID(const String& name); - - Result allocateReg(const SourceLocation &loc); - void freeReg(Register count = 1); - int addConstant(Value val); - - void emit(Instruction inst, SourceLocation *loc); - - Result compileStmt(Stmt *stmt); - Result compileExpr(Expr *expr, Register target = NO_REG); - - public: - Compiler(SourceManager &m, Diagnostics &d) : manager(m), diag(d) {} - Result Compile(Program *) - { - auto *mod = new CompiledModule(); - auto *boot = new Proto(); - boot->name = "[bootstrapper]"; - boot->maxRegisters = 1; - boot->code.push_back(Op::iAsBx(OpCode::Exit, 0, 0)); - mod->protos.push_back(boot); - return mod; - } - }; -} diff --git a/src/Core/Core.hpp b/src/Core/Core.hpp deleted file mode 100644 index 595393f..0000000 --- a/src/Core/Core.hpp +++ /dev/null @@ -1,13 +0,0 @@ -/*! - @file src/Core/Core.hpp - @brief Core总合集 - @author PuqiAR (im@puqiar.top) - @date 2026-02-14 -*/ - -#pragma once - -#include -#include -#include -#include \ No newline at end of file diff --git a/src/Core/CoreIO.cpp b/src/Core/CoreIO.cpp deleted file mode 100644 index 363368e..0000000 --- a/src/Core/CoreIO.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/*! - @file src/Core/CoreIO.cpp - @brief 标准输入输出链接 - @author PuqiAR (im@puqiar.top) - @date 2026-02-14 -*/ - -#include -#include - -#ifdef _WIN32 - #include -#endif - -namespace Fig::CoreIO -{ -#if defined(_WIN32) || defined(__APPLE__) || defined (__linux__) || defined (__unix__) - std::ostream &GetStdOut() - { - static std::ostream &out = std::cout; - return out; - } - std::ostream &GetStdErr() - { - static std::ostream &err = std::cerr; - return err; - } - std::ostream &GetStdLog() - { - static std::ostream &log = std::clog; - return log; - } - std::istream &GetStdCin() - { - static std::istream &cin = std::cin; - return cin; - } -#else - // link -#endif - - void InitConsoleIO() - { -#ifdef _WIN32 - SetConsoleCP(CP_UTF8); - SetConsoleOutputCP(CP_UTF8); -#endif - } -}; \ No newline at end of file diff --git a/src/Core/CoreIO.hpp b/src/Core/CoreIO.hpp deleted file mode 100644 index 3231918..0000000 --- a/src/Core/CoreIO.hpp +++ /dev/null @@ -1,20 +0,0 @@ -/*! - @file src/Core/CoreIO.hpp - @brief 标准输入输出链接定义 - @author PuqiAR (im@puqiar.top) - @date 2026-02-14 -*/ - -#pragma once - -#include - -namespace Fig::CoreIO -{ - std::ostream &GetStdOut(); - std::ostream &GetStdErr(); - std::ostream &GetStdLog(); - std::istream &GetStdCin(); - - void InitConsoleIO(); -}; // namespace Fig::CoreIO \ No newline at end of file diff --git a/src/Core/CoreInfos.hpp b/src/Core/CoreInfos.hpp deleted file mode 100644 index 41acb5a..0000000 --- a/src/Core/CoreInfos.hpp +++ /dev/null @@ -1,143 +0,0 @@ -/*! - @file src/Core/CoreInfos.hpp - @brief 核心系统信息 - @author PuqiAR (im@puqiar.top) - @date 2026-02-14 -*/ - -#pragma once - -#include -#include -#include - -#define __FCORE_VERSION "0.5.0-alpha" - -#if defined(_WIN32) - #define __FCORE_PLATFORM "Windows" -#elif defined(__APPLE__) - #define __FCORE_PLATFORM "Apple" -#elif defined(__linux__) - #define __FCORE_PLATFORM "Linux" -#elif defined(__unix__) - #define __FCORE_PLATFORM "Unix" -#else - #define __FCORE_PLATFORM "Unknown" -#endif - -#if defined(__GNUC__) - #if defined(_WIN32) - #if defined(__clang__) - #define __FCORE_COMPILER "llvm-mingw" - #else - #define __FCORE_COMPILER "MinGW" - #endif - - #else - #define __FCORE_COMPILER "GCC" - #endif -#elif defined(__clang__) - #define __FCORE_COMPILER "Clang" -#elif defined(_MSC_VER) - #define __FCORE_COMPILER "MSVC" -#else - #define __FCORE_COMPILER "Unknown" -#endif - -#if SIZE_MAX == 18446744073709551615ull - #define __FCORE_ARCH "64" -#else - #define __FCORE_ARCH "86" -#endif - -#define __FCORE_LINK_DEPS - -namespace Fig -{ - namespace Core - { - inline constexpr std::string_view VERSION = __FCORE_VERSION; - inline constexpr std::string_view LICENSE = "MIT"; - inline constexpr std::string_view AUTHOR = "PuqiAR"; - inline constexpr std::string_view PLATFORM = __FCORE_PLATFORM; - 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; - - const std::string LOGO = - R"( -▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ -▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ -▒▒▒▒▒██████████▓▒▒▒▒ -▒▒▒▒▒██████████▓▒▒▒▒ -▒▒▒▒▒███▓▒▒▒▒▒▒▒▒▒▒▒ -▒▒▒▒▒█████████▒▒▒▒▒▒ -▒▒▒▒▒█████████▒▒▒▒▒▒ -▒▒▒▒▒███▓▒▒▒▒▒▒▒▒▒▒▒ -▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ -▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ -)"; - - const std::string LICENSE_TEXT = - R"( -MIT License (Fig) - -Copyright (c) 2026 PuqiAR - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -1. The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - -2. This project includes code from the following projects with their respective licenses: - - magic_enum (MIT License) - Copyright (c) 2019 - 2024 Daniil Goncharov - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - - - json (MIT LICENSE) (for LSP Server JSON-RPC) - Copyright (c) 2013-2026 Niels Lohmann - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - -)"; - - }; // namespace Core -}; // namespace Fig \ No newline at end of file diff --git a/src/Core/RuntimeTime.cpp b/src/Core/RuntimeTime.cpp deleted file mode 100644 index ae1bf0c..0000000 --- a/src/Core/RuntimeTime.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/*! - @file src/Core/RuntimeTime.cpp - @brief 系统时间库实现(steady_clock) - @author PuqiAR (im@puqiar.top) - @date 2026-02-14 -*/ - -#include - -#include - -namespace Fig::Time -{ - Clock::time_point start_time; - void init() - { - static bool flag = false; - if (flag) - { - assert(false); - } - start_time = Clock::now(); - flag = true; - } -}; \ No newline at end of file diff --git a/src/Core/RuntimeTime.hpp b/src/Core/RuntimeTime.hpp deleted file mode 100644 index b33fc39..0000000 --- a/src/Core/RuntimeTime.hpp +++ /dev/null @@ -1,17 +0,0 @@ -/*! - @file src/Core/RuntimeTime.hpp - @brief 系统时间库定义 - @author PuqiAR (im@puqiar.top) - @date 2026-02-14 -*/ - -#pragma once - -#include - -namespace Fig::Time -{ - using Clock = std::chrono::steady_clock; - extern Clock::time_point start_time; // since process start - void init(); -}; \ No newline at end of file diff --git a/src/Core/SourceLocations.hpp b/src/Core/SourceLocations.hpp deleted file mode 100644 index c6a81b8..0000000 --- a/src/Core/SourceLocations.hpp +++ /dev/null @@ -1,59 +0,0 @@ -/*! - @file src/Core/SourceLocations - @brief SourcePosition + SourceLocation定义,全局代码定位 - @author PuqiAR (im@puqiar.top) - @date 2026-02-14 -*/ - -#pragma once - -#include - -namespace Fig -{ - struct SourcePosition - { - size_t line, column, tok_length; - - SourcePosition() { line = column = tok_length = 0; } - SourcePosition(size_t _line, size_t _column, size_t _tok_length) - { - line = _line; - column = _column; - tok_length = _tok_length; - } - }; - - struct SourceLocation - { - SourcePosition sp; - - Deps::String fileName; - Deps::String packageName; - Deps::String functionName; - - SourceLocation() {} - SourceLocation(SourcePosition _sp, - Deps::String _fileName, - Deps::String _packageName, - Deps::String _functionName) - { - sp = std::move(_sp); - fileName = std::move(_fileName); - packageName = std::move(_packageName); - functionName = std::move(_functionName); - } - SourceLocation(size_t line, - size_t column, - size_t tok_length, - Deps::String _fileName, - Deps::String _packageName, - Deps::String _functionName) - { - sp = SourcePosition(line, column, tok_length); - fileName = std::move(_fileName); - packageName = std::move(_packageName); - functionName = std::move(_functionName); - } - }; -}; // namespace Fig \ No newline at end of file diff --git a/src/Deps/Deps.hpp b/src/Deps/Deps.hpp deleted file mode 100644 index 3170952..0000000 --- a/src/Deps/Deps.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/*! - @file src/Deps/Deps.hpp - @brief 依赖库集合 - @author PuqiAR (im@puqiar.top) - @date 2026-02-13 -*/ - -#pragma once - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace Fig -{ -#ifdef __FCORE_LINK_DEPS - using Deps::String; - using Deps::HashMap; - using Deps::CharUtils; - using Deps::DynArray; - - template - using Result = std::expected<_Tp, _Err>; -#endif -}; // namespace Fig \ No newline at end of file diff --git a/src/Deps/DynArray/DynArray.hpp b/src/Deps/DynArray/DynArray.hpp deleted file mode 100644 index fe08cf5..0000000 --- a/src/Deps/DynArray/DynArray.hpp +++ /dev/null @@ -1,14 +0,0 @@ -/*! - @file src/Deps/DynArray/DynArray - @brief 依赖库DynArray定义 - @author PuqiAR (im@puqiar.top) - @date 2026-02-14 -*/ - -#include - -namespace Fig::Deps -{ - template> - using DynArray = std::vector<_Tp, _Allocator>; -}; \ No newline at end of file diff --git a/src/Deps/HashMap/HashMap.hpp b/src/Deps/HashMap/HashMap.hpp deleted file mode 100644 index a1a3cc5..0000000 --- a/src/Deps/HashMap/HashMap.hpp +++ /dev/null @@ -1,20 +0,0 @@ -/*! - @file src/Deps/HashMap/HashMap.hpp - @brief 依赖库HashMap定义 - @author PuqiAR (im@puqiar.top) - @date 2026-02-13 -*/ - -#pragma once - -#include - -namespace Fig::Deps -{ - template , - class _Pred = std::equal_to<_Key>, - class _Alloc = std::allocator >> - using HashMap = std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>; -}; \ No newline at end of file diff --git a/src/Deps/String/CharUtils.hpp b/src/Deps/String/CharUtils.hpp deleted file mode 100644 index 7280812..0000000 --- a/src/Deps/String/CharUtils.hpp +++ /dev/null @@ -1,130 +0,0 @@ -/*! - @file src/Deps/String/CharUtils.hpp - @brief char32_t type实现 - @author PuqiAR (im@puqiar.top) - @date 2026-02-13 -*/ - -#pragma once - -namespace Fig::Deps -{ - class CharUtils - { - public: - using U32 = char32_t; - - // ===== 基础 ===== - - static constexpr bool isValidScalar(U32 c) noexcept { return c <= 0x10FFFF && !(c >= 0xD800 && c <= 0xDFFF); } - - static constexpr bool isAscii(U32 c) noexcept { return c <= 0x7F; } - - static constexpr bool isControl(U32 c) noexcept { return (c <= 0x1F) || (c == 0x7F); } - - static constexpr bool isPrintable(U32 c) noexcept { return !isControl(c); } - - // ===== ASCII 分类 ===== - - static constexpr bool isAsciiLower(U32 c) noexcept { return c >= U'a' && c <= U'z'; } - static constexpr bool isAsciiUpper(U32 c) noexcept { return c >= U'A' && c <= U'Z'; } - static constexpr bool isAsciiAlpha(U32 c) noexcept { return isAsciiLower(c) || isAsciiUpper(c); } - static constexpr bool isAsciiDigit(U32 c) noexcept { return c >= U'0' && c <= U'9'; } - - static constexpr bool isAsciiHexDigit(U32 c) noexcept - { - return isAsciiDigit(c) || (c >= U'a' && c <= U'f') || (c >= U'A' && c <= U'F'); - } - - static constexpr bool isAsciiSpace(U32 c) noexcept { return c == U' ' || (c >= 0x09 && c <= 0x0D); } - - static constexpr bool isAsciiPunct(U32 c) noexcept - { - return (c >= 33 && c <= 47) || (c >= 58 && c <= 64) || (c >= 91 && c <= 96) || (c >= 123 && c <= 126); - } - - // ===== Unicode White_Space ===== - - static constexpr bool isSpace(U32 c) noexcept - { - if (isAscii(c)) return isAsciiSpace(c); - - switch (c) - { - case 0x0085: - case 0x00A0: - case 0x1680: - case 0x2000: - case 0x2001: - case 0x2002: - case 0x2003: - case 0x2004: - case 0x2005: - case 0x2006: - case 0x2007: - case 0x2008: - case 0x2009: - case 0x200A: - case 0x2028: - case 0x2029: - case 0x202F: - case 0x205F: - case 0x3000: return true; - } - return false; - } - - // ===== Unicode Decimal_Number ===== - - static constexpr bool isDigit(U32 c) noexcept - { - if (isAscii(c)) return isAsciiDigit(c); - - return (c >= 0x0660 && c <= 0x0669) || (c >= 0x06F0 && c <= 0x06F9) || (c >= 0x0966 && c <= 0x096F) - || (c >= 0x09E6 && c <= 0x09EF) || (c >= 0x0A66 && c <= 0x0A6F) || (c >= 0x0AE6 && c <= 0x0AEF) - || (c >= 0x0B66 && c <= 0x0B6F) || (c >= 0x0BE6 && c <= 0x0BEF) || (c >= 0x0C66 && c <= 0x0C6F) - || (c >= 0x0CE6 && c <= 0x0CEF) || (c >= 0x0D66 && c <= 0x0D6F) || (c >= 0x0E50 && c <= 0x0E59) - || (c >= 0x0ED0 && c <= 0x0ED9) || (c >= 0x0F20 && c <= 0x0F29) || (c >= 0x1040 && c <= 0x1049) - || (c >= 0x17E0 && c <= 0x17E9) || (c >= 0x1810 && c <= 0x1819) || (c >= 0xFF10 && c <= 0xFF19); - } - - // ===== Unicode Letter ===== - - static constexpr bool isAlpha(U32 c) noexcept - { - if (isAscii(c)) return isAsciiAlpha(c); - - return (c >= 0x00C0 && c <= 0x02AF) || (c >= 0x0370 && c <= 0x052F) || (c >= 0x0530 && c <= 0x058F) - || (c >= 0x0590 && c <= 0x05FF) || (c >= 0x0600 && c <= 0x06FF) || (c >= 0x0900 && c <= 0x097F) - || (c >= 0x3040 && c <= 0x30FF) || (c >= 0x3100 && c <= 0x312F) || (c >= 0x4E00 && c <= 0x9FFF) - || (c >= 0xAC00 && c <= 0xD7AF); - } - - // ===== 标点 / 符号 / 分隔符(工程近似)===== - - static constexpr bool isPunct(U32 c) noexcept - { - if (isAscii(c)) return isAsciiPunct(c); - return (c >= 0x2000 && c <= 0x206F); - } - - static constexpr bool isSymbol(U32 c) noexcept - { - return (c >= 0x20A0 && c <= 0x20CF) || // currency - (c >= 0x2100 && c <= 0x214F) || // letterlike - (c >= 0x2190 && c <= 0x21FF) || // arrows - (c >= 0x2600 && c <= 0x26FF) || // misc symbols - (c >= 0x1F300 && c <= 0x1FAFF); // emoji block - } - - // ===== 组合 ===== - - static constexpr bool isAlnum(U32 c) noexcept { return isAlpha(c) || isDigit(c); } - - static constexpr bool isHexDigit(U32 c) noexcept { return isAsciiHexDigit(c); } - - static constexpr bool isIdentifierStart(U32 c) noexcept { return isAlpha(c) || c == U'_'; } - - static constexpr bool isIdentifierContinue(U32 c) noexcept { return isAlnum(c) || c == U'_'; } - }; -}; \ No newline at end of file diff --git a/src/Deps/String/String.hpp b/src/Deps/String/String.hpp deleted file mode 100644 index 8018c8c..0000000 --- a/src/Deps/String/String.hpp +++ /dev/null @@ -1,1074 +0,0 @@ -/*! - @file src/Deps/String/String.hpp - @brief UTF32/Pure ASCII + SSO优化的字符串实现 - @author PuqiAR (im@puqiar.top) - @date 2026-02-13 -*/ - -#pragma once - -#include -#include -#include - -#include -#include -#include - -namespace Fig::Deps -{ - class StringUtils - { - public: - static bool is_pure_ascii(const char *data, size_t n) noexcept - { - for (size_t i = 0; i < n; ++i) - { - if (static_cast(data[i]) >= 128) - return false; - } - return true; - } - - static bool is_pure_ascii(const char32_t *data, size_t n) noexcept - { - for (size_t i = 0; i < n; ++i) - { - if (data[i] >= 128) - return false; - } - return true; - } - - static size_t utf8_decode_one(const char *s, size_t n, char32_t &out) - { - unsigned char c0 = static_cast(s[0]); - - if (c0 < 0x80) - { - out = c0; - return 1; - } - - if ((c0 >> 5) == 0x6 && n >= 2) - { - unsigned char c1 = static_cast(s[1]); - out = ((c0 & 0x1F) << 6) | (c1 & 0x3F); - return 2; - } - - if ((c0 >> 4) == 0xE && n >= 3) - { - unsigned char c1 = static_cast(s[1]); - unsigned char c2 = static_cast(s[2]); - out = ((c0 & 0x0F) << 12) | ((c1 & 0x3F) << 6) | (c2 & 0x3F); - return 3; - } - - if ((c0 >> 3) == 0x1E && n >= 4) - { - unsigned char c1 = static_cast(s[1]); - unsigned char c2 = static_cast(s[2]); - unsigned char c3 = static_cast(s[3]); - out = ((c0 & 0x07) << 18) | ((c1 & 0x3F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F); - return 4; - } - - out = 0xFFFD; - return 1; - } - }; - - class String - { - public: - using u32 = char32_t; - static constexpr uint8_t SSO_SIZE = 22; - - enum class Mode : uint8_t - { - ASCII_SSO, // ASCII - ASCII_HEP, // ASCII heap - UTF32_HEP, // UTF32 heap - }; - - private: - Mode mode = Mode::ASCII_SSO; - union - { - unsigned char sso[SSO_SIZE]; // non null terminate - std::vector ascii; - std::vector utf32; - }; - - size_t _length = 0; - - void copyfrom(const String &other) - { - destroy(); - _length = other._length; - mode = other.mode; - - if (mode == Mode::ASCII_SSO) - { - memcpy(sso, other.sso, sizeof(unsigned char) * _length); - } - else if (mode == Mode::ASCII_HEP) - { - new (&ascii) std::vector(other.ascii); - } - else - { - new (&utf32) std::vector(other.utf32); - } - } - - void movefrom(String &&other) noexcept - { - destroy(); - - mode = other.mode; - _length = other._length; - - switch (mode) - { - case Mode::ASCII_SSO: std::memcpy(sso, other.sso, other._length); break; - - case Mode::ASCII_HEP: new (&ascii) std::vector(std::move(other.ascii)); break; - - case Mode::UTF32_HEP: new (&utf32) std::vector(std::move(other.utf32)); break; - } - - other.mode = Mode::ASCII_SSO; - other._length = 0; - } - - void destroy() noexcept - { - if (mode == Mode::ASCII_SSO) - { - // pass - } - if (mode == Mode::ASCII_HEP) - { - ascii.~vector(); - } - if (mode == Mode::UTF32_HEP) - { - utf32.~vector(); - } - } - - void ensure_utf32() - { - if (mode == Mode::UTF32_HEP) - return; - - std::vector tmp; - tmp.reserve(_length); - - if (mode == Mode::ASCII_SSO) - { - for (size_t i = 0; i < _length; ++i) - tmp.push_back(static_cast(sso[i])); - } - else // ASCII_HEP - { - for (unsigned char c : ascii) - tmp.push_back(static_cast(c)); - } - - destroy(); - mode = Mode::UTF32_HEP; - new (&utf32) std::vector(std::move(tmp)); - } - - void promote_sso_ascii_to_heap() noexcept - { - assert(mode == Mode::ASCII_SSO && "promote_sso_ascii_to_heap: mode is not ascii sso"); - mode = Mode::ASCII_HEP; - - std::vector tmp; - tmp.reserve(_length); - for (size_t i = 0; i < _length; ++i) - tmp.push_back(sso[i]); - - mode = Mode::ASCII_HEP; - new (&ascii) std::vector(std::move(tmp)); - } - - void init(const char *data) - { - assert(data); - size_t n = std::strlen(data); - init(data, n); - } - - void init(const char *data, size_t n) - { - destroy(); - - _length = 0; - - // ASCII 快路径 - if (n <= SSO_SIZE && StringUtils::is_pure_ascii(data, n)) - { - mode = Mode::ASCII_SSO; - std::memcpy(sso, data, n); - _length = n; - return; - } - - if (StringUtils::is_pure_ascii(data, n)) - { - mode = Mode::ASCII_HEP; - new (&ascii) std::vector(data, data + n); - _length = n; - return; - } - - // UTF-8 decode - mode = Mode::UTF32_HEP; - new (&utf32) std::vector(); - utf32.reserve(n); - - for (size_t i = 0; i < n;) - { - u32 cp; - size_t step = StringUtils::utf8_decode_one(data + i, n - i, cp); - utf32.push_back(cp); - i += step; - } - - utf32.shrink_to_fit(); - _length = utf32.size(); - } - - void init(const u32 *data) - { - assert(data); - size_t n = 0; - while (data[n] != 0) - ++n; - init(data, n); - } - - void init(const u32 *data, size_t n) - { - destroy(); - - _length = n; - - if (n <= SSO_SIZE && StringUtils::is_pure_ascii(data, n)) - { - mode = Mode::ASCII_SSO; - for (size_t i = 0; i < n; ++i) - sso[i] = static_cast(data[i]); - return; - } - - if (StringUtils::is_pure_ascii(data, n)) - { - mode = Mode::ASCII_HEP; - new (&ascii) std::vector(); - ascii.reserve(n); - for (size_t i = 0; i < n; ++i) - ascii.push_back(static_cast(data[i])); - return; - } - - mode = Mode::UTF32_HEP; - new (&utf32) std::vector(); - utf32.assign(data, data + n); - } - - public: - size_t length() const noexcept - { - return _length; - } - size_t size() const noexcept - { - return _length; - } - - bool empty() const noexcept - { - return _length == 0; - } - void reserve(size_t n) - { - if (mode == Mode::ASCII_HEP) - ascii.reserve(n); - else if (mode == Mode::UTF32_HEP) - utf32.reserve(n); - } - - void clear() noexcept - { - _length = 0; - if (mode == Mode::ASCII_SSO) - { - // pass - } - if (mode == Mode::ASCII_HEP) - { - ascii.clear(); - } - else - { - utf32.clear(); - } - } - - void shrink_to_fit() noexcept - { - if (mode == Mode::ASCII_HEP) - { - ascii.shrink_to_fit(); - } - else - { - utf32.shrink_to_fit(); - } - } - - ~String() noexcept - { - destroy(); - } - String() noexcept - { - mode = Mode::ASCII_SSO; - _length = 0; - } - String(const String &other) noexcept - { - copyfrom(other); - } - String(String &&other) noexcept - { - movefrom(std::move(other)); - } - String(const char *str) - { - init(str); - } - String(const char32_t *str) - { - init(str); - } - String(char32_t c) - { - init(""); - push_back(c); - } - String(char c) - { - init(""); - push_back(static_cast(c)); - } - String(const std::string &s) - { - init(s.data(), s.size()); - } - - String &operator=(const String &other) - { - if (this != &other) - { - destroy(); - copyfrom(other); - } - return *this; - } - - String &operator=(String &&other) noexcept - { - if (this != &other) - movefrom(std::move(other)); - return *this; - } - - String &operator+=(const String &rhs) - { - if (rhs._length == 0) - return *this; - - // 两边都是 ASCII - bool this_ascii = (mode == Mode::ASCII_SSO || mode == Mode::ASCII_HEP); - bool rhs_ascii = (rhs.mode == Mode::ASCII_SSO || rhs.mode == Mode::ASCII_HEP); - - if (this_ascii && rhs_ascii) - { - size_t newlen = _length + rhs._length; - - // SSO 可容纳 - if (mode == Mode::ASCII_SSO && newlen <= SSO_SIZE) - { - if (rhs.mode == Mode::ASCII_SSO) - std::memcpy(sso + _length, rhs.sso, rhs._length); - else - std::memcpy(sso + _length, rhs.ascii.data(), rhs._length); - - _length = newlen; - return *this; - } - - if (mode == Mode::ASCII_SSO) - promote_sso_ascii_to_heap(); - - // 追加 - if (rhs.mode == Mode::ASCII_SSO) - ascii.insert(ascii.end(), rhs.sso, rhs.sso + rhs._length); - else - ascii.insert(ascii.end(), rhs.ascii.begin(), rhs.ascii.end()); - - _length = newlen; - return *this; - } - - // 必须 UTF32 - - if (mode != Mode::UTF32_HEP) - { - std::vector tmp; - tmp.reserve(_length + rhs._length); - - if (mode == Mode::ASCII_SSO) - { - for (size_t i = 0; i < _length; ++i) - tmp.push_back(static_cast(sso[i])); - } - else // ASCII_HEP - { - for (unsigned char c : ascii) - tmp.push_back(static_cast(c)); - } - - destroy(); - mode = Mode::UTF32_HEP; - new (&utf32) std::vector(std::move(tmp)); - } - - if (rhs.mode == Mode::UTF32_HEP) - { - utf32.insert(utf32.end(), rhs.utf32.begin(), rhs.utf32.end()); - } - else if (rhs.mode == Mode::ASCII_SSO) - { - for (size_t i = 0; i < rhs._length; ++i) - utf32.push_back(static_cast(rhs.sso[i])); - } - else // ASCII_HEP - { - for (unsigned char c : rhs.ascii) - utf32.push_back(static_cast(c)); - } - - _length = utf32.size(); - return *this; - } - - String &operator+=(const char *utf8) - { - String tmp(utf8); - return (*this += tmp); - } - - friend String operator+(String lhs, const String &rhs) - { - lhs += rhs; - return lhs; - } - - void push_back(u32 cp) - { - if (cp < 128) - { - if (mode == Mode::ASCII_SSO && _length < SSO_SIZE) - { - sso[_length++] = static_cast(cp); - return; - } - - if (mode == Mode::ASCII_SSO) - promote_sso_ascii_to_heap(); - - if (mode == Mode::ASCII_HEP) - { - ascii.push_back(static_cast(cp)); - ++_length; - return; - } - } - - ensure_utf32(); - utf32.push_back(cp); - _length = utf32.size(); - } - - void pop_back() - { - assert(_length > 0); - - if (mode == Mode::ASCII_SSO) - { - --_length; - return; - } - - if (mode == Mode::ASCII_HEP) - { - ascii.pop_back(); - --_length; - return; - } - - utf32.pop_back(); - _length = utf32.size(); - } - - String &append(const char *utf8) - { - String tmp(utf8); - *this += tmp; - return *this; - } - - String &append(const char32_t *u32str) - { - String tmp(u32str); - *this += tmp; - return *this; - } - - String &append(size_t count, u32 cp) - { - for (size_t i = 0; i < count; ++i) - push_back(cp); - return *this; - } - - void resize(size_t new_size, u32 fill = 0) - { - if (new_size <= _length) - { - erase(new_size); - return; - } - - append(new_size - _length, fill); - } - - u32 front() const - { - assert(_length > 0); - return (*this)[0]; - } - - u32 back() const - { - assert(_length > 0); - return (*this)[_length - 1]; - } - - std::string toStdString() const - { - std::string out; - - if (mode == Mode::ASCII_SSO) - { - out.assign(reinterpret_cast(sso), _length); - return out; - } - - if (mode == Mode::ASCII_HEP) - { - out.assign(ascii.begin(), ascii.end()); - return out; - } - - // UTF32_HEP -> UTF-8 encode - for (u32 cp : utf32) - { - if (cp <= 0x7F) - { - out.push_back(static_cast(cp)); - } - else if (cp <= 0x7FF) - { - out.push_back(static_cast(0xC0 | (cp >> 6))); - out.push_back(static_cast(0x80 | (cp & 0x3F))); - } - else if (cp <= 0xFFFF) - { - out.push_back(static_cast(0xE0 | (cp >> 12))); - out.push_back(static_cast(0x80 | ((cp >> 6) & 0x3F))); - out.push_back(static_cast(0x80 | (cp & 0x3F))); - } - else if (cp <= 0x10FFFF) - { - out.push_back(static_cast(0xF0 | (cp >> 18))); - out.push_back(static_cast(0x80 | ((cp >> 12) & 0x3F))); - out.push_back(static_cast(0x80 | ((cp >> 6) & 0x3F))); - out.push_back(static_cast(0x80 | (cp & 0x3F))); - } - // 非法码点 - } - - return out; - } - friend std::ostream &operator<<(std::ostream &os, const String &s) - { - return os << s.toStdString(); - } - - friend bool operator==(const String &a, const String &b) noexcept - { - if (a._length != b._length) - return false; - - // 同模式 - if (a.mode == b.mode) - { - if (a.mode == Mode::ASCII_SSO) - return std::memcmp(a.sso, b.sso, a._length) == 0; - - if (a.mode == Mode::ASCII_HEP) - return a.ascii == b.ascii; - - return a.utf32 == b.utf32; - } - - // 不同模式ASCII / UTF32 - const bool a_ascii = (a.mode == Mode::ASCII_SSO || a.mode == Mode::ASCII_HEP); - const bool b_ascii = (b.mode == Mode::ASCII_SSO || b.mode == Mode::ASCII_HEP); - - if (a_ascii && b_ascii) - { - if (a.mode == Mode::ASCII_SSO) - return std::memcmp(a.sso, b.ascii.data(), a._length) == 0; - else - return std::memcmp(a.ascii.data(), b.sso, a._length) == 0; - } - - // ASCII / UTF32 - const String &ascii_str = a_ascii ? a : b; - const String &utf32_str = a_ascii ? b : a; - - if (ascii_str.mode == Mode::ASCII_SSO) - { - for (size_t i = 0; i < ascii_str._length; ++i) - if (static_cast(ascii_str.sso[i]) != utf32_str.utf32[i]) - return false; - } - else - { - for (size_t i = 0; i < ascii_str._length; ++i) - if (static_cast(ascii_str.ascii[i]) != utf32_str.utf32[i]) - return false; - } - - return true; - } - - friend bool operator!=(const String &a, const String &b) noexcept - { - return !(a == b); - } - // std::hash - friend struct std::hash; - - // read only - u32 operator[](size_t i) const - { - assert(i < _length); - - if (mode == Mode::ASCII_SSO) - return static_cast(sso[i]); - if (mode == Mode::ASCII_HEP) - return static_cast(ascii[i]); - return utf32[i]; - } - u32 at(size_t i) const - { - if (i >= _length) - throw std::out_of_range("String::at"); - return (*this)[i]; - } - - bool starts_with(const String &prefix) const - { - if (prefix._length > _length) - return false; - - for (size_t i = 0; i < prefix._length; ++i) - if ((*this)[i] != prefix[i]) - return false; - - return true; - } - - bool ends_with(const String &suffix) const - { - if (suffix._length > _length) - return false; - - size_t offset = _length - suffix._length; - - for (size_t i = 0; i < suffix._length; ++i) - if ((*this)[offset + i] != suffix[i]) - return false; - - return true; - } - - bool contains(u32 cp) const - { - if (mode == Mode::ASCII_SSO) - { - for (size_t i = 0; i < _length; ++i) - if (sso[i] == cp) - return true; - return false; - } - - if (mode == Mode::ASCII_HEP) - { - if (cp >= 128) - return false; - for (unsigned char c : ascii) - if (c == cp) - return true; - return false; - } - - for (u32 c : utf32) - if (c == cp) - return true; - - return false; - } - - String substr(size_t pos, size_t count = size_t(-1)) const - { - if (pos >= _length) - return String(); - - size_t len = (_length - pos < count) ? (_length - pos) : count; - - String out; - - // ASCII_SSO - if (mode == Mode::ASCII_SSO) - { - if (len <= SSO_SIZE) - { - out.mode = Mode::ASCII_SSO; - std::memcpy(out.sso, sso + pos, len); - out._length = len; - } - else - { - out.mode = Mode::ASCII_HEP; - new (&out.ascii) std::vector(sso + pos, sso + pos + len); - out._length = len; - } - return out; - } - - // ASCII_HEP - if (mode == Mode::ASCII_HEP) - { - if (len <= SSO_SIZE) - { - out.mode = Mode::ASCII_SSO; - std::memcpy(out.sso, ascii.data() + pos, len); - out._length = len; - } - else - { - out.mode = Mode::ASCII_HEP; - new (&out.ascii) std::vector(ascii.begin() + pos, ascii.begin() + pos + len); - out._length = len; - } - return out; - } - - // UTF32 - out.mode = Mode::UTF32_HEP; - new (&out.utf32) std::vector(utf32.begin() + pos, utf32.begin() + pos + len); - out._length = len; - return out; - } - - String &erase(size_t pos, size_t count = size_t(-1)) - { - if (pos >= _length) - return *this; - - size_t len = (_length - pos < count) ? (_length - pos) : count; - - if (mode == Mode::ASCII_SSO) - { - std::memmove(sso + pos, sso + pos + len, _length - pos - len); - _length -= len; - return *this; - } - - if (mode == Mode::ASCII_HEP) - { - ascii.erase(ascii.begin() + pos, ascii.begin() + pos + len); - _length -= len; - return *this; - } - - utf32.erase(utf32.begin() + pos, utf32.begin() + pos + len); - _length = utf32.size(); - return *this; - } - - String &insert(size_t pos, const String &other) - { - if (pos > _length) - pos = _length; - if (other._length == 0) - return *this; - - bool this_ascii = (mode != Mode::UTF32_HEP); - bool other_ascii = (other.mode != Mode::UTF32_HEP); - - // ASCII 合并路径 - if (this_ascii && other_ascii) - { - size_t newlen = _length + other._length; - - if (mode == Mode::ASCII_SSO && newlen <= SSO_SIZE) - { - std::memmove(sso + pos + other._length, sso + pos, _length - pos); - - if (other.mode == Mode::ASCII_SSO) - std::memcpy(sso + pos, other.sso, other._length); - else - std::memcpy(sso + pos, other.ascii.data(), other._length); - - _length = newlen; - return *this; - } - - if (mode == Mode::ASCII_SSO) - promote_sso_ascii_to_heap(); - - if (other.mode == Mode::ASCII_SSO) - ascii.insert(ascii.begin() + pos, other.sso, other.sso + other._length); - else - ascii.insert(ascii.begin() + pos, other.ascii.begin(), other.ascii.end()); - - _length = newlen; - return *this; - } - - // UTF32 路径 - ensure_utf32(); - - if (other.mode == Mode::UTF32_HEP) - utf32.insert(utf32.begin() + pos, other.utf32.begin(), other.utf32.end()); - else if (other.mode == Mode::ASCII_SSO) - for (size_t i = 0; i < other._length; ++i) - utf32.insert(utf32.begin() + pos + i, static_cast(other.sso[i])); - else - for (size_t i = 0; i < other._length; ++i) - utf32.insert(utf32.begin() + pos + i, static_cast(other.ascii[i])); - - _length = utf32.size(); - return *this; - } - - int compare(const String &other) const noexcept - { - size_t n = (_length < other._length) ? _length : other._length; - - for (size_t i = 0; i < n; ++i) - { - u32 a = (*this)[i]; - u32 b = other[i]; - if (a != b) - return (a < b) ? -1 : 1; - } - - if (_length == other._length) - return 0; - return (_length < other._length) ? -1 : 1; - } - - size_t find(const String &needle, size_t pos = 0) const - { - if (needle._length == 0) - return pos <= _length ? pos : size_t(-1); - if (needle._length > _length || pos >= _length) - return size_t(-1); - - size_t limit = _length - needle._length; - - for (size_t i = pos; i <= limit; ++i) - { - size_t j = 0; - for (; j < needle._length; ++j) - if ((*this)[i + j] != needle[j]) - break; - - if (j == needle._length) - return i; - } - - return size_t(-1); - } - - size_t rfind(const String &needle) const - { - if (needle._length == 0) - return _length; - if (needle._length > _length) - return size_t(-1); - - for (size_t i = _length - needle._length + 1; i-- > 0;) - { - size_t j = 0; - for (; j < needle._length; ++j) - if ((*this)[i + j] != needle[j]) - break; - - if (j == needle._length) - return i; - } - - return size_t(-1); - } - - String &replace(size_t pos, size_t len, const String &repl) - { - if (pos >= _length) - return *this; - - size_t erase_len = (_length - pos < len) ? (_length - pos) : len; - - // ASCII路径 - bool this_ascii = (mode != Mode::UTF32_HEP); - bool repl_ascii = (repl.mode != Mode::UTF32_HEP); - - if (this_ascii && repl_ascii) - { - size_t newlen = _length - erase_len + repl._length; - - // SSO容纳 - if (mode == Mode::ASCII_SSO && newlen <= SSO_SIZE) - { - std::memmove(sso + pos + repl._length, sso + pos + erase_len, _length - pos - erase_len); - - if (repl.mode == Mode::ASCII_SSO) - std::memcpy(sso + pos, repl.sso, repl._length); - else - std::memcpy(sso + pos, repl.ascii.data(), repl._length); - - _length = newlen; - return *this; - } - - if (mode == Mode::ASCII_SSO) - promote_sso_ascii_to_heap(); - - ascii.erase(ascii.begin() + pos, ascii.begin() + pos + erase_len); - - if (repl.mode == Mode::ASCII_SSO) - ascii.insert(ascii.begin() + pos, repl.sso, repl.sso + repl._length); - else - ascii.insert(ascii.begin() + pos, repl.ascii.begin(), repl.ascii.end()); - - _length = newlen; - return *this; - } - - // UTF32路径 - ensure_utf32(); - - utf32.erase(utf32.begin() + pos, utf32.begin() + pos + erase_len); - - if (repl.mode == Mode::UTF32_HEP) - utf32.insert(utf32.begin() + pos, repl.utf32.begin(), repl.utf32.end()); - else if (repl.mode == Mode::ASCII_SSO) - for (size_t i = 0; i < repl._length; ++i) - utf32.insert(utf32.begin() + pos + i, static_cast(repl.sso[i])); - else - for (size_t i = 0; i < repl._length; ++i) - utf32.insert(utf32.begin() + pos + i, static_cast(repl.ascii[i])); - - _length = utf32.size(); - return *this; - } - }; -}; // namespace Fig::Deps - -namespace std -{ - template <> - struct hash - { - size_t operator()(const Fig::Deps::String &s) const noexcept - { - using String = Fig::Deps::String; - using u32 = String::u32; - - const size_t FNV_offset = 1469598103934665603ull; - const size_t FNV_prime = 1099511628211ull; - - size_t h = FNV_offset; - - if (s.mode == String::Mode::ASCII_SSO) - { - for (size_t i = 0; i < s._length; ++i) - { - h ^= s.sso[i]; - h *= FNV_prime; - } - return h; - } - - if (s.mode == String::Mode::ASCII_HEP) - { - for (unsigned char c : s.ascii) - { - h ^= c; - h *= FNV_prime; - } - return h; - } - - // UTF32 - for (u32 cp : s.utf32) - { - h ^= static_cast(cp); - h *= FNV_prime; - } - - return h; - } - }; - - template <> - struct std::formatter - { - // 不支持自定义格式说明符 - constexpr auto parse(std::format_parse_context &ctx) - { - return ctx.begin(); - } - - template - auto format(const Fig::Deps::String &s, FormatContext &ctx) const - { - return std::format_to(ctx.out(), "{}", s.toStdString()); - } - }; - -} // namespace std diff --git a/src/Deps/String/StringTest.cpp b/src/Deps/String/StringTest.cpp deleted file mode 100644 index aff81b6..0000000 --- a/src/Deps/String/StringTest.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/*! - @file src/Deps/String/StringTest.cpp - @brief String类测试代码 - @author PuqiAR (im@puqiar.top) - @date 2026-02-13 -*/ - -#include -#include -#include "String.hpp" - -using Fig::Deps::String; - -static void test_ascii_sso() -{ - String s("hello"); - assert(s.size() == 5); - assert(s[0] == U'h'); - assert(s.toStdString() == "hello"); - - s.push_back(U'!'); - assert(s.toStdString() == "hello!"); - - s.pop_back(); - assert(s.toStdString() == "hello"); - - assert(s.starts_with("he")); - assert(s.ends_with("lo")); - assert(s.contains(U'e')); -} - -static void test_ascii_heap() -{ - String a("abcdefghijklmnopqrstuvwxyz"); // > SSO - assert(a.size() == 26); - - String b("123"); - a += b; - - assert(a.ends_with("123")); - assert(a.find(U'1') == 26); -} - -static void test_utf8_decode() -{ - String s("你好"); - assert(s.size() == 2); - assert(s.toStdString() == "你好"); - - s.push_back(U'!'); - assert(s.toStdString() == "你好!"); -} - -static void test_concat_modes() -{ - String a("abc"); - String b("你好"); - - String c = a + b; - assert(c.size() == 5); - assert(c.toStdString() == "abc你好"); - - String d = b + a; - assert(d.toStdString() == "你好abc"); -} - -static void test_substr_erase_insert() -{ - String s("abcdef"); - - String sub = s.substr(2, 3); - assert(sub.toStdString() == "cde"); - - s.erase(2, 2); - assert(s.toStdString() == "abef"); - - s.insert(2, String("CD")); - assert(s.toStdString() == "abCDef"); -} - -static void test_replace() -{ - String s("hello world"); - s.replace(6, 5, String("Fig")); - assert(s.toStdString() == "hello Fig"); -} - -static void test_find_rfind() -{ - String s("abcabcabc"); - - assert(s.find(String("abc")) == 0); - assert(s.find(String("abc"), 1) == 3); - assert(s.rfind(String("abc")) == 6); -} - -static void test_compare() -{ - String a("abc"); - String b("abd"); - String c("abc"); - - assert(a.compare(b) < 0); - assert(b.compare(a) > 0); - assert(a.compare(c) == 0); - assert(a == c); - assert(a != b); -} - -static void test_resize_append() -{ - String s("abc"); - s.resize(5, U'x'); - assert(s.toStdString() == "abcxx"); - - s.append(3, U'y'); - assert(s.toStdString() == "abcxxyyy"); -} - -static void test_std_interop() -{ - std::string stds = "hello"; - String s(stds); - assert(s.toStdString() == "hello"); - - s += " world"; - assert(s.toStdString() == "hello world"); -} - -int main() -{ - test_ascii_sso(); - test_ascii_heap(); - test_utf8_decode(); - test_concat_modes(); - test_substr_erase_insert(); - test_replace(); - test_find_rfind(); - test_compare(); - test_resize_append(); - test_std_interop(); - - std::cout << "All String tests passed.\n"; -} diff --git a/src/Error/Diagnostics.hpp b/src/Error/Diagnostics.hpp deleted file mode 100644 index 1f7943d..0000000 --- a/src/Error/Diagnostics.hpp +++ /dev/null @@ -1,47 +0,0 @@ -/*! - @file src/Error/Diagnostics.hpp - @brief 诊断信息收集器:用于存储警告与非致命错误 - @author PuqiAR (im@puqiar.top) - @date 2026-03-08 -*/ - -#pragma once - -#include - -namespace Fig -{ - class Diagnostics - { - private: - DynArray errors; - - public: - void Report(Error err) - { - errors.push_back(std::move(err)); - } - - // 统一打印所有收集到的信息 - void EmitAll(const SourceManager &manager) - { - for (const auto &err : errors) - { - ReportError(err, manager); - } - } - - bool HasErrors() const - { - for (const auto &err : errors) - { - if (!err.IsWarning()) return true; - } - return false; - } - - const DynArray& GetErrors() const { return errors; } - - void Clear() { errors.clear(); } - }; -} // namespace Fig diff --git a/src/Error/Error.cpp b/src/Error/Error.cpp deleted file mode 100644 index 9d5e235..0000000 --- a/src/Error/Error.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/*! - @file src/Error/Error.cpp - @brief 错误报告实现 - @author PuqiAR (im@puqiar.top) - @date 2026-02-14 -*/ - -#include -#include - -#include - -namespace Fig -{ - void ColoredPrint(const char *color, const char *msg, std::ostream &ost = CoreIO::GetStdErr()) - { - ost << color << msg << TerminalColors::Reset; - } - - void - ColoredPrint(const char *color, const std::string &msg, std::ostream &ost = CoreIO::GetStdErr()) - { - ost << color << msg << TerminalColors::Reset; - } - - void ColoredPrint(const char *color, const String &msg, std::ostream &ost = CoreIO::GetStdErr()) - { - ost << color << msg << TerminalColors::Reset; - } - - std::string MultipleStr(const char *c, size_t n) - { - std::string buf; - for (size_t i = 0; i < n; ++i) - { - buf += c; - } - return buf; - } - - const char *ErrorTypeToString(ErrorType type) - { - using enum ErrorType; - switch (type) - { - case UnusedSymbol: return "UnusedSymbol"; - case UnnecessarySemicolon: return "UnnecessarySemicolon"; - - case MayBeNull: return "MaybeNull"; - - case UnterminatedString: return "UnterminatedString"; - case UnterminatedComments: return "UnterminatedComments"; - case InvalidNumberLiteral: return "InvalidNumberLiteral"; - case InvalidCharacter: return "InvalidCharacter"; - case InvalidSymbol: return "InvalidSymbol"; - - case ExpectedExpression: return "ExpectedExpression"; - case SyntaxError: return "SyntaxError"; - - case RedeclarationError: return "RedeclarationError"; - case UseUndeclaredIdentifier: return "UseUndeclaredIdentifier"; - case NotAnLvalue: return "NotAnLvalue"; - case TypeError: return "TypeError"; - - case TooManyLocals: return "TooManyLocals"; - case TooManyConstants: return "TooManyConstants"; - - case RegisterOverflow: return "RegisterOverflow"; - case InternalError: - return "InternalError"; - // default: return "Some one forgot to add case to `ErrorTypeToString`"; - } - return "UnknownError"; - } - - void PrintSystemInfos() - { - std::ostream &err = CoreIO::GetStdErr(); - std::stringstream build_info; - build_info << "\r🌘 Fig v" << Core::VERSION << " on " << Core::PLATFORM << ' ' << Core::ARCH - << '[' << Core::COMPILER << ']' << '\n' - << " Build Time: " << Core::COMPILE_TIME; - - const std::string &build_info_str = build_info.str(); - err << MultipleStr("─", build_info_str.size()) << '\n'; - err << build_info_str << '\n'; - err << MultipleStr("─", build_info_str.size()) << '\n'; - } - - void PrintErrorInfo(const Error &error, const SourceManager &srcManager) - { - static constexpr const char *MinorColor = "\033[38;2;138;227;198m"; - static constexpr const char *MediumColor = "\033[38;2;255;199;95m"; - static constexpr const char *CriticalColor = "\033[38;2;255;107;107m"; - - namespace TC = TerminalColors; - std::ostream &err = CoreIO::GetStdErr(); - - uint8_t level = ErrorLevel(error.type); - // const char *level_name = (level == 1 ? "Minor" : (level == 2 ? "Medium" : "Critical")); - const char *level_color = - (level == 1 ? MinorColor : (level == 2 ? MediumColor : CriticalColor)); - - err << "🔥 " - << level_color - //<< '(' << level_name << ')' - << 'E' << static_cast(error.type) << TC::Reset << ": " << level_color - << ErrorTypeToString(error.type) << TC::Reset << '\n'; - - const SourceLocation &location = error.location; - - err << TC::DarkGray << " ┌─> Fn " << TC::Cyan << '\'' << location.packageName << '.' - << location.functionName << '\'' << " " << location.fileName << " (" << TC::DarkGray - << location.sp.line << ":" << location.sp.column << TC::Cyan << ')' << TC::Reset - << '\n'; - err << TC::DarkGray << " │" << '\n' << " │" << TC::Reset << '\n'; - - // 尝试打印上3行 下2行 - - int64_t line_start = location.sp.line - 3, line_end = location.sp.line + 2; - while (!srcManager.HasLine(line_end)) - { - --line_end; - } - while (!srcManager.HasLine(line_start)) - { - ++line_start; - } - - const auto &getLineNumWidth = [](size_t l) { - unsigned int cnt = 0; - while (l != 0) - { - l = l / 10; - cnt++; - } - return cnt; - }; - unsigned int max_line_number_width = getLineNumWidth(line_end); - for (size_t i = line_start; i <= line_end; ++i) - { - unsigned int offset = 2 + 2 + 1; - // ' └─ ' - if (i == location.sp.line) - { - err << TC::DarkGray << " └─ " << TC::Reset; - } - else if (i < location.sp.line) - { - err << TC::DarkGray << " │ " << TC::Reset; - } - else - { - err << MultipleStr(" ", offset); - } - unsigned int cur_line_number_width = getLineNumWidth(i); - - err << MultipleStr(" ", max_line_number_width - cur_line_number_width) << TC::Yellow - << i << TC::Reset; - err << " │ " << srcManager.GetLine(i) << '\n'; - if (i == location.sp.line) - { - unsigned int error_col_offset = offset + 1 + max_line_number_width + 2; - err << MultipleStr(" ", error_col_offset) - << MultipleStr(" ", location.sp.column - 1) << TC::LightGreen - << MultipleStr("^", location.sp.tok_length) << TC::Reset << '\n'; - - err << MultipleStr(" ", error_col_offset) - << MultipleStr(" ", location.sp.column - 1 + location.sp.tok_length / 2) - << "╰─ " << level_color << error.message << TC::Reset << "\n\n"; - } - } - err << "\n"; - err << "❓ " << TC::DarkGray << "Thrower: " << error.thrower_loc.function_name() << " (" - << error.thrower_loc.file_name() << ":" << error.thrower_loc.line() << ")" << TC::Reset - << "\n"; - err << "💡 " << TC::Blue << "Suggestion: " << error.suggestion << TC::Reset; - err << '\n'; - } - - void ReportError(const Error &error, const SourceManager &srcManager) - { - assert(srcManager.read && "ReportError: srcManager doesn't read source"); - // assert(srcManager.HasLine(error.location.sp.line)); - - PrintSystemInfos(); - PrintErrorInfo(error, srcManager); - } - - void ReportErrors(const std::vector &errors, const SourceManager &srcManager) - { - std::ostream &ost = CoreIO::GetStdErr(); - PrintSystemInfos(); - for (const auto &err : errors) - { - PrintErrorInfo(err, srcManager); - ost << '\n'; - } - } -}; // namespace Fig diff --git a/src/Error/Error.hpp b/src/Error/Error.hpp deleted file mode 100644 index 0e846a1..0000000 --- a/src/Error/Error.hpp +++ /dev/null @@ -1,185 +0,0 @@ -/*! - @file src/Error/Error.hpp - @brief Error定义 - @author PuqiAR (im@puqiar.top) - @date 2026-02-13 -*/ - -#pragma once - -#include -#include -#include - -#include - -namespace Fig -{ - /* - 0-1000 Minor - 1001-2000 Medium - 2001-3000 Critical - */ - enum class ErrorType : unsigned int - { - /* Minor */ - UnusedSymbol = 0, - UnnecessarySemicolon, - TrailingComma, - - /* Medium */ - MayBeNull = 1001, - - /* Critical */ - - // lexer errors - UnterminatedString = 2001, - UnterminatedComments, - InvalidNumberLiteral, - InvalidCharacter, - InvalidSymbol, - - // parser errors - ExpectedExpression, - SyntaxError, - - // analyzer errors - RedeclarationError, - UseUndeclaredIdentifier, - NotAnLvalue, - TypeError, - - // compile errors - TooManyLocals, - TooManyConstants, - - // 编译器内部约束 - RegisterOverflow, - InternalError, - }; - - const char *ErrorTypeToString(ErrorType type); - - struct Error - { - ErrorType type; - String message; - String suggestion; - - SourceLocation location; - std::source_location thrower_loc; - - Error() {} - Error(ErrorType _type, - const String &_message, - const String &_suggestion, - const SourceLocation &_location, - const std::source_location &_throwerloc = std::source_location::current()) - { - type = _type; - message = _message; - suggestion = _suggestion; - location = _location; - thrower_loc = _throwerloc; - } - - // 新增:适配诊断系统的辅助判定 - bool IsWarning() const { return static_cast(type) < 2000; } - }; - - namespace TerminalColors - { - constexpr const char *Reset = "\033[0m"; - constexpr const char *Bold = "\033[1m"; - constexpr const char *Dim = "\033[2m"; - constexpr const char *Italic = "\033[3m"; - constexpr const char *Underline = "\033[4m"; - constexpr const char *Blink = "\033[5m"; - constexpr const char *Reverse = "\033[7m"; // 前背景反色 - constexpr const char *Hidden = "\033[8m"; // 隐藏文本 - constexpr const char *Strike = "\033[9m"; // 删除线 - - constexpr const char *Black = "\033[30m"; - constexpr const char *Red = "\033[31m"; - constexpr const char *Green = "\033[32m"; - constexpr const char *Yellow = "\033[33m"; - constexpr const char *Blue = "\033[34m"; - constexpr const char *Magenta = "\033[35m"; - constexpr const char *Cyan = "\033[36m"; - constexpr const char *White = "\033[37m"; - - constexpr const char *LightBlack = "\033[90m"; - constexpr const char *LightRed = "\033[91m"; - constexpr const char *LightGreen = "\033[92m"; - constexpr const char *LightYellow = "\033[93m"; - constexpr const char *LightBlue = "\033[94m"; - constexpr const char *LightMagenta = "\033[95m"; - constexpr const char *LightCyan = "\033[96m"; - constexpr const char *LightWhite = "\033[97m"; - - constexpr const char *DarkRed = "\033[38;2;128;0;0m"; - constexpr const char *DarkGreen = "\033[38;2;0;100;0m"; - constexpr const char *DarkYellow = "\033[38;2;128;128;0m"; - constexpr const char *DarkBlue = "\033[38;2;0;0;128m"; - constexpr const char *DarkMagenta = "\033[38;2;100;0;100m"; - constexpr const char *DarkCyan = "\033[38;2;0;128;128m"; - constexpr const char *DarkGray = "\033[38;2;64;64;64m"; - constexpr const char *Gray = "\033[38;2;128;128;128m"; - constexpr const char *Silver = "\033[38;2;192;192;192m"; - - constexpr const char *Navy = "\033[38;2;0;0;128m"; - constexpr const char *RoyalBlue = "\033[38;2;65;105;225m"; - constexpr const char *ForestGreen = "\033[38;2;34;139;34m"; - constexpr const char *Olive = "\033[38;2;128;128;0m"; - constexpr const char *Teal = "\033[38;2;0;128;128m"; - constexpr const char *Maroon = "\033[38;2;128;0;0m"; - constexpr const char *Purple = "\033[38;2;128;0;128m"; - constexpr const char *Orange = "\033[38;2;255;165;0m"; - constexpr const char *Gold = "\033[38;2;255;215;0m"; - constexpr const char *Pink = "\033[38;2;255;192;203m"; - constexpr const char *Crimson = "\033[38;2;220;20;60m"; - - constexpr const char *OnBlack = "\033[40m"; - constexpr const char *OnRed = "\033[41m"; - constexpr const char *OnGreen = "\033[42m"; - constexpr const char *OnYellow = "\033[43m"; - constexpr const char *OnBlue = "\033[44m"; - constexpr const char *OnMagenta = "\033[45m"; - constexpr const char *OnCyan = "\033[46m"; - constexpr const char *OnWhite = "\033[47m"; - - constexpr const char *OnLightBlack = "\033[100m"; - constexpr const char *OnLightRed = "\033[101m"; - constexpr const char *OnLightGreen = "\033[102m"; - constexpr const char *OnLightYellow = "\033[103m"; - constexpr const char *OnLightBlue = "\033[104m"; - constexpr const char *OnLightMagenta = "\033[105m"; - constexpr const char *OnLightCyan = "\033[106m"; - constexpr const char *OnLightWhite = "\033[107m"; - - constexpr const char *OnDarkBlue = "\033[48;2;0;0;128m"; - constexpr const char *OnGreenYellow = "\033[48;2;173;255;47m"; - constexpr const char *OnOrange = "\033[48;2;255;165;0m"; - constexpr const char *OnGray = "\033[48;2;128;128;128m"; - }; // namespace TerminalColors - - inline uint8_t ErrorLevel(ErrorType t) - { - unsigned int id = static_cast(t); - if (id <= 1000) - { - return 1; - } - if (id > 1000 && id <= 2000) - { - return 2; - } - if (id > 2000) - { - return 3; - } - return 0; - } - - void ReportError(const Error &error, const SourceManager &srcManager); -}; // namespace Fig diff --git a/src/LSP/LSPServer.hpp b/src/LSP/LSPServer.hpp deleted file mode 100644 index dbcacef..0000000 --- a/src/LSP/LSPServer.hpp +++ /dev/null @@ -1,180 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include -#include - -#include // C++17/20 字符串转数字 -#include -#include - -#include -using json = nlohmann::json; - -namespace Fig -{ - - class LspServer - { - public: - void Run() - { - std::ios_base::sync_with_stdio(false); - std::cin.tie(NULL); - - while (true) - { - std::string line; - if (!std::getline(std::cin, line)) - break; // 退出循环 - - // 解析 HTTP 风格的 Header: "Content-Length: 123\r" - if (line.starts_with("Content-Length: ")) - { - std::size_t length = 0; - // 使用 C++ 极速的 from_chars 替代 stoi - auto res = std::from_chars(line.data() + 16, line.data() + line.size(), length); - if (res.ec != std::errc()) - continue; - - // 消费 Header 和 Body 之间那行空的 "\r\n" - std::string emptyLine; - std::getline(std::cin, emptyLine); - - // 读取对应字节的 JSON Body - std::string jsonBody(length, '\0'); - std::cin.read(jsonBody.data(), length); - - // 派发给路由 - HandleMessage(jsonBody); - } - } - } - - private: - void HandleMessage(const std::string &rawJson) - { - json req = json::parse(rawJson, nullptr, false); - if (req.is_discarded()) - return; // 忽略解析失败的报文 - - std::string method = req.value("method", ""); - - if (method == "initialize") - { - Respond(req["id"], R"({ - "capabilities": { - "textDocumentSync": 1, - "hoverProvider": true - } - })"); - } - else if (method == "textDocument/didOpen") - { - std::string uri = req["params"]["textDocument"]["uri"]; - std::string text = req["params"]["textDocument"]["text"]; - PublishDiagnostics(uri, text); - } - else if (method == "textDocument/didChange") - { - std::string uri = req["params"]["textDocument"]["uri"]; - std::string text = req["params"]["contentChanges"][0]["text"]; - PublishDiagnostics(uri, text); - } - } - - void Respond(int id, const std::string &resultJsonString) - { - std::string response = "{\"jsonrpc\":\"2.0\",\"id\":" + std::to_string(id) - + ",\"result\":" + resultJsonString + "}"; - std::cout << "Content-Length: " << response.size() << "\r\n\r\n" - << response << std::flush; - } - - void SendDiagnostics(const std::string &uri, const Error *err = nullptr) - { - json diagnostics = json::array(); // 默认空数组,代码无错时擦除红线 - - if (err) - { - // LSP 规定行列号必须从 0 开始算 - int startLine = err->location.sp.line - 1; - int startChar = err->location.sp.column - 1; - int endLine = startLine; - int endChar = startChar + err->location.sp.tok_length; - - std::string fullMessage = err->message.toStdString(); - if (!err->suggestion.empty()) - { - fullMessage += " 💡suggestion: " + err->suggestion.toStdString(); - } - - diagnostics.push_back( - {{"range", - {{"start", {{"line", startLine}, {"character", startChar}}}, - {"end", {{"line", endLine}, {"character", endChar}}}}}, - {"severity", 1}, // 1 = 致命错误红线 - {"source", "Fig LSP Server"}, - {"message", fullMessage}}); - } - - // 组装 Notification - json notification = {{"jsonrpc", "2.0"}, - {"method", "textDocument/publishDiagnostics"}, - {"params", {{"uri", uri}, {"diagnostics", diagnostics}}}}; - - std::string response = notification.dump(); - std::cout << "Content-Length: " << response.size() << "\r\n\r\n" - << response << std::flush; - } - - void PublishDiagnostics(const std::string &uri, const std::string &sourceCode) - { - SourceManager manager; - manager.LoadFromMemory(sourceCode); - - Lexer lexer(sourceCode, ""); - - Diagnostics diagnostics; - - Parser parser(lexer, manager, "", diagnostics); - - // 语法检查拦截 - auto parserResult = parser.Parse(); - if (!parserResult) - { - SendDiagnostics(uri, &parserResult.error()); - return; - } - - for (auto &diag : diagnostics.GetErrors()) - { - SendDiagnostics(uri, &diag); - } - - Program *program = *parserResult; - - Analyzer analyzer(manager); - - // 语义检查拦截 - auto analyzerResult = analyzer.Analyze(program); - if (!analyzerResult) - { - SendDiagnostics(uri, &analyzerResult.error()); - return; - } - - for (auto &diag : analyzer.GetDiagnostics().GetErrors()) - { - SendDiagnostics(uri, &diag); - } - - // 一切完美,发射空数组清空过去的错误红线 - SendDiagnostics(uri, nullptr); - } - }; -} // namespace Fig \ No newline at end of file diff --git a/src/Lexer/Lexer.cpp b/src/Lexer/Lexer.cpp deleted file mode 100644 index ee7e172..0000000 --- a/src/Lexer/Lexer.cpp +++ /dev/null @@ -1,328 +0,0 @@ -/*! - @file src/Lexer/Lexer.cpp - @brief 词法分析器(materialized lexeme)实现 - @author PuqiAR (im@puqiar.top) - @date 2026-02-14 -*/ -#include - -namespace Fig -{ - /* - 总则: - Lexer不涉及语义部分,语义为Parser及之后的部分确定! - 确定边界 --> 分词 - 无法确定 --> 错误的源,报错 - - */ - - Result Lexer::scanComments() - { - Token tok(rd.currentIndex(), 2, TokenType::Comments); - rd.skip(2); // 跳过 // - do - { - tok.length++; - if (rd.current() == U'\n') - { - rd.next(); // skip '\n' - break; - } - rd.next(); - } while (rd.hasNext()); - return tok; - } - - Result Lexer::scanMultilineComments() - { - Token tok(rd.currentIndex(), 2, TokenType::Comments); - SourcePosition startPos = rd.currentPosition(); - rd.skip(2); // 跳过 / * - while (true) - { - if (rd.isAtEnd()) - { - return std::unexpected(Error(ErrorType::UnterminatedComments, - "unterminated multiline comments", - "insert '*/'", - makeSourceLocation(startPos))); - } - if (rd.current() == U'*' && rd.peekIf() == U'/') - { - rd.skip(2); - break; - } - tok.length++; - rd.next(); - } - return tok; - } - - Result Lexer::scanIdentifierOrKeyword() - { - Token tok(rd.currentIndex(), 1, TokenType::Identifier); - String value; // 用于判断是标识符还是关键字 - value.push_back(rd.produce()); // 加入第一个 - - while (!rd.isAtEnd() && CharUtils::isIdentifierContinue(rd.current())) // continue: _ / 0-9 / aA - zZ - { - tok.length++; - value.push_back(rd.produce()); - if (rd.isAtEnd()) - { - break; - } - } - - if (Token::keywordMap.contains(value)) - { - tok.type = Token::keywordMap.at(value); - } - return tok; - } - - Result Lexer::scanNumberLiteral() - { - Token tok(rd.currentIndex(), 0, TokenType::LiteralNumber); - state = State::ScanDec; - - if (rd.current() == U'0') - { - char32_t _peek = std::tolower(rd.peekIf()); - if (_peek == U'b') - { - state = State::ScanBin; - rd.skip(2); // 跳过 0b - tok.length += 2; - } - else if (_peek == U'x') - { - state = State::ScanHex; - rd.skip(2); // 跳过 0x - tok.length += 2; - } - // else - // { - // return std::unexpected(Error(ErrorType::InvalidNumberLiteral, - // std::format("bad number postfix 0{}", String(_peek)), - // "correct it", - // makeSourceLocation(rd.currentPosition()))); - - // } - } - - do - { - char32_t current = rd.current(); - if (state == State::ScanDec && !CharUtils::isDigit(current)) - { - break; - } - if (state == State::ScanHex && !CharUtils::isHexDigit(current)) - { - break; - } - if (state == State::ScanBin && current != U'0' && current != U'1') - { - // return std::unexpected( - // Error(ErrorType::InvalidNumberLiteral, - // std::format("invalid binary number literal, scanning '{}'", String(¤t)), - // "correct it", - // makeSourceLocation(rd.currentPosition()))); - break; - } - tok.length++; - rd.next(); - } while (!rd.isAtEnd()); - - // 下划线表示法(1_000_000) - while (!rd.isAtEnd() && state == State::ScanDec && (rd.current() == U'_' || CharUtils::isDigit(rd.current()))) - { - tok.length++; - rd.next(); - } - - // 小数点 - if (rd.currentIf() == U'.') - { - tok.length++; - rd.next(); - - if (!CharUtils::isDigit(rd.currentIf())) - { - return std::unexpected(Error(ErrorType::InvalidNumberLiteral, - "need matissa", - "insert matissa", - makeSourceLocation(rd.currentPosition()))); - } - while (!rd.isAtEnd() && CharUtils::isDigit(rd.current())) - { - tok.length++; - rd.next(); - } - } - - // 科学计数法 - if (rd.currentIf() == U'e') - { - tok.length++; - char32_t peek = rd.peekIf(); - if (peek == U'+' || peek == U'-') // ae+b, ae-b - { - tok.length++; - rd.skip(2); // consume `e`, +/- - } - else if (CharUtils::isDigit(peek)) // aeb 情况 - { - rd.next(); // `e` - } - if (!CharUtils::isDigit(rd.currentIf())) - { - return std::unexpected(Error(ErrorType::InvalidNumberLiteral, - "need exponent for scientific notation", - "insert exponent", - makeSourceLocation(rd.currentPosition()))); - } - while (!rd.isAtEnd() && CharUtils::isDigit(rd.current())) - { - tok.length++; - rd.next(); - } - } - return tok; - } - Result Lexer::scanStringLiteral() - { - state = (rd.current() == U'"' ? State::ScanStringDQ : Lexer::State::ScanStringSQ); - - SourcePosition startPos = rd.currentPosition(); - - Token tok(rd.currentIndex(), 1, TokenType::LiteralString); // " - rd.next(); // skip " / ' - - while (true) - { - if (state == State::ScanStringDQ && rd.current() == U'"') - { - tok.length++; - rd.next(); // skip '"' - break; - } - else if (state == State::ScanStringSQ && rd.current() == U'\'') - { - tok.length++; - rd.next(); // skip `'` - break; - } - else if (rd.isAtEnd()) - { - return std::unexpected(Error(ErrorType::UnterminatedString, - "unterminated string literal", - std::format("insert '{}'", String((state == State::ScanStringDQ ? "\"" : "'"))), - makeSourceLocation(startPos))); - } - else - { - tok.length++; - rd.next(); - } - } - return tok; - } - Result Lexer::scanPunct() - { - Token tok(rd.currentIndex(), 0, TokenType::Illegal); - - auto startsWith = [&](const String &prefix) -> bool { - for (const auto &p : Token::punctMap) - { - const String &op = p.first; - if (op.starts_with(prefix)) - return true; - } - return false; - }; - - String sym; - - do - { - String candidate = sym + rd.current(); - if (startsWith(candidate)) - { - rd.next(); - tok.length++; - sym = candidate; - } - else - { - break; - } - } while (!rd.isAtEnd() && CharUtils::isPunct(rd.current())); - - if (!Token::punctMap.contains(sym)) - { - return std::unexpected(Error(ErrorType::InvalidSymbol, - std::format("invalid symbol `{}`", sym), - "correct it", - makeSourceLocation(rd.currentPosition()))); - } - tok.type = Token::punctMap.at(sym); - return tok; - } - - void Lexer::skipWhitespaces() - { - while (!rd.isAtEnd()) - { - char32_t current = rd.current(); - if (!CharUtils::isAsciiSpace(current)) // 检查 EOF - break; - rd.next(); - } - } - - Result Lexer::NextToken() - { - if (rd.isAtEnd()) - { - return Token(rd.getEOFIndex(), 1, TokenType::EndOfFile); - } - if (rd.current() == U'/' && rd.peekIf() == U'/') - { - return scanComments(); - } - else if (rd.current() == U'/' && rd.peekIf() == U'*') - { - return scanMultilineComments(); - } - else if (CharUtils::isIdentifierStart(rd.current())) - { - return scanIdentifierOrKeyword(); - } - else if (CharUtils::isDigit(rd.current())) - { - return scanNumberLiteral(); - } - else if (rd.current() == U'"' || rd.current() == U'\'') - { - return scanStringLiteral(); - } - else if (CharUtils::isPunct(rd.current())) - { - return scanPunct(); - } - else if (CharUtils::isSpace(rd.current())) - { - skipWhitespaces(); - return NextToken(); - } - else - { - return std::unexpected(Error(ErrorType::InvalidCharacter, - std::format("invalid character '{}' (U+{})", String(rd.current()), static_cast(rd.current())), - "correct it", - makeSourceLocation(rd.currentPosition()))); - } - } -}; // namespace Fig \ No newline at end of file diff --git a/src/Lexer/Lexer.hpp b/src/Lexer/Lexer.hpp deleted file mode 100644 index c74b06c..0000000 --- a/src/Lexer/Lexer.hpp +++ /dev/null @@ -1,189 +0,0 @@ -/*! - @file src/Lexer/Lexer.hpp - @brief 词法分析器(materialized lexeme) - @author PuqiAR (im@puqiar.top) - @date 2026-02-13 -*/ - -#pragma once - -#include -#include -#include -#include - - -namespace Fig -{ - class SourceReader - { - private: - String source; - size_t index; - - SourcePosition pos; - - public: - SourceReader() - { - index = 0; - pos.line = pos.column = 1; - } - SourceReader(const String &_source) // copy - { - source = _source; - index = 0; - pos.line = pos.column = 1; - } - - SourcePosition ¤tPosition() - { - return pos; - } - - inline char32_t current() const - { - assert(index < source.length() && "SourceReader: get current failed, index out of range"); - return source[index]; - } - - inline char32_t currentIf() const - { - if (index >= source.length()) - { - return U'\0'; - } - return source[index]; - } - - inline bool hasNext() const - { - return index < source.length() - 1; - } - - inline char32_t peek() const - { - assert((index + 1) < source.length() && "SourceReader: get peek failed, index out of range"); - return source[index + 1]; - } - - inline char32_t peekIf() const - { - if ((index + 1) < source.length()) - { - return source[index + 1]; - } - return 0xFFFD; - } - - inline char32_t produce() - { - // returns current rune, then next - char32_t c = current(); - next(); - return c; - } - - inline void next() - { - char32_t consumed = currentIf(); - - ++index; - if (consumed == U'\n') - { - ++pos.line; - pos.column = 1; - } - else - { - ++pos.column; - } - } - - inline void skip(size_t n) - { - for (size_t i = 0; i < n; ++i) - { - next(); - } - } - - inline size_t currentIndex() const - { - return index; - } - - inline bool isAtEnd() const - { - return index >= source.length(); - } - - inline size_t getEOFIndex() const - { - return source.length(); - } - }; - - class Lexer - { - public: - enum class State : uint8_t - { - Error, - Standby, - End, - - ScanComments, // 单行注释 - ScanMultilineComments, // 多行注释 - ScanIdentifier, // 关键字也算 - - ScanDec, // 十进制数字, 如 1.2 31, 3.14e+3, 1_000_0000 - ScanBin, // 二进制数字, 如 0b0001 / 0B0001 - ScanHex, // 十六进制数字, 如 0xABCD / 0XabCd - ScanStringDQ, // 双引号字符串, 如 "hello, world!" - ScanStringSQ, // 单引号字符串, 如 'hello' - ScanBool, // 布尔字面量, true / false - ScanNull, // 空值字面量, null - - ScanPunct, // 符号 - }; - - private: - String fileName; - SourceReader rd; - - protected: - Result scanComments(); - Result scanMultilineComments(); - - Result scanIdentifierOrKeyword(); - - Result scanNumberLiteral(); - Result scanStringLiteral(); // 支持多行 - // Result scanBoolLiteral(); 由 scanIdentifier...扫描 - // Result scanLiteralNull(); 由 scanIdentifier...扫描 - - Result scanPunct(); - - void skipWhitespaces(); - - public: - State state = State::Standby; - - Lexer() {} - Lexer(const String &source, String _fileName) - { - rd = SourceReader(source); - fileName = std::move(_fileName); - } - - SourceLocation makeSourceLocation(SourcePosition current_pos) - { - current_pos.tok_length = 1; - return SourceLocation( - current_pos, fileName, "[internal lexer]", String(magic_enum::enum_name(state).data())); - } - - Result NextToken(); - }; -}; // namespace Fig \ No newline at end of file diff --git a/src/Lexer/LexerTest.cpp b/src/Lexer/LexerTest.cpp deleted file mode 100644 index 81a5fe1..0000000 --- a/src/Lexer/LexerTest.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include -#include -#include - - -#include - -int main() -{ - using namespace Fig; - - String fileName = "test.fig"; - String filePath = "T:/Files/Maker/Code/MyCodingLanguage/The Fig Project/Fig/test.fig"; - - SourceManager manager(filePath); - manager.Read(); - - if (!manager.read) - { - std::cerr << "Couldn't read file"; - return 1; - } - - Lexer lexer(manager.GetSource(), fileName); - - while (true) - { - auto result = lexer.NextToken(); - if (!result.has_value()) - { - ReportError(result.error(), manager); - break; - } - const Token &token = *result; - const String &lexeme = manager.GetSub(token.index, token.length); - const auto &type = magic_enum::enum_name(token.type); - if (token.type == TokenType::EndOfFile) - { - std::cout << "EOF: " << type << " at " << token.index << '\n'; - break; - } - std::cout << lexeme << " --> " << type << '\n'; - } -} \ No newline at end of file diff --git a/src/Object/FunctionObject.hpp b/src/Object/FunctionObject.hpp deleted file mode 100644 index e2a997c..0000000 --- a/src/Object/FunctionObject.hpp +++ /dev/null @@ -1,40 +0,0 @@ -/*! - @file src/Object/FunctionObject.hpp - @brief 函数对象定义 -*/ - -#pragma once - -#include -#include - -namespace Fig -{ - // Upvalue (Stack Open / Heap Closed) - struct Upvalue - { - Value *location; // Open 状态指向 VM 的 registerBase[x],Closed 状态指向下面的 closedValue - Value closedValue; // 栈帧销毁时,数据物理迁移至此 - Upvalue *next; // 侵入式链表,供 VM 追踪当前 Open 的 Upvalue - std::uint32_t refCount = 0; // 多少个闭包正在使用 - }; - - struct FunctionObject final : public Object - { - String name; - Proto *proto; // 静态只读字节码 - std::uint8_t paraCount; - std::uint32_t upvalueCount; // 捕获数量 - - // 柔性数组 - Upvalue *upvalues[]; - - FunctionObject(const String &_name, Proto *_proto, std::uint32_t _upvalueCount) : - name(_name), proto(_proto), paraCount(_proto->numParams), upvalueCount(_upvalueCount) - { - type = ObjectType::Function; - } - - ~FunctionObject() = default; - }; -} // namespace Fig \ No newline at end of file diff --git a/src/Object/InstanceObject.hpp b/src/Object/InstanceObject.hpp deleted file mode 100644 index 2659491..0000000 --- a/src/Object/InstanceObject.hpp +++ /dev/null @@ -1,16 +0,0 @@ -/*! - @file src/Object/InstanceObject.hpp - @brief 实例(InstanceObject)定义 - @author PuqiAR (im@puqiar.top) - @date 2026-03-10 -*/ - -#include - -namespace Fig -{ - struct InstanceObject final : public Object - { - Value fields[]; - }; -} diff --git a/src/Object/Object.cpp b/src/Object/Object.cpp deleted file mode 100644 index fb1fb89..0000000 --- a/src/Object/Object.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/*! - @file src/Object/Object.hpp - @brief 值表示实现 (NaN Boxing) 和 堆对象函数的实现 - @author PuqiAR (im@puqiar.top) - @date 2026-02-19 -*/ - -#include - -namespace Fig -{ - String Value::ToString() const - { - if (IsNull()) - { - return "null"; - } - else if (IsInt()) - { - return std::to_string(AsInt()); - } - else if (IsDouble()) - { - return std::format("{}", AsDouble()); - } - else if (IsBool()) - { - return (AsBool() ? "true" : "false"); - } - else if (IsObject()) - { - Object *obj = AsObject(); - if (!obj) - return ""; - - // 物理分发, 扔掉虚函数!awa - switch (obj->type) - { - case ObjectType::String: { - auto *strObj = static_cast(obj); - return strObj->data; - } - case ObjectType::Function: { - auto *fnObj = static_cast(obj); - return std::format("", fnObj->name); - } - case ObjectType::Struct: { - auto *structObj = static_cast(obj); - return std::format("", structObj->name); - } - case ObjectType::Instance: { - // 利用你预留的神级指针 klass 溯源 - if (obj->klass) - { - return std::format("", obj->klass->name); - } - return ""; - } - default: return ""; - } - } - else - { - return "Unknow"; - } - } -}; // namespace Fig \ No newline at end of file diff --git a/src/Object/Object.hpp b/src/Object/Object.hpp deleted file mode 100644 index ac08955..0000000 --- a/src/Object/Object.hpp +++ /dev/null @@ -1,14 +0,0 @@ -/*! - @file src/Object/Object.hpp - @brief 值系统总文件 - @author PuqiAR (im@puqiar.top) - @date 2026-02-19 -*/ - -#pragma once - -#include -#include -#include -#include -#include diff --git a/src/Object/ObjectBase.hpp b/src/Object/ObjectBase.hpp deleted file mode 100644 index 31e9bcc..0000000 --- a/src/Object/ObjectBase.hpp +++ /dev/null @@ -1,283 +0,0 @@ -/*! - @file src/Object/ObjectBase.hpp - @brief 值表示定义 (NaN Boxing) uint64 - @author PuqiAR (im@puqiar.top) - @date 2026-02-19 -*/ - -#pragma once - -#include -#include - -#include - -namespace Fig -{ - - struct Object; // 前置声明 - - /* - 正常来说直接 Value = std::uint64_t会更快 - 但是这样会带来隐式转换的问题 - - 因此我们封装成一个类,这样速度不会损失很多。 - (release模式编译器会直接优化, 速度和uint64_t直接表示一样快) - */ - class Value - { - private: - std::uint64_t v_; // 唯一的物理成员 sizeof(Value) 永远是 8 字节。 - - // --- 私有掩码常量 --- - static constexpr std::uint64_t QNAN_MASK = 0x7ffc000000000000; - static constexpr std::uint64_t SIGN_BIT = 0x8000000000000000; - - // 专门给 Int32 预留的高位 Tag - static constexpr std::uint32_t INT_TAG_HIGH = 0x7FFD0000; - - // 基础原语 Tag - static constexpr std::uint64_t TAG_NULL = 1; - static constexpr std::uint64_t TAG_FALSE = 2; - static constexpr std::uint64_t TAG_TRUE = 3; - - // 私有底层构造:仅供内部组装使用 - constexpr explicit Value(uint64_t raw) : v_(raw) {} - - public: - // 默认构造为 Null,保证未初始化变量也是安全的 - constexpr Value() - { - *this = GetNullInstance(); - } - - [[nodiscard]] static constexpr Value FromDouble(double d) - { - uint64_t raw = std::bit_cast(d); - // 清洗非法的 NaN - if ((raw & QNAN_MASK) == QNAN_MASK) - return Value(QNAN_MASK); - return Value(raw); - } - - [[nodiscard]] static constexpr Value FromInt(std::int32_t i) - { - // 移位构造,彻底阻断符号扩展漏洞 - return Value((static_cast(INT_TAG_HIGH) << 32) | static_cast(i)); - } - - [[nodiscard]] static constexpr Value &GetTrueInstance() - { - static Value trueInstance(QNAN_MASK | TAG_TRUE); - return trueInstance; - } - [[nodiscard]] static constexpr Value &GetFalseInstance() - { - static Value falseInstance(QNAN_MASK | TAG_FALSE); - return falseInstance; - } - - [[nodiscard]] static constexpr Value &FromBool(bool b) - { - return (b ? GetTrueInstance() : GetFalseInstance()); - } - - [[nodiscard]] static constexpr Value &GetNullInstance() - { - static Value nullInstance(QNAN_MASK | TAG_NULL); - return nullInstance; - } - - [[nodiscard]] static Value FromObject(Object *ptr) - { - return Value(reinterpret_cast(ptr) | SIGN_BIT | QNAN_MASK); - } - - // 类型检查 (Is) - - [[nodiscard]] constexpr bool IsDouble() const - { - return (v_ & QNAN_MASK) != QNAN_MASK; - } - - [[nodiscard]] constexpr bool IsInt() const - { - // 安全的高 32 位移位判定 - return static_cast(v_ >> 32) == INT_TAG_HIGH; - } - - [[nodiscard]] constexpr bool IsNumber() const - { - return IsDouble() || IsInt(); - } - - [[nodiscard]] constexpr bool IsNull() const - { - return v_ == (QNAN_MASK | TAG_NULL); - } - - [[nodiscard]] constexpr bool IsBool() const - { - return (v_ | 1) == (QNAN_MASK | TAG_TRUE); - } - - [[nodiscard]] constexpr bool IsObject() const - { - return (v_ & (SIGN_BIT | QNAN_MASK)) == (SIGN_BIT | QNAN_MASK); - } - - // 提取数据 (Unbox / As) - [[nodiscard]] constexpr double AsDouble() const - { - return std::bit_cast(v_); - } - - [[nodiscard]] constexpr int32_t AsInt() const - { - return static_cast(v_); - } - - // 核心辅助:泛型数字提取。算术指令可以直接用这个,免去手写 if 分支 - // 若不是 int/double 会导致非常恐怖的问题 - [[nodiscard]] constexpr double CastToDouble() const - { - return IsInt() ? static_cast(AsInt()) : AsDouble(); - } - - [[nodiscard]] constexpr bool AsBool() const - { - return v_ == (QNAN_MASK | TAG_TRUE); - } - - [[nodiscard]] struct Object *AsObject() const - { - return reinterpret_cast(v_ & ~(SIGN_BIT | QNAN_MASK)); - } - - // 重载 - - // 暴露原生值用于硬核位运算或 Hash 计算 - [[nodiscard]] constexpr uint64_t Raw() const - { - return v_; - } - - // 让 VM 的 OP_EQ 指令极简:`if (RA == RB)` - [[nodiscard]] constexpr bool operator==(const Value &other) const - { - // IEEE 754 规定浮点数有 +0.0 == -0.0 的特殊规则,所以不直接比对raw bits而是转换成 - // double进行C++比对 - if (IsDouble() && other.IsDouble()) - { - return AsDouble() == other.AsDouble(); - } - // 直接比较 64 位整数内存,所以堆对象比较为地址(运算符重载由Compiler处理) - return v_ == other.v_; - } - - [[nodiscard]] constexpr bool operator!=(const Value &other) const - { - return !(*this == other); - } - - // 类函数 - - [[nodiscard]] - String ToString() const; - }; - - /* - C风格继承 + 手动分发 - 禁止核心使用任何 virtual 达到最高效率 - */ - enum class ObjectType : uint8_t - { - String, - Function, - Struct, - Instance, - TypeObj, - }; - - struct StructObject /* : public Object */; // 结构体基类的定义,前向声明 - - enum class GCColor : std::uint8_t - { - White = 0, // 垃圾(或新对象)! - Gray = 1, // 已发现,子节点待扫描 - Black = 2, // 存活 - }; - - // Total 24 bytes size - struct Object - { - Object *next; // 8 bytes: gc链表 - StructObject *klass; // 8 bytes: 一切皆对象,父类指针 - ObjectType type; // 1 byte : 类型 - GCColor color = GCColor::White; // 1 byte : gc标记 - // + 6 bytes padding - - constexpr bool isString() const - { - return type == ObjectType::String; - } - - constexpr bool isFunction() const - { - return type == ObjectType::Function; - } - - constexpr bool isStruct() const - { - return type == ObjectType::Struct; - } - - constexpr bool isInstance() const - { - return type == ObjectType::Instance; - } - - constexpr bool isTypeObj() const - { - return type == ObjectType::TypeObj; - } - }; - - enum class TypeTag : uint8_t - { - Null, - Int, - Double, - String, - Bool, - Any, - Type, - Function, - Struct, - Interface, - }; - - struct TypeObject : Object - { - String name; - TypeTag tag; - - TypeObject(String _name, TypeTag _t) : name(std::move(_name)), tag(_t) - { - type = ObjectType::TypeObj; - klass = nullptr; // TypeObject 自身的 klass 指向 TypeTypeObject,初始化后设置 - } - }; -} // namespace Fig - -namespace std -{ - template <> - struct hash - { - std::size_t operator()(const Fig::Value &v) const noexcept - { - return std::hash()(v.Raw()); - } - }; -} // namespace std \ No newline at end of file diff --git a/src/Object/ObjectTest.cpp b/src/Object/ObjectTest.cpp deleted file mode 100644 index f98e7cd..0000000 --- a/src/Object/ObjectTest.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include -#include -#include -#include - -int main() -{ - using namespace Fig; - - Value null; - Value d = Value::FromDouble(-std::numbers::pi); - Value i = Value::FromInt(-2143242); - Value b = Value::FromBool(false); - - std::cout << null.ToString() << '\n'; - std::cout << d.ToString() << '\n'; - std::cout << i.ToString() << '\n'; - std::cout << b.ToString() << '\n'; -} \ No newline at end of file diff --git a/src/Object/StringObject.hpp b/src/Object/StringObject.hpp deleted file mode 100644 index b4d698a..0000000 --- a/src/Object/StringObject.hpp +++ /dev/null @@ -1,29 +0,0 @@ -/*! - @file src/Object/StringObject.hpp - @brief 字符串对象标识 - @author PuqiAR (im@puqiar.top) - @date 2026-02-19 -*/ - -#pragma once - -#include - -namespace Fig -{ - /* - // Total 24 bytes size - struct Object - { - Object *next; // 8 bytes: gc链表 - Struct *klass; // 8 bytes: 一切皆对象,父类指针 - ObjectType type; // 1 byte : 类型 - bool isMarked = false; // 1 byte : gc标记 - // + 6 bytes padding - }; - */ - struct StringObject final : public Object - { - String data; // 40 bytes - }; -}; \ No newline at end of file diff --git a/src/Object/StructObject.hpp b/src/Object/StructObject.hpp deleted file mode 100644 index f811219..0000000 --- a/src/Object/StructObject.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/*! - @file src/Object/StructObject.hpp - @brief 结构体类型 StructObject 定义 - @author PuqiAR (im@puqiar.top) - @date 2026-02-19 -*/ - -#pragma once - -#include -#include -#include - -namespace Fig -{ - /* - // Total 24 bytes size - struct Object - { - Object *next; // 8 bytes: gc链表 - Struct *klass; // 8 bytes: 一切皆对象,父类指针 - ObjectType type; // 1 byte : 类型 - bool isMarked = false; // 1 byte : gc标记 - // + 6 bytes padding - }; - */ - struct FieldMeta - { - String name; - Type type; - }; - - struct StructObject final : public Object - { - String name; - std::uint8_t fieldCount; - FieldMeta *fields; // [fieldCount] - Object *operators[GetOperatorsSize()]; - // operators: [UnaryOp 0..N][BinaryOp 0..N], nullptr = 无重载 - - Object *GetUnaryOperator(UnaryOperator _op) - { - return operators[static_cast(_op)]; - } - - Object *GetBinaryOperator(BinaryOperator _op) - { - return operators[static_cast(UnaryOperator::Count) - + static_cast(_op)]; - } - }; -}; // namespace Fig \ No newline at end of file diff --git a/src/Parser/ExprParser.cpp b/src/Parser/ExprParser.cpp deleted file mode 100644 index 6bad03b..0000000 --- a/src/Parser/ExprParser.cpp +++ /dev/null @@ -1,549 +0,0 @@ -/*! - @file src/Parser/ExprParser.hpp - @brief 语法分析器(Pratt + 手动递归下降) 表达式解析实现 (pratt) - @author PuqiAR (im@puqiar.top) - @date 2026-02-14 -*/ - -#include - -namespace Fig -{ - Result Parser::parseLiteralExpr() // 当前token为literal时调用 - { - StateProtector p(this, {State::ParsingLiteralExpr}); - - const Token &literal_token = consumeToken(); - LiteralExpr *node = - arena.Allocate(literal_token, makeSourceLocation(literal_token)); - return node; - } - Result Parser::parseIdentiExpr() // 当前token为Identifier调用 - { - StateProtector p(this, {State::ParsingIdentiExpr}); - - const Token &identifier = consumeToken(); - IdentiExpr *node = arena.Allocate( - srcManager.GetSub(identifier.index, identifier.length), makeSourceLocation(identifier)); - return node; - } - - Result Parser::parseInfixExpr(Expr *lhs) // 当前token为 op - { - StateProtector p(this, {State::ParsingInfixExpr}); - - const Token &op_token = consumeToken(); - BinaryOperator op = TokenToBinaryOp(op_token); - BindingPower rbp = GetBinaryOpRBp(op); - - const auto &rhs_result = parseExpression(rbp); - if (!rhs_result) - { - return std::unexpected(rhs_result.error()); - } - Expr *rhs = *rhs_result; - - InfixExpr *node = arena.Allocate(lhs, op, rhs); - return node; - } - - Result Parser::parsePrefixExpr() // 当前token为op - { - StateProtector p(this, {State::ParsingPrefixExpr}); - - const Token &op_token = consumeToken(); - UnaryOperator op = TokenToUnaryOp(op_token); - - BindingPower rbp = GetUnaryOpRBp(op); - const auto &rhs_result = parseExpression(rbp); - if (!rhs_result) - { - return std::unexpected(rhs_result.error()); - } - - Expr *rhs = *rhs_result; - PrefixExpr *node = arena.Allocate(op, rhs); - return node; - } - - Result - Parser::parseIndexExpr(Expr *base) // 由 parseExpression调用, 当前token为 `[` - { - StateProtector p(this, {State::ParsingIndexExpr}); - - const Token &lbracket_token = consumeToken(); // consume `[` - const auto &index_result = parseExpression(); - - if (!index_result) - { - return std::unexpected(index_result.error()); - } - - if (currentToken().type != TokenType::RightBracket) // `]` - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "unclosed brackets", - "insert `]`", - makeSourceLocation(lbracket_token))); - } - consumeToken(); // consume `]` - - IndexExpr *indexExpr = arena.Allocate(base, *index_result); - return indexExpr; - } - - Result - Parser::parseCallExpr(Expr *callee) // 由 parseExpression调用, 当前token为 `(` - { - StateProtector p(this, {State::ParsingCallExpr}); - - const Token &lparen_token = consumeToken(); // consume `(` - const SourceLocation &location = makeSourceLocation(lparen_token); - - FnCallArgs callArgs; - - // 空参数列表 - if (currentToken().type == TokenType::RightParen) - { - consumeToken(); // consume `)` - return arena.Allocate(callee, callArgs, location); - } - - while (true) - { - if (currentToken().type == TokenType::EndOfFile) - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "fn call has unclosed parenthese", - "insert `)`", - makeSourceLocation(lparen_token))); - } - - const auto &arg_result = parseExpression(); - if (!arg_result) - return std::unexpected(arg_result.error()); - - callArgs.args.push_back(*arg_result); - - if (currentToken().type == TokenType::RightParen) - { - consumeToken(); // consume `)` - break; - } - - if (currentToken().type != TokenType::Comma) - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "expected `,` or `)` in argument list", - "insert `,`", - makeSourceLocation(currentToken()))); - } - - consumeToken(); // consume `,` - } - - return arena.Allocate(callee, callArgs, location); - } - - Result Parser::parseNewExpr() - { - // new type{...} - StateProtector p(this, {State::ParsingNewExpr}); - - SourceLocation location = makeSourceLocation(consumeToken()); // consume `new` - - SET_STOP_AT(TokenType::LeftBrace); // { - auto type_result = parseTypeExpr(); - if (!type_result) - { - return std::unexpected(type_result.error()); - } - Expr *type = *type_result; - - if (!match(TokenType::LeftBrace)) - { - return std::unexpected(makeUnexpectTokenError("NewExpr", "lbrace {", currentToken())); - } - - const Token &lb_token = prevToken(); - - /* - Positional: - new Point{1, 2} - Named: - new Point{x = 1, y = 2} - Shorthand: - new Point{y, x} - */ - - DynArray args; - - while (true) - { - if (isEOF) - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "unclosed `{` in new expr", - "insert '}'", - makeSourceLocation(lb_token) - )); - } - if (args.empty() && match(TokenType::RightBrace)) // 空参 - { - break; - } - - // named arg - if (currentToken().isIdentifier() && peekToken().type == TokenType::Colon) - { - const Token &name_token = consumeToken(); - const String &name = srcManager.GetSub(name_token.index, name_token.length); - consumeToken(); // consume `:` - - SET_STOP_AT(TokenType::Comma, TokenType::RightBrace); // , / } - auto result = parseExpression(); - if (!result) - { - return result; - } - - args.push_back(NewExpr::Arg{ - name, - *result - }); - } - // shorthand - else if (currentToken().isIdentifier() - && (peekToken().type == TokenType::Comma || peekToken().type == TokenType::RightBrace)) - { - const Token &name_token = consumeToken(); - const String &name = srcManager.GetSub(name_token.index, name_token.length); - - - - IdentiExpr *ident = - arena.Allocate(name, makeSourceLocation(name_token)); - args.push_back(NewExpr::Arg{name, ident}); - } - else - { - SET_STOP_AT(TokenType::Comma, TokenType::RightBrace); // , / } - auto result = parseExpression(); - if (!result) - { - return result; - } - - args.push_back(NewExpr::Arg{ - .value = *result - }); - } - - - if (match(TokenType::Comma)) - { - continue; - } - - if (match(TokenType::RightBrace)) - { - break; - } - } - - NewExpr *newExpr = arena.Allocate(type, args, location); - return newExpr; - } - - Result Parser::parseLambdaExpr() - { - StateProtector p(this, {State::ParsingLambdaExpr}); - - SourceLocation location = makeSourceLocation(consumeToken()); // consume `func` - - if (currentToken().isIdentifier()) - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "lambda expression should not have a name", - "remove the name", - makeSourceLocation(currentToken()))); - } - - if (currentToken().type != TokenType::LeftParen) - { - return std::unexpected( - makeUnexpectTokenError("fn def stmt", "lparen '('", currentToken())); - } - - DynArray params; - - auto paraResult = parseFnParams(); - if (!paraResult) - { - return std::unexpected(paraResult.error()); - } - params = *paraResult; - - Expr *returnType = nullptr; - Token rightArrowToken; - if (match(TokenType::RightArrow)) // -> - { - rightArrowToken = consumeToken(); - - auto result = parseTypeExpr(); - if (!result) - { - return std::unexpected(result.error()); - } - returnType = *result; - } - - if (match(TokenType::DoubleArrow)) // => - { - if (returnType) - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "use of expr body but specified return type in lambda expr", - "remove `-> ...`", - makeSourceLocation(rightArrowToken))); - } - auto result = parseExpression(); - if (!result) - { - return result; - } - - Expr *expr = *result; - LambdaExpr *lambda = - arena.Allocate(params, returnType, expr, true, location); - return lambda; - } - else if (currentToken().type == TokenType::LeftBrace) - { - auto result = parseBlockStmt(); - if (!result) - { - return std::unexpected(result.error()); - } - - LambdaExpr *lambda = - arena.Allocate(params, returnType, *result, false, location); - return lambda; - } - else - { - return std::unexpected( - makeUnexpectTokenError("LambdaExpr", "darrow => / lbrace {", currentToken())); - } - } - - Result Parser::parseExpression(BindingPower rbp) - { - Expr *lhs = nullptr; - Token token = currentToken(); - - // NUD - if (token.isIdentifier()) - { - const auto &lhs_result = parseIdentiExpr(); - if (!lhs_result) - { - return std::unexpected(lhs_result.error()); - } - lhs = *lhs_result; - } - else if (token.isLiteral()) - { - const auto &lhs_result = parseLiteralExpr(); - if (!lhs_result) - { - return std::unexpected(lhs_result.error()); - } - lhs = *lhs_result; - } - else if (IsTokenOp(token.type, false)) // 是否是一元前缀运算符 - { - const auto &lhs_result = parsePrefixExpr(); - if (!lhs_result) - { - return std::unexpected(lhs_result.error()); - } - lhs = *lhs_result; - } - else if (token.type == TokenType::LeftParen) - { - const Token &lparen_token = consumeToken(); // consume `(` - const auto &expr_result = parseExpression(0); - if (!expr_result) - { - return expr_result; - } - const Token &rparen_token = consumeToken(); // consume `)` - if (rparen_token.type != TokenType::RightParen) - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "unclosed parenthese", - "insert `)`", - makeSourceLocation(lparen_token))); - } - lhs = *expr_result; - } - else if (token.type == TokenType::Function) - { - auto result = parseLambdaExpr(); - if (!result) - { - return result; - } - - lhs = *result; - } - else if (token.type == TokenType::New) - { - auto result = parseNewExpr(); - if (!result) - { - return result; - } - - lhs = *result; - } - - if (!lhs) - { - return std::unexpected(Error( - ErrorType::ExpectedExpression, - "expected expression", - "insert expressions", - makeSourceLocation(prevToken()))); - } - - // LED - while (true) - { - token = currentToken(); - if (shouldTerminate()) - { - break; - } - - // is / as - if (token.type == TokenType::Is || token.type == TokenType::As) - { - BinaryOperator op = TokenToBinaryOp(token); - BindingPower lbp = GetBinaryOpLBp(op); - if (rbp >= lbp) - { - break; - } - consumeToken(); // consume `is` or `as` - auto typeRes = parseTypeExpr(); - if (!typeRes) - { - return std::unexpected(typeRes.error()); - } - lhs = arena.Allocate(lhs, op, *typeRes); - } - // binary - else if (IsTokenOp(token.type /* isBinary = true */)) - { - BinaryOperator op = TokenToBinaryOp(token); - BindingPower lbp = GetBinaryOpLBp(op); - if (rbp >= lbp) - { - break; - } - - auto result = parseInfixExpr(lhs); - if (!result) - { - return result; - } - lhs = *result; - } - // [index] - else if (token.type == TokenType::LeftBracket) - { - const auto &expr_result = parseIndexExpr(lhs); - if (!expr_result) - { - return expr_result; - } - lhs = *expr_result; - } - // call - else if (token.type == TokenType::LeftParen) - { - const auto &expr_result = parseCallExpr(lhs); - if (!expr_result) - { - return expr_result; - } - lhs = *expr_result; - } - // .member - else if (token.type == TokenType::Dot) - { - consumeToken(); // consume `.` - if (!currentToken().isIdentifier()) - { - return std::unexpected( - makeUnexpectTokenError("MemberExpr", "identifier after `.`", currentToken())); - } - const Token &nameToken = consumeToken(); - const String &name = - srcManager.GetSub(nameToken.index, nameToken.length); - SourceLocation loc = makeSourceLocation(nameToken); - lhs = arena.Allocate(lhs, name, loc); - } - // x++ x-- - else if (token.type == TokenType::DoublePlus || token.type == TokenType::DoubleMinus) - { - UnaryOperator op = TokenToUnaryOp(consumeToken()); - lhs = arena.Allocate(op, lhs); - } - // ?: - else if (token.type == TokenType::Question) - { - // ?: 最低优先 - // 赋值 rbp = 101,所以只有当 rbp < 100 时才可能进到三元 - // 实际上三元是最低优先级的非赋值运算符,我们给一个很小的 lbp - constexpr BindingPower TERNARY_LBP = 150; - if (rbp >= TERNARY_LBP) - { - break; - } - consumeToken(); // consume `?` - auto thenRes = parseExpression(0); // 重置绑定力,右结合 - if (!thenRes) - { - return std::unexpected(thenRes.error()); - } - if (!match(TokenType::Colon)) - { - return std::unexpected( - makeUnexpectTokenError("TernaryExpr", "`:` for else branch", currentToken())); - } - auto elseRes = parseExpression(TERNARY_LBP - 1); // 右结合 - if (!elseRes) - { - return std::unexpected(elseRes.error()); - } - lhs = arena.Allocate(lhs, *thenRes, *elseRes, lhs->location); - } - else - { - return lhs; - } - } - return lhs; - } - -}; // namespace Fig diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp deleted file mode 100644 index f30c730..0000000 --- a/src/Parser/Parser.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/*! - @file src/Parser/Parser.cpp - @brief 语法分析器实现 - @author PuqiAR (im@puqiar.top) - @date 2026-03-08 -*/ - -#include - -namespace Fig -{ - Result Parser::Parse() - { - Program *program = arena.Allocate(); - - while (currentToken().type != TokenType::EndOfFile) - { - if (lexerError) - { - return std::unexpected(*lexerError); - } - auto result = parseStatement(); - if (!result) - { - return std::unexpected(result.error()); - } - - Stmt *stmt = *result; - if (stmt) - { - program->nodes.push_back(stmt); - } - } - - return program; - } -}; // namespace Fig diff --git a/src/Parser/Parser.hpp b/src/Parser/Parser.hpp deleted file mode 100644 index fabc521..0000000 --- a/src/Parser/Parser.hpp +++ /dev/null @@ -1,305 +0,0 @@ -/*! - @file src/Parser/Parser.hpp - @brief 语法分析器(Pratt + 手动递归下降) 定义 - @author PuqiAR (im@puqiar.top) - @date 2026-03-08 -*/ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace Fig -{ - class Parser - { - private: - Arena arena; - Lexer &lexer; - SourceManager &srcManager; - - size_t index = 0; // 当前 Token 在 buffer 中的下标 - DynArray buffer; // 已从 Lexer 读取的 Token 缓存 - - String fileName; - bool isEOF = false; - - Diagnostics &diagnostics; - std::optional lexerError; // 词法错误缓存,避免 exit/abort - - // 惰性获取下一个 Token,跳过注释 - Token nextToken() - { - if (index + 1 < buffer.size()) - return buffer[++index]; - if (isEOF) - return buffer[index]; - - while (true) - { - auto result = lexer.NextToken(); - if (!result) - { - lexerError = result.error(); - isEOF = true; - Token eof = {0, 0, TokenType::EndOfFile}; - buffer.push_back(eof); - index = buffer.size() - 1; - return buffer[index]; - } - const Token &token = result.value(); - if (token.type == TokenType::Comments) - continue; // 惰性跳过注释 - - if (token.type == TokenType::EndOfFile) - isEOF = true; - buffer.push_back(token); - index = buffer.size() - 1; - return buffer[index]; - } - } - - inline Token prevToken() - { - return (index > 0) ? buffer[index - 1] : buffer[0]; - } - inline Token currentToken() - { - if (buffer.empty()) - return nextToken(); - return buffer[index]; - } - - // 惰性窥视后续 Token - Token peekToken(size_t lookahead = 1) - { - size_t targetIndex = index + lookahead; - while (targetIndex >= buffer.size() && !isEOF) - { - auto result = lexer.NextToken(); - if (!result) - { - lexerError = result.error(); - isEOF = true; - Token eof = {0, 0, TokenType::EndOfFile}; - buffer.push_back(eof); - index = buffer.size() - 1; - return buffer.back(); - } - if (result->type == TokenType::Comments) - continue; - if (result->type == TokenType::EndOfFile) - isEOF = true; - buffer.push_back(*result); - } - return (targetIndex >= buffer.size()) ? buffer.back() : buffer[targetIndex]; - } - - inline Token consumeToken() - { - Token current = currentToken(); - if (current.type != TokenType::EndOfFile) - nextToken(); - return current; - } - inline bool match(TokenType type) - { - if (currentToken().type == type) - { - consumeToken(); - return true; - } - return false; - } - - public: - struct State - { - enum StateType : std::uint8_t - { - Standby, - - ParsingLiteralExpr, - ParsingIdentiExpr, - ParsingInfixExpr, - ParsingPrefixExpr, - ParsingIndexExpr, - ParsingCallExpr, - ParsingLambdaExpr, - ParsingNewExpr, - - ParsingVarDecl, - ParsingIf, - ParsingWhile, - ParsingFnDefStmt, - ParsingReturn, - ParsingBreak, - ParsingContinue, - ParsingStructDef, - - ParsingTypeParameters, - ParsingNamedTypeExpr, - ParsingFnTypeExpr, - } type = StateType::Standby; - std::unordered_set stopAt = {}; - }; - - private: - const std::unordered_set &getBaseTerminators() - { - static const std::unordered_set baseTerminators{ - TokenType::Semicolon, - TokenType::RightParen, - TokenType::RightBracket, - TokenType::RightBrace, - TokenType::Comma, - TokenType::EndOfFile}; - return baseTerminators; - } - - bool shouldTerminate() - { - const Token &token = currentToken(); - if (getBaseTerminators().contains(token.type)) - return true; - for (auto it = stateStack.rbegin(); it < stateStack.rend(); ++it) - { - if (it->stopAt.contains(token.type)) - return true; - } - return false; - } - - DynArray stateStack; - State ¤tState() - { - return stateStack.back(); - } - void pushState(State _state) - { - stateStack.push_back(std::move(_state)); - } - void popState() - { - if (!stateStack.empty()) - stateStack.pop_back(); - } - - struct StateProtector - { - Parser *p; - StateProtector(Parser *_p, State _s) : p(_p) - { - p->pushState(_s); - } - ~StateProtector() - { - p->popState(); - } - }; - - SourceLocation makeSourceLocation(const Token &tok) - { - auto [line, column] = srcManager.GetLineColumn(tok.index); - // 防止因解析错位导致的异常列号引起终端 OOM - if (column > 5000) - column = 1; - return SourceLocation( - SourcePosition(line, column, tok.length), - fileName, - "[internal parser]", - magic_enum::enum_name(currentState().type).data()); - } - - inline Error makeUnexpectTokenError( - const String &stmt, - const String &exp, - const Token &got, - std::source_location th_loc = std::source_location::current()) - { - return Error( - ErrorType::SyntaxError, - std::format( - "expect '{}' in {}, got `{}`", exp, stmt, magic_enum::enum_name(got.type)), - "none", - makeSourceLocation(got), - th_loc); - } - - inline Error - makeExpectSemicolonError(std::source_location th_loc = std::source_location::current()) - { - return Error( - ErrorType::SyntaxError, - "expect ';' after statement", - "insert ';'", - makeSourceLocation(currentToken()), - th_loc); - } - - inline Error makeExpectSemicolonError( - const Token &token, std::source_location th_loc = std::source_location::current()) - { - return Error( - ErrorType::SyntaxError, - "expect ';' after statement", - "insert ';'", - makeSourceLocation(token), - th_loc); - } - - Result parseTypeParameters(); - - Result parseTypeExpr(); - Result parseNamedTypeExpr(); - Result parseFnTypeExpr(); - - Result parseExpression(BindingPower = 0); - Result parseLiteralExpr(); - Result parseIdentiExpr(); - Result parsePrefixExpr(); - Result parseInfixExpr(Expr *); - Result parseIndexExpr(Expr *); - Result parseCallExpr(Expr *); - Result parseNewExpr(); - Result parseLambdaExpr(); - - Result parseBlockStmt(); - Result parseVarDecl(bool); - Result parseConstDecl(bool); - Result parseIfStmt(); - Result parseWhileStmt(); - Result, Error> parseFnParams(); - Result parseFnDefStmt(bool); - Result parseReturnStmt(); - - Result parseStructDef(bool); - Result parseInterfaceDef(bool); - Result parseImpl(); - Result parseForStmt(); - Result parseImportStmt(); - - Result parseStatement(); - - public: - Parser(Lexer &_lexer, SourceManager &_src, String _file, Diagnostics &_diagnostics) : - lexer(_lexer), srcManager(_src), fileName(std::move(_file)), diagnostics(_diagnostics) - { - pushState(State()); - } - - Result Parse(); - }; - -#define SET_STOP_AT(...) currentState().stopAt = {__VA_ARGS__}; -} // namespace Fig diff --git a/src/Parser/ParserTest.cpp b/src/Parser/ParserTest.cpp deleted file mode 100644 index 7e9845c..0000000 --- a/src/Parser/ParserTest.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include - -int main() -{ - using namespace Fig; - - String fileName = "[memory]"; - String filePath = - "System" + fileName; - - SourceManager srcManager(filePath); - - String source = R"( - var a = 10; - var a: Int; - var a := 200 * 30 + 2; - )"; - - Lexer lexer(source, fileName); - - Diagnostics diagnostics; - Parser parser(lexer, srcManager, fileName, diagnostics); - - auto result = parser.Parse(); - if (!result) - { - ReportError(result.error(), srcManager); - return 1; - } - - diagnostics.EmitAll(srcManager); - - Program *program = *result; - std::cout << "Parsed " << program->nodes.size() << " statements\n"; - for (size_t i = 0; i < program->nodes.size(); ++i) - { - std::cout << '[' << i << "] " << program->nodes[i]->toString() << '\n'; - } - - return 0; -} diff --git a/src/Parser/StmtParser.cpp b/src/Parser/StmtParser.cpp deleted file mode 100644 index a774126..0000000 --- a/src/Parser/StmtParser.cpp +++ /dev/null @@ -1,1239 +0,0 @@ -/*! - @file src/Parser/StmtParser.cpp - @brief 语法分析器(Pratt + 手动递归下降) 语句解析实现 - @author PuqiAR (im@puqiar.top) - @date 2026-02-19 -*/ - -#include - -namespace Fig -{ - Result Parser::parseBlockStmt() - { - SourceLocation location = makeSourceLocation(consumeToken()); - BlockStmt *stmt = arena.Allocate(); - while (true) - { - if (isEOF) - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "unclosed braces in block stmt", - "insert '}'", - location)); - } - if (match(TokenType::RightBrace)) - { - break; - } - auto result = parseStatement(); - if (!result) - { - return std::unexpected(result.error()); - } - stmt->nodes.push_back(*result); - } - return stmt; - } - - Result Parser::parseVarDecl(bool isPublic) - { - StateProtector p(this, {State::ParsingVarDecl}); - - SourceLocation location = makeSourceLocation(consumeToken()); - - if (currentToken().type != TokenType::Identifier) - { - return std::unexpected(makeUnexpectTokenError("VarDecl", "var name", currentToken())); - } - const String &name = srcManager.GetSub(currentToken().index, currentToken().length); - consumeToken(); - - Expr *typeSpeicifer = nullptr; - if (match(TokenType::Colon)) - { - auto result = parseTypeExpr(); - if (!result) - { - return std::unexpected(result.error()); - } - typeSpeicifer = *result; - } - - Expr *initExpr = nullptr; - bool isInfer = false; - if (match(TokenType::Assign)) - { - auto result = parseExpression(); - if (!result) - { - return std::unexpected(result.error()); - } - initExpr = *result; - } - else if (match(TokenType::Walrus)) - { - if (typeSpeicifer) - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "used type infer but specifying the type", - "change `:=` to '='", - makeSourceLocation(prevToken()))); - } - auto result = parseExpression(); - if (!result) - { - return std::unexpected(result.error()); - } - initExpr = *result; - isInfer = true; - } - if (!match(TokenType::Semicolon)) - { - return std::unexpected(makeExpectSemicolonError()); - } - VarDecl *varDecl = - arena.Allocate(isPublic, name, typeSpeicifer, isInfer, initExpr, location); - return varDecl; - } - - Result Parser::parseConstDecl(bool isPublic) - { - // must init - StateProtector p(this, {State::ParsingVarDecl}); - - SourceLocation location = makeSourceLocation(consumeToken()); // consume `const` - - if (currentToken().type != TokenType::Identifier) - { - return std::unexpected(makeUnexpectTokenError("ConstDecl", "const name", currentToken())); - } - const String &name = srcManager.GetSub(currentToken().index, currentToken().length); - consumeToken(); - - Expr *typeSpecifier = nullptr; - if (match(TokenType::Colon)) - { - auto result = parseTypeExpr(); - if (!result) - { - return std::unexpected(result.error()); - } - typeSpecifier = *result; - } - - Expr *initExpr = nullptr; - bool isInfer = false; - if (match(TokenType::Assign)) - { - auto result = parseExpression(); - if (!result) - { - return std::unexpected(result.error()); - } - initExpr = *result; - } - else if (match(TokenType::Walrus)) - { - if (typeSpecifier) - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "used type infer but specifying the type", - "change `:=` to '='", - makeSourceLocation(prevToken()))); - } - auto result = parseExpression(); - if (!result) - { - return std::unexpected(result.error()); - } - initExpr = *result; - isInfer = true; - } - else - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "const must be initialized", - "add '=' and an initializer expression", - makeSourceLocation(prevToken()))); - } - - if (!match(TokenType::Semicolon)) - { - return std::unexpected(makeExpectSemicolonError()); - } - - VarDecl *varDecl = - arena.Allocate(isPublic, name, typeSpecifier, isInfer, initExpr, location); - return varDecl; - } - - Result Parser::parseIfStmt() - { - StateProtector p(this, {State::ParsingIf}); - - SourceLocation location = makeSourceLocation(consumeToken()); - - Expr *cond = nullptr; - if (match(TokenType::LeftParen)) - { - const Token &lpToken = prevToken(); - SET_STOP_AT(TokenType::RightParen, TokenType::LeftBrace); - const auto &result = parseExpression(0); - if (!result) - { - return std::unexpected(result.error()); - } - if (!match(TokenType::RightParen)) - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "unclosed parenthese in if condition", - "insert `)`", - makeSourceLocation(lpToken))); - } - cond = *result; - } - else - { - SET_STOP_AT(TokenType::LeftBrace); - auto result = parseExpression(0); - if (!result) - { - return std::unexpected(result.error()); - } - cond = *result; - } - - if (currentToken().type != TokenType::LeftBrace) - { - return std::unexpected( - makeUnexpectTokenError("IfStmt", "LeftBrace `{`", currentToken())); - } - auto result = parseBlockStmt(); - if (!result) - { - return std::unexpected(result.error()); - } - BlockStmt *consequent = *result; - - DynArray elifs; - BlockStmt *alternate = nullptr; - - while (match(TokenType::Else)) - { - SourceLocation elseLocation = makeSourceLocation(prevToken()); - if (match(TokenType::If)) - { - if (alternate) - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "else if after else", - "remove else if", - elseLocation)); - } - - Expr *cond = nullptr; - - if (match(TokenType::LeftParen)) - { - const Token &lpToken = prevToken(); - - SET_STOP_AT(TokenType::RightParen, TokenType::LeftBrace); - const auto &result = parseExpression(0); - if (!result) - { - return std::unexpected(result.error()); - } - if (!match(TokenType::RightParen)) - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "unclosed parenthese in if condition", - "insert `)`", - makeSourceLocation(lpToken))); - } - cond = *result; - } - else - { - SET_STOP_AT(TokenType::LeftBrace); - auto result = parseExpression(0); - if (!result) - { - return std::unexpected(result.error()); - } - cond = *result; - } - if (currentToken().type != TokenType::LeftBrace) - { - return std::unexpected( - makeUnexpectTokenError("ElseIfStmt", "LeftBrace `{`", currentToken())); - } - auto result = parseBlockStmt(); - if (!result) - { - return std::unexpected(result.error()); - } - BlockStmt *consequent = *result; - ElseIfStmt *elif = arena.Allocate(cond, consequent, elseLocation); - elifs.push_back(elif); - } - else - { - if (alternate) - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "duplicate else in if stmt", - "remove it", - elseLocation)); - } - if (currentToken().type != TokenType::LeftBrace) - { - return std::unexpected( - makeUnexpectTokenError("ElseStmt", "LeftBrace `{`", currentToken())); - } - auto result = parseBlockStmt(); - if (!result) - { - return std::unexpected(result.error()); - } - alternate = *result; - } - } - IfStmt *ifStmt = arena.Allocate(cond, consequent, elifs, alternate, location); - return ifStmt; - } - - Result Parser::parseWhileStmt() - { - StateProtector p(this, {State::ParsingWhile}); - - SourceLocation location = makeSourceLocation(consumeToken()); - - Expr *cond = nullptr; - if (match(TokenType::LeftParen)) - { - const Token &lpToken = prevToken(); - SET_STOP_AT(TokenType::RightParen, TokenType::LeftBrace); - - auto result = parseExpression(); - if (!result) - { - return std::unexpected(result.error()); - } - - if (!match(TokenType::RightParen)) - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "unclosed parenthese in while condition", - "insert ')'", - makeSourceLocation(lpToken))); - } - cond = *result; - } - else - { - SET_STOP_AT(TokenType::LeftBrace); - auto result = parseExpression(); - if (!result) - { - return std::unexpected(result.error()); - } - cond = *result; - } - - if (currentToken().type != TokenType::LeftBrace) - { - return std::unexpected( - makeUnexpectTokenError("while stmt", "left brace '{'", currentToken())); - } - - auto result = parseBlockStmt(); - if (!result) - { - return std::unexpected(result.error()); - } - BlockStmt *body = *result; - - WhileStmt *whileStmt = arena.Allocate(cond, body, location); - return whileStmt; - } - - Result Parser::parseForStmt() - { - SourceLocation location = makeSourceLocation(consumeToken()); // consume `for` - - // 括号可选 - bool hasParen = match(TokenType::LeftParen); - - // init: var decl 或 表达式语句(或空) - Stmt *init = nullptr; - if (currentToken().type == TokenType::Variable) - { - auto result = parseVarDecl(false); - if (!result) - return std::unexpected(result.error()); - init = *result; - } - else if (currentToken().type == TokenType::Semicolon) - { - // 空 init,跳过 - } - else if (!isEOF) - { - // 表达式作为 init - auto result = parseExpression(); - if (!result) - return std::unexpected(result.error()); - init = arena.Allocate(*result); - if (!match(TokenType::Semicolon)) - return std::unexpected(makeExpectSemicolonError()); - } - - // 要求分号分隔 - if (!init && currentToken().type != TokenType::Semicolon) - { - // 如果不是 var decl 且下一个不是分号,尝试作为表达式解析并消耗分号 - // 实际上 init 为 nullptr 的情况就是空 init,此时应该已经有分号了 - } - if (init) - { - - } - else - { - if (!match(TokenType::Semicolon)) - { - return std::unexpected(makeExpectSemicolonError()); - } - } - - // cond: 表达式(或空) - Expr *cond = nullptr; - SET_STOP_AT(TokenType::Semicolon); - if (currentToken().type != TokenType::Semicolon) - { - auto result = parseExpression(); - if (!result) - return std::unexpected(result.error()); - cond = *result; - } - // 确保下一个是分号 - if (currentToken().type == TokenType::Semicolon) - { - // continue - } - if (!match(TokenType::Semicolon)) - { - return std::unexpected(makeExpectSemicolonError()); - } - - // step: 表达式(或空) - Expr *step = nullptr; - if (hasParen) - { - SET_STOP_AT(TokenType::RightParen); - } - else - { - SET_STOP_AT(TokenType::LeftBrace); - } - if (hasParen && currentToken().type == TokenType::RightParen) - { - // 空 step - } - else if (!hasParen && currentToken().type == TokenType::LeftBrace) - { - // 空 step,直接进入 body - } - else if (!isEOF) - { - auto result = parseExpression(); - if (!result) - return std::unexpected(result.error()); - step = *result; - } - - if (hasParen && !match(TokenType::RightParen)) - { - return std::unexpected( - makeUnexpectTokenError("for stmt", "`)` to close", currentToken())); - } - - if (currentToken().type != TokenType::LeftBrace) - { - return std::unexpected( - makeUnexpectTokenError("for stmt", "left brace `{`", currentToken())); - } - - auto bodyRes = parseBlockStmt(); - if (!bodyRes) - { - return std::unexpected(bodyRes.error()); - } - - ForStmt *forStmt = arena.Allocate(init, cond, step, *bodyRes, location); - return forStmt; - } - - Result, Error> Parser::parseFnParams() - { - const Token &lpToken = consumeToken(); - DynArray params; - - while (true) - { - if (isEOF) - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "unclosed parenthese in function parameters", - "insert ')'", - makeSourceLocation(lpToken))); - } - if (match(TokenType::RightParen)) - { - break; - } - - const Token &nToken = consumeToken(); - SourceLocation location = makeSourceLocation(nToken); - const String &name = srcManager.GetSub(nToken.index, nToken.length); - - Expr *type = nullptr; - if (match(TokenType::Colon)) - { - auto result = parseTypeExpr(); - if (!result) - { - return std::unexpected(result.error()); - } - type = *result; - } - - Expr *defaultValue = nullptr; - - if (match(TokenType::Assign)) - { - SET_STOP_AT(TokenType::Comma, TokenType::RightParen, TokenType::LeftBrace); - auto result = parseExpression(); - if (!result) - { - return std::unexpected(result.error()); - } - defaultValue = *result; - } - - PosParam *posParam = arena.Allocate(name, type, defaultValue, location); - params.push_back(posParam); - - // 可变参数: ... (跟在最后一个参数后面) - if (match(TokenType::TripleDot)) - { - // 标记最后一个参数为可变参数 - // 通过 VarParam 标记 - // 当前用 VarParam 包装最后一个 param - // 简单方案:创建一个带 variadic 标记的 param - // TODO: 改用专门的 VarParam AST 节点 - // 暂时用 flag 标记在 posParam 上 - - if (!match(TokenType::RightParen)) - { - return std::unexpected( - makeUnexpectTokenError("fn params", "`)` after `...`", currentToken())); - } - // 直接返回,可变参数后面不能再有参数 - break; - } - - if (match(TokenType::Comma)) - { - if (match(TokenType::RightParen)) - { - // 尾部逗号允许,如 func(a, b,) - break; - } - if (!currentToken().isIdentifier()) - { - return std::unexpected( - makeUnexpectTokenError("fn params", "param name", currentToken())); - } - } - } - return params; - } - - Result Parser::parseFnDefStmt(bool isPublic) - { - StateProtector p(this, {State::ParsingFnDefStmt}); - SourceLocation location = makeSourceLocation(consumeToken()); - - if (!currentToken().isIdentifier()) - { - return std::unexpected( - makeUnexpectTokenError("fn def stmt", "function name", currentToken())); - } - const Token &nameToken = consumeToken(); - const String &name = srcManager.GetSub(nameToken.index, nameToken.length); - - if (currentToken().type != TokenType::LeftParen) - { - return std::unexpected( - makeUnexpectTokenError("fn def stmt", "lparen '('", currentToken())); - } - - DynArray params; - - auto paraResult = parseFnParams(); - if (!paraResult) - { - return std::unexpected(paraResult.error()); - } - params = *paraResult; - - Expr *returnType = nullptr; - if (match(TokenType::RightArrow)) - { - auto result = parseTypeExpr(); - if (!result) - { - return std::unexpected(result.error()); - } - returnType = *result; - } - - BlockStmt *body = nullptr; - if (match(TokenType::DoubleArrow)) // => - { - auto result = parseExpression(); - if (!result) - { - return std::unexpected(result.error()); - } - - if (match(TokenType::Semicolon)) - { - diagnostics.Report(Error( - ErrorType::UnnecessarySemicolon, - "`;` is unnecessary in this context", - "try remove `;`", - makeSourceLocation(prevToken()))); - } - - Expr *expr = *result; - ReturnStmt *returnStmt = arena.Allocate(expr, expr->location); - - body = arena.Allocate(); - body->nodes.push_back(returnStmt); - } - else if (currentToken().type == TokenType::LeftBrace) - { - auto bodyResult = parseBlockStmt(); - if (!bodyResult) - { - return std::unexpected(bodyResult.error()); - } - body = *bodyResult; - } - else - { - return std::unexpected( - makeUnexpectTokenError("fn def stmt", "function body '=>' / '{'", currentToken())); - } - - FnDefStmt *fnDef = - arena.Allocate(isPublic, name, params, returnType, body, location); - return fnDef; - } - - Result Parser::parseReturnStmt() - { - StateProtector p(this, {State::ParsingReturn}); - - SourceLocation location = makeSourceLocation(consumeToken()); - auto result = parseExpression(); - if (!result) - { - return std::unexpected(result.error()); - } - - Expr *value = *result; - ReturnStmt *returnStmt = arena.Allocate(value, location); - - if (!match(TokenType::Semicolon)) - { - return std::unexpected(makeExpectSemicolonError()); - } - return returnStmt; - } - - Result Parser::parseStructDef(bool isPublic) - { - StateProtector p(this, {State::ParsingStructDef}); - - SourceLocation location = makeSourceLocation(consumeToken()); // consume `struct` - if (!currentToken().isIdentifier()) - { - return std::unexpected( - makeUnexpectTokenError("StructDef", "struct name", currentToken())); - } - - const Token &name_tok = consumeToken(); // consume name - const String &name = srcManager.GetSub(name_tok.index, name_tok.length); - - StructDefStmt *stDef = arena.Allocate(); - - if (currentToken().type == TokenType::Less) // < - { - auto result = parseTypeParameters(); - if (!result) - { - return std::unexpected(result.error()); - } - - stDef->typeParameters = *result; - } - - if (!match(TokenType::LeftBrace)) - { - return std::unexpected( - makeUnexpectTokenError("StructDef", "lbrace '{'", currentToken())); - } - - const Token &lb_tok = prevToken(); // `{` - - while (true) - { - if (isEOF) - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "unclosed braces in struct def", - "insert '}'", - makeSourceLocation(lb_tok))); - } - if (match(TokenType::RightBrace)) - { - break; - } - - // (public) field_name (: Type) (= expr) / (:= expr) - - bool isPublicField = match(TokenType::Public); - if (currentToken().isIdentifier()) - { - const Token &name_tok = consumeToken(); - const String &field_name = srcManager.GetSub(name_tok.index, name_tok.length); - - if (match(TokenType::Walrus)) // := - { - auto result = parseExpression(); - if (!result) - { - return std::unexpected(result.error()); - } - - stDef->fields.push_back( - StructDefStmt::Field{isPublicField, true, field_name, nullptr, *result}); - } - else - { - Expr *type = nullptr; - Expr *initExpr = nullptr; - - if (match(TokenType::Colon)) // : - { - auto result = parseTypeExpr(); - if (!result) - { - return std::unexpected(result.error()); - } - type = *result; - } - - if (match(TokenType::Assign)) - { - auto result = parseExpression(); - if (!result) - { - return std::unexpected(result.error()); - } - initExpr = *result; - } - stDef->fields.push_back( - StructDefStmt::Field{isPublicField, false, field_name, type, initExpr}); - } - if (!match(TokenType::Semicolon)) - { - return std::unexpected(makeExpectSemicolonError()); - } - } - else if (currentToken().type == TokenType::Function) - { - auto result = parseFnDefStmt(isPublicField); - if (!result) - { - return result; - } - - stDef->methods.push_back(*result); - } - else - { - return std::unexpected( - makeUnexpectTokenError("StructDef", "field or method", currentToken())); - } - } - - return stDef; - } - - Result Parser::parseInterfaceDef(bool isPublic) - { - SourceLocation location = makeSourceLocation(consumeToken()); // consume `interface` - - if (!currentToken().isIdentifier()) - { - return std::unexpected( - makeUnexpectTokenError("InterfaceDef", "interface name", currentToken())); - } - - const Token &nameToken = consumeToken(); - const String &name = srcManager.GetSub(nameToken.index, nameToken.length); - - if (!match(TokenType::LeftBrace)) - { - return std::unexpected( - makeUnexpectTokenError("InterfaceDef", "lbrace '{'", currentToken())); - } - - const Token &lbToken = prevToken(); - - InterfaceDefStmt *ifaceDef = arena.Allocate(); - ifaceDef->isPublic = isPublic; - ifaceDef->name = name; - ifaceDef->location = location; - - while (true) - { - if (isEOF) - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "unclosed braces in interface def", - "insert '}'", - makeSourceLocation(lbToken))); - } - if (match(TokenType::RightBrace)) - { - break; - } - - // interface 方法需要 `func` 关键字 - if (currentToken().type != TokenType::Function) - { - return std::unexpected( - makeUnexpectTokenError("InterfaceDef", "`func` for method", currentToken())); - } - consumeToken(); // consume `func` - - if (!currentToken().isIdentifier()) - { - return std::unexpected( - makeUnexpectTokenError("InterfaceDef", "method name", currentToken())); - } - - const Token &methodNameToken = consumeToken(); - const String &methodName = - srcManager.GetSub(methodNameToken.index, methodNameToken.length); - - // 参数列表 - if (!match(TokenType::LeftParen)) - { - return std::unexpected( - makeUnexpectTokenError("InterfaceDef", "`(` for method params", currentToken())); - } - - // 解析参数类型(接口方法只声明类型,无参数名) - DynArray methods; // placeholder - DynArray paramTypes; - - while (true) - { - if (isEOF) - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "unclosed parenthese in interface method", - "insert ')'", - makeSourceLocation(methodNameToken))); - } - if (match(TokenType::RightParen)) - { - break; - } - - // 参数: name : Type - if (!currentToken().isIdentifier()) - { - return std::unexpected( - makeUnexpectTokenError("InterfaceDef", "param name", currentToken())); - } - consumeToken(); // consume param name (unused in interface) - - Expr *paramType = nullptr; - if (match(TokenType::Colon)) - { - auto res = parseTypeExpr(); - if (!res) - return std::unexpected(res.error()); - paramType = *res; - } - // 接口方法参数类型可选(如果没有标注则默认 Any) - paramTypes.push_back(paramType); - - if (match(TokenType::Comma)) - { - if (match(TokenType::RightParen)) - break; // 尾部逗号 - } - } - - // 返回类型(接口方法必须有返回类型) - Expr *returnType = nullptr; - if (match(TokenType::RightArrow)) - { - auto res = parseTypeExpr(); - if (!res) - return std::unexpected(res.error()); - returnType = *res; - } - else - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "interface method must specify return type with `->`", - "add `-> ReturnType`", - makeSourceLocation(methodNameToken))); - } - - // 默认实现?(方法签名后直接跟 `{` 表示默认实现) - BlockStmt *defaultBody = nullptr; - if (currentToken().type == TokenType::LeftBrace) - { - auto bodyRes = parseBlockStmt(); - if (!bodyRes) - return std::unexpected(bodyRes.error()); - defaultBody = *bodyRes; - } - else if (!match(TokenType::Semicolon)) - { - return std::unexpected(makeExpectSemicolonError()); - } - - // 构建方法签名 - InterfaceDefStmt::Method method; - method.name = methodName; - method.params = paramTypes; - method.retType = returnType; - method.location = makeSourceLocation(methodNameToken); - ifaceDef->methods.push_back(std::move(method)); - - // TODO: 存储默认实现体的 AST - // 当前 InterfaceDefStmt::Method 没有 body 字段 - // 如果需要默认实现,需要扩展 AST - (void) defaultBody; - } - - return ifaceDef; - } - - Result Parser::parseImpl() - { - SourceLocation location = makeSourceLocation(consumeToken()); // consume `impl` - - // impl InterfaceName for StructName { methods... } - auto interfaceTypeRes = parseTypeExpr(); - if (!interfaceTypeRes) - return std::unexpected(interfaceTypeRes.error()); - Expr *interfaceType = *interfaceTypeRes; - - if (!match(TokenType::For)) - { - return std::unexpected( - makeUnexpectTokenError("ImplStmt", "`for` keyword", currentToken())); - } - - auto structTypeRes = parseTypeExpr(); - if (!structTypeRes) - return std::unexpected(structTypeRes.error()); - Expr *structType = *structTypeRes; - - if (!match(TokenType::LeftBrace)) - { - return std::unexpected( - makeUnexpectTokenError("ImplStmt", "lbrace `{`", currentToken())); - } - - const Token &lbToken = prevToken(); - - DynArray methods; - - while (true) - { - if (isEOF) - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "unclosed braces in impl block", - "insert '}'", - makeSourceLocation(lbToken))); - } - if (match(TokenType::RightBrace)) - { - break; - } - - // impl 方法需要 `func` 关键字 - if (currentToken().type != TokenType::Function) - { - return std::unexpected( - makeUnexpectTokenError("ImplStmt", "`func` for method", currentToken())); - } - consumeToken(); // consume `func` - - if (!currentToken().isIdentifier()) - { - return std::unexpected( - makeUnexpectTokenError("ImplStmt", "method name", currentToken())); - } - - const Token &methodNameToken = consumeToken(); - const String &methodName = - srcManager.GetSub(methodNameToken.index, methodNameToken.length); - - // 参数列表 - if (!match(TokenType::LeftParen)) - { - return std::unexpected( - makeUnexpectTokenError("ImplStmt", "`(` for method params", currentToken())); - } - - // 复用 FnDefStmt 来解析 impl 方法 - // 但我们不使用 parseFnDefStmt,因为 impl 方法: - // 1. 不写返回类型(由 interface 约束) - // 2. 必须有函数体({ }) - - DynArray fnParams; - - while (true) - { - if (isEOF) - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "unclosed parenthese in impl method params", - "insert ')'", - makeSourceLocation(methodNameToken))); - } - if (match(TokenType::RightParen)) - { - break; - } - - if (!currentToken().isIdentifier()) - { - return std::unexpected( - makeUnexpectTokenError("ImplStmt", "param name", currentToken())); - } - - const Token &pToken = consumeToken(); - const String &pName = srcManager.GetSub(pToken.index, pToken.length); - - Expr *pType = nullptr; - if (match(TokenType::Colon)) - { - auto res = parseTypeExpr(); - if (!res) - return std::unexpected(res.error()); - pType = *res; - } - - PosParam *param = arena.Allocate( - pName, pType, nullptr, makeSourceLocation(pToken)); - fnParams.push_back(param); - - if (match(TokenType::Comma)) - { - if (match(TokenType::RightParen)) - break; // 尾部逗号 - } - } - - // impl 方法不写返回类型,必须有函数体 - BlockStmt *methodBody = nullptr; - if (currentToken().type == TokenType::LeftBrace) - { - auto bodyRes = parseBlockStmt(); - if (!bodyRes) - return std::unexpected(bodyRes.error()); - methodBody = *bodyRes; - } - else - { - return std::unexpected( - makeUnexpectTokenError("ImplStmt", "`{` for method body", currentToken())); - } - - FnDefStmt *fnDef = arena.Allocate( - false, methodName, fnParams, nullptr /* no return type */, methodBody, - makeSourceLocation(methodNameToken)); - methods.push_back(fnDef); - } - - ImplStmt *implStmt = arena.Allocate(interfaceType, structType, methods, location); - return implStmt; - } - - Result Parser::parseImportStmt() - { - SourceLocation location = makeSourceLocation(consumeToken()); // consume `import` - - bool isFileImport = false; - String path; - - if (currentToken().type == TokenType::LiteralString) - { - // import "path/to/file.fig" — 文件导入 - isFileImport = true; - const Token &strToken = consumeToken(); - path = srcManager.GetSub(strToken.index, strToken.length); - } - else if (currentToken().isIdentifier()) - { - // import std.io — Module 导入 - isFileImport = false; - // 收集完整的路径: a.b.c - while (true) - { - const Token &tok = consumeToken(); - path += srcManager.GetSub(tok.index, tok.length); - if (currentToken().type == TokenType::Dot) - { - path += "."; - consumeToken(); // consume `.` - } - else - { - break; - } - } - } - else - { - return std::unexpected( - makeUnexpectTokenError("ImportStmt", "module path or file string", currentToken())); - } - - if (!match(TokenType::Semicolon)) - { - return std::unexpected(makeExpectSemicolonError()); - } - - ImportStmt *importStmt = arena.Allocate(path, isFileImport, location); - return importStmt; - } - - Result Parser::parseStatement() - { - StateProtector p(this, {State::Standby}); - - bool isPublic = match(TokenType::Public); - - TokenType tt = currentToken().type; - - - switch (tt) - { - case TokenType::LeftBrace: return parseBlockStmt(); - case TokenType::If: return parseIfStmt(); - case TokenType::While: return parseWhileStmt(); - case TokenType::For: return parseForStmt(); - case TokenType::Import: return parseImportStmt(); - case TokenType::Interface: return parseInterfaceDef(isPublic); - case TokenType::Implement: return parseImpl(); - - case TokenType::Variable: return parseVarDecl(isPublic); - case TokenType::Const: return parseConstDecl(isPublic); - - case TokenType::Return: - { - return parseReturnStmt(); - } - - case TokenType::Function: - { - // 需要 lookahead: `func identifier` → 函数定义 - // `func (` 或 `func {` → Lambda 表达式语句 - if (peekToken().isIdentifier()) - return parseFnDefStmt(isPublic); - goto expr_stmt; - } - - case TokenType::Struct: - return parseStructDef(isPublic); - - case TokenType::Break: - { - consumeToken(); - SourceLocation loc = makeSourceLocation(prevToken()); - if (!match(TokenType::Semicolon)) - return std::unexpected(makeExpectSemicolonError()); - return static_cast(arena.Allocate(loc)); - } - - case TokenType::Continue: - { - consumeToken(); - SourceLocation loc = makeSourceLocation(prevToken()); - if (!match(TokenType::Semicolon)) - return std::unexpected(makeExpectSemicolonError()); - return static_cast(arena.Allocate(loc)); - } - - case TokenType::EndOfFile: - return nullptr; - - case TokenType::Semicolon: - return std::unexpected(Error( - ErrorType::SyntaxError, - "null statement is not allowed here", - "remove `;`", - makeSourceLocation(currentToken()))); - - default: - break; - } - - expr_stmt: - { - // 表达式语句 (fallback) - const auto &expr_result = parseExpression(); - if (!expr_result) - return std::unexpected(expr_result.error()); - ExprStmt *exprStmt = arena.Allocate(*expr_result); - if (!match(TokenType::Semicolon)) - return std::unexpected(makeExpectSemicolonError()); - return exprStmt; - } - } - -}; // namespace Fig diff --git a/src/Parser/TypeExprParser.cpp b/src/Parser/TypeExprParser.cpp deleted file mode 100644 index 66f6ce3..0000000 --- a/src/Parser/TypeExprParser.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/*! - @file src/Parser/TypeExprParser.cpp - @brief 类型表达式解析器实现 — 类型即值,产生 Expr* 而非 TypeExpr* - @author PuqiAR (im@puqiar.top) - @date 2026-06-06 -*/ - -#include - -namespace Fig -{ - Result Parser::parseTypeParameters() - { - StateProtector p(this, {State::ParsingTypeParameters}); - decltype(StructDefStmt::typeParameters) tp; - - const Token &lab = consumeToken(); // consume `<` - - while (true) - { - if (isEOF) - { - return std::unexpected(Error( - ErrorType::SyntaxError, - "unclosed `<` in type parameters", - "insert '>'", - makeSourceLocation(lab))); - } - if (match(TokenType::Greater)) // > - { - break; - } - if (!currentToken().isIdentifier()) - { - return std::unexpected( - makeUnexpectTokenError("TypeParams", "tp name", currentToken())); - } - - const Token &name_tok = consumeToken(); - const String &name = srcManager.GetSub(name_tok.index, name_tok.length); - tp.push_back(name); - - if (!match(TokenType::Comma)) - { - return std::unexpected(makeUnexpectTokenError( - "TypeParams", "comma or type parameter", currentToken())); - } - } - return tp; - } - - - - Result Parser::parseNamedTypeExpr() - { - StateProtector p(this, {State::ParsingNamedTypeExpr}); - - - if (!currentToken().isIdentifier()) - { - return std::unexpected( - makeUnexpectTokenError("TypeExpr", "type name", currentToken())); - } - - const Token &firstTok = consumeToken(); - SourceLocation firstLoc = makeSourceLocation(firstTok); - const String &firstName = srcManager.GetSub(firstTok.index, firstTok.length); - - IdentiExpr *ident = arena.Allocate(firstName, firstLoc); - Expr *base = ident; - - // a.b.c - while (match(TokenType::Dot)) - { - if (!currentToken().isIdentifier()) - { - return std::unexpected( - makeUnexpectTokenError("TypeExpr", "identifier after `.`", currentToken())); - } - const Token &tok = consumeToken(); - const String &name = srcManager.GetSub(tok.index, tok.length); - SourceLocation loc = makeSourceLocation(tok); - base = arena.Allocate(base, name, loc); - } - - // generic args - if (match(TokenType::Less)) - { - DynArray args; - - while (true) - { - auto result = parseTypeExpr(); - if (!result) - return std::unexpected(result.error()); - args.push_back(*result); - - if (match(TokenType::Greater)) - break; // `>` - if (!match(TokenType::Comma)) - return std::unexpected( - makeUnexpectTokenError("TypeArgs", "'>' or ','", currentToken())); - } - - base = arena.Allocate(base, std::move(args), firstLoc); - } - - return base; - } - - Result Parser::parseFnTypeExpr() - { - StateProtector p(this, {State::ParsingFnTypeExpr}); - SourceLocation location = makeSourceLocation(consumeToken()); // consume `func` - if (!match(TokenType::LeftParen)) // `(` - { - return std::unexpected( - makeUnexpectTokenError("FnTypeExpr", "lparen (", currentToken())); - } - - DynArray paraTypes; - - while (true) - { - auto result = parseTypeExpr(); - if (!result) - { - return result; - } - paraTypes.push_back(*result); - - if (match(TokenType::RightParen)) - { - break; - } - else if (isEOF) - { - return std::unexpected( - makeUnexpectTokenError("FnTypeExpr", "rparen )", currentToken())); - } - if (!match(TokenType::Comma)) - { - return std::unexpected( - makeUnexpectTokenError("FnTypeExpr", "comma ,", currentToken())); - } - } - - Expr *returnType = nullptr; - - if (match(TokenType::RightArrow)) // -> - { - auto result = parseTypeExpr(); - if (!result) - { - return result; - } - returnType = *result; - } - - FnTypeExpr *fnTypeExpr = arena.Allocate(paraTypes, returnType); - return fnTypeExpr; - } - - - Result Parser::parseTypeExpr() - { - Expr *base = nullptr; - - if (currentToken().isIdentifier()) - { - auto result = parseNamedTypeExpr(); - if (!result) - { - return result; - } - base = *result; - } - else if (currentToken().type == TokenType::Function) - { - auto result = parseFnTypeExpr(); - if (!result) - { - return result; - } - base = *result; - } - else - { - return std::unexpected(makeUnexpectTokenError("TypeExpr", "name", currentToken())); - } - - // nullable - if (currentToken().type == TokenType::Question) // ? - { - base = arena.Allocate( - base, makeSourceLocation(consumeToken())); // consume `?` - } - - return base; - } -} // namespace Fig diff --git a/src/Repl/Repl.hpp b/src/Repl/Repl.hpp deleted file mode 100644 index 1d8db4c..0000000 --- a/src/Repl/Repl.hpp +++ /dev/null @@ -1,311 +0,0 @@ -/*! - @file src/Repl/Repl.hpp - @brief Repl定义 - @author PuqiAR (im@puqiar.top) - @date 2026-03-11 -*/ - -#pragma once - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -namespace Fig -{ - class Repl - { - private: - size_t rline = 1; - - std::istream ∈ - std::ostream &out; - std::ostream &err; - - public: - Repl(std::istream &_in, std::ostream &_out, std::ostream &_err) : - in(_in), out(_out), err(_err) - { - } - - void PrintInfo() - { - out << std::format( - "Fig {}, copyright (c) 2025-2026 PuqiAR, under the {} License\n", - Core::VERSION, - Core::LICENSE); - out << std::format( - "Build time: {} [{} x{} on {}]\n", - Core::COMPILE_TIME, - Core::COMPILER, - Core::ARCH, - Core::PLATFORM); - out << "Type '#exit' to exit, '#clear' to clear the the screen, '#license' to see the full license, '#logo' to see a GREAT logo\n"; - out << '\n'; - } - - void ClearConsole() - { - // \033[2J: 清除整个屏幕 - // \033[H: 将光标移动到左上角 - out << "\033[2J\033[H" << std::flush; - } - - void PrintLicense() - { - static DynArray license_lines{}; - if (license_lines.empty()) - { - std::string l; - bool last_was_r = false; - - for (size_t i = 0; i < Core::LICENSE_TEXT.size(); ++i) - { - char c = Core::LICENSE_TEXT[i]; - - if (c == '\r') - { - last_was_r = true; - continue; - } - - if (c == '\n') - { - if (!l.empty() || last_was_r) - { - license_lines.push_back(l); - l.clear(); - } - last_was_r = false; - continue; - } - - if (last_was_r) - { - if (!l.empty()) - { - license_lines.push_back(l); - l.clear(); - } - last_was_r = false; - } - - l += c; - } - - if (!l.empty() || last_was_r) - { - license_lines.push_back(l); - } - } - - unsigned int lines_per_page = 50; - unsigned int page_printed = 0; - unsigned int lines_printed = 0; - unsigned int total_lines = license_lines.size(); - - while (true) - { - auto _csize = Utils::getConsoleSize(); - if (_csize) - { - lines_per_page = static_cast((*_csize).first * 0.75); - if (lines_per_page < 1) - lines_per_page = 1; - } - - unsigned int lines_this_page = - std::min(lines_per_page, total_lines - lines_printed); - - for (unsigned int i = 0; i < lines_this_page; ++i) - { - out << license_lines[lines_printed + i] << '\n'; - } - - lines_printed += lines_this_page; - page_printed++; - - if (lines_printed >= total_lines) - { - break; - } - - unsigned int pages_total = (total_lines + lines_per_page - 1) / lines_per_page; - - out << "\n" - << std::format( - "Press any key to continue... ({}/{})", page_printed, pages_total); - - in.get(); - out << '\n'; - ++rline; - } - } - // void PrintError(const Error &error, const String &source) - // { - // err << "Oops! An error occurred!"; - // err << "🔥 " << 'E' << static_cast(error.type) << ": " << error.message << '\n'; - // err << "Line " << rline << ", `" << source << "`\n"; - // err << "Suggestion: " << error.suggestion << '\n'; - // err << std::format( - // "Thrower: {} ({}:{}:{})\n", - // error.thrower_loc.function_name(), - // error.thrower_loc.file_name(), - // error.thrower_loc.line(), - // error.thrower_loc.column()); - // } - - void PrintError(const Error &error, const String &source) - { - static constexpr const char *MinorColor = "\033[38;2;138;227;198m"; - static constexpr const char *MediumColor = "\033[38;2;255;199;95m"; - static constexpr const char *CriticalColor = "\033[38;2;255;107;107m"; - - namespace TC = TerminalColors; - std::ostream &err = CoreIO::GetStdErr(); - - uint8_t level = ErrorLevel(error.type); - // const char *level_name = (level == 1 ? "Minor" : (level == 2 ? "Medium" : - // "Critical")); - const char *const &level_color = - (level == 1 ? MinorColor : (level == 2 ? MediumColor : CriticalColor)); - - err << "\n"; - err << "🔥 " - << level_color - //<< '(' << level_name << ')' - << 'E' << static_cast(error.type) << TC::Reset << ": " << level_color - << ErrorTypeToString(error.type) << TC::Reset << '\n'; - - const SourceLocation &location = error.location; - - err << TC::DarkGray << " ┌─> Fn " << TC::Cyan << '\'' << location.packageName << '.' - << location.functionName << '\'' << " " << location.fileName << " (" << TC::DarkGray - << location.sp.line << ":" << location.sp.column << TC::Cyan << ')' << TC::Reset - << '\n'; - err << TC::DarkGray << " │" << '\n' << " │" << TC::Reset << '\n'; - err << TC::DarkGray << " └─ " << TC::Reset; - err << source << "\n"; - - err << "\n"; - err << "❓ " << TC::DarkGray << "Thrower: " << error.thrower_loc.function_name() << " (" - << error.thrower_loc.file_name() << ":" << error.thrower_loc.line() << ")" - << TC::Reset << "\n"; - err << "💡 " << TC::Blue << "Suggestion: " << error.suggestion << TC::Reset; - err << '\n'; - } - - unsigned int Start() // exit code: unsigned int - { - // TODO: 多行输入 Repl - - PrintInfo(); - - String fileName = "[REPL]"; - String filePath = "src/Repl/Repl.hpp"; - - SourceManager manager; - - VM vm; - - Value v = Value::GetNullInstance(); - - while (true) - { - std::string buf; - - out << ">"; - - std::getline(in, buf); - - if (buf.empty()) - { - continue; - } - else if (buf == "#exit") - { - return 0; - } - else if (buf == "#clear") - { - ClearConsole(); - continue; - } - else if (buf == "#license") - { - PrintLicense(); - continue; - } - else if (buf == "#logo") - { - out << Core::LOGO << '\n'; - continue; - } - - String source(buf); - - Lexer lexer(buf, fileName); - - Diagnostics diagnostics; - - Parser parser(lexer, manager, fileName, diagnostics); - - auto _program = parser.Parse(); - if (!_program) - { - PrintError(_program.error(), source); - continue; - } - - Program *program = *_program; - - Analyzer analyzer(manager); - auto result = analyzer.Analyze(program); - - analyzer.GetDiagnostics().EmitAll(manager); - - if (!result) - { - PrintError(result.error(), source); - continue; - } - - Compiler compiler(manager, diagnostics); - - auto compile_result = compiler.Compile(program); - if (!compile_result) - { - PrintError(compile_result.error(), source); - continue; - } - - diagnostics.EmitAll(manager); - - CompiledModule *compiledModule = *compile_result; - - auto exe_result = vm.Execute(compiledModule); - if (!exe_result) - { - PrintError(exe_result.error(), source); - continue; - } - - v = *exe_result; - if (!v.IsNull()) - { - out << v.ToString() << '\n'; - } - } - - return (v.IsInt() ? v.AsInt() : 0); - } - }; -}; // namespace Fig \ No newline at end of file diff --git a/src/Repl/ReplTest.cpp b/src/Repl/ReplTest.cpp deleted file mode 100644 index 057865c..0000000 --- a/src/Repl/ReplTest.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include - -int main() -{ - using namespace Fig; - Repl repl(CoreIO::GetStdCin(), CoreIO::GetStdOut(), CoreIO::GetStdErr()); - - repl.Start(); -} \ No newline at end of file diff --git a/src/Sema/Analyzer.hpp b/src/Sema/Analyzer.hpp deleted file mode 100644 index 5e2b764..0000000 --- a/src/Sema/Analyzer.hpp +++ /dev/null @@ -1,32 +0,0 @@ -/*! - @file src/Sema/Analyzer.hpp - @brief 语义分析 - @author PuqiAR (im@puqiar.top) - @date 2026-06-06 -*/ - -#pragma once - -#include -#include -#include -#include - -namespace Fig -{ - class Analyzer - { - public: - Analyzer(SourceManager &) {} - - Result Analyze(Program *) - { - return {}; - } - - Diagnostics &GetDiagnostics() { return diag; } - - private: - Diagnostics diag; - }; -} // namespace Fig diff --git a/src/Sema/Environment.hpp b/src/Sema/Environment.hpp deleted file mode 100644 index 4f4457d..0000000 --- a/src/Sema/Environment.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/*! - @file src/Sema/Environment.hpp - @brief 符号表 - @author PuqiAR (im@puqiar.top) - @date 2026-07-05 -*/ - -#pragma once - -#include -#include - -namespace Fig -{ - enum class SymbolKind : uint8_t - { - Var, - Const, - Func, - Type, - }; - - struct Symbol - { - String name; - Type type; - SymbolKind kind; - int index; // local: register idx, global: global idx, upvalue: upvalue idx - - bool isType() const { return kind == SymbolKind::Type; } - }; - - struct Scope - { - Scope *parent = nullptr; - bool isFnBoundary = false; - HashMap locals; - int nextReg = 0; - }; - - class Environment - { - public: - Scope *current = nullptr; - - void push(bool isFn) - { - auto *s = new Scope; - s->parent = current; - s->isFnBoundary = isFn; - if (current && !isFn) - s->nextReg = current->nextReg; - current = s; - } - - void pop() - { - auto *old = current; - current = current->parent; - delete old; - } - }; -} // namespace Fig diff --git a/src/Sema/Type.hpp b/src/Sema/Type.hpp deleted file mode 100644 index fe05e51..0000000 --- a/src/Sema/Type.hpp +++ /dev/null @@ -1,36 +0,0 @@ -/*! - @file src/Sema/Type.hpp - @brief 类型系统 - @author PuqiAR (im@puqiar.top) - @date 2026-07-05 -*/ - -#pragma once - -#include - -namespace Fig -{ - struct Type - { - TypeObject *obj = nullptr; - bool isNullable = false; - - bool is(TypeTag t) const; - bool isAssignableTo(const Type &target) const; - }; - - inline bool Type::is(TypeTag t) const - { - return obj && obj->tag == t; - } - - inline bool Type::isAssignableTo(const Type &target) const - { - if (target.is(TypeTag::Any) || is(TypeTag::Any)) - return true; - if (is(TypeTag::Null) && target.isNullable) - return true; - return obj == target.obj && (!isNullable || target.isNullable); - } -} // namespace Fig diff --git a/src/SourceManager/SourceManager.hpp b/src/SourceManager/SourceManager.hpp deleted file mode 100644 index cacf812..0000000 --- a/src/SourceManager/SourceManager.hpp +++ /dev/null @@ -1,146 +0,0 @@ -/*! - @file src/SourceManager/SourceManager.hpp - @brief 源代码管理 - @author PuqiAR (im@puqiar.top) - @date 2026-02-14 -*/ - -#pragma once - -#include -#include - - -#include - -namespace Fig -{ - class SourceManager - { - private: - String filePath; - String source; - std::vector lines; - std::vector lineStartIndex; // 每行在整个源字符串中的起始 index - - void preprocessLineIndices() - { - lineStartIndex.clear(); - lineStartIndex.push_back(0); - - for (size_t i = 0; i < source.length(); ++i) - { - if (source[i] == U'\n') - { - lineStartIndex.push_back(i + 1); - } - else if (source[i] == U'\r') - { - // 处理 CRLF,只在 \n 处记录 - if (i + 1 < source.length() && source[i + 1] == U'\n') - continue; - - lineStartIndex.push_back(i + 1); - } - } - } - - public: - bool read = false; - String &Read() - { - std::fstream fs(filePath.toStdString()); - if (!fs.is_open()) - { - read = false; - return source; - } - std::string line; - while (std::getline(fs, line)) - { - source += line + '\n'; - lines.push_back(String(line)); - } - if (!source.empty() && source.back() == U'\n') - source.pop_back(); - - if (lines.empty()) - { - lines.push_back(String()); // 填充一个空的 - } - read = true; - preprocessLineIndices(); - return source; - } - - SourceManager() {} - SourceManager(String _path) - { - filePath = std::move(_path); - } - - bool HasLine(int64_t _line) const - { - return _line <= lines.size() && _line >= 1; - } - - const String &GetLine(size_t _line) const - { - assert(_line <= lines.size() && "SourceManager: GetLine failed, index out of range"); - return lines[_line - 1]; - } - - String GetSub(size_t _index_start, size_t _length) const - { - return source.substr(_index_start, _length); - } - - const String &GetSource() const - { - return source; - } - - String &GetSource() - { - return source; - } - - std::pair GetLineColumn(size_t index) const - { - if (lineStartIndex.empty()) - { - return {1, 1}; - } - - // clamp index 到合法范围(Parser报错可能传入EOF位置) - // size_t lastLine = lineStartIndex.size() - 1; - if (index < lineStartIndex[0]) - { - return {1, 1}; - } - - // upper_bound 找到第一个 > index 的行起点 - auto it = std::ranges::upper_bound(lineStartIndex.begin(), lineStartIndex.end(), index); - - size_t line; - if (it == lineStartIndex.begin()) - { - line = 0; - } - else - { - line = static_cast(it - lineStartIndex.begin() - 1); - } - - size_t column = index - lineStartIndex[line] + 1; - return {line + 1, column}; - } - - void LoadFromMemory(String src) - { - source = std::move(src); - read = true; - preprocessLineIndices(); - } - }; -}; // namespace Fig \ No newline at end of file diff --git a/src/Token/Token.cpp b/src/Token/Token.cpp deleted file mode 100644 index 669e178..0000000 --- a/src/Token/Token.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/*! - @file src/Token/Token.cpp - @brief Token实现 - @author PuqiAR (im@puqiar.top) - @date 2026-02-14 -*/ -#include - -namespace Fig -{ - const HashMap Token::punctMap = { - // 三字符 - {String("..."), TokenType::TripleDot}, - // 双字符 - {String("=="), TokenType::Equal}, - {String("!="), TokenType::NotEqual}, - {String("<="), TokenType::LessEqual}, - {String(">="), TokenType::GreaterEqual}, - {String("<<"), TokenType::ShiftLeft}, - {String(">>"), TokenType::ShiftRight}, - {String("+="), TokenType::PlusEqual}, - {String("-="), TokenType::MinusEqual}, - {String("*="), TokenType::AsteriskEqual}, - {String("/="), TokenType::SlashEqual}, - {String("%="), TokenType::PercentEqual}, - {String("^="), TokenType::CaretEqual}, - {String("++"), TokenType::DoublePlus}, - {String("--"), TokenType::DoubleMinus}, - {String("&&"), TokenType::DoubleAmpersand}, - {String("||"), TokenType::DoublePipe}, - {String(":="), TokenType::Walrus}, - {String("**"), TokenType::Power}, - {String("->"), TokenType::RightArrow}, - {String("=>"), TokenType::DoubleArrow}, - - // 单字符 - {String("+"), TokenType::Plus}, - {String("-"), TokenType::Minus}, - {String("*"), TokenType::Asterisk}, - {String("/"), TokenType::Slash}, - {String("%"), TokenType::Percent}, - {String("^"), TokenType::Caret}, - {String("&"), TokenType::Ampersand}, - {String("|"), TokenType::Pipe}, - {String("~"), TokenType::Tilde}, - {String("="), TokenType::Assign}, - {String("<"), TokenType::Less}, - {String(">"), TokenType::Greater}, - {String("."), TokenType::Dot}, - {String(","), TokenType::Comma}, - {String(":"), TokenType::Colon}, - {String(";"), TokenType::Semicolon}, - {String("'"), TokenType::SingleQuote}, - {String("\""), TokenType::DoubleQuote}, - {String("("), TokenType::LeftParen}, - {String(")"), TokenType::RightParen}, - {String("["), TokenType::LeftBracket}, - {String("]"), TokenType::RightBracket}, - {String("{"), TokenType::LeftBrace}, - {String("}"), TokenType::RightBrace}, - {String("?"), TokenType::Question}, - {String("!"), TokenType::Not}, - }; - - const HashMap Token::keywordMap{ - {String("and"), TokenType::And}, - {String("or"), TokenType::Or}, - {String("not"), TokenType::Not}, - {String("import"), TokenType::Import}, - {String("func"), TokenType::Function}, - {String("var"), TokenType::Variable}, - {String("const"), TokenType::Const}, - // {String("final"), TokenType::Final}, - {String("while"), TokenType::While}, - {String("for"), TokenType::For}, - {String("if"), TokenType::If}, - {String("else"), TokenType::Else}, - {String("new"), TokenType::New}, - {String("struct"), TokenType::Struct}, - {String("interface"), TokenType::Interface}, - {String("impl"), TokenType::Implement}, - {String("is"), TokenType::Is}, - {String("public"), TokenType::Public}, - {String("return"), TokenType::Return}, - {String("break"), TokenType::Break}, - {String("continue"), TokenType::Continue}, - {String("try"), TokenType::Try}, - {String("catch"), TokenType::Catch}, - {String("throw"), TokenType::Throw}, - {String("finally"), TokenType::Finally}, - {String("as"), TokenType::As}, - {String("true"), TokenType::LiteralTrue}, - {String("false"), TokenType::LiteralFalse}, - {String("null"), TokenType::LiteralNull}, - }; -}; // namespace Fig \ No newline at end of file diff --git a/src/Token/Token.hpp b/src/Token/Token.hpp deleted file mode 100644 index 46b808e..0000000 --- a/src/Token/Token.hpp +++ /dev/null @@ -1,168 +0,0 @@ -/*! - @file src/Token/Token.hpp - @brief Token定义 - @author PuqiAR (im@puqiar.top) - @date 2026-02-14 -*/ - -#pragma once - -#include -#include - -#include - -#include -#include - -namespace Fig -{ - enum class TokenType : int8_t - { - Illegal = -1, - EndOfFile = 0, - - Comments, - - Identifier, - - /* Keywords */ - Package, // package - And, // and - Or, // or - Not, // not - Import, // import - Function, // func - Variable, // var - Const, // const - // Final, // final - While, // while - For, // for - If, // if - Else, // else - New, // new - Struct, // struct - Interface, // interface - Implement, // impl - Is, // is - Public, // public - Return, // return - Break, // break - Continue, // continue - Try, // try - Catch, // catch - Throw, // throw - Finally, // finally - As, // as - - // TypeNull, // Null - // TypeInt, // Int - // TypeDeps::String, // Deps::String - // TypeBool, // Bool - // TypeDouble, // Double - - /* Literal Types */ - LiteralNumber, // number (int,float...) - LiteralString, // string - - LiteralTrue, // true <-- keyword - LiteralFalse, // false <-- keyword - LiteralNull, // null (Null unique instance) <-- keyword - - /* Punct */ - Plus, // + - Minus, // - - Asterisk, // * - Slash, // / - Percent, // % - Caret, // ^ - Ampersand, // & - Pipe, // | - Tilde, // ~ - ShiftLeft, // << - ShiftRight, // >> - // Exclamation, // ! - Question, // ? - Assign, // = - Less, // < - Greater, // > - Dot, // . - Comma, // , - Colon, // : - Semicolon, // ; - SingleQuote, // ' - DoubleQuote, // " - // Backtick, // ` - // At, // @ - // Hash, // # - // Dollar, // $ - // Backslash, // '\' - // Underscore, // _ - LeftParen, // ( - RightParen, // ) - LeftBracket, // [ - RightBracket, // ] - LeftBrace, // { - RightBrace, // } - // LeftArrow, // <- - RightArrow, // -> - DoubleArrow, // => - Equal, // == - NotEqual, // != - LessEqual, // <= - GreaterEqual, // >= - - PlusEqual, // += - MinusEqual, // -= - AsteriskEqual, // *= - SlashEqual, // /= - PercentEqual, // %= - CaretEqual, // ^= - - DoublePlus, // ++ - DoubleMinus, // -- - DoubleAmpersand, // && - DoublePipe, // || - Walrus, // := - Power, // ** - - TripleDot, // ... for variadic parameter - }; - - class Token final - { - public: - static const HashMap punctMap; - static const HashMap keywordMap; - - size_t index, length; - // 源文件中的下标 Token长度 - TokenType type; - - Token() : index(0), length(0), type(TokenType::Illegal) {}; - Token(size_t _index, size_t _length, TokenType _type) : index(_index), length(_length), type(_type) {} - Deps::String toString() const - { - return Deps::String(std::format("Token'{}' at {}, len {}", magic_enum::enum_name(type), index, length)); - } - - bool isIdentifier() const { return type == TokenType::Identifier; } - bool isLiteral() const - { - return type == TokenType::LiteralNull || type == TokenType::LiteralTrue || type == TokenType::LiteralFalse - || type == TokenType::LiteralNumber || type == TokenType::LiteralString; - } - - Token &operator=(const Token &other) - { - if (this == &other) - { - return *this; - } - index = other.index; - length = other.length; - type = other.type; - return *this; - } - }; -} // namespace Fig \ No newline at end of file diff --git a/src/Utils/Arena.hpp b/src/Utils/Arena.hpp deleted file mode 100644 index ec8adf5..0000000 --- a/src/Utils/Arena.hpp +++ /dev/null @@ -1,115 +0,0 @@ -/*! - @file src/Utils/Arena.hpp - @brief 线性分配内存池,支持非平凡析构对象的自动清理 - @author PuqiAR (im@puqiar.top) - @date 2026-03-08 -*/ - -#pragma once - -#include -#include -#include -#include - -namespace Fig -{ - class Arena - { - private: - struct DestructorNode - { - void (*destructor)(void *); - void *object; - DestructorNode *next; - }; - - static constexpr std::size_t CHUNK_SIZE = 64 * 1024; // 64KB 块大小 - - std::vector chunks; - char *currentPtr = nullptr; - std::size_t remaining = 0; - DestructorNode *destructorHead = nullptr; - - public: - Arena() = default; - - ~Arena() - { - // 逆序调用析构函数 - DestructorNode *node = destructorHead; - while (node) - { - node->destructor(node->object); - node = node->next; - } - - // 释放所有分配的内存块 - for (char *chunk : chunks) - { - delete[] chunk; - } - } - - // 禁止拷贝和移动,防止内存所有权混乱 - Arena(const Arena &) = delete; - Arena &operator=(const Arena &) = delete; - - template - T *Allocate(Args &&...args) - { - std::size_t size = sizeof(T); - std::size_t alignment = alignof(T); - - // 在当前块中尝试对齐并分配 - void *ptr = allocateRaw(size, alignment); - - // 在分配的内存上构造对象 - T *obj = new (ptr) T(std::forward(args)...); - - // 如果 T 需要析构(如包含 String),注册到销毁链表 - if constexpr (!std::is_trivially_destructible_v) - { - // 注意: DestructorNode 本身是 POD,直接在 Arena 里分配,不需要注册析构 - void *nodeRaw = allocateRaw(sizeof(DestructorNode), alignof(DestructorNode)); - DestructorNode *node = new (nodeRaw) DestructorNode(); - - node->object = obj; - node->destructor = [](void *p) { static_cast(p)->~T(); }; - node->next = destructorHead; - destructorHead = node; - } - - return obj; - } - - private: - void *allocateRaw(std::size_t size, std::size_t alignment) - { - // 对齐计算 - std::size_t adjustment = 0; - std::size_t currentAddr = reinterpret_cast(currentPtr); - if (alignment > 0 && (currentAddr % alignment) != 0) - { - adjustment = alignment - (currentAddr % alignment); - } - - if (remaining < (size + adjustment)) - { - // 当前块空间不足,分配新块 - std::size_t nextChunkSize = (size > CHUNK_SIZE) ? size : CHUNK_SIZE; - currentPtr = new char[nextChunkSize]; - chunks.push_back(currentPtr); - remaining = nextChunkSize; - adjustment = 0; // 新分配的块通常是最大对齐的 - } - - currentPtr += adjustment; - void *res = currentPtr; - currentPtr += size; - remaining -= (size + adjustment); - - return res; - } - }; -} // namespace Fig diff --git a/src/Utils/ArgParser/ArgParser.hpp b/src/Utils/ArgParser/ArgParser.hpp deleted file mode 100644 index fa799cb..0000000 --- a/src/Utils/ArgParser/ArgParser.hpp +++ /dev/null @@ -1,336 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace Fig::ArgParser -{ - - enum class ParseErrorCode - { - UnknownOption, - MissingValue, - MissingRequired, - InvalidFormat - }; - - struct ParseError - { - ParseErrorCode code; - String context; - - String Format() const - { - switch (code) - { - case ParseErrorCode::UnknownOption: - return String(std::format("Unknown option: {}", context.toStdString())); - case ParseErrorCode::MissingValue: - return String( - std::format("Missing value for option: {}", context.toStdString())); - case ParseErrorCode::MissingRequired: - return String( - std::format("Missing required option: {}", context.toStdString())); - case ParseErrorCode::InvalidFormat: - return String( - std::format("Invalid argument format: {}", context.toStdString())); - default: return String("Unknown parse error"); - } - } - }; - - class OptionDef - { - public: - OptionDef(char short_name, String long_name) : - short_name_(short_name), long_name_(std::move(long_name)) - { - } - - OptionDef &Help(String help_text) - { - help_ = std::move(help_text); - return *this; - } - - OptionDef &DefaultValue(String value) - { - default_value_ = std::move(value); - return *this; - } - - OptionDef &Required(bool required = true) - { - required_ = required; - return *this; - } - - OptionDef &TakesValue(bool takes_value = true) - { - takes_value_ = takes_value; - return *this; - } - - char short_name_; - String long_name_; - String help_; - std::optional default_value_; - bool required_ = false; - bool takes_value_ = false; - }; - - class ParseResult - { - public: - bool HasFlag(const String &long_name) const - { - auto it = options_.find(long_name); - return it != options_.end() && it->second == String("true"); - } - - std::optional GetOption(const String &long_name) const - { - if (auto it = options_.find(long_name); it != options_.end()) - return it->second; - return std::nullopt; - } - - const DynArray &GetPositionals() const - { - return positionals_; - } - - private: - friend class ArgumentParser; - HashMap options_; - DynArray positionals_; - }; - - class ArgumentParser - { - public: - explicit ArgumentParser(String prog_name, String description = String("")) : - prog_name_(std::move(prog_name)), description_(std::move(description)) - { - } - - OptionDef &AddFlag(char short_name, const String &long_name) - { - return registerOption(short_name, long_name).TakesValue(false); - } - - OptionDef &AddFlag(const String &long_name) - { - return registerOption('\0', long_name).TakesValue(false); - } - - OptionDef &AddOption(char short_name, const String &long_name) - { - return registerOption(short_name, long_name).TakesValue(true); - } - - OptionDef &AddOption(const String &long_name) - { - return registerOption('\0', long_name).TakesValue(true); - } - - Result Parse(int argc, const char *const *argv) const - { - if (argc <= 0) - return ParseResult{}; - - return parseInternal( - std::span{argv + 1, static_cast(argc - 1)}) - .and_then([this](ParseResult res) { return validateRequired(std::move(res)); }) - .and_then([this](ParseResult res) { return applyDefaults(std::move(res)); }); - } - - String FormatHelp() const - { - std::string help = - std::format("Usage: {} [OPTIONS] [ARGS...]\n\n", prog_name_.toStdString()); - - if (!description_.empty()) - help += std::format("{}\n\n", description_.toStdString()); - - help += "Options:\n"; - for (const auto &opt : options_) - { - std::string flags; - if (opt.short_name_ != '\0') - flags = std::format("-{}, --{}", opt.short_name_, opt.long_name_.toStdString()); - else - flags = std::format(" --{}", opt.long_name_.toStdString()); - - if (opt.takes_value_) - flags += " "; - - std::string desc = opt.help_.toStdString(); - if (opt.default_value_) - desc += std::format(" (default: {})", opt.default_value_->toStdString()); - if (opt.required_) - desc += " [required]"; - - help += std::format(" {:<25} {}\n", flags, desc); - } - - return String(help); - } - - private: - OptionDef ®isterOption(char short_name, const String &long_name) - { - size_t idx = options_.size(); - options_.emplace_back(short_name, long_name); - long_map_[long_name] = idx; - if (short_name != '\0') - short_map_[short_name] = idx; - return options_.back(); - } - - Result parseInternal(std::span args) const - { - ParseResult result; - bool only_positionals = false; - - for (size_t i = 0; i < args.size(); ++i) - { - std::string_view arg{args[i]}; - - if (only_positionals) - { - result.positionals_.emplace_back(String(std::string(arg))); - continue; - } - - if (arg == "--") - { - only_positionals = true; - continue; - } - - if (arg.starts_with("--")) - { - auto kv = arg.substr(2); - if (kv.empty()) - return std::unexpected( - ParseError{ParseErrorCode::InvalidFormat, String("--")}); - - auto eq_pos = kv.find('='); - auto key = kv.substr(0, eq_pos); - auto key_s = String(std::string(key)); - - auto it = long_map_.find(key_s); - if (it == long_map_.end()) - return std::unexpected( - ParseError{ParseErrorCode::UnknownOption, String(std::string(arg))}); - - const auto &def = options_[it->second]; - - if (def.takes_value_) - { - if (eq_pos != std::string_view::npos) - { - result.options_[def.long_name_] = - String(std::string(kv.substr(eq_pos + 1))); - } - else - { - if (i + 1 >= args.size()) - return std::unexpected(ParseError{ - ParseErrorCode::MissingValue, String(std::string(arg))}); - result.options_[def.long_name_] = String(std::string(args[++i])); - } - } - else - { - if (eq_pos != std::string_view::npos) - return std::unexpected(ParseError{ - ParseErrorCode::InvalidFormat, String(std::string(arg))}); - result.options_[def.long_name_] = String("true"); - } - } - else if (arg.starts_with('-') && arg.size() > 1) - { - auto group = arg.substr(1); - for (size_t j = 0; j < group.size(); ++j) - { - char c = group[j]; - auto it = short_map_.find(c); - if (it == short_map_.end()) - return std::unexpected(ParseError{ - ParseErrorCode::UnknownOption, String(std::string(1, c))}); - - const auto &def = options_[it->second]; - - if (def.takes_value_) - { - if (j + 1 < group.size()) - { - result.options_[def.long_name_] = - String(std::string(group.substr(j + 1))); - break; - } - else - { - if (i + 1 >= args.size()) - return std::unexpected(ParseError{ParseErrorCode::MissingValue, - String(std::format("-{}", c))}); - result.options_[def.long_name_] = String(std::string(args[++i])); - } - } - else - { - result.options_[def.long_name_] = String("true"); - } - } - } - else - { - result.positionals_.emplace_back(String(std::string(arg))); - } - } - return result; - } - - Result validateRequired(ParseResult res) const - { - for (const auto &opt : options_) - { - if (opt.required_ && res.options_.find(opt.long_name_) == res.options_.end()) - { - std::string flag = - opt.short_name_ != '\0' ? - std::format("-{}/--{}", opt.short_name_, opt.long_name_.toStdString()) : - std::format("--{}", opt.long_name_.toStdString()); - return std::unexpected( - ParseError{ParseErrorCode::MissingRequired, String(flag)}); - } - } - return res; - } - - Result applyDefaults(ParseResult res) const - { - for (const auto &opt : options_) - { - if (opt.default_value_ && res.options_.find(opt.long_name_) == res.options_.end()) - { - res.options_[opt.long_name_] = *opt.default_value_; - } - } - return res; - } - - String prog_name_; - String description_; - DynArray options_; - HashMap long_map_; - HashMap short_map_; - }; - -} // namespace Fig::ArgParser \ No newline at end of file diff --git a/src/Utils/ConsoleSize.hpp b/src/Utils/ConsoleSize.hpp deleted file mode 100644 index 031fb43..0000000 --- a/src/Utils/ConsoleSize.hpp +++ /dev/null @@ -1,88 +0,0 @@ -#include -#include -#ifdef _WIN32 - #include -#else - #include - #include -#endif - -namespace Fig::Utils -{ - - /** - * 获取控制台窗口的大小(行数和列数) - * @return 如果成功,返回包含 (rows, cols) 的 optional;失败返回 std::nullopt - */ - - inline std::optional> getConsoleSize() - { -#ifdef _WIN32 - // Windows: GetConsoleScreenBufferInfo - CONSOLE_SCREEN_BUFFER_INFO csbi; - HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); - - if (hConsole == INVALID_HANDLE_VALUE) - { - return std::nullopt; - } - - if (!GetConsoleScreenBufferInfo(hConsole, &csbi)) - { - return std::nullopt; - } - - // 窗口大小 = 右下角坐标 - 左上角坐标 + 1 - int cols = csbi.srWindow.Right - csbi.srWindow.Left + 1; - int rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; - - return std::make_pair(rows, cols); - -#else - // Linux / macOS / Unix: ioctl - struct winsize w; - - // 标准输出被重定向到文件 ? - if (!isatty(STDOUT_FILENO)) - { - // 不是终端,获取环境变量 - char *cols_env = getenv("COLUMNS"); - char *rows_env = getenv("LINES"); - if (cols_env && rows_env) - { - int cols = std::stoi(cols_env); - int rows = std::stoi(rows_env); - return std::make_pair(rows, cols); - } - return std::nullopt; - } - - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == -1) - { - return std::nullopt; - } - - int cols = w.ws_col; - int rows = w.ws_row; - - // 如果 ws_col 或 ws_row 为 0,使用环境变量 - if (cols == 0 || rows == 0) - { - char *cols_env = getenv("COLUMNS"); - char *rows_env = getenv("LINES"); - if (cols_env) - cols = std::stoi(cols_env); - if (rows_env) - rows = std::stoi(rows_env); - } - - if (cols > 0 && rows > 0) - { - return std::make_pair(rows, cols); - } - - return std::nullopt; -#endif - } - -} // namespace Fig::Utils \ No newline at end of file diff --git a/src/Utils/json/json.hpp b/src/Utils/json/json.hpp deleted file mode 100644 index 82d69f7..0000000 --- a/src/Utils/json/json.hpp +++ /dev/null @@ -1,25526 +0,0 @@ -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann -// SPDX-License-Identifier: MIT - -/****************************************************************************\ - * Note on documentation: The source files contain links to the online * - * documentation of the public API at https://json.nlohmann.me. This URL * - * contains the most recent documentation and should also be applicable to * - * previous versions; documentation for deprecated functions is not * - * removed, but marked deprecated. See "Generate documentation" section in * - * file docs/README.md. * -\****************************************************************************/ - -#ifndef INCLUDE_NLOHMANN_JSON_HPP_ -#define INCLUDE_NLOHMANN_JSON_HPP_ - -#include // all_of, find, for_each -#include // nullptr_t, ptrdiff_t, size_t -#include // hash, less -#include // initializer_list -#ifndef JSON_NO_IO - #include // istream, ostream -#endif // JSON_NO_IO -#include // random_access_iterator_tag -#include // unique_ptr -#include // string, stoi, to_string -#include // declval, forward, move, pair, swap -#include // vector - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -// This file contains all macro definitions affecting or depending on the ABI - -#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK - #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) - #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 12 || NLOHMANN_JSON_VERSION_PATCH != 0 - #warning "Already included a different version of the library!" - #endif - #endif -#endif - -#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) -#define NLOHMANN_JSON_VERSION_MINOR 12 // NOLINT(modernize-macro-to-enum) -#define NLOHMANN_JSON_VERSION_PATCH 0 // NOLINT(modernize-macro-to-enum) - -#ifndef JSON_DIAGNOSTICS - #define JSON_DIAGNOSTICS 0 -#endif - -#ifndef JSON_DIAGNOSTIC_POSITIONS - #define JSON_DIAGNOSTIC_POSITIONS 0 -#endif - -#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON - #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 -#endif - -#if JSON_DIAGNOSTICS - #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag -#else - #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS -#endif - -#if JSON_DIAGNOSTIC_POSITIONS - #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS _dp -#else - #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS -#endif - -#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON - #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp -#else - #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON -#endif - -#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION - #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 -#endif - -// Construct the namespace ABI tags component -#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) json_abi ## a ## b ## c -#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c) \ - NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) - -#define NLOHMANN_JSON_ABI_TAGS \ - NLOHMANN_JSON_ABI_TAGS_CONCAT( \ - NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ - NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON, \ - NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS) - -// Construct the namespace version component -#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ - _v ## major ## _ ## minor ## _ ## patch -#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ - NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) - -#if NLOHMANN_JSON_NAMESPACE_NO_VERSION -#define NLOHMANN_JSON_NAMESPACE_VERSION -#else -#define NLOHMANN_JSON_NAMESPACE_VERSION \ - NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ - NLOHMANN_JSON_VERSION_MINOR, \ - NLOHMANN_JSON_VERSION_PATCH) -#endif - -// Combine namespace components -#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b -#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ - NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) - -#ifndef NLOHMANN_JSON_NAMESPACE -#define NLOHMANN_JSON_NAMESPACE \ - nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ - NLOHMANN_JSON_ABI_TAGS, \ - NLOHMANN_JSON_NAMESPACE_VERSION) -#endif - -#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN -#define NLOHMANN_JSON_NAMESPACE_BEGIN \ - namespace nlohmann \ - { \ - inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ - NLOHMANN_JSON_ABI_TAGS, \ - NLOHMANN_JSON_NAMESPACE_VERSION) \ - { -#endif - -#ifndef NLOHMANN_JSON_NAMESPACE_END -#define NLOHMANN_JSON_NAMESPACE_END \ - } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ - } // namespace nlohmann -#endif - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // transform -#include // array -#include // forward_list -#include // inserter, front_inserter, end -#include // map -#ifdef JSON_HAS_CPP_17 - #include // optional -#endif -#include // string -#include // tuple, make_tuple -#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible -#include // unordered_map -#include // pair, declval -#include // valarray - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // nullptr_t -#include // exception -#if JSON_DIAGNOSTICS - #include // accumulate -#endif -#include // runtime_error -#include // to_string -#include // vector - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // array -#include // size_t -#include // uint8_t -#include // string - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // declval, pair -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -template struct make_void -{ - using type = void; -}; -template using void_t = typename make_void::type; - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -// https://en.cppreference.com/w/cpp/experimental/is_detected -struct nonesuch -{ - nonesuch() = delete; - ~nonesuch() = delete; - nonesuch(nonesuch const&) = delete; - nonesuch(nonesuch const&&) = delete; - void operator=(nonesuch const&) = delete; - void operator=(nonesuch&&) = delete; -}; - -template class Op, - class... Args> -struct detector -{ - using value_t = std::false_type; - using type = Default; -}; - -template class Op, class... Args> -struct detector>, Op, Args...> -{ - using value_t = std::true_type; - using type = Op; -}; - -template class Op, class... Args> -using is_detected = typename detector::value_t; - -template class Op, class... Args> -struct is_detected_lazy : is_detected { }; - -template class Op, class... Args> -using detected_t = typename detector::type; - -template class Op, class... Args> -using detected_or = detector; - -template class Op, class... Args> -using detected_or_t = typename detected_or::type; - -template class Op, class... Args> -using is_detected_exact = std::is_same>; - -template class Op, class... Args> -using is_detected_convertible = - std::is_convertible, To>; - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include - - -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann -// SPDX-FileCopyrightText: 2016 - 2021 Evan Nemerson -// SPDX-License-Identifier: MIT - -/* Hedley - https://nemequ.github.io/hedley - * Created by Evan Nemerson - */ - -#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) -#if defined(JSON_HEDLEY_VERSION) - #undef JSON_HEDLEY_VERSION -#endif -#define JSON_HEDLEY_VERSION 15 - -#if defined(JSON_HEDLEY_STRINGIFY_EX) - #undef JSON_HEDLEY_STRINGIFY_EX -#endif -#define JSON_HEDLEY_STRINGIFY_EX(x) #x - -#if defined(JSON_HEDLEY_STRINGIFY) - #undef JSON_HEDLEY_STRINGIFY -#endif -#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) - -#if defined(JSON_HEDLEY_CONCAT_EX) - #undef JSON_HEDLEY_CONCAT_EX -#endif -#define JSON_HEDLEY_CONCAT_EX(a,b) a##b - -#if defined(JSON_HEDLEY_CONCAT) - #undef JSON_HEDLEY_CONCAT -#endif -#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) - -#if defined(JSON_HEDLEY_CONCAT3_EX) - #undef JSON_HEDLEY_CONCAT3_EX -#endif -#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c - -#if defined(JSON_HEDLEY_CONCAT3) - #undef JSON_HEDLEY_CONCAT3 -#endif -#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) - -#if defined(JSON_HEDLEY_VERSION_ENCODE) - #undef JSON_HEDLEY_VERSION_ENCODE -#endif -#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) - -#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) - #undef JSON_HEDLEY_VERSION_DECODE_MAJOR -#endif -#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) - -#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) - #undef JSON_HEDLEY_VERSION_DECODE_MINOR -#endif -#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) - -#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) - #undef JSON_HEDLEY_VERSION_DECODE_REVISION -#endif -#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) - -#if defined(JSON_HEDLEY_GNUC_VERSION) - #undef JSON_HEDLEY_GNUC_VERSION -#endif -#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) - #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) -#elif defined(__GNUC__) - #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) -#endif - -#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) - #undef JSON_HEDLEY_GNUC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_GNUC_VERSION) - #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_MSVC_VERSION) - #undef JSON_HEDLEY_MSVC_VERSION -#endif -#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) -#elif defined(_MSC_FULL_VER) && !defined(__ICL) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) -#elif defined(_MSC_VER) && !defined(__ICL) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) -#endif - -#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) - #undef JSON_HEDLEY_MSVC_VERSION_CHECK -#endif -#if !defined(JSON_HEDLEY_MSVC_VERSION) - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) -#elif defined(_MSC_VER) && (_MSC_VER >= 1400) - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) -#elif defined(_MSC_VER) && (_MSC_VER >= 1200) - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) -#else - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) -#endif - -#if defined(JSON_HEDLEY_INTEL_VERSION) - #undef JSON_HEDLEY_INTEL_VERSION -#endif -#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) - #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) -#elif defined(__INTEL_COMPILER) && !defined(__ICL) - #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) -#endif - -#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) - #undef JSON_HEDLEY_INTEL_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_INTEL_VERSION) - #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_INTEL_CL_VERSION) - #undef JSON_HEDLEY_INTEL_CL_VERSION -#endif -#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) - #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) -#endif - -#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) - #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_INTEL_CL_VERSION) - #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_PGI_VERSION) - #undef JSON_HEDLEY_PGI_VERSION -#endif -#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) - #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) -#endif - -#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) - #undef JSON_HEDLEY_PGI_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_PGI_VERSION) - #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_SUNPRO_VERSION) - #undef JSON_HEDLEY_SUNPRO_VERSION -#endif -#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) -#elif defined(__SUNPRO_C) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) -#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) -#elif defined(__SUNPRO_CC) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) -#endif - -#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) - #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_SUNPRO_VERSION) - #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) - #undef JSON_HEDLEY_EMSCRIPTEN_VERSION -#endif -#if defined(__EMSCRIPTEN__) - #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) -#endif - -#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) - #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) - #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_ARM_VERSION) - #undef JSON_HEDLEY_ARM_VERSION -#endif -#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) - #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) -#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) - #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) -#endif - -#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) - #undef JSON_HEDLEY_ARM_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_ARM_VERSION) - #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_IBM_VERSION) - #undef JSON_HEDLEY_IBM_VERSION -#endif -#if defined(__ibmxl__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) -#elif defined(__xlC__) && defined(__xlC_ver__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) -#elif defined(__xlC__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) -#endif - -#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) - #undef JSON_HEDLEY_IBM_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_IBM_VERSION) - #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_VERSION) - #undef JSON_HEDLEY_TI_VERSION -#endif -#if \ - defined(__TI_COMPILER_VERSION__) && \ - ( \ - defined(__TMS470__) || defined(__TI_ARM__) || \ - defined(__MSP430__) || \ - defined(__TMS320C2000__) \ - ) -#if (__TI_COMPILER_VERSION__ >= 16000000) - #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif -#endif - -#if defined(JSON_HEDLEY_TI_VERSION_CHECK) - #undef JSON_HEDLEY_TI_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_VERSION) - #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL2000_VERSION) - #undef JSON_HEDLEY_TI_CL2000_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) - #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL2000_VERSION) - #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL430_VERSION) - #undef JSON_HEDLEY_TI_CL430_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) - #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL430_VERSION) - #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) - #undef JSON_HEDLEY_TI_ARMCL_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) - #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) - #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) - #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL6X_VERSION) - #undef JSON_HEDLEY_TI_CL6X_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) - #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL6X_VERSION) - #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL7X_VERSION) - #undef JSON_HEDLEY_TI_CL7X_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) - #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL7X_VERSION) - #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) - #undef JSON_HEDLEY_TI_CLPRU_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) - #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) - #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_CRAY_VERSION) - #undef JSON_HEDLEY_CRAY_VERSION -#endif -#if defined(_CRAYC) - #if defined(_RELEASE_PATCHLEVEL) - #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) - #else - #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) - #endif -#endif - -#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) - #undef JSON_HEDLEY_CRAY_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_CRAY_VERSION) - #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_IAR_VERSION) - #undef JSON_HEDLEY_IAR_VERSION -#endif -#if defined(__IAR_SYSTEMS_ICC__) - #if __VER__ > 1000 - #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) - #else - #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) - #endif -#endif - -#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) - #undef JSON_HEDLEY_IAR_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_IAR_VERSION) - #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TINYC_VERSION) - #undef JSON_HEDLEY_TINYC_VERSION -#endif -#if defined(__TINYC__) - #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) -#endif - -#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) - #undef JSON_HEDLEY_TINYC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TINYC_VERSION) - #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_DMC_VERSION) - #undef JSON_HEDLEY_DMC_VERSION -#endif -#if defined(__DMC__) - #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) -#endif - -#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) - #undef JSON_HEDLEY_DMC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_DMC_VERSION) - #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_COMPCERT_VERSION) - #undef JSON_HEDLEY_COMPCERT_VERSION -#endif -#if defined(__COMPCERT_VERSION__) - #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) -#endif - -#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) - #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_COMPCERT_VERSION) - #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_PELLES_VERSION) - #undef JSON_HEDLEY_PELLES_VERSION -#endif -#if defined(__POCC__) - #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) -#endif - -#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) - #undef JSON_HEDLEY_PELLES_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_PELLES_VERSION) - #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_MCST_LCC_VERSION) - #undef JSON_HEDLEY_MCST_LCC_VERSION -#endif -#if defined(__LCC__) && defined(__LCC_MINOR__) - #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) -#endif - -#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) - #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_MCST_LCC_VERSION) - #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_GCC_VERSION) - #undef JSON_HEDLEY_GCC_VERSION -#endif -#if \ - defined(JSON_HEDLEY_GNUC_VERSION) && \ - !defined(__clang__) && \ - !defined(JSON_HEDLEY_INTEL_VERSION) && \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_ARM_VERSION) && \ - !defined(JSON_HEDLEY_CRAY_VERSION) && \ - !defined(JSON_HEDLEY_TI_VERSION) && \ - !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ - !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ - !defined(__COMPCERT__) && \ - !defined(JSON_HEDLEY_MCST_LCC_VERSION) - #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION -#endif - -#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) - #undef JSON_HEDLEY_GCC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_GCC_VERSION) - #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_ATTRIBUTE -#endif -#if \ - defined(__has_attribute) && \ - ( \ - (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ - ) -# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) -#else -# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE -#endif -#if defined(__has_attribute) - #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) -#else - #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE -#endif -#if defined(__has_attribute) - #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) -#else - #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE -#endif -#if \ - defined(__has_cpp_attribute) && \ - defined(__cplusplus) && \ - (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) -#else - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) -#endif - -#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) - #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS -#endif -#if !defined(__cplusplus) || !defined(__has_cpp_attribute) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) -#elif \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_IAR_VERSION) && \ - (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ - (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) -#else - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE -#endif -#if defined(__has_cpp_attribute) && defined(__cplusplus) - #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) -#else - #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE -#endif -#if defined(__has_cpp_attribute) && defined(__cplusplus) - #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) -#else - #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_BUILTIN) - #undef JSON_HEDLEY_HAS_BUILTIN -#endif -#if defined(__has_builtin) - #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) -#else - #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) - #undef JSON_HEDLEY_GNUC_HAS_BUILTIN -#endif -#if defined(__has_builtin) - #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) -#else - #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) - #undef JSON_HEDLEY_GCC_HAS_BUILTIN -#endif -#if defined(__has_builtin) - #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) -#else - #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_FEATURE) - #undef JSON_HEDLEY_HAS_FEATURE -#endif -#if defined(__has_feature) - #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) -#else - #define JSON_HEDLEY_HAS_FEATURE(feature) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) - #undef JSON_HEDLEY_GNUC_HAS_FEATURE -#endif -#if defined(__has_feature) - #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) -#else - #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) - #undef JSON_HEDLEY_GCC_HAS_FEATURE -#endif -#if defined(__has_feature) - #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) -#else - #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_EXTENSION) - #undef JSON_HEDLEY_HAS_EXTENSION -#endif -#if defined(__has_extension) - #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) -#else - #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) - #undef JSON_HEDLEY_GNUC_HAS_EXTENSION -#endif -#if defined(__has_extension) - #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) -#else - #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) - #undef JSON_HEDLEY_GCC_HAS_EXTENSION -#endif -#if defined(__has_extension) - #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) -#else - #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE -#endif -#if defined(__has_declspec_attribute) - #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) -#else - #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE -#endif -#if defined(__has_declspec_attribute) - #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) -#else - #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE -#endif -#if defined(__has_declspec_attribute) - #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) -#else - #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_WARNING) - #undef JSON_HEDLEY_HAS_WARNING -#endif -#if defined(__has_warning) - #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) -#else - #define JSON_HEDLEY_HAS_WARNING(warning) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) - #undef JSON_HEDLEY_GNUC_HAS_WARNING -#endif -#if defined(__has_warning) - #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) -#else - #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_WARNING) - #undef JSON_HEDLEY_GCC_HAS_WARNING -#endif -#if defined(__has_warning) - #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) -#else - #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ - defined(__clang__) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ - (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) - #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_PRAGMA(value) __pragma(value) -#else - #define JSON_HEDLEY_PRAGMA(value) -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) - #undef JSON_HEDLEY_DIAGNOSTIC_PUSH -#endif -#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) - #undef JSON_HEDLEY_DIAGNOSTIC_POP -#endif -#if defined(__clang__) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) - #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) -#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") -#else - #define JSON_HEDLEY_DIAGNOSTIC_PUSH - #define JSON_HEDLEY_DIAGNOSTIC_POP -#endif - -/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for - HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ -#endif -#if defined(__cplusplus) -# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") -# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") -# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ - _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ - _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ - xpr \ - JSON_HEDLEY_DIAGNOSTIC_POP -# else -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ - _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ - xpr \ - JSON_HEDLEY_DIAGNOSTIC_POP -# endif -# else -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ - xpr \ - JSON_HEDLEY_DIAGNOSTIC_POP -# endif -# endif -#endif -#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x -#endif - -#if defined(JSON_HEDLEY_CONST_CAST) - #undef JSON_HEDLEY_CONST_CAST -#endif -#if defined(__cplusplus) -# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) -#elif \ - JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) -# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ - ((T) (expr)); \ - JSON_HEDLEY_DIAGNOSTIC_POP \ - })) -#else -# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) -#endif - -#if defined(JSON_HEDLEY_REINTERPRET_CAST) - #undef JSON_HEDLEY_REINTERPRET_CAST -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) -#else - #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) -#endif - -#if defined(JSON_HEDLEY_STATIC_CAST) - #undef JSON_HEDLEY_STATIC_CAST -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) -#else - #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) -#endif - -#if defined(JSON_HEDLEY_CPP_CAST) - #undef JSON_HEDLEY_CPP_CAST -#endif -#if defined(__cplusplus) -# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") -# define JSON_HEDLEY_CPP_CAST(T, expr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ - ((T) (expr)) \ - JSON_HEDLEY_DIAGNOSTIC_POP -# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) -# define JSON_HEDLEY_CPP_CAST(T, expr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("diag_suppress=Pe137") \ - JSON_HEDLEY_DIAGNOSTIC_POP -# else -# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) -# endif -#else -# define JSON_HEDLEY_CPP_CAST(T, expr) (expr) -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") -#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) -#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") -#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") -#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") -#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") -#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") -#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunused-function") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) -#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION -#endif - -#if defined(JSON_HEDLEY_DEPRECATED) - #undef JSON_HEDLEY_DEPRECATED -#endif -#if defined(JSON_HEDLEY_DEPRECATED_FOR) - #undef JSON_HEDLEY_DEPRECATED_FOR -#endif -#if \ - JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) -#elif \ - (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) -#elif defined(__cplusplus) && (__cplusplus >= 201402L) - #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) -#elif \ - JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) - #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") -#else - #define JSON_HEDLEY_DEPRECATED(since) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) -#endif - -#if defined(JSON_HEDLEY_UNAVAILABLE) - #undef JSON_HEDLEY_UNAVAILABLE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) -#else - #define JSON_HEDLEY_UNAVAILABLE(available_since) -#endif - -#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) - #undef JSON_HEDLEY_WARN_UNUSED_RESULT -#endif -#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) - #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) -#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) - #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) -#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) - #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) -#elif defined(_Check_return_) /* SAL */ - #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ -#else - #define JSON_HEDLEY_WARN_UNUSED_RESULT - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) -#endif - -#if defined(JSON_HEDLEY_SENTINEL) - #undef JSON_HEDLEY_SENTINEL -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) -#else - #define JSON_HEDLEY_SENTINEL(position) -#endif - -#if defined(JSON_HEDLEY_NO_RETURN) - #undef JSON_HEDLEY_NO_RETURN -#endif -#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_NO_RETURN __noreturn -#elif \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) -#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L - #define JSON_HEDLEY_NO_RETURN _Noreturn -#elif defined(__cplusplus) && (__cplusplus >= 201103L) - #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) -#elif \ - JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) - #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) -#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) - #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") -#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) - #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) - #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) -#else - #define JSON_HEDLEY_NO_RETURN -#endif - -#if defined(JSON_HEDLEY_NO_ESCAPE) - #undef JSON_HEDLEY_NO_ESCAPE -#endif -#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) - #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) -#else - #define JSON_HEDLEY_NO_ESCAPE -#endif - -#if defined(JSON_HEDLEY_UNREACHABLE) - #undef JSON_HEDLEY_UNREACHABLE -#endif -#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) - #undef JSON_HEDLEY_UNREACHABLE_RETURN -#endif -#if defined(JSON_HEDLEY_ASSUME) - #undef JSON_HEDLEY_ASSUME -#endif -#if \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_ASSUME(expr) __assume(expr) -#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) - #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) -#elif \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) - #if defined(__cplusplus) - #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) - #else - #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) - #endif -#endif -#if \ - (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() -#elif defined(JSON_HEDLEY_ASSUME) - #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) -#endif -#if !defined(JSON_HEDLEY_ASSUME) - #if defined(JSON_HEDLEY_UNREACHABLE) - #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) - #else - #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) - #endif -#endif -#if defined(JSON_HEDLEY_UNREACHABLE) - #if \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) - #else - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() - #endif -#else - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) -#endif -#if !defined(JSON_HEDLEY_UNREACHABLE) - #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) -#endif - -JSON_HEDLEY_DIAGNOSTIC_PUSH -#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") - #pragma clang diagnostic ignored "-Wpedantic" -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) - #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -#endif -#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) - #if defined(__clang__) - #pragma clang diagnostic ignored "-Wvariadic-macros" - #elif defined(JSON_HEDLEY_GCC_VERSION) - #pragma GCC diagnostic ignored "-Wvariadic-macros" - #endif -#endif -#if defined(JSON_HEDLEY_NON_NULL) - #undef JSON_HEDLEY_NON_NULL -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) - #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) -#else - #define JSON_HEDLEY_NON_NULL(...) -#endif -JSON_HEDLEY_DIAGNOSTIC_POP - -#if defined(JSON_HEDLEY_PRINTF_FORMAT) - #undef JSON_HEDLEY_PRINTF_FORMAT -#endif -#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) -#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) -#elif \ - JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) -#else - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) -#endif - -#if defined(JSON_HEDLEY_CONSTEXPR) - #undef JSON_HEDLEY_CONSTEXPR -#endif -#if defined(__cplusplus) - #if __cplusplus >= 201103L - #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) - #endif -#endif -#if !defined(JSON_HEDLEY_CONSTEXPR) - #define JSON_HEDLEY_CONSTEXPR -#endif - -#if defined(JSON_HEDLEY_PREDICT) - #undef JSON_HEDLEY_PREDICT -#endif -#if defined(JSON_HEDLEY_LIKELY) - #undef JSON_HEDLEY_LIKELY -#endif -#if defined(JSON_HEDLEY_UNLIKELY) - #undef JSON_HEDLEY_UNLIKELY -#endif -#if defined(JSON_HEDLEY_UNPREDICTABLE) - #undef JSON_HEDLEY_UNPREDICTABLE -#endif -#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) - #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) -#endif -#if \ - (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) -# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) -# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) -# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) -# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) -# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) -#elif \ - (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) -# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ - (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) -# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ - (__extension__ ({ \ - double hedley_probability_ = (probability); \ - ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ - })) -# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ - (__extension__ ({ \ - double hedley_probability_ = (probability); \ - ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ - })) -# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) -# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) -#else -# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) -# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) -# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) -# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) -# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) -#endif -#if !defined(JSON_HEDLEY_UNPREDICTABLE) - #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) -#endif - -#if defined(JSON_HEDLEY_MALLOC) - #undef JSON_HEDLEY_MALLOC -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_MALLOC __declspec(restrict) -#else - #define JSON_HEDLEY_MALLOC -#endif - -#if defined(JSON_HEDLEY_PURE) - #undef JSON_HEDLEY_PURE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) -# define JSON_HEDLEY_PURE __attribute__((__pure__)) -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) -# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") -#elif defined(__cplusplus) && \ - ( \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ - ) -# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") -#else -# define JSON_HEDLEY_PURE -#endif - -#if defined(JSON_HEDLEY_CONST) - #undef JSON_HEDLEY_CONST -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_CONST __attribute__((__const__)) -#elif \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_CONST _Pragma("no_side_effect") -#else - #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE -#endif - -#if defined(JSON_HEDLEY_RESTRICT) - #undef JSON_HEDLEY_RESTRICT -#endif -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) - #define JSON_HEDLEY_RESTRICT restrict -#elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ - defined(__clang__) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_RESTRICT __restrict -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) - #define JSON_HEDLEY_RESTRICT _Restrict -#else - #define JSON_HEDLEY_RESTRICT -#endif - -#if defined(JSON_HEDLEY_INLINE) - #undef JSON_HEDLEY_INLINE -#endif -#if \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ - (defined(__cplusplus) && (__cplusplus >= 199711L)) - #define JSON_HEDLEY_INLINE inline -#elif \ - defined(JSON_HEDLEY_GCC_VERSION) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) - #define JSON_HEDLEY_INLINE __inline__ -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_INLINE __inline -#else - #define JSON_HEDLEY_INLINE -#endif - -#if defined(JSON_HEDLEY_ALWAYS_INLINE) - #undef JSON_HEDLEY_ALWAYS_INLINE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) -# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) -# define JSON_HEDLEY_ALWAYS_INLINE __forceinline -#elif defined(__cplusplus) && \ - ( \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ - ) -# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) -# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") -#else -# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE -#endif - -#if defined(JSON_HEDLEY_NEVER_INLINE) - #undef JSON_HEDLEY_NEVER_INLINE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) - #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) - #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") -#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) - #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") -#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) - #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) - #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) -#else - #define JSON_HEDLEY_NEVER_INLINE -#endif - -#if defined(JSON_HEDLEY_PRIVATE) - #undef JSON_HEDLEY_PRIVATE -#endif -#if defined(JSON_HEDLEY_PUBLIC) - #undef JSON_HEDLEY_PUBLIC -#endif -#if defined(JSON_HEDLEY_IMPORT) - #undef JSON_HEDLEY_IMPORT -#endif -#if defined(_WIN32) || defined(__CYGWIN__) -# define JSON_HEDLEY_PRIVATE -# define JSON_HEDLEY_PUBLIC __declspec(dllexport) -# define JSON_HEDLEY_IMPORT __declspec(dllimport) -#else -# if \ - JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - ( \ - defined(__TI_EABI__) && \ - ( \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ - ) \ - ) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) -# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) -# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) -# else -# define JSON_HEDLEY_PRIVATE -# define JSON_HEDLEY_PUBLIC -# endif -# define JSON_HEDLEY_IMPORT extern -#endif - -#if defined(JSON_HEDLEY_NO_THROW) - #undef JSON_HEDLEY_NO_THROW -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) - #define JSON_HEDLEY_NO_THROW __declspec(nothrow) -#else - #define JSON_HEDLEY_NO_THROW -#endif - -#if defined(JSON_HEDLEY_FALL_THROUGH) - #undef JSON_HEDLEY_FALL_THROUGH -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) -#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) - #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) -#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) - #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) -#elif defined(__fallthrough) /* SAL */ - #define JSON_HEDLEY_FALL_THROUGH __fallthrough -#else - #define JSON_HEDLEY_FALL_THROUGH -#endif - -#if defined(JSON_HEDLEY_RETURNS_NON_NULL) - #undef JSON_HEDLEY_RETURNS_NON_NULL -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) -#elif defined(_Ret_notnull_) /* SAL */ - #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ -#else - #define JSON_HEDLEY_RETURNS_NON_NULL -#endif - -#if defined(JSON_HEDLEY_ARRAY_PARAM) - #undef JSON_HEDLEY_ARRAY_PARAM -#endif -#if \ - defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - !defined(__STDC_NO_VLA__) && \ - !defined(__cplusplus) && \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_TINYC_VERSION) - #define JSON_HEDLEY_ARRAY_PARAM(name) (name) -#else - #define JSON_HEDLEY_ARRAY_PARAM(name) -#endif - -#if defined(JSON_HEDLEY_IS_CONSTANT) - #undef JSON_HEDLEY_IS_CONSTANT -#endif -#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) - #undef JSON_HEDLEY_REQUIRE_CONSTEXPR -#endif -/* JSON_HEDLEY_IS_CONSTEXPR_ is for - HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ -#if defined(JSON_HEDLEY_IS_CONSTEXPR_) - #undef JSON_HEDLEY_IS_CONSTEXPR_ -#endif -#if \ - JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) - #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) -#endif -#if !defined(__cplusplus) -# if \ - JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) -#if defined(__INTPTR_TYPE__) - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) -#else - #include - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) -#endif -# elif \ - ( \ - defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ - !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_IAR_VERSION)) || \ - (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) -#if defined(__INTPTR_TYPE__) - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) -#else - #include - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) -#endif -# elif \ - defined(JSON_HEDLEY_GCC_VERSION) || \ - defined(JSON_HEDLEY_INTEL_VERSION) || \ - defined(JSON_HEDLEY_TINYC_VERSION) || \ - defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ - defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ - defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ - defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ - defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ - defined(__clang__) -# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ - sizeof(void) != \ - sizeof(*( \ - 1 ? \ - ((void*) ((expr) * 0L) ) : \ -((struct { char v[sizeof(void) * 2]; } *) 1) \ - ) \ - ) \ - ) -# endif -#endif -#if defined(JSON_HEDLEY_IS_CONSTEXPR_) - #if !defined(JSON_HEDLEY_IS_CONSTANT) - #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) - #endif - #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) -#else - #if !defined(JSON_HEDLEY_IS_CONSTANT) - #define JSON_HEDLEY_IS_CONSTANT(expr) (0) - #endif - #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) -#endif - -#if defined(JSON_HEDLEY_BEGIN_C_DECLS) - #undef JSON_HEDLEY_BEGIN_C_DECLS -#endif -#if defined(JSON_HEDLEY_END_C_DECLS) - #undef JSON_HEDLEY_END_C_DECLS -#endif -#if defined(JSON_HEDLEY_C_DECL) - #undef JSON_HEDLEY_C_DECL -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { - #define JSON_HEDLEY_END_C_DECLS } - #define JSON_HEDLEY_C_DECL extern "C" -#else - #define JSON_HEDLEY_BEGIN_C_DECLS - #define JSON_HEDLEY_END_C_DECLS - #define JSON_HEDLEY_C_DECL -#endif - -#if defined(JSON_HEDLEY_STATIC_ASSERT) - #undef JSON_HEDLEY_STATIC_ASSERT -#endif -#if \ - !defined(__cplusplus) && ( \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ - (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - defined(_Static_assert) \ - ) -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) -#elif \ - (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ - JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) -#else -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) -#endif - -#if defined(JSON_HEDLEY_NULL) - #undef JSON_HEDLEY_NULL -#endif -#if defined(__cplusplus) - #if __cplusplus >= 201103L - #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) - #elif defined(NULL) - #define JSON_HEDLEY_NULL NULL - #else - #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) - #endif -#elif defined(NULL) - #define JSON_HEDLEY_NULL NULL -#else - #define JSON_HEDLEY_NULL ((void*) 0) -#endif - -#if defined(JSON_HEDLEY_MESSAGE) - #undef JSON_HEDLEY_MESSAGE -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") -# define JSON_HEDLEY_MESSAGE(msg) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ - JSON_HEDLEY_PRAGMA(message msg) \ - JSON_HEDLEY_DIAGNOSTIC_POP -#elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) -#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) -#else -# define JSON_HEDLEY_MESSAGE(msg) -#endif - -#if defined(JSON_HEDLEY_WARNING) - #undef JSON_HEDLEY_WARNING -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") -# define JSON_HEDLEY_WARNING(msg) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ - JSON_HEDLEY_PRAGMA(clang warning msg) \ - JSON_HEDLEY_DIAGNOSTIC_POP -#elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) -# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) -# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) -#else -# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) -#endif - -#if defined(JSON_HEDLEY_REQUIRE) - #undef JSON_HEDLEY_REQUIRE -#endif -#if defined(JSON_HEDLEY_REQUIRE_MSG) - #undef JSON_HEDLEY_REQUIRE_MSG -#endif -#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) -# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") -# define JSON_HEDLEY_REQUIRE(expr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ - __attribute__((diagnose_if(!(expr), #expr, "error"))) \ - JSON_HEDLEY_DIAGNOSTIC_POP -# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ - __attribute__((diagnose_if(!(expr), msg, "error"))) \ - JSON_HEDLEY_DIAGNOSTIC_POP -# else -# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) -# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) -# endif -#else -# define JSON_HEDLEY_REQUIRE(expr) -# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) -#endif - -#if defined(JSON_HEDLEY_FLAGS) - #undef JSON_HEDLEY_FLAGS -#endif -#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) - #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) -#else - #define JSON_HEDLEY_FLAGS -#endif - -#if defined(JSON_HEDLEY_FLAGS_CAST) - #undef JSON_HEDLEY_FLAGS_CAST -#endif -#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) -# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("warning(disable:188)") \ - ((T) (expr)); \ - JSON_HEDLEY_DIAGNOSTIC_POP \ - })) -#else -# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) -#endif - -#if defined(JSON_HEDLEY_EMPTY_BASES) - #undef JSON_HEDLEY_EMPTY_BASES -#endif -#if \ - (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) -#else - #define JSON_HEDLEY_EMPTY_BASES -#endif - -/* Remaining macros are deprecated. */ - -#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) - #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK -#endif -#if defined(__clang__) - #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) -#else - #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE -#endif -#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) - -#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE -#endif -#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) - -#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) - #undef JSON_HEDLEY_CLANG_HAS_BUILTIN -#endif -#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) - -#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) - #undef JSON_HEDLEY_CLANG_HAS_FEATURE -#endif -#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) - -#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) - #undef JSON_HEDLEY_CLANG_HAS_EXTENSION -#endif -#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) - -#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE -#endif -#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) - -#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) - #undef JSON_HEDLEY_CLANG_HAS_WARNING -#endif -#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) - -#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ - - -// This file contains all internal macro definitions (except those affecting ABI) -// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them - -// #include - - -// exclude unsupported compilers -#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) - #if defined(__clang__) - #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 - #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" - #endif - #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) - #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 - #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" - #endif - #endif -#endif - -// C++ language standard detection -// if the user manually specified the used c++ version this is skipped -#if !defined(JSON_HAS_CPP_23) && !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) - #if (defined(__cplusplus) && __cplusplus > 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG > 202002L) - #define JSON_HAS_CPP_23 - #define JSON_HAS_CPP_20 - #define JSON_HAS_CPP_17 - #define JSON_HAS_CPP_14 - #elif (defined(__cplusplus) && __cplusplus > 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG > 201703L) - #define JSON_HAS_CPP_20 - #define JSON_HAS_CPP_17 - #define JSON_HAS_CPP_14 - #elif (defined(__cplusplus) && __cplusplus > 201402L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 - #define JSON_HAS_CPP_17 - #define JSON_HAS_CPP_14 - #elif (defined(__cplusplus) && __cplusplus > 201103L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) - #define JSON_HAS_CPP_14 - #endif - // the cpp 11 flag is always specified because it is the minimal required version - #define JSON_HAS_CPP_11 -#endif - -#ifdef __has_include - #if __has_include() - #include - #endif -#endif - -#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) - #ifdef JSON_HAS_CPP_17 - #if defined(__cpp_lib_filesystem) - #define JSON_HAS_FILESYSTEM 1 - #elif defined(__cpp_lib_experimental_filesystem) - #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 - #elif !defined(__has_include) - #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 - #elif __has_include() - #define JSON_HAS_FILESYSTEM 1 - #elif __has_include() - #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 - #endif - - // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ - #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support - #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support - #if defined(__clang_major__) && __clang_major__ < 7 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support - #if defined(_MSC_VER) && _MSC_VER < 1914 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before iOS 13 - #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - - // no filesystem support before macOS Catalina - #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 - #undef JSON_HAS_FILESYSTEM - #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #endif - #endif -#endif - -#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM - #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 -#endif - -#ifndef JSON_HAS_FILESYSTEM - #define JSON_HAS_FILESYSTEM 0 -#endif - -#ifndef JSON_HAS_THREE_WAY_COMPARISON - #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ - && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L - #define JSON_HAS_THREE_WAY_COMPARISON 1 - #else - #define JSON_HAS_THREE_WAY_COMPARISON 0 - #endif -#endif - -#ifndef JSON_HAS_RANGES - // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error - #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 - #define JSON_HAS_RANGES 0 - #elif defined(__cpp_lib_ranges) - #define JSON_HAS_RANGES 1 - #else - #define JSON_HAS_RANGES 0 - #endif -#endif - -#ifndef JSON_HAS_STATIC_RTTI - #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0 - #define JSON_HAS_STATIC_RTTI 1 - #else - #define JSON_HAS_STATIC_RTTI 0 - #endif -#endif - -#ifdef JSON_HAS_CPP_17 - #define JSON_INLINE_VARIABLE inline -#else - #define JSON_INLINE_VARIABLE -#endif - -#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) - #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] -#else - #define JSON_NO_UNIQUE_ADDRESS -#endif - -// disable documentation warnings on clang -#if defined(__clang__) - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wdocumentation" - #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" -#endif - -// allow disabling exceptions -#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) - #define JSON_THROW(exception) throw exception - #define JSON_TRY try - #define JSON_CATCH(exception) catch(exception) - #define JSON_INTERNAL_CATCH(exception) catch(exception) -#else - #include - #define JSON_THROW(exception) std::abort() - #define JSON_TRY if(true) - #define JSON_CATCH(exception) if(false) - #define JSON_INTERNAL_CATCH(exception) if(false) -#endif - -// override exception macros -#if defined(JSON_THROW_USER) - #undef JSON_THROW - #define JSON_THROW JSON_THROW_USER -#endif -#if defined(JSON_TRY_USER) - #undef JSON_TRY - #define JSON_TRY JSON_TRY_USER -#endif -#if defined(JSON_CATCH_USER) - #undef JSON_CATCH - #define JSON_CATCH JSON_CATCH_USER - #undef JSON_INTERNAL_CATCH - #define JSON_INTERNAL_CATCH JSON_CATCH_USER -#endif -#if defined(JSON_INTERNAL_CATCH_USER) - #undef JSON_INTERNAL_CATCH - #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER -#endif - -// allow overriding assert -#if !defined(JSON_ASSERT) - #include // assert - #define JSON_ASSERT(x) assert(x) -#endif - -// allow to access some private functions (needed by the test suite) -#if defined(JSON_TESTS_PRIVATE) - #define JSON_PRIVATE_UNLESS_TESTED public -#else - #define JSON_PRIVATE_UNLESS_TESTED private -#endif - -/*! -@brief macro to briefly define a mapping between an enum and JSON -@def NLOHMANN_JSON_SERIALIZE_ENUM -@since version 3.4.0 -*/ -#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ - template \ - inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ - { \ - /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [e](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.first == e; \ - }); \ - j = ((it != std::end(m)) ? it : std::begin(m))->second; \ - } \ - template \ - inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ - { \ - /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on */ \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [&j](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.second == j; \ - }); \ - e = ((it != std::end(m)) ? it : std::begin(m))->first; \ - } - -// Ugly macros to avoid uglier copy-paste when specializing basic_json. They -// may be removed in the future once the class is split. - -#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ - template class ObjectType, \ - template class ArrayType, \ - class StringType, class BooleanType, class NumberIntegerType, \ - class NumberUnsignedType, class NumberFloatType, \ - template class AllocatorType, \ - template class JSONSerializer, \ - class BinaryType, \ - class CustomBaseClass> - -#define NLOHMANN_BASIC_JSON_TPL \ - basic_json - -// Macros to simplify conversion from/to types - -#define NLOHMANN_JSON_EXPAND( x ) x -#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME -#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ - NLOHMANN_JSON_PASTE64, \ - NLOHMANN_JSON_PASTE63, \ - NLOHMANN_JSON_PASTE62, \ - NLOHMANN_JSON_PASTE61, \ - NLOHMANN_JSON_PASTE60, \ - NLOHMANN_JSON_PASTE59, \ - NLOHMANN_JSON_PASTE58, \ - NLOHMANN_JSON_PASTE57, \ - NLOHMANN_JSON_PASTE56, \ - NLOHMANN_JSON_PASTE55, \ - NLOHMANN_JSON_PASTE54, \ - NLOHMANN_JSON_PASTE53, \ - NLOHMANN_JSON_PASTE52, \ - NLOHMANN_JSON_PASTE51, \ - NLOHMANN_JSON_PASTE50, \ - NLOHMANN_JSON_PASTE49, \ - NLOHMANN_JSON_PASTE48, \ - NLOHMANN_JSON_PASTE47, \ - NLOHMANN_JSON_PASTE46, \ - NLOHMANN_JSON_PASTE45, \ - NLOHMANN_JSON_PASTE44, \ - NLOHMANN_JSON_PASTE43, \ - NLOHMANN_JSON_PASTE42, \ - NLOHMANN_JSON_PASTE41, \ - NLOHMANN_JSON_PASTE40, \ - NLOHMANN_JSON_PASTE39, \ - NLOHMANN_JSON_PASTE38, \ - NLOHMANN_JSON_PASTE37, \ - NLOHMANN_JSON_PASTE36, \ - NLOHMANN_JSON_PASTE35, \ - NLOHMANN_JSON_PASTE34, \ - NLOHMANN_JSON_PASTE33, \ - NLOHMANN_JSON_PASTE32, \ - NLOHMANN_JSON_PASTE31, \ - NLOHMANN_JSON_PASTE30, \ - NLOHMANN_JSON_PASTE29, \ - NLOHMANN_JSON_PASTE28, \ - NLOHMANN_JSON_PASTE27, \ - NLOHMANN_JSON_PASTE26, \ - NLOHMANN_JSON_PASTE25, \ - NLOHMANN_JSON_PASTE24, \ - NLOHMANN_JSON_PASTE23, \ - NLOHMANN_JSON_PASTE22, \ - NLOHMANN_JSON_PASTE21, \ - NLOHMANN_JSON_PASTE20, \ - NLOHMANN_JSON_PASTE19, \ - NLOHMANN_JSON_PASTE18, \ - NLOHMANN_JSON_PASTE17, \ - NLOHMANN_JSON_PASTE16, \ - NLOHMANN_JSON_PASTE15, \ - NLOHMANN_JSON_PASTE14, \ - NLOHMANN_JSON_PASTE13, \ - NLOHMANN_JSON_PASTE12, \ - NLOHMANN_JSON_PASTE11, \ - NLOHMANN_JSON_PASTE10, \ - NLOHMANN_JSON_PASTE9, \ - NLOHMANN_JSON_PASTE8, \ - NLOHMANN_JSON_PASTE7, \ - NLOHMANN_JSON_PASTE6, \ - NLOHMANN_JSON_PASTE5, \ - NLOHMANN_JSON_PASTE4, \ - NLOHMANN_JSON_PASTE3, \ - NLOHMANN_JSON_PASTE2, \ - NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) -#define NLOHMANN_JSON_PASTE2(func, v1) func(v1) -#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) -#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) -#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) -#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) -#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) -#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) -#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) -#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) -#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) -#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) -#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) -#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) -#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) -#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) -#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) -#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) -#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) -#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) -#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) -#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) -#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) -#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) -#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) -#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) -#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) -#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) -#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) -#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) -#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) -#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) -#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) -#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) -#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) -#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) -#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) -#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) -#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) -#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) -#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) -#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) -#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) -#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) -#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) -#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) -#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) -#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) -#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) -#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) -#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) -#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) -#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) -#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) -#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) -#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) -#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) -#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) -#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) -#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) -#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) -#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) -#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) -#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) - -#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; -#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); -#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = !nlohmann_json_j.is_null() ? nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1) : nlohmann_json_default_obj.v1; - -/*! -@brief macro -@def NLOHMANN_DEFINE_TYPE_INTRUSIVE -@since version 3.9.0 -@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/ -*/ -#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ - template::value, int> = 0> \ - friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } - -/*! -@brief macro -@def NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT -@since version 3.11.0 -@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/ -*/ -#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ - template::value, int> = 0> \ - friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } - -/*! -@brief macro -@def NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE -@since version 3.11.3 -@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/ -*/ -#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ - template::value, int> = 0> \ - friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } - -/*! -@brief macro -@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE -@since version 3.9.0 -@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/ -*/ -#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ - template::value, int> = 0> \ - void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } - -/*! -@brief macro -@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT -@since version 3.11.0 -@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/ -*/ -#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ - template::value, int> = 0> \ - void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } - -/*! -@brief macro -@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE -@since version 3.11.3 -@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/ -*/ -#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ - template::value, int> = 0> \ - void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } - -/*! -@brief macro -@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE -@since version 3.12.0 -@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ -*/ -#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Type, BaseType, ...) \ - template::value, int> = 0> \ - friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } - -/*! -@brief macro -@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT -@since version 3.12.0 -@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ -*/ -#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \ - template::value, int> = 0> \ - friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } - -/*! -@brief macro -@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE -@since version 3.12.0 -@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ -*/ -#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \ - template::value, int> = 0> \ - friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } - -/*! -@brief macro -@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE -@since version 3.12.0 -@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ -*/ -#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(Type, BaseType, ...) \ - template::value, int> = 0> \ - void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } - -/*! -@brief macro -@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT -@since version 3.12.0 -@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ -*/ -#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \ - template::value, int> = 0> \ - void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - template::value, int> = 0> \ - void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } - -/*! -@brief macro -@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE -@since version 3.12.0 -@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/ -*/ -#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \ - template::value, int> = 0> \ - void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } - -// inspired from https://stackoverflow.com/a/26745591 -// allows calling any std function as if (e.g., with begin): -// using std::begin; begin(x); -// -// it allows using the detected idiom to retrieve the return type -// of such an expression -#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ - namespace detail { \ - using std::std_name; \ - \ - template \ - using result_of_##std_name = decltype(std_name(std::declval()...)); \ - } \ - \ - namespace detail2 { \ - struct std_name##_tag \ - { \ - }; \ - \ - template \ - std_name##_tag std_name(T&&...); \ - \ - template \ - using result_of_##std_name = decltype(std_name(std::declval()...)); \ - \ - template \ - struct would_call_std_##std_name \ - { \ - static constexpr auto const value = ::nlohmann::detail:: \ - is_detected_exact::value; \ - }; \ - } /* namespace detail2 */ \ - \ - template \ - struct would_call_std_##std_name : detail2::would_call_std_##std_name \ - { \ - } - -#ifndef JSON_USE_IMPLICIT_CONVERSIONS - #define JSON_USE_IMPLICIT_CONVERSIONS 1 -#endif - -#if JSON_USE_IMPLICIT_CONVERSIONS - #define JSON_EXPLICIT -#else - #define JSON_EXPLICIT explicit -#endif - -#ifndef JSON_DISABLE_ENUM_SERIALIZATION - #define JSON_DISABLE_ENUM_SERIALIZATION 0 -#endif - -#ifndef JSON_USE_GLOBAL_UDLS - #define JSON_USE_GLOBAL_UDLS 1 -#endif - -#if JSON_HAS_THREE_WAY_COMPARISON - #include // partial_ordering -#endif - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -/////////////////////////// -// JSON type enumeration // -/////////////////////////// - -/*! -@brief the JSON type enumeration - -This enumeration collects the different JSON types. It is internally used to -distinguish the stored values, and the functions @ref basic_json::is_null(), -@ref basic_json::is_object(), @ref basic_json::is_array(), -@ref basic_json::is_string(), @ref basic_json::is_boolean(), -@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), -@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), -@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and -@ref basic_json::is_structured() rely on it. - -@note There are three enumeration entries (number_integer, number_unsigned, and -number_float), because the library distinguishes these three types for numbers: -@ref basic_json::number_unsigned_t is used for unsigned integers, -@ref basic_json::number_integer_t is used for signed integers, and -@ref basic_json::number_float_t is used for floating-point numbers or to -approximate integers which do not fit in the limits of their respective type. - -@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON -value with the default value for a given type - -@since version 1.0.0 -*/ -enum class value_t : std::uint8_t -{ - null, ///< null value - object, ///< object (unordered set of name/value pairs) - array, ///< array (ordered collection of values) - string, ///< string value - boolean, ///< boolean value - number_integer, ///< number value (signed integer) - number_unsigned, ///< number value (unsigned integer) - number_float, ///< number value (floating-point) - binary, ///< binary array (ordered collection of bytes) - discarded ///< discarded by the parser callback function -}; - -/*! -@brief comparison operator for JSON types - -Returns an ordering that is similar to Python: -- order: null < boolean < number < object < array < string < binary -- furthermore, each type is not smaller than itself -- discarded values are not comparable -- binary is represented as a b"" string in python and directly comparable to a - string; however, making a binary array directly comparable with a string would - be surprising behavior in a JSON file. - -@since version 1.0.0 -*/ -#if JSON_HAS_THREE_WAY_COMPARISON - inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD* -#else - inline bool operator<(const value_t lhs, const value_t rhs) noexcept -#endif -{ - static constexpr std::array order = {{ - 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, - 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, - 6 /* binary */ - } - }; - - const auto l_index = static_cast(lhs); - const auto r_index = static_cast(rhs); -#if JSON_HAS_THREE_WAY_COMPARISON - if (l_index < order.size() && r_index < order.size()) - { - return order[l_index] <=> order[r_index]; // *NOPAD* - } - return std::partial_ordering::unordered; -#else - return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; -#endif -} - -// GCC selects the built-in operator< over an operator rewritten from -// a user-defined spaceship operator -// Clang, MSVC, and ICC select the rewritten candidate -// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200) -#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__) -inline bool operator<(const value_t lhs, const value_t rhs) noexcept -{ - return std::is_lt(lhs <=> rhs); // *NOPAD* -} -#endif - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -/*! -@brief replace all occurrences of a substring by another string - -@param[in,out] s the string to manipulate; changed so that all - occurrences of @a f are replaced with @a t -@param[in] f the substring to replace with @a t -@param[in] t the string to replace @a f - -@pre The search string @a f must not be empty. **This precondition is -enforced with an assertion.** - -@since version 2.0.0 -*/ -template -inline void replace_substring(StringType& s, const StringType& f, - const StringType& t) -{ - JSON_ASSERT(!f.empty()); - for (auto pos = s.find(f); // find first occurrence of f - pos != StringType::npos; // make sure f was found - s.replace(pos, f.size(), t), // replace with t, and - pos = s.find(f, pos + t.size())) // find next occurrence of f - {} -} - -/*! - * @brief string escaping as described in RFC 6901 (Sect. 4) - * @param[in] s string to escape - * @return escaped string - * - * Note the order of escaping "~" to "~0" and "/" to "~1" is important. - */ -template -inline StringType escape(StringType s) -{ - replace_substring(s, StringType{"~"}, StringType{"~0"}); - replace_substring(s, StringType{"/"}, StringType{"~1"}); - return s; -} - -/*! - * @brief string unescaping as described in RFC 6901 (Sect. 4) - * @param[in] s string to unescape - * @return unescaped string - * - * Note the order of escaping "~1" to "/" and "~0" to "~" is important. - */ -template -static void unescape(StringType& s) -{ - replace_substring(s, StringType{"~1"}, StringType{"/"}); - replace_substring(s, StringType{"~0"}, StringType{"~"}); -} - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // size_t - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -/// struct to capture the start position of the current token -struct position_t -{ - /// the total number of characters read - std::size_t chars_read_total = 0; - /// the number of characters read in the current line - std::size_t chars_read_current_line = 0; - /// the number of lines read - std::size_t lines_read = 0; - - /// conversion to size_t to preserve SAX interface - constexpr operator size_t() const - { - return chars_read_total; - } -}; - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann -// SPDX-FileCopyrightText: 2018 The Abseil Authors -// SPDX-License-Identifier: MIT - - - -#include // array -#include // size_t -#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type -#include // index_sequence, make_index_sequence, index_sequence_for - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -template -using uncvref_t = typename std::remove_cv::type>::type; - -#ifdef JSON_HAS_CPP_14 - -// the following utilities are natively available in C++14 -using std::enable_if_t; -using std::index_sequence; -using std::make_index_sequence; -using std::index_sequence_for; - -#else - -// alias templates to reduce boilerplate -template -using enable_if_t = typename std::enable_if::type; - -// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h -// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. - -//// START OF CODE FROM GOOGLE ABSEIL - -// integer_sequence -// -// Class template representing a compile-time integer sequence. An instantiation -// of `integer_sequence` has a sequence of integers encoded in its -// type through its template arguments (which is a common need when -// working with C++11 variadic templates). `absl::integer_sequence` is designed -// to be a drop-in replacement for C++14's `std::integer_sequence`. -// -// Example: -// -// template< class T, T... Ints > -// void user_function(integer_sequence); -// -// int main() -// { -// // user_function's `T` will be deduced to `int` and `Ints...` -// // will be deduced to `0, 1, 2, 3, 4`. -// user_function(make_integer_sequence()); -// } -template -struct integer_sequence -{ - using value_type = T; - static constexpr std::size_t size() noexcept - { - return sizeof...(Ints); - } -}; - -// index_sequence -// -// A helper template for an `integer_sequence` of `size_t`, -// `absl::index_sequence` is designed to be a drop-in replacement for C++14's -// `std::index_sequence`. -template -using index_sequence = integer_sequence; - -namespace utility_internal -{ - -template -struct Extend; - -// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. -template -struct Extend, SeqSize, 0> -{ - using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; -}; - -template -struct Extend, SeqSize, 1> -{ - using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; -}; - -// Recursion helper for 'make_integer_sequence'. -// 'Gen::type' is an alias for 'integer_sequence'. -template -struct Gen -{ - using type = - typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; -}; - -template -struct Gen -{ - using type = integer_sequence; -}; - -} // namespace utility_internal - -// Compile-time sequences of integers - -// make_integer_sequence -// -// This template alias is equivalent to -// `integer_sequence`, and is designed to be a drop-in -// replacement for C++14's `std::make_integer_sequence`. -template -using make_integer_sequence = typename utility_internal::Gen::type; - -// make_index_sequence -// -// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, -// and is designed to be a drop-in replacement for C++14's -// `std::make_index_sequence`. -template -using make_index_sequence = make_integer_sequence; - -// index_sequence_for -// -// Converts a typename pack into an index sequence of the same length, and -// is designed to be a drop-in replacement for C++14's -// `std::index_sequence_for()` -template -using index_sequence_for = make_index_sequence; - -//// END OF CODE FROM GOOGLE ABSEIL - -#endif - -// dispatch utility (taken from ranges-v3) -template struct priority_tag : priority_tag < N - 1 > {}; -template<> struct priority_tag<0> {}; - -// taken from ranges-v3 -template -struct static_const -{ - static JSON_INLINE_VARIABLE constexpr T value{}; -}; - -#ifndef JSON_HAS_CPP_17 - template - constexpr T static_const::value; -#endif - -template -constexpr std::array make_array(Args&& ... args) -{ - return std::array {{static_cast(std::forward(args))...}}; -} - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // numeric_limits -#include // char_traits -#include // tuple -#include // false_type, is_constructible, is_integral, is_same, true_type -#include // declval - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // random_access_iterator_tag - -// #include - -// #include - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -template -struct iterator_types {}; - -template -struct iterator_types < - It, - void_t> -{ - using difference_type = typename It::difference_type; - using value_type = typename It::value_type; - using pointer = typename It::pointer; - using reference = typename It::reference; - using iterator_category = typename It::iterator_category; -}; - -// This is required as some compilers implement std::iterator_traits in a way that -// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. -template -struct iterator_traits -{ -}; - -template -struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> - : iterator_types -{ -}; - -template -struct iterator_traits::value>> -{ - using iterator_category = std::random_access_iterator_tag; - using value_type = T; - using difference_type = ptrdiff_t; - using pointer = T*; - using reference = T&; -}; - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - -// #include - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN - -NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); - -NLOHMANN_JSON_NAMESPACE_END - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN - -NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); - -NLOHMANN_JSON_NAMESPACE_END - -// #include - -// #include - -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.12.0 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann -// SPDX-License-Identifier: MIT - -#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ - #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ - - #include // int64_t, uint64_t - #include // map - #include // allocator - #include // string - #include // vector - - // #include - - - /*! - @brief namespace for Niels Lohmann - @see https://github.com/nlohmann - @since version 1.0.0 - */ - NLOHMANN_JSON_NAMESPACE_BEGIN - - /*! - @brief default JSONSerializer template argument - - This serializer ignores the template arguments and uses ADL - ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) - for serialization. - */ - template - struct adl_serializer; - - /// a class to store JSON values - /// @sa https://json.nlohmann.me/api/basic_json/ - template class ObjectType = - std::map, - template class ArrayType = std::vector, - class StringType = std::string, class BooleanType = bool, - class NumberIntegerType = std::int64_t, - class NumberUnsignedType = std::uint64_t, - class NumberFloatType = double, - template class AllocatorType = std::allocator, - template class JSONSerializer = - adl_serializer, - class BinaryType = std::vector, // cppcheck-suppress syntaxError - class CustomBaseClass = void> - class basic_json; - - /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document - /// @sa https://json.nlohmann.me/api/json_pointer/ - template - class json_pointer; - - /*! - @brief default specialization - @sa https://json.nlohmann.me/api/json/ - */ - using json = basic_json<>; - - /// @brief a minimal map-like container that preserves insertion order - /// @sa https://json.nlohmann.me/api/ordered_map/ - template - struct ordered_map; - - /// @brief specialization that maintains the insertion order of object keys - /// @sa https://json.nlohmann.me/api/ordered_json/ - using ordered_json = basic_json; - - NLOHMANN_JSON_NAMESPACE_END - -#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ - - -NLOHMANN_JSON_NAMESPACE_BEGIN -/*! -@brief detail namespace with internal helper functions - -This namespace collects functions that should not be exposed, -implementations of some @ref basic_json methods, and meta-programming helpers. - -@since version 2.1.0 -*/ -namespace detail -{ - -///////////// -// helpers // -///////////// - -// Note to maintainers: -// -// Every trait in this file expects a non CV-qualified type. -// The only exceptions are in the 'aliases for detected' section -// (i.e. those of the form: decltype(T::member_function(std::declval()))) -// -// In this case, T has to be properly CV-qualified to constraint the function arguments -// (e.g. to_json(BasicJsonType&, const T&)) - -template struct is_basic_json : std::false_type {}; - -NLOHMANN_BASIC_JSON_TPL_DECLARATION -struct is_basic_json : std::true_type {}; - -// used by exceptions create() member functions -// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t -// false_type otherwise -template -struct is_basic_json_context : - std::integral_constant < bool, - is_basic_json::type>::type>::value - || std::is_same::value > -{}; - -////////////////////// -// json_ref helpers // -////////////////////// - -template -class json_ref; - -template -struct is_json_ref : std::false_type {}; - -template -struct is_json_ref> : std::true_type {}; - -////////////////////////// -// aliases for detected // -////////////////////////// - -template -using mapped_type_t = typename T::mapped_type; - -template -using key_type_t = typename T::key_type; - -template -using value_type_t = typename T::value_type; - -template -using difference_type_t = typename T::difference_type; - -template -using pointer_t = typename T::pointer; - -template -using reference_t = typename T::reference; - -template -using iterator_category_t = typename T::iterator_category; - -template -using to_json_function = decltype(T::to_json(std::declval()...)); - -template -using from_json_function = decltype(T::from_json(std::declval()...)); - -template -using get_template_function = decltype(std::declval().template get()); - -// trait checking if JSONSerializer::from_json(json const&, udt&) exists -template -struct has_from_json : std::false_type {}; - -// trait checking if j.get is valid -// use this trait instead of std::is_constructible or std::is_convertible, -// both rely on, or make use of implicit conversions, and thus fail when T -// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) -template -struct is_getable -{ - static constexpr bool value = is_detected::value; -}; - -template -struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; - - static constexpr bool value = - is_detected_exact::value; -}; - -// This trait checks if JSONSerializer::from_json(json const&) exists -// this overload is used for non-default-constructible user-defined-types -template -struct has_non_default_from_json : std::false_type {}; - -template -struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; - - static constexpr bool value = - is_detected_exact::value; -}; - -// This trait checks if BasicJsonType::json_serializer::to_json exists -// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. -template -struct has_to_json : std::false_type {}; - -template -struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; - - static constexpr bool value = - is_detected_exact::value; -}; - -template -using detect_key_compare = typename T::key_compare; - -template -struct has_key_compare : std::integral_constant::value> {}; - -// obtains the actual object key comparator -template -struct actual_object_comparator -{ - using object_t = typename BasicJsonType::object_t; - using object_comparator_t = typename BasicJsonType::default_object_comparator_t; - using type = typename std::conditional < has_key_compare::value, - typename object_t::key_compare, object_comparator_t>::type; -}; - -template -using actual_object_comparator_t = typename actual_object_comparator::type; - -///////////////// -// char_traits // -///////////////// - -// Primary template of char_traits calls std char_traits -template -struct char_traits : std::char_traits -{}; - -// Explicitly define char traits for unsigned char since it is not standard -template<> -struct char_traits : std::char_traits -{ - using char_type = unsigned char; - using int_type = uint64_t; - - // Redefine to_int_type function - static int_type to_int_type(char_type c) noexcept - { - return static_cast(c); - } - - static char_type to_char_type(int_type i) noexcept - { - return static_cast(i); - } - - static constexpr int_type eof() noexcept - { - return static_cast(std::char_traits::eof()); - } -}; - -// Explicitly define char traits for signed char since it is not standard -template<> -struct char_traits : std::char_traits -{ - using char_type = signed char; - using int_type = uint64_t; - - // Redefine to_int_type function - static int_type to_int_type(char_type c) noexcept - { - return static_cast(c); - } - - static char_type to_char_type(int_type i) noexcept - { - return static_cast(i); - } - - static constexpr int_type eof() noexcept - { - return static_cast(std::char_traits::eof()); - } -}; - -/////////////////// -// is_ functions // -/////////////////// - -// https://en.cppreference.com/w/cpp/types/conjunction -template struct conjunction : std::true_type { }; -template struct conjunction : B { }; -template -struct conjunction -: std::conditional(B::value), conjunction, B>::type {}; - -// https://en.cppreference.com/w/cpp/types/negation -template struct negation : std::integral_constant < bool, !B::value > { }; - -// Reimplementation of is_constructible and is_default_constructible, due to them being broken for -// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). -// This causes compile errors in e.g. clang 3.5 or gcc 4.9. -template -struct is_default_constructible : std::is_default_constructible {}; - -template -struct is_default_constructible> - : conjunction, is_default_constructible> {}; - -template -struct is_default_constructible> - : conjunction, is_default_constructible> {}; - -template -struct is_default_constructible> - : conjunction...> {}; - -template -struct is_default_constructible> - : conjunction...> {}; - -template -struct is_constructible : std::is_constructible {}; - -template -struct is_constructible> : is_default_constructible> {}; - -template -struct is_constructible> : is_default_constructible> {}; - -template -struct is_constructible> : is_default_constructible> {}; - -template -struct is_constructible> : is_default_constructible> {}; - -template -struct is_iterator_traits : std::false_type {}; - -template -struct is_iterator_traits> -{ - private: - using traits = iterator_traits; - - public: - static constexpr auto value = - is_detected::value && - is_detected::value && - is_detected::value && - is_detected::value && - is_detected::value; -}; - -template -struct is_range -{ - private: - using t_ref = typename std::add_lvalue_reference::type; - - using iterator = detected_t; - using sentinel = detected_t; - - // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator - // and https://en.cppreference.com/w/cpp/iterator/sentinel_for - // but reimplementing these would be too much work, as a lot of other concepts are used underneath - static constexpr auto is_iterator_begin = - is_iterator_traits>::value; - - public: - static constexpr bool value = !std::is_same::value && !std::is_same::value && is_iterator_begin; -}; - -template -using iterator_t = enable_if_t::value, result_of_begin())>>; - -template -using range_value_t = value_type_t>>; - -// The following implementation of is_complete_type is taken from -// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ -// and is written by Xiang Fan who agreed to using it in this library. - -template -struct is_complete_type : std::false_type {}; - -template -struct is_complete_type : std::true_type {}; - -template -struct is_compatible_object_type_impl : std::false_type {}; - -template -struct is_compatible_object_type_impl < - BasicJsonType, CompatibleObjectType, - enable_if_t < is_detected::value&& - is_detected::value >> -{ - using object_t = typename BasicJsonType::object_t; - - // macOS's is_constructible does not play well with nonesuch... - static constexpr bool value = - is_constructible::value && - is_constructible::value; -}; - -template -struct is_compatible_object_type - : is_compatible_object_type_impl {}; - -template -struct is_constructible_object_type_impl : std::false_type {}; - -template -struct is_constructible_object_type_impl < - BasicJsonType, ConstructibleObjectType, - enable_if_t < is_detected::value&& - is_detected::value >> -{ - using object_t = typename BasicJsonType::object_t; - - static constexpr bool value = - (is_default_constructible::value && - (std::is_move_assignable::value || - std::is_copy_assignable::value) && - (is_constructible::value && - std::is_same < - typename object_t::mapped_type, - typename ConstructibleObjectType::mapped_type >::value)) || - (has_from_json::value || - has_non_default_from_json < - BasicJsonType, - typename ConstructibleObjectType::mapped_type >::value); -}; - -template -struct is_constructible_object_type - : is_constructible_object_type_impl {}; - -template -struct is_compatible_string_type -{ - static constexpr auto value = - is_constructible::value; -}; - -template -struct is_constructible_string_type -{ - // launder type through decltype() to fix compilation failure on ICPC -#ifdef __INTEL_COMPILER - using laundered_type = decltype(std::declval()); -#else - using laundered_type = ConstructibleStringType; -#endif - - static constexpr auto value = - conjunction < - is_constructible, - is_detected_exact>::value; -}; - -template -struct is_compatible_array_type_impl : std::false_type {}; - -template -struct is_compatible_array_type_impl < - BasicJsonType, CompatibleArrayType, - enable_if_t < - is_detected::value&& - is_iterator_traits>>::value&& -// special case for types like std::filesystem::path whose iterator's value_type are themselves -// c.f. https://github.com/nlohmann/json/pull/3073 - !std::is_same>::value >> -{ - static constexpr bool value = - is_constructible>::value; -}; - -template -struct is_compatible_array_type - : is_compatible_array_type_impl {}; - -template -struct is_constructible_array_type_impl : std::false_type {}; - -template -struct is_constructible_array_type_impl < - BasicJsonType, ConstructibleArrayType, - enable_if_t::value >> - : std::true_type {}; - -template -struct is_constructible_array_type_impl < - BasicJsonType, ConstructibleArrayType, - enable_if_t < !std::is_same::value&& - !is_compatible_string_type::value&& - is_default_constructible::value&& -(std::is_move_assignable::value || - std::is_copy_assignable::value)&& -is_detected::value&& -is_iterator_traits>>::value&& -is_detected::value&& -// special case for types like std::filesystem::path whose iterator's value_type are themselves -// c.f. https://github.com/nlohmann/json/pull/3073 -!std::is_same>::value&& -is_complete_type < -detected_t>::value >> -{ - using value_type = range_value_t; - - static constexpr bool value = - std::is_same::value || - has_from_json::value || - has_non_default_from_json < - BasicJsonType, - value_type >::value; -}; - -template -struct is_constructible_array_type - : is_constructible_array_type_impl {}; - -template -struct is_compatible_integer_type_impl : std::false_type {}; - -template -struct is_compatible_integer_type_impl < - RealIntegerType, CompatibleNumberIntegerType, - enable_if_t < std::is_integral::value&& - std::is_integral::value&& - !std::is_same::value >> -{ - // is there an assert somewhere on overflows? - using RealLimits = std::numeric_limits; - using CompatibleLimits = std::numeric_limits; - - static constexpr auto value = - is_constructible::value && - CompatibleLimits::is_integer && - RealLimits::is_signed == CompatibleLimits::is_signed; -}; - -template -struct is_compatible_integer_type - : is_compatible_integer_type_impl {}; - -template -struct is_compatible_type_impl: std::false_type {}; - -template -struct is_compatible_type_impl < - BasicJsonType, CompatibleType, - enable_if_t::value >> -{ - static constexpr bool value = - has_to_json::value; -}; - -template -struct is_compatible_type - : is_compatible_type_impl {}; - -template -struct is_constructible_tuple : std::false_type {}; - -template -struct is_constructible_tuple> : conjunction...> {}; - -template -struct is_json_iterator_of : std::false_type {}; - -template -struct is_json_iterator_of : std::true_type {}; - -template -struct is_json_iterator_of : std::true_type -{}; - -// checks if a given type T is a template specialization of Primary -template