From 340f945b4bb788c1ad7074e2c81bc15c345f5ccb Mon Sep 17 00:00:00 2001 From: Denis Zubarev Date: Fri, 28 Aug 2026 14:57:55 +0300 Subject: [PATCH 1/6] [compiler] reformat with clang-format --- compiler/class-assumptions.cpp | 317 +- compiler/class-assumptions.h | 24 +- compiler/code-gen/code-gen-root-cmd.h | 3 +- compiler/code-gen/code-gen-task.cpp | 16 +- compiler/code-gen/code-gen-task.h | 8 +- compiler/code-gen/code-generator.cpp | 16 +- compiler/code-gen/code-generator.h | 55 +- compiler/code-gen/common.h | 65 +- .../code-gen/const-globals-batched-mem.cpp | 211 +- compiler/code-gen/const-globals-batched-mem.h | 48 +- compiler/code-gen/declarations.cpp | 542 +- compiler/code-gen/declarations.h | 94 +- compiler/code-gen/files/cmake-lists-txt.cpp | 15 +- compiler/code-gen/files/cmake-lists-txt.h | 4 +- compiler/code-gen/files/const-vars-init.cpp | 49 +- compiler/code-gen/files/const-vars-init.h | 10 +- compiler/code-gen/files/function-header.cpp | 9 +- compiler/code-gen/files/function-header.h | 3 +- compiler/code-gen/files/function-source.cpp | 11 +- compiler/code-gen/files/function-source.h | 6 +- .../files/global-vars-memory-stats.cpp | 42 +- .../code-gen/files/global-vars-memory-stats.h | 8 +- compiler/code-gen/files/global-vars-reset.cpp | 29 +- compiler/code-gen/files/global-vars-reset.h | 12 +- compiler/code-gen/files/init-scripts.cpp | 111 +- compiler/code-gen/files/init-scripts.h | 8 +- compiler/code-gen/files/json-encoder-tags.cpp | 4 +- compiler/code-gen/files/json-encoder-tags.h | 8 +- compiler/code-gen/files/lib-header.cpp | 25 +- compiler/code-gen/files/lib-header.h | 8 +- compiler/code-gen/files/shape-keys.cpp | 4 +- compiler/code-gen/files/shape-keys.h | 6 +- .../code-gen/files/tl2cpp/tl-combinator.cpp | 125 +- .../code-gen/files/tl2cpp/tl-combinator.h | 54 +- .../code-gen/files/tl2cpp/tl-constructor.cpp | 24 +- .../code-gen/files/tl2cpp/tl-constructor.h | 22 +- .../code-gen/files/tl2cpp/tl-function.cpp | 20 +- compiler/code-gen/files/tl2cpp/tl-function.h | 24 +- compiler/code-gen/files/tl2cpp/tl-module.cpp | 58 +- compiler/code-gen/files/tl2cpp/tl-module.h | 34 +- .../tl2cpp/tl-template-php-type-helpers.h | 37 +- .../code-gen/files/tl2cpp/tl-type-expr.cpp | 39 +- compiler/code-gen/files/tl2cpp/tl-type-expr.h | 33 +- compiler/code-gen/files/tl2cpp/tl-type.cpp | 66 +- compiler/code-gen/files/tl2cpp/tl-type.h | 60 +- .../code-gen/files/tl2cpp/tl2cpp-utils.cpp | 183 +- compiler/code-gen/files/tl2cpp/tl2cpp-utils.h | 71 +- compiler/code-gen/files/tl2cpp/tl2cpp.cpp | 113 +- compiler/code-gen/files/tl2cpp/tl2cpp.h | 2 +- compiler/code-gen/files/tracing-autogen.cpp | 17 +- compiler/code-gen/files/tracing-autogen.h | 10 +- compiler/code-gen/files/type-tagger.cpp | 28 +- compiler/code-gen/files/type-tagger.h | 16 +- compiler/code-gen/gen-out-style.h | 6 +- compiler/code-gen/includes.cpp | 58 +- compiler/code-gen/includes.h | 31 +- compiler/code-gen/namespace.h | 12 +- compiler/code-gen/naming.h | 103 +- compiler/code-gen/raw-data.cpp | 115 +- compiler/code-gen/raw-data.h | 50 +- compiler/code-gen/vertex-compiler.cpp | 1240 ++- compiler/code-gen/vertex-compiler.h | 4 +- compiler/code-gen/writer-data.cpp | 41 +- compiler/code-gen/writer-data.h | 32 +- compiler/compiler-core.cpp | 247 +- compiler/compiler-core.h | 95 +- compiler/compiler-settings.cpp | 77 +- compiler/compiler-settings.h | 36 +- compiler/compiler.cpp | 166 +- compiler/compiler.h | 2 +- compiler/composer.cpp | 39 +- compiler/composer.h | 16 +- compiler/const-manipulations.h | 229 +- compiler/cpp-dest-dir-initializer.cpp | 2 +- compiler/cpp-dest-dir-initializer.h | 2 +- compiler/data/class-data.cpp | 129 +- compiler/data/class-data.h | 117 +- compiler/data/class-members.cpp | 95 +- compiler/data/class-members.h | 145 +- compiler/data/class-modifiers.h | 8 +- compiler/data/composer-json-data.cpp | 74 +- compiler/data/composer-json-data.h | 24 +- compiler/data/data_ptr.h | 40 +- compiler/data/define-data.cpp | 22 +- compiler/data/define-data.h | 16 +- compiler/data/ffi-data.cpp | 343 +- compiler/data/ffi-data.h | 107 +- compiler/data/field-modifiers.h | 37 +- compiler/data/function-data.cpp | 81 +- compiler/data/function-data.h | 89 +- compiler/data/function-modifiers.h | 78 +- compiler/data/generics-mixins.cpp | 258 +- compiler/data/generics-mixins.h | 109 +- compiler/data/kphp-json-tags.cpp | 364 +- compiler/data/kphp-json-tags.h | 45 +- compiler/data/kphp-tracing-tags.cpp | 38 +- compiler/data/kphp-tracing-tags.h | 18 +- compiler/data/lib-data.cpp | 30 +- compiler/data/lib-data.h | 34 +- compiler/data/modulite-data.cpp | 171 +- compiler/data/modulite-data.h | 36 +- compiler/data/performance-inspections.cpp | 20 +- compiler/data/performance-inspections.h | 6 +- compiler/data/src-dir.cpp | 4 +- compiler/data/src-dir.h | 6 +- compiler/data/src-file.cpp | 4 +- compiler/data/src-file.h | 21 +- compiler/data/var-data.cpp | 20 +- compiler/data/var-data.h | 39 +- compiler/data/vertex-adaptor.h | 47 +- compiler/debug.cpp | 415 +- compiler/ffi/c_parser/lexer.h | 36 +- compiler/ffi/c_parser/lexer_generated.cpp | 7186 ++++++++++------- compiler/ffi/c_parser/parsing_driver.cpp | 153 +- compiler/ffi/c_parser/parsing_driver.h | 77 +- compiler/ffi/c_parser/parsing_types.h | 40 +- compiler/ffi/c_parser/string-span.h | 14 +- compiler/ffi/c_parser/types-allocator.h | 11 +- compiler/ffi/c_parser/yy_parser_generated.cpp | 2552 +++--- compiler/ffi/ffi_parser.cpp | 45 +- compiler/ffi/ffi_parser.h | 40 +- compiler/ffi/ffi_types.cpp | 4 +- compiler/ffi/ffi_types.h | 54 +- compiler/function-colors.cpp | 18 +- compiler/function-colors.h | 32 +- compiler/function-pass.h | 72 +- compiler/generics-reification.cpp | 76 +- compiler/generics-reification.h | 8 +- compiler/gentree.cpp | 1434 ++-- compiler/gentree.h | 66 +- compiler/helper.h | 28 +- compiler/index.cpp | 105 +- compiler/index.h | 54 +- compiler/inferring/edge.h | 9 +- compiler/inferring/expr-node.cpp | 524 +- compiler/inferring/expr-node.h | 11 +- compiler/inferring/ifi.cpp | 14 +- compiler/inferring/ifi.h | 6 +- compiler/inferring/key.cpp | 18 +- compiler/inferring/key.h | 43 +- compiler/inferring/lvalue.cpp | 10 +- compiler/inferring/lvalue.h | 30 +- compiler/inferring/multi-key.cpp | 2 +- compiler/inferring/multi-key.h | 19 +- compiler/inferring/node-recalc.cpp | 54 +- compiler/inferring/node-recalc.h | 33 +- compiler/inferring/node.cpp | 78 +- compiler/inferring/node.h | 36 +- compiler/inferring/primitive-type.cpp | 64 +- compiler/inferring/primitive-type.h | 5 +- compiler/inferring/public.cpp | 16 +- compiler/inferring/public.h | 14 +- compiler/inferring/restriction-base.h | 8 +- compiler/inferring/restriction-isset.cpp | 88 +- compiler/inferring/restriction-isset.h | 11 +- .../inferring/restriction-match-phpdoc.cpp | 100 +- compiler/inferring/restriction-match-phpdoc.h | 11 +- compiler/inferring/restriction-non-void.cpp | 5 +- compiler/inferring/restriction-non-void.h | 5 +- .../restriction-stacktrace-finder.cpp | 120 +- .../inferring/restriction-stacktrace-finder.h | 15 +- compiler/inferring/rvalue.h | 33 +- compiler/inferring/type-data.cpp | 500 +- compiler/inferring/type-data.h | 193 +- compiler/inferring/type-hint-recalc.cpp | 78 +- compiler/inferring/type-inferer.cpp | 46 +- compiler/inferring/type-inferer.h | 22 +- compiler/inferring/type-node.cpp | 2 +- compiler/inferring/type-node.h | 9 +- compiler/inferring/var-node.cpp | 46 +- compiler/inferring/var-node.h | 10 +- compiler/kphp2cpp.cpp | 216 +- compiler/kphp_assert.h | 65 +- compiler/lambda-utils.cpp | 42 +- compiler/lambda-utils.h | 4 +- compiler/lexer.cpp | 468 +- compiler/lexer.h | 121 +- compiler/location.h | 26 +- compiler/make/cpp-to-obj-target.h | 11 +- compiler/make/file-target.h | 2 +- compiler/make/h-to-pch-target.h | 7 +- compiler/make/hardlink-or-copy.cpp | 18 +- compiler/make/hardlink-or-copy.h | 2 +- compiler/make/make-runner.cpp | 147 +- compiler/make/make-runner.h | 31 +- compiler/make/make.cpp | 207 +- compiler/make/objs-to-bin-target.h | 9 +- compiler/make/objs-to-k2-component-target.h | 2 +- compiler/make/objs-to-obj-target.h | 7 +- compiler/make/runtime-src-to-obj-target.h | 6 +- compiler/make/target.cpp | 12 +- compiler/make/target.h | 15 +- compiler/modulite-check-rules.cpp | 166 +- compiler/modulite-check-rules.h | 3 +- compiler/name-gen.cpp | 188 +- compiler/name-gen.h | 4 +- compiler/operation.cpp | 8 +- compiler/operation.h | 28 +- compiler/phpdoc.cpp | 591 +- compiler/phpdoc.h | 70 +- compiler/pipes/analyze-performance.cpp | 329 +- compiler/pipes/analyze-performance.h | 8 +- compiler/pipes/analyzer.cpp | 24 +- compiler/pipes/analyzer.h | 3 - compiler/pipes/array-access-transform.cpp | 10 +- compiler/pipes/calc-actual-edges.cpp | 6 +- compiler/pipes/calc-actual-edges.h | 13 +- compiler/pipes/calc-bad-vars.cpp | 212 +- compiler/pipes/calc-bad-vars.h | 2 +- compiler/pipes/calc-const-types.cpp | 42 +- compiler/pipes/calc-const-types.h | 2 +- compiler/pipes/calc-empty-functions.cpp | 78 +- compiler/pipes/calc-empty-functions.h | 2 +- compiler/pipes/calc-func-dep.cpp | 25 +- compiler/pipes/calc-func-dep.h | 14 +- compiler/pipes/calc-locations.cpp | 9 +- compiler/pipes/calc-real-defines-values.cpp | 10 +- compiler/pipes/calc-real-defines-values.h | 9 +- compiler/pipes/calc-rl.cpp | 447 +- compiler/pipes/calc-rl.h | 2 +- compiler/pipes/calc-val-ref.cpp | 86 +- compiler/pipes/calc-val-ref.h | 1 + compiler/pipes/cfg-end.cpp | 32 +- compiler/pipes/cfg-end.h | 2 +- compiler/pipes/cfg.cpp | 1423 ++-- compiler/pipes/cfg.h | 4 +- .../check-abstract-function-defaults.cpp | 4 +- .../pipes/check-abstract-function-defaults.h | 2 +- compiler/pipes/check-access-modifiers.cpp | 6 +- compiler/pipes/check-access-modifiers.h | 15 +- compiler/pipes/check-classes.cpp | 47 +- compiler/pipes/check-classes.h | 2 +- compiler/pipes/check-conversions.cpp | 77 +- compiler/pipes/check-conversions.h | 1 + .../pipes/check-func-calls-and-vararg.cpp | 49 +- compiler/pipes/check-func-calls-and-vararg.h | 2 +- .../check-modifications-of-const-vars.cpp | 162 +- .../pipes/check-modifications-of-const-vars.h | 1 - compiler/pipes/check-nested-foreach.cpp | 12 +- compiler/pipes/check-restrictions.h | 3 +- compiler/pipes/check-tl-classes.cpp | 25 +- compiler/pipes/check-type-hint-variance.cpp | 23 +- compiler/pipes/check-type-hint-variance.h | 2 +- compiler/pipes/check-ub.cpp | 52 +- compiler/pipes/check-ub.h | 2 +- compiler/pipes/clone-nested-lambdas.h | 8 +- compiler/pipes/clone-strange-const-params.cpp | 5 +- compiler/pipes/code-gen.cpp | 57 +- compiler/pipes/code-gen.h | 8 +- compiler/pipes/collect-const-vars.cpp | 87 +- compiler/pipes/collect-const-vars.h | 1 - compiler/pipes/collect-forkable-types.cpp | 6 +- compiler/pipes/collect-forkable-types.h | 14 +- compiler/pipes/collect-main-edges.cpp | 142 +- compiler/pipes/collect-main-edges.h | 20 +- .../pipes/collect-required-and-classes.cpp | 94 +- compiler/pipes/collect-required-and-classes.h | 2 +- .../pipes/convert-invoke-to-func-call.cpp | 17 +- compiler/pipes/convert-invoke-to-func-call.h | 6 +- compiler/pipes/convert-sprintf-calls.cpp | 79 +- compiler/pipes/convert-sprintf-calls.h | 2 +- .../pipes/deduce-implicit-types-and-casts.cpp | 184 +- .../pipes/deduce-implicit-types-and-casts.h | 14 +- compiler/pipes/early-optimization.cpp | 8 +- compiler/pipes/early-optimization.h | 2 +- compiler/pipes/extract-async.cpp | 3 +- compiler/pipes/extract-resumable-calls.cpp | 36 +- compiler/pipes/extract-resumable-calls.h | 7 +- compiler/pipes/file-to-tokens.cpp | 2 +- compiler/pipes/file-to-tokens.h | 2 +- compiler/pipes/filter-only-actually-used.cpp | 139 +- compiler/pipes/filter-only-actually-used.h | 5 +- compiler/pipes/final-check.cpp | 488 +- compiler/pipes/final-check.h | 3 +- compiler/pipes/fix-returns.cpp | 8 +- compiler/pipes/function-and-cfg.h | 7 +- compiler/pipes/gen-tree-postprocess.cpp | 71 +- compiler/pipes/gen-tree-postprocess.h | 2 +- compiler/pipes/generate-virtual-methods.cpp | 139 +- compiler/pipes/generate-virtual-methods.h | 2 +- compiler/pipes/inline-defines-usages.cpp | 10 +- compiler/pipes/inline-simple-functions.cpp | 104 +- compiler/pipes/inline-simple-functions.h | 4 +- compiler/pipes/instantiate-ffi-operations.cpp | 161 +- compiler/pipes/instantiate-ffi-operations.h | 10 +- .../instantiate-generics-and-lambdas.cpp | 74 +- .../pipes/instantiate-generics-and-lambdas.h | 2 +- compiler/pipes/load-files.cpp | 4 +- compiler/pipes/load-files.h | 2 +- compiler/pipes/optimization.cpp | 101 +- compiler/pipes/optimization.h | 2 +- compiler/pipes/parse-and-apply-phpdoc.cpp | 587 +- compiler/pipes/parse-and-apply-phpdoc.h | 6 +- compiler/pipes/parse.cpp | 2 +- compiler/pipes/parse.h | 2 +- compiler/pipes/preprocess-break.cpp | 20 +- compiler/pipes/preprocess-eq3.cpp | 6 +- compiler/pipes/preprocess-eq3.h | 1 + compiler/pipes/preprocess-exceptions.cpp | 8 +- compiler/pipes/propagate-throw-flag.cpp | 4 +- compiler/pipes/register-defines.cpp | 2 +- compiler/pipes/register-ffi-scopes.cpp | 75 +- compiler/pipes/register-ffi-scopes.h | 2 +- .../pipes/register-kphp-configuration.cpp | 122 +- compiler/pipes/register-kphp-configuration.h | 20 +- compiler/pipes/register-variables.cpp | 51 +- compiler/pipes/register-variables.h | 11 +- .../pipes/remove-empty-function-calls.cpp | 11 +- compiler/pipes/remove-empty-function-calls.h | 4 +- compiler/pipes/resolve-self-static-parent.cpp | 69 +- compiler/pipes/resolve-self-static-parent.h | 2 +- compiler/pipes/sort-and-inherit-classes.cpp | 178 +- compiler/pipes/sort-and-inherit-classes.h | 18 +- compiler/pipes/split-switch.cpp | 21 +- compiler/pipes/split-switch.h | 2 +- compiler/pipes/sync.h | 19 +- .../pipes/transform-to-smart-instanceof.cpp | 45 +- .../pipes/transform-to-smart-instanceof.h | 2 +- compiler/pipes/type-inferer.cpp | 6 +- compiler/pipes/type-inferer.h | 7 +- compiler/pipes/wait-for-all-classes.cpp | 8 +- compiler/pipes/wait-for-all-classes.h | 11 +- compiler/pipes/write-files.cpp | 14 +- compiler/pipes/write-files.h | 2 +- .../replace-extern-func-calls.cpp | 63 +- compiler/rewrite-rules/rules_runtime.cpp | 264 +- compiler/rewrite-rules/rules_runtime.h | 20 +- compiler/runtime_build_info.h | 4 +- compiler/scheduler/constructor.h | 53 +- compiler/scheduler/node.cpp | 8 +- compiler/scheduler/node.h | 6 +- compiler/scheduler/one-thread-scheduler.cpp | 14 +- compiler/scheduler/one-thread-scheduler.h | 13 +- compiler/scheduler/pipe.h | 43 +- compiler/scheduler/pipe_with_progress.h | 15 +- compiler/scheduler/scheduler-base.cpp | 14 +- compiler/scheduler/scheduler-base.h | 14 +- compiler/scheduler/scheduler.cpp | 35 +- compiler/scheduler/scheduler.h | 20 +- compiler/scheduler/task-pull.h | 9 +- compiler/stage.cpp | 84 +- compiler/stage.h | 25 +- compiler/stats.cpp | 54 +- compiler/stats.h | 4 +- compiler/threading/allocator.cpp | 64 +- compiler/threading/data-stream.h | 19 +- compiler/threading/hash-table.h | 23 +- compiler/threading/locks.h | 16 +- compiler/threading/profiler.cpp | 40 +- compiler/threading/profiler.h | 29 +- compiler/threading/tls.h | 26 +- compiler/tl-classes.cpp | 8 +- compiler/tl-classes.h | 10 +- compiler/token.h | 29 +- compiler/type-hint.cpp | 394 +- compiler/type-hint.h | 490 +- compiler/utils/idmap.h | 27 +- compiler/utils/string-utils.h | 20 +- compiler/utils/trie.h | 9 +- compiler/vertex-meta_op_base.h | 263 +- compiler/vertex-util.cpp | 98 +- compiler/vertex-util.h | 6 +- compiler/vertex.cpp | 7 +- compiler/vertex.h | 24 +- 364 files changed, 17646 insertions(+), 16851 deletions(-) diff --git a/compiler/class-assumptions.cpp b/compiler/class-assumptions.cpp index 855887eb37..c25cf4837a 100644 --- a/compiler/class-assumptions.cpp +++ b/compiler/class-assumptions.cpp @@ -34,59 +34,57 @@ #include "compiler/data/class-data.h" #include "compiler/data/function-data.h" -#include "compiler/pipes/instantiate-ffi-operations.h" -#include "compiler/pipes/deduce-implicit-types-and-casts.h" +#include "compiler/function-pass.h" #include "compiler/phpdoc.h" +#include "compiler/pipes/deduce-implicit-types-and-casts.h" +#include "compiler/pipes/instantiate-ffi-operations.h" #include "compiler/type-hint.h" -#include "compiler/function-pass.h" -#include "compiler/vertex.h" #include "compiler/vertex-util.h" +#include "compiler/vertex.h" - -static inline const TypeHint *assumption_unwrap_optional(const TypeHint *assum_hint) { +static inline const TypeHint* assumption_unwrap_optional(const TypeHint* assum_hint) { if (assum_hint == nullptr) { return nullptr; } - if (const auto *as_optional = assum_hint->try_as()) { + if (const auto* as_optional = assum_hint->try_as()) { return as_optional->inner; } return assum_hint; } -static inline bool assumption_needs_to_be_saved(const TypeHint *assum_hint) { +static inline bool assumption_needs_to_be_saved(const TypeHint* assum_hint) { return assum_hint && assum_hint->is_typedata_constexpr() && !assum_hint->has_autogeneric_inside(); } - -Assumption::Assumption(ClassPtr klass) : assum_hint(klass->type_hint) { -} +Assumption::Assumption(ClassPtr klass) + : assum_hint(klass->type_hint) {} std::string Assumption::as_human_readable() const { return assum_hint ? assum_hint->as_human_readable() : "undefined"; } Assumption Assumption::get_inner_if_array() const { - const TypeHint *type_hint = assumption_unwrap_optional(assum_hint); + const TypeHint* type_hint = assumption_unwrap_optional(assum_hint); if (type_hint == nullptr) { return {}; } - if (const auto *as_array = type_hint->try_as()) { + if (const auto* as_array = type_hint->try_as()) { return Assumption(as_array->inner); } return {}; } Assumption Assumption::get_subkey_by_index(VertexPtr index_key) const { - const TypeHint *type_hint = assumption_unwrap_optional(assum_hint); + const TypeHint* type_hint = assumption_unwrap_optional(assum_hint); if (type_hint == nullptr) { return {}; } - if (const auto *as_array = type_hint->try_as()) { + if (const auto* as_array = type_hint->try_as()) { return Assumption(as_array->inner); } - if (const auto *as_tuple = type_hint->try_as()) { + if (const auto* as_tuple = type_hint->try_as()) { if (auto as_int_index = VertexUtil::get_actual_value(index_key).try_as()) { int int_index = parse_int_from_string(as_int_index); if (int_index >= 0 && int_index < as_tuple->items.size()) { @@ -94,10 +92,10 @@ Assumption Assumption::get_subkey_by_index(VertexPtr index_key) const { } } } - if (const auto *as_shape = type_hint->try_as()) { + if (const auto* as_shape = type_hint->try_as()) { if (vk::any_of_equal(VertexUtil::get_actual_value(index_key)->type(), op_int_const, op_string)) { - const auto &string_index = VertexUtil::get_actual_value(index_key)->get_string(); - if (const TypeHint *at_index = as_shape->find_at(string_index)) { + const auto& string_index = VertexUtil::get_actual_value(index_key)->get_string(); + if (const TypeHint* at_index = as_shape->find_at(string_index)) { return Assumption(at_index); } } @@ -105,8 +103,8 @@ Assumption Assumption::get_subkey_by_index(VertexPtr index_key) const { return {}; } -static ClassPtr extract_instance_from_ffi_scope(const std::string &scope_name, const FFIType *type) { - if (const auto *builtin = ffi_builtin_type(type->kind)) { +static ClassPtr extract_instance_from_ffi_scope(const std::string& scope_name, const FFIType* type) { + if (const auto* builtin = ffi_builtin_type(type->kind)) { return G->get_class(builtin->php_class_name); } if (vk::any_of_equal(type->kind, FFITypeKind::Struct, FFITypeKind::StructDef, FFITypeKind::Union)) { @@ -119,26 +117,26 @@ static ClassPtr extract_instance_from_ffi_scope(const std::string &scope_name, c } // we have to resolve $a->..., knowing (by phpdoc or rough inferring) the TypeHint of a -ClassPtr Assumption::extract_instance_from_type_hint(const TypeHint *a) { +ClassPtr Assumption::extract_instance_from_type_hint(const TypeHint* a) { if (a == nullptr) { return ClassPtr{}; } // for T|false or T|null, narrow down to T - if (const auto *as_optional = a->try_as()) { + if (const auto* as_optional = a->try_as()) { a = as_optional->inner; } // the simpliest (and most common) case: just A - if (const auto *as_instance = a->try_as()) { + if (const auto* as_instance = a->try_as()) { return as_instance->resolve(); } // for A|B, when A and B all are instances and have a common base - if (const auto *as_pipe = a->try_as()) { + if (const auto* as_pipe = a->try_as()) { kphp_assert(as_pipe->items.size() >= 2); // to avoid the redundant work, check whether all union variants are classes // and that they have some parent or interface (otherwise they would never have a common base) - for (const auto *item : as_pipe->items) { - if (const auto *as_primitive = item->try_as()) { + for (const auto* item : as_pipe->items) { + if (const auto* as_primitive = item->try_as()) { if (as_primitive->ptype != tp_Null) { return ClassPtr{}; } @@ -156,7 +154,7 @@ ClassPtr Assumption::extract_instance_from_type_hint(const TypeHint *a) { // the method below is somewhat conservative, but it's good enough in the usual cases ClassPtr result; ClassPtr first; - for (const auto *item : as_pipe->items) { + for (const auto* item : as_pipe->items) { if (item->try_as()) { continue; // we know that it's tp_Null } @@ -179,54 +177,51 @@ ClassPtr Assumption::extract_instance_from_type_hint(const TypeHint *a) { return result; } // an instantiated callable or a typed callable (which is called with __invoke for example) - if (const auto *as_callable = a->try_as()) { + if (const auto* as_callable = a->try_as()) { return as_callable->is_typed_callable() ? as_callable->get_interface() : as_callable->get_lambda_class(); } // 'T::fieldName' — a syntax that's used in @return for generics - if (const auto *as_field_ref = a->try_as()) { - if (const TypeHint *field_type_hint = as_field_ref->resolve_field_type_hint()) { + if (const auto* as_field_ref = a->try_as()) { + if (const TypeHint* field_type_hint = as_field_ref->resolve_field_type_hint()) { return extract_instance_from_type_hint(field_type_hint); } } // 'T::methodName()' — a syntax that's used in @return for generics - if (const auto *as_method_ref = a->try_as()) { + if (const auto* as_method_ref = a->try_as()) { if (FunctionPtr method = as_method_ref->resolve_method()) { return assume_return_of_function(method).try_as_class(); } } // ffi_cdata — return T inside scope, it's a registered class - if (const auto *as_ffi = a->try_as()) { + if (const auto* as_ffi = a->try_as()) { return extract_instance_from_ffi_scope(as_ffi->scope_name, as_ffi->type); } // ffi_scope — return the corresponding registered class of this scope - if (const auto *as_ffi_scope = a->try_as()) { + if (const auto* as_ffi_scope = a->try_as()) { return G->get_class(FFIRoot::scope_class_name(as_ffi_scope->scope_name)); } - return ClassPtr{}; } - // -------------------------------------------- -static Assumption calc_assumption_for_class_static_var(ClassPtr c, const std::string &var_name); -static Assumption calc_assumption_for_class_instance_field(ClassPtr c, const std::string &var_name); +static Assumption calc_assumption_for_class_static_var(ClassPtr c, const std::string& var_name); +static Assumption calc_assumption_for_class_instance_field(ClassPtr c, const std::string& var_name); - -static Assumption assumption_merge(const Assumption &dst, const Assumption &rhs) { +static Assumption assumption_merge(const Assumption& dst, const Assumption& rhs) { if (dst.assum_hint == rhs.assum_hint) { return dst; } - const TypeHint *dst_hint = assumption_unwrap_optional(dst.assum_hint); - const TypeHint *rhs_hint = assumption_unwrap_optional(rhs.assum_hint); + const TypeHint* dst_hint = assumption_unwrap_optional(dst.assum_hint); + const TypeHint* rhs_hint = assumption_unwrap_optional(rhs.assum_hint); if (dst_hint == rhs_hint) { return dst.assum_hint->try_as() ? dst : rhs; } - const auto *dst_as_instance = dst_hint->try_as(); - const auto *rhs_as_instance = rhs_hint->try_as(); + const auto* dst_as_instance = dst_hint->try_as(); + const auto* rhs_as_instance = rhs_hint->try_as(); if (dst_as_instance && rhs_as_instance && dst_as_instance->resolve()->is_parent_of(rhs_as_instance->resolve())) { return dst.assum_hint->try_as() ? dst : Assumption(dst_as_instance); } @@ -234,7 +229,7 @@ static Assumption assumption_merge(const Assumption &dst, const Assumption &rhs) return {}; } -static void __attribute__((noinline)) print_error_assumptions_arent_merged_for_var(FunctionPtr f, const std::string &var_name, Assumption a, Assumption b) { +static void __attribute__((noinline)) print_error_assumptions_arent_merged_for_var(FunctionPtr f, const std::string& var_name, Assumption a, Assumption b) { ClassPtr a_klass = a.try_as_class(); ClassPtr b_klass = b.try_as_class(); std::vector common_bases = a_klass ? a_klass->get_common_base_or_interface(b_klass) : std::vector{}; @@ -243,21 +238,22 @@ static void __attribute__((noinline)) print_error_assumptions_arent_merged_for_v fmt_format("${} is was declared as @param {}, and later reassigned to {}\nPlease, use different names for local vars and arguments", var_name, TermStringFormat::paint_green(a.as_human_readable()), TermStringFormat::paint_green(b.as_human_readable()))); kphp_error_return(common_bases.empty(), - fmt_format("${} is assumed to be both {} and {}\nAdd /** @var {} ${} */ above all assignments to ${} to resolve this conflict.\nProbably, you want /** @var \\{} ${} */", - var_name, TermStringFormat::paint_green(a.as_human_readable()), TermStringFormat::paint_green(b.as_human_readable()), "{type}", var_name, var_name, common_bases.front()->name, var_name)); - kphp_error_return(0, - fmt_format("${} is assumed to be both {} and {}\nAdd /** @var {} ${} */ above all assignments to ${} to resolve this conflict.", - var_name, TermStringFormat::paint_green(a.as_human_readable()), TermStringFormat::paint_green(b.as_human_readable()), "{type}", var_name, var_name)); + fmt_format("${} is assumed to be both {} and {}\nAdd /** @var {} ${} */ above all assignments to ${} to resolve this conflict.\nProbably, " + "you want /** @var \\{} ${} */", + var_name, TermStringFormat::paint_green(a.as_human_readable()), TermStringFormat::paint_green(b.as_human_readable()), "{type}", + var_name, var_name, common_bases.front()->name, var_name)); + kphp_error_return(0, fmt_format("${} is assumed to be both {} and {}\nAdd /** @var {} ${} */ above all assignments to ${} to resolve this conflict.", + var_name, TermStringFormat::paint_green(a.as_human_readable()), TermStringFormat::paint_green(b.as_human_readable()), + "{type}", var_name, var_name)); } static void __attribute__((noinline)) print_error_assumptions_arent_merged_for_return(FunctionPtr f, Assumption a, Assumption b) { - kphp_error_return(0, - fmt_format("{}() is assumed to return both {} and {}\nAdd /** @return {} */ above a function to resolve this conflict.", - f->as_human_readable(), TermStringFormat::paint_green(a.as_human_readable()), TermStringFormat::paint_green(b.as_human_readable()), "{type}")); + kphp_error_return(0, fmt_format("{}() is assumed to return both {} and {}\nAdd /** @return {} */ above a function to resolve this conflict.", + f->as_human_readable(), TermStringFormat::paint_green(a.as_human_readable()), + TermStringFormat::paint_green(b.as_human_readable()), "{type}")); } - -void assumption_add_for_var(FunctionPtr f, const std::string &var_name, const Assumption &assumption, VertexPtr v_location) { +void assumption_add_for_var(FunctionPtr f, const std::string& var_name, const Assumption& assumption, VertexPtr v_location) { if (!assumption_needs_to_be_saved(assumption.assum_hint)) { return; } @@ -268,7 +264,7 @@ void assumption_add_for_var(FunctionPtr f, const std::string &var_name, const As } } - for (auto &name_and_a : f->assumptions_for_vars) { + for (auto& name_and_a : f->assumptions_for_vars) { if (name_and_a.first == var_name) { if (Assumption merged = assumption_merge(name_and_a.second, assumption)) { name_and_a.second = merged; @@ -281,10 +277,10 @@ void assumption_add_for_var(FunctionPtr f, const std::string &var_name, const As } f->assumptions_for_vars.emplace_front(var_name, assumption); -// printf("%s() $%s %s\n", f->name.c_str(), var_name.c_str(), assumption.as_human_readable().c_str()); + // printf("%s() $%s %s\n", f->name.c_str(), var_name.c_str(), assumption.as_human_readable().c_str()); } -void assumption_add_for_return(FunctionPtr f, const Assumption &assumption, VertexPtr v_location) { +void assumption_add_for_return(FunctionPtr f, const Assumption& assumption, VertexPtr v_location) { if (!assumption_needs_to_be_saved(assumption.assum_hint)) { return; } @@ -300,10 +296,9 @@ void assumption_add_for_return(FunctionPtr f, const Assumption &assumption, Vert } f->assumption_for_return = assumption; -// printf("%s() returns %s\n", f->as_human_readable().c_str(), assumption.as_human_readable().c_str()); + // printf("%s() returns %s\n", f->as_human_readable().c_str(), assumption.as_human_readable().c_str()); } - // this pass is executed on demand to calculate an assumption for $var_name inside a function // it traverses function body, searching for "$var_name = rhs" and other cases (trivial, must most common type-affecting ones) // note, that having a function() { $a = new A; $a->method(); $a = new B; } we need to know the assumption in the middle, @@ -311,7 +306,7 @@ void assumption_add_for_return(FunctionPtr f, const Assumption &assumption, Vert // (an assumption for B is appended afterward from DeduceImplicitTypesAndCastsPass, resulting in an appropriate error) class CalcAssumptionForVarPass final : public FunctionPassBase { VertexPtr stop_at; - const std::string &var_name; + const std::string& var_name; bool stopped{false}; public: @@ -319,12 +314,12 @@ class CalcAssumptionForVarPass final : public FunctionPassBase { return "Calc assumption for var"; } - explicit CalcAssumptionForVarPass(const std::string &var_name, VertexPtr stop_at) - : stop_at(stop_at) - , var_name(var_name) {} + explicit CalcAssumptionForVarPass(const std::string& var_name, VertexPtr stop_at) + : stop_at(stop_at), + var_name(var_name) {} void on_start() override { -// printf("start assumptions for %s() $%s\n", current_function->as_human_readable().c_str(), std::string(var_name).c_str()); + // printf("start assumptions for %s() $%s\n", current_function->as_human_readable().c_str(), std::string(var_name).c_str()); } VertexPtr on_enter_vertex(VertexPtr root) override { @@ -419,7 +414,7 @@ class CalcAssumptionForReturnPass final : public FunctionPassBase { } void on_start() override { -// printf("start assumptions for %s() return\n", current_function->as_human_readable().c_str()); + // printf("start assumptions for %s() return\n", current_function->as_human_readable().c_str()); } VertexPtr on_enter_vertex(VertexPtr root) override { @@ -438,7 +433,7 @@ class CalcAssumptionForReturnPass final : public FunctionPassBase { * A high-level function which deduces the type of $a inside f. * The results are cached per var_name; init on f is called during the first invocation. */ -static Assumption calc_assumption_for_var(FunctionPtr f, const std::string &var_name, VertexPtr stop_at) { +static Assumption calc_assumption_for_var(FunctionPtr f, const std::string& var_name, VertexPtr stop_at) { if (f->modifiers.is_instance() && var_name == "this") { return Assumption(f->class_id); } @@ -454,7 +449,7 @@ static Assumption calc_assumption_for_var(FunctionPtr f, const std::string &var_ } for (auto v : f->uses_list) { if (v->str_val == var_name) { - return calc_assumption_for_var(f->outer_function, var_name, {}); // empty stop_at is ok here + return calc_assumption_for_var(f->outer_function, var_name, {}); // empty stop_at is ok here } } } @@ -466,7 +461,7 @@ static Assumption calc_assumption_for_var(FunctionPtr f, const std::string &var_ } auto pos = var_name.find("$$"); - if (pos != std::string::npos) { // static class variable that is used inside a function + if (pos != std::string::npos) { // static class variable that is used inside a function if (auto of_class = G->get_class(replace_characters(var_name.substr(0, pos), '$', '\\'))) { return calc_assumption_for_class_static_var(of_class, var_name.substr(pos + 2)); } @@ -478,26 +473,24 @@ static Assumption calc_assumption_for_var(FunctionPtr f, const std::string &var_ return f->get_assumption_for_var(var_name); } -static Assumption calc_assumption_for_class_instance_field(ClassPtr c, const std::string &var_name) { - if (const auto *field = c->get_instance_field(var_name)) { +static Assumption calc_assumption_for_class_instance_field(ClassPtr c, const std::string& var_name) { + if (const auto* field = c->get_instance_field(var_name)) { return field->type_hint ? Assumption(field->type_hint) : Assumption(); } return {}; } -static Assumption calc_assumption_for_class_static_var(ClassPtr c, const std::string &var_name) { - if (const auto *field = c->get_static_field(var_name)) { +static Assumption calc_assumption_for_class_static_var(ClassPtr c, const std::string& var_name) { + if (const auto* field = c->get_static_field(var_name)) { return field->type_hint ? Assumption(field->type_hint) : Assumption(); } return {}; } - // ————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— - namespace { Assumption infer_from_var(FunctionPtr f, VertexAdaptor var, VertexPtr stop_at) { @@ -515,34 +508,34 @@ Assumption infer_from_call(FunctionPtr f, VertexAdaptor call, Vert // built-in functions like array_pop/array_filter/instance_cast/etc if (f_called->return_typehint && f_called->return_typehint->has_argref_inside()) { - const TypeHint *return_typehint = f_called->return_typehint->unwrap_optional(); + const TypeHint* return_typehint = f_called->return_typehint->unwrap_optional(); - if (const auto *as_arg_ref = return_typehint->try_as()) { // array_values ($a ::: array) ::: ^1 + if (const auto* as_arg_ref = return_typehint->try_as()) { // array_values ($a ::: array) ::: ^1 return assume_class_of_expr(f, VertexUtil::get_call_arg_ref(as_arg_ref->arg_num, call), stop_at); } - if (const auto *as_sub = return_typehint->try_as()) { // array_shift (&$a ::: array) ::: ^1[*] - if (const auto *arg_ref = as_sub->inner->try_as()) { + if (const auto* as_sub = return_typehint->try_as()) { // array_shift (&$a ::: array) ::: ^1[*] + if (const auto* arg_ref = as_sub->inner->try_as()) { auto expr_a = assume_class_of_expr(f, VertexUtil::get_call_arg_ref(arg_ref->arg_num, call), stop_at); if (Assumption inner = expr_a.get_inner_if_array()) { return inner; } } } - if (const auto *as_arg_ref = return_typehint->try_as()) { // f (...) ::: instance<^1> + if (const auto* as_arg_ref = return_typehint->try_as()) { // f (...) ::: instance<^1> if (auto arg = VertexUtil::get_call_arg_ref(as_arg_ref->arg_num, call)) { - if (const auto *class_name = VertexUtil::get_constexpr_string(arg)) { + if (const auto* class_name = VertexUtil::get_constexpr_string(arg)) { if (auto klass = G->get_class(*class_name)) { return Assumption(klass); } } } } - if (const auto *as_ffi = return_typehint->try_as()) { + if (const auto* as_ffi = return_typehint->try_as()) { return Assumption(as_ffi); } - if (const auto *as_ffi_scope = return_typehint->try_as()) { + if (const auto* as_ffi_scope = return_typehint->try_as()) { if (auto arg = VertexUtil::get_call_arg_ref(as_ffi_scope->arg_num, call)) { - if (const auto *scope_name = VertexUtil::get_constexpr_string(arg)) { + if (const auto* scope_name = VertexUtil::get_constexpr_string(arg)) { if (auto module_class = G->get_class(FFIRoot::scope_class_name(*scope_name))) { return Assumption(module_class); } @@ -616,7 +609,7 @@ Assumption infer_from_array(FunctionPtr f, VertexAdaptor array, Vertex } Assumption infer_from_tuple(FunctionPtr f, VertexAdaptor tuple, VertexPtr stop_at) { - std::vector sub; + std::vector sub; for (auto sub_expr : *tuple) { sub.emplace_back(assume_class_of_expr(f, sub_expr, stop_at).assum_hint ?: TypeHintPrimitive::create(tp_any)); } @@ -624,9 +617,9 @@ Assumption infer_from_tuple(FunctionPtr f, VertexAdaptor tuple, Vertex } Assumption infer_from_shape(FunctionPtr f, VertexAdaptor shape, VertexPtr stop_at) { - std::vector> sub; + std::vector> sub; for (auto sub_expr : shape->args()) { - const std::string &shape_key = VertexUtil::get_actual_value(sub_expr->front())->get_string(); + const std::string& shape_key = VertexUtil::get_actual_value(sub_expr->front())->get_string(); sub.emplace_back(shape_key, assume_class_of_expr(f, sub_expr->back(), stop_at).assum_hint ?: TypeHintPrimitive::create(tp_any)); } return Assumption(TypeHintShape::create(std::move(sub), false)); @@ -652,21 +645,21 @@ Assumption infer_from_null_coalesce(FunctionPtr f, VertexAdaptorlhs(), null_coalesce->rhs(), stop_at); } -Assumption infer_from_instance_prop(FunctionPtr f __attribute__ ((unused)), VertexAdaptor prop, VertexPtr stop_at __attribute__ ((unused))) { +Assumption infer_from_instance_prop(FunctionPtr f __attribute__((unused)), VertexAdaptor prop, VertexPtr stop_at __attribute__((unused))) { return prop->class_id ? calc_assumption_for_class_instance_field(prop->class_id, prop->str_val) : Assumption(); } -Assumption infer_from_op_lambda(FunctionPtr f __attribute__ ((unused)), VertexAdaptor lambda, VertexPtr stop_at __attribute__ ((unused))) { +Assumption infer_from_op_lambda(FunctionPtr f __attribute__((unused)), VertexAdaptor lambda, VertexPtr stop_at __attribute__((unused))) { return Assumption(TypeHintCallable::create_ptr_to_function(lambda->func_id)); } Assumption infer_from_invoke_call(FunctionPtr f, VertexAdaptor invoke_call, VertexPtr stop_at) { // we have $cb(...) transformed to op_invoke_call($cb, ...), this is called on $cb()->prop Assumption cb_assum = assume_class_of_expr(f, invoke_call->args()[0], stop_at); - const TypeHint *assum_hint = assumption_unwrap_optional(cb_assum.assum_hint) ?: TypeHintPrimitive::create(tp_any); + const TypeHint* assum_hint = assumption_unwrap_optional(cb_assum.assum_hint) ?: TypeHintPrimitive::create(tp_any); // $cb can be a raw callable got from op_lambda, while deducing types (until generics and lambdas are instantiated) - if (const auto *as_callable = assum_hint->try_as()) { + if (const auto* as_callable = assum_hint->try_as()) { if (as_callable->is_untyped_callable() && as_callable->f_bound_to) { return assume_return_of_function(as_callable->f_bound_to); } else if (as_callable->is_typed_callable()) { @@ -685,7 +678,6 @@ Assumption infer_from_invoke_call(FunctionPtr f, VertexAdaptor i } // namespace - // a public function of this module: deduce the result type of f // for `$a = getSome(), $a->...` or `getSome()->...`, we need to deduce the result type of getSome() // that information can be obtained from the @return tag or returns analysis in body @@ -713,7 +705,8 @@ Assumption assume_return_of_function(FunctionPtr f) { run_function_pass(f, &ret_pass); f->assumption_pass_status = FunctionData::AssumptionStatus::done_returns_in_body; } else if (expected == FunctionData::AssumptionStatus::processing_returns_in_body) { - while (f->assumption_pass_status == FunctionData::AssumptionStatus::processing_returns_in_body && f->assumption_processing_thread != std::this_thread::get_id()) { + while (f->assumption_pass_status == FunctionData::AssumptionStatus::processing_returns_in_body && + f->assumption_processing_thread != std::this_thread::get_id()) { std::this_thread::sleep_for(std::chrono::nanoseconds{100}); } } @@ -728,75 +721,75 @@ Assumption assume_return_of_function(FunctionPtr f) { // and if he have to traverse the function body, we start analyzing from the start and finist at stop_at) Assumption assume_class_of_expr(FunctionPtr f, VertexPtr root, VertexPtr stop_at) { switch (root->type()) { - case op_var: - return infer_from_var(f, root.as(), stop_at); - case op_instance_prop: - return infer_from_instance_prop(f, root.as(), stop_at); - case op_func_call: - return infer_from_call(f, root.as(), stop_at); - case op_invoke_call: - return infer_from_invoke_call(f, root.as(), stop_at); - case op_ffi_load_call: - return infer_from_call(f, root.as()->func_call(), stop_at); - case op_ffi_addr: - return assume_class_of_expr(f, root.as()->expr(), stop_at); - case op_ffi_cast: - return Assumption(root.as()->php_type); - case op_ffi_new: - return Assumption(root.as()->php_type); - case op_ffi_c2php_conv: - return Assumption(root.as()->php_type); - case op_ffi_cdata_value_ref: - return assume_class_of_expr(f, root.as()->expr(), stop_at); - case op_ffi_array_get: - return Assumption(root.as()->c_elem_type); - case op_index: { - auto index = root.as(); - if (index->has_key()) { - return assume_class_of_expr(f, index->array(), stop_at).get_subkey_by_index(index->key()); - } - return {}; + case op_var: + return infer_from_var(f, root.as(), stop_at); + case op_instance_prop: + return infer_from_instance_prop(f, root.as(), stop_at); + case op_func_call: + return infer_from_call(f, root.as(), stop_at); + case op_invoke_call: + return infer_from_invoke_call(f, root.as(), stop_at); + case op_ffi_load_call: + return infer_from_call(f, root.as()->func_call(), stop_at); + case op_ffi_addr: + return assume_class_of_expr(f, root.as()->expr(), stop_at); + case op_ffi_cast: + return Assumption(root.as()->php_type); + case op_ffi_new: + return Assumption(root.as()->php_type); + case op_ffi_c2php_conv: + return Assumption(root.as()->php_type); + case op_ffi_cdata_value_ref: + return assume_class_of_expr(f, root.as()->expr(), stop_at); + case op_ffi_array_get: + return Assumption(root.as()->c_elem_type); + case op_index: { + auto index = root.as(); + if (index->has_key()) { + return assume_class_of_expr(f, index->array(), stop_at).get_subkey_by_index(index->key()); } - case op_array: - return infer_from_array(f, root.as(), stop_at); - case op_tuple: - return infer_from_tuple(f, root.as(), stop_at); - case op_shape: - return infer_from_shape(f, root.as(), stop_at); - case op_ternary: - return infer_from_ternary(f, root.as(), stop_at); - case op_null_coalesce: - return infer_from_null_coalesce(f, root.as(), stop_at); - case op_lambda: - return infer_from_op_lambda(f, root.as(), stop_at); - case op_conv_array: - case op_conv_array_l: - return assume_class_of_expr(f, root.as()->expr(), stop_at); - case op_clone: - return assume_class_of_expr(f, root.as()->expr(), stop_at); - case op_seq_rval: - return assume_class_of_expr(f, root.as()->back(), stop_at); - case op_move: - return assume_class_of_expr(f, root.as()->expr(), stop_at); - case op_set: - return assume_class_of_expr(f, root.as()->rhs(), stop_at); - case op_define_val: - return assume_class_of_expr(f, root.as()->value(), stop_at); - - // assumptions for primitives aren't saved to $local_vars and don't help to resolve ->arrows, - // but they are useful for generics reification - case op_int_const: - return Assumption(TypeHintPrimitive::create(tp_int)); - case op_float_const: - return Assumption(TypeHintPrimitive::create(tp_float)); - case op_string: - case op_conv_string: - return Assumption(TypeHintPrimitive::create(tp_string)); - case op_false: - case op_true: - return Assumption(TypeHintPrimitive::create(tp_bool)); - - default: - return {}; + return {}; + } + case op_array: + return infer_from_array(f, root.as(), stop_at); + case op_tuple: + return infer_from_tuple(f, root.as(), stop_at); + case op_shape: + return infer_from_shape(f, root.as(), stop_at); + case op_ternary: + return infer_from_ternary(f, root.as(), stop_at); + case op_null_coalesce: + return infer_from_null_coalesce(f, root.as(), stop_at); + case op_lambda: + return infer_from_op_lambda(f, root.as(), stop_at); + case op_conv_array: + case op_conv_array_l: + return assume_class_of_expr(f, root.as()->expr(), stop_at); + case op_clone: + return assume_class_of_expr(f, root.as()->expr(), stop_at); + case op_seq_rval: + return assume_class_of_expr(f, root.as()->back(), stop_at); + case op_move: + return assume_class_of_expr(f, root.as()->expr(), stop_at); + case op_set: + return assume_class_of_expr(f, root.as()->rhs(), stop_at); + case op_define_val: + return assume_class_of_expr(f, root.as()->value(), stop_at); + + // assumptions for primitives aren't saved to $local_vars and don't help to resolve ->arrows, + // but they are useful for generics reification + case op_int_const: + return Assumption(TypeHintPrimitive::create(tp_int)); + case op_float_const: + return Assumption(TypeHintPrimitive::create(tp_float)); + case op_string: + case op_conv_string: + return Assumption(TypeHintPrimitive::create(tp_string)); + case op_false: + case op_true: + return Assumption(TypeHintPrimitive::create(tp_bool)); + + default: + return {}; } } diff --git a/compiler/class-assumptions.h b/compiler/class-assumptions.h index 15d45d683c..ab365c459f 100644 --- a/compiler/class-assumptions.h +++ b/compiler/class-assumptions.h @@ -9,33 +9,39 @@ #include "compiler/debug.h" class Assumption { - DEBUG_STRING_METHOD { return as_human_readable(); } + DEBUG_STRING_METHOD { + return as_human_readable(); + } public: // the only field of Assumption indicates a possible state: // 1) nullptr — undefined (meaning "not instance inside") // 2) otherwise, it contains an instance inside // important! no int / string[] / tuple(int): only if it has instances! (so that it will help -> resolving) - const TypeHint *assum_hint{nullptr}; + const TypeHint* assum_hint{nullptr}; Assumption() = default; - explicit Assumption(const TypeHint *type_hint) : assum_hint(type_hint) {} + explicit Assumption(const TypeHint* type_hint) + : assum_hint(type_hint) {} explicit Assumption(ClassPtr klass); std::string as_human_readable() const; - explicit operator bool() const { return assum_hint != nullptr; } + explicit operator bool() const { + return assum_hint != nullptr; + } - ClassPtr try_as_class() const { return extract_instance_from_type_hint(assum_hint); } + ClassPtr try_as_class() const { + return extract_instance_from_type_hint(assum_hint); + } Assumption get_inner_if_array() const; Assumption get_subkey_by_index(VertexPtr index_key) const; - static ClassPtr extract_instance_from_type_hint(const TypeHint *type_hint); + static ClassPtr extract_instance_from_type_hint(const TypeHint* type_hint); }; - -void assumption_add_for_var(FunctionPtr f, const std::string &var_name, const Assumption &assumption, VertexPtr v_location); -void assumption_add_for_return(FunctionPtr f, const Assumption &assumption, VertexPtr v_location); +void assumption_add_for_var(FunctionPtr f, const std::string& var_name, const Assumption& assumption, VertexPtr v_location); +void assumption_add_for_return(FunctionPtr f, const Assumption& assumption, VertexPtr v_location); Assumption assume_class_of_expr(FunctionPtr f, VertexPtr root, VertexPtr stop_at); Assumption assume_return_of_function(FunctionPtr f); diff --git a/compiler/code-gen/code-gen-root-cmd.h b/compiler/code-gen/code-gen-root-cmd.h index bbfa3806f6..b15a6914fd 100644 --- a/compiler/code-gen/code-gen-root-cmd.h +++ b/compiler/code-gen/code-gen-root-cmd.h @@ -4,6 +4,5 @@ struct CodeGenRootCmd { virtual ~CodeGenRootCmd() = default; - virtual void compile(CodeGenerator &W) const = 0; + virtual void compile(CodeGenerator& W) const = 0; }; - diff --git a/compiler/code-gen/code-gen-task.cpp b/compiler/code-gen/code-gen-task.cpp index 52b5145331..d635405895 100644 --- a/compiler/code-gen/code-gen-task.cpp +++ b/compiler/code-gen/code-gen-task.cpp @@ -2,27 +2,27 @@ // Copyright (c) 2020 LLC «V Kontakte» // Distributed under the GPL v3 License, see LICENSE.notice.txt -#include "compiler/code-gen/code-gen-root-cmd.h" #include "compiler/code-gen/code-gen-task.h" +#include "compiler/code-gen/code-gen-root-cmd.h" // this os exists to be passed to CodeGenerator constructor, // but it won't be used actually, as CodeGenerator is not created in "just calc hashes" mode -static DataStream dummy_os; +static DataStream dummy_os; -ProfilerRaw &get_code_gen_profiler() { +ProfilerRaw& get_code_gen_profiler() { static CachedProfiler profiler{"Code generation - calc hashes"}; return *profiler; } -CodeGenSchedulerTask::CodeGenSchedulerTask(DataStream> &os, std::unique_ptr &&cmd) - : W(true, dummy_os) - , os(os) - , cmd(std::move(cmd)) {} +CodeGenSchedulerTask::CodeGenSchedulerTask(DataStream>& os, std::unique_ptr&& cmd) + : W(true, dummy_os), + os(os), + cmd(std::move(cmd)) {} void CodeGenSchedulerTask::execute() { AutoProfiler profler{get_code_gen_profiler()}; stage::set_name("Code generation"); - + cmd->compile(W); // if a command produced diff since the previous kphp launch, forward it next, it will be re-launched and saved if (W.was_diff_in_any_file()) { diff --git a/compiler/code-gen/code-gen-task.h b/compiler/code-gen/code-gen-task.h index 7b351fa452..2e630ac852 100644 --- a/compiler/code-gen/code-gen-task.h +++ b/compiler/code-gen/code-gen-task.h @@ -9,21 +9,21 @@ #include "compiler/stage.h" #include "compiler/threading/profiler.h" -ProfilerRaw &get_code_gen_profiler(); +ProfilerRaw& get_code_gen_profiler(); struct CodeGenRootCmd; class CodeGenSchedulerTask : public Task { CodeGenerator W; - DataStream> &os; + DataStream>& os; std::unique_ptr cmd; public: - CodeGenSchedulerTask(DataStream> &os, std::unique_ptr &&cmd); + CodeGenSchedulerTask(DataStream>& os, std::unique_ptr&& cmd); void execute() final; }; -inline void code_gen_start_root_task(DataStream> &os, std::unique_ptr &&cmd) { +inline void code_gen_start_root_task(DataStream>& os, std::unique_ptr&& cmd) { register_async_task(new CodeGenSchedulerTask(os, std::move(cmd))); } diff --git a/compiler/code-gen/code-generator.cpp b/compiler/code-gen/code-generator.cpp index 7b85d78e94..6915fdeb1c 100644 --- a/compiler/code-gen/code-generator.cpp +++ b/compiler/code-gen/code-generator.cpp @@ -2,11 +2,11 @@ // Copyright (c) 2021 LLC «V Kontakte» // Distributed under the GPL v3 License, see LICENSE.notice.txt -#include "compiler/compiler-core.h" #include "compiler/code-gen/code-generator.h" +#include "compiler/compiler-core.h" #include "compiler/data/src-file.h" -void CodeGenerator::open_file_create_writer(bool compile_with_debug_info_flag, bool compile_with_crc, const std::string &file_name, const std::string &subdir) { +void CodeGenerator::open_file_create_writer(bool compile_with_debug_info_flag, bool compile_with_crc, const std::string& file_name, const std::string& subdir) { std::string full_file_name = G->cpp_dir; if (!subdir.empty()) { full_file_name += subdir; @@ -14,8 +14,8 @@ void CodeGenerator::open_file_create_writer(bool compile_with_debug_info_flag, b } full_file_name += file_name; - const auto &exclude_from_debug = G->get_exclude_namespaces(); - for (const auto &exclude_symbol : exclude_from_debug) { + const auto& exclude_from_debug = G->get_exclude_namespaces(); + for (const auto& exclude_symbol : exclude_from_debug) { if (file_name.rfind(exclude_symbol, 0) != std::string::npos) { compile_with_debug_info_flag = false; } @@ -66,8 +66,8 @@ void CodeGenerator::close_file_clear_writer() { kphp_assert(data != nullptr); data->end_line(); data->set_calculated_hashes(hash_of_cpp, hash_of_comments); - os << data; // pass it to WriteFilesF - data = nullptr; // do not delete data, as it will be used by and deleted by WriteFilesF + os << data; // pass it to WriteFilesF + data = nullptr; // do not delete data, as it will be used by and deleted by WriteFilesF } } @@ -76,14 +76,14 @@ void CodeGenerator::feed_hash_of_comments(SrcFilePtr file, int line_num) { hash_of_comments = hash_of_comments * 56235415617457ULL + string_hash(line_contents.data(), line_contents.size()); } -void CodeGenerator::add_include(const std::string &s) { +void CodeGenerator::add_include(const std::string& s) { kphp_assert(cur_file != nullptr); feed_hash(string_hash(s.c_str(), s.size())); // we need to store includes even when just calculating hashes — to make a dependency map for make cur_file->includes.emplace_front(s); } -void CodeGenerator::add_lib_include(const std::string &s) { +void CodeGenerator::add_lib_include(const std::string& s) { kphp_assert(cur_file != nullptr); feed_hash(string_hash(s.c_str(), s.size())); cur_file->lib_includes.emplace_front(s); diff --git a/compiler/code-gen/code-generator.h b/compiler/code-gen/code-generator.h index 8207b7ce9f..be719305a6 100644 --- a/compiler/code-gen/code-generator.h +++ b/compiler/code-gen/code-generator.h @@ -18,7 +18,7 @@ struct CGContext { std::vector catch_labels; std::vector catch_label_used; FunctionPtr parent_func; - const TypeData *null_coalescing_rhs_t{}; + const TypeData* null_coalescing_rhs_t{}; bool resumable_flag{false}; bool interruptible_flag{false}; bool namespace_opened{false}; @@ -45,11 +45,11 @@ class CodeGenerator { // (one codegen command may produce multiple files, they are set to 0 on opening a new one) unsigned long long hash_of_cpp; unsigned long long hash_of_comments; - File *cur_file{nullptr}; + File* cur_file{nullptr}; + + WriterData* data{nullptr}; // stored contents, is created only on step 2 (re-generating diff files) + DataStream& os; // output stream for stored contents, used only on step 2 - WriterData *data{nullptr}; // stored contents, is created only on step 2 (re-generating diff files) - DataStream &os; // output stream for stored contents, used only on step 2 - CGContext context; int indent_level; @@ -63,16 +63,15 @@ class CodeGenerator { void feed_hash_of_comments(SrcFilePtr file, int line_num); public: - - explicit CodeGenerator(bool is_step_just_calc_hashes, DataStream &os) - : is_step_just_calc_hashes(is_step_just_calc_hashes) - , os(os) {} + explicit CodeGenerator(bool is_step_just_calc_hashes, DataStream& os) + : is_step_just_calc_hashes(is_step_just_calc_hashes), + os(os) {} ~CodeGenerator() = default; - CodeGenerator(const CodeGenerator &from) = delete; - CodeGenerator &operator=(const CodeGenerator &) = delete; + CodeGenerator(const CodeGenerator& from) = delete; + CodeGenerator& operator=(const CodeGenerator&) = delete; - void open_file_create_writer(bool compile_with_debug_info_flag, bool compile_with_crc, const std::string &file_name, const std::string &subdir); + void open_file_create_writer(bool compile_with_debug_info_flag, bool compile_with_crc, const std::string& file_name, const std::string& subdir); void close_file_clear_writer(); void append(char c) { @@ -82,7 +81,7 @@ class CodeGenerator { } } - void append(const char *p, size_t len) { + void append(const char* p, size_t len) { if (need_indent) { need_indent = false; feed_hash(static_cast(' ') * indent_level); @@ -132,7 +131,6 @@ class CodeGenerator { } } - void indent(int diff) { indent_level += diff; } @@ -168,10 +166,10 @@ class CodeGenerator { lock_comments_cnt--; } - void add_include(const std::string &s); - void add_lib_include(const std::string &s); + void add_include(const std::string& s); + void add_lib_include(const std::string& s); - CGContext &get_context() { + CGContext& get_context() { return context; } @@ -181,58 +179,57 @@ class CodeGenerator { }; template -CodeGenerator &operator<<(CodeGenerator &c, const T &value) { +CodeGenerator& operator<<(CodeGenerator& c, const T& value) { value.compile(c); return c; } -inline CodeGenerator &operator<<(CodeGenerator &c, const std::string &value) { +inline CodeGenerator& operator<<(CodeGenerator& c, const std::string& value) { c.append(value.c_str(), value.size()); return c; } -inline CodeGenerator &operator<<(CodeGenerator &c, const char *value) { +inline CodeGenerator& operator<<(CodeGenerator& c, const char* value) { c.append(value, strlen(value)); return c; } -inline CodeGenerator &operator<<(CodeGenerator &c, const vk::string_view &value) { +inline CodeGenerator& operator<<(CodeGenerator& c, const vk::string_view& value) { c.append(value.data(), value.size()); return c; } -inline CodeGenerator &operator<<(CodeGenerator &c, long long value) { +inline CodeGenerator& operator<<(CodeGenerator& c, long long value) { c.append(value); return c; } -inline CodeGenerator &operator<<(CodeGenerator &c, long value) { +inline CodeGenerator& operator<<(CodeGenerator& c, long value) { c.append(static_cast(value)); return c; } -inline CodeGenerator &operator<<(CodeGenerator &c, unsigned long long value) { +inline CodeGenerator& operator<<(CodeGenerator& c, unsigned long long value) { c.append(value); return c; } -inline CodeGenerator &operator<<(CodeGenerator &c, unsigned long value) { +inline CodeGenerator& operator<<(CodeGenerator& c, unsigned long value) { c.append(static_cast(value)); return c; } -inline CodeGenerator &operator<<(CodeGenerator &c, int value) { +inline CodeGenerator& operator<<(CodeGenerator& c, int value) { c.append(value); return c; } -inline CodeGenerator &operator<<(CodeGenerator &c, unsigned int value) { +inline CodeGenerator& operator<<(CodeGenerator& c, unsigned int value) { c.append(value); return c; } -inline CodeGenerator& operator<<(CodeGenerator &c, char value) { +inline CodeGenerator& operator<<(CodeGenerator& c, char value) { c.append(value); return c; } - diff --git a/compiler/code-gen/common.h b/compiler/code-gen/common.h index 40534ffc16..49bf2c8446 100644 --- a/compiler/code-gen/common.h +++ b/compiler/code-gen/common.h @@ -21,12 +21,11 @@ struct OpenFile { std::string subdir; bool compile_with_debug_info_flag; bool compile_with_crc; - OpenFile(const std::string &file_name, const std::string &subdir = "", - bool compile_with_debug_info_flag = true, bool compile_with_crc = true) : - file_name(file_name), - subdir(subdir), - compile_with_debug_info_flag(compile_with_debug_info_flag), - compile_with_crc(compile_with_crc) { + OpenFile(const std::string& file_name, const std::string& subdir = "", bool compile_with_debug_info_flag = true, bool compile_with_crc = true) + : file_name(file_name), + subdir(subdir), + compile_with_debug_info_flag(compile_with_debug_info_flag), + compile_with_crc(compile_with_crc) { double debug_info_disable_prob = G->settings().debug_info_force_disable_prob.get(); if (compile_with_debug_info_flag && debug_info_disable_prob > 0) { if (flip_coin(debug_info_disable_prob)) { @@ -46,23 +45,22 @@ struct OpenFile { return hash * seed % PROB_RANGE < prob * PROB_RANGE; } - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { W.open_file_create_writer(compile_with_debug_info_flag, compile_with_crc, file_name, subdir); } }; struct CloseFile { - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { W.close_file_clear_writer(); } }; struct UpdateLocation { - const Location &location; - explicit UpdateLocation(const Location &location): - location(location) { - } - void compile(CodeGenerator &W) const { + const Location& location; + explicit UpdateLocation(const Location& location) + : location(location) {} + void compile(CodeGenerator& W) const { if (!W.is_comments_locked()) { stage::set_location(location); W.add_location(stage::get_file(), stage::get_line()); @@ -71,59 +69,57 @@ struct UpdateLocation { }; struct NewLine { - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { W.new_line(); } }; struct Indent { int val; - Indent(int val) : val(val) { } - inline void compile(CodeGenerator &W) const { + Indent(int val) + : val(val) {} + inline void compile(CodeGenerator& W) const { W.indent(val); } }; struct OpenBlock { - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { W << "{" << NL << Indent(+2); } }; struct CloseBlock { - inline void compile(CodeGenerator &W) const { + inline void compile(CodeGenerator& W) const { W << Indent(-2) << "}"; } }; struct SemicolonAndNL { - inline void compile(CodeGenerator &W) const { + inline void compile(CodeGenerator& W) const { W << ";" << NL; } }; struct LockComments { - inline void compile(CodeGenerator &W) const { + inline void compile(CodeGenerator& W) const { W.lock_comments(); } }; struct UnlockComments { - inline void compile(CodeGenerator &W) const { + inline void compile(CodeGenerator& W) const { W.unlock_comments(); } }; -enum class join_mode { - one_line, - multiple_lines -}; +enum class join_mode { one_line, multiple_lines }; template struct ValueSelfGen { using element_type = decltype(*std::begin(std::declval())); - void operator()(CodeGenerator &W, const element_type &obj) const { + void operator()(CodeGenerator& W, const element_type& obj) const { W << obj; } }; @@ -131,14 +127,13 @@ struct ValueSelfGen { template> class JoinValues { public: - JoinValues(const T &values_container, const char *sep, join_mode mode = join_mode::one_line, const F &value_gen = {}) : - values_container_(values_container), - sep_(sep), - mode_(mode), - value_gen_(value_gen) { - } + JoinValues(const T& values_container, const char* sep, join_mode mode = join_mode::one_line, const F& value_gen = {}) + : values_container_(values_container), + sep_(sep), + mode_(mode), + value_gen_(value_gen) {} - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { auto it = std::begin(values_container_); const auto last = std::end(values_container_); for (; it != last;) { @@ -153,8 +148,8 @@ class JoinValues { } private: - const T &values_container_; - const char *sep_{nullptr}; + const T& values_container_; + const char* sep_{nullptr}; const join_mode mode_{join_mode::one_line}; F value_gen_; }; diff --git a/compiler/code-gen/const-globals-batched-mem.cpp b/compiler/code-gen/const-globals-batched-mem.cpp index e02d0d6117..b4e50262a7 100644 --- a/compiler/code-gen/const-globals-batched-mem.cpp +++ b/compiler/code-gen/const-globals-batched-mem.cpp @@ -9,9 +9,9 @@ #include "common/php-functions.h" -#include "compiler/compiler-core.h" #include "compiler/code-gen/common.h" #include "compiler/code-gen/includes.h" +#include "compiler/compiler-core.h" #include "compiler/data/var-data.h" #include "compiler/inferring/public.h" @@ -22,45 +22,45 @@ namespace { ConstantsBatchedMem constants_batched_mem; GlobalsBatchedMem globals_batched_mem; -int calc_sizeof_tuple_shape(const TypeData *type); +int calc_sizeof_tuple_shape(const TypeData* type); -[[gnu::always_inline]] inline int calc_sizeof_in_bytes_runtime(const TypeData *type) { +[[gnu::always_inline]] inline int calc_sizeof_in_bytes_runtime(const TypeData* type) { switch (type->get_real_ptype()) { - case tp_int: - return type->use_optional() ? SIZEOF_OPTIONAL + sizeof(int64_t) : sizeof(int64_t); - case tp_float: - return type->use_optional() ? SIZEOF_OPTIONAL + sizeof(double) : sizeof(double); - case tp_string: - return type->use_optional() ? SIZEOF_OPTIONAL + SIZEOF_STRING : SIZEOF_STRING; - case tp_array: - return type->use_optional() ? SIZEOF_OPTIONAL + SIZEOF_ARRAY_ANY : SIZEOF_ARRAY_ANY; - case tp_regexp: - kphp_assert(!type->use_optional()); - return SIZEOF_REGEXP; - case tp_Class: - kphp_assert(!type->use_optional()); - return SIZEOF_INSTANCE_ANY; - case tp_mixed: - kphp_assert(!type->use_optional()); - return SIZEOF_MIXED; - case tp_bool: - return type->use_optional() ? 2 : 1; - case tp_tuple: - case tp_shape: - return calc_sizeof_tuple_shape(type); - case tp_future: - return type->use_optional() ? SIZEOF_OPTIONAL + SIZEOF_FUTURE : SIZEOF_FUTURE; - case tp_future_queue: - return type->use_optional() ? SIZEOF_OPTIONAL + SIZEOF_FUTURE_QUEUE : SIZEOF_FUTURE_QUEUE; - case tp_any: - return SIZEOF_UNKNOWN; - default: - kphp_error(0, fmt_format("Unable to detect sizeof() for type = {}", type->as_human_readable())); - return 0; + case tp_int: + return type->use_optional() ? SIZEOF_OPTIONAL + sizeof(int64_t) : sizeof(int64_t); + case tp_float: + return type->use_optional() ? SIZEOF_OPTIONAL + sizeof(double) : sizeof(double); + case tp_string: + return type->use_optional() ? SIZEOF_OPTIONAL + SIZEOF_STRING : SIZEOF_STRING; + case tp_array: + return type->use_optional() ? SIZEOF_OPTIONAL + SIZEOF_ARRAY_ANY : SIZEOF_ARRAY_ANY; + case tp_regexp: + kphp_assert(!type->use_optional()); + return SIZEOF_REGEXP; + case tp_Class: + kphp_assert(!type->use_optional()); + return SIZEOF_INSTANCE_ANY; + case tp_mixed: + kphp_assert(!type->use_optional()); + return SIZEOF_MIXED; + case tp_bool: + return type->use_optional() ? 2 : 1; + case tp_tuple: + case tp_shape: + return calc_sizeof_tuple_shape(type); + case tp_future: + return type->use_optional() ? SIZEOF_OPTIONAL + SIZEOF_FUTURE : SIZEOF_FUTURE; + case tp_future_queue: + return type->use_optional() ? SIZEOF_OPTIONAL + SIZEOF_FUTURE_QUEUE : SIZEOF_FUTURE_QUEUE; + case tp_any: + return SIZEOF_UNKNOWN; + default: + kphp_error(0, fmt_format("Unable to detect sizeof() for type = {}", type->as_human_readable())); + return 0; } } -[[gnu::noinline]] int calc_sizeof_tuple_shape(const TypeData *type) { +[[gnu::noinline]] int calc_sizeof_tuple_shape(const TypeData* type) { kphp_assert(vk::any_of_equal(type->ptype(), tp_tuple, tp_shape)); int result = 0; @@ -76,56 +76,62 @@ int calc_sizeof_tuple_shape(const TypeData *type); if (has_align_8bytes) { result = (result + 7) & -8; } - return type->use_optional() - ? has_align_8bytes ? SIZEOF_OPTIONAL + result : 1 + result - : result; + return type->use_optional() ? has_align_8bytes ? SIZEOF_OPTIONAL + result : 1 + result : result; } } // namespace - -void ConstantsBatchedMem::inc_count_by_type(const TypeData *type) { +void ConstantsBatchedMem::inc_count_by_type(const TypeData* type) { if (type->use_optional()) { count_of_type_other++; return; } switch (type->get_real_ptype()) { - case tp_string: - count_of_type_string++; - break; - case tp_regexp: - count_of_type_regexp++; - break; - case tp_array: - count_of_type_array++; - return; - case tp_mixed: - count_of_type_mixed++; - break; - case tp_Class: - count_of_type_instance++; - break; - default: - count_of_type_other++; + case tp_string: + count_of_type_string++; + break; + case tp_regexp: + count_of_type_regexp++; + break; + case tp_array: + count_of_type_array++; + return; + case tp_mixed: + count_of_type_mixed++; + break; + case tp_Class: + count_of_type_instance++; + break; + default: + count_of_type_other++; } } int ConstantsBatchedMem::detect_constants_batch_count(int n_constants) { // these values are heuristics (don't use integer division, to avoid changing buckets count frequently) - if (n_constants > 1200000) return 2048; - if (n_constants > 800000) return 1536; - if (n_constants > 500000) return 1024; - if (n_constants > 100000) return 512; - if (n_constants > 10000) return 256; - if (n_constants > 5000) return 128; - if (n_constants > 1000) return 32; - if (n_constants > 500) return 16; - if (n_constants > 100) return 4; + if (n_constants > 1200000) + return 2048; + if (n_constants > 800000) + return 1536; + if (n_constants > 500000) + return 1024; + if (n_constants > 100000) + return 512; + if (n_constants > 10000) + return 256; + if (n_constants > 5000) + return 128; + if (n_constants > 1000) + return 32; + if (n_constants > 500) + return 16; + if (n_constants > 100) + return 4; return 1; } -const ConstantsBatchedMem &ConstantsBatchedMem::prepare_mem_and_assign_offsets(const std::vector &all_constants) { - ConstantsBatchedMem &mem = constants_batched_mem; +const ConstantsBatchedMem& ConstantsBatchedMem::prepare_mem_and_assign_offsets(const std::vector& all_constants) { + ConstantsBatchedMem& mem = constants_batched_mem; const int N_BATCHES = detect_constants_batch_count(all_constants.size()); mem.batches.resize(N_BATCHES); @@ -148,15 +154,13 @@ const ConstantsBatchedMem &ConstantsBatchedMem::prepare_mem_and_assign_offsets(c mem.batches[var->batch_idx].constants.emplace_back(var); } - for (OneBatchInfo &batch : mem.batches) { + for (OneBatchInfo& batch : mem.batches) { // sort constants by name to make codegen stable - std::sort(batch.constants.begin(), batch.constants.end(), [](VarPtr c1, VarPtr c2) -> bool { - return c1->name.compare(c2->name) < 0; - }); + std::sort(batch.constants.begin(), batch.constants.end(), [](VarPtr c1, VarPtr c2) -> bool { return c1->name.compare(c2->name) < 0; }); for (VarPtr var : batch.constants) { - const TypeData *var_type = tinf::get_type(var); - mem.inc_count_by_type(var_type); // count stat to output it + const TypeData* var_type = tinf::get_type(var); + mem.inc_count_by_type(var_type); // count stat to output it } mem.total_count += batch.constants.size(); @@ -176,21 +180,27 @@ void GlobalsBatchedMem::inc_count_by_origin(VarPtr var) { count_of_require_once++; } else if (!var->is_builtin_runtime) { count_of_php_global_scope++; - } + } } int GlobalsBatchedMem::detect_globals_batch_count(int n_globals) { - if (n_globals > 10000) return 256; - if (n_globals > 5000) return 128; - if (n_globals > 1000) return 32; - if (n_globals > 500) return 16; - if (n_globals > 100) return 4; - if (n_globals > 50) return 2; + if (n_globals > 10000) + return 256; + if (n_globals > 5000) + return 128; + if (n_globals > 1000) + return 32; + if (n_globals > 500) + return 16; + if (n_globals > 100) + return 4; + if (n_globals > 50) + return 2; return 1; } -const GlobalsBatchedMem &GlobalsBatchedMem::prepare_mem_and_assign_offsets(const std::vector &all_globals) { - GlobalsBatchedMem &mem = globals_batched_mem; +const GlobalsBatchedMem& GlobalsBatchedMem::prepare_mem_and_assign_offsets(const std::vector& all_globals) { + GlobalsBatchedMem& mem = globals_batched_mem; const int N_BATCHES = detect_globals_batch_count(all_globals.size()); mem.batches.resize(N_BATCHES); @@ -210,7 +220,7 @@ const GlobalsBatchedMem &GlobalsBatchedMem::prepare_mem_and_assign_offsets(const mem.batches[var->batch_idx].globals.emplace_back(var); } - for (OneBatchInfo &batch : mem.batches) { + for (OneBatchInfo& batch : mem.batches) { // sort variables by name to make codegen stable // note, that all_globals contains also function static vars (explicitly added), // and their names can duplicate or be equal to global vars; @@ -224,8 +234,10 @@ const GlobalsBatchedMem &GlobalsBatchedMem::prepare_mem_and_assign_offsets(const } else if (c1 == c2) { return false; } else { - if (!c1->holder_func) return true; - if (!c2->holder_func) return false; + if (!c1->holder_func) + return true; + if (!c2->holder_func) + return false; return c1->holder_func->name.compare(c2->holder_func->name) < 0; } }); @@ -233,7 +245,7 @@ const GlobalsBatchedMem &GlobalsBatchedMem::prepare_mem_and_assign_offsets(const int offset = 0; for (VarPtr var : batch.globals) { - const TypeData *var_type = tinf::get_type(var); + const TypeData* var_type = tinf::get_type(var); int cur_sizeof = (calc_sizeof_in_bytes_runtime(var_type) + 7) & -8; // min 8 bytes per variable var->offset_in_linear_mem = mem.total_mem_size + offset; // it's continuous @@ -270,14 +282,14 @@ void ConstantsExternCollector::add_extern_from_init_val(VertexPtr init_val) { } } -void ConstantsExternCollector::compile(CodeGenerator &W) const { +void ConstantsExternCollector::compile(CodeGenerator& W) const { for (VarPtr c : extern_constants) { W << "extern " << type_out(tinf::get_type(c)) << " " << c->name << ";" << NL; } } -void ConstantsMemAllocation::compile(CodeGenerator &W) const { - const ConstantsBatchedMem &mem = constants_batched_mem; +void ConstantsMemAllocation::compile(CodeGenerator& W) const { + const ConstantsBatchedMem& mem = constants_batched_mem; W << "// total_count = " << mem.total_count << NL; W << "// count(string) = " << mem.count_of_type_string << NL; @@ -289,8 +301,8 @@ void ConstantsMemAllocation::compile(CodeGenerator &W) const { W << "// n_batches = " << mem.batches.size() << NL; } -void GlobalsMemAllocation::compile(CodeGenerator &W) const { - const GlobalsBatchedMem &mem = globals_batched_mem; +void GlobalsMemAllocation::compile(CodeGenerator& W) const { + const GlobalsBatchedMem& mem = globals_batched_mem; W << "// total_mem_size = " << mem.total_mem_size << NL; W << "// total_count = " << mem.total_count << NL; @@ -308,32 +320,33 @@ void GlobalsMemAllocation::compile(CodeGenerator &W) const { } } -void PhpMutableGlobalsAssignCurrent::compile(CodeGenerator &W) const { +void PhpMutableGlobalsAssignCurrent::compile(CodeGenerator& W) const { W << "PhpScriptMutableGlobals &php_globals = PhpScriptMutableGlobals::current();" << NL; } -void PhpMutableGlobalsDeclareInResumableClass::compile(CodeGenerator &W) const { +void PhpMutableGlobalsDeclareInResumableClass::compile(CodeGenerator& W) const { W << "PhpScriptMutableGlobals &php_globals;" << NL; } -void PhpMutableGlobalsAssignInResumableConstructor::compile(CodeGenerator &W) const { +void PhpMutableGlobalsAssignInResumableConstructor::compile(CodeGenerator& W) const { W << "php_globals(PhpScriptMutableGlobals::current())"; } -void PhpMutableGlobalsRefArgument::compile(CodeGenerator &W) const { +void PhpMutableGlobalsRefArgument::compile(CodeGenerator& W) const { W << "PhpScriptMutableGlobals &php_globals"; } -void PhpMutableGlobalsConstRefArgument::compile(CodeGenerator &W) const { +void PhpMutableGlobalsConstRefArgument::compile(CodeGenerator& W) const { W << "const PhpScriptMutableGlobals &php_globals"; } -void GlobalVarInPhpGlobals::compile(CodeGenerator &W) const { +void GlobalVarInPhpGlobals::compile(CodeGenerator& W) const { if (global_var->is_builtin_runtime) { W << "php_globals.get_superglobals().v$" << global_var->name; } else if (!G->is_output_mode_lib() && !G->is_output_mode_k2_lib()) { W << "(*reinterpret_cast<" << type_out(tinf::get_type(global_var)) << "*>(php_globals.mem()+" << global_var->offset_in_linear_mem << "))"; } else { - W << "(*reinterpret_cast<" << type_out(tinf::get_type(global_var)) << "*>(php_globals.mem_for_lib(\"" << G->settings().static_lib_name.get() << "\")+" << global_var->offset_in_linear_mem << "))"; + W << "(*reinterpret_cast<" << type_out(tinf::get_type(global_var)) << "*>(php_globals.mem_for_lib(\"" << G->settings().static_lib_name.get() << "\")+" + << global_var->offset_in_linear_mem << "))"; } } diff --git a/compiler/code-gen/const-globals-batched-mem.h b/compiler/code-gen/const-globals-batched-mem.h index 67970e036e..b540ceea52 100644 --- a/compiler/code-gen/const-globals-batched-mem.h +++ b/compiler/code-gen/const-globals-batched-mem.h @@ -49,17 +49,21 @@ class ConstantsBatchedMem { int count_of_type_other = 0; int total_count = 0; - + std::vector batches; - void inc_count_by_type(const TypeData *type); + void inc_count_by_type(const TypeData* type); public: static int detect_constants_batch_count(int n_constants); - static const ConstantsBatchedMem &prepare_mem_and_assign_offsets(const std::vector &all_constants); - - const std::vector &get_batches() const { return batches; } - const OneBatchInfo &get_batch(uint64_t batch_hash) const { return batches.at(batch_hash); } + static const ConstantsBatchedMem& prepare_mem_and_assign_offsets(const std::vector& all_constants); + + const std::vector& get_batches() const { + return batches; + } + const OneBatchInfo& get_batch(uint64_t batch_hash) const { + return batches.at(batch_hash); + } }; // While constants are initialized once in master process, mutable globals exists in each script @@ -108,55 +112,59 @@ class GlobalsBatchedMem { public: static int detect_globals_batch_count(int n_globals); - static const GlobalsBatchedMem &prepare_mem_and_assign_offsets(const std::vector &all_globals); - - const std::vector &get_batches() const { return batches; } - const OneBatchInfo &get_batch(int batch_idx) const { return batches.at(batch_idx); } + static const GlobalsBatchedMem& prepare_mem_and_assign_offsets(const std::vector& all_globals); + + const std::vector& get_batches() const { + return batches; + } + const OneBatchInfo& get_batch(int batch_idx) const { + return batches.at(batch_idx); + } }; struct ConstantsExternCollector { void add_extern_from_var(VarPtr var); void add_extern_from_init_val(VertexPtr init_val); - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; private: std::set extern_constants; }; struct ConstantsMemAllocation { - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; struct GlobalsMemAllocation { - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; struct PhpMutableGlobalsAssignCurrent { - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; struct PhpMutableGlobalsDeclareInResumableClass { - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; struct PhpMutableGlobalsAssignInResumableConstructor { - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; struct PhpMutableGlobalsRefArgument { - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; struct PhpMutableGlobalsConstRefArgument { - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; struct GlobalVarInPhpGlobals { VarPtr global_var; explicit GlobalVarInPhpGlobals(VarPtr global_var) - : global_var(global_var) {} + : global_var(global_var) {} - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; diff --git a/compiler/code-gen/declarations.cpp b/compiler/code-gen/declarations.cpp index 0aa48c32da..a1bdf7c302 100644 --- a/compiler/code-gen/declarations.cpp +++ b/compiler/code-gen/declarations.cpp @@ -15,29 +15,28 @@ #include "compiler/code-gen/naming.h" #include "compiler/code-gen/vertex-compiler.h" #include "compiler/data/class-data.h" -#include "compiler/data/function-data.h" #include "compiler/data/ffi-data.h" +#include "compiler/data/function-data.h" #include "compiler/data/kphp-json-tags.h" -#include "compiler/data/src-file.h" #include "compiler/data/lib-data.h" +#include "compiler/data/src-file.h" #include "compiler/data/var-data.h" -#include "compiler/vertex-util.h" #include "compiler/inferring/public.h" #include "compiler/inferring/type-data.h" #include "compiler/tl-classes.h" +#include "compiler/vertex-util.h" VarDeclaration VarPlainDeclaration(VarPtr var) { return {var, false, false}; } -VarDeclaration::VarDeclaration(VarPtr var, bool extern_flag, bool defval_flag) : - var(var), - extern_flag(extern_flag), - defval_flag(defval_flag) { -} +VarDeclaration::VarDeclaration(VarPtr var, bool extern_flag, bool defval_flag) + : var(var), + extern_flag(extern_flag), + defval_flag(defval_flag) {} -void VarDeclaration::compile(CodeGenerator &W) const { - const TypeData *type = tinf::get_type(var); +void VarDeclaration::compile(CodeGenerator& W) const { + const TypeData* type = tinf::get_type(var); kphp_assert(type->ptype() != tp_void); @@ -52,66 +51,60 @@ void VarDeclaration::compile(CodeGenerator &W) const { } W << ";" << NL; if (var->needs_const_iterator_flag) { - for (const auto &name : {"$it", "$it$end"}) { - W << (extern_flag ? "extern " : "") << - "decltype(const_begin(" << VarName(var) << "))" << " " << VarName(var) << name << ";" << NL; + for (const auto& name : {"$it", "$it$end"}) { + W << (extern_flag ? "extern " : "") << "decltype(const_begin(" << VarName(var) << "))" << " " << VarName(var) << name << ";" << NL; } } } -FunctionDeclaration::FunctionDeclaration(FunctionPtr function, bool in_header, gen_out_style style) : - function(function), - in_header(in_header), - style(style) { -} +FunctionDeclaration::FunctionDeclaration(FunctionPtr function, bool in_header, gen_out_style style) + : function(function), + in_header(in_header), + style(style) {} -void FunctionDeclaration::compile(CodeGenerator &W) const { +void FunctionDeclaration::compile(CodeGenerator& W) const { TypeName ret_type_gen(tinf::get_type(function, -1), style); FunctionParams params_gen(function, in_header, style); switch (style) { - case gen_out_style::tagger: - case gen_out_style::cpp: { - if (function->is_interruptible) { - FunctionSignatureGenerator(W) << "kphp::coro::task<" << ret_type_gen << ">" << " " << FunctionName(function) << "(" - << params_gen << ")"; - } else { - FunctionSignatureGenerator(W) << ret_type_gen << " " << FunctionName(function) << "(" << params_gen << ")"; - } - break; - } - case gen_out_style::txt: { - W << "function " << function->name << "(" << params_gen << ") ::: " << ret_type_gen; - break; + case gen_out_style::tagger: + case gen_out_style::cpp: { + if (function->is_interruptible) { + FunctionSignatureGenerator(W) << "kphp::coro::task<" << ret_type_gen << ">" << " " << FunctionName(function) << "(" << params_gen << ")"; + } else { + FunctionSignatureGenerator(W) << ret_type_gen << " " << FunctionName(function) << "(" << params_gen << ")"; } + break; + } + case gen_out_style::txt: { + W << "function " << function->name << "(" << params_gen << ") ::: " << ret_type_gen; + break; + } } } -FunctionForkDeclaration::FunctionForkDeclaration(FunctionPtr function, bool in_header) : - function(function), - in_header(in_header) { -} +FunctionForkDeclaration::FunctionForkDeclaration(FunctionPtr function, bool in_header) + : function(function), + in_header(in_header) {} -void FunctionForkDeclaration::compile(CodeGenerator &W) const { - FunctionSignatureGenerator(W) << "int64_t " << FunctionForkName(function) << - "(" << FunctionParams(function, in_header) << ")"; +void FunctionForkDeclaration::compile(CodeGenerator& W) const { + FunctionSignatureGenerator(W) << "int64_t " << FunctionForkName(function) << "(" << FunctionParams(function, in_header) << ")"; } -FunctionParams::FunctionParams(FunctionPtr function, bool in_header, gen_out_style style) : - FunctionParams(function, 0, in_header, style) { -} -FunctionParams::FunctionParams(FunctionPtr function, size_t shift, bool in_header, gen_out_style style) : - function(function), - params(function->get_params()), - in_header(in_header), - style(style), - shift(shift) { +FunctionParams::FunctionParams(FunctionPtr function, bool in_header, gen_out_style style) + : FunctionParams(function, 0, in_header, style) {} +FunctionParams::FunctionParams(FunctionPtr function, size_t shift, bool in_header, gen_out_style style) + : function(function), + params(function->get_params()), + in_header(in_header), + style(style), + shift(shift) { if (shift > 0) { params = {std::next(params.begin(), shift), params.end()}; } } -void FunctionParams::declare_cpp_param(CodeGenerator &W, VertexAdaptor var, const TypeName &type) const { +void FunctionParams::declare_cpp_param(CodeGenerator& W, VertexAdaptor var, const TypeName& type) const { W << type << " "; auto var_ptr = var->var_id; if (var->ref_flag) { @@ -122,11 +115,11 @@ void FunctionParams::declare_cpp_param(CodeGenerator &W, VertexAdaptor v W << VarName(var_ptr); } -void FunctionParams::declare_txt_param(CodeGenerator &W, VertexAdaptor var, const TypeName &type) const { +void FunctionParams::declare_txt_param(CodeGenerator& W, VertexAdaptor var, const TypeName& type) const { W << type << " " << (var->ref_flag ? "&" : "") << "$" << var->var_id->name; } -void FunctionParams::compile(CodeGenerator &W) const { +void FunctionParams::compile(CodeGenerator& W) const { bool first = true; size_t ii = shift; for (auto i : params) { @@ -140,40 +133,41 @@ void FunctionParams::compile(CodeGenerator &W) const { auto var = param->var(); TypeName type_gen(tinf::get_type(function, ii), style); switch (style) { - case gen_out_style::tagger: - case gen_out_style::cpp: { - declare_cpp_param(W, var, type_gen); - if (param->has_default_value() && param->default_value() && in_header) { - W << " = " << param->default_value(); - } - break; + case gen_out_style::tagger: + case gen_out_style::cpp: { + declare_cpp_param(W, var, type_gen); + if (param->has_default_value() && param->default_value() && in_header) { + W << " = " << param->default_value(); } - case gen_out_style::txt: { - declare_txt_param(W, var, type_gen); - if (param->has_default_value() && param->default_value() && in_header) { - VertexPtr default_value = VertexUtil::get_actual_value(param->default_value()); - kphp_assert(vk::any_of_equal(default_value->type(), op_int_const, op_float_const)); - W << " = " << default_value->get_string(); - } - break; + break; + } + case gen_out_style::txt: { + declare_txt_param(W, var, type_gen); + if (param->has_default_value() && param->default_value() && in_header) { + VertexPtr default_value = VertexUtil::get_actual_value(param->default_value()); + kphp_assert(vk::any_of_equal(default_value->type(), op_int_const, op_float_const)); + W << " = " << default_value->get_string(); } + break; + } } ii++; } } -FFIDeclaration::FFIDeclaration(ClassPtr ffi_scope): ffi_scope{ffi_scope} {} +FFIDeclaration::FFIDeclaration(ClassPtr ffi_scope) + : ffi_scope{ffi_scope} {} -InterfaceDeclaration::InterfaceDeclaration(InterfacePtr interface) : - interface(interface) { -} +InterfaceDeclaration::InterfaceDeclaration(InterfacePtr interface) + : interface(interface) {} -TlDependentTypesUsings::TlDependentTypesUsings(vk::tlo_parsing::type *tl_type, const std::string &php_tl_class_name) : tl_type(tl_type) { +TlDependentTypesUsings::TlDependentTypesUsings(vk::tlo_parsing::type* tl_type, const std::string& php_tl_class_name) + : tl_type(tl_type) { int template_suf_start = php_tl_class_name.find("__"); kphp_assert(template_suf_start != std::string::npos); specialization_suffix = php_tl_class_name.substr(template_suf_start); - for (const auto &constructor : tl_type->constructors) { - for (const auto &arg : constructor->args) { + for (const auto& constructor : tl_type->constructors) { + for (const auto& arg : constructor->args) { if (arg->is_optional()) { continue; } @@ -183,7 +177,7 @@ TlDependentTypesUsings::TlDependentTypesUsings(vk::tlo_parsing::type *tl_type, c // Can't deduce in cases like 'arg:fields_mask.1? t', where {t: Type}: don't know if 't' is wrapped to optional or not continue; } - auto *arg_type_expr = arg->type_expr->as(); + auto* arg_type_expr = arg->type_expr->as(); kphp_assert(arg_type_expr); // .fields_mask.0?[int] is prohibited in TL arg_wrapped_to_optional = tl2cpp::is_tl_type_wrapped_to_Optional(G->get_tl_classes().get_scheme()->get_type_by_magic(arg_type_expr->type_id)); } @@ -201,16 +195,16 @@ TlDependentTypesUsings::TlDependentTypesUsings(vk::tlo_parsing::type *tl_type, c } } if (!check_deduction_result()) { - kphp_error(false, - fmt_format("Couldn't deduce generic type-parameters for TL type '{}'.\n" - "Each type variable in this type must be used at least once " - "NOT like '... Maybe t ... ' and ' :fields_mask.? t'", tl_type->name)); + kphp_error(false, fmt_format("Couldn't deduce generic type-parameters for TL type '{}'.\n" + "Each type variable in this type must be used at least once " + "NOT like '... Maybe t ... ' and ' :fields_mask.? t'", + tl_type->name)); } } -TlDependentTypesUsings::DeducingInfo::DeducingInfo(std::string deduced_type, std::vector path) : - deduced_type(std::move(deduced_type)), - path_to_inner_param(std::move(path)) {} +TlDependentTypesUsings::DeducingInfo::DeducingInfo(std::string deduced_type, std::vector path) + : deduced_type(std::move(deduced_type)), + path_to_inner_param(std::move(path)) {} // Traverse a tree while ignoring all vertices except vk::tlo_parsing::type_var and vk::tlo_parsing::type_expr. // Collect a path to a type_var to get the type. @@ -220,7 +214,7 @@ TlDependentTypesUsings::DeducingInfo::DeducingInfo(std::string deduced_type, std // x : (Either (Maybe (%Vector t1)) (Maybe (%VectorTotal t2))) // = Test t1 t2; // ********************** cl/C@VK@TL@Types@Test__int__graph_Vertex.h ********************** -//struct C$VK$TL$Types$Test__int__graph_Vertex : public abstract_refcountable_php_interface { +// struct C$VK$TL$Types$Test__int__graph_Vertex : public abstract_refcountable_php_interface { // using t1 = class_instance::ClassType::X::InnerType::ValueType; // using t2 = class_instance::ClassType::Y::ClassType::t; // virtual const char *get_class() const { @@ -230,27 +224,27 @@ TlDependentTypesUsings::DeducingInfo::DeducingInfo(std::string deduced_type, std // Assume that TL arrays won't have any type vars, i.e. this case is impossible: // test {t:Type} [x:t] = Test; // All such cases (vector, tuple) are implemented manually in tl_builtins.h -void TlDependentTypesUsings::deduce_params_from_type_tree(vk::tlo_parsing::type_expr_base *type_tree, std::vector &recursion_stack) { - if (auto *type_var = dynamic_cast(type_tree)) { +void TlDependentTypesUsings::deduce_params_from_type_tree(vk::tlo_parsing::type_expr_base* type_tree, std::vector& recursion_stack) { + if (auto* type_var = dynamic_cast(type_tree)) { std::string type_var_name = cur_tl_constructor->get_var_num_arg(type_var->var_num)->name; if (!deduced_params.count(type_var_name)) { ClassPtr tl_constructor_php_class = tl2cpp::get_php_class_of_tl_constructor_specialization(cur_tl_constructor, specialization_suffix); - const TypeData *deduced_type = tl_constructor_php_class->members.get_instance_field(cur_tl_arg->name)->get_inferred_type(); + const TypeData* deduced_type = tl_constructor_php_class->members.get_instance_field(cur_tl_arg->name)->get_inferred_type(); deduced_params[type_var_name] = DeducingInfo(type_out(deduced_type), recursion_stack); std::unordered_set classes; deduced_type->get_all_class_types_inside(classes); - for (const auto &klass : classes) { + for (const auto& klass : classes) { kphp_assert(klass); dependencies.add_class_forward_declaration(klass); } } return; } - if (auto *type_expr = dynamic_cast(type_tree)) { + if (auto* type_expr = dynamic_cast(type_tree)) { int i = 0; - for (const auto &child : type_expr->children) { - if (auto *casted_child = dynamic_cast(child.get())) { - vk::tlo_parsing::type *parent_tl_type = G->get_tl_classes().get_scheme()->get_type_by_magic(type_expr->type_id); + for (const auto& child : type_expr->children) { + if (auto* casted_child = dynamic_cast(child.get())) { + vk::tlo_parsing::type* parent_tl_type = G->get_tl_classes().get_scheme()->get_type_by_magic(type_expr->type_id); kphp_assert(parent_tl_type); InnerParamTypeAccess inner_access; @@ -263,9 +257,9 @@ void TlDependentTypesUsings::deduce_params_from_type_tree(vk::tlo_parsing::type_ // Can't deduce in cases like 'Maybe t', where {t: Type}: don't know if 't' is wrapped to optional or not continue; } - auto *child_type_expr = dynamic_cast(casted_child); + auto* child_type_expr = dynamic_cast(casted_child); kphp_assert(child_type_expr); - vk::tlo_parsing::type *child_tl_type = G->get_tl_classes().get_scheme()->get_type_by_magic(child_type_expr->type_id); + vk::tlo_parsing::type* child_tl_type = G->get_tl_classes().get_scheme()->get_type_by_magic(child_type_expr->type_id); kphp_assert(child_tl_type); if (tl2cpp::is_tl_type_wrapped_to_Optional(child_tl_type)) { inner_access.drop_class_instance = false; @@ -278,7 +272,7 @@ void TlDependentTypesUsings::deduce_params_from_type_tree(vk::tlo_parsing::type_ // correctness of this is verified inside tl_scheme_final_check() inner_access.inner_type_name = parent_tl_type->constructors[0]->args[i]->name; auto php_classes = tl2cpp::get_all_php_classes_of_tl_type(parent_tl_type); - std::for_each(php_classes.begin(), php_classes.end(), [&](ClassPtr klass){ dependencies.add_class_include(klass); }); + std::for_each(php_classes.begin(), php_classes.end(), [&](ClassPtr klass) { dependencies.add_class_include(klass); }); } if (!skip_maybe) { recursion_stack.emplace_back(inner_access); @@ -294,11 +288,11 @@ void TlDependentTypesUsings::deduce_params_from_type_tree(vk::tlo_parsing::type_ } } -void TlDependentTypesUsings::compile(CodeGenerator &W) const { - for (const auto &item : deduced_params) { - const auto &info = item.second; +void TlDependentTypesUsings::compile(CodeGenerator& W) const { + for (const auto& item : deduced_params) { + const auto& info = item.second; W << "using " << item.first << " = " << info.deduced_type; - for (const auto &step : info.path_to_inner_param) { + for (const auto& step : info.path_to_inner_param) { if (step.drop_class_instance) { W << "::ClassType"; } @@ -308,20 +302,18 @@ void TlDependentTypesUsings::compile(CodeGenerator &W) const { } } -void TlDependentTypesUsings::compile_dependencies(CodeGenerator &W) { +void TlDependentTypesUsings::compile_dependencies(CodeGenerator& W) { W << dependencies << NL; } bool TlDependentTypesUsings::check_deduction_result() const { - const auto &args = tl_type->constructors.front()->args; - return std::all_of(args.begin(), args.end(), [&](const auto &arg) { - return !arg->is_type() || deduced_params.count(arg->name); - }); + const auto& args = tl_type->constructors.front()->args; + return std::all_of(args.begin(), args.end(), [&](const auto& arg) { return !arg->is_type() || deduced_params.count(arg->name); }); } std::unique_ptr InterfaceDeclaration::detect_if_needs_tl_usings() const { if (tl2cpp::is_php_class_a_tl_polymorphic_type(interface)) { - vk::tlo_parsing::type *cur_tl_type = tl2cpp::get_tl_type_of_php_class(interface); + vk::tlo_parsing::type* cur_tl_type = tl2cpp::get_tl_type_of_php_class(interface); bool needs_tl_usings = tl2cpp::is_type_dependent(cur_tl_type, G->get_tl_classes().get_scheme().get()); if (needs_tl_usings) { @@ -331,25 +323,25 @@ std::unique_ptr InterfaceDeclaration::detect_if_needs_tl return {}; } -void FFIDeclaration::compile(CodeGenerator &W) const { +void FFIDeclaration::compile(CodeGenerator& W) const { W << OpenFile(ffi_scope->h_filename, ffi_scope->get_subdir()); W << "#pragma once" << NL; W << ExternInclude("runtime/ffi.h"); - auto *scope = ffi_scope->ffi_scope_mixin; + auto* scope = ffi_scope->ffi_scope_mixin; W << "extern \"C\" {" << NL; // struct definitions are emitted for both shared (dynamic) and static libraries - for (const auto &type : scope->types) { + for (const auto& type : scope->types) { W << (type->kind == FFITypeKind::StructDef ? "struct" : "union"); W << " " << FFIRoot::c_name_mangle(scope->scope_name, type->str); // empty members list mean "forward declaration", don't emit {} for them if (!type->members.empty()) { W << " " << BEGIN; - for (const FFIType *field : type->members) { + for (const FFIType* field : type->members) { W << ffi_mangled_type_string(scope->scope_name, field) << ";" << NL; } W << END; @@ -360,10 +352,10 @@ void FFIDeclaration::compile(CodeGenerator &W) const { // for shared libraries we don't emit function declarations as they're accessed // via FFIEnv object that contains dynamically loaded symbols inside if (!scope->is_shared_lib()) { - for (const auto &sym : scope->variables) { + for (const auto& sym : scope->variables) { W << "extern " << ffi_type_string(sym.type) << ";" << NL; } - for (const auto &sym : scope->functions) { + for (const auto& sym : scope->functions) { // note: static lib function symbols are unmangled W << ffi_decltype_string(sym.type->members[0]) << " " << sym.type->str << "("; for (int i = 1; i < sym.type->members.size(); i++) { @@ -384,7 +376,7 @@ void FFIDeclaration::compile(CodeGenerator &W) const { W << CloseFile(); } -void InterfaceDeclaration::compile(CodeGenerator &W) const { +void InterfaceDeclaration::compile(CodeGenerator& W) const { W << OpenFile(interface->h_filename, interface->get_subdir()); W << "#pragma once" << NL; @@ -407,7 +399,7 @@ void InterfaceDeclaration::compile(CodeGenerator &W) const { W << "struct " << interface->src_name << " : public "; if (!interface->implements.empty()) { - auto transform_to_src_name = [](CodeGenerator &W, const InterfacePtr &i) { W << i->src_name; }; + auto transform_to_src_name = [](CodeGenerator& W, const InterfacePtr& i) { W << i->src_name; }; W << JoinValues(interface->implements, ", public ", join_mode::one_line, transform_to_src_name); } else { W << (interface->need_virtual_modifier() ? "virtual " : "") << (interface->may_be_mixed ? "may_be_mixed_base" : "abstract_refcountable_php_interface"); @@ -423,7 +415,6 @@ void InterfaceDeclaration::compile(CodeGenerator &W) const { W << interface->src_name << "() __attribute__((always_inline)) = default;" << NL; W << "~" << interface->src_name << "() __attribute__((always_inline)) = default;" << NL; - W << END << ";" << NL; W << CloseNamespace(); @@ -431,15 +422,14 @@ void InterfaceDeclaration::compile(CodeGenerator &W) const { W << CloseFile(); } -ClassDeclaration::ClassDeclaration(ClassPtr klass) : - klass(klass) { -} +ClassDeclaration::ClassDeclaration(ClassPtr klass) + : klass(klass) {} std::unique_ptr ClassDeclaration::detect_if_needs_tl_usings() const { if (tl2cpp::is_php_class_a_tl_constructor(klass) && !tl2cpp::is_php_class_a_tl_array_item(klass)) { - const auto &scheme = G->get_tl_classes().get_scheme(); - vk::tlo_parsing::combinator *cur_tl_constructor = tl2cpp::get_tl_constructor_of_php_class(klass); - vk::tlo_parsing::type *cur_tl_type = scheme->get_type_by_magic(cur_tl_constructor->type_id); + const auto& scheme = G->get_tl_classes().get_scheme(); + vk::tlo_parsing::combinator* cur_tl_constructor = tl2cpp::get_tl_constructor_of_php_class(klass); + vk::tlo_parsing::type* cur_tl_type = scheme->get_type_by_magic(cur_tl_constructor->type_id); bool needs_tl_usings = tl2cpp::is_type_dependent(cur_tl_constructor, scheme.get()) && !cur_tl_type->is_polymorphic(); if (needs_tl_usings) { @@ -449,7 +439,7 @@ std::unique_ptr ClassDeclaration::detect_if_needs_tl_usi return {}; } -void ClassDeclaration::compile(CodeGenerator &W) const { +void ClassDeclaration::compile(CodeGenerator& W) const { W << OpenFile(klass->h_filename, klass->get_subdir()); W << "#pragma once" << NL; @@ -463,7 +453,7 @@ void ClassDeclaration::compile(CodeGenerator &W) const { } ConstantsExternCollector c_mem_extern; - klass->members.for_each([&c_mem_extern](const ClassMemberInstanceField &f) { + klass->members.for_each([&c_mem_extern](const ClassMemberInstanceField& f) { if (f.var->init_val) { c_mem_extern.add_extern_from_init_val(f.var->init_val); } @@ -471,15 +461,13 @@ void ClassDeclaration::compile(CodeGenerator &W) const { W << c_mem_extern << NL; auto get_all_interfaces = [klass = this->klass] { - auto transform_to_src_name = [](CodeGenerator &W, InterfacePtr i) { W << i->src_name.c_str(); }; + auto transform_to_src_name = [](CodeGenerator& W, InterfacePtr i) { W << i->src_name.c_str(); }; return JoinValues(klass->implements, ", ", join_mode::one_line, transform_to_src_name); }; W << NL << "struct " << klass->src_name; // builtin classes that should not be extended must be marked with "final"; // classes without "final" are expected to be a proper KPHP classes that can be extended - bool parent_class_is_builtin = klass->parent_class && - klass->parent_class->is_builtin() && - klass->parent_class->is_class(); + bool parent_class_is_builtin = klass->parent_class && klass->parent_class->is_builtin() && klass->parent_class->is_class(); if (parent_class_is_builtin || (klass->parent_class && klass->parent_class->does_need_codegen())) { W << (klass->derived_classes.empty() ? " final" : "") << " : public "; if (!klass->implements.empty()) { @@ -495,10 +483,9 @@ void ClassDeclaration::compile(CodeGenerator &W) const { if (klass->need_virtual_modifier()) { W << ": public refcountable_polymorphic_php_classes_virt<>" << (klass->may_be_mixed ? ", virtual may_be_mixed_base" : ""); } else { - W << ": public refcountable_polymorphic_php_classes<" << - (klass->may_be_mixed ? "may_be_mixed_base" : "abstract_refcountable_php_interface") << ">"; + W << ": public refcountable_polymorphic_php_classes<" << (klass->may_be_mixed ? "may_be_mixed_base" : "abstract_refcountable_php_interface") << ">"; } - } else if(klass->may_be_mixed) { + } else if (klass->may_be_mixed) { W << ": public refcountable_polymorphic_php_classes"; } else { // not polymorphic W << ": public refcountable_php_classes<" << klass->src_name << ">"; @@ -545,9 +532,10 @@ static bool is_may_be_mixed_virtual_method(vk::string_view method_signature) { } template -void ClassDeclaration::compile_class_method(FunctionSignatureGenerator &&W, ClassPtr klass, vk::string_view method_signature, const ReturnValueT &return_value) { +void ClassDeclaration::compile_class_method(FunctionSignatureGenerator&& W, ClassPtr klass, vk::string_view method_signature, + const ReturnValueT& return_value) { const bool has_parent = (klass->parent_class && klass->parent_class->does_need_codegen()) || - vk::any_of(klass->implements, [](InterfacePtr i) { return i->does_need_codegen() || i->is_builtin(); }); + vk::any_of(klass->implements, [](InterfacePtr i) { return i->does_need_codegen() || i->is_builtin(); }); const bool has_derived = !klass->derived_classes.empty(); const bool is_overridden = has_parent && has_derived; const bool is_final = has_parent && !has_derived; @@ -559,12 +547,9 @@ void ClassDeclaration::compile_class_method(FunctionSignatureGenerator &&W, Clas return; } - FunctionSignatureGenerator &&signature = std::move(W) - .set_is_virtual(is_pure_virtual || has_derived) - .set_final(is_final) - .set_overridden(is_overridden) - .set_pure_virtual(is_pure_virtual) - << method_signature; + FunctionSignatureGenerator&& signature = + std::move(W).set_is_virtual(is_pure_virtual || has_derived).set_final(is_final).set_overridden(is_overridden).set_pure_virtual(is_pure_virtual) + << method_signature; if (is_pure_virtual) { std::move(signature) << SemicolonAndNL{} << NL; @@ -573,7 +558,7 @@ void ClassDeclaration::compile_class_method(FunctionSignatureGenerator &&W, Clas } } -void ClassDeclaration::compile_inner_methods(CodeGenerator &W, ClassPtr klass) { +void ClassDeclaration::compile_inner_methods(CodeGenerator& W, ClassPtr klass) { compile_json_flatten_flag(W, klass); compile_has_wakeup_flag(W, klass); compile_get_class(W, klass); @@ -586,10 +571,8 @@ void ClassDeclaration::compile_inner_methods(CodeGenerator &W, ClassPtr klass) { // type_size_approx tries to calculate the TypeData value size when interpreted as C++ type // it's used for field sorting, so it's not expected to give the byte-precise results -static int64_t type_size_approx(const TypeData *type_data) { - auto round_up = [](int64_t x, int64_t multiplier) { - return (x + (multiplier - 1)) & (-multiplier); - }; +static int64_t type_size_approx(const TypeData* type_data) { + auto round_up = [](int64_t x, int64_t multiplier) { return (x + (multiplier - 1)) & (-multiplier); }; auto calc_rounded_size = [round_up](int64_t size) -> std::pair { if (size == 1) { // byte-sized objects should not require any alignment @@ -608,26 +591,26 @@ static int64_t type_size_approx(const TypeData *type_data) { int64_t total_result = 0; int64_t align = 8; switch (type_data->ptype()) { - case tp_bool: - total_result = 1; - align = 1; - break; - case tp_mixed: - total_result = 16; - break; - case tp_shape: - case tp_tuple: { - for (auto it = type_data->lookup_begin(); it != type_data->lookup_end(); ++it) { - auto [member_size, member_alignment] = calc_rounded_size(type_size_approx(it->second)); - align = std::max(align, member_alignment); - total_result += member_size; - } - break; + case tp_bool: + total_result = 1; + align = 1; + break; + case tp_mixed: + total_result = 16; + break; + case tp_shape: + case tp_tuple: { + for (auto it = type_data->lookup_begin(); it != type_data->lookup_end(); ++it) { + auto [member_size, member_alignment] = calc_rounded_size(type_size_approx(it->second)); + align = std::max(align, member_alignment); + total_result += member_size; } - default: - // most types are 8-byte wide: ints, floats, strings, arrays, objects, ... - total_result = 8; - break; + break; + } + default: + // most types are 8-byte wide: ints, floats, strings, arrays, objects, ... + total_result = 8; + break; } if (type_data->use_optional()) { @@ -642,7 +625,7 @@ static int64_t type_size_approx(const TypeData *type_data) { return total_result; } -void ClassDeclaration::compile_fields(CodeGenerator &W, ClassPtr klass) { +void ClassDeclaration::compile_fields(CodeGenerator& W, ClassPtr klass) { // try to output class fields in the order that leads to the most compact object layout possible; // we're trying to minimize the amount of unnecessary field padding here // @@ -652,10 +635,10 @@ void ClassDeclaration::compile_fields(CodeGenerator &W, ClassPtr klass) { struct FieldWithSize { int64_t size; - const ClassMemberInstanceField *ptr; + const ClassMemberInstanceField* ptr; }; - auto compile_field = [](CodeGenerator &W, const ClassMemberInstanceField *f) { + auto compile_field = [](CodeGenerator& W, const ClassMemberInstanceField* f) { W << TypeName(tinf::get_type(f->var)) << " $" << f->local_name() << "{"; if (f->var->init_val) { W << f->var->init_val; @@ -665,13 +648,11 @@ void ClassDeclaration::compile_fields(CodeGenerator &W, ClassPtr klass) { // build a sorted vector of fields, from bigger size to the smallest std::vector fields; - klass->members.for_each([&](const ClassMemberInstanceField &f) { + klass->members.for_each([&](const ClassMemberInstanceField& f) { int64_t size = type_size_approx(tinf::get_type(f.var)); fields.push_back({size, &f}); }); - sort(fields.begin(), fields.end(), [](const FieldWithSize &a, const FieldWithSize &b) { - return a.size > b.size; - }); + sort(fields.begin(), fields.end(), [](const FieldWithSize& a, const FieldWithSize& b) { return a.size > b.size; }); // most classes have a 4-byte prefix that may create an unwanted gap if we're not careful // @@ -700,7 +681,7 @@ void ClassDeclaration::compile_fields(CodeGenerator &W, ClassPtr klass) { if (needs_padding) { constexpr int prefix_size = 4; int64_t size_filled = 0; - for (auto &f : fields) { + for (auto& f : fields) { if (size_filled >= prefix_size) { break; // the gap is filled, field padding is completed } @@ -719,7 +700,7 @@ void ClassDeclaration::compile_fields(CodeGenerator &W, ClassPtr klass) { // emit all fields, except the ones that were used for the gap filling; // the fields are printed from the bigger size to the smaller - for (const auto &f : fields) { + for (const auto& f : fields) { if (!f.ptr) { continue; // this field was already compiled above } @@ -727,46 +708,46 @@ void ClassDeclaration::compile_fields(CodeGenerator &W, ClassPtr klass) { } } -void ClassDeclaration::compile_json_flatten_flag(CodeGenerator &W, ClassPtr klass) { - const auto *tag_flatten = klass->kphp_json_tags - ? klass->kphp_json_tags->find_tag([](const kphp_json::KphpJsonTag &tag) { return tag.attr_type == kphp_json::json_attr_flatten && tag.flatten; }) - : nullptr; +void ClassDeclaration::compile_json_flatten_flag(CodeGenerator& W, ClassPtr klass) { + const auto* tag_flatten = + klass->kphp_json_tags + ? klass->kphp_json_tags->find_tag([](const kphp_json::KphpJsonTag& tag) { return tag.attr_type == kphp_json::json_attr_flatten && tag.flatten; }) + : nullptr; if (tag_flatten) { W << "constexpr static bool json_flatten_class{true};" << NL << NL; } } -void ClassDeclaration::compile_has_wakeup_flag(CodeGenerator &W, ClassPtr klass) { +void ClassDeclaration::compile_has_wakeup_flag(CodeGenerator& W, ClassPtr klass) { bool has_wakeup = klass->members.has_instance_method("__wakeup"); if (has_wakeup) { W << "constexpr static bool has_wakeup_method{true};" << NL << NL; } } -void ClassDeclaration::compile_get_class(CodeGenerator &W, ClassPtr klass) { +void ClassDeclaration::compile_get_class(CodeGenerator& W, ClassPtr klass) { auto class_name_as_raw_string = "R\"(" + klass->name + ")\""; compile_class_method(FunctionSignatureGenerator(W).set_const_this(), klass, "const char *get_class()", class_name_as_raw_string); } -void ClassDeclaration::compile_get_hash(CodeGenerator &W, ClassPtr klass) { +void ClassDeclaration::compile_get_hash(CodeGenerator& W, ClassPtr klass) { compile_class_method(FunctionSignatureGenerator(W).set_const_this(), klass, "int get_hash()", klass->get_hash()); } -void ClassDeclaration::compile_accept_visitor(CodeGenerator &W, ClassPtr klass, const char *visitor_type) { +void ClassDeclaration::compile_accept_visitor(CodeGenerator& W, ClassPtr klass, const char* visitor_type) { compile_class_method(FunctionSignatureGenerator(W), klass, fmt_format("void accept({} &visitor)", visitor_type), "generic_accept(visitor)"); } -static void do_compile_generic_accept(CodeGenerator &W, ClassPtr klass, bool compile_declaration_only) { +static void do_compile_generic_accept(CodeGenerator& W, ClassPtr klass, bool compile_declaration_only) { const std::string class_name = compile_declaration_only ? "" : klass->src_name + "::"; - FunctionSignatureGenerator(W) << "template" << NL - << "void " << class_name << "generic_accept(Visitor &&visitor) "; + FunctionSignatureGenerator(W) << "template" << NL << "void " << class_name << "generic_accept(Visitor &&visitor) "; if (compile_declaration_only) { W << SemicolonAndNL{}; return; } W << BEGIN; for (auto cur_klass = klass; cur_klass; cur_klass = cur_klass->parent_class) { - cur_klass->members.for_each([&W](const ClassMemberInstanceField &f) { + cur_klass->members.for_each([&W](const ClassMemberInstanceField& f) { // will generate visitor("field_name", $field_name); W << "visitor(\"" << f.local_name() << "\", $" << f.local_name() << ");" << NL; }); @@ -774,12 +755,12 @@ static void do_compile_generic_accept(CodeGenerator &W, ClassPtr klass, bool com W << END << NL; } -void ClassDeclaration::compile_generic_accept(CodeGenerator &W, ClassPtr klass) { +void ClassDeclaration::compile_generic_accept(CodeGenerator& W, ClassPtr klass) { do_compile_generic_accept(W, klass, true); } // generate `visitor("json_key", $field_name);`, wrapped with `if ($field_name != default)` if skip_if_default, etc. -static void compile_json_visitor_call(CodeGenerator &W, ClassPtr json_encoder, ClassPtr klass, const ClassMemberInstanceField &field, bool to_encode) noexcept { +static void compile_json_visitor_call(CodeGenerator& W, ClassPtr json_encoder, ClassPtr klass, const ClassMemberInstanceField& field, bool to_encode) noexcept { auto props = kphp_json::merge_and_inherit_json_tags(field, klass, json_encoder); if (to_encode ? props.skip_when_encoding : props.skip_when_decoding) { @@ -816,13 +797,15 @@ static void compile_json_visitor_call(CodeGenerator &W, ClassPtr json_encoder, C } } -static void do_compile_accept_json_visitor(CodeGenerator &W, ClassPtr klass, bool to_encode, ClassPtr json_encoder, bool compile_declaration_only) { +static void do_compile_accept_json_visitor(CodeGenerator& W, ClassPtr klass, bool to_encode, ClassPtr json_encoder, bool compile_declaration_only) { bool parent_has_method = false; if (ClassPtr parent = klass->parent_class) { - parent_has_method |= parent->json_encoders.end() != std::find(parent->json_encoders.begin(), parent->json_encoders.end(), std::pair{json_encoder, to_encode}); + parent_has_method |= + parent->json_encoders.end() != std::find(parent->json_encoders.begin(), parent->json_encoders.end(), std::pair{json_encoder, to_encode}); } for (InterfacePtr parent : klass->implements) { - parent_has_method |= parent->json_encoders.end() != std::find(parent->json_encoders.begin(), parent->json_encoders.end(), std::pair{json_encoder, to_encode}); + parent_has_method |= + parent->json_encoders.end() != std::find(parent->json_encoders.begin(), parent->json_encoders.end(), std::pair{json_encoder, to_encode}); } const bool has_derived = !klass->derived_classes.empty(); @@ -837,24 +820,25 @@ static void do_compile_accept_json_visitor(CodeGenerator &W, ClassPtr klass, boo return; } FunctionSignatureGenerator(W) - .set_is_virtual(is_pure_virtual || has_derived) - .set_final(parent_has_method && !has_derived) - .set_overridden(parent_has_method && has_derived) - .set_pure_virtual(is_pure_virtual) - .set_definition(!compile_declaration_only) - << fmt_format("void accept({}<{}> &visitor)", to_encode ? "ToJsonVisitor" : "FromJsonVisitor", JsonEncoderTags::get_cppStructTag_name(json_encoder->name)) - << SemicolonAndNL{}; + .set_is_virtual(is_pure_virtual || has_derived) + .set_final(parent_has_method && !has_derived) + .set_overridden(parent_has_method && has_derived) + .set_pure_virtual(is_pure_virtual) + .set_definition(!compile_declaration_only) + << fmt_format("void accept({}<{}> &visitor)", to_encode ? "ToJsonVisitor" : "FromJsonVisitor", + JsonEncoderTags::get_cppStructTag_name(json_encoder->name)) + << SemicolonAndNL{}; return; } else { const std::string class_name = compile_declaration_only ? "" : klass->src_name + "::"; FunctionSignatureGenerator(W) - .set_is_virtual(is_pure_virtual || has_derived) - .set_final(parent_has_method && !has_derived) - .set_overridden(parent_has_method && has_derived) - .set_pure_virtual(is_pure_virtual) - .set_definition(!compile_declaration_only) - << fmt_format("void {}accept({}<{}> &visitor)", class_name, to_encode ? "ToJsonVisitor" : "FromJsonVisitor", - JsonEncoderTags::get_cppStructTag_name(json_encoder->name)); + .set_is_virtual(is_pure_virtual || has_derived) + .set_final(parent_has_method && !has_derived) + .set_overridden(parent_has_method && has_derived) + .set_pure_virtual(is_pure_virtual) + .set_definition(!compile_declaration_only) + << fmt_format("void {}accept({}<{}> &visitor)", class_name, to_encode ? "ToJsonVisitor" : "FromJsonVisitor", + JsonEncoderTags::get_cppStructTag_name(json_encoder->name)); if (compile_declaration_only) { W << SemicolonAndNL{}; return; @@ -863,10 +847,10 @@ static void do_compile_accept_json_visitor(CodeGenerator &W, ClassPtr klass, boo } // generates `visitor("json_key", $field_name)` calls in appropriate order - auto compile_visitor_calls_for_class_fields = [](CodeGenerator &W, ClassPtr klass, ClassPtr json_encoder, bool to_encode) { + auto compile_visitor_calls_for_class_fields = [](CodeGenerator& W, ClassPtr klass, ClassPtr json_encoder, bool to_encode) { // if @kphp-json 'fields' exists above a class, we use it to output fields in that order if (klass->kphp_json_tags) { - const kphp_json::KphpJsonTag *tag_fields = klass->kphp_json_tags->find_tag([json_encoder](const kphp_json::KphpJsonTag &tag) { + const kphp_json::KphpJsonTag* tag_fields = klass->kphp_json_tags->find_tag([json_encoder](const kphp_json::KphpJsonTag& tag) { return tag.attr_type == kphp_json::json_attr_fields && (!tag.for_encoder || tag.for_encoder == json_encoder); }); if (tag_fields) { @@ -877,9 +861,8 @@ static void do_compile_accept_json_visitor(CodeGenerator &W, ClassPtr klass, boo } } // otherwise, we output fields in an order they are declared - klass->members.for_each([&W, json_encoder, klass, to_encode](const ClassMemberInstanceField &field) { - compile_json_visitor_call(W, json_encoder, klass, field, to_encode); - }); + klass->members.for_each( + [&W, json_encoder, klass, to_encode](const ClassMemberInstanceField& field) { compile_json_visitor_call(W, json_encoder, klass, field, to_encode); }); }; if (!klass->parent_class) { @@ -898,16 +881,16 @@ static void do_compile_accept_json_visitor(CodeGenerator &W, ClassPtr klass, boo W << END << NL; } -void ClassDeclaration::compile_accept_json_visitor(CodeGenerator &W, ClassPtr klass) { +void ClassDeclaration::compile_accept_json_visitor(CodeGenerator& W, ClassPtr klass) { for (auto [encoder, to_encode] : klass->json_encoders) { W << NL; do_compile_accept_json_visitor(W, klass, to_encode, encoder, true); } } -void ClassDeclaration::compile_accept_visitor_methods(CodeGenerator &W, ClassPtr klass) { +void ClassDeclaration::compile_accept_visitor_methods(CodeGenerator& W, ClassPtr klass) { bool need_generic_accept = - klass->need_to_array_debug_visitor || (klass->need_instance_cache_visitors && !G->is_output_mode_k2()) || (klass->need_instance_memory_estimate_visitor); + klass->need_to_array_debug_visitor || (klass->need_instance_cache_visitors && !G->is_output_mode_k2()) || (klass->need_instance_memory_estimate_visitor); if (!need_generic_accept && klass->json_encoders.empty()) { return; @@ -942,7 +925,7 @@ void ClassDeclaration::compile_accept_visitor_methods(CodeGenerator &W, ClassPtr compile_accept_json_visitor(W, klass); } -void ClassDeclaration::compile_msgpack_declarations(CodeGenerator &W, ClassPtr klass) { +void ClassDeclaration::compile_msgpack_declarations(CodeGenerator& W, ClassPtr klass) { if (!klass->is_serializable) { return; } @@ -952,20 +935,19 @@ void ClassDeclaration::compile_msgpack_declarations(CodeGenerator &W, ClassPtr k W << "void msgpack_unpack(const vk::msgpack::object &msgpack_o);" << NL; } -void ClassDeclaration::compile_virtual_builtin_functions(CodeGenerator &W, ClassPtr klass) { +void ClassDeclaration::compile_virtual_builtin_functions(CodeGenerator& W, ClassPtr klass) { if (!klass->need_virtual_builtin_functions) { return; } - compile_class_method(FunctionSignatureGenerator(W).set_const_this(), klass, - "size_t virtual_builtin_sizeof()", "sizeof(*this)"); + compile_class_method(FunctionSignatureGenerator(W).set_const_this(), klass, "size_t virtual_builtin_sizeof()", "sizeof(*this)"); - compile_class_method(FunctionSignatureGenerator(W).set_const_this(), klass, - klass->src_name + "* virtual_builtin_clone()", "new " + klass->src_name + "{*this}"); + compile_class_method(FunctionSignatureGenerator(W).set_const_this(), klass, klass->src_name + "* virtual_builtin_clone()", + "new " + klass->src_name + "{*this}"); } -void ClassDeclaration::compile_wakeup(CodeGenerator &W, ClassPtr klass) { - const auto *m_wakeup = klass->members.get_instance_method("__wakeup"); +void ClassDeclaration::compile_wakeup(CodeGenerator& W, ClassPtr klass) { + const auto* m_wakeup = klass->members.get_instance_method("__wakeup"); if (!m_wakeup || klass->is_interface()) { return; } @@ -984,11 +966,9 @@ void ClassDeclaration::compile_wakeup(CodeGenerator &W, ClassPtr klass) { W << END << NL; } -IncludesCollector ClassDeclaration::compile_front_includes(CodeGenerator &W) const { +IncludesCollector ClassDeclaration::compile_front_includes(CodeGenerator& W) const { IncludesCollector includes; - klass->members.for_each([&includes](const ClassMemberInstanceField &f) { - includes.add_var_signature_forward_declarations(f.var); - }); + klass->members.for_each([&includes](const ClassMemberInstanceField& f) { includes.add_var_signature_forward_declarations(f.var); }); includes.add_base_classes_include(klass); if (!klass->json_encoders.empty()) { @@ -998,7 +978,7 @@ IncludesCollector ClassDeclaration::compile_front_includes(CodeGenerator &W) con W << includes; if (tl2cpp::is_php_class_a_tl_function(klass)) { - std::string tl_src_name = tl2cpp::get_tl_function_name_of_php_class(klass); // 'net.pid', 'rpcPing' + std::string tl_src_name = tl2cpp::get_tl_function_name_of_php_class(klass); // 'net.pid', 'rpcPing' unsigned long pos = tl_src_name.find('.'); W << Include("tl/" + (pos == std::string::npos ? "common" : tl_src_name.substr(0, pos)) + ".h"); } @@ -1006,23 +986,21 @@ IncludesCollector ClassDeclaration::compile_front_includes(CodeGenerator &W) con return includes; } -void ClassDeclaration::compile_back_includes(CodeGenerator &W, IncludesCollector &&front_includes) const { +void ClassDeclaration::compile_back_includes(CodeGenerator& W, IncludesCollector&& front_includes) const { IncludesCollector includes{std::move(front_includes)}; includes.start_next_block(); - klass->members.for_each([&includes](const ClassMemberInstanceField &f) { - includes.add_var_signature_depends(f.var); - }); + klass->members.for_each([&includes](const ClassMemberInstanceField& f) { includes.add_var_signature_depends(f.var); }); W << includes; } -void ClassDeclaration::compile_job_worker_shared_memory_piece_methods(CodeGenerator &W, bool compile_declaration_only) const { +void ClassDeclaration::compile_job_worker_shared_memory_piece_methods(CodeGenerator& W, bool compile_declaration_only) const { if (G->is_output_mode_k2()) { return; // The current version of runtime-light does not support shared memory pieces } auto request_interface = G->get_class("KphpJobWorkerRequest"); - if (!request_interface) { // when functions.txt deleted while development + if (!request_interface) { // when functions.txt deleted while development return; } @@ -1031,22 +1009,24 @@ void ClassDeclaration::compile_job_worker_shared_memory_piece_methods(CodeGenera return; } if (compile_declaration_only) { - FunctionSignatureGenerator(W).set_overridden().set_const_this() << "class_instance get_shared_memory_piece()" << SemicolonAndNL{}; - FunctionSignatureGenerator(W).set_overridden() << "void set_shared_memory_piece(const class_instance &instance)" << SemicolonAndNL{}; + FunctionSignatureGenerator(W).set_overridden().set_const_this() + << "class_instance get_shared_memory_piece()" << SemicolonAndNL{}; + FunctionSignatureGenerator(W).set_overridden() << "void set_shared_memory_piece(const class_instance &instance)" + << SemicolonAndNL{}; return; } - const ClassMemberInstanceField *field = nullptr; + const ClassMemberInstanceField* field = nullptr; if (klass->has_job_shared_memory_piece) { field = klass->get_job_shared_memory_pieces().front(); } W << NL; FunctionSignatureGenerator(W).set_const_this().set_inline() - << "class_instance " << klass->src_name << "::get_shared_memory_piece() " << BEGIN; + << "class_instance " << klass->src_name << "::get_shared_memory_piece() " << BEGIN; W << "return " << (field ? field->get_hash_name() : "{}") << SemicolonAndNL{}; W << END << NL << NL; FunctionSignatureGenerator(W).set_inline() << "void " << klass->src_name - << "::set_shared_memory_piece(const class_instance &instance) " << BEGIN; + << "::set_shared_memory_piece(const class_instance &instance) " << BEGIN; if (field) { W << "auto casted = instance.cast_to<" << field->get_inferred_type()->class_type()->src_name << ">();" << NL; W << "php_assert(instance.is_null() || !casted.is_null());" << NL; @@ -1057,9 +1037,9 @@ void ClassDeclaration::compile_job_worker_shared_memory_piece_methods(CodeGenera W << END << NL; } -void ClassMembersDefinition::compile(CodeGenerator &W) const { +void ClassMembersDefinition::compile(CodeGenerator& W) const { bool need_generic_accept = - klass->need_to_array_debug_visitor || (klass->need_instance_cache_visitors && !G->is_output_mode_k2()) || (klass->need_instance_memory_estimate_visitor); + klass->need_to_array_debug_visitor || (klass->need_instance_cache_visitors && !G->is_output_mode_k2()) || (klass->need_instance_memory_estimate_visitor); if (!need_generic_accept && !klass->is_serializable && klass->json_encoders.empty()) { return; @@ -1113,32 +1093,32 @@ void ClassMembersDefinition::compile(CodeGenerator &W) const { W << CloseFile(); } -void ClassMembersDefinition::compile_generic_accept(CodeGenerator &W, ClassPtr klass) { +void ClassMembersDefinition::compile_generic_accept(CodeGenerator& W, ClassPtr klass) { do_compile_generic_accept(W, klass, false); } -void ClassMembersDefinition::compile_generic_accept_instantiations(CodeGenerator &W, ClassPtr klass, vk::string_view type) { +void ClassMembersDefinition::compile_generic_accept_instantiations(CodeGenerator& W, ClassPtr klass, vk::string_view type) { W << "template void " << klass->src_name << "::generic_accept(" << type << " &) noexcept;"; } -void ClassMembersDefinition::compile_accept_json_visitor(CodeGenerator &W, ClassPtr klass) { - for (auto[encoder, to_encode] : klass->json_encoders) { +void ClassMembersDefinition::compile_accept_json_visitor(CodeGenerator& W, ClassPtr klass) { + for (auto [encoder, to_encode] : klass->json_encoders) { W << NL; do_compile_accept_json_visitor(W, klass, to_encode, encoder, false); } } -void ClassMembersDefinition::compile_msgpack_serialize(CodeGenerator &W, ClassPtr klass) { +void ClassMembersDefinition::compile_msgpack_serialize(CodeGenerator& W, ClassPtr klass) { if (!klass->is_serializable) { return; } - //template - //void msgpack_pack(Packer &packer) const { - // packer.pack(tag_1); - // packer.pack(field_1); - // ... - //} + // template + // void msgpack_pack(Packer &packer) const { + // packer.pack(tag_1); + // packer.pack(field_1); + // ... + // } std::vector body; uint16_t cnt_fields = 0; @@ -1153,8 +1133,8 @@ void ClassMembersDefinition::compile_msgpack_serialize(CodeGenerator &W, ClassPt std::reverse(klasses.begin(), klasses.end()); - for (auto &k : klasses) { - k->members.for_each([&](ClassMemberInstanceField &field) { + for (auto& k : klasses) { + k->members.for_each([&](ClassMemberInstanceField& field) { if (field.serialization_tag != -1) { auto func_name = fmt_format("vk::msgpack::packer_float32_decorator::pack_value{}", field.serialize_as_float32 ? "_float32" : ""); body.emplace_back(fmt_format("packer.pack({}); {}(packer, ${});", field.serialization_tag, func_name, field.var->name)); @@ -1163,29 +1143,27 @@ void ClassMembersDefinition::compile_msgpack_serialize(CodeGenerator &W, ClassPt }); } - FunctionSignatureGenerator(W).set_const_this() - << "void " << klass->src_name << "::msgpack_pack(vk::msgpack::packer &packer)" << BEGIN - << "packer.pack_array(" << cnt_fields << ");" << NL - << JoinValues(body, "", join_mode::multiple_lines) << NL - << END << NL; + FunctionSignatureGenerator(W).set_const_this() << "void " << klass->src_name << "::msgpack_pack(vk::msgpack::packer &packer)" << BEGIN + << "packer.pack_array(" << cnt_fields << ");" << NL << JoinValues(body, "", join_mode::multiple_lines) << NL + << END << NL; } -void ClassMembersDefinition::compile_msgpack_deserialize(CodeGenerator &W, ClassPtr klass) { +void ClassMembersDefinition::compile_msgpack_deserialize(CodeGenerator& W, ClassPtr klass) { if (!klass->is_serializable) { return; } - //if (msgpack_o.type != vk::msgpack::stored_type::ARRAY) { SerializationLibContext::get().set_msgpack_error(vk::msgpack::TYPE_ERROR); return; } - //auto arr = msgpack_o.via.array; - //for (size_t i = 0; i < arr.size; i += 2) { - // auto tag = arr.ptr[i].as(); - // [[maybe_unused]] auto elem = arr.ptr[i + 1]; - // switch (tag) { - // case tag_x: elem.convert(x); break; - // case tag_s: elem.convert(s); break; - // default : break; - // } - //} + // if (msgpack_o.type != vk::msgpack::stored_type::ARRAY) { SerializationLibContext::get().set_msgpack_error(vk::msgpack::TYPE_ERROR); return; } + // auto arr = msgpack_o.via.array; + // for (size_t i = 0; i < arr.size; i += 2) { + // auto tag = arr.ptr[i].as(); + // [[maybe_unused]] auto elem = arr.ptr[i + 1]; + // switch (tag) { + // case tag_x: elem.convert(x); break; + // case tag_s: elem.convert(s); break; + // default : break; + // } + // } // std::vector cases; @@ -1201,8 +1179,8 @@ void ClassMembersDefinition::compile_msgpack_deserialize(CodeGenerator &W, Class std::reverse(klasses.begin(), klasses.end()); - for (auto &k : klasses) { - k->members.for_each([&](ClassMemberInstanceField &field) { + for (auto& k : klasses) { + k->members.for_each([&](ClassMemberInstanceField& field) { if (field.serialization_tag != -1) { cases.emplace_back(fmt_format("case {}: elem.convert(${}); break;", field.serialization_tag, field.var->name)); } @@ -1212,30 +1190,22 @@ void ClassMembersDefinition::compile_msgpack_deserialize(CodeGenerator &W, Class W << "void " << klass->src_name << "::msgpack_unpack(const vk::msgpack::object &msgpack_o) " << BEGIN << "if (msgpack_o.type != vk::msgpack::stored_type::ARRAY) { SerializationLibContext::get().set_msgpack_error(vk::msgpack::TYPE_ERROR); return; }" << NL - << "auto arr = msgpack_o.via.array;" << NL - << "for (size_t i = 0; i < arr.size; i += 2)" << BEGIN - << "auto tag = arr.ptr[i].as();" << NL - << "[[maybe_unused]] auto elem = arr.ptr[i + 1];" << NL - << "switch (tag) " << BEGIN - << JoinValues(cases, "", join_mode::multiple_lines) << NL - << END << NL - << END << NL - << END << NL; + << "auto arr = msgpack_o.via.array;" << NL << "for (size_t i = 0; i < arr.size; i += 2)" << BEGIN << "auto tag = arr.ptr[i].as();" << NL + << "[[maybe_unused]] auto elem = arr.ptr[i + 1];" << NL << "switch (tag) " << BEGIN << JoinValues(cases, "", join_mode::multiple_lines) << NL << END << NL + << END << NL << END << NL; } -StaticLibraryRunGlobal::StaticLibraryRunGlobal(gen_out_style style) : - style(style) { -} +StaticLibraryRunGlobal::StaticLibraryRunGlobal(gen_out_style style) + : style(style) {} -void StaticLibraryRunGlobal::compile(CodeGenerator &W) const { +void StaticLibraryRunGlobal::compile(CodeGenerator& W) const { switch (style) { - case gen_out_style::tagger: - case gen_out_style::cpp: - FunctionSignatureGenerator(W) << "void f$" << LibData::run_global_function_name(G->get_global_namespace()) << "()"; - break; - case gen_out_style::txt: - W << "function " << LibData::run_global_function_name(G->get_global_namespace()) << "() ::: void"; - break; + case gen_out_style::tagger: + case gen_out_style::cpp: + FunctionSignatureGenerator(W) << "void f$" << LibData::run_global_function_name(G->get_global_namespace()) << "()"; + break; + case gen_out_style::txt: + W << "function " << LibData::run_global_function_name(G->get_global_namespace()) << "() ::: void"; + break; } } - diff --git a/compiler/code-gen/declarations.h b/compiler/code-gen/declarations.h index d46adc9cd6..2b5927e288 100644 --- a/compiler/code-gen/declarations.h +++ b/compiler/code-gen/declarations.h @@ -12,18 +12,18 @@ #include "compiler/code-gen/code-gen-root-cmd.h" #include "compiler/code-gen/code-generator.h" #include "compiler/code-gen/gen-out-style.h" +#include "compiler/code-gen/includes.h" #include "compiler/code-gen/naming.h" #include "compiler/compiler-core.h" #include "compiler/data/data_ptr.h" #include "compiler/vertex-meta_op_base.h" -#include "compiler/code-gen/includes.h" struct VarDeclaration { VarPtr var; bool extern_flag; bool defval_flag; VarDeclaration(VarPtr var, bool extern_flag = false, bool defval_flag = true); - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; VarDeclaration VarPlainDeclaration(VarPtr var); @@ -33,14 +33,14 @@ struct FunctionDeclaration { bool in_header; gen_out_style style; FunctionDeclaration(FunctionPtr function, bool in_header = false, gen_out_style style = gen_out_style::cpp); - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; struct FunctionForkDeclaration { FunctionPtr function; bool in_header; FunctionForkDeclaration(FunctionPtr function, bool in_header = false); - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; struct FunctionParams { @@ -54,19 +54,20 @@ struct FunctionParams { FunctionParams(FunctionPtr function, size_t shift, bool in_header = false, gen_out_style style = gen_out_style::cpp); - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; private: - void declare_cpp_param(CodeGenerator &W, VertexAdaptor var, const TypeName &type) const; - void declare_txt_param(CodeGenerator &W, VertexAdaptor var, const TypeName &type) const; + void declare_cpp_param(CodeGenerator& W, VertexAdaptor var, const TypeName& type) const; + void declare_txt_param(CodeGenerator& W, VertexAdaptor var, const TypeName& type) const; }; struct TlDependentTypesUsings { TlDependentTypesUsings() = default; - explicit TlDependentTypesUsings(vk::tlo_parsing::type *tl_type, const std::string &php_tl_class_name); + explicit TlDependentTypesUsings(vk::tlo_parsing::type* tl_type, const std::string& php_tl_class_name); + + void compile(CodeGenerator& W) const; + void compile_dependencies(CodeGenerator& W); - void compile(CodeGenerator &W) const; - void compile_dependencies(CodeGenerator &W); private: struct InnerParamTypeAccess { bool drop_class_instance{false}; @@ -74,9 +75,9 @@ struct TlDependentTypesUsings { InnerParamTypeAccess() = default; - InnerParamTypeAccess(bool drop_class_instance, const std::string &inner_type_name) : - drop_class_instance(drop_class_instance), - inner_type_name(inner_type_name) {} + InnerParamTypeAccess(bool drop_class_instance, const std::string& inner_type_name) + : drop_class_instance(drop_class_instance), + inner_type_name(inner_type_name) {} }; struct DeducingInfo { @@ -87,28 +88,29 @@ struct TlDependentTypesUsings { DeducingInfo(std::string deduced_type, std::vector path); }; - vk::tlo_parsing::type *tl_type; + vk::tlo_parsing::type* tl_type; std::map deduced_params; IncludesCollector dependencies; std::string specialization_suffix; // Deducing context - vk::tlo_parsing::combinator *cur_tl_constructor{}; - vk::tlo_parsing::arg *cur_tl_arg{}; + vk::tlo_parsing::combinator* cur_tl_constructor{}; + vk::tlo_parsing::arg* cur_tl_arg{}; - void deduce_params_from_type_tree(vk::tlo_parsing::type_expr_base *type_tree, std::vector &recursion_stack); + void deduce_params_from_type_tree(vk::tlo_parsing::type_expr_base* type_tree, std::vector& recursion_stack); bool check_deduction_result() const; }; struct FFIDeclaration : CodeGenRootCmd { ClassPtr ffi_scope; explicit FFIDeclaration(ClassPtr ffi_scope); - void compile(CodeGenerator &W) const final; + void compile(CodeGenerator& W) const final; }; struct InterfaceDeclaration : CodeGenRootCmd { InterfacePtr interface; explicit InterfaceDeclaration(InterfacePtr interface); - void compile(CodeGenerator &W) const final; + void compile(CodeGenerator& W) const final; + private: std::unique_ptr detect_if_needs_tl_usings() const; }; @@ -116,49 +118,49 @@ struct InterfaceDeclaration : CodeGenRootCmd { struct ClassDeclaration : CodeGenRootCmd { ClassPtr klass; explicit ClassDeclaration(ClassPtr klass); - void compile(CodeGenerator &W) const final; - static void compile_inner_methods(CodeGenerator &W, ClassPtr klass); + void compile(CodeGenerator& W) const final; + static void compile_inner_methods(CodeGenerator& W, ClassPtr klass); private: - static void compile_fields(CodeGenerator &W, ClassPtr klass); - static void compile_json_flatten_flag(CodeGenerator &W, ClassPtr klass); - static void compile_has_wakeup_flag(CodeGenerator &W, ClassPtr klass); - static void compile_get_class(CodeGenerator &W, ClassPtr klass); - static void compile_get_hash(CodeGenerator &W, ClassPtr klass); - static void compile_accept_visitor_methods(CodeGenerator &W, ClassPtr klass); - static void compile_msgpack_declarations(CodeGenerator &W, ClassPtr klass); - static void compile_virtual_builtin_functions(CodeGenerator &W, ClassPtr klass); - static void compile_wakeup(CodeGenerator &W, ClassPtr klass); + static void compile_fields(CodeGenerator& W, ClassPtr klass); + static void compile_json_flatten_flag(CodeGenerator& W, ClassPtr klass); + static void compile_has_wakeup_flag(CodeGenerator& W, ClassPtr klass); + static void compile_get_class(CodeGenerator& W, ClassPtr klass); + static void compile_get_hash(CodeGenerator& W, ClassPtr klass); + static void compile_accept_visitor_methods(CodeGenerator& W, ClassPtr klass); + static void compile_msgpack_declarations(CodeGenerator& W, ClassPtr klass); + static void compile_virtual_builtin_functions(CodeGenerator& W, ClassPtr klass); + static void compile_wakeup(CodeGenerator& W, ClassPtr klass); template - static void compile_class_method(FunctionSignatureGenerator &&W, ClassPtr klass, vk::string_view method_signature, const ReturnValueT &return_value); - - static void compile_accept_visitor(CodeGenerator &W, ClassPtr klass, const char *visitor_type); - static void compile_generic_accept(CodeGenerator &W, ClassPtr klass); - static void compile_accept_json_visitor(CodeGenerator &W, ClassPtr klass); - IncludesCollector compile_front_includes(CodeGenerator &W) const; - void compile_back_includes(CodeGenerator &W, IncludesCollector &&front_includes) const; - void compile_job_worker_shared_memory_piece_methods(CodeGenerator &W, bool compile_declaration_only = false) const; + static void compile_class_method(FunctionSignatureGenerator&& W, ClassPtr klass, vk::string_view method_signature, const ReturnValueT& return_value); + + static void compile_accept_visitor(CodeGenerator& W, ClassPtr klass, const char* visitor_type); + static void compile_generic_accept(CodeGenerator& W, ClassPtr klass); + static void compile_accept_json_visitor(CodeGenerator& W, ClassPtr klass); + IncludesCollector compile_front_includes(CodeGenerator& W) const; + void compile_back_includes(CodeGenerator& W, IncludesCollector&& front_includes) const; + void compile_job_worker_shared_memory_piece_methods(CodeGenerator& W, bool compile_declaration_only = false) const; std::unique_ptr detect_if_needs_tl_usings() const; }; struct ClassMembersDefinition : CodeGenRootCmd { ClassPtr klass; explicit ClassMembersDefinition(ClassPtr klass) - : klass(klass) {} - void compile(CodeGenerator &W) const final; + : klass(klass) {} + void compile(CodeGenerator& W) const final; private: - static void compile_generic_accept(CodeGenerator &W, ClassPtr klass); - static void compile_generic_accept_instantiations(CodeGenerator &W, ClassPtr klass, vk::string_view type); - static void compile_accept_json_visitor(CodeGenerator &W, ClassPtr klass); - static void compile_msgpack_serialize(CodeGenerator &W, ClassPtr klass); - static void compile_msgpack_deserialize(CodeGenerator &W, ClassPtr klass); + static void compile_generic_accept(CodeGenerator& W, ClassPtr klass); + static void compile_generic_accept_instantiations(CodeGenerator& W, ClassPtr klass, vk::string_view type); + static void compile_accept_json_visitor(CodeGenerator& W, ClassPtr klass); + static void compile_msgpack_serialize(CodeGenerator& W, ClassPtr klass); + static void compile_msgpack_deserialize(CodeGenerator& W, ClassPtr klass); }; struct StaticLibraryRunGlobal { gen_out_style style; explicit StaticLibraryRunGlobal(gen_out_style style); - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; diff --git a/compiler/code-gen/files/cmake-lists-txt.cpp b/compiler/code-gen/files/cmake-lists-txt.cpp index 1fa87a4269..29c5e5339a 100644 --- a/compiler/code-gen/files/cmake-lists-txt.cpp +++ b/compiler/code-gen/files/cmake-lists-txt.cpp @@ -7,9 +7,9 @@ #include #include +#include "common/wrappers/fmt_format.h" #include "compiler/code-gen/common.h" #include "compiler/compiler-core.h" -#include "common/wrappers/fmt_format.h" void CmakeListsTxt::compile_include_cmake() const noexcept { // 1) creating of file outside of CompilerSettings::dest_cpp_dir directory is unable with CodeGenerator, @@ -19,16 +19,16 @@ void CmakeListsTxt::compile_include_cmake() const noexcept { std::filesystem::path file_path{G->settings().kphp_src_path.get()}; file_path /= "objs/custom_php_project.cmake"; if (!std::filesystem::exists(file_path)) { - std::ofstream file{file_path}; - file << "add_subdirectory(" << G->settings().dest_cpp_dir.get() << ")"; + std::ofstream file{file_path}; + file << "add_subdirectory(" << G->settings().dest_cpp_dir.get() << ")"; } } -void CmakeListsTxt::compile_cmake_lists_txt(CodeGenerator &W) const noexcept { +void CmakeListsTxt::compile_cmake_lists_txt(CodeGenerator& W) const noexcept { W << OpenFile{"CMakeLists.txt", {}, false, false}; const std::string target_name{"autogen_" + G->settings().mode.get()}; - W << fmt_format(R"cmake(#[[ + W << fmt_format(R"cmake(#[[ this CMakeLists.txt is autogenerated. It serves two purposes: 1) mostly to make IDE aware about *.cpp sources having been transpiled by kphp 2) but it also possible to use it for building *.cpp sources into final binary @@ -40,12 +40,13 @@ file(GLOB_RECURSE SRC_FILES ${{CMAKE_CURRENT_SOURCE_DIR}}/*.cpp) add_executable({0} EXCLUDE_FROM_ALL ${{SRC_FILES}}) target_include_directories({0} PRIVATE . ${{AUTO_DIR}}/runtime/) -target_link_libraries({0} PRIVATE ${{RUNTIME_LIBS}} ${{RUNTIME_LINK_TEST_LIBS}}))cmake", target_name); +target_link_libraries({0} PRIVATE ${{RUNTIME_LIBS}} ${{RUNTIME_LINK_TEST_LIBS}}))cmake", + target_name); W << CloseFile{}; } -void CmakeListsTxt::compile(CodeGenerator &W) const noexcept { +void CmakeListsTxt::compile(CodeGenerator& W) const noexcept { compile_include_cmake(); compile_cmake_lists_txt(W); } diff --git a/compiler/code-gen/files/cmake-lists-txt.h b/compiler/code-gen/files/cmake-lists-txt.h index b15a7b1987..c03894f484 100644 --- a/compiler/code-gen/files/cmake-lists-txt.h +++ b/compiler/code-gen/files/cmake-lists-txt.h @@ -9,9 +9,9 @@ class CodeGenerator; struct CmakeListsTxt : CodeGenRootCmd { - void compile(CodeGenerator &W) const noexcept final; + void compile(CodeGenerator& W) const noexcept final; private: void compile_include_cmake() const noexcept; - void compile_cmake_lists_txt(CodeGenerator &W) const noexcept; + void compile_cmake_lists_txt(CodeGenerator& W) const noexcept; }; diff --git a/compiler/code-gen/files/const-vars-init.cpp b/compiler/code-gen/files/const-vars-init.cpp index 51c1519ffe..c860d0ff17 100644 --- a/compiler/code-gen/files/const-vars-init.cpp +++ b/compiler/code-gen/files/const-vars-init.cpp @@ -17,9 +17,10 @@ struct InitConstVar { VarPtr var; - explicit InitConstVar(VarPtr var) : var(var) {} + explicit InitConstVar(VarPtr var) + : var(var) {} - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { Location save_location = stage::get_location(); VertexPtr init_val = var->init_val; @@ -40,8 +41,7 @@ struct InitConstVar { } }; - -static void compile_raw_array(CodeGenerator &W, const VarPtr &var, int shift) { +static void compile_raw_array(CodeGenerator& W, const VarPtr& var, int shift) { if (shift == -1) { W << InitConstVar(var); W << var->name << ".set_reference_counter_to(ExtraRefCnt::for_global_const);" << NL << NL; @@ -51,10 +51,10 @@ static void compile_raw_array(CodeGenerator &W, const VarPtr &var, int shift) { W << var->name << ".assign_raw((char *) &raw_arrays[" << shift << "]);" << NL << NL; } -ConstVarsInit::ConstVarsInit(const ConstantsBatchedMem &all_constants_in_mem) - : all_constants_in_mem(all_constants_in_mem) {} +ConstVarsInit::ConstVarsInit(const ConstantsBatchedMem& all_constants_in_mem) + : all_constants_in_mem(all_constants_in_mem) {} -void ConstVarsInit::compile_const_init_part(CodeGenerator &W, const ConstantsBatchedMem::OneBatchInfo &batch) { +void ConstVarsInit::compile_const_init_part(CodeGenerator& W, const ConstantsBatchedMem::OneBatchInfo& batch) { DepLevelContainer const_raw_array_vars; DepLevelContainer other_const_vars; DepLevelContainer const_raw_string_vars; @@ -78,21 +78,20 @@ void ConstVarsInit::compile_const_init_part(CodeGenerator &W, const ConstantsBat for (VarPtr var : batch.constants) { switch (var->init_val->type()) { - case op_string: - const_raw_string_vars.add(var); - break; - case op_array: - const_raw_array_vars.add(var); - break; - default: - other_const_vars.add(var); - break; + case op_string: + const_raw_string_vars.add(var); + break; + case op_array: + const_raw_array_vars.add(var); + break; + default: + other_const_vars.add(var); + break; } } std::vector str_values(const_raw_string_vars.size()); - std::transform(const_raw_string_vars.begin(), const_raw_string_vars.end(), - str_values.begin(), + std::transform(const_raw_string_vars.begin(), const_raw_string_vars.end(), str_values.begin(), [](VarPtr var) { return var->init_val.as()->str_val; }); const std::vector const_string_shifts = compile_raw_data(W, str_values); @@ -113,9 +112,9 @@ void ConstVarsInit::compile_const_init_part(CodeGenerator &W, const ConstantsBat compile_raw_array(W, var, const_array_shifts[arr_idx++]); } - for (VarPtr var: other_const_vars.vars_by_dep_level(dep_level)) { + for (VarPtr var : other_const_vars.vars_by_dep_level(dep_level)) { W << InitConstVar(var); - const TypeData *type_data = var->tinf_node.get_type(); + const TypeData* type_data = var->tinf_node.get_type(); if (vk::any_of_equal(type_data->ptype(), tp_array, tp_mixed, tp_string, tp_Class)) { W << var->name; if (type_data->use_optional()) { @@ -131,7 +130,7 @@ void ConstVarsInit::compile_const_init_part(CodeGenerator &W, const ConstantsBat W << CloseNamespace(); } -void ConstVarsInit::compile_const_init(CodeGenerator &W, const ConstantsBatchedMem &all_constants_in_mem) { +void ConstVarsInit::compile_const_init(CodeGenerator& W, const ConstantsBatchedMem& all_constants_in_mem) { W << OpenNamespace(); W << NL; @@ -140,12 +139,12 @@ void ConstVarsInit::compile_const_init(CodeGenerator &W, const ConstantsBatchedM W << ConstantsMemAllocation() << NL; int very_max_dep_level = 0; - for (const auto &batch : all_constants_in_mem.get_batches()) { + for (const auto& batch : all_constants_in_mem.get_batches()) { very_max_dep_level = std::max(very_max_dep_level, batch.max_dep_level); } for (int dep_level = 0; dep_level <= very_max_dep_level; ++dep_level) { - for (const auto &batch : all_constants_in_mem.get_batches()) { + for (const auto& batch : all_constants_in_mem.get_batches()) { if (dep_level <= batch.max_dep_level) { const std::string func_name_i = fmt_format("const_init_level{}_file{}", dep_level, batch.batch_idx); // function declaration @@ -159,8 +158,8 @@ void ConstVarsInit::compile_const_init(CodeGenerator &W, const ConstantsBatchedM W << CloseNamespace(); } -void ConstVarsInit::compile(CodeGenerator &W) const { - for (const auto &batch : all_constants_in_mem.get_batches()) { +void ConstVarsInit::compile(CodeGenerator& W) const { + for (const auto& batch : all_constants_in_mem.get_batches()) { W << OpenFile("c." + std::to_string(batch.batch_idx) + ".cpp", "o_const_init", false); W << ExternInclude(G->settings().runtime_headers.get()); compile_const_init_part(W, batch); diff --git a/compiler/code-gen/files/const-vars-init.h b/compiler/code-gen/files/const-vars-init.h index 585e0a0916..5d00e81218 100644 --- a/compiler/code-gen/files/const-vars-init.h +++ b/compiler/code-gen/files/const-vars-init.h @@ -9,13 +9,13 @@ #include "compiler/code-gen/const-globals-batched-mem.h" struct ConstVarsInit : CodeGenRootCmd { - explicit ConstVarsInit(const ConstantsBatchedMem &all_constants_in_mem); - - void compile(CodeGenerator &W) const final; + explicit ConstVarsInit(const ConstantsBatchedMem& all_constants_in_mem); + + void compile(CodeGenerator& W) const final; static void compile_const_init_part(CodeGenerator& W, const ConstantsBatchedMem::OneBatchInfo& batch); - static void compile_const_init(CodeGenerator &W, const ConstantsBatchedMem &all_constants_in_mem); + static void compile_const_init(CodeGenerator& W, const ConstantsBatchedMem& all_constants_in_mem); private: - const ConstantsBatchedMem &all_constants_in_mem; + const ConstantsBatchedMem& all_constants_in_mem; }; diff --git a/compiler/code-gen/files/function-header.cpp b/compiler/code-gen/files/function-header.cpp index f75890d0e4..7076503ccb 100644 --- a/compiler/code-gen/files/function-header.cpp +++ b/compiler/code-gen/files/function-header.cpp @@ -13,11 +13,10 @@ #include "compiler/code-gen/vertex-compiler.h" #include "compiler/data/function-data.h" -FunctionH::FunctionH(FunctionPtr function) : - function(function) { -} +FunctionH::FunctionH(FunctionPtr function) + : function(function) {} -void FunctionH::compile(CodeGenerator &W) const { +void FunctionH::compile(CodeGenerator& W) const { W << OpenFile(function->header_name, function->subdir); W << "#pragma once" << NL << ExternInclude(G->settings().runtime_headers.get()); @@ -46,7 +45,7 @@ void FunctionH::compile(CodeGenerator &W) const { } if (function->is_inline) { stage::set_function(function); - function->name_gen_map = {}; // make codegeneration of this function idempotent + function->name_gen_map = {}; // make codegeneration of this function idempotent W << CloseNamespace(); includes.start_next_block(); diff --git a/compiler/code-gen/files/function-header.h b/compiler/code-gen/files/function-header.h index df36efea05..2a2ef35614 100644 --- a/compiler/code-gen/files/function-header.h +++ b/compiler/code-gen/files/function-header.h @@ -11,6 +11,5 @@ struct FunctionH : CodeGenRootCmd { FunctionPtr function; explicit FunctionH(FunctionPtr function); - void compile(CodeGenerator &W) const final; + void compile(CodeGenerator& W) const final; }; - diff --git a/compiler/code-gen/files/function-source.cpp b/compiler/code-gen/files/function-source.cpp index d464e457fc..e13f76116d 100644 --- a/compiler/code-gen/files/function-source.cpp +++ b/compiler/code-gen/files/function-source.cpp @@ -13,11 +13,10 @@ #include "compiler/code-gen/vertex-compiler.h" #include "compiler/stage.h" -FunctionCpp::FunctionCpp(FunctionPtr function) : - function(function) { -} +FunctionCpp::FunctionCpp(FunctionPtr function) + : function(function) {} -void declare_const_vars(FunctionPtr function, CodeGenerator &W) { +void declare_const_vars(FunctionPtr function, CodeGenerator& W) { ConstantsExternCollector c_mem_extern; for (VarPtr var : function->explicit_const_var_ids) { c_mem_extern.add_extern_from_var(var); @@ -25,7 +24,7 @@ void declare_const_vars(FunctionPtr function, CodeGenerator &W) { W << c_mem_extern << NL; } -void FunctionCpp::compile(CodeGenerator &W) const { +void FunctionCpp::compile(CodeGenerator& W) const { if (function->is_inline) { return; } @@ -34,7 +33,7 @@ void FunctionCpp::compile(CodeGenerator &W) const { W << Include(function->header_full_name); stage::set_function(function); - function->name_gen_map = {}; // make codegeneration of this function idempotent + function->name_gen_map = {}; // make codegeneration of this function idempotent IncludesCollector includes; includes.add_function_body_depends(function); diff --git a/compiler/code-gen/files/function-source.h b/compiler/code-gen/files/function-source.h index 7e7062c9c7..a1f39db48a 100644 --- a/compiler/code-gen/files/function-source.h +++ b/compiler/code-gen/files/function-source.h @@ -11,8 +11,8 @@ struct FunctionCpp : CodeGenRootCmd { FunctionPtr function; explicit FunctionCpp(FunctionPtr function); - void compile(CodeGenerator &W) const final; + void compile(CodeGenerator& W) const final; }; -void declare_global_vars(FunctionPtr function, CodeGenerator &W); -void declare_const_vars(FunctionPtr function, CodeGenerator &W); +void declare_global_vars(FunctionPtr function, CodeGenerator& W); +void declare_const_vars(FunctionPtr function, CodeGenerator& W); diff --git a/compiler/code-gen/files/global-vars-memory-stats.cpp b/compiler/code-gen/files/global-vars-memory-stats.cpp index 6e5b7a62c6..f5fb8022ff 100644 --- a/compiler/code-gen/files/global-vars-memory-stats.cpp +++ b/compiler/code-gen/files/global-vars-memory-stats.cpp @@ -13,7 +13,7 @@ #include "compiler/data/src-file.h" #include "compiler/inferring/public.h" -GlobalVarsMemoryStats::GlobalVarsMemoryStats(const std::vector &all_globals) { +GlobalVarsMemoryStats::GlobalVarsMemoryStats(const std::vector& all_globals) { for (VarPtr global_var : all_globals) { bool is_primitive = vk::any_of_equal(tinf::get_type(global_var)->get_real_ptype(), tp_bool, tp_int, tp_float, tp_regexp, tp_any); if (!is_primitive && !global_var->is_builtin_runtime) { @@ -24,34 +24,29 @@ GlobalVarsMemoryStats::GlobalVarsMemoryStats(const std::vector &all_glob std::sort(all_nonprimitive_globals.begin(), all_nonprimitive_globals.end()); } -void GlobalVarsMemoryStats::compile(CodeGenerator &W) const { +void GlobalVarsMemoryStats::compile(CodeGenerator& W) const { int total_count = static_cast(all_nonprimitive_globals.size()); int parts_cnt = static_cast(std::ceil(static_cast(total_count) / N_GLOBALS_PER_FILE)); - W << OpenFile("globals_memory_stats.cpp", "", false) - << ExternInclude(G->settings().runtime_headers.get()) - << OpenNamespace(); + W << OpenFile("globals_memory_stats.cpp", "", false) << ExternInclude(G->settings().runtime_headers.get()) << OpenNamespace(); // we don't take libs into account here (don't call "global memory stats" for every lib), // since we have to guarantee that libs were compiled with a necessary flag also // (most likely, not, then C++ compilation will fail) - FunctionSignatureGenerator(W) << "array " << getter_name_ << "(int64_t lower_bound, " - << PhpMutableGlobalsConstRefArgument() << ")" << BEGIN - << "array result;" << NL - << "result.reserve(" << total_count << ", false);" << NL << NL; + FunctionSignatureGenerator(W) << "array " << getter_name_ << "(int64_t lower_bound, " << PhpMutableGlobalsConstRefArgument() << ")" << BEGIN + << "array result;" << NL << "result.reserve(" << total_count << ", false);" << NL << NL; for (int part_id = 0; part_id < parts_cnt; ++part_id) { const std::string func_name_i = getter_name_ + std::to_string(part_id); // function declaration - FunctionSignatureGenerator(W) << "void " << func_name_i << "(int64_t lower_bound, array &result, " << PhpMutableGlobalsConstRefArgument() << ")" << SemicolonAndNL(); + FunctionSignatureGenerator(W) << "void " << func_name_i << "(int64_t lower_bound, array &result, " << PhpMutableGlobalsConstRefArgument() << ")" + << SemicolonAndNL(); // function call W << func_name_i << "(lower_bound, result, php_globals);" << NL << NL; } - W << "return result;" << NL << END - << CloseNamespace() - << CloseFile(); + W << "return result;" << NL << END << CloseNamespace() << CloseFile(); for (int part_id = 0; part_id < parts_cnt; ++part_id) { int offset = part_id * N_GLOBALS_PER_FILE; @@ -64,7 +59,7 @@ void GlobalVarsMemoryStats::compile(CodeGenerator &W) const { } } -void GlobalVarsMemoryStats::compile_getter_part(CodeGenerator &W, int part_id, const std::vector &global_vars, int offset, int count) { +void GlobalVarsMemoryStats::compile_getter_part(CodeGenerator& W, int part_id, const std::vector& global_vars, int offset, int count) { IncludesCollector includes; std::vector var_names; var_names.reserve(count); @@ -79,31 +74,24 @@ void GlobalVarsMemoryStats::compile_getter_part(CodeGenerator &W, int part_id, c var_names.emplace_back(std::move(var_name)); } - W << includes << NL - << OpenNamespace(); + W << includes << NL << OpenNamespace(); const auto var_name_shifts = compile_raw_data(W, var_names); W << NL; FunctionSignatureGenerator(W) << "static string get_raw_string(int raw_offset) " << BEGIN; - W << "string str;" << NL - << "str.assign_raw(&raw[raw_offset]);" << NL - << "return str;" << NL - << END << NL << NL; + W << "string str;" << NL << "str.assign_raw(&raw[raw_offset]);" << NL << "return str;" << NL << END << NL << NL; - FunctionSignatureGenerator(W) << "void " << getter_name_ << part_id << "(int64_t lower_bound, array &result, " - << PhpMutableGlobalsConstRefArgument() << ")" << BEGIN; + FunctionSignatureGenerator(W) << "void " << getter_name_ << part_id << "(int64_t lower_bound, array &result, " << PhpMutableGlobalsConstRefArgument() + << ")" << BEGIN; if (count) { W << "int64_t estimation = 0;" << NL; } for (int i = 0; i < count; ++i) { VarPtr global_var = global_vars[offset + i]; - W << "// " << var_names[i] << NL - << "estimation = f$estimate_memory_usage(" << GlobalVarInPhpGlobals(global_var) << ");" << NL - << "if (estimation > lower_bound) " << BEGIN - << "result.set_value(get_raw_string(" << var_name_shifts[i] << "), estimation);" << NL - << END << NL; + W << "// " << var_names[i] << NL << "estimation = f$estimate_memory_usage(" << GlobalVarInPhpGlobals(global_var) << ");" << NL + << "if (estimation > lower_bound) " << BEGIN << "result.set_value(get_raw_string(" << var_name_shifts[i] << "), estimation);" << NL << END << NL; } W << END; diff --git a/compiler/code-gen/files/global-vars-memory-stats.h b/compiler/code-gen/files/global-vars-memory-stats.h index 8c324b3fed..16b6ea2ba3 100644 --- a/compiler/code-gen/files/global-vars-memory-stats.h +++ b/compiler/code-gen/files/global-vars-memory-stats.h @@ -9,15 +9,15 @@ #include "compiler/data/data_ptr.h" struct GlobalVarsMemoryStats : CodeGenRootCmd { - explicit GlobalVarsMemoryStats(const std::vector &all_globals); + explicit GlobalVarsMemoryStats(const std::vector& all_globals); - void compile(CodeGenerator &W) const final; + void compile(CodeGenerator& W) const final; private: - static void compile_getter_part(CodeGenerator &W, int part_id, const std::vector &global_vars, int offset, int count); + static void compile_getter_part(CodeGenerator& W, int part_id, const std::vector& global_vars, int offset, int count); std::vector all_nonprimitive_globals; - static constexpr const char *getter_name_ = "globals_memory_stats_impl"; // hardcoded in runtime, see f$get_global_vars_memory_stats() + static constexpr const char* getter_name_ = "globals_memory_stats_impl"; // hardcoded in runtime, see f$get_global_vars_memory_stats() static constexpr int N_GLOBALS_PER_FILE = 512; }; diff --git a/compiler/code-gen/files/global-vars-reset.cpp b/compiler/code-gen/files/global-vars-reset.cpp index 8c0bbbc392..14fe28c2f2 100644 --- a/compiler/code-gen/files/global-vars-reset.cpp +++ b/compiler/code-gen/files/global-vars-reset.cpp @@ -14,10 +14,10 @@ #include "compiler/inferring/type-data.h" #include "compiler/kphp_assert.h" -GlobalVarsReset::GlobalVarsReset(const GlobalsBatchedMem &all_globals_in_mem) - : all_globals_in_mem(all_globals_in_mem) {} +GlobalVarsReset::GlobalVarsReset(const GlobalsBatchedMem& all_globals_in_mem) + : all_globals_in_mem(all_globals_in_mem) {} -void GlobalVarsReset::compile_globals_reset_part(CodeGenerator &W, const GlobalsBatchedMem::OneBatchInfo &batch) { +void GlobalVarsReset::compile_globals_reset_part(CodeGenerator& W, const GlobalsBatchedMem::OneBatchInfo& batch) { IncludesCollector includes; for (VarPtr var : batch.globals) { includes.add_var_signature_depends(var); @@ -36,7 +36,7 @@ void GlobalVarsReset::compile_globals_reset_part(CodeGenerator &W, const Globals FunctionSignatureGenerator(W) << "void global_vars_reset_file" << batch.batch_idx << "(" << PhpMutableGlobalsRefArgument() << ")" << BEGIN; for (VarPtr var : batch.globals) { - if (var->is_builtin_runtime) { // they are manually reset in runtime sources + if (var->is_builtin_runtime) { // they are manually reset in runtime sources continue; } @@ -45,13 +45,12 @@ void GlobalVarsReset::compile_globals_reset_part(CodeGenerator &W, const Globals W << "hard_reset_var(" << GlobalVarInPhpGlobals(var); if (var->init_val) { // TODO: fix unstable type inferring - const TypeData *global_var_type = tinf::get_type(var); - const TypeData *init_val_type = tinf::get_type(var->init_val); + const TypeData* global_var_type = tinf::get_type(var); + const TypeData* init_val_type = tinf::get_type(var->init_val); // a -> b <=> !a || b - kphp_error(!(global_var_type->get_real_ptype() == tp_array && - init_val_type->get_real_ptype() == tp_array && - init_val_type->lookup_at_any_key()->get_real_ptype() != tp_any) - || are_equal_types(global_var_type, init_val_type), + kphp_error(!(global_var_type->get_real_ptype() == tp_array && init_val_type->get_real_ptype() == tp_array && + init_val_type->lookup_at_any_key()->get_real_ptype() != tp_any) || + are_equal_types(global_var_type, init_val_type), fmt_format("Types of global variable and its init value differ: {} and {}.\n" "Probably because of unstable type inferring, try rerun compilation", global_var_type->as_human_readable(), init_val_type->as_human_readable())); @@ -65,11 +64,11 @@ void GlobalVarsReset::compile_globals_reset_part(CodeGenerator &W, const Globals W << CloseNamespace(); } -void GlobalVarsReset::compile_globals_reset(CodeGenerator &W, const GlobalsBatchedMem &all_globals_in_mem) { +void GlobalVarsReset::compile_globals_reset(CodeGenerator& W, const GlobalsBatchedMem& all_globals_in_mem) { W << OpenNamespace(); FunctionSignatureGenerator(W) << "void global_vars_reset(" << PhpMutableGlobalsRefArgument() << ")" << BEGIN; - for (const auto &batch : all_globals_in_mem.get_batches()) { + for (const auto& batch : all_globals_in_mem.get_batches()) { const std::string func_name_i = "global_vars_reset_file" + std::to_string(batch.batch_idx); // function declaration W << "void " << func_name_i << "(" << PhpMutableGlobalsRefArgument() << ");" << NL; @@ -82,7 +81,7 @@ void GlobalVarsReset::compile_globals_reset(CodeGenerator &W, const GlobalsBatch W << CloseNamespace(); } -void GlobalVarsReset::compile_globals_allocate(CodeGenerator &W) { +void GlobalVarsReset::compile_globals_allocate(CodeGenerator& W) { W << OpenNamespace(); FunctionSignatureGenerator(W) << "void global_vars_allocate(" << PhpMutableGlobalsRefArgument() << ")" << BEGIN; @@ -92,8 +91,8 @@ void GlobalVarsReset::compile_globals_allocate(CodeGenerator &W) { W << CloseNamespace(); } -void GlobalVarsReset::compile(CodeGenerator &W) const { - for (const auto &batch : all_globals_in_mem.get_batches()) { +void GlobalVarsReset::compile(CodeGenerator& W) const { + for (const auto& batch : all_globals_in_mem.get_batches()) { W << OpenFile("globals_reset." + std::to_string(batch.batch_idx) + ".cpp", "o_globals_reset", false); W << ExternInclude(G->settings().runtime_headers.get()); compile_globals_reset_part(W, batch); diff --git a/compiler/code-gen/files/global-vars-reset.h b/compiler/code-gen/files/global-vars-reset.h index 0d519d8e35..7997927e03 100644 --- a/compiler/code-gen/files/global-vars-reset.h +++ b/compiler/code-gen/files/global-vars-reset.h @@ -9,14 +9,14 @@ #include "compiler/code-gen/const-globals-batched-mem.h" struct GlobalVarsReset : CodeGenRootCmd { - explicit GlobalVarsReset(const GlobalsBatchedMem &all_globals_in_mem); + explicit GlobalVarsReset(const GlobalsBatchedMem& all_globals_in_mem); - void compile(CodeGenerator &W) const final; + void compile(CodeGenerator& W) const final; - static void compile_globals_reset_part(CodeGenerator &W, const GlobalsBatchedMem::OneBatchInfo &batch); - static void compile_globals_reset(CodeGenerator &W, const GlobalsBatchedMem &all_globals_in_mem); - static void compile_globals_allocate(CodeGenerator &W); + static void compile_globals_reset_part(CodeGenerator& W, const GlobalsBatchedMem::OneBatchInfo& batch); + static void compile_globals_reset(CodeGenerator& W, const GlobalsBatchedMem& all_globals_in_mem); + static void compile_globals_allocate(CodeGenerator& W); private: - const GlobalsBatchedMem &all_globals_in_mem; + const GlobalsBatchedMem& all_globals_in_mem; }; diff --git a/compiler/code-gen/files/init-scripts.cpp b/compiler/code-gen/files/init-scripts.cpp index df87e6c814..9537f3c602 100644 --- a/compiler/code-gen/files/init-scripts.cpp +++ b/compiler/code-gen/files/init-scripts.cpp @@ -21,10 +21,10 @@ #include "compiler/data/src-file.h" struct StaticInit { - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; -void StaticInit::compile(CodeGenerator &W) const { +void StaticInit::compile(CodeGenerator& W) const { if (G->is_output_mode_lib() || G->is_output_mode_k2_lib()) { return; } @@ -53,7 +53,7 @@ void StaticInit::compile(CodeGenerator &W) const { if (!G->is_output_mode_k2()) { FunctionSignatureGenerator(W) << ("char **get_runtime_options([[maybe_unused]] int *count)") << BEGIN; - const auto &runtime_opts = G->get_kphp_runtime_opts(); + const auto& runtime_opts = G->get_kphp_runtime_opts(); if (runtime_opts.empty()) { W << "return nullptr;" << NL; } else { @@ -92,27 +92,27 @@ void StaticInit::compile(CodeGenerator &W) const { FunctionSignatureGenerator(W) << "void const_vars_check_reference_counter()" << SemicolonAndNL() << NL; W << "const_vars_check_reference_counter();" << NL; - } + } W << NL; FunctionSignatureGenerator(W) << "void " << ShapeKeys::get_function_name() << "()" << SemicolonAndNL(); W << ShapeKeys::get_function_name() << "();" << NL; - const auto &ffi = G->get_ffi_root(); - const auto &ffi_shared_libs = ffi.get_shared_libs(); + const auto& ffi = G->get_ffi_root(); + const auto& ffi_shared_libs = ffi.get_shared_libs(); if (!ffi_shared_libs.empty()) { W << "ffi_env_instance = FFIEnv{" << ffi_shared_libs.size() << ", " << ffi.get_dynamic_symbols_num() << "};" << NL; W << "ffi_env_instance.funcs.dlopen = dlopen;" << NL; W << "ffi_env_instance.funcs.dlsym = dlsym;" << NL; - for (const auto &lib : ffi_shared_libs) { + for (const auto& lib : ffi_shared_libs) { W << "ffi_env_instance.libs[" << lib.id << "].path = " << RawString{lib.path} << ";" << NL; } - const auto &ffi_scopes = ffi.get_scopes(); - for (const auto &ffi_scope : ffi_scopes) { - for (const auto &sym : ffi_scope->variables) { + const auto& ffi_scopes = ffi.get_scopes(); + for (const auto& ffi_scope : ffi_scopes) { + for (const auto& sym : ffi_scope->variables) { W << "ffi_env_instance.symbols[" << sym.env_index << "].name = \"" << sym.name() << "\";" << NL; } - for (const auto &sym : ffi_scope->functions) { + for (const auto& sym : ffi_scope->functions) { W << "ffi_env_instance.symbols[" << sym.env_index << "].name = \"" << sym.name() << "\";" << NL; } } @@ -129,9 +129,9 @@ void StaticInit::compile(CodeGenerator &W) const { struct RunInterruptedFunction { FunctionPtr function; RunInterruptedFunction(FunctionPtr function) - : function(function) {} + : function(function) {} - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { std::string await_prefix = function->is_interruptible ? "co_await " : ""; std::string try_wrapper = "TRY_CALL_VOID_CORO(void, "; std::string image_kind = G->is_output_mode_k2_cli() ? "image_kind::cli" @@ -152,33 +152,31 @@ struct RunInterruptedFunction { struct RunFunction { FunctionPtr function; - RunFunction(FunctionPtr function) : function(function) {} + RunFunction(FunctionPtr function) + : function(function) {} - void compile(CodeGenerator &W) const { - FunctionSignatureGenerator(W) << "void " << FunctionName(function) << "$run() " << BEGIN - << "TRY_CALL_VOID (void, " << FunctionName(function) << "());" << NL - << "finish (0, false);" << NL - << END; + void compile(CodeGenerator& W) const { + FunctionSignatureGenerator(W) << "void " << FunctionName(function) << "$run() " << BEGIN << "TRY_CALL_VOID (void, " << FunctionName(function) << "());" + << NL << "finish (0, false);" << NL << END; W << NL; } }; - struct GlobalsResetFunction { FunctionPtr main_function; explicit GlobalsResetFunction(FunctionPtr main_function); - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; GlobalsResetFunction::GlobalsResetFunction(FunctionPtr main_function) - : main_function(main_function) {} + : main_function(main_function) {} -void GlobalsResetFunction::compile(CodeGenerator &W) const { +void GlobalsResetFunction::compile(CodeGenerator& W) const { // "global vars reset" declarations FunctionSignatureGenerator(W) << "void global_vars_allocate(" << PhpMutableGlobalsRefArgument() << ")" << SemicolonAndNL(); FunctionSignatureGenerator(W) << "void global_vars_reset(" << PhpMutableGlobalsRefArgument() << ")" << SemicolonAndNL(); W << NL; - for (LibPtr lib: G->get_libs()) { + for (LibPtr lib : G->get_libs()) { if (lib && !lib->is_raw_php()) { W << OpenNamespace(lib->lib_namespace()); FunctionSignatureGenerator(W) << "void global_vars_allocate(" << PhpMutableGlobalsRefArgument() << ")" << SemicolonAndNL(); @@ -190,7 +188,7 @@ void GlobalsResetFunction::compile(CodeGenerator &W) const { // "global vars reset" calls FunctionSignatureGenerator(W) << "void " << FunctionName(main_function) << "$globals_reset(" << PhpMutableGlobalsRefArgument() << ")" << BEGIN; W << "global_vars_reset(php_globals);" << NL; - for (LibPtr lib: G->get_libs()) { + for (LibPtr lib : G->get_libs()) { if (lib && !lib->is_raw_php()) { W << lib->lib_namespace() << "::global_vars_reset(php_globals);" << NL; } @@ -198,45 +196,39 @@ void GlobalsResetFunction::compile(CodeGenerator &W) const { W << END << NL; } - struct LibRunFunction { FunctionPtr main_function; LibRunFunction(FunctionPtr main_function); - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; -LibRunFunction::LibRunFunction(FunctionPtr main_function) : - main_function(main_function) { -} +LibRunFunction::LibRunFunction(FunctionPtr main_function) + : main_function(main_function) {} -void LibRunFunction::compile(CodeGenerator &W) const { +void LibRunFunction::compile(CodeGenerator& W) const { // "run" functions just calls the main file of a lib // it's guaranteed that it doesn't contain code except declarations (body_value is empty), // that's why we shouldn't deal with `if (!called)` global - W << StaticLibraryRunGlobal(gen_out_style::cpp) << BEGIN - << "using namespace " << G->get_global_namespace() << ";" << NL - << FunctionName(main_function) << "();" << NL - << END << NL << NL; + W << StaticLibraryRunGlobal(gen_out_style::cpp) << BEGIN << "using namespace " << G->get_global_namespace() << ";" << NL << FunctionName(main_function) + << "();" << NL << END << NL << NL; } +InitScriptsCpp::InitScriptsCpp(SrcFilePtr main_file_id) + : main_file_id(main_file_id) {} -InitScriptsCpp::InitScriptsCpp(SrcFilePtr main_file_id) : - main_file_id(main_file_id) {} - -void InitScriptsCpp::compile(CodeGenerator &W) const { +void InitScriptsCpp::compile(CodeGenerator& W) const { W << OpenFile("init_php_scripts.cpp", "", false); W << ExternInclude(G->settings().runtime_headers.get()); if (!G->is_output_mode_k2()) { - W << ExternInclude("server/php-init-scripts.h"); + W << ExternInclude("server/php-init-scripts.h"); } - W << Include(main_file_id->main_function->header_full_name); if (!G->get_ffi_root().get_shared_libs().empty()) { W << ExternInclude("runtime/ffi.h"); // FFI env singleton - W << ExternInclude("dlfcn.h"); // dlopen, dlsym + W << ExternInclude("dlfcn.h"); // dlopen, dlsym } W << NL << StaticInit() << NL; @@ -255,13 +247,16 @@ void InitScriptsCpp::compile(CodeGenerator &W) const { W << GlobalsResetFunction(main_file_id->main_function) << NL; if (G->is_output_mode_k2()) { - FunctionSignatureGenerator(W) << "void init_php_scripts_in_each_worker(" << PhpMutableGlobalsRefArgument() << ", kphp::coro::task<> &run" ")" << BEGIN; + FunctionSignatureGenerator(W) << "void init_php_scripts_in_each_worker(" << PhpMutableGlobalsRefArgument() + << ", kphp::coro::task<> &run" + ")" + << BEGIN; } else { FunctionSignatureGenerator(W) << "void init_php_scripts_in_each_worker(" << PhpMutableGlobalsRefArgument() << ")" << BEGIN; } W << "global_vars_allocate(php_globals);" << NL; - for (LibPtr lib: G->get_libs()) { + for (LibPtr lib : G->get_libs()) { if (lib && !lib->is_raw_php()) { W << lib->lib_namespace() << "::global_vars_allocate(php_globals);" << NL; } @@ -272,9 +267,7 @@ void InitScriptsCpp::compile(CodeGenerator &W) const { if (G->is_output_mode_k2()) { W << "run = " << FunctionName(main_file_id->main_function) << "$run();" << NL; } else { - W << "set_script (" - << FunctionName(main_file_id->main_function) << "$run, " - << FunctionName(main_file_id->main_function) << "$globals_reset);" << NL; + W << "set_script (" << FunctionName(main_file_id->main_function) << "$run, " << FunctionName(main_file_id->main_function) << "$globals_reset);" << NL; } W << END; @@ -282,7 +275,7 @@ void InitScriptsCpp::compile(CodeGenerator &W) const { W << CloseFile(); } -void LibVersionHFile::compile(CodeGenerator &W) const { +void LibVersionHFile::compile(CodeGenerator& W) const { W << OpenFile("_lib_version.h"); W << "// Runtime sha256: " << G->settings().runtime_sha256.get() << NL; W << "// CXX: " << G->settings().cxx.get() << NL; @@ -291,39 +284,31 @@ void LibVersionHFile::compile(CodeGenerator &W) const { W << CloseFile(); } -void CppMainFile::compile(CodeGenerator &W) const { +void CppMainFile::compile(CodeGenerator& W) const { kphp_assert(G->is_output_mode_server() || G->is_output_mode_cli()); W << OpenFile("main.cpp"); W << ExternInclude("server/php-engine.h") << NL; - W << "int main(int argc, char *argv[]) " << BEGIN - << "return run_main(argc, argv, php_mode::" << G->settings().mode.get() << ")" << SemicolonAndNL{} - << END; + W << "int main(int argc, char *argv[]) " << BEGIN << "return run_main(argc, argv, php_mode::" << G->settings().mode.get() << ")" << SemicolonAndNL{} << END; W << CloseFile(); } -void ComponentInfoFile::compile(CodeGenerator &W) const { +void ComponentInfoFile::compile(CodeGenerator& W) const { kphp_assert(G->is_output_mode_k2()); std::string php_code_commit_hash; if (!G->settings().php_code_commit_hash.get().empty()) { php_code_commit_hash.reserve(40 * 3 + 39 * 2); php_code_commit_hash.append(std::to_string(static_cast(G->settings().php_code_commit_hash.get().front()))); for (size_t i{1}; i != 40 && i != G->settings().php_code_commit_hash.get().size(); ++i) { - php_code_commit_hash - .append(", ") - .append(std::to_string(static_cast(G->settings().php_code_commit_hash.get()[i]))); + php_code_commit_hash.append(", ").append(std::to_string(static_cast(G->settings().php_code_commit_hash.get()[i]))); } } W << OpenFile("image_info.cpp"); W << ExternInclude(G->settings().runtime_headers.get()); W << "__attribute__((visibility(\"default\"))) const ImageInfo *k2_describe() " << BEGIN - << R"(static std::array extraInfo {ImageInfo::KeyValuePair{.key = "compiler_version", .value = ")" - << G->settings().get_version() << "\"}};" << NL << "static ImageInfo imageInfo {\"" - << G->settings().k2_component_name.get() << "\"" << "," - << (G->is_output_mode_k2_multishot() ? "0" : "1") << "," - << std::to_string( - std::chrono::duration_cast(G->settings().build_tp.time_since_epoch()).count() - ) << "," + << R"(static std::array extraInfo {ImageInfo::KeyValuePair{.key = "compiler_version", .value = ")" << G->settings().get_version() << "\"}};" << NL + << "static ImageInfo imageInfo {\"" << G->settings().k2_component_name.get() << "\"" << "," << (G->is_output_mode_k2_multishot() ? "0" : "1") << "," + << std::to_string(std::chrono::duration_cast(G->settings().build_tp.time_since_epoch()).count()) << "," << "K2_PLATFORM_HEADER_H_VERSION, " << "{" << php_code_commit_hash << "}," << "\"" << G->settings().php_code_version.get() << "\"," diff --git a/compiler/code-gen/files/init-scripts.h b/compiler/code-gen/files/init-scripts.h index 1c476fbf7c..0258c33bed 100644 --- a/compiler/code-gen/files/init-scripts.h +++ b/compiler/code-gen/files/init-scripts.h @@ -13,17 +13,17 @@ struct InitScriptsCpp : CodeGenRootCmd { SrcFilePtr main_file_id; explicit InitScriptsCpp(SrcFilePtr main_file_id); - void compile(CodeGenerator &W) const final; + void compile(CodeGenerator& W) const final; }; struct LibVersionHFile : CodeGenRootCmd { - void compile(CodeGenerator &W) const final; + void compile(CodeGenerator& W) const final; }; struct CppMainFile : CodeGenRootCmd { - void compile(CodeGenerator &W) const final; + void compile(CodeGenerator& W) const final; }; struct ComponentInfoFile : CodeGenRootCmd { - void compile(CodeGenerator &W) const final; + void compile(CodeGenerator& W) const final; }; diff --git a/compiler/code-gen/files/json-encoder-tags.cpp b/compiler/code-gen/files/json-encoder-tags.cpp index 92d5f5043b..a52f7e609b 100644 --- a/compiler/code-gen/files/json-encoder-tags.cpp +++ b/compiler/code-gen/files/json-encoder-tags.cpp @@ -11,11 +11,11 @@ const std::string JsonEncoderTags::all_tags_file_ = "_json_tags.h"; -std::string JsonEncoderTags::get_cppStructTag_name(const std::string &json_encoder) noexcept { +std::string JsonEncoderTags::get_cppStructTag_name(const std::string& json_encoder) noexcept { return replace_backslashes(json_encoder) + "Tag"; } -void JsonEncoderTags::compile(CodeGenerator &W) const { +void JsonEncoderTags::compile(CodeGenerator& W) const { if (all_json_encoders_.empty()) { return; } diff --git a/compiler/code-gen/files/json-encoder-tags.h b/compiler/code-gen/files/json-encoder-tags.h index c95026b1dc..c9d27e4b81 100644 --- a/compiler/code-gen/files/json-encoder-tags.h +++ b/compiler/code-gen/files/json-encoder-tags.h @@ -13,13 +13,13 @@ class CodeGenerator; struct JsonEncoderTags : CodeGenRootCmd { - explicit JsonEncoderTags(std::set &&all_json_encoders) noexcept : - all_json_encoders_(all_json_encoders) {} + explicit JsonEncoderTags(std::set&& all_json_encoders) noexcept + : all_json_encoders_(all_json_encoders) {} - void compile(CodeGenerator &W) const final; + void compile(CodeGenerator& W) const final; static const std::string all_tags_file_; - static std::string get_cppStructTag_name(const std::string &json_encoder) noexcept; + static std::string get_cppStructTag_name(const std::string& json_encoder) noexcept; private: const std::set all_json_encoders_; diff --git a/compiler/code-gen/files/lib-header.cpp b/compiler/code-gen/files/lib-header.cpp index 3f58c35227..630bec32ae 100644 --- a/compiler/code-gen/files/lib-header.cpp +++ b/compiler/code-gen/files/lib-header.cpp @@ -12,9 +12,8 @@ #include "compiler/compiler-core.h" #include "compiler/data/lib-data.h" -void StaticLibraryRunGlobalHeaderH::compile(CodeGenerator &W) const { - const std::string header_path = LibData::headers_tmp_dir() + - LibData::run_global_function_name(G->get_global_namespace()) + ".h"; +void StaticLibraryRunGlobalHeaderH::compile(CodeGenerator& W) const { + const std::string header_path = LibData::headers_tmp_dir() + LibData::run_global_function_name(G->get_global_namespace()) + ".h"; W << OpenFile(header_path, "", false); @@ -23,17 +22,16 @@ void StaticLibraryRunGlobalHeaderH::compile(CodeGenerator &W) const { W << CloseFile(); } -LibHeaderTxt::LibHeaderTxt(std::vector &&exported_functions) : - exported_functions(std::move(exported_functions)) { -} +LibHeaderTxt::LibHeaderTxt(std::vector&& exported_functions) + : exported_functions(std::move(exported_functions)) {} -void LibHeaderTxt::compile(CodeGenerator &W) const { +void LibHeaderTxt::compile(CodeGenerator& W) const { W << OpenFile(LibData::functions_txt_tmp_file(), "", false, false); W << "is_interruptible) { W << "/** @kphp-extern-func-info interruptible */" << NL; } @@ -43,19 +41,16 @@ void LibHeaderTxt::compile(CodeGenerator &W) const { W << CloseFile(); } -LibHeaderH::LibHeaderH(FunctionPtr exported_function) : - exported_function(exported_function) { -} +LibHeaderH::LibHeaderH(FunctionPtr exported_function) + : exported_function(exported_function) {} -void LibHeaderH::compile(CodeGenerator &W) const { +void LibHeaderH::compile(CodeGenerator& W) const { W << OpenFile(LibData::headers_tmp_dir() + exported_function->header_name, "", false); W << "#pragma once" << NL; W << ExternInclude(G->settings().runtime_headers.get()) << NL; - W << OpenNamespace() - << FunctionDeclaration(exported_function, true, gen_out_style::cpp) << ";" << NL - << CloseNamespace(); + W << OpenNamespace() << FunctionDeclaration(exported_function, true, gen_out_style::cpp) << ";" << NL << CloseNamespace(); W << "using " << G->get_global_namespace() << "::" << FunctionName(exported_function) << ";" << NL; W << CloseFile(); diff --git a/compiler/code-gen/files/lib-header.h b/compiler/code-gen/files/lib-header.h index 31e5b7fade..c25c4c8c86 100644 --- a/compiler/code-gen/files/lib-header.h +++ b/compiler/code-gen/files/lib-header.h @@ -8,17 +8,17 @@ #include "compiler/code-gen/code-generator.h" struct StaticLibraryRunGlobalHeaderH : CodeGenRootCmd { - void compile(CodeGenerator &W) const final; + void compile(CodeGenerator& W) const final; }; struct LibHeaderH : CodeGenRootCmd { FunctionPtr exported_function; explicit LibHeaderH(FunctionPtr exported_function); - void compile(CodeGenerator &W) const final; + void compile(CodeGenerator& W) const final; }; struct LibHeaderTxt : CodeGenRootCmd { std::vector exported_functions; - explicit LibHeaderTxt(std::vector &&exported_functions); - void compile(CodeGenerator &W) const final; + explicit LibHeaderTxt(std::vector&& exported_functions); + void compile(CodeGenerator& W) const final; }; diff --git a/compiler/code-gen/files/shape-keys.cpp b/compiler/code-gen/files/shape-keys.cpp index 763c2f4e76..f0450b1a40 100644 --- a/compiler/code-gen/files/shape-keys.cpp +++ b/compiler/code-gen/files/shape-keys.cpp @@ -16,7 +16,7 @@ std::string ShapeKeys::get_function_name() noexcept { return "init_shape_demangler"; } -void ShapeKeys::compile(CodeGenerator &W) const { +void ShapeKeys::compile(CodeGenerator& W) const { W << OpenFile{"_shape_keys.cpp"}; W << ExternInclude{G->settings().runtime_headers.get()}; std::string_view shape_keys_storage_t{G->is_output_mode_k2() ? "kphp::stl::unordered_map" @@ -27,7 +27,7 @@ void ShapeKeys::compile(CodeGenerator &W) const { FunctionSignatureGenerator{W} << "void " << get_function_name() << "()" << BEGIN; W << shape_keys_storage_t << " shape_keys_storage{" << NL; - for (const auto &[hash, key] : shape_keys_storage_) { + for (const auto& [hash, key] : shape_keys_storage_) { W << Indent{2} << "{" << hash << ", \"" << key.data() << "\"}," << NL << Indent{-2}; } diff --git a/compiler/code-gen/files/shape-keys.h b/compiler/code-gen/files/shape-keys.h index 585b1c32fb..31c098e84c 100644 --- a/compiler/code-gen/files/shape-keys.h +++ b/compiler/code-gen/files/shape-keys.h @@ -12,10 +12,10 @@ class CodeGenerator; struct ShapeKeys : CodeGenRootCmd { - explicit ShapeKeys(std::map shape_keys_storage) noexcept : - shape_keys_storage_(std::move(shape_keys_storage)) {} + explicit ShapeKeys(std::map shape_keys_storage) noexcept + : shape_keys_storage_(std::move(shape_keys_storage)) {} - void compile(CodeGenerator &W) const final; + void compile(CodeGenerator& W) const final; static std::string get_function_name() noexcept; diff --git a/compiler/code-gen/files/tl2cpp/tl-combinator.cpp b/compiler/code-gen/files/tl2cpp/tl-combinator.cpp index 65796d67c6..fadc35d332 100644 --- a/compiler/code-gen/files/tl2cpp/tl-combinator.cpp +++ b/compiler/code-gen/files/tl2cpp/tl-combinator.cpp @@ -9,9 +9,9 @@ #include "compiler/code-gen/files/tl2cpp/tl-type-expr.h" namespace tl2cpp { -inline std::vector get_not_optional_fields_masks(const vk::tlo_parsing::combinator *constructor) { +inline std::vector get_not_optional_fields_masks(const vk::tlo_parsing::combinator* constructor) { std::vector res; - for (const auto &arg : constructor->args) { + for (const auto& arg : constructor->args) { if (arg->var_num != -1 && type_of(arg->type_expr)->is_integer_variable() && !arg->is_optional()) { res.emplace_back(arg->name); } @@ -19,37 +19,37 @@ inline std::vector get_not_optional_fields_masks(const vk::tlo_pars return res; } -CombinatorGen::CombinatorGen(const vk::tlo_parsing::combinator *combinator, CombinatorPart part, bool typed_mode) : - combinator(combinator), - part(part), - typed_mode(typed_mode) { +CombinatorGen::CombinatorGen(const vk::tlo_parsing::combinator* combinator, CombinatorPart part, bool typed_mode) + : combinator(combinator), + part(part), + typed_mode(typed_mode) { kphp_error(!(part == CombinatorPart::RIGHT && combinator->is_constructor()), "Storing/fetching of constructor right part is never needed and strange"); this->var_num_access = (combinator->is_function() && part == CombinatorPart::LEFT ? "tl_func_state->" : ""); } -void CombinatorGen::compile(CodeGenerator &W) const { +void CombinatorGen::compile(CodeGenerator& W) const { switch (part) { - case CombinatorPart::LEFT: - compile_left(W); - break; - case CombinatorPart::RIGHT: - kphp_assert(!combinator->is_constructor()); - compile_right(W); - break; + case CombinatorPart::LEFT: + compile_left(W); + break; + case CombinatorPart::RIGHT: + kphp_assert(!combinator->is_constructor()); + compile_right(W); + break; } } -void CombinatorGen::compile_left(CodeGenerator &W) const { +void CombinatorGen::compile_left(CodeGenerator& W) const { tl2cpp::cur_combinator = combinator; // create local variables to hold the field mask values if (combinator->is_constructor()) { auto fields_masks = tl2cpp::get_not_optional_fields_masks(combinator); - for (const auto &item : fields_masks) { + for (const auto& item : fields_masks) { W << "int64_t " << item << "{0}; (void) " << item << ";" << NL; } } gen_before_args_processing(W); - for (const auto &arg : combinator->args) { + for (const auto& arg : combinator->args) { if (arg->is_optional()) { continue; } @@ -58,11 +58,11 @@ void CombinatorGen::compile_left(CodeGenerator &W) const { gen_after_args_processing(W); } -void CombinatorGen::compile_right(CodeGenerator &W) const { +void CombinatorGen::compile_right(CodeGenerator& W) const { gen_result_expr_processing(W); } -void CombinatorStore::gen_before_args_processing(CodeGenerator &W) const { +void CombinatorStore::gen_before_args_processing(CodeGenerator& W) const { W << "(void)tl_object;" << NL; if (combinator->is_function()) { W << fmt_format("f$store_int({:#010x});", static_cast(combinator->id)) << NL; @@ -70,22 +70,21 @@ void CombinatorStore::gen_before_args_processing(CodeGenerator &W) const { } } -void CombinatorStore::gen_arg_processing(CodeGenerator &W, const std::unique_ptr &arg) const { +void CombinatorStore::gen_arg_processing(CodeGenerator& W, const std::unique_ptr& arg) const { if (arg->is_named_fields_mask_bit()) { return; } if (arg->is_fields_mask_optional()) { - W << fmt_format("if ({}{} & (1 << {})) ", var_num_access, - combinator->get_var_num_arg(arg->exist_var_num)->name, - arg->exist_var_bit) << BEGIN; + W << fmt_format("if ({}{} & (1 << {})) ", var_num_access, combinator->get_var_num_arg(arg->exist_var_num)->name, arg->exist_var_bit) << BEGIN; if (typed_mode) { // check that field under the field mask is set std::string value_check = get_value_absence_check_for_optional_arg(arg); if (!value_check.empty()) { W << "if (" << value_check << ") " << BEGIN; - W - << fmt_format(R"(CurrentTlQuery::get().raise_storing_error("Optional field %s of %s is not set, but corresponding fields mask bit is set", "{}", "{}");)", - arg->name, combinator->name) << NL; + W << fmt_format( + R"(CurrentTlQuery::get().raise_storing_error("Optional field %s of %s is not set, but corresponding fields mask bit is set", "{}", "{}");)", + arg->name, combinator->name) + << NL; W << "return" << (combinator->is_function() ? " {};" : ";") << NL; W << END << NL; } @@ -97,45 +96,35 @@ void CombinatorStore::gen_arg_processing(CodeGenerator &W, const std::unique_ptr // Exclamation mark "!" handling if (arg->is_forwarded_function()) { kphp_assert(combinator->is_function()); - auto *as_type_var = arg->type_expr->as(); + auto* as_type_var = arg->type_expr->as(); kphp_assert(as_type_var); if (!typed_mode) { - const auto *k2_tl_storers_prefix = G->is_output_mode_k2() ? "RpcImageState::get()." : ""; + const auto* k2_tl_storers_prefix = G->is_output_mode_k2() ? "RpcImageState::get()." : ""; W << "auto _cur_arg = " - << fmt_format("tl_arr_get(tl_object, {}, {}, {}L)", tl2cpp::register_tl_const_str(arg->name), arg->idx, tl2cpp::hash_tl_const_str(arg->name)) + << fmt_format("tl_arr_get(tl_object, {}, {}, {}L)", tl2cpp::register_tl_const_str(arg->name), arg->idx, tl2cpp::hash_tl_const_str(arg->name)) << ";" + << NL; + W << "mixed target_f_name_mixed = " << fmt_format("tl_arr_get(_cur_arg, {}, 0, {}L)", tl2cpp::register_tl_const_str("_"), tl2cpp::hash_tl_const_str("_")) << ";" << NL; - W << "mixed target_f_name_mixed = " - << fmt_format("tl_arr_get(_cur_arg, {}, 0, {}L)", tl2cpp::register_tl_const_str("_"), tl2cpp::hash_tl_const_str("_")) - << ";" << NL; - W << "if (!target_f_name_mixed.is_string()) " << BEGIN - << R"(CurrentTlQuery::get().raise_storing_error("Field \"_\" of \")" << arg->name << R"(\" array is not string");)" << NL - << "return {};" << NL - << END << NL; + W << "if (!target_f_name_mixed.is_string()) " << BEGIN << R"(CurrentTlQuery::get().raise_storing_error("Field \"_\" of \")" << arg->name + << R"(\" array is not string");)" << NL << "return {};" << NL << END << NL; W << "string target_f_name = target_f_name_mixed.as_string();" << NL; W << fmt_format("if (!{}tl_storers_ht.has_key(target_f_name)) ", k2_tl_storers_prefix) << BEGIN - << "CurrentTlQuery::get().raise_storing_error(\"Function %s not found in tl-scheme\", target_f_name.c_str());" << NL - << "return {};" << NL - << END << NL; + << "CurrentTlQuery::get().raise_storing_error(\"Function %s not found in tl-scheme\", target_f_name.c_str());" << NL << "return {};" << NL << END << NL; W << fmt_format("const auto &storer_kv = {}tl_storers_ht.get_value(target_f_name);", k2_tl_storers_prefix) << NL; W << "tl_func_state->" << combinator->get_var_num_arg(as_type_var->var_num)->name << ".fetcher = storer_kv(_cur_arg);" << NL; } else { - W << "if (tl_object->$" << arg->name << ".is_null()) " << BEGIN - << R"(CurrentTlQuery::get().raise_storing_error("Field \")" << arg->name << R"(\" not found in tl object");)" << NL - << "return {};" << NL - << END << NL; - W << "tl_func_state->" << combinator->get_var_num_arg(as_type_var->var_num)->name << ".fetcher = " - << tl2cpp::get_tl_object_field_access(arg, tl2cpp::field_rw_type::READ) << ".get()->store();" << NL; + W << "if (tl_object->$" << arg->name << ".is_null()) " << BEGIN << R"(CurrentTlQuery::get().raise_storing_error("Field \")" << arg->name + << R"(\" not found in tl object");)" << NL << "return {};" << NL << END << NL; + W << "tl_func_state->" << combinator->get_var_num_arg(as_type_var->var_num)->name + << ".fetcher = " << tl2cpp::get_tl_object_field_access(arg, tl2cpp::field_rw_type::READ) << ".get()->store();" << NL; } } else if (arg->var_num != -1 && tl2cpp::type_of(arg->type_expr)->is_integer_variable()) { // save the field mask for the future use; // it can be either a local variable or a struct field if (!typed_mode) { - W << fmt_format("{}{} = tl_arr_get(tl_object, {}, {}, {}L).to_int();", - var_num_access, - combinator->get_var_num_arg(arg->var_num)->name, - tl2cpp::register_tl_const_str(arg->name), - arg->idx, - tl2cpp::hash_tl_const_str(arg->name)) << NL; + W << fmt_format("{}{} = tl_arr_get(tl_object, {}, {}, {}L).to_int();", var_num_access, combinator->get_var_num_arg(arg->var_num)->name, + tl2cpp::register_tl_const_str(arg->name), arg->idx, tl2cpp::hash_tl_const_str(arg->name)) + << NL; } else { W << var_num_access << combinator->get_var_num_arg(arg->var_num)->name << " = " << tl2cpp::get_tl_object_field_access(arg, tl2cpp::field_rw_type::READ) << ";" << NL; @@ -146,7 +135,7 @@ void CombinatorStore::gen_arg_processing(CodeGenerator &W, const std::unique_ptr } } -void CombinatorStore::gen_result_expr_processing(CodeGenerator &W) const { +void CombinatorStore::gen_result_expr_processing(CodeGenerator& W) const { kphp_assert(typed_mode); if (combinator->original_result_constructor_id) { W << fmt_format("f$store_int({:#010x});", combinator->original_result_constructor_id) << NL; @@ -158,12 +147,12 @@ void CombinatorStore::gen_result_expr_processing(CodeGenerator &W) const { W << tl2cpp::get_full_value(combinator->result.get(), var_num_access) << ".typed_store(tl_object->$value);" << NL; } -std::string CombinatorStore::get_value_absence_check_for_optional_arg(const std::unique_ptr &arg) { +std::string CombinatorStore::get_value_absence_check_for_optional_arg(const std::unique_ptr& arg) { kphp_assert(arg->is_fields_mask_optional()); if (arg->type_expr->as()) { return ""; } - auto *type = tl2cpp::type_of(arg->type_expr); + auto* type = tl2cpp::type_of(arg->type_expr); kphp_assert(type); std::string check_target = "tl_object->$" + arg->name; if (tl2cpp::is_tl_type_wrapped_to_Optional(type) || !tl2cpp::CUSTOM_IMPL_TYPES.count(type->name)) { @@ -176,17 +165,15 @@ std::string CombinatorStore::get_value_absence_check_for_optional_arg(const std: } } -void CombinatorFetch::gen_before_args_processing(CodeGenerator &W) const { +void CombinatorFetch::gen_before_args_processing(CodeGenerator& W) const { if (!typed_mode) { W << "array result;" << NL; } -}; +} -void CombinatorFetch::gen_arg_processing(CodeGenerator &W, const std::unique_ptr &arg) const { +void CombinatorFetch::gen_arg_processing(CodeGenerator& W, const std::unique_ptr& arg) const { if (arg->is_fields_mask_optional()) { - W << fmt_format("if ({}{} & (1 << {})) ", var_num_access, - combinator->get_var_num_arg(arg->exist_var_num)->name, - arg->exist_var_bit) << BEGIN; + W << fmt_format("if ({}{} & (1 << {})) ", var_num_access, combinator->get_var_num_arg(arg->exist_var_num)->name, arg->exist_var_bit) << BEGIN; } W << tl2cpp::TypeExprFetch(arg, var_num_access, typed_mode); if (arg->var_num != -1 && tl2cpp::type_of(arg->type_expr)->is_integer_variable()) { @@ -204,17 +191,17 @@ void CombinatorFetch::gen_arg_processing(CodeGenerator &W, const std::unique_ptr } } -void CombinatorFetch::gen_after_args_processing(CodeGenerator &W) const { +void CombinatorFetch::gen_after_args_processing(CodeGenerator& W) const { if (!typed_mode) { W << "return result;" << NL; } -}; +} -void CombinatorFetch::gen_result_expr_processing(CodeGenerator &W) const { +void CombinatorFetch::gen_result_expr_processing(CodeGenerator& W) const { // if function returns a flattable type, then after the perform_flat_optimization() it's contents are inlined; // although, during the function fetching we need a magic value of the original type (even if it was flattened). // To handle this, there is an original_result_constructor_id function field that stores a real type 'magic' if the type is flattened and 0 otherwise. - if (combinator->original_result_constructor_id) { + if (combinator->original_result_constructor_id) { W << fmt_format(R"(fetch_magic_if_not_bare({:#010x}, "Incorrect magic in result of function: {}");)", static_cast(combinator->original_result_constructor_id), tl2cpp::cur_combinator->name) << NL; @@ -228,15 +215,13 @@ void CombinatorFetch::gen_result_expr_processing(CodeGenerator &W) const { W << "return " << tl2cpp::get_full_value(combinator->result.get(), "") << ".fetch();" << NL; return; } - if (auto *type_var = combinator->result->as()) { + if (auto* type_var = combinator->result->as()) { // multiexclamation optimization W << "return " << tl2cpp::cur_combinator->get_var_num_arg(type_var->var_num)->name << ".fetcher->typed_fetch();" << NL; return; } // for every 'getChatInfo implements RpcFunction' there is a 'getChatInfo_result implements RpcFunctionReturnResult' - W << tl2cpp::get_php_runtime_type(combinator, true, combinator->name + "_result") << " result;" << NL - << "result.alloc();" << NL - << tl2cpp::get_full_value(combinator->result.get(), "") + ".typed_fetch_to(result->$value);" << NL - << "return result;" << NL; -} + W << tl2cpp::get_php_runtime_type(combinator, true, combinator->name + "_result") << " result;" << NL << "result.alloc();" << NL + << tl2cpp::get_full_value(combinator->result.get(), "") + ".typed_fetch_to(result->$value);" << NL << "return result;" << NL; } +} // namespace tl2cpp diff --git a/compiler/code-gen/files/tl2cpp/tl-combinator.h b/compiler/code-gen/files/tl2cpp/tl-combinator.h index bd9f3454d7..950a981603 100644 --- a/compiler/code-gen/files/tl2cpp/tl-combinator.h +++ b/compiler/code-gen/files/tl2cpp/tl-combinator.h @@ -7,32 +7,29 @@ #include "compiler/code-gen/files/tl2cpp/tl2cpp-utils.h" namespace tl2cpp { -enum class CombinatorPart { - LEFT, - RIGHT -}; +enum class CombinatorPart { LEFT, RIGHT }; -std::vector get_not_optional_fields_masks(const vk::tlo_parsing::combinator *constructor); +std::vector get_not_optional_fields_masks(const vk::tlo_parsing::combinator* constructor); struct CombinatorGen { - const vk::tlo_parsing::combinator *combinator; + const vk::tlo_parsing::combinator* combinator; CombinatorPart part; bool typed_mode; std::string var_num_access; - explicit CombinatorGen(const vk::tlo_parsing::combinator *combinator, CombinatorPart part, bool typed_mode); + explicit CombinatorGen(const vk::tlo_parsing::combinator* combinator, CombinatorPart part, bool typed_mode); - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; - void compile_left(CodeGenerator &W) const; + void compile_left(CodeGenerator& W) const; - void compile_right(CodeGenerator &W) const; + void compile_right(CodeGenerator& W) const; - virtual void gen_before_args_processing(CodeGenerator &W __attribute__ ((unused))) const {}; - virtual void gen_arg_processing(CodeGenerator &W, const std::unique_ptr &arg) const = 0; - virtual void gen_after_args_processing(CodeGenerator &W __attribute__ ((unused))) const {}; + virtual void gen_before_args_processing(CodeGenerator& W __attribute__((unused))) const {}; + virtual void gen_arg_processing(CodeGenerator& W, const std::unique_ptr& arg) const = 0; + virtual void gen_after_args_processing(CodeGenerator& W __attribute__((unused))) const {}; - virtual void gen_result_expr_processing(CodeGenerator &W) const = 0; + virtual void gen_result_expr_processing(CodeGenerator& W) const = 0; }; /* The code that is common for combinators (func/constructor) store method generation. @@ -69,17 +66,17 @@ struct CombinatorGen { * 3) Handling of the main part of the type expression in TypeExprStore/Fetch */ struct CombinatorStore : CombinatorGen { - CombinatorStore(const vk::tlo_parsing::combinator *combinator, CombinatorPart part, bool typed_mode) : - CombinatorGen(combinator, part, typed_mode) {}; + CombinatorStore(const vk::tlo_parsing::combinator* combinator, CombinatorPart part, bool typed_mode) + : CombinatorGen(combinator, part, typed_mode) {}; - void gen_before_args_processing(CodeGenerator &W) const final; + void gen_before_args_processing(CodeGenerator& W) const final; - void gen_arg_processing(CodeGenerator &W, const std::unique_ptr &arg) const final; + void gen_arg_processing(CodeGenerator& W, const std::unique_ptr& arg) const final; - void gen_result_expr_processing(CodeGenerator &W) const final; + void gen_result_expr_processing(CodeGenerator& W) const final; private: - static std::string get_value_absence_check_for_optional_arg(const std::unique_ptr &arg); + static std::string get_value_absence_check_for_optional_arg(const std::unique_ptr& arg); }; /* The code that is common for combinators (func/constructor) fetch method generation. @@ -99,20 +96,21 @@ struct CombinatorStore : CombinatorGen { * 2) Exclamation mark handling (! modifier): var f_rpcProxy_diagonalTargets::fetch() { fetch_magic_if_not_bare(0x1cb5c415, "Incorrect magic in result of function: rpcProxy.diagonalTargets"); - return t_Vector, 0>, 0>(t_Vector, 0>(t_Maybe(std::move(X)))).fetch(); + return t_Vector, 0>, 0>(t_Vector, + 0>(t_Maybe(std::move(X)))).fetch(); } * 3) Handling of the main part of the type expression in TypeExprStore/Fetch */ struct CombinatorFetch : CombinatorGen { - CombinatorFetch(const vk::tlo_parsing::combinator *combinator, CombinatorPart part, bool typed_mode) : - CombinatorGen(combinator, part, typed_mode) {}; + CombinatorFetch(const vk::tlo_parsing::combinator* combinator, CombinatorPart part, bool typed_mode) + : CombinatorGen(combinator, part, typed_mode) {}; - void gen_before_args_processing(CodeGenerator &W) const final; + void gen_before_args_processing(CodeGenerator& W) const final; - void gen_arg_processing(CodeGenerator &W, const std::unique_ptr &arg) const final; + void gen_arg_processing(CodeGenerator& W, const std::unique_ptr& arg) const final; - void gen_after_args_processing(CodeGenerator &W) const final; + void gen_after_args_processing(CodeGenerator& W) const final; - void gen_result_expr_processing(CodeGenerator &W) const final; + void gen_result_expr_processing(CodeGenerator& W) const final; }; -} +} // namespace tl2cpp diff --git a/compiler/code-gen/files/tl2cpp/tl-constructor.cpp b/compiler/code-gen/files/tl2cpp/tl-constructor.cpp index 1acc3788fb..5d72378d23 100644 --- a/compiler/code-gen/files/tl2cpp/tl-constructor.cpp +++ b/compiler/code-gen/files/tl2cpp/tl-constructor.cpp @@ -9,11 +9,11 @@ #include "compiler/code-gen/naming.h" namespace tl2cpp { -const vk::tlo_parsing::combinator *constructor; +const vk::tlo_parsing::combinator* constructor; -std::string TlConstructorDecl::get_optional_args_for_decl(const vk::tlo_parsing::combinator *c) { +std::string TlConstructorDecl::get_optional_args_for_decl(const vk::tlo_parsing::combinator* c) { std::vector res; - for (const auto &arg : c->args) { + for (const auto& arg : c->args) { if (arg->is_optional()) { if (type_of(arg->type_expr)->is_integer_variable()) { res.emplace_back("int64_t " + arg->name); @@ -25,7 +25,7 @@ std::string TlConstructorDecl::get_optional_args_for_decl(const vk::tlo_parsing: return vk::join(res, ", "); } -void TlConstructorDecl::compile(CodeGenerator &W) const { +void TlConstructorDecl::compile(CodeGenerator& W) const { const bool needs_typed_fetch_store = TlConstructorDecl::does_tl_constructor_need_typed_fetch_store(constructor); if (needs_typed_fetch_store && is_type_dependent(constructor, tl)) { @@ -45,13 +45,15 @@ void TlConstructorDecl::compile(CodeGenerator &W) const { if (needs_typed_fetch_store) { std::string php_type = get_php_runtime_type(constructor, false); - FunctionSignatureGenerator(W) << "static void typed_store(const " << php_type << " *tl_object" << (!params.empty() ? ", " + params : "") << ")" << SemicolonAndNL(); - FunctionSignatureGenerator(W) << "static void typed_fetch_to(" << php_type << " *tl_object" << (!params.empty() ? ", " + params : "") << ")" << SemicolonAndNL(); + FunctionSignatureGenerator(W) << "static void typed_store(const " << php_type << " *tl_object" << (!params.empty() ? ", " + params : "") << ")" + << SemicolonAndNL(); + FunctionSignatureGenerator(W) << "static void typed_fetch_to(" << php_type << " *tl_object" << (!params.empty() ? ", " + params : "") << ")" + << SemicolonAndNL(); } W << END << ";\n\n"; } -void TlConstructorDef::compile(CodeGenerator &W) const { +void TlConstructorDef::compile(CodeGenerator& W) const { const bool needs_typed_fetch_store = TlConstructorDecl::does_tl_constructor_need_typed_fetch_store(constructor); std::string template_decl = get_template_declaration(constructor); @@ -74,14 +76,16 @@ void TlConstructorDef::compile(CodeGenerator &W) const { if (needs_typed_fetch_store) { std::string php_type = get_php_runtime_type(constructor, false); W << template_decl << NL; - FunctionSignatureGenerator(W) << "void " << full_struct_name + "::typed_store(const " << php_type << " *tl_object" << (!params.empty() ? ", " + params : "") << ") " << BEGIN; + FunctionSignatureGenerator(W) << "void " << full_struct_name + "::typed_store(const " << php_type << " *tl_object" << (!params.empty() ? ", " + params : "") + << ") " << BEGIN; W << CombinatorStore(constructor, CombinatorPart::LEFT, true); W << END << "\n\n"; W << template_decl << NL; - FunctionSignatureGenerator(W) << "void " << full_struct_name << "::typed_fetch_to(" << php_type << " *tl_object" << (!params.empty() ? ", " + params : "") << ") " << BEGIN; + FunctionSignatureGenerator(W) << "void " << full_struct_name << "::typed_fetch_to(" << php_type << " *tl_object" << (!params.empty() ? ", " + params : "") + << ") " << BEGIN; W << CombinatorFetch(constructor, CombinatorPart::LEFT, true); W << END << "\n\n"; } } -} +} // namespace tl2cpp diff --git a/compiler/code-gen/files/tl2cpp/tl-constructor.h b/compiler/code-gen/files/tl2cpp/tl-constructor.h index 72ed91163b..5acb931ebb 100644 --- a/compiler/code-gen/files/tl2cpp/tl-constructor.h +++ b/compiler/code-gen/files/tl2cpp/tl-constructor.h @@ -8,26 +8,26 @@ namespace tl2cpp { struct TlConstructorDecl { - const vk::tlo_parsing::combinator *constructor; + const vk::tlo_parsing::combinator* constructor; - explicit TlConstructorDecl(const vk::tlo_parsing::combinator *constructor) : - constructor(constructor) {}; + explicit TlConstructorDecl(const vk::tlo_parsing::combinator* constructor) + : constructor(constructor) {}; - static bool does_tl_constructor_need_typed_fetch_store(const vk::tlo_parsing::combinator *c) { + static bool does_tl_constructor_need_typed_fetch_store(const vk::tlo_parsing::combinator* c) { return !get_all_php_classes_of_tl_constructor(c).empty(); } - static std::string get_optional_args_for_decl(const vk::tlo_parsing::combinator *c); + static std::string get_optional_args_for_decl(const vk::tlo_parsing::combinator* c); - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; struct TlConstructorDef { - const vk::tlo_parsing::combinator *constructor; + const vk::tlo_parsing::combinator* constructor; - explicit TlConstructorDef(const vk::tlo_parsing::combinator *constructor) : - constructor(constructor) {}; + explicit TlConstructorDef(const vk::tlo_parsing::combinator* constructor) + : constructor(constructor) {}; - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; -} +} // namespace tl2cpp diff --git a/compiler/code-gen/files/tl2cpp/tl-function.cpp b/compiler/code-gen/files/tl2cpp/tl-function.cpp index 6e8bcd444a..f09243c949 100644 --- a/compiler/code-gen/files/tl2cpp/tl-function.cpp +++ b/compiler/code-gen/files/tl2cpp/tl-function.cpp @@ -8,13 +8,13 @@ #include "compiler/code-gen/naming.h" namespace tl2cpp { -void TlFunctionDecl::compile(CodeGenerator &W) const { +void TlFunctionDecl::compile(CodeGenerator& W) const { W << "/* ~~~~~~~~~ " << f->name << " ~~~~~~~~~ */\n" << NL; const bool needs_typed_fetch_store = TlFunctionDecl::does_tl_function_need_typed_fetch_store(f); std::string struct_name = cpp_tl_struct_name("f_", f->name); W << "struct " + struct_name + " : tl_func_base " << BEGIN; - for (const auto &arg : f->args) { + for (const auto& arg : f->args) { if (arg->is_optional()) { W << "tl_exclamation_fetch_wrapper " << arg->name << ";" << NL; } else if (arg->var_num != -1) { @@ -29,7 +29,8 @@ void TlFunctionDecl::compile(CodeGenerator &W) const { } if (needs_typed_fetch_store) { FunctionSignatureGenerator(W) << "static std::unique_ptr typed_store(const " << get_php_runtime_type(f) << " *tl_object)" << SemicolonAndNL(); - FunctionSignatureGenerator(W) << "class_instance<" << G->settings().tl_classname_prefix.get() << "RpcFunctionReturnResult> typed_fetch()" << SemicolonAndNL(); + FunctionSignatureGenerator(W) << "class_instance<" << G->settings().tl_classname_prefix.get() << "RpcFunctionReturnResult> typed_fetch()" + << SemicolonAndNL(); } if (f->is_kphp_rpc_server_function() && needs_typed_fetch_store) { check_kphp_function(f); @@ -41,7 +42,7 @@ void TlFunctionDecl::compile(CodeGenerator &W) const { W << END << ";" << NL << NL; } -void TlFunctionDef::compile(CodeGenerator &W) const { +void TlFunctionDef::compile(CodeGenerator& W) const { const bool needs_typed_fetch_store = TlFunctionDecl::does_tl_function_need_typed_fetch_store(f); std::string struct_name = cpp_tl_struct_name("f_", f->name); @@ -57,18 +58,21 @@ void TlFunctionDef::compile(CodeGenerator &W) const { W << END << NL << NL; } if (needs_typed_fetch_store) { - FunctionSignatureGenerator(W) << "std::unique_ptr " << struct_name << "::typed_store(const " << get_php_runtime_type(f) << " *tl_object) " << BEGIN; + FunctionSignatureGenerator(W) << "std::unique_ptr " << struct_name << "::typed_store(const " << get_php_runtime_type(f) << " *tl_object) " + << BEGIN; W << "auto tl_func_state = make_unique_on_script_memory<" << struct_name << ">();" << NL; W << CombinatorStore(f, CombinatorPart::LEFT, true); W << "return std::move(tl_func_state);" << NL; W << END << NL << NL; - FunctionSignatureGenerator(W) << "class_instance<" << G->settings().tl_classname_prefix.get() << "RpcFunctionReturnResult> " << struct_name << "::typed_fetch() " << BEGIN; + FunctionSignatureGenerator(W) << "class_instance<" << G->settings().tl_classname_prefix.get() << "RpcFunctionReturnResult> " << struct_name + << "::typed_fetch() " << BEGIN; W << CombinatorFetch(f, CombinatorPart::RIGHT, true); W << END << NL << NL; } if (f->is_kphp_rpc_server_function() && needs_typed_fetch_store) { - FunctionSignatureGenerator(W) << "std::unique_ptr " << struct_name << "::rpc_server_typed_fetch(" << get_php_runtime_type(f) << " *tl_object) " << BEGIN; + FunctionSignatureGenerator(W) << "std::unique_ptr " << struct_name << "::rpc_server_typed_fetch(" << get_php_runtime_type(f) + << " *tl_object) " << BEGIN; W << "CurrentTlQuery::get().set_current_tl_function(" << register_tl_const_str(f->name) << ");" << NL; W << "auto tl_func_state = make_unique_on_script_memory<" << struct_name << ">();" << NL; W << CombinatorFetch(f, CombinatorPart::LEFT, true); @@ -84,4 +88,4 @@ void TlFunctionDef::compile(CodeGenerator &W) const { W << END << NL << NL; } } -} +} // namespace tl2cpp diff --git a/compiler/code-gen/files/tl2cpp/tl-function.h b/compiler/code-gen/files/tl2cpp/tl-function.h index f1415043ea..1a6dcb3076 100644 --- a/compiler/code-gen/files/tl2cpp/tl-function.h +++ b/compiler/code-gen/files/tl2cpp/tl-function.h @@ -7,31 +7,31 @@ namespace tl2cpp { struct TlFunctionDecl { - const vk::tlo_parsing::combinator *f; + const vk::tlo_parsing::combinator* f; - explicit TlFunctionDecl(const vk::tlo_parsing::combinator *f) : - f(f) {} + explicit TlFunctionDecl(const vk::tlo_parsing::combinator* f) + : f(f) {} - static bool does_tl_function_need_typed_fetch_store(const vk::tlo_parsing::combinator *f) { + static bool does_tl_function_need_typed_fetch_store(const vk::tlo_parsing::combinator* f) { return !!get_php_class_of_tl_function(f); } - static void check_kphp_function(const vk::tlo_parsing::combinator *f) { - for (const auto &arg : f->args) { + static void check_kphp_function(const vk::tlo_parsing::combinator* f) { + for (const auto& arg : f->args) { kphp_error(!arg->is_forwarded_function(), fmt_format("In TL function {}: Exclamation is not allowed in @kphp TL functions", f->name)); } } - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; class TlFunctionDef { - const vk::tlo_parsing::combinator *f; + const vk::tlo_parsing::combinator* f; public: - explicit TlFunctionDef(const vk::tlo_parsing::combinator *f) : - f(f) {} + explicit TlFunctionDef(const vk::tlo_parsing::combinator* f) + : f(f) {} - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; -} +} // namespace tl2cpp diff --git a/compiler/code-gen/files/tl2cpp/tl-module.cpp b/compiler/code-gen/files/tl2cpp/tl-module.cpp index d847ad31a2..e8276a8abc 100644 --- a/compiler/code-gen/files/tl2cpp/tl-module.cpp +++ b/compiler/code-gen/files/tl2cpp/tl-module.cpp @@ -12,57 +12,57 @@ namespace tl2cpp { std::unordered_map modules; std::set modules_with_functions; -void Module::compile_tl_h_file(CodeGenerator &W) const { +void Module::compile_tl_h_file(CodeGenerator& W) const { W << OpenFile(name + ".h", "tl"); W << "#pragma once" << NL; W << ExternInclude("tl/tl_const_vars.h"); W << h_includes; W << NL; - for (const auto &t : target_types) { - for (const auto &constructor : t->constructors) { + for (const auto& t : target_types) { + for (const auto& constructor : t->constructors) { W << TlConstructorDecl(constructor.get()); } } - for (const auto &t : target_types) { + for (const auto& t : target_types) { W << TlTypeDeclaration(t); if (is_type_dependent(t, tl)) { W << TlTypeDefinition(t); } } - for (const auto &t : target_types) { + for (const auto& t : target_types) { if (is_type_dependent(t, tl)) { - for (const auto &constructor : t->constructors) { + for (const auto& constructor : t->constructors) { W << TlConstructorDef(constructor.get()); } } } - for (const auto &f : target_functions) { + for (const auto& f : target_functions) { W << TlFunctionDecl(f); } W << CloseFile(); } -void Module::compile_tl_cpp_file(CodeGenerator &W) const { +void Module::compile_tl_cpp_file(CodeGenerator& W) const { W << OpenFile(name + ".cpp", "tl", false); W << ExternInclude(G->settings().runtime_headers.get()); W << Include("tl/" + name + ".h") << NL; W << cpp_includes; - for (const auto &t : target_types) { + for (const auto& t : target_types) { if (!is_type_dependent(t, tl)) { W << TlTypeDefinition(t); - for (const auto &constructor : t->constructors) { + for (const auto& constructor : t->constructors) { W << TlConstructorDef(constructor.get()); } } } - for (const auto &f: target_functions) { + for (const auto& f : target_functions) { W << TlFunctionDef(f); } W << CloseFile(); } -void Module::add_obj(const std::unique_ptr &f) { +void Module::add_obj(const std::unique_ptr& f) { modules_with_functions.insert(name); target_functions.push_back(f.get()); update_dependencies(f); @@ -78,11 +78,11 @@ void Module::add_obj(const std::unique_ptr &f) { } } -void Module::add_obj(const std::unique_ptr &t) { +void Module::add_obj(const std::unique_ptr& t) { target_types.push_back(t.get()); update_dependencies(t); - for (const auto &c : t->constructors) { + for (const auto& c : t->constructors) { if (TlConstructorDecl::does_tl_constructor_need_typed_fetch_store(c.get())) { auto php_classes = get_all_php_classes_of_tl_constructor(c.get()); std::for_each(php_classes.begin(), php_classes.end(), [&](ClassPtr klass) { h_includes.add_class_include(klass); }); @@ -90,8 +90,8 @@ void Module::add_obj(const std::unique_ptr &t) { } } -void Module::update_dependencies(const std::unique_ptr &combinator) { - for (const auto &arg : combinator->args) { +void Module::update_dependencies(const std::unique_ptr& combinator) { + for (const auto& arg : combinator->args) { collect_deps_from_type_tree(arg->type_expr.get()); } if (combinator->is_function()) { @@ -99,23 +99,23 @@ void Module::update_dependencies(const std::unique_ptr &t) { - for (const auto &c : t->constructors) { +void Module::update_dependencies(const std::unique_ptr& t) { + for (const auto& c : t->constructors) { update_dependencies(c); } } -void Module::collect_deps_from_type_tree(vk::tlo_parsing::expr_base *expr) { - if (auto *as_type_expr = expr->as()) { +void Module::collect_deps_from_type_tree(vk::tlo_parsing::expr_base* expr) { + if (auto* as_type_expr = expr->as()) { std::string expr_module = get_module_name(tl->types[as_type_expr->type_id]->name); if (name != expr_module) { h_includes.add_raw_filename_include("tl/" + expr_module + ".h"); } - for (const auto &child : as_type_expr->children) { + for (const auto& child : as_type_expr->children) { collect_deps_from_type_tree(child.get()); } - } else if (auto *as_type_array = expr->as()) { - for (const auto &arg : as_type_array->args) { + } else if (auto* as_type_array = expr->as()) { + for (const auto& arg : as_type_array->args) { collect_deps_from_type_tree(arg->type_expr.get()); } } @@ -125,13 +125,9 @@ bool Module::is_empty() const { if (G->get_untyped_rpc_tl_used()) { return false; } - return - std::all_of(target_functions.begin(), target_functions.end(), [](const auto *f) { - return !TlFunctionDecl::does_tl_function_need_typed_fetch_store(f); - }) && - std::all_of(target_types.begin(), target_types.end(), [](const auto *t) { - return !TlTypeDeclaration::does_tl_type_need_typed_fetch_store(t); - }); + return std::all_of(target_functions.begin(), target_functions.end(), + [](const auto* f) { return !TlFunctionDecl::does_tl_function_need_typed_fetch_store(f); }) && + std::all_of(target_types.begin(), target_types.end(), [](const auto* t) { return !TlTypeDeclaration::does_tl_type_need_typed_fetch_store(t); }); } -} +} // namespace tl2cpp diff --git a/compiler/code-gen/files/tl2cpp/tl-module.h b/compiler/code-gen/files/tl2cpp/tl-module.h index 8ef4e6d759..eed2390050 100644 --- a/compiler/code-gen/files/tl2cpp/tl-module.h +++ b/compiler/code-gen/files/tl2cpp/tl-module.h @@ -19,60 +19,60 @@ extern std::set modules_with_functions; // A module is a two (.cpp+.h) files that correspond to one TL scheme module. class Module { public: - std::vector target_types; - std::vector target_functions; + std::vector target_types; + std::vector target_functions; IncludesCollector h_includes; IncludesCollector cpp_includes; std::string name; Module() = default; - explicit Module(std::string name) : - name(std::move(name)) {} + explicit Module(std::string name) + : name(std::move(name)) {} - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { compile_tl_h_file(W); if (!is_empty()) { compile_tl_cpp_file(W); } } - void compile_tl_h_file(CodeGenerator &W) const; + void compile_tl_h_file(CodeGenerator& W) const; - void compile_tl_cpp_file(CodeGenerator &W) const; + void compile_tl_cpp_file(CodeGenerator& W) const; - void add_obj(const std::unique_ptr &f); + void add_obj(const std::unique_ptr& f); - void add_obj(const std::unique_ptr &t); + void add_obj(const std::unique_ptr& t); - static std::string get_module_name(const std::string &type_or_comb_name) { + static std::string get_module_name(const std::string& type_or_comb_name) { auto pos = type_or_comb_name.find('.'); return pos == std::string::npos ? "common" : type_or_comb_name.substr(0, pos); } - static void add_to_module(const std::unique_ptr &t) { + static void add_to_module(const std::unique_ptr& t) { ensure_existence(get_module_name(t->name)).add_obj(t); } - static void add_to_module(const std::unique_ptr &c) { + static void add_to_module(const std::unique_ptr& c) { ensure_existence(get_module_name(c->name)).add_obj(c); } bool is_empty() const; private: - static Module &ensure_existence(const std::string &module_name) { + static Module& ensure_existence(const std::string& module_name) { if (modules.find(module_name) == modules.end()) { modules[module_name] = Module(module_name); } return modules[module_name]; } - void update_dependencies(const std::unique_ptr &combinator); + void update_dependencies(const std::unique_ptr& combinator); - void update_dependencies(const std::unique_ptr &t); + void update_dependencies(const std::unique_ptr& t); - void collect_deps_from_type_tree(vk::tlo_parsing::expr_base *expr); + void collect_deps_from_type_tree(vk::tlo_parsing::expr_base* expr); }; -} +} // namespace tl2cpp diff --git a/compiler/code-gen/files/tl2cpp/tl-template-php-type-helpers.h b/compiler/code-gen/files/tl2cpp/tl-template-php-type-helpers.h index ede321785c..89e8f1d7c5 100644 --- a/compiler/code-gen/files/tl2cpp/tl-template-php-type-helpers.h +++ b/compiler/code-gen/files/tl2cpp/tl-template-php-type-helpers.h @@ -7,32 +7,30 @@ namespace tl2cpp { struct TlTemplatePhpTypeHelpers { - explicit TlTemplatePhpTypeHelpers(const vk::tlo_parsing::type *type) : - type(get_this_from_renamed_tl_scheme(type)), - constructor(nullptr) {} + explicit TlTemplatePhpTypeHelpers(const vk::tlo_parsing::type* type) + : type(get_this_from_renamed_tl_scheme(type)), + constructor(nullptr) {} - explicit TlTemplatePhpTypeHelpers(const vk::tlo_parsing::combinator *constructor) : - type(nullptr), - constructor(get_this_from_renamed_tl_scheme(constructor)) {} + explicit TlTemplatePhpTypeHelpers(const vk::tlo_parsing::combinator* constructor) + : type(nullptr), + constructor(get_this_from_renamed_tl_scheme(constructor)) {} - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { size_t cnt = 0; std::vector type_var_names; - const vk::tlo_parsing::combinator *target_constructor = type ? type->constructors[0].get() : constructor; - for (const auto &arg : target_constructor->args) { + const vk::tlo_parsing::combinator* target_constructor = type ? type->constructors[0].get() : constructor; + for (const auto& arg : target_constructor->args) { if (arg->is_type()) { ++cnt; type_var_names.emplace_back(arg->name); } } - const std::string &struct_name = cpp_tl_struct_name("", type ? type->name : constructor->name, "__"); + const std::string& struct_name = cpp_tl_struct_name("", type ? type->name : constructor->name, "__"); W << "template <" << vk::join(std::vector(cnt, "typename"), ", ") << ">" << NL; - W << "struct " << struct_name << " " << BEGIN - << "using type = tl_undefined_php_type;" << NL - << END << ";" << NL << NL; + W << "struct " << struct_name << " " << BEGIN << "using type = tl_undefined_php_type;" << NL << END << ";" << NL << NL; auto php_classes = type ? get_all_php_classes_of_tl_type(type) : get_all_php_classes_of_tl_constructor(constructor); - for (const auto &cur_php_class_template_instantiation : php_classes) { - const std::string &cur_instantiation_name = cur_php_class_template_instantiation->src_name; + for (const auto& cur_php_class_template_instantiation : php_classes) { + const std::string& cur_instantiation_name = cur_php_class_template_instantiation->src_name; std::vector template_specialization_params = type_var_names; std::string type_var_access; if (type) { @@ -50,15 +48,16 @@ struct TlTemplatePhpTypeHelpers { } } std::transform(template_specialization_params.begin(), template_specialization_params.end(), template_specialization_params.begin(), - [&](const std::string &s) { return type_var_access + "::" += s; }); + [&](const std::string& s) { return type_var_access + "::" += s; }); W << "template <>" << NL; W << "struct " << struct_name << "<" << vk::join(template_specialization_params, ", ") << "> " << BEGIN; W << "using type = " << cur_instantiation_name << ";" << NL; W << END << ";" << NL << NL; } } + private: - const vk::tlo_parsing::type *type; - const vk::tlo_parsing::combinator *constructor; + const vk::tlo_parsing::type* type; + const vk::tlo_parsing::combinator* constructor; }; -} +} // namespace tl2cpp diff --git a/compiler/code-gen/files/tl2cpp/tl-type-expr.cpp b/compiler/code-gen/files/tl2cpp/tl-type-expr.cpp index dc97c7289c..dbd8d1104b 100644 --- a/compiler/code-gen/files/tl2cpp/tl-type-expr.cpp +++ b/compiler/code-gen/files/tl2cpp/tl-type-expr.cpp @@ -8,14 +8,14 @@ namespace tl2cpp { // Recursively traverse the type expression tree and return pair -std::pair get_full_type_expr_str(vk::tlo_parsing::expr_base *type_expr, const std::string &var_num_access) { - if (auto *as_nat_var = type_expr->as()) { +std::pair get_full_type_expr_str(vk::tlo_parsing::expr_base* type_expr, const std::string& var_num_access) { + if (auto* as_nat_var = type_expr->as()) { return {"", var_num_access + cur_combinator->get_var_num_arg(as_nat_var->var_num)->name}; } - if (auto *as_nat_const = type_expr->as()) { + if (auto* as_nat_const = type_expr->as()) { return {"", std::to_string(as_nat_const->num)}; } - if (auto *as_type_var = type_expr->as()) { + if (auto* as_type_var = type_expr->as()) { std::string expr = "std::move(" + cur_combinator->get_var_num_arg(as_type_var->var_num)->name + ")"; if (cur_combinator->is_constructor()) { return {"T" + std::to_string(as_type_var->var_num), expr}; @@ -23,13 +23,13 @@ std::pair get_full_type_expr_str(vk::tlo_parsing::expr return {"tl_exclamation_fetch_wrapper", expr}; } } - if (auto *as_type_array = type_expr->as()) { + if (auto* as_type_array = type_expr->as()) { std::string inner_magic = "0"; // after the replace_anonymous_args TL array that had multiple items now has only one item // that became a named type that contains all data from the original item; // size*[A B] -> size*[T] where T has A and B as its fields kphp_assert(as_type_array->args.size() == 1); - if (auto *casted = as_type_array->args[0]->type_expr->as()) { + if (auto* casted = as_type_array->args[0]->type_expr->as()) { if (is_magic_processing_needed(casted)) { inner_magic = fmt_format("{:#010x}", static_cast(type_of(casted)->id)); } @@ -38,16 +38,14 @@ std::pair get_full_type_expr_str(vk::tlo_parsing::expr } std::string array_item_type_name = cpp_tl_struct_name("t_", type_of(as_type_array->args[0]->type_expr)->name); std::string type = fmt_format("tl_array<{}, {}>", array_item_type_name, inner_magic); - return {type, type + fmt_format("({}, {}())", - get_full_value(as_type_array->multiplicity.get(), var_num_access), - array_item_type_name)}; + return {type, type + fmt_format("({}, {}())", get_full_value(as_type_array->multiplicity.get(), var_num_access), array_item_type_name)}; } - auto *as_type_expr = type_expr->as(); + auto* as_type_expr = type_expr->as(); kphp_assert(as_type_expr); - const auto &type = tl->types[as_type_expr->type_id]; + const auto& type = tl->types[as_type_expr->type_id]; std::vector template_params; std::vector constructor_params; - for (const auto &child : as_type_expr->children) { + for (const auto& child : as_type_expr->children) { auto child_type_str = get_full_type_expr_str(child.get(), var_num_access); std::string child_type_name = child_type_str.first; std::string child_type_value = child_type_str.second; @@ -55,13 +53,13 @@ std::pair get_full_type_expr_str(vk::tlo_parsing::expr if (!child_type_name.empty()) { kphp_assert(child->as()); template_params.emplace_back(child_type_name); - if (auto *child_as_type_expr = child->as()) { + if (auto* child_as_type_expr = child->as()) { if (is_magic_processing_needed(child_as_type_expr)) { template_params.emplace_back(fmt_format("{:#010x}", static_cast(type_of(child_as_type_expr)->id))); } else { template_params.emplace_back("0"); } - } else if (auto *child_as_type_var = child->as()) { + } else if (auto* child_as_type_var = child->as()) { if (vk::string_view(child_type_name).starts_with("T")) { template_params.emplace_back(fmt_format("inner_magic{}", child_as_type_var->var_num)); } else { @@ -80,7 +78,7 @@ std::pair get_full_type_expr_str(vk::tlo_parsing::expr return {full_type_name, full_type_value}; } -void TypeExprStore::compile(CodeGenerator &W) const { +void TypeExprStore::compile(CodeGenerator& W) const { std::string magic_storing = get_magic_storing(arg->type_expr.get()); if (!magic_storing.empty()) { W << magic_storing << NL; @@ -94,18 +92,17 @@ void TypeExprStore::compile(CodeGenerator &W) const { W << ";" << NL; } -void TypeExprFetch::compile(CodeGenerator &W) const { - const auto magic_fetching = get_magic_fetching(arg->type_expr.get(), - fmt_format("Incorrect magic of arg: {}\\nin constructor: {}", arg->name, cur_combinator->name)); +void TypeExprFetch::compile(CodeGenerator& W) const { + const auto magic_fetching = + get_magic_fetching(arg->type_expr.get(), fmt_format("Incorrect magic of arg: {}\\nin constructor: {}", arg->name, cur_combinator->name)); if (!magic_fetching.empty()) { W << magic_fetching << NL; } if (!typed_mode) { - W << "result.set_value(" << register_tl_const_str(arg->name) << ", " - << get_full_value(arg->type_expr.get(), var_num_access) << ".fetch(), " + W << "result.set_value(" << register_tl_const_str(arg->name) << ", " << get_full_value(arg->type_expr.get(), var_num_access) << ".fetch(), " << hash_tl_const_str(arg->name) << "L);" << NL; } else { W << get_full_value(arg->type_expr.get(), var_num_access) + ".typed_fetch_to(" << get_tl_object_field_access(arg, field_rw_type::WRITE) << ");" << NL; } } -} +} // namespace tl2cpp diff --git a/compiler/code-gen/files/tl2cpp/tl-type-expr.h b/compiler/code-gen/files/tl2cpp/tl-type-expr.h index b72ca15153..a821cd22c0 100644 --- a/compiler/code-gen/files/tl2cpp/tl-type-expr.h +++ b/compiler/code-gen/files/tl2cpp/tl-type-expr.h @@ -8,44 +8,43 @@ namespace tl2cpp { -std::pair get_full_type_expr_str(vk::tlo_parsing::expr_base *type_expr, const std::string &var_num_access); +std::pair get_full_type_expr_str(vk::tlo_parsing::expr_base* type_expr, const std::string& var_num_access); -inline std::string get_full_value(vk::tlo_parsing::expr_base *type_expr, const std::string &var_num_access) { +inline std::string get_full_value(vk::tlo_parsing::expr_base* type_expr, const std::string& var_num_access) { auto ans = get_full_type_expr_str(type_expr, var_num_access); return ans.second; } -inline std::string get_full_type(vk::tlo_parsing::expr_base *type_expr, const std::string &var_num_access) { +inline std::string get_full_type(vk::tlo_parsing::expr_base* type_expr, const std::string& var_num_access) { auto ans = get_full_type_expr_str(type_expr, var_num_access); return ans.first; } // Structure for any type expression store generation struct TypeExprStore { - const std::unique_ptr &arg; + const std::unique_ptr& arg; std::string var_num_access; bool typed_mode; - TypeExprStore(const std::unique_ptr &arg, std::string var_num_access, bool typed_mode = false) : - arg(arg), - var_num_access(std::move(var_num_access)), - typed_mode(typed_mode) {} + TypeExprStore(const std::unique_ptr& arg, std::string var_num_access, bool typed_mode = false) + : arg(arg), + var_num_access(std::move(var_num_access)), + typed_mode(typed_mode) {} - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; - // Structure for any type expression fetch generation struct TypeExprFetch { - const std::unique_ptr &arg; + const std::unique_ptr& arg; std::string var_num_access; bool typed_mode; - explicit inline TypeExprFetch(const std::unique_ptr &arg, std::string var_num_access, bool typed_mode = false) : - arg(arg), - var_num_access(std::move(var_num_access)), - typed_mode(typed_mode) {} + explicit inline TypeExprFetch(const std::unique_ptr& arg, std::string var_num_access, bool typed_mode = false) + : arg(arg), + var_num_access(std::move(var_num_access)), + typed_mode(typed_mode) {} - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; -} +} // namespace tl2cpp diff --git a/compiler/code-gen/files/tl2cpp/tl-type.cpp b/compiler/code-gen/files/tl2cpp/tl-type.cpp index 4ac6dfde75..03e13c1b60 100644 --- a/compiler/code-gen/files/tl2cpp/tl-type.cpp +++ b/compiler/code-gen/files/tl2cpp/tl-type.cpp @@ -11,18 +11,15 @@ namespace tl2cpp { using vk::tlo_parsing::FLAG_DEFAULT_CONSTRUCTOR; using vk::tlo_parsing::FLAG_NOCONS; -void TypeStore::compile(CodeGenerator &W) const { +void TypeStore::compile(CodeGenerator& W) const { // todo: CHECK_EXCEPTION(return); ??? Should we interrupt storing if the exception was thrown? (Right now it's inconsistent with fetching) auto store_params = get_optional_args_for_call(type->constructors[0]); - store_params.insert(store_params.begin(), - typed_mode ? (type->is_polymorphic() ? "conv_obj" : "tl_object.get()") : "tl_object"); + store_params.insert(store_params.begin(), typed_mode ? (type->is_polymorphic() ? "conv_obj" : "tl_object.get()") : "tl_object"); std::string store_call = (typed_mode ? "typed_store(" : "store(") + vk::join(store_params, ", ") + ");"; if (typed_mode) { - W << "if (tl_object.is_null()) " << BEGIN - << "CurrentTlQuery::get().raise_storing_error(\"Instance expected, but false given while storing tl type\");" << NL - << "return;" << NL - << END << NL; + W << "if (tl_object.is_null()) " << BEGIN << "CurrentTlQuery::get().raise_storing_error(\"Instance expected, but false given while storing tl type\");" + << NL << "return;" << NL << END << NL; } // non-polymorphic types — 1 constructor — forwards a ::store() into the constructor without 'magic' if (!type->is_polymorphic()) { @@ -30,12 +27,12 @@ void TypeStore::compile(CodeGenerator &W) const { return; } - auto *default_constructor = (type->flags & FLAG_DEFAULT_CONSTRUCTOR ? type->constructors.back().get() : nullptr); + auto* default_constructor = (type->flags & FLAG_DEFAULT_CONSTRUCTOR ? type->constructors.back().get() : nullptr); // for polymorphic types: // typed TL: ifs with dynamic_cast, similar to the interface methods if (typed_mode) { bool first = true; - for (const auto &c : type->constructors) { + for (const auto& c : type->constructors) { W << (first ? "if " : " else if "); first = false; @@ -47,17 +44,14 @@ void TypeStore::compile(CodeGenerator &W) const { W << "const " << cpp_class << " *conv_obj = tl_object.template cast_to<" << cpp_class << ">().get();" << NL; W << cpp_tl_struct_name("c_", c->name, template_str) << "::" << store_call << NL << END; } - W << (first ? "" : " else ") << BEGIN - << "CurrentTlQuery::get().raise_storing_error(\"Invalid constructor %s of type %s\", " - << "tl_object.get_class(), \"" << type->name << "\");" << NL - << END << NL; + W << (first ? "" : " else ") << BEGIN << "CurrentTlQuery::get().raise_storing_error(\"Invalid constructor %s of type %s\", " + << "tl_object.get_class(), \"" << type->name << "\");" << NL << END << NL; // untyped TL: ifs with constructor_name checks } else { bool first = true; - W << "const string &c_name = tl_arr_get(tl_object, " - << register_tl_const_str("_") << ", 0, " << hash_tl_const_str("_") << "L).to_string();" << NL; - for (const auto &c : type->constructors) { + W << "const string &c_name = tl_arr_get(tl_object, " << register_tl_const_str("_") << ", 0, " << hash_tl_const_str("_") << "L).to_string();" << NL; + for (const auto& c : type->constructors) { W << (first ? "if " : " else if "); first = false; @@ -67,14 +61,12 @@ void TypeStore::compile(CodeGenerator &W) const { } W << cpp_tl_struct_name("c_", c->name, template_str) << "::" << store_call << NL << END; } - W << (first ? "" : " else ") << BEGIN - << "CurrentTlQuery::get().raise_storing_error(\"Invalid constructor %s of type %s\", " - << "c_name.c_str(), \"" << type->name << "\");" << NL - << END << NL; + W << (first ? "" : " else ") << BEGIN << "CurrentTlQuery::get().raise_storing_error(\"Invalid constructor %s of type %s\", " + << "c_name.c_str(), \"" << type->name << "\");" << NL << END << NL; } } -void TypeFetch::compile(CodeGenerator &W) const { +void TypeFetch::compile(CodeGenerator& W) const { auto fetch_params = get_optional_args_for_call(type->constructors[0]); std::string fetch_call; if (!typed_mode) { @@ -86,7 +78,7 @@ void TypeFetch::compile(CodeGenerator &W) const { // non-polymorphic types are fetched in a trivial way - their fetch is delegated to the constructor if (!type->is_polymorphic()) { - const auto &constructor = type->constructors.front(); + const auto& constructor = type->constructors.front(); if (typed_mode) { W << "CHECK_EXCEPTION(return);" << NL; W << get_php_runtime_type(constructor.get(), true) << " result;" << NL; @@ -107,14 +99,14 @@ void TypeFetch::compile(CodeGenerator &W) const { W << "array result;" << NL; } W << "CHECK_EXCEPTION(return" << (typed_mode ? "" : " result") << ");" << NL; - auto *default_constructor = (type->flags & FLAG_DEFAULT_CONSTRUCTOR ? type->constructors.back().get() : nullptr); + auto* default_constructor = (type->flags & FLAG_DEFAULT_CONSTRUCTOR ? type->constructors.back().get() : nullptr); bool has_name = type->constructors_num > 1 && !(type->flags & FLAG_NOCONS); if (default_constructor != nullptr) { W << "int pos = tl_parse_save_pos();" << NL; } W << "auto magic = static_cast(f$fetch_int());" << NL; W << "switch(magic) " << BEGIN; - for (const auto &c : type->constructors) { + for (const auto& c : type->constructors) { if (c.get() == default_constructor) { continue; } @@ -122,8 +114,7 @@ void TypeFetch::compile(CodeGenerator &W) const { if (!typed_mode) { W << "result = " << cpp_tl_struct_name("c_", c->name, template_str) << "::" << fetch_call << NL; if (has_name) { - W << "result.set_value(" << register_tl_const_str("_") << ", " << register_tl_const_str(c->name) << ", " << hash_tl_const_str("_") << "L);" - << NL; + W << "result.set_value(" << register_tl_const_str("_") << ", " << register_tl_const_str(c->name) << ", " << hash_tl_const_str("_") << "L);" << NL; } } else { W << get_php_runtime_type(c.get(), true) << " result;" << NL; @@ -140,8 +131,8 @@ void TypeFetch::compile(CodeGenerator &W) const { if (!typed_mode) { W << "result = " << cpp_tl_struct_name("c_", default_constructor->name, template_str) << "::" << fetch_call << NL; if (has_name) { - W << "result.set_value(" << register_tl_const_str("_") << ", " << register_tl_const_str(default_constructor->name) << ", " - << hash_tl_const_str("_") << "L);" << NL; + W << "result.set_value(" << register_tl_const_str("_") << ", " << register_tl_const_str(default_constructor->name) << ", " << hash_tl_const_str("_") + << "L);" << NL; } } else { W << get_php_runtime_type(default_constructor, true) << " result;" << NL; @@ -159,7 +150,7 @@ void TypeFetch::compile(CodeGenerator &W) const { } } -void TlTypeDeclaration::compile(CodeGenerator &W) const { +void TlTypeDeclaration::compile(CodeGenerator& W) const { W << "/* ~~~~~~~~~ " << t->name << " ~~~~~~~~~ */\n" << NL; const bool needs_typed_fetch_store = TlTypeDeclaration::does_tl_type_need_typed_fetch_store(t); if (needs_typed_fetch_store && is_type_dependent(t, tl) && t->is_polymorphic()) { @@ -167,17 +158,16 @@ void TlTypeDeclaration::compile(CodeGenerator &W) const { W << TlTemplatePhpTypeHelpers(t); } std::string struct_name = cpp_tl_struct_name("t_", t->name); - auto *constructor = t->constructors[0].get(); + auto* constructor = t->constructors[0].get(); std::string template_decl = get_template_declaration(constructor); if (!template_decl.empty()) { W << template_decl << NL; } W << "struct " << struct_name << " " << BEGIN; - W << "using PhpType = " - << (needs_typed_fetch_store ? get_php_runtime_type(t) : "tl_undefined_php_type") << ";" << NL; + W << "using PhpType = " << (needs_typed_fetch_store ? get_php_runtime_type(t) : "tl_undefined_php_type") << ";" << NL; std::vector constructor_params; std::vector constructor_inits; - for (const auto &arg : constructor->args) { + for (const auto& arg : constructor->args) { if (arg->var_num != -1) { if (type_of(arg->type_expr)->is_integer_variable()) { if (arg->is_optional()) { @@ -201,16 +191,16 @@ void TlTypeDeclaration::compile(CodeGenerator &W) const { FunctionSignatureGenerator(W) << "array fetch()" << SemicolonAndNL(); } if (needs_typed_fetch_store) { - FunctionSignatureGenerator(W) << "void typed_store(const PhpType &tl_object)" << SemicolonAndNL(); - FunctionSignatureGenerator(W) << "void typed_fetch_to(PhpType &tl_object)" << SemicolonAndNL(); + FunctionSignatureGenerator(W) << "void typed_store(const PhpType &tl_object)" << SemicolonAndNL(); + FunctionSignatureGenerator(W) << "void typed_fetch_to(PhpType &tl_object)" << SemicolonAndNL(); } W << END << ";\n\n"; } -void TlTypeDefinition::compile(CodeGenerator &W) const { +void TlTypeDefinition::compile(CodeGenerator& W) const { const bool needs_typed_fetch_store = TlTypeDeclaration::does_tl_type_need_typed_fetch_store(t); - auto *constructor = t->constructors[0].get(); + auto* constructor = t->constructors[0].get(); std::string struct_name = cpp_tl_struct_name("t_", t->name); std::string template_decl = get_template_declaration(constructor); std::string template_def = get_template_definition(constructor); @@ -240,4 +230,4 @@ void TlTypeDefinition::compile(CodeGenerator &W) const { W << END << "\n\n"; } } -} +} // namespace tl2cpp diff --git a/compiler/code-gen/files/tl2cpp/tl-type.h b/compiler/code-gen/files/tl2cpp/tl-type.h index 7197deaa4b..faaa8a5dd5 100644 --- a/compiler/code-gen/files/tl2cpp/tl-type.h +++ b/compiler/code-gen/files/tl2cpp/tl-type.h @@ -30,31 +30,28 @@ template::typed_store(const PhpType &tl_object) { if (f$is_a::type>(tl_object)) { f$store_int(0x0a29cd5d); - const typename left__::type *conv_obj = tl_object.template cast_to::type>().get(); - c_left::typed_store(conv_obj, std::move(X), std::move(Y)); - } else if (f$is_a::type>(tl_object)) { - f$store_int(0xdf3ecb3b); - const typename right__::type *conv_obj = tl_object.template cast_to::type>().get(); - c_right::typed_store(conv_obj, std::move(X), std::move(Y)); - } else { - CurrentTlQuery::get().raise_storing_error("Invalid constructor %s of type %s", tl_object.get_class(), "Either"); + const typename left__::type *conv_obj = tl_object.template cast_to::type>().get(); c_left::typed_store(conv_obj, std::move(X), std::move(Y)); } else if (f$is_a::type>(tl_object)) { f$store_int(0xdf3ecb3b); const typename right__::type *conv_obj = tl_object.template cast_to::type>().get(); c_right::typed_store(conv_obj, std::move(X), std::move(Y)); } else { CurrentTlQuery::get().raise_storing_error("Invalid constructor %s of type %s", +tl_object.get_class(), "Either"); } } */ struct TypeStore { - const vk::tlo_parsing::type *type; + const vk::tlo_parsing::type* type; std::string template_str; bool typed_mode; - TypeStore(const vk::tlo_parsing::type *type, std::string template_str, bool typed_mode = false) : - type(type), - template_str(std::move(template_str)), - typed_mode(typed_mode) {} + TypeStore(const vk::tlo_parsing::type* type, std::string template_str, bool typed_mode = false) + : type(type), + template_str(std::move(template_str)), + typed_mode(typed_mode) {} - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; - // Generated code example: /* * Untyped TL: @@ -107,19 +104,18 @@ void t_Either::typed_fetch_to(PhpType &tl_ob } */ struct TypeFetch { - const vk::tlo_parsing::type *type; + const vk::tlo_parsing::type* type; std::string template_str; bool typed_mode; - inline TypeFetch(const vk::tlo_parsing::type *type, std::string template_str, bool typed_mode = false) : - type(type), - template_str(std::move(template_str)), - typed_mode(typed_mode) {} + inline TypeFetch(const vk::tlo_parsing::type* type, std::string template_str, bool typed_mode = false) + : type(type), + template_str(std::move(template_str)), + typed_mode(typed_mode) {} - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; - /* * Typed TL example: template @@ -146,12 +142,12 @@ struct t_Either { }; */ struct TlTypeDeclaration { - const vk::tlo_parsing::type *t; + const vk::tlo_parsing::type* t; // 'messages.ChatInfoUser' TL type can be either: // * A VK\TL\Types\messages\chatInfoUser PHP class // * A VK\TL\Types\messages\ChatInfoUser PHP interface if the type is polymorphic - static bool does_tl_type_need_typed_fetch_store(const vk::tlo_parsing::type *t) { + static bool does_tl_type_need_typed_fetch_store(const vk::tlo_parsing::type* t) { if (t->name == "ReqResult") { // the site won't compile without it unless the typed rpc is included as t_ReqResult is not a compilation target bool typed_php_code_exists = !!G->get_class(vk::tl::PhpClasses::rpc_response_ok_with_tl_full_namespace()); @@ -160,18 +156,18 @@ struct TlTypeDeclaration { return !get_all_php_classes_of_tl_type(t).empty(); } - explicit TlTypeDeclaration(const vk::tlo_parsing::type *t) : - t(t) {} + explicit TlTypeDeclaration(const vk::tlo_parsing::type* t) + : t(t) {} - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; struct TlTypeDefinition { - const vk::tlo_parsing::type *t; + const vk::tlo_parsing::type* t; - explicit TlTypeDefinition(const vk::tlo_parsing::type *t) : - t(t) {} + explicit TlTypeDefinition(const vk::tlo_parsing::type* t) + : t(t) {} - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; -} +} // namespace tl2cpp diff --git a/compiler/code-gen/files/tl2cpp/tl2cpp-utils.cpp b/compiler/code-gen/files/tl2cpp/tl2cpp-utils.cpp index 580b487bab..fbce961191 100644 --- a/compiler/code-gen/files/tl2cpp/tl2cpp-utils.cpp +++ b/compiler/code-gen/files/tl2cpp/tl2cpp-utils.cpp @@ -10,13 +10,29 @@ namespace tl2cpp { const std::string T_TYPE = "Type"; -const std::unordered_set CUSTOM_IMPL_TYPES - {"#", T_TYPE, "Int", "Long", "Double", "Float", "String", "Bool", "True", "False", "Vector", "Maybe", "Tuple", - "Dictionary", "DictionaryField", "IntKeyDictionary", "IntKeyDictionaryField", "LongKeyDictionary", "LongKeyDictionaryField"}; +const std::unordered_set CUSTOM_IMPL_TYPES{"#", + T_TYPE, + "Int", + "Long", + "Double", + "Float", + "String", + "Bool", + "True", + "False", + "Vector", + "Maybe", + "Tuple", + "Dictionary", + "DictionaryField", + "IntKeyDictionary", + "IntKeyDictionaryField", + "LongKeyDictionary", + "LongKeyDictionaryField"}; static const std::string VK_name_prefix = "VK\\"; -vk::tlo_parsing::tl_scheme *tl; -const vk::tlo_parsing::combinator *cur_combinator; +vk::tlo_parsing::tl_scheme* tl; +const vk::tlo_parsing::combinator* cur_combinator; std::set tl_const_vars; @@ -25,45 +41,45 @@ std::string cpp_tl_const_str(std::string tl_name) { return "tl_str$" + tl_name; } -std::string register_tl_const_str(const std::string &tl_name) { +std::string register_tl_const_str(const std::string& tl_name) { tl_const_vars.insert(tl_name); return cpp_tl_const_str(tl_name); } -int64_t hash_tl_const_str(const std::string &tl_name) { +int64_t hash_tl_const_str(const std::string& tl_name) { return string_hash(tl_name.c_str(), tl_name.size()); } -std::string cpp_tl_struct_name(const char *prefix, std::string tl_name, const std::string &template_args_postfix) { +std::string cpp_tl_struct_name(const char* prefix, std::string tl_name, const std::string& template_args_postfix) { std::replace(tl_name.begin(), tl_name.end(), '.', '_'); return std::string(prefix) + tl_name + template_args_postfix; } -std::string get_magic_storing(const vk::tlo_parsing::type_expr_base *arg_type_expr) { - if (const auto *arg_as_type_expr = arg_type_expr->template as()) { +std::string get_magic_storing(const vk::tlo_parsing::type_expr_base* arg_type_expr) { + if (const auto* arg_as_type_expr = arg_type_expr->template as()) { if (is_magic_processing_needed(arg_as_type_expr)) { return fmt_format("f$store_int({:#010x});", static_cast(type_of(arg_as_type_expr)->id)); } - } else if (const auto *arg_as_type_var = arg_type_expr->template as()) { + } else if (const auto* arg_as_type_var = arg_type_expr->template as()) { return fmt_format("store_magic_if_not_bare(inner_magic{});", arg_as_type_var->var_num); } return ""; } -std::string get_magic_fetching(const vk::tlo_parsing::type_expr_base *arg_type_expr, const std::string &error_msg) { - if (const auto *arg_as_type_expr = arg_type_expr->template as()) { +std::string get_magic_fetching(const vk::tlo_parsing::type_expr_base* arg_type_expr, const std::string& error_msg) { + if (const auto* arg_as_type_expr = arg_type_expr->template as()) { if (is_magic_processing_needed(arg_as_type_expr)) { return fmt_format(R"(fetch_magic_if_not_bare({:#010x}, "{}");)", static_cast(type_of(arg_as_type_expr)->id), error_msg); } - } else if (const auto *arg_as_type_var = arg_type_expr->template as()) { - for (const auto &arg : cur_combinator->args) { - if (auto *casted = arg->type_expr->as()) { + } else if (const auto* arg_as_type_var = arg_type_expr->template as()) { + for (const auto& arg : cur_combinator->args) { + if (auto* casted = arg->type_expr->as()) { if (arg->is_forwarded_function() && casted->var_num == arg_as_type_var->var_num) { return ""; } } } - return fmt_format( R"(fetch_magic_if_not_bare(inner_magic{}, "{}");)", arg_as_type_var->var_num, error_msg); + return fmt_format(R"(fetch_magic_if_not_bare(inner_magic{}, "{}");)", arg_as_type_var->var_num, error_msg); } return ""; } @@ -73,16 +89,16 @@ std::string get_magic_fetching(const vk::tlo_parsing::type_expr_base *arg_type_e // 1) TlTemplateTypeHelpers // 2) get_php_runtime_type(...) // 3) get_php_class_of_tl_*(...) -vk::tlo_parsing::type *get_this_from_renamed_tl_scheme(const vk::tlo_parsing::type *t) { +vk::tlo_parsing::type* get_this_from_renamed_tl_scheme(const vk::tlo_parsing::type* t) { return G->get_tl_classes().get_scheme()->get_type_by_magic(t->id); } -vk::tlo_parsing::combinator *get_this_from_renamed_tl_scheme(const vk::tlo_parsing::combinator *c) { - return c->is_constructor() ? - G->get_tl_classes().get_scheme()->get_constructor_by_magic(c->id) : G->get_tl_classes().get_scheme()->get_function_by_magic(c->id); +vk::tlo_parsing::combinator* get_this_from_renamed_tl_scheme(const vk::tlo_parsing::combinator* c) { + return c->is_constructor() ? G->get_tl_classes().get_scheme()->get_constructor_by_magic(c->id) + : G->get_tl_classes().get_scheme()->get_function_by_magic(c->id); } -std::string get_php_namespace(const std::string &tl_name) { +std::string get_php_namespace(const std::string& tl_name) { size_t dot_pos = tl_name.find('.'); return dot_pos == std::string::npos ? vk::tl::PhpClasses::common_engine_namespace() : tl_name.substr(0, dot_pos); } @@ -90,17 +106,17 @@ std::string get_php_namespace(const std::string &tl_name) { // find the TL constructor by the PHP-class // for example, class VK\TL\messages\Types\messages_chatInfo => messages.chatInfo // it could be a specialization of the dependent type constructor: Types\vectorTotal__int => vectorTotal -vk::tlo_parsing::combinator *get_tl_constructor_of_php_class(ClassPtr klass) { - const auto &tl_scheme = G->get_tl_classes().get_scheme(); +vk::tlo_parsing::combinator* get_tl_constructor_of_php_class(ClassPtr klass) { + const auto& tl_scheme = G->get_tl_classes().get_scheme(); - const auto &php_representations = G->get_tl_classes().get_php_classes().all_classes; + const auto& php_representations = G->get_tl_classes().get_php_classes().all_classes; auto constructor_php_repr_iter = php_representations.find(klass->name.substr(VK_name_prefix.length())); kphp_assert(constructor_php_repr_iter != php_representations.end()); - const auto &constructor_magic_iter = tl_scheme->magics.find(constructor_php_repr_iter->second.get().tl_name); + const auto& constructor_magic_iter = tl_scheme->magics.find(constructor_php_repr_iter->second.get().tl_name); kphp_assert(constructor_magic_iter != tl_scheme->magics.end()); - vk::tlo_parsing::combinator *res = tl_scheme->get_constructor_by_magic(constructor_magic_iter->second); + vk::tlo_parsing::combinator* res = tl_scheme->get_constructor_by_magic(constructor_magic_iter->second); kphp_assert(res); return res; } @@ -108,18 +124,18 @@ vk::tlo_parsing::combinator *get_tl_constructor_of_php_class(ClassPtr klass) { // find the TL polymorphic type by the PHP-interface; // it won't work for non-polymorphic types as we'll have constructors instead of types for them (e.g. class messages_chatInfo); // therefore, this function works only for polymorphic types (e.g. interface memcache_Value) -vk::tlo_parsing::type *get_tl_type_of_php_class(ClassPtr interface) { +vk::tlo_parsing::type* get_tl_type_of_php_class(ClassPtr interface) { kphp_assert(is_php_class_a_tl_polymorphic_type(interface)); - const auto &tl_scheme = G->get_tl_classes().get_scheme(); + const auto& tl_scheme = G->get_tl_classes().get_scheme(); - const auto &tl_type_php_representations = G->get_tl_classes().get_php_classes().types; + const auto& tl_type_php_representations = G->get_tl_classes().get_php_classes().types; auto php_repr_iter = tl_type_php_representations.find(interface->name.substr(VK_name_prefix.length())); kphp_assert(php_repr_iter != tl_type_php_representations.end()); auto tl_magic_iter = tl_scheme->magics.find(php_repr_iter->second.type_representation->tl_name); kphp_assert(tl_magic_iter != tl_scheme->magics.end()); - auto *res_tl_type = tl_scheme->get_type_by_magic(tl_magic_iter->second); + auto* res_tl_type = tl_scheme->get_type_by_magic(tl_magic_iter->second); kphp_assert(res_tl_type); return res_tl_type; } @@ -127,10 +143,11 @@ vk::tlo_parsing::type *get_tl_type_of_php_class(ClassPtr interface) { // for dependent type constructors, like vectorTotal {t:Type}, // there can be multiple PHP-specializations like vectorTotal__int, etc per one TL constructor. // this function accepts the concrete specialization of such constructor with the raw suffix of the PHP class (e.g. "__int") -ClassPtr get_php_class_of_tl_constructor_specialization(const vk::tlo_parsing::combinator *c, const std::string &specialization_suffix) { - auto *c_from_renamed = get_this_from_renamed_tl_scheme(c); +ClassPtr get_php_class_of_tl_constructor_specialization(const vk::tlo_parsing::combinator* c, const std::string& specialization_suffix) { + auto* c_from_renamed = get_this_from_renamed_tl_scheme(c); std::string php_namespace = get_php_namespace(c_from_renamed->name); - std::string php_class_name = G->settings().tl_namespace_prefix.get() + php_namespace + "\\Types\\" + replace_characters(c_from_renamed->name, '.', '_') + specialization_suffix; + std::string php_class_name = + G->settings().tl_namespace_prefix.get() + php_namespace + "\\Types\\" + replace_characters(c_from_renamed->name, '.', '_') + specialization_suffix; return G->get_class(php_class_name); } @@ -138,7 +155,7 @@ std::vector _get_all_php_classes_by_tl_magic(int magic, bool need_only std::vector classes; auto range = G->get_tl_classes().get_php_classes().magic_to_classes.equal_range(magic); for (auto it = range.first; it != range.second; ++it) { - const vk::tl::PhpClassRepresentation &php_representation = it->second.get(); + const vk::tl::PhpClassRepresentation& php_representation = it->second.get(); ClassPtr klass = G->get_class(php_representation.get_full_php_class_name()); if (php_representation.is_interface == need_only_interfaces && klass) { classes.emplace_back(klass); @@ -149,35 +166,36 @@ std::vector _get_all_php_classes_by_tl_magic(int magic, bool need_only // For every TL constructor there can be one PHP-class (in case of the simple constructors like likes.item) // or more if it's a constructor with dependent types (then we'll have vectorTotal__int and other specializations) -std::vector get_all_php_classes_of_tl_constructor(const vk::tlo_parsing::combinator *c) { - auto *c_from_renamed = get_this_from_renamed_tl_scheme(c); // For the sake of consistency +std::vector get_all_php_classes_of_tl_constructor(const vk::tlo_parsing::combinator* c) { + auto* c_from_renamed = get_this_from_renamed_tl_scheme(c); // For the sake of consistency return _get_all_php_classes_by_tl_magic(c_from_renamed->id, false); } // For every TL type there can be one class/interface (in case of the simple types like likes.Item) // or more if it's a type with dependent types (then we'll have Either_string_Vertex and other specializations) -std::vector get_all_php_classes_of_tl_type(const vk::tlo_parsing::type *t) { - auto *t_from_renamed = get_this_from_renamed_tl_scheme(t); // For the sake of consistency +std::vector get_all_php_classes_of_tl_type(const vk::tlo_parsing::type* t) { + auto* t_from_renamed = get_this_from_renamed_tl_scheme(t); // For the sake of consistency return _get_all_php_classes_by_tl_magic(t_from_renamed->id, t_from_renamed->is_polymorphic()); } // If type has dependent types, VectorTotal for example, then one TL type will have // many PHP-specializations vectorTotal__int, etc // (non-polymorphic types are combined with constructors into a single class as usual) -ClassPtr get_php_class_of_tl_type_specialization(const vk::tlo_parsing::type *t, const std::string &specialization_suffix) { - auto *t_from_renamed = get_this_from_renamed_tl_scheme(t); +ClassPtr get_php_class_of_tl_type_specialization(const vk::tlo_parsing::type* t, const std::string& specialization_suffix) { + auto* t_from_renamed = get_this_from_renamed_tl_scheme(t); kphp_assert(is_type_dependent(t_from_renamed, G->get_tl_classes().get_scheme().get())); std::string php_namespace = get_php_namespace(t_from_renamed->name); std::string lookup_name = t_from_renamed->is_polymorphic() ? t_from_renamed->name : t_from_renamed->constructors[0]->name; - std::string php_class_name = G->settings().tl_namespace_prefix.get() + php_namespace + "\\Types\\" + replace_characters(lookup_name, '.', '_') + specialization_suffix; + std::string php_class_name = + G->settings().tl_namespace_prefix.get() + php_namespace + "\\Types\\" + replace_characters(lookup_name, '.', '_') + specialization_suffix; return G->get_class(php_class_name); } // For the 'messages.getChatInfo' TL function there is a PHP class VK\TL\messages\Functions\messages_getChatInfo // if that class is reachable by the compiler, typed form of the 'messages.getChatInfo' should be generated // (otherwise, that typed TL function is guaranteed not to be called, hence we don't need it) -ClassPtr get_php_class_of_tl_function(const vk::tlo_parsing::combinator *f) { - auto *f_from_renamed = get_this_from_renamed_tl_scheme(f); +ClassPtr get_php_class_of_tl_function(const vk::tlo_parsing::combinator* f) { + auto* f_from_renamed = get_this_from_renamed_tl_scheme(f); std::string php_namespace = get_php_namespace(f_from_renamed->name); std::string php_class_name = G->settings().tl_namespace_prefix.get() + php_namespace + "\\Functions\\" + replace_characters(f_from_renamed->name, '.', '_'); return G->get_class(php_class_name); @@ -207,10 +225,11 @@ std::string get_tl_function_name_of_php_class(ClassPtr klass) { // 'messages.getChatInfo' TL function has a typed result in form of the PHP class VK\TL\messages\Functions\messages_getChatInfo_result // If it's reachable <=> the result is reachable -ClassPtr get_php_class_of_tl_function_result(const vk::tlo_parsing::combinator *f) { - auto *f_from_renamed = get_this_from_renamed_tl_scheme(f); +ClassPtr get_php_class_of_tl_function_result(const vk::tlo_parsing::combinator* f) { + auto* f_from_renamed = get_this_from_renamed_tl_scheme(f); std::string php_namespace = get_php_namespace(f_from_renamed->name); - std::string php_class_name = G->settings().tl_namespace_prefix.get() + php_namespace + "\\Functions\\" + replace_characters(f_from_renamed->name, '.', '_') + "_result"; + std::string php_class_name = + G->settings().tl_namespace_prefix.get() + php_namespace + "\\Functions\\" + replace_characters(f_from_renamed->name, '.', '_') + "_result"; return G->get_class(php_class_name); } @@ -231,20 +250,19 @@ bool is_php_class_a_tl_constructor(ClassPtr klass) { // will produce a isearch\isearch_typeInfo_arg2_item { int type, double probability } class and we'll get: // isearch.typeInfo n:# data:n*[isearch\isearch_typeInfo_arg2_item] = isearch.TypeInfo bool is_php_class_a_tl_array_item(ClassPtr klass) { - return klass->is_tl_class && klass->is_class() && klass->name.find("Types\\") != std::string::npos && - klass->name.find("_arg") != std::string::npos && klass->name.find("_item") != std::string::npos; + return klass->is_tl_class && klass->is_class() && klass->name.find("Types\\") != std::string::npos && klass->name.find("_arg") != std::string::npos && + klass->name.find("_item") != std::string::npos; } -bool is_tl_type_a_php_array(const vk::tlo_parsing::type *t) { - return t->id == TL_VECTOR || t->id == TL_TUPLE || t->id == TL_DICTIONARY || - t->id == TL_INT_KEY_DICTIONARY || t->id == TL_LONG_KEY_DICTIONARY; +bool is_tl_type_a_php_array(const vk::tlo_parsing::type* t) { + return t->id == TL_VECTOR || t->id == TL_TUPLE || t->id == TL_DICTIONARY || t->id == TL_INT_KEY_DICTIONARY || t->id == TL_LONG_KEY_DICTIONARY; } -bool is_tl_type_wrapped_to_Optional(const vk::tlo_parsing::type *type) { +bool is_tl_type_wrapped_to_Optional(const vk::tlo_parsing::type* type) { // [fields_mask.n? | Maybe] [int|string|array|double|bool] -- with Optional // [fields_mask.n? | Maybe] [class_instance|Optional|var] -- without Optional - return is_tl_type_a_php_array(type) || vk::any_of_equal(type->id, TL_INT, TL_DOUBLE, TL_FLOAT, TL_STRING) || type->name == "Bool" || type->is_integer_variable() - || type->id == TL_LONG; + return is_tl_type_a_php_array(type) || vk::any_of_equal(type->id, TL_INT, TL_DOUBLE, TL_FLOAT, TL_STRING) || type->name == "Bool" || + type->is_integer_variable() || type->id == TL_LONG; } // classes VK\TL\*\Types\* are a non-interface types that correspond to the TL-constructors @@ -255,8 +273,8 @@ bool is_php_class_a_tl_polymorphic_type(ClassPtr klass) { return klass->is_tl_class && klass->is_interface() && klass->name.find("Types\\") != std::string::npos; } -bool is_magic_processing_needed(const vk::tlo_parsing::type_expr *type_expr) { - const auto &type = tl->types[type_expr->type_id]; +bool is_magic_processing_needed(const vk::tlo_parsing::type_expr* type_expr) { + const auto& type = tl->types[type_expr->type_id]; // polymorphic types do the 'magic' processing internally; '#' never needs to process 'magic' bool handles_magic_inside = type->is_integer_variable() ? true : type->is_polymorphic(); bool is_used_as_bare = type_expr->is_bare(); @@ -264,8 +282,8 @@ bool is_magic_processing_needed(const vk::tlo_parsing::type_expr *type_expr) { return !(handles_magic_inside || is_used_as_bare); } -vk::tlo_parsing::type *type_of(const std::unique_ptr &type_expr, const vk::tlo_parsing::tl_scheme *scheme) { - if (auto *casted = type_expr->template as()) { +vk::tlo_parsing::type* type_of(const std::unique_ptr& type_expr, const vk::tlo_parsing::tl_scheme* scheme) { + if (auto* casted = type_expr->template as()) { auto type_it = scheme->types.find(casted->type_id); if (type_it != scheme->types.end()) { return type_it->second.get(); @@ -274,7 +292,7 @@ vk::tlo_parsing::type *type_of(const std::unique_ptrtypes.find(type->type_id); if (type_it != scheme->types.end()) { return type_it->second.get(); @@ -282,9 +300,9 @@ vk::tlo_parsing::type *type_of(const vk::tlo_parsing::type_expr *type, const vk: return nullptr; } -std::vector get_optional_args_for_call(const std::unique_ptr &constructor) { +std::vector get_optional_args_for_call(const std::unique_ptr& constructor) { std::vector res; - for (const auto &arg : constructor->args) { + for (const auto& arg : constructor->args) { if (arg->is_optional()) { if (type_of(arg->type_expr)->is_integer_variable()) { res.emplace_back(arg->name); @@ -297,9 +315,9 @@ std::vector get_optional_args_for_call(const std::unique_ptr get_template_params(const vk::tlo_parsing::combinator *constructor) { +std::vector get_template_params(const vk::tlo_parsing::combinator* constructor) { std::vector typenames; - for (const auto &arg : constructor->args) { + for (const auto& arg : constructor->args) { if (arg->var_num != -1 && type_of(arg->type_expr)->name == T_TYPE) { kphp_assert(arg->is_optional()); typenames.emplace_back(fmt_format("T{}", arg->var_num)); @@ -309,7 +327,7 @@ std::vector get_template_params(const vk::tlo_parsing::combinator * return typenames; } -std::string get_template_declaration(const vk::tlo_parsing::combinator *constructor) { +std::string get_template_declaration(const vk::tlo_parsing::combinator* constructor) { std::vector typenames = get_template_params(constructor); if (typenames.empty()) { return ""; @@ -324,7 +342,7 @@ std::string get_template_declaration(const vk::tlo_parsing::combinator *construc return "template<" + vk::join(typenames, ", ") + ">"; } -std::string get_template_definition(const vk::tlo_parsing::combinator *constructor) { +std::string get_template_definition(const vk::tlo_parsing::combinator* constructor) { std::vector typenames = get_template_params(constructor); if (typenames.empty()) { return ""; @@ -332,14 +350,13 @@ std::string get_template_definition(const vk::tlo_parsing::combinator *construct return "<" + vk::join(typenames, ", ") + ">"; } - -std::string get_php_runtime_type(const vk::tlo_parsing::combinator *c, bool wrap_to_class_instance, const std::string &type_name) { - auto *c_from_renamed = get_this_from_renamed_tl_scheme(c); +std::string get_php_runtime_type(const vk::tlo_parsing::combinator* c, bool wrap_to_class_instance, const std::string& type_name) { + auto* c_from_renamed = get_this_from_renamed_tl_scheme(c); std::string res; std::string name = type_name.empty() ? c_from_renamed->name : type_name; if (c_from_renamed->is_constructor() && is_type_dependent(c_from_renamed, tl)) { std::vector template_params; - for (const auto &arg : c_from_renamed->args) { + for (const auto& arg : c_from_renamed->args) { if (arg->is_type()) { kphp_assert(arg->is_optional()); template_params.emplace_back(fmt_format("typename T{}::PhpType", arg->var_num)); @@ -359,24 +376,24 @@ std::string get_php_runtime_type(const vk::tlo_parsing::combinator *c, bool wrap return res; } -std::string get_php_runtime_type(const vk::tlo_parsing::type *t) { - auto *t_from_renamed = get_this_from_renamed_tl_scheme(t); - if (t_from_renamed->is_polymorphic()) { // then we'll use a type name instead of the constructor name +std::string get_php_runtime_type(const vk::tlo_parsing::type* t) { + auto* t_from_renamed = get_this_from_renamed_tl_scheme(t); + if (t_from_renamed->is_polymorphic()) { // then we'll use a type name instead of the constructor name return get_php_runtime_type(t_from_renamed->constructors[0].get(), true, t_from_renamed->name); } return get_php_runtime_type(t_from_renamed->constructors[0].get(), true); } -std::string get_tl_object_field_access(const std::unique_ptr &arg, field_rw_type rw_type) { +std::string get_tl_object_field_access(const std::unique_ptr& arg, field_rw_type rw_type) { kphp_assert(!arg->name.empty()); if (arg->is_fields_mask_optional()) { - if (auto *type_var = arg->type_expr->as()) { + if (auto* type_var = arg->type_expr->as()) { std::string serializer_type_name = "T" + std::to_string(type_var->var_num); std::string field_access_type = rw_type == field_rw_type::READ ? "read" : "write"; - return fmt_format("get_serialization_target_from_optional_field<{}, FieldAccessType::{}>(tl_object->${})", - serializer_type_name, field_access_type, arg->name); + return fmt_format("get_serialization_target_from_optional_field<{}, FieldAccessType::{}>(tl_object->${})", serializer_type_name, field_access_type, + arg->name); } else { - vk::tlo_parsing::type *type = type_of(arg->type_expr); + vk::tlo_parsing::type* type = type_of(arg->type_expr); kphp_assert(type); if (is_tl_type_wrapped_to_Optional(type)) { return fmt_format("tl_object->${}.{}", arg->name, rw_type == field_rw_type::READ ? "val()" : "ref()"); @@ -386,10 +403,10 @@ std::string get_tl_object_field_access(const std::unique_ptr${}", arg->name); } -bool is_type_dependent(const vk::tlo_parsing::combinator *constructor, const vk::tlo_parsing::tl_scheme *scheme) { +bool is_type_dependent(const vk::tlo_parsing::combinator* constructor, const vk::tlo_parsing::tl_scheme* scheme) { kphp_assert(constructor->is_constructor()); - for (const auto &arg : constructor->args) { - auto *arg_type = type_of(arg->type_expr, scheme); + for (const auto& arg : constructor->args) { + auto* arg_type = type_of(arg->type_expr, scheme); if (arg_type && arg_type->name == "Type") { return true; } @@ -397,7 +414,7 @@ bool is_type_dependent(const vk::tlo_parsing::combinator *constructor, const vk: return false; } -bool is_type_dependent(const vk::tlo_parsing::type *type, const vk::tlo_parsing::tl_scheme *scheme) { +bool is_type_dependent(const vk::tlo_parsing::type* type, const vk::tlo_parsing::tl_scheme* scheme) { return is_type_dependent(type->constructors[0].get(), scheme); } -} +} // namespace tl2cpp diff --git a/compiler/code-gen/files/tl2cpp/tl2cpp-utils.h b/compiler/code-gen/files/tl2cpp/tl2cpp-utils.h index dff616979d..f0cb654f2d 100644 --- a/compiler/code-gen/files/tl2cpp/tl2cpp-utils.h +++ b/compiler/code-gen/files/tl2cpp/tl2cpp-utils.h @@ -15,60 +15,57 @@ class CodeGenerator; namespace tl2cpp { -extern const std::unordered_set CUSTOM_IMPL_TYPES; // from tl_builtins.h -extern vk::tlo_parsing::tl_scheme *tl; -extern const vk::tlo_parsing::combinator *cur_combinator; +extern const std::unordered_set CUSTOM_IMPL_TYPES; // from tl_builtins.h +extern vk::tlo_parsing::tl_scheme* tl; +extern const vk::tlo_parsing::combinator* cur_combinator; extern const std::string T_TYPE; extern std::set tl_const_vars; -enum class field_rw_type { - READ, - WRITE -}; +enum class field_rw_type { READ, WRITE }; -std::string get_tl_object_field_access(const std::unique_ptr &arg, field_rw_type rw_type); +std::string get_tl_object_field_access(const std::unique_ptr& arg, field_rw_type rw_type); -vk::tlo_parsing::type *type_of(const std::unique_ptr &type_expr, const vk::tlo_parsing::tl_scheme *scheme = tl); -vk::tlo_parsing::type *type_of(const vk::tlo_parsing::type_expr *type, const vk::tlo_parsing::tl_scheme *scheme = tl); +vk::tlo_parsing::type* type_of(const std::unique_ptr& type_expr, const vk::tlo_parsing::tl_scheme* scheme = tl); +vk::tlo_parsing::type* type_of(const vk::tlo_parsing::type_expr* type, const vk::tlo_parsing::tl_scheme* scheme = tl); -bool is_magic_processing_needed(const vk::tlo_parsing::type_expr *type_expr); -std::string get_magic_storing(const vk::tlo_parsing::type_expr_base *arg_type_expr); -std::string get_magic_fetching(const vk::tlo_parsing::type_expr_base *arg_type_expr, const std::string &error_msg); -std::string cpp_tl_struct_name(const char *prefix, std::string tl_name, const std::string &template_args_postfix = ""); +bool is_magic_processing_needed(const vk::tlo_parsing::type_expr* type_expr); +std::string get_magic_storing(const vk::tlo_parsing::type_expr_base* arg_type_expr); +std::string get_magic_fetching(const vk::tlo_parsing::type_expr_base* arg_type_expr, const std::string& error_msg); +std::string cpp_tl_struct_name(const char* prefix, std::string tl_name, const std::string& template_args_postfix = ""); std::string cpp_tl_const_str(std::string tl_name); -std::string register_tl_const_str(const std::string &tl_name); -int64_t hash_tl_const_str(const std::string &tl_name); +std::string register_tl_const_str(const std::string& tl_name); +int64_t hash_tl_const_str(const std::string& tl_name); -vk::tlo_parsing::type *get_tl_type_of_php_class(ClassPtr interface); -vk::tlo_parsing::combinator *get_tl_constructor_of_php_class(ClassPtr klass); -std::vector get_all_php_classes_of_tl_constructor(const vk::tlo_parsing::combinator *c); -std::vector get_all_php_classes_of_tl_type(const vk::tlo_parsing::type *t); -ClassPtr get_php_class_of_tl_constructor_specialization(const vk::tlo_parsing::combinator *c, const std::string &specialization_suffix); -ClassPtr get_php_class_of_tl_type_specialization(const vk::tlo_parsing::type *t, const std::string &specialization_suffix); +vk::tlo_parsing::type* get_tl_type_of_php_class(ClassPtr interface); +vk::tlo_parsing::combinator* get_tl_constructor_of_php_class(ClassPtr klass); +std::vector get_all_php_classes_of_tl_constructor(const vk::tlo_parsing::combinator* c); +std::vector get_all_php_classes_of_tl_type(const vk::tlo_parsing::type* t); +ClassPtr get_php_class_of_tl_constructor_specialization(const vk::tlo_parsing::combinator* c, const std::string& specialization_suffix); +ClassPtr get_php_class_of_tl_type_specialization(const vk::tlo_parsing::type* t, const std::string& specialization_suffix); -ClassPtr get_php_class_of_tl_function(const vk::tlo_parsing::combinator *f); +ClassPtr get_php_class_of_tl_function(const vk::tlo_parsing::combinator* f); std::string get_tl_function_name_of_php_class(ClassPtr klass); -ClassPtr get_php_class_of_tl_function_result(const vk::tlo_parsing::combinator *f); +ClassPtr get_php_class_of_tl_function_result(const vk::tlo_parsing::combinator* f); -vk::tlo_parsing::type *get_this_from_renamed_tl_scheme(const vk::tlo_parsing::type *t); -vk::tlo_parsing::combinator *get_this_from_renamed_tl_scheme(const vk::tlo_parsing::combinator *c); +vk::tlo_parsing::type* get_this_from_renamed_tl_scheme(const vk::tlo_parsing::type* t); +vk::tlo_parsing::combinator* get_this_from_renamed_tl_scheme(const vk::tlo_parsing::combinator* c); -std::vector get_optional_args_for_call(const std::unique_ptr &constructor); -std::vector get_template_params(const vk::tlo_parsing::combinator *constructor); -std::string get_template_declaration(const vk::tlo_parsing::combinator *constructor); -std::string get_template_definition(const vk::tlo_parsing::combinator *constructor); +std::vector get_optional_args_for_call(const std::unique_ptr& constructor); +std::vector get_template_params(const vk::tlo_parsing::combinator* constructor); +std::string get_template_declaration(const vk::tlo_parsing::combinator* constructor); +std::string get_template_definition(const vk::tlo_parsing::combinator* constructor); -std::string get_php_runtime_type(const vk::tlo_parsing::combinator *c, bool wrap_to_class_instance = false, const std::string &type_name = ""); -std::string get_php_runtime_type(const vk::tlo_parsing::type *t); +std::string get_php_runtime_type(const vk::tlo_parsing::combinator* c, bool wrap_to_class_instance = false, const std::string& type_name = ""); +std::string get_php_runtime_type(const vk::tlo_parsing::type* t); bool is_php_class_a_tl_function(ClassPtr klass); bool is_php_class_a_tl_constructor(ClassPtr klass); bool is_php_class_a_tl_polymorphic_type(ClassPtr klass); bool is_php_class_a_tl_array_item(ClassPtr klass); -bool is_tl_type_a_php_array(const vk::tlo_parsing::type *t); -bool is_tl_type_wrapped_to_Optional(const vk::tlo_parsing::type *type); +bool is_tl_type_a_php_array(const vk::tlo_parsing::type* t); +bool is_tl_type_wrapped_to_Optional(const vk::tlo_parsing::type* type); -bool is_type_dependent(const vk::tlo_parsing::type *type, const vk::tlo_parsing::tl_scheme *); -bool is_type_dependent(const vk::tlo_parsing::combinator *constructor, const vk::tlo_parsing::tl_scheme *); -} +bool is_type_dependent(const vk::tlo_parsing::type* type, const vk::tlo_parsing::tl_scheme*); +bool is_type_dependent(const vk::tlo_parsing::combinator* constructor, const vk::tlo_parsing::tl_scheme*); +} // namespace tl2cpp diff --git a/compiler/code-gen/files/tl2cpp/tl2cpp.cpp b/compiler/code-gen/files/tl2cpp/tl2cpp.cpp index 34af97fcb3..5e6be6324a 100644 --- a/compiler/code-gen/files/tl2cpp/tl2cpp.cpp +++ b/compiler/code-gen/files/tl2cpp/tl2cpp.cpp @@ -47,37 +47,37 @@ namespace tl2cpp { /* Bundle all combinators and types by modules while collecting all their dependencies along the way. * */ static void collect_target_objects() { - auto should_exclude_tl_type = [](const std::unique_ptr &t) { - return CUSTOM_IMPL_TYPES.find(t->name) != CUSTOM_IMPL_TYPES.end() - || t->name == "engine.Query"; // it's the only type with !X; can we get rid of it in the future? + auto should_exclude_tl_type = [](const std::unique_ptr& t) { + return CUSTOM_IMPL_TYPES.find(t->name) != CUSTOM_IMPL_TYPES.end() || + t->name == "engine.Query"; // it's the only type with !X; can we get rid of it in the future? }; - auto should_exclude_tl_function = [](const std::unique_ptr &f) { + auto should_exclude_tl_function = [](const std::unique_ptr& f) { return !G->settings().gen_tl_internals.get() && f->is_internal_function(); }; - for (const auto &e : tl->types) { - const std::unique_ptr &t = e.second; + for (const auto& e : tl->types) { + const std::unique_ptr& t = e.second; if (!should_exclude_tl_type(t)) { Module::add_to_module(t); } } - for (const auto &e : tl->functions) { - const std::unique_ptr &f = e.second; + for (const auto& e : tl->functions) { + const std::unique_ptr& f = e.second; if (!should_exclude_tl_function(f)) { Module::add_to_module(f); } } } -void write_rpc_server_functions(CodeGenerator &W) { +void write_rpc_server_functions(CodeGenerator& W) { W << OpenFile("rpc_server_fetch_request.cpp", "tl", false); W << ExternInclude(G->settings().runtime_headers.get()); - std::vector kphp_functions; + std::vector kphp_functions; IncludesCollector deps; deps.add_raw_filename_include("tl/common.h"); // to make it successfully compile even if there are no @kphp functions - for (const auto &item : tl->functions) { - const auto &f = item.second; + for (const auto& item : tl->functions) { + const auto& f = item.second; if (f->is_kphp_rpc_server_function()) { auto klass = get_php_class_of_tl_function(f.get()); if (klass) { // With !klass we assume that such function doesn't exist @@ -104,65 +104,53 @@ void write_rpc_server_functions(CodeGenerator &W) { W << END << NL; W << "(void)tl_parse_restore_pos(start);" << NL; W << "switch(function_magic) " << BEGIN; - for (const auto &f : kphp_functions) { + for (const auto& f : kphp_functions) { W << fmt_format("case {:#010x}: ", static_cast(f->id)) << BEGIN; - W << get_php_runtime_type(f, true) << " request;" << NL - << "request.alloc();" << NL + W << get_php_runtime_type(f, true) << " request;" << NL << "request.alloc();" << NL << "CurrentTlQuery::get().set_current_tl_function(f$VK$TL$RpcFunction$$getTLFunctionName(request));" << NL - << "auto custom_fetcher = f$VK$TL$RpcFunction$$typedFetch(request);" << NL - << "CHECK_EXCEPTION(" << NL - << " php_warning(\"Exception when calling typedFetch for function magic: 0x%08x tl_version: %d\", function_magic, tl_version);" << NL - << " return {};" << NL - << ")" << NL - << "if (custom_fetcher.is_null())" << BEGIN - << "if (tl_version == 2)" << BEGIN + << "auto custom_fetcher = f$VK$TL$RpcFunction$$typedFetch(request);" << NL << "CHECK_EXCEPTION(" << NL + << " php_warning(\"Exception when calling typedFetch for function magic: 0x%08x tl_version: %d\", function_magic, tl_version);" << NL << " return {};" + << NL << ")" << NL << "if (custom_fetcher.is_null())" << BEGIN << "if (tl_version == 2)" << BEGIN << "php_warning(\"TL2 request to function with not generated or disabled typedFetch(): 0x%08x tl_version: %d\", function_magic, tl_version);" << NL - << "return {};" << NL - << END << NL - << "(void)f$fetch_int();" << NL - << "CurrentRpcServerQuery::get().save(" << cpp_tl_struct_name("f_", f->name) << "::rpc_server_typed_fetch(request.get()));" << NL - << END << "else" << BEGIN - << "CurrentRpcServerQuery::get().save(make_tl_func_base_simple_wrapper(std::move(custom_fetcher)));" << NL - << END << NL - << "return request;" << NL - << END << NL; + << "return {};" << NL << END << NL << "(void)f$fetch_int();" << NL << "CurrentRpcServerQuery::get().save(" << cpp_tl_struct_name("f_", f->name) + << "::rpc_server_typed_fetch(request.get()));" << NL << END << "else" << BEGIN + << "CurrentRpcServerQuery::get().save(make_tl_func_base_simple_wrapper(std::move(custom_fetcher)));" << NL << END << NL << "return request;" << NL << END + << NL; } W << "default: " << BEGIN - << "php_warning(\"Unexpected function magic on fetching request in rpc server: 0x%08x tl_version: %d\", function_magic, tl_version);" << NL - << "return {};" << NL - << END << NL; + << "php_warning(\"Unexpected function magic on fetching request in rpc server: 0x%08x tl_version: %d\", function_magic, tl_version);" << NL << "return {};" + << NL << END << NL; W << END << NL; W << END << NL; W << CloseFile(); } -void write_tl_query_handlers(CodeGenerator &W) { +void write_tl_query_handlers(CodeGenerator& W) { if (G->settings().tl_schema_file.get().empty()) { return; } auto parsing_result = vk::tlo_parsing::parse_tlo(G->settings().tl_schema_file.get().c_str(), false); - kphp_error_return(parsing_result.parsed_schema, - fmt_format("Error while reading tlo: {}", parsing_result.error)); + kphp_error_return(parsing_result.parsed_schema, fmt_format("Error while reading tlo: {}", parsing_result.error)); tl = parsing_result.parsed_schema.get(); try { vk::tlo_parsing::replace_anonymous_args(*tl); vk::tlo_parsing::perform_flat_optimization(*tl); vk::tlo_parsing::tl_scheme_final_check(*tl); - } catch (const std::exception &ex) { + } catch (const std::exception& ex) { kphp_error_return(false, ex.what()); } collect_target_objects(); - for (const auto &e : modules) { - const Module &module = e.second; + for (const auto& e : modules) { + const Module& module = e.second; W << module; } if (G->get_untyped_rpc_tl_used()) { W << OpenFile("tl_runtime_bindings.cpp", "tl", false); W << ExternInclude(G->settings().runtime_headers.get()); - for (const auto &module_name : modules_with_functions) { + for (const auto& module_name : modules_with_functions) { W << Include("tl/" + module_name + ".h"); } W << NL; @@ -170,8 +158,7 @@ void write_tl_query_handlers(CodeGenerator &W) { // we do this to avoid t_ReqResult-related dependencies inside the runtime FunctionSignatureGenerator(W) << "array gen$tl_fetch_wrapper(std::unique_ptr stored_fetcher) " << BEGIN << "tl_exclamation_fetch_wrapper X(std::move(stored_fetcher));" << NL - << "return t_ReqResult(std::move(X)).fetch();" << NL - << END << NL << NL; + << "return t_ReqResult(std::move(X)).fetch();" << NL << END << NL << NL; // a hash table that contains all TL functions; // it's passed to the runtime just like the fetch wrapper W << "array gen$tl_storers_ht;" << NL; @@ -180,9 +167,9 @@ void write_tl_query_handlers(CodeGenerator &W) { FunctionSignatureGenerator(W) << "void fill_tl_storers_ht() " << BEGIN; std::stringstream ss{}; // TODO: use std::transform_reduce or something like that int32_t tl_storers_nums = 0; - for (const auto &module_name : modules_with_functions) { + for (const auto& module_name : modules_with_functions) { tl_storers_nums += modules[module_name].target_functions.size(); - for (const auto &f : modules[module_name].target_functions) { + for (const auto& f : modules[module_name].target_functions) { ss << "gen$tl_storers_ht.set_value(" << register_tl_const_str(f->name) << ", " << "&" << cpp_tl_struct_name("f_", f->name) << "::store, " << hash_tl_const_str(f->name) << "L);\n"; } @@ -197,23 +184,18 @@ void write_tl_query_handlers(CodeGenerator &W) { W << OpenFile("tl_const_vars.h", "tl"); W << "#pragma once" << NL; W << ExternInclude(G->settings().runtime_headers.get()); - std::for_each(tl_const_vars.begin(), tl_const_vars.end(), [&W](const std::string &s) { - W << "extern string " << cpp_tl_const_str(s) << ";" << NL; - }); + std::for_each(tl_const_vars.begin(), tl_const_vars.end(), [&W](const std::string& s) { W << "extern string " << cpp_tl_const_str(s) << ";" << NL; }); W << CloseFile(); W << OpenFile("tl_const_vars.cpp", "tl", false); W << ExternInclude(G->settings().runtime_headers.get()); W << Include("tl/tl_const_vars.h"); - std::for_each(tl_const_vars.begin(), tl_const_vars.end(), [&W](const std::string &s) { - W << "string " << cpp_tl_const_str(s) << ";" << NL; - }); + std::for_each(tl_const_vars.begin(), tl_const_vars.end(), [&W](const std::string& s) { W << "string " << cpp_tl_const_str(s) << ";" << NL; }); auto const_string_shifts = compile_raw_data(W, tl_const_vars); FunctionSignatureGenerator(W) << "void tl_str_const_init() " << BEGIN; size_t i = 0; - std::for_each(tl_const_vars.begin(), tl_const_vars.end(), [&](const std::string &s) { - W << cpp_tl_const_str(s) << ".assign_raw (&raw[" << const_string_shifts[i++] << "]);" << NL; - }); + std::for_each(tl_const_vars.begin(), tl_const_vars.end(), + [&](const std::string& s) { W << cpp_tl_const_str(s) << ".assign_raw (&raw[" << const_string_shifts[i++] << "]);" << NL; }); W << END << NL << NL; // to decode tl magics to strings at runtime, codegen everything @@ -221,36 +203,31 @@ void write_tl_query_handlers(CodeGenerator &W) { // see runtime/tl/tl_magics_decoding.cpp W << "static const unsigned int tl_magic_ids[" << tl->functions.size() << "] = " << BEGIN; - for (const auto &[magic, tl_fun] : tl->functions) { + for (const auto& [magic, tl_fun] : tl->functions) { W << fmt_format("{:#010x}U,", static_cast(tl_fun->id)) << NL; } W << END << ";" << NL; W << "static const char *tl_magic_names[" << tl->functions.size() << "] = " << BEGIN; - for (const auto &[magic, tl_fun] : tl->functions) { + for (const auto& [magic, tl_fun] : tl->functions) { W << "\"" << tl_fun->name.c_str() << "\"," << NL; } W << END << ";" << NL << NL; - W << "void tl_magic_fill_all_functions_impl(array &out) noexcept " << BEGIN - << "out.reserve(" << tl->functions.size() << ", false);" << NL - << "for (int i=0; i<" << tl->functions.size() << "; ++i)" << BEGIN - << "out.set_value(static_cast(tl_magic_ids[i]), string(tl_magic_names[i]));" << NL << END - << NL << END << NL; + W << "void tl_magic_fill_all_functions_impl(array &out) noexcept " << BEGIN << "out.reserve(" << tl->functions.size() << ", false);" << NL + << "for (int i=0; i<" << tl->functions.size() << "; ++i)" << BEGIN << "out.set_value(static_cast(tl_magic_ids[i]), string(tl_magic_names[i]));" + << NL << END << NL << END << NL; - W << "const char *tl_magic_convert_to_name_impl(unsigned int magic) noexcept " << BEGIN - << "for (int i=0; i<" << tl->functions.size() << "; ++i)" << BEGIN - << "if (tl_magic_ids[i] == magic) return tl_magic_names[i];" << NL << END - << "return \"__unknown__\";" - << NL << END << NL; + W << "const char *tl_magic_convert_to_name_impl(unsigned int magic) noexcept " << BEGIN << "for (int i=0; i<" << tl->functions.size() << "; ++i)" << BEGIN + << "if (tl_magic_ids[i] == magic) return tl_magic_names[i];" << NL << END << "return \"__unknown__\";" << NL << END << NL; W << CloseFile(); modules.clear(); modules_with_functions.clear(); } -} // namespace tl_gen +} // namespace tl2cpp -void TlSchemaToCpp::compile(CodeGenerator &W) const { +void TlSchemaToCpp::compile(CodeGenerator& W) const { tl2cpp::write_tl_query_handlers(W); } diff --git a/compiler/code-gen/files/tl2cpp/tl2cpp.h b/compiler/code-gen/files/tl2cpp/tl2cpp.h index ed6f5e1c2b..ddf982c485 100644 --- a/compiler/code-gen/files/tl2cpp/tl2cpp.h +++ b/compiler/code-gen/files/tl2cpp/tl2cpp.h @@ -8,5 +8,5 @@ #include "compiler/code-gen/code-generator.h" struct TlSchemaToCpp : CodeGenRootCmd { - void compile(CodeGenerator &W) const final; + void compile(CodeGenerator& W) const final; }; diff --git a/compiler/code-gen/files/tracing-autogen.cpp b/compiler/code-gen/files/tracing-autogen.cpp index 369d21994f..681be561a1 100644 --- a/compiler/code-gen/files/tracing-autogen.cpp +++ b/compiler/code-gen/files/tracing-autogen.cpp @@ -14,17 +14,15 @@ #include "compiler/data/function-data.h" #include "compiler/data/kphp-tracing-tags.h" - std::vector TracingAutogen::all_with_aggregate; std::vector TracingAutogen::all_aggregate_names; std::mutex TracingAutogen::mu; - // from BuiltinFuncID in runtime constexpr int _shift_for_branch = 16; constexpr int _shift_for_aggregate = 18; -void TracingAutogen::compile(CodeGenerator &W) const { +void TracingAutogen::compile(CodeGenerator& W) const { W << OpenFile{"_tracing_autogen.cpp"}; W << ExternInclude{G->settings().runtime_headers.get()}; @@ -39,7 +37,7 @@ void TracingAutogen::compile(CodeGenerator &W) const { for (FunctionPtr f : all_with_aggregate) { add_value(f_idx, f->kphp_tracing->span_title, f->name); if (!f->kphp_tracing->branches.empty()) { - for (const auto &[branch_num, cond_title] : f->kphp_tracing->branches) { + for (const auto& [branch_num, cond_title] : f->kphp_tracing->branches) { add_value((branch_num << _shift_for_branch) + f_idx, cond_title, std::to_string(branch_num)); } } @@ -64,7 +62,7 @@ void TracingAutogen::register_function_marked_kphp_tracing(FunctionPtr f) { } } -void TracingAutogen::codegen_runtime_func_guard_declaration(CodeGenerator &W, FunctionPtr f) { +void TracingAutogen::codegen_runtime_func_guard_declaration(CodeGenerator& W, FunctionPtr f) { kphp_assert(f->kphp_tracing); if (!f->kphp_tracing->is_aggregate()) { @@ -74,7 +72,7 @@ void TracingAutogen::codegen_runtime_func_guard_declaration(CodeGenerator &W, Fu } } -void TracingAutogen::codegen_runtime_func_guard_start(CodeGenerator &W, FunctionPtr f) { +void TracingAutogen::codegen_runtime_func_guard_start(CodeGenerator& W, FunctionPtr f) { if (G->is_output_mode_k2()) { // The current version of runtime-light does not support tracing return; @@ -85,8 +83,8 @@ void TracingAutogen::codegen_runtime_func_guard_start(CodeGenerator &W, Function return; } - auto it = std::lower_bound(all_with_aggregate.begin(), all_with_aggregate.end(), f, - [](FunctionPtr a, FunctionPtr b) { return a->name.compare(b->name) < 0; }); + auto it = + std::lower_bound(all_with_aggregate.begin(), all_with_aggregate.end(), f, [](FunctionPtr a, FunctionPtr b) { return a->name.compare(b->name) < 0; }); int func_id = it == all_with_aggregate.end() ? 0 : it - all_with_aggregate.begin() + 1; auto it_agg = std::lower_bound(all_aggregate_names.begin(), all_aggregate_names.end(), f->kphp_tracing->aggregate_name); @@ -96,8 +94,7 @@ void TracingAutogen::codegen_runtime_func_guard_start(CodeGenerator &W, Function } void TracingAutogen::finished_appending_and_prepare() { - std::sort(all_with_aggregate.begin(), all_with_aggregate.end(), - [](FunctionPtr a, FunctionPtr b) { return a->name.compare(b->name) < 0; }); + std::sort(all_with_aggregate.begin(), all_with_aggregate.end(), [](FunctionPtr a, FunctionPtr b) { return a->name.compare(b->name) < 0; }); std::set uniq_aggregates_sorted; for (FunctionPtr f : all_with_aggregate) { diff --git a/compiler/code-gen/files/tracing-autogen.h b/compiler/code-gen/files/tracing-autogen.h index c2627017fa..ea8b4ed35a 100644 --- a/compiler/code-gen/files/tracing-autogen.h +++ b/compiler/code-gen/files/tracing-autogen.h @@ -13,14 +13,16 @@ class CodeGenerator; class KphpTracingDeclarationMixin; struct TracingAutogen : CodeGenRootCmd { - void compile(CodeGenerator &W) const final; + void compile(CodeGenerator& W) const final; static void register_function_marked_kphp_tracing(FunctionPtr f); static void finished_appending_and_prepare(); - static bool empty() { return all_with_aggregate.empty(); } + static bool empty() { + return all_with_aggregate.empty(); + } - static void codegen_runtime_func_guard_declaration(CodeGenerator &W, FunctionPtr f); - static void codegen_runtime_func_guard_start(CodeGenerator &W, FunctionPtr f); + static void codegen_runtime_func_guard_declaration(CodeGenerator& W, FunctionPtr f); + static void codegen_runtime_func_guard_start(CodeGenerator& W, FunctionPtr f); private: static std::vector all_with_aggregate; diff --git a/compiler/code-gen/files/type-tagger.cpp b/compiler/code-gen/files/type-tagger.cpp index 0f71c89ab7..581c2698a9 100644 --- a/compiler/code-gen/files/type-tagger.cpp +++ b/compiler/code-gen/files/type-tagger.cpp @@ -16,16 +16,16 @@ #include "compiler/inferring/type-data.h" #include "compiler/kphp_assert.h" -TypeTagger::TypeTagger(std::vector &&forkable_types, std::vector &&waitable_types) noexcept - : forkable_types_(std::move(forkable_types)) - , waitable_types_(std::move(waitable_types)) {} +TypeTagger::TypeTagger(std::vector&& forkable_types, std::vector&& waitable_types) noexcept + : forkable_types_(std::move(forkable_types)), + waitable_types_(std::move(waitable_types)) {} IncludesCollector TypeTagger::collect_includes() const noexcept { IncludesCollector includes; - for (const auto *type : forkable_types_) { + for (const auto* type : forkable_types_) { includes.add_all_class_types(*type); } - for (const auto *type : waitable_types_) { + for (const auto* type : waitable_types_) { includes.add_all_class_types(*type); } return includes; @@ -72,13 +72,13 @@ std::map TypeTagger::collect_hash_of_types() const noexcept { }; }; - for (const auto *type : forkable_types_) { + for (const auto* type : forkable_types_) { sorted_types.emplace(type_out(type, gen_out_style::tagger)); } std::map hashes; - for (const auto &type : sorted_types) { + for (const auto& type : sorted_types) { const auto hash = static_cast(vk::std_hash(type)); kphp_assert(hash); kphp_assert(hashes.emplace(hash, type).second); @@ -87,7 +87,7 @@ std::map TypeTagger::collect_hash_of_types() const noexcept { return hashes; } -void TypeTagger::compile_tagger(CodeGenerator &W, const IncludesCollector &includes, const std::map &hash_of_types) const noexcept { +void TypeTagger::compile_tagger(CodeGenerator& W, const IncludesCollector& includes, const std::map& hash_of_types) const noexcept { W << OpenFile{"_tagger.cpp"}; W << ExternInclude{G->settings().runtime_headers.get()}; W << includes << NL; @@ -145,8 +145,8 @@ void TypeTagger::compile_loader_header(CodeGenerator& W, const IncludesCollector W << CloseFile{}; } -template -static void compile_loader_instantiations_batch(CodeGenerator &W, const IncludesCollector &includes, It begin, It end, std::size_t batch) noexcept { +template +static void compile_loader_instantiations_batch(CodeGenerator& W, const IncludesCollector& includes, It begin, It end, std::size_t batch) noexcept { W << OpenFile{fmt_format("_loader_instantiations{}.cpp", batch)}; W << ExternInclude{G->settings().runtime_headers.get()}; W << includes << NL; @@ -165,12 +165,12 @@ static void compile_loader_instantiations_batch(CodeGenerator &W, const Includes W << CloseFile{}; } -void TypeTagger::compile_loader_instantiations(CodeGenerator &W) const noexcept { +void TypeTagger::compile_loader_instantiations(CodeGenerator& W) const noexcept { IncludesCollector loader_includes; loader_includes.add_raw_filename_include(loader_file_); std::set waitable_types_str; - for (const auto *type : waitable_types_) { + for (const auto* type : waitable_types_) { waitable_types_str.emplace(type_out(type, gen_out_style::tagger)); } @@ -184,12 +184,12 @@ void TypeTagger::compile_loader_instantiations(CodeGenerator &W) const noexcept } } -void TypeTagger::compile_loader(CodeGenerator &W, const IncludesCollector &includes, const std::map &hash_of_types) const noexcept { +void TypeTagger::compile_loader(CodeGenerator& W, const IncludesCollector& includes, const std::map& hash_of_types) const noexcept { compile_loader_header(W, includes, hash_of_types); compile_loader_instantiations(W); } -void TypeTagger::compile(CodeGenerator &W) const { +void TypeTagger::compile(CodeGenerator& W) const { const auto includes = collect_includes(); const auto hash_of_types = collect_hash_of_types(); diff --git a/compiler/code-gen/files/type-tagger.h b/compiler/code-gen/files/type-tagger.h index 1912f284f8..2ba9fd0f82 100644 --- a/compiler/code-gen/files/type-tagger.h +++ b/compiler/code-gen/files/type-tagger.h @@ -15,19 +15,19 @@ class TypeData; struct IncludesCollector; struct TypeTagger : CodeGenRootCmd { - TypeTagger(std::vector &&forkable_types, std::vector &&waitable_types) noexcept; - void compile(CodeGenerator &W) const final; + TypeTagger(std::vector&& forkable_types, std::vector&& waitable_types) noexcept; + void compile(CodeGenerator& W) const final; private: IncludesCollector collect_includes() const noexcept; std::map collect_hash_of_types() const noexcept; - void compile_tagger(CodeGenerator &W, const IncludesCollector &includes, const std::map &hash_of_types) const noexcept; - void compile_loader_header(CodeGenerator &W, const IncludesCollector &includes, const std::map &hash_of_types) const noexcept; - void compile_loader_instantiations(CodeGenerator &W) const noexcept; - void compile_loader(CodeGenerator &W, const IncludesCollector &includes, const std::map &hash_of_types) const noexcept; + void compile_tagger(CodeGenerator& W, const IncludesCollector& includes, const std::map& hash_of_types) const noexcept; + void compile_loader_header(CodeGenerator& W, const IncludesCollector& includes, const std::map& hash_of_types) const noexcept; + void compile_loader_instantiations(CodeGenerator& W) const noexcept; + void compile_loader(CodeGenerator& W, const IncludesCollector& includes, const std::map& hash_of_types) const noexcept; constexpr static std::size_t loader_split_granularity_{20}; const std::string loader_file_{"_loader.h"}; - const std::vector forkable_types_; - const std::vector waitable_types_; + const std::vector forkable_types_; + const std::vector waitable_types_; }; diff --git a/compiler/code-gen/gen-out-style.h b/compiler/code-gen/gen-out-style.h index 6f760847a7..fac0c661cd 100644 --- a/compiler/code-gen/gen-out-style.h +++ b/compiler/code-gen/gen-out-style.h @@ -6,9 +6,9 @@ // enum for type_out() enum class gen_out_style { - cpp, // for C++ code - txt, // for functions.txt in lib export and some type comparison todo get rid of it - tagger // for C++ code inside storage tagger (types available from forks, futures are ints there) + cpp, // for C++ code + txt, // for functions.txt in lib export and some type comparison todo get rid of it + tagger // for C++ code inside storage tagger (types available from forks, futures are ints there) // to output a type to console, use type->as_human_readable(), not type_out() }; diff --git a/compiler/code-gen/includes.cpp b/compiler/code-gen/includes.cpp index 7cbf272c2a..c17b1cadc8 100644 --- a/compiler/code-gen/includes.cpp +++ b/compiler/code-gen/includes.cpp @@ -11,26 +11,26 @@ #include "compiler/data/function-data.h" #include "compiler/data/var-data.h" -ExternInclude::ExternInclude(vk::string_view file_name) : - file_name(file_name) { +ExternInclude::ExternInclude(vk::string_view file_name) + : file_name(file_name) { kphp_assert(!file_name.empty()); } -void ExternInclude::compile(CodeGenerator &W) const { +void ExternInclude::compile(CodeGenerator& W) const { W << "#include \"" << file_name << "\"" << NL; } -void Include::compile(CodeGenerator &W) const { +void Include::compile(CodeGenerator& W) const { W.add_include(static_cast(file_name)); ExternInclude::compile(W); } -void LibInclude::compile(CodeGenerator &W) const { +void LibInclude::compile(CodeGenerator& W) const { W.add_lib_include(static_cast(absolute_path)); ExternInclude::compile(W); } -static std::string make_relative_path(const std::string &source_path, const std::string &to_include_path) noexcept { +static std::string make_relative_path(const std::string& source_path, const std::string& to_include_path) noexcept { std::size_t idx = 0; while ((idx < source_path.size()) && (idx < to_include_path.size()) && (source_path[idx] == to_include_path[idx])) { ++idx; @@ -47,7 +47,7 @@ static std::string make_relative_path(const std::string &source_path, const std: return relative_path; } -void IncludesCollector::add_function_body_depends(const FunctionPtr &function) { +void IncludesCollector::add_function_body_depends(const FunctionPtr& function) { for (auto to_include : function->dep) { if (to_include == function) { continue; @@ -78,24 +78,24 @@ void IncludesCollector::add_function_body_depends(const FunctionPtr &function) { add_var_signature_depends(global_var); } - if (function->tl_common_h_dep) { // functions that use a typed TL RPC need to see t_ReqResult during the compilation + if (function->tl_common_h_dep) { // functions that use a typed TL RPC need to see t_ReqResult during the compilation kphp_error(!G->settings().tl_schema_file.get().empty(), "tl schema not given as -T option for compilation"); internal_headers_.emplace("tl/common.h"); } } -void IncludesCollector::add_function_signature_depends(const FunctionPtr &function) { +void IncludesCollector::add_function_signature_depends(const FunctionPtr& function) { add_all_class_types(*function->tinf_node.get_type()); - for (const auto ¶m : function->param_ids) { + for (const auto& param : function->param_ids) { add_all_class_types(*param->tinf_node.get_type()); } } -void IncludesCollector::add_class_include(const ClassPtr &klass) { +void IncludesCollector::add_class_include(const ClassPtr& klass) { classes_.emplace(klass); } -void IncludesCollector::add_class_forward_declaration(const ClassPtr &klass) { +void IncludesCollector::add_class_forward_declaration(const ClassPtr& klass) { // CData classes do not require forward declarations, they're bundled // with their associated FFI scope class in a single header file if (!klass->is_ffi_cdata()) { @@ -103,15 +103,15 @@ void IncludesCollector::add_class_forward_declaration(const ClassPtr &klass) { } } -void IncludesCollector::add_var_signature_forward_declarations(const VarPtr &var) { +void IncludesCollector::add_var_signature_forward_declarations(const VarPtr& var) { std::unordered_set all_classes; var->tinf_node.get_type()->get_all_class_types_inside(all_classes); - for (auto klass: all_classes) { + for (auto klass : all_classes) { add_class_forward_declaration(klass); } } -void IncludesCollector::add_base_classes_include(const ClassPtr &klass) { +void IncludesCollector::add_base_classes_include(const ClassPtr& klass) { classes_.insert(klass->implements.cbegin(), klass->implements.cend()); if (klass->parent_class && klass->parent_class->does_need_codegen()) { @@ -119,17 +119,17 @@ void IncludesCollector::add_base_classes_include(const ClassPtr &klass) { } } -void IncludesCollector::add_var_signature_depends(const VarPtr &var) { +void IncludesCollector::add_var_signature_depends(const VarPtr& var) { add_all_class_types(*var->tinf_node.get_type()); } -void IncludesCollector::add_all_class_types(const TypeData &tinf_type) { +void IncludesCollector::add_all_class_types(const TypeData& tinf_type) { if (tinf_type.has_class_type_inside()) { tinf_type.get_all_class_types_inside(classes_); } } -void IncludesCollector::add_raw_filename_include(const std::string &file_name) { +void IncludesCollector::add_raw_filename_include(const std::string& file_name) { internal_headers_.emplace(file_name); } @@ -142,7 +142,7 @@ void IncludesCollector::add_vertex_depends(VertexPtr v) { } if (auto as_func_call = v.try_as()) { if (as_func_call->func_id) { - const auto &header_full_name = as_func_call->func_id->header_full_name; + const auto& header_full_name = as_func_call->func_id->header_full_name; if (!header_full_name.empty()) { add_raw_filename_include(as_func_call->func_id->header_full_name); } @@ -154,15 +154,15 @@ void IncludesCollector::add_vertex_depends(VertexPtr v) { } } -void IncludesCollector::compile(CodeGenerator &W) const { - for (const auto &lib_header : lib_headers_) { +void IncludesCollector::compile(CodeGenerator& W) const { + for (const auto& lib_header : lib_headers_) { if (!prev_headers_.count(lib_header.first)) { W << LibInclude(lib_header.first, lib_header.second); } } std::set class_headers; - for (const auto &klass : classes_) { + for (const auto& klass : classes_) { ClassPtr class_to_include; if (klass->ffi_class_mixin) { // FFI CData classes (structs really) are defined at their scope class header @@ -174,28 +174,26 @@ void IncludesCollector::compile(CodeGenerator &W) const { class_headers.emplace(class_to_include->get_subdir() + "/" + class_to_include->h_filename); } } - for (const auto &class_header : class_headers) { + for (const auto& class_header : class_headers) { W << Include(class_header); } std::set class_forward_declarations; - for (const auto &klass : forward_declarations_) { - if (!prev_classes_forward_declared_.count(klass) && - !prev_classes_.count(klass) && - !classes_.count(klass)) { + for (const auto& klass : forward_declarations_) { + if (!prev_classes_forward_declared_.count(klass) && !prev_classes_.count(klass) && !classes_.count(klass)) { class_forward_declarations.emplace(klass->src_name); } } if (!class_forward_declarations.empty()) { W << OpenNamespace(); - for (const auto &class_name : class_forward_declarations) { + for (const auto& class_name : class_forward_declarations) { W << "struct " << class_name << ";" << NL; } W << CloseNamespace(); } - for (const auto &internal_header : internal_headers_) { + for (const auto& internal_header : internal_headers_) { if (!prev_headers_.count(internal_header)) { W << Include(internal_header); } @@ -210,7 +208,7 @@ void IncludesCollector::start_next_block() { classes_.clear(); prev_headers_.insert(internal_headers_.begin(), internal_headers_.end()); - for (const auto &header : lib_headers_) { + for (const auto& header : lib_headers_) { prev_headers_.insert(header.first); } internal_headers_.clear(); diff --git a/compiler/code-gen/includes.h b/compiler/code-gen/includes.h index aa202ca7f9..92c4b9b53d 100644 --- a/compiler/code-gen/includes.h +++ b/compiler/code-gen/includes.h @@ -10,7 +10,7 @@ struct ExternInclude { explicit ExternInclude(vk::string_view file_name); - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; protected: vk::string_view file_name; @@ -18,35 +18,34 @@ struct ExternInclude { struct Include : private ExternInclude { using ExternInclude::ExternInclude; - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; }; struct LibInclude : private ExternInclude { LibInclude(vk::string_view absolute_path, vk::string_view relative_path) noexcept - : ExternInclude(relative_path) - , absolute_path(absolute_path) {} - void compile(CodeGenerator &W) const; + : ExternInclude(relative_path), + absolute_path(absolute_path) {} + void compile(CodeGenerator& W) const; vk::string_view absolute_path; }; struct IncludesCollector { public: - void add_function_body_depends(const FunctionPtr &function); - void add_function_signature_depends(const FunctionPtr &function); - void add_var_signature_depends(const VarPtr &var); + void add_function_body_depends(const FunctionPtr& function); + void add_function_signature_depends(const FunctionPtr& function); + void add_var_signature_depends(const VarPtr& var); void add_vertex_depends(VertexPtr v); + void add_class_forward_declaration(const ClassPtr& klass); + void add_var_signature_forward_declarations(const VarPtr& var); - void add_class_forward_declaration(const ClassPtr &klass); - void add_var_signature_forward_declarations(const VarPtr &var); + void add_class_include(const ClassPtr& klass); + void add_base_classes_include(const ClassPtr& klass); + void add_all_class_types(const TypeData& tinf_type); - void add_class_include(const ClassPtr &klass); - void add_base_classes_include(const ClassPtr &klass); - void add_all_class_types(const TypeData &tinf_type); + void add_raw_filename_include(const std::string& file_name); - void add_raw_filename_include(const std::string &file_name); - - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; void start_next_block(); diff --git a/compiler/code-gen/namespace.h b/compiler/code-gen/namespace.h index 61011f899d..261afa41f4 100644 --- a/compiler/code-gen/namespace.h +++ b/compiler/code-gen/namespace.h @@ -10,11 +10,13 @@ #include "compiler/compiler-core.h" struct OpenNamespace { - OpenNamespace() : OpenNamespace(G->get_global_namespace()) { } + OpenNamespace() + : OpenNamespace(G->get_global_namespace()) {} - explicit OpenNamespace(const std::string &ns) : ns_(ns) {} + explicit OpenNamespace(const std::string& ns) + : ns_(ns) {} - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { if (!ns_.empty()) { kphp_assert(!W.get_context().namespace_opened); W << "namespace " << ns_ << " {" << NL; @@ -23,11 +25,11 @@ struct OpenNamespace { } private: - const std::string &ns_; + const std::string& ns_; }; struct CloseNamespace { - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { if (W.get_context().namespace_opened) { W << "}" << NL << NL; W.get_context().namespace_opened = false; diff --git a/compiler/code-gen/naming.h b/compiler/code-gen/naming.h index 815159db22..a5d906ffb6 100644 --- a/compiler/code-gen/naming.h +++ b/compiler/code-gen/naming.h @@ -15,38 +15,37 @@ struct LabelName { int label_id; - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { W << "label" << label_id; } }; struct MacroBegin { - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { W.get_context().inside_macro++; W << "("; } }; struct MacroEnd { - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { W.get_context().inside_macro--; W << ")"; } }; struct TypeName { - const TypeData *type; + const TypeData* type; gen_out_style style; - explicit TypeName(const TypeData *type, gen_out_style style = gen_out_style::cpp) : - type(type), - style(style) { - } + explicit TypeName(const TypeData* type, gen_out_style style = gen_out_style::cpp) + : type(type), + style(style) {} - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { std::string s = type_out(type, style); if (W.get_context().inside_macro) { while (s.find(',') != std::string::npos) { - s = s.replace(s.find(','), 1, " COMMA "); // tuples have it + s = s.replace(s.find(','), 1, " COMMA "); // tuples have it } } W << s; @@ -55,15 +54,14 @@ struct TypeName { class FunctionSignatureGenerator { public: - explicit FunctionSignatureGenerator(CodeGenerator &W) noexcept - : W_(W) { - } - - FunctionSignatureGenerator(const FunctionSignatureGenerator &) = delete; - FunctionSignatureGenerator& operator=(const FunctionSignatureGenerator &) = delete; + explicit FunctionSignatureGenerator(CodeGenerator& W) noexcept + : W_(W) {} + + FunctionSignatureGenerator(const FunctionSignatureGenerator&) = delete; + FunctionSignatureGenerator& operator=(const FunctionSignatureGenerator&) = delete; - template - FunctionSignatureGenerator &&operator<<(const T &value) && noexcept { + template + FunctionSignatureGenerator&& operator<<(const T& value) && noexcept { if (is_empty_) { if (inline_) { W_ << "inline "; @@ -78,11 +76,11 @@ class FunctionSignatureGenerator { return std::move(*this); } - FunctionSignatureGenerator &&operator<<(const OpenBlock &value) && noexcept { + FunctionSignatureGenerator&& operator<<(const OpenBlock& value) && noexcept { return generate_specifiers(value); } - FunctionSignatureGenerator &&operator<<(const SemicolonAndNL &value) && noexcept { + FunctionSignatureGenerator&& operator<<(const SemicolonAndNL& value) && noexcept { return generate_specifiers(value); } @@ -90,61 +88,61 @@ class FunctionSignatureGenerator { generate_specifiers(""); } - FunctionSignatureGenerator &&set_is_virtual(bool new_value = true) && noexcept { + FunctionSignatureGenerator&& set_is_virtual(bool new_value = true) && noexcept { virtual_ = new_value; return std::move(*this); } - FunctionSignatureGenerator &&set_noexcept(bool new_value = true) && noexcept { + FunctionSignatureGenerator&& set_noexcept(bool new_value = true) && noexcept { noexcept_ = new_value; return std::move(*this); } - FunctionSignatureGenerator &&set_const_this(bool new_value = true) && noexcept { + FunctionSignatureGenerator&& set_const_this(bool new_value = true) && noexcept { const_this_ = new_value; return std::move(*this); } - FunctionSignatureGenerator &&set_overridden(bool new_value = true) && noexcept { + FunctionSignatureGenerator&& set_overridden(bool new_value = true) && noexcept { overridden_ = new_value; return std::move(*this); } - FunctionSignatureGenerator &&set_final(bool new_value = true) && noexcept { + FunctionSignatureGenerator&& set_final(bool new_value = true) && noexcept { final_ = new_value; return std::move(*this); } - FunctionSignatureGenerator &&set_pure_virtual(bool new_value = true) && noexcept { + FunctionSignatureGenerator&& set_pure_virtual(bool new_value = true) && noexcept { pure_virtual_ = new_value; return std::move(*this); } - FunctionSignatureGenerator &&set_inline(bool new_value = true) && noexcept { + FunctionSignatureGenerator&& set_inline(bool new_value = true) && noexcept { inline_ = new_value; return std::move(*this); } - FunctionSignatureGenerator &&set_definition(bool new_value = true) && noexcept { + FunctionSignatureGenerator&& set_definition(bool new_value = true) && noexcept { definition_ = new_value; return std::move(*this); } - FunctionSignatureGenerator &&clear_all() &&noexcept { + FunctionSignatureGenerator&& clear_all() && noexcept { return std::move(*this) - .set_is_virtual(false) - .set_noexcept(false) - .set_const_this(false) - .set_overridden(false) - .set_final(false) - .set_pure_virtual(false) - .set_inline(false) - .set_definition(false); + .set_is_virtual(false) + .set_noexcept(false) + .set_const_this(false) + .set_overridden(false) + .set_final(false) + .set_pure_virtual(false) + .set_inline(false) + .set_definition(false); } private: template - FunctionSignatureGenerator &&generate_specifiers(const T &value) noexcept { + FunctionSignatureGenerator&& generate_specifiers(const T& value) noexcept { if (!specifiers_generated_) { if (const_this_) { W_ << " const "; @@ -177,7 +175,7 @@ class FunctionSignatureGenerator { bool is_empty_ = true; bool specifiers_generated_ = false; - CodeGenerator &W_; + CodeGenerator& W_; bool virtual_ = false; bool const_this_ = false; @@ -191,31 +189,30 @@ class FunctionSignatureGenerator { struct FunctionName { FunctionPtr function; - explicit FunctionName(FunctionPtr function) : - function(function) { - } + explicit FunctionName(FunctionPtr function) + : function(function) {} - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { W << "f$" << function->name; } }; struct FunctionForkName { FunctionPtr function; - inline FunctionForkName(FunctionPtr function) : function(function) {} + inline FunctionForkName(FunctionPtr function) + : function(function) {} - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { W << "f$fork$" << function->name; } }; struct FunctionClassName { FunctionPtr function; - explicit FunctionClassName(FunctionPtr function) : - function(function) { - } + explicit FunctionClassName(FunctionPtr function) + : function(function) {} - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { W << "c$" << function->name; } }; @@ -225,14 +222,16 @@ struct VarName { vk::string_view name; VarName() = default; - explicit VarName(VarPtr var) : var(var) {} - explicit VarName(vk::string_view name) : name{name} {} + explicit VarName(VarPtr var) + : var(var) {} + explicit VarName(vk::string_view name) + : name{name} {} bool empty() const { return !var && name.empty(); } - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { if (!name.empty()) { W << name; } else { diff --git a/compiler/code-gen/raw-data.cpp b/compiler/code-gen/raw-data.cpp index 4f0d1f76cf..b66bd1a4c8 100644 --- a/compiler/code-gen/raw-data.cpp +++ b/compiler/code-gen/raw-data.cpp @@ -7,58 +7,58 @@ #include "compiler/code-gen/vertex-compiler.h" #include "compiler/const-manipulations.h" -void RawString::compile(CodeGenerator &W) const { +void RawString::compile(CodeGenerator& W) const { W << "\""; for (size_t i = 0; i < str.size(); i++) { switch (str[i]) { - case '\r': - W << "\\r"; - break; - case '\n': - W << "\\n"; - break; - case '"': - W << "\\\""; - break; - case '\\': - W << "\\\\"; - break; - case '\'': - W << "\\\'"; - break; - case 0: { - if (str[i + 1] < '0' || str[i + 1] > '9') { - W << "\\0"; - } else { - W << "\\000"; - } - break; + case '\r': + W << "\\r"; + break; + case '\n': + W << "\\n"; + break; + case '"': + W << "\\\""; + break; + case '\\': + W << "\\\\"; + break; + case '\'': + W << "\\\'"; + break; + case 0: { + if (str[i + 1] < '0' || str[i + 1] > '9') { + W << "\\0"; + } else { + W << "\\000"; + } + break; + } + case '\a': + W << "\\a"; + break; + case '\b': + W << "\\b"; + break; + case '\f': + W << "\\f"; + break; + case '\t': + W << "\\t"; + break; + case '\v': + W << "\\v"; + break; + default: + if ((unsigned char)str[i] < 32) { + std::string tmp = "\\0"; + tmp += (char)('0' + (str[i] / 8)); + tmp += (char)('0' + (str[i] % 8)); + W << tmp; + } else { + W << str[i]; } - case '\a': - W << "\\a"; - break; - case '\b': - W << "\\b"; - break; - case '\f': - W << "\\f"; - break; - case '\t': - W << "\\t"; - break; - case '\v': - W << "\\v"; - break; - default: - if ((unsigned char)str[i] < 32) { - std::string tmp = "\\0"; - tmp += (char)('0' + (str[i] / 8)); - tmp += (char)('0' + (str[i] % 8)); - W << tmp; - } else { - W << str[i]; - } - break; + break; } } W << "\""; @@ -71,7 +71,7 @@ DepLevelContainer::const_iterator DepLevelContainer::begin() const { return {*this, begin_idx, 0}; } -const std::vector &DepLevelContainer::vars_by_dep_level(size_t dep_level) const { +const std::vector& DepLevelContainer::vars_by_dep_level(size_t dep_level) const { if (dep_level >= max_dep_level()) { static const auto EMPTY = std::vector{}; return EMPTY; @@ -88,7 +88,7 @@ void DepLevelContainer::add(VarPtr v) { mapping[dep_level].emplace_back(v); } -DepLevelContainer::const_iterator &DepLevelContainer::const_iterator::operator++() { +DepLevelContainer::const_iterator& DepLevelContainer::const_iterator::operator++() { ++internal_index; while (dep_level < owner.mapping.size() && internal_index >= owner.mapping[dep_level].size()) { internal_index = 0; @@ -104,7 +104,7 @@ static inline int array_len() { return (8 * sizeof(int)) / sizeof(double); } -std::vector compile_arrays_raw_representation(const DepLevelContainer &const_raw_array_vars, CodeGenerator &W) { +std::vector compile_arrays_raw_representation(const DepLevelContainer& const_raw_array_vars, CodeGenerator& W) { if (const_raw_array_vars.empty()) { return {}; } @@ -117,8 +117,7 @@ std::vector compile_arrays_raw_representation(const DepLevelContainer &cons for (auto var_it : const_raw_array_vars) { VertexAdaptor vertex = var_it->init_val.as(); - const TypeData *vertex_inner_type = vertex->tinf_node.get_type()->lookup_at_any_key(); - + const TypeData* vertex_inner_type = vertex->tinf_node.get_type()->lookup_at_any_key(); int array_size = vertex->size(); int array_len_in_doubles = -1; @@ -137,12 +136,9 @@ std::vector compile_arrays_raw_representation(const DepLevelContainer &cons if (shift != 0) { W << ","; } else { - W << "static_assert(sizeof(array::iterator::inner_type) == " << array_len() * sizeof(double) << ", \"size of array_len should be compatible with runtime array_inner\");" << NL; - W << "static const union " << BEGIN - << "struct { uint32_t a; uint32_t b; } is;" << NL - << "double d;" << NL - << "int64_t i64;" << NL - << END + W << "static_assert(sizeof(array::iterator::inner_type) == " << array_len() * sizeof(double) + << ", \"size of array_len should be compatible with runtime array_inner\");" << NL; + W << "static const union " << BEGIN << "struct { uint32_t a; uint32_t b; } is;" << NL << "double d;" << NL << "int64_t i64;" << NL << END << " raw_arrays[] = { "; } @@ -181,4 +177,3 @@ std::vector compile_arrays_raw_representation(const DepLevelContainer &cons return shifts; } - diff --git a/compiler/code-gen/raw-data.h b/compiler/code-gen/raw-data.h index 1c1989708b..98524515a5 100644 --- a/compiler/code-gen/raw-data.h +++ b/compiler/code-gen/raw-data.h @@ -10,8 +10,8 @@ #include "common/php-functions.h" #include "compiler/code-gen/code-generator.h" #include "compiler/code-gen/common.h" -#include "compiler/vertex.h" #include "compiler/data/var-data.h" +#include "compiler/vertex.h" struct DepLevelContainer { DepLevelContainer() { @@ -19,27 +19,27 @@ struct DepLevelContainer { } struct const_iterator { - const_iterator(const DepLevelContainer &owner, size_t dep_level, size_t internal_index) - : owner(owner) - , dep_level(dep_level) - , internal_index(internal_index) {} + const_iterator(const DepLevelContainer& owner, size_t dep_level, size_t internal_index) + : owner(owner), + dep_level(dep_level), + internal_index(internal_index) {} - const VarPtr &operator*() { + const VarPtr& operator*() { return owner.mapping[dep_level][internal_index]; } - const_iterator &operator++(); + const_iterator& operator++(); - bool operator==(const const_iterator &oth) const { + bool operator==(const const_iterator& oth) const { return std::make_tuple(&owner, dep_level, internal_index) == std::make_tuple(&oth.owner, oth.dep_level, oth.internal_index); } - bool operator!=(const const_iterator &oth) const { + bool operator!=(const const_iterator& oth) const { return !(*this == oth); } private: - const DepLevelContainer &owner; + const DepLevelContainer& owner; size_t dep_level; size_t internal_index; }; @@ -62,7 +62,7 @@ struct DepLevelContainer { return mapping.size(); } - const std::vector &vars_by_dep_level(size_t dep_level) const; + const std::vector& vars_by_dep_level(size_t dep_level) const; void add(VarPtr v); @@ -75,19 +75,18 @@ struct DepLevelContainer { class RawString { public: - explicit RawString(vk::string_view str) : - str(str) { - } + explicit RawString(vk::string_view str) + : str(str) {} - void compile(CodeGenerator &W) const; + void compile(CodeGenerator& W) const; private: std::string str; }; -std::vector compile_arrays_raw_representation(const DepLevelContainer &const_raw_array_vars, CodeGenerator &W); +std::vector compile_arrays_raw_representation(const DepLevelContainer& const_raw_array_vars, CodeGenerator& W); -//returns len of raw string representation or -1 on error +// returns len of raw string representation or -1 on error inline int string_raw_len(int src_len) { if (src_len < 0 || src_len >= (1 << 30) - 13) { return -1; @@ -96,13 +95,13 @@ inline int string_raw_len(int src_len) { return src_len + 13; } -//returns len of raw string representation and writes it to dest or returns -1 on error -inline int string_raw(char *dest, int dest_len, const char *src, int src_len) { +// returns len of raw string representation and writes it to dest or returns -1 on error +inline int string_raw(char* dest, int dest_len, const char* src, int src_len) { int raw_len = string_raw_len(src_len); if (raw_len == -1 || raw_len > dest_len) { return -1; } - int *dest_int = reinterpret_cast (dest); + int* dest_int = reinterpret_cast(dest); dest_int[0] = src_len; dest_int[1] = src_len; dest_int[2] = ExtraRefCnt::for_global_const; @@ -112,22 +111,22 @@ inline int string_raw(char *dest, int dest_len, const char *src, int src_len) { return raw_len; } -template -std::vector compile_raw_data(CodeGenerator &W, const Container &values) { +template +std::vector compile_raw_data(CodeGenerator& W, const Container& values) { std::string raw_data; std::vector const_string_shifts(values.size()); int ii = 0; - for (const auto &s : values) { + for (const auto& s : values) { int shift_to_align = (((int)raw_data.size() + 7) & -8) - (int)raw_data.size(); if (shift_to_align != 0) { raw_data.append(shift_to_align, 0); } int raw_len = string_raw_len(static_cast(s.size())); - kphp_assert (raw_len != -1); + kphp_assert(raw_len != -1); const_string_shifts[ii] = (int)raw_data.size(); raw_data.append(raw_len, 0); int err = string_raw(&raw_data[const_string_shifts[ii]], raw_len, s.c_str(), (int)s.size()); - kphp_assert (err == raw_len); + kphp_assert(err == raw_len); ii++; } if (!raw_data.empty()) { @@ -135,4 +134,3 @@ std::vector compile_raw_data(CodeGenerator &W, const Container &values) { } return const_string_shifts; } - diff --git a/compiler/code-gen/vertex-compiler.cpp b/compiler/code-gen/vertex-compiler.cpp index 84e5a000f0..a8b4e9c60f 100644 --- a/compiler/code-gen/vertex-compiler.cpp +++ b/compiler/code-gen/vertex-compiler.cpp @@ -42,7 +42,7 @@ namespace { struct IntLit { vk::string_view value; - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { if (unlikely(value == "-9223372036854775808")) { // avoid "integer overflow" warning for PHP_INT_MIN values W << "(-9223372036854775807_i64 - 1_i64)"; @@ -58,10 +58,11 @@ struct IntLit { struct TmpExpr { VertexPtr root; - TmpExpr(VertexPtr root) : root{root} {} + TmpExpr(VertexPtr root) + : root{root} {} - const TypeData *get_type() { - const auto *type = tinf::get_type(root); + const TypeData* get_type() { + const auto* type = tinf::get_type(root); if (type->ptype() == tp_tmp_string) { // tmp_string must be materialized if it's used as an intermediate value // tmp_string is never optional, so we don't have to worry about the flags @@ -70,8 +71,8 @@ struct TmpExpr { return type; } - void compile(CodeGenerator &W) const { - const auto *type = tinf::get_type(root); + void compile(CodeGenerator& W) const { + const auto* type = tinf::get_type(root); if (type->ptype() == tp_tmp_string) { W << "materialize_tmp_string(" << root << ")"; return; @@ -85,7 +86,7 @@ struct Operand { Operation parent_type; bool is_left; - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { int priority = OpInfo::priority(parent_type); bool left_to_right = OpInfo::fixity(parent_type) == left_opp; @@ -110,17 +111,15 @@ struct TupleGetIndex { VertexPtr tuple; std::string int_index; - TupleGetIndex(VertexPtr tuple, std::string int_index) : - tuple(tuple), - int_index(std::move(int_index)) { - } + TupleGetIndex(VertexPtr tuple, std::string int_index) + : tuple(tuple), + int_index(std::move(int_index)) {} - TupleGetIndex(VertexPtr tuple, VertexPtr key) : - tuple(tuple), - int_index(VertexUtil::get_actual_value(key)->get_string()) { - } + TupleGetIndex(VertexPtr tuple, VertexPtr key) + : tuple(tuple), + int_index(VertexUtil::get_actual_value(key)->get_string()) {} - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { W << "std::get<" << int_index << ">(" << tuple << ")"; } }; @@ -129,17 +128,15 @@ struct ShapeGetIndex { VertexPtr shape; std::string index; - ShapeGetIndex(VertexPtr shape, std::string index) : - shape(shape), - index(std::move(index)) { - } + ShapeGetIndex(VertexPtr shape, std::string index) + : shape(shape), + index(std::move(index)) {} - ShapeGetIndex(VertexPtr shape, VertexPtr key) : - shape(shape), - index(VertexUtil::get_actual_value(key)->get_string()) { - } + ShapeGetIndex(VertexPtr shape, VertexPtr key) + : shape(shape), + index(VertexUtil::get_actual_value(key)->get_string()) {} - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { W << shape << ".get<" << static_cast(string_hash(index.c_str(), index.size())) << "UL>()"; } }; @@ -147,7 +144,7 @@ struct ShapeGetIndex { struct AsSeq { VertexAdaptor root; - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { for (auto i : *root) { if (vk::none_of_equal(i->type(), op_var, op_empty)) { W << i << ";" << NL; @@ -159,7 +156,7 @@ struct AsSeq { struct Label { int label_id; - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { if (label_id != 0) { W << NL << LabelName{label_id} << ":;" << NL; } @@ -171,24 +168,20 @@ struct CycleBody { int continue_label_id; int break_label_id; - void compile(CodeGenerator &W) const { - W << BEGIN << - AsSeq{body} << - Label{continue_label_id} << - END << - Label{break_label_id}; + void compile(CodeGenerator& W) const { + W << BEGIN << AsSeq{body} << Label{continue_label_id} << END << Label{break_label_id}; } }; struct EmptyReturn { // TODO: it's copypasted to compile_return - void compile(CodeGenerator &W) const { - CGContext &context = W.get_context(); - const TypeData *tp = tinf::get_type(context.parent_func, -1); + void compile(CodeGenerator& W) const { + CGContext& context = W.get_context(); + const TypeData* tp = tinf::get_type(context.parent_func, -1); if (G->is_output_mode_k2()) { const std::string_view return_stmnt = context.interruptible_flag ? "co_return" : "return"; - const TypeData *return_t = W.get_context().null_coalescing_rhs_t == nullptr ? tp : W.get_context().null_coalescing_rhs_t; + const TypeData* return_t = W.get_context().null_coalescing_rhs_t == nullptr ? tp : W.get_context().null_coalescing_rhs_t; W << return_stmnt << "(" << TypeName(return_t) << "())"; return; } @@ -215,9 +208,9 @@ struct EmptyReturn { }; struct ThrowAction { - //TODO: some interface for context? - static void compile(CodeGenerator &W) { - CGContext &context = W.get_context(); + // TODO: some interface for context? + static void compile(CodeGenerator& W) { + CGContext& context = W.get_context(); if (context.catch_labels.empty() || context.catch_labels.back().empty()) { W << EmptyReturn(); } else { @@ -227,31 +220,31 @@ struct ThrowAction { } }; -void compile_prefix_op(VertexAdaptor root, CodeGenerator &W) { +void compile_prefix_op(VertexAdaptor root, CodeGenerator& W) { W << OpInfo::str(root->type()) << Operand{root->expr(), root->type(), true}; } -void compile_postfix_op(VertexAdaptor root, CodeGenerator &W) { +void compile_postfix_op(VertexAdaptor root, CodeGenerator& W) { W << Operand{root->expr(), root->type(), true} << OpInfo::str(root->type()); } -void compile_ffi_c2php(VertexPtr expr, bool is_ref, const TypeHint *php_type, CodeGenerator &W) { - if (const FFIType *ffi_type = FFIRoot::get_ffi_type(php_type)) { +void compile_ffi_c2php(VertexPtr expr, bool is_ref, const TypeHint* php_type, CodeGenerator& W) { + if (const FFIType* ffi_type = FFIRoot::get_ffi_type(php_type)) { if (ffi_type->kind == FFITypeKind::Array && ffi_type->num != -1) { W << "ffi_c2php_array(" << expr << ", " << ffi_type->num << ")"; return; } } - const char *func = is_ref ? "ffi_c2php_ref" : "ffi_c2php"; + const char* func = is_ref ? "ffi_c2php_ref" : "ffi_c2php"; W << func << "(" << expr << ")"; } -void compile_ffi_c2php_conv(VertexAdaptor root, CodeGenerator &W) { +void compile_ffi_c2php_conv(VertexAdaptor root, CodeGenerator& W) { compile_ffi_c2php(root->expr(), tinf::get_type(root)->is_ffi_ref(), root->php_type, W); } -void compile_ffi_php2c_tag(const FFIType *c_type, const std::string scope_name, CodeGenerator &W) { - const FFIType *type = c_type->kind == FFITypeKind::Var ? c_type->members[0] : c_type; +void compile_ffi_php2c_tag(const FFIType* c_type, const std::string scope_name, CodeGenerator& W) { + const FFIType* type = c_type->kind == FFITypeKind::Var ? c_type->members[0] : c_type; std::string tag; // some tags have unboxed specializations, other types are specialized with CData templates; // see ffi_tag<> specializations in ffi.h for more info @@ -267,13 +260,13 @@ void compile_ffi_php2c_tag(const FFIType *c_type, const std::string scope_name, W << "ffi_tag<" << tag << ">{}"; } -void compile_ffi_php2c(VertexPtr expr, const TypeHint *c_type, CodeGenerator &W) { +void compile_ffi_php2c(VertexPtr expr, const TypeHint* c_type, CodeGenerator& W) { W << "ffi_php2c(" << expr << ", "; compile_ffi_php2c_tag(FFIRoot::get_ffi_type(c_type), FFIRoot::get_ffi_scope(c_type), W); W << ")"; } -void compile_ffi_php2c_conv(VertexAdaptor root, CodeGenerator &W) { +void compile_ffi_php2c_conv(VertexAdaptor root, CodeGenerator& W) { // just to make the generated code a bit more compact if (root->expr()->type() == op_null) { W << "nullptr"; @@ -282,7 +275,7 @@ void compile_ffi_php2c_conv(VertexAdaptor root, CodeGenerator compile_ffi_php2c(root->expr(), root->c_type, W); } -void compile_conv_op(VertexAdaptor root, CodeGenerator &W) { +void compile_conv_op(VertexAdaptor root, CodeGenerator& W) { if (root->type() == op_conv_regexp) { W << root->expr(); } else if (root->type() == op_ffi_php2c_conv) { @@ -299,23 +292,20 @@ void compile_conv_op(VertexAdaptor root, CodeGenerator &W) { } } -void compile_noerr(VertexAdaptor root, CodeGenerator &W) { +void compile_noerr(VertexAdaptor root, CodeGenerator& W) { if (root->rl_type == val_none) { W << "NOERR_VOID" << MacroBegin{} << Operand{root->expr(), root->type(), true} << MacroEnd{}; } else { - const TypeData *res_tp = tinf::get_type(root); + const TypeData* res_tp = tinf::get_type(root); W << "NOERR" << MacroBegin{} << Operand{root->expr(), root->type(), true} << ", " << TypeName(res_tp) << MacroEnd{}; } } -void compile_throw(VertexAdaptor root, CodeGenerator &W) { - W << BEGIN << - "THROW_EXCEPTION " << MacroBegin{} << root->exception() << MacroEnd{} << ";" << NL << - ThrowAction() << ";" << NL << - END << NL; +void compile_throw(VertexAdaptor root, CodeGenerator& W) { + W << BEGIN << "THROW_EXCEPTION " << MacroBegin{} << root->exception() << MacroEnd{} << ";" << NL << ThrowAction() << ";" << NL << END << NL; } -void compile_try(VertexAdaptor root, CodeGenerator &W) { +void compile_try(VertexAdaptor root, CodeGenerator& W) { std::string_view cur_exception{G->is_output_mode_k2() ? "ForkInstanceState::get().current_info().get().thrown_exception" : "CurException"}; auto move_exception = [&](ClassPtr caught_class, VertexAdaptor dst) { @@ -324,8 +314,8 @@ void compile_try(VertexAdaptor root, CodeGenerator &W) { return; } std::string e = gen_unique_name("e"); - W << BEGIN << "auto " << e << " = std::move(" << cur_exception << ");" << NL << - dst << " = " << e << ".template cast_to<" << caught_class->src_name << ">();" << NL << END << NL; + W << BEGIN << "auto " << e << " = std::move(" << cur_exception << ");" << NL << dst << " = " << e << ".template cast_to<" << caught_class->src_name + << ">();" << NL << END << NL; // we don't allow catching arbitrary classes, but we don't check // interfaces at compile time; to be on the safe side, check that // exception dynamic_cast succeeded @@ -334,10 +324,13 @@ void compile_try(VertexAdaptor root, CodeGenerator &W) { } }; - CGContext &context = W.get_context(); + CGContext& context = W.get_context(); std::string catch_label = gen_unique_name("catch_label"); - W << "/""*** TRY ***""/" << NL; + W << "/" + "*** TRY ***" + "/" + << NL; context.catch_labels.push_back(catch_label); context.catch_label_used.push_back(0); W << root->try_cmd() << NL; @@ -356,14 +349,16 @@ void compile_try(VertexAdaptor root, CodeGenerator &W) { // If try block is marked with catches_all=true, then instead of the // normal else branch with ThrowAction we'll generate an unconditional exception move. - W << "/""*** CATCH ***""/" << NL; - W << "if (0) " << BEGIN << - catch_label << ":;" << NL; // TODO: Label (label_id) ? + W << "/" + "*** CATCH ***" + "/" + << NL; + W << "if (0) " << BEGIN << catch_label << ":;" << NL; // TODO: Label (label_id) ? bool need_else = !root->catches_all; bool is_first_catch = true; auto last_catch = root->catch_list().back(); - for (auto &c : root->catch_list()) { + for (auto& c : root->catch_list()) { auto catch_op = c.as(); bool is_last_catch = c == last_catch; @@ -405,32 +400,30 @@ void compile_try(VertexAdaptor root, CodeGenerator &W) { } if (need_else) { - W << "else " << BEGIN << - ThrowAction() << ";" << NL << - END << NL; + W << "else " << BEGIN << ThrowAction() << ";" << NL << END << NL; } W << END << NL; } } -void compile_power(VertexAdaptor power, CodeGenerator &W) { +void compile_power(VertexAdaptor power, CodeGenerator& W) { switch (tinf::get_type(power)->ptype()) { - case tp_int: - // pow return type with positive constexpr integer exponent and any integer base is inferred as int - W << "int_power"; - return; - case tp_float: - // pow return type with positive constexpr integer exponent and any float base is inferred as float - W << "float_power"; - return; - case tp_mixed: - // pow return type with any other types in exponent, - // including negative constexpr integer or unknown integer, is inferred as var - W << "var_power"; - return; - default: - kphp_error(false, "Unexpected power return type"); + case tp_int: + // pow return type with positive constexpr integer exponent and any integer base is inferred as int + W << "int_power"; + return; + case tp_float: + // pow return type with positive constexpr integer exponent and any float base is inferred as float + W << "float_power"; + return; + case tp_mixed: + // pow return type with any other types in exponent, + // including negative constexpr integer or unknown integer, is inferred as var + W << "var_power"; + return; + default: + kphp_error(false, "Unexpected power return type"); } } @@ -444,7 +437,7 @@ inline int64_t can_use_precomputed_hash_indexing_array(VertexPtr key) { // if it's just a ['string'] that became [$const_string$xxx] (it can also be op_concat or other kind thing) if (auto key_var = key.try_as()) { if (key->extra_type == op_ex_var_const && key_var->var_id->init_val->type() == op_string) { - const std::string &string_key = key_var->var_id->init_val->get_string(); + const std::string& string_key = key_var->var_id->init_val->get_string(); // see array::get_value()/set_value(): numeric strings have a separate code path int64_t int_val; @@ -474,8 +467,8 @@ bool is_interruptible_expr(VertexPtr vertex) { return std::any_of(vertex->begin(), vertex->end(), is_interruptible_expr); } -void compile_null_coalesce(VertexAdaptor root, CodeGenerator &W) { - const TypeData *type = tinf::get_type(root); +void compile_null_coalesce(VertexAdaptor root, CodeGenerator& W) { + const TypeData* type = tinf::get_type(root); auto lhs = root->lhs(); auto rhs = root->rhs(); @@ -493,7 +486,7 @@ void compile_null_coalesce(VertexAdaptor root, CodeGenerator & const auto index = lhs.try_as(); const auto array_ptype = index ? tinf::get_type(index->array())->get_real_ptype() : tp_any; if (index && vk::none_of_equal(array_ptype, tp_shape, tp_tuple)) { - kphp_assert (index->has_key()); + kphp_assert(index->has_key()); W << index->array() << ", " << index->key(); if (vk::any_of_equal(array_ptype, tp_array, tp_mixed)) { if (auto precomputed_hash = can_use_precomputed_hash_indexing_array(index->key())) { @@ -509,7 +502,7 @@ void compile_null_coalesce(VertexAdaptor root, CodeGenerator & if (vk::any_of_equal(rhs->type(), op_var, op_int_const, op_float_const, op_false, op_null)) { W << rhs; } else { - auto &context = W.get_context(); + auto& context = W.get_context(); context.catch_labels.emplace_back(); ++context.inside_null_coalesce_fallback; /* TODO: K2 @@ -546,34 +539,30 @@ void compile_null_coalesce(VertexAdaptor root, CodeGenerator & } } -void compile_binary_func_op(VertexAdaptor root, CodeGenerator &W) { +void compile_binary_func_op(VertexAdaptor root, CodeGenerator& W) { if (auto pow_vertex = root.try_as()) { compile_power(pow_vertex, W); } else { W << OpInfo::str(root->type()); } - W << " (" << - Operand{root->lhs(), root->type(), true} << - ", " << - Operand{root->rhs(), root->type(), false} << - ")"; + W << " (" << Operand{root->lhs(), root->type(), true} << ", " << Operand{root->rhs(), root->type(), false} << ")"; } -bool try_compile_append_inplace(VertexAdaptor root, CodeGenerator &W); -bool try_compile_set_by_index_of_mixed(VertexPtr root, CodeGenerator &W); +bool try_compile_append_inplace(VertexAdaptor root, CodeGenerator& W); +bool try_compile_set_by_index_of_mixed(VertexPtr root, CodeGenerator& W); -void compile_binary_op(VertexAdaptor root, CodeGenerator &W) { - const auto &root_type_str = OpInfo::str(root->type()); - kphp_error_return (root_type_str[0] != '@', fmt_format("Unexpected {}\n", vk::string_view{root_type_str}.substr(1))); +void compile_binary_op(VertexAdaptor root, CodeGenerator& W) { + const auto& root_type_str = OpInfo::str(root->type()); + kphp_error_return(root_type_str[0] != '@', fmt_format("Unexpected {}\n", vk::string_view{root_type_str}.substr(1))); auto lhs = root->lhs(); auto rhs = root->rhs(); - const auto *lhs_tp = tinf::get_type(lhs); - const auto *rhs_tp = tinf::get_type(rhs); + const auto* lhs_tp = tinf::get_type(lhs); + const auto* rhs_tp = tinf::get_type(rhs); if (auto instanceof = root.try_as()) { - if (lhs_tp->ptype() == tp_mixed && !instanceof->derived_class->may_be_mixed.load(std::memory_order_relaxed)) { + if (lhs_tp->ptype() == tp_mixed && ! instanceof->derived_class->may_be_mixed.load(std::memory_order_relaxed)) { W << "(false)"; } else { W << "f$is_a<" << instanceof->derived_class->src_name << ">(" << lhs << ")"; @@ -588,14 +577,14 @@ void compile_binary_op(VertexAdaptor root, CodeGenerator &W) { if (root->type() == op_add) { if (lhs_tp->ptype() == tp_array && rhs_tp->ptype() == tp_array && type_out(lhs_tp) != type_out(rhs_tp)) { - const TypeData *res_tp = tinf::get_type(root)->lookup_at_any_key(); + const TypeData* res_tp = tinf::get_type(root)->lookup_at_any_key(); W << "array_add < " << TypeName(res_tp) << " > (" << lhs << ", " << rhs << ")"; return; } } // special inplace variables that are defined at the assignment location, not in the beginning of the function if (root->type() == op_set && lhs->type() == op_var && lhs->extra_type == op_ex_var_superlocal_inplace) { - W << TypeName(lhs_tp) << " "; // generates "array $tmp = v" instead of "$tmp = v" + W << TypeName(lhs_tp) << " "; // generates "array $tmp = v" instead of "$tmp = v" } if (root->type() == op_set_dot && root->rl_type == val_none) { @@ -612,10 +601,10 @@ void compile_binary_op(VertexAdaptor root, CodeGenerator &W) { bool lhs_is_bool = lhs_tp->get_real_ptype() == tp_bool; bool rhs_is_bool = rhs_tp->get_real_ptype() == tp_bool; if (rhs_is_bool ^ lhs_is_bool) { - static const std::unordered_map> tp_to_str{ - {op_lt, "lt"}, - {op_le, "leq"}, - {op_eq2, "eq2"}, + static const std::unordered_map> tp_to_str{ + {op_lt, "lt"}, + {op_le, "leq"}, + {op_eq2, "eq2"}, }; auto str_repr_it = tp_to_str.find(root->type()); @@ -629,12 +618,10 @@ void compile_binary_op(VertexAdaptor root, CodeGenerator &W) { return; } - W << Operand{lhs, root->type(), true} << - " " << root_type_str << " " << - Operand{rhs, root->type(), false}; + W << Operand{lhs, root->type(), true} << " " << root_type_str << " " << Operand{rhs, root->type(), false}; } -void compile_ternary_op(VertexAdaptor root, CodeGenerator &W) { +void compile_ternary_op(VertexAdaptor root, CodeGenerator& W) { VertexPtr cond = root->cond(); VertexPtr true_expr = root->true_expr(); VertexPtr false_expr = root->false_expr(); @@ -643,7 +630,7 @@ void compile_ternary_op(VertexAdaptor root, CodeGenerator &W) { true_expr_tp = tinf::get_type(true_expr); false_expr_tp = tinf::get_type(false_expr); - //TODO: optimize type_out + // TODO: optimize type_out if (type_out(true_expr_tp) != type_out(false_expr_tp)) { res_tp = tinf::get_type(root); } @@ -669,36 +656,25 @@ void compile_ternary_op(VertexAdaptor root, CodeGenerator &W) { } } - -void compile_if(VertexAdaptor root, CodeGenerator &W) { - W << "if (" << root->cond() << ") " << - BEGIN << - AsSeq{root->true_cmd()} << - END; +void compile_if(VertexAdaptor root, CodeGenerator& W) { + W << "if (" << root->cond() << ") " << BEGIN << AsSeq{root->true_cmd()} << END; if (root->has_false_cmd()) { W << " else " << root->false_cmd(); } } -void compile_while(VertexAdaptor root, CodeGenerator &W) { - W << "while (" << root->cond() << ") " << - CycleBody{root->cmd(), root->continue_label_id, root->break_label_id}; +void compile_while(VertexAdaptor root, CodeGenerator& W) { + W << "while (" << root->cond() << ") " << CycleBody{root->cmd(), root->continue_label_id, root->break_label_id}; } - -void compile_do(VertexAdaptor root, CodeGenerator &W) { - W << "do " << - BEGIN << - AsSeq{root->cmd()} << - Label{root->continue_label_id} << - END << " while ("; - W << root->cond(); +void compile_do(VertexAdaptor root, CodeGenerator& W) { + W << "do " << BEGIN << AsSeq{root->cmd()} << Label{root->continue_label_id} << END << " while ("; + W << root->cond(); W << ");" << NL << Label{root->break_label_id}; } - -void compile_return(VertexAdaptor root, CodeGenerator &W) { +void compile_return(VertexAdaptor root, CodeGenerator& W) { bool resumable_flag = W.get_context().resumable_flag; bool interruptible_flag = W.get_context().interruptible_flag; if (resumable_flag) { @@ -724,15 +700,12 @@ void compile_return(VertexAdaptor root, CodeGenerator &W) { } } -void compile_for(VertexAdaptor root, CodeGenerator &W) { - W << "for (" << - JoinValues(*root->pre_cond(), ", ") << "; " << - JoinValues(*root->cond(), ", ") << "; " << - JoinValues(*root->post_cond(), ", ") << ") " << - CycleBody{root->cmd(), root->continue_label_id, root->break_label_id}; +void compile_for(VertexAdaptor root, CodeGenerator& W) { + W << "for (" << JoinValues(*root->pre_cond(), ", ") << "; " << JoinValues(*root->cond(), ", ") << "; " << JoinValues(*root->post_cond(), ", ") << ") " + << CycleBody{root->cmd(), root->continue_label_id, root->break_label_id}; } -void compile_ffi_callback(VertexAdaptor callback, const FFIType *fn_type, const std::string &scope_name, CodeGenerator &W) { +void compile_ffi_callback(VertexAdaptor callback, const FFIType* fn_type, const std::string& scope_name, CodeGenerator& W) { // for FFI callback the code generation is close to what we're doing for normal op_callback_of_builtin, // except we need to add some prologue and epilogue to the function being passed; // the prologue converts all callback arguments with c2php (C calls callback with C types, KPHP expects PHP types) @@ -749,8 +722,8 @@ void compile_ffi_callback(VertexAdaptor callback, const if (need_comma) { W << ", "; } - const auto *param_type = fn_type->members[i]->members[0]; - auto param = php_params[i-1].as(); + const auto* param_type = fn_type->members[i]->members[0]; + auto param = php_params[i - 1].as(); W << ffi_mangled_type_string(scope_name, param_type) << " " << param->var(); need_comma = true; } @@ -764,7 +737,7 @@ void compile_ffi_callback(VertexAdaptor callback, const } W << "FFI_INVOKE_CALLBACK(" << FunctionName(callback->func_id) << "("; bool first_arg = true; - for (const auto &x : callback->func_id->get_params()) { + for (const auto& x : callback->func_id->get_params()) { if (!first_arg) { W << ", "; } @@ -774,7 +747,7 @@ void compile_ffi_callback(VertexAdaptor callback, const } W << "))"; if (!is_void) { - const FFIType *c_return_type = fn_type->members[0]; + const FFIType* c_return_type = fn_type->members[0]; W << ", "; compile_ffi_php2c_tag(c_return_type, scope_name, W); W << ")"; @@ -786,10 +759,10 @@ void compile_ffi_callback(VertexAdaptor callback, const W << UnlockComments{}; } -void compile_ffi_func_call(VertexAdaptor call, CodeGenerator &W) { +void compile_ffi_func_call(VertexAdaptor call, CodeGenerator& W) { std::string local_name = std::string(call->func_id->local_name()); - auto *scope = call->func_id->class_id->ffi_scope_mixin; - const FFISymbol *sym = scope->find_function(local_name); + auto* scope = call->func_id->class_id->ffi_scope_mixin; + const FFISymbol* sym = scope->find_function(local_name); if (!sym->type->is_signal_safe()) { W << "FFI_CALL("; @@ -802,7 +775,7 @@ void compile_ffi_func_call(VertexAdaptor call, CodeGenerator &W) { } W << "("; - const auto &args = call->args(); + const auto& args = call->args(); bool need_comma = false; // since FFI methods are instance methods, ignore the first $this argument for (int i = 1; i < args.size(); i++) { @@ -819,7 +792,7 @@ void compile_ffi_func_call(VertexAdaptor call, CodeGenerator &W) { } else { W << arg; } - if (j != variadic_arg->args().size()-1) { + if (j != variadic_arg->args().size() - 1) { W << ", "; } } @@ -831,7 +804,7 @@ void compile_ffi_func_call(VertexAdaptor call, CodeGenerator &W) { } if (auto as_callback = args[i].try_as()) { // sym->type->members[i] is Var, so its members[0] is an actual param type - const FFIType *function_pointer = sym->type->members[i]->members[0]; + const FFIType* function_pointer = sym->type->members[i]->members[0]; kphp_assert(function_pointer->kind == FFITypeKind::FunctionPointer); compile_ffi_callback(as_callback, function_pointer, scope->scope_name, W); } else { @@ -849,13 +822,13 @@ void compile_ffi_func_call(VertexAdaptor call, CodeGenerator &W) { enum class func_call_mode { simple = 0, // just call async_call, // call of resumable function inside another resumable function, but not in fork - fork_call // call using fork + fork_call // call using fork }; // to_json_impl() and from_json_impl() are represented in AST as `impl($json_encoder, ...args)` // but we want them to be codegenerated as `f$impl(JsonEncoderTag{}, ...args)` // here we shift call args by one and manually output cpp struct tag{} as the first argument -VertexAdaptor patch_compiling_json_impl_call(CodeGenerator &W, VertexAdaptor call) noexcept { +VertexAdaptor patch_compiling_json_impl_call(CodeGenerator& W, VertexAdaptor call) noexcept { auto args = call->args(); auto first_arg = args.begin(); auto v_encoder = VertexUtil::get_actual_value(*first_arg); @@ -871,7 +844,7 @@ VertexAdaptor patch_compiling_json_impl_call(CodeGenerator &W, Ver return new_call; } -void compile_func_call(VertexAdaptor root, CodeGenerator &W, func_call_mode mode = func_call_mode::simple) { +void compile_func_call(VertexAdaptor root, CodeGenerator& W, func_call_mode mode = func_call_mode::simple) { if (root->func_id->is_extern()) { if (root->str_val == "make_clone" && tinf::get_type(root->args()[0])->is_primitive_type()) { // avoid generating make_clone call for primitive types such that (int, double, bool) just for beauty @@ -903,7 +876,7 @@ void compile_func_call(VertexAdaptor root, CodeGenerator &W, func_ FunctionPtr func; constexpr auto is_function_call_should_be_tracked = [](FunctionPtr func) { - const auto & tracked_functions = G->get_tracked_builtins(); + const auto& tracked_functions = G->get_tracked_builtins(); return func->is_extern() && tracked_functions.find(func->name) != tracked_functions.end(); }; if (root->extra_type == op_ex_internal_func) { @@ -918,11 +891,11 @@ void compile_func_call(VertexAdaptor root, CodeGenerator &W, func_ kphp_error(0, "Too many same errors about resumable functions, will skip others"); } } else { - kphp_error (0, fmt_format("Can't compile call of resumable function [{}] in too complex expression\n" - "Consider using a temporary variable for this call.\n" - "Function is resumable because of calls chain:\n" - "{}", - func->as_human_readable(), func->get_resumable_path())); + kphp_error(0, fmt_format("Can't compile call of resumable function [{}] in too complex expression\n" + "Consider using a temporary variable for this call.\n" + "Function is resumable because of calls chain:\n" + "{}", + func->as_human_readable(), func->get_resumable_path())); } } @@ -944,7 +917,7 @@ void compile_func_call(VertexAdaptor root, CodeGenerator &W, func_ } } if (func && func->cpp_template_call) { - const TypeData *tp = tinf::get_type(root); + const TypeData* tp = tinf::get_type(root); W << "< " << TypeName(tp) << " >"; } W << "("; @@ -976,7 +949,7 @@ void compile_func_call(VertexAdaptor root, CodeGenerator &W, func_ } } -void compile_func_call_fast(VertexAdaptor root, CodeGenerator &W) { +void compile_func_call_fast(VertexAdaptor root, CodeGenerator& W) { if (!root->func_id->can_throw()) { compile_func_call(root, W); return; @@ -986,7 +959,7 @@ void compile_func_call_fast(VertexAdaptor root, CodeGenerator &W) if (is_void) { W << "TRY_CALL_VOID_ " << MacroBegin{}; } else { - const TypeData *type = tinf::get_type(root); + const TypeData* type = tinf::get_type(root); W << "TRY_CALL_ " << MacroBegin{} << TypeName(type) << ", "; } @@ -997,15 +970,16 @@ void compile_func_call_fast(VertexAdaptor root, CodeGenerator &W) W << ", " << ThrowAction{} << MacroEnd{}; } -void compile_ffi_cast(VertexAdaptor root, CodeGenerator &W) { - const auto *from_type = tinf::get_type(root->expr()); - const auto *to_type = FFIRoot::get_ffi_type(root->php_type); - const std::string &scope_name = FFIRoot::get_ffi_scope(root->php_type); +void compile_ffi_cast(VertexAdaptor root, CodeGenerator& W) { + const auto* from_type = tinf::get_type(root->expr()); + const auto* to_type = FFIRoot::get_ffi_type(root->php_type); + const std::string& scope_name = FFIRoot::get_ffi_scope(root->php_type); if (to_type->kind == FFITypeKind::Array) { kphp_assert(root->has_array_size_expr() || to_type->num != -1); // right now only pointer types can be cast to arrays; // also, these arrays always have only 1 dimension (therefore, members[0] is a non-array element type) - W << "ffi_cast_to_array" << "<" << ffi_mangled_decltype_string(scope_name, to_type->members[0]) << ">(" << root->expr() << ", "; // << root->array_size_expr() << ")"; + W << "ffi_cast_to_array" << "<" << ffi_mangled_decltype_string(scope_name, to_type->members[0]) << ">(" << root->expr() + << ", "; // << root->array_size_expr() << ")"; if (to_type->num != -1) { W << to_type->num; } else { @@ -1014,25 +988,26 @@ void compile_ffi_cast(VertexAdaptor root, CodeGenerator &W) { W << ")"; return; } - const char *func = "ffi_cast"; + const char* func = "ffi_cast"; if (from_type->lookup_at_any_key()) { func = "ffi_cast_from_array"; } else if (from_type->get_indirection() == 0 && ffi_builtin_type(from_type->class_type()->ffi_class_mixin->ffi_type->kind)) { - func = "ffi_cast_scalar"; + func = "ffi_cast_scalar"; } W << func << "<" << ffi_mangled_decltype_string(scope_name, to_type) << ">(" << root->expr() << ")"; } -void compile_ffi_addr(VertexAdaptor root, CodeGenerator &W) { +void compile_ffi_addr(VertexAdaptor root, CodeGenerator& W) { W << "ffi_addr(" << root->expr() << ")"; } -void compile_ffi_new(VertexAdaptor root, CodeGenerator &W) { - const auto *ffi_type = FFIRoot::get_ffi_type(root->php_type); +void compile_ffi_new(VertexAdaptor root, CodeGenerator& W) { + const auto* ffi_type = FFIRoot::get_ffi_type(root->php_type); if (root->has_array_size_expr()) { - const auto *elem_type = ffi_type->members[0]; + const auto* elem_type = ffi_type->members[0]; std::string scope_name = FFIRoot::get_ffi_scope(root->php_type); - W << "ffi_new_cdata_array" << "<" << ffi_mangled_decltype_string(scope_name, elem_type) << ">" << "(" << root->array_size_expr() << ", " << root->owned_flag_expr() << ")"; + W << "ffi_new_cdata_array" << "<" << ffi_mangled_decltype_string(scope_name, elem_type) << ">" << "(" << root->array_size_expr() << ", " + << root->owned_flag_expr() << ")"; } else if (ffi_type->kind != FFITypeKind::Pointer) { W << "ffi_new_cdata<" << ffi_mangled_decltype_string(root->php_type) << ">(" << root->owned_flag_expr() << ")"; } else { @@ -1040,8 +1015,8 @@ void compile_ffi_new(VertexAdaptor root, CodeGenerator &W) { } } -void compile_ffi_cdata_value_ref(VertexAdaptor root, CodeGenerator &W) { - const auto *type = tinf::get_type(root->expr()); +void compile_ffi_cdata_value_ref(VertexAdaptor root, CodeGenerator& W) { + const auto* type = tinf::get_type(root->expr()); if (type->is_ffi_ref()) { W << "*(" << root->expr() << ".c_value)"; } else { @@ -1049,8 +1024,8 @@ void compile_ffi_cdata_value_ref(VertexAdaptor root, Cod } } -void compile_ffi_load_call(VertexAdaptor root, CodeGenerator &W) { - auto *scope = G->get_ffi_root().find_scope(root->scope_name); +void compile_ffi_load_call(VertexAdaptor root, CodeGenerator& W) { + auto* scope = G->get_ffi_root().find_scope(root->scope_name); if (!scope->is_shared_lib()) { compile_func_call(root->func_call(), W); @@ -1068,19 +1043,19 @@ void compile_ffi_load_call(VertexAdaptor root, CodeGenerator & W << ", " << scope->shared_lib_id << ", " << scope->get_env_offset() << ", " << num_dynamic_symbols << ")"; } -void compile_ffi_array_get(VertexAdaptor root, CodeGenerator &W) { +void compile_ffi_array_get(VertexAdaptor root, CodeGenerator& W) { W << "ffi_array_get(" << root->array() << ", " << root->key() << ")"; } -void compile_ffi_array_set(VertexAdaptor root, CodeGenerator &W) { +void compile_ffi_array_set(VertexAdaptor root, CodeGenerator& W) { W << "ffi_array_set(" << root->array() << ", " << root->key() << ", " << root->value() << ")"; } -void compile_fork(VertexAdaptor root, CodeGenerator &W) { +void compile_fork(VertexAdaptor root, CodeGenerator& W) { compile_func_call(root->func_call(), W, func_call_mode::fork_call); } -void compile_async(VertexAdaptor root, CodeGenerator &W) { +void compile_async(VertexAdaptor root, CodeGenerator& W) { auto func_call = root->func_call(); if (root->has_save_var()) { W << root->save_var() << " = "; @@ -1100,11 +1075,11 @@ void compile_async(VertexAdaptor root, CodeGenerator &W) { } } -void compile_foreach_ref_header(VertexAdaptor root, CodeGenerator &W) { +void compile_foreach_ref_header(VertexAdaptor root, CodeGenerator& W) { kphp_error(!W.get_context().resumable_flag, "foreach by reference is forbidden in resumable mode"); auto params = root->params(); - //foreach (xs as [key =>] x) + // foreach (xs as [key =>] x) VertexPtr xs = params->xs(); VertexPtr x = params->x(); VertexPtr key; @@ -1114,18 +1089,14 @@ void compile_foreach_ref_header(VertexAdaptor root, CodeGenerator &W std::string xs_copy_str; xs_copy_str = gen_unique_name("tmp_expr"); - const TypeData *xs_type = tinf::get_type(xs); + const TypeData* xs_type = tinf::get_type(xs); W << BEGIN; - //save array to 'xs_copy_str' + // save array to 'xs_copy_str' W << TypeName(xs_type) << " &" << xs_copy_str << " = " << xs << ";" << NL; std::string it = gen_unique_name("it"); - W << "for (auto " << it << " = begin (" << xs_copy_str << "); " << - it << " != end (" << xs_copy_str << "); " << - "++" << it << ")" << - BEGIN; - + W << "for (auto " << it << " = begin (" << xs_copy_str << "); " << it << " != end (" << xs_copy_str << "); " << "++" << it << ")" << BEGIN; // save value: codegen `T &v$name = it.get_value()` // note, that in global scope `v$name` remains a C++ variable (though other mutable globals are placed in linear mem) @@ -1133,15 +1104,15 @@ void compile_foreach_ref_header(VertexAdaptor root, CodeGenerator &W W << TypeName(tinf::get_type(x)) << " &"; W << x << " = " << it << ".get_value();" << NL; - //save key + // save key if (key) { W << key << " = " << it << ".get_key();" << NL; } } -void compile_foreach_noref_header(VertexAdaptor root, CodeGenerator &W) { +void compile_foreach_noref_header(VertexAdaptor root, CodeGenerator& W) { auto params = root->params(); - //foreach (xs as [key =>] x) + // foreach (xs as [key =>] x) VertexPtr x = params->x(); VertexPtr xs = params->xs(); VertexPtr key; @@ -1150,7 +1121,7 @@ void compile_foreach_noref_header(VertexAdaptor root, CodeGenerator key = params->key(); } - TypeData const *type_data = tinf::get_type(xs); + TypeData const* type_data = tinf::get_type(xs); if (auto xs_var = xs.try_as()) { type_data = tinf::get_type(xs_var->var_id); } @@ -1162,27 +1133,26 @@ void compile_foreach_noref_header(VertexAdaptor root, CodeGenerator } W << BEGIN; - //save array to 'xs_copy_str' + // save array to 'xs_copy_str' W << temp_var << " = " << xs << ";" << NL; W << temp_var << "$it = const_begin(" << temp_var << ");" << NL; W << temp_var << "$it$end = const_end(" << temp_var << ");" << NL; - W << "for (; " << temp_var << "$it != " << temp_var << "$it$end; ++" << temp_var << "$it) " << - BEGIN; + W << "for (; " << temp_var << "$it != " << temp_var << "$it$end; ++" << temp_var << "$it) " << BEGIN; - //save value + // save value W << x << " = " << temp_var << "$it" << ".get_value();" << NL; - //save key + // save key if (key) { W << key << " = " << temp_var << "$it" << ".get_key();" << NL; } } -void compile_foreach(VertexAdaptor root, CodeGenerator &W) { +void compile_foreach(VertexAdaptor root, CodeGenerator& W) { auto params = root->params(); auto cmd = root->cmd(); - //foreach (xs as [key =>] x) + // foreach (xs as [key =>] x) if (params->x()->ref_flag) { compile_foreach_ref_header(root, W); } else { @@ -1193,10 +1163,7 @@ void compile_foreach(VertexAdaptor root, CodeGenerator &W) { return; } - W << AsSeq{cmd} << NL << - Label{root->continue_label_id} << - END << - Label{root->break_label_id} << NL; + W << AsSeq{cmd} << NL << Label{root->continue_label_id} << END << Label{root->break_label_id} << NL; if (!params->x()->ref_flag) { VertexPtr temp_var = params->temp_var(); W << "clear_array(" << temp_var << ");" << NL; @@ -1208,23 +1175,23 @@ struct CaseInfo { size_t hash{0}; bool is_default{false}; std::string goto_name; - CaseInfo *next{nullptr}; + CaseInfo* next{nullptr}; VertexPtr v; VertexPtr expr; VertexPtr cmd; CaseInfo() = default; - explicit CaseInfo(VertexPtr root) : - is_default(root->type() == op_default), - v(root) { + explicit CaseInfo(VertexPtr root) + : is_default(root->type() == op_default), + v(root) { if (auto cs = v.try_as()) { expr = cs->expr(); cmd = cs->cmd(); VertexPtr val = VertexUtil::get_actual_value(expr); - kphp_assert (val->type() == op_string); - const std::string &s = val.as()->str_val; + kphp_assert(val->type() == op_string); + const std::string& s = val.as()->str_val; hash = string_hash(s.c_str(), s.size()); } else { cmd = v.as()->cmd(); @@ -1232,13 +1199,13 @@ struct CaseInfo { } }; -void compile_switch_str(VertexAdaptor root, CodeGenerator &W) { +void compile_switch_str(VertexAdaptor root, CodeGenerator& W) { auto cases_vertices = root->cases(); std::vector cases(cases_vertices.size()); std::transform(cases_vertices.begin(), cases_vertices.end(), cases.begin(), [](auto v) { return CaseInfo(v); }); auto default_case_it = std::find_if(cases.begin(), cases.end(), vk::make_field_getter(&CaseInfo::is_default)); - auto *default_case = default_case_it != cases.end() ? &(*default_case_it) : nullptr; + auto* default_case = default_case_it != cases.end() ? &(*default_case_it) : nullptr; int n = static_cast(cases.size()); std::map hash_to_last_id; @@ -1258,7 +1225,7 @@ void compile_switch_str(VertexAdaptor root, CodeGenerator &W) { cases[i].next = &cases[next_i]; } - auto *next = cases[i].next; + auto* next = cases[i].next; if (next && next->goto_name.empty()) { next->goto_name = gen_unique_name("switch_goto"); } @@ -1272,7 +1239,7 @@ void compile_switch_str(VertexAdaptor root, CodeGenerator &W) { W << temp_var_matched_with_a_case << " = false;" << NL; W << "switch (" << temp_var_strval_of_condition << ".hash()) " << BEGIN; - for (const auto &one_case : cases) { + for (const auto& one_case : cases) { if (one_case.is_default) { W << "default:" << NL; if (!one_case.goto_name.empty()) { @@ -1305,12 +1272,10 @@ void compile_switch_str(VertexAdaptor root, CodeGenerator &W) { } W << END << NL; - W << Label{root->continue_label_id} << - END << - Label{root->break_label_id}; + W << Label{root->continue_label_id} << END << Label{root->break_label_id}; } -void compile_switch_int(VertexAdaptor root, CodeGenerator &W) { +void compile_switch_int(VertexAdaptor root, CodeGenerator& W) { W << "switch (f$intval (" << root->condition() << "))" << BEGIN; W << "static_cast(" << root->condition_on_switch() << ");" << NL; @@ -1324,7 +1289,7 @@ void compile_switch_int(VertexAdaptor root, CodeGenerator &W) { VertexPtr val = VertexUtil::get_actual_value(cs->expr()); W << "case "; if (val->type() == op_int_const) { - const std::string &str = val.as()->str_val; + const std::string& str = val.as()->str_val; W << str; kphp_error(used.insert(str).second, fmt_format("Switch: repeated cases found [{}]", str)); } else { @@ -1342,8 +1307,7 @@ void compile_switch_int(VertexAdaptor root, CodeGenerator &W) { W << Label{root->break_label_id}; } - -void compile_switch_var(VertexAdaptor root, CodeGenerator &W) { +void compile_switch_var(VertexAdaptor root, CodeGenerator& W) { std::string goto_name_if_default_in_the_middle; auto temp_var_condition_on_switch = root->condition_on_switch(); @@ -1355,7 +1319,7 @@ void compile_switch_var(VertexAdaptor root, CodeGenerator &W) { const auto cases = root->cases(); const bool default_case_is_the_last = !cases.empty() && cases.back()->type() == op_default; - for (const auto &one_case : cases) { + for (const auto& one_case : cases) { VertexAdaptor cmd; if (auto cs = one_case.try_as()) { cmd = cs->cmd(); @@ -1391,8 +1355,7 @@ void compile_switch_var(VertexAdaptor root, CodeGenerator &W) { W << Label{root->break_label_id}; } - -void compile_switch(VertexAdaptor root, CodeGenerator &W) { +void compile_switch(VertexAdaptor root, CodeGenerator& W) { kphp_assert(root->condition_on_switch()->type() == op_var && root->matched_with_one_case()->type() == op_var); bool has_default = false; @@ -1416,31 +1379,25 @@ void compile_switch(VertexAdaptor root, CodeGenerator &W) { } } - -bool compile_tracing_profiler(FunctionPtr func, CodeGenerator &W) { - if (func->profiler_state == FunctionData::profiler_status::disable - || (func->is_inline && func->profiler_state == FunctionData::profiler_status::enable_as_child) - || !G->settings().profiler_level.get()) { +bool compile_tracing_profiler(FunctionPtr func, CodeGenerator& W) { + if (func->profiler_state == FunctionData::profiler_status::disable || + (func->is_inline && func->profiler_state == FunctionData::profiler_status::enable_as_child) || !G->settings().profiler_level.get()) { return false; } - const auto &location = func->root->get_location(); - const char *is_root = func->profiler_state == FunctionData::profiler_status::enable_as_root ? "true" : "false"; - W << "struct TracingProfilerTraits " << BEGIN - << "static constexpr const char *file_name() noexcept { return " << RawString(location.file ? location.file->relative_file_name : "unknown file") << "; }" << NL + const auto& location = func->root->get_location(); + const char* is_root = func->profiler_state == FunctionData::profiler_status::enable_as_root ? "true" : "false"; + W << "struct TracingProfilerTraits " << BEGIN << "static constexpr const char *file_name() noexcept { return " + << RawString(location.file ? location.file->relative_file_name : "unknown file") << "; }" << NL << "static constexpr const char *function_name() noexcept { return " << RawString(func->as_human_readable(false)) << "; }" << NL << "static constexpr size_t function_line() noexcept { return " << std::max(location.line, 0) << "; }" << NL << "static constexpr size_t profiler_level() noexcept { return " << G->settings().profiler_level.get() << "; }" << NL - << "static constexpr bool is_root() noexcept { return " << is_root << "; }" << NL - << END << ";" << NL; + << "static constexpr bool is_root() noexcept { return " << is_root << "; }" << NL << END << ";" << NL; if (func->is_resumable) { W << "ResumableProfiler resumable_profiler;" << NL << NL; - FunctionSignatureGenerator(W).set_final() - << "bool run()" << BEGIN - << "resumable_profiler.start(pos__);" << NL - << "const bool done = run_profiling_resumable();" << NL - << "resumable_profiler.stop(done);" << NL - << "return done;" << NL << END << NL << NL; + FunctionSignatureGenerator(W).set_final() << "bool run()" << BEGIN << "resumable_profiler.start(pos__);" << NL + << "const bool done = run_profiling_resumable();" << NL << "resumable_profiler.stop(done);" << NL + << "return done;" << NL << END << NL << NL; } else { W << "AutoProfiler auto_profiler;" << NL << NL; } @@ -1448,29 +1405,25 @@ bool compile_tracing_profiler(FunctionPtr func, CodeGenerator &W) { return true; } -void compile_generated_stub(VertexAdaptor func_root, CodeGenerator &W) { +void compile_generated_stub(VertexAdaptor func_root, CodeGenerator& W) { FunctionPtr func = func_root->func_id; - W << FunctionDeclaration(func, false) << " " << - BEGIN; + W << FunctionDeclaration(func, false) << " " << BEGIN; W << "php_critical_error(\"call to unsupported function : " << func->name << "\");" << NL; W << END << NL; } -void compile_function_resumable(VertexAdaptor func_root, CodeGenerator &W) { +void compile_function_resumable(VertexAdaptor func_root, CodeGenerator& W) { FunctionPtr func = func_root->func_id; W << "//RESUMABLE FUNCTION IMPLEMENTATION" << NL; - W << "class " << FunctionClassName(func) << " final : public Resumable " << - BEGIN << - "private:" << NL << Indent(+2); + W << "class " << FunctionClassName(func) << " final : public Resumable " << BEGIN << "private:" << NL << Indent(+2); - - //MEMBER VARIABLES + // MEMBER VARIABLES for (VarPtr var : func->param_ids) { kphp_error(!var->is_reference, "reference function parametrs are forbidden in resumable mode"); W << VarPlainDeclaration(var); } for (VarPtr var : func->local_var_ids) { - W << VarPlainDeclaration(var); // inplace variables are stored as Resumable class fields as well + W << VarPlainDeclaration(var); // inplace variables are stored as Resumable class fields as well } if (func->has_global_vars_inside) { W << PhpMutableGlobalsDeclareInResumableClass(); @@ -1481,30 +1434,24 @@ void compile_function_resumable(VertexAdaptor func_root, CodeGenera W << Indent(-2) << "public:" << NL << Indent(+2); - //ReturnT + // ReturnT W << "using ReturnT = " << TypeName(tinf::get_type(func, -1)) << ";" << NL; - //CONSTRUCTOR + // CONSTRUCTOR FunctionSignatureGenerator(W) << FunctionClassName(func) << "(" << FunctionParams(func) << ")"; bool has_members_in_constructor = !func->param_ids.empty() || !func->local_var_ids.empty() || func->has_global_vars_inside; if (has_members_in_constructor) { bool any_inited = false; W << " :" << NL << Indent(+2); if (!func->param_ids.empty()) { - W << JoinValues(func->param_ids, ",", join_mode::multiple_lines, - [](CodeGenerator &W, VarPtr var) { - W << VarName(var) << "(" << VarName(var) << ")"; - }); + W << JoinValues(func->param_ids, ",", join_mode::multiple_lines, [](CodeGenerator& W, VarPtr var) { W << VarName(var) << "(" << VarName(var) << ")"; }); any_inited = true; } if (!func->local_var_ids.empty()) { if (any_inited) { W << "," << NL; } - W << JoinValues(func->local_var_ids, ",", join_mode::multiple_lines, - [](CodeGenerator &W, VarPtr var) { - W << VarName(var) << "()"; - }); + W << JoinValues(func->local_var_ids, ",", join_mode::multiple_lines, [](CodeGenerator& W, VarPtr var) { W << VarName(var) << "()"; }); any_inited = true; } if (func->has_global_vars_inside) { @@ -1530,37 +1477,30 @@ void compile_function_resumable(VertexAdaptor func_root, CodeGenera W << AsSeq{func_root->cmd()} << NL; - W << Indent(-2) << - "RESUMABLE_END" << NL << - END << NL; - + W << Indent(-2) << "RESUMABLE_END" << NL << END << NL; W << Indent(-2); W << END << ";" << NL; - //CALL FUNCTION - W << FunctionDeclaration(func, false) << " " << - BEGIN; - W << "return start_resumable < " << FunctionClassName(func) << "::ReturnT >" << - "(new " << FunctionClassName(func) << "("; + // CALL FUNCTION + W << FunctionDeclaration(func, false) << " " << BEGIN; + W << "return start_resumable < " << FunctionClassName(func) << "::ReturnT >" << "(new " << FunctionClassName(func) << "("; - const auto var_name_gen = [](CodeGenerator &W, VarPtr var) { W << VarName(var); }; + const auto var_name_gen = [](CodeGenerator& W, VarPtr var) { W << VarName(var); }; W << JoinValues(func->param_ids, ", ", join_mode::one_line, var_name_gen); W << "));" << NL; W << END << NL; - //FORK FUNCTION - W << FunctionForkDeclaration(func, false) << " " << - BEGIN; + // FORK FUNCTION + W << FunctionForkDeclaration(func, false) << " " << BEGIN; W << "return fork_resumable(new " << FunctionClassName(func) << "("; W << JoinValues(func->param_ids, ", ", join_mode::one_line, var_name_gen); W << "));" << NL; W << END << NL; - } -void compile_function(VertexAdaptor func_root, CodeGenerator &W) { +void compile_function(VertexAdaptor func_root, CodeGenerator& W) { FunctionPtr func = func_root->func_id; W.get_context().parent_func = func; @@ -1622,7 +1562,7 @@ static bool can_save_ref(VertexPtr v) { if (v->type() == op_func_call) { FunctionPtr func = v.as()->func_id; if (func->is_extern()) { - //todo + // todo return false; } return true; @@ -1630,13 +1570,13 @@ static bool can_save_ref(VertexPtr v) { return false; } -void compile_string_build_impl(VertexAdaptor root, VarName dst, const TypeData *dst_type, CodeGenerator &W) { +void compile_string_build_impl(VertexAdaptor root, VarName dst, const TypeData* dst_type, CodeGenerator& W) { struct LenArg { std::string var_name; int64_t static_len = 0; bool complex_flag = false; - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { if (complex_flag) { W << var_name; } else { @@ -1645,11 +1585,12 @@ void compile_string_build_impl(VertexAdaptor root, VarName dst, } }; struct AppendArg { - const StrlenInfo &str_info; + const StrlenInfo& str_info; - AppendArg(const StrlenInfo &str_info): str_info{str_info} {} + AppendArg(const StrlenInfo& str_info) + : str_info{str_info} {} - void compile(CodeGenerator &W) const { + void compile(CodeGenerator& W) const { if (str_info.str_flag) { W << RawString(str_info.str) << ", " << str_info.len; } else if (str_info.var_flag) { @@ -1662,8 +1603,8 @@ void compile_string_build_impl(VertexAdaptor root, VarName dst, if (dst.empty() && root->args().size() <= 5) { bool all_string_args = true; - for (const auto &arg : root->args()) { - const auto *arg_type = tinf::get_type(arg); + for (const auto& arg : root->args()) { + const auto* arg_type = tinf::get_type(arg); if (arg_type->use_optional() || vk::none_of_equal(arg_type->ptype(), tp_string, tp_tmp_string)) { all_string_args = false; break; @@ -1692,11 +1633,11 @@ void compile_string_build_impl(VertexAdaptor root, VarName dst, for (auto i : root->args()) { info[ii].v = i; VertexPtr value = VertexUtil::get_actual_value(i); - const TypeData *type = tinf::get_type(value); + const TypeData* type = tinf::get_type(value); int value_length = type_strlen(type); if (value_length == STRLEN_ERROR) { - kphp_error (0, fmt_format("Cannot convert type [{}] to string", type_out(type))); + kphp_error(0, fmt_format("Cannot convert type [{}] to string", type_out(type))); ok = false; ii++; continue; @@ -1715,10 +1656,10 @@ void compile_string_build_impl(VertexAdaptor root, VarName dst, } else { if (value_length & STRLEN_WARNING_FLAG) { value_length &= ~STRLEN_WARNING_FLAG; - kphp_warning (fmt_format("Suspicious conversion of type [{}] to string", type_out(type))); + kphp_warning(fmt_format("Suspicious conversion of type [{}] to string", type_out(type))); } - kphp_assert (value_length >= 0); + kphp_assert(value_length >= 0); len_arg.static_len += value_length; } @@ -1738,7 +1679,7 @@ void compile_string_build_impl(VertexAdaptor root, VarName dst, if (complex_flag) { W << "(" << BEGIN; std::vector to_add; - for (auto &str_info : info) { + for (auto& str_info : info) { if (str_info.str_flag) { continue; } @@ -1748,12 +1689,9 @@ void compile_string_build_impl(VertexAdaptor root, VarName dst, if (str_info.len == STRLEN_DYNAMIC) { TmpExpr v{str_info.v}; bool can_save_ref_flag = can_save_ref(str_info.v); - W << "const " << TypeName(v.get_type()) << " " << - (can_save_ref_flag ? "&" : "") << - var_name << "=" << v << ";" << NL; + W << "const " << TypeName(v.get_type()) << " " << (can_save_ref_flag ? "&" : "") << var_name << "=" << v << ";" << NL; } else if (str_info.len == STRLEN_OBJECT) { - W << "const string " << var_name << " = f$strval" << - "(" << str_info.v << ");" << NL; + W << "const string " << var_name << " = f$strval" << "(" << str_info.v << ");" << NL; } to_add.push_back(var_name); @@ -1764,7 +1702,7 @@ void compile_string_build_impl(VertexAdaptor root, VarName dst, len_arg.var_name = "tmp_strlen"; W << "string::size_type " << len_arg.var_name << " = " << len_arg.static_len; - for (const auto &str : to_add) { + for (const auto& str : to_add) { W << " + max_string_size (" << str << ")"; } W << ";" << NL; @@ -1788,7 +1726,7 @@ void compile_string_build_impl(VertexAdaptor root, VarName dst, // the finish_append call will insert that 0 byte once in the very end W << string_dst << ".reserve_at_least(" << len_arg << " + " << string_dst << ".size());" << NL; W << string_dst; - for (const auto &str_info : info) { + for (const auto& str_info : info) { W << ".append_unsafe(" << AppendArg{str_info} << ")"; } W << ".finish_append();" << NL; @@ -1801,25 +1739,23 @@ void compile_string_build_impl(VertexAdaptor root, VarName dst, W << "string " << tmp_string_name << " = "; } W << "string (" << len_arg << ", true)"; - for (const auto &str_info : info) { + for (const auto& str_info : info) { W << ".append_unsafe (" << AppendArg{str_info} << ")"; } W << ".finish_append()"; if (complex_flag) { - W << ";" << NL - << tmp_string_name << ";" << NL - << END << ")"; + W << ";" << NL << tmp_string_name << ";" << NL << END << ")"; } } -void compile_string_build_as_string(VertexAdaptor root, CodeGenerator &W) { +void compile_string_build_as_string(VertexAdaptor root, CodeGenerator& W) { compile_string_build_impl(root, {}, nullptr, W); } -bool try_compile_append_inplace(VertexAdaptor root, CodeGenerator &W) { +bool try_compile_append_inplace(VertexAdaptor root, CodeGenerator& W) { if (root->rhs()->type() == op_string_build) { - const auto *lhs_type = tinf::get_type(root->lhs()); + const auto* lhs_type = tinf::get_type(root->lhs()); if (lhs_type->ptype() != tp_string) { return false; } @@ -1842,7 +1778,7 @@ bool try_compile_append_inplace(VertexAdaptor root, CodeGenerator &W return false; } -void compile_index_of_array_or_mixed(VertexAdaptor root, CodeGenerator &W) { +void compile_index_of_array_or_mixed(VertexAdaptor root, CodeGenerator& W) { bool used_as_rval = root->rl_type != val_l; if (!used_as_rval) { kphp_assert(root->has_key()); @@ -1871,85 +1807,85 @@ void compile_index_of_array_or_mixed(VertexAdaptor root, CodeGenerator } } -void compile_index_of_string(VertexAdaptor root, CodeGenerator &W) { +void compile_index_of_string(VertexAdaptor root, CodeGenerator& W) { kphp_assert(root->has_key()); W << root->array() << ".get_value(" << root->key() << ")"; } -void compile_instance_prop(VertexAdaptor root, CodeGenerator &W) { +void compile_instance_prop(VertexAdaptor root, CodeGenerator& W) { switch (root->access_type) { - case InstancePropAccessType::Default: - W << root->instance() << "->$" << root->get_string(); - break; - - case InstancePropAccessType::CData: { - const auto *type = tinf::get_type(root->instance()); - if (type->is_ffi_ref() || type->get_indirection() != 0) { - // CDataPtr or CDataRef - W << root->instance() << ".c_value->" << root->get_string(); - } else { - W << root->instance() << "->c_value." << root->get_string(); - } - break; + case InstancePropAccessType::Default: + W << root->instance() << "->$" << root->get_string(); + break; + + case InstancePropAccessType::CData: { + const auto* type = tinf::get_type(root->instance()); + if (type->is_ffi_ref() || type->get_indirection() != 0) { + // CDataPtr or CDataRef + W << root->instance() << ".c_value->" << root->get_string(); + } else { + W << root->instance() << "->c_value." << root->get_string(); } + break; + } - case InstancePropAccessType::CDataDirect: - W << root->instance() << "." << root->get_string(); - break; + case InstancePropAccessType::CDataDirect: + W << root->instance() << "." << root->get_string(); + break; - case InstancePropAccessType::CDataDirectPtr: - W << root->instance() << "->" << root->get_string(); - break; + case InstancePropAccessType::CDataDirectPtr: + W << root->instance() << "->" << root->get_string(); + break; - case InstancePropAccessType::ExternVar: { - auto *scope_class = tinf::get_type(root->instance())->class_type()->ffi_scope_mixin; - if (scope_class->is_shared_lib()) { - const auto *sym = scope_class->find_variable(root->get_string()); - W << "*reinterpret_cast<" << ffi_mangled_decltype_string(scope_class->scope_name, sym->type) << "*>(ffi_env_instance.symbols[" << sym->env_index << "].ptr)"; - } else { - W << root->get_string(); - } - break; + case InstancePropAccessType::ExternVar: { + auto* scope_class = tinf::get_type(root->instance())->class_type()->ffi_scope_mixin; + if (scope_class->is_shared_lib()) { + const auto* sym = scope_class->find_variable(root->get_string()); + W << "*reinterpret_cast<" << ffi_mangled_decltype_string(scope_class->scope_name, sym->type) << "*>(ffi_env_instance.symbols[" << sym->env_index + << "].ptr)"; + } else { + W << root->get_string(); } + break; + } } } -void compile_index(VertexAdaptor root, CodeGenerator &W) { +void compile_index(VertexAdaptor root, CodeGenerator& W) { PrimitiveType array_ptype = root->array()->tinf_node.get_type()->ptype(); switch (array_ptype) { - case tp_string: - compile_index_of_string(root, W); - break; - case tp_tuple: - W << TupleGetIndex(root->array(), root->key()); - break; - case tp_shape: - W << ShapeGetIndex(root->array(), root->key()); - break; - default: - compile_index_of_array_or_mixed(root, W); + case tp_string: + compile_index_of_string(root, W); + break; + case tp_tuple: + W << TupleGetIndex(root->array(), root->key()); + break; + case tp_shape: + W << ShapeGetIndex(root->array(), root->key()); + break; + default: + compile_index_of_array_or_mixed(root, W); } } - -void compile_seq_rval(VertexPtr root, CodeGenerator &W) { +void compile_seq_rval(VertexPtr root, CodeGenerator& W) { kphp_assert(root->size()); - W << "(" << BEGIN; // gcc "statement exprs" feature: ({ ...; v$result_var; }) + W << "(" << BEGIN; // gcc "statement exprs" feature: ({ ...; v$result_var; }) for (auto i : *root) { - W << i << ";" << NL; // last statement evaluation result will be used as a whole block result + W << i << ";" << NL; // last statement evaluation result will be used as a whole block result } W << END << ")"; } -void compile_xset(VertexAdaptor root, CodeGenerator &W) { +void compile_xset(VertexAdaptor root, CodeGenerator& W) { auto arg = root->expr(); // separately: isset($arr[idx]) — is v$arr.isset(idx) (same for the unset) // but if $arr is a tuple/shape, then it's not an .isset method but is_null on the actual element if (auto index = arg.try_as()) { - kphp_assert (index->has_key()); + kphp_assert(index->has_key()); if (vk::any_of_equal(tinf::get_type(index->array())->ptype(), tp_array, tp_mixed)) { W << "(" << index->array(); if (root->type() == op_isset) { @@ -1957,7 +1893,7 @@ void compile_xset(VertexAdaptor root, CodeGenerator &W) { } else if (root->type() == op_unset) { W << ").unset ("; } else { - kphp_assert (0); + kphp_assert(0); } W << index->key(); if (auto precomputed_hash = can_use_precomputed_hash_indexing_array(index->key())) { @@ -1974,7 +1910,7 @@ void compile_xset(VertexAdaptor root, CodeGenerator &W) { } } -void compile_list(VertexAdaptor root, CodeGenerator &W) { +void compile_list(VertexAdaptor root, CodeGenerator& W) { VertexPtr arr = root->array(); VertexRange list = root->list(); PrimitiveType ptype = tinf::get_type(arr)->get_real_ptype(); @@ -1994,10 +1930,9 @@ void compile_list(VertexAdaptor root, CodeGenerator &W) { } } - -void compile_array(VertexAdaptor root, CodeGenerator &W) { +void compile_array(VertexAdaptor root, CodeGenerator& W) { int n = (int)root->args().size(); - const TypeData *type = tinf::get_type(root); + const TypeData* type = tinf::get_type(root); if (n == 0) { W << TypeName(type) << " ()"; @@ -2028,15 +1963,13 @@ void compile_array(VertexAdaptor root, CodeGenerator &W) { std::string arr_name = "tmp_array"; W << TypeName(type) << " " << arr_name << " = "; - //TODO: check + // TODO: check if (type->ptype() == tp_array) { W << TypeName(type); } else { W << "array "; } - W << " (array_size (" - << size << ", " - << (has_double_arrow ? "false" : "true") << "));" << NL; + W << " (array_size (" << size << ", " << (has_double_arrow ? "false" : "true") << "));" << NL; for (auto cur : root->args()) { W << arr_name; if (auto arrow = cur.try_as()) { @@ -2052,38 +1985,34 @@ void compile_array(VertexAdaptor root, CodeGenerator &W) { W << ";" << NL; } - W << arr_name << ";" << NL << - END << ")"; + W << arr_name << ";" << NL << END << ")"; } -void compile_tuple(VertexAdaptor root, CodeGenerator &W) { +void compile_tuple(VertexAdaptor root, CodeGenerator& W) { W << "std::make_tuple(" << JoinValues(root->args(), ", ") << ")"; } -void compile_shape(VertexAdaptor root, CodeGenerator &W) { +void compile_shape(VertexAdaptor root, CodeGenerator& W) { // important! values are sorted in the keys hash ascending order; // this is in sync with how shape cpp-layout is generated in type_out_impl() std::vector> sorted_by_hash; sorted_by_hash.reserve(root->args().size()); for (auto double_arrow : *root) { - const std::string &key_str = VertexUtil::get_actual_value(double_arrow.as()->lhs())->get_string(); + const std::string& key_str = VertexUtil::get_actual_value(double_arrow.as()->lhs())->get_string(); sorted_by_hash.emplace_back(string_hash(key_str.c_str(), key_str.size()), double_arrow.as()->rhs()); } - std::sort(sorted_by_hash.begin(), sorted_by_hash.end(), [](const auto &a, const auto &b) -> bool { + std::sort(sorted_by_hash.begin(), sorted_by_hash.end(), [](const auto& a, const auto& b) -> bool { kphp_assert(a.second == b.second || a.first != b.first); return a.first < b.first; }); - const auto val_gen = [](CodeGenerator &W, const std::pair &hash_and_rhs) { - W << hash_and_rhs.second; - }; + const auto val_gen = [](CodeGenerator& W, const std::pair& hash_and_rhs) { W << hash_and_rhs.second; }; - const char *sep = W.get_context().inside_macro ? " COMMA " : ", "; - W << TypeName(tinf::get_type(root)) << "{shape_variadic_constructor_stub{} " << sep << - JoinValues(sorted_by_hash, sep, join_mode::one_line, val_gen) << "}"; + const char* sep = W.get_context().inside_macro ? " COMMA " : ", "; + W << TypeName(tinf::get_type(root)) << "{shape_variadic_constructor_stub{} " << sep << JoinValues(sorted_by_hash, sep, join_mode::one_line, val_gen) << "}"; } -void compile_callback_of_builtin(VertexAdaptor root, CodeGenerator &W) { +void compile_callback_of_builtin(VertexAdaptor root, CodeGenerator& W) { /** * PHP code like this: * array_map(fn($x) => $x + $extern, [1,2,3]); @@ -2103,9 +2032,9 @@ void compile_callback_of_builtin(VertexAdaptor root, Cod W << LockComments{}; int idx = 0; - W << "[" << JoinValues(*root, ", ", join_mode::one_line, [&idx](CodeGenerator &W, VertexPtr cpp_captured) { - W << "captured" << (++idx) << " = " << cpp_captured; - }) << "]"; + W << "[" + << JoinValues(*root, ", ", join_mode::one_line, [&idx](CodeGenerator& W, VertexPtr cpp_captured) { W << "captured" << (++idx) << " = " << cpp_captured; }) + << "]"; const bool k2_async_callback = G->is_output_mode_k2() && root->func_id->is_interruptible; @@ -2129,12 +2058,12 @@ void compile_callback_of_builtin(VertexAdaptor root, Cod W << UnlockComments{}; } -void compile_defined(VertexPtr root __attribute__((unused)), CodeGenerator &W __attribute__((unused))) { +void compile_defined(VertexPtr root __attribute__((unused)), CodeGenerator& W __attribute__((unused))) { W << "false"; - //TODO: it is not CodeGen part + // TODO: it is not CodeGen part } -bool try_compile_set_by_index_of_mixed(VertexPtr root, CodeGenerator &W) { +bool try_compile_set_by_index_of_mixed(VertexPtr root, CodeGenerator& W) { if (auto set = root.try_as()) { auto lhs = set->lhs(); auto rhs = set->rhs(); @@ -2165,17 +2094,12 @@ bool try_compile_set_by_index_of_mixed(VertexPtr root, CodeGenerator &W) { return false; } -void compile_safe_version(VertexPtr root, CodeGenerator &W) { +void compile_safe_version(VertexPtr root, CodeGenerator& W) { if (auto set_value = root.try_as()) { TmpExpr key{set_value->key()}; TmpExpr value{set_value->value()}; - W << "SAFE_SET_VALUE " << MacroBegin{} << - set_value->array() << ", " << - key << ", " << - TypeName(key.get_type()) << ", " << - value << ", " << - TypeName(value.get_type()) << - MacroEnd{}; + W << "SAFE_SET_VALUE " << MacroBegin{} << set_value->array() << ", " << key << ", " << TypeName(key.get_type()) << ", " << value << ", " + << TypeName(value.get_type()) << MacroEnd{}; } else if (OpInfo::rl(root->type()) == rl_set) { if (try_compile_set_by_index_of_mixed(root, W)) { return; @@ -2189,30 +2113,18 @@ void compile_safe_version(VertexPtr root, CodeGenerator &W) { kphp_fail(); } TmpExpr rhs{op->rhs()}; - W << op->lhs() << ", " << - OpInfo::str(root->type()) << ", " << - rhs << ", " << - TypeName(rhs.get_type()) << - MacroEnd{}; + W << op->lhs() << ", " << OpInfo::str(root->type()) << ", " << rhs << ", " << TypeName(rhs.get_type()) << MacroEnd{}; } else if (auto pb = root.try_as()) { TmpExpr value{pb->value()}; - W << "SAFE_PUSH_BACK " << MacroBegin{} << - pb->array() << ", " << - value << ", " << - TypeName(value.get_type()) << - MacroEnd{}; + W << "SAFE_PUSH_BACK " << MacroBegin{} << pb->array() << ", " << value << ", " << TypeName(value.get_type()) << MacroEnd{}; } else if (auto pb = root.try_as()) { TmpExpr value{pb->value()}; - W << "SAFE_PUSH_BACK_RETURN " << MacroBegin{} << - pb->array() << ", " << - value << ", " << - TypeName(value.get_type()) << - MacroEnd{}; + W << "SAFE_PUSH_BACK_RETURN " << MacroBegin{} << pb->array() << ", " << value << ", " << TypeName(value.get_type()) << MacroEnd{}; } else if (root->type() == op_array) { compile_array(root.as(), W); return; } else if (auto index = root.try_as()) { - kphp_assert (index->has_key()); + kphp_assert(index->has_key()); TmpExpr key{index->key()}; vk::string_view pre{}; vk::string_view past{}; @@ -2222,14 +2134,12 @@ void compile_safe_version(VertexPtr root, CodeGenerator &W) { } W << pre << "SAFE_INDEX " << MacroBegin{} << index->array() << ", " << key << ", " << TypeName(key.get_type()) << MacroEnd{} << past; } else { - kphp_error (0, fmt_format("Safe version of [{}] is not supported", OpInfo::str(root->type()))); + kphp_error(0, fmt_format("Safe version of [{}] is not supported", OpInfo::str(root->type()))); kphp_fail(); } - } - -void compile_set_value(VertexAdaptor root, CodeGenerator &W) { +void compile_set_value(VertexAdaptor root, CodeGenerator& W) { W << "(" << root->array() << ").set_value (" << root->key() << ", " << root->value(); if (auto precomputed_hash = can_use_precomputed_hash_indexing_array(root->key())) { W << ", " << precomputed_hash << "_i64"; @@ -2240,24 +2150,23 @@ void compile_set_value(VertexAdaptor root, CodeGenerator &W) { // and a tuple will give an error; in the end we get only array/var here } -void compile_push_back(VertexAdaptor root, CodeGenerator &W) { +void compile_push_back(VertexAdaptor root, CodeGenerator& W) { W << "(" << root->array() << ").push_back (" << root->value() << ")"; } -void compile_push_back_return(VertexAdaptor root, CodeGenerator &W) { +void compile_push_back_return(VertexAdaptor root, CodeGenerator& W) { W << "(" << root->array() << ").push_back_return (" << root->value() << ")"; } - -void compile_string(VertexAdaptor root, CodeGenerator &W) { +void compile_string(VertexAdaptor root, CodeGenerator& W) { W << "string (" << RawString(root->str_val) << ", " << root->str_val.size() << ")"; } -void compile_string_build(VertexAdaptor root, CodeGenerator &W) { +void compile_string_build(VertexAdaptor root, CodeGenerator& W) { compile_string_build_as_string(root, W); } -void compile_break_continue(VertexAdaptor root, CodeGenerator &W) { +void compile_break_continue(VertexAdaptor root, CodeGenerator& W) { if (root->int_val != 0) { W << "goto " << LabelName{root->int_val}; } else { @@ -2266,19 +2175,17 @@ void compile_break_continue(VertexAdaptor root, CodeGenerator &W) } else if (root->type() == op_continue) { W << "continue"; } else { - assert (0); + assert(0); } } } template -void compile_conv_l(VertexAdaptor root, CodeGenerator &W) { +void compile_conv_l(VertexAdaptor root, CodeGenerator& W) { static_assert(vk::any_of_equal(op_conv_l, op_conv_array_l, op_conv_int_l, op_conv_string_l), "unexpected conv_op"); VertexPtr val = root->expr(); PrimitiveType tp = tinf::get_type(val)->get_real_ptype(); - if (tp == tp_mixed || - (op_conv_l == op_conv_array_l && tp == tp_array) || - (op_conv_l == op_conv_int_l && tp == tp_int) || + if (tp == tp_mixed || (op_conv_l == op_conv_array_l && tp == tp_array) || (op_conv_l == op_conv_int_l && tp == tp_int) || (op_conv_l == op_conv_string_l && tp == tp_string)) { std::string fun_name = "unknown"; if (auto cur_fun = stage::get_function()) { @@ -2286,242 +2193,241 @@ void compile_conv_l(VertexAdaptor root, CodeGenerator &W) { } W << OpInfo::str(op_conv_l) << " (" << val << ", R\"(" << fun_name << ")\")"; } else { - kphp_error (0, fmt_format("Trying to pass incompatible type as reference to '{}'", root->get_string())); + kphp_error(0, fmt_format("Trying to pass incompatible type as reference to '{}'", root->get_string())); } } -void compile_cycle_op(VertexPtr root, CodeGenerator &W) { +void compile_cycle_op(VertexPtr root, CodeGenerator& W) { Operation tp = root->type(); switch (tp) { - case op_while: - compile_while(root.as(), W); - break; - case op_do: - compile_do(root.as(), W); - break; - case op_for: - compile_for(root.as(), W); - break; - case op_foreach: - compile_foreach(root.as(), W); - break; - case op_switch: - compile_switch(root.as(), W); - break; - default: - assert (0); - break; - } -} - - -void compile_common_op(VertexPtr root, CodeGenerator &W) { + case op_while: + compile_while(root.as(), W); + break; + case op_do: + compile_do(root.as(), W); + break; + case op_for: + compile_for(root.as(), W); + break; + case op_foreach: + compile_foreach(root.as(), W); + break; + case op_switch: + compile_switch(root.as(), W); + break; + default: + assert(0); + break; + } +} + +void compile_common_op(VertexPtr root, CodeGenerator& W) { Operation tp = root->type(); std::string str; switch (tp) { - case op_seq: - W << BEGIN << AsSeq{root.as()} << END; - break; - case op_seq_rval: - compile_seq_rval(root, W); - break; - - case op_int_const: - W << IntLit{root.as()->str_val}; - break; - case op_float_const: - str = root.as()->str_val; - W << "(double)" << str; - break; - case op_false: - W << "false"; - break; - case op_true: - W << "true"; - break; - case op_null: - W << "Optional{}"; - break; - case op_var: { - VarPtr var_id = root.as()->var_id; - if (var_id->is_constant()) { - // auto-extracted constant variables (const strings, arrays, etc.) in codegen are C++ variables - W << var_id->name; - } else if (var_id->is_in_global_scope() && !var_id->is_foreach_reference) { - // mutable globals, as opposed, are not C++ variables: instead, - // they all are placed in linear memory chunks, see php-script-globals.h - // with the only exception of `foreach (... as &$ref)` in global scope, see compile_foreach_ref_header() - W << GlobalVarInPhpGlobals(var_id); - } else { - W << VarName(var_id); + case op_seq: + W << BEGIN << AsSeq{root.as()} << END; + break; + case op_seq_rval: + compile_seq_rval(root, W); + break; + + case op_int_const: + W << IntLit{root.as()->str_val}; + break; + case op_float_const: + str = root.as()->str_val; + W << "(double)" << str; + break; + case op_false: + W << "false"; + break; + case op_true: + W << "true"; + break; + case op_null: + W << "Optional{}"; + break; + case op_var: { + VarPtr var_id = root.as()->var_id; + if (var_id->is_constant()) { + // auto-extracted constant variables (const strings, arrays, etc.) in codegen are C++ variables + W << var_id->name; + } else if (var_id->is_in_global_scope() && !var_id->is_foreach_reference) { + // mutable globals, as opposed, are not C++ variables: instead, + // they all are placed in linear memory chunks, see php-script-globals.h + // with the only exception of `foreach (... as &$ref)` in global scope, see compile_foreach_ref_header() + W << GlobalVarInPhpGlobals(var_id); + } else { + W << VarName(var_id); + } + break; + } + case op_string: + compile_string(root.as(), W); + break; + + case op_if: + compile_if(root.as(), W); + break; + case op_return: + compile_return(root.as(), W); + break; + case op_global: + case op_static: + // already processed + break; + case op_throw: + compile_throw(root.as(), W); + break; + case op_continue: + case op_break: + compile_break_continue(root.as(), W); + break; + case op_try: + compile_try(root.as(), W); + break; + case op_fork: + compile_fork(root.as(), W); + break; + case op_async: + compile_async(root.as(), W); + break; + case op_function: + compile_function(root.as(), W); + break; + case op_ffi_cdata_value_ref: + compile_ffi_cdata_value_ref(root.as(), W); + break; + case op_ffi_new: + compile_ffi_new(root.as(), W); + break; + case op_ffi_addr: + compile_ffi_addr(root.as(), W); + break; + case op_ffi_cast: + compile_ffi_cast(root.as(), W); + break; + case op_ffi_load_call: + compile_ffi_load_call(root.as(), W); + break; + case op_ffi_array_get: + compile_ffi_array_get(root.as(), W); + break; + case op_ffi_array_set: + compile_ffi_array_set(root.as(), W); + break; + case op_func_call: + compile_func_call_fast(root.as(), W); + break; + case op_callback_of_builtin: + compile_callback_of_builtin(root.as(), W); + break; + case op_string_build: + compile_string_build(root.as(), W); + break; + case op_index: + compile_index(root.as(), W); + break; + case op_instance_prop: + compile_instance_prop(root.as(), W); + break; + case op_isset: + compile_xset(root.as(), W); + break; + case op_list: + compile_list(root.as(), W); + break; + case op_array: + compile_array(root.as(), W); + break; + case op_tuple: + compile_tuple(root.as(), W); + break; + case op_shape: + compile_shape(root.as(), W); + break; + case op_unset: + compile_xset(root.as(), W); + break; + case op_empty: + case op_phpdoc_var: + break; + case op_defined: + compile_defined(root.as(), W); + break; + case op_conv_array_l: + compile_conv_l(root.as(), W); + break; + case op_conv_int_l: + compile_conv_l(root.as(), W); + break; + case op_conv_string_l: + compile_conv_l(root.as(), W); + break; + case op_set_value: + compile_set_value(root.as(), W); + break; + case op_push_back: + compile_push_back(root.as(), W); + break; + case op_push_back_return: + compile_push_back_return(root.as(), W); + break; + case op_noerr: + compile_noerr(root.as(), W); + break; + case op_clone: { + const auto* tp = tinf::get_type(root); + if (auto klass = tp->class_type()) { + if (klass->is_class()) { + W << root.as()->expr() << ".clone()"; + break; } - break; - } - case op_string: - compile_string(root.as(), W); - break; - - case op_if: - compile_if(root.as(), W); - break; - case op_return: - compile_return(root.as(), W); - break; - case op_global: - case op_static: - //already processed - break; - case op_throw: - compile_throw(root.as(), W); - break; - case op_continue: - case op_break: - compile_break_continue(root.as(), W); - break; - case op_try: - compile_try(root.as(), W); - break; - case op_fork: - compile_fork(root.as(), W); - break; - case op_async: - compile_async(root.as(), W); - break; - case op_function: - compile_function(root.as(), W); - break; - case op_ffi_cdata_value_ref: - compile_ffi_cdata_value_ref(root.as(), W); - break; - case op_ffi_new: - compile_ffi_new(root.as(), W); - break; - case op_ffi_addr: - compile_ffi_addr(root.as(), W); - break; - case op_ffi_cast: - compile_ffi_cast(root.as(), W); - break; - case op_ffi_load_call: - compile_ffi_load_call(root.as(), W); - break; - case op_ffi_array_get: - compile_ffi_array_get(root.as(), W); - break; - case op_ffi_array_set: - compile_ffi_array_set(root.as(), W); - break; - case op_func_call: - compile_func_call_fast(root.as(), W); - break; - case op_callback_of_builtin: - compile_callback_of_builtin(root.as(), W); - break; - case op_string_build: - compile_string_build(root.as(), W); - break; - case op_index: - compile_index(root.as(), W); - break; - case op_instance_prop: - compile_instance_prop(root.as(), W); - break; - case op_isset: - compile_xset(root.as(), W); - break; - case op_list: - compile_list(root.as(), W); - break; - case op_array: - compile_array(root.as(), W); - break; - case op_tuple: - compile_tuple(root.as(), W); - break; - case op_shape: - compile_shape(root.as(), W); - break; - case op_unset: - compile_xset(root.as(), W); - break; - case op_empty: - case op_phpdoc_var: - break; - case op_defined: - compile_defined(root.as(), W); - break; - case op_conv_array_l: - compile_conv_l(root.as(), W); - break; - case op_conv_int_l: - compile_conv_l(root.as(), W); - break; - case op_conv_string_l: - compile_conv_l(root.as(), W); - break; - case op_set_value: - compile_set_value(root.as(), W); - break; - case op_push_back: - compile_push_back(root.as(), W); - break; - case op_push_back_return: - compile_push_back_return(root.as(), W); - break; - case op_noerr: - compile_noerr(root.as(), W); - break; - case op_clone: { - const auto *tp = tinf::get_type(root); - if (auto klass = tp->class_type()) { - if (klass->is_class()) { - W << root.as()->expr() << ".clone()"; - break; - } - if (klass->is_ffi_cdata()) { - W << "ffi_clone(" << root.as()->expr() << ")"; - break; - } + if (klass->is_ffi_cdata()) { + W << "ffi_clone(" << root.as()->expr() << ")"; + break; } - kphp_error_return(false, "unsupported operand for cloning"); - break; - } - case op_alloc: { - const TypeData *tp = tinf::get_type(root); - kphp_assert(tp->ptype() == tp_Class); - const auto *alloc_function = tp->class_type()->is_empty_class() ? "().empty_alloc()" : "().alloc()"; - W << TypeName(tp) << alloc_function; - break; - } - case op_arr_acc_set_return: { - auto v = root.as(); - W << "ARR_ACC_SET_RETURN" << MacroBegin{} << v->obj() << ", " << v->offset() << ", " << v->value() << ", " - << "f$" << v->set_method->name << MacroEnd{}; - break; } - case op_arr_acc_check_and_get: { - auto v = root.as(); - - if (v->is_empty) { - W << "ARR_ACC_GET_IF_NOT_EMPTY"; - } else { - W << "ARR_ACC_GET_IF_ISSET"; - } + kphp_error_return(false, "unsupported operand for cloning"); + break; + } + case op_alloc: { + const TypeData* tp = tinf::get_type(root); + kphp_assert(tp->ptype() == tp_Class); + const auto* alloc_function = tp->class_type()->is_empty_class() ? "().empty_alloc()" : "().alloc()"; + W << TypeName(tp) << alloc_function; + break; + } + case op_arr_acc_set_return: { + auto v = root.as(); + W << "ARR_ACC_SET_RETURN" << MacroBegin{} << v->obj() << ", " << v->offset() << ", " << v->value() << ", " + << "f$" << v->set_method->name << MacroEnd{}; + break; + } + case op_arr_acc_check_and_get: { + auto v = root.as(); - W << MacroBegin{} << v->obj() << ", " << v->offset() << ", " - << "f$" << v->check_method->name << ", " - << "f$" << v->get_method->name << MacroEnd{}; - break; + if (v->is_empty) { + W << "ARR_ACC_GET_IF_NOT_EMPTY"; + } else { + W << "ARR_ACC_GET_IF_ISSET"; } - default: - kphp_fail(); - break; + + W << MacroBegin{} << v->obj() << ", " << v->offset() << ", " + << "f$" << v->check_method->name << ", " + << "f$" << v->get_method->name << MacroEnd{}; + break; + } + default: + kphp_fail(); + break; } } } // anonymous namespace -void compile_vertex(VertexPtr root, CodeGenerator &W) { +void compile_vertex(VertexPtr root, CodeGenerator& W) { OperationType tp = OpInfo::type(root->type()); W << UpdateLocation(root->location); @@ -2538,32 +2444,32 @@ void compile_vertex(VertexPtr root, CodeGenerator &W) { compile_safe_version(root, W); } else { switch (tp) { - case prefix_op: - compile_prefix_op(root.as(), W); - break; - case postfix_op: - compile_postfix_op(root.as(), W); - break; - case binary_op: - case binary_func_op: - compile_binary_op(root.as(), W); - break; - case ternary_op: - compile_ternary_op(root.as(), W); - break; - case common_op: - compile_common_op(root, W); - break; - case cycle_op: - compile_cycle_op(root, W); - break; - case conv_op: - compile_conv_op(root.as(), W); - break; - default: - fmt_print("{}: {}\n", vk::to_underlying(tp), vk::to_underlying(root->type())); - assert (0); - break; + case prefix_op: + compile_prefix_op(root.as(), W); + break; + case postfix_op: + compile_postfix_op(root.as(), W); + break; + case binary_op: + case binary_func_op: + compile_binary_op(root.as(), W); + break; + case ternary_op: + compile_ternary_op(root.as(), W); + break; + case common_op: + compile_common_op(root, W); + break; + case cycle_op: + compile_cycle_op(root, W); + break; + case conv_op: + compile_conv_op(root.as(), W); + break; + default: + fmt_print("{}: {}\n", vk::to_underlying(tp), vk::to_underlying(root->type())); + assert(0); + break; } } diff --git a/compiler/code-gen/vertex-compiler.h b/compiler/code-gen/vertex-compiler.h index 2a24e25507..d1cbb28133 100644 --- a/compiler/code-gen/vertex-compiler.h +++ b/compiler/code-gen/vertex-compiler.h @@ -7,10 +7,10 @@ #include "compiler/code-gen/code-generator.h" #include "compiler/data/vertex-adaptor.h" -void compile_vertex(VertexPtr root, CodeGenerator &W); +void compile_vertex(VertexPtr root, CodeGenerator& W); template -CodeGenerator& operator<<(CodeGenerator &W, VertexAdaptor root) { +CodeGenerator& operator<<(CodeGenerator& W, VertexAdaptor root) { compile_vertex(root, W); return W; } diff --git a/compiler/code-gen/writer-data.cpp b/compiler/code-gen/writer-data.cpp index f990394822..c42b593827 100644 --- a/compiler/code-gen/writer-data.cpp +++ b/compiler/code-gen/writer-data.cpp @@ -4,18 +4,17 @@ #include "compiler/code-gen/writer-data.h" +#include "common/wrappers/fmt_format.h" #include "compiler/data/src-file.h" #include "compiler/stage.h" -#include "common/wrappers/fmt_format.h" -WriterData::WriterData(File *file, bool compile_with_crc) : - file(file), - lines(), - text(), - hash_of_cpp(-1), - hash_of_comments(-1), - compile_with_crc_flag(compile_with_crc) { -} +WriterData::WriterData(File* file, bool compile_with_crc) + : file(file), + lines(), + text(), + hash_of_cpp(-1), + hash_of_comments(-1), + compile_with_crc_flag(compile_with_crc) {} void WriterData::begin_line() { lines.emplace_back((int)text.size()); @@ -37,10 +36,7 @@ void WriterData::add_location(SrcFilePtr file, int line) { if (lines.back().file && !(lines.back().file == file)) { return; } - kphp_error ( - !lines.back().file || lines.back().file == file, - fmt_format("{}|{}", file->file_name, lines.back().file->file_name) - ); + kphp_error(!lines.back().file || lines.back().file == file, fmt_format("{}|{}", file->file_name, lines.back().file->file_name)); lines.back().file = file; if (line != -1) { lines.back().line_ids.insert(line); @@ -52,14 +48,14 @@ void WriterData::set_calculated_hashes(unsigned long long int hash_of_cpp, unsig this->hash_of_comments = hash_of_comments; } -void WriterData::write_code(std::string &dest_str, const Line &line) { - const char *s = &text[line.begin_pos]; +void WriterData::write_code(std::string& dest_str, const Line& line) { + const char* s = &text[line.begin_pos]; int length = line.end_pos - line.begin_pos; dest_str.append(s, length); dest_str += '\n'; } -void WriterData::dump(std::string &dest_str, const std::vector::iterator &begin, const std::vector::iterator &end, SrcFilePtr file) { +void WriterData::dump(std::string& dest_str, const std::vector::iterator& begin, const std::vector::iterator& end, SrcFilePtr file) { int l = (int)1e9, r = -1; if (file) { @@ -132,13 +128,12 @@ void WriterData::dump(std::string &dest_str, const std::vector::iterator & } } - if (t == 0) { if (r == -1) { l = -1; } - //fprintf (stderr, "l = %d, r = %d\n", l, r); - assert (l <= r); + // fprintf (stderr, "l = %d, r = %d\n", l, r); + assert(l <= r); rev.resize(r - l + 1, -1); } else if (t == 2) { while (cur_line != end) { @@ -147,10 +142,9 @@ void WriterData::dump(std::string &dest_str, const std::vector::iterator & } } } - } -void WriterData::dump(std::string &dest_str) { +void WriterData::dump(std::string& dest_str) { for (auto i = lines.begin(); i != lines.end();) { if (!i->file) { dump(dest_str, i, i + 1, SrcFilePtr()); @@ -158,10 +152,7 @@ void WriterData::dump(std::string &dest_str) { continue; } - auto j = std::find_if(std::next(i), lines.end(), - [i](const Line &l) { - return (l.file && i->file != l.file) || l.brk; - }); + auto j = std::find_if(std::next(i), lines.end(), [i](const Line& l) { return (l.file && i->file != l.file) || l.brk; }); dump(dest_str, i, j, i->file); i = j; } diff --git a/compiler/code-gen/writer-data.h b/compiler/code-gen/writer-data.h index 56d796371b..549fa2f6e0 100644 --- a/compiler/code-gen/writer-data.h +++ b/compiler/code-gen/writer-data.h @@ -21,10 +21,11 @@ class WriterData { bool brk = false; std::set line_ids; Line() = default; - explicit Line(int begin_pos) : begin_pos(begin_pos){} + explicit Line(int begin_pos) + : begin_pos(begin_pos) {} }; - File *file; + File* file; std::vector lines; std::string text; @@ -33,14 +34,13 @@ class WriterData { bool compile_with_crc_flag; - - void write_code(std::string &dest_str, const Line &line); - void dump(std::string &dest_str, const std::vector::iterator &begin, const std::vector::iterator &end, SrcFilePtr file); + void write_code(std::string& dest_str, const Line& line); + void dump(std::string& dest_str, const std::vector::iterator& begin, const std::vector::iterator& end, SrcFilePtr file); public: - explicit WriterData(File *file, bool compile_with_crc); + explicit WriterData(File* file, bool compile_with_crc); - void append(const char *begin, size_t length) { + void append(const char* begin, size_t length) { text.append(begin, length); } void append(size_t n, char c) { @@ -56,10 +56,18 @@ class WriterData { void add_location(SrcFilePtr file, int line); void set_calculated_hashes(unsigned long long hash_of_cpp, unsigned long long hash_of_comments); - unsigned long long get_hash_of_cpp() { return hash_of_cpp; } - unsigned long long get_hash_of_comments() { return hash_of_comments; } - void dump(std::string &dest_str); + unsigned long long get_hash_of_cpp() { + return hash_of_cpp; + } + unsigned long long get_hash_of_comments() { + return hash_of_comments; + } + void dump(std::string& dest_str); - File *get_file() const { return file; } - bool compile_with_crc() const { return compile_with_crc_flag; } + File* get_file() const { + return file; + } + bool compile_with_crc() const { + return compile_with_crc_flag; + } }; diff --git a/compiler/compiler-core.cpp b/compiler/compiler-core.cpp index a07ac010af..df6ba50dc0 100644 --- a/compiler/compiler-core.cpp +++ b/compiler/compiler-core.cpp @@ -5,12 +5,12 @@ #include "compiler/compiler-core.h" #include -#include #include +#include #include "common/algorithms/contains.h" -#include "common/wrappers/mkdir_recursive.h" #include "common/smart_ptrs/unique_ptr_with_delete_function.h" +#include "common/wrappers/mkdir_recursive.h" #include "compiler/const-manipulations.h" #include "compiler/data/composer-json-data.h" @@ -27,11 +27,11 @@ namespace { -void close_dir(DIR *d) { +void close_dir(DIR* d) { closedir(d); } -void collect_composer_folders(const std::string &path, std::vector &result) { +void collect_composer_folders(const std::string& path, std::vector& result) { // can't use nftw here as it doesn't provide a portable way to stop directory traversal; // we don't want to visit *all* files in the vendor tree // @@ -58,7 +58,7 @@ void collect_composer_folders(const std::string &path, std::vector bool recurse = true; std::vector dirs; - while (const auto *entry = readdir(dp.get())) { + while (const auto* entry = readdir(dp.get())) { if (entry->d_name[0] == '.') { continue; } @@ -84,26 +84,25 @@ void collect_composer_folders(const std::string &path, std::vector } if (recurse) { - for (const auto &dir : dirs) { + for (const auto& dir : dirs) { collect_composer_folders(dir, result); } } } // Collect all composer.json file roots that can be found in the given directory. -std::vector find_composer_folders(const std::string &dir) { +std::vector find_composer_folders(const std::string& dir) { std::vector result; collect_composer_folders(dir, result); return result; } -} +} // namespace -static FunctionPtr UNPARSED_BUT_REQUIRED_FUNC_PTR = FunctionPtr(reinterpret_cast(0x0001)); +static FunctionPtr UNPARSED_BUT_REQUIRED_FUNC_PTR = FunctionPtr(reinterpret_cast(0x0001)); -CompilerCore::CompilerCore() : - settings_(nullptr) { -} +CompilerCore::CompilerCore() + : settings_(nullptr) {} void CompilerCore::start() { stage::die_if_global_errors(); @@ -122,7 +121,7 @@ void CompilerCore::finish() { settings_ = nullptr; } -void CompilerCore::register_settings(CompilerSettings *settings) { +void CompilerCore::register_settings(CompilerSettings* settings) { kphp_assert(settings_ == nullptr); settings_ = settings; const auto mode = settings->mode.get(); @@ -146,18 +145,18 @@ void CompilerCore::register_settings(CompilerSettings *settings) { } } -const CompilerSettings &CompilerCore::settings() const { - kphp_assert (settings_ != nullptr); +const CompilerSettings& CompilerCore::settings() const { + kphp_assert(settings_ != nullptr); return *settings_; } -const std::string &CompilerCore::get_global_namespace() const { +const std::string& CompilerCore::get_global_namespace() const { return settings().static_lib_name.get(); } -FunctionPtr CompilerCore::get_function(const std::string &name) { - auto *node = functions_ht.at(vk::std_hash(name)); - AutoLocker locker(node); +FunctionPtr CompilerCore::get_function(const std::string& name) { + auto* node = functions_ht.at(vk::std_hash(name)); + AutoLocker locker(node); if (!node->data || node->data == UNPARSED_BUT_REQUIRED_FUNC_PTR) { return {}; } @@ -167,13 +166,13 @@ FunctionPtr CompilerCore::get_function(const std::string &name) { return f; } -std::string CompilerCore::search_file_in_include_dirs(const std::string &file_name, size_t *dir_index) const { +std::string CompilerCore::search_file_in_include_dirs(const std::string& file_name, size_t* dir_index) const { if (file_name.empty() || file_name[0] == '/' || file_name[0] == '.') { return {}; } std::string full_file_name; size_t index = 0; - const auto &includes = settings().includes.get(); + const auto& includes = settings().includes.get(); for (; index < includes.size() && full_file_name.empty(); ++index) { full_file_name = get_full_path(includes[index] + file_name); } @@ -185,7 +184,7 @@ std::string CompilerCore::search_file_in_include_dirs(const std::string &file_na // search_required_file resolves the file_name like it would be expanded when user as require() argument; // it uses search_file_in_include_dirs as well as the current file relative search -std::string CompilerCore::search_required_file(const std::string &file_name) const { +std::string CompilerCore::search_required_file(const std::string& file_name) const { std::string full_file_name = search_file_in_include_dirs(file_name); if (file_name[0] == '/') { return get_full_path(file_name); @@ -197,7 +196,7 @@ std::string CompilerCore::search_required_file(const std::string &file_name) con if (from_file) { std::string from_file_name = from_file->file_name; size_t en = from_file_name.find_last_of('/'); - assert (en != std::string::npos); + assert(en != std::string::npos); std::string cur_dir = from_file_name.substr(0, en + 1); cur_include_dirs.push_back(cur_dir); if (from_file->owner_lib) { @@ -216,7 +215,7 @@ std::string CompilerCore::search_required_file(const std::string &file_name) con return full_file_name; } -FFIRoot &CompilerCore::get_ffi_root() { +FFIRoot& CompilerCore::get_ffi_root() { return ffi; } @@ -224,7 +223,6 @@ OutputMode CompilerCore::get_output_mode() const { return output_mode; } - vk::string_view CompilerCore::calc_relative_name(SrcFilePtr file, bool builtin) const { vk::string_view full_file_name = file->file_name; if (full_file_name.starts_with(settings_->base_dir.get())) { @@ -238,7 +236,7 @@ vk::string_view CompilerCore::calc_relative_name(SrcFilePtr file, bool builtin) } } -SrcFilePtr CompilerCore::register_file(const std::string &file_name, LibPtr owner_lib, bool builtin) { +SrcFilePtr CompilerCore::register_file(const std::string& file_name, LibPtr owner_lib, bool builtin) { if (file_name.empty()) { return {}; } @@ -265,10 +263,10 @@ SrcFilePtr CompilerCore::register_file(const std::string &file_name, LibPtr owne short_file_name += extension; } - //register file if needed - TSHashTable::HTNode *node = file_ht.at(vk::std_hash(full_file_name)); + // register file if needed + TSHashTable::HTNode* node = file_ht.at(vk::std_hash(full_file_name)); if (!node->data) { - AutoLocker locker(node); + AutoLocker locker(node); if (!node->data) { SrcFilePtr new_file = SrcFilePtr(new SrcFile(full_file_name, short_file_name, owner_lib)); new_file->is_from_functions_file = builtin; @@ -282,9 +280,9 @@ SrcFilePtr CompilerCore::register_file(const std::string &file_name, LibPtr owne } } - TSHashTable::HTNode *node_file_dir = dirs_ht.at(vk::std_hash(full_dir_name)); + TSHashTable::HTNode* node_file_dir = dirs_ht.at(vk::std_hash(full_dir_name)); if (!node_file_dir->data) { - AutoLocker locker(node_file_dir); + AutoLocker locker(node_file_dir); if (!node_file_dir->data) { node_file_dir->data = register_dir(full_dir_name); } @@ -307,22 +305,22 @@ SrcDirPtr CompilerCore::register_dir(vk::string_view full_dir_name) { size_t last_pos_of_slash = full_dir_name.rfind('/', full_dir_name.size() - 2); vk::string_view parent_dir_name = full_dir_name.substr(0, last_pos_of_slash + 1); - TSHashTable::HTNode *node_parent_dir = dirs_ht.at(vk::std_hash(parent_dir_name)); + TSHashTable::HTNode* node_parent_dir = dirs_ht.at(vk::std_hash(parent_dir_name)); if (!node_parent_dir->data) { - AutoLocker locker(node_parent_dir); + AutoLocker locker(node_parent_dir); if (!node_parent_dir->data) { node_parent_dir->data = register_dir(parent_dir_name); } } dir->parent_dir = node_parent_dir->data; -// printf("%s -> %s\n", dir->full_dir_name.c_str(), dir->parent_dir->full_dir_name.c_str()); + // printf("%s -> %s\n", dir->full_dir_name.c_str(), dir->parent_dir->full_dir_name.c_str()); } return dir; } -void CompilerCore::require_function(const std::string &name, DataStream &os) { - operate_on_function_locking(name, [&](FunctionPtr &f) { +void CompilerCore::require_function(const std::string& name, DataStream& os) { + operate_on_function_locking(name, [&](FunctionPtr& f) { if (!f) { f = UNPARSED_BUT_REQUIRED_FUNC_PTR; } else if (f != UNPARSED_BUT_REQUIRED_FUNC_PTR) { @@ -331,7 +329,7 @@ void CompilerCore::require_function(const std::string &name, DataStream &os) { +void CompilerCore::require_function(FunctionPtr function, DataStream& os) { if (!function->is_required) { function->is_required = true; os << function; @@ -339,13 +337,13 @@ void CompilerCore::require_function(FunctionPtr function, DataStreamis_required); } -void CompilerCore::register_and_require_function(FunctionPtr function, DataStream &os, bool force_require /*= false*/) { - operate_on_function_locking(function->name, [&](FunctionPtr &f) { +void CompilerCore::register_and_require_function(FunctionPtr function, DataStream& os, bool force_require /*= false*/) { + operate_on_function_locking(function->name, [&](FunctionPtr& f) { bool was_previously_required = f == UNPARSED_BUT_REQUIRED_FUNC_PTR; kphp_error(!f || was_previously_required, fmt_format("Redeclaration of function {}(), the previous declaration was in {}", function->as_human_readable(), f->file_id->file_name)); @@ -381,8 +379,8 @@ void CompilerCore::register_and_require_function(FunctionPtr function, DataStrea } ClassPtr CompilerCore::try_register_class(ClassPtr cur_class) { - TSHashTable::HTNode *node = classes_ht.at(vk::std_hash(cur_class->name)); - AutoLocker locker(node); + TSHashTable::HTNode* node = classes_ht.at(vk::std_hash(cur_class->name)); + AutoLocker locker(node); if (!node->data) { node->data = cur_class; } @@ -391,14 +389,14 @@ ClassPtr CompilerCore::try_register_class(ClassPtr cur_class) { bool CompilerCore::register_class(ClassPtr cur_class) { auto registered_class = try_register_class(cur_class); - kphp_error (registered_class == cur_class, - fmt_format("Redeclaration of class {}, the previous declaration was in {}", cur_class->name, registered_class->file_id->file_name)); + kphp_error(registered_class == cur_class, + fmt_format("Redeclaration of class {}, the previous declaration was in {}", cur_class->name, registered_class->file_id->file_name)); return registered_class == cur_class; } LibPtr CompilerCore::register_lib(LibPtr lib) { - TSHashTable::HTNode *node = libs_ht.at(vk::std_hash(lib->lib_namespace())); - AutoLocker locker(node); + TSHashTable::HTNode* node = libs_ht.at(vk::std_hash(lib->lib_namespace())); + AutoLocker locker(node); if (!node->data) { node->data = lib; } @@ -406,22 +404,24 @@ LibPtr CompilerCore::register_lib(LibPtr lib) { } ModulitePtr CompilerCore::register_modulite(ModulitePtr modulite) { - auto *node = modulites_ht.at(vk::std_hash(modulite->modulite_name)); - AutoLocker locker(node); - kphp_error(!node->data, fmt_format("Redeclaration of modulite {}, declared in:\n- {}\n- {}", modulite->modulite_name, modulite->yaml_file->relative_file_name, node->data->yaml_file->relative_file_name)); + auto* node = modulites_ht.at(vk::std_hash(modulite->modulite_name)); + AutoLocker locker(node); + kphp_error(!node->data, fmt_format("Redeclaration of modulite {}, declared in:\n- {}\n- {}", modulite->modulite_name, modulite->yaml_file->relative_file_name, + node->data->yaml_file->relative_file_name)); node->data = modulite; return node->data; } ModulitePtr CompilerCore::get_modulite(vk::string_view name) { - const auto *result = modulites_ht.find(vk::std_hash(name)); + const auto* result = modulites_ht.find(vk::std_hash(name)); return result ? *result : ModulitePtr{}; } ComposerJsonPtr CompilerCore::register_composer_json(ComposerJsonPtr composer_json) { - auto *node = composer_json_ht.at(vk::std_hash(composer_json->package_name)); - AutoLocker locker(node); - kphp_error(!node->data, fmt_format("Redeclaration of composer package {}, declared in:\n- {}\n- {}", composer_json->package_name, composer_json->json_file->relative_file_name, node->data->json_file->relative_file_name)); + auto* node = composer_json_ht.at(vk::std_hash(composer_json->package_name)); + AutoLocker locker(node); + kphp_error(!node->data, fmt_format("Redeclaration of composer package {}, declared in:\n- {}\n- {}", composer_json->package_name, + composer_json->json_file->relative_file_name, node->data->json_file->relative_file_name)); node->data = composer_json; kphp_assert(composer_json->json_file->dir); composer_json->json_file->dir->has_composer_json = true; @@ -429,23 +429,21 @@ ComposerJsonPtr CompilerCore::register_composer_json(ComposerJsonPtr composer_js } ComposerJsonPtr CompilerCore::get_composer_json(vk::string_view name) { - const auto *result = composer_json_ht.find(vk::std_hash(name)); + const auto* result = composer_json_ht.find(vk::std_hash(name)); return result ? *result : ComposerJsonPtr{}; } ComposerJsonPtr CompilerCore::get_composer_json_at_dir(SrcDirPtr dir) { - std::vector at_dir = composer_json_ht.get_all_if([dir](ComposerJsonPtr j) { - return j->json_file->dir == dir; - }); + std::vector at_dir = composer_json_ht.get_all_if([dir](ComposerJsonPtr j) { return j->json_file->dir == dir; }); kphp_assert(at_dir.size() < 2); return at_dir.empty() ? ComposerJsonPtr{} : at_dir.front(); } -void CompilerCore::register_main_file(const std::string &file_name, DataStream &os) { +void CompilerCore::register_main_file(const std::string& file_name, DataStream& os) { kphp_assert(!main_file); SrcFilePtr res = register_file(file_name, LibPtr{}); - kphp_error (file_name.empty() || res, fmt_format("Cannot load main file [{}]", file_name)); + kphp_error(file_name.empty() || res, fmt_format("Cannot load main file [{}]", file_name)); if (res && try_require_file(res)) { main_file = res; @@ -453,44 +451,39 @@ void CompilerCore::register_main_file(const std::string &file_name, DataStream &os, bool error_if_not_exists /* = true */, bool builtin) { +SrcFilePtr CompilerCore::require_file(const std::string& file_name, LibPtr owner_lib, DataStream& os, bool error_if_not_exists /* = true */, + bool builtin) { SrcFilePtr file = register_file(file_name, owner_lib, builtin); - kphp_error (file || !error_if_not_exists, fmt_format("Cannot load file [{}]", file_name)); + kphp_error(file || !error_if_not_exists, fmt_format("Cannot load file [{}]", file_name)); if (file && try_require_file(file)) { os << file; } return file; } - ClassPtr CompilerCore::get_class(vk::string_view name) { - const auto *result = classes_ht.find(vk::std_hash(name)); + const auto* result = classes_ht.find(vk::std_hash(name)); return result ? *result : ClassPtr{}; } ClassPtr CompilerCore::get_memcache_class() { - if (!memcache_class) { // if specific memcache implementation is not set - return get_class("Memcache"); // take it from the functions.txt + if (!memcache_class) { // if specific memcache implementation is not set + return get_class("Memcache"); // take it from the functions.txt } return memcache_class; } void CompilerCore::set_memcache_class(ClassPtr klass) { - kphp_error(!memcache_class || memcache_class == klass, - fmt_format("Duplicate Memcache realization {} and {}", memcache_class->name, klass->name)); + kphp_error(!memcache_class || memcache_class == klass, fmt_format("Duplicate Memcache realization {} and {}", memcache_class->name, klass->name)); memcache_class = klass; } bool CompilerCore::register_define(DefinePtr def_id) { - TSHashTable::HTNode *node = defines_ht.at(vk::std_hash(def_id->name)); - AutoLocker locker(node); + TSHashTable::HTNode* node = defines_ht.at(vk::std_hash(def_id->name)); + AutoLocker locker(node); - kphp_error_act ( - !node->data, - fmt_format("Redeclaration of define [{}], the previous declaration was in [{}]", - def_id->name, node->data->file_id->file_name), - return false - ); + kphp_error_act(!node->data, fmt_format("Redeclaration of define [{}], the previous declaration was in [{}]", def_id->name, node->data->file_id->file_name), + return false); node->data = def_id; return true; @@ -502,11 +495,11 @@ DefinePtr CompilerCore::get_define(std::string_view name) { if (!name.empty() && name.front() == '\\') { name.remove_prefix(1); } - const auto *result = defines_ht.find(vk::std_hash(name)); + const auto* result = defines_ht.find(vk::std_hash(name)); return result ? *result : DefinePtr{}; } -VarPtr CompilerCore::create_var(const std::string &name, VarData::Type type) { +VarPtr CompilerCore::create_var(const std::string& name, VarData::Type type) { VarPtr var = VarPtr(new VarData(type)); var->name = name; var->tinf_node.init_as_variable(var); @@ -514,11 +507,11 @@ VarPtr CompilerCore::create_var(const std::string &name, VarData::Type type) { return var; } -VarPtr CompilerCore::get_global_var(const std::string &name, VertexPtr init_val) { - auto *node = globals_ht.at(vk::std_hash(name)); +VarPtr CompilerCore::get_global_var(const std::string& name, VertexPtr init_val) { + auto* node = globals_ht.at(vk::std_hash(name)); if (!node->data) { - AutoLocker locker(node); + AutoLocker locker(node); if (!node->data) { node->data = create_var(name, VarData::var_global_t); node->data->init_val = init_val; @@ -529,11 +522,11 @@ VarPtr CompilerCore::get_global_var(const std::string &name, VertexPtr init_val) return node->data; } -VarPtr CompilerCore::get_constant_var(const std::string &name, VertexPtr init_val, bool *is_new_inserted) { - auto *node = constants_ht.at(vk::std_hash(name)); +VarPtr CompilerCore::get_constant_var(const std::string& name, VertexPtr init_val, bool* is_new_inserted) { + auto* node = constants_ht.at(vk::std_hash(name)); VarPtr new_var; if (!node->data) { - AutoLocker locker(node); + AutoLocker locker(node); if (!node->data) { new_var = create_var(name, VarData::var_const_t); new_var->init_val = init_val; @@ -545,7 +538,7 @@ VarPtr CompilerCore::get_constant_var(const std::string &name, VertexPtr init_va // it's created by a thread that first found it, and all others just ref to the same node // here we make var->init_val->location stable, as it's sometimes used in code generation (locations of regexps, for example) if (!new_var) { - AutoLocker locker(node); + AutoLocker locker(node); if (node->data->init_val->get_location() < init_val->get_location()) { std::swap(node->data->init_val, init_val); } @@ -563,45 +556,45 @@ VarPtr CompilerCore::get_constant_var(const std::string &name, VertexPtr init_va kphp_assert_msg(var->name == name, fmt_format("bug in compiler (hash collision) {} {}", var->name, name)); switch (init_val->type()) { - case op_string: - kphp_assert(var->init_val->get_string() == init_val->get_string()); - break; - case op_conv_regexp: { - const std::string &new_regexp = init_val.as()->expr().as()->str_val; - const std::string &hashed_regexp = var->init_val.as()->expr().as()->str_val; - kphp_assert_msg(hashed_regexp == new_regexp, fmt_format("hash collision of regexp: {} vs {}", new_regexp, hashed_regexp)); - break; - } - case op_array: { - std::string new_array_repr = VertexPtrFormatter::to_string(init_val); - std::string hashed_array_repr = VertexPtrFormatter::to_string(var->init_val); - kphp_assert_msg(new_array_repr == hashed_array_repr, fmt_format("hash collision of arrays: {} vs {}", new_array_repr, hashed_array_repr)); - break; - } - default: - break; + case op_string: + kphp_assert(var->init_val->get_string() == init_val->get_string()); + break; + case op_conv_regexp: { + const std::string& new_regexp = init_val.as()->expr().as()->str_val; + const std::string& hashed_regexp = var->init_val.as()->expr().as()->str_val; + kphp_assert_msg(hashed_regexp == new_regexp, fmt_format("hash collision of regexp: {} vs {}", new_regexp, hashed_regexp)); + break; + } + case op_array: { + std::string new_array_repr = VertexPtrFormatter::to_string(init_val); + std::string hashed_array_repr = VertexPtrFormatter::to_string(var->init_val); + kphp_assert_msg(new_array_repr == hashed_array_repr, fmt_format("hash collision of arrays: {} vs {}", new_array_repr, hashed_array_repr)); + break; + } + default: + break; } } return var; } -VarPtr CompilerCore::create_local_var(FunctionPtr function, const std::string &name, VarData::Type type) { +VarPtr CompilerCore::create_local_var(FunctionPtr function, const std::string& name, VarData::Type type) { VarPtr var = create_var(name, type); var->holder_func = function; switch (type) { - case VarData::var_local_t: - case VarData::var_local_inplace_t: - function->local_var_ids.push_back(var); - break; - case VarData::var_static_t: - function->static_var_ids.push_back(var); - break; - case VarData::var_param_t: - var->param_i = (int)function->param_ids.size(); - var->tinf_node.init_as_argument(var); - function->param_ids.push_back(var); - break; - default: + case VarData::var_local_t: + case VarData::var_local_inplace_t: + function->local_var_ids.push_back(var); + break; + case VarData::var_static_t: + function->static_var_ids.push_back(var); + break; + case VarData::var_param_t: + var->param_i = (int)function->param_ids.size(); + var->tinf_node.init_as_argument(var); + function->param_ids.push_back(var); + break; + default: kphp_fail(); } return var; @@ -629,9 +622,7 @@ std::vector CompilerCore::get_classes() { } std::vector CompilerCore::get_interfaces() { - return classes_ht.get_all_if([](ClassPtr klass) { - return klass->is_interface(); - }); + return classes_ht.get_all_if([](ClassPtr klass) { return klass->is_interface(); }); } std::vector CompilerCore::get_defines() { @@ -650,7 +641,7 @@ std::vector CompilerCore::get_modulites() { return modulites_ht.get_all(); } -const ComposerAutoloader &CompilerCore::get_composer_autoloader() const { +const ComposerAutoloader& CompilerCore::get_composer_autoloader() const { return composer_class_loader; } @@ -666,27 +657,27 @@ void CompilerCore::save_index() { } } -const Index &CompilerCore::get_index() { +const Index& CompilerCore::get_index() { return cpp_index; } -const Index &CompilerCore::get_runtime_index() { +const Index& CompilerCore::get_runtime_index() { return runtime_sources_index; } -const Index &CompilerCore::get_runtime_core_index() { +const Index& CompilerCore::get_runtime_core_index() { return runtime_common_sources_index; } -const Index &CompilerCore::get_common_index() { +const Index& CompilerCore::get_common_index() { return common_sources_index; } -const Index &CompilerCore::get_unicode_index() { +const Index& CompilerCore::get_unicode_index() { return unicode_sources_index; } -File *CompilerCore::get_file_info(std::string &&file_name) { +File* CompilerCore::get_file_info(std::string&& file_name) { return cpp_index.insert_file(std::move(file_name)); } @@ -783,7 +774,7 @@ void CompilerCore::init_composer_class_loader() { std::string vendor = settings().composer_root.get() + "vendor"; bool vendor_folder_exists = access(vendor.c_str(), F_OK) == 0; if (vendor_folder_exists) { - for (const std::string &composer_root : find_composer_folders(vendor)) { + for (const std::string& composer_root : find_composer_folders(vendor)) { composer_class_loader.load_file(composer_root); } } @@ -813,4 +804,4 @@ void CompilerCore::update_hash_tables_stats() { stats.ht_total_composer_jsons = composer_json_ht.get_size(); } -CompilerCore *G; +CompilerCore* G; diff --git a/compiler/compiler-core.h b/compiler/compiler-core.h index ccd7d62063..d7ed6cc786 100644 --- a/compiler/compiler-core.h +++ b/compiler/compiler-core.h @@ -4,9 +4,8 @@ #pragma once - /*** Core ***/ -//Consists mostly of functions that require synchronization +// Consists mostly of functions that require synchronization #include #include @@ -47,13 +46,14 @@ class CompilerCore { TSHashTable functions_ht; TSHashTable classes_ht; TSHashTable defines_ht; - TSHashTable constants_ht; // auto-collected constants (const strings / arrays / regexps / pure func calls); are inited once in a master process - TSHashTable globals_ht; // mutable globals (vars in global scope, class static fields); are reset for each php script inside worker processes + TSHashTable + constants_ht; // auto-collected constants (const strings / arrays / regexps / pure func calls); are inited once in a master process + TSHashTable globals_ht; // mutable globals (vars in global scope, class static fields); are reset for each php script inside worker processes TSHashTable libs_ht; TSHashTable modulites_ht; TSHashTable composer_json_ht; SrcFilePtr main_file; - CompilerSettings *settings_; + CompilerSettings* settings_; ComposerAutoloader composer_class_loader; OutputMode output_mode; FFIRoot ffi; @@ -80,43 +80,43 @@ class CompilerCore { CompilerCore(); void start(); void finish(); - void register_settings(CompilerSettings *settings); - const CompilerSettings &settings() const; - const std::string &get_global_namespace() const; + void register_settings(CompilerSettings* settings); + const CompilerSettings& settings() const; + const std::string& get_global_namespace() const; vk::string_view calc_relative_name(SrcFilePtr file, bool builtin) const; - std::string search_required_file(const std::string &file_name) const; - std::string search_file_in_include_dirs(const std::string &file_name, size_t *dir_index = nullptr) const; - SrcFilePtr register_file(const std::string &file_name, LibPtr owner_lib, bool builtin = false); + std::string search_required_file(const std::string& file_name) const; + std::string search_file_in_include_dirs(const std::string& file_name, size_t* dir_index = nullptr) const; + SrcFilePtr register_file(const std::string& file_name, LibPtr owner_lib, bool builtin = false); SrcDirPtr register_dir(vk::string_view full_dir_name); - FFIRoot &get_ffi_root(); + FFIRoot& get_ffi_root(); OutputMode get_output_mode() const; - void register_main_file(const std::string &file_name, DataStream &os); - SrcFilePtr require_file(const std::string &file_name, LibPtr owner_lib, DataStream &os, bool error_if_not_exists = true, bool builtin = false); + void register_main_file(const std::string& file_name, DataStream& os); + SrcFilePtr require_file(const std::string& file_name, LibPtr owner_lib, DataStream& os, bool error_if_not_exists = true, bool builtin = false); - void require_function(const std::string &name, DataStream &os); - void require_function(FunctionPtr function, DataStream &os); + void require_function(const std::string& name, DataStream& os); + void require_function(FunctionPtr function, DataStream& os); - template - void operate_on_function_locking(const std::string &name, CallbackT callback) { + template + void operate_on_function_locking(const std::string& name, CallbackT callback) { static_assert(std::is_constructible, CallbackT>::value, "invalid callback signature"); - auto *node = functions_ht.at(vk::std_hash(name)); - AutoLocker locker(node); + auto* node = functions_ht.at(vk::std_hash(name)); + AutoLocker locker(node); callback(node->data); } void register_function(FunctionPtr function); - void register_and_require_function(FunctionPtr function, DataStream &os, bool force_require = false); + void register_and_require_function(FunctionPtr function, DataStream& os, bool force_require = false); ClassPtr try_register_class(ClassPtr cur_class); bool register_class(ClassPtr cur_class); LibPtr register_lib(LibPtr lib); ModulitePtr register_modulite(ModulitePtr modulite); ComposerJsonPtr register_composer_json(ComposerJsonPtr composer_json); - FunctionPtr get_function(const std::string &name); + FunctionPtr get_function(const std::string& name); ModulitePtr get_modulite(vk::string_view name); ComposerJsonPtr get_composer_json(vk::string_view name); ComposerJsonPtr get_composer_json_at_dir(SrcDirPtr dir); @@ -127,12 +127,14 @@ class CompilerCore { bool register_define(DefinePtr def_id); DefinePtr get_define(std::string_view name); - VarPtr create_var(const std::string &name, VarData::Type type); - VarPtr get_global_var(const std::string &name, VertexPtr init_val); - VarPtr get_constant_var(const std::string &name, VertexPtr init_val, bool *is_new_inserted = nullptr); - VarPtr create_local_var(FunctionPtr function, const std::string &name, VarData::Type type); + VarPtr create_var(const std::string& name, VarData::Type type); + VarPtr get_global_var(const std::string& name, VertexPtr init_val); + VarPtr get_constant_var(const std::string& name, VertexPtr init_val, bool* is_new_inserted = nullptr); + VarPtr create_local_var(FunctionPtr function, const std::string& name, VarData::Type type); - SrcFilePtr get_main_file() { return main_file; } + SrcFilePtr get_main_file() { + return main_file; + } std::vector get_global_vars(); std::vector get_constants_vars(); std::vector get_classes(); @@ -141,37 +143,43 @@ class CompilerCore { std::vector get_libs(); std::vector get_dirs(); std::vector get_modulites(); - const ComposerAutoloader &get_composer_autoloader() const; + const ComposerAutoloader& get_composer_autoloader() const; void parse_tracked_builtins(const std::string& builtin_list) noexcept; - const auto & get_tracked_builtins() const noexcept { + const auto& get_tracked_builtins() const noexcept { return tracked_builtins; } void load_index(); void save_index(); - const Index &get_index(); - const Index &get_runtime_core_index(); - const Index &get_runtime_index(); - const Index &get_common_index(); - const Index &get_unicode_index(); - File *get_file_info(std::string &&file_name); + const Index& get_index(); + const Index& get_runtime_core_index(); + const Index& get_runtime_index(); + const Index& get_common_index(); + const Index& get_unicode_index(); + File* get_file_info(std::string&& file_name); void del_extra_files(); void init_dest_dir(); void init_runtime_and_common_srcs_dir(); void try_load_tl_classes(); void init_composer_class_loader(); - const TlClasses &get_tl_classes() const { return tl_classes; } + const TlClasses& get_tl_classes() const { + return tl_classes; + } - void add_kphp_runtime_opt(std::string opt) { kphp_runtime_opts.emplace_back(std::move(opt)); } - const std::vector &get_kphp_runtime_opts() const { return kphp_runtime_opts; } + void add_kphp_runtime_opt(std::string opt) { + kphp_runtime_opts.emplace_back(std::move(opt)); + } + const std::vector& get_kphp_runtime_opts() const { + return kphp_runtime_opts; + } - void set_function_palette(function_palette::Palette &&palette) { + void set_function_palette(function_palette::Palette&& palette) { function_palette = palette; } - function_palette::Palette &get_function_palette() { + function_palette::Palette& get_function_palette() { return function_palette; } @@ -227,11 +235,11 @@ class CompilerCore { return is_output_mode_k2_cli() || is_output_mode_k2_server() || is_output_mode_k2_oneshot() || is_output_mode_k2_multishot() || is_output_mode_k2_lib(); } - void set_exclude_namespaces(std::vector &&excludes) { + void set_exclude_namespaces(std::vector&& excludes) { exclude_namespaces = std::move(excludes); } - const std::vector &get_exclude_namespaces() const { + const std::vector& get_exclude_namespaces() const { return exclude_namespaces; } @@ -240,5 +248,4 @@ class CompilerCore { Stats stats; }; -extern CompilerCore *G; - +extern CompilerCore* G; diff --git a/compiler/compiler-settings.cpp b/compiler/compiler-settings.cpp index 2afde09710..282a11b5d9 100644 --- a/compiler/compiler-settings.cpp +++ b/compiler/compiler-settings.cpp @@ -24,8 +24,8 @@ #include "compiler/threading/tls.h" #include "compiler/utils/string-utils.h" -void KphpRawOption::init(const char *env, std::string default_value, std::vector choices) noexcept { - if (char *val = getenv(env)) { +void KphpRawOption::init(const char* env, std::string default_value, std::vector choices) noexcept { + if (char* val = getenv(env)) { raw_option_arg_ = val; } else { raw_option_arg_ = std::move(default_value); @@ -34,7 +34,7 @@ void KphpRawOption::init(const char *env, std::string default_value, std::vector choices_ = std::move(choices); } -void KphpRawOption::substitute_depends(const KphpRawOption &other) noexcept { +void KphpRawOption::substitute_depends(const KphpRawOption& other) noexcept { raw_option_arg_ = vk::replace_all(raw_option_arg_, "${" + other.get_env_var() + "}", other.raw_option_arg_); } @@ -44,32 +44,32 @@ void KphpRawOption::verify_arg_value() const { } } -void KphpRawOption::throw_param_exception(const std::string &reason) const { +void KphpRawOption::throw_param_exception(const std::string& reason) const { throw std::runtime_error{"Can't parse " + get_env_var() + " option: " + reason}; } template<> -void KphpOption::dump_option(std::ostream &out) const noexcept { +void KphpOption::dump_option(std::ostream& out) const noexcept { out << value_; } template<> -void KphpOption::dump_option(std::ostream &out) const noexcept { +void KphpOption::dump_option(std::ostream& out) const noexcept { out << value_; } template<> -void KphpOption::dump_option(std::ostream &out) const noexcept { +void KphpOption::dump_option(std::ostream& out) const noexcept { out << value_; } template<> -void KphpOption::dump_option(std::ostream &out) const noexcept { +void KphpOption::dump_option(std::ostream& out) const noexcept { out << (value_ ? "true" : "false"); } template<> -void KphpOption>::dump_option(std::ostream &out) const noexcept { +void KphpOption>::dump_option(std::ostream& out) const noexcept { out << vk::join(value_, ", "); } @@ -138,7 +138,7 @@ bool contains_lib(vk::string_view ld_flags, vk::string_view libname) noexcept { } template -void append_if_doesnt_contain(std::string &ld_flags, const T &libs, vk::string_view prefix, vk::string_view suffix = {}) noexcept { +void append_if_doesnt_contain(std::string& ld_flags, const T& libs, vk::string_view prefix, vk::string_view suffix = {}) noexcept { for (vk::string_view lib : libs) { if (!contains_lib(ld_flags, lib)) { ld_flags.append(" ").append(prefix.begin(), prefix.end()); @@ -147,7 +147,7 @@ void append_if_doesnt_contain(std::string &ld_flags, const T &libs, vk::string_v } } -void append_apple_options(std::string &cxx_flags, std::string &ld_flags) noexcept { +void append_apple_options(std::string& cxx_flags, std::string& ld_flags) noexcept { #if defined(__APPLE__) #ifdef __arm64__ std::string common_path = "/opt/homebrew"; @@ -157,10 +157,13 @@ void append_apple_options(std::string &cxx_flags, std::string &ld_flags) noexcep cxx_flags += " -I" + common_path + "/include"; ld_flags += " -liconv" " -lepoll-shim" - " -L" EPOLL_SHIM_LIB_DIR - " -L" + common_path + "/lib" + " -L" EPOLL_SHIM_LIB_DIR " -L" + + common_path + + "/lib" #ifdef PDO_DRIVER_PGSQL - " -L" + common_path + "/opt/libpq/lib" + " -L" + + common_path + + "/opt/libpq/lib" #endif " -undefined dynamic_lookup"; @@ -195,8 +198,8 @@ std::string calc_cxx_flags_sha256(vk::string_view cxx, vk::string_view cxx_flags } // namespace -void CxxFlags::init(const std::string &runtime_sha256, const std::string &cxx, - std::string cxx_flags_line, const std::string &dest_cpp_dir, bool enable_pch) noexcept { +void CxxFlags::init(const std::string& runtime_sha256, const std::string& cxx, std::string cxx_flags_line, const std::string& dest_cpp_dir, + bool enable_pch) noexcept { remove_extra_spaces(cxx_flags_line); flags.value_ = std::move(cxx_flags_line); flags_sha256.value_ = calc_cxx_flags_sha256(cxx, flags.get()); @@ -206,7 +209,7 @@ void CxxFlags::init(const std::string &runtime_sha256, const std::string &cxx, } } -void CompilerSettings::option_as_dir(KphpOption &path_option) noexcept { +void CompilerSettings::option_as_dir(KphpOption& path_option) noexcept { path_option.value_ = as_dir(path_option.value_); } @@ -222,9 +225,7 @@ void CompilerSettings::init() { option_as_dir(kphp_src_path); functions_file.value_ = get_full_path(functions_file.get()); runtime_sha256_file.value_ = get_full_path(runtime_sha256_file.get()); - build_timestamp.value_ = std::to_string( - std::chrono::duration_cast(build_tp.time_since_epoch()).count() - ); + build_timestamp.value_ = std::to_string(std::chrono::duration_cast(build_tp.time_since_epoch()).count()); bool is_k2_mode = mode.get().substr(0, 3) == "k2-"; if (link_file.value_.empty()) { @@ -286,7 +287,7 @@ void CompilerSettings::init() { throw std::runtime_error{"Option " + threads_count.get_env_var() + " is expected to be <= " + std::to_string(MAX_THREADS_COUNT)}; } - for (std::string &include : includes.value_) { + for (std::string& include : includes.value_) { include = as_dir(include); } @@ -302,11 +303,7 @@ void CompilerSettings::init() { remove_extra_spaces(extra_cxx_flags.value_); std::stringstream ss; - ss << "-Wall " - << extra_cxx_flags.get() - << " -iquote" << kphp_src_path.get() - << " -iquote " << kphp_src_path.get() - << "objs/generated/auto/runtime" + ss << "-Wall " << extra_cxx_flags.get() << " -iquote" << kphp_src_path.get() << " -iquote " << kphp_src_path.get() << "objs/generated/auto/runtime" << " -fwrapv -Wno-parentheses -Wno-trigraphs" << " -fno-strict-aliasing -fno-omit-frame-pointer"; #ifdef __x86_64__ @@ -323,15 +320,15 @@ void CompilerSettings::init() { if (vk::contains(cxx.get(), "clang")) { ss << " -Wno-invalid-source-encoding"; } - #if __cplusplus <= 201703L - ss << " -std=c++17"; - #elif __cplusplus <= 202002L - ss << " -std=c++20"; - #elif __cplusplus <= 202302L - ss << " -std=c++23"; - #else - #error unsupported __cplusplus value - #endif +#if __cplusplus <= 201703L + ss << " -std=c++17"; +#elif __cplusplus <= 202002L + ss << " -std=c++20"; +#elif __cplusplus <= 202302L + ss << " -std=c++23"; +#else +#error unsupported __cplusplus value +#endif ss << " -I" << kphp_src_path.get() + "objs/include "; if (is_k2_mode) { @@ -424,7 +421,7 @@ void CompilerSettings::init() { main_file.value_.assign(full_path); const size_t dir_pos = main_file.get().rfind('/'); - kphp_assert (dir_pos != std::string::npos); + kphp_assert(dir_pos != std::string::npos); base_dir.value_ = main_file.get().substr(0, dir_pos + 1); mkdir_recursive(dest_dir.get().c_str(), 0777); @@ -449,16 +446,14 @@ void CompilerSettings::init() { option_as_dir(composer_root); } -std::string CompilerSettings::read_runtime_sha256_file(const std::string &filename) { +std::string CompilerSettings::read_runtime_sha256_file(const std::string& filename) { std::ifstream runtime_sha256_file(filename.c_str()); - kphp_error(runtime_sha256_file, - fmt_format("Can't open runtime sha256 file '{}'", filename)); + kphp_error(runtime_sha256_file, fmt_format("Can't open runtime sha256 file '{}'", filename)); constexpr std::streamsize SHA256_LEN = 64; char runtime_sha256[SHA256_LEN] = {0}; runtime_sha256_file.read(runtime_sha256, SHA256_LEN); - kphp_error(runtime_sha256_file.gcount() == SHA256_LEN, - fmt_format("Can't read runtime sha256 from file '{}'", filename)); + kphp_error(runtime_sha256_file.gcount() == SHA256_LEN, fmt_format("Can't read runtime sha256 from file '{}'", filename)); return {runtime_sha256, runtime_sha256 + SHA256_LEN}; } diff --git a/compiler/compiler-settings.h b/compiler/compiler-settings.h index b4f42d0557..097210fcad 100644 --- a/compiler/compiler-settings.h +++ b/compiler/compiler-settings.h @@ -15,22 +15,22 @@ struct KphpRawOption : vk::not_copyable { public: - const std::string &get_env_var() const noexcept { + const std::string& get_env_var() const noexcept { return env_var_; } - void init(const char *env, std::string default_value, std::vector choices) noexcept; + void init(const char* env, std::string default_value, std::vector choices) noexcept; - void substitute_depends(const KphpRawOption &other) noexcept; + void substitute_depends(const KphpRawOption& other) noexcept; void verify_arg_value() const; - virtual void set_option_arg_value(const char *optarg_value) noexcept = 0; + virtual void set_option_arg_value(const char* optarg_value) noexcept = 0; virtual void parse_arg_value() = 0; - virtual void dump_option(std::ostream &out) const noexcept = 0; + virtual void dump_option(std::ostream& out) const noexcept = 0; virtual ~KphpRawOption() = default; protected: - void throw_param_exception(const std::string &reason) const; + void throw_param_exception(const std::string& reason) const; std::string env_var_; std::string raw_option_arg_; @@ -42,7 +42,7 @@ class KphpOption final : public KphpRawOption { public: friend class CompilerSettings; - const T &get() const noexcept { + const T& get() const noexcept { return value_; } @@ -52,14 +52,14 @@ class KphpOption final : public KphpRawOption { using KphpRawOption::substitute_depends; using KphpRawOption::verify_arg_value; - KphpOption &set_default(std::string &&default_opt) noexcept { + KphpOption& set_default(std::string&& default_opt) noexcept { if (raw_option_arg_.empty()) { raw_option_arg_ = std::move(default_opt); } return *this; } - void set_option_arg_value(const char *optarg_value) noexcept final { + void set_option_arg_value(const char* optarg_value) noexcept final { if (std::is_same{}) { raw_option_arg_ = "1"; } else if (std::is_same>{} && !raw_option_arg_.empty()) { @@ -69,7 +69,7 @@ class KphpOption final : public KphpRawOption { } } - void dump_option(std::ostream &out) const noexcept final; + void dump_option(std::ostream& out) const noexcept final; void parse_arg_value() final; T value_{}; @@ -80,7 +80,7 @@ class KphpImplicitOption : vk::not_copyable { friend class CompilerSettings; friend class CxxFlags; - const std::string &get() const noexcept { + const std::string& get() const noexcept { return value_; } @@ -90,24 +90,20 @@ class KphpImplicitOption : vk::not_copyable { class CxxFlags { public: - void init(const std::string &runtime_sha256, const std::string &cxx, std::string cxx_flags_line, const std::string &dest_cpp_dir, bool enable_pch) noexcept; + void init(const std::string& runtime_sha256, const std::string& cxx, std::string cxx_flags_line, const std::string& dest_cpp_dir, bool enable_pch) noexcept; KphpImplicitOption flags; KphpImplicitOption flags_sha256; KphpImplicitOption pch_dir; - friend inline bool operator==(const CxxFlags &lhs, const CxxFlags &rhs) noexcept { + friend inline bool operator==(const CxxFlags& lhs, const CxxFlags& rhs) noexcept { return std::tie(lhs.flags.get(), lhs.flags_sha256.get(), lhs.pch_dir.get()) == std::tie(rhs.flags.get(), rhs.flags_sha256.get(), rhs.pch_dir.get()); } }; class CompilerSettings : vk::not_copyable { public: - enum color_settings { - auto_colored, - not_colored, - colored - }; + enum color_settings { auto_colored, not_colored, colored }; KphpOption main_file; @@ -206,10 +202,10 @@ class CompilerSettings : vk::not_copyable { void init(); - static std::string read_runtime_sha256_file(const std::string &filename); + static std::string read_runtime_sha256_file(const std::string& filename); private: - static void option_as_dir(KphpOption &path) noexcept; + static void option_as_dir(KphpOption& path) noexcept; color_settings color_{auto_colored}; }; diff --git a/compiler/compiler.cpp b/compiler/compiler.cpp index 290e009908..e2d47ab5a8 100644 --- a/compiler/compiler.cpp +++ b/compiler/compiler.cpp @@ -16,8 +16,8 @@ #include #include "common/algorithms/hashes.h" -#include "common/dl-utils-lite.h" #include "common/crc32.h" +#include "common/dl-utils-lite.h" #include "common/type_traits/function_traits.h" #include "common/version-string.h" @@ -27,6 +27,7 @@ #include "compiler/make/make.h" #include "compiler/pipes/analyze-performance.h" #include "compiler/pipes/analyzer.h" +#include "compiler/pipes/array-access-transform.h" #include "compiler/pipes/calc-actual-edges.h" #include "compiler/pipes/calc-bad-vars.h" #include "compiler/pipes/calc-const-types.h" @@ -44,7 +45,6 @@ #include "compiler/pipes/check-func-calls-and-vararg.h" #include "compiler/pipes/check-modifications-of-const-vars.h" #include "compiler/pipes/check-nested-foreach.h" -#include "compiler/pipes/wait-for-all-classes.h" #include "compiler/pipes/check-restrictions.h" #include "compiler/pipes/check-tl-classes.h" #include "compiler/pipes/check-type-hint-variance.h" @@ -58,24 +58,23 @@ #include "compiler/pipes/convert-invoke-to-func-call.h" #include "compiler/pipes/convert-list-assignments.h" #include "compiler/pipes/convert-sprintf-calls.h" +#include "compiler/pipes/deduce-implicit-types-and-casts.h" +#include "compiler/pipes/early-optimization.h" #include "compiler/pipes/erase-defines-declarations.h" #include "compiler/pipes/extract-async.h" #include "compiler/pipes/extract-resumable-calls.h" #include "compiler/pipes/file-to-tokens.h" #include "compiler/pipes/filter-only-actually-used.h" #include "compiler/pipes/final-check.h" -#include "compiler/pipes/array-access-transform.h" #include "compiler/pipes/fix-returns.h" #include "compiler/pipes/gen-tree-postprocess.h" #include "compiler/pipes/generate-virtual-methods.h" -#include "compiler/pipes/deduce-implicit-types-and-casts.h" -#include "compiler/pipes/instantiate-generics-and-lambdas.h" -#include "compiler/pipes/instantiate-ffi-operations.h" #include "compiler/pipes/inline-defines-usages.h" #include "compiler/pipes/inline-simple-functions.h" +#include "compiler/pipes/instantiate-ffi-operations.h" +#include "compiler/pipes/instantiate-generics-and-lambdas.h" #include "compiler/pipes/load-files.h" #include "compiler/pipes/optimization.h" -#include "compiler/pipes/early-optimization.h" #include "compiler/pipes/parse-and-apply-phpdoc.h" #include "compiler/pipes/parse.h" #include "compiler/pipes/preprocess-break.h" @@ -91,6 +90,7 @@ #include "compiler/pipes/sort-and-inherit-classes.h" #include "compiler/pipes/split-switch.h" #include "compiler/pipes/type-inferer.h" +#include "compiler/pipes/wait-for-all-classes.h" #include "compiler/pipes/write-files.h" #include "compiler/scheduler/constructor.h" #include "compiler/scheduler/one-thread-scheduler.h" @@ -156,11 +156,7 @@ template using ExecuteFunctionOutput = typename std::remove_reference::template Argument<1>>::type; template -using PipeStream = PipeWithProgress< - PipeFunctionT, - DataStream>, - ExecuteFunctionOutput ->; +using PipeStream = PipeWithProgress>, ExecuteFunctionOutput>; using SyncNode = sync_node_tag; @@ -168,8 +164,7 @@ template using FunctionPassPipe = PipeStream>; template -struct PipeProgressName> : PipeProgressName { -}; +struct PipeProgressName> : PipeProgressName {}; template using PipeC = pipe_creator_tag, parallel>; @@ -180,25 +175,24 @@ using PassC = pipe_creator_tag>; template using SyncC = sync_pipe_creator_tag>; - -bool compiler_execute(CompilerSettings *settings) { +bool compiler_execute(CompilerSettings* settings) { double st = dl_time(); G = new CompilerCore(); G->register_settings(settings); G->start(); if (!settings->warnings_file.get().empty()) { - FILE *f = fopen(settings->warnings_file.get().c_str(), "w"); + FILE* f = fopen(settings->warnings_file.get().c_str(), "w"); if (!f) { std::cerr << "Can't open warnings-file " << settings->warnings_file.get() << "\n"; return false; } stage::set_warning_file(f); } - if (const auto &tracked_builtins_list = settings->tracked_builtins_list.get(); !tracked_builtins_list.empty()) { + if (const auto& tracked_builtins_list = settings->tracked_builtins_list.get(); !tracked_builtins_list.empty()) { G->parse_tracked_builtins(tracked_builtins_list); } - //TODO: call it with pthread_once on need + // TODO: call it with pthread_once on need lexer_init(); if (G->is_output_mode_k2()) { k2_lexer_init(); @@ -217,13 +211,13 @@ bool compiler_execute(CompilerSettings *settings) { return false; } - SchedulerBase *scheduler; + SchedulerBase* scheduler; const auto scheduler_threads = static_cast(G->settings().threads_count.get()); if (scheduler_threads == 1) { scheduler = new OneThreadScheduler(); vk::singleton::get().initialize_sync(); } else { - auto *s = new Scheduler(); + auto* s = new Scheduler(); s->set_threads_count(scheduler_threads); scheduler = s; vk::singleton::get().initialize_async(scheduler_threads + 1); @@ -236,99 +230,39 @@ bool compiler_execute(CompilerSettings *settings) { PipeC::get()->set_input_stream(&src_file_stream); - SchedulerConstructor{scheduler} - >> PipeC{} - >> PipeC{} - >> PipeC{} - >> PassC{} - >> PipeC{} - >> PipeC{} - >> PassC{} - >> PipeC{} >> use_nth_output_tag<0>{} - >> SyncC{} - >> PipeC{} - >> PassC{} - >> PassC{} - >> SyncC{} - >> SyncC{} - >> PassC{} - >> PassC{} - >> PassC{} - >> PassC{} - >> SyncC{} - // from this point, @param/@return are parsed in all functions, we can calculate and use assumptions - // lambdas don't traverse this part of pipeline — they are processed by containing functions as vertices - // generics are also stopped by the SyncPipe above, they are instantiated on demand and passed here, see <1> output - // do NOT insert any pipe before, see DeduceImplicitTypesAndCastsPass::check_function() - >> PassC{} - >> PipeC{} >> use_nth_output_tag<0>{} - >> PipeC{} - >> SyncC{} - >> PipeC{} - >> PassC{} - >> PassC{} - >> PipeC{} - >> PipeC{} - >> PassC{} - >> SyncC{} - >> PassC{} - >> PassC{} - >> PassC{} - >> PassC{} - >> PassC{} - >> PassC{} - >> PassC{} - >> PassC{} - >> PassC{} - >> PipeC{} - >> PipeC{} - >> SyncC{} - >> PassC{} - >> PassC{} - >> SyncC{} - >> SyncC{} - >> PipeC{} - >> PassC{} - >> PassC{} - >> PassC{} - >> PassC{} - >> PassC{} - >> PassC{} - >> PassC{} - >> SyncC{} - >> PipeC{} - >> PassC{} - >> PassC{} - >> PassC{} - >> PassC{} - >> PassC{} - >> PassC{} - >> PassC{} - >> PassC{} - >> PassC{} - >> PassC{} - >> SyncC{} // create all codegen commands and launch them in "just calc hashes" mode - >> PipeC{} // re-launch codegen commands that diff from the previous kphp launch - >> PipeC{}; // store files that differ from the previous kphp launch - - SchedulerConstructor{scheduler} - >> PipeC{} >> use_nth_output_tag<1>{} - >> PipeC{}; - - SchedulerConstructor{scheduler} - >> PipeC{} >> use_nth_output_tag<2>{} - >> PassC{}; - - SchedulerConstructor{scheduler} - >> PipeC{} >> use_nth_output_tag<3>{} - // output 1 is used to restart class processing - >> PipeC{} >> use_nth_output_tag<1>{} - >> PipeC{} >> use_nth_output_tag<0>{} - >> PassC{}; - - SchedulerConstructor{scheduler} - >> PipeC{} >> use_nth_output_tag<1>{} - >> PassC{}; + SchedulerConstructor{scheduler} >> PipeC{} >> PipeC{} >> PipeC{} >> PassC{} >> + PipeC{} >> PipeC{} >> PassC{} >> PipeC{} >> use_nth_output_tag<0>{} >> + SyncC{} >> PipeC{} >> PassC{} >> PassC{} >> + SyncC{} >> SyncC{} >> PassC{} >> + PassC{} >> PassC{} >> PassC{} >> SyncC{} + // from this point, @param/@return are parsed in all functions, we can calculate and use assumptions + // lambdas don't traverse this part of pipeline — they are processed by containing functions as vertices + // generics are also stopped by the SyncPipe above, they are instantiated on demand and passed here, see <1> output + // do NOT insert any pipe before, see DeduceImplicitTypesAndCastsPass::check_function() + >> PassC{} >> PipeC{} >> use_nth_output_tag<0>{} >> PipeC{} >> + SyncC{} >> PipeC{} >> PassC{} >> PassC{} >> + PipeC{} >> PipeC{} >> PassC{} >> SyncC{} >> + PassC{} >> PassC{} >> PassC{} >> PassC{} >> + PassC{} >> PassC{} >> PassC{} >> PassC{} >> + PassC{} >> PipeC{} >> PipeC{} >> SyncC{} >> PassC{} >> + PassC{} >> SyncC{} >> SyncC{} >> PipeC{} >> PassC{} >> + PassC{} >> PassC{} >> PassC{} >> PassC{} >> PassC{} >> + PassC{} >> SyncC{} >> PipeC{} >> PassC{} >> PassC{} >> + PassC{} >> PassC{} >> PassC{} >> PassC{} >> + PassC{} >> PassC{} >> PassC{} >> PassC{} >> SyncC{} + // create all codegen commands and launch them in "just calc hashes" mode + >> PipeC{} // re-launch codegen commands that diff from the previous kphp launch + >> PipeC{}; // store files that differ from the previous kphp launch + + SchedulerConstructor{scheduler} >> PipeC{} >> use_nth_output_tag<1>{} >> PipeC{}; + + SchedulerConstructor{scheduler} >> PipeC{} >> use_nth_output_tag<2>{} >> PassC{}; + + SchedulerConstructor{scheduler} >> PipeC{} >> use_nth_output_tag<3>{} // output 1 is used to restart class processing + >> PipeC{} >> use_nth_output_tag<1>{} >> PipeC{} >> use_nth_output_tag<0>{} >> + PassC{}; + + SchedulerConstructor{scheduler} >> PipeC{} >> use_nth_output_tag<1>{} >> PassC{}; if (G->settings().show_progress.get()) { PipesProgress::get().enable(); @@ -345,7 +279,7 @@ bool compiler_execute(CompilerSettings *settings) { } if (vk::singleton::get().is_flush_required()) { - if (auto *report_file = fopen(G->settings().performance_analyze_report_path.get().c_str(), "w")) { + if (auto* report_file = fopen(G->settings().performance_analyze_report_path.get().c_str(), "w")) { vk::singleton::get().flush_to(report_file); fclose(report_file); } else { @@ -360,7 +294,7 @@ bool compiler_execute(CompilerSettings *settings) { if (verbosity > 1) { bool got_changes = false; - for (const auto &file: G->get_index().get_files()) { + for (const auto& file : G->get_index().get_files()) { if (file->is_changed) { std::cerr << "\nFile [" << file->path << "] changed"; got_changes = true; diff --git a/compiler/compiler.h b/compiler/compiler.h index 6ca0b3aeac..cd18aab78e 100644 --- a/compiler/compiler.h +++ b/compiler/compiler.h @@ -8,4 +8,4 @@ class Compiler; -bool compiler_execute(CompilerSettings *settings); +bool compiler_execute(CompilerSettings* settings); diff --git a/compiler/composer.cpp b/compiler/composer.cpp index dda13c9f18..25772b8e3b 100644 --- a/compiler/composer.cpp +++ b/compiler/composer.cpp @@ -11,12 +11,11 @@ #include "compiler/data/composer-json-data.h" #include "compiler/kphp_assert.h" - -static bool file_exists(const std::string &filename) { +static bool file_exists(const std::string& filename) { return access(filename.c_str(), F_OK) == 0; -}; +} -std::string ComposerAutoloader::psr_lookup_nocache(const PsrMap &psr, const std::string &class_name, bool transform_underscore) { +std::string ComposerAutoloader::psr_lookup_nocache(const PsrMap& psr, const std::string& class_name, bool transform_underscore) { std::string prefix = class_name; // we start from a longest prefix and then try to match it @@ -38,12 +37,12 @@ std::string ComposerAutoloader::psr_lookup_nocache(const PsrMap &psr, const std: // candidate (e.g. "VK\Feed"->"tests/" and "VK\Feed"->"src/"; // we choose a first successful guess based on a file existence: if \VK\Feed\C // exists in VK\Feed\src\C.php, we return that, otherwise we try VK\Feed\tests\C.php - for (const auto &dir : candidates->second) { + for (const auto& dir : candidates->second) { auto short_class_name = class_name.substr(key.size()); if (transform_underscore) { std::replace(short_class_name.begin(), short_class_name.end(), '_', '/'); } - const auto &psr4_filename = dir + short_class_name + ".php"; + const auto& psr4_filename = dir + short_class_name + ".php"; if (file_exists(psr4_filename)) { return psr4_filename; } @@ -53,13 +52,13 @@ std::string ComposerAutoloader::psr_lookup_nocache(const PsrMap &psr, const std: // "" key contains fallback directories auto fallback_dirs = psr.find(""); if (fallback_dirs != psr.end()) { - for (const auto &dir : fallback_dirs->second) { + for (const auto& dir : fallback_dirs->second) { auto class_name_copy = class_name; auto last_slash = class_name_copy.find_last_of('/'); if (transform_underscore && last_slash != std::string::npos) { std::replace(std::next(class_name_copy.begin(), last_slash), class_name_copy.end(), '_', '/'); } - const auto &psr4_filename = dir + class_name_copy + ".php"; + const auto& psr4_filename = dir + class_name_copy + ".php"; if (file_exists(psr4_filename)) { return psr4_filename; } @@ -69,7 +68,7 @@ std::string ComposerAutoloader::psr_lookup_nocache(const PsrMap &psr, const std: return ""; } -std::string ComposerAutoloader::psr4_lookup(const std::string &class_name) const { +std::string ComposerAutoloader::psr4_lookup(const std::string& class_name) const { // we could add a special path for packages with a single candidate, but // they seem to be almost non-existent; a single candidate package can // be handled without caching/touching FS/locking @@ -91,7 +90,7 @@ std::string ComposerAutoloader::psr4_lookup(const std::string &class_name) const return psr4_filename; } -std::string ComposerAutoloader::psr0_lookup(const std::string &class_name) const { +std::string ComposerAutoloader::psr0_lookup(const std::string& class_name) const { auto file = psr_lookup_nocache(autoload_psr0_, class_name, true); if (file.empty()) { auto it = autoload_psr0_classmap_.find(class_name); @@ -106,7 +105,7 @@ void ComposerAutoloader::set_use_dev(bool v) { use_dev_ = v; } -void ComposerAutoloader::load_root_file(const std::string &pkg_root) { +void ComposerAutoloader::load_root_file(const std::string& pkg_root) { kphp_assert(!pkg_root.empty() && pkg_root.back() == '/'); kphp_assert(autoload_filename_.empty()); kphp_error_return(file_exists(pkg_root + "composer.json"), fmt_format("composer.json does not exist in --composer-root {}", pkg_root)); @@ -115,11 +114,11 @@ void ComposerAutoloader::load_root_file(const std::string &pkg_root) { load_file(pkg_root, true); } -void ComposerAutoloader::load_file(const std::string &pkg_root) { +void ComposerAutoloader::load_file(const std::string& pkg_root) { load_file(pkg_root, false); } -void ComposerAutoloader::load_file(const std::string &pkg_root, bool is_root_file) { +void ComposerAutoloader::load_file(const std::string& pkg_root, bool is_root_file) { // composer.json structure (that we care about): // { // // name -- used to identify this composer package @@ -176,38 +175,38 @@ void ComposerAutoloader::load_file(const std::string &pkg_root, bool is_root_fil if (!composer_json->package_name.empty()) { G->register_composer_json(composer_json); } -// printf("composer package %s in %s\n", composer_json->package_name.c_str(), pkg_root.c_str()); + // printf("composer package %s in %s\n", composer_json->package_name.c_str(), pkg_root.c_str()); // we handle "require/autoload/files" only in direct root deps, see https://github.com/VKCOM/kphp/pull/465 bool require_autoload_files = is_root_file || vk::contains(deps_, composer_json->package_name); bool use_dev = is_root_file && use_dev_; - for (const auto &autoload_file : composer_json->autoload_files) { + for (const auto& autoload_file : composer_json->autoload_files) { if (require_autoload_files && (!autoload_file.is_dev || use_dev)) { files_to_require_.emplace_back(autoload_file.file_name); } } - for (const auto &autoload_psr0 : composer_json->autoload_psr0) { + for (const auto& autoload_psr0 : composer_json->autoload_psr0) { if (!autoload_psr0.is_dev || use_dev) { if (autoload_psr0.prefix_is_classname) { kphp_assert(autoload_psr0.dirs.size() == 1); autoload_psr0_classmap_[autoload_psr0.prefix] = autoload_psr0.dirs.front(); } else { - auto &at_prefix = autoload_psr0_[autoload_psr0.prefix]; + auto& at_prefix = autoload_psr0_[autoload_psr0.prefix]; at_prefix.insert(at_prefix.end(), autoload_psr0.dirs.begin(), autoload_psr0.dirs.end()); } } } - for (const auto &autoload_psr4 : composer_json->autoload_psr4) { + for (const auto& autoload_psr4 : composer_json->autoload_psr4) { if (!autoload_psr4.is_dev || use_dev) { - auto &at_prefix = autoload_psr4_[autoload_psr4.prefix]; + auto& at_prefix = autoload_psr4_[autoload_psr4.prefix]; at_prefix.insert(at_prefix.end(), autoload_psr4.dirs.begin(), autoload_psr4.dirs.end()); } } - for (const auto &require : composer_json->require) { + for (const auto& require : composer_json->require) { if (is_root_file && (!require.is_dev || use_dev)) { deps_.insert(require.package_name); } diff --git a/compiler/composer.h b/compiler/composer.h index 76dddf17e4..8c15366885 100644 --- a/compiler/composer.h +++ b/compiler/composer.h @@ -29,35 +29,35 @@ class ComposerAutoloader : private vk::not_copyable { // load_file parses the "$pkg_root/composer.json" file and saves // all relevant definitions inside loader; // this method is not thread-safe and should be called only during the compiler init - void load_file(const std::string &pkg_root); + void load_file(const std::string& pkg_root); // load_root_file is like load_file, but should be only used // for the main composer file; // this method is not thread-safe and should be called only during the compiler init - void load_root_file(const std::string &pkg_root); + void load_root_file(const std::string& pkg_root); // psr4_lookup/psr0_lookup tries to find a filename that should contain // a class class_name; the lookup is based on the loaded // composer files and their autoload definitions - std::string psr4_lookup(const std::string &class_name) const; - std::string psr0_lookup(const std::string &class_name) const; + std::string psr4_lookup(const std::string& class_name) const; + std::string psr0_lookup(const std::string& class_name) const; // is_autoload_file reports whether the specified absolute filename // is a composer-generated autoload.php file - bool is_autoload_file(const std::string &filename) const noexcept { + bool is_autoload_file(const std::string& filename) const noexcept { return filename == autoload_filename_; } - const std::vector &get_files_to_require() const noexcept { + const std::vector& get_files_to_require() const noexcept { return files_to_require_; } using PsrMap = std::map, std::less<>>; private: - void load_file(const std::string &filename, bool root); + void load_file(const std::string& filename, bool root); - static std::string psr_lookup_nocache(const PsrMap &psr, const std::string &class_name, bool transform_underscore = false); + static std::string psr_lookup_nocache(const PsrMap& psr, const std::string& class_name, bool transform_underscore = false); bool use_dev_; PsrMap autoload_psr4_; diff --git a/compiler/const-manipulations.h b/compiler/const-manipulations.h index df57c22479..527dd5787e 100644 --- a/compiler/const-manipulations.h +++ b/compiler/const-manipulations.h @@ -8,16 +8,16 @@ #include #include "common/php-functions.h" +#include "compiler/compiler-core.h" #include "compiler/data/data_ptr.h" #include "compiler/data/define-data.h" #include "compiler/data/var-data.h" -#include "compiler/compiler-core.h" #include "compiler/name-gen.h" #include "compiler/operation.h" #include "compiler/pipes/check-access-modifiers.h" #include "compiler/utils/string-utils.h" -#include "compiler/vertex.h" #include "compiler/vertex-util.h" +#include "compiler/vertex.h" template struct ConstManipulations { @@ -25,33 +25,61 @@ struct ConstManipulations { virtual ~ConstManipulations() = default; protected: - virtual T on_trivial(VertexPtr v) { return on_non_const(v); } + virtual T on_trivial(VertexPtr v) { + return on_non_const(v); + } - virtual T on_conv(VertexAdaptor v) { return on_non_const(v); } + virtual T on_conv(VertexAdaptor v) { + return on_non_const(v); + } - virtual T on_unary(VertexAdaptor v) { return on_non_const(v); } + virtual T on_unary(VertexAdaptor v) { + return on_non_const(v); + } - virtual T on_binary(VertexAdaptor v) { return on_non_const(v); } + virtual T on_binary(VertexAdaptor v) { + return on_non_const(v); + } - virtual T on_double_arrow(VertexAdaptor v) { return on_non_const(v); } + virtual T on_double_arrow(VertexAdaptor v) { + return on_non_const(v); + } - virtual bool on_array_value([[maybe_unused]] VertexAdaptor array, [[maybe_unused]] size_t ind) { return false; } + virtual bool on_array_value([[maybe_unused]] VertexAdaptor array, [[maybe_unused]] size_t ind) { + return false; + } - virtual T on_array_finish(VertexAdaptor v) { return on_non_const(v); } + virtual T on_array_finish(VertexAdaptor v) { + return on_non_const(v); + } - virtual T on_func_name(VertexAdaptor v) { return on_non_const(v); } + virtual T on_func_name(VertexAdaptor v) { + return on_non_const(v); + } - virtual T on_var(VertexAdaptor v) { return on_non_const(v); } + virtual T on_var(VertexAdaptor v) { + return on_non_const(v); + } - virtual T on_instance_prop(VertexAdaptor v) { return on_non_const(v); } + virtual T on_instance_prop(VertexAdaptor v) { + return on_non_const(v); + } - virtual T on_define_val(VertexAdaptor v) { return on_non_const(v); } + virtual T on_define_val(VertexAdaptor v) { + return on_non_const(v); + } - virtual T on_func_call(VertexAdaptor v) { return on_non_const(v); } + virtual T on_func_call(VertexAdaptor v) { + return on_non_const(v); + } - virtual T on_alloc(VertexAdaptor v) { return on_non_const(v); } + virtual T on_alloc(VertexAdaptor v) { + return on_non_const(v); + } - virtual T on_non_const([[maybe_unused]] VertexPtr vertex) { return T(); } + virtual T on_non_const([[maybe_unused]] VertexPtr vertex) { + return T(); + } virtual T on_array(VertexAdaptor v) { VertexRange arr = v->args(); @@ -63,7 +91,9 @@ struct ConstManipulations { return on_array_finish(v); } - virtual bool on_index_key([[maybe_unused]] VertexPtr key) { return false; } + virtual bool on_index_key([[maybe_unused]] VertexPtr key) { + return false; + } virtual T on_index(VertexAdaptor index) { if (index->has_key() && !on_index_key(index->key())) { @@ -74,83 +104,82 @@ struct ConstManipulations { T visit(VertexPtr v) { switch (v->type()) { - case op_conv_int: - case op_conv_int_l: - case op_conv_float: - case op_conv_string: - case op_conv_string_l: - case op_conv_array: - case op_conv_array_l: - case op_conv_object: - case op_conv_bool: - case op_conv_mixed: - case op_force_mixed: - case op_conv_regexp: - return on_conv(v.as()); - - case op_int_const: - case op_float_const: - case op_string: - case op_false: - case op_true: - case op_null: - return on_trivial(v); - - case op_minus: - case op_plus: - case op_not: - return on_unary(v.as()); - - case op_add: - case op_mul: - case op_sub: - case op_div: - case op_mod: - case op_pow: - case op_and: - case op_or: - case op_xor: - case op_shl: - case op_shr: - return on_binary(v.as()); - - case op_array: - return on_array(v.as()); - - case op_index: - return on_index(v.as()); - - case op_var: - return on_var(v.as()); - - case op_instance_prop: - return on_instance_prop(v.as()); - - case op_func_name: - return on_func_name(v.as()); - - case op_double_arrow: - return on_double_arrow(v.as()); - - case op_define_val: - return on_define_val(v.as()); - - case op_func_call: - return on_func_call(v.as()); - - case op_alloc: - return on_alloc(v.as()); - - default: - return on_non_const(v); + case op_conv_int: + case op_conv_int_l: + case op_conv_float: + case op_conv_string: + case op_conv_string_l: + case op_conv_array: + case op_conv_array_l: + case op_conv_object: + case op_conv_bool: + case op_conv_mixed: + case op_force_mixed: + case op_conv_regexp: + return on_conv(v.as()); + + case op_int_const: + case op_float_const: + case op_string: + case op_false: + case op_true: + case op_null: + return on_trivial(v); + + case op_minus: + case op_plus: + case op_not: + return on_unary(v.as()); + + case op_add: + case op_mul: + case op_sub: + case op_div: + case op_mod: + case op_pow: + case op_and: + case op_or: + case op_xor: + case op_shl: + case op_shr: + return on_binary(v.as()); + + case op_array: + return on_array(v.as()); + + case op_index: + return on_index(v.as()); + + case op_var: + return on_var(v.as()); + + case op_instance_prop: + return on_instance_prop(v.as()); + + case op_func_name: + return on_func_name(v.as()); + + case op_double_arrow: + return on_double_arrow(v.as()); + + case op_define_val: + return on_define_val(v.as()); + + case op_func_call: + return on_func_call(v.as()); + + case op_alloc: + return on_alloc(v.as()); + + default: + return on_non_const(v); } } }; // CheckConst is used as Base class below // And in name-gen.cpp, to check -- whether we should hash and utilize as const variable or not -struct CheckConst - : ConstManipulations { +struct CheckConst : ConstManipulations { public: static bool is_const(VertexPtr v) { static CheckConst check_const; @@ -207,11 +236,9 @@ struct CheckConst } }; - // CheckConstWithDefines is used in CalcRealDefinesValues pass // To choose correct `def->val->const_type` (cnst_const_val or def_var) -struct CheckConstWithDefines final - : CheckConst { +struct CheckConstWithDefines final : CheckConst { public: bool is_const(VertexPtr v) { return visit(v); @@ -257,10 +284,10 @@ struct CheckConstWithDefines final int in_concat = 0; }; -struct CheckConstAccess final - : CheckConst { +struct CheckConstAccess final : CheckConst { private: ClassPtr caller_class_id; + public: void check(VertexPtr v, ClassPtr class_id) { caller_class_id = class_id; @@ -299,8 +326,7 @@ static inline std::string collect_string_concatenation(VertexPtr v, bool allow_d // MakeConst is used in CalcRealDefinesValues pass // To choose correct `def->val->const_type` (cnst_const_val or def_var) -struct MakeConst final - : ConstManipulations { +struct MakeConst final : ConstManipulations { public: VertexPtr make_const(VertexPtr v) { return visit(v); @@ -383,16 +409,14 @@ struct MakeConst final VertexPtr on_func_call(VertexAdaptor v) final { return v; } - }; -struct CommonHash - : ConstManipulations { +struct CommonHash : ConstManipulations { void feed_hash(uint64_t val) { cur_hash = cur_hash * HASH_MULT + val; } - void feed_hash_string(const std::string &s) { + void feed_hash_string(const std::string& s) { feed_hash(string_hash(s.c_str(), s.size())); } @@ -501,8 +525,7 @@ struct ObjectHash final : CommonHash { } }; -struct VertexPtrFormatter final - : ConstManipulations { +struct VertexPtrFormatter final : ConstManipulations { static std::string to_string(VertexPtr v) { static VertexPtrFormatter serializer; return serializer.visit(VertexUtil::get_actual_value(v)); @@ -574,8 +597,7 @@ struct VertexPtrFormatter final } }; -struct CanGenerateRawArray final - : ConstManipulations { +struct CanGenerateRawArray final : ConstManipulations { public: static bool is_raw(VertexAdaptor v) { static CanGenerateRawArray can_generate_raw; @@ -611,4 +633,3 @@ struct CanGenerateRawArray final return true; } }; - diff --git a/compiler/cpp-dest-dir-initializer.cpp b/compiler/cpp-dest-dir-initializer.cpp index 6e54b7a49b..029f451327 100644 --- a/compiler/cpp-dest-dir-initializer.cpp +++ b/compiler/cpp-dest-dir-initializer.cpp @@ -7,7 +7,7 @@ #include "compiler/compiler-core.h" void CppDestDirInitializer::initialize_sync() noexcept { - const char *description = "Init cpp dest dir"; + const char* description = "Init cpp dest dir"; stage::set_name(description); stage::set_file(SrcFilePtr{}); static CachedProfiler cache{description}; diff --git a/compiler/cpp-dest-dir-initializer.h b/compiler/cpp-dest-dir-initializer.h index d12e73e8da..866885706c 100644 --- a/compiler/cpp-dest-dir-initializer.h +++ b/compiler/cpp-dest-dir-initializer.h @@ -4,8 +4,8 @@ #pragma once -#include #include +#include #include "common/mixin/not_copyable.h" #include "common/smart_ptrs/singleton.h" diff --git a/compiler/data/class-data.cpp b/compiler/data/class-data.cpp index 23122ba606..780e433f1e 100644 --- a/compiler/data/class-data.cpp +++ b/compiler/data/class-data.cpp @@ -4,35 +4,34 @@ #include "compiler/data/class-data.h" -#include #include +#include #include "common/termformat/termformat.h" #include "common/wrappers/string_view.h" #include "compiler/compiler-core.h" +#include "compiler/data/define-data.h" #include "compiler/data/function-data.h" #include "compiler/data/src-file.h" -#include "compiler/vertex-util.h" #include "compiler/inferring/type-data.h" #include "compiler/name-gen.h" #include "compiler/type-hint.h" #include "compiler/utils/string-utils.h" -#include "compiler/data/define-data.h" +#include "compiler/vertex-util.h" -const char *ClassData::NAME_OF_VIRT_CLONE = "__virt_clone$"; -const char *ClassData::NAME_OF_CLONE = "__clone"; -const char *ClassData::NAME_OF_CONSTRUCT = "__construct"; -const char *ClassData::NAME_OF_TO_STRING = "__toString"; -const char *ClassData::NAME_OF_WAKEUP = "__wakeup"; +const char* ClassData::NAME_OF_VIRT_CLONE = "__virt_clone$"; +const char* ClassData::NAME_OF_CLONE = "__clone"; +const char* ClassData::NAME_OF_CONSTRUCT = "__construct"; +const char* ClassData::NAME_OF_TO_STRING = "__toString"; +const char* ClassData::NAME_OF_WAKEUP = "__wakeup"; -ClassData::ClassData(ClassType type) : - class_type(type), - members(this), - type_data(TypeData::create_for_class(ClassPtr(this))) { -} +ClassData::ClassData(ClassType type) + : class_type(type), + members(this), + type_data(TypeData::create_for_class(ClassPtr(this))) {} -void ClassData::set_name_and_src_name(const std::string &full_name) { +void ClassData::set_name_and_src_name(const std::string& full_name) { this->name = full_name; this->src_name = std::string("C$").append(replace_backslashes(full_name)); this->cpp_filename = replace_characters(src_name + ".cpp", '$', '@'); @@ -50,31 +49,19 @@ void ClassData::set_name_and_src_name(const std::string &full_name) { } void ClassData::debugPrint() { - const char *str_class_type = - is_interface() ? "interface" : - is_trait() ? "trait" : "class"; + const char* str_class_type = is_interface() ? "interface" : is_trait() ? "trait" : "class"; fmt_print("=== {} {}\n", str_class_type, name); - members.for_each([](ClassMemberConstant &m) { - fmt_print("const {}\n", m.local_name()); - }); - members.for_each([](ClassMemberStaticField &m) { - fmt_print("static ${}\n", m.local_name()); - }); - members.for_each([](ClassMemberStaticMethod &m) { - fmt_print("static {}()\n", m.local_name()); - }); - members.for_each([](ClassMemberInstanceField &m) { - fmt_print("var ${}\n", m.local_name()); - }); - members.for_each([](ClassMemberInstanceMethod &m) { - fmt_print("method {}()\n", m.local_name()); - }); + members.for_each([](ClassMemberConstant& m) { fmt_print("const {}\n", m.local_name()); }); + members.for_each([](ClassMemberStaticField& m) { fmt_print("static ${}\n", m.local_name()); }); + members.for_each([](ClassMemberStaticMethod& m) { fmt_print("static {}()\n", m.local_name()); }); + members.for_each([](ClassMemberInstanceField& m) { fmt_print("var ${}\n", m.local_name()); }); + members.for_each([](ClassMemberInstanceMethod& m) { fmt_print("method {}()\n", m.local_name()); }); } std::string ClassData::as_human_readable() const { if (is_typed_callable_interface()) { - const auto *m_invoke = get_instance_method("__invoke"); + const auto* m_invoke = get_instance_method("__invoke"); return m_invoke ? m_invoke->function->as_human_readable() : name; } if (is_ffi_scope()) { @@ -83,8 +70,8 @@ std::string ClassData::as_human_readable() const { return name; } -FunctionPtr ClassData::gen_holder_function(const std::string &name) { - std::string func_name = "$" + replace_backslashes(name); // function-wrapper for class +FunctionPtr ClassData::gen_holder_function(const std::string& name) { + std::string func_name = "$" + replace_backslashes(name); // function-wrapper for class auto func_params = VertexAdaptor::create(); auto func_body = VertexAdaptor::create(); auto func_root = VertexAdaptor::create(func_params, func_body); @@ -114,9 +101,7 @@ FunctionPtr ClassData::add_virt_clone() { std::string virt_clone_f_name = replace_backslashes(name) + "$$" + NAME_OF_VIRT_CLONE; auto param_list = VertexAdaptor::create(gen_param_this({})); - auto body = !is_interface() - ? VertexAdaptor::create(VertexAdaptor::create(clone_this)) - : VertexAdaptor::create(); + auto body = !is_interface() ? VertexAdaptor::create(VertexAdaptor::create(clone_this)) : VertexAdaptor::create(); auto v_op_function = VertexAdaptor::create(param_list, body); FunctionPtr f_virt_clone = FunctionData::create_function(virt_clone_f_name, v_op_function, FunctionData::func_local); @@ -126,7 +111,7 @@ FunctionPtr ClassData::add_virt_clone() { f_virt_clone->modifiers = FunctionModifiers::instance_public(); f_virt_clone->root.set_location_recursively(Location(location_line_num)); - members.add_instance_method(f_virt_clone); // don't need a lock here, it's invoked from a sync pipe + members.add_instance_method(f_virt_clone); // don't need a lock here, it's invoked from a sync pipe return f_virt_clone; } @@ -139,7 +124,7 @@ std::string ClassData::get_subdir() const { return (is_lambda ? "cl_l_" : "cl_") + std::to_string(bucket); } -void ClassData::create_constructor_with_parent_call(DataStream &os) { +void ClassData::create_constructor_with_parent_call(DataStream& os) { auto parent_constructor = parent_class->construct_function; auto list = parent_constructor->root->param_list().clone(); // skip parent's this @@ -153,7 +138,7 @@ void ClassData::create_constructor_with_parent_call(DataStream &os) construct_function->is_auto_inherited = true; } -void ClassData::create_default_constructor_if_required(DataStream &os) { +void ClassData::create_default_constructor_if_required(DataStream& os) { if (!is_class() || construct_function || name == "KphpConfiguration") { return; } @@ -171,7 +156,8 @@ void ClassData::create_default_constructor_if_required(DataStream & } } -void ClassData::create_constructor(VertexAdaptor param_list, VertexAdaptor body, const PhpDocComment *phpdoc, DataStream &os) { +void ClassData::create_constructor(VertexAdaptor param_list, VertexAdaptor body, const PhpDocComment* phpdoc, + DataStream& os) { auto func = VertexAdaptor::create(param_list, body); func.set_location_recursively(Location{location_line_num}); create_constructor(func); @@ -201,7 +187,7 @@ bool ClassData::is_parent_of(ClassPtr other) const { return true; } - for (const auto &interface : other->implements) { + for (const auto& interface : other->implements) { if (is_parent_of(interface)) { return true; } @@ -242,7 +228,7 @@ std::vector ClassData::get_common_base_or_interface(ClassPtr other) co if (cur_ancestor->parent_class) { active_ancestors.push(cur_ancestor->parent_class); } - for (const auto &c : cur_ancestor->implements) { + for (const auto& c : cur_ancestor->implements) { active_ancestors.push(c); } } @@ -250,28 +236,28 @@ std::vector ClassData::get_common_base_or_interface(ClassPtr other) co return lcas; } -static const ClassMemberInstanceMethod *find_method_in_interface(InterfacePtr interface, vk::string_view local_name) { +static const ClassMemberInstanceMethod* find_method_in_interface(InterfacePtr interface, vk::string_view local_name) { // we don't lock the class here: it's assumed, that members are not inserted concurrently - if (const auto *member = interface->members.find_by_local_name(local_name)) { + if (const auto* member = interface->members.find_by_local_name(local_name)) { return member; } // interfaces can extend multiple other interfaces; these interfaces are stored in 'implements' member for (InterfacePtr base_interface : interface->implements) { - if (const auto *member = find_method_in_interface(base_interface, local_name)) { + if (const auto* member = find_method_in_interface(base_interface, local_name)) { return member; } } return nullptr; } -const ClassMemberInstanceMethod *ClassData::find_instance_method_by_local_name(vk::string_view local_name) const { - const ClassMemberInstanceMethod *result{nullptr}; +const ClassMemberInstanceMethod* ClassData::find_instance_method_by_local_name(vk::string_view local_name) const { + const ClassMemberInstanceMethod* result{nullptr}; ClassPtr current = get_self(); while (current) { // we don't lock the class here: it's assumed, that members are not inserted concurrently - const auto *member = current->members.find_by_local_name(local_name); + const auto* member = current->members.find_by_local_name(local_name); if (member) { if (!member->function->modifiers.is_abstract()) { @@ -285,7 +271,7 @@ const ClassMemberInstanceMethod *ClassData::find_instance_method_by_local_name(v // if we already found some abstract implementation, don't bother with interfaces traversal if (!result) { for (InterfacePtr interface : current->implements) { - if (const auto *member = find_method_in_interface(interface, local_name)) { + if (const auto* member = find_method_in_interface(interface, local_name)) { result = member; break; } @@ -316,7 +302,7 @@ VertexAdaptor ClassData::gen_vertex_this(Location location) { std::vector ClassData::get_all_derived_classes() const { std::vector inheritors{get_self()}; for (int last_derived_indx = 0; last_derived_indx != inheritors.size(); ++last_derived_indx) { - const auto &cur_derived = inheritors[last_derived_indx]->derived_classes; + const auto& cur_derived = inheritors[last_derived_indx]->derived_classes; inheritors.insert(inheritors.end(), cur_derived.begin(), cur_derived.end()); } return inheritors; @@ -348,27 +334,26 @@ bool ClassData::is_polymorphic_or_has_polymorphic_member() const { return has_polymorphic_member_dfs(checked); } -bool ClassData::has_polymorphic_member_dfs(std::unordered_set &checked) const { - return nullptr != members.find_member( - [&checked](const ClassMemberInstanceField &field) { - std::unordered_set sub_classes; - field.var->tinf_node.get_type()->get_all_class_types_inside(sub_classes); - for (auto klass : sub_classes) { - if (checked.insert(klass).second) { - if (klass->is_polymorphic_class() || klass->has_polymorphic_member_dfs(checked)) { - return true; - } +bool ClassData::has_polymorphic_member_dfs(std::unordered_set& checked) const { + return nullptr != members.find_member([&checked](const ClassMemberInstanceField& field) { + std::unordered_set sub_classes; + field.var->tinf_node.get_type()->get_all_class_types_inside(sub_classes); + for (auto klass : sub_classes) { + if (checked.insert(klass).second) { + if (klass->is_polymorphic_class() || klass->has_polymorphic_member_dfs(checked)) { + return true; } } - return false; - }); + } + return false; + }); } bool ClassData::does_need_codegen() const { return need_generated_stub || (!is_builtin() && !is_trait() && (really_used || is_tl_class)); } -bool operator<(const ClassPtr &lhs, const ClassPtr &rhs) { +bool operator<(const ClassPtr& lhs, const ClassPtr& rhs) { return lhs->name < rhs->name; } @@ -380,7 +365,7 @@ void ClassData::mark_as_used() { if (parent_class) { parent_class->mark_as_used(); } - for (const auto &interface : implements) { + for (const auto& interface : implements) { interface->mark_as_used(); } } @@ -393,7 +378,7 @@ void ClassData::set_atomic_field_deeply(bool on_fields) { this->*field_ptr = true; if (on_fields) { - members.for_each([](ClassMemberInstanceField &field) { + members.for_each([](ClassMemberInstanceField& field) { std::unordered_set sub_classes; field.var->tinf_node.get_type()->get_all_class_types_inside(sub_classes); for (auto klass : sub_classes) { @@ -442,8 +427,8 @@ void ClassData::add_str_dependent(FunctionPtr cur_function, ClassType type, vk:: } void ClassData::register_defines() const { - members.for_each([this](const ClassMemberConstant &c) { - auto *data = new DefineData(std::string{c.global_name()}, c.value, DefineData::def_unknown); + members.for_each([this](const ClassMemberConstant& c) { + auto* data = new DefineData(std::string{c.global_name()}, c.value, DefineData::def_unknown); data->file_id = file_id; data->access = c.access; data->class_id = get_self(); @@ -451,13 +436,13 @@ void ClassData::register_defines() const { }); } -std::vector ClassData::get_job_shared_memory_pieces() const { +std::vector ClassData::get_job_shared_memory_pieces() const { auto shared_memory_piece_interface = G->get_class("KphpJobWorkerSharedMemoryPiece"); kphp_assert(shared_memory_piece_interface); - std::vector res; + std::vector res; for (ClassPtr ancestor : get_all_ancestors()) { - ancestor->members.for_each([&](const ClassMemberInstanceField &field) { + ancestor->members.for_each([&](const ClassMemberInstanceField& field) { for (ClassPtr field_class : field.get_inferred_type()->class_types()) { if (shared_memory_piece_interface->is_parent_of(field_class)) { res.emplace_back(&field); diff --git a/compiler/data/class-data.h b/compiler/data/class-data.h index 58c0dd082c..051f1f3875 100644 --- a/compiler/data/class-data.h +++ b/compiler/data/class-data.h @@ -22,13 +22,11 @@ struct FFIClassDataMixin; struct FFIScopeDataMixin; -namespace kphp_json { class KphpJsonTagList; } +namespace kphp_json { +class KphpJsonTagList; +} -enum class SubtreeImmutableType { - immutable, - not_immutable, - not_visited -}; +enum class SubtreeImmutableType { immutable, not_immutable, not_visited }; enum class ClassType { klass, @@ -39,30 +37,32 @@ enum class ClassType { }; class ClassData : public Lockable { - DEBUG_STRING_METHOD { return as_human_readable(); } - + DEBUG_STRING_METHOD { + return as_human_readable(); + } + public: // extends/implements/use trait description in a string form (class_name) struct StrDependence { ClassType type; std::string class_name; - StrDependence(ClassType type, std::string class_name) : - type(type), - class_name(std::move(class_name)) {} + StrDependence(ClassType type, std::string class_name) + : type(type), + class_name(std::move(class_name)) {} }; int id{0}; ClassType class_type{ClassType::klass}; // class/interface/trait std::string name; // class name with a full namespace path and slashes: "VK\Feed\A" - ClassPtr parent_class; // extends + ClassPtr parent_class; // extends std::vector implements; std::vector derived_classes; FunctionPtr construct_function; - const PhpDocComment *phpdoc{nullptr}; - const kphp_json::KphpJsonTagList *kphp_json_tags{nullptr}; + const PhpDocComment* phpdoc{nullptr}; + const kphp_json::KphpJsonTagList* kphp_json_tags{nullptr}; bool can_be_php_autoloaded{false}; bool is_immutable{false}; @@ -94,40 +94,39 @@ class ClassData : public Lockable { ClassModifiers modifiers; ClassMembersContainer members; - const TypeHint *type_hint{nullptr}; - const TypeData *const type_data; + const TypeHint* type_hint{nullptr}; + const TypeData* const type_data; - FFIClassDataMixin *ffi_class_mixin = nullptr; // non-null for ffi_cdata classes - FFIScopeDataMixin *ffi_scope_mixin = nullptr; // non-null for ffi_scope classes + FFIClassDataMixin* ffi_class_mixin = nullptr; // non-null for ffi_cdata classes + FFIScopeDataMixin* ffi_scope_mixin = nullptr; // non-null for ffi_scope classes // if JsonEncoder::encode() and MyJsonEncoder::decode() were called for this class, // this field will contain [ {JsonEncoder,true}, {MyJsonEncoder,false} ] std::forward_list> json_encoders; - static const char *NAME_OF_VIRT_CLONE; - static const char *NAME_OF_CLONE; - static const char *NAME_OF_CONSTRUCT; - static const char *NAME_OF_TO_STRING; - static const char *NAME_OF_WAKEUP; + static const char* NAME_OF_VIRT_CLONE; + static const char* NAME_OF_CLONE; + static const char* NAME_OF_CONSTRUCT; + static const char* NAME_OF_TO_STRING; + static const char* NAME_OF_WAKEUP; explicit ClassData(ClassType type); std::string as_human_readable() const; static VertexAdaptor gen_vertex_this(Location location); - FunctionPtr gen_holder_function(const std::string &name); + FunctionPtr gen_holder_function(const std::string& name); FunctionPtr add_virt_clone(); void add_class_constant(); - void create_constructor_with_parent_call(DataStream &os); - void create_default_constructor_if_required(DataStream &os); - void create_constructor(VertexAdaptor param_list, VertexAdaptor body, const PhpDocComment *phpdoc, DataStream &os); + void create_constructor_with_parent_call(DataStream& os); + void create_default_constructor_if_required(DataStream& os); + void create_constructor(VertexAdaptor param_list, VertexAdaptor body, const PhpDocComment* phpdoc, DataStream& os); void create_constructor(VertexAdaptor func); static auto gen_param_this(Location location) { return VertexAdaptor::create(gen_vertex_this(location)); } - bool is_polymorphic_class() const { return !derived_classes.empty() || !implements.empty() || parent_class || may_be_mixed; } @@ -136,32 +135,46 @@ class ClassData : public Lockable { return !members.has_any_instance_var() && !is_builtin() && !is_tl_class && !is_polymorphic_class(); } - bool is_class() const { return class_type == ClassType::klass; } - bool is_interface() const { return class_type == ClassType::interface; } - bool is_trait() const { return class_type == ClassType::trait; } - bool is_ffi_scope() const { return class_type == ClassType::ffi_scope; } - bool is_ffi_cdata() const { return class_type == ClassType::ffi_cdata; } - bool is_lambda_class() const { return class_type == ClassType::klass && is_lambda; } - bool is_typed_callable_interface() const { return class_type == ClassType::interface && is_lambda; } + bool is_class() const { + return class_type == ClassType::klass; + } + bool is_interface() const { + return class_type == ClassType::interface; + } + bool is_trait() const { + return class_type == ClassType::trait; + } + bool is_ffi_scope() const { + return class_type == ClassType::ffi_scope; + } + bool is_ffi_cdata() const { + return class_type == ClassType::ffi_cdata; + } + bool is_lambda_class() const { + return class_type == ClassType::klass && is_lambda; + } + bool is_typed_callable_interface() const { + return class_type == ClassType::interface && is_lambda; + } bool is_parent_of(ClassPtr other) const; std::vector get_common_base_or_interface(ClassPtr other) const; - const ClassMemberInstanceMethod *get_instance_method(vk::string_view local_name) const { + const ClassMemberInstanceMethod* get_instance_method(vk::string_view local_name) const { return find_instance_method_by_local_name(local_name); } - const ClassMemberInstanceField *get_instance_field(vk::string_view local_name) const { + const ClassMemberInstanceField* get_instance_field(vk::string_view local_name) const { return find_by_local_name(local_name); } - const ClassMemberStaticField *get_static_field(vk::string_view local_name) const { + const ClassMemberStaticField* get_static_field(vk::string_view local_name) const { return find_by_local_name(local_name); } - const ClassMemberConstant *get_constant(vk::string_view local_name) const { + const ClassMemberConstant* get_constant(vk::string_view local_name) const { return find_by_local_name(local_name); } ClassPtr get_self() const { - return ClassPtr{const_cast(this)}; + return ClassPtr{const_cast(this)}; } FunctionPtr get_holder_function() const; @@ -171,7 +184,7 @@ class ClassData : public Lockable { return vk::any_of(get_all_derived_classes(), has_several_parents); } - void set_name_and_src_name(const std::string &full_name); + void set_name_and_src_name(const std::string& full_name); void debugPrint(); @@ -181,10 +194,10 @@ class ClassData : public Lockable { std::string get_subdir() const; - const std::string *get_parent_class_name() const { + const std::string* get_parent_class_name() const { // this method returns string name from the extends; // it can work before the classes are bound (i.e. parent_class is not set yet) - for (const auto &dep : str_dependents) { + for (const auto& dep : str_dependents) { if (dep.type == ClassType::klass) { return &dep.class_name; } @@ -207,27 +220,27 @@ class ClassData : public Lockable { void deeply_require_may_be_mixed_base(); void add_str_dependent(FunctionPtr cur_function, ClassType type, vk::string_view class_name); - const std::vector &get_str_dependents() const { + const std::vector& get_str_dependents() const { return str_dependents; } void register_defines() const; - std::vector get_job_shared_memory_pieces() const; + std::vector get_job_shared_memory_pieces() const; private: - bool has_polymorphic_member_dfs(std::unordered_set &checked) const; + bool has_polymorphic_member_dfs(std::unordered_set& checked) const; - const ClassMemberInstanceMethod *find_instance_method_by_local_name(vk::string_view local_name) const; + const ClassMemberInstanceMethod* find_instance_method_by_local_name(vk::string_view local_name) const; template - const MemberT *find_by_local_name(vk::string_view local_name) const { + const MemberT* find_by_local_name(vk::string_view local_name) const { // we don't lock the class here: it's assumed, that members are not inserted concurrently - if (const auto *member = members.find_by_local_name(local_name)) { + if (const auto* member = members.find_by_local_name(local_name)) { return member; } for (ClassPtr ancestor : get_all_ancestors()) { - if (const auto *member = ancestor->members.find_by_local_name(local_name)) { + if (const auto* member = ancestor->members.find_by_local_name(local_name)) { return member; } } @@ -235,7 +248,7 @@ class ClassData : public Lockable { return {}; } - template ClassData:: *field_ptr> + template ClassData::*field_ptr> void set_atomic_field_deeply(bool on_fields = true); // extends/implements/use trait during the parsing (before ptr is assigned) @@ -245,4 +258,4 @@ class ClassData : public Lockable { bool is_lambda{false}; }; -bool operator<(const ClassPtr &lhs, const ClassPtr &rhs); +bool operator<(const ClassPtr& lhs, const ClassPtr& rhs); diff --git a/compiler/data/class-members.cpp b/compiler/data/class-members.cpp index 434b62df58..39b3940e7c 100644 --- a/compiler/data/class-members.cpp +++ b/compiler/data/class-members.cpp @@ -19,11 +19,11 @@ #include "compiler/utils/string-utils.h" #include "compiler/vertex.h" -vk::string_view ClassMemberStaticMethod::global_name() const & { +vk::string_view ClassMemberStaticMethod::global_name() const& { return function->name; } -vk::string_view ClassMemberStaticMethod::local_name() const & { +vk::string_view ClassMemberStaticMethod::local_name() const& { return function->local_name(); } @@ -35,11 +35,11 @@ std::string ClassMemberStaticMethod::get_hash_name() const { return hash_name(global_name()); } -const std::string &ClassMemberInstanceMethod::global_name() const { +const std::string& ClassMemberInstanceMethod::global_name() const { return function->name; } -vk::string_view ClassMemberInstanceMethod::local_name() const & { +vk::string_view ClassMemberInstanceMethod::local_name() const& { return function->local_name(); } @@ -51,11 +51,12 @@ std::string ClassMemberInstanceMethod::get_hash_name() const { return hash_name(local_name()); } -inline ClassMemberStaticField::ClassMemberStaticField(ClassPtr klass, VertexAdaptor root, VertexPtr def_val, FieldModifiers modifiers, const PhpDocComment *phpdoc, const TypeHint *type_hint) : - modifiers(modifiers), - root(root), - phpdoc(phpdoc), - type_hint(type_hint) { +inline ClassMemberStaticField::ClassMemberStaticField(ClassPtr klass, VertexAdaptor root, VertexPtr def_val, FieldModifiers modifiers, + const PhpDocComment* phpdoc, const TypeHint* type_hint) + : modifiers(modifiers), + root(root), + phpdoc(phpdoc), + type_hint(type_hint) { std::string global_var_name = replace_backslashes(klass->name) + "$$" + root->get_string(); var = G->get_global_var(global_var_name, def_val); @@ -64,7 +65,7 @@ inline ClassMemberStaticField::ClassMemberStaticField(ClassPtr klass, VertexAdap var->class_id = klass; } -vk::string_view ClassMemberStaticField::local_name() const & { +vk::string_view ClassMemberStaticField::local_name() const& { return root->str_val; } @@ -76,11 +77,11 @@ std::string ClassMemberStaticField::get_hash_name() const { return hash_name(local_name()); } -const TypeData *ClassMemberStaticField::get_inferred_type() const { +const TypeData* ClassMemberStaticField::get_inferred_type() const { return tinf::get_type(var); } -vk::string_view ClassMemberInstanceField::local_name() const & { +vk::string_view ClassMemberInstanceField::local_name() const& { return var->name; } @@ -92,11 +93,12 @@ std::string ClassMemberInstanceField::get_hash_name() const { return hash_name(local_name()); } -ClassMemberInstanceField::ClassMemberInstanceField(ClassPtr klass, VertexAdaptor root, VertexPtr def_val, FieldModifiers modifiers, const PhpDocComment *phpdoc, const TypeHint *type_hint) : - modifiers(modifiers), - root(root), - phpdoc(phpdoc), - type_hint(type_hint) { +ClassMemberInstanceField::ClassMemberInstanceField(ClassPtr klass, VertexAdaptor root, VertexPtr def_val, FieldModifiers modifiers, + const PhpDocComment* phpdoc, const TypeHint* type_hint) + : modifiers(modifiers), + root(root), + phpdoc(phpdoc), + type_hint(type_hint) { std::string local_var_name = root->get_string(); var = G->create_var(local_var_name, VarData::var_instance_t); @@ -106,21 +108,21 @@ ClassMemberInstanceField::ClassMemberInstanceField(ClassPtr klass, VertexAdaptor var->marked_as_const = klass->is_immutable || (phpdoc && phpdoc->has_tag(PhpDocType::kphp_const)); } -const TypeData *ClassMemberInstanceField::get_inferred_type() const { +const TypeData* ClassMemberInstanceField::get_inferred_type() const { return tinf::get_type(var); } -inline ClassMemberConstant::ClassMemberConstant(ClassPtr klass, const std::string &const_name, VertexPtr value, AccessModifiers access) : - value(value), - access(access) { +inline ClassMemberConstant::ClassMemberConstant(ClassPtr klass, const std::string& const_name, VertexPtr value, AccessModifiers access) + : value(value), + access(access) { define_name = "c#" + replace_backslashes(klass->name) + "$$" + const_name; } -vk::string_view ClassMemberConstant::global_name() const & { +vk::string_view ClassMemberConstant::global_name() const& { return define_name; } -vk::string_view ClassMemberConstant::local_name() const & { +vk::string_view ClassMemberConstant::local_name() const& { return get_local_name_from_global_$$(define_name); } @@ -132,20 +134,18 @@ std::string ClassMemberConstant::get_hash_name() const { return std::string{hash_name(local_name())}; } -template -void ClassMembersContainer::append_member(MemberT &&member) { +template +void ClassMembersContainer::append_member(MemberT&& member) { auto hash_num = vk::std_hash(member.get_hash_name()); - kphp_error(names_hashes.insert(hash_num).second, - fmt_format("Redeclaration of {}::{}", klass->name, member.get_hash_name())); + kphp_error(names_hashes.insert(hash_num).second, fmt_format("Redeclaration of {}::{}", klass->name, member.get_hash_name())); get_all_of().push_back(std::forward(member)); - //printf("append %s::%s\n", klass->name.c_str(), hash_name.c_str()); + // printf("append %s::%s\n", klass->name.c_str(), hash_name.c_str()); } inline bool ClassMembersContainer::member_exists(vk::string_view hash_name) const { return vk::contains(names_hashes, vk::std_hash(hash_name)); } - void ClassMembersContainer::add_static_method(FunctionPtr function) { append_member(ClassMemberStaticMethod{function}); // note that this method gets all functions during the parsing; some of them may not be required @@ -176,15 +176,17 @@ void ClassMembersContainer::add_instance_method(FunctionPtr function) { } } -void ClassMembersContainer::add_static_field(VertexAdaptor root, VertexPtr def_val, FieldModifiers modifiers, const PhpDocComment *phpdoc, const TypeHint *type_hint) { +void ClassMembersContainer::add_static_field(VertexAdaptor root, VertexPtr def_val, FieldModifiers modifiers, const PhpDocComment* phpdoc, + const TypeHint* type_hint) { append_member(ClassMemberStaticField{klass, root, def_val, modifiers, phpdoc, type_hint}); } -void ClassMembersContainer::add_instance_field(VertexAdaptor root, VertexPtr def_val, FieldModifiers modifiers, const PhpDocComment *phpdoc, const TypeHint *type_hint) { +void ClassMembersContainer::add_instance_field(VertexAdaptor root, VertexPtr def_val, FieldModifiers modifiers, const PhpDocComment* phpdoc, + const TypeHint* type_hint) { append_member(ClassMemberInstanceField{klass, root, def_val, modifiers, phpdoc, type_hint}); } -void ClassMembersContainer::add_constant(const std::string &const_name, VertexPtr value, AccessModifiers access) { +void ClassMembersContainer::add_constant(const std::string& const_name, VertexPtr value, AccessModifiers access) { append_member(ClassMemberConstant{klass, const_name, value, access}); } @@ -193,11 +195,11 @@ bool ClassMembersContainer::has_constant(vk::string_view local_name) const { } bool ClassMembersContainer::has_field(vk::string_view local_name) const { - return member_exists(ClassMemberStaticField::hash_name(local_name)); // either static or instance field — they can't share the same name + return member_exists(ClassMemberStaticField::hash_name(local_name)); // either static or instance field — they can't share the same name } bool ClassMembersContainer::has_instance_method(vk::string_view local_name) const { - return member_exists(ClassMemberInstanceMethod::hash_name(local_name)); // either static or instance method — they can't share the same name + return member_exists(ClassMemberInstanceMethod::hash_name(local_name)); // either static or instance method — they can't share the same name } bool ClassMembersContainer::has_static_method(vk::string_view local_name) const { @@ -205,39 +207,38 @@ bool ClassMembersContainer::has_static_method(vk::string_view local_name) const } FunctionPtr ClassMembersContainer::get_constructor() const { - if (const auto *construct_method = get_instance_method(ClassData::NAME_OF_CONSTRUCT)) { + if (const auto* construct_method = get_instance_method(ClassData::NAME_OF_CONSTRUCT)) { return construct_method->function; } return {}; } -const ClassMemberStaticMethod *ClassMembersContainer::get_static_method(vk::string_view local_name) const { +const ClassMemberStaticMethod* ClassMembersContainer::get_static_method(vk::string_view local_name) const { return find_by_local_name(local_name); } -const ClassMemberInstanceMethod *ClassMembersContainer::get_instance_method(vk::string_view local_name) const { +const ClassMemberInstanceMethod* ClassMembersContainer::get_instance_method(vk::string_view local_name) const { return find_by_local_name(local_name); } -const ClassMemberStaticField *ClassMembersContainer::get_static_field(vk::string_view local_name) const { +const ClassMemberStaticField* ClassMembersContainer::get_static_field(vk::string_view local_name) const { return find_by_local_name(local_name); } -const ClassMemberInstanceField *ClassMembersContainer::get_instance_field(vk::string_view local_name) const { +const ClassMemberInstanceField* ClassMembersContainer::get_instance_field(vk::string_view local_name) const { return find_by_local_name(local_name); } -const ClassMemberConstant *ClassMembersContainer::get_constant(vk::string_view local_name) const { +const ClassMemberConstant* ClassMembersContainer::get_constant(vk::string_view local_name) const { return find_by_local_name(local_name); } -ClassMemberInstanceMethod *ClassMembersContainer::get_instance_method(vk::string_view local_name) { - const auto *container = this; - return const_cast(container->get_instance_method(local_name)); +ClassMemberInstanceMethod* ClassMembersContainer::get_instance_method(vk::string_view local_name) { + const auto* container = this; + return const_cast(container->get_instance_method(local_name)); } -ClassMemberStaticMethod *ClassMembersContainer::get_static_method(vk::string_view local_name) { - const auto *container = this; - return const_cast(container->get_static_method(local_name)); +ClassMemberStaticMethod* ClassMembersContainer::get_static_method(vk::string_view local_name) { + const auto* container = this; + return const_cast(container->get_static_method(local_name)); } - diff --git a/compiler/data/class-members.h b/compiler/data/class-members.h index d3f911bc9a..462c8fd137 100644 --- a/compiler/data/class-members.h +++ b/compiler/data/class-members.h @@ -35,19 +35,21 @@ class TypeData; class ClassMembersContainer; -namespace kphp_json { class KphpJsonTagList; } +namespace kphp_json { +class KphpJsonTagList; +} struct ClassMemberStaticMethod { FunctionPtr function; - explicit ClassMemberStaticMethod(FunctionPtr function) : - function(std::move(function)) {} + explicit ClassMemberStaticMethod(FunctionPtr function) + : function(std::move(function)) {} - vk::string_view global_name() const &; - vk::string_view global_name() const && = delete; + vk::string_view global_name() const&; + vk::string_view global_name() const&& = delete; - vk::string_view local_name() const &; - vk::string_view local_name() const && = delete; + vk::string_view local_name() const&; + vk::string_view local_name() const&& = delete; // can't use name() due to the context-inheritance (it introduces collisions) static std::string hash_name(vk::string_view name); @@ -57,11 +59,11 @@ struct ClassMemberStaticMethod { struct ClassMemberInstanceMethod { FunctionPtr function; - explicit ClassMemberInstanceMethod(FunctionPtr function) : - function(std::move(function)) {} + explicit ClassMemberInstanceMethod(FunctionPtr function) + : function(std::move(function)) {} - const std::string &global_name() const; - vk::string_view local_name() const &; + const std::string& global_name() const; + vk::string_view local_name() const&; static std::string hash_name(vk::string_view name); std::string get_hash_name() const; }; @@ -70,35 +72,37 @@ struct ClassMemberStaticField { FieldModifiers modifiers; VertexAdaptor root; VarPtr var; - const PhpDocComment *phpdoc{nullptr}; - const TypeHint *type_hint{nullptr}; // from @var / php 7.4 type hint / default value + const PhpDocComment* phpdoc{nullptr}; + const TypeHint* type_hint{nullptr}; // from @var / php 7.4 type hint / default value - ClassMemberStaticField(ClassPtr klass, VertexAdaptor root, VertexPtr def_val, FieldModifiers modifiers, const PhpDocComment *phpdoc, const TypeHint *type_hint); + ClassMemberStaticField(ClassPtr klass, VertexAdaptor root, VertexPtr def_val, FieldModifiers modifiers, const PhpDocComment* phpdoc, + const TypeHint* type_hint); - vk::string_view local_name() const &; + vk::string_view local_name() const&; static std::string hash_name(vk::string_view name); std::string get_hash_name() const; - const TypeData *get_inferred_type() const; + const TypeData* get_inferred_type() const; }; struct ClassMemberInstanceField { FieldModifiers modifiers; VertexAdaptor root; VarPtr var; - const PhpDocComment *phpdoc{nullptr}; - const kphp_json::KphpJsonTagList *kphp_json_tags{nullptr}; - const TypeHint *type_hint{nullptr}; // from @var / php 7.4 type hint / default value + const PhpDocComment* phpdoc{nullptr}; + const kphp_json::KphpJsonTagList* kphp_json_tags{nullptr}; + const TypeHint* type_hint{nullptr}; // from @var / php 7.4 type hint / default value int8_t serialization_tag = -1; bool serialize_as_float32{false}; - ClassMemberInstanceField(ClassPtr klass, VertexAdaptor root, VertexPtr def_val, FieldModifiers modifiers, const PhpDocComment *phpdoc, const TypeHint *type_hint); + ClassMemberInstanceField(ClassPtr klass, VertexAdaptor root, VertexPtr def_val, FieldModifiers modifiers, const PhpDocComment* phpdoc, + const TypeHint* type_hint); - vk::string_view local_name() const &; - vk::string_view local_name() const && = delete; + vk::string_view local_name() const&; + vk::string_view local_name() const&& = delete; static std::string hash_name(vk::string_view name); std::string get_hash_name() const; - const TypeData *get_inferred_type() const; + const TypeData* get_inferred_type() const; }; struct ClassMemberConstant { @@ -106,18 +110,17 @@ struct ClassMemberConstant { VertexPtr value; AccessModifiers access; - ClassMemberConstant(ClassPtr klass, const std::string &const_name, VertexPtr value, AccessModifiers access); + ClassMemberConstant(ClassPtr klass, const std::string& const_name, VertexPtr value, AccessModifiers access); - vk::string_view global_name() const &; - vk::string_view global_name() const && = delete; + vk::string_view global_name() const&; + vk::string_view global_name() const&& = delete; - vk::string_view local_name() const &; - vk::string_view local_name() const && = delete; + vk::string_view local_name() const&; + vk::string_view local_name() const&& = delete; static vk::string_view hash_name(vk::string_view name); std::string get_hash_name() const; }; - /* ————————————————————————————————————— @@ -137,7 +140,7 @@ class ClassMembersContainer { std::set names_hashes; template - void append_member(MemberT &&member); + void append_member(MemberT&& member); bool member_exists(vk::string_view hash_name) const; template @@ -145,72 +148,82 @@ class ClassMembersContainer { // appropriate list selection out of the static_methods/instance_methods/etc; see implementations below template - std::list &get_all_of() { + std::list& get_all_of() { static_assert(sizeof(MemberT) == -1u, "Invalid template MemberT parameter"); return {}; } template - const std::list &get_all_of() const { return const_cast(this)->get_all_of(); } + const std::list& get_all_of() const { + return const_cast(this)->get_all_of(); + } public: - explicit ClassMembersContainer(ClassData *klass) : - klass(ClassPtr(klass)) {} + explicit ClassMembersContainer(ClassData* klass) + : klass(ClassPtr(klass)) {} template inline void for_each(CallbackT callback) const { - const auto &container = get_all_of>(); + const auto& container = get_all_of>(); std::for_each(container.cbegin(), container.cend(), std::move(callback)); } template inline void for_each(CallbackT callback) { - auto &container = get_all_of>(); + auto& container = get_all_of>(); std::for_each(container.begin(), container.end(), std::move(callback)); } template inline void remove_if(CallbackT callbackReturningBool) { - auto &container = get_all_of>(); + auto& container = get_all_of>(); container.remove_if(std::move(callbackReturningBool)); } template - inline const GetMemberT *find_member(CallbackT callbackReturningBool) const { - const auto &container = get_all_of>(); + inline const GetMemberT* find_member(CallbackT callbackReturningBool) const { + const auto& container = get_all_of>(); auto it = std::find_if(container.cbegin(), container.cend(), std::move(callbackReturningBool)); return it == container.cend() ? nullptr : &(*it); } template - inline const MemberT *find_by_local_name(vk::string_view local_name) const { - return find_member([&local_name](const MemberT &f) { return f.local_name() == local_name; }); + inline const MemberT* find_by_local_name(vk::string_view local_name) const { + return find_member([&local_name](const MemberT& f) { return f.local_name() == local_name; }); } void add_static_method(FunctionPtr function); void add_instance_method(FunctionPtr function); - void add_static_field(VertexAdaptor root, VertexPtr def_val, FieldModifiers modifiers, const PhpDocComment *phpdoc, const TypeHint *type_hint); - void add_instance_field(VertexAdaptor root, VertexPtr def_val, FieldModifiers modifiers, const PhpDocComment *phpdoc, const TypeHint *type_hint); - void add_constant(const std::string &const_name, VertexPtr value, AccessModifiers access); + void add_static_field(VertexAdaptor root, VertexPtr def_val, FieldModifiers modifiers, const PhpDocComment* phpdoc, const TypeHint* type_hint); + void add_instance_field(VertexAdaptor root, VertexPtr def_val, FieldModifiers modifiers, const PhpDocComment* phpdoc, const TypeHint* type_hint); + void add_constant(const std::string& const_name, VertexPtr value, AccessModifiers access); bool has_constant(vk::string_view local_name) const; bool has_field(vk::string_view local_name) const; bool has_instance_method(vk::string_view local_name) const; bool has_static_method(vk::string_view local_name) const; - bool has_any_instance_var() const { return !instance_fields.empty(); } - bool has_any_instance_method() const { return !instance_methods.empty(); } - bool has_any_static_var() const { return !static_fields.empty(); } - bool has_any_static_method() const { return !static_methods.empty(); } + bool has_any_instance_var() const { + return !instance_fields.empty(); + } + bool has_any_instance_method() const { + return !instance_methods.empty(); + } + bool has_any_static_var() const { + return !static_fields.empty(); + } + bool has_any_static_method() const { + return !static_methods.empty(); + } - const ClassMemberStaticMethod *get_static_method(vk::string_view local_name) const; - const ClassMemberInstanceMethod *get_instance_method(vk::string_view local_name) const; - const ClassMemberStaticField *get_static_field(vk::string_view local_name) const; - const ClassMemberInstanceField *get_instance_field(vk::string_view local_name) const; - const ClassMemberConstant *get_constant(vk::string_view local_name) const; + const ClassMemberStaticMethod* get_static_method(vk::string_view local_name) const; + const ClassMemberInstanceMethod* get_instance_method(vk::string_view local_name) const; + const ClassMemberStaticField* get_static_field(vk::string_view local_name) const; + const ClassMemberInstanceField* get_instance_field(vk::string_view local_name) const; + const ClassMemberConstant* get_constant(vk::string_view local_name) const; - ClassMemberStaticMethod *get_static_method(vk::string_view local_name); - ClassMemberInstanceMethod *get_instance_method(vk::string_view local_name); + ClassMemberStaticMethod* get_static_method(vk::string_view local_name); + ClassMemberInstanceMethod* get_instance_method(vk::string_view local_name); FunctionPtr get_constructor() const; }; @@ -225,18 +238,28 @@ inline vk::string_view get_local_name_from_global_$$(vk::string_view global_name } template -inline vk::string_view get_local_name_from_global_$$(T &&global_name) { +inline vk::string_view get_local_name_from_global_$$(T&& global_name) { static_assert(!std::is_rvalue_reference{}, "get_local_name should be called only from lvalues"); return get_local_name_from_global_$$(vk::string_view{global_name}); } template<> -inline std::list &ClassMembersContainer::get_all_of() { return static_methods; } +inline std::list& ClassMembersContainer::get_all_of() { + return static_methods; +} template<> -inline std::list &ClassMembersContainer::get_all_of() { return instance_methods; } +inline std::list& ClassMembersContainer::get_all_of() { + return instance_methods; +} template<> -inline std::list &ClassMembersContainer::get_all_of() { return static_fields; } +inline std::list& ClassMembersContainer::get_all_of() { + return static_fields; +} template<> -inline std::list &ClassMembersContainer::get_all_of() { return instance_fields; } +inline std::list& ClassMembersContainer::get_all_of() { + return instance_fields; +} template<> -inline std::list &ClassMembersContainer::get_all_of() { return constants; } +inline std::list& ClassMembersContainer::get_all_of() { + return constants; +} diff --git a/compiler/data/class-modifiers.h b/compiler/data/class-modifiers.h index 5db8e7350a..b9edeae5c2 100644 --- a/compiler/data/class-modifiers.h +++ b/compiler/data/class-modifiers.h @@ -21,8 +21,12 @@ class ClassModifiers { abstract_modifier_ = AbstractModifiers::abstract_; } - bool is_final() const { return abstract_modifier_ == AbstractModifiers::final_; } - bool is_abstract() const { return abstract_modifier_ == AbstractModifiers::abstract_; } + bool is_final() const { + return abstract_modifier_ == AbstractModifiers::final_; + } + bool is_abstract() const { + return abstract_modifier_ == AbstractModifiers::abstract_; + } private: AbstractModifiers abstract_modifier_{AbstractModifiers::not_modifier_}; diff --git a/compiler/data/composer-json-data.cpp b/compiler/data/composer-json-data.cpp index 705096b918..99908a3f13 100644 --- a/compiler/data/composer-json-data.cpp +++ b/compiler/data/composer-json-data.cpp @@ -10,32 +10,30 @@ #include "compiler/data/src-dir.h" #include "compiler/data/src-file.h" - -[[gnu::cold]] static void fire_json_error(ComposerJsonPtr inside_j, const std::string &reason, int line) { - inside_j->json_file->load(); // load a file from disk, so that error message in console outputs a line +[[gnu::cold]] static void fire_json_error(ComposerJsonPtr inside_j, const std::string& reason, int line) { + inside_j->json_file->load(); // load a file from disk, so that error message in console outputs a line stage::set_file(inside_j->json_file); stage::set_line(line); kphp_error(0, fmt_format("Failed loading {}:\n{}", inside_j->json_file->relative_file_name, reason)); } -[[gnu::cold]] static void fire_json_error(ComposerJsonPtr inside_p, const std::string &reason, const YAML::Node &y_node) { +[[gnu::cold]] static void fire_json_error(ComposerJsonPtr inside_p, const std::string& reason, const YAML::Node& y_node) { fire_json_error(inside_p, reason, y_node.Mark().line + 1); } - class ComposerJsonParser { - SrcDirPtr composer_json_dir; // /path/to/folder/ (where composer.json is placed) + SrcDirPtr composer_json_dir; // /path/to/folder/ (where composer.json is placed) ComposerJsonPtr out; - [[gnu::always_inline]] const std::string &as_string(const YAML::Node &y) { + [[gnu::always_inline]] const std::string& as_string(const YAML::Node& y) { if (!y.IsScalar() || y.Scalar().empty()) { fire_json_error(out, "expected non-empty string", y); } return y.Scalar(); } - [[gnu::always_inline]] const std::string &as_string_maybe_empty(const YAML::Node &y) { + [[gnu::always_inline]] const std::string& as_string_maybe_empty(const YAML::Node& y) { if (!y.IsScalar()) { fire_json_error(out, "expected string", y); } @@ -43,14 +41,14 @@ class ComposerJsonParser { } // in autoload/psr-0 and autoload/psr-4, dirs can occur in {"key":"dir"} or {"key":["dir1","dir2"]} - std::string parse_composer_json_autoload_psr_dir(const YAML::Node &y_dir) { + std::string parse_composer_json_autoload_psr_dir(const YAML::Node& y_dir) { std::string dir = as_string_maybe_empty(y_dir); if (dir.empty()) { dir = "./"; // composer interprets "" as "./" or "." } std::replace(dir.begin(), dir.end(), '\\', '/'); if (dir.back() != '/') { - dir.push_back('/'); // ensure that dir always ends with '/' + dir.push_back('/'); // ensure that dir always ends with '/' } return composer_json_dir->full_dir_name + dir; @@ -58,7 +56,7 @@ class ComposerJsonParser { // parse autoload/psr-0 {"namespace\\classname":"filename"} case; \\ was already replaced by / // according to psr-0 rules, {"foo\\my_test4":"src"} means that class my_test4 is in {root}/src/foo/my/test4.php - std::string parse_composer_json_autoload_psr0_classname(std::string class_name, const YAML::Node &y_filename) { + std::string parse_composer_json_autoload_psr0_classname(std::string class_name, const YAML::Node& y_filename) { std::string path = as_string_maybe_empty(y_filename); auto last_slash = class_name.find_last_of('/'); auto begin = class_name.begin(); @@ -74,14 +72,14 @@ class ComposerJsonParser { // in autoload/psr-0, either {"ns\\":"dir"} or {"ns\\":["dir1", "dir2"]} or {"ns\\classname":"file"} is allowed // here we handle all cases - void parse_composer_json_autoload_psr0_kv(const YAML::Node &y_key, const YAML::Node &y_dirs, bool is_autoload_dev) { + void parse_composer_json_autoload_psr0_kv(const YAML::Node& y_key, const YAML::Node& y_dirs, bool is_autoload_dev) { std::string key = as_string_maybe_empty(y_key); bool is_classname = !key.empty() && key.back() != '\\'; std::replace(key.begin(), key.end(), '\\', '/'); std::vector dirs; if (y_dirs.IsSequence()) { - for (const auto &y_require_dir : y_dirs) { + for (const auto& y_require_dir : y_dirs) { if (is_classname) { dirs.emplace_back(parse_composer_json_autoload_psr0_classname(key, y_require_dir)); } else { @@ -102,13 +100,13 @@ class ComposerJsonParser { } // in autoload/psr-4, either {"ns\\":"dir"} or {"ns\\":["dir1", "dir2"]} is allowed - void parse_composer_json_autoload_psr4_kv(const YAML::Node &y_prefix, const YAML::Node &y_dirs, bool is_autoload_dev) { + void parse_composer_json_autoload_psr4_kv(const YAML::Node& y_prefix, const YAML::Node& y_dirs, bool is_autoload_dev) { std::string prefix = as_string_maybe_empty(y_prefix); std::replace(prefix.begin(), prefix.end(), '\\', '/'); std::vector dirs; if (y_dirs.IsSequence()) { - for (const auto &y_require_dir : y_dirs) { + for (const auto& y_require_dir : y_dirs) { dirs.emplace_back(parse_composer_json_autoload_psr_dir(y_require_dir)); } } else if (y_dirs.IsScalar()) { @@ -118,42 +116,42 @@ class ComposerJsonParser { } out->autoload_psr4.emplace_back(ComposerJsonData::AutoloadPsr4Item{std::move(prefix), std::move(dirs), is_autoload_dev}); - }; + } // in autoload/files, every file.php is a relative path - void parse_composer_json_autoload_file(const YAML::iterator::value_type &y_filename, bool is_autoload_dev) { + void parse_composer_json_autoload_file(const YAML::iterator::value_type& y_filename, bool is_autoload_dev) { std::string abs_file_name = composer_json_dir->full_dir_name + as_string(y_filename); out->autoload_files.emplace_back(ComposerJsonData::AutoloadFileItem{std::move(abs_file_name), is_autoload_dev}); } // parse composer.json "autoload" and "autoload-dev" - void parse_composer_json_autoload(const YAML::Node &y_autoload, bool is_autoload_dev) { - if (const auto &y_psr0 = y_autoload["psr-0"]) { - for (const auto &kv : y_psr0) { + void parse_composer_json_autoload(const YAML::Node& y_autoload, bool is_autoload_dev) { + if (const auto& y_psr0 = y_autoload["psr-0"]) { + for (const auto& kv : y_psr0) { parse_composer_json_autoload_psr0_kv(kv.first, kv.second, is_autoload_dev); } } - if (const auto &y_psr4 = y_autoload["psr-4"]) { - for (const auto &kv : y_psr4) { + if (const auto& y_psr4 = y_autoload["psr-4"]) { + for (const auto& kv : y_psr4) { parse_composer_json_autoload_psr4_kv(kv.first, kv.second, is_autoload_dev); } } - if (const auto &y_files = y_autoload["files"]) { - for (const auto &y_filename : y_files) { + if (const auto& y_files = y_autoload["files"]) { + for (const auto& y_filename : y_files) { parse_composer_json_autoload_file(y_filename, is_autoload_dev); } } } // parse composer.json "require" and "require-dev" - void parse_composer_json_require(const YAML::Node &y_require, bool is_require_dev) { - for (const auto &kv : y_require) { + void parse_composer_json_require(const YAML::Node& y_require, bool is_require_dev) { + for (const auto& kv : y_require) { out->require.emplace_back(ComposerJsonData::RequireItem{as_string(kv.first), as_string(kv.second), is_require_dev}); } } // parse composer.json "name" - std::string parse_composer_json_name(const YAML::Node &y_name) { + std::string parse_composer_json_name(const YAML::Node& y_name) { std::string name = as_string(y_name); // it's supposed to be "vendorname/packagename", but we allow arbitrary return name; @@ -161,40 +159,40 @@ class ComposerJsonParser { public: explicit ComposerJsonParser(ComposerJsonPtr out) - : composer_json_dir(out->json_file->dir) - , out(std::move(out)) {} + : composer_json_dir(out->json_file->dir), + out(std::move(out)) {} - void parse_composer_json_file(const YAML::Node &y_file) { - const auto &y_name = y_file["name"]; + void parse_composer_json_file(const YAML::Node& y_file) { + const auto& y_name = y_file["name"]; if (y_name && y_name.IsScalar()) { out->package_name = parse_composer_json_name(y_name); } else { fire_json_error(out, "'name' not specified", -1); } - if (const auto &y_require = y_file["require"]) { + if (const auto& y_require = y_file["require"]) { parse_composer_json_require(y_require, false); } - if (const auto &y_require_dev = y_file["require-dev"]) { + if (const auto& y_require_dev = y_file["require-dev"]) { parse_composer_json_require(y_require_dev, true); } - if (const auto &y_autoload = y_file["autoload"]) { + if (const auto& y_autoload = y_file["autoload"]) { parse_composer_json_autoload(y_autoload, false); } - if (const auto &y_autoload_dev = y_file["autoload-dev"]) { + if (const auto& y_autoload_dev = y_file["autoload-dev"]) { parse_composer_json_autoload(y_autoload_dev, true); } } }; -ComposerJsonData::ComposerJsonData(const std::string &json_filename) - : json_file(G->register_file(json_filename, LibPtr{})) { +ComposerJsonData::ComposerJsonData(const std::string& json_filename) + : json_file(G->register_file(json_filename, LibPtr{})) { try { YAML::Node y_file = YAML::LoadFile(json_file->file_name); ComposerJsonParser parser(get_self_ptr()); parser.parse_composer_json_file(y_file); - } catch (const YAML::Exception &ex) { + } catch (const YAML::Exception& ex) { fire_json_error(get_self_ptr(), ex.msg, ex.mark.line + 1); } } diff --git a/compiler/data/composer-json-data.h b/compiler/data/composer-json-data.h index f23962a5ac..bfc5ebd367 100644 --- a/compiler/data/composer-json-data.h +++ b/compiler/data/composer-json-data.h @@ -4,48 +4,50 @@ #pragma once -#include #include +#include #include "compiler/data/data_ptr.h" #include "compiler/debug.h" - // represents composer.json structure (the parts we care about) // they are used for autoloading (in the same manner as Composer does) // and as implicit modulites class ComposerJsonData { - DEBUG_STRING_METHOD { return package_name; } + DEBUG_STRING_METHOD { + return package_name; + } - ComposerJsonPtr get_self_ptr() { return ComposerJsonPtr(this); } + ComposerJsonPtr get_self_ptr() { + return ComposerJsonPtr(this); + } public: struct RequireItem { std::string package_name; std::string version; - bool is_dev; // whether it's in "require-dev" + bool is_dev; // whether it's in "require-dev" }; struct AutoloadPsr0Item { std::string prefix; std::vector dirs; - bool prefix_is_classname; // if true, psr-0 key is "ns\\class" not "ns\\"; dirs.size = 1, dirs[0] is a .php file - bool is_dev; // whether it's in "autoload-dev" + bool prefix_is_classname; // if true, psr-0 key is "ns\\class" not "ns\\"; dirs.size = 1, dirs[0] is a .php file + bool is_dev; // whether it's in "autoload-dev" }; struct AutoloadPsr4Item { std::string prefix; std::vector dirs; - bool is_dev; // whether it's in "autoload-dev" + bool is_dev; // whether it's in "autoload-dev" }; struct AutoloadFileItem { std::string file_name; - bool is_dev; // whether it's in "autoload-dev" + bool is_dev; // whether it's in "autoload-dev" }; - - explicit ComposerJsonData(const std::string &json_filename); + explicit ComposerJsonData(const std::string& json_filename); // full absolute path to composer.json, it's registered in G, it has ->dir, kphp_error can point to it SrcFilePtr json_file; diff --git a/compiler/data/data_ptr.h b/compiler/data/data_ptr.h index 6ff443dc9e..b6fadb4e61 100644 --- a/compiler/data/data_ptr.h +++ b/compiler/data/data_ptr.h @@ -14,44 +14,44 @@ template class Id { - IdData *ptr = nullptr; + IdData* ptr = nullptr; + public: struct Hash { - size_t operator()(const Id &arg) const noexcept { + size_t operator()(const Id& arg) const noexcept { return reinterpret_cast(arg.ptr); } }; + public: Id() = default; - explicit Id(IdData *ptr): - ptr(ptr) {} + explicit Id(IdData* ptr) + : ptr(ptr) {} - Id(const Id &id) = default; + Id(const Id& id) = default; - Id(Id &&id) noexcept - : ptr(id.ptr) - { + Id(Id&& id) noexcept + : ptr(id.ptr) { id.ptr = nullptr; } template - Id(const Id &derived) - : ptr(derived.ptr) - {} + Id(const Id& derived) + : ptr(derived.ptr) {} - Id &operator=(Id id) noexcept { + Id& operator=(Id id) noexcept { std::swap(ptr, id.ptr); return *this; } template - Id &operator=(const Id &derived) { + Id& operator=(const Id& derived) { ptr = derived.ptr; return *this; } - IdData &operator*() const { + IdData& operator*() const { kphp_assert(ptr != nullptr); return *ptr; } @@ -60,22 +60,22 @@ class Id { return ptr != nullptr; } - IdData *operator->() const { + IdData* operator->() const { kphp_assert(ptr != nullptr); return ptr; } - bool operator==(const Id &other) const { + bool operator==(const Id& other) const { return ptr == other.ptr; } - bool operator!=(const Id &other) const { + bool operator!=(const Id& other) const { return !(*this == other); } }; template -void my_unique(std::vector> *v) { +void my_unique(std::vector>* v) { if (v->empty()) { return; } @@ -86,12 +86,12 @@ void my_unique(std::vector> *v) { } template -int get_index(const Id &i) { +int get_index(const Id& i) { return i->id; } template -void set_index(Id &d, int index) { +void set_index(Id& d, int index) { d->id = index; } diff --git a/compiler/data/define-data.cpp b/compiler/data/define-data.cpp index ab3ddd4d9d..9585264cf1 100644 --- a/compiler/data/define-data.cpp +++ b/compiler/data/define-data.cpp @@ -7,21 +7,19 @@ #include "compiler/data/class-data.h" #include "compiler/data/src-file.h" -DefineData::DefineData() : - id(), - type_(def_unknown), - val(nullptr) {} +DefineData::DefineData() + : id(), + type_(def_unknown), + val(nullptr) {} -DefineData::DefineData(std::string name, VertexPtr val, DefineType type_) : - id(), - type_(type_), - val(val), - name(std::move(name)) {} +DefineData::DefineData(std::string name, VertexPtr val, DefineType type_) + : id(), + type_(type_), + val(val), + name(std::move(name)) {} std::string DefineData::as_human_readable() const { - return class_id - ? class_id->as_human_readable() + "::" + get_local_name_from_global_$$(name) - : name; + return class_id ? class_id->as_human_readable() + "::" + get_local_name_from_global_$$(name) : name; } bool DefineData::is_builtin() const { diff --git a/compiler/data/define-data.h b/compiler/data/define-data.h index 44aabbe70d..dfca3f13f9 100644 --- a/compiler/data/define-data.h +++ b/compiler/data/define-data.h @@ -13,14 +13,12 @@ #include "compiler/debug.h" class DefineData : private vk::not_copyable { - DEBUG_STRING_METHOD { return name; } - + DEBUG_STRING_METHOD { + return name; + } + public: - enum DefineType { - def_unknown, - def_const, - def_var - }; + enum DefineType { def_unknown, def_const, def_var }; int id; DefineType type_; @@ -35,7 +33,9 @@ class DefineData : private vk::not_copyable { DefineData(); DefineData(std::string name, VertexPtr val, DefineType type_); - inline DefineType &type() { return type_; } + inline DefineType& type() { + return type_; + } std::string as_human_readable() const; bool is_builtin() const; diff --git a/compiler/data/ffi-data.cpp b/compiler/data/ffi-data.cpp index 42ef6e9616..0ebd8bd2f0 100644 --- a/compiler/data/ffi-data.cpp +++ b/compiler/data/ffi-data.cpp @@ -4,38 +4,31 @@ #include "compiler/data/ffi-data.h" -#include "compiler/type-hint.h" -#include "compiler/data/function-data.h" #include "common/algorithms/contains.h" +#include "compiler/data/function-data.h" +#include "compiler/type-hint.h" static std::vector make_builtin_types() { auto make_builtin_type = [](FFITypeKind kind, std::string php_class_name, std::string c_name) { std::string src_name = "C$FFI$CData<" + c_name + ">"; return FFIBuiltinType{ - FFIType{kind}, - std::move(php_class_name), - std::move(c_name), - std::move(src_name), + FFIType{kind}, + std::move(php_class_name), + std::move(c_name), + std::move(src_name), }; }; std::vector result = { - make_builtin_type(FFITypeKind::Void, "FFI\\CData_void", "void"), - make_builtin_type(FFITypeKind::Bool, "FFI\\CData_bool", "bool"), - make_builtin_type(FFITypeKind::Char, "FFI\\CData_char", "char"), - make_builtin_type(FFITypeKind::Float, "FFI\\CData_float", "float"), - make_builtin_type(FFITypeKind::Double, "FFI\\CData_double", "double"), - make_builtin_type(FFITypeKind::Int8, "FFI\\CData_int8", "int8_t"), - make_builtin_type(FFITypeKind::Int16, "FFI\\CData_int16", "int16_t"), - make_builtin_type(FFITypeKind::Int32, "FFI\\CData_int32", "int32_t"), - make_builtin_type(FFITypeKind::Int64, "FFI\\CData_int64", "int64_t"), - make_builtin_type(FFITypeKind::Uint8, "FFI\\CData_uint8", "uint8_t"), - make_builtin_type(FFITypeKind::Uint16, "FFI\\CData_uint16", "uint16_t"), - make_builtin_type(FFITypeKind::Uint32, "FFI\\CData_uint32", "uint32_t"), - make_builtin_type(FFITypeKind::Uint64, "FFI\\CData_uint64", "uint64_t"), - - make_builtin_type(FFITypeKind::Unknown, "FFI\\CData", "cdata"), - make_builtin_type(FFITypeKind::Unknown, "", "unknown"), + make_builtin_type(FFITypeKind::Void, "FFI\\CData_void", "void"), make_builtin_type(FFITypeKind::Bool, "FFI\\CData_bool", "bool"), + make_builtin_type(FFITypeKind::Char, "FFI\\CData_char", "char"), make_builtin_type(FFITypeKind::Float, "FFI\\CData_float", "float"), + make_builtin_type(FFITypeKind::Double, "FFI\\CData_double", "double"), make_builtin_type(FFITypeKind::Int8, "FFI\\CData_int8", "int8_t"), + make_builtin_type(FFITypeKind::Int16, "FFI\\CData_int16", "int16_t"), make_builtin_type(FFITypeKind::Int32, "FFI\\CData_int32", "int32_t"), + make_builtin_type(FFITypeKind::Int64, "FFI\\CData_int64", "int64_t"), make_builtin_type(FFITypeKind::Uint8, "FFI\\CData_uint8", "uint8_t"), + make_builtin_type(FFITypeKind::Uint16, "FFI\\CData_uint16", "uint16_t"), make_builtin_type(FFITypeKind::Uint32, "FFI\\CData_uint32", "uint32_t"), + make_builtin_type(FFITypeKind::Uint64, "FFI\\CData_uint64", "uint64_t"), + + make_builtin_type(FFITypeKind::Unknown, "FFI\\CData", "cdata"), make_builtin_type(FFITypeKind::Unknown, "", "unknown"), }; return result; @@ -43,8 +36,8 @@ static std::vector make_builtin_types() { static const std::vector builtin_types = make_builtin_types(); -const FFIBuiltinType *ffi_builtin_type(FFITypeKind kind) { - for (const auto &builtin_type : builtin_types) { +const FFIBuiltinType* ffi_builtin_type(FFITypeKind kind) { + for (const auto& builtin_type : builtin_types) { if (builtin_type.type.kind == kind) { return &builtin_type; } @@ -52,8 +45,8 @@ const FFIBuiltinType *ffi_builtin_type(FFITypeKind kind) { return nullptr; } -const FFIBuiltinType *ffi_builtin_type(const std::string &php_class_name) { - for (const auto &builtin_type : builtin_types) { +const FFIBuiltinType* ffi_builtin_type(const std::string& php_class_name) { + for (const auto& builtin_type : builtin_types) { if (builtin_type.php_class_name == php_class_name) { return &builtin_type; } @@ -61,7 +54,7 @@ const FFIBuiltinType *ffi_builtin_type(const std::string &php_class_name) { return nullptr; } -static ClassPtr register_builtin_class(const FFIBuiltinType *builtin, DataStream &os, ClassPtr non_ref = {}) { +static ClassPtr register_builtin_class(const FFIBuiltinType* builtin, DataStream& os, ClassPtr non_ref = {}) { bool is_ref = static_cast(non_ref); auto cdata_class = ClassPtr{new ClassData{ClassType::ffi_cdata}}; cdata_class->ffi_class_mixin = new FFIClassDataMixin{&builtin->type, "C", non_ref}; @@ -77,10 +70,10 @@ static ClassPtr register_builtin_class(const FFIBuiltinType *builtin, DataStream return cdata_class; } -void FFIRoot::register_builtin_classes(DataStream &os) { +void FFIRoot::register_builtin_classes(DataStream& os) { register_builtin_class(ffi_builtin_type("FFI\\CData"), os); - for (const auto &builtin_type : builtin_types) { + for (const auto& builtin_type : builtin_types) { if (builtin_type.type.kind == FFITypeKind::Unknown) { continue; } @@ -97,78 +90,78 @@ void FFIRoot::register_builtin_classes(DataStream &os) { } } -std::string FFIRoot::get_ffi_scope(const TypeHint *type_hint) { - if (const auto *as_instance = type_hint->try_as()) { +std::string FFIRoot::get_ffi_scope(const TypeHint* type_hint) { + if (const auto* as_instance = type_hint->try_as()) { auto klass = as_instance->to_type_data()->class_type(); return klass->ffi_class_mixin ? klass->ffi_class_mixin->scope_name : ""; } - if (const auto *as_ffi = type_hint->try_as()) { + if (const auto* as_ffi = type_hint->try_as()) { return as_ffi->scope_name; } return ""; } -const FFIType *FFIRoot::get_ffi_type(const TypeHint *type_hint) { - if (const auto *as_instance = type_hint->try_as()) { +const FFIType* FFIRoot::get_ffi_type(const TypeHint* type_hint) { + if (const auto* as_instance = type_hint->try_as()) { return get_ffi_type(as_instance->to_type_data()->class_type()); } - if (const auto *as_ffi = type_hint->try_as()) { + if (const auto* as_ffi = type_hint->try_as()) { return as_ffi->type; } return nullptr; } -const FFIType *FFIRoot::get_ffi_type(ClassPtr klass) { +const FFIType* FFIRoot::get_ffi_type(ClassPtr klass) { if (klass->ffi_class_mixin) { return klass->ffi_class_mixin->ffi_type; } return nullptr; } -const TypeHint *FFIRoot::c2php_scalar_type_hint(ClassPtr cdata_class) { - if (const auto *ffi_type = get_ffi_type(cdata_class)) { +const TypeHint* FFIRoot::c2php_scalar_type_hint(ClassPtr cdata_class) { + if (const auto* ffi_type = get_ffi_type(cdata_class)) { return c2php_scalar_type_hint(ffi_type->kind); } return nullptr; } -const TypeHint *FFIRoot::c2php_return_type_hint(const TypeHint *c_hint) { +const TypeHint* FFIRoot::c2php_return_type_hint(const TypeHint* c_hint) { return c2php_type_hint(c_hint, Php2cMode::FuncReturn); } -const TypeHint *FFIRoot::c2php_field_type_hint(const TypeHint *c_hint) { +const TypeHint* FFIRoot::c2php_field_type_hint(const TypeHint* c_hint) { return c2php_type_hint(c_hint, Php2cMode::FieldRead); } -const TypeHint *FFIRoot::c2php_scalar_type_hint(FFITypeKind kind) { +const TypeHint* FFIRoot::c2php_scalar_type_hint(FFITypeKind kind) { switch (kind) { - case FFITypeKind::Int8: - case FFITypeKind::Int16: - case FFITypeKind::Int32: - case FFITypeKind::Int64: - case FFITypeKind::Uint8: - case FFITypeKind::Uint16: - case FFITypeKind::Uint32: - case FFITypeKind::Uint64: - return TypeHintPrimitive::create(tp_int); - - case FFITypeKind::Void: - return TypeHintPrimitive::create(tp_void); - - case FFITypeKind::Bool: - return TypeHintPrimitive::create(tp_bool); - - case FFITypeKind::Float: - case FFITypeKind::Double: - return TypeHintPrimitive::create(tp_float); - - default: - return nullptr; + case FFITypeKind::Int8: + case FFITypeKind::Int16: + case FFITypeKind::Int32: + case FFITypeKind::Int64: + case FFITypeKind::Uint8: + case FFITypeKind::Uint16: + case FFITypeKind::Uint32: + case FFITypeKind::Uint64: + return TypeHintPrimitive::create(tp_int); + + case FFITypeKind::Void: + return TypeHintPrimitive::create(tp_void); + + case FFITypeKind::Bool: + return TypeHintPrimitive::create(tp_bool); + + case FFITypeKind::Float: + case FFITypeKind::Double: + return TypeHintPrimitive::create(tp_float); + + default: + return nullptr; } } -const TypeHint *FFIRoot::c2php_type_hint(const TypeHint *c_hint, Php2cMode mode) { - const FFIType *type = get_ffi_type(c_hint); +const TypeHint* FFIRoot::c2php_type_hint(const TypeHint* c_hint, Php2cMode mode) { + const FFIType* type = get_ffi_type(c_hint); if (!type) { return nullptr; } @@ -177,80 +170,80 @@ const TypeHint *FFIRoot::c2php_type_hint(const TypeHint *c_hint, Php2cMode mode) return TypeHintOptional::create(TypeHintPrimitive::create(tp_string), true, false); } - if (const auto *as_scalar = c2php_scalar_type_hint(type->kind)) { + if (const auto* as_scalar = c2php_scalar_type_hint(type->kind)) { return as_scalar; } switch (type->kind) { - case FFITypeKind::Char: - return TypeHintPrimitive::create(tp_string); - - case FFITypeKind::Pointer: - case FFITypeKind::Array: - return c_hint; - - case FFITypeKind::Struct: - case FFITypeKind::StructDef: - if (mode == Php2cMode::FieldRead) { - if (const auto *as_instance = c_hint->try_as()) { - return TypeHintInstance::create("&" + as_instance->full_class_name); - } - if (const auto *as_ffi = c_hint->try_as()) { - return TypeHintInstance::create("&" + cdata_class_name(as_ffi->scope_name, as_ffi->type->str)); - } + case FFITypeKind::Char: + return TypeHintPrimitive::create(tp_string); + + case FFITypeKind::Pointer: + case FFITypeKind::Array: + return c_hint; + + case FFITypeKind::Struct: + case FFITypeKind::StructDef: + if (mode == Php2cMode::FieldRead) { + if (const auto* as_instance = c_hint->try_as()) { + return TypeHintInstance::create("&" + as_instance->full_class_name); + } + if (const auto* as_ffi = c_hint->try_as()) { + return TypeHintInstance::create("&" + cdata_class_name(as_ffi->scope_name, as_ffi->type->str)); } - return c_hint; + } + return c_hint; - default: - return nullptr; + default: + return nullptr; } } -const TypeHint *FFIRoot::create_type_hint(const FFIType *type, const std::string &scope_name) { - const auto *builtin_type = ffi_builtin_type(type->kind); +const TypeHint* FFIRoot::create_type_hint(const FFIType* type, const std::string& scope_name) { + const auto* builtin_type = ffi_builtin_type(type->kind); if (builtin_type) { return TypeHintInstance::create(builtin_type->php_class_name); } switch (type->kind) { - case FFITypeKind::Struct: - case FFITypeKind::StructDef: - case FFITypeKind::Union: - case FFITypeKind::UnionDef: - return TypeHintInstance::create(cdata_class_name(scope_name, type->str)); - - case FFITypeKind::Pointer: - case FFITypeKind::Array: - return TypeHintFFIType::create(scope_name, type); - - case FFITypeKind::FunctionPointer: { - const auto *return_type = unboxed_type_hint(type->members[0], scope_name, true); - if (!return_type) { + case FFITypeKind::Struct: + case FFITypeKind::StructDef: + case FFITypeKind::Union: + case FFITypeKind::UnionDef: + return TypeHintInstance::create(cdata_class_name(scope_name, type->str)); + + case FFITypeKind::Pointer: + case FFITypeKind::Array: + return TypeHintFFIType::create(scope_name, type); + + case FFITypeKind::FunctionPointer: { + const auto* return_type = unboxed_type_hint(type->members[0], scope_name, true); + if (!return_type) { + return nullptr; + } + std::vector param_types; + param_types.reserve(type->members.size() - 1); + for (int i = 1; i < type->members.size(); i++) { + kphp_assert(type->members[i]->kind == FFITypeKind::Var); + const auto* param_type = unboxed_type_hint(type->members[i]->members[0], scope_name, false); + if (!param_type) { return nullptr; } - std::vector param_types; - param_types.reserve(type->members.size() - 1); - for (int i = 1; i < type->members.size(); i++) { - kphp_assert(type->members[i]->kind == FFITypeKind::Var); - const auto *param_type = unboxed_type_hint(type->members[i]->members[0], scope_name, false); - if (!param_type) { - return nullptr; - } - param_types.push_back(param_type); - } - return TypeHintCallable::create(std::move(param_types), return_type); + param_types.push_back(param_type); } + return TypeHintCallable::create(std::move(param_types), return_type); + } - default: - return nullptr; + default: + return nullptr; } } -const TypeHint *FFIRoot::unboxed_type_hint(const FFIType *type, const std::string &scope_name, bool is_return) { +const TypeHint* FFIRoot::unboxed_type_hint(const FFIType* type, const std::string& scope_name, bool is_return) { // auto-convertible types, like int and float are kept unboxed if (!is_return && type->is_cstring()) { return TypeHintOptional::create(TypeHintPrimitive::create(tp_string), true, false); } - if (const TypeHint *as_scalar = c2php_scalar_type_hint(type->kind)) { + if (const TypeHint* as_scalar = c2php_scalar_type_hint(type->kind)) { return as_scalar; } return create_type_hint(type, scope_name); @@ -259,18 +252,18 @@ const TypeHint *FFIRoot::unboxed_type_hint(const FFIType *type, const std::strin std::vector FFIRoot::get_scopes() const { std::vector result; result.reserve(scopes.size()); - for (const auto &it : scopes) { + for (const auto& it : scopes) { result.emplace_back(it.second); } - std::sort(result.begin(), result.end(), [](const auto &x, const auto &y) { return x->scope_name < y->scope_name; }); + std::sort(result.begin(), result.end(), [](const auto& x, const auto& y) { return x->scope_name < y->scope_name; }); return result; } -FFIScopeDataMixin *FFIRoot::find_scope(const std::string &scope_name) { +FFIScopeDataMixin* FFIRoot::find_scope(const std::string& scope_name) { return scopes.at(scope_name); } -bool FFIRoot::register_scope(const std::string &scope_name, FFIScopeDataMixin *data) { +bool FFIRoot::register_scope(const std::string& scope_name, FFIScopeDataMixin* data) { std::lock_guard locker{mutex}; if (vk::contains(scopes, scope_name)) { @@ -280,12 +273,10 @@ bool FFIRoot::register_scope(const std::string &scope_name, FFIScopeDataMixin *d return true; } -int FFIRoot::get_shared_lib_id(const std::string &path) { +int FFIRoot::get_shared_lib_id(const std::string& path) { std::lock_guard locker{mutex}; - const auto &it = std::find_if(shared_libs.begin(), shared_libs.end(), [&](const FFISharedLib &x){ - return x.path == path; - }); + const auto& it = std::find_if(shared_libs.begin(), shared_libs.end(), [&](const FFISharedLib& x) { return x.path == path; }); if (it != shared_libs.end()) { return std::distance(shared_libs.begin(), it); } @@ -294,19 +285,19 @@ int FFIRoot::get_shared_lib_id(const std::string &path) { return id; } -const std::vector &FFIRoot::get_shared_libs() const { +const std::vector& FFIRoot::get_shared_libs() const { return shared_libs; } void FFIRoot::bind_symbols() { int index = 0; - for (auto &it : scopes) { - auto &scope = it.second; - for (auto &sym : scope->variables) { + for (auto& it : scopes) { + auto& scope = it.second; + for (auto& sym : scope->variables) { sym.env_index = index; index++; } - for (auto &sym : scope->functions) { + for (auto& sym : scope->functions) { sym.env_index = index; index++; } @@ -315,9 +306,7 @@ void FFIRoot::bind_symbols() { } bool FFIRoot::is_ffi_scope_call(VertexAdaptor call) { - return call->extra_type == op_ex_func_call_arrow && - call->func_id->class_id && - call->func_id->class_id->is_ffi_scope(); + return call->extra_type == op_ex_func_call_arrow && call->func_id->class_id && call->func_id->class_id->is_ffi_scope(); } struct TypePrinter { @@ -337,12 +326,12 @@ struct TypePrinter { return result; } - std::string format_var(const FFIType *var) const { + std::string format_var(const FFIType* var) const { if (is_decltype) { return format_type(var->members[0]); } - const FFIType *type = var->members[0]; + const FFIType* type = var->members[0]; std::string name = var->str; std::string array_suffix; @@ -366,31 +355,31 @@ struct TypePrinter { return format_type(type) + " " + name + array_suffix; } - std::string format_function(const FFIType *f, const std::string &func_name, bool is_func_ptr) const { + std::string format_function(const FFIType* f, const std::string& func_name, bool is_func_ptr) const { std::string variadic_arg = f->is_variadic() ? ", ..." : ""; - const std::string ¶ms = "(" + format_list(f->members.begin() + 1, f->members.end()) + variadic_arg + ")"; + const std::string& params = "(" + format_list(f->members.begin() + 1, f->members.end()) + variadic_arg + ")"; if (is_func_ptr) { return format_type(f->members[0]) + " (*" + func_name + ")" + params; } - const std::string &name = func_name.empty() ? "(*)" : func_name; + const std::string& name = func_name.empty() ? "(*)" : func_name; return format_type(f->members[0]) + " " + name + params; } - std::string format_struct_or_union_def(const FFIType *s, const std::string &tag) const { + std::string format_struct_or_union_def(const FFIType* s, const std::string& tag) const { if (is_decltype) { return tag + " " + format_type_name(s->str); } return tag + " " + format_type_name(s->str) + "{ " + format_list(s->members.begin(), s->members.end(), ';') + "; }"; } - std::string format_type_name(const std::string &name) const { + std::string format_type_name(const std::string& name) const { if (name_mangling) { return FFIRoot::c_name_mangle(scope_name, name); } return name; } - std::string format_type(const FFIType *type) const { + std::string format_type(const FFIType* type) const { auto result = format_type_no_cv_qualifiers(type); if (type->flags & FFIType::Flag::Volatile) { result = "volatile " + result; @@ -401,54 +390,54 @@ struct TypePrinter { return result; } - std::string format_type_no_cv_qualifiers(const FFIType *type) const { - if (const auto *builtin = ffi_builtin_type(type->kind)) { + std::string format_type_no_cv_qualifiers(const FFIType* type) const { + if (const auto* builtin = ffi_builtin_type(type->kind)) { return builtin->c_name; } switch (type->kind) { - case FFITypeKind::StructDef: - return format_struct_or_union_def(type, "struct"); - case FFITypeKind::UnionDef: - return format_struct_or_union_def(type, "union"); - - case FFITypeKind::Union: - return "union " + format_type_name(type->str); - case FFITypeKind::Struct: - return "struct " + format_type_name(type->str); - case FFITypeKind::Enum: - return "enum " + format_type_name(type->str); - - case FFITypeKind::Var: - return format_var(type); - case FFITypeKind::Array: - if (type->num == -1) { - return format_type(type->members[0]) + "[]"; - } - return format_type(type->members[0]) + "[" + std::to_string(type->num) + "]"; - - case FFITypeKind::Pointer: - return type->members.empty() ? "*" : format_type(type->members[0]) + std::string(type->num, '*'); - - case FFITypeKind::FunctionPointer: - return format_function(type, "", true); - - case FFITypeKind::Function: - return format_function(type, is_decltype ? "" : type->str, false); - - default: - return "?"; + case FFITypeKind::StructDef: + return format_struct_or_union_def(type, "struct"); + case FFITypeKind::UnionDef: + return format_struct_or_union_def(type, "union"); + + case FFITypeKind::Union: + return "union " + format_type_name(type->str); + case FFITypeKind::Struct: + return "struct " + format_type_name(type->str); + case FFITypeKind::Enum: + return "enum " + format_type_name(type->str); + + case FFITypeKind::Var: + return format_var(type); + case FFITypeKind::Array: + if (type->num == -1) { + return format_type(type->members[0]) + "[]"; + } + return format_type(type->members[0]) + "[" + std::to_string(type->num) + "]"; + + case FFITypeKind::Pointer: + return type->members.empty() ? "*" : format_type(type->members[0]) + std::string(type->num, '*'); + + case FFITypeKind::FunctionPointer: + return format_function(type, "", true); + + case FFITypeKind::Function: + return format_function(type, is_decltype ? "" : type->str, false); + + default: + return "?"; } } }; -std::string ffi_decltype_string(const FFIType *type) { +std::string ffi_decltype_string(const FFIType* type) { TypePrinter p; p.is_decltype = true; return p.format_type(type); } -std::string ffi_mangled_decltype_string(const std::string &scope_name, const FFIType *type) { +std::string ffi_mangled_decltype_string(const std::string& scope_name, const FFIType* type) { TypePrinter p; p.is_decltype = true; p.name_mangling = true; @@ -456,16 +445,16 @@ std::string ffi_mangled_decltype_string(const std::string &scope_name, const FFI return p.format_type(type); } -std::string ffi_mangled_decltype_string(const TypeHint *type_hint) { +std::string ffi_mangled_decltype_string(const TypeHint* type_hint) { return ffi_mangled_decltype_string(FFIRoot::get_ffi_scope(type_hint), FFIRoot::get_ffi_type(type_hint)); } -std::string ffi_type_string(const FFIType *type) { +std::string ffi_type_string(const FFIType* type) { TypePrinter p; return p.format_type(type); } -std::string ffi_mangled_type_string(const std::string &scope_name, const FFIType *type) { +std::string ffi_mangled_type_string(const std::string& scope_name, const FFIType* type) { TypePrinter p; p.scope_name = scope_name; p.name_mangling = true; diff --git a/compiler/data/ffi-data.h b/compiler/data/ffi-data.h index 413fed2687..c1b39ce823 100644 --- a/compiler/data/ffi-data.h +++ b/compiler/data/ffi-data.h @@ -4,11 +4,11 @@ #pragma once -#include #include +#include -#include "compiler/ffi/ffi_types.h" #include "compiler/data/class-data.h" +#include "compiler/ffi/ffi_types.h" // FFI symbol is an extern variable or function information carrier struct FFISymbol { @@ -16,25 +16,32 @@ struct FFISymbol { // it's an index inside FFIEnv.symbols array (runtime structure) int env_index = -1; - const FFIType *type = nullptr; + const FFIType* type = nullptr; - FFISymbol(const FFIType *type): type{type} {} + FFISymbol(const FFIType* type) + : type{type} {} - std::string name() const { return type->str; } + std::string name() const { + return type->str; + } - bool operator <(const FFISymbol& other) const { return name() < other.name(); } + bool operator<(const FFISymbol& other) const { + return name() < other.name(); + } }; struct FFIClassDataMixin { - FFIClassDataMixin(const FFIType *ffi_type, std::string scope_name, ClassPtr non_ref = {}) - : non_ref{non_ref} - , ffi_type{ffi_type} - , scope_name{std::move(scope_name)} {} + FFIClassDataMixin(const FFIType* ffi_type, std::string scope_name, ClassPtr non_ref = {}) + : non_ref{non_ref}, + ffi_type{ffi_type}, + scope_name{std::move(scope_name)} {} - bool is_ref() const noexcept { return static_cast(non_ref); } + bool is_ref() const noexcept { + return static_cast(non_ref); + } ClassPtr non_ref; // for reference types this field will contain the original (non-referential) type - const FFIType *ffi_type; + const FFIType* ffi_type; std::string scope_name; }; @@ -56,7 +63,9 @@ struct FFIScopeDataMixin { FFITypedefs typedefs; - bool is_shared_lib() const noexcept { return shared_lib_id != -1; } + bool is_shared_lib() const noexcept { + return shared_lib_id != -1; + } int get_env_offset() const noexcept { // variables are placed before functions, so if there @@ -68,15 +77,17 @@ struct FFIScopeDataMixin { return functions[0].env_index; } - const FFISymbol *find_variable(const vk::string_view name) { return find_symbol(variables, name); } - const FFISymbol *find_function(const vk::string_view name) { return find_symbol(functions, name); } + const FFISymbol* find_variable(const vk::string_view name) { + return find_symbol(variables, name); + } + const FFISymbol* find_function(const vk::string_view name) { + return find_symbol(functions, name); + } private: - - static const FFISymbol *find_symbol(const std::vector &sorted_vector, vk::string_view name) { - const auto &it = std::lower_bound(sorted_vector.begin(), sorted_vector.end(), name, [](const FFISymbol &lhs, vk::string_view name) { - return lhs.name() < name; - }); + static const FFISymbol* find_symbol(const std::vector& sorted_vector, vk::string_view name) { + const auto& it = + std::lower_bound(sorted_vector.begin(), sorted_vector.end(), name, [](const FFISymbol& lhs, vk::string_view name) { return lhs.name() < name; }); if (it != sorted_vector.end() && it->name() == name) { return &sorted_vector[std::distance(sorted_vector.begin(), it)]; } @@ -98,63 +109,63 @@ class FFIRoot { int num_dynamic_symbols = 0; public: + const TypeHint* c2php_field_type_hint(const TypeHint* c_hint); + const TypeHint* c2php_return_type_hint(const TypeHint* c_hint); + const TypeHint* c2php_scalar_type_hint(ClassPtr cdata_class); - const TypeHint *c2php_field_type_hint(const TypeHint *c_hint); - const TypeHint *c2php_return_type_hint(const TypeHint *c_hint); - const TypeHint *c2php_scalar_type_hint(ClassPtr cdata_class); + const TypeHint* create_type_hint(const FFIType* type, const std::string& scope_name); - const TypeHint *create_type_hint(const FFIType *type, const std::string &scope_name); - - const std::vector &get_shared_libs() const; - int get_shared_lib_id(const std::string &path); + const std::vector& get_shared_libs() const; + int get_shared_lib_id(const std::string& path); std::vector get_scopes() const; - FFIScopeDataMixin* find_scope(const std::string &scope_name); + FFIScopeDataMixin* find_scope(const std::string& scope_name); - static const FFIType *get_ffi_type(ClassPtr klass); - static const FFIType *get_ffi_type(const TypeHint *type_hint); - static std::string get_ffi_scope(const TypeHint *type_hint); + static const FFIType* get_ffi_type(ClassPtr klass); + static const FFIType* get_ffi_type(const TypeHint* type_hint); + static std::string get_ffi_scope(const TypeHint* type_hint); static bool is_ffi_scope_call(VertexAdaptor call); - static void register_builtin_classes(DataStream &os); + static void register_builtin_classes(DataStream& os); - bool register_scope(const std::string &scope_name, FFIScopeDataMixin *data); + bool register_scope(const std::string& scope_name, FFIScopeDataMixin* data); void bind_symbols(); - int get_dynamic_symbols_num() const noexcept { return num_dynamic_symbols; } + int get_dynamic_symbols_num() const noexcept { + return num_dynamic_symbols; + } // produces a name suitable for a C code declaration; // uses a scope_name as a prefix part // // note that not every symbol needs to be mangled - static std::string c_name_mangle(const std::string &scope_name, const std::string name) { + static std::string c_name_mangle(const std::string& scope_name, const std::string name) { return "ffi_" + scope_name + "_" + name; } - static std::string scope_class_name(const std::string &scope_name) { + static std::string scope_class_name(const std::string& scope_name) { return "scope$" + scope_name; } - static std::string cdata_class_name(const std::string &scope_name, const std::string &name) { + static std::string cdata_class_name(const std::string& scope_name, const std::string& name) { return "cdata$" + scope_name + "\\" + name; } private: - enum class Php2cMode { FuncReturn, FieldRead, }; - const TypeHint *c2php_type_hint(const TypeHint *c_type, Php2cMode mode); - const TypeHint *c2php_scalar_type_hint(FFITypeKind kind); + const TypeHint* c2php_type_hint(const TypeHint* c_type, Php2cMode mode); + const TypeHint* c2php_scalar_type_hint(FFITypeKind kind); - const TypeHint *unboxed_type_hint(const FFIType *type, const std::string &scope_name, bool is_return); + const TypeHint* unboxed_type_hint(const FFIType* type, const std::string& scope_name, bool is_return); }; -const FFIBuiltinType *ffi_builtin_type(FFITypeKind); -const FFIBuiltinType *ffi_builtin_type(const std::string &php_class_name); +const FFIBuiltinType* ffi_builtin_type(FFITypeKind); +const FFIBuiltinType* ffi_builtin_type(const std::string& php_class_name); // FFI printing routines: // @@ -167,8 +178,8 @@ const FFIBuiltinType *ffi_builtin_type(const std::string &php_class_name); // // The name mangling is performed by a FFIRoot::c_name_mangle function. -std::string ffi_type_string(const FFIType *type); -std::string ffi_mangled_type_string(const std::string &scope_name, const FFIType *type); -std::string ffi_decltype_string(const FFIType *type); -std::string ffi_mangled_decltype_string(const std::string &scope_name, const FFIType *type); -std::string ffi_mangled_decltype_string(const TypeHint *type_hint); +std::string ffi_type_string(const FFIType* type); +std::string ffi_mangled_type_string(const std::string& scope_name, const FFIType* type); +std::string ffi_decltype_string(const FFIType* type); +std::string ffi_mangled_decltype_string(const std::string& scope_name, const FFIType* type); +std::string ffi_mangled_decltype_string(const TypeHint* type_hint); diff --git a/compiler/data/field-modifiers.h b/compiler/data/field-modifiers.h index 6b1841c1c5..e2fc3f796c 100644 --- a/compiler/data/field-modifiers.h +++ b/compiler/data/field-modifiers.h @@ -12,42 +12,51 @@ class FieldModifiers { public: FieldModifiers() = default; - explicit FieldModifiers(AccessModifiers access_modifiers) : - access_modifier_(access_modifiers) { - } + explicit FieldModifiers(AccessModifiers access_modifiers) + : access_modifier_(access_modifiers) {} - FieldModifiers &set_public() { + FieldModifiers& set_public() { kphp_error(!is_private() && !is_protected(), "Mupliple access modifiers (e.g. public and private at the same time) are not allowed"); access_modifier_ = AccessModifiers::public_; return *this; } - FieldModifiers &set_private() { + FieldModifiers& set_private() { kphp_error(!is_public() && !is_protected(), "Mupliple access modifiers (e.g. public and private at the same time) are not allowed"); access_modifier_ = AccessModifiers::private_; return *this; } - FieldModifiers &set_protected() { + FieldModifiers& set_protected() { kphp_error(!is_private() && !is_public(), "Mupliple access modifiers (e.g. public and private at the same time) are not allowed"); access_modifier_ = AccessModifiers::protected_; return *this; } - bool is_public() const { return access_modifier_ == AccessModifiers::public_; } - bool is_private() const { return access_modifier_ == AccessModifiers::private_; } - bool is_protected() const { return access_modifier_ == AccessModifiers::protected_; } + bool is_public() const { + return access_modifier_ == AccessModifiers::public_; + } + bool is_private() const { + return access_modifier_ == AccessModifiers::private_; + } + bool is_protected() const { + return access_modifier_ == AccessModifiers::protected_; + } std::string to_string() const { switch (access_modifier_) { - case AccessModifiers::public_ : return "public"; - case AccessModifiers::private_ : return "private"; - case AccessModifiers::protected_: return "protected"; - default: return ""; + case AccessModifiers::public_: + return "public"; + case AccessModifiers::private_: + return "private"; + case AccessModifiers::protected_: + return "protected"; + default: + return ""; } } - friend bool operator==(const FieldModifiers &lhs, const FieldModifiers &rhs) { + friend bool operator==(const FieldModifiers& lhs, const FieldModifiers& rhs) { return lhs.access_modifier_ == rhs.access_modifier_; } diff --git a/compiler/data/function-data.cpp b/compiler/data/function-data.cpp index babc7a651c..db22df3055 100644 --- a/compiler/data/function-data.cpp +++ b/compiler/data/function-data.cpp @@ -6,6 +6,7 @@ #include "common/termformat/termformat.h" +#include "common/algorithms/contains.h" #include "compiler/compiler-core.h" #include "compiler/data/class-data.h" #include "compiler/data/generics-mixins.h" @@ -15,7 +16,6 @@ #include "compiler/inferring/public.h" #include "compiler/type-hint.h" #include "compiler/vertex.h" -#include "common/algorithms/contains.h" FunctionPtr FunctionData::create_function(std::string name, VertexAdaptor root, func_type_t type) { static CachedProfiler cache("Create Function"); @@ -32,7 +32,7 @@ FunctionPtr FunctionData::create_function(std::string name, VertexAdaptor root_instead_of_cloning) { +FunctionPtr FunctionData::clone_from(FunctionPtr other, const std::string& new_name, VertexAdaptor root_instead_of_cloning) { FunctionPtr res(new FunctionData(*other)); res->root = root_instead_of_cloning ?: other->root.clone(); res->root->func_id = res; @@ -51,7 +51,8 @@ bool FunctionData::is_constructor() const { } void FunctionData::update_location_in_body() { - if (!root) return; + if (!root) + return; SrcFilePtr file = root->location.file; @@ -69,18 +70,17 @@ std::vector> FunctionData::get_params_as_vector_of_vars(in std::vector> res_params(static_cast(func_params.size() - shift)); std::transform(std::next(func_params.begin(), shift), func_params.end(), res_params.begin(), - [](VertexPtr param) { return param.as()->var().clone(); } - ); + [](VertexPtr param) { return param.as()->var().clone(); }); return res_params; } -void FunctionData::move_virtual_to_self_method(DataStream &os) { +void FunctionData::move_virtual_to_self_method(DataStream& os) { auto v_op_function = VertexAdaptor::create(root->param_list().clone(), root->cmd()); auto self_function = clone_from(get_self(), replace_backslashes(class_id->name) + "$$" + get_name_of_self_method(), v_op_function); self_function->is_virtual_method = false; - class_id->members.add_instance_method(self_function); // don't need a lock here, it's invoked from a sync pipe + class_id->members.add_instance_method(self_function); // don't need a lock here, it's invoked from a sync pipe root->cmd_ref() = VertexAdaptor::create(); G->register_and_require_function(self_function, os, true); @@ -147,18 +147,19 @@ std::string FunctionData::get_throws_call_chain() const { return vk::join(names, " -> ") + (last.get_line() != -1 ? fmt_format(" (line {})", last.get_line()) : ""); } -std::string FunctionData::get_performance_inspections_warning_chain(PerformanceInspections::Inspections inspection, bool search_disabled_inspection) const noexcept { +std::string FunctionData::get_performance_inspections_warning_chain(PerformanceInspections::Inspections inspection, + bool search_disabled_inspection) const noexcept { const auto check_inspection = [search_disabled_inspection, inspection](FunctionPtr f) { - return search_disabled_inspection - ? (f->performance_inspections_for_warning.disabled_inspections() & inspection) - : (f->performance_inspections_for_warning.inspections() & inspection); + return search_disabled_inspection ? (f->performance_inspections_for_warning.disabled_inspections() & inspection) + : (f->performance_inspections_for_warning.inspections() & inspection); }; std::forward_list chain; FunctionPtr fun = get_self(); chain.emplace_front(fun->as_human_readable()); while (!fun->performance_inspections_for_warning.has_their_own_inspections()) { - auto caller_it = std::find_if(fun->performance_inspections_for_warning_parents.begin(), fun->performance_inspections_for_warning_parents.end(), check_inspection); + auto caller_it = + std::find_if(fun->performance_inspections_for_warning_parents.begin(), fun->performance_inspections_for_warning_parents.end(), check_inspection); kphp_assert(caller_it != fun->performance_inspections_for_warning_parents.end()); fun = *caller_it; chain.emplace_front(fun->as_human_readable()); @@ -171,12 +172,8 @@ std::string FunctionData::get_performance_inspections_warning_chain(PerformanceI // we don't want to print something like _explode_nth() instead of expode() // that would be unhelpful for the user static const std::unordered_map internal_function_pretty_names = { - {"_explode_nth", "explode"}, - {"_explode_1", "explode"}, - {"_microtime_float", "microtime"}, - {"_microtime_string", "microtime"}, - {"_hrtime_int", "hrtime"}, - {"_hrtime_array", "hrtime"}, + {"_explode_nth", "explode"}, {"_explode_1", "explode"}, {"_microtime_float", "microtime"}, + {"_microtime_string", "microtime"}, {"_hrtime_int", "hrtime"}, {"_hrtime_array", "hrtime"}, }; std::string FunctionData::as_human_readable(bool add_details) const { @@ -199,10 +196,13 @@ std::string FunctionData::as_human_readable(bool add_details) const { } else if (instantiationTs && outer_function) { result_name = outer_function->as_human_readable(add_details); result_name.erase(result_name.rfind('<')); - result_name += "<" + vk::join(*outer_function->genericTs, ", ", [this](const GenericsDeclarationMixin::GenericsItem &item) { - const TypeHint *itemT = instantiationTs->find(item.nameT); - return itemT == nullptr ? "nullptr" : itemT->as_human_readable(); - }) + ">"; + result_name += "<" + + vk::join(*outer_function->genericTs, ", ", + [this](const GenericsDeclarationMixin::GenericsItem& item) { + const TypeHint* itemT = instantiationTs->find(item.nameT); + return itemT == nullptr ? "nullptr" : itemT->as_human_readable(); + }) + + ">"; if (add_details) { SrcFilePtr file = instantiationTs->location.get_file(); std::string line = std::to_string(instantiationTs->location.line); @@ -216,19 +216,19 @@ std::string FunctionData::as_human_readable(bool add_details) const { // if name is just a function "function_name", doesn't belong to any class if (pos1 == std::string::npos) { if (is_internal) { - const auto &pretty_name = internal_function_pretty_names.find(name); + const auto& pretty_name = internal_function_pretty_names.find(name); result_name = pretty_name != internal_function_pretty_names.end() ? pretty_name->second : name; } else { result_name = name; } } - // if name is "class$$method" + // if name is "class$$method" else if (pos2 == pos1) { std::string base_class = replace_characters(name.substr(0, pos1), '$', '\\'); std::string method_name = name.substr(pos1 + 2); result_name = base_class + "::" + method_name; } - // if name is "class$$method$$context" + // if name is "class$$method$$context" else { std::string base_class = replace_characters(name.substr(0, pos1), '$', '\\'); std::string method_name = name.substr(pos1 + 2, pos2 - pos1 - 2); @@ -254,9 +254,8 @@ bool FunctionData::is_invoke_method() const { vk::string_view FunctionData::get_tmp_string_specialization() const { static std::unordered_map funcs = { - {"substr", "_tmp_substr"}, - {"trim", "_tmp_trim"}, - // TODO: ltrim, rtrim, strstr + {"substr", "_tmp_substr"}, {"trim", "_tmp_trim"}, + // TODO: ltrim, rtrim, strstr }; auto it = funcs.find(name); return it == funcs.end() ? "" : it->second; @@ -271,7 +270,7 @@ VertexAdaptor FunctionData::find_param_by_name(vk::string_view va return {}; } -VertexAdaptor FunctionData::find_use_by_name(const std::string &var_name) { +VertexAdaptor FunctionData::find_use_by_name(const std::string& var_name) { for (auto var_as_use : uses_list) { if (var_as_use->str_val == var_name) { return var_as_use; @@ -280,25 +279,25 @@ VertexAdaptor FunctionData::find_use_by_name(const std::string &var_name return {}; } -VarPtr FunctionData::find_var_by_name(const std::string &var_name) { - auto search_in_vector = [&var_name](const std::vector &lookup_vars_list) -> VarPtr { - auto var_it = std::find_if(lookup_vars_list.begin(), lookup_vars_list.end(), - [&var_name](VarPtr var) { return var->name == var_name; }); +VarPtr FunctionData::find_var_by_name(const std::string& var_name) { + auto search_in_vector = [&var_name](const std::vector& lookup_vars_list) -> VarPtr { + auto var_it = std::find_if(lookup_vars_list.begin(), lookup_vars_list.end(), [&var_name](VarPtr var) { return var->name == var_name; }); return var_it == lookup_vars_list.end() ? VarPtr{} : *var_it; }; - VarPtr found = search_in_vector(local_var_ids); - if (!found) found = search_in_vector(global_var_ids); - if (!found) found = search_in_vector(static_var_ids); - if (!found) found = search_in_vector(param_ids); + VarPtr found = search_in_vector(local_var_ids); + if (!found) + found = search_in_vector(global_var_ids); + if (!found) + found = search_in_vector(static_var_ids); + if (!found) + found = search_in_vector(param_ids); return found ?: VarPtr{}; } bool FunctionData::does_need_codegen() const { - return need_generated_stub || - (type != FunctionData::func_class_holder && - type != FunctionData::func_extern && - (body_seq != body_value::empty || G->get_main_file()->main_function == get_self() || is_lambda())); + return need_generated_stub || (type != FunctionData::func_class_holder && type != FunctionData::func_extern && + (body_seq != body_value::empty || G->get_main_file()->main_function == get_self() || is_lambda())); } bool operator<(FunctionPtr a, FunctionPtr b) { diff --git a/compiler/data/function-data.h b/compiler/data/function-data.h index c8aabc2830..b462798c87 100644 --- a/compiler/data/function-data.h +++ b/compiler/data/function-data.h @@ -29,32 +29,27 @@ class GenericsDeclarationMixin; class KphpTracingDeclarationMixin; class FunctionData { - DEBUG_STRING_METHOD { return as_human_readable(); } - + DEBUG_STRING_METHOD { + return as_human_readable(); + } + // code outside of the data/ should use FunctionData::create_function() FunctionData() = default; - FunctionData& operator=(const FunctionData &other) = default; - FunctionData(const FunctionData &other) = default; + FunctionData& operator=(const FunctionData& other) = default; + FunctionData(const FunctionData& other) = default; public: int id = -1; - std::string name; // full function name; when it belongs to a class, it looks like VK$Namespace$$funcname + std::string name; // full function name; when it belongs to a class, it looks like VK$Namespace$$funcname VertexAdaptor root; bool is_required = false; - enum func_type_t { - func_main, - func_local, - func_lambda, - func_switch, - func_extern, - func_class_holder - }; + enum func_type_t { func_main, func_local, func_lambda, func_switch, func_extern, func_class_holder }; func_type_t type = func_local; std::vector local_var_ids, global_var_ids, static_var_ids, param_ids; - std::unordered_set *bad_vars = nullptr; // for check ub and safe operations wrapper, see comments in check-ub.cpp + std::unordered_set* bad_vars = nullptr; // for check ub and safe operations wrapper, see comments in check-ub.cpp std::set implicit_const_var_ids, explicit_const_var_ids, explicit_header_const_var_ids; std::vector dep; std::set class_dep; @@ -75,16 +70,10 @@ class FunctionData { // to check that a function does not throw, should_not_throw flag is used std::forward_list check_throws; - std::forward_list> assumptions_for_vars; // (var_name, assumption)[] + std::forward_list> assumptions_for_vars; // (var_name, assumption)[] Assumption assumption_for_return; - enum class AssumptionStatus { - uninitialized, - processing_deduce_pass, - done_deduce_pass, - processing_returns_in_body, - done_returns_in_body - }; + enum class AssumptionStatus { uninitialized, processing_deduce_pass, done_deduce_pass, processing_returns_in_body, done_returns_in_body }; vk::copyable_atomic assumption_pass_status{AssumptionStatus::uninitialized}; vk::copyable_atomic assumption_processing_thread{std::thread::id{}}; @@ -100,10 +89,10 @@ class FunctionData { std::set disabled_warnings; std::map name_gen_map; - const TypeHint *return_typehint{nullptr}; - tinf::VarNode tinf_node; // tinf node for return + const TypeHint* return_typehint{nullptr}; + tinf::VarNode tinf_node; // tinf node for return - const PhpDocComment *phpdoc{nullptr}; + const PhpDocComment* phpdoc{nullptr}; // TODO: pack most (all?) bool fields to std::bitset // can save a few bytes per every FunctionData object even if we add more flags later; @@ -125,21 +114,21 @@ class FunctionData { bool is_virtual_method = false; bool is_overridden_method = false; bool is_no_return = false; - bool has_lambdas_inside = false; // used for optimization after cloning (not to launch CloneNestedLambdasPass) - bool has_var_tags_inside = false; // used for optimization (not to traverse body if no @var inside) - bool has_commentTs_inside = false; // used for optimization (not to traverse body if no /*<...>*/ inside) - bool has_global_vars_inside = false; // used for codegeneration; true if function body refs any mutable php globals/superglobals (after cfg pass) + bool has_lambdas_inside = false; // used for optimization after cloning (not to launch CloneNestedLambdasPass) + bool has_var_tags_inside = false; // used for optimization (not to traverse body if no @var inside) + bool has_commentTs_inside = false; // used for optimization (not to traverse body if no /*<...>*/ inside) + bool has_global_vars_inside = false; // used for codegeneration; true if function body refs any mutable php globals/superglobals (after cfg pass) bool warn_unused_result = false; bool is_flatten = false; bool is_pure = false; - bool is_internal = false; // whether this function can be called only when inserted by the compiler - bool is_result_indexing = false; // whether this function implicitly does array indexing inside + bool is_internal = false; // whether this function can be called only when inserted by the compiler + bool is_result_indexing = false; // whether this function implicitly does array indexing inside bool is_result_array2tuple = false; // whether this function result is optimized from array to tuple, and we need to preserve the semantics int8_t readonly_param_index = -1; // until we need more than one, encode it as a byte-sized index - function_palette::ColorContainer colors{}; // colors specified with @kphp-color - std::vector *next_with_colors{nullptr}; // next colored functions reachable via call graph + function_palette::ColorContainer colors{}; // colors specified with @kphp-color + std::vector* next_with_colors{nullptr}; // next colored functions reachable via call graph enum class profiler_status : uint8_t { disable, @@ -157,13 +146,13 @@ class FunctionData { // non-null for generic functions, e.g. f or g // describes what's actually written in @kphp-generic: that f has T, probably with extends_hint - GenericsDeclarationMixin *genericTs{nullptr}; + GenericsDeclarationMixin* genericTs{nullptr}; // non-null for instantiations of generic functions, e.g. f // describes a mapping between generic types (T) and actual instantiation types (User) - GenericsInstantiationMixin *instantiationTs{nullptr}; + GenericsInstantiationMixin* instantiationTs{nullptr}; // non-null for functions marked with @kphp-tracing, contains parsed tag contents - KphpTracingDeclarationMixin *kphp_tracing{nullptr}; + KphpTracingDeclarationMixin* kphp_tracing{nullptr}; ClassPtr class_id; ClassPtr context_class; @@ -176,14 +165,14 @@ class FunctionData { } body_seq = body_value::unknown; static FunctionPtr create_function(std::string name, VertexAdaptor root, func_type_t type); - static FunctionPtr clone_from(FunctionPtr other, const std::string &new_name, VertexAdaptor root_instead_of_cloning = {}); + static FunctionPtr clone_from(FunctionPtr other, const std::string& new_name, VertexAdaptor root_instead_of_cloning = {}); std::string get_resumable_path() const; std::string get_throws_call_chain() const; std::string get_performance_inspections_warning_chain(PerformanceInspections::Inspections inspection, bool search_disabled_inspection = false) const noexcept; std::string as_human_readable(bool add_details = true) const; - bool can_throw() const noexcept { + bool can_throw() const noexcept { return !exceptions_thrown.empty(); } @@ -217,21 +206,23 @@ class FunctionData { vk::string_view get_tmp_string_specialization() const; - const FunctionData *get_this_or_topmost_if_lambda() const { + const FunctionData* get_this_or_topmost_if_lambda() const { return type == FunctionData::func_lambda ? outer_function->get_this_or_topmost_if_lambda() : this; } void update_location_in_body(); std::vector> get_params_as_vector_of_vars(int shift = 0) const; - void move_virtual_to_self_method(DataStream &os); + void move_virtual_to_self_method(DataStream& os); static std::string get_name_of_self_method(vk::string_view name); std::string get_name_of_self_method() const; // a range of op_func_param, but it can't be expressed with VertexRange and needs .as() when using - VertexRange get_params() const { return root->param_list()->params(); } + VertexRange get_params() const { + return root->param_list()->params(); + } - Assumption get_assumption_for_var(const std::string &var_name) { - for (const auto &name_and_a : assumptions_for_vars) { + Assumption get_assumption_for_var(const std::string& var_name) { + for (const auto& name_and_a : assumptions_for_vars) { if (name_and_a.first == var_name) { return name_and_a.second; } @@ -240,17 +231,19 @@ class FunctionData { } VertexAdaptor find_param_by_name(vk::string_view var_name); - VertexAdaptor find_use_by_name(const std::string &var_name); - VarPtr find_var_by_name(const std::string &var_name); + VertexAdaptor find_use_by_name(const std::string& var_name); + VarPtr find_var_by_name(const std::string& var_name); int get_min_argn() const; - vk::string_view local_name() const & { return get_local_name_from_global_$$(name); } - vk::string_view local_name() const && = delete; + vk::string_view local_name() const& { + return get_local_name_from_global_$$(name); + } + vk::string_view local_name() const&& = delete; bool does_need_codegen() const; private: FunctionPtr get_self() const { - return FunctionPtr{const_cast(this)}; + return FunctionPtr{const_cast(this)}; } }; diff --git a/compiler/data/function-modifiers.h b/compiler/data/function-modifiers.h index f2cd78e347..8adf9c41e3 100644 --- a/compiler/data/function-modifiers.h +++ b/compiler/data/function-modifiers.h @@ -14,8 +14,8 @@ class FunctionModifiers { FunctionModifiers() = default; public: - FunctionModifiers(const FunctionModifiers &) = default; - FunctionModifiers& operator=(const FunctionModifiers &) = default; + FunctionModifiers(const FunctionModifiers&) = default; + FunctionModifiers& operator=(const FunctionModifiers&) = default; ~FunctionModifiers() = default; void set_static() { @@ -53,31 +53,57 @@ class FunctionModifiers { abstract_modifier_ = AbstractModifiers::abstract_; } - bool is_static() const { return scope_modifier_ == ScopeModifiers::static_; } - bool is_instance() const { return scope_modifier_ == ScopeModifiers::instance_; } - bool is_nonmember() const { return !is_static() && !is_instance(); } - - bool is_static_lambda() const { return scope_modifier_ == ScopeModifiers::static_lambda_; } + bool is_static() const { + return scope_modifier_ == ScopeModifiers::static_; + } + bool is_instance() const { + return scope_modifier_ == ScopeModifiers::instance_; + } + bool is_nonmember() const { + return !is_static() && !is_instance(); + } - bool is_public() const { return access_modifier_ == AccessModifiers::public_; } - bool is_private() const { return access_modifier_ == AccessModifiers::private_; } - bool is_protected() const { return access_modifier_ == AccessModifiers::protected_; } + bool is_static_lambda() const { + return scope_modifier_ == ScopeModifiers::static_lambda_; + } + + bool is_public() const { + return access_modifier_ == AccessModifiers::public_; + } + bool is_private() const { + return access_modifier_ == AccessModifiers::private_; + } + bool is_protected() const { + return access_modifier_ == AccessModifiers::protected_; + } - bool is_final() const { return abstract_modifier_ == AbstractModifiers::final_; } - bool is_abstract() const { return abstract_modifier_ == AbstractModifiers::abstract_; } + bool is_final() const { + return abstract_modifier_ == AbstractModifiers::final_; + } + bool is_abstract() const { + return abstract_modifier_ == AbstractModifiers::abstract_; + } std::string to_string() const { std::string res; - if (is_final()) res += "final"; - if (is_abstract()) res += "abstract"; - - if (is_public()) res += " public"; - if (is_private()) res += " private"; - if (is_protected()) res += " protected"; - - if (is_static()) res += " static"; - if (is_instance()) res += " instance"; - if (is_nonmember()) res += " nonmember"; + if (is_final()) + res += "final"; + if (is_abstract()) + res += "abstract"; + + if (is_public()) + res += " public"; + if (is_private()) + res += " private"; + if (is_protected()) + res += " protected"; + + if (is_static()) + res += " static"; + if (is_instance()) + res += " instance"; + if (is_nonmember()) + res += " nonmember"; return res; } @@ -113,13 +139,11 @@ class FunctionModifiers { return FunctionModifiers{}; } - friend bool operator==(const FunctionModifiers &lhs, const FunctionModifiers &rhs) { - return lhs.abstract_modifier_ == rhs.abstract_modifier_ && - lhs.scope_modifier_ == rhs.scope_modifier_ && - lhs.access_modifier_ == rhs.access_modifier_; + friend bool operator==(const FunctionModifiers& lhs, const FunctionModifiers& rhs) { + return lhs.abstract_modifier_ == rhs.abstract_modifier_ && lhs.scope_modifier_ == rhs.scope_modifier_ && lhs.access_modifier_ == rhs.access_modifier_; } - friend bool operator!=(const FunctionModifiers &lhs, const FunctionModifiers &rhs) { + friend bool operator!=(const FunctionModifiers& lhs, const FunctionModifiers& rhs) { return !(lhs == rhs); } diff --git a/compiler/data/generics-mixins.cpp b/compiler/data/generics-mixins.cpp index 83d9e74571..5ce256dc3d 100644 --- a/compiler/data/generics-mixins.cpp +++ b/compiler/data/generics-mixins.cpp @@ -60,49 +60,48 @@ * For `f` with T=SomeClass, an instantiated function is named "f$_$SomeClass". */ - // an old syntax has only @kphp-template with $argument inside (or many such tags) -static void create_from_phpdoc_kphp_template_old_syntax(FunctionPtr f, GenericsDeclarationMixin *out, const PhpDocComment *phpdoc) { - for (const PhpDocTag &tag : phpdoc->tags) { +static void create_from_phpdoc_kphp_template_old_syntax(FunctionPtr f, GenericsDeclarationMixin* out, const PhpDocComment* phpdoc) { + for (const PhpDocTag& tag : phpdoc->tags) { switch (tag.type) { - case PhpDocType::kphp_template: { - std::string nameT; // can be before $arg - const TypeHint *extends_hint = nullptr; - for (const auto &var_name : split_skipping_delimeters(tag.value, ", ")) { - if (var_name[0] != '$') { - kphp_error_return(nameT.empty(), "invalid @kphp-template syntax"); - nameT = static_cast(var_name); - continue; - } - if (nameT.empty()) { - nameT = "T" + std::to_string(out->size() + 1); - } - - auto param = f->find_param_by_name(var_name.substr(1)); - kphp_error_return(param, fmt_format("@kphp-template for {} — argument not found", var_name)); - extends_hint = param->type_hint && param->type_hint->try_as() ? param->type_hint : nullptr; - param->type_hint = TypeHintGenericT::create(nameT); + case PhpDocType::kphp_template: { + std::string nameT; // can be before $arg + const TypeHint* extends_hint = nullptr; + for (const auto& var_name : split_skipping_delimeters(tag.value, ", ")) { + if (var_name[0] != '$') { + kphp_error_return(nameT.empty(), "invalid @kphp-template syntax"); + nameT = static_cast(var_name); + continue; + } + if (nameT.empty()) { + nameT = "T" + std::to_string(out->size() + 1); } - kphp_error_return(!nameT.empty(), "invalid @kphp-template syntax"); - out->add_itemT(nameT, extends_hint, nullptr); - break; + auto param = f->find_param_by_name(var_name.substr(1)); + kphp_error_return(param, fmt_format("@kphp-template for {} — argument not found", var_name)); + extends_hint = param->type_hint && param->type_hint->try_as() ? param->type_hint : nullptr; + param->type_hint = TypeHintGenericT::create(nameT); } - case PhpDocType::kphp_param: - kphp_error(0, "@kphp-param is not acceptable with old-style @kphp-template syntax"); - break; + kphp_error_return(!nameT.empty(), "invalid @kphp-template syntax"); + out->add_itemT(nameT, extends_hint, nullptr); + break; + } + + case PhpDocType::kphp_param: + kphp_error(0, "@kphp-param is not acceptable with old-style @kphp-template syntax"); + break; - case PhpDocType::kphp_return: { - kphp_error_return(!out->empty(), "@kphp-template must precede @kphp-return"); - if (auto tag_parsed = tag.value_as_type_and_var_name(f, out)) { - f->return_typehint = tag_parsed.type_hint; // typically, T or T::field - } - break; + case PhpDocType::kphp_return: { + kphp_error_return(!out->empty(), "@kphp-template must precede @kphp-return"); + if (auto tag_parsed = tag.value_as_type_and_var_name(f, out)) { + f->return_typehint = tag_parsed.type_hint; // typically, T or T::field } + break; + } - default: - break; + default: + break; } } @@ -114,76 +113,81 @@ static void create_from_phpdoc_kphp_template_old_syntax(FunctionPtr f, GenericsD // * every T may have def_hint: "T = mixed", "T = \VK\Err" // (if both, it looks like "T: Err = Err") // (@param tags depending on T's are parsed afterward, like regular @param: T will be interpreted as TypeHintGenericT) -static void create_from_phpdoc_kphp_generic_new_syntax(FunctionPtr current_function, GenericsDeclarationMixin *out, const PhpDocComment *phpdoc) { - for (const PhpDocTag &tag : phpdoc->tags) { +static void create_from_phpdoc_kphp_generic_new_syntax(FunctionPtr current_function, GenericsDeclarationMixin* out, const PhpDocComment* phpdoc) { + for (const PhpDocTag& tag : phpdoc->tags) { switch (tag.type) { - case PhpDocType::kphp_generic: - for (auto s : split_skipping_delimeters(tag.value, ",")) { - std::vector tokens = phpdoc_to_tokens(s); - auto cur_tok = tokens.cbegin(); - bool is_variadic = false; - - if (cur_tok->type() == tok_varg) { // not T, but ...T (variadic generic) - is_variadic = true; - cur_tok++; - } - - kphp_error_return(cur_tok->type() != tok_var_name, fmt_format("'@kphp-generic ${}' is an invalid syntax: provide T names, not variables.\nProbably, you want:\n* @kphp-generic T\n* @param T ${}", cur_tok->str_val, cur_tok->str_val)); - kphp_error_return(cur_tok->type() == tok_func_name, fmt_format("Can't parse generic declaration: can't detect T from '{}'", s)); - - std::string nameT = static_cast(cur_tok->str_val); - const TypeHint *extends_hint = nullptr; - const TypeHint *def_hint = nullptr; - + case PhpDocType::kphp_generic: + for (auto s : split_skipping_delimeters(tag.value, ",")) { + std::vector tokens = phpdoc_to_tokens(s); + auto cur_tok = tokens.cbegin(); + bool is_variadic = false; + + if (cur_tok->type() == tok_varg) { // not T, but ...T (variadic generic) + is_variadic = true; cur_tok++; - if (cur_tok->type() == tok_colon) { - PhpDocTypeHintParser parser(current_function, out); - extends_hint = parser.parse_from_tokens_silent(++cur_tok); - kphp_error_return(extends_hint, fmt_format("Can't parse generic declaration <{}> after ':'", nameT)); - // since this is called from gentree, we don't have classes to resolve, so check_declarationT_extends_hint() will be called later - // also, for each call `f()`, we'll check that particular T, see check_reifiedT_extends_hint() - } - if (cur_tok->type() == tok_eq1) { - PhpDocTypeHintParser parser(current_function, out); - def_hint = parser.parse_from_tokens_silent(++cur_tok); - kphp_error_return(def_hint, fmt_format("Can't parse generic declaration <{}> after '='", nameT)); - kphp_error_return(cur_tok->type() != tok_colon, fmt_format("Can't parse generic declaration <{}>: ':' should go before a default value", nameT)); - } - kphp_error_return(cur_tok->type() != tok_func_name, "Can't parse generic declaration: use a comma to separate generic T ('T1, T2' instead of 'T1 T2')"); - kphp_error_return(cur_tok->type() == tok_end, fmt_format("Can't parse generic declaration <{}>: unexpected end", nameT)); - - out->add_itemT(nameT, extends_hint, def_hint, is_variadic); } - break; - case PhpDocType::kphp_param: - kphp_error_return(0, "Don't use @kphp-param with generics, use just @param"); - break; + kphp_error_return( + cur_tok->type() != tok_var_name, + fmt_format("'@kphp-generic ${}' is an invalid syntax: provide T names, not variables.\nProbably, you want:\n* @kphp-generic T\n* @param T ${}", + cur_tok->str_val, cur_tok->str_val)); + kphp_error_return(cur_tok->type() == tok_func_name, fmt_format("Can't parse generic declaration: can't detect T from '{}'", s)); + + std::string nameT = static_cast(cur_tok->str_val); + const TypeHint* extends_hint = nullptr; + const TypeHint* def_hint = nullptr; + + cur_tok++; + if (cur_tok->type() == tok_colon) { + PhpDocTypeHintParser parser(current_function, out); + extends_hint = parser.parse_from_tokens_silent(++cur_tok); + kphp_error_return(extends_hint, fmt_format("Can't parse generic declaration <{}> after ':'", nameT)); + // since this is called from gentree, we don't have classes to resolve, so check_declarationT_extends_hint() will be called later + // also, for each call `f()`, we'll check that particular T, see check_reifiedT_extends_hint() + } + if (cur_tok->type() == tok_eq1) { + PhpDocTypeHintParser parser(current_function, out); + def_hint = parser.parse_from_tokens_silent(++cur_tok); + kphp_error_return(def_hint, fmt_format("Can't parse generic declaration <{}> after '='", nameT)); + kphp_error_return(cur_tok->type() != tok_colon, fmt_format("Can't parse generic declaration <{}>: ':' should go before a default value", nameT)); + } + kphp_error_return(cur_tok->type() != tok_func_name, "Can't parse generic declaration: use a comma to separate generic T ('T1, T2' instead of 'T1 T2')"); + kphp_error_return(cur_tok->type() == tok_end, fmt_format("Can't parse generic declaration <{}>: unexpected end", nameT)); + + out->add_itemT(nameT, extends_hint, def_hint, is_variadic); + } + break; + + case PhpDocType::kphp_param: + kphp_error_return(0, "Don't use @kphp-param with generics, use just @param"); + break; - case PhpDocType::kphp_return: - kphp_error_return(0, "Don't use @kphp-return with generics, use just @return"); - break; + case PhpDocType::kphp_return: + kphp_error_return(0, "Don't use @kphp-return with generics, use just @return"); + break; - default: - break; + default: + break; } } kphp_assert(!out->empty()); } - std::string GenericsDeclarationMixin::as_human_readable() const { - return "<" + vk::join(itemsT, ", ", [](const GenericsItem &itemT) { - if (itemT.is_variadic) { - return "..." + itemT.nameT; - } - return itemT.nameT; - }) + ">"; + return "<" + + vk::join(itemsT, ", ", + [](const GenericsItem& itemT) { + if (itemT.is_variadic) { + return "..." + itemT.nameT; + } + return itemT.nameT; + }) + + ">"; } -bool GenericsDeclarationMixin::has_nameT(const std::string &nameT) const { - for (const GenericsItem &item : itemsT) { +bool GenericsDeclarationMixin::has_nameT(const std::string& nameT) const { + for (const GenericsItem& item : itemsT) { if (item.nameT == nameT) { return true; } @@ -191,15 +195,15 @@ bool GenericsDeclarationMixin::has_nameT(const std::string &nameT) const { return false; } -void GenericsDeclarationMixin::add_itemT(const std::string &nameT, const TypeHint *extends_hint, const TypeHint *def_hint, bool is_variadic) { +void GenericsDeclarationMixin::add_itemT(const std::string& nameT, const TypeHint* extends_hint, const TypeHint* def_hint, bool is_variadic) { kphp_error_return(!nameT.empty(), "Invalid (empty) generic in declaration"); kphp_error_return(!has_nameT(nameT), fmt_format("Duplicate generic <{}> in declaration", nameT)); kphp_error_return(itemsT.empty() || !itemsT.back().is_variadic, fmt_format("Variadic <...{}> is not the last in declaration", itemsT.back().nameT)); itemsT.emplace_back(GenericsItem{nameT, extends_hint, def_hint, is_variadic}); } -const TypeHint *GenericsDeclarationMixin::get_extends_hint(const std::string &nameT) const { - for (const GenericsItem &item : itemsT) { +const TypeHint* GenericsDeclarationMixin::get_extends_hint(const std::string& nameT) const { + for (const GenericsItem& item : itemsT) { if (item.nameT == nameT) { return item.extends_hint; } @@ -210,18 +214,16 @@ const TypeHint *GenericsDeclarationMixin::get_extends_hint(const std::string &na std::string GenericsDeclarationMixin::prompt_provide_commentTs_human_readable(VertexPtr call) const { std::string call_str = replace_call_string_to_readable(call->get_string()); std::string params_str = call->size() > (call->extra_type == op_ex_func_call_arrow ? 1 : 0) ? "(...)" : "()"; - std::string t_str = vk::join(itemsT, ", ", [](const GenericsItem &itemT) { return itemT.nameT; }); + std::string t_str = vk::join(itemsT, ", ", [](const GenericsItem& itemT) { return itemT.nameT; }); return "Please, provide all generic types using syntax " + call_str + "/*<" + t_str + ">*/" + params_str; } - std::string GenericsInstantiationPhpComment::as_human_readable() const { - return "/*<" + vk::join(vectorTs, ", ", [](const TypeHint *instantiationT) { return instantiationT->as_human_readable(); }) + ">*/"; + return "/*<" + vk::join(vectorTs, ", ", [](const TypeHint* instantiationT) { return instantiationT->as_human_readable(); }) + ">*/"; } - -GenericsInstantiationMixin::GenericsInstantiationMixin(const GenericsInstantiationMixin &rhs) { +GenericsInstantiationMixin::GenericsInstantiationMixin(const GenericsInstantiationMixin& rhs) { if (rhs.commentTs != nullptr) { this->commentTs = new GenericsInstantiationPhpComment(*rhs.commentTs); } @@ -229,9 +231,7 @@ GenericsInstantiationMixin::GenericsInstantiationMixin(const GenericsInstantiati std::string GenericsInstantiationMixin::as_human_readable() const { if (!instantiations.empty()) { - return vk::join(instantiations, ", ", [](const auto &pair) { - return pair.first + "=" + pair.second->as_human_readable(); - }); + return vk::join(instantiations, ", ", [](const auto& pair) { return pair.first + "=" + pair.second->as_human_readable(); }); } if (commentTs != nullptr) { @@ -240,56 +240,51 @@ std::string GenericsInstantiationMixin::as_human_readable() const { return "empty"; } -void GenericsInstantiationMixin::provideT(const std::string &nameT, const TypeHint *instantiationT, VertexPtr call) { +void GenericsInstantiationMixin::provideT(const std::string& nameT, const TypeHint* instantiationT, VertexPtr call) { auto insertion_result = instantiations.emplace(nameT, instantiationT); if (!insertion_result.second) { - const TypeHint *previous_inst = insertion_result.first->second; + const TypeHint* previous_inst = insertion_result.first->second; FunctionPtr generic_function = call.as()->func_id; kphp_error(previous_inst == instantiationT, - fmt_format("Couldn't reify generic <{}> for call: it's both {} and {}.\n{}", - nameT, previous_inst->as_human_readable(), instantiationT->as_human_readable(), generic_function->genericTs->prompt_provide_commentTs_human_readable(call))); + fmt_format("Couldn't reify generic <{}> for call: it's both {} and {}.\n{}", nameT, previous_inst->as_human_readable(), + instantiationT->as_human_readable(), generic_function->genericTs->prompt_provide_commentTs_human_readable(call))); } } -const TypeHint *GenericsInstantiationMixin::find(const std::string &nameT) const { +const TypeHint* GenericsInstantiationMixin::find(const std::string& nameT) const { auto it = instantiations.find(nameT); return it == instantiations.end() ? nullptr : it->second; } -std::string GenericsInstantiationMixin::generate_instantiated_name(const std::string &orig_name, const GenericsDeclarationMixin *genericTs) const { +std::string GenericsInstantiationMixin::generate_instantiated_name(const std::string& orig_name, const GenericsDeclarationMixin* genericTs) const { // an instantiated function name will be "{orig_name}$_${postfix}", where postfix = "T1$_$T2" std::string name = orig_name; - for (const auto &itemT : *genericTs) { + for (const auto& itemT : *genericTs) { name += "$_$"; name += replace_non_alphanum(instantiations.find(itemT.nameT)->second->as_human_readable()); } return name; } - // having parsed and resolved 'T: SomeInterface' in @kphp-generic, check that extends_hint -void GenericsDeclarationMixin::check_declarationT_extends_hint(const TypeHint *extends_hint, const std::string &nameT) { +void GenericsDeclarationMixin::check_declarationT_extends_hint(const TypeHint* extends_hint, const std::string& nameT) { // we allow only 'T: SomeClass' / 'T: SomeInterface' and 'T: callable' created implicitly // if an unknown class is specified, an error was printed before (on resolving) - if (!extends_hint || - extends_hint->try_as() || // 'T: callable' is created implicitly for untyped 'callable' params - extends_hint->try_as() || // 'T: object' - extends_hint->try_as() || // 'T: BaseClass' / 'T: SomeInterface' - extends_hint->try_as()) { // 'T: int|string' / 'T: SomeInterface|SomeInterface2' + if (!extends_hint || extends_hint->try_as() || // 'T: callable' is created implicitly for untyped 'callable' params + extends_hint->try_as() || // 'T: object' + extends_hint->try_as() || // 'T: BaseClass' / 'T: SomeInterface' + extends_hint->try_as()) { // 'T: int|string' / 'T: SomeInterface|SomeInterface2' return; } - kphp_error_return(!extends_hint->try_as(), - "A generic T can't extend ?Some or Some|false"); - kphp_error_return(!extends_hint->try_as(), - "A generic T can't extend a primitive, what does it mean?"); - kphp_error_return(!extends_hint->try_as(), - "A generic T can't extend an array; use just T in declaration, and T[] in @param"); + kphp_error_return(!extends_hint->try_as(), "A generic T can't extend ?Some or Some|false"); + kphp_error_return(!extends_hint->try_as(), "A generic T can't extend a primitive, what does it mean?"); + kphp_error_return(!extends_hint->try_as(), "A generic T can't extend an array; use just T in declaration, and T[] in @param"); kphp_error_return(0, fmt_format("Strange or unsupported extends condition in generic T after '{}:'", nameT)); } // having parsed and resolved 'T = Err' in @kphp-generic, check that def_hint -void GenericsDeclarationMixin::check_declarationT_def_hint(const TypeHint *def_hint, const std::string &nameT) { +void GenericsDeclarationMixin::check_declarationT_def_hint(const TypeHint* def_hint, const std::string& nameT) { // we allow anything as a default // if it's 'self', it was already resolved up to this point // we also allow 'T2 = T1' (T1 is TypeHintGenericT) @@ -300,21 +295,21 @@ void GenericsDeclarationMixin::check_declarationT_def_hint(const TypeHint *def_h kphp_error_return(0, fmt_format("Strange or unsupported default type in generic T after '{}='", nameT)); } -bool GenericsDeclarationMixin::is_new_kphp_generic_syntax(const PhpDocComment *phpdoc) { +bool GenericsDeclarationMixin::is_new_kphp_generic_syntax(const PhpDocComment* phpdoc) { // @kphp-generic is a new syntax, @kphp-template is an old one return phpdoc && phpdoc->find_tag(PhpDocType::kphp_generic); } // creates genericTs as an empty object, ready for parsing -GenericsDeclarationMixin *GenericsDeclarationMixin::create_for_function_empty(FunctionPtr f) { - auto *out = new GenericsDeclarationMixin(); - (void)f; // reserved for the future +GenericsDeclarationMixin* GenericsDeclarationMixin::create_for_function_empty(FunctionPtr f) { + auto* out = new GenericsDeclarationMixin(); + (void)f; // reserved for the future return out; } // creates genericTs parsed from @kphp-generic above the function -GenericsDeclarationMixin *GenericsDeclarationMixin::create_for_function_from_phpdoc(FunctionPtr f, const PhpDocComment *phpdoc) { - auto *out = create_for_function_empty(f); +GenericsDeclarationMixin* GenericsDeclarationMixin::create_for_function_from_phpdoc(FunctionPtr f, const PhpDocComment* phpdoc) { + auto* out = create_for_function_empty(f); if (is_new_kphp_generic_syntax(phpdoc)) { create_from_phpdoc_kphp_generic_new_syntax(f, out, phpdoc); @@ -326,10 +321,10 @@ GenericsDeclarationMixin *GenericsDeclarationMixin::create_for_function_from_php } // creates genericTs as a clone from generic_f->genericTs, replacing "...TArgs" with "TArg1, TArg2" (for N=2 here) -GenericsDeclarationMixin *GenericsDeclarationMixin::create_for_function_cloning_from_variadic(FunctionPtr generic_f, int n_variadic) { - auto *out = create_for_function_empty(generic_f); +GenericsDeclarationMixin* GenericsDeclarationMixin::create_for_function_cloning_from_variadic(FunctionPtr generic_f, int n_variadic) { + auto* out = create_for_function_empty(generic_f); - for (const auto &itemT : *generic_f->genericTs) { + for (const auto& itemT : *generic_f->genericTs) { if (itemT.is_variadic) { for (int i = 1; i <= n_variadic; ++i) { auto ith_nameT = itemT.nameT + std::to_string(i); @@ -355,11 +350,10 @@ void GenericsDeclarationMixin::make_function_generic_on_callable_arg(FunctionPtr // function f(callable $cb) { ... } // f('some_fn'); // even if f() is called with a string, it should be instantiated as f, not f - const TypeHint *extends_hint_callable = TypeHintCallable::create_untyped_callable(); + const TypeHint* extends_hint_callable = TypeHintCallable::create_untyped_callable(); f->genericTs->add_itemT(nameT, extends_hint_callable, nullptr); } - void GenericsDeclarationMixin::make_function_generic_on_object_arg(FunctionPtr f, VertexPtr func_param) { if (!f->genericTs) { f->genericTs = GenericsDeclarationMixin::create_for_function_empty(f); diff --git a/compiler/data/generics-mixins.h b/compiler/data/generics-mixins.h index 0b26fbbece..9840ac2844 100644 --- a/compiler/data/generics-mixins.h +++ b/compiler/data/generics-mixins.h @@ -4,98 +4,123 @@ #pragma once -#include -#include #include +#include +#include +#include "common/wrappers/string_view.h" #include "compiler/data/data_ptr.h" #include "compiler/data/vertex-adaptor.h" #include "compiler/debug.h" -#include "common/wrappers/string_view.h" // see the .cpp file for detailed comments of how do generics work // when we have `f`, then f->genericTs is an instance of this class, itemsT = [ {nameT = T1}, {nameT = T2} ] // syntactically, such functions are declared with @kphp-generic, parsed in gentree class GenericsDeclarationMixin { - DEBUG_STRING_METHOD { return as_human_readable(); } + DEBUG_STRING_METHOD { + return as_human_readable(); + } GenericsDeclarationMixin() = default; public: - struct GenericsItem { std::string nameT; - const TypeHint *extends_hint; // in @kphp-generic, it goes after ':', e.g. T1:SomeInterface - const TypeHint *def_hint; // in @kphp-generic, it goes after '=', e.g. T2=Err - bool is_variadic{false}; // in @kphp-generic, it's declared as ...T, not T + const TypeHint* extends_hint; // in @kphp-generic, it goes after ':', e.g. T1:SomeInterface + const TypeHint* def_hint; // in @kphp-generic, it goes after '=', e.g. T2=Err + bool is_variadic{false}; // in @kphp-generic, it's declared as ...T, not T }; std::vector itemsT; std::string as_human_readable() const; - bool empty() const { return itemsT.empty(); } - size_t size() const { return itemsT.size(); } - auto begin() const { return itemsT.begin(); } - auto end() const { return itemsT.end(); } - bool is_variadic() const { return !itemsT.empty() && itemsT.back().is_variadic; } - - bool has_nameT(const std::string &nameT) const; - void add_itemT(const std::string &nameT, const TypeHint *extends_hint, const TypeHint *def_hint, bool is_variadic = false); - const TypeHint *get_extends_hint(const std::string &nameT) const; + bool empty() const { + return itemsT.empty(); + } + size_t size() const { + return itemsT.size(); + } + auto begin() const { + return itemsT.begin(); + } + auto end() const { + return itemsT.end(); + } + bool is_variadic() const { + return !itemsT.empty() && itemsT.back().is_variadic; + } + + bool has_nameT(const std::string& nameT) const; + void add_itemT(const std::string& nameT, const TypeHint* extends_hint, const TypeHint* def_hint, bool is_variadic = false); + const TypeHint* get_extends_hint(const std::string& nameT) const; std::string prompt_provide_commentTs_human_readable(VertexPtr call) const; - static void check_declarationT_extends_hint(const TypeHint *extends_hint, const std::string &nameT); - static void check_declarationT_def_hint(const TypeHint *def_hint, const std::string &nameT); - static bool is_new_kphp_generic_syntax(const PhpDocComment *phpdoc); + static void check_declarationT_extends_hint(const TypeHint* extends_hint, const std::string& nameT); + static void check_declarationT_def_hint(const TypeHint* def_hint, const std::string& nameT); + static bool is_new_kphp_generic_syntax(const PhpDocComment* phpdoc); static void make_function_generic_on_callable_arg(FunctionPtr f, VertexPtr func_param); static void make_function_generic_on_object_arg(FunctionPtr f, VertexPtr func_param); - static GenericsDeclarationMixin *create_for_function_empty(FunctionPtr f); - static GenericsDeclarationMixin *create_for_function_from_phpdoc(FunctionPtr f, const PhpDocComment *phpdoc); - static GenericsDeclarationMixin *create_for_function_cloning_from_variadic(FunctionPtr generic_f, int n_variadic); + static GenericsDeclarationMixin* create_for_function_empty(FunctionPtr f); + static GenericsDeclarationMixin* create_for_function_from_phpdoc(FunctionPtr f, const PhpDocComment* phpdoc); + static GenericsDeclarationMixin* create_for_function_cloning_from_variadic(FunctionPtr generic_f, int n_variadic); }; // we have a special syntax in PHP to explicitly provide generic types inside a PHP comment: `f/**/(...)` // at the moment of parsing (in gentree), we store only vector of T until it's matched with real `f` class GenericsInstantiationPhpComment { - DEBUG_STRING_METHOD { return as_human_readable(); } + DEBUG_STRING_METHOD { + return as_human_readable(); + } public: - std::vector vectorTs; + std::vector vectorTs; - explicit GenericsInstantiationPhpComment(std::vector vectorTs) - : vectorTs(std::move(vectorTs)) {} + explicit GenericsInstantiationPhpComment(std::vector vectorTs) + : vectorTs(std::move(vectorTs)) {} std::string as_human_readable() const; - size_t size() const { return vectorTs.size(); } + size_t size() const { + return vectorTs.size(); + } }; // when we have `f` and a call `f($o1,$o2)`, then it has call->reifiedTs set class GenericsInstantiationMixin { - DEBUG_STRING_METHOD { return as_human_readable(); } + DEBUG_STRING_METHOD { + return as_human_readable(); + } public: - GenericsInstantiationPhpComment *commentTs{nullptr}; // non-null if created in gentree from /*<...>*/ syntax - std::map instantiations; // {"T1": SomeClass, "T2": int[], ...} - Location location; // from where this instance of a generic function is instantiated + GenericsInstantiationPhpComment* commentTs{nullptr}; // non-null if created in gentree from /*<...>*/ syntax + std::map instantiations; // {"T1": SomeClass, "T2": int[], ...} + Location location; // from where this instance of a generic function is instantiated explicit GenericsInstantiationMixin(Location location) - : location(std::move(location)) {} - GenericsInstantiationMixin(const GenericsInstantiationMixin &rhs); + : location(std::move(location)) {} + GenericsInstantiationMixin(const GenericsInstantiationMixin& rhs); std::string as_human_readable() const; - void provideT(const std::string &nameT, const TypeHint *instantiationT, VertexPtr call); - const TypeHint *find(const std::string &nameT) const; + void provideT(const std::string& nameT, const TypeHint* instantiationT, VertexPtr call); + const TypeHint* find(const std::string& nameT) const; // generates a name like "f$_${T1}$_${T2}" - std::string generate_instantiated_name(const std::string &orig_name, const GenericsDeclarationMixin *genericTs) const; - - size_t size() const { return instantiations.size(); } - bool empty() const { return instantiations.empty(); } - auto begin() const { return instantiations.begin(); } - auto end() const { return instantiations.end(); } + std::string generate_instantiated_name(const std::string& orig_name, const GenericsDeclarationMixin* genericTs) const; + + size_t size() const { + return instantiations.size(); + } + bool empty() const { + return instantiations.empty(); + } + auto begin() const { + return instantiations.begin(); + } + auto end() const { + return instantiations.end(); + } }; diff --git a/compiler/data/kphp-json-tags.cpp b/compiler/data/kphp-json-tags.cpp index 6d5d02244f..33adde89de 100644 --- a/compiler/data/kphp-json-tags.cpp +++ b/compiler/data/kphp-json-tags.cpp @@ -36,12 +36,12 @@ namespace kphp_json { struct KnownJsonAttr { JsonAttrType type; int attr_strlen; - const char *attr_name; + const char* attr_name; - constexpr KnownJsonAttr(const char *attr_name, JsonAttrType type) - : type(type) - , attr_strlen(__builtin_strlen(attr_name)) - , attr_name(attr_name) {} + constexpr KnownJsonAttr(const char* attr_name, JsonAttrType type) + : type(type), + attr_strlen(__builtin_strlen(attr_name)), + attr_name(attr_name) {} }; class AllJsonAttrs { @@ -50,7 +50,7 @@ class AllJsonAttrs { public: [[gnu::always_inline]] static JsonAttrType name2type(vk::string_view name) { - for (const KnownJsonAttr &attr : ALL_ATTRS) { + for (const KnownJsonAttr& attr : ALL_ATTRS) { if (attr.attr_strlen == name.size() && !strncmp(name.data(), attr.attr_name, name.size())) { return attr.type; } @@ -58,8 +58,8 @@ class AllJsonAttrs { return JsonAttrType::json_attr_unknown; } - [[gnu::noinline]] static const char *type2name(JsonAttrType type) { - for (const KnownJsonAttr &tag : ALL_ATTRS) { + [[gnu::noinline]] static const char* type2name(JsonAttrType type) { + for (const KnownJsonAttr& tag : ALL_ATTRS) { if (tag.type == type) { return tag.attr_name; } @@ -69,44 +69,30 @@ class AllJsonAttrs { }; const KnownJsonAttr AllJsonAttrs::ALL_ATTRS[] = { - KnownJsonAttr("rename", json_attr_rename), - KnownJsonAttr("skip", json_attr_skip), - KnownJsonAttr("array_as_hashmap", json_attr_array_as_hashmap), - KnownJsonAttr("raw_string", json_attr_raw_string), - KnownJsonAttr("required", json_attr_required), - KnownJsonAttr("float_precision", json_attr_float_precision), - KnownJsonAttr("skip_if_default", json_attr_skip_if_default), - KnownJsonAttr("visibility_policy", json_attr_visibility_policy), - KnownJsonAttr("rename_policy", json_attr_rename_policy), - KnownJsonAttr("flatten", json_attr_flatten), - KnownJsonAttr("fields", json_attr_fields), + KnownJsonAttr("rename", json_attr_rename), + KnownJsonAttr("skip", json_attr_skip), + KnownJsonAttr("array_as_hashmap", json_attr_array_as_hashmap), + KnownJsonAttr("raw_string", json_attr_raw_string), + KnownJsonAttr("required", json_attr_required), + KnownJsonAttr("float_precision", json_attr_float_precision), + KnownJsonAttr("skip_if_default", json_attr_skip_if_default), + KnownJsonAttr("visibility_policy", json_attr_visibility_policy), + KnownJsonAttr("rename_policy", json_attr_rename_policy), + KnownJsonAttr("flatten", json_attr_flatten), + KnownJsonAttr("fields", json_attr_fields), }; -static constexpr int ATTRS_ALLOWED_FOR_FIELD = - json_attr_rename | - json_attr_skip | - json_attr_array_as_hashmap | - json_attr_raw_string | - json_attr_required | - json_attr_float_precision | - json_attr_skip_if_default | - 0; +static constexpr int ATTRS_ALLOWED_FOR_FIELD = json_attr_rename | json_attr_skip | json_attr_array_as_hashmap | json_attr_raw_string | json_attr_required | + json_attr_float_precision | json_attr_skip_if_default | 0; static constexpr int ATTRS_ALLOWED_FOR_CLASS = - json_attr_float_precision | - json_attr_skip_if_default | - json_attr_visibility_policy | - json_attr_rename_policy | - json_attr_flatten | - json_attr_fields | - 0; + json_attr_float_precision | json_attr_skip_if_default | json_attr_visibility_policy | json_attr_rename_policy | json_attr_flatten | json_attr_fields | 0; - -static bool does_type_hint_allow_null(const TypeHint *type_hint) noexcept { - if (const auto *as_optional = type_hint->try_as()) { +static bool does_type_hint_allow_null(const TypeHint* type_hint) noexcept { + if (const auto* as_optional = type_hint->try_as()) { return as_optional->or_null; - } else if (const auto *as_pipe = type_hint->try_as()) { + } else if (const auto* as_pipe = type_hint->try_as()) { return vk::any_of(as_pipe->items, does_type_hint_allow_null); - } else if (const auto *as_primitive = type_hint->try_as()) { + } else if (const auto* as_primitive = type_hint->try_as()) { return vk::any_of_equal(as_primitive->ptype, tp_Null, tp_mixed, tp_any); } @@ -116,7 +102,7 @@ static bool does_type_hint_allow_null(const TypeHint *type_hint) noexcept { // @kphp-json can be prefixed with 'for': `@kphp-json for MyJsonEncoder attr = value` // here we extract this MyJsonEncoder, resolving uses and leaving a pointer after it into str -static ClassPtr extract_for_encoder_from_kphp_json_tag(FunctionPtr resolve_context, vk::string_view &str) { +static ClassPtr extract_for_encoder_from_kphp_json_tag(FunctionPtr resolve_context, vk::string_view& str) { kphp_assert(str.starts_with("for ")); str = vk::trim(str.substr(4)); @@ -138,8 +124,7 @@ static RenamePolicy parse_rename_policy(vk::string_view rhs) noexcept { if (rhs == "camelCase") { return RenamePolicy::camel_case; } - kphp_error(rhs == "none", - fmt_format("@kphp-json '{}' should be none|snake_case|camelCase, got '{}'", AllJsonAttrs::type2name(json_attr_rename_policy), rhs)); + kphp_error(rhs == "none", fmt_format("@kphp-json '{}' should be none|snake_case|camelCase, got '{}'", AllJsonAttrs::type2name(json_attr_rename_policy), rhs)); return RenamePolicy::none; } @@ -147,8 +132,7 @@ static VisibilityPolicy parse_visibility_policy(vk::string_view rhs) noexcept { if (rhs == "all") { return VisibilityPolicy::all; } - kphp_error(rhs == "public", - fmt_format("@kphp-json '{}' should be all|public, got '{}'", AllJsonAttrs::type2name(json_attr_visibility_policy), rhs)); + kphp_error(rhs == "public", fmt_format("@kphp-json '{}' should be all|public, got '{}'", AllJsonAttrs::type2name(json_attr_visibility_policy), rhs)); return VisibilityPolicy::public_only; } @@ -178,8 +162,8 @@ static SkipFieldType parse_skip(vk::string_view rhs) noexcept { static vk::string_view parse_fields_delimited_by_comma(vk::string_view rhs) noexcept { // convert "$id, $age" to ",id,age," for fast later search of substr ",{name}," std::unordered_set names_hashes; - auto *fields_delim = new std::string(","); - for (const auto &field_name : split_skipping_delimeters(rhs, "$, ")) { + auto* fields_delim = new std::string(","); + for (const auto& field_name : split_skipping_delimeters(rhs, "$, ")) { *fields_delim += field_name; *fields_delim += ','; kphp_error(names_hashes.insert(vk::std_hash(field_name)).second, @@ -192,8 +176,7 @@ static bool parse_bool_or_true_if_nothing(JsonAttrType attr_type, vk::string_vie if (rhs.empty() || rhs == "true" || rhs == "1") { return true; } - kphp_error(rhs == "false" || rhs == "0", - fmt_format("@kphp-json '{}' should be empty or true|false, got '{}'", AllJsonAttrs::type2name(attr_type), rhs)); + kphp_error(rhs == "false" || rhs == "0", fmt_format("@kphp-json '{}' should be empty or true|false, got '{}'", AllJsonAttrs::type2name(attr_type), rhs)); return false; } @@ -214,121 +197,123 @@ static KphpJsonTag parse_kphp_json_tag(FunctionPtr resolve_context, vk::string_v KphpJsonTag json_tag{.attr_type = attr_type, .for_encoder = for_encoder, .rename = {}}; // initialize union by 0 switch (attr_type) { - case json_attr_rename: - kphp_error_act(!rhs.empty(), "@kphp-json 'rename' expected to have a value after '='", break); - json_tag.rename = parse_rename(rhs); - break; - case json_attr_skip: - json_tag.skip = parse_skip(rhs); - break; - case json_attr_array_as_hashmap: - json_tag.array_as_hashmap = parse_bool_or_true_if_nothing(attr_type, rhs); - break; - case json_attr_raw_string: - json_tag.raw_string = parse_bool_or_true_if_nothing(attr_type, rhs); - break; - case json_attr_required: - json_tag.required = parse_bool_or_true_if_nothing(attr_type, rhs); - break; - case json_attr_float_precision: - kphp_error_act(!rhs.empty(), "@kphp-json 'float_precision' expected to have a value after '='", break); - json_tag.float_precision = parse_float_precision(rhs); - break; - case json_attr_skip_if_default: - json_tag.skip_if_default = parse_bool_or_true_if_nothing(attr_type, rhs); - break; - case json_attr_visibility_policy: - kphp_error_act(!rhs.empty(), "@kphp-json 'visibility_policy' expected to have a value after '='", break); - json_tag.visibility_policy = parse_visibility_policy(rhs); - break; - case json_attr_rename_policy: - kphp_error_act(!rhs.empty(), "@kphp-json 'rename_policy' expected to have a value after '='", break); - json_tag.rename_policy = parse_rename_policy(rhs); - break; - case json_attr_flatten: - json_tag.flatten = parse_bool_or_true_if_nothing(attr_type, rhs); - break; - case json_attr_fields: - kphp_error_act(!rhs.empty(), "@kphp-json 'fields' expected to have a value after '='", break); - json_tag.fields = parse_fields_delimited_by_comma(rhs); - break; - case json_attr_unknown: - default: - kphp_error(0, fmt_format("Unknown @kphp-json attribute '{}'", attr_name)); - break; + case json_attr_rename: + kphp_error_act(!rhs.empty(), "@kphp-json 'rename' expected to have a value after '='", break); + json_tag.rename = parse_rename(rhs); + break; + case json_attr_skip: + json_tag.skip = parse_skip(rhs); + break; + case json_attr_array_as_hashmap: + json_tag.array_as_hashmap = parse_bool_or_true_if_nothing(attr_type, rhs); + break; + case json_attr_raw_string: + json_tag.raw_string = parse_bool_or_true_if_nothing(attr_type, rhs); + break; + case json_attr_required: + json_tag.required = parse_bool_or_true_if_nothing(attr_type, rhs); + break; + case json_attr_float_precision: + kphp_error_act(!rhs.empty(), "@kphp-json 'float_precision' expected to have a value after '='", break); + json_tag.float_precision = parse_float_precision(rhs); + break; + case json_attr_skip_if_default: + json_tag.skip_if_default = parse_bool_or_true_if_nothing(attr_type, rhs); + break; + case json_attr_visibility_policy: + kphp_error_act(!rhs.empty(), "@kphp-json 'visibility_policy' expected to have a value after '='", break); + json_tag.visibility_policy = parse_visibility_policy(rhs); + break; + case json_attr_rename_policy: + kphp_error_act(!rhs.empty(), "@kphp-json 'rename_policy' expected to have a value after '='", break); + json_tag.rename_policy = parse_rename_policy(rhs); + break; + case json_attr_flatten: + json_tag.flatten = parse_bool_or_true_if_nothing(attr_type, rhs); + break; + case json_attr_fields: + kphp_error_act(!rhs.empty(), "@kphp-json 'fields' expected to have a value after '='", break); + json_tag.fields = parse_fields_delimited_by_comma(rhs); + break; + case json_attr_unknown: + default: + kphp_error(0, fmt_format("Unknown @kphp-json attribute '{}'", attr_name)); + break; } return json_tag; } - -void KphpJsonTagList::add_tag(const KphpJsonTag &json_tag) { +void KphpJsonTagList::add_tag(const KphpJsonTag& json_tag) { // when adding, check for duplicates // if both 'for' and no-'for' for the same attr exist, 'for' must be placed below: it allows linear pattern matching - for (const KphpJsonTag &existing : tags) { + for (const KphpJsonTag& existing : tags) { if (existing.attr_type == json_tag.attr_type) { if (existing.for_encoder == json_tag.for_encoder) { kphp_error(existing.for_encoder, fmt_format("@kphp-json '{}' is duplicated", AllJsonAttrs::type2name(json_tag.attr_type))); - kphp_error(!existing.for_encoder, fmt_format("@kphp-json for {} '{}' is duplicated", existing.for_encoder->as_human_readable(), AllJsonAttrs::type2name(json_tag.attr_type))); + kphp_error(!existing.for_encoder, + fmt_format("@kphp-json for {} '{}' is duplicated", existing.for_encoder->as_human_readable(), AllJsonAttrs::type2name(json_tag.attr_type))); } else if (existing.for_encoder) { - kphp_error(json_tag.for_encoder, fmt_format("@kphp-json for {} '{}' should be placed below @kphp-json '{}' without for", existing.for_encoder->as_human_readable(), AllJsonAttrs::type2name(json_tag.attr_type), AllJsonAttrs::type2name(json_tag.attr_type))); + kphp_error(json_tag.for_encoder, + fmt_format("@kphp-json for {} '{}' should be placed below @kphp-json '{}' without for", existing.for_encoder->as_human_readable(), + AllJsonAttrs::type2name(json_tag.attr_type), AllJsonAttrs::type2name(json_tag.attr_type))); } } } - + tags.emplace_back(json_tag); } void KphpJsonTagList::validate_tags_compatibility(ClassPtr above_class) const { unsigned int existing_mask = 0; - for (const KphpJsonTag &tag : tags) { + for (const KphpJsonTag& tag : tags) { existing_mask |= tag.attr_type; } - for (const KphpJsonTag &tag : tags) { + for (const KphpJsonTag& tag : tags) { switch (tag.attr_type) { - case json_attr_flatten: - if (tag.flatten) { - constexpr unsigned int disallowed_over_class = json_attr_rename_policy | json_attr_visibility_policy | json_attr_skip_if_default | json_attr_fields; - kphp_error((disallowed_over_class & existing_mask) == 0, "@kphp-json 'flatten' can't be used with some other @kphp-json tags"); - kphp_error(!tag.for_encoder, "@kphp-json 'flatten' can't be used with 'for', it's a global state"); - } - break; - case json_attr_fields: - if (above_class) { - for (const auto &field_name : split_skipping_delimeters(tag.fields, ",")) { - kphp_error(above_class->members.has_field(field_name), fmt_format("@kphp-json 'fields' specifies '{}', but such field doesn't exist in class {}", field_name, above_class->as_human_readable())); - } + case json_attr_flatten: + if (tag.flatten) { + constexpr unsigned int disallowed_over_class = json_attr_rename_policy | json_attr_visibility_policy | json_attr_skip_if_default | json_attr_fields; + kphp_error((disallowed_over_class & existing_mask) == 0, "@kphp-json 'flatten' can't be used with some other @kphp-json tags"); + kphp_error(!tag.for_encoder, "@kphp-json 'flatten' can't be used with 'for', it's a global state"); + } + break; + case json_attr_fields: + if (above_class) { + for (const auto& field_name : split_skipping_delimeters(tag.fields, ",")) { + kphp_error(above_class->members.has_field(field_name), + fmt_format("@kphp-json 'fields' specifies '{}', but such field doesn't exist in class {}", field_name, above_class->as_human_readable())); } - default: - break; + } + default: + break; } } } void KphpJsonTagList::check_flatten_class(ClassPtr flatten_class) const { int members_count = 0; - flatten_class->members.for_each([&members_count](const ClassMemberInstanceField &f) { + flatten_class->members.for_each([&members_count](const ClassMemberInstanceField& f) { members_count++; if (f.kphp_json_tags) { constexpr unsigned int disallowed_over_field = json_attr_rename | json_attr_skip | json_attr_required | json_attr_skip_if_default; - for (const KphpJsonTag &f_tag : *f.kphp_json_tags) { + for (const KphpJsonTag& f_tag : *f.kphp_json_tags) { kphp_error((disallowed_over_field & f_tag.attr_type) == 0, fmt_format("@kphp-json '{}' over a field is disallowed for flatten classes", AllJsonAttrs::type2name(f_tag.attr_type))); } } }); - kphp_error(members_count == 1, - "@kphp-json 'flatten' class must have exactly one field"); + kphp_error(members_count == 1, "@kphp-json 'flatten' class must have exactly one field"); kphp_error(!flatten_class->parent_class && flatten_class->derived_classes.empty(), "@kphp-json 'flatten' class can not extend anything or have derived classes"); } -const KphpJsonTagList *KphpJsonTagList::create_from_phpdoc(FunctionPtr resolve_context, const PhpDocComment *phpdoc, ClassPtr above_class) { - auto *list = new KphpJsonTagList; +const KphpJsonTagList* KphpJsonTagList::create_from_phpdoc(FunctionPtr resolve_context, const PhpDocComment* phpdoc, ClassPtr above_class) { + auto* list = new KphpJsonTagList; - for (const PhpDocTag &tag : phpdoc->tags) { + for (const PhpDocTag& tag : phpdoc->tags) { if (tag.type == PhpDocType::kphp_json) { KphpJsonTag json_tag = parse_kphp_json_tag(resolve_context, vk::trim(tag.value)); if (json_tag.attr_type == json_attr_unknown) { @@ -350,23 +335,22 @@ const KphpJsonTagList *KphpJsonTagList::create_from_phpdoc(FunctionPtr resolve_c return list; } - std::string transform_json_name_to(RenamePolicy policy, vk::string_view name) noexcept { switch (policy) { - case RenamePolicy::snake_case: - return transform_to_snake_case(name); - case RenamePolicy::camel_case: - return transform_to_camel_case(name); - default: - return std::string{name}; + case RenamePolicy::snake_case: + return transform_to_snake_case(name); + case RenamePolicy::camel_case: + return transform_to_camel_case(name); + default: + return std::string{name}; } } // a PHP class JsonEncoder (and its custom inheritors) have `const visibility_policy` and others // their values have exactly the same format as could be written in @kphp-json above jsonable classes // this function converts constants (all of them surely exist) into the same structure -const KphpJsonTagList *convert_encoder_constants_to_tags(ClassPtr json_encoder) { - auto *contants_as_tags = new KphpJsonTagList; +const KphpJsonTagList* convert_encoder_constants_to_tags(ClassPtr json_encoder) { + auto* contants_as_tags = new KphpJsonTagList; KphpJsonTag from_const{.attr_type = json_attr_unknown, .for_encoder = ClassPtr{}}; std::string s_const; VertexPtr v_const; @@ -398,7 +382,7 @@ const KphpJsonTagList *convert_encoder_constants_to_tags(ClassPtr json_encoder) return contants_as_tags; } -FieldJsonSettings merge_and_inherit_json_tags(const ClassMemberInstanceField &field, ClassPtr klass, ClassPtr json_encoder) { +FieldJsonSettings merge_and_inherit_json_tags(const ClassMemberInstanceField& field, ClassPtr klass, ClassPtr json_encoder) { FieldJsonSettings s; // for 'public int $id;' — no default and non-nullable type — set 'required' so that decode() would fire unless exists @@ -408,93 +392,93 @@ FieldJsonSettings merge_and_inherit_json_tags(const ClassMemberInstanceField &fi } // loop over constants in encoder that can be overridden by a class - for (const KphpJsonTag &encoder_const : *json_encoder->kphp_json_tags) { - const KphpJsonTag *override_klass_tag{nullptr}; + for (const KphpJsonTag& encoder_const : *json_encoder->kphp_json_tags) { + const KphpJsonTag* override_klass_tag{nullptr}; if (klass->kphp_json_tags) { - override_klass_tag = klass->kphp_json_tags->find_tag([encoder_const, json_encoder](const KphpJsonTag &tag){ + override_klass_tag = klass->kphp_json_tags->find_tag([encoder_const, json_encoder](const KphpJsonTag& tag) { return tag.attr_type == encoder_const.attr_type && (!tag.for_encoder || tag.for_encoder == json_encoder); }); } - const KphpJsonTag *tag = override_klass_tag ?: &encoder_const; + const KphpJsonTag* tag = override_klass_tag ?: &encoder_const; switch (tag->attr_type) { - case json_attr_rename_policy: - s.json_key = transform_json_name_to(tag->rename_policy, field.local_name()); - break; - case json_attr_skip_if_default: - s.skip_if_default = tag->skip_if_default; - break; - case json_attr_float_precision: - s.float_precision = tag->float_precision; - break; - case json_attr_visibility_policy: { - bool skip_unless_changed_below = tag->visibility_policy == VisibilityPolicy::all ? false : !field.modifiers.is_public(); - s.skip_when_encoding = skip_unless_changed_below; - s.skip_when_decoding = skip_unless_changed_below; - break; - } - default: - kphp_assert(0 && "unexpected json attr_type in class/encoder codegen"); + case json_attr_rename_policy: + s.json_key = transform_json_name_to(tag->rename_policy, field.local_name()); + break; + case json_attr_skip_if_default: + s.skip_if_default = tag->skip_if_default; + break; + case json_attr_float_precision: + s.float_precision = tag->float_precision; + break; + case json_attr_visibility_policy: { + bool skip_unless_changed_below = tag->visibility_policy == VisibilityPolicy::all ? false : !field.modifiers.is_public(); + s.skip_when_encoding = skip_unless_changed_below; + s.skip_when_decoding = skip_unless_changed_below; + break; + } + default: + kphp_assert(0 && "unexpected json attr_type in class/encoder codegen"); } } // loop over attrs that can be only above class if (klass->kphp_json_tags) { - for (const KphpJsonTag &klass_tag : *klass->kphp_json_tags) { + for (const KphpJsonTag& klass_tag : *klass->kphp_json_tags) { if (klass_tag.for_encoder && klass_tag.for_encoder != json_encoder) { continue; } switch (klass_tag.attr_type) { - case json_attr_flatten: - s.skip_if_default = false; - s.skip_when_encoding = false; - s.skip_when_decoding = false; - break; - case json_attr_fields: { - bool skip_unless_changed_below = klass_tag.fields.find("," + field.local_name() + ",") == std::string::npos; - s.skip_when_encoding = skip_unless_changed_below; - s.skip_when_decoding = skip_unless_changed_below; - break; - } - default: - break; + case json_attr_flatten: + s.skip_if_default = false; + s.skip_when_encoding = false; + s.skip_when_decoding = false; + break; + case json_attr_fields: { + bool skip_unless_changed_below = klass_tag.fields.find("," + field.local_name() + ",") == std::string::npos; + s.skip_when_encoding = skip_unless_changed_below; + s.skip_when_decoding = skip_unless_changed_below; + break; + } + default: + break; } } } // loop over attrs above field: they override class/encoder if (field.kphp_json_tags) { - for (const KphpJsonTag &tag : *field.kphp_json_tags) { + for (const KphpJsonTag& tag : *field.kphp_json_tags) { if (tag.for_encoder && tag.for_encoder != json_encoder) { continue; } switch (tag.attr_type) { - case json_attr_rename: - s.json_key = static_cast(tag.rename); - break; - case json_attr_skip: - s.skip_when_decoding = tag.skip == SkipFieldType::skip_decode_only || tag.skip == SkipFieldType::always_skip; - s.skip_when_encoding = tag.skip == SkipFieldType::skip_encode_only || tag.skip == SkipFieldType::always_skip; - break; - case json_attr_array_as_hashmap: - s.array_as_hashmap = tag.array_as_hashmap; - break; - case json_attr_raw_string: - s.raw_string = tag.raw_string; - break; - case json_attr_required: - s.required = tag.required; - break; - case json_attr_float_precision: - s.float_precision = tag.float_precision; - break; - case json_attr_skip_if_default: - s.skip_if_default = tag.skip_if_default; - break; - default: - kphp_assert(0 && "unexpected json attr_type in field codegen"); + case json_attr_rename: + s.json_key = static_cast(tag.rename); + break; + case json_attr_skip: + s.skip_when_decoding = tag.skip == SkipFieldType::skip_decode_only || tag.skip == SkipFieldType::always_skip; + s.skip_when_encoding = tag.skip == SkipFieldType::skip_encode_only || tag.skip == SkipFieldType::always_skip; + break; + case json_attr_array_as_hashmap: + s.array_as_hashmap = tag.array_as_hashmap; + break; + case json_attr_raw_string: + s.raw_string = tag.raw_string; + break; + case json_attr_required: + s.required = tag.required; + break; + case json_attr_float_precision: + s.float_precision = tag.float_precision; + break; + case json_attr_skip_if_default: + s.skip_if_default = tag.skip_if_default; + break; + default: + kphp_assert(0 && "unexpected json attr_type in field codegen"); } } } diff --git a/compiler/data/kphp-json-tags.h b/compiler/data/kphp-json-tags.h index 28ec731ff8..9043828a74 100644 --- a/compiler/data/kphp-json-tags.h +++ b/compiler/data/kphp-json-tags.h @@ -7,24 +7,16 @@ #include #include -#include "compiler/data/data_ptr.h" #include "common/wrappers/string_view.h" +#include "compiler/data/data_ptr.h" struct ClassMemberInstanceField; - namespace kphp_json { -enum class RenamePolicy { - none, - snake_case, - camel_case -}; +enum class RenamePolicy { none, snake_case, camel_case }; -enum class VisibilityPolicy { - all, - public_only -}; +enum class VisibilityPolicy { all, public_only }; enum class SkipFieldType { dont_skip, @@ -48,15 +40,14 @@ enum JsonAttrType { json_attr_fields = 1 << 11, }; - // one `@kphp-json attr=value` is represented as this class // depending on attr_type, one of union fields is set // there could be for statement: `@kphp-json for MyEncoder attr=value` struct KphpJsonTag { JsonAttrType attr_type{json_attr_unknown}; ClassPtr for_encoder; - - union { + + union { vk::string_view rename; SkipFieldType skip; bool array_as_hashmap; @@ -77,15 +68,21 @@ class KphpJsonTagList { std::vector tags; public: - bool empty() const noexcept { return tags.empty(); } - auto begin() const noexcept { return tags.begin(); } - auto end() const noexcept { return tags.end(); } + bool empty() const noexcept { + return tags.empty(); + } + auto begin() const noexcept { + return tags.begin(); + } + auto end() const noexcept { + return tags.end(); + } template - const KphpJsonTag *find_tag(const CallbackT &callback) const noexcept { + const KphpJsonTag* find_tag(const CallbackT& callback) const noexcept { // no-'for' tag appears above 'for', so find the last one satisfying - const KphpJsonTag *last{nullptr}; - for (const KphpJsonTag &tag : tags) { + const KphpJsonTag* last{nullptr}; + for (const KphpJsonTag& tag : tags) { if (callback(tag)) { last = &tag; } @@ -93,11 +90,11 @@ class KphpJsonTagList { return last; } - void add_tag(const KphpJsonTag &json_tag); + void add_tag(const KphpJsonTag& json_tag); void validate_tags_compatibility(ClassPtr above_class) const; void check_flatten_class(ClassPtr flatten_class) const; - static const KphpJsonTagList *create_from_phpdoc(FunctionPtr resolve_context, const PhpDocComment *phpdoc, ClassPtr above_class); + static const KphpJsonTagList* create_from_phpdoc(FunctionPtr resolve_context, const PhpDocComment* phpdoc, ClassPtr above_class); }; // represents final settings for a field @@ -114,7 +111,7 @@ struct FieldJsonSettings { }; std::string transform_json_name_to(RenamePolicy policy, vk::string_view name) noexcept; -const KphpJsonTagList *convert_encoder_constants_to_tags(ClassPtr json_encoder); -FieldJsonSettings merge_and_inherit_json_tags(const ClassMemberInstanceField &field, ClassPtr klass, ClassPtr json_encoder); +const KphpJsonTagList* convert_encoder_constants_to_tags(ClassPtr json_encoder); +FieldJsonSettings merge_and_inherit_json_tags(const ClassMemberInstanceField& field, ClassPtr klass, ClassPtr json_encoder); } // namespace kphp_json diff --git a/compiler/data/kphp-tracing-tags.cpp b/compiler/data/kphp-tracing-tags.cpp index 6a30935f09..6f32acf089 100644 --- a/compiler/data/kphp-tracing-tags.cpp +++ b/compiler/data/kphp-tracing-tags.cpp @@ -9,25 +9,26 @@ #include "compiler/data/function-data.h" #include "compiler/data/src-file.h" -int KphpTracingDeclarationMixin::parse_level_attr(vk::string_view beg, size_t &pos_end) { +int KphpTracingDeclarationMixin::parse_level_attr(vk::string_view beg, size_t& pos_end) { int level = 0; int len = beg.size(); - for (; pos_end < len && isspace(beg[pos_end]); ++pos_end) {} + for (; pos_end < len && isspace(beg[pos_end]); ++pos_end) { + } for (; pos_end < len && isdigit(beg[pos_end]); ++pos_end) { level = level * 10 + (beg[pos_end] - '0'); } - kphp_error_act(level >= 1 && level <= 2, - "invalid 'level' in @kphp-tracing: expected to be 1/2", return 1); + kphp_error_act(level >= 1 && level <= 2, "invalid 'level' in @kphp-tracing: expected to be 1/2", return 1); return level; } -std::string KphpTracingDeclarationMixin::parse_string_attr(vk::string_view beg, size_t &pos_end) { +std::string KphpTracingDeclarationMixin::parse_string_attr(vk::string_view beg, size_t& pos_end) { std::string out; size_t len = beg.size(); - for (; pos_end < len && isspace(beg[pos_end]); ++pos_end) {} + for (; pos_end < len && isspace(beg[pos_end]); ++pos_end) { + } char quote = '\0'; if (pos_end < len && (beg[pos_end] == '"' || beg[pos_end] == '\'')) { @@ -35,7 +36,7 @@ std::string KphpTracingDeclarationMixin::parse_string_attr(vk::string_view beg, pos_end++; } - for (; pos_end < len; ++pos_end) { // eat a string until it ends + for (; pos_end < len; ++pos_end) { // eat a string until it ends char c = beg[pos_end]; if (isspace(c) && quote == '\0') { break; @@ -55,18 +56,17 @@ std::string KphpTracingDeclarationMixin::parse_string_attr(vk::string_view beg, return out; } -std::pair KphpTracingDeclarationMixin::parse_branch_attr(vk::string_view beg, size_t &pos_end) { +std::pair KphpTracingDeclarationMixin::parse_branch_attr(vk::string_view beg, size_t& pos_end) { int branch_num = 0; size_t len = beg.size(); - for (; pos_end < len && isspace(beg[pos_end]); ++pos_end) {} + for (; pos_end < len && isspace(beg[pos_end]); ++pos_end) { + } for (; pos_end < len && isdigit(beg[pos_end]); ++pos_end) { branch_num = branch_num * 10 + (beg[pos_end] - '0'); } - kphp_error_act(branch_num != 0 && pos_end < len && beg[pos_end] == ':', - "invalid 'branch' format in @kphp-tracing", return {}); - kphp_error_act(branch_num >= 1 && branch_num <= 3, - "invalid 'branch' in @kphp-tracing: number can be 1/2/3 only", return {}); + kphp_error_act(branch_num != 0 && pos_end < len && beg[pos_end] == ':', "invalid 'branch' format in @kphp-tracing", return {}); + kphp_error_act(branch_num >= 1 && branch_num <= 3, "invalid 'branch' in @kphp-tracing: number can be 1/2/3 only", return {}); pos_end++; size_t pos_end_str = 0; @@ -95,13 +95,13 @@ std::string KphpTracingDeclarationMixin::generate_default_span_title(FunctionPtr } title += static_cast(class_name) + "::" + f->local_name(); if (size_t rpos = title.rfind("$$"); rpos != std::string::npos) { - title = title.substr(0, rpos); // drop context class + title = title.substr(0, rpos); // drop context class } return title; } -KphpTracingDeclarationMixin *KphpTracingDeclarationMixin::create_for_function_from_phpdoc(FunctionPtr f, vk::string_view value) { - KphpTracingDeclarationMixin *m = new KphpTracingDeclarationMixin(); +KphpTracingDeclarationMixin* KphpTracingDeclarationMixin::create_for_function_from_phpdoc(FunctionPtr f, vk::string_view value) { + KphpTracingDeclarationMixin* m = new KphpTracingDeclarationMixin(); while (true) { value = vk::ltrim(value); @@ -141,10 +141,10 @@ KphpTracingDeclarationMixin *KphpTracingDeclarationMixin::create_for_function_fr return m; } -KphpTracingDeclarationMixin *KphpTracingDeclarationMixin::create_for_shutdown_function(FunctionPtr f) { - KphpTracingDeclarationMixin *m = new KphpTracingDeclarationMixin(); +KphpTracingDeclarationMixin* KphpTracingDeclarationMixin::create_for_shutdown_function(FunctionPtr f) { + KphpTracingDeclarationMixin* m = new KphpTracingDeclarationMixin(); m->span_title = generate_default_span_title(f); - + return m; } diff --git a/compiler/data/kphp-tracing-tags.h b/compiler/data/kphp-tracing-tags.h index 9b2bac3467..10a0a5a9a7 100644 --- a/compiler/data/kphp-tracing-tags.h +++ b/compiler/data/kphp-tracing-tags.h @@ -4,18 +4,18 @@ #pragma once -#include #include +#include -#include "compiler/data/data_ptr.h" #include "common/wrappers/string_view.h" +#include "compiler/data/data_ptr.h" class KphpTracingDeclarationMixin { static std::string generate_default_span_title(FunctionPtr f); - static int parse_level_attr(vk::string_view beg, size_t &pos_end); - static std::string parse_string_attr(vk::string_view beg, size_t &pos_end); - static std::pair parse_branch_attr(vk::string_view beg, size_t &pos_end); + static int parse_level_attr(vk::string_view beg, size_t& pos_end); + static std::string parse_string_attr(vk::string_view beg, size_t& pos_end); + static std::pair parse_branch_attr(vk::string_view beg, size_t& pos_end); public: int level{1}; @@ -23,8 +23,10 @@ class KphpTracingDeclarationMixin { std::string aggregate_name; std::forward_list> branches; - bool is_aggregate() const { return !aggregate_name.empty(); } + bool is_aggregate() const { + return !aggregate_name.empty(); + } - static KphpTracingDeclarationMixin *create_for_function_from_phpdoc(FunctionPtr f, vk::string_view value); - static KphpTracingDeclarationMixin *create_for_shutdown_function(FunctionPtr f); + static KphpTracingDeclarationMixin* create_for_function_from_phpdoc(FunctionPtr f, vk::string_view value); + static KphpTracingDeclarationMixin* create_for_shutdown_function(FunctionPtr f); }; diff --git a/compiler/data/lib-data.cpp b/compiler/data/lib-data.cpp index 476df61f42..c79283e900 100644 --- a/compiler/data/lib-data.cpp +++ b/compiler/data/lib-data.cpp @@ -9,18 +9,16 @@ #include "compiler/stage.h" namespace { -std::string get_lib_dir(const std::string &main_file_path) { +std::string get_lib_dir(const std::string& main_file_path) { const std::size_t last_slash = main_file_path.rfind('/'); kphp_assert_msg(last_slash != std::string::npos, "bad lib main file path"); return main_file_path.substr(0, last_slash + 1); } -std::string get_lib_name(const std::string &lib_require_name) { +std::string get_lib_name(const std::string& lib_require_name) { // expected: .../?${name} const std::size_t start_pos = lib_require_name.rfind('/'); - std::string lib_name = start_pos == std::string::npos - ? lib_require_name - : lib_require_name.substr(start_pos + 1); + std::string lib_name = start_pos == std::string::npos ? lib_require_name : lib_require_name.substr(start_pos + 1); kphp_assert_msg(!lib_name.empty(), "bad lib require name"); return lib_name; } @@ -30,23 +28,21 @@ bool is_raw_php_dir(vk::string_view lib_dir) { } } // namespace -LibData::LibData(const std::string &lib_name, const std::string &lib_dir) : - lib_dir_(lib_dir), - lib_name_(lib_name) { -} +LibData::LibData(const std::string& lib_name, const std::string& lib_dir) + : lib_dir_(lib_dir), + lib_name_(lib_name) {} -LibData::LibData(const std::string &lib_require_name) : - lib_name_(get_lib_name(lib_require_name)) { -} +LibData::LibData(const std::string& lib_require_name) + : lib_name_(get_lib_name(lib_require_name)) {} -void LibData::update_lib_main_file(const std::string &main_file_path, const std::string &unified_lib_dir) { +void LibData::update_lib_main_file(const std::string& main_file_path, const std::string& unified_lib_dir) { kphp_assert_msg(lib_dir_.empty(), "lib directory is known"); lib_dir_ = get_lib_dir(main_file_path); unified_lib_dir_ = unified_lib_dir; is_raw_php_ = is_raw_php_dir(lib_dir_); } -std::string LibData::run_global_function_name(const std::string &lib_name) { +std::string LibData::run_global_function_name(const std::string& lib_name) { return lib_name + "_run_global"; } @@ -77,15 +73,15 @@ std::string LibData::runtime_lib_sha256_file() const { return lib_dir() + "php_lib_version.sha256"; } -const std::string &LibData::lib_dir() const { +const std::string& LibData::lib_dir() const { kphp_assert_msg(!lib_dir_.empty(), "lib directory is unknown"); return lib_dir_; } -const char *LibData::headers_tmp_dir() { +const char* LibData::headers_tmp_dir() { return "lib_headers/"; } -const char *LibData::functions_txt_tmp_file() { +const char* LibData::functions_txt_tmp_file() { return "lib_functions.txt"; } diff --git a/compiler/data/lib-data.h b/compiler/data/lib-data.h index 13af4bbffc..40f50772d8 100644 --- a/compiler/data/lib-data.h +++ b/compiler/data/lib-data.h @@ -9,28 +9,36 @@ #include "compiler/debug.h" class LibData { - DEBUG_STRING_METHOD { return lib_name_; } - + DEBUG_STRING_METHOD { + return lib_name_; + } + public: - LibData(const std::string &lib_name, const std::string &lib_dir); - LibData(const std::string &lib_require_name); + LibData(const std::string& lib_name, const std::string& lib_dir); + LibData(const std::string& lib_require_name); - void update_lib_main_file(const std::string &main_file_path, const std::string &unified_lib_dir); + void update_lib_main_file(const std::string& main_file_path, const std::string& unified_lib_dir); - static std::string run_global_function_name(const std::string &lib_name); + static std::string run_global_function_name(const std::string& lib_name); std::string run_global_function_name() const; std::string static_archive_path() const; std::string headers_dir() const; std::string functions_txt_file() const; std::string runtime_lib_sha256_file() const; - const std::string &lib_dir() const; - const std::string &lib_namespace() const { return lib_name_; } - const std::string &unified_lib_dir() const { return unified_lib_dir_; } - bool is_raw_php() const { return is_raw_php_; } - - static const char *headers_tmp_dir(); - static const char *functions_txt_tmp_file(); + const std::string& lib_dir() const; + const std::string& lib_namespace() const { + return lib_name_; + } + const std::string& unified_lib_dir() const { + return unified_lib_dir_; + } + bool is_raw_php() const { + return is_raw_php_; + } + + static const char* headers_tmp_dir(); + static const char* functions_txt_tmp_file(); private: std::string lib_dir_; diff --git a/compiler/data/modulite-data.cpp b/compiler/data/modulite-data.cpp index 109fcba340..dcf37e84cd 100644 --- a/compiler/data/modulite-data.cpp +++ b/compiler/data/modulite-data.cpp @@ -39,19 +39,17 @@ * IMPORTANT! keep this file and logic very close to ModuliteData in modulite-phpstan */ - static const std::string EMPTY_STRING_RETURNED_WHEN_GOT_NONSTRING_IN_YAML; - -[[gnu::cold]] static void fire_yaml_error(ModulitePtr inside_m, const std::string &reason, int line) { - inside_m->yaml_file->load(); // load a file from disk, so that error message in console outputs a line +[[gnu::cold]] static void fire_yaml_error(ModulitePtr inside_m, const std::string& reason, int line) { + inside_m->yaml_file->load(); // load a file from disk, so that error message in console outputs a line stage::set_file(inside_m->yaml_file); stage::set_line(line); kphp_error(0, fmt_format("Failed loading {}:\n{}", inside_m->yaml_file->relative_file_name, reason)); } -[[gnu::cold]] static void fire_yaml_error(ModulitePtr inside_m, const std::string &reason, const YAML::Node &y_node) { +[[gnu::cold]] static void fire_yaml_error(ModulitePtr inside_m, const std::string& reason, const YAML::Node& y_node) { fire_yaml_error(inside_m, reason, y_node.Mark().line + 1); } @@ -63,7 +61,7 @@ static const std::string EMPTY_STRING_RETURNED_WHEN_GOT_NONSTRING_IN_YAML; class ModuliteYamlParser { ModulitePtr out; - [[gnu::always_inline]] const std::string &as_string(const YAML::Node &y) { + [[gnu::always_inline]] const std::string& as_string(const YAML::Node& y) { if (unlikely(!y.IsScalar() || y.Scalar().empty())) { fire_yaml_error(out, "expected non-empty string", y); return EMPTY_STRING_RETURNED_WHEN_GOT_NONSTRING_IN_YAML; @@ -71,8 +69,8 @@ class ModuliteYamlParser { return y.Scalar(); } - void parse_yaml_name(const YAML::Node &y_name) { - const std::string &name = y_name.Scalar(); + void parse_yaml_name(const YAML::Node& y_name) { + const std::string& name = y_name.Scalar(); if (name.empty() || name[0] != '@') { if (name == "") { return; @@ -97,8 +95,8 @@ class ModuliteYamlParser { out->modulite_name = std::move(modulite_name); } - void parse_yaml_namespace(const YAML::Node &y_namespace) { - const std::string &ns = y_namespace.Scalar(); + void parse_yaml_namespace(const YAML::Node& y_namespace) { + const std::string& ns = y_namespace.Scalar(); if (ns.empty() || ns == "\\") { return; } @@ -115,42 +113,42 @@ class ModuliteYamlParser { // parse any symbol as a string: "\\f()", "@msg/channels", "RelativeClass", etc. // at the moment of parsing, they are stored as strings, and later resolved to symbols (see resolve_names_to_pointers()) - ModuliteSymbol parse_any_scalar_symbol(const std::string &s, const YAML::Node &y_loc) const { + ModuliteSymbol parse_any_scalar_symbol(const std::string& s, const YAML::Node& y_loc) const { int line = y_loc.Mark().line + 1; - return ModuliteSymbol{.kind=ModuliteSymbol::kind_ref_stringname, .line=line, .ref_stringname=string_view_dup(s)}; + return ModuliteSymbol{.kind = ModuliteSymbol::kind_ref_stringname, .line = line, .ref_stringname = string_view_dup(s)}; } - void parse_yaml_export(const YAML::Node &y_export) { - for (const auto &y : y_export) { - const std::string &y_name = as_string(y); + void parse_yaml_export(const YAML::Node& y_export) { + for (const auto& y : y_export) { + const std::string& y_name = as_string(y); out->exports.emplace_back(parse_any_scalar_symbol(y_name, y)); } } - void parse_yaml_force_internal(const YAML::Node &y_force_internal) { - for (const auto &y : y_force_internal) { - const std::string &y_name = as_string(y); + void parse_yaml_force_internal(const YAML::Node& y_force_internal) { + for (const auto& y : y_force_internal) { + const std::string& y_name = as_string(y); out->force_internal.emplace_back(parse_any_scalar_symbol(y_name, y)); } } - void parse_yaml_require(const YAML::Node &y_require) { - for (const auto &y : y_require) { - const std::string &y_name = as_string(y); + void parse_yaml_require(const YAML::Node& y_require) { + for (const auto& y : y_require) { + const std::string& y_name = as_string(y); out->require.emplace_back(parse_any_scalar_symbol(y_name, y)); } } - void parse_yaml_allow_internal(const YAML::Node &y_allow_internal) { - for (const auto &y : y_allow_internal) { - const std::string &y_rule = as_string(y.first); + void parse_yaml_allow_internal(const YAML::Node& y_allow_internal) { + for (const auto& y : y_allow_internal) { + const std::string& y_rule = as_string(y.first); if (!y.second.IsSequence()) { fire_yaml_error(out, "invalid format, expected a map of sequences", y.first); continue; } std::vector e_vector; e_vector.reserve(y.second.size()); - for (const auto &y_rule_val : y.second) { + for (const auto& y_rule_val : y.second) { e_vector.emplace_back(parse_any_scalar_symbol(as_string(y_rule_val), y_rule_val)); } out->allow_internal.emplace_back(parse_any_scalar_symbol(y_rule, y.first), std::move(e_vector)); @@ -158,24 +156,25 @@ class ModuliteYamlParser { } public: - explicit ModuliteYamlParser(ModulitePtr out) : out(std::move(out)) {} + explicit ModuliteYamlParser(ModulitePtr out) + : out(std::move(out)) {} - void parse_modulite_yaml_file(const YAML::Node &y_file) { - const auto &y_name = y_file["name"]; + void parse_modulite_yaml_file(const YAML::Node& y_file) { + const auto& y_name = y_file["name"]; if (y_name && y_name.IsScalar()) { parse_yaml_name(y_name); } else { fire_yaml_error(out, "'name' not specified", -1); } - const auto &y_namespace = y_file["namespace"]; + const auto& y_namespace = y_file["namespace"]; if (y_namespace && y_namespace.IsScalar()) { parse_yaml_namespace(y_namespace); } else { fire_yaml_error(out, "'namespace' not specified", -1); } - const auto &y_export = y_file["export"]; + const auto& y_export = y_file["export"]; if (y_export && y_export.IsSequence()) { parse_yaml_export(y_export); } else if (!y_export) { @@ -184,14 +183,14 @@ class ModuliteYamlParser { fire_yaml_error(out, "'export' has incorrect format", y_export); } - const auto &y_force_internal = y_file["force-internal"]; + const auto& y_force_internal = y_file["force-internal"]; if (y_force_internal && y_force_internal.IsSequence()) { parse_yaml_force_internal(y_force_internal); } else if (y_force_internal && !y_force_internal.IsNull()) { fire_yaml_error(out, "'force-internal' has incorrect format", y_force_internal); } - const auto &y_require = y_file["require"]; + const auto& y_require = y_file["require"]; if (y_require && y_require.IsSequence()) { parse_yaml_require(y_require); } else if (!y_require) { @@ -200,7 +199,7 @@ class ModuliteYamlParser { fire_yaml_error(out, "'require' has incorrect format", y_require); } - const auto &y_allow_internal = y_file["allow-internal-access"]; + const auto& y_allow_internal = y_file["allow-internal-access"]; if (y_allow_internal && y_allow_internal.IsMap()) { parse_yaml_allow_internal(y_allow_internal); } else if (y_allow_internal && !y_allow_internal.IsNull()) { @@ -212,15 +211,14 @@ class ModuliteYamlParser { // modulites named absolutely, like @utils or @flood-details — like in any other project // but when a monolith uses that package placed in vendor/, all its modulites are prefixed: // @flood/details in #vk/common is represented as "#vk/common/@flood/details" on monolith compilation - static std::string prepend_composer_package_to_name(ComposerJsonPtr composer_json, const std::string &modulite_name) { + static std::string prepend_composer_package_to_name(ComposerJsonPtr composer_json, const std::string& modulite_name) { return "#" + composer_json->package_name + "/" + modulite_name; } }; - // having some_file.php, detect a modulite this file belongs to // up to this point, all dirs have been traversed and propagated to child dirs also -static inline ModulitePtr get_modulite_of_file(const SrcFilePtr &file_id) { +static inline ModulitePtr get_modulite_of_file(const SrcFilePtr& file_id) { return file_id->dir->nested_files_modulite; } @@ -229,24 +227,24 @@ static inline ModulitePtr get_modulite_of_file(const SrcFilePtr &file_id) { // because that properties haven't been assigned up to the point of yaml validation // `FunctionData::modulite` and similar will be assigned later, to be used for checking func calls / class access / etc. // See `CalcRealDefinesAndAssignModulitesF` sync pipe. -static ModulitePtr get_modulite_of_symbol(const ModuliteSymbol &s) { +static ModulitePtr get_modulite_of_symbol(const ModuliteSymbol& s) { switch (s.kind) { - case ModuliteSymbol::kind_ref_stringname: - return ModulitePtr{}; - case ModuliteSymbol::kind_modulite: - return s.modulite->parent; - case ModuliteSymbol::kind_klass: - case ModuliteSymbol::kind_constant: - case ModuliteSymbol::kind_property: - return get_modulite_of_file(s.klass->file_id); - case ModuliteSymbol::kind_function: - return get_modulite_of_file(s.klass ? s.klass->file_id : s.function->file_id); - case ModuliteSymbol::kind_global_const: - return get_modulite_of_file(s.constant->file_id); - case ModuliteSymbol::kind_global_var: - return ModulitePtr{}; - default: - __builtin_unreachable(); + case ModuliteSymbol::kind_ref_stringname: + return ModulitePtr{}; + case ModuliteSymbol::kind_modulite: + return s.modulite->parent; + case ModuliteSymbol::kind_klass: + case ModuliteSymbol::kind_constant: + case ModuliteSymbol::kind_property: + return get_modulite_of_file(s.klass->file_id); + case ModuliteSymbol::kind_function: + return get_modulite_of_file(s.klass ? s.klass->file_id : s.function->file_id); + case ModuliteSymbol::kind_global_const: + return get_modulite_of_file(s.constant->file_id); + case ModuliteSymbol::kind_global_var: + return ModulitePtr{}; + default: + __builtin_unreachable(); } } @@ -261,8 +259,9 @@ ModulitePtr ModuliteData::create_from_composer_json(ComposerJsonPtr composer_jso out->is_composer_package = true; // json->require (dependent packages, e.g. "vk/utils") are copied to modulite->require, e.g. "#vk/utils" - for (const ComposerJsonData::RequireItem &c_require : composer_json->require) { - out->require.emplace_back(ModuliteSymbol{.kind=ModuliteSymbol::kind_ref_stringname, .line=-1, .ref_stringname=string_view_dup("#" + c_require.package_name)}); + for (const ComposerJsonData::RequireItem& c_require : composer_json->require) { + out->require.emplace_back( + ModuliteSymbol{.kind = ModuliteSymbol::kind_ref_stringname, .line = -1, .ref_stringname = string_view_dup("#" + c_require.package_name)}); } if (has_modulite_yaml_also) { @@ -272,7 +271,7 @@ ModulitePtr ModuliteData::create_from_composer_json(ComposerJsonPtr composer_jso YAML::Node y_file = YAML::LoadFile(out->yaml_file->file_name); ModuliteYamlParser parser(out); parser.parse_modulite_yaml_file(y_file); - } catch (const YAML::Exception &ex) { + } catch (const YAML::Exception& ex) { fire_yaml_error(out, ex.msg, ex.mark.line + 1); return ModulitePtr{}; } @@ -282,7 +281,7 @@ ModulitePtr ModuliteData::create_from_composer_json(ComposerJsonPtr composer_jso } // parse modulite.yaml and emit ModulitePtr from it -ModulitePtr ModuliteData::create_from_modulite_yaml(const std::string &yaml_filename, ModulitePtr parent) { +ModulitePtr ModuliteData::create_from_modulite_yaml(const std::string& yaml_filename, ModulitePtr parent) { ModulitePtr out = ModulitePtr(new ModuliteData()); out->yaml_file = G->register_file(yaml_filename, LibPtr{}); out->parent = parent; @@ -294,7 +293,7 @@ ModulitePtr ModuliteData::create_from_modulite_yaml(const std::string &yaml_file ModuliteYamlParser parser(out); parser.parse_modulite_yaml_file(y_file); return out; - } catch (const YAML::Exception &ex) { + } catch (const YAML::Exception& ex) { fire_yaml_error(out, ex.msg, ex.mark.line + 1); return ModulitePtr{}; } @@ -305,25 +304,24 @@ ModulitePtr ModuliteData::create_from_modulite_yaml(const std::string &yaml_file void ModuliteData::resolve_names_to_pointers() { ModulitePtr inside_m = get_self_ptr(); - for (ModuliteSymbol &symbol : exports) { + for (ModuliteSymbol& symbol : exports) { resolve_symbol_from_yaml(symbol); } - for (ModuliteSymbol &symbol : force_internal) { + for (ModuliteSymbol& symbol : force_internal) { resolve_symbol_from_yaml(symbol); } - for (ModuliteSymbol &symbol : require) { + for (ModuliteSymbol& symbol : require) { resolve_symbol_from_yaml(symbol); } - for (auto &p_allow_rule : allow_internal) { + for (auto& p_allow_rule : allow_internal) { resolve_symbol_from_yaml(p_allow_rule.first); - for (ModuliteSymbol &symbol : p_allow_rule.second) { + for (ModuliteSymbol& symbol : p_allow_rule.second) { resolve_symbol_from_yaml(symbol); } } - inside_m->exported_from_parent = parent && vk::any_of(parent->exports, [inside_m](const ModuliteSymbol &e) { - return e.kind == ModuliteSymbol::kind_modulite && e.modulite == inside_m; - }); + inside_m->exported_from_parent = + parent && vk::any_of(parent->exports, [inside_m](const ModuliteSymbol& e) { return e.kind == ModuliteSymbol::kind_modulite && e.modulite == inside_m; }); // if a composer package is written using modulites, then all its child modulites are exported and available from the monolith // (unless .modulite.yaml near composer.json explicitly declares "export") @@ -343,7 +341,7 @@ void ModuliteData::resolve_names_to_pointers() { // resolve any config item ("SomeClass", "SomeClass::f()", "@msg", etc.) from a string to a symbol // this is done in-place, modifying s.kind and s.{union_prop} // on error resolving, it's also printed here, pointing to a concrete line in yaml file -void ModuliteData::resolve_symbol_from_yaml(ModuliteSymbol &s) { +void ModuliteData::resolve_symbol_from_yaml(ModuliteSymbol& s) { kphp_assert(s.kind == ModuliteSymbol::kind_ref_stringname); ModulitePtr inside_m = get_self_ptr(); vk::string_view v = s.ref_stringname; @@ -362,7 +360,7 @@ void ModuliteData::resolve_symbol_from_yaml(ModuliteSymbol &s) { } return; } - + // #composer-package if (v[0] == '#') { if (ModulitePtr m_ref = G->get_modulite(v)) { @@ -421,7 +419,7 @@ void ModuliteData::resolve_symbol_from_yaml(ModuliteSymbol &s) { // C::$static_field if (v[pos$$ + 2] == '$') { vk::string_view local_name = v.substr(pos$$ + 3); - if (const ClassMemberStaticField *f = klass->get_static_field(local_name)) { + if (const ClassMemberStaticField* f = klass->get_static_field(local_name)) { s.kind = ModuliteSymbol::kind_property; s.klass = klass; s.property = f->var; @@ -433,11 +431,11 @@ void ModuliteData::resolve_symbol_from_yaml(ModuliteSymbol &s) { // C::static_method() or C::instance_method() if (v[v.size() - 1] == ')') { vk::string_view local_name = v.substr(pos$$ + 2, v.size() - pos$$ - 4); - if (const ClassMemberStaticMethod *m = klass->members.get_static_method(local_name)) { + if (const ClassMemberStaticMethod* m = klass->members.get_static_method(local_name)) { s.kind = ModuliteSymbol::kind_function; s.klass = klass; s.function = m->function; - } else if (const ClassMemberInstanceMethod *m = klass->get_instance_method(local_name)) { + } else if (const ClassMemberInstanceMethod* m = klass->get_instance_method(local_name)) { s.kind = ModuliteSymbol::kind_function; s.klass = klass; s.function = m->function; @@ -448,7 +446,7 @@ void ModuliteData::resolve_symbol_from_yaml(ModuliteSymbol &s) { } // C::CONST vk::string_view local_name = v.substr(pos$$ + 2); - if (const ClassMemberConstant *c = klass->get_constant(local_name)) { + if (const ClassMemberConstant* c = klass->get_constant(local_name)) { s.kind = ModuliteSymbol::kind_constant; s.klass = klass; s.constant = G->get_define(c->define_name); @@ -456,12 +454,12 @@ void ModuliteData::resolve_symbol_from_yaml(ModuliteSymbol &s) { fire_yaml_error(inside_m, fmt_format("can't find constant {}::{}", paint_bold(c_fqn), paint_bold(local_name)), s.line); } } -}; +} void ModuliteData::validate_yaml_requires() { ModulitePtr inside_m = get_self_ptr(); - for (const ModuliteSymbol &r : require) { + for (const ModuliteSymbol& r : require) { if (r.kind == ModuliteSymbol::kind_modulite) { // @msg requires @feed or @some/another // valid: @feed has no parent or @some/another is exported from @some @@ -477,14 +475,17 @@ void ModuliteData::validate_yaml_requires() { if (ModulitePtr cur_parent = child->parent; cur_parent && !child->exported_from_parent) { // valid: even if @some/another is not exported, but mentioned in "allow-internal-access" for @msg in @some auto it_this = std::find_if(cur_parent->allow_internal.begin(), cur_parent->allow_internal.end(), - [inside_m](const auto &p) { return p.first.kind == ModuliteSymbol::kind_modulite && p.first.modulite == inside_m; }); + [inside_m](const auto& p) { return p.first.kind == ModuliteSymbol::kind_modulite && p.first.modulite == inside_m; }); if (it_this != cur_parent->allow_internal.end()) { - bool lists_cur = vk::any_of(it_this->second, [child](const ModuliteSymbol &s) { return s.kind == ModuliteSymbol::kind_modulite && s.modulite == child; }); + bool lists_cur = + vk::any_of(it_this->second, [child](const ModuliteSymbol& s) { return s.kind == ModuliteSymbol::kind_modulite && s.modulite == child; }); if (lists_cur) { continue; } } - fire_yaml_error(inside_m, fmt_format("can't require {}: {} is internal in {}", another_m->modulite_name, child->modulite_name, child->parent->modulite_name), r.line); + fire_yaml_error(inside_m, + fmt_format("can't require {}: {} is internal in {}", another_m->modulite_name, child->modulite_name, child->parent->modulite_name), + r.line); } } @@ -495,7 +496,10 @@ void ModuliteData::validate_yaml_requires() { ModulitePtr of_modulite = get_modulite_of_symbol(r); bool is_global_scope = !of_modulite || (of_modulite->is_composer_package && of_modulite->composer_json == inside_m->composer_json); if (!is_global_scope) { - fire_yaml_error(inside_m, fmt_format("'require' contains a member of {}; you should require {} directly, not its members", of_modulite->modulite_name, of_modulite->modulite_name), r.line); + fire_yaml_error(inside_m, + fmt_format("'require' contains a member of {}; you should require {} directly, not its members", of_modulite->modulite_name, + of_modulite->modulite_name), + r.line); } } } @@ -504,7 +508,7 @@ void ModuliteData::validate_yaml_requires() { void ModuliteData::validate_yaml_exports() { ModulitePtr inside_m = get_self_ptr(); - for (const ModuliteSymbol &e : exports) { + for (const ModuliteSymbol& e : exports) { if (e.kind == ModuliteSymbol::kind_modulite) { // @msg exports @another_m // valid: @msg exports @msg/channels @@ -532,18 +536,17 @@ void ModuliteData::validate_yaml_exports() { void ModuliteData::validate_yaml_force_internal() { ModulitePtr inside_m = get_self_ptr(); - for (const ModuliteSymbol &fi : force_internal) { + for (const ModuliteSymbol& fi : force_internal) { // if @msg force internals A::someMethod() or A::CONST, // it can't be also declared in exports - for (const ModuliteSymbol &e : inside_m->exports) { + for (const ModuliteSymbol& e : inside_m->exports) { if (e.kind == fi.kind && e.function == fi.function) { fire_yaml_error(inside_m, fmt_format("'force-internal' contains a symbol which is exported"), fi.line); } } - bool is_allowed = (fi.kind == ModuliteSymbol::kind_constant && fi.klass) - || (fi.kind == ModuliteSymbol::kind_function && fi.klass) - || (fi.kind == ModuliteSymbol::kind_property && fi.klass); + bool is_allowed = (fi.kind == ModuliteSymbol::kind_constant && fi.klass) || (fi.kind == ModuliteSymbol::kind_function && fi.klass) || + (fi.kind == ModuliteSymbol::kind_property && fi.klass); if (!is_allowed) { // @msg force internals @msg/channels or #vk/common or SomeClass fire_yaml_error(inside_m, "'force-internal' can contain only class members", fi.line); diff --git a/compiler/data/modulite-data.h b/compiler/data/modulite-data.h index d6ed98b10b..2bdf727bd0 100644 --- a/compiler/data/modulite-data.h +++ b/compiler/data/modulite-data.h @@ -4,9 +4,9 @@ #pragma once -#include -#include #include +#include +#include #include "common/wrappers/string_view.h" @@ -20,18 +20,18 @@ // depending on kind, a field of a union is set struct ModuliteSymbol { enum Kind { - kind_ref_stringname, // @another_m or #composer/package until being resolved - kind_modulite, // @feed or @msg/channels - kind_klass, // SomeClass - kind_function, // someFunction() or A::someMethod() - kind_constant, // A::CONST - kind_property, // A::$static_field - kind_global_const, // SOME_DEFINE or GLOBAL_CONST - kind_global_var, // $global_var + kind_ref_stringname, // @another_m or #composer/package until being resolved + kind_modulite, // @feed or @msg/channels + kind_klass, // SomeClass + kind_function, // someFunction() or A::someMethod() + kind_constant, // A::CONST + kind_property, // A::$static_field + kind_global_const, // SOME_DEFINE or GLOBAL_CONST + kind_global_var, // $global_var } kind; int line; - ClassPtr klass; // valid for kind_klass, kind_function (when method), kind_constant, kind_property + ClassPtr klass; // valid for kind_klass, kind_function (when method), kind_constant, kind_property // note, that for inheritance, when A{const C} and B extends A, B::C refers to A::C actually // (when we parse "B::C" in yaml, we call $b->get_constant('C'), it returns a member of A) // if B and A belong to different modulites, this fact leads to unexpected errors @@ -54,13 +54,17 @@ struct ModuliteSymbol { // represents structure of .modulite.yaml // IMPORTANT! keep this class and logic very close to ModuliteData in modulite-phpstan class ModuliteData { - DEBUG_STRING_METHOD { return modulite_name; } + DEBUG_STRING_METHOD { + return modulite_name; + } - ModulitePtr get_self_ptr() { return ModulitePtr(this); } + ModulitePtr get_self_ptr() { + return ModulitePtr(this); + } public: static ModulitePtr create_from_composer_json(ComposerJsonPtr composer_json, bool has_modulite_yaml_also); - static ModulitePtr create_from_modulite_yaml(const std::string &yaml_filename, ModulitePtr parent); + static ModulitePtr create_from_modulite_yaml(const std::string& yaml_filename, ModulitePtr parent); // full absolute path to .modulite.yaml, it's registered in G, it has ->dir, kphp_error can point to it SrcFilePtr yaml_file; @@ -94,9 +98,8 @@ class ModuliteData { // "allow-internal-access" from yaml lists additional "export" rules for specific usage contexts std::vector>> allow_internal; - void resolve_names_to_pointers(); - void resolve_symbol_from_yaml(ModuliteSymbol &s); + void resolve_symbol_from_yaml(ModuliteSymbol& s); void validate_yaml_requires(); void validate_yaml_exports(); @@ -104,4 +107,3 @@ class ModuliteData { ModulitePtr find_lca_with(ModulitePtr another_m); }; - diff --git a/compiler/data/performance-inspections.cpp b/compiler/data/performance-inspections.cpp index 490e1869e0..1ae45cc738 100644 --- a/compiler/data/performance-inspections.cpp +++ b/compiler/data/performance-inspections.cpp @@ -10,14 +10,13 @@ namespace { constexpr auto get_all_inspections() noexcept { - return vk::to_array>( - { - {PerformanceInspections::array_merge_into, "array-merge-into"}, - {PerformanceInspections::array_reserve, "array-reserve"}, + return vk::to_array>({ + {PerformanceInspections::array_merge_into, "array-merge-into"}, + {PerformanceInspections::array_reserve, "array-reserve"}, {PerformanceInspections::constant_execution_in_loop, "constant-execution-in-loop"}, - {PerformanceInspections::implicit_array_cast, "implicit-array-cast"}, - {PerformanceInspections::all_inspections, "all"}, - }); + {PerformanceInspections::implicit_array_cast, "implicit-array-cast"}, + {PerformanceInspections::all_inspections, "all"}, + }); } PerformanceInspections::Inspections string2inspection(vk::string_view str_inspection) { @@ -32,8 +31,7 @@ PerformanceInspections::Inspections string2inspection(vk::string_view str_inspec } // namespace PerformanceInspections::PerformanceInspections(Inspections enabled) noexcept - : enabled_inspections_(enabled) { -} + : enabled_inspections_(enabled) {} void PerformanceInspections::set_from_php_doc(vk::string_view php_doc_tag) { const auto raw_inspections = split_skipping_delimeters(php_doc_tag); @@ -66,8 +64,8 @@ PerformanceInspections::merge_with_caller(PerformanceInspections caller_inspecti return {InheritStatus::no_need, no_inspections}; } - if (std::underlying_type_t conflicts = (inspections() & caller_inspections.disabled_inspections_) | - (disabled_inspections_ & caller_inspections.inspections())) { + if (std::underlying_type_t conflicts = + (inspections() & caller_inspections.disabled_inspections_) | (disabled_inspections_ & caller_inspections.inspections())) { const auto first_conflict = static_cast((1 << (__builtin_ffsll(conflicts) - 1))); return {InheritStatus::conflict, first_conflict}; } diff --git a/compiler/data/performance-inspections.h b/compiler/data/performance-inspections.h index fef611a25f..5c01de73e0 100644 --- a/compiler/data/performance-inspections.h +++ b/compiler/data/performance-inspections.h @@ -36,11 +36,7 @@ class PerformanceInspections { return disabled_inspections_; } - enum class InheritStatus { - ok, - no_need, - conflict - }; + enum class InheritStatus { ok, no_need, conflict }; std::pair merge_with_caller(PerformanceInspections caller_inspections) noexcept; static vk::string_view inspection2string(Inspections inspection) noexcept; diff --git a/compiler/data/src-dir.cpp b/compiler/data/src-dir.cpp index 04cc4fa8f9..c7d652921b 100644 --- a/compiler/data/src-dir.cpp +++ b/compiler/data/src-dir.cpp @@ -6,8 +6,8 @@ #include - -SrcDir::SrcDir(std::string full_dir_name) : full_dir_name(std::move(full_dir_name)) { +SrcDir::SrcDir(std::string full_dir_name) + : full_dir_name(std::move(full_dir_name)) { kphp_assert(this->full_dir_name[this->full_dir_name.size() - 1] == '/'); has_modulite_yaml = access(get_modulite_yaml_filename().c_str(), F_OK) == 0; diff --git a/compiler/data/src-dir.h b/compiler/data/src-dir.h index fbc6a647f1..16e0355a1b 100644 --- a/compiler/data/src-dir.h +++ b/compiler/data/src-dir.h @@ -13,7 +13,9 @@ #include "compiler/debug.h" class SrcDir { - DEBUG_STRING_METHOD { return full_dir_name; } + DEBUG_STRING_METHOD { + return full_dir_name; + } public: explicit SrcDir(std::string full_dir_name); @@ -29,7 +31,7 @@ class SrcDir { processing, done, }; - std::atomic state_collect_required{PassStatus::uninitialized}; // for "collect required" pass + std::atomic state_collect_required{PassStatus::uninitialized}; // for "collect required" pass std::string get_modulite_yaml_filename() const; }; diff --git a/compiler/data/src-file.cpp b/compiler/data/src-file.cpp index e3417dbd34..fe6d491551 100644 --- a/compiler/data/src-file.cpp +++ b/compiler/data/src-file.cpp @@ -23,7 +23,7 @@ bool SrcFile::load() { int err; int fid = open(file_name.c_str(), O_RDONLY); - kphp_assert_msg (fid >= 0, fmt_format("failed to open file [{}] : {}", file_name, strerror(errno))); + kphp_assert_msg(fid >= 0, fmt_format("failed to open file [{}] : {}", file_name, strerror(errno))); struct stat buf; err = fstat(fid, &buf); @@ -36,7 +36,7 @@ bool SrcFile::load() { kphp_assert_msg(err >= 0, fmt_format("Can't read file [{}]: {}", file_name, strerror(errno))); for (int i = 0, prev_i = 0; i < file_size; i++) { - if (unlikely (text[i] == 0)) { + if (unlikely(text[i] == 0)) { kphp_warning(fmt_format("symbol with code zero was replaced by space in file [{}] at [{}]", file_name, i)); text[i] = ' '; } diff --git a/compiler/data/src-file.h b/compiler/data/src-file.h index 2d9fac7c98..99bfbeaedb 100644 --- a/compiler/data/src-file.h +++ b/compiler/data/src-file.h @@ -13,8 +13,10 @@ #include "compiler/debug.h" class SrcFile { - DEBUG_STRING_METHOD { return relative_file_name; } - + DEBUG_STRING_METHOD { + return relative_file_name; + } + public: int id{0}; std::string text, file_name, short_file_name; @@ -22,7 +24,7 @@ class SrcFile { std::string relative_dir_name; bool loaded{false}; bool is_required{false}; - bool is_strict_types{false}; // whether declare(strict_types=1) is set + bool is_strict_types{false}; // whether declare(strict_types=1) is set bool is_from_functions_file{false}; // functions.txt + all files required from it bool is_loaded_by_psr0{false}; @@ -38,17 +40,18 @@ class SrcFile { std::map namespace_uses; SrcFile() = default; - SrcFile(std::string file_name, std::string short_file_name, LibPtr owner_lib_id) : - file_name(std::move(file_name)), - short_file_name(std::move(short_file_name)), - owner_lib(owner_lib_id) { - } + SrcFile(std::string file_name, std::string short_file_name, LibPtr owner_lib_id) + : file_name(std::move(file_name)), + short_file_name(std::move(short_file_name)), + owner_lib(owner_lib_id) {} bool load(); vk::string_view get_line(int id); - bool is_builtin() const { return is_from_functions_file || is_from_owner_lib(); } + bool is_builtin() const { + return is_from_functions_file || is_from_owner_lib(); + } bool is_from_owner_lib() const; std::string get_main_func_run_var_name() const; diff --git a/compiler/data/var-data.cpp b/compiler/data/var-data.cpp index 6c7dc36915..622b030640 100644 --- a/compiler/data/var-data.cpp +++ b/compiler/data/var-data.cpp @@ -7,8 +7,8 @@ #include "compiler/data/class-data.h" #include "compiler/stage.h" -VarData::VarData(VarData::Type type_) : - type_(type_) {} +VarData::VarData(VarData::Type type_) + : type_(type_) {} void VarData::set_uninited_flag(bool f) { uninited_flag = f; @@ -22,30 +22,28 @@ std::string VarData::as_human_readable() const { return (this->class_id ? (this->class_id->as_human_readable() + "::$" + get_local_name_from_global_$$(this->name)) : "$" + this->name); } -const ClassMemberStaticField *VarData::as_class_static_field() const { +const ClassMemberStaticField* VarData::as_class_static_field() const { kphp_assert(is_class_static_var() && class_id); return class_id->members.get_static_field(get_local_name_from_global_$$(name)); } -const ClassMemberInstanceField *VarData::as_class_instance_field() const { +const ClassMemberInstanceField* VarData::as_class_instance_field() const { kphp_assert(is_class_instance_var() && class_id); return class_id->members.get_instance_field(name); } -bool VarData::does_name_eq_any_language_superglobal(const std::string &name) { +bool VarData::does_name_eq_any_language_superglobal(const std::string& name) { // these vars are 'superglobals' in PHP language: they are available in all scopes static const std::unordered_set superglobal_names = { - "_SERVER", "_GET", "_POST", "_ENV", "_FILES", "_COOKIE", "_REQUEST", + "_SERVER", "_GET", "_POST", "_ENV", "_FILES", "_COOKIE", "_REQUEST", }; return superglobal_names.find(name) != superglobal_names.end(); } -bool VarData::does_name_eq_any_builtin_runtime(const std::string &name) { +bool VarData::does_name_eq_any_builtin_runtime(const std::string& name) { // these vars are runtime built-ins, see PhpScriptBuiltInSuperGlobals - static const std::unordered_set runtime_names = { - "_SERVER", "_GET", "_POST", "_ENV", "_FILES", "_COOKIE", "_REQUEST", - "argc", "argv", "d$PHP_SAPI" - }; + static const std::unordered_set runtime_names = {"_SERVER", "_GET", "_POST", "_ENV", "_FILES", + "_COOKIE", "_REQUEST", "argc", "argv", "d$PHP_SAPI"}; return runtime_names.find(name) != runtime_names.end(); } diff --git a/compiler/data/var-data.h b/compiler/data/var-data.h index 17599dddf8..1ec4feae0f 100644 --- a/compiler/data/var-data.h +++ b/compiler/data/var-data.h @@ -12,19 +12,12 @@ #include "compiler/inferring/var-node.h" class VarData { - DEBUG_STRING_METHOD { return as_human_readable(); } - + DEBUG_STRING_METHOD { + return as_human_readable(); + } + public: - enum Type { - var_unknown_t = 0, - var_local_t, - var_local_inplace_t, - var_global_t, - var_param_t, - var_const_t, - var_static_t, - var_instance_t - }; + enum Type { var_unknown_t = 0, var_local_t, var_local_inplace_t, var_global_t, var_param_t, var_const_t, var_static_t, var_instance_t }; Type type_ = var_unknown_t; int id = -1; @@ -35,7 +28,7 @@ class VarData { bool had_user_assigned_val = false; FunctionPtr holder_func; ClassPtr class_id; - std::unordered_set *bad_vars = nullptr; + std::unordered_set* bad_vars = nullptr; bool is_reference = false; bool uninited_flag = false; bool optimize_flag = false; @@ -45,17 +38,19 @@ class VarData { bool marked_as_const = false; bool is_read_only = true; bool is_foreach_reference = false; - bool is_builtin_runtime = false; // $_SERVER, $argv, etc., see PhpScriptBuiltInSuperGlobals in runtime - int dependency_level = 0; // for constants only (c_str$, c_arr$, etc) - int offset_in_linear_mem = -1; // for globals only (offset in g_linear_mem) - int batch_idx = -1; // for constants and globals, a number [0;N), see const-globals-batched-mem.h + bool is_builtin_runtime = false; // $_SERVER, $argv, etc., see PhpScriptBuiltInSuperGlobals in runtime + int dependency_level = 0; // for constants only (c_str$, c_arr$, etc) + int offset_in_linear_mem = -1; // for globals only (offset in g_linear_mem) + int batch_idx = -1; // for constants and globals, a number [0;N), see const-globals-batched-mem.h void set_uninited_flag(bool f); bool get_uninited_flag(); explicit VarData(Type type); - inline Type &type() { return type_; } + inline Type& type() { + return type_; + } std::string as_human_readable() const; @@ -83,9 +78,9 @@ class VarData { return type_ == var_const_t; } - const ClassMemberStaticField *as_class_static_field() const; - const ClassMemberInstanceField *as_class_instance_field() const; + const ClassMemberStaticField* as_class_static_field() const; + const ClassMemberInstanceField* as_class_instance_field() const; - static bool does_name_eq_any_language_superglobal(const std::string &name); - static bool does_name_eq_any_builtin_runtime(const std::string &name); + static bool does_name_eq_any_language_superglobal(const std::string& name); + static bool does_name_eq_any_builtin_runtime(const std::string& name); }; diff --git a/compiler/data/vertex-adaptor.h b/compiler/data/vertex-adaptor.h index 76dfea5b49..b191c411c0 100644 --- a/compiler/data/vertex-adaptor.h +++ b/compiler/data/vertex-adaptor.h @@ -22,31 +22,30 @@ VertexPtr clone_vertex(VertexPtr); template class VertexAdaptor { - vertex_inner *impl_{nullptr}; + vertex_inner* impl_{nullptr}; template friend class VertexAdaptor; public: struct Hash { - size_t operator()(const VertexAdaptor &arg) const noexcept { + size_t operator()(const VertexAdaptor& arg) const noexcept { return reinterpret_cast(arg.impl_); } }; VertexAdaptor() = default; - explicit VertexAdaptor(vertex_inner *impl) noexcept - : impl_(impl) {} + explicit VertexAdaptor(vertex_inner* impl) noexcept + : impl_(impl) {} template> - VertexAdaptor(const VertexAdaptor &from) noexcept - : impl_(static_cast *>(from.impl_)) { - } + VertexAdaptor(const VertexAdaptor& from) noexcept + : impl_(static_cast*>(from.impl_)) {} template> - VertexAdaptor &operator=(const VertexAdaptor &from) noexcept { - impl_ = static_cast *>(from.impl_); + VertexAdaptor& operator=(const VertexAdaptor& from) noexcept { + impl_ = static_cast*>(from.impl_); return *this; } @@ -54,22 +53,22 @@ class VertexAdaptor { return impl_ != nullptr; } - vertex_inner *operator->() noexcept { + vertex_inner* operator->() noexcept { assert(impl_ != nullptr); return impl_; } - const vertex_inner *operator->() const noexcept { + const vertex_inner* operator->() const noexcept { assert(impl_ != nullptr); return impl_; } - vertex_inner &operator*() noexcept { + vertex_inner& operator*() noexcept { assert(impl_ != nullptr); return *impl_; } - const vertex_inner &operator*() const noexcept { + const vertex_inner& operator*() const noexcept { assert(impl_ != nullptr); return *impl_; } @@ -90,23 +89,23 @@ class VertexAdaptor { static_assert(op_type_is_base_of(Op, to), "Strange downcast to not derived vertex"); static_assert(Op != to || Op == meta_op_base, "Useless cast"); if (op_type_is_base_of(to, impl_->type())) { - return VertexAdaptor{static_cast *>(impl_)}; + return VertexAdaptor{static_cast*>(impl_)}; } return {}; } - static void init_properties(OpProperties *prop) { + static void init_properties(OpProperties* prop) { vertex_inner::init_properties(prop); } template - static VertexAdaptor create(Args &&...args) noexcept { + static VertexAdaptor create(Args&&... args) noexcept { return VertexAdaptor{vertex_inner::create(std::forward(args)...)}; } template - static VertexAdaptor create_vararg(Args &&...args) noexcept { + static VertexAdaptor create_vararg(Args&&... args) noexcept { return VertexAdaptor{vertex_inner::create_vararg(std::forward(args)...)}; } @@ -114,31 +113,31 @@ class VertexAdaptor { return impl_ ? VertexAdaptor(clone_vertex(*this).template as()) : VertexAdaptor{}; } - bool operator==(const VertexAdaptor &other) const noexcept { + bool operator==(const VertexAdaptor& other) const noexcept { return impl_ == other.impl_; } - bool operator!=(const VertexAdaptor &other) const noexcept { + bool operator!=(const VertexAdaptor& other) const noexcept { return impl_ != other.impl_; } - VertexAdaptor &set_rl_type(RLValueType type) noexcept { + VertexAdaptor& set_rl_type(RLValueType type) noexcept { impl_->rl_type = type; return *this; } - VertexAdaptor &set_location(const Location &location) noexcept { + VertexAdaptor& set_location(const Location& location) noexcept { impl_->location = location; return *this; } template - VertexAdaptor &set_location(VertexAdaptor other) noexcept { + VertexAdaptor& set_location(VertexAdaptor other) noexcept { impl_->location = other.impl_->location; return *this; } - VertexAdaptor &set_location_recursively(const Location &location) noexcept { + VertexAdaptor& set_location_recursively(const Location& location) noexcept { set_location(location); for (auto child : *impl_) { child.set_location_recursively(location); @@ -147,7 +146,7 @@ class VertexAdaptor { } template - VertexAdaptor &set_location_recursively(VertexAdaptor other) noexcept { + VertexAdaptor& set_location_recursively(VertexAdaptor other) noexcept { return set_location_recursively(other.impl_->location); } diff --git a/compiler/debug.cpp b/compiler/debug.cpp index 795ed12fd9..2199cc6701 100644 --- a/compiler/debug.cpp +++ b/compiler/debug.cpp @@ -6,13 +6,13 @@ #include +#include "common/wrappers/to_array.h" #include "compiler/compiler-core.h" #include "compiler/data/class-data.h" #include "compiler/data/function-data.h" #include "compiler/data/src-file.h" #include "compiler/type-hint.h" #include "compiler/vertex.h" -#include "common/wrappers/to_array.h" static std::map OPERATION_NAMES; @@ -23,182 +23,182 @@ static void fillOperationNames() { } std::string debugTokenName(TokenType t) { - constexpr auto name_pairs = vk::to_array>({ - {tok_empty, "tok_empty"}, - {tok_int_const, "tok_int_const"}, - {tok_int_const_sep, "tok_int_const_sep"}, - {tok_float_const, "tok_float_const"}, - {tok_float_const_sep, "tok_float_const_sep"}, - {tok_null, "tok_null"}, - {tok_nan, "tok_nan"}, - {tok_inf, "tok_inf"}, - {tok_inline_html, "tok_inline_html"}, - {tok_str, "tok_str"}, - {tok_str_begin, "tok_str_begin"}, - {tok_str_end, "tok_str_end"}, - {tok_str_skip_indent, "tok_str_skip_indent"}, - {tok_expr_begin, "tok_expr_begin"}, - {tok_expr_end, "tok_expr_end"}, - {tok_var_name, "tok_var_name"}, - {tok_func_name, "tok_func_name"}, - {tok_while, "tok_while"}, - {tok_for, "tok_for"}, - {tok_foreach, "tok_foreach"}, - {tok_if, "tok_if"}, - {tok_else, "tok_else"}, - {tok_elseif, "tok_elseif"}, - {tok_break, "tok_break"}, - {tok_continue, "tok_continue"}, - {tok_echo, "tok_echo"}, - {tok_dbg_echo, "tok_dbg_echo"}, - {tok_var_dump, "tok_var_dump"}, - {tok_function, "tok_function"}, - {tok_fn, "tok_fn"}, - {tok_varg, "tok_varg"}, - {tok_array, "tok_array"}, - {tok_tuple, "tok_tuple"}, - {tok_shape, "tok_shape"}, - {tok_as, "tok_as"}, - {tok_case, "tok_case"}, - {tok_switch, "tok_switch"}, - {tok_class, "tok_class"}, - {tok_interface, "tok_interface"}, - {tok_trait, "tok_trait"}, - {tok_extends, "tok_extends"}, - {tok_implements, "tok_implements"}, - {tok_namespace, "tok_namespace"}, - {tok_use, "tok_use"}, - {tok_const, "tok_const"}, - {tok_default, "tok_default"}, - {tok_do, "tok_do"}, - {tok_eval, "tok_eval"}, - {tok_return, "tok_return"}, - {tok_list, "tok_list"}, - {tok_include, "tok_include"}, - {tok_include_once, "tok_include_once"}, - {tok_require, "tok_require"}, - {tok_require_once, "tok_require_once"}, - {tok_print, "tok_print"}, - {tok_unset, "tok_unset"}, - {tok_var, "tok_var"}, - {tok_global, "tok_global"}, - {tok_static, "tok_static"}, - {tok_final, "tok_final"}, - {tok_abstract, "tok_abstract"}, - {tok_goto, "tok_goto"}, - {tok_isset, "tok_isset"}, - {tok_declare, "tok_declare"}, - {tok_eq1, "tok_eq1"}, - {tok_eq2, "tok_eq2"}, - {tok_eq3, "tok_eq3"}, - {tok_lt, "tok_lt"}, - {tok_gt, "tok_gt"}, - {tok_le, "tok_le"}, - {tok_ge, "tok_ge"}, - {tok_spaceship, "tok_spaceship"}, - {tok_neq2, "tok_neq2"}, - {tok_neq3, "tok_neq3"}, - {tok_neq_lg, "tok_neq_lg"}, - {tok_oppar, "tok_oppar"}, - {tok_clpar, "tok_clpar"}, - {tok_opbrc, "tok_opbrc"}, - {tok_clbrc, "tok_clbrc"}, - {tok_opbrk, "tok_opbrk"}, - {tok_clbrk, "tok_clbrk"}, - {tok_semicolon, "tok_semicolon"}, - {tok_comma, "tok_comma"}, - {tok_dot, "tok_dot"}, - {tok_colon, "tok_colon"}, - {tok_at, "tok_at"}, - {tok_pow, "tok_pow"}, - {tok_inc, "tok_inc"}, - {tok_dec, "tok_dec"}, - {tok_plus, "tok_plus"}, - {tok_minus, "tok_minus"}, - {tok_times, "tok_times"}, - {tok_divide, "tok_divide"}, - {tok_mod, "tok_mod"}, - {tok_and, "tok_and"}, - {tok_or, "tok_or"}, - {tok_xor, "tok_xor"}, - {tok_not, "tok_not"}, - {tok_log_not, "tok_log_not"}, - {tok_question, "tok_question"}, - {tok_null_coalesce, "tok_null_coalesce"}, - {tok_leq, "tok_leq"}, - {tok_shl, "tok_shl"}, - {tok_geq, "tok_geq"}, - {tok_shr, "tok_shr"}, - {tok_neq, "tok_neq"}, - {tok_set_add, "tok_set_add"}, - {tok_set_sub, "tok_set_sub"}, - {tok_set_mul, "tok_set_mul"}, - {tok_set_div, "tok_set_div"}, - {tok_set_mod, "tok_set_mod"}, - {tok_set_pow, "tok_set_pow"}, - {tok_set_and, "tok_set_and"}, - {tok_log_and, "tok_log_and"}, - {tok_log_and_let, "tok_log_and_let"}, - {tok_set_or, "tok_set_or"}, - {tok_log_or, "tok_log_or"}, - {tok_log_or_let, "tok_log_or_let"}, - {tok_set_xor, "tok_set_xor"}, - {tok_log_xor, "tok_log_xor"}, - {tok_log_xor_let, "tok_log_xor_let"}, - {tok_set_shr, "tok_set_shr"}, - {tok_set_shl, "tok_set_shl"}, - {tok_set_dot, "tok_set_dot"}, - {tok_set_null_coalesce, "tok_set_null_coalesce"}, - {tok_double_arrow, "tok_double_arrow"}, - {tok_double_colon, "tok_double_colon"}, - {tok_arrow, "tok_arrow"}, - {tok_class_c, "tok_class_c"}, - {tok_file_c, "tok_file_c"}, - {tok_file_relative_c, "tok_file_relative_c"}, - {tok_func_c, "tok_func_c"}, - {tok_dir_c, "tok_dir_c"}, - {tok_line_c, "tok_line_c"}, - {tok_method_c, "tok_method_c"}, - {tok_namespace_c, "tok_namespace_c"}, - {tok_int, "tok_int"}, - {tok_float, "tok_float"}, - {tok_double, "tok_double"}, - {tok_string, "tok_string"}, - {tok_object, "tok_object"}, - {tok_callable, "tok_callable"}, - {tok_bool, "tok_bool"}, - {tok_boolean, "tok_boolean"}, - {tok_void, "tok_void"}, - {tok_mixed, "tok_mixed"}, - {tok_conv_int, "tok_conv_int"}, - {tok_conv_float, "tok_conv_float"}, - {tok_conv_string, "tok_conv_string"}, - {tok_conv_array, "tok_conv_array"}, - {tok_conv_object, "tok_conv_object"}, - {tok_conv_bool, "tok_conv_bool"}, - {tok_false, "tok_false"}, - {tok_true, "tok_true"}, - {tok_define, "tok_define"}, - {tok_defined, "tok_defined"}, - {tok_triple_colon, "tok_triple_colon"}, - {tok_throw, "tok_throw"}, - {tok_new, "tok_new"}, - {tok_try, "tok_try"}, - {tok_catch, "tok_catch"}, - {tok_public, "tok_public"}, - {tok_private, "tok_private"}, - {tok_protected, "tok_protected"}, - {tok_phpdoc, "tok_phpdoc"}, - {tok_commentTs, "tok_commentTs"}, - {tok_clone, "tok_clone"}, - {tok_instanceof, "tok_instanceof"}, - {tok_end, "tok_end"}, + constexpr auto name_pairs = vk::to_array>({ + {tok_empty, "tok_empty"}, + {tok_int_const, "tok_int_const"}, + {tok_int_const_sep, "tok_int_const_sep"}, + {tok_float_const, "tok_float_const"}, + {tok_float_const_sep, "tok_float_const_sep"}, + {tok_null, "tok_null"}, + {tok_nan, "tok_nan"}, + {tok_inf, "tok_inf"}, + {tok_inline_html, "tok_inline_html"}, + {tok_str, "tok_str"}, + {tok_str_begin, "tok_str_begin"}, + {tok_str_end, "tok_str_end"}, + {tok_str_skip_indent, "tok_str_skip_indent"}, + {tok_expr_begin, "tok_expr_begin"}, + {tok_expr_end, "tok_expr_end"}, + {tok_var_name, "tok_var_name"}, + {tok_func_name, "tok_func_name"}, + {tok_while, "tok_while"}, + {tok_for, "tok_for"}, + {tok_foreach, "tok_foreach"}, + {tok_if, "tok_if"}, + {tok_else, "tok_else"}, + {tok_elseif, "tok_elseif"}, + {tok_break, "tok_break"}, + {tok_continue, "tok_continue"}, + {tok_echo, "tok_echo"}, + {tok_dbg_echo, "tok_dbg_echo"}, + {tok_var_dump, "tok_var_dump"}, + {tok_function, "tok_function"}, + {tok_fn, "tok_fn"}, + {tok_varg, "tok_varg"}, + {tok_array, "tok_array"}, + {tok_tuple, "tok_tuple"}, + {tok_shape, "tok_shape"}, + {tok_as, "tok_as"}, + {tok_case, "tok_case"}, + {tok_switch, "tok_switch"}, + {tok_class, "tok_class"}, + {tok_interface, "tok_interface"}, + {tok_trait, "tok_trait"}, + {tok_extends, "tok_extends"}, + {tok_implements, "tok_implements"}, + {tok_namespace, "tok_namespace"}, + {tok_use, "tok_use"}, + {tok_const, "tok_const"}, + {tok_default, "tok_default"}, + {tok_do, "tok_do"}, + {tok_eval, "tok_eval"}, + {tok_return, "tok_return"}, + {tok_list, "tok_list"}, + {tok_include, "tok_include"}, + {tok_include_once, "tok_include_once"}, + {tok_require, "tok_require"}, + {tok_require_once, "tok_require_once"}, + {tok_print, "tok_print"}, + {tok_unset, "tok_unset"}, + {tok_var, "tok_var"}, + {tok_global, "tok_global"}, + {tok_static, "tok_static"}, + {tok_final, "tok_final"}, + {tok_abstract, "tok_abstract"}, + {tok_goto, "tok_goto"}, + {tok_isset, "tok_isset"}, + {tok_declare, "tok_declare"}, + {tok_eq1, "tok_eq1"}, + {tok_eq2, "tok_eq2"}, + {tok_eq3, "tok_eq3"}, + {tok_lt, "tok_lt"}, + {tok_gt, "tok_gt"}, + {tok_le, "tok_le"}, + {tok_ge, "tok_ge"}, + {tok_spaceship, "tok_spaceship"}, + {tok_neq2, "tok_neq2"}, + {tok_neq3, "tok_neq3"}, + {tok_neq_lg, "tok_neq_lg"}, + {tok_oppar, "tok_oppar"}, + {tok_clpar, "tok_clpar"}, + {tok_opbrc, "tok_opbrc"}, + {tok_clbrc, "tok_clbrc"}, + {tok_opbrk, "tok_opbrk"}, + {tok_clbrk, "tok_clbrk"}, + {tok_semicolon, "tok_semicolon"}, + {tok_comma, "tok_comma"}, + {tok_dot, "tok_dot"}, + {tok_colon, "tok_colon"}, + {tok_at, "tok_at"}, + {tok_pow, "tok_pow"}, + {tok_inc, "tok_inc"}, + {tok_dec, "tok_dec"}, + {tok_plus, "tok_plus"}, + {tok_minus, "tok_minus"}, + {tok_times, "tok_times"}, + {tok_divide, "tok_divide"}, + {tok_mod, "tok_mod"}, + {tok_and, "tok_and"}, + {tok_or, "tok_or"}, + {tok_xor, "tok_xor"}, + {tok_not, "tok_not"}, + {tok_log_not, "tok_log_not"}, + {tok_question, "tok_question"}, + {tok_null_coalesce, "tok_null_coalesce"}, + {tok_leq, "tok_leq"}, + {tok_shl, "tok_shl"}, + {tok_geq, "tok_geq"}, + {tok_shr, "tok_shr"}, + {tok_neq, "tok_neq"}, + {tok_set_add, "tok_set_add"}, + {tok_set_sub, "tok_set_sub"}, + {tok_set_mul, "tok_set_mul"}, + {tok_set_div, "tok_set_div"}, + {tok_set_mod, "tok_set_mod"}, + {tok_set_pow, "tok_set_pow"}, + {tok_set_and, "tok_set_and"}, + {tok_log_and, "tok_log_and"}, + {tok_log_and_let, "tok_log_and_let"}, + {tok_set_or, "tok_set_or"}, + {tok_log_or, "tok_log_or"}, + {tok_log_or_let, "tok_log_or_let"}, + {tok_set_xor, "tok_set_xor"}, + {tok_log_xor, "tok_log_xor"}, + {tok_log_xor_let, "tok_log_xor_let"}, + {tok_set_shr, "tok_set_shr"}, + {tok_set_shl, "tok_set_shl"}, + {tok_set_dot, "tok_set_dot"}, + {tok_set_null_coalesce, "tok_set_null_coalesce"}, + {tok_double_arrow, "tok_double_arrow"}, + {tok_double_colon, "tok_double_colon"}, + {tok_arrow, "tok_arrow"}, + {tok_class_c, "tok_class_c"}, + {tok_file_c, "tok_file_c"}, + {tok_file_relative_c, "tok_file_relative_c"}, + {tok_func_c, "tok_func_c"}, + {tok_dir_c, "tok_dir_c"}, + {tok_line_c, "tok_line_c"}, + {tok_method_c, "tok_method_c"}, + {tok_namespace_c, "tok_namespace_c"}, + {tok_int, "tok_int"}, + {tok_float, "tok_float"}, + {tok_double, "tok_double"}, + {tok_string, "tok_string"}, + {tok_object, "tok_object"}, + {tok_callable, "tok_callable"}, + {tok_bool, "tok_bool"}, + {tok_boolean, "tok_boolean"}, + {tok_void, "tok_void"}, + {tok_mixed, "tok_mixed"}, + {tok_conv_int, "tok_conv_int"}, + {tok_conv_float, "tok_conv_float"}, + {tok_conv_string, "tok_conv_string"}, + {tok_conv_array, "tok_conv_array"}, + {tok_conv_object, "tok_conv_object"}, + {tok_conv_bool, "tok_conv_bool"}, + {tok_false, "tok_false"}, + {tok_true, "tok_true"}, + {tok_define, "tok_define"}, + {tok_defined, "tok_defined"}, + {tok_triple_colon, "tok_triple_colon"}, + {tok_throw, "tok_throw"}, + {tok_new, "tok_new"}, + {tok_try, "tok_try"}, + {tok_catch, "tok_catch"}, + {tok_public, "tok_public"}, + {tok_private, "tok_private"}, + {tok_protected, "tok_protected"}, + {tok_phpdoc, "tok_phpdoc"}, + {tok_commentTs, "tok_commentTs"}, + {tok_clone, "tok_clone"}, + {tok_instanceof, "tok_instanceof"}, + {tok_end, "tok_end"}, }); // this assert will fail whether TokenType entry is added (or removed); // how to fix: add {$newtok, "$newtok"} to the name_pairs // hint: insert that entry into the right position - static_assert(name_pairs.size() - 1 == tok_end,"name_pairs needs to be updated"); + static_assert(name_pairs.size() - 1 == tok_end, "name_pairs needs to be updated"); #if __cplusplus > 201703 static_assert(std::is_sorted(name_pairs.begin(), name_pairs.end()), "name_pairs should be sorted"); @@ -222,47 +222,46 @@ static std::string debugOperationName(Operation o) { return OPERATION_NAMES[o]; } - static std::string debugVertexMore(VertexPtr v) { switch (v->type()) { - case op_alloc: - return "new " + v.as()->allocated_class_name; - case op_func_call: - return std::string(v->extra_type == op_ex_func_call_arrow ? "->" : "") + - (v.as()->func_id ? v.as()->func_id->as_human_readable(false) : v->get_string()) + "()"; - case op_func_name: - return v->get_string(); - case op_function: - return v.as()->func_id->as_human_readable(); - case op_func_param: - return v.as()->type_hint ? v.as()->type_hint->as_human_readable() : ""; - case op_lambda: - return v.as()->func_id->as_human_readable(); - case op_callback_of_builtin: - return v->get_string(); - case op_var: - return "$" + v->get_string(); - case op_instance_prop: - return "...->" + v->get_string(); - case op_string: - return v->get_string() == "\n" ? "\"\\n\"" : "\"" + v->get_string() + "\""; - case op_int_const: - return v->get_string(); - case op_seq: - case op_array: - return std::to_string(v->size()); - case op_phpdoc_var: - return "@var for " + v.as()->var()->str_val; - case op_ffi_php2c_conv: - return "to " + v.as()->c_type->as_human_readable(); - case op_ffi_c2php_conv: - return "to " + v.as()->php_type->as_human_readable(); - default: - return ""; + case op_alloc: + return "new " + v.as()->allocated_class_name; + case op_func_call: + return std::string(v->extra_type == op_ex_func_call_arrow ? "->" : "") + + (v.as()->func_id ? v.as()->func_id->as_human_readable(false) : v->get_string()) + "()"; + case op_func_name: + return v->get_string(); + case op_function: + return v.as()->func_id->as_human_readable(); + case op_func_param: + return v.as()->type_hint ? v.as()->type_hint->as_human_readable() : ""; + case op_lambda: + return v.as()->func_id->as_human_readable(); + case op_callback_of_builtin: + return v->get_string(); + case op_var: + return "$" + v->get_string(); + case op_instance_prop: + return "...->" + v->get_string(); + case op_string: + return v->get_string() == "\n" ? "\"\\n\"" : "\"" + v->get_string() + "\""; + case op_int_const: + return v->get_string(); + case op_seq: + case op_array: + return std::to_string(v->size()); + case op_phpdoc_var: + return "@var for " + v.as()->var()->str_val; + case op_ffi_php2c_conv: + return "to " + v.as()->c_type->as_human_readable(); + case op_ffi_c2php_conv: + return "to " + v.as()->php_type->as_human_readable(); + default: + return ""; } } -static void debugVertexTree(VertexPtr root, int level, std::string &append) { +static void debugVertexTree(VertexPtr root, int level, std::string& append) { for (int i = 0; i < level; ++i) { append += " "; } diff --git a/compiler/ffi/c_parser/lexer.h b/compiler/ffi/c_parser/lexer.h index 4b789cc318..246f35e9aa 100644 --- a/compiler/ffi/c_parser/lexer.h +++ b/compiler/ffi/c_parser/lexer.h @@ -8,10 +8,10 @@ #undef YY_DECL #define YY_DECL ffi::YYParser::symbol_type ffi::Lexer::get_next_token() +#include "common/algorithms/contains.h" #include "compiler/ffi/c_parser/location.h" #include "compiler/ffi/c_parser/string-span.h" #include "compiler/ffi/c_parser/yy_parser_generated.hpp" -#include "common/algorithms/contains.h" #include @@ -19,21 +19,23 @@ namespace ffi { class Lexer { public: - explicit Lexer(const FFITypedefs &typedefs, const std::string& input) - : p_{input.c_str()} - , input_start_{input.c_str()} - , input_end_{input.c_str() + input.length()} - , typedefs_{typedefs} { + explicit Lexer(const FFITypedefs& typedefs, const std::string& input) + : p_{input.c_str()}, + input_start_{input.c_str()}, + input_end_{input.c_str() + input.length()}, + typedefs_{typedefs} { reset_comment(); } - int get_next_token(YYParser::semantic_type *sym, YYParser::location_type *loc) { + int get_next_token(YYParser::semantic_type* sym, YYParser::location_type* loc) { auto tok = get_next_token_impl(sym, loc); offset_ = p_ - input_start_; return tok; } - string_span get_comment() const noexcept { return comment_; } + string_span get_comment() const noexcept { + return comment_; + } void reset_comment() noexcept { comment_.data_ = nullptr; @@ -41,11 +43,11 @@ class Lexer { } private: - const char *p_; - const char *input_start_; - const char *input_end_; + const char* p_; + const char* input_start_; + const char* input_end_; int64_t offset_ = 0; - const FFITypedefs &typedefs_; + const FFITypedefs& typedefs_; using token_type = YYParser::token_type; @@ -61,9 +63,9 @@ class Lexer { // Ragel args explanation: // -C is for C/C++ output format; // -G2 generates a goto-based FSM, 2 is like optimization level (G0 code is more compact, but slower) - int get_next_token_impl(YYParser::semantic_type *sym, YYParser::location_type *loc); + int get_next_token_impl(YYParser::semantic_type* sym, YYParser::location_type* loc); - void set_location(int tok, const char *token_begin, const char *token_end, YYParser::location_type *loc) { + void set_location(int tok, const char* token_begin, const char* token_end, YYParser::location_type* loc) { if (tok == token_type::C_TOKEN_END) { loc->begin = input_end_ - input_start_; loc->end = loc->begin; @@ -73,17 +75,17 @@ class Lexer { } } - int int_constant(YYParser::semantic_type *sym, string_span text) { + int int_constant(YYParser::semantic_type* sym, string_span text) { sym->str_ = text; return token_type::C_TOKEN_INT_CONSTANT; } - int float_constant(YYParser::semantic_type *sym, string_span text) { + int float_constant(YYParser::semantic_type* sym, string_span text) { sym->str_ = text; return token_type::C_TOKEN_FLOAT_CONSTANT; } - int typename_or_identifier(YYParser::semantic_type *sym, string_span text) { + int typename_or_identifier(YYParser::semantic_type* sym, string_span text) { sym->str_ = text; if (vk::contains(typedefs_, text.to_string())) { return token_type::C_TOKEN_TYPEDEF_NAME; diff --git a/compiler/ffi/c_parser/lexer_generated.cpp b/compiler/ffi/c_parser/lexer_generated.cpp index c7e4af583a..7825e97e8f 100644 --- a/compiler/ffi/c_parser/lexer_generated.cpp +++ b/compiler/ffi/c_parser/lexer_generated.cpp @@ -7,19 +7,17 @@ #include "compiler/ffi/c_parser/lexer.h" #if defined(__GNUC__) && (__GNUC__ >= 7) -# pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" #elif defined(__clang__) -# pragma clang diagnostic ignored "-Wunused-variable" +#pragma clang diagnostic ignored "-Wunused-variable" #elif defined(__has_warning) -# if __has_warning("-Wimplicit-fallthrough") -# pragma clang diagnostic ignored "-Wimplicit-fallthrough" -# endif +#if __has_warning("-Wimplicit-fallthrough") +#pragma clang diagnostic ignored "-Wimplicit-fallthrough" +#endif #endif - #line 18 "lexer.rl" - #line 24 "lexer_generated.cpp" static const int lexer_start = 14; static const int lexer_error = 0; @@ -27,3075 +25,4371 @@ static const int lexer_error = 0; static const int lexer_en_multiline_comment = 12; static const int lexer_en_main = 14; - #line 20 "lexer.rl" -int ffi::Lexer::get_next_token_impl(YYParser::semantic_type *sym, YYParser::location_type *loc) { +int ffi::Lexer::get_next_token_impl(YYParser::semantic_type* sym, YYParser::location_type* loc) { int result = token_type::C_TOKEN_END; // ragel-related variables that we initialize ourselves p_ = input_start_ + offset_; - const char *pe = input_end_; - const char *eof = pe; + const char* pe = input_end_; + const char* eof = pe; // ragel-related variables that are initialized in the generated init() section below int cs, act; const char *ts, *te; - + #line 46 "lexer_generated.cpp" - { - cs = lexer_start; - ts = 0; - te = 0; - act = 0; - } + { + cs = lexer_start; + ts = 0; + te = 0; + act = 0; + } #line 33 "lexer.rl" - const auto token_text = [&ts, &te]() { - return string_span{ts, te}; - }; + const auto token_text = [&ts, &te]() { return string_span{ts, te}; }; - #line 115 "lexer.rl" - - #line 65 "lexer_generated.cpp" - { - if ( ( p_) == pe ) - goto _test_eof; - switch ( cs ) - { -tr3: + { + if ((p_) == pe) + goto _test_eof; + switch (cs) { + tr3: #line 108 "lexer.rl" - {te = ( p_)+1;{ result = token_type::C_TOKEN_ELLIPSIS; {( p_)++; cs = 14; goto _out;} }} - goto st14; -tr4: + { + te = (p_) + 1; + { + result = token_type::C_TOKEN_ELLIPSIS; + { + (p_)++; + cs = 14; + goto _out; + } + } + } + goto st14; + tr4: #line 1 "NONE" - { switch( act ) { - case 4: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_AUTO; {( p_)++; cs = 14; goto _out;} } - break; - case 5: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_REGISTER; {( p_)++; cs = 14; goto _out;} } - break; - case 6: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_EXTERN; {( p_)++; cs = 14; goto _out;} } - break; - case 7: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_ENUM; {( p_)++; cs = 14; goto _out;} } - break; - case 8: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_STATIC; {( p_)++; cs = 14; goto _out;} } - break; - case 9: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_INLINE; {( p_)++; cs = 14; goto _out;} } - break; - case 10: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_TYPEDEF; {( p_)++; cs = 14; goto _out;} } - break; - case 11: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_CONST; {( p_)++; cs = 14; goto _out;} } - break; - case 12: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_VOLATILE; {( p_)++; cs = 14; goto _out;} } - break; - case 13: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_VOID; {( p_)++; cs = 14; goto _out;} } - break; - case 14: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_FLOAT; {( p_)++; cs = 14; goto _out;} } - break; - case 15: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_DOUBLE; {( p_)++; cs = 14; goto _out;} } - break; - case 16: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_CHAR; {( p_)++; cs = 14; goto _out;} } - break; - case 17: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_BOOL; {( p_)++; cs = 14; goto _out;} } - break; - case 19: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_INT8; {( p_)++; cs = 14; goto _out;} } - break; - case 20: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_INT16; {( p_)++; cs = 14; goto _out;} } - break; - case 21: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_INT32; {( p_)++; cs = 14; goto _out;} } - break; - case 22: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_INT64; {( p_)++; cs = 14; goto _out;} } - break; - case 23: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_UINT8; {( p_)++; cs = 14; goto _out;} } - break; - case 24: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_UINT16; {( p_)++; cs = 14; goto _out;} } - break; - case 25: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_UINT32; {( p_)++; cs = 14; goto _out;} } - break; - case 26: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_UINT64; {( p_)++; cs = 14; goto _out;} } - break; - case 27: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_INTPTR_T; {( p_)++; cs = 14; goto _out;} } - break; - case 28: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_UINTPTR_T; {( p_)++; cs = 14; goto _out;} } - break; - case 29: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_SIZE_T; {( p_)++; cs = 14; goto _out;} } - break; - case 30: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_LONG; {( p_)++; cs = 14; goto _out;} } - break; - case 31: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_SHORT; {( p_)++; cs = 14; goto _out;} } - break; - case 32: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_UNSIGNED; {( p_)++; cs = 14; goto _out;} } - break; - case 33: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_UNION; {( p_)++; cs = 14; goto _out;} } - break; - case 34: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_SIGNED; {( p_)++; cs = 14; goto _out;} } - break; - case 35: - {{( p_) = ((te))-1;} result = token_type::C_TOKEN_STRUCT; {( p_)++; cs = 14; goto _out;} } - break; - case 49: - {{( p_) = ((te))-1;} result = int_constant(sym, token_text()); {( p_)++; cs = 14; goto _out;} } - break; - case 50: - {{( p_) = ((te))-1;} result = float_constant(sym, token_text()); {( p_)++; cs = 14; goto _out;} } - break; - case 51: - {{( p_) = ((te))-1;} result = typename_or_identifier(sym, token_text()); {( p_)++; cs = 14; goto _out;} } - break; - } - } - goto st14; -tr7: + { + switch (act) { + case 4: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_AUTO; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 5: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_REGISTER; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 6: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_EXTERN; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 7: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_ENUM; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 8: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_STATIC; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 9: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_INLINE; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 10: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_TYPEDEF; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 11: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_CONST; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 12: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_VOLATILE; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 13: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_VOID; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 14: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_FLOAT; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 15: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_DOUBLE; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 16: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_CHAR; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 17: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_BOOL; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 19: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_INT8; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 20: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_INT16; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 21: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_INT32; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 22: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_INT64; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 23: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_UINT8; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 24: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_UINT16; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 25: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_UINT32; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 26: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_UINT64; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 27: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_INTPTR_T; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 28: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_UINTPTR_T; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 29: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_SIZE_T; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 30: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_LONG; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 31: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_SHORT; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 32: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_UNSIGNED; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 33: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_UNION; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 34: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_SIGNED; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 35: { + { + (p_) = ((te)) - 1; + } + result = token_type::C_TOKEN_STRUCT; + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 49: { + { + (p_) = ((te)) - 1; + } + result = int_constant(sym, token_text()); + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 50: { + { + (p_) = ((te)) - 1; + } + result = float_constant(sym, token_text()); + { + (p_)++; + cs = 14; + goto _out; + } + } break; + case 51: { + { + (p_) = ((te)) - 1; + } + result = typename_or_identifier(sym, token_text()); + { + (p_)++; + cs = 14; + goto _out; + } + } break; + } + } + goto st14; + tr7: #line 60 "lexer.rl" - {te = ( p_)+1;{ {goto st12;} }} - goto st14; -tr9: + { + te = (p_) + 1; + { + { goto st12; } + } + } + goto st14; + tr9: #line 59 "lexer.rl" - {te = ( p_)+1;{ comment_ = token_text(); }} - goto st14; -tr10: + { + te = (p_) + 1; + { comment_ = token_text(); } + } + goto st14; + tr10: #line 110 "lexer.rl" - {{( p_) = ((te))-1;}{ result = int_constant(sym, token_text()); {( p_)++; cs = 14; goto _out;} }} - goto st14; -tr14: + { + { (p_) = ((te)) - 1; } + { + result = int_constant(sym, token_text()); + { + (p_)++; + cs = 14; + goto _out; + } + } + } + goto st14; + tr14: #line 110 "lexer.rl" - {te = ( p_)+1;{ result = int_constant(sym, token_text()); {( p_)++; cs = 14; goto _out;} }} - goto st14; -tr20: + { + te = (p_) + 1; + { + result = int_constant(sym, token_text()); + { + (p_)++; + cs = 14; + goto _out; + } + } + } + goto st14; + tr20: #line 57 "lexer.rl" - {te = ( p_)+1;{ /* ignore */ }} - goto st14; -tr21: + { + te = (p_) + 1; + { /* ignore */ + } + } + goto st14; + tr21: #line 100 "lexer.rl" - {te = ( p_)+1;{ result = token_type::C_TOKEN_LPAREN; {( p_)++; cs = 14; goto _out;} }} - goto st14; -tr22: + { + te = (p_) + 1; + { + result = token_type::C_TOKEN_LPAREN; + { + (p_)++; + cs = 14; + goto _out; + } + } + } + goto st14; + tr22: #line 101 "lexer.rl" - {te = ( p_)+1;{ result = token_type::C_TOKEN_RPAREN; {( p_)++; cs = 14; goto _out;} }} - goto st14; -tr23: + { + te = (p_) + 1; + { + result = token_type::C_TOKEN_RPAREN; + { + (p_)++; + cs = 14; + goto _out; + } + } + } + goto st14; + tr23: #line 105 "lexer.rl" - {te = ( p_)+1;{ result = token_type::C_TOKEN_MUL; {( p_)++; cs = 14; goto _out;} }} - goto st14; -tr24: + { + te = (p_) + 1; + { + result = token_type::C_TOKEN_MUL; + { + (p_)++; + cs = 14; + goto _out; + } + } + } + goto st14; + tr24: #line 96 "lexer.rl" - {te = ( p_)+1;{ result = token_type::C_TOKEN_PLUS; {( p_)++; cs = 14; goto _out;} }} - goto st14; -tr25: + { + te = (p_) + 1; + { + result = token_type::C_TOKEN_PLUS; + { + (p_)++; + cs = 14; + goto _out; + } + } + } + goto st14; + tr25: #line 104 "lexer.rl" - {te = ( p_)+1;{ result = token_type::C_TOKEN_COMMA; {( p_)++; cs = 14; goto _out;} }} - goto st14; -tr26: + { + te = (p_) + 1; + { + result = token_type::C_TOKEN_COMMA; + { + (p_)++; + cs = 14; + goto _out; + } + } + } + goto st14; + tr26: #line 95 "lexer.rl" - {te = ( p_)+1;{ result = token_type::C_TOKEN_MINUS; {( p_)++; cs = 14; goto _out;} }} - goto st14; -tr31: + { + te = (p_) + 1; + { + result = token_type::C_TOKEN_MINUS; + { + (p_)++; + cs = 14; + goto _out; + } + } + } + goto st14; + tr31: #line 97 "lexer.rl" - {te = ( p_)+1;{ result = token_type::C_TOKEN_SEMICOLON; {( p_)++; cs = 14; goto _out;} }} - goto st14; -tr32: + { + te = (p_) + 1; + { + result = token_type::C_TOKEN_SEMICOLON; + { + (p_)++; + cs = 14; + goto _out; + } + } + } + goto st14; + tr32: #line 106 "lexer.rl" - {te = ( p_)+1;{ result = token_type::C_TOKEN_EQUAL; {( p_)++; cs = 14; goto _out;} }} - goto st14; -tr34: + { + te = (p_) + 1; + { + result = token_type::C_TOKEN_EQUAL; + { + (p_)++; + cs = 14; + goto _out; + } + } + } + goto st14; + tr34: #line 102 "lexer.rl" - {te = ( p_)+1;{ result = token_type::C_TOKEN_LBRACKET; {( p_)++; cs = 14; goto _out;} }} - goto st14; -tr35: + { + te = (p_) + 1; + { + result = token_type::C_TOKEN_LBRACKET; + { + (p_)++; + cs = 14; + goto _out; + } + } + } + goto st14; + tr35: #line 103 "lexer.rl" - {te = ( p_)+1;{ result = token_type::C_TOKEN_RBRACKET; {( p_)++; cs = 14; goto _out;} }} - goto st14; -tr49: + { + te = (p_) + 1; + { + result = token_type::C_TOKEN_RBRACKET; + { + (p_)++; + cs = 14; + goto _out; + } + } + } + goto st14; + tr49: #line 98 "lexer.rl" - {te = ( p_)+1;{ result = token_type::C_TOKEN_LBRACE; {( p_)++; cs = 14; goto _out;} }} - goto st14; -tr50: + { + te = (p_) + 1; + { + result = token_type::C_TOKEN_LBRACE; + { + (p_)++; + cs = 14; + goto _out; + } + } + } + goto st14; + tr50: #line 99 "lexer.rl" - {te = ( p_)+1;{ result = token_type::C_TOKEN_RBRACE; {( p_)++; cs = 14; goto _out;} }} - goto st14; -tr51: + { + te = (p_) + 1; + { + result = token_type::C_TOKEN_RBRACE; + { + (p_)++; + cs = 14; + goto _out; + } + } + } + goto st14; + tr51: #line 111 "lexer.rl" - {te = ( p_);( p_)--;{ result = float_constant(sym, token_text()); {( p_)++; cs = 14; goto _out;} }} - goto st14; -tr52: + { + te = (p_); + (p_)--; + { + result = float_constant(sym, token_text()); + { + (p_)++; + cs = 14; + goto _out; + } + } + } + goto st14; + tr52: #line 111 "lexer.rl" - {te = ( p_)+1;{ result = float_constant(sym, token_text()); {( p_)++; cs = 14; goto _out;} }} - goto st14; -tr53: + { + te = (p_) + 1; + { + result = float_constant(sym, token_text()); + { + (p_)++; + cs = 14; + goto _out; + } + } + } + goto st14; + tr53: #line 110 "lexer.rl" - {te = ( p_);( p_)--;{ result = int_constant(sym, token_text()); {( p_)++; cs = 14; goto _out;} }} - goto st14; -tr58: + { + te = (p_); + (p_)--; + { + result = int_constant(sym, token_text()); + { + (p_)++; + cs = 14; + goto _out; + } + } + } + goto st14; + tr58: #line 113 "lexer.rl" - {te = ( p_);( p_)--;{ result = typename_or_identifier(sym, token_text()); {( p_)++; cs = 14; goto _out;} }} - goto st14; -tr95: + { + te = (p_); + (p_)--; + { + result = typename_or_identifier(sym, token_text()); + { + (p_)++; + cs = 14; + goto _out; + } + } + } + goto st14; + tr95: #line 76 "lexer.rl" - {te = ( p_);( p_)--;{ result = token_type::C_TOKEN_INT; {( p_)++; cs = 14; goto _out;} }} - goto st14; -st14: + { + te = (p_); + (p_)--; + { + result = token_type::C_TOKEN_INT; + { + (p_)++; + cs = 14; + goto _out; + } + } + } + goto st14; + st14: #line 1 "NONE" - {ts = 0;} - if ( ++( p_) == pe ) - goto _test_eof14; -case 14: + { + ts = 0; + } + if (++(p_) == pe) + goto _test_eof14; + case 14: #line 1 "NONE" - {ts = ( p_);} + { + ts = (p_); + } #line 279 "lexer_generated.cpp" - switch( (*( p_)) ) { - case 32: goto tr20; - case 40: goto tr21; - case 41: goto tr22; - case 42: goto tr23; - case 43: goto tr24; - case 44: goto tr25; - case 45: goto tr26; - case 46: goto st1; - case 47: goto st5; - case 48: goto tr29; - case 59: goto tr31; - case 61: goto tr32; - case 91: goto tr34; - case 93: goto tr35; - case 95: goto tr33; - case 97: goto st23; - case 98: goto st26; - case 99: goto st29; - case 100: goto st35; - case 101: goto st40; - case 102: goto st47; - case 105: goto st51; - case 108: goto st72; - case 114: goto st75; - case 115: goto st82; - case 116: goto st100; - case 117: goto st106; - case 118: goto st133; - case 123: goto tr49; - case 125: goto tr50; - } - if ( (*( p_)) < 49 ) { - if ( 9 <= (*( p_)) && (*( p_)) <= 12 ) - goto tr20; - } else if ( (*( p_)) > 57 ) { - if ( (*( p_)) > 90 ) { - if ( 103 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else if ( (*( p_)) >= 65 ) - goto tr33; - } else - goto tr30; - goto st0; -st0: -cs = 0; - goto _out; -st1: - if ( ++( p_) == pe ) - goto _test_eof1; -case 1: - if ( (*( p_)) == 46 ) - goto st2; - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr2; - goto st0; -st2: - if ( ++( p_) == pe ) - goto _test_eof2; -case 2: - if ( (*( p_)) == 46 ) - goto tr3; - goto st0; -tr2: + switch ((*(p_))) { + case 32: + goto tr20; + case 40: + goto tr21; + case 41: + goto tr22; + case 42: + goto tr23; + case 43: + goto tr24; + case 44: + goto tr25; + case 45: + goto tr26; + case 46: + goto st1; + case 47: + goto st5; + case 48: + goto tr29; + case 59: + goto tr31; + case 61: + goto tr32; + case 91: + goto tr34; + case 93: + goto tr35; + case 95: + goto tr33; + case 97: + goto st23; + case 98: + goto st26; + case 99: + goto st29; + case 100: + goto st35; + case 101: + goto st40; + case 102: + goto st47; + case 105: + goto st51; + case 108: + goto st72; + case 114: + goto st75; + case 115: + goto st82; + case 116: + goto st100; + case 117: + goto st106; + case 118: + goto st133; + case 123: + goto tr49; + case 125: + goto tr50; + } + if ((*(p_)) < 49) { + if (9 <= (*(p_)) && (*(p_)) <= 12) + goto tr20; + } else if ((*(p_)) > 57) { + if ((*(p_)) > 90) { + if (103 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else if ((*(p_)) >= 65) + goto tr33; + } else + goto tr30; + goto st0; + st0: + cs = 0; + goto _out; + st1: + if (++(p_) == pe) + goto _test_eof1; + case 1: + if ((*(p_)) == 46) + goto st2; + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr2; + goto st0; + st2: + if (++(p_) == pe) + goto _test_eof2; + case 2: + if ((*(p_)) == 46) + goto tr3; + goto st0; + tr2: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 111 "lexer.rl" - {act = 50;} - goto st15; -st15: - if ( ++( p_) == pe ) - goto _test_eof15; -case 15: + { act = 50; } + goto st15; + st15: + if (++(p_) == pe) + goto _test_eof15; + case 15: #line 353 "lexer_generated.cpp" - switch( (*( p_)) ) { - case 69: goto st3; - case 70: goto tr52; - case 76: goto tr52; - case 101: goto st3; - case 102: goto tr52; - case 108: goto tr52; - } - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr2; - goto tr51; -st3: - if ( ++( p_) == pe ) - goto _test_eof3; -case 3: - switch( (*( p_)) ) { - case 43: goto st4; - case 45: goto st4; - } - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto st16; - goto tr4; -st4: - if ( ++( p_) == pe ) - goto _test_eof4; -case 4: - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto st16; - goto tr4; -st16: - if ( ++( p_) == pe ) - goto _test_eof16; -case 16: - switch( (*( p_)) ) { - case 70: goto tr52; - case 76: goto tr52; - case 102: goto tr52; - case 108: goto tr52; - } - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto st16; - goto tr51; -st5: - if ( ++( p_) == pe ) - goto _test_eof5; -case 5: - switch( (*( p_)) ) { - case 42: goto tr7; - case 47: goto st6; - } - goto st0; -st6: - if ( ++( p_) == pe ) - goto _test_eof6; -case 6: - if ( (*( p_)) == 10 ) - goto tr9; - goto st6; -tr29: + switch ((*(p_))) { + case 69: + goto st3; + case 70: + goto tr52; + case 76: + goto tr52; + case 101: + goto st3; + case 102: + goto tr52; + case 108: + goto tr52; + } + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr2; + goto tr51; + st3: + if (++(p_) == pe) + goto _test_eof3; + case 3: + switch ((*(p_))) { + case 43: + goto st4; + case 45: + goto st4; + } + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto st16; + goto tr4; + st4: + if (++(p_) == pe) + goto _test_eof4; + case 4: + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto st16; + goto tr4; + st16: + if (++(p_) == pe) + goto _test_eof16; + case 16: + switch ((*(p_))) { + case 70: + goto tr52; + case 76: + goto tr52; + case 102: + goto tr52; + case 108: + goto tr52; + } + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto st16; + goto tr51; + st5: + if (++(p_) == pe) + goto _test_eof5; + case 5: + switch ((*(p_))) { + case 42: + goto tr7; + case 47: + goto st6; + } + goto st0; + st6: + if (++(p_) == pe) + goto _test_eof6; + case 6: + if ((*(p_)) == 10) + goto tr9; + goto st6; + tr29: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 110 "lexer.rl" - {act = 49;} - goto st17; -st17: - if ( ++( p_) == pe ) - goto _test_eof17; -case 17: + { act = 49; } + goto st17; + st17: + if (++(p_) == pe) + goto _test_eof17; + case 17: #line 422 "lexer_generated.cpp" - switch( (*( p_)) ) { - case 46: goto tr2; - case 69: goto st3; - case 76: goto st8; - case 85: goto st10; - case 88: goto st11; - case 101: goto st3; - case 108: goto st8; - case 117: goto st10; - case 120: goto st11; - } - if ( (*( p_)) > 55 ) { - if ( 56 <= (*( p_)) && (*( p_)) <= 57 ) - goto st7; - } else if ( (*( p_)) >= 48 ) - goto tr54; - goto tr53; -tr54: + switch ((*(p_))) { + case 46: + goto tr2; + case 69: + goto st3; + case 76: + goto st8; + case 85: + goto st10; + case 88: + goto st11; + case 101: + goto st3; + case 108: + goto st8; + case 117: + goto st10; + case 120: + goto st11; + } + if ((*(p_)) > 55) { + if (56 <= (*(p_)) && (*(p_)) <= 57) + goto st7; + } else if ((*(p_)) >= 48) + goto tr54; + goto tr53; + tr54: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 110 "lexer.rl" - {act = 49;} - goto st18; -st18: - if ( ++( p_) == pe ) - goto _test_eof18; -case 18: + { act = 49; } + goto st18; + st18: + if (++(p_) == pe) + goto _test_eof18; + case 18: #line 450 "lexer_generated.cpp" - switch( (*( p_)) ) { - case 46: goto tr2; - case 69: goto st3; - case 76: goto st8; - case 85: goto st10; - case 101: goto st3; - case 108: goto st8; - case 117: goto st10; - } - if ( (*( p_)) > 55 ) { - if ( 56 <= (*( p_)) && (*( p_)) <= 57 ) - goto st7; - } else if ( (*( p_)) >= 48 ) - goto tr54; - goto tr53; -st7: - if ( ++( p_) == pe ) - goto _test_eof7; -case 7: - switch( (*( p_)) ) { - case 46: goto tr2; - case 69: goto st3; - case 101: goto st3; - } - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto st7; - goto tr10; -st8: - if ( ++( p_) == pe ) - goto _test_eof8; -case 8: - switch( (*( p_)) ) { - case 76: goto st9; - case 85: goto tr14; - case 108: goto st9; - case 117: goto tr14; - } - goto tr10; -st9: - if ( ++( p_) == pe ) - goto _test_eof9; -case 9: - switch( (*( p_)) ) { - case 85: goto tr14; - case 117: goto tr14; - } - goto tr10; -st10: - if ( ++( p_) == pe ) - goto _test_eof10; -case 10: - switch( (*( p_)) ) { - case 76: goto st19; - case 108: goto st19; - } - goto tr10; -st19: - if ( ++( p_) == pe ) - goto _test_eof19; -case 19: - switch( (*( p_)) ) { - case 76: goto tr14; - case 108: goto tr14; - } - goto tr53; -st11: - if ( ++( p_) == pe ) - goto _test_eof11; -case 11: - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr16; - } else if ( (*( p_)) > 70 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 102 ) - goto tr16; - } else - goto tr16; - goto tr10; -tr16: + switch ((*(p_))) { + case 46: + goto tr2; + case 69: + goto st3; + case 76: + goto st8; + case 85: + goto st10; + case 101: + goto st3; + case 108: + goto st8; + case 117: + goto st10; + } + if ((*(p_)) > 55) { + if (56 <= (*(p_)) && (*(p_)) <= 57) + goto st7; + } else if ((*(p_)) >= 48) + goto tr54; + goto tr53; + st7: + if (++(p_) == pe) + goto _test_eof7; + case 7: + switch ((*(p_))) { + case 46: + goto tr2; + case 69: + goto st3; + case 101: + goto st3; + } + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto st7; + goto tr10; + st8: + if (++(p_) == pe) + goto _test_eof8; + case 8: + switch ((*(p_))) { + case 76: + goto st9; + case 85: + goto tr14; + case 108: + goto st9; + case 117: + goto tr14; + } + goto tr10; + st9: + if (++(p_) == pe) + goto _test_eof9; + case 9: + switch ((*(p_))) { + case 85: + goto tr14; + case 117: + goto tr14; + } + goto tr10; + st10: + if (++(p_) == pe) + goto _test_eof10; + case 10: + switch ((*(p_))) { + case 76: + goto st19; + case 108: + goto st19; + } + goto tr10; + st19: + if (++(p_) == pe) + goto _test_eof19; + case 19: + switch ((*(p_))) { + case 76: + goto tr14; + case 108: + goto tr14; + } + goto tr53; + st11: + if (++(p_) == pe) + goto _test_eof11; + case 11: + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr16; + } else if ((*(p_)) > 70) { + if (97 <= (*(p_)) && (*(p_)) <= 102) + goto tr16; + } else + goto tr16; + goto tr10; + tr16: #line 1 "NONE" - {te = ( p_)+1;} - goto st20; -st20: - if ( ++( p_) == pe ) - goto _test_eof20; -case 20: + { + te = (p_) + 1; + } + goto st20; + st20: + if (++(p_) == pe) + goto _test_eof20; + case 20: #line 537 "lexer_generated.cpp" - switch( (*( p_)) ) { - case 76: goto st8; - case 85: goto st10; - case 108: goto st8; - case 117: goto st10; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr16; - } else if ( (*( p_)) > 70 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 102 ) - goto tr16; - } else - goto tr16; - goto tr53; -tr30: + switch ((*(p_))) { + case 76: + goto st8; + case 85: + goto st10; + case 108: + goto st8; + case 117: + goto st10; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr16; + } else if ((*(p_)) > 70) { + if (97 <= (*(p_)) && (*(p_)) <= 102) + goto tr16; + } else + goto tr16; + goto tr53; + tr30: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 110 "lexer.rl" - {act = 49;} - goto st21; -st21: - if ( ++( p_) == pe ) - goto _test_eof21; -case 21: + { act = 49; } + goto st21; + st21: + if (++(p_) == pe) + goto _test_eof21; + case 21: #line 563 "lexer_generated.cpp" - switch( (*( p_)) ) { - case 46: goto tr2; - case 69: goto st3; - case 76: goto st8; - case 85: goto st10; - case 101: goto st3; - case 108: goto st8; - case 117: goto st10; - } - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr30; - goto tr53; -tr33: + switch ((*(p_))) { + case 46: + goto tr2; + case 69: + goto st3; + case 76: + goto st8; + case 85: + goto st10; + case 101: + goto st3; + case 108: + goto st8; + case 117: + goto st10; + } + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr30; + goto tr53; + tr33: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 113 "lexer.rl" - {act = 51;} - goto st22; -tr61: + { act = 51; } + goto st22; + tr61: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 62 "lexer.rl" - {act = 4;} - goto st22; -tr64: + { act = 4; } + goto st22; + tr64: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 75 "lexer.rl" - {act = 17;} - goto st22; -tr68: + { act = 17; } + goto st22; + tr68: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 74 "lexer.rl" - {act = 16;} - goto st22; -tr71: + { act = 16; } + goto st22; + tr71: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 69 "lexer.rl" - {act = 11;} - goto st22; -tr76: + { act = 11; } + goto st22; + tr76: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 73 "lexer.rl" - {act = 15;} - goto st22; -tr80: + { act = 15; } + goto st22; + tr80: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 65 "lexer.rl" - {act = 7;} - goto st22; -tr84: + { act = 7; } + goto st22; + tr84: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 64 "lexer.rl" - {act = 6;} - goto st22; -tr88: + { act = 6; } + goto st22; + tr88: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 72 "lexer.rl" - {act = 14;} - goto st22; -tr94: + { act = 14; } + goto st22; + tr94: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 67 "lexer.rl" - {act = 9;} - goto st22; -tr103: + { act = 9; } + goto st22; + tr103: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 78 "lexer.rl" - {act = 20;} - goto st22; -tr106: + { act = 20; } + goto st22; + tr106: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 79 "lexer.rl" - {act = 21;} - goto st22; -tr109: + { act = 21; } + goto st22; + tr109: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 80 "lexer.rl" - {act = 22;} - goto st22; -tr111: + { act = 22; } + goto st22; + tr111: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 77 "lexer.rl" - {act = 19;} - goto st22; -tr115: + { act = 19; } + goto st22; + tr115: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 85 "lexer.rl" - {act = 27;} - goto st22; -tr118: + { act = 27; } + goto st22; + tr118: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 88 "lexer.rl" - {act = 30;} - goto st22; -tr125: + { act = 30; } + goto st22; + tr125: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 63 "lexer.rl" - {act = 5;} - goto st22; -tr131: + { act = 5; } + goto st22; + tr131: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 89 "lexer.rl" - {act = 31;} - goto st22; -tr136: + { act = 31; } + goto st22; + tr136: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 92 "lexer.rl" - {act = 34;} - goto st22; -tr139: + { act = 34; } + goto st22; + tr139: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 87 "lexer.rl" - {act = 29;} - goto st22; -tr144: + { act = 29; } + goto st22; + tr144: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 66 "lexer.rl" - {act = 8;} - goto st22; -tr147: + { act = 8; } + goto st22; + tr147: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 93 "lexer.rl" - {act = 35;} - goto st22; -tr153: + { act = 35; } + goto st22; + tr153: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 68 "lexer.rl" - {act = 10;} - goto st22; -tr165: + { act = 10; } + goto st22; + tr165: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 82 "lexer.rl" - {act = 24;} - goto st22; -tr168: + { act = 24; } + goto st22; + tr168: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 83 "lexer.rl" - {act = 25;} - goto st22; -tr171: + { act = 25; } + goto st22; + tr171: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 84 "lexer.rl" - {act = 26;} - goto st22; -tr173: + { act = 26; } + goto st22; + tr173: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 81 "lexer.rl" - {act = 23;} - goto st22; -tr177: + { act = 23; } + goto st22; + tr177: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 86 "lexer.rl" - {act = 28;} - goto st22; -tr181: + { act = 28; } + goto st22; + tr181: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 91 "lexer.rl" - {act = 33;} - goto st22; -tr186: + { act = 33; } + goto st22; + tr186: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 90 "lexer.rl" - {act = 32;} - goto st22; -tr190: + { act = 32; } + goto st22; + tr190: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 71 "lexer.rl" - {act = 13;} - goto st22; -tr195: + { act = 13; } + goto st22; + tr195: #line 1 "NONE" - {te = ( p_)+1;} + { + te = (p_) + 1; + } #line 70 "lexer.rl" - {act = 12;} - goto st22; -st22: - if ( ++( p_) == pe ) - goto _test_eof22; -case 22: + { act = 12; } + goto st22; + st22: + if (++(p_) == pe) + goto _test_eof22; + case 22: #line 772 "lexer_generated.cpp" - if ( (*( p_)) == 95 ) - goto tr33; - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr4; -st23: - if ( ++( p_) == pe ) - goto _test_eof23; -case 23: - switch( (*( p_)) ) { - case 95: goto tr33; - case 117: goto st24; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st24: - if ( ++( p_) == pe ) - goto _test_eof24; -case 24: - switch( (*( p_)) ) { - case 95: goto tr33; - case 116: goto st25; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st25: - if ( ++( p_) == pe ) - goto _test_eof25; -case 25: - switch( (*( p_)) ) { - case 95: goto tr33; - case 111: goto tr61; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st26: - if ( ++( p_) == pe ) - goto _test_eof26; -case 26: - switch( (*( p_)) ) { - case 95: goto tr33; - case 111: goto st27; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st27: - if ( ++( p_) == pe ) - goto _test_eof27; -case 27: - switch( (*( p_)) ) { - case 95: goto tr33; - case 111: goto st28; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st28: - if ( ++( p_) == pe ) - goto _test_eof28; -case 28: - switch( (*( p_)) ) { - case 95: goto tr33; - case 108: goto tr64; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st29: - if ( ++( p_) == pe ) - goto _test_eof29; -case 29: - switch( (*( p_)) ) { - case 95: goto tr33; - case 104: goto st30; - case 111: goto st32; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st30: - if ( ++( p_) == pe ) - goto _test_eof30; -case 30: - switch( (*( p_)) ) { - case 95: goto tr33; - case 97: goto st31; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 98 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st31: - if ( ++( p_) == pe ) - goto _test_eof31; -case 31: - switch( (*( p_)) ) { - case 95: goto tr33; - case 114: goto tr68; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st32: - if ( ++( p_) == pe ) - goto _test_eof32; -case 32: - switch( (*( p_)) ) { - case 95: goto tr33; - case 110: goto st33; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st33: - if ( ++( p_) == pe ) - goto _test_eof33; -case 33: - switch( (*( p_)) ) { - case 95: goto tr33; - case 115: goto st34; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st34: - if ( ++( p_) == pe ) - goto _test_eof34; -case 34: - switch( (*( p_)) ) { - case 95: goto tr33; - case 116: goto tr71; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st35: - if ( ++( p_) == pe ) - goto _test_eof35; -case 35: - switch( (*( p_)) ) { - case 95: goto tr33; - case 111: goto st36; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st36: - if ( ++( p_) == pe ) - goto _test_eof36; -case 36: - switch( (*( p_)) ) { - case 95: goto tr33; - case 117: goto st37; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st37: - if ( ++( p_) == pe ) - goto _test_eof37; -case 37: - switch( (*( p_)) ) { - case 95: goto tr33; - case 98: goto st38; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st38: - if ( ++( p_) == pe ) - goto _test_eof38; -case 38: - switch( (*( p_)) ) { - case 95: goto tr33; - case 108: goto st39; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st39: - if ( ++( p_) == pe ) - goto _test_eof39; -case 39: - switch( (*( p_)) ) { - case 95: goto tr33; - case 101: goto tr76; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st40: - if ( ++( p_) == pe ) - goto _test_eof40; -case 40: - switch( (*( p_)) ) { - case 95: goto tr33; - case 110: goto st41; - case 120: goto st43; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st41: - if ( ++( p_) == pe ) - goto _test_eof41; -case 41: - switch( (*( p_)) ) { - case 95: goto tr33; - case 117: goto st42; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st42: - if ( ++( p_) == pe ) - goto _test_eof42; -case 42: - switch( (*( p_)) ) { - case 95: goto tr33; - case 109: goto tr80; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st43: - if ( ++( p_) == pe ) - goto _test_eof43; -case 43: - switch( (*( p_)) ) { - case 95: goto tr33; - case 116: goto st44; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st44: - if ( ++( p_) == pe ) - goto _test_eof44; -case 44: - switch( (*( p_)) ) { - case 95: goto tr33; - case 101: goto st45; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st45: - if ( ++( p_) == pe ) - goto _test_eof45; -case 45: - switch( (*( p_)) ) { - case 95: goto tr33; - case 114: goto st46; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st46: - if ( ++( p_) == pe ) - goto _test_eof46; -case 46: - switch( (*( p_)) ) { - case 95: goto tr33; - case 110: goto tr84; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st47: - if ( ++( p_) == pe ) - goto _test_eof47; -case 47: - switch( (*( p_)) ) { - case 95: goto tr33; - case 108: goto st48; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st48: - if ( ++( p_) == pe ) - goto _test_eof48; -case 48: - switch( (*( p_)) ) { - case 95: goto tr33; - case 111: goto st49; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st49: - if ( ++( p_) == pe ) - goto _test_eof49; -case 49: - switch( (*( p_)) ) { - case 95: goto tr33; - case 97: goto st50; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 98 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st50: - if ( ++( p_) == pe ) - goto _test_eof50; -case 50: - switch( (*( p_)) ) { - case 95: goto tr33; - case 116: goto tr88; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st51: - if ( ++( p_) == pe ) - goto _test_eof51; -case 51: - switch( (*( p_)) ) { - case 95: goto tr33; - case 110: goto st52; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st52: - if ( ++( p_) == pe ) - goto _test_eof52; -case 52: - switch( (*( p_)) ) { - case 95: goto tr33; - case 108: goto st53; - case 116: goto st56; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st53: - if ( ++( p_) == pe ) - goto _test_eof53; -case 53: - switch( (*( p_)) ) { - case 95: goto tr33; - case 105: goto st54; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st54: - if ( ++( p_) == pe ) - goto _test_eof54; -case 54: - switch( (*( p_)) ) { - case 95: goto tr33; - case 110: goto st55; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st55: - if ( ++( p_) == pe ) - goto _test_eof55; -case 55: - switch( (*( p_)) ) { - case 95: goto tr33; - case 101: goto tr94; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st56: - if ( ++( p_) == pe ) - goto _test_eof56; -case 56: - switch( (*( p_)) ) { - case 49: goto st57; - case 51: goto st60; - case 54: goto st63; - case 56: goto st66; - case 95: goto tr33; - case 112: goto st68; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr95; -st57: - if ( ++( p_) == pe ) - goto _test_eof57; -case 57: - switch( (*( p_)) ) { - case 54: goto st58; - case 95: goto tr33; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st58: - if ( ++( p_) == pe ) - goto _test_eof58; -case 58: - if ( (*( p_)) == 95 ) - goto st59; - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st59: - if ( ++( p_) == pe ) - goto _test_eof59; -case 59: - switch( (*( p_)) ) { - case 95: goto tr33; - case 116: goto tr103; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st60: - if ( ++( p_) == pe ) - goto _test_eof60; -case 60: - switch( (*( p_)) ) { - case 50: goto st61; - case 95: goto tr33; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st61: - if ( ++( p_) == pe ) - goto _test_eof61; -case 61: - if ( (*( p_)) == 95 ) - goto st62; - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st62: - if ( ++( p_) == pe ) - goto _test_eof62; -case 62: - switch( (*( p_)) ) { - case 95: goto tr33; - case 116: goto tr106; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st63: - if ( ++( p_) == pe ) - goto _test_eof63; -case 63: - switch( (*( p_)) ) { - case 52: goto st64; - case 95: goto tr33; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st64: - if ( ++( p_) == pe ) - goto _test_eof64; -case 64: - if ( (*( p_)) == 95 ) - goto st65; - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st65: - if ( ++( p_) == pe ) - goto _test_eof65; -case 65: - switch( (*( p_)) ) { - case 95: goto tr33; - case 116: goto tr109; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st66: - if ( ++( p_) == pe ) - goto _test_eof66; -case 66: - if ( (*( p_)) == 95 ) - goto st67; - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st67: - if ( ++( p_) == pe ) - goto _test_eof67; -case 67: - switch( (*( p_)) ) { - case 95: goto tr33; - case 116: goto tr111; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st68: - if ( ++( p_) == pe ) - goto _test_eof68; -case 68: - switch( (*( p_)) ) { - case 95: goto tr33; - case 116: goto st69; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st69: - if ( ++( p_) == pe ) - goto _test_eof69; -case 69: - switch( (*( p_)) ) { - case 95: goto tr33; - case 114: goto st70; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st70: - if ( ++( p_) == pe ) - goto _test_eof70; -case 70: - if ( (*( p_)) == 95 ) - goto st71; - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st71: - if ( ++( p_) == pe ) - goto _test_eof71; -case 71: - switch( (*( p_)) ) { - case 95: goto tr33; - case 116: goto tr115; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st72: - if ( ++( p_) == pe ) - goto _test_eof72; -case 72: - switch( (*( p_)) ) { - case 95: goto tr33; - case 111: goto st73; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st73: - if ( ++( p_) == pe ) - goto _test_eof73; -case 73: - switch( (*( p_)) ) { - case 95: goto tr33; - case 110: goto st74; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st74: - if ( ++( p_) == pe ) - goto _test_eof74; -case 74: - switch( (*( p_)) ) { - case 95: goto tr33; - case 103: goto tr118; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st75: - if ( ++( p_) == pe ) - goto _test_eof75; -case 75: - switch( (*( p_)) ) { - case 95: goto tr33; - case 101: goto st76; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st76: - if ( ++( p_) == pe ) - goto _test_eof76; -case 76: - switch( (*( p_)) ) { - case 95: goto tr33; - case 103: goto st77; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st77: - if ( ++( p_) == pe ) - goto _test_eof77; -case 77: - switch( (*( p_)) ) { - case 95: goto tr33; - case 105: goto st78; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st78: - if ( ++( p_) == pe ) - goto _test_eof78; -case 78: - switch( (*( p_)) ) { - case 95: goto tr33; - case 115: goto st79; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st79: - if ( ++( p_) == pe ) - goto _test_eof79; -case 79: - switch( (*( p_)) ) { - case 95: goto tr33; - case 116: goto st80; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st80: - if ( ++( p_) == pe ) - goto _test_eof80; -case 80: - switch( (*( p_)) ) { - case 95: goto tr33; - case 101: goto st81; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st81: - if ( ++( p_) == pe ) - goto _test_eof81; -case 81: - switch( (*( p_)) ) { - case 95: goto tr33; - case 114: goto tr125; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st82: - if ( ++( p_) == pe ) - goto _test_eof82; -case 82: - switch( (*( p_)) ) { - case 95: goto tr33; - case 104: goto st83; - case 105: goto st86; - case 116: goto st93; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st83: - if ( ++( p_) == pe ) - goto _test_eof83; -case 83: - switch( (*( p_)) ) { - case 95: goto tr33; - case 111: goto st84; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st84: - if ( ++( p_) == pe ) - goto _test_eof84; -case 84: - switch( (*( p_)) ) { - case 95: goto tr33; - case 114: goto st85; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st85: - if ( ++( p_) == pe ) - goto _test_eof85; -case 85: - switch( (*( p_)) ) { - case 95: goto tr33; - case 116: goto tr131; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st86: - if ( ++( p_) == pe ) - goto _test_eof86; -case 86: - switch( (*( p_)) ) { - case 95: goto tr33; - case 103: goto st87; - case 122: goto st90; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 121 ) - goto tr33; - } else - goto tr33; - goto tr58; -st87: - if ( ++( p_) == pe ) - goto _test_eof87; -case 87: - switch( (*( p_)) ) { - case 95: goto tr33; - case 110: goto st88; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st88: - if ( ++( p_) == pe ) - goto _test_eof88; -case 88: - switch( (*( p_)) ) { - case 95: goto tr33; - case 101: goto st89; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st89: - if ( ++( p_) == pe ) - goto _test_eof89; -case 89: - switch( (*( p_)) ) { - case 95: goto tr33; - case 100: goto tr136; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st90: - if ( ++( p_) == pe ) - goto _test_eof90; -case 90: - switch( (*( p_)) ) { - case 95: goto tr33; - case 101: goto st91; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st91: - if ( ++( p_) == pe ) - goto _test_eof91; -case 91: - if ( (*( p_)) == 95 ) - goto st92; - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st92: - if ( ++( p_) == pe ) - goto _test_eof92; -case 92: - switch( (*( p_)) ) { - case 95: goto tr33; - case 116: goto tr139; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st93: - if ( ++( p_) == pe ) - goto _test_eof93; -case 93: - switch( (*( p_)) ) { - case 95: goto tr33; - case 97: goto st94; - case 114: goto st97; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 98 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st94: - if ( ++( p_) == pe ) - goto _test_eof94; -case 94: - switch( (*( p_)) ) { - case 95: goto tr33; - case 116: goto st95; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st95: - if ( ++( p_) == pe ) - goto _test_eof95; -case 95: - switch( (*( p_)) ) { - case 95: goto tr33; - case 105: goto st96; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st96: - if ( ++( p_) == pe ) - goto _test_eof96; -case 96: - switch( (*( p_)) ) { - case 95: goto tr33; - case 99: goto tr144; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st97: - if ( ++( p_) == pe ) - goto _test_eof97; -case 97: - switch( (*( p_)) ) { - case 95: goto tr33; - case 117: goto st98; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st98: - if ( ++( p_) == pe ) - goto _test_eof98; -case 98: - switch( (*( p_)) ) { - case 95: goto tr33; - case 99: goto st99; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st99: - if ( ++( p_) == pe ) - goto _test_eof99; -case 99: - switch( (*( p_)) ) { - case 95: goto tr33; - case 116: goto tr147; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st100: - if ( ++( p_) == pe ) - goto _test_eof100; -case 100: - switch( (*( p_)) ) { - case 95: goto tr33; - case 121: goto st101; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st101: - if ( ++( p_) == pe ) - goto _test_eof101; -case 101: - switch( (*( p_)) ) { - case 95: goto tr33; - case 112: goto st102; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st102: - if ( ++( p_) == pe ) - goto _test_eof102; -case 102: - switch( (*( p_)) ) { - case 95: goto tr33; - case 101: goto st103; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st103: - if ( ++( p_) == pe ) - goto _test_eof103; -case 103: - switch( (*( p_)) ) { - case 95: goto tr33; - case 100: goto st104; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st104: - if ( ++( p_) == pe ) - goto _test_eof104; -case 104: - switch( (*( p_)) ) { - case 95: goto tr33; - case 101: goto st105; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st105: - if ( ++( p_) == pe ) - goto _test_eof105; -case 105: - switch( (*( p_)) ) { - case 95: goto tr33; - case 102: goto tr153; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st106: - if ( ++( p_) == pe ) - goto _test_eof106; -case 106: - switch( (*( p_)) ) { - case 95: goto tr33; - case 105: goto st107; - case 110: goto st125; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st107: - if ( ++( p_) == pe ) - goto _test_eof107; -case 107: - switch( (*( p_)) ) { - case 95: goto tr33; - case 110: goto st108; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st108: - if ( ++( p_) == pe ) - goto _test_eof108; -case 108: - switch( (*( p_)) ) { - case 95: goto tr33; - case 116: goto st109; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st109: - if ( ++( p_) == pe ) - goto _test_eof109; -case 109: - switch( (*( p_)) ) { - case 49: goto st110; - case 51: goto st113; - case 54: goto st116; - case 56: goto st119; - case 95: goto tr33; - case 112: goto st121; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st110: - if ( ++( p_) == pe ) - goto _test_eof110; -case 110: - switch( (*( p_)) ) { - case 54: goto st111; - case 95: goto tr33; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st111: - if ( ++( p_) == pe ) - goto _test_eof111; -case 111: - if ( (*( p_)) == 95 ) - goto st112; - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st112: - if ( ++( p_) == pe ) - goto _test_eof112; -case 112: - switch( (*( p_)) ) { - case 95: goto tr33; - case 116: goto tr165; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st113: - if ( ++( p_) == pe ) - goto _test_eof113; -case 113: - switch( (*( p_)) ) { - case 50: goto st114; - case 95: goto tr33; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st114: - if ( ++( p_) == pe ) - goto _test_eof114; -case 114: - if ( (*( p_)) == 95 ) - goto st115; - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st115: - if ( ++( p_) == pe ) - goto _test_eof115; -case 115: - switch( (*( p_)) ) { - case 95: goto tr33; - case 116: goto tr168; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st116: - if ( ++( p_) == pe ) - goto _test_eof116; -case 116: - switch( (*( p_)) ) { - case 52: goto st117; - case 95: goto tr33; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st117: - if ( ++( p_) == pe ) - goto _test_eof117; -case 117: - if ( (*( p_)) == 95 ) - goto st118; - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st118: - if ( ++( p_) == pe ) - goto _test_eof118; -case 118: - switch( (*( p_)) ) { - case 95: goto tr33; - case 116: goto tr171; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st119: - if ( ++( p_) == pe ) - goto _test_eof119; -case 119: - if ( (*( p_)) == 95 ) - goto st120; - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st120: - if ( ++( p_) == pe ) - goto _test_eof120; -case 120: - switch( (*( p_)) ) { - case 95: goto tr33; - case 116: goto tr173; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st121: - if ( ++( p_) == pe ) - goto _test_eof121; -case 121: - switch( (*( p_)) ) { - case 95: goto tr33; - case 116: goto st122; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st122: - if ( ++( p_) == pe ) - goto _test_eof122; -case 122: - switch( (*( p_)) ) { - case 95: goto tr33; - case 114: goto st123; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st123: - if ( ++( p_) == pe ) - goto _test_eof123; -case 123: - if ( (*( p_)) == 95 ) - goto st124; - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st124: - if ( ++( p_) == pe ) - goto _test_eof124; -case 124: - switch( (*( p_)) ) { - case 95: goto tr33; - case 116: goto tr177; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st125: - if ( ++( p_) == pe ) - goto _test_eof125; -case 125: - switch( (*( p_)) ) { - case 95: goto tr33; - case 105: goto st126; - case 115: goto st128; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st126: - if ( ++( p_) == pe ) - goto _test_eof126; -case 126: - switch( (*( p_)) ) { - case 95: goto tr33; - case 111: goto st127; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st127: - if ( ++( p_) == pe ) - goto _test_eof127; -case 127: - switch( (*( p_)) ) { - case 95: goto tr33; - case 110: goto tr181; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st128: - if ( ++( p_) == pe ) - goto _test_eof128; -case 128: - switch( (*( p_)) ) { - case 95: goto tr33; - case 105: goto st129; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st129: - if ( ++( p_) == pe ) - goto _test_eof129; -case 129: - switch( (*( p_)) ) { - case 95: goto tr33; - case 103: goto st130; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st130: - if ( ++( p_) == pe ) - goto _test_eof130; -case 130: - switch( (*( p_)) ) { - case 95: goto tr33; - case 110: goto st131; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st131: - if ( ++( p_) == pe ) - goto _test_eof131; -case 131: - switch( (*( p_)) ) { - case 95: goto tr33; - case 101: goto st132; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st132: - if ( ++( p_) == pe ) - goto _test_eof132; -case 132: - switch( (*( p_)) ) { - case 95: goto tr33; - case 100: goto tr186; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st133: - if ( ++( p_) == pe ) - goto _test_eof133; -case 133: - switch( (*( p_)) ) { - case 95: goto tr33; - case 111: goto st134; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st134: - if ( ++( p_) == pe ) - goto _test_eof134; -case 134: - switch( (*( p_)) ) { - case 95: goto tr33; - case 105: goto st135; - case 108: goto st136; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st135: - if ( ++( p_) == pe ) - goto _test_eof135; -case 135: - switch( (*( p_)) ) { - case 95: goto tr33; - case 100: goto tr190; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st136: - if ( ++( p_) == pe ) - goto _test_eof136; -case 136: - switch( (*( p_)) ) { - case 95: goto tr33; - case 97: goto st137; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 98 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st137: - if ( ++( p_) == pe ) - goto _test_eof137; -case 137: - switch( (*( p_)) ) { - case 95: goto tr33; - case 116: goto st138; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st138: - if ( ++( p_) == pe ) - goto _test_eof138; -case 138: - switch( (*( p_)) ) { - case 95: goto tr33; - case 105: goto st139; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st139: - if ( ++( p_) == pe ) - goto _test_eof139; -case 139: - switch( (*( p_)) ) { - case 95: goto tr33; - case 108: goto st140; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st140: - if ( ++( p_) == pe ) - goto _test_eof140; -case 140: - switch( (*( p_)) ) { - case 95: goto tr33; - case 101: goto tr195; - } - if ( (*( p_)) < 65 ) { - if ( 48 <= (*( p_)) && (*( p_)) <= 57 ) - goto tr33; - } else if ( (*( p_)) > 90 ) { - if ( 97 <= (*( p_)) && (*( p_)) <= 122 ) - goto tr33; - } else - goto tr33; - goto tr58; -st12: + if ((*(p_)) == 95) + goto tr33; + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr4; + st23: + if (++(p_) == pe) + goto _test_eof23; + case 23: + switch ((*(p_))) { + case 95: + goto tr33; + case 117: + goto st24; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st24: + if (++(p_) == pe) + goto _test_eof24; + case 24: + switch ((*(p_))) { + case 95: + goto tr33; + case 116: + goto st25; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st25: + if (++(p_) == pe) + goto _test_eof25; + case 25: + switch ((*(p_))) { + case 95: + goto tr33; + case 111: + goto tr61; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st26: + if (++(p_) == pe) + goto _test_eof26; + case 26: + switch ((*(p_))) { + case 95: + goto tr33; + case 111: + goto st27; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st27: + if (++(p_) == pe) + goto _test_eof27; + case 27: + switch ((*(p_))) { + case 95: + goto tr33; + case 111: + goto st28; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st28: + if (++(p_) == pe) + goto _test_eof28; + case 28: + switch ((*(p_))) { + case 95: + goto tr33; + case 108: + goto tr64; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st29: + if (++(p_) == pe) + goto _test_eof29; + case 29: + switch ((*(p_))) { + case 95: + goto tr33; + case 104: + goto st30; + case 111: + goto st32; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st30: + if (++(p_) == pe) + goto _test_eof30; + case 30: + switch ((*(p_))) { + case 95: + goto tr33; + case 97: + goto st31; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (98 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st31: + if (++(p_) == pe) + goto _test_eof31; + case 31: + switch ((*(p_))) { + case 95: + goto tr33; + case 114: + goto tr68; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st32: + if (++(p_) == pe) + goto _test_eof32; + case 32: + switch ((*(p_))) { + case 95: + goto tr33; + case 110: + goto st33; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st33: + if (++(p_) == pe) + goto _test_eof33; + case 33: + switch ((*(p_))) { + case 95: + goto tr33; + case 115: + goto st34; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st34: + if (++(p_) == pe) + goto _test_eof34; + case 34: + switch ((*(p_))) { + case 95: + goto tr33; + case 116: + goto tr71; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st35: + if (++(p_) == pe) + goto _test_eof35; + case 35: + switch ((*(p_))) { + case 95: + goto tr33; + case 111: + goto st36; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st36: + if (++(p_) == pe) + goto _test_eof36; + case 36: + switch ((*(p_))) { + case 95: + goto tr33; + case 117: + goto st37; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st37: + if (++(p_) == pe) + goto _test_eof37; + case 37: + switch ((*(p_))) { + case 95: + goto tr33; + case 98: + goto st38; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st38: + if (++(p_) == pe) + goto _test_eof38; + case 38: + switch ((*(p_))) { + case 95: + goto tr33; + case 108: + goto st39; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st39: + if (++(p_) == pe) + goto _test_eof39; + case 39: + switch ((*(p_))) { + case 95: + goto tr33; + case 101: + goto tr76; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st40: + if (++(p_) == pe) + goto _test_eof40; + case 40: + switch ((*(p_))) { + case 95: + goto tr33; + case 110: + goto st41; + case 120: + goto st43; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st41: + if (++(p_) == pe) + goto _test_eof41; + case 41: + switch ((*(p_))) { + case 95: + goto tr33; + case 117: + goto st42; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st42: + if (++(p_) == pe) + goto _test_eof42; + case 42: + switch ((*(p_))) { + case 95: + goto tr33; + case 109: + goto tr80; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st43: + if (++(p_) == pe) + goto _test_eof43; + case 43: + switch ((*(p_))) { + case 95: + goto tr33; + case 116: + goto st44; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st44: + if (++(p_) == pe) + goto _test_eof44; + case 44: + switch ((*(p_))) { + case 95: + goto tr33; + case 101: + goto st45; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st45: + if (++(p_) == pe) + goto _test_eof45; + case 45: + switch ((*(p_))) { + case 95: + goto tr33; + case 114: + goto st46; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st46: + if (++(p_) == pe) + goto _test_eof46; + case 46: + switch ((*(p_))) { + case 95: + goto tr33; + case 110: + goto tr84; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st47: + if (++(p_) == pe) + goto _test_eof47; + case 47: + switch ((*(p_))) { + case 95: + goto tr33; + case 108: + goto st48; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st48: + if (++(p_) == pe) + goto _test_eof48; + case 48: + switch ((*(p_))) { + case 95: + goto tr33; + case 111: + goto st49; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st49: + if (++(p_) == pe) + goto _test_eof49; + case 49: + switch ((*(p_))) { + case 95: + goto tr33; + case 97: + goto st50; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (98 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st50: + if (++(p_) == pe) + goto _test_eof50; + case 50: + switch ((*(p_))) { + case 95: + goto tr33; + case 116: + goto tr88; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st51: + if (++(p_) == pe) + goto _test_eof51; + case 51: + switch ((*(p_))) { + case 95: + goto tr33; + case 110: + goto st52; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st52: + if (++(p_) == pe) + goto _test_eof52; + case 52: + switch ((*(p_))) { + case 95: + goto tr33; + case 108: + goto st53; + case 116: + goto st56; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st53: + if (++(p_) == pe) + goto _test_eof53; + case 53: + switch ((*(p_))) { + case 95: + goto tr33; + case 105: + goto st54; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st54: + if (++(p_) == pe) + goto _test_eof54; + case 54: + switch ((*(p_))) { + case 95: + goto tr33; + case 110: + goto st55; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st55: + if (++(p_) == pe) + goto _test_eof55; + case 55: + switch ((*(p_))) { + case 95: + goto tr33; + case 101: + goto tr94; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st56: + if (++(p_) == pe) + goto _test_eof56; + case 56: + switch ((*(p_))) { + case 49: + goto st57; + case 51: + goto st60; + case 54: + goto st63; + case 56: + goto st66; + case 95: + goto tr33; + case 112: + goto st68; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr95; + st57: + if (++(p_) == pe) + goto _test_eof57; + case 57: + switch ((*(p_))) { + case 54: + goto st58; + case 95: + goto tr33; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st58: + if (++(p_) == pe) + goto _test_eof58; + case 58: + if ((*(p_)) == 95) + goto st59; + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st59: + if (++(p_) == pe) + goto _test_eof59; + case 59: + switch ((*(p_))) { + case 95: + goto tr33; + case 116: + goto tr103; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st60: + if (++(p_) == pe) + goto _test_eof60; + case 60: + switch ((*(p_))) { + case 50: + goto st61; + case 95: + goto tr33; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st61: + if (++(p_) == pe) + goto _test_eof61; + case 61: + if ((*(p_)) == 95) + goto st62; + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st62: + if (++(p_) == pe) + goto _test_eof62; + case 62: + switch ((*(p_))) { + case 95: + goto tr33; + case 116: + goto tr106; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st63: + if (++(p_) == pe) + goto _test_eof63; + case 63: + switch ((*(p_))) { + case 52: + goto st64; + case 95: + goto tr33; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st64: + if (++(p_) == pe) + goto _test_eof64; + case 64: + if ((*(p_)) == 95) + goto st65; + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st65: + if (++(p_) == pe) + goto _test_eof65; + case 65: + switch ((*(p_))) { + case 95: + goto tr33; + case 116: + goto tr109; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st66: + if (++(p_) == pe) + goto _test_eof66; + case 66: + if ((*(p_)) == 95) + goto st67; + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st67: + if (++(p_) == pe) + goto _test_eof67; + case 67: + switch ((*(p_))) { + case 95: + goto tr33; + case 116: + goto tr111; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st68: + if (++(p_) == pe) + goto _test_eof68; + case 68: + switch ((*(p_))) { + case 95: + goto tr33; + case 116: + goto st69; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st69: + if (++(p_) == pe) + goto _test_eof69; + case 69: + switch ((*(p_))) { + case 95: + goto tr33; + case 114: + goto st70; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st70: + if (++(p_) == pe) + goto _test_eof70; + case 70: + if ((*(p_)) == 95) + goto st71; + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st71: + if (++(p_) == pe) + goto _test_eof71; + case 71: + switch ((*(p_))) { + case 95: + goto tr33; + case 116: + goto tr115; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st72: + if (++(p_) == pe) + goto _test_eof72; + case 72: + switch ((*(p_))) { + case 95: + goto tr33; + case 111: + goto st73; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st73: + if (++(p_) == pe) + goto _test_eof73; + case 73: + switch ((*(p_))) { + case 95: + goto tr33; + case 110: + goto st74; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st74: + if (++(p_) == pe) + goto _test_eof74; + case 74: + switch ((*(p_))) { + case 95: + goto tr33; + case 103: + goto tr118; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st75: + if (++(p_) == pe) + goto _test_eof75; + case 75: + switch ((*(p_))) { + case 95: + goto tr33; + case 101: + goto st76; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st76: + if (++(p_) == pe) + goto _test_eof76; + case 76: + switch ((*(p_))) { + case 95: + goto tr33; + case 103: + goto st77; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st77: + if (++(p_) == pe) + goto _test_eof77; + case 77: + switch ((*(p_))) { + case 95: + goto tr33; + case 105: + goto st78; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st78: + if (++(p_) == pe) + goto _test_eof78; + case 78: + switch ((*(p_))) { + case 95: + goto tr33; + case 115: + goto st79; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st79: + if (++(p_) == pe) + goto _test_eof79; + case 79: + switch ((*(p_))) { + case 95: + goto tr33; + case 116: + goto st80; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st80: + if (++(p_) == pe) + goto _test_eof80; + case 80: + switch ((*(p_))) { + case 95: + goto tr33; + case 101: + goto st81; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st81: + if (++(p_) == pe) + goto _test_eof81; + case 81: + switch ((*(p_))) { + case 95: + goto tr33; + case 114: + goto tr125; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st82: + if (++(p_) == pe) + goto _test_eof82; + case 82: + switch ((*(p_))) { + case 95: + goto tr33; + case 104: + goto st83; + case 105: + goto st86; + case 116: + goto st93; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st83: + if (++(p_) == pe) + goto _test_eof83; + case 83: + switch ((*(p_))) { + case 95: + goto tr33; + case 111: + goto st84; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st84: + if (++(p_) == pe) + goto _test_eof84; + case 84: + switch ((*(p_))) { + case 95: + goto tr33; + case 114: + goto st85; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st85: + if (++(p_) == pe) + goto _test_eof85; + case 85: + switch ((*(p_))) { + case 95: + goto tr33; + case 116: + goto tr131; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st86: + if (++(p_) == pe) + goto _test_eof86; + case 86: + switch ((*(p_))) { + case 95: + goto tr33; + case 103: + goto st87; + case 122: + goto st90; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 121) + goto tr33; + } else + goto tr33; + goto tr58; + st87: + if (++(p_) == pe) + goto _test_eof87; + case 87: + switch ((*(p_))) { + case 95: + goto tr33; + case 110: + goto st88; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st88: + if (++(p_) == pe) + goto _test_eof88; + case 88: + switch ((*(p_))) { + case 95: + goto tr33; + case 101: + goto st89; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st89: + if (++(p_) == pe) + goto _test_eof89; + case 89: + switch ((*(p_))) { + case 95: + goto tr33; + case 100: + goto tr136; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st90: + if (++(p_) == pe) + goto _test_eof90; + case 90: + switch ((*(p_))) { + case 95: + goto tr33; + case 101: + goto st91; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st91: + if (++(p_) == pe) + goto _test_eof91; + case 91: + if ((*(p_)) == 95) + goto st92; + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st92: + if (++(p_) == pe) + goto _test_eof92; + case 92: + switch ((*(p_))) { + case 95: + goto tr33; + case 116: + goto tr139; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st93: + if (++(p_) == pe) + goto _test_eof93; + case 93: + switch ((*(p_))) { + case 95: + goto tr33; + case 97: + goto st94; + case 114: + goto st97; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (98 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st94: + if (++(p_) == pe) + goto _test_eof94; + case 94: + switch ((*(p_))) { + case 95: + goto tr33; + case 116: + goto st95; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st95: + if (++(p_) == pe) + goto _test_eof95; + case 95: + switch ((*(p_))) { + case 95: + goto tr33; + case 105: + goto st96; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st96: + if (++(p_) == pe) + goto _test_eof96; + case 96: + switch ((*(p_))) { + case 95: + goto tr33; + case 99: + goto tr144; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st97: + if (++(p_) == pe) + goto _test_eof97; + case 97: + switch ((*(p_))) { + case 95: + goto tr33; + case 117: + goto st98; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st98: + if (++(p_) == pe) + goto _test_eof98; + case 98: + switch ((*(p_))) { + case 95: + goto tr33; + case 99: + goto st99; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st99: + if (++(p_) == pe) + goto _test_eof99; + case 99: + switch ((*(p_))) { + case 95: + goto tr33; + case 116: + goto tr147; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st100: + if (++(p_) == pe) + goto _test_eof100; + case 100: + switch ((*(p_))) { + case 95: + goto tr33; + case 121: + goto st101; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st101: + if (++(p_) == pe) + goto _test_eof101; + case 101: + switch ((*(p_))) { + case 95: + goto tr33; + case 112: + goto st102; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st102: + if (++(p_) == pe) + goto _test_eof102; + case 102: + switch ((*(p_))) { + case 95: + goto tr33; + case 101: + goto st103; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st103: + if (++(p_) == pe) + goto _test_eof103; + case 103: + switch ((*(p_))) { + case 95: + goto tr33; + case 100: + goto st104; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st104: + if (++(p_) == pe) + goto _test_eof104; + case 104: + switch ((*(p_))) { + case 95: + goto tr33; + case 101: + goto st105; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st105: + if (++(p_) == pe) + goto _test_eof105; + case 105: + switch ((*(p_))) { + case 95: + goto tr33; + case 102: + goto tr153; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st106: + if (++(p_) == pe) + goto _test_eof106; + case 106: + switch ((*(p_))) { + case 95: + goto tr33; + case 105: + goto st107; + case 110: + goto st125; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st107: + if (++(p_) == pe) + goto _test_eof107; + case 107: + switch ((*(p_))) { + case 95: + goto tr33; + case 110: + goto st108; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st108: + if (++(p_) == pe) + goto _test_eof108; + case 108: + switch ((*(p_))) { + case 95: + goto tr33; + case 116: + goto st109; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st109: + if (++(p_) == pe) + goto _test_eof109; + case 109: + switch ((*(p_))) { + case 49: + goto st110; + case 51: + goto st113; + case 54: + goto st116; + case 56: + goto st119; + case 95: + goto tr33; + case 112: + goto st121; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st110: + if (++(p_) == pe) + goto _test_eof110; + case 110: + switch ((*(p_))) { + case 54: + goto st111; + case 95: + goto tr33; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st111: + if (++(p_) == pe) + goto _test_eof111; + case 111: + if ((*(p_)) == 95) + goto st112; + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st112: + if (++(p_) == pe) + goto _test_eof112; + case 112: + switch ((*(p_))) { + case 95: + goto tr33; + case 116: + goto tr165; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st113: + if (++(p_) == pe) + goto _test_eof113; + case 113: + switch ((*(p_))) { + case 50: + goto st114; + case 95: + goto tr33; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st114: + if (++(p_) == pe) + goto _test_eof114; + case 114: + if ((*(p_)) == 95) + goto st115; + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st115: + if (++(p_) == pe) + goto _test_eof115; + case 115: + switch ((*(p_))) { + case 95: + goto tr33; + case 116: + goto tr168; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st116: + if (++(p_) == pe) + goto _test_eof116; + case 116: + switch ((*(p_))) { + case 52: + goto st117; + case 95: + goto tr33; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st117: + if (++(p_) == pe) + goto _test_eof117; + case 117: + if ((*(p_)) == 95) + goto st118; + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st118: + if (++(p_) == pe) + goto _test_eof118; + case 118: + switch ((*(p_))) { + case 95: + goto tr33; + case 116: + goto tr171; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st119: + if (++(p_) == pe) + goto _test_eof119; + case 119: + if ((*(p_)) == 95) + goto st120; + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st120: + if (++(p_) == pe) + goto _test_eof120; + case 120: + switch ((*(p_))) { + case 95: + goto tr33; + case 116: + goto tr173; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st121: + if (++(p_) == pe) + goto _test_eof121; + case 121: + switch ((*(p_))) { + case 95: + goto tr33; + case 116: + goto st122; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st122: + if (++(p_) == pe) + goto _test_eof122; + case 122: + switch ((*(p_))) { + case 95: + goto tr33; + case 114: + goto st123; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st123: + if (++(p_) == pe) + goto _test_eof123; + case 123: + if ((*(p_)) == 95) + goto st124; + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st124: + if (++(p_) == pe) + goto _test_eof124; + case 124: + switch ((*(p_))) { + case 95: + goto tr33; + case 116: + goto tr177; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st125: + if (++(p_) == pe) + goto _test_eof125; + case 125: + switch ((*(p_))) { + case 95: + goto tr33; + case 105: + goto st126; + case 115: + goto st128; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st126: + if (++(p_) == pe) + goto _test_eof126; + case 126: + switch ((*(p_))) { + case 95: + goto tr33; + case 111: + goto st127; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st127: + if (++(p_) == pe) + goto _test_eof127; + case 127: + switch ((*(p_))) { + case 95: + goto tr33; + case 110: + goto tr181; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st128: + if (++(p_) == pe) + goto _test_eof128; + case 128: + switch ((*(p_))) { + case 95: + goto tr33; + case 105: + goto st129; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st129: + if (++(p_) == pe) + goto _test_eof129; + case 129: + switch ((*(p_))) { + case 95: + goto tr33; + case 103: + goto st130; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st130: + if (++(p_) == pe) + goto _test_eof130; + case 130: + switch ((*(p_))) { + case 95: + goto tr33; + case 110: + goto st131; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st131: + if (++(p_) == pe) + goto _test_eof131; + case 131: + switch ((*(p_))) { + case 95: + goto tr33; + case 101: + goto st132; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st132: + if (++(p_) == pe) + goto _test_eof132; + case 132: + switch ((*(p_))) { + case 95: + goto tr33; + case 100: + goto tr186; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st133: + if (++(p_) == pe) + goto _test_eof133; + case 133: + switch ((*(p_))) { + case 95: + goto tr33; + case 111: + goto st134; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st134: + if (++(p_) == pe) + goto _test_eof134; + case 134: + switch ((*(p_))) { + case 95: + goto tr33; + case 105: + goto st135; + case 108: + goto st136; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st135: + if (++(p_) == pe) + goto _test_eof135; + case 135: + switch ((*(p_))) { + case 95: + goto tr33; + case 100: + goto tr190; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st136: + if (++(p_) == pe) + goto _test_eof136; + case 136: + switch ((*(p_))) { + case 95: + goto tr33; + case 97: + goto st137; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (98 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st137: + if (++(p_) == pe) + goto _test_eof137; + case 137: + switch ((*(p_))) { + case 95: + goto tr33; + case 116: + goto st138; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st138: + if (++(p_) == pe) + goto _test_eof138; + case 138: + switch ((*(p_))) { + case 95: + goto tr33; + case 105: + goto st139; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st139: + if (++(p_) == pe) + goto _test_eof139; + case 139: + switch ((*(p_))) { + case 95: + goto tr33; + case 108: + goto st140; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st140: + if (++(p_) == pe) + goto _test_eof140; + case 140: + switch ((*(p_))) { + case 95: + goto tr33; + case 101: + goto tr195; + } + if ((*(p_)) < 65) { + if (48 <= (*(p_)) && (*(p_)) <= 57) + goto tr33; + } else if ((*(p_)) > 90) { + if (97 <= (*(p_)) && (*(p_)) <= 122) + goto tr33; + } else + goto tr33; + goto tr58; + st12: #line 1 "NONE" - {ts = 0;} - if ( ++( p_) == pe ) - goto _test_eof12; -case 12: + { + ts = 0; + } + if (++(p_) == pe) + goto _test_eof12; + case 12: #line 2792 "lexer_generated.cpp" - if ( (*( p_)) == 42 ) - goto st13; - goto st12; -st13: - if ( ++( p_) == pe ) - goto _test_eof13; -case 13: - switch( (*( p_)) ) { - case 42: goto st13; - case 47: goto tr19; - } - goto st12; -tr19: + if ((*(p_)) == 42) + goto st13; + goto st12; + st13: + if (++(p_) == pe) + goto _test_eof13; + case 13: + switch ((*(p_))) { + case 42: + goto st13; + case 47: + goto tr19; + } + goto st12; + tr19: #line 54 "lexer.rl" - { {goto st14;} } - goto st141; -st141: - if ( ++( p_) == pe ) - goto _test_eof141; -case 141: + { + { goto st14; } + } + goto st141; + st141: + if (++(p_) == pe) + goto _test_eof141; + case 141: #line 2813 "lexer_generated.cpp" - goto st0; - } - _test_eof14: cs = 14; goto _test_eof; - _test_eof1: cs = 1; goto _test_eof; - _test_eof2: cs = 2; goto _test_eof; - _test_eof15: cs = 15; goto _test_eof; - _test_eof3: cs = 3; goto _test_eof; - _test_eof4: cs = 4; goto _test_eof; - _test_eof16: cs = 16; goto _test_eof; - _test_eof5: cs = 5; goto _test_eof; - _test_eof6: cs = 6; goto _test_eof; - _test_eof17: cs = 17; goto _test_eof; - _test_eof18: cs = 18; goto _test_eof; - _test_eof7: cs = 7; goto _test_eof; - _test_eof8: cs = 8; goto _test_eof; - _test_eof9: cs = 9; goto _test_eof; - _test_eof10: cs = 10; goto _test_eof; - _test_eof19: cs = 19; goto _test_eof; - _test_eof11: cs = 11; goto _test_eof; - _test_eof20: cs = 20; goto _test_eof; - _test_eof21: cs = 21; goto _test_eof; - _test_eof22: cs = 22; goto _test_eof; - _test_eof23: cs = 23; goto _test_eof; - _test_eof24: cs = 24; goto _test_eof; - _test_eof25: cs = 25; goto _test_eof; - _test_eof26: cs = 26; goto _test_eof; - _test_eof27: cs = 27; goto _test_eof; - _test_eof28: cs = 28; goto _test_eof; - _test_eof29: cs = 29; goto _test_eof; - _test_eof30: cs = 30; goto _test_eof; - _test_eof31: cs = 31; goto _test_eof; - _test_eof32: cs = 32; goto _test_eof; - _test_eof33: cs = 33; goto _test_eof; - _test_eof34: cs = 34; goto _test_eof; - _test_eof35: cs = 35; goto _test_eof; - _test_eof36: cs = 36; goto _test_eof; - _test_eof37: cs = 37; goto _test_eof; - _test_eof38: cs = 38; goto _test_eof; - _test_eof39: cs = 39; goto _test_eof; - _test_eof40: cs = 40; goto _test_eof; - _test_eof41: cs = 41; goto _test_eof; - _test_eof42: cs = 42; goto _test_eof; - _test_eof43: cs = 43; goto _test_eof; - _test_eof44: cs = 44; goto _test_eof; - _test_eof45: cs = 45; goto _test_eof; - _test_eof46: cs = 46; goto _test_eof; - _test_eof47: cs = 47; goto _test_eof; - _test_eof48: cs = 48; goto _test_eof; - _test_eof49: cs = 49; goto _test_eof; - _test_eof50: cs = 50; goto _test_eof; - _test_eof51: cs = 51; goto _test_eof; - _test_eof52: cs = 52; goto _test_eof; - _test_eof53: cs = 53; goto _test_eof; - _test_eof54: cs = 54; goto _test_eof; - _test_eof55: cs = 55; goto _test_eof; - _test_eof56: cs = 56; goto _test_eof; - _test_eof57: cs = 57; goto _test_eof; - _test_eof58: cs = 58; goto _test_eof; - _test_eof59: cs = 59; goto _test_eof; - _test_eof60: cs = 60; goto _test_eof; - _test_eof61: cs = 61; goto _test_eof; - _test_eof62: cs = 62; goto _test_eof; - _test_eof63: cs = 63; goto _test_eof; - _test_eof64: cs = 64; goto _test_eof; - _test_eof65: cs = 65; goto _test_eof; - _test_eof66: cs = 66; goto _test_eof; - _test_eof67: cs = 67; goto _test_eof; - _test_eof68: cs = 68; goto _test_eof; - _test_eof69: cs = 69; goto _test_eof; - _test_eof70: cs = 70; goto _test_eof; - _test_eof71: cs = 71; goto _test_eof; - _test_eof72: cs = 72; goto _test_eof; - _test_eof73: cs = 73; goto _test_eof; - _test_eof74: cs = 74; goto _test_eof; - _test_eof75: cs = 75; goto _test_eof; - _test_eof76: cs = 76; goto _test_eof; - _test_eof77: cs = 77; goto _test_eof; - _test_eof78: cs = 78; goto _test_eof; - _test_eof79: cs = 79; goto _test_eof; - _test_eof80: cs = 80; goto _test_eof; - _test_eof81: cs = 81; goto _test_eof; - _test_eof82: cs = 82; goto _test_eof; - _test_eof83: cs = 83; goto _test_eof; - _test_eof84: cs = 84; goto _test_eof; - _test_eof85: cs = 85; goto _test_eof; - _test_eof86: cs = 86; goto _test_eof; - _test_eof87: cs = 87; goto _test_eof; - _test_eof88: cs = 88; goto _test_eof; - _test_eof89: cs = 89; goto _test_eof; - _test_eof90: cs = 90; goto _test_eof; - _test_eof91: cs = 91; goto _test_eof; - _test_eof92: cs = 92; goto _test_eof; - _test_eof93: cs = 93; goto _test_eof; - _test_eof94: cs = 94; goto _test_eof; - _test_eof95: cs = 95; goto _test_eof; - _test_eof96: cs = 96; goto _test_eof; - _test_eof97: cs = 97; goto _test_eof; - _test_eof98: cs = 98; goto _test_eof; - _test_eof99: cs = 99; goto _test_eof; - _test_eof100: cs = 100; goto _test_eof; - _test_eof101: cs = 101; goto _test_eof; - _test_eof102: cs = 102; goto _test_eof; - _test_eof103: cs = 103; goto _test_eof; - _test_eof104: cs = 104; goto _test_eof; - _test_eof105: cs = 105; goto _test_eof; - _test_eof106: cs = 106; goto _test_eof; - _test_eof107: cs = 107; goto _test_eof; - _test_eof108: cs = 108; goto _test_eof; - _test_eof109: cs = 109; goto _test_eof; - _test_eof110: cs = 110; goto _test_eof; - _test_eof111: cs = 111; goto _test_eof; - _test_eof112: cs = 112; goto _test_eof; - _test_eof113: cs = 113; goto _test_eof; - _test_eof114: cs = 114; goto _test_eof; - _test_eof115: cs = 115; goto _test_eof; - _test_eof116: cs = 116; goto _test_eof; - _test_eof117: cs = 117; goto _test_eof; - _test_eof118: cs = 118; goto _test_eof; - _test_eof119: cs = 119; goto _test_eof; - _test_eof120: cs = 120; goto _test_eof; - _test_eof121: cs = 121; goto _test_eof; - _test_eof122: cs = 122; goto _test_eof; - _test_eof123: cs = 123; goto _test_eof; - _test_eof124: cs = 124; goto _test_eof; - _test_eof125: cs = 125; goto _test_eof; - _test_eof126: cs = 126; goto _test_eof; - _test_eof127: cs = 127; goto _test_eof; - _test_eof128: cs = 128; goto _test_eof; - _test_eof129: cs = 129; goto _test_eof; - _test_eof130: cs = 130; goto _test_eof; - _test_eof131: cs = 131; goto _test_eof; - _test_eof132: cs = 132; goto _test_eof; - _test_eof133: cs = 133; goto _test_eof; - _test_eof134: cs = 134; goto _test_eof; - _test_eof135: cs = 135; goto _test_eof; - _test_eof136: cs = 136; goto _test_eof; - _test_eof137: cs = 137; goto _test_eof; - _test_eof138: cs = 138; goto _test_eof; - _test_eof139: cs = 139; goto _test_eof; - _test_eof140: cs = 140; goto _test_eof; - _test_eof12: cs = 12; goto _test_eof; - _test_eof13: cs = 13; goto _test_eof; - _test_eof141: cs = 141; goto _test_eof; + goto st0; + } + _test_eof14: + cs = 14; + goto _test_eof; + _test_eof1: + cs = 1; + goto _test_eof; + _test_eof2: + cs = 2; + goto _test_eof; + _test_eof15: + cs = 15; + goto _test_eof; + _test_eof3: + cs = 3; + goto _test_eof; + _test_eof4: + cs = 4; + goto _test_eof; + _test_eof16: + cs = 16; + goto _test_eof; + _test_eof5: + cs = 5; + goto _test_eof; + _test_eof6: + cs = 6; + goto _test_eof; + _test_eof17: + cs = 17; + goto _test_eof; + _test_eof18: + cs = 18; + goto _test_eof; + _test_eof7: + cs = 7; + goto _test_eof; + _test_eof8: + cs = 8; + goto _test_eof; + _test_eof9: + cs = 9; + goto _test_eof; + _test_eof10: + cs = 10; + goto _test_eof; + _test_eof19: + cs = 19; + goto _test_eof; + _test_eof11: + cs = 11; + goto _test_eof; + _test_eof20: + cs = 20; + goto _test_eof; + _test_eof21: + cs = 21; + goto _test_eof; + _test_eof22: + cs = 22; + goto _test_eof; + _test_eof23: + cs = 23; + goto _test_eof; + _test_eof24: + cs = 24; + goto _test_eof; + _test_eof25: + cs = 25; + goto _test_eof; + _test_eof26: + cs = 26; + goto _test_eof; + _test_eof27: + cs = 27; + goto _test_eof; + _test_eof28: + cs = 28; + goto _test_eof; + _test_eof29: + cs = 29; + goto _test_eof; + _test_eof30: + cs = 30; + goto _test_eof; + _test_eof31: + cs = 31; + goto _test_eof; + _test_eof32: + cs = 32; + goto _test_eof; + _test_eof33: + cs = 33; + goto _test_eof; + _test_eof34: + cs = 34; + goto _test_eof; + _test_eof35: + cs = 35; + goto _test_eof; + _test_eof36: + cs = 36; + goto _test_eof; + _test_eof37: + cs = 37; + goto _test_eof; + _test_eof38: + cs = 38; + goto _test_eof; + _test_eof39: + cs = 39; + goto _test_eof; + _test_eof40: + cs = 40; + goto _test_eof; + _test_eof41: + cs = 41; + goto _test_eof; + _test_eof42: + cs = 42; + goto _test_eof; + _test_eof43: + cs = 43; + goto _test_eof; + _test_eof44: + cs = 44; + goto _test_eof; + _test_eof45: + cs = 45; + goto _test_eof; + _test_eof46: + cs = 46; + goto _test_eof; + _test_eof47: + cs = 47; + goto _test_eof; + _test_eof48: + cs = 48; + goto _test_eof; + _test_eof49: + cs = 49; + goto _test_eof; + _test_eof50: + cs = 50; + goto _test_eof; + _test_eof51: + cs = 51; + goto _test_eof; + _test_eof52: + cs = 52; + goto _test_eof; + _test_eof53: + cs = 53; + goto _test_eof; + _test_eof54: + cs = 54; + goto _test_eof; + _test_eof55: + cs = 55; + goto _test_eof; + _test_eof56: + cs = 56; + goto _test_eof; + _test_eof57: + cs = 57; + goto _test_eof; + _test_eof58: + cs = 58; + goto _test_eof; + _test_eof59: + cs = 59; + goto _test_eof; + _test_eof60: + cs = 60; + goto _test_eof; + _test_eof61: + cs = 61; + goto _test_eof; + _test_eof62: + cs = 62; + goto _test_eof; + _test_eof63: + cs = 63; + goto _test_eof; + _test_eof64: + cs = 64; + goto _test_eof; + _test_eof65: + cs = 65; + goto _test_eof; + _test_eof66: + cs = 66; + goto _test_eof; + _test_eof67: + cs = 67; + goto _test_eof; + _test_eof68: + cs = 68; + goto _test_eof; + _test_eof69: + cs = 69; + goto _test_eof; + _test_eof70: + cs = 70; + goto _test_eof; + _test_eof71: + cs = 71; + goto _test_eof; + _test_eof72: + cs = 72; + goto _test_eof; + _test_eof73: + cs = 73; + goto _test_eof; + _test_eof74: + cs = 74; + goto _test_eof; + _test_eof75: + cs = 75; + goto _test_eof; + _test_eof76: + cs = 76; + goto _test_eof; + _test_eof77: + cs = 77; + goto _test_eof; + _test_eof78: + cs = 78; + goto _test_eof; + _test_eof79: + cs = 79; + goto _test_eof; + _test_eof80: + cs = 80; + goto _test_eof; + _test_eof81: + cs = 81; + goto _test_eof; + _test_eof82: + cs = 82; + goto _test_eof; + _test_eof83: + cs = 83; + goto _test_eof; + _test_eof84: + cs = 84; + goto _test_eof; + _test_eof85: + cs = 85; + goto _test_eof; + _test_eof86: + cs = 86; + goto _test_eof; + _test_eof87: + cs = 87; + goto _test_eof; + _test_eof88: + cs = 88; + goto _test_eof; + _test_eof89: + cs = 89; + goto _test_eof; + _test_eof90: + cs = 90; + goto _test_eof; + _test_eof91: + cs = 91; + goto _test_eof; + _test_eof92: + cs = 92; + goto _test_eof; + _test_eof93: + cs = 93; + goto _test_eof; + _test_eof94: + cs = 94; + goto _test_eof; + _test_eof95: + cs = 95; + goto _test_eof; + _test_eof96: + cs = 96; + goto _test_eof; + _test_eof97: + cs = 97; + goto _test_eof; + _test_eof98: + cs = 98; + goto _test_eof; + _test_eof99: + cs = 99; + goto _test_eof; + _test_eof100: + cs = 100; + goto _test_eof; + _test_eof101: + cs = 101; + goto _test_eof; + _test_eof102: + cs = 102; + goto _test_eof; + _test_eof103: + cs = 103; + goto _test_eof; + _test_eof104: + cs = 104; + goto _test_eof; + _test_eof105: + cs = 105; + goto _test_eof; + _test_eof106: + cs = 106; + goto _test_eof; + _test_eof107: + cs = 107; + goto _test_eof; + _test_eof108: + cs = 108; + goto _test_eof; + _test_eof109: + cs = 109; + goto _test_eof; + _test_eof110: + cs = 110; + goto _test_eof; + _test_eof111: + cs = 111; + goto _test_eof; + _test_eof112: + cs = 112; + goto _test_eof; + _test_eof113: + cs = 113; + goto _test_eof; + _test_eof114: + cs = 114; + goto _test_eof; + _test_eof115: + cs = 115; + goto _test_eof; + _test_eof116: + cs = 116; + goto _test_eof; + _test_eof117: + cs = 117; + goto _test_eof; + _test_eof118: + cs = 118; + goto _test_eof; + _test_eof119: + cs = 119; + goto _test_eof; + _test_eof120: + cs = 120; + goto _test_eof; + _test_eof121: + cs = 121; + goto _test_eof; + _test_eof122: + cs = 122; + goto _test_eof; + _test_eof123: + cs = 123; + goto _test_eof; + _test_eof124: + cs = 124; + goto _test_eof; + _test_eof125: + cs = 125; + goto _test_eof; + _test_eof126: + cs = 126; + goto _test_eof; + _test_eof127: + cs = 127; + goto _test_eof; + _test_eof128: + cs = 128; + goto _test_eof; + _test_eof129: + cs = 129; + goto _test_eof; + _test_eof130: + cs = 130; + goto _test_eof; + _test_eof131: + cs = 131; + goto _test_eof; + _test_eof132: + cs = 132; + goto _test_eof; + _test_eof133: + cs = 133; + goto _test_eof; + _test_eof134: + cs = 134; + goto _test_eof; + _test_eof135: + cs = 135; + goto _test_eof; + _test_eof136: + cs = 136; + goto _test_eof; + _test_eof137: + cs = 137; + goto _test_eof; + _test_eof138: + cs = 138; + goto _test_eof; + _test_eof139: + cs = 139; + goto _test_eof; + _test_eof140: + cs = 140; + goto _test_eof; + _test_eof12: + cs = 12; + goto _test_eof; + _test_eof13: + cs = 13; + goto _test_eof; + _test_eof141: + cs = 141; + goto _test_eof; - _test_eof: {} - if ( ( p_) == eof ) - { - switch ( cs ) { - case 15: goto tr51; - case 3: goto tr4; - case 4: goto tr4; - case 16: goto tr51; - case 17: goto tr53; - case 18: goto tr53; - case 7: goto tr10; - case 8: goto tr10; - case 9: goto tr10; - case 10: goto tr10; - case 19: goto tr53; - case 11: goto tr10; - case 20: goto tr53; - case 21: goto tr53; - case 22: goto tr4; - case 23: goto tr58; - case 24: goto tr58; - case 25: goto tr58; - case 26: goto tr58; - case 27: goto tr58; - case 28: goto tr58; - case 29: goto tr58; - case 30: goto tr58; - case 31: goto tr58; - case 32: goto tr58; - case 33: goto tr58; - case 34: goto tr58; - case 35: goto tr58; - case 36: goto tr58; - case 37: goto tr58; - case 38: goto tr58; - case 39: goto tr58; - case 40: goto tr58; - case 41: goto tr58; - case 42: goto tr58; - case 43: goto tr58; - case 44: goto tr58; - case 45: goto tr58; - case 46: goto tr58; - case 47: goto tr58; - case 48: goto tr58; - case 49: goto tr58; - case 50: goto tr58; - case 51: goto tr58; - case 52: goto tr58; - case 53: goto tr58; - case 54: goto tr58; - case 55: goto tr58; - case 56: goto tr95; - case 57: goto tr58; - case 58: goto tr58; - case 59: goto tr58; - case 60: goto tr58; - case 61: goto tr58; - case 62: goto tr58; - case 63: goto tr58; - case 64: goto tr58; - case 65: goto tr58; - case 66: goto tr58; - case 67: goto tr58; - case 68: goto tr58; - case 69: goto tr58; - case 70: goto tr58; - case 71: goto tr58; - case 72: goto tr58; - case 73: goto tr58; - case 74: goto tr58; - case 75: goto tr58; - case 76: goto tr58; - case 77: goto tr58; - case 78: goto tr58; - case 79: goto tr58; - case 80: goto tr58; - case 81: goto tr58; - case 82: goto tr58; - case 83: goto tr58; - case 84: goto tr58; - case 85: goto tr58; - case 86: goto tr58; - case 87: goto tr58; - case 88: goto tr58; - case 89: goto tr58; - case 90: goto tr58; - case 91: goto tr58; - case 92: goto tr58; - case 93: goto tr58; - case 94: goto tr58; - case 95: goto tr58; - case 96: goto tr58; - case 97: goto tr58; - case 98: goto tr58; - case 99: goto tr58; - case 100: goto tr58; - case 101: goto tr58; - case 102: goto tr58; - case 103: goto tr58; - case 104: goto tr58; - case 105: goto tr58; - case 106: goto tr58; - case 107: goto tr58; - case 108: goto tr58; - case 109: goto tr58; - case 110: goto tr58; - case 111: goto tr58; - case 112: goto tr58; - case 113: goto tr58; - case 114: goto tr58; - case 115: goto tr58; - case 116: goto tr58; - case 117: goto tr58; - case 118: goto tr58; - case 119: goto tr58; - case 120: goto tr58; - case 121: goto tr58; - case 122: goto tr58; - case 123: goto tr58; - case 124: goto tr58; - case 125: goto tr58; - case 126: goto tr58; - case 127: goto tr58; - case 128: goto tr58; - case 129: goto tr58; - case 130: goto tr58; - case 131: goto tr58; - case 132: goto tr58; - case 133: goto tr58; - case 134: goto tr58; - case 135: goto tr58; - case 136: goto tr58; - case 137: goto tr58; - case 138: goto tr58; - case 139: goto tr58; - case 140: goto tr58; - } - } + _test_eof: {} + if ((p_) == eof) { + switch (cs) { + case 15: + goto tr51; + case 3: + goto tr4; + case 4: + goto tr4; + case 16: + goto tr51; + case 17: + goto tr53; + case 18: + goto tr53; + case 7: + goto tr10; + case 8: + goto tr10; + case 9: + goto tr10; + case 10: + goto tr10; + case 19: + goto tr53; + case 11: + goto tr10; + case 20: + goto tr53; + case 21: + goto tr53; + case 22: + goto tr4; + case 23: + goto tr58; + case 24: + goto tr58; + case 25: + goto tr58; + case 26: + goto tr58; + case 27: + goto tr58; + case 28: + goto tr58; + case 29: + goto tr58; + case 30: + goto tr58; + case 31: + goto tr58; + case 32: + goto tr58; + case 33: + goto tr58; + case 34: + goto tr58; + case 35: + goto tr58; + case 36: + goto tr58; + case 37: + goto tr58; + case 38: + goto tr58; + case 39: + goto tr58; + case 40: + goto tr58; + case 41: + goto tr58; + case 42: + goto tr58; + case 43: + goto tr58; + case 44: + goto tr58; + case 45: + goto tr58; + case 46: + goto tr58; + case 47: + goto tr58; + case 48: + goto tr58; + case 49: + goto tr58; + case 50: + goto tr58; + case 51: + goto tr58; + case 52: + goto tr58; + case 53: + goto tr58; + case 54: + goto tr58; + case 55: + goto tr58; + case 56: + goto tr95; + case 57: + goto tr58; + case 58: + goto tr58; + case 59: + goto tr58; + case 60: + goto tr58; + case 61: + goto tr58; + case 62: + goto tr58; + case 63: + goto tr58; + case 64: + goto tr58; + case 65: + goto tr58; + case 66: + goto tr58; + case 67: + goto tr58; + case 68: + goto tr58; + case 69: + goto tr58; + case 70: + goto tr58; + case 71: + goto tr58; + case 72: + goto tr58; + case 73: + goto tr58; + case 74: + goto tr58; + case 75: + goto tr58; + case 76: + goto tr58; + case 77: + goto tr58; + case 78: + goto tr58; + case 79: + goto tr58; + case 80: + goto tr58; + case 81: + goto tr58; + case 82: + goto tr58; + case 83: + goto tr58; + case 84: + goto tr58; + case 85: + goto tr58; + case 86: + goto tr58; + case 87: + goto tr58; + case 88: + goto tr58; + case 89: + goto tr58; + case 90: + goto tr58; + case 91: + goto tr58; + case 92: + goto tr58; + case 93: + goto tr58; + case 94: + goto tr58; + case 95: + goto tr58; + case 96: + goto tr58; + case 97: + goto tr58; + case 98: + goto tr58; + case 99: + goto tr58; + case 100: + goto tr58; + case 101: + goto tr58; + case 102: + goto tr58; + case 103: + goto tr58; + case 104: + goto tr58; + case 105: + goto tr58; + case 106: + goto tr58; + case 107: + goto tr58; + case 108: + goto tr58; + case 109: + goto tr58; + case 110: + goto tr58; + case 111: + goto tr58; + case 112: + goto tr58; + case 113: + goto tr58; + case 114: + goto tr58; + case 115: + goto tr58; + case 116: + goto tr58; + case 117: + goto tr58; + case 118: + goto tr58; + case 119: + goto tr58; + case 120: + goto tr58; + case 121: + goto tr58; + case 122: + goto tr58; + case 123: + goto tr58; + case 124: + goto tr58; + case 125: + goto tr58; + case 126: + goto tr58; + case 127: + goto tr58; + case 128: + goto tr58; + case 129: + goto tr58; + case 130: + goto tr58; + case 131: + goto tr58; + case 132: + goto tr58; + case 133: + goto tr58; + case 134: + goto tr58; + case 135: + goto tr58; + case 136: + goto tr58; + case 137: + goto tr58; + case 138: + goto tr58; + case 139: + goto tr58; + case 140: + goto tr58; + } + } - _out: {} - } + _out: {} + } #line 118 "lexer.rl" diff --git a/compiler/ffi/c_parser/parsing_driver.cpp b/compiler/ffi/c_parser/parsing_driver.cpp index a20c1f82a7..ffd673f046 100644 --- a/compiler/ffi/c_parser/parsing_driver.cpp +++ b/compiler/ffi/c_parser/parsing_driver.cpp @@ -15,7 +15,7 @@ using namespace ffi; inline long parse_string_span(string_span s) { - const auto *start = s.data_; + const auto* start = s.data_; long result = 0; int base = 10; if (start[0] == '0' && start[1] == 'b') { @@ -34,19 +34,19 @@ inline long parse_string_span(string_span s) { static FFITypeKind int_type_by_size(size_t size, bool is_signed = true) { switch (size) { - case 1: - return is_signed ? FFITypeKind::Int8 : FFITypeKind::Uint8; - case 2: - return is_signed ? FFITypeKind::Int16 : FFITypeKind::Uint16; - case 4: - return is_signed ? FFITypeKind::Int32 : FFITypeKind::Uint32; - default: - return is_signed ? FFITypeKind::Int64 : FFITypeKind::Uint64; + case 1: + return is_signed ? FFITypeKind::Int8 : FFITypeKind::Uint8; + case 2: + return is_signed ? FFITypeKind::Int16 : FFITypeKind::Uint16; + case 4: + return is_signed ? FFITypeKind::Int32 : FFITypeKind::Uint32; + default: + return is_signed ? FFITypeKind::Int64 : FFITypeKind::Uint64; } } -static void finalize_types(FFIType *type) { - const auto finalize = [](const FFIType *type) { +static void finalize_types(FFIType* type) { + const auto finalize = [](const FFIType* type) { // we make an assumption that unsigned types have the same bit size as their signed counterparts static_assert(sizeof(unsigned) == sizeof(signed), "odd-sized unsigned"); static_assert(sizeof(unsigned long) == sizeof(signed long), "odd-sized unsigned long"); @@ -104,14 +104,14 @@ static void finalize_types(FFIType *type) { }; type->kind = finalize(type); - for (auto &member : type->members) { + for (auto& member : type->members) { finalize_types(member); } } -FFIType *ParsingDriver::function_to_var(FFIType *function) { +FFIType* ParsingDriver::function_to_var(FFIType* function) { function->kind = FFITypeKind::Var; - FFIType *function_ptr_type = alloc.new_type(FFITypeKind::FunctionPointer); + FFIType* function_ptr_type = alloc.new_type(FFITypeKind::FunctionPointer); function_ptr_type->members = std::move(function->members); function->members = {function_ptr_type}; return function; @@ -132,15 +132,15 @@ void ParsingDriver::add_missing_decls() { std::unordered_set declared_types; declared_types.reserve(types.size()); - for (const FFIType *type : types) { + for (const FFIType* type : types) { declared_types.insert(type->str); } - for (const auto &it : may_need_forward_decl) { + for (const auto& it : may_need_forward_decl) { if (vk::contains(declared_types, it.first)) { continue; } - FFIType *fwd_decl = alloc.new_type(it.second); + FFIType* fwd_decl = alloc.new_type(it.second); fwd_decl->str = it.first; add_type(fwd_decl); } @@ -153,7 +153,7 @@ ParsingDriver::Result ParsingDriver::parse() { add_missing_decls(); - for (FFIType *type : types) { + for (FFIType* type : types) { alloc.mark_used(type); } auto num_deleted = alloc.collect_garbage(); @@ -167,22 +167,20 @@ ParsingDriver::Result ParsingDriver::parse() { return result; } -void ParsingDriver::add_type(FFIType *type) { - vk::finally([&] () { - lexer.reset_comment(); - }); +void ParsingDriver::add_type(FFIType* type) { + vk::finally([&]() { lexer.reset_comment(); }); if (type->kind == FFITypeKind::Unknown) { return; } if (vk::any_of_equal(type->kind, FFITypeKind::Struct, FFITypeKind::Union)) { - FFIType *fwd_decl = alloc.new_type(type->kind == FFITypeKind::Struct ? FFITypeKind::StructDef : FFITypeKind::UnionDef); + FFIType* fwd_decl = alloc.new_type(type->kind == FFITypeKind::Struct ? FFITypeKind::StructDef : FFITypeKind::UnionDef); fwd_decl->str = type->str; add_type(fwd_decl); return; } if (type->kind == FFITypeKind::_typesList) { - for (const auto &x : type->members) { + for (const auto& x : type->members) { add_type(x); } return; @@ -191,8 +189,8 @@ void ParsingDriver::add_type(FFIType *type) { types.emplace_back(type); } -void ParsingDriver::add_typedef(FFIType *type, FFIType *declarator) { - FFIType *combined_type = combine(DeclarationSpecifiers{type}, Declarator{declarator}); +void ParsingDriver::add_typedef(FFIType* type, FFIType* declarator) { + FFIType* combined_type = combine(DeclarationSpecifiers{type}, Declarator{declarator}); finalize_types(combined_type); if (combined_type->kind == FFITypeKind::Function) { @@ -203,7 +201,7 @@ void ParsingDriver::add_typedef(FFIType *type, FFIType *declarator) { } std::string alias_name = combined_type->str; - FFIType *aliased_type = combined_type->members[0]; + FFIType* aliased_type = combined_type->members[0]; if (vk::any_of_equal(aliased_type->kind, FFITypeKind::Struct, FFITypeKind::Union)) { may_need_forward_decl.emplace(aliased_type->str, aliased_type->kind == FFITypeKind::Struct ? FFITypeKind::StructDef : FFITypeKind::UnionDef); @@ -217,7 +215,7 @@ void ParsingDriver::add_typedef(FFIType *type, FFIType *declarator) { } add_type(aliased_type); // save struct (or union) definition bool is_struct = (aliased_type->kind == FFITypeKind::StructDef); - FFIType *new_aliased_type = alloc.new_type(is_struct ? FFITypeKind::Struct : FFITypeKind::Union); + FFIType* new_aliased_type = alloc.new_type(is_struct ? FFITypeKind::Struct : FFITypeKind::Union); new_aliased_type->str = aliased_type->str; aliased_type = new_aliased_type; } @@ -228,7 +226,7 @@ void ParsingDriver::add_typedef(FFIType *type, FFIType *declarator) { if (aliased_type->str.empty()) { aliased_type->str = alias_name; } - FFIType *new_aliased_type = alloc.new_type(FFITypeKind::Enum); + FFIType* new_aliased_type = alloc.new_type(FFITypeKind::Enum); new_aliased_type->str = aliased_type->str; aliased_type = new_aliased_type; } @@ -239,7 +237,7 @@ void ParsingDriver::add_typedef(FFIType *type, FFIType *declarator) { } } -void ParsingDriver::add_enumerator(FFIType *enum_list, FFIType *enumerator) { +void ParsingDriver::add_enumerator(FFIType* enum_list, FFIType* enumerator) { int enum_value = enumerator->num; if (enumerator->num == 0 || enumerator->num == enum_list->num) { enum_value = enum_list->num++; @@ -254,19 +252,19 @@ int ParsingDriver::stoi(string_span s) { return parse_string_span(s); } -FFIType *ParsingDriver::combine(const TypeQualifier &type_qualifier, const DeclarationSpecifiers &decl_specs) { +FFIType* ParsingDriver::combine(const TypeQualifier& type_qualifier, const DeclarationSpecifiers& decl_specs) { return combine(TypeSpecifier{type_qualifier.type}, decl_specs); } -FFIType *ParsingDriver::combine(const TypeSpecifier &type_spec, const SpecifierQualifierList &list) { +FFIType* ParsingDriver::combine(const TypeSpecifier& type_spec, const SpecifierQualifierList& list) { return combine(type_spec, DeclarationSpecifiers{list.type}); } -FFIType *ParsingDriver::combine(const TypeQualifier &type_qualifier, const SpecifierQualifierList &list) { +FFIType* ParsingDriver::combine(const TypeQualifier& type_qualifier, const SpecifierQualifierList& list) { return combine(type_qualifier, DeclarationSpecifiers{list.type}); } -FFIType *ParsingDriver::combine(const TypeSpecifier &type_spec, const DeclarationSpecifiers &decl_specs) { +FFIType* ParsingDriver::combine(const TypeSpecifier& type_spec, const DeclarationSpecifiers& decl_specs) { // TODO: errors for things like combine(char, char). if (decl_specs.type->kind == FFITypeKind::_typeFlags && type_spec.type->kind != FFITypeKind::_typeFlags) { @@ -276,37 +274,37 @@ FFIType *ParsingDriver::combine(const TypeSpecifier &type_spec, const Declaratio if ((type_spec.type->flags & FFIType::Flag::Long) && (decl_specs.type->flags & FFIType::Flag::Long)) { flags |= FFIType::Flag::LongLong; } - FFIType *result = decl_specs.type; + FFIType* result = decl_specs.type; result->flags = static_cast(flags); return result; } -FFIType *ParsingDriver::combine(const DeclarationSpecifiers &decl_specs, const InitDeclaratorList &init_declarator_list) { - FFIType *result = alloc.new_type(FFITypeKind::_typesList); - for (auto &declarator : init_declarator_list.type->members) { +FFIType* ParsingDriver::combine(const DeclarationSpecifiers& decl_specs, const InitDeclaratorList& init_declarator_list) { + FFIType* result = alloc.new_type(FFITypeKind::_typesList); + for (auto& declarator : init_declarator_list.type->members) { // init_declarator is basically a simple declarator right now result->members.emplace_back(combine(decl_specs, Declarator{declarator})); } return result; } -FFIType *ParsingDriver::combine(const DeclarationSpecifiers &decl_specs, const Declarator &declarator) { +FFIType* ParsingDriver::combine(const DeclarationSpecifiers& decl_specs, const Declarator& declarator) { if (declarator.type->kind == FFITypeKind::Name) { - FFIType *result = alloc.new_type(FFITypeKind::Var); + FFIType* result = alloc.new_type(FFITypeKind::Var); result->str = declarator.type->str; result->members.emplace_back(decl_specs.type); return result; } if (declarator.type->kind == FFITypeKind::Function) { - FFIType *result = alloc.new_type(); + FFIType* result = alloc.new_type(); *result = *declarator.type; result->members[0] = decl_specs.type; return result; } if (declarator.type->kind == FFITypeKind::_pointerDeclarator) { - FFIType *ptr_type = alloc.new_type(FFITypeKind::Pointer); + FFIType* ptr_type = alloc.new_type(FFITypeKind::Pointer); ptr_type->num = declarator.type->num; // when typedef over a pointer is combined with a pointer type, we want to // merge it into a single pointer type with total indirection; @@ -321,73 +319,74 @@ FFIType *ParsingDriver::combine(const DeclarationSpecifiers &decl_specs, const D } if (declarator.type->kind == FFITypeKind::_arrayDeclarator) { - FFIType *array_type = alloc.new_type(FFITypeKind::Array); - FFIType *nested_declarator = combine_array_type(array_type, decl_specs.type, declarator.type); + FFIType* array_type = alloc.new_type(FFITypeKind::Array); + FFIType* nested_declarator = combine_array_type(array_type, decl_specs.type, declarator.type); return combine(DeclarationSpecifiers{array_type}, Declarator{nested_declarator}); } return nullptr; } -FFIType *ParsingDriver::combine(const Pointer &pointer, const DirectDeclarator &declarator) { - FFIType *result = alloc.new_type(FFITypeKind::_pointerDeclarator); +FFIType* ParsingDriver::combine(const Pointer& pointer, const DirectDeclarator& declarator) { + FFIType* result = alloc.new_type(FFITypeKind::_pointerDeclarator); result->num = pointer.type->num; result->members.emplace_back(declarator.type); return result; } -FFIType *ParsingDriver::combine(const Pointer &pointer, const DirectAbstractDeclarator &declarator) { +FFIType* ParsingDriver::combine(const Pointer& pointer, const DirectAbstractDeclarator& declarator) { return combine(pointer, DirectDeclarator{declarator.type}); } -FFIType *ParsingDriver::combine(const DeclarationSpecifiers &decl_specs, const AbstractDeclarator &declarator) { +FFIType* ParsingDriver::combine(const DeclarationSpecifiers& decl_specs, const AbstractDeclarator& declarator) { if (declarator.type->kind == FFITypeKind::Pointer) { - FFIType *ptr_declarator = alloc.new_type(FFITypeKind::_pointerDeclarator); + FFIType* ptr_declarator = alloc.new_type(FFITypeKind::_pointerDeclarator); ptr_declarator->num = declarator.type->num; - FFIType *name = alloc.new_type(FFITypeKind::Name); + FFIType* name = alloc.new_type(FFITypeKind::Name); ptr_declarator->members.emplace_back(name); return combine(decl_specs, Declarator{ptr_declarator}); } - return combine(decl_specs, Declarator{declarator.type});; + return combine(decl_specs, Declarator{declarator.type}); + ; } -FFIType *ParsingDriver::combine_array_type(FFIType *dst, FFIType *elem_type, FFIType *current) { +FFIType* ParsingDriver::combine_array_type(FFIType* dst, FFIType* elem_type, FFIType* current) { dst->num = current->num; if (current->members[0]->kind != FFITypeKind::_arrayDeclarator) { dst->members.emplace_back(elem_type); return current->members[0]; } - FFIType *nested_array_type = alloc.new_type(FFITypeKind::Array); - FFIType *declarator = combine_array_type(nested_array_type, elem_type, current->members[0]); + FFIType* nested_array_type = alloc.new_type(FFITypeKind::Array); + FFIType* declarator = combine_array_type(nested_array_type, elem_type, current->members[0]); dst->members.emplace_back(nested_array_type); return declarator; } -FFIType *ParsingDriver::make_enum_member(string_span name, int value) { - FFIType *result = alloc.new_type(FFITypeKind::_enumMember); +FFIType* ParsingDriver::make_enum_member(string_span name, int value) { + FFIType* result = alloc.new_type(FFITypeKind::_enumMember); result->str = name.to_string(); result->num = value; return result; } -FFIType *ParsingDriver::make_abstract_array_declarator(string_span size_str) { - FFIType *result = alloc.new_type(FFITypeKind::_arrayDeclarator); +FFIType* ParsingDriver::make_abstract_array_declarator(string_span size_str) { + FFIType* result = alloc.new_type(FFITypeKind::_arrayDeclarator); result->num = parse_string_span(size_str); - FFIType *name = alloc.new_type(FFITypeKind::Name); + FFIType* name = alloc.new_type(FFITypeKind::Name); result->members.emplace_back(name); return result; } -FFIType *ParsingDriver::make_array_declarator(FFIType *declarator, string_span size_str) { - FFIType *result = alloc.new_type(FFITypeKind::_arrayDeclarator); +FFIType* ParsingDriver::make_array_declarator(FFIType* declarator, string_span size_str) { + FFIType* result = alloc.new_type(FFITypeKind::_arrayDeclarator); result->num = parse_string_span(size_str); result->members.emplace_back(declarator); return result; } -FFIType *ParsingDriver::make_function(FFIType *func_expr, FFIType *params) { - FFIType *function_type = alloc.new_type(FFITypeKind::Function); +FFIType* ParsingDriver::make_function(FFIType* func_expr, FFIType* params) { + FFIType* function_type = alloc.new_type(FFITypeKind::Function); kphp_assert(vk::any_of_equal(func_expr->kind, FFITypeKind::Name, FFITypeKind::_pointerDeclarator)); bool is_func_ptr = func_expr->kind == FFITypeKind::_pointerDeclarator; if (is_func_ptr) { @@ -404,7 +403,7 @@ FFIType *ParsingDriver::make_function(FFIType *func_expr, FFIType *params) { function_type->flags = static_cast(function_type->flags | FFIType::Flag::SignalSafe); } } - FFIType *result_type_placeholder = alloc.new_type(); // return type will be inserted here later + FFIType* result_type_placeholder = alloc.new_type(); // return type will be inserted here later function_type->members.emplace_back(result_type_placeholder); if (params) { // nullptr for a func with an empty param list if (!expr_mode && params->members.size() == 1 && params->members[0]->kind == FFITypeKind::Void) { @@ -412,7 +411,7 @@ FFIType *ParsingDriver::make_function(FFIType *func_expr, FFIType *params) { return function_type; } - for (FFIType *p : params->members) { + for (FFIType* p : params->members) { if (p->kind == FFITypeKind::_ellipsis) { function_type->flags = static_cast(function_type->flags | FFIType::Flag::Variadic); continue; @@ -424,7 +423,7 @@ FFIType *ParsingDriver::make_function(FFIType *func_expr, FFIType *params) { } else if (p->kind == FFITypeKind::Var) { function_type->members.emplace_back(p); } else { - FFIType *var = alloc.new_type(FFITypeKind::Var); + FFIType* var = alloc.new_type(FFITypeKind::Var); var->members.emplace_back(p); function_type->members.emplace_back(var); } @@ -433,29 +432,29 @@ FFIType *ParsingDriver::make_function(FFIType *func_expr, FFIType *params) { return function_type; } -FFIType *ParsingDriver::make_pointer() { - FFIType *ptr = alloc.new_type(FFITypeKind::Pointer); +FFIType* ParsingDriver::make_pointer() { + FFIType* ptr = alloc.new_type(FFITypeKind::Pointer); ptr->num = 1; return ptr; } -FFIType *ParsingDriver::make_union_def(FFIType *fields) { +FFIType* ParsingDriver::make_union_def(FFIType* fields) { return make_struct_or_union_def(fields, false); } -FFIType *ParsingDriver::make_struct_def(FFIType *fields) { +FFIType* ParsingDriver::make_struct_def(FFIType* fields) { return make_struct_or_union_def(fields, true); } -FFIType *ParsingDriver::make_struct_or_union_def(FFIType *fields, bool is_struct) { - FFIType *struct_type = alloc.new_type(is_struct ? FFITypeKind::StructDef : FFITypeKind::UnionDef); - for (FFIType *list : fields->members) { +FFIType* ParsingDriver::make_struct_or_union_def(FFIType* fields, bool is_struct) { + FFIType* struct_type = alloc.new_type(is_struct ? FFITypeKind::StructDef : FFITypeKind::UnionDef); + for (FFIType* list : fields->members) { kphp_assert(list->kind == FFITypeKind::_structFieldList); int num_names = list->members.size() - 1; for (int i = 0; i < num_names; i++) { - FFIType *declarator = list->members[i]; - FFIType *field_type = list->members.back(); - FFIType *field = combine(DeclarationSpecifiers{field_type}, Declarator{declarator}); + FFIType* declarator = list->members[i]; + FFIType* field_type = list->members.back(); + FFIType* field = combine(DeclarationSpecifiers{field_type}, Declarator{declarator}); if (field->kind == FFITypeKind::Function) { field = function_to_var(field); } @@ -465,7 +464,7 @@ FFIType *ParsingDriver::make_struct_or_union_def(FFIType *fields, bool is_struct return struct_type; } -void ParsingDriver::raise_error(const std::string &message) { +void ParsingDriver::raise_error(const std::string& message) { // TODO: better error locations, more context information ffi::Location loc{0, 0}; throw ParsingDriver::ParseError{loc, message}; diff --git a/compiler/ffi/c_parser/parsing_driver.h b/compiler/ffi/c_parser/parsing_driver.h index f406295467..a7185d6326 100644 --- a/compiler/ffi/c_parser/parsing_driver.h +++ b/compiler/ffi/c_parser/parsing_driver.h @@ -4,14 +4,14 @@ #pragma once -#include "compiler/ffi/ffi_types.h" #include "compiler/ffi/c_parser/lexer.h" #include "compiler/ffi/c_parser/parsing_types.h" #include "compiler/ffi/c_parser/types-allocator.h" #include "compiler/ffi/c_parser/yy_parser_generated.hpp" +#include "compiler/ffi/ffi_types.h" -#include #include +#include namespace ffi { @@ -39,60 +39,61 @@ class ParsingDriver { class ParseError : public std::exception { public: ParseError(ffi::Location location, std::string message) - : location{location} - , message{std::move(message)} {} + : location{location}, + message{std::move(message)} {} ffi::Location location; std::string message; }; - explicit ParsingDriver(const std::string &src, FFITypedefs &typedefs, bool expr_mode = false): - typedefs(typedefs), - expr_mode(expr_mode), - lexer(typedefs, src), - yy_parser(lexer, *this) { - } + explicit ParsingDriver(const std::string& src, FFITypedefs& typedefs, bool expr_mode = false) + : typedefs(typedefs), + expr_mode(expr_mode), + lexer(typedefs, src), + yy_parser(lexer, *this) {} Result parse(); - FFIType *get_aliased_type(string_span name) { + FFIType* get_aliased_type(string_span name) { return typedefs[name.to_string()]; } - void add_type(FFIType *type); - void add_typedef(FFIType *type, FFIType *declarator); - void add_enumerator(FFIType *enum_list, FFIType *enumerator); + void add_type(FFIType* type); + void add_typedef(FFIType* type, FFIType* declarator); + void add_enumerator(FFIType* enum_list, FFIType* enumerator); int stoi(string_span s); - FFIType *combine(const TypeSpecifier &type_spec, const SpecifierQualifierList &list); - FFIType *combine(const TypeQualifier &type_qualifier, const SpecifierQualifierList &list); - FFIType *combine(const TypeSpecifier &type_spec, const DeclarationSpecifiers &decl_specs); - FFIType *combine(const TypeQualifier &type_qualifier, const DeclarationSpecifiers &decl_specs); - FFIType *combine(const DeclarationSpecifiers &decl_specs, const InitDeclaratorList &init_declarator_list); - FFIType *combine(const DeclarationSpecifiers &decl_specs, const Declarator &declarator); - FFIType *combine(const DeclarationSpecifiers &decl_specs, const AbstractDeclarator &declarator); - FFIType *combine(const Pointer &pointer, const DirectDeclarator &declarator); - FFIType *combine(const Pointer &pointer, const DirectAbstractDeclarator &declarator); - - FFIType *make_simple_type(FFITypeKind kind) { + FFIType* combine(const TypeSpecifier& type_spec, const SpecifierQualifierList& list); + FFIType* combine(const TypeQualifier& type_qualifier, const SpecifierQualifierList& list); + FFIType* combine(const TypeSpecifier& type_spec, const DeclarationSpecifiers& decl_specs); + FFIType* combine(const TypeQualifier& type_qualifier, const DeclarationSpecifiers& decl_specs); + FFIType* combine(const DeclarationSpecifiers& decl_specs, const InitDeclaratorList& init_declarator_list); + FFIType* combine(const DeclarationSpecifiers& decl_specs, const Declarator& declarator); + FFIType* combine(const DeclarationSpecifiers& decl_specs, const AbstractDeclarator& declarator); + FFIType* combine(const Pointer& pointer, const DirectDeclarator& declarator); + FFIType* combine(const Pointer& pointer, const DirectAbstractDeclarator& declarator); + + FFIType* make_simple_type(FFITypeKind kind) { return alloc.new_type(kind); } - FFIType *make_simple_type(FFITypeKind kind, FFIType::Flag flags) { return alloc.new_type(kind, flags); } + FFIType* make_simple_type(FFITypeKind kind, FFIType::Flag flags) { + return alloc.new_type(kind, flags); + } - FFIType *make_enum_member(string_span name, int value); - FFIType *make_abstract_array_declarator(string_span size_str); - FFIType *make_array_declarator(FFIType *declarator, string_span size_str); - FFIType *make_function(FFIType *func_expr, FFIType *params); - FFIType *make_pointer(); - FFIType *make_struct_def(FFIType *fields); - FFIType *make_union_def(FFIType *fields); + FFIType* make_enum_member(string_span name, int value); + FFIType* make_abstract_array_declarator(string_span size_str); + FFIType* make_array_declarator(FFIType* declarator, string_span size_str); + FFIType* make_function(FFIType* func_expr, FFIType* params); + FFIType* make_pointer(); + FFIType* make_struct_def(FFIType* fields); + FFIType* make_union_def(FFIType* fields); friend class YYParser; private: - FFITypedefs &typedefs; + FFITypedefs& typedefs; bool expr_mode; Lexer lexer; YYParser yy_parser; @@ -101,12 +102,12 @@ class ParsingDriver { std::unordered_map may_need_forward_decl; std::map enum_constants; - FFIType *combine_array_type(FFIType *dst, FFIType *elem_type, FFIType *current); - FFIType *make_struct_or_union_def(FFIType *fields, bool is_struct); + FFIType* combine_array_type(FFIType* dst, FFIType* elem_type, FFIType* current); + FFIType* make_struct_or_union_def(FFIType* fields, bool is_struct); - FFIType *function_to_var(FFIType *function); + FFIType* function_to_var(FFIType* function); - void raise_error(const std::string &message); + void raise_error(const std::string& message); void add_missing_decls(); }; diff --git a/compiler/ffi/c_parser/parsing_types.h b/compiler/ffi/c_parser/parsing_types.h index d3bba0eda5..8d76686638 100644 --- a/compiler/ffi/c_parser/parsing_types.h +++ b/compiler/ffi/c_parser/parsing_types.h @@ -8,15 +8,35 @@ struct FFIType; namespace ffi { -struct TypeSpecifier { FFIType *type; }; -struct DeclarationSpecifiers { FFIType *type; }; -struct InitDeclaratorList { FFIType *type; }; -struct AbstractDeclarator { FFIType *type; }; -struct DirectAbstractDeclarator { FFIType *type; }; -struct DirectDeclarator { FFIType *type; }; -struct Declarator { FFIType *type; }; -struct TypeQualifier { FFIType *type; }; -struct Pointer { FFIType *type; }; -struct SpecifierQualifierList { FFIType *type; }; +struct TypeSpecifier { + FFIType* type; +}; +struct DeclarationSpecifiers { + FFIType* type; +}; +struct InitDeclaratorList { + FFIType* type; +}; +struct AbstractDeclarator { + FFIType* type; +}; +struct DirectAbstractDeclarator { + FFIType* type; +}; +struct DirectDeclarator { + FFIType* type; +}; +struct Declarator { + FFIType* type; +}; +struct TypeQualifier { + FFIType* type; +}; +struct Pointer { + FFIType* type; +}; +struct SpecifierQualifierList { + FFIType* type; +}; } // namespace ffi diff --git a/compiler/ffi/c_parser/string-span.h b/compiler/ffi/c_parser/string-span.h index c05ab96624..c7c78abf03 100644 --- a/compiler/ffi/c_parser/string-span.h +++ b/compiler/ffi/c_parser/string-span.h @@ -16,18 +16,18 @@ namespace ffi { // // As a workaround, we pass this string_span wrapper around the parser. struct string_span { - const char *data_; + const char* data_; size_t len_; string_span() = default; - string_span(const char *data) - : data_{data} - , len_{std::strlen(data)} {} + string_span(const char* data) + : data_{data}, + len_{std::strlen(data)} {} - string_span(const char *data, const char *data_end) - : data_{data} - , len_{static_cast(data_end - data)} {} + string_span(const char* data, const char* data_end) + : data_{data}, + len_{static_cast(data_end - data)} {} std::string to_string() const { return std::string{data_, len_}; diff --git a/compiler/ffi/c_parser/types-allocator.h b/compiler/ffi/c_parser/types-allocator.h index 103ca8d73c..80075f224c 100644 --- a/compiler/ffi/c_parser/types-allocator.h +++ b/compiler/ffi/c_parser/types-allocator.h @@ -27,10 +27,9 @@ namespace ffi { // TypesAllocator should not be shared between several C parsers. class TypesAllocator { public: - template - FFIType *new_type(Args&&... args) { - auto *type = new FFIType{std::forward(args)...}; + FFIType* new_type(Args&&... args) { + auto* type = new FFIType{std::forward(args)...}; allocated_.push_back(type); return type; } @@ -39,10 +38,10 @@ class TypesAllocator { return allocated_.size(); } - void mark_used(FFIType *type, bool recursive = true) const { + void mark_used(FFIType* type, bool recursive = true) const { type->flags = static_cast(type->flags | FFIType::Flag::Used); if (recursive) { - for (FFIType *member : type->members) { + for (FFIType* member : type->members) { mark_used(member, recursive); } } @@ -50,7 +49,7 @@ class TypesAllocator { uint64_t collect_garbage() const { uint64_t num_deleted = 0; - for (FFIType *type : allocated_) { + for (FFIType* type : allocated_) { if ((type->flags & FFIType::Flag::Used) == 0) { delete type; num_deleted++; diff --git a/compiler/ffi/c_parser/yy_parser_generated.cpp b/compiler/ffi/c_parser/yy_parser_generated.cpp index 1505d66820..933725ffc9 100644 --- a/compiler/ffi/c_parser/yy_parser_generated.cpp +++ b/compiler/ffi/c_parser/yy_parser_generated.cpp @@ -37,42 +37,38 @@ // "%code top" blocks. #line 41 "c.y" - #include "compiler/ffi/c_parser/lexer.h" - #include "compiler/ffi/c_parser/parsing_driver.h" - #include "compiler/ffi/c_parser/yy_parser_generated.hpp" +// The order of these includes is important: lexer.h must come before yy_parser_generated.hpp +#include "compiler/ffi/c_parser/lexer.h" +// +#include "compiler/ffi/c_parser/parsing_driver.h" +// +#include "compiler/ffi/c_parser/yy_parser_generated.hpp" - #define yylex(sym, loc) lexer.get_next_token((sym), (loc)) +#define yylex(sym, loc) lexer.get_next_token((sym), (loc)) #line 47 "yy_parser_generated.cpp" - - - #include "yy_parser_generated.hpp" - - - #ifndef YY_ -# if defined YYENABLE_NLS && YYENABLE_NLS -# if ENABLE_NLS -# include // FIXME: INFRINGES ON USER NAME SPACE. -# define YY_(msgid) dgettext ("bison-runtime", msgid) -# endif -# endif -# ifndef YY_ -# define YY_(msgid) msgid -# endif +#if defined YYENABLE_NLS && YYENABLE_NLS +#if ENABLE_NLS +#include // FIXME: INFRINGES ON USER NAME SPACE. +#define YY_(msgid) dgettext("bison-runtime", msgid) +#endif +#endif +#ifndef YY_ +#define YY_(msgid) msgid +#endif #endif - // Whether we are compiled with exception support. #ifndef YY_EXCEPTIONS -# if defined __GNUC__ && !defined __EXCEPTIONS -# define YY_EXCEPTIONS 0 -# else -# define YY_EXCEPTIONS 1 -# endif +#if defined __GNUC__ && !defined __EXCEPTIONS +#define YY_EXCEPTIONS 0 +#else +#define YY_EXCEPTIONS 1 +#endif #endif #define YYRHSLOC(Rhs, K) ((Rhs)[K].location) @@ -80,415 +76,337 @@ If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ -# ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (N) \ - { \ - (Current).begin = YYRHSLOC (Rhs, 1).begin; \ - (Current).end = YYRHSLOC (Rhs, N).end; \ - } \ - else \ - { \ - (Current).begin = (Current).end = YYRHSLOC (Rhs, 0).end; \ - } \ - while (false) -# endif - +#ifndef YYLLOC_DEFAULT +#define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (N) { \ + (Current).begin = YYRHSLOC(Rhs, 1).begin; \ + (Current).end = YYRHSLOC(Rhs, N).end; \ + } else { \ + (Current).begin = (Current).end = YYRHSLOC(Rhs, 0).end; \ + } \ + while (false) +#endif // Enable debugging if requested. #if YYDEBUG // A pseudo ostream that takes yydebug_ into account. -# define YYCDEBUG if (yydebug_) (*yycdebug_) - -# define YY_SYMBOL_PRINT(Title, Symbol) \ - do { \ - if (yydebug_) \ - { \ - *yycdebug_ << Title << ' '; \ - yy_print_ (*yycdebug_, Symbol); \ - *yycdebug_ << '\n'; \ - } \ +#define YYCDEBUG \ + if (yydebug_) \ + (*yycdebug_) + +#define YY_SYMBOL_PRINT(Title, Symbol) \ + do { \ + if (yydebug_) { \ + *yycdebug_ << Title << ' '; \ + yy_print_(*yycdebug_, Symbol); \ + *yycdebug_ << '\n'; \ + } \ } while (false) -# define YY_REDUCE_PRINT(Rule) \ - do { \ - if (yydebug_) \ - yy_reduce_print_ (Rule); \ +#define YY_REDUCE_PRINT(Rule) \ + do { \ + if (yydebug_) \ + yy_reduce_print_(Rule); \ } while (false) -# define YY_STACK_PRINT() \ - do { \ - if (yydebug_) \ - yy_stack_print_ (); \ +#define YY_STACK_PRINT() \ + do { \ + if (yydebug_) \ + yy_stack_print_(); \ } while (false) #else // !YYDEBUG -# define YYCDEBUG if (false) std::cerr -# define YY_SYMBOL_PRINT(Title, Symbol) YY_USE (Symbol) -# define YY_REDUCE_PRINT(Rule) static_cast (0) -# define YY_STACK_PRINT() static_cast (0) +#define YYCDEBUG \ + if (false) \ + std::cerr +#define YY_SYMBOL_PRINT(Title, Symbol) YY_USE(Symbol) +#define YY_REDUCE_PRINT(Rule) static_cast(0) +#define YY_STACK_PRINT() static_cast(0) #endif // !YYDEBUG -#define yyerrok (yyerrstatus_ = 0) -#define yyclearin (yyla.clear ()) +#define yyerrok (yyerrstatus_ = 0) +#define yyclearin (yyla.clear()) -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab -#define YYRECOVERING() (!!yyerrstatus_) +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab +#define YYRECOVERING() (!!yyerrstatus_) #line 13 "c.y" namespace ffi { #line 147 "yy_parser_generated.cpp" - /// Build a parser object. - YYParser::YYParser (ffi::Lexer &lexer_yyarg, ffi::ParsingDriver &driver_yyarg) +/// Build a parser object. +YYParser::YYParser(ffi::Lexer& lexer_yyarg, ffi::ParsingDriver& driver_yyarg) #if YYDEBUG - : yydebug_ (false), - yycdebug_ (&std::cerr), + : yydebug_(false), + yycdebug_(&std::cerr), #else : #endif - lexer (lexer_yyarg), - driver (driver_yyarg) - {} - - YYParser::~YYParser () - {} - - YYParser::syntax_error::~syntax_error () YY_NOEXCEPT YY_NOTHROW - {} - - /*---------------. - | symbol kinds. | - `---------------*/ - - // basic_symbol. - template - YYParser::basic_symbol::basic_symbol (const basic_symbol& that) - : Base (that) - , value (that.value) - , location (that.location) - {} - - - /// Constructor for valueless symbols. - template - YYParser::basic_symbol::basic_symbol (typename Base::kind_type t, YY_MOVE_REF (location_type) l) - : Base (t) - , value () - , location (l) - {} - - template - YYParser::basic_symbol::basic_symbol (typename Base::kind_type t, YY_RVREF (semantic_type) v, YY_RVREF (location_type) l) - : Base (t) - , value (YY_MOVE (v)) - , location (YY_MOVE (l)) - {} - - template - YYParser::symbol_kind_type - YYParser::basic_symbol::type_get () const YY_NOEXCEPT - { - return this->kind (); - } + lexer(lexer_yyarg), + driver(driver_yyarg) { +} - template - bool - YYParser::basic_symbol::empty () const YY_NOEXCEPT - { - return this->kind () == symbol_kind::S_YYEMPTY; - } +YYParser::~YYParser() {} + +YYParser::syntax_error::~syntax_error() YY_NOEXCEPT YY_NOTHROW {} + +/*---------------. +| symbol kinds. | +`---------------*/ + +// basic_symbol. +template +YYParser::basic_symbol::basic_symbol(const basic_symbol& that) + : Base(that), + value(that.value), + location(that.location) {} + +/// Constructor for valueless symbols. +template +YYParser::basic_symbol::basic_symbol(typename Base::kind_type t, YY_MOVE_REF(location_type) l) + : Base(t), + value(), + location(l) {} + +template +YYParser::basic_symbol::basic_symbol(typename Base::kind_type t, YY_RVREF(semantic_type) v, YY_RVREF(location_type) l) + : Base(t), + value(YY_MOVE(v)), + location(YY_MOVE(l)) {} + +template +YYParser::symbol_kind_type YYParser::basic_symbol::type_get() const YY_NOEXCEPT { + return this->kind(); +} - template - void - YYParser::basic_symbol::move (basic_symbol& s) - { - super_type::move (s); - value = YY_MOVE (s.value); - location = YY_MOVE (s.location); - } +template +bool YYParser::basic_symbol::empty() const YY_NOEXCEPT { + return this->kind() == symbol_kind::S_YYEMPTY; +} - // by_kind. - YYParser::by_kind::by_kind () - : kind_ (symbol_kind::S_YYEMPTY) - {} +template +void YYParser::basic_symbol::move(basic_symbol& s) { + super_type::move(s); + value = YY_MOVE(s.value); + location = YY_MOVE(s.location); +} + +// by_kind. +YYParser::by_kind::by_kind() + : kind_(symbol_kind::S_YYEMPTY) {} #if 201103L <= YY_CPLUSPLUS - YYParser::by_kind::by_kind (by_kind&& that) - : kind_ (that.kind_) - { - that.clear (); - } +YYParser::by_kind::by_kind(by_kind&& that) + : kind_(that.kind_) { + that.clear(); +} #endif - YYParser::by_kind::by_kind (const by_kind& that) - : kind_ (that.kind_) - {} +YYParser::by_kind::by_kind(const by_kind& that) + : kind_(that.kind_) {} - YYParser::by_kind::by_kind (token_kind_type t) - : kind_ (yytranslate_ (t)) - {} +YYParser::by_kind::by_kind(token_kind_type t) + : kind_(yytranslate_(t)) {} - void - YYParser::by_kind::clear () YY_NOEXCEPT - { - kind_ = symbol_kind::S_YYEMPTY; - } - - void - YYParser::by_kind::move (by_kind& that) - { - kind_ = that.kind_; - that.clear (); - } +void YYParser::by_kind::clear() YY_NOEXCEPT { + kind_ = symbol_kind::S_YYEMPTY; +} - YYParser::symbol_kind_type - YYParser::by_kind::kind () const YY_NOEXCEPT - { - return kind_; - } +void YYParser::by_kind::move(by_kind& that) { + kind_ = that.kind_; + that.clear(); +} - YYParser::symbol_kind_type - YYParser::by_kind::type_get () const YY_NOEXCEPT - { - return this->kind (); - } +YYParser::symbol_kind_type YYParser::by_kind::kind() const YY_NOEXCEPT { + return kind_; +} +YYParser::symbol_kind_type YYParser::by_kind::type_get() const YY_NOEXCEPT { + return this->kind(); +} - // by_state. - YYParser::by_state::by_state () YY_NOEXCEPT - : state (empty_state) - {} +// by_state. +YYParser::by_state::by_state() YY_NOEXCEPT : state(empty_state) {} - YYParser::by_state::by_state (const by_state& that) YY_NOEXCEPT - : state (that.state) - {} +YYParser::by_state::by_state(const by_state& that) YY_NOEXCEPT : state(that.state) {} - void - YYParser::by_state::clear () YY_NOEXCEPT - { - state = empty_state; - } +void YYParser::by_state::clear() YY_NOEXCEPT { + state = empty_state; +} - void - YYParser::by_state::move (by_state& that) - { - state = that.state; - that.clear (); - } +void YYParser::by_state::move(by_state& that) { + state = that.state; + that.clear(); +} - YYParser::by_state::by_state (state_type s) YY_NOEXCEPT - : state (s) - {} +YYParser::by_state::by_state(state_type s) YY_NOEXCEPT : state(s) {} - YYParser::symbol_kind_type - YYParser::by_state::kind () const YY_NOEXCEPT - { - if (state == empty_state) - return symbol_kind::S_YYEMPTY; - else - return YY_CAST (symbol_kind_type, yystos_[+state]); - } +YYParser::symbol_kind_type YYParser::by_state::kind() const YY_NOEXCEPT { + if (state == empty_state) + return symbol_kind::S_YYEMPTY; + else + return YY_CAST(symbol_kind_type, yystos_[+state]); +} - YYParser::stack_symbol_type::stack_symbol_type () - {} +YYParser::stack_symbol_type::stack_symbol_type() {} - YYParser::stack_symbol_type::stack_symbol_type (YY_RVREF (stack_symbol_type) that) - : super_type (YY_MOVE (that.state), YY_MOVE (that.value), YY_MOVE (that.location)) - { +YYParser::stack_symbol_type::stack_symbol_type(YY_RVREF(stack_symbol_type) that) + : super_type(YY_MOVE(that.state), YY_MOVE(that.value), YY_MOVE(that.location)) { #if 201103L <= YY_CPLUSPLUS - // that is emptied. - that.state = empty_state; + // that is emptied. + that.state = empty_state; #endif - } +} - YYParser::stack_symbol_type::stack_symbol_type (state_type s, YY_MOVE_REF (symbol_type) that) - : super_type (s, YY_MOVE (that.value), YY_MOVE (that.location)) - { - // that is emptied. - that.kind_ = symbol_kind::S_YYEMPTY; - } +YYParser::stack_symbol_type::stack_symbol_type(state_type s, YY_MOVE_REF(symbol_type) that) + : super_type(s, YY_MOVE(that.value), YY_MOVE(that.location)) { + // that is emptied. + that.kind_ = symbol_kind::S_YYEMPTY; +} #if YY_CPLUSPLUS < 201103L - YYParser::stack_symbol_type& - YYParser::stack_symbol_type::operator= (const stack_symbol_type& that) - { - state = that.state; - value = that.value; - location = that.location; - return *this; - } +YYParser::stack_symbol_type& YYParser::stack_symbol_type::operator=(const stack_symbol_type& that) { + state = that.state; + value = that.value; + location = that.location; + return *this; +} - YYParser::stack_symbol_type& - YYParser::stack_symbol_type::operator= (stack_symbol_type& that) - { - state = that.state; - value = that.value; - location = that.location; - // that is emptied. - that.state = empty_state; - return *this; - } +YYParser::stack_symbol_type& YYParser::stack_symbol_type::operator=(stack_symbol_type& that) { + state = that.state; + value = that.value; + location = that.location; + // that is emptied. + that.state = empty_state; + return *this; +} #endif - template - void - YYParser::yy_destroy_ (const char* yymsg, basic_symbol& yysym) const - { - if (yymsg) - YY_SYMBOL_PRINT (yymsg, yysym); +template +void YYParser::yy_destroy_(const char* yymsg, basic_symbol& yysym) const { + if (yymsg) + YY_SYMBOL_PRINT(yymsg, yysym); - // User destructor. - YY_USE (yysym.kind ()); - } + // User destructor. + YY_USE(yysym.kind()); +} #if YYDEBUG - template - void - YYParser::yy_print_ (std::ostream& yyo, const basic_symbol& yysym) const - { - std::ostream& yyoutput = yyo; - YY_USE (yyoutput); - if (yysym.empty ()) - yyo << "empty symbol"; - else - { - symbol_kind_type yykind = yysym.kind (); - yyo << (yykind < YYNTOKENS ? "token" : "nterm") - << ' ' << yysym.name () << " (" - << yysym.location << ": "; - YY_USE (yykind); - yyo << ')'; - } +template +void YYParser::yy_print_(std::ostream& yyo, const basic_symbol& yysym) const { + std::ostream& yyoutput = yyo; + YY_USE(yyoutput); + if (yysym.empty()) + yyo << "empty symbol"; + else { + symbol_kind_type yykind = yysym.kind(); + yyo << (yykind < YYNTOKENS ? "token" : "nterm") << ' ' << yysym.name() << " (" << yysym.location << ": "; + YY_USE(yykind); + yyo << ')'; } +} #endif - void - YYParser::yypush_ (const char* m, YY_MOVE_REF (stack_symbol_type) sym) - { - if (m) - YY_SYMBOL_PRINT (m, sym); - yystack_.push (YY_MOVE (sym)); - } +void YYParser::yypush_(const char* m, YY_MOVE_REF(stack_symbol_type) sym) { + if (m) + YY_SYMBOL_PRINT(m, sym); + yystack_.push(YY_MOVE(sym)); +} - void - YYParser::yypush_ (const char* m, state_type s, YY_MOVE_REF (symbol_type) sym) - { +void YYParser::yypush_(const char* m, state_type s, YY_MOVE_REF(symbol_type) sym) { #if 201103L <= YY_CPLUSPLUS - yypush_ (m, stack_symbol_type (s, std::move (sym))); + yypush_(m, stack_symbol_type(s, std::move(sym))); #else - stack_symbol_type ss (s, sym); - yypush_ (m, ss); + stack_symbol_type ss(s, sym); + yypush_(m, ss); #endif - } +} - void - YYParser::yypop_ (int n) - { - yystack_.pop (n); - } +void YYParser::yypop_(int n) { + yystack_.pop(n); +} #if YYDEBUG - std::ostream& - YYParser::debug_stream () const - { - return *yycdebug_; - } - - void - YYParser::set_debug_stream (std::ostream& o) - { - yycdebug_ = &o; - } +std::ostream& YYParser::debug_stream() const { + return *yycdebug_; +} +void YYParser::set_debug_stream(std::ostream& o) { + yycdebug_ = &o; +} - YYParser::debug_level_type - YYParser::debug_level () const - { - return yydebug_; - } +YYParser::debug_level_type YYParser::debug_level() const { + return yydebug_; +} - void - YYParser::set_debug_level (debug_level_type l) - { - yydebug_ = l; - } +void YYParser::set_debug_level(debug_level_type l) { + yydebug_ = l; +} #endif // YYDEBUG - YYParser::state_type - YYParser::yy_lr_goto_state_ (state_type yystate, int yysym) - { - int yyr = yypgoto_[yysym - YYNTOKENS] + yystate; - if (0 <= yyr && yyr <= yylast_ && yycheck_[yyr] == yystate) - return yytable_[yyr]; - else - return yydefgoto_[yysym - YYNTOKENS]; - } +YYParser::state_type YYParser::yy_lr_goto_state_(state_type yystate, int yysym) { + int yyr = yypgoto_[yysym - YYNTOKENS] + yystate; + if (0 <= yyr && yyr <= yylast_ && yycheck_[yyr] == yystate) + return yytable_[yyr]; + else + return yydefgoto_[yysym - YYNTOKENS]; +} - bool - YYParser::yy_pact_value_is_default_ (int yyvalue) - { - return yyvalue == yypact_ninf_; - } +bool YYParser::yy_pact_value_is_default_(int yyvalue) { + return yyvalue == yypact_ninf_; +} - bool - YYParser::yy_table_value_is_error_ (int yyvalue) - { - return yyvalue == yytable_ninf_; - } +bool YYParser::yy_table_value_is_error_(int yyvalue) { + return yyvalue == yytable_ninf_; +} - int - YYParser::operator() () - { - return parse (); - } +int YYParser::operator()() { + return parse(); +} - int - YYParser::parse () - { - int yyn; - /// Length of the RHS of the rule being reduced. - int yylen = 0; +int YYParser::parse() { + int yyn; + /// Length of the RHS of the rule being reduced. + int yylen = 0; - // Error handling. - int yynerrs_ = 0; - int yyerrstatus_ = 0; + // Error handling. + int yynerrs_ = 0; + int yyerrstatus_ = 0; - /// The lookahead symbol. - symbol_type yyla; + /// The lookahead symbol. + symbol_type yyla; - /// The locations where the error started and ended. - stack_symbol_type yyerror_range[3]; + /// The locations where the error started and ended. + stack_symbol_type yyerror_range[3]; - /// The return value of parse (). - int yyresult; + /// The return value of parse (). + int yyresult; #if YY_EXCEPTIONS - try + try #endif // YY_EXCEPTIONS - { + { YYCDEBUG << "Starting parse\n"; - /* Initialize the stack. The initial state will be set in yynewstate, since the latter expects the semantical and the location values to have been already stored, initialize these stacks with a primary value. */ - yystack_.clear (); - yypush_ (YY_NULLPTR, 0, YY_MOVE (yyla)); + yystack_.clear(); + yypush_(YY_NULLPTR, 0, YY_MOVE(yyla)); /*-----------------------------------------------. | yynewstate -- push a new symbol on the stack. | `-----------------------------------------------*/ yynewstate: - YYCDEBUG << "Entering state " << int (yystack_[0].state) << '\n'; - YY_STACK_PRINT (); + YYCDEBUG << "Entering state " << int(yystack_[0].state) << '\n'; + YY_STACK_PRINT(); // Accept? if (yystack_[0].state == yyfinal_) @@ -496,39 +414,35 @@ namespace ffi { goto yybackup; - /*-----------. | yybackup. | `-----------*/ yybackup: // Try to take a decision without lookahead. yyn = yypact_[+yystack_[0].state]; - if (yy_pact_value_is_default_ (yyn)) + if (yy_pact_value_is_default_(yyn)) goto yydefault; // Read a lookahead token. - if (yyla.empty ()) - { - YYCDEBUG << "Reading a token\n"; + if (yyla.empty()) { + YYCDEBUG << "Reading a token\n"; #if YY_EXCEPTIONS - try + try #endif // YY_EXCEPTIONS - { - yyla.kind_ = yytranslate_ (yylex (&yyla.value, &yyla.location)); - } + { + yyla.kind_ = yytranslate_(yylex(&yyla.value, &yyla.location)); + } #if YY_EXCEPTIONS - catch (const syntax_error& yyexc) - { - YYCDEBUG << "Caught exception: " << yyexc.what() << '\n'; - error (yyexc); - goto yyerrlab1; - } -#endif // YY_EXCEPTIONS + catch (const syntax_error& yyexc) { + YYCDEBUG << "Caught exception: " << yyexc.what() << '\n'; + error(yyexc); + goto yyerrlab1; } - YY_SYMBOL_PRINT ("Next token is", yyla); +#endif // YY_EXCEPTIONS + } + YY_SYMBOL_PRINT("Next token is", yyla); - if (yyla.kind () == symbol_kind::S_YYerror) - { + if (yyla.kind() == symbol_kind::S_YYerror) { // The scanner already issued an error message, process directly // to error recovery. But do not keep the error token as // lookahead, it is too special and may lead us to an endless @@ -539,31 +453,28 @@ namespace ffi { /* If the proper action on seeing token YYLA.TYPE is to reduce or to detect an error, take that action. */ - yyn += yyla.kind (); - if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yyla.kind ()) - { - goto yydefault; - } + yyn += yyla.kind(); + if (yyn < 0 || yylast_ < yyn || yycheck_[yyn] != yyla.kind()) { + goto yydefault; + } // Reduce or error. yyn = yytable_[yyn]; - if (yyn <= 0) - { - if (yy_table_value_is_error_ (yyn)) - goto yyerrlab; - yyn = -yyn; - goto yyreduce; - } + if (yyn <= 0) { + if (yy_table_value_is_error_(yyn)) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } // Count tokens shifted since error; after three, turn off error status. if (yyerrstatus_) --yyerrstatus_; // Shift the lookahead token. - yypush_ ("Shifting", state_type (yyn), YY_MOVE (yyla)); + yypush_("Shifting", state_type(yyn), YY_MOVE(yyla)); goto yynewstate; - /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ @@ -573,7 +484,6 @@ namespace ffi { goto yyerrlab; goto yyreduce; - /*-----------------------------. | yyreduce -- do a reduction. | `-----------------------------*/ @@ -581,7 +491,7 @@ namespace ffi { yylen = yyr2_[yyn]; { stack_symbol_type yylhs; - yylhs.state = yy_lr_goto_state_ (yystack_[yylen].state, yyr1_[yyn]); + yylhs.state = yy_lr_goto_state_(yystack_[yylen].state, yyr1_[yyn]); /* If YYLEN is nonzero, implement the default value of the action: '$$ = $1'. Otherwise, use the top of the stack. @@ -595,684 +505,901 @@ namespace ffi { // Default location. { - stack_type::slice range (yystack_, yylen); - YYLLOC_DEFAULT (yylhs.location, range, yylen); + stack_type::slice range(yystack_, yylen); + YYLLOC_DEFAULT(yylhs.location, range, yylen); yyerror_range[1].location = yylhs.location; } // Perform the reduction. - YY_REDUCE_PRINT (yyn); + YY_REDUCE_PRINT(yyn); #if YY_EXCEPTIONS try #endif // YY_EXCEPTIONS - { - switch (yyn) - { - case 4: // external_declaration: declaration + { + switch (yyn) { + case 4: // external_declaration: declaration #line 130 "c.y" - { driver.add_type((yystack_[0].value. type_ )); } + { + driver.add_type((yystack_[0].value.type_)); + } #line 615 "yy_parser_generated.cpp" - break; + break; - case 5: // external_declaration: typedef_declaration + case 5: // external_declaration: typedef_declaration #line 131 "c.y" - {} + { + } #line 621 "yy_parser_generated.cpp" - break; + break; - case 6: // external_declaration: EXTERN declaration + case 6: // external_declaration: EXTERN declaration #line 132 "c.y" - { driver.add_type((yystack_[0].value. type_ )); } + { + driver.add_type((yystack_[0].value.type_)); + } #line 627 "yy_parser_generated.cpp" - break; + break; - case 7: // external_declaration: STATIC declaration + case 7: // external_declaration: STATIC declaration #line 133 "c.y" - { driver.add_type((yystack_[0].value. type_ )); } + { + driver.add_type((yystack_[0].value.type_)); + } #line 633 "yy_parser_generated.cpp" - break; + break; - case 8: // external_declaration: AUTO declaration + case 8: // external_declaration: AUTO declaration #line 134 "c.y" - { driver.add_type((yystack_[0].value. type_ )); } + { + driver.add_type((yystack_[0].value.type_)); + } #line 639 "yy_parser_generated.cpp" - break; + break; - case 9: // external_declaration: REGISTER declaration + case 9: // external_declaration: REGISTER declaration #line 135 "c.y" - { driver.add_type((yystack_[0].value. type_ )); } + { + driver.add_type((yystack_[0].value.type_)); + } #line 645 "yy_parser_generated.cpp" - break; + break; - case 10: // typedef_declaration: TYPEDEF specifier_qualifier_list declarator ";" + case 10: // typedef_declaration: TYPEDEF specifier_qualifier_list declarator ";" #line 139 "c.y" - { driver.add_typedef((yystack_[2].value. type_ ), (yystack_[1].value. type_ )); } + { + driver.add_typedef((yystack_[2].value.type_), (yystack_[1].value.type_)); + } #line 651 "yy_parser_generated.cpp" - break; + break; - case 11: // declaration: declaration_specifiers ";" + case 11: // declaration: declaration_specifiers ";" #line 143 "c.y" - { (yylhs.value. type_ ) = (yystack_[1].value. type_ ); } + { + (yylhs.value.type_) = (yystack_[1].value.type_); + } #line 657 "yy_parser_generated.cpp" - break; + break; - case 12: // declaration: declaration_specifiers init_declarator_list ";" + case 12: // declaration: declaration_specifiers init_declarator_list ";" #line 144 "c.y" - { (yylhs.value. type_ ) = driver.combine(DeclarationSpecifiers{(yystack_[2].value. type_ )}, InitDeclaratorList{(yystack_[1].value. type_ )}); } + { + (yylhs.value.type_) = driver.combine(DeclarationSpecifiers{(yystack_[2].value.type_)}, InitDeclaratorList{(yystack_[1].value.type_)}); + } #line 663 "yy_parser_generated.cpp" - break; + break; - case 13: // declaration_specifiers: type_specifier + case 13: // declaration_specifiers: type_specifier #line 148 "c.y" - { (yylhs.value. type_ ) = (yystack_[0].value. type_ ); } + { + (yylhs.value.type_) = (yystack_[0].value.type_); + } #line 669 "yy_parser_generated.cpp" - break; + break; - case 14: // declaration_specifiers: type_specifier declaration_specifiers + case 14: // declaration_specifiers: type_specifier declaration_specifiers #line 149 "c.y" - { (yylhs.value. type_ ) = driver.combine(TypeSpecifier{(yystack_[1].value. type_ )}, DeclarationSpecifiers{(yystack_[0].value. type_ )}); } + { + (yylhs.value.type_) = driver.combine(TypeSpecifier{(yystack_[1].value.type_)}, DeclarationSpecifiers{(yystack_[0].value.type_)}); + } #line 675 "yy_parser_generated.cpp" - break; + break; - case 15: // declaration_specifiers: type_qualifier + case 15: // declaration_specifiers: type_qualifier #line 150 "c.y" - { (yylhs.value. type_ ) = (yystack_[0].value. type_ ); } + { + (yylhs.value.type_) = (yystack_[0].value.type_); + } #line 681 "yy_parser_generated.cpp" - break; + break; - case 16: // declaration_specifiers: type_qualifier declaration_specifiers + case 16: // declaration_specifiers: type_qualifier declaration_specifiers #line 151 "c.y" - { (yylhs.value. type_ ) = driver.combine(TypeQualifier{(yystack_[1].value. type_ )}, DeclarationSpecifiers{(yystack_[0].value. type_ )}); } + { + (yylhs.value.type_) = driver.combine(TypeQualifier{(yystack_[1].value.type_)}, DeclarationSpecifiers{(yystack_[0].value.type_)}); + } #line 687 "yy_parser_generated.cpp" - break; + break; - case 17: // type_qualifier: CONST + case 17: // type_qualifier: CONST #line 155 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::_typeFlags, FFIType::Flag::Const); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::_typeFlags, FFIType::Flag::Const); + } #line 693 "yy_parser_generated.cpp" - break; + break; - case 18: // type_qualifier: VOLATILE + case 18: // type_qualifier: VOLATILE #line 156 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::_typeFlags, FFIType::Flag::Volatile); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::_typeFlags, FFIType::Flag::Volatile); + } #line 699 "yy_parser_generated.cpp" - break; + break; - case 19: // base_type_specifier: VOID + case 19: // base_type_specifier: VOID #line 160 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::Void); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::Void); + } #line 705 "yy_parser_generated.cpp" - break; + break; - case 20: // base_type_specifier: CHAR + case 20: // base_type_specifier: CHAR #line 161 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::Char); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::Char); + } #line 711 "yy_parser_generated.cpp" - break; + break; - case 21: // base_type_specifier: BOOL + case 21: // base_type_specifier: BOOL #line 162 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::Bool); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::Bool); + } #line 717 "yy_parser_generated.cpp" - break; + break; - case 22: // base_type_specifier: FLOAT + case 22: // base_type_specifier: FLOAT #line 163 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::Float); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::Float); + } #line 723 "yy_parser_generated.cpp" - break; + break; - case 23: // base_type_specifier: DOUBLE + case 23: // base_type_specifier: DOUBLE #line 164 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::Double); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::Double); + } #line 729 "yy_parser_generated.cpp" - break; + break; - case 24: // base_type_specifier: INT + case 24: // base_type_specifier: INT #line 165 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::_int); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::_int); + } #line 735 "yy_parser_generated.cpp" - break; + break; - case 25: // base_type_specifier: LONG + case 25: // base_type_specifier: LONG #line 166 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::_typeFlags, FFIType::Flag::Long); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::_typeFlags, FFIType::Flag::Long); + } #line 741 "yy_parser_generated.cpp" - break; + break; - case 26: // base_type_specifier: SHORT + case 26: // base_type_specifier: SHORT #line 167 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::_typeFlags, FFIType::Flag::Short); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::_typeFlags, FFIType::Flag::Short); + } #line 747 "yy_parser_generated.cpp" - break; + break; - case 27: // base_type_specifier: SIGNED + case 27: // base_type_specifier: SIGNED #line 168 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::_typeFlags, FFIType::Flag::Signed); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::_typeFlags, FFIType::Flag::Signed); + } #line 753 "yy_parser_generated.cpp" - break; + break; - case 28: // base_type_specifier: UNSIGNED + case 28: // base_type_specifier: UNSIGNED #line 169 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::_typeFlags, FFIType::Flag::Unsigned); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::_typeFlags, FFIType::Flag::Unsigned); + } #line 759 "yy_parser_generated.cpp" - break; + break; - case 29: // base_type_specifier: INT8 + case 29: // base_type_specifier: INT8 #line 170 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::Int8); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::Int8); + } #line 765 "yy_parser_generated.cpp" - break; + break; - case 30: // base_type_specifier: INT16 + case 30: // base_type_specifier: INT16 #line 171 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::Int16); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::Int16); + } #line 771 "yy_parser_generated.cpp" - break; + break; - case 31: // base_type_specifier: INT32 + case 31: // base_type_specifier: INT32 #line 172 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::Int32); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::Int32); + } #line 777 "yy_parser_generated.cpp" - break; + break; - case 32: // base_type_specifier: INT64 + case 32: // base_type_specifier: INT64 #line 173 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::Int64); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::Int64); + } #line 783 "yy_parser_generated.cpp" - break; + break; - case 33: // base_type_specifier: UINT8 + case 33: // base_type_specifier: UINT8 #line 174 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::Uint8); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::Uint8); + } #line 789 "yy_parser_generated.cpp" - break; + break; - case 34: // base_type_specifier: UINT16 + case 34: // base_type_specifier: UINT16 #line 175 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::Uint16); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::Uint16); + } #line 795 "yy_parser_generated.cpp" - break; + break; - case 35: // base_type_specifier: UINT32 + case 35: // base_type_specifier: UINT32 #line 176 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::Uint32); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::Uint32); + } #line 801 "yy_parser_generated.cpp" - break; + break; - case 36: // base_type_specifier: UINT64 + case 36: // base_type_specifier: UINT64 #line 177 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::Uint64); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::Uint64); + } #line 807 "yy_parser_generated.cpp" - break; + break; - case 37: // base_type_specifier: INTPTR_T + case 37: // base_type_specifier: INTPTR_T #line 178 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::_intptr); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::_intptr); + } #line 813 "yy_parser_generated.cpp" - break; + break; - case 38: // base_type_specifier: UINTPTR_T + case 38: // base_type_specifier: UINTPTR_T #line 179 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::_uintptr); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::_uintptr); + } #line 819 "yy_parser_generated.cpp" - break; + break; - case 39: // base_type_specifier: SIZE_T + case 39: // base_type_specifier: SIZE_T #line 180 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::_size); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::_size); + } #line 825 "yy_parser_generated.cpp" - break; + break; - case 40: // type_specifier: base_type_specifier + case 40: // type_specifier: base_type_specifier #line 184 "c.y" - { (yylhs.value. type_ ) = (yystack_[0].value. type_ ); } + { + (yylhs.value.type_) = (yystack_[0].value.type_); + } #line 831 "yy_parser_generated.cpp" - break; + break; - case 41: // type_specifier: struct_or_union_specifier + case 41: // type_specifier: struct_or_union_specifier #line 185 "c.y" - { (yylhs.value. type_ ) = (yystack_[0].value. type_ ); } + { + (yylhs.value.type_) = (yystack_[0].value.type_); + } #line 837 "yy_parser_generated.cpp" - break; + break; - case 42: // type_specifier: enum_specifier + case 42: // type_specifier: enum_specifier #line 186 "c.y" - { (yylhs.value. type_ ) = (yystack_[0].value. type_ ); } + { + (yylhs.value.type_) = (yystack_[0].value.type_); + } #line 843 "yy_parser_generated.cpp" - break; + break; - case 43: // type_specifier: TYPEDEF_NAME + case 43: // type_specifier: TYPEDEF_NAME #line 187 "c.y" - { (yylhs.value. type_ ) = driver.get_aliased_type((yystack_[0].value. str_ )); } + { + (yylhs.value.type_) = driver.get_aliased_type((yystack_[0].value.str_)); + } #line 849 "yy_parser_generated.cpp" - break; + break; - case 44: // init_declarator_list: init_declarator + case 44: // init_declarator_list: init_declarator #line 191 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::_initDeclaratorList); (yylhs.value. type_ )->members.emplace_back((yystack_[0].value. type_ )); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::_initDeclaratorList); + (yylhs.value.type_)->members.emplace_back((yystack_[0].value.type_)); + } #line 855 "yy_parser_generated.cpp" - break; + break; - case 45: // init_declarator_list: init_declarator_list "," init_declarator + case 45: // init_declarator_list: init_declarator_list "," init_declarator #line 192 "c.y" - { (yylhs.value. type_ ) = (yystack_[2].value. type_ ); (yylhs.value. type_ )->members.emplace_back((yystack_[0].value. type_ )); } + { + (yylhs.value.type_) = (yystack_[2].value.type_); + (yylhs.value.type_)->members.emplace_back((yystack_[0].value.type_)); + } #line 861 "yy_parser_generated.cpp" - break; + break; - case 46: // init_declarator: declarator + case 46: // init_declarator: declarator #line 197 "c.y" - { (yylhs.value. type_ ) = (yystack_[0].value. type_ ); } + { + (yylhs.value.type_) = (yystack_[0].value.type_); + } #line 867 "yy_parser_generated.cpp" - break; + break; - case 47: // declarator: direct_declarator + case 47: // declarator: direct_declarator #line 201 "c.y" - { (yylhs.value. type_ ) = (yystack_[0].value. type_ ); } + { + (yylhs.value.type_) = (yystack_[0].value.type_); + } #line 873 "yy_parser_generated.cpp" - break; + break; - case 48: // declarator: pointer direct_declarator + case 48: // declarator: pointer direct_declarator #line 202 "c.y" - { (yylhs.value. type_ ) = driver.combine(Pointer{(yystack_[1].value. type_ )}, DirectDeclarator{(yystack_[0].value. type_ )}); } + { + (yylhs.value.type_) = driver.combine(Pointer{(yystack_[1].value.type_)}, DirectDeclarator{(yystack_[0].value.type_)}); + } #line 879 "yy_parser_generated.cpp" - break; + break; - case 49: // pointer: "*" type_qualifier_list pointer + case 49: // pointer: "*" type_qualifier_list pointer #line 208 "c.y" - { (yylhs.value. type_ ) = (yystack_[0].value. type_ ); (yylhs.value. type_ )->num++; } + { + (yylhs.value.type_) = (yystack_[0].value.type_); + (yylhs.value.type_)->num++; + } #line 885 "yy_parser_generated.cpp" - break; + break; - case 50: // pointer: "*" type_qualifier_list + case 50: // pointer: "*" type_qualifier_list #line 209 "c.y" - { (yylhs.value. type_ ) = driver.make_pointer(); } + { + (yylhs.value.type_) = driver.make_pointer(); + } #line 891 "yy_parser_generated.cpp" - break; + break; - case 51: // pointer: "*" pointer + case 51: // pointer: "*" pointer #line 210 "c.y" - { (yylhs.value. type_ ) = (yystack_[0].value. type_ ); (yylhs.value. type_ )->num++; } + { + (yylhs.value.type_) = (yystack_[0].value.type_); + (yylhs.value.type_)->num++; + } #line 897 "yy_parser_generated.cpp" - break; + break; - case 52: // pointer: "*" + case 52: // pointer: "*" #line 211 "c.y" - { (yylhs.value. type_ ) = driver.make_pointer(); } + { + (yylhs.value.type_) = driver.make_pointer(); + } #line 903 "yy_parser_generated.cpp" - break; + break; - case 53: // type_qualifier_list: type_qualifier + case 53: // type_qualifier_list: type_qualifier #line 215 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::_typesList); (yylhs.value. type_ )->members.emplace_back((yystack_[0].value. type_ )); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::_typesList); + (yylhs.value.type_)->members.emplace_back((yystack_[0].value.type_)); + } #line 909 "yy_parser_generated.cpp" - break; + break; - case 54: // type_qualifier_list: type_qualifier_list type_qualifier + case 54: // type_qualifier_list: type_qualifier_list type_qualifier #line 216 "c.y" - { (yylhs.value. type_ ) = (yystack_[1].value. type_ ); (yylhs.value. type_ )->members.emplace_back((yystack_[0].value. type_ )); } + { + (yylhs.value.type_) = (yystack_[1].value.type_); + (yylhs.value.type_)->members.emplace_back((yystack_[0].value.type_)); + } #line 915 "yy_parser_generated.cpp" - break; + break; - case 55: // direct_declarator: IDENTIFIER + case 55: // direct_declarator: IDENTIFIER #line 220 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::Name); (yylhs.value. type_ )->str = (yystack_[0].value. str_ ).to_string(); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::Name); + (yylhs.value.type_)->str = (yystack_[0].value.str_).to_string(); + } #line 921 "yy_parser_generated.cpp" - break; + break; - case 56: // direct_declarator: "(" declarator ")" + case 56: // direct_declarator: "(" declarator ")" #line 221 "c.y" - { (yylhs.value. type_ ) = (yystack_[1].value. type_ ); } + { + (yylhs.value.type_) = (yystack_[1].value.type_); + } #line 927 "yy_parser_generated.cpp" - break; + break; - case 57: // direct_declarator: direct_declarator "[" "]" + case 57: // direct_declarator: direct_declarator "[" "]" #line 222 "c.y" - { (yylhs.value. type_ ) = driver.make_array_declarator((yystack_[2].value. type_ ), "-1"); } + { + (yylhs.value.type_) = driver.make_array_declarator((yystack_[2].value.type_), "-1"); + } #line 933 "yy_parser_generated.cpp" - break; + break; - case 58: // direct_declarator: direct_declarator "[" INT_CONSTANT "]" + case 58: // direct_declarator: direct_declarator "[" INT_CONSTANT "]" #line 223 "c.y" - { (yylhs.value. type_ ) = driver.make_array_declarator((yystack_[3].value. type_ ), (yystack_[1].value. str_ )); } + { + (yylhs.value.type_) = driver.make_array_declarator((yystack_[3].value.type_), (yystack_[1].value.str_)); + } #line 939 "yy_parser_generated.cpp" - break; + break; - case 59: // direct_declarator: direct_declarator "(" parameter_type_list ")" + case 59: // direct_declarator: direct_declarator "(" parameter_type_list ")" #line 224 "c.y" - { (yylhs.value. type_ ) = driver.make_function((yystack_[3].value. type_ ), (yystack_[1].value. type_ )); } + { + (yylhs.value.type_) = driver.make_function((yystack_[3].value.type_), (yystack_[1].value.type_)); + } #line 945 "yy_parser_generated.cpp" - break; + break; - case 60: // direct_declarator: direct_declarator "(" ")" + case 60: // direct_declarator: direct_declarator "(" ")" #line 225 "c.y" - { (yylhs.value. type_ ) = driver.make_function((yystack_[2].value. type_ ), nullptr); } + { + (yylhs.value.type_) = driver.make_function((yystack_[2].value.type_), nullptr); + } #line 951 "yy_parser_generated.cpp" - break; + break; - case 61: // parameter_type_list: parameter_list "," ELLIPSIS + case 61: // parameter_type_list: parameter_list "," ELLIPSIS #line 229 "c.y" - { (yylhs.value. type_ ) = (yystack_[2].value. type_ ); (yylhs.value. type_ )->members.emplace_back(driver.make_simple_type(FFITypeKind::_ellipsis)); } + { + (yylhs.value.type_) = (yystack_[2].value.type_); + (yylhs.value.type_)->members.emplace_back(driver.make_simple_type(FFITypeKind::_ellipsis)); + } #line 957 "yy_parser_generated.cpp" - break; + break; - case 62: // parameter_type_list: parameter_list + case 62: // parameter_type_list: parameter_list #line 230 "c.y" - { (yylhs.value. type_ ) = (yystack_[0].value. type_ ); } + { + (yylhs.value.type_) = (yystack_[0].value.type_); + } #line 963 "yy_parser_generated.cpp" - break; + break; - case 63: // parameter_list: parameter_declaration + case 63: // parameter_list: parameter_declaration #line 234 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::_typesList); (yylhs.value. type_ )->members.emplace_back((yystack_[0].value. type_ )); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::_typesList); + (yylhs.value.type_)->members.emplace_back((yystack_[0].value.type_)); + } #line 969 "yy_parser_generated.cpp" - break; + break; - case 64: // parameter_list: parameter_list "," parameter_declaration + case 64: // parameter_list: parameter_list "," parameter_declaration #line 235 "c.y" - { (yylhs.value. type_ ) = (yystack_[2].value. type_ ); (yylhs.value. type_ )->members.emplace_back((yystack_[0].value. type_ )); } + { + (yylhs.value.type_) = (yystack_[2].value.type_); + (yylhs.value.type_)->members.emplace_back((yystack_[0].value.type_)); + } #line 975 "yy_parser_generated.cpp" - break; + break; - case 65: // parameter_declaration: declaration_specifiers declarator + case 65: // parameter_declaration: declaration_specifiers declarator #line 239 "c.y" - { (yylhs.value. type_ ) = driver.combine(DeclarationSpecifiers{(yystack_[1].value. type_ )}, Declarator{(yystack_[0].value. type_ )}); } + { + (yylhs.value.type_) = driver.combine(DeclarationSpecifiers{(yystack_[1].value.type_)}, Declarator{(yystack_[0].value.type_)}); + } #line 981 "yy_parser_generated.cpp" - break; + break; - case 66: // parameter_declaration: declaration_specifiers abstract_declarator + case 66: // parameter_declaration: declaration_specifiers abstract_declarator #line 240 "c.y" - { (yylhs.value. type_ ) = driver.combine(DeclarationSpecifiers{(yystack_[1].value. type_ )}, AbstractDeclarator{(yystack_[0].value. type_ )}); } + { + (yylhs.value.type_) = driver.combine(DeclarationSpecifiers{(yystack_[1].value.type_)}, AbstractDeclarator{(yystack_[0].value.type_)}); + } #line 987 "yy_parser_generated.cpp" - break; + break; - case 67: // parameter_declaration: declaration_specifiers + case 67: // parameter_declaration: declaration_specifiers #line 241 "c.y" - { (yylhs.value. type_ ) = (yystack_[0].value. type_ ); } + { + (yylhs.value.type_) = (yystack_[0].value.type_); + } #line 993 "yy_parser_generated.cpp" - break; + break; - case 68: // abstract_declarator: pointer direct_abstract_declarator + case 68: // abstract_declarator: pointer direct_abstract_declarator #line 245 "c.y" - { (yylhs.value. type_ ) = driver.combine(Pointer{(yystack_[1].value. type_ )}, DirectAbstractDeclarator{(yystack_[0].value. type_ )}); } + { + (yylhs.value.type_) = driver.combine(Pointer{(yystack_[1].value.type_)}, DirectAbstractDeclarator{(yystack_[0].value.type_)}); + } #line 999 "yy_parser_generated.cpp" - break; + break; - case 69: // abstract_declarator: pointer + case 69: // abstract_declarator: pointer #line 246 "c.y" - { (yylhs.value. type_ ) = (yystack_[0].value. type_ ); } + { + (yylhs.value.type_) = (yystack_[0].value.type_); + } #line 1005 "yy_parser_generated.cpp" - break; + break; - case 70: // abstract_declarator: direct_abstract_declarator + case 70: // abstract_declarator: direct_abstract_declarator #line 247 "c.y" - { (yylhs.value. type_ ) = (yystack_[0].value. type_ ); } + { + (yylhs.value.type_) = (yystack_[0].value.type_); + } #line 1011 "yy_parser_generated.cpp" - break; + break; - case 71: // direct_abstract_declarator: "[" "]" + case 71: // direct_abstract_declarator: "[" "]" #line 251 "c.y" - { (yylhs.value. type_ ) = driver.make_abstract_array_declarator("-1"); } + { + (yylhs.value.type_) = driver.make_abstract_array_declarator("-1"); + } #line 1017 "yy_parser_generated.cpp" - break; + break; - case 72: // direct_abstract_declarator: "[" INT_CONSTANT "]" + case 72: // direct_abstract_declarator: "[" INT_CONSTANT "]" #line 252 "c.y" - { (yylhs.value. type_ ) = driver.make_abstract_array_declarator((yystack_[1].value. str_ )); } + { + (yylhs.value.type_) = driver.make_abstract_array_declarator((yystack_[1].value.str_)); + } #line 1023 "yy_parser_generated.cpp" - break; + break; - case 73: // direct_abstract_declarator: direct_abstract_declarator "[" "]" + case 73: // direct_abstract_declarator: direct_abstract_declarator "[" "]" #line 253 "c.y" - { (yylhs.value. type_ ) = driver.make_array_declarator((yystack_[2].value. type_ ), "-1"); } + { + (yylhs.value.type_) = driver.make_array_declarator((yystack_[2].value.type_), "-1"); + } #line 1029 "yy_parser_generated.cpp" - break; + break; - case 74: // direct_abstract_declarator: direct_abstract_declarator "[" INT_CONSTANT "]" + case 74: // direct_abstract_declarator: direct_abstract_declarator "[" INT_CONSTANT "]" #line 254 "c.y" - { (yylhs.value. type_ ) = driver.make_array_declarator((yystack_[3].value. type_ ), (yystack_[1].value. str_ )); } + { + (yylhs.value.type_) = driver.make_array_declarator((yystack_[3].value.type_), (yystack_[1].value.str_)); + } #line 1035 "yy_parser_generated.cpp" - break; + break; - case 75: // struct_or_union_specifier: STRUCT "{" struct_declaration_list "}" + case 75: // struct_or_union_specifier: STRUCT "{" struct_declaration_list "}" #line 258 "c.y" - { (yylhs.value. type_ ) = driver.make_struct_def((yystack_[1].value. type_ )); } + { + (yylhs.value.type_) = driver.make_struct_def((yystack_[1].value.type_)); + } #line 1041 "yy_parser_generated.cpp" - break; + break; - case 76: // struct_or_union_specifier: STRUCT typedef_name_or_identifier "{" struct_declaration_list "}" + case 76: // struct_or_union_specifier: STRUCT typedef_name_or_identifier "{" struct_declaration_list "}" #line 259 "c.y" - { (yylhs.value. type_ ) = driver.make_struct_def((yystack_[1].value. type_ )); (yylhs.value. type_ )->str = (yystack_[3].value. str_ ).to_string(); } + { + (yylhs.value.type_) = driver.make_struct_def((yystack_[1].value.type_)); + (yylhs.value.type_)->str = (yystack_[3].value.str_).to_string(); + } #line 1047 "yy_parser_generated.cpp" - break; + break; - case 77: // struct_or_union_specifier: STRUCT typedef_name_or_identifier + case 77: // struct_or_union_specifier: STRUCT typedef_name_or_identifier #line 260 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::Struct); (yylhs.value. type_ )->str = (yystack_[0].value. str_ ).to_string(); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::Struct); + (yylhs.value.type_)->str = (yystack_[0].value.str_).to_string(); + } #line 1053 "yy_parser_generated.cpp" - break; + break; - case 78: // struct_or_union_specifier: UNION "{" struct_declaration_list "}" + case 78: // struct_or_union_specifier: UNION "{" struct_declaration_list "}" #line 261 "c.y" - { (yylhs.value. type_ ) = driver.make_union_def((yystack_[1].value. type_ )); } + { + (yylhs.value.type_) = driver.make_union_def((yystack_[1].value.type_)); + } #line 1059 "yy_parser_generated.cpp" - break; + break; - case 79: // struct_or_union_specifier: UNION typedef_name_or_identifier "{" struct_declaration_list "}" + case 79: // struct_or_union_specifier: UNION typedef_name_or_identifier "{" struct_declaration_list "}" #line 262 "c.y" - { (yylhs.value. type_ ) = driver.make_union_def((yystack_[1].value. type_ )); (yylhs.value. type_ )->str = (yystack_[3].value. str_ ).to_string(); } + { + (yylhs.value.type_) = driver.make_union_def((yystack_[1].value.type_)); + (yylhs.value.type_)->str = (yystack_[3].value.str_).to_string(); + } #line 1065 "yy_parser_generated.cpp" - break; + break; - case 80: // struct_or_union_specifier: UNION typedef_name_or_identifier + case 80: // struct_or_union_specifier: UNION typedef_name_or_identifier #line 263 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::Union); (yylhs.value. type_ )->str = (yystack_[0].value. str_ ).to_string(); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::Union); + (yylhs.value.type_)->str = (yystack_[0].value.str_).to_string(); + } #line 1071 "yy_parser_generated.cpp" - break; + break; - case 81: // typedef_name_or_identifier: IDENTIFIER + case 81: // typedef_name_or_identifier: IDENTIFIER #line 267 "c.y" - { (yylhs.value. str_ ) = (yystack_[0].value. str_ ); } + { + (yylhs.value.str_) = (yystack_[0].value.str_); + } #line 1077 "yy_parser_generated.cpp" - break; + break; - case 82: // typedef_name_or_identifier: TYPEDEF_NAME + case 82: // typedef_name_or_identifier: TYPEDEF_NAME #line 268 "c.y" - { (yylhs.value. str_ ) = (yystack_[0].value. str_ ); } + { + (yylhs.value.str_) = (yystack_[0].value.str_); + } #line 1083 "yy_parser_generated.cpp" - break; + break; - case 83: // struct_declaration_list: struct_declaration + case 83: // struct_declaration_list: struct_declaration #line 272 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::_typesList); (yylhs.value. type_ )->members.emplace_back((yystack_[0].value. type_ )); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::_typesList); + (yylhs.value.type_)->members.emplace_back((yystack_[0].value.type_)); + } #line 1089 "yy_parser_generated.cpp" - break; + break; - case 84: // struct_declaration_list: struct_declaration_list struct_declaration + case 84: // struct_declaration_list: struct_declaration_list struct_declaration #line 273 "c.y" - { (yylhs.value. type_ ) = (yystack_[1].value. type_ ); (yylhs.value. type_ )->members.emplace_back((yystack_[0].value. type_ )); } + { + (yylhs.value.type_) = (yystack_[1].value.type_); + (yylhs.value.type_)->members.emplace_back((yystack_[0].value.type_)); + } #line 1095 "yy_parser_generated.cpp" - break; + break; - case 85: // struct_declaration: specifier_qualifier_list struct_declarator_list ";" + case 85: // struct_declaration: specifier_qualifier_list struct_declarator_list ";" #line 277 "c.y" - { (yylhs.value. type_ ) = (yystack_[1].value. type_ ); (yylhs.value. type_ )->members.emplace_back((yystack_[2].value. type_ )); } + { + (yylhs.value.type_) = (yystack_[1].value.type_); + (yylhs.value.type_)->members.emplace_back((yystack_[2].value.type_)); + } #line 1101 "yy_parser_generated.cpp" - break; + break; - case 86: // specifier_qualifier_list: type_specifier specifier_qualifier_list + case 86: // specifier_qualifier_list: type_specifier specifier_qualifier_list #line 281 "c.y" - { (yylhs.value. type_ ) = driver.combine(TypeSpecifier{(yystack_[1].value. type_ )}, SpecifierQualifierList{(yystack_[0].value. type_ )}); } + { + (yylhs.value.type_) = driver.combine(TypeSpecifier{(yystack_[1].value.type_)}, SpecifierQualifierList{(yystack_[0].value.type_)}); + } #line 1107 "yy_parser_generated.cpp" - break; + break; - case 87: // specifier_qualifier_list: type_specifier + case 87: // specifier_qualifier_list: type_specifier #line 282 "c.y" - { (yylhs.value. type_ ) = (yystack_[0].value. type_ ); } + { + (yylhs.value.type_) = (yystack_[0].value.type_); + } #line 1113 "yy_parser_generated.cpp" - break; + break; - case 88: // specifier_qualifier_list: type_qualifier specifier_qualifier_list + case 88: // specifier_qualifier_list: type_qualifier specifier_qualifier_list #line 283 "c.y" - { (yylhs.value. type_ ) = driver.combine(TypeQualifier{(yystack_[1].value. type_ )}, SpecifierQualifierList{(yystack_[0].value. type_ )}); } + { + (yylhs.value.type_) = driver.combine(TypeQualifier{(yystack_[1].value.type_)}, SpecifierQualifierList{(yystack_[0].value.type_)}); + } #line 1119 "yy_parser_generated.cpp" - break; + break; - case 89: // specifier_qualifier_list: type_qualifier + case 89: // specifier_qualifier_list: type_qualifier #line 284 "c.y" - { (yylhs.value. type_ ) = (yystack_[0].value. type_ ); } + { + (yylhs.value.type_) = (yystack_[0].value.type_); + } #line 1125 "yy_parser_generated.cpp" - break; + break; - case 90: // struct_declarator_list: struct_declarator + case 90: // struct_declarator_list: struct_declarator #line 288 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::_structFieldList); (yylhs.value. type_ )->members.emplace_back((yystack_[0].value. type_ )); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::_structFieldList); + (yylhs.value.type_)->members.emplace_back((yystack_[0].value.type_)); + } #line 1131 "yy_parser_generated.cpp" - break; + break; - case 91: // struct_declarator_list: struct_declarator_list "," struct_declarator + case 91: // struct_declarator_list: struct_declarator_list "," struct_declarator #line 289 "c.y" - { (yylhs.value. type_ ) = (yystack_[2].value. type_ ); (yylhs.value. type_ )->members.emplace_back((yystack_[0].value. type_ )); } + { + (yylhs.value.type_) = (yystack_[2].value.type_); + (yylhs.value.type_)->members.emplace_back((yystack_[0].value.type_)); + } #line 1137 "yy_parser_generated.cpp" - break; + break; - case 92: // struct_declarator: declarator + case 92: // struct_declarator: declarator #line 293 "c.y" - { (yylhs.value. type_ ) = (yystack_[0].value. type_ ); } + { + (yylhs.value.type_) = (yystack_[0].value.type_); + } #line 1143 "yy_parser_generated.cpp" - break; + break; - case 93: // enum_specifier: ENUM "{" enumerator_list "}" + case 93: // enum_specifier: ENUM "{" enumerator_list "}" #line 300 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::EnumDef); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::EnumDef); + } #line 1149 "yy_parser_generated.cpp" - break; + break; - case 94: // enum_specifier: ENUM "{" enumerator_list "," "}" + case 94: // enum_specifier: ENUM "{" enumerator_list "," "}" #line 301 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::EnumDef); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::EnumDef); + } #line 1155 "yy_parser_generated.cpp" - break; + break; - case 95: // enum_specifier: ENUM IDENTIFIER "{" enumerator_list "}" + case 95: // enum_specifier: ENUM IDENTIFIER "{" enumerator_list "}" #line 302 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::EnumDef); (yylhs.value. type_ )->str = (yystack_[3].value. str_ ).to_string(); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::EnumDef); + (yylhs.value.type_)->str = (yystack_[3].value.str_).to_string(); + } #line 1161 "yy_parser_generated.cpp" - break; + break; - case 96: // enum_specifier: ENUM IDENTIFIER "{" enumerator_list "," "}" + case 96: // enum_specifier: ENUM IDENTIFIER "{" enumerator_list "," "}" #line 303 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::EnumDef); (yylhs.value. type_ )->str = (yystack_[4].value. str_ ).to_string(); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::EnumDef); + (yylhs.value.type_)->str = (yystack_[4].value.str_).to_string(); + } #line 1167 "yy_parser_generated.cpp" - break; + break; - case 97: // enum_specifier: ENUM IDENTIFIER + case 97: // enum_specifier: ENUM IDENTIFIER #line 304 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::Enum); (yylhs.value. type_ )->str = (yystack_[0].value. str_ ).to_string(); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::Enum); + (yylhs.value.type_)->str = (yystack_[0].value.str_).to_string(); + } #line 1173 "yy_parser_generated.cpp" - break; + break; - case 98: // enumerator_list: enumerator + case 98: // enumerator_list: enumerator #line 308 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::_enumList); driver.add_enumerator((yylhs.value. type_ ), (yystack_[0].value. type_ )); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::_enumList); + driver.add_enumerator((yylhs.value.type_), (yystack_[0].value.type_)); + } #line 1179 "yy_parser_generated.cpp" - break; + break; - case 99: // enumerator_list: enumerator_list "," enumerator + case 99: // enumerator_list: enumerator_list "," enumerator #line 309 "c.y" - { (yylhs.value. type_ ) = (yystack_[2].value. type_ ); driver.add_enumerator((yylhs.value. type_ ), (yystack_[0].value. type_ )); } + { + (yylhs.value.type_) = (yystack_[2].value.type_); + driver.add_enumerator((yylhs.value.type_), (yystack_[0].value.type_)); + } #line 1185 "yy_parser_generated.cpp" - break; + break; - case 100: // enumerator: IDENTIFIER "=" int_value + case 100: // enumerator: IDENTIFIER "=" int_value #line 313 "c.y" - { (yylhs.value. type_ ) = driver.make_enum_member((yystack_[2].value. str_ ), (yystack_[0].value. int_ )); } + { + (yylhs.value.type_) = driver.make_enum_member((yystack_[2].value.str_), (yystack_[0].value.int_)); + } #line 1191 "yy_parser_generated.cpp" - break; + break; - case 101: // enumerator: IDENTIFIER + case 101: // enumerator: IDENTIFIER #line 314 "c.y" - { (yylhs.value. type_ ) = driver.make_simple_type(FFITypeKind::_enumMember); (yylhs.value. type_ )->str = (yystack_[0].value. str_ ).to_string(); } + { + (yylhs.value.type_) = driver.make_simple_type(FFITypeKind::_enumMember); + (yylhs.value.type_)->str = (yystack_[0].value.str_).to_string(); + } #line 1197 "yy_parser_generated.cpp" - break; + break; - case 102: // int_value: INT_CONSTANT + case 102: // int_value: INT_CONSTANT #line 318 "c.y" - { (yylhs.value. int_ ) = driver.stoi((yystack_[0].value. str_ )); } + { + (yylhs.value.int_) = driver.stoi((yystack_[0].value.str_)); + } #line 1203 "yy_parser_generated.cpp" - break; + break; - case 103: // int_value: "-" INT_CONSTANT + case 103: // int_value: "-" INT_CONSTANT #line 319 "c.y" - { (yylhs.value. int_ ) = -driver.stoi((yystack_[0].value. str_ )); } + { + (yylhs.value.int_) = -driver.stoi((yystack_[0].value.str_)); + } #line 1209 "yy_parser_generated.cpp" - break; + break; - case 104: // int_value: "+" INT_CONSTANT + case 104: // int_value: "+" INT_CONSTANT #line 320 "c.y" - { (yylhs.value. int_ ) = driver.stoi((yystack_[0].value. str_ )); } + { + (yylhs.value.int_) = driver.stoi((yystack_[0].value.str_)); + } #line 1215 "yy_parser_generated.cpp" - break; - + break; #line 1219 "yy_parser_generated.cpp" - default: - break; - } + default: + break; } + } #if YY_EXCEPTIONS - catch (const syntax_error& yyexc) - { - YYCDEBUG << "Caught exception: " << yyexc.what() << '\n'; - error (yyexc); - YYERROR; - } + catch (const syntax_error& yyexc) { + YYCDEBUG << "Caught exception: " << yyexc.what() << '\n'; + error(yyexc); + YYERROR; + } #endif // YY_EXCEPTIONS - YY_SYMBOL_PRINT ("-> $$ =", yylhs); - yypop_ (yylen); + YY_SYMBOL_PRINT("-> $$ =", yylhs); + yypop_(yylen); yylen = 0; // Shift the result of the reduction. - yypush_ (YY_NULLPTR, YY_MOVE (yylhs)); + yypush_(YY_NULLPTR, YY_MOVE(yylhs)); } goto yynewstate; - /*--------------------------------------. | yyerrlab -- here on detecting error. | `--------------------------------------*/ yyerrlab: // If not already recovering from an error, report this error. - if (!yyerrstatus_) - { - ++yynerrs_; - context yyctx (*this, yyla); - std::string msg = yysyntax_error_ (yyctx); - error (yyla.location, YY_MOVE (msg)); - } - + if (!yyerrstatus_) { + ++yynerrs_; + context yyctx(*this, yyla); + std::string msg = yysyntax_error_(yyctx); + error(yyla.location, YY_MOVE(msg)); + } yyerror_range[1].location = yyla.location; - if (yyerrstatus_ == 3) - { - /* If just tried and failed to reuse lookahead token after an - error, discard it. */ - - // Return failure if at end of input. - if (yyla.kind () == symbol_kind::S_YYEOF) - YYABORT; - else if (!yyla.empty ()) - { - yy_destroy_ ("Error: discarding", yyla); - yyla.clear (); - } + if (yyerrstatus_ == 3) { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + // Return failure if at end of input. + if (yyla.kind() == symbol_kind::S_YYEOF) + YYABORT; + else if (!yyla.empty()) { + yy_destroy_("Error: discarding", yyla); + yyla.clear(); } + } // Else will try to reuse lookahead token after shifting the error token. goto yyerrlab1; - /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ @@ -1284,55 +1411,49 @@ namespace ffi { /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ - yypop_ (yylen); + yypop_(yylen); yylen = 0; - YY_STACK_PRINT (); + YY_STACK_PRINT(); goto yyerrlab1; - /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: - yyerrstatus_ = 3; // Each real token shifted decrements this. + yyerrstatus_ = 3; // Each real token shifted decrements this. // Pop stack until we find a state that shifts the error token. - for (;;) - { - yyn = yypact_[+yystack_[0].state]; - if (!yy_pact_value_is_default_ (yyn)) - { - yyn += symbol_kind::S_YYerror; - if (0 <= yyn && yyn <= yylast_ - && yycheck_[yyn] == symbol_kind::S_YYerror) - { - yyn = yytable_[yyn]; - if (0 < yyn) - break; - } - } - - // Pop the current state because it cannot handle the error token. - if (yystack_.size () == 1) - YYABORT; - - yyerror_range[1].location = yystack_[0].location; - yy_destroy_ ("Error: popping", yystack_[0]); - yypop_ (); - YY_STACK_PRINT (); + for (;;) { + yyn = yypact_[+yystack_[0].state]; + if (!yy_pact_value_is_default_(yyn)) { + yyn += symbol_kind::S_YYerror; + if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == symbol_kind::S_YYerror) { + yyn = yytable_[yyn]; + if (0 < yyn) + break; + } } + + // Pop the current state because it cannot handle the error token. + if (yystack_.size() == 1) + YYABORT; + + yyerror_range[1].location = yystack_[0].location; + yy_destroy_("Error: popping", yystack_[0]); + yypop_(); + YY_STACK_PRINT(); + } { stack_symbol_type error_token; yyerror_range[2].location = yyla.location; - YYLLOC_DEFAULT (error_token.location, yyerror_range, 2); + YYLLOC_DEFAULT(error_token.location, yyerror_range, 2); // Shift the error token. - error_token.state = state_type (yyn); - yypush_ ("Shifting", YY_MOVE (error_token)); + error_token.state = state_type(yyn); + yypush_("Shifting", YY_MOVE(error_token)); } goto yynewstate; - /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ @@ -1340,7 +1461,6 @@ namespace ffi { yyresult = 0; goto yyreturn; - /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ @@ -1348,582 +1468,442 @@ namespace ffi { yyresult = 1; goto yyreturn; - /*-----------------------------------------------------. | yyreturn -- parsing is finished, return the result. | `-----------------------------------------------------*/ yyreturn: - if (!yyla.empty ()) - yy_destroy_ ("Cleanup: discarding lookahead", yyla); + if (!yyla.empty()) + yy_destroy_("Cleanup: discarding lookahead", yyla); /* Do not reclaim the symbols of the rule whose action triggered this YYABORT or YYACCEPT. */ - yypop_ (yylen); - YY_STACK_PRINT (); - while (1 < yystack_.size ()) - { - yy_destroy_ ("Cleanup: popping", yystack_[0]); - yypop_ (); - } + yypop_(yylen); + YY_STACK_PRINT(); + while (1 < yystack_.size()) { + yy_destroy_("Cleanup: popping", yystack_[0]); + yypop_(); + } return yyresult; } #if YY_EXCEPTIONS - catch (...) - { - YYCDEBUG << "Exception caught: cleaning lookahead and stack\n"; - // Do not try to display the values of the reclaimed symbols, - // as their printers might throw an exception. - if (!yyla.empty ()) - yy_destroy_ (YY_NULLPTR, yyla); - - while (1 < yystack_.size ()) - { - yy_destroy_ (YY_NULLPTR, yystack_[0]); - yypop_ (); - } - throw; - } -#endif // YY_EXCEPTIONS - } - - void - YYParser::error (const syntax_error& yyexc) - { - error (yyexc.location, yyexc.what ()); + catch (...) { + YYCDEBUG << "Exception caught: cleaning lookahead and stack\n"; + // Do not try to display the values of the reclaimed symbols, + // as their printers might throw an exception. + if (!yyla.empty()) + yy_destroy_(YY_NULLPTR, yyla); + + while (1 < yystack_.size()) { + yy_destroy_(YY_NULLPTR, yystack_[0]); + yypop_(); + } + throw; } +#endif // YY_EXCEPTIONS +} - /* Return YYSTR after stripping away unnecessary quotes and - backslashes, so that it's suitable for yyerror. The heuristic is - that double-quoting is unnecessary unless the string contains an - apostrophe, a comma, or backslash (other than backslash-backslash). - YYSTR is taken from yytname. */ - std::string - YYParser::yytnamerr_ (const char *yystr) - { - if (*yystr == '"') - { - std::string yyr; - char const *yyp = yystr; - - for (;;) - switch (*++yyp) - { - case '\'': - case ',': - goto do_not_strip_quotes; - - case '\\': - if (*++yyp != '\\') - goto do_not_strip_quotes; - else - goto append; - - append: - default: - yyr += *yyp; - break; - - case '"': - return yyr; - } - do_not_strip_quotes: ; - } +void YYParser::error(const syntax_error& yyexc) { + error(yyexc.location, yyexc.what()); +} - return yystr; - } +/* Return YYSTR after stripping away unnecessary quotes and + backslashes, so that it's suitable for yyerror. The heuristic is + that double-quoting is unnecessary unless the string contains an + apostrophe, a comma, or backslash (other than backslash-backslash). + YYSTR is taken from yytname. */ +std::string YYParser::yytnamerr_(const char* yystr) { + if (*yystr == '"') { + std::string yyr; + char const* yyp = yystr; - std::string - YYParser::symbol_name (symbol_kind_type yysymbol) - { - return yytnamerr_ (yytname_[yysymbol]); + for (;;) + switch (*++yyp) { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + else + goto append; + + append: + default: + yyr += *yyp; + break; + + case '"': + return yyr; + } + do_not_strip_quotes:; } + return yystr; +} +std::string YYParser::symbol_name(symbol_kind_type yysymbol) { + return yytnamerr_(yytname_[yysymbol]); +} - // YYParser::context. - YYParser::context::context (const YYParser& yyparser, const symbol_type& yyla) - : yyparser_ (yyparser) - , yyla_ (yyla) - {} - - int - YYParser::context::expected_tokens (symbol_kind_type yyarg[], int yyargn) const - { - // Actual number of expected tokens - int yycount = 0; - - int yyn = yypact_[+yyparser_.yystack_[0].state]; - if (!yy_pact_value_is_default_ (yyn)) - { - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. In other words, skip the first -YYN actions for - this state because they are default actions. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - // Stay within bounds of both yycheck and yytname. - int yychecklim = yylast_ - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - for (int yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck_[yyx + yyn] == yyx && yyx != symbol_kind::S_YYerror - && !yy_table_value_is_error_ (yytable_[yyx + yyn])) - { - if (!yyarg) - ++yycount; - else if (yycount == yyargn) - return 0; - else - yyarg[yycount++] = YY_CAST (symbol_kind_type, yyx); - } +// YYParser::context. +YYParser::context::context(const YYParser& yyparser, const symbol_type& yyla) + : yyparser_(yyparser), + yyla_(yyla) {} + +int YYParser::context::expected_tokens(symbol_kind_type yyarg[], int yyargn) const { + // Actual number of expected tokens + int yycount = 0; + + int yyn = yypact_[+yyparser_.yystack_[0].state]; + if (!yy_pact_value_is_default_(yyn)) { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + // Stay within bounds of both yycheck and yytname. + int yychecklim = yylast_ - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + for (int yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck_[yyx + yyn] == yyx && yyx != symbol_kind::S_YYerror && !yy_table_value_is_error_(yytable_[yyx + yyn])) { + if (!yyarg) + ++yycount; + else if (yycount == yyargn) + return 0; + else + yyarg[yycount++] = YY_CAST(symbol_kind_type, yyx); } - - if (yyarg && yycount == 0 && 0 < yyargn) - yyarg[0] = symbol_kind::S_YYEMPTY; - return yycount; } + if (yyarg && yycount == 0 && 0 < yyargn) + yyarg[0] = symbol_kind::S_YYEMPTY; + return yycount; +} - - int - YYParser::yy_syntax_error_arguments_ (const context& yyctx, - symbol_kind_type yyarg[], int yyargn) const - { - /* There are many possibilities here to consider: - - If this state is a consistent state with a default action, then - the only way this function was invoked is if the default action - is an error action. In that case, don't check for expected - tokens because there are none. - - The only way there can be no lookahead present (in yyla) is - if this state is a consistent state with a default action. - Thus, detecting the absence of a lookahead is sufficient to - determine that there is no unexpected or expected token to - report. In that case, just report a simple "syntax error". - - Don't assume there isn't a lookahead just because this state is - a consistent state with a default action. There might have - been a previous inconsistent state, consistent state with a - non-default action, or user semantic action that manipulated - yyla. (However, yyla is currently not documented for users.) - - Of course, the expected token list depends on states to have - correct lookahead information, and it depends on the parser not - to perform extra reductions after fetching a lookahead from the - scanner and before detecting a syntax error. Thus, state merging - (from LALR or IELR) and default reductions corrupt the expected - token list. However, the list is correct for canonical LR with - one exception: it will still contain any token that will not be - accepted due to an error action in a later state. - */ - - if (!yyctx.lookahead ().empty ()) - { - if (yyarg) - yyarg[0] = yyctx.token (); - int yyn = yyctx.expected_tokens (yyarg ? yyarg + 1 : yyarg, yyargn - 1); - return yyn + 1; - } - return 0; +int YYParser::yy_syntax_error_arguments_(const context& yyctx, symbol_kind_type yyarg[], int yyargn) const { + /* There are many possibilities here to consider: + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yyla) is + if this state is a consistent state with a default action. + Thus, detecting the absence of a lookahead is sufficient to + determine that there is no unexpected or expected token to + report. In that case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is + a consistent state with a default action. There might have + been a previous inconsistent state, consistent state with a + non-default action, or user semantic action that manipulated + yyla. (However, yyla is currently not documented for users.) + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + + if (!yyctx.lookahead().empty()) { + if (yyarg) + yyarg[0] = yyctx.token(); + int yyn = yyctx.expected_tokens(yyarg ? yyarg + 1 : yyarg, yyargn - 1); + return yyn + 1; } + return 0; +} - // Generate an error message. - std::string - YYParser::yysyntax_error_ (const context& yyctx) const - { - // Its maximum. - enum { YYARGS_MAX = 5 }; - // Arguments of yyformat. - symbol_kind_type yyarg[YYARGS_MAX]; - int yycount = yy_syntax_error_arguments_ (yyctx, yyarg, YYARGS_MAX); - - char const* yyformat = YY_NULLPTR; - switch (yycount) - { -#define YYCASE_(N, S) \ - case N: \ - yyformat = S; \ - break - default: // Avoid compiler warnings. - YYCASE_ (0, YY_("syntax error")); - YYCASE_ (1, YY_("syntax error, unexpected %s")); - YYCASE_ (2, YY_("syntax error, unexpected %s, expecting %s")); - YYCASE_ (3, YY_("syntax error, unexpected %s, expecting %s or %s")); - YYCASE_ (4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); - YYCASE_ (5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +// Generate an error message. +std::string YYParser::yysyntax_error_(const context& yyctx) const { + // Its maximum. + enum { YYARGS_MAX = 5 }; + // Arguments of yyformat. + symbol_kind_type yyarg[YYARGS_MAX]; + int yycount = yy_syntax_error_arguments_(yyctx, yyarg, YYARGS_MAX); + + char const* yyformat = YY_NULLPTR; + switch (yycount) { +#define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + default: // Avoid compiler warnings. + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); #undef YYCASE_ - } - - std::string yyres; - // Argument number. - std::ptrdiff_t yyi = 0; - for (char const* yyp = yyformat; *yyp; ++yyp) - if (yyp[0] == '%' && yyp[1] == 's' && yyi < yycount) - { - yyres += symbol_name (yyarg[yyi++]); - ++yyp; - } - else - yyres += *yyp; - return yyres; } + std::string yyres; + // Argument number. + std::ptrdiff_t yyi = 0; + for (char const* yyp = yyformat; *yyp; ++yyp) + if (yyp[0] == '%' && yyp[1] == 's' && yyi < yycount) { + yyres += symbol_name(yyarg[yyi++]); + ++yyp; + } else + yyres += *yyp; + return yyres; +} - const signed char YYParser::yypact_ninf_ = -78; - - const signed char YYParser::yytable_ninf_ = -1; - - const short - YYParser::yypact_[] = - { - 332, -78, 366, 366, 366, 366, 366, -78, -78, -78, - -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, - -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, - 10, 13, 16, 56, -78, -78, -78, 67, 366, -78, - 366, -78, -78, 366, 366, 65, -78, -78, -78, -78, - 366, -78, -78, 31, 366, 44, 50, 76, -78, -78, - -78, 65, 5, -78, 19, -78, -78, 22, 132, -78, - -78, -78, -78, 66, 125, -78, 65, 366, 159, 366, - 84, 83, -78, 50, 80, -78, -78, 5, 65, -78, - 132, 263, 42, -78, -78, -78, -78, 141, -78, 195, - -78, 229, 120, 24, -78, 134, -78, -78, -78, -78, - -78, 46, 124, 135, -78, -78, 136, 65, -78, -78, - -78, 126, 131, -78, -78, -78, -78, 28, -78, 69, - -78, 68, -78, 139, -78, 297, -78, -78, -78, -78, - -78, -78, 140, 139, 74, -78, -78, -78, -78, 142, - -78 - }; - - const signed char - YYParser::yydefact_[] = - { - 0, 43, 0, 0, 0, 0, 0, 21, 20, 26, - 24, 25, 27, 28, 22, 23, 17, 18, 19, 29, - 30, 31, 32, 33, 34, 35, 36, 39, 37, 38, - 0, 0, 0, 0, 2, 5, 4, 0, 15, 40, - 13, 41, 42, 89, 87, 0, 6, 7, 8, 9, - 0, 81, 82, 77, 0, 80, 0, 97, 1, 3, - 11, 0, 52, 55, 0, 44, 46, 0, 47, 16, - 14, 88, 86, 0, 0, 83, 0, 0, 0, 0, - 101, 0, 98, 0, 0, 53, 51, 50, 0, 12, - 48, 0, 0, 10, 75, 84, 92, 0, 90, 0, - 78, 0, 0, 0, 93, 0, 56, 54, 49, 45, - 60, 67, 0, 62, 63, 57, 0, 0, 85, 76, - 79, 0, 0, 102, 100, 94, 99, 0, 95, 0, - 65, 69, 66, 70, 59, 0, 58, 91, 104, 103, - 96, 71, 0, 68, 0, 61, 64, 72, 73, 0, - 74 - }; - - const signed char - YYParser::yypgoto_[] = - { - -78, -78, 116, -78, 89, -31, 0, -78, 8, -78, - 63, -44, -52, -78, -65, -78, -78, 18, -78, 23, - -78, 127, -35, -54, 25, -78, 38, -78, 73, -77, - -78 - }; - - const unsigned char - YYParser::yydefgoto_[] = - { - 0, 33, 34, 35, 36, 37, 43, 39, 44, 64, - 65, 66, 67, 87, 68, 112, 113, 114, 132, 133, - 41, 53, 74, 75, 76, 97, 98, 42, 81, 82, - 124 - }; - - const unsigned char - YYParser::yytable_[] = - { - 38, 73, 90, 38, 38, 38, 38, 69, 40, 70, - 86, 40, 40, 40, 40, 50, 62, 84, 54, 78, - 95, 56, 88, 89, 95, 51, 126, 45, 51, 61, - 125, 57, 96, 38, 140, 108, 77, 63, 38, 80, - 38, 40, 99, 80, 101, 95, 40, 95, 40, 79, - 126, 52, 115, 61, 52, 129, 58, 62, 116, 131, - 111, 63, 85, 16, 17, 80, 90, 130, 71, 72, - 93, 60, 61, 96, 61, 61, 62, 129, 62, 141, - 63, 83, 63, 63, 148, 142, 103, 107, 106, 104, - 149, 38, 46, 47, 48, 49, 102, 1, 2, 40, - 3, 4, 5, 6, 111, 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, 94, 134, 121, 122, 38, 123, 127, 135, 91, - 128, 92, 138, 40, 117, 118, 136, 139, 144, 59, - 147, 109, 150, 146, 143, 137, 105, 0, 55, 0, - 0, 0, 0, 0, 0, 100, 1, 0, 0, 0, - 0, 0, 0, 0, 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, - 1, 119, 0, 0, 0, 0, 0, 0, 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, 0, 120, 1, 0, 0, 0, - 0, 0, 0, 0, 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, - 1, 110, 0, 0, 0, 0, 0, 0, 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, 1, 0, 0, 0, 0, 0, - 0, 0, 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, 1, 0, - 0, 0, 0, 0, 0, 0, 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, 145, 1, 2, 0, 3, 4, 5, 6, - 0, 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, 1, 0, 0, - 0, 0, 0, 0, 0, 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 - }; - - const short - YYParser::yycheck_[] = - { - 0, 45, 67, 3, 4, 5, 6, 38, 0, 40, - 62, 3, 4, 5, 6, 5, 11, 61, 5, 54, - 74, 5, 3, 4, 78, 15, 103, 2, 15, 7, - 6, 15, 76, 33, 6, 87, 5, 15, 38, 15, - 40, 33, 77, 15, 79, 99, 38, 101, 40, 5, - 127, 41, 10, 7, 41, 9, 0, 11, 16, 111, - 91, 15, 62, 58, 59, 15, 131, 111, 43, 44, - 4, 4, 7, 117, 7, 7, 11, 9, 11, 10, - 15, 5, 15, 15, 10, 16, 3, 87, 8, 6, - 16, 91, 3, 4, 5, 6, 12, 41, 42, 91, - 44, 45, 46, 47, 135, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 6, 8, 13, 14, 135, 16, 3, 3, 7, - 6, 9, 16, 135, 3, 4, 10, 16, 9, 33, - 10, 88, 10, 135, 131, 117, 83, -1, 31, -1, - -1, -1, -1, -1, -1, 6, 41, -1, -1, -1, - -1, -1, -1, -1, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 41, 6, -1, -1, -1, -1, -1, -1, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, -1, 6, 41, -1, -1, -1, - -1, -1, -1, -1, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 41, 8, -1, -1, -1, -1, -1, -1, 49, 50, - 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, - 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, 74, 41, -1, -1, -1, -1, -1, - -1, -1, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 41, -1, - -1, -1, -1, -1, -1, -1, 49, 50, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, - 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, - 73, 74, 75, 41, 42, -1, 44, 45, 46, 47, - -1, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, 41, -1, -1, - -1, -1, -1, -1, -1, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74 - }; - - const signed char - YYParser::yystos_[] = - { - 0, 41, 42, 44, 45, 46, 47, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 89, 90, 91, 92, 93, 94, 95, - 96, 108, 115, 94, 96, 112, 92, 92, 92, 92, - 5, 15, 41, 109, 5, 109, 5, 15, 0, 90, - 4, 7, 11, 15, 97, 98, 99, 100, 102, 93, - 93, 112, 112, 99, 110, 111, 112, 5, 110, 5, - 15, 116, 117, 5, 99, 94, 100, 101, 3, 4, - 102, 7, 9, 4, 6, 111, 99, 113, 114, 110, - 6, 110, 12, 3, 6, 116, 8, 94, 100, 98, - 8, 93, 103, 104, 105, 10, 16, 3, 4, 6, - 6, 13, 14, 16, 118, 6, 117, 3, 6, 9, - 99, 100, 106, 107, 8, 3, 10, 114, 16, 16, - 6, 10, 16, 107, 9, 75, 105, 10, 10, 16, - 10 - }; - - const signed char - YYParser::yyr1_[] = - { - 0, 88, 89, 89, 90, 90, 90, 90, 90, 90, - 91, 92, 92, 93, 93, 93, 93, 94, 94, 95, - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, - 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, - 96, 96, 96, 96, 97, 97, 98, 99, 99, 100, - 100, 100, 100, 101, 101, 102, 102, 102, 102, 102, - 102, 103, 103, 104, 104, 105, 105, 105, 106, 106, - 106, 107, 107, 107, 107, 108, 108, 108, 108, 108, - 108, 109, 109, 110, 110, 111, 112, 112, 112, 112, - 113, 113, 114, 115, 115, 115, 115, 115, 116, 116, - 117, 117, 118, 118, 118 - }; - - const signed char - YYParser::yyr2_[] = - { - 0, 2, 1, 2, 1, 1, 2, 2, 2, 2, - 4, 2, 3, 1, 2, 1, 2, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 3, 1, 1, 2, 3, - 2, 2, 1, 1, 2, 1, 3, 3, 4, 4, - 3, 3, 1, 1, 3, 2, 2, 1, 2, 1, - 1, 2, 3, 3, 4, 4, 5, 2, 4, 5, - 2, 1, 1, 1, 2, 3, 2, 1, 2, 1, - 1, 3, 1, 4, 5, 5, 6, 2, 1, 3, - 3, 1, 1, 2, 2 - }; - +const signed char YYParser::yypact_ninf_ = -78; + +const signed char YYParser::yytable_ninf_ = -1; + +const short YYParser::yypact_[] = { + 332, -78, 366, 366, 366, 366, 366, -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, 10, + 13, 16, 56, -78, -78, -78, 67, 366, -78, 366, -78, -78, 366, 366, 65, -78, -78, -78, -78, 366, -78, -78, 31, 366, 44, 50, 76, -78, -78, -78, 65, + 5, -78, 19, -78, -78, 22, 132, -78, -78, -78, -78, 66, 125, -78, 65, 366, 159, 366, 84, 83, -78, 50, 80, -78, -78, 5, 65, -78, 132, 263, 42, + -78, -78, -78, -78, 141, -78, 195, -78, 229, 120, 24, -78, 134, -78, -78, -78, -78, -78, 46, 124, 135, -78, -78, 136, 65, -78, -78, -78, 126, 131, -78, + -78, -78, -78, 28, -78, 69, -78, 68, -78, 139, -78, 297, -78, -78, -78, -78, -78, -78, 140, 139, 74, -78, -78, -78, -78, 142, -78}; + +const signed char YYParser::yydefact_[] = { + 0, 43, 0, 0, 0, 0, 0, 21, 20, 26, 24, 25, 27, 28, 22, 23, 17, 18, 19, 29, 30, 31, 32, 33, 34, 35, 36, 39, 37, 38, 0, 0, 0, 0, 2, 5, 4, 0, + 15, 40, 13, 41, 42, 89, 87, 0, 6, 7, 8, 9, 0, 81, 82, 77, 0, 80, 0, 97, 1, 3, 11, 0, 52, 55, 0, 44, 46, 0, 47, 16, 14, 88, 86, 0, 0, 83, + 0, 0, 0, 0, 101, 0, 98, 0, 0, 53, 51, 50, 0, 12, 48, 0, 0, 10, 75, 84, 92, 0, 90, 0, 78, 0, 0, 0, 93, 0, 56, 54, 49, 45, 60, 67, 0, 62, + 63, 57, 0, 0, 85, 76, 79, 0, 0, 102, 100, 94, 99, 0, 95, 0, 65, 69, 66, 70, 59, 0, 58, 91, 104, 103, 96, 71, 0, 68, 0, 61, 64, 72, 73, 0, 74}; + +const signed char YYParser::yypgoto_[] = {-78, -78, 116, -78, 89, -31, 0, -78, 8, -78, 63, -44, -52, -78, -65, -78, + -78, 18, -78, 23, -78, 127, -35, -54, 25, -78, 38, -78, 73, -77, -78}; + +const unsigned char YYParser::yydefgoto_[] = {0, 33, 34, 35, 36, 37, 43, 39, 44, 64, 65, 66, 67, 87, 68, 112, + 113, 114, 132, 133, 41, 53, 74, 75, 76, 97, 98, 42, 81, 82, 124}; + +const unsigned char YYParser::yytable_[] = { + 38, 73, 90, 38, 38, 38, 38, 69, 40, 70, 86, 40, 40, 40, 40, 50, 62, 84, 54, 78, 95, 56, 88, 89, 95, 51, 126, 45, 51, 61, 125, 57, + 96, 38, 140, 108, 77, 63, 38, 80, 38, 40, 99, 80, 101, 95, 40, 95, 40, 79, 126, 52, 115, 61, 52, 129, 58, 62, 116, 131, 111, 63, 85, 16, + 17, 80, 90, 130, 71, 72, 93, 60, 61, 96, 61, 61, 62, 129, 62, 141, 63, 83, 63, 63, 148, 142, 103, 107, 106, 104, 149, 38, 46, 47, 48, 49, + 102, 1, 2, 40, 3, 4, 5, 6, 111, 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, 94, 134, 121, 122, 38, 123, 127, 135, 91, 128, 92, 138, 40, 117, 118, 136, 139, 144, 59, 147, 109, 150, 146, 143, 137, 105, 0, 55, 0, + 0, 0, 0, 0, 0, 100, 1, 0, 0, 0, 0, 0, 0, 0, 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, 1, 119, 0, 0, 0, 0, 0, 0, 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, 0, 120, 1, 0, 0, 0, 0, 0, 0, 0, 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, 1, 110, 0, 0, 0, 0, 0, 0, 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, 1, 0, 0, 0, 0, 0, 0, 0, 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, 1, 0, 0, 0, 0, 0, 0, 0, 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, 145, 1, 2, 0, 3, 4, 5, 6, 0, 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, 1, 0, 0, 0, 0, 0, 0, 0, 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}; + +const short YYParser::yycheck_[] = { + 0, 45, 67, 3, 4, 5, 6, 38, 0, 40, 62, 3, 4, 5, 6, 5, 11, 61, 5, 54, 74, 5, 3, 4, 78, 15, 103, 2, 15, 7, 6, 15, 76, 33, + 6, 87, 5, 15, 38, 15, 40, 33, 77, 15, 79, 99, 38, 101, 40, 5, 127, 41, 10, 7, 41, 9, 0, 11, 16, 111, 91, 15, 62, 58, 59, 15, 131, 111, + 43, 44, 4, 4, 7, 117, 7, 7, 11, 9, 11, 10, 15, 5, 15, 15, 10, 16, 3, 87, 8, 6, 16, 91, 3, 4, 5, 6, 12, 41, 42, 91, 44, 45, + 46, 47, 135, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 6, 8, 13, 14, 135, + 16, 3, 3, 7, 6, 9, 16, 135, 3, 4, 10, 16, 9, 33, 10, 88, 10, 135, 131, 117, 83, -1, 31, -1, -1, -1, -1, -1, -1, 6, 41, -1, -1, -1, + -1, -1, -1, -1, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 41, 6, -1, -1, + -1, -1, -1, -1, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, -1, 6, 41, -1, + -1, -1, -1, -1, -1, -1, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 41, 8, + -1, -1, -1, -1, -1, -1, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 41, -1, + -1, -1, -1, -1, -1, -1, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 41, -1, + -1, -1, -1, -1, -1, -1, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 41, + 42, -1, 44, 45, 46, 47, -1, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 41, + -1, -1, -1, -1, -1, -1, -1, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74}; + +const signed char YYParser::yystos_[] = { + 0, 41, 42, 44, 45, 46, 47, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 89, 90, 91, 92, 93, 94, 95, 96, 108, 115, 94, 96, 112, 92, 92, 92, 92, 5, 15, 41, 109, 5, 109, 5, 15, 0, 90, 4, 7, + 11, 15, 97, 98, 99, 100, 102, 93, 93, 112, 112, 99, 110, 111, 112, 5, 110, 5, 15, 116, 117, 5, 99, 94, 100, 101, 3, 4, 102, 7, 9, + 4, 6, 111, 99, 113, 114, 110, 6, 110, 12, 3, 6, 116, 8, 94, 100, 98, 8, 93, 103, 104, 105, 10, 16, 3, 4, 6, 6, 13, 14, 16, + 118, 6, 117, 3, 6, 9, 99, 100, 106, 107, 8, 3, 10, 114, 16, 16, 6, 10, 16, 107, 9, 75, 105, 10, 10, 16, 10}; + +const signed char YYParser::yyr1_[] = {0, 88, 89, 89, 90, 90, 90, 90, 90, 90, 91, 92, 92, 93, 93, 93, 93, 94, 94, 95, 95, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 96, 96, + 96, 96, 97, 97, 98, 99, 99, 100, 100, 100, 100, 101, 101, 102, 102, 102, 102, 102, 102, 103, 103, + 104, 104, 105, 105, 105, 106, 106, 106, 107, 107, 107, 107, 108, 108, 108, 108, 108, 108, 109, 109, 110, + 110, 111, 112, 112, 112, 112, 113, 113, 114, 115, 115, 115, 115, 115, 116, 116, 117, 117, 118, 118, 118}; + +const signed char YYParser::yyr2_[] = {0, 2, 1, 2, 1, 1, 2, 2, 2, 2, 4, 2, 3, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 2, 3, 2, 2, 1, 1, 2, 1, 3, 3, 4, 4, 3, 3, 1, 1, 3, 2, 2, 1, 2, 1, + 1, 2, 3, 3, 4, 4, 5, 2, 4, 5, 2, 1, 1, 1, 2, 3, 2, 1, 2, 1, 1, 3, 1, 4, 5, 5, 6, 2, 1, 3, 3, 1, 1, 2, 2}; #if YYDEBUG || 1 - // YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - // First, the terminals, then, starting at \a YYNTOKENS, nonterminals. - const char* - const YYParser::yytname_[] = - { - "\"end of file\"", "error", "\"invalid token\"", "\",\"", "\";\"", - "\"{\"", "\"}\"", "\"(\"", "\")\"", "\"[\"", "\"]\"", "\"*\"", "\"=\"", - "\"+\"", "\"-\"", "IDENTIFIER", "INT_CONSTANT", "FLOAT_CONSTANT", - "STRING_LITERAL", "SIZEOF", "PTR_OP", "INC_OP", "DEC_OP", "LEFT_OP", - "RIGHT_OP", "LE_OP", "GE_OP", "EQ_OP", "NE_OP", "AND_OP", "OR_OP", - "MUL_ASSIGN", "DIV_ASSIGN", "MOD_ASSIGN", "ADD_ASSIGN", "SUB_ASSIGN", - "LEFT_ASSIGN", "RIGHT_ASSIGN", "AND_ASSIGN", "XOR_ASSIGN", "OR_ASSIGN", - "TYPEDEF_NAME", "TYPEDEF", "INLINE", "EXTERN", "STATIC", "AUTO", - "REGISTER", "THREAD_LOCAL", "BOOL", "CHAR", "SHORT", "INT", "LONG", - "SIGNED", "UNSIGNED", "FLOAT", "DOUBLE", "CONST", "VOLATILE", "VOID", - "INT8", "INT16", "INT32", "INT64", "UINT8", "UINT16", "UINT32", "UINT64", - "SIZE_T", "INTPTR_T", "UINTPTR_T", "STRUCT", "UNION", "ENUM", "ELLIPSIS", - "CASE", "DEFAULT", "IF", "ELSE", "SWITCH", "WHILE", "DO", "FOR", "GOTO", - "CONTINUE", "BREAK", "RETURN", "$accept", "translation_unit", - "external_declaration", "typedef_declaration", "declaration", - "declaration_specifiers", "type_qualifier", "base_type_specifier", - "type_specifier", "init_declarator_list", "init_declarator", - "declarator", "pointer", "type_qualifier_list", "direct_declarator", - "parameter_type_list", "parameter_list", "parameter_declaration", - "abstract_declarator", "direct_abstract_declarator", - "struct_or_union_specifier", "typedef_name_or_identifier", - "struct_declaration_list", "struct_declaration", - "specifier_qualifier_list", "struct_declarator_list", - "struct_declarator", "enum_specifier", "enumerator_list", "enumerator", - "int_value", YY_NULLPTR - }; +// YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. +// First, the terminals, then, starting at \a YYNTOKENS, nonterminals. +const char* const YYParser::yytname_[] = {"\"end of file\"", + "error", + "\"invalid token\"", + "\",\"", + "\";\"", + "\"{\"", + "\"}\"", + "\"(\"", + "\")\"", + "\"[\"", + "\"]\"", + "\"*\"", + "\"=\"", + "\"+\"", + "\"-\"", + "IDENTIFIER", + "INT_CONSTANT", + "FLOAT_CONSTANT", + "STRING_LITERAL", + "SIZEOF", + "PTR_OP", + "INC_OP", + "DEC_OP", + "LEFT_OP", + "RIGHT_OP", + "LE_OP", + "GE_OP", + "EQ_OP", + "NE_OP", + "AND_OP", + "OR_OP", + "MUL_ASSIGN", + "DIV_ASSIGN", + "MOD_ASSIGN", + "ADD_ASSIGN", + "SUB_ASSIGN", + "LEFT_ASSIGN", + "RIGHT_ASSIGN", + "AND_ASSIGN", + "XOR_ASSIGN", + "OR_ASSIGN", + "TYPEDEF_NAME", + "TYPEDEF", + "INLINE", + "EXTERN", + "STATIC", + "AUTO", + "REGISTER", + "THREAD_LOCAL", + "BOOL", + "CHAR", + "SHORT", + "INT", + "LONG", + "SIGNED", + "UNSIGNED", + "FLOAT", + "DOUBLE", + "CONST", + "VOLATILE", + "VOID", + "INT8", + "INT16", + "INT32", + "INT64", + "UINT8", + "UINT16", + "UINT32", + "UINT64", + "SIZE_T", + "INTPTR_T", + "UINTPTR_T", + "STRUCT", + "UNION", + "ENUM", + "ELLIPSIS", + "CASE", + "DEFAULT", + "IF", + "ELSE", + "SWITCH", + "WHILE", + "DO", + "FOR", + "GOTO", + "CONTINUE", + "BREAK", + "RETURN", + "$accept", + "translation_unit", + "external_declaration", + "typedef_declaration", + "declaration", + "declaration_specifiers", + "type_qualifier", + "base_type_specifier", + "type_specifier", + "init_declarator_list", + "init_declarator", + "declarator", + "pointer", + "type_qualifier_list", + "direct_declarator", + "parameter_type_list", + "parameter_list", + "parameter_declaration", + "abstract_declarator", + "direct_abstract_declarator", + "struct_or_union_specifier", + "typedef_name_or_identifier", + "struct_declaration_list", + "struct_declaration", + "specifier_qualifier_list", + "struct_declarator_list", + "struct_declarator", + "enum_specifier", + "enumerator_list", + "enumerator", + "int_value", + YY_NULLPTR}; #endif - #if YYDEBUG - const short - YYParser::yyrline_[] = - { - 0, 124, 124, 125, 130, 131, 132, 133, 134, 135, - 139, 143, 144, 148, 149, 150, 151, 155, 156, 160, - 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, - 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, - 184, 185, 186, 187, 191, 192, 197, 201, 202, 208, - 209, 210, 211, 215, 216, 220, 221, 222, 223, 224, - 225, 229, 230, 234, 235, 239, 240, 241, 245, 246, - 247, 251, 252, 253, 254, 258, 259, 260, 261, 262, - 263, 267, 268, 272, 273, 277, 281, 282, 283, 284, - 288, 289, 293, 300, 301, 302, 303, 304, 308, 309, - 313, 314, 318, 319, 320 - }; - - void - YYParser::yy_stack_print_ () const - { - *yycdebug_ << "Stack now"; - for (stack_type::const_iterator - i = yystack_.begin (), - i_end = yystack_.end (); - i != i_end; ++i) - *yycdebug_ << ' ' << int (i->state); - *yycdebug_ << '\n'; - } +const short YYParser::yyrline_[] = {0, 124, 124, 125, 130, 131, 132, 133, 134, 135, 139, 143, 144, 148, 149, 150, 151, 155, 156, 160, 161, + 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 184, 185, + 186, 187, 191, 192, 197, 201, 202, 208, 209, 210, 211, 215, 216, 220, 221, 222, 223, 224, 225, 229, 230, + 234, 235, 239, 240, 241, 245, 246, 247, 251, 252, 253, 254, 258, 259, 260, 261, 262, 263, 267, 268, 272, + 273, 277, 281, 282, 283, 284, 288, 289, 293, 300, 301, 302, 303, 304, 308, 309, 313, 314, 318, 319, 320}; + +void YYParser::yy_stack_print_() const { + *yycdebug_ << "Stack now"; + for (stack_type::const_iterator i = yystack_.begin(), i_end = yystack_.end(); i != i_end; ++i) + *yycdebug_ << ' ' << int(i->state); + *yycdebug_ << '\n'; +} - void - YYParser::yy_reduce_print_ (int yyrule) const - { - int yylno = yyrline_[yyrule]; - int yynrhs = yyr2_[yyrule]; - // Print the symbols being reduced, and their result. - *yycdebug_ << "Reducing stack by rule " << yyrule - 1 - << " (line " << yylno << "):\n"; - // The symbols being reduced. - for (int yyi = 0; yyi < yynrhs; yyi++) - YY_SYMBOL_PRINT (" $" << yyi + 1 << " =", - yystack_[(yynrhs) - (yyi + 1)]); - } +void YYParser::yy_reduce_print_(int yyrule) const { + int yylno = yyrline_[yyrule]; + int yynrhs = yyr2_[yyrule]; + // Print the symbols being reduced, and their result. + *yycdebug_ << "Reducing stack by rule " << yyrule - 1 << " (line " << yylno << "):\n"; + // The symbols being reduced. + for (int yyi = 0; yyi < yynrhs; yyi++) + YY_SYMBOL_PRINT(" $" << yyi + 1 << " =", yystack_[(yynrhs) - (yyi + 1)]); +} #endif // YYDEBUG - YYParser::symbol_kind_type - YYParser::yytranslate_ (int t) - { - // YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to - // TOKEN-NUM as returned by yylex. - static - const signed char - translate_table[] = - { - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 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, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87 - }; - // Last valid token kind. - const int code_max = 342; - - if (t <= 0) - return symbol_kind::S_YYEOF; - else if (t <= code_max) - return YY_CAST (symbol_kind_type, translate_table[t]); - else - return symbol_kind::S_YYUNDEF; - } +YYParser::symbol_kind_type YYParser::yytranslate_(int t) { + // YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to + // TOKEN-NUM as returned by yylex. + static const signed char translate_table[] = { + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 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, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87}; + // Last valid token kind. + const int code_max = 342; + + if (t <= 0) + return symbol_kind::S_YYEOF; + else if (t <= code_max) + return YY_CAST(symbol_kind_type, translate_table[t]); + else + return symbol_kind::S_YYUNDEF; +} #line 13 "c.y" -} // ffi +} // namespace ffi #line 1923 "yy_parser_generated.cpp" #line 322 "c.y" - -void ffi::YYParser::error(const ffi::Location &loc, const std::string &message) { +void ffi::YYParser::error(const ffi::Location& loc, const std::string& message) { throw ParsingDriver::ParseError{loc, message}; } diff --git a/compiler/ffi/ffi_parser.cpp b/compiler/ffi/ffi_parser.cpp index 64b714037b..df6086c231 100644 --- a/compiler/ffi/ffi_parser.cpp +++ b/compiler/ffi/ffi_parser.cpp @@ -4,29 +4,28 @@ #include "compiler/ffi/ffi_parser.h" +#include "compiler/compiler-core.h" #include "compiler/ffi/c_parser/parsing_driver.h" #include "compiler/kphp_assert.h" -#include "compiler/compiler-core.h" #include -static void log_ffi_parser_stats(const ffi::ParsingDriver::Result &result) { +static void log_ffi_parser_stats(const ffi::ParsingDriver::Result& result) { if (G->settings().verbosity.get() >= 1) { - fprintf(stderr, "FFI parser: allocated %ld objects (%ld collected as garbage)\n", - static_cast(result.num_allocated), + fprintf(stderr, "FFI parser: allocated %ld objects (%ld collected as garbage)\n", static_cast(result.num_allocated), static_cast(result.num_deleted)); } } -std::string ffi_preprocess_file(const std::string &src, FFIParseResult &parse_result) { +std::string ffi_preprocess_file(const std::string& src, FFIParseResult& parse_result) { // this code is definitely not as good as it could be; // like in PHP, we don't really handle any preprocessor directives // apart from the special FFI_SCOPE and FFI_LIB #defines std::string result; result.reserve(src.size()); - const char *p = src.c_str(); - const char *end = p + src.size(); + const char* p = src.c_str(); + const char* end = p + src.size(); while (p < end) { if (*p != '#') { @@ -36,18 +35,18 @@ std::string ffi_preprocess_file(const std::string &src, FFIParseResult &parse_re } if (std::strncmp(p, "#define FFI_SCOPE \"", strlen("#define FFI_SCOPE \"")) == 0) { - const char *str_begin = p + strlen("#define FFI_SCOPE \""); - const char *str_end = strstr(str_begin, "\"\n"); + const char* str_begin = p + strlen("#define FFI_SCOPE \""); + const char* str_end = strstr(str_begin, "\"\n"); parse_result.scope = std::string(str_begin, static_cast(str_end - str_begin)); } if (std::strncmp(p, "#define FFI_LIB \"", strlen("#define FFI_LIB \"")) == 0) { - const char *str_begin = p + strlen("#define FFI_LIB \""); - const char *str_end = strstr(str_begin, "\"\n"); + const char* str_begin = p + strlen("#define FFI_LIB \""); + const char* str_end = strstr(str_begin, "\"\n"); parse_result.lib = std::string(str_begin, static_cast(str_end - str_begin)); } if (std::strncmp(p, "#define FFI_STATIC_LIB \"", strlen("#define FFI_STATIC_LIB \"")) == 0) { - const char *str_begin = p + strlen("#define FFI_STATIC_LIB \""); - const char *str_end = strstr(str_begin, "\"\n"); + const char* str_begin = p + strlen("#define FFI_STATIC_LIB \""); + const char* str_end = strstr(str_begin, "\"\n"); parse_result.static_lib = std::string(str_begin, static_cast(str_end - str_begin)); } @@ -71,16 +70,14 @@ std::string ffi_preprocess_file(const std::string &src, FFIParseResult &parse_re return result; } -static void set_error(FFIParseError &dst, const std::string &src, ffi::ParsingDriver::ParseError &e) { +static void set_error(FFIParseError& dst, const std::string& src, ffi::ParsingDriver::ParseError& e) { dst.message = std::move(e.message); dst.line = 1; std::string chunk(src.begin(), src.begin() + e.location.begin); - dst.line += std::count_if(src.begin(), src.begin() + e.location.begin, [](char c){ - return c == '\n'; - }); + dst.line += std::count_if(src.begin(), src.begin() + e.location.begin, [](char c) { return c == '\n'; }); } -FFIParseResult ffi_parse_file(const std::string &src, FFITypedefs &typedefs) { +FFIParseResult ffi_parse_file(const std::string& src, FFITypedefs& typedefs) { FFIParseResult result; if (src.empty()) { @@ -96,15 +93,15 @@ FFIParseResult ffi_parse_file(const std::string &src, FFITypedefs &typedefs) { log_ffi_parser_stats(parse_result); result.set_types(std::move(parse_result.types)); result.enum_constants = parse_result.enum_constants; - } catch (ffi::ParsingDriver::ParseError &e) { + } catch (ffi::ParsingDriver::ParseError& e) { set_error(result.err, preprocessed_src, e); } return result; } -std::pair ffi_parse_type(const std::string &type_expr, FFITypedefs &typedefs) { - FFIType *result_type = nullptr; +std::pair ffi_parse_type(const std::string& type_expr, FFITypedefs& typedefs) { + FFIType* result_type = nullptr; FFIParseError err; // to parse an arbitrary type expression, parse it as a part of @@ -116,13 +113,13 @@ std::pair ffi_parse_type(const std::string &type_ try { auto parse_result = driver.parse(); log_ffi_parser_stats(parse_result); - const auto &types = parse_result.types; + const auto& types = parse_result.types; kphp_assert(types.size() == 1); - FFIType *param = types[0]->members[1]; + FFIType* param = types[0]->members[1]; kphp_assert(param->kind == FFITypeKind::Var); result_type = param->members[0]; delete param; - } catch (ffi::ParsingDriver::ParseError &e) { + } catch (ffi::ParsingDriver::ParseError& e) { set_error(err, src, e); } diff --git a/compiler/ffi/ffi_parser.h b/compiler/ffi/ffi_parser.h index 7662e17239..22dbdca849 100644 --- a/compiler/ffi/ffi_parser.h +++ b/compiler/ffi/ffi_parser.h @@ -4,10 +4,10 @@ #pragma once -#include -#include #include #include +#include +#include #include "compiler/ffi/ffi_types.h" @@ -28,15 +28,15 @@ struct FFIParseResult { std::vector types_; struct Iter { - Iter(const std::vector *vec, int64_t pos) - : pos_{pos} - , vec_{vec} {} + Iter(const std::vector* vec, int64_t pos) + : pos_{pos}, + vec_{vec} {} - bool operator!=(const Iter &other) const noexcept { + bool operator!=(const Iter& other) const noexcept { return pos_ != other.pos_; } - const FFIType* operator* () const { + const FFIType* operator*() const { return (*vec_)[pos_]; } @@ -46,7 +46,7 @@ struct FFIParseResult { } int64_t pos_; - const std::vector *vec_; + const std::vector* vec_; }; public: @@ -57,16 +57,24 @@ struct FFIParseResult { FFIParseError err; - void set_types(std::vector &&types) { types_ = std::move(types); } - - size_t num_types() const noexcept { return types_.size(); } - Iter begin() const noexcept { return Iter{&types_, 0}; } - Iter end() const noexcept { return Iter{&types_, static_cast(types_.size())}; } + void set_types(std::vector&& types) { + types_ = std::move(types); + } + + size_t num_types() const noexcept { + return types_.size(); + } + Iter begin() const noexcept { + return Iter{&types_, 0}; + } + Iter end() const noexcept { + return Iter{&types_, static_cast(types_.size())}; + } }; -FFIParseResult ffi_parse_file(const std::string &src, FFITypedefs &typedefs); +FFIParseResult ffi_parse_file(const std::string& src, FFITypedefs& typedefs); // exposed for testing purposes -std::string ffi_preprocess_file(const std::string &src, FFIParseResult &parse_result); +std::string ffi_preprocess_file(const std::string& src, FFIParseResult& parse_result); -std::pair ffi_parse_type(const std::string &type_expr, FFITypedefs &typedefs); +std::pair ffi_parse_type(const std::string& type_expr, FFITypedefs& typedefs); diff --git a/compiler/ffi/ffi_types.cpp b/compiler/ffi/ffi_types.cpp index a78c285284..a73b355a81 100644 --- a/compiler/ffi/ffi_types.cpp +++ b/compiler/ffi/ffi_types.cpp @@ -4,8 +4,8 @@ #include "compiler/ffi/ffi_types.h" -void ffi_type_delete(const FFIType *type) { - for (const auto *member : type->members) { +void ffi_type_delete(const FFIType* type) { + for (const auto* member : type->members) { ffi_type_delete(member); } delete type; diff --git a/compiler/ffi/ffi_types.h b/compiler/ffi/ffi_types.h index 146e763a3b..d7127aacbf 100644 --- a/compiler/ffi/ffi_types.h +++ b/compiler/ffi/ffi_types.h @@ -9,7 +9,7 @@ #include #include -enum class FFITypeKind: uint16_t { +enum class FFITypeKind : uint16_t { Unknown, // Function is a function definition. @@ -35,13 +35,13 @@ enum class FFITypeKind: uint16_t { // this->members[0]: type Var, - Struct, // str: struct type name + Struct, // str: struct type name StructDef, // str: struct type name; members: StructField entries - Enum, // str: enum type name + Enum, // str: enum type name EnumDef, // str: enum type name - Union, // str: union type name + Union, // str: union type name UnionDef, // str: union type name; members: StructField entries Name, // str: associated name @@ -84,8 +84,8 @@ enum class FFITypeKind: uint16_t { // They're like intermediate AST representations. _abstractArrayDeclarator, // num: array size - _arrayDeclarator, // num: array size - _pointerDeclarator, // num: indirection level + _arrayDeclarator, // num: array size + _pointerDeclarator, // num: indirection level _typesList, _structFieldList, _initDeclaratorList, @@ -100,17 +100,17 @@ enum class FFITypeKind: uint16_t { }; struct FFIType { - enum Flag: uint16_t { + enum Flag : uint16_t { EmptySet = 0, - Const = 1 << 0, + Const = 1 << 0, Volatile = 1 << 1, Variadic = 1 << 2, Unsigned = 1 << 3, - Signed = 1 << 4, - Short = 1 << 5, - Long = 1 << 6, + Signed = 1 << 4, + Short = 1 << 5, + Long = 1 << 6, LongLong = 1 << 7, // Second "long" specifier bit Used = 1 << 8, @@ -126,15 +126,26 @@ struct FFIType { FFIType() = default; - explicit FFIType(FFITypeKind kind): kind{kind} {} - explicit FFIType(std::string str): str{std::move(str)} {} - explicit FFIType(Flag flags): flags{flags} {} + explicit FFIType(FFITypeKind kind) + : kind{kind} {} + explicit FFIType(std::string str) + : str{std::move(str)} {} + explicit FFIType(Flag flags) + : flags{flags} {} - FFIType(FFITypeKind kind, Flag flags): kind{kind}, flags{flags} {} + FFIType(FFITypeKind kind, Flag flags) + : kind{kind}, + flags{flags} {} - bool is_const() const noexcept { return flags & Flag::Const; } - bool is_variadic() const noexcept { return flags & Flag::Variadic; } - bool is_signal_safe() const noexcept { return flags & Flag::SignalSafe; } + bool is_const() const noexcept { + return flags & Flag::Const; + } + bool is_variadic() const noexcept { + return flags & Flag::Variadic; + } + bool is_signal_safe() const noexcept { + return flags & Flag::SignalSafe; + } // whether a type is `void*` bool is_void_ptr() const noexcept { @@ -143,10 +154,7 @@ struct FFIType { // whether a type is `const char*` bool is_cstring() const noexcept { - return kind == FFITypeKind::Pointer && - members[0]->kind == FFITypeKind::Char && - members[0]->is_const() && - num == 1; + return kind == FFITypeKind::Pointer && members[0]->kind == FFITypeKind::Char && members[0]->is_const() && num == 1; } }; @@ -157,6 +165,6 @@ struct FFIBuiltinType { std::string src_name; }; -void ffi_type_delete(const FFIType *type); +void ffi_type_delete(const FFIType* type); using FFITypedefs = std::unordered_map; diff --git a/compiler/function-colors.cpp b/compiler/function-colors.cpp index 9ee51a3d40..48c33cdc79 100644 --- a/compiler/function-colors.cpp +++ b/compiler/function-colors.cpp @@ -8,16 +8,16 @@ using namespace function_palette; -PaletteRule::PaletteRule(std::vector &&colors, std::string error) - : colors(std::move(colors)) - , error(std::move(error)) { +PaletteRule::PaletteRule(std::vector&& colors, std::string error) + : colors(std::move(colors)), + error(std::move(error)) { for (color_t color : this->colors) { mask |= color; } } -std::string PaletteRule::as_human_readable(const Palette &palette) const { +std::string PaletteRule::as_human_readable(const Palette& palette) const { return vk::join(colors, " ", [palette](auto color) { return palette.get_name_by_color(color); }); } @@ -28,13 +28,13 @@ Palette::Palette() { color_names_mapping["remover"] = special_color_remover; } -color_t Palette::register_color_name(const std::string &color_name) { +color_t Palette::register_color_name(const std::string& color_name) { auto found = color_names_mapping.find(color_name); if (found != color_names_mapping.end()) { return found->second; } - int bit_shift = color_names_mapping.size() - 1; // user-defined colors are 1<<1, 1<<2, and so on + int bit_shift = color_names_mapping.size() - 1; // user-defined colors are 1<<1, 1<<2, and so on color_t color = 1ULL << bit_shift; color_names_mapping[color_name] = color; @@ -42,14 +42,14 @@ color_t Palette::register_color_name(const std::string &color_name) { return color; } -color_t Palette::get_color_by_name(const std::string &color_name) const { +color_t Palette::get_color_by_name(const std::string& color_name) const { const auto found = color_names_mapping.find(color_name); kphp_assert(found != color_names_mapping.end()); return found->second; } std::string Palette::get_name_by_color(color_t color) const { - for (const auto &pair : color_names_mapping) { + for (const auto& pair : color_names_mapping) { if (pair.second == color) { return pair.first; } @@ -73,7 +73,7 @@ bool ColorContainer::contains(color_t color) const { return std::any_of(sep_colors.begin(), sep_colors.end(), [=](color_t c) { return c == color; }); } -std::string ColorContainer::to_string(const Palette &palette, colors_mask_t with_highlights) const { +std::string ColorContainer::to_string(const Palette& palette, colors_mask_t with_highlights) const { std::string desc; for (color_t color : sep_colors) { diff --git a/compiler/function-colors.h b/compiler/function-colors.h index 67d0a821dc..1cfa89f83d 100644 --- a/compiler/function-colors.h +++ b/compiler/function-colors.h @@ -15,8 +15,8 @@ namespace function_palette { using color_t = uint64_t; using colors_mask_t = uint64_t; -constexpr color_t special_color_transparent = 0; // all functions without any colors are transparent: C + transparent = C -constexpr color_t special_color_remover = 1ULL << 63; // @kphp-color remover works so: C + remover = transparent +constexpr color_t special_color_transparent = 0; // all functions without any colors are transparent: C + transparent = C +constexpr color_t special_color_remover = 1ULL << 63; // @kphp-color remover works so: C + remover = transparent class Palette; @@ -27,9 +27,9 @@ struct PaletteRule { colors_mask_t mask{0}; std::string error; - PaletteRule(std::vector &&colors, std::string error); + PaletteRule(std::vector&& colors, std::string error); - std::string as_human_readable(const Palette &palette) const; + std::string as_human_readable(const Palette& palette) const; bool is_error() const { return !error.empty(); @@ -54,21 +54,21 @@ class Palette { public: Palette(); - color_t register_color_name(const std::string &color_name); + color_t register_color_name(const std::string& color_name); - void add_ruleset(PaletteRuleset &&ruleset) { + void add_ruleset(PaletteRuleset&& ruleset) { rulesets.emplace_back(std::move(ruleset)); } - const std::vector &get_rulesets() const { + const std::vector& get_rulesets() const { return rulesets; } - bool color_exists(const std::string &color_name) const { + bool color_exists(const std::string& color_name) const { return color_names_mapping.find(color_name) != color_names_mapping.end(); } - color_t get_color_by_name(const std::string &color_name) const; + color_t get_color_by_name(const std::string& color_name) const; std::string get_name_by_color(color_t color) const; }; @@ -79,15 +79,21 @@ class ColorContainer { public: ColorContainer() = default; - bool empty() const { return sep_colors.empty(); } + bool empty() const { + return sep_colors.empty(); + } - auto begin() const { return sep_colors.begin(); } - auto end() const { return sep_colors.end(); } + auto begin() const { + return sep_colors.begin(); + } + auto end() const { + return sep_colors.end(); + } void add(color_t color); bool contains(color_t color) const; - std::string to_string(const Palette &palette, colors_mask_t with_highlights) const; + std::string to_string(const Palette& palette, colors_mask_t with_highlights) const; }; } // namespace function_palette diff --git a/compiler/function-pass.h b/compiler/function-pass.h index 6375c250ce..e99e8c6ad4 100644 --- a/compiler/function-pass.h +++ b/compiler/function-pass.h @@ -4,7 +4,6 @@ #pragma once - #include "common/type_traits/function_traits.h" #include "compiler/data/data_ptr.h" @@ -19,8 +18,8 @@ class FunctionPassBase { protected: FunctionPtr current_function; -public: +public: using ExecuteType = FunctionPtr; void setup(FunctionPtr function) { @@ -37,9 +36,9 @@ class FunctionPassBase { return true; } - virtual void on_start() { } + virtual void on_start() {} - virtual void on_finish() { } + virtual void on_finish() {} virtual VertexPtr on_enter_vertex(VertexPtr vertex) { return vertex; @@ -55,22 +54,22 @@ class FunctionPassBase { }; template -void run_function_pass(VertexPtr &vertex, FunctionPassT *pass) { +void run_function_pass(VertexPtr& vertex, FunctionPassT* pass) { #ifdef __x86_64__ constexpr size_t STACK_INIT_CAP = 1000; constexpr uintptr_t MASK = 1UL << 49; - std::vector vertex_stack; + std::vector vertex_stack; vertex_stack.reserve(STACK_INIT_CAP); vertex_stack.push_back(&vertex); while (!vertex_stack.empty()) { - VertexPtr *cur_vertex = vertex_stack.back(); + VertexPtr* cur_vertex = vertex_stack.back(); if (reinterpret_cast(cur_vertex) & MASK) { vertex_stack.pop_back(); - cur_vertex = reinterpret_cast(reinterpret_cast(cur_vertex) ^ MASK); + cur_vertex = reinterpret_cast(reinterpret_cast(cur_vertex) ^ MASK); stage::set_location((*cur_vertex)->get_location()); *cur_vertex = pass->on_exit_vertex(*cur_vertex); continue; @@ -78,9 +77,9 @@ void run_function_pass(VertexPtr &vertex, FunctionPassT *pass) { stage::set_location((*cur_vertex)->get_location()); *cur_vertex = pass->on_enter_vertex(*cur_vertex); - vertex_stack.back() = reinterpret_cast(reinterpret_cast(cur_vertex) | MASK); + vertex_stack.back() = reinterpret_cast(reinterpret_cast(cur_vertex) | MASK); if (!pass->user_recursion(*cur_vertex)) { - for (auto *son_iter = (*cur_vertex)->rbegin(); son_iter != (*cur_vertex)->rend(); ++son_iter) { + for (auto* son_iter = (*cur_vertex)->rbegin(); son_iter != (*cur_vertex)->rend(); ++son_iter) { vertex_stack.push_back(&*son_iter); } } @@ -91,7 +90,7 @@ void run_function_pass(VertexPtr &vertex, FunctionPassT *pass) { vertex = pass->on_enter_vertex(vertex); if (!pass->user_recursion(vertex)) { - for (auto &i : *vertex) { + for (auto& i : *vertex) { run_function_pass(i, pass); } } @@ -102,7 +101,7 @@ void run_function_pass(VertexPtr &vertex, FunctionPassT *pass) { } template -void run_function_pass(VertexAdaptor &vertex, FunctionPassT *pass) { +void run_function_pass(VertexAdaptor& vertex, FunctionPassT* pass) { VertexPtr v = vertex; run_function_pass(v, pass); vertex = v.as(); @@ -111,52 +110,57 @@ void run_function_pass(VertexAdaptor &vertex, FunctionPassT *pass) { template class FunctionPassTraits { struct get_data_helper { - template static decltype(std::declval().get_data()) Test(std::nullptr_t); - template static std::nullptr_t Test(...); + template + static decltype(std::declval().get_data()) Test(std::nullptr_t); + template + static std::nullptr_t Test(...); }; + public: using GetDataReturnT = decltype(get_data_helper::template Test(nullptr)); using IsNullPtr = std::is_same; using ExecuteType = typename FunctionPassT::ExecuteType; - using OutType = typename std::conditional< - IsNullPtr{}, - ExecuteType, - std::pair - >::type; - static OutType create_out_type(ExecuteType &&function, GetDataReturnT &&ret) { + using OutType = typename std::conditional>::type; + static OutType create_out_type(ExecuteType&& function, GetDataReturnT&& ret) { return create_out_type(std::move(function), std::move(ret), IsNullPtr{}); } - static FunctionPtr get_function(const ExecuteType &f) { + static FunctionPtr get_function(const ExecuteType& f) { return get_function_impl(f); } - static auto get_data(FunctionPassT &f) { + static auto get_data(FunctionPassT& f) { return get_data_impl(f, IsNullPtr{}); } - static_assert(IsNullPtr::value || std::is_same::value, - "Can't have nontrivial both on_finish return type and execute type"); + static_assert(IsNullPtr::value || std::is_same::value, "Can't have nontrivial both on_finish return type and execute type"); + private: - static OutType create_out_type(ExecuteType &&function, GetDataReturnT &&, std::true_type) { + static OutType create_out_type(ExecuteType&& function, GetDataReturnT&&, std::true_type) { return std::move(function); } - static OutType create_out_type(ExecuteType &&function, GetDataReturnT &&ret, std::false_type) { + static OutType create_out_type(ExecuteType&& function, GetDataReturnT&& ret, std::false_type) { return {std::move(function), std::move(ret)}; } - static std::nullptr_t get_data_impl(FunctionPassT &, std::true_type) { + static std::nullptr_t get_data_impl(FunctionPassT&, std::true_type) { return nullptr; } - static auto get_data_impl(FunctionPassT &f, std::false_type) { + static auto get_data_impl(FunctionPassT& f, std::false_type) { return f.get_data(); } template - static FunctionPtr get_function_impl(const T &f) { return f.function; } + static FunctionPtr get_function_impl(const T& f) { + return f.function; + } template - static FunctionPtr get_function_impl(const std::pair &f) { return f.first; } - static FunctionPtr get_function_impl(const FunctionPtr &f) { return f; } + static FunctionPtr get_function_impl(const std::pair& f) { + return f.first; + } + static FunctionPtr get_function_impl(const FunctionPtr& f) { + return f; + } }; template -typename FunctionPassTraits::GetDataReturnT run_function_pass(FunctionPtr function, FunctionPassT *pass) { +typename FunctionPassTraits::GetDataReturnT run_function_pass(FunctionPtr function, FunctionPassT* pass) { if (!pass->check_function(function)) { return {}; } @@ -172,14 +176,13 @@ typename FunctionPassTraits::GetDataReturnT run_function_pass(Fun return FunctionPassTraits::get_data(*pass); } - template class FunctionPassF { public: using need_profiler = std::false_type; using Traits = FunctionPassTraits; using OutType = typename Traits::OutType; - void execute(typename Traits::ExecuteType function, DataStream &os) { + void execute(typename Traits::ExecuteType function, DataStream& os) { FunctionPassT pass; auto x = run_function_pass(Traits::get_function(function), &pass); if (stage::has_error()) { @@ -188,4 +191,3 @@ class FunctionPassF { os << Traits::create_out_type(std::move(function), std::move(x)); } }; - diff --git a/compiler/generics-reification.cpp b/compiler/generics-reification.cpp index ed617b2db0..67d09052c6 100644 --- a/compiler/generics-reification.cpp +++ b/compiler/generics-reification.cpp @@ -11,7 +11,6 @@ #include "compiler/type-hint.h" #include "compiler/vertex-util.h" - /* * The word "reification" means deducing generic T to instantiate generic functions/classes. * function f(T $arg) {} @@ -58,12 +57,12 @@ */ // implemented in DeduceImplicitTypesAndCastsPass cpp -void patch_rhs_casting_to_callable(VertexPtr &rhs, const TypeHintCallable *as_callable, VertexAdaptor call); +void patch_rhs_casting_to_callable(VertexPtr& rhs, const TypeHintCallable* as_callable, VertexAdaptor call); // assumptions for vars aren't saved unless they contain instances (neither for parameters, nor for local vars) // i.e. even if you write `@var int|false $a`, it won't be saved as an assumption, and `return $a` will assume unknown // for generics instantiating, like calls `f($a)` we intentionally search for @var even with primitives -static const TypeHint *find_first_phpdoc_for_var(FunctionPtr current_function, const std::string &var_name, VertexPtr stop_at) { +static const TypeHint* find_first_phpdoc_for_var(FunctionPtr current_function, const std::string& var_name, VertexPtr stop_at) { bool stopped = false; VertexAdaptor found; @@ -93,7 +92,7 @@ static const TypeHint *find_first_phpdoc_for_var(FunctionPtr current_function, c // we also support `f`, that's why we call phpdoc_replace_genericTs_with_reified() here // having default types which depend on earlier T is specially useful for generic classes, e.g. `C>` static inline void apply_defaultTs_if_someTs_not_set(FunctionPtr generic_function, VertexAdaptor call) { - for (const auto &itemT : *generic_function->genericTs) { + for (const auto& itemT : *generic_function->genericTs) { if (itemT.def_hint && !call->reifiedTs->find(itemT.nameT)) { call->reifiedTs->provideT(itemT.nameT, phpdoc_replace_genericTs_with_reified(itemT.def_hint, call->reifiedTs), call); } @@ -102,7 +101,7 @@ static inline void apply_defaultTs_if_someTs_not_set(FunctionPtr generic_functio // when php code contains an explicit generics instantiation `f/**/()`, apply it to f // "T1, T2" was parsed earlier by tokenizer in ParseAndApplyPhpDocForFunction -void apply_instantiationTs_from_php_comment(FunctionPtr generic_function, VertexAdaptor call, const GenericsInstantiationPhpComment *commentTs) { +void apply_instantiationTs_from_php_comment(FunctionPtr generic_function, VertexAdaptor call, const GenericsInstantiationPhpComment* commentTs) { kphp_assert(commentTs != nullptr && !commentTs->vectorTs.empty()); kphp_error(commentTs->vectorTs.size() <= generic_function->genericTs->size(), fmt_format("Mismatch generics instantiation count: waiting {}, got {}", generic_function->genericTs->size(), commentTs->vectorTs.size())); @@ -117,8 +116,8 @@ void apply_instantiationTs_from_php_comment(FunctionPtr generic_function, Vertex // when we have a call `f($v)` for a generic function `f`, then T depends on $v // for $v=1 return int, for $v=$a->field return type of A::$field (even for primitives), etc. -static const TypeHint *reify_instantiationT_from_expr(FunctionPtr current_function, VertexPtr v) { - const TypeHint *instantiationT = assume_class_of_expr(current_function, v, v).assum_hint; +static const TypeHint* reify_instantiationT_from_expr(FunctionPtr current_function, VertexPtr v) { + const TypeHint* instantiationT = assume_class_of_expr(current_function, v, v).assum_hint; // assumptions don't save @var for variables if they are primitives (on purpose, because they can be splitted) // that's why, having code `$a = 1; f($a)`, assumption for $a will be null, even if `@var int` written @@ -134,7 +133,8 @@ static const TypeHint *reify_instantiationT_from_expr(FunctionPtr current_functi // having a call `f($arg)`, where f is `f`, and $arg is `@param T[] $array`, deduce T // for example, if an assumption for $arg is A[], then T is A // this function is called for every generic argument of `f()` invocation -static void reify_genericT_from_call_argument(FunctionPtr current_function, FunctionPtr generic_function, const TypeHint *param_hint, VertexAdaptor call, VertexPtr &call_arg, bool old_syntax) { +static void reify_genericT_from_call_argument(FunctionPtr current_function, FunctionPtr generic_function, const TypeHint* param_hint, + VertexAdaptor call, VertexPtr& call_arg, bool old_syntax) { kphp_assert(param_hint->has_genericT_inside() && generic_function->genericTs != nullptr); param_hint = param_hint->unwrap_optional(); @@ -144,8 +144,8 @@ static void reify_genericT_from_call_argument(FunctionPtr current_function, Func // f($a->field) means T=(type hint of A::$field), f(someFn()) means T=(return of someFn()) // f($var) means T=(assumption of $var) // f(null) and other (which can't be handled or are not handled in assumptions) don't reify T - if (const auto *as_genericT = param_hint->try_as()) { - const TypeHint *extends_hint = generic_function->genericTs->get_extends_hint(as_genericT->nameT); + if (const auto* as_genericT = param_hint->try_as()) { + const TypeHint* extends_hint = generic_function->genericTs->get_extends_hint(as_genericT->nameT); // here extends_hint is just used for converting 'strlen' to callable // this seems ugly, but I couldn't find a better way to reify f, not f @@ -157,7 +157,7 @@ static void reify_genericT_from_call_argument(FunctionPtr current_function, Func // fall through, instantiationT will be set to lambda$xxx } - const TypeHint *instantiationT = reify_instantiationT_from_expr(current_function, call_arg); + const TypeHint* instantiationT = reify_instantiationT_from_expr(current_function, call_arg); if (old_syntax && !instantiationT) { instantiationT = TypeHintPrimitive::create(tp_any); } @@ -169,11 +169,11 @@ static void reify_genericT_from_call_argument(FunctionPtr current_function, Func // for @param T[], if an argument is an array, reify T // f($arr_of_A) means T=A if $arr_of_a has an assumption A[] // f([1, ...]) means T=int, f($a->field) and f(someFn()) also work, even for arrays of primitives - if (const auto *as_array = param_hint->try_as()) { - if (const auto *as_genericT = as_array->inner->try_as()) { - const TypeHint *instantiationT = reify_instantiationT_from_expr(current_function, call_arg); + if (const auto* as_array = param_hint->try_as()) { + if (const auto* as_genericT = as_array->inner->try_as()) { + const TypeHint* instantiationT = reify_instantiationT_from_expr(current_function, call_arg); if (instantiationT) { - if (const auto *arg_array = instantiationT->try_as()) { + if (const auto* arg_array = instantiationT->try_as()) { call->reifiedTs->provideT(as_genericT->nameT, arg_array->inner, call); } } @@ -186,7 +186,7 @@ static void reify_genericT_from_call_argument(FunctionPtr current_function, Func // it will be reified (and filled into call) in `patch_rhs_casting_to_callable()` // for @param class-string, if an argument is A::class, reify T=A - if (const auto *as_class_string = param_hint->try_as()) { + if (const auto* as_class_string = param_hint->try_as()) { ClassPtr klassT; auto real_call_arg = VertexUtil::get_actual_value(call_arg); if (real_call_arg->type() == op_string) { @@ -195,7 +195,7 @@ static void reify_genericT_from_call_argument(FunctionPtr current_function, Func } kphp_error_return(klassT, "Expected ::class as a parameter, but got not a const string"); - const auto *as_genericT = as_class_string->inner->try_as(); + const auto* as_genericT = as_class_string->inner->try_as(); kphp_assert(as_genericT); call->reifiedTs->provideT(as_genericT->nameT, TypeHintInstance::create(klassT->name), call); } @@ -205,7 +205,8 @@ static void reify_genericT_from_call_argument(FunctionPtr current_function, Func // "auto deducing" for generic arguments is typically called "reification" // note, that if a PHP user calls f explicitly using `f/**/(...)`, this is NOT called: // this is called for auto-reification, when /*<...>*/ is omitted, meant to be obviously reified -void reify_function_genericTs_on_generic_func_call(FunctionPtr current_function, FunctionPtr generic_function, VertexAdaptor call, bool old_syntax) { +void reify_function_genericTs_on_generic_func_call(FunctionPtr current_function, FunctionPtr generic_function, VertexAdaptor call, + bool old_syntax) { kphp_assert(generic_function->is_generic() && generic_function->genericTs); call->reifiedTs = new GenericsInstantiationMixin(call->location); @@ -236,9 +237,9 @@ void reify_function_genericTs_on_generic_func_call(FunctionPtr current_function, // on instantiation `f()`, we have to detect whether `A` satisfies this "extends" restriction (implements SomeInterface here) // this function does this check, filling out_err or leaving it empty // for `f` this function is called for every of OR conditions -static bool does_instantiationT_fit_extends_condition(const TypeHint *instantiationT, const TypeHint *extends_cond, std::string &out_err) { - if (const auto *as_instance = extends_cond->try_as()) { - const auto *inst_instance = instantiationT->try_as(); +static bool does_instantiationT_fit_extends_condition(const TypeHint* instantiationT, const TypeHint* extends_cond, std::string& out_err) { + if (const auto* as_instance = extends_cond->try_as()) { + const auto* inst_instance = instantiationT->try_as(); if (!inst_instance) { out_err = fmt_format("It should be a class extending {}", as_instance->full_class_name); } else if (!as_instance->resolve()->is_parent_of(inst_instance->resolve())) { @@ -280,16 +281,16 @@ static bool does_instantiationT_fit_extends_condition(const TypeHint *instantiat // check that A corresponds SomeInterface // for `f`, check all conditions // we check only hints that are supported in declarations, see check_declarationT_extends_hint() -static void check_reifiedT_extends_hint(const std::string &nameT, const TypeHint *instantiationT, const TypeHint *extends_hint) { +static void check_reifiedT_extends_hint(const std::string& nameT, const TypeHint* instantiationT, const TypeHint* extends_hint) { std::string err; if (extends_hint->try_as() || extends_hint->try_as() || extends_hint->try_as()) { // 'T: SomeInterface' / 'T: BaseClass' / 'T: callable' / 'T: object' does_instantiationT_fit_extends_condition(instantiationT->unwrap_optional(), extends_hint, err); - } else if (const auto *as_pipe = extends_hint->try_as()) { + } else if (const auto* as_pipe = extends_hint->try_as()) { // 'T: int|string' / 'T: SomeInterface|SomeInterface2' - for (const TypeHint *item : as_pipe->items) { + for (const TypeHint* item : as_pipe->items) { if (does_instantiationT_fit_extends_condition(instantiationT->unwrap_optional(), item, err)) { return; } @@ -300,24 +301,25 @@ static void check_reifiedT_extends_hint(const std::string &nameT, const TypeHint kphp_assert(0 && "unexpected extends_hint branch"); } - kphp_error(err.empty(), - fmt_format("Calculated generic <{}> = {} breaks condition '{}:{}'.\n{}", nameT, TermStringFormat::paint_green(instantiationT->as_human_readable()), nameT, extends_hint->as_human_readable(), err)); + kphp_error(err.empty(), fmt_format("Calculated generic <{}> = {} breaks condition '{}:{}'.\n{}", nameT, + TermStringFormat::paint_green(instantiationT->as_human_readable()), nameT, extends_hint->as_human_readable(), err)); } // when all generic T of `f()` have been auto-reified or parsed from /**/, // check their correctness -void check_reifiedTs_for_generic_func_call(const GenericsDeclarationMixin *genericTs, VertexAdaptor call, bool old_syntax) { +void check_reifiedTs_for_generic_func_call(const GenericsDeclarationMixin* genericTs, VertexAdaptor call, bool old_syntax) { kphp_assert(call->reifiedTs); - for (const auto &itemT : *genericTs) { - const TypeHint *instantiationT = call->reifiedTs->find(itemT.nameT); + for (const auto& itemT : *genericTs) { + const TypeHint* instantiationT = call->reifiedTs->find(itemT.nameT); if (!instantiationT || instantiationT->has_genericT_inside() || instantiationT->has_autogeneric_inside()) { kphp_error(0, fmt_format("Couldn't reify generic <{}> for call.\n{}", itemT.nameT, genericTs->prompt_provide_commentTs_human_readable(call))); continue; } // prohibit f() and others any-containing (even if set explicitly) if (!old_syntax) { - kphp_error(!instantiationT->has_tp_any_inside(), fmt_format("Generics <{}> = {} should be strict, it must not contain 'any' inside", itemT.nameT, TermStringFormat::paint_green(instantiationT->as_human_readable()))); + kphp_error(!instantiationT->has_tp_any_inside(), fmt_format("Generics <{}> = {} should be strict, it must not contain 'any' inside", itemT.nameT, + TermStringFormat::paint_green(instantiationT->as_human_readable()))); } if (itemT.extends_hint) { @@ -341,8 +343,8 @@ class ReplaceVariadicArgWithNArgsPass : public FunctionPassBase { public: explicit ReplaceVariadicArgWithNArgsPass(FunctionPtr generic_function, int n_variadic) - : generic_function(std::move(generic_function)) - , n_variadic(n_variadic) {} + : generic_function(std::move(generic_function)), + n_variadic(n_variadic) {} std::string get_description() override { return "Replace $args with $args$1, $args$2"; @@ -368,7 +370,9 @@ class ReplaceVariadicArgWithNArgsPass : public FunctionPassBase { } if (is_op_var_generic(root)) { - kphp_error(0, fmt_format("Variadic argument ...${} used incorrectly in a variadic generic.\nIt can not be replaced with N={} copies here.\nFor example, f(${}) is incorrect, but f(...${}) is okay.", variadic_var_name, n_variadic, variadic_var_name, variadic_var_name)); + kphp_error(0, fmt_format("Variadic argument ...${} used incorrectly in a variadic generic.\nIt can not be replaced with N={} copies here.\nFor example, " + "f(${}) is incorrect, but f(...${}) is okay.", + variadic_var_name, n_variadic, variadic_var_name, variadic_var_name)); } return root; @@ -442,12 +446,12 @@ class ReplaceVariadicArgWithNArgsPass : public FunctionPassBase { new_args_vector.reserve(call->size() - 1 + n_variadic); for (VertexPtr arg : call->args()) { - if (is_op_varg_op_var_generic(arg)) { // f(1, 2, ...$here) + if (is_op_varg_op_var_generic(arg)) { // f(1, 2, ...$here) occured_varg = true; for (int i = 1; i <= n_variadic; ++i) { new_args_vector.emplace_back(create_ith_op_var(arg, i)); } - } else if (is_array_creation && is_op_var_generic(arg)) { // [1, 2, ...$here] (actually array_merge_spread(1, 2, $here)) + } else if (is_array_creation && is_op_var_generic(arg)) { // [1, 2, ...$here] (actually array_merge_spread(1, 2, $here)) occured_varg = true; for (int i = 1; i <= n_variadic; ++i) { std::vector ith_wrap{create_ith_op_var(arg, i)}; @@ -477,7 +481,7 @@ FunctionPtr convert_variadic_generic_function_accepting_N_args(FunctionPtr gener std::string name = generic_function->name + "$n" + std::to_string(n_variadic); FunctionPtr f_converted; - G->operate_on_function_locking(name, [generic_function, n_variadic, name, &f_converted](FunctionPtr &f_ht) { + G->operate_on_function_locking(name, [generic_function, n_variadic, name, &f_converted](FunctionPtr& f_ht) { if (f_ht) { f_converted = f_ht; return; diff --git a/compiler/generics-reification.h b/compiler/generics-reification.h index c0dfcb712a..8b45b028c4 100644 --- a/compiler/generics-reification.h +++ b/compiler/generics-reification.h @@ -9,8 +9,8 @@ class GenericsDeclarationMixin; - -void apply_instantiationTs_from_php_comment(FunctionPtr generic_function, VertexAdaptor call, const GenericsInstantiationPhpComment *commentTs); -void reify_function_genericTs_on_generic_func_call(FunctionPtr current_function, FunctionPtr generic_function, VertexAdaptor call, bool old_syntax); -void check_reifiedTs_for_generic_func_call(const GenericsDeclarationMixin *genericTs, VertexAdaptor call, bool old_syntax); +void apply_instantiationTs_from_php_comment(FunctionPtr generic_function, VertexAdaptor call, const GenericsInstantiationPhpComment* commentTs); +void reify_function_genericTs_on_generic_func_call(FunctionPtr current_function, FunctionPtr generic_function, VertexAdaptor call, + bool old_syntax); +void check_reifiedTs_for_generic_func_call(const GenericsDeclarationMixin* genericTs, VertexAdaptor call, bool old_syntax); FunctionPtr convert_variadic_generic_function_accepting_N_args(FunctionPtr generic_function, int n_variadic); diff --git a/compiler/gentree.cpp b/compiler/gentree.cpp index e914f481f3..3e2496cea4 100644 --- a/compiler/gentree.cpp +++ b/compiler/gentree.cpp @@ -14,9 +14,9 @@ #include "compiler/data/class-data.h" #include "compiler/data/define-data.h" #include "compiler/data/function-data.h" +#include "compiler/data/generics-mixins.h" #include "compiler/data/lib-data.h" #include "compiler/data/src-file.h" -#include "compiler/data/generics-mixins.h" #include "compiler/lambda-utils.h" #include "compiler/lexer.h" #include "compiler/name-gen.h" @@ -24,21 +24,24 @@ #include "compiler/stage.h" #include "compiler/type-hint.h" #include "compiler/utils/string-utils.h" -#include "compiler/vertex.h" #include "compiler/vertex-util.h" +#include "compiler/vertex.h" -#define CE(x) if (!(x)) {return {};} +#define CE(x) \ + if (!(x)) { \ + return {}; \ + } -GenTree::GenTree(std::vector tokens, SrcFilePtr file, DataStream &os) : - tokens(std::move(tokens)), - parsed_os(os), - cur(this->tokens.begin()), - end(this->tokens.end()), - processing_file(file) { // = stage::get_file() +GenTree::GenTree(std::vector tokens, SrcFilePtr file, DataStream& os) + : tokens(std::move(tokens)), + parsed_os(os), + cur(this->tokens.begin()), + end(this->tokens.end()), + processing_file(file) { // = stage::get_file() - kphp_assert (cur != end); + kphp_assert(cur != end); end--; - kphp_assert (end->type() == tok_end); + kphp_assert(end->type() == tok_end); line_num = cur->line_num; stage::set_line(line_num); @@ -54,26 +57,28 @@ void GenTree::next_cur() { } } -#define expect_msg(msg) ({ \ - fmt_format ("Expected {}, found '{}'", msg, cur == end ? "END OF FILE" : cur->to_str().c_str()); \ -}) +#define expect_msg(msg) ({ fmt_format("Expected {}, found '{}'", msg, cur == end ? "END OF FILE" : cur->to_str().c_str()); }) -#define expect(tp, msg) ({ \ - bool res__;\ - if (kphp_error (test_expect (tp), expect_msg(msg))) {\ - res__ = false;\ - } else {\ - next_cur();\ - res__ = true;\ - }\ - res__; \ -}) +#define expect(tp, msg) \ + ({ \ + bool res__; \ + if (kphp_error(test_expect(tp), expect_msg(msg))) { \ + res__ = false; \ + } else { \ + next_cur(); \ + res__ = true; \ + } \ + res__; \ + }) -#define expect2(tp1, tp2, msg) ({ \ - kphp_error (test_expect (tp1) || test_expect (tp2), expect_msg(msg)); \ - if (cur != end) {next_cur();} \ - 1;\ -}) +#define expect2(tp1, tp2, msg) \ + ({ \ + kphp_error(test_expect(tp1) || test_expect(tp2), expect_msg(msg)); \ + if (cur != end) { \ + next_cur(); \ + } \ + 1; \ + }) VertexAdaptor GenTree::get_var_name() { auto location = auto_location(); @@ -131,15 +136,15 @@ inline void GenTree::skip_phpdoc_tokens() { // consider the phpdocs in unexpected locations like array or return to be an ordinary comment // (usually such phpdocs contain @see or some text, they don't have @var annotations) while (cur->type() == tok_phpdoc) { - //kphp_error(cur->str_val.find("@var") == std::string::npos, "@var would not be analyzed"); + // kphp_error(cur->str_val.find("@var") == std::string::npos, "@var would not be analyzed"); next_cur(); } // phpdoc comments that need to be analyzed don't come here: see op_phpdoc_var } template -bool GenTree::gen_list(std::vector *res, FuncT f, TokenType delim) { - //Do not clear res. Result must be appended to it. +bool GenTree::gen_list(std::vector* res, FuncT f, TokenType delim) { + // Do not clear res. Result must be appended to it. bool prev_delim = false; bool next_delim = true; @@ -189,7 +194,7 @@ VertexAdaptor GenTree::get_conv() { auto location = auto_location(); next_cur(); VertexPtr converted_expression = get_expression(); - CE (!kphp_error(converted_expression, "get_conv failed")); + CE(!kphp_error(converted_expression, "get_conv failed")); return VertexAdaptor::create(converted_expression).set_location(location); } @@ -212,20 +217,20 @@ VertexAdaptor GenTree::get_func_call() { std::string name{cur->str_val}; next_cur(); - GenericsInstantiationPhpComment *commentTs{nullptr}; + GenericsInstantiationPhpComment* commentTs{nullptr}; if constexpr (Op == op_func_call) { - if (test_expect(tok_commentTs)) { // f/*<...>*/(args) + if (test_expect(tok_commentTs)) { // f/*<...>*/(args) commentTs = parse_php_commentTs(cur->str_val); next_cur(); } } - CE (expect(tok_oppar, "'('")); + CE(expect(tok_oppar, "'('")); skip_phpdoc_tokens(); std::vector next; bool ok_next = gen_list(&next, &GenTree::get_expression, tok_comma); - CE (!kphp_error(ok_next, "get argument list failed")); - CE (expect(tok_clpar, "')'")); + CE(!kphp_error(ok_next, "get argument list failed")); + CE(expect(tok_clpar, "')'")); auto call = VertexAdaptor::create_vararg(next).set_location(location); @@ -248,13 +253,12 @@ VertexAdaptor GenTree::get_short_array() { std::vector arr_elements; bool ok_next = gen_list(&arr_elements, &GenTree::get_expression, tok_comma); - CE (!kphp_error(ok_next, "get short array failed")); - CE (expect(tok_clbrk, "']'")); + CE(!kphp_error(ok_next, "get short array failed")); + CE(expect(tok_clbrk, "']'")); return VertexAdaptor::create(arr_elements).set_location(location); } - VertexAdaptor GenTree::get_string() { auto str = VertexAdaptor::create().set_location(auto_location()); str->str_val = static_cast(cur->str_val); @@ -269,7 +273,7 @@ VertexAdaptor GenTree::get_string_build() { std::vector strings; bool after_simple_expression = false; while (cur != end && cur->type() != tok_str_end) { - CE (vk::any_of_equal(cur->type(), tok_str, tok_expr_begin)); // make sure we handle all possible tokens + CE(vk::any_of_equal(cur->type(), tok_str, tok_expr_begin)); // make sure we handle all possible tokens if (cur->type() == tok_str) { strings.push_back(get_string()); if (after_simple_expression) { @@ -286,18 +290,18 @@ VertexAdaptor GenTree::get_string_build() { next_cur(); VertexPtr add = get_expression(); - CE (!kphp_error(add, "Bad expression in string")); + CE(!kphp_error(add, "Bad expression in string")); strings.push_back(add); - CE (expect(tok_expr_end, "'}'")); + CE(expect(tok_expr_end, "'}'")); } } - CE (expect(tok_str_end, "'\"'")); + CE(expect(tok_str_end, "'\"'")); return VertexAdaptor::create(strings).set_location(sb_location); } VertexPtr GenTree::get_postfix_expression(VertexPtr res, bool parenthesized) { - //postfix operators x++, x--, x[] and x{}, x->y, x() + // postfix operators x++, x--, x[] and x{}, x->y, x() bool need = true; while (need && cur != end) { auto op = cur; @@ -309,23 +313,23 @@ VertexPtr GenTree::get_postfix_expression(VertexPtr res, bool parenthesized) { res = v; need = true; next_cur(); - CE (!kphp_error(!parenthesized, "Expected variable, found parenthesized expression")); + CE(!kphp_error(!parenthesized, "Expected variable, found parenthesized expression")); } else if (tp == tok_dec) { auto v = VertexAdaptor::create(res).set_location(auto_location()); res = v; need = true; next_cur(); - CE (!kphp_error(!parenthesized, "Expected variable, found parenthesized expression")); + CE(!kphp_error(!parenthesized, "Expected variable, found parenthesized expression")); } else if (tp == tok_opbrk || tp == tok_opbrc) { auto location = auto_location(); next_cur(); VertexPtr i = get_expression(); if (tp == tok_opbrk) { - CE (expect(tok_clbrk, "']'")); + CE(expect(tok_clbrk, "']'")); } else { - CE (expect(tok_clbrc, "'}'")); + CE(expect(tok_clbrc, "'}'")); } - //TODO: it should be to separate operations + // TODO: it should be to separate operations if (!i) { auto v = VertexAdaptor::create(res); res = v; @@ -339,7 +343,7 @@ VertexPtr GenTree::get_postfix_expression(VertexPtr res, bool parenthesized) { auto location = auto_location(); next_cur(); VertexPtr rhs = get_expr_top(true); - CE (!kphp_error(rhs, "Failed to parse right argument of '->'")); + CE(!kphp_error(rhs, "Failed to parse right argument of '->'")); res = process_arrow(res, rhs); CE(res); res.set_location(location); @@ -351,22 +355,20 @@ VertexPtr GenTree::get_postfix_expression(VertexPtr res, bool parenthesized) { std::vector next; next.emplace_back(res); bool ok_next = gen_list(&next, &GenTree::get_expression, tok_comma); - CE (!kphp_error(ok_next, "get argument list failed")); - CE (expect(tok_clpar, "')'")); + CE(!kphp_error(ok_next, "get argument list failed")); + CE(expect(tok_clpar, "')'")); res = VertexAdaptor::create(next).set_location(location); need = true; } - - } return res; } -void GenTree::check_and_remove_num_separators(std::string &s) { +void GenTree::check_and_remove_num_separators(std::string& s) { bool was_separator = false; - for (const char &c : s) { + for (const char& c : s) { if (c == '_') { if (was_separator) { kphp_error_return(false, "Bad numeric constant, several '_' in a row are prohibited"); @@ -382,7 +384,7 @@ void GenTree::check_and_remove_num_separators(std::string &s) { } VertexPtr GenTree::get_op_num_const() { - auto get_vertex_with_str_val = [this] (auto vertex, std::string val) { + auto get_vertex_with_str_val = [this](auto vertex, std::string val) { auto res = decltype(vertex)::create(); res.set_location(auto_location()); res->str_val = std::move(val); @@ -412,13 +414,13 @@ VertexPtr GenTree::get_op_num_const() { return VertexPtr{}; } -VertexPtr GenTree::get_expr_top(bool was_arrow, const PhpDocComment *phpdoc) { +VertexPtr GenTree::get_expr_top(bool was_arrow, const PhpDocComment* phpdoc) { auto op = cur; VertexPtr res, first_node; TokenType type = op->type(); - auto get_vertex_with_str_val = [this] (auto vertex, std::string val) { + auto get_vertex_with_str_val = [this](auto vertex, std::string val) { auto res = decltype(vertex)::create(); res.set_location(auto_location()); res->str_val = std::move(val); @@ -428,271 +430,269 @@ VertexPtr GenTree::get_expr_top(bool was_arrow, const PhpDocComment *phpdoc) { bool return_flag = true; // whether to stop parsing without trying to parse expr as postfix expr bool parenthesized = false; switch (type) { - case tok_line_c: { - res = get_vertex_with_str_val(VertexAdaptor{}, std::to_string(stage::get_line())); - next_cur(); - break; - } - case tok_file_c: { - res = get_vertex_with_str_val(VertexAdaptor{}, processing_file->file_name); - next_cur(); - break; - } - case tok_file_relative_c: { - res = get_vertex_with_str_val(VertexAdaptor{}, processing_file->relative_file_name); - next_cur(); - break; - } - case tok_class_c: { - res = get_vertex_with_str_val(VertexAdaptor{}, cur_class ? cur_class->name : ""); - next_cur(); - break; - } - case tok_dir_c: { - res = get_vertex_with_str_val(VertexAdaptor{}, processing_file->file_name.substr(0, processing_file->file_name.rfind('/'))); - next_cur(); - break; - } - case tok_method_c: { - std::string fun_name; - if (cur_function->is_lambda()) { - fun_name = "{closure}"; - } else if (!cur_function->is_main_function()) { - fun_name = cur_class - ? cur_class->name + "::" + cur_function->name.substr(cur_function->name.rfind('$') + 1) - : cur_function->name; - } - res = get_vertex_with_str_val(VertexAdaptor{}, fun_name); - next_cur(); - break; - } - case tok_namespace_c: { - res = get_vertex_with_str_val(VertexAdaptor{}, processing_file->namespace_name); - next_cur(); - break; - } - case tok_func_c: { - std::string fun_name; - if (cur_function->is_lambda()) { - fun_name = "{closure}"; - } else if (!cur_function->is_main_function()) { - fun_name = cur_function->name.substr(cur_function->name.rfind('$') + 1); - } - res = get_vertex_with_str_val(VertexAdaptor{}, fun_name); - next_cur(); - break; - } - case tok_int_const_sep: { - res = get_op_num_const(); - next_cur(); - break; - } - case tok_int_const: { - res = get_op_num_const(); - next_cur(); - break; - } - case tok_nan: { - res = get_vertex_with_str_val(VertexAdaptor{}, "NAN"); - next_cur(); - break; - } - case tok_inf: { - res = get_vertex_with_str_val(VertexAdaptor{}, "std::numeric_limits::infinity()"); - next_cur(); - break; - } - case tok_float_const_sep: { - res = get_op_num_const(); - next_cur(); - break; - } - case tok_float_const: { - res = get_op_num_const(); - next_cur(); - break; - } - case tok_null: { - res = VertexAdaptor::create().set_location(auto_location()); - next_cur(); - break; - } - case tok_false: { - res = VertexAdaptor::create().set_location(auto_location()); - next_cur(); - break; - } - case tok_true: { - res = VertexAdaptor::create().set_location(auto_location()); - next_cur(); - break; - } - case tok_var_name: { - res = get_var_name(); - if (cur->type() == tok_double_colon) { // $class::method(), $class::$field, $class::CONST - res = get_member_by_name_after_var(res.as()); - } - return_flag = false; - break; - } - case tok_varg: { - bool good_prefix = cur != tokens.begin() && vk::any_of_equal(std::prev(cur)->type(), tok_comma, tok_oppar, tok_opbrk); - CE (!kphp_error(good_prefix, "It's not allowed using `...` in this place")); - - next_cur(); - res = get_expression(); - // since the argument for the spread operator can be anything, - // we do not check the type of the expression here - res = VertexAdaptor::create(res).set_location(res); - break; + case tok_line_c: { + res = get_vertex_with_str_val(VertexAdaptor{}, std::to_string(stage::get_line())); + next_cur(); + break; + } + case tok_file_c: { + res = get_vertex_with_str_val(VertexAdaptor{}, processing_file->file_name); + next_cur(); + break; + } + case tok_file_relative_c: { + res = get_vertex_with_str_val(VertexAdaptor{}, processing_file->relative_file_name); + next_cur(); + break; + } + case tok_class_c: { + res = get_vertex_with_str_val(VertexAdaptor{}, cur_class ? cur_class->name : ""); + next_cur(); + break; + } + case tok_dir_c: { + res = get_vertex_with_str_val(VertexAdaptor{}, processing_file->file_name.substr(0, processing_file->file_name.rfind('/'))); + next_cur(); + break; + } + case tok_method_c: { + std::string fun_name; + if (cur_function->is_lambda()) { + fun_name = "{closure}"; + } else if (!cur_function->is_main_function()) { + fun_name = cur_class ? cur_class->name + "::" + cur_function->name.substr(cur_function->name.rfind('$') + 1) : cur_function->name; } - case tok_str: - res = get_string(); - return_flag = false; // string is a valid postfix expr operand - break; - case tok_conv_int: - res = get_conv(); - break; - case tok_conv_bool: - res = get_conv(); - break; - case tok_conv_float: - res = get_conv(); - break; - case tok_conv_string: - res = get_conv(); - break; - case tok_conv_array: - res = get_conv(); - break; - - case tok_print: { - auto location = auto_location(); - next_cur(); - first_node = get_expression(); - CE (!kphp_error(first_node, "Failed to get print argument")); - auto print = VertexAdaptor::create(first_node).set_location(location); - print->str_val = "print"; - res = print; - break; + res = get_vertex_with_str_val(VertexAdaptor{}, fun_name); + next_cur(); + break; + } + case tok_namespace_c: { + res = get_vertex_with_str_val(VertexAdaptor{}, processing_file->namespace_name); + next_cur(); + break; + } + case tok_func_c: { + std::string fun_name; + if (cur_function->is_lambda()) { + fun_name = "{closure}"; + } else if (!cur_function->is_main_function()) { + fun_name = cur_function->name.substr(cur_function->name.rfind('$') + 1); } - case tok_require: - res = get_require(false); - break; - case tok_require_once: - res = get_require(true); - break; - - case tok_new: { - next_cur(); - if (test_expect(tok_func_name)) { // 'new A()' / 'new \Some\Class($args)' - auto func_call = get_func_call(); - // Hack to be more compatible with php - if (func_call->str_val == "Memcache") { - func_call->set_string("McMemcache"); - } - res = gen_constructor_call_with_args(func_call->str_val, func_call->get_next(), func_call->location); - CE(res); - } else if (test_expect(tok_var_name)) { // 'new $class_name' / 'new $class_name(...$args)' - res = get_by_name_construct(); - CE(res); - } else { - CE(!kphp_error(0, "Expected class name after new")); - } - break; + res = get_vertex_with_str_val(VertexAdaptor{}, fun_name); + next_cur(); + break; + } + case tok_int_const_sep: { + res = get_op_num_const(); + next_cur(); + break; + } + case tok_int_const: { + res = get_op_num_const(); + next_cur(); + break; + } + case tok_nan: { + res = get_vertex_with_str_val(VertexAdaptor{}, "NAN"); + next_cur(); + break; + } + case tok_inf: { + res = get_vertex_with_str_val(VertexAdaptor{}, "std::numeric_limits::infinity()"); + next_cur(); + break; + } + case tok_float_const_sep: { + res = get_op_num_const(); + next_cur(); + break; + } + case tok_float_const: { + res = get_op_num_const(); + next_cur(); + break; + } + case tok_null: { + res = VertexAdaptor::create().set_location(auto_location()); + next_cur(); + break; + } + case tok_false: { + res = VertexAdaptor::create().set_location(auto_location()); + next_cur(); + break; + } + case tok_true: { + res = VertexAdaptor::create().set_location(auto_location()); + next_cur(); + break; + } + case tok_var_name: { + res = get_var_name(); + if (cur->type() == tok_double_colon) { // $class::method(), $class::$field, $class::CONST + res = get_member_by_name_after_var(res.as()); } - case tok_func_name: { - cur++; - if (!test_expect(tok_oppar) && !test_expect(tok_commentTs)) { - if (!was_arrow && vk::any_of_equal(op->str_val, "die", "exit")) { // can be called without "()" - res = get_vertex_with_str_val(VertexAdaptor{}, static_cast(op->str_val)); - } else { - res = get_vertex_with_str_val(VertexAdaptor{}, static_cast(op->str_val)); - } - return_flag = was_arrow; - break; - } - cur--; + return_flag = false; + break; + } + case tok_varg: { + bool good_prefix = cur != tokens.begin() && vk::any_of_equal(std::prev(cur)->type(), tok_comma, tok_oppar, tok_opbrk); + CE(!kphp_error(good_prefix, "It's not allowed using `...` in this place")); - // we don't support namespaces for functions yet, but we - // permit \func() syntax and interpret it as func(); - // this logic is compatible with what we'll get after the - // function namespaces will be implemented + next_cur(); + res = get_expression(); + // since the argument for the spread operator can be anything, + // we do not check the type of the expression here + res = VertexAdaptor::create(res).set_location(res); + break; + } + case tok_str: + res = get_string(); + return_flag = false; // string is a valid postfix expr operand + break; + case tok_conv_int: + res = get_conv(); + break; + case tok_conv_bool: + res = get_conv(); + break; + case tok_conv_float: + res = get_conv(); + break; + case tok_conv_string: + res = get_conv(); + break; + case tok_conv_array: + res = get_conv(); + break; + + case tok_print: { + auto location = auto_location(); + next_cur(); + first_node = get_expression(); + CE(!kphp_error(first_node, "Failed to get print argument")); + auto print = VertexAdaptor::create(first_node).set_location(location); + print->str_val = "print"; + res = print; + break; + } + case tok_require: + res = get_require(false); + break; + case tok_require_once: + res = get_require(true); + break; + + case tok_new: { + next_cur(); + if (test_expect(tok_func_name)) { // 'new A()' / 'new \Some\Class($args)' auto func_call = get_func_call(); - if (func_call && func_call->str_val[0] == '\\' && !vk::contains(func_call->str_val, "::")) { - func_call->str_val.erase(0, 1); + // Hack to be more compatible with php + if (func_call->str_val == "Memcache") { + func_call->set_string("McMemcache"); } - - res = func_call; - return_flag = was_arrow; - break; + res = gen_constructor_call_with_args(func_call->str_val, func_call->get_next(), func_call->location); + CE(res); + } else if (test_expect(tok_var_name)) { // 'new $class_name' / 'new $class_name(...$args)' + res = get_by_name_construct(); + CE(res); + } else { + CE(!kphp_error(0, "Expected class name after new")); } - case tok_static: - next_cur(); - res = get_lambda_function(phpdoc, FunctionModifiers::static_lambda()); - break; - case tok_function: - case tok_fn: - res = get_lambda_function(phpdoc, FunctionModifiers::nonmember()); - break; - case tok_phpdoc: { // /** ... */ before expression (not before a statement) - vk::string_view phpdoc_str = cur->str_val; - next_cur(); - return get_expr_top(was_arrow, new PhpDocComment(phpdoc_str)); - } - case tok_isset: { - auto temp = get_multi_call(&GenTree::get_expression, true); - CE (!kphp_error(temp->size(), "isset function requires at least one argument")); - res = VertexPtr{}; - for (auto right : temp->args()) { - res = res ? VertexPtr(VertexAdaptor::create(res, right)) : right; + break; + } + case tok_func_name: { + cur++; + if (!test_expect(tok_oppar) && !test_expect(tok_commentTs)) { + if (!was_arrow && vk::any_of_equal(op->str_val, "die", "exit")) { // can be called without "()" + res = get_vertex_with_str_val(VertexAdaptor{}, static_cast(op->str_val)); + } else { + res = get_vertex_with_str_val(VertexAdaptor{}, static_cast(op->str_val)); } - res.set_location(temp->location); + return_flag = was_arrow; break; } - case tok_declare: - // see GenTree::parse_declare_at_top_of_file - kphp_error(0, "strict_types declaration must be the very first statement in the script"); - break; - case tok_array: - res = get_func_call(); - return_flag = false; // array is valid postfix expression operand - break; - case tok_tuple: - res = get_func_call(); - CE (!kphp_error(res.as()->size(), "tuple() must have at least one argument")); - break; - case tok_shape: - res = get_shape(); - break; - case tok_opbrk: - res = get_short_array(); - return_flag = false; // array is valid postfix expression operand - break; - case tok_list: - res = get_func_call(); - break; - case tok_defined: - res = get_func_call(); - break; - case tok_oppar: - next_cur(); - res = get_expression(); - CE (!kphp_error(res, "Failed to parse expression after '('")); - CE (expect(tok_clpar, "')'")); - return_flag = false; // expression inside '()' is valid postfix expression operand - parenthesized = true; - break; - case tok_str_begin: - res = get_string_build(); - break; - case tok_clone: { - next_cur(); - res = VertexAdaptor::create(get_expr_top(false)).set_location(auto_location()); - break; + cur--; + + // we don't support namespaces for functions yet, but we + // permit \func() syntax and interpret it as func(); + // this logic is compatible with what we'll get after the + // function namespaces will be implemented + auto func_call = get_func_call(); + if (func_call && func_call->str_val[0] == '\\' && !vk::contains(func_call->str_val, "::")) { + func_call->str_val.erase(0, 1); } - default: - return {}; + + res = func_call; + return_flag = was_arrow; + break; + } + case tok_static: + next_cur(); + res = get_lambda_function(phpdoc, FunctionModifiers::static_lambda()); + break; + case tok_function: + case tok_fn: + res = get_lambda_function(phpdoc, FunctionModifiers::nonmember()); + break; + case tok_phpdoc: { // /** ... */ before expression (not before a statement) + vk::string_view phpdoc_str = cur->str_val; + next_cur(); + return get_expr_top(was_arrow, new PhpDocComment(phpdoc_str)); + } + case tok_isset: { + auto temp = get_multi_call(&GenTree::get_expression, true); + CE(!kphp_error(temp->size(), "isset function requires at least one argument")); + res = VertexPtr{}; + for (auto right : temp->args()) { + res = res ? VertexPtr(VertexAdaptor::create(res, right)) : right; + } + res.set_location(temp->location); + break; + } + case tok_declare: + // see GenTree::parse_declare_at_top_of_file + kphp_error(0, "strict_types declaration must be the very first statement in the script"); + break; + case tok_array: + res = get_func_call(); + return_flag = false; // array is valid postfix expression operand + break; + case tok_tuple: + res = get_func_call(); + CE(!kphp_error(res.as()->size(), "tuple() must have at least one argument")); + break; + case tok_shape: + res = get_shape(); + break; + case tok_opbrk: + res = get_short_array(); + return_flag = false; // array is valid postfix expression operand + break; + case tok_list: + res = get_func_call(); + break; + case tok_defined: + res = get_func_call(); + break; + case tok_oppar: + next_cur(); + res = get_expression(); + CE(!kphp_error(res, "Failed to parse expression after '('")); + CE(expect(tok_clpar, "')'")); + return_flag = false; // expression inside '()' is valid postfix expression operand + parenthesized = true; + break; + case tok_str_begin: + res = get_string_build(); + break; + case tok_clone: { + next_cur(); + res = VertexAdaptor::create(get_expr_top(false)).set_location(auto_location()); + break; + } + default: + return {}; } if (return_flag) { @@ -748,17 +748,17 @@ VertexPtr GenTree::get_unary_op(int op_priority_cur, Operation unary_op_tp, bool TokenType transform_compare_operation_token(TokenType token) noexcept { switch (token) { - case tok_gt: - return tok_lt; - case tok_ge: - return tok_le; - case tok_neq_lg: - case tok_neq2: - return tok_eq2; - case tok_neq3: - return tok_eq3; - default: - return token; + case tok_gt: + return tok_lt; + case tok_ge: + return tok_le; + case tok_neq_lg: + case tok_neq2: + return tok_eq2; + case tok_neq3: + return tok_eq3; + default: + return token; } } @@ -793,21 +793,18 @@ VertexPtr GenTree::get_binary_op(int op_priority_cur, bool till_ternary) { const bool left_to_right = OpInfo::fixity(binary_op_tp) == left_opp; next_cur(); - VertexPtr right = ternary - ? get_expression() - : get_binary_op(op_priority_cur + left_to_right, - till_ternary && op_priority_cur >= OpInfo::ternaryP); + VertexPtr right = ternary ? get_expression() : get_binary_op(op_priority_cur + left_to_right, till_ternary && op_priority_cur >= OpInfo::ternaryP); if (!right && !ternary) { - kphp_error (0, fmt_format("Failed to parse second argument in [{}]", OpInfo::str(binary_op_tp))); + kphp_error(0, fmt_format("Failed to parse second argument in [{}]", OpInfo::str(binary_op_tp))); return {}; } VertexPtr third; if (ternary) { - CE (expect(tok_colon, "':'")); + CE(expect(tok_colon, "':'")); third = get_expression_impl(true); if (!third) { - kphp_error (0, fmt_format("Failed to parse third argument in [{}]", OpInfo::str(binary_op_tp))); + kphp_error(0, fmt_format("Failed to parse third argument in [{}]", OpInfo::str(binary_op_tp))); return {}; } if (right) { @@ -864,7 +861,7 @@ VertexPtr GenTree::get_def_value() { if (cur->type() == tok_eq1) { next_cur(); val = get_expression(); - kphp_error (val, "Cannot parse function parameter"); + kphp_error(val, "Cannot parse function parameter"); } return val; @@ -873,7 +870,7 @@ VertexPtr GenTree::get_def_value() { VertexAdaptor GenTree::get_func_param() { auto location = auto_location(); - const TypeHint *type_hint = get_typehint(); + const TypeHint* type_hint = get_typehint(); bool is_varg = false; // if the argument is vararg and has a type hint — e.g. int ...$a — then cur points to $a, as ... were consumed by the type lexer @@ -895,7 +892,7 @@ VertexAdaptor GenTree::get_func_param() { } bool is_cast_param = false; - if (cur->type() == tok_triple_colon) { // $x ::: string — a cast param + if (cur->type() == tok_triple_colon) { // $x ::: string — a cast param is_cast_param = true; next_cur(); type_hint = get_typehint(); @@ -928,9 +925,9 @@ VertexAdaptor GenTree::get_func_param() { std::pair, VertexPtr> GenTree::get_foreach_param() { auto location = auto_location(); VertexPtr array_expression = get_expression(); - CE (!kphp_error(array_expression, "")); + CE(!kphp_error(array_expression, "")); - CE (expect(tok_as, "'as'")); + CE(expect(tok_as, "'as'")); skip_phpdoc_tokens(); VertexAdaptor key; @@ -942,7 +939,7 @@ std::pair, VertexPtr> GenTree::get_foreach_param // as we can't easily distinguish $k=>$v from just $v if // get_var_name_ref failed to parse a variable. auto tok = *cur; - CE (!kphp_error(value_expr, fmt_format("Expected a var name, ref or list, found {}", tok.str_val))); + CE(!kphp_error(value_expr, fmt_format("Expected a var name, ref or list, found {}", tok.str_val))); if (vk::any_of_equal(value_expr->type(), op_list_ce, op_array)) { value = VertexUtil::create_superlocal_var("list", cur_function); @@ -956,7 +953,7 @@ std::pair, VertexPtr> GenTree::get_foreach_param key = value; tok = *cur; value = get_var_name_ref(); - CE (!kphp_error(value, fmt_format("Expected a var name, ref or list as a foreach value, found {}", tok.str_val))); + CE(!kphp_error(value, fmt_format("Expected a var name, ref or list as a foreach value, found {}", tok.str_val))); } VertexPtr temp_var; @@ -982,19 +979,19 @@ VertexPtr GenTree::get_call_arg_for_param(VertexAdaptor call, Vert } template -VertexAdaptor GenTree::get_multi_call(FuncT &&f, bool parenthesis) { +VertexAdaptor GenTree::get_multi_call(FuncT&& f, bool parenthesis) { auto location = auto_location(); next_cur(); if (parenthesis) { - CE (expect(tok_oppar, "'('")); + CE(expect(tok_oppar, "'('")); } std::vector next; bool ok_next = gen_list(&next, f, tok_comma); - CE (!kphp_error(ok_next, "Failed get_multi_call")); + CE(!kphp_error(ok_next, "Failed get_multi_call")); if (parenthesis) { - CE (expect(tok_clpar, "')'")); + CE(expect(tok_clpar, "')'")); } std::vector> new_next; @@ -1006,7 +1003,6 @@ VertexAdaptor GenTree::get_multi_call(FuncT &&f, bool parenthesis) { return VertexAdaptor::create(new_next).set_location(location); } - VertexAdaptor GenTree::get_return() { auto location = auto_location(); next_cur(); @@ -1021,23 +1017,21 @@ VertexAdaptor GenTree::get_return() { ret = VertexAdaptor::create(); } else { if (cur_function->is_constructor()) { - kphp_error(return_val->type() == op_var && return_val->get_string() == "this", - "Class constructor may return only $this or nothing."); + kphp_error(return_val->type() == op_var && return_val->get_string() == "this", "Class constructor may return only $this or nothing."); } ret = VertexAdaptor::create(return_val); } - CE (expect(tok_semicolon, "';'")); + CE(expect(tok_semicolon, "';'")); return ret.set_location(location); } - template VertexAdaptor GenTree::get_break_or_continue() { auto location = auto_location(); next_cur(); // https://www.php.net/manual/en/control-structures.continue.php auto level_of_enclosing_loops_to_skip = get_expression(); - CE (expect(tok_semicolon, "';'")); + CE(expect(tok_semicolon, "';'")); if (!level_of_enclosing_loops_to_skip) { auto one = VertexUtil::create_int_const(1); @@ -1051,16 +1045,16 @@ VertexAdaptor GenTree::get_foreach() { auto foreach_location = auto_location(); next_cur(); - CE (expect(tok_oppar, "'('")); + CE(expect(tok_oppar, "'('")); skip_phpdoc_tokens(); auto [foreach_param, foreach_list] = get_foreach_param(); - CE (!kphp_error(foreach_param, "Failed to parse 'foreach' params")); - CE (expect(tok_clpar, "')'")); + CE(!kphp_error(foreach_param, "Failed to parse 'foreach' params")); + CE(expect(tok_clpar, "')'")); VertexPtr body = get_statement(); - CE (!kphp_error(body, "Failed to parse 'foreach' body")); + CE(!kphp_error(body, "Failed to parse 'foreach' body")); // If foreach value is list expression, we rewrite the body // to include the list assignment as a first statement. @@ -1075,15 +1069,15 @@ VertexAdaptor GenTree::get_foreach() { VertexAdaptor GenTree::get_while() { auto while_location = auto_location(); next_cur(); - CE (expect(tok_oppar, "'('")); + CE(expect(tok_oppar, "'('")); skip_phpdoc_tokens(); VertexPtr condition = get_expression(); - CE (!kphp_error(condition, "Failed to parse 'while' condition")); + CE(!kphp_error(condition, "Failed to parse 'while' condition")); condition = VertexUtil::create_conv_to(tp_bool, condition); - CE (expect(tok_clpar, "')'")); + CE(expect(tok_clpar, "')'")); VertexPtr body = get_statement(); - CE (!kphp_error(body, "Failed to parse 'while' body")); + CE(!kphp_error(body, "Failed to parse 'while' body")); return VertexAdaptor::create(condition, VertexUtil::embrace(body)).set_location(while_location); } @@ -1091,20 +1085,20 @@ VertexAdaptor GenTree::get_while() { VertexAdaptor GenTree::get_if() { auto if_location = auto_location(); next_cur(); - CE (expect(tok_oppar, "'('")); + CE(expect(tok_oppar, "'('")); skip_phpdoc_tokens(); VertexPtr condition = get_expression(); - CE (!kphp_error(condition, "Failed to parse 'if' condition")); + CE(!kphp_error(condition, "Failed to parse 'if' condition")); condition = VertexUtil::create_conv_to(tp_bool, condition); - CE (expect(tok_clpar, "')'")); + CE(expect(tok_clpar, "')'")); VertexPtr true_cmd = get_statement(); - CE (!kphp_error(true_cmd, "Failed to parse 'if' body")); + CE(!kphp_error(true_cmd, "Failed to parse 'if' body")); if (cur->type() == tok_else) { next_cur(); auto false_cmd = get_statement(); - CE (!kphp_error(false_cmd, "Failed to parse 'else' statement")); + CE(!kphp_error(false_cmd, "Failed to parse 'else' statement")); return VertexAdaptor::create(condition, VertexUtil::embrace(true_cmd), VertexUtil::embrace(false_cmd)).set_location(if_location); } @@ -1114,21 +1108,21 @@ VertexAdaptor GenTree::get_if() { VertexAdaptor GenTree::get_for() { auto for_location = auto_location(); next_cur(); - CE (expect(tok_oppar, "'('")); + CE(expect(tok_oppar, "'('")); skip_phpdoc_tokens(); auto pre_cond_location = auto_location(); std::vector init_statements; bool ok_first_next = gen_list(&init_statements, &GenTree::get_expression, tok_comma); - CE (!kphp_error(ok_first_next, "Failed to parse 'for' precondition")); + CE(!kphp_error(ok_first_next, "Failed to parse 'for' precondition")); auto initialization = VertexAdaptor::create(init_statements).set_location(pre_cond_location); - CE (expect(tok_semicolon, "';'")); + CE(expect(tok_semicolon, "';'")); auto cond_location = auto_location(); std::vector condition_expressions; bool ok_second_next = gen_list(&condition_expressions, &GenTree::get_expression, tok_comma); - CE (!kphp_error(ok_second_next, "Failed to parse 'for' action")); + CE(!kphp_error(ok_second_next, "Failed to parse 'for' action")); if (condition_expressions.empty()) { condition_expressions.push_back(VertexAdaptor::create()); } else { @@ -1136,18 +1130,18 @@ VertexAdaptor GenTree::get_for() { } auto condition = VertexAdaptor::create(condition_expressions).set_location(cond_location); - CE (expect(tok_semicolon, "';'")); + CE(expect(tok_semicolon, "';'")); auto iteration_location = auto_location(); std::vector iteration_expressions; bool ok_third_next = gen_list(&iteration_expressions, &GenTree::get_expression, tok_comma); - CE (!kphp_error(ok_third_next, "Failed to parse 'for' postcondition")); + CE(!kphp_error(ok_third_next, "Failed to parse 'for' postcondition")); auto iteration = VertexAdaptor::create(iteration_expressions).set_location(iteration_location); - CE (expect(tok_clpar, "')'")); + CE(expect(tok_clpar, "')'")); VertexPtr cmd = get_statement(); - CE (!kphp_error(cmd, "Failed to parse 'for' statement")); + CE(!kphp_error(cmd, "Failed to parse 'for' statement")); return VertexAdaptor::create(initialization, condition, iteration, VertexUtil::embrace(cmd)).set_location(for_location); } @@ -1156,18 +1150,18 @@ VertexAdaptor GenTree::get_do() { auto location = auto_location(); next_cur(); VertexPtr body = get_statement(); - CE (!kphp_error(body, "Failed to parser 'do' statement")); + CE(!kphp_error(body, "Failed to parser 'do' statement")); - CE (expect(tok_while, "'while'")); - CE (expect(tok_oppar, "'('")); + CE(expect(tok_while, "'while'")); + CE(expect(tok_oppar, "'('")); skip_phpdoc_tokens(); VertexPtr condition = get_expression(); - CE (!kphp_error(condition, "Failed to parse 'do' condition")); + CE(!kphp_error(condition, "Failed to parse 'do' condition")); condition = VertexUtil::create_conv_to(tp_bool, condition); - CE (expect(tok_clpar, "')'")); - CE (expect(tok_semicolon, "';'")); + CE(expect(tok_clpar, "')'")); + CE(expect(tok_semicolon, "';'")); return VertexAdaptor::create(VertexUtil::embrace(body), condition).set_location(location); } @@ -1176,13 +1170,13 @@ VertexAdaptor GenTree::get_switch() { auto location = auto_location(); next_cur(); - CE (expect(tok_oppar, "'('")); + CE(expect(tok_oppar, "'('")); skip_phpdoc_tokens(); auto switch_condition = get_expression(); - CE (!kphp_error(switch_condition, "Failed to parse 'switch' expression")); - CE (expect(tok_clpar, "')'")); + CE(!kphp_error(switch_condition, "Failed to parse 'switch' expression")); + CE(expect(tok_clpar, "')'")); - CE (expect(tok_opbrc, "'{'")); + CE(expect(tok_opbrc, "'{'")); std::vector cases; while (cur->type() != tok_clbrc) { @@ -1194,13 +1188,13 @@ VertexAdaptor GenTree::get_switch() { if (cur_type == tok_case) { next_cur(); case_val = get_expression(); - CE (!kphp_error(case_val, "Failed to parse 'case' value")); + CE(!kphp_error(case_val, "Failed to parse 'case' value")); - CE (expect2(tok_colon, tok_semicolon, "':'")); + CE(expect2(tok_colon, tok_semicolon, "':'")); } else { CE(test_expect(tok_default)); next_cur(); - CE (expect2(tok_colon, tok_semicolon, "':'")); + CE(expect2(tok_colon, tok_semicolon, "':'")); } auto seq_location = auto_location(); @@ -1219,7 +1213,7 @@ VertexAdaptor GenTree::get_switch() { } cases.back().set_location(case_location); } - CE (expect(tok_clbrc, "'}'")); + CE(expect(tok_clbrc, "'}'")); return VertexUtil::create_switch_vertex(cur_function, switch_condition.set_location(location), std::move(cases)).set_location(location); } @@ -1228,20 +1222,20 @@ VertexAdaptor GenTree::get_shape() { auto location = auto_location(); next_cur(); - CE (expect(tok_oppar, "'('")); + CE(expect(tok_oppar, "'('")); VertexPtr inner_array = get_expression(); - CE (expect(tok_clpar, "')'")); - CE (!kphp_error(inner_array && inner_array->type() == op_array && !inner_array->empty(), "shape() must have an array associative non-empty inside")); + CE(expect(tok_clpar, "')'")); + CE(!kphp_error(inner_array && inner_array->type() == op_array && !inner_array->empty(), "shape() must have an array associative non-empty inside")); std::set keys_hashes; for (VertexPtr arr_elem : inner_array.as()->args()) { auto double_arrow = arr_elem.try_as(); - CE (!kphp_error(double_arrow, "shape() must have an array associative non-empty inside")); + CE(!kphp_error(double_arrow, "shape() must have an array associative non-empty inside")); auto key_v = double_arrow->lhs(); - CE (!kphp_error(vk::any_of_equal(key_v->type(), op_int_const, op_string, op_func_name), "keys of shape() must be constant")); - const std::string &key_str = key_v->get_string(); + CE(!kphp_error(vk::any_of_equal(key_v->type(), op_int_const, op_string, op_func_name), "keys of shape() must be constant")); + const std::string& key_str = key_v->get_string(); const std::int64_t hash = string_hash(key_str.data(), key_str.size()); - CE (!kphp_error(keys_hashes.insert(hash).second, "keys of shape() are not unique")); + CE(!kphp_error(keys_hashes.insert(hash).second, "keys of shape() are not unique")); } // shape->args() is a sequence of op_double_arrow @@ -1253,7 +1247,7 @@ VertexAdaptor GenTree::get_shape() { // later, if $c is constexpr (class-string for example), this call will be replaced with `new T(...)` // see replace-extern-func-calls.cpp VertexPtr GenTree::get_by_name_construct() { - kphp_assert(cur->type() == tok_var_name); // cur is $c + kphp_assert(cur->type() == tok_var_name); // cur is $c auto v_class_name = VertexAdaptor::create().set_location(auto_location()); v_class_name->str_val = static_cast(cur->str_val); // 'c' @@ -1264,7 +1258,7 @@ VertexPtr GenTree::get_by_name_construct() { if (dummy_call) { args.insert(args.end(), dummy_call->begin(), dummy_call->end()); } - } else { // `new $c` + } else { // `new $c` next_cur(); } @@ -1283,13 +1277,13 @@ VertexPtr GenTree::get_member_by_name_after_var(VertexAdaptor v_before) next_cur(); // $c::method(...) -> _by_name_call_method($c, 'method', ...) - if (cur->type() == tok_func_name && (cur+1)->type() == tok_oppar) { + if (cur->type() == tok_func_name && (cur + 1)->type() == tok_oppar) { auto v_method_name = VertexAdaptor::create().set_location(auto_location()); v_method_name->str_val = static_cast(cur->str_val); auto dummy_call = get_func_call(); std::vector args = {v_before, v_method_name}; - if (dummy_call) { // 'if' not to fail on unclosed '(' + if (dummy_call) { // 'if' not to fail on unclosed '(' args.insert(args.end(), dummy_call->begin(), dummy_call->end()); } @@ -1301,7 +1295,7 @@ VertexPtr GenTree::get_member_by_name_after_var(VertexAdaptor v_before) // $c::CONST -> _by_name_get_const($c, 'CONST') // $c::CONST[0] and similar also supported - if (cur->type() == tok_func_name && (cur+1)->type() != tok_oppar) { + if (cur->type() == tok_func_name && (cur + 1)->type() != tok_oppar) { auto v_const_name = VertexAdaptor::create().set_location(auto_location()); v_const_name->str_val = static_cast(cur->str_val); @@ -1318,7 +1312,10 @@ VertexPtr GenTree::get_member_by_name_after_var(VertexAdaptor v_before) // $c::$field[0] += and similar also supported // note, that for $c::$var(, we fire an error, because it's $c::$method(), an unsupported dynamic call by name if (cur->type() == tok_var_name) { - kphp_error_act((cur+1)->type() != tok_oppar, "Syntax '$class_name::$method_name()' is invalid in KPHP.\nProbably, you need switch-case or code generation instead of invocations via dynamic names.", return v_before); + kphp_error_act( + (cur + 1)->type() != tok_oppar, + "Syntax '$class_name::$method_name()' is invalid in KPHP.\nProbably, you need switch-case or code generation instead of invocations via dynamic names.", + return v_before); auto v_field_name = VertexAdaptor::create().set_location(auto_location()); v_field_name->str_val = static_cast(cur->str_val); @@ -1344,7 +1341,7 @@ VertexPtr GenTree::get_phpdoc_inside_function() { vk::string_view phpdoc_str = cur->str_val; // there can be several @var directives (for example, a block of @var comments above the list() assignment) - for (const PhpDocTag &tag: PhpDocComment(phpdoc_str).tags) { + for (const PhpDocTag& tag : PhpDocComment(phpdoc_str).tags) { if (tag.type == PhpDocType::var) { // we are able to parse @var in gentree: @kphp-generic was already parsed, and generic T won't mess with class T // classes resolving (and error for unknown classes) will happen later, in parse-and-apply-phpdoc.cpp @@ -1369,7 +1366,7 @@ VertexPtr GenTree::get_phpdoc_inside_function() { } } - next_cur(); // only here, not at the beginning: in case of phpdoc errors to point to phpdoc + next_cur(); // only here, not at the beginning: in case of phpdoc errors to point to phpdoc return result ?: VertexPtr(VertexAdaptor::create()); } @@ -1381,24 +1378,22 @@ bool GenTree::parse_cur_function_uses() { std::vector> uses_as_vars; gen_list(&uses_as_vars, &GenTree::get_function_use_var_name_ref, tok_comma); - for (auto &v : uses_as_vars) { - cur_function->uses_list.emplace_front(v); // the order — use($v1, $v2) or use($v2, $v1) — doesn't matter + for (auto& v : uses_as_vars) { + cur_function->uses_list.emplace_front(v); // the order — use($v1, $v2) or use($v2, $v1) — doesn't matter } return expect(tok_clpar, "`)`"); } -bool GenTree::test_if_uses_and_arguments_intersect(const std::forward_list> &uses_list, const VertexRange ¶ms) { +bool GenTree::test_if_uses_and_arguments_intersect(const std::forward_list>& uses_list, const VertexRange& params) { return std::any_of(uses_list.begin(), uses_list.end(), [params](auto var_as_use) { - return std::any_of(params.begin(), params.end(), [var_as_use](auto p) { - return p.template as()->var()->str_val == var_as_use->str_val; - }); + return std::any_of(params.begin(), params.end(), [var_as_use](auto p) { return p.template as()->var()->str_val == var_as_use->str_val; }); }); } -VertexAdaptor GenTree::get_lambda_function(const PhpDocComment *phpdoc, FunctionModifiers modifiers) { +VertexAdaptor GenTree::get_lambda_function(const PhpDocComment* phpdoc, FunctionModifiers modifiers) { auto v_op_function_lambda = get_function(true, phpdoc, modifiers); - CE (v_op_function_lambda); + CE(v_op_function_lambda); cur_function->has_lambdas_inside = true; @@ -1413,26 +1408,26 @@ ClassMemberModifiers GenTree::parse_class_member_modifier_mask() { auto modifiers = ClassMemberModifiers::nonmember(); while (cur != end) { switch (cur->type()) { - case tok_public: - modifiers.set_public(); - break; - case tok_private: - modifiers.set_private(); - break; - case tok_protected: - modifiers.set_protected(); - break; - case tok_static: - modifiers.set_static(); - break; - case tok_final: - modifiers.set_final(); - break; - case tok_abstract: - modifiers.set_abstract(); - break; - default: - return modifiers; + case tok_public: + modifiers.set_public(); + break; + case tok_private: + modifiers.set_private(); + break; + case tok_protected: + modifiers.set_protected(); + break; + case tok_static: + modifiers.set_static(); + break; + case tok_final: + modifiers.set_final(); + break; + case tok_abstract: + modifiers.set_abstract(); + break; + default: + return modifiers; } next_cur(); } @@ -1455,7 +1450,7 @@ std::string GenTree::get_identifier() { return static_cast(std::prev(cur)->str_val); } -VertexPtr GenTree::get_class_member(const PhpDocComment *phpdoc) { +VertexPtr GenTree::get_class_member(const PhpDocComment* phpdoc) { auto modifiers = parse_class_member_modifier_mask(); if (!modifiers.is_static()) { modifiers.set_instance(); @@ -1470,7 +1465,7 @@ VertexPtr GenTree::get_class_member(const PhpDocComment *phpdoc) { return {}; } - const TypeHint *type_hint = get_typehint(); + const TypeHint* type_hint = get_typehint(); if (test_expect(tok_var_name)) { kphp_error(!cur_class->is_interface(), "Interfaces may not include member variables"); @@ -1492,7 +1487,7 @@ VertexAdaptor GenTree::parse_cur_function_param_list() { CE(expect(tok_oppar, "'('")); - if (cur_function->modifiers.is_instance()) { // add implicit $this + if (cur_function->modifiers.is_instance()) { // add implicit $this params_next.emplace_back(ClassData::gen_param_this(auto_location())); } @@ -1513,7 +1508,7 @@ VertexAdaptor GenTree::parse_cur_function_param_list() { return VertexAdaptor::create(params_next).set_location(cur_function->root); } -VertexAdaptor GenTree::get_function(bool is_lambda, const PhpDocComment *phpdoc, FunctionModifiers modifiers) { +VertexAdaptor GenTree::get_function(bool is_lambda, const PhpDocComment* phpdoc, FunctionModifiers modifiers) { bool is_arrow = test_expect(tok_fn); CE(expect2(tok_fn, tok_function, "function")); auto func_location = auto_location(); @@ -1546,7 +1541,9 @@ VertexAdaptor GenTree::get_function(bool is_lambda, const PhpDocCom } auto func_root = VertexAdaptor::create(VertexAdaptor::create(), VertexAdaptor::create()).set_location(func_location); - FunctionData::func_type_t func_type = is_lambda ? FunctionData::func_lambda : processing_file->is_builtin() ? FunctionData::func_extern : FunctionData::func_local; + FunctionData::func_type_t func_type = is_lambda ? FunctionData::func_lambda + : processing_file->is_builtin() ? FunctionData::func_extern + : FunctionData::func_local; StackPushPop f_alive(functions_stack, cur_function, FunctionData::create_function(func_name, func_root, func_type)); cur_function->phpdoc = phpdoc; @@ -1574,7 +1571,7 @@ VertexAdaptor GenTree::get_function(bool is_lambda, const PhpDocCom "arguments and captured variables (in `use` clause) must have different names"); } - if (test_expect(tok_colon) || test_expect(tok_triple_colon)) { // function.txt allows ::: besides : + if (test_expect(tok_colon) || test_expect(tok_triple_colon)) { // function.txt allows ::: besides : next_cur(); cur_function->return_typehint = get_typehint(); kphp_error(cur_function->return_typehint, "Expected return typehint after :"); @@ -1587,9 +1584,9 @@ VertexAdaptor GenTree::get_function(bool is_lambda, const PhpDocCom } if (is_arrow) { - CE (expect(tok_double_arrow, "'=>'")); + CE(expect(tok_double_arrow, "'=>'")); auto body_expr = get_expression(); - CE (!kphp_error(body_expr, "Bad expression in arrow function body")); + CE(!kphp_error(body_expr, "Bad expression in arrow function body")); auto return_stmt = VertexAdaptor::create(body_expr).set_location(func_location); cur_function->root->cmd_ref() = VertexAdaptor::create(return_stmt).set_location(func_location); auto_capture_vars_from_body_in_arrow_lambda(cur_function); @@ -1605,7 +1602,7 @@ VertexAdaptor GenTree::get_function(bool is_lambda, const PhpDocCom } } else { CE(!kphp_error(cur_function->modifiers.is_abstract() || processing_file->is_builtin(), "function must have non-empty body")); - CE (expect(tok_semicolon, "';'")); + CE(expect(tok_semicolon, "';'")); cur_function->root->cmd_ref() = VertexAdaptor::create(); } @@ -1613,11 +1610,8 @@ VertexAdaptor GenTree::get_function(bool is_lambda, const PhpDocCom // the constructor is registered later, after the entire class is parsed if (!cur_function->is_constructor()) { bool kphp_required_flag = phpdoc && phpdoc->has_tag(PhpDocType::kphp_required, PhpDocType::kphp_lib_export); - bool auto_require = cur_function->is_extern() - || cur_function->modifiers.is_abstract() - || cur_function->modifiers.is_instance() - || cur_function->is_lambda() - || kphp_required_flag; + bool auto_require = cur_function->is_extern() || cur_function->modifiers.is_abstract() || cur_function->modifiers.is_instance() || + cur_function->is_lambda() || kphp_required_flag; G->register_and_require_function(cur_function, parsed_os, auto_require); } @@ -1626,32 +1620,32 @@ VertexAdaptor GenTree::get_function(bool is_lambda, const PhpDocCom bool GenTree::check_seq_end() { if (!test_expect(tok_clbrc)) { - kphp_error (0, "Failed to parse sequence"); + kphp_error(0, "Failed to parse sequence"); while (cur != end && !test_expect(tok_clbrc)) { next_cur(); } } - return expect (tok_clbrc, "'}'"); + return expect(tok_clbrc, "'}'"); } bool GenTree::check_statement_end() { - //if (test_expect (tok_clbrc)) { - //return true; - //} + // if (test_expect (tok_clbrc)) { + // return true; + // } if (!test_expect(tok_semicolon)) { stage::set_line(line_num); - kphp_error (0, "Failed to parse statement. Expected `;`"); + kphp_error(0, "Failed to parse statement. Expected `;`"); while (cur != end && !test_expect(tok_clbrc) && !test_expect(tok_semicolon)) { next_cur(); } } - return expect (tok_semicolon, "';'"); + return expect(tok_semicolon, "';'"); } void GenTree::parse_extends_implements() { - if (test_expect(tok_extends)) { // extends comes before 'implements', the order is fixed + if (test_expect(tok_extends)) { // extends comes before 'implements', the order is fixed do { - next_cur(); // (same as in PHP) + next_cur(); // (same as in PHP) kphp_error_return(test_expect(tok_func_name), "Class name expected after 'extends'"); kphp_error(!cur_class->is_trait(), "Traits may not extend each other"); cur_class->add_str_dependent(cur_function, cur_class->class_type, cur->str_val); @@ -1669,7 +1663,7 @@ void GenTree::parse_extends_implements() { } } -VertexPtr GenTree::get_class(const PhpDocComment *phpdoc, ClassType class_type) { +VertexPtr GenTree::get_class(const PhpDocComment* phpdoc, ClassType class_type) { ClassModifiers modifiers; if (test_expect(tok_abstract)) { modifiers.set_abstract(); @@ -1685,7 +1679,7 @@ VertexPtr GenTree::get_class(const PhpDocComment *phpdoc, ClassType class_type) CE(vk::any_of_equal(cur->type(), tok_class, tok_interface, tok_trait)); next_cur(); - CE (!kphp_error(test_expect(tok_func_name), "Class name expected")); + CE(!kphp_error(test_expect(tok_func_name), "Class name expected")); auto name_str = cur->str_val; next_cur(); @@ -1720,7 +1714,7 @@ VertexPtr GenTree::get_class(const PhpDocComment *phpdoc, ClassType class_type) name_vertex->str_val = static_cast(name_str); cur_class->file_id = processing_file; - cur_class->set_name_and_src_name(full_class_name); // with full namespaces and slashes + cur_class->set_name_and_src_name(full_class_name); // with full namespaces and slashes cur_class->phpdoc = phpdoc; cur_class->is_immutable = phpdoc && phpdoc->has_tag(PhpDocType::kphp_immutable_class); cur_class->need_generated_stub = phpdoc && phpdoc->has_tag(PhpDocType::kphp_generated_stub_class); @@ -1732,8 +1726,8 @@ VertexPtr GenTree::get_class(const PhpDocComment *phpdoc, ClassType class_type) ++G->stats.total_classes; } - VertexPtr body_vertex = get_statement(); // an empty op_seq - CE (!kphp_error(body_vertex, "Failed to parse class body")); + VertexPtr body_vertex = get_statement(); // an empty op_seq + CE(!kphp_error(body_vertex, "Failed to parse class body")); cur_class->add_class_constant(); // A::class @@ -1743,14 +1737,14 @@ VertexPtr GenTree::get_class(const PhpDocComment *phpdoc, ClassType class_type) } if (registered) { - G->register_and_require_function(cur_function, parsed_os, true); // push the class down the pipeline + G->register_and_require_function(cur_function, parsed_os, true); // push the class down the pipeline } return {}; } - -VertexAdaptor GenTree::gen_constructor_call_with_args(const std::string &allocated_class_name, std::vector args, const Location &location) { +VertexAdaptor GenTree::gen_constructor_call_with_args(const std::string& allocated_class_name, std::vector args, + const Location& location) { auto alloc = VertexAdaptor::create().set_location(location); alloc->allocated_class_name = allocated_class_name; auto constructor_call = VertexAdaptor::create(alloc, std::move(args)).set_location(location); @@ -1760,7 +1754,7 @@ VertexAdaptor GenTree::gen_constructor_call_with_args(const std::s return constructor_call; } -VertexAdaptor GenTree::gen_constructor_call_with_args(ClassPtr allocated_class, std::vector args, const Location &location) { +VertexAdaptor GenTree::gen_constructor_call_with_args(ClassPtr allocated_class, std::vector args, const Location& location) { auto res_func_call = gen_constructor_call_with_args(allocated_class->name, std::move(args), location); res_func_call->args()[0].as()->allocated_class = allocated_class; res_func_call->func_id = allocated_class->construct_function; @@ -1776,7 +1770,7 @@ VertexAdaptor GenTree::auto_capture_this_in_lambda(FunctionPtr f_lambda) kphp_assert(f_lambda->is_lambda()); // bubble up $this through all nested lambdas upwards while (f_lambda->is_lambda()) { - G->operate_on_function_locking(f_lambda->name, [v_captured_this](FunctionPtr &f_lambda) { + G->operate_on_function_locking(f_lambda->name, [v_captured_this](FunctionPtr& f_lambda) { if (f_lambda->uses_list.empty() || f_lambda->uses_list.front()->extra_type != op_ex_var_this) { f_lambda->uses_list.emplace_front(v_captured_this); } @@ -1801,7 +1795,7 @@ VertexPtr GenTree::process_arrow(VertexPtr lhs, VertexPtr rhs) { return new_root; } else { - kphp_error (false, "Operator '->' expects property or function call as its right operand"); + kphp_error(false, "Operator '->' expects property or function call as its right operand"); return {}; } } @@ -1809,7 +1803,7 @@ VertexPtr GenTree::process_arrow(VertexPtr lhs, VertexPtr rhs) { void GenTree::get_traits_uses() { next_cur(); auto name = cur->str_val; - if (!expect(tok_func_name, "trait name expected")|| !expect(tok_semicolon, "`;` expected")) { + if (!expect(tok_func_name, "trait name expected") || !expect(tok_semicolon, "`;` expected")) { return; } @@ -1850,11 +1844,11 @@ void GenTree::get_use() { } void GenTree::parse_namespace_and_uses_at_top_of_file() { - kphp_assert (test_expect(tok_namespace)); - kphp_assert (processing_file->namespace_name.empty()); + kphp_assert(test_expect(tok_namespace)); + kphp_assert(processing_file->namespace_name.empty()); next_cur(); - kphp_error (test_expect(tok_func_name), "Namespace name expected"); + kphp_error(test_expect(tok_func_name), "Namespace name expected"); processing_file->namespace_name = static_cast(cur->str_val); std::string real_relative_dir = processing_file->relative_dir_name; if (processing_file->owner_lib) { @@ -1864,11 +1858,11 @@ void GenTree::parse_namespace_and_uses_at_top_of_file() { real_relative_dir.erase(0, lib_unified_dir.size() + 1); } // to properly handle the vendor/ folder, assert from below is commented-out - //string expected_namespace_name = replace_characters(real_unified_dir, '/', '\\'); - //kphp_error (processing_file->namespace_name == expected_namespace_name, fmt_format("Wrong namespace name, expected {}", expected_namespace_name)); + // string expected_namespace_name = replace_characters(real_unified_dir, '/', '\\'); + // kphp_error (processing_file->namespace_name == expected_namespace_name, fmt_format("Wrong namespace name, expected {}", expected_namespace_name)); next_cur(); - expect (tok_semicolon, "';'"); + expect(tok_semicolon, "';'"); if (stage::has_error()) { while (cur != end) { @@ -1928,34 +1922,34 @@ void GenTree::parse_declare_at_top_of_file() { expect(tok_semicolon, ";"); } -VertexAdaptor GenTree::get_static_field_list(const PhpDocComment *phpdoc, FieldModifiers modifiers, const TypeHint *type_hint) { - cur--; // it was a $field_name; we do it before the get_multi_call() as it does next_cur() by itself +VertexAdaptor GenTree::get_static_field_list(const PhpDocComment* phpdoc, FieldModifiers modifiers, const TypeHint* type_hint) { + cur--; // it was a $field_name; we do it before the get_multi_call() as it does next_cur() by itself VertexAdaptor v = get_multi_call(&GenTree::get_expression); - CE (check_statement_end()); + CE(check_statement_end()); - for (auto seq: v->args()) { + for (auto seq : v->args()) { // node is a op_var $a (if there is no default value) or op_set(op_var $a, init_val) VertexPtr node = seq.as()->args()[0]; switch (node->type()) { - case op_var: { - cur_class->members.add_static_field(node.as(), VertexPtr{}, modifiers, phpdoc, type_hint); - break; - } - case op_set: { - auto set_expr = node.as(); - kphp_error_act(set_expr->lhs()->type() == op_var, "unexpected expression in 'static'", break); - cur_class->members.add_static_field(set_expr->lhs().as(), set_expr->rhs(), modifiers, phpdoc, type_hint); - break; - } - default: - kphp_error(0, "unexpected expression in 'static'"); + case op_var: { + cur_class->members.add_static_field(node.as(), VertexPtr{}, modifiers, phpdoc, type_hint); + break; + } + case op_set: { + auto set_expr = node.as(); + kphp_error_act(set_expr->lhs()->type() == op_var, "unexpected expression in 'static'", break); + cur_class->members.add_static_field(set_expr->lhs().as(), set_expr->rhs(), modifiers, phpdoc, type_hint); + break; + } + default: + kphp_error(0, "unexpected expression in 'static'"); } } return VertexAdaptor::create(); } -const TypeHint *GenTree::get_typehint() { +const TypeHint* GenTree::get_typehint() { // optimization: don't start the lexer if it's 100% not a type hint here (so it wouldn't be parsed, and it's okay) // without this, everything still works, just a bit slower if (vk::any_of_equal(cur->type(), TokenType::tok_var_name, TokenType::tok_clpar, TokenType::tok_and, TokenType::tok_varg)) { @@ -1965,24 +1959,24 @@ const TypeHint *GenTree::get_typehint() { try { PhpDocTypeHintParser parser(cur_function, cur_function->get_this_or_topmost_if_lambda()->genericTs); return parser.parse_from_tokens(cur); - } catch (std::runtime_error &) { + } catch (std::runtime_error&) { kphp_error(0, "Cannot parse type hint"); return {}; } } // parse a php comment like /**/ or /**/ which expresses manual types for generic instantiation -GenericsInstantiationPhpComment *GenTree::parse_php_commentTs(vk::string_view str_commentTs) { +GenericsInstantiationPhpComment* GenTree::parse_php_commentTs(vk::string_view str_commentTs) { PhpDocTypeHintParser parser(cur_function, cur_function->get_this_or_topmost_if_lambda()->genericTs); std::vector doc_tokens = phpdoc_to_tokens(str_commentTs); - std::vector vectorTs; + std::vector vectorTs; auto cur_tok = doc_tokens.cbegin(); while (cur_tok != doc_tokens.cend() && cur_tok->type() != tok_end) { - const TypeHint *instantiationT = nullptr; + const TypeHint* instantiationT = nullptr; try { instantiationT = parser.parse_from_tokens(cur_tok); - } catch (std::runtime_error &ex) { + } catch (std::runtime_error& ex) { kphp_error_act(0, fmt_format("Could not parse generic instantiation comment: {}", ex.what()), return nullptr); } @@ -1995,17 +1989,17 @@ GenericsInstantiationPhpComment *GenTree::parse_php_commentTs(vk::string_view st } VertexAdaptor GenTree::get_catch() { - CE (expect(tok_catch, "'catch'")); - CE (expect(tok_oppar, "'('")); + CE(expect(tok_catch, "'catch'")); + CE(expect(tok_oppar, "'('")); auto exception_class = cur->str_val; - CE (expect(tok_func_name, "type that implements Throwable")); + CE(expect(tok_func_name, "type that implements Throwable")); auto exception_var_name = get_expression(); - CE (!kphp_error(exception_var_name, "Cannot parse catch")); - CE (!kphp_error(exception_var_name->type() == op_var, "Expected variable name in 'catch'")); + CE(!kphp_error(exception_var_name, "Cannot parse catch")); + CE(!kphp_error(exception_var_name->type() == op_var, "Expected variable name in 'catch'")); - CE (expect(tok_clpar, "')'")); + CE(expect(tok_clpar, "')'")); auto catch_body = get_statement(); - CE (!kphp_error(catch_body, "Cannot parse catch block")); + CE(!kphp_error(catch_body, "Cannot parse catch block")); auto catch_op = VertexAdaptor::create(exception_var_name.as(), VertexUtil::embrace(catch_body)); catch_op->type_declaration = resolve_uses(cur_function, static_cast(exception_class)); @@ -2013,238 +2007,240 @@ VertexAdaptor GenTree::get_catch() { return catch_op; } -VertexPtr GenTree::get_statement(const PhpDocComment *phpdoc) { +VertexPtr GenTree::get_statement(const PhpDocComment* phpdoc) { TokenType type = cur->type(); is_top_of_the_function_ &= vk::any_of_equal(type, tok_global, tok_opbrc); switch (type) { - case tok_opbrc: { - next_cur(); - auto res = get_seq(); - kphp_error (res, "Failed to parse sequence"); - CE (check_seq_end()); - return res; - } - case tok_return: - return get_return(); - case tok_continue: - return get_break_or_continue(); - case tok_break: - return get_break_or_continue(); - case tok_unset: { - auto res = get_multi_call(&GenTree::get_expression, true); - CE (check_statement_end()); - if (res->size() == 1) { - return res->args()[0]; - } - return res; + case tok_opbrc: { + next_cur(); + auto res = get_seq(); + kphp_error(res, "Failed to parse sequence"); + CE(check_seq_end()); + return res; + } + case tok_return: + return get_return(); + case tok_continue: + return get_break_or_continue(); + case tok_break: + return get_break_or_continue(); + case tok_unset: { + auto res = get_multi_call(&GenTree::get_expression, true); + CE(check_statement_end()); + if (res->size() == 1) { + return res->args()[0]; } - case tok_var_dump: { - auto res = get_multi_call(&GenTree::get_expression, true); - CE (res && check_statement_end()); - for (VertexPtr x : res->args()) { - x.as()->str_val = "var_dump"; - } - if (res->size() == 1) { - return res->args()[0]; - } - return res; + return res; + } + case tok_var_dump: { + auto res = get_multi_call(&GenTree::get_expression, true); + CE(res && check_statement_end()); + for (VertexPtr x : res->args()) { + x.as()->str_val = "var_dump"; } - case tok_define: { - auto res = get_func_call(); - CE (check_statement_end()); - return res; + if (res->size() == 1) { + return res->args()[0]; } - case tok_global: { - if (G->settings().warnings_level.get() >= 2 && cur_function && cur_function->type == FunctionData::func_local && !is_top_of_the_function_) { - kphp_warning("`global` keyword is allowed only at the top of the function"); - } - auto res = get_multi_call(&GenTree::get_var_name); - CE (check_statement_end()); - return res; + return res; + } + case tok_define: { + auto res = get_func_call(); + CE(check_statement_end()); + return res; + } + case tok_global: { + if (G->settings().warnings_level.get() >= 2 && cur_function && cur_function->type == FunctionData::func_local && !is_top_of_the_function_) { + kphp_warning("`global` keyword is allowed only at the top of the function"); } - case tok_protected: - case tok_public: - case tok_private: - if (std::next(cur, 1)->type() == tok_const) { - next_cur(); - - auto access = AccessModifiers::public_; - if (type == tok_protected) { - access = AccessModifiers::protected_; - } else if (type == tok_private) { - access = AccessModifiers::private_; - } - return get_const_after_explicit_access_modifier(access); - } - // fall through - case tok_final: - case tok_abstract: - if (cur_function->type == FunctionData::func_class_holder) { - return get_class_member(phpdoc); - } else if (vk::any_of_equal(cur->type(), tok_final, tok_abstract)) { - return get_class(phpdoc, ClassType::klass); - } + auto res = get_multi_call(&GenTree::get_var_name); + CE(check_statement_end()); + return res; + } + case tok_protected: + case tok_public: + case tok_private: + if (std::next(cur, 1)->type() == tok_const) { next_cur(); - kphp_error(0, "Unexpected access modifier outside of class body"); - return {}; - case tok_static: { - if (cur_function->type == FunctionData::func_class_holder) { - return get_class_member(phpdoc); - } - if (cur + 1 != end && ((cur + 1)->type() == tok_var_name)) { // a function-scoped static variable - auto res = get_multi_call(&GenTree::get_expression); - CE (check_statement_end()); - return res; + + auto access = AccessModifiers::public_; + if (type == tok_protected) { + access = AccessModifiers::protected_; + } else if (type == tok_private) { + access = AccessModifiers::private_; } - next_cur(); - kphp_error(0, "Expected function or variable after keyword `static`"); - return {}; + return get_const_after_explicit_access_modifier(access); + } + // fall through + case tok_final: + case tok_abstract: + if (cur_function->type == FunctionData::func_class_holder) { + return get_class_member(phpdoc); + } else if (vk::any_of_equal(cur->type(), tok_final, tok_abstract)) { + return get_class(phpdoc, ClassType::klass); } - case tok_echo: { - auto res = get_multi_call(&GenTree::get_expression); - for (VertexPtr x : res->args()) { - x.as()->str_val = "echo"; - } - CE (check_statement_end()); - return res; + next_cur(); + kphp_error(0, "Unexpected access modifier outside of class body"); + return {}; + case tok_static: { + if (cur_function->type == FunctionData::func_class_holder) { + return get_class_member(phpdoc); } - case tok_dbg_echo: { - auto res = get_multi_call(&GenTree::get_expression); - for (VertexPtr x : res->args()) { - x.as()->str_val = "dbg_echo"; - } - CE (check_statement_end()); + if (cur + 1 != end && ((cur + 1)->type() == tok_var_name)) { // a function-scoped static variable + auto res = get_multi_call(&GenTree::get_expression); + CE(check_statement_end()); return res; } - case tok_throw: { - auto location = auto_location(); + next_cur(); + kphp_error(0, "Expected function or variable after keyword `static`"); + return {}; + } + case tok_echo: { + auto res = get_multi_call(&GenTree::get_expression); + for (VertexPtr x : res->args()) { + x.as()->str_val = "echo"; + } + CE(check_statement_end()); + return res; + } + case tok_dbg_echo: { + auto res = get_multi_call(&GenTree::get_expression); + for (VertexPtr x : res->args()) { + x.as()->str_val = "dbg_echo"; + } + CE(check_statement_end()); + return res; + } + case tok_throw: { + auto location = auto_location(); + next_cur(); + auto throw_expr = get_expression(); + CE(!kphp_error(throw_expr, "Empty expression in throw")); + auto throw_vertex = VertexAdaptor::create(throw_expr).set_location(location); + CE(check_statement_end()); + return throw_vertex; + } + + case tok_while: + return get_while(); + case tok_if: + return get_if(); + case tok_for: + return get_for(); + case tok_do: + return get_do(); + case tok_foreach: + return get_foreach(); + case tok_switch: + return get_switch(); + case tok_phpdoc: { // enter /** ... */ + // phpdoc above a function/class/field + auto next = (cur + 1)->type(); + if (vk::any_of_equal(next, tok_class, tok_interface, tok_trait, tok_function, tok_public, tok_private, tok_protected, tok_final, tok_abstract, tok_var, + tok_const) || + (next == tok_static && cur_function->type == FunctionData::func_class_holder)) { + vk::string_view phpdoc_str = cur->str_val; next_cur(); - auto throw_expr = get_expression(); - CE (!kphp_error(throw_expr, "Empty expression in throw")); - auto throw_vertex = VertexAdaptor::create(throw_expr).set_location(location); - CE (check_statement_end()); - return throw_vertex; - } - - case tok_while: - return get_while(); - case tok_if: - return get_if(); - case tok_for: - return get_for(); - case tok_do: - return get_do(); - case tok_foreach: - return get_foreach(); - case tok_switch: - return get_switch(); - case tok_phpdoc: { // enter /** ... */ - // phpdoc above a function/class/field - auto next = (cur+1)->type(); - if (vk::any_of_equal(next, tok_class, tok_interface, tok_trait, tok_function, tok_public, tok_private, tok_protected, tok_final, tok_abstract, tok_var, tok_const) - || (next == tok_static && cur_function->type == FunctionData::func_class_holder)) { - vk::string_view phpdoc_str = cur->str_val; + return get_statement(new PhpDocComment(phpdoc_str)); + } + // phpdoc above a lambda before assignment: /** ... */ $f = function() { ... }; + // we do not support complex expressions on the left-hand side (like $f[0] = fn) + // todo reconsider this when I'll rewrite phpdoc parsing + if (cur + 5 < tokens.end() && next == tok_var_name && (cur + 2)->type() == tok_eq1 && + vk::any_of_equal((cur + 3)->type(), tok_function, tok_fn, tok_static)) { + vk::string_view phpdoc_str = cur->str_val; + if (phpdoc_str.find("@var") == std::string::npos) { // if it's not @var for $f, but @param for lambda next_cur(); - return get_statement(new PhpDocComment(phpdoc_str)); - } - // phpdoc above a lambda before assignment: /** ... */ $f = function() { ... }; - // we do not support complex expressions on the left-hand side (like $f[0] = fn) - // todo reconsider this when I'll rewrite phpdoc parsing - if (cur+5 < tokens.end() && next == tok_var_name && (cur+2)->type() == tok_eq1 && vk::any_of_equal((cur+3)->type(), tok_function, tok_fn, tok_static)) { - vk::string_view phpdoc_str = cur->str_val; - if (phpdoc_str.find("@var") == std::string::npos) { // if it's not @var for $f, but @param for lambda - next_cur(); - auto lhs = get_expr_top(false); - next_cur(); - auto rhs = get_expr_top(false, new PhpDocComment(phpdoc_str)); - return rhs ? VertexPtr(VertexAdaptor::create(lhs, rhs)) : rhs; - } + auto lhs = get_expr_top(false); + next_cur(); + auto rhs = get_expr_top(false, new PhpDocComment(phpdoc_str)); + return rhs ? VertexPtr(VertexAdaptor::create(lhs, rhs)) : rhs; } - // otherwise it's a phpdoc-statement: it may contain @var which will be used for assumptions and tinf - return get_phpdoc_inside_function(); } - case tok_function: - if (cur_class) { // no access modifier implies 'public' - get_class_member(phpdoc); - } else { - get_function(false, phpdoc, FunctionModifiers::nonmember()); - } - return {}; + // otherwise it's a phpdoc-statement: it may contain @var which will be used for assumptions and tinf + return get_phpdoc_inside_function(); + } + case tok_function: + if (cur_class) { // no access modifier implies 'public' + get_class_member(phpdoc); + } else { + get_function(false, phpdoc, FunctionModifiers::nonmember()); + } + return {}; - case tok_try: { - auto location = auto_location(); - next_cur(); - auto try_body = get_statement(); - CE (!kphp_error(try_body, "Cannot parse try block")); - - std::vector catch_list; - while (test_expect(tok_catch)) { - auto catch_op = get_catch(); - CE (!kphp_error(catch_op, "Cannot parse catch statement")); - catch_op.set_location(location); - catch_list.emplace_back(catch_op); - } - CE (!kphp_error(!catch_list.empty(), "Expected at least 1 'catch' statement")); + case tok_try: { + auto location = auto_location(); + next_cur(); + auto try_body = get_statement(); + CE(!kphp_error(try_body, "Cannot parse try block")); - return VertexAdaptor::create(VertexUtil::embrace(try_body), std::move(catch_list)).set_location(location); + std::vector catch_list; + while (test_expect(tok_catch)) { + auto catch_op = get_catch(); + CE(!kphp_error(catch_op, "Cannot parse catch statement")); + catch_op.set_location(location); + catch_list.emplace_back(catch_op); } - case tok_inline_html: { - auto html_code = VertexAdaptor::create().set_location(auto_location()); - html_code->str_val = static_cast(cur->str_val); + CE(!kphp_error(!catch_list.empty(), "Expected at least 1 'catch' statement")); - auto echo_cmd = VertexAdaptor::create(html_code).set_location(auto_location()); - echo_cmd->str_val = "print"; - next_cur(); - return echo_cmd; - } - case tok_at: { - auto location = auto_location(); - next_cur(); - auto expression = get_statement(); - CE (expression); - return VertexAdaptor::create(expression).set_location(location); - } - case tok_clbrc: { - return {}; - } - case tok_const: { - return get_const(AccessModifiers::public_); - } - case tok_use: { - if (cur_class) { - get_traits_uses(); - } else { - kphp_error(cur_function && cur_function->is_main_function(), "'use' can be declared only in global scope"); - get_use(); - } - return VertexAdaptor::create(); - } - case tok_var: { - next_cur(); - get_instance_var_list(phpdoc, FieldModifiers{}.set_public(), get_typehint()); - CE (check_statement_end()); - auto empty = VertexAdaptor::create(); - return empty; - } - case tok_class: - return get_class(phpdoc, ClassType::klass); - case tok_interface: - return get_class(phpdoc, ClassType::interface); - case tok_trait: { - auto res = get_class(phpdoc, ClassType::trait); - kphp_error(processing_file->namespace_uses.empty(), "Usage of operator `use`(Aliasing/Importing) with traits is temporarily prohibited"); - return res; + return VertexAdaptor::create(VertexUtil::embrace(try_body), std::move(catch_list)).set_location(location); + } + case tok_inline_html: { + auto html_code = VertexAdaptor::create().set_location(auto_location()); + html_code->str_val = static_cast(cur->str_val); + + auto echo_cmd = VertexAdaptor::create(html_code).set_location(auto_location()); + echo_cmd->str_val = "print"; + next_cur(); + return echo_cmd; + } + case tok_at: { + auto location = auto_location(); + next_cur(); + auto expression = get_statement(); + CE(expression); + return VertexAdaptor::create(expression).set_location(location); + } + case tok_clbrc: { + return {}; + } + case tok_const: { + return get_const(AccessModifiers::public_); + } + case tok_use: { + if (cur_class) { + get_traits_uses(); + } else { + kphp_error(cur_function && cur_function->is_main_function(), "'use' can be declared only in global scope"); + get_use(); } - default: { - auto res = get_expression(); - CE (check_statement_end()); - if (!res) { - res = VertexAdaptor::create().set_location(auto_location()); - } - return res; + return VertexAdaptor::create(); + } + case tok_var: { + next_cur(); + get_instance_var_list(phpdoc, FieldModifiers{}.set_public(), get_typehint()); + CE(check_statement_end()); + auto empty = VertexAdaptor::create(); + return empty; + } + case tok_class: + return get_class(phpdoc, ClassType::klass); + case tok_interface: + return get_class(phpdoc, ClassType::interface); + case tok_trait: { + auto res = get_class(phpdoc, ClassType::trait); + kphp_error(processing_file->namespace_uses.empty(), "Usage of operator `use`(Aliasing/Importing) with traits is temporarily prohibited"); + return res; + } + default: { + auto res = get_expression(); + CE(check_statement_end()); + if (!res) { + res = VertexAdaptor::create().set_location(auto_location()); } + return res; + } } kphp_fail(); } @@ -2265,14 +2261,14 @@ VertexPtr GenTree::get_const(AccessModifiers access) { bool const_in_global_scope = functions_stack.size() == 1 && !cur_class; bool const_in_class = !!cur_class; - CE (!kphp_error(const_in_global_scope || const_in_class, "const expressions supported only inside classes and namespaces or in global scope")); + CE(!kphp_error(const_in_global_scope || const_in_class, "const expressions supported only inside classes and namespaces or in global scope")); std::string const_name = get_identifier(); - CE (!const_name.empty()); + CE(!const_name.empty()); kphp_error(const_name != "class", "A class constant must not be called 'class'; it is reserved for class name fetching"); - CE (expect(tok_eq1, "'='")); + CE(expect(tok_eq1, "'='")); VertexPtr v = get_expression(); - CE (check_statement_end()); + CE(check_statement_end()); if (const_in_class) { cur_class->members.add_constant(const_name, v, access); @@ -2284,7 +2280,7 @@ VertexPtr GenTree::get_const(AccessModifiers access) { return VertexAdaptor::create(name, v).set_location(location); } -void GenTree::get_instance_var_list(const PhpDocComment *phpdoc, FieldModifiers modifiers, const TypeHint *type_hint) { +void GenTree::get_instance_var_list(const PhpDocComment* phpdoc, FieldModifiers modifiers, const TypeHint* type_hint) { kphp_error(cur_class, "var declaration is outside of class"); vk::string_view var_name = cur->str_val; @@ -2309,7 +2305,7 @@ void GenTree::get_instance_var_list(const PhpDocComment *phpdoc, FieldModifiers } } -void GenTree::get_seq(std::vector &seq_next) { +void GenTree::get_seq(std::vector& seq_next) { while (cur != end && !test_expect(tok_clbrc)) { if (auto cur_node = get_statement()) { seq_next.push_back(cur_node); @@ -2330,7 +2326,8 @@ void GenTree::run() { auto v_func_params = VertexAdaptor::create(); auto root = VertexAdaptor::create(v_func_params, VertexAdaptor{}).set_location(auto_location()); - StackPushPop f_alive(functions_stack, cur_function, FunctionData::create_function(processing_file->main_func_name, root, FunctionData::func_main)); + StackPushPop f_alive(functions_stack, cur_function, + FunctionData::create_function(processing_file->main_func_name, root, FunctionData::func_main)); processing_file->main_function = cur_function; parse_declare_at_top_of_file(); @@ -2350,7 +2347,7 @@ void GenTree::run() { seq_next.push_back(VertexAdaptor::create(VertexAdaptor::create())); cur_function->root->cmd_ref() = VertexAdaptor::create(seq_next).set_location(location); - G->register_and_require_function(cur_function, parsed_os, true); // global function — therefore required + G->register_and_require_function(cur_function, parsed_os, true); // global function — therefore required if (processing_file->file_name == G->settings().functions_file.get()) { G->set_functions_txt_parsed(); @@ -2358,17 +2355,14 @@ void GenTree::run() { if (cur != end) { fmt_fprintf(stderr, "line {}: something wrong\n", line_num); - kphp_error (0, "Cannot compile (probably problems with brace balance)"); + kphp_error(0, "Cannot compile (probably problems with brace balance)"); } } -bool GenTree::is_magic_method_name_allowed(const std::string &name) { +bool GenTree::is_magic_method_name_allowed(const std::string& name) { static std::set names = { - ClassData::NAME_OF_CONSTRUCT, - ClassData::NAME_OF_CLONE, - ClassData::NAME_OF_TO_STRING, - ClassData::NAME_OF_WAKEUP, - // other __-staring methods like __invoke/_self$ are implicitly generated and aren't allowed to occur in php + ClassData::NAME_OF_CONSTRUCT, ClassData::NAME_OF_CLONE, ClassData::NAME_OF_TO_STRING, ClassData::NAME_OF_WAKEUP, + // other __-staring methods like __invoke/_self$ are implicitly generated and aren't allowed to occur in php }; return vk::contains(names, name); diff --git a/compiler/gentree.h b/compiler/gentree.h index 31e5fe6314..0d13897cc9 100644 --- a/compiler/gentree.h +++ b/compiler/gentree.h @@ -20,13 +20,13 @@ class GenTree { template class StackPushPop { - std::vector &stack; - T &top_element; + std::vector& stack; + T& top_element; public: - StackPushPop(std::vector &stack, T &top_element, T elem_to_push) : - stack(stack), - top_element(top_element) { + StackPushPop(std::vector& stack, T& top_element, T elem_to_push) + : stack(stack), + top_element(top_element) { stack.emplace_back(elem_to_push); top_element = elem_to_push; } @@ -38,14 +38,17 @@ class GenTree { }; public: - Location auto_location() const { return Location{this->line_num}; } + Location auto_location() const { + return Location{this->line_num}; + } - static bool is_magic_method_name_allowed(const std::string &name); + static bool is_magic_method_name_allowed(const std::string& name); + GenTree(std::vector tokens, SrcFilePtr file, DataStream& os); - GenTree(std::vector tokens, SrcFilePtr file, DataStream &os); - - bool test_expect(TokenType tp) { return cur->type() == tp; } + bool test_expect(TokenType tp) { + return cur->type() == tp; + } void next_cur(); int open_parent(); @@ -58,18 +61,18 @@ class GenTree { VertexAdaptor get_func_param(); VertexAdaptor get_var_name(); VertexAdaptor get_var_name_ref(); - VertexPtr get_expr_top(bool was_arrow, const PhpDocComment *phpdoc = nullptr); + VertexPtr get_expr_top(bool was_arrow, const PhpDocComment* phpdoc = nullptr); VertexPtr get_postfix_expression(VertexPtr res, bool parenthesized); VertexPtr get_unary_op(int op_priority_cur, Operation unary_op_tp, bool till_ternary); VertexPtr get_binary_op(int op_priority_cur, bool till_ternary); VertexPtr get_expression_impl(bool till_ternary); VertexPtr get_expression(); - VertexPtr get_statement(const PhpDocComment *phpdoc = nullptr); + VertexPtr get_statement(const PhpDocComment* phpdoc = nullptr); VertexAdaptor get_catch(); - void get_instance_var_list(const PhpDocComment *phpdoc, FieldModifiers modifiers, const TypeHint *type_hint); + void get_instance_var_list(const PhpDocComment* phpdoc, FieldModifiers modifiers, const TypeHint* type_hint); void get_traits_uses(); void get_use(); - void get_seq(std::vector &seq_next); + void get_seq(std::vector& seq_next); VertexAdaptor get_seq(); void parse_declare_at_top_of_file(); @@ -79,7 +82,7 @@ class GenTree { void run(); template::ResultType> - bool gen_list(std::vector *res, FuncT f, TokenType delim); + bool gen_list(std::vector* res, FuncT f, TokenType delim); template VertexAdaptor get_conv(); VertexAdaptor get_require(bool once); @@ -90,7 +93,7 @@ class GenTree { VertexAdaptor get_string_build(); VertexPtr get_def_value(); template::ResultType> - VertexAdaptor get_multi_call(FuncT &&f, bool parenthesis = false); + VertexAdaptor get_multi_call(FuncT&& f, bool parenthesis = false); VertexAdaptor get_return(); template VertexAdaptor get_break_or_continue(); @@ -105,34 +108,35 @@ class GenTree { VertexPtr get_member_by_name_after_var(VertexAdaptor v_before); VertexPtr get_phpdoc_inside_function(); bool parse_cur_function_uses(); - static bool test_if_uses_and_arguments_intersect(const std::forward_list> &uses_list, const VertexRange ¶ms); - VertexAdaptor get_lambda_function(const PhpDocComment *phpdoc, FunctionModifiers modifiers); - VertexAdaptor get_function(bool is_lambda, const PhpDocComment *phpdoc, FunctionModifiers modifiers); + static bool test_if_uses_and_arguments_intersect(const std::forward_list>& uses_list, const VertexRange& params); + VertexAdaptor get_lambda_function(const PhpDocComment* phpdoc, FunctionModifiers modifiers); + VertexAdaptor get_function(bool is_lambda, const PhpDocComment* phpdoc, FunctionModifiers modifiers); ClassMemberModifiers parse_class_member_modifier_mask(); - VertexPtr get_class_member(const PhpDocComment *phpdoc); + VertexPtr get_class_member(const PhpDocComment* phpdoc); std::string get_identifier(); - static VertexAdaptor gen_constructor_call_with_args(const std::string &allocated_class_name, std::vector args, const Location &location); - static VertexAdaptor gen_constructor_call_with_args(ClassPtr allocated_class, std::vector args, const Location &locaction); + static VertexAdaptor gen_constructor_call_with_args(const std::string& allocated_class_name, std::vector args, + const Location& location); + static VertexAdaptor gen_constructor_call_with_args(ClassPtr allocated_class, std::vector args, const Location& locaction); static VertexAdaptor auto_capture_this_in_lambda(FunctionPtr f_lambda); - VertexPtr get_class(const PhpDocComment *phpdoc, ClassType class_type); + VertexPtr get_class(const PhpDocComment* phpdoc, ClassType class_type); void parse_extends_implements(); static VertexPtr process_arrow(VertexPtr lhs, VertexPtr rhs); private: - const TypeHint *get_typehint(); - GenericsInstantiationPhpComment *parse_php_commentTs(vk::string_view str_commentTs); + const TypeHint* get_typehint(); + GenericsInstantiationPhpComment* parse_php_commentTs(vk::string_view str_commentTs); - static void check_and_remove_num_separators(std::string &s); + static void check_and_remove_num_separators(std::string& s); VertexPtr get_op_num_const(); VertexAdaptor parse_cur_function_param_list(); - VertexAdaptor get_static_field_list(const PhpDocComment *phpdoc, FieldModifiers modifiers, const TypeHint *type_hint); + VertexAdaptor get_static_field_list(const PhpDocComment* phpdoc, FieldModifiers modifiers, const TypeHint* type_hint); VertexAdaptor get_function_use_var_name_ref(); VertexPtr get_foreach_value(); std::pair, VertexPtr> get_foreach_param(); @@ -140,16 +144,14 @@ class GenTree { VertexPtr get_const_after_explicit_access_modifier(AccessModifiers access); VertexPtr get_const(AccessModifiers access); - int line_num{0}; const std::vector tokens; - DataStream &parsed_os; + DataStream& parsed_os; bool is_top_of_the_function_{false}; decltype(tokens)::const_iterator cur, end; std::vector class_stack; - ClassPtr cur_class; // = class_stack.back() + ClassPtr cur_class; // = class_stack.back() std::vector functions_stack; - FunctionPtr cur_function; // = functions_stack.back() + FunctionPtr cur_function; // = functions_stack.back() SrcFilePtr processing_file; }; - diff --git a/compiler/helper.h b/compiler/helper.h index f9b2749a8d..3f769d4936 100644 --- a/compiler/helper.h +++ b/compiler/helper.h @@ -12,21 +12,21 @@ #include "compiler/utils/string-utils.h" #include "compiler/utils/trie.h" -inline std::vector expand_template(const std::string &s); +inline std::vector expand_template(const std::string& s); template struct Helper : private vk::not_copyable { - Trie trie; - T *on_fail; + Trie trie; + T* on_fail; - explicit Helper(T *on_fail) : - on_fail(on_fail) { + explicit Helper(T* on_fail) + : on_fail(on_fail) { assert(on_fail != nullptr); } - void add_rule(const std::string &rule_template, T *val_, bool need_expand = true) { + void add_rule(const std::string& rule_template, T* val_, bool need_expand = true) { if (need_expand) { - for (auto &rule : expand_template(rule_template)) { + for (auto& rule : expand_template(rule_template)) { trie.add(rule, val_); } } else { @@ -34,15 +34,15 @@ struct Helper : private vk::not_copyable { } } - void add_simple_rule(const std::string &rule_template, T *val) { + void add_simple_rule(const std::string& rule_template, T* val) { add_rule(rule_template, val, false); } - T *get_default() { + T* get_default() { return on_fail; } - T *get_help(const char *s) { + T* get_help(const char* s) { if (auto best = trie.get_deepest(s)) { return *best; } @@ -63,11 +63,11 @@ inline std::vector expand_template_(vk::string_view str_template) { while (si < sn && str_template[si] != ']') { if (si + 1 < sn && str_template[si + 1] == '-') { - assert (si + 2 < sn); + assert(si + 2 < sn); char l = str_template[si]; char r = str_template[si + 2]; - assert (l < r); + assert(l < r); for (char c = l; c <= r; c++) { to_append += c; } @@ -78,7 +78,7 @@ inline std::vector expand_template_(vk::string_view str_template) { si++; } } - assert (si < sn); + assert(si < sn); si++; } else { to_append += str_template[si]; @@ -97,7 +97,7 @@ inline std::vector expand_template_(vk::string_view str_template) { return all_possible_templates; } -inline std::vector expand_template(const std::string &s) { +inline std::vector expand_template(const std::string& s) { auto template_alternatives = split_skipping_delimeters(s, "|"); std::vector res; diff --git a/compiler/index.cpp b/compiler/index.cpp index a7cb6dfc58..2806b6b380 100644 --- a/compiler/index.cpp +++ b/compiler/index.cpp @@ -9,8 +9,8 @@ #include #include -#include "common/macos-ports.h" #include "common/containers/final_action.h" +#include "common/macos-ports.h" #include "common/wrappers/mkdir_recursive.h" #include "compiler/kphp_assert.h" @@ -18,27 +18,27 @@ #include "compiler/stage.h" #include "compiler/utils/string-utils.h" -bool is_dir(const std::string &path) { +bool is_dir(const std::string& path) { struct stat s; int err = stat(path.c_str(), &s); kphp_assert_msg(err == 0, fmt_format("Failed to stat [{}]", path)); - return S_ISDIR (s.st_mode); + return S_ISDIR(s.st_mode); } -int64_t get_mtime(const struct stat &sb) { +int64_t get_mtime(const struct stat& sb) { return sb.st_mtime * 1000000000ll + sb.st_mtim.tv_nsec; } -//Index: -// holds some information about all files in given directory (and all its subdirs) -// can be synchronized with file system -// can be saved to file -// can be loaded from file +// Index: +// holds some information about all files in given directory (and all its subdirs) +// can be synchronized with file system +// can be saved to file +// can be loaded from file // -// for a start, files will be indexed by their names -// hashes will be used in future +// for a start, files will be indexed by their names +// hashes will be used in future -void File::calc_name_ext_and_others(const std::string &basedir) { +void File::calc_name_ext_and_others(const std::string& basedir) { kphp_assert(vk::string_view{path}.starts_with(basedir)); name = vk::string_view{path}.substr(basedir.size()); auto dot_i = name.rfind('.'); @@ -78,10 +78,10 @@ long long File::read_stat() { return -1; } on_disk = true; - //TODO: check if it is file + // TODO: check if it is file mtime = get_mtime(buf); file_size = buf.st_size; - //fprintf (stderr, "%lld [%d %d] %s\n", mtime, (int)buf.st_mtime, (int)buf.st_mtim.tv_nsec, path.c_str()); + // fprintf (stderr, "%lld [%d %d] %s\n", mtime, (int)buf.st_mtime, (int)buf.st_mtim.tv_nsec, path.c_str()); return 1; } @@ -95,14 +95,14 @@ void File::unlink() { on_disk = false; } -void Index::set_dir(const std::string &new_dir) { +void Index::set_dir(const std::string& new_dir) { bool res_mkdir = mkdir_recursive(new_dir.c_str(), 0777); kphp_assert_msg(res_mkdir, fmt_format("Failed to mkdir [{}] ({})", new_dir, strerror(errno))); dir = get_full_path(new_dir); - kphp_assert (!dir.empty()); + kphp_assert(!dir.empty()); if (!is_dir(dir)) { - kphp_error (0, fmt_format("[{}] is not a directory", dir)); + kphp_error(0, fmt_format("[{}] is not a directory", dir)); kphp_fail(); } if (dir[dir.size() - 1] != '/') { @@ -111,57 +111,56 @@ void Index::set_dir(const std::string &new_dir) { index_file = dir + "index_file"; } -const std::string &Index::get_dir() const { +const std::string& Index::get_dir() const { return dir; } -Index *Index::current_index = nullptr; +Index* Index::current_index = nullptr; -int Index::scan_dir_callback(const char *fpath, const struct stat *sb, int typeflag, - struct FTW *ftwbuf __attribute__((unused))) { +int Index::scan_dir_callback(const char* fpath, const struct stat* sb, int typeflag, struct FTW* ftwbuf __attribute__((unused))) { if (typeflag == FTW_D) { - //skip + // skip } else if (typeflag == FTW_F) { // ignore index file if (current_index->index_file == fpath) { return 0; } char full_path[PATH_MAX + 1]; - File *f = current_index->on_new_file_during_scan_dir(realpath(fpath, full_path)); + File* f = current_index->on_new_file_during_scan_dir(realpath(fpath, full_path)); f->on_disk = true; long long new_mtime = get_mtime(*sb); - //fprintf (stderr, "%lld [%d %d] %s\n", new_mtime, (int)sb->st_mtime, (int)sb->st_mtim.tv_nsec, fpath); + // fprintf (stderr, "%lld [%d %d] %s\n", new_mtime, (int)sb->st_mtime, (int)sb->st_mtim.tv_nsec, fpath); if (f->mtime != new_mtime) { f->crc64 = -1; f->crc64_with_comments = -1; } f->mtime = new_mtime; } else { - kphp_error (0, fmt_format("Failed to scan directory [fpath={}]\n", fpath)); + kphp_error(0, fmt_format("Failed to scan directory [fpath={}]\n", fpath)); kphp_fail(); } return 0; } -void Index::sync_with_dir(const std::string &dir) { +void Index::sync_with_dir(const std::string& dir) { kphp_assert(files_prev_launch.empty() && files_only_cur_launch.empty() && this->dir.empty()); set_dir(dir); current_index = this; // Presence of this global variable is strange. Used for traversal callback in NFTW function - int err = nftw(dir.c_str(), scan_dir_callback, 10, FTW_PHYS/*ignore symbolic links*/); + int err = nftw(dir.c_str(), scan_dir_callback, 10, FTW_PHYS /*ignore symbolic links*/); kphp_assert_msg(err == 0, fmt_format("ftw [{}] failed", dir)); } -void Index::filter_with_whitelist(const std::vector &white_list) { +void Index::filter_with_whitelist(const std::vector& white_list) { subdirs.clear(); std::unordered_set white_set; white_set.reserve(white_list.size()); - for (const auto &allowed : white_list) { + for (const auto& allowed : white_list) { white_set.insert(allowed); } for (auto it = files_prev_launch.begin(); it != files_prev_launch.end();) { - File *file = it->second; + File* file = it->second; if (white_set.count(file->name) == 0) { delete file; it = files_prev_launch.erase(it); @@ -175,13 +174,13 @@ void Index::filter_with_whitelist(const std::vector &white_list) { } void Index::del_all_files() { - for (File *file : get_files()) { + for (File* file : get_files()) { if (G->settings().verbosity.get() > 1) { fprintf(stderr, "unlink %s\n", file->path.c_str()); } int err = unlink(file->path.c_str()); if (err != 0) { - kphp_error (0, fmt_format("Failed to unlink file {}: {}", file->path, strerror(errno))); + kphp_error(0, fmt_format("Failed to unlink file {}: {}", file->path, strerror(errno))); kphp_fail(); } @@ -193,7 +192,7 @@ void Index::del_extra_files() { // delete files that were not emerged by the current launch // we need only to iterate through files_prev_codegen and unlink if !file->needed for (auto it = files_prev_launch.begin(); it != files_prev_launch.end();) { - File *file = it->second; + File* file = it->second; if (!file->needed) { if (file->on_disk) { if (G->settings().verbosity.get() > 1) { @@ -201,7 +200,7 @@ void Index::del_extra_files() { } int err = unlink(file->path.c_str()); if (err != 0) { - kphp_error (0, fmt_format("Failed to unlink file {}: {}", file->path, strerror(errno))); + kphp_error(0, fmt_format("Failed to unlink file {}: {}", file->path, strerror(errno))); kphp_fail(); } } @@ -222,20 +221,20 @@ void Index::create_subdir(vk::string_view subdir) { int ret = mkdir_recursive(full_path.c_str(), 0777); kphp_assert_msg(ret != -1 || errno == EEXIST, full_path); if (errno == EEXIST && !is_dir(full_path)) { - kphp_error (0, fmt_format("[{}] is not a directory", full_path.c_str())); + kphp_error(0, fmt_format("[{}] is not a directory", full_path.c_str())); kphp_fail(); } } -void Index::fix_path(std::string &path) const { +void Index::fix_path(std::string& path) const { kphp_assert(!path.empty()); if (path[0] != '/') { path.insert(0, get_dir()); } - kphp_assert (path[0] == '/'); + kphp_assert(path[0] == '/'); } -File *Index::get_file(std::string path) const { +File* Index::get_file(std::string path) const { fix_path(path); auto it = files_prev_launch.find(path); if (it != files_prev_launch.end()) { @@ -253,14 +252,14 @@ File *Index::get_file(std::string path) const { return nullptr; } -File *Index::insert_file(std::string path) { +File* Index::insert_file(std::string path) { fix_path(path); - File *f = get_file(path); + File* f = get_file(path); if (f != nullptr) { return f; } -// printf("%s not found in index, creating\n", file_name.c_str()); + // printf("%s not found in index, creating\n", file_name.c_str()); std::lock_guard guard{mutex_rw_cur_launch}; // It's reasonable only for Php2Cpp @@ -272,10 +271,10 @@ File *Index::insert_file(std::string path) { return f; } -File *Index::on_new_file_during_scan_dir(std::string path) { +File* Index::on_new_file_during_scan_dir(std::string path) { fix_path(path); - File *f = new File(path); + File* f = new File(path); f->calc_name_ext_and_others(get_dir()); create_subdir(f->subdir); @@ -283,14 +282,14 @@ File *Index::on_new_file_during_scan_dir(std::string path) { return f; } -std::vector Index::get_files() const { +std::vector Index::get_files() const { // return a vector to traverse values of files_prev_codegen, then files_cur_codegen // can be improved by returning a custom iterator; for now, leave a stupid version - std::vector files_joined; - for (const auto &it : files_prev_launch) { + std::vector files_joined; + for (const auto& it : files_prev_launch) { files_joined.emplace_back(it.second); } - for (const auto &it : files_only_cur_launch) { + for (const auto& it : files_only_cur_launch) { files_joined.emplace_back(it.second); } return files_joined; @@ -313,7 +312,7 @@ void Index::save_into_index_file() { return; } - std::unique_ptr f{fdopen(tmp_index_file_fd, "w"), fclose}; + std::unique_ptr f{fdopen(tmp_index_file_fd, "w"), fclose}; kphp_assert(f); auto file_deleter = vk::finally([&index_file_tmp_name]() { unlink(index_file_tmp_name.c_str()); }); @@ -322,10 +321,10 @@ void Index::save_into_index_file() { return; } - for (const auto &file : get_files()) { + for (const auto& file : get_files()) { const std::string path = file->path.substr(dir.length()); if (fprintf(f.get(), "%s %llu %llu\n", path.c_str(), file->crc64, file->crc64_with_comments) <= 0) { - kphp_warning (fmt_format("Can't write crc32 into tmp index file '{}'", index_file_tmp_name)); + kphp_warning(fmt_format("Can't write crc32 into tmp index file '{}'", index_file_tmp_name)); return; } } @@ -343,7 +342,7 @@ void Index::load_from_index_file() { if (index_file.empty()) { return; } - std::unique_ptr f{fopen(index_file.c_str(), "r"), fclose}; + std::unique_ptr f{fopen(index_file.c_str(), "r"), fclose}; if (!f) { return; } @@ -368,12 +367,10 @@ void Index::load_from_index_file() { kphp_warning(fmt_format("Can't read crc32 from index file '{}:{}'", index_file, i + 2)); return; } - File *file = get_file(tmp); + File* file = get_file(tmp); if (file && file->mtime < file_index_mtime) { file->crc64 = crc64; file->crc64_with_comments = crc64_with_comments; } } } - - diff --git a/compiler/index.h b/compiler/index.h index 8421951ca8..4e406dbe68 100644 --- a/compiler/index.h +++ b/compiler/index.h @@ -4,14 +4,14 @@ #pragma once +#include #include +#include #include #include +#include #include -#include #include -#include -#include #include "common/wrappers/iterator_range.h" #include "common/wrappers/string_view.h" @@ -21,8 +21,9 @@ class Target; class File { private: - File(const File &from); - File &operator=(const File &from); + File(const File& from); + File& operator=(const File& from); + public: std::string path; vk::string_view name; @@ -31,20 +32,21 @@ class File { vk::string_view subdir; long long mtime{0}; long long file_size{0}; - unsigned long long crc64{static_cast(-1)}; // actually, some hash of cpp contents - unsigned long long crc64_with_comments{static_cast(-1)}; // actually, some hash of comments (php lines) + unsigned long long crc64{static_cast(-1)}; // actually, some hash of cpp contents + unsigned long long crc64_with_comments{static_cast(-1)}; // actually, some hash of comments (php lines) bool on_disk{false}; bool needed{false}; - Target *target{nullptr}; - //Don't know where else I can save it + Target* target{nullptr}; + // Don't know where else I can save it std::forward_list includes; std::forward_list lib_includes; bool compile_with_debug_info_flag{true}; bool is_changed{false}; - explicit File(std::string path) : path(std::move(path)) {} - void calc_name_ext_and_others(const std::string &basedir); - long long read_stat() __attribute__ ((warn_unused_result)); + explicit File(std::string path) + : path(std::move(path)) {} + void calc_name_ext_and_others(const std::string& basedir); + long long read_stat() __attribute__((warn_unused_result)); void set_mtime(long long mtime_value); void unlink(); }; @@ -61,33 +63,33 @@ class Index { // * files_only_cur_launch are read/written from multiple threads — and therefore a mutex is required // keys of these maps are relative file names // keys files_only_cur_launch always differ from keys of prev launch: if a file with the same name is generated, it's found in prev - std::unordered_map files_prev_launch; - std::unordered_map files_only_cur_launch; + std::unordered_map files_prev_launch; + std::unordered_map files_only_cur_launch; mutable std::mutex mutex_rw_cur_launch; - + std::string dir; std::set subdirs; std::string index_file; void create_subdir(vk::string_view subdir); - static Index *current_index; - static int scan_dir_callback(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf); - File *on_new_file_during_scan_dir(std::string path); + static Index* current_index; + static int scan_dir_callback(const char* fpath, const struct stat* sb, int typeflag, struct FTW* ftwbuf); + File* on_new_file_during_scan_dir(std::string path); - void fix_path(std::string &path) const; + void fix_path(std::string& path) const; public: - void set_dir(const std::string &dir); - const std::string &get_dir() const; - void sync_with_dir(const std::string &dir); - void filter_with_whitelist(const std::vector &white_list); + void set_dir(const std::string& dir); + const std::string& get_dir() const; + void sync_with_dir(const std::string& dir); + void filter_with_whitelist(const std::vector& white_list); void del_extra_files(); void del_all_files(); - File *insert_file(std::string path); - File *get_file(std::string path) const; + File* insert_file(std::string path); + File* get_file(std::string path) const; // return a vector combining values of files_prev_codegen and files_cur_codegen; can be improved - std::vector get_files() const; + std::vector get_files() const; size_t get_files_count() const; // stupid text version. to be improved diff --git a/compiler/inferring/edge.h b/compiler/inferring/edge.h index 272adae61d..2aa970da86 100644 --- a/compiler/inferring/edge.h +++ b/compiler/inferring/edge.h @@ -11,12 +11,11 @@ namespace tinf { class Node; class Edge { -public : - Node *from; - Node *to; +public: + Node* from; + Node* to; - const MultiKey *from_at; + const MultiKey* from_at; }; - } // namespace tinf diff --git a/compiler/inferring/expr-node.cpp b/compiler/inferring/expr-node.cpp index 532f36ad8f..df0e5207fc 100644 --- a/compiler/inferring/expr-node.cpp +++ b/compiler/inferring/expr-node.cpp @@ -10,10 +10,10 @@ #include "compiler/data/define-data.h" #include "compiler/data/function-data.h" #include "compiler/data/var-data.h" -#include "compiler/vertex-util.h" #include "compiler/inferring/edge.h" #include "compiler/inferring/node-recalc.h" #include "compiler/type-hint.h" +#include "compiler/vertex-util.h" class ExprNodeRecalc : public NodeRecalc { private: @@ -50,7 +50,7 @@ class ExprNodeRecalc : public NodeRecalc { void recalc_expr(VertexPtr expr); public: - ExprNodeRecalc(tinf::ExprNode *node, tinf::TypeInferer *inferer); + ExprNodeRecalc(tinf::ExprNode* node, tinf::TypeInferer* inferer); void do_recalc() final; bool auto_edge_flag() final; }; @@ -61,7 +61,6 @@ void ExprNodeRecalc::recalc_ptype() { set_lca(TypeData::get_type(tp)); } - void ExprNodeRecalc::recalc_and_drop_false(VertexAdaptor expr) { VertexPtr inner_expr = expr->expr(); inner_expr->tinf_node.recalc(inferer_); @@ -156,7 +155,7 @@ void ExprNodeRecalc::recalc_foreach_param(VertexAdaptor param) void ExprNodeRecalc::recalc_conv_array(VertexAdaptor conv) { VertexPtr arg = conv->expr(); - //FIXME: (extra dependenty) + // FIXME: (extra dependenty) add_dependency(as_rvalue(arg)); if (tinf::get_type(arg)->get_real_ptype() == tp_array) { set_lca(drop_optional(as_rvalue(arg))); @@ -165,7 +164,7 @@ void ExprNodeRecalc::recalc_conv_array(VertexAdaptor conv) { set_lca(TypeData::get_type(tp_Error)); } else { recalc_ptype(); - if (tinf::get_type(arg)->ptype() != tp_any) { //hack + if (tinf::get_type(arg)->ptype() != tp_any) { // hack set_lca_at(&MultiKey::any_key(1), tinf::get_type(arg)->get_real_ptype()); } } @@ -181,7 +180,7 @@ void ExprNodeRecalc::recalc_array(VertexAdaptor array) { void ExprNodeRecalc::recalc_tuple(VertexAdaptor tuple) { recalc_ptype(); int index = 0; - for (auto i: tuple->args()) { + for (auto i : tuple->args()) { std::vector i_key_index{Key::int_key(index++)}; MultiKey key(i_key_index); set_lca_at(&key, i); @@ -190,9 +189,9 @@ void ExprNodeRecalc::recalc_tuple(VertexAdaptor tuple) { void ExprNodeRecalc::recalc_shape(VertexAdaptor shape) { recalc_ptype(); - for (auto i: shape->args()) { + for (auto i : shape->args()) { auto double_arrow = i.as(); - const std::string &str_index = VertexUtil::get_actual_value(double_arrow->key())->get_string(); + const std::string& str_index = VertexUtil::get_actual_value(double_arrow->key())->get_string(); std::vector i_key_index{Key::string_key(str_index)}; MultiKey key(i_key_index); set_lca_at(&key, double_arrow->value()); @@ -210,7 +209,7 @@ void ExprNodeRecalc::recalc_plus_minus(VertexAdaptor expr) { } void ExprNodeRecalc::recalc_inc_dec(VertexAdaptor expr) { - //or false ??? + // or false ??? set_lca(drop_optional(as_rvalue(expr->expr()))); } @@ -240,7 +239,7 @@ void ExprNodeRecalc::recalc_arithm(VertexAdaptor expr) { VertexPtr lhs = expr->lhs(); VertexPtr rhs = expr->rhs(); - //FIXME: (extra dependency) + // FIXME: (extra dependency) add_dependency(as_rvalue(lhs)); add_dependency(as_rvalue(rhs)); @@ -275,225 +274,225 @@ void ExprNodeRecalc::recalc_power(VertexAdaptor expr) { void ExprNodeRecalc::recalc_expr(VertexPtr expr) { switch (expr->type()) { - case op_move: - recalc_expr(expr.as()->expr()); - break; - case op_ternary: - recalc_ternary(expr.as()); - break; - case op_func_call: - recalc_func_call(expr.as()); - break; - case op_ffi_load_call: - recalc_func_call(expr.as()->func_call()); - break; - case op_ffi_addr: - recalc_ffi_addr(expr.as()); - break; - case op_ffi_cast: - set_lca(expr.as()->php_type->to_type_data()); - break; - case op_ffi_cdata_value_ref: - recalc_expr(expr.as()->expr()); - break; - case op_ffi_new: - set_lca(expr.as()->php_type->to_type_data()); - break; - case op_ffi_array_get: - set_lca(expr.as()->c_elem_type->to_type_data()); - break; - case op_trigger_recalc_arg_ref_rule: - recalc_arg_ref_rule(expr.as()); - break; - case op_var: - recalc_var(expr.as()); - break; - case op_push_back_return: - recalc_push_back_return(expr.as()); - break; - case op_index: - recalc_index(expr.as()); - break; - case op_instance_prop: - recalc_instance_prop(expr.as()); - break; - case op_set: - recalc_set(expr.as()); - break; - case op_false: - recalc_ptype(); - break; - case op_log_or_let: - case op_log_and_let: - case op_log_xor_let: - case op_log_or: - case op_log_and: - case op_log_not: - case op_conv_bool: - case op_true: - case op_eq2: - case op_eq3: - case op_lt: - case op_le: - case op_isset: - recalc_ptype(); - break; - - case op_conv_string: - case op_conv_string_l: - case op_concat: - case op_string_build: - case op_string: - recalc_ptype(); - break; - - case op_ffi_c2php_conv: - recalc_c2php(expr.as()); - break; - - case op_ffi_php2c_conv: - recalc_php2c(expr.as()); - break; - - case op_conv_int: - case op_conv_int_l: - case op_int_const: - case op_mod: - case op_spaceship: - case op_not: - case op_or: - case op_and: - case op_xor: - recalc_ptype(); - break; - case op_fork: - recalc_fork(expr.as()); - break; - - case op_conv_float: - case op_float_const: - case op_div: - recalc_ptype(); - break; - - case op_conv_regexp: - recalc_ptype(); - break; - - case op_double_arrow: - recalc_double_arrow(expr.as()); - break; - - case op_foreach_param: - recalc_foreach_param(expr.as()); - break; - - case op_conv_array: - case op_conv_array_l: - recalc_conv_array(expr.as()); - break; - - case op_array: - recalc_array(expr.as()); - break; - case op_tuple: - recalc_tuple(expr.as()); - break; - case op_shape: - recalc_shape(expr.as()); - break; - - case op_conv_mixed: - // we don't want to spoil types and need this vertex just for further checks - recalc_expr(expr.as()->expr()); - break; - - case op_force_mixed: - recalc_ptype(); - break; - - case op_null: - recalc_ptype(); - break; - - case op_conv_drop_false: - recalc_and_drop_false(expr.as()); - break; - case op_conv_drop_null: - recalc_and_drop_null(expr.as()); - break; - - case op_plus: - case op_minus: - recalc_plus_minus(expr.as()); - break; - - case op_prefix_inc: - case op_prefix_dec: - case op_postfix_inc: - case op_postfix_dec: - recalc_inc_dec(expr.as()); - break; - - case op_noerr: - recalc_noerr(expr.as()); - break; - - case op_sub: - case op_add: - case op_mul: - case op_shl: - case op_shr: - recalc_arithm(expr.as()); - break; - - case op_set_add: - case op_set_sub: - case op_set_mul: - case op_set_div: - case op_set_mod: - case op_set_pow: - case op_set_and: - case op_set_or: - case op_set_xor: - case op_set_dot: - case op_set_shr: - case op_set_shl: - set_lca(expr.as()->lhs()); - break; - - case op_pow: - recalc_power(expr.as()); - break; - - case op_clone: - // for FFI cdata values, clone() drops the reference in &T and returns T; - // for non-cdata types, drop_ref is ignored - set_lca(ffi_rvalue_drop_ref(as_rvalue(expr.as()->expr()))); - break; - - case op_seq_rval: - set_lca(expr.as()->back()); - break; - - case op_null_coalesce: - recalc_null_coalesce(expr.as()); - break; - - case op_return: - recalc_return(expr.as()); - break; - - case op_alloc: - set_lca(expr.as()->allocated_class); - break; - - case op_instanceof: - recalc_ptype(); - break; - - default: - break; + case op_move: + recalc_expr(expr.as()->expr()); + break; + case op_ternary: + recalc_ternary(expr.as()); + break; + case op_func_call: + recalc_func_call(expr.as()); + break; + case op_ffi_load_call: + recalc_func_call(expr.as()->func_call()); + break; + case op_ffi_addr: + recalc_ffi_addr(expr.as()); + break; + case op_ffi_cast: + set_lca(expr.as()->php_type->to_type_data()); + break; + case op_ffi_cdata_value_ref: + recalc_expr(expr.as()->expr()); + break; + case op_ffi_new: + set_lca(expr.as()->php_type->to_type_data()); + break; + case op_ffi_array_get: + set_lca(expr.as()->c_elem_type->to_type_data()); + break; + case op_trigger_recalc_arg_ref_rule: + recalc_arg_ref_rule(expr.as()); + break; + case op_var: + recalc_var(expr.as()); + break; + case op_push_back_return: + recalc_push_back_return(expr.as()); + break; + case op_index: + recalc_index(expr.as()); + break; + case op_instance_prop: + recalc_instance_prop(expr.as()); + break; + case op_set: + recalc_set(expr.as()); + break; + case op_false: + recalc_ptype(); + break; + case op_log_or_let: + case op_log_and_let: + case op_log_xor_let: + case op_log_or: + case op_log_and: + case op_log_not: + case op_conv_bool: + case op_true: + case op_eq2: + case op_eq3: + case op_lt: + case op_le: + case op_isset: + recalc_ptype(); + break; + + case op_conv_string: + case op_conv_string_l: + case op_concat: + case op_string_build: + case op_string: + recalc_ptype(); + break; + + case op_ffi_c2php_conv: + recalc_c2php(expr.as()); + break; + + case op_ffi_php2c_conv: + recalc_php2c(expr.as()); + break; + + case op_conv_int: + case op_conv_int_l: + case op_int_const: + case op_mod: + case op_spaceship: + case op_not: + case op_or: + case op_and: + case op_xor: + recalc_ptype(); + break; + case op_fork: + recalc_fork(expr.as()); + break; + + case op_conv_float: + case op_float_const: + case op_div: + recalc_ptype(); + break; + + case op_conv_regexp: + recalc_ptype(); + break; + + case op_double_arrow: + recalc_double_arrow(expr.as()); + break; + + case op_foreach_param: + recalc_foreach_param(expr.as()); + break; + + case op_conv_array: + case op_conv_array_l: + recalc_conv_array(expr.as()); + break; + + case op_array: + recalc_array(expr.as()); + break; + case op_tuple: + recalc_tuple(expr.as()); + break; + case op_shape: + recalc_shape(expr.as()); + break; + + case op_conv_mixed: + // we don't want to spoil types and need this vertex just for further checks + recalc_expr(expr.as()->expr()); + break; + + case op_force_mixed: + recalc_ptype(); + break; + + case op_null: + recalc_ptype(); + break; + + case op_conv_drop_false: + recalc_and_drop_false(expr.as()); + break; + case op_conv_drop_null: + recalc_and_drop_null(expr.as()); + break; + + case op_plus: + case op_minus: + recalc_plus_minus(expr.as()); + break; + + case op_prefix_inc: + case op_prefix_dec: + case op_postfix_inc: + case op_postfix_dec: + recalc_inc_dec(expr.as()); + break; + + case op_noerr: + recalc_noerr(expr.as()); + break; + + case op_sub: + case op_add: + case op_mul: + case op_shl: + case op_shr: + recalc_arithm(expr.as()); + break; + + case op_set_add: + case op_set_sub: + case op_set_mul: + case op_set_div: + case op_set_mod: + case op_set_pow: + case op_set_and: + case op_set_or: + case op_set_xor: + case op_set_dot: + case op_set_shr: + case op_set_shl: + set_lca(expr.as()->lhs()); + break; + + case op_pow: + recalc_power(expr.as()); + break; + + case op_clone: + // for FFI cdata values, clone() drops the reference in &T and returns T; + // for non-cdata types, drop_ref is ignored + set_lca(ffi_rvalue_drop_ref(as_rvalue(expr.as()->expr()))); + break; + + case op_seq_rval: + set_lca(expr.as()->back()); + break; + + case op_null_coalesce: + recalc_null_coalesce(expr.as()); + break; + + case op_return: + recalc_return(expr.as()); + break; + + case op_alloc: + set_lca(expr.as()->allocated_class); + break; + + case op_instanceof: + recalc_ptype(); + break; + + default: + break; } } @@ -502,55 +501,54 @@ bool ExprNodeRecalc::auto_edge_flag() { return !node_->was_recalc_finished_at_least_once(); } -ExprNodeRecalc::ExprNodeRecalc(tinf::ExprNode *node, tinf::TypeInferer *inferer) : - NodeRecalc(node, inferer) { -} +ExprNodeRecalc::ExprNodeRecalc(tinf::ExprNode* node, tinf::TypeInferer* inferer) + : NodeRecalc(node, inferer) {} void ExprNodeRecalc::do_recalc() { - //fprintf (stderr, "recalc expr %d %p %s\n", get_thread_id(), node_, node_->get_description().c_str()); - VertexPtr expr = dynamic_cast(node_)->get_expr(); + // fprintf (stderr, "recalc expr %d %p %s\n", get_thread_id(), node_, node_->get_description().c_str()); + VertexPtr expr = dynamic_cast(node_)->get_expr(); stage::set_location(expr->get_location()); recalc_expr(expr); } -void tinf::ExprNode::recalc(tinf::TypeInferer *inferer) { +void tinf::ExprNode::recalc(tinf::TypeInferer* inferer) { ExprNodeRecalc(this, inferer).run(); } std::string tinf::ExprNode::convert_expr_to_human_readable(VertexPtr expr) { switch (expr->type()) { - case op_var: - return expr.as()->var_id->as_human_readable(); - - case op_func_call: { - auto func = expr.as()->func_id; - if (func->is_result_indexing) { - return func->as_human_readable() + "[.]"; - } - return func->is_constructor() ? "new " + func->class_id->as_human_readable() : func->as_human_readable(); + case op_var: + return expr.as()->var_id->as_human_readable(); + + case op_func_call: { + auto func = expr.as()->func_id; + if (func->is_result_indexing) { + return func->as_human_readable() + "[.]"; } + return func->is_constructor() ? "new " + func->class_id->as_human_readable() : func->as_human_readable(); + } - case op_instance_prop: - return convert_expr_to_human_readable(expr.as()->instance()) + "->" + expr->get_string(); - - case op_index: { - std::string suff; - auto outer_expr = expr; - while (outer_expr->type() == op_index) { - suff += "[.]"; - outer_expr = outer_expr.as()->array(); - } - return convert_expr_to_human_readable(outer_expr) + suff; + case op_instance_prop: + return convert_expr_to_human_readable(expr.as()->instance()) + "->" + expr->get_string(); + + case op_index: { + std::string suff; + auto outer_expr = expr; + while (outer_expr->type() == op_index) { + suff += "[.]"; + outer_expr = outer_expr.as()->array(); } + return convert_expr_to_human_readable(outer_expr) + suff; + } - case op_int_const: - case op_float_const: - return expr->get_string(); - case op_string: - return '"' + expr->get_string() + '"'; + case op_int_const: + case op_float_const: + return expr->get_string(); + case op_string: + return '"' + expr->get_string() + '"'; - default: - return OpInfo::str(expr->type()); + default: + return OpInfo::str(expr->type()); } } @@ -562,6 +560,6 @@ std::string tinf::ExprNode::get_description() { return "ExprNode " + get_expr_human_readable() + " at " + get_location().as_human_readable() + " : " + tinf::get_type(expr_)->as_human_readable(); } -const Location &tinf::ExprNode::get_location() const { +const Location& tinf::ExprNode::get_location() const { return expr_->location; } diff --git a/compiler/inferring/expr-node.h b/compiler/inferring/expr-node.h index d8bd666340..3834e13cd0 100644 --- a/compiler/inferring/expr-node.h +++ b/compiler/inferring/expr-node.h @@ -17,16 +17,15 @@ class ExprNode : public Node { static std::string convert_expr_to_human_readable(VertexPtr expr); public: - explicit ExprNode(VertexPtr expr) : - expr_(expr) { - } + explicit ExprNode(VertexPtr expr) + : expr_(expr) {} - void copy_type_from(const TypeData *from) { + void copy_type_from(const TypeData* from) { type_ = from; recalc_state_ = recalc_st_waiting | recalc_bit_at_least_once; } - void recalc(TypeInferer *inferer); + void recalc(TypeInferer* inferer); VertexPtr get_expr() const { return expr_; @@ -34,7 +33,7 @@ class ExprNode : public Node { std::string get_description() final; std::string get_expr_human_readable() const; - const Location &get_location() const final; + const Location& get_location() const final; }; } // namespace tinf diff --git a/compiler/inferring/ifi.cpp b/compiler/inferring/ifi.cpp index 1f95481967..7d66478210 100644 --- a/compiler/inferring/ifi.cpp +++ b/compiler/inferring/ifi.cpp @@ -6,8 +6,8 @@ #include "compiler/data/function-data.h" #include "compiler/data/var-data.h" -#include "compiler/vertex.h" #include "compiler/vertex-util.h" +#include "compiler/vertex.h" is_func_id_t get_ifi_id(VertexPtr v) { if (v->type() == op_unset) { @@ -22,24 +22,24 @@ is_func_id_t get_ifi_id(VertexPtr v) { b = VertexUtil::get_actual_value(v.as()->lhs()); } - if (b->type() == op_false) { // $var === false + if (b->type() == op_false) { // $var === false return ifi_is_false; } - if (b->type() == op_string && b->get_string().empty()) { // $var === '' + if (b->type() == op_string && b->get_string().empty()) { // $var === '' return ifi_is_string; } - if (b->type() == op_int_const && b->get_string() == "0") { // $var === 0 + if (b->type() == op_int_const && b->get_string() == "0") { // $var === 0 return ifi_is_integer; } - if (b->type() == op_float_const) { // $var === 3.52 + if (b->type() == op_float_const) { // $var === 3.52 return ifi_is_float; } - if (b->type() == op_array && b->empty()) { // $var === [] + if (b->type() == op_array && b->empty()) { // $var === [] return ifi_is_array; } } if (auto call = v.try_as()) { - const std::string &name = call->func_id->name; + const std::string& name = call->func_id->name; if (name.size() > 2 && name[0] == 'i' && name[1] == 's') { if (name == "is_bool") { return ifi_is_bool; diff --git a/compiler/inferring/ifi.h b/compiler/inferring/ifi.h index 5f9844ba3d..44eb83cf5d 100644 --- a/compiler/inferring/ifi.h +++ b/compiler/inferring/ifi.h @@ -22,10 +22,6 @@ enum is_func_id_t { ifi_is_false = 1 << 11, }; -constexpr int ifi_any_type = ( - ifi_is_bool | ifi_is_null | ifi_is_integer | - ifi_is_float | ifi_is_string | - ifi_is_array | ifi_is_object | ifi_is_false -); +constexpr int ifi_any_type = (ifi_is_bool | ifi_is_null | ifi_is_integer | ifi_is_float | ifi_is_string | ifi_is_array | ifi_is_object | ifi_is_false); is_func_id_t get_ifi_id(VertexPtr v); diff --git a/compiler/inferring/key.cpp b/compiler/inferring/key.cpp index f194faf030..15f64d3d87 100644 --- a/compiler/inferring/key.cpp +++ b/compiler/inferring/key.cpp @@ -10,18 +10,18 @@ #include "compiler/stage.h" #include "compiler/threading/hash-table.h" -static TSHashTable int_keys_ht; -static TSHashTable string_keys_ht; -static TSHashTable string_key_names_ht; +static TSHashTable int_keys_ht; +static TSHashTable string_keys_ht; +static TSHashTable string_key_names_ht; static int n_string_keys_ht = 0; -Key Key::string_key(const std::string &key) { - auto *node = string_keys_ht.at(vk::std_hash(key)); +Key Key::string_key(const std::string& key) { + auto* node = string_keys_ht.at(vk::std_hash(key)); if (node->data != nullptr) { return *node->data; } - AutoLocker locker(node); + AutoLocker locker(node); if (node->data != nullptr) { return *node->data; } @@ -29,19 +29,19 @@ Key Key::string_key(const std::string &key) { int old_n = __sync_fetch_and_add(&n_string_keys_ht, 1); node->data = new Key(old_n * 2 + 2); - auto *name_node = string_key_names_ht.at(node->data->id); + auto* name_node = string_key_names_ht.at(node->data->id); name_node->data = new std::string(key); return *node->data; } Key Key::int_key(int key) { - TSHashTable::HTNode *node = int_keys_ht.at((unsigned int)key); + TSHashTable::HTNode* node = int_keys_ht.at((unsigned int)key); if (node->data != nullptr) { return *node->data; } - AutoLocker locker(node); + AutoLocker locker(node); node->data = new Key((unsigned int)key * 2 + 1); return *node->data; } diff --git a/compiler/inferring/key.h b/compiler/inferring/key.h index 160e10b48f..bf74b3e162 100644 --- a/compiler/inferring/key.h +++ b/compiler/inferring/key.h @@ -9,46 +9,55 @@ #include "compiler/debug.h" class Key { - DEBUG_STRING_METHOD { return to_string(); } + DEBUG_STRING_METHOD { + return to_string(); + } private: int id{-1}; - explicit Key(int id) : - id(id) { - } + explicit Key(int id) + : id(id) {} public: Key() = default; - Key(const Key &other) = default; - Key &operator=(const Key &other) = default; + Key(const Key& other) = default; + Key& operator=(const Key& other) = default; - static Key any_key() { return Key(0); } + static Key any_key() { + return Key(0); + } - static Key string_key(const std::string &key); + static Key string_key(const std::string& key); static Key int_key(int key); std::string to_string() const; - inline bool is_any_key() const { return id == 0; } + inline bool is_any_key() const { + return id == 0; + } - inline bool is_int_key() const { return id > 0 && id % 2 == 1; } + inline bool is_int_key() const { + return id > 0 && id % 2 == 1; + } - inline bool is_string_key() const { return id > 0 && id % 2 == 0; } + inline bool is_string_key() const { + return id > 0 && id % 2 == 0; + } - friend inline bool operator<(const Key &a, const Key &b); - friend inline bool operator!=(const Key &a, const Key &b); - friend inline bool operator==(const Key &a, const Key &b); + friend inline bool operator<(const Key& a, const Key& b); + friend inline bool operator!=(const Key& a, const Key& b); + friend inline bool operator==(const Key& a, const Key& b); }; -inline bool operator<(const Key &a, const Key &b) { +inline bool operator<(const Key& a, const Key& b) { return a.id < b.id; } -inline bool operator!=(const Key &a, const Key &b) { +inline bool operator!=(const Key& a, const Key& b) { return a.id != b.id; } -inline bool operator==(const Key &a, const Key &b) { +inline bool operator==(const Key& a, const Key& b) { return a.id == b.id; } diff --git a/compiler/inferring/lvalue.cpp b/compiler/inferring/lvalue.cpp index f06ccd33ab..225f78f3b6 100644 --- a/compiler/inferring/lvalue.cpp +++ b/compiler/inferring/lvalue.cpp @@ -23,23 +23,23 @@ LValue as_lvalue(VertexPtr v) { v = v.as()->array(); } - tinf::Node *value = nullptr; + tinf::Node* value = nullptr; if (auto var = v.try_as()) { value = tinf::get_tinf_node(var->var_id); } else if (vk::any_of_equal(v->type(), op_conv_array_l, op_conv_int_l, op_conv_string_l, op_ffi_cdata_value_ref)) { - kphp_assert (depth == 0); + kphp_assert(depth == 0); return as_lvalue(v.as()->expr()); } else if (v->type() == op_array) { kphp_fail(); } else if (auto call = v.try_as()) { value = tinf::get_tinf_node(call->func_id, -1); - } else if (auto prop = v.try_as()) { // for '$a->arr[] = 1;' + } else if (auto prop = v.try_as()) { // for '$a->arr[] = 1;' value = tinf::get_tinf_node(prop->var_id); } else { - kphp_error (0, fmt_format("Bug in compiler: Trying to use [{}] as lvalue", OpInfo::str(v->type()))); + kphp_error(0, fmt_format("Bug in compiler: Trying to use [{}] as lvalue", OpInfo::str(v->type()))); kphp_fail(); } - kphp_assert (value != nullptr); + kphp_assert(value != nullptr); return {value, &MultiKey::any_key(depth)}; } diff --git a/compiler/inferring/lvalue.h b/compiler/inferring/lvalue.h index 3ba852edbe..6065946785 100644 --- a/compiler/inferring/lvalue.h +++ b/compiler/inferring/lvalue.h @@ -8,24 +8,21 @@ #include "compiler/inferring/public.h" struct LValue { - tinf::Node *value; - const MultiKey *key; - LValue() : - value(nullptr), - key(nullptr) { - } + tinf::Node* value; + const MultiKey* key; + LValue() + : value(nullptr), + key(nullptr) {} - LValue(tinf::Node *value, const MultiKey *key) : - value(value), - key(key) { - } + LValue(tinf::Node* value, const MultiKey* key) + : value(value), + key(key) {} - LValue(const LValue &from) : - value(from.value), - key(from.key) { - } + LValue(const LValue& from) + : value(from.value), + key(from.key) {} - LValue &operator=(const LValue &from) { + LValue& operator=(const LValue& from) { value = from.value; key = from.key; return *this; @@ -42,7 +39,6 @@ inline LValue as_lvalue(VarPtr var) { return {tinf::get_tinf_node(var), &MultiKey::any_key(0)}; } -inline const LValue &as_lvalue(const LValue &lvalue) { +inline const LValue& as_lvalue(const LValue& lvalue) { return lvalue; } - diff --git a/compiler/inferring/multi-key.cpp b/compiler/inferring/multi-key.cpp index 210248cc9b..3e5702095d 100644 --- a/compiler/inferring/multi-key.cpp +++ b/compiler/inferring/multi-key.cpp @@ -12,7 +12,7 @@ std::string MultiKey::to_string() const { if (keys_.empty()) { return "(empty)"; } - return "[" + vk::join(*this, ",", std::mem_fn(&Key::to_string))+ "]"; + return "[" + vk::join(*this, ",", std::mem_fn(&Key::to_string)) + "]"; } std::vector MultiKey::any_key_vec; diff --git a/compiler/inferring/multi-key.h b/compiler/inferring/multi-key.h index dd41bf2220..bbc618aab5 100644 --- a/compiler/inferring/multi-key.h +++ b/compiler/inferring/multi-key.h @@ -13,7 +13,9 @@ #include "compiler/kphp_assert.h" class MultiKey { - DEBUG_STRING_METHOD { return to_string(); } + DEBUG_STRING_METHOD { + return to_string(); + } private: std::vector keys_; @@ -24,18 +26,17 @@ class MultiKey { using reverse_iterator = std::vector::const_reverse_iterator; MultiKey() = default; - MultiKey(const MultiKey &multi_key) = default; - MultiKey &operator=(const MultiKey &multi_key) = default; + MultiKey(const MultiKey& multi_key) = default; + MultiKey& operator=(const MultiKey& multi_key) = default; - explicit MultiKey(std::vector keys) : - keys_(std::move(keys)) { - } + explicit MultiKey(std::vector keys) + : keys_(std::move(keys)) {} - void push_back(const Key &key) { + void push_back(const Key& key) { keys_.push_back(key); } - void push_front(const Key &key) { + void push_front(const Key& key) { keys_.insert(keys_.begin(), key); } @@ -69,7 +70,7 @@ class MultiKey { } } - static const MultiKey &any_key(uint32_t depth) { + static const MultiKey& any_key(uint32_t depth) { if (depth < any_key_vec.size()) { return any_key_vec[depth]; } diff --git a/compiler/inferring/node-recalc.cpp b/compiler/inferring/node-recalc.cpp index 4acfb9f82a..bca2faebb5 100644 --- a/compiler/inferring/node-recalc.cpp +++ b/compiler/inferring/node-recalc.cpp @@ -16,7 +16,7 @@ // by default, we try to detect the reason and print it out // (it may be because of mixing classes with primitives in an array, for example — they any_key will emerge tp_Error) // note, that if a node is restricted with phpdoc, no error is printed, as VarNode overloads this callback -void NodeRecalc::on_new_type_became_tpError(const TypeData *because_of_type, const RValue &because_of_rvalue) { +void NodeRecalc::on_new_type_became_tpError(const TypeData* because_of_type, const RValue& because_of_rvalue) { PrimitiveType ptype_before_error = node_->get_type()->ptype(); ClassPtr mix_class = new_type_->get_first_class_type_inside(); ClassPtr mix_class2 = because_of_type->get_first_class_type_inside(); @@ -27,9 +27,8 @@ void NodeRecalc::on_new_type_became_tpError(const TypeData *because_of_type, con } if (mix_class && mix_class2 && mix_class != mix_class2 && !vk::any_of_equal(ptype_before_error, tp_tuple, tp_shape)) { - kphp_error(0, fmt_format("Type Error: mix classes {} and {}: {} and {}\n", - TermStringFormat::paint_green(mix_class->name), TermStringFormat::paint_green(mix_class2->name), - desc1, desc2)); + kphp_error(0, fmt_format("Type Error: mix classes {} and {}: {} and {}\n", TermStringFormat::paint_green(mix_class->name), + TermStringFormat::paint_green(mix_class2->name), desc1, desc2)); } else if ((mix_class || mix_class2) && !vk::any_of_equal(ptype_before_error, tp_tuple, tp_shape)) { const auto class_name = TermStringFormat::paint_green(mix_class ? mix_class->name : mix_class2->name); @@ -49,14 +48,13 @@ void NodeRecalc::on_new_type_became_tpError(const TypeData *because_of_type, con } else if (ptype_before_error == tp_void || because_of_type->ptype() == tp_void) { kphp_error(0, fmt_format("Type Error: mixing void and non-void expressions ({} and {})\n", desc1, desc2)); - + } else { - kphp_error (0, fmt_format("Type Error [{}] updated by [{}]\n", desc1, desc2)); + kphp_error(0, fmt_format("Type Error [{}] updated by [{}]\n", desc1, desc2)); } } - -const TypeData *NodeRecalc::new_type() { +const TypeData* NodeRecalc::new_type() { return new_type_; } @@ -64,8 +62,8 @@ bool NodeRecalc::auto_edge_flag() { return false; } -void NodeRecalc::add_dependency_impl(tinf::Node *from, tinf::Node *to, const MultiKey *from_at) { - tinf::Edge *e = new tinf::Edge(); +void NodeRecalc::add_dependency_impl(tinf::Node* from, tinf::Node* to, const MultiKey* from_at) { + tinf::Edge* e = new tinf::Edge(); e->from = from; e->to = to; // for any key (most of cases) save the pointer, as it remains valid always, otherwise clone, as it may be in temporary memory @@ -74,17 +72,17 @@ void NodeRecalc::add_dependency_impl(tinf::Node *from, tinf::Node *to, const Mul inferer_->add_node(e->to); } -void NodeRecalc::add_dependency(const RValue &rvalue) { +void NodeRecalc::add_dependency(const RValue& rvalue) { if (auto_edge_flag() && rvalue.node != nullptr) { add_dependency_impl(node_, rvalue.node, nullptr); } } -void NodeRecalc::set_lca_at(const MultiKey *key, const RValue &rvalue) { +void NodeRecalc::set_lca_at(const MultiKey* key, const RValue& rvalue) { if (new_type_->error_flag()) { return; } - const TypeData *type = nullptr; + const TypeData* type = nullptr; if (rvalue.node != nullptr) { if (auto_edge_flag()) { add_dependency_impl(node_, rvalue.node, key); @@ -110,15 +108,15 @@ void NodeRecalc::set_lca_at(const MultiKey *key, const RValue &rvalue) { } } -void NodeRecalc::set_lca_at(const MultiKey *key, VertexPtr expr) { +void NodeRecalc::set_lca_at(const MultiKey* key, VertexPtr expr) { set_lca_at(key, as_rvalue(expr)); } -void NodeRecalc::set_lca_at(const MultiKey *key, PrimitiveType ptype) { +void NodeRecalc::set_lca_at(const MultiKey* key, PrimitiveType ptype) { set_lca_at(key, as_rvalue(TypeData::get_type(ptype))); } -void NodeRecalc::set_lca(const RValue &rvalue) { +void NodeRecalc::set_lca(const RValue& rvalue) { set_lca_at(nullptr, rvalue); } @@ -130,11 +128,11 @@ void NodeRecalc::set_lca(FunctionPtr function, int id) { set_lca_at(nullptr, as_rvalue(function, id)); } -void NodeRecalc::set_lca(VertexPtr vertex, const MultiKey *key /* = nullptr*/) { +void NodeRecalc::set_lca(VertexPtr vertex, const MultiKey* key /* = nullptr*/) { set_lca_at(nullptr, as_rvalue(vertex, key)); } -void NodeRecalc::set_lca(const TypeData *type, const MultiKey *key /* = nullptr*/) { +void NodeRecalc::set_lca(const TypeData* type, const MultiKey* key /* = nullptr*/) { set_lca_at(nullptr, as_rvalue(type, key)); } @@ -147,21 +145,20 @@ void NodeRecalc::set_lca(ClassPtr klass) { set_lca(klass->type_data); } - -NodeRecalc::NodeRecalc(tinf::Node *node, tinf::TypeInferer *inferer) : - new_type_(nullptr), - node_(node), - inferer_(inferer) {} +NodeRecalc::NodeRecalc(tinf::Node* node, tinf::TypeInferer* inferer) + : new_type_(nullptr), + node_(node), + inferer_(inferer) {} void NodeRecalc::on_changed() { - //fmt_fprintf(stderr, "{} : {} -> {}\n", node_->get_description(), type_out(node_->get_type()), type_out(new_type())); + // fmt_fprintf(stderr, "{} : {} -> {}\n", node_->get_description(), type_out(node_->get_type()), type_out(new_type())); new_type_->mark_classes_used(); node_->set_type(new_type_); new_type_ = nullptr; // here we need a lock: in case another thread updates edges_to_this_ just now via auto edge - AutoLocker locker(node_); - for (const tinf::Edge *e : node_->get_edges_to_this()) { + AutoLocker locker(node_); + for (const tinf::Edge* e : node_->get_edges_to_this()) { inferer_->recalc_node(e->from); } } @@ -170,7 +167,7 @@ void NodeRecalc::run() { // current node type is node_->type_ // while recalculation (in set_lca_at() and others), new_type_ is updated // after recalculation, if new_type_ was updated somehow, it is cloned to node_->type_ - const TypeData *before = node_->get_type(); + const TypeData* before = node_->get_type(); new_type_ = before->clone(); do_recalc(); @@ -179,8 +176,7 @@ void NodeRecalc::run() { } // detect if new_type_ differs from before (the first line is a small optimization, not to invoke a function if obvious) - bool changed = new_type_->ptype() != before->ptype() || new_type_->flags() != before->flags() || - new_type_->did_type_data_change_after_tinf_step(before); + bool changed = new_type_->ptype() != before->ptype() || new_type_->flags() != before->flags() || new_type_->did_type_data_change_after_tinf_step(before); if (changed) { on_changed(); } diff --git a/compiler/inferring/node-recalc.h b/compiler/inferring/node-recalc.h index a291394502..b499a1d433 100644 --- a/compiler/inferring/node-recalc.h +++ b/compiler/inferring/node-recalc.h @@ -9,35 +9,36 @@ class NodeRecalc { protected: - TypeData *new_type_; - tinf::Node *node_; - tinf::TypeInferer *inferer_; + TypeData* new_type_; + tinf::Node* node_; + tinf::TypeInferer* inferer_; + public: - const TypeData *new_type(); - void add_dependency_impl(tinf::Node *from, tinf::Node *to, const MultiKey *from_at); - void add_dependency(const RValue &rvalue); - void set_lca_at(const MultiKey *key, const RValue &rvalue); - void set_lca_at(const MultiKey *key, VertexPtr expr); - void set_lca_at(const MultiKey *key, PrimitiveType ptype); - void set_lca(const RValue &rvalue); + const TypeData* new_type(); + void add_dependency_impl(tinf::Node* from, tinf::Node* to, const MultiKey* from_at); + void add_dependency(const RValue& rvalue); + void set_lca_at(const MultiKey* key, const RValue& rvalue); + void set_lca_at(const MultiKey* key, VertexPtr expr); + void set_lca_at(const MultiKey* key, PrimitiveType ptype); + void set_lca(const RValue& rvalue); void set_lca(PrimitiveType ptype); void set_lca(FunctionPtr function, int id); - void set_lca(VertexPtr vertex, const MultiKey *key = nullptr); - void set_lca(const TypeData *type, const MultiKey *key = nullptr); + void set_lca(VertexPtr vertex, const MultiKey* key = nullptr); + void set_lca(const TypeData* type, const MultiKey* key = nullptr); void set_lca(VarPtr var); void set_lca(ClassPtr klass); - NodeRecalc(tinf::Node *node, tinf::TypeInferer *inferer); + NodeRecalc(tinf::Node* node, tinf::TypeInferer* inferer); virtual ~NodeRecalc() = default; - NodeRecalc(const NodeRecalc &) = delete; - NodeRecalc &operator=(const NodeRecalc &) = delete; + NodeRecalc(const NodeRecalc&) = delete; + NodeRecalc& operator=(const NodeRecalc&) = delete; void on_changed(); virtual bool auto_edge_flag(); virtual void do_recalc() = 0; - virtual void on_new_type_became_tpError(const TypeData *because_of_type, const RValue &because_of_rvalue); + virtual void on_new_type_became_tpError(const TypeData* because_of_type, const RValue& because_of_rvalue); void run(); }; diff --git a/compiler/inferring/node.cpp b/compiler/inferring/node.cpp index 42ef98839a..1e86e33b45 100644 --- a/compiler/inferring/node.cpp +++ b/compiler/inferring/node.cpp @@ -13,13 +13,13 @@ std::string Node::as_human_readable() const { return type_->as_human_readable(false); } -void Node::register_edge_from_this(const tinf::Edge *edge) { - AutoLocker locker(this); +void Node::register_edge_from_this(const tinf::Edge* edge) { + AutoLocker locker(this); edges_from_this_.emplace_front(edge); } -void Node::register_edge_to_this(const tinf::Edge *edge) { - AutoLocker locker(this); +void Node::register_edge_to_this(const tinf::Edge* edge) { + AutoLocker locker(this); edges_to_this_.emplace_front(edge); } @@ -27,28 +27,28 @@ bool Node::try_start_recalc() { while (true) { int recalc_state_copy = recalc_state_; int once_finished_flag = recalc_state_copy & recalc_bit_at_least_once; - switch (recalc_state_copy & 15) { // preserve bit 16 in transformations - case recalc_st_waiting: - if (__sync_bool_compare_and_swap(&recalc_state_, recalc_st_waiting | once_finished_flag, recalc_st_need_relaunch | once_finished_flag)) { - return true; - } - break; - case recalc_st_processing: - if (__sync_bool_compare_and_swap(&recalc_state_, recalc_st_processing | once_finished_flag, recalc_st_need_relaunch | once_finished_flag)) { - return false; - } - break; - case recalc_st_need_relaunch: + switch (recalc_state_copy & 15) { // preserve bit 16 in transformations + case recalc_st_waiting: + if (__sync_bool_compare_and_swap(&recalc_state_, recalc_st_waiting | once_finished_flag, recalc_st_need_relaunch | once_finished_flag)) { + return true; + } + break; + case recalc_st_processing: + if (__sync_bool_compare_and_swap(&recalc_state_, recalc_st_processing | once_finished_flag, recalc_st_need_relaunch | once_finished_flag)) { return false; - default: - assert (0); + } + break; + case recalc_st_need_relaunch: + return false; + default: + assert(0); } } return false; } void Node::start_recalc() { - int once_finished_flag = recalc_state_ & recalc_bit_at_least_once; // preserve bit 16 in transformation + int once_finished_flag = recalc_state_ & recalc_bit_at_least_once; // preserve bit 16 in transformation bool swapped = __sync_bool_compare_and_swap(&recalc_state_, recalc_st_need_relaunch | once_finished_flag, recalc_st_processing | once_finished_flag); kphp_assert(swapped); } @@ -56,26 +56,26 @@ void Node::start_recalc() { bool Node::try_finish_recalc() { while (true) { int recalc_state_copy = recalc_state_; - switch (recalc_state_copy) { // always set bit 16 in transformations - case recalc_st_processing: - if (__sync_bool_compare_and_swap(&recalc_state_, recalc_st_processing, recalc_st_waiting | recalc_bit_at_least_once)) { - return true; - } - break; - case recalc_st_processing | recalc_bit_at_least_once: - if (__sync_bool_compare_and_swap(&recalc_state_, recalc_st_processing | recalc_bit_at_least_once, recalc_st_waiting | recalc_bit_at_least_once)) { - return true; - } - break; - case recalc_st_need_relaunch: - if (__sync_bool_compare_and_swap(&recalc_state_, recalc_st_need_relaunch, recalc_st_need_relaunch | recalc_bit_at_least_once)) { - return false; // false here, unlike above, but like below - } - break; - case recalc_st_need_relaunch | recalc_bit_at_least_once: - return false; - default: - assert (0); + switch (recalc_state_copy) { // always set bit 16 in transformations + case recalc_st_processing: + if (__sync_bool_compare_and_swap(&recalc_state_, recalc_st_processing, recalc_st_waiting | recalc_bit_at_least_once)) { + return true; + } + break; + case recalc_st_processing | recalc_bit_at_least_once: + if (__sync_bool_compare_and_swap(&recalc_state_, recalc_st_processing | recalc_bit_at_least_once, recalc_st_waiting | recalc_bit_at_least_once)) { + return true; + } + break; + case recalc_st_need_relaunch: + if (__sync_bool_compare_and_swap(&recalc_state_, recalc_st_need_relaunch, recalc_st_need_relaunch | recalc_bit_at_least_once)) { + return false; // false here, unlike above, but like below + } + break; + case recalc_st_need_relaunch | recalc_bit_at_least_once: + return false; + default: + assert(0); } } return false; diff --git a/compiler/inferring/node.h b/compiler/inferring/node.h index 84e1e9bd80..0c4b333484 100644 --- a/compiler/inferring/node.h +++ b/compiler/inferring/node.h @@ -4,12 +4,12 @@ #pragma once -#include #include +#include #include "compiler/debug.h" -#include "compiler/location.h" #include "compiler/inferring/type-data.h" +#include "compiler/location.h" #include "compiler/threading/locks.h" namespace tinf { @@ -19,13 +19,15 @@ class Edge; class TypeInferer; class Node : public Lockable { - DEBUG_STRING_METHOD { return as_human_readable(); } + DEBUG_STRING_METHOD { + return as_human_readable(); + } private: // this list contains edges from=this to=other - std::forward_list edges_from_this_; + std::forward_list edges_from_this_; // this list contains edges to=this from=other - std::forward_list edges_to_this_; + std::forward_list edges_to_this_; // using forward_list here is a bit-bit slower than vector, but takes considerably less memory // these two lists are separate variables, as joining them into one list causes negative performance impact @@ -39,17 +41,15 @@ class Node : public Lockable { recalc_bit_at_least_once = 16, }; - const TypeData *type_{TypeData::get_type(tp_any)}; + const TypeData* type_{TypeData::get_type(tp_any)}; // this field is a finite-state automation for multithreading synchronization, see enum above // if should be placed here (after TypeData*) to make it join with the next int field in memory int recalc_state_{recalc_st_waiting}; public: - - int isset_flags{0}; // ifi bitmask, see get_ifi_id(): for example, when is_integer($a) then node of $a has this flags - int isset_was{0}; // used to find "result may differ from PHP" error, see RestrictionIsset - + int isset_flags{0}; // ifi bitmask, see get_ifi_id(): for example, when is_integer($a) then node of $a has this flags + int isset_was{0}; // used to find "result may differ from PHP" error, see RestrictionIsset std::string as_human_readable() const; @@ -61,14 +61,14 @@ class Node : public Lockable { return recalc_state_ >= recalc_bit_at_least_once; } - void register_edge_from_this(const tinf::Edge *edge); - void register_edge_to_this(const tinf::Edge *edge); + void register_edge_from_this(const tinf::Edge* edge); + void register_edge_to_this(const tinf::Edge* edge); - const std::forward_list &get_edges_from_this() const { + const std::forward_list& get_edges_from_this() const { return edges_from_this_; } - const std::forward_list &get_edges_to_this() const { + const std::forward_list& get_edges_to_this() const { return edges_to_this_; } @@ -76,17 +76,17 @@ class Node : public Lockable { void start_recalc(); bool try_finish_recalc(); - const TypeData *get_type() const { + const TypeData* get_type() const { return type_; } - void set_type(const TypeData *type) { + void set_type(const TypeData* type) { type_ = type; } - virtual void recalc(TypeInferer *inferer) = 0; + virtual void recalc(TypeInferer* inferer) = 0; virtual std::string get_description() = 0; - virtual const Location &get_location() const = 0; + virtual const Location& get_location() const = 0; }; } // namespace tinf diff --git a/compiler/inferring/primitive-type.cpp b/compiler/inferring/primitive-type.cpp index c8c73a95e9..364e99f713 100644 --- a/compiler/inferring/primitive-type.cpp +++ b/compiler/inferring/primitive-type.cpp @@ -9,31 +9,51 @@ #include "common/algorithms/find.h" -#include "compiler/stage.h" #include "compiler/compiler-core.h" +#include "compiler/stage.h" -const char *ptype_name(PrimitiveType id) { +const char* ptype_name(PrimitiveType id) { switch (id) { - case tp_any: return "any"; - case tp_Null: return "Null"; - case tp_False: return "False"; - case tp_bool: return "bool"; - case tp_int: return "int"; - case tp_float: return "float"; - case tp_array: return "array"; - case tp_string: return "string"; - case tp_tmp_string: return "tmp_string"; - case tp_mixed: return "mixed"; - case tp_tuple: return "tuple"; - case tp_shape: return "shape"; - case tp_future: return "future"; - case tp_future_queue: return "future_queue"; - case tp_regexp: return G->is_output_mode_k2() ? "kphp::regex::regexp" : "regexp"; - case tp_Class: return "Class"; - case tp_object: return "object"; - case tp_void: return "void"; - case tp_Error: return "Error"; - case ptype_size: kphp_fail(); + case tp_any: + return "any"; + case tp_Null: + return "Null"; + case tp_False: + return "False"; + case tp_bool: + return "bool"; + case tp_int: + return "int"; + case tp_float: + return "float"; + case tp_array: + return "array"; + case tp_string: + return "string"; + case tp_tmp_string: + return "tmp_string"; + case tp_mixed: + return "mixed"; + case tp_tuple: + return "tuple"; + case tp_shape: + return "shape"; + case tp_future: + return "future"; + case tp_future_queue: + return "future_queue"; + case tp_regexp: + return G->is_output_mode_k2() ? "kphp::regex::regexp" : "regexp"; + case tp_Class: + return "Class"; + case tp_object: + return "object"; + case tp_void: + return "void"; + case tp_Error: + return "Error"; + case ptype_size: + kphp_fail(); } kphp_fail(); } diff --git a/compiler/inferring/primitive-type.h b/compiler/inferring/primitive-type.h index 67bf393ad0..86f4a49085 100644 --- a/compiler/inferring/primitive-type.h +++ b/compiler/inferring/primitive-type.h @@ -4,7 +4,7 @@ #pragma once -// Order is important. These values are compared with operator< +// Order is important. These values are compared with operator< // in some passes (in type inferring, for example) enum PrimitiveType { tp_any, @@ -29,8 +29,7 @@ enum PrimitiveType { ptype_size }; -const char *ptype_name(PrimitiveType id); +const char* ptype_name(PrimitiveType id); PrimitiveType type_lca(PrimitiveType a, PrimitiveType b); bool can_store_false(PrimitiveType tp); bool can_store_null(PrimitiveType tp); - diff --git a/compiler/inferring/public.cpp b/compiler/inferring/public.cpp index 567392c4ce..5a20596283 100644 --- a/compiler/inferring/public.cpp +++ b/compiler/inferring/public.cpp @@ -10,7 +10,7 @@ namespace tinf { -Node *get_tinf_node(FunctionPtr function, int param_i) { +Node* get_tinf_node(FunctionPtr function, int param_i) { if (param_i == -1) { return &function->tinf_node; } @@ -19,35 +19,35 @@ Node *get_tinf_node(FunctionPtr function, int param_i) { return &function->param_ids[param_i]->tinf_node; } -Node *get_tinf_node(VertexPtr vertex) { +Node* get_tinf_node(VertexPtr vertex) { return &vertex->tinf_node; } -Node *get_tinf_node(VarPtr vertex) { +Node* get_tinf_node(VarPtr vertex) { return &vertex->tinf_node; } -TypeInferer *get_inferer() { +TypeInferer* get_inferer() { static TypeInferer inferer; return &inferer; } -inline const TypeData *get_type_impl(Node *node) { +inline const TypeData* get_type_impl(Node* node) { if (!node->was_recalc_started_at_least_once()) { get_inferer()->run_node(node); } return node->get_type(); } -const TypeData *get_type(VertexPtr vertex) { +const TypeData* get_type(VertexPtr vertex) { return get_type_impl(get_tinf_node(vertex)); } -const TypeData *get_type(VarPtr var) { +const TypeData* get_type(VarPtr var) { return get_type_impl(get_tinf_node(var)); } -const TypeData *get_type(FunctionPtr function, int param_i) { +const TypeData* get_type(FunctionPtr function, int param_i) { return get_type_impl(get_tinf_node(function, param_i)); } diff --git a/compiler/inferring/public.h b/compiler/inferring/public.h index 59dcc86279..155541e8da 100644 --- a/compiler/inferring/public.h +++ b/compiler/inferring/public.h @@ -12,13 +12,13 @@ namespace tinf { -tinf::Node *get_tinf_node(VertexPtr vertex); -tinf::Node *get_tinf_node(VarPtr vertex); -tinf::Node *get_tinf_node(FunctionPtr function, int param_i); +tinf::Node* get_tinf_node(VertexPtr vertex); +tinf::Node* get_tinf_node(VarPtr vertex); +tinf::Node* get_tinf_node(FunctionPtr function, int param_i); -tinf::TypeInferer *get_inferer(); -const TypeData *get_type(VertexPtr vertex); -const TypeData *get_type(VarPtr var); -const TypeData *get_type(FunctionPtr function, int param_i); +tinf::TypeInferer* get_inferer(); +const TypeData* get_type(VertexPtr vertex); +const TypeData* get_type(VarPtr var); +const TypeData* get_type(FunctionPtr function, int param_i); } // namespace tinf diff --git a/compiler/inferring/restriction-base.h b/compiler/inferring/restriction-base.h index 8813c90251..02af1db59a 100644 --- a/compiler/inferring/restriction-base.h +++ b/compiler/inferring/restriction-base.h @@ -12,10 +12,12 @@ class RestrictionBase { public: virtual ~RestrictionBase() = default; - RestrictionBase() : - location(stage::get_location()) {} + RestrictionBase() + : location(stage::get_location()) {} - const Location &get_location() const { return location; } + const Location& get_location() const { + return location; + } virtual bool is_restriction_broken() = 0; virtual std::string get_description() = 0; diff --git a/compiler/inferring/restriction-isset.cpp b/compiler/inferring/restriction-isset.cpp index f19740e0af..0f17031b53 100644 --- a/compiler/inferring/restriction-isset.cpp +++ b/compiler/inferring/restriction-isset.cpp @@ -4,8 +4,8 @@ #include "compiler/inferring/restriction-isset.h" -#include "compiler/data/var-data.h" #include "compiler/data/function-data.h" +#include "compiler/data/var-data.h" #include "compiler/inferring/edge.h" #include "compiler/inferring/expr-node.h" #include "compiler/inferring/ifi.h" @@ -14,30 +14,29 @@ #include "compiler/inferring/var-node.h" #include "compiler/vertex.h" -RestrictionIsset::RestrictionIsset(tinf::Node *a) : - a_(a) { - //empty +RestrictionIsset::RestrictionIsset(tinf::Node* a) + : a_(a) { + // empty } std::string RestrictionIsset::get_description() { return desc; } - -void RestrictionIsset::find_dangerous_isset_warning(std::vector *bt, tinf::Node *node, const std::string &msg __attribute__((unused))) { +void RestrictionIsset::find_dangerous_isset_warning(std::vector* bt, tinf::Node* node, const std::string& msg __attribute__((unused))) { desc = "isset, !==, ===, is_array or similar function result may differ from PHP\n"; desc += " Probably, this happened because " + node->get_description(); desc += " can't be null in KPHP, while it can be in PHP\n Chain of assignments:\n"; bt->emplace_back(node); - for (auto *const n : *bt) { + for (auto* const n : *bt) { desc += " "; desc += n->get_description(); desc += "\n"; } } -bool RestrictionIsset::isset_is_dangerous(int isset_flags, const TypeData *tp) { +bool RestrictionIsset::isset_is_dangerous(int isset_flags, const TypeData* tp) { if (tp->use_optional()) { return false; } @@ -50,55 +49,53 @@ bool RestrictionIsset::isset_is_dangerous(int isset_flags, const TypeData *tp) { int check_mask = ifi_is_null; switch (ptp) { - case tp_array: { - check_mask |= ifi_is_array; - break; - } - case tp_bool: { - check_mask |= ifi_is_scalar | ifi_is_bool | ifi_is_false; - break; - } - case tp_int: { - check_mask |= ifi_is_scalar | ifi_is_numeric | ifi_is_integer; - break; - } - case tp_float: { - check_mask |= ifi_is_scalar | ifi_is_numeric | ifi_is_float; - break; - } - case tp_string: { - check_mask |= ifi_is_scalar | ifi_is_string; - break; - } - default: { - check_mask = 0; - break; - } + case tp_array: { + check_mask |= ifi_is_array; + break; + } + case tp_bool: { + check_mask |= ifi_is_scalar | ifi_is_bool | ifi_is_false; + break; + } + case tp_int: { + check_mask |= ifi_is_scalar | ifi_is_numeric | ifi_is_integer; + break; + } + case tp_float: { + check_mask |= ifi_is_scalar | ifi_is_numeric | ifi_is_float; + break; + } + case tp_string: { + check_mask |= ifi_is_scalar | ifi_is_string; + break; + } + default: { + check_mask = 0; + break; + } } return (isset_flags & check_mask) != 0; } -bool RestrictionIsset::find_dangerous_isset_dfs(int isset_flags, tinf::Node *node, - std::vector *bt) { +bool RestrictionIsset::find_dangerous_isset_dfs(int isset_flags, tinf::Node* node, std::vector* bt) { if ((node->isset_was & isset_flags) == isset_flags) { return false; } node->isset_was |= isset_flags; - tinf::TypeNode *type_node = dynamic_cast (node); + tinf::TypeNode* type_node = dynamic_cast(node); if (type_node != nullptr) { return false; } - tinf::ExprNode *expr_node = dynamic_cast (node); + tinf::ExprNode* expr_node = dynamic_cast(node); if (expr_node != nullptr) { VertexPtr v = expr_node->get_expr(); if (v->type() == op_index) { - const auto *type = tinf::get_type(v.as()->array()); + const auto* type = tinf::get_type(v.as()->array()); // check all indexing operations except shapes and tuples, // unless the tuple is used in array context (so it may lead to the same side effects as array indexing) - bool should_check = type->ptype() != tp_shape && - (type->ptype() != tp_tuple || type->tuple_as_array_flag()); + bool should_check = type->ptype() != tp_shape && (type->ptype() != tp_tuple || type->tuple_as_array_flag()); if (should_check && isset_is_dangerous(isset_flags, node->get_type())) { node->isset_was = -1; find_dangerous_isset_warning(bt, node, "[index]"); @@ -135,25 +132,24 @@ bool RestrictionIsset::find_dangerous_isset_dfs(int isset_flags, tinf::Node *nod return false; } - tinf::VarNode *var_node = dynamic_cast (node); + tinf::VarNode* var_node = dynamic_cast(node); if (var_node != nullptr) { VarPtr from_var = var_node->get_var(); - for (const tinf::Edge *e : var_node->get_edges_from_this()) { + for (const tinf::Edge* e : var_node->get_edges_from_this()) { if (e->from_at->begin() != e->from_at->end()) { continue; } - tinf::Node *to_node = e->to; + tinf::Node* to_node = e->to; /*** function f(&$a){}; f($b) fix ***/ if (from_var) { VarPtr to_var; - tinf::VarNode *to_var_node = dynamic_cast (to_node); + tinf::VarNode* to_var_node = dynamic_cast(to_node); if (to_var_node != nullptr) { to_var = to_var_node->get_var(); } - if (to_var && to_var->type() == VarData::var_param_t && - !(to_var->holder_func == from_var->holder_func)) { + if (to_var && to_var->type() == VarData::var_param_t && !(to_var->holder_func == from_var->holder_func)) { continue; } } @@ -170,6 +166,6 @@ bool RestrictionIsset::find_dangerous_isset_dfs(int isset_flags, tinf::Node *nod } bool RestrictionIsset::is_restriction_broken() { - std::vector bt; + std::vector bt; return find_dangerous_isset_dfs(a_->isset_flags, a_, &bt); } diff --git a/compiler/inferring/restriction-isset.h b/compiler/inferring/restriction-isset.h index aeb41b7da2..37c0b93bc1 100644 --- a/compiler/inferring/restriction-isset.h +++ b/compiler/inferring/restriction-isset.h @@ -8,16 +8,15 @@ #include "compiler/inferring/restriction-base.h" class RestrictionIsset : public tinf::RestrictionBase { - tinf::Node *a_; + tinf::Node* a_; std::string desc; - void find_dangerous_isset_warning(std::vector *bt, tinf::Node *node, const std::string &msg); - bool isset_is_dangerous(int isset_flags, const TypeData *tp); - bool find_dangerous_isset_dfs(int isset_flags, tinf::Node *node, std::vector *bt); + void find_dangerous_isset_warning(std::vector* bt, tinf::Node* node, const std::string& msg); + bool isset_is_dangerous(int isset_flags, const TypeData* tp); + bool find_dangerous_isset_dfs(int isset_flags, tinf::Node* node, std::vector* bt); public: - - explicit RestrictionIsset(tinf::Node *a); + explicit RestrictionIsset(tinf::Node* a); bool is_restriction_broken() final; std::string get_description() final; diff --git a/compiler/inferring/restriction-match-phpdoc.cpp b/compiler/inferring/restriction-match-phpdoc.cpp index 6820304c39..f517b94f4b 100644 --- a/compiler/inferring/restriction-match-phpdoc.cpp +++ b/compiler/inferring/restriction-match-phpdoc.cpp @@ -17,12 +17,12 @@ // see comments in var-node.cpp and collect-main-edges.cpp -RestrictionMatchPhpdoc::RestrictionMatchPhpdoc(tinf::VarNode *restricted_node, tinf::Node *actual_node, const TypeData *expected_type) - : restricted_node(restricted_node) - , actual_node(actual_node) - , expected_type(expected_type) { +RestrictionMatchPhpdoc::RestrictionMatchPhpdoc(tinf::VarNode* restricted_node, tinf::Node* actual_node, const TypeData* expected_type) + : restricted_node(restricted_node), + actual_node(actual_node), + expected_type(expected_type) { - if (auto *as_expr = dynamic_cast(actual_node)) { + if (auto* as_expr = dynamic_cast(actual_node)) { location = as_expr->get_expr()->location; } // else will be stage location by default @@ -39,61 +39,61 @@ std::string RestrictionMatchPhpdoc::get_description() { switch (detect_usage_context()) { - case usage_pass_to_argument: { - VarPtr arg = restricted_node->var_; - std::string arg_name = arg->as_human_readable(); - std::string function_name = arg->holder_func->as_human_readable(); + case usage_pass_to_argument: { + VarPtr arg = restricted_node->var_; + std::string arg_name = arg->as_human_readable(); + std::string function_name = arg->holder_func->as_human_readable(); - desc += "pass " + actual_str + " to argument " + arg_name + " of " + function_name + "\n"; - desc += "but it's declared as @param " + expected_str + "\n"; - break; - } + desc += "pass " + actual_str + " to argument " + arg_name + " of " + function_name + "\n"; + desc += "but it's declared as @param " + expected_str + "\n"; + break; + } - case usage_assign_to_variable: { - std::string var_name = restricted_node->var_->as_human_readable(); + case usage_assign_to_variable: { + std::string var_name = restricted_node->var_->as_human_readable(); - desc += "assign " + actual_str + " to " + var_name + "\n"; - desc += "but it's declared as @var " + expected_str + "\n"; - break; - } + desc += "assign " + actual_str + " to " + var_name + "\n"; + desc += "but it's declared as @var " + expected_str + "\n"; + break; + } - case usage_assign_to_argument: { - std::string arg_name = restricted_node->var_->as_human_readable(); + case usage_assign_to_argument: { + std::string arg_name = restricted_node->var_->as_human_readable(); - desc += "assign " + actual_str + " to " + arg_name + ", modifying a function argument" + "\n"; - desc += "but it's declared as @param " + expected_str + "\n"; - break; - } + desc += "assign " + actual_str + " to " + arg_name + ", modifying a function argument" + "\n"; + desc += "but it's declared as @param " + expected_str + "\n"; + break; + } - case usage_assign_to_array_index: { - std::string var_name = restricted_node->var_->as_human_readable(); + case usage_assign_to_array_index: { + std::string var_name = restricted_node->var_->as_human_readable(); - desc += "insert " + actual_str + " into " + var_name + "[]\n"; - desc += "but it's declared as @var " + expected_str + "\n"; - break; - } + desc += "insert " + actual_str + " into " + var_name + "[]\n"; + desc += "but it's declared as @var " + expected_str + "\n"; + break; + } - case usage_return_from_function: { - std::string function_name = restricted_node->function_->as_human_readable(false); + case usage_return_from_function: { + std::string function_name = restricted_node->function_->as_human_readable(false); - desc += "return " + actual_str + " from " + function_name + "\n"; - desc += "but it's declared as @return " + expected_str + "\n"; - break; - } + desc += "return " + actual_str + " from " + function_name + "\n"; + desc += "but it's declared as @return " + expected_str + "\n"; + break; + } - case usage_return_from_callback: { - std::string function_name = restricted_node->function_->as_human_readable(false); + case usage_return_from_callback: { + std::string function_name = restricted_node->function_->as_human_readable(false); - desc += "return " + actual_str + " from " + function_name + "\n"; - desc += "but a callback was expected to return " + expected_str + "\n"; - break; - } + desc += "return " + actual_str + " from " + function_name + "\n"; + desc += "but a callback was expected to return " + expected_str + "\n"; + break; + } - default: { - desc += "some strange usage, couldn't detect\n"; - desc += "expected " + expected_str + ", actual " + actual_str + "\n"; - break; - } + default: { + desc += "some strange usage, couldn't detect\n"; + desc += "expected " + expected_str + ", actual " + actual_str + "\n"; + break; + } } RestrictionStacktraceFinder stacktrace_finder(actual_node, expected_type); @@ -107,7 +107,7 @@ RestrictionMatchPhpdoc::UsageContext RestrictionMatchPhpdoc::detect_usage_contex // it may be a function call: function f(array $arg) {...} f(3) // or it may be modification of an argument inside the function: function f(array $v) { $v++ } // this heuristics seems to work unless a function calls itself recursively - const auto *as_expr_node = dynamic_cast(actual_node); + const auto* as_expr_node = dynamic_cast(actual_node); if (as_expr_node && as_expr_node->get_expr()->location.function == restricted_node->var_->holder_func) { return usage_assign_to_argument; } @@ -122,7 +122,7 @@ RestrictionMatchPhpdoc::UsageContext RestrictionMatchPhpdoc::detect_usage_contex } if (restricted_node->is_variable()) { - for (const tinf::Edge *e : actual_node->get_edges_to_this()) { + for (const tinf::Edge* e : actual_node->get_edges_to_this()) { if (e->from == restricted_node && e->from_at && !e->from_at->empty()) { return usage_assign_to_array_index; } diff --git a/compiler/inferring/restriction-match-phpdoc.h b/compiler/inferring/restriction-match-phpdoc.h index aa77dd1c14..ac9fe4af14 100644 --- a/compiler/inferring/restriction-match-phpdoc.h +++ b/compiler/inferring/restriction-match-phpdoc.h @@ -5,13 +5,13 @@ #pragma once #include "compiler/inferring/multi-key.h" -#include "compiler/inferring/var-node.h" #include "compiler/inferring/restriction-base.h" +#include "compiler/inferring/var-node.h" class RestrictionMatchPhpdoc : public tinf::RestrictionBase { - tinf::VarNode *restricted_node; - tinf::Node *actual_node; - const TypeData *expected_type; + tinf::VarNode* restricted_node; + tinf::Node* actual_node; + const TypeData* expected_type; // this enum is used for better error descriptions enum UsageContext { @@ -27,8 +27,7 @@ class RestrictionMatchPhpdoc : public tinf::RestrictionBase { UsageContext detect_usage_context(); public: - - RestrictionMatchPhpdoc(tinf::VarNode *restricted_node, tinf::Node *actual_node, const TypeData *expected_type); + RestrictionMatchPhpdoc(tinf::VarNode* restricted_node, tinf::Node* actual_node, const TypeData* expected_type); bool is_restriction_broken() final; std::string get_description() final; diff --git a/compiler/inferring/restriction-non-void.cpp b/compiler/inferring/restriction-non-void.cpp index 65ef5aa971..2738e795b8 100644 --- a/compiler/inferring/restriction-non-void.cpp +++ b/compiler/inferring/restriction-non-void.cpp @@ -8,14 +8,15 @@ #include "compiler/inferring/type-data.h" #include "compiler/inferring/var-node.h" -RestrictionNonVoid::RestrictionNonVoid(tinf::Node *node) : node(node) {} +RestrictionNonVoid::RestrictionNonVoid(tinf::Node* node) + : node(node) {} bool RestrictionNonVoid::is_restriction_broken() { return node->get_type()->ptype() == tp_void; } std::string RestrictionNonVoid::get_description() { - const auto *as_var_node = dynamic_cast(node); + const auto* as_var_node = dynamic_cast(node); if (as_var_node && as_var_node->is_return_value_from_function()) { return as_var_node->function_->as_human_readable() + " should return something, but it is void"; } diff --git a/compiler/inferring/restriction-non-void.h b/compiler/inferring/restriction-non-void.h index 8e4c9bebea..477e748518 100644 --- a/compiler/inferring/restriction-non-void.h +++ b/compiler/inferring/restriction-non-void.h @@ -8,11 +8,10 @@ #include "compiler/inferring/restriction-base.h" class RestrictionNonVoid : public tinf::RestrictionBase { - tinf::Node *node; + tinf::Node* node; public: - - explicit RestrictionNonVoid(tinf::Node *node); + explicit RestrictionNonVoid(tinf::Node* node); bool is_restriction_broken() final; std::string get_description() final; diff --git a/compiler/inferring/restriction-stacktrace-finder.cpp b/compiler/inferring/restriction-stacktrace-finder.cpp index f7df4b261b..7279b3a199 100644 --- a/compiler/inferring/restriction-stacktrace-finder.cpp +++ b/compiler/inferring/restriction-stacktrace-finder.cpp @@ -8,15 +8,15 @@ #include "common/algorithms/string-algorithms.h" #include "common/termformat/termformat.h" -#include "compiler/data/src-file.h" #include "compiler/data/function-data.h" +#include "compiler/data/src-file.h" #include "compiler/inferring/edge.h" #include "compiler/inferring/public.h" #include "compiler/inferring/type-node.h" #include "compiler/inferring/var-node.h" #include "compiler/type-hint.h" -#include "compiler/vertex.h" #include "compiler/vertex-util.h" +#include "compiler/vertex.h" /* This module finds a stacktrace to describe, why a type mismatch occurred. @@ -33,7 +33,7 @@ * when mixed is a result of non-mixed operands, we actually trace into only one operand we find the most important */ -RestrictionStacktraceFinder::RestrictionStacktraceFinder(tinf::Node *cur_node, const TypeData *expected_type) { +RestrictionStacktraceFinder::RestrictionStacktraceFinder(tinf::Node* cur_node, const TypeData* expected_type) { assert(cur_node != nullptr); find_call_trace_with_error(cur_node, expected_type); @@ -42,11 +42,11 @@ RestrictionStacktraceFinder::RestrictionStacktraceFinder(tinf::Node *cur_node, c std::reverse(stacktrace.begin(), stacktrace.end()); } -VarPtr RestrictionStacktraceFinder::get_var_id_from_node(const tinf::Node *node) { - if (const auto *as_var_node = dynamic_cast(node)) { +VarPtr RestrictionStacktraceFinder::get_var_id_from_node(const tinf::Node* node) { + if (const auto* as_var_node = dynamic_cast(node)) { return as_var_node->var_; } - if (const auto *as_expr_node = dynamic_cast(node)) { + if (const auto* as_expr_node = dynamic_cast(node)) { if (as_expr_node->get_expr()->type() == op_var) { return as_expr_node->get_expr().as()->var_id; } @@ -59,31 +59,31 @@ VarPtr RestrictionStacktraceFinder::get_var_id_from_node(const tinf::Node *node) // for example, when we are searching for why $a is float, and we have { $a = 4.5; $a = $v; } and $v is float, // then $v is a more important reason than 4.5, as we want to see, why $v also occurred float, not just stop at 4.5 // so, a variable is more important than a constant, a func call is more important that assigning an array, and other heuristics -int RestrictionStacktraceFinder::get_importance_of_reason(const tinf::Node *from, const tinf::Node *to) { - if (dynamic_cast(to)) { +int RestrictionStacktraceFinder::get_importance_of_reason(const tinf::Node* from, const tinf::Node* to) { + if (dynamic_cast(to)) { return 0; } - if (dynamic_cast(to)) { + if (dynamic_cast(to)) { return 0; } - VertexPtr expr = VertexUtil::get_actual_value(dynamic_cast(to)->get_expr()); + VertexPtr expr = VertexUtil::get_actual_value(dynamic_cast(to)->get_expr()); switch (expr->type()) { - case op_var: - return get_var_id_from_node(to) == get_var_id_from_node(from) ? 4 : 5; - case op_func_call: - return expr->get_string() == "make_clone" ? 4 : 3; - case op_array: - return 2; - case op_float_const: - case op_int_const: - case op_string: - case op_true: - case op_false: - case op_null: - return 0; - default: - return 1; + case op_var: + return get_var_id_from_node(to) == get_var_id_from_node(from) ? 4 : 5; + case op_func_call: + return expr->get_string() == "make_clone" ? 4 : 3; + case op_array: + return 2; + case op_float_const: + case op_int_const: + case op_string: + case op_true: + case op_false: + case op_null: + return 0; + default: + return 1; } } @@ -91,44 +91,43 @@ int RestrictionStacktraceFinder::get_importance_of_reason(const tinf::Node *from // then we continue dfs starting from the highest priority // this priority is now well this edge answers the question "how did from->type occur, why is it not expected_type?" // for example, if from is mixed and to is mixed, it's the best answer: further we'll have to find out why to is mixed -int RestrictionStacktraceFinder::get_priority(const tinf::Edge *edge, const TypeData *expected_type) { - const TypeData *from_type = edge->from->get_type(); - const TypeData *to_type = edge->to->get_type(); +int RestrictionStacktraceFinder::get_priority(const tinf::Edge* edge, const TypeData* expected_type) { + const TypeData* from_type = edge->from->get_type(); + const TypeData* to_type = edge->to->get_type(); int importance = get_importance_of_reason(edge->from, edge->to); - return are_equal_types(to_type, from_type) ? 300 + importance : - !is_less_or_equal_type(to_type, expected_type, edge->from_at) ? 200 + importance : - is_less_or_equal_type(to_type, from_type, edge->from_at) ? 100 + importance : - importance; + return are_equal_types(to_type, from_type) ? 300 + importance + : !is_less_or_equal_type(to_type, expected_type, edge->from_at) ? 200 + importance + : is_less_or_equal_type(to_type, from_type, edge->from_at) ? 100 + importance + : importance; } // this is the main function to fill the stacktrace field, it's done recursively // on each step, we have all edges pointing from cur_node and sort them by priority // then take the highest priority and find stacktrace pointing to it -bool RestrictionStacktraceFinder::find_call_trace_with_error(tinf::Node *cur_node, const TypeData *expected_type) { +bool RestrictionStacktraceFinder::find_call_trace_with_error(tinf::Node* cur_node, const TypeData* expected_type) { static int limit_calls = 1000000; if (--limit_calls <= 0) { return true; } - std::vector ordered_edges; - for (const tinf::Edge *e : cur_node->get_edges_from_this()) { + std::vector ordered_edges; + for (const tinf::Edge* e : cur_node->get_edges_from_this()) { ordered_edges.emplace_back(e); } - std::sort(ordered_edges.begin(), ordered_edges.end(), [&](const tinf::Edge *a, const tinf::Edge *b) { - return get_priority(a, expected_type) > get_priority(b, expected_type); - }); + std::sort(ordered_edges.begin(), ordered_edges.end(), + [&](const tinf::Edge* a, const tinf::Edge* b) { return get_priority(a, expected_type) > get_priority(b, expected_type); }); if (ordered_edges.empty()) { return true; } - for (const tinf::Edge *e : ordered_edges) { - tinf::Node *to = e->to; + for (const tinf::Edge* e : ordered_edges) { + tinf::Node* to = e->to; kphp_assert(e->from == cur_node && e->to != cur_node); - if (vk::contains(node_path, to) && dynamic_cast(to) == nullptr) { + if (vk::contains(node_path, to) && dynamic_cast(to) == nullptr) { continue; } if (node_path.size() == max_cnt_nodes_in_path) { @@ -137,12 +136,11 @@ bool RestrictionStacktraceFinder::find_call_trace_with_error(tinf::Node *cur_nod node_path.push_back(e->to); - - const TypeData *next_expected_type{nullptr}; + const TypeData* next_expected_type{nullptr}; if (e->from_at) { // inside arrays/tuples next_expected_type = expected_type->const_read_at(*e->from_at); - } else if (auto *as_expr_node = dynamic_cast(e->from)) { - if (as_expr_node->get_expr()->type() == op_index) { // outside arrays + } else if (auto* as_expr_node = dynamic_cast(e->from)) { + if (as_expr_node->get_expr()->type() == op_index) { // outside arrays next_expected_type = TypeData::create_array_of(expected_type); // hard to explain, comment to see a failing test } } @@ -164,17 +162,17 @@ std::string RestrictionStacktraceFinder::get_stacktrace_text() { std::string desc; // to see full development stacktrace, uncomment these lines -// for (tinf::Node *node : stacktrace) -// desc += node->get_description() + "\n"; -// return desc; + // for (tinf::Node *node : stacktrace) + // desc += node->get_description() + "\n"; + // return desc; // here we make stacktrace pretty and human-readable: // don't use internal get_description(), join some combinations of ExprNode+VarNode, skip some technical nodes, etc - const tinf::Node *prev{nullptr}; + const tinf::Node* prev{nullptr}; - auto append_current_php_line_if_changed = [&prev, &desc](const tinf::Node *cur_node) { - const Location &loc = cur_node->get_location(); + auto append_current_php_line_if_changed = [&prev, &desc](const tinf::Node* cur_node) { + const Location& loc = cur_node->get_location(); if (loc.line <= 0 || !loc.file) { desc += " "; return; @@ -193,9 +191,9 @@ std::string RestrictionStacktraceFinder::get_stacktrace_text() { desc += "\n "; }; - for (const tinf::Node *node : stacktrace) { + for (const tinf::Node* node : stacktrace) { - if (const auto *var_node = dynamic_cast(node)) { + if (const auto* var_node = dynamic_cast(node)) { if (var_node->is_argument_of_function()) { FunctionPtr function = var_node->var_->holder_func; auto param = function->get_params()[var_node->param_i].as(); @@ -215,12 +213,11 @@ std::string RestrictionStacktraceFinder::get_stacktrace_text() { continue; } - } else if (const auto *expr_node = dynamic_cast(node)) { + } else if (const auto* expr_node = dynamic_cast(node)) { VertexPtr expr = expr_node->get_expr(); - bool skip = - (expr->type() == op_func_call && expr.as()->func_id->name == "make_clone") || - (expr->type() == op_return && expr.as()->has_expr()) || - (expr->type() == op_var && expr.as()->extra_type == OperationExtra::op_ex_var_const); + bool skip = (expr->type() == op_func_call && expr.as()->func_id->name == "make_clone") || + (expr->type() == op_return && expr.as()->has_expr()) || + (expr->type() == op_var && expr.as()->extra_type == OperationExtra::op_ex_var_const); if (skip) { continue; } @@ -231,14 +228,13 @@ std::string RestrictionStacktraceFinder::get_stacktrace_text() { desc += expr_node->get_type()->as_human_readable(); desc += "\n"; - bool stop = - (expr->type() == op_func_call && expr.as()->func_id->is_constructor()); + bool stop = (expr->type() == op_func_call && expr.as()->func_id->is_constructor()); if (stop) { break; } - } else if (const auto *type_node = dynamic_cast(node)) { - const auto *prev_as_var = dynamic_cast(prev); + } else if (const auto* type_node = dynamic_cast(node)) { + const auto* prev_as_var = dynamic_cast(prev); bool skip = prev_as_var && prev_as_var->type_restriction && are_equal_types(prev_as_var->type_restriction, type_node->get_type()); if (skip) { // then a line above is "... declared that returns T", see create_type_assign_with_restriction() continue; diff --git a/compiler/inferring/restriction-stacktrace-finder.h b/compiler/inferring/restriction-stacktrace-finder.h index 3daabca2e2..a606f2f0fa 100644 --- a/compiler/inferring/restriction-stacktrace-finder.h +++ b/compiler/inferring/restriction-stacktrace-finder.h @@ -11,19 +11,18 @@ class RestrictionStacktraceFinder { static const unsigned long max_cnt_nodes_in_path = 50; - std::vector stacktrace; - std::vector node_path; + std::vector stacktrace; + std::vector node_path; std::string desc; - static VarPtr get_var_id_from_node(const tinf::Node *node); - static int get_importance_of_reason(const tinf::Node *from, const tinf::Node *to); - static int get_priority(const tinf::Edge *edge, const TypeData *expected_type); + static VarPtr get_var_id_from_node(const tinf::Node* node); + static int get_importance_of_reason(const tinf::Node* from, const tinf::Node* to); + static int get_priority(const tinf::Edge* edge, const TypeData* expected_type); - bool find_call_trace_with_error(tinf::Node *cur_node, const TypeData *expected_type); + bool find_call_trace_with_error(tinf::Node* cur_node, const TypeData* expected_type); public: - - RestrictionStacktraceFinder(tinf::Node *cur_node, const TypeData *expected_type); + RestrictionStacktraceFinder(tinf::Node* cur_node, const TypeData* expected_type); std::string get_stacktrace_text(); }; diff --git a/compiler/inferring/rvalue.h b/compiler/inferring/rvalue.h index 607ccf2d27..5d42770c18 100644 --- a/compiler/inferring/rvalue.h +++ b/compiler/inferring/rvalue.h @@ -11,19 +11,17 @@ struct RValue { RValue() = default; - explicit RValue(const TypeData *type, const MultiKey *key = nullptr) : - type(type), - key(key) { - } - - explicit RValue(tinf::Node *node, const MultiKey *key = nullptr) : - node(node), - key(key) { - } - - const TypeData *type{nullptr}; - tinf::Node *node{nullptr}; - const MultiKey *key{nullptr}; + explicit RValue(const TypeData* type, const MultiKey* key = nullptr) + : type(type), + key(key) {} + + explicit RValue(tinf::Node* node, const MultiKey* key = nullptr) + : node(node), + key(key) {} + + const TypeData* type{nullptr}; + tinf::Node* node{nullptr}; + const MultiKey* key{nullptr}; bool drop_or_false{false}; bool drop_or_null{false}; TypeData::FFIRvalueFlags ffi_flags; @@ -59,8 +57,7 @@ inline RValue drop_or_false(RValue rvalue) { return rvalue; } - -inline RValue as_rvalue(VertexPtr v, const MultiKey *key = nullptr) { +inline RValue as_rvalue(VertexPtr v, const MultiKey* key = nullptr) { return RValue(tinf::get_tinf_node(v), key); } @@ -72,14 +69,14 @@ inline RValue as_rvalue(VarPtr var) { return RValue(tinf::get_tinf_node(var)); } -inline RValue as_rvalue(const TypeData *type, const MultiKey *key = nullptr) { +inline RValue as_rvalue(const TypeData* type, const MultiKey* key = nullptr) { return RValue(type, key); } -inline const RValue &as_rvalue(const RValue &rvalue) { +inline const RValue& as_rvalue(const RValue& rvalue) { return rvalue; } -inline RValue as_rvalue(tinf::Node *node, const MultiKey *key = nullptr) { +inline RValue as_rvalue(tinf::Node* node, const MultiKey* key = nullptr) { return RValue(node, key); } diff --git a/compiler/inferring/type-data.cpp b/compiler/inferring/type-data.cpp index 4915ffcdac..b6b49f7420 100644 --- a/compiler/inferring/type-data.cpp +++ b/compiler/inferring/type-data.cpp @@ -4,7 +4,6 @@ #include "compiler/inferring/type-data.h" - #include #include @@ -24,8 +23,8 @@ #include "compiler/threading/hash-table.h" #include "compiler/utils/string-utils.h" -static std::vector primitive_types; -static std::vector array_types; +static std::vector primitive_types; +static std::vector array_types; void TypeData::init_static() { if (!primitive_types.empty()) { @@ -43,19 +42,19 @@ void TypeData::init_static() { } } -const TypeData *TypeData::get_type(PrimitiveType type) { +const TypeData* TypeData::get_type(PrimitiveType type) { return primitive_types[type]; } -const TypeData *TypeData::get_type(PrimitiveType array, PrimitiveType type) { +const TypeData* TypeData::get_type(PrimitiveType array, PrimitiveType type) { if (array != tp_array) { return get_type(array); } return array_types[type]; } -TypeData::TypeData(PrimitiveType ptype) : - ptype_(ptype) { +TypeData::TypeData(PrimitiveType ptype) + : ptype_(ptype) { if (ptype_ == tp_Null) { set_or_null_flag(); ptype_ = tp_any; @@ -66,19 +65,19 @@ TypeData::TypeData(PrimitiveType ptype) : } } -TypeData::TypeData(const TypeData &from) : - ptype_(from.ptype_), - flags_(from.flags_), - indirection_(from.indirection_), - class_type_(from.class_type_), - subkeys(from.subkeys) { - for (auto &subkey : subkeys) { +TypeData::TypeData(const TypeData& from) + : ptype_(from.ptype_), + flags_(from.flags_), + indirection_(from.indirection_), + class_type_(from.class_type_), + subkeys(from.subkeys) { + for (auto& subkey : subkeys) { subkey.second = subkey.second->clone(); } } TypeData::~TypeData() { - for (auto &subkey : subkeys) { + for (auto& subkey : subkeys) { delete subkey.second; } } @@ -87,65 +86,65 @@ std::string TypeData::as_human_readable(bool colored) const { std::string res; switch (ptype_) { - case tp_array: { - const TypeData *inner = lookup_at_any_key() ?: TypeData::get_type(tp_any); - if (inner->get_real_ptype() == tp_any) { - res = "array"; - } else { - std::string inner_str = inner->as_human_readable(false); - res = inner->use_optional() ? "(" + inner_str + ")" + "[]" : inner_str + "[]"; - } - break; - } - case tp_tuple: { - res = "tuple("; - for (int tuple_i = 0; tuple_i < get_tuple_max_index(); ++tuple_i) { - if (tuple_i > 0) { - res += ", "; - } - res += lookup_at(Key::int_key(tuple_i))->as_human_readable(false); - } - res += ")"; - break; + case tp_array: { + const TypeData* inner = lookup_at_any_key() ?: TypeData::get_type(tp_any); + if (inner->get_real_ptype() == tp_any) { + res = "array"; + } else { + std::string inner_str = inner->as_human_readable(false); + res = inner->use_optional() ? "(" + inner_str + ")" + "[]" : inner_str + "[]"; } - case tp_shape: { - std::vector items{lookup_begin(), lookup_end()}; - std::reverse(items.begin(), items.end()); - res = "shape(" + vk::join(items, ", ", [](const SubkeyItem &p) { return p.first.to_string() + ":" + p.second->as_human_readable(false); }); - if (shape_has_varg_flag()) { - res += ", ..."; + break; + } + case tp_tuple: { + res = "tuple("; + for (int tuple_i = 0; tuple_i < get_tuple_max_index(); ++tuple_i) { + if (tuple_i > 0) { + res += ", "; } - res += ")"; - break; - } - case tp_future: { - const TypeData *inner = lookup_at_any_key() ?: TypeData::get_type(tp_any); - res = "future<" + inner->as_human_readable(false) + ">"; - break; + res += lookup_at(Key::int_key(tuple_i))->as_human_readable(false); } - case tp_future_queue: { - const TypeData *inner = lookup_at_any_key() ?: TypeData::get_type(tp_any); - res = "future_queue<" + inner->as_human_readable(false) + ">"; - break; - } - case tp_Class: { - res = class_type()->as_human_readable(); - break; + res += ")"; + break; + } + case tp_shape: { + std::vector items{lookup_begin(), lookup_end()}; + std::reverse(items.begin(), items.end()); + res = "shape(" + vk::join(items, ", ", [](const SubkeyItem& p) { return p.first.to_string() + ":" + p.second->as_human_readable(false); }); + if (shape_has_varg_flag()) { + res += ", ..."; } - case tp_any: { - if (or_null_flag() && !or_false_flag()) { - res = "null"; - } else if (or_false_flag() && !or_null_flag()) { - res += "false"; - } else if (or_false_flag() && or_null_flag()) { - res += "false|null"; - } else { - res = "any"; - } - break; + res += ")"; + break; + } + case tp_future: { + const TypeData* inner = lookup_at_any_key() ?: TypeData::get_type(tp_any); + res = "future<" + inner->as_human_readable(false) + ">"; + break; + } + case tp_future_queue: { + const TypeData* inner = lookup_at_any_key() ?: TypeData::get_type(tp_any); + res = "future_queue<" + inner->as_human_readable(false) + ">"; + break; + } + case tp_Class: { + res = class_type()->as_human_readable(); + break; + } + case tp_any: { + if (or_null_flag() && !or_false_flag()) { + res = "null"; + } else if (or_false_flag() && !or_null_flag()) { + res += "false"; + } else if (or_false_flag() && or_null_flag()) { + res += "false|null"; + } else { + res = "any"; } - default: - res = ptype_name(ptype_); + break; + } + default: + res = ptype_name(ptype_); } if (ptype_ != tp_any) { @@ -168,16 +167,16 @@ std::string TypeData::as_human_readable(bool colored) const { return colored ? TermStringFormat::paint_green(res) : res; } -TypeData *TypeData::at_force(const Key &key) { - kphp_assert_msg (structured(), "bug in TypeData"); +TypeData* TypeData::at_force(const Key& key) { + kphp_assert_msg(structured(), "bug in TypeData"); - for (const auto &subkey : subkeys) { + for (const auto& subkey : subkeys) { if (subkey.first == key) { return subkey.second; } } - TypeData *value = get_type(tp_any)->clone(); + TypeData* value = get_type(tp_any)->clone(); subkeys.emplace_front(key, value); return value; } @@ -198,7 +197,7 @@ bool TypeData::is_ffi_ref() const { return false; } -void TypeData::set_ffi_pointer_type(const TypeData *new_ptr_type, int new_indirection) { +void TypeData::set_ffi_pointer_type(const TypeData* new_ptr_type, int new_indirection) { if (std::distance(new_ptr_type->class_type_.begin(), new_ptr_type->class_type_.end()) != 1) { set_ptype(tp_Error); return; @@ -220,7 +219,7 @@ void TypeData::set_ffi_pointer_type(const TypeData *new_ptr_type, int new_indire return; } - auto *ptr_class = class_type()->ffi_class_mixin; + auto* ptr_class = class_type()->ffi_class_mixin; if (!ptr_class) { set_ptype(tp_Error); @@ -233,7 +232,7 @@ void TypeData::set_ffi_pointer_type(const TypeData *new_ptr_type, int new_indire return; } - auto *new_ptr_class = new_ptr_type->class_type()->ffi_class_mixin; + auto* new_ptr_class = new_ptr_type->class_type()->ffi_class_mixin; if (ptr_class != new_ptr_class) { set_ptype(tp_Error); return; @@ -246,7 +245,7 @@ void TypeData::set_ffi_pointer_type(const TypeData *new_ptr_type, int new_indire } } -void TypeData::set_class_type(const std::forward_list &new_class_type) { +void TypeData::set_class_type(const std::forward_list& new_class_type) { if (new_class_type.empty()) { return; } @@ -255,8 +254,8 @@ void TypeData::set_class_type(const std::forward_list &new_class_type) class_type_ = new_class_type; } else if (!vk::all_of(class_type_, [&](ClassPtr c) { return vk::contains(new_class_type, c); })) { std::unordered_set result_type; - for (const auto &possible_class : class_type_) { - for (const auto &new_class : new_class_type) { + for (const auto& possible_class : class_type_) { + for (const auto& new_class : new_class_type) { auto common_interfaces = possible_class->get_common_base_or_interface(new_class); result_type.insert(common_interfaces.begin(), common_interfaces.end()); } @@ -272,11 +271,11 @@ void TypeData::set_class_type(const std::forward_list &new_class_type) } template -bool TypeData::for_each_deep(const F &visitor) const { +bool TypeData::for_each_deep(const F& visitor) const { if (visitor(*this)) { return true; } - for (const auto &sub_key: subkeys) { + for (const auto& sub_key : subkeys) { if (sub_key.second->for_each_deep(visitor)) { return true; } @@ -288,13 +287,13 @@ bool TypeData::for_each_deep(const F &visitor) const { * Faster alternative for !get_all_class_types_inside().empty() */ bool TypeData::has_class_type_inside() const { - return for_each_deep([](const TypeData &data) { return !data.class_type_.empty(); }); + return for_each_deep([](const TypeData& data) { return !data.class_type_.empty(); }); } void TypeData::mark_classes_used() const { - for_each_deep([](const TypeData &this_) { + for_each_deep([](const TypeData& this_) { if (this_.ptype() == tp_Class) { - for (const auto &klass : this_.class_type_) { + for (const auto& klass : this_.class_type_) { klass->mark_as_used(); } } @@ -302,8 +301,8 @@ void TypeData::mark_classes_used() const { }); } -void TypeData::get_all_class_types_inside(std::unordered_set &out) const { - for_each_deep([&out](const TypeData &this_) { +void TypeData::get_all_class_types_inside(std::unordered_set& out) const { + for_each_deep([&out](const TypeData& this_) { out.insert(this_.class_type_.begin(), this_.class_type_.end()); return false; }); @@ -311,7 +310,7 @@ void TypeData::get_all_class_types_inside(std::unordered_set &out) con ClassPtr TypeData::get_first_class_type_inside() const { ClassPtr first_class; - for_each_deep([&first_class](const TypeData &this_) { + for_each_deep([&first_class](const TypeData& this_) { first_class = this_.class_type(); return first_class; }); @@ -342,11 +341,11 @@ bool TypeData::structured() const { return vk::any_of_equal(ptype(), tp_array, tp_tuple, tp_shape, tp_future, tp_future_queue); } -TypeData *TypeData::clone() const { +TypeData* TypeData::clone() const { return new TypeData(*this); } -const TypeData *TypeData::const_read_at(const Key &key) const { +const TypeData* TypeData::const_read_at(const Key& key) const { if (ptype() == tp_mixed) { return get_type(tp_mixed); } @@ -368,7 +367,7 @@ const TypeData *TypeData::const_read_at(const Key &key) const { return get_type(tp_any); } - const TypeData *res = lookup_at(key); + const TypeData* res = lookup_at(key); if (res == nullptr && !key.is_any_key()) { res = lookup_at_any_key(); } @@ -382,8 +381,8 @@ const TypeData *TypeData::const_read_at(const Key &key) const { return res; } -const TypeData *TypeData::lookup_at(const Key &key) const { - for (const auto &subkey : subkeys) { +const TypeData* TypeData::lookup_at(const Key& key) const { + for (const auto& subkey : subkeys) { if (subkey.first == key) { return subkey.second; } @@ -391,8 +390,8 @@ const TypeData *TypeData::lookup_at(const Key &key) const { return nullptr; } -const TypeData *TypeData::const_read_at(const MultiKey &multi_key) const { - const TypeData *res = this; +const TypeData* TypeData::const_read_at(const MultiKey& multi_key) const { + const TypeData* res = this; for (Key i : multi_key) { res = res->const_read_at(i); } @@ -407,28 +406,28 @@ void TypeData::make_structured() { } } -TypeData *TypeData::write_at(const Key &key) { +TypeData* TypeData::write_at(const Key& key) { make_structured(); if (!structured()) { return nullptr; } - TypeData *res = at_force(key); + TypeData* res = at_force(key); res->set_write_flag(); return res; } -const TypeData *TypeData::get_deepest_type_of_array() const { +const TypeData* TypeData::get_deepest_type_of_array() const { if (ptype() == tp_array) { return lookup_at_any_key()->get_deepest_type_of_array(); } return this; } -void TypeData::set_lca(const TypeData *rhs, bool save_or_false, bool save_or_null, FFIRvalueFlags ffi_flags) { +void TypeData::set_lca(const TypeData* rhs, bool save_or_false, bool save_or_null, FFIRvalueFlags ffi_flags) { if (rhs == nullptr) { return; } - TypeData *lhs = this; + TypeData* lhs = this; PrimitiveType new_ptype = type_lca(lhs->ptype(), rhs->ptype()); if (lhs->ptype_ == tp_array && rhs->ptype_ == tp_Class) { @@ -467,7 +466,7 @@ void TypeData::set_lca(const TypeData *rhs, bool save_or_false, bool save_or_nul lhs->set_flags(new_flags); if (ffi_flags.drop_ref && rhs->is_ffi_ref()) { - auto *new_rhs = rhs->clone(); + auto* new_rhs = rhs->clone(); new_rhs->class_type_ = {rhs->class_type()->ffi_class_mixin->non_ref}; rhs = new_rhs; } @@ -498,7 +497,7 @@ void TypeData::set_lca(const TypeData *rhs, bool save_or_false, bool save_or_nul if (new_ptype == tp_tuple && rhs->ptype() == tp_tuple) { if (!lhs->subkeys.empty() && !rhs->subkeys.empty() && lhs->get_tuple_max_index() != rhs->get_tuple_max_index()) { - lhs->set_ptype(tp_Error); // mixing tuples of different sizes + lhs->set_ptype(tp_Error); // mixing tuples of different sizes return; } } @@ -511,17 +510,17 @@ void TypeData::set_lca(const TypeData *rhs, bool save_or_false, bool save_or_nul bool needs_any_key = vk::any_of_equal(new_ptype, tp_array, tp_future, tp_future_queue); if (needs_any_key) { - lhs->at_force(Key::any_key()); // if didn't exist, became tp_any + lhs->at_force(Key::any_key()); // if didn't exist, became tp_any } if (!rhs->subkeys.empty()) { - for (const auto &rhs_subkey : rhs->subkeys) { + for (const auto& rhs_subkey : rhs->subkeys) { Key rhs_key = rhs_subkey.first; - TypeData *rhs_value = rhs_subkey.second; - TypeData *lhs_value = lhs->at_force(rhs_key); + TypeData* rhs_value = rhs_subkey.second; + TypeData* lhs_value = lhs->at_force(rhs_key); lhs_value->set_lca(rhs_value); } - for (auto &lhs_subkey : lhs->subkeys) { + for (auto& lhs_subkey : lhs->subkeys) { if (!rhs->lookup_at(lhs_subkey.first)) { lhs_subkey.second->set_or_null_flag(); } @@ -529,11 +528,11 @@ void TypeData::set_lca(const TypeData *rhs, bool save_or_false, bool save_or_nul } } -void TypeData::set_lca_at(const MultiKey &multi_key, const TypeData *rhs, bool save_or_false, bool save_or_null, FFIRvalueFlags ffi_flags) { - TypeData *cur = this; - - for (const Key &key : multi_key) { - auto *prev = cur; +void TypeData::set_lca_at(const MultiKey& multi_key, const TypeData* rhs, bool save_or_false, bool save_or_null, FFIRvalueFlags ffi_flags) { + TypeData* cur = this; + + for (const Key& key : multi_key) { + auto* prev = cur; cur = cur->write_at(key); // handle writing to a subkey of mixed (when cur is not structured) if (cur == nullptr) { @@ -558,15 +557,15 @@ void TypeData::set_lca_at(const MultiKey &multi_key, const TypeData *rhs, bool s } cur->set_lca(rhs, save_or_false, save_or_null, ffi_flags); - if (cur->error_flag()) { // proxy tp_Error from keys to the type itself + if (cur->error_flag()) { // proxy tp_Error from keys to the type itself this->set_ptype(tp_Error); } } void TypeData::fix_inf_array() { - //hack: used just to make current version stable + // hack: used just to make current version stable int depth = 0; - const TypeData *cur = this; + const TypeData* cur = this; while (cur != nullptr) { cur = cur->lookup_at_any_key(); depth++; @@ -580,9 +579,9 @@ void TypeData::set_lca(PrimitiveType ptype) { set_lca(TypeData::get_type(ptype)); } -static void append_ffi_type(const TypeData *type, ClassPtr klass, bool boxed, std::string &res) { - auto *as_ffi = klass->ffi_class_mixin; - const auto *key = type->lookup_at_any_key(); +static void append_ffi_type(const TypeData* type, ClassPtr klass, bool boxed, std::string& res) { + auto* as_ffi = klass->ffi_class_mixin; + const auto* key = type->lookup_at_any_key(); if (key) { // CData as FFI array res += "class_instanceget_real_ptype(); switch (tp) { - case tp_Class: { - auto klass = type->class_type(); - if (klass->ffi_class_mixin) { - append_ffi_type(type, klass, true, res); - break; - } - res += "class_instance<"; - res += klass->src_name; - res += ">"; - break; - } - case tp_float: { - res += "double"; - break; - } - case tp_int: { - res += "int64_t"; - break; - } - case tp_tuple: { - res += "std::tuple"; - break; - } - case tp_any: { - res += "Unknown"; - break; - } - default : { - res += ptype_name(tp); + case tp_Class: { + auto klass = type->class_type(); + if (klass->ffi_class_mixin) { + append_ffi_type(type, klass, true, res); break; } + res += "class_instance<"; + res += klass->src_name; + res += ">"; + break; + } + case tp_float: { + res += "double"; + break; + } + case tp_int: { + res += "int64_t"; + break; + } + case tp_tuple: { + res += "std::tuple"; + break; + } + case tp_any: { + res += "Unknown"; + break; + } + default: { + res += ptype_name(tp); + break; + } } } -inline void get_txt_style_type(const TypeData *type, std::string &res) { +inline void get_txt_style_type(const TypeData* type, std::string& res) { const PrimitiveType tp = type->get_real_ptype(); switch (tp) { - case tp_Class: - res += vk::join(type->class_types(), ", ", std::mem_fn(&ClassData::name)); - break; - default : - res += ptype_name(tp); - break; + case tp_Class: + res += vk::join(type->class_types(), ", ", std::mem_fn(&ClassData::name)); + break; + default: + res += ptype_name(tp); + break; } } -static bool try_get_txt_or_false_or_null_for_unknown(const TypeData *type, std::string &res) { +static bool try_get_txt_or_false_or_null_for_unknown(const TypeData* type, std::string& res) { if (type->ptype() == tp_any) { if (type->or_false_flag()) { res += "false"; @@ -687,7 +686,7 @@ static bool try_get_txt_or_false_or_null_for_unknown(const TypeData *type, std:: return false; } -static void get_txt_or_false_or_null(const TypeData *type, std::string &res) { +static void get_txt_or_false_or_null(const TypeData* type, std::string& res) { if (type->use_or_null()) { res += "|null"; } @@ -696,7 +695,7 @@ static void get_txt_or_false_or_null(const TypeData *type, std::string &res) { } } -static void type_out_impl(const TypeData *type, std::string &res, gen_out_style style) { +static void type_out_impl(const TypeData* type, std::string& res, gen_out_style style) { if (style == gen_out_style::txt && try_get_txt_or_false_or_null_for_unknown(type, res)) { return; } @@ -724,8 +723,8 @@ static void type_out_impl(const TypeData *type, std::string &res, gen_out_style if (tp == tp_tuple) { res += "<"; - int size = type->get_tuple_max_index(); // order of keys is undetermined - for (int tuple_i = 0; tuple_i < size; ++tuple_i) { // that's why use loop by indexes + int size = type->get_tuple_max_index(); // order of keys is undetermined + for (int tuple_i = 0; tuple_i < size; ++tuple_i) { // that's why use loop by indexes if (tuple_i > 0) { res += " , "; } @@ -739,10 +738,10 @@ static void type_out_impl(const TypeData *type, std::string &res, gen_out_style // we emit the shape keys sorted by their key hashes to get the stable code generation // Note: key ids can vary between the compiler runs, so they can't be used for sorting // Note: this order is used during the shape construction, see compile_shape() - std::vector> sorted_by_hash(type->lookup_begin(), type->lookup_end()); - std::sort(sorted_by_hash.begin(), sorted_by_hash.end(), [](const auto &a, const auto &b) -> bool { - const std::string &a_str = a.first.to_string(); - const std::string &b_str = b.first.to_string(); + std::vector> sorted_by_hash(type->lookup_begin(), type->lookup_end()); + std::sort(sorted_by_hash.begin(), sorted_by_hash.end(), [](const auto& a, const auto& b) -> bool { + const std::string& a_str = a.first.to_string(); + const std::string& b_str = b.first.to_string(); return string_hash(a_str.c_str(), a_str.size()) < string_hash(b_str.c_str(), b_str.size()); }); @@ -752,7 +751,7 @@ static void type_out_impl(const TypeData *type, std::string &res, gen_out_style keys_hashes_str += ","; types_str += ", "; } - const std::string &key_str = subkey.first.to_string(); + const std::string& key_str = subkey.first.to_string(); keys_hashes_str += std::to_string(static_cast(string_hash(key_str.c_str(), key_str.size()))); keys_hashes_str += "UL"; if (style == gen_out_style::txt) { @@ -785,57 +784,57 @@ static void type_out_impl(const TypeData *type, std::string &res, gen_out_style } } -std::string type_out(const TypeData *type, gen_out_style style) { +std::string type_out(const TypeData* type, gen_out_style style) { std::string res; type_out_impl(type, res, style); return res; } -int type_strlen(const TypeData *type) { +int type_strlen(const TypeData* type) { PrimitiveType tp = type->ptype(); switch (tp) { - case tp_any: - if (type->or_null_flag() || type->or_false_flag()) { - return STRLEN_EMPTY; - } - return STRLEN_UNKNOWN; - case tp_Null: - case tp_False: + case tp_any: + if (type->or_null_flag() || type->or_false_flag()) { return STRLEN_EMPTY; - case tp_bool: - return STRLEN_BOOL_; - case tp_int: - return STRLEN_INT; - case tp_float: - return STRLEN_FLOAT; - case tp_array: - case tp_tuple: - case tp_shape: - return STRLEN_ARRAY_; - case tp_string: - case tp_tmp_string: - return STRLEN_STRING; - case tp_mixed: - return STRLEN_VAR; - case tp_Class: - case tp_object: - return STRLEN_CLASS; - case tp_void: - return STRLEN_VOID; - case tp_future: - return STRLEN_FUTURE; - case tp_future_queue: - return STRLEN_FUTURE_QUEUE; - case tp_Error: - return STRLEN_ERROR; - case tp_regexp: - case ptype_size: + } + return STRLEN_UNKNOWN; + case tp_Null: + case tp_False: + return STRLEN_EMPTY; + case tp_bool: + return STRLEN_BOOL_; + case tp_int: + return STRLEN_INT; + case tp_float: + return STRLEN_FLOAT; + case tp_array: + case tp_tuple: + case tp_shape: + return STRLEN_ARRAY_; + case tp_string: + case tp_tmp_string: + return STRLEN_STRING; + case tp_mixed: + return STRLEN_VAR; + case tp_Class: + case tp_object: + return STRLEN_CLASS; + case tp_void: + return STRLEN_VOID; + case tp_future: + return STRLEN_FUTURE; + case tp_future_queue: + return STRLEN_FUTURE_QUEUE; + case tp_Error: + return STRLEN_ERROR; + case tp_regexp: + case ptype_size: kphp_fail(); } return STRLEN_ERROR; } -bool can_be_same_type(const TypeData *type1, const TypeData *type2) { +bool can_be_same_type(const TypeData* type1, const TypeData* type2) { if (type1->ptype() == tp_mixed || type2->ptype() == tp_mixed) { return true; } @@ -847,7 +846,7 @@ bool can_be_same_type(const TypeData *type1, const TypeData *type2) { } // TODO: do we need this? - auto is_array_or_tuple = [](const TypeData *type) { return vk::any_of_equal(type->ptype(), tp_array, tp_tuple, tp_shape); }; + auto is_array_or_tuple = [](const TypeData* type) { return vk::any_of_equal(type->ptype(), tp_array, tp_tuple, tp_shape); }; if (is_array_or_tuple(type1) && is_array_or_tuple(type2)) { return true; } @@ -857,7 +856,7 @@ bool can_be_same_type(const TypeData *type1, const TypeData *type2) { // check if types fully equal (if type2 is any, it's equal to anything) // note that false != bool here -bool are_equal_types(const TypeData *type1, const TypeData *type2) { +bool are_equal_types(const TypeData* type1, const TypeData* type2) { if (type1 == nullptr) { return type2 == nullptr; } @@ -882,7 +881,7 @@ bool are_equal_types(const TypeData *type1, const TypeData *type2) { if (vk::any_of_equal(tp, tp_shape, tp_tuple)) { for (auto it1 = type1->lookup_begin(); it1 != type1->lookup_end(); ++it1) { - const TypeData *t2_at_it = type2->lookup_at(it1->first); + const TypeData* t2_at_it = type2->lookup_at(it1->first); if (t2_at_it == nullptr && !type2->shape_has_varg_flag()) { return false; } else if (t2_at_it && !are_equal_types(it1->second, t2_at_it)) { @@ -890,7 +889,7 @@ bool are_equal_types(const TypeData *type1, const TypeData *type2) { } } for (auto it2 = type2->lookup_begin(); it2 != type2->lookup_end(); ++it2) { - const TypeData *t1_at_it = type1->lookup_at(it2->first); + const TypeData* t1_at_it = type1->lookup_at(it2->first); if (t1_at_it == nullptr && !type1->shape_has_varg_flag()) { return false; } @@ -902,51 +901,51 @@ bool are_equal_types(const TypeData *type1, const TypeData *type2) { // check that given <= expected, to if expected is a phpdoc restriction, check that actual inferred type matches // note that false < bool -bool is_less_or_equal_type(const TypeData *given, const TypeData *expected, const MultiKey *from_at) { +bool is_less_or_equal_type(const TypeData* given, const TypeData* expected, const MultiKey* from_at) { // optimization: for obvious cases (like primitive=primitive or primitiveuse_or_false() == expected->use_or_false() && given->use_or_null() == expected->use_or_null(); if (eq_flags && !from_at) { PrimitiveType tp = given->ptype(); switch (expected->ptype()) { - case tp_any: - if (expected->get_real_ptype() == tp_any) { - return true; - } - break; - case tp_string: - case tp_int: - case tp_float: - case tp_bool: - case tp_void: - if (tp == expected->ptype()) { - return true; - } - break; - case tp_array: - if (tp == tp_array && expected->lookup_at(Key::any_key())->get_real_ptype() == tp_any) { - return true; + case tp_any: + if (expected->get_real_ptype() == tp_any) { + return true; + } + break; + case tp_string: + case tp_int: + case tp_float: + case tp_bool: + case tp_void: + if (tp == expected->ptype()) { + return true; + } + break; + case tp_array: + if (tp == tp_array && expected->lookup_at(Key::any_key())->get_real_ptype() == tp_any) { + return true; + } + break; + case tp_mixed: + if (vk::any_of_equal(tp, tp_bool, tp_int, tp_float, tp_string, tp_mixed)) { + return true; + } + break; + case tp_Class: + if (given->class_types() == expected->class_types()) { + if (given->ffi_const_flag() && !expected->ffi_const_flag()) { + return false; } - break; - case tp_mixed: - if (vk::any_of_equal(tp, tp_bool, tp_int, tp_float, tp_string, tp_mixed)) { + if (given->get_indirection() == expected->get_indirection()) { return true; } - break; - case tp_Class: - if (given->class_types() == expected->class_types()) { - if (given->ffi_const_flag() && !expected->ffi_const_flag()) { - return false; - } - if (given->get_indirection() == expected->get_indirection()) { - return true; - } - } - break; - case tp_object: - return tp == tp_Class || tp == tp_object; - default: - break; + } + break; + case tp_object: + return tp == tp_Class || tp == tp_object; + default: + break; } } @@ -962,12 +961,12 @@ bool is_less_or_equal_type(const TypeData *given, const TypeData *expected, cons return are_equal_types(type_of_to_node.get(), expected); } -bool is_implicit_array_conversion(const TypeData *from, const TypeData *to) noexcept { +bool is_implicit_array_conversion(const TypeData* from, const TypeData* to) noexcept { if (!from || !to) { return false; } if (from->get_real_ptype() == tp_array) { - const auto *from_array_value_type = from->lookup_at_any_key(); + const auto* from_array_value_type = from->lookup_at_any_key(); if (from_array_value_type->get_real_ptype() == tp_any) { return false; } @@ -977,7 +976,7 @@ bool is_implicit_array_conversion(const TypeData *from, const TypeData *to) noex return !are_equal_types(from_array_value_type, to->lookup_at_any_key()); } - const auto implicit_cast_pred = [to](const TypeData::SubkeyItem &key_value) { + const auto implicit_cast_pred = [to](const TypeData::SubkeyItem& key_value) { return is_implicit_array_conversion(key_value.second, to->lookup_at(key_value.first)); }; return std::find_if(from->lookup_begin(), from->lookup_end(), implicit_cast_pred) != from->lookup_end(); @@ -988,7 +987,7 @@ size_t TypeData::get_tuple_max_index() const { return std::distance(subkeys.begin(), subkeys.end()); } -bool TypeData::did_type_data_change_after_tinf_step(const TypeData *before) const { +bool TypeData::did_type_data_change_after_tinf_step(const TypeData* before) const { if (ptype_ != before->ptype_ || flags_ != before->flags_) { return true; } @@ -1013,15 +1012,14 @@ bool TypeData::did_type_data_change_after_tinf_step(const TypeData *before) cons return i1 != e1 || i2 != e2; } -const TypeData *TypeData::create_for_class(ClassPtr klass) { - auto *res = new TypeData(tp_Class); +const TypeData* TypeData::create_for_class(ClassPtr klass) { + auto* res = new TypeData(tp_Class); res->class_type_ = {klass}; return res; } -const TypeData *TypeData::create_array_of(const TypeData *element_type) { - auto *res = new TypeData(tp_array); +const TypeData* TypeData::create_array_of(const TypeData* element_type) { + auto* res = new TypeData(tp_array); res->set_lca_at(MultiKey::any_key(1), element_type); return res; } - diff --git a/compiler/inferring/type-data.h b/compiler/inferring/type-data.h index db0ef8bcc7..520f7eba86 100644 --- a/compiler/inferring/type-data.h +++ b/compiler/inferring/type-data.h @@ -17,40 +17,40 @@ #include "compiler/stage.h" #include "compiler/threading/tls.h" - class TypeData { - DEBUG_STRING_METHOD { return as_human_readable(false); } + DEBUG_STRING_METHOD { + return as_human_readable(false); + } private: enum flag_id_t : uint8_t { - write_flag_e = 0b00000001, - or_null_flag_e = 0b00000010, - or_false_flag_e = 0b00000100, + write_flag_e = 0b00000001, + or_null_flag_e = 0b00000010, + or_false_flag_e = 0b00000100, shape_has_varg_flag_e = 0b00001000, - ffi_const_flag_e = 0b00010000, + ffi_const_flag_e = 0b00010000, tuple_as_array_flag_e = 0b00100000, }; public: - using SubkeyItem = std::pair; + using SubkeyItem = std::pair; using lookup_iterator = std::forward_list::const_iterator; // TODO: move all flags (drop_false, drop_null) here and rename this struct? // passing several booleans as set_lca args is clumsy struct FFIRvalueFlags { - bool drop_ref: 1; - bool take_addr: 1; + bool drop_ref : 1; + bool take_addr : 1; FFIRvalueFlags() - : drop_ref{false} - , take_addr{false} {} + : drop_ref{false}, + take_addr{false} {} }; private: - - PrimitiveType ptype_ : 8; // current type (int/array/etc); tp_any for uninited, tp_Error if error - uint8_t flags_{0}; // a binary mask of flag_id_t - uint8_t indirection_{0}; // ptr levels for FFI pointers + PrimitiveType ptype_ : 8; // current type (int/array/etc); tp_any for uninited, tp_Error if error + uint8_t flags_{0}; // a binary mask of flag_id_t + uint8_t indirection_{0}; // ptr levels for FFI pointers // current class for tp_Class (but during inferring it could contain many classes due to multiple implements) std::forward_list class_type_; @@ -60,75 +60,122 @@ class TypeData { // for tuples/shapes, it contains multiple items — {key1, key1_type}, {key2, key2_type}, order is undetermined std::forward_list subkeys; - explicit TypeData(PrimitiveType ptype); - TypeData *at_force(const Key &key); - TypeData *write_at(const Key &key); - const TypeData *const_read_at(const Key &key) const; + TypeData* at_force(const Key& key); + TypeData* write_at(const Key& key); + const TypeData* const_read_at(const Key& key) const; template - inline bool get_flag() const { return flags_ & FLAG; } + inline bool get_flag() const { + return flags_ & FLAG; + } template - void set_flag() { flags_ |= FLAG; } + void set_flag() { + flags_ |= FLAG; + } template - bool for_each_deep(const F &visitor) const; + bool for_each_deep(const F& visitor) const; public: - TypeData &operator=(const TypeData &) = delete; - TypeData(const TypeData &from); + TypeData& operator=(const TypeData&) = delete; + TypeData(const TypeData& from); ~TypeData(); std::string as_human_readable(bool colored = true) const; - PrimitiveType ptype() const { return ptype_; } + PrimitiveType ptype() const { + return ptype_; + } PrimitiveType get_real_ptype() const; - void set_ptype(PrimitiveType new_ptype) { ptype_ = new_ptype; } + void set_ptype(PrimitiveType new_ptype) { + ptype_ = new_ptype; + } - const std::forward_list &class_types() const { return class_type_; } - ClassPtr class_type() const { return class_type_.empty() ? ClassPtr{} : class_type_.front(); } - void set_class_type(const std::forward_list &new_class_type); - void set_ffi_pointer_type(const TypeData *new_ptr_type, int new_indirection); + const std::forward_list& class_types() const { + return class_type_; + } + ClassPtr class_type() const { + return class_type_.empty() ? ClassPtr{} : class_type_.front(); + } + void set_class_type(const std::forward_list& new_class_type); + void set_ffi_pointer_type(const TypeData* new_ptr_type, int new_indirection); bool has_class_type_inside() const; void mark_classes_used() const; - void get_all_class_types_inside(std::unordered_set &out) const; + void get_all_class_types_inside(std::unordered_set& out) const; ClassPtr get_first_class_type_inside() const; bool is_primitive_type() const; - uint8_t flags() const { return flags_; } + uint8_t flags() const { + return flags_; + } void set_flags(uint8_t new_flags); bool is_ffi_ref() const; - bool ffi_const_flag() const { return get_flag(); } - void set_ffi_const_flag() { set_flag(); } + bool ffi_const_flag() const { + return get_flag(); + } + void set_ffi_const_flag() { + set_flag(); + } - bool or_false_flag() const { return get_flag(); } - void set_or_false_flag() { set_flag(); } - bool use_or_false() const { return or_false_flag() && !::can_store_false(ptype_); } + bool or_false_flag() const { + return get_flag(); + } + void set_or_false_flag() { + set_flag(); + } + bool use_or_false() const { + return or_false_flag() && !::can_store_false(ptype_); + } bool can_store_false() const; - bool or_null_flag() const { return get_flag(); } - void set_or_null_flag() { set_flag(); } - bool use_or_null() const { return or_null_flag() && !::can_store_null(ptype_); } + bool or_null_flag() const { + return get_flag(); + } + void set_or_null_flag() { + set_flag(); + } + bool use_or_null() const { + return or_null_flag() && !::can_store_null(ptype_); + } bool can_store_null() const; - bool use_optional() const { return use_or_false() || use_or_null(); } + bool use_optional() const { + return use_or_false() || use_or_null(); + } - void set_write_flag() { set_flag(); } - bool get_write_flag() { return get_flag(); } + void set_write_flag() { + set_flag(); + } + bool get_write_flag() { + return get_flag(); + } - bool error_flag() const { return ptype_ == tp_Error; } + bool error_flag() const { + return ptype_ == tp_Error; + } - void set_shape_has_varg_flag() { set_flag(); } - bool shape_has_varg_flag() const { return get_flag(); } + void set_shape_has_varg_flag() { + set_flag(); + } + bool shape_has_varg_flag() const { + return get_flag(); + } - void set_tuple_as_array_flag() { set_flag(); } - bool tuple_as_array_flag() const { return get_flag(); } + void set_tuple_as_array_flag() { + set_flag(); + } + bool tuple_as_array_flag() const { + return get_flag(); + } - int get_indirection() const noexcept { return indirection_; } + int get_indirection() const noexcept { + return indirection_; + } void set_indirection(int indirection) { kphp_error(indirection > 0 && indirection <= 0xff, "too many indirection level"); @@ -137,41 +184,45 @@ class TypeData { bool structured() const; void make_structured(); - TypeData *clone() const; + TypeData* clone() const; + + lookup_iterator lookup_begin() const { + return subkeys.begin(); + } + lookup_iterator lookup_end() const { + return subkeys.end(); + } - lookup_iterator lookup_begin() const { return subkeys.begin(); } - lookup_iterator lookup_end() const { return subkeys.end(); } - - const TypeData *lookup_at(const Key &key) const; - const TypeData *lookup_at_any_key() const { // a bit faster than lookup_at(Key::any_key()), but lookup_at() also surely works + const TypeData* lookup_at(const Key& key) const; + const TypeData* lookup_at_any_key() const { // a bit faster than lookup_at(Key::any_key()), but lookup_at() also surely works if (subkeys.empty()) { return nullptr; } - const SubkeyItem &front = subkeys.front(); // if any_key exists, it's the only one + const SubkeyItem& front = subkeys.front(); // if any_key exists, it's the only one return front.first.is_any_key() ? front.second : nullptr; } - const TypeData *const_read_at(const MultiKey &multi_key) const; - void set_lca(const TypeData *rhs, bool save_or_false = true, bool save_or_null = true, FFIRvalueFlags ffi_flags = {}); - void set_lca_at(const MultiKey &multi_key, const TypeData *rhs, bool save_or_false = true, bool save_or_null = true, FFIRvalueFlags ffi_flags = {}); + const TypeData* const_read_at(const MultiKey& multi_key) const; + void set_lca(const TypeData* rhs, bool save_or_false = true, bool save_or_null = true, FFIRvalueFlags ffi_flags = {}); + void set_lca_at(const MultiKey& multi_key, const TypeData* rhs, bool save_or_false = true, bool save_or_null = true, FFIRvalueFlags ffi_flags = {}); void set_lca(PrimitiveType ptype); void fix_inf_array(); size_t get_tuple_max_index() const; - const TypeData *get_deepest_type_of_array() const; + const TypeData* get_deepest_type_of_array() const; - bool did_type_data_change_after_tinf_step(const TypeData *before) const; + bool did_type_data_change_after_tinf_step(const TypeData* before) const; static void init_static(); - static const TypeData *get_type(PrimitiveType type); - static const TypeData *get_type(PrimitiveType array, PrimitiveType type); - static const TypeData *create_for_class(ClassPtr klass); - static const TypeData *create_array_of(const TypeData *element_type); + static const TypeData* get_type(PrimitiveType type); + static const TypeData* get_type(PrimitiveType array, PrimitiveType type); + static const TypeData* create_for_class(ClassPtr klass); + static const TypeData* create_array_of(const TypeData* element_type); }; -std::string type_out(const TypeData *type, gen_out_style style = gen_out_style::cpp); -int type_strlen(const TypeData *type); -bool can_be_same_type(const TypeData *type1, const TypeData *type2); -bool are_equal_types(const TypeData *type1, const TypeData *type2); -bool is_less_or_equal_type(const TypeData *given, const TypeData *expected, const MultiKey *from_at = nullptr); -bool is_implicit_array_conversion(const TypeData *from, const TypeData *to) noexcept; +std::string type_out(const TypeData* type, gen_out_style style = gen_out_style::cpp); +int type_strlen(const TypeData* type); +bool can_be_same_type(const TypeData* type1, const TypeData* type2); +bool are_equal_types(const TypeData* type1, const TypeData* type2); +bool is_less_or_equal_type(const TypeData* given, const TypeData* expected, const MultiKey* from_at = nullptr); +bool is_implicit_array_conversion(const TypeData* from, const TypeData* to) noexcept; diff --git a/compiler/inferring/type-hint-recalc.cpp b/compiler/inferring/type-hint-recalc.cpp index b14277f8b9..ef1ad1de2c 100644 --- a/compiler/inferring/type-hint-recalc.cpp +++ b/compiler/inferring/type-hint-recalc.cpp @@ -5,21 +5,20 @@ #include "compiler/type-hint.h" #include "compiler/data/function-data.h" -#include "compiler/vertex-util.h" #include "compiler/inferring/public.h" +#include "compiler/vertex-util.h" // recalc_type_data_in_context_of_call() from type-hint.h for all ancestors // they are implemented in a separate .cpp file to leave type-hint.cpp more clear, as recalculation is a separate inferring part - -void TypeHintArgRef::recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call) const { +void TypeHintArgRef::recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call) const { if (auto vertex = VertexUtil::get_call_arg_ref(arg_num, call)) { dst->set_lca(vertex->tinf_node.get_type()); } } -void TypeHintArgRefCallbackCall::recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call) const { - static auto prevent_recursion_thread_safe = [](const std::function &)> &callback) { +void TypeHintArgRefCallbackCall::recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call) const { + static auto prevent_recursion_thread_safe = [](const std::function&)>& callback) { static std::mutex mutex; static std::vector recursively_recalculated; std::lock_guard guard{mutex}; @@ -37,26 +36,24 @@ void TypeHintArgRefCallbackCall::recalc_type_data_in_context_of_call(TypeData *d // create a fake inner call: array_map(function(...$args) { return array_filter(...$args); }, $arr) if (provided_callback->return_typehint && provided_callback->return_typehint->has_argref_inside()) { bool in_recursion = false; - prevent_recursion_thread_safe([provided_callback, &in_recursion](std::vector &recursion) { + prevent_recursion_thread_safe([provided_callback, &in_recursion](std::vector& recursion) { in_recursion = std::find(recursion.begin(), recursion.end(), provided_callback->name) != recursion.end(); }); if (in_recursion) { // see array_reduce(): when we calc ^2() as a return, stop calculating ^2() as a callback parameter return; } - std::vector fake_call_params; // e.g., only one here for fake array_filter call: ^2[*] - for (const auto *callback_param_hint : callback_param->type_hint->try_as()->arg_types) { - prevent_recursion_thread_safe([provided_callback](std::vector &recursion) { - recursion.emplace_back(provided_callback->name); - }); + std::vector fake_call_params; // e.g., only one here for fake array_filter call: ^2[*] + for (const auto* callback_param_hint : callback_param->type_hint->try_as()->arg_types) { + prevent_recursion_thread_safe([provided_callback](std::vector& recursion) { recursion.emplace_back(provided_callback->name); }); - auto fake_call_param = VertexAdaptor::create(); // it has no contents, only tinf_node - TypeData *type_of_passed = TypeData::get_type(tp_any)->clone(); // type of passed ^2[*] + auto fake_call_param = VertexAdaptor::create(); // it has no contents, only tinf_node + TypeData* type_of_passed = TypeData::get_type(tp_any)->clone(); // type of passed ^2[*] callback_param_hint->recalc_type_data_in_context_of_call(type_of_passed, call); fake_call_param->tinf_node.set_type(type_of_passed); fake_call_params.emplace_back(fake_call_param); - prevent_recursion_thread_safe([provided_callback](std::vector &recursion) { + prevent_recursion_thread_safe([provided_callback](std::vector& recursion) { recursion.erase(std::find(recursion.begin(), recursion.end(), provided_callback->name)); }); } @@ -71,9 +68,9 @@ void TypeHintArgRefCallbackCall::recalc_type_data_in_context_of_call(TypeData *d } } -void TypeHintArgRefInstance::recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call) const { +void TypeHintArgRefInstance::recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call) const { if (auto v = VertexUtil::get_call_arg_ref(arg_num, call)) { - if (const auto *class_name = VertexUtil::get_constexpr_string(v)) { + if (const auto* class_name = VertexUtil::get_constexpr_string(v)) { if (auto klass = G->get_class(*class_name)) { dst->set_lca(klass->type_data); return; @@ -86,20 +83,20 @@ void TypeHintArgRefInstance::recalc_type_data_in_context_of_call(TypeData *dst, dst->set_lca(TypeData::get_type(tp_Error)); } -void TypeHintArgSubkeyGet::recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call) const { +void TypeHintArgSubkeyGet::recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call) const { TypeData nested(*TypeData::get_type(tp_any)); inner->recalc_type_data_in_context_of_call(&nested, call); dst->set_lca(nested.const_read_at(MultiKey::any_key(1))); } -void TypeHintArray::recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call) const { +void TypeHintArray::recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call) const { dst->set_lca(TypeData::get_type(tp_array)); TypeData nested(*TypeData::get_type(tp_any)); inner->recalc_type_data_in_context_of_call(&nested, call); dst->set_lca_at(MultiKey::any_key(1), &nested); } -void TypeHintCallable::recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call) const { +void TypeHintCallable::recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call) const { if (is_typed_callable() && (!call || !call.as()->func_id->is_extern())) { dst->set_lca(get_interface()->type_data); } else if (is_untyped_callable() && f_bound_to) { @@ -111,7 +108,7 @@ void TypeHintCallable::recalc_type_data_in_context_of_call(TypeData *dst, Vertex } } -static void recalc_ffi_type(TypeData *dst, const std::string &scope_name, const FFIType *type) { +static void recalc_ffi_type(TypeData* dst, const std::string& scope_name, const FFIType* type) { if (type->kind == FFITypeKind::Pointer) { TypeData nested{*TypeData::get_type(tp_any)}; recalc_ffi_type(&nested, scope_name, type->members[0]); @@ -140,29 +137,29 @@ static void recalc_ffi_type(TypeData *dst, const std::string &scope_name, const return; } - if (const auto *builtin = ffi_builtin_type(type->kind)) { + if (const auto* builtin = ffi_builtin_type(type->kind)) { dst->set_lca(G->get_class(builtin->php_class_name)->type_data); return; } } -void TypeHintFFIType::recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call __attribute__ ((unused))) const { +void TypeHintFFIType::recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call __attribute__((unused))) const { recalc_ffi_type(dst, scope_name, type); } -void TypeHintFFIScopeArgRef::recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call) const { +void TypeHintFFIScopeArgRef::recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call) const { if (auto v = VertexUtil::get_call_arg_ref(arg_num, call)) { - if (const auto *arg_scope_name = VertexUtil::get_constexpr_string(v)) { + if (const auto* arg_scope_name = VertexUtil::get_constexpr_string(v)) { dst->set_lca(G->get_class(FFIRoot::scope_class_name(*arg_scope_name))->type_data); } } } -void TypeHintFFIScope::recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call __attribute__ ((unused))) const { +void TypeHintFFIScope::recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call __attribute__((unused))) const { dst->set_lca(G->get_class(FFIRoot::scope_class_name(scope_name))->type_data); } -void TypeHintFuture::recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call) const { +void TypeHintFuture::recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call) const { kphp_assert(vk::any_of_equal(ptype, tp_future, tp_future_queue)); dst->set_lca(ptype); TypeData nested(*TypeData::get_type(tp_any)); @@ -170,27 +167,27 @@ void TypeHintFuture::recalc_type_data_in_context_of_call(TypeData *dst, VertexPt dst->set_lca_at(MultiKey::any_key(1), &nested); } -void TypeHintNotNull::recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call) const { +void TypeHintNotNull::recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call) const { TypeData nested(*TypeData::get_type(tp_any)); inner->recalc_type_data_in_context_of_call(&nested, call); dst->set_lca(&nested, !drop_not_false, !drop_not_null); } -void TypeHintInstance::recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call __attribute__ ((unused))) const { +void TypeHintInstance::recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call __attribute__((unused))) const { dst->set_lca(resolve()->type_data); } -void TypeHintRefToField::recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call __attribute__ ((unused))) const { +void TypeHintRefToField::recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call __attribute__((unused))) const { kphp_error(0, "Syntax ClassName::field is available only in a combination with generics"); dst->set_lca(tp_any); } -void TypeHintRefToMethod::recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call __attribute__ ((unused))) const { +void TypeHintRefToMethod::recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call __attribute__((unused))) const { kphp_error(0, "Syntax ClassName::method() is available only in a combination with generics"); dst->set_lca(tp_any); } -void TypeHintOptional::recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call) const { +void TypeHintOptional::recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call) const { inner->recalc_type_data_in_context_of_call(dst, call); if (or_null) { dst->set_lca(TypeData::get_type(tp_Null)); @@ -200,25 +197,25 @@ void TypeHintOptional::recalc_type_data_in_context_of_call(TypeData *dst, Vertex } } -void TypeHintPipe::recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call) const { - for (const TypeHint *item : items) { +void TypeHintPipe::recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call) const { + for (const TypeHint* item : items) { item->recalc_type_data_in_context_of_call(dst, call); } } -void TypeHintPrimitive::recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call __attribute__ ((unused))) const { +void TypeHintPrimitive::recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call __attribute__((unused))) const { dst->set_lca(TypeData::get_type(ptype)); } -void TypeHintObject::recalc_type_data_in_context_of_call(TypeData *dst __attribute__ ((unused)), VertexPtr call __attribute__ ((unused))) const { +void TypeHintObject::recalc_type_data_in_context_of_call(TypeData* dst __attribute__((unused)), VertexPtr call __attribute__((unused))) const { // 'object' keyword is allowed only in params of functions // (it remains for extern functions, but for PHP functions it converts a function into generic and drops away) dst->set_lca(tp_object); } -void TypeHintShape::recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call) const { +void TypeHintShape::recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call) const { dst->set_lca(TypeData::get_type(tp_shape)); - for (const auto &item : items) { + for (const auto& item : items) { TypeData nested(*TypeData::get_type(tp_any)); item.second->recalc_type_data_in_context_of_call(&nested, call); MultiKey key({Key::string_key(item.first)}); @@ -229,7 +226,7 @@ void TypeHintShape::recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr } } -void TypeHintTuple::recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call) const { +void TypeHintTuple::recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call) const { dst->set_lca(TypeData::get_type(tp_tuple)); for (int int_index = 0; int_index < items.size(); ++int_index) { TypeData nested(*TypeData::get_type(tp_any)); @@ -239,12 +236,11 @@ void TypeHintTuple::recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr } } -void TypeHintGenericT::recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call __attribute__ ((unused))) const { +void TypeHintGenericT::recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call __attribute__((unused))) const { dst->set_lca(tp_Error); kphp_assert(0 && "generic T not instantiated before type inferring"); } -void TypeHintClassString::recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call __attribute__ ((unused))) const { +void TypeHintClassString::recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call __attribute__((unused))) const { dst->set_ptype(tp_string); } - diff --git a/compiler/inferring/type-inferer.cpp b/compiler/inferring/type-inferer.cpp index ae08fa6744..5235455244 100644 --- a/compiler/inferring/type-inferer.cpp +++ b/compiler/inferring/type-inferer.cpp @@ -15,29 +15,30 @@ namespace tinf { TypeInferer::TypeInferer() - : finish_flag(false) {} + : finish_flag(false) {} -void TypeInferer::recalc_node(Node *node) { - //fprintf (stderr, "tinf::recalc_node %d %p %s\n", get_thread_id(), node, node->get_description().c_str()); +void TypeInferer::recalc_node(Node* node) { + // fprintf (stderr, "tinf::recalc_node %d %p %s\n", get_thread_id(), node, node->get_description().c_str()); if (node->try_start_recalc()) { Q->push(node); } } -void TypeInferer::add_node(Node *node) { - //fprintf (stderr, "tinf::add_node %d %p %s\n", get_thread_id(), node, node->get_description().c_str()); +void TypeInferer::add_node(Node* node) { + // fprintf (stderr, "tinf::add_node %d %p %s\n", get_thread_id(), node, node->get_description().c_str()); if (!node->was_recalc_started_at_least_once()) { recalc_node(node); } } -void TypeInferer::add_edge(const Edge *edge) { - //fprintf (stderr, "add_edge %d [%p %s] -> [%p %s]\n", get_thread_id(), edge->from, edge->from->get_description().c_str(), edge->to, edge->to->get_description().c_str()); +void TypeInferer::add_edge(const Edge* edge) { + // fprintf (stderr, "add_edge %d [%p %s] -> [%p %s]\n", get_thread_id(), edge->from, edge->from->get_description().c_str(), edge->to, + // edge->to->get_description().c_str()); edge->from->register_edge_from_this(edge); edge->to->register_edge_to_this(edge); } -void TypeInferer::add_restriction(RestrictionBase *restriction) { +void TypeInferer::add_restriction(RestrictionBase* restriction) { restrictions->push_back(restriction); } @@ -46,7 +47,7 @@ void TypeInferer::check_restrictions() { int shown = 0; for (int i = 0; i < restrictions.size(); i++) { - for (RestrictionBase *r : restrictions.get(i)) { + for (RestrictionBase* r : restrictions.get(i)) { if (r->is_restriction_broken()) { std::string description = r->get_description(); stage::set_location(r->get_location()); // after get_description(), as its call could change location @@ -60,17 +61,17 @@ void TypeInferer::check_restrictions() { } } - class TypeInfererTask : public Task { static CachedProfiler type_inferer_profiler; + private: - TypeInferer *inferer_; + TypeInferer* inferer_; NodeQueue queue_; + public: - TypeInfererTask(TypeInferer *inferer, NodeQueue &&queue) : - inferer_(inferer), - queue_(std::move(queue)) { - } + TypeInfererTask(TypeInferer* inferer, NodeQueue&& queue) + : inferer_(inferer), + queue_(std::move(queue)) {} void execute() override { AutoProfiler profiler{*type_inferer_profiler}; @@ -82,8 +83,8 @@ class TypeInfererTask : public Task { CachedProfiler TypeInfererTask::type_inferer_profiler{"Type Inferring"}; -std::vector TypeInferer::get_tasks() { - std::vector res; +std::vector TypeInferer::get_tasks() { + std::vector res; for (int i = 0; i < Q.size(); i++) { NodeQueue q = std::move(Q.get(i)); if (q.empty()) { @@ -96,10 +97,10 @@ std::vector TypeInferer::get_tasks() { } void TypeInferer::do_run_queue() { - NodeQueue &q = Q.get(); + NodeQueue& q = Q.get(); while (!q.empty()) { - Node *node = q.front(); + Node* node = q.front(); node->start_recalc(); node->recalc(this); @@ -109,12 +110,12 @@ void TypeInferer::do_run_queue() { } } -void TypeInferer::run_queue(NodeQueue *new_q) { +void TypeInferer::run_queue(NodeQueue* new_q) { *Q = std::move(*new_q); do_run_queue(); } -void TypeInferer::run_node(Node *node) { +void TypeInferer::run_node(Node* node) { if (!node->was_recalc_started_at_least_once()) { add_node(node); do_run_queue(); @@ -129,7 +130,4 @@ void TypeInferer::finish() { kphp_assert(Q->empty()); } - - } // namespace tinf - diff --git a/compiler/inferring/type-inferer.h b/compiler/inferring/type-inferer.h index cf687f3870..f206f4c6b4 100644 --- a/compiler/inferring/type-inferer.h +++ b/compiler/inferring/type-inferer.h @@ -13,11 +13,11 @@ namespace tinf { -using NodeQueue = std::queue; +using NodeQueue = std::queue; class TypeInferer { private: - TLS> restrictions; + TLS> restrictions; bool finish_flag; public: @@ -26,21 +26,23 @@ class TypeInferer { public: TypeInferer(); - void add_edge(const Edge *edge); + void add_edge(const Edge* edge); - void recalc_node(Node *node); - void add_node(Node *node); + void recalc_node(Node* node); + void add_node(Node* node); - void add_restriction(RestrictionBase *restriction); + void add_restriction(RestrictionBase* restriction); void check_restrictions(); - void run_queue(NodeQueue *q); - std::vector get_tasks(); + void run_queue(NodeQueue* q); + std::vector get_tasks(); - void run_node(Node *node); + void run_node(Node* node); void finish(); - bool is_finished() const { return finish_flag; } + bool is_finished() const { + return finish_flag; + } private: void do_run_queue(); diff --git a/compiler/inferring/type-node.cpp b/compiler/inferring/type-node.cpp index 038f8d1a34..037292e363 100644 --- a/compiler/inferring/type-node.cpp +++ b/compiler/inferring/type-node.cpp @@ -11,6 +11,6 @@ std::string tinf::TypeNode::get_description() { return "TypeNode at " + location_.as_human_readable() + " : " + type_->as_human_readable(); } -const Location &tinf::TypeNode::get_location() const { +const Location& tinf::TypeNode::get_location() const { return location_; } diff --git a/compiler/inferring/type-node.h b/compiler/inferring/type-node.h index 712283c328..17fefc9dbe 100644 --- a/compiler/inferring/type-node.h +++ b/compiler/inferring/type-node.h @@ -13,16 +13,15 @@ class TypeNode : public Node { Location location_; public: - explicit TypeNode(const TypeData *type, Location location) : - location_(std::move(location)) { + explicit TypeNode(const TypeData* type, Location location) + : location_(std::move(location)) { set_type(type); } - void recalc(TypeInferer *inferer __attribute__((unused))) { - } + void recalc(TypeInferer* inferer __attribute__((unused))) {} std::string get_description() final; - const Location &get_location() const final; + const Location& get_location() const final; }; } // namespace tinf diff --git a/compiler/inferring/var-node.cpp b/compiler/inferring/var-node.cpp index 3885542f70..2a0cd31dee 100644 --- a/compiler/inferring/var-node.cpp +++ b/compiler/inferring/var-node.cpp @@ -12,29 +12,27 @@ #include "compiler/vertex.h" class VarNodeRecalc : public NodeRecalc { - static void on_restricted_type_mismatch(const tinf::Edge *edge, const TypeData *type_restriction); + static void on_restricted_type_mismatch(const tinf::Edge* edge, const TypeData* type_restriction); public: - VarNodeRecalc(tinf::VarNode *node, tinf::TypeInferer *inferer); + VarNodeRecalc(tinf::VarNode* node, tinf::TypeInferer* inferer); void do_recalc() final; - void on_new_type_became_tpError(const TypeData *because_of_type, const RValue &because_of_rvalue) final; + void on_new_type_became_tpError(const TypeData* because_of_type, const RValue& because_of_rvalue) final; }; - -VarNodeRecalc::VarNodeRecalc(tinf::VarNode *node, tinf::TypeInferer *inferer) : - NodeRecalc(node, inferer) { -} +VarNodeRecalc::VarNodeRecalc(tinf::VarNode* node, tinf::TypeInferer* inferer) + : NodeRecalc(node, inferer) {} void VarNodeRecalc::do_recalc() { - tinf::VarNode *node = dynamic_cast(this->node_); + tinf::VarNode* node = dynamic_cast(this->node_); if (inferer_->is_finished()) { // the main reason of this error is that you have forgotten add_node() in collect-main-edges - kphp_error (0, fmt_format("called do_recalc on finished inferer, {}", node->get_description())); + kphp_error(0, fmt_format("called do_recalc on finished inferer, {}", node->get_description())); kphp_fail(); } // at first, we just calculate new_type_ without any checks - for (const tinf::Edge *e : node->get_edges_from_this()) { + for (const tinf::Edge* e : node->get_edges_from_this()) { set_lca_at(e->from_at, as_rvalue(e->to)); inferer_->add_node(e->to); } @@ -52,13 +50,14 @@ void VarNodeRecalc::do_recalc() { // so, passed string/tuple won't affect @param array, but will show a mismatch error after tinf finishes new_type_ = node->get_type()->clone(); - for (const tinf::Edge *e : node->get_edges_from_this()) { - TypeData *before_type = new_type_->clone(); + for (const tinf::Edge* e : node->get_edges_from_this()) { + TypeData* before_type = new_type_->clone(); set_lca_at(e->from_at, as_rvalue(e->to)); satisfied = !new_type_->error_flag() && is_less_or_equal_type(new_type_, node->type_restriction); if (!satisfied) { -// fmt_print("rollback {} from {} to {} due to restriction {}\n", node->get_description(), colored_type_out(new_type_), colored_type_out(before_type), colored_type_out(node->type_restriction)); + // fmt_print("rollback {} from {} to {} due to restriction {}\n", node->get_description(), colored_type_out(new_type_), + // colored_type_out(before_type), colored_type_out(node->type_restriction)); on_restricted_type_mismatch(e, node->type_restriction); new_type_ = before_type->clone(); } @@ -70,8 +69,8 @@ void VarNodeRecalc::do_recalc() { // when new_type_ became tp_Error but a node is restricted with phpdoc (example: @param string, but passed Exception) // — then don't print it out, just skip this fact, it will be handled just a type mismatch -void VarNodeRecalc::on_new_type_became_tpError(const TypeData *because_of_type, const RValue &because_of_rvalue) { - tinf::VarNode *node = dynamic_cast(this->node_); +void VarNodeRecalc::on_new_type_became_tpError(const TypeData* because_of_type, const RValue& because_of_rvalue) { + tinf::VarNode* node = dynamic_cast(this->node_); if (!node->type_restriction) { NodeRecalc::on_new_type_became_tpError(because_of_type, because_of_rvalue); } @@ -80,12 +79,12 @@ void VarNodeRecalc::on_new_type_became_tpError(const TypeData *because_of_type, // when a type restriction is broken (examples: 1) @param string, but passed int 2) @return int[], but actually return mixed) // then we have an edge (edge->from is VarNode with restriction, edge->to is a mismatched actual node) // this error will be shown after tinf finishes -void VarNodeRecalc::on_restricted_type_mismatch(const tinf::Edge *edge, const TypeData *type_restriction) { +void VarNodeRecalc::on_restricted_type_mismatch(const tinf::Edge* edge, const TypeData* type_restriction) { static std::mutex mutex; - static std::vector already_fired_errors; + static std::vector already_fired_errors; std::lock_guard guard{mutex}; - for (const tinf::Edge *e : already_fired_errors) { + for (const tinf::Edge* e : already_fired_errors) { if (e->from == edge->from && e->to == edge->to) { return; } @@ -93,11 +92,11 @@ void VarNodeRecalc::on_restricted_type_mismatch(const tinf::Edge *edge, const Ty if (edge->from_at) { type_restriction = type_restriction->const_read_at(*edge->from_at); } - tinf::get_inferer()->add_restriction(new RestrictionMatchPhpdoc(dynamic_cast(edge->from), edge->to, type_restriction)); + tinf::get_inferer()->add_restriction(new RestrictionMatchPhpdoc(dynamic_cast(edge->from), edge->to, type_restriction)); already_fired_errors.emplace_back(edge); } -void tinf::VarNode::recalc(tinf::TypeInferer *inferer) { +void tinf::VarNode::recalc(tinf::TypeInferer* inferer) { kphp_assert(param_i != e_uninited); VarNodeRecalc(this, inferer).run(); } @@ -109,13 +108,14 @@ std::string tinf::VarNode::get_description() { } else if (is_return_value_from_function()) { return fmt_format("VarNode (return of {}) : {}", function_->as_human_readable(), tinf::get_type(function_, -1)->as_human_readable()); } else if (is_argument_of_function()) { - return fmt_format("VarNode (arg{} {} of {}) : {}", var_->param_i, var_->as_human_readable(), var_->holder_func->as_human_readable(), tinf::get_type(var_)->as_human_readable()); + return fmt_format("VarNode (arg{} {} of {}) : {}", var_->param_i, var_->as_human_readable(), var_->holder_func->as_human_readable(), + tinf::get_type(var_)->as_human_readable()); } else { return "VarNode (strange)"; } } -const Location &tinf::VarNode::get_location() const { +const Location& tinf::VarNode::get_location() const { if (is_variable()) { return var_->init_val ? var_->init_val->location : var_->holder_func ? var_->holder_func->root->location : stage::get_location(); } else if (is_argument_of_function()) { @@ -125,7 +125,7 @@ const Location &tinf::VarNode::get_location() const { } } -void tinf::VarNode::set_type_restriction(const TypeData *r) { +void tinf::VarNode::set_type_restriction(const TypeData* r) { kphp_assert(!type_restriction && "Setting type_restriction to VarNode more than once"); type_restriction = r; } diff --git a/compiler/inferring/var-node.h b/compiler/inferring/var-node.h index ab4e0f988d..82a31066d2 100644 --- a/compiler/inferring/var-node.h +++ b/compiler/inferring/var-node.h @@ -21,7 +21,7 @@ class VarNode : public Node { VarPtr var_; int param_i{e_uninited}; FunctionPtr function_; - const TypeData *type_restriction{nullptr}; + const TypeData* type_restriction{nullptr}; VarNode() = default; @@ -29,19 +29,19 @@ class VarNode : public Node { void init_as_argument(VarPtr var); void init_as_return_value(FunctionPtr function); - void copy_type_from(const TypeData *from) { + void copy_type_from(const TypeData* from) { type_ = from; recalc_state_ = recalc_st_waiting | recalc_bit_at_least_once; } - void recalc(TypeInferer *inferer) final; + void recalc(TypeInferer* inferer) final; VarPtr get_var() const { return var_; } std::string get_description() final; - const Location &get_location() const final; + const Location& get_location() const final; bool is_variable() const { return param_i == e_variable; @@ -55,7 +55,7 @@ class VarNode : public Node { return param_i >= 0; } - void set_type_restriction(const TypeData *r); + void set_type_restriction(const TypeData* r); }; } // namespace tinf diff --git a/compiler/kphp2cpp.cpp b/compiler/kphp2cpp.cpp index 2bf0f3310c..552091d68b 100644 --- a/compiler/kphp2cpp.cpp +++ b/compiler/kphp2cpp.cpp @@ -14,8 +14,8 @@ #include "common/version-string.h" #include "common/wrappers/string_view.h" -#include "compiler/compiler.h" #include "compiler/compiler-settings.h" +#include "compiler/compiler.h" #include "compiler/threading/tls.h" #include "compiler/utils/string-utils.h" @@ -23,7 +23,7 @@ namespace { class OptionParser : vk::not_copyable { public: - static OptionParser &get_instance() noexcept { + static OptionParser& get_instance() noexcept { static OptionParser parser; return parser; } @@ -34,23 +34,21 @@ class OptionParser : vk::not_copyable { parse_option("version", no_argument, version_and_first_option_id_, "Print version and exit."); } - void add_other_args(const char *description, KphpRawOption &raw_option) { + void add_other_args(const char* description, KphpRawOption& raw_option) { usage_set_other_args_desc(description); other_options_ = &raw_option; other_options_description_ = description; } template - void add(const char *description, KphpOption &option, - const char *long_option, const char *env, - std::string default_value = {}, std::vector choices = {}) noexcept { + void add(const char* description, KphpOption& option, const char* long_option, const char* env, std::string default_value = {}, + std::vector choices = {}) noexcept { add(description, option, 0, long_option, env, std::move(default_value), std::move(choices)); } template - void add(const char *description, KphpOption &option, - char short_option, const char *long_option, const char *env, - std::string default_value = {}, std::vector choices = {}) noexcept { + void add(const char* description, KphpOption& option, char short_option, const char* long_option, const char* env, std::string default_value = {}, + std::vector choices = {}) noexcept { assert(envs_.insert(vk::string_view{env}).second); std::string default_str; if (!default_value.empty()) { @@ -62,22 +60,22 @@ class OptionParser : vk::not_copyable { } const auto option_id = static_cast(version_and_first_option_id_ + options_.size() + 1); - parse_option(long_option, std::is_same{} ? no_argument : required_argument, option_id, - "[%s] %s%s%s.", env, description, choices_str.c_str(), default_str.c_str()); + parse_option(long_option, std::is_same{} ? no_argument : required_argument, option_id, "[%s] %s%s%s.", env, description, choices_str.c_str(), + default_str.c_str()); if (short_option) { parse_option_alias(long_option, short_option); } - KphpRawOption &raw_option = option; + KphpRawOption& raw_option = option; raw_option.init(env, std::move(default_value), std::move(choices)); options_.emplace_back(&raw_option); } - void add_implicit_option(vk::string_view description, KphpImplicitOption &implicit_option) { + void add_implicit_option(vk::string_view description, KphpImplicitOption& implicit_option) { implicit_options_.emplace_back(description, &implicit_option); } - void process_args(int32_t argc, char **argv) { - parse_engine_options_long(argc, argv, [](int32_t option_id, const char *) { + void process_args(int32_t argc, char** argv) { + parse_engine_options_long(argc, argv, [](int32_t option_id, const char*) { if (option_id == 'h') { usage_and_exit(); } @@ -86,7 +84,7 @@ class OptionParser : vk::not_copyable { exit(0); } option_id -= version_and_first_option_id_ + 1; - auto &this_ = get_instance(); + auto& this_ = get_instance(); if (option_id < 0 || option_id >= this_.options_.size()) { return -1; } @@ -108,17 +106,17 @@ class OptionParser : vk::not_copyable { finalize(); } - void dump_options(std::ostream &out) const noexcept { + void dump_options(std::ostream& out) const noexcept { out << other_options_description_ << ": "; other_options_->dump_option(out); out << std::endl << std::endl; - for (const auto &raw_option : options_) { + for (const auto& raw_option : options_) { out << raw_option->get_env_var() << ": ["; raw_option->dump_option(out); out << "]" << std::endl; } out << std::endl; - for (const auto &implicit_option : implicit_options_) { + for (const auto& implicit_option : implicit_options_) { out << implicit_option.first << ": [" << implicit_option.second->get() << "]" << std::endl; } out << std::endl; @@ -128,8 +126,8 @@ class OptionParser : vk::not_copyable { void finalize() { other_options_->parse_arg_value(); - for (auto &raw_option : options_) { - for (auto &option_for_substitute : options_) { + for (auto& raw_option : options_) { + for (auto& option_for_substitute : options_) { raw_option->substitute_depends(*option_for_substitute); } raw_option->verify_arg_value(); @@ -139,13 +137,13 @@ class OptionParser : vk::not_copyable { OptionParser() = default; - KphpRawOption *other_options_{nullptr}; + KphpRawOption* other_options_{nullptr}; vk::string_view other_options_description_; - std::vector options_; + std::vector options_; std::unordered_set envs_; - std::vector> implicit_options_; + std::vector> implicit_options_; static constexpr int32_t version_and_first_option_id_{2000}; }; @@ -154,7 +152,7 @@ std::string get_default_kphp_path() noexcept { #ifdef DEFAULT_KPHP_PATH return as_dir(DEFAULT_KPHP_PATH); #endif - auto *home = getenv("HOME"); + auto* home = getenv("HOME"); assert(home); return std::string{home} + "/kphp/"; } @@ -191,7 +189,7 @@ std::string get_default_extra_ldflags() noexcept { } // namespace -int main(int argc, char *argv[]) { +int main(int argc, char* argv[]) { #if ASAN_ENABLED // asan adds redzones to the stack variables, which increases the footprint, // therefore increase the system limit on the main thread stack @@ -205,112 +203,80 @@ int main(int argc, char *argv[]) { auto settings = std::make_unique(); OptionParser::add_default_options(); - auto &parser = OptionParser::get_instance(); + auto& parser = OptionParser::get_instance(); parser.add_other_args("", settings->main_file); - parser.add("Verbosity", settings->verbosity, - 'v', "verbosity", "KPHP_VERBOSITY", "0", {"0", "1", "2", "3"}); - parser.add("Path to kphp source", settings->kphp_src_path, - 's', "source-path", "KPHP_PATH", get_default_kphp_path()); - parser.add("Internal file with the list of supported PHP functions", settings->functions_file, - 'f', "functions-file", "KPHP_FUNCTIONS"); - parser.add("List of builtins whose calls need to be tracked", settings->tracked_builtins_list, - "tracked-builtins-list", "KPHP_TRACKED_BUILTINS_LIST"); - parser.add("File with kphp runtime sha256 hash", settings->runtime_sha256_file, - "runtime-sha256", "KPHP_RUNTIME_SHA256", "${KPHP_PATH}/objs/php_lib_version.sha256"); - parser.add("The output binary type: server, cli, lib, k2-lib, k2-cli, k2-server, k2-oneshot, k2-multishot", settings->mode, 'M', "mode", "KPHP_MODE", "server", - {"server", "cli", "lib", "k2-lib", "k2-cli", "k2-server", "k2-oneshot", "k2-multishot"}); - parser.add("A runtime library for building the output binary", settings->link_file, - 'l', "link-with", "KPHP_LINK_FILE"); - parser.add("Build runtime from sources", settings->force_link_runtime, - "force-link-runtime", "KPHP_FORCE_LINK_RUNTIME"); - parser.add("Enable safe compilation mode that treats calls to stub functions as compilation error", settings->forbid_stubs_using, - "forbid-stubs", "KPHP_FORBID_STUBS_USING"); + parser.add("Verbosity", settings->verbosity, 'v', "verbosity", "KPHP_VERBOSITY", "0", {"0", "1", "2", "3"}); + parser.add("Path to kphp source", settings->kphp_src_path, 's', "source-path", "KPHP_PATH", get_default_kphp_path()); + parser.add("Internal file with the list of supported PHP functions", settings->functions_file, 'f', "functions-file", "KPHP_FUNCTIONS"); + parser.add("List of builtins whose calls need to be tracked", settings->tracked_builtins_list, "tracked-builtins-list", "KPHP_TRACKED_BUILTINS_LIST"); + parser.add("File with kphp runtime sha256 hash", settings->runtime_sha256_file, "runtime-sha256", "KPHP_RUNTIME_SHA256", + "${KPHP_PATH}/objs/php_lib_version.sha256"); + parser.add("The output binary type: server, cli, lib, k2-lib, k2-cli, k2-server, k2-oneshot, k2-multishot", settings->mode, 'M', "mode", "KPHP_MODE", + "server", {"server", "cli", "lib", "k2-lib", "k2-cli", "k2-server", "k2-oneshot", "k2-multishot"}); + parser.add("A runtime library for building the output binary", settings->link_file, 'l', "link-with", "KPHP_LINK_FILE"); + parser.add("Build runtime from sources", settings->force_link_runtime, "force-link-runtime", "KPHP_FORCE_LINK_RUNTIME"); + parser.add("Enable safe compilation mode that treats calls to stub functions as compilation error", settings->forbid_stubs_using, "forbid-stubs", + "KPHP_FORBID_STUBS_USING"); parser.add("Path to runtime sources", settings->runtime_and_common_src, "rt-path", "KPHP_RT_PATH", get_default_kphp_path()); - parser.add("Directory where php files will be searched", settings->includes, - 'I', "include-dir", "KPHP_INCLUDE_DIR"); - parser.add("Destination directory", settings->dest_dir, - 'd', "destination-directory", "KPHP_DEST_DIR", "./kphp_out/"); - parser.add("Path for the output binary", settings->user_binary_path, - 'o', "output-file", "KPHP_USER_BINARY_PATH"); - parser.add("Directory for placing out static lib and header. Compatible only with lib mode", settings->static_lib_out_dir, - 'O', "output-lib-dir", "KPHP_OUT_LIB_DIR"); - parser.add("Force make. Old object files and binary will be removed", settings->force_make, - 'F', "force-make", "KPHP_FORCE_MAKE"); - parser.add("Code generation only, without making an output binary", settings->no_make, - "no-make", "KPHP_NO_MAKE"); - parser.add("Processes number for the compilation", settings->jobs_count, - 'j', "jobs-num", "KPHP_JOBS_COUNT", std::to_string(get_default_threads_count())); - parser.add("Number of file buckets", settings->file_buckets_count, - "file-buckets-count", "KPHP_FILE_BUCKETS_COUNT", "120"); - parser.add("Threads number for the transpilation", settings->threads_count, - 't', "threads-count", "KPHP_THREADS_COUNT", std::to_string(get_default_threads_count())); - parser.add("Builtin tl schema. Incompatible with lib mode", settings->tl_schema_file, - 'T', "tl-schema", "KPHP_TL_SCHEMA"); - parser.add("Generate storers and fetchers for internal tl functions", settings->gen_tl_internals, - "gen-tl-internals", "KPHP_GEN_TL_INTERNALS"); - parser.add("All compile time warnings will be errors", settings->error_on_warns, - 'W', "Werror", "KPHP_ERROR_ON_WARNINGS"); - parser.add("Print all warnings to file, otherwise warnings are printed to stderr", settings->warnings_file, - "warnings-file", "KPHP_WARNINGS_FILE"); - parser.add("Warnings level: prints more warnings, according to level set", settings->warnings_level, - "warnings-level", "KPHP_WARNINGS_LEVEL", "0", {"0", "1", "2"}); - parser.add("Show all type errors", settings->show_all_type_errors, - "show-all-type-errors", "KPHP_SHOW_ALL_TYPE_ERRORS"); - parser.add("Colorize warnings output: yes, no, auto", settings->colorize, - "colorize", "KPHP_COLORS", "auto", {"auto", "yes", "no"}); - parser.add("Save C++ compiler statistics to file", settings->stats_file, - "stats-file", "KPHP_STATS_FILE"); - parser.add("Save transpilation metrics to file", settings->compilation_metrics_file, - "compilation-metrics-file", "KPHP_COMPILATION_METRICS_FILE"); - parser.add("Override kphp version string", settings->override_kphp_version, - "kphp-version-override", "KPHP_VERSION_OVERRIDE"); - parser.add("Specify the compiled php code version", settings->php_code_version, - "php-code-version", "KPHP_PHP_CODE_VERSION", "unknown"); - parser.add("Specify the compiled php code commit hash", settings->php_code_commit_hash, - "php-code-commit-hash", "KPHP_PHP_CODE_COMMIT_HASH", "0000000000000000000000000000000000000000"); - parser.add("C++ compiler for building the output binary", settings->cxx, - "cxx", "KPHP_CXX", get_default_cxx()); - parser.add("Directory for c++ compiler toolchain. Will be passed to cxx via -B option", settings->cxx_toolchain_dir, - "cxx-toolchain-dir", "KPHP_CXX_TOOLCHAIN_DIR"); - parser.add("Extra C++ compiler flags for building the output binary", settings->extra_cxx_flags, - "extra-cxx-flags", "KPHP_EXTRA_CXXFLAGS", get_default_extra_cxxflags()); - parser.add("Extra linker flags for building the output binary", settings->extra_ld_flags, - "extra-linker-flags", "KPHP_EXTRA_LDFLAGS", get_default_extra_ldflags()); - parser.add("C++ compiler debug level for building the output binary", settings->extra_cxx_debug_level, - "debug-level", "KPHP_DEBUG_LEVEL"); - parser.add("Probability of partially disabling debug info for some random part of files", - settings->debug_info_force_disable_prob, "debug-info-force-disable-probability", "KPHP_DEBUG_INFO_FORCE_DISABLE_PROBABILITY"); - parser.add("Seed for random check from --debug-info-force-disable-probability option", - settings->debug_info_force_disable_prob_seed, "debug-info-force-disable-probability-seed", "KPHP_DEBUG_INFO_FORCE_DISABLE_PROBABILITY_SEED"); - - parser.add("Archive creator for building the output binary", settings->archive_creator, - "archive-creator", "KPHP_ARCHIVE_CREATOR", "ar"); - parser.add("Use dynamic incremental linkage for building the output binary", settings->dynamic_incremental_linkage, - "dynamic-incremental-linkage", "KPHP_DYNAMIC_INCREMENTAL_LINKAGE"); - parser.add("Profile functions: 0 - disabled, 1 - enabled for marked functions, 2 - enabled for all", settings->profiler_level, - 'g', "profiler", "KPHP_PROFILER", "0", {"0", "1", "2"}); - parser.add("Enable an ability to get global vars memory stats", settings->enable_global_vars_memory_stats, - "enable-global-vars-memory-stats", "KPHP_ENABLE_GLOBAL_VARS_MEMORY_STATS"); + parser.add("Directory where php files will be searched", settings->includes, 'I', "include-dir", "KPHP_INCLUDE_DIR"); + parser.add("Destination directory", settings->dest_dir, 'd', "destination-directory", "KPHP_DEST_DIR", "./kphp_out/"); + parser.add("Path for the output binary", settings->user_binary_path, 'o', "output-file", "KPHP_USER_BINARY_PATH"); + parser.add("Directory for placing out static lib and header. Compatible only with lib mode", settings->static_lib_out_dir, 'O', "output-lib-dir", + "KPHP_OUT_LIB_DIR"); + parser.add("Force make. Old object files and binary will be removed", settings->force_make, 'F', "force-make", "KPHP_FORCE_MAKE"); + parser.add("Code generation only, without making an output binary", settings->no_make, "no-make", "KPHP_NO_MAKE"); + parser.add("Processes number for the compilation", settings->jobs_count, 'j', "jobs-num", "KPHP_JOBS_COUNT", std::to_string(get_default_threads_count())); + parser.add("Number of file buckets", settings->file_buckets_count, "file-buckets-count", "KPHP_FILE_BUCKETS_COUNT", "120"); + parser.add("Threads number for the transpilation", settings->threads_count, 't', "threads-count", "KPHP_THREADS_COUNT", + std::to_string(get_default_threads_count())); + parser.add("Builtin tl schema. Incompatible with lib mode", settings->tl_schema_file, 'T', "tl-schema", "KPHP_TL_SCHEMA"); + parser.add("Generate storers and fetchers for internal tl functions", settings->gen_tl_internals, "gen-tl-internals", "KPHP_GEN_TL_INTERNALS"); + parser.add("All compile time warnings will be errors", settings->error_on_warns, 'W', "Werror", "KPHP_ERROR_ON_WARNINGS"); + parser.add("Print all warnings to file, otherwise warnings are printed to stderr", settings->warnings_file, "warnings-file", "KPHP_WARNINGS_FILE"); + parser.add("Warnings level: prints more warnings, according to level set", settings->warnings_level, "warnings-level", "KPHP_WARNINGS_LEVEL", "0", + {"0", "1", "2"}); + parser.add("Show all type errors", settings->show_all_type_errors, "show-all-type-errors", "KPHP_SHOW_ALL_TYPE_ERRORS"); + parser.add("Colorize warnings output: yes, no, auto", settings->colorize, "colorize", "KPHP_COLORS", "auto", {"auto", "yes", "no"}); + parser.add("Save C++ compiler statistics to file", settings->stats_file, "stats-file", "KPHP_STATS_FILE"); + parser.add("Save transpilation metrics to file", settings->compilation_metrics_file, "compilation-metrics-file", "KPHP_COMPILATION_METRICS_FILE"); + parser.add("Override kphp version string", settings->override_kphp_version, "kphp-version-override", "KPHP_VERSION_OVERRIDE"); + parser.add("Specify the compiled php code version", settings->php_code_version, "php-code-version", "KPHP_PHP_CODE_VERSION", "unknown"); + parser.add("Specify the compiled php code commit hash", settings->php_code_commit_hash, "php-code-commit-hash", "KPHP_PHP_CODE_COMMIT_HASH", + "0000000000000000000000000000000000000000"); + parser.add("C++ compiler for building the output binary", settings->cxx, "cxx", "KPHP_CXX", get_default_cxx()); + parser.add("Directory for c++ compiler toolchain. Will be passed to cxx via -B option", settings->cxx_toolchain_dir, "cxx-toolchain-dir", + "KPHP_CXX_TOOLCHAIN_DIR"); + parser.add("Extra C++ compiler flags for building the output binary", settings->extra_cxx_flags, "extra-cxx-flags", "KPHP_EXTRA_CXXFLAGS", + get_default_extra_cxxflags()); + parser.add("Extra linker flags for building the output binary", settings->extra_ld_flags, "extra-linker-flags", "KPHP_EXTRA_LDFLAGS", + get_default_extra_ldflags()); + parser.add("C++ compiler debug level for building the output binary", settings->extra_cxx_debug_level, "debug-level", "KPHP_DEBUG_LEVEL"); + parser.add("Probability of partially disabling debug info for some random part of files", settings->debug_info_force_disable_prob, + "debug-info-force-disable-probability", "KPHP_DEBUG_INFO_FORCE_DISABLE_PROBABILITY"); + parser.add("Seed for random check from --debug-info-force-disable-probability option", settings->debug_info_force_disable_prob_seed, + "debug-info-force-disable-probability-seed", "KPHP_DEBUG_INFO_FORCE_DISABLE_PROBABILITY_SEED"); + + parser.add("Archive creator for building the output binary", settings->archive_creator, "archive-creator", "KPHP_ARCHIVE_CREATOR", "ar"); + parser.add("Use dynamic incremental linkage for building the output binary", settings->dynamic_incremental_linkage, "dynamic-incremental-linkage", + "KPHP_DYNAMIC_INCREMENTAL_LINKAGE"); + parser.add("Profile functions: 0 - disabled, 1 - enabled for marked functions, 2 - enabled for all", settings->profiler_level, 'g', "profiler", + "KPHP_PROFILER", "0", {"0", "1", "2"}); + parser.add("Enable an ability to get global vars memory stats", settings->enable_global_vars_memory_stats, "enable-global-vars-memory-stats", + "KPHP_ENABLE_GLOBAL_VARS_MEMORY_STATS"); parser.add("Enable all inspections available for @kphp-analyze-performance for all reachable functions", settings->enable_full_performance_analyze, "enable-full-performance-analyze", "KPHP_ENABLE_FULL_PERFORMANCE_ANALYZE"); - parser.add("Print graph of resumable calls to stderr", settings->print_resumable_graph, - 'p', "print-graph", "KPHP_PRINT_RESUMABLE_GRAPH"); - parser.add("Forbid to use the precompile header", settings->no_pch, - "no-pch", "KPHP_NO_PCH"); - parser.add("Forbid to use an index file which contains codegen hashes from previous compilation", settings->no_index_file, - "no-index-file", "KPHP_NO_INDEX_FILE"); - parser.add("Show transpilation progress", settings->show_progress, - "show-progress", "KPHP_SHOW_PROGRESS"); - parser.add("A folder that contains composer.json file", settings->composer_root, - "composer-root", "KPHP_COMPOSER_ROOT"); - parser.add("Include autoload-dev section for the root composer file", settings->composer_autoload_dev, - "composer-autoload-dev", "KPHP_COMPOSER_AUTOLOAD_DEV"); + parser.add("Print graph of resumable calls to stderr", settings->print_resumable_graph, 'p', "print-graph", "KPHP_PRINT_RESUMABLE_GRAPH"); + parser.add("Forbid to use the precompile header", settings->no_pch, "no-pch", "KPHP_NO_PCH"); + parser.add("Forbid to use an index file which contains codegen hashes from previous compilation", settings->no_index_file, "no-index-file", + "KPHP_NO_INDEX_FILE"); + parser.add("Show transpilation progress", settings->show_progress, "show-progress", "KPHP_SHOW_PROGRESS"); + parser.add("A folder that contains composer.json file", settings->composer_root, "composer-root", "KPHP_COMPOSER_ROOT"); + parser.add("Include autoload-dev section for the root composer file", settings->composer_autoload_dev, "composer-autoload-dev", "KPHP_COMPOSER_AUTOLOAD_DEV"); parser.add("Require functions typing (1 - @param / type hint is mandatory, 0 - auto infer or check if exists)", settings->require_functions_typing, "require-functions-typing", "KPHP_REQUIRE_FUNCTIONS_TYPING"); parser.add("Require class typing (1 - @var / default value is mandatory, 0 - auto infer or check if exists)", settings->require_class_typing, "require-class-typing", "KPHP_REQUIRE_CLASS_TYPING"); - parser.add("Define k2 component name. Default is \"KPHP\"", settings->k2_component_name, - "k2-component-name", "KPHP_K2_COMPONENT_NAME", "KPHP"); + parser.add("Define k2 component name. Default is \"KPHP\"", settings->k2_component_name, "k2-component-name", "KPHP_K2_COMPONENT_NAME", "KPHP"); parser.add_implicit_option("Linker flags", settings->ld_flags); parser.add_implicit_option("Incremental linker flags", settings->incremental_linker_flags); @@ -335,7 +301,7 @@ int main(int argc, char *argv[]) { try { parser.process_args(argc, argv); settings->init(); - } catch (const std::exception &ex) { + } catch (const std::exception& ex) { std::cout << ex.what() << std::endl; return 1; } diff --git a/compiler/kphp_assert.h b/compiler/kphp_assert.h index 7503b6ffe5..9cd0feb655 100644 --- a/compiler/kphp_assert.h +++ b/compiler/kphp_assert.h @@ -6,37 +6,38 @@ #include -#define compiler_assert_(x, y, level, unreachable) ({ \ - int kphp_error_res__ = 0; \ - if (!(x)) { \ - kphp_error_res__ = 1; \ - on_compilation_error (#x, __FILE__, __LINE__, y, level); \ - unreachable; \ - } \ - kphp_error_res__; \ -}) - -#define compiler_assert(x, y, level) compiler_assert_(x, y, level,) +#define compiler_assert_(x, y, level, unreachable) \ + ({ \ + int kphp_error_res__ = 0; \ + if (!(x)) { \ + kphp_error_res__ = 1; \ + on_compilation_error(#x, __FILE__, __LINE__, y, level); \ + unreachable; \ + } \ + kphp_error_res__; \ + }) + +#define compiler_assert(x, y, level) compiler_assert_(x, y, level, ) #define compiler_assert_noret(x, y, level) compiler_assert_(x, y, level, __builtin_unreachable()) -#define kphp_warning(y) compiler_assert (0, y, WRN_ASSERT_LEVEL) -#define kphp_notice(y) compiler_assert (0, y, NOTICE_ASSERT_LEVEL) -#define kphp_error(x, y) compiler_assert (x, y, CE_ASSERT_LEVEL) -#define kphp_error_act(x, y, act) if (kphp_error (x, y)) act -#define kphp_error_return(x, y) kphp_error_act (x, y, return) -#define kphp_assert(x) compiler_assert_noret (x, "Assertion " #x " failed", FATAL_ASSERT_LEVEL) -#define kphp_assert_msg(x, y) compiler_assert_noret (x, y, FATAL_ASSERT_LEVEL) -#define kphp_fail_msg(y) kphp_assert_msg (0, y); _exit(1) -#define kphp_fail() kphp_assert (0); _exit(1) - -enum AssertLevelT { - WRN_ASSERT_LEVEL, - CE_ASSERT_LEVEL, - NOTICE_ASSERT_LEVEL, - FATAL_ASSERT_LEVEL -}; - -void on_compilation_error(const char *description, const char *file_name, int line_number, - const char *full_description, AssertLevelT assert_level); - -void on_compilation_error(const char *description, const char *file_name, int line_number, const std::string &full_description, AssertLevelT assert_level); +#define kphp_warning(y) compiler_assert(0, y, WRN_ASSERT_LEVEL) +#define kphp_notice(y) compiler_assert(0, y, NOTICE_ASSERT_LEVEL) +#define kphp_error(x, y) compiler_assert(x, y, CE_ASSERT_LEVEL) +#define kphp_error_act(x, y, act) \ + if (kphp_error(x, y)) \ + act +#define kphp_error_return(x, y) kphp_error_act(x, y, return) +#define kphp_assert(x) compiler_assert_noret(x, "Assertion " #x " failed", FATAL_ASSERT_LEVEL) +#define kphp_assert_msg(x, y) compiler_assert_noret(x, y, FATAL_ASSERT_LEVEL) +#define kphp_fail_msg(y) \ + kphp_assert_msg(0, y); \ + _exit(1) +#define kphp_fail() \ + kphp_assert(0); \ + _exit(1) + +enum AssertLevelT { WRN_ASSERT_LEVEL, CE_ASSERT_LEVEL, NOTICE_ASSERT_LEVEL, FATAL_ASSERT_LEVEL }; + +void on_compilation_error(const char* description, const char* file_name, int line_number, const char* full_description, AssertLevelT assert_level); + +void on_compilation_error(const char* description, const char* file_name, int line_number, const std::string& full_description, AssertLevelT assert_level); diff --git a/compiler/lambda-utils.cpp b/compiler/lambda-utils.cpp index 093ebac69a..7083c6cb76 100644 --- a/compiler/lambda-utils.cpp +++ b/compiler/lambda-utils.cpp @@ -5,15 +5,15 @@ #include "compiler/lambda-utils.h" #include "compiler/compiler-core.h" -#include "compiler/gentree.h" #include "compiler/data/class-data.h" #include "compiler/data/function-data.h" #include "compiler/data/src-file.h" +#include "compiler/gentree.h" #include "compiler/name-gen.h" #include "compiler/type-hint.h" #include "compiler/utils/string-utils.h" -#include "compiler/vertex.h" #include "compiler/vertex-util.h" +#include "compiler/vertex.h" /* * How do lambdas work. @@ -166,7 +166,6 @@ * for the same reason that we can bind op_invoke_call only at that moment. */ - // this function adds variables from uses_list to arguments // function($x) use ($a) // before: lambda$xxx($x) @@ -244,7 +243,7 @@ static FunctionPtr generate_invoke_method_for_lambda_class(FunctionPtr f_lambda, // implicitly created a class Lambda$xxx { public $a; }, and here we generate // __construct($a) { $this->a = $a; } static FunctionPtr generate_constructor_for_lambda_class(FunctionPtr f_lambda, ClassPtr c_lambda) { - const Location &location = f_lambda->root->location; + const Location& location = f_lambda->root->location; std::vector> construct_params; std::vector fields_initializers; @@ -279,8 +278,7 @@ ClassPtr generate_lambda_class_wrapping_lambda_function(FunctionPtr f_lambda) { var_as_field->str_val = var_as_use->str_val; c_lambda->members.add_instance_field(var_as_field, {}, FieldModifiers{}.set_public(), nullptr, nullptr); - kphp_error(!f_lambda->modifiers.is_static_lambda() || var_as_use->extra_type != op_ex_var_this, - "Using $this in a static lambda"); + kphp_error(!f_lambda->modifiers.is_static_lambda() || var_as_use->extra_type != op_ex_var_this, "Using $this in a static lambda"); } FunctionPtr f_invoke = generate_invoke_method_for_lambda_class(f_lambda, c_lambda); @@ -292,7 +290,7 @@ ClassPtr generate_lambda_class_wrapping_lambda_function(FunctionPtr f_lambda) { G->register_function(f_construct); kphp_assert(!f_lambda->class_id); - f_lambda->class_id = c_lambda; // save the class that wraps this lambda (its __invoke method calls it) + f_lambda->class_id = c_lambda; // save the class that wraps this lambda (its __invoke method calls it) return c_lambda; } @@ -319,8 +317,8 @@ VertexPtr generate_lambda_class_construct_call_replacing_op_lambda(FunctionPtr f // at the moment, it has no implementations: // when actual lambdas are passed/assigned to this typed callable, they will implicitly implement this interface, // and the body of __invoke() method will be generated like a regular virtual function, after processing all lambdas -InterfacePtr generate_interface_from_typed_callable(const TypeHint *type_hint) { - const auto *typed_callable = type_hint->try_as(); +InterfacePtr generate_interface_from_typed_callable(const TypeHint* type_hint) { + const auto* typed_callable = type_hint->try_as(); kphp_assert(typed_callable && typed_callable->is_typed_callable()); std::string interface_name = "ITyped$" + replace_non_alphanum(typed_callable->as_human_readable()); @@ -334,7 +332,7 @@ InterfacePtr generate_interface_from_typed_callable(const TypeHint *type_hint) { auto registered_interface = G->try_register_class(interface); if (registered_interface != interface) { - while (!registered_interface->members.has_any_instance_method()) { // __invoke not registered yet by another thread + while (!registered_interface->members.has_any_instance_method()) { // __invoke not registered yet by another thread usleep(150); } return registered_interface; @@ -371,19 +369,19 @@ void inherit_lambda_class_from_typed_callable(ClassPtr c_lambda, InterfacePtr ty c_lambda->implements.emplace_back(typed_interface); - AutoLocker locker(&(*typed_interface)); + AutoLocker locker(&(*typed_interface)); typed_interface->derived_classes.emplace_back(c_lambda); } // having 'strlen' or [$obj, 'method'] used as callable, generate a lambda // think of it as: fn($s) => strlen($s) or function(...$args) use($obj) { return $obj->method(...$args); } -FunctionPtr generate_lambda_from_string_or_array(FunctionPtr current_function, const std::string &func_name, VertexPtr bound_this, VertexPtr v_location) { +FunctionPtr generate_lambda_from_string_or_array(FunctionPtr current_function, const std::string& func_name, VertexPtr bound_this, VertexPtr v_location) { FunctionPtr f_to_be_wrapped; if (bound_this) { ClassPtr klass = assume_class_of_expr(current_function, bound_this, v_location).try_as_class(); kphp_error_act(klass, fmt_format("Could not detect a class, method {} of which to call", func_name), return {}); - const auto *method = klass->get_instance_method(func_name); + const auto* method = klass->get_instance_method(func_name); kphp_error_act(method, fmt_format("Could not find a method {} in class {}", func_name, klass->as_human_readable()), return {}); f_to_be_wrapped = method->function; } else { @@ -391,7 +389,8 @@ FunctionPtr generate_lambda_from_string_or_array(FunctionPtr current_function, c } kphp_error_act(f_to_be_wrapped, fmt_format("Could not find a function {}", func_name), return {}); - kphp_error_act(f_to_be_wrapped->is_required, fmt_format("{} needs the @kphp-required tag, because it's used only as a string callback", f_to_be_wrapped->as_human_readable()), return {}); + kphp_error_act(f_to_be_wrapped->is_required, + fmt_format("{} needs the @kphp-required tag, because it's used only as a string callback", f_to_be_wrapped->as_human_readable()), return {}); std::vector> w_params; std::vector w_call_args; @@ -424,7 +423,7 @@ FunctionPtr generate_lambda_from_string_or_array(FunctionPtr current_function, c if (bound_this) { w_call->extra_type = op_ex_func_call_arrow; - if (auto bound_this_var = bound_this.try_as()) { // [$inst, 'method'], not [getInst(), 'method'] + if (auto bound_this_var = bound_this.try_as()) { // [$inst, 'method'], not [getInst(), 'method'] f_lambda->uses_list.emplace_front(bound_this_var); } } @@ -435,13 +434,10 @@ FunctionPtr generate_lambda_from_string_or_array(FunctionPtr current_function, c // having fn($x) => $x + $other + $captured + $variables, // walk the arrow function body and capture them by value (fill f_lambda->uses_list) void auto_capture_vars_from_body_in_arrow_lambda(FunctionPtr f_lambda) { - auto needs_to_be_captured = [f_lambda](const std::string &var_name) { - return var_name != "this" && // $this is captured by another approach, in non-arrow lambdas also - var_name.find("::") == std::string::npos && - var_name.find("$u") == std::string::npos && // not a superlocal var created in gentree - !VarData::does_name_eq_any_language_superglobal(var_name) && - !f_lambda->find_param_by_name(var_name) && - !f_lambda->find_use_by_name(var_name); + auto needs_to_be_captured = [f_lambda](const std::string& var_name) { + return var_name != "this" && // $this is captured by another approach, in non-arrow lambdas also + var_name.find("::") == std::string::npos && var_name.find("$u") == std::string::npos && // not a superlocal var created in gentree + !VarData::does_name_eq_any_language_superglobal(var_name) && !f_lambda->find_param_by_name(var_name) && !f_lambda->find_use_by_name(var_name); }; std::function find_recursive = [&find_recursive, &needs_to_be_captured, f_lambda](VertexPtr root) { @@ -450,7 +446,7 @@ void auto_capture_vars_from_body_in_arrow_lambda(FunctionPtr f_lambda) { f_lambda->uses_list.emplace_front(v); } } else if (auto inner_lambda = root.try_as()) { - for (auto v : inner_lambda->func_id->uses_list) { // bubble up uses from nested lambdas + for (auto v : inner_lambda->func_id->uses_list) { // bubble up uses from nested lambdas if (needs_to_be_captured(v->str_val)) { f_lambda->uses_list.emplace_front(v); } diff --git a/compiler/lambda-utils.h b/compiler/lambda-utils.h index fb60ed7335..ed6088b286 100644 --- a/compiler/lambda-utils.h +++ b/compiler/lambda-utils.h @@ -13,6 +13,6 @@ void auto_capture_vars_from_body_in_arrow_lambda(FunctionPtr f_lambda); void patch_lambda_function_add_uses_as_arguments(FunctionPtr f_lambda); ClassPtr generate_lambda_class_wrapping_lambda_function(FunctionPtr f_lambda); VertexPtr generate_lambda_class_construct_call_replacing_op_lambda(FunctionPtr f_lambda, VertexAdaptor v_lambda); -InterfacePtr generate_interface_from_typed_callable(const TypeHint *type_hint); +InterfacePtr generate_interface_from_typed_callable(const TypeHint* type_hint); void inherit_lambda_class_from_typed_callable(ClassPtr c_lambda, InterfacePtr typed_interface); -FunctionPtr generate_lambda_from_string_or_array(FunctionPtr current_function, const std::string &func_name, VertexPtr bound_this, VertexPtr v_location); +FunctionPtr generate_lambda_from_string_or_array(FunctionPtr current_function, const std::string& func_name, VertexPtr bound_this, VertexPtr v_location); diff --git a/compiler/lexer.cpp b/compiler/lexer.cpp index 0d6844893b..06fcf028d2 100644 --- a/compiler/lexer.cpp +++ b/compiler/lexer.cpp @@ -26,12 +26,12 @@ void LexerData::new_line() { line_num++; } -LexerData::LexerData(vk::string_view new_code) : - code(new_code.data()), - code_end(code + new_code.size()), - code_len(new_code.size()) { +LexerData::LexerData(vk::string_view new_code) + : code(new_code.data()), + code_end(code + new_code.size()), + code_len(new_code.size()) { new_line(); - tokens.reserve(static_cast(code_len * 0.3)); + tokens.reserve(static_cast(code_len * 0.3)); } void LexerData::pass(int shift) { @@ -43,19 +43,19 @@ void LexerData::pass_raw(int shift) { code += shift; } -template -void LexerData::add_token_(int shift, Args&& ...tok) { - kphp_assert (code + shift <= code_end); +template +void LexerData::add_token_(int shift, Args&&... tok) { + kphp_assert(code + shift <= code_end); tokens.emplace_back(std::forward(tok)...); tokens.back().line_num = line_num; tokens.back().debug_str = vk::string_view(code, code + shift); - //fprintf (stderr, "[%d] %.*s : %d\n", tok->type(), tok->debug_str.length(), tok->debug_str.begin(), line_num); + // fprintf (stderr, "[%d] %.*s : %d\n", tok->type(), tok->debug_str.length(), tok->debug_str.begin(), line_num); pass(shift); hack_last_tokens(); } -template -void LexerData::add_token(int shift, Args&& ...tok) { +template +void LexerData::add_token(int shift, Args&&... tok) { flush_str(); add_token_(shift, std::forward(tok)...); } @@ -81,13 +81,13 @@ void LexerData::append_char(int c) { } if (c == -1) { int c = *get_code(); - *const_cast(str_cur++) = (char)c; + *const_cast(str_cur++) = (char)c; if (c == '\n') { new_line(); } pass_raw(1); } else { - *const_cast(str_cur++) = (char)c; + *const_cast(str_cur++) = (char)c; } } @@ -95,7 +95,7 @@ void LexerData::flush_str() { if (in_gen_str) { add_token_(0, tok_str, str_begin, str_cur); while (str_cur != get_code()) { - *const_cast(str_cur++) = ' '; + *const_cast(str_cur++) = ' '; } in_gen_str = false; } @@ -105,24 +105,19 @@ bool LexerData::are_last_tokens() { return true; } -template -bool LexerData::are_last_tokens(TokenType type1, Args ...args) { - return tokens.size() >= (sizeof...(args) + 1) && - tokens[tokens.size() - sizeof...(args) - 1].type() == type1 && - are_last_tokens(args...); +template +bool LexerData::are_last_tokens(TokenType type1, Args... args) { + return tokens.size() >= (sizeof...(args) + 1) && tokens[tokens.size() - sizeof...(args) - 1].type() == type1 && are_last_tokens(args...); } -template -bool LexerData::are_last_tokens(any_token_tag, Args ...args) { - return tokens.size() >= (sizeof...(args) + 1) && - are_last_tokens(args...); +template +bool LexerData::are_last_tokens(any_token_tag, Args... args) { + return tokens.size() >= (sizeof...(args) + 1) && are_last_tokens(args...); } -template -bool LexerData::are_last_tokens(except_token_tag, Args ...args) { - return tokens.size() >= (sizeof...(args) + 1) && - tokens[tokens.size() - sizeof...(args) - 1].type() != token && - are_last_tokens(args...); +template +bool LexerData::are_last_tokens(except_token_tag, Args... args) { + return tokens.size() >= (sizeof...(args) + 1) && tokens[tokens.size() - sizeof...(args) - 1].type() != token && are_last_tokens(args...); } vk::string_view LexerData::strip_whitespaces(char space_char, std::size_t spaces_to_skip, vk::string_view source) noexcept { @@ -154,24 +149,16 @@ void LexerData::hack_last_tokens() { return; } - auto remove_last_tokens = [this](size_t cnt) { - tokens.erase(std::prev(tokens.end(), cnt), tokens.end()); - }; + auto remove_last_tokens = [this](size_t cnt) { tokens.erase(std::prev(tokens.end(), cnt), tokens.end()); }; // perform a cast array matching only if we have something // that looks like a cast (a token surrounded by parenthesis) if (are_last_tokens(tok_oppar, any_token_tag{}, tok_clpar)) { static TokenType casts[][2] = { - {tok_int, tok_conv_int}, - {tok_float, tok_conv_float}, - {tok_double, tok_conv_float}, - {tok_string, tok_conv_string}, - {tok_array, tok_conv_array}, - {tok_object, tok_conv_object}, - {tok_bool, tok_conv_bool}, - {tok_boolean, tok_conv_bool}, + {tok_int, tok_conv_int}, {tok_float, tok_conv_float}, {tok_double, tok_conv_float}, {tok_string, tok_conv_string}, + {tok_array, tok_conv_array}, {tok_object, tok_conv_object}, {tok_bool, tok_conv_bool}, {tok_boolean, tok_conv_bool}, }; - for (auto &cast : casts) { + for (auto& cast : casts) { // check the middle token, the one that goes before ')' if (tokens[tokens.size() - 2].type() == cast[0]) { remove_last_tokens(3); @@ -284,7 +271,8 @@ void LexerData::hack_last_tokens() { * A kludge to parse functions with such names correctly in functions.txt; * but keep them as a separate token kinds as they need a slightly different parsing */ - if (are_last_tokens(tok_function, tok_var_dump) || are_last_tokens(tok_function, tok_dbg_echo) || are_last_tokens(tok_function, tok_print) || are_last_tokens(tok_function, tok_echo)) { + if (are_last_tokens(tok_function, tok_var_dump) || are_last_tokens(tok_function, tok_dbg_echo) || are_last_tokens(tok_function, tok_print) || + are_last_tokens(tok_function, tok_echo)) { tokens.back() = {tok_func_name, tokens.back().str_val}; } @@ -304,7 +292,7 @@ void LexerData::set_dont_hack_last_tokens() { dont_hack_last_tokens = true; } -std::vector &&LexerData::move_tokens() { +std::vector&& LexerData::move_tokens() { return std::move(tokens); } @@ -312,11 +300,10 @@ int LexerData::get_line_num() { return line_num; } +bool parse_with_helper(LexerData* lexer_data, const std::unique_ptr>& h) { + const char* s = lexer_data->get_code(); -bool parse_with_helper(LexerData *lexer_data, const std::unique_ptr> &h) { - const char *s = lexer_data->get_code(); - - TokenLexer *fnd = h->get_help(s); + TokenLexer* fnd = h->get_help(s); if (fnd && fnd->parse(lexer_data)) { return true; @@ -324,13 +311,13 @@ bool parse_with_helper(LexerData *lexer_data, const std::unique_ptrget_default()->parse(lexer_data); } -bool TokenLexerError::parse(LexerData *lexer_data) const { +bool TokenLexerError::parse(LexerData* lexer_data) const { stage::set_line(lexer_data->get_line_num()); - kphp_error (0, error_str.c_str()); + kphp_error(0, error_str.c_str()); return false; } -bool TokenLexerName::parse(LexerData *lexer_data) const { +bool TokenLexerName::parse(LexerData* lexer_data) const { const char *s = lexer_data->get_code(), *st = s; const TokenType type = s[0] == '$' ? tok_var_name : tok_func_name; @@ -338,7 +325,7 @@ bool TokenLexerName::parse(LexerData *lexer_data) const { ++s; } - const char *t = s; + const char* t = s; bool closing_curly = false; // whether it's a ${varname} and we need to find matching '}' if (type == tok_var_name) { if (t[0] == '{') { @@ -364,7 +351,7 @@ bool TokenLexerName::parse(LexerData *lexer_data) const { if (t[-1] == '\\') { bad = true; } - for (const char *cur = s; cur + 1 != t; cur++) { + for (const char* cur = s; cur + 1 != t; cur++) { if (cur[0] == '\\' && cur[1] == '\\') { bad = true; break; @@ -390,7 +377,7 @@ bool TokenLexerName::parse(LexerData *lexer_data) const { } if (type == tok_func_name) { - const KeywordType *tp = KeywordsSet::get_type(name.begin(), name.size()); + const KeywordType* tp = KeywordsSet::get_type(name.begin(), name.size()); if (tp != nullptr) { lexer_data->add_token((int)(t - st), tp->type, s, t); return true; @@ -403,10 +390,10 @@ bool TokenLexerName::parse(LexerData *lexer_data) const { return true; } -bool TokenLexerNum::parse(LexerData *lexer_data) const { - const char *s = lexer_data->get_code(); +bool TokenLexerNum::parse(LexerData* lexer_data) const { + const char* s = lexer_data->get_code(); - const char *t = s; + const char* t = s; enum { before_dot, @@ -437,125 +424,125 @@ bool TokenLexerNum::parse(LexerData *lexer_data) const { continue; } switch (state) { - case hex: { - switch (*t) { - case '0' ... '9': - case 'A' ... 'F': - case 'a' ... 'f': - t++; - break; - default: - state = finish; - break; - } + case hex: { + switch (*t) { + case '0' ... '9': + case 'A' ... 'F': + case 'a' ... 'f': + t++; + break; + default: + state = finish; break; } - case binary: { - switch(*t) { - case '0': - case '1': - t++; - break; - default: - state = finish; - break; - } + break; + } + case binary: { + switch (*t) { + case '0': + case '1': + t++; + break; + default: + state = finish; break; } - case before_dot: { - switch (*t) { - case '0' ... '9': { - t++; - break; - } - case '.': { - t++; - is_float = true; - state = after_dot; - break; - } - case 'e': - case 'E': { - t++; - is_float = true; - state = after_e; - break; - } - default: { - state = finish; - break; - } - } + break; + } + case before_dot: { + switch (*t) { + case '0' ... '9': { + t++; break; } - case after_dot: { - switch (*t) { - case '0' ... '9': { - t++; - break; - } - case 'e': - case 'E': { - t++; - state = after_e; - break; - } - default: { - state = finish; - break; - } - } + case '.': { + t++; + is_float = true; + state = after_dot; break; } - case after_e: { - switch (*t) { - case '-': - case '+': { - t++; - state = after_e_and_sign; - break; - } - case '0' ... '9': { - t++; - state = after_e_and_digit; - break; - } - default: { - return TokenLexerError("Bad exponent").parse(lexer_data); - } - } + case 'e': + case 'E': { + t++; + is_float = true; + state = after_e; break; } - case after_e_and_sign: { - switch (*t) { - case '0' ... '9': { - t++; - state = after_e_and_digit; - break; - } - default: { - return TokenLexerError("Bad exponent").parse(lexer_data); - } - } + default: { + state = finish; break; } - case after_e_and_digit: { - switch (*t) { - case '0' ... '9': { - t++; - break; - } - default: { - state = finish; - break; - } - } + } + break; + } + case after_dot: { + switch (*t) { + case '0' ... '9': { + t++; break; } - - case finish: { - assert (0); + case 'e': + case 'E': { + t++; + state = after_e; + break; } + default: { + state = finish; + break; + } + } + break; + } + case after_e: { + switch (*t) { + case '-': + case '+': { + t++; + state = after_e_and_sign; + break; + } + case '0' ... '9': { + t++; + state = after_e_and_digit; + break; + } + default: { + return TokenLexerError("Bad exponent").parse(lexer_data); + } + } + break; + } + case after_e_and_sign: { + switch (*t) { + case '0' ... '9': { + t++; + state = after_e_and_digit; + break; + } + default: { + return TokenLexerError("Bad exponent").parse(lexer_data); + } + } + break; + } + case after_e_and_digit: { + switch (*t) { + case '0' ... '9': { + t++; + break; + } + default: { + state = finish; + break; + } + } + break; + } + + case finish: { + assert(0); + } } } @@ -569,7 +556,7 @@ bool TokenLexerNum::parse(LexerData *lexer_data) const { } } - assert (t != s); + assert(t != s); auto token_type = is_float ? tok_float_const : tok_int_const; @@ -582,42 +569,41 @@ bool TokenLexerNum::parse(LexerData *lexer_data) const { return true; } - -bool TokenLexerSimpleString::parse(LexerData *lexer_data) const { +bool TokenLexerSimpleString::parse(LexerData* lexer_data) const { std::string str; - const char *s = lexer_data->get_code(); - const char *t = s + 1; + const char* s = lexer_data->get_code(); + const char* t = s + 1; lexer_data->pass_raw(1); bool need = true; lexer_data->start_str(); while (need) { switch (t[0]) { - case 0: - return TokenLexerError("Unexpected end of file").parse(lexer_data); + case 0: + return TokenLexerError("Unexpected end of file").parse(lexer_data); - case '\'': - need = false; - t++; - continue; + case '\'': + need = false; + t++; + continue; - case '\\': - if (t[1] == '\\') { - t += 2; - lexer_data->append_char('\\'); - lexer_data->pass_raw(2); - continue; - } else if (t[1] == '\'') { - t += 2; - lexer_data->append_char('\''); - lexer_data->pass_raw(2); - continue; - } - break; + case '\\': + if (t[1] == '\\') { + t += 2; + lexer_data->append_char('\\'); + lexer_data->pass_raw(2); + continue; + } else if (t[1] == '\'') { + t += 2; + lexer_data->append_char('\''); + lexer_data->pass_raw(2); + continue; + } + break; - default: - break; + default: + break; } lexer_data->append_char(-1); t++; @@ -627,13 +613,13 @@ bool TokenLexerSimpleString::parse(LexerData *lexer_data) const { return true; } -bool TokenLexerAppendChar::parse(LexerData *lexer_data) const { +bool TokenLexerAppendChar::parse(LexerData* lexer_data) const { lexer_data->append_char(c); lexer_data->pass_raw(pass); return true; } -bool TokenLexerOctChar::parse(LexerData *lexer_data) const { +bool TokenLexerOctChar::parse(LexerData* lexer_data) const { const char *s = lexer_data->get_code(), *t = s; int val = t[1] - '0'; t += 2; @@ -649,13 +635,13 @@ bool TokenLexerOctChar::parse(LexerData *lexer_data) const { } } - //TODO: \777 + // TODO: \777 lexer_data->append_char(val); lexer_data->pass_raw((int)(t - s)); return true; } -bool TokenLexerHexChar::parse(LexerData *lexer_data) const { +bool TokenLexerHexChar::parse(LexerData* lexer_data) const { const char *s = lexer_data->get_code(), *t = s + 2; int val = conv_hex_digit(*t); if (val == -1) { @@ -682,15 +668,15 @@ void TokenLexerStringSimpleExpr::init() { h->add_simple_rule("", &vk::singleton::get()); } -bool TokenLexerStringSimpleExpr::parse_operand(LexerData *lexer_data, TokenType type = tok_func_name) const { +bool TokenLexerStringSimpleExpr::parse_operand(LexerData* lexer_data, TokenType type = tok_func_name) const { // in places where we expect a "name" we call this method instead of parse_with_helper // as we don't want \\ to become a part of the name; // in strings, $x->y\n should produce a tok_var_name($x) tok_arrow tok_func_name(y) tok_str(\n), // not tok_var_name($x) tok_arrow tok_func_name(y\n) as it would do if we used // a TokenLexerName for that. - const char *begin = lexer_data->get_code(); - const char *s = begin; + const char* begin = lexer_data->get_code(); + const char* s = begin; if (!is_alpha(*s)) { return parse_with_helper(lexer_data, h); @@ -706,7 +692,7 @@ bool TokenLexerStringSimpleExpr::parse_operand(LexerData *lexer_data, TokenType return true; } -bool TokenLexerStringSimpleExpr::parse(LexerData *lexer_data) const { +bool TokenLexerStringSimpleExpr::parse(LexerData* lexer_data) const { assert(h != nullptr); lexer_data->add_token(0, tok_expr_begin); @@ -715,7 +701,7 @@ bool TokenLexerStringSimpleExpr::parse(LexerData *lexer_data) const { return false; } - const char *s = lexer_data->get_code(); + const char* s = lexer_data->get_code(); bool ok = true; if (*s == 0) { ok = false; @@ -747,22 +733,22 @@ void TokenLexerStringExpr::init() { h->add_simple_rule("\"", &vk::singleton::get()); h->add_rule("[a-zA-Z_$\\]", &vk::singleton::get()); - //TODO: double (?) + // TODO: double (?) h->add_rule("[0-9]|.[0-9]", &vk::singleton::get()); h->add_rule(" |\t|\n|\r", &vk::singleton::get()); h->add_simple_rule("", &vk::singleton::get()); } -bool TokenLexerStringExpr::parse(LexerData *lexer_data) const { - assert (h != nullptr); - const char *s = lexer_data->get_code(); - assert (*s == '{'); +bool TokenLexerStringExpr::parse(LexerData* lexer_data) const { + assert(h != nullptr); + const char* s = lexer_data->get_code(); + assert(*s == '{'); lexer_data->add_token(1, tok_expr_begin); int bal = 0; while (true) { - const char *s = lexer_data->get_code(); + const char* s = lexer_data->get_code(); if (*s == 0) { return TokenLexerError("Unexpected end of file").parse(lexer_data); @@ -783,12 +769,11 @@ bool TokenLexerStringExpr::parse(LexerData *lexer_data) const { return true; } - -void TokenLexerString::add_esc(const std::string &s, char c) { +void TokenLexerString::add_esc(const std::string& s, char c) { h->add_simple_rule(s, new TokenLexerAppendChar(c, (int)s.size())); } -void TokenLexerHeredocString::add_esc(const std::string &s, char c) { +void TokenLexerHeredocString::add_esc(const std::string& s, char c) { h->add_simple_rule(s, new TokenLexerAppendChar(c, (int)s.size())); } @@ -831,16 +816,16 @@ void TokenLexerHeredocString::init() { h->add_simple_rule("{$", &vk::singleton::get()); } -bool TokenLexerString::parse(LexerData *lexer_data) const { - assert (h != nullptr); - const char *s = lexer_data->get_code(); +bool TokenLexerString::parse(LexerData* lexer_data) const { + assert(h != nullptr); + const char* s = lexer_data->get_code(); int is_heredoc = s[0] == '<'; - assert (!is_heredoc); + assert(!is_heredoc); lexer_data->add_token(1, tok_str_begin); while (true) { - const char *s = lexer_data->get_code(); + const char* s = lexer_data->get_code(); if (*s == '\"') { lexer_data->add_token(1, tok_str_end); break; @@ -857,14 +842,14 @@ bool TokenLexerString::parse(LexerData *lexer_data) const { return true; } -bool TokenLexerHeredocString::parse(LexerData *lexer_data) const { - const char *s = lexer_data->get_code(); +bool TokenLexerHeredocString::parse(LexerData* lexer_data) const { + const char* s = lexer_data->get_code(); int is_heredoc = s[0] == '<'; - assert (is_heredoc); + assert(is_heredoc); std::string tag; - const char *st = s; - assert (s[1] == '<' && s[2] == '<'); + const char* st = s; + assert(s[1] == '<' && s[2] == '<'); s += 3; @@ -902,19 +887,19 @@ bool TokenLexerHeredocString::parse(LexerData *lexer_data) const { if (!single_quote) { lexer_data->add_token((int)(s - st), tok_str_begin); - assert (s == lexer_data->get_code()); + assert(s == lexer_data->get_code()); } else { lexer_data->start_str(); lexer_data->pass_raw((int)(s - st)); - assert (s == lexer_data->get_code()); + assert(s == lexer_data->get_code()); } bool first = true; while (true) { - const char *s = lexer_data->get_code(); + const char* s = lexer_data->get_code(); const char *t = s, *st = s; if (t[0] == '\n' || first) { t += t[0] == '\n'; - const char *const spaces_start = t; + const char* const spaces_start = t; std::size_t spaces_count = 0; std::size_t tabs_count = 0; for (; *t != '\0'; ++t) { @@ -942,7 +927,8 @@ bool TokenLexerHeredocString::parse(LexerData *lexer_data) const { lexer_data->add_token((int)(t - st - semicolon), tok_str_end); } else { lexer_data->flush_str(); - lexer_data->pass_raw((int)(t - st - semicolon));; + lexer_data->pass_raw((int)(t - st - semicolon)); + ; } if (std::size_t indent = spaces_count ?: tabs_count) { lexer_data->add_token(0, tok_str_skip_indent, spaces_start, spaces_start + indent); @@ -968,11 +954,10 @@ bool TokenLexerHeredocString::parse(LexerData *lexer_data) const { return true; } -bool TokenLexerComment::parse(LexerData *lexer_data) const { - const char *s = lexer_data->get_code(), - *st = s; +bool TokenLexerComment::parse(LexerData* lexer_data) const { + const char *s = lexer_data->get_code(), *st = s; - assert (s[0] == '/' || s[0] == '#'); + assert(s[0] == '/' || s[0] == '#'); if (s[0] == '#' || s[1] == '/') { while (s[0] && s[0] != '\n') { s++; @@ -980,7 +965,7 @@ bool TokenLexerComment::parse(LexerData *lexer_data) const { } else { s += 2; if (s[0] && s[1] && s[0] == '*' && s[1] != '/') { // phpdoc - char const *phpdoc_start = s; + char const* phpdoc_start = s; bool is_phpdoc = false; while (s[0] && (s[0] != '*' || s[1] != '/')) { // @return, @var, @param, @type, etc @@ -993,7 +978,7 @@ bool TokenLexerComment::parse(LexerData *lexer_data) const { lexer_data->add_token(0, tok_phpdoc, phpdoc_start, s); } } else if (s[0] && s[1] && s[0] == '<') { // generics commentTs: /**/ - char const *inst_start = ++s; + char const* inst_start = ++s; while (s[0] && (s[0] != '*' || s[1] != '/')) { s++; } @@ -1017,9 +1002,8 @@ bool TokenLexerComment::parse(LexerData *lexer_data) const { return true; } -bool TokenLexerIfndefComment::parse(LexerData *lexer_data) const { - kphp_assert(lexer_data->get_code_view().starts_with("#ifndef KPHP") - || lexer_data->get_code_view().starts_with("#ifndef K2")); +bool TokenLexerIfndefComment::parse(LexerData* lexer_data) const { + kphp_assert(lexer_data->get_code_view().starts_with("#ifndef KPHP") || lexer_data->get_code_view().starts_with("#ifndef K2")); auto endif_pos = lexer_data->get_code_view().find("#endif"); if (endif_pos == vk::string_view::npos) { @@ -1030,17 +1014,17 @@ bool TokenLexerIfndefComment::parse(LexerData *lexer_data) const { return true; } -bool TokenLexerWithHelper::parse(LexerData *lexer_data) const { - assert (h != nullptr); +bool TokenLexerWithHelper::parse(LexerData* lexer_data) const { + assert(h != nullptr); return parse_with_helper(lexer_data, h); } -bool TokenLexerToken::parse(LexerData *lexer_data) const { +bool TokenLexerToken::parse(LexerData* lexer_data) const { lexer_data->add_token(len, tp); return true; } -void TokenLexerCommon::add_rule(const std::unique_ptr> &h, const std::string &str, TokenType tp) { +void TokenLexerCommon::add_rule(const std::unique_ptr>& h, const std::string& str, TokenType tp) { h->add_simple_rule(str, new TokenLexerToken(tp, (int)str.size())); } @@ -1048,7 +1032,7 @@ void TokenLexerCommon::init() { assert(!h); h = std::make_unique>(new TokenLexerError("No found")); - add_rule(h, ":::", tok_triple_colon); // used in functions.txt to express cast params + add_rule(h, ":::", tok_triple_colon); // used in functions.txt to express cast params add_rule(h, "=", tok_eq1); add_rule(h, "==", tok_eq2); @@ -1116,7 +1100,7 @@ void TokenLexerCommon::init() { add_rule(h, "...", tok_varg); } -bool TokenLexerSkip::parse(LexerData *lexer_data) const { +bool TokenLexerSkip::parse(LexerData* lexer_data) const { lexer_data->pass(n); return true; } @@ -1138,13 +1122,13 @@ void TokenLexerPHP::init() { h->add_simple_rule("", &vk::singleton::get()); } -void TokenLexerPHPDoc::add_rule(const std::unique_ptr> &h, const std::string &str, TokenType tp) { +void TokenLexerPHPDoc::add_rule(const std::unique_ptr>& h, const std::string& str, TokenType tp) { h->add_simple_rule(str, new TokenLexerToken(tp, (int)str.size())); } void TokenLexerPHPDoc::init() { struct TokenLexerPHPDocStopParsing final : TokenLexer { - bool parse(LexerData *lexer_data) const final { + bool parse(LexerData* lexer_data) const final { lexer_data->add_token(0, tok_end); lexer_data->pass(1); return false; @@ -1185,9 +1169,9 @@ void TokenLexerPHPDoc::init() { add_rule(h, "=", tok_eq1); } -bool TokenLexerGlobal::parse(LexerData *lexer_data) const { - const char *s = lexer_data->get_code(); - const char *t = s; +bool TokenLexerGlobal::parse(LexerData* lexer_data) const { + const char* s = lexer_data->get_code(); + const char* t = s; while (*t && strncmp(t, "pass_raw(strlen("get_code(); - const char *t = s; + const char* s = lexer_data->get_code(); + const char* t = s; while (t[0] == ' ' || t[0] == '\t') { t++; } @@ -1253,7 +1236,7 @@ void lexer_init() { } void k2_lexer_init() { - auto & h = vk::singleton::get().h; + auto& h = vk::singleton::get().h; h->add_simple_rule("#ifndef K2", &vk::singleton::get()); } @@ -1295,4 +1278,3 @@ std::vector phpdoc_to_tokens(vk::string_view text) { } return lexer_data.move_tokens(); } - diff --git a/compiler/lexer.h b/compiler/lexer.h index 6b9042ba7f..b900a75b61 100644 --- a/compiler/lexer.h +++ b/compiler/lexer.h @@ -17,31 +17,37 @@ struct LexerData : private vk::not_copyable { explicit LexerData(vk::string_view new_code); void new_line(); - const char *get_code() const { return code; } - vk::string_view get_code_view() const { return vk::string_view{code, code_end}; }; + const char* get_code() const { + return code; + } + vk::string_view get_code_view() const { + return vk::string_view{code, code_end}; + } void pass(int shift); void pass_raw(int shift); - template - void add_token_(int shift, Args&& ...tok); - template - void add_token(int shift, Args&& ...tok); + template + void add_token_(int shift, Args&&... tok); + template + void add_token(int shift, Args&&... tok); void start_str(); void append_char(int c); void flush_str(); void hack_last_tokens(); void set_dont_hack_last_tokens(); - struct any_token_tag{}; + struct any_token_tag {}; template - struct except_token_tag{}; - template - bool are_last_tokens(TokenType type1, Args ...args); - template - bool are_last_tokens(any_token_tag type1, Args ...args); - template - bool are_last_tokens(except_token_tag type1, Args ...args); + struct except_token_tag {}; + template + bool are_last_tokens(TokenType type1, Args... args); + template + bool are_last_tokens(any_token_tag type1, Args... args); + template + bool are_last_tokens(except_token_tag type1, Args... args); bool are_last_tokens(); - int get_num_tokens() const { return tokens.size(); } + int get_num_tokens() const { + return tokens.size(); + } std::vector&& move_tokens(); int get_line_num(); @@ -50,137 +56,132 @@ struct LexerData : private vk::not_copyable { vk::string_view strip_whitespaces(char space_char, std::size_t spaces_to_skip, vk::string_view source) noexcept; int line_num{0}; - const char *code{nullptr}; - const char *code_end{nullptr}; + const char* code{nullptr}; + const char* code_end{nullptr}; int code_len{0}; std::vector tokens; bool in_gen_str{false}; - const char *str_begin{nullptr}; - const char *str_cur{nullptr}; + const char* str_begin{nullptr}; + const char* str_cur{nullptr}; bool dont_hack_last_tokens{false}; }; struct TokenLexer : private vk::not_copyable { - virtual bool parse(LexerData *lexer_data) const = 0; + virtual bool parse(LexerData* lexer_data) const = 0; virtual ~TokenLexer() = default; }; -//TODO ?? -bool parse_with_helper(LexerData *lexer_data, const std::unique_ptr> &h); +// TODO ?? +bool parse_with_helper(LexerData* lexer_data, const std::unique_ptr>& h); struct TokenLexerError final : TokenLexer { std::string error_str; - explicit TokenLexerError(std::string error_str = "unknown_error") : - error_str(std::move(error_str)) { - } + explicit TokenLexerError(std::string error_str = "unknown_error") + : error_str(std::move(error_str)) {} - bool parse(LexerData *lexer_data) const final; + bool parse(LexerData* lexer_data) const final; }; struct TokenLexerName final : TokenLexer { - bool parse(LexerData *lexer_data) const final; + bool parse(LexerData* lexer_data) const final; }; struct TokenLexerNum final : TokenLexer { - bool parse(LexerData *lexer_data) const final; + bool parse(LexerData* lexer_data) const final; }; struct TokenLexerSimpleString final : TokenLexer { - bool parse(LexerData *lexer_data) const final; + bool parse(LexerData* lexer_data) const final; }; struct TokenLexerAppendChar final : TokenLexer { int c, pass; - TokenLexerAppendChar(int c, int pass) : - c(c), - pass(pass) { - } + TokenLexerAppendChar(int c, int pass) + : c(c), + pass(pass) {} - bool parse(LexerData *lexer_data) const final; + bool parse(LexerData* lexer_data) const final; }; struct TokenLexerOctChar final : TokenLexer { - bool parse(LexerData *lexer_data) const final; + bool parse(LexerData* lexer_data) const final; }; struct TokenLexerHexChar final : TokenLexer { - bool parse(LexerData *lexer_data) const final; + bool parse(LexerData* lexer_data) const final; }; struct TokenLexerStringSimpleExpr final : TokenLexer { std::unique_ptr> h; void init(); - bool parse(LexerData *lexer_data) const final; - bool parse_operand(LexerData *lexer_data, TokenType type) const; + bool parse(LexerData* lexer_data) const final; + bool parse_operand(LexerData* lexer_data, TokenType type) const; }; struct TokenLexerStringExpr final : TokenLexer { std::unique_ptr> h; void init(); - bool parse(LexerData *lexer_data) const final; + bool parse(LexerData* lexer_data) const final; }; struct TokenLexerHeredocString final : TokenLexer { std::unique_ptr> h; - void add_esc(const std::string &s, char c); + void add_esc(const std::string& s, char c); void init(); - bool parse(LexerData *lexer_data) const final; + bool parse(LexerData* lexer_data) const final; }; struct TokenLexerString final : TokenLexer { std::unique_ptr> h; - void add_esc(const std::string &s, char c); + void add_esc(const std::string& s, char c); void init(); - bool parse(LexerData *lexer_data) const final; + bool parse(LexerData* lexer_data) const final; }; - struct TokenLexerComment final : TokenLexer { - bool parse(LexerData *lexer_data) const final; + bool parse(LexerData* lexer_data) const final; }; struct TokenLexerIfndefComment final : TokenLexer { - bool parse(LexerData *lexer_data) const final; + bool parse(LexerData* lexer_data) const final; }; struct TokenLexerWithHelper : TokenLexer { std::unique_ptr> h; virtual void init() = 0; - bool parse(LexerData *lexer_data) const final; + bool parse(LexerData* lexer_data) const final; }; struct TokenLexerToken final : TokenLexer { TokenType tp; int len; - TokenLexerToken(TokenType tp, int len) : - tp(tp), - len(len) { - } + TokenLexerToken(TokenType tp, int len) + : tp(tp), + len(len) {} - bool parse(LexerData *lexer_data) const final; + bool parse(LexerData* lexer_data) const final; }; struct TokenLexerCommon final : TokenLexerWithHelper { - inline void add_rule(const std::unique_ptr> &h, const std::string &str, TokenType tp); + inline void add_rule(const std::unique_ptr>& h, const std::string& str, TokenType tp); void init() final; }; struct TokenLexerSkip final : TokenLexer { int n; - explicit TokenLexerSkip(int n = 1) : - n(n) { - } + explicit TokenLexerSkip(int n = 1) + : n(n) {} - bool parse(LexerData *lexer_data) const final; + bool parse(LexerData* lexer_data) const final; }; struct TokenLexerPHP final : TokenLexerWithHelper { @@ -188,15 +189,15 @@ struct TokenLexerPHP final : TokenLexerWithHelper { }; struct TokenLexerPHPDoc final : TokenLexerWithHelper { - inline void add_rule(const std::unique_ptr> &h, const std::string &str, TokenType tp); + inline void add_rule(const std::unique_ptr>& h, const std::string& str, TokenType tp); void init() final; }; struct TokenLexerGlobal final : TokenLexer { - TokenLexerPHP *php_lexer{&vk::singleton::get()}; + TokenLexerPHP* php_lexer{&vk::singleton::get()}; - bool parse(LexerData *lexer_data) const final; + bool parse(LexerData* lexer_data) const final; }; void lexer_init(); diff --git a/compiler/location.h b/compiler/location.h index 479bdeee82..ef6328d7a2 100644 --- a/compiler/location.h +++ b/compiler/location.h @@ -8,26 +8,34 @@ #include "compiler/debug.h" class Location { - DEBUG_STRING_METHOD { return as_human_readable(); } - + DEBUG_STRING_METHOD { + return as_human_readable(); + } + public: SrcFilePtr file; FunctionPtr function; int line = -1; Location() = default; - explicit Location(int line) : line(line) {} - Location(const SrcFilePtr &file, const FunctionPtr &function, int line); + explicit Location(int line) + : line(line) {} + Location(const SrcFilePtr& file, const FunctionPtr& function, int line); void set_file(SrcFilePtr file); void set_function(FunctionPtr function); void set_line(int line); - SrcFilePtr get_file() const { return file; } - FunctionPtr get_function() const { return function; } - int get_line() const { return line; } + SrcFilePtr get_file() const { + return file; + } + FunctionPtr get_function() const { + return function; + } + int get_line() const { + return line; + } std::string as_human_readable() const; - friend bool operator< (const Location &lhs, const Location &rhs); + friend bool operator<(const Location& lhs, const Location& rhs); }; - diff --git a/compiler/make/cpp-to-obj-target.h b/compiler/make/cpp-to-obj-target.h index c1507aab0e..9a2c47cd61 100644 --- a/compiler/make/cpp-to-obj-target.h +++ b/compiler/make/cpp-to-obj-target.h @@ -16,10 +16,8 @@ class Cpp2ObjTarget : public Target { std::string get_cmd() final { std::stringstream ss; const auto cpp_list = dep_list(); - ss << settings->cxx.get() << - " -c -o " << target() << - " " << cpp_list; - const auto &cxx_flags = get_file()->compile_with_debug_info_flag ? settings->cxx_flags_with_debug : settings->cxx_flags_default; + ss << settings->cxx.get() << " -c -o " << target() << " " << cpp_list; + const auto& cxx_flags = get_file()->compile_with_debug_info_flag ? settings->cxx_flags_with_debug : settings->cxx_flags_default; // make #include "runtime-headers.h" capture generated pch file // it's done via -iquote to a folder inside /tmp/kphp_gch where runtime-headers.h with pch file are placed if (!settings->no_pch.get()) { @@ -27,7 +25,6 @@ class Cpp2ObjTarget : public Target { if (vk::contains(settings->cxx.get(), "clang")) { ss << " -include " << cxx_flags.pch_dir.get() << settings->runtime_headers.get(); } - } ss << " " << cxx_flags.flags.get(); @@ -36,8 +33,8 @@ class Cpp2ObjTarget : public Target { void compute_priority() final { priority = 0; - for (auto *dep : deps) { - if (File *dep_file = dep->get_file()) { + for (auto* dep : deps) { + if (File* dep_file = dep->get_file()) { priority += dep_file->file_size; } } diff --git a/compiler/make/file-target.h b/compiler/make/file-target.h index d72f8d82ba..4b546876de 100644 --- a/compiler/make/file-target.h +++ b/compiler/make/file-target.h @@ -9,7 +9,7 @@ class FileTarget : public Target { public: std::string get_cmd() final { - assert (0); + assert(0); return ""; } }; diff --git a/compiler/make/h-to-pch-target.h b/compiler/make/h-to-pch-target.h index fc08e91cea..37ac9e33ed 100644 --- a/compiler/make/h-to-pch-target.h +++ b/compiler/make/h-to-pch-target.h @@ -18,11 +18,8 @@ class H2PchTarget : public Target { kphp_assert(deps.size() == 1); std::stringstream ss; - const auto &cxx_flags = get_file()->compile_with_debug_info_flag ? settings->cxx_flags_with_debug : settings->cxx_flags_default; - ss << settings->cxx.get() << - " -c -o " << target() << - " -x c++-header " << deps[0]->get_name() << - " " << cxx_flags.flags.get(); + const auto& cxx_flags = get_file()->compile_with_debug_info_flag ? settings->cxx_flags_with_debug : settings->cxx_flags_default; + ss << settings->cxx.get() << " -c -o " << target() << " -x c++-header " << deps[0]->get_name() << " " << cxx_flags.flags.get(); // printf("compile pch cmd line %s\n", ss.str().c_str()); return ss.str(); diff --git a/compiler/make/hardlink-or-copy.cpp b/compiler/make/hardlink-or-copy.cpp index 0909028550..ee51692c0d 100644 --- a/compiler/make/hardlink-or-copy.cpp +++ b/compiler/make/hardlink-or-copy.cpp @@ -12,18 +12,17 @@ #include "common/algorithms/find.h" #include "common/macos-ports.h" -#include "compiler/stage.h" #include "common/wrappers/fmt_format.h" +#include "compiler/stage.h" -static void hard_link_or_copy_impl(const std::string &from, const std::string &to, bool replace, bool allow_copy) noexcept { +static void hard_link_or_copy_impl(const std::string& from, const std::string& to, bool replace, bool allow_copy) noexcept { if (!link(from.c_str(), to.c_str())) { return; } if (errno == EEXIST) { if (replace) { - kphp_error_return(!unlink(to.c_str()), - fmt_format("Can't remove file '{}': {}", to, strerror(errno))); + kphp_error_return(!unlink(to.c_str()), fmt_format("Can't remove file '{}': {}", to, strerror(errno))); hard_link_or_copy_impl(from, to, false, allow_copy); } return; @@ -32,15 +31,12 @@ static void hard_link_or_copy_impl(const std::string &from, const std::string &t // the file is placed on other device, or we have a permission problems, try to copy it if (vk::any_of_equal(errno, EXDEV, EPERM) && allow_copy) { struct stat file_stat; - kphp_error_return (!stat(from.c_str(), &file_stat), - fmt_format("Can't get file stat '{}': {}", from, strerror(errno))); + kphp_error_return(!stat(from.c_str(), &file_stat), fmt_format("Can't get file stat '{}': {}", from, strerror(errno))); std::string tmp_file = to + ".XXXXXX"; int tmp_fd = mkstemp(&tmp_file[0]); - kphp_error_return(tmp_fd != -1, - fmt_format("Can't create tmp file '{}': {}", tmp_file, strerror(errno))); - kphp_error_return(fchmod(tmp_fd, file_stat.st_mode) != -1, - fmt_format("Can't change permissions of tmp file '{}': {}", tmp_file, strerror(errno))); + kphp_error_return(tmp_fd != -1, fmt_format("Can't create tmp file '{}': {}", tmp_file, strerror(errno))); + kphp_error_return(fchmod(tmp_fd, file_stat.st_mode) != -1, fmt_format("Can't change permissions of tmp file '{}': {}", tmp_file, strerror(errno))); int from_fd = open(from.c_str(), O_RDONLY); const ssize_t s = sendfile(tmp_fd, from_fd, nullptr, file_stat.st_size); close(from_fd); @@ -55,7 +51,7 @@ static void hard_link_or_copy_impl(const std::string &from, const std::string &t kphp_error(0, fmt_format("Can't copy file from '{}' to '{}': {}", from, to, strerror(errno))); } -void hard_link_or_copy(const std::string &from, const std::string &to, bool replace) { +void hard_link_or_copy(const std::string& from, const std::string& to, bool replace) { hard_link_or_copy_impl(from, to, replace, true); stage::die_if_global_errors(); } diff --git a/compiler/make/hardlink-or-copy.h b/compiler/make/hardlink-or-copy.h index 1d13f1124e..d4bb2264f5 100644 --- a/compiler/make/hardlink-or-copy.h +++ b/compiler/make/hardlink-or-copy.h @@ -6,4 +6,4 @@ #include -void hard_link_or_copy(const std::string &from, const std::string &to, bool replace = true); +void hard_link_or_copy(const std::string& from, const std::string& to, bool replace = true); diff --git a/compiler/make/make-runner.cpp b/compiler/make/make-runner.cpp index 2c590da376..8e7055ca20 100644 --- a/compiler/make/make-runner.cpp +++ b/compiler/make/make-runner.cpp @@ -12,10 +12,10 @@ #include "compiler/compiler-core.h" #include "compiler/utils/string-utils.h" -void MakeRunner::run_target(Target *target) { +void MakeRunner::run_target(Target* target) { bool ready = target->mtime != 0; if (ready) { - for (const auto *dep : target->deps) { + for (const auto* dep : target->deps) { if (dep->mtime > target->mtime) { ready = false; break; @@ -31,21 +31,21 @@ void MakeRunner::run_target(Target *target) { } } -void MakeRunner::ready_target(Target *target) { - //fprintf (stderr, "ready target %s\n", target->get_name().c_str()); - assert (!target->is_ready); +void MakeRunner::ready_target(Target* target) { + // fprintf (stderr, "ready target %s\n", target->get_name().c_str()); + assert(!target->is_ready); targets_left--; target->is_ready = true; - for (auto *rdep : target->rdeps) { + for (auto* rdep : target->rdeps) { one_dep_ready_target(rdep); } } -void MakeRunner::one_dep_ready_target(Target *target) { - //fprintf (stderr, "one_dep_ready target %s\n", target->get_name().c_str()); +void MakeRunner::one_dep_ready_target(Target* target) { + // fprintf (stderr, "one_dep_ready target %s\n", target->get_name().c_str()); target->pending_deps--; - assert (target->pending_deps >= 0); + assert(target->pending_deps >= 0); if (target->pending_deps == 0) { if (target->is_waiting) { target->is_waiting = false; @@ -55,14 +55,14 @@ void MakeRunner::one_dep_ready_target(Target *target) { } } -void MakeRunner::wait_target(Target *target) { - assert (!target->is_waiting); +void MakeRunner::wait_target(Target* target) { + assert(!target->is_waiting); target->is_waiting = true; targets_waiting++; } -void MakeRunner::register_target(Target *target, std::vector &&deps) { - for (auto *dep : deps) { +void MakeRunner::register_target(Target* target, std::vector&& deps) { + for (auto* dep : deps) { dep->rdeps.push_back(target); if (!dep->is_ready) { target->pending_deps++; @@ -74,7 +74,7 @@ void MakeRunner::register_target(Target *target, std::vector &&deps) { all_targets.push_back(target); } -void MakeRunner::require_target(Target *target) { +void MakeRunner::require_target(Target* target) { if (!target->require()) { return; } @@ -83,26 +83,26 @@ void MakeRunner::require_target(Target *target) { run_target(target); } else { wait_target(target); - for (auto *dep : target->deps) { + for (auto* dep : target->deps) { require_target(dep); } } } -static int run_cmd(const std::string &cmd) { +static int run_cmd(const std::string& cmd) { // fmt_print("{}\n", cmd); std::vector args = split(cmd); - std::vector argv(args.size() + 1); + std::vector argv(args.size() + 1); for (int i = 0; i < (int)args.size(); i++) { - argv[i] = (char *)args[i].c_str(); + argv[i] = (char*)args[i].c_str(); } argv.back() = nullptr; - #ifdef __APPLE__ +#ifdef __APPLE__ int pid = fork(); - #else +#else int pid = vfork(); - #endif +#endif if (pid < 0) { perror("vfork failed: "); @@ -110,7 +110,7 @@ static int run_cmd(const std::string &cmd) { } if (pid == 0) { - //prctl (PR_SET_PDEATHSIG, SIGKILL); + // prctl (PR_SET_PDEATHSIG, SIGKILL); execvp(argv[0], &argv[0]); perror("execvp failed: "); _exit(1); @@ -119,7 +119,7 @@ static int run_cmd(const std::string &cmd) { } } -bool MakeRunner::start_job(Target *target) { +bool MakeRunner::start_job(Target* target) { target->start_time = dl_time(); std::string cmd = target->get_cmd(); @@ -133,8 +133,8 @@ bool MakeRunner::start_job(Target *target) { bool MakeRunner::finish_job(int pid, int return_code, int by_signal) { auto it = jobs.find(pid); - assert (it != jobs.end()); - Target *target = it->second; + assert(it != jobs.end()); + Target* target = it->second; if (stats_file_) { double passed = dl_time() - target->start_time; fmt_fprintf(stats_file_, "{}s {}\n", passed, target->get_name()); @@ -168,7 +168,7 @@ void MakeRunner::on_fail() { } fmt_fprintf(stdout, "Make failed. Waiting for {} children\n", (int)jobs.size()); fail_flag = true; - for (const auto &pid_and_target : jobs) { + for (const auto& pid_and_target : jobs) { int err = kill(pid_and_target.first, SIGINT); if (err < 0) { perror("kill failed: "); @@ -182,7 +182,7 @@ void MakeRunner::sigint_handler(int sig __attribute__((unused))) { signal_flag = 1; } -bool MakeRunner::make_targets(const std::vector &targets, const std::string &build_message, std::size_t jobs_count) { +bool MakeRunner::make_targets(const std::vector& targets, const std::string& build_message, std::size_t jobs_count) { if (jobs_count < 1) { fmt_print("Invalid jobs_count [{}]\n", jobs_count); return false; @@ -192,8 +192,8 @@ bool MakeRunner::make_targets(const std::vector &targets, const std::s ksignal(SIGINT, MakeRunner::sigint_handler); ksignal(SIGTERM, MakeRunner::sigint_handler); - //TODO: check timeouts - for (auto *target : targets) { + // TODO: check timeouts + for (auto* target : targets) { // fprintf (stderr, "make target: %s\n", target->get_name().c_str()); require_target(target); } @@ -207,8 +207,8 @@ bool MakeRunner::make_targets(const std::vector &targets, const std::s int perc = (total_jobs - targets_left) * 100 / std::max(1, total_jobs); // don't show progress when there is only one job to do if (old_perc != perc && total_jobs > 1) { - fmt_fprintf(stderr, "{:3}% [total jobs {}] [left jobs {}] [running jobs {}] [waiting jobs {}]\n", - perc, total_jobs, targets_left, (int)jobs.size(), targets_waiting); + fmt_fprintf(stderr, "{:3}% [total jobs {}] [left jobs {}] [running jobs {}] [waiting jobs {}]\n", perc, total_jobs, targets_left, (int)jobs.size(), + targets_waiting); old_perc = perc; } if (jobs.empty() && (fail_flag || pending_jobs.empty())) { @@ -221,70 +221,69 @@ bool MakeRunner::make_targets(const std::vector &targets, const std::s } switch (state) { - case start_jobs_st: { - if (fail_flag || pending_jobs.empty() || jobs.size() >= jobs_count) { - state = wait_jobs_st; - break; - } + case start_jobs_st: { + if (fail_flag || pending_jobs.empty() || jobs.size() >= jobs_count) { + state = wait_jobs_st; + break; + } - Target *target = pending_jobs.top(); - pending_jobs.pop(); - if (!start_job(target)) { - on_fail(); - } + Target* target = pending_jobs.top(); + pending_jobs.pop(); + if (!start_job(target)) { + on_fail(); + } + break; + } + case wait_jobs_st: { + if (jobs.empty()) { + state = start_jobs_st; break; } - case wait_jobs_st: { - if (jobs.empty()) { - state = start_jobs_st; - break; + int status; + int pid = wait(&status); + if (pid == -1) { + if (errno != EINTR) { + perror("waitpid failed: "); + on_fail(); } - int status; - int pid = wait(&status); - if (pid == -1) { - if (errno != EINTR) { - perror("waitpid failed: "); - on_fail(); - } + } else { + int return_code = -1; + int by_signal = -1; + if (WIFEXITED(status)) { + return_code = WEXITSTATUS(status); + } else if (WIFSIGNALED(status)) { + by_signal = WTERMSIG(status); } else { - int return_code = -1; - int by_signal = -1; - if (WIFEXITED (status)) { - return_code = WEXITSTATUS (status); - } else if (WIFSIGNALED (status)) { - by_signal = WTERMSIG (status); - } else { - fmt_print("Something strange happened with pid [{}]\n", pid); - } - if (!finish_job(pid, return_code, by_signal)) { - on_fail(); - } + fmt_print("Something strange happened with pid [{}]\n", pid); } - if (!fail_flag) { - state = start_jobs_st; + if (!finish_job(pid, return_code, by_signal)) { + on_fail(); } - break; } + if (!fail_flag) { + state = start_jobs_st; + } + break; + } } } - //TODO: use old handlers instead SIG_DFL + // TODO: use old handlers instead SIG_DFL ksignal(SIGINT, SIG_DFL); ksignal(SIGTERM, SIG_DFL); bool is_ready = true; - for (auto *target : targets) { + for (auto* target : targets) { is_ready = is_ready && target->is_ready; } return !fail_flag && is_ready; } -MakeRunner::MakeRunner(FILE *stats_file) noexcept: - stats_file_(stats_file) { -} +MakeRunner::MakeRunner(FILE* stats_file) noexcept + : stats_file_(stats_file) {} MakeRunner::~MakeRunner() { - //TODO: delete targets - for (auto *target : all_targets) { + // TODO: delete targets + for (auto* target : all_targets) { delete target; } } diff --git a/compiler/make/make-runner.h b/compiler/make/make-runner.h index d92c667ebf..fda1c30a17 100644 --- a/compiler/make/make-runner.h +++ b/compiler/make/make-runner.h @@ -14,36 +14,37 @@ class MakeRunner : private vk::not_copyable { class compare_by_priority { public: - bool operator()(Target *a, Target *b) const { + bool operator()(Target* a, Target* b) const { return a->priority < b->priority; } }; + private: int targets_waiting = 0; int targets_left = 0; - std::vector all_targets; - FILE *stats_file_{nullptr}; + std::vector all_targets; + FILE* stats_file_{nullptr}; - std::priority_queue, compare_by_priority> pending_jobs; - std::map jobs; + std::priority_queue, compare_by_priority> pending_jobs; + std::map jobs; bool fail_flag = false; static int signal_flag; static void sigint_handler(int sig); - bool start_job(Target *target) __attribute__ ((warn_unused_result)); - bool finish_job(int pid, int return_code, int by_signal) __attribute__ ((warn_unused_result)); + bool start_job(Target* target) __attribute__((warn_unused_result)); + bool finish_job(int pid, int return_code, int by_signal) __attribute__((warn_unused_result)); void on_fail(); - void run_target(Target *target); - void ready_target(Target *target); - void one_dep_ready_target(Target *target); - void wait_target(Target *target); - void require_target(Target *target); + void run_target(Target* target); + void ready_target(Target* target); + void one_dep_ready_target(Target* target); + void wait_target(Target* target); + void require_target(Target* target); public: - void register_target(Target *target, std::vector &&deps); - bool make_targets(const std::vector &target, const std::string &build_message, std::size_t jobs_count = 32); - explicit MakeRunner(FILE *stats_file) noexcept; + void register_target(Target* target, std::vector&& deps); + bool make_targets(const std::vector& target, const std::string& build_message, std::size_t jobs_count = 32); + explicit MakeRunner(FILE* stats_file) noexcept; ~MakeRunner(); }; diff --git a/compiler/make/make.cpp b/compiler/make/make.cpp index 5d1043c8e8..a57ff15a0b 100644 --- a/compiler/make/make.cpp +++ b/compiler/make/make.cpp @@ -39,38 +39,38 @@ class MakeSetup { private: MakeRunner make; - const CompilerSettings &settings; + const CompilerSettings& settings; - void target_set_file(Target *target, File *file) { - assert (file->target == nullptr); + void target_set_file(Target* target, File* file) { + assert(file->target == nullptr); target->set_file(file); file->target = target; } - void target_set_env(Target *target) { + void target_set_env(Target* target) { target->set_settings(&settings); } - Target *to_target(File *file) { + Target* to_target(File* file) { if (file->target != nullptr) { return file->target; } return create_cpp_target(file); } - std::vector to_targets(File *file) { + std::vector to_targets(File* file) { return {to_target(file)}; } - std::vector to_targets(std::vector files) { - std::vector res(files.size()); + std::vector to_targets(std::vector files) { + std::vector res(files.size()); for (int i = 0; i < (int)files.size(); i++) { res[i] = to_target(files[i]); } return res; } - Target *create_target(Target *target, std::vector &&deps, File *file) { + Target* create_target(Target* target, std::vector&& deps, File* file) { target_set_file(target, file); target_set_env(target); make.register_target(target, std::move(deps)); @@ -78,58 +78,56 @@ class MakeSetup { } public: - MakeSetup(FILE *stats_file, const CompilerSettings &compiler_settings) noexcept: - make(stats_file), - settings(compiler_settings) { - } + MakeSetup(FILE* stats_file, const CompilerSettings& compiler_settings) noexcept + : make(stats_file), + settings(compiler_settings) {} - Target *create_runtime_src2obj_target(File *cpp, File *obj, const std::string &options) { + Target* create_runtime_src2obj_target(File* cpp, File* obj, const std::string& options) { return create_target(new RuntimeSrc2ObjTarget(options), to_targets(cpp), obj); } - Target *create_cpp_target(File *cpp) { - return create_target(new FileTarget(), std::vector(), cpp); + Target* create_cpp_target(File* cpp) { + return create_target(new FileTarget(), std::vector(), cpp); } - Target *create_cpp2obj_target(File *cpp, File *obj) { + Target* create_cpp2obj_target(File* cpp, File* obj) { return create_target(new Cpp2ObjTarget(), to_targets(cpp), obj); } - Target *create_h2pch_target(File *header_h, File *pch) { + Target* create_h2pch_target(File* header_h, File* pch) { return create_target(new H2PchTarget(), to_targets(header_h), pch); } - Target *create_objs2obj_target(std::vector objs, File *obj) { + Target* create_objs2obj_target(std::vector objs, File* obj) { return create_target(new Objs2ObjTarget(), to_targets(std::move(objs)), obj); } - Target *create_objs2bin_target(std::vector objs, File *bin) { + Target* create_objs2bin_target(std::vector objs, File* bin) { bool need_libdl = !G->get_ffi_root().get_shared_libs().empty(); return create_target(new Objs2BinTarget(need_libdl), to_targets(std::move(objs)), bin); } - Target *create_objs2static_lib_target(std::vector objs, File *lib) { + Target* create_objs2static_lib_target(std::vector objs, File* lib) { return create_target(new Objs2StaticLibTarget, to_targets(std::move(objs)), lib); } - Target *create_objs2k2_component_target(std::vector objs, File *lib) { + Target* create_objs2k2_component_target(std::vector objs, File* lib) { return create_target(new Objs2K2ComponentTarget, to_targets(std::move(objs)), lib); } - bool make_target(File *bin, const std::string &build_message, int jobs_count) { + bool make_target(File* bin, const std::string& build_message, int jobs_count) { return make.make_targets(to_targets(bin), build_message, jobs_count); } - bool make_targets(const std::vector &bins, const std::string &build_message, int jobs_count) { + bool make_targets(const std::vector& bins, const std::string& build_message, int jobs_count) { return make.make_targets(to_targets(bins), build_message, jobs_count); } }; - -static void copy_static_lib_to_out_dir(File &&static_archive) { +static void copy_static_lib_to_out_dir(File&& static_archive) { Index out_dir; out_dir.set_dir(G->settings().static_lib_out_dir.get()); - out_dir.del_extra_files(); // todo seems that this invocation does nothing, as files are empty + out_dir.del_extra_files(); // todo seems that this invocation does nothing, as files are empty // copy static archive LibData out_lib(G->settings().static_lib_name.get(), out_dir.get_dir()); @@ -150,33 +148,33 @@ static void copy_static_lib_to_out_dir(File &&static_archive) { Index out_headers_dir; out_headers_dir.set_dir(out_lib.headers_dir()); // copy cpp header files of this static archive - for (File *header_file: headers_tmp_dir.get_files()) { + for (File* header_file : headers_tmp_dir.get_files()) { hard_link_or_copy(header_file->path, out_headers_dir.get_dir() + header_file->name); header_file->unlink(); } } -static std::forward_list collect_imported_libs() { - const std::string &binary_runtime_sha256 = G->settings().runtime_sha256.get(); +static std::forward_list collect_imported_libs() { + const std::string& binary_runtime_sha256 = G->settings().runtime_sha256.get(); stage::die_if_global_errors(); - std::forward_list imported_libs; + std::forward_list imported_libs; if (G->settings().force_link_runtime.get()) { imported_libs.emplace_front(new File{G->settings().link_file.get()}); } - for (const auto &lib: G->get_libs()) { + for (const auto& lib : G->get_libs()) { if (lib && !lib->is_raw_php()) { std::string lib_runtime_sha256 = CompilerSettings::read_runtime_sha256_file(lib->runtime_lib_sha256_file()); kphp_error_act(binary_runtime_sha256 == lib_runtime_sha256, - fmt_format("Mismatching between sha256 of binary runtime '{}' and lib runtime '{}'", - G->settings().runtime_sha256_file.get(), lib->runtime_lib_sha256_file()), + fmt_format("Mismatching between sha256 of binary runtime '{}' and lib runtime '{}'", G->settings().runtime_sha256_file.get(), + lib->runtime_lib_sha256_file()), continue); imported_libs.emplace_front(new File{lib->static_archive_path()}); } } - for (File *file: imported_libs) { + for (File* file : imported_libs) { kphp_error_act(file->read_stat() > 0, fmt_format("Can't read mtime of link_file [{}]", file->path), continue); if (G->settings().verbosity.get() >= 1) { fmt_fprintf(stderr, "Use static lib [{}]\n", file->path); @@ -187,9 +185,9 @@ static std::forward_list collect_imported_libs() { return imported_libs; } -static long long get_imported_header_mtime(const std::string &header_path, const std::forward_list &imported_headers) { - for (const Index &lib_headers_dir: imported_headers) { - if (File *header = lib_headers_dir.get_file(header_path)) { +static long long get_imported_header_mtime(const std::string& header_path, const std::forward_list& imported_headers) { + for (const Index& lib_headers_dir : imported_headers) { + if (File* header = lib_headers_dir.get_file(header_path)) { return header->mtime; } } @@ -197,7 +195,7 @@ static long long get_imported_header_mtime(const std::string &header_path, const return 0; } -static int unlink_cb(const char *fpath, [[maybe_unused]] const struct stat *sb, [[maybe_unused]] int typeflag, [[maybe_unused]] struct FTW *ftwbuf) { +static int unlink_cb(const char* fpath, [[maybe_unused]] const struct stat* sb, [[maybe_unused]] int typeflag, [[maybe_unused]] struct FTW* ftwbuf) { int rv = remove(fpath); if (rv) @@ -206,15 +204,15 @@ static int unlink_cb(const char *fpath, [[maybe_unused]] const struct stat *sb, return rv; } -static int rm_rf(const char *path) { +static int rm_rf(const char* path) { return nftw(path, unlink_cb, 64, FTW_DEPTH | FTW_PHYS); } // prepare dir kphp_out/objs/pch_{flags} and make a target runtime-headers.h.gch inside it // in production, there will be two pch_ folders: with debug symbols and without them // later on, we'll copy this folder inside /tmp/kphp_pch — that's why if it exists, don't do anything -File *prepare_precompiled_header(Index *obj_dir, MakeSetup &make, File &runtime_headers_h, const CompilerSettings &settings, bool with_debug) { - const auto &flags = with_debug ? settings.cxx_flags_with_debug : settings.cxx_flags_default; +File* prepare_precompiled_header(Index* obj_dir, MakeSetup& make, File& runtime_headers_h, const CompilerSettings& settings, bool with_debug) { + const auto& flags = with_debug ? settings.cxx_flags_with_debug : settings.cxx_flags_default; if (with_debug && flags == settings.cxx_flags_default) { return nullptr; } @@ -223,9 +221,9 @@ File *prepare_precompiled_header(Index *obj_dir, MakeSetup &make, File &runtime_ int stat_res = stat(flags.pch_dir.get().c_str(), &sb_pch_dir); long long pch_dir_mtime = sb_pch_dir.st_mtime * 1000000000LL + #ifdef __APPLE__ - sb_pch_dir.st_mtimespec.tv_nsec; + sb_pch_dir.st_mtimespec.tv_nsec; #else - sb_pch_dir.st_mtim.tv_nsec; + sb_pch_dir.st_mtim.tv_nsec; #endif if (stat_res != -1 && runtime_headers_h.mtime > pch_dir_mtime) { // check for mtime because compiler fails when .h file has bigger mtime than .gch rm_rf(flags.pch_dir.get().c_str()); @@ -238,7 +236,7 @@ File *prepare_precompiled_header(Index *obj_dir, MakeSetup &make, File &runtime_ std::string objs_pch_dir = settings.dest_objs_dir.get() + "pch_" + flags.flags_sha256.get() + "/"; std::string pch_basename = std::string{kbasename(runtime_headers_h.path.c_str())} + ".gch"; - auto *runtime_header_h_pch = obj_dir->insert_file(objs_pch_dir + pch_basename); + auto* runtime_header_h_pch = obj_dir->insert_file(objs_pch_dir + pch_basename); runtime_header_h_pch->compile_with_debug_info_flag = with_debug; make.create_h2pch_target(&runtime_headers_h, runtime_header_h_pch); return runtime_header_h_pch; @@ -250,7 +248,7 @@ File *prepare_precompiled_header(Index *obj_dir, MakeSetup &make, File &runtime_ // (for instance, nocc emits a .nocc-pch file instead of requested .gch) // todo it's better to use H2PchTarget::after_run_success() for this // todo why do we need /tmp/kphp_pch at all? why not to just leave pch inside kphp_out/objs? -bool finalize_precompiled_header(File &runtime_headers_h, File &runtime_headers_h_pch, const std::string &dst_pch_dir) { +bool finalize_precompiled_header(File& runtime_headers_h, File& runtime_headers_h_pch, const std::string& dst_pch_dir) { const mode_t old_mask = umask(0); const bool dir_created = mkdir_recursive(dst_pch_dir.c_str(), 0777); umask(old_mask); @@ -258,8 +256,8 @@ bool finalize_precompiled_header(File &runtime_headers_h, File &runtime_headers_ hard_link_or_copy(runtime_headers_h.path, dst_pch_dir + kbasename(runtime_headers_h.path.c_str()), false); std::string objs_pch_dir = runtime_headers_h_pch.path.substr(0, runtime_headers_h_pch.path.rfind('/') + 1); - DIR *objs_pch_dirptr = opendir(objs_pch_dir.c_str()); - while (const auto *entry = readdir(objs_pch_dirptr)) { + DIR* objs_pch_dirptr = opendir(objs_pch_dir.c_str()); + while (const auto* entry = readdir(objs_pch_dirptr)) { if (entry->d_name[0] == '.') { continue; } @@ -274,7 +272,7 @@ bool finalize_precompiled_header(File &runtime_headers_h, File &runtime_headers_ return true; } -static bool kphp_make_precompiled_headers(Index *obj_dir, const CompilerSettings &settings, FILE *stats_file) { +static bool kphp_make_precompiled_headers(Index* obj_dir, const CompilerSettings& settings, FILE* stats_file) { MakeSetup make{stats_file, settings}; File sha256_version_file(settings.runtime_sha256_file.get()); kphp_assert(sha256_version_file.read_stat() > 0); @@ -284,10 +282,10 @@ static bool kphp_make_precompiled_headers(Index *obj_dir, const CompilerSettings make.create_cpp_target(&runtime_headers_h); runtime_headers_h.target->force_changed(sha256_version_file.mtime); - std::vector runtime_header_pch_files; + std::vector runtime_header_pch_files; std::vector pch_dirs; for (auto with_debug : {false, true}) { - if (File *runtime_header_gch_file = prepare_precompiled_header(obj_dir, make, runtime_headers_h, settings, with_debug)) { + if (File* runtime_header_gch_file = prepare_precompiled_header(obj_dir, make, runtime_headers_h, settings, with_debug)) { pch_dirs.emplace_back(with_debug ? settings.cxx_flags_with_debug.pch_dir.get() : settings.cxx_flags_default.pch_dir.get()); runtime_header_pch_files.emplace_back(runtime_header_gch_file); } @@ -296,7 +294,6 @@ static bool kphp_make_precompiled_headers(Index *obj_dir, const CompilerSettings return true; } - if (!make.make_targets(runtime_header_pch_files, "Compiling pch", settings.jobs_count.get())) { return false; } @@ -308,27 +305,27 @@ static bool kphp_make_precompiled_headers(Index *obj_dir, const CompilerSettings return is_ok; } -static std::unordered_map create_dep_mtime(const Index &cpp_dir, const std::forward_list &imported_headers) { - std::unordered_map dep_mtime; - std::priority_queue> mtime_queue; - std::unordered_map> reverse_includes; +static std::unordered_map create_dep_mtime(const Index& cpp_dir, const std::forward_list& imported_headers) { + std::unordered_map dep_mtime; + std::priority_queue> mtime_queue; + std::unordered_map> reverse_includes; - const auto &files = cpp_dir.get_files(); + const auto& files = cpp_dir.get_files(); - auto lib_version_it = std::find_if(files.begin(), files.end(), [](File *file) { return file->name == "_lib_version.h"; }); + auto lib_version_it = std::find_if(files.begin(), files.end(), [](File* file) { return file->name == "_lib_version.h"; }); kphp_assert(lib_version_it != files.end()); - File *lib_version = *lib_version_it; + File* lib_version = *lib_version_it; - for (const auto &file : files) { - for (const auto &include : file->includes) { - File *header = cpp_dir.get_file(include); + for (const auto& file : files) { + for (const auto& include : file->includes) { + File* header = cpp_dir.get_file(include); kphp_assert_msg(header != nullptr, fmt_format("Can't find header {} required by {}", include, file->name)); kphp_assert(header->on_disk); reverse_includes[header].push_back(file); } long long max_mtime = std::max(file->mtime, lib_version->mtime); - for (const auto &lib_include : file->lib_includes) { + for (const auto& lib_include : file->lib_includes) { max_mtime = std::max(max_mtime, get_imported_header_mtime(lib_include, imported_headers)); } @@ -349,8 +346,8 @@ static std::unordered_map create_dep_mtime(const Index &cpp_d continue; } - for (auto *including_file: file_includes_it->second) { - auto &including_file_mtime = dep_mtime[including_file]; + for (auto* including_file : file_includes_it->second) { + auto& including_file_mtime = dep_mtime[including_file]; if (including_file_mtime < mtime) { including_file_mtime = mtime; mtime_queue.emplace(including_file_mtime, including_file); @@ -360,25 +357,24 @@ static std::unordered_map create_dep_mtime(const Index &cpp_d return dep_mtime; } -static std::vector create_obj_files(MakeSetup *make, Index &obj_dir, const Index &cpp_dir, - const std::forward_list &imported_headers) { - std::unordered_map dep_mtime = create_dep_mtime(cpp_dir, imported_headers); - std::vector objs; - for (const auto &cpp_file : cpp_dir.get_files()) { +static std::vector create_obj_files(MakeSetup* make, Index& obj_dir, const Index& cpp_dir, const std::forward_list& imported_headers) { + std::unordered_map dep_mtime = create_dep_mtime(cpp_dir, imported_headers); + std::vector objs; + for (const auto& cpp_file : cpp_dir.get_files()) { if (cpp_file->ext == ".cpp") { - File *obj_file = obj_dir.insert_file(static_cast(cpp_file->name_without_ext) + ".o"); + File* obj_file = obj_dir.insert_file(static_cast(cpp_file->name_without_ext) + ".o"); obj_file->compile_with_debug_info_flag = cpp_file->compile_with_debug_info_flag; make->create_cpp2obj_target(cpp_file, obj_file); - Target *cpp_target = cpp_file->target; + Target* cpp_target = cpp_file->target; cpp_target->force_changed(dep_mtime[cpp_file]); objs.push_back(obj_file); } } fmt_fprintf(stderr, "objs cnt = {}\n", objs.size()); - std::map> subdirs; - std::vector tmp_objs; - for (auto *obj_file : objs) { + std::map> subdirs; + std::vector tmp_objs; + for (auto* obj_file : objs) { auto name = obj_file->subdir; if (!name.empty()) { name.remove_suffix(1); @@ -391,16 +387,15 @@ static std::vector create_obj_files(MakeSetup *make, Index &obj_dir, con } objs = std::move(tmp_objs); - for (auto &name_and_files : subdirs) { - auto &deps = name_and_files.second; - std::sort(deps.begin(), deps.end(), [](File *a, File *b) { return a->name < b->name; }); + for (auto& name_and_files : subdirs) { + auto& deps = name_and_files.second; + std::sort(deps.begin(), deps.end(), [](File* a, File* b) { return a->name < b->name; }); size_t hash = 0; - for (File *f : deps) { + for (File* f : deps) { vk::hash_combine(hash, vk::std_hash(f->name)); } - auto intermediate_file_name = fmt_format("{}_{:x}.{}", name_and_files.first, hash, - G->settings().dynamic_incremental_linkage.get() ? "so" : "o"); - File *obj_file = obj_dir.insert_file(std::move(intermediate_file_name)); + auto intermediate_file_name = fmt_format("{}_{:x}.{}", name_and_files.first, hash, G->settings().dynamic_incremental_linkage.get() ? "so" : "o"); + File* obj_file = obj_dir.insert_file(std::move(intermediate_file_name)); make->create_objs2obj_target(std::move(deps), obj_file); objs.push_back(obj_file); } @@ -408,27 +403,25 @@ static std::vector create_obj_files(MakeSetup *make, Index &obj_dir, con return objs; } -static std::vector kphp_make_target(Index &obj_dir, const Index &cpp_dir, - const std::forward_list &imported_headers, MakeSetup &make) { - std::vector lib_objs; +static std::vector kphp_make_target(Index& obj_dir, const Index& cpp_dir, const std::forward_list& imported_headers, MakeSetup& make) { + std::vector lib_objs; auto imported_libs = collect_imported_libs(); - for (File *link_file: imported_libs) { + for (File* link_file : imported_libs) { make.create_cpp_target(link_file); lib_objs.emplace_back(link_file); } - std::vector objs = create_obj_files(&make, obj_dir, cpp_dir, imported_headers); + std::vector objs = create_obj_files(&make, obj_dir, cpp_dir, imported_headers); std::copy(lib_objs.begin(), lib_objs.end(), std::back_inserter(objs)); return objs; } -static std::vector kphp_make_static_lib_target(Index &obj_dir, const Index &cpp_dir, - const std::forward_list &imported_headers, MakeSetup &make) { +static std::vector kphp_make_static_lib_target(Index& obj_dir, const Index& cpp_dir, const std::forward_list& imported_headers, MakeSetup& make) { return create_obj_files(&make, obj_dir, cpp_dir, imported_headers); } static std::forward_list collect_imported_headers() { std::forward_list imported_headers; - for (const auto &lib: G->get_libs()) { + for (const auto& lib : G->get_libs()) { if (lib && !lib->is_raw_php()) { imported_headers.emplace_front(); imported_headers.front().sync_with_dir(lib->lib_dir()); @@ -446,7 +439,8 @@ static std::string get_light_runtime_compiler_options() { for (vk::string_view option : options) { for (vk::string_view prohibit_substr : black_list_substrings) { - if (vk::contains(option, prohibit_substr)) continue; + if (vk::contains(option, prohibit_substr)) + continue; s << option << " "; } } @@ -459,13 +453,13 @@ static std::string get_light_runtime_compiler_options() { return s.str(); } -static std::vector build_runtime_and_common_from_sources(const std::string &compiler_flags, MakeSetup &make, Index &obj_dir) { - const std::unordered_map specific_flags_for_files = - {{"stdlib/vkext/string-processing.cpp", " -Wno-invalid-source-encoding"}}; - const Index &runtime_core_dir = G->get_runtime_core_index(); - const Index &runtime_dir = G->get_runtime_index(); - const Index &common_dir = G->get_common_index(); - const Index &unicode_dir = G->get_unicode_index(); +static std::vector build_runtime_and_common_from_sources(const std::string& compiler_flags, MakeSetup& make, Index& obj_dir) { + const std::unordered_map specific_flags_for_files = { + {"stdlib/vkext/string-processing.cpp", " -Wno-invalid-source-encoding"}}; + const Index& runtime_core_dir = G->get_runtime_core_index(); + const Index& runtime_dir = G->get_runtime_index(); + const Index& common_dir = G->get_common_index(); + const Index& unicode_dir = G->get_unicode_index(); std::vector objs; objs.reserve(runtime_dir.get_files_count() + common_dir.get_files_count()); @@ -473,8 +467,8 @@ static std::vector build_runtime_and_common_from_sources(const std::stri std::unordered_set files_hashes; files_hashes.reserve(runtime_core_dir.get_files_count() + runtime_dir.get_files_count() + common_dir.get_files_count() + unicode_dir.get_files_count()); - for (const auto *dir : std::vector{&runtime_core_dir, &runtime_dir, &common_dir, &unicode_dir}) { - for (File *cpp_file : dir->get_files()) { + for (const auto* dir : std::vector{&runtime_core_dir, &runtime_dir, &common_dir, &unicode_dir}) { + for (File* cpp_file : dir->get_files()) { auto obj_name = static_cast(cpp_file->name_without_ext) + ".o"; if (unlikely(vk::contains(files_hashes, vk::std_hash(obj_name)))) { // in case of files with same pathes in different dirs, for example in runtime_dir and common_dir @@ -482,7 +476,7 @@ static std::vector build_runtime_and_common_from_sources(const std::stri obj_name = static_cast(cpp_file->name_without_ext) + "_" + std::to_string(vk::std_hash(cpp_file->path)) + ".o"; } files_hashes.insert(vk::std_hash(obj_name)); - File *obj_file = obj_dir.insert_file(std::move(obj_name)); + File* obj_file = obj_dir.insert_file(std::move(obj_name)); make.create_cpp_target(cpp_file); if (auto it = specific_flags_for_files.find(cpp_file->name); it != specific_flags_for_files.end()) { make.create_runtime_src2obj_target(cpp_file, obj_file, compiler_flags + std::string(it->second)); @@ -496,7 +490,7 @@ static std::vector build_runtime_and_common_from_sources(const std::stri return objs; } -static std::string get_parent_dir(const std::string &s) { +static std::string get_parent_dir(const std::string& s) { size_t end_i = s.size(); if (end_i == 0) { return ""; @@ -513,7 +507,8 @@ static std::string get_parent_dir(const std::string &s) { return s.substr(0, last_slash_i); } -static std::vector run_pre_make(OutputMode output_mode, const CompilerSettings &settings, FILE *make_stats_file, MakeSetup &make, Index &obj_index, File &bin_file, Index &obj_rt_index) { +static std::vector run_pre_make(OutputMode output_mode, const CompilerSettings& settings, FILE* make_stats_file, MakeSetup& make, Index& obj_index, + File& bin_file, Index& obj_rt_index) { AutoProfiler profiler{get_profiler("Prepare Targets For Build")}; G->del_extra_files(); @@ -524,7 +519,7 @@ static std::vector run_pre_make(OutputMode output_mode, const CompilerSe bin_file.unlink(); } - std::vector response; + std::vector response; if (!settings.force_link_runtime.get()) { std::string obj_dir = get_parent_dir(obj_index.get_dir()) + "/runtime_and_common_objs/"; @@ -549,9 +544,9 @@ static std::vector run_pre_make(OutputMode output_mode, const CompilerSe } void run_make() { - const auto &settings = G->settings(); + const auto& settings = G->settings(); OutputMode output_mode = G->get_output_mode(); - FILE *make_stats_file = nullptr; + FILE* make_stats_file = nullptr; if (!settings.stats_file.get().empty()) { make_stats_file = fopen(settings.stats_file.get().c_str(), "w"); kphp_error(make_stats_file, fmt_format("Can't open stats-file {}", settings.stats_file.get())); diff --git a/compiler/make/objs-to-bin-target.h b/compiler/make/objs-to-bin-target.h index 2b331d740e..d71e4800db 100644 --- a/compiler/make/objs-to-bin-target.h +++ b/compiler/make/objs-to-bin-target.h @@ -11,9 +11,8 @@ class Objs2BinTarget : public Target { public: - explicit Objs2BinTarget(bool need_libdl = false) noexcept : - need_libdl_{need_libdl} { - } + explicit Objs2BinTarget(bool need_libdl = false) noexcept + : need_libdl_{need_libdl} {} std::string get_cmd() final { #if defined(__APPLE__) @@ -24,8 +23,8 @@ class Objs2BinTarget : public Target { std::string_view close_dep{" -Wl,--as-needed -Wl,--end-group -Wl,--no-whole-archive "}; #endif std::stringstream ss; - ss << settings->cxx.get() << " " << settings->cxx_toolchain_option.get() - << " -o " << target() << open_dep << dep_list() << close_dep << settings->ld_flags.get(); + ss << settings->cxx.get() << " " << settings->cxx_toolchain_option.get() << " -o " << target() << open_dep << dep_list() << close_dep + << settings->ld_flags.get(); if (need_libdl_) { ss << " -ldl"; } diff --git a/compiler/make/objs-to-k2-component-target.h b/compiler/make/objs-to-k2-component-target.h index 49f54a6694..4c3a8448c0 100644 --- a/compiler/make/objs-to-k2-component-target.h +++ b/compiler/make/objs-to-k2-component-target.h @@ -71,7 +71,7 @@ class Objs2K2ComponentTarget : public Target { if (!settings->force_link_runtime.get()) { std::vector libs = split(RUNTIME_LIGHT_LINK_LIBS); ss << start_group; - std::for_each(libs.cbegin(), libs.cend(), [&ss](const auto &lib) noexcept { ss << lib << " "; }); + std::for_each(libs.cbegin(), libs.cend(), [&ss](const auto& lib) noexcept { ss << lib << " "; }); ss << end_group; } return ss.str(); diff --git a/compiler/make/objs-to-obj-target.h b/compiler/make/objs-to-obj-target.h index 11858b6b42..5788fe1a21 100644 --- a/compiler/make/objs-to-obj-target.h +++ b/compiler/make/objs-to-obj-target.h @@ -13,11 +13,8 @@ class Objs2ObjTarget : public Target { public: std::string get_cmd() final { std::stringstream ss; - ss << settings->cxx.get() << - " " << settings->cxx_toolchain_option.get() << - " " << settings->incremental_linker_flags.get() << - " -o " << target() << - " " << dep_list(); + ss << settings->cxx.get() << " " << settings->cxx_toolchain_option.get() << " " << settings->incremental_linker_flags.get() << " -o " << target() << " " + << dep_list(); return ss.str(); } }; diff --git a/compiler/make/runtime-src-to-obj-target.h b/compiler/make/runtime-src-to-obj-target.h index 1e41c3702e..a483492e03 100644 --- a/compiler/make/runtime-src-to-obj-target.h +++ b/compiler/make/runtime-src-to-obj-target.h @@ -8,14 +8,14 @@ class RuntimeSrc2ObjTarget : public Target { std::string options; + public: RuntimeSrc2ObjTarget(std::string options) - : options(std::move(options)) {} + : options(std::move(options)) {} std::string get_cmd() final { std::stringstream ss; const auto cpp_list = dep_list(); - ss << settings->cxx.get() << - " -c -o " << target(); + ss << settings->cxx.get() << " -c -o " << target(); ss << " " << dep_list() << " " << options; return ss.str(); diff --git a/compiler/make/target.cpp b/compiler/make/target.cpp index de2f4640bf..ed778e69e5 100644 --- a/compiler/make/target.cpp +++ b/compiler/make/target.cpp @@ -48,7 +48,7 @@ std::string Target::target() { std::string Target::dep_list() { std::string ss; - for (auto *dep : deps) { + for (auto* dep : deps) { ss += dep->get_name(); ss += " "; } @@ -78,17 +78,17 @@ void Target::after_run_fail() { file->unlink(); } -void Target::set_file(File *new_file) { - assert (file == nullptr); +void Target::set_file(File* new_file) { + assert(file == nullptr); file = new_file; set_mtime(file->mtime); } -File *Target::get_file() const { +File* Target::get_file() const { return file; } -void Target::set_settings(const CompilerSettings *new_settings) { - assert (settings == nullptr); +void Target::set_settings(const CompilerSettings* new_settings) { + assert(settings == nullptr); settings = new_settings; } diff --git a/compiler/make/target.h b/compiler/make/target.h index d1db21ecf1..cc5b533204 100644 --- a/compiler/make/target.h +++ b/compiler/make/target.h @@ -17,21 +17,22 @@ class Target : private vk::not_copyable { friend class MakeRunner; private: - std::vector rdeps; + std::vector rdeps; long long mtime = 0; int pending_deps = 0; bool is_required = false; bool is_waiting = false; bool is_ready = false; - File *file = nullptr; + File* file = nullptr; protected: bool upd_mtime(long long new_mtime); void set_mtime(long long new_mtime); - std::vector deps; - const CompilerSettings *settings{nullptr}; + std::vector deps; + const CompilerSettings* settings{nullptr}; + public: long long priority; double start_time; @@ -51,7 +52,7 @@ class Target : private vk::not_copyable { std::string target(); std::string dep_list(); - void set_file(File *new_file); - File *get_file() const; - void set_settings(const CompilerSettings *new_settings); + void set_file(File* new_file); + File* get_file() const; + void set_settings(const CompilerSettings* new_settings); }; diff --git a/compiler/modulite-check-rules.cpp b/compiler/modulite-check-rules.cpp index 086dd50d76..644c149573 100644 --- a/compiler/modulite-check-rules.cpp +++ b/compiler/modulite-check-rules.cpp @@ -33,9 +33,8 @@ * IMPORTANT! keep this file and logic very close to ModuliteCheckRules in modulite-phpstan */ - -static bool does_allow_internal_rule_satisfy_usage_context(FunctionPtr usage_context, const ModuliteSymbol &rule) { - const FunctionData *outer = usage_context->get_this_or_topmost_if_lambda(); +static bool does_allow_internal_rule_satisfy_usage_context(FunctionPtr usage_context, const ModuliteSymbol& rule) { + const FunctionData* outer = usage_context->get_this_or_topmost_if_lambda(); return (rule.kind == ModuliteSymbol::kind_function && rule.function.operator->() == outer) || (rule.kind == ModuliteSymbol::kind_klass && rule.klass == outer->class_id) || (rule.kind == ModuliteSymbol::kind_modulite && rule.modulite == outer->modulite); @@ -48,8 +47,7 @@ static inline bool should_this_usage_context_be_ignored(FunctionPtr usage_contex // then Err::act (static=FeedErr) becomes { echo FeedErr::CONST; }, whereas FeedErr::act()->file_id = @common // due to f->modulite, @common calls @feed, but it does not actually // solution: analyze only Err::act(), but skip FeedErr::act() - if (usage_context && usage_context->modifiers.is_static() && - usage_context->class_id != usage_context->context_class) { + if (usage_context && usage_context->modifiers.is_static() && usage_context->class_id != usage_context->context_class) { return true; // NOLINT(readability-simplify-boolean-expr) } // case 2. @@ -68,15 +66,15 @@ static inline bool should_this_usage_context_be_ignored(FunctionPtr usage_contex // - "A" is declared in 'export' // - or "A" is declared in 'allow internal' for current usage context static bool is_class_exported_from(ClassPtr klass, ModulitePtr owner, FunctionPtr usage_context) { - for (const ModuliteSymbol &e : owner->exports) { + for (const ModuliteSymbol& e : owner->exports) { if (e.kind == ModuliteSymbol::kind_klass && e.klass == klass) { return true; } } - for (const auto &p : owner->allow_internal) { + for (const auto& p : owner->allow_internal) { if (does_allow_internal_rule_satisfy_usage_context(usage_context, p.first)) { - for (const ModuliteSymbol &e : p.second) { + for (const ModuliteSymbol& e : p.second) { if (e.kind == ModuliteSymbol::kind_klass && e.klass == klass) { return true; } @@ -84,8 +82,8 @@ static bool is_class_exported_from(ClassPtr klass, ModulitePtr owner, FunctionPt } } - if (owner->is_composer_package) { // when it's an implicit modulite created from composer.json, all is exported - return owner->exports.empty(); // (unless .modulite.yaml exists near composer.json and manually provides "export") + if (owner->is_composer_package) { // when it's an implicit modulite created from composer.json, all is exported + return owner->exports.empty(); // (unless .modulite.yaml exists near composer.json and manually provides "export") } return false; @@ -96,12 +94,12 @@ static bool is_class_exported_from(ClassPtr klass, ModulitePtr owner, FunctionPt // - or "A" is declared in 'export' AND "A::f" is not declared in 'force-internal' // - or either "A" or "A::f" is declared in 'allow internal' for current usage context static bool is_function_exported_from(FunctionPtr function, ModulitePtr owner, FunctionPtr usage_context) { - for (const ModuliteSymbol &e : owner->exports) { + for (const ModuliteSymbol& e : owner->exports) { if (e.kind == ModuliteSymbol::kind_function && e.function == function) { return true; } if (e.kind == ModuliteSymbol::kind_klass && e.klass == function->class_id) { - for (const ModuliteSymbol &fi : owner->force_internal) { + for (const ModuliteSymbol& fi : owner->force_internal) { if (fi.kind == ModuliteSymbol::kind_function && fi.function == function) { goto search_allow_internal; } @@ -110,10 +108,10 @@ static bool is_function_exported_from(FunctionPtr function, ModulitePtr owner, F } } - search_allow_internal: - for (const auto &p : owner->allow_internal) { +search_allow_internal: + for (const auto& p : owner->allow_internal) { if (does_allow_internal_rule_satisfy_usage_context(usage_context, p.first)) { - for (const ModuliteSymbol &e : p.second) { + for (const ModuliteSymbol& e : p.second) { if (e.kind == ModuliteSymbol::kind_function && e.function == function) { return true; } @@ -124,8 +122,8 @@ static bool is_function_exported_from(FunctionPtr function, ModulitePtr owner, F } } - if (owner->is_composer_package) { // when it's an implicit modulite created from composer.json, all is exported - return owner->exports.empty(); // (unless .modulite.yaml exists near composer.json and manually provides "export") + if (owner->is_composer_package) { // when it's an implicit modulite created from composer.json, all is exported + return owner->exports.empty(); // (unless .modulite.yaml exists near composer.json and manually provides "export") } return false; @@ -134,15 +132,15 @@ static bool is_function_exported_from(FunctionPtr function, ModulitePtr owner, F // constant GLOBAL_DEFINE is exported from a modulite when // - "\\GLOBAL_DEFINE" is declared in 'export' (already checked that it's declared inside a modulite) static bool is_global_const_exported_from(DefinePtr constant, ModulitePtr owner, FunctionPtr usage_context) { - for (const ModuliteSymbol &e : owner->exports) { + for (const ModuliteSymbol& e : owner->exports) { if (e.kind == ModuliteSymbol::kind_global_const && e.constant == constant) { return true; } } - for (const auto &p : owner->allow_internal) { + for (const auto& p : owner->allow_internal) { if (does_allow_internal_rule_satisfy_usage_context(usage_context, p.first)) { - for (const ModuliteSymbol &e : p.second) { + for (const ModuliteSymbol& e : p.second) { if (e.kind == ModuliteSymbol::kind_global_const && e.constant == constant) { return true; } @@ -150,8 +148,8 @@ static bool is_global_const_exported_from(DefinePtr constant, ModulitePtr owner, } } - if (owner->is_composer_package) { // when it's an implicit modulite created from composer.json, all is exported - return owner->exports.empty(); // (unless .modulite.yaml exists near composer.json and manually provides "export") + if (owner->is_composer_package) { // when it's an implicit modulite created from composer.json, all is exported + return owner->exports.empty(); // (unless .modulite.yaml exists near composer.json and manually provides "export") } return false; @@ -162,12 +160,12 @@ static bool is_global_const_exported_from(DefinePtr constant, ModulitePtr owner, // - or "A" is declared in 'export' AND "A::C" is not declared in 'force-internal' // - or either "A" or "A::C" is declared in 'allow internal' for current usage context static bool is_constant_exported_from(DefinePtr constant, ClassPtr requested_class, ModulitePtr owner, FunctionPtr usage_context) { - for (const ModuliteSymbol &e : owner->exports) { + for (const ModuliteSymbol& e : owner->exports) { if (e.kind == ModuliteSymbol::kind_constant && e.constant == constant) { return true; } if (e.kind == ModuliteSymbol::kind_klass && e.klass == requested_class) { - for (const ModuliteSymbol &fi : owner->force_internal) { + for (const ModuliteSymbol& fi : owner->force_internal) { if (fi.kind == ModuliteSymbol::kind_constant && fi.constant == constant) { goto search_allow_internal; } @@ -176,10 +174,10 @@ static bool is_constant_exported_from(DefinePtr constant, ClassPtr requested_cla } } - search_allow_internal: - for (const auto &p : owner->allow_internal) { +search_allow_internal: + for (const auto& p : owner->allow_internal) { if (does_allow_internal_rule_satisfy_usage_context(usage_context, p.first)) { - for (const ModuliteSymbol &e : p.second) { + for (const ModuliteSymbol& e : p.second) { if (e.kind == ModuliteSymbol::kind_constant && e.constant == constant) { return true; } @@ -190,8 +188,8 @@ static bool is_constant_exported_from(DefinePtr constant, ClassPtr requested_cla } } - if (owner->is_composer_package) { // when it's an implicit modulite created from composer.json, all is exported - return owner->exports.empty(); // (unless .modulite.yaml exists near composer.json and manually provides "export") + if (owner->is_composer_package) { // when it's an implicit modulite created from composer.json, all is exported + return owner->exports.empty(); // (unless .modulite.yaml exists near composer.json and manually provides "export") } return false; @@ -202,12 +200,12 @@ static bool is_constant_exported_from(DefinePtr constant, ClassPtr requested_cla // - or "A" is declared in 'export' AND "A::$f" is not declared in 'force-internal' // - or either "A" or "A::$f" is declared in 'allow internal' for current usage context static bool is_static_field_exported_from(VarPtr property, ClassPtr requested_class, ModulitePtr owner, FunctionPtr usage_context) { - for (const ModuliteSymbol &e : owner->exports) { + for (const ModuliteSymbol& e : owner->exports) { if (e.kind == ModuliteSymbol::kind_property && e.property == property) { return true; } if (e.kind == ModuliteSymbol::kind_klass && e.klass == requested_class) { - for (const ModuliteSymbol &fi : owner->force_internal) { + for (const ModuliteSymbol& fi : owner->force_internal) { if (fi.kind == ModuliteSymbol::kind_property && fi.klass == requested_class && fi.property == property) { goto search_allow_internal; } @@ -216,10 +214,10 @@ static bool is_static_field_exported_from(VarPtr property, ClassPtr requested_cl } } - search_allow_internal: - for (const auto &p : owner->allow_internal) { +search_allow_internal: + for (const auto& p : owner->allow_internal) { if (does_allow_internal_rule_satisfy_usage_context(usage_context, p.first)) { - for (const ModuliteSymbol &e : p.second) { + for (const ModuliteSymbol& e : p.second) { if (e.kind == ModuliteSymbol::kind_property && e.property == property) { return true; } @@ -230,8 +228,8 @@ static bool is_static_field_exported_from(VarPtr property, ClassPtr requested_cl } } - if (owner->is_composer_package) { // when it's an implicit modulite created from composer.json, all is exported - return owner->exports.empty(); // (unless .modulite.yaml exists near composer.json and manually provides "export") + if (owner->is_composer_package) { // when it's an implicit modulite created from composer.json, all is exported + return owner->exports.empty(); // (unless .modulite.yaml exists near composer.json and manually provides "export") } return false; @@ -250,9 +248,9 @@ static bool is_submodulite_exported(ModulitePtr child, FunctionPtr usage_context return !check_all_depth || !parent->parent || is_submodulite_exported(parent, usage_context); } - for (const auto &p : parent->allow_internal) { + for (const auto& p : parent->allow_internal) { if (does_allow_internal_rule_satisfy_usage_context(usage_context, p.first)) { - for (const ModuliteSymbol &e : p.second) { + for (const ModuliteSymbol& e : p.second) { if (e.kind == ModuliteSymbol::kind_modulite && e.modulite == child) { return !check_all_depth || !parent->parent || is_submodulite_exported(parent, usage_context); } @@ -264,18 +262,17 @@ static bool is_submodulite_exported(ModulitePtr child, FunctionPtr usage_context return true; } - if (parent->is_composer_package) { // when parent is an implicit modulite created from composer.json, all is exported - return parent->exports.empty(); // (unless .modulite.yaml exists near composer.json and manually provides "export") + if (parent->is_composer_package) { // when parent is an implicit modulite created from composer.json, all is exported + return parent->exports.empty(); // (unless .modulite.yaml exists near composer.json and manually provides "export") } return false; } - static bool does_require_another_modulite(ModulitePtr inside_m, ModulitePtr another_m) { // examples: we are at inside_m = @feed, accessing another_m = @msg/channels // fast path: if @feed requires @msg/channels - for (const ModuliteSymbol &req : inside_m->require) { + for (const ModuliteSymbol& req : inside_m->require) { if (req.kind == ModuliteSymbol::kind_modulite && req.modulite == another_m) { return true; } @@ -283,7 +280,7 @@ static bool does_require_another_modulite(ModulitePtr inside_m, ModulitePtr anot // slow path: if @feed requires @msg, then @msg/channels is auto-required unless internal in @msg (for any depth) // same for composer packages: if @feed requires #vk/common, #vk/common/@strings is auto-required unless not exported - for (const ModuliteSymbol &req : inside_m->require) { + for (const ModuliteSymbol& req : inside_m->require) { if (req.kind == ModuliteSymbol::kind_modulite && vk::contains(req.modulite->submodulites_exported_at_any_depth, another_m)) { return true; } @@ -299,7 +296,6 @@ static bool does_require_another_modulite(ModulitePtr inside_m, ModulitePtr anot return false; } - // this class is close to ModuliteErrFormatter in modulite-phpstan class ModuliteErr { ModulitePtr inside_m; @@ -309,34 +305,34 @@ class ModuliteErr { public: [[gnu::cold]] ModuliteErr(FunctionPtr usage_context, ClassPtr klass) - : inside_m(usage_context->modulite) - , another_m(klass->modulite) - , usage_context(usage_context) - , desc(fmt_format("use {}", TermStringFormat::paint_bold(klass->as_human_readable()))) {} + : inside_m(usage_context->modulite), + another_m(klass->modulite), + usage_context(usage_context), + desc(fmt_format("use {}", TermStringFormat::paint_bold(klass->as_human_readable()))) {} [[gnu::cold]] ModuliteErr(FunctionPtr usage_context, FunctionPtr called_f) - : inside_m(usage_context->modulite) - , another_m(called_f->modulite) - , usage_context(usage_context) - , desc(fmt_format("call {}()", TermStringFormat::paint_bold(called_f->as_human_readable()))) {} + : inside_m(usage_context->modulite), + another_m(called_f->modulite), + usage_context(usage_context), + desc(fmt_format("call {}()", TermStringFormat::paint_bold(called_f->as_human_readable()))) {} [[gnu::cold]] ModuliteErr(FunctionPtr usage_context, ClassPtr requested_class, DefinePtr used_c) - : inside_m(usage_context->modulite) - , another_m(used_c->modulite) - , usage_context(usage_context) - , desc(fmt_format("use {}", TermStringFormat::paint_bold(requested_class ? requested_class->as_human_readable() : used_c->as_human_readable()))) {} + : inside_m(usage_context->modulite), + another_m(used_c->modulite), + usage_context(usage_context), + desc(fmt_format("use {}", TermStringFormat::paint_bold(requested_class ? requested_class->as_human_readable() : used_c->as_human_readable()))) {} [[gnu::cold]] ModuliteErr(FunctionPtr usage_context, ClassPtr requested_class, VarPtr property) - : inside_m(usage_context->modulite) - , another_m(property->class_id->modulite) - , usage_context(usage_context) - , desc(fmt_format("use {}", TermStringFormat::paint_bold(requested_class ? requested_class->as_human_readable() : property->as_human_readable()))) {} + : inside_m(usage_context->modulite), + another_m(property->class_id->modulite), + usage_context(usage_context), + desc(fmt_format("use {}", TermStringFormat::paint_bold(requested_class ? requested_class->as_human_readable() : property->as_human_readable()))) {} - [[gnu::cold]] ModuliteErr(FunctionPtr usage_context, const std::string &global_var_name) - : inside_m(usage_context->modulite) - , another_m({}) - , usage_context(usage_context) - , desc(fmt_format("use global {}", TermStringFormat::paint_bold("$" + global_var_name))) {} + [[gnu::cold]] ModuliteErr(FunctionPtr usage_context, const std::string& global_var_name) + : inside_m(usage_context->modulite), + another_m({}), + usage_context(usage_context), + desc(fmt_format("use global {}", TermStringFormat::paint_bold("$" + global_var_name))) {} [[gnu::cold]] void print_error_symbol_is_not_exported() { kphp_error(0, fmt_format("[modulite] restricted to {}, it's internal in {}", desc, another_m->modulite_name)); @@ -353,7 +349,8 @@ class ModuliteErr { [[gnu::cold]] void print_error_modulite_is_not_required() { if (inside_m->composer_json && another_m->composer_json) { - kphp_error(0, fmt_format("[modulite] restricted to {}, {} is not required by {} in composer.json", desc, another_m->modulite_name, inside_m->modulite_name)); + kphp_error(0, + fmt_format("[modulite] restricted to {}, {} is not required by {} in composer.json", desc, another_m->modulite_name, inside_m->modulite_name)); } else { kphp_error(0, fmt_format("[modulite] restricted to {}, {} is not required by {}", desc, another_m->modulite_name, inside_m->modulite_name)); } @@ -368,7 +365,6 @@ class ModuliteErr { } }; - void modulite_check_when_use_class(FunctionPtr usage_context, ClassPtr klass) { ModulitePtr inside_m = usage_context->modulite; ModulitePtr another_m = klass->modulite; @@ -396,9 +392,7 @@ void modulite_check_when_use_class(FunctionPtr usage_context, ClassPtr klass) { } } else { - bool in_require = vk::any_of(inside_m->require, [klass](const ModuliteSymbol &s) { - return s.kind == ModuliteSymbol::kind_klass && s.klass == klass; - }); + bool in_require = vk::any_of(inside_m->require, [klass](const ModuliteSymbol& s) { return s.kind == ModuliteSymbol::kind_klass && s.klass == klass; }); if (!in_require && !klass->is_builtin()) { ModuliteErr(usage_context, klass).print_error_symbol_is_not_required(); } @@ -433,9 +427,8 @@ void modulite_check_when_use_global_const(FunctionPtr usage_context, DefinePtr u } } else { - bool in_require = vk::any_of(inside_m->require, [used_c](const ModuliteSymbol &s) { - return s.kind == ModuliteSymbol::kind_global_const && s.constant == used_c; - }); + bool in_require = + vk::any_of(inside_m->require, [used_c](const ModuliteSymbol& s) { return s.kind == ModuliteSymbol::kind_global_const && s.constant == used_c; }); if (!in_require && !used_c->is_builtin()) { ModuliteErr(usage_context, {}, used_c).print_error_symbol_is_not_required(); } @@ -470,9 +463,8 @@ void modulite_check_when_use_constant(FunctionPtr usage_context, DefinePtr used_ } } else { - bool in_require = vk::any_of(inside_m->require, [used_c, requested_class](const ModuliteSymbol &s) { - return (s.kind == ModuliteSymbol::kind_klass && s.klass == requested_class) || - (s.kind == ModuliteSymbol::kind_constant && s.constant == used_c); + bool in_require = vk::any_of(inside_m->require, [used_c, requested_class](const ModuliteSymbol& s) { + return (s.kind == ModuliteSymbol::kind_klass && s.klass == requested_class) || (s.kind == ModuliteSymbol::kind_constant && s.constant == used_c); }); if (!in_require && !used_c->is_builtin()) { ModuliteErr(usage_context, requested_class, used_c).print_error_symbol_is_not_required(); @@ -515,10 +507,9 @@ void modulite_check_when_call_function(FunctionPtr usage_context, FunctionPtr ca } } else { - bool in_require = vk::any_of(inside_m->require, [called_f](const ModuliteSymbol &s) { - return s.kind == ModuliteSymbol::kind_function && s.function == called_f; - }); - if (!in_require) { // builtin functions were beforehand filtered out by func_local condition + bool in_require = + vk::any_of(inside_m->require, [called_f](const ModuliteSymbol& s) { return s.kind == ModuliteSymbol::kind_function && s.function == called_f; }); + if (!in_require) { // builtin functions were beforehand filtered out by func_local condition ModuliteErr(usage_context, called_f).print_error_symbol_is_not_required(); } } @@ -552,9 +543,8 @@ void modulite_check_when_use_static_field(FunctionPtr usage_context, VarPtr prop } } else { - bool in_require = vk::any_of(inside_m->require, [property, requested_class](const ModuliteSymbol &s) { - return (s.kind == ModuliteSymbol::kind_klass && s.klass == requested_class) || - (s.kind == ModuliteSymbol::kind_property && s.property == property); + bool in_require = vk::any_of(inside_m->require, [property, requested_class](const ModuliteSymbol& s) { + return (s.kind == ModuliteSymbol::kind_klass && s.klass == requested_class) || (s.kind == ModuliteSymbol::kind_property && s.property == property); }); if (!in_require && !requested_class->is_builtin()) { ModuliteErr(usage_context, requested_class, property).print_error_symbol_is_not_required(); @@ -563,19 +553,17 @@ void modulite_check_when_use_static_field(FunctionPtr usage_context, VarPtr prop } } -void modulite_check_when_global_keyword(FunctionPtr usage_context, const std::string &global_var_name) { +void modulite_check_when_global_keyword(FunctionPtr usage_context, const std::string& global_var_name) { ModulitePtr inside_m = usage_context->modulite; if (should_this_usage_context_be_ignored(usage_context)) { return; } if (inside_m) { - bool in_require = vk::any_of(inside_m->require, [global_var_name](const ModuliteSymbol &s) { - return s.kind == ModuliteSymbol::kind_global_var && s.global_var == global_var_name; - }); - if (!in_require && !inside_m->is_composer_package) { // composer root, like project root, has no place to declare requires + bool in_require = vk::any_of( + inside_m->require, [global_var_name](const ModuliteSymbol& s) { return s.kind == ModuliteSymbol::kind_global_var && s.global_var == global_var_name; }); + if (!in_require && !inside_m->is_composer_package) { // composer root, like project root, has no place to declare requires ModuliteErr(usage_context, global_var_name).print_error_symbol_is_not_required(); } } } - diff --git a/compiler/modulite-check-rules.h b/compiler/modulite-check-rules.h index e3e1ad4fc2..522068a14b 100644 --- a/compiler/modulite-check-rules.h +++ b/compiler/modulite-check-rules.h @@ -12,5 +12,4 @@ void modulite_check_when_use_global_const(FunctionPtr usage_context, DefinePtr u void modulite_check_when_use_constant(FunctionPtr usage_context, DefinePtr used_c, ClassPtr requested_class); void modulite_check_when_call_function(FunctionPtr usage_context, FunctionPtr called_f); void modulite_check_when_use_static_field(FunctionPtr usage_context, VarPtr property, ClassPtr requested_class); -void modulite_check_when_global_keyword(FunctionPtr usage_context, const std::string &global_var_name); - +void modulite_check_when_global_keyword(FunctionPtr usage_context, const std::string& global_var_name); diff --git a/compiler/name-gen.cpp b/compiler/name-gen.cpp index 0538a26029..4b8ae56eab 100644 --- a/compiler/name-gen.cpp +++ b/compiler/name-gen.cpp @@ -7,13 +7,13 @@ #include "common/algorithms/hashes.h" #include "common/wrappers/likely.h" -#include "compiler/type-hint.h" #include "compiler/compiler-core.h" #include "compiler/const-manipulations.h" #include "compiler/data/class-data.h" #include "compiler/data/src-file.h" #include "compiler/pipes/register-variables.h" #include "compiler/stage.h" +#include "compiler/type-hint.h" std::string gen_anonymous_scope_name(FunctionPtr function) { return gen_unique_name("cdef", function); @@ -30,11 +30,11 @@ std::string gen_unique_name(const std::string& prefix, FunctionPtr function) { kphp_assert(function); auto h = vk::std_hash(function->name); auto ph = vk::std_hash(prefix); - auto &index = function->name_gen_map[ph]; + auto& index = function->name_gen_map[ph]; return fmt_format("{}$u{:x}_{}", prefix, h, index++); } -std::string resolve_uses(FunctionPtr resolve_context, const std::string &class_name) { +std::string resolve_uses(FunctionPtr resolve_context, const std::string& class_name) { if (class_name[0] == '\\') { return class_name.substr(1); } @@ -42,11 +42,10 @@ std::string resolve_uses(FunctionPtr resolve_context, const std::string &class_n if (class_name == "parent") { // do a str_dependents search instead of using parent_class->name: // resolve_uses() is called before the classes are resolved - if (const auto *parent_name = resolve_context->get_this_or_topmost_if_lambda()->class_id->get_parent_class_name()) { + if (const auto* parent_name = resolve_context->get_this_or_topmost_if_lambda()->class_id->get_parent_class_name()) { return *parent_name; } - kphp_error(resolve_context->class_id && resolve_context->class_id->is_trait(), - "Using parent:: in class that extends nothing"); + kphp_error(resolve_context->class_id && resolve_context->class_id->is_trait(), "Using parent:: in class that extends nothing"); return {}; } @@ -82,7 +81,7 @@ static std::string __attribute__((noinline)) _safe_str(VertexPtr v) { return v->has_get_string() ? v->get_string() : "..."; } -static std::string __attribute__((noinline)) _err_instance_access(VertexPtr v, const std::string &desc) { +static std::string __attribute__((noinline)) _err_instance_access(VertexPtr v, const std::string& desc) { if (v->type() == op_func_call) { return "Invalid call ...->" + v->get_string() + "(): " + desc; } @@ -98,114 +97,105 @@ static std::string __attribute__((noinline)) _err_instance_access(VertexPtr v, c */ ClassPtr resolve_class_of_arrow_access(FunctionPtr function, VertexPtr lhs, VertexPtr v) { switch (lhs->type()) { - // $var->... - case op_var: { - auto klass = assume_class_of_expr(function, lhs, v).try_as_class(); - kphp_error(klass, - _err_instance_access(v, - function->find_param_by_name(lhs->get_string()) - ? fmt_format("${} is not an instance or it can't be detected.\n" - "Add /** @param {} ${} */ to phpdoc above {}.", - _safe_str(lhs), "{type}", _safe_str(lhs), function->as_human_readable()) - : fmt_format("${} is not an instance or it can't be detected.\n" - "Add /** @var {} ${} */ above the first assignment to ${}.", - _safe_str(lhs), "{type}", _safe_str(lhs), _safe_str(lhs)) - )); - return klass; - } + // $var->... + case op_var: { + auto klass = assume_class_of_expr(function, lhs, v).try_as_class(); + kphp_error(klass, _err_instance_access(v, function->find_param_by_name(lhs->get_string()) + ? fmt_format("${} is not an instance or it can't be detected.\n" + "Add /** @param {} ${} */ to phpdoc above {}.", + _safe_str(lhs), "{type}", _safe_str(lhs), function->as_human_readable()) + : fmt_format("${} is not an instance or it can't be detected.\n" + "Add /** @var {} ${} */ above the first assignment to ${}.", + _safe_str(lhs), "{type}", _safe_str(lhs), _safe_str(lhs)))); + return klass; + } - // getInstance()->... - case op_func_call: { - auto klass = assume_class_of_expr(function, lhs, v).try_as_class(); - kphp_error(klass, - _err_instance_access(v, fmt_format("{}() does not return an instance or it can't be detected.\n" - "Add @return tag to function phpdoc.", - _safe_str(lhs)))); - return klass; - } + // getInstance()->... + case op_func_call: { + auto klass = assume_class_of_expr(function, lhs, v).try_as_class(); + kphp_error(klass, _err_instance_access(v, fmt_format("{}() does not return an instance or it can't be detected.\n" + "Add @return tag to function phpdoc.", + _safe_str(lhs)))); + return klass; + } - // $callback()->... - case op_invoke_call: { - auto klass = assume_class_of_expr(function, lhs, v).try_as_class(); - kphp_error(klass, - _err_instance_access(v, fmt_format("A callback does not return an instance or it can't be detected.\n" - "Extract the result of a callback invocation to a separate variable, providing @var phpdoc."))); - return klass; - } + // $callback()->... + case op_invoke_call: { + auto klass = assume_class_of_expr(function, lhs, v).try_as_class(); + kphp_error(klass, _err_instance_access(v, fmt_format("A callback does not return an instance or it can't be detected.\n" + "Extract the result of a callback invocation to a separate variable, providing @var phpdoc."))); + return klass; + } - // ...->anotherInstance->... - case op_instance_prop: { - auto klass = assume_class_of_expr(function, lhs, v).try_as_class(); - kphp_error(klass, - _err_instance_access(v, fmt_format("{}->{} is not an instance or it can't be detected.\n" - "Provide /** @var {} */ above the field declaration or use a field type hint.", - _safe_str(lhs.as()->instance()), _safe_str(lhs), "{type}"))); - return klass; - } + // ...->anotherInstance->... + case op_instance_prop: { + auto klass = assume_class_of_expr(function, lhs, v).try_as_class(); + kphp_error(klass, _err_instance_access(v, fmt_format("{}->{} is not an instance or it can't be detected.\n" + "Provide /** @var {} */ above the field declaration or use a field type hint.", + _safe_str(lhs.as()->instance()), _safe_str(lhs), "{type}"))); + return klass; + } - // ...[$idx]->... - case op_index: { - VertexAdaptor index = lhs.as(); - VertexPtr array = index->array(); - if (index->has_key()) { - // $var[$idx]->... - if (array->type() == op_var) { - auto as_inner_klass = assume_class_of_expr(function, array, v).get_subkey_by_index(index->key()).try_as_class(); - kphp_error(as_inner_klass, - _err_instance_access(v, fmt_format("${} is not an array of instances or it can't be detected.\n" - "Add /** @var {}[] ${} */ above the first assignment to ${}.", - _safe_str(array), "{type}", _safe_str(array), _safe_str(array)))); - return as_inner_klass; - } - // getArr()[$idx]->... - if (array->type() == op_func_call) { - auto as_inner_klass = assume_class_of_expr(function, array, v).get_subkey_by_index(index->key()).try_as_class(); - kphp_error(as_inner_klass, - _err_instance_access(v, fmt_format("{}() does not return an array of instances or it can't be detected.\n" - "Add @return tag to function phpdoc.", - _safe_str(array)))); - return as_inner_klass; - } - // ...->arrOfInstances[$idx]->... - if (array->type() == op_instance_prop) { - auto as_inner_klass = assume_class_of_expr(function, array, v).get_subkey_by_index(index->key()).try_as_class(); - kphp_error(as_inner_klass, - _err_instance_access(v, fmt_format("{}->{} is not array of instances or it can't be detected.\n" - "Provide /** @var {}[] */ above the field declaration.", - _safe_str(array.as()->instance()), _safe_str(array), "{type}"))); - return as_inner_klass; - } + // ...[$idx]->... + case op_index: { + VertexAdaptor index = lhs.as(); + VertexPtr array = index->array(); + if (index->has_key()) { + // $var[$idx]->... + if (array->type() == op_var) { + auto as_inner_klass = assume_class_of_expr(function, array, v).get_subkey_by_index(index->key()).try_as_class(); + kphp_error(as_inner_klass, _err_instance_access(v, fmt_format("${} is not an array of instances or it can't be detected.\n" + "Add /** @var {}[] ${} */ above the first assignment to ${}.", + _safe_str(array), "{type}", _safe_str(array), _safe_str(array)))); + return as_inner_klass; + } + // getArr()[$idx]->... + if (array->type() == op_func_call) { + auto as_inner_klass = assume_class_of_expr(function, array, v).get_subkey_by_index(index->key()).try_as_class(); + kphp_error(as_inner_klass, _err_instance_access(v, fmt_format("{}() does not return an array of instances or it can't be detected.\n" + "Add @return tag to function phpdoc.", + _safe_str(array)))); + return as_inner_klass; + } + // ...->arrOfInstances[$idx]->... + if (array->type() == op_instance_prop) { + auto as_inner_klass = assume_class_of_expr(function, array, v).get_subkey_by_index(index->key()).try_as_class(); + kphp_error(as_inner_klass, _err_instance_access(v, fmt_format("{}->{} is not array of instances or it can't be detected.\n" + "Provide /** @var {}[] */ above the field declaration.", + _safe_str(array.as()->instance()), _safe_str(array), "{type}"))); + return as_inner_klass; } - break; } + break; + } - // (clone $expr)->... - case op_clone: - return resolve_class_of_arrow_access(function, lhs.as()->expr(), v); + // (clone $expr)->... + case op_clone: + return resolve_class_of_arrow_access(function, lhs.as()->expr(), v); - // ({ $tmp = clone $expr; $tmp->clone(); $tmp })->... - case op_seq_rval: - return resolve_class_of_arrow_access(function, lhs.as()->back(), v); + // ({ $tmp = clone $expr; $tmp->clone(); $tmp })->... + case op_seq_rval: + return resolve_class_of_arrow_access(function, lhs.as()->back(), v); - // ($a = new A)->... - case op_set: - return resolve_class_of_arrow_access(function, lhs.as()->rhs(), v); + // ($a = new A)->... + case op_set: + return resolve_class_of_arrow_access(function, lhs.as()->rhs(), v); - // inlined constant value - case op_define_val: - return resolve_class_of_arrow_access(function, lhs.as()->value(), v); + // inlined constant value + case op_define_val: + return resolve_class_of_arrow_access(function, lhs.as()->value(), v); - default: - break; + default: + break; } kphp_error(false, _err_instance_access(v, "Can not parse: maybe, too deep nesting")); return ClassPtr{}; } -std::string resolve_static_method_append_context(FunctionPtr f, const std::string &prefix_name, const std::string &class_name, const std::string &local_name) { +std::string resolve_static_method_append_context(FunctionPtr f, const std::string& prefix_name, const std::string& class_name, const std::string& local_name) { if (is_string_self_static_parent(prefix_name)) { - const std::string &context_name = f->get_this_or_topmost_if_lambda()->context_class->name; + const std::string& context_name = f->get_this_or_topmost_if_lambda()->context_class->name; if (context_name != class_name) { return replace_characters(class_name + "$$" + local_name + "$$" + context_name, '\\', '$'); } @@ -219,10 +209,10 @@ std::string resolve_define_name(std::string name) { if (pos$$ != std::string::npos) { std::string class_name = name.substr(0, pos$$); std::string define_name = name.substr(pos$$ + 2); - const std::string &real_class_name = replace_characters(class_name, '$', '\\'); + const std::string& real_class_name = replace_characters(class_name, '$', '\\'); if (auto klass = G->get_class(real_class_name)) { ClassPtr last_ancestor; - for (const auto &ancestor : klass->get_all_ancestors()) { + for (const auto& ancestor : klass->get_all_ancestors()) { if (ancestor->members.has_constant(define_name)) { if (!last_ancestor) { name = "c#" + replace_backslashes(ancestor->name) + "$$" + define_name; diff --git a/compiler/name-gen.h b/compiler/name-gen.h index 619b53fee9..c2b27eb8c5 100644 --- a/compiler/name-gen.h +++ b/compiler/name-gen.h @@ -13,7 +13,7 @@ std::string gen_anonymous_scope_name(FunctionPtr parent_function); std::string gen_anonymous_function_name(FunctionPtr parent_function); std::string gen_unique_name(const std::string& prefix, FunctionPtr function = FunctionPtr{}); -std::string resolve_uses(FunctionPtr resolve_context, const std::string &class_name); +std::string resolve_uses(FunctionPtr resolve_context, const std::string& class_name); ClassPtr resolve_class_of_arrow_access(FunctionPtr function, VertexPtr lhs, VertexPtr v); -std::string resolve_static_method_append_context(FunctionPtr f, const std::string &prefix_name, const std::string &class_name, const std::string &local_name); +std::string resolve_static_method_append_context(FunctionPtr f, const std::string& prefix_name, const std::string& class_name, const std::string& local_name); std::string resolve_define_name(std::string name); diff --git a/compiler/operation.cpp b/compiler/operation.cpp index d22efea676..bd42cf7991 100644 --- a/compiler/operation.cpp +++ b/compiler/operation.cpp @@ -17,7 +17,7 @@ inline void OpInfo::add_unary_op(int priority, TokenType tok, Operation op) { } inline void OpInfo::add_op(TokenType tok, Operation op) { - assert (tok_to_op[tok] == op_err); + assert(tok_to_op[tok] == op_err); tok_to_op[tok] = op; } @@ -27,10 +27,10 @@ void OpInfo::init_static() { } was_init_static = 1; - static OpProperties default_properties;//TODO was not initialized, static added + static OpProperties default_properties; // TODO was not initialized, static added default_properties.cnst = cnst_not_func; std::fill(P, P + Operation_size, default_properties); -#define FOREACH_OP(x) VertexAdaptor ::init_properties (&P[x]); +#define FOREACH_OP(x) VertexAdaptor::init_properties(&P[x]); #include "auto/compiler/vertex/foreach-op.h" @@ -142,7 +142,7 @@ void OpInfo::init_static() { OpProperties OpInfo::P[Operation_size]; int OpInfo::was_init_static = 0; -//TODO: assert that 255 is enough +// TODO: assert that 255 is enough Operation OpInfo::tok_to_op[255]; Operation OpInfo::tok_to_binary_op[255]; Operation OpInfo::tok_to_unary_op[255]; diff --git a/compiler/operation.h b/compiler/operation.h index 00c1889dd8..f402cc0bf5 100644 --- a/compiler/operation.h +++ b/compiler/operation.h @@ -23,19 +23,8 @@ enum OperationExtra { op_ex_safe_version, }; -enum RLValueType { - val_error = 0, - val_r, - val_l, - val_none -}; -enum ConstValueType { - cnst_error_ = 0, - cnst_not_val, - cnst_nonconst_val, - cnst_const_val -}; - +enum RLValueType { val_error = 0, val_r, val_l, val_none }; +enum ConstValueType { cnst_error_ = 0, cnst_not_val, cnst_nonconst_val, cnst_const_val }; struct OpProperties { Operation op; @@ -55,7 +44,7 @@ struct OpProperties { struct OpInfo { static int was_init_static; - //TODO: assert that 255 is enough + // TODO: assert that 255 is enough static Operation tok_to_op[255]; static Operation tok_to_binary_op[255]; static Operation tok_to_unary_op[255]; @@ -70,7 +59,7 @@ struct OpInfo { static void init_static(); private: - static inline OpProperties &get_properties(Operation op) { + static inline OpProperties& get_properties(Operation op) { return P[op]; } @@ -79,7 +68,7 @@ struct OpInfo { } public: - static inline const OpProperties &properties(Operation op) { + static inline const OpProperties& properties(Operation op) { return get_properties(op); } @@ -95,15 +84,15 @@ struct OpInfo { return properties(op).type; } - static inline const std::string &desc(Operation op) { + static inline const std::string& desc(Operation op) { return properties(op).description; } - static inline const std::string &str(Operation op) { + static inline const std::string& str(Operation op) { return properties(op).str; } - static inline const char *op_str(Operation op) { + static inline const char* op_str(Operation op) { return properties(op).op_str.c_str(); } @@ -119,4 +108,3 @@ struct OpInfo { return properties(op).fixity; } }; - diff --git a/compiler/phpdoc.cpp b/compiler/phpdoc.cpp index 269b46eba2..32ac4c5c30 100644 --- a/compiler/phpdoc.cpp +++ b/compiler/phpdoc.cpp @@ -7,26 +7,25 @@ #include #include -#include "common/termformat/termformat.h" #include "common/php-functions.h" +#include "common/termformat/termformat.h" #include "compiler/compiler-core.h" #include "compiler/data/function-data.h" -#include "compiler/data/src-file.h" #include "compiler/data/generics-mixins.h" +#include "compiler/data/src-file.h" +#include "compiler/ffi/ffi_parser.h" #include "compiler/lexer.h" #include "compiler/modulite-check-rules.h" #include "compiler/name-gen.h" #include "compiler/stage.h" #include "compiler/type-hint.h" #include "compiler/utils/string-utils.h" -#include "compiler/ffi/ffi_parser.h" #include "compiler/vertex-util.h" - -static constexpr unsigned int calcHashOfTagName(const char *start, const char *end) { +static constexpr unsigned int calcHashOfTagName(const char* start, const char* end) { unsigned int hash = 5381; - for (const char *c = start; c != end; ++c) { + for (const char* c = start; c != end; ++c) { hash = (hash << 5) + hash + *c; } return hash; @@ -35,10 +34,12 @@ static constexpr unsigned int calcHashOfTagName(const char *start, const char *e struct KnownPhpDocTag { unsigned int hash; PhpDocType type; - const char *tag_name; + const char* tag_name; - constexpr KnownPhpDocTag(const char *tag_name, PhpDocType type) - : hash(calcHashOfTagName(tag_name, tag_name + __builtin_strlen(tag_name))), type(type), tag_name(tag_name) {} + constexpr KnownPhpDocTag(const char* tag_name, PhpDocType type) + : hash(calcHashOfTagName(tag_name, tag_name + __builtin_strlen(tag_name))), + type(type), + tag_name(tag_name) {} }; class AllDocTags { @@ -46,10 +47,10 @@ class AllDocTags { static const KnownPhpDocTag ALL_TAGS[N_TAGS]; public: - [[gnu::always_inline]] static PhpDocType name2type(const char *start, const char *end) { + [[gnu::always_inline]] static PhpDocType name2type(const char* start, const char* end) { unsigned int hash = calcHashOfTagName(start, end); - for (const KnownPhpDocTag &tag: ALL_TAGS) { + for (const KnownPhpDocTag& tag : ALL_TAGS) { if (tag.hash == hash) { return tag.type; } @@ -57,8 +58,8 @@ class AllDocTags { return PhpDocType::unknown; } - static const char *type2name(PhpDocType type) { - for (const KnownPhpDocTag &tag: ALL_TAGS) { + static const char* type2name(PhpDocType type) { + for (const KnownPhpDocTag& tag : ALL_TAGS) { if (tag.type == type) { return tag.tag_name; } @@ -68,54 +69,53 @@ class AllDocTags { }; const KnownPhpDocTag AllDocTags::ALL_TAGS[] = { - KnownPhpDocTag("@param", PhpDocType::param), - KnownPhpDocTag("@var", PhpDocType::var), - KnownPhpDocTag("@return", PhpDocType::returns), - KnownPhpDocTag("@type", PhpDocType::var), - KnownPhpDocTag("@returns", PhpDocType::returns), - KnownPhpDocTag("@kphp-inline", PhpDocType::kphp_inline), - KnownPhpDocTag("@kphp-flatten", PhpDocType::kphp_flatten), - KnownPhpDocTag("@kphp-infer", PhpDocType::kphp_infer), - KnownPhpDocTag("@kphp-required", PhpDocType::kphp_required), - KnownPhpDocTag("@kphp-lib-export", PhpDocType::kphp_lib_export), - KnownPhpDocTag("@kphp-sync", PhpDocType::kphp_sync), - KnownPhpDocTag("@kphp-should-not-throw", PhpDocType::kphp_should_not_throw), - KnownPhpDocTag("@kphp-throws", PhpDocType::kphp_throws), - KnownPhpDocTag("@kphp-disable-warnings", PhpDocType::kphp_disable_warnings), - KnownPhpDocTag("@kphp-extern-func-info", PhpDocType::kphp_extern_func_info), - KnownPhpDocTag("@kphp-pure-function", PhpDocType::kphp_pure_function), - KnownPhpDocTag("@kphp-template", PhpDocType::kphp_template), - KnownPhpDocTag("@kphp-generic", PhpDocType::kphp_generic), - KnownPhpDocTag("@kphp-tracing", PhpDocType::kphp_tracing), - KnownPhpDocTag("@kphp-param", PhpDocType::kphp_param), - KnownPhpDocTag("@kphp-return", PhpDocType::kphp_return), - KnownPhpDocTag("@kphp-memcache-class", PhpDocType::kphp_memcache_class), - KnownPhpDocTag("@kphp-immutable-class", PhpDocType::kphp_immutable_class), - KnownPhpDocTag("@kphp-tl-class", PhpDocType::kphp_tl_class), - KnownPhpDocTag("@kphp-generate-stub-class", PhpDocType::kphp_generated_stub_class), - KnownPhpDocTag("@kphp-const", PhpDocType::kphp_const), - KnownPhpDocTag("@kphp-no-return", PhpDocType::kphp_noreturn), - KnownPhpDocTag("@kphp-warn-unused-result", PhpDocType::kphp_warn_unused_result), - KnownPhpDocTag("@kphp-warn-performance", PhpDocType::kphp_warn_performance), - KnownPhpDocTag("@kphp-analyze-performance", PhpDocType::kphp_analyze_performance), - KnownPhpDocTag("@kphp-serializable", PhpDocType::kphp_serializable), - KnownPhpDocTag("@kphp-reserved-fields", PhpDocType::kphp_reserved_fields), - KnownPhpDocTag("@kphp-serialized-field", PhpDocType::kphp_serialized_field), - KnownPhpDocTag("@kphp-serialized-float32", PhpDocType::kphp_serialized_float32), - KnownPhpDocTag("@kphp-json", PhpDocType::kphp_json), - KnownPhpDocTag("@kphp-profile", PhpDocType::kphp_profile), - KnownPhpDocTag("@kphp-profile-allow-inline", PhpDocType::kphp_profile_allow_inline), - KnownPhpDocTag("@kphp-strict-types-enable", PhpDocType::kphp_strict_types_enable), - KnownPhpDocTag("@kphp-color", PhpDocType::kphp_color), - KnownPhpDocTag("@kphp-internal-result-indexing", PhpDocType::kphp_internal_result_indexing), - KnownPhpDocTag("@kphp-internal-result-array2tuple", PhpDocType::kphp_internal_result_array2tuple), - KnownPhpDocTag("@kphp-internal-param-readonly", PhpDocType::kphp_internal_param_readonly), + KnownPhpDocTag("@param", PhpDocType::param), + KnownPhpDocTag("@var", PhpDocType::var), + KnownPhpDocTag("@return", PhpDocType::returns), + KnownPhpDocTag("@type", PhpDocType::var), + KnownPhpDocTag("@returns", PhpDocType::returns), + KnownPhpDocTag("@kphp-inline", PhpDocType::kphp_inline), + KnownPhpDocTag("@kphp-flatten", PhpDocType::kphp_flatten), + KnownPhpDocTag("@kphp-infer", PhpDocType::kphp_infer), + KnownPhpDocTag("@kphp-required", PhpDocType::kphp_required), + KnownPhpDocTag("@kphp-lib-export", PhpDocType::kphp_lib_export), + KnownPhpDocTag("@kphp-sync", PhpDocType::kphp_sync), + KnownPhpDocTag("@kphp-should-not-throw", PhpDocType::kphp_should_not_throw), + KnownPhpDocTag("@kphp-throws", PhpDocType::kphp_throws), + KnownPhpDocTag("@kphp-disable-warnings", PhpDocType::kphp_disable_warnings), + KnownPhpDocTag("@kphp-extern-func-info", PhpDocType::kphp_extern_func_info), + KnownPhpDocTag("@kphp-pure-function", PhpDocType::kphp_pure_function), + KnownPhpDocTag("@kphp-template", PhpDocType::kphp_template), + KnownPhpDocTag("@kphp-generic", PhpDocType::kphp_generic), + KnownPhpDocTag("@kphp-tracing", PhpDocType::kphp_tracing), + KnownPhpDocTag("@kphp-param", PhpDocType::kphp_param), + KnownPhpDocTag("@kphp-return", PhpDocType::kphp_return), + KnownPhpDocTag("@kphp-memcache-class", PhpDocType::kphp_memcache_class), + KnownPhpDocTag("@kphp-immutable-class", PhpDocType::kphp_immutable_class), + KnownPhpDocTag("@kphp-tl-class", PhpDocType::kphp_tl_class), + KnownPhpDocTag("@kphp-generate-stub-class", PhpDocType::kphp_generated_stub_class), + KnownPhpDocTag("@kphp-const", PhpDocType::kphp_const), + KnownPhpDocTag("@kphp-no-return", PhpDocType::kphp_noreturn), + KnownPhpDocTag("@kphp-warn-unused-result", PhpDocType::kphp_warn_unused_result), + KnownPhpDocTag("@kphp-warn-performance", PhpDocType::kphp_warn_performance), + KnownPhpDocTag("@kphp-analyze-performance", PhpDocType::kphp_analyze_performance), + KnownPhpDocTag("@kphp-serializable", PhpDocType::kphp_serializable), + KnownPhpDocTag("@kphp-reserved-fields", PhpDocType::kphp_reserved_fields), + KnownPhpDocTag("@kphp-serialized-field", PhpDocType::kphp_serialized_field), + KnownPhpDocTag("@kphp-serialized-float32", PhpDocType::kphp_serialized_float32), + KnownPhpDocTag("@kphp-json", PhpDocType::kphp_json), + KnownPhpDocTag("@kphp-profile", PhpDocType::kphp_profile), + KnownPhpDocTag("@kphp-profile-allow-inline", PhpDocType::kphp_profile_allow_inline), + KnownPhpDocTag("@kphp-strict-types-enable", PhpDocType::kphp_strict_types_enable), + KnownPhpDocTag("@kphp-color", PhpDocType::kphp_color), + KnownPhpDocTag("@kphp-internal-result-indexing", PhpDocType::kphp_internal_result_indexing), + KnownPhpDocTag("@kphp-internal-result-array2tuple", PhpDocType::kphp_internal_result_array2tuple), + KnownPhpDocTag("@kphp-internal-param-readonly", PhpDocType::kphp_internal_param_readonly), }; - PhpDocComment::PhpDocComment(vk::string_view phpdoc_str) { - const char *c = phpdoc_str.data(); - const char *end = phpdoc_str.end(); + const char* c = phpdoc_str.data(); + const char* end = phpdoc_str.end(); auto iter_next = tags.before_begin(); while (c != end) { @@ -145,7 +145,7 @@ PhpDocComment::PhpDocComment(vk::string_view phpdoc_str) { } // c points to '@', read tag name until space - const char *start = c; + const char* start = c; while (c != end && *c != ' ' && *c != '\n' && *c != '\t') { ++c; } @@ -179,7 +179,7 @@ std::string PhpDocTag::get_tag_name() const noexcept { * or "$var tuple(int, string) maybe comment" or "A[] maybe comment" * parse a type (turn it into the TypeHint tree representation) and a variable name (if present). */ -PhpDocTag::TypeAndVarName PhpDocTag::value_as_type_and_var_name(FunctionPtr current_function, const GenericsDeclarationMixin *genericTs) const { +PhpDocTag::TypeAndVarName PhpDocTag::value_as_type_and_var_name(FunctionPtr current_function, const GenericsDeclarationMixin* genericTs) const { std::vector tokens = phpdoc_to_tokens(value); auto tok_iter = tokens.cbegin(); vk::string_view var_name; @@ -188,20 +188,19 @@ PhpDocTag::TypeAndVarName PhpDocTag::value_as_type_and_var_name(FunctionPtr curr if (tokens.front().type() == tok_var_name) { var_name = tokens.front().str_val; tok_iter++; - if (tokens.size() <= 2) { // only tok_end is left + if (tokens.size() <= 2) { // only tok_end is left return {nullptr, var_name}; } } PhpDocTypeHintParser parser(current_function, genericTs); - const TypeHint *type_hint{nullptr}; + const TypeHint* type_hint{nullptr}; try { type_hint = parser.parse_from_tokens(tok_iter); - } catch (std::runtime_error &ex) { + } catch (std::runtime_error& ex) { kphp_error(0, fmt_format("{}: {}\n{}", TermStringFormat::paint_red(TermStringFormat::add_text_attribute("Could not parse " + get_tag_name(), TermStringFormat::bold)), - TermStringFormat::add_text_attribute(value_as_string(), TermStringFormat::underline), - ex.what())); + TermStringFormat::add_text_attribute(value_as_string(), TermStringFormat::underline), ex.what())); } if (!type_hint) { @@ -211,7 +210,7 @@ PhpDocTag::TypeAndVarName PhpDocTag::value_as_type_and_var_name(FunctionPtr curr if (var_name.empty()) { kphp_assert(tok_iter != tokens.end()); // phpdoc|type $var_name maybe comment - if (tok_iter->type() == tok_var_name) { // tok_iter — right after the parsing is finished + if (tok_iter->type() == tok_var_name) { // tok_iter — right after the parsing is finished var_name = tok_iter->str_val; } } @@ -219,8 +218,7 @@ PhpDocTag::TypeAndVarName PhpDocTag::value_as_type_and_var_name(FunctionPtr curr return {type_hint, var_name}; } - -const TypeHint *PhpDocTypeHintParser::parse_classname(const std::string &phpdoc_class_name) { +const TypeHint* PhpDocTypeHintParser::parse_classname(const std::string& phpdoc_class_name) { cur_tok++; // here we have a relative class name, that can be resolved into full unless self/static/parent // if self/static/parent, it will be resolved at context, see phpdoc_finalize_type_hint_and_resolve() @@ -233,7 +231,7 @@ const TypeHint *PhpDocTypeHintParser::parse_classname(const std::string &phpdoc_ return TypeHintInstance::create(resolve_uses(current_function, phpdoc_class_name)); } -const TypeHint *PhpDocTypeHintParser::parse_ffi_cdata() { +const TypeHint* PhpDocTypeHintParser::parse_ffi_cdata() { if (vk::none_of_equal(cur_tok->type(), tok_lt, tok_oppar)) { throw std::runtime_error("expected '<' or '('"); } @@ -281,7 +279,7 @@ const TypeHint *PhpDocTypeHintParser::parse_ffi_cdata() { need_space = true; } else if (tok == tok_times) { cdef.push_back('*'); - } else if (tok == tok_opbrk) { + } else if (tok == tok_opbrk) { cdef.push_back('['); } else if (tok == tok_clbrk) { cdef.push_back(']'); @@ -308,7 +306,7 @@ const TypeHint *PhpDocTypeHintParser::parse_ffi_cdata() { return TypeHintFFIType::create(scope_name, type, transfer_ownership); } -const TypeHint *PhpDocTypeHintParser::parse_ffi_scope() { +const TypeHint* PhpDocTypeHintParser::parse_ffi_scope() { if (vk::none_of_equal(cur_tok->type(), tok_lt, tok_oppar)) { throw std::runtime_error("expected '<' or '('"); } @@ -337,7 +335,7 @@ const TypeHint *PhpDocTypeHintParser::parse_ffi_scope() { return TypeHintFFIScope::create(std::string(scope_name)); } -const TypeHint *PhpDocTypeHintParser::parse_simple_type() { +const TypeHint* PhpDocTypeHintParser::parse_simple_type() { TokenType cur_type = cur_tok->type(); // some type names inside phpdoc are not keywords/tokens, but they should be interpreted as such if (cur_type == tok_func_name) { @@ -349,166 +347,166 @@ const TypeHint *PhpDocTypeHintParser::parse_simple_type() { } switch (cur_type) { - case tok_end: - throw std::runtime_error("unexpected end"); - case tok_oppar: { - cur_tok++; - const TypeHint *type_hint = parse_type_expression(); - if (cur_tok->type() != tok_clpar) { - throw std::runtime_error("unmatching ()"); + case tok_end: + throw std::runtime_error("unexpected end"); + case tok_oppar: { + cur_tok++; + const TypeHint* type_hint = parse_type_expression(); + if (cur_tok->type() != tok_clpar) { + throw std::runtime_error("unmatching ()"); + } + cur_tok++; + return type_hint; + } + case tok_int: + cur_tok++; + return TypeHintPrimitive::create(tp_int); + case tok_bool: + [[fallthrough]]; + case tok_boolean: + cur_tok++; + return TypeHintPrimitive::create(tp_bool); + case tok_float: + case tok_double: + cur_tok++; + return TypeHintPrimitive::create(tp_float); + case tok_string: + cur_tok++; + return TypeHintPrimitive::create(tp_string); + case tok_false: + cur_tok++; + return TypeHintPrimitive::create(tp_False); + case tok_true: + cur_tok++; + return TypeHintPrimitive::create(tp_bool); + case tok_null: + cur_tok++; + return TypeHintPrimitive::create(tp_Null); + case tok_mixed: + cur_tok++; + return TypeHintPrimitive::create(tp_mixed); + case tok_void: + cur_tok++; + return TypeHintPrimitive::create(tp_void); + case tok_tuple: + cur_tok++; + return TypeHintTuple::create(parse_nested_type_hints()); + case tok_shape: + cur_tok++; + return parse_shape_type(); + case tok_callable: + cur_tok++; + if (cur_tok->type() == tok_oppar) { // callable(...) : ... — typed callable + return parse_typed_callable(); + } + return TypeHintCallable::create_untyped_callable(); + case tok_array: + cur_tok++; + if (vk::any_of_equal(cur_tok->type(), tok_lt, tok_oppar)) { // array<...> + const auto& type_hints = parse_nested_type_hints(); + if (type_hints.empty() || type_hints.size() > 2) { + throw std::runtime_error{"array<...> has to be parameterized with one type or two types at most"}; } - cur_tok++; - return type_hint; + // just ignore array's key type if there is any + return TypeHintArray::create(type_hints.back()); } - case tok_int: - cur_tok++; - return TypeHintPrimitive::create(tp_int); - case tok_bool: - [[fallthrough]]; - case tok_boolean: - cur_tok++; - return TypeHintPrimitive::create(tp_bool); - case tok_float: - case tok_double: - cur_tok++; - return TypeHintPrimitive::create(tp_float); - case tok_string: - cur_tok++; - return TypeHintPrimitive::create(tp_string); - case tok_false: - cur_tok++; - return TypeHintPrimitive::create(tp_False); - case tok_true: + return TypeHintArray::create_array_of_any(); + case tok_at: { // @tl\... + cur_tok++; + if (!cur_tok->str_val.starts_with("tl\\")) { + throw std::runtime_error("Invalid magic namespace after '@'"); + } + return parse_classname(G->settings().tl_namespace_prefix.get() + std::string(cur_tok->str_val).substr(3)); + } + case tok_xor: // ^1, ^2[*] (for functions.txt) + cur_tok++; + return parse_arg_ref(); + case tok_question: // ?string == string|null; ?string[] == string[]|null + cur_tok++; + return TypeHintOptional::create(parse_type_expression(), true, false); + case tok_object: + cur_tok++; + return TypeHintObject::create(); + case tok_class: + if ((cur_tok + 1)->type() == tok_minus && (cur_tok + 2)->type() == tok_string) { // class-string + cur_tok += 3; + const auto* nested = parse_nested_one_type_hint(); + if (!nested->try_as()) { + throw std::runtime_error("class-string<> should contain generic T inside"); + } + return TypeHintClassString::create(nested); + } + break; + + case tok_static: + case tok_func_name: + // tok_future doesn't exist, it's a string + if (vk::any_of_equal(cur_tok->str_val, "future", "\\future")) { cur_tok++; - return TypeHintPrimitive::create(tp_bool); - case tok_null: + return TypeHintFuture::create(tp_future, parse_nested_one_type_hint()); + } + // same for the future_queue + if (cur_tok->str_val == "future_queue") { cur_tok++; - return TypeHintPrimitive::create(tp_Null); - case tok_mixed: + return TypeHintFuture::create(tp_future_queue, parse_nested_one_type_hint()); + } + if (cur_tok->str_val == "ffi_cdata") { cur_tok++; - return TypeHintPrimitive::create(tp_mixed); - case tok_void: + return parse_ffi_cdata(); + } + if (cur_tok->str_val == "ffi_scope") { cur_tok++; - return TypeHintPrimitive::create(tp_void); - case tok_tuple: + return parse_ffi_scope(); + } + // plus some extra types that are not tokens as well, but they make sense inside the phpdoc/functions.txt + if (cur_tok->str_val == "any") { cur_tok++; - return TypeHintTuple::create(parse_nested_type_hints()); - case tok_shape: + return TypeHintPrimitive::create(tp_any); + } + if (cur_tok->str_val == "regexp") { cur_tok++; - return parse_shape_type(); - case tok_callable: + return TypeHintPrimitive::create(tp_regexp); + } + // force(T) = T (for PhpStorm) + if (cur_tok->str_val == "force") { cur_tok++; - if (cur_tok->type() == tok_oppar) { // callable(...) : ... — typed callable - return parse_typed_callable(); - } - return TypeHintCallable::create_untyped_callable(); - case tok_array: + return parse_nested_one_type_hint(); + } + // (for functions.txt) instance<^2> + if (cur_tok->str_val == "instance") { cur_tok++; - if (vk::any_of_equal(cur_tok->type(), tok_lt, tok_oppar)) { // array<...> - const auto &type_hints = parse_nested_type_hints(); - if (type_hints.empty() || type_hints.size() > 2) { - throw std::runtime_error{"array<...> has to be parameterized with one type or two types at most"}; - } - // just ignore array's key type if there is any - return TypeHintArray::create(type_hints.back()); - } - return TypeHintArray::create_array_of_any(); - case tok_at: { // @tl\... + const auto* nested = dynamic_cast(parse_nested_one_type_hint()); + kphp_assert(nested); + return TypeHintArgRefInstance::create(nested->arg_num); + } + if (cur_tok->str_val == "_tmp_string") { cur_tok++; - if (!cur_tok->str_val.starts_with("tl\\")) { - throw std::runtime_error("Invalid magic namespace after '@'"); + if (!current_function->is_extern()) { + throw std::runtime_error("_tmp_string type can only be used for KPHP builtin functions"); } - return parse_classname(G->settings().tl_namespace_prefix.get() + std::string(cur_tok->str_val).substr(3)); + return TypeHintPrimitive::create(tp_tmp_string); } - case tok_xor: // ^1, ^2[*] (for functions.txt) - cur_tok++; - return parse_arg_ref(); - case tok_question: // ?string == string|null; ?string[] == string[]|null + if (cur_tok->str_val == "not_null") { cur_tok++; - return TypeHintOptional::create(parse_type_expression(), true, false); - case tok_object: + return TypeHintNotNull::create(parse_nested_one_type_hint(), true, false); + } + if (cur_tok->str_val == "not_false") { cur_tok++; - return TypeHintObject::create(); - case tok_class: - if ((cur_tok + 1)->type() == tok_minus && (cur_tok + 2)->type() == tok_string) { // class-string - cur_tok += 3; - const auto *nested = parse_nested_one_type_hint(); - if (!nested->try_as()) { - throw std::runtime_error("class-string<> should contain generic T inside"); - } - return TypeHintClassString::create(nested); - } - break; - - case tok_static: - case tok_func_name: - // tok_future doesn't exist, it's a string - if (vk::any_of_equal(cur_tok->str_val, "future", "\\future")) { - cur_tok++; - return TypeHintFuture::create(tp_future, parse_nested_one_type_hint()); - } - // same for the future_queue - if (cur_tok->str_val == "future_queue") { - cur_tok++; - return TypeHintFuture::create(tp_future_queue, parse_nested_one_type_hint()); - } - if (cur_tok->str_val == "ffi_cdata") { - cur_tok++; - return parse_ffi_cdata(); - } - if (cur_tok->str_val == "ffi_scope") { - cur_tok++; - return parse_ffi_scope(); - } - // plus some extra types that are not tokens as well, but they make sense inside the phpdoc/functions.txt - if (cur_tok->str_val == "any") { - cur_tok++; - return TypeHintPrimitive::create(tp_any); - } - if (cur_tok->str_val == "regexp") { - cur_tok++; - return TypeHintPrimitive::create(tp_regexp); - } - // force(T) = T (for PhpStorm) - if (cur_tok->str_val == "force") { - cur_tok++; - return parse_nested_one_type_hint(); - } - // (for functions.txt) instance<^2> - if (cur_tok->str_val == "instance") { - cur_tok++; - const auto *nested = dynamic_cast(parse_nested_one_type_hint()); - kphp_assert(nested); - return TypeHintArgRefInstance::create(nested->arg_num); - } - if (cur_tok->str_val == "_tmp_string") { - cur_tok++; - if (!current_function->is_extern()) { - throw std::runtime_error("_tmp_string type can only be used for KPHP builtin functions"); - } - return TypeHintPrimitive::create(tp_tmp_string); - } - if (cur_tok->str_val == "not_null") { - cur_tok++; - return TypeHintNotNull::create(parse_nested_one_type_hint(), true, false); - } - if (cur_tok->str_val == "not_false") { - cur_tok++; - return TypeHintNotNull::create(parse_nested_one_type_hint(), false, true); - } - // otherwise interpreted as a class name (including the lowercase names); - // it works with the absolute and relative names as well as for a special names like 'self'; - // file 'use' directives are taken into the account - return parse_classname(std::string(cur_tok->str_val)); + return TypeHintNotNull::create(parse_nested_one_type_hint(), false, true); + } + // otherwise interpreted as a class name (including the lowercase names); + // it works with the absolute and relative names as well as for a special names like 'self'; + // file 'use' directives are taken into the account + return parse_classname(std::string(cur_tok->str_val)); - default: - break; + default: + break; } throw std::runtime_error(fmt_format("can't parse '{}'", cur_tok->str_val)); } -const TypeHint *PhpDocTypeHintParser::parse_arg_ref() { // ^1, ^2[*][*], ^3() +const TypeHint* PhpDocTypeHintParser::parse_arg_ref() { // ^1, ^2[*][*], ^3() if (cur_tok->type() != tok_int_const) { throw std::runtime_error("Invalid number after ^"); } @@ -520,7 +518,7 @@ const TypeHint *PhpDocTypeHintParser::parse_arg_ref() { // ^1, ^2[*][*], ^3() return TypeHintArgRefCallbackCall::create(arg_num); } - const TypeHint *res = TypeHintArgRef::create(arg_num); + const TypeHint* res = TypeHintArgRef::create(arg_num); while (cur_tok->type() == tok_opbrk && (cur_tok + 1)->type() == tok_times && (cur_tok + 2)->type() == tok_clbrk) { res = TypeHintArgSubkeyGet::create(res); cur_tok += 3; @@ -529,10 +527,10 @@ const TypeHint *PhpDocTypeHintParser::parse_arg_ref() { // ^1, ^2[*][*], ^3() return res; } -const TypeHint *PhpDocTypeHintParser::parse_type_array() { - const TypeHint *inner = parse_simple_type(); +const TypeHint* PhpDocTypeHintParser::parse_type_array() { + const TypeHint* inner = parse_simple_type(); - if (cur_tok->type() == tok_double_colon) { // T::methodName(), T::fieldName + if (cur_tok->type() == tok_double_colon) { // T::methodName(), T::fieldName cur_tok++; if (cur_tok->type() == tok_func_name && (cur_tok + 1)->type() == tok_oppar && (cur_tok + 2)->type() == tok_clpar) { inner = TypeHintRefToMethod::create(inner, std::string(cur_tok->str_val)); @@ -553,12 +551,12 @@ const TypeHint *PhpDocTypeHintParser::parse_type_array() { return inner; } -std::vector PhpDocTypeHintParser::parse_nested_type_hints() { +std::vector PhpDocTypeHintParser::parse_nested_type_hints() { if (vk::none_of_equal(cur_tok->type(), tok_lt, tok_oppar)) { throw std::runtime_error("expected '('"); } cur_tok++; - std::vector sub_types; + std::vector sub_types; while (true) { sub_types.emplace_back(parse_type_expression()); @@ -574,13 +572,13 @@ std::vector PhpDocTypeHintParser::parse_nested_type_hints() { return sub_types; } -const TypeHint *PhpDocTypeHintParser::parse_nested_one_type_hint() { +const TypeHint* PhpDocTypeHintParser::parse_nested_one_type_hint() { if (vk::none_of_equal(cur_tok->type(), tok_lt, tok_oppar)) { throw std::runtime_error("expected '('"); } cur_tok++; - const TypeHint *sub_type = parse_type_expression(); + const TypeHint* sub_type = parse_type_expression(); if (vk::none_of_equal(cur_tok->type(), tok_gt, tok_clpar)) { throw std::runtime_error("expected ')'"); } @@ -589,13 +587,13 @@ const TypeHint *PhpDocTypeHintParser::parse_nested_one_type_hint() { return sub_type; } -const TypeHint *PhpDocTypeHintParser::parse_typed_callable() { // callable(int, int):?string, callable(int $x), callable():void +const TypeHint* PhpDocTypeHintParser::parse_typed_callable() { // callable(int, int):?string, callable(int $x), callable():void if (cur_tok->type() != tok_oppar) { throw std::runtime_error("expected '('"); } cur_tok++; - std::vector arg_types; + std::vector arg_types; while (true) { if (cur_tok->type() == tok_clpar) { cur_tok++; @@ -603,7 +601,7 @@ const TypeHint *PhpDocTypeHintParser::parse_typed_callable() { // callable(int, } arg_types.emplace_back(parse_type_expression()); - if (cur_tok->type() == tok_var_name) { // callable(int $x) — var name is like a comment in declaration + if (cur_tok->type() == tok_var_name) { // callable(int $x) — var name is like a comment in declaration cur_tok++; } if (cur_tok->type() == tok_comma) { @@ -613,7 +611,7 @@ const TypeHint *PhpDocTypeHintParser::parse_typed_callable() { // callable(int, } } - const TypeHint *return_type; + const TypeHint* return_type; if (cur_tok->type() == tok_colon) { cur_tok++; return_type = parse_type_expression(); @@ -624,13 +622,13 @@ const TypeHint *PhpDocTypeHintParser::parse_typed_callable() { // callable(int, return TypeHintCallable::create(std::move(arg_types), return_type); } -const TypeHint *PhpDocTypeHintParser::parse_shape_type() { +const TypeHint* PhpDocTypeHintParser::parse_shape_type() { if (vk::none_of_equal(cur_tok->type(), tok_lt, tok_oppar)) { throw std::runtime_error("expected '('"); } cur_tok++; - std::vector> shape_items; + std::vector> shape_items; bool has_varg = false; // example: shape(x:int, y?:\A, z:tuple(...)) // elements are [ op_double_arrow ( op_func_name "x", TypeHint "int" ), ... ] @@ -649,7 +647,7 @@ const TypeHint *PhpDocTypeHintParser::parse_shape_type() { } cur_tok++; - const TypeHint *elem_type_hint = parse_type_expression(); + const TypeHint* elem_type_hint = parse_type_expression(); if (is_nullable) { elem_type_hint = TypeHintOptional::create(elem_type_hint, true, false); const std::int64_t hash = string_hash(elem_name.data(), elem_name.size()); @@ -683,20 +681,20 @@ const TypeHint *PhpDocTypeHintParser::parse_shape_type() { return TypeHintShape::create(std::move(shape_items), has_varg); } -const TypeHint *PhpDocTypeHintParser::parse_type_expression() { - const TypeHint *result = parse_type_array(); +const TypeHint* PhpDocTypeHintParser::parse_type_expression() { + const TypeHint* result = parse_type_array(); if (cur_tok->type() != tok_or) { return result; } - std::vector items; + std::vector items; bool was_raw_bool = false; bool was_false = false; bool was_null = false; - - auto on_each_item = [&](const TypeHint *item) { + + auto on_each_item = [&](const TypeHint* item) { items.emplace_back(item); - if (const auto *as_primitive = item->try_as()) { + if (const auto* as_primitive = item->try_as()) { was_raw_bool |= as_primitive->ptype == tp_bool && (cur_tok - 1)->type() == tok_bool; was_false |= as_primitive->ptype == tp_False; was_null |= as_primitive->ptype == tp_Null; @@ -716,8 +714,8 @@ const TypeHint *PhpDocTypeHintParser::parse_type_expression() { // try to simplify: T|false and similar as an optional, not as a vector bool can_be_simplified_as_optional = 1 == (items.size() - was_false - was_null); if (can_be_simplified_as_optional) { - for (const TypeHint *item : items) { - const auto *as_primitive = item->try_as(); + for (const TypeHint* item : items) { + const auto* as_primitive = item->try_as(); if (!as_primitive || vk::none_of_equal(as_primitive->ptype, tp_Null, tp_False)) { return TypeHintOptional::create(item, was_null, was_false); } @@ -727,9 +725,9 @@ const TypeHint *PhpDocTypeHintParser::parse_type_expression() { return TypeHintPipe::create(std::move(items)); } -const TypeHint *PhpDocTypeHintParser::parse_from_tokens(std::vector::const_iterator &tok_iter) { +const TypeHint* PhpDocTypeHintParser::parse_from_tokens(std::vector::const_iterator& tok_iter) { cur_tok = tok_iter; - const TypeHint *v = parse_type_expression(); // could throw an exception + const TypeHint* v = parse_type_expression(); // could throw an exception // "?int ...$args" == "(?int)[] $args", "int|false ...$a" == "(int|false)[] $a"; handle "..." after all has been parsed if (cur_tok->type() == tok_varg) { @@ -738,13 +736,13 @@ const TypeHint *PhpDocTypeHintParser::parse_from_tokens(std::vector::cons } tok_iter = cur_tok; - return v; // not null if an exception was not thrown + return v; // not null if an exception was not thrown } -const TypeHint *PhpDocTypeHintParser::parse_from_tokens_silent(std::vector::const_iterator &tok_iter) noexcept { +const TypeHint* PhpDocTypeHintParser::parse_from_tokens_silent(std::vector::const_iterator& tok_iter) noexcept { try { return parse_from_tokens(tok_iter); - } catch (std::runtime_error &) { + } catch (std::runtime_error&) { return {}; } } @@ -757,7 +755,7 @@ const TypeHint *PhpDocTypeHintParser::parse_from_tokens_silent(std::vectorfile_id->is_builtin()) { return type_hint; } @@ -770,8 +768,8 @@ const TypeHint *phpdoc_finalize_type_hint_and_resolve(const TypeHint *type_hint, } if (type_hint->has_instances_inside()) { - type_hint->traverse([&all_resolved, resolve_context](const TypeHint *child) { - if (const auto *as_instance = child->try_as()) { + type_hint->traverse([&all_resolved, resolve_context](const TypeHint* child) { + if (const auto* as_instance = child->try_as()) { ClassPtr klass = as_instance->resolve(); if (!klass) { all_resolved = false; @@ -784,11 +782,11 @@ const TypeHint *phpdoc_finalize_type_hint_and_resolve(const TypeHint *type_hint, modulite_check_when_use_class(resolve_context, klass); } - } else if (const auto *as_scope = child->try_as()) { + } else if (const auto* as_scope = child->try_as()) { ClassPtr klass = G->get_class(FFIRoot::scope_class_name(as_scope->scope_name)); kphp_error_return(klass, fmt_format("Could not find ffi_scope<{}>", as_scope->scope_name)); - } else if (const auto *as_ffi = child->try_as()) { + } else if (const auto* as_ffi = child->try_as()) { if (vk::any_of_equal(as_ffi->type->kind, FFITypeKind::Struct, FFITypeKind::Union)) { ClassPtr klass = G->get_class(FFIRoot::cdata_class_name(as_ffi->scope_name, as_ffi->type->str)); kphp_error_return(klass, fmt_format("Could not find ffi_cdata<{}, {}>", as_ffi->scope_name, as_ffi->type->str)); @@ -802,19 +800,19 @@ const TypeHint *phpdoc_finalize_type_hint_and_resolve(const TypeHint *type_hint, if (type_hint->has_autogeneric_inside()) { // 'callable' and 'object' are allowed only standalone; fire an error for 'callable[]' and other nested - kphp_error(type_hint->try_as() || - (type_hint->try_as() && type_hint->try_as()->is_untyped_callable()), - "Keywords 'callable' and 'object' have special treatment, they are not real types.\nThey can be used for a parameter, implicitly converting a function into generic.\nThey can NOT be used inside arrays, tuples, etc. — only as a standalone keyword.\nConsider using typed callables instead of 'callable', and generic functions/classes instead of 'object'."); + kphp_error(type_hint->try_as() || (type_hint->try_as() && type_hint->try_as()->is_untyped_callable()), + "Keywords 'callable' and 'object' have special treatment, they are not real types.\nThey can be used for a parameter, implicitly converting a " + "function into generic.\nThey can NOT be used inside arrays, tuples, etc. — only as a standalone keyword.\nConsider using typed callables " + "instead of 'callable', and generic functions/classes instead of 'object'."); } if (type_hint->has_callables_inside()) { - type_hint->traverse([](const TypeHint *child) { - if (const auto *as_callable = child->try_as()) { + type_hint->traverse([](const TypeHint* child) { + if (const auto* as_callable = child->try_as()) { if (as_callable->is_typed_callable() && !as_callable->has_genericT_inside()) { as_callable->get_interface(); } - } }); } @@ -827,23 +825,22 @@ const TypeHint *phpdoc_finalize_type_hint_and_resolve(const TypeHint *type_hint, * We also handle @return here, that can ref to a field T::fieldName, replacing it after T is instantiated. * (note, that we don't allow ClassName::fieldName anywhere but in generics; if it's written, it will fail on type inferring) */ -const TypeHint *phpdoc_replace_genericTs_with_reified(const TypeHint *type_hint, const GenericsInstantiationMixin *reifiedTs) { +const TypeHint* phpdoc_replace_genericTs_with_reified(const TypeHint* type_hint, const GenericsInstantiationMixin* reifiedTs) { if (!type_hint->has_genericT_inside()) { return type_hint; } - return type_hint->replace_children_custom([reifiedTs](const TypeHint *child) { - - if (const auto *as_genericT = child->try_as()) { - const TypeHint *replacement = reifiedTs->find(as_genericT->nameT); + return type_hint->replace_children_custom([reifiedTs](const TypeHint* child) { + if (const auto* as_genericT = child->try_as()) { + const TypeHint* replacement = reifiedTs->find(as_genericT->nameT); return replacement ?: child; } - if (const auto *as_field_ref = child->try_as()) { - const TypeHint *field_type_hint = as_field_ref->resolve_field_type_hint(); + if (const auto* as_field_ref = child->try_as()) { + const TypeHint* field_type_hint = as_field_ref->resolve_field_type_hint(); kphp_error(field_type_hint, "Could not detect a field that :: points to in phpdoc white instantiating generics"); return field_type_hint ?: TypeHintPrimitive::create(tp_any); } - if (const auto *as_field_ref = child->try_as()) { + if (const auto* as_field_ref = child->try_as()) { FunctionPtr method = as_field_ref->resolve_method(); kphp_error(method, "Could not detect a method that :: points to in phpdoc white instantiating generics"); return method && method->return_typehint ? method->return_typehint : TypeHintPrimitive::create(tp_any); @@ -855,46 +852,46 @@ const TypeHint *phpdoc_replace_genericTs_with_reified(const TypeHint *type_hint, // when a field has neither @var not type hint, we use the default value initializer like a type guard // here we convert this value initializer (init_val) to a TypeHint, like a phpdoc was actually written -const TypeHint *phpdoc_convert_default_value_to_type_hint(VertexPtr init_val) { +const TypeHint* phpdoc_convert_default_value_to_type_hint(VertexPtr init_val) { switch (init_val->type()) { - case op_define_val: - return phpdoc_convert_default_value_to_type_hint(init_val.as()->value()); - case op_int_const: - case op_conv_int: - return TypeHintPrimitive::create(tp_int); - case op_string: - case op_string_build: - case op_concat: - return TypeHintPrimitive::create(tp_string); - case op_float_const: - case op_conv_float: - return TypeHintPrimitive::create(tp_float); - case op_array: - case op_conv_array: - // an array as a default => like "array" as a type hint, meaning "array of any", regardless of elements values - return TypeHintArray::create_array_of_any(); - case op_true: - case op_false: - return TypeHintPrimitive::create(tp_bool); - case op_mul: - case op_sub: - case op_plus: { - const auto *lhs_type_hint = phpdoc_convert_default_value_to_type_hint(init_val.as()->lhs())->try_as(); - const auto *rhs_type_hint = phpdoc_convert_default_value_to_type_hint(init_val.as()->rhs())->try_as(); - if (lhs_type_hint && rhs_type_hint) { - if (lhs_type_hint->ptype == tp_float || rhs_type_hint->ptype == tp_float) { - return TypeHintPrimitive::create(tp_float); - } else if (lhs_type_hint->ptype == tp_int && rhs_type_hint->ptype == tp_int) { - return TypeHintPrimitive::create(tp_int); - } + case op_define_val: + return phpdoc_convert_default_value_to_type_hint(init_val.as()->value()); + case op_int_const: + case op_conv_int: + return TypeHintPrimitive::create(tp_int); + case op_string: + case op_string_build: + case op_concat: + return TypeHintPrimitive::create(tp_string); + case op_float_const: + case op_conv_float: + return TypeHintPrimitive::create(tp_float); + case op_array: + case op_conv_array: + // an array as a default => like "array" as a type hint, meaning "array of any", regardless of elements values + return TypeHintArray::create_array_of_any(); + case op_true: + case op_false: + return TypeHintPrimitive::create(tp_bool); + case op_mul: + case op_sub: + case op_plus: { + const auto* lhs_type_hint = phpdoc_convert_default_value_to_type_hint(init_val.as()->lhs())->try_as(); + const auto* rhs_type_hint = phpdoc_convert_default_value_to_type_hint(init_val.as()->rhs())->try_as(); + if (lhs_type_hint && rhs_type_hint) { + if (lhs_type_hint->ptype == tp_float || rhs_type_hint->ptype == tp_float) { + return TypeHintPrimitive::create(tp_float); + } else if (lhs_type_hint->ptype == tp_int && rhs_type_hint->ptype == tp_int) { + return TypeHintPrimitive::create(tp_int); } - return {}; - } - case op_div: - return TypeHintPrimitive::create(tp_float); - - default: - // 'null' or something strange as a default — can't detect, will report "specify @var manually" - return {}; + } + return {}; + } + case op_div: + return TypeHintPrimitive::create(tp_float); + + default: + // 'null' or something strange as a default — can't detect, will report "specify @var manually" + return {}; } } diff --git a/compiler/phpdoc.h b/compiler/phpdoc.h index 07a5151a67..ced07d3908 100644 --- a/compiler/phpdoc.h +++ b/compiler/phpdoc.h @@ -4,14 +4,13 @@ #pragma once -#include #include +#include #include #include "compiler/data/data_ptr.h" #include "compiler/data/vertex-adaptor.h" - enum class PhpDocType { unknown, kphp_inline, @@ -64,22 +63,27 @@ struct PhpDocTag { // if a tag value is like "int|false $var_name" (for @param / @var / etc.), // it's represented as this structure struct TypeAndVarName { - const TypeHint *type_hint{nullptr}; - vk::string_view var_name; // stored without leading "$"; could be empty if omitted in phpdoc + const TypeHint* type_hint{nullptr}; + vk::string_view var_name; // stored without leading "$"; could be empty if omitted in phpdoc - operator bool() const noexcept { return static_cast(type_hint); } + operator bool() const noexcept { + return static_cast(type_hint); + } }; - PhpDocType type; vk::string_view value; - PhpDocTag(PhpDocType type, vk::string_view value) : type(type), value(value) {} + PhpDocTag(PhpDocType type, vk::string_view value) + : type(type), + value(value) {} std::string get_tag_name() const noexcept; - std::string value_as_string() const noexcept { return std::string(value); } - TypeAndVarName value_as_type_and_var_name(FunctionPtr current_function, const GenericsDeclarationMixin *genericTs) const; + std::string value_as_string() const noexcept { + return std::string(value); + } + TypeAndVarName value_as_type_and_var_name(FunctionPtr current_function, const GenericsDeclarationMixin* genericTs) const; }; // a class representing whole php doc comment @@ -92,7 +96,7 @@ class PhpDocComment { explicit PhpDocComment(vk::string_view phpdoc_str); bool has_tag(PhpDocType type) const noexcept { - for (const PhpDocTag &tag: tags) { + for (const PhpDocTag& tag : tags) { if (tag.type == type) { return true; } @@ -101,7 +105,7 @@ class PhpDocComment { } bool has_tag(PhpDocType type, PhpDocType or_type2) const noexcept { - for (const PhpDocTag &tag: tags) { + for (const PhpDocTag& tag : tags) { if (tag.type == type || tag.type == or_type2) { return true; } @@ -109,8 +113,8 @@ class PhpDocComment { return false; } - const PhpDocTag *find_tag(PhpDocType type) const noexcept { - for (const PhpDocTag &tag: tags) { + const PhpDocTag* find_tag(PhpDocType type) const noexcept { + for (const PhpDocTag& tag : tags) { if (tag.type == type) { return &tag; } @@ -123,31 +127,31 @@ class PhpDocComment { // such parsing could be done only based on current_function, when we know all classes and function's properties class PhpDocTypeHintParser { public: - explicit PhpDocTypeHintParser(FunctionPtr current_function, const GenericsDeclarationMixin *genericTs) - : current_function(current_function) - , genericTs(genericTs) {} + explicit PhpDocTypeHintParser(FunctionPtr current_function, const GenericsDeclarationMixin* genericTs) + : current_function(current_function), + genericTs(genericTs) {} - const TypeHint *parse_from_tokens(std::vector::const_iterator &tok_iter); - const TypeHint *parse_from_tokens_silent(std::vector::const_iterator &tok_iter) noexcept; + const TypeHint* parse_from_tokens(std::vector::const_iterator& tok_iter); + const TypeHint* parse_from_tokens_silent(std::vector::const_iterator& tok_iter) noexcept; private: FunctionPtr current_function; - const GenericsDeclarationMixin *genericTs; + const GenericsDeclarationMixin* genericTs; std::vector::const_iterator cur_tok; - const TypeHint *parse_ffi_scope(); - const TypeHint *parse_ffi_cdata(); - const TypeHint *parse_classname(const std::string &phpdoc_class_name); - const TypeHint *parse_simple_type(); - const TypeHint *parse_arg_ref(); - const TypeHint *parse_type_array(); - std::vector parse_nested_type_hints(); - const TypeHint *parse_shape_type(); - const TypeHint *parse_nested_one_type_hint(); - const TypeHint *parse_typed_callable(); - const TypeHint *parse_type_expression(); + const TypeHint* parse_ffi_scope(); + const TypeHint* parse_ffi_cdata(); + const TypeHint* parse_classname(const std::string& phpdoc_class_name); + const TypeHint* parse_simple_type(); + const TypeHint* parse_arg_ref(); + const TypeHint* parse_type_array(); + std::vector parse_nested_type_hints(); + const TypeHint* parse_shape_type(); + const TypeHint* parse_nested_one_type_hint(); + const TypeHint* parse_typed_callable(); + const TypeHint* parse_type_expression(); }; -const TypeHint *phpdoc_finalize_type_hint_and_resolve(const TypeHint *type_hint, FunctionPtr resolve_context); -const TypeHint *phpdoc_replace_genericTs_with_reified(const TypeHint *type_hint, const GenericsInstantiationMixin *reifiedTs); -const TypeHint *phpdoc_convert_default_value_to_type_hint(VertexPtr init_val); +const TypeHint* phpdoc_finalize_type_hint_and_resolve(const TypeHint* type_hint, FunctionPtr resolve_context); +const TypeHint* phpdoc_replace_genericTs_with_reified(const TypeHint* type_hint, const GenericsInstantiationMixin* reifiedTs); +const TypeHint* phpdoc_convert_default_value_to_type_hint(VertexPtr init_val); diff --git a/compiler/pipes/analyze-performance.cpp b/compiler/pipes/analyze-performance.cpp index d10df0e72e..6ca295c6a7 100644 --- a/compiler/pipes/analyze-performance.cpp +++ b/compiler/pipes/analyze-performance.cpp @@ -29,12 +29,9 @@ VertexPtr remove_conv_wrap(VertexPtr vertex) noexcept { } bool is_pure_nary_operation(VertexPtr vertex) noexcept { - return vk::any_of_equal(vertex->type(), op_minus, op_plus, op_not, - op_add, op_mul, op_sub, op_div, op_mod, op_pow, - op_and, op_or, op_xor, op_shl, op_shr, - op_log_xor_let, op_log_and_let, op_log_or_let, op_log_and, op_log_or, - op_eq2, op_eq3, op_le, op_lt, - op_spaceship, op_null_coalesce, op_ternary, op_isset, op_string_build); + return vk::any_of_equal(vertex->type(), op_minus, op_plus, op_not, op_add, op_mul, op_sub, op_div, op_mod, op_pow, op_and, op_or, op_xor, op_shl, op_shr, + op_log_xor_let, op_log_and_let, op_log_or_let, op_log_and, op_log_or, op_eq2, op_eq3, op_le, op_lt, op_spaceship, op_null_coalesce, + op_ternary, op_isset, op_string_build); } template @@ -48,49 +45,45 @@ template std::string get_description_for_help_impl(VertexPtr expr) { expr = remove_conv_wrap(expr); switch (expr->type()) { - case op_var: - if (const auto *constexpr_str = VertexUtil::get_constexpr_string(expr)) { - std::string raw_str{constexpr_str->c_str(), std::min(constexpr_str->size(), size_t{36})}; - if (raw_str.size() < constexpr_str->size()) { - raw_str.append("<...>"); - } - std::replace_if(raw_str.begin(), raw_str.end(), - [](char c) { - return iscntrl(c) || vk::any_of_equal(c, '"', '\'', '\\'); - }, '?'); - raw_str.erase(std::unique(raw_str.begin(), raw_str.end(), - [](char lhs, char rhs) { return vk::any_of_equal(lhs, '?', ' ') && lhs == rhs; }), - raw_str.end()); - return "'" + vk::replace_all(raw_str, "?", "<...>") + "'"; + case op_var: + if (const auto* constexpr_str = VertexUtil::get_constexpr_string(expr)) { + std::string raw_str{constexpr_str->c_str(), std::min(constexpr_str->size(), size_t{36})}; + if (raw_str.size() < constexpr_str->size()) { + raw_str.append("<...>"); } - return (full ? "variable " : "") + TermStringFormat::paint_green(expr.as()->var_id->as_human_readable()); - case op_instance_prop: - return (full ? "variable " : "") + TermStringFormat::paint_green(expr.as()->var_id->as_human_readable()); - case op_func_call: - return (full ? "function call " : "") + TermStringFormat::paint_green(expr.as()->func_id->as_human_readable(false)) + - "(" + vk::join(expr.as()->args(), ", ", get_description_for_help_impl) + ")"; - case op_index: { - std::string key; - auto op_index_vertex = expr.as(); - if (op_index_vertex->has_key()) { - key = get_description_for_help_impl(op_index_vertex->key()); - } - return (full ? "array element " : "") + get_description_for_help_impl(op_index_vertex->array()) + "[" + key + "]"; + std::replace_if(raw_str.begin(), raw_str.end(), [](char c) { return iscntrl(c) || vk::any_of_equal(c, '"', '\'', '\\'); }, '?'); + raw_str.erase(std::unique(raw_str.begin(), raw_str.end(), [](char lhs, char rhs) { return vk::any_of_equal(lhs, '?', ' ') && lhs == rhs; }), + raw_str.end()); + return "'" + vk::replace_all(raw_str, "?", "<...>") + "'"; + } + return (full ? "variable " : "") + TermStringFormat::paint_green(expr.as()->var_id->as_human_readable()); + case op_instance_prop: + return (full ? "variable " : "") + TermStringFormat::paint_green(expr.as()->var_id->as_human_readable()); + case op_func_call: + return (full ? "function call " : "") + TermStringFormat::paint_green(expr.as()->func_id->as_human_readable(false)) + "(" + + vk::join(expr.as()->args(), ", ", get_description_for_help_impl) + ")"; + case op_index: { + std::string key; + auto op_index_vertex = expr.as(); + if (op_index_vertex->has_key()) { + key = get_description_for_help_impl(op_index_vertex->key()); } - case op_string_build: - return join_string_build_elements(expr.as()->args()); - case op_true: - return "true"; - case op_false: - return "false"; - case op_null: - return "null"; - case op_int_const: - case op_float_const: - return expr.as()->str_val; - default: - // TODO add more cases - return full ? "expresion <...>" : "<...>"; + return (full ? "array element " : "") + get_description_for_help_impl(op_index_vertex->array()) + "[" + key + "]"; + } + case op_string_build: + return join_string_build_elements(expr.as()->args()); + case op_true: + return "true"; + case op_false: + return "false"; + case op_null: + return "null"; + case op_int_const: + case op_float_const: + return expr.as()->str_val; + default: + // TODO add more cases + return full ? "expresion <...>" : "<...>"; } } @@ -110,40 +103,40 @@ bool is_same_var_expression(VertexPtr lhs, VertexPtr rhs) noexcept { } switch (lhs->type()) { - case op_var: - if (lhs.as()->var_id != rhs.as()->var_id) { - return false; - } - break; - case op_instance_prop: - if (lhs.as()->var_id != rhs.as()->var_id) { - return false; - } - break; - case op_int_const: - case op_float_const: - if (lhs.as()->str_val != rhs.as()->str_val) { - return false; - } - break; - case op_index: - case op_false: - case op_true: - case op_null: - break; - default: - if (!is_pure_nary_operation(lhs)) { - // unsupported compare - return false; - } + case op_var: + if (lhs.as()->var_id != rhs.as()->var_id) { + return false; + } + break; + case op_instance_prop: + if (lhs.as()->var_id != rhs.as()->var_id) { + return false; + } + break; + case op_int_const: + case op_float_const: + if (lhs.as()->str_val != rhs.as()->str_val) { + return false; + } + break; + case op_index: + case op_false: + case op_true: + case op_null: + break; + default: + if (!is_pure_nary_operation(lhs)) { + // unsupported compare + return false; + } } return std::equal(lhs->begin(), lhs->end(), rhs->begin(), rhs->end(), is_same_var_expression); } VertexPtr get_first_arg_from_builtin_call(VertexAdaptor func_call, vk::string_view func_name) noexcept { return func_call && func_call->func_id->is_extern() && func_call->func_id->name == func_name && !func_call->args().empty() - ? remove_conv_wrap(func_call->args().front()) - : VertexPtr{}; + ? remove_conv_wrap(func_call->args().front()) + : VertexPtr{}; } VertexPtr get_first_arg_from_array_merge_call(VertexAdaptor func_call) noexcept { @@ -151,18 +144,11 @@ VertexPtr get_first_arg_from_array_merge_call(VertexAdaptor func_c } constexpr auto get_reserve_function_names() noexcept { - return vk::to_array( - { - "array_reserve", - "array_reserve_vector", - "array_reserve_map_int_keys", - "array_reserve_map_string_keys", - "array_reserve_from" - }); + return vk::to_array({"array_reserve", "array_reserve_vector", "array_reserve_map_int_keys", "array_reserve_map_string_keys", "array_reserve_from"}); } VertexPtr get_first_arg_from_array_reserve_call(VertexAdaptor func_call) noexcept { - for (const auto *reserve_function : get_reserve_function_names()) { + for (const auto* reserve_function : get_reserve_function_names()) { if (auto first_arg = get_first_arg_from_builtin_call(func_call, reserve_function)) { return first_arg; } @@ -177,10 +163,8 @@ bool is_var_can_be_optimized_in_loop(VertexAdaptor op_var_vertex) noexce bool is_op_index_sequence_with_non_int_keys(VertexPtr expr) noexcept { expr = remove_conv_wrap(expr); if (auto op_index_vertex = expr.try_as()) { - return !op_index_vertex->has_key() || - tinf::get_type(op_index_vertex->key())->get_real_ptype() != tp_int || - is_op_index_sequence_with_non_int_keys(op_index_vertex->array()) || - is_op_index_sequence_with_non_int_keys(op_index_vertex->key()); + return !op_index_vertex->has_key() || tinf::get_type(op_index_vertex->key())->get_real_ptype() != tp_int || + is_op_index_sequence_with_non_int_keys(op_index_vertex->array()) || is_op_index_sequence_with_non_int_keys(op_index_vertex->key()); } return vk::none_of_equal(expr->type(), op_var, op_int_const, op_float_const); } @@ -193,7 +177,7 @@ std::string prepare_for_json(std::string str) noexcept { void AnalyzePerformance::analyze_func_call(VertexAdaptor func_call) noexcept { if (is_enabled() && !func_call->func_id->is_extern()) { - const auto &func_params = func_call->func_id->param_ids; + const auto& func_params = func_call->func_id->param_ids; VertexRange call_params = func_call->args(); const size_t params_count = std::min(func_params.size(), static_cast(call_params.size())); for (size_t i = 0; i < params_count; ++i) { @@ -230,8 +214,7 @@ void AnalyzePerformance::analyze_set_array_value(VertexAdaptor op_ if (is_enabled()) { const auto first_arg = get_first_arg_from_array_merge_call(op_set_value_vertex->value().try_as()); auto first_arg_array_index = first_arg.try_as(); - if (first_arg_array_index && first_arg_array_index->has_key() && - is_same_var_expression(op_set_value_vertex->key(), first_arg_array_index->key()) && + if (first_arg_array_index && first_arg_array_index->has_key() && is_same_var_expression(op_set_value_vertex->key(), first_arg_array_index->key()) && is_same_var_expression(op_set_value_vertex->array(), first_arg_array_index->array())) { trigger_array_merge(first_arg); } @@ -243,7 +226,7 @@ void AnalyzePerformance::analyze_set_array_value(VertexAdaptor op_ template void AnalyzePerformance::analyze_array_insertion(VertexAdaptor vertex) noexcept { if (is_enabled()) { - const auto *to_type = tinf::get_type(vertex->array()); + const auto* to_type = tinf::get_type(vertex->array()); if (to_type->get_real_ptype() == tp_array) { to_type = to_type->lookup_at_any_key(); } @@ -255,7 +238,7 @@ void AnalyzePerformance::analyze_array_insertion(VertexAdaptor vertex) noexc void AnalyzePerformance::analyze_op_array(VertexAdaptor op_array_vertex) noexcept { if (is_enabled()) { - const auto *to_type = tinf::get_type(op_array_vertex)->lookup_at_any_key(); + const auto* to_type = tinf::get_type(op_array_vertex)->lookup_at_any_key(); for (auto array_element : *op_array_vertex) { if (vk::any_of_equal(array_element->type(), op_var, op_array)) { check_implicit_array_conversion(array_element, to_type); @@ -281,8 +264,8 @@ void AnalyzePerformance::analyze_op_var(VertexAdaptor op_var_vertex) noe } } -void AnalyzePerformance::check_implicit_array_conversion(VertexPtr expr, const TypeData *to) noexcept { - const auto *from = tinf::get_type(expr); +void AnalyzePerformance::check_implicit_array_conversion(VertexPtr expr, const TypeData* to) noexcept { + const auto* from = tinf::get_type(expr); if (is_implicit_array_conversion(from, to)) { trigger_inspection(PerformanceInspections::implicit_array_cast, get_description_for_help(expr) + " is implicitly converted from " + from->as_human_readable() + " to " + to->as_human_readable()); @@ -306,12 +289,11 @@ void AnalyzePerformance::run_second_pass_on_loop_exit(VertexPtr vertex, uint64_t } } if (auto op_string_build_vertex = vertex.try_as()) { - auto first_it = std::adjacent_find(op_string_build_vertex->begin(), op_string_build_vertex->end(), - [this](VertexPtr lhs, VertexPtr rhs) { - return is_constant_expression_in_this_loop(lhs) && is_constant_expression_in_this_loop(rhs); - }); - auto last_it = std::find_if_not(first_it, op_string_build_vertex->end(), - [this](VertexPtr vertex) { return is_constant_expression_in_this_loop(vertex); }); + auto first_it = std::adjacent_find(op_string_build_vertex->begin(), op_string_build_vertex->end(), [this](VertexPtr lhs, VertexPtr rhs) { + return is_constant_expression_in_this_loop(lhs) && is_constant_expression_in_this_loop(rhs); + }); + auto last_it = + std::find_if_not(first_it, op_string_build_vertex->end(), [this](VertexPtr vertex) { return is_constant_expression_in_this_loop(vertex); }); VertexRange constant_expressions_range{first_it, last_it}; if (!constant_expressions_range.empty()) { auto message = "string building " + join_string_build_elements(constant_expressions_range) + " can be saved in a separate variable out of loop"; @@ -335,8 +317,8 @@ void AnalyzePerformance::run_second_pass_on_loop_exit(VertexPtr vertex, uint64_t auto array_var = remove_conv_wrap(op_set_value_vertex->array()).try_as(); auto array_set_key = remove_conv_wrap(op_set_value_vertex->key()).try_as(); auto foreach_key = op_foreach_loop_exit->params()->key(); - if (array_var && !array_var->var_id->is_in_global_scope() && !reserved_arrays_.count(array_var->var_id) && - array_set_key && array_set_key->var_id == foreach_key->var_id) { + if (array_var && !array_var->var_id->is_in_global_scope() && !reserved_arrays_.count(array_var->var_id) && array_set_key && + array_set_key->var_id == foreach_key->var_id) { auto message = get_description_for_help(array_var) + " can be reserved with array_reserve functions family out of loop"; trigger_inspection_on_second_pass(op_set_value_vertex, PerformanceInspections::array_reserve, std::move(message)); enabled_inspections &= ~PerformanceInspections::array_reserve; @@ -363,9 +345,9 @@ void AnalyzePerformance::exit_loop(VertexPtr loop_vertex) noexcept { } const size_t loop_depth = loop_data_for_second_pass_.size(); kphp_assert(loop_depth); - const auto &exiting_loop = loop_data_for_second_pass_.back(); + const auto& exiting_loop = loop_data_for_second_pass_.back(); if (loop_depth > 1) { - const auto &loop_exit_modified_vars = exiting_loop.first_pass_modified_vars; + const auto& loop_exit_modified_vars = exiting_loop.first_pass_modified_vars; loop_data_for_second_pass_[loop_depth - 2].first_pass_modified_vars.insert(loop_exit_modified_vars.begin(), loop_exit_modified_vars.end()); loop_data_for_second_pass_[loop_depth - 2].has_return |= exiting_loop.has_return; } @@ -404,8 +386,7 @@ bool AnalyzePerformance::is_constant_expression_in_this_loop(VertexPtr vertex) c return is_var_can_be_optimized_in_loop(op_var_vertex) && !loop_data_for_second_pass_.back().first_pass_modified_vars.count(op_var_vertex->var_id); } if (auto op_index_vertex = vertex.try_as()) { - return op_index_vertex->has_key() && - is_constant_expression_in_this_loop(op_index_vertex->key()) && + return op_index_vertex->has_key() && is_constant_expression_in_this_loop(op_index_vertex->key()) && is_constant_expression_in_this_loop(op_index_vertex->array()); } if (auto op_func_call_vertex = vertex.try_as()) { @@ -422,8 +403,8 @@ bool AnalyzePerformance::is_constant_expression_in_this_loop(VertexPtr vertex) c void AnalyzePerformance::trigger_array_merge(VertexPtr first_arg) noexcept { auto first_arg_help = get_description_for_help_impl(first_arg); - auto message = "expression " + first_arg_help + " = array_merge(" + first_arg_help + ", <...>) " + - "can be replaced with array_merge_into(" + first_arg_help + ", <...>)"; + auto message = "expression " + first_arg_help + " = array_merge(" + first_arg_help + ", <...>) " + "can be replaced with array_merge_into(" + first_arg_help + + ", <...>)"; trigger_inspection(PerformanceInspections::array_merge_into, std::move(message)); } @@ -445,8 +426,7 @@ void AnalyzePerformance::trigger_inspection(PerformanceInspections::Inspections } } -void AnalyzePerformance::trigger_inspection_on_second_pass(VertexPtr inspected_vertex, - PerformanceInspections::Inspections inspection, +void AnalyzePerformance::trigger_inspection_on_second_pass(VertexPtr inspected_vertex, PerformanceInspections::Inspections inspection, std::string message) noexcept { const auto origin_location = stage::get_location(); stage::set_location(inspected_vertex->get_location()); @@ -460,45 +440,45 @@ bool AnalyzePerformance::check_function(FunctionPtr func) const { VertexPtr AnalyzePerformance::on_enter_vertex(VertexPtr vertex) { switch (vertex->type()) { - case op_func_call: - analyze_func_call(vertex.as()); - break; - case op_set: - analyze_set(vertex.as()); - break; - case op_set_value: - analyze_set_array_value(vertex.as()); - break; - case op_push_back: - case op_push_back_return: - analyze_array_insertion(vertex.as()); - break; - case op_array: - analyze_op_array(vertex.as()); - break; - case op_return: - analyze_op_return(vertex.as()); - break; - case op_while: - case op_do: - enter_loop(); - break; - case op_string_build: - case op_index: - save_to_second_pass_analyze_on_loop_exit(vertex); - break; - case op_var: - analyze_op_var(vertex.as()); - break; - case op_continue: - // TODO think about switch break - case op_break: - if (!loop_data_for_second_pass_.empty()) { - loop_data_for_second_pass_.back().has_break_or_continue = true; - } - break; - default: - break; + case op_func_call: + analyze_func_call(vertex.as()); + break; + case op_set: + analyze_set(vertex.as()); + break; + case op_set_value: + analyze_set_array_value(vertex.as()); + break; + case op_push_back: + case op_push_back_return: + analyze_array_insertion(vertex.as()); + break; + case op_array: + analyze_op_array(vertex.as()); + break; + case op_return: + analyze_op_return(vertex.as()); + break; + case op_while: + case op_do: + enter_loop(); + break; + case op_string_build: + case op_index: + save_to_second_pass_analyze_on_loop_exit(vertex); + break; + case op_var: + analyze_op_var(vertex.as()); + break; + case op_continue: + // TODO think about switch break + case op_break: + if (!loop_data_for_second_pass_.empty()) { + loop_data_for_second_pass_.back().has_break_or_continue = true; + } + break; + default: + break; } return vertex; } @@ -549,7 +529,7 @@ bool AnalyzePerformance::user_recursion(VertexPtr vertex) { enter_conditional(); run_function_pass(op_case_vertex->condition_on_switch_ref(), this); run_function_pass(op_case_vertex->matched_with_one_case_ref(), this); - for (auto &case_vertex : op_case_vertex->cases()) { + for (auto& case_vertex : op_case_vertex->cases()) { run_function_pass(case_vertex, this); } exit_conditional(); @@ -573,12 +553,12 @@ VertexPtr AnalyzePerformance::on_exit_vertex(VertexPtr vertex) { second_pass_saved_top_vertex_ = {}; } switch (vertex->type()) { - case op_while: - case op_do: - exit_loop(vertex); - break; - default: - break; + case op_while: + case op_do: + exit_loop(vertex); + break; + default: + break; } return vertex; } @@ -589,21 +569,15 @@ void AnalyzePerformance::on_finish() { } } -void PerformanceIssuesReport::add_issues_and_require_flush(FunctionPtr function, std::vector &&issues) noexcept { +void PerformanceIssuesReport::add_issues_and_require_flush(FunctionPtr function, std::vector&& issues) noexcept { is_flush_required_ = true; if (issues.empty()) { return; } - FunctionPerformanceIssues function_issues{ - function->file_id->relative_file_name, - prepare_for_json(function->as_human_readable(false)), - std::move(issues) - }; - std::sort(function_issues.issues.begin(), function_issues.issues.end(), - [](const AnalyzePerformance::Issue &lhs, const AnalyzePerformance::Issue &rhs) { - return std::tie(lhs.line, lhs.inspection, lhs.description) < - std::tie(rhs.line, rhs.inspection, rhs.description); - }); + FunctionPerformanceIssues function_issues{function->file_id->relative_file_name, prepare_for_json(function->as_human_readable(false)), std::move(issues)}; + std::sort(function_issues.issues.begin(), function_issues.issues.end(), [](const AnalyzePerformance::Issue& lhs, const AnalyzePerformance::Issue& rhs) { + return std::tie(lhs.line, lhs.inspection, lhs.description) < std::tie(rhs.line, rhs.inspection, rhs.description); + }); std::lock_guard lock{mutex_}; report_.emplace_back(std::move(function_issues)); } @@ -612,7 +586,7 @@ bool PerformanceIssuesReport::is_flush_required() const noexcept { return is_flush_required_; } -void PerformanceIssuesReport::flush_to(FILE *out) noexcept { +void PerformanceIssuesReport::flush_to(FILE* out) noexcept { struct IssueDetail { std::string file_name; std::string function_name; @@ -622,11 +596,11 @@ void PerformanceIssuesReport::flush_to(FILE *out) noexcept { return std::tie(file_name, issue.line, function_name, issue.inspection, issue.description); } - bool operator<(const IssueDetail &rhs) const noexcept { + bool operator<(const IssueDetail& rhs) const noexcept { return to_tuple() < rhs.to_tuple(); } - bool operator==(const IssueDetail &rhs) const noexcept { + bool operator==(const IssueDetail& rhs) const noexcept { return to_tuple() == rhs.to_tuple(); } }; @@ -634,8 +608,8 @@ void PerformanceIssuesReport::flush_to(FILE *out) noexcept { std::vector full_report; { std::lock_guard lock{mutex_}; - for (FunctionPerformanceIssues &fun_issues : report_) { - for (AnalyzePerformance::Issue &issue : fun_issues.issues) { + for (FunctionPerformanceIssues& fun_issues : report_) { + for (AnalyzePerformance::Issue& issue : fun_issues.issues) { full_report.emplace_back(IssueDetail{fun_issues.file_name, fun_issues.function_name, std::move(issue)}); } } @@ -644,11 +618,10 @@ void PerformanceIssuesReport::flush_to(FILE *out) noexcept { vk::sort_and_unique(full_report); fprintf(out, "["); - const char *line_begin = "\n"; - for (const auto &record : full_report) { - fmt_fprintf(out, R"json({}{{"location": "{}:{}", "function": "{}", "inspection": "{}", "description": "{}"}})json", - line_begin, record.file_name, record.issue.line, record.function_name, - PerformanceInspections::inspection2string(record.issue.inspection), record.issue.description); + const char* line_begin = "\n"; + for (const auto& record : full_report) { + fmt_fprintf(out, R"json({}{{"location": "{}:{}", "function": "{}", "inspection": "{}", "description": "{}"}})json", line_begin, record.file_name, + record.issue.line, record.function_name, PerformanceInspections::inspection2string(record.issue.inspection), record.issue.description); line_begin = ",\n"; } fprintf(out, "\n]\n"); diff --git a/compiler/pipes/analyze-performance.h b/compiler/pipes/analyze-performance.h index e032a3533b..28835da44b 100644 --- a/compiler/pipes/analyze-performance.h +++ b/compiler/pipes/analyze-performance.h @@ -8,7 +8,6 @@ #include "compiler/function-pass.h" - class AnalyzePerformance final : public FunctionPassBase { public: std::string get_description() final { @@ -26,6 +25,7 @@ class AnalyzePerformance final : public FunctionPassBase { PerformanceInspections::Inspections inspection; std::string description; }; + private: void analyze_func_call(VertexAdaptor op_func_call_vertex) noexcept; void analyze_set(VertexAdaptor op_set_vertex) noexcept; @@ -36,7 +36,7 @@ class AnalyzePerformance final : public FunctionPassBase { void analyze_op_return(VertexAdaptor op_return_vertex) noexcept; void analyze_op_var(VertexAdaptor op_var_vertex) noexcept; - void check_implicit_array_conversion(VertexPtr expr, const TypeData *to) noexcept; + void check_implicit_array_conversion(VertexPtr expr, const TypeData* to) noexcept; void save_to_second_pass_analyze_on_loop_exit(VertexPtr vertex) noexcept; void run_second_pass_on_loop_exit(VertexPtr vertex, uint64_t enabled_inspections, VertexPtr loop_vertex) noexcept; @@ -80,10 +80,10 @@ class PerformanceIssuesReport : vk::not_copyable { public: friend class vk::singleton; - void add_issues_and_require_flush(FunctionPtr function, std::vector &&issues) noexcept; + void add_issues_and_require_flush(FunctionPtr function, std::vector&& issues) noexcept; bool is_flush_required() const noexcept; - void flush_to(FILE *out) noexcept; + void flush_to(FILE* out) noexcept; private: PerformanceIssuesReport() = default; diff --git a/compiler/pipes/analyzer.cpp b/compiler/pipes/analyzer.cpp index 11b60338a0..0adc108426 100644 --- a/compiler/pipes/analyzer.cpp +++ b/compiler/pipes/analyzer.cpp @@ -51,21 +51,21 @@ std::set collect_duplicate_keys(VertexPtr to_check) { return duplicates; } -void check_var_init_value(const VarPtr &var) { +void check_var_init_value(const VarPtr& var) { if (auto var_init_const = var->init_val.try_as()) { if (auto const_array = var_init_const->var_id->init_val.try_as()) { auto duplications = collect_duplicate_keys(const_array); if (!duplications.empty()) { - const char *static_prefix = (var->is_function_static_var() || var->is_class_static_var()) ? "static " : ""; + const char* static_prefix = (var->is_function_static_var() || var->is_class_static_var()) ? "static " : ""; stage::set_location(const_array->get_location()); - kphp_warning(fmt_format("Got array duplicate keys ['{}'] in '{}{}' init value", - vk::join(duplications, "', '"), static_prefix, var->as_human_readable())); + kphp_warning( + fmt_format("Got array duplicate keys ['{}'] in '{}{}' init value", vk::join(duplications, "', '"), static_prefix, var->as_human_readable())); } } } } -} +} // namespace void CommonAnalyzerPass::check_set(VertexAdaptor to_check) { VertexPtr left = to_check->lhs(); @@ -74,7 +74,7 @@ void CommonAnalyzerPass::check_set(VertexAdaptor to_check) { VarPtr lvar = left.as()->var_id; VarPtr rvar = right.as()->var_id; if (lvar->name == rvar->name) { - kphp_warning ("Assigning variable to itself\n"); + kphp_warning("Assigning variable to itself\n"); } } } @@ -108,26 +108,26 @@ VertexPtr CommonAnalyzerPass::on_enter_vertex(VertexPtr vertex) { } } if (vertex->type() == op_set) { - //TODO: $x = (int)$x; - //check_set(vertex.as()); + // TODO: $x = (int)$x; + // check_set(vertex.as()); return vertex; } return vertex; } void CommonAnalyzerPass::on_finish() { - for (VarPtr &var : current_function->local_var_ids) { + for (VarPtr& var : current_function->local_var_ids) { G->stats.cnt_mixed_vars += tinf::get_type(var)->ptype() == tp_mixed; } - for (VarPtr &var : current_function->param_ids) { + for (VarPtr& var : current_function->param_ids) { G->stats.cnt_mixed_params += tinf::get_type(var)->ptype() == tp_mixed; G->stats.cnt_const_mixed_params += (tinf::get_type(var)->ptype() == tp_mixed) && var->is_read_only; } if (current_function->type == FunctionData::func_class_holder) { - current_function->class_id->members.for_each([](ClassMemberStaticField &field) { check_var_init_value(field.var); }); - current_function->class_id->members.for_each([](ClassMemberInstanceField &field) { check_var_init_value(field.var); }); + current_function->class_id->members.for_each([](ClassMemberStaticField& field) { check_var_init_value(field.var); }); + current_function->class_id->members.for_each([](ClassMemberInstanceField& field) { check_var_init_value(field.var); }); } std::for_each(current_function->static_var_ids.begin(), current_function->static_var_ids.end(), check_var_init_value); diff --git a/compiler/pipes/analyzer.h b/compiler/pipes/analyzer.h index c0cb7f0773..5ceedea144 100644 --- a/compiler/pipes/analyzer.h +++ b/compiler/pipes/analyzer.h @@ -4,14 +4,12 @@ #pragma once - #include "compiler/function-pass.h" class CommonAnalyzerPass final : public FunctionPassBase { void check_set(VertexAdaptor to_check); public: - std::string get_description() override { return "Try to detect common errors"; } @@ -20,7 +18,6 @@ class CommonAnalyzerPass final : public FunctionPassBase { return !function->is_extern(); } - VertexPtr on_enter_vertex(VertexPtr vertex) override; void on_finish() override; diff --git a/compiler/pipes/array-access-transform.cpp b/compiler/pipes/array-access-transform.cpp index 03410a7fc6..4a1bb10c7c 100644 --- a/compiler/pipes/array-access-transform.cpp +++ b/compiler/pipes/array-access-transform.cpp @@ -64,7 +64,7 @@ std::pair fixup_check_function(VertexPtr cur, VertexPtr prev, F auto klass = func_call->func_id->class_id; kphp_assert_msg(klass, "Internal error: cannot get type of object for [] access"); - const auto *isset_method = klass->get_instance_method("offsetExists"); + const auto* isset_method = klass->get_instance_method("offsetExists"); kphp_error(isset_method, fmt_format("Class {} does not implement \\ArrayAccess", klass->name).c_str()); if (prev->type() == op_index) { @@ -91,8 +91,8 @@ std::pair fixup_check_function(VertexPtr cur, VertexPtr prev, F exists_call->str_val = isset_method->global_name(); exists_call->func_id = isset_method->function; - auto as_or = - VertexAdaptor::create(VertexAdaptor::create(exists_call), VertexAdaptor::create(cur, VertexAdaptor::create())); + auto as_or = VertexAdaptor::create(VertexAdaptor::create(exists_call), + VertexAdaptor::create(cur, VertexAdaptor::create())); as_or.set_location_recursively(cur); return {as_or, true}; @@ -139,7 +139,7 @@ VertexPtr on_log_not(VertexAdaptor log_not_op) { } if (has_index) { - const auto *tpe = tinf::get_type(v); + const auto* tpe = tinf::get_type(v); if (tpe->ptype() == tp_mixed || (tpe->ptype() == tp_Class && G->get_class("ArrayAccess")->is_parent_of(tpe->class_type()))) { return VertexAdaptor::create(isset->front(), VertexAdaptor::create()); } @@ -157,7 +157,7 @@ VertexPtr on_unset(VertexAdaptor unset) { auto klass = func_call->func_id->class_id; kphp_assert_msg(klass, "Internal error: cannot get type of object for [] access"); - const auto *unset_method = klass->get_instance_method("offsetUnset"); + const auto* unset_method = klass->get_instance_method("offsetUnset"); kphp_error(unset_method, fmt_format("Class {} does not implement \\ArrayAccess", klass->name).c_str()); func_call->str_val = unset_method->global_name(); diff --git a/compiler/pipes/calc-actual-edges.cpp b/compiler/pipes/calc-actual-edges.cpp index bed49a1119..57bc254edd 100644 --- a/compiler/pipes/calc-actual-edges.cpp +++ b/compiler/pipes/calc-actual-edges.cpp @@ -5,18 +5,18 @@ #include "compiler/pipes/calc-actual-edges.h" #include "compiler/compiler-core.h" -#include "compiler/inferring/public.h" #include "compiler/data/class-data.h" #include "compiler/function-pass.h" +#include "compiler/inferring/public.h" // handle_exception reports whether a thrown_class will be caught by any of the given try blocks; // try_stack should contain the innermost try block in its end. // // This function will mark try blocks that failed to handle the exception with catches_all=false. -bool CalcActualCallsEdgesPass::handle_exception(std::vector> &try_stack, ClassPtr thrown_class) { +bool CalcActualCallsEdgesPass::handle_exception(std::vector>& try_stack, ClassPtr thrown_class) { // walk from the innermost try statement for (auto i = try_stack.rbegin(); i != try_stack.rend(); ++i) { - auto &try_op = *i; + auto& try_op = *i; for (auto c : try_op->catch_list()) { if (c.as()->exception_class->is_parent_of(thrown_class)) { return true; diff --git a/compiler/pipes/calc-actual-edges.h b/compiler/pipes/calc-actual-edges.h index 5f2b3d04cb..2b45f40c44 100644 --- a/compiler/pipes/calc-actual-edges.h +++ b/compiler/pipes/calc-actual-edges.h @@ -39,11 +39,10 @@ class CalcActualCallsEdgesPass final : public FunctionPassBase { bool inside_fork; bool can_throw = true; // always `true` for now - EdgeInfo(const FunctionPtr &called_f, std::vector> try_stack, bool inside_fork) : - called_f(called_f), - try_stack(std::move(try_stack)), - inside_fork(inside_fork) - {} + EdgeInfo(const FunctionPtr& called_f, std::vector> try_stack, bool inside_fork) + : called_f(called_f), + try_stack(std::move(try_stack)), + inside_fork(inside_fork) {} }; private: @@ -52,7 +51,7 @@ class CalcActualCallsEdgesPass final : public FunctionPassBase { int inside_fork = 0; public: - static bool handle_exception(std::vector> &try_stack, ClassPtr thrown_class); + static bool handle_exception(std::vector>& try_stack, ClassPtr thrown_class); std::string get_description() override { return "Collect actual calls edges"; @@ -66,5 +65,3 @@ class CalcActualCallsEdgesPass final : public FunctionPassBase { return std::move(edges); } }; - - diff --git a/compiler/pipes/calc-bad-vars.cpp b/compiler/pipes/calc-bad-vars.cpp index 1337d3d3ee..3ba1c68451 100644 --- a/compiler/pipes/calc-bad-vars.cpp +++ b/compiler/pipes/calc-bad-vars.cpp @@ -25,7 +25,7 @@ template class MergeReachalbeCallback { public: - virtual void for_component(const std::vector &component, const std::vector &edges) = 0; + virtual void for_component(const std::vector& component, const std::vector& edges) = 0; virtual ~MergeReachalbeCallback() {} }; @@ -35,19 +35,19 @@ class MergeReachalbe { private: using GraphT = IdMap>; - void dfs(const VertexT &vertex, const GraphT &graph, IdMap *was, std::vector *topsorted) { + void dfs(const VertexT& vertex, const GraphT& graph, IdMap* was, std::vector* topsorted) { if ((*was)[vertex]) { return; } (*was)[vertex] = 1; - for (const auto &next_vertex : graph[vertex]) { + for (const auto& next_vertex : graph[vertex]) { dfs(next_vertex, graph, was, topsorted); } topsorted->push_back(vertex); } - void dfs_component(VertexT vertex, const GraphT &graph, int color, IdMap *was, - std::vector *was_color, std::vector *component, std::vector *edges) { + void dfs_component(VertexT vertex, const GraphT& graph, int color, IdMap* was, std::vector* was_color, std::vector* component, + std::vector* edges) { int other_color = (*was)[vertex]; if (other_color == color) { return; @@ -61,19 +61,18 @@ class MergeReachalbe { } (*was)[vertex] = color; component->push_back(vertex); - for (const auto &next_vertex : graph[vertex]) { + for (const auto& next_vertex : graph[vertex]) { dfs_component(next_vertex, graph, color, was, was_color, component, edges); } } public: - void run(const GraphT &graph, const GraphT &rev_graph, const std::vector &vertices, - MergeReachalbeCallback *callback) { + void run(const GraphT& graph, const GraphT& rev_graph, const std::vector& vertices, MergeReachalbeCallback* callback) { int vertex_n = (int)vertices.size(); IdMap was(vertex_n); std::vector topsorted; topsorted.reserve(vertex_n); - for (const auto &vertex : vertices) { + for (const auto& vertex : vertices) { dfs(vertex, rev_graph, &was, &topsorted); } @@ -81,14 +80,13 @@ class MergeReachalbe { std::vector was_color(vertex_n + 1, 0); int current_color = 0; for (auto vertex_it = topsorted.rbegin(); vertex_it != topsorted.rend(); ++vertex_it) { - auto &vertex = *vertex_it; + auto& vertex = *vertex_it; if (was[vertex]) { continue; } std::vector component; std::vector edges; - dfs_component(vertex, graph, ++current_color, &was, - &was_color, &component, &edges); + dfs_component(vertex, graph, ++current_color, &was, &was_color, &component, &edges); callback->for_component(component, edges); } @@ -102,11 +100,11 @@ struct FuncCallGraph { IdMap> rev_graph; std::vector>> temporarily_removed; - FuncCallGraph(std::vector other_functions, std::vector &dep_datas) : - n((int)other_functions.size()), - functions(std::move(other_functions)), - graph(n), - rev_graph(n) { + FuncCallGraph(std::vector other_functions, std::vector& dep_datas) + : n((int)other_functions.size()), + functions(std::move(other_functions)), + graph(n), + rev_graph(n) { for (int cur_id = 0, i = 0; i < n; i++, cur_id++) { set_index(functions[i], cur_id); @@ -114,9 +112,9 @@ struct FuncCallGraph { for (int i = 0; i < n; i++) { FunctionPtr to = functions[i]; - DepData &data = dep_datas[i]; + DepData& data = dep_datas[i]; - for (const auto &from : data.dep) { + for (const auto& from : data.dep) { rev_graph[from].push_back(to); } graph[to] = std::move(data.dep); @@ -128,24 +126,24 @@ struct FuncCallGraph { graph[caller].erase(std::find(graph[caller].begin(), graph[caller].end(), to_remove)); } temporarily_removed.emplace_back(to_remove, std::move(rev_graph[to_remove])); - }; + } void restore_all_removed() { - for (auto &pair : temporarily_removed) { + for (auto& pair : temporarily_removed) { for (FunctionPtr caller : pair.second) { graph[caller].emplace_back(pair.first); } rev_graph[pair.first] = std::move(pair.second); } temporarily_removed.clear(); - }; + } }; class CallstackOfColoredFunctions { - std::vector stack; // functions placed in order, only colored functions - std::vector colors_chain; // blended colors of stacked functions, one-by-one - std::unordered_set index_set; // a quick index for contains(), has the same elements as stack - function_palette::colors_mask_t colors_mask{0}; // mask of all colors_chain + std::vector stack; // functions placed in order, only colored functions + std::vector colors_chain; // blended colors of stacked functions, one-by-one + std::unordered_set index_set; // a quick index for contains(), has the same elements as stack + function_palette::colors_mask_t colors_mask{0}; // mask of all colors_chain void recalc_mask() { colors_mask = 0; @@ -164,11 +162,11 @@ class CallstackOfColoredFunctions { return stack.size(); } - const std::vector &as_vector() const { + const std::vector& as_vector() const { return stack; } - const std::vector &get_colors_chain() const { + const std::vector& get_colors_chain() const { return colors_chain; } @@ -176,10 +174,10 @@ class CallstackOfColoredFunctions { return colors_mask; } - void push_back(const FunctionPtr &el) { + void push_back(const FunctionPtr& el) { stack.push_back(el); index_set.insert(el); - for (const auto &sep_color : el->colors) { + for (const auto& sep_color : el->colors) { colors_chain.push_back(sep_color); } recalc_mask(); @@ -189,13 +187,13 @@ class CallstackOfColoredFunctions { FunctionPtr pop = stack.back(); index_set.erase(pop); stack.pop_back(); - for (const auto &sep_color __attribute__((unused)) : pop->colors) { + for (const auto& sep_color __attribute__((unused)) : pop->colors) { colors_chain.pop_back(); } recalc_mask(); } - bool contains(const FunctionPtr &el) const { + bool contains(const FunctionPtr& el) const { return index_set.find(el) != index_set.end(); } }; @@ -206,22 +204,22 @@ class CallstackOfColoredFunctions { class CheckFunctionsColors { static constexpr int max_shown_errors_count = 10; - const FuncCallGraph &call_graph; - const function_palette::Palette &palette; - std::unordered_set shown_errors; // the easiest way to avoid duplicated errors + const FuncCallGraph& call_graph; + const function_palette::Palette& palette; + std::unordered_set shown_errors; // the easiest way to avoid duplicated errors public: - explicit CheckFunctionsColors(const FuncCallGraph &call_graph) - : call_graph(call_graph) - , palette(G->get_function_palette()) {} + explicit CheckFunctionsColors(const FuncCallGraph& call_graph) + : call_graph(call_graph), + palette(G->get_function_palette()) {} - void check_func_dfs(CallstackOfColoredFunctions &callstack, const FunctionPtr &func) { + void check_func_dfs(CallstackOfColoredFunctions& callstack, const FunctionPtr& func) { callstack.push_back(func); bool was_any_error = false; - for (const auto &ruleset : palette.get_rulesets()) { - for (auto it = ruleset.rbegin(); it != ruleset.rend(); ++it) { // reverse is important - const function_palette::PaletteRule &rule = *it; + for (const auto& ruleset : palette.get_rulesets()) { + for (auto it = ruleset.rbegin(); it != ruleset.rend(); ++it) { // reverse is important + const function_palette::PaletteRule& rule = *it; if (!match_rule(callstack, rule)) { continue; } @@ -244,7 +242,7 @@ class CheckFunctionsColors { callstack.pop_back(); } - static bool match_rule(const CallstackOfColoredFunctions &callstack, const function_palette::PaletteRule &rule) { + static bool match_rule(const CallstackOfColoredFunctions& callstack, const function_palette::PaletteRule& rule) { const auto match_mask = callstack.get_colors_mask(); if (match_mask == 0 || !rule.contains_in(match_mask)) { return false; @@ -253,7 +251,7 @@ class CheckFunctionsColors { return match_two_vectors(rule.colors, callstack.get_colors_chain()); } - static bool match_two_vectors(const std::vector &rule_chain, const std::vector &actual_chain) { + static bool match_two_vectors(const std::vector& rule_chain, const std::vector& actual_chain) { auto rule_it = rule_chain.end() - 1; auto actual_it = actual_chain.end() - 1; @@ -281,7 +279,8 @@ class CheckFunctionsColors { // on error (colored chain breaks some rule), we want to find an actual chain of calling // this is launched only on error, that's why we don't care about performance and just use bfs // todo think about using such approach for fork chains, throws chains, etc (and drop fork_prev, wait_prev, throws_reason from FunctionData) - std::vector find_callstack_between_two_functions_bfs(FunctionPtr from, FunctionPtr target, const std::unordered_set &shouldnt_appear) { + std::vector find_callstack_between_two_functions_bfs(FunctionPtr from, FunctionPtr target, + const std::unordered_set& shouldnt_appear) { std::unordered_map visited_level; std::queue bfs_queue; @@ -304,7 +303,7 @@ class CheckFunctionsColors { } } - if (visited_level.find(target) == visited_level.end()) { // couldn't find, just return [from, target] + if (visited_level.find(target) == visited_level.end()) { // couldn't find, just return [from, target] return {from, target}; } @@ -327,16 +326,16 @@ class CheckFunctionsColors { return callstack; } - void show_error_on_rule_broken(const CallstackOfColoredFunctions &color_callstack, const function_palette::PaletteRule &rule) { + void show_error_on_rule_broken(const CallstackOfColoredFunctions& color_callstack, const function_palette::PaletteRule& rule) { kphp_assert(rule.is_error()); if (shown_errors.size() > max_shown_errors_count) { return; } - auto vector = color_callstack.as_vector(); // f1, f2, f3 — all of them are colored, and their chain breaks the rule - std::vector full_callstack; // will be: src_main -> ... -> f1 -> ... -> f2 -> ... -> f3 + auto vector = color_callstack.as_vector(); // f1, f2, f3 — all of them are colored, and their chain breaks the rule + std::vector full_callstack; // will be: src_main -> ... -> f1 -> ... -> f2 -> ... -> f3 for (int i = 0; i < vector.size() - 1; ++i) { - FunctionPtr cur = vector[i], next = vector[i+1]; + FunctionPtr cur = vector[i], next = vector[i + 1]; std::unordered_set shouldnt_appear; kphp_assert(cur->next_with_colors); for (FunctionPtr exclude : *cur->next_with_colors) { @@ -369,38 +368,37 @@ class CheckFunctionsColors { }); stage::set_location((*first_item_to_show)->root->location); - kphp_error(!shown_errors.insert(callstack_str).second, - fmt_format("{} => {}\n This color rule is broken, call chain:\n{}", - TermStringFormat::paint(rule.as_human_readable(palette), TermStringFormat::cyan), - TermStringFormat::paint_red(rule.error), - callstack_str)); + kphp_error(!shown_errors.insert(callstack_str).second, fmt_format("{} => {}\n This color rule is broken, call chain:\n{}", + TermStringFormat::paint(rule.as_human_readable(palette), TermStringFormat::cyan), + TermStringFormat::paint_red(rule.error), callstack_str)); } }; class CalcBadVars { class MergeBadVarsCallback : public MergeReachalbeCallback { IdMap> modified_global_vars; + public: - explicit MergeBadVarsCallback(IdMap> &&modified_global_vars) : - modified_global_vars(std::move(modified_global_vars)) {} + explicit MergeBadVarsCallback(IdMap>&& modified_global_vars) + : modified_global_vars(std::move(modified_global_vars)) {} // here we calculate "bad vars" for a function — they will be used in check-ub.cpp // "bad vars" are modified non-primitive globals, that can lead to a potential ub when modified and accessed in subcalls // this method just unions all edges' bad_vars to the current function // this works in a single thread and uses some heuristic for speedup, but generally it means // "for f in component { for e in edge { f.bad_vars += e.bad_vars } }" - void for_component(const std::vector &component, const std::vector &edges) override { + void for_component(const std::vector& component, const std::vector& edges) override { // optimization 1: lots of functions don't modify globals at all // then we leave f->bad_vars nullptr - bool empty = vk::all_of(component, [&](FunctionPtr f) { return modified_global_vars[f].empty(); }) - && vk::all_of(edges, [&](FunctionPtr e) { return e->bad_vars == nullptr; }); + bool empty = vk::all_of(component, [&](FunctionPtr f) { return modified_global_vars[f].empty(); }) && + vk::all_of(edges, [&](FunctionPtr e) { return e->bad_vars == nullptr; }); if (empty) { return; } // optimization 2: maybe, one of the edges has bad_vars that includes all other edges // then we just assign f->bad_vars = largest_edge->bad_vars - std::unordered_set *largest_e{nullptr}; + std::unordered_set* largest_e{nullptr}; for (FunctionPtr e : edges) { if (e->bad_vars != nullptr && (!largest_e || e->bad_vars->size() > largest_e->size())) { largest_e = e->bad_vars; @@ -408,14 +406,11 @@ class CalcBadVars { } if (largest_e) { bool all_in_largest_e = vk::all_of(component, [&](FunctionPtr f) { - return vk::all_of(modified_global_vars[f], [&](VarPtr v_in_self) { - return largest_e->find(v_in_self) != largest_e->end(); - }); + return vk::all_of(modified_global_vars[f], [&](VarPtr v_in_self) { return largest_e->find(v_in_self) != largest_e->end(); }); }); all_in_largest_e &= vk::all_of(edges, [&](FunctionPtr e) { - return e->bad_vars == nullptr || e->bad_vars == largest_e || vk::all_of(*e->bad_vars, [&](VarPtr v_in_e) { - return largest_e->find(v_in_e) != largest_e->end(); - }); + return e->bad_vars == nullptr || e->bad_vars == largest_e || + vk::all_of(*e->bad_vars, [&](VarPtr v_in_e) { return largest_e->find(v_in_e) != largest_e->end(); }); }); if (all_in_largest_e) { for (FunctionPtr f : component) { @@ -427,7 +422,7 @@ class CalcBadVars { // if not, allocate and fill the set which unites all edges // optimization 3: start from largest_e and unite all others into result - auto *bad_vars = largest_e ? new std::unordered_set(*largest_e) : new std::unordered_set(); + auto* bad_vars = largest_e ? new std::unordered_set(*largest_e) : new std::unordered_set(); for (FunctionPtr f : component) { bad_vars->insert(modified_global_vars[f].begin(), modified_global_vars[f].end()); @@ -450,13 +445,13 @@ class CalcBadVars { // here we calculate next_with_colors for every function // we'll use it for perform dfs only for colored nodes of a call graph // (this precalculation is needed, because dfs for a whole call graph is too heavy on a large code base) - void for_component(const std::vector &component, const std::vector &edges) override { + void for_component(const std::vector& component, const std::vector& edges) override { // (this can be optimized if many functions are marked with colors, for now left simple to me more understandable) std::unordered_set next_colored_uniq; // if an edge is colored, append this edge // if not, append next_with_colors from this edge - for (FunctionPtr f: edges) { + for (FunctionPtr f : edges) { if (!f->colors.empty()) { next_colored_uniq.insert(f); } else if (f->next_with_colors != nullptr) { @@ -482,7 +477,7 @@ class CalcBadVars { } if (!next_colored_uniq.empty()) { - auto *next_with_colors = new std::vector(next_colored_uniq.begin(), next_colored_uniq.end()); + auto* next_with_colors = new std::vector(next_colored_uniq.begin(), next_colored_uniq.end()); for (FunctionPtr f : component) { f->next_with_colors = next_with_colors; } @@ -490,7 +485,7 @@ class CalcBadVars { } }; - void generate_bad_vars(const FuncCallGraph &call_graph, std::vector &dep_datas) { + void generate_bad_vars(const FuncCallGraph& call_graph, std::vector& dep_datas) { IdMap> modified_global_vars(call_graph.n); for (int i = 0; i < call_graph.n; i++) { @@ -503,7 +498,7 @@ class CalcBadVars { merge_bad_vars.run(call_graph.graph, call_graph.rev_graph, call_graph.functions, &callback); } - void check_func_colors(FuncCallGraph &call_graph) { + void check_func_colors(FuncCallGraph& call_graph) { // to perform calculating next_with_colors and checking color rules from the palette, // we need to drop '@kphp-color remover' functions from a call graph completely, like they don't exist at all // this special color is for manual cutting connectivity rules, allowing to explicitly separate recursively-joint components @@ -521,14 +516,14 @@ class CalcBadVars { call_graph.restore_all_removed(); } - static void mark(const IdMap> &graph, IdMap &was, FunctionPtr start, IdMap &parents) { + static void mark(const IdMap>& graph, IdMap& was, FunctionPtr start, IdMap& parents) { was[start] = 1; std::queue q; q.push(start); while (!q.empty()) { auto vertex = q.front(); q.pop(); - for (const auto &next : graph[vertex]) { + for (const auto& next : graph[vertex]) { if (!was[next]) { parents[next] = vertex; was[next] = true; @@ -538,17 +533,17 @@ class CalcBadVars { } } - static void calc_interruptible(const FuncCallGraph &call_graph) { + static void calc_interruptible(const FuncCallGraph& call_graph) { IdMap into_interruptible(call_graph.n); IdMap to_parents(call_graph.n); - for (const auto &func : call_graph.functions) { + for (const auto& func : call_graph.functions) { if (func->is_interruptible) { mark(call_graph.rev_graph, into_interruptible, func, to_parents); } } - for (const auto &func : call_graph.functions) { + for (const auto& func : call_graph.functions) { if (into_interruptible[func]) { func->is_interruptible = true; if (unlikely(func->class_id && func->class_id == G->get_class("ArrayAccess"))) { @@ -574,9 +569,9 @@ class CalcBadVars { } } - static void calc_resumable(const FuncCallGraph &call_graph, const std::vector &dep_data) { + static void calc_resumable(const FuncCallGraph& call_graph, const std::vector& dep_data) { for (int i = 0; i < call_graph.n; i++) { - for (const auto &fork : dep_data[i].forks) { + for (const auto& fork : dep_data[i].forks) { fork->is_resumable = true; } } @@ -584,13 +579,13 @@ class CalcBadVars { IdMap into_resumable(call_graph.n); IdMap from_parents(call_graph.n); IdMap to_parents(call_graph.n); - for (const auto &func : call_graph.functions) { + for (const auto& func : call_graph.functions) { if (func->is_resumable) { mark(call_graph.graph, from_resumable, func, from_parents); mark(call_graph.rev_graph, into_resumable, func, to_parents); } } - for (const auto &func : call_graph.functions) { + for (const auto& func : call_graph.functions) { func->can_be_implicitly_interrupted_by_other_resumable = into_resumable[func]; if (from_resumable[func] && into_resumable[func]) { func->is_resumable = true; @@ -599,7 +594,7 @@ class CalcBadVars { } } - for (const auto &func : call_graph.functions) { + for (const auto& func : call_graph.functions) { if (func->class_id && func->class_id == G->get_class("ArrayAccess") && func->can_be_implicitly_interrupted_by_other_resumable) { kphp_error(false, fmt_format("Function [{}] is a method of ArrayAccess, it cannot call resumable functions\n" "Function transitively calls the resumable function along the following chain:\n{}\n", @@ -607,8 +602,9 @@ class CalcBadVars { } if (func->is_resumable) { if (func->should_be_sync) { - kphp_error (0, fmt_format("Function [{}] marked with @kphp-sync, but turn up to be resumable\n" - "Function is resumable because of calls chain:\n{}\n", func->name, func->get_resumable_path())); + kphp_error(0, fmt_format("Function [{}] marked with @kphp-sync, but turn up to be resumable\n" + "Function is resumable because of calls chain:\n{}\n", + func->name, func->get_resumable_path())); } if (func->is_inline) { func->is_inline = false; @@ -616,11 +612,11 @@ class CalcBadVars { } } if (G->settings().print_resumable_graph.get()) { - for (const auto &func : call_graph.functions) { + for (const auto& func : call_graph.functions) { if (!func->is_resumable) { continue; } - for (const auto &next : call_graph.graph[func]) { + for (const auto& next : call_graph.graph[func]) { if (!next->is_resumable) { continue; } @@ -630,7 +626,7 @@ class CalcBadVars { } } - void save_func_dep(const FuncCallGraph &call_graph) { + void save_func_dep(const FuncCallGraph& call_graph) { for (int i = 0; i < call_graph.n; i++) { FunctionPtr function = call_graph.functions[i]; function->dep = std::move(call_graph.graph[function]); @@ -640,7 +636,7 @@ class CalcBadVars { return; } - auto &main_dep = G->get_main_file()->main_function->dep; + auto& main_dep = G->get_main_file()->main_function->dep; for (int i = 0; i < call_graph.n; i++) { FunctionPtr fun = call_graph.functions[i]; if (fun->kphp_lib_export) { @@ -650,7 +646,7 @@ class CalcBadVars { my_unique(&main_dep); } - static std::string get_call_path(FunctionPtr func, const IdMap &to_parents) { + static std::string get_call_path(FunctionPtr func, const IdMap& to_parents) { kphp_assert_msg(func, "Unexpected null FunctionPtr in getting call-chain"); std::vector names; names.push_back(TermStringFormat::paint(func->as_human_readable(), TermStringFormat::red)); @@ -661,22 +657,22 @@ class CalcBadVars { func = to_parents[func]; } return vk::join(names, " -> "); - }; + } class MergeRefVarsCallback : public MergeReachalbeCallback { private: - const IdMap> &to_merge_; + const IdMap>& to_merge_; + public: - explicit MergeRefVarsCallback(const IdMap> &to_merge) : - to_merge_(to_merge) { - } + explicit MergeRefVarsCallback(const IdMap>& to_merge) + : to_merge_(to_merge) {} - void for_component(const std::vector &component, const std::vector &edges) { - auto *res = new std::unordered_set(); - for (const auto &var : component) { + void for_component(const std::vector& component, const std::vector& edges) { + auto* res = new std::unordered_set(); + for (const auto& var : component) { res->insert(to_merge_[var].begin(), to_merge_[var].end()); } - for (const auto &var : edges) { + for (const auto& var : edges) { if (var->bad_vars != nullptr) { res->insert(var->bad_vars->begin(), var->bad_vars->end()); } @@ -685,15 +681,15 @@ class CalcBadVars { delete res; return; } - for (const auto &var : component) { + for (const auto& var : component) { var->bad_vars = res; } } }; - void generate_ref_vars(const std::vector &dep_datas) { + void generate_ref_vars(const std::vector& dep_datas) { std::vector vars; - for (const auto &data : dep_datas) { + for (const auto& data : dep_datas) { vars.insert(vars.end(), data.ref_param_vars.begin(), data.ref_param_vars.end()); } int vars_n = static_cast(vars.size()); @@ -702,11 +698,11 @@ class CalcBadVars { } IdMap> rev_graph(vars_n), graph(vars_n), ref_vars(vars_n); - for (const auto &data : dep_datas) { - for (const auto &edge : data.global_ref_edges) { + for (const auto& data : dep_datas) { + for (const auto& edge : data.global_ref_edges) { ref_vars[edge.second].push_back(edge.first); } - for (const auto &edge : data.ref_ref_edges) { + for (const auto& edge : data.ref_ref_edges) { graph[edge.second].push_back(edge.first); rev_graph[edge.first].push_back(edge.second); } @@ -718,7 +714,7 @@ class CalcBadVars { } public: - void run(std::vector> &tmp_vec) { + void run(std::vector>& tmp_vec) { int all_n = (int)tmp_vec.size(); std::vector functions(all_n); std::vector dep_datas(all_n); @@ -744,13 +740,13 @@ class CalcBadVars { } }; -void CalcBadVarsF::on_finish(DataStream &os) { +void CalcBadVarsF::on_finish(DataStream& os) { stage::die_if_global_errors(); stage::set_name("Calc bad vars (for UB check)"); auto tmp_vec = tmp_stream.flush_as_vector(); CalcBadVars{}.run(tmp_vec); - for (const auto &fun_dep : tmp_vec) { + for (const auto& fun_dep : tmp_vec) { os << fun_dep.first; } } diff --git a/compiler/pipes/calc-bad-vars.h b/compiler/pipes/calc-bad-vars.h index d98ce07200..756ae63809 100644 --- a/compiler/pipes/calc-bad-vars.h +++ b/compiler/pipes/calc-bad-vars.h @@ -11,5 +11,5 @@ class CalcBadVarsF final : public SyncPipeF, FunctionPtr> { public: - void on_finish(DataStream &os) final; + void on_finish(DataStream& os) final; }; diff --git a/compiler/pipes/calc-const-types.cpp b/compiler/pipes/calc-const-types.cpp index 17af0b3033..406acdfd12 100644 --- a/compiler/pipes/calc-const-types.cpp +++ b/compiler/pipes/calc-const-types.cpp @@ -16,13 +16,13 @@ void CalcConstTypePass::on_start() { } void CalcConstTypePass::calc_const_type_of_class_fields(ClassPtr klass) { - klass->members.for_each([this](ClassMemberStaticField &f) { + klass->members.for_each([this](ClassMemberStaticField& f) { if (f.var->init_val) { run_function_pass(f.var->init_val, this); kphp_error(f.var->init_val->const_type == cnst_const_val, fmt_format("Default value of {} is not constant", f.var->as_human_readable())); } }); - klass->members.for_each([this](ClassMemberInstanceField &f) { + klass->members.for_each([this](ClassMemberInstanceField& f) { if (f.var->init_val) { run_function_pass(f.var->init_val, this); kphp_error(f.var->init_val->const_type == cnst_const_val, fmt_format("Default value of {} is not constant", f.var->as_human_readable())); @@ -42,31 +42,31 @@ VertexPtr CalcConstTypePass::on_exit_vertex(VertexPtr v) { // for now only pure functions and // constructors in defines can be `cnst_const_val`-ed if (auto as_func_call = v.try_as()) { - const bool can_be_const = as_func_call->func_id && ((as_func_call->func_id->is_constructor() && inlined_define_cnt > 0)|| as_func_call->func_id->is_pure); + const bool can_be_const = as_func_call->func_id && ((as_func_call->func_id->is_constructor() && inlined_define_cnt > 0) || as_func_call->func_id->is_pure); if (!can_be_const) { v->const_type = cnst_nonconst_val; return v; } } switch (OpInfo::cnst(v->type())) { - case cnst_func: - case cnst_const_func: { - bool has_nonconst_son = vk::any_of(*v, [](VertexPtr son) { return son->const_type == cnst_nonconst_val; }); - v->const_type = has_nonconst_son ? cnst_nonconst_val : cnst_const_val; - break; - } - case cnst_nonconst_func: { - v->const_type = cnst_nonconst_val; - break; - } - case cnst_not_func: { - v->const_type = cnst_not_val; - break; - } - default: - kphp_error (0, fmt_format("Unknown cnst-type for [op = {}]", vk::to_underlying(v->type()))); - kphp_fail(); - break; + case cnst_func: + case cnst_const_func: { + bool has_nonconst_son = vk::any_of(*v, [](VertexPtr son) { return son->const_type == cnst_nonconst_val; }); + v->const_type = has_nonconst_son ? cnst_nonconst_val : cnst_const_val; + break; + } + case cnst_nonconst_func: { + v->const_type = cnst_nonconst_val; + break; + } + case cnst_not_func: { + v->const_type = cnst_not_val; + break; + } + default: + kphp_error(0, fmt_format("Unknown cnst-type for [op = {}]", vk::to_underlying(v->type()))); + kphp_fail(); + break; } return v; } diff --git a/compiler/pipes/calc-const-types.h b/compiler/pipes/calc-const-types.h index 73af344bb9..6de2cd26c3 100644 --- a/compiler/pipes/calc-const-types.h +++ b/compiler/pipes/calc-const-types.h @@ -10,8 +10,8 @@ class CalcConstTypePass final : public FunctionPassBase { void calc_const_type_of_class_fields(ClassPtr klass); int inlined_define_cnt{0}; -public: +public: void on_start() override; std::string get_description() override { diff --git a/compiler/pipes/calc-empty-functions.cpp b/compiler/pipes/calc-empty-functions.cpp index fdcc9d0901..b90aeb6f2d 100644 --- a/compiler/pipes/calc-empty-functions.cpp +++ b/compiler/pipes/calc-empty-functions.cpp @@ -15,49 +15,49 @@ FunctionData::body_value calc_seq_body_type(VertexAdaptor seq); FunctionData::body_value get_vertex_body_type(VertexPtr vertex) { switch (vertex->type()) { - case op_set: { - FunctionPtr fun = stage::get_function(); - if (fun->file_id->main_function == fun) { - auto set = vertex.as(); - auto lhs = set->lhs(); - auto rhs = set->rhs(); - if (rhs->type() == op_true && lhs->type() == op_var && lhs->get_string() == fun->file_id->get_main_func_run_var_name()) { - return FunctionData::body_value::empty; - } - } - return FunctionData::body_value::non_empty; - } - case op_if: { - auto if_v = vertex.as(); - auto cond = if_v->cond(); - if (cond->type() == op_log_not && cond.as()->expr()->type() == op_var && !if_v->has_false_cmd()) { - return get_vertex_body_type(if_v->true_cmd()); - } - return FunctionData::body_value::non_empty; - } - case op_func_call: - return FunctionData::body_value::unknown; - case op_return: { - auto return_vertex = vertex.as(); - if (!return_vertex->has_expr() || (return_vertex->expr()->type() == op_null && stage::get_function()->is_main_function())) { + case op_set: { + FunctionPtr fun = stage::get_function(); + if (fun->file_id->main_function == fun) { + auto set = vertex.as(); + auto lhs = set->lhs(); + auto rhs = set->rhs(); + if (rhs->type() == op_true && lhs->type() == op_var && lhs->get_string() == fun->file_id->get_main_func_run_var_name()) { return FunctionData::body_value::empty; - } else { - return get_vertex_body_type(return_vertex->expr()); } } - case op_seq: - return calc_seq_body_type(vertex.as()); - case op_empty: - case op_global: + return FunctionData::body_value::non_empty; + } + case op_if: { + auto if_v = vertex.as(); + auto cond = if_v->cond(); + if (cond->type() == op_log_not && cond.as()->expr()->type() == op_var && !if_v->has_false_cmd()) { + return get_vertex_body_type(if_v->true_cmd()); + } + return FunctionData::body_value::non_empty; + } + case op_func_call: + return FunctionData::body_value::unknown; + case op_return: { + auto return_vertex = vertex.as(); + if (!return_vertex->has_expr() || (return_vertex->expr()->type() == op_null && stage::get_function()->is_main_function())) { return FunctionData::body_value::empty; - default: - return FunctionData::body_value::non_empty; + } else { + return get_vertex_body_type(return_vertex->expr()); + } + } + case op_seq: + return calc_seq_body_type(vertex.as()); + case op_empty: + case op_global: + return FunctionData::body_value::empty; + default: + return FunctionData::body_value::non_empty; } } FunctionData::body_value calc_seq_body_type(VertexAdaptor seq) { FunctionData::body_value result = FunctionData::body_value::empty; - for (VertexPtr seq_element: *seq) { + for (VertexPtr seq_element : *seq) { FunctionData::body_value vertex_body = get_vertex_body_type(seq_element); if (vertex_body == FunctionData::body_value::non_empty) { return FunctionData::body_value::non_empty; @@ -70,12 +70,9 @@ FunctionData::body_value calc_seq_body_type(VertexAdaptor seq) { } FunctionData::body_value calc_function_body_type(FunctionPtr f) { - kphp_assert (f->body_seq == FunctionData::body_value::unknown); + kphp_assert(f->body_seq == FunctionData::body_value::unknown); - if (f->is_extern() || - f->type == FunctionData::func_switch || - f->type == FunctionData::func_class_holder || - f->root->type() != op_function || + if (f->is_extern() || f->type == FunctionData::func_switch || f->type == FunctionData::func_class_holder || f->root->type() != op_function || !f->get_params().empty()) { return FunctionData::body_value::non_empty; } @@ -85,8 +82,7 @@ FunctionData::body_value calc_function_body_type(FunctionPtr f) { } // namespace - -void CalcEmptyFunctions::execute(FunctionPtr f, DataStream &os) { +void CalcEmptyFunctions::execute(FunctionPtr f, DataStream& os) { stage::set_function(f); f->body_seq = calc_function_body_type(f); diff --git a/compiler/pipes/calc-empty-functions.h b/compiler/pipes/calc-empty-functions.h index 9c15277a68..9232e6cf36 100644 --- a/compiler/pipes/calc-empty-functions.h +++ b/compiler/pipes/calc-empty-functions.h @@ -9,5 +9,5 @@ class CalcEmptyFunctions { public: - void execute(FunctionPtr f, DataStream &os); + void execute(FunctionPtr f, DataStream& os); }; diff --git a/compiler/pipes/calc-func-dep.cpp b/compiler/pipes/calc-func-dep.cpp index b6adbfa017..4f8bf54a73 100644 --- a/compiler/pipes/calc-func-dep.cpp +++ b/compiler/pipes/calc-func-dep.cpp @@ -25,9 +25,9 @@ VertexPtr CalcFuncDepPass::on_enter_vertex(VertexPtr vertex) { } // There are 117 callbacks was passed to internal functions which throw exception - //bool extern_func_throws_exception = local->extern_func_call->get_func_id()->can_throw; - //bool callback_throws = !callback_passed_to_extern_func->can_throw; - //if (callback_throws && !extern_func_throws_exception) { + // bool extern_func_throws_exception = local->extern_func_call->get_func_id()->can_throw; + // bool callback_throws = !callback_passed_to_extern_func->can_throw; + // if (callback_throws && !extern_func_throws_exception) { // kphp_error(false, "It's not allowed to throw exception in callback which was passed to internal function"); //} } @@ -47,7 +47,7 @@ VertexPtr CalcFuncDepPass::on_enter_vertex(VertexPtr vertex) { current_function->class_dep.insert(klass); } - //NB: There is no user functions in default values of any kind. + // NB: There is no user functions in default values of any kind. if (auto call = vertex.try_as()) { FunctionPtr other_function = call->func_id; // instead of just @@ -58,14 +58,14 @@ VertexPtr CalcFuncDepPass::on_enter_vertex(VertexPtr vertex) { // 2) build resumable call graph — to propagate resumable state and to calc resumable chains // 3) build interruptible call graph - calc interruptible chains // adding all built-in calls won't affect codegen, it will just overhead call graphs and execution time - if (!other_function->is_extern() || other_function->is_resumable || other_function->is_imported_from_static_lib() - || other_function->is_interruptible || other_function->need_generated_stub) { + if (!other_function->is_extern() || other_function->is_resumable || other_function->is_imported_from_static_lib() || other_function->is_interruptible || + other_function->need_generated_stub) { data.dep.push_back(other_function); } calls.push_back(other_function); if (other_function->is_extern()) { if (other_function->cpp_template_call) { - const auto *tp = tinf::get_type(call); + const auto* tp = tinf::get_type(call); if (auto klass = tp->class_type()) { current_function->class_dep.insert(klass); } @@ -79,16 +79,16 @@ VertexPtr CalcFuncDepPass::on_enter_vertex(VertexPtr vertex) { } int cnt_func_params = other_function->param_ids.size(); - if(other_function->has_variadic_param) { + if (other_function->has_variadic_param) { cnt_func_params--; } cnt_func_params = std::min(cnt_func_params, static_cast(call->args().size())); for (int ii = 0; ii < cnt_func_params; ++ii) { auto val = call->args()[ii]; VarPtr to_var = other_function->param_ids[ii]; - if (to_var->is_reference) { //passed as reference + if (to_var->is_reference) { // passed as reference while (val->type() == op_index) { - val = val.as()->array(); // from $a['b'] extract $a + val = val.as()->array(); // from $a['b'] extract $a } VarPtr from_var = (val->type() == op_var ? val.as()->var_id : val.as()->var_id); if (from_var->is_in_global_scope()) { @@ -103,8 +103,8 @@ VertexPtr CalcFuncDepPass::on_enter_vertex(VertexPtr vertex) { } else if (auto var_vertex = vertex.try_as()) { VarPtr var = var_vertex->var_id; // here we add var for later ub check; we store only vars that can potentially lead to ub, see check-ub.cpp - if ((var->is_global_var() || var->is_class_static_var()) && // only globals (not even static inside functions) - vertex->rl_type == val_l && // only modified in one way or another + if ((var->is_global_var() || var->is_class_static_var()) && // only globals (not even static inside functions) + vertex->rl_type == val_l && // only modified in one way or another vk::any_of_equal(tinf::get_type(var)->ptype(), tp_array, tp_mixed)) { // only indexable that can be ref-passed data.modified_global_vars.push_back(var); } @@ -137,7 +137,6 @@ VertexPtr CalcFuncDepPass::on_exit_vertex(VertexPtr vertex) { return vertex; } - DepData CalcFuncDepPass::get_data() { my_unique(&data.dep); my_unique(&data.modified_global_vars); diff --git a/compiler/pipes/calc-func-dep.h b/compiler/pipes/calc-func-dep.h index 836634c1d8..d322863dc7 100644 --- a/compiler/pipes/calc-func-dep.h +++ b/compiler/pipes/calc-func-dep.h @@ -12,14 +12,14 @@ #include "compiler/function-pass.h" struct DepData : private vk::movable_only { - std::vector dep; // functions accessible directly from the current (called or lambdas) (except extern) - std::vector modified_global_vars; // val_l globals for ub check later + std::vector dep; // functions accessible directly from the current (called or lambdas) (except extern) + std::vector modified_global_vars; // val_l globals for ub check later - std::forward_list ref_param_vars; // param &$refs from func declaration - std::forward_list> ref_ref_edges; // calls to f($v) when $v is a reference - std::forward_list> global_ref_edges; // calls to f($v) when $v is a global + std::forward_list ref_param_vars; // param &$refs from func declaration + std::forward_list> ref_ref_edges; // calls to f($v) when $v is a reference + std::forward_list> global_ref_edges; // calls to f($v) when $v is a global - std::forward_list forks; // calls to fork(f(...)) to calc resumable graph later + std::forward_list forks; // calls to fork(f(...)) to calc resumable graph later }; static_assert(std::is_nothrow_move_constructible::value, "DepData should be movable"); @@ -29,8 +29,8 @@ class CalcFuncDepPass final : public FunctionPassBase { private: DepData data; std::vector calls; -public: +public: std::string get_description() override { return "Calc function dependencies"; } diff --git a/compiler/pipes/calc-locations.cpp b/compiler/pipes/calc-locations.cpp index 89d34584c2..9e33393552 100644 --- a/compiler/pipes/calc-locations.cpp +++ b/compiler/pipes/calc-locations.cpp @@ -9,21 +9,20 @@ void CalcLocationsPass::on_start() { if (current_function->type == FunctionData::func_class_holder) { - current_function->class_id->members.for_each([this](ClassMemberInstanceField &f) { + current_function->class_id->members.for_each([this](ClassMemberInstanceField& f) { f.root->location = Location{current_function->file_id, current_function, f.root->location.line}; if (f.var->init_val) { f.var->init_val.set_location_recursively(f.root->location); } }); - current_function->class_id->members.for_each([this](ClassMemberStaticField &f) { + current_function->class_id->members.for_each([this](ClassMemberStaticField& f) { f.root->location = Location{current_function->file_id, current_function, f.root->location.line}; if (f.var->init_val) { f.var->init_val.set_location_recursively(f.root->location); } }); - current_function->class_id->members.for_each([this](ClassMemberConstant &c) { - c.value.set_location_recursively(Location{current_function->file_id, current_function, c.value->location.line}); - }); + current_function->class_id->members.for_each( + [this](ClassMemberConstant& c) { c.value.set_location_recursively(Location{current_function->file_id, current_function, c.value->location.line}); }); } } diff --git a/compiler/pipes/calc-real-defines-values.cpp b/compiler/pipes/calc-real-defines-values.cpp index e1732efd97..af94d5ee13 100644 --- a/compiler/pipes/calc-real-defines-values.cpp +++ b/compiler/pipes/calc-real-defines-values.cpp @@ -30,16 +30,16 @@ * (functions and classes could be assigned some pipes before, but there's no reason to split them) */ - -CalcRealDefinesAndAssignModulitesF::CalcRealDefinesAndAssignModulitesF() : Base() { +CalcRealDefinesAndAssignModulitesF::CalcRealDefinesAndAssignModulitesF() + : Base() { auto val = VertexAdaptor::create(); val->set_string(G->settings().get_version()); - DefineData *data = new DefineData("KPHP_COMPILER_VERSION", val, DefineData::def_const); + DefineData* data = new DefineData("KPHP_COMPILER_VERSION", val, DefineData::def_const); data->file_id = G->get_main_file(); G->register_define(DefinePtr(data)); } -void CalcRealDefinesAndAssignModulitesF::execute(FunctionPtr f, DataStream &unused_os) { +void CalcRealDefinesAndAssignModulitesF::execute(FunctionPtr f, DataStream& unused_os) { if (f->type == FunctionData::func_class_holder) { f->class_id->modulite = f->file_id->dir->nested_files_modulite; } @@ -52,7 +52,7 @@ void CalcRealDefinesAndAssignModulitesF::execute(FunctionPtr f, DataStream &os) { +void CalcRealDefinesAndAssignModulitesF::on_finish(DataStream& os) { stage::set_name("Calc real defines values"); stage::set_file(SrcFilePtr()); stage::die_if_global_errors(); diff --git a/compiler/pipes/calc-real-defines-values.h b/compiler/pipes/calc-real-defines-values.h index 903f264417..dc4acb1590 100644 --- a/compiler/pipes/calc-real-defines-values.h +++ b/compiler/pipes/calc-real-defines-values.h @@ -13,8 +13,8 @@ class CalcRealDefinesAndAssignModulitesF final : public SyncPipeF { private: using Base = SyncPipeF; - std::set in_progress; - std::vector stack; + std::set in_progress; + std::vector stack; CheckConstWithDefines check_const; CheckConstAccess check_const_access; @@ -26,9 +26,8 @@ class CalcRealDefinesAndAssignModulitesF final : public SyncPipeF { void print_error_infinite_define(DefinePtr cur_def); public: - CalcRealDefinesAndAssignModulitesF(); - void execute(FunctionPtr f, DataStream &unused_os) override; - void on_finish(DataStream &os) final; + void execute(FunctionPtr f, DataStream& unused_os) override; + void on_finish(DataStream& os) final; }; diff --git a/compiler/pipes/calc-rl.cpp b/compiler/pipes/calc-rl.cpp index 7684904e57..1043555044 100644 --- a/compiler/pipes/calc-rl.cpp +++ b/compiler/pipes/calc-rl.cpp @@ -10,7 +10,7 @@ void rl_calc(VertexPtr root, RLValueType expected_rl_type); -template +template void rl_calc_all(VertexPtr root, int except) { int ii = 0; for (auto v : *root) { @@ -23,37 +23,37 @@ void rl_calc_all(VertexPtr root, int except) { } } -template +template void rl_calc_all(VertexPtr root) { - for (auto v: *root) { + for (auto v : *root) { rl_calc(v, type); } } void rl_func_call_calc(VertexPtr root, RLValueType expected_rl_type) { - kphp_error (expected_rl_type != val_l, "Function result cannot be used as lvalue"); + kphp_error(expected_rl_type != val_l, "Function result cannot be used as lvalue"); switch (root->type()) { - case op_list: - rl_calc_all(root, root->size() - 1); - return; - case op_seq_comma: - case op_seq_rval: - rl_calc_all(root, root->size() - 1); - return; - case op_fork: - rl_calc_all(root); - return; - case op_array: //TODO: in fact it is wrong - case op_tuple: - case op_shape: - case op_defined: - rl_calc_all(root); - return; - case op_func_call: - break; - default: + case op_list: + rl_calc_all(root, root->size() - 1); + return; + case op_seq_comma: + case op_seq_rval: + rl_calc_all(root, root->size() - 1); + return; + case op_fork: + rl_calc_all(root); + return; + case op_array: // TODO: in fact it is wrong + case op_tuple: + case op_shape: + case op_defined: + rl_calc_all(root); + return; + case op_func_call: + break; + default: kphp_fail(); - break; + break; } auto call = root.as(); @@ -71,97 +71,97 @@ void rl_func_call_calc(VertexPtr root, RLValueType expected_rl_type) { void rl_other_calc(VertexPtr root, RLValueType expected_rl_type) { switch (root->type()) { - case op_ffi_new: { - auto v = root.try_as(); - if (v->has_array_size_expr()) { - rl_calc(v->array_size_expr(), expected_rl_type); - } - break; + case op_ffi_new: { + auto v = root.try_as(); + if (v->has_array_size_expr()) { + rl_calc(v->array_size_expr(), expected_rl_type); } - case op_ffi_cdata_value_ref: - case op_conv_array_l: - case op_conv_int_l: - case op_conv_string_l: - rl_calc_all(root); - break; - case op_noerr: - rl_calc(root.as()->expr(), expected_rl_type); - break; - case op_phpdoc_var: - break; - case op_list_keyval: { - const auto kv = root.as(); - rl_calc(kv->key(), val_r); - rl_calc(kv->var(), val_l); - break; - } - default: - assert ("Unknown operation in rl_other_calc" && 0); - break; + break; + } + case op_ffi_cdata_value_ref: + case op_conv_array_l: + case op_conv_int_l: + case op_conv_string_l: + rl_calc_all(root); + break; + case op_noerr: + rl_calc(root.as()->expr(), expected_rl_type); + break; + case op_phpdoc_var: + break; + case op_list_keyval: { + const auto kv = root.as(); + rl_calc(kv->key(), val_r); + rl_calc(kv->var(), val_l); + break; + } + default: + assert("Unknown operation in rl_other_calc" && 0); + break; } } void rl_common_calc(VertexPtr root, RLValueType expected_rl_type) { - kphp_error (expected_rl_type == val_none, "Invalid lvalue/rvalue operation"); + kphp_error(expected_rl_type == val_none, "Invalid lvalue/rvalue operation"); switch (root->type()) { - case op_if: - case op_while: - case op_switch: - case op_case: - rl_calc_all(root, 0); - break; - case op_do: - rl_calc_all(root, 1); - break; - case op_ffi_new: - break; - case op_ffi_array_set: - case op_return: - case op_break: - case op_continue: - case op_throw: - rl_calc_all(root); - break; - case op_unset: //TODO: fix it (???) - rl_calc_all(root); - break; - case op_try: { - auto v = root.as(); - rl_calc(v->try_cmd(), val_none); - for (auto c : v->catch_list()) { - auto catch_op = c.as(); - rl_calc(catch_op->var(), val_none); - rl_calc(catch_op->cmd(), val_none); - } - break; + case op_if: + case op_while: + case op_switch: + case op_case: + rl_calc_all(root, 0); + break; + case op_do: + rl_calc_all(root, 1); + break; + case op_ffi_new: + break; + case op_ffi_array_set: + case op_return: + case op_break: + case op_continue: + case op_throw: + rl_calc_all(root); + break; + case op_unset: // TODO: fix it (???) + rl_calc_all(root); + break; + case op_try: { + auto v = root.as(); + rl_calc(v->try_cmd(), val_none); + for (auto c : v->catch_list()) { + auto catch_op = c.as(); + rl_calc(catch_op->var(), val_none); + rl_calc(catch_op->cmd(), val_none); } - case op_seq: - case op_foreach: - case op_default: - rl_calc_all(root); - break; - case op_for: - //TODO: it may be untrue - rl_calc_all(root, 1); - break; - case op_global: - case op_static: - case op_empty: - break; - case op_foreach_param: - if (root.as()->x()->ref_flag) { - rl_calc_all(root, 2); - } else { - rl_calc_all(root, 0); - } - break; - case op_function: - rl_calc(root.as()->cmd(), val_none); - break; + break; + } + case op_seq: + case op_foreach: + case op_default: + rl_calc_all(root); + break; + case op_for: + // TODO: it may be untrue + rl_calc_all(root, 1); + break; + case op_global: + case op_static: + case op_empty: + break; + case op_foreach_param: + if (root.as()->x()->ref_flag) { + rl_calc_all(root, 2); + } else { + rl_calc_all(root, 0); + } + break; + case op_function: + rl_calc(root.as()->cmd(), val_none); + break; - default: + default: kphp_fail(); - break; + break; } return; } @@ -173,150 +173,149 @@ void rl_calc(VertexPtr root, RLValueType expected_rl_type) { Operation tp = root->type(); - //fprintf (stderr, "rl_calc (%p = %s)\n", root, OpInfo::str (tp).c_str()); + // fprintf (stderr, "rl_calc (%p = %s)\n", root, OpInfo::str (tp).c_str()); switch (OpInfo::rl(tp)) { - case rl_set: - switch (expected_rl_type) { - case val_r: - case val_none: { - auto set_op = root.as(); - if (set_op->lhs()->extra_type != op_ex_var_superlocal_inplace) { - rl_calc(set_op->lhs(), val_l); - } - rl_calc(set_op->rhs(), val_r); - break; - } - case val_l: - kphp_error (0, fmt_format("trying to use result of [{}] as lvalue", OpInfo::str(tp))); - break; - default: - kphp_fail(); - break; - } - break; - case rl_index: { - auto index = root.as(); - VertexPtr array = index->array(); - switch (expected_rl_type) { - case val_l: - rl_calc(array, val_l); - if (index->has_key()) { - rl_calc(index->key(), val_r); - } - break; - case val_r: - case val_none: - kphp_error (vk::any_of_equal(array->type(), op_var, op_index, op_func_call, op_instance_prop, op_array), - "op_index has to be used on lvalue"); - rl_calc(array, val_r); - - if (index->has_key()) { - rl_calc(index->key(), val_r); - } - break; - default: - assert (0); - break; + case rl_set: + switch (expected_rl_type) { + case val_r: + case val_none: { + auto set_op = root.as(); + if (set_op->lhs()->extra_type != op_ex_var_superlocal_inplace) { + rl_calc(set_op->lhs(), val_l); } + rl_calc(set_op->rhs(), val_r); break; } - case rl_instance_prop: { - VertexPtr lhs = root.as()->instance(); - switch (expected_rl_type) { - case val_l: - rl_calc(lhs, val_r); // ..a..->b as a whole is lvalue, but ..a.. is rvalue - break; - case val_r: - case val_none: - if (lhs->type() != op_var) { // "$a->prop" is most common usage, but others like "f()->prop" are also possible - kphp_error(vk::any_of_equal(lhs->type(), op_index, op_func_call, op_instance_prop, op_clone, op_seq_rval, op_ffi_new, op_ffi_addr, op_ffi_array_get), - "op_instance_prop has to be used on lvalue"); - } - rl_calc(lhs, val_r); - break; - default: - assert (0); - break; - } + case val_l: + kphp_error(0, fmt_format("trying to use result of [{}] as lvalue", OpInfo::str(tp))); + break; + default: + kphp_fail(); break; } - case rl_op: - switch (expected_rl_type) { - case val_l: - kphp_error (0, "Can't make result of operation to be lvalue"); - break; - case val_r: - case val_none: - rl_calc_all(root); - break; - default: - assert (0); - break; + break; + case rl_index: { + auto index = root.as(); + VertexPtr array = index->array(); + switch (expected_rl_type) { + case val_l: + rl_calc(array, val_l); + if (index->has_key()) { + rl_calc(index->key(), val_r); } break; + case val_r: + case val_none: + kphp_error(vk::any_of_equal(array->type(), op_var, op_index, op_func_call, op_instance_prop, op_array), "op_index has to be used on lvalue"); + rl_calc(array, val_r); - case rl_op_l: - switch (expected_rl_type) { - case val_l: - kphp_error (0, "Can't make result of operation to be lvalue"); - break; - case val_r: - case val_none: - rl_calc(root.as()->expr(), val_l); - break; - default: - kphp_fail(); - break; + if (index->has_key()) { + rl_calc(index->key(), val_r); } break; - - case rl_const: - switch (expected_rl_type) { - case val_l: - kphp_error (0, "Can't make const to be lvalue"); - break; - case val_r: - case val_none: - break; - default: - kphp_fail(); - break; - } + default: + assert(0); break; - case rl_var: - switch (expected_rl_type) { - case val_l: - kphp_error (root->extra_type != op_ex_var_const, "Can't make const to be lvalue"); - break; - case val_r: - case val_none: - break; - default: - kphp_fail(); - break; + } + break; + } + case rl_instance_prop: { + VertexPtr lhs = root.as()->instance(); + switch (expected_rl_type) { + case val_l: + rl_calc(lhs, val_r); // ..a..->b as a whole is lvalue, but ..a.. is rvalue + break; + case val_r: + case val_none: + if (lhs->type() != op_var) { // "$a->prop" is most common usage, but others like "f()->prop" are also possible + kphp_error(vk::any_of_equal(lhs->type(), op_index, op_func_call, op_instance_prop, op_clone, op_seq_rval, op_ffi_new, op_ffi_addr, op_ffi_array_get), + "op_instance_prop has to be used on lvalue"); } + rl_calc(lhs, val_r); break; - case rl_other: - rl_other_calc(root, expected_rl_type); + default: + assert(0); break; - case rl_func: - rl_func_call_calc(root, expected_rl_type); + } + break; + } + case rl_op: + switch (expected_rl_type) { + case val_l: + kphp_error(0, "Can't make result of operation to be lvalue"); break; - case rl_mem_func: + case val_r: + case val_none: rl_calc_all(root); break; - case rl_common: - rl_common_calc(root, expected_rl_type); + default: + assert(0); + break; + } + break; + + case rl_op_l: + switch (expected_rl_type) { + case val_l: + kphp_error(0, "Can't make result of operation to be lvalue"); break; + case val_r: + case val_none: + rl_calc(root.as()->expr(), val_l); + break; + default: + kphp_fail(); + break; + } + break; + case rl_const: + switch (expected_rl_type) { + case val_l: + kphp_error(0, "Can't make const to be lvalue"); + break; + case val_r: + case val_none: + break; default: - kphp_fail(); + kphp_fail(); + break; + } + break; + case rl_var: + switch (expected_rl_type) { + case val_l: + kphp_error(root->extra_type != op_ex_var_const, "Can't make const to be lvalue"); break; + case val_r: + case val_none: + break; + default: + kphp_fail(); + break; + } + break; + case rl_other: + rl_other_calc(root, expected_rl_type); + break; + case rl_func: + rl_func_call_calc(root, expected_rl_type); + break; + case rl_mem_func: + rl_calc_all(root); + break; + case rl_common: + rl_common_calc(root, expected_rl_type); + break; + + default: + kphp_fail(); + break; } } -void CalcRLF::execute(FunctionPtr function, DataStream &os) { +void CalcRLF::execute(FunctionPtr function, DataStream& os) { stage::set_name("Calc RL"); stage::set_function(function); diff --git a/compiler/pipes/calc-rl.h b/compiler/pipes/calc-rl.h index bd9a134a0d..be8f7266b0 100644 --- a/compiler/pipes/calc-rl.h +++ b/compiler/pipes/calc-rl.h @@ -9,5 +9,5 @@ class CalcRLF { public: - void execute(FunctionPtr function, DataStream &os); + void execute(FunctionPtr function, DataStream& os); }; diff --git a/compiler/pipes/calc-val-ref.cpp b/compiler/pipes/calc-val-ref.cpp index 52095554ad..f358f550df 100644 --- a/compiler/pipes/calc-val-ref.cpp +++ b/compiler/pipes/calc-val-ref.cpp @@ -8,58 +8,58 @@ bool CalcValRefPass::is_allowed_for_getting_val_or_ref(Operation op, bool is_last, bool is_first) { switch (op) { - case op_push_back: - case op_push_back_return: - case op_index: - return !is_last; + case op_push_back: + case op_push_back_return: + case op_index: + return !is_last; - case op_set_value: - return is_first; + case op_set_value: + return is_first; - case op_list: - return is_last; + case op_list: + return is_last; - case op_minus: - case op_plus: + case op_minus: + case op_plus: - case op_set_add: - case op_set_sub: - case op_set_mul: - case op_set_div: - case op_set_mod: - case op_set_pow: - case op_set_and: - case op_set_or: - case op_set_xor: - case op_set_shr: - case op_set_shl: + case op_set_add: + case op_set_sub: + case op_set_mul: + case op_set_div: + case op_set_mod: + case op_set_pow: + case op_set_and: + case op_set_or: + case op_set_xor: + case op_set_shr: + case op_set_shl: - case op_add: - case op_sub: - case op_mul: - case op_div: - case op_mod: - case op_pow: - case op_not: - case op_log_not: + case op_add: + case op_sub: + case op_mul: + case op_div: + case op_mod: + case op_pow: + case op_not: + case op_log_not: - case op_prefix_inc: - case op_prefix_dec: - case op_postfix_inc: - case op_postfix_dec: + case op_prefix_inc: + case op_prefix_dec: + case op_postfix_inc: + case op_postfix_dec: - case op_conv_int: - case op_conv_int_l: - case op_conv_float: - case op_conv_string_l: - // case op_conv_bool is ignored on purpose so f$boolval(Optional) doesn't turn into the default T + case op_conv_int: + case op_conv_int_l: + case op_conv_float: + case op_conv_string_l: + // case op_conv_bool is ignored on purpose so f$boolval(Optional) doesn't turn into the default T - case op_unset: - case op_switch: - return true; + case op_unset: + case op_switch: + return true; - default: - return false; + default: + return false; } } VertexPtr CalcValRefPass::on_enter_vertex(VertexPtr v) { diff --git a/compiler/pipes/calc-val-ref.h b/compiler/pipes/calc-val-ref.h index ee002bfd10..8c9b54762e 100644 --- a/compiler/pipes/calc-val-ref.h +++ b/compiler/pipes/calc-val-ref.h @@ -8,6 +8,7 @@ class CalcValRefPass final : public FunctionPassBase { bool is_allowed_for_getting_val_or_ref(Operation op, bool is_last, bool is_first); + public: std::string get_description() override { return "Calc val ref"; diff --git a/compiler/pipes/cfg-end.cpp b/compiler/pipes/cfg-end.cpp index 77cd73e000..ae79bf35b7 100644 --- a/compiler/pipes/cfg-end.cpp +++ b/compiler/pipes/cfg-end.cpp @@ -15,25 +15,25 @@ struct MergeData { VarPtr var; }; -bool operator<(const MergeData&a, const MergeData&b) { +bool operator<(const MergeData& a, const MergeData& b) { // sort by types if they're different; // sort by name otherwise (name$vN < name$vM with Nname < b.var->name : eq < 0; } -bool operator==(const MergeData &a, const MergeData &b) { - return type_out(tinf::get_type(a.var), gen_out_style::txt) == - type_out(tinf::get_type(b.var), gen_out_style::txt); +bool operator==(const MergeData& a, const MergeData& b) { + return type_out(tinf::get_type(a.var), gen_out_style::txt) == type_out(tinf::get_type(b.var), gen_out_style::txt); } -bool operator!=(const MergeData &a, const MergeData &b) { +bool operator!=(const MergeData& a, const MergeData& b) { return !(a == b); } -static VarPtr merge_vars(FunctionPtr function, const std::vector &vars, const std::string &new_name) { - VarPtr new_var = G->create_var(new_name, VarData::var_unknown_t);; - //new_var->tinf = vars[0]->tinf; //hack, TODO: fix it +static VarPtr merge_vars(FunctionPtr function, const std::vector& vars, const std::string& new_name) { + VarPtr new_var = G->create_var(new_name, VarData::var_unknown_t); + ; + // new_var->tinf = vars[0]->tinf; //hack, TODO: fix it new_var->tinf_node.copy_type_from(tinf::get_type(vars[0])); int param_i = -1; @@ -42,8 +42,8 @@ static VarPtr merge_vars(FunctionPtr function, const std::vector &vars, if (var->type() == VarData::var_param_t) { param_i = var->param_i; } else if (var->type() == VarData::var_local_t) { - //FIXME: remember to remove all unused variables - //func->local_var_ids.erase (*i); + // FIXME: remember to remove all unused variables + // func->local_var_ids.erase (*i); auto tmp = std::find(function->local_var_ids.begin(), function->local_var_ids.end(), var); if (function->local_var_ids.end() != tmp) { function->local_var_ids.erase(tmp); @@ -66,9 +66,9 @@ static VarPtr merge_vars(FunctionPtr function, const std::vector &vars, return new_var; } -static void merge_same_type(FunctionPtr function, const std::forward_list>>> &split_parts_list) { +static void merge_same_type(FunctionPtr function, const std::forward_list>>>& split_parts_list) { std::vector to_merge; - for (const auto &parts : split_parts_list) { + for (const auto& parts : split_parts_list) { to_merge.clear(); to_merge.reserve(parts.size()); for (int i = 0; i < parts.size(); i++) { @@ -86,7 +86,7 @@ static void merge_same_type(FunctionPtr function, const std::forward_listvar_id); } - const std::string &new_name = vars[0]->name; // name or name$vN + const std::string& new_name = vars[0]->name; // name or name$vN VarPtr new_var = merge_vars(function, vars, new_name); for (int id : ids) { for (auto v : parts[id]) { @@ -104,18 +104,18 @@ static void merge_same_type(FunctionPtr function, const std::forward_list> &uninited_vars) { +static void check_uninited(const std::forward_list>& uninited_vars) { for (auto v : uninited_vars) { if (tinf::get_type(v)->ptype() == tp_mixed) { continue; } stage::set_location(v->get_location()); - kphp_warning (fmt_format("Variable ${} may be used uninitialized", v->var_id->name)); + kphp_warning(fmt_format("Variable ${} may be used uninitialized", v->var_id->name)); } } -void CFGEndF::execute(FunctionAndCFG data, DataStream &os) { +void CFGEndF::execute(FunctionAndCFG data, DataStream& os) { stage::set_name("Control flow graph. End"); stage::set_function(data.function); check_uninited(data.data.uninited_vars); diff --git a/compiler/pipes/cfg-end.h b/compiler/pipes/cfg-end.h index 67e28d06bb..fa6537f0d6 100644 --- a/compiler/pipes/cfg-end.h +++ b/compiler/pipes/cfg-end.h @@ -10,5 +10,5 @@ class CFGEndF { public: - void execute(FunctionAndCFG data, DataStream &os); + void execute(FunctionAndCFG data, DataStream& os); }; diff --git a/compiler/pipes/cfg.cpp b/compiler/pipes/cfg.cpp index d560979389..60eaa38411 100644 --- a/compiler/pipes/cfg.cpp +++ b/compiler/pipes/cfg.cpp @@ -4,34 +4,47 @@ #include "compiler/pipes/cfg.h" -#include #include +#include +#include "compiler/compiler-core.h" #include "compiler/data/function-data.h" #include "compiler/data/var-data.h" -#include "compiler/compiler-core.h" -#include "compiler/function-pass.h" #include "compiler/debug.h" +#include "compiler/function-pass.h" #include "compiler/inferring/ifi.h" #include "compiler/utils/idmap.h" namespace cfg { // just simple int id type class Node { - DEBUG_STRING_METHOD { return std::to_string(id_); } + DEBUG_STRING_METHOD { + return std::to_string(id_); + } int id_{-1}; public: Node() = default; - explicit Node(int id): id_(id) {} + explicit Node(int id) + : id_(id) {} - explicit operator bool() const { return id_ != -1; } - void clear() { id_ = -1; } + explicit operator bool() const { + return id_ != -1; + } + void clear() { + id_ = -1; + } - friend int get_index(const Node &i) { return i.id_; } - friend bool operator==(const Node &n1, const Node &n2) { return n1.id_ == n2.id_; } - friend bool operator!=(const Node &n1, const Node &n2) { return n1.id_ != n2.id_; } + friend int get_index(const Node& i) { + return i.id_; + } + friend bool operator==(const Node& n1, const Node& n2) { + return n1.id_ == n2.id_; + } + friend bool operator!=(const Node& n1, const Node& n2) { + return n1.id_ != n2.id_; + } }; enum UsageType : uint8_t { @@ -43,23 +56,24 @@ enum UsageType : uint8_t { }; struct UsageData { - DEBUG_STRING_METHOD { return std::to_string(id); } + DEBUG_STRING_METHOD { + return std::to_string(id); + } int id; int part_id = -1; - int dsu; // disjoint set union identifier, see VarSplitData dsu + int dsu; // disjoint set union identifier, see VarSplitData dsu Node node; UsageType type; is_func_id_t checked_type; VertexAdaptor v; - UsageData(UsageType type, VertexAdaptor v, int id): - id(id), - dsu(id), - type(type), - v(v) { - } + UsageData(UsageType type, VertexAdaptor v, int id) + : id(id), + dsu(id), + type(type), + v(v) {} }; using UsagePtr = Id; @@ -68,11 +82,11 @@ struct VarSplitData { std::vector usages; VarSplitData() { - usages.reserve(4); // an empiric value + usages.reserve(4); // an empiric value } UsagePtr dsu_get(UsagePtr usage) { - while (usage->dsu != usage->id) { // non-recursive dsu, works faster than recursive + while (usage->dsu != usage->id) { // non-recursive dsu, works faster than recursive usage->dsu = usages[usage->dsu]->dsu; usage = usages[usage->dsu]; } @@ -132,10 +146,10 @@ class CFG { void add_usage(Node node, UsagePtr usage); void add_subtree(Node node, VertexPtr subtree_vertex, bool recursive_flag); void add_edge(Node from, Node to); - void collect_ref_vars(VertexPtr v, std::unordered_set &ref); + void collect_ref_vars(VertexPtr v, std::unordered_set& ref); std::vector collect_splittable_vars(FunctionPtr func); - void create_cfg(VertexPtr tree_node, Node *res_start, Node *res_finish, bool write_flag = false, bool weak_write_flag = false); - void create_condition_cfg(VertexPtr tree_node, Node *res_start, Node *res_true, Node *res_false); + void create_cfg(VertexPtr tree_node, Node* res_start, Node* res_finish, bool write_flag = false, bool weak_write_flag = false); + void create_condition_cfg(VertexPtr tree_node, Node* res_start, Node* res_true, Node* res_false); void calc_used(Node v); @@ -147,7 +161,8 @@ class CFG { bool dfs_is_uninited_usage(Node v, UsagePtr read_usage); void process_var(FunctionPtr function, VarPtr v); void on_uninited_var(VertexAdaptor v); - void split_var(FunctionPtr function, VarPtr var, std::vector>> &parts); + void split_var(FunctionPtr function, VarPtr var, std::vector>>& parts); + public: void process_function(FunctionPtr func); CFGData move_data() { @@ -181,11 +196,11 @@ void CFG::reserve_size_for_dfs_idmaps() { UsagePtr CFG::new_usage(UsageType type, VertexAdaptor v) { VarPtr var = v->var_id; - kphp_assert (var); - if (get_index(var) < 0) { // non-splittable var + kphp_assert(var); + if (get_index(var) < 0) { // non-splittable var return {}; } - VarSplitData &var_split = var_split_data[var]; + VarSplitData& var_split = var_split_data[var]; UsagePtr res = UsagePtr(new UsageData(type, v, var_split.usages.size())); var_split.usages.emplace_back(res); return res; @@ -195,17 +210,17 @@ void CFG::add_usage(Node node, UsagePtr usage) { if (!usage) { return; } - //fprintf(stderr, "%s is used at node %d with type %d\n", usage->v->get_string().c_str(), get_index(node), usage->type); - //hope that one node will contain usages of the same type - kphp_assert (node_usages[node].empty() || node_usages[node].front()->type == usage->type); + // fprintf(stderr, "%s is used at node %d with type %d\n", usage->v->get_string().c_str(), get_index(node), usage->type); + // hope that one node will contain usages of the same type + kphp_assert(node_usages[node].empty() || node_usages[node].front()->type == usage->type); node_usages[node].emplace_front(usage); usage->node = node; } void CFG::add_subtree(Node node, VertexPtr subtree_vertex, bool recursive_flag) { - kphp_assert (node && subtree_vertex); + kphp_assert(node && subtree_vertex); node_subvertices[node].emplace_front(subtree_vertex); - + if (recursive_flag) { for (VertexPtr v : *subtree_vertex) { add_subtree(node, v, true); @@ -215,13 +230,13 @@ void CFG::add_subtree(Node node, VertexPtr subtree_vertex, bool recursive_flag) void CFG::add_edge(Node from, Node to) { if (from && to) { - //fprintf(stderr, "%s, add-edge: %d->%d\n", stage::get_function_name().c_str(), get_index(from), get_index(to)); + // fprintf(stderr, "%s, add-edge: %d->%d\n", stage::get_function_name().c_str(), get_index(from), get_index(to)); node_next[from].emplace_front(to); node_prev[to].emplace_front(from); } } -void CFG::collect_ref_vars(VertexPtr v, std::unordered_set &ref) { +void CFG::collect_ref_vars(VertexPtr v, std::unordered_set& ref) { if (v->type() == op_var && v->ref_flag) { ref.emplace(v.as()->var_id); } @@ -270,16 +285,16 @@ void CFG::create_cfg_exit_cycle(Node continue_dest, Node break_dest) { } void CFG::create_cfg_add_break_node(Node v, int depth) { - kphp_assert (depth >= 1); + kphp_assert(depth >= 1); int i = (int)break_nodes.size() - depth; - kphp_assert (i >= 0); + kphp_assert(i >= 0); break_nodes[i].push_back(v); } void CFG::create_cfg_add_continue_node(Node v, int depth) { - kphp_assert (depth >= 1); + kphp_assert(depth >= 1); int i = (int)continue_nodes.size() - depth; - kphp_assert (i >= 0); + kphp_assert(i >= 0); continue_nodes[i].push_back(v); } @@ -297,747 +312,746 @@ void CFG::create_cfg_register_exception(Node from) { } } -void CFG::create_condition_cfg(VertexPtr tree_node, Node *res_start, Node *res_true, Node *res_false) { +void CFG::create_condition_cfg(VertexPtr tree_node, Node* res_start, Node* res_true, Node* res_false) { switch (tree_node->type()) { - case op_conv_bool: { - create_condition_cfg(tree_node.as()->expr(), res_start, res_true, res_false); - break; - } - case op_log_not: { - create_condition_cfg(tree_node.as()->expr(), res_start, res_false, res_true); - break; - } - case op_log_and: - case op_log_or: { - Node first_start, first_true, first_false, second_start, second_true, second_false; - auto op = tree_node.as(); - create_condition_cfg(op->lhs(), &first_start, &first_true, &first_false); - create_condition_cfg(op->rhs(), &second_start, &second_true, &second_false); - *res_start = first_start; - *res_true = new_node(); - *res_false = new_node(); - add_edge(first_true, tree_node->type() == op_log_and ? second_start : *res_true); - add_edge(first_false, tree_node->type() == op_log_or ? second_start : *res_false); - add_edge(second_true, *res_true); - add_edge(second_false, *res_false); - break; - } - default: { - Node res_finish; - create_cfg(tree_node, res_start, &res_finish); - *res_true = new_node(); - *res_false = new_node(); - auto add_type_check_usage = [&](Node to, int type, VertexAdaptor var) { - bool can_var_be_smartcasted = get_index(var->var_id) >= 0; - if (can_var_be_smartcasted) { - UsagePtr usage = new_usage(usage_type_check_t, var); - usage->checked_type = static_cast(type); - add_usage(to, usage); + case op_conv_bool: { + create_condition_cfg(tree_node.as()->expr(), res_start, res_true, res_false); + break; + } + case op_log_not: { + create_condition_cfg(tree_node.as()->expr(), res_start, res_false, res_true); + break; + } + case op_log_and: + case op_log_or: { + Node first_start, first_true, first_false, second_start, second_true, second_false; + auto op = tree_node.as(); + create_condition_cfg(op->lhs(), &first_start, &first_true, &first_false); + create_condition_cfg(op->rhs(), &second_start, &second_true, &second_false); + *res_start = first_start; + *res_true = new_node(); + *res_false = new_node(); + add_edge(first_true, tree_node->type() == op_log_and ? second_start : *res_true); + add_edge(first_false, tree_node->type() == op_log_or ? second_start : *res_false); + add_edge(second_true, *res_true); + add_edge(second_false, *res_false); + break; + } + default: { + Node res_finish; + create_cfg(tree_node, res_start, &res_finish); + *res_true = new_node(); + *res_false = new_node(); + auto add_type_check_usage = [&](Node to, int type, VertexAdaptor var) { + bool can_var_be_smartcasted = get_index(var->var_id) >= 0; + if (can_var_be_smartcasted) { + UsagePtr usage = new_usage(usage_type_check_t, var); + usage->checked_type = static_cast(type); + add_usage(to, usage); + } + }; + if (auto call = tree_node.try_as()) { + is_func_id_t type = get_ifi_id(tree_node); + if (type != ifi_error) { + auto var = call->args()[0].try_as(); + if (auto mixed_conv = call->args()[0].try_as()) { + // we're going to analyze internal var, instead of fake cast to mixed + var = mixed_conv->expr().try_as(); } - }; - if (auto call = tree_node.try_as()) { - is_func_id_t type = get_ifi_id(tree_node); - if (type != ifi_error) { - auto var = call->args()[0].try_as(); - if (auto mixed_conv = call->args()[0].try_as()) { - // we're going to analyze internal var, instead of fake cast to mixed - var = mixed_conv->expr().try_as(); + if (var) { + is_func_id_t true_type{}; + if (type == ifi_is_bool) { + true_type = static_cast(ifi_is_bool | ifi_is_false); + } else if (type == ifi_is_scalar) { + true_type = static_cast(ifi_is_false | ifi_is_bool | ifi_is_integer | ifi_is_float | ifi_is_string); + } else if (type == ifi_is_numeric) { + true_type = static_cast(ifi_is_integer | ifi_is_float | ifi_is_string); + } else { + true_type = type; } - if (var) { - is_func_id_t true_type{}; - if (type == ifi_is_bool) { - true_type = static_cast(ifi_is_bool | ifi_is_false); - } else if (type == ifi_is_scalar) { - true_type = static_cast(ifi_is_false | ifi_is_bool | ifi_is_integer | ifi_is_float | ifi_is_string); - } else if (type == ifi_is_numeric) { - true_type = static_cast(ifi_is_integer | ifi_is_float | ifi_is_string); - } else { - true_type = type; - } - is_func_id_t false_type{}; - if (type == ifi_is_numeric) { - false_type = static_cast((ifi_any_type & ~true_type) | ifi_is_string); - } else { - false_type = static_cast(ifi_any_type & ~true_type); - } - add_type_check_usage(*res_true, true_type, var); - add_type_check_usage(*res_false, false_type, var); + is_func_id_t false_type{}; + if (type == ifi_is_numeric) { + false_type = static_cast((ifi_any_type & ~true_type) | ifi_is_string); + } else { + false_type = static_cast(ifi_any_type & ~true_type); } + add_type_check_usage(*res_true, true_type, var); + add_type_check_usage(*res_false, false_type, var); } - } else if (auto isset = tree_node.try_as()) { - if (auto var = isset->expr().try_as()) { - add_type_check_usage(*res_true, ifi_any_type & ~ifi_is_null, var); - add_type_check_usage(*res_false, ifi_is_null, var); - } - } else if (tree_node->type() == op_set) { - // support for cases like: if ($x = $some_value) {...} - if (auto var = tree_node.try_as()->lhs().try_as()) { - add_type_check_usage(*res_true, ifi_any_type & ~(ifi_is_false | ifi_is_null), var); - } - } else if (auto var = tree_node.try_as()) { + } + } else if (auto isset = tree_node.try_as()) { + if (auto var = isset->expr().try_as()) { + add_type_check_usage(*res_true, ifi_any_type & ~ifi_is_null, var); + add_type_check_usage(*res_false, ifi_is_null, var); + } + } else if (tree_node->type() == op_set) { + // support for cases like: if ($x = $some_value) {...} + if (auto var = tree_node.try_as()->lhs().try_as()) { add_type_check_usage(*res_true, ifi_any_type & ~(ifi_is_false | ifi_is_null), var); - } else if (tree_node->type() == op_eq3) { - if (auto var = tree_node.try_as()->lhs().try_as()) { - if (tree_node.try_as()->rhs()->type() == op_false) { - add_type_check_usage(*res_true, ifi_is_false, var); - add_type_check_usage(*res_false, ifi_any_type & ~ifi_is_false, var); - } + } + } else if (auto var = tree_node.try_as()) { + add_type_check_usage(*res_true, ifi_any_type & ~(ifi_is_false | ifi_is_null), var); + } else if (tree_node->type() == op_eq3) { + if (auto var = tree_node.try_as()->lhs().try_as()) { + if (tree_node.try_as()->rhs()->type() == op_false) { + add_type_check_usage(*res_true, ifi_is_false, var); + add_type_check_usage(*res_false, ifi_any_type & ~ifi_is_false, var); } - } else if (tree_node->type() == op_eq2) { - if (auto var = tree_node.try_as()->lhs().try_as()) { - if (vk::any_of_equal(tree_node.try_as()->rhs()->type(), op_false, op_null)) { - add_type_check_usage(*res_false, ifi_any_type & ~(ifi_is_false|ifi_is_null), var); - } + } + } else if (tree_node->type() == op_eq2) { + if (auto var = tree_node.try_as()->lhs().try_as()) { + if (vk::any_of_equal(tree_node.try_as()->rhs()->type(), op_false, op_null)) { + add_type_check_usage(*res_false, ifi_any_type & ~(ifi_is_false | ifi_is_null), var); } } - add_edge(res_finish, *res_true); - add_edge(res_finish, *res_false); - break; } + add_edge(res_finish, *res_true); + add_edge(res_finish, *res_false); + break; + } } add_subtree(*res_start, tree_node, false); } -void CFG::create_cfg(VertexPtr tree_node, Node *res_start, Node *res_finish, bool write_flag, bool weak_write_flag) { +void CFG::create_cfg(VertexPtr tree_node, Node* res_start, Node* res_finish, bool write_flag, bool weak_write_flag) { stage::set_location(tree_node->location); bool recursive_flag = false; switch (tree_node->type()) { - // vararg operators - case op_array: - case op_tuple: - case op_shape: - case op_seq_comma: - case op_seq_rval: - case op_seq: - case op_string_build: - case op_callback_of_builtin: { - Node a, b, end; - if (tree_node->empty()) { - *res_start = *res_finish = new_node(); - break; - } - VertexRange args = tree_node.as()->args(); - create_cfg(args[0], res_start, &b); - end = b; - for (int i = 1; i < tree_node->size(); i++) { - create_cfg(args[i], &a, &b); - add_edge(end, a); - end = b; - } - *res_finish = end; - break; - } - - // simple just-value operators - case op_int_const: - case op_float_const: - case op_true: - case op_false: - case op_null: - case op_empty: - case op_alloc: { + // vararg operators + case op_array: + case op_tuple: + case op_shape: + case op_seq_comma: + case op_seq_rval: + case op_seq: + case op_string_build: + case op_callback_of_builtin: { + Node a, b, end; + if (tree_node->empty()) { *res_start = *res_finish = new_node(); break; } - - // simple binary operators - case op_add: - case op_sub: - case op_mul: - case op_div: - case op_shl: - case op_shr: - case op_concat: - case op_le: - case op_lt: - case op_null_coalesce: - case op_instanceof: - case op_and: - case op_xor: - case op_or: - case op_eq3: - case op_eq2: - case op_mod: - case op_pow: - case op_set_add: - case op_set_sub: - case op_set_mul: - case op_set_div: - case op_set_mod: - case op_set_pow: - case op_set_and: - case op_set_or: - case op_set_xor: - case op_set_dot: - case op_set_shr: - case op_set_shl: - case op_spaceship: - case op_double_arrow: { - auto op = tree_node.as(); - Node first_finish, second_start; - create_cfg(op->lhs(), res_start, &first_finish); - create_cfg(op->rhs(), &second_start, res_finish); - add_edge(first_finish, second_start); - break; + VertexRange args = tree_node.as()->args(); + create_cfg(args[0], res_start, &b); + end = b; + for (int i = 1; i < tree_node->size(); i++) { + create_cfg(args[i], &a, &b); + add_edge(end, a); + end = b; } + *res_finish = end; + break; + } - // simple unary operators - case op_ffi_c2php_conv: - case op_ffi_php2c_conv: - case op_ffi_addr: - case op_ffi_cdata_value_ref: - case op_conv_int: - case op_conv_int_l: - case op_conv_float: - case op_conv_string: - case op_conv_string_l: - case op_conv_array: - case op_conv_array_l: - case op_conv_object: - case op_conv_mixed: - case op_force_mixed: - case op_conv_regexp: - case op_conv_bool: - case op_conv_drop_null: - case op_conv_drop_false: - case op_isset: - case op_unset: - case op_postfix_inc: - case op_postfix_dec: - case op_prefix_inc: - case op_prefix_dec: - case op_plus: - case op_minus: - case op_move: - case op_log_not: - case op_noerr: - case op_not: - case op_addr: - case op_clone: { - create_cfg(tree_node.as()->expr(), res_start, res_finish); - break; - } + // simple just-value operators + case op_int_const: + case op_float_const: + case op_true: + case op_false: + case op_null: + case op_empty: + case op_alloc: { + *res_start = *res_finish = new_node(); + break; + } - case op_ffi_cast: { - auto op = tree_node.as(); - if (op->has_array_size_expr()) { - Node expr_end, array_size_expr_start; - create_cfg(op->expr(), res_start, &expr_end); - create_cfg(op->array_size_expr(), &array_size_expr_start, res_finish); - add_edge(expr_end, array_size_expr_start); - } else { - create_cfg(op->expr(), res_start, res_finish); - } - break; - } + // simple binary operators + case op_add: + case op_sub: + case op_mul: + case op_div: + case op_shl: + case op_shr: + case op_concat: + case op_le: + case op_lt: + case op_null_coalesce: + case op_instanceof: + case op_and: + case op_xor: + case op_or: + case op_eq3: + case op_eq2: + case op_mod: + case op_pow: + case op_set_add: + case op_set_sub: + case op_set_mul: + case op_set_div: + case op_set_mod: + case op_set_pow: + case op_set_and: + case op_set_or: + case op_set_xor: + case op_set_dot: + case op_set_shr: + case op_set_shl: + case op_spaceship: + case op_double_arrow: { + auto op = tree_node.as(); + Node first_finish, second_start; + create_cfg(op->lhs(), res_start, &first_finish); + create_cfg(op->rhs(), &second_start, res_finish); + add_edge(first_finish, second_start); + break; + } - case op_ffi_array_get: { - auto op = tree_node.as(); - Node array_end, key_start; - create_cfg(op->array(), res_start, &array_end); - create_cfg(op->key(), &key_start, res_finish); - add_edge(array_end, key_start); - break; - } + // simple unary operators + case op_ffi_c2php_conv: + case op_ffi_php2c_conv: + case op_ffi_addr: + case op_ffi_cdata_value_ref: + case op_conv_int: + case op_conv_int_l: + case op_conv_float: + case op_conv_string: + case op_conv_string_l: + case op_conv_array: + case op_conv_array_l: + case op_conv_object: + case op_conv_mixed: + case op_force_mixed: + case op_conv_regexp: + case op_conv_bool: + case op_conv_drop_null: + case op_conv_drop_false: + case op_isset: + case op_unset: + case op_postfix_inc: + case op_postfix_dec: + case op_prefix_inc: + case op_prefix_dec: + case op_plus: + case op_minus: + case op_move: + case op_log_not: + case op_noerr: + case op_not: + case op_addr: + case op_clone: { + create_cfg(tree_node.as()->expr(), res_start, res_finish); + break; + } - case op_ffi_array_set: { - auto op = tree_node.as(); - Node array_end, key_start, key_end, value_start; - create_cfg(op->array(), res_start, &array_end, false, write_flag || weak_write_flag); - create_cfg(op->key(), &key_start, &key_end); - create_cfg(op->value(), &value_start, res_finish); - add_edge(array_end, key_start); - add_edge(key_end, value_start); - break; + case op_ffi_cast: { + auto op = tree_node.as(); + if (op->has_array_size_expr()) { + Node expr_end, array_size_expr_start; + create_cfg(op->expr(), res_start, &expr_end); + create_cfg(op->array_size_expr(), &array_size_expr_start, res_finish); + add_edge(expr_end, array_size_expr_start); + } else { + create_cfg(op->expr(), res_start, res_finish); } + break; + } - case op_ffi_new: { - auto op = tree_node.as(); - Node owned_flag_expr_end, array_size_expr_start; - create_cfg(op->owned_flag_expr(), res_start, &owned_flag_expr_end); - if (op->has_array_size_expr()) { - create_cfg(op->array_size_expr(), &array_size_expr_start, res_finish); - add_edge(owned_flag_expr_end, array_size_expr_start); - } else { - *res_finish = owned_flag_expr_end; - } - break; - } + case op_ffi_array_get: { + auto op = tree_node.as(); + Node array_end, key_start; + create_cfg(op->array(), res_start, &array_end); + create_cfg(op->key(), &key_start, res_finish); + add_edge(array_end, key_start); + break; + } - case op_instance_prop: { - create_cfg(tree_node.as()->instance(), res_start, res_finish); - break; - } - case op_index: { - Node var_start, var_finish; - auto index = tree_node.as(); - create_cfg(index->array(), &var_start, &var_finish, false, write_flag || weak_write_flag); - Node start = var_start; - Node finish = var_finish; - if (index->has_key()) { - Node index_start, index_finish; - create_cfg(index->key(), &index_start, &index_finish); - add_edge(index_finish, start); - start = index_start; - } - *res_start = start; - *res_finish = finish; - break; + case op_ffi_array_set: { + auto op = tree_node.as(); + Node array_end, key_start, key_end, value_start; + create_cfg(op->array(), res_start, &array_end, false, write_flag || weak_write_flag); + create_cfg(op->key(), &key_start, &key_end); + create_cfg(op->value(), &value_start, res_finish); + add_edge(array_end, key_start); + add_edge(key_end, value_start); + break; + } + + case op_ffi_new: { + auto op = tree_node.as(); + Node owned_flag_expr_end, array_size_expr_start; + create_cfg(op->owned_flag_expr(), res_start, &owned_flag_expr_end); + if (op->has_array_size_expr()) { + create_cfg(op->array_size_expr(), &array_size_expr_start, res_finish); + add_edge(owned_flag_expr_end, array_size_expr_start); + } else { + *res_finish = owned_flag_expr_end; } - case op_log_and: - case op_log_or: - case op_log_and_let: - case op_log_or_let: - case op_log_xor_let: { - Node first_start, first_finish, second_start, second_finish; - auto op = tree_node.as(); - create_cfg(op->lhs(), &first_start, &first_finish); - create_cfg(op->rhs(), &second_start, &second_finish); - Node finish = new_node(); - add_edge(first_finish, second_start); - add_edge(second_finish, finish); - add_edge(first_finish, finish); - *res_start = first_start; - *res_finish = finish; - break; + break; + } + + case op_instance_prop: { + create_cfg(tree_node.as()->instance(), res_start, res_finish); + break; + } + case op_index: { + Node var_start, var_finish; + auto index = tree_node.as(); + create_cfg(index->array(), &var_start, &var_finish, false, write_flag || weak_write_flag); + Node start = var_start; + Node finish = var_finish; + if (index->has_key()) { + Node index_start, index_finish; + create_cfg(index->key(), &index_start, &index_finish); + add_edge(index_finish, start); + start = index_start; } - case op_func_call: { - FunctionPtr func = tree_node.as()->func_id; + *res_start = start; + *res_finish = finish; + break; + } + case op_log_and: + case op_log_or: + case op_log_and_let: + case op_log_or_let: + case op_log_xor_let: { + Node first_start, first_finish, second_start, second_finish; + auto op = tree_node.as(); + create_cfg(op->lhs(), &first_start, &first_finish); + create_cfg(op->rhs(), &second_start, &second_finish); + Node finish = new_node(); + add_edge(first_finish, second_start); + add_edge(second_finish, finish); + add_edge(first_finish, finish); + *res_start = first_start; + *res_finish = finish; + break; + } + case op_func_call: { + FunctionPtr func = tree_node.as()->func_id; - Node start, a, b; - start = new_node(); - *res_start = start; + Node start, a, b; + start = new_node(); + *res_start = start; - int ii = 0; - for (auto cur : tree_node.as()->args()) { - bool new_weak_write_flag = false; + int ii = 0; + for (auto cur : tree_node.as()->args()) { + bool new_weak_write_flag = false; - if (func) { - auto param = func->get_params()[ii].try_as(); - if (param && param->var()->ref_flag) { - new_weak_write_flag = true; - } + if (func) { + auto param = func->get_params()[ii].try_as(); + if (param && param->var()->ref_flag) { + new_weak_write_flag = true; } - - kphp_assert (cur); - create_cfg(cur, &a, &b, false, new_weak_write_flag); - add_edge(start, a); - start = b; - - ii++; - } - if (func->is_no_return) { - *res_finish = Node(); - } else { - *res_finish = start; } - if (func->can_throw()) { - create_cfg_register_exception(*res_finish); - } - break; - } - case op_ffi_load_call: - create_cfg(tree_node.as()->func_call(), res_start, res_finish); - break; - case op_fork: { - create_cfg(tree_node.as()->func_call(), res_start, res_finish); - break; + kphp_assert(cur); + create_cfg(cur, &a, &b, false, new_weak_write_flag); + add_edge(start, a); + start = b; + + ii++; } - case op_return: { - auto return_op = tree_node.as(); - if (return_op->has_expr()) { - Node tmp; - create_cfg(return_op->expr(), res_start, &tmp); - } else { - *res_start = new_node(); - } + if (func->is_no_return) { *res_finish = Node(); - break; + } else { + *res_finish = start; } - case op_set: { - auto set_op = tree_node.as(); - Node a, b; - create_cfg(set_op->rhs(), res_start, &a); - create_cfg(set_op->lhs(), &b, res_finish, true); - add_edge(a, b); - break; + + if (func->can_throw()) { + create_cfg_register_exception(*res_finish); } - case op_list: { - auto list = tree_node.as(); - Node prev; - create_cfg(list->array(), res_start, &prev); - for (auto param : list->list().get_reversed_range()) { - Node a, b; - create_cfg(param, &a, &b, true); - add_edge(prev, a); - prev = b; - } - *res_finish = prev; - break; + break; + } + case op_ffi_load_call: + create_cfg(tree_node.as()->func_call(), res_start, res_finish); + break; + case op_fork: { + create_cfg(tree_node.as()->func_call(), res_start, res_finish); + break; + } + case op_return: { + auto return_op = tree_node.as(); + if (return_op->has_expr()) { + Node tmp; + create_cfg(return_op->expr(), res_start, &tmp); + } else { + *res_start = new_node(); } - case op_list_keyval: { - const auto kv = tree_node.as(); + *res_finish = Node(); + break; + } + case op_set: { + auto set_op = tree_node.as(); + Node a, b; + create_cfg(set_op->rhs(), res_start, &a); + create_cfg(set_op->lhs(), &b, res_finish, true); + add_edge(a, b); + break; + } + case op_list: { + auto list = tree_node.as(); + Node prev; + create_cfg(list->array(), res_start, &prev); + for (auto param : list->list().get_reversed_range()) { Node a, b; - create_cfg(kv->var(), res_start, &a, true); - create_cfg(kv->key(), &b, res_finish); - add_edge(a, b); - break; - } - case op_var: { - Node res = new_node(); - UsagePtr usage = new_usage(write_flag ? usage_write_t : weak_write_flag ? usage_weak_write_t : usage_read_t, tree_node.as()); - add_usage(res, usage); - *res_start = *res_finish = res; - break; - } - case op_phpdoc_var: { - Node res = new_node(); - UsagePtr usage = new_usage(usage_type_hint_t, tree_node.as()->var()); - add_usage(res, usage); - *res_start = *res_finish = res; - add_subtree(*res_start, tree_node.as()->var(), false); - break; + create_cfg(param, &a, &b, true); + add_edge(prev, a); + prev = b; } - case op_if: { - auto if_op = tree_node.as(); - Node finish = new_node(); - Node cond_true, cond_false, if_start, if_finish; - create_condition_cfg(if_op->cond(), res_start, &cond_true, &cond_false); - create_cfg(if_op->true_cmd(), &if_start, &if_finish); - add_edge(cond_true, if_start); - add_edge(if_finish, finish); - if (if_op->has_false_cmd()) { - Node else_start, else_finish; - create_cfg(if_op->false_cmd(), &else_start, &else_finish); - add_edge(cond_false, else_start); - add_edge(else_finish, finish); - } else { - add_edge(cond_false, finish); - } - - *res_finish = finish; - break; - } - case op_ternary: { - auto ternary_op = tree_node.as(); - Node finish = new_node(); - Node cond_true, cond_false; - - Node if_start, if_finish; - create_condition_cfg(ternary_op->cond(), res_start, &cond_true, &cond_false); - create_cfg(ternary_op->true_expr(), &if_start, &if_finish); - add_edge(cond_true, if_start); - add_edge(if_finish, finish); - + *res_finish = prev; + break; + } + case op_list_keyval: { + const auto kv = tree_node.as(); + Node a, b; + create_cfg(kv->var(), res_start, &a, true); + create_cfg(kv->key(), &b, res_finish); + add_edge(a, b); + break; + } + case op_var: { + Node res = new_node(); + UsagePtr usage = new_usage(write_flag ? usage_write_t : weak_write_flag ? usage_weak_write_t : usage_read_t, tree_node.as()); + add_usage(res, usage); + *res_start = *res_finish = res; + break; + } + case op_phpdoc_var: { + Node res = new_node(); + UsagePtr usage = new_usage(usage_type_hint_t, tree_node.as()->var()); + add_usage(res, usage); + *res_start = *res_finish = res; + add_subtree(*res_start, tree_node.as()->var(), false); + break; + } + case op_if: { + auto if_op = tree_node.as(); + Node finish = new_node(); + Node cond_true, cond_false, if_start, if_finish; + create_condition_cfg(if_op->cond(), res_start, &cond_true, &cond_false); + create_cfg(if_op->true_cmd(), &if_start, &if_finish); + add_edge(cond_true, if_start); + add_edge(if_finish, finish); + if (if_op->has_false_cmd()) { Node else_start, else_finish; - create_cfg(ternary_op->false_expr(), &else_start, &else_finish); + create_cfg(if_op->false_cmd(), &else_start, &else_finish); add_edge(cond_false, else_start); add_edge(else_finish, finish); - - *res_finish = finish; - break; - } - case op_break: { - auto break_op = tree_node.as(); - recursive_flag = true; - Node start = new_node(), finish = Node(); - create_cfg_add_break_node(start, atoi(break_op->level()->get_string().c_str())); - - *res_start = start; - *res_finish = finish; - break; - } - case op_continue: { - auto continue_op = tree_node.as(); - recursive_flag = true; - Node start = new_node(), finish = Node(); - create_cfg_add_continue_node(start, atoi(continue_op->level()->get_string().c_str())); - - *res_start = start; - *res_finish = finish; - break; + } else { + add_edge(cond_false, finish); } - case op_for: { - create_cfg_enter_cycle(); - auto for_op = tree_node.as(); + *res_finish = finish; + break; + } + case op_ternary: { + auto ternary_op = tree_node.as(); + Node finish = new_node(); + Node cond_true, cond_false; + + Node if_start, if_finish; + create_condition_cfg(ternary_op->cond(), res_start, &cond_true, &cond_false); + create_cfg(ternary_op->true_expr(), &if_start, &if_finish); + add_edge(cond_true, if_start); + add_edge(if_finish, finish); + + Node else_start, else_finish; + create_cfg(ternary_op->false_expr(), &else_start, &else_finish); + add_edge(cond_false, else_start); + add_edge(else_finish, finish); + + *res_finish = finish; + break; + } + case op_break: { + auto break_op = tree_node.as(); + recursive_flag = true; + Node start = new_node(), finish = Node(); + create_cfg_add_break_node(start, atoi(break_op->level()->get_string().c_str())); + + *res_start = start; + *res_finish = finish; + break; + } + case op_continue: { + auto continue_op = tree_node.as(); + recursive_flag = true; + Node start = new_node(), finish = Node(); + create_cfg_add_continue_node(start, atoi(continue_op->level()->get_string().c_str())); + + *res_start = start; + *res_finish = finish; + break; + } + case op_for: { + create_cfg_enter_cycle(); - Node init_start, init_finish; - create_cfg(for_op->pre_cond(), &init_start, &init_finish); + auto for_op = tree_node.as(); - Node cond_start, cond_finish_true, cond_finish_false; - create_condition_cfg(for_op->cond(), &cond_start, &cond_finish_true, &cond_finish_false); + Node init_start, init_finish; + create_cfg(for_op->pre_cond(), &init_start, &init_finish); - Node inc_start, inc_finish; - create_cfg(for_op->post_cond(), &inc_start, &inc_finish); + Node cond_start, cond_finish_true, cond_finish_false; + create_condition_cfg(for_op->cond(), &cond_start, &cond_finish_true, &cond_finish_false); - Node action_start, action_finish_pre, action_finish = new_node(); - create_cfg(for_op->cmd(), &action_start, &action_finish_pre); - add_edge(action_finish_pre, action_finish); + Node inc_start, inc_finish; + create_cfg(for_op->post_cond(), &inc_start, &inc_finish); - add_edge(init_finish, cond_start); - add_edge(cond_finish_true, action_start); - add_edge(action_finish, inc_start); - add_edge(inc_finish, cond_start); + Node action_start, action_finish_pre, action_finish = new_node(); + create_cfg(for_op->cmd(), &action_start, &action_finish_pre); + add_edge(action_finish_pre, action_finish); - Node finish = new_node(); - add_edge(cond_finish_false, finish); + add_edge(init_finish, cond_start); + add_edge(cond_finish_true, action_start); + add_edge(action_finish, inc_start); + add_edge(inc_finish, cond_start); - *res_start = init_start; - *res_finish = finish; + Node finish = new_node(); + add_edge(cond_finish_false, finish); - create_cfg_exit_cycle(action_finish, finish); - break; - } - case op_do: - case op_while: { - create_cfg_enter_cycle(); - - VertexPtr cond, cmd; - if (auto do_op = tree_node.try_as()) { - cond = do_op->cond(); - cmd = do_op->cmd(); - } else if (auto while_op = tree_node.try_as()) { - cond = while_op->cond(); - cmd = while_op->cmd(); - } else { - kphp_fail(); - } + *res_start = init_start; + *res_finish = finish; + create_cfg_exit_cycle(action_finish, finish); + break; + } + case op_do: + case op_while: { + create_cfg_enter_cycle(); + + VertexPtr cond, cmd; + if (auto do_op = tree_node.try_as()) { + cond = do_op->cond(); + cmd = do_op->cmd(); + } else if (auto while_op = tree_node.try_as()) { + cond = while_op->cond(); + cmd = while_op->cmd(); + } else { + kphp_fail(); + } - Node cond_start, cond_finish_true, cond_finish_false; - create_condition_cfg(cond, &cond_start, &cond_finish_true, &cond_finish_false); - - Node action_start, action_finish_pre, action_finish = new_node(); - create_cfg(cmd, &action_start, &action_finish_pre); - add_edge(action_finish_pre, action_finish); - - add_edge(cond_finish_true, action_start); - add_edge(action_finish, cond_start); + Node cond_start, cond_finish_true, cond_finish_false; + create_condition_cfg(cond, &cond_start, &cond_finish_true, &cond_finish_false); - Node finish = new_node(); - add_edge(cond_finish_false, finish); + Node action_start, action_finish_pre, action_finish = new_node(); + create_cfg(cmd, &action_start, &action_finish_pre); + add_edge(action_finish_pre, action_finish); - if (tree_node->type() == op_do) { - *res_start = action_start; - } else if (tree_node->type() == op_while) { - *res_start = cond_start; - } else { - kphp_fail(); - } - *res_finish = finish; + add_edge(cond_finish_true, action_start); + add_edge(action_finish, cond_start); - if (tree_node->type() == op_do && action_finish_pre) { - add_subtree(*res_start, cond, true); - } + Node finish = new_node(); + add_edge(cond_finish_false, finish); - create_cfg_exit_cycle(action_finish, finish); - break; + if (tree_node->type() == op_do) { + *res_start = action_start; + } else if (tree_node->type() == op_while) { + *res_start = cond_start; + } else { + kphp_fail(); } - case op_foreach: { - create_cfg_enter_cycle(); + *res_finish = finish; - auto foreach_op = tree_node.as(); + if (tree_node->type() == op_do && action_finish_pre) { + add_subtree(*res_start, cond, true); + } - auto foreach_param = foreach_op->params(); - Node val_start, val_finish; + create_cfg_exit_cycle(action_finish, finish); + break; + } + case op_foreach: { + create_cfg_enter_cycle(); - create_cfg(foreach_param->xs(), &val_start, &val_finish); + auto foreach_op = tree_node.as(); - Node writes = new_node(); - add_usage(writes, new_usage(usage_write_t, foreach_param->x())); - if (!foreach_param->x()->ref_flag) { - add_usage(writes, new_usage(usage_write_t, foreach_param->temp_var().as())); - } - if (foreach_param->has_key()) { - add_usage(writes, new_usage(usage_write_t, foreach_param->key())); - } + auto foreach_param = foreach_op->params(); + Node val_start, val_finish; - //?? not sure - add_subtree(val_start, foreach_param, true); + create_cfg(foreach_param->xs(), &val_start, &val_finish); - Node finish = new_node(); + Node writes = new_node(); + add_usage(writes, new_usage(usage_write_t, foreach_param->x())); + if (!foreach_param->x()->ref_flag) { + add_usage(writes, new_usage(usage_write_t, foreach_param->temp_var().as())); + } + if (foreach_param->has_key()) { + add_usage(writes, new_usage(usage_write_t, foreach_param->key())); + } - Node cond_start = val_start; - Node cond_check = new_node(); - Node cond_true = writes; - Node cond_false = finish; + //?? not sure + add_subtree(val_start, foreach_param, true); - add_edge(val_finish, cond_check); - add_edge(cond_check, cond_true); - add_edge(cond_check, cond_false); + Node finish = new_node(); - Node action_start, action_finish_pre, action_finish = new_node(); - create_cfg(foreach_op->cmd(), &action_start, &action_finish_pre); - add_edge(action_finish_pre, action_finish); + Node cond_start = val_start; + Node cond_check = new_node(); + Node cond_true = writes; + Node cond_false = finish; - add_edge(cond_true, action_start); - add_edge(action_finish, cond_check); + add_edge(val_finish, cond_check); + add_edge(cond_check, cond_true); + add_edge(cond_check, cond_false); - *res_start = cond_start; - *res_finish = finish; + Node action_start, action_finish_pre, action_finish = new_node(); + create_cfg(foreach_op->cmd(), &action_start, &action_finish_pre); + add_edge(action_finish_pre, action_finish); - create_cfg_exit_cycle(action_finish, finish); - break; - } - case op_switch: { - create_cfg_enter_cycle(); - - auto switch_op = tree_node.as(); - Node cond_start; - Node cond_finish; - create_cfg(switch_op->condition(), &cond_start, &cond_finish); - - Node prev_finish; - Node prev_var_finish = cond_finish; - - Node vars_init = new_node(); - Node vars_read = new_node(); - - add_edge(vars_init, vars_read); - auto add_usages_for_switch_var = [&](VertexAdaptor switch_var) { - add_usage(vars_init, new_usage(usage_write_t, switch_var)); - add_usage(vars_read, new_usage(usage_read_t, switch_var)); - add_subtree(vars_init, switch_var, false); - add_subtree(vars_read, switch_var, false); - }; - add_usages_for_switch_var(switch_op->condition_on_switch()); - add_usages_for_switch_var(switch_op->matched_with_one_case()); - - bool was_default = false; - Node default_start; - for (auto i : switch_op->cases()) { - VertexPtr expr, cmd; - bool is_default = false; - if (auto cs = i.try_as()) { - expr = cs->expr(); - cmd = cs->cmd(); - } else if (auto def = i.try_as()) { - is_default = true; - cmd = def->cmd(); - } else { - kphp_fail(); - } + add_edge(cond_true, action_start); + add_edge(action_finish, cond_check); - Node cur_start, cur_finish; - create_cfg(cmd, &cur_start, &cur_finish); - add_edge(prev_finish, cur_start); - prev_finish = cur_finish; - - if (is_default) { - default_start = cur_start; - was_default = true; - } else { - Node cur_var_start, cur_var_finish; - create_cfg(expr, &cur_var_start, &cur_var_finish); - add_edge(cur_var_finish, cur_start); - add_edge(prev_var_finish, cur_var_start); - prev_var_finish = cur_var_finish; - } + *res_start = cond_start; + *res_finish = finish; - add_subtree(cond_start, i, false); - } - Node finish = new_node(); - add_edge(prev_finish, finish); - if (was_default) { - add_edge(prev_var_finish, default_start); + create_cfg_exit_cycle(action_finish, finish); + break; + } + case op_switch: { + create_cfg_enter_cycle(); + + auto switch_op = tree_node.as(); + Node cond_start; + Node cond_finish; + create_cfg(switch_op->condition(), &cond_start, &cond_finish); + + Node prev_finish; + Node prev_var_finish = cond_finish; + + Node vars_init = new_node(); + Node vars_read = new_node(); + + add_edge(vars_init, vars_read); + auto add_usages_for_switch_var = [&](VertexAdaptor switch_var) { + add_usage(vars_init, new_usage(usage_write_t, switch_var)); + add_usage(vars_read, new_usage(usage_read_t, switch_var)); + add_subtree(vars_init, switch_var, false); + add_subtree(vars_read, switch_var, false); + }; + add_usages_for_switch_var(switch_op->condition_on_switch()); + add_usages_for_switch_var(switch_op->matched_with_one_case()); + + bool was_default = false; + Node default_start; + for (auto i : switch_op->cases()) { + VertexPtr expr, cmd; + bool is_default = false; + if (auto cs = i.try_as()) { + expr = cs->expr(); + cmd = cs->cmd(); + } else if (auto def = i.try_as()) { + is_default = true; + cmd = def->cmd(); } else { - add_edge(prev_var_finish, finish); + kphp_fail(); } - add_edge(vars_read, cond_start); - *res_start = vars_init; - *res_finish = finish; + Node cur_start, cur_finish; + create_cfg(cmd, &cur_start, &cur_finish); + add_edge(prev_finish, cur_start); + prev_finish = cur_finish; - create_cfg_exit_cycle(finish, finish); - break; + if (is_default) { + default_start = cur_start; + was_default = true; + } else { + Node cur_var_start, cur_var_finish; + create_cfg(expr, &cur_var_start, &cur_var_finish); + add_edge(cur_var_finish, cur_start); + add_edge(prev_var_finish, cur_var_start); + prev_var_finish = cur_var_finish; + } + + add_subtree(cond_start, i, false); } - case op_throw: { - auto throw_op = tree_node.as(); - Node throw_start, throw_finish; - create_cfg(throw_op->exception(), &throw_start, &throw_finish); - create_cfg_register_exception(throw_finish); - - *res_start = throw_start; - //*res_finish = throw_finish; - *res_finish = new_node(); - break; + Node finish = new_node(); + add_edge(prev_finish, finish); + if (was_default) { + add_edge(prev_var_finish, default_start); + } else { + add_edge(prev_var_finish, finish); } - case op_try: { - auto try_op = tree_node.as(); - Node try_start, try_finish; - create_cfg_begin_try(); - create_cfg(try_op->try_cmd(), &try_start, &try_finish); - std::vector exceptions = exception_nodes.back(); - create_cfg_end_try(); + add_edge(vars_read, cond_start); + *res_start = vars_init; + *res_finish = finish; - Node finish = new_node(); - add_edge(try_finish, finish); + create_cfg_exit_cycle(finish, finish); + break; + } + case op_throw: { + auto throw_op = tree_node.as(); + Node throw_start, throw_finish; + create_cfg(throw_op->exception(), &throw_start, &throw_finish); + create_cfg_register_exception(throw_finish); + + *res_start = throw_start; + //*res_finish = throw_finish; + *res_finish = new_node(); + break; + } + case op_try: { + auto try_op = tree_node.as(); - Node catch_list_start = new_node(); - for (Node e : exceptions) { - add_edge(e, catch_list_start); - } + Node try_start, try_finish; + create_cfg_begin_try(); + create_cfg(try_op->try_cmd(), &try_start, &try_finish); + std::vector exceptions = exception_nodes.back(); + create_cfg_end_try(); - // connect catch_list_start to every catch block - for (auto c : try_op->catch_list()) { - auto catch_op = c.as(); - Node exception_start, exception_finish; - create_cfg(catch_op->var(), &exception_start, &exception_finish, true); + Node finish = new_node(); + add_edge(try_finish, finish); - add_edge(catch_list_start, exception_start); + Node catch_list_start = new_node(); + for (Node e : exceptions) { + add_edge(e, catch_list_start); + } - Node catch_start, catch_finish; - create_cfg(catch_op->cmd(), &catch_start, &catch_finish); + // connect catch_list_start to every catch block + for (auto c : try_op->catch_list()) { + auto catch_op = c.as(); + Node exception_start, exception_finish; + create_cfg(catch_op->var(), &exception_start, &exception_finish, true); - add_edge(exception_finish, catch_start); - add_edge(catch_finish, finish); + add_edge(catch_list_start, exception_start); - add_subtree(catch_list_start, catch_op, false); - add_subtree(exception_start, catch_op->var(), false); - add_subtree(catch_start, catch_op->cmd(), true); // todo shall we pass true here? - } + Node catch_start, catch_finish; + create_cfg(catch_op->cmd(), &catch_start, &catch_finish); - if (!try_op->catches_all) { - // propagate all thrown exceptions - for (Node n : exceptions) { - create_cfg_register_exception(n); - } - } + add_edge(exception_finish, catch_start); + add_edge(catch_finish, finish); - *res_start = try_start; - *res_finish = finish; - break; + add_subtree(catch_list_start, catch_op, false); + add_subtree(exception_start, catch_op->var(), false); + add_subtree(catch_start, catch_op->cmd(), true); // todo shall we pass true here? } - case op_function: { - auto function = tree_node.as(); - Node a, b; - create_cfg(function->param_list(), res_start, &a); - create_cfg(function->cmd(), &b, res_finish); - add_edge(a, b); - break; - } - case op_func_param_list: { - auto param_list = tree_node.as(); - Node a = new_node(); - for (auto p : param_list->params()) { - add_usage(a, new_usage(usage_read_t, p.as()->var())); + if (!try_op->catches_all) { + // propagate all thrown exceptions + for (Node n : exceptions) { + create_cfg_register_exception(n); } - *res_start = a; - *res_finish = a; - recursive_flag = true; - break; } - default: { - kphp_error(0, fmt_format("cfg doesnt handle this type of operation: {}", static_cast(tree_node->type()))); - kphp_fail(); - return; + *res_start = try_start; + *res_finish = finish; + break; + } + + case op_function: { + auto function = tree_node.as(); + Node a, b; + create_cfg(function->param_list(), res_start, &a); + create_cfg(function->cmd(), &b, res_finish); + add_edge(a, b); + break; + } + case op_func_param_list: { + auto param_list = tree_node.as(); + Node a = new_node(); + for (auto p : param_list->params()) { + add_usage(a, new_usage(usage_read_t, p.as()->var())); } + *res_start = a; + *res_finish = a; + recursive_flag = true; + break; + } + + default: { + kphp_error(0, fmt_format("cfg doesnt handle this type of operation: {}", static_cast(tree_node->type()))); + kphp_fail(); + return; + } } add_subtree(*res_start, tree_node, recursive_flag); @@ -1047,7 +1061,7 @@ bool CFG::try_uni_usages(UsagePtr usage, UsagePtr another_usage) { VarPtr var = usage->v->var_id; VarPtr another_var = another_usage->v->var_id; if (var == another_var) { - VarSplitData &var_split = var_split_data[var]; + VarSplitData& var_split = var_split_data[var]; var_split.dsu_uni(usage, another_usage); return true; } @@ -1068,7 +1082,7 @@ void CFG::dfs_uni_rw_usages(Node v, UsagePtr usage) { for (UsagePtr another_usage : node_usages[v]) { if (try_uni_usages(usage, another_usage) && another_usage->type == usage_write_t) { - return; // stop when we reached a write usage traversing up + return; // stop when we reached a write usage traversing up } } @@ -1093,7 +1107,7 @@ void CFG::dfs_apply_type_hint(Node v, UsagePtr type_hint_usage) { for (UsagePtr another_usage : node_usages[v]) { if (another_usage->type == usage_type_hint_t && type_hint_usage != another_usage && another_usage->v->var_id == type_hint_usage->v->var_id) { - return; // stop when we reached another type hint traversing down + return; // stop when we reached another type hint traversing down } try_uni_usages(type_hint_usage, another_usage); } @@ -1145,7 +1159,7 @@ void CFG::dfs_apply_smartcasts(Node v, VarPtr var, int current_mask) { if (another_usage->v->var_id == var) { if (another_usage->type == usage_write_t || another_usage->type == usage_weak_write_t) { current_mask = ifi_any_type; - } else if (another_usage->type == usage_type_check_t) { // is_int($v), $v !== false, etc + } else if (another_usage->type == usage_type_check_t) { // is_int($v), $v !== false, etc current_mask &= another_usage->checked_type; } } @@ -1162,7 +1176,7 @@ void CFG::on_uninited_var(VertexAdaptor v) { v->var_id->set_uninited_flag(true); } -void CFG::split_var(FunctionPtr function, VarPtr var, std::vector>> &parts) { +void CFG::split_var(FunctionPtr function, VarPtr var, std::vector>>& parts) { kphp_assert(var->type() == VarData::var_local_t || var->type() == VarData::var_param_t); if (parts.empty()) { if (var->type() == VarData::var_local_t) { @@ -1180,7 +1194,7 @@ void CFG::split_var(FunctionPtr function, VarPtr var, std::vectorname + "$v" + std::to_string(i) : var->name; + const std::string& new_name = i ? var->name + "$v" + std::to_string(i) : var->name; VarPtr new_var = G->create_var(new_name, var->type()); new_var->holder_func = var->holder_func; @@ -1192,10 +1206,10 @@ void CFG::split_var(FunctionPtr function, VarPtr var, std::vectortype() == VarData::var_local_t) { function->local_var_ids.push_back(new_var); - } else { // var_param_t + } else { // var_param_t bool is_param = std::find(parts[i].begin(), parts[i].end(), params[var->param_i].as()->var()) != parts[i].end(); - if (is_param) { //union of part that contains function argument + if (is_param) { // union of part that contains function argument new_var->param_i = var->param_i; new_var->init_val = var->init_val; new_var->is_read_only = var->is_read_only; @@ -1216,7 +1230,7 @@ void CFG::split_var(FunctionPtr function, VarPtr var, std::vectortype == usage_read_t || u->type == usage_weak_write_t) { if (node_dfs[u->node] && dfs_is_uninited_usage(u->node, u)) { on_uninited_var(u->v); - break; // fire only the first uninited usage for a variable, not all usages + break; // fire only the first uninited usage for a variable, not all usages } } } @@ -1262,7 +1276,7 @@ void CFG::process_var(FunctionPtr function, VarPtr var) { size_t parts_cnt = 0; for (UsagePtr i : var_split.usages) { - if (node_dfs[i->node]) { // is used (has ever occurred in dfs searching) + if (node_dfs[i->node]) { // is used (has ever occurred in dfs searching) UsagePtr u = var_split.dsu_get(i); if (u->part_id == -1) { u->part_id = static_cast(parts_cnt++); @@ -1294,7 +1308,7 @@ void CFG::calc_used(Node v) { node_stack.pop(); node_dfs[v] = cur_dfs_step; - //fprintf (stdout, "calc_used %d\n", get_index (v)); + // fprintf (stdout, "calc_used %d\n", get_index (v)); for (VertexPtr node_subvertex : node_subvertices[v]) { node_subvertex->used_flag = true; @@ -1339,32 +1353,33 @@ class DropUnusedPass final : public FunctionPassBase { } return v; } - }; class AddSmartcastsConversionsPass final : public FunctionPassBase { - std::unordered_map, is_func_id_t> &conversions; + std::unordered_map, is_func_id_t>& conversions; + public: std::string get_description() override { return "Add conversions after checks"; } - explicit AddSmartcastsConversionsPass(std::unordered_map, is_func_id_t> &conversions) : - conversions(conversions) {} + explicit AddSmartcastsConversionsPass(std::unordered_map, is_func_id_t>& conversions) + : conversions(conversions) {} VertexPtr on_exit_vertex(VertexPtr v) override { if (v->rl_type != val_r) { return v; } if (auto var = v.try_as()) { - if (!vk::any_of_equal(var->var_id->type(), VarData::var_local_t, VarData::var_param_t) || var->var_id->is_reference || var->var_id->is_foreach_reference) { + if (!vk::any_of_equal(var->var_id->type(), VarData::var_local_t, VarData::var_param_t) || var->var_id->is_reference || + var->var_id->is_foreach_reference) { return v; } - const auto &it = conversions.find(var); + const auto& it = conversions.find(var); if (it == conversions.end()) { return v; } is_func_id_t conv = it->second; - //fprintf(stderr, "Variable %s have conv_type %d\n", var->var_id->name.c_str(), conv); + // fprintf(stderr, "Variable %s have conv_type %d\n", var->var_id->name.c_str(), conv); if (conv == 0) { kphp_warning(fmt_format("Unreachable code: variable type conditions creates contradiction for variable {}", var->get_string())); @@ -1374,7 +1389,7 @@ class AddSmartcastsConversionsPass final : public FunctionPassBase { return VertexAdaptor::create(v).set_rl_type(val_r).set_location(v); } else if (conv == ifi_is_array) { return VertexAdaptor::create(v).set_rl_type(val_r).set_location(v); - } else if (conv == (ifi_is_bool|ifi_is_false) || conv == ifi_is_bool) { + } else if (conv == (ifi_is_bool | ifi_is_false) || conv == ifi_is_bool) { return VertexAdaptor::create(v).set_rl_type(val_r).set_location(v); } else if (conv == ifi_is_float) { return VertexAdaptor::create(v).set_rl_type(val_r).set_location(v); @@ -1382,8 +1397,10 @@ class AddSmartcastsConversionsPass final : public FunctionPassBase { return VertexAdaptor::create().set_rl_type(val_r).set_location(v); } else if (conv == ifi_is_false) { return VertexAdaptor::create().set_rl_type(val_r).set_location(v); - } else if ((conv & (ifi_is_false|ifi_is_null)) == 0) { - return VertexAdaptor::create(VertexAdaptor::create(v).set_rl_type(val_r).set_location(v)).set_rl_type(val_r).set_location(v); + } else if ((conv & (ifi_is_false | ifi_is_null)) == 0) { + return VertexAdaptor::create(VertexAdaptor::create(v).set_rl_type(val_r).set_location(v)) + .set_rl_type(val_r) + .set_location(v); } else if ((conv & ifi_is_false) == 0) { return VertexAdaptor::create(v).set_rl_type(val_r).set_location(v); } else if ((conv & ifi_is_null) == 0) { @@ -1419,7 +1436,7 @@ void CFG::process_function(FunctionPtr function) { run_function_pass(function, &pass); } - for (auto var: splittable_vars) { + for (auto var : splittable_vars) { process_var(function, var); } @@ -1432,7 +1449,7 @@ void CFG::process_function(FunctionPtr function) { } } // namespace cfg -void CFGBeginF::execute(FunctionPtr function, DataStream &os) { +void CFGBeginF::execute(FunctionPtr function, DataStream& os) { stage::set_name("Calc control flow graph"); stage::set_function(function); diff --git a/compiler/pipes/cfg.h b/compiler/pipes/cfg.h index ba9c12677b..910f42147e 100644 --- a/compiler/pipes/cfg.h +++ b/compiler/pipes/cfg.h @@ -11,13 +11,13 @@ class CFGBeginF { public: - void execute(FunctionPtr function, DataStream &os); + void execute(FunctionPtr function, DataStream& os); }; // This wrapper is used to get a readable name in the profiler. class CFGBeginSync final : public SyncPipeF { public: - void on_finish(DataStream &os) final { + void on_finish(DataStream& os) final { SyncPipeF::on_finish(os); } }; diff --git a/compiler/pipes/check-abstract-function-defaults.cpp b/compiler/pipes/check-abstract-function-defaults.cpp index b4c6732aeb..34ee9e4f76 100644 --- a/compiler/pipes/check-abstract-function-defaults.cpp +++ b/compiler/pipes/check-abstract-function-defaults.cpp @@ -11,7 +11,7 @@ #include "compiler/data/function-data.h" #include "compiler/pipes/calc-real-defines-values.h" -void CheckAbstractFunctionDefaults::execute(FunctionPtr interface_function, DataStream &os) { +void CheckAbstractFunctionDefaults::execute(FunctionPtr interface_function, DataStream& os) { stage::set_function(interface_function); auto forward_function_next = vk::finally([&] { os << interface_function; }); @@ -29,7 +29,7 @@ void CheckAbstractFunctionDefaults::execute(FunctionPtr interface_function, Data auto interface_params = interface_function->get_params(); for (auto derived_class : interface_function->class_id->get_all_derived_classes()) { - auto *derived_method = derived_class->members.get_instance_method(interface_function->local_name()); + auto* derived_method = derived_class->members.get_instance_method(interface_function->local_name()); if (!derived_method || derived_method->function == interface_function) { continue; } diff --git a/compiler/pipes/check-abstract-function-defaults.h b/compiler/pipes/check-abstract-function-defaults.h index 8b9901ce94..fa9afd26be 100644 --- a/compiler/pipes/check-abstract-function-defaults.h +++ b/compiler/pipes/check-abstract-function-defaults.h @@ -9,5 +9,5 @@ class CheckAbstractFunctionDefaults { public: - void execute(FunctionPtr interface_function, DataStream &os); + void execute(FunctionPtr interface_function, DataStream& os); }; diff --git a/compiler/pipes/check-access-modifiers.cpp b/compiler/pipes/check-access-modifiers.cpp index 4e5c1736e7..24d42d0289 100644 --- a/compiler/pipes/check-access-modifiers.cpp +++ b/compiler/pipes/check-access-modifiers.cpp @@ -16,21 +16,21 @@ VertexPtr CheckAccessModifiersPass::on_enter_vertex(VertexPtr root) { if (auto var = root.try_as()) { VarPtr var_id = var->var_id; if (var_id->is_class_static_var()) { - const auto *member = var_id->as_class_static_field(); + const auto* member = var_id->as_class_static_field(); kphp_assert(member); check_access(class_id, lambda_class_id, member->modifiers, var_id->class_id, "static field", member->local_name()); } } else if (auto prop = root.try_as()) { VarPtr var_id = prop->var_id; if (var_id->is_class_instance_var()) { - const auto *member = var_id->as_class_instance_field(); + const auto* member = var_id->as_class_instance_field(); kphp_assert(member); check_access(class_id, lambda_class_id, member->modifiers, var_id->class_id, "field", member->local_name()); } } else if (auto call = root.try_as()) { FunctionPtr func_id = call->func_id; if (func_id->modifiers.is_instance() || func_id->modifiers.is_static()) { - //TODO: this is hack, which should be fixed after functions with context are added to static methods list + // TODO: this is hack, which should be fixed after functions with context are added to static methods list auto real_name = func_id->local_name().substr(0, func_id->local_name().find("$$")); if (func_id->context_class->members.has_static_method(real_name)) { check_access(class_id, lambda_class_id, func_id->modifiers, func_id->class_id, "static method", func_id); diff --git a/compiler/pipes/check-access-modifiers.h b/compiler/pipes/check-access-modifiers.h index 97325ba4fa..6a3f1008af 100644 --- a/compiler/pipes/check-access-modifiers.h +++ b/compiler/pipes/check-access-modifiers.h @@ -12,6 +12,7 @@ class CheckAccessModifiersPass final : public FunctionPassBase { private: ClassPtr class_id; ClassPtr lambda_class_id; + public: std::string get_description() override { return "Check access modifiers"; @@ -29,27 +30,23 @@ class CheckAccessModifiersPass final : public FunctionPassBase { namespace impl_ { template -const Field &get_field_name(const Field &field) { +const Field& get_field_name(const Field& field) { return field; } -inline std::string get_field_name(const FunctionPtr &field) { +inline std::string get_field_name(const FunctionPtr& field) { return field->as_human_readable(); } } // namespace impl_ template -void check_access(ClassPtr class_id, ClassPtr lambda_class_id, MemberModifier modifiers, ClassPtr access_class, const char *entity_type, const Field &field) { +void check_access(ClassPtr class_id, ClassPtr lambda_class_id, MemberModifier modifiers, ClassPtr access_class, const char* entity_type, const Field& field) { if (modifiers.is_private()) { kphp_error(class_id == access_class || lambda_class_id == access_class, fmt_format("Can't access private {} {}", entity_type, impl_::get_field_name(field))); } else if (modifiers.is_protected()) { - auto is_ok = [&access_class](ClassPtr class_id) { - return class_id && (class_id->is_parent_of(access_class) || access_class->is_parent_of(class_id)); - }; - kphp_error(is_ok(class_id) || is_ok(lambda_class_id), - fmt_format("Can't access protected {} {}", entity_type, impl_::get_field_name(field))); + auto is_ok = [&access_class](ClassPtr class_id) { return class_id && (class_id->is_parent_of(access_class) || access_class->is_parent_of(class_id)); }; + kphp_error(is_ok(class_id) || is_ok(lambda_class_id), fmt_format("Can't access protected {} {}", entity_type, impl_::get_field_name(field))); } } - diff --git a/compiler/pipes/check-classes.cpp b/compiler/pipes/check-classes.cpp index 947c3440c8..6aedff9ae0 100644 --- a/compiler/pipes/check-classes.cpp +++ b/compiler/pipes/check-classes.cpp @@ -16,16 +16,14 @@ #include "compiler/phpdoc.h" VertexPtr CheckClassesPass::on_enter_vertex(VertexPtr root) { - const auto *type_data = root->tinf_node.get_type(); + const auto* type_data = root->tinf_node.get_type(); if (auto var = root.try_as()) { type_data = var->var_id ? var->var_id->tinf_node.get_type() : type_data; } if (type_data && type_data->ptype() == tp_Class) { - const auto &class_types = type_data->class_types(); + const auto& class_types = type_data->class_types(); kphp_error(std::distance(class_types.begin(), class_types.end()) == 1, - fmt_format("Can't deduce class type, possible options are: {}", - vk::join(class_types, ", ", [](ClassPtr c) { return c->as_human_readable(); })) - ); + fmt_format("Can't deduce class type, possible options are: {}", vk::join(class_types, ", ", [](ClassPtr c) { return c->as_human_readable(); }))); } return root; @@ -44,9 +42,9 @@ inline void CheckClassesPass::analyze_class(ClassPtr klass) { check_instance_fields_inited(klass); } if (klass->can_be_php_autoloaded && !klass->is_builtin() && !klass->need_generated_stub) { - kphp_error(klass->file_id->main_function->body_seq == FunctionData::body_value::empty, - fmt_format("class {} can be autoloaded, but its file contains some logic (maybe, require_once files with global vars?)\n", - klass->as_human_readable())); + kphp_error( + klass->file_id->main_function->body_seq == FunctionData::body_value::empty, + fmt_format("class {} can be autoloaded, but its file contains some logic (maybe, require_once files with global vars?)\n", klass->as_human_readable())); } } @@ -54,7 +52,7 @@ inline void CheckClassesPass::analyze_class(ClassPtr klass) { * Check that all static class fields are properly initialized during the declaration. */ inline void CheckClassesPass::check_static_fields_inited(ClassPtr klass) { - klass->members.for_each([&](const ClassMemberStaticField &f) { + klass->members.for_each([&](const ClassMemberStaticField& f) { bool allow_no_default_value = false; // default value can be omitted for the instance values if (!f.var->init_val) { @@ -62,16 +60,14 @@ inline void CheckClassesPass::check_static_fields_inited(ClassPtr klass) { } kphp_error(f.var->init_val || allow_no_default_value, - fmt_format("static {} is not inited at declaration (inferred {})", - f.var->as_human_readable(), f.get_inferred_type()->as_human_readable())); + fmt_format("static {} is not inited at declaration (inferred {})", f.var->as_human_readable(), f.get_inferred_type()->as_human_readable())); }); } inline void CheckClassesPass::check_instance_fields_inited(ClassPtr klass) { - klass->members.for_each([](const ClassMemberInstanceField &f) { + klass->members.for_each([](const ClassMemberInstanceField& f) { PrimitiveType ptype = f.var->tinf_node.get_type()->get_real_ptype(); - kphp_error(ptype != tp_any, - fmt_format("var {} is declared but never written; please, provide a default value", f.var->as_human_readable())); + kphp_error(ptype != tp_any, fmt_format("var {} is declared but never written; please, provide a default value", f.var->as_human_readable())); }); } @@ -79,7 +75,7 @@ void CheckClassesPass::check_serialized_fields(ClassPtr klass) { used_serialization_tags_t used_serialization_tags_for_fields{false}; fill_reserved_serialization_tags(used_serialization_tags_for_fields, klass); - klass->members.for_each([&](ClassMemberInstanceField &f) { + klass->members.for_each([&](ClassMemberInstanceField& f) { auto kphp_serialized_field_tag = f.phpdoc ? f.phpdoc->find_tag(PhpDocType::kphp_serialized_field) : nullptr; if (!kphp_serialized_field_tag) { kphp_error(!klass->is_serializable, fmt_format("kphp-serialized-field is required for field: {}", f.local_name())); @@ -91,12 +87,12 @@ void CheckClassesPass::check_serialized_fields(ClassPtr klass) { } std::string value = kphp_serialized_field_tag->value_as_string(); - const auto *field_type = f.root->var_id->tinf_node.get_type(); + const auto* field_type = f.root->var_id->tinf_node.get_type(); std::unordered_set classes_inside; field_type->get_all_class_types_inside(classes_inside); for (auto inner_c : classes_inside) { - kphp_error(inner_c->is_serializable, fmt_format("class {} must be serializable as it is used in field {}::{}", - TermStringFormat::paint_red(inner_c->name), klass->name, f.local_name())); + kphp_error(inner_c->is_serializable, fmt_format("class {} must be serializable as it is used in field {}::{}", TermStringFormat::paint_red(inner_c->name), + klass->name, f.local_name())); } try { @@ -114,25 +110,24 @@ void CheckClassesPass::check_serialized_fields(ClassPtr klass) { f.serialization_tag = kphp_serialized_field; f.serialize_as_float32 = f.phpdoc->has_tag(PhpDocType::kphp_serialized_float32); used_serialization_tags_for_fields[kphp_serialized_field] = true; - } catch (std::logic_error &) { + } catch (std::logic_error&) { kphp_error_return(false, fmt_format("bad kphp-serialized-field: '{}'", value)); } }); - klass->members.for_each([&](ClassMemberStaticField &f) { + klass->members.for_each([&](ClassMemberStaticField& f) { if (f.phpdoc) { - kphp_error_return(!f.phpdoc->has_tag(PhpDocType::kphp_serialized_field) && - !f.phpdoc->has_tag(PhpDocType::kphp_serialized_float32), + kphp_error_return(!f.phpdoc->has_tag(PhpDocType::kphp_serialized_field) && !f.phpdoc->has_tag(PhpDocType::kphp_serialized_float32), fmt_format("kphp-serialized-field is allowed only for instance fields: {}", f.local_name())); } }); } -void CheckClassesPass::fill_reserved_serialization_tags(used_serialization_tags_t &used_serialization_tags_for_fields, ClassPtr klass) { +void CheckClassesPass::fill_reserved_serialization_tags(used_serialization_tags_t& used_serialization_tags_for_fields, ClassPtr klass) { if (!klass->phpdoc) { return; } - if (const PhpDocTag *reserved_ids = klass->phpdoc->find_tag(PhpDocType::kphp_reserved_fields)) { + if (const PhpDocTag* reserved_ids = klass->phpdoc->find_tag(PhpDocType::kphp_reserved_fields)) { vk::string_view ids = reserved_ids->value; kphp_error_return(ids.size() >= 2 && ids[0] == '[' && ids[ids.size() - 1] == ']', "reserved tags must be wrapped by []"); ids = ids.substr(1, ids.size() - 2); @@ -140,9 +135,9 @@ void CheckClassesPass::fill_reserved_serialization_tags(used_serialization_tags_ for (auto id_str : split_skipping_delimeters(ids, ",")) { int id; kphp_error_return(sscanf(id_str.data(), "%d", &id) == 1, "tag expected"); - kphp_error_return(0 <= id && id < max_serialization_tag_value, fmt_format("kphp-reserved-field({}) must be >=0 and < than {}", id, max_serialization_tag_value + 0)); + kphp_error_return(0 <= id && id < max_serialization_tag_value, + fmt_format("kphp-reserved-field({}) must be >=0 and < than {}", id, max_serialization_tag_value + 0)); used_serialization_tags_for_fields[id] = true; } } } - diff --git a/compiler/pipes/check-classes.h b/compiler/pipes/check-classes.h index 28b4218cf1..1c3a8a2833 100644 --- a/compiler/pipes/check-classes.h +++ b/compiler/pipes/check-classes.h @@ -21,7 +21,7 @@ class CheckClassesPass final : public FunctionPassBase { static void check_serialized_fields(ClassPtr klass); - static void fill_reserved_serialization_tags(used_serialization_tags_t &used_serialization_tags_for_fields, ClassPtr klass); + static void fill_reserved_serialization_tags(used_serialization_tags_t& used_serialization_tags_for_fields, ClassPtr klass); public: std::string get_description() override { diff --git a/compiler/pipes/check-conversions.cpp b/compiler/pipes/check-conversions.cpp index 12d5ce51e9..54ebbe849c 100644 --- a/compiler/pipes/check-conversions.cpp +++ b/compiler/pipes/check-conversions.cpp @@ -7,64 +7,63 @@ #include "compiler/inferring/public.h" const std::multimap CheckConversionsPass::forbidden_conversions = { - {op_conv_int, tp_Class}, - {op_conv_int_l, tp_Class}, - {op_conv_float, tp_Class}, -// {op_conv_string, tp_Class}, // allowed for classes with __toString() - {op_conv_string_l, tp_Class}, - {op_conv_array, tp_Class}, - {op_conv_array_l, tp_Class}, - {op_conv_object, tp_Class}, - {op_conv_mixed, tp_Class}, - {op_conv_regexp, tp_Class}, + {op_conv_int, tp_Class}, + {op_conv_int_l, tp_Class}, + {op_conv_float, tp_Class}, + // {op_conv_string, tp_Class}, // allowed for classes with __toString() + {op_conv_string_l, tp_Class}, + {op_conv_array, tp_Class}, + {op_conv_array_l, tp_Class}, + {op_conv_object, tp_Class}, + {op_conv_mixed, tp_Class}, + {op_conv_regexp, tp_Class}, - {op_conv_int, tp_array}, - {op_conv_int_l, tp_array}, - {op_conv_float, tp_array}, - {op_conv_string, tp_array}, - {op_conv_string_l, tp_array}, - {op_conv_object, tp_array}, + {op_conv_int, tp_array}, + {op_conv_int_l, tp_array}, + {op_conv_float, tp_array}, + {op_conv_string, tp_array}, + {op_conv_string_l, tp_array}, + {op_conv_object, tp_array}, - {op_conv_bool, tp_tuple}, - {op_conv_int, tp_tuple}, - {op_conv_int_l, tp_tuple}, - {op_conv_float, tp_tuple}, - {op_conv_string, tp_tuple}, - {op_conv_string_l, tp_tuple}, - {op_conv_object, tp_tuple}, - {op_conv_regexp, tp_tuple}, + {op_conv_bool, tp_tuple}, + {op_conv_int, tp_tuple}, + {op_conv_int_l, tp_tuple}, + {op_conv_float, tp_tuple}, + {op_conv_string, tp_tuple}, + {op_conv_string_l, tp_tuple}, + {op_conv_object, tp_tuple}, + {op_conv_regexp, tp_tuple}, - {op_conv_bool, tp_shape}, - {op_conv_int, tp_shape}, - {op_conv_int_l, tp_shape}, - {op_conv_float, tp_shape}, - {op_conv_string, tp_shape}, - {op_conv_string_l, tp_shape}, - {op_conv_array, tp_shape}, - {op_conv_array_l, tp_shape}, - {op_conv_object, tp_shape}, - {op_conv_mixed, tp_shape}, - {op_conv_regexp, tp_shape}, + {op_conv_bool, tp_shape}, + {op_conv_int, tp_shape}, + {op_conv_int_l, tp_shape}, + {op_conv_float, tp_shape}, + {op_conv_string, tp_shape}, + {op_conv_string_l, tp_shape}, + {op_conv_array, tp_shape}, + {op_conv_array_l, tp_shape}, + {op_conv_object, tp_shape}, + {op_conv_mixed, tp_shape}, + {op_conv_regexp, tp_shape}, }; VertexPtr CheckConversionsPass::on_enter_vertex(VertexPtr vertex) { if (forbidden_conversions.count(vertex->type())) { auto range = forbidden_conversions.equal_range(vertex->type()); - const auto *converted_expr_type = tinf::get_type(vertex.as()->expr()); + const auto* converted_expr_type = tinf::get_type(vertex.as()->expr()); if (vertex->type() == op_conv_mixed) { converted_expr_type = converted_expr_type->get_deepest_type_of_array(); } - auto is_forbidden_conversion = std::any_of(range.first, range.second, [=](auto &operation_and_type) { + auto is_forbidden_conversion = std::any_of(range.first, range.second, [=](auto& operation_and_type) { // we do this so the op_conv_bool doesn't report T|false and T|null, but report T. bool is_conversion_of_optional = operation_and_type.first == op_conv_bool && converted_expr_type->use_optional(); return !is_conversion_of_optional && converted_expr_type->ptype() == operation_and_type.second; }); - kphp_error(!is_forbidden_conversion, fmt_format("conversion from {} to {} is forbidden", - converted_expr_type->as_human_readable(), + kphp_error(!is_forbidden_conversion, fmt_format("conversion from {} to {} is forbidden", converted_expr_type->as_human_readable(), TermStringFormat::paint_green(OpInfo::str(vertex->type())))); } return vertex; diff --git a/compiler/pipes/check-conversions.h b/compiler/pipes/check-conversions.h index 6bdfa63ac5..ca6e4c3350 100644 --- a/compiler/pipes/check-conversions.h +++ b/compiler/pipes/check-conversions.h @@ -9,6 +9,7 @@ // This pipe forbids suspicious conversions (op_conv*) after the type inference. class CheckConversionsPass final : public FunctionPassBase { static const std::multimap forbidden_conversions; + public: std::string get_description() override { return "CheckConversions"; diff --git a/compiler/pipes/check-func-calls-and-vararg.cpp b/compiler/pipes/check-func-calls-and-vararg.cpp index d9fadb3076..e3235e64c7 100644 --- a/compiler/pipes/check-func-calls-and-vararg.cpp +++ b/compiler/pipes/check-func-calls-and-vararg.cpp @@ -4,11 +4,11 @@ #include "compiler/pipes/check-func-calls-and-vararg.h" -#include "compiler/modulite-check-rules.h" #include "compiler/data/src-file.h" +#include "compiler/modulite-check-rules.h" #include "compiler/rewrite-rules/replace-extern-func-calls.h" -#include "compiler/vertex-util.h" #include "compiler/type-hint.h" +#include "compiler/vertex-util.h" /* * This pass checks that func calls are correct, i.e. provided necessary amount of arguments, etc. @@ -159,7 +159,8 @@ VertexAdaptor CheckFuncCallsAndVarargPass::process_varargs(VertexA } // when calling f($arg) like f() (without $arg), then maybe, this $arg is auto-filled -VertexPtr CheckFuncCallsAndVarargPass::maybe_autofill_missing_call_arg(VertexAdaptor call, [[maybe_unused]] FunctionPtr f_called, VertexAdaptor param) { +VertexPtr CheckFuncCallsAndVarargPass::maybe_autofill_missing_call_arg(VertexAdaptor call, [[maybe_unused]] FunctionPtr f_called, + VertexAdaptor param) { if (param->type_hint == nullptr) { return {}; } @@ -167,7 +168,7 @@ VertexPtr CheckFuncCallsAndVarargPass::maybe_autofill_missing_call_arg(VertexAda // CompileTimeLocation is a built-in KPHP class // in PHP, we declare f(CompileTimeLocation $loc = null) and just call f() // in KPHP, we implicitly replace f() with f(new CompileTimeLocation(__FILE__, __METHOD__, __LINE__)) - if (const auto *as_instance = param->type_hint->unwrap_optional()->try_as()) { + if (const auto* as_instance = param->type_hint->unwrap_optional()->try_as()) { if (as_instance->resolve()->name == "CompileTimeLocation" && param->has_default_value()) { return CheckFuncCallsAndVarargPass::create_CompileTimeLocation_call_arg(call->location); } @@ -177,7 +178,7 @@ VertexPtr CheckFuncCallsAndVarargPass::maybe_autofill_missing_call_arg(VertexAda } // create constructor call: new CompileTimeLocation(__RELATIVE_FILE__, __METHOD__, __LINE__) -VertexPtr CheckFuncCallsAndVarargPass::create_CompileTimeLocation_call_arg(const Location &call_location) { +VertexPtr CheckFuncCallsAndVarargPass::create_CompileTimeLocation_call_arg(const Location& call_location) { ClassPtr klass_CompileTimeLocation = G->get_class("CompileTimeLocation"); kphp_assert(klass_CompileTimeLocation); @@ -185,12 +186,11 @@ VertexPtr CheckFuncCallsAndVarargPass::create_CompileTimeLocation_call_arg(const v_file->str_val = call_location.get_file()->relative_file_name; auto v_function = VertexAdaptor::create().set_location(call_location); - if (current_function->is_lambda()) { // like tok_method_c in gentree (PHP polyfill also emits the same format) + if (current_function->is_lambda()) { // like tok_method_c in gentree (PHP polyfill also emits the same format) v_function->str_val = "{closure}"; } else if (!current_function->is_main_function()) { - v_function->str_val = !current_function->modifiers.is_nonmember() - ? current_function->class_id->name + "::" + current_function->local_name() - : current_function->name; + v_function->str_val = + !current_function->modifiers.is_nonmember() ? current_function->class_id->name + "::" + current_function->local_name() : current_function->name; } auto v_line = VertexUtil::create_int_const(call_location.get_line()); @@ -204,13 +204,12 @@ VertexPtr CheckFuncCallsAndVarargPass::create_CompileTimeLocation_call_arg(const return v_loc; } - // check func call, that a call is valid (not abstract, etc) and provided a valid number of arguments // also, check the number of arguments passed as callbacks to extern functions VertexPtr CheckFuncCallsAndVarargPass::on_func_call(VertexAdaptor call) { FunctionPtr f = call->func_id; if (!f) { - return call; // an error has already been printed when it wasn't set + return call; // an error has already been printed when it wasn't set } if (f->is_extern()) { @@ -230,24 +229,20 @@ VertexPtr CheckFuncCallsAndVarargPass::on_func_call(VertexAdaptor } // if f_called is f(...$args) or call is f(...[1,2]), then resample called arguments - bool has_variadic_arg = vk::any_of(call->args(), [](VertexPtr arg) { - return arg->type() == op_varg; - }); + bool has_variadic_arg = vk::any_of(call->args(), [](VertexPtr arg) { return arg->type() == op_varg; }); if (f->has_variadic_param || has_variadic_arg) { call = process_varargs(call, call->func_id); } if (f->modifiers.is_static()) { - kphp_error(call->extra_type != op_ex_func_call_arrow, - fmt_format("Called static method {}() using -> (need to use ::)", f->as_human_readable())); + kphp_error(call->extra_type != op_ex_func_call_arrow, fmt_format("Called static method {}() using -> (need to use ::)", f->as_human_readable())); } if (f->modifiers.is_instance()) { kphp_error(call->extra_type == op_ex_func_call_arrow || call->extra_type == op_ex_constructor_call, fmt_format("Non-static method {}() is called statically (use ->, not ::)", f->as_human_readable())); } if (f->modifiers.is_abstract()) { - kphp_error(f->is_virtual_method, - fmt_format("Can not call an abstract method {}()", f->as_human_readable())); + kphp_error(f->is_virtual_method, fmt_format("Can not call an abstract method {}()", f->as_human_readable())); } VertexRange func_params = f->get_params(); @@ -266,12 +261,14 @@ VertexPtr CheckFuncCallsAndVarargPass::on_func_call(VertexAdaptor } int call_n_params = call_params.size(); - int delta_this = f->has_implicit_this_arg() ? 1 : 0; // not to count implicit $this on error output + int delta_this = f->has_implicit_this_arg() ? 1 : 0; // not to count implicit $this on error output kphp_error(call_n_params >= f->get_min_argn(), - fmt_format("Too few arguments in call to {}(), expected {}, have {}", TermStringFormat::paint_bold(f->as_human_readable()), f->get_min_argn() - delta_this, call_n_params - delta_this)); + fmt_format("Too few arguments in call to {}(), expected {}, have {}", TermStringFormat::paint_bold(f->as_human_readable()), + f->get_min_argn() - delta_this, call_n_params - delta_this)); kphp_error(func_params.size() >= call_n_params, - fmt_format("Too many arguments in call to {}(), expected {}, have {}", TermStringFormat::paint_bold(f->as_human_readable()), func_params.size() - delta_this, call_n_params - delta_this)); + fmt_format("Too many arguments in call to {}(), expected {}, have {}", TermStringFormat::paint_bold(f->as_human_readable()), + func_params.size() - delta_this, call_n_params - delta_this)); for (int i = 0; i < call_params.size() && i < func_params.size(); ++i) { auto func_param = func_params[i].as(); @@ -279,14 +276,16 @@ VertexPtr CheckFuncCallsAndVarargPass::on_func_call(VertexAdaptor if (f->is_extern() && func_param->type_hint && call_arg->type() == op_callback_of_builtin) { if (FunctionPtr f_callback = call_arg.as()->func_id) { - const auto *typed_callable = func_param->type_hint->try_as(); + const auto* typed_callable = func_param->type_hint->try_as(); int call_n_params = typed_callable->arg_types.size() + call_arg.as()->args().size(); int delta_this = f_callback->has_implicit_this_arg() ? 1 : 0; auto expected_callback_signature = typed_callable->as_human_readable(); kphp_error(call_n_params >= f_callback->get_min_argn(), - fmt_format("Too many arguments for callback ({}), expected {}, have {}", expected_callback_signature, call_n_params - delta_this, f_callback->get_min_argn() - delta_this)); + fmt_format("Too many arguments for callback ({}), expected {}, have {}", expected_callback_signature, call_n_params - delta_this, + f_callback->get_min_argn() - delta_this)); kphp_error(f_callback->get_params().size() >= call_n_params, - fmt_format("Too few arguments for callback ({}), expected {}, have {}", expected_callback_signature, call_n_params - delta_this, f_callback->get_params().size() - delta_this)); + fmt_format("Too few arguments for callback ({}), expected {}, have {}", expected_callback_signature, call_n_params - delta_this, + f_callback->get_params().size() - delta_this)); for (auto p : f_callback->get_params()) { kphp_error(!p.as()->var()->ref_flag, "You can't pass callbacks with &references to built-in functions"); @@ -301,7 +300,7 @@ VertexPtr CheckFuncCallsAndVarargPass::on_func_call(VertexAdaptor if (f->type == FunctionData::func_local && !is_instance_call) { // static::f() (and some other cases) could be earlier replaced by Base::f(static=Derived) if (f->modifiers.is_static() && f->context_class && f->outer_function) { - f = f->outer_function; // refs back to Base::f() + f = f->outer_function; // refs back to Base::f() } modulite_check_when_call_function(current_function, f); } else if (f->type == FunctionData::func_local && is_constructor_call) { diff --git a/compiler/pipes/check-func-calls-and-vararg.h b/compiler/pipes/check-func-calls-and-vararg.h index 30f8e65ede..ab70f943b1 100644 --- a/compiler/pipes/check-func-calls-and-vararg.h +++ b/compiler/pipes/check-func-calls-and-vararg.h @@ -11,7 +11,7 @@ class CheckFuncCallsAndVarargPass final : public FunctionPassBase { VertexAdaptor process_varargs(VertexAdaptor call, FunctionPtr f_called); VertexPtr maybe_autofill_missing_call_arg(VertexAdaptor call, FunctionPtr f_called, VertexAdaptor param); - VertexPtr create_CompileTimeLocation_call_arg(const Location &call_location); + VertexPtr create_CompileTimeLocation_call_arg(const Location& call_location); public: std::string get_description() override { diff --git a/compiler/pipes/check-modifications-of-const-vars.cpp b/compiler/pipes/check-modifications-of-const-vars.cpp index 49b78595a1..54fb921c0a 100644 --- a/compiler/pipes/check-modifications-of-const-vars.cpp +++ b/compiler/pipes/check-modifications-of-const-vars.cpp @@ -34,103 +34,101 @@ void CheckModificationsOfConstVars::check_modifications(VertexPtr v, bool write_ } switch (v->type()) { - case op_ffi_array_set: { - auto array_set = v.as(); - check_modifications(array_set->array(), true); - check_modifications(array_set->key(), false); - check_modifications(array_set->value(), false); - break; - } - case op_ffi_array_get: { - // ffi_array_get returns a non-const reference to the element - auto array_get = v.as(); - check_modifications(array_get->array(), true); - check_modifications(array_get->key(), false); - break; - } + case op_ffi_array_set: { + auto array_set = v.as(); + check_modifications(array_set->array(), true); + check_modifications(array_set->key(), false); + check_modifications(array_set->value(), false); + break; + } + case op_ffi_array_get: { + // ffi_array_get returns a non-const reference to the element + auto array_get = v.as(); + check_modifications(array_get->array(), true); + check_modifications(array_get->key(), false); + break; + } - case op_prefix_inc: - case op_postfix_inc: - case op_prefix_dec: - case op_postfix_dec: - case op_conv_array_l: - case op_conv_int_l: - case op_conv_string_l: - return check_modifications(v.as()->expr(), true); - - case op_foreach: { - auto foreach_param = v.as()->params(); - if (foreach_param->x()->ref_flag) { - check_modifications(foreach_param->xs(), true); - } - check_modifications(foreach_param->x(), true); + case op_prefix_inc: + case op_postfix_inc: + case op_prefix_dec: + case op_postfix_dec: + case op_conv_array_l: + case op_conv_int_l: + case op_conv_string_l: + return check_modifications(v.as()->expr(), true); + + case op_foreach: { + auto foreach_param = v.as()->params(); + if (foreach_param->x()->ref_flag) { + check_modifications(foreach_param->xs(), true); + } + check_modifications(foreach_param->x(), true); - if (foreach_param->has_key()) { - check_modifications(foreach_param->key(), true); - } - break; + if (foreach_param->has_key()) { + check_modifications(foreach_param->key(), true); } + break; + } - case op_func_call: { - FunctionPtr func = v.as()->func_id; - if (!func) { - return; - } + case op_func_call: { + FunctionPtr func = v.as()->func_id; + if (!func) { + return; + } - auto func_call = v.as(); - auto cnt_params = func_call->args().size(); - for (int i = 0; i < cnt_params; ++i) { - auto param = func->get_params()[i].try_as(); - if (param && param->var()->ref_flag) { - check_modifications(func_call->args()[i], true); - } + auto func_call = v.as(); + auto cnt_params = func_call->args().size(); + for (int i = 0; i < cnt_params; ++i) { + auto param = func->get_params()[i].try_as(); + if (param && param->var()->ref_flag) { + check_modifications(func_call->args()[i], true); } - break; } + break; + } - case op_index: - return check_modifications(v.as()->array(), write_flag); + case op_index: + return check_modifications(v.as()->array(), write_flag); - case op_list: { - for (auto lhs_var_in_list : v.as()->list()) { - const auto kv = lhs_var_in_list.as(); - check_modifications(kv->var(), true); - } - break; + case op_list: { + for (auto lhs_var_in_list : v.as()->list()) { + const auto kv = lhs_var_in_list.as(); + check_modifications(kv->var(), true); } + break; + } - case op_var: - case op_instance_prop: { - if (write_flag) { - if (auto const_var = v->type() == op_var ? v.as()->var_id : v.as()->var_id) { - const_var->is_read_only = false; - if (!const_var->marked_as_const) { - return; - } - const bool modification_allowed = const_var->class_id && - const_var->class_id->construct_function == current_function && - v->type() == op_instance_prop && - v.as()->instance()->get_string() == "this"; - static constexpr auto constant_prefix = "d$"; - - if (vk::string_view(const_var->name).starts_with(constant_prefix)) { // constant - kphp_error(modification_allowed, - fmt_format("Modification of constant: {}", - TermStringFormat::paint(std::string(std::next(const_var->name.begin(), std::strlen(constant_prefix)), const_var->name.end()), - TermStringFormat::red))); - } else { - kphp_error(modification_allowed, fmt_format("Modification of const variable: {}", TermStringFormat::paint(const_var->name, TermStringFormat::red))); - } + case op_var: + case op_instance_prop: { + if (write_flag) { + if (auto const_var = v->type() == op_var ? v.as()->var_id : v.as()->var_id) { + const_var->is_read_only = false; + if (!const_var->marked_as_const) { + return; + } + const bool modification_allowed = const_var->class_id && const_var->class_id->construct_function == current_function && v->type() == op_instance_prop && + v.as()->instance()->get_string() == "this"; + static constexpr auto constant_prefix = "d$"; + + if (vk::string_view(const_var->name).starts_with(constant_prefix)) { // constant + kphp_error(modification_allowed, + fmt_format("Modification of constant: {}", + TermStringFormat::paint(std::string(std::next(const_var->name.begin(), std::strlen(constant_prefix)), const_var->name.end()), + TermStringFormat::red))); + } else { + kphp_error(modification_allowed, fmt_format("Modification of const variable: {}", TermStringFormat::paint(const_var->name, TermStringFormat::red))); } } - break; } + break; + } - case op_unset: { - return check_modifications(v.as()->expr(), true); - } + case op_unset: { + return check_modifications(v.as()->expr(), true); + } - default: - return; + default: + return; } } diff --git a/compiler/pipes/check-modifications-of-const-vars.h b/compiler/pipes/check-modifications-of-const-vars.h index c2bdc6244b..7d1278f787 100644 --- a/compiler/pipes/check-modifications-of-const-vars.h +++ b/compiler/pipes/check-modifications-of-const-vars.h @@ -21,4 +21,3 @@ class CheckModificationsOfConstVars final : public FunctionPassBase { private: void check_modifications(VertexPtr v, bool write_flag = false) const; }; - diff --git a/compiler/pipes/check-nested-foreach.cpp b/compiler/pipes/check-nested-foreach.cpp index 5c87151b16..192a0ce8bf 100644 --- a/compiler/pipes/check-nested-foreach.cpp +++ b/compiler/pipes/check-nested-foreach.cpp @@ -24,15 +24,13 @@ VarPtr get_non_local_scope_visible_var(VertexAdaptor params) n } VertexPtr CheckNestedForeachPass::on_enter_vertex(VertexPtr vertex) { - auto already_used = [&](VarPtr v) { - return vk::contains(foreach_vars_, v) || vk::contains(foreach_key_vars_, v); - }; + auto already_used = [&](VarPtr v) { return vk::contains(foreach_vars_, v) || vk::contains(foreach_key_vars_, v); }; if (auto foreach_v = vertex.try_as()) { auto params = foreach_v->params(); auto x = params->x(); if (already_used(x->var_id)) { - kphp_warning (fmt_format("Foreach key {} shadows key or value of outer foreach", - TermStringFormat::add_text_attribute("&$" + x->var_id->name, TermStringFormat::bold))); + kphp_warning(fmt_format("Foreach key {} shadows key or value of outer foreach", + TermStringFormat::add_text_attribute("&$" + x->var_id->name, TermStringFormat::bold))); } foreach_vars_.push_back(x->var_id); if (x->ref_flag) { @@ -41,8 +39,8 @@ VertexPtr CheckNestedForeachPass::on_enter_vertex(VertexPtr vertex) { if (params->has_key()) { auto key = params->key(); if (already_used(key->var_id)) { - kphp_warning (fmt_format("Foreach key {} shadows key or value of outer foreach", - TermStringFormat::add_text_attribute("&$" + key->var_id->name, TermStringFormat::bold))); + kphp_warning(fmt_format("Foreach key {} shadows key or value of outer foreach", + TermStringFormat::add_text_attribute("&$" + key->var_id->name, TermStringFormat::bold))); } foreach_key_vars_.push_back(key->var_id); } diff --git a/compiler/pipes/check-restrictions.h b/compiler/pipes/check-restrictions.h index 51091186d3..96b7a82eff 100644 --- a/compiler/pipes/check-restrictions.h +++ b/compiler/pipes/check-restrictions.h @@ -13,10 +13,11 @@ class CheckRestrictionsF final : public SyncPipeF { using Base = SyncPipeF; + public: CheckRestrictionsF() = default; - void on_finish(DataStream &os) final { + void on_finish(DataStream& os) final { tinf::get_inferer()->check_restrictions(); tinf::get_inferer()->finish(); Base::on_finish(os); diff --git a/compiler/pipes/check-tl-classes.cpp b/compiler/pipes/check-tl-classes.cpp index 482ed41ade..ea9ebfd48e 100644 --- a/compiler/pipes/check-tl-classes.cpp +++ b/compiler/pipes/check-tl-classes.cpp @@ -11,29 +11,26 @@ namespace { -void verify_class_against_repr(ClassPtr class_id, const vk::tl::PhpClassRepresentation &repr) { +void verify_class_against_repr(ClassPtr class_id, const vk::tl::PhpClassRepresentation& repr) { kphp_error_return(repr.is_builtin == class_id->is_builtin(), fmt_format("Tl-class '{}' is{} expected to be builtin", class_id->name, repr.is_builtin ? "" : "not")); kphp_error_return(class_id->is_interface() == repr.is_interface, fmt_format("Tl-class '{}' is{} expected to be an interface", class_id->name, repr.is_interface ? "" : " not")); - for (const auto &child : class_id->derived_classes) { + for (const auto& child : class_id->derived_classes) { kphp_error_return(child->phpdoc->has_tag(PhpDocType::kphp_tl_class), - fmt_format("Class '{}' is expected to be tl-class, because it inherits from tl-class '{}'", - child->name, class_id->name)); + fmt_format("Class '{}' is expected to be tl-class, because it inherits from tl-class '{}'", child->name, class_id->name)); } if (repr.parent) { const std::string expected = repr.parent->php_class_namespace + "\\" + repr.parent->php_class_name; - kphp_error_return(class_id->implements.size() == 1, - fmt_format("Tl-class '{}' must inherit '{}'", class_id->name, expected)); + kphp_error_return(class_id->implements.size() == 1, fmt_format("Tl-class '{}' must inherit '{}'", class_id->name, expected)); const vk::string_view got{class_id->implements.front()->name}; - kphp_error_return(got.ends_with(expected), - fmt_format("Tl-class '{}' must inherit '{}', but it inherits '{}'", class_id->name, expected, got)); + kphp_error_return(got.ends_with(expected), fmt_format("Tl-class '{}' must inherit '{}', but it inherits '{}'", class_id->name, expected, got)); } - for (const auto &field : repr.class_fields) { - const auto *member = class_id->members.find_by_local_name(field.field_name); + for (const auto& field : repr.class_fields) { + const auto* member = class_id->members.find_by_local_name(field.field_name); kphp_error_return(member, fmt_format("Can't find field '{}' in tl-class '{}'", field.field_name, class_id->name)); } } @@ -41,13 +38,11 @@ void verify_class_against_repr(ClassPtr class_id, const vk::tl::PhpClassRepresen void check_class(ClassPtr class_id) { if (class_id->is_tl_class) { const size_t pos = class_id->name.find(vk::tl::PhpClasses::tl_namespace()); - kphp_error_return(pos != std::string::npos, - fmt_format("Bad tl-class '{}' namespace", class_id->name)); + kphp_error_return(pos != std::string::npos, fmt_format("Bad tl-class '{}' namespace", class_id->name)); std::string tl_class_name = class_id->name.substr(pos); - const auto &tl_php_classes = G->get_tl_classes().get_php_classes(); + const auto& tl_php_classes = G->get_tl_classes().get_php_classes(); auto tl_class_php_repr_it = tl_php_classes.all_classes.find(tl_class_name); - kphp_error_return(tl_class_php_repr_it != tl_php_classes.all_classes.end(), - fmt_format("Can't find tl-class '{}' in schema", class_id->name)); + kphp_error_return(tl_class_php_repr_it != tl_php_classes.all_classes.end(), fmt_format("Can't find tl-class '{}' in schema", class_id->name)); verify_class_against_repr(class_id, tl_class_php_repr_it->second.get()); } } diff --git a/compiler/pipes/check-type-hint-variance.cpp b/compiler/pipes/check-type-hint-variance.cpp index 7a8fe7cec6..c390820a7a 100644 --- a/compiler/pipes/check-type-hint-variance.cpp +++ b/compiler/pipes/check-type-hint-variance.cpp @@ -13,16 +13,16 @@ namespace { FunctionPtr get_derived_method(FunctionPtr base_function, ClassPtr derived_class) { if (base_function->modifiers.is_static()) { - auto *member = derived_class->members.get_static_method(base_function->local_name()); + auto* member = derived_class->members.get_static_method(base_function->local_name()); return member ? member->function : FunctionPtr{}; } - auto *member = derived_class->members.get_instance_method(base_function->local_name()); + auto* member = derived_class->members.get_instance_method(base_function->local_name()); return member ? member->function : FunctionPtr{}; } } // namespace -void CheckTypeHintVariance::execute(FunctionPtr f, DataStream &os) { +void CheckTypeHintVariance::execute(FunctionPtr f, DataStream& os) { stage::set_name("Child method signature check"); stage::set_function(f); stage::set_line(f->root->get_location().line); @@ -48,7 +48,7 @@ void CheckTypeHintVariance::execute(FunctionPtr f, DataStream &os) // // we do an actual type checking in GenerateVirtualMethods pass - for (const auto &derived_class : f->class_id->derived_classes) { + for (const auto& derived_class : f->class_id->derived_classes) { const FunctionPtr derived_f = get_derived_method(f, derived_class); if (!derived_f) { continue; @@ -56,13 +56,11 @@ void CheckTypeHintVariance::execute(FunctionPtr f, DataStream &os) // if a base method has a return type hint, derived method should have it too kphp_error(!f->return_typehint || derived_f->return_typehint, - fmt_format("{}() should provide a return type hint compatible with {}()", - derived_f->as_human_readable(), - f->as_human_readable())); + fmt_format("{}() should provide a return type hint compatible with {}()", derived_f->as_human_readable(), f->as_human_readable())); // if base methods doesn't have a param type hint, derived method can't have it too - const auto ¶ms = f->get_params(); - const auto &derived_params = derived_f->get_params(); + const auto& params = f->get_params(); + const auto& derived_params = derived_f->get_params(); if (params.size() != derived_params.size()) { continue; } @@ -71,11 +69,8 @@ void CheckTypeHintVariance::execute(FunctionPtr f, DataStream &os) auto p = params[i].as(); auto derived_p = derived_params[i].as(); if (!p->type_hint) { - kphp_error(!derived_p->type_hint, - fmt_format("{}() should not have a ${} param type hint, it would be incompatible with {}()", - derived_f->as_human_readable(), - derived_p->var()->get_string(), - f->as_human_readable())); + kphp_error(!derived_p->type_hint, fmt_format("{}() should not have a ${} param type hint, it would be incompatible with {}()", + derived_f->as_human_readable(), derived_p->var()->get_string(), f->as_human_readable())); } } } diff --git a/compiler/pipes/check-type-hint-variance.h b/compiler/pipes/check-type-hint-variance.h index 1a395f7bfa..affcc3e752 100644 --- a/compiler/pipes/check-type-hint-variance.h +++ b/compiler/pipes/check-type-hint-variance.h @@ -22,5 +22,5 @@ // https://www.php.net/manual/en/language.oop5.variance.php class CheckTypeHintVariance { public: - void execute(FunctionPtr interface_function, DataStream &os); + void execute(FunctionPtr interface_function, DataStream& os); }; diff --git a/compiler/pipes/check-ub.cpp b/compiler/pipes/check-ub.cpp index c9a1416e89..af39cfb941 100644 --- a/compiler/pipes/check-ub.cpp +++ b/compiler/pipes/check-ub.cpp @@ -38,8 +38,7 @@ const int UB_SIGSEGV = 3; TLS last_ub_error; - -static inline bool in_set(const std::unordered_set *a, VarPtr elem) { +static inline bool in_set(const std::unordered_set* a, VarPtr elem) { if (a != nullptr && a->find(elem) != a->end()) { *last_ub_error = elem; return true; @@ -47,7 +46,7 @@ static inline bool in_set(const std::unordered_set *a, VarPtr elem) { return false; } -static bool sets_intersect(const std::unordered_set *a, const std::unordered_set *b) { +static bool sets_intersect(const std::unordered_set* a, const std::unordered_set* b) { if (a == nullptr || b == nullptr) { return false; } @@ -59,16 +58,15 @@ static bool sets_intersect(const std::unordered_set *a, const std::unord return false; } -bool is_same_var(const VarPtr &a, const VarPtr &b) { +bool is_same_var(const VarPtr& a, const VarPtr& b) { if (a == b) { *last_ub_error = a; return true; } - return in_set(a->bad_vars, b) || in_set(b->bad_vars, a) || - sets_intersect(a->bad_vars, b->bad_vars); + return in_set(a->bad_vars, b) || in_set(b->bad_vars, a) || sets_intersect(a->bad_vars, b->bad_vars); } -bool is_var_written(const FunctionPtr &function, const VarPtr &var) { +bool is_var_written(const FunctionPtr& function, const VarPtr& var) { if (function->bad_vars == nullptr || (!var->is_in_global_scope() && var->bad_vars == nullptr)) { return false; } @@ -78,7 +76,6 @@ bool is_var_written(const FunctionPtr &function, const VarPtr &var) { return sets_intersect(var->bad_vars, function->bad_vars); } - class UBMergeData { private: std::vector writes_; @@ -87,18 +84,14 @@ class UBMergeData { std::vector functions_; template - static void check( - const std::vector &first, - const std::vector &second, - F f, - int error_mask, int *res_error) { + static void check(const std::vector& first, const std::vector& second, F f, int error_mask, int* res_error) { if ((*res_error & error_mask) == error_mask) { return; } - for (const A &a : first) { - for (const B &b : second) { + for (const A& a : first) { + for (const B& b : second) { if (f(a, b)) { *res_error |= error_mask; return; @@ -107,21 +100,21 @@ class UBMergeData { } } - static int check(const UBMergeData &first, const UBMergeData &second) { + static int check(const UBMergeData& first, const UBMergeData& second) { int err = 0; - //sigsegv + // sigsegv check(first.functions_, second.index_refs_, is_var_written, UB_SIGSEGV, &err); check(second.functions_, first.index_refs_, is_var_written, UB_SIGSEGV, &err); check(first.writes_, second.writes_, is_same_var, UB_SIGSEGV, &err); - //just ub + // just ub check(first.reads_, second.writes_, is_same_var, UB_SIGSEGV, &err); check(first.writes_, second.reads_, is_same_var, UB_SIGSEGV, &err); return err; } - static int check(const UBMergeData &data, FunctionPtr function) { + static int check(const UBMergeData& data, FunctionPtr function) { int err = 0; std::vector tmp(1, function); check(tmp, data.index_refs_, is_var_written, UB_SIGSEGV, &err); @@ -129,10 +122,9 @@ class UBMergeData { } public: - UBMergeData() { - }; + UBMergeData() {}; - int merge_with(const UBMergeData &other, bool no_check_flag) { + int merge_with(const UBMergeData& other, bool no_check_flag) { int err = 0; if (!no_check_flag) { err = check(*this, other); @@ -144,7 +136,7 @@ class UBMergeData { return err; } - int check_index_refs(const std::vector &vars) { + int check_index_refs(const std::vector& vars) { int err = 0; check(functions_, vars, is_var_written, UB_SIGSEGV, &err); check(reads_, vars, is_same_var, UB_SIGSEGV, &err); @@ -178,7 +170,7 @@ class UBMergeData { } }; -void fix_ub_dfs(VertexPtr v, UBMergeData *data, VertexPtr parent = VertexPtr()) { +void fix_ub_dfs(VertexPtr v, UBMergeData* data, VertexPtr parent = VertexPtr()) { stage::set_location(v->get_location()); *last_ub_error = VarPtr(); @@ -206,18 +198,18 @@ void fix_ub_dfs(VertexPtr v, UBMergeData *data, VertexPtr parent = VertexPtr()) stage::set_location(save_location); if (res > 0) { - bool supported = vk::any_of_equal(v->type(), op_set, op_set_value, op_push_back, op_push_back_return, op_array, op_index) - || OpInfo::rl(v->type()) == rl_set; + bool supported = + vk::any_of_equal(v->type(), op_set, op_set_value, op_push_back, op_push_back_return, op_array, op_index) || OpInfo::rl(v->type()) == rl_set; if (supported) { v->extra_type = op_ex_safe_version; } else { - kphp_warning (fmt_format("Dangerous undefined behaviour {}, [var = {}]", OpInfo::str(v->type()), (*last_ub_error)->as_human_readable())); + kphp_warning(fmt_format("Dangerous undefined behaviour {}, [var = {}]", OpInfo::str(v->type()), (*last_ub_error)->as_human_readable())); } } } } -void fix_ub(VertexPtr v, std::vector *foreach_vars) { +void fix_ub(VertexPtr v, std::vector* foreach_vars) { if (v->type() == op_global || v->type() == op_static) { return; } @@ -248,11 +240,11 @@ void fix_ub(VertexPtr v, std::vector *foreach_vars) { fix_ub_dfs(v, &data); int err = data.check_index_refs(*foreach_vars); if (err > 0) { - kphp_warning (fmt_format("Dangerous undefined behaviour {}, [foreach var = {}]", OpInfo::str(v->type()), (*last_ub_error)->as_human_readable())); + kphp_warning(fmt_format("Dangerous undefined behaviour {}, [foreach var = {}]", OpInfo::str(v->type()), (*last_ub_error)->as_human_readable())); } } -void CheckUBF::execute(FunctionPtr function, DataStream &os) { +void CheckUBF::execute(FunctionPtr function, DataStream& os) { stage::set_name("Check for undefined behaviour"); stage::set_function(function); diff --git a/compiler/pipes/check-ub.h b/compiler/pipes/check-ub.h index 253dd9f35e..dc18ca30c9 100644 --- a/compiler/pipes/check-ub.h +++ b/compiler/pipes/check-ub.h @@ -9,5 +9,5 @@ class CheckUBF { public: - void execute(FunctionPtr function, DataStream &os); + void execute(FunctionPtr function, DataStream& os); }; diff --git a/compiler/pipes/clone-nested-lambdas.h b/compiler/pipes/clone-nested-lambdas.h index 0dd7c0c2dc..5fd54d5cca 100644 --- a/compiler/pipes/clone-nested-lambdas.h +++ b/compiler/pipes/clone-nested-lambdas.h @@ -14,15 +14,15 @@ // This pass takes functions that were cloned from existing ones (base$$fname$$context, trait methods, etc). // Every op_lambda inside must point to a new function instead of an old one. class CloneNestedLambdasPass final : public FunctionPassBase { - DataStream *function_stream; + DataStream* function_stream; public: std::string get_description() override { return "Clone nested lambdas"; } - explicit CloneNestedLambdasPass(DataStream *function_stream) : - function_stream(function_stream) {} + explicit CloneNestedLambdasPass(DataStream* function_stream) + : function_stream(function_stream) {} VertexPtr on_enter_vertex(VertexPtr root) override { if (auto as_op_lambda = root.try_as()) { @@ -42,7 +42,7 @@ class CloneNestedLambdasPass final : public FunctionPassBase { return root; } - static inline void run_if_lambdas_inside(FunctionPtr cloned_function, DataStream *function_stream) { + static inline void run_if_lambdas_inside(FunctionPtr cloned_function, DataStream* function_stream) { if (cloned_function->has_lambdas_inside) { CloneNestedLambdasPass pass(function_stream); run_function_pass(cloned_function, &pass); diff --git a/compiler/pipes/clone-strange-const-params.cpp b/compiler/pipes/clone-strange-const-params.cpp index 090fc53c3c..5bbbe725c0 100644 --- a/compiler/pipes/clone-strange-const-params.cpp +++ b/compiler/pipes/clone-strange-const-params.cpp @@ -26,11 +26,12 @@ VertexPtr CloneStrangeConstParams::on_enter_vertex(VertexPtr root) { }; if (passed_params.size() > params_of_called_func.size()) { - auto msg = fmt_format("func: {}, passed_cnt: {}, params_of_func_cnt: {}\n", func_call->func_id->as_human_readable(), passed_params.size(), params_of_called_func.size()); + auto msg = fmt_format("func: {}, passed_cnt: {}, params_of_func_cnt: {}\n", func_call->func_id->as_human_readable(), passed_params.size(), + params_of_called_func.size()); kphp_assert_msg(false, msg); } for (size_t i = 0; i < passed_params.size() - func_call->func_id->has_variadic_param; ++i) { - auto &cur_passed_param = passed_params[i]; + auto& cur_passed_param = passed_params[i]; if (func_call->func_id->is_extern()) { continue; } diff --git a/compiler/pipes/code-gen.cpp b/compiler/pipes/code-gen.cpp index f2f8ba5804..d8a09e3fbf 100644 --- a/compiler/pipes/code-gen.cpp +++ b/compiler/pipes/code-gen.cpp @@ -34,7 +34,7 @@ #include "compiler/pipes/collect-forkable-types.h" #include "compiler/type-hint.h" -void CodeGenF::execute(FunctionPtr function, DataStream> &unused_os __attribute__ ((unused))) { +void CodeGenF::execute(FunctionPtr function, DataStream>& unused_os __attribute__((unused))) { if (function->does_need_codegen() || function->is_imported_from_static_lib()) { prepare_generate_function(function); G->stats.on_function_processed(function); @@ -42,7 +42,7 @@ void CodeGenF::execute(FunctionPtr function, DataStream> &os) { +void CodeGenF::on_finish(DataStream>& os) { vk::singleton::get().wait(); G->get_ffi_root().bind_symbols(); @@ -52,18 +52,18 @@ void CodeGenF::on_finish(DataStream> &os) { stage::set_file(SrcFilePtr()); stage::die_if_global_errors(); - std::forward_list all_functions = tmp_stream.flush(); // functions to codegen, order doesn't matter - const std::vector &all_classes = G->get_classes(); + std::forward_list all_functions = tmp_stream.flush(); // functions to codegen, order doesn't matter + const std::vector& all_classes = G->get_classes(); std::set all_json_encoders; std::vector all_globals = G->get_global_vars(); for (FunctionPtr f : all_functions) { all_globals.insert(all_globals.end(), f->static_var_ids.begin(), f->static_var_ids.end()); } - const GlobalsBatchedMem &all_globals_in_mem = GlobalsBatchedMem::prepare_mem_and_assign_offsets(all_globals); + const GlobalsBatchedMem& all_globals_in_mem = GlobalsBatchedMem::prepare_mem_and_assign_offsets(all_globals); std::vector all_constants = G->get_constants_vars(); - const ConstantsBatchedMem &all_constants_in_mem = ConstantsBatchedMem::prepare_mem_and_assign_offsets(all_constants); + const ConstantsBatchedMem& all_constants_in_mem = ConstantsBatchedMem::prepare_mem_and_assign_offsets(all_constants); for (FunctionPtr f : all_functions) { code_gen_start_root_task(os, std::make_unique(f)); @@ -79,19 +79,19 @@ void CodeGenF::on_finish(DataStream> &os) { } switch (c->class_type) { - case ClassType::klass: - code_gen_start_root_task(os, std::make_unique(c)); - code_gen_start_root_task(os, std::make_unique(c)); - break; - case ClassType::interface: - code_gen_start_root_task(os, std::make_unique(c)); - break; - case ClassType::ffi_scope: - code_gen_start_root_task(os, std::make_unique(c)); - break; - - default: - kphp_assert(false); + case ClassType::klass: + code_gen_start_root_task(os, std::make_unique(c)); + code_gen_start_root_task(os, std::make_unique(c)); + break; + case ClassType::interface: + code_gen_start_root_task(os, std::make_unique(c)); + break; + case ClassType::ffi_scope: + code_gen_start_root_task(os, std::make_unique(c)); + break; + + default: + kphp_assert(false); } } @@ -147,9 +147,9 @@ void CodeGenF::prepare_generate_function(FunctionPtr func) { // because original (long) function names are sometimes parsed to show proper compilation errors // (for instance, from "baseclass$$method$$contextclass" static=contextclass is parsed) if (file_name.size() > 100 && func->is_instantiation_of_generic_function()) { - for (const auto &[_, type_hint] : *func->instantiationTs) { - type_hint->traverse([&file_name, this](const TypeHint *child) { - if (const auto *as_instance = child->try_as()) { + for (const auto& [_, type_hint] : *func->instantiationTs) { + type_hint->traverse([&file_name, this](const TypeHint* child) { + if (const auto* as_instance = child->try_as()) { file_name = shorten_occurence_of_class_in_file_name(as_instance->resolve(), file_name); } }); @@ -168,20 +168,16 @@ void CodeGenF::prepare_generate_function(FunctionPtr func) { } func->header_full_name = - func->is_imported_from_static_lib() - ? func->file_id->owner_lib->headers_dir() + func->header_name - : func->subdir + "/" + func->header_name; + func->is_imported_from_static_lib() ? func->file_id->owner_lib->headers_dir() + func->header_name : func->subdir + "/" + func->header_name; - std::sort(func->local_var_ids.begin(), func->local_var_ids.end(), [](VarPtr v1, VarPtr v2) { - return v1->name.compare(v2->name) < 0; - }); + std::sort(func->local_var_ids.begin(), func->local_var_ids.end(), [](VarPtr v1, VarPtr v2) { return v1->name.compare(v2->name) < 0; }); if (func->kphp_tracing) { TracingAutogen::register_function_marked_kphp_tracing(func); } } -std::string CodeGenF::shorten_occurence_of_class_in_file_name(ClassPtr occuring_class, const std::string &file_name) { +std::string CodeGenF::shorten_occurence_of_class_in_file_name(ClassPtr occuring_class, const std::string& file_name) { size_t pos = occuring_class->name.rfind('\\'); if (pos == std::string::npos) { return file_name; @@ -216,8 +212,7 @@ std::string CodeGenF::calc_subdir_for_function(FunctionPtr func) { return "o_" + std::to_string(bucket); } - -void CodeGenForDiffF::execute(std::unique_ptr cmd, DataStream &os) { +void CodeGenForDiffF::execute(std::unique_ptr cmd, DataStream& os) { stage::set_name("Code generation for diff"); // re-launch cmd not with "calc hashes", but with "store cpp/h contents and php comments" mode diff --git a/compiler/pipes/code-gen.h b/compiler/pipes/code-gen.h index 7b3f98fae8..afabef5502 100644 --- a/compiler/pipes/code-gen.h +++ b/compiler/pipes/code-gen.h @@ -18,16 +18,16 @@ class CodeGenF final : public SyncPipeF> &unused_os) final; - void on_finish(DataStream> &os) final; + void execute(FunctionPtr function, DataStream>& unused_os) final; + void on_finish(DataStream>& os) final; }; // this pipe re-launches codegen commands that differ from previous kphp launch // now they are launches not as "just calc hashes", but as "store all cpp/h contents and php comments" class CodeGenForDiffF { public: - void execute(std::unique_ptr cmd, DataStream &os); + void execute(std::unique_ptr cmd, DataStream& os); }; diff --git a/compiler/pipes/collect-const-vars.cpp b/compiler/pipes/collect-const-vars.cpp index 7767bad996..ba7a61e1f8 100644 --- a/compiler/pipes/collect-const-vars.cpp +++ b/compiler/pipes/collect-const-vars.cpp @@ -8,13 +8,13 @@ #include "auto/compiler/vertex/vertex-types.h" #include "common/algorithms/hashes.h" +#include "compiler/compiler-core.h" +#include "compiler/const-manipulations.h" +#include "compiler/data/var-data.h" #include "compiler/data/vertex-adaptor.h" #include "compiler/kphp_assert.h" -#include "compiler/vertex-util.h" -#include "compiler/data/var-data.h" -#include "compiler/const-manipulations.h" -#include "compiler/compiler-core.h" #include "compiler/name-gen.h" +#include "compiler/vertex-util.h" namespace { @@ -157,7 +157,7 @@ struct ShouldStoreOnBottomUp : public VertexVisitor struct NameGenerator : public VertexVisitor { static constexpr auto prefix = "const_var"; - static std::string fallback(VertexPtr v[[maybe_unused]]) { + static std::string fallback(VertexPtr v [[maybe_unused]]) { return gen_unique_name(prefix); } @@ -193,67 +193,67 @@ struct NameGenerator : public VertexVisitor { private: // checks that inlined as define' value constructor is suitable to be stored as constant var static bool is_object_suitable_for_hashing(VertexPtr vertex) { - return vertex->type() == op_define_val && vertex.as()->value()->type() == op_func_call - && vertex.as()->value()->extra_type == op_ex_constructor_call && vertex->const_type == cnst_const_val; + return vertex->type() == op_define_val && vertex.as()->value()->type() == op_func_call && + vertex.as()->value()->extra_type == op_ex_constructor_call && vertex->const_type == cnst_const_val; } static bool is_array_suitable_for_hashing(VertexPtr vertex) { return vertex->type() == op_array && CheckConst::is_const(vertex); } - static std::string gen_const_string_name(const std::string &str) { + static std::string gen_const_string_name(const std::string& str) { return fmt_format("c_str${:x}", vk::std_hash(str)); } - static std::string gen_const_regexp_name(const std::string &str) { + static std::string gen_const_regexp_name(const std::string& str) { return fmt_format("c_reg${:x}", vk::std_hash(str)); } - static std::string gen_const_object_name(const VertexAdaptor &def) { + static std::string gen_const_object_name(const VertexAdaptor& def) { kphp_assert_msg(def->value()->type() == op_func_call, "Internal error: expected op_define_val "); return fmt_format("c_obj${:x}", ObjectHash::calc_hash(def)); } - static std::string gen_const_array_name(const VertexAdaptor &array) { + static std::string gen_const_array_name(const VertexAdaptor& array) { return fmt_format("c_arr${:x}", ArrayHash::calc_hash(array)); } }; struct ProcessBeforeReplace : public VertexVisitor { - static VertexPtr fallback(VertexPtr v) { - return v; - } + static VertexPtr fallback(VertexPtr v) { + return v; + } - static VertexPtr on_func_call(VertexAdaptor v) { - return remove_op_define_val(v); - } + static VertexPtr on_func_call(VertexAdaptor v) { + return remove_op_define_val(v); + } - static VertexPtr on_conv_regexp(VertexAdaptor regexp) { - return remove_op_define_val(regexp); - } + static VertexPtr on_conv_regexp(VertexAdaptor regexp) { + return remove_op_define_val(regexp); + } - static VertexPtr on_concat(VertexAdaptor concat) { - return remove_op_define_val(concat); - } + static VertexPtr on_concat(VertexAdaptor concat) { + return remove_op_define_val(concat); + } - static VertexPtr on_string_build(VertexAdaptor str_build) { - return remove_op_define_val(str_build); - } + static VertexPtr on_string_build(VertexAdaptor str_build) { + return remove_op_define_val(str_build); + } - static VertexPtr on_add(VertexAdaptor add) { - return remove_op_define_val(add); - } + static VertexPtr on_add(VertexAdaptor add) { + return remove_op_define_val(add); + } - private: - static VertexPtr remove_op_define_val(VertexPtr v) { - for (VertexPtr& sub_vertex: *v) { - sub_vertex = remove_op_define_val(sub_vertex); - } - if (auto as_op_define_val = v.try_as()) { - return as_op_define_val->value(); - } - return v; +private: + static VertexPtr remove_op_define_val(VertexPtr v) { + for (VertexPtr& sub_vertex : *v) { + sub_vertex = remove_op_define_val(sub_vertex); } + if (auto as_op_define_val = v.try_as()) { + return as_op_define_val->value(); + } + return v; + } }; int get_expr_dep_level(VertexPtr vertex) { @@ -261,7 +261,7 @@ int get_expr_dep_level(VertexPtr vertex) { return var->var_id->dependency_level; } int max_dependency_level = 0; - for (const auto &child: *vertex) { + for (const auto& child : *vertex) { max_dependency_level = std::max(max_dependency_level, get_expr_dep_level(child)); } return max_dependency_level; @@ -280,8 +280,8 @@ void set_var_dep_level(VarPtr var_id) { VertexPtr CollectConstVarsPass::on_exit_vertex(VertexPtr root) { if (root->const_type == cnst_const_val) { composite_const_depth_ -= static_cast(IsComposite::visit(root)); - if (ShouldStoreOnBottomUp::visit(root) - && !current_function->is_extern()) { // don't extract constants from extern func default arguments, they are in C++ runtime + if (ShouldStoreOnBottomUp::visit(root) && + !current_function->is_extern()) { // don't extract constants from extern func default arguments, they are in C++ runtime root = ProcessBeforeReplace::visit(root); root = create_const_variable(root, root->location); } @@ -311,7 +311,6 @@ VertexPtr CollectConstVarsPass::on_enter_vertex(VertexPtr root) { return root; } - VertexPtr CollectConstVarsPass::create_const_variable(VertexPtr root, Location loc) { std::string name = NameGenerator::visit(root); @@ -341,12 +340,12 @@ bool CollectConstVarsPass::user_recursion(VertexPtr v) { if (v->type() == op_function) { if (current_function->type == FunctionData::func_class_holder) { ClassPtr c = current_function->class_id; - c->members.for_each([&](ClassMemberInstanceField &field) { + c->members.for_each([&](ClassMemberInstanceField& field) { if (field.var->init_val) { run_function_pass(field.var->init_val, this); } }); - c->members.for_each([&](ClassMemberStaticField &field) { + c->members.for_each([&](ClassMemberStaticField& field) { if (field.var->init_val) { run_function_pass(field.var->init_val, this); } diff --git a/compiler/pipes/collect-const-vars.h b/compiler/pipes/collect-const-vars.h index 4d67597216..f1a311b467 100644 --- a/compiler/pipes/collect-const-vars.h +++ b/compiler/pipes/collect-const-vars.h @@ -24,5 +24,4 @@ class CollectConstVarsPass final : public FunctionPassBase { VertexPtr on_exit_vertex(VertexPtr root) override; bool user_recursion(VertexPtr v) override; - }; diff --git a/compiler/pipes/collect-forkable-types.cpp b/compiler/pipes/collect-forkable-types.cpp index dec13ea881..fd920901b6 100644 --- a/compiler/pipes/collect-forkable-types.cpp +++ b/compiler/pipes/collect-forkable-types.cpp @@ -35,18 +35,18 @@ void CollectForkableTypesPass::on_finish() { } } -void ForkableTypeStorage::add_types(const std::vector &waitable_types, const std::vector &forkable_types) noexcept { +void ForkableTypeStorage::add_types(const std::vector& waitable_types, const std::vector& forkable_types) noexcept { std::lock_guard lock{mutex_}; waitable_types_.insert(waitable_types_.end(), waitable_types.begin(), waitable_types.end()); forkable_types_.insert(forkable_types_.end(), forkable_types.begin(), forkable_types.end()); } -std::vector ForkableTypeStorage::flush_waitable_types() noexcept { +std::vector ForkableTypeStorage::flush_waitable_types() noexcept { std::lock_guard lock{mutex_}; return std::move(waitable_types_); } -std::vector ForkableTypeStorage::flush_forkable_types() noexcept { +std::vector ForkableTypeStorage::flush_forkable_types() noexcept { std::lock_guard lock{mutex_}; return std::move(forkable_types_); } diff --git a/compiler/pipes/collect-forkable-types.h b/compiler/pipes/collect-forkable-types.h index e08c6b42c2..76bc292770 100644 --- a/compiler/pipes/collect-forkable-types.h +++ b/compiler/pipes/collect-forkable-types.h @@ -19,23 +19,23 @@ class CollectForkableTypesPass final : public FunctionPassBase { void on_finish() final; private: - std::vector waitable_types_; - std::vector forkable_types_; + std::vector waitable_types_; + std::vector forkable_types_; }; class ForkableTypeStorage : vk::not_copyable { public: friend class vk::singleton; - void add_types(const std::vector &waitable_types, const std::vector &forkable_types) noexcept; + void add_types(const std::vector& waitable_types, const std::vector& forkable_types) noexcept; - std::vector flush_waitable_types() noexcept; - std::vector flush_forkable_types() noexcept; + std::vector flush_waitable_types() noexcept; + std::vector flush_forkable_types() noexcept; private: ForkableTypeStorage() = default; std::mutex mutex_; - std::vector waitable_types_; - std::vector forkable_types_; + std::vector waitable_types_; + std::vector forkable_types_; }; diff --git a/compiler/pipes/collect-main-edges.cpp b/compiler/pipes/collect-main-edges.cpp index 96b6510aa8..5a192fdf1d 100644 --- a/compiler/pipes/collect-main-edges.cpp +++ b/compiler/pipes/collect-main-edges.cpp @@ -4,12 +4,12 @@ #include "compiler/pipes/collect-main-edges.h" +#include "common/php-functions.h" #include "compiler/compiler-core.h" #include "compiler/data/define-data.h" #include "compiler/data/src-file.h" #include "compiler/data/var-data.h" #include "compiler/function-pass.h" -#include "compiler/vertex-util.h" #include "compiler/inferring/edge.h" #include "compiler/inferring/ifi.h" #include "compiler/inferring/public.h" @@ -18,7 +18,7 @@ #include "compiler/inferring/restriction-non-void.h" #include "compiler/inferring/type-node.h" #include "compiler/type-hint.h" -#include "common/php-functions.h" +#include "compiler/vertex-util.h" namespace { @@ -87,8 +87,8 @@ RValue CollectMainEdgesPass::as_set_value(VertexPtr v) { // an isset check will analyze expressions that may differ from PHP after getting elements from typed arrays // for example: if $a is int[], then if($a[100] === 0) may differ from PHP if 100-th element doesn't exist (null vs 0) -void CollectMainEdgesPass::create_isset_check(const RValue &rvalue) { - tinf::Node *a = rvalue.node; +void CollectMainEdgesPass::create_isset_check(const RValue& rvalue) { + tinf::Node* a = rvalue.node; tinf::get_inferer()->add_node(a); tinf::get_inferer()->add_restriction(new RestrictionIsset(a)); } @@ -98,8 +98,8 @@ void CollectMainEdgesPass::create_isset_check(const RValue &rvalue) { // lhs is VarNode (for ExprNode this has no effect, as expr nodes are recalculated in another way) // rhs is an expression (not a type!), so every time rhs is recalculated, lhs is recalculated also template -void CollectMainEdgesPass::create_set(const LValue &lhs, const R &rhs) { - tinf::Edge *edge = new tinf::Edge(); +void CollectMainEdgesPass::create_set(const LValue& lhs, const R& rhs) { + tinf::Edge* edge = new tinf::Edge(); edge->from = lhs.value; edge->from_at = lhs.key; edge->to = as_rvalue(rhs).node; @@ -112,8 +112,8 @@ void CollectMainEdgesPass::create_set(const LValue &lhs, const R &rhs) { // for example, a key in foreach is mixed // it is very similar to create_set(), but this function exists in parallel to express another semantics // btw, this edge also appears in stacktrace on type mismatch, answering "why it was inferred in such a way" -void CollectMainEdgesPass::create_type_assign(const LValue &lhs, const TypeData *initial_type) { - tinf::Edge *edge = new tinf::Edge(); +void CollectMainEdgesPass::create_type_assign(const LValue& lhs, const TypeData* initial_type) { + tinf::Edge* edge = new tinf::Edge(); edge->from = lhs.value; edge->from_at = lhs.key; edge->to = new tinf::TypeNode(initial_type, stage::get_location()); @@ -125,7 +125,7 @@ void CollectMainEdgesPass::create_type_assign(const LValue &lhs, const TypeData // it's because array_map's first argument is declared as callable(^2[*] $x) : any // as an input, we have lhs ($v), func_call (exact array_map invocation), and type_hint for lhs (^2[*]) // it's not a type assign, because tinf::TypeNode holds a constexpr type, whereas here we have a rule with call context -void CollectMainEdgesPass::create_type_assign_with_arg_ref_rule(const LValue &lhs, const TypeHint *type_hint, VertexPtr func_call) { +void CollectMainEdgesPass::create_type_assign_with_arg_ref_rule(const LValue& lhs, const TypeHint* type_hint, VertexPtr func_call) { auto recalc_trigger = VertexAdaptor::create(); // see ExprNodeRecalc recalc_trigger->type_hint = type_hint; recalc_trigger->func_call = func_call; @@ -139,12 +139,12 @@ void CollectMainEdgesPass::create_type_assign_with_arg_ref_rule(const LValue &lh // for example, function f(?int $x) — then $x is set int|null, and even if passed string to f, $x remains int|null, triggering an error // if a type contains any, e.g. array $x — then $x is set to any[], this any is inferred via other edges, but passing string triggers an error // lhs here is VarNode (it means: a variable, or a function param, or a function return) -void CollectMainEdgesPass::create_type_assign_with_restriction(const LValue &var_lhs, const TypeHint *type_hint) { - auto *restricted_node = dynamic_cast(var_lhs.value); +void CollectMainEdgesPass::create_type_assign_with_restriction(const LValue& var_lhs, const TypeHint* type_hint) { + auto* restricted_node = dynamic_cast(var_lhs.value); kphp_assert(restricted_node && var_lhs.key->empty() && type_hint->is_typedata_constexpr()); // this is just a type assign - tinf::Edge *edge = new tinf::Edge(); + tinf::Edge* edge = new tinf::Edge(); edge->from = restricted_node; edge->from_at = var_lhs.key; edge->to = new tinf::TypeNode(type_hint->to_type_data(), stage::get_location()); @@ -160,9 +160,9 @@ void CollectMainEdgesPass::create_type_assign_with_restriction(const LValue &var // therefore, we don't need to create an edge $x->$v, but after tinf has finished, we need to check that type of $v matches int|null // this is just an optimization to create less set edges: whenever $v is updated, $x recalculation is not triggered // without this, everything would still work jue to type checks, but a bit slower due to useless recalculations -void CollectMainEdgesPass::create_postponed_type_check(const RValue &restricted_value, const RValue &actual_value, const TypeHint *type_hint) { - auto *restricted_node = dynamic_cast(restricted_value.node); - auto *actual_node = actual_value.node; +void CollectMainEdgesPass::create_postponed_type_check(const RValue& restricted_value, const RValue& actual_value, const TypeHint* type_hint) { + auto* restricted_node = dynamic_cast(restricted_value.node); + auto* actual_node = actual_value.node; kphp_assert(restricted_node && actual_node && type_hint->is_typedata_constexpr()); tinf::get_inferer()->add_node(actual_node); tinf::get_inferer()->add_restriction(new RestrictionMatchPhpdoc(restricted_node, actual_node, type_hint->to_type_data())); @@ -170,33 +170,32 @@ void CollectMainEdgesPass::create_postponed_type_check(const RValue &restricted_ // a 'non-void check' will test that lhs value is not void // for example, callback of array_map isn't allowed to return void -void CollectMainEdgesPass::create_non_void(const RValue &lhs) { - tinf::Node *a = lhs.node; +void CollectMainEdgesPass::create_non_void(const RValue& lhs) { + tinf::Node* a = lhs.node; tinf::get_inferer()->add_node(a); tinf::get_inferer()->add_restriction(new RestrictionNonVoid(a)); } // create edges for ^1, ^2[*] recalculations in a context of a func call like array_map('cb', $arr); // every type call_arg ^i is recalculated ($arr for example), dependent_vertex recalculation will be triggered -void CollectMainEdgesPass::create_edges_to_recalc_arg_ref(const TypeHint *type_hint, VertexPtr dependent_vertex, VertexPtr func_call) { +void CollectMainEdgesPass::create_edges_to_recalc_arg_ref(const TypeHint* type_hint, VertexPtr dependent_vertex, VertexPtr func_call) { kphp_assert(type_hint->has_argref_inside()); - type_hint->traverse([func_call, dependent_vertex](const TypeHint *child) { + type_hint->traverse([func_call, dependent_vertex](const TypeHint* child) { VertexPtr call_arg{nullptr}; - if (const auto *as_arg_ref = child->try_as()) { + if (const auto* as_arg_ref = child->try_as()) { call_arg = VertexUtil::get_call_arg_ref(as_arg_ref->arg_num, func_call); - } else if (const auto *as_arg_ref = child->try_as()) { + } else if (const auto* as_arg_ref = child->try_as()) { call_arg = VertexUtil::get_call_arg_ref(as_arg_ref->arg_num, func_call); - } else if (const auto *as_arg_ref = child->try_as()) { + } else if (const auto* as_arg_ref = child->try_as()) { call_arg = VertexUtil::get_call_arg_ref(as_arg_ref->arg_num, func_call); } if (call_arg) { - tinf::Edge *e = new tinf::Edge; + tinf::Edge* e = new tinf::Edge; e->from = tinf::get_tinf_node(dependent_vertex); - e->to = call_arg->type() == op_callback_of_builtin - ? tinf::get_tinf_node(call_arg.as()->func_id, -1) - : tinf::get_tinf_node(call_arg); + e->to = + call_arg->type() == op_callback_of_builtin ? tinf::get_tinf_node(call_arg.as()->func_id, -1) : tinf::get_tinf_node(call_arg); e->from_at = nullptr; tinf::get_inferer()->add_edge(e); tinf::get_inferer()->add_node(e->to); @@ -204,7 +203,6 @@ void CollectMainEdgesPass::create_edges_to_recalc_arg_ref(const TypeHint *type_h }); } - // handle @var phpdoc for local/static vars inside a function (or global vars, for top-level functions) void CollectMainEdgesPass::on_var_phpdoc(VertexAdaptor var_op) { VarPtr var_id = var_op->var()->var_id; @@ -226,7 +224,7 @@ void CollectMainEdgesPass::on_func_call_extern_modifying_arg_type(VertexAdaptor< VertexRange args = call->args(); LValue val = as_lvalue(args[0]); - auto *key = new MultiKey(*val.key); + auto* key = new MultiKey(*val.key); key->push_back(Key::any_key()); val.key = key; @@ -249,12 +247,11 @@ void CollectMainEdgesPass::on_func_call_extern_modifying_arg_type(VertexAdaptor< create_set(dest_array_arg, another_array_arg); } - if (extern_function->name == "wait_queue_push") { VertexRange args = call->args(); LValue future_queue_arg = as_lvalue(args[0]); - const TypeHint *type_hint = TypeHintFuture::create(tp_future_queue, TypeHintArgSubkeyGet::create(TypeHintArgRef::create(2))); + const TypeHint* type_hint = TypeHintFuture::create(tp_future_queue, TypeHintArgSubkeyGet::create(TypeHintArgRef::create(2))); create_type_assign_with_arg_ref_rule(as_lvalue(future_queue_arg), type_hint, call); } } @@ -263,15 +260,15 @@ void CollectMainEdgesPass::on_func_call_extern_modifying_arg_type(VertexAdaptor< // array_filter($a, function($v) { ... }), array_filter($a, 'cb') and similar // (not to php functions with callable arguments! built-in only) void CollectMainEdgesPass::on_passed_callback_to_builtin(VertexAdaptor call, int param_i, VertexAdaptor v_callback) { - FunctionPtr call_function = call->func_id; // array_filter, etc - FunctionPtr provided_callback = v_callback->func_id; // typically, a lambda or __invoke method + FunctionPtr call_function = call->func_id; // array_filter, etc + FunctionPtr provided_callback = v_callback->func_id; // typically, a lambda or __invoke method auto callback_param = call_function->get_params()[param_i].as(); - const auto *type_hint_callable = callback_param->type_hint->try_as(); + const auto* type_hint_callable = callback_param->type_hint->try_as(); // set restriction of return type of provided callback // built-in functions are declared as 'callable(...):any' or 'callable(...):bool' // if 'any', it must return anything but void; otherwise, the type rule must be satisfied (it's static, no argument depends) - const auto *as_primitive = type_hint_callable->return_type->try_as(); + const auto* as_primitive = type_hint_callable->return_type->try_as(); if (as_primitive && as_primitive->ptype == tp_any) { create_non_void(as_rvalue(provided_callback, -1)); } else { @@ -281,7 +278,7 @@ void CollectMainEdgesPass::on_passed_callback_to_builtin(VertexAdaptorreturn_typehint && provided_callback->return_typehint->has_argref_inside()) { - for (const auto *callback_param_type_hint : type_hint_callable->arg_types) { + for (const auto* callback_param_type_hint : type_hint_callable->arg_types) { if (callback_param_type_hint->has_argref_inside()) { create_edges_to_recalc_arg_ref(callback_param_type_hint, call, call); } @@ -302,7 +299,7 @@ void CollectMainEdgesPass::on_passed_callback_to_builtin(VertexAdaptorarg_types.size(); ++i, ++param_i) { - const auto *callback_param_decl = type_hint_callable->arg_types[i]; // ^2[*] above + const auto* callback_param_decl = type_hint_callable->arg_types[i]; // ^2[*] above if (callback_param_decl->has_argref_inside()) { create_type_assign_with_arg_ref_rule(as_lvalue(provided_callback, param_i), callback_param_decl, call); } else { @@ -344,8 +341,7 @@ void CollectMainEdgesPass::on_func_call(VertexAdaptor call) { // we create a set-edge, as we need to infer this 'any' (remember, that $x has a type restriction created in on_function) // * the paragraph above about 'any' refers only to PHP functions; built-ins accepting 'any' need only a postponed check // * cast params go their own way - bool should_create_set_to_infer = (!param->type_hint || param->type_hint->has_tp_any_inside()) - && !function->is_extern() && !is_cast_param; + bool should_create_set_to_infer = (!param->type_hint || param->type_hint->has_tp_any_inside()) && !function->is_extern() && !is_cast_param; if (should_create_set_to_infer) { create_set(as_lvalue(function, i), arg); @@ -414,7 +410,7 @@ void CollectMainEdgesPass::on_switch(VertexAdaptor switch_op) { } else if (switch_op->kind != SwitchKind::EmptySwitch) { // the condition variable should be lca of all case expression types and the condition expr result type itself create_set(as_lvalue(switch_op->condition_on_switch()->var_id), switch_op->condition()); - for (const auto &c : switch_op->cases()) { + for (const auto& c : switch_op->cases()) { if (auto as_case = c.try_as()) { create_set(as_lvalue(switch_op->condition_on_switch()->var_id), as_case->expr()); } @@ -457,18 +453,18 @@ void CollectMainEdgesPass::on_set_op(VertexPtr v) { kphp_fail(); } - const RValue &rval = as_set_value(v); + const RValue& rval = as_set_value(v); // if it's a variable with type hint (for example, public int|false $prop), we also don't need to create a set-edge, only a postponed check // here we try to detect if lval is a variable with type hint or @var declared, looks a bit complicated // (it's still an optimization, everything would work without it, always creating set-edges, but a bit slower) - const TypeHint *type_hint{nullptr}; + const TypeHint* type_hint{nullptr}; VarPtr lhs_var; if (auto as_prop = lval.try_as()) { // $a->prop++ lhs_var = as_prop->var_id; type_hint = as_prop->var_id->as_class_instance_field()->type_hint; } else if (auto as_var = lval.try_as()) { - if (as_var->var_id->is_class_static_var()) { // A::$prop++ + if (as_var->var_id->is_class_static_var()) { // A::$prop++ lhs_var = as_var->var_id; type_hint = as_var->var_id->as_class_static_field()->type_hint; } @@ -500,11 +496,9 @@ void CollectMainEdgesPass::ifi_fix(VertexPtr v) { } } - const auto is_indexing_func_call = [](VertexPtr v) { - return v->type() == op_func_call && v.as()->func_id->is_result_indexing; - }; + const auto is_indexing_func_call = [](VertexPtr v) { return v->type() == op_func_call && v.as()->func_id->is_result_indexing; }; if ((cur->type() == op_var && ifi_tp != ifi_unset) || (ifi_tp > ifi_isset && (cur->type() == op_index || is_indexing_func_call(cur)))) { - tinf::Node *node = tinf::get_tinf_node(cur); + tinf::Node* node = tinf::get_tinf_node(cur); if (node->isset_flags == 0) { create_isset_check(as_rvalue(node)); } @@ -514,14 +508,14 @@ void CollectMainEdgesPass::ifi_fix(VertexPtr v) { } void CollectMainEdgesPass::on_class(ClassPtr klass) { - klass->members.for_each([&](ClassMemberInstanceField &f) { + klass->members.for_each([&](ClassMemberInstanceField& f) { on_var(f.var); if (f.type_hint) { create_type_assign_with_restriction(as_lvalue(f.var), f.type_hint); } }); - klass->members.for_each([&](ClassMemberStaticField &f) { + klass->members.for_each([&](ClassMemberStaticField& f) { on_var(f.var); if (f.type_hint) { create_type_assign_with_restriction(as_lvalue(f.var), f.type_hint); @@ -557,30 +551,30 @@ void CollectMainEdgesPass::on_start() { VertexPtr CollectMainEdgesPass::on_enter_vertex(VertexPtr v) { switch (v->type()) { - case op_func_call: - on_func_call(v.as()); - break; - case op_return: - have_returns = true; - on_return(v.as(), current_function); - break; - case op_foreach: - on_foreach(v.as()); - break; - case op_switch: - on_switch(v.as()); - break; - case op_list: - on_list(v.as()); - break; - case op_try: - on_try(v.as()); - break; - case op_phpdoc_var: - on_var_phpdoc(v.as()); - break; - default: - break; + case op_func_call: + on_func_call(v.as()); + break; + case op_return: + have_returns = true; + on_return(v.as(), current_function); + break; + case op_foreach: + on_foreach(v.as()); + break; + case op_switch: + on_switch(v.as()); + break; + case op_list: + on_list(v.as()); + break; + case op_try: + on_try(v.as()); + break; + case op_phpdoc_var: + on_var_phpdoc(v.as()); + break; + default: + break; } if (OpInfo::rl(v->type()) == rl_set || vk::any_of_equal(v->type(), op_prefix_inc, op_postfix_inc, op_prefix_dec, op_postfix_dec)) { on_set_op(v); @@ -634,8 +628,8 @@ void CollectMainEdgesPass::on_finish() { } template -void CollectMainEdgesPass::call_on_var(const CollectionT &collection) { - for (const auto &el: collection) { +void CollectMainEdgesPass::call_on_var(const CollectionT& collection) { + for (const auto& el : collection) { on_var(el); } } diff --git a/compiler/pipes/collect-main-edges.h b/compiler/pipes/collect-main-edges.h index 11ba745e50..327bf94027 100644 --- a/compiler/pipes/collect-main-edges.h +++ b/compiler/pipes/collect-main-edges.h @@ -15,16 +15,15 @@ class CollectMainEdgesPass final : public FunctionPassBase { static RValue as_set_value(VertexPtr v); - template - static void create_set(const LValue &lhs, const R &rhs); - static void create_type_assign(const LValue &lhs, const TypeData *initial_type); - static void create_type_assign_with_arg_ref_rule(const LValue &lhs, const TypeHint *type_hint, VertexPtr func_call); - static void create_type_assign_with_restriction(const LValue &var_lhs, const TypeHint *type_hint); - static void create_postponed_type_check(const RValue &restricted_value, const RValue &actual_value, const TypeHint *type_hint); - static void create_non_void(const RValue &lhs); - static void create_isset_check(const RValue &rvalue); - static void create_edges_to_recalc_arg_ref(const TypeHint *type_hint, VertexPtr dependent_vertex, VertexPtr func_call); + static void create_set(const LValue& lhs, const R& rhs); + static void create_type_assign(const LValue& lhs, const TypeData* initial_type); + static void create_type_assign_with_arg_ref_rule(const LValue& lhs, const TypeHint* type_hint, VertexPtr func_call); + static void create_type_assign_with_restriction(const LValue& var_lhs, const TypeHint* type_hint); + static void create_postponed_type_check(const RValue& restricted_value, const RValue& actual_value, const TypeHint* type_hint); + static void create_non_void(const RValue& lhs); + static void create_isset_check(const RValue& rvalue); + static void create_edges_to_recalc_arg_ref(const TypeHint* type_hint, VertexPtr dependent_vertex, VertexPtr func_call); static void on_var_phpdoc(VertexAdaptor var_op); static void on_passed_callback_to_builtin(VertexAdaptor call, int param_i, VertexAdaptor v_callback); @@ -43,10 +42,9 @@ class CollectMainEdgesPass final : public FunctionPassBase { static void search_for_nested_calls(VertexPtr v); template - void call_on_var(const CollectionT &collection); + void call_on_var(const CollectionT& collection); public: - using ExecuteType = FunctionAndCFG; std::string get_description() override { diff --git a/compiler/pipes/collect-required-and-classes.cpp b/compiler/pipes/collect-required-and-classes.cpp index 761f585828..1820696401 100644 --- a/compiler/pipes/collect-required-and-classes.cpp +++ b/compiler/pipes/collect-required-and-classes.cpp @@ -4,30 +4,29 @@ #include "compiler/pipes/collect-required-and-classes.h" -#include "compiler/const-manipulations.h" #include "compiler/compiler-core.h" +#include "compiler/const-manipulations.h" #include "compiler/data/modulite-data.h" -#include "compiler/data/src-file.h" #include "compiler/data/src-dir.h" +#include "compiler/data/src-file.h" #include "compiler/function-pass.h" #include "compiler/phpdoc.h" #include "compiler/type-hint.h" - class CollectRequiredPass final : public FunctionPassBase { private: - DataStream &file_stream; - DataStream &function_stream; + DataStream& file_stream; + DataStream& function_stream; - SrcFilePtr require_file(const std::string &file_name, bool error_if_not_exists, bool builtin = false) { + SrcFilePtr require_file(const std::string& file_name, bool error_if_not_exists, bool builtin = false) { return G->require_file(file_name, current_function->file_id->owner_lib, file_stream, error_if_not_exists, builtin); } - void require_function(const std::string &name) { + void require_function(const std::string& name) { G->require_function(name, function_stream); } - void require_class(const std::string &class_name) { + void require_class(const std::string& class_name) { // avoid a race condition, when we try to search for RpcFunction.php and other built-in classes that are visible from index.php // (if such files exist, extra src_xxx$called variables will be created: unstable codegeneration) while (!G->get_functions_txt_parsed()) { @@ -40,12 +39,12 @@ class CollectRequiredPass final : public FunctionPassBase { std::string file_name = replace_characters(class_name, '\\', '/'); if (G->settings().is_composer_enabled()) { - const auto &composer = G->get_composer_autoloader(); - if (const auto &psr4_filename = composer.psr4_lookup(file_name); !psr4_filename.empty()) { + const auto& composer = G->get_composer_autoloader(); + if (const auto& psr4_filename = composer.psr4_lookup(file_name); !psr4_filename.empty()) { require_file(psr4_filename, false); return; // required from the composer autoload PSR-4 path } - if (const auto &psr0_filename = composer.psr0_lookup(file_name); !psr0_filename.empty()) { + if (const auto& psr0_filename = composer.psr0_lookup(file_name); !psr0_filename.empty()) { auto file = require_file(psr0_filename, false); file->is_loaded_by_psr0 = true; return; // required from the composer autoload PSR-0 path @@ -65,7 +64,7 @@ class CollectRequiredPass final : public FunctionPassBase { FFIRoot::register_builtin_classes(function_stream); } - for (const auto &dep : cur_class->get_str_dependents()) { + for (const auto& dep : cur_class->get_str_dependents()) { if (!cur_class->is_builtin() && dep.class_name == "Throwable") { if (cur_class->is_interface()) { kphp_error(false, fmt_format("Interface {} cannot extend Throwable", cur_class->name)); @@ -77,10 +76,8 @@ class CollectRequiredPass final : public FunctionPassBase { require_class(dep.class_name); } // class constant values may contain other class constants that may need require_class() - cur_class->members.for_each([&](ClassMemberConstant &c) { - run_function_pass(c.value, this); - }); - cur_class->members.for_each([&](ClassMemberStaticField &f) { + cur_class->members.for_each([&](ClassMemberConstant& c) { run_function_pass(c.value, this); }); + cur_class->members.for_each([&](ClassMemberStaticField& f) { if (f.var->init_val) { run_function_pass(f.var->init_val, this); } @@ -91,7 +88,7 @@ class CollectRequiredPass final : public FunctionPassBase { require_all_classes_in_phpdoc_type(f.type_hint); } }); - cur_class->members.for_each([&](ClassMemberInstanceField &f) { + cur_class->members.for_each([&](ClassMemberInstanceField& f) { if (f.var->init_val) { run_function_pass(f.var->init_val, this); } @@ -105,8 +102,8 @@ class CollectRequiredPass final : public FunctionPassBase { } // looking at /** @var Photo */ above a field, load Photo class - inline void require_all_classes_in_field_phpdoc(const PhpDocComment *phpdoc) { - if (const PhpDocTag *var_tag = phpdoc->find_tag(PhpDocType::var)) { + inline void require_all_classes_in_field_phpdoc(const PhpDocComment* phpdoc) { + if (const PhpDocTag* var_tag = phpdoc->find_tag(PhpDocType::var)) { if (auto tag_parsed = var_tag->value_as_type_and_var_name(current_function, current_function->genericTs)) { require_all_classes_in_phpdoc_type(tag_parsed.type_hint); } @@ -114,10 +111,10 @@ class CollectRequiredPass final : public FunctionPassBase { } // Searching for classes inside @var/@param phpdoc as well as inside type hints - inline void require_all_classes_in_phpdoc_type(const TypeHint *type_hint) { + inline void require_all_classes_in_phpdoc_type(const TypeHint* type_hint) { if (type_hint && type_hint->has_instances_inside()) { - type_hint->traverse([this](const TypeHint *child) { - if (const auto *as_instance = child->try_as()) { + type_hint->traverse([this](const TypeHint* child) { + if (const auto* as_instance = child->try_as()) { if (!as_instance->has_self_static_parent_inside()) { require_class(as_instance->full_class_name); } @@ -135,7 +132,7 @@ class CollectRequiredPass final : public FunctionPassBase { // (that "invalid" functions aren't reachable in fact, they just exist in a dead codebase, // so their phpdocs aren't analyzed later, but trying to parse them in gentree leads to 10k errors) if (f->phpdoc && !f->is_lambda()) { - for (const PhpDocTag &tag : f->phpdoc->tags) { + for (const PhpDocTag& tag : f->phpdoc->tags) { if (tag.type == PhpDocType::param) { if (auto tag_parsed = tag.value_as_type_and_var_name(current_function, current_function->genericTs)) { require_all_classes_in_phpdoc_type(tag_parsed.type_hint); @@ -143,7 +140,7 @@ class CollectRequiredPass final : public FunctionPassBase { } } } - for (const auto &p: f->get_params()) { + for (const auto& p : f->get_params()) { if (p.as()->type_hint) { require_all_classes_in_phpdoc_type(p.as()->type_hint); } @@ -153,9 +150,9 @@ class CollectRequiredPass final : public FunctionPassBase { } } - VertexPtr make_require_call(VertexPtr root, const std::string &name, bool once, bool builtin = false) { + VertexPtr make_require_call(VertexPtr root, const std::string& name, bool once, bool builtin = false) { auto file = require_file(name, true, builtin); - kphp_error_act (file, fmt_format("Cannot require [{}]\n", name), return root); + kphp_error_act(file, fmt_format("Cannot require [{}]\n", name), return root); VertexPtr call = VertexAdaptor::create(); call->set_string(file->main_func_name); call->location = root->location; @@ -168,7 +165,7 @@ class CollectRequiredPass final : public FunctionPassBase { } // whether required file name refers to the composer-generated autoload file - static bool is_composer_autoload(const std::string &required_path) { + static bool is_composer_autoload(const std::string& required_path) { // fast path: it there is no "/autoload.php", then we don't // need to bother and expand the filename if (!vk::ends_with(required_path, "/autoload.php")) { @@ -184,10 +181,10 @@ class CollectRequiredPass final : public FunctionPassBase { // // note that we use once=true all the time since composer would // do the same (it uses require+inclusion map to perform the inclusion exactly once) - const auto &files_to_require = G->get_composer_autoloader().get_files_to_require(); + const auto& files_to_require = G->get_composer_autoloader().get_files_to_require(); std::vector list; list.reserve(files_to_require.size()); - for (const auto &file : files_to_require) { + for (const auto& file : files_to_require) { list.emplace_back(make_require_call(root, file, true)); } return VertexAdaptor::create(list).set_location(root->location); @@ -232,7 +229,7 @@ class CollectRequiredPass final : public FunctionPassBase { ModulitePtr modulite = ModuliteData::create_from_composer_json(composer_json, dir->has_modulite_yaml); bool is_root = dir->full_dir_name == G->settings().composer_root.get(); - if (is_root || !modulite) { // composer.json at project root is loaded, but not stored as a modulite + if (is_root || !modulite) { // composer.json at project root is loaded, but not stored as a modulite return {}; } dir->nested_files_modulite = modulite; @@ -249,7 +246,7 @@ class CollectRequiredPass final : public FunctionPassBase { ModulitePtr parent = with_parent ? with_parent->nested_files_modulite : ModulitePtr{}; ModulitePtr modulite = ModuliteData::create_from_modulite_yaml(dir->get_modulite_yaml_filename(), parent); - if (!modulite || modulite->modulite_name.empty()) { // an error while parsing yaml, was already printed + if (!modulite || modulite->modulite_name.empty()) { // an error while parsing yaml, was already printed return {}; } dir->nested_files_modulite = modulite; @@ -271,9 +268,9 @@ class CollectRequiredPass final : public FunctionPassBase { // this is quite important, because Modulite plugin auto-generates config from all sources, // and some of them may not be reachable at the moment of compilation (some wip yet unused code) void require_all_deps_of_modulite(ModulitePtr modulite) { - for (const ModuliteSymbol &s : modulite->exports) { + for (const ModuliteSymbol& s : modulite->exports) { if (s.kind == ModuliteSymbol::kind_ref_stringname) { - vk::string_view e = s.ref_stringname; // exported symbol: class / define / method / etc. + vk::string_view e = s.ref_stringname; // exported symbol: class / define / method / etc. bool seems_like_classname = !e.ends_with(")") && e[0] != '$' && e[0] != '@' && e[0] != '#'; if (seems_like_classname) { require_class(modulite->modulite_namespace + e); @@ -287,10 +284,9 @@ class CollectRequiredPass final : public FunctionPassBase { } public: - CollectRequiredPass(DataStream &file_stream, DataStream &function_stream) - : file_stream(file_stream) - , function_stream(function_stream) { - } + CollectRequiredPass(DataStream& file_stream, DataStream& function_stream) + : file_stream(file_stream), + function_stream(function_stream) {} std::string get_description() override { return "Collect required"; @@ -323,9 +319,9 @@ class CollectRequiredPass final : public FunctionPassBase { if (root->type() == op_func_call && root->extra_type != op_ex_func_call_arrow) { size_t pos = root->get_string().find("::"); if (pos != std::string::npos) { - const std::string &prefix_name = root->get_string().substr(0, pos); - const std::string &local_name = root->get_string().substr(pos + 2); - const std::string &class_name = resolve_uses(current_function, prefix_name); + const std::string& prefix_name = root->get_string().substr(0, pos); + const std::string& local_name = root->get_string().substr(pos + 2); + const std::string& class_name = resolve_uses(current_function, prefix_name); require_class(class_name); require_function(resolve_static_method_append_context(current_function, prefix_name, class_name, local_name)); } else { @@ -336,8 +332,8 @@ class CollectRequiredPass final : public FunctionPassBase { if (root->type() == op_var || root->type() == op_func_name) { size_t pos = root->get_string().find("::"); if (pos != std::string::npos) { - const std::string &prefix_name = root->get_string().substr(0, pos); - const std::string &class_name = resolve_uses(current_function, prefix_name); + const std::string& prefix_name = root->get_string().substr(0, pos); + const std::string& class_name = resolve_uses(current_function, prefix_name); require_class(class_name); } } @@ -350,7 +346,7 @@ class CollectRequiredPass final : public FunctionPassBase { if (auto require = root.try_as()) { std::string name = collect_string_concatenation(require->expr(), true); - kphp_error_act (!name.empty(), "Not a string in 'require' arguments", return root); + kphp_error_act(!name.empty(), "Not a string in 'require' arguments", return root); if (is_composer_autoload(name)) { return require_composer_autoload(root); } @@ -363,15 +359,13 @@ class CollectRequiredPass final : public FunctionPassBase { return root; } - }; - -void CollectRequiredAndClassesF::execute(FunctionPtr function, CollectRequiredAndClassesF::OStreamT &os) { - auto &ready_function_stream = *os.template project_to_nth_data_stream<0>(); - auto &file_stream = *os.template project_to_nth_data_stream<1>(); - auto &function_stream = *os.template project_to_nth_data_stream<2>(); - auto &class_stream = *os.template project_to_nth_data_stream<3>(); +void CollectRequiredAndClassesF::execute(FunctionPtr function, CollectRequiredAndClassesF::OStreamT& os) { + auto& ready_function_stream = *os.template project_to_nth_data_stream<0>(); + auto& file_stream = *os.template project_to_nth_data_stream<1>(); + auto& function_stream = *os.template project_to_nth_data_stream<2>(); + auto& class_stream = *os.template project_to_nth_data_stream<3>(); CollectRequiredPass pass(file_stream, function_stream); run_function_pass(function, &pass); diff --git a/compiler/pipes/collect-required-and-classes.h b/compiler/pipes/collect-required-and-classes.h index e5fae2f621..3083aab243 100644 --- a/compiler/pipes/collect-required-and-classes.h +++ b/compiler/pipes/collect-required-and-classes.h @@ -16,5 +16,5 @@ class CollectRequiredAndClassesF { using ReadyFunctionPtr = FunctionPtr; using OStreamT = MultipleDataStreams; - void execute(FunctionPtr function, OStreamT &os); + void execute(FunctionPtr function, OStreamT& os); }; diff --git a/compiler/pipes/convert-invoke-to-func-call.cpp b/compiler/pipes/convert-invoke-to-func-call.cpp index 3b93064203..1b3b827cae 100644 --- a/compiler/pipes/convert-invoke-to-func-call.cpp +++ b/compiler/pipes/convert-invoke-to-func-call.cpp @@ -55,7 +55,8 @@ VertexPtr ConvertInvokeToFuncCallPass::on_callback_of_builtin(VertexAdaptorargs().empty()) { FunctionPtr f_points_to = G->get_function(v_callback->str_val); kphp_error_act(f_points_to, fmt_format("Can't find function {}", v_callback->str_val), return v_callback); - kphp_error(f_points_to->is_required, fmt_format("{} needs the @kphp-required tag, because it's used only as a string callback", f_points_to->as_human_readable())); + kphp_error(f_points_to->is_required, + fmt_format("{} needs the @kphp-required tag, because it's used only as a string callback", f_points_to->as_human_readable())); v_callback->func_id = f_points_to; return v_callback; @@ -63,7 +64,7 @@ VertexPtr ConvertInvokeToFuncCallPass::on_callback_of_builtin(VertexAdaptorargs()[0]; ClassPtr c_assumed = assume_class_of_expr(current_function, bound_this, v_callback).try_as_class(); - const auto *class_method = c_assumed ? c_assumed->get_instance_method(v_callback->str_val) : nullptr; + const auto* class_method = c_assumed ? c_assumed->get_instance_method(v_callback->str_val) : nullptr; kphp_error_act(class_method, "Invalid callback passed, could not detect a class or its method", return v_callback); v_callback->func_id = class_method->function; @@ -89,8 +90,7 @@ VertexPtr ConvertInvokeToFuncCallPass::on_func_call(VertexAdaptor // this can be done only here (not in deducing types), after all lambdas have been instantiated VertexPtr ConvertInvokeToFuncCallPass::on_invoke_call(VertexAdaptor v_invoke_call) { ClassPtr klass = assume_class_of_expr(current_function, v_invoke_call->args()[0], v_invoke_call).try_as_class(); - kphp_error_act(klass && (klass->is_lambda_class() || klass->is_typed_callable_interface()), - "Invalid ()-invocation of a non-lambda", return v_invoke_call); + kphp_error_act(klass && (klass->is_lambda_class() || klass->is_typed_callable_interface()), "Invalid ()-invocation of a non-lambda", return v_invoke_call); auto v_func_call = VertexAdaptor::create(v_invoke_call->args()).set_location(v_invoke_call); v_func_call->extra_type = op_ex_func_call_arrow; @@ -105,9 +105,8 @@ VertexPtr ConvertInvokeToFuncCallPass::on_invoke_call(VertexAdaptor v_clone) { ClassPtr klass = v_clone->class_id; - bool inside_virt_clone = vk::any_of_equal(current_function->local_name(), - ClassData::NAME_OF_VIRT_CLONE, - FunctionData::get_name_of_self_method(ClassData::NAME_OF_VIRT_CLONE)); + bool inside_virt_clone = + vk::any_of_equal(current_function->local_name(), ClassData::NAME_OF_VIRT_CLONE, FunctionData::get_name_of_self_method(ClassData::NAME_OF_VIRT_CLONE)); // clone $obj, when $obj is a parent class/interface, is replaced with $obj->__virt_clone() if (!klass->derived_classes.empty() && !inside_virt_clone) { @@ -140,7 +139,7 @@ VertexPtr ConvertInvokeToFuncCallPass::on_clone(VertexAdaptor v_clone) } // ConvertInvokeToFuncCallF is needed to hold lambdas so they don't pass the pipeline before a containing function -void ConvertInvokeToFuncCallF::execute(FunctionPtr f, DataStream &os) { +void ConvertInvokeToFuncCallF::execute(FunctionPtr f, DataStream& os) { if (f->is_lambda()) { // don't push it into pipeline // it will be pushed (or already was pushed) by a function containing this lambda @@ -151,7 +150,7 @@ void ConvertInvokeToFuncCallF::execute(FunctionPtr f, DataStream &o } // whenever f is pushed to the pipeline, all lambdas within it have already been processed -void ConvertInvokeToFuncCallF::execute_with_nested_lambdas(FunctionPtr f, DataStream &os) { +void ConvertInvokeToFuncCallF::execute_with_nested_lambdas(FunctionPtr f, DataStream& os) { ConvertInvokeToFuncCallPass pass; run_function_pass(f, &pass); for (FunctionPtr f_lambda : pass.flush_nested_lambdas()) { diff --git a/compiler/pipes/convert-invoke-to-func-call.h b/compiler/pipes/convert-invoke-to-func-call.h index 19f5fdbe0d..29c9b6329a 100644 --- a/compiler/pipes/convert-invoke-to-func-call.h +++ b/compiler/pipes/convert-invoke-to-func-call.h @@ -26,7 +26,7 @@ class ConvertInvokeToFuncCallPass final : public FunctionPassBase { VertexPtr on_invoke_call(VertexAdaptor v_invoke_call); VertexPtr on_callback_of_builtin(VertexAdaptor v_callback); - std::forward_list &&flush_nested_lambdas() { + std::forward_list&& flush_nested_lambdas() { return std::move(nested_lambdas); } }; @@ -35,7 +35,7 @@ class ConvertInvokeToFuncCallPass final : public FunctionPassBase { // it's needed to hold lambdas so they don't pass the pipeline before a containing function, see execute() class ConvertInvokeToFuncCallF { public: - void execute(FunctionPtr f, DataStream &os); + void execute(FunctionPtr f, DataStream& os); - static void execute_with_nested_lambdas(FunctionPtr f, DataStream &os); + static void execute_with_nested_lambdas(FunctionPtr f, DataStream& os); }; diff --git a/compiler/pipes/convert-sprintf-calls.cpp b/compiler/pipes/convert-sprintf-calls.cpp index 06fe542ac9..712bfd3f1a 100644 --- a/compiler/pipes/convert-sprintf-calls.cpp +++ b/compiler/pipes/convert-sprintf-calls.cpp @@ -8,7 +8,8 @@ #include struct FormatCallInfo { - FormatCallInfo() : args(VertexRange(Vertex::iterator{}, Vertex::iterator{})) {} + FormatCallInfo() + : args(VertexRange(Vertex::iterator{}, Vertex::iterator{})) {} // stores a variable that contains all the call arguments, // if all arguments are constant VertexAdaptor var; @@ -22,16 +23,13 @@ struct FormatCallInfo { }; struct FormatPart { - enum class FormatSpecType { - decimal, - string - }; + enum class FormatSpecType { decimal, string }; explicit FormatPart(std::string value) - : value(std::move(value)) {} + : value(std::move(value)) {} explicit FormatPart(FormatSpecType specifier) - : specifier(specifier) {} + : specifier(specifier) {} std::string value; FormatSpecType specifier{}; @@ -41,12 +39,12 @@ struct FormatPart { } }; -std::vector try_parse_format_string(const std::string &format) { +std::vector try_parse_format_string(const std::string& format) { std::vector parts; std::string last_value; bool find_percent = false; - for (const auto &symbol : format) { + for (const auto& symbol : format) { if (find_percent) { if (symbol == 'd') { parts.emplace_back(FormatPart::FormatSpecType::decimal); @@ -90,7 +88,7 @@ VertexPtr ConvertSprintfCallsPass::on_exit_vertex(VertexPtr root) { VertexPtr ConvertSprintfCallsPass::convert_sprintf_call(VertexAdaptor call) { const auto args = call->args(); const auto format_arg_raw = args[0]; - const auto *format_string = VertexUtil::get_constexpr_string(format_arg_raw); + const auto* format_string = VertexUtil::get_constexpr_string(format_arg_raw); if (format_string == nullptr) { return call; } @@ -100,9 +98,7 @@ VertexPtr ConvertSprintfCallsPass::convert_sprintf_call(VertexAdaptor 1) { const auto format_args_raw = args[1]; switch (format_args_raw->type()) { - // if all arguments are constant - case op_var: { - info.var = format_args_raw.as(); - info.array = info.var->var_id->init_val.try_as(); - if (!info.array) { - return call; - } - info.args = info.array->args(); - info.is_var = true; - break; - } - // if at least one argument calls a function or variable - case op_array: { - info.array = format_args_raw.as(); - info.args = info.array->args(); - break; - } - default: + // if all arguments are constant + case op_var: { + info.var = format_args_raw.as(); + info.array = info.var->var_id->init_val.try_as(); + if (!info.array) { return call; + } + info.args = info.array->args(); + info.is_var = true; + break; + } + // if at least one argument calls a function or variable + case op_array: { + info.array = format_args_raw.as(); + info.args = info.array->args(); + break; + } + default: + return call; } if (count_specifiers > info.args.size()) { @@ -139,7 +135,7 @@ VertexPtr ConvertSprintfCallsPass::convert_sprintf_call(VertexAdaptor vertex_parts; size_t index_spec = 0; - for (const auto &part : parts) { + for (const auto& part : parts) { const auto vertex = convert_format_part_to_vertex(part, index_spec, info, call->location); vertex_parts.push_back(vertex); @@ -151,7 +147,8 @@ VertexPtr ConvertSprintfCallsPass::convert_sprintf_call(VertexAdaptor::create(vertex_parts).set_location(call->location); } -VertexPtr ConvertSprintfCallsPass::convert_format_part_to_vertex(const FormatPart &part, size_t arg_index, const FormatCallInfo &info, const Location &call_location) { +VertexPtr ConvertSprintfCallsPass::convert_format_part_to_vertex(const FormatPart& part, size_t arg_index, const FormatCallInfo& info, + const Location& call_location) { if (part.is_specifier()) { VertexPtr element; @@ -167,14 +164,14 @@ VertexPtr ConvertSprintfCallsPass::convert_format_part_to_vertex(const FormatPar VertexPtr convert; switch (part.specifier) { - case FormatPart::FormatSpecType::decimal: - convert = VertexAdaptor::create(element); - break; - case FormatPart::FormatSpecType::string: - convert = VertexAdaptor::create(element); - break; - default: - return element; + case FormatPart::FormatSpecType::decimal: + convert = VertexAdaptor::create(element); + break; + case FormatPart::FormatSpecType::string: + convert = VertexAdaptor::create(element); + break; + default: + return element; } return VertexAdaptor::create(convert); diff --git a/compiler/pipes/convert-sprintf-calls.h b/compiler/pipes/convert-sprintf-calls.h index 5f14308630..5c26536ccd 100644 --- a/compiler/pipes/convert-sprintf-calls.h +++ b/compiler/pipes/convert-sprintf-calls.h @@ -37,5 +37,5 @@ class ConvertSprintfCallsPass final : public FunctionPassBase { private: static VertexPtr convert_sprintf_call(VertexAdaptor call); - static VertexPtr convert_format_part_to_vertex(const FormatPart &part, size_t arg_index, const FormatCallInfo &info, const Location &call_location); + static VertexPtr convert_format_part_to_vertex(const FormatPart& part, size_t arg_index, const FormatCallInfo& info, const Location& call_location); }; diff --git a/compiler/pipes/deduce-implicit-types-and-casts.cpp b/compiler/pipes/deduce-implicit-types-and-casts.cpp index 61e4c3426d..3b12df805a 100644 --- a/compiler/pipes/deduce-implicit-types-and-casts.cpp +++ b/compiler/pipes/deduce-implicit-types-and-casts.cpp @@ -6,14 +6,14 @@ #include "compiler/pipes/transform-to-smart-instanceof.h" #include "compiler/compiler-core.h" -#include "compiler/data/src-file.h" #include "compiler/data/generics-mixins.h" +#include "compiler/data/src-file.h" #include "compiler/generics-reification.h" -#include "compiler/vertex-util.h" #include "compiler/lambda-utils.h" #include "compiler/name-gen.h" #include "compiler/phpdoc.h" #include "compiler/type-hint.h" +#include "compiler/vertex-util.h" /* * Deducing implicit types is a very important step of the compilation pipeline. @@ -137,15 +137,14 @@ * - some other minors, read the code */ - // having a lambda with assumed types, construct TypeHintCallable from it // (to inherit from a typed callable interface, for example) static InterfacePtr get_typed_callable_interface_from_lambda(FunctionPtr f_lambda) { - std::vector arg_types; + std::vector arg_types; arg_types.reserve(f_lambda->get_params().size()); for (auto p : f_lambda->get_params()) { - const TypeHint *param_hint = p.as()->type_hint; + const TypeHint* param_hint = p.as()->type_hint; if (!param_hint) { return InterfacePtr{}; } @@ -155,22 +154,23 @@ static InterfacePtr get_typed_callable_interface_from_lambda(FunctionPtr f_lambd return InterfacePtr{}; } - const TypeHint *as_callable = TypeHintCallable::create(std::move(arg_types), f_lambda->return_typehint); + const TypeHint* as_callable = TypeHintCallable::create(std::move(arg_types), f_lambda->return_typehint); return as_callable->is_typedata_constexpr() ? as_callable->try_as()->get_interface() : InterfacePtr{}; } // having an array_map type_hint `callable(^2[*] $x)` and a call `array_map(fn($a) => ..., [new A]), // deduce that $a is A, based on ^arg refs and assumptions -static const TypeHint *patch_type_hint_with_argref_in_context_of_call(const TypeHint *type_hint, FunctionPtr current_function, VertexAdaptor call) { - const TypeHint *replaced = type_hint->replace_children_custom([current_function, call](const TypeHint *child) { - if (const auto *as_arg_ref = child->try_as()) { +static const TypeHint* patch_type_hint_with_argref_in_context_of_call(const TypeHint* type_hint, FunctionPtr current_function, + VertexAdaptor call) { + const TypeHint* replaced = type_hint->replace_children_custom([current_function, call](const TypeHint* child) { + if (const auto* as_arg_ref = child->try_as()) { if (auto call_arg = VertexUtil::get_call_arg_ref(as_arg_ref->arg_num, call)) { return assume_class_of_expr(current_function, call_arg, call).assum_hint ?: child; } } - if (const auto *as_arg_ref_subkey = child->try_as()) { - const TypeHint *inner = patch_type_hint_with_argref_in_context_of_call(as_arg_ref_subkey->inner, current_function, call) ?: as_arg_ref_subkey->inner; - if (const auto *as_array = inner->unwrap_optional()->try_as()) { + if (const auto* as_arg_ref_subkey = child->try_as()) { + const TypeHint* inner = patch_type_hint_with_argref_in_context_of_call(as_arg_ref_subkey->inner, current_function, call) ?: as_arg_ref_subkey->inner; + if (const auto* as_array = inner->unwrap_optional()->try_as()) { return as_array->inner; } } @@ -185,8 +185,8 @@ static const TypeHint *patch_type_hint_with_argref_in_context_of_call(const Type // having a call `map([new A], fn($a) => $a)`, at reification scan KPHP deduces `TIn = A, TOut = unknown` // then it starts patching arguments, `fn` becomes `callable(A):TOut` // this function fills TOut=(assumption of fn)=A, which is also set to f_lambda->return_typehint -static const TypeHint *patch_lambda_return_hint_replacing_genericT_in_call(const TypeHint *type_hint, FunctionPtr f_lambda, VertexAdaptor call) { - if (const auto *as_genericT = type_hint->try_as()) { +static const TypeHint* patch_lambda_return_hint_replacing_genericT_in_call(const TypeHint* type_hint, FunctionPtr f_lambda, VertexAdaptor call) { + if (const auto* as_genericT = type_hint->try_as()) { // implementation detail: this will execute DeduceImplicitTypesAndCastsPass of f_lambda in current thread // like any assumptions, it will correctly analyze `{ $a2 = $a; return $a2; }` // note, that `map([1], fn($i) => $i)` will still work, because assumption `$i=int` is saved @@ -204,7 +204,7 @@ static const TypeHint *patch_lambda_return_hint_replacing_genericT_in_call(const // perform necessary modifications of rhs // the argument `call` is valid for func calls (to resolve ^2 and fill TOut), but is empty for assignments // mind that lambdas and non-lambdas passed to built-in functions are represented as op_callback_of_builtin -void patch_rhs_casting_to_callable(VertexPtr &rhs, const TypeHintCallable *as_callable, VertexAdaptor call) { +void patch_rhs_casting_to_callable(VertexPtr& rhs, const TypeHintCallable* as_callable, VertexAdaptor call) { bool is_extern_func_param = call && call->func_id && call->func_id->is_extern(); InterfacePtr typed_interface = as_callable->is_typed_callable() && as_callable->is_typedata_constexpr() ? as_callable->get_interface() : InterfacePtr{}; @@ -228,7 +228,7 @@ void patch_rhs_casting_to_callable(VertexPtr &rhs, const TypeHintCallable *as_ca f_lambda->return_typehint = patch_lambda_return_hint_replacing_genericT_in_call(as_callable->return_type, f_lambda, call); typed_interface = get_typed_callable_interface_from_lambda(f_lambda); } - rhs.as()->lambda_class = typed_interface; // save for the next pass + rhs.as()->lambda_class = typed_interface; // save for the next pass } else if (VertexUtil::unwrap_inlined_define(rhs)->type() == op_string) { rhs = VertexUtil::unwrap_inlined_define(rhs); @@ -246,8 +246,8 @@ void patch_rhs_casting_to_callable(VertexPtr &rhs, const TypeHintCallable *as_ca v_lambda->lambda_class = typed_interface; rhs = v_lambda; } - } else if (rhs->type() == op_array && rhs->size() == 2 && VertexUtil::unwrap_inlined_define(rhs->front())->type() == op_string - && VertexUtil::unwrap_inlined_define(rhs->back())->type() == op_string) { + } else if (rhs->type() == op_array && rhs->size() == 2 && VertexUtil::unwrap_inlined_define(rhs->front())->type() == op_string && + VertexUtil::unwrap_inlined_define(rhs->back())->type() == op_string) { // ['A', 'staticMethod'] auto unwrapped_front = VertexUtil::unwrap_inlined_define(rhs->front()); auto unwrapped_back = VertexUtil::unwrap_inlined_define(rhs->back()); @@ -310,7 +310,7 @@ void patch_rhs_casting_to_callable(VertexPtr &rhs, const TypeHintCallable *as_ca // the main function that patches rhs to fit lhs type, see detailed comments above // called when rhs is passed as @param, or when @var $v = rhs, or for "return expr" to fit @return, etc -static void patch_rhs_casting_to_lhs_type(VertexPtr &rhs, const TypeHint *lhs_type_hint, VertexAdaptor call = {}) { +static void patch_rhs_casting_to_lhs_type(VertexPtr& rhs, const TypeHint* lhs_type_hint, VertexAdaptor call = {}) { // to avoid redundant work, every type hint has a special flag whether it potentially can require an rhs cast // for example, we do nothing for @param int or @param string[], but start analyzing rhs for @param callable if (!lhs_type_hint->has_flag_maybe_casts_rhs()) { @@ -328,14 +328,14 @@ static void patch_rhs_casting_to_lhs_type(VertexPtr &rhs, const TypeHint *lhs_ty lhs_type_hint = lhs_type_hint->unwrap_optional(); // @param callable — extracted to a separate method, not to mess here - if (const auto *as_callable = lhs_type_hint->try_as()) { + if (const auto* as_callable = lhs_type_hint->try_as()) { patch_rhs_casting_to_callable(rhs, as_callable, call); } // @param (callable():void)[], cast every rhs array's element - if (const auto *as_array = lhs_type_hint->try_as()) { + if (const auto* as_array = lhs_type_hint->try_as()) { if (auto rhs_as_array = rhs.try_as()) { - for (auto &item : *rhs_as_array) { + for (auto& item : *rhs_as_array) { if (auto as_double_arrow = item.try_as()) { patch_rhs_casting_to_lhs_type(as_double_arrow->value(), as_array->inner, call); } else { @@ -346,7 +346,7 @@ static void patch_rhs_casting_to_lhs_type(VertexPtr &rhs, const TypeHint *lhs_ty } // @param tuple(int, callable(...):void), cast correspondent arguments of a passed tuple - if (const auto *as_tuple = lhs_type_hint->try_as()) { + if (const auto* as_tuple = lhs_type_hint->try_as()) { if (auto rhs_as_tuple = rhs.try_as()) { for (int i = 0; i < as_tuple->items.size() && i < rhs_as_tuple->size(); ++i) { patch_rhs_casting_to_lhs_type(rhs_as_tuple->args()[i], as_tuple->items[i], call); @@ -355,11 +355,11 @@ static void patch_rhs_casting_to_lhs_type(VertexPtr &rhs, const TypeHint *lhs_ty } // @param shape(cb: callable(...):int), cast corresponding arguments of a passed shape - if (const auto *as_shape = lhs_type_hint->try_as()) { + if (const auto* as_shape = lhs_type_hint->try_as()) { if (auto rhs_as_shape = rhs.try_as()) { for (auto sub_expr : rhs_as_shape->args()) { - const std::string &shape_key = VertexUtil::get_actual_value(sub_expr->front())->get_string(); - if (const TypeHint *lhs_type_at_key = as_shape->find_at(shape_key)) { + const std::string& shape_key = VertexUtil::get_actual_value(sub_expr->front())->get_string(); + if (const TypeHint* lhs_type_at_key = as_shape->find_at(shape_key)) { patch_rhs_casting_to_lhs_type(sub_expr->back(), lhs_type_at_key, call); } } @@ -367,15 +367,14 @@ static void patch_rhs_casting_to_lhs_type(VertexPtr &rhs, const TypeHint *lhs_ty } } - // we have @kphp-infer cast and ::: syntax in functions.txt that means auto-casting of passed arguments, // but we don't auto-cast in files marked with @kphp-strict-types-enable -static bool is_implicit_cast_allowed(bool strict_types, const TypeHint *type_hint_cast_to) { +static bool is_implicit_cast_allowed(bool strict_types, const TypeHint* type_hint_cast_to) { if (!strict_types) { return true; } // converting to regexp is OK even in strict_types mode - if (const auto *primitive_type = type_hint_cast_to->try_as()) { + if (const auto* primitive_type = type_hint_cast_to->try_as()) { return primitive_type->ptype == tp_regexp; } return false; @@ -383,50 +382,49 @@ static bool is_implicit_cast_allowed(bool strict_types, const TypeHint *type_hin // we have @kphp-infer cast and ::: syntax in functions.txt that means auto-casting of passed arguments // this function performs this cast: it takes rhs and returns a nesessary op_conv_* wrapping rhs -static VertexPtr implicit_cast_call_arg_to_cast_param(VertexPtr rhs, const TypeHint *type_hint_cast_to, bool ref_flag) { +static VertexPtr implicit_cast_call_arg_to_cast_param(VertexPtr rhs, const TypeHint* type_hint_cast_to, bool ref_flag) { PrimitiveType tp = tp_any; if (type_hint_cast_to->try_as()) { tp = tp_array; - } else if (const auto *as_primitive = type_hint_cast_to->try_as()) { + } else if (const auto* as_primitive = type_hint_cast_to->try_as()) { tp = as_primitive->ptype; } if (ref_flag) { switch (tp) { - case tp_array: - return VertexUtil::create_conv_to_lval(tp_array, rhs); - case tp_int: - return VertexUtil::create_conv_to_lval(tp_int, rhs); - case tp_string: - return VertexUtil::create_conv_to_lval(tp_string, rhs); - case tp_mixed: - return rhs; - default: - kphp_error (0, "Too hard rule for cast a param with ref_flag"); - return rhs; - } - } - switch (tp) { + case tp_array: + return VertexUtil::create_conv_to_lval(tp_array, rhs); case tp_int: - return VertexUtil::create_conv_to(tp_int, rhs); - case tp_bool: - return VertexUtil::create_conv_to(tp_bool, rhs); + return VertexUtil::create_conv_to_lval(tp_int, rhs); case tp_string: - return VertexUtil::create_conv_to(tp_string, rhs); - case tp_float: - return VertexUtil::create_conv_to(tp_float, rhs); - case tp_array: - return VertexUtil::create_conv_to(tp_array, rhs); - case tp_regexp: - return VertexUtil::create_conv_to(tp_regexp, rhs); + return VertexUtil::create_conv_to_lval(tp_string, rhs); case tp_mixed: - return VertexUtil::create_conv_to(tp_mixed, rhs); + return rhs; default: + kphp_error(0, "Too hard rule for cast a param with ref_flag"); return rhs; + } + } + switch (tp) { + case tp_int: + return VertexUtil::create_conv_to(tp_int, rhs); + case tp_bool: + return VertexUtil::create_conv_to(tp_bool, rhs); + case tp_string: + return VertexUtil::create_conv_to(tp_string, rhs); + case tp_float: + return VertexUtil::create_conv_to(tp_float, rhs); + case tp_array: + return VertexUtil::create_conv_to(tp_array, rhs); + case tp_regexp: + return VertexUtil::create_conv_to(tp_regexp, rhs); + case tp_mixed: + return VertexUtil::create_conv_to(tp_mixed, rhs); + default: + return rhs; } } - // this pass is very tricky, probably it's the most cognitively hard in KPHP // a function can reach it in 3 ways actually: // - normally, through compilation pipeline @@ -439,7 +437,8 @@ bool DeduceImplicitTypesAndCastsPass::check_function(FunctionPtr f) const { f->assumption_processing_thread = std::this_thread::get_id(); return true; } else if (expected == FunctionData::AssumptionStatus::processing_deduce_pass) { - while (f->assumption_pass_status == FunctionData::AssumptionStatus::processing_deduce_pass && f->assumption_processing_thread != std::this_thread::get_id()) { + while (f->assumption_pass_status == FunctionData::AssumptionStatus::processing_deduce_pass && + f->assumption_processing_thread != std::this_thread::get_id()) { std::this_thread::sleep_for(std::chrono::nanoseconds{100}); } } @@ -491,7 +490,7 @@ VertexPtr DeduceImplicitTypesAndCastsPass::on_exit_vertex(VertexPtr root) { if (root->type() == op_set) { auto lhs = root.as()->lhs(); - auto &rhs = root.as()->rhs(); + auto& rhs = root.as()->rhs(); if (lhs->type() == op_var) { on_set_to_var(lhs.as(), rhs); } else if (lhs->type() == op_instance_prop) { @@ -536,20 +535,23 @@ void DeduceImplicitTypesAndCastsPass::on_func_param(VertexAdaptor // 2) for non-primitives, we check that phpdocs coincide with each other and with code-based assumptions (if any made before phpdoc occured) void DeduceImplicitTypesAndCastsPass::on_phpdoc_for_var(VertexAdaptor v_phpdoc) { Assumption existing = current_function->get_assumption_for_var(v_phpdoc->var()->str_val); - const std::string &var_name = v_phpdoc->var()->str_val; + const std::string& var_name = v_phpdoc->var()->str_val; if (existing) { - const TypeHint *prev_phpdoc_hint = get_found_phpdoc_for_var(var_name); + const TypeHint* prev_phpdoc_hint = get_found_phpdoc_for_var(var_name); if (prev_phpdoc_hint) { // we had @var already, so we expect this @var to be exactly the same kphp_error_return(prev_phpdoc_hint == v_phpdoc->type_hint, - fmt_format("${} has inconsistent phpdocs.\nAt first it was declared as @var {}, and then @var {}", - var_name, TermStringFormat::paint_green(prev_phpdoc_hint->as_human_readable()), TermStringFormat::paint_green(v_phpdoc->type_hint->as_human_readable()))); + fmt_format("${} has inconsistent phpdocs.\nAt first it was declared as @var {}, and then @var {}", var_name, + TermStringFormat::paint_green(prev_phpdoc_hint->as_human_readable()), + TermStringFormat::paint_green(v_phpdoc->type_hint->as_human_readable()))); } else { // we had an assumption for $v already ($v was used to bind arrow calls or instantiate a generic), check that phpdoc equals kphp_error_return(existing.assum_hint == v_phpdoc->type_hint, - fmt_format("You want ${} to have the type {}, but ${} was already used above in this function.\n${} was already assumed to be {}.\nMove this phpdoc above all assignments to ${} to resolve this conflict.", - var_name, TermStringFormat::paint_green(v_phpdoc->type_hint->as_human_readable()), var_name, var_name, TermStringFormat::paint_green(existing.assum_hint->as_human_readable()), var_name)); + fmt_format("You want ${} to have the type {}, but ${} was already used above in this function.\n${} was already assumed to be " + "{}.\nMove this phpdoc above all assignments to ${} to resolve this conflict.", + var_name, TermStringFormat::paint_green(v_phpdoc->type_hint->as_human_readable()), var_name, var_name, + TermStringFormat::paint_green(existing.assum_hint->as_human_readable()), var_name)); } } else { // it it's a primitive, it would be skipped; if not — saved as an assumption @@ -582,13 +584,14 @@ void DeduceImplicitTypesAndCastsPass::on_func_call(VertexAdaptor c auto lhs = call->args()[0]; ClassPtr klass = resolve_class_of_arrow_access(current_function, lhs, call); - if (!klass) { // if so, an error has already been printed + if (!klass) { // if so, an error has already been printed return; } - const auto *method = klass->get_instance_method(call->str_val); + const auto* method = klass->get_instance_method(call->str_val); if (!method) { kphp_error_return(!klass->members.get_static_method(call->str_val), fmt_format("Static method {} is called using $this", call->str_val)); - kphp_error_return(0, fmt_format("Method {}() not found in {} {}", call->str_val, klass->is_interface() ? "interface" : "class", klass->as_human_readable())); + kphp_error_return( + 0, fmt_format("Method {}() not found in {} {}", call->str_val, klass->is_interface() ? "interface" : "class", klass->as_human_readable())); } call->func_id = method->function; @@ -617,9 +620,8 @@ void DeduceImplicitTypesAndCastsPass::on_func_call(VertexAdaptor c // if `f` is a variadic generic `f<...TArg>` called with N=2 arguments, `f$n2` is created and called instead // (same for manually provided variadic types: `f/**/` => `f$n3`) if (f_called->has_variadic_param && f_called->genericTs->is_variadic()) { - int n_variadic = call->reifiedTs - ? call->reifiedTs->commentTs->size() - : call_args.size() - (f_called_params.size() - 1 + f_called->has_implicit_this_arg()); + int n_variadic = + call->reifiedTs ? call->reifiedTs->commentTs->size() : call_args.size() - (f_called_params.size() - 1 + f_called->has_implicit_this_arg()); if (n_variadic >= 0) { f_called = convert_variadic_generic_function_accepting_N_args(f_called, n_variadic); f_called_params = f_called->get_params(); @@ -644,8 +646,8 @@ void DeduceImplicitTypesAndCastsPass::on_func_call(VertexAdaptor c if (param->type_hint) { patch_call_arg_on_func_call(param, call_args[i], call); - if (param->extra_type == op_ex_param_variadic) { // all the rest arguments are meant to be passed to this param - for (++i; i < call_args.size(); ++i) { // here, they are not replaced with an array: see CheckFuncCallsAndVarargPass + if (param->extra_type == op_ex_param_variadic) { // all the rest arguments are meant to be passed to this param + for (++i; i < call_args.size(); ++i) { // here, they are not replaced with an array: see CheckFuncCallsAndVarargPass patch_call_arg_on_func_call(param, call_args[i], call); } } @@ -655,7 +657,7 @@ void DeduceImplicitTypesAndCastsPass::on_func_call(VertexAdaptor c // a helper to print a human-readable error for `f()` when f not found // the return value is not used, it's just to make the code shorter by using `return kphp_error(...)` -int DeduceImplicitTypesAndCastsPass::print_error_unexisting_function(const std::string &call_string) { +int DeduceImplicitTypesAndCastsPass::print_error_unexisting_function(const std::string& call_string) { std::string unexisting_func_name = replace_call_string_to_readable(call_string); // people try to use some of these and struggle to find an alternative @@ -683,8 +685,8 @@ int DeduceImplicitTypesAndCastsPass::print_error_unexisting_function(const std:: } // having `f($arg1, $arg2)`, this functions patches $arg_i to fit the corresponding @param of f() -void DeduceImplicitTypesAndCastsPass::patch_call_arg_on_func_call(VertexAdaptor param, VertexPtr &call_arg, VertexAdaptor call) { - const TypeHint *param_hint = param->type_hint; +void DeduceImplicitTypesAndCastsPass::patch_call_arg_on_func_call(VertexAdaptor param, VertexPtr& call_arg, VertexAdaptor call) { + const TypeHint* param_hint = param->type_hint; // for cast params (::: in functions.txt or '@kphp-infer cast') we add conversions automatically (implicit casts), // unless the file from where we're calling this function is annotated with strict_types=1 @@ -718,8 +720,7 @@ void DeduceImplicitTypesAndCastsPass::on_return(VertexAdaptor v_retur } // this allows mixing void and non-void, but probably, somewhen we'll get rid of this in vkcom - if (current_function->type == FunctionData::func_main || - current_function->type == FunctionData::func_switch || + if (current_function->type == FunctionData::func_main || current_function->type == FunctionData::func_switch || current_function->disabled_warnings.count("return")) { if (v_return->has_expr() && v_return->expr()->type() != op_null) { v_return->expr() = VertexAdaptor::create(v_return->expr()); @@ -728,9 +729,9 @@ void DeduceImplicitTypesAndCastsPass::on_return(VertexAdaptor v_retur } // handle `$v = rhs`, patch rhs to fit @var if it was set to $v -void DeduceImplicitTypesAndCastsPass::on_set_to_var(VertexAdaptor lhs, VertexPtr &rhs) { - const std::string &var_name = lhs->str_val; - const TypeHint *var_type_hint = get_found_phpdoc_for_var(var_name); +void DeduceImplicitTypesAndCastsPass::on_set_to_var(VertexAdaptor lhs, VertexPtr& rhs) { + const std::string& var_name = lhs->str_val; + const TypeHint* var_type_hint = get_found_phpdoc_for_var(var_name); if (var_type_hint) { patch_rhs_casting_to_lhs_type(rhs, var_type_hint); } @@ -745,24 +746,24 @@ void DeduceImplicitTypesAndCastsPass::on_set_to_var(VertexAdaptor lhs, V } // handle `$object->field = rhs`, patch rhs to fir @var of the field -void DeduceImplicitTypesAndCastsPass::on_set_to_instance_prop(VertexAdaptor lhs, VertexPtr &rhs) { - const auto *field = lhs->class_id ? lhs->class_id->get_instance_field(lhs->str_val) : nullptr; +void DeduceImplicitTypesAndCastsPass::on_set_to_instance_prop(VertexAdaptor lhs, VertexPtr& rhs) { + const auto* field = lhs->class_id ? lhs->class_id->get_instance_field(lhs->str_val) : nullptr; if (field && field->type_hint) { patch_rhs_casting_to_lhs_type(rhs, field->type_hint); } } // handle `$a[$idx][$idx2] = rhs` or `$a[] = rhs`, patch rhs to fit @var if it was set to $a -void DeduceImplicitTypesAndCastsPass::on_set_to_index(VertexPtr lhs, VertexPtr &rhs) { +void DeduceImplicitTypesAndCastsPass::on_set_to_index(VertexPtr lhs, VertexPtr& rhs) { int depth = 0; while (lhs->type() == op_index) { depth++; lhs = lhs.as()->array(); } if (lhs->type() == op_var) { - const TypeHint *type_hint_at_depth = get_found_phpdoc_for_var(lhs.as()->str_val); + const TypeHint* type_hint_at_depth = get_found_phpdoc_for_var(lhs.as()->str_val); while (type_hint_at_depth && depth--) { - const auto *as_array = type_hint_at_depth->unwrap_optional()->try_as(); + const auto* as_array = type_hint_at_depth->unwrap_optional()->try_as(); type_hint_at_depth = as_array ? as_array->inner : nullptr; } if (type_hint_at_depth) { @@ -779,7 +780,7 @@ void DeduceImplicitTypesAndCastsPass::on_list(VertexAdaptor v_list) { auto kv = x.as(); if (kv->key()->type() == op_int_const && kv->var()->type() == op_var) { int ith_index = parse_int_from_string(kv->key().as()); - const TypeHint *var_type_hint = get_found_phpdoc_for_var(kv->var()->get_string()); + const TypeHint* var_type_hint = get_found_phpdoc_for_var(kv->var()->get_string()); if (ith_index >= 0 && ith_index < v_list->array()->size() && var_type_hint) { patch_rhs_casting_to_lhs_type(v_list->array().as()->args()[ith_index], var_type_hint); } @@ -792,7 +793,7 @@ void DeduceImplicitTypesAndCastsPass::on_list(VertexAdaptor v_list) { for (auto x : v_list->list()) { auto kv = x.as(); if (auto as_var = kv->var().try_as()) { - const std::string &var_name = as_var->str_val; + const std::string& var_name = as_var->str_val; if (!get_found_phpdoc_for_var(var_name) && current_function->get_assumption_for_var(var_name)) { Assumption rhs_assum = assume_class_of_expr(current_function, v_list->array(), v_list->array()); assumption_add_for_var(current_function, var_name, rhs_assum.get_subkey_by_index(kv->key()), v_list); @@ -807,7 +808,8 @@ void DeduceImplicitTypesAndCastsPass::on_clone(VertexAdaptor v_clone) kphp_error_return(v_clone->class_id, "`clone` keyword can be used only with instances"); kphp_error(!v_clone->class_id->is_lambda_class(), "It's forbidden to `clone` lambdas"); kphp_error(!v_clone->class_id->is_typed_callable_interface(), "It's forbidden to `clone` lambdas"); - kphp_error(!v_clone->class_id->is_builtin() || v_clone->class_id->need_generated_stub || v_clone->class_id->is_ffi_cdata(), "It's forbidden to `clone` built-in classes"); + kphp_error(!v_clone->class_id->is_builtin() || v_clone->class_id->need_generated_stub || v_clone->class_id->is_ffi_cdata(), + "It's forbidden to `clone` built-in classes"); } // handle `throw $ex`, calc assumptions to be used later @@ -824,7 +826,7 @@ void DeduceImplicitTypesAndCastsPass::on_lambda(VertexAdaptor v_lambd void DeduceImplicitTypesAndCastsPass::on_instance_prop(VertexAdaptor v_prop) { // lhs->field; we need to infer the class of lhs ClassPtr klass = resolve_class_of_arrow_access(current_function, v_prop->instance(), v_prop); - if (!klass) { // if so, an error has already been printed + if (!klass) { // if so, an error has already been printed return; } v_prop->class_id = klass; @@ -834,7 +836,7 @@ void DeduceImplicitTypesAndCastsPass::on_instance_prop(VertexAdaptorclass_id->get_instance_field(v_prop->str_val); + const auto* field = v_prop->class_id->get_instance_field(v_prop->str_val); kphp_error_return(field, fmt_format("Field ${} not found in class {}", v_prop->str_val, klass->as_human_readable())); v_prop->var_id = field->var; diff --git a/compiler/pipes/deduce-implicit-types-and-casts.h b/compiler/pipes/deduce-implicit-types-and-casts.h index fe6fd6ef6c..a23a7205f9 100644 --- a/compiler/pipes/deduce-implicit-types-and-casts.h +++ b/compiler/pipes/deduce-implicit-types-and-casts.h @@ -14,8 +14,8 @@ class DeduceImplicitTypesAndCastsPass final : public FunctionPassBase { std::forward_list> generic_calls; std::forward_list nested_lambdas; - const TypeHint *get_found_phpdoc_for_var(const std::string &var_name) { - for (const auto &phpdoc_var : phpdocs_for_vars) { + const TypeHint* get_found_phpdoc_for_var(const std::string& var_name) { + for (const auto& phpdoc_var : phpdocs_for_vars) { if (phpdoc_var->var()->str_val == var_name) { return phpdoc_var->type_hint; } @@ -33,13 +33,13 @@ class DeduceImplicitTypesAndCastsPass final : public FunctionPassBase { void on_finish() override; VertexPtr on_exit_vertex(VertexPtr root) override; - int print_error_unexisting_function(const std::string &call_string); + int print_error_unexisting_function(const std::string& call_string); - void patch_call_arg_on_func_call(VertexAdaptor param, VertexPtr &call_arg, VertexAdaptor call); + void patch_call_arg_on_func_call(VertexAdaptor param, VertexPtr& call_arg, VertexAdaptor call); - void on_set_to_var(VertexAdaptor lhs, VertexPtr &rhs); - void on_set_to_instance_prop(VertexAdaptor lhs, VertexPtr &rhs); - void on_set_to_index(VertexPtr lhs, VertexPtr &rhs); + void on_set_to_var(VertexAdaptor lhs, VertexPtr& rhs); + void on_set_to_instance_prop(VertexAdaptor lhs, VertexPtr& rhs); + void on_set_to_index(VertexPtr lhs, VertexPtr& rhs); void on_func_call(VertexAdaptor call); void on_func_param(VertexAdaptor v_param); void on_return(VertexAdaptor v_return); diff --git a/compiler/pipes/early-optimization.cpp b/compiler/pipes/early-optimization.cpp index d49ea394b1..0dd116b563 100644 --- a/compiler/pipes/early-optimization.cpp +++ b/compiler/pipes/early-optimization.cpp @@ -38,7 +38,6 @@ class EarlyOptimizationPass final : public FunctionPassBase { } private: - VertexPtr on_list(VertexAdaptor root) { auto rhs = root->array().try_as(); if (!rhs || rhs->get_string() != std::string_view{"explode"} || vk::none_of_equal(rhs->args().size(), 2, 3)) { @@ -64,8 +63,8 @@ class EarlyOptimizationPass final : public FunctionPassBase { } std::vector new_call_args; new_call_args.reserve(rhs->args().size() + 1); - new_call_args.push_back(rhs->args()[0]); // delimiter - new_call_args.push_back(rhs->args()[1]); // string + new_call_args.push_back(rhs->args()[0]); // delimiter + new_call_args.push_back(rhs->args()[1]); // string new_call_args.push_back(VertexUtil::create_int_const(mask).set_location(root)); // result mask if (rhs->args().size() == 3) { new_call_args.push_back(rhs->args()[2]); // limit @@ -112,7 +111,7 @@ class EarlyOptimizationPass final : public FunctionPassBase { } }; -void EarlyOptimizationF::execute(FunctionPtr f, DataStream &os) { +void EarlyOptimizationF::execute(FunctionPtr f, DataStream& os) { if (!f->is_extern()) { run_early_opt_rules_pass(f); @@ -122,4 +121,3 @@ void EarlyOptimizationF::execute(FunctionPtr f, DataStream &os) { os << f; } - diff --git a/compiler/pipes/early-optimization.h b/compiler/pipes/early-optimization.h index b41b322c13..cac4c7edac 100644 --- a/compiler/pipes/early-optimization.h +++ b/compiler/pipes/early-optimization.h @@ -12,5 +12,5 @@ // that would execute faster or allocate less heap memory. class EarlyOptimizationF { public: - void execute(FunctionPtr f, DataStream &os); + void execute(FunctionPtr f, DataStream& os); }; diff --git a/compiler/pipes/extract-async.cpp b/compiler/pipes/extract-async.cpp index 498b3f89db..ecfe58b744 100644 --- a/compiler/pipes/extract-async.cpp +++ b/compiler/pipes/extract-async.cpp @@ -45,7 +45,8 @@ void ExtractAsyncPass::raise_cant_save_result_of_resumable_func(FunctionPtr func kphp_error(false, fmt_format("Can't save result of resumable function {} into non-var inside another resumable function\n" "Consider using a temporary variable for this call.\n" "Function is resumable because of calls chain:\n" - "{}", func->as_human_readable(), func->get_resumable_path())); + "{}", + func->as_human_readable(), func->get_resumable_path())); } else if (cnt == max_errors_count) { kphp_error(false, "Too many same errors about resumable functions, will skip others"); } diff --git a/compiler/pipes/extract-resumable-calls.cpp b/compiler/pipes/extract-resumable-calls.cpp index 22e522fb62..227b97aa16 100644 --- a/compiler/pipes/extract-resumable-calls.cpp +++ b/compiler/pipes/extract-resumable-calls.cpp @@ -5,11 +5,11 @@ #include "compiler/pipes/extract-resumable-calls.h" #include "compiler/compiler-core.h" -#include "compiler/vertex-util.h" #include "compiler/inferring/public.h" #include "compiler/name-gen.h" +#include "compiler/vertex-util.h" -VertexPtr *ExtractResumableCallsPass::skip_conv_and_sets(VertexPtr *replace) noexcept { +VertexPtr* ExtractResumableCallsPass::skip_conv_and_sets(VertexPtr* replace) noexcept { if (auto set_modify = replace->try_as()) { return skip_conv_and_sets(&(set_modify->rhs())); } @@ -42,8 +42,8 @@ bool ExtractResumableCallsPass::is_resumable_expr(VertexPtr vertex) noexcept { return false; } -VertexPtr *ExtractResumableCallsPass::extract_resumable_expr(VertexPtr vertex) noexcept { - VertexPtr *resumable_expr = nullptr; +VertexPtr* ExtractResumableCallsPass::extract_resumable_expr(VertexPtr vertex) noexcept { + VertexPtr* resumable_expr = nullptr; if (auto return_v = vertex.try_as()) { resumable_expr = return_v->has_expr() ? &return_v->expr() : nullptr; @@ -99,12 +99,12 @@ std::pair, VertexAdaptor> ExtractResumableCallsPa VertexPtr ExtractResumableCallsPass::replace_set_ternary(VertexAdaptor set_vertex, VertexAdaptor rhs_ternary) noexcept { auto set_true_case = set_vertex.clone(); - VertexPtr &true_case_rhs = *skip_conv_and_sets(&set_true_case->rhs()); + VertexPtr& true_case_rhs = *skip_conv_and_sets(&set_true_case->rhs()); true_case_rhs = rhs_ternary->true_expr(); true_case_rhs->val_ref_flag = rhs_ternary->val_ref_flag; auto set_false_case = set_vertex.clone(); - VertexPtr &false_case_rhs = *skip_conv_and_sets(&set_false_case->rhs()); + VertexPtr& false_case_rhs = *skip_conv_and_sets(&set_false_case->rhs()); false_case_rhs = rhs_ternary->false_expr(); false_case_rhs->val_ref_flag = rhs_ternary->val_ref_flag; @@ -119,23 +119,23 @@ VertexPtr ExtractResumableCallsPass::replace_set_logical_operation(VertexAdaptor auto set_if_lhs_false = set_vertex.clone(); switch (operation->type()) { - case op_log_or: - *skip_conv_and_sets(&set_if_lhs_true->rhs()) = temp_var.first; - *skip_conv_and_sets(&set_if_lhs_false->rhs()) = operation->rhs(); - break; - case op_log_and: - *skip_conv_and_sets(&set_if_lhs_false->rhs()) = temp_var.first; - *skip_conv_and_sets(&set_if_lhs_true->rhs()) = operation->rhs(); - break; - default: - kphp_assert(0 && "unexpected type"); + case op_log_or: + *skip_conv_and_sets(&set_if_lhs_true->rhs()) = temp_var.first; + *skip_conv_and_sets(&set_if_lhs_false->rhs()) = operation->rhs(); + break; + case op_log_and: + *skip_conv_and_sets(&set_if_lhs_false->rhs()) = temp_var.first; + *skip_conv_and_sets(&set_if_lhs_true->rhs()) = operation->rhs(); + break; + default: + kphp_assert(0 && "unexpected type"); } auto check_lhs = VertexAdaptor::create(temp_var.second, VertexUtil::embrace(set_if_lhs_true), VertexUtil::embrace(set_if_lhs_false)); return VertexUtil::embrace(check_lhs.set_rl_type(val_none).set_location(operation)); } -VertexPtr ExtractResumableCallsPass::replace_resumable_expr_with_temp_var(VertexPtr *resumable_expr, VertexPtr expr_user) noexcept { +VertexPtr ExtractResumableCallsPass::replace_resumable_expr_with_temp_var(VertexPtr* resumable_expr, VertexPtr expr_user) noexcept { auto temp_var = make_temp_resumable_var(*resumable_expr); *resumable_expr = temp_var.first; return VertexAdaptor::create(temp_var.second, expr_user).set_rl_type(val_none).set_location(expr_user); @@ -146,7 +146,7 @@ VertexPtr ExtractResumableCallsPass::on_enter_vertex(VertexPtr vertex) { return vertex; } - VertexPtr *resumable_expr = extract_resumable_expr(vertex); + VertexPtr* resumable_expr = extract_resumable_expr(vertex); if (!resumable_expr) { return vertex; } diff --git a/compiler/pipes/extract-resumable-calls.h b/compiler/pipes/extract-resumable-calls.h index 1a09d5dd1c..90b2e0295a 100644 --- a/compiler/pipes/extract-resumable-calls.h +++ b/compiler/pipes/extract-resumable-calls.h @@ -8,14 +8,14 @@ class ExtractResumableCallsPass final : public FunctionPassBase { private: - static VertexPtr *skip_conv_and_sets(VertexPtr *replace) noexcept; + static VertexPtr* skip_conv_and_sets(VertexPtr* replace) noexcept; static bool is_resumable_expr(VertexPtr vertex) noexcept; - static VertexPtr *extract_resumable_expr(VertexPtr vertex) noexcept; + static VertexPtr* extract_resumable_expr(VertexPtr vertex) noexcept; static std::pair, VertexAdaptor> make_temp_resumable_var(VertexPtr init) noexcept; static VertexPtr replace_set_ternary(VertexAdaptor set_vertex, VertexAdaptor rhs_ternary) noexcept; static VertexPtr replace_set_logical_operation(VertexAdaptor set_vertex, VertexAdaptor operation) noexcept; - static VertexPtr replace_resumable_expr_with_temp_var(VertexPtr *resumable_expr, VertexPtr expr_user) noexcept; + static VertexPtr replace_resumable_expr_with_temp_var(VertexPtr* resumable_expr, VertexPtr expr_user) noexcept; public: std::string get_description() override { @@ -25,5 +25,4 @@ class ExtractResumableCallsPass final : public FunctionPassBase { bool check_function(FunctionPtr function) const override; VertexPtr on_enter_vertex(VertexPtr vertex) override; - }; diff --git a/compiler/pipes/file-to-tokens.cpp b/compiler/pipes/file-to-tokens.cpp index cfbc22c12f..1d434017a0 100644 --- a/compiler/pipes/file-to-tokens.cpp +++ b/compiler/pipes/file-to-tokens.cpp @@ -9,7 +9,7 @@ #include "compiler/stage.h" #include "compiler/threading/profiler.h" -void FileToTokensF::execute(SrcFilePtr file, DataStream>> &os) { +void FileToTokensF::execute(SrcFilePtr file, DataStream>>& os) { stage::set_name("Split file to tokens"); stage::set_file(file); kphp_assert(file); diff --git a/compiler/pipes/file-to-tokens.h b/compiler/pipes/file-to-tokens.h index 3640c6f2d7..d4e2908bfd 100644 --- a/compiler/pipes/file-to-tokens.h +++ b/compiler/pipes/file-to-tokens.h @@ -10,5 +10,5 @@ class FileToTokensF { public: - void execute(SrcFilePtr file, DataStream>> &os); + void execute(SrcFilePtr file, DataStream>>& os); }; diff --git a/compiler/pipes/filter-only-actually-used.cpp b/compiler/pipes/filter-only-actually-used.cpp index 6d3a76f1a0..71a844b63b 100644 --- a/compiler/pipes/filter-only-actually-used.cpp +++ b/compiler/pipes/filter-only-actually-used.cpp @@ -5,10 +5,10 @@ #include "compiler/pipes/filter-only-actually-used.h" #include "common/algorithms/find.h" +#include "compiler/compiler-core.h" #include "compiler/data/class-data.h" #include "compiler/data/function-data.h" #include "compiler/data/src-file.h" -#include "compiler/compiler-core.h" #include "compiler/threading/profiler.h" #include "compiler/vertex-util.h" @@ -24,7 +24,7 @@ class RemoveLambdaCallFromTypedCallablePass final : public FunctionPassBase { } explicit RemoveLambdaCallFromTypedCallablePass(ClassPtr lambda_class_to_remove) - : case_hash(std::to_string(lambda_class_to_remove->get_hash())) {} + : case_hash(std::to_string(lambda_class_to_remove->get_hash())) {} VertexPtr on_enter_vertex(VertexPtr root) override { if (auto as_case = root.try_as()) { @@ -46,21 +46,21 @@ class RemoveLambdaCallFromTypedCallablePass final : public FunctionPassBase { // to prevent this, manually remove this lambda from that __invoke() body // as well as remove all lambda's mentions from used_functions class AnalyzeLambdasInUnusedFunctionPass final : public FunctionPassBase { - IdMap &used_functions; + IdMap& used_functions; public: std::string get_description() override { return "Analyze lambdas in unused function"; } - explicit AnalyzeLambdasInUnusedFunctionPass(IdMap &used_functions) - : used_functions(used_functions) {} + explicit AnalyzeLambdasInUnusedFunctionPass(IdMap& used_functions) + : used_functions(used_functions) {} VertexPtr on_enter_vertex(VertexPtr root) override { if (auto as_call = root.try_as(); - as_call && as_call->func_id->class_id && as_call->func_id->class_id->is_lambda_class() && as_call->func_id->is_constructor()) { + as_call && as_call->func_id->class_id && as_call->func_id->class_id->is_lambda_class() && as_call->func_id->is_constructor()) { ClassPtr lambda_class = as_call->func_id->class_id; - const ClassMemberInstanceMethod *m_invoke = lambda_class->members.get_instance_method("__invoke"); + const ClassMemberInstanceMethod* m_invoke = lambda_class->members.get_instance_method("__invoke"); if (m_invoke && used_functions[m_invoke->function->outer_function]) { // f_lambda occurs inside unused function, but is used; the only reason is it's used from a typed callable FunctionPtr f_lambda = m_invoke->function->outer_function; @@ -90,16 +90,15 @@ using FunctionAndEdges = FilterOnlyActuallyUsedFunctionsF::FunctionAndEdges; struct ThrowGraphNode { FunctionPtr f; - std::vector> &try_stack; + std::vector>& try_stack; - ThrowGraphNode(FunctionPtr f, std::vector> &try_stack): - f{f}, - try_stack{try_stack} - {} + ThrowGraphNode(FunctionPtr f, std::vector>& try_stack) + : f{f}, + try_stack{try_stack} {} }; -void calc_throws_dfs(FunctionPtr callee, IdMap> &throws_graph) { - for (ThrowGraphNode &n : throws_graph[callee]) { +void calc_throws_dfs(FunctionPtr callee, IdMap>& throws_graph) { + for (ThrowGraphNode& n : throws_graph[callee]) { FunctionPtr caller = n.f; for (auto e : callee->exceptions_thrown) { @@ -116,8 +115,8 @@ void calc_throws_dfs(FunctionPtr callee, IdMap> &thr } } -void calc_non_empty_body_dfs(FunctionPtr callee, const IdMap> &non_empty_body_graph) { - for (const FunctionPtr &caller : non_empty_body_graph[callee]) { +void calc_non_empty_body_dfs(FunctionPtr callee, const IdMap>& non_empty_body_graph) { + for (const FunctionPtr& caller : non_empty_body_graph[callee]) { kphp_assert_msg(caller->body_seq != FunctionData::body_value::empty, "Body can't be empty!"); if (caller->body_seq == FunctionData::body_value::unknown) { caller->body_seq = FunctionData::body_value::non_empty; @@ -126,32 +125,31 @@ void calc_non_empty_body_dfs(FunctionPtr callee, const IdMap &all) { +void calc_throws_and_body_value_through_call_edges(std::vector& all) { IdMap> throws_graph(static_cast(all.size())); IdMap> non_empty_body_graph(static_cast(all.size())); - for (const auto &f_and_e : all) { - for (const auto &edge : f_and_e.second) { + for (const auto& f_and_e : all) { + for (const auto& edge : f_and_e.second) { if (edge.inside_fork) { edge.called_f->body_seq = FunctionData::body_value::non_empty; } } } - for (auto &f_and_e : all) { + for (auto& f_and_e : all) { FunctionPtr fun = f_and_e.first; - for (auto &edge : f_and_e.second) { + for (auto& edge : f_and_e.second) { if (edge.can_throw) { kphp_assert(edge.called_f); throws_graph[edge.called_f].emplace_back(fun, edge.try_stack); } - if (fun->body_seq == FunctionData::body_value::unknown - && edge.called_f->body_seq != FunctionData::body_value::empty) { + if (fun->body_seq == FunctionData::body_value::unknown && edge.called_f->body_seq != FunctionData::body_value::empty) { non_empty_body_graph[edge.called_f].emplace_back(fun); } } } - for (const auto &f_and_e : all) { + for (const auto& f_and_e : all) { FunctionPtr fun = f_and_e.first; if (fun->can_throw()) { calc_throws_dfs(fun, throws_graph); @@ -161,7 +159,7 @@ void calc_throws_and_body_value_through_call_edges(std::vector } } - for (const auto &f_and_e : all) { + for (const auto& f_and_e : all) { FunctionPtr fun = f_and_e.first; if (fun->body_seq == FunctionData::body_value::unknown) { fun->body_seq = FunctionData::body_value::empty; @@ -169,23 +167,21 @@ void calc_throws_and_body_value_through_call_edges(std::vector } } - -void calc_actually_used_dfs(FunctionPtr from, IdMap &used_functions, - const IdMap> &call_graph) { +void calc_actually_used_dfs(FunctionPtr from, IdMap& used_functions, const IdMap>& call_graph) { used_functions[from] = from; - for (const auto &to : call_graph[from]) { + for (const auto& to : call_graph[from]) { if (!used_functions[to.called_f]) { calc_actually_used_dfs(to.called_f, used_functions, call_graph); } } } -void mark_profiler_dfs(FunctionPtr caller, const IdMap> &call_graph) { +void mark_profiler_dfs(FunctionPtr caller, const IdMap>& call_graph) { if (caller->profiler_state == FunctionData::profiler_status::disable) { return; } - for (const auto &edge: call_graph[caller]) { + for (const auto& edge : call_graph[caller]) { if (edge.called_f->profiler_state == FunctionData::profiler_status::disable) { edge.called_f->profiler_state = FunctionData::profiler_status::enable_as_child; mark_profiler_dfs(edge.called_f, call_graph); @@ -194,35 +190,33 @@ void mark_profiler_dfs(FunctionPtr caller, const IdMap> &c } struct DfsException : std::runtime_error { - DfsException(FunctionPtr f, std::string &&msg) : - runtime_error(std::move(msg)), - function(f) {} + DfsException(FunctionPtr f, std::string&& msg) + : runtime_error(std::move(msg)), + function(f) {} FunctionPtr function; }; -void mark_performance_inspections_dfs(FunctionPtr caller, const IdMap> &call_graph) { - for (const auto &edge: call_graph[caller]) { +void mark_performance_inspections_dfs(FunctionPtr caller, const IdMap>& call_graph) { + for (const auto& edge : call_graph[caller]) { if (edge.called_f->is_extern()) { continue; } const auto analyse_inherit_res = edge.called_f->performance_inspections_for_analysis.merge_with_caller(caller->performance_inspections_for_analysis); if (analyse_inherit_res.first == PerformanceInspections::InheritStatus::conflict) { - throw DfsException{edge.called_f, - fmt_format("@kphp-analyze-performance conflict, one caller enables '{}' while other disables it", - PerformanceInspections::inspection2string(analyse_inherit_res.second))}; + throw DfsException{edge.called_f, fmt_format("@kphp-analyze-performance conflict, one caller enables '{}' while other disables it", + PerformanceInspections::inspection2string(analyse_inherit_res.second))}; } const auto warning_inherit_res = edge.called_f->performance_inspections_for_warning.merge_with_caller(caller->performance_inspections_for_warning); if (warning_inherit_res.first != PerformanceInspections::InheritStatus::no_need) { edge.called_f->performance_inspections_for_warning_parents.emplace_front(caller); } if (warning_inherit_res.first == PerformanceInspections::InheritStatus::conflict) { - throw DfsException{edge.called_f, - fmt_format("@kphp-warn-performance conflict, one caller enables '{}' while other disables it\n" - "Enabled by: {}\nDisabled by: {}", - PerformanceInspections::inspection2string(warning_inherit_res.second), - edge.called_f->get_performance_inspections_warning_chain(warning_inherit_res.second, false), - edge.called_f->get_performance_inspections_warning_chain(warning_inherit_res.second, true))}; + throw DfsException{edge.called_f, fmt_format("@kphp-warn-performance conflict, one caller enables '{}' while other disables it\n" + "Enabled by: {}\nDisabled by: {}", + PerformanceInspections::inspection2string(warning_inherit_res.second), + edge.called_f->get_performance_inspections_warning_chain(warning_inherit_res.second, false), + edge.called_f->get_performance_inspections_warning_chain(warning_inherit_res.second, true))}; } if (vk::any_of_equal(PerformanceInspections::InheritStatus::ok, analyse_inherit_res.first, warning_inherit_res.first)) { mark_performance_inspections_dfs(edge.called_f, call_graph); @@ -230,24 +224,22 @@ void mark_performance_inspections_dfs(FunctionPtr caller, const IdMap calc_actually_used_having_call_edges(std::vector &all) { +IdMap calc_actually_used_having_call_edges(std::vector& all) { IdMap used_functions(static_cast(all.size())); IdMap> call_graph(static_cast(all.size())); - for (auto &f_and_e : all) { + for (auto& f_and_e : all) { call_graph[f_and_e.first] = std::move(f_and_e.second); } - for (const auto &f_and_e : all) { + for (const auto& f_and_e : all) { FunctionPtr fun = f_and_e.first; - const bool should_be_used_apriori = - fun->is_main_function() || - fun->type == FunctionData::func_class_holder || // classes should be carried along the pipeline - (fun->is_extern() && vk::any_of_equal(fun->name, "wait", "make_clone")) || - fun->kphp_lib_export || - (fun->modifiers.is_instance() && fun->local_name() == ClassData::NAME_OF_TO_STRING) || - (fun->modifiers.is_instance() && fun->local_name() == ClassData::NAME_OF_WAKEUP) || - (fun->modifiers.is_instance() && fun->class_id->is_required_interface); + const bool should_be_used_apriori = fun->is_main_function() || + fun->type == FunctionData::func_class_holder || // classes should be carried along the pipeline + (fun->is_extern() && vk::any_of_equal(fun->name, "wait", "make_clone")) || fun->kphp_lib_export || + (fun->modifiers.is_instance() && fun->local_name() == ClassData::NAME_OF_TO_STRING) || + (fun->modifiers.is_instance() && fun->local_name() == ClassData::NAME_OF_WAKEUP) || + (fun->modifiers.is_instance() && fun->class_id->is_required_interface); if (should_be_used_apriori && !used_functions[fun]) { calc_actually_used_dfs(fun, used_functions, call_graph); } @@ -264,7 +256,7 @@ IdMap calc_actually_used_having_call_edges(std::vector calc_actually_used_having_call_edges(std::vector &all, const IdMap &used_functions) { - for (const auto &f_and_e : all) { +void remove_unused_class_methods(const std::vector& all, const IdMap& used_functions) { + for (const auto& f_and_e : all) { FunctionPtr fun = f_and_e.first; if (fun->type == FunctionData::func_class_holder) { fun->class_id->members.remove_if( - [&used_functions](const ClassMemberStaticMethod &m) { - return get_index(m.function) == -1 || !used_functions[m.function]; - }); + [&used_functions](const ClassMemberStaticMethod& m) { return get_index(m.function) == -1 || !used_functions[m.function]; }); fun->class_id->members.remove_if( - [&used_functions](const ClassMemberInstanceMethod &m) { - return get_index(m.function) == -1 || !used_functions[m.function]; - }); + [&used_functions](const ClassMemberInstanceMethod& m) { return get_index(m.function) == -1 || !used_functions[m.function]; }); } } } } // namespace -void FilterOnlyActuallyUsedFunctionsF::on_finish(DataStream &os) { +void FilterOnlyActuallyUsedFunctionsF::on_finish(DataStream& os) { if (G->settings().profiler_level.get() == 2) { G->get_main_file()->main_function->profiler_state = FunctionData::profiler_status::enable_as_root; } @@ -307,13 +295,13 @@ void FilterOnlyActuallyUsedFunctionsF::on_finish(DataStream &os) { } // uncomment this to debug "invalid index of IdMap: -1" -// for (const auto &f_and_e : all) { -// for (const auto &edge : f_and_e.second) { -// if (get_index(edge.called_f) == -1) { -// printf("-1 of %s -> %s\n", f_and_e.first->name.c_str(), edge.called_f->name.c_str()); -// } -// } -// } + // for (const auto &f_and_e : all) { + // for (const auto &edge : f_and_e.second) { + // if (get_index(edge.called_f) == -1) { + // printf("-1 of %s -> %s\n", f_and_e.first->name.c_str(), edge.called_f->name.c_str()); + // } + // } + // } stage::set_name("Calc throws and body value"); stage::set_file(SrcFilePtr()); @@ -336,7 +324,7 @@ void FilterOnlyActuallyUsedFunctionsF::on_finish(DataStream &os) { stage::die_if_global_errors(); // remove lambdas from unused functions, see comments above - for (const auto &f_and_e : all) { + for (const auto& f_and_e : all) { FunctionPtr fun = f_and_e.first; if (fun->has_lambdas_inside && !fun->is_lambda() && !used_functions[fun]) { AnalyzeLambdasInUnusedFunctionPass pass(used_functions); @@ -347,10 +335,9 @@ void FilterOnlyActuallyUsedFunctionsF::on_finish(DataStream &os) { // forward the reachable functions into the data stream; // this should be the last step - for (const auto &f : used_functions) { + for (const auto& f : used_functions) { if (f) { os << f; } } } - diff --git a/compiler/pipes/filter-only-actually-used.h b/compiler/pipes/filter-only-actually-used.h index 76b5ada429..b6bc2176e5 100644 --- a/compiler/pipes/filter-only-actually-used.h +++ b/compiler/pipes/filter-only-actually-used.h @@ -23,12 +23,13 @@ using FunctionAndEdges = std::pair>; // 4) Sends actually reachable functions to the os. // All instance functions are parsed, but this pipe sends only those that are actually used. // 5) Removes the unused class methods. -class FilterOnlyActuallyUsedFunctionsF final: public SyncPipeF { +class FilterOnlyActuallyUsedFunctionsF final : public SyncPipeF { public: using EdgeInfo = filter_detail::EdgeInfo; using FunctionAndEdges = filter_detail::FunctionAndEdges; + public: FilterOnlyActuallyUsedFunctionsF() = default; - void on_finish(DataStream &os) final; + void on_finish(DataStream& os) final; }; diff --git a/compiler/pipes/final-check.cpp b/compiler/pipes/final-check.cpp index 9d6fcb96c7..a40324fdd9 100644 --- a/compiler/pipes/final-check.cpp +++ b/compiler/pipes/final-check.cpp @@ -22,7 +22,7 @@ void check_class_immutableness(ClassPtr klass) { if (!klass->is_immutable) { return; } - klass->members.for_each([klass](const ClassMemberInstanceField &field) { + klass->members.for_each([klass](const ClassMemberInstanceField& field) { kphp_assert(field.var->marked_as_const); std::unordered_set sub_classes; field.var->tinf_node.get_type()->get_all_class_types_inside(sub_classes); @@ -30,14 +30,12 @@ void check_class_immutableness(ClassPtr klass) { kphp_error(sub_class->is_immutable || sub_class->is_interface(), fmt_format("Field {} of immutable class {} should be immutable too, but class {} is mutable", TermStringFormat::paint(std::string{field.local_name()}, TermStringFormat::red), - TermStringFormat::paint(klass->name, TermStringFormat::red), - TermStringFormat::paint(sub_class->name, TermStringFormat::red))); + TermStringFormat::paint(klass->name, TermStringFormat::red), TermStringFormat::paint(sub_class->name, TermStringFormat::red))); } }); kphp_error(!klass->parent_class || klass->parent_class->is_immutable, - fmt_format("Immutable class {} has mutable base {}", - TermStringFormat::paint(klass->name, TermStringFormat::red), + fmt_format("Immutable class {} has mutable base {}", TermStringFormat::paint(klass->name, TermStringFormat::red), TermStringFormat::paint(klass->parent_class->name, TermStringFormat::red))); } @@ -49,7 +47,7 @@ void check_fields_ic_compatibility(ClassPtr klass) { if (!klass->process_fields_ic_compatibility.compare_exchange_strong(flag, true, std::memory_order_acq_rel)) { return; } - klass->members.for_each([klass](const ClassMemberInstanceField &field) { + klass->members.for_each([klass](const ClassMemberInstanceField& field) { kphp_assert(field.var->marked_as_const); std::unordered_set sub_classes; field.var->tinf_node.get_type()->get_all_class_types_inside(sub_classes); @@ -57,11 +55,11 @@ void check_fields_ic_compatibility(ClassPtr klass) { // sub_class already checked for is_immutable || is_interface @see check_class_immutableness check_fields_ic_compatibility(sub_class); std::vector descendants = find_not_ic_compatibility_derivatives(sub_class); - for (auto & element : descendants) { - kphp_error(false, fmt_format("Field {} of immutable class {} has mutable derived {}", - TermStringFormat::paint(std::string{field.local_name()}, TermStringFormat::red), - TermStringFormat::paint(klass->name, TermStringFormat::red), - TermStringFormat::paint(element->name, TermStringFormat::red))); + for (auto& element : descendants) { + kphp_error(false, + fmt_format("Field {} of immutable class {} has mutable derived {}", + TermStringFormat::paint(std::string{field.local_name()}, TermStringFormat::red), + TermStringFormat::paint(klass->name, TermStringFormat::red), TermStringFormat::paint(element->name, TermStringFormat::red))); } } }); @@ -71,7 +69,7 @@ void check_fields_ic_compatibility(ClassPtr klass) { void check_derivatives_ic_compatibility(ClassPtr klass) { // In case of K2 mode, all checks about serializability have already done std::vector descendants = find_not_ic_compatibility_derivatives(klass); - for (const auto &element : descendants) { + for (const auto& element : descendants) { kphp_error(false, fmt_format("Can not store polymorphic type {} with mutable derived class {}", klass->name, element->name)); } } @@ -83,7 +81,7 @@ std::vector find_not_ic_compatibility_derivatives(ClassPtr klass) { while (!stack.empty()) { ClassPtr current = stack.back(); stack.pop_back(); - for (const auto & derived : current->derived_classes) { + for (const auto& derived : current->derived_classes) { if (derived->is_subtree_immutable.load(std::memory_order_acquire) == SubtreeImmutableType::immutable) { // continue } else if (derived->is_subtree_immutable.load(std::memory_order_acquire) == SubtreeImmutableType::not_immutable) { @@ -96,8 +94,7 @@ std::vector find_not_ic_compatibility_derivatives(ClassPtr klass) { } } } - klass->is_subtree_immutable.store(has_mutable_subtree || !mutable_children.empty() - ? SubtreeImmutableType::not_immutable : SubtreeImmutableType::immutable, + klass->is_subtree_immutable.store(has_mutable_subtree || !mutable_children.empty() ? SubtreeImmutableType::not_immutable : SubtreeImmutableType::immutable, std::memory_order_release); return mutable_children; } @@ -106,7 +103,7 @@ void process_job_worker_class(ClassPtr klass) { auto request_interface = G->get_class("KphpJobWorkerRequest"); auto response_interface = G->get_class("KphpJobWorkerResponse"); auto shared_memory_piece_interface = G->get_class("KphpJobWorkerSharedMemoryPiece"); - if (!shared_memory_piece_interface) { // when functions.txt deleted while development + if (!shared_memory_piece_interface) { // when functions.txt deleted while development return; } @@ -119,14 +116,17 @@ void process_job_worker_class(ClassPtr klass) { klass->deeply_require_virtual_builtin_functions(); } if (implements_shared_memory_piece) { - kphp_error(klass->is_immutable, fmt_format("Class {} must be immutable (@kphp-immutable-class) as it implements KphpJobWorkerSharedMemoryPiece", klass->name)); + kphp_error(klass->is_immutable, + fmt_format("Class {} must be immutable (@kphp-immutable-class) as it implements KphpJobWorkerSharedMemoryPiece", klass->name)); } if (implements_request) { - std::vector shared_memory_pieces_fields = klass->get_job_shared_memory_pieces(); - kphp_error(shared_memory_pieces_fields.size() <= 1, fmt_format("Class {} must have at most 1 member implementing KphpJobWorkerSharedMemoryPiece, but {} found", klass->name, shared_memory_pieces_fields.size())); + std::vector shared_memory_pieces_fields = klass->get_job_shared_memory_pieces(); + kphp_error(shared_memory_pieces_fields.size() <= 1, + fmt_format("Class {} must have at most 1 member implementing KphpJobWorkerSharedMemoryPiece, but {} found", klass->name, + shared_memory_pieces_fields.size())); klass->has_job_shared_memory_piece = !shared_memory_pieces_fields.empty(); } -}; +} void check_instance_cache_fetch_call(VertexAdaptor call) { auto klass = tinf::get_type(call)->class_type(); @@ -134,8 +134,7 @@ void check_instance_cache_fetch_call(VertexAdaptor call) { kphp_error(klass->is_immutable || klass->is_interface(), fmt_format("Can not fetch instance of mutable class {} with instance_cache_fetch call", klass->name)); - kphp_error(klass->is_serializable, - fmt_format("Can not fetch instance of non-serializable class {} with instance_cache_fetch call", klass->name)); + kphp_error(klass->is_serializable, fmt_format("Can not fetch instance of non-serializable class {} with instance_cache_fetch call", klass->name)); if (G->is_output_mode_k2()) { // To be able to store instances in request cache @@ -146,7 +145,7 @@ void check_instance_cache_fetch_call(VertexAdaptor call) { } void check_instance_cache_store_call(VertexAdaptor call) { - const auto *type = tinf::get_type(call->args()[1]); + const auto* type = tinf::get_type(call->args()[1]); kphp_error_return(type->ptype() == tp_Class, "Called instance_cache_store() with a non-instance argument"); auto klass = type->class_type(); kphp_error(!klass->is_empty_class(), fmt_format("Can not store instance of empty class {} with instance_cache_store call", klass->name)); @@ -174,14 +173,14 @@ void to_array_debug_on_class(ClassPtr klass) { } void check_to_array_debug_call(VertexAdaptor call) { - const auto *type = tinf::get_type(call->args()[0]); + const auto* type = tinf::get_type(call->args()[0]); const auto ptype = type->ptype(); if (ptype == tp_Class) { to_array_debug_on_class(type->class_type()); } else if (vk::any_of_equal(ptype, tp_tuple, tp_shape)) { std::unordered_set classes; type->get_all_class_types_inside(classes); - for (const auto &klass : classes) { + for (const auto& klass : classes) { to_array_debug_on_class(klass); } } else { @@ -189,8 +188,8 @@ void check_to_array_debug_call(VertexAdaptor call) { } } -void check_field_of_a_jsonable_class(const ClassMemberInstanceField &field, const kphp_json::FieldJsonSettings &props, bool to_encode) noexcept { - const TypeData *type = tinf::get_type(field.var); +void check_field_of_a_jsonable_class(const ClassMemberInstanceField& field, const kphp_json::FieldJsonSettings& props, bool to_encode) noexcept { + const TypeData* type = tinf::get_type(field.var); kphp_error_return(!props.array_as_hashmap || type->ptype() == tp_array, fmt_format("Field {} is @kphp-json 'array_as_hashmap', but it's not an array", field.var->as_human_readable())); @@ -198,21 +197,24 @@ void check_field_of_a_jsonable_class(const ClassMemberInstanceField &field, cons fmt_format("Field {} is @kphp-json 'raw_string', but it's not a string", field.var->as_human_readable())); if (field.type_hint) { - field.type_hint->traverse([field, to_encode](const TypeHint *child) { + field.type_hint->traverse([field, to_encode](const TypeHint* child) { // for now, these types are denied both for encoding and decoding, // though potentially tuples and shapes can easily be allowed at least for encoding bool denied = child->try_as() || child->try_as() || child->try_as() || child->try_as(); - if (const auto *as_instance = child->try_as()) { + if (const auto* as_instance = child->try_as()) { ClassPtr field_class = as_instance->resolve(); denied = field_class->is_builtin(); if (!to_encode) { if (field_class->is_interface()) { - kphp_error(0, fmt_format("Json decoding for {} is unavailable, because {} is an interface", field.var->as_human_readable(), field_class->as_human_readable())); + kphp_error(0, fmt_format("Json decoding for {} is unavailable, because {} is an interface", field.var->as_human_readable(), + field_class->as_human_readable())); } else if (field_class->modifiers.is_abstract()) { - kphp_error(0, fmt_format("Json decoding for {} is unavailable, because {} is an abstract class", field.var->as_human_readable(), field_class->as_human_readable())); + kphp_error(0, fmt_format("Json decoding for {} is unavailable, because {} is an abstract class", field.var->as_human_readable(), + field_class->as_human_readable())); } else if (!field_class->derived_classes.empty()) { - kphp_error(0, fmt_format("Json decoding for {} is unavailable, because {} has derived classes", field.var->as_human_readable(), field_class->as_human_readable())); + kphp_error(0, fmt_format("Json decoding for {} is unavailable, because {} has derived classes", field.var->as_human_readable(), + field_class->as_human_readable())); } } } @@ -225,7 +227,7 @@ void check_field_of_a_jsonable_class(const ClassMemberInstanceField &field, cons // (so, in on_start() that list is empty, and all checks are done when adding the next found at a call) void store_json_encoder(ClassPtr klass, ClassPtr json_encoder, bool to_encode) noexcept { { - AutoLocker lock{&(*klass)}; + AutoLocker lock{&(*klass)}; auto it = std::find(klass->json_encoders.begin(), klass->json_encoders.end(), std::pair{json_encoder, to_encode}); if (it != klass->json_encoders.end()) { return; @@ -252,7 +254,7 @@ void store_json_encoder(ClassPtr klass, ClassPtr json_encoder, bool to_encode) n std::set used_json_keys; for (ClassPtr parent = klass; parent; parent = parent->parent_class) { - parent->members.for_each([json_encoder, to_encode, klass, parent, &used_json_keys](const ClassMemberInstanceField &field) { + parent->members.for_each([json_encoder, to_encode, klass, parent, &used_json_keys](const ClassMemberInstanceField& field) { // tuples/interfaces are not allowed as fields, but if a field is marked with @kphp-json skip // or is implicitly skipped (for example, due to visibility_policy of encoder), // we shouldn't analyze it and store json encoders for it @@ -270,41 +272,44 @@ void store_json_encoder(ClassPtr klass, ClassPtr json_encoder, bool to_encode) n check_field_of_a_jsonable_class(field, props, to_encode); kphp_error(props.json_key.empty() || used_json_keys.insert(props.json_key).second, - fmt_format("Json key \"{}\" appears twice for class {} encoded with {}", props.json_key, klass->as_human_readable(), json_encoder->as_human_readable())); + fmt_format("Json key \"{}\" appears twice for class {} encoded with {}", props.json_key, klass->as_human_readable(), + json_encoder->as_human_readable())); }); } } ClassPtr extract_json_encoder_from_call(VertexAdaptor call) noexcept { auto v_encoder = VertexUtil::get_actual_value(call->args().front()); - kphp_assert(v_encoder->type() == op_string); // it's const string of a class name (JsonEncoder of inheritors) + kphp_assert(v_encoder->type() == op_string); // it's const string of a class name (JsonEncoder of inheritors) return G->get_class(v_encoder->get_string()); } void check_to_json_impl_call(VertexAdaptor call) noexcept { auto encoder = extract_json_encoder_from_call(call); - const auto *type = tinf::get_type(call->args()[1]); + const auto* type = tinf::get_type(call->args()[1]); kphp_assert(type->ptype() == tp_Class); store_json_encoder(type->class_type(), encoder, true); } void check_from_json_impl_call(VertexAdaptor call) noexcept { auto encoder = extract_json_encoder_from_call(call); - const auto *type = tinf::get_type(call); + const auto* type = tinf::get_type(call); kphp_assert(type->ptype() == tp_Class); store_json_encoder(type->class_type(), encoder, false); } void check_instance_serialize_call(VertexAdaptor call) { - const auto *type = tinf::get_type(call->args()[0]); + const auto* type = tinf::get_type(call->args()[0]); kphp_error_return(type->ptype() == tp_Class, "Called instance_serialize() with a non-instance argument"); - kphp_error(type->class_type()->is_serializable, fmt_format("Called instance_serialize() for class {}, but it's not marked with @kphp-serializable", type->class_type()->name)); + kphp_error(type->class_type()->is_serializable, + fmt_format("Called instance_serialize() for class {}, but it's not marked with @kphp-serializable", type->class_type()->name)); } void check_instance_deserialize_call(VertexAdaptor call) { - const auto *type = tinf::get_type(call); + const auto* type = tinf::get_type(call); kphp_assert(type->ptype() == tp_Class); - kphp_error(type->class_type()->is_serializable, fmt_format("Called instance_deserialize() for class {}, but it's not marked with @kphp-serializable", type->class_type()->name)); + kphp_error(type->class_type()->is_serializable, + fmt_format("Called instance_deserialize() for class {}, but it's not marked with @kphp-serializable", type->class_type()->name)); } void to_mixed_on_class(ClassPtr klass) { @@ -312,7 +317,7 @@ void to_mixed_on_class(ClassPtr klass) { } void check_to_mixed_call(VertexAdaptor call) { - const auto *type = tinf::get_type(call->args().front()); + const auto* type = tinf::get_type(call->args().front()); kphp_assert(type->ptype() == tp_Class); to_mixed_on_class(type->class_type()); @@ -324,10 +329,10 @@ void check_rand_call(VertexAdaptor call) { } void check_estimate_memory_usage_call(VertexAdaptor call) { - const auto *type = tinf::get_type(call->args()[0]); + const auto* type = tinf::get_type(call->args()[0]); std::unordered_set classes_inside; type->get_all_class_types_inside(classes_inside); - for (auto klass: classes_inside) { + for (auto klass : classes_inside) { klass->deeply_require_instance_memory_estimate_visitor(); } } @@ -342,12 +347,12 @@ static void check_kphp_tracing_func_enter_branch_call(FunctionPtr current_functi "kphp_tracing_func_enter_branch() is available only inside functions with @kphp-tracing aggregate"); } -void raise_error_if_throwable(const std::string &where, const VertexAdaptor &callback) { +void raise_error_if_throwable(const std::string& where, const VertexAdaptor& callback) { if (!callback->func_id->can_throw()) { return; } std::vector throws; - for (const auto &e : callback->func_id->exceptions_thrown) { + for (const auto& e : callback->func_id->exceptions_thrown) { throws.emplace_back(e->name); } kphp_error(false, fmt_format("{} should not throw exceptions\n" @@ -366,12 +371,12 @@ void check_header_register_callback(VertexAdaptor call) { raise_error_if_throwable(call->func_id->name, callback); } -void mark_global_vars_for_memory_stats(const std::vector &vars_list) { +void mark_global_vars_for_memory_stats(const std::vector& vars_list) { std::unordered_set classes_inside; for (VarPtr var : vars_list) { tinf::get_type(var)->get_all_class_types_inside(classes_inside); } - for (ClassPtr klass: classes_inside) { + for (ClassPtr klass : classes_inside) { klass->deeply_require_instance_memory_estimate_visitor(); } } @@ -393,7 +398,7 @@ void check_func_call_params(VertexAdaptor call) { kphp_error(call_params[i]->type() != op_callback_of_builtin, "Unexpected function pointer"); continue; } - const auto *type_hint_callable = param->type_hint->try_as(); + const auto* type_hint_callable = param->type_hint->try_as(); if (call_params[i]->type() == op_ffi_php2c_conv) { continue; @@ -409,13 +414,14 @@ void check_func_call_params(VertexAdaptor call) { kphp_error(!f_passed_to_builtin->is_resumable, fmt_format("Callbacks passed to builtin functions must not be resumable.\n" "But '{}' became resumable because of the calls chain:\n" - "{}", f_passed_to_builtin->as_human_readable(), f_passed_to_builtin->get_resumable_path())); + "{}", + f_passed_to_builtin->as_human_readable(), f_passed_to_builtin->get_resumable_path())); if (auto name = f_passed_to_builtin->local_name(); name == "to_array_debug" || name == "instance_to_array") { - if (const auto *as_subkey = type_hint_callable->arg_types[0]->try_as()) { - const auto *arg_ref = as_subkey->inner->try_as(); + if (const auto* as_subkey = type_hint_callable->arg_types[0]->try_as()) { + const auto* arg_ref = as_subkey->inner->try_as(); if (auto arg = VertexUtil::get_call_arg_ref(arg_ref ? arg_ref->arg_num : -1, call)) { - const auto *value_type = tinf::get_type(arg)->lookup_at_any_key(); + const auto* value_type = tinf::get_type(arg)->lookup_at_any_key(); auto out_class = value_type->class_type(); kphp_error_return(out_class, "type of argument for to_array_debug has to be array of Classes"); out_class->deeply_require_to_array_debug_visitor(); @@ -426,63 +432,60 @@ void check_func_call_params(VertexAdaptor call) { } void check_null_usage_in_binary_operations(VertexAdaptor binary_vertex) { - const auto *lhs_type = tinf::get_type(binary_vertex->lhs()); - const auto *rhs_type = tinf::get_type(binary_vertex->rhs()); + const auto* lhs_type = tinf::get_type(binary_vertex->lhs()); + const auto* rhs_type = tinf::get_type(binary_vertex->rhs()); switch (binary_vertex->type()) { - case op_add: - case op_set_add: - if (vk::any_of_equal(tp_array, lhs_type->get_real_ptype(), rhs_type->get_real_ptype())) { - kphp_error(vk::none_of_equal(tp_any, lhs_type->ptype(), rhs_type->ptype()), - fmt_format("Can't use '{}' operation between {} and {} types", - OpInfo::str(binary_vertex->type()), lhs_type->as_human_readable(), rhs_type->as_human_readable())); - return; - } - - // fall through - case op_mul: - case op_sub: - case op_div: - case op_mod: - case op_pow: - case op_and: - case op_or: - case op_xor: - case op_shl: - case op_shr: - - case op_set_mul: - case op_set_sub: - case op_set_div: - case op_set_mod: - case op_set_pow: - case op_set_and: - case op_set_or: - case op_set_xor: - case op_set_shl: - case op_set_shr: { - kphp_error((lhs_type->ptype() != tp_any || lhs_type->or_false_flag()) && - (rhs_type->ptype() != tp_any || rhs_type->or_false_flag()), - fmt_format("Got '{}' operation between {} and {} types", - OpInfo::str(binary_vertex->type()), lhs_type->as_human_readable(), rhs_type->as_human_readable())); + case op_add: + case op_set_add: + if (vk::any_of_equal(tp_array, lhs_type->get_real_ptype(), rhs_type->get_real_ptype())) { + kphp_error(vk::none_of_equal(tp_any, lhs_type->ptype(), rhs_type->ptype()), + fmt_format("Can't use '{}' operation between {} and {} types", OpInfo::str(binary_vertex->type()), lhs_type->as_human_readable(), + rhs_type->as_human_readable())); return; } - default: - return; + // fall through + case op_mul: + case op_sub: + case op_div: + case op_mod: + case op_pow: + case op_and: + case op_or: + case op_xor: + case op_shl: + case op_shr: + + case op_set_mul: + case op_set_sub: + case op_set_div: + case op_set_mod: + case op_set_pow: + case op_set_and: + case op_set_or: + case op_set_xor: + case op_set_shl: + case op_set_shr: { + kphp_error((lhs_type->ptype() != tp_any || lhs_type->or_false_flag()) && (rhs_type->ptype() != tp_any || rhs_type->or_false_flag()), + fmt_format("Got '{}' operation between {} and {} types", OpInfo::str(binary_vertex->type()), lhs_type->as_human_readable(), + rhs_type->as_human_readable())); + return; + } + + default: + return; } } void check_function_throws(FunctionPtr f) { std::unordered_set throws_expected(f->check_throws.begin(), f->check_throws.end()); std::unordered_set throws_actual; - for (const auto &e : f->exceptions_thrown) { + for (const auto& e : f->exceptions_thrown) { throws_actual.insert(e->name); } kphp_error(throws_expected == throws_actual, - fmt_format("kphp-throws mismatch: have <{}>, want <{}>", - vk::join(throws_actual, ", "), - vk::join(throws_expected, ", "))); + fmt_format("kphp-throws mismatch: have <{}>, want <{}>", vk::join(throws_actual, ", "), vk::join(throws_expected, ", "))); } void check_ffi_call(VertexAdaptor call) { @@ -494,21 +497,20 @@ void check_ffi_call(VertexAdaptor call) { // but PHP will give a run-time error for 1-argument form // of the function if it's not a `char*` or `const char*`; // we'll try to give that error at the compile-time - const auto *type = tinf::get_type(call->args()[0]); + const auto* type = tinf::get_type(call->args()[0]); int indirection = type->get_indirection(); - if (const auto *elem_type = type->lookup_at_any_key()) { + if (const auto* elem_type = type->lookup_at_any_key()) { type = elem_type; indirection = 1; } - const auto *ffi_type = FFIRoot::get_ffi_type(type->class_type()); + const auto* ffi_type = FFIRoot::get_ffi_type(type->class_type()); kphp_error(indirection == 1 && ffi_type->kind == FFITypeKind::Char, - fmt_format("$ptr argument is {}, expected a C string compatible type", - type->as_human_readable())); + fmt_format("$ptr argument is {}, expected a C string compatible type", type->as_human_readable())); return; } } -bool is_php2c_valid(VertexAdaptor conv, const FFIType *ffi_type, const TypeData *php_type) { +bool is_php2c_valid(VertexAdaptor conv, const FFIType* ffi_type, const TypeData* php_type) { auto php_expr = conv->expr(); if (php_type->use_or_false()) { @@ -523,54 +525,54 @@ bool is_php2c_valid(VertexAdaptor conv, const FFIType *ffi_ty } switch (ffi_type->kind) { - case FFITypeKind::Int8: - case FFITypeKind::Int16: - case FFITypeKind::Int32: - case FFITypeKind::Int64: - case FFITypeKind::Uint8: - case FFITypeKind::Uint16: - case FFITypeKind::Uint32: - case FFITypeKind::Uint64: - return php_type->ptype() == tp_int; - - case FFITypeKind::Char: - return php_type->ptype() == tp_string && !php_type->use_or_null(); - - case FFITypeKind::Bool: - return vk::any_of_equal(php_expr->type(), op_false, op_true) || php_type->ptype() == tp_bool; - - case FFITypeKind::Float: - case FFITypeKind::Double: - return php_type->ptype() == tp_float; - - case FFITypeKind::Struct: - case FFITypeKind::StructDef: - case FFITypeKind::Union: - case FFITypeKind::UnionDef: - return php_type->class_type() == conv->c_type->to_type_data()->class_type(); - - case FFITypeKind::Pointer: - if (php_expr->type() == op_null) { - return true; - } - if (!ffi_type->members[0]->is_const() && php_type->ffi_const_flag()) { - return false; - } - if (ffi_type->members[0]->kind == FFITypeKind::Void && ffi_type->num == 1) { - return true; - } - if (ffi_type->num == php_type->get_indirection()) { - return php_type->class_type() == conv->c_type->to_type_data()->class_type(); - } + case FFITypeKind::Int8: + case FFITypeKind::Int16: + case FFITypeKind::Int32: + case FFITypeKind::Int64: + case FFITypeKind::Uint8: + case FFITypeKind::Uint16: + case FFITypeKind::Uint32: + case FFITypeKind::Uint64: + return php_type->ptype() == tp_int; + + case FFITypeKind::Char: + return php_type->ptype() == tp_string && !php_type->use_or_null(); + + case FFITypeKind::Bool: + return vk::any_of_equal(php_expr->type(), op_false, op_true) || php_type->ptype() == tp_bool; + + case FFITypeKind::Float: + case FFITypeKind::Double: + return php_type->ptype() == tp_float; + + case FFITypeKind::Struct: + case FFITypeKind::StructDef: + case FFITypeKind::Union: + case FFITypeKind::UnionDef: + return php_type->class_type() == conv->c_type->to_type_data()->class_type(); + + case FFITypeKind::Pointer: + if (php_expr->type() == op_null) { + return true; + } + if (!ffi_type->members[0]->is_const() && php_type->ffi_const_flag()) { return false; + } + if (ffi_type->members[0]->kind == FFITypeKind::Void && ffi_type->num == 1) { + return true; + } + if (ffi_type->num == php_type->get_indirection()) { + return php_type->class_type() == conv->c_type->to_type_data()->class_type(); + } + return false; - default: - return false; + default: + return false; } } void check_php2c_conv(VertexAdaptor conv) { - if (const auto *as_instance = conv->c_type->try_as()) { + if (const auto* as_instance = conv->c_type->try_as()) { if (as_instance->full_class_name == "FFI\\CData") { return; } @@ -578,13 +580,10 @@ void check_php2c_conv(VertexAdaptor conv) { if (conv->c_type->try_as() && conv->expr()->type() == op_null) { return; } - const auto *php_type = tinf::get_type(conv->expr()); - const FFIType *ffi_type = FFIRoot::get_ffi_type(conv->c_type); - kphp_error(is_php2c_valid(conv, ffi_type, php_type), - fmt_format("Invalid php2c conversion{}: {} -> {}", - conv->simple_dst ? "" : " in this context", - php_type->as_human_readable(), - ffi_decltype_string(ffi_type))); + const auto* php_type = tinf::get_type(conv->expr()); + const FFIType* ffi_type = FFIRoot::get_ffi_type(conv->c_type); + kphp_error(is_php2c_valid(conv, ffi_type, php_type), fmt_format("Invalid php2c conversion{}: {} -> {}", conv->simple_dst ? "" : " in this context", + php_type->as_human_readable(), ffi_decltype_string(ffi_type))); } } // namespace @@ -609,11 +608,11 @@ void FinalCheckPass::on_start() { check_magic_methods(current_function); if (current_function->should_not_throw && current_function->can_throw()) { - kphp_error(0, fmt_format("Function {} marked as @kphp-should-not-throw, but really can throw an exception:\n{}", - current_function->as_human_readable(), current_function->get_throws_call_chain())); + kphp_error(0, fmt_format("Function {} marked as @kphp-should-not-throw, but really can throw an exception:\n{}", current_function->as_human_readable(), + current_function->get_throws_call_chain())); } - for (auto &static_var : current_function->static_var_ids) { + for (auto& static_var : current_function->static_var_ids) { check_static_var_inited(static_var); } @@ -628,22 +627,21 @@ void FinalCheckPass::on_start() { VertexPtr FinalCheckPass::on_enter_vertex(VertexPtr vertex) { if (vertex->type() == op_func_name) { - kphp_error (0, fmt_format("Unexpected {} (maybe, it should be a define?)", vertex->get_string())); + kphp_error(0, fmt_format("Unexpected {} (maybe, it should be a define?)", vertex->get_string())); } if (vertex->type() == op_addr) { - kphp_error (0, "Getting references is unsupported"); + kphp_error(0, "Getting references is unsupported"); } if (vertex->type() == op_ffi_php2c_conv) { check_php2c_conv(vertex.as()); } if (auto array_get = vertex.try_as()) { - const auto *key_type = tinf::get_type(array_get->key()); - kphp_error(key_type->ptype() == tp_int, - fmt_format("ffi_array_get index type must be int, {} used instead", key_type->as_human_readable())); - }if (auto array_set = vertex.try_as()) { - const auto *key_type = tinf::get_type(array_set->key()); - kphp_error(key_type->ptype() == tp_int, - fmt_format("ffi_array_set index type must be int, {} used instead", key_type->as_human_readable())); + const auto* key_type = tinf::get_type(array_get->key()); + kphp_error(key_type->ptype() == tp_int, fmt_format("ffi_array_get index type must be int, {} used instead", key_type->as_human_readable())); + } + if (auto array_set = vertex.try_as()) { + const auto* key_type = tinf::get_type(array_set->key()); + kphp_error(key_type->ptype() == tp_int, fmt_format("ffi_array_set index type must be int, {} used instead", key_type->as_human_readable())); } if (vertex->type() == op_eq3) { @@ -653,50 +651,47 @@ VertexPtr FinalCheckPass::on_enter_vertex(VertexPtr vertex) { check_comparisons(vertex.as()->lhs(), vertex.as()->rhs(), vertex->type()); } if (vertex->type() == op_add) { - const TypeData *type_left = tinf::get_type(vertex.as()->lhs()); - const TypeData *type_right = tinf::get_type(vertex.as()->rhs()); + const TypeData* type_left = tinf::get_type(vertex.as()->lhs()); + const TypeData* type_right = tinf::get_type(vertex.as()->rhs()); if ((type_left->ptype() == tp_array) ^ (type_right->ptype() == tp_array)) { if (type_left->ptype() != tp_mixed && type_right->ptype() != tp_mixed) { - kphp_warning (fmt_format("{} + {} is strange operation", type_out(type_left), type_out(type_right))); + kphp_warning(fmt_format("{} + {} is strange operation", type_out(type_left), type_out(type_right))); } } } if (vk::any_of_equal(vertex->type(), op_sub, op_mul, op_div, op_mod, op_pow)) { - const TypeData *type_left = tinf::get_type(vertex.as()->lhs()); - const TypeData *type_right = tinf::get_type(vertex.as()->rhs()); + const TypeData* type_left = tinf::get_type(vertex.as()->lhs()); + const TypeData* type_right = tinf::get_type(vertex.as()->rhs()); if ((type_left->ptype() == tp_array) || (type_right->ptype() == tp_array)) { - kphp_warning(fmt_format("{} {} {} is strange operation", - OpInfo::str(vertex->type()), - type_out(type_left), - type_out(type_right))); + kphp_warning(fmt_format("{} {} {} is strange operation", OpInfo::str(vertex->type()), type_out(type_left), type_out(type_right))); } } if (vertex->type() == op_foreach) { VertexPtr arr = vertex.as()->params()->xs(); - const TypeData *arrayType = tinf::get_type(arr); + const TypeData* arrayType = tinf::get_type(arr); if (arrayType->ptype() == tp_array) { - const TypeData *valueType = arrayType->lookup_at_any_key(); + const TypeData* valueType = arrayType->lookup_at_any_key(); if (valueType->get_real_ptype() == tp_any) { - kphp_error (0, "Can not compile foreach on array of Unknown type"); + kphp_error(0, "Can not compile foreach on array of Unknown type"); } } } if (vertex->type() == op_list) { const auto list = vertex.as(); VertexPtr arr = list->array(); - const TypeData *arrayType = tinf::get_type(arr); + const TypeData* arrayType = tinf::get_type(arr); if (arrayType->ptype() == tp_array) { - const TypeData *valueType = arrayType->lookup_at_any_key(); - kphp_error (valueType->get_real_ptype() != tp_any, "Can not compile list with array of Unknown type"); + const TypeData* valueType = arrayType->lookup_at_any_key(); + kphp_error(valueType->get_real_ptype() != tp_any, "Can not compile list with array of Unknown type"); } else if (arrayType->ptype() == tp_tuple) { size_t list_size = vertex.as()->list().size(); size_t tuple_size = arrayType->get_tuple_max_index(); - kphp_error (list_size <= tuple_size, fmt_format("Can't assign tuple of length {} to list of length {}", tuple_size, list_size)); + kphp_error(list_size <= tuple_size, fmt_format("Can't assign tuple of length {} to list of length {}", tuple_size, list_size)); for (auto cur : list->list()) { const auto kv = cur.as(); if (VertexUtil::get_actual_value(kv->key())->type() != op_int_const) { - const TypeData *key_type = tinf::get_type(kv->key()); + const TypeData* key_type = tinf::get_type(kv->key()); kphp_error(0, fmt_format("Only int const keys can be used, got '{}'", ptype_name(key_type->ptype()))); } } @@ -704,18 +699,18 @@ VertexPtr FinalCheckPass::on_enter_vertex(VertexPtr vertex) { for (auto cur : list->list()) { const auto kv = cur.as(); if (VertexUtil::get_actual_value(kv->key())->type() != op_string) { - const TypeData *key_type = tinf::get_type(kv->key()); + const TypeData* key_type = tinf::get_type(kv->key()); kphp_error(0, fmt_format("Only string const keys can be used, got '{}'", ptype_name(key_type->ptype()))); } } } else { - kphp_error (arrayType->ptype() == tp_mixed, fmt_format("Can not compile list with '{}'", ptype_name(arrayType->ptype()))); + kphp_error(arrayType->ptype() == tp_mixed, fmt_format("Can not compile list with '{}'", ptype_name(arrayType->ptype()))); } } if (vertex->type() == op_index && vertex.as()->has_key()) { VertexPtr arr = vertex.as()->array(); VertexPtr key = vertex.as()->key(); - const TypeData *array_type = tinf::get_type(arr); + const TypeData* array_type = tinf::get_type(arr); // TODO: do we need this? if (array_type->ptype() == tp_tuple) { const auto key_value = VertexUtil::get_actual_value(key); @@ -725,13 +720,13 @@ VertexPtr FinalCheckPass::on_enter_vertex(VertexPtr vertex) { kphp_error(0 <= index && index < tuple_size, fmt_format("Can't get element {} of tuple of length {}", index, tuple_size)); } } - const TypeData *key_type = tinf::get_type(key); + const TypeData* key_type = tinf::get_type(key); kphp_error(key_type->ptype() != tp_any || key_type->or_false_flag(), fmt_format("Can't get array element by key with {} type", key_type->as_human_readable())); } if (auto xset = vertex.try_as()) { auto v = xset->expr(); - if (auto var_vertex = v.try_as()) { // isset($var), unset($var) + if (auto var_vertex = v.try_as()) { // isset($var), unset($var) VarPtr var = var_vertex->var_id; if (vertex->type() == op_unset) { kphp_error(!var->is_reference, "Unset of reference variables is not supported"); @@ -741,12 +736,11 @@ VertexPtr FinalCheckPass::on_enter_vertex(VertexPtr vertex) { } } } else { - const TypeData *type_info = tinf::get_type(var); - kphp_error(type_info->can_store_null(), - fmt_format("isset({}) will be always true for {}", var->as_human_readable(), type_info->as_human_readable())); + const TypeData* type_info = tinf::get_type(var); + kphp_error(type_info->can_store_null(), fmt_format("isset({}) will be always true for {}", var->as_human_readable(), type_info->as_human_readable())); } - } else if (v->type() == op_index) { // isset($arr[index]), unset($arr[index]) - const TypeData *arrayType = tinf::get_type(v.as()->array()); + } else if (v->type() == op_index) { // isset($arr[index]), unset($arr[index]) + const TypeData* arrayType = tinf::get_type(v.as()->array()); PrimitiveType ptype = arrayType->get_real_ptype(); kphp_error(vk::any_of_equal(ptype, tp_tuple, tp_shape, tp_array, tp_mixed), "Can't use isset/unset by[idx] for not an array"); } @@ -761,22 +755,21 @@ VertexPtr FinalCheckPass::on_enter_vertex(VertexPtr vertex) { kphp_error(false, "Exception is thrown from no return function"); } if (vertex->type() == op_instance_prop) { - const TypeData *lhs_type = tinf::get_type(vertex.as()->instance()); - kphp_error(lhs_type->ptype() == tp_Class, - fmt_format("Accessing ->property of non-instance {}", lhs_type->as_human_readable())); + const TypeData* lhs_type = tinf::get_type(vertex.as()->instance()); + kphp_error(lhs_type->ptype() == tp_Class, fmt_format("Accessing ->property of non-instance {}", lhs_type->as_human_readable())); } if (auto instanceof = vertex.try_as()) { instanceof->derived_class->mark_as_used(); } if (vertex->type() == op_throw) { - const TypeData *thrown_type = tinf::get_type(vertex.as()->exception()); + const TypeData* thrown_type = tinf::get_type(vertex.as()->exception()); kphp_error(thrown_type->ptype() == tp_Class && G->get_class("Throwable")->is_parent_of(thrown_type->class_type()), fmt_format("Throw not Throwable, but {}", thrown_type->as_human_readable())); } if (vertex->type() == op_fork) { - const VertexAdaptor &func_call = vertex.as()->func_call(); + const VertexAdaptor& func_call = vertex.as()->func_call(); kphp_error(!func_call->func_id->is_extern(), "fork of builtin function is forbidden"); kphp_error(tinf::get_type(func_call)->get_real_ptype() != tp_void, "forking void functions is forbidden, return null at least"); } @@ -812,7 +805,7 @@ VertexPtr FinalCheckPass::on_enter_vertex(VertexPtr vertex) { check_array_literal(v_array); } - //TODO: may be this should be moved to tinf_check + // TODO: may be this should be moved to tinf_check return vertex; } @@ -822,22 +815,23 @@ void FinalCheckPass::check_instanceof(VertexAdaptor instanceof_ve return; } - const auto *instanceof_var_type = tinf::get_type(instance_var); + const auto* instanceof_var_type = tinf::get_type(instance_var); if (!instanceof_var_type) { return; } - kphp_error(instanceof_var_type->class_type() || instanceof_var_type->ptype() == tp_mixed, fmt_format("left operand of 'instanceof' should be an instance or mixed, but passed {}", instanceof_var_type->as_human_readable())); + kphp_error(instanceof_var_type->class_type() || instanceof_var_type->ptype() == tp_mixed, + fmt_format("left operand of 'instanceof' should be an instance or mixed, but passed {}", instanceof_var_type->as_human_readable())); } -static void check_indexing_violation(vk::string_view allowed_types_string, const std::vector &allowed_types, vk::string_view what_indexing, - const TypeData &key_type) noexcept { +static void check_indexing_violation(vk::string_view allowed_types_string, const std::vector& allowed_types, vk::string_view what_indexing, + const TypeData& key_type) noexcept { kphp_error(vk::contains(allowed_types, key_type.ptype()), fmt_format("Only {} types are allowed for {}{}indexing, but {} type is passed", allowed_types_string, what_indexing, what_indexing.empty() ? "" : " ", key_type.as_human_readable())); } -static void check_indexing_type(PrimitiveType indexed_type, const TypeData &key_type) noexcept { +static void check_indexing_type(PrimitiveType indexed_type, const TypeData& key_type) noexcept { if (key_type.get_real_ptype() == tp_bool) { return; } @@ -852,10 +846,10 @@ static void check_indexing_type(PrimitiveType indexed_type, const TypeData &key_ } void FinalCheckPass::check_array_literal(VertexAdaptor vertex) noexcept { - for (const auto &element : vertex->args()) { + for (const auto& element : vertex->args()) { if (element->type() == op_double_arrow) { auto arrow = element.as(); - if (const auto *key_type = tinf::get_type(arrow->key())) { + if (const auto* key_type = tinf::get_type(arrow->key())) { check_indexing_type(tp_array, *key_type); } } @@ -863,8 +857,8 @@ void FinalCheckPass::check_array_literal(VertexAdaptor vertex) noexcep } void FinalCheckPass::check_indexing(VertexPtr array, VertexPtr key) noexcept { - const auto *key_type = tinf::get_type(key); - const auto *array_type = tinf::get_type(array); + const auto* key_type = tinf::get_type(key); + const auto* array_type = tinf::get_type(array); if (key_type || array_type) { check_indexing_type(array_type->ptype(), *key_type); } @@ -876,7 +870,7 @@ VertexPtr FinalCheckPass::on_exit_vertex(VertexPtr vertex) { void FinalCheckPass::check_op_func_call(VertexAdaptor call) { if (call->func_id->is_extern()) { - const auto &function_name = call->get_string(); + const auto& function_name = call->get_string(); if (function_name == "instance_cache_fetch") { check_instance_cache_fetch_call(call); } else if (function_name == "instance_cache_store") { @@ -898,7 +892,7 @@ void FinalCheckPass::check_op_func_call(VertexAdaptor call) { } else if (function_name == "kphp_tracing_func_enter_branch") { check_kphp_tracing_func_enter_branch_call(current_function); } else if (function_name == "is_null") { - const TypeData *arg_type = tinf::get_type(call->args()[0]); + const TypeData* arg_type = tinf::get_type(call->args()[0]); kphp_error(arg_type->can_store_null(), fmt_format("is_null() will be always false for {}", arg_type->as_human_readable())); } else if (function_name == "register_shutdown_function") { check_register_shutdown_functions(call); @@ -918,8 +912,8 @@ void FinalCheckPass::check_op_func_call(VertexAdaptor call) { bool is_value_sort_function = vk::any_of_equal(function_name, "sort", "rsort", "asort", "arsort"); if (is_value_sort_function) { // Forbid arrays with elements that would be rejected by check_comparisons(). - const TypeData *array_type = tinf::get_type(call->args()[0]); - const auto *elem_type = array_type->lookup_at_any_key(); + const TypeData* array_type = tinf::get_type(call->args()[0]); + const auto* elem_type = array_type->lookup_at_any_key(); kphp_error(vk::none_of_equal(elem_type->ptype(), tp_Class, tp_tuple, tp_shape), fmt_format("{} is not comparable and cannot be sorted", elem_type->as_human_readable())); } @@ -927,17 +921,16 @@ void FinalCheckPass::check_op_func_call(VertexAdaptor call) { // TODO: get rid of this when rewrite array_diff_impl with some hash set container if (vk::any_of_equal(function_name, "array_diff")) { // Forbid arrays with elements that would be rejected by key projection function. - for (const auto arg: call->args()) { - const TypeData *array_type = tinf::get_type(arg); - const auto *elem_type = array_type->lookup_at_any_key(); + for (const auto arg : call->args()) { + const TypeData* array_type = tinf::get_type(arg); + const auto* elem_type = array_type->lookup_at_any_key(); kphp_error(vk::none_of_equal(elem_type->ptype(), tp_tuple, tp_shape), fmt_format("{} in {}() is not supported", elem_type->as_human_readable(), function_name)); } } if (call->func_id->is_stub) { - kphp_error(!G->settings().forbid_stubs_using.get(), - fmt_format("try call {} stub that is prohibited by option", function_name)); + kphp_error(!G->settings().forbid_stubs_using.get(), fmt_format("try call {} stub that is prohibited by option", function_name)); } } @@ -951,34 +944,30 @@ inline void FinalCheckPass::check_static_var_inited(VarPtr static_var) { } void FinalCheckPass::check_lib_exported_function(FunctionPtr function) { - const TypeData *ret_type = tinf::get_type(function, -1); - kphp_error(!ret_type->has_class_type_inside(), - "Can not use class instance in return of @kphp-lib-export function"); + const TypeData* ret_type = tinf::get_type(function, -1); + kphp_error(!ret_type->has_class_type_inside(), "Can not use class instance in return of @kphp-lib-export function"); - for (auto p: function->get_params()) { + for (auto p : function->get_params()) { auto param = p.as(); if (param->has_default_value() && param->default_value()) { VertexPtr default_value = VertexUtil::get_actual_value(param->default_value()); kphp_error_act(vk::any_of_equal(default_value->type(), op_int_const, op_float_const), - "Only const int, const float are allowed as default param for @kphp-lib-export function", - continue); + "Only const int, const float are allowed as default param for @kphp-lib-export function", continue); } - kphp_error(!tinf::get_type(p)->has_class_type_inside(), - "Can not use class instance in param of @kphp-lib-export function"); + kphp_error(!tinf::get_type(p)->has_class_type_inside(), "Can not use class instance in param of @kphp-lib-export function"); } } void FinalCheckPass::check_eq3(VertexPtr lhs, VertexPtr rhs) { - const auto *lhs_type = tinf::get_type(lhs); - const auto *rhs_type = tinf::get_type(rhs); + const auto* lhs_type = tinf::get_type(lhs); + const auto* rhs_type = tinf::get_type(rhs); if ((lhs_type->ptype() == tp_float && !lhs_type->or_false_flag() && !lhs_type->or_null_flag()) || (rhs_type->ptype() == tp_float && !rhs_type->or_false_flag() && !rhs_type->or_null_flag())) { - kphp_warning(fmt_format("Identity operator between {} and {} types may give an unexpected result", - lhs_type->as_human_readable(), rhs_type->as_human_readable())); + kphp_warning( + fmt_format("Identity operator between {} and {} types may give an unexpected result", lhs_type->as_human_readable(), rhs_type->as_human_readable())); } else if (!can_be_same_type(lhs_type, rhs_type)) { - kphp_warning(fmt_format("Types {} and {} can't be identical", - lhs_type->as_human_readable(), rhs_type->as_human_readable())); + kphp_warning(fmt_format("Types {} and {} can't be identical", lhs_type->as_human_readable(), rhs_type->as_human_readable())); } } @@ -987,8 +976,8 @@ void FinalCheckPass::check_comparisons(VertexPtr lhs, VertexPtr rhs, Operation o std::swap(lhs, rhs); } - const auto *lhs_t = tinf::get_type(lhs); - const auto *rhs_t = tinf::get_type(rhs); + const auto* lhs_t = tinf::get_type(lhs); + const auto* rhs_t = tinf::get_type(rhs); if (lhs_t->ptype() == tp_Class) { if (op == op_eq2) { @@ -1005,10 +994,8 @@ void FinalCheckPass::check_comparisons(VertexPtr lhs, VertexPtr rhs, Operation o fmt_format("You may not compare {} with {} used operator {}", lhs_t->as_human_readable(), rhs_t->as_human_readable(), OpInfo::desc(op))); } else if (lhs_t->ptype() == tp_shape) { // shape can't be compared with anything using ==, it's meaningless - kphp_error(0, - fmt_format("You may not compare {} with {} used operator {}", lhs_t->as_human_readable(), rhs_t->as_human_readable(), OpInfo::desc(op))); + kphp_error(0, fmt_format("You may not compare {} with {} used operator {}", lhs_t->as_human_readable(), rhs_t->as_human_readable(), OpInfo::desc(op))); } - } bool FinalCheckPass::user_recursion(VertexPtr v) { @@ -1020,7 +1007,7 @@ bool FinalCheckPass::user_recursion(VertexPtr v) { if (vk::any_of_equal(v->type(), op_func_call, op_var, op_index, op_conv_drop_false, op_conv_drop_null)) { if (v->rl_type == val_r) { - const TypeData *type = tinf::get_type(v); + const TypeData* type = tinf::get_type(v); if (type->get_real_ptype() == tp_any) { raise_error_using_Unknown_type(v); return true; @@ -1032,13 +1019,13 @@ bool FinalCheckPass::user_recursion(VertexPtr v) { } void FinalCheckPass::on_function() { - const TypeData *return_type = tinf::get_type(current_function, -1); + const TypeData* return_type = tinf::get_type(current_function, -1); if (return_type->get_real_ptype() == tp_void) { kphp_error(!return_type->or_false_flag(), fmt_format("Function returns void and false simultaneously")); kphp_error(!return_type->or_null_flag(), fmt_format("Function returns void and null simultaneously")); } for (int i = 0; i < current_function->param_ids.size(); ++i) { - const TypeData *arg_type = tinf::get_type(current_function, i); + const TypeData* arg_type = tinf::get_type(current_function, i); if (arg_type->get_real_ptype() == tp_any) { stage::set_location(current_function->root->location); raise_error_using_Unknown_type(current_function->get_params()[i].as()->var()); @@ -1059,9 +1046,9 @@ void FinalCheckPass::raise_error_using_Unknown_type(VertexPtr v) { if (auto var_vertex = v.try_as()) { VarPtr var = var_vertex->var_id; - if (index_depth.empty()) { // Unknown type single var access + if (index_depth.empty()) { // Unknown type single var access kphp_error(0, fmt_format("Variable ${} has Unknown type", var->name)); - } else if (index_depth.size() == 3) { // 1-depth array[*] access (most common case) + } else if (index_depth.size() == 3) { // 1-depth array[*] access (most common case) if (vk::any_of_equal(tinf::get_type(var)->get_real_ptype(), tp_array, tp_mixed)) { kphp_error(0, fmt_format("Array ${} is always empty, getting its element has Unknown type", var->name)); @@ -1071,7 +1058,7 @@ void FinalCheckPass::raise_error_using_Unknown_type(VertexPtr v) { kphp_error(0, fmt_format("${} is {}, can not get element", var->name, tinf::get_type(var)->as_human_readable())); } - } else { // multidimentional array[*]...[*] access + } else { // multidimentional array[*]...[*] access kphp_error(0, fmt_format("${}{} has Unknown type", var->name, index_depth)); } } else if (auto call = v.try_as()) { @@ -1103,13 +1090,12 @@ void FinalCheckPass::check_magic_tostring_method(FunctionPtr fun) { const auto count_args = fun->param_ids.size(); kphp_error(count_args == 1, fmt_format("Magic method {} cannot take arguments", fun->as_human_readable())); - const auto *ret_type = tinf::get_type(fun, -1); + const auto* ret_type = tinf::get_type(fun, -1); if (!ret_type) { return; } - kphp_error(ret_type->ptype() == tp_string && ret_type->flags() == 0, - fmt_format("Magic method {} must have string return type", fun->as_human_readable())); + kphp_error(ret_type->ptype() == tp_string && ret_type->flags() == 0, fmt_format("Magic method {} must have string return type", fun->as_human_readable())); } void FinalCheckPass::check_magic_clone_method(FunctionPtr fun) { @@ -1117,7 +1103,6 @@ void FinalCheckPass::check_magic_clone_method(FunctionPtr fun) { kphp_error(!fun->can_throw(), fmt_format("{} method should not throw exception", fun->as_human_readable())); } - void FinalCheckPass::check_serialized_fields_hierarchy(ClassPtr klass) { auto the_klass = klass; // This loop finishes unconditionally since there is NULL klass->parent_class if there is no base class. @@ -1128,25 +1113,24 @@ void FinalCheckPass::check_serialized_fields_hierarchy(ClassPtr klass) { // * if there are instance fields, class should be marked with kphp-serializable if (klass->is_serializable) { kphp_error_return( - (the_klass->members.has_any_instance_var() && the_klass->is_serializable) || !the_klass->members.has_any_instance_var(), - fmt_format("Class {} and all its ancestors must be @kphp-serializable if there are instance fields. Class {} is not.", klass->name, the_klass->name)); - + (the_klass->members.has_any_instance_var() && the_klass->is_serializable) || !the_klass->members.has_any_instance_var(), + fmt_format("Class {} and all its ancestors must be @kphp-serializable if there are instance fields. Class {} is not.", klass->name, the_klass->name)); } the_klass = the_klass->parent_class; } - klass->members.for_each([&](ClassMemberInstanceField &f) { + klass->members.for_each([&](ClassMemberInstanceField& f) { // Check if there is a field with the same number available above in hierarchy auto f_tag = f.serialization_tag; the_klass = klass->parent_class; while (the_klass) { - auto same_numbered_field = the_klass->members.find_member([&f_tag](const ClassMemberInstanceField &f) { - return (f.serialization_tag == f_tag) && (f_tag != -1); - }); + auto same_numbered_field = + the_klass->members.find_member([&f_tag](const ClassMemberInstanceField& f) { return (f.serialization_tag == f_tag) && (f_tag != -1); }); if (same_numbered_field) { - kphp_error_return(false, fmt_format("kphp-serialized-field: field with number {} found in both classes {} and {}", f_tag, the_klass->name, klass->name)); + kphp_error_return(false, + fmt_format("kphp-serialized-field: field with number {} found in both classes {} and {}", f_tag, the_klass->name, klass->name)); } the_klass = the_klass->parent_class; diff --git a/compiler/pipes/final-check.h b/compiler/pipes/final-check.h index 04c7b583c5..d562e6ccca 100644 --- a/compiler/pipes/final-check.h +++ b/compiler/pipes/final-check.h @@ -11,9 +11,8 @@ class FinalCheckPass final : public FunctionPassBase { private: void check_static_var_inited(VarPtr static_var); - -public: +public: std::string get_description() override { return "Final check"; } diff --git a/compiler/pipes/fix-returns.cpp b/compiler/pipes/fix-returns.cpp index 35fcea213a..1a534e62a9 100644 --- a/compiler/pipes/fix-returns.cpp +++ b/compiler/pipes/fix-returns.cpp @@ -8,12 +8,8 @@ #include "compiler/inferring/public.h" VertexPtr FixReturnsPass::on_enter_vertex(VertexPtr root) { - auto is_void_fun = [](FunctionPtr f) { - return tinf::get_type(f, -1)->ptype() == tp_void; - }; - auto is_void_expr = [](VertexPtr root) { - return tinf::get_type(root)->ptype() == tp_void; - }; + auto is_void_fun = [](FunctionPtr f) { return tinf::get_type(f, -1)->ptype() == tp_void; }; + auto is_void_expr = [](VertexPtr root) { return tinf::get_type(root)->ptype() == tp_void; }; if (root->rl_type == val_r && is_void_expr(root)) { if (auto call = root.try_as()) { diff --git a/compiler/pipes/function-and-cfg.h b/compiler/pipes/function-and-cfg.h index bef954f0fd..eeea5fbadf 100644 --- a/compiler/pipes/function-and-cfg.h +++ b/compiler/pipes/function-and-cfg.h @@ -19,8 +19,7 @@ struct FunctionAndCFG { CFGData data; FunctionAndCFG() = default; - explicit FunctionAndCFG(FunctionPtr function, CFGData data) : - function(std::move(function)), - data(std::move(data)) { - } + explicit FunctionAndCFG(FunctionPtr function, CFGData data) + : function(std::move(function)), + data(std::move(data)) {} }; diff --git a/compiler/pipes/gen-tree-postprocess.cpp b/compiler/pipes/gen-tree-postprocess.cpp index 8d027e0969..5cf1e8c9d5 100644 --- a/compiler/pipes/gen-tree-postprocess.cpp +++ b/compiler/pipes/gen-tree-postprocess.cpp @@ -11,12 +11,12 @@ #include "compiler/vertex-util.h" namespace { -template -bool contains_vertex(const VertexPtr &root, F fn) { +template +bool contains_vertex(const VertexPtr& root, F fn) { if (fn(root)) { return true; } - for (const auto &v : *root) { + for (const auto& v : *root) { if (contains_vertex(v, fn)) { return true; } @@ -29,9 +29,7 @@ VertexAdaptor convert_set_null_coalesce(VertexAdaptorlhs(), [](VertexPtr v) { - return v->type() == op_func_call; - }); + bool has_call = contains_vertex(v->lhs(), [](VertexPtr v) { return v->type() == op_func_call; }); kphp_error(!has_call, "Function calls on the left-hand side of \?\?= are not supported"); // lhs() is cloned to make it possible for the compiler to split @@ -90,15 +88,15 @@ VertexAdaptor make_require_once_call(SrcFilePtr lib_main_file, Verte } VertexPtr process_require_lib(VertexAdaptor require_lib_call) { - kphp_error_act (!G->is_output_mode_lib() && !G->is_output_mode_k2_lib(), "require_lib is forbidden to use for compiling libs", return require_lib_call); + kphp_error_act(!G->is_output_mode_lib() && !G->is_output_mode_k2_lib(), "require_lib is forbidden to use for compiling libs", return require_lib_call); VertexRange args = require_lib_call->args(); - kphp_error_act (args.size() == 1, fmt_format("require_lib expected 1 arguments, got {}", args.size()), return require_lib_call); + kphp_error_act(args.size() == 1, fmt_format("require_lib expected 1 arguments, got {}", args.size()), return require_lib_call); auto lib_name_node = args[0]; - kphp_error_act (lib_name_node->type() == op_string, "First argument of require_lib must be a string", return require_lib_call); + kphp_error_act(lib_name_node->type() == op_string, "First argument of require_lib must be a string", return require_lib_call); std::string lib_require_name = lib_name_node->get_string(); - kphp_error_act (!lib_require_name.empty() && lib_require_name.back() != '/', - fmt_format("require_lib got bad lib name '{}'", lib_require_name), return require_lib_call); + kphp_error_act(!lib_require_name.empty() && lib_require_name.back() != '/', fmt_format("require_lib got bad lib name '{}'", lib_require_name), + return require_lib_call); size_t txt_file_index = std::numeric_limits::max(); const std::string functions_txt = lib_require_name + "/lib/functions.txt"; @@ -111,7 +109,7 @@ VertexPtr process_require_lib(VertexAdaptor require_lib_call) { LibPtr lib(new LibData(lib_require_name)); LibPtr registered_lib = G->register_lib(lib); if (txt_file_index <= php_file_index) { - const std::string &txt_file = functions_txt_full.empty() ? functions_txt : functions_txt_full; + const std::string& txt_file = functions_txt_full.empty() ? functions_txt : functions_txt_full; if (SrcFilePtr header_file = G->register_file(txt_file, registered_lib)) { lib->update_lib_main_file(header_file->file_name, header_file->relative_dir_name); auto req_header_txt = make_require_once_call(header_file, require_lib_call); @@ -121,29 +119,22 @@ VertexPtr process_require_lib(VertexAdaptor require_lib_call) { } } if (!new_vertex) { - const std::string &php_file = index_php_full.empty() ? index_php : index_php_full; + const std::string& php_file = index_php_full.empty() ? index_php : index_php_full; if (SrcFilePtr lib_index_file = G->register_file(php_file, registered_lib)) { lib->update_lib_main_file(lib_index_file->file_name, lib_index_file->relative_dir_name); new_vertex = make_require_once_call(lib_index_file, require_lib_call); } } - kphp_error_act (new_vertex, fmt_format("Can't find '{}' lib", lib_require_name), return require_lib_call); + kphp_error_act(new_vertex, fmt_format("Can't find '{}' lib", lib_require_name), return require_lib_call); return new_vertex; } } // namespace -GenTreePostprocessPass::builtin_fun GenTreePostprocessPass::get_builtin_function(const std::string &name) { +GenTreePostprocessPass::builtin_fun GenTreePostprocessPass::get_builtin_function(const std::string& name) { static std::unordered_map functions = { - {"strval", {op_conv_string, 1}}, - {"intval", {op_conv_int, 1}}, - {"boolval", {op_conv_bool, 1}}, - {"floatval", {op_conv_float, 1}}, - {"arrayval", {op_conv_array, 1}}, - {"not_false", {op_conv_drop_false, 1}}, - {"not_null", {op_conv_drop_null, 1}}, - {"fork", {op_fork, 1}}, - {"pow", {op_pow, 2}} - }; + {"strval", {op_conv_string, 1}}, {"intval", {op_conv_int, 1}}, {"boolval", {op_conv_bool, 1}}, + {"floatval", {op_conv_float, 1}}, {"arrayval", {op_conv_array, 1}}, {"not_false", {op_conv_drop_false, 1}}, + {"not_null", {op_conv_drop_null, 1}}, {"fork", {op_fork, 1}}, {"pow", {op_pow, 2}}}; auto it = functions.find(name); if (it == functions.end()) { if (name == "profiler_is_enabled") { @@ -172,14 +163,14 @@ VertexPtr GenTreePostprocessPass::on_enter_vertex(VertexPtr root) { if (auto instanceof = root.try_as()) { kphp_error(instanceof->rhs()->type() == op_func_name, "right side of `instanceof` should be a class name"); - if (!vk::string_view{instanceof->rhs()->get_string()}.ends_with("::class")) { + if (!vk::string_view{ instanceof->rhs()->get_string()}.ends_with("::class")) { instanceof->rhs()->set_string(instanceof->rhs()->get_string() + "::class"); } return root; } if (auto call = root.try_as()) { - const auto &name = call->get_string(); + const auto& name = call->get_string(); auto builtin = get_builtin_function(name); if (builtin.op != op_err && call->size() == builtin.args) { @@ -188,8 +179,8 @@ VertexPtr GenTreePostprocessPass::on_enter_vertex(VertexPtr root) { if (name == "call_user_func_array") { auto args = call->args(); - kphp_error (args.size() == 2, fmt_format("call_user_func_array expected 2 arguments, got {}", (int)root->size())); - kphp_error_act (args[0]->type() == op_string, "First argument of call_user_func_array must be a const string", return root); + kphp_error(args.size() == 2, fmt_format("call_user_func_array expected 2 arguments, got {}", (int)root->size())); + kphp_error_act(args[0]->type() == op_string, "First argument of call_user_func_array must be a const string", return root); auto arg = VertexAdaptor::create(args[1]).set_location(args[1]); auto new_root = VertexAdaptor::create(arg).set_location(arg); new_root->set_string(args[0]->get_string()); @@ -250,17 +241,13 @@ VertexPtr GenTreePostprocessPass::on_exit_vertex(VertexPtr root) { return root; } -VertexAdaptor array_vertex_from_slice(const VertexRange &args, size_t start, size_t end) { - return VertexAdaptor::create( - std::vector{args.begin() + start, args.begin() + end} - ); +VertexAdaptor array_vertex_from_slice(const VertexRange& args, size_t start, size_t end) { + return VertexAdaptor::create(std::vector{args.begin() + start, args.begin() + end}); } VertexPtr GenTreePostprocessPass::convert_array_with_spread_operators(VertexAdaptor array_vertex) { const auto args = array_vertex->args(); - const auto with_spread = std::any_of(args.begin(), args.end(), [](const auto &arg) { - return arg->type() == op_varg; - }); + const auto with_spread = std::any_of(args.begin(), args.end(), [](const auto& arg) { return arg->type() == op_varg; }); if (!with_spread) { return array_vertex; @@ -280,17 +267,13 @@ VertexPtr GenTreePostprocessPass::convert_array_with_spread_operators(VertexAdap const auto has_elements_before = (last_spread_index != 0); if (has_elements_before) { - parts.emplace_back( - array_vertex_from_slice(args, 0, last_spread_index) - ); + parts.emplace_back(array_vertex_from_slice(args, 0, last_spread_index)); } } else { const auto count_elements = last_spread_index - (prev_spread_index + 1); if (count_elements != 0) { - parts.emplace_back( - array_vertex_from_slice(args, prev_spread_index + 1, last_spread_index) - ); + parts.emplace_back(array_vertex_from_slice(args, prev_spread_index + 1, last_spread_index)); } } @@ -301,9 +284,7 @@ VertexPtr GenTreePostprocessPass::convert_array_with_spread_operators(VertexAdap } if (last_spread_index != args.size() - 1) { - parts.emplace_back( - array_vertex_from_slice(args, last_spread_index + 1, args.size()) - ); + parts.emplace_back(array_vertex_from_slice(args, last_spread_index + 1, args.size())); } auto call = VertexAdaptor::create(parts).set_location(array_vertex->location); diff --git a/compiler/pipes/gen-tree-postprocess.h b/compiler/pipes/gen-tree-postprocess.h index 0828172abb..ffa8b7eb2b 100644 --- a/compiler/pipes/gen-tree-postprocess.h +++ b/compiler/pipes/gen-tree-postprocess.h @@ -12,7 +12,7 @@ class GenTreePostprocessPass final : public FunctionPassBase { int args; }; - builtin_fun get_builtin_function(const std::string &name); + builtin_fun get_builtin_function(const std::string& name); public: std::string get_description() override { diff --git a/compiler/pipes/generate-virtual-methods.cpp b/compiler/pipes/generate-virtual-methods.cpp index 5bb1e2b4ce..38daa7c29c 100644 --- a/compiler/pipes/generate-virtual-methods.cpp +++ b/compiler/pipes/generate-virtual-methods.cpp @@ -10,8 +10,8 @@ #include "compiler/data/class-data.h" #include "compiler/data/function-data.h" #include "compiler/data/src-file.h" -#include "compiler/vertex-util.h" #include "compiler/type-hint.h" +#include "compiler/vertex-util.h" // a "virtual method" is an instance method overridden in child classes (all methods of interfaces are virtual also) // $obj->virtual_method() call actually dynamically handles the runtime type of $obj, proxying a call to a concrete class @@ -40,7 +40,7 @@ VertexAdaptor generate_call_of_self_method(VertexPtr instance_var, if (function->has_variadic_param) { kphp_assert(!call_method->args().empty()); - auto &last_param_passed_to_method = *std::prev(call_method->args().end()); + auto& last_param_passed_to_method = *std::prev(call_method->args().end()); last_param_passed_to_method = VertexAdaptor::create(params.back()).set_location(params.back()); } @@ -67,7 +67,6 @@ enum class VarianceKind { ParamTypeHints, // contravariance }; - // check that type hints are compatible following the PHP rules // // ReturnTypeHints: derived type can be more specific than the base type @@ -75,7 +74,7 @@ enum class VarianceKind { // see https://www.php.net/manual/en/language.oop5.variance.php // // note: the PHP docs lie about int<->float, int is not considered to be a more specific type -bool php_type_hints_compatible(VarianceKind mode, const TypeHint *base, const TypeHint *derived) { +bool php_type_hints_compatible(VarianceKind mode, const TypeHint* base, const TypeHint* derived) { if (mode == VarianceKind::ParamTypeHints) { return php_type_hints_compatible(VarianceKind::ReturnTypeHints, derived, base); } @@ -89,49 +88,49 @@ bool php_type_hints_compatible(VarianceKind mode, const TypeHint *base, const Ty return false; } - if (const auto *base_array = base->try_as()) { - if (const auto *derived_array = derived->try_as()) { + if (const auto* base_array = base->try_as()) { + if (const auto* derived_array = derived->try_as()) { return php_type_hints_compatible(mode, base_array->inner, derived_array->inner); } } - if (const auto *base_optional = base->try_as()) { + if (const auto* base_optional = base->try_as()) { if (!base_optional->or_false && base_optional->or_null) { - if (const auto *derived_optional = derived->try_as()) { + if (const auto* derived_optional = derived->try_as()) { if (!derived_optional->or_false && derived_optional->or_null) { return php_type_hints_compatible(mode, base_optional->inner, derived_optional->inner); } } // covariance allows base `?T` type to be compared as `T`, but not the other way around - return base_optional->or_null && !base_optional->or_false && - php_type_hints_compatible(mode, base_optional->inner, derived); + return base_optional->or_null && !base_optional->or_false && php_type_hints_compatible(mode, base_optional->inner, derived); } // or-false types are handled below } // can't use Assumption::extract_instance_from_type_hint as it will // unwrap the TypeHintOptional here - if (const auto *base_instance = base->try_as()) { - if (const auto *derived_instance = derived->try_as()) { + if (const auto* base_instance = base->try_as()) { + if (const auto* derived_instance = derived->try_as()) { return base_instance->resolve()->is_parent_of(derived_instance->resolve()); } // TODO: this should not be allowed, `T -> null` is not a valid transition; // we could probably use ?T instead of standalone null in this case // see tests/phpt/interfaces/signature_compatibility return_null.php - if (const auto *derived_primitive = derived->try_as()) { + if (const auto* derived_primitive = derived->try_as()) { return derived_primitive->ptype == tp_Null; } return false; } - if (const auto *base_callable = base->try_as()) { - if (const auto *derived_callable = derived->try_as()) { + if (const auto* base_callable = base->try_as()) { + if (const auto* derived_callable = derived->try_as()) { if (base_callable->is_untyped_callable() && derived_callable->is_untyped_callable()) { return true; } // for typed callables inheritance, we allow when parent/child are totally equal // we don't allow co[ntra]variance in typed callables' params/return - if (base_callable->is_typed_callable() && derived_callable->is_typed_callable() && base_callable->arg_types.size() == derived_callable->arg_types.size()) { + if (base_callable->is_typed_callable() && derived_callable->is_typed_callable() && + base_callable->arg_types.size() == derived_callable->arg_types.size()) { for (int i = 0; i < base_callable->arg_types.size(); ++i) { if (base_callable->arg_types[i] != derived_callable->arg_types[i]) { return false; @@ -149,8 +148,8 @@ bool php_type_hints_compatible(VarianceKind mode, const TypeHint *base, const Ty // we'll probably want to sort (by hash?) all TypeHintPipe items to make // their full comparison faster (without a map or O(n^2) complexity) if (base->is_typedata_constexpr() && derived->is_typedata_constexpr()) { - const auto *base_td = base->to_type_data(); - const auto *derived_td = derived->to_type_data(); + const auto* base_td = base->to_type_data(); + const auto* derived_td = derived->to_type_data(); if (base_td->ptype() == tp_float && derived_td->ptype() == tp_int) { return false; } @@ -160,10 +159,8 @@ bool php_type_hints_compatible(VarianceKind mode, const TypeHint *base, const Ty return false; } -bool check_php_signatures_variance(FunctionPtr base_function, FunctionPtr derived_method, std::string &error_info) { - const auto type_hint_string = [](const TypeHint *type_hint) { - return type_hint ? type_hint->as_human_readable() : ""; - }; +bool check_php_signatures_variance(FunctionPtr base_function, FunctionPtr derived_method, std::string& error_info) { + const auto type_hint_string = [](const TypeHint* type_hint) { return type_hint ? type_hint->as_human_readable() : ""; }; if (!php_type_hints_compatible(VarianceKind::ReturnTypeHints, base_function->return_typehint, derived_method->return_typehint)) { error_info = fmt_format("\t{} return type: {}\n", base_function->class_id->name, type_hint_string(base_function->return_typehint)) + @@ -179,9 +176,11 @@ bool check_php_signatures_variance(FunctionPtr base_function, FunctionPtr derive auto base_param = base_params[i].as(); auto derived_param = derived_params[i].as(); if (!php_type_hints_compatible(VarianceKind::ParamTypeHints, base_param->type_hint, derived_param->type_hint)) { - error_info = fmt_format("\t{} parameter ${} type: {}\n", base_function->class_id->name, base_param->var()->get_string(), type_hint_string(base_param->type_hint)) + - fmt_format("\t{} parameter ${} type: {}\n", derived_method->class_id->name, derived_param->var()->get_string(), type_hint_string(derived_param->type_hint)) + - "\tNote: derived method param type can't be more specific, but it can be more generic (it should be contravariant)"; + error_info = + fmt_format("\t{} parameter ${} type: {}\n", base_function->class_id->name, base_param->var()->get_string(), type_hint_string(base_param->type_hint)) + + fmt_format("\t{} parameter ${} type: {}\n", derived_method->class_id->name, derived_param->var()->get_string(), + type_hint_string(derived_param->type_hint)) + + "\tNote: derived method param type can't be more specific, but it can be more generic (it should be contravariant)"; return false; } } @@ -190,14 +189,14 @@ bool check_php_signatures_variance(FunctionPtr base_function, FunctionPtr derive } template -bool check_that_signatures_are_same(FunctionPtr interface_function, ClassPtr context_class, const ClassMemberMethod *interface_method_in_derived) { +bool check_that_signatures_are_same(FunctionPtr interface_function, ClassPtr context_class, const ClassMemberMethod* interface_method_in_derived) { stage::set_line(interface_function->root->get_location().line); if (!interface_method_in_derived || (interface_method_in_derived->function->is_constructor() && !context_class->has_custom_constructor)) { kphp_error_act(context_class->modifiers.is_abstract(), fmt_format("class {} must be abstract: method {} is not overridden", context_class->name, interface_function->as_human_readable()), return true); for (auto derived : context_class->derived_classes) { - const auto *method_in_derived = derived->members.find_by_local_name(interface_function->local_name()); + const auto* method_in_derived = derived->members.find_by_local_name(interface_function->local_name()); if (!check_that_signatures_are_same(interface_function, derived, method_in_derived)) { return false; } @@ -228,8 +227,7 @@ bool check_that_signatures_are_same(FunctionPtr interface_function, ClassPtr con if (!(i_argn <= max_argn && (default_argn >= max_argn - i_argn))) { stage::set_location(derived_method->root->location); - kphp_error(false, fmt_format("Count of arguments differ in {} and {}", - interface_function->as_human_readable(), derived_method->as_human_readable())); + kphp_error(false, fmt_format("Count of arguments differ in {} and {}", interface_function->as_human_readable(), derived_method->as_human_readable())); return false; } @@ -239,8 +237,8 @@ bool check_that_signatures_are_same(FunctionPtr interface_function, ClassPtr con std::string error_info; if (!check_php_signatures_variance(interface_function, derived_method, error_info)) { stage::set_location(derived_method->root->location); - kphp_error(false, fmt_format("Declaration of {}() must be compatible with {}()\n{}", - derived_method->as_human_readable(), interface_function->as_human_readable(), error_info)); + kphp_error(false, fmt_format("Declaration of {}() must be compatible with {}()\n{}", derived_method->as_human_readable(), + interface_function->as_human_readable(), error_info)); } } @@ -248,20 +246,20 @@ bool check_that_signatures_are_same(FunctionPtr interface_function, ClassPtr con } bool check_that_signatures_are_same(ClassPtr context_class, FunctionPtr interface_function) { - const auto *interface_method_in_derived = context_class->members.get_instance_method(interface_function->local_name()); + const auto* interface_method_in_derived = context_class->members.get_instance_method(interface_function->local_name()); return check_that_signatures_are_same(interface_function, context_class, interface_method_in_derived); } -void check_static_function_signatures_compatibility(FunctionPtr interface_function, const std::vector &derived_classes) { +void check_static_function_signatures_compatibility(FunctionPtr interface_function, const std::vector& derived_classes) { for (ClassPtr derived : derived_classes) { - const auto *static_in_derived = derived->members.get_static_method(interface_function->local_name()); + const auto* static_in_derived = derived->members.get_static_method(interface_function->local_name()); check_that_signatures_are_same(interface_function, derived, static_in_derived); } } -void check_constructor_signature_compatibility(FunctionPtr interface_constructor, const std::vector &derived_classes) { +void check_constructor_signature_compatibility(FunctionPtr interface_constructor, const std::vector& derived_classes) { for (ClassPtr derived : derived_classes) { - const auto *derived_constructor = derived->members.get_instance_method(ClassData::NAME_OF_CONSTRUCT); + const auto* derived_constructor = derived->members.get_instance_method(ClassData::NAME_OF_CONSTRUCT); check_that_signatures_are_same(interface_constructor, derived, derived_constructor); } } @@ -273,17 +271,16 @@ VertexAdaptor gen_case_on_hash(ClassPtr derived, VertexAdaptor VertexAdaptor gen_case_calling_methods_on_derived_class(ClassPtr derived, FunctionPtr virtual_function) { FunctionPtr concrete_method_of_derived; - if (const auto *method_of_derived = derived->members.get_instance_method(virtual_function->local_name())) { + if (const auto* method_of_derived = derived->members.get_instance_method(virtual_function->local_name())) { concrete_method_of_derived = method_of_derived->function; } else { - if (const auto *method_from_ancestor = derived->get_instance_method(virtual_function->local_name())) { + if (const auto* method_from_ancestor = derived->get_instance_method(virtual_function->local_name())) { concrete_method_of_derived = method_from_ancestor->function; } bool is_overridden_by_ancestors = concrete_method_of_derived && !concrete_method_of_derived->modifiers.is_abstract(); if (virtual_function->modifiers.is_abstract() && !derived->modifiers.is_abstract() && !is_overridden_by_ancestors) { - kphp_error(false, fmt_format("You should override abstract method {} in class {}", - virtual_function->as_human_readable(), derived->as_human_readable())); + kphp_error(false, fmt_format("You should override abstract method {} in class {}", virtual_function->as_human_readable(), derived->as_human_readable())); return {}; } } @@ -293,7 +290,7 @@ VertexAdaptor gen_case_calling_methods_on_derived_class(ClassPtr derive } if (!concrete_method_of_derived->file_id->is_builtin() && concrete_method_of_derived->is_virtual_method) { - auto &members_of_derived_class = concrete_method_of_derived->class_id->members; + auto& members_of_derived_class = concrete_method_of_derived->class_id->members; concrete_method_of_derived = members_of_derived_class.get_instance_method(virtual_function->get_name_of_self_method())->function; } @@ -311,16 +308,16 @@ VertexAdaptor gen_case_calling_methods_on_derived_class(ClassPtr derive // we can't express "return default of ReturnT", something like 'return {}' in C++ code // that's why, we accept most common cases — "return 0" for int, "return null" for instances, etc. -VertexPtr generate_default_value_of_type(const TypeHint *ret_type) { - if (const auto *as_optional = ret_type->try_as()) { +VertexPtr generate_default_value_of_type(const TypeHint* ret_type) { + if (const auto* as_optional = ret_type->try_as()) { return as_optional->or_null ? VertexPtr(VertexAdaptor::create()) : VertexPtr(VertexAdaptor::create()); } else if (ret_type->try_as()) { return VertexAdaptor::create(); } else if (ret_type->try_as()) { return VertexAdaptor::create(); - } else if (const auto *as_tuple = ret_type->try_as()) { + } else if (const auto* as_tuple = ret_type->try_as()) { std::vector args; - for (const TypeHint *item : as_tuple->items) { + for (const TypeHint* item : as_tuple->items) { VertexPtr arg = generate_default_value_of_type(item); if (!arg) { return {}; @@ -328,18 +325,18 @@ VertexPtr generate_default_value_of_type(const TypeHint *ret_type) { args.emplace_back(arg); } return VertexAdaptor::create(args); - } else if (const auto *ret_primitive = ret_type->try_as()) { + } else if (const auto* ret_primitive = ret_type->try_as()) { switch (ret_primitive->ptype) { - case tp_int: - case tp_float: - case tp_mixed: - return VertexUtil::create_int_const(0); - case tp_bool: - return VertexAdaptor::create(); - case tp_string: - return VertexAdaptor::create(); - default: - break; + case tp_int: + case tp_float: + case tp_mixed: + return VertexUtil::create_int_const(0); + case tp_bool: + return VertexAdaptor::create(); + case tp_string: + return VertexAdaptor::create(); + default: + break; } } else if (ret_type->try_as()) { return VertexAdaptor::create(); @@ -352,7 +349,7 @@ VertexPtr generate_default_value_of_type(const TypeHint *ret_type) { // it won't be executed at runtime, but it would be compiled by gcc // this could be done if all type hints of params/return are set strictly (otherwise, Unknown would be left after inferring) VertexAdaptor generate_body_of_empty_virtual_method(ClassPtr klass, FunctionPtr method) { - const TypeHint *ret_type = method->return_typehint ?: TypeHintPrimitive::create(tp_void); + const TypeHint* ret_type = method->return_typehint ?: TypeHintPrimitive::create(tp_void); bool all_type_hints_set = true; bool any_type_hint_has_tp_any = ret_type->has_tp_any_inside(); for (auto p : method->get_params()) { @@ -363,19 +360,23 @@ VertexAdaptor generate_body_of_empty_virtual_method(ClassPtr klass, Func kphp_error_act(all_type_hints_set, fmt_format("Error compiling {}, because {} has no inheritors.\nProvide types for all params (via type hints or phpdoc)", - method->as_human_readable(), klass->as_human_readable()), return VertexAdaptor::create()); + method->as_human_readable(), klass->as_human_readable()), + return VertexAdaptor::create()); kphp_error_act(!any_type_hint_has_tp_any, fmt_format("Error compiling {}, because {} has no inheritors.\nTypes must not contain 'any' or 'array', they should be definite", - method->as_human_readable(), klass->as_human_readable()), return VertexAdaptor::create()); + method->as_human_readable(), klass->as_human_readable()), + return VertexAdaptor::create()); if (ret_type->try_as() && ret_type->try_as()->ptype == tp_void) { return VertexAdaptor::create(VertexAdaptor::create()); } VertexPtr return_expr = generate_default_value_of_type(ret_type); - kphp_error_act(return_expr, - fmt_format("Error compiling {}, because {} has no inheritors.\nKPHP can't generate a default implementation, because the return type is too complex", - method->as_human_readable(), klass->as_human_readable()), return VertexAdaptor::create()); + kphp_error_act( + return_expr, + fmt_format("Error compiling {}, because {} has no inheritors.\nKPHP can't generate a default implementation, because the return type is too complex", + method->as_human_readable(), klass->as_human_readable()), + return VertexAdaptor::create()); return VertexAdaptor::create(VertexAdaptor::create(return_expr)); } @@ -415,7 +416,8 @@ void generate_body_of_virtual_method(FunctionPtr virtual_function) { ClassPtr prev_derived; for (ClassPtr derived : all_derived_classes) { - kphp_error (prev_derived != derived, fmt_format("Duplicated class {} in hierarchy from class {}.\nDiamond inheritance is not supported", derived->name, klass->name)); + kphp_error(prev_derived != derived, + fmt_format("Duplicated class {} in hierarchy from class {}.\nDiamond inheritance is not supported", derived->name, klass->name)); prev_derived = derived; if (auto v_case = gen_case_calling_methods_on_derived_class(derived, virtual_function)) { @@ -432,17 +434,18 @@ void generate_body_of_virtual_method(FunctionPtr virtual_function) { auto call_get_hash = VertexAdaptor::create(ClassData::gen_vertex_this({})); call_get_hash->str_val = "get_hash_of_class"; call_get_hash->func_id = G->get_function(call_get_hash->str_val); - virtual_function->root->cmd_ref() = VertexAdaptor::create(VertexUtil::create_switch_vertex(virtual_function, call_get_hash, std::move(cases)), generate_critical_error_call(fmt_format("call method({}) on null object", virtual_function->as_human_readable(false)))); + virtual_function->root->cmd_ref() = + VertexAdaptor::create(VertexUtil::create_switch_vertex(virtual_function, call_get_hash, std::move(cases)), + generate_critical_error_call(fmt_format("call method({}) on null object", virtual_function->as_human_readable(false)))); } - virtual_function->type = FunctionData::func_local; // could be func_extern before, but now it has a body + virtual_function->type = FunctionData::func_local; // could be func_extern before, but now it has a body virtual_function->update_location_in_body(); } } // namespace - -void GenerateVirtualMethodsF::on_finish(DataStream &os) { +void GenerateVirtualMethodsF::on_finish(DataStream& os) { stage::set_name("Generate virtual method dispatching"); stage::die_if_global_errors(); @@ -452,7 +455,7 @@ void GenerateVirtualMethodsF::on_finish(DataStream &os) { for (FunctionPtr f : all_functions) { kphp_assert(!f->is_generic()); - if (f->modifiers.is_static() && f->modifiers.is_abstract()) { // is_abstract() to make vkcom compile, as it has invalid phpdoc inheritance + if (f->modifiers.is_static() && f->modifiers.is_abstract()) { // is_abstract() to make vkcom compile, as it has invalid phpdoc inheritance check_static_function_signatures_compatibility(f, f->class_id->derived_classes); } if (f->is_virtual_method) { diff --git a/compiler/pipes/generate-virtual-methods.h b/compiler/pipes/generate-virtual-methods.h index 9f49ed04db..4e118849c2 100644 --- a/compiler/pipes/generate-virtual-methods.h +++ b/compiler/pipes/generate-virtual-methods.h @@ -10,5 +10,5 @@ class GenerateVirtualMethodsF final : public SyncPipeF { public: - void on_finish(DataStream &os) final; + void on_finish(DataStream& os) final; }; diff --git a/compiler/pipes/inline-defines-usages.cpp b/compiler/pipes/inline-defines-usages.cpp index 240023497a..88a2f61c21 100644 --- a/compiler/pipes/inline-defines-usages.cpp +++ b/compiler/pipes/inline-defines-usages.cpp @@ -12,11 +12,7 @@ VertexPtr InlineDefinesUsagesPass::on_enter_vertex(VertexPtr root) { // defined('NAME') is replaced by true or false if (auto defined = root.try_as()) { - kphp_error_act ( - (int)root->size() == 1 && defined->expr()->type() == op_string, - "wrong arguments in 'defined'", - return VertexPtr() - ); + kphp_error_act((int)root->size() == 1 && defined->expr()->type() == op_string, "wrong arguments in 'defined'", return VertexPtr()); DefinePtr def = G->get_define(defined->expr()->get_string()); @@ -73,12 +69,12 @@ void InlineDefinesUsagesPass::on_start() { lambda_class_id = current_function->get_this_or_topmost_if_lambda()->class_id; if (current_function->type == FunctionData::func_class_holder) { - current_function->class_id->members.for_each([&](ClassMemberStaticField &f) { + current_function->class_id->members.for_each([&](ClassMemberStaticField& f) { if (f.var->init_val) { run_function_pass(f.var->init_val, this); } }); - current_function->class_id->members.for_each([&](ClassMemberInstanceField &f) { + current_function->class_id->members.for_each([&](ClassMemberInstanceField& f) { if (f.var->init_val) { run_function_pass(f.var->init_val, this); } diff --git a/compiler/pipes/inline-simple-functions.cpp b/compiler/pipes/inline-simple-functions.cpp index 25fa19c8a7..699ab3cdf8 100644 --- a/compiler/pipes/inline-simple-functions.cpp +++ b/compiler/pipes/inline-simple-functions.cpp @@ -26,62 +26,59 @@ VertexPtr InlineSimpleFunctions::on_enter_vertex(VertexPtr root) { } if (auto var_vertex = root.try_as()) { - if (in_param_list_ && var_vertex->var_id && - !var_vertex->var_id->marked_as_const && - !var_vertex->var_id->is_read_only && - !var_vertex->var_id->is_reference && - !tinf::get_type(var_vertex->var_id)->is_primitive_type()) { + if (in_param_list_ && var_vertex->var_id && !var_vertex->var_id->marked_as_const && !var_vertex->var_id->is_read_only && + !var_vertex->var_id->is_reference && !tinf::get_type(var_vertex->var_id)->is_primitive_type()) { inline_is_possible_ = false; } return root; } switch (root->type()) { - case op_empty: - case op_func_param: - case op_false: - case op_true: - case op_null: - case op_function: - case op_instance_prop: - case op_ffi_cdata_value_ref: - case op_ffi_cast: - case op_ffi_load_call: - case op_ffi_php2c_conv: - case op_ffi_c2php_conv: - break; - case op_func_name: - case op_func_call: - case op_index: - case op_push_back: - case op_return: - case op_ternary: - case op_if: - case op_alloc: - case op_ffi_new: - case op_ffi_addr: - case op_ffi_array_get: - case op_ffi_array_set: - on_simple_operation(); - break; - case op_func_param_list: - in_param_list_ = true; - // fallthrough - case op_seq: - if (root->size() > 5) { - inline_is_possible_ = false; - } - break; - case op_string_build: - case op_array: - case op_tuple: - case op_shape: - if (root->size() > 2) { - inline_is_possible_ = false; - } - break; - default: + case op_empty: + case op_func_param: + case op_false: + case op_true: + case op_null: + case op_function: + case op_instance_prop: + case op_ffi_cdata_value_ref: + case op_ffi_cast: + case op_ffi_load_call: + case op_ffi_php2c_conv: + case op_ffi_c2php_conv: + break; + case op_func_name: + case op_func_call: + case op_index: + case op_push_back: + case op_return: + case op_ternary: + case op_if: + case op_alloc: + case op_ffi_new: + case op_ffi_addr: + case op_ffi_array_get: + case op_ffi_array_set: + on_simple_operation(); + break; + case op_func_param_list: + in_param_list_ = true; + // fallthrough + case op_seq: + if (root->size() > 5) { + inline_is_possible_ = false; + } + break; + case op_string_build: + case op_array: + case op_tuple: + case op_shape: + if (root->size() > 2) { inline_is_possible_ = false; + } + break; + default: + inline_is_possible_ = false; } return root; } @@ -98,13 +95,8 @@ bool InlineSimpleFunctions::user_recursion(VertexPtr) { } bool InlineSimpleFunctions::check_function(FunctionPtr function) const { - return !function->is_resumable && - !function->is_inline && - !function->can_throw() && - !function->has_variadic_param && - !function->is_main_function() && - function->type != FunctionData::func_class_holder && - (!function->modifiers.is_instance() || function->local_name() != "__wakeup") && + return !function->is_resumable && !function->is_inline && !function->can_throw() && !function->has_variadic_param && !function->is_main_function() && + function->type != FunctionData::func_class_holder && (!function->modifiers.is_instance() || function->local_name() != "__wakeup") && !function->kphp_lib_export; } diff --git a/compiler/pipes/inline-simple-functions.h b/compiler/pipes/inline-simple-functions.h index c5f88a9f55..1ee410903a 100644 --- a/compiler/pipes/inline-simple-functions.h +++ b/compiler/pipes/inline-simple-functions.h @@ -15,7 +15,9 @@ class InlineSimpleFunctions final : public FunctionPassBase { void on_simple_operation() noexcept; public: - std::string get_description() final { return "Inline simple functions"; } + std::string get_description() final { + return "Inline simple functions"; + } VertexPtr on_enter_vertex(VertexPtr root) final; VertexPtr on_exit_vertex(VertexPtr root) final; diff --git a/compiler/pipes/instantiate-ffi-operations.cpp b/compiler/pipes/instantiate-ffi-operations.cpp index 9675da185a..ad76707d59 100644 --- a/compiler/pipes/instantiate-ffi-operations.cpp +++ b/compiler/pipes/instantiate-ffi-operations.cpp @@ -4,10 +4,10 @@ #include "compiler/pipes/instantiate-ffi-operations.h" -#include "compiler/vertex-util.h" #include "compiler/const-manipulations.h" #include "compiler/ffi/ffi_parser.h" #include "compiler/type-hint.h" +#include "compiler/vertex-util.h" /* * This pass creates op_ffi_* vertices. @@ -32,8 +32,8 @@ // this functions doesn't cover all cases like T* and other FFI type hints, // but it catches some simple errors to avoid compiler crashes; // TODO: revisit this later, we need to consolidate undefined classes checking -static void check_class_defined(const TypeHint *type_hint) { - if (const auto *as_instance = type_hint->try_as()) { +static void check_class_defined(const TypeHint* type_hint) { + if (const auto* as_instance = type_hint->try_as()) { kphp_error(as_instance->resolve(), fmt_format("Could not find class {}", TermStringFormat::paint_red(as_instance->full_class_name))); } } @@ -41,10 +41,10 @@ static void check_class_defined(const TypeHint *type_hint) { struct TypeExpr { std::string cdef; VertexPtr size_expr; - const char *err = nullptr; + const char* err = nullptr; }; -static void resolve_type_expr_string(TypeExpr &dst, VertexPtr e) { +static void resolve_type_expr_string(TypeExpr& dst, VertexPtr e) { if (dst.err != nullptr) { return; } @@ -59,7 +59,7 @@ static void resolve_type_expr_string(TypeExpr &dst, VertexPtr e) { return; } if (auto as_string_build = e.try_as()) { - for (const auto &arg : as_string_build->args()) { + for (const auto& arg : as_string_build->args()) { resolve_type_expr_string(dst, arg); } return; @@ -103,12 +103,12 @@ static ClassPtr get_cdata_class(FunctionPtr context, VertexPtr expr) { return {}; } -static const FFIType *get_ffi_type(FunctionPtr context, VertexPtr expr) { +static const FFIType* get_ffi_type(FunctionPtr context, VertexPtr expr) { auto assumption = assume_class_of_expr(context, expr, expr); if (!assumption.assum_hint) { return nullptr; } - if (const auto *as_ffi = assumption.assum_hint->try_as()) { + if (const auto* as_ffi = assumption.assum_hint->try_as()) { return as_ffi->type; } if (auto as_class = assumption.try_as_class()) { @@ -119,48 +119,46 @@ static const FFIType *get_ffi_type(FunctionPtr context, VertexPtr expr) { return nullptr; } -static bool is_ptr_type_hint(const TypeHint *type_hint) { - const auto *as_ffi = type_hint->try_as(); +static bool is_ptr_type_hint(const TypeHint* type_hint) { + const auto* as_ffi = type_hint->try_as(); if (!as_ffi) { return false; } return as_ffi->type->kind == FFITypeKind::Pointer; } -static bool is_ptr_field(ClassPtr klass, const std::string &field_name) { - const auto *field = klass->get_instance_field(field_name); +static bool is_ptr_field(ClassPtr klass, const std::string& field_name) { + const auto* field = klass->get_instance_field(field_name); if (!field) { return false; } return is_ptr_type_hint(field->type_hint); } -static bool contains_non_scalar_types(const FFIType *type) { +static bool contains_non_scalar_types(const FFIType* type) { if (vk::any_of_equal(type->kind, FFITypeKind::Struct, FFITypeKind::Union)) { return true; } - return std::any_of(type->members.begin(), type->members.end(), [](const FFIType *member) { - return contains_non_scalar_types(member); - }); + return std::any_of(type->members.begin(), type->members.end(), [](const FFIType* member) { return contains_non_scalar_types(member); }); } static inline VertexPtr unwrap_if_c2php_conv(VertexPtr v) { - return v->type() == op_ffi_c2php_conv // unwrapping might be useful for outermost ast roots, - ? v.as()->expr() // since op_ffi_c2php_conv is created in on_exit_vertex() - : v; + return v->type() == op_ffi_c2php_conv // unwrapping might be useful for outermost ast roots, + ? v.as()->expr() // since op_ffi_c2php_conv is created in on_exit_vertex() + : v; } // internal handling FFI::cast('int', $cdata) and $cdef->cast('struct A', $cdata): calc the @return of this operation // from_type is a FFI type of $cdata value -static const TypeHint *ffi_cast_impl(const FFIType *type, const FFIType *from_type, ClassPtr scope_class) { +static const TypeHint* ffi_cast_impl(const FFIType* type, const FFIType* from_type, ClassPtr scope_class) { // FFI::cast returns a reference-like non-owning data, so a special care // should be taken here - if (const auto *to_builtin = ffi_builtin_type(type->kind)) { - const auto *from_builtin = ffi_builtin_type(from_type->kind); + if (const auto* to_builtin = ffi_builtin_type(type->kind)) { + const auto* from_builtin = ffi_builtin_type(from_type->kind); // it could potentially be safe to perform some struct->scalar conversions, // but we're forbidding them for now - kphp_error_act(from_builtin, - fmt_format("ffi casting a non-scalar type {} to a scalar type {}", ffi_decltype_string(from_type), to_builtin->c_name), return nullptr); + kphp_error_act(from_builtin, fmt_format("ffi casting a non-scalar type {} to a scalar type {}", ffi_decltype_string(from_type), to_builtin->c_name), + return nullptr); return TypeHintInstance::create("&" + to_builtin->php_class_name); } @@ -168,7 +166,8 @@ static const TypeHint *ffi_cast_impl(const FFIType *type, const FFIType *from_ty kphp_error_act(type->kind == FFITypeKind::Pointer, "can only cast arrays to pointers", return nullptr); } if (type->kind == FFITypeKind::Array) { - kphp_error_act(from_type->kind == FFITypeKind::Pointer, fmt_format("only pointers can be cast to arrays (got {})", ffi_decltype_string(from_type)), return nullptr); + kphp_error_act(from_type->kind == FFITypeKind::Pointer, fmt_format("only pointers can be cast to arrays (got {})", ffi_decltype_string(from_type)), + return nullptr); kphp_error_act(type->members[0]->kind != FFITypeKind::Array, "can't cast to multi-dimensional array", return nullptr); } @@ -176,31 +175,27 @@ static const TypeHint *ffi_cast_impl(const FFIType *type, const FFIType *from_ty return TypeHintInstance::create("&" + FFIRoot::cdata_class_name(scope_class->ffi_scope_mixin->scope_name, type->str)); } - const TypeHint *php_type = G->get_ffi_root().create_type_hint(type, !scope_class ? "C" : scope_class->ffi_scope_mixin->scope_name); + const TypeHint* php_type = G->get_ffi_root().create_type_hint(type, !scope_class ? "C" : scope_class->ffi_scope_mixin->scope_name); check_class_defined(php_type); return php_type; } struct InferResult { - const TypeHint *type_hint = nullptr; + const TypeHint* type_hint = nullptr; VertexPtr size_expr; VertexPtr owned_flag_expr; }; static InferResult infer_from_static_new(VertexAdaptor call) { - kphp_error_act(!call->args().empty(), - "FFI::new() expects one non-empty string argument", return {}); + kphp_error_act(!call->args().empty(), "FFI::new() expects one non-empty string argument", return {}); TypeExpr type_expr = resolve_type_expr_string(call->args()[0]); - kphp_error_act(!type_expr.err, - fmt_format("FFI::new(): {}", type_expr.err), return {}); + kphp_error_act(!type_expr.err, fmt_format("FFI::new(): {}", type_expr.err), return {}); FFITypedefs typedefs; - auto[type, err] = ffi_parse_type(type_expr.cdef, typedefs); - kphp_error_act(err.message.empty(), - fmt_format("FFI::new(): line {}: {}", err.line, err.message), return {}); - kphp_error_act(!contains_non_scalar_types(type), - "static FFI::new() can only create scalar types", return {}); + auto [type, err] = ffi_parse_type(type_expr.cdef, typedefs); + kphp_error_act(err.message.empty(), fmt_format("FFI::new(): line {}: {}", err.line, err.message), return {}); + kphp_error_act(!contains_non_scalar_types(type), "static FFI::new() can only create scalar types", return {}); VertexPtr owned_flag_expr; if (call->args().size() == 2) { @@ -211,41 +206,36 @@ static InferResult infer_from_static_new(VertexAdaptor call) { } static InferResult infer_from_scope_new(VertexAdaptor call, ClassPtr scope_class) { - kphp_error_act(call->args().size() >= 2, // first is implicit $this + kphp_error_act(call->args().size() >= 2, // first is implicit $this "ffi->new() expects a non-empty const string argument", return {}); TypeExpr type_expr = resolve_type_expr_string(call->args()[1]); - kphp_error_act(!type_expr.err, - fmt_format("ffi->new(): {}", type_expr.err), return {}); + kphp_error_act(!type_expr.err, fmt_format("ffi->new(): {}", type_expr.err), return {}); - auto[type, err] = ffi_parse_type(type_expr.cdef, scope_class->ffi_scope_mixin->typedefs); - kphp_error_act(err.message.empty(), - fmt_format("ffi->new(): line {}: {}", err.line, err.message), return {}); + auto [type, err] = ffi_parse_type(type_expr.cdef, scope_class->ffi_scope_mixin->typedefs); + kphp_error_act(err.message.empty(), fmt_format("ffi->new(): line {}: {}", err.line, err.message), return {}); VertexPtr owned_flag_expr; if (call->args().size() == 3) { owned_flag_expr = call->args()[2]; } - const TypeHint *php_type = G->get_ffi_root().create_type_hint(type, scope_class->ffi_scope_mixin->scope_name); + const TypeHint* php_type = G->get_ffi_root().create_type_hint(type, scope_class->ffi_scope_mixin->scope_name); kphp_error(php_type, fmt_format("ffi->new(): failed to infer a PHP type hint for {} type", type->str)); return {php_type, type_expr.size_expr, owned_flag_expr}; } static InferResult infer_from_static_cast(FunctionPtr f, VertexAdaptor call) { - kphp_error_act(call->args().size() == 2, - "FFI::cast() expects two arguments", return {}); + kphp_error_act(call->args().size() == 2, "FFI::cast() expects two arguments", return {}); TypeExpr type_expr = resolve_type_expr_string(call->args()[0]); - kphp_error_act(!type_expr.err, - fmt_format("FFI::cast(): {}", type_expr.err), return {}); + kphp_error_act(!type_expr.err, fmt_format("FFI::cast(): {}", type_expr.err), return {}); FFITypedefs typedefs; - auto[type, err] = ffi_parse_type(type_expr.cdef, typedefs); - kphp_error_act(err.message.empty(), - fmt_format("FFI::cast(): line {}: {}", err.line, err.message), return {}); + auto [type, err] = ffi_parse_type(type_expr.cdef, typedefs); + kphp_error_act(err.message.empty(), fmt_format("FFI::cast(): line {}: {}", err.line, err.message), return {}); - const FFIType *from_type = get_ffi_type(f, call->args()[1]); + const FFIType* from_type = get_ffi_type(f, call->args()[1]); if (!from_type) { return {}; } @@ -254,18 +244,16 @@ static InferResult infer_from_static_cast(FunctionPtr f, VertexAdaptor call, ClassPtr scope_class) { - kphp_error_act(call->args().size() == 3, // first is implicit $this + kphp_error_act(call->args().size() == 3, // first is implicit $this "ffi->cast() expects two arguments", return {}); TypeExpr type_expr = resolve_type_expr_string(call->args()[1]); - kphp_error_act(!type_expr.err, - fmt_format("ffi->cast(): {}", type_expr.err), return {}); + kphp_error_act(!type_expr.err, fmt_format("ffi->cast(): {}", type_expr.err), return {}); - auto[type, err] = ffi_parse_type(type_expr.cdef, scope_class->ffi_scope_mixin->typedefs); - kphp_error_act(err.message.empty(), - fmt_format("ffi->cast(): line {}: {}", err.line, err.message), return {}); + auto [type, err] = ffi_parse_type(type_expr.cdef, scope_class->ffi_scope_mixin->typedefs); + kphp_error_act(err.message.empty(), fmt_format("ffi->cast(): line {}: {}", err.line, err.message), return {}); - const FFIType *from_type = get_ffi_type(f, call->args()[2]); + const FFIType* from_type = get_ffi_type(f, call->args()[2]); if (!from_type) { return {}; } @@ -273,7 +261,7 @@ static InferResult infer_from_scope_cast(FunctionPtr f, VertexAdaptor create_ffi_new(const InferResult &infer_result) { +static VertexAdaptor create_ffi_new(const InferResult& infer_result) { VertexPtr size_expr; VertexPtr owned_flag_expr = infer_result.owned_flag_expr; if (!infer_result.owned_flag_expr) { @@ -283,7 +271,7 @@ static VertexAdaptor create_ffi_new(const InferResult &infer_result) // a dynamically sized array size_expr = infer_result.size_expr; return VertexAdaptor::create(owned_flag_expr, infer_result.size_expr); - } else if (const auto *ffi_type_hint = infer_result.type_hint->try_as()) { + } else if (const auto* ffi_type_hint = infer_result.type_hint->try_as()) { if (ffi_type_hint->type->kind == FFITypeKind::Array && ffi_type_hint->type->num >= 0) { // a fixed-size array size_expr = VertexUtil::create_int_const(ffi_type_hint->type->num); @@ -295,12 +283,12 @@ static VertexAdaptor create_ffi_new(const InferResult &infer_result) return VertexAdaptor::create(owned_flag_expr); } -static const TypeHint *infer_ffi_array_elem_type(FunctionPtr context, VertexPtr array_arg) { - const auto *type_hint = assume_class_of_expr(context, array_arg, array_arg).assum_hint; +static const TypeHint* infer_ffi_array_elem_type(FunctionPtr context, VertexPtr array_arg) { + const auto* type_hint = assume_class_of_expr(context, array_arg, array_arg).assum_hint; if (!type_hint) { return nullptr; } - const auto *ffi_type = type_hint->try_as(); + const auto* ffi_type = type_hint->try_as(); if (!ffi_type) { return nullptr; } @@ -347,18 +335,16 @@ VertexPtr InstantiateFFIOperationsPass::on_ffi_array_get(VertexAdaptorargs()[0]; auto key_arg = call->args()[1]; - const auto *c_elem_type = infer_ffi_array_elem_type(current_function, array_arg); + const auto* c_elem_type = infer_ffi_array_elem_type(current_function, array_arg); kphp_error_act(c_elem_type, "ffi_array_get: invalid $arr argument", return call); auto array_get = VertexAdaptor::create(array_arg, key_arg).set_location(call); array_get->c_elem_type = c_elem_type; - const auto *php_type = G->get_ffi_root().c2php_field_type_hint(array_get->c_elem_type); + const auto* php_type = G->get_ffi_root().c2php_field_type_hint(array_get->c_elem_type); auto conv = VertexAdaptor::create(array_get).set_location(array_get); conv->php_type = php_type; - kphp_error_act(php_type, - fmt_format("Unsupported c2php type: {}", array_get->c_elem_type->as_human_readable()), - return array_get); + kphp_error_act(php_type, fmt_format("Unsupported c2php type: {}", array_get->c_elem_type->as_human_readable()), return array_get); return conv; } @@ -370,7 +356,7 @@ VertexPtr InstantiateFFIOperationsPass::on_ffi_array_set(VertexAdaptorargs()[1]; auto value_arg = call->args()[2]; - const auto *c_elem_type = infer_ffi_array_elem_type(current_function, array_arg); + const auto* c_elem_type = infer_ffi_array_elem_type(current_function, array_arg); kphp_error_act(c_elem_type, "ffi_array_set: invalid $arr argument", return call); auto php2c_conv = VertexAdaptor::create(value_arg).set_location(value_arg); @@ -428,14 +414,14 @@ VertexPtr InstantiateFFIOperationsPass::on_ffi_scope_cast(VertexAdaptor call) { FunctionPtr called_func = call->func_id; - for (int i = 1; i < call->args().size(); i++) { // 0 is implicit $this + for (int i = 1; i < call->args().size(); i++) { // 0 is implicit $this auto arg = call->args()[i]; auto func_param = called_func->get_params()[i].as(); // last param of a variadic function: wrap each item of arg (it's op_array) into php2c conv if (called_func->has_variadic_param && i == called_func->get_params().size() - 1) { kphp_assert(arg->type() == op_array); - for (auto &array_item: *arg) { + for (auto& array_item : *arg) { if (array_item->type() == op_ffi_c2php_conv) { array_item = unwrap_if_c2php_conv(array_item); } else { @@ -464,7 +450,7 @@ VertexPtr InstantiateFFIOperationsPass::on_ffi_scope_call_custom(VertexAdaptorargs()[i] = php2c_conv; } - const auto *php_type = G->get_ffi_root().c2php_return_type_hint(called_func->return_typehint); + const auto* php_type = G->get_ffi_root().c2php_return_type_hint(called_func->return_typehint); kphp_error_act(php_type, fmt_format("Unsupported c2php type: {}", called_func->return_typehint->as_human_readable()), return call); auto conv = VertexAdaptor::create(call).set_location(call); @@ -491,9 +477,7 @@ VertexPtr InstantiateFFIOperationsPass::on_cdata_instance_prop(ClassPtr root_cla current->access_type = InstancePropAccessType::CData; break; } - current->access_type = is_ptr_field(cdata_class, next->get_string()) - ? InstancePropAccessType::CDataDirectPtr - : InstancePropAccessType::CDataDirect; + current->access_type = is_ptr_field(cdata_class, next->get_string()) ? InstancePropAccessType::CDataDirectPtr : InstancePropAccessType::CDataDirect; current = next; } @@ -504,7 +488,7 @@ VertexPtr InstantiateFFIOperationsPass::on_cdata_instance_prop(ClassPtr root_cla // $struct->field = $value; // works in both PHP and KPHP // var_dump($struct->field); // works in both PHP and KPHP if (root->str_val == "cdata" && root->instance()->type() == op_var) { - const auto *php_type = G->get_ffi_root().c2php_scalar_type_hint(root_class); + const auto* php_type = G->get_ffi_root().c2php_scalar_type_hint(root_class); if (php_type) { auto getref = VertexAdaptor::create(root->instance()).set_location(root); auto conv = VertexAdaptor::create(getref).set_location(getref); @@ -512,12 +496,12 @@ VertexPtr InstantiateFFIOperationsPass::on_cdata_instance_prop(ClassPtr root_cla return conv; } } - kphp_error_act(root->str_val != "cdata", // non-var lhs + kphp_error_act(root->str_val != "cdata", // non-var lhs fmt_format("Field $cdata not found in class {}", root_class->as_human_readable()), return root); - const auto *field = root_class->get_instance_field(root->get_string()); + const auto* field = root_class->get_instance_field(root->get_string()); kphp_assert(field && field->type_hint); - const auto *php_type = G->get_ffi_root().c2php_field_type_hint(field->type_hint); + const auto* php_type = G->get_ffi_root().c2php_field_type_hint(field->type_hint); kphp_error_act(php_type, fmt_format("Unsupported c2php type: {}", field->type_hint->as_human_readable()), return root); auto conv = VertexAdaptor::create(root).set_location(root); @@ -534,9 +518,9 @@ VertexPtr InstantiateFFIOperationsPass::on_scope_instance_prop(ClassPtr scope_cl root->access_type = InstancePropAccessType::ExternVar; - const auto *field = scope_class->get_instance_field(root->get_string()); + const auto* field = scope_class->get_instance_field(root->get_string()); kphp_assert(field && field->type_hint); - const auto *php_type = G->get_ffi_root().c2php_field_type_hint(field->type_hint); + const auto* php_type = G->get_ffi_root().c2php_field_type_hint(field->type_hint); kphp_error_act(php_type, fmt_format("Unsupported c2php type: {}", field->type_hint->as_human_readable()), return root); auto conv = VertexAdaptor::create(root).set_location(root); @@ -544,31 +528,30 @@ VertexPtr InstantiateFFIOperationsPass::on_scope_instance_prop(ClassPtr scope_cl return conv; } -const TypeHint *InstantiateFFIOperationsPass::infer_from_ffi_array_get(FunctionPtr f, VertexAdaptor call) { +const TypeHint* InstantiateFFIOperationsPass::infer_from_ffi_array_get(FunctionPtr f, VertexAdaptor call) { return call->args().empty() ? nullptr : infer_ffi_array_elem_type(f, call->args()[0]); } // infer @return for FFI::new() -const TypeHint *InstantiateFFIOperationsPass::infer_from_ffi_static_new(VertexAdaptor call) { +const TypeHint* InstantiateFFIOperationsPass::infer_from_ffi_static_new(VertexAdaptor call) { return infer_from_static_new(call).type_hint; } // infer @return for $cdef->new() -const TypeHint *InstantiateFFIOperationsPass::infer_from_ffi_scope_new(VertexAdaptor call, ClassPtr scope_class) { +const TypeHint* InstantiateFFIOperationsPass::infer_from_ffi_scope_new(VertexAdaptor call, ClassPtr scope_class) { return infer_from_scope_new(call, scope_class).type_hint; } // infer @return for FFI::cast() -const TypeHint *InstantiateFFIOperationsPass::infer_from_ffi_static_cast(FunctionPtr f, VertexAdaptor call) { +const TypeHint* InstantiateFFIOperationsPass::infer_from_ffi_static_cast(FunctionPtr f, VertexAdaptor call) { return infer_from_static_cast(f, call).type_hint; } // infer @return for $cdef->cast() -const TypeHint *InstantiateFFIOperationsPass::infer_from_ffi_scope_cast(FunctionPtr f, VertexAdaptor call, ClassPtr scope_class) { +const TypeHint* InstantiateFFIOperationsPass::infer_from_ffi_scope_cast(FunctionPtr f, VertexAdaptor call, ClassPtr scope_class) { return infer_from_scope_cast(f, call, scope_class).type_hint; } - VertexPtr InstantiateFFIOperationsPass::on_enter_vertex(VertexPtr root) { if (auto instance_prop = root.try_as()) { if (instance_prop->access_type != InstancePropAccessType::Default) { @@ -629,7 +612,7 @@ VertexPtr InstantiateFFIOperationsPass::on_exit_vertex(VertexPtr root) { auto c2php = call->args()[0].as(); // it's easy to get C fixed sized array type decay to a pointer, // so we inline the count result right away - if (const auto *as_ffi = c2php->php_type->try_as()) { + if (const auto* as_ffi = c2php->php_type->try_as()) { if (as_ffi->type->kind == FFITypeKind::Array && as_ffi->type->num != -1) { return VertexUtil::create_int_const(as_ffi->type->num); } @@ -677,7 +660,7 @@ VertexPtr InstantiateFFIOperationsPass::on_exit_vertex(VertexPtr root) { assign->rhs() = rhs_c2php_conv->expr(); } else { auto php2c_conv = VertexAdaptor::create(assign->rhs()).set_location(assign->rhs()); - const TypeHint *c_type = assume_class_of_expr(current_function, lhs, assign).assum_hint; + const TypeHint* c_type = assume_class_of_expr(current_function, lhs, assign).assum_hint; php2c_conv->c_type = c_type; php2c_conv->simple_dst = lhs->type() == op_var; assign->rhs() = php2c_conv; diff --git a/compiler/pipes/instantiate-ffi-operations.h b/compiler/pipes/instantiate-ffi-operations.h index 3d2d668a9f..cc92b2075a 100644 --- a/compiler/pipes/instantiate-ffi-operations.h +++ b/compiler/pipes/instantiate-ffi-operations.h @@ -35,9 +35,9 @@ class InstantiateFFIOperationsPass final : public FunctionPassBase { // calc @return of FFI::new() and others, that can't be expressed in functions.txt // they are used in assumptions also - static const TypeHint *infer_from_ffi_static_new(VertexAdaptor call); - static const TypeHint *infer_from_ffi_scope_new(VertexAdaptor call, ClassPtr scope_class); - static const TypeHint *infer_from_ffi_static_cast(FunctionPtr f, VertexAdaptor call); - static const TypeHint *infer_from_ffi_scope_cast(FunctionPtr f, VertexAdaptor call, ClassPtr scope_class); - static const TypeHint *infer_from_ffi_array_get(FunctionPtr f, VertexAdaptor call); + static const TypeHint* infer_from_ffi_static_new(VertexAdaptor call); + static const TypeHint* infer_from_ffi_scope_new(VertexAdaptor call, ClassPtr scope_class); + static const TypeHint* infer_from_ffi_static_cast(FunctionPtr f, VertexAdaptor call); + static const TypeHint* infer_from_ffi_scope_cast(FunctionPtr f, VertexAdaptor call, ClassPtr scope_class); + static const TypeHint* infer_from_ffi_array_get(FunctionPtr f, VertexAdaptor call); }; diff --git a/compiler/pipes/instantiate-generics-and-lambdas.cpp b/compiler/pipes/instantiate-generics-and-lambdas.cpp index 6ccd834a69..13e15a5a48 100644 --- a/compiler/pipes/instantiate-generics-and-lambdas.cpp +++ b/compiler/pipes/instantiate-generics-and-lambdas.cpp @@ -8,11 +8,11 @@ #include "compiler/data/class-data.h" #include "compiler/data/function-data.h" #include "compiler/data/generics-mixins.h" -#include "compiler/vertex-util.h" #include "compiler/lambda-utils.h" #include "compiler/phpdoc.h" -#include "compiler/type-hint.h" #include "compiler/pipes/clone-nested-lambdas.h" +#include "compiler/type-hint.h" +#include "compiler/vertex-util.h" /* * This pass creates new functions and passes them backwards to be handled again: @@ -25,13 +25,12 @@ class InstantiateGenericFunctionPass final : public FunctionPassBase { FunctionPtr generic_function; - const GenericsInstantiationMixin *instantiationTs; + const GenericsInstantiationMixin* instantiationTs; public: - InstantiateGenericFunctionPass(FunctionPtr generic_function, const GenericsInstantiationMixin *instantiationTs) - : generic_function(generic_function) - , instantiationTs(instantiationTs) { - } + InstantiateGenericFunctionPass(FunctionPtr generic_function, const GenericsInstantiationMixin* instantiationTs) + : generic_function(generic_function), + instantiationTs(instantiationTs) {} std::string get_description() override { return "Instantiate generic function"; @@ -46,15 +45,15 @@ class InstantiateGenericFunctionPass final : public FunctionPassBase { if (as_call->reifiedTs) { kphp_assert(as_call->reifiedTs->empty() && as_call->reifiedTs->commentTs); as_call->reifiedTs = new GenericsInstantiationMixin(*as_call->reifiedTs); - for (auto &type_hint : as_call->reifiedTs->commentTs->vectorTs) { + for (auto& type_hint : as_call->reifiedTs->commentTs->vectorTs) { type_hint = phpdoc_replace_genericTs_with_reified(type_hint, instantiationTs); } } // inside f, replace `classof($o)` with "A" if `f(T $o)` called as `f(expr_assumed_A)` if (as_call->str_val == "classof" && as_call->size() == 1 && as_call->extra_type != op_ex_func_call_arrow) { if (auto as_var = as_call->args().begin()->try_as()) { - if (const TypeHint *param_type_hint = get_param_type_hint_if_generic(as_var->str_val)) { - if (const auto *as_genericT = param_type_hint->try_as()) { + if (const TypeHint* param_type_hint = get_param_type_hint_if_generic(as_var->str_val)) { + if (const auto* as_genericT = param_type_hint->try_as()) { return replace_with_string_const_if_T_is_class(as_genericT->nameT, root); } } @@ -63,8 +62,8 @@ class InstantiateGenericFunctionPass final : public FunctionPassBase { } else if (auto as_var = root.try_as()) { // inside f, replace `$cn` with "A" if `f(class-string $cn)` called as `f(A::class)` - if (const TypeHint *param_type_hint = get_param_type_hint_if_generic(as_var->str_val)) { - if (const auto *as_class_string = param_type_hint->try_as()) { + if (const TypeHint* param_type_hint = get_param_type_hint_if_generic(as_var->str_val)) { + if (const auto* as_class_string = param_type_hint->try_as()) { return replace_with_string_const_if_T_is_class(as_class_string->inner->try_as()->nameT, root); } } @@ -85,16 +84,16 @@ class InstantiateGenericFunctionPass final : public FunctionPassBase { return false; } - VertexPtr replace_with_string_const_if_T_is_class(const std::string &nameT, VertexPtr v_to_replace) { - if (const TypeHint *instT = instantiationTs->find(nameT)) { - if (const auto *as_instance = instT->try_as()) { + VertexPtr replace_with_string_const_if_T_is_class(const std::string& nameT, VertexPtr v_to_replace) { + if (const TypeHint* instT = instantiationTs->find(nameT)) { + if (const auto* as_instance = instT->try_as()) { return VertexUtil::create_string_const(as_instance->full_class_name).set_location(v_to_replace); } } return v_to_replace; } - const TypeHint *get_param_type_hint_if_generic(const std::string &var_name) { + const TypeHint* get_param_type_hint_if_generic(const std::string& var_name) { auto param = generic_function->find_param_by_name(var_name); if (param && param->type_hint && param->type_hint->has_genericT_inside() && find_param_by_name(var_name)) { return param->type_hint; @@ -102,7 +101,7 @@ class InstantiateGenericFunctionPass final : public FunctionPassBase { return nullptr; } - VertexAdaptor find_param_by_name(const std::string &var_name) { + VertexAdaptor find_param_by_name(const std::string& var_name) { FunctionPtr outer_function = current_function; while (outer_function->is_lambda()) { bool is_used = std::find_if(outer_function->uses_list.begin(), outer_function->uses_list.end(), @@ -116,12 +115,10 @@ class InstantiateGenericFunctionPass final : public FunctionPassBase { } }; - // when we have a call `f(...)`, we generate a new function `f$_$T1$_$T2`, // which is not a generic one, but an instantiated one -static FunctionPtr instantiate_generic_function(FunctionPtr generic_function, - GenericsInstantiationMixin *instantiationTs, - const std::string &name_of_instantiated_function) { +static FunctionPtr instantiate_generic_function(FunctionPtr generic_function, GenericsInstantiationMixin* instantiationTs, + const std::string& name_of_instantiated_function) { auto new_function = FunctionData::clone_from(generic_function, name_of_instantiated_function); CloneNestedLambdasPass::run_if_lambdas_inside(new_function, nullptr); @@ -151,13 +148,11 @@ static FunctionPtr instantiate_generic_function(FunctionPtr generic_function, return new_function; } -static FunctionPtr instantiate_generic_function_concurrent(FunctionPtr generic_function, - GenericsInstantiationMixin *instantiationTs, - const std::string &name_of_instantiated_function, - DataStream &function_stream) { +static FunctionPtr instantiate_generic_function_concurrent(FunctionPtr generic_function, GenericsInstantiationMixin* instantiationTs, + const std::string& name_of_instantiated_function, DataStream& function_stream) { FunctionPtr generated_function; - G->operate_on_function_locking(name_of_instantiated_function, [&](FunctionPtr &f) { + G->operate_on_function_locking(name_of_instantiated_function, [&](FunctionPtr& f) { if (!f) { f = instantiate_generic_function(generic_function, instantiationTs, name_of_instantiated_function); @@ -175,18 +170,16 @@ static FunctionPtr instantiate_generic_function_concurrent(FunctionPtr generic_f return generated_function; } - // the pass which is called from the F pipe // (the F pipe is needed to have several outputs, which is impossible with Pass structure) class InstantiateGenericsAndLambdasPass final : public FunctionPassBase { - DataStream &function_stream; - DataStream &forward_next_stream; + DataStream& function_stream; + DataStream& forward_next_stream; public: - - explicit InstantiateGenericsAndLambdasPass(DataStream &function_stream, DataStream &forward_next_stream) - : function_stream(function_stream) - , forward_next_stream(forward_next_stream) {} + explicit InstantiateGenericsAndLambdasPass(DataStream& function_stream, DataStream& forward_next_stream) + : function_stream(function_stream), + forward_next_stream(forward_next_stream) {} std::string get_description() override { return "Instantiate generics and lambdas"; @@ -218,10 +211,10 @@ class InstantiateGenericsAndLambdasPass final : public FunctionPassBase { // if f is a member of an interface, instantiate f in all derived classes // note, that we don't allow `class A { foo() { ... } } class B : A { foo() { ... } }` (moving a generic to self method) if (generic_function->modifiers.is_instance() && generic_function->is_virtual_method) { - kphp_assert(generic_function->modifiers.is_abstract()); // should have been checked in advance + kphp_assert(generic_function->modifiers.is_abstract()); // should have been checked in advance for (ClassPtr derived : generic_function->class_id->get_all_derived_classes()) { if (derived != generic_function->class_id) { - if (const auto *method = derived->members.get_instance_method(generic_function->local_name())) { + if (const auto* method = derived->members.get_instance_method(generic_function->local_name())) { on_generic_func_call_instantiate(method->function, call); } } @@ -245,7 +238,7 @@ class InstantiateGenericsAndLambdasPass final : public FunctionPassBase { ClassPtr c_lambda = generate_lambda_class_wrapping_lambda_function(f_lambda); kphp_assert(f_lambda->class_id == c_lambda); - if (v_lambda->lambda_class) { // while deducing types, we used this field to express inheritance from a typed callable + if (v_lambda->lambda_class) { // while deducing types, we used this field to express inheritance from a typed callable kphp_assert(v_lambda->lambda_class->is_typed_callable_interface()); inherit_lambda_class_from_typed_callable(c_lambda, v_lambda->lambda_class); G->require_function(v_lambda->lambda_class->get_instance_method("__invoke")->function, function_stream); @@ -254,7 +247,7 @@ class InstantiateGenericsAndLambdasPass final : public FunctionPassBase { InstantiateGenericsAndLambdasPass pass_lambda(function_stream, forward_next_stream); run_function_pass(f_lambda, &pass_lambda); - forward_next_stream << f_lambda; // nested lambdas were already processed by DeduceImplicitTypesAndCastsPass + forward_next_stream << f_lambda; // nested lambdas were already processed by DeduceImplicitTypesAndCastsPass G->require_function(c_lambda->construct_function, function_stream); G->require_function(c_lambda->get_instance_method("__invoke")->function, function_stream); @@ -281,10 +274,9 @@ class InstantiateGenericsAndLambdasPass final : public FunctionPassBase { } }; - -void InstantiateGenericsAndLambdasF::execute(FunctionPtr function, OStreamT &os) { - auto &forward_next_stream = *os.project_to_nth_data_stream<0>(); - auto &newly_generated_functions_stream = *os.project_to_nth_data_stream<1>(); +void InstantiateGenericsAndLambdasF::execute(FunctionPtr function, OStreamT& os) { + auto& forward_next_stream = *os.project_to_nth_data_stream<0>(); + auto& newly_generated_functions_stream = *os.project_to_nth_data_stream<1>(); InstantiateGenericsAndLambdasPass pass(newly_generated_functions_stream, forward_next_stream); run_function_pass(function, &pass); diff --git a/compiler/pipes/instantiate-generics-and-lambdas.h b/compiler/pipes/instantiate-generics-and-lambdas.h index 5dabd0a89a..9cafd15a1e 100644 --- a/compiler/pipes/instantiate-generics-and-lambdas.h +++ b/compiler/pipes/instantiate-generics-and-lambdas.h @@ -22,5 +22,5 @@ class InstantiateGenericsAndLambdasF { // (this pipe is needed to have several outputs, which is impossible with Pass structure) using need_profiler = std::false_type; - void execute(FunctionPtr function, OStreamT &os); + void execute(FunctionPtr function, OStreamT& os); }; diff --git a/compiler/pipes/load-files.cpp b/compiler/pipes/load-files.cpp index 15b9f7eab0..6c0856adfb 100644 --- a/compiler/pipes/load-files.cpp +++ b/compiler/pipes/load-files.cpp @@ -8,11 +8,11 @@ #include "compiler/stage.h" #include "compiler/threading/profiler.h" -void LoadFileF::execute(SrcFilePtr file, DataStream &os) { +void LoadFileF::execute(SrcFilePtr file, DataStream& os) { stage::set_name("Load file"); stage::set_file(file); - kphp_assert (!file->loaded); + kphp_assert(!file->loaded); file->load(); if (stage::has_error()) { diff --git a/compiler/pipes/load-files.h b/compiler/pipes/load-files.h index 5b969ce154..cd0e68f9ce 100644 --- a/compiler/pipes/load-files.h +++ b/compiler/pipes/load-files.h @@ -9,5 +9,5 @@ class LoadFileF { public: - void execute(SrcFilePtr file, DataStream &os); + void execute(SrcFilePtr file, DataStream& os); }; diff --git a/compiler/pipes/optimization.cpp b/compiler/pipes/optimization.cpp index 1ce099e507..a320b82f83 100644 --- a/compiler/pipes/optimization.cpp +++ b/compiler/pipes/optimization.cpp @@ -15,8 +15,8 @@ #include "common/algorithms/hashes.h" #include "compiler/data/class-data.h" -#include "compiler/vertex-util.h" #include "compiler/inferring/public.h" +#include "compiler/vertex-util.h" namespace { @@ -27,45 +27,42 @@ int get_expr_dep_level(VertexPtr vertex) { return var->var_id->dependency_level; } int max_dependency_level = 0; - for (const auto &child: *vertex) { + for (const auto& child : *vertex) { max_dependency_level = std::max(max_dependency_level, get_expr_dep_level(child)); } return max_dependency_level; } -bool can_init_value_be_removed(VertexPtr init_value, const VarPtr &variable) { - const auto *variable_type = tinf::get_type(variable); - if (variable_type->use_optional() || - vk::any_of_equal(variable_type->ptype(), tp_Class, tp_mixed)) { +bool can_init_value_be_removed(VertexPtr init_value, const VarPtr& variable) { + const auto* variable_type = tinf::get_type(variable); + if (variable_type->use_optional() || vk::any_of_equal(variable_type->ptype(), tp_Class, tp_mixed)) { return init_value->type() == op_null; } - const auto *init_type = tinf::get_type(init_value); - if (init_value->extra_type != op_ex_var_const || - init_type->use_optional() || - init_type->ptype() != variable_type->ptype()) { + const auto* init_type = tinf::get_type(init_value); + if (init_value->extra_type != op_ex_var_const || init_type->use_optional() || init_type->ptype() != variable_type->ptype()) { return false; } switch (init_type->ptype()) { - case tp_string: { - const auto *init_string = VertexUtil::get_constexpr_string(init_value); - return init_string && init_string->empty(); - } - case tp_array: - return init_type->lookup_at_any_key()->get_real_ptype() == tp_any; - default: - return false; + case tp_string: { + const auto* init_string = VertexUtil::get_constexpr_string(init_value); + return init_string && init_string->empty(); + } + case tp_array: + return init_type->lookup_at_any_key()->get_real_ptype() == tp_any; + default: + return false; } } -VarPtr cast_const_array_type(VertexPtr &type_acceptor, const TypeData *required_type) noexcept { +VarPtr cast_const_array_type(VertexPtr& type_acceptor, const TypeData* required_type) noexcept { std::stringstream ss; ss << type_acceptor->get_string() << "$" << std::hex << vk::std_hash(type_out(required_type)); std::string name = ss.str(); bool is_new = true; VarPtr var_id = G->get_constant_var(name, type_acceptor, &is_new); - var_id->tinf_node.copy_type_from(required_type); // not inside if(is_new) to avoid race conditions when one thread creates and another uses faster + var_id->tinf_node.copy_type_from(required_type); // not inside if(is_new) to avoid race conditions when one thread creates and another uses faster if (is_new) { var_id->dependency_level = type_acceptor.as()->var_id->dependency_level + 1; } @@ -80,7 +77,7 @@ VarPtr cast_const_array_type(VertexPtr &type_acceptor, const TypeData *required_ return var_id; } -void cast_array_creation_type(VertexAdaptor op_array_vertex, const TypeData *required_type) noexcept { +void cast_array_creation_type(VertexAdaptor op_array_vertex, const TypeData* required_type) noexcept { if (required_type->get_real_ptype() == tp_mixed) { required_type = TypeData::get_type(tp_array, tp_mixed); } else if (required_type->use_optional()) { @@ -89,10 +86,9 @@ void cast_array_creation_type(VertexAdaptor op_array_vertex, const Typ op_array_vertex->tinf_node.set_type(required_type); } -void explicit_cast_array_type(VertexPtr &type_acceptor, const TypeData *required_type, std::set *new_var_out = nullptr) noexcept { - const auto *existed_type = tinf::get_type(type_acceptor); - if (existed_type->get_real_ptype() != tp_array || - !is_implicit_array_conversion(existed_type, required_type)) { +void explicit_cast_array_type(VertexPtr& type_acceptor, const TypeData* required_type, std::set* new_var_out = nullptr) noexcept { + const auto* existed_type = tinf::get_type(type_acceptor); + if (existed_type->get_real_ptype() != tp_array || !is_implicit_array_conversion(existed_type, required_type)) { return; } if (!vk::any_of_equal(required_type->get_real_ptype(), tp_array, tp_mixed)) { @@ -123,7 +119,7 @@ VertexPtr transform_set_on_class(VertexPtr set_op, VertexPtr container, VertexPt auto klass = tinf::get_type(container)->class_type(); kphp_assert_msg(klass, "Internal error: cannot get type of object for write [] access"); - const auto *method = klass->get_instance_method("offsetSet"); + const auto* method = klass->get_instance_method("offsetSet"); kphp_error(method, fmt::format("Class {} does not implement \\ArrayAccess", klass->name).c_str()); if (set_op->rl_type == val_none) { @@ -146,15 +142,15 @@ VertexPtr transform_set_on_class(VertexPtr set_op, VertexPtr container, VertexPt return result; } -VertexPtr optimize_set_push_back(VertexPtr set_op, VertexAdaptor index, VertexPtr container, VertexPtr key, VertexPtr value, PrimitiveType container_ptype ) { +VertexPtr optimize_set_push_back(VertexPtr set_op, VertexAdaptor index, VertexPtr container, VertexPtr key, VertexPtr value, + PrimitiveType container_ptype) { VertexPtr result; if (index->has_key() && set_op->rl_type != val_none) { return set_op; } if (!key) { - kphp_error (container_ptype == tp_array || container_ptype == tp_mixed, - fmt_format("Can not use [] for {}", type_out(tinf::get_type(container)))); + kphp_error(container_ptype == tp_array || container_ptype == tp_mixed, fmt_format("Can not use [] for {}", type_out(tinf::get_type(container)))); if (set_op->rl_type == val_none) { result = VertexAdaptor::create(container, value); @@ -180,14 +176,14 @@ VertexPtr OptimizationPass::optimize_set_with_offset(VertexAdaptor set_o VertexPtr container = index->array(); VertexPtr key = index->has_key() ? index->key() : VertexPtr{}; VertexPtr value = set_op->rhs(); - + PrimitiveType container_ptype = tinf::get_type(container)->get_real_ptype(); if (container_ptype == tp_Class) { return transform_set_on_class(set_op, container, key, value); } return optimize_set_push_back(set_op, index, container, key, value, container_ptype); } -void OptimizationPass::collect_concat(VertexPtr root, std::vector *collected) { +void OptimizationPass::collect_concat(VertexPtr root, std::vector* collected) { if (root->type() == op_string_build || root->type() == op_concat) { for (auto i : *root) { collect_concat(i, collected); @@ -229,19 +225,19 @@ VertexPtr OptimizationPass::optimize_postfix_dec(VertexPtr root) { VertexPtr OptimizationPass::optimize_index(VertexAdaptor index) { if (!index->has_key()) { if (index->rl_type == val_l) { - kphp_error (0, "Unsupported []"); + kphp_error(0, "Unsupported []"); } else { - kphp_error (0, "Cannot use [] for reading"); + kphp_error(0, "Cannot use [] for reading"); } } - auto &lhs = index->array(); - const auto *tpe = tinf::get_type(index->array()); // funny + auto& lhs = index->array(); + const auto* tpe = tinf::get_type(index->array()); // funny if (tpe->get_real_ptype() == tp_Class) { auto klass = tpe->class_type(); kphp_assert_msg(klass, "Internal error: cannot get type of object for read [] access"); - const auto *method = klass->get_instance_method("offsetGet"); + const auto* method = klass->get_instance_method("offsetGet"); kphp_error(method, fmt_format("Class {} does not implement \\ArrayAccess", klass->name).c_str()); auto new_call = VertexAdaptor::create(lhs, index->key()).set_location(lhs); @@ -266,7 +262,7 @@ VertexPtr OptimizationPass::remove_extra_conversions(VertexPtr root) { while (OpInfo::type(root->type()) == conv_op || vk::any_of_equal(root->type(), op_conv_array_l, op_conv_int_l, op_conv_string_l)) { VertexPtr expr = root.as()->expr(); - const TypeData *tp = tinf::get_type(expr); + const TypeData* tp = tinf::get_type(expr); VertexPtr res; if (!tp->use_optional()) { if (vk::any_of_equal(root->type(), op_conv_int, op_conv_int_l) && tp->ptype() == tp_int) { @@ -280,19 +276,19 @@ VertexPtr OptimizationPass::remove_extra_conversions(VertexPtr root) { } else if (vk::any_of_equal(root->type(), op_conv_array, op_conv_array_l) && tp->get_real_ptype() == tp_array) { res = expr; } else if (root->type() == op_force_mixed && tp->ptype() == tp_void) { - expr->rl_type = val_none; - res = VertexAdaptor::create(expr, VertexAdaptor::create()); + expr->rl_type = val_none; + res = VertexAdaptor::create(expr, VertexAdaptor::create()); } } if (root->type() == op_conv_mixed) { res = expr; } - if (root->type() == op_conv_drop_null){ + if (root->type() == op_conv_drop_null) { if (!tp->can_store_null()) { res = expr; } } - if (root->type() == op_conv_drop_false){ + if (root->type() == op_conv_drop_false) { if (!tp->can_store_false()) { res = expr; } @@ -312,7 +308,7 @@ VertexPtr OptimizationPass::remove_extra_conversions(VertexPtr root) { // has such a method. // If the conversion fails, an empty VertexPtr will be returned. VertexPtr OptimizationPass::try_convert_expr_to_call_to_string_method(VertexPtr expr) { - const auto *type = tinf::get_type(expr); + const auto* type = tinf::get_type(expr); if (type == nullptr) { return {}; } @@ -322,9 +318,8 @@ VertexPtr OptimizationPass::try_convert_expr_to_call_to_string_method(VertexPtr return {}; } - const auto *to_string_method = klass->get_instance_method(ClassData::NAME_OF_TO_STRING); - kphp_error_act(to_string_method, - fmt_format("Converting to a string of a class {} that does not contain a __toString() method", klass->as_human_readable()), + const auto* to_string_method = klass->get_instance_method(ClassData::NAME_OF_TO_STRING); + kphp_error_act(to_string_method, fmt_format("Converting to a string of a class {} that does not contain a __toString() method", klass->as_human_readable()), return {}); auto call_function = VertexAdaptor::create(expr); @@ -361,7 +356,7 @@ VertexPtr OptimizationPass::on_enter_vertex(VertexPtr root) { } else if (auto param = root.try_as()) { if (!param->x()->ref_flag) { auto temp_var = root.as()->temp_var().as(); - if (temp_var && temp_var->extra_type == op_ex_var_superlocal) { // see CreateSwitchForeachVarsPass + if (temp_var && temp_var->extra_type == op_ex_var_superlocal) { // see CreateSwitchForeachVarsPass temp_var->var_id->needs_const_iterator_flag = true; } } @@ -373,7 +368,7 @@ VertexPtr OptimizationPass::on_enter_vertex(VertexPtr root) { auto func = func_call->func_id; if (!func->is_extern()) { auto args = func_call->args(); - const auto ¶ms = func->param_ids; + const auto& params = func->param_ids; const size_t elements = std::min(static_cast(args.size()), params.size()); for (size_t index = 0; index < elements; ++index) { explicit_cast_array_type(args[index], tinf::get_type(params[index]), ¤t_function->explicit_const_var_ids); @@ -381,8 +376,8 @@ VertexPtr OptimizationPass::on_enter_vertex(VertexPtr root) { } } else if (auto op_array_vertex = root.try_as()) { if (var_init_expression_optimization_depth_ == 0 || op_array_vertex->const_type == ConstValueType::cnst_const_val) { - for (auto &array_element : *op_array_vertex) { - const auto *required_type = tinf::get_type(op_array_vertex)->lookup_at_any_key(); + for (auto& array_element : *op_array_vertex) { + const auto* required_type = tinf::get_type(op_array_vertex)->lookup_at_any_key(); if (vk::any_of_equal(array_element->type(), op_var, op_array)) { explicit_cast_array_type(array_element, required_type, ¤t_function->explicit_const_var_ids); } else if (auto array_key_value = array_element.try_as()) { @@ -398,7 +393,7 @@ VertexPtr OptimizationPass::on_enter_vertex(VertexPtr root) { root = convert_strval_to_magic_tostring_method_call(op_conv_string_vertex); } - if (root->rl_type != val_none/* && root->rl_type != val_error*/) { + if (root->rl_type != val_none /* && root->rl_type != val_error*/) { // wtf? tinf::get_type(root); } @@ -408,7 +403,7 @@ VertexPtr OptimizationPass::on_enter_vertex(VertexPtr root) { bool OptimizationPass::user_recursion(VertexPtr root) { if (auto var_vertex = root.try_as()) { VarPtr var = var_vertex->var_id; - kphp_assert (var); + kphp_assert(var); if (var->init_val) { if (__sync_bool_compare_and_swap(&var->optimize_flag, false, true)) { ++var_init_expression_optimization_depth_; @@ -432,7 +427,7 @@ bool OptimizationPass::check_function(FunctionPtr function) const { void OptimizationPass::on_finish() { if (current_function->type == FunctionData::func_class_holder) { auto class_id = current_function->class_id; - class_id->members.for_each([this](ClassMemberInstanceField &class_field) { + class_id->members.for_each([this](ClassMemberInstanceField& class_field) { if (class_field.var->init_val) { run_function_pass(class_field.var->init_val, this); @@ -445,7 +440,7 @@ void OptimizationPass::on_finish() { } }); - class_id->members.for_each([this](ClassMemberStaticField &static_field) { + class_id->members.for_each([this](ClassMemberStaticField& static_field) { if (static_field.var->init_val) { run_function_pass(static_field.var->init_val, this); // a static field's init value is stored in php globals and is reset via hard_reset_var() diff --git a/compiler/pipes/optimization.h b/compiler/pipes/optimization.h index 958ac65222..f3a8aa1205 100644 --- a/compiler/pipes/optimization.h +++ b/compiler/pipes/optimization.h @@ -10,7 +10,7 @@ class OptimizationPass final : public FunctionPassBase { private: VertexPtr optimize_set_with_offset(VertexAdaptor set_op); - void collect_concat(VertexPtr root, std::vector *collected); + void collect_concat(VertexPtr root, std::vector* collected); VertexPtr optimize_string_building(VertexPtr root); VertexPtr optimize_postfix_inc(VertexPtr root); VertexPtr optimize_postfix_dec(VertexPtr root); diff --git a/compiler/pipes/parse-and-apply-phpdoc.cpp b/compiler/pipes/parse-and-apply-phpdoc.cpp index fffb4ec463..d627877e4e 100644 --- a/compiler/pipes/parse-and-apply-phpdoc.cpp +++ b/compiler/pipes/parse-and-apply-phpdoc.cpp @@ -36,7 +36,6 @@ * - 'callable' and 'object' convert a function into a generic one */ - class ParseAndApplyPhpDocForFunction { FunctionPtr f_; bool infer_cast_{false}; @@ -45,24 +44,24 @@ class ParseAndApplyPhpDocForFunction { public: explicit ParseAndApplyPhpDocForFunction(FunctionPtr f) - : f_(f) - , phpdoc_from_fun_(get_phpdoc_from_fun_considering_inheritance()) - , func_params_(f->get_params()) { + : f_(f), + phpdoc_from_fun_(get_phpdoc_from_fun_considering_inheritance()), + func_params_(f->get_params()) { stage::set_location(phpdoc_from_fun_->root->location); - const PhpDocComment *phpdoc = phpdoc_from_fun_->phpdoc; + const PhpDocComment* phpdoc = phpdoc_from_fun_->phpdoc; // first, search for @kphp-... tags // @param/@return will be scanned later, as @kphp- annotations can affect their behavior if (phpdoc) { - for (const PhpDocTag &tag : phpdoc->tags) { + for (const PhpDocTag& tag : phpdoc->tags) { parse_kphp_doc_tag(tag); } } // at first, parse @param tags: do it before @return if (phpdoc) { - for (const PhpDocTag &tag : phpdoc->tags) { + for (const PhpDocTag& tag : phpdoc->tags) { if (tag.type == PhpDocType::param) { parse_param_doc_tag(tag); } @@ -77,7 +76,7 @@ class ParseAndApplyPhpDocForFunction { // now, parse @return tags if (phpdoc) { - for (const auto &tag : phpdoc->tags) { + for (const auto& tag : phpdoc->tags) { if (tag.type == PhpDocType::returns) { parse_return_doc_tag(tag); } @@ -113,26 +112,25 @@ class ParseAndApplyPhpDocForFunction { // does the user need to specify @param for all and @return unless void? bool needs_to_be_fully_typed = - // if KPHP_REQUIRE_FUNCTIONS_TYPING = 0, only check types if given, typing everything is not mandatory - G->settings().require_functions_typing.get() && - // if 1, typing is mandatory, except these conditions - f_->type == FunctionData::func_local && - !f_->is_lambda() && // lambdas may have implicitly deduced types, they are going to be checked later - !f_->disabled_warnings.count("return"); // "@kphp-disable-warnings return" in function phpdoc + // if KPHP_REQUIRE_FUNCTIONS_TYPING = 0, only check types if given, typing everything is not mandatory + G->settings().require_functions_typing.get() && + // if 1, typing is mandatory, except these conditions + f_->type == FunctionData::func_local && !f_->is_lambda() && // lambdas may have implicitly deduced types, they are going to be checked later + !f_->disabled_warnings.count("return"); // "@kphp-disable-warnings return" in function phpdoc if (needs_to_be_fully_typed) { check_all_arguments_have_param_or_type_hint(); } if (!f_->return_typehint) { f_->return_typehint = auto_create_return_type_if_not_provided(); - if (!f_->return_typehint && needs_to_be_fully_typed) { // if @return not set, assume void + if (!f_->return_typehint && needs_to_be_fully_typed) { // if @return not set, assume void f_->return_typehint = TypeHintPrimitive::create(tp_void); } } } private: - bool is_phpdoc_meaningful(const PhpDocComment *phpdoc) { + bool is_phpdoc_meaningful(const PhpDocComment* phpdoc) { if (!phpdoc) { return false; } @@ -155,18 +153,18 @@ class ParseAndApplyPhpDocForFunction { if (!is_phpdoc_inherited) { return f_; } - for (const auto &ancestor : f_->class_id->get_all_ancestors()) { + for (const auto& ancestor : f_->class_id->get_all_ancestors()) { if (ancestor == f_->class_id) { continue; } if (f_->modifiers.is_instance()) { - if (const auto *method = ancestor->members.get_instance_method(f_->local_name())) { + if (const auto* method = ancestor->members.get_instance_method(f_->local_name())) { if (is_phpdoc_meaningful(method->function->phpdoc)) { return method->function; } } - } else if (const auto *method = ancestor->members.get_static_method(f_->local_name())) { + } else if (const auto* method = ancestor->members.get_static_method(f_->local_name())) { if (is_phpdoc_meaningful(method->function->phpdoc)) { return method->function; } @@ -183,8 +181,8 @@ class ParseAndApplyPhpDocForFunction { continue; } - if (const auto *as_callable = cur_func_param->type_hint->try_as()) { - if (!as_callable->is_typed_callable()) { // we will generate common interfaces for typed callables in on_finish() + if (const auto* as_callable = cur_func_param->type_hint->try_as()) { + if (!as_callable->is_typed_callable()) { // we will generate common interfaces for typed callables in on_finish() GenericsDeclarationMixin::make_function_generic_on_callable_arg(f_, cur_func_param); } } else if (!f_->is_extern() && cur_func_param->type_hint->try_as()) { @@ -196,253 +194,255 @@ class ParseAndApplyPhpDocForFunction { // for `f<...TArg>`, there must be a variadic parameter annotated `TArg ...$name` void check_variadic_generic_f_has_necessary_param() { VertexRange f_params = f_->get_params(); - auto last_param = f_params[f_params.size()-1].as(); + auto last_param = f_params[f_params.size() - 1].as(); kphp_assert(last_param->extra_type == op_ex_param_variadic); - const auto *as_array = last_param->type_hint ? last_param->type_hint->try_as() : nullptr; - bool is_declared_ok = as_array && as_array->inner->try_as() && as_array->inner->try_as()->nameT == f_->genericTs->itemsT.back().nameT; - kphp_error(is_declared_ok, fmt_format("Invalid @param declaration for a variadic generic.\nMust declare @param {} ...${}", f_->genericTs->itemsT.back().nameT, last_param->var()->str_val)); + const auto* as_array = last_param->type_hint ? last_param->type_hint->try_as() : nullptr; + bool is_declared_ok = + as_array && as_array->inner->try_as() && as_array->inner->try_as()->nameT == f_->genericTs->itemsT.back().nameT; + kphp_error(is_declared_ok, fmt_format("Invalid @param declaration for a variadic generic.\nMust declare @param {} ...${}", + f_->genericTs->itemsT.back().nameT, last_param->var()->str_val)); } - static inline const GenericsDeclarationMixin *get_genericTs_for_phpdoc_parsing(FunctionPtr f_) { - const auto *f = f_->get_this_or_topmost_if_lambda(); + static inline const GenericsDeclarationMixin* get_genericTs_for_phpdoc_parsing(FunctionPtr f_) { + const auto* f = f_->get_this_or_topmost_if_lambda(); if (f->genericTs) { return f->genericTs; } return nullptr; } - void parse_kphp_doc_tag(const PhpDocTag &tag) { + void parse_kphp_doc_tag(const PhpDocTag& tag) { switch (tag.type) { - case PhpDocType::kphp_inline: { - f_->is_inline = true; - break; - } + case PhpDocType::kphp_inline: { + f_->is_inline = true; + break; + } - case PhpDocType::kphp_profile: { - f_->profiler_state = FunctionData::profiler_status::enable_as_root; - break; - } - case PhpDocType::kphp_profile_allow_inline: { - if (f_->profiler_state == FunctionData::profiler_status::disable) { - f_->profiler_state = FunctionData::profiler_status::enable_as_inline_child; - } else { - kphp_assert(f_->profiler_state == FunctionData::profiler_status::enable_as_root); - } - break; + case PhpDocType::kphp_profile: { + f_->profiler_state = FunctionData::profiler_status::enable_as_root; + break; + } + case PhpDocType::kphp_profile_allow_inline: { + if (f_->profiler_state == FunctionData::profiler_status::disable) { + f_->profiler_state = FunctionData::profiler_status::enable_as_inline_child; + } else { + kphp_assert(f_->profiler_state == FunctionData::profiler_status::enable_as_root); } + break; + } - case PhpDocType::kphp_sync: { - f_->should_be_sync = true; - break; - } + case PhpDocType::kphp_sync: { + f_->should_be_sync = true; + break; + } - case PhpDocType::kphp_should_not_throw: { - f_->should_not_throw = true; - break; - } + case PhpDocType::kphp_should_not_throw: { + f_->should_not_throw = true; + break; + } - case PhpDocType::kphp_infer: { - if (tag.value.find("cast") != std::string::npos) { - infer_cast_ = true; - } - break; + case PhpDocType::kphp_infer: { + if (tag.value.find("cast") != std::string::npos) { + infer_cast_ = true; } + break; + } - case PhpDocType::kphp_warn_unused_result: { - f_->warn_unused_result = true; - break; - } + case PhpDocType::kphp_warn_unused_result: { + f_->warn_unused_result = true; + break; + } - case PhpDocType::kphp_disable_warnings: { - std::istringstream is(tag.value_as_string()); - std::string token; - while (is >> token) { - if (!f_->disabled_warnings.insert(token).second) { - kphp_warning(fmt_format("Warning '{}' has been disabled twice", token)); - } + case PhpDocType::kphp_disable_warnings: { + std::istringstream is(tag.value_as_string()); + std::string token; + while (is >> token) { + if (!f_->disabled_warnings.insert(token).second) { + kphp_warning(fmt_format("Warning '{}' has been disabled twice", token)); } - break; - } - - case PhpDocType::kphp_extern_func_info: { - // This is temporary solution for generate-stub - bool doc_is_generated_stub = false; - std::istringstream is(tag.value_as_string()); - std::string token; - while (is >> token) { - if (token == "can_throw") { - // since we don't know which exceptions it can throw, mark is as \Exception - f_->exceptions_thrown.insert(G->get_class("Exception")); - } else if (token == "resumable") { - f_->is_resumable = true; - } else if (token == "cpp_template_call") { - f_->cpp_template_call = true; - } else if (token == "cpp_variadic_call") { - f_->cpp_variadic_call = true; - } else if (token == "tl_common_h_dep") { - f_->tl_common_h_dep = true; - } else if (token == "interruptible") { - f_->is_interruptible = true; - } else if (token == "stub") { - f_->is_stub = true; - } else if (token == "generation-required") { - if (!f_->is_stub) { - kphp_error(0, fmt_format("generation required can be used only for stubs")); - } - doc_is_generated_stub = true; - f_->need_generated_stub = true; - } else { - kphp_error(0, fmt_format("Unknown @kphp-extern-func-info {}", token)); + } + break; + } + + case PhpDocType::kphp_extern_func_info: { + // This is temporary solution for generate-stub + bool doc_is_generated_stub = false; + std::istringstream is(tag.value_as_string()); + std::string token; + while (is >> token) { + if (token == "can_throw") { + // since we don't know which exceptions it can throw, mark is as \Exception + f_->exceptions_thrown.insert(G->get_class("Exception")); + } else if (token == "resumable") { + f_->is_resumable = true; + } else if (token == "cpp_template_call") { + f_->cpp_template_call = true; + } else if (token == "cpp_variadic_call") { + f_->cpp_variadic_call = true; + } else if (token == "tl_common_h_dep") { + f_->tl_common_h_dep = true; + } else if (token == "interruptible") { + f_->is_interruptible = true; + } else if (token == "stub") { + f_->is_stub = true; + } else if (token == "generation-required") { + if (!f_->is_stub) { + kphp_error(0, fmt_format("generation required can be used only for stubs")); } + doc_is_generated_stub = true; + f_->need_generated_stub = true; + } else { + kphp_error(0, fmt_format("Unknown @kphp-extern-func-info {}", token)); } - kphp_error(f_->is_extern() || (f_->is_constructor() && doc_is_generated_stub), "@kphp-extern-func-info used for regular function"); - break; } + kphp_error(f_->is_extern() || (f_->is_constructor() && doc_is_generated_stub), "@kphp-extern-func-info used for regular function"); + break; + } - case PhpDocType::kphp_pure_function: { - kphp_error(f_->is_extern(), "@kphp-pure-function is supported only for built-in functions"); - f_->is_pure = true; - break; - } + case PhpDocType::kphp_pure_function: { + kphp_error(f_->is_extern(), "@kphp-pure-function is supported only for built-in functions"); + f_->is_pure = true; + break; + } - case PhpDocType::kphp_noreturn: { - f_->is_no_return = true; - break; - } + case PhpDocType::kphp_noreturn: { + f_->is_no_return = true; + break; + } - case PhpDocType::kphp_lib_export: { - f_->kphp_lib_export = true; - break; - } + case PhpDocType::kphp_lib_export: { + f_->kphp_lib_export = true; + break; + } - case PhpDocType::kphp_template: { - if (!f_->genericTs) { // @kphp-template is an old-style declaration, there may be multiple tags - f_->genericTs = GenericsDeclarationMixin::create_for_function_from_phpdoc(f_, phpdoc_from_fun_->phpdoc); - } - break; + case PhpDocType::kphp_template: { + if (!f_->genericTs) { // @kphp-template is an old-style declaration, there may be multiple tags + f_->genericTs = GenericsDeclarationMixin::create_for_function_from_phpdoc(f_, phpdoc_from_fun_->phpdoc); } + break; + } - case PhpDocType::kphp_generic: { - kphp_error_return(!f_->is_constructor(), "__construct() can't be declared as a generic function"); - // @kphp-generic above a function was parsed in gentree (though it could be inherited) - kphp_assert(f_->genericTs || phpdoc_from_fun_->genericTs); - if (!f_->genericTs) { - f_->genericTs = new GenericsDeclarationMixin(*phpdoc_from_fun_->genericTs); + case PhpDocType::kphp_generic: { + kphp_error_return(!f_->is_constructor(), "__construct() can't be declared as a generic function"); + // @kphp-generic above a function was parsed in gentree (though it could be inherited) + kphp_assert(f_->genericTs || phpdoc_from_fun_->genericTs); + if (!f_->genericTs) { + f_->genericTs = new GenericsDeclarationMixin(*phpdoc_from_fun_->genericTs); + } + // but still needs to check classes existence to react on T=Unknown and to resolve 'self' + for (auto& itemT : f_->genericTs->itemsT) { + if (itemT.extends_hint) { + itemT.extends_hint = phpdoc_finalize_type_hint_and_resolve(itemT.extends_hint, f_); + kphp_error(itemT.extends_hint, fmt_format("Could not parse generic T extends after '{}:'", itemT.nameT)); + GenericsDeclarationMixin::check_declarationT_extends_hint(itemT.extends_hint, itemT.nameT); } - // but still needs to check classes existence to react on T=Unknown and to resolve 'self' - for (auto &itemT : f_->genericTs->itemsT) { - if (itemT.extends_hint) { - itemT.extends_hint = phpdoc_finalize_type_hint_and_resolve(itemT.extends_hint, f_); - kphp_error(itemT.extends_hint, fmt_format("Could not parse generic T extends after '{}:'", itemT.nameT)); - GenericsDeclarationMixin::check_declarationT_extends_hint(itemT.extends_hint, itemT.nameT); - } - if (itemT.def_hint) { - itemT.def_hint = phpdoc_finalize_type_hint_and_resolve(itemT.def_hint, f_); - kphp_error(itemT.def_hint, fmt_format("Could not parse generic T default after '{}='", itemT.nameT)); - GenericsDeclarationMixin::check_declarationT_def_hint(itemT.def_hint, itemT.nameT); - } + if (itemT.def_hint) { + itemT.def_hint = phpdoc_finalize_type_hint_and_resolve(itemT.def_hint, f_); + kphp_error(itemT.def_hint, fmt_format("Could not parse generic T default after '{}='", itemT.nameT)); + GenericsDeclarationMixin::check_declarationT_def_hint(itemT.def_hint, itemT.nameT); } - break; } + break; + } - case PhpDocType::kphp_tracing: { - bool is_static_method_wrap = f_->class_id && f_->modifiers.is_static() && f_->is_auto_inherited; - if (!is_static_method_wrap) { - f_->kphp_tracing = KphpTracingDeclarationMixin::create_for_function_from_phpdoc(f_, tag.value); - } - break; + case PhpDocType::kphp_tracing: { + bool is_static_method_wrap = f_->class_id && f_->modifiers.is_static() && f_->is_auto_inherited; + if (!is_static_method_wrap) { + f_->kphp_tracing = KphpTracingDeclarationMixin::create_for_function_from_phpdoc(f_, tag.value); } + break; + } - case PhpDocType::kphp_const: { - for (const auto &var_name : split_skipping_delimeters(tag.value, ", ")) { - auto param = f_->find_param_by_name(var_name.substr(1)); - kphp_error_return(param, fmt_format("@kphp-const tag var name mismatch. found {}.", var_name)); - param->var()->is_const = true; - } - - break; + case PhpDocType::kphp_const: { + for (const auto& var_name : split_skipping_delimeters(tag.value, ", ")) { + auto param = f_->find_param_by_name(var_name.substr(1)); + kphp_error_return(param, fmt_format("@kphp-const tag var name mismatch. found {}.", var_name)); + param->var()->is_const = true; } - case PhpDocType::kphp_flatten: { - f_->is_flatten = true; - break; - } + break; + } - case PhpDocType::kphp_warn_performance: { - try { - f_->performance_inspections_for_warning.set_from_php_doc(tag.value); - } catch (const std::exception &ex) { - kphp_error(false, fmt_format("@kphp-warn-performance bad tag: {}", ex.what())); - } - break; + case PhpDocType::kphp_flatten: { + f_->is_flatten = true; + break; + } + + case PhpDocType::kphp_warn_performance: { + try { + f_->performance_inspections_for_warning.set_from_php_doc(tag.value); + } catch (const std::exception& ex) { + kphp_error(false, fmt_format("@kphp-warn-performance bad tag: {}", ex.what())); } + break; + } - case PhpDocType::kphp_analyze_performance: { - try { - f_->performance_inspections_for_analysis.set_from_php_doc(tag.value); - } catch (const std::exception &ex) { - kphp_error(false, fmt_format("@kphp-analyze-performance bad tag: {}", ex.what())); - } - break; + case PhpDocType::kphp_analyze_performance: { + try { + f_->performance_inspections_for_analysis.set_from_php_doc(tag.value); + } catch (const std::exception& ex) { + kphp_error(false, fmt_format("@kphp-analyze-performance bad tag: {}", ex.what())); } + break; + } - case PhpDocType::kphp_throws: { - std::istringstream is(tag.value_as_string()); - std::string klass; - while (is >> klass) { - f_->check_throws.emplace_front(klass); // the reversed order doesn't matter - } - break; + case PhpDocType::kphp_throws: { + std::istringstream is(tag.value_as_string()); + std::string klass; + while (is >> klass) { + f_->check_throws.emplace_front(klass); // the reversed order doesn't matter } + break; + } - case PhpDocType::kphp_color: { - std::istringstream is(tag.value_as_string()); - std::string color_name; - is >> color_name; + case PhpDocType::kphp_color: { + std::istringstream is(tag.value_as_string()); + std::string color_name; + is >> color_name; - kphp_error_return(!color_name.empty(), "An empty tag value"); - kphp_error_return(G->get_function_palette().color_exists(color_name), "Color missing in palette (either a misprint or a new color that needs to be added)"); + kphp_error_return(!color_name.empty(), "An empty tag value"); + kphp_error_return(G->get_function_palette().color_exists(color_name), + "Color missing in palette (either a misprint or a new color that needs to be added)"); - f_->colors.add(G->get_function_palette().get_color_by_name(color_name)); - break; - } + f_->colors.add(G->get_function_palette().get_color_by_name(color_name)); + break; + } - case PhpDocType::kphp_internal_result_indexing: { - kphp_error(f_->is_internal, "@kphp-internal-result-indexing is supported only for internal functions"); - f_->is_result_indexing = true; - break; - } + case PhpDocType::kphp_internal_result_indexing: { + kphp_error(f_->is_internal, "@kphp-internal-result-indexing is supported only for internal functions"); + f_->is_result_indexing = true; + break; + } - case PhpDocType::kphp_internal_result_array2tuple: { - kphp_error(f_->is_internal, "@kphp-internal-result-array2tuple is supported only for internal functions"); - f_->is_result_array2tuple = true; - break; - } + case PhpDocType::kphp_internal_result_array2tuple: { + kphp_error(f_->is_internal, "@kphp-internal-result-array2tuple is supported only for internal functions"); + f_->is_result_array2tuple = true; + break; + } - case PhpDocType::kphp_internal_param_readonly: { - kphp_error(f_->is_extern(), "@kphp-internal-param-readonly is supported only for builtin functions"); - std::istringstream is(tag.value_as_string()); - std::string param_name; - is >> param_name; - auto it = std::find_if(func_params_.begin(), func_params_.end(), [¶m_name](VertexPtr v) { - return v.as()->var()->str_val == vk::string_view(param_name).substr(1); - }); - kphp_error_return(it != func_params_.end(), "kphp-internal-param-readonly used for non-existing param"); - int param_index = std::distance(func_params_.begin(), it); - kphp_error_return(param_index <= std::numeric_limits::max(), "kphp-internal-param-readonly index overflow"); - f_->readonly_param_index = param_index; - break; - } + case PhpDocType::kphp_internal_param_readonly: { + kphp_error(f_->is_extern(), "@kphp-internal-param-readonly is supported only for builtin functions"); + std::istringstream is(tag.value_as_string()); + std::string param_name; + is >> param_name; + auto it = std::find_if(func_params_.begin(), func_params_.end(), + [¶m_name](VertexPtr v) { return v.as()->var()->str_val == vk::string_view(param_name).substr(1); }); + kphp_error_return(it != func_params_.end(), "kphp-internal-param-readonly used for non-existing param"); + int param_index = std::distance(func_params_.begin(), it); + kphp_error_return(param_index <= std::numeric_limits::max(), "kphp-internal-param-readonly index overflow"); + f_->readonly_param_index = param_index; + break; + } - default: - break; + default: + break; } } - void parse_return_doc_tag(const PhpDocTag &tag) { + void parse_return_doc_tag(const PhpDocTag& tag) { auto tag_parsed = tag.value_as_type_and_var_name(phpdoc_from_fun_, get_genericTs_for_phpdoc_parsing(f_)); - if (!tag_parsed) { // an error has already been printed + if (!tag_parsed) { // an error has already been printed return; } @@ -458,9 +458,9 @@ class ParseAndApplyPhpDocForFunction { } } - void parse_param_doc_tag(const PhpDocTag &tag) { + void parse_param_doc_tag(const PhpDocTag& tag) { auto tag_parsed = tag.value_as_type_and_var_name(phpdoc_from_fun_, get_genericTs_for_phpdoc_parsing(f_)); - if (!tag_parsed) { // an error has already been printed + if (!tag_parsed) { // an error has already been printed return; } @@ -482,11 +482,13 @@ class ParseAndApplyPhpDocForFunction { } if (param->extra_type == op_ex_param_variadic) { - kphp_error(param->type_hint->try_as(), fmt_format("@param for a variadic parameter is not an array.\nDeclare either @param T ...${} or @param T[] ${}", param->var()->str_val, param->var()->str_val)); + kphp_error(param->type_hint->try_as(), + fmt_format("@param for a variadic parameter is not an array.\nDeclare either @param T ...${} or @param T[] ${}", param->var()->str_val, + param->var()->str_val)); } if (infer_cast_) { - const auto *as_primitive = tag_parsed.type_hint->try_as(); + const auto* as_primitive = tag_parsed.type_hint->try_as(); kphp_error(as_primitive, "Too hard rule for cast"); kphp_error(!param->is_cast_param, fmt_format("Duplicate type cast for argument '{}'", tag_parsed.var_name)); param->is_cast_param = true; @@ -495,7 +497,7 @@ class ParseAndApplyPhpDocForFunction { // when both type hint and phpdoc for a param/return exist, // check their compatibility and choose one of them - const TypeHint *merge_php_hint_and_phpdoc(const TypeHint *php_hint, const TypeHint *phpdoc_hint, bool is_param __attribute__ ((unused))) { + const TypeHint* merge_php_hint_and_phpdoc(const TypeHint* php_hint, const TypeHint* phpdoc_hint, bool is_param __attribute__((unused))) { if (php_hint == phpdoc_hint) { return php_hint; } @@ -516,16 +518,16 @@ class ParseAndApplyPhpDocForFunction { } // todo this is commented out, as currently vkcom has tons of mismatches // some tests in phpt/phpdocs/ are also marked with '@todo' -// if (!does_php_hint_match_phpdoc(php_hint, phpdoc_hint)) { -// print_error_php_hint_and_phpdoc_mismatch(php_hint, phpdoc_hint, is_param); -// } + // if (!does_php_hint_match_phpdoc(php_hint, phpdoc_hint)) { + // print_error_php_hint_and_phpdoc_mismatch(php_hint, phpdoc_hint, is_param); + // } return phpdoc_hint; } // for parent f($a) with @param $a and child f(hint $a), // check whether we need to prefer parent @return over self type hint - bool should_inherited_phpdoc_override_self_type_hint(const TypeHint *php_hint, const TypeHint *phpdoc_hint) { + bool should_inherited_phpdoc_override_self_type_hint(const TypeHint* php_hint, const TypeHint* phpdoc_hint) { // consider: // parent: @param callable(int):void f(callable $cb) // child: f(callable $cb) @@ -546,7 +548,7 @@ class ParseAndApplyPhpDocForFunction { // for f():array with @return int[] (same function, no inheritance), // check that type hint and phpdoc type match // note, that we can't use to_type_data(), as classes have not yet been resolved - bool does_php_hint_match_phpdoc(const TypeHint *php_hint, const TypeHint *phpdoc_hint) { + bool does_php_hint_match_phpdoc(const TypeHint* php_hint, const TypeHint* phpdoc_hint) { if (php_hint->try_as()) { return php_hint == phpdoc_hint; } @@ -557,21 +559,22 @@ class ParseAndApplyPhpDocForFunction { if (phpdoc_hint->try_as()) { return true; } - if (const auto *doc_pipe = phpdoc_hint->try_as()) { - return std::all_of(doc_pipe->items.begin(), doc_pipe->items.end(), [](const TypeHint *item_hint) -> bool { return item_hint->try_as(); }); + if (const auto* doc_pipe = phpdoc_hint->try_as()) { + return std::all_of(doc_pipe->items.begin(), doc_pipe->items.end(), + [](const TypeHint* item_hint) -> bool { return item_hint->try_as(); }); } return false; } if (php_hint->try_as()) { return phpdoc_hint->try_as(); } - if (const auto *php_optional = php_hint->try_as()) { - if (const auto *doc_optional = phpdoc_hint->try_as()) { + if (const auto* php_optional = php_hint->try_as()) { + if (const auto* doc_optional = phpdoc_hint->try_as()) { return !doc_optional->or_false && does_php_hint_match_phpdoc(php_optional->inner, doc_optional->inner); } - if (const auto *doc_pipe = phpdoc_hint->try_as()) { - return std::all_of(doc_pipe->items.begin(), doc_pipe->items.end(), [this, php_optional](const TypeHint *item_hint) -> bool { - if (const auto *as_primitive = item_hint->try_as()) { + if (const auto* doc_pipe = phpdoc_hint->try_as()) { + return std::all_of(doc_pipe->items.begin(), doc_pipe->items.end(), [this, php_optional](const TypeHint* item_hint) -> bool { + if (const auto* as_primitive = item_hint->try_as()) { return as_primitive->ptype == tp_Null; } return does_php_hint_match_phpdoc(php_optional->inner, item_hint); @@ -582,12 +585,12 @@ class ParseAndApplyPhpDocForFunction { return true; } - void print_error_php_hint_and_phpdoc_mismatch(const TypeHint *php_hint, const TypeHint *phpdoc_hint, bool is_param) __attribute__((noinline)) { + void print_error_php_hint_and_phpdoc_mismatch(const TypeHint* php_hint, const TypeHint* phpdoc_hint, bool is_param) __attribute__((noinline)) { stage::set_location(f_->root->location); std::string php_hint_str = php_hint == TypeHintArray::create_array_of_any() ? "array" : php_hint->as_human_readable(); std::string doc_hint_str = phpdoc_hint->as_human_readable(); - kphp_error(0, fmt_format("php type hint {} mismatches with {} {}{}", - TermStringFormat::paint_green(php_hint_str), is_param ? "@param" : "@return", TermStringFormat::paint_green(doc_hint_str), + kphp_error(0, fmt_format("php type hint {} mismatches with {} {}{}", TermStringFormat::paint_green(php_hint_str), is_param ? "@param" : "@return", + TermStringFormat::paint_green(doc_hint_str), phpdoc_from_fun_ == f_ ? "" : " inherited from " + phpdoc_from_fun_->as_human_readable())); } @@ -609,7 +612,7 @@ class ParseAndApplyPhpDocForFunction { kphp_assert(as_call->reifiedTs->commentTs); stage::set_location(root->location); - for (auto &inst_type_hint : as_call->reifiedTs->commentTs->vectorTs) { + for (auto& inst_type_hint : as_call->reifiedTs->commentTs->vectorTs) { inst_type_hint = phpdoc_finalize_type_hint_and_resolve(inst_type_hint, f_); kphp_error(inst_type_hint, fmt_format("Failed to parse /*<...>*/ inside {}", f_->as_human_readable())); } @@ -633,7 +636,7 @@ class ParseAndApplyPhpDocForFunction { } } - const TypeHint *auto_create_return_type_if_not_provided() { + const TypeHint* auto_create_return_type_if_not_provided() { if (f_->is_constructor()) { return f_->class_id->type_hint; } @@ -644,28 +647,27 @@ class ParseAndApplyPhpDocForFunction { } }; - class ParseAndApplyPhpDocForClass { ClassPtr klass; FunctionPtr holder_function; public: explicit ParseAndApplyPhpDocForClass(FunctionPtr holder_function) - : klass(holder_function->class_id) - , holder_function(holder_function) { + : klass(holder_function->class_id), + holder_function(holder_function) { // apply @kphp-serializable, @kphp-json and so on // do this before parsing @var for fields, as phpdoc for the class can affect parsing behaviour stage::set_location({klass->file_id, klass->get_holder_function(), klass->location_line_num}); if (klass->phpdoc) { - for (const PhpDocTag &tag : klass->phpdoc->tags) { + for (const PhpDocTag& tag : klass->phpdoc->tags) { parse_kphp_doc_tag(tag); } } // if there is @var / type hint near class field — save it; otherwise, convert the field default value to a type hint // note: it's safe to use init_val here (even if it refers to constants of other classes): defines were inlined at previous pipe - klass->members.for_each([&](ClassMemberInstanceField &f) { + klass->members.for_each([&](ClassMemberInstanceField& f) { stage::set_location(f.root->location); f.type_hint = calculate_field_type_hint(f.phpdoc, f.type_hint, f.var); if (f.type_hint) { @@ -678,7 +680,7 @@ class ParseAndApplyPhpDocForClass { } }); - klass->members.for_each([&](ClassMemberStaticField &f) { + klass->members.for_each([&](ClassMemberStaticField& f) { stage::set_location(f.root->location); f.type_hint = calculate_field_type_hint(f.phpdoc, f.type_hint, f.var); if (f.type_hint) { @@ -693,7 +695,7 @@ class ParseAndApplyPhpDocForClass { // `@kphp-json flatten` above a class should satisfy some restrictions, check them after parsing all fields if (klass->kphp_json_tags) { stage::set_location({klass->file_id, klass->get_holder_function(), klass->location_line_num}); - if (klass->kphp_json_tags->find_tag([](const kphp_json::KphpJsonTag &tag) { return tag.attr_type == kphp_json::json_attr_flatten && tag.flatten; })) { + if (klass->kphp_json_tags->find_tag([](const kphp_json::KphpJsonTag& tag) { return tag.attr_type == kphp_json::json_attr_flatten && tag.flatten; })) { klass->kphp_json_tags->check_flatten_class(klass); } } @@ -702,11 +704,11 @@ class ParseAndApplyPhpDocForClass { private: // calculate type_hint for a field using all rules // returns TypeHint or nullptr - const TypeHint *calculate_field_type_hint(const PhpDocComment *phpdoc, const TypeHint *php_type_hint, VarPtr var) { + const TypeHint* calculate_field_type_hint(const PhpDocComment* phpdoc, const TypeHint* php_type_hint, VarPtr var) { // if there is a /** @var int|false */ comment above the class field declaration // moreover, it overrides php_type_hint: /** @var int[] */ public array $a; — int[] is used instead of array if (phpdoc) { - if (const PhpDocTag *tag_phpdoc = phpdoc->find_tag(PhpDocType::var)) { + if (const PhpDocTag* tag_phpdoc = phpdoc->find_tag(PhpDocType::var)) { auto tag_parsed = tag_phpdoc->value_as_type_and_var_name(holder_function, nullptr); if (!kphp_error(tag_parsed, fmt_format("Failed to parse phpdoc of {}", var->as_human_readable()))) { return tag_parsed.type_hint; @@ -726,11 +728,11 @@ class ParseAndApplyPhpDocForClass { return nullptr; } if (var->init_val) { - const TypeHint *type_hint = phpdoc_convert_default_value_to_type_hint(var->init_val); + const TypeHint* type_hint = phpdoc_convert_default_value_to_type_hint(var->init_val); kphp_error(type_hint, fmt_format("Specify @var to {}", var->as_human_readable())); return type_hint; } - if (klass->is_lambda_class()) { // they are auto-generated, not coming from PHP code + if (klass->is_lambda_class()) { // they are auto-generated, not coming from PHP code return nullptr; } @@ -738,64 +740,55 @@ class ParseAndApplyPhpDocForClass { return nullptr; } - void parse_kphp_doc_tag(const PhpDocTag &tag) { + void parse_kphp_doc_tag(const PhpDocTag& tag) { switch (tag.type) { - case PhpDocType::kphp_serializable: - klass->is_serializable = true; - kphp_error(klass->is_class(), "@kphp-serialize is allowed only for classes"); - break; - - case PhpDocType::kphp_tl_class: - klass->is_tl_class = true; - break; - - case PhpDocType::kphp_memcache_class: - G->set_memcache_class(klass); - break; - - case PhpDocType::kphp_warn_performance: - try { - klass->members.for_each([&tag](const ClassMemberInstanceMethod &f) { - f.function->performance_inspections_for_warning.set_from_php_doc(tag.value); - }); - klass->members.for_each([&tag](const ClassMemberStaticMethod &f) { - f.function->performance_inspections_for_warning.set_from_php_doc(tag.value); - }); - } catch (const std::exception &ex) { - kphp_error(false, fmt_format("@kphp-warn-performance bad tag: {}", ex.what())); - } - break; - - case PhpDocType::kphp_analyze_performance: - try { - klass->members.for_each([&tag](const ClassMemberInstanceMethod &f) { - f.function->performance_inspections_for_analysis.set_from_php_doc(tag.value); - }); - klass->members.for_each([&tag](const ClassMemberStaticMethod &f) { - f.function->performance_inspections_for_analysis.set_from_php_doc(tag.value); - }); - } catch (const std::exception &ex) { - kphp_error(false, fmt_format("@kphp-analyze-performance bad tag: {}", ex.what())); - } - break; + case PhpDocType::kphp_serializable: + klass->is_serializable = true; + kphp_error(klass->is_class(), "@kphp-serialize is allowed only for classes"); + break; - case PhpDocType::kphp_json: - if (!klass->kphp_json_tags) { // meeting the first @kphp-json, parse them all - klass->kphp_json_tags = kphp_json::KphpJsonTagList::create_from_phpdoc(klass->get_holder_function(), klass->phpdoc, klass); - } - break; + case PhpDocType::kphp_tl_class: + klass->is_tl_class = true; + break; - default: - break; + case PhpDocType::kphp_memcache_class: + G->set_memcache_class(klass); + break; + + case PhpDocType::kphp_warn_performance: + try { + klass->members.for_each([&tag](const ClassMemberInstanceMethod& f) { f.function->performance_inspections_for_warning.set_from_php_doc(tag.value); }); + klass->members.for_each([&tag](const ClassMemberStaticMethod& f) { f.function->performance_inspections_for_warning.set_from_php_doc(tag.value); }); + } catch (const std::exception& ex) { + kphp_error(false, fmt_format("@kphp-warn-performance bad tag: {}", ex.what())); + } + break; + + case PhpDocType::kphp_analyze_performance: + try { + klass->members.for_each([&tag](const ClassMemberInstanceMethod& f) { f.function->performance_inspections_for_analysis.set_from_php_doc(tag.value); }); + klass->members.for_each([&tag](const ClassMemberStaticMethod& f) { f.function->performance_inspections_for_analysis.set_from_php_doc(tag.value); }); + } catch (const std::exception& ex) { + kphp_error(false, fmt_format("@kphp-analyze-performance bad tag: {}", ex.what())); + } + break; + + case PhpDocType::kphp_json: + if (!klass->kphp_json_tags) { // meeting the first @kphp-json, parse them all + klass->kphp_json_tags = kphp_json::KphpJsonTagList::create_from_phpdoc(klass->get_holder_function(), klass->phpdoc, klass); + } + break; + + default: + break; } } }; - -void ParseAndApplyPhpdocF::execute(FunctionPtr function, DataStream &unused_os) { +void ParseAndApplyPhpdocF::execute(FunctionPtr function, DataStream& unused_os) { stage::set_name("Apply phpdocs"); stage::set_function(function); - kphp_assert (function); + kphp_assert(function); if (function->type == FunctionData::func_class_holder) { ParseAndApplyPhpDocForClass{function}; @@ -810,7 +803,7 @@ void ParseAndApplyPhpdocF::execute(FunctionPtr function, DataStream Base::execute(function, unused_os); } -void ParseAndApplyPhpdocF::on_finish(DataStream &os) { +void ParseAndApplyPhpdocF::on_finish(DataStream& os) { stage::die_if_global_errors(); // now, when all phpdocs have been parsed, diff --git a/compiler/pipes/parse-and-apply-phpdoc.h b/compiler/pipes/parse-and-apply-phpdoc.h index 9455e2d203..6c57f1a233 100644 --- a/compiler/pipes/parse-and-apply-phpdoc.h +++ b/compiler/pipes/parse-and-apply-phpdoc.h @@ -15,10 +15,10 @@ class ParseAndApplyPhpdocF final : public SyncPipeF { using Base = SyncPipeF; public: - bool forward_to_next_pipe(const FunctionPtr &f) override { + bool forward_to_next_pipe(const FunctionPtr& f) override { return !f->is_lambda() && !f->is_generic(); } - void execute(FunctionPtr function, DataStream &unused_os) final; - void on_finish(DataStream &os) final; + void execute(FunctionPtr function, DataStream& unused_os) final; + void on_finish(DataStream& os) final; }; diff --git a/compiler/pipes/parse.cpp b/compiler/pipes/parse.cpp index 54927bd344..122685ac79 100644 --- a/compiler/pipes/parse.cpp +++ b/compiler/pipes/parse.cpp @@ -6,7 +6,7 @@ #include "compiler/gentree.h" -void ParseF::execute(std::pair> file_and_tokens, DataStream &os) { +void ParseF::execute(std::pair> file_and_tokens, DataStream& os) { stage::set_name("Parse file"); stage::set_file(file_and_tokens.first); kphp_assert(file_and_tokens.first); diff --git a/compiler/pipes/parse.h b/compiler/pipes/parse.h index bc71b80652..acd333f94c 100644 --- a/compiler/pipes/parse.h +++ b/compiler/pipes/parse.h @@ -10,5 +10,5 @@ class ParseF { public: - void execute(std::pair> file_and_tokens, DataStream &os); + void execute(std::pair> file_and_tokens, DataStream& os); }; diff --git a/compiler/pipes/preprocess-break.cpp b/compiler/pipes/preprocess-break.cpp index aa4e64fb4a..e93d951e16 100644 --- a/compiler/pipes/preprocess-break.cpp +++ b/compiler/pipes/preprocess-break.cpp @@ -5,7 +5,7 @@ #include "compiler/pipes/preprocess-break.h" int PreprocessBreakPass::get_label_id(VertexAdaptor cycle, Operation op) { - int &label_id = op == op_break ? cycle->break_label_id : cycle->continue_label_id; + int& label_id = op == op_break ? cycle->break_label_id : cycle->continue_label_id; if (label_id == 0) { label_id = ++current_label_id; } @@ -19,24 +19,12 @@ VertexPtr PreprocessBreakPass::on_enter_vertex(VertexPtr root) { if (vk::any_of_equal(root->type(), op_break, op_continue)) { auto goto_op = root.as(); - kphp_error_act ( - goto_op->level()->type() == op_int_const, - "Break/continue parameter expected to be constant integer", - return root - ); + kphp_error_act(goto_op->level()->type() == op_int_const, "Break/continue parameter expected to be constant integer", return root); int val = atoi(goto_op->level()->get_string().c_str()); - kphp_error_act ( - 1 <= val && val <= 10, - "Break/continue parameter expected to be in [1;10] interval", - return root - ); + kphp_error_act(1 <= val && val <= 10, "Break/continue parameter expected to be in [1;10] interval", return root); int cycles_n = static_cast(cycles.size()); - kphp_error_act ( - val <= cycles_n, - "Break/continue parameter is too big", - return root - ); + kphp_error_act(val <= cycles_n, "Break/continue parameter is too big", return root); bool force_label = goto_op->type() == op_continue && val == 1 && !cycles.empty() && cycles.back()->type() == op_switch; if (val != 1 || force_label) { diff --git a/compiler/pipes/preprocess-eq3.cpp b/compiler/pipes/preprocess-eq3.cpp index 089a4b2ccf..8f2d6ba6e2 100644 --- a/compiler/pipes/preprocess-eq3.cpp +++ b/compiler/pipes/preprocess-eq3.cpp @@ -33,11 +33,11 @@ inline VertexPtr PreprocessEq3Pass::convert_eq3_null_to_isset(VertexPtr eq_op, V } auto unwrapped = VertexUtil::unwrap_inlined_define(v); - if (vk::any_of_equal(unwrapped->type(), op_var, op_instance_prop, op_array) || (unwrapped->type() == op_func_call && unwrapped.try_as()->extra_type == op_ex_constructor_call)) { + if (vk::any_of_equal(unwrapped->type(), op_var, op_instance_prop, op_array) || + (unwrapped->type() == op_func_call && unwrapped.try_as()->extra_type == op_ex_constructor_call)) { // it's a kludge to make "real world" PHP code compile // TODO: can we get rid of this? - if (unwrapped->has_get_string() && - (unwrapped->get_string() == "connection" || vk::contains(unwrapped->get_string(), "MC"))) { + if (unwrapped->has_get_string() && (unwrapped->get_string() == "connection" || vk::contains(unwrapped->get_string(), "MC"))) { return eq_op; } diff --git a/compiler/pipes/preprocess-eq3.h b/compiler/pipes/preprocess-eq3.h index ca723ce2fd..cef8f5df5b 100644 --- a/compiler/pipes/preprocess-eq3.h +++ b/compiler/pipes/preprocess-eq3.h @@ -9,6 +9,7 @@ class PreprocessEq3Pass final : public FunctionPassBase { private: VertexPtr convert_eq3_null_to_isset(VertexPtr eq_op, VertexPtr not_null); + public: std::string get_description() override { return "Preprocess eq3"; diff --git a/compiler/pipes/preprocess-exceptions.cpp b/compiler/pipes/preprocess-exceptions.cpp index 46120ec55f..509a6e4fde 100644 --- a/compiler/pipes/preprocess-exceptions.cpp +++ b/compiler/pipes/preprocess-exceptions.cpp @@ -4,21 +4,19 @@ #include "compiler/pipes/preprocess-exceptions.h" +#include "compiler/compiler-core.h" #include "compiler/data/src-file.h" #include "compiler/vertex-util.h" -#include "compiler/compiler-core.h" VertexPtr PreprocessExceptions::on_exit_vertex(VertexPtr root) { static const ClassPtr throwable_class = G->get_class("Throwable"); - if (!throwable_class) { // when functions.txt deleted while development + if (!throwable_class) { // when functions.txt deleted while development return root; } if (auto catch_op = root.try_as()) { catch_op->exception_class = G->get_class(catch_op->type_declaration); - kphp_error_act(catch_op->exception_class, - fmt_format("Can't find class: {}", catch_op->type_declaration), - return catch_op); + kphp_error_act(catch_op->exception_class, fmt_format("Can't find class: {}", catch_op->type_declaration), return catch_op); if (catch_op->exception_class->is_class()) { kphp_error(throwable_class->is_parent_of(catch_op->exception_class), fmt_format("Can't catch {}; only classes that implement Throwable can be caught", catch_op->type_declaration)); diff --git a/compiler/pipes/propagate-throw-flag.cpp b/compiler/pipes/propagate-throw-flag.cpp index 7b7d914283..8a9f9b8b8b 100644 --- a/compiler/pipes/propagate-throw-flag.cpp +++ b/compiler/pipes/propagate-throw-flag.cpp @@ -13,7 +13,7 @@ VertexPtr PropagateThrowFlagPass::on_enter_vertex(VertexPtr v) { } else if (v->type() == op_func_call) { v->throw_flag = v.as()->func_id->can_throw(); } - + return v; } @@ -24,6 +24,6 @@ VertexPtr PropagateThrowFlagPass::on_exit_vertex(VertexPtr v) { break; } } - + return v; } diff --git a/compiler/pipes/register-defines.cpp b/compiler/pipes/register-defines.cpp index 736aee27b9..60ac6b64b1 100644 --- a/compiler/pipes/register-defines.cpp +++ b/compiler/pipes/register-defines.cpp @@ -16,7 +16,7 @@ VertexPtr RegisterDefinesPass::on_exit_vertex(VertexPtr root) { kphp_error_act(name->type() == op_string, "Define name should be a valid string", return root); - auto *data = new DefineData(name->get_string(), val, DefineData::def_unknown); + auto* data = new DefineData(name->get_string(), val, DefineData::def_unknown); data->file_id = stage::get_file(); G->register_define(DefinePtr(data)); diff --git a/compiler/pipes/register-ffi-scopes.cpp b/compiler/pipes/register-ffi-scopes.cpp index 48718d334b..537f90ef64 100644 --- a/compiler/pipes/register-ffi-scopes.cpp +++ b/compiler/pipes/register-ffi-scopes.cpp @@ -4,11 +4,11 @@ #include "compiler/pipes/register-ffi-scopes.h" -#include "compiler/name-gen.h" -#include "compiler/ffi/ffi_parser.h" #include "compiler/const-manipulations.h" -#include "compiler/data/src-file.h" #include "compiler/data/ffi-data.h" +#include "compiler/data/src-file.h" +#include "compiler/ffi/ffi_parser.h" +#include "compiler/name-gen.h" #include "compiler/type-hint.h" #include "compiler/vertex-util.h" @@ -16,10 +16,10 @@ class RegisterFFIScopes final : public FunctionPassBase { private: - DataStream &os; + DataStream& os; - static bool register_scope(FFIScopeDataMixin *scope, const FFIParseResult &result) { - for (const FFIType *type : result) { + static bool register_scope(FFIScopeDataMixin* scope, const FFIParseResult& result) { + for (const FFIType* type : result) { if (type->kind == FFITypeKind::Var) { scope->variables.emplace_back(type); } else if (type->kind == FFITypeKind::Function) { @@ -46,21 +46,21 @@ class RegisterFFIScopes final : public FunctionPassBase { os << class_holder; } - static void add_extern_var(VertexAdaptor call, ClassPtr scope_class, const FFIType *type, const FFIParseResult &result) { - const TypeHint *type_hint = G->get_ffi_root().create_type_hint(type->members[0], result.scope); + static void add_extern_var(VertexAdaptor call, ClassPtr scope_class, const FFIType* type, const FFIParseResult& result) { + const TypeHint* type_hint = G->get_ffi_root().create_type_hint(type->members[0], result.scope); kphp_error_return(type_hint, fmt_format("unsupported C variable type: {}", ffi_decltype_string(type->members[0]))); auto var = VertexAdaptor::create().set_location(call); var->str_val = type->str; scope_class->members.add_instance_field(var, {}, FieldModifiers{}.set_public(), nullptr, type_hint); } - void add_function(VertexAdaptor call, ClassPtr scope_class, const FFIType *type, const FFIParseResult &result) { + void add_function(VertexAdaptor call, ClassPtr scope_class, const FFIType* type, const FFIParseResult& result) { int num_params = type->members.size() - 1; // [0] stores return type, it's not a param std::vector> params; params.reserve(1 + num_params); // +1 due to $this param params.emplace_back(ClassData::gen_param_this(call->location)); for (int i = 1; i < type->members.size(); i++) { - const FFIType *ffi_type = type->members[i]; + const FFIType* ffi_type = type->members[i]; auto var = VertexAdaptor::create().set_location(call->location); auto param = VertexAdaptor::create(var).set_location(call->location); kphp_assert(ffi_type->kind == FFITypeKind::Var); @@ -99,7 +99,7 @@ class RegisterFFIScopes final : public FunctionPassBase { os << ffi_func; } - void add_struct_or_union(VertexAdaptor call, const FFIType *type, const FFIParseResult &result) { + void add_struct_or_union(VertexAdaptor call, const FFIType* type, const FFIParseResult& result) { bool is_struct = type->kind == FFITypeKind::StructDef; auto cdata_class = ClassPtr{new ClassData{ClassType::ffi_cdata}}; @@ -114,14 +114,12 @@ class RegisterFFIScopes final : public FunctionPassBase { cdata_class_ref->src_name = "CDataRef<" + ffi_mangled_decltype_string(result.scope, type) + ">"; cdata_class_ref->add_str_dependent(current_function, ClassType::klass, "\\FFI\\CData"); - for (const FFIType *field : type->members) { + for (const FFIType* field : type->members) { auto var = VertexAdaptor::create().set_location(call); var->set_string(field->str); VertexPtr default_value; - const TypeHint *type_hint = G->get_ffi_root().create_type_hint(field->members[0], result.scope); - kphp_error_return(type_hint, fmt_format("unsupported C {} field type: {}", - is_struct ? "struct" : "union", - ffi_decltype_string(field->members[0]))); + const TypeHint* type_hint = G->get_ffi_root().create_type_hint(field->members[0], result.scope); + kphp_error_return(type_hint, fmt_format("unsupported C {} field type: {}", is_struct ? "struct" : "union", ffi_decltype_string(field->members[0]))); cdata_class->members.add_instance_field(var, default_value, FieldModifiers{}.set_public(), nullptr, type_hint); cdata_class_ref->members.add_instance_field(var, default_value, FieldModifiers{}.set_public(), nullptr, type_hint); } @@ -130,7 +128,7 @@ class RegisterFFIScopes final : public FunctionPassBase { register_class(cdata_class_ref); } - void add_enum_constant(const std::string &const_name, int const_value, ClassPtr scope_class) { + void add_enum_constant(const std::string& const_name, int const_value, ClassPtr scope_class) { auto fake_op_var = VertexAdaptor::create(); fake_op_var->str_val = const_name; auto fake_def_val = VertexUtil::create_int_const(const_value); @@ -141,10 +139,8 @@ class RegisterFFIScopes final : public FunctionPassBase { scope_class->members.add_instance_field(fake_op_var, fake_def_val, FieldModifiers{}.set_public(), nullptr, nullptr); } - VertexPtr make_ffi_load_call(VertexAdaptor call, FFIScopeDataMixin *scope, const FFIParseResult &result) { - kphp_error_act(register_scope(scope, result), - fmt_format("duplicate definition of `{}` scope", result.scope), - return call); + VertexPtr make_ffi_load_call(VertexAdaptor call, FFIScopeDataMixin* scope, const FFIParseResult& result) { + kphp_error_act(register_scope(scope, result), fmt_format("duplicate definition of `{}` scope", result.scope), return call); auto scope_class = ClassPtr{new ClassData{ClassType::ffi_scope}}; scope_class->ffi_scope_mixin = scope; @@ -155,7 +151,7 @@ class RegisterFFIScopes final : public FunctionPassBase { scope->location = call->location; - for (const FFIType *type : result) { + for (const FFIType* type : result) { if (type->kind == FFITypeKind::Var) { add_extern_var(call, scope_class, type, result); } else if (type->kind == FFITypeKind::Function) { @@ -164,7 +160,7 @@ class RegisterFFIScopes final : public FunctionPassBase { add_struct_or_union(call, type, result); } } - for (const auto &enum_item : result.enum_constants) { + for (const auto& enum_item : result.enum_constants) { add_enum_constant(enum_item.first, enum_item.second, scope_class); } @@ -179,7 +175,7 @@ class RegisterFFIScopes final : public FunctionPassBase { if (call->args().empty()) { return call; } - const std::string &code = collect_string_concatenation(call->args()[0]); + const std::string& code = collect_string_concatenation(call->args()[0]); kphp_error_act(!code.empty(), "FFI::cdef() $code param expects a non-empty const string argument", return call); // we rewrite FFI::cdef('...') to FFI::load('') call and re-use the same code path as with FFI::load() @@ -187,20 +183,18 @@ class RegisterFFIScopes final : public FunctionPassBase { auto fake_load_call = VertexAdaptor::create(fake_filename_vertex).set_location(call); fake_load_call->set_string("FFI$$load"); - FFIRoot &ffi = G->get_ffi_root(); + FFIRoot& ffi = G->get_ffi_root(); int shared_lib_id = -1; if (call->args().size() > 1 && call->args()[1]->type() != op_null) { - const std::string &lib = collect_string_concatenation(call->args()[1]); + const std::string& lib = collect_string_concatenation(call->args()[1]); kphp_error_act(!lib.empty(), "FFI::cdef() $lib param expects a non-empty const string argument or null", return call); shared_lib_id = ffi.get_shared_lib_id(lib); } - auto *scope = new FFIScopeDataMixin{}; + auto* scope = new FFIScopeDataMixin{}; FFIParseResult result = ffi_parse_file(code, scope->typedefs); - kphp_error_act(result.err.message.empty(), - fmt_format("FFI::cdef(): line {}: {}", result.err.line, result.err.message), - return call); + kphp_error_act(result.err.message.empty(), fmt_format("FFI::cdef(): line {}: {}", result.err.line, result.err.message), return call); if (result.scope.empty()) { result.scope = gen_anonymous_scope_name(current_function); } @@ -217,7 +211,7 @@ class RegisterFFIScopes final : public FunctionPassBase { return VertexAdaptor::create(ffi_load_call, ffi_scope).set_location(call); } - static std::string read_file(const std::string &filename) { + static std::string read_file(const std::string& filename) { std::ifstream file{filename}; if (!file.is_open()) { return ""; @@ -236,25 +230,21 @@ class RegisterFFIScopes final : public FunctionPassBase { if (call->args().size() != 1) { return call; } - const std::string &filename = collect_string_concatenation(call->args()[0]); + const std::string& filename = collect_string_concatenation(call->args()[0]); kphp_error_act(!filename.empty(), "FFI::load() $filename param expects a non-empty const string argument", return call); std::string file_contents = read_file(filename); kphp_error_act(!file_contents.empty(), fmt_format("FFI::load() can't read {}", filename), return call); - auto *scope = new FFIScopeDataMixin{}; + auto* scope = new FFIScopeDataMixin{}; FFIParseResult result = ffi_parse_file(file_contents, scope->typedefs); - kphp_error_act(result.err.message.empty(), - fmt_format("FFI::load(): line {}: {}", result.err.line, result.err.message), - return call); + kphp_error_act(result.err.message.empty(), fmt_format("FFI::load(): line {}: {}", result.err.line, result.err.message), return call); scope->scope_name = result.scope; scope->enum_constants = result.enum_constants; - kphp_error_act(result.static_lib.empty() || result.lib.empty(), - "can't use both FFI_LIB and FFI_STATIC_LIB at the same time", - return call); + kphp_error_act(result.static_lib.empty() || result.lib.empty(), "can't use both FFI_LIB and FFI_STATIC_LIB at the same time", return call); - FFIRoot &ffi = G->get_ffi_root(); + FFIRoot& ffi = G->get_ffi_root(); int shared_lib_id = -1; if (!result.lib.empty()) { @@ -266,7 +256,8 @@ class RegisterFFIScopes final : public FunctionPassBase { } public: - explicit RegisterFFIScopes(DataStream &os): os{os} {}; + explicit RegisterFFIScopes(DataStream& os) + : os{os} {}; std::string get_description() override { return "Register FFI scopes"; @@ -295,7 +286,7 @@ VertexPtr RegisterFFIScopes::on_exit_vertex(VertexPtr root) { return root; } -void RegisterFFIScopesF::execute(FunctionPtr f, DataStream &os) { +void RegisterFFIScopesF::execute(FunctionPtr f, DataStream& os) { RegisterFFIScopes pass{os}; pass.setup(f); run_function_pass(f->root, &pass); diff --git a/compiler/pipes/register-ffi-scopes.h b/compiler/pipes/register-ffi-scopes.h index c1a7f89158..022573c562 100644 --- a/compiler/pipes/register-ffi-scopes.h +++ b/compiler/pipes/register-ffi-scopes.h @@ -10,5 +10,5 @@ // and FFI::load() - it parses FFI strings and creates scope classes. class RegisterFFIScopesF { public: - void execute(FunctionPtr f, DataStream &os); + void execute(FunctionPtr f, DataStream& os); }; diff --git a/compiler/pipes/register-kphp-configuration.cpp b/compiler/pipes/register-kphp-configuration.cpp index 07a313cfb5..588e72cf3d 100644 --- a/compiler/pipes/register-kphp-configuration.cpp +++ b/compiler/pipes/register-kphp-configuration.cpp @@ -18,7 +18,7 @@ // defined value. Besides, there are These vertices will be replaced with their values // on CollectConstVarsPass -void RegisterKphpConfiguration::execute(FunctionPtr function, DataStream &unused_os __attribute__ ((unused))) { +void RegisterKphpConfiguration::execute(FunctionPtr function, DataStream& unused_os __attribute__((unused))) { if (function->type == FunctionData::func_class_holder && function->class_id->name == configuration_class_name_) { stage::set_name("Register KphpConfiguration"); handle_KphpConfiguration_class(function->class_id); @@ -26,22 +26,17 @@ void RegisterKphpConfiguration::execute(FunctionPtr function, DataStream &os) { +void RegisterKphpConfiguration::on_finish(DataStream& os) { stage::die_if_global_errors(); Base::on_finish(os); } - void RegisterKphpConfiguration::handle_KphpConfiguration_class(ClassPtr klass) { - kphp_error( - !klass->members.has_any_instance_method() && - !klass->members.has_any_instance_var() && - !klass->members.has_any_static_method() && - !klass->members.has_any_static_var(), - fmt_format("{} class must be empty", configuration_class_name_) - ); - - klass->members.for_each([this](const ClassMemberConstant &c) { + kphp_error(!klass->members.has_any_instance_method() && !klass->members.has_any_instance_var() && !klass->members.has_any_static_method() && + !klass->members.has_any_static_var(), + fmt_format("{} class must be empty", configuration_class_name_)); + + klass->members.for_each([this](const ClassMemberConstant& c) { if (c.local_name() == "class") { return; } @@ -53,39 +48,36 @@ void RegisterKphpConfiguration::handle_KphpConfiguration_class(ClassPtr klass) { } else if (c.local_name() == exclude_namespaces_name_) { handle_constant_function_exclude_namespaces(c); } else { - kphp_error_return(0, fmt_format("Got unexpected {} constant '{}'", - configuration_class_name_, c.local_name())); + kphp_error_return(0, fmt_format("Got unexpected {} constant '{}'", configuration_class_name_, c.local_name())); } }); } -void RegisterKphpConfiguration::handle_constant_function_palette(const ClassMemberConstant &c) { +void RegisterKphpConfiguration::handle_constant_function_palette(const ClassMemberConstant& c) { function_palette::Palette palette; parse_palette(c.value, palette); G->set_function_palette(std::move(palette)); } -void RegisterKphpConfiguration::parse_palette(VertexPtr const_val, function_palette::Palette &palette) { +void RegisterKphpConfiguration::parse_palette(VertexPtr const_val, function_palette::Palette& palette) { auto arr = VertexUtil::get_actual_value(const_val).try_as(); - kphp_error_return(arr, fmt_format("{}::{} must be a constexpr array", - configuration_class_name_, function_color_palette_name_)); + kphp_error_return(arr, fmt_format("{}::{} must be a constexpr array", configuration_class_name_, function_color_palette_name_)); - for (const auto &opt : arr->args()) { + for (const auto& opt : arr->args()) { const auto ruleset_arr = VertexUtil::get_actual_value(opt).try_as(); - kphp_error_act(ruleset_arr, fmt_format("{}::{} must contain constexpr arrays (rulesets)", - configuration_class_name_, function_color_palette_name_), continue); + kphp_error_act(ruleset_arr, fmt_format("{}::{} must contain constexpr arrays (rulesets)", configuration_class_name_, function_color_palette_name_), + continue); parse_palette_ruleset(ruleset_arr, palette); } } -void RegisterKphpConfiguration::parse_palette_ruleset(VertexAdaptor arr, function_palette::Palette &palette) { +void RegisterKphpConfiguration::parse_palette_ruleset(VertexAdaptor arr, function_palette::Palette& palette) { function_palette::PaletteRuleset ruleset; - for (const auto &rule_node : arr->args()) { + for (const auto& rule_node : arr->args()) { auto pair = VertexUtil::get_actual_value(rule_node).try_as(); - kphp_error_act(pair, fmt_format("{}::{} rule must be an associative map", - configuration_class_name_, function_color_palette_name_), continue); + kphp_error_act(pair, fmt_format("{}::{} rule must be an associative map", configuration_class_name_, function_color_palette_name_), continue); parse_palette_rule(pair, palette, ruleset); } @@ -93,25 +85,25 @@ void RegisterKphpConfiguration::parse_palette_ruleset(VertexAdaptor ar palette.add_ruleset(std::move(ruleset)); } -void RegisterKphpConfiguration::parse_palette_rule(VertexAdaptor pair, function_palette::Palette &palette, function_palette::PaletteRuleset &add_to) { +void RegisterKphpConfiguration::parse_palette_rule(VertexAdaptor pair, function_palette::Palette& palette, + function_palette::PaletteRuleset& add_to) { auto parse_rule_key_colors = [this, &palette](VertexPtr key) -> std::vector { auto unwrapped_key = VertexUtil::get_actual_value(key); - const auto *rule_string = VertexUtil::get_constexpr_string(unwrapped_key); + const auto* rule_string = VertexUtil::get_constexpr_string(unwrapped_key); auto color_names_strings = split(rule_string != nullptr ? *rule_string : "", ' '); - kphp_error(!color_names_strings.empty(), fmt_format("{}::{} map keys must be non-empty constexpr strings", - configuration_class_name_, function_color_palette_name_)); - auto mapper = vk::make_transform_iterator_range([&palette](auto color_name) { - return palette.register_color_name(color_name); - }, color_names_strings.begin(), color_names_strings.end()); + kphp_error(!color_names_strings.empty(), + fmt_format("{}::{} map keys must be non-empty constexpr strings", configuration_class_name_, function_color_palette_name_)); + auto mapper = vk::make_transform_iterator_range([&palette](auto color_name) { return palette.register_color_name(color_name); }, + color_names_strings.begin(), color_names_strings.end()); return {mapper.begin(), mapper.end()}; }; auto parse_rule_value_error = [this](VertexPtr value) -> std::string { auto unwrapped_value = VertexUtil::get_actual_value(value); - const std::string *errtext_val = VertexUtil::get_constexpr_string(unwrapped_value); + const std::string* errtext_val = VertexUtil::get_constexpr_string(unwrapped_value); const auto ok_val = VertexUtil::get_actual_value(unwrapped_value).try_as(); - kphp_error(errtext_val || (ok_val && ok_val->get_string() == "1"), fmt_format("{}::{} map values must be constexpr strings or number 1", - configuration_class_name_, function_color_palette_name_)); + kphp_error(errtext_val || (ok_val && ok_val->get_string() == "1"), + fmt_format("{}::{} map values must be constexpr strings or number 1", configuration_class_name_, function_color_palette_name_)); return errtext_val != nullptr ? *errtext_val : ""; }; @@ -122,40 +114,35 @@ void RegisterKphpConfiguration::parse_palette_rule(VertexAdaptor(); - kphp_error_return(arr, fmt_format("{}::{} must be a constexpr array", - configuration_class_name_, runtime_options_name_)); - for (const auto &opt : arr->args()) { + kphp_error_return(arr, fmt_format("{}::{} must be a constexpr array", configuration_class_name_, runtime_options_name_)); + for (const auto& opt : arr->args()) { auto opt_pair = VertexUtil::get_actual_value(opt).try_as(); - kphp_error_return(opt_pair, fmt_format("{}::{} must be an associative map", - configuration_class_name_, runtime_options_name_)); - const auto *opt_key = VertexUtil::get_constexpr_string(VertexUtil::get_actual_value(opt_pair->key())); - kphp_error_return(opt_key, fmt_format("{}::{} map keys must be constexpr strings", - configuration_class_name_, runtime_options_name_)); + kphp_error_return(opt_pair, fmt_format("{}::{} must be an associative map", configuration_class_name_, runtime_options_name_)); + const auto* opt_key = VertexUtil::get_constexpr_string(VertexUtil::get_actual_value(opt_pair->key())); + kphp_error_return(opt_key, fmt_format("{}::{} map keys must be constexpr strings", configuration_class_name_, runtime_options_name_)); if (*opt_key == confdata_blacklist_key_) { register_confdata_blacklist(opt_pair->value()); } else if (*opt_key == confdata_predefined_wildcard_key_) { register_confdata_predefined_wildcard(opt_pair->value()); } else if (*opt_key == net_dc_mask_key_) { register_net_dc_mask(opt_pair->value()); - } else if (vk::any_of_equal(*opt_key, - warmup_workers_part_key_, warmup_instance_cache_elements_part_key_, warmup_timeout_sec_key_, + } else if (vk::any_of_equal(*opt_key, warmup_workers_part_key_, warmup_instance_cache_elements_part_key_, warmup_timeout_sec_key_, oom_handling_memory_ratio_key_, mysql_db_name_key_, job_workers_shared_memory_distribution_weights_)) { generic_register_simple_option(opt_pair->value(), *opt_key); } else { - kphp_error(0, fmt_format("Got unexpected option {}::{}['{}']", - configuration_class_name_, runtime_options_name_, *opt_key)); + kphp_error(0, fmt_format("Got unexpected option {}::{}['{}']", configuration_class_name_, runtime_options_name_, *opt_key)); } } } -void RegisterKphpConfiguration::handle_constant_function_exclude_namespaces(const ClassMemberConstant &c) { +void RegisterKphpConfiguration::handle_constant_function_exclude_namespaces(const ClassMemberConstant& c) { std::vector cases; - const auto &arr = VertexUtil::get_actual_value(c.value).try_as(); + const auto& arr = VertexUtil::get_actual_value(c.value).try_as(); cases.reserve(arr->args().size()); - for (const auto &opt : arr->args()) { + for (const auto& opt : arr->args()) { auto opt_str = VertexUtil::get_actual_value(opt).try_as(); cases.emplace_back(std::move(opt_str->str_val)); } @@ -164,22 +151,19 @@ void RegisterKphpConfiguration::handle_constant_function_exclude_namespaces(cons } void RegisterKphpConfiguration::generic_register_simple_option(VertexPtr value, vk::string_view opt_key) const noexcept { - const auto *opt_value = VertexUtil::get_constexpr_string(VertexUtil::get_actual_value(value)); - kphp_error_return(opt_value, fmt_format("{}::{} must be a constexpr string", - configuration_class_name_, runtime_options_name_)); + const auto* opt_value = VertexUtil::get_constexpr_string(VertexUtil::get_actual_value(value)); + kphp_error_return(opt_value, fmt_format("{}::{} must be a constexpr string", configuration_class_name_, runtime_options_name_)); G->add_kphp_runtime_opt(static_cast(opt_key)); G->add_kphp_runtime_opt(*opt_value); } void RegisterKphpConfiguration::register_confdata_blacklist(VertexPtr value) const noexcept { - const auto *opt_value = VertexUtil::get_constexpr_string(VertexUtil::get_actual_value(value)); - kphp_error_return(opt_value, fmt_format("{}[{}] must be a constexpr string", - runtime_options_name_, confdata_blacklist_key_)); + const auto* opt_value = VertexUtil::get_constexpr_string(VertexUtil::get_actual_value(value)); + kphp_error_return(opt_value, fmt_format("{}[{}] must be a constexpr string", runtime_options_name_, confdata_blacklist_key_)); re2::RE2 compiled_pattern{*opt_value, re2::RE2::CannedOptions::Quiet}; - kphp_error_return(compiled_pattern.ok(), fmt_format("Got bad regex pattern in {}::{}['{}']: {}", - configuration_class_name_, runtime_options_name_, + kphp_error_return(compiled_pattern.ok(), fmt_format("Got bad regex pattern in {}::{}['{}']: {}", configuration_class_name_, runtime_options_name_, confdata_blacklist_key_, compiled_pattern.error())); G->add_kphp_runtime_opt(static_cast(confdata_blacklist_key_)); G->add_kphp_runtime_opt(*opt_value); @@ -187,13 +171,11 @@ void RegisterKphpConfiguration::register_confdata_blacklist(VertexPtr value) con void RegisterKphpConfiguration::register_confdata_predefined_wildcard(VertexPtr value) const noexcept { auto wildcards = VertexUtil::get_actual_value(value).try_as(); - kphp_error_return(wildcards, fmt_format("{}[{}] must be a constexpr array", - runtime_options_name_, confdata_predefined_wildcard_key_)); - for (const auto &wildcard : wildcards->args()) { - const auto *wildcard_str_value = VertexUtil::get_constexpr_string(VertexUtil::get_actual_value(wildcard)); + kphp_error_return(wildcards, fmt_format("{}[{}] must be a constexpr array", runtime_options_name_, confdata_predefined_wildcard_key_)); + for (const auto& wildcard : wildcards->args()) { + const auto* wildcard_str_value = VertexUtil::get_constexpr_string(VertexUtil::get_actual_value(wildcard)); kphp_error_return(wildcard_str_value && !wildcard_str_value->empty(), - fmt_format("{}[{}][] must be non empty constexpr string", - runtime_options_name_, confdata_predefined_wildcard_key_)); + fmt_format("{}[{}][] must be non empty constexpr string", runtime_options_name_, confdata_predefined_wildcard_key_)); G->add_kphp_runtime_opt(static_cast(confdata_predefined_wildcard_key_)); G->add_kphp_runtime_opt(*wildcard_str_value); } @@ -201,13 +183,11 @@ void RegisterKphpConfiguration::register_confdata_predefined_wildcard(VertexPtr void RegisterKphpConfiguration::register_net_dc_mask(VertexPtr value) const noexcept { auto dc_masks = VertexUtil::get_actual_value(value).try_as(); - kphp_error_return(dc_masks, fmt_format("{}[{}] must be a constexpr array", - runtime_options_name_, net_dc_mask_key_)); - for (const auto &dc_mask_v : dc_masks->args()) { - const auto *index_ipv4_subnet = VertexUtil::get_constexpr_string(VertexUtil::get_actual_value(dc_mask_v)); + kphp_error_return(dc_masks, fmt_format("{}[{}] must be a constexpr array", runtime_options_name_, net_dc_mask_key_)); + for (const auto& dc_mask_v : dc_masks->args()) { + const auto* index_ipv4_subnet = VertexUtil::get_constexpr_string(VertexUtil::get_actual_value(dc_mask_v)); kphp_error_return(index_ipv4_subnet && !index_ipv4_subnet->empty(), - fmt_format("{}[{}][] must be non empty constexpr string", - runtime_options_name_, net_dc_mask_key_)); + fmt_format("{}[{}][] must be non empty constexpr string", runtime_options_name_, net_dc_mask_key_)); G->add_kphp_runtime_opt(static_cast(net_dc_mask_key_)); G->add_kphp_runtime_opt(*index_ipv4_subnet); } diff --git a/compiler/pipes/register-kphp-configuration.h b/compiler/pipes/register-kphp-configuration.h index 88483901db..aa7070d9ec 100644 --- a/compiler/pipes/register-kphp-configuration.h +++ b/compiler/pipes/register-kphp-configuration.h @@ -4,10 +4,10 @@ #pragma once -#include "compiler/pipes/sync.h" -#include "compiler/data/data_ptr.h" #include "compiler/data/class-members.h" +#include "compiler/data/data_ptr.h" #include "compiler/function-colors.h" +#include "compiler/pipes/sync.h" class RegisterKphpConfiguration final : public SyncPipeF { using need_profiler = std::false_type; @@ -15,19 +15,19 @@ class RegisterKphpConfiguration final : public SyncPipeF { void handle_KphpConfiguration_class(ClassPtr klass); - void handle_constant_runtime_options(const ClassMemberConstant &c); + void handle_constant_runtime_options(const ClassMemberConstant& c); void generic_register_simple_option(VertexPtr value, vk::string_view opt_key) const noexcept; void register_confdata_blacklist(VertexPtr value) const noexcept; void register_confdata_predefined_wildcard(VertexPtr value) const noexcept; void register_net_dc_mask(VertexPtr value) const noexcept; - void handle_constant_function_palette(const ClassMemberConstant &c); - void parse_palette(VertexPtr const_val, function_palette::Palette &palette); - void parse_palette_ruleset(VertexAdaptor arr, function_palette::Palette &palette); - void parse_palette_rule(VertexAdaptor pair, function_palette::Palette &palette, function_palette::PaletteRuleset &add_to); + void handle_constant_function_palette(const ClassMemberConstant& c); + void parse_palette(VertexPtr const_val, function_palette::Palette& palette); + void parse_palette_ruleset(VertexAdaptor arr, function_palette::Palette& palette); + void parse_palette_rule(VertexAdaptor pair, function_palette::Palette& palette, function_palette::PaletteRuleset& add_to); - void handle_constant_function_exclude_namespaces(const ClassMemberConstant &c); + void handle_constant_function_exclude_namespaces(const ClassMemberConstant& c); const vk::string_view configuration_class_name_{"KphpConfiguration"}; const vk::string_view runtime_options_name_{"DEFAULT_RUNTIME_OPTIONS"}; @@ -48,6 +48,6 @@ class RegisterKphpConfiguration final : public SyncPipeF { const vk::string_view job_workers_shared_memory_distribution_weights_{"--job-workers-shared-memory-distribution-weights"}; public: - void execute(FunctionPtr function, DataStream &unused_os) final; - void on_finish(DataStream &os) override; + void execute(FunctionPtr function, DataStream& unused_os) final; + void on_finish(DataStream& os) override; }; diff --git a/compiler/pipes/register-variables.cpp b/compiler/pipes/register-variables.cpp index 30b8f80290..445503be7f 100644 --- a/compiler/pipes/register-variables.cpp +++ b/compiler/pipes/register-variables.cpp @@ -11,7 +11,7 @@ #include "compiler/name-gen.h" #include "compiler/utils/string-utils.h" -VarPtr RegisterVariablesPass::create_global_var(const std::string &name) { +VarPtr RegisterVariablesPass::create_global_var(const std::string& name) { VarPtr var = G->get_global_var(name, VertexPtr()); auto it = registred_vars.insert(make_pair(name, var)); if (it.second == false) { @@ -24,19 +24,19 @@ VarPtr RegisterVariablesPass::create_global_var(const std::string &name) { return var; } -VarPtr RegisterVariablesPass::create_local_var(const std::string &name, VarData::Type type, bool create_flag) { +VarPtr RegisterVariablesPass::create_local_var(const std::string& name, VarData::Type type, bool create_flag) { auto it = registred_vars.find(name); if (it != registred_vars.end()) { - kphp_error (!create_flag, fmt_format("Redeclaration of local variable: {}", name)); + kphp_error(!create_flag, fmt_format("Redeclaration of local variable: {}", name)); return it->second; } VarPtr var = G->create_local_var(current_function, name, type); - kphp_error (registred_vars.insert(make_pair(name, var)).second, fmt_format("Redeclaration of local variable: {}", name)); + kphp_error(registred_vars.insert(make_pair(name, var)).second, fmt_format("Redeclaration of local variable: {}", name)); return var; } -VarPtr RegisterVariablesPass::get_global_var(const std::string &name) { +VarPtr RegisterVariablesPass::get_global_var(const std::string& name) { auto it = registred_vars.find(name); if (it != registred_vars.end()) { return it->second; @@ -44,7 +44,7 @@ VarPtr RegisterVariablesPass::get_global_var(const std::string &name) { return create_global_var(name); } -VarPtr RegisterVariablesPass::get_local_var(const std::string &name, VarData::Type type) { +VarPtr RegisterVariablesPass::get_local_var(const std::string& name, VarData::Type type) { return create_local_var(name, type, false); } @@ -59,8 +59,7 @@ void RegisterVariablesPass::register_global_var(VertexAdaptor var_vertex } bool RegisterVariablesPass::is_const(VertexPtr v) { - return v->const_type == cnst_const_val || - (v->type() == op_var && v.as()->var_id->is_constant()); + return v->const_type == cnst_const_val || (v->type() == op_var && v.as()->var_id->is_constant()); } bool RegisterVariablesPass::is_global_var(VertexPtr v) { @@ -88,7 +87,7 @@ void RegisterVariablesPass::register_param_var(VertexAdaptor var_vertex, VarPtr var = create_local_var(name, VarData::var_param_t, true); var->is_reference = var_vertex->ref_flag; var->marked_as_const = var_vertex->is_const; - kphp_assert (var); + kphp_assert(var); if (default_value) { kphp_error_return(is_const(default_value) || current_function->is_extern(), fmt_format("Default value of [{}] is not constant", name)); var->init_val = default_value; @@ -101,9 +100,7 @@ void RegisterVariablesPass::register_var(VertexAdaptor var_vertex) { ClassPtr requested_class; std::string name = var_vertex->str_val; size_t pos$$ = name.find("$$"); - if (pos$$ != std::string::npos || - (vk::none_of_equal(var_vertex->extra_type, op_ex_var_superlocal, op_ex_var_superlocal_inplace) && - global_function_flag) || + if (pos$$ != std::string::npos || (vk::none_of_equal(var_vertex->extra_type, op_ex_var_superlocal, op_ex_var_superlocal_inplace) && global_function_flag) || var_vertex->extra_type == op_ex_var_superglobal) { if (pos$$ != std::string::npos) { std::string class_name = name.substr(0, pos$$); @@ -115,7 +112,7 @@ void RegisterVariablesPass::register_var(VertexAdaptor var_vertex) { klass = klass->parent_class; } kphp_error_return(klass, fmt_format("static field not found: {}", name)); - const auto *field = klass->members.get_static_field(var_name); + const auto* field = klass->members.get_static_field(var_name); kphp_error_return(field, fmt_format("field {} is not static in class {}", var_name, requested_class->name)); kphp_error_return(klass == requested_class || !field->modifiers.is_private(), fmt_format("Can't access private static field using derived class: {}", name)); @@ -123,9 +120,7 @@ void RegisterVariablesPass::register_var(VertexAdaptor var_vertex) { } var = get_global_var(name); } else { - VarData::Type var_type = var_vertex->extra_type == op_ex_var_superlocal_inplace - ? VarData::var_local_inplace_t - : VarData::var_local_t; + VarData::Type var_type = var_vertex->extra_type == op_ex_var_superlocal_inplace ? VarData::var_local_inplace_t : VarData::var_local_t; var = get_local_var(name, var_type); } var_vertex->var_id = var; @@ -141,11 +136,7 @@ void RegisterVariablesPass::register_var(VertexAdaptor var_vertex) { void RegisterVariablesPass::visit_global_vertex(VertexAdaptor global) { for (auto var : global->args()) { - kphp_error_act ( - var->type() == op_var, - "unexpected expression in 'global'", - continue - ); + kphp_error_act(var->type() == op_var, "unexpected expression in 'global'", continue); register_global_var(var.as()); if (current_function->modulite) { modulite_check_when_global_keyword(current_function, var.as()->str_val); @@ -160,15 +151,11 @@ void RegisterVariablesPass::visit_static_vertex(VertexAdaptor stat) { auto var = node.try_as(); if (!var) { if (auto set_expr = node.try_as()) { - kphp_error_act ( - set_expr->lhs()->type() == op_var, - "unexpected expression in 'static'", - continue - ); + kphp_error_act(set_expr->lhs()->type() == op_var, "unexpected expression in 'static'", continue); var = set_expr->lhs().as(); default_value = set_expr->rhs(); } else { - kphp_error_act (0, "unexpected expression in 'static'", continue); + kphp_error_act(0, "unexpected expression in 'static'", continue); } } @@ -179,15 +166,14 @@ void RegisterVariablesPass::visit_static_vertex(VertexAdaptor stat) { void RegisterVariablesPass::visit_var(VertexAdaptor var) { if (var->var_id) { // autogenerated via CREATE_VERTEX op_var types that have one VarData per multiple vertices - kphp_assert (var->var_id->is_constant() || vk::any_of_equal(var->var_id->type(), VarData::var_local_inplace_t, VarData::var_local_t)); + kphp_assert(var->var_id->is_constant() || vk::any_of_equal(var->var_id->type(), VarData::var_local_inplace_t, VarData::var_local_t)); return; } register_var(var); } - VertexPtr RegisterVariablesPass::on_enter_vertex(VertexPtr root) { - kphp_assert (root); + kphp_assert(root); if (root->type() == op_global) { visit_global_vertex(root.as()); return VertexAdaptor::create(); @@ -204,7 +190,8 @@ VertexPtr RegisterVariablesPass::on_enter_vertex(VertexPtr root) { VertexPtr RegisterVariablesPass::on_exit_vertex(VertexPtr root) { if (auto foreach = root.try_as()) { if (foreach->x()->ref_flag) { - foreach->x()->var_id->is_foreach_reference = true; + foreach + ->x()->var_id->is_foreach_reference = true; } } return root; @@ -224,7 +211,7 @@ void RegisterVariablesPass::visit_func_param_list(VertexAdaptor phpdoc_var) { - const std::string &var_name = phpdoc_var->var()->str_val; + const std::string& var_name = phpdoc_var->var()->str_val; VarPtr var_in_f = current_function->find_var_by_name(var_name); kphp_error(var_in_f, fmt_format("Unknown var ${} in phpdoc", var_name)); diff --git a/compiler/pipes/register-variables.h b/compiler/pipes/register-variables.h index 1aa033185c..c857ae8f1b 100644 --- a/compiler/pipes/register-variables.h +++ b/compiler/pipes/register-variables.h @@ -24,10 +24,10 @@ class RegisterVariablesPass final : public FunctionPassBase { bool global_function_flag{false}; int in_param_list{0}; - VarPtr create_global_var(const std::string &name); - VarPtr create_local_var(const std::string &name, VarData::Type type, bool create_flag); - VarPtr get_global_var(const std::string &name); - VarPtr get_local_var(const std::string &name, VarData::Type type = VarData::var_local_t); + VarPtr create_global_var(const std::string& name); + VarPtr create_local_var(const std::string& name, VarData::Type type, bool create_flag); + VarPtr get_global_var(const std::string& name); + VarPtr get_local_var(const std::string& name, VarData::Type type = VarData::var_local_t); void register_global_var(VertexAdaptor var_vertex); bool is_const(VertexPtr v); bool is_global_var(VertexPtr v); @@ -41,9 +41,7 @@ class RegisterVariablesPass final : public FunctionPassBase { void visit_func_param_list(VertexAdaptor list); - public: - std::string get_description() override { return "Register variables"; } @@ -58,5 +56,4 @@ class RegisterVariablesPass final : public FunctionPassBase { VertexPtr on_exit_vertex(VertexPtr root) override; bool user_recursion(VertexPtr v) override; - }; diff --git a/compiler/pipes/remove-empty-function-calls.cpp b/compiler/pipes/remove-empty-function-calls.cpp index 92a0ad2007..e4ce4583ba 100644 --- a/compiler/pipes/remove-empty-function-calls.cpp +++ b/compiler/pipes/remove-empty-function-calls.cpp @@ -4,13 +4,13 @@ #include "compiler/pipes/remove-empty-function-calls.h" -#include "compiler/vertex.h" -#include "compiler/data/src-file.h" #include "compiler/compiler-core.h" +#include "compiler/data/src-file.h" +#include "compiler/vertex.h" static bool is_empty_func_call(VertexPtr v) { return v->type() == op_func_call && v.as()->func_id->body_seq == FunctionData::body_value::empty; -}; +} VertexPtr RemoveEmptyFunctionCallsPass::on_enter_vertex(VertexPtr v) { if (auto return_v = v.try_as()) { @@ -27,7 +27,7 @@ VertexPtr RemoveEmptyFunctionCallsPass::on_exit_vertex(VertexPtr v) { } if (v->type() == op_seq) { - auto is_empty = [](VertexPtr v) { return v->type() == op_null || v->type() == op_empty;}; + auto is_empty = [](VertexPtr v) { return v->type() == op_null || v->type() == op_empty; }; if (std::any_of(v->begin(), v->end(), is_empty)) { std::vector next; std::remove_copy_if(v->begin(), v->end(), std::back_inserter(next), is_empty); @@ -46,7 +46,8 @@ VertexPtr RemoveEmptyFunctionCallsPass::on_exit_vertex(VertexPtr v) { // get rid of $called - global variables for empty source files; // namely, detect 'v$src_fooxxx$called = true' assign in such files and remove it, // this allows to avoid further call of register_var() with such global variable - if (!G->is_output_mode_lib() && !G->is_output_mode_k2_lib() && current_function->is_main_function() && current_function->body_seq == FunctionData::body_value::empty) { + if (!G->is_output_mode_lib() && !G->is_output_mode_k2_lib() && current_function->is_main_function() && + current_function->body_seq == FunctionData::body_value::empty) { auto set = v.as(); auto lhs = set->lhs(); auto rhs = set->rhs(); diff --git a/compiler/pipes/remove-empty-function-calls.h b/compiler/pipes/remove-empty-function-calls.h index 9b58c59b4b..bf32f5bcb4 100644 --- a/compiler/pipes/remove-empty-function-calls.h +++ b/compiler/pipes/remove-empty-function-calls.h @@ -8,7 +8,9 @@ class RemoveEmptyFunctionCallsPass final : public FunctionPassBase { public: - std::string get_description() override { return "Filter empty functions"; } + std::string get_description() override { + return "Filter empty functions"; + } VertexPtr on_enter_vertex(VertexPtr v) override; VertexPtr on_exit_vertex(VertexPtr v) override; diff --git a/compiler/pipes/resolve-self-static-parent.cpp b/compiler/pipes/resolve-self-static-parent.cpp index 3bee5e90b1..0edaf3133d 100644 --- a/compiler/pipes/resolve-self-static-parent.cpp +++ b/compiler/pipes/resolve-self-static-parent.cpp @@ -9,25 +9,22 @@ #include "compiler/compiler-core.h" #include "compiler/data/class-data.h" #include "compiler/data/src-file.h" -#include "compiler/vertex-util.h" #include "compiler/gentree.h" #include "compiler/name-gen.h" #include "compiler/phpdoc.h" #include "compiler/type-hint.h" - +#include "compiler/vertex-util.h" void ResolveSelfStaticParentPass::on_start() { // replace self::, parent:: and accesses to other classes like Classes\A::CONST if (current_function->type == FunctionData::func_class_holder) { - current_function->class_id->members.for_each([&](ClassMemberConstant &c) { - run_function_pass(c.value, this); - }); - current_function->class_id->members.for_each([&](ClassMemberStaticField &f) { + current_function->class_id->members.for_each([&](ClassMemberConstant& c) { run_function_pass(c.value, this); }); + current_function->class_id->members.for_each([&](ClassMemberStaticField& f) { if (f.var->init_val) { run_function_pass(f.var->init_val, this); } }); - current_function->class_id->members.for_each([&](ClassMemberInstanceField &f) { + current_function->class_id->members.for_each([&](ClassMemberInstanceField& f) { if (f.var->init_val) { run_function_pass(f.var->init_val, this); } @@ -43,9 +40,9 @@ VertexPtr ResolveSelfStaticParentPass::on_enter_vertex(VertexPtr v) { return v; } - const std::string &prefix_name = as_func_call->str_val.substr(0, pos); - const std::string &local_name = as_func_call->str_val.substr(pos + 2); - const std::string &class_name = resolve_uses(current_function, prefix_name); + const std::string& prefix_name = as_func_call->str_val.substr(0, pos); + const std::string& local_name = as_func_call->str_val.substr(pos + 2); + const std::string& class_name = resolve_uses(current_function, prefix_name); ClassPtr ref_class = G->get_class(class_name); check_access_to_class_from_this_file(prefix_name, ref_class); @@ -53,7 +50,7 @@ VertexPtr ResolveSelfStaticParentPass::on_enter_vertex(VertexPtr v) { // but don't replace SomeOtherClass::instance_method(), it should give an error "non-static method is called statically" bool inside_instance_method = current_function->get_this_or_topmost_if_lambda()->modifiers.is_instance(); if (ref_class && inside_instance_method && ref_class->is_parent_of(current_function->get_this_or_topmost_if_lambda()->class_id)) { - if (const auto *found_method = ref_class->get_instance_method(local_name)) { + if (const auto* found_method = ref_class->get_instance_method(local_name)) { if (!found_method->function->modifiers.is_abstract()) { return replace_func_call_with_colons_with_this_call(found_method->function, ref_class, as_func_call); } @@ -72,9 +69,9 @@ VertexPtr ResolveSelfStaticParentPass::on_enter_vertex(VertexPtr v) { return v; } - const std::string &prefix_name = as_var->str_val.substr(0, pos); - const std::string &var_name = as_var->str_val.substr(pos + 2); - const std::string &class_name = resolve_uses(current_function, prefix_name); + const std::string& prefix_name = as_var->str_val.substr(0, pos); + const std::string& var_name = as_var->str_val.substr(pos + 2); + const std::string& class_name = resolve_uses(current_function, prefix_name); ClassPtr ref_class = G->get_class(class_name); check_access_to_class_from_this_file(prefix_name, ref_class); @@ -87,9 +84,9 @@ VertexPtr ResolveSelfStaticParentPass::on_enter_vertex(VertexPtr v) { return v; } - const std::string &prefix_name = as_func_name->str_val.substr(0, pos); - const std::string &const_name = as_func_name->str_val.substr(pos + 2); - const std::string &class_name = resolve_uses(current_function, prefix_name); + const std::string& prefix_name = as_func_name->str_val.substr(0, pos); + const std::string& const_name = as_func_name->str_val.substr(pos + 2); + const std::string& class_name = resolve_uses(current_function, prefix_name); ClassPtr ref_class = G->get_class(class_name); check_access_to_class_from_this_file(prefix_name, ref_class); @@ -97,21 +94,21 @@ VertexPtr ResolveSelfStaticParentPass::on_enter_vertex(VertexPtr v) { } else if (auto as_alloc = v.try_as()) { // replace 'new A' to the fully resolved name 'new Classes\A' (set allocated_class) - const std::string &prefix_name = as_alloc->allocated_class_name; - const std::string &class_name = resolve_uses(current_function, prefix_name); + const std::string& prefix_name = as_alloc->allocated_class_name; + const std::string& class_name = resolve_uses(current_function, prefix_name); ClassPtr ref_class = G->get_class(class_name); check_access_to_class_from_this_file(prefix_name, ref_class); - as_alloc->allocated_class = ref_class; // if not exists, checked later, on func_call bind + as_alloc->allocated_class = ref_class; // if not exists, checked later, on func_call bind } else if (auto as_instanceof = v.try_as()) { // ... instanceof XXX, the right was replaced by XXX::class - const std::string &instanceof_class = VertexUtil::get_actual_value(as_instanceof->rhs())->get_string(); + const std::string& instanceof_class = VertexUtil::get_actual_value(as_instanceof->rhs())->get_string(); auto pos = instanceof_class.find("::"); kphp_assert(pos != std::string::npos); - const std::string &prefix_name = instanceof_class.substr(0, pos); - const std::string &class_name = resolve_uses(current_function, prefix_name); + const std::string& prefix_name = instanceof_class.substr(0, pos); + const std::string& class_name = resolve_uses(current_function, prefix_name); ClassPtr ref_class = G->get_class(class_name); check_access_to_class_from_this_file(prefix_name, ref_class); @@ -122,18 +119,18 @@ VertexPtr ResolveSelfStaticParentPass::on_enter_vertex(VertexPtr v) { return v; } -void ResolveSelfStaticParentPass::check_access_to_class_from_this_file(const std::string &prefix_name, ClassPtr ref_class) { +void ResolveSelfStaticParentPass::check_access_to_class_from_this_file(const std::string& prefix_name, ClassPtr ref_class) { bool inside_instance_method = current_function->get_this_or_topmost_if_lambda()->modifiers.is_instance(); - + if (inside_instance_method && prefix_name == "static") { - kphp_error(ref_class && ref_class->derived_classes.empty(), - "Using 'static' is prohibited from instance methods when a class has derived classes.\nEither use 'self', or modify your code to use '$this->' func calls."); + kphp_error(ref_class && ref_class->derived_classes.empty(), "Using 'static' is prohibited from instance methods when a class has derived classes.\nEither " + "use 'self', or modify your code to use '$this->' func calls."); } if (ref_class && !ref_class->can_be_php_autoloaded && !ref_class->file_id->is_loaded_by_psr0) { // todo temporary allow direct using tl _result classes for vkcom; roll back after switching to long ID - kphp_error(ref_class->file_id == current_function->file_id || current_function->is_virtual_method || (ref_class->phpdoc && ref_class->phpdoc->has_tag(PhpDocType::kphp_tl_class)), - fmt_format("Class {} can be accessed only from file {}, as it is not autoloadable", - ref_class->name, ref_class->file_id->relative_file_name)); + kphp_error(ref_class->file_id == current_function->file_id || current_function->is_virtual_method || + (ref_class->phpdoc && ref_class->phpdoc->has_tag(PhpDocType::kphp_tl_class)), + fmt_format("Class {} can be accessed only from file {}, as it is not autoloadable", ref_class->name, ref_class->file_id->relative_file_name)); } if (ref_class && ref_class->is_trait()) { kphp_error(current_function->class_id && current_function->class_id->is_trait(), @@ -143,18 +140,18 @@ void ResolveSelfStaticParentPass::check_access_to_class_from_this_file(const std // PHP allows to call self::instance_method(), we should replace it with $this->instance_method() // (parent::fun() follows the same logic, ref_class refs to a parent class, considering that fun() is virtual in parent) -VertexPtr ResolveSelfStaticParentPass::replace_func_call_with_colons_with_this_call(FunctionPtr called_method, ClassPtr ref_class, VertexAdaptor call_colons) { - VertexPtr this_vertex = current_function->is_lambda() - ? GenTree::auto_capture_this_in_lambda(current_function) - : ClassData::gen_vertex_this(call_colons->location); - +VertexPtr ResolveSelfStaticParentPass::replace_func_call_with_colons_with_this_call(FunctionPtr called_method, ClassPtr ref_class, + VertexAdaptor call_colons) { + VertexPtr this_vertex = + current_function->is_lambda() ? GenTree::auto_capture_this_in_lambda(current_function) : ClassData::gen_vertex_this(call_colons->location); + auto call_inst = VertexAdaptor::create(this_vertex, call_colons->args()).set_location(call_colons); call_inst->extra_type = op_ex_func_call_arrow; call_inst->str_val = std::string{called_method->local_name()}; call_inst->func_id = called_method; if (called_method->is_virtual_method) { - const auto *self_method = ref_class->get_instance_method(called_method->get_name_of_self_method()); + const auto* self_method = ref_class->get_instance_method(called_method->get_name_of_self_method()); kphp_assert(self_method); call_inst->str_val = std::string{self_method->local_name()}; call_inst->func_id = self_method->function; diff --git a/compiler/pipes/resolve-self-static-parent.h b/compiler/pipes/resolve-self-static-parent.h index 03441939bd..1ebda2523d 100644 --- a/compiler/pipes/resolve-self-static-parent.h +++ b/compiler/pipes/resolve-self-static-parent.h @@ -8,7 +8,7 @@ class ResolveSelfStaticParentPass final : public FunctionPassBase { private: - void check_access_to_class_from_this_file(const std::string &prefix_name, ClassPtr ref_class); + void check_access_to_class_from_this_file(const std::string& prefix_name, ClassPtr ref_class); VertexPtr replace_func_call_with_colons_with_this_call(FunctionPtr called_method, ClassPtr ref_class, VertexAdaptor call_colons); public: diff --git a/compiler/pipes/sort-and-inherit-classes.cpp b/compiler/pipes/sort-and-inherit-classes.cpp index 9338ed8d38..8ac7afca66 100644 --- a/compiler/pipes/sort-and-inherit-classes.cpp +++ b/compiler/pipes/sort-and-inherit-classes.cpp @@ -12,32 +12,31 @@ #include "compiler/data/class-data.h" #include "compiler/data/src-file.h" #include "compiler/name-gen.h" +#include "compiler/pipes/clone-nested-lambdas.h" #include "compiler/stage.h" #include "compiler/threading/profiler.h" -#include "compiler/pipes/clone-nested-lambdas.h" #include "compiler/utils/string-utils.h" - TSHashTable SortAndInheritClassesF::ht; namespace { -void mark_virtual_and_overridden_methods(ClassPtr cur_class, DataStream &os) { +void mark_virtual_and_overridden_methods(ClassPtr cur_class, DataStream& os) { static std::unordered_set visited_classes; if (vk::contains(visited_classes, cur_class)) { return; } visited_classes.insert(cur_class); - auto find_virtual_overridden = [&](ClassMemberInstanceMethod &method) { + auto find_virtual_overridden = [&](ClassMemberInstanceMethod& method) { if (!method.function || method.function->is_constructor() || method.function->modifiers.is_private()) { return; } - for (const auto &ancestor : cur_class->get_all_ancestors()) { + for (const auto& ancestor : cur_class->get_all_ancestors()) { if (ancestor == cur_class) { continue; } - if (auto *parent_member = ancestor->members.get_instance_method(method.local_name())) { + if (auto* parent_member = ancestor->members.get_instance_method(method.local_name())) { auto parent_function = parent_member->function; kphp_error(parent_function->modifiers.is_abstract() || !parent_function->modifiers.is_final(), @@ -64,7 +63,7 @@ void mark_virtual_and_overridden_methods(ClassPtr cur_class, DataStream &function_stream) { +bool clone_method(FunctionPtr from, ClassPtr to_class, DataStream& function_stream) { if (from->modifiers.is_instance() && to_class->members.has_instance_method(from->local_name())) { return false; } else if (from->modifiers.is_static() && to_class->members.has_static_method(from->local_name())) { @@ -82,16 +81,15 @@ bool clone_method(FunctionPtr from, ClassPtr to_class, DataStream & G->register_and_require_function(cloned_fun, function_stream, true); return true; -}; +} } // namespace - // Returns nullptr if all class dependents are already processed. // Otherwise it returns a pointer to a dependent class/interface that needs to be processed. auto SortAndInheritClassesF::get_not_ready_dependency(ClassPtr klass) -> decltype(ht)::HTNode* { - for (const auto &dep : klass->get_str_dependents()) { - auto *node = ht.at(vk::std_hash(dep.class_name)); + for (const auto& dep : klass->get_str_dependents()) { + auto* node = ht.at(vk::std_hash(dep.class_name)); kphp_assert(node); if (!node->data.done) { return node; @@ -103,7 +101,7 @@ auto SortAndInheritClassesF::get_not_ready_dependency(ClassPtr klass) -> decltyp // Generate a childclassname$$localname function that looks like this: // function childclassname$$localname($args) { return baseclassname$$localname$$childclassname(...$args); } -VertexAdaptor SortAndInheritClassesF::generate_function_with_parent_call(ClassPtr child_class, const ClassMemberStaticMethod &parent_method) { +VertexAdaptor SortAndInheritClassesF::generate_function_with_parent_call(ClassPtr child_class, const ClassMemberStaticMethod& parent_method) { auto parent_f = parent_method.function; auto parent_function_name = parent_f->name + "$$" + replace_backslashes(child_class->name); @@ -115,7 +113,7 @@ VertexAdaptor SortAndInheritClassesF::generate_function_with_parent new_func_call = VertexAdaptor::create(parent_params); } else { kphp_assert(!parent_params.empty()); - auto &last_param = parent_params.back(); + auto& last_param = parent_params.back(); auto unpacked_last_param = VertexAdaptor::create(last_param).set_location(last_param); parent_params.pop_back(); @@ -133,20 +131,20 @@ VertexAdaptor SortAndInheritClassesF::generate_function_with_parent // PHP has late static binding, that's why inheriting a static method is not trivial // a new function is created with context_class (to resolve 'static') -void SortAndInheritClassesF::inherit_static_method_from_parent(ClassPtr child_class, const ClassMemberStaticMethod &parent_method, DataStream &function_stream) { +void SortAndInheritClassesF::inherit_static_method_from_parent(ClassPtr child_class, const ClassMemberStaticMethod& parent_method, + DataStream& function_stream) { auto local_name = parent_method.local_name(); auto parent_f = parent_method.function; auto parent_class = parent_f->class_id; - // A::f() -> B -> C; with A->B becomes A::f$$B - // but with B->C it should be A::f$$C and not B::f$$C - // so we don't assume B::f$$C as required + // A::f() -> B -> C; with A->B becomes A::f$$B + // but with B->C it should be A::f$$C and not B::f$$C + // so we don't assume B::f$$C as required if (parent_f->is_auto_inherited || parent_f->context_class != parent_class) { return; } - if (const auto *child_method = child_class->members.get_static_method(local_name)) { - kphp_error(!parent_f->modifiers.is_final(), - fmt_format("Can not override method marked as 'final': {}", parent_f->as_human_readable())); + if (const auto* child_method = child_class->members.get_static_method(local_name)) { + kphp_error(!parent_f->modifiers.is_final(), fmt_format("Can not override method marked as 'final': {}", parent_f->as_human_readable())); kphp_error(!(parent_method.function->modifiers.is_static() && parent_method.function->modifiers.is_private()), fmt_format("Can not override private method: {}", parent_f->as_human_readable())); kphp_error(parent_method.function->modifiers.access_modifier() == child_method->function->modifiers.access_modifier(), @@ -180,8 +178,8 @@ void SortAndInheritClassesF::inherit_static_method_from_parent(ClassPtr child_cl // when Base::f and Child::f (non-static) both exist, we just do some checks // (Base could be a class or an interface) -void SortAndInheritClassesF::inherit_instance_method_from_parent(ClassPtr child_class, const ClassMemberInstanceMethod &parent_method) { - const auto *child_method = child_class->members.get_instance_method(parent_method.local_name()); +void SortAndInheritClassesF::inherit_instance_method_from_parent(ClassPtr child_class, const ClassMemberInstanceMethod& parent_method) { + const auto* child_method = child_class->members.get_instance_method(parent_method.local_name()); if (!child_method) { return; } @@ -195,79 +193,63 @@ void SortAndInheritClassesF::inherit_instance_method_from_parent(ClassPtr child_ kphp_error(!(parent_f->is_generic() && child_f->is_generic() && !parent_f->modifiers.is_abstract()), fmt_format("Overriding non-abstract generic methods is forbidden: {}", child_f->as_human_readable())); kphp_error(!(parent_f->is_generic() && !child_f->is_generic()), - fmt_format("{} is a generic method, but child {} is not.\n@kphp-generic is not inherited, add it manually to child methods", parent_f->as_human_readable(), child_f->as_human_readable())); + fmt_format("{} is a generic method, but child {} is not.\n@kphp-generic is not inherited, add it manually to child methods", + parent_f->as_human_readable(), child_f->as_human_readable())); kphp_error(!(child_f->is_generic() && !parent_f->is_generic()), fmt_format("{} is a generic method, but parent {} is not", child_f->as_human_readable(), parent_f->as_human_readable())); } - -void SortAndInheritClassesF::inherit_child_class_from_parent(ClassPtr child_class, ClassPtr parent_class, DataStream &function_stream) { +void SortAndInheritClassesF::inherit_child_class_from_parent(ClassPtr child_class, ClassPtr parent_class, DataStream& function_stream) { stage::set_file(child_class->file_id); stage::set_function(FunctionPtr{}); if (parent_class->is_ffi_cdata() || parent_class->name == "FFI\\Scope") { - kphp_error_return(child_class->is_builtin() || child_class->is_ffi_scope(), - "FFI classes should not be extended"); + kphp_error_return(child_class->is_builtin() || child_class->is_ffi_scope(), "FFI classes should not be extended"); } else { - kphp_error_return(parent_class->is_class() && child_class->is_class(), - fmt_format("Error extends {} and {}", child_class->name, parent_class->name)); - + kphp_error_return(parent_class->is_class() && child_class->is_class(), fmt_format("Error extends {} and {}", child_class->name, parent_class->name)); } - kphp_error_return(!parent_class->modifiers.is_final(), - fmt_format("You cannot extends final class: {}", child_class->name)); + kphp_error_return(!parent_class->modifiers.is_final(), fmt_format("You cannot extends final class: {}", child_class->name)); child_class->parent_class = parent_class; // A::f -> B -> C -> D; for D we require C::f$$D, B::f$$D, A::f$$D for (; parent_class; parent_class = parent_class->parent_class) { - parent_class->members.for_each([&](const ClassMemberStaticMethod &m) { - inherit_static_method_from_parent(child_class, m, function_stream); - }); - parent_class->members.for_each([&](const ClassMemberInstanceMethod &m) { - inherit_instance_method_from_parent(child_class, m); - }); - parent_class->members.for_each([&](const ClassMemberStaticField &f) { - if (const auto *field = child_class->members.get_static_field(f.local_name())) { - kphp_error(!f.modifiers.is_private(), - fmt_format("Can't redeclare private static field {} in class {}\n", f.local_name(), child_class->name)); - - kphp_error(f.modifiers == field->modifiers, - fmt_format("Can't change access type for static field {} ({}) in class {} ({})\n", - f.local_name(), f.modifiers.to_string(), - child_class->name, field->modifiers.to_string()) - ); + parent_class->members.for_each([&](const ClassMemberStaticMethod& m) { inherit_static_method_from_parent(child_class, m, function_stream); }); + parent_class->members.for_each([&](const ClassMemberInstanceMethod& m) { inherit_instance_method_from_parent(child_class, m); }); + parent_class->members.for_each([&](const ClassMemberStaticField& f) { + if (const auto* field = child_class->members.get_static_field(f.local_name())) { + kphp_error(!f.modifiers.is_private(), fmt_format("Can't redeclare private static field {} in class {}\n", f.local_name(), child_class->name)); + + kphp_error(f.modifiers == field->modifiers, fmt_format("Can't change access type for static field {} ({}) in class {} ({})\n", f.local_name(), + f.modifiers.to_string(), child_class->name, field->modifiers.to_string())); } }); - parent_class->members.for_each([&](const ClassMemberConstant &c) { - if (const auto *child_const = child_class->get_constant(c.local_name())) { - kphp_error(child_const->access == c.access, - fmt_format("Can't change access type for constant {} in class {}", c.local_name(), child_class->name)); + parent_class->members.for_each([&](const ClassMemberConstant& c) { + if (const auto* child_const = child_class->get_constant(c.local_name())) { + kphp_error(child_const->access == c.access, fmt_format("Can't change access type for constant {} in class {}", c.local_name(), child_class->name)); } }); } if (child_class->parent_class) { - AutoLocker locker(&(*child_class->parent_class)); + AutoLocker locker(&(*child_class->parent_class)); child_class->parent_class->derived_classes.emplace_back(child_class); } } void SortAndInheritClassesF::inherit_class_from_interface(ClassPtr child_class, InterfacePtr interface_class) { - kphp_error(interface_class->is_interface(), - fmt_format("{} `implements` a non-interface {}", child_class->name, interface_class->name)); + kphp_error(interface_class->is_interface(), fmt_format("{} `implements` a non-interface {}", child_class->name, interface_class->name)); child_class->implements.emplace_back(interface_class); - interface_class->members.for_each([&](const ClassMemberInstanceMethod &m) { - inherit_instance_method_from_parent(child_class, m); - }); + interface_class->members.for_each([&](const ClassMemberInstanceMethod& m) { inherit_instance_method_from_parent(child_class, m); }); - AutoLocker locker(&(*interface_class)); + AutoLocker locker(&(*interface_class)); interface_class->derived_classes.emplace_back(child_class); } -void SortAndInheritClassesF::clone_members_from_traits(std::vector &&traits, ClassPtr ready_class, DataStream &function_stream) { +void SortAndInheritClassesF::clone_members_from_traits(std::vector&& traits, ClassPtr ready_class, DataStream& function_stream) { for (size_t i = 0; i < traits.size(); ++i) { auto check_other_traits_doesnt_contain_method_and_clone = [&](FunctionPtr method) { if (!clone_method(method, ready_class, function_stream)) { @@ -281,20 +263,20 @@ void SortAndInheritClassesF::clone_members_from_traits(std::vector &&t } }; - traits[i]->members.for_each([&](ClassMemberInstanceMethod &m) { check_other_traits_doesnt_contain_method_and_clone(m.function); }); - traits[i]->members.for_each([&](ClassMemberStaticMethod &m) { check_other_traits_doesnt_contain_method_and_clone(m.function); }); + traits[i]->members.for_each([&](ClassMemberInstanceMethod& m) { check_other_traits_doesnt_contain_method_and_clone(m.function); }); + traits[i]->members.for_each([&](ClassMemberStaticMethod& m) { check_other_traits_doesnt_contain_method_and_clone(m.function); }); - traits[i]->members.for_each([&](const ClassMemberInstanceField &f) { + traits[i]->members.for_each([&](const ClassMemberInstanceField& f) { ready_class->members.add_instance_field(f.root.clone(), f.var->init_val.clone(), f.modifiers, f.phpdoc, f.type_hint); }); - traits[i]->members.for_each([&](const ClassMemberStaticField &f) { + traits[i]->members.for_each([&](const ClassMemberStaticField& f) { ready_class->members.add_static_field(f.root.clone(), f.var->init_val.clone(), f.modifiers, f.phpdoc, f.type_hint); }); } if (ready_class->is_class()) { - ready_class->members.for_each([&](ClassMemberInstanceMethod &m) { + ready_class->members.for_each([&](ClassMemberInstanceMethod& m) { if (m.function->modifiers.is_abstract()) { kphp_error(ready_class->modifiers.is_abstract(), fmt_format("class {} must be declared abstract, as it has an abstract method {}", ready_class->as_human_readable(), m.local_name())); @@ -304,46 +286,46 @@ void SortAndInheritClassesF::clone_members_from_traits(std::vector &&t } // Every class is passed here exactly once - when that class and all of its dependents are ready. -void SortAndInheritClassesF::on_class_ready(ClassPtr klass, DataStream &function_stream) { +void SortAndInheritClassesF::on_class_ready(ClassPtr klass, DataStream& function_stream) { stage::set_file(klass->file_id); std::vector traits; // we have to resolve traits first to see overridden methods before static inheritance - for (const auto &dep : klass->get_str_dependents()) { + for (const auto& dep : klass->get_str_dependents()) { if (dep.type == ClassType::trait) { traits.emplace_back(G->get_class(dep.class_name)); } } clone_members_from_traits(std::move(traits), klass, function_stream); - for (const auto &dep : klass->get_str_dependents()) { + for (const auto& dep : klass->get_str_dependents()) { ClassPtr dep_class = G->get_class(dep.class_name); switch (dep.type) { - case ClassType::klass: - inherit_child_class_from_parent(klass, dep_class, function_stream); - break; - case ClassType::interface: - inherit_class_from_interface(klass, dep_class); - break; - case ClassType::ffi_cdata: - case ClassType::ffi_scope: - kphp_assert(vk::any_of_equal(dep_class->name, "FFI\\CData", "FFI\\Scope")); - klass->parent_class = dep_class; - break; - case ClassType::trait: - break; + case ClassType::klass: + inherit_child_class_from_parent(klass, dep_class, function_stream); + break; + case ClassType::interface: + inherit_class_from_interface(klass, dep_class); + break; + case ClassType::ffi_cdata: + case ClassType::ffi_scope: + kphp_assert(vk::any_of_equal(dep_class->name, "FFI\\CData", "FFI\\Scope")); + klass->parent_class = dep_class; + break; + case ClassType::trait: + break; } } klass->create_default_constructor_if_required(function_stream); } -void SortAndInheritClassesF::execute(ClassPtr klass, MultipleDataStreams &os) { - auto &function_stream = *os.template project_to_nth_data_stream<0>(); - auto &restart_class_stream = *os.template project_to_nth_data_stream<1>(); +void SortAndInheritClassesF::execute(ClassPtr klass, MultipleDataStreams& os) { + auto& function_stream = *os.template project_to_nth_data_stream<0>(); + auto& restart_class_stream = *os.template project_to_nth_data_stream<1>(); - if (auto *dependency = get_not_ready_dependency(klass)) { + if (auto* dependency = get_not_ready_dependency(klass)) { AutoLocker locker(dependency); // check whether done is changed at this point if (dependency->data.done) { @@ -356,13 +338,13 @@ void SortAndInheritClassesF::execute(ClassPtr klass, MultipleDataStreamsname)); + auto* node = ht.at(vk::std_hash(klass->name)); kphp_assert(!node->data.done); - AutoLocker locker(node); + AutoLocker locker(node); // for every class that was waiting for the current class // we run SortAndInheritClassesF again - for (ClassPtr restart_klass: node->data.waiting) { + for (ClassPtr restart_klass : node->data.waiting) { restart_class_stream << restart_klass; } @@ -370,18 +352,17 @@ void SortAndInheritClassesF::execute(ClassPtr klass, MultipleDataStreamsdata.done = true; } -void SortAndInheritClassesF::check_on_finish(DataStream &os) { +void SortAndInheritClassesF::check_on_finish(DataStream& os) { DataStream generated_self_methods{true}; auto classes = G->get_classes(); for (ClassPtr c : classes) { - auto *node = ht.at(vk::std_hash(c->name)); + auto* node = ht.at(vk::std_hash(c->name)); if (!node->data.done) { - auto is_not_done = [](const ClassData::StrDependence &dep) { return !ht.at(vk::std_hash(dep.class_name))->data.done; }; - auto str_dep_to_string = [](const ClassData::StrDependence &dep) { return dep.class_name; }; + auto is_not_done = [](const ClassData::StrDependence& dep) { return !ht.at(vk::std_hash(dep.class_name))->data.done; }; + auto str_dep_to_string = [](const ClassData::StrDependence& dep) { return dep.class_name; }; kphp_error(false, fmt_format("class `{}` has unresolved dependencies [{}]", c->name, - vk::join(vk::filter(is_not_done, c->get_str_dependents()), ", ", str_dep_to_string)) - ); + vk::join(vk::filter(is_not_done, c->get_str_dependents()), ", ", str_dep_to_string))); } if ((!c->is_builtin() || c->need_generated_stub) && c->is_polymorphic_class()) { @@ -401,17 +382,16 @@ void SortAndInheritClassesF::check_on_finish(DataStream &os) { // check that members of this class don't conflict with parent's // we are in on_finish() of a sync block, all classes have been parsed and are not modified by other threads: no locks if (c->parent_class) { - c->members.for_each([c](const ClassMemberInstanceField &f) { + c->members.for_each([c](const ClassMemberInstanceField& f) { auto field_name = f.local_name(); kphp_error(!c->parent_class->get_instance_field(field_name) && !c->parent_class->get_static_field(field_name), fmt_format("You may not override field ${} in class {}", field_name, c->name)); }); - c->members.for_each([c](const ClassMemberStaticField &f) { + c->members.for_each([c](const ClassMemberStaticField& f) { auto field_name = f.local_name(); - kphp_error(!c->parent_class->get_instance_field(field_name), - fmt_format("You may not override field ${} in class {}", field_name, c->name)); + kphp_error(!c->parent_class->get_instance_field(field_name), fmt_format("You may not override field ${} in class {}", field_name, c->name)); }); - c->members.for_each([c](const ClassMemberStaticMethod &m) { + c->members.for_each([c](const ClassMemberStaticMethod& m) { kphp_error(!c->parent_class->get_instance_method(m.local_name()), fmt_format("Cannot make non-static method {}() static", m.function->as_human_readable())); }); diff --git a/compiler/pipes/sort-and-inherit-classes.h b/compiler/pipes/sort-and-inherit-classes.h index d23e51bac3..087aad9aaf 100644 --- a/compiler/pipes/sort-and-inherit-classes.h +++ b/compiler/pipes/sort-and-inherit-classes.h @@ -20,20 +20,20 @@ class SortAndInheritClassesF { static TSHashTable ht; - void on_class_ready(ClassPtr klass, DataStream &function_stream); + void on_class_ready(ClassPtr klass, DataStream& function_stream); - VertexAdaptor generate_function_with_parent_call(ClassPtr child_class, const ClassMemberStaticMethod &parent_method); + VertexAdaptor generate_function_with_parent_call(ClassPtr child_class, const ClassMemberStaticMethod& parent_method); - void inherit_child_class_from_parent(ClassPtr child_class, ClassPtr parent_class, DataStream &function_stream); - void inherit_static_method_from_parent(ClassPtr child_class, const ClassMemberStaticMethod &parent_method, DataStream &function_stream); - void inherit_instance_method_from_parent(ClassPtr child_class, const ClassMemberInstanceMethod &parent_method); + void inherit_child_class_from_parent(ClassPtr child_class, ClassPtr parent_class, DataStream& function_stream); + void inherit_static_method_from_parent(ClassPtr child_class, const ClassMemberStaticMethod& parent_method, DataStream& function_stream); + void inherit_instance_method_from_parent(ClassPtr child_class, const ClassMemberInstanceMethod& parent_method); void inherit_class_from_interface(ClassPtr child_class, InterfacePtr interface_class); - static void clone_members_from_traits(std::vector &&traits, ClassPtr ready_class, DataStream &function_stream); + static void clone_members_from_traits(std::vector&& traits, ClassPtr ready_class, DataStream& function_stream); - decltype(ht)::HTNode *get_not_ready_dependency(ClassPtr klass); + decltype(ht)::HTNode* get_not_ready_dependency(ClassPtr klass); public: - void execute(ClassPtr klass, MultipleDataStreams &os); - static void check_on_finish(DataStream &os); + void execute(ClassPtr klass, MultipleDataStreams& os); + static void check_on_finish(DataStream& os); }; diff --git a/compiler/pipes/split-switch.cpp b/compiler/pipes/split-switch.cpp index 7d08efc1e4..b904c58388 100644 --- a/compiler/pipes/split-switch.cpp +++ b/compiler/pipes/split-switch.cpp @@ -7,16 +7,15 @@ #include "compiler/compiler-core.h" #include "compiler/data/src-file.h" #include "compiler/function-pass.h" -#include "compiler/vertex-util.h" #include "compiler/name-gen.h" +#include "compiler/vertex-util.h" class SplitSwitchPass final : public FunctionPassBase { private: int depth{0}; std::vector new_functions; - static VertexPtr fix_break_continue(VertexAdaptor goto_op, - const std::string &state_name, int cycle_depth) { + static VertexPtr fix_break_continue(VertexAdaptor goto_op, const std::string& state_name, int cycle_depth) { int depth = -1; VertexPtr label = goto_op->level(); if (label->type() == op_int_const) { @@ -31,17 +30,14 @@ class SplitSwitchPass final : public FunctionPassBase { state->str_val = state_name; auto expr = VertexAdaptor::create(state, minus_one); - //TODO: auto_return instead of return true! + // TODO: auto_return instead of return true! auto true_val = VertexAdaptor::create(); auto new_return = VertexAdaptor::create(true_val); auto seq = VertexAdaptor::create(expr, new_return); return seq; } - static VertexPtr prepare_switch_func( - VertexPtr root, - const std::string &state_name, - int cycle_depth) { + static VertexPtr prepare_switch_func(VertexPtr root, const std::string& state_name, int cycle_depth) { if (root->type() == op_return) { auto one = VertexUtil::create_int_const(1); auto state = VertexAdaptor::create(); @@ -54,8 +50,8 @@ class SplitSwitchPass final : public FunctionPassBase { return fix_break_continue(root.as(), state_name, cycle_depth); } - for (auto &i : *root) { - //TODO: hack... write proper Range + for (auto& i : *root) { + // TODO: hack... write proper Range bool is_cycle = OpInfo::type(i->type()) == cycle_op; i = prepare_switch_func(i, state_name, cycle_depth + is_cycle); } @@ -133,7 +129,6 @@ class SplitSwitchPass final : public FunctionPassBase { case_res_copy->extra_type = op_ex_var_superlocal; auto run_func = VertexAdaptor::create(case_res, func_call); - auto zero = VertexUtil::create_int_const(0); auto one = VertexUtil::create_int_const(1); auto minus_one = VertexUtil::create_int_const(-1); @@ -165,12 +160,12 @@ class SplitSwitchPass final : public FunctionPassBase { return root; } - const std::vector &get_new_functions() { + const std::vector& get_new_functions() { return new_functions; } }; -void SplitSwitchF::execute(FunctionPtr function, DataStream &os) { +void SplitSwitchF::execute(FunctionPtr function, DataStream& os) { SplitSwitchPass split_switch; run_function_pass(function, &split_switch); diff --git a/compiler/pipes/split-switch.h b/compiler/pipes/split-switch.h index 58b85124fb..d53938d3be 100644 --- a/compiler/pipes/split-switch.h +++ b/compiler/pipes/split-switch.h @@ -9,5 +9,5 @@ class SplitSwitchF { public: - void execute(FunctionPtr function, DataStream &os); + void execute(FunctionPtr function, DataStream& os); }; diff --git a/compiler/pipes/sync.h b/compiler/pipes/sync.h index 1a6654891c..8620ceb613 100644 --- a/compiler/pipes/sync.h +++ b/compiler/pipes/sync.h @@ -12,36 +12,35 @@ template class SyncPipeFBase { protected: DataStream tmp_stream; + public: - SyncPipeFBase() : - tmp_stream(true) {} + SyncPipeFBase() + : tmp_stream(true) {} - virtual void execute(In input, DataStream &) { + virtual void execute(In input, DataStream&) { tmp_stream << std::move(input); } - virtual void on_finish(DataStream &) = 0; + virtual void on_finish(DataStream&) = 0; virtual ~SyncPipeFBase() = default; }; } // namespace sync_detail - template -class SyncPipeF : public sync_detail::SyncPipeFBase { -}; +class SyncPipeF : public sync_detail::SyncPipeFBase {}; template class SyncPipeF : public sync_detail::SyncPipeFBase { public: using need_profiler = std::false_type; - virtual bool forward_to_next_pipe(const T &) { + virtual bool forward_to_next_pipe(const T&) { return true; } - void on_finish(DataStream &os) override { + void on_finish(DataStream& os) override { stage::die_if_global_errors(); - for (auto &element: this->tmp_stream.flush()) { + for (auto& element : this->tmp_stream.flush()) { if (forward_to_next_pipe(element)) { os << std::move(element); } diff --git a/compiler/pipes/transform-to-smart-instanceof.cpp b/compiler/pipes/transform-to-smart-instanceof.cpp index 3fbfe6605b..f7e7e8d5f2 100644 --- a/compiler/pipes/transform-to-smart-instanceof.cpp +++ b/compiler/pipes/transform-to-smart-instanceof.cpp @@ -9,7 +9,6 @@ #include "compiler/name-gen.h" #include "compiler/vertex-util.h" - bool TransformToSmartInstanceofPass::user_recursion(VertexPtr v) { if (v->type() == op_if) { return on_if_user_recursion(v.as()); @@ -18,7 +17,7 @@ bool TransformToSmartInstanceofPass::user_recursion(VertexPtr v) { } else if (v->type() == op_lambda) { return on_lambda_user_recursion(v.as()); } - + return false; } @@ -66,7 +65,7 @@ bool TransformToSmartInstanceofPass::on_catch_user_recursion(VertexAdaptor $captured_var` — maybe, $captured_var from uses_list is modified (i.e. from smart instanceof or catch) bool TransformToSmartInstanceofPass::on_lambda_user_recursion(VertexAdaptor v_lambda) { FunctionPtr f_lambda = v_lambda->func_id; - for (auto &var_as_use : f_lambda->uses_list) { + for (auto& var_as_use : f_lambda->uses_list) { var_as_use = on_enter_vertex(var_as_use).as(); } run_function_pass(f_lambda->root, this); @@ -76,13 +75,14 @@ bool TransformToSmartInstanceofPass::on_lambda_user_recursion(VertexAdaptor v_if_not, VertexAdaptor instance_var, VertexPtr name_of_derived) { +bool TransformToSmartInstanceofPass::try_replace_if_not_instanceof_return(VertexAdaptor v_if_not, VertexAdaptor instance_var, + VertexPtr name_of_derived) { bool is_if_not_instanceof_return = !v_if_not->has_false_cmd() && v_if_not->true_cmd()->size() == 1 && v_if_not->true_cmd()->front()->type() == op_return; if (!is_if_not_instanceof_return) { return false; } - for (auto &child: *current_function->root->cmd()) { + for (auto& child : *current_function->root->cmd()) { if (child == v_if_not) { run_function_pass(v_if_not->cond(), this); run_function_pass(v_if_not->true_cmd_ref(), this); @@ -98,17 +98,15 @@ bool TransformToSmartInstanceofPass::try_replace_if_not_instanceof_return(Vertex return false; } -void TransformToSmartInstanceofPass::add_tmp_var_with_instance_cast(VertexAdaptor instance_var, VertexPtr name_of_derived, VertexPtr &cmd) { +void TransformToSmartInstanceofPass::add_tmp_var_with_instance_cast(VertexAdaptor instance_var, VertexPtr name_of_derived, VertexPtr& cmd) { auto set_instance_cast_to_tmp = generate_tmp_var_with_instance_cast(instance_var, name_of_derived); - auto &name_of_tmp_var = set_instance_cast_to_tmp->lhs().as()->str_val; + auto& name_of_tmp_var = set_instance_cast_to_tmp->lhs().as()->str_val; new_names_of_var[instance_var->str_val].push(name_of_tmp_var); cmd = VertexAdaptor::create(set_instance_cast_to_tmp, cmd.as()->args()).set_location(cmd); auto commands = cmd.as()->args(); - std::for_each(std::next(commands.begin()), commands.end(), [&](VertexPtr &v) { - return run_function_pass(v, this); - }); + std::for_each(std::next(commands.begin()), commands.end(), [&](VertexPtr& v) { return run_function_pass(v, this); }); } VertexPtr TransformToSmartInstanceofPass::on_enter_vertex(VertexPtr v) { @@ -181,22 +179,23 @@ VertexPtr TransformToSmartInstanceofPass::try_replace_switch_when_constexpr(Vert // 1) all cases are const strings // 2) every case ends with `break`/`return`/`throw` or is empty (just fallthrough) VertexRange cases = v_switch->cases(); - bool is_valid_const_string_switch = cases.size() > 1 && vk::all_of(cases, [](VertexPtr v) { - auto as_case = v.try_as(); - if (!as_case) { // default - return true; - } - VertexPtr last_stmt = as_case->cmd()->empty() ? (VertexPtr)VertexAdaptor::create() : as_case->cmd()->args()[as_case->cmd()->size() - 1]; - return VertexUtil::get_actual_value(as_case->expr())->type() == op_string && - vk::any_of_equal(last_stmt->type(), op_break, op_return, op_throw); - }); + bool is_valid_const_string_switch = + cases.size() > 1 && vk::all_of(cases, [](VertexPtr v) { + auto as_case = v.try_as(); + if (!as_case) { // default + return true; + } + VertexPtr last_stmt = as_case->cmd()->empty() ? (VertexPtr)VertexAdaptor::create() : as_case->cmd()->args()[as_case->cmd()->size() - 1]; + return VertexUtil::get_actual_value(as_case->expr())->type() == op_string && vk::any_of_equal(last_stmt->type(), op_break, op_return, op_throw); + }); if (!is_valid_const_string_switch) { return v_switch; } // find case x where x == switch condition (true case) - auto it_true_case = std::find_if(cases.begin(), cases.end(), - [v_cond](VertexPtr v_case) { return v_case->type() == op_case && VertexUtil::get_actual_value(v_case.as()->expr())->get_string() == v_cond->get_string(); }); + auto it_true_case = std::find_if(cases.begin(), cases.end(), [v_cond](VertexPtr v_case) { + return v_case->type() == op_case && VertexUtil::get_actual_value(v_case.as()->expr())->get_string() == v_cond->get_string(); + }); // for 'case x: case y: ...', fall through empty cases while (it_true_case != cases.end() && (*it_true_case)->type() == op_case && it_true_case->as()->cmd()->empty()) { ++it_true_case; @@ -207,8 +206,7 @@ VertexPtr TransformToSmartInstanceofPass::try_replace_switch_when_constexpr(Vert if (it_true_case != cases.end() && (*it_true_case)->type() == op_case) { v_true_cmd = it_true_case->as()->cmd(); } else { - auto it_default = std::find_if(cases.begin(), cases.end(), - [](VertexPtr v_case) { return v_case->type() == op_default; }); + auto it_default = std::find_if(cases.begin(), cases.end(), [](VertexPtr v_case) { return v_case->type() == op_default; }); if (it_default != cases.end()) { v_true_cmd = it_default->as()->cmd(); } @@ -223,4 +221,3 @@ VertexPtr TransformToSmartInstanceofPass::try_replace_switch_when_constexpr(Vert auto ins_default = VertexAdaptor::create(v_true_cmd).set_location(v_true_cmd); return VertexUtil::create_switch_vertex(current_function, v_switch->condition(), {ins_default}); } - diff --git a/compiler/pipes/transform-to-smart-instanceof.h b/compiler/pipes/transform-to-smart-instanceof.h index ea49c869d2..71f1820d40 100644 --- a/compiler/pipes/transform-to-smart-instanceof.h +++ b/compiler/pipes/transform-to-smart-instanceof.h @@ -29,7 +29,7 @@ class TransformToSmartInstanceofPass final : public FunctionPassBase { static VertexAdaptor generate_tmp_var_with_instance_cast(VertexPtr instance_var, VertexPtr derived_name_vertex); static VertexAdaptor get_instanceof_from_if_condition(VertexPtr if_cond); static VertexAdaptor get_instanceof_from_if_not_condition(VertexPtr if_cond); - void add_tmp_var_with_instance_cast(VertexAdaptor instance_var, VertexPtr name_of_derived, VertexPtr &cmd); + void add_tmp_var_with_instance_cast(VertexAdaptor instance_var, VertexPtr name_of_derived, VertexPtr& cmd); bool try_replace_if_not_instanceof_return(VertexAdaptor v_if_not, VertexAdaptor instance_var, VertexPtr name_of_derived); bool on_if_user_recursion(VertexAdaptor v_if); diff --git a/compiler/pipes/type-inferer.cpp b/compiler/pipes/type-inferer.cpp index 12ef62b5ff..2f7a3bbbc5 100644 --- a/compiler/pipes/type-inferer.cpp +++ b/compiler/pipes/type-inferer.cpp @@ -6,11 +6,11 @@ #include "compiler/inferring/public.h" -void TypeInfererF::execute(FunctionAndCFG input, DataStream &os) { +void TypeInfererF::execute(FunctionAndCFG input, DataStream& os) { os << input; } -void TypeInfererF::on_finish(DataStream &) { - std::vector tasks = tinf::get_inferer()->get_tasks(); +void TypeInfererF::on_finish(DataStream&) { + std::vector tasks = tinf::get_inferer()->get_tasks(); std::for_each(tasks.begin(), tasks.end(), register_async_task); } diff --git a/compiler/pipes/type-inferer.h b/compiler/pipes/type-inferer.h index b17632e165..a30239790a 100644 --- a/compiler/pipes/type-inferer.h +++ b/compiler/pipes/type-inferer.h @@ -11,9 +11,8 @@ class TypeInfererF { public: // don't show on_finish() in profiler, as it does nothing and is just a zero line using need_on_finish_profiler = std::false_type; - - void execute(FunctionAndCFG input, DataStream &os); - void on_finish(DataStream &os); -}; + void execute(FunctionAndCFG input, DataStream& os); + void on_finish(DataStream& os); +}; diff --git a/compiler/pipes/wait-for-all-classes.cpp b/compiler/pipes/wait-for-all-classes.cpp index 92c3b3ef33..d4e283c8e4 100644 --- a/compiler/pipes/wait-for-all-classes.cpp +++ b/compiler/pipes/wait-for-all-classes.cpp @@ -7,9 +7,9 @@ #include "compiler/compiler-core.h" #include "compiler/data/composer-json-data.h" +#include "compiler/data/modulite-data.h" #include "compiler/data/src-dir.h" #include "compiler/data/src-file.h" -#include "compiler/data/modulite-data.h" /* * This is a sync point. When `on_finish()` is called (once, in a single thread), then @@ -24,7 +24,7 @@ * On complete, pass all functions forward the compilation pipeline. */ -void WaitForAllClassesF::on_finish(DataStream &os) { +void WaitForAllClassesF::on_finish(DataStream& os) { stage::die_if_global_errors(); SortAndInheritClassesF::check_on_finish(tmp_stream); stage::set_name("Register modulites"); @@ -38,9 +38,7 @@ void WaitForAllClassesF::resolve_and_validate_modulites() { // sort all modulites from short to long, so that a parent appears before a child when iterating // this fact is used to fill `child->exported_from_parent` by lookup, and some others std::vector all_modulites = G->get_modulites(); - std::sort(all_modulites.begin(), all_modulites.end(), [](ModulitePtr m1, ModulitePtr m2) { - return m1->modulite_name.size() < m2->modulite_name.size(); - }); + std::sort(all_modulites.begin(), all_modulites.end(), [](ModulitePtr m1, ModulitePtr m2) { return m1->modulite_name.size() < m2->modulite_name.size(); }); // resolve symbols like SomeClass and @msg in "export"/"require"/etc. // until now, they are stored just as string names, they can be resolved only after all classes have been loaded diff --git a/compiler/pipes/wait-for-all-classes.h b/compiler/pipes/wait-for-all-classes.h index 52315dd73c..531ac57f76 100644 --- a/compiler/pipes/wait-for-all-classes.h +++ b/compiler/pipes/wait-for-all-classes.h @@ -6,23 +6,24 @@ #include "compiler/data/class-data.h" #include "compiler/data/function-data.h" -#include "compiler/threading/data-stream.h" #include "compiler/pipes/sync.h" +#include "compiler/threading/data-stream.h" -class WaitForAllClassesF final: public SyncPipeF { +class WaitForAllClassesF final : public SyncPipeF { using Base = SyncPipeF; + public: - bool forward_to_next_pipe(const FunctionPtr &f) final { + bool forward_to_next_pipe(const FunctionPtr& f) final { if (f->type == FunctionData::func_local || f->type == FunctionData::func_class_holder) { return !f->class_id || !f->class_id->is_trait(); } if (f->type == FunctionData::func_lambda) { - const FunctionData *p = f->get_this_or_topmost_if_lambda(); + const FunctionData* p = f->get_this_or_topmost_if_lambda(); return !p->class_id || !p->class_id->is_trait(); } return true; } - void on_finish(DataStream &os) final; + void on_finish(DataStream& os) final; void resolve_and_validate_modulites(); }; diff --git a/compiler/pipes/write-files.cpp b/compiler/pipes/write-files.cpp index aff8493b47..d69a5423de 100644 --- a/compiler/pipes/write-files.cpp +++ b/compiler/pipes/write-files.cpp @@ -9,10 +9,10 @@ #include "compiler/compiler-core.h" #include "compiler/stage.h" -void WriteFilesF::execute(WriterData *data, EmptyStream &) { +void WriteFilesF::execute(WriterData* data, EmptyStream&) { stage::set_name("Write files"); - File *file = data->get_file(); + File* file = data->get_file(); bool need_del = false; bool need_fix = false; @@ -35,7 +35,7 @@ void WriteFilesF::execute(WriterData *data, EmptyStream &) { if (need_fix) { std::string code_str; data->dump(code_str); -// printf("overwrite file %s need_fix=%d need_del=%d need_save_time=%d\n", file->path.c_str(), need_fix, need_del, need_save_time); + // printf("overwrite file %s need_fix=%d need_del=%d need_save_time=%d\n", file->path.c_str(), need_fix, need_del, need_save_time); long long mtime_before = 0; if (need_save_time) { @@ -49,9 +49,8 @@ void WriteFilesF::execute(WriterData *data, EmptyStream &) { int err = unlink(file->path.c_str()); kphp_assert_msg(err == 0, fmt_format("Failed to unlink [{}] : {}", file->path, strerror(errno))); } - FILE *dest_file = fopen(file->path.c_str(), "w"); - kphp_assert_msg(dest_file != nullptr, - fmt_format("Failed to open [{}] for write : {}\n", file->path, strerror(errno))); + FILE* dest_file = fopen(file->path.c_str(), "w"); + kphp_assert_msg(dest_file != nullptr, fmt_format("Failed to open [{}] for write : {}\n", file->path, strerror(errno))); if (data->compile_with_crc()) { // the first two lines of every .cpp/.h are hashes @@ -65,8 +64,7 @@ void WriteFilesF::execute(WriterData *data, EmptyStream &) { kphp_assert(fseek(dest_file, 0, SEEK_SET) >= 0); kphp_assert(fprintf(dest_file, "//crc64:%016llx\n", hash_of_cpp) >= 0); kphp_assert(fprintf(dest_file, "//crc64_with_comments:%016llx\n", hash_of_comments) >= 0); - } - else { + } else { kphp_assert(fprintf(dest_file, "%s", code_str.c_str()) >= 0); } diff --git a/compiler/pipes/write-files.h b/compiler/pipes/write-files.h index 5fc36417aa..cdc71c1084 100644 --- a/compiler/pipes/write-files.h +++ b/compiler/pipes/write-files.h @@ -9,5 +9,5 @@ class WriteFilesF { public: - void execute(WriterData *data, EmptyStream &); + void execute(WriterData* data, EmptyStream&); }; diff --git a/compiler/rewrite-rules/replace-extern-func-calls.cpp b/compiler/rewrite-rules/replace-extern-func-calls.cpp index f9d98aeeaf..83b17a0150 100644 --- a/compiler/rewrite-rules/replace-extern-func-calls.cpp +++ b/compiler/rewrite-rules/replace-extern-func-calls.cpp @@ -10,8 +10,8 @@ #include "compiler/compiler-core.h" #include "compiler/data/class-data.h" #include "compiler/data/define-data.h" -#include "compiler/data/kphp-json-tags.h" #include "compiler/data/function-data.h" +#include "compiler/data/kphp-json-tags.h" #include "compiler/data/kphp-tracing-tags.h" #include "compiler/vertex-util.h" @@ -45,8 +45,10 @@ static bool is_class_JsonEncoder_or_child(ClassPtr class_id) { // `new $c(...)` is stored as `_by_name_construct($c, ...)` in AST // here we replace `_by_name_construct('A', ...args)` => `A::__construct(op_alloc, ...args)` static VertexPtr replace_by_name_construct(VertexAdaptor call) { - const std::string *class_name = VertexUtil::get_constexpr_string(call->args()[0]); - kphp_error_act(class_name, "Syntax 'new $class_name' works only if $class_name is compile-time known.\nIt can be achieved via generics and class-string, for example.", return call); + const std::string* class_name = VertexUtil::get_constexpr_string(call->args()[0]); + kphp_error_act(class_name, + "Syntax 'new $class_name' works only if $class_name is compile-time known.\nIt can be achieved via generics and class-string, for example.", + return call); ClassPtr klass = G->get_class(*class_name); kphp_assert(klass); @@ -77,22 +79,28 @@ static VertexPtr replace_by_name_construct(VertexAdaptor call) { // `$c::method()` is stored as `_by_name_call_method($c, 'method')` in AST // here we replace `_by_name_call_method('A', 'method', ...args)` => `A::method(...args)` static VertexPtr replace_by_name_call_method(VertexAdaptor call) { - const std::string *class_name = VertexUtil::get_constexpr_string(call->args()[0]); - const std::string *method_name = VertexUtil::get_constexpr_string(call->args()[1]); - kphp_error_act(class_name, "Syntax '$class_name::method()' works only if $class_name is compile-time known.\nIt can be achieved via generics and class-string, for example.", return call); + const std::string* class_name = VertexUtil::get_constexpr_string(call->args()[0]); + const std::string* method_name = VertexUtil::get_constexpr_string(call->args()[1]); + kphp_error_act( + class_name, + "Syntax '$class_name::method()' works only if $class_name is compile-time known.\nIt can be achieved via generics and class-string, for example.", + return call); ClassPtr klass = G->get_class(*class_name); kphp_assert(klass && method_name); - const auto *m_method = klass->members.get_static_method(*method_name); + const auto* m_method = klass->members.get_static_method(*method_name); if (!m_method) { - const auto *instance_method_m = klass->get_instance_method(*method_name); - kphp_error(!instance_method_m, fmt_format("Syntax '$class_name::method()' works only for static methods, but {} is an instance method", instance_method_m->function->as_human_readable())); - kphp_error( instance_method_m, fmt_format("Syntax '$class_name::method()' not resolved: method {} not found in class {}", *method_name, klass->as_human_readable())); + const auto* instance_method_m = klass->get_instance_method(*method_name); + kphp_error(!instance_method_m, fmt_format("Syntax '$class_name::method()' works only for static methods, but {} is an instance method", + instance_method_m->function->as_human_readable())); + kphp_error(instance_method_m, + fmt_format("Syntax '$class_name::method()' not resolved: method {} not found in class {}", *method_name, klass->as_human_readable())); return call; } FunctionPtr method = m_method->function; - kphp_error(method->is_required, fmt_format("Add @kphp-required over {}, because it's used only from a '$class_name::method()' syntax", method->as_human_readable())); + kphp_error(method->is_required, + fmt_format("Add @kphp-required over {}, because it's used only from a '$class_name::method()' syntax", method->as_human_readable())); std::vector method_args; method_args.reserve(call->size() - 2); @@ -109,14 +117,17 @@ static VertexPtr replace_by_name_call_method(VertexAdaptor call) { // `$c::CONST` is stored as `_by_name_get_const($c, 'CONST')` in AST // here we replace `_by_name_get_const('A', 'const')` => `A::CONST (value of)` static VertexPtr replace_by_name_get_const(FunctionPtr current_function, VertexAdaptor call) { - const std::string *class_name = VertexUtil::get_constexpr_string(call->args()[0]); - const std::string *const_name = VertexUtil::get_constexpr_string(call->args()[1]); - kphp_error_act(class_name, "Syntax '$class_name::CONST' works only if $class_name is compile-time known.\nIt can be achieved via generics and class-string, for example.", return call); + const std::string* class_name = VertexUtil::get_constexpr_string(call->args()[0]); + const std::string* const_name = VertexUtil::get_constexpr_string(call->args()[1]); + kphp_error_act( + class_name, + "Syntax '$class_name::CONST' works only if $class_name is compile-time known.\nIt can be achieved via generics and class-string, for example.", + return call); ClassPtr klass = G->get_class(*class_name); kphp_assert(klass && const_name); - const auto *m_const = klass->get_constant(*const_name); + const auto* m_const = klass->get_constant(*const_name); if (!m_const) { kphp_error(0, fmt_format("Syntax '$class_name::CONST' not resolved: const {} not found in class {}", *const_name, klass->as_human_readable())); return call; @@ -134,18 +145,23 @@ static VertexPtr replace_by_name_get_const(FunctionPtr current_function, VertexA // `$c::$field` is stored as `_by_name_get_field($c, 'field')` in AST // here we replace `_by_name_get_field('A', 'field')` => `A::$field` static VertexPtr replace_by_name_get_field(VertexAdaptor call) { - const std::string *class_name = VertexUtil::get_constexpr_string(call->args()[0]); - const std::string *field_name = VertexUtil::get_constexpr_string(call->args()[1]); - kphp_error_act(class_name, "Syntax '$class_name::$field' works only if $class_name is compile-time known.\nIt can be achieved via generics and class-string, for example.", return call); + const std::string* class_name = VertexUtil::get_constexpr_string(call->args()[0]); + const std::string* field_name = VertexUtil::get_constexpr_string(call->args()[1]); + kphp_error_act( + class_name, + "Syntax '$class_name::$field' works only if $class_name is compile-time known.\nIt can be achieved via generics and class-string, for example.", + return call); ClassPtr klass = G->get_class(*class_name); kphp_assert(klass && field_name); - const auto *m_field = klass->get_static_field(*field_name); + const auto* m_field = klass->get_static_field(*field_name); if (!m_field) { - const auto *instance_field_m = klass->get_instance_field(*field_name); - kphp_error(!instance_field_m, fmt_format("Syntax '$class_name::$field' works only for static fields, but {} is an instance field", instance_field_m->var->as_human_readable())); - kphp_error( instance_field_m, fmt_format("Syntax '$class_name::$field' not resolved: field ${} not found in class {}", *field_name, klass->as_human_readable())); + const auto* instance_field_m = klass->get_instance_field(*field_name); + kphp_error(!instance_field_m, fmt_format("Syntax '$class_name::$field' works only for static fields, but {} is an instance field", + instance_field_m->var->as_human_readable())); + kphp_error(instance_field_m, + fmt_format("Syntax '$class_name::$field' not resolved: field ${} not found in class {}", *field_name, klass->as_human_readable())); return call; } VarPtr field = m_field->var; @@ -186,12 +202,11 @@ static VertexPtr replace_classof([[maybe_unused]] FunctionPtr current_function, return call; } - // it's the main (exported) function // see comment at the top of the file VertexPtr maybe_replace_extern_func_call(FunctionPtr current_function, VertexAdaptor call) { FunctionPtr f_called = call->func_id; - const std::string &f_name = f_called->name; + const std::string& f_name = f_called->name; int n_args = call->size(); // new $c, $c::method(), $c::CONST, $c::$FIELD diff --git a/compiler/rewrite-rules/rules_runtime.cpp b/compiler/rewrite-rules/rules_runtime.cpp index 829a78ca78..a7c1f1952c 100644 --- a/compiler/rewrite-rules/rules_runtime.cpp +++ b/compiler/rewrite-rules/rules_runtime.cpp @@ -4,90 +4,90 @@ #include "compiler/rewrite-rules/rules_runtime.h" +#include "compiler/data/function-data.h" #include "compiler/inferring/public.h" #include "compiler/type-hint.h" -#include "compiler/data/function-data.h" #include "compiler/vertex-util.h" namespace rewrite_rules { -Context &get_context() { +Context& get_context() { static thread_local Context ctx; return ctx; } -bool add_to_cache(Context &ctx, VertexPtr v) { +bool add_to_cache(Context& ctx, VertexPtr v) { switch (v->type()) { - case op_int_const: - ctx.int_const_cache_.push(v.as()); - return true; + case op_int_const: + ctx.int_const_cache_.push(v.as()); + return true; - case op_string: - ctx.string_cache_.push(v.as()); - return true; + case op_string: + ctx.string_cache_.push(v.as()); + return true; - case op_func_call: { - auto func_call = v.as(); - kphp_assert(func_call->extra_type == op_ex_none); - switch (func_call->args().size()) { - case 0: - ctx.func_call0_cache_.push(func_call); - return true; - case 1: - ctx.func_call1_cache_.push(func_call); - return true; - case 2: - ctx.func_call2_cache_.push(func_call); - return true; - case 3: - ctx.func_call3_cache_.push(func_call); - return true; - } - return false; + case op_func_call: { + auto func_call = v.as(); + kphp_assert(func_call->extra_type == op_ex_none); + switch (func_call->args().size()) { + case 0: + ctx.func_call0_cache_.push(func_call); + return true; + case 1: + ctx.func_call1_cache_.push(func_call); + return true; + case 2: + ctx.func_call2_cache_.push(func_call); + return true; + case 3: + ctx.func_call3_cache_.push(func_call); + return true; } + return false; + } - default: - return false; + default: + return false; } } -void retire_vertex(Context &ctx, VertexPtr v) { +void retire_vertex(Context& ctx, VertexPtr v) { add_to_cache(ctx, v); } // is_pure reports whether the evaluation of v is free of side effects. bool is_pure(VertexPtr v) { switch (v->type()) { - case op_var: - case op_int_const: - case op_float_const: - case op_string: - case op_false: - case op_true: - case op_null: - return true; + case op_var: + case op_int_const: + case op_float_const: + case op_string: + case op_false: + case op_true: + case op_null: + return true; - case op_conv_array: - case op_conv_string: - case op_conv_int: - case op_conv_float: - case op_conv_bool: - case op_conv_mixed: - return is_pure(v.as()->expr()); - - case op_instance_prop: - return is_pure(v.as()->instance()); - - case op_index: { - auto as_index = v.as(); - if (as_index->has_key()) { - return is_pure(as_index->array()) && is_pure(as_index->key()); - } - return false; + case op_conv_array: + case op_conv_string: + case op_conv_int: + case op_conv_float: + case op_conv_bool: + case op_conv_mixed: + return is_pure(v.as()->expr()); + + case op_instance_prop: + return is_pure(v.as()->instance()); + + case op_index: { + auto as_index = v.as(); + if (as_index->has_key()) { + return is_pure(as_index->array()) && is_pure(as_index->key()); } + return false; + } - default: - return false; + default: + return false; } } @@ -107,42 +107,40 @@ bool is_same(VertexPtr x, VertexPtr y) { } switch (x->type()) { - case op_var: - case op_string: - case op_int_const: - case op_float_const: - return x->get_string() == y->get_string(); - - case op_index: { - auto x_index = x.as(); - auto y_index = y.as(); - VertexPtr x_key; - VertexPtr y_key; - if (x_index->has_key()) { - if (y_index->has_key() != x_index->has_key()) { - return false; - } - x_key = x_index->key(); - y_key = y_index->key(); + case op_var: + case op_string: + case op_int_const: + case op_float_const: + return x->get_string() == y->get_string(); + + case op_index: { + auto x_index = x.as(); + auto y_index = y.as(); + VertexPtr x_key; + VertexPtr y_key; + if (x_index->has_key()) { + if (y_index->has_key() != x_index->has_key()) { + return false; } - return is_same(x_index->array(), y_index->array()) && - is_same(x_key, y_key); + x_key = x_index->key(); + y_key = y_index->key(); } + return is_same(x_index->array(), y_index->array()) && is_same(x_key, y_key); + } - case op_instance_prop: { - auto x_instance_prop = x.as(); - auto y_instance_prop = y.as(); - return is_same(x_instance_prop->instance(), y_instance_prop->instance()) && - x_instance_prop->get_string() == y_instance_prop->get_string(); - } + case op_instance_prop: { + auto x_instance_prop = x.as(); + auto y_instance_prop = y.as(); + return is_same(x_instance_prop->instance(), y_instance_prop->instance()) && x_instance_prop->get_string() == y_instance_prop->get_string(); + } - case op_false: - case op_true: - case op_null: - return true; + case op_false: + case op_true: + case op_null: + return true; - default: - return false; + default: + return false; } } @@ -155,60 +153,60 @@ static bool is_safe_simple_expr(VertexPtr v) { // some notes on why certain vertex types are not included // * mixed/array/string conversions could allocate switch (v->type()) { - case op_var: - case op_int_const: - case op_float_const: - case op_string: - case op_false: - case op_true: - case op_null: - return true; + case op_var: + case op_int_const: + case op_float_const: + case op_string: + case op_false: + case op_true: + case op_null: + return true; - case op_conv_int: - case op_conv_float: - case op_conv_bool: - // these conversions never allocate - return is_safe_simple_expr(v.as()->expr()); - - case op_instance_prop: - // even though $foo->x could allocate $foo if it was null, - // it will never affect the lifetimes: $foo variable existed before - // this expression was evaluated - return is_safe_simple_expr(v.as()->instance()); - - case op_index: { - auto as_index = v.as(); - if (as_index->has_key()) { - return is_safe_simple_expr(as_index->array()) && is_safe_simple_expr(as_index->key()); - } - return false; - } - case op_define_val: { - return is_safe_simple_expr(v.as()->value()); + case op_conv_int: + case op_conv_float: + case op_conv_bool: + // these conversions never allocate + return is_safe_simple_expr(v.as()->expr()); + + case op_instance_prop: + // even though $foo->x could allocate $foo if it was null, + // it will never affect the lifetimes: $foo variable existed before + // this expression was evaluated + return is_safe_simple_expr(v.as()->instance()); + + case op_index: { + auto as_index = v.as(); + if (as_index->has_key()) { + return is_safe_simple_expr(as_index->array()) && is_safe_simple_expr(as_index->key()); } - default: - return false; + return false; + } + case op_define_val: { + return is_safe_simple_expr(v.as()->value()); + } + default: + return false; } } static VertexAdaptor extract_var(VertexPtr v) { switch (v->type()) { - case op_var: - return v.as(); + case op_var: + return v.as(); - case op_index: - return extract_var(v.as()->array()); + case op_index: + return extract_var(v.as()->array()); - case op_instance_prop: - return extract_var(v.as()->instance()); + case op_instance_prop: + return extract_var(v.as()->instance()); - case op_conv_array_l: - case op_conv_int_l: - case op_conv_string_l: - return extract_var(v.as()->expr()); + case op_conv_array_l: + case op_conv_int_l: + case op_conv_string_l: + return extract_var(v.as()->expr()); - default: - return {}; + default: + return {}; } } @@ -216,9 +214,7 @@ bool contains(VertexPtr tree, VertexPtr x) { if (is_same(tree, x)) { return true; } - return std::any_of(tree->begin(), tree->end(), [x](VertexPtr e) { - return contains(e, x); - }); + return std::any_of(tree->begin(), tree->end(), [x](VertexPtr e) { return contains(e, x); }); } bool contains_var(VertexPtr tree, VertexPtr var) { diff --git a/compiler/rewrite-rules/rules_runtime.h b/compiler/rewrite-rules/rules_runtime.h index f9395e2df0..4ac513a062 100644 --- a/compiler/rewrite-rules/rules_runtime.h +++ b/compiler/rewrite-rules/rules_runtime.h @@ -7,20 +7,18 @@ // This file is intended to be used inside auto-generated rewrite rules. // Do not include it from somewhere else. -#include -#include "compiler/vertex.h" #include "compiler/compiler-core.h" +#include "compiler/vertex.h" +#include namespace rewrite_rules { template class VertexCache { private: - std::vector> stack_; public: - VertexAdaptor pop() { if (!stack_.empty()) { auto v = stack_.back(); @@ -49,7 +47,7 @@ struct Context { std::vector tmp_args_vector_; }; -Context &get_context(); +Context& get_context(); bool is_pure(VertexPtr v); bool is_same(VertexPtr x, VertexPtr y); @@ -67,24 +65,24 @@ VertexAdaptor vertex_cast(T v) { return v.template as(); } -void retire_vertex(Context &ctx, VertexPtr v); +void retire_vertex(Context& ctx, VertexPtr v); inline void set_func_call_args(VertexAdaptor call __attribute__((unused))) {} -inline void set_func_call_args(VertexAdaptor call, const std::vector &args) { +inline void set_func_call_args(VertexAdaptor call, const std::vector& args) { for (int i = 0; i < args.size(); i++) { call->args()[i] = args[i]; } } template -void set_func_call_args(VertexAdaptor call, const Args &...args) { +void set_func_call_args(VertexAdaptor call, const Args&... args) { int i = 0; ((call->args()[i++] = args), ...); } template -VertexAdaptor create_vertex_with_string(Context &ctx, std::string &&str_val, Args &&...args) { +VertexAdaptor create_vertex_with_string(Context& ctx, std::string&& str_val, Args&&... args) { // allocate a vertex or take it from the cache VertexAdaptor v; @@ -124,7 +122,7 @@ VertexAdaptor create_vertex_with_string(Context &ctx, std::string &&str_val, } template -VertexAdaptor create_vertex_with_string(Context &ctx, std::string &&name, const VertexConstRange &args) { +VertexAdaptor create_vertex_with_string(Context& ctx, std::string&& name, const VertexConstRange& args) { ctx.tmp_args_vector_.insert(ctx.tmp_args_vector_.end(), args.begin(), args.end()); auto result = create_vertex_with_string(ctx, std::move(name), ctx.tmp_args_vector_); ctx.tmp_args_vector_.clear(); @@ -132,7 +130,7 @@ VertexAdaptor create_vertex_with_string(Context &ctx, std::string &&name, co } template -VertexAdaptor create_vertex(Context &ctx, Args &&...args) { +VertexAdaptor create_vertex(Context& ctx, Args&&... args) { static_cast(ctx); auto v = VertexAdaptor::create(std::forward(args)...); return v; diff --git a/compiler/runtime_build_info.h b/compiler/runtime_build_info.h index 0f07847a22..da3a181b9f 100644 --- a/compiler/runtime_build_info.h +++ b/compiler/runtime_build_info.h @@ -3,9 +3,9 @@ #ifdef RUNTIME_LIGHT #include "auto/compiler/common_sources.h" -#include "auto/compiler/unicode_sources.h" -#include "auto/compiler/runtime_compile_flags.h" #include "auto/compiler/runtime_common_sources.h" +#include "auto/compiler/runtime_compile_flags.h" #include "auto/compiler/runtime_sources.h" +#include "auto/compiler/unicode_sources.h" #endif diff --git a/compiler/scheduler/constructor.h b/compiler/scheduler/constructor.h index e94164735a..df06b8b9d0 100644 --- a/compiler/scheduler/constructor.h +++ b/compiler/scheduler/constructor.h @@ -14,17 +14,17 @@ struct sync_node_tag { }; template -struct use_nth_output_tag { -}; +struct use_nth_output_tag {}; template class pipe_creator; template class pipe_creator { - static PipeT *pipe; + static PipeT* pipe; + public: - static PipeT *get() { + static PipeT* get() { if (pipe == nullptr) { pipe = new PipeT(parallel); } @@ -33,21 +33,19 @@ class pipe_creator { }; template -PipeT *pipe_creator::pipe = nullptr; +PipeT* pipe_creator::pipe = nullptr; template class pipe_creator { public: - static PipeT *get() { + static PipeT* get() { return new PipeT(parallel); } }; - template struct pipe_creator_tag : pipe_creator { static_assert(!PipeT::pipe_fun_have_on_finish::value, "Non-sync pipe mustn't have on_finish function"); - }; template @@ -58,13 +56,12 @@ struct sync_pipe_creator_tag : pipe_creator { template class SC_Pipe { private: - SchedulerBase *scheduler; - StreamT *&previous_output_stream; - Node *previous_node; + SchedulerBase* scheduler; + StreamT*& previous_output_stream; + Node* previous_node; private: - - static void connect(StreamT *&first_stream, StreamT *&second_stream) { + static void connect(StreamT*& first_stream, StreamT*& second_stream) { if (first_stream != nullptr && second_stream != nullptr) { assert(first_stream == second_stream); return; @@ -81,23 +78,23 @@ class SC_Pipe { } template - SC_Pipe operator>>(NextPipeT &next_pipe) { + SC_Pipe operator>>(NextPipeT& next_pipe) { connect(previous_output_stream, next_pipe.get_input_stream()); next_pipe.init_output_stream_if_not_inited(); return {scheduler, &next_pipe}; } public: - SC_Pipe(SchedulerBase *scheduler, StreamT *&stream, Node *previous_node) : - scheduler(scheduler), - previous_output_stream(stream), - previous_node(previous_node) {} + SC_Pipe(SchedulerBase* scheduler, StreamT*& stream, Node* previous_node) + : scheduler(scheduler), + previous_output_stream(stream), + previous_node(previous_node) {} template - SC_Pipe(SchedulerBase *scheduler, PipeT *pipe) : - scheduler(scheduler), - previous_output_stream(pipe->get_output_stream()), - previous_node(pipe) { + SC_Pipe(SchedulerBase* scheduler, PipeT* pipe) + : scheduler(scheduler), + previous_output_stream(pipe->get_output_stream()), + previous_node(pipe) { pipe->add_to_scheduler(scheduler); } @@ -119,16 +116,14 @@ class SC_Pipe { template SC_Pipe> operator>>(use_nth_output_tag) { - return SC_Pipe> - {scheduler, previous_output_stream->template project_to_nth_data_stream(), previous_node}; + return SC_Pipe>{scheduler, previous_output_stream->template project_to_nth_data_stream(), previous_node}; } - }; class SchedulerConstructor { - SchedulerBase *scheduler; -public: + SchedulerBase* scheduler; +public: template SC_Pipe operator>>(pipe_creator) { auto pipe = pipe_creator::get(); @@ -139,6 +134,6 @@ class SchedulerConstructor { return sc_pipe; } - explicit SchedulerConstructor(SchedulerBase *scheduler) : - scheduler(scheduler) {} + explicit SchedulerConstructor(SchedulerBase* scheduler) + : scheduler(scheduler) {} }; diff --git a/compiler/scheduler/node.cpp b/compiler/scheduler/node.cpp index 3b9708ef50..da66e5540c 100644 --- a/compiler/scheduler/node.cpp +++ b/compiler/scheduler/node.cpp @@ -8,7 +8,7 @@ #include "compiler/scheduler/scheduler-base.h" -void Node::add_to_scheduler(SchedulerBase *scheduler) { +void Node::add_to_scheduler(SchedulerBase* scheduler) { if (in_scheduler == scheduler) { return; } @@ -26,6 +26,6 @@ bool Node::is_parallel() { return parallel; } -Node::Node(bool parallel) : - in_scheduler(nullptr), - parallel(parallel) {} +Node::Node(bool parallel) + : in_scheduler(nullptr), + parallel(parallel) {} diff --git a/compiler/scheduler/node.h b/compiler/scheduler/node.h index 44f2f45bed..eafcd9671a 100644 --- a/compiler/scheduler/node.h +++ b/compiler/scheduler/node.h @@ -8,7 +8,7 @@ class SchedulerBase; class Task; class Node { - SchedulerBase *in_scheduler; + SchedulerBase* in_scheduler; bool parallel; public: @@ -20,12 +20,12 @@ class Node { virtual ~Node() = default; - void add_to_scheduler(SchedulerBase *scheduler); + void add_to_scheduler(SchedulerBase* scheduler); void add_to_scheduler_as_sync_node(); virtual bool is_parallel(); - virtual Task *get_task() = 0; + virtual Task* get_task() = 0; virtual void on_finish() = 0; }; diff --git a/compiler/scheduler/one-thread-scheduler.cpp b/compiler/scheduler/one-thread-scheduler.cpp index 76ebb29541..a9193bfadf 100644 --- a/compiler/scheduler/one-thread-scheduler.cpp +++ b/compiler/scheduler/one-thread-scheduler.cpp @@ -13,16 +13,16 @@ OneThreadScheduler::OneThreadScheduler() { task_pull = new TaskPull(); } -void OneThreadScheduler::add_node(Node *node) { +void OneThreadScheduler::add_node(Node* node) { nodes.push_back(node); } -void OneThreadScheduler::add_sync_node(Node *node) { +void OneThreadScheduler::add_sync_node(Node* node) { sync_nodes.push(node); } -void OneThreadScheduler::add_task(Task *task) { - assert (task_pull != nullptr); +void OneThreadScheduler::add_task(Task* task) { + assert(task_pull != nullptr); task_pull->add_task(task); } @@ -35,8 +35,8 @@ void OneThreadScheduler::execute() { bool run_flag = true; while (run_flag) { run_flag = false; - for (auto *node : nodes) { - Task *task; + for (auto* node : nodes) { + Task* task; while ((task = node->get_task()) != nullptr) { run_flag = true; task->execute(); @@ -49,7 +49,7 @@ void OneThreadScheduler::execute() { run_flag = true; } } - for (auto *node : nodes) { + for (auto* node : nodes) { delete node; } } diff --git a/compiler/scheduler/one-thread-scheduler.h b/compiler/scheduler/one-thread-scheduler.h index 6e29021c86..7bbb36c2f4 100644 --- a/compiler/scheduler/one-thread-scheduler.h +++ b/compiler/scheduler/one-thread-scheduler.h @@ -13,15 +13,16 @@ class TaskPull; class OneThreadScheduler : public SchedulerBase { private: - std::vector nodes; - std::queue sync_nodes; - TaskPull *task_pull; + std::vector nodes; + std::queue sync_nodes; + TaskPull* task_pull; + public: OneThreadScheduler(); - void add_node(Node *node) override; - void add_sync_node(Node *node) override; - void add_task(Task *task) override; + void add_node(Node* node) override; + void add_sync_node(Node* node) override; + void add_task(Task* task) override; void execute() override; void set_threads_count(int threads_count); }; diff --git a/compiler/scheduler/pipe.h b/compiler/scheduler/pipe.h index d0b124ccba..49e5a75ac3 100644 --- a/compiler/scheduler/pipe.h +++ b/compiler/scheduler/pipe.h @@ -27,17 +27,16 @@ class PipeTask : public Task { private: using InputType = typename PipeType::InputType; InputType input; - PipeType *pipe_ptr; + PipeType* pipe_ptr; static ProfilerRaw& get_task_profiler() { static CachedProfiler cache{demangle(typeid(typename PipeType::PipeFunctionType).name())}; return *cache; } public: - PipeTask(InputType &&input, PipeType *pipe_ptr) : - input(std::move(input)), - pipe_ptr(pipe_ptr) { - } + PipeTask(InputType&& input, PipeType* pipe_ptr) + : input(std::move(input)), + pipe_ptr(pipe_ptr) {} void execute() override { if (NeedProfiler::value) { @@ -52,10 +51,14 @@ class PipeTask : public Task { template class Pipe : public Node { struct have_on_finish_helper { - template struct SFINAE; - template static std::true_type Test(SFINAE *); - template static std::false_type Test(...); + template + struct SFINAE; + template + static std::true_type Test(SFINAE*); + template + static std::false_type Test(...); }; + public: using PipeFunctionType = PipeF; using InputStreamType = InputStreamT; @@ -68,8 +71,8 @@ class Pipe : public Node { using pipe_fun_have_on_finish = decltype(have_on_finish_helper::template Test(0)); private: - InputStreamType *input_stream = nullptr; - OutputStreamType *output_stream = nullptr; + InputStreamType* input_stream = nullptr; + OutputStreamType* output_stream = nullptr; PipeF function; void on_finish(std::true_type) { @@ -84,12 +87,16 @@ class Pipe : public Node { void on_finish(std::false_type) {} public: - explicit Pipe(bool parallel = true) : - Node(parallel) {} + explicit Pipe(bool parallel = true) + : Node(parallel) {} - InputStreamType *&get_input_stream() { return input_stream; } + InputStreamType*& get_input_stream() { + return input_stream; + } - OutputStreamType *&get_output_stream() { return output_stream; } + OutputStreamType*& get_output_stream() { + return output_stream; + } void init_output_stream_if_not_inited() { if (!output_stream) { @@ -97,9 +104,11 @@ class Pipe : public Node { } } - void set_input_stream(InputStreamType *is) { input_stream = is; } + void set_input_stream(InputStreamType* is) { + input_stream = is; + } - Task *get_task() override { + Task* get_task() override { InputType x{}; if (!input_stream->get(x)) { return nullptr; @@ -107,7 +116,7 @@ class Pipe : public Node { return new TaskType(std::move(x), this); } - virtual void process_input(InputType &&input) { + virtual void process_input(InputType&& input) { function.execute(std::move(input), *output_stream); } diff --git a/compiler/scheduler/pipe_with_progress.h b/compiler/scheduler/pipe_with_progress.h index 4a21eb5993..28e4dd2e11 100644 --- a/compiler/scheduler/pipe_with_progress.h +++ b/compiler/scheduler/pipe_with_progress.h @@ -6,9 +6,9 @@ #include "compiler/scheduler/pipe.h" +#include #include #include -#include #include template @@ -29,7 +29,7 @@ struct PipeProgressName { class PipesProgress { public: - static PipesProgress &get() { + static PipesProgress& get() { static PipesProgress this_; return this_; } @@ -65,11 +65,10 @@ class PipesProgress { private: template - void write_progress(const char *name_postfix = "") { + void write_progress(const char* name_postfix = "") { std::lock_guard lock{mutex_}; const size_t percent = *name_postfix ? 100 * ++stages_counter_ / total_stages_ : 100; - std::cerr << "[" << std::setw(3) << percent << "%] " - << PipeProgressName::get() << name_postfix << "\n"; + std::cerr << "[" << std::setw(3) << percent << "%] " << PipeProgressName::get() << name_postfix << "\n"; } template @@ -92,15 +91,15 @@ class PipeWithProgress final : public Pipe { public: using BasePipe::BasePipe; - explicit PipeWithProgress(bool parallel = true) : - BasePipe(parallel) { + explicit PipeWithProgress(bool parallel = true) + : BasePipe(parallel) { PipesProgress::get().register_stage(); if (BasePipe::pipe_fun_have_on_finish::value) { PipesProgress::get().register_stage(); } } - void process_input(typename BasePipe::InputType &&input) final { + void process_input(typename BasePipe::InputType&& input) final { PipesProgress::get().on_pipe_process_input(); BasePipe::process_input(std::move(input)); } diff --git a/compiler/scheduler/scheduler-base.cpp b/compiler/scheduler/scheduler-base.cpp index 1ab866cba5..f99c2f4686 100644 --- a/compiler/scheduler/scheduler-base.cpp +++ b/compiler/scheduler/scheduler-base.cpp @@ -8,20 +8,20 @@ volatile int tasks_before_sync_node; -static SchedulerBase *scheduler; +static SchedulerBase* scheduler; -void set_scheduler(SchedulerBase *new_scheduler) { - assert (scheduler == nullptr); +void set_scheduler(SchedulerBase* new_scheduler) { + assert(scheduler == nullptr); scheduler = new_scheduler; } -void unset_scheduler(SchedulerBase *old_scheduler) { - assert (scheduler == old_scheduler); +void unset_scheduler(SchedulerBase* old_scheduler) { + assert(scheduler == old_scheduler); scheduler = nullptr; } -SchedulerBase *get_scheduler() { - assert (scheduler != nullptr); +SchedulerBase* get_scheduler() { + assert(scheduler != nullptr); return scheduler; } diff --git a/compiler/scheduler/scheduler-base.h b/compiler/scheduler/scheduler-base.h index f5d7c3fbc9..e81fb5a029 100644 --- a/compiler/scheduler/scheduler-base.h +++ b/compiler/scheduler/scheduler-base.h @@ -12,18 +12,18 @@ class SchedulerBase { public: SchedulerBase(); virtual ~SchedulerBase(); - virtual void add_node(Node *node) = 0; - virtual void add_sync_node(Node *node) = 0; - virtual void add_task(Task *task) = 0; + virtual void add_node(Node* node) = 0; + virtual void add_sync_node(Node* node) = 0; + virtual void add_task(Task* task) = 0; virtual void execute() = 0; }; -SchedulerBase *get_scheduler(); -void set_scheduler(SchedulerBase *new_scheduler); -void unset_scheduler(SchedulerBase *old_scheduler); +SchedulerBase* get_scheduler(); +void set_scheduler(SchedulerBase* new_scheduler); +void unset_scheduler(SchedulerBase* old_scheduler); extern volatile int tasks_before_sync_node; -inline void register_async_task(Task *task) { +inline void register_async_task(Task* task) { get_scheduler()->add_task(task); } diff --git a/compiler/scheduler/scheduler.cpp b/compiler/scheduler/scheduler.cpp index 633db5dea0..db63ace969 100644 --- a/compiler/scheduler/scheduler.cpp +++ b/compiler/scheduler/scheduler.cpp @@ -15,25 +15,24 @@ class ThreadContext { pthread_t pthread_id; int thread_id; - class Scheduler *scheduler; + class Scheduler* scheduler; - Node *node; + Node* node; bool run_flag; }; - -void *scheduler_thread_execute(void *arg) { - auto *tls = (ThreadContext *)arg; +void* scheduler_thread_execute(void* arg) { + auto* tls = (ThreadContext*)arg; tls->scheduler->thread_execute(tls); return nullptr; } -Scheduler::Scheduler() : - threads_count(-1) { +Scheduler::Scheduler() + : threads_count(-1) { task_pull = new TaskPull(); } -void Scheduler::add_node(Node *node) { +void Scheduler::add_node(Node* node) { if (node->is_parallel()) { nodes.push_back(node); } else { @@ -41,12 +40,12 @@ void Scheduler::add_node(Node *node) { } } -void Scheduler::add_sync_node(Node *node) { +void Scheduler::add_sync_node(Node* node) { sync_nodes.push(node); } -void Scheduler::add_task(Task *task) { - assert (task_pull != nullptr); +void Scheduler::add_task(Task* task) { + assert(task_pull != nullptr); task_pull->add_task(task); } @@ -55,7 +54,7 @@ void Scheduler::execute() { set_thread_id(0); std::vector threads(threads_count + 1); - assert ((int)one_thread_nodes.size() < threads_count); + assert((int)one_thread_nodes.size() < threads_count); for (int i = 1; i <= threads_count; i++) { threads[i].thread_id = i; threads[i].scheduler = this; @@ -84,18 +83,18 @@ void Scheduler::execute() { pthread_join(threads[i].pthread_id, nullptr); } - for (auto *node : nodes) { + for (auto* node : nodes) { delete node; } } void Scheduler::set_threads_count(int new_threads_count) { - assert (1 <= new_threads_count && new_threads_count <= MAX_THREADS_COUNT); + assert(1 <= new_threads_count && new_threads_count <= MAX_THREADS_COUNT); threads_count = new_threads_count; } -bool Scheduler::thread_process_node(Node *node) { - Task *task = node->get_task(); +bool Scheduler::thread_process_node(Node* node) { + Task* task = node->get_task(); if (task == nullptr) { return false; } @@ -105,10 +104,10 @@ bool Scheduler::thread_process_node(Node *node) { return true; } -void Scheduler::thread_execute(ThreadContext *tls) { +void Scheduler::thread_execute(ThreadContext* tls) { set_thread_id(tls->thread_id); - auto process_node = [this](Node *node) { + auto process_node = [this](Node* node) { bool at_least_one_task_executed = false; while (thread_process_node(node)) { at_least_one_task_executed = true; diff --git a/compiler/scheduler/scheduler.h b/compiler/scheduler/scheduler.h index 4c176803bb..2766ba2b1f 100644 --- a/compiler/scheduler/scheduler.h +++ b/compiler/scheduler/scheduler.h @@ -14,22 +14,22 @@ class ThreadContext; class Scheduler : public SchedulerBase { private: - std::vector nodes; - std::vector one_thread_nodes; - std::queue sync_nodes; + std::vector nodes; + std::vector one_thread_nodes; + std::queue sync_nodes; int threads_count; - TaskPull *task_pull; + TaskPull* task_pull; - bool thread_process_node(Node *node); - void thread_execute(ThreadContext *tls); - friend void *scheduler_thread_execute(void *arg); + bool thread_process_node(Node* node); + void thread_execute(ThreadContext* tls); + friend void* scheduler_thread_execute(void* arg); public: Scheduler(); - void add_node(Node *node) override; - void add_sync_node(Node *node) override; - void add_task(Task *task) override; + void add_node(Node* node) override; + void add_sync_node(Node* node) override; + void add_task(Task* task) override; void execute() override; void set_threads_count(int new_threads_count); diff --git a/compiler/scheduler/task-pull.h b/compiler/scheduler/task-pull.h index 3d09ed70d4..73b9c17020 100644 --- a/compiler/scheduler/task-pull.h +++ b/compiler/scheduler/task-pull.h @@ -11,14 +11,15 @@ class Task; class TaskPull : public Node { private: - DataStream stream; + DataStream stream; + public: - inline void add_task(Task *task) { + inline void add_task(Task* task) { stream << task; } - Task *get_task() override { - Task *x = nullptr; + Task* get_task() override { + Task* x = nullptr; if (!stream.get(x)) { return nullptr; } diff --git a/compiler/stage.cpp b/compiler/stage.cpp index 31db92603a..f11d6a1066 100644 --- a/compiler/stage.cpp +++ b/compiler/stage.cpp @@ -16,36 +16,36 @@ int stage::warnings_count; -const char *get_assert_level_desc(AssertLevelT assert_level) { +const char* get_assert_level_desc(AssertLevelT assert_level) { switch (assert_level) { - case WRN_ASSERT_LEVEL: - return "Warning"; - case CE_ASSERT_LEVEL: - return "Compilation error"; - case NOTICE_ASSERT_LEVEL: - return "Notice"; - case FATAL_ASSERT_LEVEL: - return "Fatal error"; - default: - assert (0); + case WRN_ASSERT_LEVEL: + return "Warning"; + case CE_ASSERT_LEVEL: + return "Compilation error"; + case NOTICE_ASSERT_LEVEL: + return "Notice"; + case FATAL_ASSERT_LEVEL: + return "Fatal error"; + default: + assert(0); } } volatile int ce_locker; namespace { -FILE *warning_file{nullptr}; +FILE* warning_file{nullptr}; } -void stage::set_warning_file(FILE *file) noexcept { +void stage::set_warning_file(FILE* file) noexcept { warning_file = file; } -void on_compilation_error(const char *description __attribute__((unused)), const char *file_name, int line_number, - const char *full_description, AssertLevelT assert_level) { +void on_compilation_error(const char* description __attribute__((unused)), const char* file_name, int line_number, const char* full_description, + AssertLevelT assert_level) { - AutoLocker locker(&ce_locker); - FILE *file = stdout; + AutoLocker locker(&ce_locker); + FILE* file = stdout; if (assert_level == WRN_ASSERT_LEVEL && warning_file) { file = warning_file; } @@ -60,7 +60,7 @@ void on_compilation_error(const char *description __attribute__((unused)), const "It is probably happened due to incorrect or unsupported PHP input.\n" "But it is still bug in compiler.\n"); #ifdef __arm64__ - __builtin_debugtrap(); // for easier debugging kphp_assert / kphp_fail + __builtin_debugtrap(); // for easier debugging kphp_assert / kphp_fail #endif abort(); } @@ -73,7 +73,6 @@ void on_compilation_error(const char *description __attribute__((unused)), const fflush(file); } - void Location::set_file(SrcFilePtr new_file) { file = new_file; function = FunctionPtr(); @@ -92,10 +91,10 @@ void Location::set_line(int new_line) { line = new_line; } -Location::Location(const SrcFilePtr &file, const FunctionPtr &function, int line) : - file(file), - function(function), - line(line) {} +Location::Location(const SrcFilePtr& file, const FunctionPtr& function, int line) + : file(file), + function(function), + line(line) {} // return a location in the format: "{file}:{line} in {function}" std::string Location::as_human_readable() const { @@ -107,7 +106,7 @@ std::string Location::as_human_readable() const { // if it's a method of an PSR-4 class /path/to/A.php, output only A::methodName, not fully-qualified path\to\A::methodName // if we are inside a lambda, print out the outermost named function - const auto *f_outer = function ? function->get_this_or_topmost_if_lambda() : nullptr; + const auto* f_outer = function ? function->get_this_or_topmost_if_lambda() : nullptr; if (f_outer && f_outer->type == FunctionData::func_local) { std::string function_name = f_outer->as_human_readable(); std::string psr4_file_name = replace_characters(function_name.substr(0, function_name.find(':')), '\\', '/') + ".php"; @@ -121,7 +120,7 @@ std::string Location::as_human_readable() const { return out; } -bool operator<(const Location &lhs, const Location &rhs) { +bool operator<(const Location& lhs, const Location& rhs) { if (lhs.file && rhs.file) { if (const int cmp = lhs.file->file_name.compare(rhs.file->file_name)) { return cmp < 0; @@ -142,7 +141,7 @@ namespace stage { static TLS stage_info; } // namespace stage -void stage::print_current_location_on_error(FILE *f) { +void stage::print_current_location_on_error(FILE* f) { bool use_colors = should_be_colored(f); Location location = get_location(); @@ -163,7 +162,7 @@ void stage::print_current_location_on_error(FILE *f) { } } -stage::StageInfo *stage::get_stage_info_ptr() { +stage::StageInfo* stage::get_stage_info_ptr() { return &*stage_info; } @@ -171,7 +170,7 @@ void stage::set_exit_code(ExitCode code) { get_stage_info_ptr()->exit_code = code; } -void stage::set_name(std::string &&name) { +void stage::set_name(std::string&& name) { get_stage_info_ptr()->name = std::move(name); get_stage_info_ptr()->cnt_errors = 0; } @@ -201,7 +200,7 @@ void stage::die_if_global_errors() { } } -const std::string &stage::get_name() { +const std::string& stage::get_name() { return get_stage_info_ptr()->name; } @@ -209,15 +208,15 @@ ExitCode stage::get_exit_code() { return get_stage_info_ptr()->exit_code; } -Location *stage::get_location_ptr() { +Location* stage::get_location_ptr() { return &get_stage_info_ptr()->location; } -const Location &stage::get_location() { +const Location& stage::get_location() { return *get_location_ptr(); } -void stage::set_location(const Location &new_location) { +void stage::set_location(const Location& new_location) { if (!new_location.get_file()) { return; } @@ -248,7 +247,7 @@ int stage::get_line() { return get_location().get_line(); } -const std::string &stage::get_function_name() { +const std::string& stage::get_function_name() { static std::string no_function = "unknown"; FunctionPtr function = get_function(); if (!function) { @@ -257,15 +256,16 @@ const std::string &stage::get_function_name() { return function->name; } -bool stage::should_be_colored(FILE *f) { - if (!G) return TermStringFormat::is_terminal(f); +bool stage::should_be_colored(FILE* f) { + if (!G) + return TermStringFormat::is_terminal(f); switch (G->settings().get_color_settings()) { - case CompilerSettings::colored: - return true; - case CompilerSettings::not_colored: - return false; - case CompilerSettings::auto_colored: - default: - return TermStringFormat::is_terminal(f); + case CompilerSettings::colored: + return true; + case CompilerSettings::not_colored: + return false; + case CompilerSettings::auto_colored: + default: + return TermStringFormat::is_terminal(f); } } diff --git a/compiler/stage.h b/compiler/stage.h index de1fea19bf..db2536be2c 100644 --- a/compiler/stage.h +++ b/compiler/stage.h @@ -13,13 +13,14 @@ #include "compiler/kphp_assert.h" #include "compiler/location.h" -inline void on_compilation_error(const char *description, const char *file_name, int line_number, const std::string &full_description, AssertLevelT assert_level) { +inline void on_compilation_error(const char* description, const char* file_name, int line_number, const std::string& full_description, + AssertLevelT assert_level) { on_compilation_error(description, file_name, line_number, full_description.c_str(), assert_level); } namespace stage { -void set_warning_file(FILE *file) noexcept; +void set_warning_file(FILE* file) noexcept; struct StageInfo { std::string name; @@ -29,21 +30,21 @@ struct StageInfo { ExitCode exit_code = ExitCode::KPHP_TO_CPP_STAGE; }; -StageInfo *get_stage_info_ptr(); +StageInfo* get_stage_info_ptr(); void error(); bool has_error(); bool has_global_error(); void die_if_global_errors(); -Location *get_location_ptr(); -const Location &get_location(); -void set_location(const Location &new_location); +Location* get_location_ptr(); +const Location& get_location(); +void set_location(const Location& new_location); -void print_current_location_on_error(FILE *f); +void print_current_location_on_error(FILE* f); -void set_name(std::string &&name); -const std::string &get_name(); +void set_name(std::string&& name); +const std::string& get_name(); void set_exit_code(ExitCode code); ExitCode get_exit_code(); @@ -55,10 +56,8 @@ SrcFilePtr get_file(); FunctionPtr get_function(); int get_line(); -const std::string &get_function_name(); -bool should_be_colored(FILE *f); +const std::string& get_function_name(); +bool should_be_colored(FILE* f); extern int warnings_count; } // namespace stage - - diff --git a/compiler/stats.cpp b/compiler/stats.cpp index 86bfb04207..250724bf63 100644 --- a/compiler/stats.cpp +++ b/compiler/stats.cpp @@ -10,29 +10,29 @@ void Stats::on_var_inserting(VarData::Type type) { switch (type) { - case VarData::var_local_t: - ++local_vars_; - break; - case VarData::var_local_inplace_t: - ++local_inplace_vars_; - break; - case VarData::var_global_t: - ++global_vars_; - break; - case VarData::var_param_t: - ++param_vars_; - break; - case VarData::var_const_t: - ++global_const_vars_; - break; - case VarData::var_static_t: - ++static_vars_; - break; - case VarData::var_instance_t: - ++instance_vars_; - break; - default: - break; + case VarData::var_local_t: + ++local_vars_; + break; + case VarData::var_local_inplace_t: + ++local_inplace_vars_; + break; + case VarData::var_global_t: + ++global_vars_; + break; + case VarData::var_param_t: + ++param_vars_; + break; + case VarData::var_const_t: + ++global_const_vars_; + break; + case VarData::var_static_t: + ++static_vars_; + break; + case VarData::var_instance_t: + ++instance_vars_; + break; + default: + break; } } @@ -58,9 +58,9 @@ void Stats::update_memory_stats() { memory_rss_peak_ = mem_info.rss_peak; } -void Stats::write_to(std::ostream &out, bool with_indent) const { - const char *indent = with_indent ? " " : ""; - const char *block_sep = with_indent ? "\n" : ""; +void Stats::write_to(std::ostream& out, bool with_indent) const { + const char* indent = with_indent ? " " : ""; + const char* block_sep = with_indent ? "\n" : ""; out << indent << "classes.total: " << total_classes << std::endl; out << indent << "classes.total_lambdas: " << total_lambdas << std::endl; out << block_sep; @@ -112,7 +112,7 @@ void Stats::write_to(std::ostream &out, bool with_indent) const { out << indent << "hash_tables.total_composer_jsons: " << ht_total_composer_jsons << std::endl; out << block_sep; out << std::fixed; - for (const auto &prof : profiler_stats) { + for (const auto& prof : profiler_stats) { std::string name = prof.first; std::replace_if(name.begin(), name.end(), [](char c) { return !std::isalnum(c); }, '_'); out << "pipes." << name << ".working_time: " << std::chrono::duration(prof.second.get_working_time()).count() << std::endl; diff --git a/compiler/stats.h b/compiler/stats.h index 5639ed2406..070c0f15ba 100644 --- a/compiler/stats.h +++ b/compiler/stats.h @@ -17,7 +17,7 @@ class Stats { void update_memory_stats(); - void write_to(std::ostream &out, bool with_indent = true) const; + void write_to(std::ostream& out, bool with_indent = true) const; std::atomic total_classes{0u}; std::atomic total_lambdas{0u}; @@ -73,5 +73,3 @@ class Stats { std::atomic memory_rss_{0}; std::atomic memory_rss_peak_{0}; }; - - diff --git a/compiler/threading/allocator.cpp b/compiler/threading/allocator.cpp index 9354a8bae1..6bfe8a9f30 100644 --- a/compiler/threading/allocator.cpp +++ b/compiler/threading/allocator.cpp @@ -7,8 +7,8 @@ #include #include -#include "common/sanitizer.h" #include "common/container_of.h" +#include "common/sanitizer.h" #include "common/wrappers/likely.h" #include "compiler/threading/tls.h" @@ -23,7 +23,7 @@ extern decltype(realloc) __libc_realloc; struct block_t { union { size_t size; - block_t *next; + block_t* next; }; char data[0]; }; @@ -32,9 +32,9 @@ struct block_t { class ZAllocatorRaw { private: - char *buf{nullptr}; + char* buf{nullptr}; size_t left{0}; - block_t *free_blocks[MAX_BLOCK_SIZE >> 3]{nullptr}; + block_t* free_blocks[MAX_BLOCK_SIZE >> 3]{nullptr}; size_t memory_usage{0}; size_t memory_total_allocated{0}; @@ -47,31 +47,31 @@ class ZAllocatorRaw { return memory_total_allocated; } - block_t *to_block(void *ptr) { + block_t* to_block(void* ptr) { return container_of(ptr, block_t, data); } - void *from_block(block_t *block) { + void* from_block(block_t* block) { return &block->data; } - block_t *block_alloc(size_t size) { - size_t block_size = size + offsetof (block_t, data); - block_t *res; + block_t* block_alloc(size_t size) { + size_t block_size = size + offsetof(block_t, data); + block_t* res; if (size >= MAX_BLOCK_SIZE) { - res = (block_t *)__libc_malloc(block_size); + res = (block_t*)__libc_malloc(block_size); } else { size_t bucket_id = size >> 3; if (free_blocks[bucket_id] != nullptr) { res = free_blocks[bucket_id]; free_blocks[bucket_id] = res->next; } else { - if (unlikely (left < block_size)) { - assert (malloc != __libc_malloc); - buf = (char *)__libc_malloc(1 << 26); + if (unlikely(left < block_size)) { + assert(malloc != __libc_malloc); + buf = (char*)__libc_malloc(1 << 26); left = 1 << 26; } - res = (block_t *)buf; + res = (block_t*)buf; buf += block_size; left -= block_size; } @@ -82,7 +82,7 @@ class ZAllocatorRaw { return res; } - void block_free(block_t *block) { + void block_free(block_t* block) { memory_usage -= block->size; if (block->size >= MAX_BLOCK_SIZE) { __libc_free(block); @@ -93,14 +93,14 @@ class ZAllocatorRaw { } } - inline void *alloc(size_t size) { + inline void* alloc(size_t size) { size = (size + 7) & -8; - block_t *block = block_alloc(size); + block_t* block = block_alloc(size); return from_block(block); } - inline void *realloc(void *ptr, size_t new_size) { + inline void* realloc(void* ptr, size_t new_size) { if (ptr == nullptr) { return alloc(new_size); } @@ -108,48 +108,48 @@ class ZAllocatorRaw { free(ptr); return nullptr; } - block_t *block = to_block(ptr); + block_t* block = to_block(ptr); size_t old_size = block->size; - void *res = alloc(new_size); + void* res = alloc(new_size); memcpy(res, ptr, std::min(old_size, new_size)); block_free(block); return res; } - inline void *calloc(size_t size_a, size_t size_b) { + inline void* calloc(size_t size_a, size_t size_b) { size_t size = size_a * size_b; - void *res = alloc(size); + void* res = alloc(size); memset(res, 0, size); return res; } - inline void free(void *ptr) { + inline void free(void* ptr) { if (ptr == nullptr) { return; } - block_t *block = to_block(ptr); + block_t* block = to_block(ptr); block_free(block); } }; static TLS zallocator; -void *malloc(size_t size) { - assert (malloc != __libc_malloc); +void* malloc(size_t size) { + assert(malloc != __libc_malloc); return zallocator->alloc(size); } -void *calloc(size_t size_a, size_t size_b) { +void* calloc(size_t size_a, size_t size_b) { return zallocator->calloc(size_a, size_b); } -void *realloc(void *ptr, size_t size) { +void* realloc(void* ptr, size_t size) { return zallocator->realloc(ptr, size); } -__attribute__((error("memalign function is assert(0), don't use it"))) -void *memalign(size_t aligment __attribute__((unused)), size_t size __attribute__((unused))) { - assert (0); +__attribute__((error("memalign function is assert(0), don't use it"))) void* memalign(size_t aligment __attribute__((unused)), + size_t size __attribute__((unused))) { + assert(0); return nullptr; } -void free(void *ptr) { +void free(void* ptr) { return zallocator->free(ptr); } } diff --git a/compiler/threading/data-stream.h b/compiler/threading/data-stream.h index 03e285c184..947ee63d2e 100644 --- a/compiler/threading/data-stream.h +++ b/compiler/threading/data-stream.h @@ -21,12 +21,10 @@ class DataStream { template using NthDataType = DataType; - explicit DataStream(bool is_sink = false) : - is_sink_mode_(is_sink) - { - } + explicit DataStream(bool is_sink = false) + : is_sink_mode_(is_sink) {} - bool get(DataType &result) { + bool get(DataType& result) { std::lock_guard lock{mutex_}; if (!queue_.empty()) { result = std::move(queue_.front()); @@ -60,34 +58,33 @@ class DataStream { const bool is_sink_mode_; }; - struct EmptyStream { template using NthDataType = EmptyStream; }; -template +template class MultipleDataStreams { private: - std::tuple *...> streams_; + std::tuple*...> streams_; public: template using NthDataType = vk::get_nth_type; template - decltype(std::get(streams_)) &project_to_nth_data_stream() { + decltype(std::get(streams_))& project_to_nth_data_stream() { return std::get(streams_); } template - DataStream *&project_to_single_data_stream() { + DataStream*& project_to_single_data_stream() { constexpr size_t data_id = vk::index_of_type::value; return std::get(streams_); } template - void operator<<(const DataType &data) { + void operator<<(const DataType& data) { *project_to_single_data_stream() << data; } }; diff --git a/compiler/threading/hash-table.h b/compiler/threading/hash-table.h index a70f0cc179..02b95915a5 100644 --- a/compiler/threading/hash-table.h +++ b/compiler/threading/hash-table.h @@ -16,22 +16,21 @@ class TSHashTable { unsigned long long hash; T data; - HTNode() : - hash(0), - data() { - } + HTNode() + : hash(0), + data() {} }; private: - HTNode *nodes; + HTNode* nodes; int used_size; + public: - TSHashTable() : - nodes(new HTNode[N]), - used_size(0) { - } + TSHashTable() + : nodes(new HTNode[N]), + used_size(0) {} - HTNode *at(unsigned long long hash) { + HTNode* at(unsigned long long hash) { int i = (unsigned)hash % (unsigned)N; while (true) { while (nodes[i].hash != 0 && nodes[i].hash != hash) { @@ -50,7 +49,7 @@ class TSHashTable { return &nodes[i]; } - const T *find(unsigned long long hash) { + const T* find(unsigned long long hash) { int i = (unsigned)hash % (unsigned)N; while (nodes[i].hash != 0 && nodes[i].hash != hash) { i++; @@ -85,7 +84,7 @@ class TSHashTable { } template - std::vector get_all_if(const CondF &callbackF) { + std::vector get_all_if(const CondF& callbackF) { std::vector res; for (int i = 0; i < N; i++) { if (nodes[i].hash != 0 && callbackF(nodes[i].data)) { diff --git a/compiler/threading/locks.h b/compiler/threading/locks.h index e90fb041fe..a866bb27ef 100644 --- a/compiler/threading/locks.h +++ b/compiler/threading/locks.h @@ -20,17 +20,17 @@ void unlock(T locker) { locker->unlock(); } -inline bool try_lock(volatile int *locker) { +inline bool try_lock(volatile int* locker) { return __sync_lock_test_and_set(locker, 1) == 0; } -inline void lock(volatile int *locker) { +inline void lock(volatile int* locker) { while (!try_lock(locker)) { usleep(250); } } -inline void unlock(volatile int *locker) { +inline void unlock(volatile int* locker) { assert(*locker == 1); __sync_lock_release(locker); } @@ -38,9 +38,10 @@ inline void unlock(volatile int *locker) { class Lockable { private: volatile int x; + public: - Lockable() : - x(0) {} + Lockable() + : x(0) {} virtual ~Lockable() = default; @@ -57,9 +58,10 @@ template class AutoLocker { private: DataT ptr; + public: - explicit AutoLocker(DataT ptr) : - ptr(ptr) { + explicit AutoLocker(DataT ptr) + : ptr(ptr) { lock(ptr); } diff --git a/compiler/threading/profiler.cpp b/compiler/threading/profiler.cpp index 8ea6a8bc71..c023f7a8e6 100644 --- a/compiler/threading/profiler.cpp +++ b/compiler/threading/profiler.cpp @@ -17,7 +17,7 @@ std::unordered_map collect_profiler_stats() { std::unordered_map collected; for (int i = 0; i <= MAX_THREADS_COUNT; i++) { - for (const auto &raw : profiler.get(i)) { + for (const auto& raw : profiler.get(i)) { if (raw.second.get_calls() > 0) { collected[raw.first] += raw.second; } @@ -49,23 +49,17 @@ std::string pretty_time(std::chrono::nanoseconds t) { if (std::chrono::milliseconds{1} > t) { return TermStringFormat::paint(" > 0.001 sec", TermStringFormat::grey); } - const auto color = t > std::chrono::seconds{10} - ? TermStringFormat::red - : t > std::chrono::seconds{1} - ? TermStringFormat::yellow - : TermStringFormat::green; + const auto color = t > std::chrono::seconds{10} ? TermStringFormat::red : t > std::chrono::seconds{1} ? TermStringFormat::yellow : TermStringFormat::green; t -= t % std::chrono::milliseconds{1}; return TermStringFormat::paint(fmt_format("{: >8.3f} sec", std::chrono::duration(t).count()), color); } -void profiler_print_all(const std::unordered_map &collected) { +void profiler_print_all(const std::unordered_map& collected) { std::vector> all{collected.begin(), collected.end()}; - std::sort(all.begin(), all.end(), [](const auto &a, const auto &b) { - return a.second.print_id < b.second.print_id; - }); + std::sort(all.begin(), all.end(), [](const auto& a, const auto& b) { return a.second.print_id < b.second.print_id; }); size_t name_width = 0; - for (const auto &prof : all) { + for (const auto& prof : all) { name_width = std::max(name_width, prof.first.size()); } @@ -76,31 +70,23 @@ void profiler_print_all(const std::unordered_map &coll "-{2:-^{0}}-\n" "|{3: ^{1}}|{4: ^9}|{5: ^14}|{6: ^14}|{7: ^12}|{8: ^12}|\n" "-{2:-^{0}}-\n", - name_width + table_fixed_size, name_width, - "", "Name", "Calls", "Working time", "Duration", "Memory", "Allocated"); + name_width + table_fixed_size, name_width, "", "Name", "Calls", "Working time", "Duration", "Memory", "Allocated"); - for (const auto &prof : all) { - fmt_fprintf(stderr, - "|{1: ^{0}}|{2: >8} | {3: >12} | {4: >12} | {5: >10} | {6: >10} |\n", - name_width, - prof.first, - prof.second.get_calls(), - pretty_time(prof.second.get_working_time()), - pretty_time(prof.second.get_duration()), - pretty_memory(prof.second.get_memory_usage()), - pretty_memory(prof.second.get_memory_total_allocated()) - ); + for (const auto& prof : all) { + fmt_fprintf(stderr, "|{1: ^{0}}|{2: >8} | {3: >12} | {4: >12} | {5: >10} | {6: >10} |\n", name_width, prof.first, prof.second.get_calls(), + pretty_time(prof.second.get_working_time()), pretty_time(prof.second.get_duration()), pretty_memory(prof.second.get_memory_usage()), + pretty_memory(prof.second.get_memory_total_allocated())); } fmt_fprintf(stderr, "-{0:-^{1}}-\n", "", name_width + table_fixed_size); } -ProfilerRaw &get_profiler(const std::string &name) { +ProfilerRaw& get_profiler(const std::string& name) { return (*profiler)[name]; } -std::string demangle(const char *name) { +std::string demangle(const char* name) { int status; - char *demangled = abi::__cxa_demangle(name, nullptr, nullptr, &status); + char* demangled = abi::__cxa_demangle(name, nullptr, nullptr, &status); std::string result = demangled; free(demangled); return result; diff --git a/compiler/threading/profiler.h b/compiler/threading/profiler.h index e132509b6c..fa6bf2d5fa 100644 --- a/compiler/threading/profiler.h +++ b/compiler/threading/profiler.h @@ -75,7 +75,7 @@ class ProfilerRaw { return calls_; } - ProfilerRaw &operator+=(const ProfilerRaw &other) noexcept { + ProfilerRaw& operator+=(const ProfilerRaw& other) noexcept { calls_ += other.calls_; working_time_ += other.working_time_; min_time_ = std::min(min_time_, other.min_time_); @@ -87,30 +87,28 @@ class ProfilerRaw { } }; -ProfilerRaw &get_profiler(const std::string &name); +ProfilerRaw& get_profiler(const std::string& name); std::unordered_map collect_profiler_stats(); -void profiler_print_all(const std::unordered_map &collected); - -std::string demangle(const char *name); +void profiler_print_all(const std::unordered_map& collected); +std::string demangle(const char* name); class CachedProfiler : vk::not_copyable { - TLS raws_; + TLS raws_; std::string name_; public: - explicit CachedProfiler(std::string name) : - name_(std::move(name)) { - } + explicit CachedProfiler(std::string name) + : name_(std::move(name)) {} - ProfilerRaw &operator*() { + ProfilerRaw& operator*() { return *operator->(); } - ProfilerRaw *operator->() { - auto *raw = *raws_; + ProfilerRaw* operator->() { + auto* raw = *raws_; if (raw == nullptr) { raw = &get_profiler(name_); *raws_ = raw; @@ -121,11 +119,11 @@ class CachedProfiler : vk::not_copyable { class AutoProfiler : vk::not_copyable { private: - ProfilerRaw &prof_; + ProfilerRaw& prof_; public: - explicit AutoProfiler(ProfilerRaw &prof) : - prof_(prof) { + explicit AutoProfiler(ProfilerRaw& prof) + : prof_(prof) { prof_.start(); } @@ -133,4 +131,3 @@ class AutoProfiler : vk::not_copyable { prof_.finish(); } }; - diff --git a/compiler/threading/tls.h b/compiler/threading/tls.h index 0b0f2a83f8..edfac63ff1 100644 --- a/compiler/threading/tls.h +++ b/compiler/threading/tls.h @@ -35,34 +35,32 @@ struct TLS { // Therefore, the system requires a total of MAX_THREADS_CNT + 2 threads to be available. TLSRaw arr[MAX_THREADS_COUNT + 2]; - TLSRaw *get_raw(int id) { + TLSRaw* get_raw(int id) { assert(0 <= id && id <= 1 + MAX_THREADS_COUNT); return &arr[id]; } - TLSRaw *get_raw() { + TLSRaw* get_raw() { return get_raw(get_thread_id()); } public: - TLS() : - arr() { - } - + TLS() + : arr() {} - T &get() { + T& get() { return get_raw()->data; } - T &get(int i) { + T& get(int i) { return get_raw(i)->data; } - T *operator->() { + T* operator->() { return &get(); } - T &operator*() { + T& operator*() { return get(); } @@ -70,15 +68,15 @@ struct TLS { return MAX_THREADS_COUNT + 1; } - T *lock_get() { - TLSRaw *raw = get_raw(); + T* lock_get() { + TLSRaw* raw = get_raw(); bool ok = try_lock(&raw->locker); assert(ok); return &raw->data; } - void unlock_get(T *ptr) { - TLSRaw *raw = get_raw(); + void unlock_get(T* ptr) { + TLSRaw* raw = get_raw(); assert(&raw->data == ptr); unlock(&raw->locker); } diff --git a/compiler/tl-classes.cpp b/compiler/tl-classes.cpp index d33b049fba..02ca2faf20 100644 --- a/compiler/tl-classes.cpp +++ b/compiler/tl-classes.cpp @@ -9,21 +9,19 @@ #include "compiler/stage.h" -void TlClasses::load_from(const std::string &tlo_schema, bool generate_tl_internals) { +void TlClasses::load_from(const std::string& tlo_schema, bool generate_tl_internals) { auto parsing_result = vk::tlo_parsing::parse_tlo(tlo_schema.c_str(), true); - kphp_error_return(parsing_result.parsed_schema, - fmt_format("Error while reading tlo: {}", parsing_result.error)); + kphp_error_return(parsing_result.parsed_schema, fmt_format("Error while reading tlo: {}", parsing_result.error)); std::unique_ptr scheme = std::move(parsing_result.parsed_schema); try { vk::tlo_parsing::replace_anonymous_args(*scheme); vk::tlo_parsing::perform_flat_optimization(*scheme); vk::tlo_parsing::tl_scheme_final_check(*scheme); - } catch (const std::exception &ex) { + } catch (const std::exception& ex) { kphp_error_return(false, ex.what()); } scheme_ = std::move(scheme); php_classes_.load_from(*scheme_, generate_tl_internals); } - diff --git a/compiler/tl-classes.h b/compiler/tl-classes.h index 6e1c08044c..fc7c980207 100644 --- a/compiler/tl-classes.h +++ b/compiler/tl-classes.h @@ -11,10 +11,14 @@ class TlClasses { public: - void load_from(const std::string &tlo_schema, bool generate_tl_internals); + void load_from(const std::string& tlo_schema, bool generate_tl_internals); - const std::unique_ptr &get_scheme() const { return scheme_; } - const vk::tl::PhpClasses &get_php_classes() const { return php_classes_; } + const std::unique_ptr& get_scheme() const { + return scheme_; + } + const vk::tl::PhpClasses& get_php_classes() const { + return php_classes_; + } private: std::unique_ptr scheme_; diff --git a/compiler/token.h b/compiler/token.h index 8303527035..7480187ae9 100644 --- a/compiler/token.h +++ b/compiler/token.h @@ -200,29 +200,30 @@ class Token { vk::string_view str_val; vk::string_view debug_str; - explicit Token(TokenType type) : - type_(type) { - } + explicit Token(TokenType type) + : type_(type) {} - Token(TokenType type_, vk::string_view s) : - type_(type_), - str_val(s) { - } + Token(TokenType type_, vk::string_view s) + : type_(type_), + str_val(s) {} - Token(TokenType type_, const char *s, const char *t) : - type_(type_), - str_val(s, t) { - } + Token(TokenType type_, const char* s, const char* t) + : type_(type_), + str_val(s, t) {} // use 'cur->debugPrint()' anywhere in gentree while development // (in release it's not used and is not linked to a binary) void debugPrint() const { - std::string debugTokenName(TokenType t); // implemented in debug.cpp + std::string debugTokenName(TokenType t); // implemented in debug.cpp printf("%s '%s'\n", debugTokenName(type_).c_str(), static_cast(debug_str.empty() ? str_val : debug_str).c_str()); } - inline TokenType &type() { return type_; } - inline const TokenType &type() const { return type_; } + inline TokenType& type() { + return type_; + } + inline const TokenType& type() const { + return type_; + } std::string to_str() const { return static_cast(debug_str); diff --git a/compiler/type-hint.cpp b/compiler/type-hint.cpp index 4b19b1da1a..449cfd96d0 100644 --- a/compiler/type-hint.cpp +++ b/compiler/type-hint.cpp @@ -9,12 +9,11 @@ #include "common/php-functions.h" #include "compiler/data/class-data.h" -#include "compiler/data/function-data.h" #include "compiler/data/ffi-data.h" +#include "compiler/data/function-data.h" #include "compiler/lambda-utils.h" #include "compiler/name-gen.h" - /** * This class stores a big hashtable [hash => TypeHint] * Every TypeHint*::create() method at first looks up here, and allocates an object only if not found. @@ -23,35 +22,35 @@ class HasherOfTypeHintForOptimization { uint64_t cur_hash; - static TSHashTable all_type_hints_ht; + static TSHashTable all_type_hints_ht; public: explicit HasherOfTypeHintForOptimization(uint64_t hash_of_type_hint_class_name) - : cur_hash(hash_of_type_hint_class_name) {} + : cur_hash(hash_of_type_hint_class_name) {} void feed_hash(uint64_t val) { cur_hash = cur_hash * 56235515617499ULL + val; } - void feed_string(const std::string &s) { + void feed_string(const std::string& s) { feed_hash(string_hash(s.c_str(), s.size())); } - void feed_inner(const TypeHint *inner) { + void feed_inner(const TypeHint* inner) { feed_hash(inner->hash); } - const TypeHint *get_existing() const __attribute__((flatten)) { - const auto *result = all_type_hints_ht.find(cur_hash); + const TypeHint* get_existing() const __attribute__((flatten)) { + const auto* result = all_type_hints_ht.find(cur_hash); return result ? *result : nullptr; } - const TypeHint *add_because_doesnt_exist(TypeHint *newly_created) const __attribute__((noinline)) { - TSHashTable::HTNode *node = all_type_hints_ht.at(cur_hash); - AutoLocker locker(node); + const TypeHint* add_because_doesnt_exist(TypeHint* newly_created) const __attribute__((noinline)) { + TSHashTable::HTNode* node = all_type_hints_ht.at(cur_hash); + AutoLocker locker(node); if (!node->data) { newly_created->hash = cur_hash; - newly_created->traverse([&newly_created](const TypeHint *child) { + newly_created->traverse([&newly_created](const TypeHint* child) { newly_created->flags |= child->flags; // parent's flags are merged child flags (which were already calculated up to here) }); node->data = newly_created; @@ -64,26 +63,23 @@ class HasherOfTypeHintForOptimization { } }; - -TSHashTable HasherOfTypeHintForOptimization::all_type_hints_ht; - +TSHashTable HasherOfTypeHintForOptimization::all_type_hints_ht; // -------------------------------------------- - -const TypeData *TypeHint::to_type_data() const { +const TypeData* TypeHint::to_type_data() const { kphp_assert(is_typedata_constexpr()); if (!cached_typedata_if_constexpr) { - TypeData *dst = TypeData::get_type(tp_any)->clone(); + TypeData* dst = TypeData::get_type(tp_any)->clone(); recalc_type_data_in_context_of_call(dst, {}); // call = {}, as constexpr recalculation will never access it cached_typedata_if_constexpr = dst; } return cached_typedata_if_constexpr; } -const TypeHint *TypeHint::unwrap_optional() const { - if (const auto *as_optional = this->try_as()) { +const TypeHint* TypeHint::unwrap_optional() const { + if (const auto* as_optional = this->try_as()) { return as_optional->inner; } return this; @@ -94,13 +90,13 @@ ClassPtr TypeHintInstance::resolve_and_set_klass() const { return klass = G->get_class(full_class_name); } -const TypeHint *TypeHintRefToField::resolve_field_type_hint() const { - if (const auto *inner_instance = inner->unwrap_optional()->try_as()) { +const TypeHint* TypeHintRefToField::resolve_field_type_hint() const { + if (const auto* inner_instance = inner->unwrap_optional()->try_as()) { if (ClassPtr inner_resolved = inner_instance->resolve()) { - if (const ClassMemberInstanceField *member = inner_resolved->get_instance_field(field_name)) { + if (const ClassMemberInstanceField* member = inner_resolved->get_instance_field(field_name)) { return member->type_hint ?: TypeHintPrimitive::create(tp_any); } - if (const ClassMemberStaticField *member = inner_resolved->get_static_field(field_name)) { + if (const ClassMemberStaticField* member = inner_resolved->get_static_field(field_name)) { return member->type_hint ?: TypeHintPrimitive::create(tp_any); } } @@ -109,12 +105,12 @@ const TypeHint *TypeHintRefToField::resolve_field_type_hint() const { } FunctionPtr TypeHintRefToMethod::resolve_method() const { - if (const auto *inner_instance = inner->unwrap_optional()->try_as()) { + if (const auto* inner_instance = inner->unwrap_optional()->try_as()) { if (ClassPtr inner_resolved = inner_instance->resolve()) { - if (const ClassMemberInstanceMethod *member = inner_resolved->get_instance_method(method_name)) { + if (const ClassMemberInstanceMethod* member = inner_resolved->get_instance_method(method_name)) { return member->function; } - if (const ClassMemberStaticMethod *member = inner_resolved->members.get_static_method(method_name)) { + if (const ClassMemberStaticMethod* member = inner_resolved->members.get_static_method(method_name)) { return member->function; } } @@ -134,8 +130,8 @@ ClassPtr TypeHintCallable::get_lambda_class() const { return f_bound_to && f_bound_to->is_lambda() && f_bound_to->class_id && f_bound_to->class_id->is_lambda_class() ? f_bound_to->class_id : ClassPtr{}; } -const TypeHint *TypeHintShape::find_at(const std::string &key) const { - for (const auto &p : items) { +const TypeHint* TypeHintShape::find_at(const std::string& key) const { + for (const auto& p : items) { if (p.first == key) { return p.second; } @@ -152,7 +148,7 @@ void TypeHintShape::register_known_key(std::int64_t key_hash, std::string_view k shape_keys_storage_.emplace(key_hash, key); } -const std::map &TypeHintShape::get_all_registered_keys() noexcept { +const std::map& TypeHintShape::get_all_registered_keys() noexcept { return shape_keys_storage_; } @@ -161,109 +157,90 @@ const std::map &TypeHintShape::get_all_registered_key // all constructors of TypeHint classes are private, only TypeHint*::create() is allowed // each create() method calculates hash and creates an object only if it isn't found in a global hashtable - -const TypeHint *TypeHintArgRef::create(int arg_num) { +const TypeHint* TypeHintArgRef::create(int arg_num) { HasherOfTypeHintForOptimization hash(5693590762732189562ULL); hash.feed_hash(arg_num); - return hash.get_existing() ?: hash.add_because_doesnt_exist( - new TypeHintArgRef(arg_num) - ); + return hash.get_existing() ?: hash.add_because_doesnt_exist(new TypeHintArgRef(arg_num)); } -const TypeHint *TypeHintArgRefCallbackCall::create(int arg_num) { +const TypeHint* TypeHintArgRefCallbackCall::create(int arg_num) { HasherOfTypeHintForOptimization hash(1296495626775553170ULL); hash.feed_hash(arg_num); - return hash.get_existing() ?: hash.add_because_doesnt_exist( - new TypeHintArgRefCallbackCall(arg_num) - ); + return hash.get_existing() ?: hash.add_because_doesnt_exist(new TypeHintArgRefCallbackCall(arg_num)); } -const TypeHint *TypeHintArgRefInstance::create(int arg_num) { +const TypeHint* TypeHintArgRefInstance::create(int arg_num) { HasherOfTypeHintForOptimization hash(17043732264461707628ULL); hash.feed_hash(arg_num); - return hash.get_existing() ?: hash.add_because_doesnt_exist( - new TypeHintArgRefInstance(arg_num) - ); + return hash.get_existing() ?: hash.add_because_doesnt_exist(new TypeHintArgRefInstance(arg_num)); } -const TypeHint *TypeHintArgSubkeyGet::create(const TypeHint *inner) { +const TypeHint* TypeHintArgSubkeyGet::create(const TypeHint* inner) { HasherOfTypeHintForOptimization hash(1151996677232147726ULL); hash.feed_inner(inner); - return hash.get_existing() ?: hash.add_because_doesnt_exist( - new TypeHintArgSubkeyGet(inner) - ); + return hash.get_existing() ?: hash.add_because_doesnt_exist(new TypeHintArgSubkeyGet(inner)); } -const TypeHint *TypeHintArray::create(const TypeHint *inner) { +const TypeHint* TypeHintArray::create(const TypeHint* inner) { HasherOfTypeHintForOptimization hash(7584642663608918592ULL); hash.feed_inner(inner); - return hash.get_existing() ?: hash.add_because_doesnt_exist( - new TypeHintArray(inner) - ); + return hash.get_existing() ?: hash.add_because_doesnt_exist(new TypeHintArray(inner)); } -const TypeHint *TypeHintArray::create_array_of_any() { +const TypeHint* TypeHintArray::create_array_of_any() { HasherOfTypeHintForOptimization hash(7584642663608918592ULL); hash.feed_inner(TypeHintPrimitive::create(tp_any)); - return hash.get_existing() ?: hash.add_because_doesnt_exist( - new TypeHintArray(TypeHintPrimitive::create(tp_any)) - ); + return hash.get_existing() ?: hash.add_because_doesnt_exist(new TypeHintArray(TypeHintPrimitive::create(tp_any))); } -const TypeHint *TypeHintCallable::create(std::vector &&arg_types, const TypeHint *return_type) { +const TypeHint* TypeHintCallable::create(std::vector&& arg_types, const TypeHint* return_type) { HasherOfTypeHintForOptimization hash(16112178357011888472ULL); - for (const auto *arg : arg_types) { + for (const auto* arg : arg_types) { hash.feed_inner(arg); hash.feed_hash(161121); } hash.feed_inner(return_type); hash.feed_hash(161122); - return hash.get_existing() ?: hash.add_because_doesnt_exist( - new TypeHintCallable(std::move(arg_types), return_type) - ); + return hash.get_existing() ?: hash.add_because_doesnt_exist(new TypeHintCallable(std::move(arg_types), return_type)); } -const TypeHint *TypeHintCallable::create_untyped_callable() { +const TypeHint* TypeHintCallable::create_untyped_callable() { HasherOfTypeHintForOptimization hash(16112178357011888472ULL); - return hash.get_existing() ?: hash.add_because_doesnt_exist( - new TypeHintCallable() - ); + return hash.get_existing() ?: hash.add_because_doesnt_exist(new TypeHintCallable()); } -const TypeHint *TypeHintCallable::create_ptr_to_function(FunctionPtr f_bound_to) { +const TypeHint* TypeHintCallable::create_ptr_to_function(FunctionPtr f_bound_to) { HasherOfTypeHintForOptimization hash(16112178357011888472ULL); hash.feed_string(f_bound_to->name); - return hash.get_existing() ?: hash.add_because_doesnt_exist( - new TypeHintCallable(f_bound_to) - ); + return hash.get_existing() ?: hash.add_because_doesnt_exist(new TypeHintCallable(f_bound_to)); } -static void calculate_ffi_type_hash(HasherOfTypeHintForOptimization &hash, const FFIType *type) { +static void calculate_ffi_type_hash(HasherOfTypeHintForOptimization& hash, const FFIType* type) { hash.feed_hash(static_cast(type->kind)); hash.feed_hash(type->flags); hash.feed_hash(type->num); hash.feed_string(type->str); - for (const FFIType *member : type->members) { + for (const FFIType* member : type->members) { calculate_ffi_type_hash(hash, member); } } -const TypeHint *TypeHintFFIType::create(const std::string &scope_name, const FFIType *type, bool move) { +const TypeHint* TypeHintFFIType::create(const std::string& scope_name, const FFIType* type, bool move) { HasherOfTypeHintForOptimization hash(4941189930887759468ULL); hash.feed_string(scope_name); calculate_ffi_type_hash(hash, type); - if (const auto *existing = hash.get_existing()) { + if (const auto* existing = hash.get_existing()) { if (move) { // this cleanup is only necessary due to how we parse/create FFI types from the phpdoc ffi_type_delete(type); @@ -273,76 +250,62 @@ const TypeHint *TypeHintFFIType::create(const std::string &scope_name, const FFI return hash.add_because_doesnt_exist(new TypeHintFFIType{scope_name, type}); } -const TypeHint *TypeHintFFIScopeArgRef::create(int arg_num) { +const TypeHint* TypeHintFFIScopeArgRef::create(int arg_num) { HasherOfTypeHintForOptimization hash(9731618202711445786ULL); hash.feed_hash(arg_num); - return hash.get_existing() ?: hash.add_because_doesnt_exist( - new TypeHintFFIScopeArgRef{arg_num} - ); + return hash.get_existing() ?: hash.add_because_doesnt_exist(new TypeHintFFIScopeArgRef{arg_num}); } -const TypeHint *TypeHintFFIScope::create(const std::string &scope_name) { +const TypeHint* TypeHintFFIScope::create(const std::string& scope_name) { HasherOfTypeHintForOptimization hash(8265450633645347407ULL); hash.feed_string(scope_name); - return hash.get_existing() ?: hash.add_because_doesnt_exist( - new TypeHintFFIScope{scope_name} - ); + return hash.get_existing() ?: hash.add_because_doesnt_exist(new TypeHintFFIScope{scope_name}); } -const TypeHint *TypeHintFuture::create(PrimitiveType ptype, const TypeHint *inner) { +const TypeHint* TypeHintFuture::create(PrimitiveType ptype, const TypeHint* inner) { HasherOfTypeHintForOptimization hash(5072702167144640720ULL); hash.feed_inner(inner); hash.feed_hash(static_cast(ptype)); - return hash.get_existing() ?: hash.add_because_doesnt_exist( - new TypeHintFuture(ptype, inner) - ); + return hash.get_existing() ?: hash.add_because_doesnt_exist(new TypeHintFuture(ptype, inner)); } -const TypeHint *TypeHintNotNull::create(const TypeHint *inner, bool drop_not_null, bool drop_not_false) { +const TypeHint* TypeHintNotNull::create(const TypeHint* inner, bool drop_not_null, bool drop_not_false) { HasherOfTypeHintForOptimization hash(5192347813149011894ULL); hash.feed_inner(inner); hash.feed_hash(static_cast(drop_not_null)); hash.feed_hash(static_cast(drop_not_false)); - return hash.get_existing() ?: hash.add_because_doesnt_exist( - new TypeHintNotNull(inner, drop_not_null, drop_not_false) - ); + return hash.get_existing() ?: hash.add_because_doesnt_exist(new TypeHintNotNull(inner, drop_not_null, drop_not_false)); } -const TypeHint *TypeHintInstance::create(const std::string &full_class_name) { +const TypeHint* TypeHintInstance::create(const std::string& full_class_name) { HasherOfTypeHintForOptimization hash(16370122391586404558ULL); hash.feed_string(full_class_name); - return hash.get_existing() ?: hash.add_because_doesnt_exist( - new TypeHintInstance(full_class_name, is_string_self_static_parent(full_class_name)) - ); + return hash.get_existing() ?: hash.add_because_doesnt_exist(new TypeHintInstance(full_class_name, is_string_self_static_parent(full_class_name))); } -const TypeHint *TypeHintRefToField::create(const TypeHint *inner, const std::string &field_name) { +const TypeHint* TypeHintRefToField::create(const TypeHint* inner, const std::string& field_name) { HasherOfTypeHintForOptimization hash(12470101183576506574ULL); hash.feed_inner(inner); hash.feed_string(field_name); - return hash.get_existing() ?: hash.add_because_doesnt_exist( - new TypeHintRefToField(inner, field_name) - ); + return hash.get_existing() ?: hash.add_because_doesnt_exist(new TypeHintRefToField(inner, field_name)); } -const TypeHint *TypeHintRefToMethod::create(const TypeHint *inner, const std::string &method_name) { +const TypeHint* TypeHintRefToMethod::create(const TypeHint* inner, const std::string& method_name) { HasherOfTypeHintForOptimization hash(11681103389463249563ULL); hash.feed_inner(inner); hash.feed_string(method_name); - return hash.get_existing() ?: hash.add_because_doesnt_exist( - new TypeHintRefToMethod(inner, method_name) - ); + return hash.get_existing() ?: hash.add_because_doesnt_exist(new TypeHintRefToMethod(inner, method_name)); } -const TypeHint *TypeHintOptional::create(const TypeHint *inner, bool or_null, bool or_false) { - if (const auto *opt = inner->try_as()) { +const TypeHint* TypeHintOptional::create(const TypeHint* inner, bool or_null, bool or_false) { + if (const auto* opt = inner->try_as()) { return TypeHintOptional::create(opt->inner, opt->or_null || or_null, opt->or_false || or_false); } @@ -350,43 +313,35 @@ const TypeHint *TypeHintOptional::create(const TypeHint *inner, bool or_null, bo hash.feed_inner(inner); hash.feed_hash(static_cast(or_null) * 2 + static_cast(or_false)); - return hash.get_existing() ?: hash.add_because_doesnt_exist( - new TypeHintOptional(inner, or_null, or_false) - ); + return hash.get_existing() ?: hash.add_because_doesnt_exist(new TypeHintOptional(inner, or_null, or_false)); } -const TypeHint *TypeHintPipe::create(std::vector &&items) { +const TypeHint* TypeHintPipe::create(std::vector&& items) { HasherOfTypeHintForOptimization hash(420035265936859756ULL); - for (const TypeHint *item : items) { + for (const TypeHint* item : items) { hash.feed_inner(item); hash.feed_hash(420035); } - return hash.get_existing() ?: hash.add_because_doesnt_exist( - new TypeHintPipe(std::move(items)) - ); + return hash.get_existing() ?: hash.add_because_doesnt_exist(new TypeHintPipe(std::move(items))); } -const TypeHint *TypeHintPrimitive::create(PrimitiveType ptype) { +const TypeHint* TypeHintPrimitive::create(PrimitiveType ptype) { HasherOfTypeHintForOptimization hash(18266006284047729844ULL); hash.feed_hash(static_cast(ptype)); - return hash.get_existing() ?: hash.add_because_doesnt_exist( - new TypeHintPrimitive(ptype) - ); + return hash.get_existing() ?: hash.add_because_doesnt_exist(new TypeHintPrimitive(ptype)); } -const TypeHint *TypeHintObject::create() { +const TypeHint* TypeHintObject::create() { HasherOfTypeHintForOptimization hash(13255191682146639421ULL); - return hash.get_existing() ?: hash.add_because_doesnt_exist( - new TypeHintObject() - ); + return hash.get_existing() ?: hash.add_because_doesnt_exist(new TypeHintObject()); } -const TypeHint *TypeHintShape::create(std::vector> &&items, bool is_vararg) { +const TypeHint* TypeHintShape::create(std::vector>&& items, bool is_vararg) { HasherOfTypeHintForOptimization hash(8163025479511413046ULL); - for (const auto &item : items) { + for (const auto& item : items) { hash.feed_string(item.first); hash.feed_inner(item.second); hash.feed_hash(816302); @@ -395,47 +350,37 @@ const TypeHint *TypeHintShape::create(std::vector &&items) { +const TypeHint* TypeHintTuple::create(std::vector&& items) { HasherOfTypeHintForOptimization hash(8195157858190991427ULL); - for (const TypeHint *item : items) { + for (const TypeHint* item : items) { hash.feed_inner(item); hash.feed_hash(819515); } - return hash.get_existing() ?: hash.add_because_doesnt_exist( - new TypeHintTuple(std::move(items)) - ); + return hash.get_existing() ?: hash.add_because_doesnt_exist(new TypeHintTuple(std::move(items))); } -const TypeHint *TypeHintGenericT::create(const std::string &nameT) { +const TypeHint* TypeHintGenericT::create(const std::string& nameT) { HasherOfTypeHintForOptimization hash(4117413899192632779ULL); hash.feed_string(nameT); - return hash.get_existing() ?: hash.add_because_doesnt_exist( - new TypeHintGenericT(nameT) - ); + return hash.get_existing() ?: hash.add_because_doesnt_exist(new TypeHintGenericT(nameT)); } -const TypeHint *TypeHintClassString::create(const TypeHint *inner) { +const TypeHint* TypeHintClassString::create(const TypeHint* inner) { HasherOfTypeHintForOptimization hash(2914531788341198112ULL); hash.feed_inner(inner); - return hash.get_existing() ?: hash.add_because_doesnt_exist( - new TypeHintClassString(inner) - ); + return hash.get_existing() ?: hash.add_because_doesnt_exist(new TypeHintClassString(inner)); } - // -------------------------------------------- // as_human_readable() // returns a notation very similar to how it's expressed in phpdoc - std::string TypeHintArgRef::as_human_readable() const { return std::string("^") + std::to_string(arg_num); } @@ -460,8 +405,8 @@ std::string TypeHintArray::as_human_readable() const { std::string TypeHintCallable::as_human_readable() const { return is_untyped_callable() - ? f_bound_to ? f_bound_to->name : "callable" - : "callable(" + vk::join(arg_types, ", ", [](const TypeHint *arg) { return arg->as_human_readable(); }) + "): " + return_type->as_human_readable(); + ? f_bound_to ? f_bound_to->name : "callable" + : "callable(" + vk::join(arg_types, ", ", [](const TypeHint* arg) { return arg->as_human_readable(); }) + "): " + return_type->as_human_readable(); } std::string TypeHintFFIType::as_human_readable() const { @@ -502,7 +447,7 @@ std::string TypeHintOptional::as_human_readable() const { } std::string TypeHintPipe::as_human_readable() const { - return vk::join(items, "|", [](const TypeHint *item) { return item->as_human_readable(); }); + return vk::join(items, "|", [](const TypeHint* item) { return item->as_human_readable(); }); } std::string TypeHintPrimitive::as_human_readable() const { @@ -514,11 +459,11 @@ std::string TypeHintObject::as_human_readable() const { } std::string TypeHintShape::as_human_readable() const { - return "shape(" + vk::join(items, ", ", [](const auto &item) { return item.first + ":" + item.second->as_human_readable(); }) + (is_vararg ? ", ...)" : ")"); + return "shape(" + vk::join(items, ", ", [](const auto& item) { return item.first + ":" + item.second->as_human_readable(); }) + (is_vararg ? ", ...)" : ")"); } std::string TypeHintTuple::as_human_readable() const { - return "tuple(" + vk::join(items, ", ", [](const TypeHint *item) { return item->as_human_readable(); }) + ")"; + return "tuple(" + vk::join(items, ", ", [](const TypeHint* item) { return item->as_human_readable(); }) + ")"; } std::string TypeHintGenericT::as_human_readable() const { @@ -529,37 +474,35 @@ std::string TypeHintClassString::as_human_readable() const { return "class_string<" + inner->as_human_readable() + ">"; } - // -------------------------------------------- // traverse() // invokes a callback for type hint itself and all its children - -void TypeHintArgRef::traverse(const TraverserCallbackT &callback) const { +void TypeHintArgRef::traverse(const TraverserCallbackT& callback) const { callback(this); } -void TypeHintArgRefCallbackCall::traverse(const TraverserCallbackT &callback) const { +void TypeHintArgRefCallbackCall::traverse(const TraverserCallbackT& callback) const { callback(this); } -void TypeHintArgRefInstance::traverse(const TraverserCallbackT &callback) const { +void TypeHintArgRefInstance::traverse(const TraverserCallbackT& callback) const { callback(this); } -void TypeHintArgSubkeyGet::traverse(const TraverserCallbackT &callback) const { +void TypeHintArgSubkeyGet::traverse(const TraverserCallbackT& callback) const { callback(this); inner->traverse(callback); } -void TypeHintArray::traverse(const TraverserCallbackT &callback) const { +void TypeHintArray::traverse(const TraverserCallbackT& callback) const { callback(this); inner->traverse(callback); } -void TypeHintCallable::traverse(const TraverserCallbackT &callback) const { +void TypeHintCallable::traverse(const TraverserCallbackT& callback) const { callback(this); - for (const TypeHint *arg : arg_types) { + for (const TypeHint* arg : arg_types) { arg->traverse(callback); } if (return_type != nullptr) { @@ -567,189 +510,191 @@ void TypeHintCallable::traverse(const TraverserCallbackT &callback) const { } } -void TypeHintFFIType::traverse(const TraverserCallbackT &callback) const { +void TypeHintFFIType::traverse(const TraverserCallbackT& callback) const { callback(this); } -void TypeHintFFIScopeArgRef::traverse(const TraverserCallbackT &callback) const { +void TypeHintFFIScopeArgRef::traverse(const TraverserCallbackT& callback) const { callback(this); } -void TypeHintFFIScope::traverse(const TraverserCallbackT &callback) const { +void TypeHintFFIScope::traverse(const TraverserCallbackT& callback) const { callback(this); } -void TypeHintFuture::traverse(const TraverserCallbackT &callback) const { +void TypeHintFuture::traverse(const TraverserCallbackT& callback) const { callback(this); inner->traverse(callback); } -void TypeHintNotNull::traverse(const TraverserCallbackT &callback) const { +void TypeHintNotNull::traverse(const TraverserCallbackT& callback) const { callback(this); inner->traverse(callback); } -void TypeHintInstance::traverse(const TraverserCallbackT &callback) const { +void TypeHintInstance::traverse(const TraverserCallbackT& callback) const { callback(this); } -void TypeHintRefToField::traverse(const TraverserCallbackT &callback) const { +void TypeHintRefToField::traverse(const TraverserCallbackT& callback) const { callback(this); inner->traverse(callback); } -void TypeHintRefToMethod::traverse(const TraverserCallbackT &callback) const { +void TypeHintRefToMethod::traverse(const TraverserCallbackT& callback) const { callback(this); inner->traverse(callback); } -void TypeHintOptional::traverse(const TraverserCallbackT &callback) const { +void TypeHintOptional::traverse(const TraverserCallbackT& callback) const { callback(this); inner->traverse(callback); } -void TypeHintPipe::traverse(const TraverserCallbackT &callback) const { +void TypeHintPipe::traverse(const TraverserCallbackT& callback) const { callback(this); - for (const TypeHint *item : items) { + for (const TypeHint* item : items) { item->traverse(callback); } } -void TypeHintPrimitive::traverse(const TraverserCallbackT &callback) const { +void TypeHintPrimitive::traverse(const TraverserCallbackT& callback) const { callback(this); } -void TypeHintObject::traverse(const TraverserCallbackT &callback) const { +void TypeHintObject::traverse(const TraverserCallbackT& callback) const { callback(this); } -void TypeHintShape::traverse(const TraverserCallbackT &callback) const { +void TypeHintShape::traverse(const TraverserCallbackT& callback) const { callback(this); - for (const auto &item : items) { + for (const auto& item : items) { item.second->traverse(callback); } } -void TypeHintTuple::traverse(const TraverserCallbackT &callback) const { +void TypeHintTuple::traverse(const TraverserCallbackT& callback) const { callback(this); - for (const TypeHint *item : items) { + for (const TypeHint* item : items) { item->traverse(callback); } } -void TypeHintGenericT::traverse(const TypeHint::TraverserCallbackT &callback) const { +void TypeHintGenericT::traverse(const TypeHint::TraverserCallbackT& callback) const { callback(this); } -void TypeHintClassString::traverse(const TypeHint::TraverserCallbackT &callback) const { +void TypeHintClassString::traverse(const TypeHint::TraverserCallbackT& callback) const { callback(this); inner->traverse(callback); } - // -------------------------------------------- // replace_self_static_parent() // returns a new type hint with resolved self/static/parent inside // for example, tuple(self[], int) becomes tuple(T[], int) // it's called externally only if a flag is set, so we don't need to do extra checks inside implementations - -const TypeHint *TypeHintArgRef::replace_self_static_parent(FunctionPtr resolve_context __attribute__ ((unused))) const { +const TypeHint* TypeHintArgRef::replace_self_static_parent(FunctionPtr resolve_context __attribute__((unused))) const { return this; } -const TypeHint *TypeHintArgRefCallbackCall::replace_self_static_parent(FunctionPtr resolve_context __attribute__ ((unused))) const { +const TypeHint* TypeHintArgRefCallbackCall::replace_self_static_parent(FunctionPtr resolve_context __attribute__((unused))) const { return this; } -const TypeHint *TypeHintArgRefInstance::replace_self_static_parent(FunctionPtr resolve_context __attribute__ ((unused))) const { +const TypeHint* TypeHintArgRefInstance::replace_self_static_parent(FunctionPtr resolve_context __attribute__((unused))) const { return this; } -const TypeHint *TypeHintArgSubkeyGet::replace_self_static_parent(FunctionPtr resolve_context __attribute__ ((unused))) const { +const TypeHint* TypeHintArgSubkeyGet::replace_self_static_parent(FunctionPtr resolve_context __attribute__((unused))) const { return this; } -const TypeHint *TypeHintArray::replace_self_static_parent(FunctionPtr resolve_context) const { +const TypeHint* TypeHintArray::replace_self_static_parent(FunctionPtr resolve_context) const { return create(inner->replace_self_static_parent(resolve_context)); } -const TypeHint *TypeHintCallable::replace_self_static_parent(FunctionPtr resolve_context) const { +const TypeHint* TypeHintCallable::replace_self_static_parent(FunctionPtr resolve_context) const { if (is_untyped_callable()) { return this; } - auto mapper = vk::make_transform_iterator_range([resolve_context](auto sub) { return sub->replace_self_static_parent(resolve_context); }, arg_types.begin(), arg_types.end()); + auto mapper = vk::make_transform_iterator_range([resolve_context](auto sub) { return sub->replace_self_static_parent(resolve_context); }, arg_types.begin(), + arg_types.end()); return create({mapper.begin(), mapper.end()}, return_type->replace_self_static_parent(resolve_context)); } -const TypeHint *TypeHintFFIType::replace_self_static_parent(FunctionPtr resolve_context __attribute__ ((unused))) const { +const TypeHint* TypeHintFFIType::replace_self_static_parent(FunctionPtr resolve_context __attribute__((unused))) const { return this; } -const TypeHint *TypeHintFFIScopeArgRef::replace_self_static_parent(FunctionPtr resolve_context __attribute__ ((unused))) const { +const TypeHint* TypeHintFFIScopeArgRef::replace_self_static_parent(FunctionPtr resolve_context __attribute__((unused))) const { return this; } -const TypeHint *TypeHintFFIScope::replace_self_static_parent(FunctionPtr resolve_context __attribute__ ((unused))) const { +const TypeHint* TypeHintFFIScope::replace_self_static_parent(FunctionPtr resolve_context __attribute__((unused))) const { return this; } -const TypeHint *TypeHintFuture::replace_self_static_parent(FunctionPtr resolve_context) const { +const TypeHint* TypeHintFuture::replace_self_static_parent(FunctionPtr resolve_context) const { return create(ptype, inner->replace_self_static_parent(resolve_context)); } -const TypeHint *TypeHintNotNull::replace_self_static_parent(FunctionPtr resolve_context) const { +const TypeHint* TypeHintNotNull::replace_self_static_parent(FunctionPtr resolve_context) const { return create(inner->replace_self_static_parent(resolve_context), drop_not_null, drop_not_false); } -const TypeHint *TypeHintInstance::replace_self_static_parent(FunctionPtr resolve_context) const { +const TypeHint* TypeHintInstance::replace_self_static_parent(FunctionPtr resolve_context) const { return is_string_self_static_parent(full_class_name) ? create(resolve_uses(resolve_context, full_class_name)) : this; } -const TypeHint *TypeHintRefToField::replace_self_static_parent(FunctionPtr resolve_context) const { +const TypeHint* TypeHintRefToField::replace_self_static_parent(FunctionPtr resolve_context) const { return create(inner->replace_self_static_parent(resolve_context), field_name); } -const TypeHint *TypeHintRefToMethod::replace_self_static_parent(FunctionPtr resolve_context) const { +const TypeHint* TypeHintRefToMethod::replace_self_static_parent(FunctionPtr resolve_context) const { return create(inner->replace_self_static_parent(resolve_context), method_name); } -const TypeHint *TypeHintOptional::replace_self_static_parent(FunctionPtr resolve_context) const { +const TypeHint* TypeHintOptional::replace_self_static_parent(FunctionPtr resolve_context) const { return create(inner->replace_self_static_parent(resolve_context), or_null, or_false); } -const TypeHint *TypeHintPipe::replace_self_static_parent(FunctionPtr resolve_context) const { - auto mapper = vk::make_transform_iterator_range([resolve_context](auto sub) { return sub->replace_self_static_parent(resolve_context); }, items.begin(), items.end()); +const TypeHint* TypeHintPipe::replace_self_static_parent(FunctionPtr resolve_context) const { + auto mapper = + vk::make_transform_iterator_range([resolve_context](auto sub) { return sub->replace_self_static_parent(resolve_context); }, items.begin(), items.end()); return create({mapper.begin(), mapper.end()}); } -const TypeHint *TypeHintPrimitive::replace_self_static_parent(FunctionPtr resolve_context __attribute__ ((unused))) const { +const TypeHint* TypeHintPrimitive::replace_self_static_parent(FunctionPtr resolve_context __attribute__((unused))) const { return this; } -const TypeHint *TypeHintObject::replace_self_static_parent(FunctionPtr resolve_context __attribute__ ((unused))) const { +const TypeHint* TypeHintObject::replace_self_static_parent(FunctionPtr resolve_context __attribute__((unused))) const { return this; } -const TypeHint *TypeHintShape::replace_self_static_parent(FunctionPtr resolve_context) const { - auto mapper = vk::make_transform_iterator_range([resolve_context](const auto &sub) { return std::make_pair(sub.first, sub.second->replace_self_static_parent(resolve_context)); }, items.begin(), items.end()); +const TypeHint* TypeHintShape::replace_self_static_parent(FunctionPtr resolve_context) const { + auto mapper = vk::make_transform_iterator_range( + [resolve_context](const auto& sub) { return std::make_pair(sub.first, sub.second->replace_self_static_parent(resolve_context)); }, items.begin(), + items.end()); return create({mapper.begin(), mapper.end()}, is_vararg); } -const TypeHint *TypeHintTuple::replace_self_static_parent(FunctionPtr resolve_context) const { - auto mapper = vk::make_transform_iterator_range([resolve_context](auto sub) { return sub->replace_self_static_parent(resolve_context); }, items.begin(), items.end()); +const TypeHint* TypeHintTuple::replace_self_static_parent(FunctionPtr resolve_context) const { + auto mapper = + vk::make_transform_iterator_range([resolve_context](auto sub) { return sub->replace_self_static_parent(resolve_context); }, items.begin(), items.end()); return create({mapper.begin(), mapper.end()}); } -const TypeHint *TypeHintGenericT::replace_self_static_parent(FunctionPtr resolve_context __attribute__ ((unused))) const { +const TypeHint* TypeHintGenericT::replace_self_static_parent(FunctionPtr resolve_context __attribute__((unused))) const { return this; } -const TypeHint *TypeHintClassString::replace_self_static_parent(FunctionPtr resolve_context) const { +const TypeHint* TypeHintClassString::replace_self_static_parent(FunctionPtr resolve_context) const { return create(inner->replace_self_static_parent(resolve_context)); } - // -------------------------------------------- // replace_children_custom() // returns a new type hint with children replaced by a custom callback @@ -757,28 +702,27 @@ const TypeHint *TypeHintClassString::replace_self_static_parent(FunctionPtr reso // also used to replace generic T with an exact type hint — to convert tuple(T) to tuple(B) // replace_self_static_parent() could be dropped off, but is left for performance - -const TypeHint *TypeHintArgRef::replace_children_custom(const ReplacerCallbackT &callback) const { +const TypeHint* TypeHintArgRef::replace_children_custom(const ReplacerCallbackT& callback) const { return callback(this); } -const TypeHint *TypeHintArgRefCallbackCall::replace_children_custom(const ReplacerCallbackT &callback) const { +const TypeHint* TypeHintArgRefCallbackCall::replace_children_custom(const ReplacerCallbackT& callback) const { return callback(this); } -const TypeHint *TypeHintArgRefInstance::replace_children_custom(const ReplacerCallbackT &callback) const { +const TypeHint* TypeHintArgRefInstance::replace_children_custom(const ReplacerCallbackT& callback) const { return callback(this); } -const TypeHint *TypeHintArgSubkeyGet::replace_children_custom(const ReplacerCallbackT &callback) const { +const TypeHint* TypeHintArgSubkeyGet::replace_children_custom(const ReplacerCallbackT& callback) const { return callback(this); } -const TypeHint *TypeHintArray::replace_children_custom(const ReplacerCallbackT &callback) const { +const TypeHint* TypeHintArray::replace_children_custom(const ReplacerCallbackT& callback) const { return callback(create(inner->replace_children_custom(callback))); } -const TypeHint *TypeHintCallable::replace_children_custom(const ReplacerCallbackT &callback) const { +const TypeHint* TypeHintCallable::replace_children_custom(const ReplacerCallbackT& callback) const { if (is_untyped_callable()) { return callback(this); } @@ -786,74 +730,74 @@ const TypeHint *TypeHintCallable::replace_children_custom(const ReplacerCallback return callback(create({mapper.begin(), mapper.end()}, return_type->replace_children_custom(callback))); } -const TypeHint *TypeHintFFIType::replace_children_custom(const ReplacerCallbackT &callback) const { +const TypeHint* TypeHintFFIType::replace_children_custom(const ReplacerCallbackT& callback) const { return callback(this); } -const TypeHint *TypeHintFFIScopeArgRef::replace_children_custom(const ReplacerCallbackT &callback) const { +const TypeHint* TypeHintFFIScopeArgRef::replace_children_custom(const ReplacerCallbackT& callback) const { return callback(this); } -const TypeHint *TypeHintFFIScope::replace_children_custom(const ReplacerCallbackT &callback) const { +const TypeHint* TypeHintFFIScope::replace_children_custom(const ReplacerCallbackT& callback) const { return callback(this); } -const TypeHint *TypeHintFuture::replace_children_custom(const ReplacerCallbackT &callback) const { +const TypeHint* TypeHintFuture::replace_children_custom(const ReplacerCallbackT& callback) const { return callback(create(ptype, inner->replace_children_custom(callback))); } -const TypeHint *TypeHintNotNull::replace_children_custom(const ReplacerCallbackT &callback) const { +const TypeHint* TypeHintNotNull::replace_children_custom(const ReplacerCallbackT& callback) const { return callback(create(inner->replace_children_custom(callback), drop_not_null, drop_not_false)); } -const TypeHint *TypeHintInstance::replace_children_custom(const ReplacerCallbackT &callback) const { +const TypeHint* TypeHintInstance::replace_children_custom(const ReplacerCallbackT& callback) const { return callback(this); } -const TypeHint *TypeHintRefToField::replace_children_custom(const ReplacerCallbackT &callback) const { +const TypeHint* TypeHintRefToField::replace_children_custom(const ReplacerCallbackT& callback) const { return callback(create(inner->replace_children_custom(callback), field_name)); } -const TypeHint *TypeHintRefToMethod::replace_children_custom(const ReplacerCallbackT &callback) const { +const TypeHint* TypeHintRefToMethod::replace_children_custom(const ReplacerCallbackT& callback) const { return callback(create(inner->replace_children_custom(callback), method_name)); } -const TypeHint *TypeHintOptional::replace_children_custom(const ReplacerCallbackT &callback) const { +const TypeHint* TypeHintOptional::replace_children_custom(const ReplacerCallbackT& callback) const { return callback(create(inner->replace_children_custom(callback), or_null, or_false)); } -const TypeHint *TypeHintPipe::replace_children_custom(const ReplacerCallbackT &callback) const { +const TypeHint* TypeHintPipe::replace_children_custom(const ReplacerCallbackT& callback) const { auto mapper = vk::make_transform_iterator_range([callback](auto sub) { return sub->replace_children_custom(callback); }, items.begin(), items.end()); return callback(create({mapper.begin(), mapper.end()})); } -const TypeHint *TypeHintPrimitive::replace_children_custom(const ReplacerCallbackT &callback) const { +const TypeHint* TypeHintPrimitive::replace_children_custom(const ReplacerCallbackT& callback) const { return callback(this); } -const TypeHint *TypeHintObject::replace_children_custom(const ReplacerCallbackT &callback) const { +const TypeHint* TypeHintObject::replace_children_custom(const ReplacerCallbackT& callback) const { return callback(this); } -const TypeHint *TypeHintShape::replace_children_custom(const ReplacerCallbackT &callback) const { - auto mapper = vk::make_transform_iterator_range([callback](const auto &sub) { return std::make_pair(sub.first, sub.second->replace_children_custom(callback)); }, items.begin(), items.end()); +const TypeHint* TypeHintShape::replace_children_custom(const ReplacerCallbackT& callback) const { + auto mapper = vk::make_transform_iterator_range( + [callback](const auto& sub) { return std::make_pair(sub.first, sub.second->replace_children_custom(callback)); }, items.begin(), items.end()); return callback(create({mapper.begin(), mapper.end()}, is_vararg)); } -const TypeHint *TypeHintTuple::replace_children_custom(const ReplacerCallbackT &callback) const { +const TypeHint* TypeHintTuple::replace_children_custom(const ReplacerCallbackT& callback) const { auto mapper = vk::make_transform_iterator_range([callback](auto sub) { return sub->replace_children_custom(callback); }, items.begin(), items.end()); return callback(create({mapper.begin(), mapper.end()})); } -const TypeHint *TypeHintGenericT::replace_children_custom(const ReplacerCallbackT &callback) const { +const TypeHint* TypeHintGenericT::replace_children_custom(const ReplacerCallbackT& callback) const { return callback(this); } -const TypeHint *TypeHintClassString::replace_children_custom(const ReplacerCallbackT &callback) const { +const TypeHint* TypeHintClassString::replace_children_custom(const ReplacerCallbackT& callback) const { return callback(create(inner->replace_children_custom(callback))); } - // -------------------------------------------- // recalc_type_data_in_context_of_call() // they are implemented in a separate file: see compiler/inferring/type-hint-recalc.cpp diff --git a/compiler/type-hint.h b/compiler/type-hint.h index 77d967a332..2ebdf8f584 100644 --- a/compiler/type-hint.h +++ b/compiler/type-hint.h @@ -12,7 +12,6 @@ #include "compiler/debug.h" #include "compiler/inferring/primitive-type.h" - // do not confuse TypeHint with TypeData! // TypeData is a part of _type inferring_; it's mutable and plain, it represents current inferred state of every vertex class TypeData; @@ -34,17 +33,19 @@ class TypeData; * When bound to a function, they must be replaced with actual context, see phpdoc_finalize_type_hint_and_resolve() */ class TypeHint { - DEBUG_STRING_METHOD { return as_human_readable(); } + DEBUG_STRING_METHOD { + return as_human_readable(); + } // these fields are calculated only once for every unique type hint - uint64_t hash{0}; // a unique hash: only unique type hints are actually created - int flags{0}; // bits of flag_mask, to store often-used properties and return them without tree traversing + uint64_t hash{0}; // a unique hash: only unique type hints are actually created + int flags{0}; // bits of flag_mask, to store often-used properties and return them without tree traversing // to leave public interface more clear, don't expose setters, use friend friend class HasherOfTypeHintForOptimization; // this field is calculated only once on need, see to_type_data() - mutable const TypeData *cached_typedata_if_constexpr{nullptr}; + mutable const TypeData* cached_typedata_if_constexpr{nullptr}; protected: enum flag_mask { @@ -58,37 +59,56 @@ class TypeHint { flag_potentially_casts_rhs = 1 << 10, }; - explicit TypeHint(int self_flags_without_children) : flags(self_flags_without_children) {} + explicit TypeHint(int self_flags_without_children) + : flags(self_flags_without_children) {} public: - virtual ~TypeHint() = default; // though instances of TypeHint are never deleted :) + virtual ~TypeHint() = default; // though instances of TypeHint are never deleted :) template - const Derived *try_as() const { - return dynamic_cast(this); + const Derived* try_as() const { + return dynamic_cast(this); } - bool has_instances_inside() const { return flags & flag_contains_instances_inside; } - bool has_self_static_parent_inside() const { return flags & flag_contains_self_static_parent_inside; } - bool has_argref_inside() const { return flags & flag_contains_argref_inside; } - bool has_tp_any_inside() const { return flags & flag_contains_tp_any_inside; } - bool has_callables_inside() const { return flags & flag_contains_callables_inside; } - bool has_genericT_inside() const { return flags & flag_contains_genericT_inside; } - bool has_autogeneric_inside() const { return flags & flag_contains_autogeneric_inside; } - bool has_flag_maybe_casts_rhs() const { return flags & flag_potentially_casts_rhs; } + bool has_instances_inside() const { + return flags & flag_contains_instances_inside; + } + bool has_self_static_parent_inside() const { + return flags & flag_contains_self_static_parent_inside; + } + bool has_argref_inside() const { + return flags & flag_contains_argref_inside; + } + bool has_tp_any_inside() const { + return flags & flag_contains_tp_any_inside; + } + bool has_callables_inside() const { + return flags & flag_contains_callables_inside; + } + bool has_genericT_inside() const { + return flags & flag_contains_genericT_inside; + } + bool has_autogeneric_inside() const { + return flags & flag_contains_autogeneric_inside; + } + bool has_flag_maybe_casts_rhs() const { + return flags & flag_potentially_casts_rhs; + } - bool is_typedata_constexpr() const { return !has_argref_inside() && !has_self_static_parent_inside() && !has_genericT_inside(); } - const TypeData *to_type_data() const; - const TypeHint *unwrap_optional() const; + bool is_typedata_constexpr() const { + return !has_argref_inside() && !has_self_static_parent_inside() && !has_genericT_inside(); + } + const TypeData* to_type_data() const; + const TypeHint* unwrap_optional() const; - using TraverserCallbackT = std::function; - using ReplacerCallbackT = std::function; + using TraverserCallbackT = std::function; + using ReplacerCallbackT = std::function; virtual std::string as_human_readable() const = 0; - virtual void traverse(const TraverserCallbackT &callback) const = 0; - virtual const TypeHint *replace_self_static_parent(FunctionPtr resolve_context) const = 0; - virtual const TypeHint *replace_children_custom(const ReplacerCallbackT &callback) const = 0; - virtual void recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr func_call) const = 0; + virtual void traverse(const TraverserCallbackT& callback) const = 0; + virtual const TypeHint* replace_self_static_parent(FunctionPtr resolve_context) const = 0; + virtual const TypeHint* replace_children_custom(const ReplacerCallbackT& callback) const = 0; + virtual void recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr func_call) const = 0; }; /** @@ -97,19 +117,19 @@ class TypeHint { */ class TypeHintArgRef : public TypeHint { explicit TypeHintArgRef(int arg_num) - : TypeHint(flag_contains_argref_inside) - , arg_num(arg_num) {} + : TypeHint(flag_contains_argref_inside), + arg_num(arg_num) {} public: int arg_num; - static const TypeHint *create(int arg_num); + static const TypeHint* create(int arg_num); std::string as_human_readable() const final; - void traverse(const TraverserCallbackT &callback) const final; - const TypeHint *replace_self_static_parent(FunctionPtr resolve_context) const final; - const TypeHint *replace_children_custom(const ReplacerCallbackT &callback) const final; - void recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr func_call) const final; + void traverse(const TraverserCallbackT& callback) const final; + const TypeHint* replace_self_static_parent(FunctionPtr resolve_context) const final; + const TypeHint* replace_children_custom(const ReplacerCallbackT& callback) const final; + void recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr func_call) const final; }; /** @@ -118,19 +138,19 @@ class TypeHintArgRef : public TypeHint { */ class TypeHintArgRefCallbackCall : public TypeHint { explicit TypeHintArgRefCallbackCall(int arg_num) - : TypeHint(flag_contains_argref_inside) - , arg_num(arg_num) {} + : TypeHint(flag_contains_argref_inside), + arg_num(arg_num) {} public: int arg_num; - static const TypeHint *create(int arg_num); + static const TypeHint* create(int arg_num); std::string as_human_readable() const final; - void traverse(const TraverserCallbackT &callback) const final; - const TypeHint *replace_self_static_parent(FunctionPtr resolve_context) const final; - const TypeHint *replace_children_custom(const ReplacerCallbackT &callback) const final; - void recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr func_call) const final; + void traverse(const TraverserCallbackT& callback) const final; + const TypeHint* replace_self_static_parent(FunctionPtr resolve_context) const final; + const TypeHint* replace_children_custom(const ReplacerCallbackT& callback) const final; + void recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr func_call) const final; }; /** @@ -139,19 +159,19 @@ class TypeHintArgRefCallbackCall : public TypeHint { */ class TypeHintArgRefInstance : public TypeHint { explicit TypeHintArgRefInstance(int arg_num) - : TypeHint(flag_contains_argref_inside) - , arg_num(arg_num) {} + : TypeHint(flag_contains_argref_inside), + arg_num(arg_num) {} public: int arg_num; - static const TypeHint *create(int arg_num); + static const TypeHint* create(int arg_num); std::string as_human_readable() const final; - void traverse(const TraverserCallbackT &callback) const final; - const TypeHint *replace_self_static_parent(FunctionPtr resolve_context) const final; - const TypeHint *replace_children_custom(const ReplacerCallbackT &callback) const final; - void recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr func_call) const final; + void traverse(const TraverserCallbackT& callback) const final; + const TypeHint* replace_self_static_parent(FunctionPtr resolve_context) const final; + const TypeHint* replace_children_custom(const ReplacerCallbackT& callback) const final; + void recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr func_call) const final; }; /** @@ -159,20 +179,20 @@ class TypeHintArgRefInstance : public TypeHint { * Theoretically, later it could be not [*] (any_key) but [0] and others to get from tuples */ class TypeHintArgSubkeyGet : public TypeHint { - explicit TypeHintArgSubkeyGet(const TypeHint *inner) - : TypeHint(0) - , inner(inner) {} + explicit TypeHintArgSubkeyGet(const TypeHint* inner) + : TypeHint(0), + inner(inner) {} public: - const TypeHint *inner; + const TypeHint* inner; - static const TypeHint *create(const TypeHint *inner); + static const TypeHint* create(const TypeHint* inner); std::string as_human_readable() const final; - void traverse(const TraverserCallbackT &callback) const final; - const TypeHint *replace_self_static_parent(FunctionPtr resolve_context) const final; - const TypeHint *replace_children_custom(const ReplacerCallbackT &callback) const final; - void recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr func_call) const final; + void traverse(const TraverserCallbackT& callback) const final; + const TypeHint* replace_self_static_parent(FunctionPtr resolve_context) const final; + const TypeHint* replace_children_custom(const ReplacerCallbackT& callback) const final; + void recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr func_call) const final; }; /** @@ -180,24 +200,24 @@ class TypeHintArgSubkeyGet : public TypeHint { * We allow this to be used only with generic T, see phpdoc_replace_genericTs_with_reified(); SomeClass::f will fail. */ class TypeHintRefToField : public TypeHint { - explicit TypeHintRefToField(const TypeHint *inner, std::string field_name) - : TypeHint(0) - , inner(inner) - , field_name(std::move(field_name)) {} + explicit TypeHintRefToField(const TypeHint* inner, std::string field_name) + : TypeHint(0), + inner(inner), + field_name(std::move(field_name)) {} public: - const TypeHint *inner; + const TypeHint* inner; std::string field_name; - static const TypeHint *create(const TypeHint *inner, const std::string &field_name); + static const TypeHint* create(const TypeHint* inner, const std::string& field_name); std::string as_human_readable() const final; - void traverse(const TraverserCallbackT &callback) const final; - const TypeHint *replace_self_static_parent(FunctionPtr resolve_context) const final; - const TypeHint *replace_children_custom(const ReplacerCallbackT &callback) const final; - void recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr func_call) const final; + void traverse(const TraverserCallbackT& callback) const final; + const TypeHint* replace_self_static_parent(FunctionPtr resolve_context) const final; + const TypeHint* replace_children_custom(const ReplacerCallbackT& callback) const final; + void recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr func_call) const final; - const TypeHint *resolve_field_type_hint() const; + const TypeHint* resolve_field_type_hint() const; }; /** @@ -205,22 +225,22 @@ class TypeHintRefToField : public TypeHint { * Like TypeHintRefToField, used in generics to express "a type that is returned from a method": `@ return T::getValue()` */ class TypeHintRefToMethod : public TypeHint { - explicit TypeHintRefToMethod(const TypeHint *inner, std::string method_name) - : TypeHint(0) - , inner(inner) - , method_name(std::move(method_name)) {} + explicit TypeHintRefToMethod(const TypeHint* inner, std::string method_name) + : TypeHint(0), + inner(inner), + method_name(std::move(method_name)) {} public: - const TypeHint *inner; + const TypeHint* inner; std::string method_name; - static const TypeHint *create(const TypeHint *inner, const std::string &method_name); + static const TypeHint* create(const TypeHint* inner, const std::string& method_name); std::string as_human_readable() const final; - void traverse(const TraverserCallbackT &callback) const final; - const TypeHint *replace_self_static_parent(FunctionPtr resolve_context) const final; - const TypeHint *replace_children_custom(const ReplacerCallbackT &callback) const final; - void recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr func_call) const final; + void traverse(const TraverserCallbackT& callback) const final; + const TypeHint* replace_self_static_parent(FunctionPtr resolve_context) const final; + const TypeHint* replace_children_custom(const ReplacerCallbackT& callback) const final; + void recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr func_call) const final; FunctionPtr resolve_method() const; }; @@ -231,21 +251,21 @@ class TypeHintRefToMethod : public TypeHint { * The 'array' keyword means "array of anything" and is any[] in face */ class TypeHintArray : public TypeHint { - explicit TypeHintArray(const TypeHint *inner) - : TypeHint(0) - , inner(inner) {} + explicit TypeHintArray(const TypeHint* inner) + : TypeHint(0), + inner(inner) {} public: - const TypeHint *inner; + const TypeHint* inner; - static const TypeHint *create(const TypeHint *inner); - static const TypeHint *create_array_of_any(); + static const TypeHint* create(const TypeHint* inner); + static const TypeHint* create_array_of_any(); std::string as_human_readable() const final; - void traverse(const TraverserCallbackT &callback) const final; - const TypeHint *replace_self_static_parent(FunctionPtr resolve_context) const final; - const TypeHint *replace_children_custom(const ReplacerCallbackT &callback) const final; - void recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr func_call) const final; + void traverse(const TraverserCallbackT& callback) const final; + const TypeHint* replace_self_static_parent(FunctionPtr resolve_context) const final; + const TypeHint* replace_children_custom(const ReplacerCallbackT& callback) const final; + void recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr func_call) const final; }; /** @@ -254,37 +274,41 @@ class TypeHintArray : public TypeHint { */ class TypeHintCallable : public TypeHint { explicit TypeHintCallable() - : TypeHint(flag_contains_callables_inside | flag_potentially_casts_rhs | flag_contains_autogeneric_inside | flag_contains_tp_any_inside) {} + : TypeHint(flag_contains_callables_inside | flag_potentially_casts_rhs | flag_contains_autogeneric_inside | flag_contains_tp_any_inside) {} explicit TypeHintCallable(FunctionPtr f_bound_to) - : TypeHint(flag_contains_callables_inside) - , f_bound_to(std::move(f_bound_to)) {} - explicit TypeHintCallable(std::vector &&arg_types, const TypeHint *return_type) - : TypeHint(flag_contains_callables_inside | flag_potentially_casts_rhs) - , arg_types(arg_types) - , return_type(return_type) {} + : TypeHint(flag_contains_callables_inside), + f_bound_to(std::move(f_bound_to)) {} + explicit TypeHintCallable(std::vector&& arg_types, const TypeHint* return_type) + : TypeHint(flag_contains_callables_inside | flag_potentially_casts_rhs), + arg_types(arg_types), + return_type(return_type) {} - mutable InterfacePtr interface{nullptr}; // for typed callables; will be created on demand, see get_interface() + mutable InterfacePtr interface{nullptr}; // for typed callables; will be created on demand, see get_interface() public: - std::vector arg_types; // for typed callables - const TypeHint *return_type{nullptr}; // for typed callables - FunctionPtr f_bound_to{nullptr}; // for untyped callables: not just 'callable', but bound to a function + std::vector arg_types; // for typed callables + const TypeHint* return_type{nullptr}; // for typed callables + FunctionPtr f_bound_to{nullptr}; // for untyped callables: not just 'callable', but bound to a function - static const TypeHint *create(std::vector &&arg_types, const TypeHint *return_type); - static const TypeHint *create_untyped_callable(); - static const TypeHint *create_ptr_to_function(FunctionPtr f_bound_to); + static const TypeHint* create(std::vector&& arg_types, const TypeHint* return_type); + static const TypeHint* create_untyped_callable(); + static const TypeHint* create_ptr_to_function(FunctionPtr f_bound_to); - bool is_untyped_callable() const { return return_type == nullptr; } - bool is_typed_callable() const { return return_type != nullptr; } + bool is_untyped_callable() const { + return return_type == nullptr; + } + bool is_typed_callable() const { + return return_type != nullptr; + } - InterfacePtr get_interface() const; // for typed callables - ClassPtr get_lambda_class() const; // for untyped callables: a class that wraps a bound lambda + InterfacePtr get_interface() const; // for typed callables + ClassPtr get_lambda_class() const; // for untyped callables: a class that wraps a bound lambda std::string as_human_readable() const final; - void traverse(const TraverserCallbackT &callback) const final; - const TypeHint *replace_self_static_parent(FunctionPtr resolve_context) const final; - const TypeHint *replace_children_custom(const ReplacerCallbackT &callback) const final; - void recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr func_call) const final; + void traverse(const TraverserCallbackT& callback) const final; + const TypeHint* replace_self_static_parent(FunctionPtr resolve_context) const final; + const TypeHint* replace_children_custom(const ReplacerCallbackT& callback) const final; + void recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr func_call) const final; }; // an arbitrary FFI type @@ -298,22 +322,22 @@ class TypeHintCallable : public TypeHint { // ffi_cdata = CDataArray // ffi_cdata = CDataArray> class TypeHintFFIType : public TypeHint { - TypeHintFFIType(std::string scope_name, const FFIType *type) - : TypeHint(flag_contains_instances_inside) - , scope_name{std::move(scope_name)} - , type{type} {} + TypeHintFFIType(std::string scope_name, const FFIType* type) + : TypeHint(flag_contains_instances_inside), + scope_name{std::move(scope_name)}, + type{type} {} public: std::string scope_name; - const FFIType *type; + const FFIType* type; - static const TypeHint *create(const std::string &scope_name, const FFIType *type, bool move = false); + static const TypeHint* create(const std::string& scope_name, const FFIType* type, bool move = false); std::string as_human_readable() const final; - void traverse(const TraverserCallbackT &callback) const final; - const TypeHint *replace_self_static_parent(FunctionPtr resolve_context) const final; - const TypeHint *replace_children_custom(const ReplacerCallbackT &callback) const final; - void recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call) const final; + void traverse(const TraverserCallbackT& callback) const final; + const TypeHint* replace_self_static_parent(FunctionPtr resolve_context) const final; + const TypeHint* replace_children_custom(const ReplacerCallbackT& callback) const final; + void recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call) const final; }; /** @@ -321,19 +345,19 @@ class TypeHintFFIType : public TypeHint { */ class TypeHintFFIScopeArgRef : public TypeHint { explicit TypeHintFFIScopeArgRef(int arg_num) - : TypeHint(flag_contains_argref_inside) - , arg_num{arg_num} {} + : TypeHint(flag_contains_argref_inside), + arg_num{arg_num} {} public: int arg_num; - static const TypeHint *create(int arg_num); + static const TypeHint* create(int arg_num); std::string as_human_readable() const final; - void traverse(const TraverserCallbackT &callback) const final; - const TypeHint *replace_self_static_parent(FunctionPtr resolve_context) const final; - const TypeHint *replace_children_custom(const ReplacerCallbackT &callback) const final; - void recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call) const final; + void traverse(const TraverserCallbackT& callback) const final; + const TypeHint* replace_self_static_parent(FunctionPtr resolve_context) const final; + const TypeHint* replace_children_custom(const ReplacerCallbackT& callback) const final; + void recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call) const final; }; /** @@ -341,19 +365,19 @@ class TypeHintFFIScopeArgRef : public TypeHint { */ class TypeHintFFIScope : public TypeHint { explicit TypeHintFFIScope(std::string scope_name) - : TypeHint(flag_contains_instances_inside) - , scope_name{std::move(scope_name)} {} + : TypeHint(flag_contains_instances_inside), + scope_name{std::move(scope_name)} {} public: std::string scope_name; - static const TypeHint *create(const std::string &scope_name); + static const TypeHint* create(const std::string& scope_name); std::string as_human_readable() const final; - void traverse(const TraverserCallbackT &callback) const final; - const TypeHint *replace_self_static_parent(FunctionPtr resolve_context) const final; - const TypeHint *replace_children_custom(const ReplacerCallbackT &callback) const final; - void recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr call) const final; + void traverse(const TraverserCallbackT& callback) const final; + const TypeHint* replace_self_static_parent(FunctionPtr resolve_context) const final; + const TypeHint* replace_children_custom(const ReplacerCallbackT& callback) const final; + void recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr call) const final; }; /** @@ -361,22 +385,22 @@ class TypeHintFFIScope : public TypeHint { * They occur not only in functions.txt, but in phpdoc also of course */ class TypeHintFuture : public TypeHint { - explicit TypeHintFuture(PrimitiveType ptype, const TypeHint *inner) - : TypeHint(0) - , ptype(ptype) - , inner(inner) {} + explicit TypeHintFuture(PrimitiveType ptype, const TypeHint* inner) + : TypeHint(0), + ptype(ptype), + inner(inner) {} public: PrimitiveType ptype; - const TypeHint *inner; + const TypeHint* inner; - static const TypeHint *create(PrimitiveType ptype, const TypeHint *inner); + static const TypeHint* create(PrimitiveType ptype, const TypeHint* inner); std::string as_human_readable() const final; - void traverse(const TraverserCallbackT &callback) const final; - const TypeHint *replace_self_static_parent(FunctionPtr resolve_context) const final; - const TypeHint *replace_children_custom(const ReplacerCallbackT &callback) const final; - void recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr func_call) const final; + void traverse(const TraverserCallbackT& callback) const final; + const TypeHint* replace_self_static_parent(FunctionPtr resolve_context) const final; + const TypeHint* replace_children_custom(const ReplacerCallbackT& callback) const final; + void recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr func_call) const final; }; /** @@ -384,24 +408,24 @@ class TypeHintFuture : public TypeHint { * Primarily used in generics to unwrap genericT, similar to std::remove_reference. */ class TypeHintNotNull : public TypeHint { - explicit TypeHintNotNull(const TypeHint *inner, bool drop_not_null, bool drop_not_false) - : TypeHint(0) - , inner(inner) - , drop_not_null(drop_not_null) - , drop_not_false(drop_not_false) {} + explicit TypeHintNotNull(const TypeHint* inner, bool drop_not_null, bool drop_not_false) + : TypeHint(0), + inner(inner), + drop_not_null(drop_not_null), + drop_not_false(drop_not_false) {} public: - const TypeHint *inner; + const TypeHint* inner; bool drop_not_null; bool drop_not_false; - static const TypeHint *create(const TypeHint *inner, bool drop_not_null, bool drop_not_false); + static const TypeHint* create(const TypeHint* inner, bool drop_not_null, bool drop_not_false); std::string as_human_readable() const final; - void traverse(const TraverserCallbackT &callback) const final; - const TypeHint *replace_self_static_parent(FunctionPtr resolve_context) const final; - const TypeHint *replace_children_custom(const ReplacerCallbackT &callback) const final; - void recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr func_call) const final; + void traverse(const TraverserCallbackT& callback) const final; + const TypeHint* replace_self_static_parent(FunctionPtr resolve_context) const final; + const TypeHint* replace_children_custom(const ReplacerCallbackT& callback) const final; + void recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr func_call) const final; }; /** @@ -412,8 +436,8 @@ class TypeHintNotNull : public TypeHint { */ class TypeHintInstance : public TypeHint { explicit TypeHintInstance(std::string full_class_name, bool is_self_static_parent) - : TypeHint(flag_contains_instances_inside | (is_self_static_parent ? flag_contains_self_static_parent_inside : 0)) - , full_class_name(std::move(full_class_name)) {} + : TypeHint(flag_contains_instances_inside | (is_self_static_parent ? flag_contains_self_static_parent_inside : 0)), + full_class_name(std::move(full_class_name)) {} mutable ClassPtr klass; ClassPtr resolve_and_set_klass() const; @@ -421,15 +445,17 @@ class TypeHintInstance : public TypeHint { public: std::string full_class_name; - static const TypeHint *create(const std::string &full_class_name); + static const TypeHint* create(const std::string& full_class_name); std::string as_human_readable() const final; - void traverse(const TraverserCallbackT &callback) const final; - const TypeHint *replace_self_static_parent(FunctionPtr resolve_context) const final; - const TypeHint *replace_children_custom(const ReplacerCallbackT &callback) const final; - void recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr func_call) const final; + void traverse(const TraverserCallbackT& callback) const final; + const TypeHint* replace_self_static_parent(FunctionPtr resolve_context) const final; + const TypeHint* replace_children_custom(const ReplacerCallbackT& callback) const final; + void recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr func_call) const final; - ClassPtr resolve() const { return klass ?: resolve_and_set_klass(); } + ClassPtr resolve() const { + return klass ?: resolve_and_set_klass(); + } }; /** @@ -437,24 +463,24 @@ class TypeHintInstance : public TypeHint { * This class can be easily avoided, representing optional as |pipes, but it's more semantic */ class TypeHintOptional : public TypeHint { - explicit TypeHintOptional(const TypeHint *inner, bool or_null, bool or_false) - : TypeHint(0) - , inner(inner) - , or_null(or_null) - , or_false(or_false) {} + explicit TypeHintOptional(const TypeHint* inner, bool or_null, bool or_false) + : TypeHint(0), + inner(inner), + or_null(or_null), + or_false(or_false) {} public: - const TypeHint *inner; + const TypeHint* inner; bool or_null{false}; bool or_false{false}; - static const TypeHint *create(const TypeHint *inner, bool or_null, bool or_false); + static const TypeHint* create(const TypeHint* inner, bool or_null, bool or_false); std::string as_human_readable() const final; - void traverse(const TraverserCallbackT &callback) const final; - const TypeHint *replace_self_static_parent(FunctionPtr resolve_context) const final; - const TypeHint *replace_children_custom(const ReplacerCallbackT &callback) const final; - void recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr func_call) const final; + void traverse(const TraverserCallbackT& callback) const final; + const TypeHint* replace_self_static_parent(FunctionPtr resolve_context) const final; + const TypeHint* replace_children_custom(const ReplacerCallbackT& callback) const final; + void recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr func_call) const final; }; /** @@ -463,20 +489,20 @@ class TypeHintOptional : public TypeHint { * T|null|false are represented as TypeHintOptional (though leaving them as a pipe doesn't break anything) */ class TypeHintPipe : public TypeHint { - explicit TypeHintPipe(std::vector &&items) - : TypeHint(0) - , items(items) {} + explicit TypeHintPipe(std::vector&& items) + : TypeHint(0), + items(items) {} public: - std::vector items; + std::vector items; - static const TypeHint *create(std::vector &&items); + static const TypeHint* create(std::vector&& items); std::string as_human_readable() const final; - void traverse(const TraverserCallbackT &callback) const final; - const TypeHint *replace_self_static_parent(FunctionPtr resolve_context) const final; - const TypeHint *replace_children_custom(const ReplacerCallbackT &callback) const final; - void recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr func_call) const final; + void traverse(const TraverserCallbackT& callback) const final; + const TypeHint* replace_self_static_parent(FunctionPtr resolve_context) const final; + const TypeHint* replace_children_custom(const ReplacerCallbackT& callback) const final; + void recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr func_call) const final; }; /** @@ -485,19 +511,19 @@ class TypeHintPipe : public TypeHint { */ class TypeHintPrimitive : public TypeHint { explicit TypeHintPrimitive(PrimitiveType ptype) - : TypeHint(ptype == tp_any ? flag_contains_tp_any_inside : 0) - , ptype(ptype) {} + : TypeHint(ptype == tp_any ? flag_contains_tp_any_inside : 0), + ptype(ptype) {} public: PrimitiveType ptype; - static const TypeHint *create(PrimitiveType ptype); + static const TypeHint* create(PrimitiveType ptype); std::string as_human_readable() const final; - void traverse(const TraverserCallbackT &callback) const final; - const TypeHint *replace_self_static_parent(FunctionPtr resolve_context) const final; - const TypeHint *replace_children_custom(const ReplacerCallbackT &callback) const final; - void recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr func_call) const final; + void traverse(const TraverserCallbackT& callback) const final; + const TypeHint* replace_self_static_parent(FunctionPtr resolve_context) const final; + const TypeHint* replace_children_custom(const ReplacerCallbackT& callback) const final; + void recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr func_call) const final; }; /** @@ -507,16 +533,16 @@ class TypeHintPrimitive : public TypeHint { */ class TypeHintObject : public TypeHint { explicit TypeHintObject() - : TypeHint(flag_contains_autogeneric_inside | flag_contains_tp_any_inside) {} + : TypeHint(flag_contains_autogeneric_inside | flag_contains_tp_any_inside) {} public: - static const TypeHint *create(); + static const TypeHint* create(); std::string as_human_readable() const final; - void traverse(const TraverserCallbackT &callback) const final; - const TypeHint *replace_self_static_parent(FunctionPtr resolve_context) const final; - const TypeHint *replace_children_custom(const ReplacerCallbackT &callback) const final; - void recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr func_call) const final; + void traverse(const TraverserCallbackT& callback) const final; + const TypeHint* replace_self_static_parent(FunctionPtr resolve_context) const final; + const TypeHint* replace_children_custom(const ReplacerCallbackT& callback) const final; + void recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr func_call) const final; }; /** @@ -524,29 +550,29 @@ class TypeHintObject : public TypeHint { * While x and y exist as strings in TypeHint, they become Key (string keys) in TypeData subkeys */ class TypeHintShape : public TypeHint { - explicit TypeHintShape(std::vector> &&items, bool is_vararg) - : TypeHint(is_vararg ? flag_contains_tp_any_inside : 0) - , items(items) - , is_vararg(is_vararg) {} + explicit TypeHintShape(std::vector>&& items, bool is_vararg) + : TypeHint(is_vararg ? flag_contains_tp_any_inside : 0), + items(items), + is_vararg(is_vararg) {} static std::map shape_keys_storage_; public: - std::vector> items; + std::vector> items; bool is_vararg{false}; - static const TypeHint *create(std::vector> &&items, bool is_vararg); + static const TypeHint* create(std::vector>&& items, bool is_vararg); static void register_known_key(std::int64_t key_hash, std::string_view key) noexcept; - static const std::map &get_all_registered_keys() noexcept; + static const std::map& get_all_registered_keys() noexcept; std::string as_human_readable() const final; - void traverse(const TraverserCallbackT &callback) const final; - const TypeHint *replace_self_static_parent(FunctionPtr resolve_context) const final; - const TypeHint *replace_children_custom(const ReplacerCallbackT &callback) const final; - void recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr func_call) const final; + void traverse(const TraverserCallbackT& callback) const final; + const TypeHint* replace_self_static_parent(FunctionPtr resolve_context) const final; + const TypeHint* replace_children_custom(const ReplacerCallbackT& callback) const final; + void recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr func_call) const final; - const TypeHint *find_at(const std::string &key) const; + const TypeHint* find_at(const std::string& key) const; }; /** @@ -554,20 +580,20 @@ class TypeHintShape : public TypeHint { * T_i can be any other type, even another tuple, it will me correctly parsed and mapped to TypeData */ class TypeHintTuple : public TypeHint { - explicit TypeHintTuple(std::vector &&items) - : TypeHint(0) - , items(items) {} + explicit TypeHintTuple(std::vector&& items) + : TypeHint(0), + items(items) {} public: - std::vector items; + std::vector items; - static const TypeHint *create(std::vector &&items); + static const TypeHint* create(std::vector&& items); std::string as_human_readable() const final; - void traverse(const TraverserCallbackT &callback) const final; - const TypeHint *replace_self_static_parent(FunctionPtr resolve_context) const final; - const TypeHint *replace_children_custom(const ReplacerCallbackT &callback) const final; - void recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr func_call) const final; + void traverse(const TraverserCallbackT& callback) const final; + const TypeHint* replace_self_static_parent(FunctionPtr resolve_context) const final; + const TypeHint* replace_children_custom(const ReplacerCallbackT& callback) const final; + void recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr func_call) const final; }; /** @@ -576,19 +602,19 @@ class TypeHintTuple : public TypeHint { */ class TypeHintGenericT : public TypeHint { explicit TypeHintGenericT(std::string nameT) - : TypeHint(flag_contains_genericT_inside) - , nameT(std::move(nameT)) {} + : TypeHint(flag_contains_genericT_inside), + nameT(std::move(nameT)) {} public: std::string nameT; - static const TypeHint *create(const std::string &nameT); + static const TypeHint* create(const std::string& nameT); std::string as_human_readable() const final; - void traverse(const TraverserCallbackT &callback) const final; - const TypeHint *replace_self_static_parent(FunctionPtr resolve_context) const final; - const TypeHint *replace_children_custom(const ReplacerCallbackT &callback) const final; - void recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr func_call) const final; + void traverse(const TraverserCallbackT& callback) const final; + const TypeHint* replace_self_static_parent(FunctionPtr resolve_context) const final; + const TypeHint* replace_children_custom(const ReplacerCallbackT& callback) const final; + void recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr func_call) const final; }; /** @@ -596,18 +622,18 @@ class TypeHintGenericT : public TypeHint { * Used to express parameters that are expected to be passed Some::class. */ class TypeHintClassString : public TypeHint { - explicit TypeHintClassString(const TypeHint *inner) - : TypeHint(0) - , inner(inner) {} + explicit TypeHintClassString(const TypeHint* inner) + : TypeHint(0), + inner(inner) {} public: - const TypeHint *inner; + const TypeHint* inner; - static const TypeHint *create(const TypeHint *inner); + static const TypeHint* create(const TypeHint* inner); std::string as_human_readable() const final; - void traverse(const TraverserCallbackT &callback) const final; - const TypeHint *replace_self_static_parent(FunctionPtr resolve_context) const final; - const TypeHint *replace_children_custom(const ReplacerCallbackT &callback) const final; - void recalc_type_data_in_context_of_call(TypeData *dst, VertexPtr func_call) const final; + void traverse(const TraverserCallbackT& callback) const final; + const TypeHint* replace_self_static_parent(FunctionPtr resolve_context) const final; + const TypeHint* replace_children_custom(const ReplacerCallbackT& callback) const final; + void recalc_type_data_in_context_of_call(TypeData* dst, VertexPtr func_call) const final; }; diff --git a/compiler/utils/idmap.h b/compiler/utils/idmap.h index 39125106c3..0157f89458 100644 --- a/compiler/utils/idmap.h +++ b/compiler/utils/idmap.h @@ -4,8 +4,8 @@ #pragma once -#include "compiler/stage.h" #include "common/wrappers/likely.h" +#include "compiler/stage.h" template class IdMap { @@ -15,25 +15,32 @@ class IdMap { public: using iterator = typename std::vector::iterator; - + IdMap() = default; - explicit IdMap(int size): data(size) {} + explicit IdMap(int size) + : data(size) {} template - inline DataType &operator[](const IndexType &i); + inline DataType& operator[](const IndexType& i); template - inline const DataType &operator[](const IndexType &i) const; + inline const DataType& operator[](const IndexType& i) const; - iterator begin() { return data.begin(); } - iterator end() { return data.end(); } - void clear() { data.clear(); } + iterator begin() { + return data.begin(); + } + iterator end() { + return data.end(); + } + void clear() { + data.clear(); + } void update_size(int n); }; template template -DataType &IdMap::operator[](const IndexType &i) { +DataType& IdMap::operator[](const IndexType& i) { int index = get_index(i); if (unlikely(index < 0 || index >= data.size())) { print_error_invalid_index(index); @@ -43,7 +50,7 @@ DataType &IdMap::operator[](const IndexType &i) { template template -const DataType &IdMap::operator[](const IndexType &i) const { +const DataType& IdMap::operator[](const IndexType& i) const { int index = get_index(i); if (unlikely(index < 0 || index >= data.size())) { print_error_invalid_index(index); diff --git a/compiler/utils/string-utils.h b/compiler/utils/string-utils.h index 87bd8de86a..5456066867 100644 --- a/compiler/utils/string-utils.h +++ b/compiler/utils/string-utils.h @@ -12,9 +12,9 @@ #include "common/algorithms/string-algorithms.h" #include "common/wrappers/string_view.h" -inline std::string get_full_path(const std::string &file_name) { +inline std::string get_full_path(const std::string& file_name) { char name[PATH_MAX + 1]; - char *ptr = realpath(file_name.c_str(), name); + char* ptr = realpath(file_name.c_str(), name); if (ptr == nullptr) { return ""; @@ -71,12 +71,12 @@ static inline int conv_hex_digit(int c) { } inline vk::string_view string_view_dup(vk::string_view s) { - char *buf = new char[s.size()]; + char* buf = new char[s.size()]; memcpy(buf, s.begin(), s.size()); return {buf, buf + s.size()}; } -inline std::vector split(const std::string &s, char delimiter = ' ') { +inline std::vector split(const std::string& s, char delimiter = ' ') { std::vector res; int prev = 0; @@ -113,8 +113,8 @@ static inline std::string replace_characters(std::string s, char from, char to) return s; } -static inline void replace_non_alphanum_inplace(std::string &s, char to = '_') { - //std::not_fn +static inline void replace_non_alphanum_inplace(std::string& s, char to = '_') { + // std::not_fn std::replace_if(s.begin(), s.end(), [](auto c) { return !is_alphanum(c); }, to); } @@ -123,24 +123,24 @@ static inline std::string replace_non_alphanum(std::string s, char to = '_') { return s; } -static inline std::string replace_backslashes(const std::string &s) { +static inline std::string replace_backslashes(const std::string& s) { return replace_characters(s, '\\', '$'); } -static inline std::string replace_call_string_to_readable(const std::string &s_with_$) { +static inline std::string replace_call_string_to_readable(const std::string& s_with_$) { std::string repl = vk::replace_all(s_with_$, "$$", "::"); repl = vk::replace_all(repl, "$", "\\"); return repl; } -static inline void remove_extra_spaces(std::string &str) { +static inline void remove_extra_spaces(std::string& str) { std::replace_if(str.begin(), str.end(), isspace, ' '); str = static_cast(vk::trim(str)); auto new_end = std::unique(str.begin(), str.end(), [](char lhs, char rhs) { return (lhs == rhs) && lhs == ' '; }); str.erase(new_end, str.end()); } -static inline bool is_string_self_static_parent(const std::string &s) { +static inline bool is_string_self_static_parent(const std::string& s) { return s == "self" || s == "static" || s == "parent"; } diff --git a/compiler/utils/trie.h b/compiler/utils/trie.h index f2245a1795..752b8dd64f 100644 --- a/compiler/utils/trie.h +++ b/compiler/utils/trie.h @@ -17,8 +17,8 @@ struct Trie : private vk::not_copyable { std::array, 256> next{}; std::optional val; - void add(const std::string &s, T val) { - Trie *cur = this; + void add(const std::string& s, T val) { + Trie* cur = this; for (char c : s) { if (cur->next[c] == nullptr) { @@ -31,8 +31,8 @@ struct Trie : private vk::not_copyable { cur->val = std::move(val); } - std::optional get_deepest(const char *s) { - auto *best = this; + std::optional get_deepest(const char* s) { + auto* best = this; for (auto cur = this; *s && cur; ++s) { cur = cur->next[static_cast(*s)].get(); @@ -44,4 +44,3 @@ struct Trie : private vk::not_copyable { return best->val; } }; - diff --git a/compiler/vertex-meta_op_base.h b/compiler/vertex-meta_op_base.h index 4bd5ba07e9..c1ce8a541a 100644 --- a/compiler/vertex-meta_op_base.h +++ b/compiler/vertex-meta_op_base.h @@ -15,18 +15,18 @@ #include "compiler/inferring/primitive-type.h" template -vertex_inner *raw_create_vertex_inner(int args_n); +vertex_inner* raw_create_vertex_inner(int args_n); class TypeHint; -enum class SwitchKind: uint8_t { +enum class SwitchKind : uint8_t { EmptySwitch, // switch with no expr cases IntSwitch, // switch with int-only constexpr cases StringSwitch, // switch with string-only constexpr VarSwitch, // switch with arbitrary (mixed) expr cases }; -enum class InstancePropAccessType: uint8_t { +enum class InstancePropAccessType : uint8_t { Default, // normal instance prop access CData, // accessing a FFI field through php2c level CDataDirect, // accessing a FFI field directly (using '.') @@ -38,14 +38,15 @@ template<> class vertex_inner { public: using value_type = VertexPtr; - using xiterator = value_type *; - using const_xiterator = const value_type *; + using xiterator = value_type*; + using const_xiterator = const value_type*; using iterator = std::reverse_iterator; using const_iterator = std::reverse_iterator; private: Operation type_; int n; + public: tinf::ExprNode tinf_node; Location location; @@ -60,55 +61,53 @@ class vertex_inner { bool auto_inserted : 1; // this flag is true if this vertex was auto-generated by the compiler (but it may be unset for some vertices anyway) private: - VertexPtr *arr() const { - return (VertexPtr *)this - 1; + VertexPtr* arr() const { + return (VertexPtr*)this - 1; } protected: + bool check_range(int i) const { + return 0 <= i && i < size(); + } - bool check_range(int i) const { return 0 <= i && i < size(); } - - VertexPtr &ith(int i) { + VertexPtr& ith(int i) { kphp_assert(check_range(i)); return arr()[-i]; } - const VertexPtr &ith(int i) const { + const VertexPtr& ith(int i) const { kphp_assert(check_range(i)); return arr()[-i]; } - public: - vertex_inner() : - type_(op_none), - n(-1), - tinf_node(VertexPtr(this)), - location(), - extra_type(op_ex_none), - rl_type(val_error), - val_ref_flag(val_none), - const_type(cnst_error_), - ref_flag(false), - throw_flag(false), - used_flag(false), - auto_inserted(false) { - } - - vertex_inner(const vertex_inner &from) : - type_(from.type_), - n(-1), - tinf_node(VertexPtr(this)), - location(from.location), - extra_type(from.extra_type), - rl_type(from.rl_type), - val_ref_flag(from.val_ref_flag), - const_type(from.const_type), - ref_flag(from.ref_flag), - throw_flag(from.throw_flag), - used_flag(from.used_flag), - auto_inserted(from.auto_inserted) { - } + vertex_inner() + : type_(op_none), + n(-1), + tinf_node(VertexPtr(this)), + location(), + extra_type(op_ex_none), + rl_type(val_error), + val_ref_flag(val_none), + const_type(cnst_error_), + ref_flag(false), + throw_flag(false), + used_flag(false), + auto_inserted(false) {} + + vertex_inner(const vertex_inner& from) + : type_(from.type_), + n(-1), + tinf_node(VertexPtr(this)), + location(from.location), + extra_type(from.extra_type), + rl_type(from.rl_type), + val_ref_flag(from.val_ref_flag), + const_type(from.const_type), + ref_flag(from.ref_flag), + throw_flag(from.throw_flag), + used_flag(from.used_flag), + auto_inserted(from.auto_inserted) {} virtual ~vertex_inner() {} @@ -116,134 +115,166 @@ class vertex_inner { kphp_assert(n == -1); n = real_n; for (int i = 0; i < n; i++) { - new(&ith(i)) VertexPtr(); + new (&ith(i)) VertexPtr(); } } - void raw_copy(const vertex_inner &from) { + void raw_copy(const vertex_inner& from) { kphp_assert(n == -1); n = from.size(); for (int i = 0; i < n; i++) { - new(&ith(i)) VertexPtr(from.ith(i).clone()); + new (&ith(i)) VertexPtr(from.ith(i).clone()); } } - int size() const { return n; } + int size() const { + return n; + } - VertexPtr &front() { return ith(0); } + VertexPtr& front() { + return ith(0); + } - VertexPtr &back() { return ith(size() - 1); } + VertexPtr& back() { + return ith(size() - 1); + } - std::vector get_next() { return {begin(), end()}; } + std::vector get_next() { + return {begin(), end()}; + } - bool empty() const { return size() == 0; } + bool empty() const { + return size() == 0; + } - iterator begin() { return iterator(arr() + 1); } + iterator begin() { + return iterator(arr() + 1); + } - iterator end() { return iterator(arr() - size() + 1); } + iterator end() { + return iterator(arr() - size() + 1); + } - xiterator rbegin() { return xiterator(arr() - size() + 1); } + xiterator rbegin() { + return xiterator(arr() - size() + 1); + } - xiterator rend() { return xiterator(arr() + 1); } + xiterator rend() { + return xiterator(arr() + 1); + } - const_iterator begin() const { return const_iterator(arr() + 1); } + const_iterator begin() const { + return const_iterator(arr() + 1); + } - const_iterator end() const { return const_iterator(arr() - size() + 1); } + const_iterator end() const { + return const_iterator(arr() - size() + 1); + } - const_xiterator rbegin() const { return const_xiterator(arr() - size() + 1); } + const_xiterator rbegin() const { + return const_xiterator(arr() - size() + 1); + } - const_xiterator rend() const { return const_xiterator(arr() - 1); } + const_xiterator rend() const { + return const_xiterator(arr() - 1); + } - const Location &get_location() const { return location; } + const Location& get_location() const { + return location; + } void init() {} - static void init_properties(OpProperties *p __attribute__((unused))) { + static void init_properties(OpProperties* p __attribute__((unused))) { p->op_str = "meta_op_base"; } - const Operation &type() const { return type_; } + const Operation& type() const { + return type_; + } - virtual const std::string &get_string() const { kphp_fail_msg (fmt_format("not supported [{}:{}]", vk::to_underlying(type_), OpInfo::str(type_))); } + virtual const std::string& get_string() const { + kphp_fail_msg(fmt_format("not supported [{}:{}]", vk::to_underlying(type_), OpInfo::str(type_))); + } - virtual void set_string(std::string) { kphp_fail_msg (fmt_format("not supported [{}:{}]", vk::to_underlying(type_), OpInfo::str(type_))); } + virtual void set_string(std::string) { + kphp_fail_msg(fmt_format("not supported [{}:{}]", vk::to_underlying(type_), OpInfo::str(type_))); + } - virtual bool has_get_string() const { return false; } + virtual bool has_get_string() const { + return false; + } template - friend vertex_inner *raw_create_vertex_inner(int args_n); + friend vertex_inner* raw_create_vertex_inner(int args_n); template - static vertex_inner *create_vararg(Args &&... args) { - vertex_inner *v = raw_create_vertex_inner(get_children_size(std::forward(args)...)); + static vertex_inner* create_vararg(Args&&... args) { + vertex_inner* v = raw_create_vertex_inner(get_children_size(std::forward(args)...)); v->set_children(0, std::forward(args)...); return v; } - static bool deep_equal(VertexPtr lhs, VertexPtr rhs) { - if (lhs == rhs) { - return true; - } - if (!lhs || !rhs) { - return false; - } + static bool deep_equal(VertexPtr lhs, VertexPtr rhs) { + if (lhs == rhs) { + return true; + } + if (!lhs || !rhs) { + return false; + } - auto get_string_def = [](VertexPtr v) { - return v->has_get_string() ? v->get_string() : ""; - }; + auto get_string_def = [](VertexPtr v) { return v->has_get_string() ? v->get_string() : ""; }; - return lhs->type() == rhs->type() && - get_string_def(lhs) == get_string_def(rhs) && - std::equal(lhs->begin(), lhs->end(), rhs->begin(), rhs->end(), deep_equal); - } + return lhs->type() == rhs->type() && get_string_def(lhs) == get_string_def(rhs) && + std::equal(lhs->begin(), lhs->end(), rhs->begin(), rhs->end(), deep_equal); + } - template - static int get_children_size(const VertexPtr &, Args &&... args) { - return 1 + get_children_size(std::forward(args)...); - } + template + static int get_children_size(const VertexPtr&, Args&&... args) { + return 1 + get_children_size(std::forward(args)...); + } - template - static int get_children_size(const std::vector> &arg, Args &&... args) { - return (int)arg.size() + get_children_size(std::forward(args)...); - } + template + static int get_children_size(const std::vector>& arg, Args&&... args) { + return (int)arg.size() + get_children_size(std::forward(args)...); + } - template - static int get_children_size(const vk::iterator_range::iterator> &arg, Args &&... args) { - return (int)arg.size() + get_children_size(std::forward(args)...); - } + template + static int get_children_size(const vk::iterator_range::iterator>& arg, Args&&... args) { + return (int)arg.size() + get_children_size(std::forward(args)...); + } - static int get_children_size() { - return 0; - } + static int get_children_size() { + return 0; + } - template - void set_children(int shift, VertexPtr arg, Args &&... args) { - ith(shift) = arg; - set_children(shift + 1, std::forward(args)...); - } + template + void set_children(int shift, VertexPtr arg, Args&&... args) { + ith(shift) = arg; + set_children(shift + 1, std::forward(args)...); + } - template - void set_children(int shift, const std::vector> &arg, Args &&... args) { - for (int i = 0, ni = (int)arg.size(); i < ni; i++) { - ith(shift + i) = arg[i]; - } - set_children(shift + (int)arg.size(), std::forward(args)...); + template + void set_children(int shift, const std::vector>& arg, Args&&... args) { + for (int i = 0, ni = (int)arg.size(); i < ni; i++) { + ith(shift + i) = arg[i]; } + set_children(shift + (int)arg.size(), std::forward(args)...); + } - template - void set_children(int shift, const vk::iterator_range::iterator> &arg, Args &&... args) { - for (int i = 0, ni = (int)arg.size(); i < ni; i++) { - ith(shift + i) = arg[i]; - } - set_children(shift + (int)arg.size(), std::forward(args)...); + template + void set_children(int shift, const vk::iterator_range::iterator>& arg, Args&&... args) { + for (int i = 0, ni = (int)arg.size(); i < ni; i++) { + ith(shift + i) = arg[i]; } + set_children(shift + (int)arg.size(), std::forward(args)...); + } - void set_children(int shift) { - kphp_assert_msg(shift == n, "???"); - } + void set_children(int shift) { + kphp_assert_msg(shift == n, "???"); + } }; using Vertex = vertex_inner; using VertexRange = vk::iterator_range; using VertexConstRange = vk::iterator_range; - diff --git a/compiler/vertex-util.cpp b/compiler/vertex-util.cpp index 56a01608da..9c90b0c6f7 100644 --- a/compiler/vertex-util.cpp +++ b/compiler/vertex-util.cpp @@ -30,7 +30,7 @@ VertexPtr VertexUtil::unwrap_inlined_define(VertexPtr v) { return v; } -const std::string *VertexUtil::get_constexpr_string(VertexPtr v) { +const std::string* VertexUtil::get_constexpr_string(VertexPtr v) { v = VertexUtil::get_actual_value(v); if (auto conv_vertex = v.try_as()) { return get_constexpr_string(conv_vertex->expr()); @@ -74,23 +74,24 @@ VertexPtr VertexUtil::create_int_const(int64_t number) { return int_v; } -VertexAdaptor VertexUtil::create_string_const(const std::string &s) { +VertexAdaptor VertexUtil::create_string_const(const std::string& s) { auto string_v = VertexAdaptor::create(); string_v->set_string(s); return string_v; } -VertexAdaptor VertexUtil::create_superlocal_var(const std::string &name_prefix, FunctionPtr cur_function) { +VertexAdaptor VertexUtil::create_superlocal_var(const std::string& name_prefix, FunctionPtr cur_function) { auto v = VertexAdaptor::create(); v->str_val = gen_unique_name(name_prefix, cur_function); v->extra_type = op_ex_var_superlocal; return v; } -VertexAdaptor VertexUtil::create_switch_vertex(FunctionPtr cur_function, VertexPtr switch_condition, std::vector &&cases) { +VertexAdaptor VertexUtil::create_switch_vertex(FunctionPtr cur_function, VertexPtr switch_condition, std::vector&& cases) { auto temp_var_condition_on_switch = create_superlocal_var("condition_on_switch", cur_function); auto temp_var_matched_with_one_case = create_superlocal_var("matched_with_one_case", cur_function); - return VertexAdaptor::create(switch_condition, temp_var_condition_on_switch, temp_var_matched_with_one_case, std::move(cases)).set_location(switch_condition); + return VertexAdaptor::create(switch_condition, temp_var_condition_on_switch, temp_var_matched_with_one_case, std::move(cases)) + .set_location(switch_condition); } VertexAdaptor VertexUtil::embrace(VertexPtr v) { @@ -102,7 +103,7 @@ VertexAdaptor VertexUtil::embrace(VertexPtr v) { void VertexUtil::func_force_return(VertexAdaptor func, VertexPtr val) { VertexPtr cmd = func->cmd(); - assert (cmd->type() == op_seq); + assert(cmd->type() == op_seq); VertexAdaptor return_node; if (val) { @@ -123,65 +124,68 @@ bool VertexUtil::is_positive_constexpr_int(VertexPtr v) { bool VertexUtil::is_const_int(VertexPtr root) { switch (root->type()) { - case op_int_const: - return true; - case op_minus: - case op_plus: - case op_not: - return is_const_int(root.as()->expr()); - case op_add: - case op_mul: - case op_sub: - case op_div: - case op_and: - case op_or: - case op_xor: - case op_shl: - case op_shr: - case op_mod: - case op_pow: - return is_const_int(root.as()->lhs()) && is_const_int(root.as()->rhs()); - default: - break; + case op_int_const: + return true; + case op_minus: + case op_plus: + case op_not: + return is_const_int(root.as()->expr()); + case op_add: + case op_mul: + case op_sub: + case op_div: + case op_and: + case op_or: + case op_xor: + case op_shl: + case op_shr: + case op_mod: + case op_pow: + return is_const_int(root.as()->lhs()) && is_const_int(root.as()->rhs()); + default: + break; } return false; } VertexPtr VertexUtil::create_conv_to(PrimitiveType targetType, VertexPtr x) { switch (targetType) { - case tp_int: - return VertexAdaptor::create(x).set_location(x); + case tp_int: + return VertexAdaptor::create(x).set_location(x); - case tp_bool: - return VertexAdaptor::create(x).set_location(x); + case tp_bool: + return VertexAdaptor::create(x).set_location(x); - case tp_string: - return VertexAdaptor::create(x).set_location(x); + case tp_string: + return VertexAdaptor::create(x).set_location(x); - case tp_float: - return VertexAdaptor::create(x).set_location(x); + case tp_float: + return VertexAdaptor::create(x).set_location(x); - case tp_array: - return VertexAdaptor::create(x).set_location(x); + case tp_array: + return VertexAdaptor::create(x).set_location(x); - case tp_regexp: - return VertexAdaptor::create(x).set_location(x); + case tp_regexp: + return VertexAdaptor::create(x).set_location(x); - case tp_mixed: - return VertexAdaptor::create(x).set_location(x); + case tp_mixed: + return VertexAdaptor::create(x).set_location(x); - default: - return x; + default: + return x; } } VertexAdaptor VertexUtil::create_conv_to_lval(PrimitiveType targetType, VertexPtr x) { switch (targetType) { - case tp_array : return VertexAdaptor::create(x).set_location(x); - case tp_int : return VertexAdaptor::create(x).set_location(x); - case tp_string: return VertexAdaptor::create(x).set_location(x); - default: - return {}; + case tp_array: + return VertexAdaptor::create(x).set_location(x); + case tp_int: + return VertexAdaptor::create(x).set_location(x); + case tp_string: + return VertexAdaptor::create(x).set_location(x); + default: + return {}; } } diff --git a/compiler/vertex-util.h b/compiler/vertex-util.h index c118e7a3a9..62cd237e26 100644 --- a/compiler/vertex-util.h +++ b/compiler/vertex-util.h @@ -15,16 +15,16 @@ class VertexUtil { public: static VertexPtr get_actual_value(VertexPtr v); static VertexPtr unwrap_inlined_define(VertexPtr v); - static const std::string *get_constexpr_string(VertexPtr v); + static const std::string* get_constexpr_string(VertexPtr v); static VertexPtr get_call_arg_ref(int arg_num, VertexPtr v_func_call); static VertexAdaptor add_call_arg(VertexPtr to_add, VertexAdaptor call, bool prepend); static VertexPtr create_conv_to(PrimitiveType targetType, VertexPtr x); static VertexAdaptor create_conv_to_lval(PrimitiveType targetType, VertexPtr x); static VertexPtr create_int_const(int64_t number); - static VertexAdaptor create_string_const(const std::string &s); + static VertexAdaptor create_string_const(const std::string& s); static VertexAdaptor create_superlocal_var(const std::string& name_prefix, FunctionPtr cur_function); - static VertexAdaptor create_switch_vertex(FunctionPtr cur_function, VertexPtr switch_condition, std::vector &&cases); + static VertexAdaptor create_switch_vertex(FunctionPtr cur_function, VertexPtr switch_condition, std::vector&& cases); static VertexPtr unwrap_array_value(VertexPtr v); static VertexPtr unwrap_string_value(VertexPtr v); diff --git a/compiler/vertex.cpp b/compiler/vertex.cpp index b82434b899..c3795b528d 100644 --- a/compiler/vertex.cpp +++ b/compiler/vertex.cpp @@ -6,11 +6,14 @@ VertexPtr clone_vertex(VertexPtr from) { switch (from->type()) { -#define FOREACH_OP(x) case x: {return VertexPtr (raw_clone_vertex_inner (*from.as()));} break; +#define FOREACH_OP(x) \ + case x: { \ + return VertexPtr(raw_clone_vertex_inner(*from.as())); \ + } break; #include "auto/compiler/vertex/foreach-op.h" - default: + default: kphp_fail(); } return {}; diff --git a/compiler/vertex.h b/compiler/vertex.h index 6e2ac9f469..98be7e469a 100644 --- a/compiler/vertex.h +++ b/compiler/vertex.h @@ -30,36 +30,38 @@ size_t vertex_inner_shift(int args_n) { } template -vertex_inner *raw_create_vertex_inner(int args_n) { +vertex_inner* raw_create_vertex_inner(int args_n) { size_t size = vertex_inner_size(args_n); size_t shift = vertex_inner_shift(args_n); - auto ptr = reinterpret_cast *>((char *)malloc(size) + shift); - new(ptr) vertex_inner(); + auto ptr = reinterpret_cast*>((char*)malloc(size) + shift); + new (ptr) vertex_inner(); ptr->raw_init(args_n); ptr->type_ = Op; return ptr; } template -vertex_inner *raw_clone_vertex_inner(const vertex_inner &from) { +vertex_inner* raw_clone_vertex_inner(const vertex_inner& from) { size_t size = vertex_inner_size((int)from.size()); size_t shift = vertex_inner_shift((int)from.size()); - auto ptr = reinterpret_cast *>((char *)malloc(size) + shift); - new(ptr) vertex_inner(from); + auto ptr = reinterpret_cast*>((char*)malloc(size) + shift); + new (ptr) vertex_inner(from); ptr->raw_copy(from); return ptr; } -template -VertexPtr create_vertex(Operation op, Args&& ...args) { +template +VertexPtr create_vertex(Operation op, Args&&... args) { switch (op) { -#define FOREACH_OP(x) case x: return VertexAdaptor::create_vararg(std::forward(args)...); +#define FOREACH_OP(x) \ + case x: \ + return VertexAdaptor::create_vararg(std::forward(args)...); #include "auto/compiler/vertex/foreach-op.h" - default: + default: kphp_fail(); } return {}; @@ -68,7 +70,7 @@ VertexPtr create_vertex(Operation op, Args&& ...args) { // op_int_const string representation can be "123", "0x123", "0002", "-123", "0b0010101" // but it is guaranteed to be a valid int inline long parse_int_from_string(VertexAdaptor v) { - const auto *start = v->get_string().c_str(); + const auto* start = v->get_string().c_str(); if (start[0] == '0' && start[1] == 'b') { return std::strtol(start + 2, nullptr, 2); From 2f39a23b7cc69ff55c731c76c0f6023ec6fd944e Mon Sep 17 00:00:00 2001 From: Denis Zubarev Date: Fri, 28 Aug 2026 15:12:53 +0300 Subject: [PATCH 2/6] update .git-blame-ignore-revs --- .git-blame-ignore-revs | 1 + 1 file changed, 1 insertion(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index f71a5f5e63..2da2445ef7 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -9,3 +9,4 @@ # apply clang-format to common, runtime, runtime-common, and runtime-light directories ff72b37bda68cf282c37a92d23bc763de6f47795 +340f945b4bb788c1ad7074e2c81bc15c345f5ccb From df3c6f4ad4bb888e8764f0860c53b380885cddd3 Mon Sep 17 00:00:00 2001 From: Denis Zubarev Date: Fri, 28 Aug 2026 15:50:18 +0300 Subject: [PATCH 3/6] fix --- common/algorithms/contains.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/common/algorithms/contains.h b/common/algorithms/contains.h index 173ab04cbb..d1d7c5fbc8 100644 --- a/common/algorithms/contains.h +++ b/common/algorithms/contains.h @@ -4,6 +4,9 @@ #pragma once #include +#include +#include +#include namespace vk { From da8a3a1db3160e6f258639c4ccb993b488072692 Mon Sep 17 00:00:00 2001 From: Denis Zubarev Date: Fri, 28 Aug 2026 17:28:00 +0300 Subject: [PATCH 4/6] update .github/workflows/pr-code-format.yml --- .github/workflows/pr-code-format.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-code-format.yml b/.github/workflows/pr-code-format.yml index a4449f63f5..a30d05edf5 100644 --- a/.github/workflows/pr-code-format.yml +++ b/.github/workflows/pr-code-format.yml @@ -56,7 +56,7 @@ jobs: run: | # Get list of changed files CHANGED_FILES=$(git diff --name-only --diff-filter=ACM origin/master...HEAD --) - CHANGED_CPP_FILES=$(echo "$CHANGED_FILES" | (grep -E '^(common|runtime|runtime-common|runtime-light)/.*\.(cpp|hpp|h|inl)$' || :; )) + CHANGED_CPP_FILES=$(echo "$CHANGED_FILES" | (grep -E '^(common|runtime|runtime-common|runtime-light|compiler)/.*\.(cpp|hpp|h|inl)$' || :; )) # Apply clang-format to each changed source file echo "$CHANGED_CPP_FILES" | xargs -r clang-format-18 -i From d7dfcd947efea311112dacb22965caefe9ce5deb Mon Sep 17 00:00:00 2001 From: Denis Zubarev Date: Fri, 28 Aug 2026 18:08:18 +0300 Subject: [PATCH 5/6] update .github/workflows/pr-code-format.yml --- .github/workflows/pr-code-format.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr-code-format.yml b/.github/workflows/pr-code-format.yml index a30d05edf5..a1715f582e 100644 --- a/.github/workflows/pr-code-format.yml +++ b/.github/workflows/pr-code-format.yml @@ -50,16 +50,16 @@ jobs: fi - name: Install clang-format - run: sudo apt-get install -y clang-format-18 + run: pip install --break-system-packages clang-format==18.1.8 - name: Run clang-format on changed files run: | # Get list of changed files CHANGED_FILES=$(git diff --name-only --diff-filter=ACM origin/master...HEAD --) CHANGED_CPP_FILES=$(echo "$CHANGED_FILES" | (grep -E '^(common|runtime|runtime-common|runtime-light|compiler)/.*\.(cpp|hpp|h|inl)$' || :; )) - + # Apply clang-format to each changed source file - echo "$CHANGED_CPP_FILES" | xargs -r clang-format-18 -i + echo "$CHANGED_CPP_FILES" | xargs -r clang-format -i - name: Check for formatting changes run: | From 94b751660af37bd2e4dc255a75f843a6178a6ade Mon Sep 17 00:00:00 2001 From: Denis Zubarev Date: Fri, 28 Aug 2026 18:29:59 +0300 Subject: [PATCH 6/6] update Check '#pragma once' --- .github/workflows/pr-code-format.yml | 2 +- compiler/lambda-utils.h | 2 ++ compiler/pipes/clone-nested-lambdas.h | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-code-format.yml b/.github/workflows/pr-code-format.yml index a1715f582e..b51d0c1709 100644 --- a/.github/workflows/pr-code-format.yml +++ b/.github/workflows/pr-code-format.yml @@ -37,7 +37,7 @@ jobs: - name: Check "#pragma once" in files run: | EXIT_CODE=0 - for file in $(find . -name '*.h' -type f \( -path './common/*' -o -path './runtime/*' -o -path './runtime-common/*' -o -path './runtime-light/*' \)); do + for file in $(find . -name '*.h' -type f \( -path './common/*' -o -path './runtime/*' -o -path './runtime-common/*' -o -path './runtime-light/*' -o -path './compiler/*' \)); do if [[ $( grep -q -E '^#pragma\ once' "$file" )$? -ne 0 ]]; then echo "Missing '#pragma once' in file '$file'" EXIT_CODE=1 diff --git a/compiler/lambda-utils.h b/compiler/lambda-utils.h index ed6088b286..7bc36c4e77 100644 --- a/compiler/lambda-utils.h +++ b/compiler/lambda-utils.h @@ -2,6 +2,8 @@ // Copyright (c) 2021 LLC «V Kontakte» // Distributed under the GPL v3 License, see LICENSE.notice.txt +#pragma once + #include "compiler/data/data_ptr.h" #include "compiler/data/vertex-adaptor.h" #include "compiler/threading/data-stream.h" diff --git a/compiler/pipes/clone-nested-lambdas.h b/compiler/pipes/clone-nested-lambdas.h index 5fd54d5cca..6712938c29 100644 --- a/compiler/pipes/clone-nested-lambdas.h +++ b/compiler/pipes/clone-nested-lambdas.h @@ -2,6 +2,8 @@ // Copyright (c) 2020 LLC «V Kontakte» // Distributed under the GPL v3 License, see LICENSE.notice.txt +#pragma once + #include "compiler/compiler-core.h" #include "compiler/data/data_ptr.h" #include "compiler/function-pass.h"