herb 0.11.1 → 0.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +4 -2
- data/config.yml +6 -0
- data/ext/herb/extconf.rb +8 -31
- data/ext/herb/nodes.c +75 -75
- data/ext/herb/parser_options_helpers.c +26 -0
- data/lib/herb/analysis/partial_index.rb +1 -1
- data/lib/herb/analysis/partial_resolution.rb +27 -0
- data/lib/herb/ast/helpers.rb +1 -1
- data/lib/herb/configuration.rb +11 -1
- data/lib/herb/dev/classifier.rb +1 -1
- data/lib/herb/engine/compiler.rb +5 -8
- data/lib/herb/engine/slots/dynamics_compiler.rb +53 -14
- data/lib/herb/engine/slots/subtree_compiler.rb +1 -1
- data/lib/herb/engine/slots/visitor.rb +32 -4
- data/lib/herb/engine/visitors/instrumentation_visitor.rb +18 -6
- data/lib/herb/parser_options.rb +6 -3
- data/lib/herb/project.rb +19 -8
- data/lib/herb/version.rb +1 -1
- data/lib/herb.rb +1 -1
- data/sig/herb/analysis/partial_resolution.rbs +8 -0
- data/sig/herb/configuration.rbs +3 -0
- data/sig/herb/engine/slots/dynamics_compiler.rbs +24 -7
- data/sig/herb/engine/slots/visitor.rbs +14 -0
- data/sig/herb/engine/visitors/instrumentation_visitor.rbs +5 -1
- data/sig/herb/parser_options.rbs +6 -4
- data/sig/herb.rbs +2 -2
- data/src/analyze/action_view/attribute_extraction_helpers.c +40 -21
- data/src/analyze/action_view/generated_handlers.c +36 -36
- data/src/analyze/action_view/image_tag.c +7 -3
- data/src/analyze/action_view/javascript_include_tag.c +6 -3
- data/src/analyze/action_view/link_to.c +23 -23
- data/src/analyze/action_view/registry.c +7 -3
- data/src/analyze/action_view/tag_helper_node_builders.c +6 -13
- data/src/analyze/action_view/tag_helpers.c +139 -90
- data/src/analyze/action_view/turbo_frame_tag.c +5 -4
- data/src/analyze/analyze.c +35 -19
- data/src/analyze/analyze_helpers.c +161 -188
- data/src/analyze/analyzed_ruby.c +8 -7
- data/src/analyze/control_type.c +29 -22
- data/src/analyze/herb_directives.c +16 -20
- data/src/analyze/iteration_nodes.c +69 -24
- data/src/analyze/parse_errors.c +32 -22
- data/src/analyze/postfix_conditionals.c +23 -13
- data/src/analyze/prism_annotate.c +29 -28
- data/src/analyze/render_nodes.c +51 -41
- data/src/analyze/strict_locals.c +14 -15
- data/src/analyze/ternary_conditionals.c +14 -10
- data/src/herb.c +10 -8
- data/src/include/analyze/action_view/tag_helper_handler.h +1 -1
- data/src/include/analyze/action_view/tag_helper_node_builders.h +1 -0
- data/src/include/analyze/action_view/tag_helpers.h +1 -1
- data/src/include/analyze/analyze.h +3 -2
- data/src/include/analyze/analyzed_ruby.h +4 -2
- data/src/include/analyze/helpers.h +6 -6
- data/src/include/herb.h +3 -2
- data/src/include/parser/parser_options.h +5 -0
- data/src/include/prism/prism_context.h +12 -12
- data/src/include/prism/prism_helpers.h +30 -0
- data/src/include/prism_version.h +11 -0
- data/src/include/version.h +1 -1
- data/src/parser/parser_helpers.c +1 -2
- data/src/parser.c +6 -7
- data/src/parser_options_defaults.c +1 -0
- data/src/prism/prism_helpers.c +84 -50
- data/src/prism/ruby_parser.c +20 -20
- data/templates/ext/herb/nodes.c.erb +5 -5
- data/templates/ext/herb/parser_options_helpers.c.erb +33 -0
- data/templates/java/nodes.c.erb +6 -6
- data/templates/java/parser_options_helpers.c.erb +41 -2
- data/templates/java/parser_options_helpers.h.erb +2 -1
- data/templates/javascript/packages/node/extension/nodes.cpp.erb +5 -5
- data/templates/javascript/packages/node/extension/parser_options_helpers.cpp.erb +34 -2
- data/templates/javascript/packages/node/extension/parser_options_helpers.h.erb +1 -1
- data/templates/lib/herb/parser_options.rb.erb +1 -1
- data/templates/rust/src/prism/generated_deserialize.rs.erb +90 -44
- data/templates/rust/src/prism/generated_prettyprint.rs.erb +18 -27
- data/templates/src/analyze/action_view/generated_handlers.c.erb +23 -22
- data/templates/src/include/parser/parser_options.h.erb +10 -0
- data/templates/src/include/prism_version.h.erb +17 -0
- data/templates/src/parser_options_defaults.c.erb +1 -1
- data/templates/template.rb +17 -2
- data/templates/wasm/nodes.cpp.erb +5 -5
- data/templates/wasm/parser_options_helpers.cpp.erb +24 -0
- data/vendor/prism/Rakefile +76 -7
- data/vendor/prism/config.yml +174 -161
- data/vendor/prism/include/prism/arena.h +45 -0
- data/vendor/prism/include/prism/arena.hpp +42 -0
- data/vendor/prism/include/prism/ast.h +2738 -611
- data/vendor/prism/include/prism/ast.hpp +641 -0
- data/vendor/prism/include/prism/buffer.h +60 -0
- data/vendor/prism/include/prism/buffer.hpp +55 -0
- data/vendor/prism/include/prism/comments.h +72 -0
- data/vendor/prism/include/prism/compiler/accel.h +26 -0
- data/vendor/prism/include/prism/compiler/align.h +36 -0
- data/vendor/prism/include/prism/compiler/assume.h +25 -0
- data/vendor/prism/include/prism/compiler/branch.h +26 -0
- data/vendor/prism/include/prism/compiler/bswap.h +46 -0
- data/vendor/prism/include/prism/compiler/cplusplus.hpp +16 -0
- data/vendor/prism/include/prism/compiler/endianness.h +34 -0
- data/vendor/prism/include/prism/compiler/exceptions.hpp +17 -0
- data/vendor/prism/include/prism/compiler/exported.h +24 -0
- data/vendor/prism/include/prism/compiler/fallthrough.h +22 -0
- data/vendor/prism/include/prism/compiler/filesystem.h +32 -0
- data/vendor/prism/include/prism/compiler/flex_array.h +19 -0
- data/vendor/prism/include/prism/compiler/force_inline.h +21 -0
- data/vendor/prism/include/prism/compiler/format.h +27 -0
- data/vendor/prism/include/prism/compiler/inline.h +17 -0
- data/vendor/prism/include/prism/compiler/lifetimebound.hpp +25 -0
- data/vendor/prism/include/prism/compiler/nodiscard.h +22 -0
- data/vendor/prism/include/prism/compiler/nonnull.h +18 -0
- data/vendor/prism/include/prism/compiler/unused.h +18 -0
- data/vendor/prism/include/prism/constant_pool.h +106 -0
- data/vendor/prism/include/prism/diagnostic.h +55 -402
- data/vendor/prism/include/prism/errors_format.h +61 -0
- data/vendor/prism/include/prism/excludes.h +29 -0
- data/vendor/prism/include/prism/integer.h +41 -0
- data/vendor/prism/include/prism/internal/allocator.h +68 -0
- data/vendor/prism/include/prism/internal/allocator_debug.h +88 -0
- data/vendor/prism/include/prism/internal/arena.h +108 -0
- data/vendor/prism/include/prism/internal/bit.h +42 -0
- data/vendor/prism/include/prism/internal/buffer.h +94 -0
- data/vendor/prism/include/prism/internal/char.h +145 -0
- data/vendor/prism/include/prism/internal/comments.h +54 -0
- data/vendor/prism/include/prism/internal/constant_pool.h +152 -0
- data/vendor/prism/include/prism/internal/diagnostic.h +389 -0
- data/vendor/prism/include/prism/{encoding.h → internal/encoding.h} +27 -68
- data/vendor/prism/include/prism/internal/integer.h +68 -0
- data/vendor/prism/include/prism/internal/isinf.h +16 -0
- data/vendor/prism/include/prism/internal/line_offset_list.h +34 -0
- data/vendor/prism/include/prism/{util/pm_list.h → internal/list.h} +11 -52
- data/vendor/prism/include/prism/internal/magic_comments.h +23 -0
- data/vendor/prism/include/prism/internal/memchr.h +15 -0
- data/vendor/prism/include/prism/internal/node.h +42 -0
- data/vendor/prism/include/prism/internal/options.h +232 -0
- data/vendor/prism/include/prism/internal/parser.h +1015 -0
- data/vendor/prism/include/prism/internal/regexp.h +26 -0
- data/vendor/prism/include/prism/internal/serialize.h +39 -0
- data/vendor/prism/include/prism/internal/source.h +72 -0
- data/vendor/prism/include/prism/internal/static_literals.h +60 -0
- data/vendor/prism/include/prism/internal/stringy.h +30 -0
- data/vendor/prism/include/prism/{util/pm_strncasecmp.h → internal/strncasecmp.h} +3 -17
- data/vendor/prism/include/prism/{util/pm_strpbrk.h → internal/strpbrk.h} +7 -20
- data/vendor/prism/include/prism/internal/tokens.h +11 -0
- data/vendor/prism/include/prism/internal/xxh3.h +16 -0
- data/vendor/prism/include/prism/json.h +40 -0
- data/vendor/prism/include/prism/line_offset_list.h +69 -0
- data/vendor/prism/include/prism/magic_comments.h +53 -0
- data/vendor/prism/include/prism/node.h +59 -49
- data/vendor/prism/include/prism/node.hpp +272 -0
- data/vendor/prism/include/prism/node_type.hpp +38 -0
- data/vendor/prism/include/prism/options.h +154 -279
- data/vendor/prism/include/prism/options.hpp +43 -0
- data/vendor/prism/include/prism/parser.h +367 -870
- data/vendor/prism/include/prism/parser.hpp +274 -0
- data/vendor/prism/include/prism/prettyprint.h +14 -9
- data/vendor/prism/include/prism/serialize.h +123 -0
- data/vendor/prism/include/prism/source.h +163 -0
- data/vendor/prism/include/prism/stream.h +36 -0
- data/vendor/prism/include/prism/string_query.h +82 -0
- data/vendor/prism/include/prism/stringy.h +61 -0
- data/vendor/prism/include/prism/stringy.hpp +31 -0
- data/vendor/prism/include/prism/version.h +20 -3
- data/vendor/prism/include/prism.h +35 -320
- data/vendor/prism/include/prism.hpp +24 -0
- data/vendor/prism/src/arena.c +122 -0
- data/vendor/prism/src/{util/pm_buffer.c → buffer.c} +53 -21
- data/vendor/prism/src/{util/pm_char.c → char.c} +28 -57
- data/vendor/prism/src/comments.c +455 -0
- data/vendor/prism/src/constant_pool.c +406 -0
- data/vendor/prism/src/diagnostic.c +120 -68
- data/vendor/prism/src/encoding.c +8 -3
- data/vendor/prism/src/errors_format.c +519 -0
- data/vendor/prism/src/{util/pm_integer.c → integer.c} +38 -22
- data/vendor/prism/src/json.c +5733 -0
- data/vendor/prism/src/line_offset_list.c +100 -0
- data/vendor/prism/src/list.c +24 -0
- data/vendor/prism/src/{util/pm_memchr.c → memchr.c} +8 -6
- data/vendor/prism/src/node.c +3465 -7787
- data/vendor/prism/src/options.c +161 -54
- data/vendor/prism/src/parser.c +371 -0
- data/vendor/prism/src/prettyprint.c +421 -354
- data/vendor/prism/src/prism.c +8522 -7280
- data/vendor/prism/src/regexp.c +960 -45
- data/vendor/prism/src/serialize.c +2434 -2048
- data/vendor/prism/src/source.c +524 -0
- data/vendor/prism/src/static_literals.c +303 -360
- data/vendor/prism/src/string_query.c +180 -0
- data/vendor/prism/src/stringy.c +61 -0
- data/vendor/prism/src/{util/pm_strncasecmp.c → strncasecmp.c} +5 -4
- data/vendor/prism/src/strpbrk.c +447 -0
- data/vendor/prism/src/{token_type.c → tokens.c} +39 -18
- data/vendor/prism/src/xxh3.c +292 -0
- data/vendor/prism/templates/ext/prism/api_node.c.erb +58 -44
- data/vendor/prism/templates/include/prism/ast.h.erb +67 -17
- data/vendor/prism/templates/include/prism/ast.hpp.erb +31 -0
- data/vendor/prism/templates/include/prism/internal/diagnostic.h.erb +60 -0
- data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/AbstractNodeVisitor.java.erb +1 -1
- data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/Loader.java.erb +232 -133
- data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/Nodes.java.erb +62 -23
- data/vendor/prism/templates/javascript/src/deserialize.js.erb +153 -146
- data/vendor/prism/templates/javascript/src/nodes.js.erb +4 -9
- data/vendor/prism/templates/lib/prism/compiler.rb.erb +14 -5
- data/vendor/prism/templates/lib/prism/dispatcher.rb.erb +20 -12
- data/vendor/prism/templates/lib/prism/dot_visitor.rb.erb +37 -11
- data/vendor/prism/templates/lib/prism/dsl.rb.erb +43 -4
- data/vendor/prism/templates/lib/prism/inspect_visitor.rb.erb +26 -10
- data/vendor/prism/templates/lib/prism/mutation_compiler.rb.erb +5 -2
- data/vendor/prism/templates/lib/prism/node.rb.erb +283 -105
- data/vendor/prism/templates/lib/prism/reflection.rb.erb +11 -2
- data/vendor/prism/templates/lib/prism/serialize.rb.erb +291 -134
- data/vendor/prism/templates/lib/prism/visitor.rb.erb +18 -0
- data/vendor/prism/templates/src/diagnostic.c.erb +114 -63
- data/vendor/prism/templates/src/json.c.erb +130 -0
- data/vendor/prism/templates/src/node.c.erb +79 -236
- data/vendor/prism/templates/src/prettyprint.c.erb +24 -13
- data/vendor/prism/templates/src/serialize.c.erb +369 -183
- data/vendor/prism/templates/src/{token_type.c.erb → tokens.c.erb} +22 -11
- data/vendor/prism/templates/template.rb +193 -91
- metadata +100 -42
- data/vendor/prism/include/prism/defines.h +0 -260
- data/vendor/prism/include/prism/pack.h +0 -163
- data/vendor/prism/include/prism/regexp.h +0 -43
- data/vendor/prism/include/prism/static_literals.h +0 -121
- data/vendor/prism/include/prism/util/pm_buffer.h +0 -236
- data/vendor/prism/include/prism/util/pm_char.h +0 -204
- data/vendor/prism/include/prism/util/pm_constant_pool.h +0 -218
- data/vendor/prism/include/prism/util/pm_integer.h +0 -130
- data/vendor/prism/include/prism/util/pm_memchr.h +0 -29
- data/vendor/prism/include/prism/util/pm_newline_list.h +0 -113
- data/vendor/prism/include/prism/util/pm_string.h +0 -200
- data/vendor/prism/src/pack.c +0 -509
- data/vendor/prism/src/util/pm_constant_pool.c +0 -342
- data/vendor/prism/src/util/pm_list.c +0 -49
- data/vendor/prism/src/util/pm_newline_list.c +0 -125
- data/vendor/prism/src/util/pm_string.c +0 -381
- data/vendor/prism/src/util/pm_strpbrk.c +0 -206
- data/vendor/prism/templates/include/prism/diagnostic.h.erb +0 -130
- data/vendor/prism/templates/rbi/prism/dsl.rbi.erb +0 -68
- data/vendor/prism/templates/rbi/prism/node.rbi.erb +0 -167
- data/vendor/prism/templates/rbi/prism/visitor.rbi.erb +0 -18
- data/vendor/prism/templates/sig/prism/_private/dot_visitor.rbs.erb +0 -45
- data/vendor/prism/templates/sig/prism/dsl.rbs.erb +0 -31
- data/vendor/prism/templates/sig/prism/mutation_compiler.rbs.erb +0 -7
- data/vendor/prism/templates/sig/prism/node.rbs.erb +0 -136
- data/vendor/prism/templates/sig/prism/visitor.rbs.erb +0 -17
- data/vendor/prism/templates/sig/prism.rbs.erb +0 -92
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file ast.hpp
|
|
3
|
+
*
|
|
4
|
+
* The mapping between node structs and node types, generated from the same
|
|
5
|
+
* configuration as ast.h so that it covers every node.
|
|
6
|
+
*/
|
|
7
|
+
#ifndef PRISM_AST_HPP
|
|
8
|
+
#define PRISM_AST_HPP
|
|
9
|
+
|
|
10
|
+
#include "prism/compiler/cplusplus.hpp"
|
|
11
|
+
|
|
12
|
+
#include "prism/ast.h"
|
|
13
|
+
#include "prism/node_type.hpp"
|
|
14
|
+
|
|
15
|
+
#include <cstddef>
|
|
16
|
+
#include <type_traits>
|
|
17
|
+
|
|
18
|
+
namespace prism {
|
|
19
|
+
|
|
20
|
+
/* Each node struct is cast to and from pm_node_t, which C++ allows only
|
|
21
|
+
* because the struct is standard-layout with pm_node_t as its first member. */
|
|
22
|
+
<%- nodes.each do |node| -%>
|
|
23
|
+
|
|
24
|
+
/** Maps pm_<%= node.human %>_t to <%= node.type %>. */
|
|
25
|
+
template <> struct node_type<pm_<%= node.human %>_t> : std::integral_constant<pm_node_type_t, <%= node.type %>> {};
|
|
26
|
+
static_assert(std::is_standard_layout_v<pm_<%= node.human %>_t> && offsetof(pm_<%= node.human %>_t, base) == 0, "pm_<%= node.human %>_t must begin with its pm_node_t");
|
|
27
|
+
<%- end -%>
|
|
28
|
+
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
#endif
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#ifndef PRISM_INTERNAL_DIAGNOSTIC_H
|
|
2
|
+
#define PRISM_INTERNAL_DIAGNOSTIC_H
|
|
3
|
+
|
|
4
|
+
#include "prism/internal/list.h"
|
|
5
|
+
|
|
6
|
+
#include "prism/arena.h"
|
|
7
|
+
#include "prism/diagnostic.h"
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
* The diagnostic IDs of all of the diagnostics, used to communicate the types
|
|
11
|
+
* of errors between the parser and the user.
|
|
12
|
+
*/
|
|
13
|
+
typedef enum {
|
|
14
|
+
/* These are the error diagnostics. */
|
|
15
|
+
<%- errors.each do |error| -%>
|
|
16
|
+
PM_ERR_<%= error.name %>,
|
|
17
|
+
<%- end -%>
|
|
18
|
+
|
|
19
|
+
/* These are the warning diagnostics. */
|
|
20
|
+
<%- warnings.each do |warning| -%>
|
|
21
|
+
PM_WARN_<%= warning.name %>,
|
|
22
|
+
<%- end -%>
|
|
23
|
+
} pm_diagnostic_id_t;
|
|
24
|
+
|
|
25
|
+
/*
|
|
26
|
+
* This struct represents a diagnostic generated during parsing.
|
|
27
|
+
*/
|
|
28
|
+
struct pm_diagnostic_t {
|
|
29
|
+
/* The embedded base node. */
|
|
30
|
+
pm_list_node_t node;
|
|
31
|
+
|
|
32
|
+
/* The location of the diagnostic in the source. */
|
|
33
|
+
pm_location_t location;
|
|
34
|
+
|
|
35
|
+
/* The ID of the diagnostic. */
|
|
36
|
+
pm_diagnostic_id_t diag_id;
|
|
37
|
+
|
|
38
|
+
/* The message associated with the diagnostic. */
|
|
39
|
+
const char *message;
|
|
40
|
+
|
|
41
|
+
/*
|
|
42
|
+
* The level of the diagnostic, see `pm_error_level_t` and
|
|
43
|
+
* `pm_warning_level_t` for possible values.
|
|
44
|
+
*/
|
|
45
|
+
uint8_t level;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/*
|
|
49
|
+
* Append a diagnostic to the given list of diagnostics that is using shared
|
|
50
|
+
* memory for its message.
|
|
51
|
+
*/
|
|
52
|
+
void pm_diagnostic_list_append(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id);
|
|
53
|
+
|
|
54
|
+
/*
|
|
55
|
+
* Append a diagnostic to the given list of diagnostics that is using a format
|
|
56
|
+
* string for its message.
|
|
57
|
+
*/
|
|
58
|
+
void pm_diagnostic_list_append_format(pm_arena_t *arena, pm_list_t *list, uint32_t start, uint32_t length, pm_diagnostic_id_t diag_id, ...);
|
|
59
|
+
|
|
60
|
+
#endif
|
|
@@ -1,77 +1,67 @@
|
|
|
1
|
-
<%-
|
|
2
|
-
package org.prism;
|
|
3
|
-
|
|
4
|
-
import org.prism.Nodes;
|
|
1
|
+
<%- id_type = Prism::Template::JAVA_IDENTIFIER_TYPE -%>
|
|
2
|
+
package org.ruby_lang.prism;
|
|
5
3
|
|
|
6
4
|
import java.lang.Short;
|
|
7
5
|
import java.math.BigInteger;
|
|
8
6
|
import java.nio.ByteBuffer;
|
|
9
7
|
import java.nio.ByteOrder;
|
|
10
|
-
import java.nio.charset.Charset;
|
|
11
8
|
import java.nio.charset.StandardCharsets;
|
|
12
|
-
import java.util.Locale;
|
|
13
9
|
|
|
14
10
|
// GENERATED BY <%= File.basename(__FILE__) %>
|
|
15
11
|
// @formatter:off
|
|
16
12
|
public class Loader {
|
|
17
13
|
|
|
18
|
-
public static ParseResult load(byte[] serialized
|
|
19
|
-
return new Loader(serialized
|
|
14
|
+
public static ParseResult load(byte[] serialized) {
|
|
15
|
+
return new Loader(serialized).load();
|
|
20
16
|
}
|
|
21
17
|
|
|
22
18
|
// Overridable methods
|
|
23
19
|
|
|
24
|
-
public
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return Charset.forName(encodingName);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
public <%= string_type %> bytesToName(byte[] bytes) {
|
|
33
|
-
<%- if string_type == "String" -%>
|
|
34
|
-
return new String(bytes, encodingCharset).intern();
|
|
20
|
+
public <%= id_type %> bytesToName(byte[] serialized, int offset, int length) {
|
|
21
|
+
<%- if id_type == "byte[]" -%>
|
|
22
|
+
byte[] bytes = new byte[length];
|
|
23
|
+
System.arraycopy(serialized, offset, bytes, 0, length);
|
|
24
|
+
return bytes;
|
|
35
25
|
<%- else -%>
|
|
36
|
-
|
|
26
|
+
throw new AbstractMethodError("Loader.bytesToName(<%= id_type %>) is not implemented");
|
|
37
27
|
<%- end -%>
|
|
38
28
|
}
|
|
39
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Whether to skip the bodies of DefNodes while loading. A lazily loaded
|
|
32
|
+
* DefNode has a null body until it is replaced with DefNode#getNonLazy(),
|
|
33
|
+
* which loads the whole DefNode again from the serialized output.
|
|
34
|
+
*/
|
|
35
|
+
protected boolean loadDefNodesLazily() {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
|
|
40
39
|
private static final class ConstantPool {
|
|
41
40
|
|
|
42
41
|
private final Loader loader;
|
|
43
|
-
private final byte[] source;
|
|
44
42
|
private final int bufferOffset;
|
|
45
|
-
private final <%=
|
|
43
|
+
private final <%= id_type %>[] cache;
|
|
46
44
|
|
|
47
|
-
ConstantPool(Loader loader,
|
|
45
|
+
ConstantPool(Loader loader, int bufferOffset, int length) {
|
|
48
46
|
this.loader = loader;
|
|
49
|
-
this.source = source;
|
|
50
47
|
this.bufferOffset = bufferOffset;
|
|
51
|
-
|
|
48
|
+
<%- if id_type == "String" -%>
|
|
49
|
+
this.cache = new <%= id_type %>[length];
|
|
50
|
+
<%- else -%>
|
|
51
|
+
this.cache = new byte[length][];
|
|
52
|
+
<%- end -%>
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
<%=
|
|
55
|
+
<%= id_type %> get(ByteBuffer buffer, int oneBasedIndex) {
|
|
55
56
|
int index = oneBasedIndex - 1;
|
|
56
|
-
<%=
|
|
57
|
+
<%= id_type %> constant = cache[index];
|
|
57
58
|
|
|
58
59
|
if (constant == null) {
|
|
59
60
|
int offset = bufferOffset + index * 8;
|
|
60
61
|
int start = buffer.getInt(offset);
|
|
61
62
|
int length = buffer.getInt(offset + 4);
|
|
62
63
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (Integer.compareUnsigned(start, 0x7FFFFFFF) <= 0) {
|
|
66
|
-
System.arraycopy(source, start, bytes, 0, length);
|
|
67
|
-
} else {
|
|
68
|
-
int position = buffer.position();
|
|
69
|
-
buffer.position(start & 0x7FFFFFFF);
|
|
70
|
-
buffer.get(bytes, 0, length);
|
|
71
|
-
buffer.position(position);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
constant = loader.bytesToName(bytes);
|
|
64
|
+
constant = loader.bytesToName(loader.serialized, start, length);
|
|
75
65
|
cache[index] = constant;
|
|
76
66
|
}
|
|
77
67
|
|
|
@@ -80,28 +70,28 @@ public class Loader {
|
|
|
80
70
|
|
|
81
71
|
}
|
|
82
72
|
|
|
73
|
+
private final byte[] serialized;
|
|
83
74
|
private final ByteBuffer buffer;
|
|
84
|
-
private final Nodes.Source source;
|
|
85
75
|
protected String encodingName;
|
|
86
|
-
<%- if string_type == "String" -%>
|
|
87
|
-
private Charset encodingCharset;
|
|
88
|
-
<%- end -%>
|
|
89
76
|
private ConstantPool constantPool;
|
|
77
|
+
private Nodes.Source source = null;
|
|
90
78
|
|
|
91
|
-
protected Loader(byte[] serialized
|
|
79
|
+
protected Loader(byte[] serialized) {
|
|
80
|
+
this.serialized = serialized;
|
|
92
81
|
this.buffer = ByteBuffer.wrap(serialized).order(ByteOrder.nativeOrder());
|
|
93
|
-
this.source = new Nodes.Source(sourceBytes);
|
|
94
82
|
}
|
|
95
83
|
|
|
96
84
|
protected ParseResult load() {
|
|
85
|
+
this.source = new Nodes.Source();
|
|
86
|
+
|
|
97
87
|
expect((byte) 'P', "incorrect prism header");
|
|
98
88
|
expect((byte) 'R', "incorrect prism header");
|
|
99
89
|
expect((byte) 'I', "incorrect prism header");
|
|
100
90
|
expect((byte) 'S', "incorrect prism header");
|
|
101
91
|
expect((byte) 'M', "incorrect prism header");
|
|
102
92
|
|
|
103
|
-
expect((byte)
|
|
104
|
-
expect((byte)
|
|
93
|
+
expect((byte) 2, "prism major version does not match");
|
|
94
|
+
expect((byte) 1, "prism minor version does not match");
|
|
105
95
|
expect((byte) 0, "prism patch version does not match");
|
|
106
96
|
|
|
107
97
|
expect((byte) 1, "Loader.java requires no location fields in the serialized output");
|
|
@@ -111,63 +101,49 @@ public class Loader {
|
|
|
111
101
|
byte[] encodingNameBytes = new byte[encodingLength];
|
|
112
102
|
buffer.get(encodingNameBytes);
|
|
113
103
|
this.encodingName = new String(encodingNameBytes, StandardCharsets.US_ASCII);
|
|
114
|
-
<%- if string_type == "String" -%>
|
|
115
|
-
this.encodingCharset = getEncodingCharset(this.encodingName);
|
|
116
|
-
<%- end -%>
|
|
117
104
|
|
|
118
105
|
source.setStartLine(loadVarSInt());
|
|
106
|
+
|
|
107
|
+
// Skip the 8-byte hash of the source, which this library does not expose.
|
|
108
|
+
buffer.getLong();
|
|
109
|
+
|
|
119
110
|
source.setLineOffsets(loadLineOffsets());
|
|
120
111
|
|
|
121
112
|
ParseResult.MagicComment[] magicComments = loadMagicComments();
|
|
122
113
|
Nodes.Location dataLocation = loadOptionalLocation();
|
|
123
114
|
ParseResult.Error[] errors = loadErrors();
|
|
124
115
|
ParseResult.Warning[] warnings = loadWarnings();
|
|
116
|
+
boolean continuable = buffer.get() != 0;
|
|
125
117
|
|
|
126
118
|
int constantPoolBufferOffset = buffer.getInt();
|
|
127
119
|
int constantPoolLength = loadVarUInt();
|
|
128
|
-
this.constantPool = new ConstantPool(this,
|
|
120
|
+
this.constantPool = new ConstantPool(this, constantPoolBufferOffset, constantPoolLength);
|
|
129
121
|
|
|
130
122
|
Nodes.Node node;
|
|
131
123
|
if (errors.length == 0) {
|
|
132
|
-
node =
|
|
124
|
+
node = loadNodes(constantPoolBufferOffset, -1);
|
|
133
125
|
|
|
134
126
|
int left = constantPoolBufferOffset - buffer.position();
|
|
135
127
|
if (left != 0) {
|
|
136
128
|
throw new Error("Expected to consume all bytes while deserializing but there were " + left + " bytes left");
|
|
137
129
|
}
|
|
138
130
|
|
|
139
|
-
|
|
140
|
-
MarkNewlinesVisitor visitor = new MarkNewlinesVisitor(source, newlineMarked);
|
|
131
|
+
MarkNewlinesVisitor visitor = new MarkNewlinesVisitor(source);
|
|
141
132
|
node.accept(visitor);
|
|
142
133
|
} else {
|
|
143
134
|
node = null;
|
|
144
135
|
}
|
|
145
136
|
|
|
146
|
-
return new ParseResult(node, magicComments, dataLocation, errors, warnings, source);
|
|
137
|
+
return new ParseResult(node, magicComments, dataLocation, errors, warnings, continuable, source);
|
|
147
138
|
}
|
|
148
139
|
|
|
149
|
-
private byte[]
|
|
140
|
+
private byte[] loadString() {
|
|
150
141
|
int length = loadVarUInt();
|
|
151
142
|
byte[] bytes = new byte[length];
|
|
152
143
|
buffer.get(bytes);
|
|
153
144
|
return bytes;
|
|
154
145
|
}
|
|
155
146
|
|
|
156
|
-
private byte[] loadString() {
|
|
157
|
-
switch (buffer.get()) {
|
|
158
|
-
case 1:
|
|
159
|
-
int start = loadVarUInt();
|
|
160
|
-
int length = loadVarUInt();
|
|
161
|
-
byte[] bytes = new byte[length];
|
|
162
|
-
System.arraycopy(source.bytes, start, bytes, 0, length);
|
|
163
|
-
return bytes;
|
|
164
|
-
case 2:
|
|
165
|
-
return loadEmbeddedString();
|
|
166
|
-
default:
|
|
167
|
-
throw new Error("Expected 0 or 1 but was " + buffer.get());
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
147
|
private int[] loadLineOffsets() {
|
|
172
148
|
int count = loadVarUInt();
|
|
173
149
|
int[] lineOffsets = new int[count];
|
|
@@ -199,7 +175,7 @@ public class Loader {
|
|
|
199
175
|
// error messages only contain ASCII characters
|
|
200
176
|
for (int i = 0; i < count; i++) {
|
|
201
177
|
Nodes.ErrorType type = Nodes.ERROR_TYPES[loadVarUInt()];
|
|
202
|
-
byte[] bytes =
|
|
178
|
+
byte[] bytes = loadString();
|
|
203
179
|
String message = new String(bytes, StandardCharsets.US_ASCII);
|
|
204
180
|
Nodes.Location location = loadLocation();
|
|
205
181
|
ParseResult.ErrorLevel level = ParseResult.ERROR_LEVELS[buffer.get()];
|
|
@@ -218,7 +194,7 @@ public class Loader {
|
|
|
218
194
|
// warning messages only contain ASCII characters
|
|
219
195
|
for (int i = 0; i < count; i++) {
|
|
220
196
|
Nodes.WarningType type = Nodes.WARNING_TYPES[loadVarUInt() - <%= errors.length %>];
|
|
221
|
-
byte[] bytes =
|
|
197
|
+
byte[] bytes = loadString();
|
|
222
198
|
String message = new String(bytes, StandardCharsets.US_ASCII);
|
|
223
199
|
Nodes.Location location = loadLocation();
|
|
224
200
|
ParseResult.WarningLevel level = ParseResult.WARNING_LEVELS[buffer.get()];
|
|
@@ -230,20 +206,11 @@ public class Loader {
|
|
|
230
206
|
return warnings;
|
|
231
207
|
}
|
|
232
208
|
|
|
233
|
-
private
|
|
234
|
-
if (buffer.get(buffer.position()) != 0) {
|
|
235
|
-
return loadNode();
|
|
236
|
-
} else {
|
|
237
|
-
buffer.position(buffer.position() + 1); // continue after the 0 byte
|
|
238
|
-
return null;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
private <%= string_type %> loadConstant() {
|
|
209
|
+
private <%= id_type %> loadConstant() {
|
|
243
210
|
return constantPool.get(buffer, loadVarUInt());
|
|
244
211
|
}
|
|
245
212
|
|
|
246
|
-
private <%=
|
|
213
|
+
private <%= id_type %> loadOptionalConstant() {
|
|
247
214
|
if (buffer.get(buffer.position()) != 0) {
|
|
248
215
|
return loadConstant();
|
|
249
216
|
} else {
|
|
@@ -252,12 +219,16 @@ public class Loader {
|
|
|
252
219
|
}
|
|
253
220
|
}
|
|
254
221
|
|
|
255
|
-
private <%=
|
|
222
|
+
private <%= id_type %>[] loadConstants() {
|
|
256
223
|
int length = loadVarUInt();
|
|
257
224
|
if (length == 0) {
|
|
258
|
-
return Nodes.
|
|
225
|
+
return Nodes.EMPTY_IDENTIFIER_ARRAY;
|
|
259
226
|
}
|
|
260
|
-
|
|
227
|
+
<%- if id_type == "String" -%>
|
|
228
|
+
<%= id_type %>[] constants = new <%= id_type %>[length];
|
|
229
|
+
<%- else -%>
|
|
230
|
+
<%= id_type %>[] constants = new byte[length][];
|
|
231
|
+
<%- end -%>
|
|
261
232
|
for (int i = 0; i < length; i++) {
|
|
262
233
|
constants[i] = constantPool.get(buffer, loadVarUInt());
|
|
263
234
|
}
|
|
@@ -356,67 +327,195 @@ public class Loader {
|
|
|
356
327
|
return negative ? result.negate() : result;
|
|
357
328
|
}
|
|
358
329
|
|
|
359
|
-
private
|
|
360
|
-
|
|
330
|
+
private static final int LAZY_MARKER = <%= Prism::Template::LAZY_MARKER %>;
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* The stack of nodes that have been loaded but not yet attached to their
|
|
334
|
+
* parent, along with the lazy subtrees that are pending.
|
|
335
|
+
*/
|
|
336
|
+
private static final class NodeStack {
|
|
337
|
+
|
|
338
|
+
private Nodes.Node[] nodes = new Nodes.Node[64];
|
|
339
|
+
private int size = 0;
|
|
340
|
+
|
|
341
|
+
/** For each pending lazy subtree, its marker position, start, and end. */
|
|
342
|
+
private int[] lazy = new int[3 * 8];
|
|
343
|
+
private int lazySize = 0;
|
|
344
|
+
|
|
345
|
+
void push(Nodes.Node node) {
|
|
346
|
+
if (size == nodes.length) {
|
|
347
|
+
nodes = java.util.Arrays.copyOf(nodes, size * 2);
|
|
348
|
+
}
|
|
349
|
+
nodes[size++] = node;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
Nodes.Node pop() {
|
|
353
|
+
Nodes.Node node = nodes[--size];
|
|
354
|
+
nodes[size] = null;
|
|
355
|
+
return node;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
void pushLazy(int marker, int start, int end) {
|
|
359
|
+
if (lazySize * 3 == lazy.length) {
|
|
360
|
+
lazy = java.util.Arrays.copyOf(lazy, lazy.length * 2);
|
|
361
|
+
}
|
|
362
|
+
lazy[lazySize * 3] = marker;
|
|
363
|
+
lazy[lazySize * 3 + 1] = start;
|
|
364
|
+
lazy[lazySize * 3 + 2] = end;
|
|
365
|
+
lazySize++;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Returns the marker position of the most recently pushed lazy
|
|
370
|
+
* subtree, or -1 if there is none. That subtree always belongs to the
|
|
371
|
+
* node whose record is being loaded, because the lazy subtrees of its
|
|
372
|
+
* descendants are popped when their own records are loaded.
|
|
373
|
+
*/
|
|
374
|
+
int popLazy() {
|
|
375
|
+
return lazySize == 0 ? -1 : lazy[--lazySize * 3];
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Loads the nodes serialized from the current position, stopping at the
|
|
381
|
+
* given offset once a single root remains, and returns that root. Nodes
|
|
382
|
+
* are serialized in post-order, so the children of each node are the
|
|
383
|
+
* topmost values on the stack, in field order, by the time its record is
|
|
384
|
+
* loaded. The lazy marker at eagerMarker, if any, is loaded eagerly even
|
|
385
|
+
* when DefNodes are loaded lazily.
|
|
386
|
+
*/
|
|
387
|
+
private Nodes.Node loadNodes(int end, int eagerMarker) {
|
|
388
|
+
boolean lazy = loadDefNodesLazily();
|
|
389
|
+
NodeStack stack = new NodeStack();
|
|
390
|
+
|
|
391
|
+
while (buffer.position() < end || stack.size != 1) {
|
|
392
|
+
if (stack.lazySize > 0 && buffer.position() == stack.lazy[stack.lazySize * 3 - 2]) {
|
|
393
|
+
buffer.position(stack.lazy[stack.lazySize * 3 - 1]);
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
int type = buffer.get() & 0xFF;
|
|
398
|
+
switch (type) {
|
|
399
|
+
case 0:
|
|
400
|
+
stack.push(null);
|
|
401
|
+
break;
|
|
402
|
+
case LAZY_MARKER: {
|
|
403
|
+
int marker = buffer.position() - 1;
|
|
404
|
+
int skip = buffer.getInt();
|
|
405
|
+
int length = buffer.getInt();
|
|
406
|
+
if (lazy && marker != eagerMarker) {
|
|
407
|
+
int start = buffer.position() + skip;
|
|
408
|
+
stack.pushLazy(marker, start, start + length);
|
|
409
|
+
}
|
|
410
|
+
break;
|
|
411
|
+
}
|
|
412
|
+
<%- nodes.each.with_index(1) do |node, index| -%>
|
|
413
|
+
case <%= index %>:
|
|
414
|
+
stack.push(load<%= node.name %>(stack));
|
|
415
|
+
break;
|
|
416
|
+
<%- end -%>
|
|
417
|
+
default:
|
|
418
|
+
throw new Error("Unknown node type: " + type);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
return stack.pop();
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
Nodes.DefNode loadNonLazyDefNode(int lazyPosition) {
|
|
426
|
+
Nodes.DefNode node;
|
|
427
|
+
// This method mutates the buffer position and may be called from different threads so we must synchronize
|
|
428
|
+
synchronized (this) {
|
|
429
|
+
buffer.position(lazyPosition + 1);
|
|
430
|
+
int skip = buffer.getInt();
|
|
431
|
+
int length = buffer.getInt();
|
|
432
|
+
int end = buffer.position() + skip + length;
|
|
433
|
+
|
|
434
|
+
buffer.position(lazyPosition);
|
|
435
|
+
node = (Nodes.DefNode) loadNodes(end, lazyPosition);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
MarkNewlinesVisitor visitor = new MarkNewlinesVisitor(source);
|
|
439
|
+
node.accept(visitor);
|
|
440
|
+
|
|
441
|
+
return node;
|
|
442
|
+
}
|
|
443
|
+
<%- array_types = [] -%>
|
|
444
|
+
<%- nodes.each do |node| -%>
|
|
445
|
+
|
|
446
|
+
private Nodes.<%= node.name %> load<%= node.name %>(NodeStack stack) {
|
|
361
447
|
<%- if Prism::Template::INCLUDE_NODE_ID -%>
|
|
362
448
|
int nodeId = loadVarUInt();
|
|
363
449
|
<%- end -%>
|
|
364
450
|
int startOffset = loadVarUInt();
|
|
365
451
|
int length = loadVarUInt();
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
452
|
+
<%- if node.flags -%>
|
|
453
|
+
short flags = loadFlags();
|
|
454
|
+
<%- end -%>
|
|
455
|
+
<%- node.semantic_fields.each do |field| -%>
|
|
456
|
+
<%- case field -%>
|
|
457
|
+
<%- when Prism::Template::NodeField, Prism::Template::OptionalNodeField -%>
|
|
458
|
+
<%- when Prism::Template::NodeListField -%>
|
|
459
|
+
int <%= field.name %>Size = loadVarUInt();
|
|
460
|
+
<%- else -%>
|
|
461
|
+
var field_<%= field.name %> = <%=
|
|
462
|
+
case field
|
|
463
|
+
when Prism::Template::StringField then "loadString()"
|
|
464
|
+
when Prism::Template::ConstantField then "loadConstant()"
|
|
465
|
+
when Prism::Template::OptionalConstantField then "loadOptionalConstant()"
|
|
466
|
+
when Prism::Template::ConstantListField then "loadConstants()"
|
|
467
|
+
when Prism::Template::LocationField then "loadLocation()"
|
|
468
|
+
when Prism::Template::OptionalLocationField then "loadOptionalLocation()"
|
|
469
|
+
when Prism::Template::UInt8Field then "buffer.get()"
|
|
470
|
+
when Prism::Template::UInt32Field then "loadVarUInt()"
|
|
471
|
+
when Prism::Template::IntegerField then "loadInteger()"
|
|
472
|
+
when Prism::Template::DoubleField then "buffer.getDouble()"
|
|
473
|
+
else raise
|
|
474
|
+
end
|
|
475
|
+
%>;
|
|
476
|
+
<%- end -%>
|
|
477
|
+
<%- end -%>
|
|
478
|
+
<%- if node.lazy_field -%>
|
|
479
|
+
int lazyPosition = stack.popLazy();
|
|
480
|
+
<%- end -%>
|
|
481
|
+
<%- node.child_fields.reverse_each do |field| -%>
|
|
482
|
+
<%- case field -%>
|
|
483
|
+
<%- when Prism::Template::NodeListField -%>
|
|
484
|
+
<%- element_type = field.java_type.sub("[]", ""); array_types << element_type -%>
|
|
485
|
+
var field_<%= field.name %> = pop<%= element_type %>s(stack, <%= field.name %>Size);
|
|
486
|
+
<%- else -%>
|
|
487
|
+
<%- if field == node.lazy_field -%>
|
|
488
|
+
var field_<%= field.name %> = lazyPosition == -1 ? <%= field.java_cast %>stack.pop() : null;
|
|
489
|
+
<%- else -%>
|
|
490
|
+
var field_<%= field.name %> = <%= field.java_cast %>stack.pop();
|
|
491
|
+
<%- end -%>
|
|
492
|
+
<%- end -%>
|
|
493
|
+
<%- end -%>
|
|
494
|
+
<%-
|
|
495
|
+
params = []
|
|
496
|
+
params << "nodeId" if Prism::Template::INCLUDE_NODE_ID
|
|
497
|
+
params << "startOffset" << "length"
|
|
498
|
+
params << "lazyPosition" << "lazyPosition == -1 ? null : this" if node.lazy_field
|
|
499
|
+
params << "flags" if node.flags
|
|
500
|
+
params.concat(node.semantic_fields.map { |field| "field_#{field.name}" })
|
|
501
|
+
-%>
|
|
502
|
+
return new Nodes.<%= node.name %>(<%= params.join(", ") %>);
|
|
404
503
|
}
|
|
504
|
+
<%- end -%>
|
|
405
505
|
<%- array_types.uniq.each do |type| -%>
|
|
406
506
|
|
|
407
507
|
private static final Nodes.<%= type %>[] EMPTY_<%= type %>_ARRAY = {};
|
|
408
508
|
|
|
409
|
-
private Nodes.<%= type %>[]
|
|
410
|
-
int length = loadVarUInt();
|
|
509
|
+
private static Nodes.<%= type %>[] pop<%= type %>s(NodeStack stack, int length) {
|
|
411
510
|
if (length == 0) {
|
|
412
511
|
return EMPTY_<%= type %>_ARRAY;
|
|
413
512
|
}
|
|
414
513
|
Nodes.<%= type %>[] nodes = new Nodes.<%= type %>[length];
|
|
415
|
-
for (int i =
|
|
416
|
-
<%- if type ==
|
|
417
|
-
nodes[i] =
|
|
514
|
+
for (int i = length - 1; i >= 0; i--) {
|
|
515
|
+
<%- if type == "Node" -%>
|
|
516
|
+
nodes[i] = stack.pop();
|
|
418
517
|
<%- else -%>
|
|
419
|
-
nodes[i] = (Nodes.<%= type %>)
|
|
518
|
+
nodes[i] = (Nodes.<%= type %>) stack.pop();
|
|
420
519
|
<%- end -%>
|
|
421
520
|
}
|
|
422
521
|
return nodes;
|