Version 2.0.0-dev.61.0
Merge commit '5aa65c003721ff190dd34ae16a6959c38243fb1a' into dev
diff --git a/BUILD.gn b/BUILD.gn
index d0cd1b5..b3f49d3 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -51,7 +51,8 @@
group("runtime_kernel") {
import("runtime/runtime_args.gni")
- target_supports_aot = dart_target_arch == "arm" || dart_target_arch == "arm64" || dart_target_arch == "x64"
+ target_supports_aot = dart_target_arch == "arm" ||
+ dart_target_arch == "arm64" || dart_target_arch == "x64"
if (targetting_fuchsia) {
# Fuchsia has run_vm_tests marked testonly.
@@ -67,7 +68,7 @@
]
if (target_supports_aot) {
- deps += ["runtime/bin:precompiler_entry_points_json"]
+ deps += [ "runtime/bin:precompiler_entry_points_json" ]
}
}
@@ -139,9 +140,19 @@
]
}
+# This rule and the compressed_observatory_archive rule are for the Fuchsia
+# bots that pre-build the Observatory. They copy the observatory tar files to
+# the root build output directory for convenient access by the Fuchsia buildbot
+# scripts.
group("observatory_archive") {
deps = [
- "runtime/observatory:observatory_archive"
+ "runtime/observatory:copy_observatory_archive",
+ ]
+}
+
+group("compressed_observatory_archive") {
+ deps = [
+ "runtime/observatory:copy_compressed_observatory_archive",
]
}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 08bfa29..79549fe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,26 @@
+## 2.0.0-dev.61.0
+
+### Dart VM
+
+* `async` functions now start synchronously by default.
+ Passing the `--no-sync-async` flag will produce the old behavior,
+ starting `async` functions asynchronously.
+
+### Tool Changes
+
+#### Pub
+
+* Fix support for running executables in Dart 2 mode.
+
+### Core library changes
+
+* `dart:io`
+ * Dart-styled constants have been added for `HttpStatus`, `HttpHeaders`,
+ `ContentType`, `HttpClient`, `WebSocketStatus`, `CompressionOptions`,
+ and `WebSocket`. The `SCREAMING_CAPS` constants are marked deprecated.
+ Note that `HttpStatus.CONTINUE` is now `HttpStatus.continue_`, and that
+ e.g. `HttpHeaders.FIELD_NAME` is now `HttpHeaders.fieldNameHeader`.
+
## 2.0.0-dev.60.0
### Core library changes
@@ -98,6 +121,14 @@
* Added `FileSystemEntity.fromRawPath` constructor to allow for
the creation of `FileSystemEntity` using `Uint8List` buffers.
+### Dart VM
+
+* `async` functions now start synchronously when previewing Dart 2 with
+ `--preview-dart-2`. Build tools (e.g., build_runner) may override the
+ default and/or allow developers to configure. Passing the
+ `--no-sync-async` flag will produce the old behavior, starting `async`
+ functions asynchronously.
+
### Tool Changes
#### dartfmt
diff --git a/DEPS b/DEPS
index 76e7739..544ccdc 100644
--- a/DEPS
+++ b/DEPS
@@ -94,7 +94,7 @@
"intl_tag": "0.15.2",
"jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
"json_rpc_2_tag": "2.0.6",
- "linter_tag": "0.1.51",
+ "linter_tag": "0.1.52",
"logging_tag": "0.11.3+1",
"markdown_tag": "2.0.0",
"matcher_tag": "0.12.1+4",
@@ -110,7 +110,7 @@
"ply_rev": "604b32590ffad5cbb82e4afef1d305512d06ae93",
"pool_tag": "1.3.4",
"protobuf_tag": "0.7.1",
- "pub_rev": "7bdcf4e4de85a7a8c7a322511b8198f1b6cb0a73",
+ "pub_rev": "d84173eeb03c328ed533469108ce81b11d736a80",
"pub_semver_tag": "1.4.1",
"quiver_tag": "5aaa3f58c48608af5b027444d561270b53f15dbf",
"resource_rev":"af5a5bf65511943398146cf146e466e5f0b95cb9",
diff --git a/build/dart/dart_action.gni b/build/dart/dart_action.gni
index 6bd19d7..77a0130 100644
--- a/build/dart/dart_action.gni
+++ b/build/dart/dart_action.gni
@@ -52,6 +52,10 @@
visibility = invoker.visibility
}
+ if (defined(invoker.testonly)) {
+ testonly = invoker.testonly
+ }
+
script = "$_dart_root/build/gn_run_binary.py"
if (defined(invoker.inputs)) {
@@ -111,10 +115,11 @@
not_needed(invoker, ["target"])
action(target_name) {
forward_variables_from(invoker, [
- "outputs",
- "deps",
- "visibility",
"depfile",
+ "deps",
+ "outputs",
+ "testonly",
+ "visibility",
])
script = "$_dart_root/build/gn_run_binary.py"
@@ -148,11 +153,12 @@
not_needed(invoker, ["binary"])
_compiled_action(target_name) {
forward_variables_from(invoker, [
+ "depfile",
+ "deps",
"inputs",
"outputs",
- "deps",
+ "testonly",
"visibility",
- "depfile",
])
if (defined(invoker.script)) {
@@ -200,6 +206,7 @@
# deps
# inputs
# outputs
+# testonly
# visibility
template("prebuilt_dart_action") {
assert(defined(invoker.script), "script must be defined for $target_name")
@@ -253,6 +260,7 @@
# deps
# inputs
# outputs
+# testonly
# visibility
template("_built_tool_action") {
assert(defined(invoker.tool), "tool must be defined for $target_name")
@@ -273,6 +281,7 @@
"inputs",
"outputs",
"tool",
+ "testonly",
"visibility",
])
@@ -317,6 +326,7 @@
# deps
# inputs
# outputs
+# testonly
# visibility
template("dart_action") {
assert(defined(invoker.script), "script must be defined for $target_name")
@@ -331,6 +341,7 @@
"outputs",
"packages",
"script",
+ "testonly",
"tool",
"visibility",
"vm_args",
@@ -363,6 +374,7 @@
# deps
# inputs
# outputs
+# testonly
# visibility
template("dart_bootstrap_action") {
assert(defined(invoker.script), "script must be defined for $target_name")
@@ -377,6 +389,7 @@
"outputs",
"packages",
"script",
+ "testonly",
"tool",
"visibility",
"vm_args",
@@ -408,6 +421,7 @@
# deps
# inputs
# outputs
+# testonly
# visibility
template("gen_snapshot_action") {
assert(!defined(invoker.script),
@@ -422,6 +436,7 @@
"inputs",
"outputs",
"packages",
+ "testonly",
"tool",
"visibility",
"vm_args",
diff --git a/dartdoc_options.yaml b/dartdoc_options.yaml
index 4e73e84..6c233f4 100644
--- a/dartdoc_options.yaml
+++ b/dartdoc_options.yaml
@@ -1,2 +1,2 @@
dartdoc:
- categoryOrder: ["VM", "Web"]
+ categoryOrder: ["Core", VM", "Web"]
diff --git a/docs/language/dart.sty b/docs/language/dart.sty
index 468a8e8..6c8a3e5 100644
--- a/docs/language/dart.sty
+++ b/docs/language/dart.sty
@@ -95,6 +95,9 @@
%\end{verbatim}
}
+% A commonly used name for an identifier
+\newcommand{\id}{\metavar{id}}
+
% ----------------------------------------------------------------------
% Support for hash valued Location Markers
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex
index 2db8dfe..17d6731 100644
--- a/docs/language/dartLangSpec.tex
+++ b/docs/language/dartLangSpec.tex
@@ -47,11 +47,14 @@
% local function evaluates to the closurization of that declaration.
% - Make `mixin` and `interface` built-in identifiers.
% - Make `async` *not* a reserved word inside async functions.
-% - Added 'Class Member Conflicts', simplifying and adjusting rules about
+% - Add 'Class Member Conflicts', simplifying and adjusting rules about
% member declaration conflicts beyond "`n` declared twice in one scope".
% - Specify that integer literals are limited to signed 64-bit values,
% and that the `int` class is intended as signed 64-bit integer, but
% that platforms may differ.
+% - Specify variance and super-bounded types.
+% - Introduce `subterm` and `immediate subterm`.
+% - Introduce `top type`.
%
% 1.15
% - Change how language specification describes control flow.
@@ -230,12 +233,38 @@
Productions are embedded, as much as possible, in the discussion of the constructs they represent.
\LMHash{}
+A {\em term} is a syntactic construct.
+It may be considered to be a piece of text which is derivable in the grammar,
+and it may be considered to be a tree created by such a derivation.
+An {\em immediate subterm} of a given term $t$ is a syntactic construct
+which corresponds to an immediate subtree of $t$ considered as a derivation tree.
+A {\em subterm} of a given term $t$ is $t$,
+or an immediate subterm of $t$,
+or a subterm of an immediate subterm of $t$.
+
+\LMHash{}
A list $x_1, \ldots, x_n$ denotes any list of $n$ elements of the form $x_i, 1 \le i \le n$.
Note that $n$ may be zero, in which case the list is empty.
We use such lists extensively throughout this specification.
\LMHash{}
-The notation $[x_1/y_1, \ldots, x_n/y_n]E$ denotes a copy of $E$ in which all occurrences of $y_i, 1 \le i \le n$ have been replaced with $x_i$.
+For $j \in 1 .. n$,
+let $y_j$ be an atomic syntactic entity (like an identifier),
+$x_j$ a composite syntactic entity (like an expression or a type),
+and $E$ again a composite syntactic entity.
+The notation $[x_1/y_1, \ldots, x_n/y_n]E$ then denotes a copy of $E$
+in which each occurrence of $y_i, 1 \le i \le n$ has been replaced by $x_i$.
+
+\LMHash{}
+This operation is also known as substitution, and it is the variant that avoids capture.
+That is, when $E$ contains a construct that introduces $y_i$ into a nested scope for some $i \in 1 .. n$,
+the substitution will not replace $y_i$ in that scope.
+Conversely, if such a replacement would put an identifier \id{} (a subterm of $x_i$) into a scope where \id{} is declared,
+the relevant declarations in $E$ are systematically renamed to fresh names.
+
+\commentary{
+In short, capture freedom ensures that the ``meaning'' of each identifier is preserved during substitution.
+}
\LMHash{}
We sometimes abuse list or map literal syntax, writing $[o_1, \ldots, o_n]$ (respectively $\{k_1: o_1, \ldots, k_n: o_n\}$) where the $o_i$ and $k_i$ may be objects rather than expressions.
@@ -1611,7 +1640,7 @@
Constructors may be generative (\ref{generativeConstructors}) or they may be factories (\ref{factories}).
\LMHash{}
-A {\em constructor name} always begins with the name of its immediately enclosing class, and may optionally be followed by a dot and an identifier $id$.
+A {\em constructor name} always begins with the name of its immediately enclosing class, and may optionally be followed by a dot and an identifier \id.
It is a compile-time error if the name of a constructor is not a constructor name.
\commentary{
@@ -1641,14 +1670,14 @@
\LMHash{}
A {\em constructor parameter list} is a parenthesized, comma-separated list of formal constructor parameters.
A {\em formal constructor parameter} is either a formal parameter (\ref{formalParameters}) or an initializing formal.
-An {\em initializing formal} has the form \code{\THIS{}.$id$}, where $id$ is the name of an instance variable of the immediately enclosing class.
-It is a compile-time error if $id$ is not an instance variable of the immediately enclosing class.
+An {\em initializing formal} has the form \code{\THIS{}.\id}, where \id{} is the name of an instance variable of the immediately enclosing class.
+It is a compile-time error if \id{} is not an instance variable of the immediately enclosing class.
It is a compile-time error if an initializing formal is used by a function other than a non-redirecting generative constructor.
\LMHash{}
If an explicit type is attached to the initializing formal, that is its static type.
-Otherwise, the type of an initializing formal named $id$ is $T_{id}$, where $T_{id}$ is the type of the instance variable named $id$ in the immediately enclosing class.
-It is a static warning if the static type of $id$ is not a subtype of $T_{id}$.
+Otherwise, the type of an initializing formal named \id{} is $T_{id}$, where $T_{id}$ is the type of the instance variable named \id{} in the immediately enclosing class.
+It is a static warning if the static type of \id{} is not a subtype of $T_{id}$.
\LMHash{}
Initializing formals constitute an exception to the rule that every formal parameter introduces a local variable into the formal parameter scope (\ref{formalParameters}).
@@ -1663,8 +1692,8 @@
\LMHash{}
Initializing formals are executed during the execution of generative constructors detailed below.
-Executing an initializing formal \code{\THIS{}.$id$} causes the instance variable $id$ of the immediately surrounding class to be assigned the value of the corresponding actual parameter,
-unless $id$ is a final variable that has already been initialized, in which case a run-time error occurs.
+Executing an initializing formal \code{\THIS{}.\id} causes the instance variable \id{} of the immediately surrounding class to be assigned the value of the corresponding actual parameter,
+unless \id{} is a final variable that has already been initialized, in which case a run-time error occurs.
\commentary{
The above rule allows initializing formals to be used as optional parameters:
@@ -1861,7 +1890,7 @@
\code{\SUPER{}($a_1, \ldots,\ a_n,\ x_{n+1}: a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
(respectively
-\code{\SUPER{}.id($a_1, \ldots,\ a_n,\ x_{n+1}: a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)})
+\code{\SUPER{}.\id($a_1, \ldots,\ a_n,\ x_{n+1}: a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)})
proceeds as follows:
@@ -1879,13 +1908,13 @@
If $S$ is generic (\ref{generics}), let $U_1, \ldots, U_m$ be the actual type arguments passed to $S$ in the superclass clause of $C$.
\LMHash{}
-The generative constructor $S$ (respectively $S.id$) of $S$ is executed
+The generative constructor $S$ (respectively \code{$S$.\id}) of $S$ is executed
to initialize $i$ with respect to the bindings that resulted from the evaluation of
\code{($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)},
and the type parameters (if any) of class $S$ bound to $U_1, \ldots, U_m$.
\LMHash{}
-It is a compile-time error if class $S$ does not declare a generative constructor named $S$ (respectively $S.id$).
+It is a compile-time error if class $S$ does not declare a generative constructor named $S$ (respectively \code{$S$.\id}).
\subsubsection{Factories}
@@ -1902,7 +1931,7 @@
%The enclosing scope of a factory constructor is the static scope \ref{} of the class in which it is declared.
\LMHash{}
-The {\em return type} of a factory whose signature is of the form \FACTORY{} $M$ or the form \FACTORY{} $M.id$ is $M$ if $M$ is not a generic type;
+The {\em return type} of a factory whose signature is of the form \FACTORY{} $M$ or the form \FACTORY{} \code{$M$.\id} is $M$ if $M$ is not a generic type;
otherwise the return type is \code{$M$<$T_1, \ldots,\ T_n$>} where $T_1, \ldots, T_n$ are the type parameters of the enclosing class.
\LMHash{}
@@ -1940,7 +1969,7 @@
The resulting constructor call is governed by the same rules as an instance creation expression using \NEW{} (\ref{instanceCreation}).
\commentary{
-It follows that if $type$ or $type.id$ are not defined, or do not refer to a class or constructor, a dynamic error occurs, as with any other undefined constructor call.
+It follows that if \metavar{type} or \code{\metavar{type}.\id} are not defined, or do not refer to a class or constructor, a dynamic error occurs, as with any other undefined constructor call.
The same holds if $k$ is called with fewer required parameters or more positional parameters than $k'$ expects, or if $k$ is called with a named parameter that is not declared by $k'$.
}
@@ -1962,7 +1991,7 @@
}
\LMHash{}
-It is a static warning if $type$ does not denote a class accessible in the current scope; if $type$ does denote such a class $C$ it is a static warning if the referenced constructor (be it $type$ or $type.id$) is not a constructor of $C$.
+It is a static warning if $type$ does not denote a class accessible in the current scope; if $type$ does denote such a class $C$ it is a static warning if the referenced constructor (be it \metavar{type} or \code{\metavar{type}.\id}) is not a constructor of $C$.
\commentary{
Note that it is not possible to modify the arguments being passed to $k'$.
@@ -2803,16 +2832,16 @@
A {\em generic class} is a mapping that accepts a list of actual type arguments and maps them to a class.
Consider a generic class declaration $G$ named \code{C} with formal type parameter declarations
$X_1\ \EXTENDS\ B_1, \ldots,\ X_m\ \EXTENDS\ B_m$,
-and a parameterized type \code{C<$T_1, \ldots,\ T_l$>}.
+and a parameterized type $T$ of the form \code{C<$T_1, \ldots,\ T_l$>}.
\LMHash{}
It is a static warning if $m \not= l$.
-It is a static warning if there exists a $j$
-such that $T_j$ is not a subtype of $[T_1/X_1, \ldots, T_m/X_m]B_j$.
+It is a static warning if $T$ is not well-bounded
+(\ref{superBoundedTypes}).
\commentary{
That is, if the number of type arguments is wrong,
-or if the $j$th actual type argument is not a subtype of the corresponding bound, where each formal type parameter has been replaced by the corresponding actual type argument.
+or one or more of the upper bounds has been violated.
}
\LMHash{}
@@ -2829,16 +2858,16 @@
Consider a generic type alias declaration $G$ named \code{F} with formal type parameter declarations
$X_1\ \EXTENDS\ B_1, \ldots,\ X_m\ \EXTENDS\ B_m$,
and right hand side $T$,
-and the parameterized type \code{F<$T_1, \ldots,\ T_l$>}.
+and the parameterized type $S$ of the form \code{F<$T_1, \ldots,\ T_l$>}.
\LMHash{}
It is a static warning if $m \not= l$.
-It is a static warning if there exists a $j$
-such that $T_j$ is not a subtype of $[T_1/X_1, \ldots, T_m/X_m]B_j$.
+It is a static warning if $S$ is not well-bounded
+(\ref{superBoundedTypes}).
\commentary{
That is, if the number of type arguments is wrong,
-or if the $j$th actual type argument violates the bound.
+or one or more of the upper bounds has been violated.
}
\LMHash{}
@@ -2856,6 +2885,11 @@
}
\LMHash{}
+A {\em generic type} is a type which is introduced by
+a generic class declaration or a generic type alias,
+or it is the type \code{FutureOr}.
+
+\LMHash{}
A {\em generic function declaration} introduces a generic function (\ref{formalParameters}) into the enclosing scope.
Consider a function invocation expression of the form
\code{f<$T_1, \ldots,\ T_l$>(\ldots)},
@@ -2869,7 +2903,8 @@
\commentary{
That is, if the number of type arguments is wrong,
-or if the $j$th actual type argument is not a subtype of the corresponding bound, where each formal type parameter has been replaced by the corresponding actual type argument.
+or if the $j$th actual type argument is not a subtype of the corresponding bound,
+where each formal type parameter has been replaced by the corresponding actual type argument.
}
\begin{grammar}
@@ -2972,6 +3007,358 @@
%By current rules, this is illegal. Make sure we preserve this.
+\subsection{Variance}
+\LMLabel{variance}
+
+\LMHash{}
+We say that a type $S$ {\em occurs covariantly} in a type $T$ if{}f
+$S$ occurs in a covariant position in $T$,
+but not in a contravariant position,
+and not in an invariant position.
+
+\LMHash{}
+We say that a type $S$ {\em occurs contravariantly} in a type $T$ if{}f
+$S$ occurs in a contravariant position in $T$,
+but not in a covariant position,
+and not in an invariant position.
+
+\LMHash{}
+We say that a type $S$ {\em occurs invariantly} in a type $T$ if{}f
+$S$ occurs in an invariant position in $T$,
+or $S$ occurs in a covariant position as well as a contravariant position.
+
+\LMHash{}
+We say that a type $S$ occurs {\em in a covariant position} in a type $T$
+if{}f one of the following conditions is true:
+
+\begin{itemize}
+\item $T$ is $S$
+
+\item $T$ is of the form \code{$G$<$S_1,\ \ldots,\ S_n$>}
+ where $G$ denotes a generic class
+ and $S$ occurs in a covariant position in $S_j$ for some $j \in 1 .. n$.
+
+\item $T$ is of the form
+ \code{$S_0$ \FUNCTION<$X_1\ \EXTENDS\ B_1, \ldots$>($S_1\ x_1, \ldots$)}
+ where the type parameter list may be omitted,
+ and $S$ occurs in a covariant position in $S_0$.
+
+\item $T$ is of the form
+
+ \code{$S_0$ \FUNCTION<$X_1\ \EXTENDS\ B_1, \ldots$>}
+
+ \code{\quad($S_1\ x_1, \ldots,\ S_k\ x_k,
+ $ [$S_{k+1}\ x_{k+1} = d_{k+1}, \ldots,\ S_n\ x_n = d_n$])}
+
+ \noindent
+ or of the form
+
+ \code{$S_0$ \FUNCTION<$X_1\ \EXTENDS\ B_1, \ldots$>}
+
+ \code{\quad($S_1\ x_1, \ldots,\ S_k\ x_k,
+ $ \{$S_{k+1}\ x_{k+1} = d_{k+1}, \ldots,\ S_n\ x_n = d_n$\})}
+
+ \noindent
+ where the type parameter list and each default value may be omitted,
+ and $S$ occurs in a contravariant position in $S_j$
+ for some $j \in 1 .. n$.
+
+\item $T$ is of the form \code{$G$<$S_1, \ldots,\ S_n$>}
+ where $G$ denotes a parameterized type alias such that
+ $j \in 1 .. n$,
+ the formal type parameter corresponding to $S_j$ is covariant,
+ and $S$ occurs in a covariant position in $S_j$.
+
+\item $T$ is of the form \code{$G$<$S_1, \ldots,\ S_n$>}
+ where $G$ denotes a parameterized type alias such that
+ $j \in 1 .. n$,
+ the formal type parameter corresponding to $S_j$ is contravariant,
+ and $S$ occurs in a contravariant position in $S_j$.
+\end{itemize}
+
+\LMHash{}
+We say that a type $S$ occurs {\em in a contravariant position} in a type $T$
+if{}f one of the following conditions is true:
+
+\begin{itemize}
+\item $T$ is of the form \code{$G$<$S_1,\ \ldots,\ S_n$>}
+ where $G$ denotes a generic class
+ and $S$ occurs in a contravariant position in $S_j$
+ for some $j \in 1 .. n$.
+
+\item $T$ is of the form
+ \code{$S_0$ \FUNCTION<$X_1\ \EXTENDS\ B_1, \ldots$>($S_1\ x_1, \ldots$)}
+ where the type parameter list may be omitted,
+ and $S$ occurs in a contravariant position in $S_0$.
+
+\item $T$ is of the form
+
+ \code{$S_0$ \FUNCTION<$X_1\ \EXTENDS\ B_1, \ldots$>}
+
+ \code{\quad($S_1\ x_1, \ldots,\ S_k\ x_k,
+ $ [$S_{k+1}\ x_{k+1} = d_{k+1}, \ldots,\ S_n\ x_n = d_n$])}
+
+ \noindent
+ or of the form
+
+ \code{$S_0$ \FUNCTION<$X_1\ \EXTENDS\ B_1, \ldots$>}
+
+ \code{\quad($S_1\ x_1, \ldots,\ S_k\ x_k,
+ $ \{$S_{k+1}\ x_{k+1} = d_{k+1}, \ldots,\ S_n\ x_n = d_n$\})}
+
+ \noindent
+ where the type parameter list and each default value may be omitted,
+ and $S$ occurs in a covariant position in $S_j$
+ for some $j \in 1 .. n$.
+
+\item $T$ is of the form \code{$G$<$S_1, \ldots,\ S_n$>}
+ where $G$ denotes a parameterized type alias such that
+ $j \in 1 .. n$,
+ the formal type parameter corresponding to $S_j$ is covariant,
+ and $S$ occurs in a contravariant position in $S_j$.
+
+\item $T$ is of the form \code{$G$<$S_1, \ldots,\ S_n$>}
+ where $G$ denotes a parameterized type alias such that
+ $j \in 1 .. n$,
+ the formal type parameter corresponding to $S_j$ is contravariant,
+ and $S$ occurs in a covariant position in $S_j$.
+\end{itemize}
+
+\LMHash{}
+We say that a type $S$ occurs {\em in an invariant position} in a type $T$
+if{}f one of the following conditions is true:
+
+\begin{itemize}
+\item $T$ is of the form \code{$G$<$S_1,\ \ldots,\ S_n$>}
+ where $G$ denotes a generic class or a parameterized type alias,
+ and $S$ occurs in an invariant position in $S_j$ for some $j \in 1 .. n$.
+
+\item $T$ is of the form
+
+ \code{$S_0$ \FUNCTION<$X_1\ \EXTENDS\ B_1, \ldots,\ X_m\ \EXTENDS\ B_m$>}
+
+ \code{\quad($S_1\ x_1, \ldots,\ S_k\ x_k,
+ $ [$S_{k+1}\ x_{k+1} = d_{k+1}, \ldots,\ S_n\ x_n = d_n$])}
+
+ \noindent
+ or of the form
+
+ \code{$S_0$ \FUNCTION<$X_1\ \EXTENDS\ B_1, \ldots,\ X_m\ \EXTENDS\ B_m$>}
+
+ \code{\quad($S_1\ x_1, \ldots,\ S_k\ x_k,
+ $ \{$S_{k+1}\ x_{k+1} = d_{k+1}, \ldots,\ S_n\ x_n = d_n$\})}
+
+ \noindent
+ where the type parameter list and each default value may be omitted,
+ and $S$ occurs in an invariant position in $S_j$
+ for some $j \in 0 .. n$,
+ or $S$ occurs in $B_i$
+ for some $i \in 1 .. m$.
+
+\item $T$ is of the form \code{$G$<$S_1, \ldots,\ S_n$>}
+ where $G$ denotes a parameterized type alias,
+ $j \in 1 .. n$,
+ the formal type parameter corresponding to $S_j$ is invariant,
+ and $S$ occurs in $S_j$.
+\end{itemize}
+
+\LMHash{}
+Consider a generic type alias declaration $G$
+with formal type parameter declarations
+$X_1\ \EXTENDS\ B_1, \ldots,\ X_m\ \EXTENDS\ B_m$,
+and right hand side $T$.
+Let $j \in 1 .. m$.
+%
+We say that {\em the formal type parameter} $X_j$ {\em is invariant}
+if{}f $X_j$ occurs invariantly in $T$,
+$X_j$ {\em is covariant} if{}f $X_j$ occurs covariantly in $T$,
+and $X_j$ {\em is contravariant} if{}f $X_j$ occurs contravariantly in $T$.
+
+\rationale{
+Variance gives a characterization of the way a type varies
+as the value of a subterm varies, e.g., a type variable:
+Assume that $T$ is a type where a type variable $X$ occurs,
+and $L$ and $U$ are types such that $L$ is a subtype of $U$.
+If $X$ occurs covariantly in $T$
+then $[L/X]T$ is a subtype of $[U/X]T$.
+Similarly, if $X$ occurs contravariantly in $T$
+then $[U/X]T$ is a subtype of $[L/X]T$.
+If $X$ occurs invariantly
+then $[L/X]T$ and $[U/X]T$ are not guaranteed to be subtypes of each other in any direction.
+In short: with covariance, the type covaries;
+with contravariance, the type contravaries;
+with invariance, all bets are off.
+}
+
+
+\subsection{Super-Bounded Types}
+\LMLabel{superBoundedTypes}
+
+\LMHash{}
+This section describes how
+the declared upper bounds of formal type parameters are enforced,
+including some cases where a limited form of violation is allowed.
+
+\LMHash{}
+A {\em top type} is a type $T$ such that \code{Object} is a subtype of $T$.
+\commentary{
+For instance, \code{Object}, \DYNAMIC, and \VOID{} are top types,
+and so are \code{FutureOr<\VOID>} and \code{FutureOr<FutureOr<\DYNAMIC>{}>}.
+}
+
+% We define the property of being regular-bounded for all types,
+% being super-bounded for parameterized types, and being well-bounded
+% for all types. We require that all types are well-bounded, which
+% covers every subterm of a type that is itself a type, and then we
+% require that types must be regular-bounded when used in certain
+% situations.
+
+\LMHash{}
+Every type which is not a parameterized type is {\em regular-bounded}.
+Let $T$ be a parameterized type of the form
+\code{$G$<$S_1, \ldots,\ S_n$>}
+where $G$ denotes a generic class or a parameterized type alias.
+Let
+\code{$X_1\ \EXTENDS\ B_1, \ldots,\ X_n\ \EXTENDS\ B_n$}
+be the formal type parameter declarations of $G$.
+$T$ is {\em regular-bounded} if{}f
+$S_j$ is a subtype of
+$[S_1/X_1, \ldots,\ S_n/X_n]B_j$,
+for all $j \in 1 .. n$.
+
+\commentary{
+This means that each actual type argument satisfies the declared upper
+bound for the corresponding formal type parameter.
+}
+
+\LMHash{}
+Let $T$ be a parameterized type of the form
+\code{$G$<$S_1, \ldots,\ S_n$>}
+where $G$ denotes a generic class or a parameterized type alias.
+$T$ is {\em super-bounded} if{}f the following conditions are both true:
+
+\begin{itemize}
+\item
+ $T$ is not regular-bounded.
+\item
+ For each $j \in 1 .. n$, let $S'_j$ be the result of replacing
+ every occurrence of a top type
+ in a covariant position in $S_j$ by \code{Null},
+ and every occurrence of \code{Null}
+ in a contravariant position in $S_j$ by \code{Object}.
+ It is then required that
+ \code{$G$<$S'_1, \ldots,\ S'_n$>}
+ is regular-bounded.
+\end{itemize}
+
+\commentary{
+In short, at least one type argument violates its bound, but the type is
+regular-bounded after replacing all occurrences of an extreme type by an
+opposite extreme type, depending on their variance.
+}
+
+\LMHash{}
+A type $T$ is {\em well-bounded} if{}f
+it is either regular-bounded or super-bounded.
+
+\LMHash{}
+Any use of a type $T$ which is not well-bounded is a compile-time error.
+
+\LMHash{}
+It is a compile-time error if a parameterized type $T$ is super-bounded
+when it is used in any of the following ways:
+\begin{itemize}
+\item $T$ is an immediate subterm of a new expression
+ (\ref{new})
+ or a constant object expression
+ (\ref{const}).
+\item $T$ is an immediate subterm of a redirecting factory constructor
+ signature
+ (\ref{redirectingFactoryConstructors}).
+\item $T$ is an immediate subterm of an \EXTENDS{} clause
+ (\ref{superclasses}),
+ or it occurs as an element in the type list of an \IMPLEMENTS{} clause
+ (\ref{superinterfaces}),
+ or a \WITH{} clause
+ (\ref{classes}).
+\end{itemize}
+
+\commentary{
+Types of members from super-bounded class types are computed using the same
+rules as types of members from other types. Types of function applications
+involving super-bounded types are computed using the same rules as types of
+function applications involving other types. Here is an example:
+}
+
+\begin{dartCode}
+\CLASS{} A<X \EXTENDS{} num> \{
+ X x;
+\}
+
+A<Object> a;
+\end{dartCode}
+
+\commentary{
+With this, \code{a.x} has static type \code{Object},
+even though the upper bound on the type variable \code{X} is \code{num}.
+}
+
+\rationale{
+Super-bounded types enable the expression of informative common supertypes
+of some sets of types whose common supertypes would otherwise be much less informative.
+For example, consider the following class:
+}
+
+\begin{dartCode}
+\CLASS{} C<X \EXTENDS{} C<X>$\!$> \{
+ X next;
+\}
+\end{dartCode}
+
+\rationale{
+Without super-bounded types,
+there is no type $T$ which makes \code{C<$T$>} a common supertype of
+all types of the form \code{C<$S$>}
+(noting that all types must be regular-bounded
+when we do not have the notion of super-bounded types).
+So if we wish to allow a variable to hold any instance ``of type \code{C}''
+then that variable must use \code{Object} or another top type
+as its type annotation,
+which means that a member like \code{next} is not known to exist
+(which is what we mean by saying that the type is `less informative').
+
+We could introduce a notion of recursive (infinite) types, and express
+the least upper bound of all types of the form \code{C<$S$>} as
+some syntax whose meaning could be approximated by
+\code{C<C<C<C<$\ldots$>$\!$>$\!$>$\!$>}.
+
+However, we expect that any such concept in Dart would incur a significant cost
+on developers and implementations in terms of added complexity and subtlety,
+so we have chosen not to do that.
+Super-bounded types are finite,
+but they offer a useful developer-controlled approximation to such infinite types.
+}
+
+\commentary{
+For example,
+\code{C<Object>} and
+\code{C<C<C<\VOID>{}>{}>}
+are types that a developer may choose to use as a type annotation.
+This choice serves as a commitment to
+a finite level of unfolding of the infinite type,
+and it allows for a certain amount of control
+at the point where the unfolding ends:
+%
+If \code{c} has type \code{C<C<\DYNAMIC>{}>}
+then \code{c.next.next} has type \DYNAMIC{}
+and \code{c.next.next.whatever} has no compile-time error,
+but if \code{c} has type \code{C<C<\VOID>{}>} then
+\code{Object x = c.next.next;} is a compile-time error.
+It is thus possible for developers to get a more or less strict treatment
+of expressions whose type proceeds beyond the given finite unfolding.
+}
+
+
\section{Metadata}
\LMLabel{metadata}
@@ -3636,7 +4023,7 @@
An unescaped \$ character in a string signifies the beginning of an interpolated expression.
The \$ sign may be followed by either:
\begin{itemize}
-\item A single identifier $id$ that must not contain the \$ character.
+\item A single identifier \id{} that must not contain the \$ character.
\item An expression $e$ delimited by curly braces.
\end{itemize}
@@ -3665,10 +4052,10 @@
\end{grammar}
\LMHash{}
-A symbol literal \code{\#$id$} where $id$ does not begin with an underscore ('\code{\_}') is equivalent to the expression \code{\CONST{} Symbol('$id$')}.
+A symbol literal \code{\#\id} where \id{} does not begin with an underscore ('\code{\_}') is equivalent to the expression \code{\CONST{} Symbol('\id')}.
\LMHash{}
-A symbol literal \code{\#\_$id$} evaluates to the object that would be returned by the call \code{MirrorSystem.getSymbol("\_$id$", \metavar{libraryMirror})} where \metavar{libraryMirror} is an instance of the class \code{LibraryMirror} defined in the library \code{dart:mirrors}, reflecting the current library.
+A symbol literal \code{\#\_\id} evaluates to the object that would be returned by the call \code{MirrorSystem.getSymbol("\_\id", \metavar{libraryMirror})} where \metavar{libraryMirror} is an instance of the class \code{LibraryMirror} defined in the library \code{dart:mirrors}, reflecting the current library.
\rationale{
One may well ask what is the motivation for introducing literal symbols? In some languages, symbols are canonicalized whereas strings are not.
@@ -4169,11 +4556,11 @@
It is a static type warning if
the type $T$ in an instance creation expression of one of the forms
-\code{\NEW{} $T.id$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)},
+\code{\NEW{} $T$.\id($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)},
\code{\NEW{} $T$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)},
-\code{\CONST{} $T.id$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)},
+\code{\CONST{} $T$.\id($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)},
\code{\CONST{} $T$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
is malformed (\ref{dynamicTypeSystem}) or malbounded (\ref{parameterizedTypes}).
@@ -4181,11 +4568,11 @@
\LMHash{}
It is a compile-time error if the type $T$ in an instance creation expression of one of the forms
-\code{\NEW{} $T.id$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)},
+\code{\NEW{} $T$.\id($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)},
\code{\NEW{} $T$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)},
-\code{\CONST{} $T.id$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)},
+\code{\CONST{} $T$.\id($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)},
\code{\CONST{} $T$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
@@ -4207,7 +4594,7 @@
\LMHash{}
Let $e$ be a new expression of the form
-\code{\NEW{} $T.id$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
+\code{\NEW{} $T$.\id($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
or the form
\code{\NEW{} $T$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}.
@@ -4223,8 +4610,8 @@
\begin{itemize}
\item
If $e$ is of the form
-\code{\NEW{} $T.id$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
-it is a static warning if $T.id$ is not the name of a constructor declared by the type $T$.
+\code{\NEW{} $T$.\id($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
+it is a static warning if \code{$T$.\id} is not the name of a constructor declared by the type $T$.
\item
If $e$ is of the form
\code{\NEW{} $T$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
@@ -4241,8 +4628,8 @@
%error if $S$ is not a generic (\ref{generics}) type with $m$ type parameters.
If $T$ is not a parameterized type, let $R = T$.
Furthermore, if $e$ is of the form
-\code{\NEW{} $T.id$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
-then let $q$ be the constructor $T.id$, otherwise let $q$ be the constructor $T$.
+\code{\NEW{} $T$.\id($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
+then let $q$ be the constructor \code{$T$.\id}, otherwise let $q$ be the constructor $T$.
\LMHash{}
If $R$ is a generic with $l = m$ type parameters then
@@ -4297,9 +4684,12 @@
Then:
\LMHash{}
-If $q$ is a redirecting factory constructor of the form $T(p_1, \ldots,\ p_{n+k}) = c;$ or of the form $T.id(p_1, \ldots,\ p_{n+k}) = c;$ then the result of the evaluation of $e$ is equivalent to evaluating the expression
+If $q$ is a redirecting factory constructor of the form $T(p_1, \ldots,\ p_{n+k}) = c;$ or of the form \code{$T$.\id($p_1, \ldots,\ p_{n+k}$) = $c$;} then the result of the evaluation of $e$ is equivalent to evaluating the expression
-$[V_1/T_1, \ldots, V_m/T_m]($\code{\NEW{} $c(a_1, \ldots,\ a_n, x_{n+1}: a_{n+1}, \ldots,\ x_{n+k}: a_{n+k}))$}.
+\code{[$V_1/X_1, \ldots, V_m/X_m$](\NEW{} $c$($a_1, \ldots,\ a_n, x_{n+1}: a_{n+1}, \ldots,\ x_{n+k}: a_{n+k}$))}
+
+\noindent
+where $X_1, \ldots,\ X_m$ are the formal type parameters of $R$.
If evaluation of $q$ causes $q$ to be re-evaluated cyclically, with only factory constructor redirections in-between, a run-time error occurs.
% Used to not have the "in-between" clause, which would disallow a factory constructor redirecting to another constructor which conditionally calls the original factory constructor again with different arguments.
@@ -4327,14 +4717,14 @@
\LMHash{}
The static type of an instance creation expression of either the form
-\code{\NEW{} $T.id$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
+\code{\NEW{} $T$.\id($a_1, \ldots,\ a_n,\ x_{n+1}:\ a_{n+1}, \ldots,\ x_{n+k}:\ a_{n+k}$)}
or the form
-\code{\NEW{} $T$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
+\code{\NEW{} $T$($a_1, \ldots,\ a_n,\ x_{n+1}:\ a_{n+1}, \ldots,\ x_{n+k}:\ a_{n+k}$)}
is $T$.
-It is a static warning if the static type of $a_i, 1 \le i \le n + k$ may not be assigned to the type of the corresponding formal parameter of the constructor $T.id$ (respectively $T$).
+It is a static warning if the static type of $a_i, 1 \le i \le n + k$ may not be assigned to the type of the corresponding formal parameter of the constructor \code{$T$.\id} (respectively $T$).
\subsubsection{Const}
@@ -4351,10 +4741,10 @@
\LMHash{}
Let $e$ be a constant object expression of the form
-\code{\CONST{} $T.id$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
+\code{\CONST{} $T$.\id($a_1, \ldots,\ a_n,\ x_{n+1}:\ a_{n+1}, \ldots,\ x_{n+k}:\ a_{n+k}$)}
or the form
-\code{\CONST{} $T$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}.
+\code{\CONST{} $T$($a_1, \ldots,\ a_n,\ x_{n+1}:\ a_{n+1}, \ldots,\ x_{n+k}:\ a_{n+k}$)}.
It is a compile-time error if $T$ does not denote a class accessible in the current scope.
It is a compile-time error if $T$ is a deferred type (\ref{staticTypes}).
@@ -4367,8 +4757,8 @@
\LMHash{}
If $e$ is of the form
-\code{\CONST{} $T.id$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
-it is a compile-time error if $T.id$ is not the name of a constant constructor declared by the type $T$.
+\code{\CONST{} $T$.\id($a_1, \ldots,\ a_n,\ x_{n+1}:\ a_{n+1}, \ldots,\ x_{n+k}:\ a_{n+k}$)}
+it is a compile-time error if \code{$T$.\id} is not the name of a constant constructor declared by the type $T$.
If $e$ is of the form
\code{\CONST{} $T$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
it is a compile-time error if the type $T$ does not declare a constant constructor with the same name as the declaration of $T$.
@@ -4386,11 +4776,11 @@
\LMHash{}
First, if $e$ is of the form
-\code{\CONST{} $T.id$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
+\code{\CONST{} $T$.\id($a_1, \ldots,\ a_n,\ x_{n+1}:\ a_{n+1}, \ldots,\ x_{n+k}:\ a_{n+k}$)}
then let $i$ be the value of the expression
-\code{\NEW{} $T.id$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}.
+\code{\NEW{} $T$.\id($a_1, \ldots,\ a_n,\ x_{n+1}:\ a_{n+1}, \ldots,\ x_{n+k}:\ a_{n+k}$)}.
\LMHash{}
Otherwise, $e$ must be of the form
@@ -4424,14 +4814,14 @@
\LMHash{}
The static type of a constant object expression of either the form
-\code{\CONST{} $T.id$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
+\code{\CONST{} $T$.\id($a_1, \ldots,\ a_n,\ x_{n+1}:\ a_{n+1}, \ldots,\ x_{n+k}:\ a_{n+k}$)}
or the form
-\code{\CONST{} $T$($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}
+\code{\CONST{} $T$($a_1, \ldots,\ a_n,\ x_{n+1}:\ a_{n+1}, \ldots,\ x_{n+k}:\ a_{n+k}$)}
is $T$.
-It is a static warning if the static type of $a_i, 1 \le i \le n+ k$ may not be assigned to the type of the corresponding formal parameter of the constructor $T.id$ (respectively $T$).
+It is a static warning if the static type of $a_i, 1 \le i \le n+ k$ may not be assigned to the type of the corresponding formal parameter of the constructor \code{$T$.\id} (respectively $T$).
\LMHash{}
It is a compile-time error if evaluation of a constant object results in an uncaught exception being thrown.
@@ -4785,23 +5175,23 @@
\LMHash{}
An unqualified function invocation $i$ has the form
-\code{$id$<$A_1, \ldots,\ A_r$>($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)},
+\code{\id<$A_1, \ldots,\ A_r$>($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)},
\noindent
-where $id$ is an identifier.
+where \id{} is an identifier.
\commentary{
Note that the type argument list is omitted when $r = 0$ (\ref{generics}).
}
\LMHash{}
-If there exists a lexically visible declaration named $id$, let $f_{id}$ be the innermost such declaration.
+If there exists a lexically visible declaration named \id, let $f_{id}$ be the innermost such declaration.
Then:
\begin{itemize}
\item
-If $id$ is a type literal, then $i$ is interpreted as a function expression invocation (\ref{functionExpressionInvocation}) with $(id)$ as the expression $e_f$.
+If \id{} is a type literal, then $i$ is interpreted as a function expression invocation (\ref{functionExpressionInvocation}) with $(\id)$ as the expression $e_f$.
\commentary{
-The expression $(id)$ where $id$ is a type literal always evaluates to an instance of class \code{Type} which is not a function.
+The expression $(\id)$ where \id{} is a type literal always evaluates to an instance of class \code{Type} which is not a function.
This ensures that a run-time error occurs when trying to call a type literal.
}
\item
@@ -4810,10 +5200,10 @@
If $f_{id}$ is a local function, a library function, a library or static getter or a variable then $i$ is interpreted as a function expression invocation (\ref{functionExpressionInvocation}).
\item
Otherwise, if $f_{id}$ is a static method of the enclosing class $C$, $i$ is equivalent to
-\code{$C.id$<$A_1, \ldots,\ A_r$>($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}.
+\code{$C$.\id<$A_1, \ldots,\ A_r$>($a_1, \ldots,\ a_n,\ x_{n+1}:\ a_{n+1}, \ldots,\ x_{n+k}:\ a_{n+k}$)}.
\item Otherwise, $f_{id}$ is equivalent to the ordinary method invocation
-\code{\THIS{}.$id$<$A_1, \ldots,\ A_r$>($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}.
+\code{\THIS{}.\id<$A_1, \ldots,\ A_r$>($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}.
\end{itemize}
\LMHash{}
@@ -4821,10 +5211,10 @@
\LMHash{}
If $i$ does not occur inside a top level or static function, $i$ is equivalent to
-\code{\THIS{}.$id$<$A_1, \ldots,\ A_r$>($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}.
+\code{\THIS{}.\id<$A_1, \ldots,\ A_r$>($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}.
% Should also say:
-% It is a static warning if $i$ occurs inside a top level or static function (be it function, method, getter, or setter) or variable initializer and there is no lexically visible declaration named $id$ in scope.
+% It is a static warning if $i$ occurs inside a top level or static function (be it function, method, getter, or setter) or variable initializer and there is no lexically visible declaration named \id{} in scope.
\subsubsection{Function Expression Invocation}
@@ -4843,7 +5233,7 @@
}
\LMHash{}
-If $e_f$ is an identifier $id$, then $id$ must necessarily denote a local function, a library function, a library or static getter or a variable as described above, or $i$ is not considered a function expression invocation.
+If $e_f$ is an identifier \id, then \id{} must necessarily denote a local function, a library function, a library or static getter or a variable as described above, or $i$ is not considered a function expression invocation.
If $e_f$ is a type literal, then it is equivalent to the expression $(e_f)$.
\commentary{
@@ -5482,7 +5872,7 @@
\LMHash{}
Evaluation of a {\em conditional property extraction expression} $e$
-of the form \code{$e_1$?.\metavar{id}} proceeds as follows:
+of the form \code{$e_1$?.\id} proceeds as follows:
\LMHash{}
If $e_1$ is a type literal, $e$ is equivalent to \code{$e_1$.$m$}.
@@ -5491,12 +5881,12 @@
Otherwise evaluate $e_1$ to an object $o$.
If $o$ is the null object, $e$ evaluates to the null object (\ref{null}).
Otherwise let $x$ be a fresh variable bound to $o$
-and evaluate \code{$x$.\metavar{id}} to a value $r$.
+and evaluate \code{$x$.\id} to a value $r$.
Then $e$ evaluates to $r$.
-The static type of $e$ is the same as the static type of \code{$e_1$.\metavar{id}}.
+The static type of $e$ is the same as the static type of \code{$e_1$.\id}.
Let $T$ be the static type of $e_1$ and let $y$ be a fresh variable of type $T$.
-Exactly the same static warnings that would be caused by \code{$y$.\metavar{id}} are also generated in the case of \code{$e_1$?.\metavar{id}}.
+Exactly the same static warnings that would be caused by \code{$y$.\id} are also generated in the case of \code{$e_1$?.\id}.
\LMHash{}
Unconditional property extraction has one of two syntactic forms: $e.m$ (\ref{getterAccessAndMethodExtraction}) or $\SUPER.m$ (\ref{superGetterAccessAndMethodClosurization}), where $e$ is an expression and $m$ is an identifier.
@@ -6849,18 +7239,18 @@
\end{itemize}
\LMHash{}
-An assignable expression of the form $id$ is evaluated as an identifier expression (\ref{identifierReference}).
+An assignable expression of the form \id{} is evaluated as an identifier expression (\ref{identifierReference}).
-%An assignable expression of the form $e.id(a_1, \ldots, a_n)$ is evaluated as a method invocation (\ref{methodInvocation}).
+%An assignable expression of the form \code{$e$.\id($a_1, \ldots, a_n$)} is evaluated as a method invocation (\ref{methodInvocation}).
\LMHash{}
-An assignable expression of the form $e.id$ or $e?.id$ is evaluated as a property extraction (\ref{propertyExtraction}).
+An assignable expression of the form \code{$e$.\id} or \code{$e$?.\id} is evaluated as a property extraction (\ref{propertyExtraction}).
\LMHash{}
An assignable expression of the form \code{$e_1$[$e_2$]} is evaluated as a method invocation of the operator method \code{[]} on $e_1$ with argument $e_2$.
\LMHash{}
-An assignable expression of the form \code{\SUPER{}.id} is evaluated as a property extraction.
+An assignable expression of the form \code{\SUPER{}.\id} is evaluated as a property extraction.
\LMHash{}
Evaluation of an assignable expression of the form \code{\SUPER{}[$e_2$]} is equivalent to evaluation of the method invocation \code{\SUPER{}.[]($e_2$)}.
@@ -6950,12 +7340,12 @@
}
\LMHash{}
-Evaluation of an identifier expression $e$ of the form $id$ proceeds as follows:
+Evaluation of an identifier expression $e$ of the form \id{} proceeds as follows:
\LMHash{}
-Let $d$ be the innermost declaration in the enclosing lexical scope whose name is $id$ or $id=$.
-If no such declaration exists in the lexical scope, let $d$ be the declaration of the inherited member named $id$ if it exists.
-%If no such member exists, let $d$ be the declaration of the static member name $id$ declared in a superclass of the current class, if it exists.
+Let $d$ be the innermost declaration in the enclosing lexical scope whose name is \id{} or \code{\id=}.
+If no such declaration exists in the lexical scope, let $d$ be the declaration of the inherited member named \id{} if it exists.
+%If no such member exists, let $d$ be the declaration of the static member name \id{} declared in a superclass of the current class, if it exists.
\begin{itemize}
\item if $d$ is a prefix $p$, a compile-time error occurs unless the token immediately following $d$ is \code{'.'}.
@@ -6967,17 +7357,17 @@
%\item If $d$ is a library variable then:
% \begin{itemize}
% \item If $d$ is of one of the forms \code{\VAR{} $v$ = $e_i$;} , \code{$T$ $v$ = $e_i$;} , \code{\FINAL{} $v$ = $e_i$;} or \code{\FINAL{} $T$ $v$ = $e_i$;} and no value has yet been stored into $v$ then the initializer expression $e_i$ is evaluated. If, during the evaluation of $e_i$, the getter for $v$ is referenced, a \code{CyclicInitializationError} is thrown. If the evaluation succeeded yielding an object $o$, let $r$ be $o$, otherwise let $r$ be the null object (\ref{null}). In any case, $r$ is stored into $v$. The value of $e$ is $r$.
-\item If $d$ is a constant variable of one of the forms \code{\CONST{} $v$ = $e$;} or \code{\CONST{} $T$ $v$ = $e$;} then the value $id$ is the value of the compile-time constant $e$.
+\item If $d$ is a constant variable of one of the forms \code{\CONST{} $v$ = $e$;} or \code{\CONST{} $T$ $v$ = $e$;} then the value \id{} is the value of the compile-time constant $e$.
% Otherwise
-% \item $e$ evaluates to the current binding of $id$.
+% \item $e$ evaluates to the current binding of \id.
% \end{itemize}
-\item If $d$ is a local variable or formal parameter then $e$ evaluates to the current binding of $id$.
-%\item If $d$ is a library variable, local variable, or formal parameter, then $e$ evaluates to the current binding of $id$. \commentary{This case also applies if d is a library or local function declaration, as these are equivalent to function-valued variable declarations.}
+\item If $d$ is a local variable or formal parameter then $e$ evaluates to the current binding of \id.
+%\item If $d$ is a library variable, local variable, or formal parameter, then $e$ evaluates to the current binding of \id. \commentary{This case also applies if d is a library or local function declaration, as these are equivalent to function-valued variable declarations.}
\item If $d$ is a static method, top-level function or local function then $e$ evaluates to the function object obtained by closurization (\ref{functionClosurization}) of the declaration denoted by $d$.
-\item If $d$ is the declaration of a static variable, static getter or static setter declared in class $C$, then evaluation of $e$ is equivalent to evaluation of the property extraction (\ref{propertyExtraction}) $C.id$.
-\item If $d$ is the declaration of a library variable, top-level getter or top-level setter, then evaluation of $e$ is equivalent to evaluation of the top level getter invocation (\ref{topLevelGetterInvocation}) $id$.
+\item If $d$ is the declaration of a static variable, static getter or static setter declared in class $C$, then evaluation of $e$ is equivalent to evaluation of the property extraction (\ref{propertyExtraction}) \code{$C$.\id}.
+\item If $d$ is the declaration of a library variable, top-level getter or top-level setter, then evaluation of $e$ is equivalent to evaluation of the top level getter invocation (\ref{topLevelGetterInvocation}) \id.
\item Otherwise, if $e$ occurs inside a top level or static function (be it function, method, getter, or setter) or variable initializer, evaluation of $e$ causes a \code{NoSuchMethod} to be thrown.
-\item Otherwise, evaluation of $e$ is equivalent to evaluation of the property extraction (\ref{propertyExtraction}) \THIS{}.$id$.
+\item Otherwise, evaluation of $e$ is equivalent to evaluation of the property extraction (\ref{propertyExtraction}) \THIS{}.\id.
% This implies that referring to an undefined static getter by simple name is an error, whereas doing so by qualified name is only a warning. Same with assignments. Revise?
\end{itemize}
@@ -6986,12 +7376,12 @@
\begin{itemize}
\item If $d$ is a class, type alias or type parameter the static type of $e$ is \code{Type}.
-\item If $d$ is a local variable or formal parameter the static type of $e$ is the type of the variable $id$, unless $id$ is known to have some type $T$, in which case the static type of $e$ is $T$, provided that $T$ is more specific than any other type $S$ such that $v$ is known to have type $S$.
+\item If $d$ is a local variable or formal parameter the static type of $e$ is the type of the variable \id, unless \id{} is known to have some type $T$, in which case the static type of $e$ is $T$, provided that $T$ is more specific than any other type $S$ such that $v$ is known to have type $S$.
\item If $d$ is a static method, top-level function or local function the static type of $e$ is the function type defined by $d$.
-\item If $d$ is the declaration of a static variable, static getter or static setter declared in class $C$, the static type of $e$ is the static type of the getter invocation (\ref{propertyExtraction}) $C.id$.
-\item If $d$ is the declaration of a library variable, top-level getter or top-level setter, the static type of $e$ is the static type of the top level getter invocation $id$.
+\item If $d$ is the declaration of a static variable, static getter or static setter declared in class $C$, the static type of $e$ is the static type of the getter invocation (\ref{propertyExtraction}) \code{$C$.\id}.
+\item If $d$ is the declaration of a library variable, top-level getter or top-level setter, the static type of $e$ is the static type of the top level getter invocation \id.
\item Otherwise, if $e$ occurs inside a top level or static function (be it function, method, getter, or setter) or variable initializer, the static type of $e$ is \DYNAMIC{}.
-\item Otherwise, the static type of $e$ is the type of the property extraction (\ref{propertyExtraction}) \THIS{}.$id$.
+\item Otherwise, the static type of $e$ is the type of the property extraction (\ref{propertyExtraction}) \THIS{}.\id.
\end{itemize}
\commentary{
@@ -7004,7 +7394,7 @@
}
\LMHash{}
-It is a static warning if an identifier expression $id$ occurs inside a top level or static function (be it function, method, getter, or setter) or variable initializer and there is no declaration $d$ with name $id$ in the lexical scope enclosing the expression.
+It is a static warning if an identifier expression \id{} occurs inside a top level or static function (be it function, method, getter, or setter) or variable initializer and there is no declaration $d$ with name \id{} in the lexical scope enclosing the expression.
\subsection{Type Test}
@@ -7252,7 +7642,11 @@
\end{grammar}
\LMHash{}
-A function declaration statement of one of the forms $id$ $signature$ $\{ statements \}$ or $T$ $id$ $signature$ $\{ statements \}$ causes a new function named $id$ to be added to the innermost enclosing scope.
+A function declaration statement of one of the forms
+\code{\id{} \metavar{signature} \{ \metavar{statements} \}}
+or
+\code{$T$ \id{} \metavar{signature} \{ \metavar{statements} \}}
+causes a new function named \id{} to be added to the innermost enclosing scope.
It is a compile-time error to reference a local function before its declaration.
\commentary{
@@ -7448,12 +7842,12 @@
\LMHash{}
Let $D$ be derived from \code{finalConstVarOrType?}
and let $n0$ be an identifier that does not occur anywhere in the program.
-A for statement of the form \code{\FOR{} ($D$ $id$ \IN{} $e$) $s$} is equivalent to the following code:
+A for statement of the form \code{\FOR{} ($D$ \id{} \IN{} $e$) $s$} is equivalent to the following code:
\begin{dartCode}
\VAR{} $n0$ = $e$.iterator;
\WHILE{} ($n0$.moveNext()) \{
- $D$ $id$ = $n0$.current;
+ $D$ \id{} = $n0$.current;
$s$
\}
\end{dartCode}
@@ -7463,7 +7857,7 @@
where $T$ is the static type of \code{$e$.iterator}.
\commentary{
-It follows that it is a static warning if $D$ is empty and $id$ is a final variable,
+It follows that it is a static warning if $D$ is empty and \id{} is a final variable,
and a dynamic error will then occur if the body is executed.
}
@@ -7479,13 +7873,13 @@
\LMHash{}
Let $D$ be derived from \code{finalConstVarOrType?}.
Execution of a for-in statement, $f$, of the form
-\code{\AWAIT{} \FOR{} ($D$ $id$ \IN{} $e$) $s$}
+\code{\AWAIT{} \FOR{} ($D$ \id{} \IN{} $e$) $s$}
proceeds as follows:
\LMHash{}
The expression $e$ is evaluated to an object $o$.
It is a dynamic error if $o$ is not an instance of a class that implements \code{Stream}.
-It is a static warning if $D$ is empty and $id$ is a final variable,
+It is a static warning if $D$ is empty and \id{} is a final variable,
and it is then a dynamic error if the body is executed.
\LMHash{}
@@ -7507,7 +7901,7 @@
\LMHash{}
For each {\em data event} from $u$,
-the statement $s$ is executed with $id$ bound to the value of the current data event.
+the statement $s$ is executed with \id{} bound to the value of the current data event.
\commentary{
Either execution of $s$ is completely synchronous, or it contains an
@@ -7707,7 +8101,7 @@
proceeds as follows:
\LMHash{}
-The statement \code{\VAR{} $id$ = $e$;} is evaluated, where $id$ is a fresh variable.
+The statement \code{\VAR{} \id{} = $e$;} is evaluated, where \id{} is a fresh variable.
In checked mode, it is a run-time error if the value of $e$ is not an instance of the same class as the constants $e_1, \ldots, e_n$.
\commentary{
@@ -7715,7 +8109,7 @@
}
\LMHash{}
-Next, the case clause \CASE{} $e_{1}$: $s_{1}$ is matched against $id$, if $n > 0$.
+Next, the case clause \CASE{} $e_{1}$: $s_{1}$ is matched against \id, if $n > 0$.
Otherwise if there is a \DEFAULT{} clause, the case statements $s_{n+1}$ are executed (\ref{case-execute}).
\LMHash{}
@@ -7730,11 +8124,11 @@
\}
\end{dartCode}
-against the value of a variable $id$ proceeds as follows:
+against the value of a variable \id{} proceeds as follows:
\LMHash{}
-The expression \code{$e_k$ == $id$} is evaluated to an object $o$ which is then subjected to boolean conversion evaluating to a value $v$.
-If $v$ is not \TRUE{} the following case, \CASE{} $e_{k+1}: s_{k+1}$ is matched against $id$ if $k < n$.
+The expression \code{$e_k$ == \id} is evaluated to an object $o$ which is then subjected to boolean conversion evaluating to a value $v$.
+If $v$ is not \TRUE{} the following case, \CASE{} $e_{k+1}: s_{k+1}$ is matched against \id{} if $k < n$.
If $k = n$, then the \DEFAULT{} clause's statements are executed (\ref{case-execute}).
If $v$ is \TRUE{}, let $h$ be the smallest number such that $h \ge k$ and $s_h$ is non-empty.
If no such $h$ exists, let $h = n + 1$.
@@ -7751,11 +8145,11 @@
\}
\end{dartCode}
-against the value of a variable $id$ proceeds as follows:
+against the value of a variable \id{} proceeds as follows:
\LMHash{}
-The expression \code{$e_k$ == $id$} is evaluated to an object $o$ which is then subjected to boolean conversion evaluating to a value $v$.
-If $v$ is not \TRUE{} the following case, \CASE{} $e_{k+1}: s_{k+1}$ is matched against $id$ if $k < n$.
+The expression \code{$e_k$ == \id} is evaluated to an object $o$ which is then subjected to boolean conversion evaluating to a value $v$.
+If $v$ is not \TRUE{} the following case, \CASE{} $e_{k+1}: s_{k+1}$ is matched against \id{} if $k < n$.
If $v$ is \TRUE{}, let $h$ be the smallest integer such that $h \ge k$ and $s_h$ is non-empty.
If such a $h$ exists, the case statements $s_h$ are executed (\ref{case-execute}).
Otherwise the switch statement completes normally (\ref{completion}).
@@ -8534,7 +8928,7 @@
The import modifies the namespace of the current library in a manner that is determined by the imported library and by the optional elements of the import.
\LMHash{}
-An immediate import directive $I$ may optionally include a prefix clause of the form \code{\AS{} $id$} used to prefix names imported by $I$.
+An immediate import directive $I$ may optionally include a prefix clause of the form \code{\AS{} \id} used to prefix names imported by $I$.
A deferred import must include a prefix clause or a compile-time error occurs.
It is a compile-time error if a prefix used in a deferred import is used in another import clause.
@@ -8557,13 +8951,13 @@
When called, the method causes an immediate import $I'$ to be executed at some future time, where $I'$ is derived from $I$ by eliding the word \DEFERRED{} and adding a \HIDE{} \code{loadLibrary} combinator clause.
When $I'$ executes without error, $f$ completes successfully.
If $I'$ executes without error, we say that the call to \code{loadLibrary} has succeeded, otherwise we say the call has failed.
-\item For every top level function $f$ named $id$ in the imported library $B$, a corresponding method named $id$ with the same signature as $f$.
+\item For every top level function $f$ named \id{} in the imported library $B$, a corresponding method named \id{} with the same signature as $f$.
Calling the method results in a run-time error.
-\item For every top level getter $g$ named $id$ in $B$, a corresponding getter named $id$ with the same signature as $g$.
+\item For every top level getter $g$ named \id{} in $B$, a corresponding getter named \id{} with the same signature as $g$.
Calling the method results in a run-time error.
-\item For every top level setter $s$ named $id$ in $B$, a corresponding setter named $id$ with the same signature as $s$.
+\item For every top level setter $s$ named \id{} in $B$, a corresponding setter named \id{} with the same signature as $s$.
Calling the method results in a run-time error.
-\item For every type $T$ named $id$ in $B$, a corresponding getter named $id$ with return type \code{Type}.
+\item For every type $T$ named \id{} in $B$, a corresponding getter named \id{} with return type \code{Type}.
Calling the method results in a run-time error.
\end{itemize}
@@ -8642,10 +9036,10 @@
Next, if $I$ includes a prefix clause of the form \AS{} $p$, let $NS = NS_n \cup \{p: prefixObject(NS_n)\}$ where $prefixObject(NS_n)$ is a {\em prefix object} for the namespace $NS_n$, which is an object that has the following members:
\begin{itemize}
-\item For every top level function $f$ named $id$ in $NS_n$, a corresponding method with the same name and signature as $f$ that forwards (\ref{functionDeclarations}) to $f$.
-\item For every top level getter with the same name and signature as $g$ named $id$ in $NS_n$, a corresponding getter that forwards to $g$.
-\item For every top level setter $s$ with the same name and signature as named $id$ in $NS_n$, a corresponding setter that forwards to $s$.
-\item For every type $T$ named $id$ in $NS_n$, a corresponding getter named $id$ with return type \code{Type}, that, when invoked, returns the type object for $T$.
+\item For every top level function $f$ named \id{} in $NS_n$, a corresponding method with the same name and signature as $f$ that forwards (\ref{functionDeclarations}) to $f$.
+\item For every top level getter with the same name and signature as $g$ named \id{} in $NS_n$, a corresponding getter that forwards to $g$.
+\item For every top level setter $s$ with the same name and signature as named \id{} in $NS_n$, a corresponding setter that forwards to $s$.
+\item For every type $T$ named \id{} in $NS_n$, a corresponding getter named \id{} with return type \code{Type}, that, when invoked, returns the type object for $T$.
\end{itemize}
\LMHash{}
@@ -8964,7 +9358,7 @@
Dart supports optional typing based on interface types.
\rationale{
-The type system is unsound, due to the covariance of generic types.
+The type system is unsound, due to the covariance of generic classes.
This is a deliberate choice (and undoubtedly controversial).
Experience has shown that sound type rules for generics fly in the face of programmer intuition.
It is easy for tools to provide a sound type analysis if they choose, which may be useful for tasks like refactoring.
@@ -9009,18 +9403,45 @@
\LMHash{}
A type $T$ is {\em malformed} if{}f:
\begin{itemize}
-\item $T$ has the form $id$ or the form $prefix.id$, and in the enclosing lexical scope, the name $id$ (respectively $prefix.id$) does not denote a type.
-\item $T$ denotes a type variable in the enclosing lexical scope, but occurs in the signature or body of a static member.
-\item $T$ is a parameterized type of the form \code{$G$<$S_1, \ldots,\ S_n$>}, and $G$ is malformed.
-\item $T$ denotes declarations that were imported from multiple imports clauses.
-%Either $G$ or $S_i, i \in 1 .. n$ are malformed.
-% \item $G$ is not a generic type with $n$ type parameters.
-% \item Let $T_i$ be the type parameters of $G$ (if any) and let $B_i$ be the bound of $T_i, i \in 1 .. n$, and $S_i$ is not a subtype of $[S_1/T_1, \ldots, S_n/T_n]B_i, i \in 1 .. n$.
-% \end{itemize}
+\item
+ $T$ has the form \id{} or the form \code{\metavar{prefix}.\id},
+ and in the enclosing lexical scope,
+ the name \id{} (respectively \code{\metavar{prefix}.\id}) does not denote a type.
+
+\item
+ $T$ denotes a type variable in the enclosing lexical scope,
+ but occurs in the signature or body of a static member.
+
+\item $T$ is a parameterized type of the form \code{$G$<$S_1, \ldots,\ S_n$>},
+ and $G$ is malformed,
+ or $G$ is not a generic type,
+ or $G$ is a generic type, but it declares $n'$ type parameters and $n' \not= n$,
+ or $S_j$ is malformed for some $j \in 1 .. n$.
+
+\item $T$ is a function type of the form
+
+ \code{$T_0$ \FUNCTION{}<$X_1\ \EXTENDS\ B_1, \ldots,\ X_m\ \EXTENDS\ B_m$>}
+
+ \code{\quad($T_1\ x_1, \ldots,\ T_k\ x_k,\ $[$T_{k+1}\ x_{k+1}, \ldots,\ T_n\ x_n$])}
+
+ \noindent
+ or of the form
+
+ \code{$T_0$ \FUNCTION{}<$X_1\ \EXTENDS\ B_1, \ldots,\ X_m\ \EXTENDS\ B_m$>}
+
+ \code{\quad($T_1\ x_1, \ldots,\ T_k\ x_k,\ $\{$T_{k+1}\ x_{k+1}, \ldots,\ T_n\ x_n$\})}
+
+ \noindent
+ where each $x_j$ which is not a named parameter may be omitted,
+ and $T_j$ is malformed for some $j \in 0 .. n$,
+ or $B_j$ is malformed for some $j \in 1 .. m$.
+
+\item
+ $T$ denotes declarations that were imported from multiple imports clauses.
\end{itemize}
\LMHash{}
- Any use of a malformed type gives rise to a static warning.
+Any use of a malformed type gives rise to a static warning.
A malformed type is then interpreted as \DYNAMIC{} by the static type checker and the run-time system unless explicitly specified otherwise.
\rationale{
@@ -9191,17 +9612,17 @@
\LMHash{}
The effect of a type alias of the form
-\code{\TYPEDEF{} $T$ $id$($T_1\ p_1, \ldots,\ T_n\ p_n,\ [T_{n+1}\ p_{n+1}, \ldots,\ T_{n+k}\ p_{n+k}]$)}
+\code{\TYPEDEF{} $T$ \id($T_1\ p_1, \ldots,\ T_n\ p_n,\ [T_{n+1}\ p_{n+1}, \ldots,\ T_{n+k}\ p_{n+k}]$)}
\noindent
-declared in a library $L$ is to introduce the name $id$ into the scope of $L$, bound to the function type
+declared in a library $L$ is to introduce the name \id{} into the scope of $L$, bound to the function type
$(T_1, \ldots,\ T_n, [T_{n+1}\ p_{n+1}, \ldots,\ T_{n+k} p_{n+k}]) \rightarrow T$.
The effect of a type alias of the form
-\code{\TYPEDEF{} $T$ $id$($T_1\ p_1, \ldots,\ T_n\ p_n,\ \{T_{n+1}\ p_{n+1}, \ldots,\ T_{n+k}\ p_{n+k}\}$)}
+\code{\TYPEDEF{} $T$ \id($T_1\ p_1, \ldots,\ T_n\ p_n,\ \{T_{n+1}\ p_{n+1}, \ldots,\ T_{n+k}\ p_{n+k}\}$)}
\noindent
-declared in a library $L$ is to introduce the name $id$ into the scope of $L$, bound to the function type
+declared in a library $L$ is to introduce the name \id{} into the scope of $L$, bound to the function type
$(T_1, \ldots,\ T_n, \{T_{n+1}\ p_{n+1}, \ldots,\ T_{n+k}\ p_{n+k}\}) \rightarrow T$.
In either case, if{}f no return type is specified, it is taken to be \DYNAMIC{}.
Likewise, if a type annotation is omitted on a formal parameter, it is taken to be \DYNAMIC{}.
@@ -9679,60 +10100,38 @@
\LMHash{}
Let $T$ be a parameterized type \code{$G$<$S_1, \ldots,\ S_n$>}.
-It is evaluated as follows.
+Assume that $T$ is not malformed.
-\LMHash{}
-If $G$ is not a generic type,
-the type arguments $S_i, i \in 1 .. n$ are ignored.
-If $G$ has $m \ne n$ type parameters, $T$ is treated as a parameterized type with $m$ arguments,
-all of which are \DYNAMIC{},
-and $S_i, i \in 1 .. n$ are ignored.
-
-%% TODO[dart-2]: This commentary should be completely obsolete in Dart 2.
\commentary{
-In short, any arity mismatch results in all type arguments being dropped, and replaced by the correct number of type arguments, all set to \DYNAMIC{}.
-Of course, a static warning will be issued.
+In particular, $G$ denotes a generic type with $n$ formal type parameters.
}
\LMHash{}
-Otherwise, let $X_i$ be the type parameters of $G$ and let $B_i$ be the bound of $X_i, i \in 1 .. n$.
-Let $t_i$ be the result of evaluating $S_i$, for $i \in 1 .. n$.
-
-\LMHash{}
-$T$ is {\em malbounded} if{}f either $S_i$ is malbounded or $t_i$ is not a subtype of
-$[t_1/X_1, \ldots, t_n/X_n]B_i$,
-for one or more $i \in 1 .. n$.
-
-% TODO(eernst): When changing from warnings to errors, include the following
-% as a commentary:
-%
-% We do not specify the result of evaluating a malbounded type.
-% This is because it is a compile-time error when a parameterized type is
-% encountered, unless it is statically known that it will not be malbounded.
-%
-% That is also the reason why we say "$S_i$ is malbounded", not "$t_i$" above.
-
-\LMHash{}
-Otherwise, $T$ evaluates to the generic instantiation where $G$ is applied to $t_1, \ldots, t_n$.
-
-\commentary{
-Note, that, in checked mode, it is a dynamic type error if a malbounded type is used in a type test as specified in \ref{dynamicTypeSystem}.
-}
+$T$ is {\em malbounded} if{}f either
+$S_i$ is malbounded for one or more $i \in 1 .. n$,
+or $T$ is not well-bounded (\ref{superBoundedTypes}).
\LMHash{}
Any use of a malbounded type gives rise to a static warning.
\LMHash{}
-If $S$ is the static type of a member $m$ of $G$,
-then the static type of the member $m$ of
+Let $T$ be a parameterized type of the form
\code{$G$<$A_1, \ldots,\ A_n$>}
-is
+and assume that $T$ is not malformed and not malbounded.
+If $S$ is the static type of a member $m$ declared by $G$,
+then the static type of the member $m$ of an expression of type $T$ is
$[A_1/X_1, \ldots, A_n/X_n]S$,
where $X_1, \ldots, X_n$ are the formal type parameters of $G$.
-Let $B_i$ be the bounds of $X_i, i \in 1 .. n$.
-It is a static type warning if $A_i$ is not a subtype of
-$[A_1/X_1, \ldots, A_n/X_n]B_i, i \in 1 .. n$.
-It is a static type warning if $G$ is not a generic type with exactly $n$ type parameters.
+
+\LMHash{}
+Let $T$ be a parameterized type of the form
+\code{$G$<$A_1, \ldots,\ A_n$>}
+and assume that $T$ is not malformed and not malbounded.
+$T$ is then evaluated as follows:
+
+\LMHash{}
+For $j \in 1 .. n$, evaluate $A_j$ to a type $t_j$.
+$T$ then evaluates to the generic instantiation where $G$ is applied to $t_1, \ldots, t_n$.
\subsubsection{Actual Type of Declaration}
@@ -9741,7 +10140,7 @@
% NOTE(eernst): The actual type arguments in this section are dynamic entities,
% not syntax (the concept of an 'actual type' and an 'actual bound' is used to
% specify the dynamic semantics, including dynamic errors). So we use $t_i$
-% to denote these type arguments, just like all those location where the
+% to denote these type arguments, just like all those locations where the
% concept is used, rather than $A_i$ which is frequently used to denote the
% syntax of an actual type argument.
%
@@ -9775,7 +10174,7 @@
Let \code{$X$ \EXTENDS{} $B$} be a formal type parameter declaration.
Let
$X_1, \ldots, X_n$
-be the formal type parameters in scope the declaration of $X$.
+be the formal type parameters in scope at the declaration of $X$.
In a context where the actual type arguments corresponding to
$X_1, \ldots, X_n$
are
@@ -9789,7 +10188,6 @@
}
-
\subsubsection{Least Upper Bounds}
\LMLabel{leastUpperBounds}
diff --git a/docs/language/informal/covariant-from-class.md b/docs/language/informal/covariant-from-class.md
index 0b66edf..2cdb696 100644
--- a/docs/language/informal/covariant-from-class.md
+++ b/docs/language/informal/covariant-from-class.md
@@ -4,7 +4,7 @@
**Status**: Implemented.
-**Version**: 0.5 (2018-02-01)
+**Version**: 0.6 (2018-06-01)
## Summary
@@ -258,55 +258,9 @@
may be different) which contains the built-in identifier `covariant`.*
*We need to introduce a new kind of covariant parameters, in addition to the
-ones that are covariant by modifier. To do that, we also need to define the
-variance of each occurrence of a type variable in a type, which determines how
-variations of the value of that type variable affect the overall type in a
-specific direction. There are three kinds: covariant, contravariant, and
-invariant occurrences.*
-
-We say that a type variable _X_ _occurs covariantly_ in a type _T_ if:
-
-- _T_ is _X_.
-- _T_ is a parameterized type _G<S<sub>0</sub> ..., S<sub>n</sub>>_, and
- there is a _j_ such that _X_ occurs covariantly in _S<sub>j</sub>_.
-- _T_ is a function type and _X_ occurs covariantly in the return type of
- _T_, or _X_ occurs contravariantly in a parameter type of _T_.
-
-We say that a type variable _X_ _occurs contravariantly_ in a type _T_ if:
-
-- _T_ is a parameterized type _G<S<sub>0</sub>, ..., S<sub>n</sub>>_, and
- there is a _j_ such that _X_ occurs contravariantly in _S<sub>j</sub>_.
-- _T_ is a function type and _X_ occurs contravariantly in the return
- type of _T_, or _X_ occurs covariantly in a parameter type of _T_.
-
-We say that a type variable _X_ _occurs invariantly_ in a type _T_ if:
-
-- _T_ is a parameterized type _G<S<sub>0</sub> ..., S<sub>n</sub>>_, and
- there is a _j_ such that _X_ occurs invariantly in _S<sub>j</sub>_.
-- _T_ is a function type, and _X_ occurs invariantly in the return type
- or a parameter type of _T_, or _X_ occurs anywhere in the bound of a
- formal type parameter of _T_.
-
-*Note that the notion of occurring invariantly differs from that of many
-other languages, where it simply means occurring covariantly as well as
-contravariantly somewhere in the same type. In Dart, a type variable occurs
-invariantly if and only if it occurs in the bound of a formal type
-parameter of a function type, anywhere in the given type. The situation
-where a given type variable occurs both covariantly and contravariantly
-differs from this situation, and there is no separate name for that in
-Dart; if it is of interest it must be spelled out as we just did here.*
-
-*As mentioned, variance gives a characterization of the way a type varies
-as the value of a type variable therein varies: Assume that _T_ is a type
-where a type variable _X_ occurs, and and _L_ and _U_ are types such that
-_L <: U_. If _X_ occurs covariantly in _T_, but not contravariantly and not
-invariantly, then _[L/X]T <: [U/X]T_. Similarly, if _X_ occurs
-contravariantly in _T_, but not covariantly and not invariantly, then
-_[U/X]T <: [L/X]T_. If _X_ occurs both covariantly and contravariantly, or
-it occurs invariantly (at all), then _[L/X]T_ and _[U/X]T_ are not
-guaranteed to be subtypes of each other in any direction. In short: with
-covariance, the type covaries; with contravariance, the type contravaries;
-with invariance, all bets are off.*
+ones that are covariant by modifier. To do that, we also need to refer to
+the variance of each occurrence of a type variable in a type, which is
+specified in the language specification.*
Consider a class _T_ which is generic or has a generic supertype (directly
or indirectly). Let _S_ be said generic class. Assume that there is a
@@ -512,6 +466,11 @@
## Updates
+* Jun 1st 2018, version 0.6: Removed specification of variance, for which
+ the normative text is now part of the language specification. Adjusted
+ the wording to fit the slightly different definitions of variance given
+ there. The meaning of this feature specification has not changed.
+
* Feb 1st 2018, version 0.5: Added specification of override checks for
parameters which are covariant from class.
diff --git a/docs/language/informal/generic-method-syntax.md b/docs/language/informal/generic-method-syntax.md
index f7ddc3e..b2b20a2 100644
--- a/docs/language/informal/generic-method-syntax.md
+++ b/docs/language/informal/generic-method-syntax.md
@@ -2,10 +2,9 @@
**Author**: eernst@
-**Status**: Integrated into (and subsumed by) updates to the language
-specification as of
+**Status**: Background material.
+The normative text on this topic is part of the language specification as of
[`673d5f0`](https://github.com/dart-lang/sdk/commit/673d5f0a665085153d25f8c39495eacdb010ca64).
-This document is now background material.
**This document** is an informal specification of the support in Dart 1.x
for generic methods and functions which includes syntax and name
diff --git a/docs/language/informal/super-bounded-types.md b/docs/language/informal/super-bounded-types.md
index b7d19da..cfcb996 100644
--- a/docs/language/informal/super-bounded-types.md
+++ b/docs/language/informal/super-bounded-types.md
@@ -2,9 +2,10 @@
**Author**: eernst@.
-**Version**: 0.6 (2018-05-25).
+**Version**: 0.7 (2018-06-01).
-**Status**: Under implementation.
+**Status**: Background material.
+The language specification has the normative text on this topic.
**This document** is an informal specification of the support in Dart 2 for
using certain generic types where the declared bounds are violated. The
@@ -580,6 +581,10 @@
## Updates
+* Version 0.7 (2018-06-01), marked as background material: The normative
+ text on variance and on super-bounded types is now part of the language
+ specification.
+
* Version 0.6 (2018-05-25), added example showing why we must check the
right hand side of type aliases.
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 3e2656a..dd02b95 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -109,7 +109,7 @@
<body>
<h1>Analysis Server API Specification</h1>
<h1 style="color:#999999">Version
- 1.20.3
+ 1.20.4
</h1>
<p>
This document contains a specification of the API provided by the
@@ -3309,7 +3309,7 @@
An enumeration of the kinds of folding regions.
</p>
- <dl><dt class="value">ANNOTATIONS</dt><dt class="value">CLASS_BODY</dt><dt class="value">DIRECTIVES</dt><dt class="value">DOCUMENTATION_COMMENT</dt><dt class="value">FILE_HEADER</dt><dt class="value">FUNCTION_BODY</dt></dl></dd><dt class="typeDefinition"><a name="type_FoldingRegion">FoldingRegion: object</a></dt><dd>
+ <dl><dt class="value">ANNOTATIONS</dt><dt class="value">CLASS_BODY</dt><dt class="value">DIRECTIVES</dt><dt class="value">DOCUMENTATION_COMMENT</dt><dt class="value">FILE_HEADER</dt><dt class="value">FUNCTION_BODY</dt><dt class="value">INVOCATION</dt><dt class="value">LITERAL</dt></dl></dd><dt class="typeDefinition"><a name="type_FoldingRegion">FoldingRegion: object</a></dt><dd>
<p>
A description of a region that can be folded.
</p>
diff --git a/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart b/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart
index e5b0f1f56..fc19967 100644
--- a/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart
+++ b/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart
@@ -52,6 +52,8 @@
abstract class DartFixContributor implements FixContributor {
@override
Future<List<Fix>> computeFixes(FixContext context) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AnalysisDriver driver = context.analysisDriver;
Source source = context.error.source;
if (!AnalysisEngine.isDartFileName(source.fullName)) {
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index ded8e70..eb9db41 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -40,6 +40,7 @@
import 'package:analysis_server/src/search/search_domain.dart';
import 'package:analysis_server/src/server/diagnostic_server.dart';
import 'package:analysis_server/src/services/correction/namespace.dart';
+import 'package:analysis_server/src/services/search/element_visitors.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analysis_server/src/services/search/search_engine_internal.dart';
import 'package:analysis_server/src/utilities/null_string_sink.dart';
@@ -656,6 +657,25 @@
* [offset] or the node does not have an element.
*/
Future<Element> getElementAtOffset(String file, int offset) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
+ if (!priorityFiles.contains(file)) {
+ var driver = await getAnalysisDriver(file);
+ if (driver == null) {
+ return null;
+ }
+
+ var unitElementResult = await driver.getUnitElement(file);
+ if (unitElementResult == null) {
+ return null;
+ }
+
+ var element = findElementByNameOffset(unitElementResult.element, offset);
+ if (element != null) {
+ return element;
+ }
+ }
+
AstNode node = await getNodeAtOffset(file, offset);
return getElementOfNode(node);
}
@@ -690,6 +710,8 @@
* the [offset].
*/
Future<AstNode> getNodeAtOffset(String file, int offset) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
nd.AnalysisResult result = await getAnalysisResult(file);
CompilationUnit unit = result?.unit;
if (unit != null) {
@@ -704,6 +726,8 @@
* Dart file or cannot be resolved.
*/
Future<CompilationUnit> getResolvedCompilationUnit(String path) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
nd.AnalysisResult result = await getAnalysisResult(path);
return result?.unit;
}
@@ -975,6 +999,8 @@
}
Future<Null> shutdown() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
running = false;
await options.analytics
@@ -1116,6 +1142,8 @@
}
_scheduleAnalysisImplementedNotification() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
Set<String> files = analysisServices[AnalysisService.IMPLEMENTED];
if (files != null) {
scheduleImplementedNotification(this, files);
diff --git a/pkg/analysis_server/lib/src/channel/byte_stream_channel.dart b/pkg/analysis_server/lib/src/channel/byte_stream_channel.dart
index 72e7cfb..8bdb5d5 100644
--- a/pkg/analysis_server/lib/src/channel/byte_stream_channel.dart
+++ b/pkg/analysis_server/lib/src/channel/byte_stream_channel.dart
@@ -50,6 +50,8 @@
@override
Future<Response> sendRequest(Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String id = request.id;
output.write(json.encode(request.toJson()) + '\n');
return await responseStream
diff --git a/pkg/analysis_server/lib/src/computer/computer_folding.dart b/pkg/analysis_server/lib/src/computer/computer_folding.dart
index ee82362..1a5a5c3 100644
--- a/pkg/analysis_server/lib/src/computer/computer_folding.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_folding.dart
@@ -158,24 +158,59 @@
}
@override
+ Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+ _computer._addRegion(node.argumentList.leftParenthesis.end,
+ node.argumentList.rightParenthesis.offset, FoldingKind.INVOCATION);
+ return super.visitFunctionExpressionInvocation(node);
+ }
+
+ @override
visitImportDirective(ImportDirective node) {
_computer._recordDirective(node);
return super.visitImportDirective(node);
}
@override
+ Object visitInstanceCreationExpression(InstanceCreationExpression node) {
+ _computer._addRegion(node.argumentList.leftParenthesis.end,
+ node.argumentList.rightParenthesis.offset, FoldingKind.INVOCATION);
+ return super.visitInstanceCreationExpression(node);
+ }
+
+ @override
Object visitLibraryDirective(LibraryDirective node) {
_computer._recordDirective(node);
return super.visitLibraryDirective(node);
}
@override
+ Object visitListLiteral(ListLiteral node) {
+ _computer._addRegion(
+ node.leftBracket.end, node.rightBracket.offset, FoldingKind.LITERAL);
+ return super.visitListLiteral(node);
+ }
+
+ @override
+ Object visitMapLiteral(MapLiteral node) {
+ _computer._addRegion(
+ node.leftBracket.end, node.rightBracket.offset, FoldingKind.LITERAL);
+ return super.visitMapLiteral(node);
+ }
+
+ @override
Object visitMethodDeclaration(MethodDeclaration node) {
_computer._addRegionForAnnotations(node.metadata);
return super.visitMethodDeclaration(node);
}
@override
+ Object visitMethodInvocation(MethodInvocation node) {
+ _computer._addRegion(node.argumentList.leftParenthesis.end,
+ node.argumentList.rightParenthesis.offset, FoldingKind.INVOCATION);
+ return super.visitMethodInvocation(node);
+ }
+
+ @override
Object visitPartDirective(PartDirective node) {
_computer._recordDirective(node);
return super.visitPartDirective(node);
diff --git a/pkg/analysis_server/lib/src/computer/import_elements_computer.dart b/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
index c1be612..292b748 100644
--- a/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
+++ b/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
@@ -6,6 +6,7 @@
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/analysis/uri_converter.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/ast_factory.dart';
import 'package:analyzer/dart/ast/token.dart';
@@ -50,10 +51,12 @@
*/
Future<SourceChange> createEdits(
List<ImportedElements> importedElementsList) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<ImportedElements> filteredImportedElements =
_filterImportedElements(importedElementsList);
LibraryElement libraryElement = libraryResult.libraryElement;
- SourceFactory sourceFactory = libraryResult.session.sourceFactory;
+ UriConverter uriConverter = libraryResult.session.uriConverter;
List<ImportDirective> existingImports = <ImportDirective>[];
for (var directive in libraryResult.unit.directives) {
if (directive is ImportDirective) {
@@ -73,7 +76,7 @@
// so we need to add an import.
//
File importedFile = resourceProvider.getFile(importedElements.path);
- Uri uri = sourceFactory.restoreUri(importedFile.createSource());
+ Uri uri = uriConverter.pathToUri(importedFile.path);
Source importedSource = importedFile.createSource(uri);
String importUri =
_getLibrarySourceUri(libraryElement, importedSource);
diff --git a/pkg/analysis_server/lib/src/domain_abstract.dart b/pkg/analysis_server/lib/src/domain_abstract.dart
index 65a2dd4..3c01cbf 100644
--- a/pkg/analysis_server/lib/src/domain_abstract.dart
+++ b/pkg/analysis_server/lib/src/domain_abstract.dart
@@ -42,6 +42,8 @@
Map<PluginInfo, Future<plugin.Response>> futures,
{plugin.RequestParams requestParameters,
int timeout: 500}) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// TODO(brianwilkerson) requestParameters might need to be required.
int endTime = new DateTime.now().millisecondsSinceEpoch + timeout;
List<plugin.Response> responses = <plugin.Response>[];
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index b586b41..a5d5199 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -45,6 +45,8 @@
* Implement the `analysis.getErrors` request.
*/
Future<Null> getErrors(Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String file = new AnalysisGetErrorsParams.fromRequest(request).file;
void send(engine.AnalysisOptions analysisOptions, LineInfo lineInfo,
@@ -77,6 +79,8 @@
* Implement the `analysis.getHover` request.
*/
Future<Null> getHover(Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var params = new AnalysisGetHoverParams.fromRequest(request);
// Prepare the resolved units.
@@ -102,6 +106,8 @@
* Implement the `analysis.getImportedElements` request.
*/
Future<Null> getImportedElements(Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AnalysisGetImportedElementsParams params =
new AnalysisGetImportedElementsParams.fromRequest(request);
//
@@ -158,6 +164,8 @@
* Implement the `analysis.getNavigation` request.
*/
Future<Null> getNavigation(Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var params = new AnalysisGetNavigationParams.fromRequest(request);
String file = params.file;
int offset = params.offset;
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 97d4ec5..6a4a0ff 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -72,6 +72,8 @@
*/
Future<CompletionResult> computeSuggestions(CompletionRequestImpl request,
CompletionGetSuggestionsParams params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
//
// Allow plugins to start computing fixes.
//
@@ -166,6 +168,8 @@
* Process a `completion.getSuggestions` request.
*/
Future<Null> processRequest(Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
performance = new CompletionPerformance();
// extract and validate params
diff --git a/pkg/analysis_server/lib/src/domain_diagnostic.dart b/pkg/analysis_server/lib/src/domain_diagnostic.dart
index 81bff6b..6c03067 100644
--- a/pkg/analysis_server/lib/src/domain_diagnostic.dart
+++ b/pkg/analysis_server/lib/src/domain_diagnostic.dart
@@ -38,6 +38,8 @@
/// Answer the `diagnostic.getServerPort` request.
Future handleGetServerPort(Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
try {
// Open a port (or return the existing one).
int port = await server.diagnosticServer.getServerPort();
diff --git a/pkg/analysis_server/lib/src/domain_execution.dart b/pkg/analysis_server/lib/src/domain_execution.dart
index 16c23fb..a1ed194 100644
--- a/pkg/analysis_server/lib/src/domain_execution.dart
+++ b/pkg/analysis_server/lib/src/domain_execution.dart
@@ -63,6 +63,8 @@
* Implement the 'execution.getSuggestions' request.
*/
void getSuggestions(Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var params = new ExecutionGetSuggestionsParams.fromRequest(request);
var computer = new RuntimeCompletionComputer(
server.resourceProvider,
diff --git a/pkg/analysis_server/lib/src/domain_kythe.dart b/pkg/analysis_server/lib/src/domain_kythe.dart
index 895bd82..2529bb1 100644
--- a/pkg/analysis_server/lib/src/domain_kythe.dart
+++ b/pkg/analysis_server/lib/src/domain_kythe.dart
@@ -35,6 +35,8 @@
* Implement the `kythe.getKytheEntries` request.
*/
Future<Null> getKytheEntries(Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String file = new KytheGetKytheEntriesParams.fromRequest(request).file;
AnalysisDriver driver = server.getAnalysisDriver(file);
if (driver == null) {
diff --git a/pkg/analysis_server/lib/src/domain_server.dart b/pkg/analysis_server/lib/src/domain_server.dart
index ccd12bc..1f205bb 100644
--- a/pkg/analysis_server/lib/src/domain_server.dart
+++ b/pkg/analysis_server/lib/src/domain_server.dart
@@ -67,6 +67,8 @@
* Cleanly shutdown the analysis server.
*/
Future<Null> shutdown(Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
await server.shutdown();
Response response = new ServerShutdownResult().toResponse(request.id);
server.sendResponse(response);
diff --git a/pkg/analysis_server/lib/src/domains/analysis/implemented_dart.dart b/pkg/analysis_server/lib/src/domains/analysis/implemented_dart.dart
index 54f9973..cff08c1 100644
--- a/pkg/analysis_server/lib/src/domains/analysis/implemented_dart.dart
+++ b/pkg/analysis_server/lib/src/domains/analysis/implemented_dart.dart
@@ -18,6 +18,8 @@
ImplementedComputer(this.searchEngine, this.unitElement);
compute() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
for (ClassElement type in unitElement.types) {
// Always include Object and its members.
if (type.supertype == null) {
diff --git a/pkg/analysis_server/lib/src/domains/execution/completion.dart b/pkg/analysis_server/lib/src/domains/execution/completion.dart
index 9a4e0b3..c3a218e 100644
--- a/pkg/analysis_server/lib/src/domains/execution/completion.dart
+++ b/pkg/analysis_server/lib/src/domains/execution/completion.dart
@@ -46,6 +46,8 @@
this.expressions);
Future<RuntimeCompletionResult> compute() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var contextResult = await analysisDriver.getResult(contextFile);
var session = contextResult.session;
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index 1fd145f..2857e67 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -148,6 +148,8 @@
}
Future getAssists(Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
EditGetAssistsParams params = new EditGetAssistsParams.fromRequest(request);
String file = params.file;
int offset = params.offset;
@@ -210,6 +212,8 @@
}
Future getFixes(Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
EditGetFixesParams params = new EditGetFixesParams.fromRequest(request);
String file = params.file;
int offset = params.offset;
@@ -257,6 +261,8 @@
}
Future getPostfixCompletion(Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
server.options.analytics?.sendEvent('edit', 'getPostfixCompletion');
var params = new EditGetPostfixCompletionParams.fromRequest(request);
@@ -293,6 +299,8 @@
}
Future getStatementCompletion(Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var params = new EditGetStatementCompletionParams.fromRequest(request);
SourceChange change;
@@ -373,6 +381,8 @@
* Implement the `edit.importElements` request.
*/
Future<Null> importElements(Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
EditImportElementsParams params =
new EditImportElementsParams.fromRequest(request);
//
@@ -406,6 +416,8 @@
}
Future isPostfixCompletionApplicable(Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var params = new EditGetPostfixCompletionParams.fromRequest(request);
bool value = false;
@@ -436,6 +448,8 @@
}
Future listPostfixCompletionTemplates(Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var templates = DartPostfixCompletion.ALL_TEMPLATES
.map((pfc) =>
new PostfixTemplateDescriptor(pfc.name, pfc.key, pfc.example))
@@ -447,6 +461,8 @@
}
Future<Null> organizeDirectives(Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
server.options.analytics?.sendEvent('edit', 'organizeDirectives');
var params = new EditOrganizeDirectivesParams.fromRequest(request);
@@ -482,6 +498,8 @@
}
Future<Null> sortMembers(Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var params = new EditSortMembersParams.fromRequest(request);
// prepare file
String file = params.file;
@@ -520,6 +538,8 @@
*/
Future<List<AnalysisErrorFixes>> _computeServerErrorFixes(
AnalysisDriver driver, String file, int offset) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<AnalysisErrorFixes> errorFixesList = <AnalysisErrorFixes>[];
AnalysisResult result = await server.getAnalysisResult(file);
if (result != null) {
@@ -562,6 +582,8 @@
}
Future _getAvailableRefactoringsImpl(Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// prepare parameters
var params = new EditGetAvailableRefactoringsParams.fromRequest(request);
String file = params.file;
@@ -786,6 +808,8 @@
}
runZoned(() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
await _init(params.kind, params.file, params.offset, params.length);
if (initStatus.hasFatalError) {
feedback = null;
@@ -876,6 +900,8 @@
*/
Future _init(
RefactoringKind kind, String file, int offset, int length) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// check if we can continue with the existing Refactoring instance
if (this.kind == kind &&
this.file == file &&
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_correction.dart b/pkg/analysis_server/lib/src/flutter/flutter_correction.dart
index 3791140..459baf7 100644
--- a/pkg/analysis_server/lib/src/flutter/flutter_correction.dart
+++ b/pkg/analysis_server/lib/src/flutter/flutter_correction.dart
@@ -53,6 +53,8 @@
String get eol => utils.endOfLine;
Future<SourceChange> addForDesignTimeConstructor() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
final node = this.node;
if (node is ClassDeclaration) {
var className = node.name.name;
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_domain.dart b/pkg/analysis_server/lib/src/flutter/flutter_domain.dart
index 5c5470a3..45698c4 100644
--- a/pkg/analysis_server/lib/src/flutter/flutter_domain.dart
+++ b/pkg/analysis_server/lib/src/flutter/flutter_domain.dart
@@ -21,6 +21,39 @@
*/
FlutterDomainHandler(AnalysisServer server) : super(server);
+ /**
+ * Implement the 'flutter.getChangeAddForDesignTimeConstructor' request.
+ */
+ Future getChangeAddForDesignTimeConstructor(Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
+ var params =
+ new FlutterGetChangeAddForDesignTimeConstructorParams.fromRequest(
+ request);
+ String file = params.file;
+ int offset = params.offset;
+
+ ResolveResult result = await server.getAnalysisResult(file);
+ if (result != null) {
+ var corrections = new FlutterCorrections(
+ file: file,
+ fileContent: result.content,
+ selectionOffset: offset,
+ selectionLength: 0,
+ session: result.session,
+ unit: result.unit);
+ SourceChange change = await corrections.addForDesignTimeConstructor();
+ if (change != null) {
+ server.sendResponse(
+ new FlutterGetChangeAddForDesignTimeConstructorResult(change)
+ .toResponse(request.id));
+ return;
+ }
+ }
+ server.sendResponse(
+ new Response.invalidParameter(request, 'file', 'No change'));
+ }
+
@override
Response handleRequest(Request request) {
try {
@@ -49,35 +82,4 @@
server.setFlutterSubscriptions(subMap);
return new FlutterSetSubscriptionsResult().toResponse(request.id);
}
-
- /**
- * Implement the 'flutter.getChangeAddForDesignTimeConstructor' request.
- */
- Future getChangeAddForDesignTimeConstructor(Request request) async {
- var params =
- new FlutterGetChangeAddForDesignTimeConstructorParams.fromRequest(
- request);
- String file = params.file;
- int offset = params.offset;
-
- ResolveResult result = await server.getAnalysisResult(file);
- if (result != null) {
- var corrections = new FlutterCorrections(
- file: file,
- fileContent: result.content,
- selectionOffset: offset,
- selectionLength: 0,
- session: result.session,
- unit: result.unit);
- SourceChange change = await corrections.addForDesignTimeConstructor();
- if (change != null) {
- server.sendResponse(
- new FlutterGetChangeAddForDesignTimeConstructorResult(change)
- .toResponse(request.id));
- return;
- }
- }
- server.sendResponse(
- new Response.invalidParameter(request, 'file', 'No change'));
- }
}
diff --git a/pkg/analysis_server/lib/src/operation/operation_analysis.dart b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
index 24a4811..1ec5d31 100644
--- a/pkg/analysis_server/lib/src/operation/operation_analysis.dart
+++ b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
@@ -20,6 +20,8 @@
Future<Null> scheduleImplementedNotification(
AnalysisServer server, Iterable<String> files) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
SearchEngine searchEngine = server.searchEngine;
if (searchEngine == null) {
return;
@@ -81,15 +83,6 @@
});
}
-void sendAnalysisNotificationFolding(AnalysisServer server, String file,
- LineInfo lineInfo, CompilationUnit dartUnit) {
- _sendNotification(server, () {
- var regions = new DartUnitFoldingComputer(lineInfo, dartUnit).compute();
- var params = new protocol.AnalysisFoldingParams(file, regions);
- server.sendNotification(params.toNotification());
- });
-}
-
void sendAnalysisNotificationFlushResults(
AnalysisServer server, List<String> files) {
_sendNotification(server, () {
@@ -100,6 +93,15 @@
});
}
+void sendAnalysisNotificationFolding(AnalysisServer server, String file,
+ LineInfo lineInfo, CompilationUnit dartUnit) {
+ _sendNotification(server, () {
+ var regions = new DartUnitFoldingComputer(lineInfo, dartUnit).compute();
+ var params = new protocol.AnalysisFoldingParams(file, regions);
+ server.sendNotification(params.toNotification());
+ });
+}
+
void sendAnalysisNotificationHighlights(
AnalysisServer server, String file, CompilationUnit dartUnit) {
_sendNotification(server, () {
diff --git a/pkg/analysis_server/lib/src/plugin/plugin_manager.dart b/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
index 4686b23..13e4b5f 100644
--- a/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
+++ b/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
@@ -246,6 +246,8 @@
* used to interact with the plugin, or `null` if the plugin could not be run.
*/
Future<PluginSession> start(String byteStorePath, String sdkPath) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (currentSession != null) {
throw new StateError('Cannot start a plugin that is already running.');
}
@@ -378,6 +380,8 @@
*/
Future<Null> addPluginToContextRoot(
analyzer.ContextRoot contextRoot, String path) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
PluginInfo plugin = _pluginMap[path];
bool isNew = plugin == null;
if (isNew) {
@@ -447,6 +451,8 @@
*/
Future<List<Future<Response>>> broadcastWatchEvent(
watcher.WatchEvent watchEvent) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String filePath = watchEvent.path;
/**
@@ -572,6 +578,8 @@
* Restart all currently running plugins.
*/
Future<Null> restartPlugins() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
for (PluginInfo plugin in _pluginMap.values.toList()) {
if (plugin.currentSession != null) {
//
@@ -1044,6 +1052,8 @@
* running.
*/
Future<bool> start(String byteStorePath, String sdkPath) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (channel != null) {
throw new StateError('Cannot start a plugin that is already running.');
}
diff --git a/pkg/analysis_server/lib/src/search/element_references.dart b/pkg/analysis_server/lib/src/search/element_references.dart
index fc60fb9..79f3714f 100644
--- a/pkg/analysis_server/lib/src/search/element_references.dart
+++ b/pkg/analysis_server/lib/src/search/element_references.dart
@@ -23,6 +23,8 @@
*/
Future<List<SearchResult>> compute(
Element element, bool withPotential) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<SearchResult> results = <SearchResult>[];
// Add element references.
@@ -45,6 +47,8 @@
* to the corresponding hierarchy [Element]s.
*/
Future<List<SearchResult>> _findElementsReferences(Element element) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<SearchResult> allResults = <SearchResult>[];
Iterable<Element> refElements = await _getRefElements(element);
for (Element refElement in refElements) {
@@ -60,6 +64,8 @@
*/
Future<List<SearchResult>> _findSingleElementReferences(
Element element) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<SearchMatch> matches = await searchEngine.searchReferences(element);
matches = SearchMatch.withNotNullElement(matches);
return matches.map(toResult).toList();
diff --git a/pkg/analysis_server/lib/src/search/search_domain.dart b/pkg/analysis_server/lib/src/search/search_domain.dart
index ab94d11..805344d 100644
--- a/pkg/analysis_server/lib/src/search/search_domain.dart
+++ b/pkg/analysis_server/lib/src/search/search_domain.dart
@@ -42,6 +42,8 @@
searchEngine = server.searchEngine;
Future findElementReferences(protocol.Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var params =
new protocol.SearchFindElementReferencesParams.fromRequest(request);
String file = params.file;
@@ -74,6 +76,8 @@
}
Future findMemberDeclarations(protocol.Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var params =
new protocol.SearchFindMemberDeclarationsParams.fromRequest(request);
await server.onAnalysisComplete;
@@ -89,6 +93,8 @@
}
Future findMemberReferences(protocol.Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var params =
new protocol.SearchFindMemberReferencesParams.fromRequest(request);
await server.onAnalysisComplete;
@@ -104,6 +110,8 @@
}
Future findTopLevelDeclarations(protocol.Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var params =
new protocol.SearchFindTopLevelDeclarationsParams.fromRequest(request);
try {
@@ -131,6 +139,8 @@
* Implement the `search.getDeclarations` request.
*/
Future getDeclarations(protocol.Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var params =
new protocol.SearchGetElementDeclarationsParams.fromRequest(request);
@@ -218,6 +228,8 @@
* Implement the `search.getTypeHierarchy` request.
*/
Future getTypeHierarchy(protocol.Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var params = new protocol.SearchGetTypeHierarchyParams.fromRequest(request);
String file = params.file;
// prepare element
diff --git a/pkg/analysis_server/lib/src/search/type_hierarchy.dart b/pkg/analysis_server/lib/src/search/type_hierarchy.dart
index 841e291..40b71ad 100644
--- a/pkg/analysis_server/lib/src/search/type_hierarchy.dart
+++ b/pkg/analysis_server/lib/src/search/type_hierarchy.dart
@@ -52,6 +52,8 @@
* Returns the computed type hierarchy, maybe `null`.
*/
Future<List<TypeHierarchyItem>> compute() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (_pivotClass != null) {
InterfaceType type = _pivotClass.type;
_createSuperItem(type);
@@ -75,6 +77,8 @@
Future _createSubclasses(
TypeHierarchyItem item, int itemId, InterfaceType type) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
Set<ClassElement> subElements =
await getDirectSubClasses(_searchEngine, type.element);
List<int> subItemIds = <int>[];
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index ac0d78b..af6e262 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -433,6 +433,8 @@
_captureExceptions(instrumentationService, () {
stdioServer.serveStdio().then((_) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (serve_http) {
httpServer.close();
}
diff --git a/pkg/analysis_server/lib/src/server/http_server.dart b/pkg/analysis_server/lib/src/server/http_server.dart
index bcbf428..6acfe4e 100644
--- a/pkg/analysis_server/lib/src/server/http_server.dart
+++ b/pkg/analysis_server/lib/src/server/http_server.dart
@@ -78,7 +78,11 @@
/**
* Return the port this server is bound to.
*/
- Future<int> get boundPort async => (await _serverFuture)?.port;
+ Future<int> get boundPort async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
+ return (await _serverFuture)?.port;
+ }
void close() {
_serverFuture?.then((HttpServer server) {
@@ -101,6 +105,8 @@
* Begin serving HTTP requests over the given port.
*/
Future<int> serveHttp([int initialPort]) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (_serverFuture != null) {
return boundPort;
}
@@ -125,6 +131,8 @@
* Handle a GET request received by the HTTP server.
*/
Future<Null> _handleGetRequest(HttpRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (getHandler == null) {
getHandler = new DiagnosticsSite(socketServer, _printBuffer);
}
@@ -136,6 +144,8 @@
*/
void _handleServer(HttpServer httpServer) {
httpServer.listen((HttpRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<String> updateValues = request.headers[HttpHeaders.UPGRADE];
if (request.method == 'GET') {
await _handleGetRequest(request);
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
index 1291f78..005cc23 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
@@ -179,6 +179,8 @@
@override
Future<List<CompletionSuggestion>> computeSuggestions(
DartCompletionRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
this.request = request;
this.suggestions = <CompletionSuggestion>[];
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/combinator_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/combinator_contributor.dart
index 2914658..3481a82 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/combinator_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/combinator_contributor.dart
@@ -19,6 +19,8 @@
@override
Future<List<CompletionSuggestion>> computeSuggestions(
DartCompletionRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AstNode node = request.target.containingNode;
if (node is! Combinator) {
return EMPTY_LIST;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index 22062cc5..275fbd2 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -56,6 +56,8 @@
@override
Future<List<CompletionSuggestion>> computeSuggestions(
CompletionRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
request.checkAborted();
if (!AnalysisEngine.isDartFileName(request.result.path)) {
return EMPTY_LIST;
@@ -292,6 +294,8 @@
*/
static Future<DartCompletionRequest> from(CompletionRequest request,
{ResultDescriptor resultDescriptor}) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
request.checkAborted();
CompletionPerformance performance =
(request as CompletionRequestImpl).performance;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart
index 94f4318..c3db2af 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart
@@ -18,6 +18,8 @@
@override
Future<List<CompletionSuggestion>> computeSuggestions(
DartCompletionRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AstNode node = request.target.containingNode;
if (node is! FieldFormalParameter) {
return EMPTY_LIST;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
index e182fdf..9c2a7e8 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
@@ -41,6 +41,8 @@
@override
Future<List<CompletionSuggestion>> computeSuggestions(
DartCompletionRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (!request.includeIdentifiers) {
return EMPTY_LIST;
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart
index 63d624c..95d2650 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/inherited_reference_contributor.dart
@@ -57,6 +57,8 @@
@override
Future<List<CompletionSuggestion>> computeSuggestions(
DartCompletionRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (!request.includeIdentifiers) {
return EMPTY_LIST;
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
index baef690..a2ceffb 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
@@ -30,6 +30,8 @@
@override
Future<List<CompletionSuggestion>> computeSuggestions(
DartCompletionRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
// Don't suggest anything right after double or integer literals.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart
index 1e8c520..4dead0e 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart
@@ -24,6 +24,8 @@
@override
Future<List<CompletionSuggestion>> computeSuggestions(
DartCompletionRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
OpType optype = (request as DartCompletionRequestImpl).opType;
// Collect suggestions from the specific child [AstNode] that contains
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
index b7afbbe..a9c9afc 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
@@ -20,6 +20,8 @@
@override
Future<List<CompletionSuggestion>> computeSuggestions(
DartCompletionRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// Determine if the target looks like a library prefix
Expression targetId = request.dotTarget;
if (targetId is SimpleIdentifier && !request.target.isCascade) {
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart
index 9ba62c4..537b7bf 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart
@@ -19,6 +19,8 @@
@override
Future<List<CompletionSuggestion>> computeSuggestions(
DartCompletionRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (!request.includeIdentifiers) {
return EMPTY_LIST;
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart
index ec71bf9..d81e161 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_constructor_contributor.dart
@@ -28,6 +28,8 @@
@override
Future<List<CompletionSuggestion>> computeSuggestions(
DartCompletionRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
OpType optype = (request as DartCompletionRequestImpl).opType;
// Collect suggestions from the specific child [AstNode] that contains
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
index d22c4f5..2098f24 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
@@ -192,6 +192,8 @@
@override
Future<List<CompletionSuggestion>> computeSuggestions(
DartCompletionRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (!request.includeIdentifiers) {
return EMPTY_LIST;
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
index 0205b18..f179469 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
@@ -31,6 +31,8 @@
@override
Future<List<CompletionSuggestion>> computeSuggestions(
DartCompletionRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
OpType optype = (request as DartCompletionRequestImpl).opType;
AstNode node = request.target.containingNode;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart
index 5874ac5..0a80399 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart
@@ -19,6 +19,8 @@
@override
Future<List<CompletionSuggestion>> computeSuggestions(
DartCompletionRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AstNode node = request.target.containingNode;
LibraryElement libElem = request.libraryElement;
if (libElem == null) {
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
index e31866b..d435a04 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
@@ -27,6 +27,8 @@
@override
Future<List<CompletionSuggestion>> computeSuggestions(
DartCompletionRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
SimpleIdentifier targetId = _getTargetId(request.target);
if (targetId == null) {
return EMPTY_LIST;
@@ -69,6 +71,8 @@
SimpleIdentifier targetId,
ExecutableElement element,
StringBuffer displayTextBuffer) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
DartChangeBuilder builder =
new DartChangeBuilder(result.driver.currentSession);
await builder.addFileEdit(result.path, (DartFileEditBuilder builder) {
@@ -86,6 +90,8 @@
*/
Future<CompletionSuggestion> _buildSuggestion(DartCompletionRequest request,
SimpleIdentifier targetId, ExecutableElement element) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
StringBuffer displayTextBuffer = new StringBuffer();
DartChangeBuilder builder = await _buildReplacementText(
request.result, targetId, element, displayTextBuffer);
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
index 593de24..d06eab9 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
@@ -20,6 +20,8 @@
@override
Future<List<CompletionSuggestion>> computeSuggestions(
DartCompletionRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
Expression targetId = request.dotTarget;
if (targetId is Identifier && !request.target.isCascade) {
Element elem = targetId.bestElement;
@@ -63,11 +65,6 @@
}
@override
- visitElement(Element element) {
- // ignored
- }
-
- @override
visitConstructorElement(ConstructorElement element) {
if (element.context.analysisOptions.previewDart2) {
_addSuggestion(element);
@@ -75,6 +72,11 @@
}
@override
+ visitElement(Element element) {
+ // ignored
+ }
+
+ @override
visitFieldElement(FieldElement element) {
if (element.isStatic) {
_addSuggestion(element);
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
index e49bdab..d1acf19 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
@@ -22,6 +22,8 @@
@override
Future<List<CompletionSuggestion>> computeSuggestions(
DartCompletionRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
LibraryElement containingLibrary = request.libraryElement;
// Gracefully degrade if the library element is not resolved
// e.g. detached part file or source change
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/uri_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/uri_contributor.dart
index de77d4c..6226346 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/uri_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/uri_contributor.dart
@@ -20,8 +20,6 @@
* A contributor for calculating uri suggestions for import and part directives.
*/
class UriContributor extends DartCompletionContributor {
- _UriSuggestionBuilder builder;
-
/**
* A flag indicating whether file: and package: URI suggestions should
* be included in the list of completion suggestions.
@@ -31,9 +29,13 @@
// to only those paths within context roots.
static bool suggestFilePaths = true;
+ _UriSuggestionBuilder builder;
+
@override
Future<List<CompletionSuggestion>> computeSuggestions(
DartCompletionRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
builder = new _UriSuggestionBuilder(request);
request.target.containingNode.accept(builder);
return builder.suggestions;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart
index 92a8389..44790b9 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart
@@ -40,6 +40,8 @@
@override
Future<List<CompletionSuggestion>> computeSuggestions(
DartCompletionRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
OpType optype = (request as DartCompletionRequestImpl).opType;
// Collect suggestions from the specific child [AstNode] that contains
diff --git a/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart b/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
index 704ffdb..32f0504 100644
--- a/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
+++ b/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
@@ -76,6 +76,8 @@
static Future<PostfixCompletion> expandAssert(
PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return processor.expand(kind, processor.findAssertExpression, (expr) {
return "assert(${processor.utils.getNodeText(expr)});";
}, withBraces: false);
@@ -83,12 +85,16 @@
static Future<PostfixCompletion> expandElse(
PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return processor.expand(kind, processor.findBoolExpression,
(expr) => "if (${processor.makeNegatedBoolExpr(expr)})");
}
static Future<PostfixCompletion> expandFor(
PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return processor.expand(kind, processor.findIterableExpression, (expr) {
String value = processor.newVariable("value");
return "for (var $value in ${processor.utils.getNodeText(expr)})";
@@ -97,6 +103,8 @@
static Future<PostfixCompletion> expandFori(
PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return processor.expand(kind, processor.findIntExpression, (expr) {
String index = processor.newVariable("i");
return "for (int $index = 0; $index < ${processor.utils.getNodeText(
@@ -106,12 +114,16 @@
static Future<PostfixCompletion> expandIf(
PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return processor.expand(kind, processor.findBoolExpression,
(expr) => "if (${processor.utils.getNodeText(expr)})");
}
static Future<PostfixCompletion> expandNegate(
PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return processor.expand(kind, processor.findBoolExpression,
(expr) => processor.makeNegatedBoolExpr(expr),
withBraces: false);
@@ -119,6 +131,8 @@
static Future<PostfixCompletion> expandNotNull(
PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return processor.expand(kind, processor.findObjectExpression, (expr) {
return expr is NullLiteral
? "if (false)"
@@ -128,6 +142,8 @@
static Future<PostfixCompletion> expandNull(
PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return processor.expand(kind, processor.findObjectExpression, (expr) {
return expr is NullLiteral
? "if (true)"
@@ -137,6 +153,8 @@
static Future<PostfixCompletion> expandParen(
PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return processor.expand(kind, processor.findObjectExpression,
(expr) => "(${processor.utils.getNodeText(expr)})",
withBraces: false);
@@ -144,6 +162,8 @@
static Future<PostfixCompletion> expandReturn(
PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return processor.expand(kind, processor.findObjectExpression,
(expr) => "return ${processor.utils.getNodeText(expr)};",
withBraces: false);
@@ -151,22 +171,30 @@
static Future<PostfixCompletion> expandSwitch(
PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return processor.expand(kind, processor.findObjectExpression,
(expr) => "switch (${processor.utils.getNodeText(expr)})");
}
static Future<PostfixCompletion> expandTry(
PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return processor.expandTry(kind, processor.findStatement, withOn: false);
}
static Future<PostfixCompletion> expandTryon(
PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return processor.expandTry(kind, processor.findStatement, withOn: true);
}
static Future<PostfixCompletion> expandWhile(
PostfixCompletionProcessor processor, PostfixCompletionKind kind) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return processor.expand(kind, processor.findBoolExpression,
(expr) => "while (${processor.utils.getNodeText(expr)})");
}
@@ -320,6 +348,8 @@
CompilationUnitElement get unitElement => completionContext.unitElement;
Future<PostfixCompletion> compute() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
node = _selectedNode();
if (node == null) {
return NO_COMPLETION;
@@ -331,6 +361,8 @@
Future<PostfixCompletion> expand(
PostfixCompletionKind kind, Function contexter, Function sourcer,
{bool withBraces: true}) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AstNode expr = contexter();
if (expr == null) {
return null;
@@ -366,6 +398,8 @@
Future<PostfixCompletion> expandTry(
PostfixCompletionKind kind, Function contexter,
{bool withOn: false}) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AstNode stmt = contexter();
if (stmt == null) {
return null;
@@ -470,6 +504,8 @@
}
Future<bool> isApplicable() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
node = _selectedNode();
if (node == null) {
return false;
diff --git a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
index 3c7bdd83..029ed3f 100644
--- a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
+++ b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
@@ -162,6 +162,8 @@
CompilationUnitElement get unitElement => statementContext.unitElement;
Future<StatementCompletion> compute() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
node = _selectedNode();
if (node == null) {
return NO_COMPLETION;
diff --git a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
index 8497b25..8fd931b 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -110,6 +110,8 @@
}
Future<List<Assist>> compute() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
try {
utils = new CorrectionUtils(unit);
} catch (e) {
@@ -219,6 +221,8 @@
}
Future<Null> _addProposal_addTypeAnnotation_DeclaredIdentifier() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
DeclaredIdentifier declaredIdentifier =
node.getAncestor((n) => n is DeclaredIdentifier);
if (declaredIdentifier == null) {
@@ -268,6 +272,8 @@
}
Future<Null> _addProposal_addTypeAnnotation_SimpleFormalParameter() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AstNode node = this.node;
// should be the name of a simple parameter
if (node is! SimpleIdentifier || node.parent is! SimpleFormalParameter) {
@@ -308,6 +314,8 @@
}
Future<Null> _addProposal_addTypeAnnotation_VariableDeclaration() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AstNode node = this.node;
// prepare VariableDeclarationList
VariableDeclarationList declarationList =
@@ -369,6 +377,8 @@
}
Future<Null> _addProposal_assignToLocalVariable() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// prepare enclosing ExpressionStatement
ExpressionStatement expressionStatement;
for (AstNode node = this.node; node != null; node = node.parent) {
@@ -422,6 +432,8 @@
}
Future<Null> _addProposal_convertDocumentationIntoBlock() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
Comment comment = node.getAncestor((n) => n is Comment);
if (comment == null || !comment.isDocumentation) {
return;
@@ -453,6 +465,8 @@
}
Future<Null> _addProposal_convertDocumentationIntoLine() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
Comment comment = node.getAncestor((n) => n is Comment);
if (comment == null ||
!comment.isDocumentation ||
@@ -512,6 +526,8 @@
}
Future<Null> _addProposal_convertIntoFinalField() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// Find the enclosing getter.
MethodDeclaration getter;
for (AstNode n = node; n != null; n = n.parent) {
@@ -581,6 +597,8 @@
}
Future<Null> _addProposal_convertIntoGetter() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// Find the enclosing field declaration.
FieldDeclaration fieldDeclaration;
for (AstNode n = node; n != null; n = n.parent) {
@@ -630,6 +648,8 @@
}
Future<Null> _addProposal_convertPartOfToUri() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
PartOfDirective directive =
node.getAncestor((node) => node is PartOfDirective);
if (directive == null || directive.libraryName == null) {
@@ -648,6 +668,8 @@
}
Future<Null> _addProposal_convertToAsyncFunctionBody() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
FunctionBody body = getEnclosingFunctionBody();
if (body == null || body.isAsynchronous || body.isGenerator) {
_coverageMarker();
@@ -679,6 +701,8 @@
}
Future<Null> _addProposal_convertToBlockFunctionBody() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
FunctionBody body = getEnclosingFunctionBody();
// prepare expression body
if (body is! ExpressionFunctionBody || body.isGenerator) {
@@ -722,10 +746,14 @@
}
Future<Null> _addProposal_convertToDoubleQuotedString() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
await _convertQuotes(false, DartAssistKind.CONVERT_TO_DOUBLE_QUOTED_STRING);
}
Future<Null> _addProposal_convertToExpressionFunctionBody() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// prepare current body
FunctionBody body = getEnclosingFunctionBody();
if (body is! BlockFunctionBody || body.isGenerator) {
@@ -777,6 +805,8 @@
}
Future<Null> _addProposal_convertToFieldParameter() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node == null) {
return;
}
@@ -869,6 +899,8 @@
}
Future<Null> _addProposal_convertToForIndexLoop() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// find enclosing ForEachStatement
ForEachStatement forEachStatement =
node.getAncestor((n) => n is ForEachStatement);
@@ -947,6 +979,8 @@
}
Future<Null> _addProposal_convertToGenericFunctionSyntax() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AstNode node = this.node;
while (node != null) {
if (node is FunctionTypeAlias) {
@@ -965,6 +999,8 @@
}
Future<Null> _addProposal_convertToIsNot_onIs() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// may be child of "is"
AstNode node = this.node;
while (node != null && node is! IsExpression) {
@@ -1016,6 +1052,8 @@
}
Future<Null> _addProposal_convertToIsNot_onNot() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// may be () in prefix expression
if (node is ParenthesizedExpression && node.parent is PrefixExpression) {
node = node.parent;
@@ -1070,6 +1108,8 @@
* Converts "!isEmpty" -> "isNotEmpty" if possible.
*/
Future<Null> _addProposal_convertToIsNotEmpty() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// prepare "expr.isEmpty"
AstNode isEmptyAccess = null;
SimpleIdentifier isEmptyIdentifier = null;
@@ -1128,6 +1168,8 @@
}
Future<Null> _addProposal_convertToNormalParameter() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is SimpleIdentifier &&
node.parent is FieldFormalParameter &&
node.parent.parent is FormalParameterList &&
@@ -1167,10 +1209,14 @@
}
Future<Null> _addProposal_convertToSingleQuotedString() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
await _convertQuotes(true, DartAssistKind.CONVERT_TO_SINGLE_QUOTED_STRING);
}
Future<Null> _addProposal_encapsulateField() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// find FieldDeclaration
FieldDeclaration fieldDeclaration =
node.getAncestor((x) => x is FieldDeclaration);
@@ -1270,6 +1316,8 @@
}
Future<Null> _addProposal_exchangeOperands() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// check that user invokes quick assist on binary expression
if (node is! BinaryExpression) {
_coverageMarker();
@@ -1325,6 +1373,8 @@
}
Future<Null> _addProposal_flutterConvertToChildren() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// Find "child: widget" under selection.
NamedExpression namedExp;
{
@@ -1354,6 +1404,8 @@
}
Future<Null> _addProposal_flutterConvertToStatefulWidget() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
ClassDeclaration widgetClass =
node.getAncestor((n) => n is ClassDeclaration);
TypeName superclass = widgetClass?.extendsClause?.superclass;
@@ -1428,6 +1480,8 @@
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
builder.addReplacement(range.node(superclass), (builder) {
builder.writeType(statefulWidgetClass.type);
});
@@ -1451,6 +1505,8 @@
}
Future<Null> _addProposal_flutterMoveWidgetDown() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var widget = flutter.identifyWidgetExpression(node);
if (widget == null) {
return;
@@ -1483,6 +1539,8 @@
}
Future<Null> _addProposal_flutterMoveWidgetUp() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var widget = flutter.identifyWidgetExpression(node);
if (widget == null) {
return;
@@ -1514,6 +1572,8 @@
}
Future<Null> _addProposal_flutterRemoveWidget_multipleChildren() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var widgetCreation = flutter.identifyNewExpression(node);
if (widgetCreation == null) {
return;
@@ -1552,6 +1612,8 @@
}
Future<Null> _addProposal_flutterRemoveWidget_singleChild() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var widgetCreation = flutter.identifyNewExpression(node);
if (widgetCreation == null) {
return;
@@ -1577,6 +1639,8 @@
}
Future<Null> _addProposal_flutterSwapWithChild() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
InstanceCreationExpression parent = flutter.identifyNewExpression(node);
if (!flutter.isWidgetCreation(parent)) {
_coverageMarker();
@@ -1596,6 +1660,8 @@
}
Future<Null> _addProposal_flutterSwapWithParent() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
InstanceCreationExpression child = flutter.identifyNewExpression(node);
if (!flutter.isWidgetCreation(child)) {
_coverageMarker();
@@ -1615,6 +1681,8 @@
}
Future<Null> _addProposal_flutterWrapWidget() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
await _addProposal_flutterWrapWidgetImpl();
await _addProposal_flutterWrapWidgetImpl(
kind: DartAssistKind.FLUTTER_WRAP_CENTER,
@@ -1639,6 +1707,8 @@
String parentLibraryUri,
String parentClassName,
List<String> leadingLines: const []}) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
Expression widgetExpr = flutter.identifyWidgetExpression(node);
if (widgetExpr == null) {
_coverageMarker();
@@ -1702,6 +1772,8 @@
}
Future<Null> _addProposal_flutterWrapWidgets() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var selectionRange = new SourceRange(selectionOffset, selectionLength);
var analyzer = new SelectionAnalyzer(selectionRange);
unit.accept(analyzer);
@@ -1733,6 +1805,8 @@
{@required AssistKind kind,
@required String parentLibraryUri,
@required String parentClassName}) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
ClassElement parentClassElement =
await sessionHelper.getClass(parentLibraryUri, parentClassName);
ClassElement widgetClassElement =
@@ -1790,6 +1864,8 @@
}
Future<Null> _addProposal_importAddShow() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// prepare ImportDirective
ImportDirective importDirective =
node.getAncestor((node) => node is ImportDirective);
@@ -1833,6 +1909,8 @@
}
Future<Null> _addProposal_introduceLocalTestedType() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AstNode node = this.node;
if (node is IfStatement) {
node = (node as IfStatement).condition;
@@ -1904,6 +1982,8 @@
}
Future<Null> _addProposal_invertIf() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is! IfStatement) {
return;
}
@@ -1930,6 +2010,8 @@
}
Future<Null> _addProposal_joinIfStatementInner() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// climb up condition to the (supposedly) "if" statement
AstNode node = this.node;
while (node is Expression) {
@@ -1990,6 +2072,8 @@
}
Future<Null> _addProposal_joinIfStatementOuter() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// climb up condition to the (supposedly) "if" statement
AstNode node = this.node;
while (node is Expression) {
@@ -2054,6 +2138,8 @@
}
Future<Null> _addProposal_joinVariableDeclaration_onAssignment() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// check that node is LHS in assignment
if (node is SimpleIdentifier &&
node.parent is AssignmentExpression &&
@@ -2129,6 +2215,8 @@
}
Future<Null> _addProposal_joinVariableDeclaration_onDeclaration() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// prepare enclosing VariableDeclarationList
VariableDeclarationList declList =
node.getAncestor((node) => node is VariableDeclarationList);
@@ -2197,6 +2285,8 @@
}
Future<Null> _addProposal_removeTypeAnnotation() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
VariableDeclarationList declarationList =
node.getAncestor((n) => n is VariableDeclarationList);
if (declarationList == null) {
@@ -2241,6 +2331,8 @@
}
Future<Null> _addProposal_reparentFlutterList() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is! ListLiteral) {
return;
}
@@ -2288,6 +2380,8 @@
}
Future<Null> _addProposal_replaceConditionalWithIfElse() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
ConditionalExpression conditional = null;
// may be on Statement with Conditional
Statement statement = node.getAncestor((node) => node is Statement);
@@ -2392,6 +2486,8 @@
}
Future<Null> _addProposal_replaceIfElseWithConditional() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// should be "if"
if (node is! IfStatement) {
_coverageMarker();
@@ -2458,6 +2554,8 @@
}
Future<Null> _addProposal_splitAndCondition() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// check that user invokes quick assist on binary expression
if (node is! BinaryExpression) {
_coverageMarker();
@@ -2549,6 +2647,8 @@
}
Future<Null> _addProposal_splitVariableDeclaration() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// prepare DartVariableStatement, should be part of Block
VariableDeclarationStatement statement =
node.getAncestor((node) => node is VariableDeclarationStatement);
@@ -2587,6 +2687,8 @@
}
Future<Null> _addProposal_surroundWith() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// prepare selected statements
List<Statement> selectedStatements;
{
@@ -2872,6 +2974,8 @@
Future<Null> _convertFunctionTypeAliasToGenericTypeAlias(
FunctionTypeAlias node) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (!_allParametersHaveTypes(node.parameters)) {
return;
}
@@ -2901,6 +3005,8 @@
Future<Null> _convertFunctionTypedFormalParameterToSimpleFormalParameter(
FunctionTypedFormalParameter node) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (!_allParametersHaveTypes(node.parameters)) {
return;
}
@@ -2927,6 +3033,8 @@
}
Future<Null> _convertQuotes(bool fromDouble, AssistKind kind) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is SimpleStringLiteral) {
SimpleStringLiteral literal = node;
if (fromDouble ? !literal.isSingleQuoted : literal.isSingleQuoted) {
@@ -2996,6 +3104,8 @@
Future<void> _swapParentAndChild(InstanceCreationExpression parent,
InstanceCreationExpression child, AssistKind kind) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// The child must have its own child.
if (flutter.findChildArgument(child) == null) {
_coverageMarker();
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 26867a4..c47f71a 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -81,6 +81,8 @@
class DefaultFixContributor extends DartFixContributor {
@override
Future<List<Fix>> internalComputeFixes(DartFixContext context) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
try {
FixProcessor processor = new FixProcessor(context);
List<Fix> fixes = await processor.compute();
@@ -93,6 +95,8 @@
Future<List<Fix>> _computeFixAllFixes(
DartFixContext context, List<Fix> fixes) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
final AnalysisError analysisError = context.error;
final List<AnalysisError> allAnalysisErrors = context.errors;
@@ -274,6 +278,8 @@
}
Future<List<Fix>> compute() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
try {
utils = new CorrectionUtils(unit);
} catch (e) {
@@ -588,6 +594,8 @@
}
Future<Null> _addFix_addAsync() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
FunctionBody body = node.getAncestor((n) => n is FunctionBody);
if (body != null && body.keyword == null) {
TypeProvider typeProvider = await this.typeProvider;
@@ -600,6 +608,8 @@
}
Future<Null> _addFix_addExplicitCast() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (coveredNode is! Expression) {
return;
}
@@ -699,6 +709,8 @@
}
Future<Null> _addFix_addMissingNamedArgument() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// Prepare the name of the missing parameter.
if (this.node is! SimpleIdentifier) {
return;
@@ -730,6 +742,8 @@
}
Future<void> addParameter(int offset, String prefix, String suffix) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (offset != null) {
var changeBuilder = new DartChangeBuilder(session);
await changeBuilder.addFileEdit(context.file, (builder) {
@@ -759,6 +773,8 @@
}
Future<Null> _addFix_addMissingParameter() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// The error is reported on ArgumentList.
if (node is! ArgumentList) {
return;
@@ -781,6 +797,8 @@
Future<void> addParameter(
FixKind kind, int offset, String prefix, String suffix) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (offset != null) {
var changeBuilder = new DartChangeBuilder(session);
await changeBuilder.addFileEdit(context.file, (builder) {
@@ -825,6 +843,8 @@
}
Future<Null> _addFix_addMissingRequiredArgument() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
InstanceCreationExpression creation;
Element targetElement;
ArgumentList argumentList;
@@ -892,6 +912,8 @@
}
Future<Null> _addFix_addOverrideAnnotation() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
ClassMember member = node.getAncestor((n) => n is ClassMember);
if (member == null) {
return;
@@ -917,6 +939,8 @@
}
Future<Null> _addFix_addRequiredAnnotation() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
builder.addSimpleInsertion(node.parent.offset, '@required ');
@@ -925,6 +949,8 @@
}
Future<Null> _addFix_addStatic() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
FieldDeclaration declaration =
node.getAncestor((n) => n is FieldDeclaration);
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
@@ -935,6 +961,8 @@
}
Future<Null> _addFix_boolInsteadOfBoolean() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
builder.addSimpleReplacement(range.error(error), 'bool');
@@ -943,6 +971,8 @@
}
Future<Null> _addFix_canBeNullAfterNullAware() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AstNode node = coveredNode;
if (node is Expression) {
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
@@ -965,6 +995,8 @@
}
Future<Null> _addFix_changeTypeAnnotation() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AstNode declaration = coveredNode.parent;
if (declaration is VariableDeclaration &&
declaration.initializer == coveredNode) {
@@ -996,6 +1028,8 @@
}
Future<Null> _addFix_convertFlutterChild() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
NamedExpression named = flutter.findNamedExpression(node, 'child');
if (named == null) {
return;
@@ -1036,6 +1070,8 @@
}
Future<Null> _addFix_convertFlutterChildren() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AstNode node = this.node;
if (node is SimpleIdentifier &&
node.name == 'children' &&
@@ -1064,6 +1100,8 @@
}
Future<Null> _addFix_convertToNamedArgument() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var argumentList = this.node;
if (argumentList is ArgumentList) {
// Prepare ExecutableElement.
@@ -1132,6 +1170,8 @@
}
Future<Null> _addFix_createClass() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
Element prefixElement = null;
String name = null;
SimpleIdentifier nameNode;
@@ -1215,6 +1255,8 @@
* class has uninitialized final fields.
*/
Future<Null> _addFix_createConstructor_forUninitializedFinalFields() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is! SimpleIdentifier || node.parent is! VariableDeclaration) {
return;
}
@@ -1291,6 +1333,8 @@
}
Future<Null> _addFix_createConstructor_insteadOfSyntheticDefault() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is! ArgumentList) {
return;
}
@@ -1334,6 +1378,8 @@
}
Future<Null> _addFix_createConstructor_named() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
SimpleIdentifier name = null;
ConstructorName constructorName = null;
InstanceCreationExpression instanceCreation = null;
@@ -1392,6 +1438,8 @@
}
Future<Null> _addFix_createConstructorSuperExplicit() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node.parent is! ConstructorDeclaration ||
node.parent.parent is! ClassDeclaration) {
return;
@@ -1461,6 +1509,8 @@
}
Future<Null> _addFix_createConstructorSuperImplicit() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
ClassDeclaration targetClassNode = node.parent as ClassDeclaration;
ClassElement targetClassElement = targetClassNode.element;
InterfaceType superType = targetClassElement.supertype;
@@ -1528,6 +1578,8 @@
}
Future<Null> _addFix_createField() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is! SimpleIdentifier) {
return;
}
@@ -1603,6 +1655,8 @@
}
Future<Null> _addFix_createField_initializingFormal() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
//
// Ensure that we are in an initializing formal parameter.
//
@@ -1637,6 +1691,8 @@
}
Future<Null> _addFix_createFunction_forFunctionType() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is SimpleIdentifier) {
SimpleIdentifier nameNode = node as SimpleIdentifier;
// prepare argument expression (to get parameter)
@@ -1685,6 +1741,8 @@
}
Future<Null> _addFix_createGetter() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is! SimpleIdentifier) {
return;
}
@@ -1760,6 +1818,8 @@
}
Future<Null> _addFix_createImportUri() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// TODO(brianwilkerson) Generalize this to allow other valid string literals.
// TODO(brianwilkerson) Support the case where the node's parent is a Configuration.
if (node is SimpleStringLiteral && node.parent is ImportDirective) {
@@ -1786,6 +1846,8 @@
}
Future<Null> _addFix_createLocalVariable() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is! SimpleIdentifier) {
return;
}
@@ -1837,6 +1899,8 @@
}
Future<Null> _addFix_createMissingOverrides() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node.parent is! ClassDeclaration) {
return;
}
@@ -1986,6 +2050,8 @@
}
Future<Null> _addFix_createNoSuchMethod() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node.parent is! ClassDeclaration) {
return;
}
@@ -2012,6 +2078,8 @@
}
Future<Null> _addFix_createPartUri() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// TODO(brianwilkerson) Generalize this to allow other valid string literals.
if (node is SimpleStringLiteral && node.parent is PartDirective) {
PartDirective partDirective = node.parent;
@@ -2031,6 +2099,8 @@
}
Future<Null> _addFix_illegalAsyncReturnType() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// prepare the existing type
TypeAnnotation typeName = node.getAncestor((n) => n is TypeAnnotation);
TypeProvider typeProvider = this.typeProvider;
@@ -2042,6 +2112,8 @@
}
Future<Null> _addFix_importLibrary(FixKind kind, Uri library) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String uriText;
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
@@ -2052,6 +2124,8 @@
Future<Null> _addFix_importLibrary_withElement(String name,
List<ElementKind> elementKinds, TopLevelDeclarationKind kind2) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// ignore if private
if (name.startsWith('_')) {
return;
@@ -2153,6 +2227,8 @@
}
Future<Null> _addFix_importLibrary_withFunction() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is SimpleIdentifier && node.parent is MethodInvocation) {
MethodInvocation invocation = node.parent as MethodInvocation;
if (invocation.realTarget == null && invocation.methodName == node) {
@@ -2164,6 +2240,8 @@
}
Future<Null> _addFix_importLibrary_withTopLevelVariable() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is SimpleIdentifier) {
String name = (node as SimpleIdentifier).name;
await _addFix_importLibrary_withElement(
@@ -2174,6 +2252,8 @@
}
Future<Null> _addFix_importLibrary_withType() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (_mayBeTypeIdentifier(node)) {
String typeName = (node as SimpleIdentifier).name;
await _addFix_importLibrary_withElement(
@@ -2188,6 +2268,8 @@
}
Future<Null> _addFix_insertSemicolon() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (error.message.contains("';'")) {
if (_isAwaitNode()) {
return;
@@ -2202,6 +2284,8 @@
}
Future<Null> _addFix_isNotEmpty() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is! PrefixExpression) {
return;
}
@@ -2228,6 +2312,8 @@
}
Future<Null> _addFix_isNotNull() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (coveredNode is IsExpression) {
IsExpression isExpression = coveredNode as IsExpression;
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
@@ -2243,6 +2329,8 @@
}
Future<Null> _addFix_isNull() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (coveredNode is IsExpression) {
IsExpression isExpression = coveredNode as IsExpression;
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
@@ -2258,6 +2346,8 @@
}
Future<Null> _addFix_makeEnclosingClassAbstract() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
ClassDeclaration enclosingClass =
node.getAncestor((node) => node is ClassDeclaration);
if (enclosingClass == null) {
@@ -2274,6 +2364,8 @@
}
Future<Null> _addFix_makeFieldNotFinal() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AstNode node = this.node;
if (node is SimpleIdentifier &&
node.bestElement is PropertyAccessorElement) {
@@ -2317,6 +2409,8 @@
}
Future<Null> _addFix_makeVariableFinal() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AstNode node = this.node;
if (node is SimpleIdentifier && node.parent is VariableDeclaration) {
VariableDeclaration declaration = node.parent;
@@ -2336,6 +2430,8 @@
}
Future<Null> _addFix_nonBoolCondition_addNotNull() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
builder.addSimpleInsertion(error.offset + error.length, ' != null');
@@ -2344,6 +2440,8 @@
}
Future<Null> _addFix_removeAwait() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
final awaitExpression = node;
if (awaitExpression is AwaitExpression) {
final awaitToken = awaitExpression.awaitKeyword;
@@ -2356,6 +2454,8 @@
}
Future<Null> _addFix_removeDeadCode() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AstNode coveringNode = this.coveredNode;
if (coveringNode is Expression) {
AstNode parent = coveredNode.parent;
@@ -2397,6 +2497,8 @@
}
Future<Null> _addFix_removeEmptyCatch() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
builder.addDeletion(utils.getLinesRange(range.node(node.parent)));
@@ -2405,6 +2507,8 @@
}
Future<Null> _addFix_removeEmptyConstructorBody() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
builder.addSimpleReplacement(
@@ -2415,6 +2519,8 @@
}
Future<Null> _addFix_removeEmptyElse() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
IfStatement ifStatement = node.parent;
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
@@ -2425,6 +2531,8 @@
}
Future<Null> _addFix_removeEmptyStatement() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
EmptyStatement emptyStatement = node;
if (emptyStatement.parent is Block) {
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
@@ -2446,6 +2554,8 @@
}
Future<Null> _addFix_removeInitializer() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// Retrieve the linted node.
VariableDeclaration ancestor =
node.getAncestor((a) => a is VariableDeclaration);
@@ -2460,6 +2570,8 @@
}
Future<Null> _addFix_removeInterpolationBraces() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AstNode node = this.node;
if (node is InterpolationExpression) {
Token right = node.rightBracket;
@@ -2477,6 +2589,8 @@
}
Future<Null> _addFix_removeMethodDeclaration() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
MethodDeclaration declaration =
node.getAncestor((node) => node is MethodDeclaration);
if (declaration != null) {
@@ -2489,6 +2603,8 @@
}
Future<Null> _addFix_removeParameters_inGetterDeclaration() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is MethodDeclaration) {
MethodDeclaration method = node as MethodDeclaration;
SimpleIdentifier name = method.name;
@@ -2505,6 +2621,8 @@
}
Future<Null> _addFix_removeParentheses_inGetterInvocation() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is SimpleIdentifier && node.parent is MethodInvocation) {
MethodInvocation invocation = node.parent as MethodInvocation;
if (invocation.methodName == node && invocation.target != null) {
@@ -2519,6 +2637,8 @@
}
Future<Null> _addFix_removeThisExpression() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
final thisExpression = node is ThisExpression
? node
: node.getAncestor((node) => node is ThisExpression);
@@ -2539,6 +2659,8 @@
}
Future<Null> _addFix_removeTypeAnnotation() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
final TypeAnnotation type =
node.getAncestor((node) => node is TypeAnnotation);
if (type != null) {
@@ -2551,6 +2673,8 @@
}
Future<Null> _addFix_removeUnnecessaryCast() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (coveredNode is! AsExpression) {
return;
}
@@ -2567,6 +2691,8 @@
}
Future<Null> _addFix_removeUnusedCatchClause() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is SimpleIdentifier) {
AstNode catchClause = node.parent;
if (catchClause is CatchClause &&
@@ -2583,6 +2709,8 @@
}
Future<Null> _addFix_removeUnusedCatchStack() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is SimpleIdentifier) {
AstNode catchClause = node.parent;
if (catchClause is CatchClause &&
@@ -2600,6 +2728,8 @@
}
Future<Null> _addFix_removeUnusedImport() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// prepare ImportDirective
ImportDirective importDirective =
node.getAncestor((node) => node is ImportDirective);
@@ -2615,6 +2745,8 @@
}
Future<Null> _addFix_renameToCamelCase() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is! SimpleIdentifier) {
return;
}
@@ -2656,6 +2788,8 @@
}
Future<Null> _addFix_replaceFinalWithConst() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is VariableDeclarationList) {
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
@@ -2667,6 +2801,8 @@
}
Future<Null> _addFix_replaceVarWithDynamic() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
builder.addSimpleReplacement(range.error(error), 'dynamic');
@@ -2675,6 +2811,8 @@
}
Future<Null> _addFix_replaceWithConditionalAssignment() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
IfStatement ifStatement = node is IfStatement
? node
: node.getAncestor((node) => node is IfStatement);
@@ -2710,6 +2848,8 @@
}
Future<Null> _addFix_replaceWithConstInstanceCreation() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (coveredNode is InstanceCreationExpression) {
var instanceCreation = coveredNode as InstanceCreationExpression;
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
@@ -2727,6 +2867,8 @@
}
Future<Null> _addFix_replaceWithIdentifier() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
final FunctionTypedFormalParameter functionTyped =
node.getAncestor((node) => node is FunctionTypedFormalParameter);
if (functionTyped != null) {
@@ -2742,6 +2884,8 @@
}
Future<Null> _addFix_replaceWithLiteral() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
final InstanceCreationExpression instanceCreation =
node.getAncestor((node) => node is InstanceCreationExpression);
final InterfaceType type = instanceCreation.staticType;
@@ -2764,12 +2908,16 @@
}
Future<Null> _addFix_replaceWithTearOff() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
FunctionExpression ancestor =
node.getAncestor((a) => a is FunctionExpression);
if (ancestor == null) {
return;
}
Future<Null> addFixOfExpression(InvocationExpression expression) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
builder.addReplacement(range.node(ancestor), (DartEditBuilder builder) {
@@ -2800,6 +2948,8 @@
}
Future<Null> _addFix_undefinedClass_useSimilar() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AstNode node = this.node;
// Prepare the optional import prefix name.
String prefixName = null;
@@ -2849,6 +2999,8 @@
}
Future<Null> _addFix_undefinedClassAccessor_useSimilar() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AstNode node = this.node;
if (node is SimpleIdentifier) {
// prepare target
@@ -2878,6 +3030,8 @@
Future<Null> _addFix_undefinedClassMember_useSimilar(
Expression target, ElementPredicate predicate) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is SimpleIdentifier) {
String name = (node as SimpleIdentifier).name;
_ClosestElementFinder finder =
@@ -2911,6 +3065,8 @@
}
Future<Null> _addFix_undefinedFunction_create() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// should be the name of the invocation
if (node is SimpleIdentifier && node.parent is MethodInvocation) {
} else {
@@ -2958,6 +3114,8 @@
}
Future<Null> _addFix_undefinedFunction_useSimilar() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AstNode node = this.node;
if (node is SimpleIdentifier) {
// Prepare the optional import prefix name.
@@ -3004,6 +3162,8 @@
}
Future<Null> _addFix_undefinedMethod_create() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is SimpleIdentifier && node.parent is MethodInvocation) {
String name = (node as SimpleIdentifier).name;
MethodInvocation invocation = node.parent as MethodInvocation;
@@ -3088,6 +3248,8 @@
}
Future<Null> _addFix_undefinedMethod_useSimilar() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node.parent is MethodInvocation) {
MethodInvocation invocation = node.parent as MethodInvocation;
await _addFix_undefinedClassMember_useSimilar(invocation.realTarget,
@@ -3096,6 +3258,8 @@
}
Future<Null> _addFix_undefinedMethodWithContructor() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is SimpleIdentifier && node.parent is MethodInvocation) {
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
@@ -3114,6 +3278,8 @@
* final fields.
*/
Future<Null> _addFix_updateConstructor_forUninitializedFinalFields() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is! SimpleIdentifier || node.parent is! ConstructorDeclaration) {
return;
}
@@ -3174,6 +3340,8 @@
}
Future<Null> _addFix_useEffectiveIntegerDivision() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
for (AstNode n = node; n != null; n = n.parent) {
if (n is MethodInvocation &&
n.offset == errorOffset &&
@@ -3201,6 +3369,8 @@
* the given [element].
*/
Future<Null> _addFix_useStaticAccess(AstNode target, Element element) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
Element declaringElement = element.enclosingElement;
if (declaringElement is ClassElement) {
DartType declaringType = declaringElement.type;
@@ -3217,6 +3387,8 @@
}
Future<Null> _addFix_useStaticAccess_method() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is SimpleIdentifier && node.parent is MethodInvocation) {
MethodInvocation invocation = node.parent as MethodInvocation;
if (invocation.methodName == node) {
@@ -3228,6 +3400,8 @@
}
Future<Null> _addFix_useStaticAccess_property() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (node is SimpleIdentifier && node.parent is PrefixedIdentifier) {
PrefixedIdentifier prefixed = node.parent as PrefixedIdentifier;
if (prefixed.identifier == node) {
@@ -3262,6 +3436,8 @@
String sourcePrefix,
String sourceSuffix,
Element target) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// build method source
String targetFile = targetSource.fullName;
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
@@ -3324,6 +3500,8 @@
*/
Future<Null> _addProposal_createFunction_function(
FunctionType functionType) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String name = (node as SimpleIdentifier).name;
// prepare environment
int insertOffset = unit.end;
@@ -3351,6 +3529,8 @@
*/
Future<Null> _addProposal_createFunction_method(
ClassElement targetClassElement, FunctionType functionType) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String name = (node as SimpleIdentifier).name;
// prepare environment
Source targetSource = targetClassElement.source;
@@ -3907,6 +4087,8 @@
* be found.
*/
Future<FormalParameterList> getParameterList() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var name = await astProvider.getParsedNameForElement(executable);
AstNode targetDeclaration = name?.parent;
if (targetDeclaration is ConstructorDeclaration) {
@@ -3925,6 +4107,8 @@
* or `null` is cannot be found.
*/
Future<FormalParameter> getParameterNode(ParameterElement element) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var name = await astProvider.getParsedNameForElement(element);
for (AstNode node = name; node != null; node = node.parent) {
if (node is FormalParameter && node.parent is FormalParameterList) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart b/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart
index 0051772..598057e 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/convert_getter_to_method.dart
@@ -48,6 +48,8 @@
@override
Future<SourceChange> createChange() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
change = new SourceChange(refactoringName);
// function
if (element.enclosingElement is CompilationUnitElement) {
@@ -60,6 +62,8 @@
Set<ClassMemberElement> elements =
await getHierarchyMembers(searchEngine, field);
await Future.forEach(elements, (ClassMemberElement member) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (member is FieldElement) {
PropertyAccessorElement getter = member.getter;
if (!getter.isSynthetic) {
@@ -86,6 +90,8 @@
Future<Null> _updateElementDeclaration(
PropertyAccessorElement element) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// prepare "get" keyword
Token getKeyword = null;
{
@@ -114,6 +120,8 @@
}
Future _updateElementReferences(Element element) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<SearchMatch> matches = await searchEngine.searchReferences(element);
List<SourceReference> references = getSourceReferences(matches);
for (SourceReference reference in references) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/convert_method_to_getter.dart b/pkg/analysis_server/lib/src/services/refactoring/convert_method_to_getter.dart
index 2ff0f5b..a6a2c7b 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/convert_method_to_getter.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/convert_method_to_getter.dart
@@ -42,6 +42,8 @@
@override
Future<RefactoringStatus> checkInitialConditions() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// check Element type
if (element is FunctionElement) {
if (element.enclosingElement is! CompilationUnitElement) {
@@ -68,6 +70,8 @@
@override
Future<SourceChange> createChange() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
change = new SourceChange(refactoringName);
// FunctionElement
if (element is FunctionElement) {
@@ -80,6 +84,8 @@
Set<ClassMemberElement> elements =
await getHierarchyMembers(searchEngine, method);
await Future.forEach(elements, (Element element) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
await _updateElementDeclaration(element);
return _updateElementReferences(element);
});
@@ -92,6 +98,8 @@
bool requiresPreview() => false;
Future<Null> _updateElementDeclaration(Element element) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// prepare parameters
FormalParameterList parameters;
{
@@ -118,6 +126,8 @@
}
Future<Null> _updateElementReferences(Element element) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<SearchMatch> matches = await searchEngine.searchReferences(element);
List<SourceReference> references = getSourceReferences(matches);
for (SourceReference reference in references) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
index f8865c5..71baf5a 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
@@ -188,6 +188,8 @@
@override
Future<RefactoringStatus> checkFinalConditions() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
RefactoringStatus result = new RefactoringStatus();
result.addStatus(validateMethodName(name));
result.addStatus(_checkParameterNames());
@@ -198,6 +200,8 @@
@override
Future<RefactoringStatus> checkInitialConditions() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
RefactoringStatus result = new RefactoringStatus();
// selection
result.addStatus(_checkSelection());
@@ -236,6 +240,8 @@
@override
Future<SourceChange> createChange() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
SourceChange change = new SourceChange(refactoringName);
// replace occurrences with method invocation
for (_Occurrence occurrence in _occurrences) {
@@ -439,6 +445,8 @@
* Checks if created method will shadow or will be shadowed by other elements.
*/
Future<RefactoringStatus> _checkPossibleConflicts() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
RefactoringStatus result = new RefactoringStatus();
AstNode parent = _parentMember.parent;
// top-level function
@@ -715,6 +723,8 @@
* parameters.
*/
Future<RefactoringStatus> _initializeParameters() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
_parameters.clear();
_parametersMap.clear();
_parameterReferencesMap.clear();
@@ -773,6 +783,8 @@
}
Future<Null> _initializeReturnType() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
TypeProvider typeProvider = await session.typeProvider;
InterfaceType futureType = typeProvider.futureType;
if (_selectionFunctionExpression != null) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
index 1ad85d0..9f8e17b 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
@@ -88,6 +88,8 @@
@override
Future<RefactoringStatus> checkFinalConditions() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
RefactoringStatus result = new RefactoringStatus();
result.addStatus(validateClassName(name));
return result;
@@ -95,6 +97,8 @@
@override
Future<RefactoringStatus> checkInitialConditions() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
RefactoringStatus result = new RefactoringStatus();
result.addStatus(_checkSelection());
@@ -138,6 +142,8 @@
@override
Future<SourceChange> createChange() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String file = unitElement.source.fullName;
var changeBuilder = new DartChangeBuilder(sessionHelper.session);
await changeBuilder.addFileEdit(file, (builder) {
@@ -171,7 +177,12 @@
/// Checks if [offset] is a widget creation expression that can be extracted.
RefactoringStatus _checkSelection() {
- AstNode node = new NodeLocator2(offset, offset + length).searchWithin(unit);
+ AstNode node = new NodeLocator(offset, offset + length).searchWithin(unit);
+
+ // Treat single ReturnStatement as its expression.
+ if (node is ReturnStatement) {
+ node = (node as ReturnStatement).expression;
+ }
// Find the enclosing class.
_enclosingClassNode = node?.getAncestor((n) => n is ClassDeclaration);
@@ -229,9 +240,13 @@
}
Future<RefactoringStatus> _initializeClasses() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var result = new RefactoringStatus();
Future<ClassElement> getClass(String name) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
const uri = 'package:flutter/widgets.dart';
var element = await sessionHelper.getClass(uri, name);
if (element == null) {
@@ -241,6 +256,8 @@
}
Future<PropertyAccessorElement> getAccessor(String uri, String name) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var element = await sessionHelper.getTopLevelPropertyAccessor(uri, name);
if (element == null) {
result.addFatalError("Unable to find 'required' in $uri");
@@ -262,6 +279,8 @@
/// Prepare referenced local variables and fields, that should be turned
/// into the widget class fields and constructor parameters.
Future<RefactoringStatus> _initializeParameters() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
_ParametersCollector collector;
if (_expression != null) {
SourceRange localRange = range.node(_expression);
diff --git a/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart b/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
index 586080a..8a18e3e 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
@@ -68,6 +68,8 @@
@override
Future<RefactoringStatus> checkInitialConditions() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
RefactoringStatus result = new RefactoringStatus();
// prepare variable
{
diff --git a/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart b/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
index 83da06e..3cc06e2 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
@@ -272,6 +272,8 @@
@override
Future<RefactoringStatus> checkInitialConditions() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
RefactoringStatus result = new RefactoringStatus();
// prepare method information
result.addStatus(await _prepareMethod());
@@ -311,6 +313,8 @@
bool requiresPreview() => false;
Future<FunctionDeclaration> _computeFunctionDeclaration() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
CompilationUnit unit = await _unitCache.getUnit(_methodElement);
return new NodeLocator(_methodElement.nameOffset)
.searchWithin(unit)
@@ -318,6 +322,8 @@
}
Future<MethodDeclaration> _computeMethodDeclaration() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
CompilationUnit unit = await _unitCache.getUnit(_methodElement);
return new NodeLocator(_methodElement.nameOffset)
.searchWithin(unit)
@@ -338,6 +344,8 @@
* Initializes [_methodElement] and related fields.
*/
Future<RefactoringStatus> _prepareMethod() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
_methodElement = null;
_methodParameters = null;
_methodBody = null;
@@ -457,6 +465,8 @@
_ReferenceProcessor(this.ref, this.reference);
Future<Null> init() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
refElement = reference.element;
// prepare CorrectionUtils
CompilationUnit refUnit = await ref._unitCache.getUnit(refElement);
diff --git a/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart b/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
index f99d9db..dc7777c 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
@@ -498,6 +498,8 @@
}
Future<CompilationUnit> getUnit(Element element) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
CompilationUnitElement unitElement = getUnitElement(element);
CompilationUnit unit = _map[unitElement];
if (unit == null) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/refactoring_internal.dart b/pkg/analysis_server/lib/src/services/refactoring/refactoring_internal.dart
index eebc587..2a81869 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/refactoring_internal.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/refactoring_internal.dart
@@ -45,6 +45,8 @@
@override
Future<RefactoringStatus> checkAllConditions() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
RefactoringStatus result = new RefactoringStatus();
result.addStatus(await checkInitialConditions());
if (result.hasFatalError) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename.dart b/pkg/analysis_server/lib/src/services/refactoring/rename.dart
index 716b2de13..aa110e0 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename.dart
@@ -89,6 +89,8 @@
@override
Future<SourceChange> createChange() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String changeName = "$refactoringName '$oldName' to '$newName'";
change = new SourceChange(changeName);
await fillChange();
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
index 7c58a69..847b333 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
@@ -64,6 +64,8 @@
@override
Future<RefactoringStatus> checkInitialConditions() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
RefactoringStatus result = await super.checkInitialConditions();
if (element is MethodElement && (element as MethodElement).isOperator) {
result.addFatalError('Cannot rename operator.');
@@ -85,6 +87,8 @@
@override
Future fillChange() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// update declarations
for (Element renameElement in _validator.elements) {
if (renameElement.isSynthetic && renameElement is FieldElement) {
@@ -159,6 +163,8 @@
elementKind = element.kind;
Future<RefactoringStatus> validate() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// check if there is a member with "newName" in the same ClassElement
for (Element newNameMember in getChildren(elementClass, name)) {
result.addError(
@@ -249,8 +255,12 @@
}
Future<_MatchShadowedByLocal> _getShadowingLocalElement() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var localElementMap = <CompilationUnitElement, List<LocalElement>>{};
Future<List<LocalElement>> getLocalElements(Element element) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var unitElement = unitCache.getUnitElement(element);
var localElements = localElementMap[unitElement];
if (localElements == null) {
@@ -285,6 +295,8 @@
* Fills [elements] with [Element]s to rename.
*/
Future _prepareElements() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (element is ClassMemberElement) {
elements = await getHierarchyMembers(searchEngine, element);
} else {
@@ -296,11 +308,15 @@
* Fills [references] with all references to [elements].
*/
Future _prepareReferences() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (!isRename) {
return new Future.value();
}
await _prepareElements();
await Future.forEach(elements, (Element element) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<SearchMatch> elementReferences =
await searchEngine.searchReferences(element);
references.addAll(elementReferences);
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_constructor.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_constructor.dart
index ccdb578..661eea2 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_constructor.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_constructor.dart
@@ -57,6 +57,8 @@
@override
Future fillChange() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// prepare references
List<SearchMatch> matches = await searchEngine.searchReferences(element);
List<SourceReference> references = getSourceReferences(matches);
@@ -112,6 +114,8 @@
}
Future<Null> _replaceSynthetic() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
ClassElement classElement = element.enclosingElement;
AstNode name = await astProvider.getResolvedNameForElement(classElement);
ClassDeclaration classNode = name.parent as ClassDeclaration;
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
index 826fcf0..2ebf57a 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
@@ -53,6 +53,8 @@
@override
Future fillChange() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// update declaration
{
PrefixElement prefix = element.prefix;
@@ -107,6 +109,8 @@
* Return the [ImportDirective] node that corresponds to the [element].
*/
Future<ImportDirective> _findNode() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
LibraryElement library = element.library;
CompilationUnit unit = await astProvider.getParsedUnitForElement(library);
int index = library.imports.indexOf(element);
@@ -120,6 +124,8 @@
*/
Future<SimpleIdentifier> _getInterpolationIdentifier(
SourceReference reference) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
Source source = reference.element.source;
AnalysisSession currentSession = astProvider.driver.currentSession;
ParseResult result = await currentSession.getParsedAst(source.fullName);
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_local.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_local.dart
index d452e7d..c417805 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_local.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_local.dart
@@ -48,6 +48,8 @@
@override
Future<RefactoringStatus> checkFinalConditions() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
RefactoringStatus result = new RefactoringStatus();
await _prepareElements();
for (LocalElement element in elements) {
@@ -74,6 +76,8 @@
@override
Future fillChange() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
for (Element element in elements) {
addDeclarationEdit(element);
var references = await searchEngine.searchReferences(element);
@@ -91,6 +95,8 @@
* Fills [elements] with [Element]s to rename.
*/
Future _prepareElements() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
Element element = this.element;
if (element is ParameterElement && element.isNamed) {
elements = await getHierarchyNamedParameters(searchEngine, element);
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_unit_member.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_unit_member.dart
index 5f483a9..29096a3 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_unit_member.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_unit_member.dart
@@ -134,6 +134,8 @@
}
Future<RefactoringStatus> validate() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
_validateWillConflict();
if (isRename) {
references = await searchEngine.searchReferences(element);
@@ -226,6 +228,8 @@
* Validates if renamed [element] will shadow any [Element] named [name].
*/
Future _validateWillShadow() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<SearchMatch> declarations =
await searchEngine.searchMemberDeclarations(name);
for (SearchMatch declaration in declarations) {
diff --git a/pkg/analysis_server/lib/src/services/search/element_visitors.dart b/pkg/analysis_server/lib/src/services/search/element_visitors.dart
index 3297709..bbd4233 100644
--- a/pkg/analysis_server/lib/src/services/search/element_visitors.dart
+++ b/pkg/analysis_server/lib/src/services/search/element_visitors.dart
@@ -6,6 +6,23 @@
import 'package:analyzer/dart/element/visitor.dart';
/**
+ * Return the [Element] that is either [root], or one of its direct or
+ * indirect children, and has the given [nameOffset].
+ */
+Element findElementByNameOffset(Element root, int nameOffset) {
+ if (root == null) {
+ return null;
+ }
+ try {
+ var visitor = new _ElementByNameOffsetVisitor(nameOffset);
+ root.accept(visitor);
+ } on Element catch (result) {
+ return result;
+ }
+ return null;
+}
+
+/**
* Uses [processor] to visit all of the children of [element].
* If [processor] returns `true`, then children of a child are visited too.
*/
@@ -28,6 +45,24 @@
typedef bool ElementProcessor(Element element);
/**
+ * A visitor that finds the deep-most [Element] that contains the [nameOffset].
+ */
+class _ElementByNameOffsetVisitor extends GeneralizingElementVisitor {
+ final int nameOffset;
+
+ _ElementByNameOffsetVisitor(this.nameOffset);
+
+ visitElement(Element element) {
+ if (element.nameOffset != -1 &&
+ !element.isSynthetic &&
+ element.nameOffset == nameOffset) {
+ throw element;
+ }
+ super.visitElement(element);
+ }
+}
+
+/**
* A [GeneralizingElementVisitor] adapter for [ElementProcessor].
*/
class _ElementVisitorAdapter extends GeneralizingElementVisitor {
diff --git a/pkg/analysis_server/lib/src/services/search/hierarchy.dart b/pkg/analysis_server/lib/src/services/search/hierarchy.dart
index 6441488..a1f03ae 100644
--- a/pkg/analysis_server/lib/src/services/search/hierarchy.dart
+++ b/pkg/analysis_server/lib/src/services/search/hierarchy.dart
@@ -57,6 +57,8 @@
*/
Future<Set<ClassElement>> getDirectSubClasses(
SearchEngine searchEngine, ClassElement seed) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<SearchMatch> matches = await searchEngine.searchSubtypes(seed);
return matches.map((match) => match.element).cast<ClassElement>().toSet();
}
@@ -67,6 +69,8 @@
*/
Future<Set<ClassMemberElement>> getHierarchyMembers(
SearchEngine searchEngine, ClassMemberElement member) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
Set<ClassMemberElement> result = new HashSet<ClassMemberElement>();
// static elements
if (member.isStatic || member is ConstructorElement) {
@@ -105,6 +109,8 @@
*/
Future<List<ParameterElement>> getHierarchyNamedParameters(
SearchEngine searchEngine, ParameterElement element) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (element.isNamed) {
Element method = element.enclosingElement;
if (method is MethodElement) {
diff --git a/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart b/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
index 496db3d..a0d3130 100644
--- a/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
+++ b/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
@@ -20,6 +20,8 @@
@override
Future<Set<String>> membersOfSubtypes(ClassElement type) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<AnalysisDriver> drivers = _drivers.toList();
String libraryUriStr = type.librarySource.uri.toString();
@@ -28,6 +30,8 @@
Set<String> members = new Set<String>();
Future<Null> addMembers(ClassElement type, SubtypeResult subtype) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (subtype != null && !visitedIds.add(subtype.id)) {
return;
}
@@ -54,9 +58,13 @@
@override
Future<Set<ClassElement>> searchAllSubtypes(ClassElement type) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
Set<ClassElement> allSubtypes = new Set<ClassElement>();
Future<Null> addSubtypes(ClassElement type) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<SearchResult> directResults = await _searchDirectSubtypes(type);
for (SearchResult directResult in directResults) {
var directSubtype = directResult.enclosingElement as ClassElement;
@@ -72,6 +80,8 @@
@override
Future<List<SearchMatch>> searchMemberDeclarations(String name) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<SearchMatch> allDeclarations = [];
List<AnalysisDriver> drivers = _drivers.toList();
for (AnalysisDriver driver in drivers) {
@@ -83,6 +93,8 @@
@override
Future<List<SearchMatch>> searchMemberReferences(String name) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<SearchResult> allResults = [];
List<AnalysisDriver> drivers = _drivers.toList();
SearchedFiles searchedFiles = _createSearchedFiles(drivers);
@@ -96,6 +108,8 @@
@override
Future<List<SearchMatch>> searchReferences(Element element) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<SearchResult> allResults = [];
List<AnalysisDriver> drivers = _drivers.toList();
SearchedFiles searchedFiles = _createSearchedFiles(drivers);
@@ -109,12 +123,16 @@
@override
Future<List<SearchMatch>> searchSubtypes(ClassElement type) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<SearchResult> results = await _searchDirectSubtypes(type);
return results.map(SearchMatchImpl.forSearchResult).toList();
}
@override
Future<List<SearchMatch>> searchTopLevelDeclarations(String pattern) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
Set<Element> allElements = new Set<Element>();
RegExp regExp = new RegExp(pattern);
List<AnalysisDriver> drivers = _drivers.toList();
@@ -138,6 +156,8 @@
}
Future<List<SearchResult>> _searchDirectSubtypes(ClassElement type) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<SearchResult> allResults = [];
List<AnalysisDriver> drivers = _drivers.toList();
SearchedFiles searchedFiles = _createSearchedFiles(drivers);
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart
index b579add..a21b681 100644
--- a/pkg/analysis_server/lib/src/status/diagnostics.dart
+++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -172,6 +172,8 @@
@override
Future<Null> generateContent(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String path = params['file'];
if (path == null) {
p('No file path provided.');
@@ -198,6 +200,8 @@
@override
Future<Null> generatePage(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
try {
_description = params['file'];
await super.generatePage(params);
@@ -215,6 +219,8 @@
@override
Future generateContent(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
void writeRow(List<String> data, {List<String> classes}) {
buf.write("<tr>");
for (int i = 0; i < data.length; i++) {
@@ -303,6 +309,8 @@
@override
Future generateContent(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
CompletionDomainHandler completionDomain = server.handlers
.firstWhere((handler) => handler is CompletionDomainHandler);
@@ -394,6 +402,8 @@
@override
Future generateContent(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
Map<Folder, AnalysisDriver> driverMap = server.driverMap;
if (driverMap.isEmpty) {
blankslate('No contexts.');
@@ -574,10 +584,14 @@
(site as DiagnosticsSite).socketServer.analysisServer;
Future<Null> generateContainer(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
buf.writeln('<div class="columns docs-layout">');
buf.writeln('<div class="three-fourths column markdown-body">');
h1(title, classes: 'page-title');
await asyncDiv(() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
p(description);
await generateContent(params);
}, classes: 'markdown-body');
@@ -618,6 +632,8 @@
}
Future<Null> generatePage(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
buf.writeln('<!DOCTYPE html><html lang="en">');
buf.write('<head>');
buf.write('<meta charset="utf-8">');
@@ -656,6 +672,8 @@
bool get showInNav => true;
Future<Null> generateContainer(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
buf.writeln('<div class="columns docs-layout">');
bool shouldShowInNav(Page page) {
@@ -679,6 +697,8 @@
buf.writeln('<div class="four-fifths column markdown-body">');
h1(title, classes: 'page-title');
await asyncDiv(() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
p(description);
await generateContent(params);
}, classes: 'markdown-body');
@@ -750,6 +770,8 @@
@override
Future<Null> generateContent(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String path = params['file'];
if (path == null) {
p('No file path provided.');
@@ -776,6 +798,8 @@
@override
Future<Null> generatePage(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
try {
_description = params['file'];
await super.generatePage(params);
@@ -793,6 +817,8 @@
@override
Future generateContent(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
buf.writeln('<table>');
buf.writeln('<tr><th>Variable</th><th>Value</th></tr>');
for (String key in Platform.environment.keys.toList()..sort()) {
@@ -810,6 +836,8 @@
: super(site, '', '500 Oops', description: message);
Future generateContent(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
p(trace.toString(), style: 'white-space: pre');
}
}
@@ -825,6 +853,8 @@
@override
Future generateContent(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (exceptions.isEmpty) {
blankslate('No exceptions encountered!');
} else {
@@ -847,6 +877,8 @@
@override
Future generateContent(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
final String issuesUrl = 'https://github.com/dart-lang/sdk/issues';
p(
'To file issues or feature requests, see our '
@@ -890,6 +922,8 @@
@override
Future generateContent(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
p(
'Instrumentation can be enabled by starting the analysis server with the '
'<code>--instrumentation-log-file=path/to/file</code> flag.',
@@ -932,6 +966,8 @@
@override
Future generateContent(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
UsageInfo usage = await profiler.getProcessUsage(pid);
developer.ServiceProtocolInfo serviceProtocolInfo =
@@ -994,7 +1030,10 @@
NotFoundPage(Site site, this.path)
: super(site, '', '404 Not found', description: "'$path' not found.");
- Future generateContent(Map<String, String> params) async {}
+ Future generateContent(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
+ }
}
class OverlaysPage extends DiagnosticPageWithNav {
@@ -1004,6 +1043,8 @@
@override
Future generateContent(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
FileContentOverlay overlays = server.fileContentOverlay;
List<String> paths = overlays.paths.toList()..sort();
@@ -1047,6 +1088,8 @@
@override
Future generateContent(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
h3('Analysis plugins');
List<PluginInfo> analysisPlugins = server.pluginManager.plugins;
@@ -1108,6 +1151,8 @@
@override
Future generateContent(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
h3('Profiling performance tag data');
// prepare sorted tags
@@ -1242,6 +1287,8 @@
}
static Future<ServiceProtocol> connect(Uri uri) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
WebSocket socket = await WebSocket.connect(uri.toString());
return new ServiceProtocol._(socket);
}
@@ -1255,6 +1302,8 @@
@override
Future generateContent(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
DiagnosticsSite diagnosticsSite = site;
buf.writeln('<div class="columns">');
@@ -1293,6 +1342,8 @@
@override
Future generateContent(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// server domain
h3('Server domain subscriptions');
ul(ServerService.VALUES, (item) {
diff --git a/pkg/analysis_server/lib/src/status/pages.dart b/pkg/analysis_server/lib/src/status/pages.dart
index 8105117..d13e0de 100644
--- a/pkg/analysis_server/lib/src/status/pages.dart
+++ b/pkg/analysis_server/lib/src/status/pages.dart
@@ -31,6 +31,8 @@
String get path => '/$id';
Future<Null> asyncDiv(void gen(), {String classes}) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (classes != null) {
buf.writeln('<div class="$classes">');
} else {
@@ -55,6 +57,8 @@
}
Future<String> generate(Map<String, String> params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
buf.clear();
await generatePage(params);
return buf.toString();
@@ -139,6 +143,8 @@
Page createUnknownPage(String unknownPath);
Future<Null> handleGetRequest(HttpRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
try {
String path = request.uri.path;
@@ -174,6 +180,8 @@
Future<Null> respond(HttpRequest request, Page page,
[int code = HttpStatus.OK]) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
HttpResponse response = request.response;
response.statusCode = code;
response.headers.contentType = ContentType.HTML;
diff --git a/pkg/analysis_server/test/benchmarks_test.dart b/pkg/analysis_server/test/benchmarks_test.dart
index 5dd51fb..165760f 100644
--- a/pkg/analysis_server/test/benchmarks_test.dart
+++ b/pkg/analysis_server/test/benchmarks_test.dart
@@ -77,5 +77,5 @@
);
Map m = json.decode(result.stdout);
List benchmarks = m['benchmarks'];
- return benchmarks.map((b) => b['id']).toList();
+ return benchmarks.map((b) => b['id']).cast<String>().toList();
}
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index bdb6726..445d9fd 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -578,6 +578,8 @@
* DOCUMENTATION_COMMENT
* FILE_HEADER
* FUNCTION_BODY
+ * INVOCATION
+ * LITERAL
* }
*/
final Matcher isFoldingKind = new MatchesEnum("FoldingKind", [
@@ -586,7 +588,9 @@
"DIRECTIVES",
"DOCUMENTATION_COMMENT",
"FILE_HEADER",
- "FUNCTION_BODY"
+ "FUNCTION_BODY",
+ "INVOCATION",
+ "LITERAL"
]);
/**
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
index 024e565..f47d69d 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -533,15 +533,17 @@
}
Future<E> performAnalysis<E>(int times, Completer<E> completer) async {
+ // Await a microtask. Otherwise the futures are chained and would
+ // resolve linearly using up the stack.
+ await null;
if (completer.isCompleted) {
return completer.future;
}
// We use a delayed future to allow microtask events to finish. The
- // Future.value or Future() constructors use scheduleMicrotask themselves and
- // would therefore not wait for microtask callbacks that are scheduled after
- // invoking this method.
- return new Future.delayed(
- Duration.zero, () => performAnalysis(times - 1, completer));
+ // Future.value or Future.microtask() constructors use scheduleMicrotask
+ // themselves and would therefore not wait for microtask callbacks that
+ // are scheduled after invoking this method.
+ return new Future(() => performAnalysis(times - 1, completer));
}
void resolveSource(String path, String content) {
diff --git a/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart b/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart
index 0573853..55a9cff 100644
--- a/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart
@@ -231,6 +231,54 @@
''');
}
+ test_expression_selection() async {
+ addFlutterPackage();
+ await indexTestUnit('''
+import 'package:flutter/material.dart';
+
+Widget main() {
+ return new Container();
+}
+''');
+
+ Future<void> assertResult(String str) async {
+ int offset = findOffset(str);
+ _createRefactoring(offset, str.length);
+
+ await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+Widget main() {
+ return new Test();
+}
+
+class Test extends StatelessWidget {
+ const Test({
+ Key key,
+ }) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return new Container();
+ }
+}
+''');
+ }
+
+ await assertResult('Container');
+ await assertResult('new Container');
+ await assertResult('new Container(');
+ await assertResult('new Container()');
+ await assertResult('new Container();');
+ await assertResult('taine');
+ await assertResult('tainer');
+ await assertResult('tainer(');
+ await assertResult('tainer()');
+ await assertResult('turn new Container');
+ await assertResult('return new Container()');
+ await assertResult('return new Container();');
+ }
+
test_expression_topFunction() async {
addFlutterPackage();
await indexTestUnit('''
diff --git a/pkg/analysis_server/test/services/search/element_visitors_test.dart b/pkg/analysis_server/test/services/search/element_visitors_test.dart
new file mode 100644
index 0000000..ef2c208
--- /dev/null
+++ b/pkg/analysis_server/test/services/search/element_visitors_test.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/search/element_visitors.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../abstract_single_unit.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(FindElementByNameOffsetTest);
+ });
+}
+
+@reflectiveTest
+class FindElementByNameOffsetTest extends AbstractSingleUnitTest {
+ test_class() async {
+ await resolveTestUnit(r'''
+class AAA {}
+class BBB {}
+''');
+ _assertElement(6, ElementKind.CLASS, 'AAA');
+ _assertElement(19, ElementKind.CLASS, 'BBB');
+ }
+
+ test_function() async {
+ await resolveTestUnit(r'''
+void aaa() {}
+void bbb() {}
+''');
+ _assertElement(5, ElementKind.FUNCTION, 'aaa');
+ _assertElement(19, ElementKind.FUNCTION, 'bbb');
+ }
+
+ test_null() async {
+ await resolveTestUnit(r'''
+class AAA {}
+class BBB {}
+''');
+ expect(findElementByNameOffset(null, 0), isNull);
+
+ expect(findElementByNameOffset(testUnitElement, 0), isNull);
+ expect(findElementByNameOffset(testUnitElement, 1), isNull);
+
+ expect(findElementByNameOffset(testUnitElement, 5), isNull);
+ expect(findElementByNameOffset(testUnitElement, 7), isNull);
+ }
+
+ test_topLevelVariable() async {
+ await resolveTestUnit(r'''
+int aaa, bbb;
+int ccc;
+''');
+ _assertElement(4, ElementKind.TOP_LEVEL_VARIABLE, 'aaa');
+ _assertElement(9, ElementKind.TOP_LEVEL_VARIABLE, 'bbb');
+ _assertElement(18, ElementKind.TOP_LEVEL_VARIABLE, 'ccc');
+ }
+
+ void _assertElement(int nameOffset, ElementKind kind, String name) {
+ var element = findElementByNameOffset(testUnitElement, nameOffset);
+ expect(element, isNotNull);
+ expect(element.kind, kind);
+ expect(element.name, name);
+ }
+}
diff --git a/pkg/analysis_server/test/services/search/test_all.dart b/pkg/analysis_server/test/services/search/test_all.dart
index 0bc46de88..eed01b8 100644
--- a/pkg/analysis_server/test/services/search/test_all.dart
+++ b/pkg/analysis_server/test/services/search/test_all.dart
@@ -4,6 +4,7 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import 'element_visitors_test.dart' as element_visitors;
import 'hierarchy_test.dart' as hierarchy_test;
import 'search_engine_test.dart' as search_engine_test;
@@ -12,6 +13,7 @@
*/
main() {
defineReflectiveSuite(() {
+ element_visitors.main();
hierarchy_test.main();
search_engine_test.main();
}, name: 'search');
diff --git a/pkg/analysis_server/test/src/computer/folding_computer_test.dart b/pkg/analysis_server/test/src/computer/folding_computer_test.dart
index 55d864b..c301f7f 100644
--- a/pkg/analysis_server/test/src/computer/folding_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/folding_computer_test.dart
@@ -106,6 +106,119 @@
_compareRegions(regions, content);
}
+ test_invocations() async {
+ String content = """
+// Content before
+
+main() {/*1:INC*/
+ print(/*2:INC*/
+ "Hello, world!",
+ /*2:INC:INVOCATION*/);
+/*1:INC:FUNCTION_BODY*/}
+
+// Content after
+""";
+
+ final regions = await _computeRegions(content);
+ _compareRegions(regions, content);
+ }
+
+ test_function_expression_invocation() async {
+ String content = """
+// Content before
+
+getFunc() => (String a, String b) {/*1:INC*/
+ print(a);
+/*1:INC:FUNCTION_BODY*/};
+
+main2() {/*2:INC*/
+ getFunc()(/*3:INC*/
+ "one",
+ "two"
+ /*3:INC:INVOCATION*/);
+/*2:INC:FUNCTION_BODY*/}
+
+// Content after
+""";
+
+ final regions = await _computeRegions(content);
+ _compareRegions(regions, content);
+ }
+
+ test_constructor_invocations() async {
+ String content = """
+// Content before
+
+main() {/*1:INC*/
+ return new Text(/*2:INC*/
+ "Hello, world!",
+ /*2:INC:INVOCATION*/);
+/*1:INC:FUNCTION_BODY*/}
+
+// Content after
+""";
+
+ final regions = await _computeRegions(content);
+ _compareRegions(regions, content);
+ }
+
+ test_nested_invocations() async {
+ String content = """
+// Content before
+
+main() {/*1:INC*/
+ a(/*2:INC*/
+ b(/*3:INC*/
+ c(/*4:INC*/
+ d()
+ /*4:INC:INVOCATION*/),
+ /*3:INC:INVOCATION*/),
+ /*2:INC:INVOCATION*/);
+/*1:INC:FUNCTION_BODY*/}
+
+// Content after
+""";
+
+ final regions = await _computeRegions(content);
+ _compareRegions(regions, content);
+ }
+
+ test_literal_list() async {
+ String content = """
+// Content before
+
+main() {/*1:INC*/
+ final List<String> things = <String>[/*2:INC*/
+ "one",
+ "two"
+ /*2:INC:LITERAL*/];
+/*1:INC:FUNCTION_BODY*/}
+
+// Content after
+""";
+
+ final regions = await _computeRegions(content);
+ _compareRegions(regions, content);
+ }
+
+ test_literal_map() async {
+ String content = """
+// Content before
+
+main2() {/*1:INC*/
+ final Map<String, String> things = <String, String>{/*2:INC*/
+ "one": "one",
+ "two": "two"
+ /*2:INC:LITERAL*/};
+/*1:INC:FUNCTION_BODY*/}
+
+// Content after
+""";
+
+ final regions = await _computeRegions(content);
+ _compareRegions(regions, content);
+ }
+
test_nested_function() async {
String content = """
// Content before
diff --git a/pkg/analysis_server/test/src/plugin/plugin_watcher_test.dart b/pkg/analysis_server/test/src/plugin/plugin_watcher_test.dart
index 2b8b4ac..4798194 100644
--- a/pkg/analysis_server/test/src/plugin/plugin_watcher_test.dart
+++ b/pkg/analysis_server/test/src/plugin/plugin_watcher_test.dart
@@ -150,8 +150,8 @@
Future<Null> computeResult(String uri) {
FileState file = fsState.getFileForUri(Uri.parse(uri));
- AnalysisResult result = new AnalysisResult(
- this, null, file.path, null, true, null, null, null, null, null, null);
+ AnalysisResult result = new AnalysisResult(this, null, file.path, null,
+ true, null, null, false, null, null, null, null);
_resultController.add(result);
return new Future.delayed(new Duration(milliseconds: 1));
}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/FoldingKind.java b/pkg/analysis_server/tool/spec/generated/java/types/FoldingKind.java
index e4fdb2e..161aa76 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/FoldingKind.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/FoldingKind.java
@@ -27,4 +27,8 @@
public static final String FUNCTION_BODY = "FUNCTION_BODY";
+ public static final String INVOCATION = "INVOCATION";
+
+ public static final String LITERAL = "LITERAL";
+
}
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 7e8bc43..0173f12 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -7,7 +7,7 @@
<body>
<h1>Analysis Server API Specification</h1>
<h1 style="color:#999999">Version
- <version>1.20.3</version>
+ <version>1.20.4</version>
</h1>
<p>
This document contains a specification of the API provided by the
diff --git a/pkg/analyzer/lib/dart/analysis/results.dart b/pkg/analyzer/lib/dart/analysis/results.dart
index 91fd27c..635fe97 100644
--- a/pkg/analyzer/lib/dart/analysis/results.dart
+++ b/pkg/analyzer/lib/dart/analysis/results.dart
@@ -42,16 +42,11 @@
*
* Clients may not extend, implement or mix-in this class.
*/
-abstract class AnalysisResultWithErrors implements AnalysisResult {
+abstract class AnalysisResultWithErrors implements FileResult {
/**
* The analysis errors that were computed during analysis.
*/
List<AnalysisError> get errors;
-
- /**
- * Information about lines in the content.
- */
- LineInfo get lineInfo;
}
/**
@@ -63,6 +58,24 @@
abstract class ErrorsResult implements AnalysisResultWithErrors {}
/**
+ * The result of computing some cheap information for a single file, when full
+ * parsed file is not required, so [ParseResult] is not necessary.
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+abstract class FileResult implements AnalysisResult {
+ /**
+ * Whether the file is a part.
+ */
+ bool get isPart;
+
+ /**
+ * Information about lines in the content.
+ */
+ LineInfo get lineInfo;
+}
+
+/**
* The result of parsing of a single file. The errors returned include only
* those discovered during scanning and parsing.
*
diff --git a/pkg/analyzer/lib/dart/analysis/session.dart b/pkg/analyzer/lib/dart/analysis/session.dart
index dd8c595..3c4d9cf 100644
--- a/pkg/analyzer/lib/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/dart/analysis/session.dart
@@ -5,6 +5,7 @@
import 'dart:async';
import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/analysis/uri_converter.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/file_system/file_system.dart';
@@ -29,7 +30,10 @@
/**
* Return the source factory used to resolve URIs.
+ *
+ * Deprecated: Use the methods on [uriConverter] instead.
*/
+ @deprecated
SourceFactory get sourceFactory;
/**
@@ -44,6 +48,11 @@
Future<TypeSystem> get typeSystem;
/**
+ * Return the URI converter used to convert between URI's and file paths.
+ */
+ UriConverter get uriConverter;
+
+ /**
* Return a future that will complete with information about the errors
* contained in the file with the given absolute, normalized [path].
*
diff --git a/pkg/analyzer/lib/dart/analysis/uri_converter.dart b/pkg/analyzer/lib/dart/analysis/uri_converter.dart
new file mode 100644
index 0000000..ec1ed8d
--- /dev/null
+++ b/pkg/analyzer/lib/dart/analysis/uri_converter.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/**
+ * A utility class used to convert between URIs and absolute file paths.
+ */
+abstract class UriConverter {
+ /**
+ * Return the URI that should be used to reference the file at the absolute
+ * [path], or `null` if there is no valid way to reference the file in this
+ * converter’s context. The file at that path is not required to exist.
+ *
+ * If a [containingPath] is provided and both the [path] and [containingPath]
+ * are within the root of this converter’s context, then the returned URI will
+ * be a relative path. Otherwise, the returned URI will be an absolute URI.
+ *
+ * Throws an `ArgumentError` if the [path] is `null` or is not a valid
+ * absolute file path.
+ */
+ Uri pathToUri(String path, {String containingPath});
+
+ /**
+ * Return the absolute path of the file to which the absolute [uri] resolves,
+ * or `null` if the [uri] cannot be resolved in this converter’s context.
+ *
+ * Throws an `ArgumentError` if the [uri] is `null` or is not an absolute URI.
+ */
+ String uriToPath(Uri uri);
+}
diff --git a/pkg/analyzer/lib/file_system/memory_file_system.dart b/pkg/analyzer/lib/file_system/memory_file_system.dart
index 0c5c8b6..ea86f5a 100644
--- a/pkg/analyzer/lib/file_system/memory_file_system.dart
+++ b/pkg/analyzer/lib/file_system/memory_file_system.dart
@@ -105,6 +105,8 @@
@override
Future<List<int>> getModificationTimes(List<Source> sources) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return sources.map((source) {
String path = source.fullName;
return _pathToTimestamp[path] ?? -1;
diff --git a/pkg/analyzer/lib/file_system/physical_file_system.dart b/pkg/analyzer/lib/file_system/physical_file_system.dart
index db86404..6d9ae48 100644
--- a/pkg/analyzer/lib/file_system/physical_file_system.dart
+++ b/pkg/analyzer/lib/file_system/physical_file_system.dart
@@ -79,7 +79,7 @@
}
@override
- Context get pathContext => io.Platform.isWindows ? windows : posix;
+ Context get pathContext => context;
@override
File getFile(String path) {
@@ -95,6 +95,8 @@
@override
Future<List<int>> getModificationTimes(List<Source> sources) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<String> paths = sources.map((source) => source.fullName).toList();
return _pathsToTimes(paths);
}
diff --git a/pkg/analyzer/lib/instrumentation/file_instrumentation.dart b/pkg/analyzer/lib/instrumentation/file_instrumentation.dart
index fa3df82..1d42dfa 100644
--- a/pkg/analyzer/lib/instrumentation/file_instrumentation.dart
+++ b/pkg/analyzer/lib/instrumentation/file_instrumentation.dart
@@ -39,6 +39,8 @@
@override
Future shutdown() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
await _sink.close();
_sink = null;
}
diff --git a/pkg/analyzer/lib/instrumentation/instrumentation.dart b/pkg/analyzer/lib/instrumentation/instrumentation.dart
index 38bf416..dc04bf5 100644
--- a/pkg/analyzer/lib/instrumentation/instrumentation.dart
+++ b/pkg/analyzer/lib/instrumentation/instrumentation.dart
@@ -379,6 +379,8 @@
* should be invoked on this instance after this method has been invoked.
*/
Future shutdown() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (_instrumentationServer != null) {
await _instrumentationServer.shutdown();
_instrumentationServer = null;
@@ -473,6 +475,8 @@
@override
Future shutdown() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
for (InstrumentationServer server in _servers) {
await server.shutdown();
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/ast_provider_driver.dart b/pkg/analyzer/lib/src/dart/analysis/ast_provider_driver.dart
index 8cd0efa..21c2297 100644
--- a/pkg/analyzer/lib/src/dart/analysis/ast_provider_driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/ast_provider_driver.dart
@@ -20,12 +20,16 @@
@override
Future<SimpleIdentifier> getParsedNameForElement(Element element) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
CompilationUnit unit = await getParsedUnitForElement(element);
return _getNameNode(unit, element);
}
@override
Future<CompilationUnit> getParsedUnitForElement(Element element) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String path = element.source.fullName;
ParseResult parseResult = await driver.parseFile(path);
return parseResult.unit;
@@ -33,12 +37,16 @@
@override
Future<SimpleIdentifier> getResolvedNameForElement(Element element) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
CompilationUnit unit = await getResolvedUnitForElement(element);
return _getNameNode(unit, element);
}
@override
Future<CompilationUnit> getResolvedUnitForElement(Element element) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String path = element.source.fullName;
AnalysisResult analysisResult = await driver.getResult(path);
return analysisResult?.unit;
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 763beda..df71b24 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -95,7 +95,7 @@
/**
* The version of data format, should be incremented on every format change.
*/
- static const int DATA_VERSION = 60;
+ static const int DATA_VERSION = 61;
/**
* The number of exception contexts allowed to write. Once this field is
@@ -605,6 +605,7 @@
*/
Future<void> discoverAvailableFiles() {
_discoverAvailableFiles();
+ _scheduler.notify(this);
return _discoverAvailableFilesTask.completer.future;
}
@@ -642,6 +643,8 @@
* interactive analysis, such as Analysis Server or its plugins.
*/
Future<ErrorsResult> getErrors(String path) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
_throwIfNotAbsolutePath(path);
// Ask the analysis result without unit, so return cached errors.
@@ -662,7 +665,7 @@
}
return new ErrorsResult(currentSession, path, analysisResult.uri,
- analysisResult.lineInfo, analysisResult.errors);
+ analysisResult.lineInfo, analysisResult.isPart, analysisResult.errors);
}
/**
@@ -690,6 +693,18 @@
}
/**
+ * Return the [FileResult] for the Dart file with the given [path].
+ *
+ * The [path] must be absolute and normalized.
+ */
+ FileResult getFileSync(String path) {
+ _throwIfNotAbsolutePath(path);
+ FileState file = _fileTracker.verifyApiSignature(path);
+ return new FileResult(
+ _currentSession, path, file.uri, file.lineInfo, file.isPart);
+ }
+
+ /**
* Return a [Future] that completes with the [AnalysisDriverUnitIndex] for
* the file with the given [path], or with `null` if the file cannot be
* analyzed.
@@ -713,6 +728,8 @@
* store, or built for a file to which the given [uri] is resolved.
*/
Future<LibraryElement> getLibraryByUri(String uri) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (_externalSummaries != null && _externalSummaries.hasUnlinkedUnit(uri)) {
return LibraryContext.resynthesizeLibraryElement(analysisOptions,
declaredVariables, sourceFactory, _externalSummaries, uri);
@@ -731,23 +748,6 @@
}
/**
- * Return the cached [AnalysisDriverResolvedUnit] for the file with the given
- * [file], or `null` if the cache does not contain this information.
- */
- AnalysisDriverResolvedUnit getResolvedUnitObject(FileState file) {
- FileState library = file.isPart ? file.library : file;
- if (library != null) {
- String signature = _getResolvedUnitSignature(library, file);
- String key = _getResolvedUnitKey(signature);
- List<int> bytes = _byteStore.get(key);
- if (bytes != null) {
- return new AnalysisDriverResolvedUnit.fromBuffer(bytes);
- }
- }
- return null;
- }
-
- /**
* Return a [Future] that completes with a [AnalysisResult] for the Dart
* file with the given [path]. If the file is not a Dart file or cannot
* be analyzed, the [Future] completes with `null`.
@@ -801,6 +801,8 @@
* The [path] must be absolute and normalized.
*/
Future<SourceKind> getSourceKind(String path) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
_throwIfNotAbsolutePath(path);
if (AnalysisEngine.isDartFileName(path)) {
FileState file = _fsState.getFileForPath(path);
@@ -883,6 +885,8 @@
* resolved unit).
*/
Future<ParseResult> parseFile(String path) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return parseFileSync(path);
}
@@ -903,11 +907,13 @@
RecordingErrorListener listener = new RecordingErrorListener();
CompilationUnit unit = file.parse(listener);
return new ParseResult(currentSession, file.path, file.uri, file.content,
- unit.lineInfo, unit, listener.errors);
+ file.lineInfo, file.isPart, unit, listener.errors);
}
@override
Future<Null> performWork() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (_fileTracker.verifyChangedFilesIfNeeded()) {
return;
}
@@ -1194,6 +1200,8 @@
{bool withUnit: false,
bool asIsIfPartWithoutLibrary: false,
bool skipIfSameSignature: false}) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
FileState file = _fsState.getFileForPath(path);
// Prepare the library - the file itself, or the known library.
@@ -1230,6 +1238,8 @@
// We need the fully resolved unit, or the result is not cached.
return _logger.runAsync('Compute analysis result for $path', () async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
try {
LibraryContext libraryContext;
KernelContext kernelContext;
@@ -1316,6 +1326,8 @@
}
Future<AnalysisDriverUnitIndex> _computeIndex(String path) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AnalysisResult analysisResult = await _computeAnalysisResult(path,
withUnit: false, asIsIfPartWithoutLibrary: true);
return analysisResult._index;
@@ -1323,6 +1335,8 @@
Future<UnitElementResult> _computeUnitElement(String path,
{bool asIsIfPartWithoutLibrary: false}) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
FileState file = _fsState.getFileForPath(path);
// Prepare the library - the file itself, or the known library.
@@ -1393,6 +1407,8 @@
}
Future<KernelContext> _createKernelContext(FileState library) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return await KernelContext.forSingleLibrary(
library,
_logger,
@@ -1426,6 +1442,8 @@
* Return the context in which the [library] should be analyzed.
*/
Future<LibraryContext> _createLibraryContext(FileState library) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
_testView.numOfCreatedLibraryContexts++;
return new LibraryContext.forSingleLibrary(
library,
@@ -1494,6 +1512,7 @@
file.exists,
content,
file.lineInfo,
+ file.isPart,
signature,
resolvedUnit,
errors,
@@ -1583,6 +1602,7 @@
file.exists,
null,
file.lineInfo,
+ file.isPart,
null,
null,
[
@@ -1939,6 +1959,8 @@
* priority first.
*/
Future<Null> _run() async {
+ // Give other microtasks the time to run before doing the analysis cycle.
+ await null;
Stopwatch timer = new Stopwatch()..start();
PerformanceLogSection analysisSection;
while (true) {
@@ -2023,6 +2045,8 @@
Future<SummaryDataStore> getSummaryStore(String libraryPath) async {
FileState library = driver.fsState.getFileForPath(libraryPath);
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
LibraryContext libraryContext = await driver._createLibraryContext(library);
try {
return libraryContext.store;
@@ -2043,10 +2067,9 @@
* Every result is independent, and is not guaranteed to be consistent with
* any previously returned result, even inside of the same library.
*/
-class AnalysisResult extends BaseAnalysisResult
- implements results.ResolveResult {
+class AnalysisResult extends FileResult implements results.ResolveResult {
static final _UNCHANGED = new AnalysisResult(
- null, null, null, null, null, null, null, null, null, null, null);
+ null, null, null, null, null, null, null, null, null, null, null, null);
/**
* The [AnalysisDriver] that produced this result.
@@ -2066,9 +2089,6 @@
@override
final String content;
- @override
- final LineInfo lineInfo;
-
/**
* The signature of the result based on the content of the file, and the
* transitive closure of files imported and exported by the library of
@@ -2094,12 +2114,13 @@
Uri uri,
this.exists,
this.content,
- this.lineInfo,
+ LineInfo lineInfo,
+ bool isPart,
this._signature,
this.unit,
this.errors,
this._index)
- : super(driver?.currentSession, path, uri);
+ : super(driver?.currentSession, path, uri, lineInfo, isPart);
@override
LibraryElement get libraryElement => unit.element.library;
@@ -2157,16 +2178,13 @@
* to each other. But none of the results is guaranteed to be consistent with
* the state of the files.
*/
-class ErrorsResult extends BaseAnalysisResult implements results.ErrorsResult {
- @override
- final LineInfo lineInfo;
-
+class ErrorsResult extends FileResult implements results.ErrorsResult {
@override
final List<AnalysisError> errors;
- ErrorsResult(
- AnalysisSession session, String path, Uri uri, this.lineInfo, this.errors)
- : super(session, path, uri);
+ ErrorsResult(AnalysisSession session, String path, Uri uri, LineInfo lineInfo,
+ bool isPart, this.errors)
+ : super(session, path, uri, lineInfo, isPart);
@override
results.ResultState get state => results.ResultState.VALID;
@@ -2200,28 +2218,44 @@
}
/**
+ * The result of computing some cheap information for a single file, when full
+ * parsed file is not required, so [ParseResult] is not necessary.
+ */
+class FileResult extends BaseAnalysisResult implements results.FileResult {
+ @override
+ final LineInfo lineInfo;
+
+ @override
+ final bool isPart;
+
+ FileResult(
+ AnalysisSession session, String path, Uri uri, this.lineInfo, this.isPart)
+ : super(session, path, uri);
+
+ @override
+ results.ResultState get state => results.ResultState.VALID;
+}
+
+/**
* The result of parsing of a single file.
*
* These results are self-consistent, i.e. [content], [lineInfo], the
* parsed [unit] correspond to each other. But none of the results is
* guaranteed to be consistent with the state of the files.
*/
-class ParseResult extends BaseAnalysisResult implements results.ParseResult {
+class ParseResult extends FileResult implements results.ParseResult {
@override
final String content;
@override
- final LineInfo lineInfo;
-
- @override
final CompilationUnit unit;
@override
final List<AnalysisError> errors;
ParseResult(AnalysisSession session, String path, Uri uri, this.content,
- this.lineInfo, this.unit, this.errors)
- : super(session, path, uri);
+ LineInfo lineInfo, bool isPart, this.unit, this.errors)
+ : super(session, path, uri, lineInfo, isPart);
@override
results.ResultState get state => results.ResultState.VALID;
diff --git a/pkg/analyzer/lib/src/dart/analysis/frontend_resolution.dart b/pkg/analyzer/lib/src/dart/analysis/frontend_resolution.dart
index ba59397..8cfdda3 100644
--- a/pkg/analyzer/lib/src/dart/analysis/frontend_resolution.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/frontend_resolution.dart
@@ -223,12 +223,16 @@
}
return _runWithFrontEndContext('Compile', () async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
try {
var dillTarget =
new DillTarget(_options.ticker, uriTranslator, _options.target);
// Append all libraries what we still have in the current component.
await _logger.runAsync('Load dill libraries', () async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
dillTarget.loader.appendLibraries(_component);
await dillTarget.buildOutlines();
});
@@ -240,6 +244,8 @@
// Compile the entry point into the new component.
_component = await _logger.runAsync('Compile', () async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
await kernelTarget.buildOutlines(nameRoot: _component.root);
return await kernelTarget.buildComponent() ?? _component;
});
@@ -346,6 +352,8 @@
}
Future<T> _runWithFrontEndContext<T>(String msg, Future<T> f()) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return await CompilerContext.runWithOptions(_options, (context) {
context.disableColors();
return _logger.runAsync(msg, f);
@@ -488,17 +496,23 @@
@override
Future<bool> exists() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return file.exists;
}
@override
Future<List<int>> readAsBytes() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// TODO(scheglov) Optimize.
return utf8.encode(file.content);
}
@override
Future<String> readAsString() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return file.content;
}
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/index.dart b/pkg/analyzer/lib/src/dart/analysis/index.dart
index 9fd2e75..42792dc 100644
--- a/pkg/analyzer/lib/src/dart/analysis/index.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/index.dart
@@ -449,7 +449,8 @@
// These functions are not bound to a source, we cannot index them.
if (elementKind == ElementKind.PARAMETER &&
element is ParameterElement &&
- element.enclosingElement.isSynthetic) {
+ (element.enclosingElement == null ||
+ element.enclosingElement.isSynthetic)) {
return;
}
// Add the relation.
diff --git a/pkg/analyzer/lib/src/dart/analysis/kernel_context.dart b/pkg/analyzer/lib/src/dart/analysis/kernel_context.dart
index 5079277..868599ed 100644
--- a/pkg/analyzer/lib/src/dart/analysis/kernel_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/kernel_context.dart
@@ -78,7 +78,11 @@
SourceFactory sourceFactory,
FileSystemState fsState,
FrontEndCompiler compiler) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return logger.runAsync('Create kernel context', () async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
Uri targetUri = targetLibrary.uri;
LibraryCompilationResult compilationResult =
await compiler.compile(targetUri);
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index 0e6d519..a9090d2 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -96,7 +96,11 @@
* Compute analysis results for all units of the library.
*/
Future<Map<FileState, UnitAnalysisResult>> analyze() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return PerformanceStatistics.analysis.makeCurrentWhileAsync(() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (_useCFE) {
return await _analyze2();
} else {
@@ -181,7 +185,11 @@
}
Future<Map<FileState, UnitAnalysisResult>> _analyze2() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return await _logger.runAsync('Analyze', () async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
Map<FileState, CompilationUnit> units = {};
// Parse all files.
@@ -683,8 +691,8 @@
.resolve(unit, unitElement);
if (_libraryElement.context.analysisOptions.previewDart2) {
- unit.accept(new AstRewriteVisitor(_libraryElement, source, _typeProvider,
- AnalysisErrorListener.NULL_LISTENER));
+ unit.accept(new AstRewriteVisitor(_context.typeSystem, _libraryElement,
+ source, _typeProvider, AnalysisErrorListener.NULL_LISTENER));
}
// TODO(scheglov) remove EnumMemberBuilder class
@@ -737,8 +745,8 @@
.resolve(unit, unitElement);
if (_libraryElement.context.analysisOptions.previewDart2) {
- unit.accept(new AstRewriteVisitor(_libraryElement, file.source,
- _typeProvider, AnalysisErrorListener.NULL_LISTENER));
+ unit.accept(new AstRewriteVisitor(_context.typeSystem, _libraryElement,
+ file.source, _typeProvider, AnalysisErrorListener.NULL_LISTENER));
}
for (var declaration in unit.declarations) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/mutex.dart b/pkg/analyzer/lib/src/dart/analysis/mutex.dart
index 562d56f..864e616 100644
--- a/pkg/analyzer/lib/src/dart/analysis/mutex.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/mutex.dart
@@ -24,6 +24,8 @@
///
/// Returns a [Future] that will be completed when the lock has been acquired.
Future<Null> acquire() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
while (_lock != null) {
await _lock.future;
}
@@ -32,6 +34,8 @@
/// Run the given [criticalSection] with acquired mutex.
Future<T> guard<T>(Future<T> criticalSection()) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
await acquire();
try {
return await criticalSection();
diff --git a/pkg/analyzer/lib/src/dart/analysis/search.dart b/pkg/analyzer/lib/src/dart/analysis/search.dart
index 1212bdc..d308de5 100644
--- a/pkg/analyzer/lib/src/dart/analysis/search.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/search.dart
@@ -82,6 +82,8 @@
* Returns class members with the given [name].
*/
Future<List<Element>> classMembers(String name) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<Element> elements = <Element>[];
void addElement(Element element) {
@@ -118,6 +120,8 @@
Future<List<Declaration>> declarations(
RegExp regExp, int maxResults, LinkedHashSet<String> files,
{String onlyForFile}) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<Declaration> declarations = <Declaration>[];
DeclarationKind getExecutableKind(
@@ -286,6 +290,8 @@
*/
Future<List<SearchResult>> references(
Element element, SearchedFiles searchedFiles) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (element == null) {
return const <SearchResult>[];
}
@@ -305,23 +311,24 @@
return _searchReferences_Field(element, searchedFiles);
} else if (kind == ElementKind.FUNCTION || kind == ElementKind.METHOD) {
if (element.enclosingElement is ExecutableElement) {
- return _searchReferences_Local(element, (n) => n is Block);
+ return _searchReferences_Local(
+ element, (n) => n is Block, searchedFiles);
}
return _searchReferences_Function(element, searchedFiles);
} else if (kind == ElementKind.IMPORT) {
- return _searchReferences_Import(element);
+ return _searchReferences_Import(element, searchedFiles);
} else if (kind == ElementKind.LABEL ||
kind == ElementKind.LOCAL_VARIABLE) {
- return _searchReferences_Local(element, (n) => n is Block);
+ return _searchReferences_Local(element, (n) => n is Block, searchedFiles);
} else if (kind == ElementKind.LIBRARY) {
- return _searchReferences_Library(element);
+ return _searchReferences_Library(element, searchedFiles);
} else if (kind == ElementKind.PARAMETER) {
return _searchReferences_Parameter(element, searchedFiles);
} else if (kind == ElementKind.PREFIX) {
- return _searchReferences_Prefix(element);
+ return _searchReferences_Prefix(element, searchedFiles);
} else if (kind == ElementKind.TYPE_PARAMETER) {
return _searchReferences_Local(
- element, (n) => n.parent is CompilationUnit);
+ element, (n) => n.parent is CompilationUnit, searchedFiles);
}
return const <SearchResult>[];
}
@@ -335,6 +342,8 @@
*/
Future<List<SearchResult>> subTypes(
ClassElement type, SearchedFiles searchedFiles) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (type == null) {
return const <SearchResult>[];
}
@@ -352,6 +361,8 @@
*/
Future<List<SubtypeResult>> subtypes(
{ClassElement type, SubtypeResult subtype}) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String name;
String id;
if (type != null) {
@@ -366,13 +377,15 @@
id = subtype.id;
}
+ await _driver.discoverAvailableFiles();
+
List<SubtypeResult> results = [];
- for (String path in _driver.addedFiles) {
+ for (String path in _driver.knownFiles) {
FileState file = _driver.fsState.getFileForPath(path);
if (file.subtypedNames.contains(name)) {
- AnalysisDriverResolvedUnit unit = _driver.getResolvedUnitObject(file);
- if (unit != null) {
- for (AnalysisDriverSubtype subtype in unit.index.subtypes) {
+ AnalysisDriverUnitIndex index = await _driver.getIndex(path);
+ if (index != null) {
+ for (AnalysisDriverSubtype subtype in index.subtypes) {
if (subtype.supertypes.contains(id)) {
FileState library = file.isPart ? file.library : file;
results.add(new SubtypeResult(
@@ -393,6 +406,8 @@
* Returns top-level elements with names matching the given [regExp].
*/
Future<List<Element>> topLevelElements(RegExp regExp) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<Element> elements = <Element>[];
void addElement(Element element) {
@@ -422,6 +437,8 @@
*/
Future<List<SearchResult>> unresolvedMemberReferences(
String name, SearchedFiles searchedFiles) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (name == null) {
return const <SearchResult>[];
}
@@ -459,6 +476,8 @@
Element element,
SearchedFiles searchedFiles,
Map<IndexRelationKind, SearchResultKind> relationToResultKind) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// Prepare the element name.
String name = element.displayName;
if (element is ConstructorElement) {
@@ -470,7 +489,7 @@
String path = element.source.fullName;
if (name.startsWith('_')) {
String libraryPath = element.library.source.fullName;
- if (_driver.addedFiles.contains(libraryPath)) {
+ if (searchedFiles.add(libraryPath, this)) {
FileState library = _driver.fsState.getFileForPath(libraryPath);
List<FileState> candidates = [library]..addAll(library.partedFiles);
for (FileState file in candidates) {
@@ -502,6 +521,8 @@
Element element,
Map<IndexRelationKind, SearchResultKind> relationToResultKind,
String file) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AnalysisDriverUnitIndex index = await _driver.getIndex(file);
if (index != null) {
_IndexRequest request = new _IndexRequest(index);
@@ -515,12 +536,16 @@
}
Future<CompilationUnitElement> _getUnitElement(String file) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
UnitElementResult result = await _driver.getUnitElement(file);
return result?.element;
}
Future<List<SearchResult>> _searchReferences(
Element element, SearchedFiles searchedFiles) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<SearchResult> results = <SearchResult>[];
await _addResults(results, element, searchedFiles,
const {IndexRelationKind.IS_REFERENCED_BY: SearchResultKind.REFERENCE});
@@ -529,6 +554,8 @@
Future<List<SearchResult>> _searchReferences_CompilationUnit(
CompilationUnitElement element) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String path = element.source.fullName;
// If the path is not known, then the file is not referenced.
@@ -557,6 +584,8 @@
Future<List<SearchResult>> _searchReferences_Field(
PropertyInducingElement field, SearchedFiles searchedFiles) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<SearchResult> results = <SearchResult>[];
PropertyAccessorElement getter = field.getter;
PropertyAccessorElement setter = field.setter;
@@ -581,6 +610,8 @@
Future<List<SearchResult>> _searchReferences_Function(
Element element, SearchedFiles searchedFiles) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (element is Member) {
element = (element as Member).baseElement;
}
@@ -594,6 +625,8 @@
Future<List<SearchResult>> _searchReferences_Getter(
PropertyAccessorElement getter, SearchedFiles searchedFiles) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<SearchResult> results = <SearchResult>[];
await _addResults(results, getter, searchedFiles, const {
IndexRelationKind.IS_REFERENCED_BY: SearchResultKind.REFERENCE,
@@ -603,10 +636,11 @@
}
Future<List<SearchResult>> _searchReferences_Import(
- ImportElement element) async {
- // Search only in drivers to which the library was added.
+ ImportElement element, SearchedFiles searchedFiles) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String path = element.source.fullName;
- if (!_driver.addedFiles.contains(path)) {
+ if (!searchedFiles.add(path, this)) {
return const <SearchResult>[];
}
@@ -624,10 +658,11 @@
}
Future<List<SearchResult>> _searchReferences_Library(
- LibraryElement element) async {
- // Search only in drivers to which the library with the prefix was added.
+ LibraryElement element, SearchedFiles searchedFiles) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String path = element.source.fullName;
- if (!_driver.addedFiles.contains(path)) {
+ if (!searchedFiles.add(path, this)) {
return const <SearchResult>[];
}
@@ -651,10 +686,12 @@
return results;
}
- Future<List<SearchResult>> _searchReferences_Local(
- Element element, bool isRootNode(AstNode n)) async {
+ Future<List<SearchResult>> _searchReferences_Local(Element element,
+ bool isRootNode(AstNode n), SearchedFiles searchedFiles) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String path = element.source.fullName;
- if (!_driver.addedFiles.contains(path)) {
+ if (!searchedFiles.add(path, this)) {
return const <SearchResult>[];
}
@@ -686,11 +723,17 @@
Future<List<SearchResult>> _searchReferences_Parameter(
ParameterElement parameter, SearchedFiles searchedFiles) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<SearchResult> results = <SearchResult>[];
- results.addAll(await _searchReferences_Local(parameter, (AstNode node) {
- AstNode parent = node.parent;
- return parent is ClassDeclaration || parent is CompilationUnit;
- }));
+ results.addAll(await _searchReferences_Local(
+ parameter,
+ (AstNode node) {
+ AstNode parent = node.parent;
+ return parent is ClassDeclaration || parent is CompilationUnit;
+ },
+ searchedFiles,
+ ));
if (parameter.isOptional) {
results.addAll(await _searchReferences(parameter, searchedFiles));
}
@@ -698,10 +741,11 @@
}
Future<List<SearchResult>> _searchReferences_Prefix(
- PrefixElement element) async {
- // Search only in drivers to which the library with the prefix was added.
+ PrefixElement element, SearchedFiles searchedFiles) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String path = element.source.fullName;
- if (!_driver.addedFiles.contains(path)) {
+ if (!searchedFiles.add(path, this)) {
return const <SearchResult>[];
}
@@ -1017,6 +1061,8 @@
int elementId,
Map<IndexRelationKind, SearchResultKind> relationToResultKind,
Future<CompilationUnitElement> getEnclosingUnitElement()) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// Find the first usage of the element.
int i = _findFirstOccurrence(index.usedElements, elementId);
if (i == -1) {
@@ -1088,6 +1134,8 @@
String name,
Map<IndexRelationKind, SearchResultKind> relationToResultKind,
Future<CompilationUnitElement> getEnclosingUnitElement()) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// Find the name identifier.
int nameId = getStringId(name);
if (nameId == -1) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/session.dart b/pkg/analyzer/lib/src/dart/analysis/session.dart
index f627fa8..10d76e5 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session.dart
@@ -6,10 +6,12 @@
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/analysis/uri_converter.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/driver.dart' as driver;
import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
+import 'package:analyzer/src/dart/analysis/uri_converter.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
@@ -33,6 +35,11 @@
TypeSystem _typeSystem;
/**
+ * The URI converter used to convert between URI's and file paths.
+ */
+ UriConverter _uriConverter;
+
+ /**
* The cache of libraries for URIs.
*/
final Map<String, LibraryElement> _uriToLibraryCache = {};
@@ -50,6 +57,8 @@
@override
Future<TypeProvider> get typeProvider async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
_checkConsistency();
if (_typeProvider == null) {
LibraryElement coreLibrary = await _driver.getLibraryByUri('dart:core');
@@ -61,6 +70,8 @@
@override
Future<TypeSystem> get typeSystem async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
_checkConsistency();
if (_typeSystem == null) {
if (_driver.analysisOptions.strongMode) {
@@ -73,6 +84,11 @@
}
@override
+ UriConverter get uriConverter {
+ return _uriConverter ??= new DriverBasedUriConverter(_driver);
+ }
+
+ @override
Future<ErrorsResult> getErrors(String path) {
_checkConsistency();
return _driver.getErrors(path);
@@ -80,6 +96,8 @@
@override
Future<LibraryElement> getLibraryByUri(String uri) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
_checkConsistency();
var libraryElement = _uriToLibraryCache[uri];
if (libraryElement == null) {
@@ -91,6 +109,8 @@
@override
Future<ParseResult> getParsedAst(String path) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return getParsedAstSync(path);
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/session_helper.dart b/pkg/analyzer/lib/src/dart/analysis/session_helper.dart
index 758fe29..e35ec6a 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session_helper.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session_helper.dart
@@ -21,6 +21,8 @@
/// from the library with the given [libraryUri], or `null` if the library
/// does not export a class with such name.
Future<ClassElement> getClass(String libraryUri, String className) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var libraryElement = await session.getLibraryByUri(libraryUri);
var element = libraryElement.exportNamespace.get(className);
if (element is ClassElement) {
@@ -35,6 +37,8 @@
/// library does not export a top-level accessor with such name.
Future<PropertyAccessorElement> getTopLevelPropertyAccessor(
String uri, String name) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var libraryElement = await session.getLibraryByUri(uri);
var element = libraryElement.exportNamespace.get(name);
if (element is PropertyAccessorElement) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/status.dart b/pkg/analyzer/lib/src/dart/analysis/status.dart
index 5759b5e..cc2ad45 100644
--- a/pkg/analyzer/lib/src/dart/analysis/status.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/status.dart
@@ -43,6 +43,8 @@
* Return a [Future] that completes when [notify] is called at least once.
*/
Future<Null> get signal async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
await _completer.future;
_completer = new Completer<Null>();
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/uri_converter.dart b/pkg/analyzer/lib/src/dart/analysis/uri_converter.dart
new file mode 100644
index 0000000..df11c02
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/analysis/uri_converter.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/analysis/uri_converter.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:path/src/context.dart';
+
+/**
+ * An implementation of a URI converter based on an analysis driver.
+ */
+class DriverBasedUriConverter implements UriConverter {
+ /**
+ * The driver associated with the context in which the conversion will occur.
+ */
+ final AnalysisDriver driver;
+
+ /**
+ * Initialize a newly created URI converter to use the given [context] and
+ * [driver] to perform the conversions.
+ */
+ DriverBasedUriConverter(this.driver);
+
+ @override
+ Uri pathToUri(String path, {String containingPath}) {
+ ResourceProvider provider = driver.resourceProvider;
+ if (containingPath != null) {
+ Context context = provider.pathContext;
+ String root = driver.contextRoot.root;
+ if (context.isWithin(root, path) &&
+ context.isWithin(root, containingPath)) {
+ String relativePath =
+ context.relative(path, from: context.dirname(containingPath));
+ if (context.isRelative(relativePath)) {
+ return new Uri.file(relativePath);
+ }
+ }
+ }
+ Source source = provider.getFile(path).createSource();
+ return driver.sourceFactory.restoreUri(source);
+ }
+
+ @override
+ String uriToPath(Uri uri) => driver.sourceFactory.forUri2(uri).fullName;
+}
diff --git a/pkg/analyzer/lib/src/dart/element/builder.dart b/pkg/analyzer/lib/src/dart/element/builder.dart
index ce9381b..e0101c1 100644
--- a/pkg/analyzer/lib/src/dart/element/builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/builder.dart
@@ -217,6 +217,7 @@
constantField.isStatic = true;
constantField.isConst = true;
constantField.type = enumType;
+ constantField.metadata = _createElementAnnotations(constant.metadata);
setElementDocumentationComment(constantField, constant);
fields.add(constantField);
new PropertyAccessorElementImpl_ImplicitGetter(constantField);
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 883fb08..a15908f 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -2101,6 +2101,19 @@
}
@override
+ List<ElementAnnotation> get metadata {
+ if (_kernel != null) {
+ _metadata ??=
+ enclosingUnit._kernelContext.buildAnnotations(_kernel.annotations);
+ }
+ if (_unlinkedEnumValue != null) {
+ return _metadata ??=
+ _buildAnnotations(enclosingUnit, _unlinkedEnumValue.annotations);
+ }
+ return super.metadata;
+ }
+
+ @override
String get name {
if (_kernelEnumValue != null) {
return _kernelEnumValue.name.name;
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index e0a73ba..d9d126a 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -19,6 +19,27 @@
import 'package:analyzer/src/summary/resynthesize.dart'
show RecursiveInstantiateToBounds;
+/// Transforms the given [list] by applying [transform] to all its elements.
+///
+/// If no changes are made (i.e. the return value of [transform] is identical
+/// to its parameter each time it is invoked), the original list is returned.
+List<T> _transformOrShare<T>(List<T> list, T Function(T) transform) {
+ var length = list.length;
+ for (int i = 0; i < length; i++) {
+ var item = list[i];
+ var transformed = transform(item);
+ if (!identical(item, transformed)) {
+ var newList = list.toList();
+ newList[i] = transformed;
+ for (i++; i < length; i++) {
+ newList[i] = transform(list[i]);
+ }
+ return newList;
+ }
+ }
+ return list;
+}
+
/**
* Type of callbacks used by [DeferredFunctionTypeImpl].
*/
@@ -80,7 +101,7 @@
* function type.
*/
class CircularFunctionTypeImpl extends DynamicTypeImpl
- implements FunctionTypeImpl {
+ implements _FunctionTypeImplLazy {
CircularFunctionTypeImpl() : super._circular();
@override
@@ -237,7 +258,7 @@
* resynthesized from a summary. The actual underlying element won't be
* constructed until it's needed.
*/
-class DeferredFunctionTypeImpl extends FunctionTypeImpl {
+class DeferredFunctionTypeImpl extends _FunctionTypeImplLazy {
/**
* Callback which should be invoked when the element associated with this
* function type is needed.
@@ -335,43 +356,7 @@
/**
* The type of a function, method, constructor, getter, or setter.
*/
-class FunctionTypeImpl extends TypeImpl implements FunctionType {
- /**
- * The list of [typeArguments].
- */
- List<DartType> _typeArguments;
-
- /**
- * The list of [typeParameters], if it has been computed already. Otherwise
- * `null`.
- */
- List<TypeParameterElement> _typeParameters;
-
- /**
- * The return type of the function, or `null` if the return type should be
- * accessed through the element.
- */
- final DartType _returnType;
-
- /**
- * The parameters to the function, or `null` if the parameters should be
- * accessed through the element.
- */
- final List<ParameterElement> _parameters;
-
- /**
- * True if this type is the result of instantiating type parameters (and thus
- * any type parameters bound by the typedef should be considered part of
- * [typeParameters] rather than [typeFormals]).
- */
- final bool _isInstantiated;
-
- /**
- * The set of typedefs which should not be expanded when exploring this type,
- * to avoid creating infinite types in response to self-referential typedefs.
- */
- final List<FunctionTypeAliasElement> prunedTypedefs;
-
+abstract class FunctionTypeImpl extends TypeImpl implements FunctionType {
/**
* Initialize a newly created function type to be declared by the given
* [element], and also initialize [typeArguments] to match the
@@ -381,7 +366,8 @@
if (element is FunctionTypeAliasElement) {
throw new StateError('Use FunctionTypeImpl.forTypedef for typedefs');
}
- return new FunctionTypeImpl._(element, null, null, null, null, null, false);
+ return new _FunctionTypeImplLazy._(
+ element, null, null, null, null, null, false);
}
/**
@@ -392,8 +378,8 @@
*/
factory FunctionTypeImpl.forTypedef(FunctionTypeAliasElement element,
{List<DartType> typeArguments}) {
- return new FunctionTypeImpl._(element, element?.name, null, typeArguments,
- null, null, typeArguments != null);
+ return new _FunctionTypeImplLazy._(element, element?.name, null,
+ typeArguments, null, null, typeArguments != null);
}
/**
@@ -454,30 +440,16 @@
return function.type = new FunctionTypeImpl(function);
}
- /**
- * Private constructor.
- */
- FunctionTypeImpl._(
- FunctionTypedElement element,
- String name,
- this.prunedTypedefs,
- this._typeArguments,
- this._returnType,
- this._parameters,
- this._isInstantiated)
- : _typeParameters = null,
- super(element, name);
+ /// Creates a function type that's not associated with any element in the
+ /// element tree.
+ factory FunctionTypeImpl.synthetic(
+ DartType returnType,
+ List<TypeParameterElement> typeFormals,
+ List<ParameterElement> parameters) {
+ return new _FunctionTypeImplStrict._(returnType, typeFormals, parameters);
+ }
- /**
- * Return the base parameter elements of this function element.
- */
- List<ParameterElement> get baseParameters =>
- _parameters ?? element.parameters;
-
- /**
- * Return the return type defined by this function's element.
- */
- DartType get baseReturnType => _returnType ?? element.returnType;
+ FunctionTypeImpl._(Element element, String name) : super(element, name);
@deprecated
@override
@@ -554,7 +526,7 @@
/**
* Return `true` if this type is the result of instantiating type parameters.
*/
- bool get isInstantiated => _isInstantiated;
+ bool get isInstantiated;
@override
Map<String, DartType> get namedParameterTypes {
@@ -569,33 +541,7 @@
* Determine the new set of typedefs which should be pruned when expanding
* this function type.
*/
- List<FunctionTypeAliasElement> get newPrune {
- Element element = this.element;
- if (element is GenericFunctionTypeElement) {
- element = (element as GenericFunctionTypeElement).enclosingElement;
- }
- if (element is FunctionTypeAliasElement && !element.isSynthetic) {
- // This typedef should be pruned, along with anything that was previously
- // pruned.
- if (prunedTypedefs == null) {
- return <FunctionTypeAliasElement>[element];
- } else {
- return new List<FunctionTypeAliasElement>.from(prunedTypedefs)
- ..add(element);
- }
- } else {
- // This is not a typedef, so nothing additional needs to be pruned.
- return prunedTypedefs;
- }
- }
-
- @override
- List<String> get normalParameterNames {
- return baseParameters
- .where((parameter) => parameter.isNotOptional)
- .map((parameter) => parameter.name)
- .toList();
- }
+ List<FunctionTypeAliasElement> get newPrune;
@override
List<DartType> get normalParameterTypes {
@@ -607,14 +553,6 @@
}
@override
- List<String> get optionalParameterNames {
- return baseParameters
- .where((parameter) => parameter.isOptionalPositional)
- .map((parameter) => parameter.name)
- .toList();
- }
-
- @override
List<DartType> get optionalParameterTypes {
List<DartType> types = <DartType>[];
_forEachParameterType(ParameterKind.POSITIONAL, (name, type) {
@@ -623,135 +561,11 @@
return types;
}
- @override
- List<ParameterElement> get parameters {
- List<ParameterElement> baseParameters = this.baseParameters;
- // no parameters, quick return
- int parameterCount = baseParameters.length;
- if (parameterCount == 0) {
- return baseParameters;
- }
-
- // create specialized parameters
- var specializedParams = new List<ParameterElement>(parameterCount);
-
- var parameterTypes = TypeParameterTypeImpl.getTypes(typeParameters);
- for (int i = 0; i < parameterCount; i++) {
- var parameter = baseParameters[i];
- if (parameter?.type == null) {
- specializedParams[i] = parameter;
- continue;
- }
-
- // Check if parameter type depends on defining type type arguments, or
- // if it needs to be pruned.
-
- if (parameter is FieldFormalParameterElement) {
- // TODO(jmesserly): this seems like it won't handle pruning correctly.
- specializedParams[i] = new FieldFormalParameterMember(parameter, this);
- continue;
- }
- var baseType = parameter.type as TypeImpl;
- TypeImpl type;
- if (typeArguments.isEmpty ||
- typeArguments.length != typeParameters.length) {
- type = baseType.pruned(newPrune);
- } else {
- type = baseType.substitute2(typeArguments, parameterTypes, newPrune);
- }
-
- specializedParams[i] = identical(type, baseType)
- ? parameter
- : new ParameterMember(parameter, this, type);
- }
- return specializedParams;
- }
-
- @override
- DartType get returnType {
- DartType baseReturnType = this.baseReturnType;
- if (baseReturnType == null) {
- // TODO(brianwilkerson) This is a patch. The return type should never be
- // null and we need to understand why it is and fix it.
- return DynamicTypeImpl.instance;
- }
- // If there are no arguments to substitute, or if the arguments size doesn't
- // match the parameter size, return the base return type.
- if (typeArguments.length == 0 ||
- typeArguments.length != typeParameters.length) {
- return (baseReturnType as TypeImpl).pruned(newPrune);
- }
- return (baseReturnType as TypeImpl).substitute2(typeArguments,
- TypeParameterTypeImpl.getTypes(typeParameters), newPrune);
- }
-
/**
- * A list containing the actual types of the type arguments.
+ * The set of typedefs which should not be expanded when exploring this type,
+ * to avoid creating infinite types in response to self-referential typedefs.
*/
- List<DartType> get typeArguments {
- if (_typeArguments == null) {
- // TODO(jmesserly): reuse TypeParameterTypeImpl.getTypes once we can
- // make it generic, which will allow it to return List<DartType> instead
- // of List<TypeParameterType>.
- if (typeParameters.isEmpty) {
- _typeArguments = DartType.EMPTY_LIST;
- } else {
- _typeArguments = new List<DartType>.from(
- typeParameters.map((t) => t.type),
- growable: false);
- }
- }
- return _typeArguments;
- }
-
- @override
- List<TypeParameterElement> get typeFormals {
- if (_isInstantiated || element == null) {
- return TypeParameterElement.EMPTY_LIST;
- }
- List<TypeParameterElement> baseTypeFormals = element.typeParameters;
- int formalCount = baseTypeFormals.length;
- if (formalCount == 0) {
- return TypeParameterElement.EMPTY_LIST;
- }
-
- // Create type formals with specialized bounds.
- // For example `<U extends T>` where T comes from an outer scope.
- return TypeParameterMember.from(baseTypeFormals, this);
- }
-
- @override
- List<TypeParameterElement> get typeParameters {
- if (_typeParameters == null) {
- // Combine the generic type variables from all enclosing contexts, except
- // for this generic function's type variables. Those variables are
- // tracked in [boundTypeParameters].
- _typeParameters = <TypeParameterElement>[];
-
- Element e = element;
- while (e != null) {
- // If a static method, skip the enclosing class type parameters.
- if (e is MethodElement && e.isStatic) {
- e = e.enclosingElement;
- }
- e = e.enclosingElement;
- if (e is TypeParameterizedElement) {
- _typeParameters.addAll(e.typeParameters);
- }
- }
-
- if (_isInstantiated) {
- // Once the type has been instantiated, type parameters defined at the
- // site of the declaration of the method are no longer considered part
- // [boundTypeParameters]; they are part of [typeParameters].
- List<TypeParameterElement> parametersToAdd = element?.typeParameters;
- if (parametersToAdd != null) {
- _typeParameters.addAll(parametersToAdd);
- }
- }
- }
- return _typeParameters;
- }
+ List<FunctionTypeAliasElement> get prunedTypedefs;
@override
bool operator ==(Object object) {
@@ -763,8 +577,8 @@
// To test this, we instantiate both types with the same (unique) type
// variables, and see if the result is equal.
if (typeFormals.isNotEmpty) {
- List<DartType> freshVariables =
- relateTypeFormals(this, object, (t, s, _, __) => t == s);
+ List<DartType> freshVariables = FunctionTypeImpl.relateTypeFormals(
+ this, object, (t, s, _, __) => t == s);
if (freshVariables == null) {
return false;
}
@@ -901,30 +715,7 @@
}
@override
- FunctionTypeImpl instantiate(List<DartType> argumentTypes) {
- if (argumentTypes.length != typeFormals.length) {
- throw new ArgumentError(
- "argumentTypes.length (${argumentTypes.length}) != "
- "typeFormals.length (${typeFormals.length})");
- }
- if (argumentTypes.isEmpty) {
- return this;
- }
-
- // Given:
- // {U/T} <S> T -> S
- // Where {U/T} represents the typeArguments (U) and typeParameters (T) list,
- // and <S> represents the typeFormals.
- //
- // Now instantiate([V]), and the result should be:
- // {U/T, V/S} T -> S.
- List<DartType> newTypeArgs = <DartType>[];
- newTypeArgs.addAll(typeArguments);
- newTypeArgs.addAll(argumentTypes);
-
- return new FunctionTypeImpl._(element, name, prunedTypedefs, newTypeArgs,
- _returnType, _parameters, true);
- }
+ FunctionTypeImpl instantiate(List<DartType> argumentTypes);
@override
bool isAssignableTo(DartType type) {
@@ -943,8 +734,8 @@
// To test this, we instantiate both types with the same (unique) type
// variables, and see if the result is equal.
if (typeFormals.isNotEmpty) {
- List<DartType> freshVariables =
- relateTypeFormals(this, other, (t, s, _, __) => t == s);
+ List<DartType> freshVariables = FunctionTypeImpl.relateTypeFormals(
+ this, other, (t, s, _, __) => t == s);
if (freshVariables == null) {
return false;
}
@@ -967,7 +758,7 @@
[bool withDynamic = false, Set<Element> visitedElements]) {
// Note: visitedElements is only used for breaking recursion in the type
// hierarchy; we don't use it when recursing into the function type.
- return relate(
+ return FunctionTypeImpl.relate(
this,
type,
(DartType t, DartType s) =>
@@ -978,7 +769,7 @@
@override
bool isSubtypeOf(DartType type) {
var typeSystem = new TypeSystemImpl(null);
- return relate(
+ return FunctionTypeImpl.relate(
typeSystem.instantiateToBounds(this),
typeSystem.instantiateToBounds(type),
(DartType t, DartType s) => t.isAssignableTo(s),
@@ -986,48 +777,9 @@
}
@override
- FunctionTypeImpl pruned(List<FunctionTypeAliasElement> prune) {
- if (prune == null) {
- return this;
- } else if (prune.contains(element) ||
- prune.contains(element.enclosingElement)) {
- // Circularity found. Prune the type declaration.
- return new CircularFunctionTypeImpl();
- } else {
- // There should never be a reason to prune a type that has already been
- // pruned, since pruning is only done when expanding a function type
- // alias, and function type aliases are always expanded by starting with
- // base types.
- assert(this.prunedTypedefs == null);
- List<DartType> typeArgs = typeArguments
- .map((DartType t) => (t as TypeImpl).pruned(prune))
- .toList(growable: false);
- return new FunctionTypeImpl._(element, name, prune, typeArgs, _returnType,
- _parameters, _isInstantiated);
- }
- }
-
- @override
FunctionType substitute2(
List<DartType> argumentTypes, List<DartType> parameterTypes,
- [List<FunctionTypeAliasElement> prune]) {
- if (argumentTypes.length != parameterTypes.length) {
- throw new ArgumentError(
- "argumentTypes.length (${argumentTypes.length}) != parameterTypes.length (${parameterTypes.length})");
- }
- Element element = this.element;
- if (prune != null && prune.contains(element)) {
- // Circularity found. Prune the type declaration.
- return new CircularFunctionTypeImpl();
- }
- if (argumentTypes.length == 0) {
- return this.pruned(prune);
- }
- List<DartType> typeArgs =
- TypeImpl.substitute(typeArguments, argumentTypes, parameterTypes);
- return new FunctionTypeImpl._(element, name, prune, typeArgs, _returnType,
- _parameters, _isInstantiated);
- }
+ [List<FunctionTypeAliasElement> prune]);
@override
FunctionTypeImpl substitute3(List<DartType> argumentTypes) =>
@@ -1038,31 +790,7 @@
* and type after any type parameters have been applied.
*/
void _forEachParameterType(
- ParameterKind kind, callback(String name, DartType type)) {
- List<ParameterElement> parameters = baseParameters;
- if (parameters.isEmpty) {
- return;
- }
-
- List<DartType> typeParameters =
- TypeParameterTypeImpl.getTypes(this.typeParameters);
- int length = parameters.length;
- for (int i = 0; i < length; i++) {
- ParameterElement parameter = parameters[i];
- // ignore: deprecated_member_use
- if (parameter.parameterKind == kind) {
- TypeImpl type = parameter.type ?? DynamicTypeImpl.instance;
- if (typeArguments.length != 0 &&
- typeArguments.length == typeParameters.length) {
- type = type.substitute2(typeArguments, typeParameters, newPrune);
- } else {
- type = type.pruned(newPrune);
- }
-
- callback(parameter.name, type);
- }
- }
- }
+ ParameterKind kind, callback(String name, DartType type));
void _freeVariablesInFunctionType(
FunctionType type, Set<TypeParameterType> free) {
@@ -3150,3 +2878,480 @@
[List<FunctionTypeAliasElement> prune]) =>
this;
}
+
+/**
+ * A [FunctionTypeImpl] that is lazily built from a [FunctionTypedElement] in
+ * the element model.
+ */
+class _FunctionTypeImplLazy extends FunctionTypeImpl {
+ /**
+ * The list of [typeArguments].
+ */
+ List<DartType> _typeArguments;
+
+ /**
+ * The list of [typeParameters], if it has been computed already. Otherwise
+ * `null`.
+ */
+ List<TypeParameterElement> _typeParameters;
+
+ /**
+ * The return type of the function, or `null` if the return type should be
+ * accessed through the element.
+ */
+ final DartType _returnType;
+
+ /**
+ * The parameters to the function, or `null` if the parameters should be
+ * accessed through the element.
+ */
+ final List<ParameterElement> _parameters;
+
+ /**
+ * True if this type is the result of instantiating type parameters (and thus
+ * any type parameters bound by the typedef should be considered part of
+ * [typeParameters] rather than [typeFormals]).
+ */
+ final bool _isInstantiated;
+
+ @override
+ final List<FunctionTypeAliasElement> prunedTypedefs;
+
+ /**
+ * Private constructor.
+ */
+ _FunctionTypeImplLazy._(
+ FunctionTypedElement element,
+ String name,
+ this.prunedTypedefs,
+ this._typeArguments,
+ this._returnType,
+ this._parameters,
+ this._isInstantiated)
+ : _typeParameters = null,
+ super._(element, name);
+
+ /**
+ * Return the base parameter elements of this function element.
+ */
+ List<ParameterElement> get baseParameters =>
+ _parameters ?? element.parameters;
+
+ /**
+ * Return the return type defined by this function's element.
+ */
+ DartType get baseReturnType => _returnType ?? element.returnType;
+
+ @override
+ bool get isInstantiated => _isInstantiated;
+
+ @override
+ List<FunctionTypeAliasElement> get newPrune {
+ Element element = this.element;
+ if (element is GenericFunctionTypeElement) {
+ element = (element as GenericFunctionTypeElement).enclosingElement;
+ }
+ if (element is FunctionTypeAliasElement && !element.isSynthetic) {
+ // This typedef should be pruned, along with anything that was previously
+ // pruned.
+ if (prunedTypedefs == null) {
+ return <FunctionTypeAliasElement>[element];
+ } else {
+ return new List<FunctionTypeAliasElement>.from(prunedTypedefs)
+ ..add(element);
+ }
+ } else {
+ // This is not a typedef, so nothing additional needs to be pruned.
+ return prunedTypedefs;
+ }
+ }
+
+ @override
+ List<String> get normalParameterNames {
+ return baseParameters
+ .where((parameter) => parameter.isNotOptional)
+ .map((parameter) => parameter.name)
+ .toList();
+ }
+
+ @override
+ List<String> get optionalParameterNames {
+ return baseParameters
+ .where((parameter) => parameter.isOptionalPositional)
+ .map((parameter) => parameter.name)
+ .toList();
+ }
+
+ @override
+ List<ParameterElement> get parameters {
+ List<ParameterElement> baseParameters = this.baseParameters;
+ // no parameters, quick return
+ int parameterCount = baseParameters.length;
+ if (parameterCount == 0) {
+ return baseParameters;
+ }
+
+ // create specialized parameters
+ var specializedParams = new List<ParameterElement>(parameterCount);
+
+ var parameterTypes = TypeParameterTypeImpl.getTypes(typeParameters);
+ for (int i = 0; i < parameterCount; i++) {
+ var parameter = baseParameters[i];
+ if (parameter?.type == null) {
+ specializedParams[i] = parameter;
+ continue;
+ }
+
+ // Check if parameter type depends on defining type type arguments, or
+ // if it needs to be pruned.
+
+ if (parameter is FieldFormalParameterElement) {
+ // TODO(jmesserly): this seems like it won't handle pruning correctly.
+ specializedParams[i] = new FieldFormalParameterMember(parameter, this);
+ continue;
+ }
+ var baseType = parameter.type as TypeImpl;
+ TypeImpl type;
+ if (typeArguments.isEmpty ||
+ typeArguments.length != typeParameters.length) {
+ type = baseType.pruned(newPrune);
+ } else {
+ type = baseType.substitute2(typeArguments, parameterTypes, newPrune);
+ }
+
+ specializedParams[i] = identical(type, baseType)
+ ? parameter
+ : new ParameterMember(parameter, this, type);
+ }
+ return specializedParams;
+ }
+
+ @override
+ DartType get returnType {
+ DartType baseReturnType = this.baseReturnType;
+ if (baseReturnType == null) {
+ // TODO(brianwilkerson) This is a patch. The return type should never be
+ // null and we need to understand why it is and fix it.
+ return DynamicTypeImpl.instance;
+ }
+ // If there are no arguments to substitute, or if the arguments size doesn't
+ // match the parameter size, return the base return type.
+ if (typeArguments.length == 0 ||
+ typeArguments.length != typeParameters.length) {
+ return (baseReturnType as TypeImpl).pruned(newPrune);
+ }
+ return (baseReturnType as TypeImpl).substitute2(typeArguments,
+ TypeParameterTypeImpl.getTypes(typeParameters), newPrune);
+ }
+
+ /**
+ * A list containing the actual types of the type arguments.
+ */
+ List<DartType> get typeArguments {
+ if (_typeArguments == null) {
+ // TODO(jmesserly): reuse TypeParameterTypeImpl.getTypes once we can
+ // make it generic, which will allow it to return List<DartType> instead
+ // of List<TypeParameterType>.
+ if (typeParameters.isEmpty) {
+ _typeArguments = DartType.EMPTY_LIST;
+ } else {
+ _typeArguments = new List<DartType>.from(
+ typeParameters.map((t) => t.type),
+ growable: false);
+ }
+ }
+ return _typeArguments;
+ }
+
+ @override
+ List<TypeParameterElement> get typeFormals {
+ if (_isInstantiated || element == null) {
+ return TypeParameterElement.EMPTY_LIST;
+ }
+ List<TypeParameterElement> baseTypeFormals = element.typeParameters;
+ int formalCount = baseTypeFormals.length;
+ if (formalCount == 0) {
+ return TypeParameterElement.EMPTY_LIST;
+ }
+
+ // Create type formals with specialized bounds.
+ // For example `<U extends T>` where T comes from an outer scope.
+ return TypeParameterMember.from(baseTypeFormals, this);
+ }
+
+ @override
+ List<TypeParameterElement> get typeParameters {
+ if (_typeParameters == null) {
+ // Combine the generic type variables from all enclosing contexts, except
+ // for this generic function's type variables. Those variables are
+ // tracked in [boundTypeParameters].
+ _typeParameters = <TypeParameterElement>[];
+
+ Element e = element;
+ while (e != null) {
+ // If a static method, skip the enclosing class type parameters.
+ if (e is MethodElement && e.isStatic) {
+ e = e.enclosingElement;
+ }
+ e = e.enclosingElement;
+ if (e is TypeParameterizedElement) {
+ _typeParameters.addAll(e.typeParameters);
+ }
+ }
+
+ if (_isInstantiated) {
+ // Once the type has been instantiated, type parameters defined at the
+ // site of the declaration of the method are no longer considered part
+ // [boundTypeParameters]; they are part of [typeParameters].
+ List<TypeParameterElement> parametersToAdd = element?.typeParameters;
+ if (parametersToAdd != null) {
+ _typeParameters.addAll(parametersToAdd);
+ }
+ }
+ }
+ return _typeParameters;
+ }
+
+ @override
+ FunctionTypeImpl instantiate(List<DartType> argumentTypes) {
+ if (argumentTypes.length != typeFormals.length) {
+ throw new ArgumentError(
+ "argumentTypes.length (${argumentTypes.length}) != "
+ "typeFormals.length (${typeFormals.length})");
+ }
+ if (argumentTypes.isEmpty) {
+ return this;
+ }
+
+ // Given:
+ // {U/T} <S> T -> S
+ // Where {U/T} represents the typeArguments (U) and typeParameters (T) list,
+ // and <S> represents the typeFormals.
+ //
+ // Now instantiate([V]), and the result should be:
+ // {U/T, V/S} T -> S.
+ List<DartType> newTypeArgs = <DartType>[];
+ newTypeArgs.addAll(typeArguments);
+ newTypeArgs.addAll(argumentTypes);
+
+ return new _FunctionTypeImplLazy._(element, name, prunedTypedefs,
+ newTypeArgs, _returnType, _parameters, true);
+ }
+
+ @override
+ FunctionTypeImpl pruned(List<FunctionTypeAliasElement> prune) {
+ if (prune == null) {
+ return this;
+ } else if (prune.contains(element) ||
+ prune.contains(element.enclosingElement)) {
+ // Circularity found. Prune the type declaration.
+ return new CircularFunctionTypeImpl();
+ } else {
+ // There should never be a reason to prune a type that has already been
+ // pruned, since pruning is only done when expanding a function type
+ // alias, and function type aliases are always expanded by starting with
+ // base types.
+ assert(this.prunedTypedefs == null);
+ List<DartType> typeArgs = typeArguments
+ .map((DartType t) => (t as TypeImpl).pruned(prune))
+ .toList(growable: false);
+ return new _FunctionTypeImplLazy._(element, name, prune, typeArgs,
+ _returnType, _parameters, _isInstantiated);
+ }
+ }
+
+ @override
+ FunctionType substitute2(
+ List<DartType> argumentTypes, List<DartType> parameterTypes,
+ [List<FunctionTypeAliasElement> prune]) {
+ if (argumentTypes.length != parameterTypes.length) {
+ throw new ArgumentError(
+ "argumentTypes.length (${argumentTypes.length}) != parameterTypes.length (${parameterTypes.length})");
+ }
+ Element element = this.element;
+ if (prune != null && prune.contains(element)) {
+ // Circularity found. Prune the type declaration.
+ return new CircularFunctionTypeImpl();
+ }
+ if (argumentTypes.length == 0) {
+ return this.pruned(prune);
+ }
+ List<DartType> typeArgs =
+ TypeImpl.substitute(typeArguments, argumentTypes, parameterTypes);
+ return new _FunctionTypeImplLazy._(element, name, prune, typeArgs,
+ _returnType, _parameters, _isInstantiated);
+ }
+
+ @override
+ void _forEachParameterType(
+ ParameterKind kind, callback(String name, DartType type)) {
+ List<ParameterElement> parameters = baseParameters;
+ if (parameters.isEmpty) {
+ return;
+ }
+
+ List<DartType> typeParameters =
+ TypeParameterTypeImpl.getTypes(this.typeParameters);
+ int length = parameters.length;
+ for (int i = 0; i < length; i++) {
+ ParameterElement parameter = parameters[i];
+ // ignore: deprecated_member_use
+ if (parameter.parameterKind == kind) {
+ TypeImpl type = parameter.type ?? DynamicTypeImpl.instance;
+ if (typeArguments.length != 0 &&
+ typeArguments.length == typeParameters.length) {
+ type = type.substitute2(typeArguments, typeParameters, newPrune);
+ } else {
+ type = type.pruned(newPrune);
+ }
+
+ callback(parameter.name, type);
+ }
+ }
+ }
+}
+
+/// A [FunctionTypeImpl] that is not associated with any element in the element
+/// model.
+///
+/// In contrast to [_FunctionTypeImplLazy], all of the properties of a
+/// [_FunctionTypeImplStrict] are known at construction time.
+class _FunctionTypeImplStrict extends FunctionTypeImpl {
+ @override
+ final DartType returnType;
+
+ @override
+ final List<TypeParameterElement> typeFormals;
+
+ @override
+ final List<ParameterElement> parameters;
+
+ _FunctionTypeImplStrict._(this.returnType, this.typeFormals, this.parameters)
+ : super._(null, null);
+
+ @override
+ List<TypeParameterElement> get boundTypeParameters => typeFormals;
+
+ @override
+ bool get isInstantiated => throw new UnimplementedError('TODO(paulberry)');
+
+ @override
+ List<FunctionTypeAliasElement> get newPrune => const [];
+
+ @override
+ List<String> get normalParameterNames =>
+ parameters.where((p) => p.isNotOptional).map((p) => p.name).toList();
+
+ @override
+ List<String> get optionalParameterNames => parameters
+ .where((p) => p.isOptionalPositional)
+ .map((p) => p.name)
+ .toList();
+
+ @override
+ List<FunctionTypeAliasElement> get prunedTypedefs => const [];
+
+ @override
+ List<DartType> get typeArguments => const [] /*TODO(paulberry)*/;
+
+ @override
+ List<TypeParameterElement> get typeParameters => const [] /*TODO(paulberry)*/;
+
+ @override
+ FunctionTypeImpl instantiate(List<DartType> argumentTypes) {
+ if (argumentTypes.length != typeFormals.length) {
+ throw new ArgumentError(
+ "argumentTypes.length (${argumentTypes.length}) != "
+ "typeFormals.length (${typeFormals.length})");
+ }
+ if (argumentTypes.isEmpty) {
+ return this;
+ }
+ var parameterTypes = typeFormals.map((p) => p.type).toList();
+ ParameterElement transformParameter(ParameterElement p) {
+ var type = p.type;
+ var newType = type.substitute2(argumentTypes, parameterTypes);
+ if (identical(newType, type)) return p;
+ return new ParameterElementImpl.synthetic(
+ p.name,
+ newType,
+ // ignore: deprecated_member_use
+ p.parameterKind);
+ }
+
+ return new _FunctionTypeImplStrict._(
+ returnType.substitute2(argumentTypes, parameterTypes),
+ const [],
+ _transformOrShare(parameters, transformParameter));
+ }
+
+ @override
+ TypeImpl pruned(List<FunctionTypeAliasElement> prune) => this;
+
+ @override
+ FunctionType substitute2(
+ List<DartType> argumentTypes, List<DartType> parameterTypes,
+ [List<FunctionTypeAliasElement> prune]) {
+ if (argumentTypes.length != parameterTypes.length) {
+ throw new ArgumentError(
+ "argumentTypes.length (${argumentTypes.length}) != "
+ "parameterTypes.length (${parameterTypes.length})");
+ }
+ TypeParameterElement transformTypeFormal(TypeParameterElement p) {
+ var bound = p.bound;
+ var newBound = bound?.substitute2(argumentTypes, parameterTypes);
+ if (identical(bound, newBound)) return p;
+ var element = new TypeParameterElementImpl.synthetic(p.name);
+ element.bound = newBound;
+ element.type = new TypeParameterTypeImpl(element);
+ return element;
+ }
+
+ var newTypeFormals = _transformOrShare(typeFormals, transformTypeFormal);
+ List<DartType> typeFormalsArgumentTypes;
+ List<DartType> typeFormalsParameterTypes;
+ if (!identical(typeFormals, newTypeFormals)) {
+ typeFormalsArgumentTypes = newTypeFormals.map((p) => p.type).toList();
+ typeFormalsParameterTypes = typeFormals.map((p) => p.type).toList();
+ }
+ DartType transformType(DartType t) {
+ t = t.substitute2(argumentTypes, parameterTypes);
+ if (typeFormalsArgumentTypes != null) {
+ t = t.substitute2(typeFormalsArgumentTypes, typeFormalsParameterTypes);
+ }
+ return t;
+ }
+
+ ParameterElement transformParameter(ParameterElement p) {
+ var type = p.type;
+ var newType = transformType(type);
+ if (identical(newType, type)) return p;
+ return new ParameterElementImpl.synthetic(
+ p.name,
+ newType,
+ // ignore: deprecated_member_use
+ p.parameterKind);
+ }
+
+ var newReturnType = transformType(returnType);
+ var newParameters = _transformOrShare(parameters, transformParameter);
+ if (identical(returnType, newReturnType) &&
+ identical(typeFormals, newTypeFormals) &&
+ identical(parameters, newParameters)) {
+ return this;
+ }
+ return new _FunctionTypeImplStrict._(
+ newReturnType, newTypeFormals, newParameters);
+ }
+
+ @override
+ void _forEachParameterType(
+ ParameterKind kind, Function(String name, DartType type) callback) {
+ for (var parameter in parameters) {
+ // ignore: deprecated_member_use
+ if (parameter.parameterKind == kind) {
+ callback(parameter.name, parameter.type);
+ }
+ }
+ }
+}
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 1d28718..2f76c16 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -157,6 +157,13 @@
}
@override
+ void endImplicitCreationExpression(Token token) {
+ debugEvent("ImplicitCreationExpression");
+
+ _handleInstanceCreation(null);
+ }
+
+ @override
void endNewExpression(Token newKeyword) {
assert(optional('new', newKeyword));
debugEvent("NewExpression");
@@ -863,6 +870,7 @@
push(ast.thisExpression(thisKeyword));
}
+ @override
void handleType(Token beginToken, Token endToken) {
debugEvent("Type");
@@ -2057,7 +2065,8 @@
}
FormalParameterList parameters = pop();
- ConstructorName constructorName = pop();
+ pop(); // Type parameters
+ Object constructorName = pop();
_Modifiers modifiers = pop();
List<Annotation> metadata = pop();
Comment comment = _findComment(metadata, beginToken);
@@ -2067,7 +2076,7 @@
SimpleIdentifier returnType;
Token period;
SimpleIdentifier name;
- Identifier typeName = constructorName.type.name;
+ Identifier typeName = constructorName;
if (typeName is SimpleIdentifier) {
returnType = typeName;
} else if (typeName is PrefixedIdentifier) {
@@ -2163,6 +2172,12 @@
}
@override
+ void beginTypeVariable(Token name) {
+ debugEvent("beginTypeVariable");
+ push(ast.simpleIdentifier(name, isDeclaration: true));
+ }
+
+ @override
void endTypeVariable(Token token, Token extendsOrSuper) {
// TODO(paulberry): set up scopes properly to resolve parameters and type
// variables. Note that this is tricky due to the handling of initializers
diff --git a/pkg/analyzer/lib/src/fasta/ast_building_factory.dart b/pkg/analyzer/lib/src/fasta/ast_building_factory.dart
index 4534573..7e08aa0 100644
--- a/pkg/analyzer/lib/src/fasta/ast_building_factory.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_building_factory.dart
@@ -321,8 +321,8 @@
node is VariableDeclarationStatement && node.variables != 1;
@override
- Label label(Token identifier, Token colon) =>
- astFactory.label(astFactory.simpleIdentifier(identifier), colon);
+ Label label(Token identifier, Token colon) => astFactory.label(
+ astFactory.simpleIdentifier(identifier, isDeclaration: true), colon);
@override
Statement labeledStatement(
diff --git a/pkg/analyzer/lib/src/fasta/error_converter.dart b/pkg/analyzer/lib/src/fasta/error_converter.dart
index 7207018..8fd383e 100644
--- a/pkg/analyzer/lib/src/fasta/error_converter.dart
+++ b/pkg/analyzer/lib/src/fasta/error_converter.dart
@@ -349,6 +349,10 @@
errorReporter?.reportErrorForOffset(
StrongModeCode.INVALID_CAST_NEW_EXPR, offset, length);
return;
+ case "INVALID_CONSTRUCTOR_NAME":
+ errorReporter?.reportErrorForOffset(
+ CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, offset, length);
+ return;
case "INVALID_GENERIC_FUNCTION_TYPE":
errorReporter?.reportErrorForOffset(
ParserErrorCode.INVALID_GENERIC_FUNCTION_TYPE, offset, length);
diff --git a/pkg/analyzer/lib/src/generated/declaration_resolver.dart b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
index 8b7ee76..27e5169 100644
--- a/pkg/analyzer/lib/src/generated/declaration_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
@@ -226,7 +226,8 @@
}
_walk(new ElementWalker.forClass(element), () {
for (EnumConstantDeclaration constant in node.constants) {
- _match(constant.name, _walker.getVariable());
+ VariableElement element = _match(constant.name, _walker.getVariable());
+ _resolveMetadata(node, constant.metadata, element);
}
_walker.getFunction(); // toString()
super.visitEnumDeclaration(node);
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 858e83f..09d4a84 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -46,13 +46,19 @@
*/
class AstRewriteVisitor extends ScopedVisitor {
final bool addConstKeyword;
+ final TypeSystem typeSystem;
/**
* Initialize a newly created visitor.
*/
- AstRewriteVisitor(LibraryElement definingLibrary, Source source,
- TypeProvider typeProvider, AnalysisErrorListener errorListener,
- {Scope nameScope, this.addConstKeyword: false})
+ AstRewriteVisitor(
+ this.typeSystem,
+ LibraryElement definingLibrary,
+ Source source,
+ TypeProvider typeProvider,
+ AnalysisErrorListener errorListener,
+ {Scope nameScope,
+ this.addConstKeyword: false})
: super(definingLibrary, source, typeProvider, errorListener,
nameScope: nameScope);
@@ -76,7 +82,6 @@
}
Element element = nameScope.lookup(methodName, definingLibrary);
if (element is ClassElement) {
- ConstructorElement constructorElement = element.unnamedConstructor;
AstFactory astFactory = new AstFactoryImpl();
TypeName typeName = astFactory.typeName(methodName, node.typeArguments);
ConstructorName constructorName =
@@ -84,7 +89,9 @@
InstanceCreationExpression instanceCreationExpression =
astFactory.instanceCreationExpression(
_getKeyword(node), constructorName, node.argumentList);
- DartType type = _getType(element, node.typeArguments);
+ InterfaceType type = _getType(element, node.typeArguments);
+ ConstructorElement constructorElement =
+ type.lookUpConstructor(null, definingLibrary);
methodName.staticElement = element;
methodName.staticType = type;
typeName.type = type;
@@ -111,7 +118,9 @@
InstanceCreationExpression instanceCreationExpression =
astFactory.instanceCreationExpression(
_getKeyword(node), constructorName, node.argumentList);
- DartType type = _getType(element, node.typeArguments);
+ InterfaceType type = _getType(element, node.typeArguments);
+ constructorElement =
+ type.lookUpConstructor(methodName.name, definingLibrary);
methodName.staticElement = element;
methodName.staticType = type;
typeName.type = type;
@@ -129,8 +138,6 @@
astFactory.simpleIdentifier(methodName.token));
Element prefixedElement = nameScope.lookup(identifier, definingLibrary);
if (prefixedElement is ClassElement) {
- ConstructorElement constructorElement =
- prefixedElement.unnamedConstructor;
TypeName typeName = astFactory.typeName(
astFactory.prefixedIdentifier(target, node.operator, methodName),
node.typeArguments);
@@ -139,7 +146,9 @@
InstanceCreationExpression instanceCreationExpression =
astFactory.instanceCreationExpression(
_getKeyword(node), constructorName, node.argumentList);
- DartType type = _getType(prefixedElement, node.typeArguments);
+ InterfaceType type = _getType(prefixedElement, node.typeArguments);
+ ConstructorElement constructorElement =
+ type.lookUpConstructor(null, definingLibrary);
methodName.staticElement = element;
methodName.staticType = type;
typeName.type = type;
@@ -164,7 +173,9 @@
InstanceCreationExpression instanceCreationExpression =
astFactory.instanceCreationExpression(
_getKeyword(node), constructorName, node.argumentList);
- DartType type = _getType(element, node.typeArguments);
+ InterfaceType type = _getType(element, node.typeArguments);
+ constructorElement =
+ type.lookUpConstructor(methodName.name, definingLibrary);
methodName.staticElement = element;
methodName.staticType = type;
typeName.type = type;
@@ -206,6 +217,8 @@
.map((TypeParameterElement parameter) => parameter.type)
.toList();
type = type.substitute2(argumentTypes, parameterTypes);
+ } else if (typeArguments == null && typeParameters != null) {
+ type = typeSystem.instantiateToBounds(type);
}
return type;
}
@@ -4164,6 +4177,37 @@
}
/**
+ * Report a [HintCode.DUPLICATE_SHOWN_HIDDEN_NAME] hint for each duplicate
+ * shown or hidden name.
+ *
+ * Only call this method after all of the compilation units have been visited
+ * by this visitor.
+ *
+ * @param errorReporter the error reporter used to report the set of
+ * [HintCode.UNUSED_SHOWN_NAME] hints
+ */
+ void generateDuplicateShownHiddenNameHints(ErrorReporter reporter) {
+ _duplicateHiddenNamesMap.forEach(
+ (NamespaceDirective directive, List<SimpleIdentifier> identifiers) {
+ int length = identifiers.length;
+ for (int i = 0; i < length; i++) {
+ Identifier identifier = identifiers[i];
+ reporter.reportErrorForNode(
+ HintCode.DUPLICATE_HIDDEN_NAME, identifier, [identifier.name]);
+ }
+ });
+ _duplicateShownNamesMap.forEach(
+ (NamespaceDirective directive, List<SimpleIdentifier> identifiers) {
+ int length = identifiers.length;
+ for (int i = 0; i < length; i++) {
+ Identifier identifier = identifiers[i];
+ reporter.reportErrorForNode(
+ HintCode.DUPLICATE_SHOWN_NAME, identifier, [identifier.name]);
+ }
+ });
+ }
+
+ /**
* Report an [HintCode.UNUSED_IMPORT] hint for each unused import.
*
* Only call this method after all of the compilation units have been visited by this visitor.
@@ -4217,37 +4261,6 @@
}
/**
- * Report a [HintCode.DUPLICATE_SHOWN_HIDDEN_NAME] hint for each duplicate
- * shown or hidden name.
- *
- * Only call this method after all of the compilation units have been visited
- * by this visitor.
- *
- * @param errorReporter the error reporter used to report the set of
- * [HintCode.UNUSED_SHOWN_NAME] hints
- */
- void generateDuplicateShownHiddenNameHints(ErrorReporter reporter) {
- _duplicateHiddenNamesMap.forEach(
- (NamespaceDirective directive, List<SimpleIdentifier> identifiers) {
- int length = identifiers.length;
- for (int i = 0; i < length; i++) {
- Identifier identifier = identifiers[i];
- reporter.reportErrorForNode(
- HintCode.DUPLICATE_HIDDEN_NAME, identifier, [identifier.name]);
- }
- });
- _duplicateShownNamesMap.forEach(
- (NamespaceDirective directive, List<SimpleIdentifier> identifiers) {
- int length = identifiers.length;
- for (int i = 0; i < length; i++) {
- Identifier identifier = identifiers[i];
- reporter.reportErrorForNode(
- HintCode.DUPLICATE_SHOWN_NAME, identifier, [identifier.name]);
- }
- });
- }
-
- /**
* Remove elements from [_unusedImports] using the given [usedElements].
*/
void removeUsedElements(UsedImportedElements usedElements) {
@@ -4291,26 +4304,6 @@
}
/**
- * Add every shown name from [importDirective] into [_unusedShownNamesMap].
- */
- void _addShownNames(ImportDirective importDirective) {
- if (importDirective.combinators == null) {
- return;
- }
- List<SimpleIdentifier> identifiers = new List<SimpleIdentifier>();
- _unusedShownNamesMap[importDirective] = identifiers;
- for (Combinator combinator in importDirective.combinators) {
- if (combinator is ShowCombinator) {
- for (SimpleIdentifier name in combinator.shownNames) {
- if (name.staticElement != null) {
- identifiers.add(name);
- }
- }
- }
- }
- }
-
- /**
* Add duplicate shown and hidden names from [directive] into
* [_duplicateHiddenNamesMap] and [_duplicateShownNamesMap].
*/
@@ -4348,6 +4341,26 @@
}
/**
+ * Add every shown name from [importDirective] into [_unusedShownNamesMap].
+ */
+ void _addShownNames(ImportDirective importDirective) {
+ if (importDirective.combinators == null) {
+ return;
+ }
+ List<SimpleIdentifier> identifiers = new List<SimpleIdentifier>();
+ _unusedShownNamesMap[importDirective] = identifiers;
+ for (Combinator combinator in importDirective.combinators) {
+ if (combinator is ShowCombinator) {
+ for (SimpleIdentifier name in combinator.shownNames) {
+ if (name.staticElement != null) {
+ identifiers.add(name);
+ }
+ }
+ }
+ }
+ }
+
+ /**
* Lookup and return the [Namespace] from the [_namespaceMap].
*
* If the map does not have the computed namespace, compute it and cache it in the map. If
@@ -5876,6 +5889,7 @@
if (node.metadata != null) {
node.metadata.accept(this);
ElementResolver.resolveMetadata(node);
+ node.constants.forEach(ElementResolver.resolveMetadata);
}
//
// Continue the enum resolution.
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index ab376a1..5656daf 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -1628,12 +1628,8 @@
return type;
}
- var function = new FunctionElementImpl(type.name, -1)
- ..isSynthetic = true
- ..returnType = newReturnType
- ..shareTypeParameters(type.typeFormals)
- ..parameters = newParameters;
- return function.type = new FunctionTypeImpl(function);
+ return new FunctionTypeImpl.synthetic(
+ newReturnType, type.typeFormals, newParameters);
}
return type;
}
diff --git a/pkg/analyzer/lib/src/generated/utilities_general.dart b/pkg/analyzer/lib/src/generated/utilities_general.dart
index 968cad3..5571721 100644
--- a/pkg/analyzer/lib/src/generated/utilities_general.dart
+++ b/pkg/analyzer/lib/src/generated/utilities_general.dart
@@ -215,6 +215,8 @@
@override
Future<E> makeCurrentWhileAsync<E>(Future<E> f()) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
PerformanceTag prevTag = makeCurrent();
try {
return await f();
diff --git a/pkg/analyzer/lib/src/lint/analysis.dart b/pkg/analyzer/lib/src/lint/analysis.dart
index 006ccb6..744db6f 100644
--- a/pkg/analyzer/lib/src/lint/analysis.dart
+++ b/pkg/analyzer/lib/src/lint/analysis.dart
@@ -159,6 +159,8 @@
}
Future<List<AnalysisErrorInfo>> analyze(Iterable<io.File> files) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AnalysisEngine.instance.logger = new StdLogger();
SourceFactory sourceFactory =
diff --git a/pkg/analyzer/lib/src/lint/linter.dart b/pkg/analyzer/lib/src/lint/linter.dart
index 92e25c4..e4fde6c 100644
--- a/pkg/analyzer/lib/src/lint/linter.dart
+++ b/pkg/analyzer/lib/src/lint/linter.dart
@@ -67,6 +67,8 @@
DartLinter(this.options, {this.reporter: const PrintingReporter()});
Future<Iterable<AnalysisErrorInfo>> lintFiles(List<File> files) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<AnalysisErrorInfo> errors = [];
final lintDriver = new LintDriver(options);
errors.addAll(await lintDriver.analyze(files.where((f) => isDartFile(f))));
@@ -377,6 +379,8 @@
@override
Future<Iterable<AnalysisErrorInfo>> lintFiles(List<File> files) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<AnalysisErrorInfo> errors = [];
final lintDriver = new LintDriver(options);
errors.addAll(await lintDriver.analyze(files.where((f) => isDartFile(f))));
diff --git a/pkg/analyzer/lib/src/lint/project.dart b/pkg/analyzer/lib/src/lint/project.dart
index 48fa64d..f87c70f 100644
--- a/pkg/analyzer/lib/src/lint/project.dart
+++ b/pkg/analyzer/lib/src/lint/project.dart
@@ -53,17 +53,6 @@
_apiModel = new _ApiModel(driver, sources, root);
}
- /// Create an initialized Dart project for the corresponding [driver] and
- /// [sources].
- /// If a [dir] is unspecified the current working directory will be
- /// used.
- static Future<DartProject> create(AnalysisDriver driver, List<Source> sources,
- {Directory dir}) async {
- DartProject project = new DartProject._(driver, sources, dir: dir);
- await project._apiModel._calculate();
- return project;
- }
-
/// The project's name.
///
/// Project names correspond to the package name as specified in the project's
@@ -91,6 +80,19 @@
}
return p.basename(root.path);
}
+
+ /// Create an initialized Dart project for the corresponding [driver] and
+ /// [sources].
+ /// If a [dir] is unspecified the current working directory will be
+ /// used.
+ static Future<DartProject> create(AnalysisDriver driver, List<Source> sources,
+ {Directory dir}) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
+ DartProject project = new DartProject._(driver, sources, dir: dir);
+ await project._apiModel._calculate();
+ return project;
+ }
}
/// An object that can be used to visit Dart project structure.
@@ -121,6 +123,8 @@
}
_calculate() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (sources == null || sources.isEmpty) {
return;
}
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index fdf5e48..8916caf 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -7238,11 +7238,23 @@
class UnlinkedEnumValueBuilder extends Object
with _UnlinkedEnumValueMixin
implements idl.UnlinkedEnumValue {
+ List<UnlinkedExprBuilder> _annotations;
UnlinkedDocumentationCommentBuilder _documentationComment;
String _name;
int _nameOffset;
@override
+ List<UnlinkedExprBuilder> get annotations =>
+ _annotations ??= <UnlinkedExprBuilder>[];
+
+ /**
+ * Annotations for this value.
+ */
+ void set annotations(List<UnlinkedExprBuilder> value) {
+ this._annotations = value;
+ }
+
+ @override
UnlinkedDocumentationCommentBuilder get documentationComment =>
_documentationComment;
@@ -7276,10 +7288,12 @@
}
UnlinkedEnumValueBuilder(
- {UnlinkedDocumentationCommentBuilder documentationComment,
+ {List<UnlinkedExprBuilder> annotations,
+ UnlinkedDocumentationCommentBuilder documentationComment,
String name,
int nameOffset})
- : _documentationComment = documentationComment,
+ : _annotations = annotations,
+ _documentationComment = documentationComment,
_name = name,
_nameOffset = nameOffset;
@@ -7287,6 +7301,7 @@
* Flush [informative] data recursively.
*/
void flushInformative() {
+ _annotations?.forEach((b) => b.flushInformative());
_documentationComment = null;
_nameOffset = null;
}
@@ -7296,11 +7311,24 @@
*/
void collectApiSignature(api_sig.ApiSignature signature) {
signature.addString(this._name ?? '');
+ if (this._annotations == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this._annotations.length);
+ for (var x in this._annotations) {
+ x?.collectApiSignature(signature);
+ }
+ }
}
fb.Offset finish(fb.Builder fbBuilder) {
+ fb.Offset offset_annotations;
fb.Offset offset_documentationComment;
fb.Offset offset_name;
+ if (!(_annotations == null || _annotations.isEmpty)) {
+ offset_annotations = fbBuilder
+ .writeList(_annotations.map((b) => b.finish(fbBuilder)).toList());
+ }
if (_documentationComment != null) {
offset_documentationComment = _documentationComment.finish(fbBuilder);
}
@@ -7308,6 +7336,9 @@
offset_name = fbBuilder.writeString(_name);
}
fbBuilder.startTable();
+ if (offset_annotations != null) {
+ fbBuilder.addOffset(3, offset_annotations);
+ }
if (offset_documentationComment != null) {
fbBuilder.addOffset(2, offset_documentationComment);
}
@@ -7337,11 +7368,20 @@
_UnlinkedEnumValueImpl(this._bc, this._bcOffset);
+ List<idl.UnlinkedExpr> _annotations;
idl.UnlinkedDocumentationComment _documentationComment;
String _name;
int _nameOffset;
@override
+ List<idl.UnlinkedExpr> get annotations {
+ _annotations ??=
+ const fb.ListReader<idl.UnlinkedExpr>(const _UnlinkedExprReader())
+ .vTableGet(_bc, _bcOffset, 3, const <idl.UnlinkedExpr>[]);
+ return _annotations;
+ }
+
+ @override
idl.UnlinkedDocumentationComment get documentationComment {
_documentationComment ??= const _UnlinkedDocumentationCommentReader()
.vTableGet(_bc, _bcOffset, 2, null);
@@ -7365,6 +7405,9 @@
@override
Map<String, Object> toJson() {
Map<String, Object> _result = <String, Object>{};
+ if (annotations.isNotEmpty)
+ _result["annotations"] =
+ annotations.map((_value) => _value.toJson()).toList();
if (documentationComment != null)
_result["documentationComment"] = documentationComment.toJson();
if (name != '') _result["name"] = name;
@@ -7374,6 +7417,7 @@
@override
Map<String, Object> toMap() => {
+ "annotations": annotations,
"documentationComment": documentationComment,
"name": name,
"nameOffset": nameOffset,
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index 2b752f0..54b21e9 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -2042,6 +2042,11 @@
*/
table UnlinkedEnumValue {
/**
+ * Annotations for this value.
+ */
+ annotations:[UnlinkedExpr] (id: 3);
+
+ /**
* Documentation comment for the enum value, or `null` if there is no
* documentation comment.
*/
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index 49b3d3e..343740b 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -1660,6 +1660,12 @@
*/
abstract class UnlinkedEnumValue extends base.SummaryClass {
/**
+ * Annotations for this value.
+ */
+ @Id(3)
+ List<UnlinkedExpr> get annotations;
+
+ /**
* Documentation comment for the enum value, or `null` if there is no
* documentation comment.
*/
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index 3c6353c..10656bd 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -2225,7 +2225,7 @@
UnlinkedExpr unlinkedConst = unlinkedExecutable.bodyExpr;
var errorListener = AnalysisErrorListener.NULL_LISTENER;
var astRewriteVisitor = new AstRewriteVisitor(
- library, unit.source, typeProvider, errorListener);
+ linker.typeSystem, library, unit.source, typeProvider, errorListener);
// TODO(paulberry): Do we need to pass a nameScope to
// resolverVisitor to get type variables to resolve properly?
var resolverVisitor = new ResolverVisitor(
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index 170a534..5c72f8a 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -1600,8 +1600,12 @@
var expression = new ExprBuilder(this, context, uc).build();
if (expression != null && context.context.analysisOptions.previewDart2) {
- astRewriteVisitor ??= new AstRewriteVisitor(libraryResynthesizer.library,
- unit.source, typeProvider, AnalysisErrorListener.NULL_LISTENER,
+ astRewriteVisitor ??= new AstRewriteVisitor(
+ libraryResynthesizer.summaryResynthesizer.context.typeSystem,
+ libraryResynthesizer.library,
+ unit.source,
+ typeProvider,
+ AnalysisErrorListener.NULL_LISTENER,
addConstKeyword: true);
var container = astFactory.expressionStatement(expression, null);
expression.accept(astRewriteVisitor);
diff --git a/pkg/analyzer/lib/src/summary/summarize_ast.dart b/pkg/analyzer/lib/src/summary/summarize_ast.dart
index ea0c328..156b98df 100644
--- a/pkg/analyzer/lib/src/summary/summarize_ast.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_ast.dart
@@ -580,6 +580,18 @@
}
/**
+ * Serialize an [EnumConstantDeclaration] into an [UnlinkedEnumValue].
+ */
+ UnlinkedEnumValueBuilder serializeEnumConstantDeclaration(
+ EnumConstantDeclaration node) {
+ return new UnlinkedEnumValueBuilder(
+ annotations: serializeAnnotations(node.metadata),
+ documentationComment: serializeDocumentation(node.documentationComment),
+ name: node.name.name,
+ nameOffset: node.name.offset);
+ }
+
+ /**
* Serialize a [FunctionDeclaration] or [MethodDeclaration] into an
* [UnlinkedExecutable].
*
@@ -1134,13 +1146,7 @@
UnlinkedEnumBuilder b = new UnlinkedEnumBuilder();
b.name = node.name.name;
b.nameOffset = node.name.offset;
- b.values = node.constants
- .map((EnumConstantDeclaration value) => new UnlinkedEnumValueBuilder(
- documentationComment:
- serializeDocumentation(value.documentationComment),
- name: value.name.name,
- nameOffset: value.name.offset))
- .toList();
+ b.values = node.constants.map(serializeEnumConstantDeclaration).toList();
b.documentationComment = serializeDocumentation(node.documentationComment);
b.annotations = serializeAnnotations(node.metadata);
b.codeRange = serializeCodeRange(node);
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index a1c7232..50ff551 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -5125,8 +5125,12 @@
// Re-write the AST to handle the optional new and const feature.
//
if (library.context.analysisOptions.previewDart2) {
- unit.accept(new AstRewriteVisitor(library, unit.element.source,
- typeProvider, AnalysisErrorListener.NULL_LISTENER));
+ unit.accept(new AstRewriteVisitor(
+ context.typeSystem,
+ library,
+ unit.element.source,
+ typeProvider,
+ AnalysisErrorListener.NULL_LISTENER));
}
//
// Record outputs.
diff --git a/pkg/analyzer/test/dart/element/builder_test.dart b/pkg/analyzer/test/dart/element/builder_test.dart
index 224a4ea..6d748aa 100644
--- a/pkg/analyzer/test/dart/element/builder_test.dart
+++ b/pkg/analyzer/test/dart/element/builder_test.dart
@@ -1293,6 +1293,13 @@
checkMetadata(parameterElement);
}
+ void test_metadata_visitEnumConstant() {
+ ElementHolder enumElement = buildElementsForText('enum E { @a v }');
+ FieldElement v = enumElement.enums[0].fields[0];
+ expect(v.name, 'v');
+ checkMetadata(v);
+ }
+
void test_metadata_visitEnumDeclaration() {
ClassElement classElement =
buildElementsForText('@a enum E { v }').enums[0];
diff --git a/pkg/analyzer/test/file_system/physical_resource_provider_test.dart b/pkg/analyzer/test/file_system/physical_resource_provider_test.dart
index 913bb27..63554c8 100644
--- a/pkg/analyzer/test/file_system/physical_resource_provider_test.dart
+++ b/pkg/analyzer/test/file_system/physical_resource_provider_test.dart
@@ -658,7 +658,7 @@
expect(changesReceived, hasLength(0));
file.writeAsStringSync('contents 2');
return _delayed(() {
- expect(changesReceived, hasLength(1));
+ expect(changesReceived, anyOf(hasLength(1), hasLength(2)));
expect(changesReceived[0].type, equals(ChangeType.MODIFY));
expect(changesReceived[0].path, equals(path));
});
diff --git a/pkg/analyzer/test/generated/declaration_resolver_test.dart b/pkg/analyzer/test/generated/declaration_resolver_test.dart
index 5809f09..6ad2446 100644
--- a/pkg/analyzer/test/generated/declaration_resolver_test.dart
+++ b/pkg/analyzer/test/generated/declaration_resolver_test.dart
@@ -95,6 +95,11 @@
checkMetadata('E');
}
+ test_metadata_enumDeclaration_constant() async {
+ await setupCode('enum E { @a v }');
+ checkMetadata('v');
+ }
+
test_metadata_exportDirective() async {
addNamedSource('/foo.dart', 'class C {}');
await setupCode('@a export "foo.dart";');
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 73c2001..0724a03 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -3700,6 +3700,19 @@
verify([source]);
}
+ test_metadata_enumConstantDeclaration() async {
+ Source source = addSource(r'''
+const x = 1;
+enum E {
+ aaa,
+ @x
+ bbb
+}''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
test_methodDeclaration_scope_signature() async {
Source source = addSource(r'''
const app = 0;
@@ -4829,6 +4842,87 @@
verify([source]);
}
+ test_optionalNew_rewrite_instantiatesToBounds() async {
+ resetWith(
+ options: new AnalysisOptionsImpl()
+ ..previewDart2 = true
+ ..strongMode = true);
+ Source source = addSource(r'''
+import 'b.dart';
+
+@B.named1()
+@B.named2()
+@B.named3()
+@B.named4()
+@B.named5()
+@B.named6()
+@B.named7()
+@B.named8()
+main() {}
+''');
+ final aSource = addNamedSource("/a.dart", r'''
+class Unbounded<T> {
+ const Unbounded();
+ const Unbounded.named();
+}
+class Bounded<T extends String> {
+ const Bounded();
+ const Bounded.named();
+}
+''');
+ final bSource = addNamedSource("/b.dart", r'''
+import 'a.dart';
+import 'a.dart' as p;
+
+const unbounded1 = Unbounded();
+const unbounded2 = Unbounded.named();
+const unbounded3 = p.Unbounded();
+const unbounded4 = p.Unbounded.named();
+const bounded1 = Bounded();
+const bounded2 = Bounded.named();
+const bounded3 = p.Bounded();
+const bounded4 = p.Bounded.named();
+
+class B {
+ const B.named1({this.unbounded: unbounded1}) : bounded = null;
+ const B.named2({this.unbounded: unbounded2}) : bounded = null;
+ const B.named3({this.unbounded: unbounded3}) : bounded = null;
+ const B.named4({this.unbounded: unbounded4}) : bounded = null;
+ const B.named5({this.bounded: bounded1}) : unbounded = null;
+ const B.named6({this.bounded: bounded2}) : unbounded = null;
+ const B.named7({this.bounded: bounded3}) : unbounded = null;
+ const B.named8({this.bounded: bounded4}) : unbounded = null;
+
+ final Unbounded unbounded;
+ final Bounded bounded;
+}
+''');
+ final result = await computeAnalysisResult(source);
+ expect(result.unit.declarations, hasLength(1));
+ final mainDecl = result.unit.declarations[0];
+ expect(mainDecl.metadata, hasLength(8));
+ mainDecl.metadata.forEach((metadata) {
+ final value = metadata.elementAnnotation.computeConstantValue();
+ expect(value, isNotNull);
+ expect(value.type.toString(), 'B');
+ final unbounded = value.getField('unbounded');
+ final bounded = value.getField('bounded');
+ if (!unbounded.isNull) {
+ expect(bounded.isNull, true);
+ expect(unbounded.type.name, 'Unbounded');
+ expect(unbounded.type.typeArguments, hasLength(1));
+ expect(unbounded.type.typeArguments[0].isDynamic, isTrue);
+ } else {
+ expect(unbounded.isNull, true);
+ expect(bounded.type.name, 'Bounded');
+ expect(bounded.type.typeArguments, hasLength(1));
+ expect(bounded.type.typeArguments[0].name, 'String');
+ }
+ });
+ assertNoErrors(source);
+ verify([source]);
+ }
+
test_optionalParameterInOperator_required() async {
Source source = addSource(r'''
class A {
diff --git a/pkg/analyzer/test/generated/package_build_test.dart b/pkg/analyzer/test/generated/package_build_test.dart
index 96cecc3..47980a8 100644
--- a/pkg/analyzer/test/generated/package_build_test.dart
+++ b/pkg/analyzer/test/generated/package_build_test.dart
@@ -7,7 +7,6 @@
import 'package:analyzer/src/context/builder.dart';
import 'package:analyzer/src/generated/package_build.dart';
import 'package:analyzer/src/generated/source.dart';
-import 'package:mockito/mockito.dart';
import 'package:package_config/packages.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -20,11 +19,31 @@
});
}
-class MockContextBuilder extends Mock implements ContextBuilder {}
+class MockContextBuilder implements ContextBuilder {
+ Map<String, Packages> packagesMapMap = <String, Packages>{};
+ Map<Packages, Map<String, List<Folder>>> packagesToMapMap =
+ <Packages, Map<String, List<Folder>>>{};
-class MockPackages extends Mock implements Packages {}
+ Map<String, List<Folder>> convertPackagesToMap(Packages packages) =>
+ packagesToMapMap[packages];
-class MockUriResolver extends Mock implements UriResolver {}
+ Packages createPackageMap(String rootDirectoryPath) =>
+ packagesMapMap[rootDirectoryPath];
+
+ noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+class MockPackages implements Packages {
+ noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+class MockUriResolver implements UriResolver {
+ Map<Uri, Source> resolveAbsoluteMap = {};
+
+ noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+
+ Source resolveAbsolute(Uri uri, [Uri actualUri]) => resolveAbsoluteMap[uri];
+}
@reflectiveTest
class PackageBuildFileUriResolverTest extends _BaseTest {
@@ -35,12 +54,10 @@
provider.newFolder(_p('/workspace/.dart_tool/build/generated/project/lib'));
provider.newFileWithBytes(
_p('/workspace/pubspec.yaml'), 'name: project'.codeUnits);
- final ContextBuilder contextBuilder = new MockContextBuilder();
+ final MockContextBuilder contextBuilder = new MockContextBuilder();
final Packages packages = new MockPackages();
- when(contextBuilder.createPackageMap(_p('/workspace')))
- .thenReturn(packages);
- when(contextBuilder.convertPackagesToMap(packages))
- .thenReturn({'project': []});
+ contextBuilder.packagesMapMap[_p('/workspace')] = packages;
+ contextBuilder.packagesToMapMap[packages] = {'project': []};
workspace =
PackageBuildWorkspace.find(provider, _p('/workspace'), contextBuilder);
resolver = new PackageBuildFileUriResolver(workspace);
@@ -112,7 +129,7 @@
class PackageBuildPackageUriResolverTest extends _BaseTest {
PackageBuildWorkspace workspace;
PackageBuildPackageUriResolver resolver;
- UriResolver packageUriResolver;
+ MockUriResolver packageUriResolver;
Uri addPackageSource(String path, String uriStr, {bool create: true}) {
Uri uri = Uri.parse(uriStr);
@@ -120,7 +137,7 @@
? provider.newFile(_p(path), '')
: provider.getResource(_p(path));
final Source source = file.createSource(uri);
- when(packageUriResolver.resolveAbsolute(uri)).thenReturn(source);
+ packageUriResolver.resolveAbsoluteMap[uri] = source;
return uri;
}
@@ -189,10 +206,8 @@
}
final contextBuilder = new MockContextBuilder();
final packages = new MockPackages();
- when(contextBuilder.createPackageMap(_p(workspacePath)))
- .thenReturn(packages);
- when(contextBuilder.convertPackagesToMap(packages))
- .thenReturn({'project': []});
+ contextBuilder.packagesMapMap[_p(workspacePath)] = packages;
+ contextBuilder.packagesToMapMap[packages] = {'project': []};
workspace =
PackageBuildWorkspace.find(provider, _p(workspacePath), contextBuilder);
packageUriResolver = new MockUriResolver();
@@ -463,8 +478,8 @@
final contextBuilder = new MockContextBuilder();
final packages = new MockPackages();
final packageMap = new Map.fromIterable(packageNames, value: ((_) => []));
- when(contextBuilder.createPackageMap(_p(root))).thenReturn(packages);
- when(contextBuilder.convertPackagesToMap(packages)).thenReturn(packageMap);
+ contextBuilder.packagesMapMap[_p(root)] = packages;
+ contextBuilder.packagesToMapMap[packages] = packageMap;
return PackageBuildWorkspace.find(provider, _p(root), contextBuilder);
}
}
diff --git a/pkg/analyzer/test/generated/parser_fasta_listener.dart b/pkg/analyzer/test/generated/parser_fasta_listener.dart
index 2d36b5a..a341ce7 100644
--- a/pkg/analyzer/test/generated/parser_fasta_listener.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_listener.dart
@@ -508,8 +508,8 @@
}
@override
- void beginTypeVariable(Token token) {
- super.beginTypeVariable(token);
+ void beginTypeVariable(Token name) {
+ super.beginTypeVariable(name);
begin('TypeVariable');
}
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index 48992b4..d5e8886 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -1326,18 +1326,6 @@
with SimpleParserTestMixin {
@override
@failingTest
- void test_parseInstanceCreation_noKeyword_noPrefix() {
- super.test_parseInstanceCreation_noKeyword_noPrefix();
- }
-
- @override
- @failingTest
- void test_parseInstanceCreation_noKeyword_prefix() {
- super.test_parseInstanceCreation_noKeyword_prefix();
- }
-
- @override
- @failingTest
void test_parseTypeParameterList_single() {
// TODO(brianwilkerson) Does not use all tokens.
super.test_parseTypeParameterList_single();
diff --git a/pkg/analyzer/test/generated/parser_forest_test.dart b/pkg/analyzer/test/generated/parser_forest_test.dart
index b1b4491..b0a2885 100644
--- a/pkg/analyzer/test/generated/parser_forest_test.dart
+++ b/pkg/analyzer/test/generated/parser_forest_test.dart
@@ -8,17 +8,19 @@
import '../src/fasta/body_builder_test_helper.dart';
import 'parser_test.dart';
-main() async {
- defineReflectiveSuite(() {
- defineReflectiveTests(ClassMemberParserTest_Forest);
- defineReflectiveTests(ComplexParserTest_Forest);
- defineReflectiveTests(ErrorParserTest_Forest);
- defineReflectiveTests(ExpressionParserTest_Forest);
- defineReflectiveTests(FormalParameterParserTest_Forest);
- defineReflectiveTests(RecoveryParserTest_Forest);
- defineReflectiveTests(SimpleParserTest_Forest);
- defineReflectiveTests(StatementParserTest_Forest);
- defineReflectiveTests(TopLevelParserTest_Forest);
+main() {
+ return CompilerTestContext.runWithTestOptions((_) {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ClassMemberParserTest_Forest);
+ defineReflectiveTests(ComplexParserTest_Forest);
+ defineReflectiveTests(ErrorParserTest_Forest);
+ defineReflectiveTests(ExpressionParserTest_Forest);
+ defineReflectiveTests(FormalParameterParserTest_Forest);
+ defineReflectiveTests(RecoveryParserTest_Forest);
+ defineReflectiveTests(SimpleParserTest_Forest);
+ defineReflectiveTests(StatementParserTest_Forest);
+ defineReflectiveTests(TopLevelParserTest_Forest);
+ });
});
}
@@ -2832,11 +2834,6 @@
}
@failingTest
- void test_parseExpression_assign_compound() {
- super.test_parseExpression_assign_compound();
- }
-
- @failingTest
void test_parseExpression_comparison() {
super.test_parseExpression_comparison();
}
@@ -5216,11 +5213,6 @@
}
@failingTest
- void test_parseStatement_singleLabel() {
- super.test_parseStatement_singleLabel();
- }
-
- @failingTest
void test_parseSwitchStatement_case() {
super.test_parseSwitchStatement_case();
}
@@ -5971,21 +5963,11 @@
}
@failingTest
- void test_parseFunctionDeclaration_functionWithTypeParameters_comment() {
- super.test_parseFunctionDeclaration_functionWithTypeParameters_comment();
- }
-
- @failingTest
void test_parseFunctionDeclaration_getter() {
super.test_parseFunctionDeclaration_getter();
}
@failingTest
- void test_parseFunctionDeclaration_getter_generic_comment_returnType() {
- super.test_parseFunctionDeclaration_getter_generic_comment_returnType();
- }
-
- @failingTest
void test_parseFunctionDeclaration_metadata() {
super.test_parseFunctionDeclaration_metadata();
}
diff --git a/pkg/analyzer/test/generated/strong_mode_kernel_test.dart b/pkg/analyzer/test/generated/strong_mode_kernel_test.dart
index 763d120..61abc60 100644
--- a/pkg/analyzer/test/generated/strong_mode_kernel_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_kernel_test.dart
@@ -275,18 +275,6 @@
bool get useCFE => true;
@override
- test_dynamicObjectGetter_hashCode() async {
- // Fails with non-kernel analyzer but works correctly with kernel.
- await super.test_dynamicObjectGetter_hashCode();
- }
-
- @override
- test_dynamicObjectMethod_toString() async {
- // Fails with non-kernel analyzer but works correctly with kernel.
- await super.test_dynamicObjectMethod_toString();
- }
-
- @override
test_futureOr_promotion3() async {
// Test passes even though the overridden method fails.
await super.test_futureOr_promotion3();
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index ab24845..1414b83 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -2814,7 +2814,6 @@
resetWith(options: options);
}
- @failingTest // https://github.com/dart-lang/sdk/issues/32173
test_dynamicObjectGetter_hashCode() async {
String code = r'''
main() {
@@ -2823,10 +2822,9 @@
}
''';
await resolveTestUnit(code);
- expectInitializerType('foo', 'dynamic', isNull);
+ expectInitializerType('foo', 'int', isNull);
}
- @failingTest // https://github.com/dart-lang/sdk/issues/32173
test_dynamicObjectMethod_toString() async {
String code = r'''
main() {
@@ -2835,7 +2833,7 @@
}
''';
await resolveTestUnit(code);
- expectInitializerType('foo', 'dynamic', isNull);
+ expectInitializerType('foo', 'String', isNull);
}
test_futureOr_promotion1() async {
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 3804ff6..30d31dd 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -1442,6 +1442,31 @@
expect(files, isNot(contains(c)));
}
+ test_getFileSync_library() async {
+ var path = _p('/test/lib/a.dart');
+ provider.newFile(path, '');
+ var file = driver.getFileSync(path);
+ expect(file.path, path);
+ expect(file.uri.toString(), 'package:test/a.dart');
+ expect(file.isPart, isFalse);
+ }
+
+ test_getFileSync_notAbsolutePath() async {
+ try {
+ driver.getFileSync('not_absolute.dart');
+ fail('ArgumentError expected.');
+ } on ArgumentError {}
+ }
+
+ test_getFileSync_part() async {
+ var path = _p('/test/lib/a.dart');
+ provider.newFile(path, 'part of lib;');
+ var file = driver.getFileSync(path);
+ expect(file.path, path);
+ expect(file.uri.toString(), 'package:test/a.dart');
+ expect(file.isPart, isTrue);
+ }
+
test_getIndex() async {
String content = r'''
foo(int p) {}
diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart
index ac55908..d667f0e 100644
--- a/pkg/analyzer/test/src/dart/analysis/search_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart
@@ -856,6 +856,31 @@
await _verifyReferences(element, expected);
}
+ test_searchReferences_ImportElement_noPrefix_inPackage() async {
+ testFile = _p('/aaa/lib/a.dart');
+ await _resolveTestUnit('''
+import 'dart:math' show max, PI, Random hide min;
+export 'dart:math' show max, PI, Random hide min;
+main() {
+ PI;
+ new Random();
+ max(1, 2);
+}
+Random bar() => null;
+''', addToDriver: false);
+ ImportElement element = testLibraryElement.imports[0];
+ Element mainElement = await _findElement('main');
+ Element barElement = await _findElement('bar');
+ var kind = SearchResultKind.REFERENCE;
+ var expected = [
+ _expectId(mainElement, kind, 'PI;', length: 0),
+ _expectId(mainElement, kind, 'Random();', length: 0),
+ _expectId(mainElement, kind, 'max(1, 2);', length: 0),
+ _expectId(barElement, kind, 'Random bar()', length: 0),
+ ];
+ await _verifyReferences(element, expected);
+ }
+
test_searchReferences_ImportElement_withPrefix() async {
await _resolveTestUnit('''
import 'dart:math' as math show max, PI, Random hide min;
@@ -952,6 +977,32 @@
await _verifyReferences(element, expected);
}
+ test_searchReferences_LibraryElement_inPackage() async {
+ testFile = _p('/aaa/lib/a.dart');
+ var partPathA = _p('/aaa/lib/unitA.dart');
+ var partPathB = _p('/aaa/lib/unitB.dart');
+
+ var codeA = 'part of lib; // A';
+ var codeB = 'part of lib; // B';
+ provider.newFile(partPathA, codeA);
+ provider.newFile(partPathB, codeB);
+ await _resolveTestUnit('''
+library lib;
+part 'unitA.dart';
+part 'unitB.dart';
+''', addToDriver: false);
+ LibraryElement element = testLibraryElement;
+ CompilationUnitElement unitElementA = element.parts[0];
+ CompilationUnitElement unitElementB = element.parts[1];
+ var expected = [
+ new ExpectedResult(unitElementA, SearchResultKind.REFERENCE,
+ codeA.indexOf('lib; // A'), 'lib'.length),
+ new ExpectedResult(unitElementB, SearchResultKind.REFERENCE,
+ codeB.indexOf('lib; // B'), 'lib'.length),
+ ];
+ await _verifyReferences(element, expected);
+ }
+
test_searchReferences_LocalVariableElement() async {
await _resolveTestUnit(r'''
main() {
@@ -973,7 +1024,7 @@
await _verifyReferences(element, expected);
}
- test_searchReferences_localVariableElement_inForEachLoop() async {
+ test_searchReferences_LocalVariableElement_inForEachLoop() async {
await _resolveTestUnit('''
main() {
for (var v in []) {
@@ -995,6 +1046,30 @@
await _verifyReferences(element, expected);
}
+ test_searchReferences_LocalVariableElement_inPackage() async {
+ testFile = _p('/aaa/lib/a.dart');
+
+ await _resolveTestUnit('''
+main() {
+ var v;
+ v = 1;
+ v += 2;
+ print(v);
+ v();
+}
+''', addToDriver: false);
+ Element element = findElementsByName(testUnit, 'v').single;
+ Element main = _findElement('main');
+
+ var expected = [
+ _expectId(main, SearchResultKind.WRITE, 'v = 1;'),
+ _expectId(main, SearchResultKind.READ_WRITE, 'v += 2;'),
+ _expectId(main, SearchResultKind.READ, 'v);'),
+ _expectId(main, SearchResultKind.INVOCATION, 'v();')
+ ];
+ await _verifyReferences(element, expected);
+ }
+
test_searchReferences_MethodElement() async {
await _resolveTestUnit('''
class A {
@@ -1212,6 +1287,36 @@
await _verifyReferences(element, expected);
}
+ test_searchReferences_PrefixElement_inPackage() async {
+ testFile = _p('/aaa/lib/a.dart');
+ var partPath = _p('/aaa/lib/my_part.dart');
+
+ String partCode = r'''
+part of my_lib;
+ppp.Future c;
+''';
+ provider.newFile(partPath, partCode);
+ await _resolveTestUnit('''
+library my_lib;
+import 'dart:async' as ppp;
+part 'my_part.dart';
+main() {
+ ppp.Future a;
+ ppp.Stream b;
+}
+''', addToDriver: false);
+ PrefixElement element = _findElementAtString('ppp;');
+ Element main = _findElement('main');
+ Element c = findChildElement(testLibraryElement, 'c');
+ var expected = [
+ _expectId(main, SearchResultKind.REFERENCE, 'ppp.Future'),
+ _expectId(main, SearchResultKind.REFERENCE, 'ppp.Stream'),
+ new ExpectedResult(c, SearchResultKind.REFERENCE,
+ partCode.indexOf('ppp.Future c'), 'ppp'.length)
+ ];
+ await _verifyReferences(element, expected);
+ }
+
test_searchReferences_private_declaredInDefiningUnit() async {
String p1 = _p('$testProject/part1.dart');
String p2 = _p('$testProject/part2.dart');
@@ -1294,6 +1399,40 @@
await _verifyReferences(element, expected);
}
+ test_searchReferences_private_inPackage() async {
+ testFile = _p('/aaa/lib/a.dart');
+ var p1 = _p('/aaa/lib/part1.dart');
+ var p2 = _p('/aaa/lib/part2.dart');
+
+ String code1 = 'part of lib; _C v1;';
+ String code2 = 'part of lib; _C v2;';
+
+ provider.newFile(p1, code1);
+ provider.newFile(p2, code2);
+
+ await _resolveTestUnit('''
+library lib;
+part 'part1.dart';
+part 'part2.dart';
+class _C {}
+_C v;
+''', addToDriver: false);
+
+ Element element = testUnitElement.types.single;
+ Element v = testUnitElement.topLevelVariables[0];
+ Element v1 = testLibraryElement.parts[0].topLevelVariables[0];
+ Element v2 = testLibraryElement.parts[1].topLevelVariables[0];
+ var expected = [
+ new ExpectedResult(
+ v, SearchResultKind.REFERENCE, testCode.indexOf('_C v;'), 2),
+ new ExpectedResult(
+ v1, SearchResultKind.REFERENCE, code1.indexOf('_C v1;'), 2),
+ new ExpectedResult(
+ v2, SearchResultKind.REFERENCE, code2.indexOf('_C v2;'), 2),
+ ];
+ await _verifyReferences(element, expected);
+ }
+
test_searchReferences_PropertyAccessorElement_getter() async {
await _resolveTestUnit('''
class A {
@@ -1507,6 +1646,68 @@
}
}
+ test_subtypes_discover() async {
+ var pathT = _p('/test/lib/t.dart');
+ var pathA = _p('/aaa/lib/a.dart');
+ var pathB = _p('/bbb/lib/b.dart');
+
+ var tUri = 'package:test/t.dart';
+ var aUri = 'package:aaa/a.dart';
+ var bUri = 'package:bbb/b.dart';
+
+ provider.newFile(pathT, r'''
+import 'package:aaa/a.dart';
+
+class T1 extends A {
+ void method1() {}
+}
+
+class T2 extends A {
+ void method2() {}
+}
+''');
+
+ provider.newFile(pathB, r'''
+import 'package:aaa/a.dart';
+
+class B extends A {
+ void method1() {}
+}
+''');
+
+ provider.newFile(pathA, r'''
+class A {
+ void method1() {}
+ void method2() {}
+}
+''');
+
+ driver.addFile(pathT);
+
+ var aLibrary = await driver.getLibraryByUri(aUri);
+ ClassElement aClass = aLibrary.getType('A');
+
+ // Search by 'type'.
+ List<SubtypeResult> subtypes = await driver.search.subtypes(type: aClass);
+ expect(subtypes, hasLength(3));
+
+ SubtypeResult t1 = subtypes.singleWhere((r) => r.name == 'T1');
+ SubtypeResult t2 = subtypes.singleWhere((r) => r.name == 'T2');
+ SubtypeResult b = subtypes.singleWhere((r) => r.name == 'B');
+
+ expect(t1.libraryUri, tUri);
+ expect(t1.id, '$tUri;$tUri;T1');
+ expect(t1.members, ['method1']);
+
+ expect(t2.libraryUri, tUri);
+ expect(t2.id, '$tUri;$tUri;T2');
+ expect(t2.members, ['method2']);
+
+ expect(b.libraryUri, bUri);
+ expect(b.id, '$bUri;$bUri;B');
+ expect(b.members, ['method1']);
+ }
+
test_subTypes_discover() async {
var t = _p('/test/lib/t.dart');
var a = _p('/aaa/lib/a.dart');
@@ -1672,8 +1873,13 @@
String _p(String path) => provider.convertPath(path);
- Future<Null> _resolveTestUnit(String code) async {
- addTestFile(code);
+ Future<Null> _resolveTestUnit(String code, {bool addToDriver: true}) async {
+ if (addToDriver) {
+ addTestFile(code);
+ } else {
+ testCode = code;
+ provider.newFile(testFile, testCode);
+ }
if (testUnit == null) {
AnalysisResult result = await driver.getResult(testFile);
testUnit = result.unit;
diff --git a/pkg/analyzer/test/src/dart/analysis/session_test.dart b/pkg/analyzer/test/src/dart/analysis/session_test.dart
index e518b96..0eab813 100644
--- a/pkg/analyzer/test/src/dart/analysis/session_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/session_test.dart
@@ -37,7 +37,7 @@
}
test_getErrors() async {
- ErrorsResult result = new ErrorsResult(null, null, null, null, null);
+ ErrorsResult result = new ErrorsResult(null, null, null, null, null, null);
driver.errorsResult = result;
expect(await session.getErrors('path'), result);
}
@@ -58,14 +58,14 @@
test_getParsedAst() async {
ParseResult result =
- new ParseResult(null, null, null, null, null, null, null);
+ new ParseResult(null, null, null, null, null, null, null, null);
driver.parseResult = result;
expect(await session.getParsedAst('path'), result);
}
test_getResolvedAst() async {
- AnalysisResult result = new AnalysisResult(
- driver, null, null, null, null, null, null, null, null, null, null);
+ AnalysisResult result = new AnalysisResult(driver, null, null, null, null,
+ null, null, null, null, null, null, null);
driver.result = result;
expect(await session.getResolvedAst('path'), result);
}
diff --git a/pkg/analyzer/test/src/dart/analysis/test_all.dart b/pkg/analyzer/test/src/dart/analysis/test_all.dart
index f452ede..cd75df1 100644
--- a/pkg/analyzer/test/src/dart/analysis/test_all.dart
+++ b/pkg/analyzer/test/src/dart/analysis/test_all.dart
@@ -4,10 +4,10 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import 'context_builder_test.dart' as context_builder_test;
-import 'context_locator_test.dart' as context_locator_test;
-import 'context_root_test.dart' as context_root_test;
-import 'defined_names_test.dart' as defined_names_test;
+import 'context_builder_test.dart' as context_builder;
+import 'context_locator_test.dart' as context_locator;
+import 'context_root_test.dart' as context_root;
+import 'defined_names_test.dart' as defined_names;
import 'driver_kernel_test.dart' as driver_kernel;
import 'driver_resolution_kernel_test.dart' as driver_resolution_kernel;
import 'driver_resolution_test.dart' as driver_resolution;
@@ -16,16 +16,17 @@
import 'index_test.dart' as index;
import 'mutex_test.dart' as mutex;
import 'referenced_names_test.dart' as referenced_names;
-import 'search_test.dart' as search_test;
-import 'session_helper_test.dart' as session_helper_test;
-import 'session_test.dart' as session_test;
+import 'search_test.dart' as search;
+import 'session_helper_test.dart' as session_helper;
+import 'session_test.dart' as session;
+import 'uri_converter_test.dart' as uri_converter;
main() {
defineReflectiveSuite(() {
- context_builder_test.main();
- context_locator_test.main();
- context_root_test.main();
- defined_names_test.main();
+ context_builder.main();
+ context_locator.main();
+ context_root.main();
+ defined_names.main();
driver.main();
driver_kernel.main();
driver_resolution.main();
@@ -34,8 +35,9 @@
index.main();
mutex.main();
referenced_names.main();
- search_test.main();
- session_helper_test.main();
- session_test.main();
+ search.main();
+ session_helper.main();
+ session.main();
+ uri_converter.main();
}, name: 'analysis');
}
diff --git a/pkg/analyzer/test/src/dart/analysis/uri_converter_test.dart b/pkg/analyzer/test/src/dart/analysis/uri_converter_test.dart
new file mode 100644
index 0000000..f400cee
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/analysis/uri_converter_test.dart
@@ -0,0 +1,98 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:analyzer/src/context/context_root.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
+import 'package:analyzer/src/dart/analysis/uri_converter.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/source/package_map_resolver.dart';
+import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../context/mock_sdk.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(DriverBasedUriConverterTest);
+ });
+}
+
+@reflectiveTest
+class DriverBasedUriConverterTest extends Object with ResourceProviderMixin {
+ DriverBasedUriConverter uriConverter;
+
+ void setUp() {
+ resourceProvider = new MemoryResourceProvider();
+
+ Folder barFolder = newFolder('/packages/bar/lib');
+ Folder fooFolder = newFolder('/packages/foo/lib');
+
+ SourceFactory sourceFactory = new SourceFactory([
+ new DartUriResolver(new MockSdk(resourceProvider: resourceProvider)),
+ new PackageMapUriResolver(resourceProvider, {
+ 'foo': [fooFolder],
+ 'bar': [barFolder],
+ }),
+ new ResourceUriResolver(resourceProvider),
+ ], null, resourceProvider);
+
+ ContextRoot contextRoot = new ContextRoot(barFolder.path, [],
+ pathContext: resourceProvider.pathContext);
+
+ MockAnalysisDriver driver = new MockAnalysisDriver();
+ driver.resourceProvider = resourceProvider;
+ driver.sourceFactory = sourceFactory;
+ driver.contextRoot = contextRoot;
+
+ uriConverter = new DriverBasedUriConverter(driver);
+ }
+
+ test_pathToUri_dart() {
+ expect(uriConverter.pathToUri(convertPath('/sdk/lib/core/core.dart')),
+ Uri.parse('dart:core'));
+ }
+
+ test_pathToUri_notRelative() {
+ expect(
+ uriConverter.pathToUri(convertPath('/packages/foo/lib/foo.dart'),
+ containingPath: convertPath('/packages/bar/lib/bar.dart')),
+ Uri.parse('package:foo/foo.dart'));
+ }
+
+ test_pathToUri_package() {
+ expect(uriConverter.pathToUri(convertPath('/packages/foo/lib/foo.dart')),
+ Uri.parse('package:foo/foo.dart'));
+ }
+
+ test_pathToUri_relative() {
+ expect(
+ uriConverter.pathToUri(convertPath('/packages/bar/lib/src/baz.dart'),
+ containingPath: convertPath('/packages/bar/lib/bar.dart')),
+ Uri.parse('src/baz.dart'));
+ }
+
+ test_uriToPath_dart() {
+ expect(uriConverter.uriToPath(Uri.parse('dart:core')),
+ convertPath('/sdk/lib/core/core.dart'));
+ }
+
+ test_uriToPath_package() {
+ expect(uriConverter.uriToPath(Uri.parse('package:foo/foo.dart')),
+ convertPath('/packages/foo/lib/foo.dart'));
+ }
+}
+
+class MockAnalysisDriver implements AnalysisDriver {
+ ResourceProvider resourceProvider;
+ SourceFactory sourceFactory;
+ ContextRoot contextRoot;
+
+ @override
+ dynamic noSuchMethod(Invocation invocation) {
+ fail('Unexpected invocation of ${invocation.memberName}');
+ }
+}
diff --git a/pkg/analyzer/test/src/dart/element/function_type_test.dart b/pkg/analyzer/test/src/dart/element/function_type_test.dart
index 8c1e001..5535b55 100644
--- a/pkg/analyzer/test/src/dart/element/function_type_test.dart
+++ b/pkg/analyzer/test/src/dart/element/function_type_test.dart
@@ -42,6 +42,8 @@
final listType = _makeListType();
+ final intType = new InterfaceTypeImpl(new MockClassElement('int'));
+
void basicChecks(FunctionType f,
{element,
displayName: '() → dynamic',
@@ -58,19 +60,23 @@
name: isNull}) {
// DartType properties
expect(f.displayName, displayName, reason: 'displayName');
- expect(f.element, element);
+ expect(f.element, element, reason: 'element');
expect(f.name, name, reason: 'name');
// ParameterizedType properties
expect(f.typeArguments, typeArguments, reason: 'typeArguments');
expect(f.typeParameters, typeParameters, reason: 'typeParameters');
// FunctionType properties
- expect(f.namedParameterTypes, namedParameterTypes);
+ expect(f.namedParameterTypes, namedParameterTypes,
+ reason: 'namedParameterTypes');
expect(f.normalParameterNames, normalParameterNames,
reason: 'normalParameterNames');
- expect(f.normalParameterTypes, normalParameterTypes);
- expect(f.optionalParameterNames, optionalParameterNames);
- expect(f.optionalParameterTypes, optionalParameterTypes);
- expect(f.parameters, parameters);
+ expect(f.normalParameterTypes, normalParameterTypes,
+ reason: 'normalParameterTypes');
+ expect(f.optionalParameterNames, optionalParameterNames,
+ reason: 'optionalParameterNames');
+ expect(f.optionalParameterTypes, optionalParameterTypes,
+ reason: 'optionalParameterTypes');
+ expect(f.parameters, parameters, reason: 'parameters');
expect(f.returnType, returnType ?? same(dynamicType), reason: 'returnType');
expect(f.typeFormals, typeFormals, reason: 'typeFormals');
}
@@ -80,25 +86,6 @@
DartType mapOf(DartType keyType, DartType valueType) =>
mapType.instantiate([keyType, valueType]);
- test_unnamedConstructor_nonTypedef_noTypeArguments() {
- var e = new MockFunctionTypedElement();
- FunctionType f = new FunctionTypeImpl(e);
- basicChecks(f, element: same(e));
- }
-
- test_unnamedConstructor_nonTypedef_withTypeArguments() {
- var t = new MockTypeParameterElement('T');
- var c = new MockClassElement('C', typeParameters: [t]);
- var e = new MockMethodElement(c, returnType: t.type);
- FunctionType f = new FunctionTypeImpl(e);
- basicChecks(f,
- element: same(e),
- typeArguments: [same(t.type)],
- typeParameters: [same(t)],
- displayName: '() → T',
- returnType: same(t.type));
- }
-
test_forInstantiatedTypedef_bothTypeParameters() {
var t = new MockTypeParameterElement('T');
var u = new MockTypeParameterElement('U');
@@ -433,12 +420,219 @@
typeParameters: [same(t)]);
}
+ test_synthetic() {
+ FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], []);
+ basicChecks(f, element: isNull);
+ }
+
+ test_synthetic_instantiate() {
+ // T Function<T>(T x)
+ var t = new MockTypeParameterElement('T');
+ var x = new MockParameterElement('x', type: t.type);
+ FunctionType f = new FunctionTypeImpl.synthetic(t.type, [t], [x]);
+ FunctionType instantiated = f.instantiate([objectType]);
+ basicChecks(instantiated,
+ element: isNull,
+ displayName: '(Object) → Object',
+ returnType: same(objectType),
+ normalParameterNames: ['x'],
+ normalParameterTypes: [same(objectType)],
+ parameters: hasLength(1));
+ }
+
+ test_synthetic_instantiate_argument_length_mismatch() {
+ // dynamic Function<T>()
+ var t = new MockTypeParameterElement('T');
+ FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [t], []);
+ expect(() => f.instantiate([]), throwsA(new isInstanceOf<ArgumentError>()));
+ }
+
+ test_synthetic_instantiate_no_type_formals() {
+ FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], []);
+ expect(f.instantiate([]), same(f));
+ }
+
+ test_synthetic_instantiate_share_parameters() {
+ // T Function<T>(int x)
+ var t = new MockTypeParameterElement('T');
+ var x = new MockParameterElement('x', type: intType);
+ FunctionType f = new FunctionTypeImpl.synthetic(t.type, [t], [x]);
+ FunctionType instantiated = f.instantiate([objectType]);
+ basicChecks(instantiated,
+ element: isNull,
+ displayName: '(int) → Object',
+ returnType: same(objectType),
+ normalParameterNames: ['x'],
+ normalParameterTypes: [same(intType)],
+ parameters: same(f.parameters));
+ }
+
+ test_synthetic_namedParameter() {
+ var p = new MockParameterElement('x',
+ type: objectType, parameterKind: ParameterKind.NAMED);
+ FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p]);
+ basicChecks(f,
+ element: isNull,
+ displayName: '({x: Object}) → dynamic',
+ namedParameterTypes: {'x': same(objectType)},
+ parameters: hasLength(1));
+ expect(f.parameters[0].isNamed, isTrue);
+ expect(f.parameters[0].name, 'x');
+ expect(f.parameters[0].type, same(objectType));
+ }
+
+ test_synthetic_normalParameter() {
+ var p = new MockParameterElement('x', type: objectType);
+ FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p]);
+ basicChecks(f,
+ element: isNull,
+ displayName: '(Object) → dynamic',
+ normalParameterNames: ['x'],
+ normalParameterTypes: [same(objectType)],
+ parameters: hasLength(1));
+ expect(f.parameters[0].isNotOptional, isTrue);
+ expect(f.parameters[0].name, 'x');
+ expect(f.parameters[0].type, same(objectType));
+ }
+
+ test_synthetic_optionalParameter() {
+ var p = new MockParameterElement('x',
+ type: objectType, parameterKind: ParameterKind.POSITIONAL);
+ FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p]);
+ basicChecks(f,
+ element: isNull,
+ displayName: '([Object]) → dynamic',
+ optionalParameterNames: ['x'],
+ optionalParameterTypes: [same(objectType)],
+ parameters: hasLength(1));
+ expect(f.parameters[0].isOptionalPositional, isTrue);
+ expect(f.parameters[0].name, 'x');
+ expect(f.parameters[0].type, same(objectType));
+ }
+
+ test_synthetic_returnType() {
+ FunctionType f = new FunctionTypeImpl.synthetic(objectType, [], []);
+ basicChecks(f,
+ element: isNull,
+ displayName: '() → Object',
+ returnType: same(objectType));
+ }
+
+ test_synthetic_substitute() {
+ // Map<T, U> Function<U extends T>(T x, U y)
+ var t = new MockTypeParameterElement('T');
+ var u = new MockTypeParameterElement('U', bound: t.type);
+ var x = new MockParameterElement('x', type: t.type);
+ var y = new MockParameterElement('y', type: u.type);
+ FunctionType f =
+ new FunctionTypeImpl.synthetic(mapOf(t.type, u.type), [u], [x, y]);
+ FunctionType substituted = f.substitute2([objectType], [t.type]);
+ var uSubstituted = substituted.typeFormals[0];
+ basicChecks(substituted,
+ element: isNull,
+ displayName: '<U extends Object>(Object, U) → Map<Object, U>',
+ returnType: mapOf(objectType, uSubstituted.type),
+ typeFormals: [uSubstituted],
+ normalParameterNames: ['x', 'y'],
+ normalParameterTypes: [same(objectType), same(uSubstituted.type)],
+ parameters: hasLength(2));
+ }
+
+ test_synthetic_substitute_argument_length_mismatch() {
+ // dynamic Function()
+ var t = new MockTypeParameterElement('T');
+ FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], []);
+ expect(() => f.substitute2([], [t.type]),
+ throwsA(new isInstanceOf<ArgumentError>()));
+ }
+
+ test_synthetic_substitute_share_returnType_and_parameters() {
+ // int Function<U extends T>(int x)
+ var t = new MockTypeParameterElement('T');
+ var u = new MockTypeParameterElement('U', bound: t.type);
+ var x = new MockParameterElement('x', type: intType);
+ FunctionType f = new FunctionTypeImpl.synthetic(intType, [u], [x]);
+ FunctionType substituted = f.substitute2([objectType], [t.type]);
+ basicChecks(substituted,
+ element: isNull,
+ displayName: '<U extends Object>(int) → int',
+ returnType: same(f.returnType),
+ typeFormals: hasLength(1),
+ normalParameterNames: ['x'],
+ normalParameterTypes: [same(intType)],
+ parameters: same(f.parameters));
+ expect(substituted.typeFormals[0].name, 'U');
+ expect(substituted.typeFormals[0].bound, same(objectType));
+ }
+
+ test_synthetic_substitute_share_returnType_and_typeFormals() {
+ // int Function<U>(T x, U y)
+ var t = new MockTypeParameterElement('T');
+ var u = new MockTypeParameterElement('U');
+ var x = new MockParameterElement('x', type: t.type);
+ var y = new MockParameterElement('y', type: u.type);
+ FunctionType f = new FunctionTypeImpl.synthetic(intType, [u], [x, y]);
+ FunctionType substituted = f.substitute2([objectType], [t.type]);
+ basicChecks(substituted,
+ element: isNull,
+ displayName: '<U>(Object, U) → int',
+ returnType: same(f.returnType),
+ typeFormals: same(f.typeFormals),
+ normalParameterNames: ['x', 'y'],
+ normalParameterTypes: [same(objectType), same(u.type)],
+ parameters: hasLength(2));
+ }
+
+ test_synthetic_substitute_share_typeFormals_and_parameters() {
+ // T Function<U>(U x)
+ var t = new MockTypeParameterElement('T');
+ var u = new MockTypeParameterElement('U');
+ var x = new MockParameterElement('x', type: u.type);
+ FunctionType f = new FunctionTypeImpl.synthetic(t.type, [u], [x]);
+ FunctionType substituted = f.substitute2([objectType], [t.type]);
+ basicChecks(substituted,
+ element: isNull,
+ displayName: '<U>(U) → Object',
+ returnType: same(objectType),
+ typeFormals: same(f.typeFormals),
+ normalParameterNames: ['x'],
+ normalParameterTypes: [same(u.type)],
+ parameters: same(f.parameters));
+ }
+
+ test_synthetic_substitute_unchanged() {
+ // dynamic Function<U>(U x)
+ var t = new MockTypeParameterElement('T');
+ var u = new MockTypeParameterElement('U');
+ var x = new MockParameterElement('x', type: u.type);
+ FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [u], [x]);
+ FunctionType substituted = f.substitute2([objectType], [t.type]);
+ expect(substituted, same(f));
+ }
+
+ test_synthetic_typeFormals() {
+ var t = new MockTypeParameterElement('T');
+ FunctionType f = new FunctionTypeImpl.synthetic(t.type, [t], []);
+ basicChecks(f,
+ element: isNull,
+ displayName: '<T>() → T',
+ returnType: same(t.type),
+ typeFormals: [same(t)]);
+ }
+
test_unnamedConstructor() {
var e = new MockFunctionTypedElement();
FunctionType f = new FunctionTypeImpl(e);
basicChecks(f, element: same(e));
}
+ test_unnamedConstructor_instantiate_argument_length_mismatch() {
+ var t = new MockTypeParameterElement('T');
+ var e = new MockFunctionTypedElement(typeParameters: [t]);
+ FunctionType f = new FunctionTypeImpl(e);
+ expect(() => f.instantiate([]), throwsA(new isInstanceOf<ArgumentError>()));
+ }
+
test_unnamedConstructor_instantiate_noop() {
var t = new MockTypeParameterElement('T');
var p = new MockParameterElement('x', type: t.type);
@@ -454,7 +648,6 @@
normalParameterTypes: [same(t.type)],
parameters: [same(p)]);
expect(instantiated.typeArguments[0], same(t.type));
- // TODO(paulberry): test instantiate length mismatch
}
test_unnamedConstructor_instantiate_noTypeParameters() {
@@ -520,6 +713,25 @@
parameters: [same(p)]);
}
+ test_unnamedConstructor_nonTypedef_noTypeArguments() {
+ var e = new MockFunctionTypedElement();
+ FunctionType f = new FunctionTypeImpl(e);
+ basicChecks(f, element: same(e));
+ }
+
+ test_unnamedConstructor_nonTypedef_withTypeArguments() {
+ var t = new MockTypeParameterElement('T');
+ var c = new MockClassElement('C', typeParameters: [t]);
+ var e = new MockMethodElement(c, returnType: t.type);
+ FunctionType f = new FunctionTypeImpl(e);
+ basicChecks(f,
+ element: same(e),
+ typeArguments: [same(t.type)],
+ typeParameters: [same(t)],
+ displayName: '() → T',
+ returnType: same(t.type));
+ }
+
test_unnamedConstructor_normalParameter() {
var p = new MockParameterElement('x');
var e = new MockFunctionTypedElement(parameters: [p]);
@@ -596,6 +808,18 @@
basicChecks(f, element: same(e));
}
+ test_unnamedConstructor_substitute_argument_length_mismatch() {
+ // abstract class C<T> {
+ // dynamic f();
+ // }
+ var t = new MockTypeParameterElement('T');
+ var c = new MockClassElement('C', typeParameters: [t]);
+ var e = new MockFunctionTypedElement(enclosingElement: c);
+ FunctionType f = new FunctionTypeImpl(e);
+ expect(() => f.substitute2([], [t.type]),
+ throwsA(new isInstanceOf<ArgumentError>()));
+ }
+
test_unnamedConstructor_substitute_bound_recursive() {
// abstract class C<T> {
// Map<S, V> f<S extends T, T extends U, V extends T>();
@@ -644,6 +868,62 @@
}
}
+ test_unnamedConstructor_substitute_bound_recursive_parameter() {
+ // abstract class C<T> {
+ // void f<S extends T, T extends U, V extends T>(S x, V y);
+ // }
+ var s = new MockTypeParameterElement('S');
+ var t = new MockTypeParameterElement('T');
+ var u = new MockTypeParameterElement('U');
+ var v = new MockTypeParameterElement('V');
+ s.bound = t.type;
+ t.bound = u.type;
+ v.bound = t.type;
+ var c = new MockClassElement('C', typeParameters: [u]);
+ var x = new MockParameterElement('x', type: s.type);
+ var y = new MockParameterElement('y', type: v.type);
+ var e = new MockFunctionTypedElement(
+ returnType: voidType,
+ typeParameters: [s, t, v],
+ enclosingElement: c,
+ parameters: [x, y]);
+ FunctionType f = new FunctionTypeImpl(e);
+ var substituted = f.substitute2([objectType], [u.type]);
+ basicChecks(substituted,
+ element: same(e),
+ displayName: isNotNull,
+ returnType: same(voidType),
+ normalParameterNames: ['x', 'y'],
+ normalParameterTypes: hasLength(2),
+ parameters: hasLength(2),
+ typeFormals: hasLength(3),
+ typeParameters: [same(u)],
+ typeArguments: [same(objectType)]);
+ if (bug_33300_fixed) {
+ expect(substituted.displayName,
+ '<S extends T,T extends Object,V extends T>(S, V) → void');
+ } else {
+ expect(
+ substituted.displayName,
+ '<S extends T extends Object,T extends Object,V extends T>(S, V) '
+ '→ void');
+ }
+ var s2 = substituted.typeFormals[0];
+ var t2 = substituted.typeFormals[1];
+ var v2 = substituted.typeFormals[2];
+ expect(s2.name, 'S');
+ expect(t2.name, 'T');
+ expect(v2.name, 'V');
+ expect(s2.bound, t2.type);
+ expect(t2.bound, same(objectType));
+ expect(v2.bound, t2.type);
+ if (bug_33301_fixed) {
+ expect(substituted.normalParameterTypes, [same(s2.type), same(v2.type)]);
+ } else {
+ expect(substituted.normalParameterTypes, [same(s.type), same(v.type)]);
+ }
+ }
+
test_unnamedConstructor_substitute_bound_simple() {
// abstract class C<T> {
// U f<U extends T>();
@@ -775,7 +1055,7 @@
}
}
-class MockClassElement implements ClassElement {
+class MockClassElement implements ClassElementImpl {
@override
final List<TypeParameterElement> typeParameters;
@@ -939,7 +1219,10 @@
ClassElement get enclosingElement => super.enclosingElement;
}
-class MockParameterElement implements ParameterElement {
+class MockParameterElement implements ParameterElementImpl {
+ @override
+ Element enclosingElement;
+
@override
final String name;
diff --git a/pkg/analyzer/test/src/fasta/body_builder_test_helper.dart b/pkg/analyzer/test/src/fasta/body_builder_test_helper.dart
index fc243e5..66b2d52 100644
--- a/pkg/analyzer/test/src/fasta/body_builder_test_helper.dart
+++ b/pkg/analyzer/test/src/fasta/body_builder_test_helper.dart
@@ -40,27 +40,132 @@
import '../../generated/parser_test.dart';
import '../../generated/test_support.dart';
+Element _buildElement(kernel.Class coreType) {
+ ClassElementImpl element =
+ new ClassElementImpl(coreType.name, coreType.fileOffset);
+ element.typeParameters = coreType.typeParameters.map((parameter) {
+ TypeParameterElementImpl element =
+ new TypeParameterElementImpl(parameter.name, parameter.fileOffset);
+ element.type = new TypeParameterTypeImpl(element);
+ return element;
+ }).toList();
+ return element;
+}
+
+class CompilerTestContext extends CompilerContext {
+ KernelTarget kernelTarget;
+ TypeProvider _typeProvider;
+
+ CompilerTestContext(ProcessedOptions options) : super(options);
+
+ Uri get entryPoint => options.inputs.single;
+
+ static Future<T> runWithTestOptions<T>(
+ Future<T> action(CompilerTestContext c)) async {
+ // TODO(danrubel): Consider HybridFileSystem.
+ final MemoryFileSystem fs =
+ new MemoryFileSystem(Uri.parse("org-dartlang-test:///"));
+
+ /// The custom URI used to locate the dill file in the MemoryFileSystem.
+ final Uri sdkSummary = fs.currentDirectory.resolve("vm_platform.dill");
+
+ /// The in memory test code URI
+ final Uri entryPoint = fs.currentDirectory.resolve("main.dart");
+
+ // Read the dill file containing kernel platform summaries into memory.
+ List<int> sdkSummaryBytes = await new File.fromUri(
+ computePlatformBinariesLocation().resolve("vm_platform.dill"))
+ .readAsBytes();
+ fs.entityForUri(sdkSummary).writeAsBytesSync(sdkSummaryBytes);
+
+ final CompilerOptions optionBuilder = new CompilerOptions()
+ ..strongMode = false // TODO(danrubel): enable strong mode.
+ ..reportMessages = true
+ ..verbose = false
+ ..fileSystem = fs
+ ..sdkSummary = sdkSummary
+ ..onProblem = (FormattedMessage problem, Severity severity,
+ List<FormattedMessage> context) {
+ // TODO(danrubel): Capture problems and check against expectations.
+// print(problem.formatted);
+ };
+
+ final ProcessedOptions options =
+ new ProcessedOptions(optionBuilder, [entryPoint]);
+
+ UriTranslatorImpl uriTranslator = await options.getUriTranslator();
+
+ return await new CompilerTestContext(options)
+ .runInContext<T>((CompilerContext _c) async {
+ CompilerTestContext c = _c;
+ DillTarget dillTarget = new DillTarget(
+ new Ticker(isVerbose: false), uriTranslator, options.target);
+
+ c.kernelTarget = new KernelTarget(fs, true, dillTarget, uriTranslator);
+
+ // Load the dill file containing platform code.
+ dillTarget.loader.read(Uri.parse('dart:core'), -1, fileUri: sdkSummary);
+ kernel.Component sdkComponent =
+ kernel.loadComponentFromBytes(sdkSummaryBytes);
+ dillTarget.loader
+ .appendLibraries(sdkComponent, byteCount: sdkSummaryBytes.length);
+ await dillTarget.buildOutlines();
+ await c.kernelTarget.buildOutlines();
+ c.kernelTarget.computeCoreTypes();
+ assert(c.kernelTarget.loader.coreTypes != null);
+
+ // Initialize the typeProvider if types should be resolved.
+ Map<String, Element> map = <String, Element>{};
+ var coreTypes = c.kernelTarget.loader.coreTypes;
+ for (var coreType in [
+ coreTypes.boolClass,
+ coreTypes.doubleClass,
+ coreTypes.functionClass,
+ coreTypes.futureClass,
+ coreTypes.futureOrClass,
+ coreTypes.intClass,
+ coreTypes.iterableClass,
+ coreTypes.iteratorClass,
+ coreTypes.listClass,
+ coreTypes.mapClass,
+ coreTypes.nullClass,
+ coreTypes.numClass,
+ coreTypes.objectClass,
+ coreTypes.stackTraceClass,
+ coreTypes.streamClass,
+ coreTypes.stringClass,
+ coreTypes.symbolClass,
+ coreTypes.typeClass
+ ]) {
+ map[coreType.name] = _buildElement(coreType);
+ }
+ Namespace namespace = new Namespace(map);
+ c._typeProvider =
+ new TypeProviderImpl.forNamespaces(namespace, namespace);
+
+ T result;
+ Completer<T> completer = new Completer<T>();
+ // Since we're using `package:test_reflective_loader`, we can't rely on
+ // normal async behavior, as `defineReflectiveSuite` doesn't return a
+ // future. However, since it's built on top of `package:test`, we can
+ // obtain a future that completes when all the tests are done using
+ // `tearDownAll`. This allows this function to complete no earlier than
+ // when the tests are done. This is important, as we don't want to call
+ // `CompilerContext.clear` before then.
+ tearDownAll(() => completer.complete(result));
+ result = await action(c);
+ return completer.future;
+ });
+ }
+
+ static CompilerTestContext get current => CompilerContext.current;
+}
+
/// Implementation of [AbstractParserTestCase] specialized for testing building
/// Analyzer AST using the fasta [Forest] API.
class FastaBodyBuilderTestCase extends Object
with ParserTestHelpers
implements AbstractParserTestCase {
- // TODO(danrubel): Consider HybridFileSystem.
- static final MemoryFileSystem fs =
- new MemoryFileSystem(Uri.parse("org-dartlang-test:///"));
-
- /// The custom URI used to locate the dill file in the MemoryFileSystem.
- static final Uri sdkSummary = fs.currentDirectory.resolve("vm_platform.dill");
-
- /// The in memory test code URI
- static final Uri entryPoint = fs.currentDirectory.resolve("main.dart");
-
- static ProcessedOptions options;
-
- static KernelTarget kernelTarget;
-
- static TypeProvider _typeProvider;
-
final bool resolveTypes;
String content;
@@ -69,11 +174,18 @@
/// finished parsing, or `null` (the default) if EOF is expected.
int expectedEndOffset;
+ @override
+ void set enableGenericMethodComments(_) {
+ // Ignored.
+ }
+
FastaBodyBuilderTestCase(this.resolveTypes);
analyzer.Parser get parser => new ParserProxy(this);
- TypeProvider get typeProvider => _typeProvider;
+ TypeProvider get typeProvider => CompilerTestContext.current._typeProvider;
+
+ bool get usingFastaParser => true;
@override
void assertNoErrors() {
@@ -90,6 +202,11 @@
// TODO(brianwilkerson) Implement this.
}
+ @override
+ ExpectedError expectedError(ErrorCode code, int offset, int length) {
+ return new ExpectedError(code, offset, length);
+ }
+
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
@override
@@ -396,156 +513,68 @@
return statement.variables;
}
- Future setUp() async {
- // TODO(danrubel): Tear down once all tests in group have been run.
- if (options != null) {
- return;
- }
-
- // Read the dill file containing kernel platform summaries into memory.
- List<int> sdkSummaryBytes = await new File.fromUri(
- computePlatformBinariesLocation().resolve("vm_platform.dill"))
- .readAsBytes();
- fs.entityForUri(sdkSummary).writeAsBytesSync(sdkSummaryBytes);
-
- final CompilerOptions optionBuilder = new CompilerOptions()
- ..strongMode = false // TODO(danrubel): enable strong mode.
- ..reportMessages = true
- ..verbose = false
- ..fileSystem = fs
- ..sdkSummary = sdkSummary
- ..onProblem = (FormattedMessage problem, Severity severity,
- List<FormattedMessage> context) {
- // TODO(danrubel): Capture problems and check against expectations.
-// print(problem.formatted);
- };
-
- options = new ProcessedOptions(optionBuilder, [entryPoint]);
-
- UriTranslatorImpl uriTranslator = await options.getUriTranslator();
-
- await CompilerContext.runWithOptions(options, (CompilerContext c) async {
- DillTarget dillTarget = new DillTarget(
- new Ticker(isVerbose: false), uriTranslator, options.target);
-
- kernelTarget = new KernelTarget(fs, true, dillTarget, uriTranslator);
-
- // Load the dill file containing platform code.
- dillTarget.loader.read(Uri.parse('dart:core'), -1, fileUri: sdkSummary);
- kernel.Component sdkComponent =
- kernel.loadComponentFromBytes(sdkSummaryBytes);
- dillTarget.loader
- .appendLibraries(sdkComponent, byteCount: sdkSummaryBytes.length);
- await dillTarget.buildOutlines();
- await kernelTarget.buildOutlines();
- kernelTarget.computeCoreTypes();
- assert(kernelTarget.loader.coreTypes != null);
-
- // Initialize the typeProvider if types should be resolved.
- Map<String, Element> map = <String, Element>{};
- var coreTypes = kernelTarget.loader.coreTypes;
- for (var coreType in [
- coreTypes.boolClass,
- coreTypes.doubleClass,
- coreTypes.functionClass,
- coreTypes.futureClass,
- coreTypes.futureOrClass,
- coreTypes.intClass,
- coreTypes.iterableClass,
- coreTypes.iteratorClass,
- coreTypes.listClass,
- coreTypes.mapClass,
- coreTypes.nullClass,
- coreTypes.numClass,
- coreTypes.objectClass,
- coreTypes.stackTraceClass,
- coreTypes.streamClass,
- coreTypes.stringClass,
- coreTypes.symbolClass,
- coreTypes.typeClass
- ]) {
- map[coreType.name] = _buildElement(coreType);
- }
- Namespace namespace = new Namespace(map);
- _typeProvider = new TypeProviderImpl.forNamespaces(namespace, namespace);
- });
- }
-
- Element _buildElement(kernel.Class coreType) {
- ClassElementImpl element =
- new ClassElementImpl(coreType.name, coreType.fileOffset);
- element.typeParameters = coreType.typeParameters.map((parameter) {
- TypeParameterElementImpl element =
- new TypeParameterElementImpl(parameter.name, parameter.fileOffset);
- element.type = new TypeParameterTypeImpl(element);
- return element;
- }).toList();
- return element;
- }
-
T _parse<T>(
String source, void parseFunction(Parser parser, Token previousToken),
{bool inAsync: false, bool inCatchBlock: false}) {
ScannerResult scan = scanString(source);
- return CompilerContext.runWithOptions(options, (CompilerContext c) {
- KernelLibraryBuilder library = new KernelLibraryBuilder(
- entryPoint,
- entryPoint,
- kernelTarget.loader,
- null /* actualOrigin */,
- null /* enclosingLibrary */,
- );
- List<KernelTypeVariableBuilder> typeVariableBuilders =
- <KernelTypeVariableBuilder>[];
- List<KernelFormalParameterBuilder> formalParameterBuilders =
- <KernelFormalParameterBuilder>[];
- KernelProcedureBuilder procedureBuilder = new KernelProcedureBuilder(
- null /* metadata */,
- Modifier.staticMask /* or Modifier.varMask */,
- kernelTarget.dynamicType,
- "analyzerTest",
- typeVariableBuilders,
- formalParameterBuilders,
- kernel.ProcedureKind.Method,
- library,
- -1 /* charOffset */,
- -1 /* charOpenParenOffset */,
- -1 /* charEndOffset */);
-
- TypeInferrerDisabled typeInferrer =
- new TypeInferrerDisabled(new TypeSchemaEnvironment(
- kernelTarget.loader.coreTypes,
- kernelTarget.loader.hierarchy,
- // TODO(danrubel): Enable strong mode.
- false /* strong mode */,
- ));
-
- AstBodyBuilder builder = new AstBodyBuilder(
+ CompilerTestContext c = CompilerTestContext.current;
+ KernelLibraryBuilder library = new KernelLibraryBuilder(
+ c.entryPoint,
+ c.entryPoint,
+ c.kernelTarget.loader,
+ null /* actualOrigin */,
+ null /* enclosingLibrary */,
+ );
+ List<KernelTypeVariableBuilder> typeVariableBuilders =
+ <KernelTypeVariableBuilder>[];
+ List<KernelFormalParameterBuilder> formalParameterBuilders =
+ <KernelFormalParameterBuilder>[];
+ KernelProcedureBuilder procedureBuilder = new KernelProcedureBuilder(
+ null /* metadata */,
+ Modifier.staticMask /* or Modifier.varMask */,
+ c.kernelTarget.dynamicType,
+ "analyzerTest",
+ typeVariableBuilders,
+ formalParameterBuilders,
+ kernel.ProcedureKind.Method,
library,
- procedureBuilder,
- new UnlinkedScope(),
- null,
- kernelTarget.loader.hierarchy,
- kernelTarget.loader.coreTypes,
- null /* classBuilder */,
- false /* isInstanceMember */,
- null /* uri */,
- typeInferrer,
- typeProvider,
- )..constantContext = ConstantContext.none; // .inferred ?
+ -1 /* charOffset */,
+ -1 /* charOpenParenOffset */,
+ -1 /* charEndOffset */);
- Parser parser = new Parser(builder);
- if (inAsync) {
- parser.asyncState = AsyncModifier.Async;
- }
- if (inCatchBlock) {
- builder.inCatchBlock = inCatchBlock;
- }
- parseFunction(parser, parser.syntheticPreviousToken(scan.tokens));
- // TODO(brianwilkerson) Check `expectedEndOffset` if it is not `null`.
- return builder.pop();
- });
+ TypeInferrerDisabled typeInferrer =
+ new TypeInferrerDisabled(new TypeSchemaEnvironment(
+ c.kernelTarget.loader.coreTypes,
+ c.kernelTarget.loader.hierarchy,
+ // TODO(danrubel): Enable strong mode.
+ false /* strong mode */,
+ ));
+
+ AstBodyBuilder builder = new AstBodyBuilder(
+ library,
+ procedureBuilder,
+ new UnlinkedScope(),
+ null,
+ c.kernelTarget.loader.hierarchy,
+ c.kernelTarget.loader.coreTypes,
+ null /* classBuilder */,
+ false /* isInstanceMember */,
+ null /* uri */,
+ typeInferrer,
+ typeProvider,
+ )..constantContext = ConstantContext.none; // .inferred ?
+
+ Parser parser = new Parser(builder);
+ if (inAsync) {
+ parser.asyncState = AsyncModifier.Async;
+ }
+ if (inCatchBlock) {
+ builder.inCatchBlock = inCatchBlock;
+ }
+ parseFunction(parser, parser.syntheticPreviousToken(scan.tokens));
+ // TODO(brianwilkerson) Check `expectedEndOffset` if it is not `null`.
+ return builder.pop();
}
}
diff --git a/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart b/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
index d312b78..492f026 100644
--- a/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
@@ -29,7 +29,6 @@
''');
}
- @failingTest
void test_missingComma() {
testRecovery('''
f() => [a, b c];
diff --git a/pkg/analyzer/test/src/fasta/recovery/paired_tokens_test.dart b/pkg/analyzer/test/src/fasta/recovery/paired_tokens_test.dart
index fdd1f54..edc6d29 100644
--- a/pkg/analyzer/test/src/fasta/recovery/paired_tokens_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/paired_tokens_test.dart
@@ -238,9 +238,7 @@
''');
}
- @failingTest
void test_listLiteral_inner_last() {
- // Parser crashes
testRecovery('''
var x = [[0], [1];
''', [ScannerErrorCode.EXPECTED_TOKEN], '''
@@ -248,13 +246,19 @@
''');
}
- @failingTest
void test_listLiteral_inner_notLast() {
- // Parser crashes
testRecovery('''
var x = [[0], [1, [2]];
''', [ScannerErrorCode.EXPECTED_TOKEN], '''
-var x = [[0], [1], [2]];
+var x = [[0], [1, [2]]];
+''');
+ }
+
+ void test_listLiteral_missing_comma() {
+ testRecovery('''
+var x = [0 1];
+''', [ParserErrorCode.EXPECTED_TOKEN], '''
+var x = [0, 1];
''');
}
diff --git a/pkg/analyzer/test/src/fasta/resolution_test.dart b/pkg/analyzer/test/src/fasta/resolution_test.dart
index 0eedb6b..1fbaa11 100644
--- a/pkg/analyzer/test/src/fasta/resolution_test.dart
+++ b/pkg/analyzer/test/src/fasta/resolution_test.dart
@@ -10,9 +10,11 @@
import '../../generated/parser_test.dart';
import 'body_builder_test_helper.dart';
-main() async {
- defineReflectiveSuite(() {
- defineReflectiveTests(ResolutionTest);
+main() {
+ return CompilerTestContext.runWithTestOptions((_) {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ResolutionTest);
+ });
});
}
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 0362a9f..dd8e30b 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -8140,6 +8140,21 @@
''');
}
+ test_metadata_enumConstantDeclaration() async {
+ var library = await checkLibrary('const a = null; enum E { @a v }');
+ checkElementText(library, r'''
+enum E {
+ synthetic final int index;
+ synthetic static const List<E> values;
+ @
+ a/*location: test.dart;a?*/
+ static const E v;
+ String toString() {}
+}
+const dynamic a = null;
+''');
+ }
+
test_metadata_enumDeclaration() async {
var library = await checkLibrary('const a = null; @a enum E { v }');
checkElementText(library, r'''
diff --git a/pkg/analyzer/test/src/summary/summary_common.dart b/pkg/analyzer/test/src/summary/summary_common.dart
index 37b5eca..0f78b0f 100644
--- a/pkg/analyzer/test/src/summary/summary_common.dart
+++ b/pkg/analyzer/test/src/summary/summary_common.dart
@@ -8674,6 +8674,12 @@
.annotations);
}
+ test_metadata_enumConstantDeclaration() {
+ checkAnnotationA(serializeEnumText('const a = null; enum E { @a v }')
+ .values[0]
+ .annotations);
+ }
+
test_metadata_enumDeclaration() {
checkAnnotationA(
serializeEnumText('const a = null; @a enum E { v }').annotations);
diff --git a/pkg/analyzer/tool/summary/generate.dart b/pkg/analyzer/tool/summary/generate.dart
index 0fc27f1..1604d01 100644
--- a/pkg/analyzer/tool/summary/generate.dart
+++ b/pkg/analyzer/tool/summary/generate.dart
@@ -312,7 +312,7 @@
cls.allFields.add(new idlModel.FieldDeclaration(doc,
classMember.name, fieldType, id, isDeprecated, isInformative));
} else if (classMember is ConstructorDeclaration &&
- classMember.name.name.endsWith('fromBuffer')) {
+ classMember.name.endsWith('fromBuffer')) {
// Ignore `fromBuffer` declarations; they simply forward to the
// read functions generated by [_generateReadFunction].
} else {
diff --git a/pkg/analyzer/tool/summary/mini_ast.dart b/pkg/analyzer/tool/summary/mini_ast.dart
index 6dc47f7..d715e53 100644
--- a/pkg/analyzer/tool/summary/mini_ast.dart
+++ b/pkg/analyzer/tool/summary/mini_ast.dart
@@ -85,22 +85,13 @@
/// "Mini AST" representation of a constructor declaration.
class ConstructorDeclaration extends ClassMember {
- final ConstructorReference name;
+ final String name;
ConstructorDeclaration(
Comment documentationComment, List<Annotation> metadata, this.name)
: super(documentationComment, metadata);
}
-/// "Mini AST" representation of a constructor reference.
-class ConstructorReference {
- final String name;
-
- final String constructorName;
-
- ConstructorReference(this.name, this.constructorName);
-}
-
/// "Mini AST" representation of an individual enum constant in an enum
/// declaration.
class EnumConstantDeclaration extends AnnotatedNode {
@@ -218,16 +209,6 @@
}
}
- @override
- void endConstructorReference(
- Token start, Token periodBeforeName, Token endToken) {
- debugEvent("ConstructorReference");
- String constructorName = popIfNotNull(periodBeforeName);
- pop(); // Type arguments
- String name = pop();
- push(new ConstructorReference(name, constructorName));
- }
-
void endEnum(Token enumKeyword, Token leftBrace, int count) {
debugEvent("Enum");
List<EnumConstantDeclaration> constants =
@@ -245,7 +226,8 @@
Token beginToken, Token factoryKeyword, Token endToken) {
debugEvent("FactoryMethod");
pop(); // Body
- ConstructorReference name = pop();
+ pop(); // Type variables
+ String name = pop();
List<Annotation> metadata = pop();
Comment comment = pop();
push(new ConstructorDeclaration(comment, metadata, name));
@@ -338,11 +320,12 @@
void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
debugEvent("Metadata");
inMetadata = false;
- List<Expression> arguments = pop();
+ List arguments = pop();
String constructorName = popIfNotNull(periodBeforeName);
pop(); // Type arguments
String name = pop();
- push(new Annotation(name, constructorName, arguments));
+ push(new Annotation(name, constructorName,
+ arguments == null ? null : arguments.cast<Expression>()));
}
@override
diff --git a/pkg/analyzer_cli/lib/src/analyzer_impl.dart b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
index b3b94a9..1974fc4 100644
--- a/pkg/analyzer_cli/lib/src/analyzer_impl.dart
+++ b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
@@ -5,15 +5,14 @@
library analyzer_cli.src.analyzer_impl;
import 'dart:async';
-import 'dart:collection';
import 'dart:io';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
+import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult;
-import 'package:analyzer/src/generated/java_io.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
@@ -36,24 +35,20 @@
final int startTime;
final AnalysisOptions analysisOptions;
- final AnalysisContext context;
final AnalysisDriver analysisDriver;
/// Accumulated analysis statistics.
final AnalysisStats stats;
- final Source librarySource;
+ /// The library file to analyze.
+ final FileState libraryFile;
- /// All [Source]s references by the analyzed library.
- final Set<Source> sources = new Set<Source>();
+ /// All files references by the analyzed library.
+ final Set<String> files = new Set<String>();
/// All [AnalysisErrorInfo]s in the analyzed library.
final List<AnalysisErrorInfo> errorInfos = new List<AnalysisErrorInfo>();
- /// [HashMap] between sources and analysis error infos.
- final HashMap<Source, AnalysisErrorInfo> sourceErrorsMap =
- new HashMap<Source, AnalysisErrorInfo>();
-
/// If the file specified on the command line is part of a package, the name
/// of that package. Otherwise `null`. This allows us to analyze the file
/// specified on the command line as though it is reached via a "package:"
@@ -61,8 +56,8 @@
/// specified the "--package-warnings" option.
String _selfPackageName;
- AnalyzerImpl(this.analysisOptions, this.context, this.analysisDriver,
- this.librarySource, this.options, this.stats, this.startTime);
+ AnalyzerImpl(this.analysisOptions, this.analysisDriver, this.libraryFile,
+ this.options, this.stats, this.startTime);
void addCompilationUnitSource(
CompilationUnitElement unit, Set<CompilationUnitElement> units) {
@@ -71,7 +66,7 @@
}
Source source = unit.source;
if (source != null) {
- sources.add(source);
+ files.add(source.fullName);
}
}
@@ -105,6 +100,8 @@
/// it will be marked as being for a cold VM.
Future<ErrorSeverity> analyze(ErrorFormatter formatter,
{int printMode: 1}) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
setupForAnalysis();
return await _analyze(printMode, formatter);
}
@@ -123,27 +120,23 @@
return status;
}
- /// Fills [errorInfos] using [sources].
+ /// Fills [errorInfos] using [files].
Future<Null> prepareErrors() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
PerformanceTag previous = _prepareErrorsTag.makeCurrent();
try {
- for (Source source in sources) {
- if (analysisDriver != null) {
- String path = source.fullName;
- ErrorsResult errorsResult = await analysisDriver.getErrors(path);
- errorInfos.add(new AnalysisErrorInfoImpl(
- errorsResult.errors, errorsResult.lineInfo));
- } else {
- context.computeErrors(source);
- errorInfos.add(context.getErrors(source));
- }
+ for (String path in files) {
+ ErrorsResult errorsResult = await analysisDriver.getErrors(path);
+ errorInfos.add(new AnalysisErrorInfoImpl(
+ errorsResult.errors, errorsResult.lineInfo));
}
} finally {
previous.makeCurrent();
}
}
- /// Fills [sources].
+ /// Fills [files].
void prepareSources(LibraryElement library) {
var units = new Set<CompilationUnitElement>();
var libraries = new Set<LibraryElement>();
@@ -152,9 +145,9 @@
/// Setup local fields such as the analysis context for analysis.
void setupForAnalysis() {
- sources.clear();
+ files.clear();
errorInfos.clear();
- Uri libraryUri = librarySource.uri;
+ Uri libraryUri = libraryFile.uri;
if (libraryUri.scheme == 'package' && libraryUri.pathSegments.length > 0) {
_selfPackageName = libraryUri.pathSegments[0];
}
@@ -162,14 +155,13 @@
Future<ErrorSeverity> _analyze(
int printMode, ErrorFormatter formatter) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// Don't try to analyze parts.
- String path = librarySource.fullName;
- SourceKind librarySourceKind = analysisDriver != null
- ? await analysisDriver.getSourceKind(path)
- : context.computeKindOf(librarySource);
- if (librarySourceKind == SourceKind.PART) {
+ if (libraryFile.isPart) {
+ String libraryPath = libraryFile.path;
stderr.writeln("Only libraries can be analyzed.");
- stderr.writeln("$path is a part and can not be analyzed.");
+ stderr.writeln("$libraryPath is a part and can not be analyzed.");
return ErrorSeverity.ERROR;
}
@@ -207,7 +199,6 @@
}
}
- // TODO(devoncarew): This is never called.
/// Determine whether the given URI refers to a package being analyzed.
bool _isAnalyzedPackage(Uri uri) {
if (uri.scheme != 'package' || uri.pathSegments.isEmpty) {
@@ -225,6 +216,7 @@
}
}
+ // TODO(devoncarew): This is never called.
void _printColdPerf() {
// Print cold VM performance numbers.
int totalTime = currentTimeMillis - startTime;
@@ -241,39 +233,20 @@
}
Future<LibraryElement> _resolveLibrary() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
PerformanceTag previous = _resolveLibraryTag.makeCurrent();
try {
- if (analysisDriver != null) {
- String path = librarySource.fullName;
- analysisDriver.priorityFiles = [path];
- UnitElementResult elementResult =
- await analysisDriver.getUnitElement(path);
- return elementResult.element.library;
- } else {
- return context.computeLibraryElement(librarySource);
- }
+ String libraryPath = libraryFile.path;
+ analysisDriver.priorityFiles = [libraryPath];
+ UnitElementResult elementResult =
+ await analysisDriver.getUnitElement(libraryPath);
+ return elementResult.element.library;
} finally {
previous.makeCurrent();
}
}
- /// Return the corresponding package directory or `null` if none is found.
- static JavaFile getPackageDirectoryFor(JavaFile sourceFile) {
- // We are going to ask parent file, so get absolute path.
- sourceFile = sourceFile.getAbsoluteFile();
- // Look in the containing directories.
- JavaFile dir = sourceFile.getParentFile();
- while (dir != null) {
- JavaFile packagesDir = new JavaFile.relative(dir, "packages");
- if (packagesDir.exists()) {
- return packagesDir;
- }
- dir = dir.getParentFile();
- }
- // Not found.
- return null;
- }
-
/// Return `true` if the given [pathName] is in the Pub cache.
static bool _isPathInPubCache(String pathName) {
List<String> parts = path.split(pathName);
diff --git a/pkg/analyzer_cli/lib/src/batch_mode.dart b/pkg/analyzer_cli/lib/src/batch_mode.dart
index 0bd9d6f..5bd75b0 100644
--- a/pkg/analyzer_cli/lib/src/batch_mode.dart
+++ b/pkg/analyzer_cli/lib/src/batch_mode.dart
@@ -32,6 +32,8 @@
Stream<String> cmdLine =
stdin.transform(utf8.decoder).transform(new LineSplitter());
cmdLine.listen((String line) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// Maybe finish.
if (line.isEmpty) {
var time = stopwatch.elapsedMilliseconds;
diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart
index 87f6f10..d83ab5e 100644
--- a/pkg/analyzer_cli/lib/src/build_mode.dart
+++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -70,6 +70,8 @@
*/
Future<Null> analyze(
CommandLineOptions options, Map<String, WorkerInput> inputs) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
var packageBundleProvider =
new WorkerPackageBundleProvider(packageBundleCache, inputs);
var buildMode = new BuildMode(
@@ -88,7 +90,11 @@
*/
@override
Future<WorkResponse> performRequest(WorkRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return logger.runAsync('Perform request', () async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
errorBuffer.clear();
outBuffer.clear();
try {
@@ -133,6 +139,8 @@
*/
@override
Future<Null> run() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
errorSink = errorBuffer;
outSink = outBuffer;
exitHandler = (int exitCode) {
@@ -191,7 +199,11 @@
* Perform package analysis according to the given [options].
*/
Future<ErrorSeverity> analyze() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return await logger.runAsync('Analyze', () async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// Write initial progress message.
if (!options.machineFormat) {
outSink.writeln("Analyzing ${options.sourceFiles.join(', ')}...");
@@ -240,8 +252,12 @@
assembler = new PackageBundleAssembler();
if (_shouldOutputSummary) {
await logger.runAsync('Build and write output summary', () async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// Prepare all unlinked units.
await logger.runAsync('Prepare unlinked units', () async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
for (var src in explicitSources) {
await _prepareUnlinkedUnit('${src.uri}');
}
@@ -316,6 +332,8 @@
}
Future<ErrorSeverity> _computeMaxSeverity() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
ErrorSeverity maxSeverity = ErrorSeverity.NONE;
if (!options.buildSuppressExitCode) {
for (Source source in explicitSources) {
@@ -451,6 +469,8 @@
* Otherwise compute it and store into the [uriToUnit] and [assembler].
*/
Future<Null> _prepareUnlinkedUnit(String absoluteUri) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// Maybe an input package contains the source.
if (summaryDataStore.unlinkedMap[absoluteUri] != null) {
return;
@@ -474,7 +494,11 @@
* is sent to a new file at that path.
*/
Future<Null> _printErrors({String outputPath}) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
await logger.runAsync('Compute and print analysis errors', () async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
StringBuffer buffer = new StringBuffer();
var severityProcessor = (AnalysisError error) =>
determineProcessedSeverity(error, options, analysisOptions);
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index 492de93..74425a8 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -10,18 +10,15 @@
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/context/builder.dart';
-import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/sdk/sdk.dart';
import 'package:analyzer/src/file_system/file_system.dart';
-import 'package:analyzer/src/generated/constant.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/interner.dart';
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/generated/utilities_general.dart'
show PerformanceTag;
import 'package:analyzer/src/plugin/resolver_provider.dart';
@@ -31,7 +28,6 @@
import 'package:analyzer/src/source/path_filter.dart';
import 'package:analyzer/src/source/pub_package_map_provider.dart';
import 'package:analyzer/src/source/sdk_ext.dart';
-import 'package:analyzer/src/source/source_resource.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/package_bundle_reader.dart';
import 'package:analyzer/src/summary/summary_sdk.dart' show SummaryBasedDartSdk;
@@ -107,17 +103,16 @@
/// The plugins that are defined outside the `analyzer_cli` package.
List<Plugin> _userDefinedPlugins = <Plugin>[];
- /// The context that was most recently created by a call to [_analyzeAll], or
+ /// The driver that was most recently created by a call to [_analyzeAll], or
/// `null` if [_analyzeAll] hasn't been called yet.
- InternalAnalysisContext _context;
-
+ @visibleForTesting
AnalysisDriver analysisDriver;
/// The total number of source files loaded by an AnalysisContext.
int _analyzedFileCount = 0;
- /// If [_context] is not `null`, the [CommandLineOptions] that guided its
- /// creation.
+ /// If [analysisDriver] is not `null`, the [CommandLineOptions] that guided
+ /// its creation.
CommandLineOptions _previousOptions;
@override
@@ -149,10 +144,6 @@
}
}
- /// This Driver's current analysis context.
- @visibleForTesting
- AnalysisContext get context => _context;
-
/// The crash reporting instance for analyzer-cli.
/// TODO(devoncarew): Replace with the real crash product ID.
CrashReportSender get crashReportSender => (_crashReportSender ??=
@@ -163,9 +154,21 @@
_userDefinedPlugins = plugins ?? <Plugin>[];
}
+ /**
+ * Converts the given [filePath] into absolute and normalized.
+ */
+ String normalizePath(String filePath) {
+ filePath = filePath.trim();
+ filePath = resourceProvider.pathContext.absolute(filePath);
+ filePath = resourceProvider.pathContext.normalize(filePath);
+ return filePath;
+ }
+
@override
Future<Null> start(List<String> args) async {
- if (_context != null) {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
+ if (analysisDriver != null) {
throw new StateError("start() can only be called once");
}
int startTime = new DateTime.now().millisecondsSinceEpoch;
@@ -196,6 +199,8 @@
} else if (options.batchMode) {
BatchRunner batchRunner = new BatchRunner(outSink, errorSink);
batchRunner.runAsBatch(args, (List<String> args) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
CommandLineOptions options = CommandLineOptions.parse(args);
return await _analyzeAll(options);
});
@@ -207,8 +212,8 @@
}
}
- if (_context != null) {
- _analyzedFileCount += _context.sources.length;
+ if (analysisDriver != null) {
+ _analyzedFileCount += analysisDriver.knownFiles.length;
}
// Send how long analysis took.
@@ -229,6 +234,8 @@
}
Future<ErrorSeverity> _analyzeAll(CommandLineOptions options) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
PerformanceTag previous = _analyzeAllTag.makeCurrent();
try {
return await _analyzeAllImpl(options);
@@ -244,6 +251,8 @@
/// Perform analysis according to the given [options].
Future<ErrorSeverity> _analyzeAllImpl(CommandLineOptions options) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (!options.machineFormat) {
List<String> fileNames = options.sourceFiles.map((String file) {
file = path.normalize(file);
@@ -259,14 +268,14 @@
}
// These are used to do part file analysis across sources.
- Set<Uri> libUris = new Set<Uri>();
- Set<Source> danglingParts = new Set<Source>();
+ Set<FileState> libraryFiles = new Set<FileState>();
+ Set<FileState> danglingParts = new Set<FileState>();
- // Note: This references _context via closure, so it will change over time
- // during the following analysis.
+ // Note: This references analysisDriver via closure, so it will change over
+ // time during the following analysis.
SeverityProcessor defaultSeverityProcessor = (AnalysisError error) {
return determineProcessedSeverity(
- error, options, _context.analysisOptions);
+ error, options, analysisDriver.analysisOptions);
};
// We currently print out to stderr to ensure that when in batch mode we
@@ -286,16 +295,15 @@
ErrorSeverity allResult = ErrorSeverity.NONE;
- void reportPartError(Source partSource) {
- errorSink
- .writeln("${partSource.fullName} is a part and cannot be analyzed.");
+ void reportPartError(String partPath) {
+ errorSink.writeln("$partPath is a part and cannot be analyzed.");
errorSink.writeln("Please pass in a library that contains this part.");
io.exitCode = ErrorSeverity.ERROR.ordinal;
allResult = allResult.max(ErrorSeverity.ERROR);
}
for (String sourcePath in options.sourceFiles) {
- sourcePath = sourcePath.trim();
+ sourcePath = normalizePath(sourcePath);
// Create a context, or re-use the previous one.
try {
@@ -308,16 +316,14 @@
// Add all the files to be analyzed en masse to the context. Skip any
// files that were added earlier (whether explicitly or implicitly) to
// avoid causing those files to be unnecessarily re-read.
- Set<Source> knownSources = context.sources.toSet();
- Set<Source> sourcesToAnalyze = new Set<Source>();
- ChangeSet changeSet = new ChangeSet();
+ Set<String> filesToAnalyze = new Set<String>();
// Collect files for analysis.
// Note that these files will all be analyzed in the same context.
// This should be updated when the ContextManager re-work is complete
// (See: https://github.com/dart-lang/sdk/issues/24133)
Iterable<io.File> files =
- _collectFiles(sourcePath, context.analysisOptions);
+ _collectFiles(sourcePath, analysisDriver.analysisOptions);
if (files.isEmpty) {
errorSink.writeln('No dart files found at: $sourcePath');
io.exitCode = ErrorSeverity.ERROR.ordinal;
@@ -325,25 +331,15 @@
}
for (io.File file in files) {
- Source source = _computeLibrarySource(file.absolute.path);
- if (!knownSources.contains(source)) {
- changeSet.addedSource(source);
- }
- sourcesToAnalyze.add(source);
- }
-
- if (analysisDriver == null) {
- context.applyChanges(changeSet);
+ filesToAnalyze.add(file.absolute.path);
}
// Analyze the libraries.
- Set<Source> partSources = new Set<Source>();
-
- for (Source source in sourcesToAnalyze) {
- if (analysisDriver != null &&
- (source.shortName == AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE ||
- source.shortName == AnalysisEngine.ANALYSIS_OPTIONS_FILE)) {
- file_system.File file = resourceProvider.getFile(source.fullName);
+ for (String path in filesToAnalyze) {
+ var shortName = resourceProvider.pathContext.basename(path);
+ if (shortName == AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE ||
+ shortName == AnalysisEngine.ANALYSIS_OPTIONS_FILE) {
+ file_system.File file = resourceProvider.getFile(path);
String content = file.readAsStringSync();
LineInfo lineInfo = new LineInfo.fromContent(content);
List<AnalysisError> errors =
@@ -352,11 +348,11 @@
formatter.formatErrors([new AnalysisErrorInfoImpl(errors, lineInfo)]);
for (AnalysisError error in errors) {
allResult = allResult.max(determineProcessedSeverity(
- error, options, _context.analysisOptions));
+ error, options, analysisDriver.analysisOptions));
}
- } else if (source.shortName == AnalysisEngine.PUBSPEC_YAML_FILE) {
+ } else if (shortName == AnalysisEngine.PUBSPEC_YAML_FILE) {
try {
- file_system.File file = resourceProvider.getFile(source.fullName);
+ file_system.File file = resourceProvider.getFile(path);
String content = file.readAsStringSync();
YamlNode node = loadYamlNode(content);
if (node is YamlMap) {
@@ -368,65 +364,37 @@
.formatErrors([new AnalysisErrorInfoImpl(errors, lineInfo)]);
for (AnalysisError error in errors) {
allResult = allResult.max(determineProcessedSeverity(
- error, options, _context.analysisOptions));
+ error, options, analysisDriver.analysisOptions));
}
}
} catch (exception) {
// If the file cannot be analyzed, ignore it.
}
} else {
- SourceKind sourceKind = analysisDriver != null
- ? await analysisDriver.getSourceKind(source.fullName)
- : context.computeKindOf(source);
- if (sourceKind == SourceKind.PART) {
- partSources.add(source);
+ var file = analysisDriver.fsState.getFileForPath(path);
+
+ if (file.isPart) {
+ if (!libraryFiles.contains(file.library)) {
+ danglingParts.add(file);
+ }
continue;
}
- ErrorSeverity status = await _runAnalyzer(source, options, formatter);
- allResult = allResult.max(status);
- libUris.add(source.uri);
- if (analysisDriver != null) {
- // With [AnalysisDriver], we can easily mark previously dangling
- // parts as no longer dangling once we process the lib.
- var libFile =
- analysisDriver.fsState.getFileForPath(source.fullName);
- for (FileState part in libFile.partedFiles) {
- danglingParts.remove(part.source);
- }
- }
- }
- }
+ libraryFiles.add(file);
- // Check that each part has a corresponding source in the input list.
- for (Source partSource in partSources) {
- if (analysisDriver != null) {
- var partFile =
- analysisDriver.fsState.getFileForPath(partSource.fullName);
- if (!libUris.contains(partFile.library?.uri)) {
- // With [AnalysisDriver], we can mark this as dangling, for now, and
- // later on remove it from this list if its containing lib is found.
- danglingParts.add(partSource);
- }
- } else {
- final potentialLibs = context.getLibrariesContaining(partSource);
- bool found = false;
- for (var lib in potentialLibs) {
- if (libUris.contains(lib.uri)) {
- found = true;
- }
- }
- if (!found) {
- // Without an analysis driver, we can't easily mark it dangling "for
- // now", but this path is deprecated anyway. Just give up now.
- reportPartError(partSource);
+ ErrorSeverity status = await _runAnalyzer(file, options, formatter);
+ allResult = allResult.max(status);
+
+ // Mark previously dangling parts as no longer dangling.
+ for (FileState part in file.partedFiles) {
+ danglingParts.remove(part);
}
}
}
}
// Any dangling parts still in this list were definitely dangling.
- for (Source partSource in danglingParts) {
- reportPartError(partSource);
+ for (FileState partFile in danglingParts) {
+ reportPartError(partFile.path);
}
formatter.flush();
@@ -440,6 +408,8 @@
/// Perform analysis in build mode according to the given [options].
Future<ErrorSeverity> _buildModeAnalyze(CommandLineOptions options) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
PerformanceTag previous = _analyzeAllTag.makeCurrent();
try {
if (options.buildModePersistentWorker) {
@@ -457,33 +427,6 @@
}
}
- /// Decide on the appropriate policy for which files need to be fully parsed
- /// and which files need to be diet parsed, based on [options], and return an
- /// [AnalyzeFunctionBodiesPredicate] that implements this policy.
- AnalyzeFunctionBodiesPredicate _chooseDietParsingPolicy(
- CommandLineOptions options) {
- if (options.batchMode) {
- // As analyzer is currently implemented, once a file has been diet
- // parsed, it can't easily be un-diet parsed without creating a brand new
- // context and losing caching. In batch mode, we can't predict which
- // files we'll need to generate errors and warnings for in the future, so
- // we can't safely diet parse anything.
- return (Source source) => true;
- }
-
- return (Source source) {
- if (options.sourceFiles.contains(source.fullName)) {
- return true;
- } else if (source.uri.scheme == 'dart') {
- return options.showSdkWarnings;
- } else {
- // TODO(paulberry): diet parse 'package:' imports when we don't want
- // diagnostics. (Full parse is still needed for "self" packages.)
- return true;
- }
- };
- }
-
/// Decide on the appropriate method for resolving URIs based on the given
/// [options] and [customUrlMappings] settings, and return a
/// [SourceFactory] that has been configured accordingly.
@@ -609,39 +552,18 @@
return files;
}
- /// Convert the given [sourcePath] (which may be relative to the current
- /// working directory) to a [Source] object that can be fed to the analysis
- /// context.
- Source _computeLibrarySource(String sourcePath) {
- sourcePath = _normalizeSourcePath(sourcePath);
- File sourceFile = resourceProvider.getFile(sourcePath);
- Source source = sdk.fromFileUri(sourceFile.toUri());
- if (source != null) {
- return source;
- }
- source = new FileSource(sourceFile, sourceFile.toUri());
- Uri uri = _context.sourceFactory.restoreUri(source);
- if (uri == null) {
- return source;
- }
- return new FileSource(sourceFile, uri);
- }
-
- /// Create an analysis context that is prepared to analyze sources according
- /// to the given [options], and store it in [_context].
+ /// Create an analysis driver that is prepared to analyze sources according
+ /// to the given [options], and store it in [analysisDriver].
void _createContextAndAnalyze(CommandLineOptions options, String source) {
// If not the same command-line options, clear cached information.
if (!_equalCommandLineOptions(_previousOptions, options)) {
_previousOptions = options;
contextCache = new ContextCache(resourceProvider, options, verbosePrint);
- _context = null;
analysisDriver = null;
}
AnalysisOptionsImpl analysisOptions =
createAnalysisOptionsForCommandLineOptions(options, source);
- analysisOptions.analyzeFunctionBodiesPredicate =
- _chooseDietParsingPolicy(options);
// Store the [PathFilter] for this context to properly exclude files
pathFilter = new PathFilter(getContextInfo(options, source).analysisRoot,
@@ -649,8 +571,9 @@
// If we have the analysis driver, and the new analysis options are the
// same, we can reuse this analysis driver.
- if (_context != null &&
- _equalAnalysisOptions(_context.analysisOptions, analysisOptions)) {
+ if (analysisDriver != null &&
+ _equalAnalysisOptions(
+ analysisDriver.analysisOptions, analysisOptions)) {
return;
}
@@ -660,8 +583,8 @@
}
// Save stats from previous context before clobbering it.
- if (_context != null) {
- _analyzedFileCount += _context.sources.length;
+ if (analysisDriver != null) {
+ _analyzedFileCount += analysisDriver.knownFiles.length;
}
// Find package info.
@@ -699,44 +622,30 @@
SourceFactory sourceFactory = _chooseUriResolutionPolicy(options,
embedderMap, packageInfo, summaryDataStore, true, analysisOptions);
- // Create a context.
- _context = AnalysisEngine.instance.createAnalysisContext();
- _context.analysisOptions = analysisOptions;
- _context.sourceFactory = sourceFactory;
- (context as AnalysisContextImpl).declaredVariables =
- new DeclaredVariables.fromMap(options.definedVariables);
+ PerformanceLog log = new PerformanceLog(null);
+ AnalysisDriverScheduler scheduler = new AnalysisDriverScheduler(log);
- if (options.enableNewAnalysisDriver) {
- PerformanceLog log = new PerformanceLog(null);
- AnalysisDriverScheduler scheduler = new AnalysisDriverScheduler(log);
-
- bool enableKernelDriver = options.useCFE;
- file_system.Folder kernelPlatformBinariesFolder;
- if (enableKernelDriver && options.dartSdkPlatformBinariesPath != null) {
- kernelPlatformBinariesFolder =
- resourceProvider.getFolder(options.dartSdkPlatformBinariesPath);
- }
-
- analysisDriver = new AnalysisDriver(
- scheduler,
- log,
- resourceProvider,
- analysisDriverMemoryByteStore,
- new FileContentOverlay(),
- null,
- context.sourceFactory,
- context.analysisOptions,
- enableKernelDriver: enableKernelDriver,
- kernelPlatformFolder: kernelPlatformBinariesFolder);
- analysisDriver.results.listen((_) {});
- analysisDriver.exceptions.listen((_) {});
- scheduler.start();
- } else {
- if (sdkBundle != null) {
- _context.resultProvider =
- new InputPackagesResultProvider(_context, summaryDataStore);
- }
+ bool enableKernelDriver = options.useCFE;
+ file_system.Folder kernelPlatformBinariesFolder;
+ if (enableKernelDriver && options.dartSdkPlatformBinariesPath != null) {
+ kernelPlatformBinariesFolder =
+ resourceProvider.getFolder(options.dartSdkPlatformBinariesPath);
}
+
+ analysisDriver = new AnalysisDriver(
+ scheduler,
+ log,
+ resourceProvider,
+ analysisDriverMemoryByteStore,
+ new FileContentOverlay(),
+ null,
+ sourceFactory,
+ analysisOptions,
+ enableKernelDriver: enableKernelDriver,
+ kernelPlatformFolder: kernelPlatformBinariesFolder);
+ analysisDriver.results.listen((_) {});
+ analysisDriver.exceptions.listen((_) {});
+ scheduler.start();
}
/// Return discovered packagespec, or `null` if none is found.
@@ -847,10 +756,10 @@
/// Analyze a single source.
Future<ErrorSeverity> _runAnalyzer(
- Source source, CommandLineOptions options, ErrorFormatter formatter) {
+ FileState file, CommandLineOptions options, ErrorFormatter formatter) {
int startTime = currentTimeMillis;
- AnalyzerImpl analyzer = new AnalyzerImpl(_context.analysisOptions, _context,
- analysisDriver, source, options, stats, startTime);
+ AnalyzerImpl analyzer = new AnalyzerImpl(analysisDriver.analysisOptions,
+ analysisDriver, file, options, stats, startTime);
return analyzer.analyze(formatter);
}
@@ -968,10 +877,6 @@
}
return true;
}
-
- /// Convert [sourcePath] into an absolute path.
- static String _normalizeSourcePath(String sourcePath) =>
- path.normalize(new io.File(sourcePath).absolute.path);
}
class _DriverError implements Exception {
diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart
index 071b3a4..d82228d 100644
--- a/pkg/analyzer_cli/lib/src/options.dart
+++ b/pkg/analyzer_cli/lib/src/options.dart
@@ -33,8 +33,6 @@
/// Analyzer commandline configuration options.
class CommandLineOptions {
- final bool enableNewAnalysisDriver = true;
-
/// Whether declaration casts are enabled (in strong mode)
final bool declarationCasts;
diff --git a/pkg/analyzer_cli/test/driver_test.dart b/pkg/analyzer_cli/test/driver_test.dart
index 9fb32f4..d33adca 100644
--- a/pkg/analyzer_cli/test/driver_test.dart
+++ b/pkg/analyzer_cli/test/driver_test.dart
@@ -11,7 +11,6 @@
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/services/lint.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/util/sdk.dart';
import 'package:analyzer_cli/src/ansi.dart' as ansi;
@@ -54,6 +53,8 @@
Driver driver;
+ AnalysisOptions get analysisOptions => driver.analysisDriver.analysisOptions;
+
bool get useCFE => false;
bool get usePreviewDart2 => false;
@@ -731,10 +732,10 @@
await _runLinter_defaultLints();
/// Lints should be enabled.
- expect(driver.context.analysisOptions.lint, isTrue);
+ expect(analysisOptions.lint, isTrue);
/// Default list should include camel_case_types.
- var lintNames = getLints(driver.context).map((r) => r.name);
+ var lintNames = analysisOptions.lintRules.map((r) => r.name);
expect(lintNames, contains('camel_case_types'));
}
@@ -748,16 +749,16 @@
await _runLinter_lintsInOptions();
/// Lints should be enabled.
- expect(driver.context.analysisOptions.lint, isTrue);
+ expect(analysisOptions.lint, isTrue);
/// The analysis options file only specifies 'camel_case_types'.
- var lintNames = getLints(driver.context).map((r) => r.name);
+ var lintNames = analysisOptions.lintRules.map((r) => r.name);
expect(lintNames, orderedEquals(['camel_case_types']));
}
test_noLints_lintsDisabled() async {
await _runLinter_noLintsFlag();
- expect(driver.context.analysisOptions.lint, isFalse);
+ expect(analysisOptions.lint, isFalse);
}
test_noLints_noGeneratedWarnings() async {
@@ -767,7 +768,7 @@
test_noLints_noRegisteredLints() async {
await _runLinter_noLintsFlag();
- expect(getLints(driver.context), isEmpty);
+ expect(analysisOptions.lintRules, isEmpty);
}
YamlMap _parseOptions(String src) =>
@@ -843,8 +844,7 @@
class OptionsTest extends BaseTest {
String get optionsFileName => AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE;
- List<ErrorProcessor> get processors =>
- driver.context.analysisOptions.errorProcessors;
+ List<ErrorProcessor> get processors => analysisOptions.errorProcessors;
ErrorProcessor processorFor(AnalysisError error) =>
processors.firstWhere((p) => p.appliesTo(error));
@@ -910,14 +910,15 @@
test_basic_language() async {
await _driveBasic();
- expect(driver.context.analysisOptions.enableSuperMixins, isTrue);
+ expect(analysisOptions.enableSuperMixins, isTrue);
}
test_basic_strongMode() async {
await _driveBasic();
- expect(driver.context.analysisOptions.strongMode, isTrue);
+ expect(analysisOptions.strongMode, isTrue);
// https://github.com/dart-lang/sdk/issues/26129
- AnalysisContext sdkContext = driver.context.sourceFactory.dartSdk.context;
+ AnalysisContext sdkContext =
+ driver.analysisDriver.sourceFactory.dartSdk.context;
expect(sdkContext.analysisOptions.strongMode, isTrue);
}
@@ -943,13 +944,13 @@
test_previewDart2() async {
await drive('data/options_tests_project/test_file.dart',
args: ['--preview-dart-2']);
- expect(driver.context.analysisOptions.useFastaParser, isFalse);
+ expect(analysisOptions.useFastaParser, isFalse);
}
test_strongSdk() async {
String testDir = path.join(testDirectory, 'data', 'strong_sdk');
await drive(path.join(testDir, 'main.dart'), args: ['--strong']);
- expect(driver.context.analysisOptions.strongMode, isTrue);
+ expect(analysisOptions.strongMode, isTrue);
expect(outSink.toString(), contains('No issues found'));
}
diff --git a/pkg/analyzer_plugin/doc/api.html b/pkg/analyzer_plugin/doc/api.html
index e0d511d..dfe6470 100644
--- a/pkg/analyzer_plugin/doc/api.html
+++ b/pkg/analyzer_plugin/doc/api.html
@@ -1280,7 +1280,7 @@
An enumeration of the kinds of folding regions.
</p>
- <dl><dt class="value">ANNOTATIONS</dt><dt class="value">CLASS_BODY</dt><dt class="value">DIRECTIVES</dt><dt class="value">DOCUMENTATION_COMMENT</dt><dt class="value">FILE_HEADER</dt><dt class="value">FUNCTION_BODY</dt></dl></dd><dt class="typeDefinition"><a name="type_FoldingRegion">FoldingRegion: object</a></dt><dd>
+ <dl><dt class="value">ANNOTATIONS</dt><dt class="value">CLASS_BODY</dt><dt class="value">DIRECTIVES</dt><dt class="value">DOCUMENTATION_COMMENT</dt><dt class="value">FILE_HEADER</dt><dt class="value">FUNCTION_BODY</dt><dt class="value">INVOCATION</dt><dt class="value">LITERAL</dt></dl></dd><dt class="typeDefinition"><a name="type_FoldingRegion">FoldingRegion: object</a></dt><dd>
<p>
A description of a region that can be folded.
</p>
diff --git a/pkg/analyzer_plugin/lib/plugin/assist_mixin.dart b/pkg/analyzer_plugin/lib/plugin/assist_mixin.dart
index 1b1d3a0..1ba1714 100644
--- a/pkg/analyzer_plugin/lib/plugin/assist_mixin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/assist_mixin.dart
@@ -38,6 +38,8 @@
@override
Future<EditGetAssistsResult> handleEditGetAssists(
EditGetAssistsParams parameters) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String path = parameters.file;
AssistRequest request = await getAssistRequest(parameters);
AssistGenerator generator =
@@ -61,6 +63,8 @@
@override
Future<AssistRequest> getAssistRequest(
EditGetAssistsParams parameters) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String path = parameters.file;
ResolveResult result = await getResolveResult(path);
return new DartAssistRequestImpl(
diff --git a/pkg/analyzer_plugin/lib/plugin/completion_mixin.dart b/pkg/analyzer_plugin/lib/plugin/completion_mixin.dart
index 0194e44..8b45068 100644
--- a/pkg/analyzer_plugin/lib/plugin/completion_mixin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/completion_mixin.dart
@@ -39,6 +39,8 @@
@override
Future<CompletionGetSuggestionsResult> handleCompletionGetSuggestions(
CompletionGetSuggestionsParams parameters) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String path = parameters.file;
CompletionRequest request = await getCompletionRequest(parameters);
CompletionGenerator generator =
@@ -64,6 +66,8 @@
@override
Future<CompletionRequest> getCompletionRequest(
CompletionGetSuggestionsParams parameters) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
ResolveResult result = await getResolveResult(parameters.file);
return new DartCompletionRequestImpl(
resourceProvider, parameters.offset, result);
diff --git a/pkg/analyzer_plugin/lib/plugin/fix_mixin.dart b/pkg/analyzer_plugin/lib/plugin/fix_mixin.dart
index 0ceedfc..16899f4 100644
--- a/pkg/analyzer_plugin/lib/plugin/fix_mixin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/fix_mixin.dart
@@ -27,6 +27,8 @@
abstract class DartFixesMixin implements FixesMixin {
@override
Future<FixesRequest> getFixesRequest(EditGetFixesParams parameters) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String path = parameters.file;
int offset = parameters.offset;
ResolveResult result = await getResolveResult(path);
@@ -69,6 +71,8 @@
@override
Future<EditGetFixesResult> handleEditGetFixes(
EditGetFixesParams parameters) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String path = parameters.file;
FixesRequest request = await getFixesRequest(parameters);
FixGenerator generator = new FixGenerator(getFixContributors(path));
diff --git a/pkg/analyzer_plugin/lib/plugin/folding_mixin.dart b/pkg/analyzer_plugin/lib/plugin/folding_mixin.dart
index bfc8182..6f90671 100644
--- a/pkg/analyzer_plugin/lib/plugin/folding_mixin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/folding_mixin.dart
@@ -25,6 +25,8 @@
abstract class DartFoldingMixin implements FoldingMixin {
@override
Future<FoldingRequest> getFoldingRequest(String path) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
ResolveResult result = await getResolveResult(path);
return new DartFoldingRequestImpl(resourceProvider, result);
}
@@ -54,6 +56,8 @@
@override
Future<Null> sendFoldingNotification(String path) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
try {
FoldingRequest request = await getFoldingRequest(path);
FoldingGenerator generator =
diff --git a/pkg/analyzer_plugin/lib/plugin/highlights_mixin.dart b/pkg/analyzer_plugin/lib/plugin/highlights_mixin.dart
index 2a3e04b..01b7ed8 100644
--- a/pkg/analyzer_plugin/lib/plugin/highlights_mixin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/highlights_mixin.dart
@@ -25,6 +25,8 @@
abstract class DartHighlightsMixin implements HighlightsMixin {
@override
Future<HighlightsRequest> getHighlightsRequest(String path) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
ResolveResult result = await getResolveResult(path);
return new DartHighlightsRequestImpl(resourceProvider, result);
}
@@ -54,6 +56,8 @@
@override
Future<Null> sendHighlightsNotification(String path) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
try {
HighlightsRequest request = await getHighlightsRequest(path);
HighlightsGenerator generator =
diff --git a/pkg/analyzer_plugin/lib/plugin/kythe_mixin.dart b/pkg/analyzer_plugin/lib/plugin/kythe_mixin.dart
index 3db9fbb..6f96c1d 100644
--- a/pkg/analyzer_plugin/lib/plugin/kythe_mixin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/kythe_mixin.dart
@@ -27,6 +27,8 @@
@override
Future<EntryRequest> getEntryRequest(
KytheGetKytheEntriesParams parameters) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String path = parameters.file;
ResolveResult result = await getResolveResult(path);
return new DartEntryRequestImpl(resourceProvider, result);
@@ -58,6 +60,8 @@
@override
Future<KytheGetKytheEntriesResult> handleKytheGetKytheEntries(
KytheGetKytheEntriesParams parameters) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String path = parameters.file;
EntryRequest request = await getEntryRequest(parameters);
EntryGenerator generator = new EntryGenerator(getEntryContributors(path));
diff --git a/pkg/analyzer_plugin/lib/plugin/navigation_mixin.dart b/pkg/analyzer_plugin/lib/plugin/navigation_mixin.dart
index f8cb90a..86b6f0c 100644
--- a/pkg/analyzer_plugin/lib/plugin/navigation_mixin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/navigation_mixin.dart
@@ -27,6 +27,8 @@
@override
Future<NavigationRequest> getNavigationRequest(
AnalysisGetNavigationParams parameters) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String path = parameters.file;
ResolveResult result = await getResolveResult(path);
int offset = parameters.offset;
@@ -66,6 +68,8 @@
@override
Future<AnalysisGetNavigationResult> handleAnalysisGetNavigation(
AnalysisGetNavigationParams parameters) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String path = parameters.file;
NavigationRequest request = await getNavigationRequest(parameters);
NavigationGenerator generator =
@@ -82,6 +86,8 @@
*/
@override
Future<Null> sendNavigationNotification(String path) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
try {
NavigationRequest request = await getNavigationRequest(
new AnalysisGetNavigationParams(path, -1, -1));
diff --git a/pkg/analyzer_plugin/lib/plugin/occurrences_mixin.dart b/pkg/analyzer_plugin/lib/plugin/occurrences_mixin.dart
index 98cb50b..dfb95d4 100644
--- a/pkg/analyzer_plugin/lib/plugin/occurrences_mixin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/occurrences_mixin.dart
@@ -25,6 +25,8 @@
abstract class DartOccurrencesMixin implements OccurrencesMixin {
@override
Future<OccurrencesRequest> getOccurrencesRequest(String path) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
ResolveResult result = await getResolveResult(path);
return new DartOccurrencesRequestImpl(resourceProvider, result);
}
@@ -54,6 +56,8 @@
@override
Future<Null> sendOccurrencesNotification(String path) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
try {
OccurrencesRequest request = await getOccurrencesRequest(path);
OccurrencesGenerator generator =
diff --git a/pkg/analyzer_plugin/lib/plugin/outline_mixin.dart b/pkg/analyzer_plugin/lib/plugin/outline_mixin.dart
index c72cec6..23506fd 100644
--- a/pkg/analyzer_plugin/lib/plugin/outline_mixin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/outline_mixin.dart
@@ -25,6 +25,8 @@
abstract class DartOutlineMixin implements OutlineMixin {
@override
Future<OutlineRequest> getOutlineRequest(String path) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
ResolveResult result = await getResolveResult(path);
return new DartOutlineRequestImpl(resourceProvider, result);
}
@@ -54,6 +56,8 @@
@override
Future<Null> sendOutlineNotification(String path) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
try {
OutlineRequest request = await getOutlineRequest(path);
OutlineGenerator generator =
diff --git a/pkg/analyzer_plugin/lib/plugin/plugin.dart b/pkg/analyzer_plugin/lib/plugin/plugin.dart
index faf50d2..7a6e478 100644
--- a/pkg/analyzer_plugin/lib/plugin/plugin.dart
+++ b/pkg/analyzer_plugin/lib/plugin/plugin.dart
@@ -209,6 +209,8 @@
* associated with the file is not an [AnalysisDriver].
*/
Future<ResolveResult> getResolveResult(String path) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
AnalysisDriverGeneric driver = driverForPath(path);
if (driver is! AnalysisDriver) {
// Return an error from the request.
@@ -232,6 +234,8 @@
*/
Future<AnalysisGetNavigationResult> handleAnalysisGetNavigation(
AnalysisGetNavigationParams params) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return new AnalysisGetNavigationResult(
<String>[], <NavigationTarget>[], <NavigationRegion>[]);
}
@@ -243,6 +247,8 @@
*/
Future<AnalysisHandleWatchEventsResult> handleAnalysisHandleWatchEvents(
AnalysisHandleWatchEventsParams parameters) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
for (WatchEvent event in parameters.events) {
switch (event.type) {
case WatchEventType.ADD:
@@ -269,6 +275,8 @@
*/
Future<AnalysisSetContextRootsResult> handleAnalysisSetContextRoots(
AnalysisSetContextRootsParams parameters) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<ContextRoot> contextRoots = parameters.roots;
List<ContextRoot> oldRoots = driverMap.keys.toList();
for (ContextRoot contextRoot in contextRoots) {
@@ -300,6 +308,8 @@
*/
Future<AnalysisSetPriorityFilesResult> handleAnalysisSetPriorityFiles(
AnalysisSetPriorityFilesParams parameters) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<String> files = parameters.files;
Map<AnalysisDriverGeneric, List<String>> filesByDriver =
<AnalysisDriverGeneric, List<String>>{};
@@ -326,6 +336,8 @@
*/
Future<AnalysisSetSubscriptionsResult> handleAnalysisSetSubscriptions(
AnalysisSetSubscriptionsParams parameters) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
Map<AnalysisService, List<String>> subscriptions = parameters.subscriptions;
Map<String, List<AnalysisService>> newSubscriptions =
subscriptionManager.setSubscriptions(subscriptions);
@@ -342,6 +354,8 @@
*/
Future<AnalysisUpdateContentResult> handleAnalysisUpdateContent(
AnalysisUpdateContentParams parameters) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
Map<String, Object> files = parameters.files;
files.forEach((String filePath, Object overlay) {
if (overlay is AddContentOverlay) {
@@ -376,9 +390,12 @@
* Throw a [RequestFailure] if the request could not be handled.
*/
Future<CompletionGetSuggestionsResult> handleCompletionGetSuggestions(
- CompletionGetSuggestionsParams parameters) async =>
- new CompletionGetSuggestionsResult(
- -1, -1, const <CompletionSuggestion>[]);
+ CompletionGetSuggestionsParams parameters) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
+ return new CompletionGetSuggestionsResult(
+ -1, -1, const <CompletionSuggestion>[]);
+ }
/**
* Handle an 'edit.getAssists' request.
@@ -386,8 +403,11 @@
* Throw a [RequestFailure] if the request could not be handled.
*/
Future<EditGetAssistsResult> handleEditGetAssists(
- EditGetAssistsParams parameters) async =>
- new EditGetAssistsResult(const <PrioritizedSourceChange>[]);
+ EditGetAssistsParams parameters) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
+ return new EditGetAssistsResult(const <PrioritizedSourceChange>[]);
+ }
/**
* Handle an 'edit.getAvailableRefactorings' request. Subclasses that override
@@ -397,8 +417,11 @@
* Throw a [RequestFailure] if the request could not be handled.
*/
Future<EditGetAvailableRefactoringsResult> handleEditGetAvailableRefactorings(
- EditGetAvailableRefactoringsParams parameters) async =>
- new EditGetAvailableRefactoringsResult(const <RefactoringKind>[]);
+ EditGetAvailableRefactoringsParams parameters) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
+ return new EditGetAvailableRefactoringsResult(const <RefactoringKind>[]);
+ }
/**
* Handle an 'edit.getFixes' request.
@@ -406,8 +429,11 @@
* Throw a [RequestFailure] if the request could not be handled.
*/
Future<EditGetFixesResult> handleEditGetFixes(
- EditGetFixesParams parameters) async =>
- new EditGetFixesResult(const <AnalysisErrorFixes>[]);
+ EditGetFixesParams parameters) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
+ return new EditGetFixesResult(const <AnalysisErrorFixes>[]);
+ }
/**
* Handle an 'edit.getRefactoring' request.
@@ -415,8 +441,10 @@
* Throw a [RequestFailure] if the request could not be handled.
*/
Future<EditGetRefactoringResult> handleEditGetRefactoring(
- EditGetRefactoringParams parameters) async =>
- null;
+ EditGetRefactoringParams parameters) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ return await null;
+ }
/**
* Handle a 'kythe.getKytheEntries' request.
@@ -424,8 +452,10 @@
* Throw a [RequestFailure] if the request could not be handled.
*/
Future<KytheGetKytheEntriesResult> handleKytheGetKytheEntries(
- KytheGetKytheEntriesParams parameters) async =>
- null;
+ KytheGetKytheEntriesParams parameters) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ return await null;
+ }
/**
* Handle a 'plugin.shutdown' request. Subclasses can override this method to
@@ -435,8 +465,11 @@
* Throw a [RequestFailure] if the request could not be handled.
*/
Future<PluginShutdownResult> handlePluginShutdown(
- PluginShutdownParams parameters) async =>
- new PluginShutdownResult();
+ PluginShutdownParams parameters) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
+ return new PluginShutdownResult();
+ }
/**
* Handle a 'plugin.versionCheck' request.
@@ -445,6 +478,8 @@
*/
Future<PluginVersionCheckResult> handlePluginVersionCheck(
PluginVersionCheckParams parameters) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
String byteStorePath = parameters.byteStorePath;
String sdkPath = parameters.sdkPath;
String versionString = parameters.version;
@@ -589,6 +624,8 @@
* `null` if the response has already been sent.
*/
Future<Response> _getResponse(Request request, int requestTime) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
ResponseResult result = null;
switch (request.method) {
case ANALYSIS_REQUEST_GET_NAVIGATION:
@@ -663,6 +700,8 @@
* server.
*/
Future<Null> _onRequest(Request request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
int requestTime = new DateTime.now().millisecondsSinceEpoch;
String id = request.id;
Response response;
diff --git a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
index e724ab7..a6b6812 100644
--- a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
+++ b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
@@ -1969,6 +1969,8 @@
* DOCUMENTATION_COMMENT
* FILE_HEADER
* FUNCTION_BODY
+ * INVOCATION
+ * LITERAL
* }
*
* Clients may not extend, implement or mix-in this class.
@@ -1987,6 +1989,10 @@
static const FoldingKind FUNCTION_BODY = const FoldingKind._("FUNCTION_BODY");
+ static const FoldingKind INVOCATION = const FoldingKind._("INVOCATION");
+
+ static const FoldingKind LITERAL = const FoldingKind._("LITERAL");
+
/**
* A list containing all of the enum values that are defined.
*/
@@ -1996,7 +2002,9 @@
DIRECTIVES,
DOCUMENTATION_COMMENT,
FILE_HEADER,
- FUNCTION_BODY
+ FUNCTION_BODY,
+ INVOCATION,
+ LITERAL
];
@override
@@ -2018,6 +2026,10 @@
return FILE_HEADER;
case "FUNCTION_BODY":
return FUNCTION_BODY;
+ case "INVOCATION":
+ return INVOCATION;
+ case "LITERAL":
+ return LITERAL;
}
throw new Exception('Illegal enum value: $name');
}
diff --git a/pkg/analyzer_plugin/lib/src/channel/isolate_channel.dart b/pkg/analyzer_plugin/lib/src/channel/isolate_channel.dart
index 2ab6bc1..2c4e8c7 100644
--- a/pkg/analyzer_plugin/lib/src/channel/isolate_channel.dart
+++ b/pkg/analyzer_plugin/lib/src/channel/isolate_channel.dart
@@ -229,6 +229,8 @@
Future<Null> listen(void onResponse(Response response),
void onNotification(Notification notification),
{Function onError, void onDone()}) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (_isolate != null) {
throw new StateError('Cannot listen to the same channel more than once.');
}
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart
index 807264c..c13ce1e 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart
@@ -63,6 +63,8 @@
@override
Future<Null> addFileEdit(
String path, void buildFileEdit(FileEditBuilder builder)) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
FileEditBuilderImpl builder = await createFileEditBuilder(path);
buildFileEdit(builder);
_change.addFileEdit(builder.fileEdit);
@@ -74,6 +76,8 @@
* the file with the given [path] and [timeStamp].
*/
Future<FileEditBuilderImpl> createFileEditBuilder(String path) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
return new FileEditBuilderImpl(this, path, 0);
}
@@ -333,6 +337,8 @@
* Finalize the source file edit that is being built.
*/
Future<Null> finalize() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
// Nothing to do.
}
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
index ef91dc7..ab29122 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
@@ -53,6 +53,8 @@
@override
Future<DartFileEditBuilderImpl> createFileEditBuilder(String path) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
ResolveResult result = await session.getResolvedAst(path);
ResultState state = result?.state ?? ResultState.INVALID_FILE_TYPE;
if (state == ResultState.INVALID_FILE_TYPE) {
@@ -1153,6 +1155,8 @@
@override
Future<Null> finalize() async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
if (librariesToImport.isNotEmpty) {
CompilationUnitElement definingUnitElement =
libraryElement.definingCompilationUnit;
diff --git a/pkg/analyzer_plugin/lib/utilities/completion/completion_core.dart b/pkg/analyzer_plugin/lib/utilities/completion/completion_core.dart
index bb2b3c8..691a179 100644
--- a/pkg/analyzer_plugin/lib/utilities/completion/completion_core.dart
+++ b/pkg/analyzer_plugin/lib/utilities/completion/completion_core.dart
@@ -99,6 +99,8 @@
*/
Future<GeneratorResult> generateCompletionResponse(
CompletionRequest request) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
List<Notification> notifications = <Notification>[];
CompletionCollectorImpl collector = new CompletionCollectorImpl();
try {
diff --git a/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart b/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart
index a983d5d..1d10d441 100644
--- a/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart
+++ b/pkg/analyzer_plugin/lib/utilities/completion/inherited_reference_contributor.dart
@@ -42,6 +42,8 @@
@override
Future<Null> computeSuggestions(
DartCompletionRequest request, CompletionCollector collector) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
CompletionTarget target =
new CompletionTarget.forOffset(request.result.unit, request.offset);
OpType optype = new OpType.forCompletion(target, request.offset);
@@ -69,6 +71,8 @@
CompletionTarget target,
OpType optype,
}) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
target ??= new CompletionTarget.forOffset(
request.result.unit, request.offset,
entryPoint: entryPoint);
diff --git a/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart b/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart
index ef70ec2..c925695 100644
--- a/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart
+++ b/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart
@@ -31,6 +31,8 @@
@override
Future<Null> computeSuggestions(
DartCompletionRequest request, CompletionCollector collector) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
LibraryElement containingLibrary = request.result.libraryElement;
// Gracefully degrade if the library element is not resolved
// e.g. detached part file or source change
@@ -51,6 +53,8 @@
*/
Future<Null> computeSuggestionsWithEntryPoint(DartCompletionRequest request,
CompletionCollector collector, AstNode entryPoint) async {
+ // TODO(brianwilkerson) Determine whether this await is necessary.
+ await null;
LibraryElement containingLibrary = request.result.libraryElement;
// Gracefully degrade if the library element is not resolved
// e.g. detached part file or source change
diff --git a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
index 841a96f..cbf5390 100644
--- a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
+++ b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
@@ -323,6 +323,8 @@
* DOCUMENTATION_COMMENT
* FILE_HEADER
* FUNCTION_BODY
+ * INVOCATION
+ * LITERAL
* }
*/
final Matcher isFoldingKind = new MatchesEnum("FoldingKind", [
@@ -331,7 +333,9 @@
"DIRECTIVES",
"DOCUMENTATION_COMMENT",
"FILE_HEADER",
- "FUNCTION_BODY"
+ "FUNCTION_BODY",
+ "INVOCATION",
+ "LITERAL"
]);
/**
diff --git a/pkg/analyzer_plugin/test/plugin/assist_mixin_test.dart b/pkg/analyzer_plugin/test/plugin/assist_mixin_test.dart
index 906a974..41d20c1 100644
--- a/pkg/analyzer_plugin/test/plugin/assist_mixin_test.dart
+++ b/pkg/analyzer_plugin/test/plugin/assist_mixin_test.dart
@@ -90,8 +90,7 @@
@override
Future<AssistRequest> getAssistRequest(
EditGetAssistsParams parameters) async {
- AnalysisResult result = new AnalysisResult(
- null, null, null, null, null, null, null, null, null, null, null);
+ AnalysisResult result = new MockAnalysisResult();
return new DartAssistRequestImpl(
resourceProvider, parameters.offset, parameters.length, result);
}
diff --git a/pkg/analyzer_plugin/test/plugin/completion_mixin_test.dart b/pkg/analyzer_plugin/test/plugin/completion_mixin_test.dart
index e4fa3e8..acd15aa 100644
--- a/pkg/analyzer_plugin/test/plugin/completion_mixin_test.dart
+++ b/pkg/analyzer_plugin/test/plugin/completion_mixin_test.dart
@@ -98,8 +98,7 @@
@override
Future<CompletionRequest> getCompletionRequest(
CompletionGetSuggestionsParams parameters) async {
- AnalysisResult result = new AnalysisResult(
- null, null, null, null, null, null, null, null, null, null, null);
+ AnalysisResult result = new MockAnalysisResult();
return new DartCompletionRequestImpl(
resourceProvider, parameters.offset, result);
}
diff --git a/pkg/analyzer_plugin/test/plugin/fix_mixin_test.dart b/pkg/analyzer_plugin/test/plugin/fix_mixin_test.dart
index 08a0e76..a30418e 100644
--- a/pkg/analyzer_plugin/test/plugin/fix_mixin_test.dart
+++ b/pkg/analyzer_plugin/test/plugin/fix_mixin_test.dart
@@ -98,8 +98,8 @@
int offset = parameters.offset;
AnalysisError error = new AnalysisError(
new MockSource(), 0, 0, CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT);
- AnalysisResult result = new AnalysisResult(null, null, null, null, null,
- null, new LineInfo([0, 20]), null, null, [error], null);
+ AnalysisResult result = new MockAnalysisResult(
+ lineInfo: new LineInfo([0, 20]), errors: [error]);
return new DartFixesRequestImpl(resourceProvider, offset, [error], result);
}
}
diff --git a/pkg/analyzer_plugin/test/plugin/folding_mixin_test.dart b/pkg/analyzer_plugin/test/plugin/folding_mixin_test.dart
index e8e2d46..cedc947 100644
--- a/pkg/analyzer_plugin/test/plugin/folding_mixin_test.dart
+++ b/pkg/analyzer_plugin/test/plugin/folding_mixin_test.dart
@@ -93,8 +93,7 @@
@override
Future<FoldingRequest> getFoldingRequest(String path) async {
- AnalysisResult result = new AnalysisResult(
- null, null, path, null, null, null, null, null, null, null, null);
+ AnalysisResult result = new MockAnalysisResult(path: path);
return new DartFoldingRequestImpl(resourceProvider, result);
}
}
diff --git a/pkg/analyzer_plugin/test/plugin/highlights_mixin_test.dart b/pkg/analyzer_plugin/test/plugin/highlights_mixin_test.dart
index f9ee17e..992446f 100644
--- a/pkg/analyzer_plugin/test/plugin/highlights_mixin_test.dart
+++ b/pkg/analyzer_plugin/test/plugin/highlights_mixin_test.dart
@@ -93,8 +93,7 @@
@override
Future<HighlightsRequest> getHighlightsRequest(String path) async {
- AnalysisResult result = new AnalysisResult(
- null, null, path, null, null, null, null, null, null, null, null);
+ AnalysisResult result = new MockAnalysisResult(path: path);
return new DartHighlightsRequestImpl(resourceProvider, result);
}
}
diff --git a/pkg/analyzer_plugin/test/plugin/kythe_mixin_test.dart b/pkg/analyzer_plugin/test/plugin/kythe_mixin_test.dart
index a3af883..94f8b4c 100644
--- a/pkg/analyzer_plugin/test/plugin/kythe_mixin_test.dart
+++ b/pkg/analyzer_plugin/test/plugin/kythe_mixin_test.dart
@@ -94,8 +94,7 @@
@override
Future<EntryRequest> getEntryRequest(
KytheGetKytheEntriesParams parameters) async {
- AnalysisResult result = new AnalysisResult(
- null, null, null, null, null, null, null, null, null, null, null);
+ AnalysisResult result = new MockAnalysisResult();
return new DartEntryRequestImpl(resourceProvider, result);
}
}
diff --git a/pkg/analyzer_plugin/test/plugin/mocks.dart b/pkg/analyzer_plugin/test/plugin/mocks.dart
index 1ccb601..3fffc76 100644
--- a/pkg/analyzer_plugin/test/plugin/mocks.dart
+++ b/pkg/analyzer_plugin/test/plugin/mocks.dart
@@ -5,10 +5,12 @@
import 'dart:async';
import 'dart:collection';
+import 'package:analyzer/error/error.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
-import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/engine.dart'
+ show AnalysisOptionsImpl, TimestampedData;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/timestamped_data.dart';
import 'package:analyzer_plugin/channel/channel.dart';
@@ -54,6 +56,22 @@
Future<Null> performWork() => new Future.value(null);
}
+class MockAnalysisResult implements AnalysisResult {
+ @override
+ final List<AnalysisError> errors;
+
+ @override
+ final LineInfo lineInfo;
+
+ @override
+ final String path;
+
+ MockAnalysisResult({this.errors, this.lineInfo, this.path});
+
+ @override
+ noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
class MockChannel implements PluginCommunicationChannel {
bool _closed = false;
diff --git a/pkg/analyzer_plugin/test/plugin/navigation_mixin_test.dart b/pkg/analyzer_plugin/test/plugin/navigation_mixin_test.dart
index 22603d2..35794aee 100644
--- a/pkg/analyzer_plugin/test/plugin/navigation_mixin_test.dart
+++ b/pkg/analyzer_plugin/test/plugin/navigation_mixin_test.dart
@@ -109,8 +109,7 @@
@override
Future<NavigationRequest> getNavigationRequest(
AnalysisGetNavigationParams parameters) async {
- AnalysisResult result = new AnalysisResult(null, null, parameters.file,
- null, null, null, null, null, null, null, null);
+ AnalysisResult result = new MockAnalysisResult(path: parameters.file);
return new DartNavigationRequestImpl(
resourceProvider, parameters.offset, parameters.length, result);
}
diff --git a/pkg/analyzer_plugin/test/plugin/occurrences_mixin_test.dart b/pkg/analyzer_plugin/test/plugin/occurrences_mixin_test.dart
index ea8a305..a3c076e 100644
--- a/pkg/analyzer_plugin/test/plugin/occurrences_mixin_test.dart
+++ b/pkg/analyzer_plugin/test/plugin/occurrences_mixin_test.dart
@@ -120,8 +120,7 @@
@override
Future<OccurrencesRequest> getOccurrencesRequest(String path) async {
- AnalysisResult result = new AnalysisResult(
- null, null, path, null, null, null, null, null, null, null, null);
+ AnalysisResult result = new MockAnalysisResult(path: path);
return new DartOccurrencesRequestImpl(resourceProvider, result);
}
}
diff --git a/pkg/analyzer_plugin/test/plugin/outline_mixin_test.dart b/pkg/analyzer_plugin/test/plugin/outline_mixin_test.dart
index 3291163..70d7620 100644
--- a/pkg/analyzer_plugin/test/plugin/outline_mixin_test.dart
+++ b/pkg/analyzer_plugin/test/plugin/outline_mixin_test.dart
@@ -94,8 +94,7 @@
@override
Future<OutlineRequest> getOutlineRequest(String path) async {
- AnalysisResult result = new AnalysisResult(
- null, null, path, null, null, null, null, null, null, null, null);
+ AnalysisResult result = new MockAnalysisResult(path: path);
return new DartOutlineRequestImpl(resourceProvider, result);
}
}
diff --git a/pkg/analyzer_plugin/test/utilities/navigation_test.dart b/pkg/analyzer_plugin/test/utilities/navigation_test.dart
index dc4a9cc..e97fcfd 100644
--- a/pkg/analyzer_plugin/test/utilities/navigation_test.dart
+++ b/pkg/analyzer_plugin/test/utilities/navigation_test.dart
@@ -4,13 +4,14 @@
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart' as driver;
import 'package:analyzer_plugin/src/utilities/navigation/navigation.dart';
import 'package:analyzer_plugin/utilities/generator.dart';
import 'package:analyzer_plugin/utilities/navigation/navigation.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import '../plugin/mocks.dart';
+
void main() {
defineReflectiveTests(NavigationGeneratorTest);
}
@@ -19,8 +20,7 @@
class NavigationGeneratorTest {
MemoryResourceProvider provider = new MemoryResourceProvider();
- ResolveResult resolveResult = new driver.AnalysisResult(
- null, null, 'a.dart', null, true, '', null, '', null, null, null);
+ ResolveResult resolveResult = new MockAnalysisResult(path: 'a.dart');
test_none() {
NavigationGenerator generator = new NavigationGenerator([]);
diff --git a/pkg/analyzer_plugin/tool/spec/common_types_spec.html b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
index 7e30303..2b1c9e5 100644
--- a/pkg/analyzer_plugin/tool/spec/common_types_spec.html
+++ b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
@@ -6,7 +6,7 @@
</head>
<body>
<h1>Common Types</h1>
-<version>1.0.1</version>
+<version>1.0.2</version>
<p>
This document contains a specification of the types that are common between
the analysis server wire protocol and the analysis server plugin wire
@@ -539,6 +539,8 @@
<value><code>DOCUMENTATION_COMMENT</code></value>
<value><code>FILE_HEADER</code></value>
<value><code>FUNCTION_BODY</code></value>
+ <value><code>INVOCATION</code></value>
+ <value><code>LITERAL</code></value>
</enum>
</type>
<type name="FoldingRegion">
diff --git a/pkg/compiler/lib/src/backend_strategy.dart b/pkg/compiler/lib/src/backend_strategy.dart
index 0e29978..be1764c 100644
--- a/pkg/compiler/lib/src/backend_strategy.dart
+++ b/pkg/compiler/lib/src/backend_strategy.dart
@@ -11,6 +11,7 @@
import 'enqueue.dart';
import 'elements/entities.dart';
import 'io/source_information.dart';
+import 'js_backend/inferred_data.dart';
import 'js_backend/js_backend.dart';
import 'js_backend/native_data.dart';
import 'js_emitter/sorter.dart';
@@ -55,6 +56,7 @@
SourceSpan spanFromSpannable(Spannable spannable, Entity currentElement);
/// Creates the [TypesInferrer] used by this strategy.
- TypesInferrer createTypesInferrer(JClosedWorld closedWorld,
+ TypesInferrer createTypesInferrer(
+ JClosedWorld closedWorld, InferredDataBuilder inferredDataBuilder,
{bool disableTypeInference: false});
}
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 4a8bc14..8f31433 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -29,6 +29,7 @@
import 'inferrer/typemasks/masks.dart' show TypeMaskStrategy;
import 'io/source_information.dart' show SourceInformation;
import 'js_backend/backend.dart' show JavaScriptBackend;
+import 'js_backend/inferred_data.dart';
import 'kernel/kernel_backend_strategy.dart';
import 'kernel/kernel_strategy.dart';
import 'library_loader.dart' show LibraryLoaderTask, LoadedLibraries;
@@ -376,8 +377,10 @@
mainFunction = closedWorld.elementEnvironment.mainFunction;
reporter.log('Inferring types...');
- globalInference.runGlobalTypeInference(mainFunction, closedWorld);
- closedWorld.computeSideEffects();
+ InferredDataBuilder inferredDataBuilder = new InferredDataBuilderImpl();
+ backend.processAnnotations(closedWorld, inferredDataBuilder);
+ globalInference.runGlobalTypeInference(
+ mainFunction, closedWorld, inferredDataBuilder);
if (stopAfterTypeInference) return;
@@ -423,9 +426,6 @@
OutputUnitData result = deferredLoadTask.run(mainFunction, closedWorld);
JClosedWorld closedWorldRefiner =
backendStrategy.createJClosedWorld(closedWorld);
- // Compute whole-program-knowledge that the backend needs. (This might
- // require the information computed in [world.closeWorld].)
- backend.onResolutionClosedWorld(closedWorldRefiner);
backend.onDeferredLoadComplete(result);
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index 15950a1..7abea41 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -286,7 +286,8 @@
String returnType = '${functionType.returnType}';
String inferredReturnType = '${_resultOfMember(function).returnType}';
- String sideEffects = '${closedWorld.getSideEffectsOfElement(function)}';
+ String sideEffects =
+ '${compiler.globalInference.inferredData.getSideEffectsOfElement(function)}';
int inlinedCount = compiler.dumpInfoTask.inlineCount[function];
if (inlinedCount == null) inlinedCount = 0;
diff --git a/pkg/compiler/lib/src/frontend_strategy.dart b/pkg/compiler/lib/src/frontend_strategy.dart
index 8f915bf..f6b8293 100644
--- a/pkg/compiler/lib/src/frontend_strategy.dart
+++ b/pkg/compiler/lib/src/frontend_strategy.dart
@@ -14,6 +14,7 @@
import 'elements/entities.dart';
import 'elements/types.dart';
import 'enqueue.dart';
+import 'js_backend/allocator_analysis.dart' show KAllocatorAnalysis;
import 'js_backend/backend_usage.dart';
import 'js_backend/interceptor_data.dart';
import 'js_backend/native_data.dart';
@@ -70,6 +71,7 @@
InterceptorDataBuilder interceptorDataBuilder,
BackendUsageBuilder backendUsageBuilder,
RuntimeTypesNeedBuilder rtiNeedBuilder,
+ KAllocatorAnalysis allocatorAnalysis,
NativeResolutionEnqueuer nativeResolutionEnqueuer,
NoSuchMethodRegistry noSuchMethodRegistry,
SelectorConstraintsStrategy selectorConstraintsStrategy,
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index d8c13d6..fe24043 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -81,7 +81,8 @@
// TODO(johnniwinther): Should side effects also be tracked for field
// initializers?
this._sideEffectsBuilder = _analyzedMember is FunctionEntity
- ? _inferrer.closedWorld.getSideEffectsBuilder(_analyzedMember)
+ ? _inferrer.inferredDataBuilder
+ .getSideEffectsBuilder(_analyzedMember)
: new SideEffectsBuilder.free(_analyzedMember),
this._inGenerativeConstructor = _analyzedNode is ir.Constructor {
if (_locals != null) return;
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
index 77622dd..5b45c23 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
@@ -13,6 +13,7 @@
import '../elements/entities.dart';
import '../elements/names.dart';
import '../js_backend/annotations.dart' as optimizerHints;
+import '../js_backend/inferred_data.dart';
import '../js_backend/no_such_method_registry.dart';
import '../js_emitter/sorter.dart';
import '../native/behavior.dart' as native;
@@ -65,6 +66,7 @@
TypeSystem<T> get types;
Map<T, TypeInformation> get concreteTypes;
+ InferredDataBuilder get inferredDataBuilder;
FunctionEntity get mainElement;
@@ -268,6 +270,7 @@
/// The [JClosedWorld] on which inference reasoning is based.
final JClosedWorld closedWorld;
+ final InferredDataBuilder inferredDataBuilder;
final TypeSystem<T> types;
final Map<T, TypeInformation> concreteTypes = new Map<T, TypeInformation>();
@@ -295,6 +298,7 @@
this.noSuchMethodRegistry,
this.mainElement,
this.sorter,
+ this.inferredDataBuilder,
TypeSystemStrategy<T> typeSystemStrategy)
: this.types = new TypeSystem<T>(closedWorld, typeSystemStrategy);
@@ -342,7 +346,8 @@
} else if (callee.isGetter && !selector.isGetter) {
sideEffectsBuilder.setAllSideEffectsAndDependsOnSomething();
} else {
- sideEffectsBuilder.addInput(closedWorld.getSideEffectsBuilder(callee));
+ sideEffectsBuilder
+ .addInput(inferredDataBuilder.getSideEffectsBuilder(callee));
}
}
@@ -502,7 +507,7 @@
tracer.run();
if (!tracer.continueAnalyzing) {
elements.forEach((FunctionEntity element) {
- closedWorld.registerMightBePassedToApply(element);
+ inferredDataBuilder.registerMightBePassedToApply(element);
if (debug.VERBOSE) {
print("traced closure $element as ${true} (bail)");
}
@@ -525,11 +530,11 @@
workQueue.add(info);
});
if (tracer.tracedType.mightBePassedToFunctionApply) {
- closedWorld.registerMightBePassedToApply(element);
+ inferredDataBuilder.registerMightBePassedToApply(element);
}
if (debug.VERBOSE) {
print("traced closure $element as "
- "${closedWorld
+ "${inferredDataBuilder
.getCurrentlyKnownMightBePassedToApply(element)}");
}
});
@@ -762,7 +767,7 @@
}
if (info is StaticCallSiteTypeInformation) {
MemberEntity member = info.calledElement;
- closedWorld.addFunctionCalledInLoop(member);
+ inferredDataBuilder.addFunctionCalledInLoop(member);
} else if (info.mask != null &&
!abstractValueDomain.containsAll(info.mask)) {
// For instance methods, we only register a selector called in a
@@ -770,7 +775,7 @@
// methods as being called from within a loop. This cuts down
// on the code bloat.
info.callees.forEach((MemberEntity element) {
- closedWorld.addFunctionCalledInLoop(element);
+ inferredDataBuilder.addFunctionCalledInLoop(element);
});
}
});
diff --git a/pkg/compiler/lib/src/inferrer/kernel_inferrer_engine.dart b/pkg/compiler/lib/src/inferrer/kernel_inferrer_engine.dart
index ef1f1bc..07d745f 100644
--- a/pkg/compiler/lib/src/inferrer/kernel_inferrer_engine.dart
+++ b/pkg/compiler/lib/src/inferrer/kernel_inferrer_engine.dart
@@ -13,6 +13,7 @@
import '../constants/values.dart';
import '../elements/entities.dart';
import '../elements/types.dart';
+import '../js_backend/inferred_data.dart';
import '../js_backend/no_such_method_registry.dart';
import '../js_emitter/sorter.dart';
import '../js_model/locals.dart';
@@ -32,9 +33,15 @@
final KernelToElementMapForBuilding _elementMap;
final GlobalLocalsMap _globalLocalsMap;
final ClosureDataLookup<ir.Node> _closureDataLookup;
+ final InferredDataBuilder _inferredDataBuilder;
- KernelTypeGraphInferrer(this._compiler, this._elementMap,
- this._globalLocalsMap, this._closureDataLookup, JClosedWorld closedWorld,
+ KernelTypeGraphInferrer(
+ this._compiler,
+ this._elementMap,
+ this._globalLocalsMap,
+ this._closureDataLookup,
+ JClosedWorld closedWorld,
+ this._inferredDataBuilder,
{bool disableTypeInference: false})
: super(closedWorld, disableTypeInference: disableTypeInference);
@@ -51,7 +58,8 @@
closedWorld,
_compiler.backend.noSuchMethodRegistry,
main,
- _compiler.backendStrategy.sorter);
+ _compiler.backendStrategy.sorter,
+ _inferredDataBuilder);
}
@override
@@ -101,7 +109,8 @@
JClosedWorld closedWorld,
NoSuchMethodRegistry noSuchMethodRegistry,
FunctionEntity mainElement,
- Sorter sorter)
+ Sorter sorter,
+ InferredDataBuilder inferredDataBuilder)
: super(
options,
progress,
@@ -111,6 +120,7 @@
noSuchMethodRegistry,
mainElement,
sorter,
+ inferredDataBuilder,
new KernelTypeSystemStrategy(
_elementMap, _globalLocalsMap, _closureDataLookup));
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index ce1cc11..dc903fc 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -770,7 +770,8 @@
giveUp(inferrer);
return safeType(inferrer);
}
- if (inferrer.closedWorld.getCurrentlyKnownMightBePassedToApply(_method)) {
+ if (inferrer.inferredDataBuilder
+ .getCurrentlyKnownMightBePassedToApply(_method)) {
giveUp(inferrer);
return safeType(inferrer);
}
diff --git a/pkg/compiler/lib/src/io/source_information.dart b/pkg/compiler/lib/src/io/source_information.dart
index 5cbb473..59e9b2e 100644
--- a/pkg/compiler/lib/src/io/source_information.dart
+++ b/pkg/compiler/lib/src/io/source_information.dart
@@ -43,7 +43,7 @@
/// Create a [SourceInformationBuilder] for [member].
SourceInformationBuilder<T> createBuilderForContext(
covariant MemberEntity member) {
- return const SourceInformationBuilder();
+ return new SourceInformationBuilder<T>();
}
/// Generate [SourceInformation] marker for non-preamble code.
diff --git a/pkg/compiler/lib/src/js_backend/allocator_analysis.dart b/pkg/compiler/lib/src/js_backend/allocator_analysis.dart
new file mode 100644
index 0000000..d57a0a0
--- /dev/null
+++ b/pkg/compiler/lib/src/js_backend/allocator_analysis.dart
@@ -0,0 +1,124 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:kernel/ast.dart' as ir;
+
+import '../constants/values.dart';
+import '../js_model/elements.dart' show JsToFrontendMap, JField;
+import '../kernel/element_map.dart';
+import '../kernel/element_map_impl.dart' show KernelElementEnvironment;
+import '../kernel/kelements.dart' show KClass, KField;
+import '../options.dart';
+
+abstract class AllocatorAnalysis {}
+
+/// AllocatorAnalysis
+///
+/// Analysis to determine features of the allocator functions. The allocator
+/// function takes parameters for each field initializer and initializes the
+/// fields. Parameters may be omitted if the initializer is always the same
+/// constant value. How the allocator is emitted will determine what kind of
+/// constants can be handled. The initial implementation only permits `null`.
+
+// TODO(sra): Analysis to determine field order. Current field order is
+// essentially declaration order, subclass first. We can reorder fields so that
+// fields initialized with the same constant are together to allow chained
+// initialization. Fields of a class and superclass can be reordered to allow
+// chaining, e.g.
+//
+// this.x = this.z = null;
+//
+class KAllocatorAnalysis implements AllocatorAnalysis {
+ final KernelElementEnvironment _elementEnvironment;
+ KernelToElementMap _elementMap;
+
+ final Map<KField, ConstantValue> _fixedInitializers =
+ <KField, ConstantValue>{};
+
+ KAllocatorAnalysis(this._elementEnvironment) {
+ _elementMap = _elementEnvironment.elementMap;
+ }
+
+ // Register class during resolution. Use simple syntactic analysis to find
+ // null-initialized fields.
+ void registerInstantiatedClass(KClass class_) {
+ ClassDefinition definition = _elementMap.getClassDefinition(class_);
+ assert(definition.kind == ClassKind.regular);
+ ir.Class classNode = definition.node;
+
+ Set<ir.Field> nulls = new Set<ir.Field>();
+ for (ir.Field field in classNode.fields) {
+ if (!field.isInstanceMember) continue;
+ ir.Expression initializer = field.initializer;
+ if (initializer == null || initializer is ir.NullLiteral) {
+ nulls.add(field);
+ }
+ }
+
+ for (ir.Constructor constructor in classNode.constructors) {
+ for (ir.Initializer initializer in constructor.initializers) {
+ if (initializer is ir.FieldInitializer) {
+ // TODO(sra): Check explicit initializer value to see if consistent
+ // over all constructors.
+ nulls.remove(initializer.field);
+ }
+ }
+ }
+
+ for (var fieldNode in nulls) {
+ _fixedInitializers[_elementMap.getField(fieldNode)] =
+ const NullConstantValue();
+ }
+ }
+}
+
+class JAllocatorAnalysis implements AllocatorAnalysis {
+ // --csp and --fast-startup have different constraints to the generated code.
+ final CompilerOptions _options;
+ final Map<JField, ConstantValue> _fixedInitializers =
+ <JField, ConstantValue>{};
+
+ JAllocatorAnalysis._(this._options);
+
+ static JAllocatorAnalysis from(KAllocatorAnalysis kAnalysis,
+ JsToFrontendMap map, CompilerOptions options) {
+ var result = new JAllocatorAnalysis._(options);
+
+ kAnalysis._fixedInitializers.forEach((KField kField, ConstantValue value) {
+ // TODO(sra): Translate constant, but Null does not need translating.
+ if (value.isNull) {
+ JField jField = map.toBackendMember(kField);
+ if (jField != null) {
+ result._fixedInitializers[jField] = value;
+ }
+ }
+ });
+
+ return result;
+ }
+
+ bool get _isEnabled {
+ if (_options.useContentSecurityPolicy && !_options.useStartupEmitter) {
+ // TODO(sra): Refactor csp 'precompiled' constructor generation to allow
+ // in-allocator initialization.
+ return false;
+ }
+ if (!_options.strongMode) return false;
+ return true;
+ }
+ // TODO(sra): Add way to let injected fields be initialized to a constant in
+ // allocator.
+
+ bool isInitializedInAllocator(JField field) {
+ if (!_isEnabled) return false;
+ return _fixedInitializers[field] != null;
+ }
+
+ /// Return constant for a field initialized in allocator. Returns `null` for
+ /// fields not initialized in allocator.
+ ConstantValue initializerValue(JField field) {
+ assert(_isEnabled);
+ return _fixedInitializers[field];
+ }
+}
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index c06c5f0..bacfc5e 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -47,6 +47,7 @@
show ImpactStrategy, ImpactUseCase, WorldImpact, WorldImpactVisitor;
import '../util/util.dart';
import '../world.dart' show JClosedWorld;
+import 'allocator_analysis.dart';
import 'annotations.dart' as optimizerHints;
import 'backend_impact.dart';
import 'backend_usage.dart';
@@ -56,6 +57,7 @@
import 'custom_elements_analysis.dart';
import 'enqueuer.dart';
import 'impact_transformer.dart';
+import 'inferred_data.dart';
import 'interceptor_data.dart';
import 'js_interop_analysis.dart' show JsInteropAnalysis;
import 'namer.dart';
@@ -363,6 +365,8 @@
/// constructors for custom elements.
CustomElementsCodegenAnalysis _customElementsCodegenAnalysis;
+ KAllocatorAnalysis _allocatorResolutionAnalysis;
+
/// Codegen support for typed JavaScript interop.
JsInteropAnalysis jsInteropAnalysis;
@@ -545,11 +549,6 @@
frontendStrategy.nativeBasicData, nativeDataBuilder);
}
- /// Called when the closed world from resolution has been computed.
- void onResolutionClosedWorld(JClosedWorld closedWorld) {
- processAnnotations(closedWorld);
- }
-
void onDeferredLoadComplete(OutputUnitData data) {
_outputUnitData = compiler.backendStrategy.convertOutputUnitData(data);
}
@@ -577,6 +576,7 @@
commonElements,
nativeBasicData,
_backendUsageBuilder);
+ _allocatorResolutionAnalysis = new KAllocatorAnalysis(elementEnvironment);
ClassQueries classQueries = compiler.frontendStrategy.createClassQueries();
ClassHierarchyBuilder classHierarchyBuilder =
new ClassHierarchyBuilder(commonElements, classQueries);
@@ -612,6 +612,7 @@
noSuchMethodRegistry,
customElementsResolutionAnalysis,
_nativeResolutionEnqueuer,
+ _allocatorResolutionAnalysis,
compiler.deferredLoadTask),
compiler.frontendStrategy.createResolutionWorldBuilder(
nativeBasicData,
@@ -619,6 +620,7 @@
interceptorDataBuilder,
_backendUsageBuilder,
rtiNeedBuilder,
+ _allocatorResolutionAnalysis,
_nativeResolutionEnqueuer,
noSuchMethodRegistry,
compiler.options.strongMode && useStrongModeWorldStrategy
@@ -842,18 +844,19 @@
/// Process backend specific annotations.
// TODO(johnniwinther): Merge this with [AnnotationProcessor] and use
// [ElementEnvironment.getMemberMetadata] in [AnnotationProcessor].
- void processAnnotations(JClosedWorld closedWorld) {
+ void processAnnotations(
+ JClosedWorld closedWorld, InferredDataBuilder inferredDataBuilder) {
// These methods are overwritten with generated versions.
inlineCache.markAsNonInlinable(
closedWorld.commonElements.getInterceptorMethod,
insideLoop: true);
for (MemberEntity entity in closedWorld.processedMembers) {
- _processMemberAnnotations(closedWorld, entity);
+ _processMemberAnnotations(closedWorld, inferredDataBuilder, entity);
}
}
- void _processMemberAnnotations(
- JClosedWorld closedWorld, MemberEntity element) {
+ void _processMemberAnnotations(JClosedWorld closedWorld,
+ InferredDataBuilder inferredDataBuilder, MemberEntity element) {
ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
CommonElements commonElements = closedWorld.commonElements;
bool hasNoInline = false;
@@ -927,14 +930,14 @@
reporter.reportHintMessage(
method, MessageKind.GENERIC, {'text': "Cannot throw"});
}
- closedWorld.registerCannotThrow(method);
+ inferredDataBuilder.registerCannotThrow(method);
} else if (cls == commonElements.noSideEffectsClass) {
hasNoSideEffects = true;
if (VERBOSE_OPTIMIZER_HINTS) {
reporter.reportHintMessage(
method, MessageKind.GENERIC, {'text': "Has no side effects"});
}
- closedWorld.registerSideEffectsFree(method);
+ inferredDataBuilder.registerSideEffectsFree(method);
}
}
if (hasForceInline && hasNoInline) {
diff --git a/pkg/compiler/lib/src/js_backend/inferred_data.dart b/pkg/compiler/lib/src/js_backend/inferred_data.dart
new file mode 100644
index 0000000..3318b1c
--- /dev/null
+++ b/pkg/compiler/lib/src/js_backend/inferred_data.dart
@@ -0,0 +1,246 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:collection' show Queue;
+
+import '../common.dart';
+import '../elements/entities.dart';
+import '../types/abstract_value_domain.dart';
+import '../universe/selector.dart';
+import '../universe/side_effects.dart';
+import '../world.dart';
+
+abstract class InferredData {
+ /// Returns the side effects of executing [element].
+ SideEffects getSideEffectsOfElement(FunctionEntity element);
+
+ /// Returns the side effects of calling [selector] on the [receiver].
+ SideEffects getSideEffectsOfSelector(
+ Selector selector, AbstractValue receiver);
+
+ /// Returns `true` if [element] is guaranteed not to throw an exception.
+ bool getCannotThrow(FunctionEntity element);
+
+ /// Returns `true` if [element] is called in a loop.
+ // TODO(johnniwinther): Is this 'potentially called' or 'known to be called'?
+ // TODO(johnniwinther): Change [MemberEntity] to [FunctionEntity].
+ bool isCalledInLoop(MemberEntity element);
+
+ /// Returns `true` if [element] might be passed to `Function.apply`.
+ // TODO(johnniwinther): Is this 'passed invocation target` or
+ // `passed as argument`?
+ bool getMightBePassedToApply(FunctionEntity element);
+}
+
+abstract class InferredDataBuilder {
+ /// Registers the executing of [element] as without side effects.
+ void registerSideEffectsFree(FunctionEntity element);
+
+ /// Returns the [SideEffectBuilder] associated with [element].
+ SideEffectsBuilder getSideEffectsBuilder(FunctionEntity member);
+
+ /// Registers that [element] might be passed to `Function.apply`.
+ // TODO(johnniwinther): Is this 'passed invocation target` or
+ // `passed as argument`?
+ void registerMightBePassedToApply(FunctionEntity element);
+
+ /// Returns `true` if [element] might be passed to `Function.apply` given the
+ /// currently inferred information.
+ bool getCurrentlyKnownMightBePassedToApply(FunctionEntity element);
+
+ /// Registers that [element] is called in a loop.
+ // TODO(johnniwinther): Is this 'potentially called' or 'known to be called'?
+ void addFunctionCalledInLoop(MemberEntity element);
+
+ /// Registers that [element] is guaranteed not to throw an exception.
+ void registerCannotThrow(FunctionEntity element);
+
+ /// Create a [InferredData] object for the collected information.
+ InferredData close(JClosedWorld closedWorld);
+}
+
+class InferredDataImpl implements InferredData {
+ final JClosedWorld _closedWorld;
+ final Set<MemberEntity> _functionsCalledInLoop;
+ final Map<FunctionEntity, SideEffects> _sideEffects;
+
+ final Set<FunctionEntity> _sideEffectsFreeElements;
+
+ final Set<FunctionEntity> _elementsThatCannotThrow;
+
+ final Set<FunctionEntity> _functionsThatMightBePassedToApply;
+
+ InferredDataImpl(
+ this._closedWorld,
+ this._functionsCalledInLoop,
+ this._sideEffects,
+ this._sideEffectsFreeElements,
+ this._elementsThatCannotThrow,
+ this._functionsThatMightBePassedToApply);
+
+ @override
+ SideEffects getSideEffectsOfSelector(
+ Selector selector, AbstractValue receiver) {
+ // We're not tracking side effects of closures.
+ if (selector.isClosureCall ||
+ _closedWorld.includesClosureCall(selector, receiver)) {
+ return new SideEffects();
+ }
+ SideEffects sideEffects = new SideEffects.empty();
+ for (MemberEntity e in _closedWorld.locateMembers(selector, receiver)) {
+ if (e.isField) {
+ if (selector.isGetter) {
+ if (!_closedWorld.fieldNeverChanges(e)) {
+ sideEffects.setDependsOnInstancePropertyStore();
+ }
+ } else if (selector.isSetter) {
+ sideEffects.setChangesInstanceProperty();
+ } else {
+ assert(selector.isCall);
+ sideEffects.setAllSideEffects();
+ sideEffects.setDependsOnSomething();
+ }
+ } else {
+ sideEffects.add(getSideEffectsOfElement(e));
+ }
+ }
+ return sideEffects;
+ }
+
+ @override
+ SideEffects getSideEffectsOfElement(FunctionEntity element) {
+ assert(_sideEffects != null,
+ failedAt(element, "Side effects have not been computed yet."));
+ // TODO(johnniwinther): Check that [_makeSideEffects] is only called if
+ // type inference has been disabled (explicitly or because of compile time
+ // errors).
+ return _sideEffects.putIfAbsent(element, _makeSideEffects);
+ }
+
+ static SideEffects _makeSideEffects() => new SideEffects();
+
+ @override
+ bool isCalledInLoop(MemberEntity element) {
+ return _functionsCalledInLoop.contains(element);
+ }
+
+ @override
+ bool getCannotThrow(FunctionEntity element) {
+ return _elementsThatCannotThrow.contains(element);
+ }
+
+ @override
+ bool getMightBePassedToApply(FunctionEntity element) {
+ // We assume all functions reach Function.apply if no functions are
+ // registered so. We get an empty set in two circumstances (1) a trivial
+ // program and (2) when compiling without type inference
+ // (i.e. --disable-type-inference). Returning `true` has consequences (extra
+ // metadata for Function.apply) only when Function.apply is also part of the
+ // program. It is an unusual trivial program that includes Function.apply
+ // but does not call it on a function.
+ //
+ // TODO(sra): We should reverse the sense of this set and register functions
+ // that we have proven do not reach Function.apply.
+ if (_functionsThatMightBePassedToApply.isEmpty) return true;
+ return _functionsThatMightBePassedToApply.contains(element);
+ }
+}
+
+class InferredDataBuilderImpl implements InferredDataBuilder {
+ final Set<MemberEntity> _functionsCalledInLoop = new Set<MemberEntity>();
+ Map<MemberEntity, SideEffectsBuilder> _sideEffectsBuilders =
+ <MemberEntity, SideEffectsBuilder>{};
+ final Set<FunctionEntity> prematureSideEffectAccesses =
+ new Set<FunctionEntity>();
+
+ final Set<FunctionEntity> _sideEffectsFreeElements =
+ new Set<FunctionEntity>();
+
+ final Set<FunctionEntity> _elementsThatCannotThrow =
+ new Set<FunctionEntity>();
+
+ final Set<FunctionEntity> _functionsThatMightBePassedToApply =
+ new Set<FunctionEntity>();
+
+ InferredDataBuilderImpl();
+
+ @override
+ SideEffectsBuilder getSideEffectsBuilder(MemberEntity member) {
+ return _sideEffectsBuilders.putIfAbsent(
+ member, () => new SideEffectsBuilder(member));
+ }
+
+ @override
+ void registerSideEffectsFree(FunctionEntity element) {
+ _sideEffectsFreeElements.add(element);
+ assert(!_sideEffectsBuilders.containsKey(element));
+ _sideEffectsBuilders[element] = new SideEffectsBuilder.free(element);
+ }
+
+ /// Compute [SideEffects] for all registered [SideEffectBuilder]s.
+ InferredData close(JClosedWorld closedWorld) {
+ assert(_sideEffectsBuilders != null,
+ "Inferred data has already been computed.");
+ Map<FunctionEntity, SideEffects> _sideEffects =
+ <FunctionEntity, SideEffects>{};
+ Iterable<SideEffectsBuilder> sideEffectsBuilders =
+ _sideEffectsBuilders.values;
+ emptyWorkList(sideEffectsBuilders);
+ for (SideEffectsBuilder sideEffectsBuilder in sideEffectsBuilders) {
+ _sideEffects[sideEffectsBuilder.member] = sideEffectsBuilder.sideEffects;
+ }
+ _sideEffectsBuilders = null;
+
+ return new InferredDataImpl(
+ closedWorld,
+ _functionsCalledInLoop,
+ _sideEffects,
+ _sideEffectsFreeElements,
+ _elementsThatCannotThrow,
+ _functionsThatMightBePassedToApply);
+ }
+
+ static void emptyWorkList(Iterable<SideEffectsBuilder> sideEffectsBuilders) {
+ // TODO(johnniwinther): Optimize this algorithm, possibly by using
+ // `pkg/front_end/lib/src/dependency_walker.dart`.
+ Queue<SideEffectsBuilder> queue = new Queue<SideEffectsBuilder>();
+ Set<SideEffectsBuilder> inQueue = new Set<SideEffectsBuilder>();
+
+ for (SideEffectsBuilder builder in sideEffectsBuilders) {
+ queue.addLast(builder);
+ inQueue.add(builder);
+ }
+ while (queue.isNotEmpty) {
+ SideEffectsBuilder sideEffectsBuilder = queue.removeFirst();
+ inQueue.remove(sideEffectsBuilder);
+ for (SideEffectsBuilder dependent in sideEffectsBuilder.depending) {
+ if (dependent.add(sideEffectsBuilder.sideEffects)) {
+ if (inQueue.add(dependent)) {
+ queue.addLast(dependent);
+ }
+ }
+ }
+ }
+ }
+
+ @override
+ void addFunctionCalledInLoop(MemberEntity element) {
+ _functionsCalledInLoop.add(element);
+ }
+
+ @override
+ void registerCannotThrow(FunctionEntity element) {
+ _elementsThatCannotThrow.add(element);
+ }
+
+ @override
+ void registerMightBePassedToApply(FunctionEntity element) {
+ _functionsThatMightBePassedToApply.add(element);
+ }
+
+ @override
+ bool getCurrentlyKnownMightBePassedToApply(FunctionEntity element) {
+ return _functionsThatMightBePassedToApply.contains(element);
+ }
+}
diff --git a/pkg/compiler/lib/src/js_backend/resolution_listener.dart b/pkg/compiler/lib/src/js_backend/resolution_listener.dart
index 3f97095..f46723a 100644
--- a/pkg/compiler/lib/src/js_backend/resolution_listener.dart
+++ b/pkg/compiler/lib/src/js_backend/resolution_listener.dart
@@ -17,6 +17,7 @@
import '../universe/use.dart' show StaticUse, TypeUse;
import '../universe/world_impact.dart'
show WorldImpact, WorldImpactBuilder, WorldImpactBuilderImpl;
+import 'allocator_analysis.dart';
import 'backend.dart';
import 'backend_impact.dart';
import 'backend_usage.dart';
@@ -43,6 +44,7 @@
final CustomElementsResolutionAnalysis _customElementsAnalysis;
final NativeResolutionEnqueuer _nativeEnqueuer;
+ final KAllocatorAnalysis _allocatorAnalysis;
/// True when we enqueue the loadLibrary code.
bool _isLoadLibraryFunctionResolved = false;
@@ -58,6 +60,7 @@
this._noSuchMethodRegistry,
this._customElementsAnalysis,
this._nativeEnqueuer,
+ this._allocatorAnalysis,
this._deferredLoadTask);
void _registerBackendImpact(
@@ -403,6 +406,7 @@
@override
WorldImpact registerInstantiatedClass(ClassEntity cls) {
+ _allocatorAnalysis.registerInstantiatedClass(cls);
return _processClass(cls);
}
diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
index b8d5263..c72190e 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -198,6 +198,8 @@
namer,
this,
closedWorld,
+ closedWorld.allocatorAnalysis,
+ compiler.globalInference.inferredData,
backend.sourceInformationStrategy,
compiler.backendStrategy.sorter,
typeTestRegistry.rtiNeededClasses,
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
index a888d94..1e24de4 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/class_emitter.dart
@@ -134,6 +134,9 @@
bool needsFieldsForConstructor = !emitStatics && !classIsNative;
if (needsFieldsForConstructor || needsAccessor) {
List<jsAst.Literal> fieldNameParts = <jsAst.Literal>[];
+ if (field.nullInitializerInAllocator) {
+ fieldNameParts.add(js.stringPart('0'));
+ }
if (!needsAccessor) {
// Emit field for constructor generation.
assert(!classIsNative);
diff --git a/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart b/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
index b5492b7..acb5308 100644
--- a/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/full_emitter/setup_program_builder.dart
@@ -206,15 +206,22 @@
var accessors = [];
var str = "function " + name + "(";
- var body = "";
+ var comma = "", body = "";
for (var i = 0; i < fields.length; i++) {
- if(i != 0) str += ", ";
-
- var field = generateAccessor(fields[i], accessors, name);
- var parameter = "p_" + field;
- str += parameter;
- body += ("this." + field + " = " + parameter + ";\\n");
+ var fieldDescriptor = fields[i];
+ if (fieldDescriptor.charCodeAt(0) == 48) {
+ fieldDescriptor = fieldDescriptor.substring(1);
+ var field = generateAccessor(fieldDescriptor, accessors, name);
+ body += ("this." + field + " = null;\\n");
+ } else {
+ var field = generateAccessor(fieldDescriptor, accessors, name);
+ var parameter = "p_" + field;
+ str += comma;
+ comma = ", ";
+ str += parameter;
+ body += ("this." + field + " = " + parameter + ";\\n");
+ }
}
if (supportsDirectProtoAccess) {
body += "this." + #deferredActionString + "();";
diff --git a/pkg/compiler/lib/src/js_emitter/model.dart b/pkg/compiler/lib/src/js_emitter/model.dart
index 3938cfb..b1436c5 100644
--- a/pkg/compiler/lib/src/js_emitter/model.dart
+++ b/pkg/compiler/lib/src/js_emitter/model.dart
@@ -384,9 +384,17 @@
final bool needsCheckedSetter;
+ final bool nullInitializerInAllocator; // TODO(sra): Generalize.
+
// TODO(floitsch): support renamed fields.
- Field(this.element, this.name, this.accessorName, this.getterFlags,
- this.setterFlags, this.needsCheckedSetter);
+ Field(
+ this.element,
+ this.name,
+ this.accessorName,
+ this.getterFlags,
+ this.setterFlags,
+ this.needsCheckedSetter,
+ this.nullInitializerInAllocator);
bool get needsGetter => getterFlags != 0;
bool get needsUncheckedSetter => setterFlags != 0;
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index 22ca61f..09d4947 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -19,15 +19,17 @@
import '../../elements/types.dart';
import '../../io/source_information.dart';
import '../../js/js.dart' as js;
+import '../../js_backend/allocator_analysis.dart' show JAllocatorAnalysis;
import '../../js_backend/backend.dart' show SuperMemberData;
import '../../js_backend/backend_usage.dart';
import '../../js_backend/constant_handler_javascript.dart'
show JavaScriptConstantCompiler;
import '../../js_backend/custom_elements_analysis.dart';
-import '../../js_backend/namer.dart' show Namer, StringBackedName;
-import '../../js_backend/native_data.dart';
+import '../../js_backend/inferred_data.dart';
import '../../js_backend/interceptor_data.dart';
import '../../js_backend/js_interop_analysis.dart';
+import '../../js_backend/namer.dart' show Namer, StringBackedName;
+import '../../js_backend/native_data.dart';
import '../../js_backend/runtime_types.dart'
show RuntimeTypesChecks, RuntimeTypesNeed, RuntimeTypesEncoder;
import '../../js_model/elements.dart' show JGeneratorBody, JSignatureMethod;
@@ -83,6 +85,8 @@
final Namer _namer;
final CodeEmitterTask _task;
final JClosedWorld _closedWorld;
+ final JAllocatorAnalysis _allocatorAnalysis;
+ final InferredData _inferredData;
final SourceInformationStrategy _sourceInformationStrategy;
/// The [Sorter] used for ordering elements in the generated JavaScript.
@@ -128,6 +132,8 @@
this._namer,
this._task,
this._closedWorld,
+ this._allocatorAnalysis,
+ this._inferredData,
this._sourceInformationStrategy,
this._sorter,
Set<ClassEntity> rtiNeededClasses,
@@ -831,7 +837,7 @@
bool _methodCanBeApplied(FunctionEntity method) {
return _backendUsage.isFunctionApplyUsed &&
- _closedWorld.getMightBePassedToApply(method);
+ _inferredData.getMightBePassedToApply(method);
}
/* Map | List */ _computeParameterDefaultValues(FunctionEntity method) {
@@ -1065,8 +1071,16 @@
}
}
}
+
+ // TODO(sra): Generalize for constants other than null.
+ bool nullInitializerInAllocator = false;
+ if (_allocatorAnalysis.isInitializedInAllocator(field)) {
+ assert(_allocatorAnalysis.initializerValue(field).isNull);
+ nullInitializerInAllocator = true;
+ }
+
fields.add(new Field(field, name, accessorName, getterFlags, setterFlags,
- needsCheckedSetter));
+ needsCheckedSetter, nullInitializerInAllocator));
}
FieldVisitor visitor = new FieldVisitor(_options, _elementEnvironment,
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index 72ea813..b0356e6 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -826,10 +826,15 @@
}
for (Field field in cls.fields) {
- js.Parameter parameter = new js.Parameter('t${parameters.length}');
- parameters.add(parameter);
- statements.add(
- js.js.statement('#.# = #', [thisRef, field.name, parameter.name]));
+ if (field.nullInitializerInAllocator) {
+ // TODO(sra): Chain initializations, e.g. `this.b = this.a = null;`.
+ statements.add(js.js.statement('#.# = null', [thisRef, field.name]));
+ } else {
+ js.Parameter parameter = new js.Parameter('t${parameters.length}');
+ parameters.add(parameter);
+ statements.add(
+ js.js.statement('#.# = #', [thisRef, field.name, parameter.name]));
+ }
}
if (cls.hasRtiField) {
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index fac95b8..d8a72c6 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -24,9 +24,11 @@
import '../inferrer/kernel_inferrer_engine.dart';
import '../js_emitter/sorter.dart';
import '../js/js_source_mapping.dart';
+import '../js_backend/allocator_analysis.dart';
import '../js_backend/backend.dart';
import '../js_backend/backend_usage.dart';
import '../js_backend/constant_system_javascript.dart';
+import '../js_backend/inferred_data.dart';
import '../js_backend/interceptor_data.dart';
import '../js_backend/native_data.dart';
import '../js_backend/no_such_method_registry.dart';
@@ -178,7 +180,7 @@
@override
SourceInformationStrategy get sourceInformationStrategy {
if (!_compiler.options.generateSourceMap) {
- return const JavaScriptSourceInformationStrategy();
+ return const JavaScriptSourceInformationStrategy<ir.Node>();
}
return new KernelSourceInformationStrategy(this);
}
@@ -215,10 +217,11 @@
}
@override
- TypesInferrer createTypesInferrer(JClosedWorld closedWorld,
+ TypesInferrer createTypesInferrer(
+ JClosedWorld closedWorld, InferredDataBuilder inferredDataBuilder,
{bool disableTypeInference: false}) {
return new KernelTypeGraphInferrer(_compiler, _elementMap, _globalLocalsMap,
- _closureDataLookup, closedWorld,
+ _closureDataLookup, closedWorld, inferredDataBuilder,
disableTypeInference: disableTypeInference);
}
}
@@ -374,6 +377,9 @@
map.toBackendFunctionSet(oldNoSuchMethodData.otherImpls),
map.toBackendFunctionSet(oldNoSuchMethodData.forwardingSyntaxImpls));
+ JAllocatorAnalysis allocatorAnalysis =
+ JAllocatorAnalysis.from(closedWorld.allocatorAnalysis, map, _options);
+
return new JsClosedWorld(_elementMap,
elementEnvironment: _elementEnvironment,
dartTypes: _elementMap.types,
@@ -396,7 +402,8 @@
processedMembers: processedMembers,
mixinUses: mixinUses,
typesImplementedBySubclasses: typesImplementedBySubclasses,
- abstractValueStrategy: _abstractValueStrategy);
+ abstractValueStrategy: _abstractValueStrategy,
+ allocatorAnalysis: allocatorAnalysis);
}
BackendUsage _convertBackendUsage(
@@ -607,6 +614,7 @@
final JsKernelToElementMap elementMap;
final RuntimeTypesNeed rtiNeed;
AbstractValueDomain _abstractValueDomain;
+ final JAllocatorAnalysis allocatorAnalysis;
JsClosedWorld(this.elementMap,
{ElementEnvironment elementEnvironment,
@@ -617,6 +625,7 @@
InterceptorData interceptorData,
BackendUsage backendUsage,
this.rtiNeed,
+ this.allocatorAnalysis,
NoSuchMethodData noSuchMethodData,
Set<ClassEntity> implementedClasses,
Iterable<ClassEntity> liveNativeClasses,
diff --git a/pkg/compiler/lib/src/kernel/element_map.dart b/pkg/compiler/lib/src/kernel/element_map.dart
index a293039..dc54118 100644
--- a/pkg/compiler/lib/src/kernel/element_map.dart
+++ b/pkg/compiler/lib/src/kernel/element_map.dart
@@ -120,6 +120,9 @@
/// Return the [ImportEntity] corresponding to [node].
ImportEntity getImport(ir.LibraryDependency node);
+
+ /// Returns the definition information for [cls].
+ ClassDefinition getClassDefinition(covariant ClassEntity cls);
}
/// Interface that translates between Kernel IR nodes and entities used for
@@ -185,9 +188,6 @@
/// Returns the definition information for [member].
MemberDefinition getMemberDefinition(covariant MemberEntity member);
- /// Returns the definition information for [cls].
- ClassDefinition getClassDefinition(covariant ClassEntity cls);
-
/// Returns the static type of [node].
// TODO(johnniwinther): This should be provided directly from kernel.
DartType getStaticType(ir.Expression node);
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index f6812f4..e566ff0 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -27,6 +27,7 @@
import '../elements/types.dart';
import '../environment.dart';
import '../frontend_strategy.dart';
+import '../js_backend/allocator_analysis.dart' show KAllocatorAnalysis;
import '../js_backend/backend_usage.dart';
import '../js_backend/constant_system_javascript.dart';
import '../js_backend/interceptor_data.dart';
@@ -1961,6 +1962,7 @@
InterceptorDataBuilder interceptorDataBuilder,
BackendUsageBuilder backendUsageBuilder,
RuntimeTypesNeedBuilder rtiNeedBuilder,
+ KAllocatorAnalysis allocatorAnalysis,
NativeResolutionEnqueuer nativeResolutionEnqueuer,
NoSuchMethodRegistry noSuchMethodRegistry,
SelectorConstraintsStrategy selectorConstraintsStrategy,
@@ -1976,6 +1978,7 @@
interceptorDataBuilder,
backendUsageBuilder,
rtiNeedBuilder,
+ allocatorAnalysis,
nativeResolutionEnqueuer,
noSuchMethodRegistry,
selectorConstraintsStrategy,
@@ -2090,6 +2093,7 @@
/// Members that are written either directly or through a setter selector.
final Iterable<MemberEntity> assignedInstanceMembers;
+ final KAllocatorAnalysis allocatorAnalysis;
final Iterable<ClassEntity> liveNativeClasses;
@@ -2106,6 +2110,7 @@
this.noSuchMethodData,
ResolutionWorldBuilder resolutionWorldBuilder,
RuntimeTypesNeedBuilder rtiNeedBuilder,
+ this.allocatorAnalysis,
Set<ClassEntity> implementedClasses,
this.liveNativeClasses,
this.liveInstanceMembers,
diff --git a/pkg/compiler/lib/src/kernel/element_map_mixins.dart b/pkg/compiler/lib/src/kernel/element_map_mixins.dart
index c661c48..d8c74cc 100644
--- a/pkg/compiler/lib/src/kernel/element_map_mixins.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_mixins.dart
@@ -604,7 +604,8 @@
@override
ConstantExpression visitIntLiteral(ir.IntLiteral node) {
- return new IntConstantExpression(new BigInt.from(node.value));
+ return new IntConstantExpression(
+ new BigInt.from(node.value).toUnsigned(64));
}
@override
diff --git a/pkg/compiler/lib/src/kernel/kernel_strategy.dart b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
index d6d273e..b595d81 100644
--- a/pkg/compiler/lib/src/kernel/kernel_strategy.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
@@ -20,6 +20,7 @@
import '../enqueue.dart';
import '../environment.dart' as env;
import '../frontend_strategy.dart';
+import '../js_backend/allocator_analysis.dart' show KAllocatorAnalysis;
import '../js_backend/backend_usage.dart';
import '../js_backend/interceptor_data.dart';
import '../js_backend/native_data.dart';
@@ -129,6 +130,7 @@
InterceptorDataBuilder interceptorDataBuilder,
BackendUsageBuilder backendUsageBuilder,
RuntimeTypesNeedBuilder rtiNeedBuilder,
+ KAllocatorAnalysis allocatorAnalysis,
NativeResolutionEnqueuer nativeResolutionEnqueuer,
NoSuchMethodRegistry noSuchMethodRegistry,
SelectorConstraintsStrategy selectorConstraintsStrategy,
@@ -142,6 +144,7 @@
interceptorDataBuilder,
backendUsageBuilder,
rtiNeedBuilder,
+ allocatorAnalysis,
nativeResolutionEnqueuer,
noSuchMethodRegistry,
selectorConstraintsStrategy,
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index dc624c1..5de83bd 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -687,15 +687,15 @@
/// Models the behavior of having instances of [type] escape from Dart code
/// into native code.
- void _escape(DartType type) {
+ void _escape(DartType type, bool isJsInterop) {
type = elementEnvironment.getUnaliasedType(type);
if (type is FunctionType) {
FunctionType functionType = type;
// A function might be called from native code, passing us novel
// parameters.
- _escape(functionType.returnType);
+ _escape(functionType.returnType, isJsInterop);
for (DartType parameter in functionType.parameterTypes) {
- _capture(parameter);
+ _capture(parameter, isJsInterop);
}
}
}
@@ -706,16 +706,16 @@
///
/// We assume that JS-interop APIs cannot instantiate Dart types or
/// non-JSInterop native types.
- void _capture(DartType type, {bool isInterop: false}) {
+ void _capture(DartType type, bool isJsInterop) {
type = elementEnvironment.getUnaliasedType(type);
if (type is FunctionType) {
FunctionType functionType = type;
- _capture(functionType.returnType, isInterop: isInterop);
+ _capture(functionType.returnType, isJsInterop);
for (DartType parameter in functionType.parameterTypes) {
- _escape(parameter);
+ _escape(parameter, isJsInterop);
}
} else {
- if (!isInterop) {
+ if (!isJsInterop) {
_behavior.typesInstantiated.add(type);
} else {
if (type is InterfaceType &&
@@ -756,14 +756,14 @@
: commonElements.dynamicType);
// Declared types are nullable.
_behavior.typesReturned.add(commonElements.nullType);
- _capture(type, isInterop: isJsInterop);
+ _capture(type, isJsInterop);
_overrideWithAnnotations(metadata, lookupType);
return _behavior;
}
NativeBehavior buildFieldStoreBehavior(DartType type) {
_behavior = new NativeBehavior();
- _escape(type);
+ _escape(type, false);
// We don't override the default behaviour - the annotations apply to
// loading the field.
return _behavior;
@@ -790,13 +790,13 @@
// Declared types are nullable.
_behavior.typesReturned.add(commonElements.nullType);
}
- _capture(type, isInterop: isJsInterop);
+ _capture(type, isJsInterop);
for (DartType type in type.optionalParameterTypes) {
- _escape(type);
+ _escape(type, isJsInterop);
}
for (DartType type in type.namedParameterTypes) {
- _escape(type);
+ _escape(type, isJsInterop);
}
_overrideWithAnnotations(metadata, lookupType);
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index aed9b6c..079f4c0 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -22,6 +22,7 @@
import '../elements/types.dart';
import '../io/source_information.dart';
import '../js/js.dart' as js;
+import '../js_backend/allocator_analysis.dart' show JAllocatorAnalysis;
import '../js_backend/backend.dart' show JavaScriptBackend;
import '../js_backend/runtime_types.dart' show RuntimeTypesSubstitutions;
import '../js_emitter/js_emitter.dart' show NativeEmitter;
@@ -36,6 +37,7 @@
import '../universe/call_structure.dart';
import '../universe/selector.dart';
import '../universe/side_effects.dart' show SideEffects;
+import '../universe/target_checks.dart' show TargetChecks;
import '../universe/use.dart'
show ConstantUse, ConstrainedDynamicUse, StaticUse;
import '../universe/world_builder.dart' show CodegenWorldBuilder;
@@ -73,6 +75,7 @@
final CodegenWorldBuilder _worldBuilder;
final CodegenRegistry registry;
final ClosureDataLookup closureDataLookup;
+ JAllocatorAnalysis _allocatorAnalysis;
/// A stack of [InterfaceType]s that have been seen during inlining of
/// factory constructors. These types are preserved in [HInvokeStatic]s and
@@ -131,7 +134,8 @@
this.nativeEmitter,
this._sourceInformationStrategy)
: this.targetElement = _effectiveTargetElementFor(initialTargetElement),
- _infoReporter = compiler.dumpInfoTask {
+ _infoReporter = compiler.dumpInfoTask,
+ _allocatorAnalysis = closedWorld.allocatorAnalysis {
_enterFrame(targetElement);
this.loopHandler = new KernelLoopHandler(this);
typeBuilder = new KernelTypeBuilder(this, _elementMap, _globalLocalsMap);
@@ -320,7 +324,7 @@
void buildField(ir.Field node) {
_inLazyInitializerExpression = node.isStatic;
FieldEntity field = _elementMap.getMember(node);
- openFunction(field);
+ openFunction(field, checks: TargetChecks.none);
if (node.isInstanceMember && options.enableTypeAssertions) {
HInstruction thisInstruction = localsHandler.readThis(
sourceInformation: _sourceInformationBuilder.buildGet(node));
@@ -468,7 +472,8 @@
ClassEntity cls = constructor.enclosingClass;
if (_inliningStack.isEmpty) {
- openFunction(constructor, node.function);
+ openFunction(constructor,
+ functionNode: node.function, checks: TargetChecks.none);
}
// [fieldValues] accumulates the field initializer values, which may be
@@ -487,7 +492,10 @@
(ClassEntity enclosingClass, FieldEntity member) {
HInstruction value = constructorData.fieldValues[member];
if (value == null) {
- assert(isCustomElement || reporter.hasReportedError,
+ assert(
+ _allocatorAnalysis.isInitializedInAllocator(member) ||
+ isCustomElement ||
+ reporter.hasReportedError,
'No initializer value for field ${member}');
} else {
fields.add(member);
@@ -697,12 +705,15 @@
default:
failedAt(field, "Unexpected member definition $definition.");
}
+
if (node.initializer == null) {
// Unassigned fields of native classes are not initialized to
// prevent overwriting pre-initialized native properties.
if (!nativeData.isNativeOrExtendsNative(cls)) {
- constructorData.fieldValues[field] =
- graph.addConstantNull(closedWorld);
+ if (!_allocatorAnalysis.isInitializedInAllocator(field)) {
+ constructorData.fieldValues[field] =
+ graph.addConstantNull(closedWorld);
+ }
}
} else if (node.initializer is! ir.NullLiteral ||
!nativeData.isNativeClass(cls)) {
@@ -710,10 +721,12 @@
// class type parameters are accessed as values.
// TODO(sra): It would be sufficient to know the context was a field
// initializer.
- inlinedFrom(field, () {
- node.initializer.accept(this);
- constructorData.fieldValues[field] = pop();
- });
+ if (!_allocatorAnalysis.isInitializedInAllocator(field)) {
+ inlinedFrom(field, () {
+ node.initializer.accept(this);
+ constructorData.fieldValues[field] = pop();
+ });
+ }
}
});
}
@@ -741,6 +754,7 @@
var foundSuperOrRedirectCall = false;
for (var initializer in constructor.initializers) {
if (initializer is ir.FieldInitializer) {
+ // TODO(sra): Skip fields initialized in allocator.
initializer.value.accept(this);
constructorData.fieldValues[_elementMap.getField(initializer.field)] =
pop();
@@ -949,8 +963,8 @@
/// Builds generative constructor body.
void buildConstructorBody(ir.Constructor constructor) {
- openFunction(
- _elementMap.getConstructorBody(constructor), constructor.function);
+ openFunction(_elementMap.getConstructorBody(constructor),
+ functionNode: constructor.function, checks: TargetChecks.none);
constructor.function.body.accept(this);
closeFunction();
}
@@ -964,7 +978,11 @@
return;
}
- openFunction(function, functionNode);
+ // TODO(sra): Static methods with no tear-off can be generated with no
+ // checks.
+ // TODO(sra): Instance methods can be generated with reduced checks if
+ // called only from non-dynamic call-sites.
+ openFunction(function, functionNode: functionNode);
// If [functionNode] is `operator==` we explicitly add a null check at the
// beginning of the method. This is to avoid having call sites do the null
@@ -1021,7 +1039,7 @@
/// per-invocation checks and the body, which is later transformed, contains
/// the re-entrant 'state machine' code.
void buildGenerator(FunctionEntity function, ir.FunctionNode functionNode) {
- openFunction(function, functionNode);
+ openFunction(function, functionNode: functionNode);
// Prepare to tail-call the body.
@@ -1085,7 +1103,7 @@
void buildGeneratorBody(
JGeneratorBody function, ir.FunctionNode functionNode) {
FunctionEntity entry = function.function;
- openFunction(entry, functionNode);
+ openFunction(entry, functionNode: functionNode, checks: TargetChecks.none);
graph.needsAsyncRewrite = true;
if (!function.elementType.containsFreeTypeVariables) {
// We can generate the element type in place
@@ -1106,13 +1124,16 @@
return true;
}
- void _potentiallyAddFunctionParameterTypeChecks(ir.FunctionNode function) {
+ void _potentiallyAddFunctionParameterTypeChecks(
+ ir.FunctionNode function, TargetChecks targetChecks) {
// Put the type checks in the first successor of the entry,
// because that is where the type guards will also be inserted.
// This way we ensure that a type guard will dominate the type
// check.
- checkTypeVariableBounds(targetElement);
+ if (targetChecks.checkTypeParameters) {
+ checkTypeVariableBounds(targetElement);
+ }
MemberDefinition definition =
_elementMap.getMemberDefinition(targetElement);
@@ -1128,9 +1149,22 @@
return;
}
HInstruction newParameter = localsHandler.directLocals[local];
+ DartType type = _getDartTypeIfValid(variable.type);
- newParameter = typeBuilder.potentiallyCheckOrTrustTypeOfParameter(
- newParameter, _getDartTypeIfValid(variable.type));
+ if (options.strongMode) {
+ if (targetChecks.checkAllParameters ||
+ (targetChecks.checkCovariantParameters &&
+ (variable.isGenericCovariantImpl || variable.isCovariant))) {
+ newParameter = typeBuilder.potentiallyCheckOrTrustTypeOfParameter(
+ newParameter, type);
+ } else {
+ newParameter = typeBuilder.trustTypeOfParameter(newParameter, type);
+ }
+ } else {
+ newParameter = typeBuilder.potentiallyCheckOrTrustTypeOfParameter(
+ newParameter, type);
+ }
+
localsHandler.directLocals[local] = newParameter;
}
@@ -1167,7 +1201,7 @@
// TODO(johnniwinther): Non-js-interop external functions should
// throw a runtime error.
assert(functionNode.body == null);
- openFunction(function, functionNode);
+ openFunction(function, functionNode: functionNode);
if (closedWorld.nativeData.isNativeMember(targetElement)) {
nativeEmitter.nativeMethods.add(targetElement);
@@ -1247,7 +1281,11 @@
}
}
- void openFunction(MemberEntity member, [ir.FunctionNode functionNode]) {
+ void openFunction(MemberEntity member,
+ {ir.FunctionNode functionNode, TargetChecks checks}) {
+ // TODO(sra): Pass from all sites.
+ checks ??= TargetChecks.dynamicChecks;
+
Map<Local, AbstractValue> parameterMap = <Local, AbstractValue>{};
if (functionNode != null) {
void handleParameter(ir.VariableDeclaration node) {
@@ -1281,7 +1319,7 @@
_addFunctionTypeVariablesIfNeeded(member);
if (functionNode != null) {
- _potentiallyAddFunctionParameterTypeChecks(functionNode);
+ _potentiallyAddFunctionParameterTypeChecks(functionNode, checks);
}
_insertTraceCall(member);
_insertCoverageCall(member);
@@ -2622,7 +2660,7 @@
@override
void visitIntLiteral(ir.IntLiteral node) {
- stack.add(graph.addConstantInt(node.value, closedWorld));
+ stack.add(graph.addConstantIntAsUnsigned(node.value, closedWorld));
}
@override
@@ -3961,14 +3999,14 @@
} else {
instruction = new HInvokeStatic(
target, arguments, typeMask, typeArguments,
- targetCanThrow: !closedWorld.getCannotThrow(target))
+ targetCanThrow: !inferredData.getCannotThrow(target))
..sourceInformation = sourceInformation;
if (currentImplicitInstantiations.isNotEmpty) {
instruction.instantiatedTypes =
new List<InterfaceType>.from(currentImplicitInstantiations);
}
- instruction.sideEffects = closedWorld.getSideEffectsOfElement(target);
+ instruction.sideEffects = inferredData.getSideEffectsOfElement(target);
}
push(instruction);
}
@@ -4361,7 +4399,7 @@
sourceInformation,
isSetter: selector.isSetter || selector.isIndexSet);
instruction.sideEffects =
- closedWorld.getSideEffectsOfSelector(selector, null);
+ inferredData.getSideEffectsOfSelector(selector, null);
push(instruction);
return instruction;
}
diff --git a/pkg/compiler/lib/src/ssa/graph_builder.dart b/pkg/compiler/lib/src/ssa/graph_builder.dart
index e67eeb4..78d0ccd 100644
--- a/pkg/compiler/lib/src/ssa/graph_builder.dart
+++ b/pkg/compiler/lib/src/ssa/graph_builder.dart
@@ -16,10 +16,11 @@
import '../js_backend/backend.dart';
import '../js_backend/backend_usage.dart';
import '../js_backend/constant_handler_javascript.dart';
+import '../js_backend/interceptor_data.dart';
+import '../js_backend/inferred_data.dart';
+import '../js_backend/js_interop_analysis.dart';
import '../js_backend/namer.dart';
import '../js_backend/native_data.dart';
-import '../js_backend/js_interop_analysis.dart';
-import '../js_backend/interceptor_data.dart';
import '../js_backend/runtime_types.dart';
import '../js_emitter/code_emitter_task.dart';
import '../options.dart';
@@ -92,6 +93,8 @@
JsInteropAnalysis get jsInteropAnalysis => backend.jsInteropAnalysis;
+ InferredData get inferredData => compiler.globalInference.inferredData;
+
DeferredLoadTask get deferredLoadTask => compiler.deferredLoadTask;
DartTypes get types => closedWorld.dartTypes;
diff --git a/pkg/compiler/lib/src/ssa/kernel_impact.dart b/pkg/compiler/lib/src/ssa/kernel_impact.dart
index 950aa78..2352143 100644
--- a/pkg/compiler/lib/src/ssa/kernel_impact.dart
+++ b/pkg/compiler/lib/src/ssa/kernel_impact.dart
@@ -235,8 +235,23 @@
@override
void visitIntLiteral(ir.IntLiteral literal) {
- impactBuilder.registerConstantLiteral(
- new IntConstantExpression(new BigInt.from(literal.value)));
+ // Check that this value can be precisely represented as a double, and throw
+ // an error if not:
+ if (new BigInt.from(literal.value) !=
+ new BigInt.from(literal.value.toDouble())) {
+ // TODO(efortuna): Switch to error message.
+ reporter.reportWarningMessage(
+ CURRENT_ELEMENT_SPANNABLE, MessageKind.GENERIC, {
+ 'text': 'The integer literal '
+ '${new BigInt.from(literal.value)} cannot be represented'
+ ' exactly in JavaScript and will be rounded to '
+ '${new BigInt.from(literal.value.toDouble())}. Use the rounded '
+ 'value to avoid this warning.'
+ });
+ }
+
+ impactBuilder.registerConstantLiteral(new IntConstantExpression(
+ new BigInt.from(literal.value).toUnsigned(64)));
}
@override
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 59ac3b2..2258231 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -301,6 +301,12 @@
closedWorld.constantSystem.createIntFromInt(i), closedWorld);
}
+ HConstant addConstantIntAsUnsigned(int i, JClosedWorld closedWorld) {
+ return addConstant(
+ closedWorld.constantSystem.createInt(new BigInt.from(i).toUnsigned(64)),
+ closedWorld);
+ }
+
HConstant addConstantDouble(double d, JClosedWorld closedWorld) {
return addConstant(closedWorld.constantSystem.createDouble(d), closedWorld);
}
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index f8313e8..bc0ea62 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -12,6 +12,7 @@
import '../elements/entities.dart';
import '../elements/types.dart';
import '../js/js.dart' as js;
+import '../js_backend/allocator_analysis.dart' show JAllocatorAnalysis;
import '../js_backend/backend.dart';
import '../js_backend/native_data.dart' show NativeData;
import '../js_backend/runtime_types.dart';
@@ -2586,17 +2587,21 @@
class SsaLoadElimination extends HBaseVisitor implements OptimizationPhase {
final Compiler compiler;
final JClosedWorld closedWorld;
+ final JAllocatorAnalysis _allocatorAnalysis;
final String name = "SsaLoadElimination";
MemorySet memorySet;
List<MemorySet> memories;
bool newGvnCandidates = false;
+ HGraph _graph;
- SsaLoadElimination(this.compiler, this.closedWorld);
+ SsaLoadElimination(this.compiler, this.closedWorld)
+ : _allocatorAnalysis = closedWorld.allocatorAnalysis;
AbstractValueDomain get _abstractValueDomain =>
closedWorld.abstractValueDomain;
void visitGraph(HGraph graph) {
+ _graph = graph;
memories = new List<MemorySet>(graph.blocks.length);
List<HBasicBlock> blocks = graph.blocks;
for (int i = 0; i < blocks.length; i++) {
@@ -2705,8 +2710,15 @@
if (compiler.elementHasCompileTimeError(
// ignore: UNNECESSARY_CAST
member as Entity)) return;
- memorySet.registerFieldValue(
- member, instruction, instruction.inputs[argumentIndex++]);
+ if (_allocatorAnalysis.isInitializedInAllocator(member)) {
+ // TODO(sra): Can we avoid calling HGraph.addConstant?
+ ConstantValue value = _allocatorAnalysis.initializerValue(member);
+ HConstant constant = _graph.addConstant(value, closedWorld);
+ memorySet.registerFieldValue(member, instruction, constant);
+ } else {
+ memorySet.registerFieldValue(
+ member, instruction, instruction.inputs[argumentIndex++]);
+ }
});
}
// In case this instruction has as input non-escaping objects, we
diff --git a/pkg/compiler/lib/src/types/types.dart b/pkg/compiler/lib/src/types/types.dart
index a182ee7..b078b9a 100644
--- a/pkg/compiler/lib/src/types/types.dart
+++ b/pkg/compiler/lib/src/types/types.dart
@@ -8,6 +8,7 @@
import '../common/tasks.dart' show CompilerTask;
import '../compiler.dart' show Compiler;
import '../elements/entities.dart';
+import '../js_backend/inferred_data.dart';
import '../inferrer/type_graph_inferrer.dart' show TypeGraphInferrer;
import '../universe/selector.dart' show Selector;
import '../world.dart' show JClosedWorld;
@@ -253,21 +254,24 @@
GlobalTypeInferenceResults results;
+ InferredData inferredData;
+
GlobalTypeInferenceTask(Compiler compiler)
: compiler = compiler,
super(compiler.measurer);
/// Runs the global type-inference algorithm once.
- void runGlobalTypeInference(
- FunctionEntity mainElement, JClosedWorld closedWorld) {
+ void runGlobalTypeInference(FunctionEntity mainElement,
+ JClosedWorld closedWorld, InferredDataBuilder inferredDataBuilder) {
measure(() {
typesInferrerInternal ??= compiler.backendStrategy.createTypesInferrer(
- closedWorld,
+ closedWorld, inferredDataBuilder,
disableTypeInference: compiler.disableTypeInference);
typesInferrerInternal.analyzeMain(mainElement);
typesInferrerInternal.clear();
results = typesInferrerInternal.createResults();
closedWorld.noSuchMethodData.categorizeComplexImplementations(results);
+ inferredData = inferredDataBuilder.close(closedWorld);
});
}
}
diff --git a/pkg/compiler/lib/src/universe/resolution_world_builder.dart b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
index f90d4a6..726dc05 100644
--- a/pkg/compiler/lib/src/universe/resolution_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
@@ -369,6 +369,7 @@
final InterceptorDataBuilder _interceptorDataBuilder;
final BackendUsageBuilder _backendUsageBuilder;
final RuntimeTypesNeedBuilder _rtiNeedBuilder;
+ final KAllocatorAnalysis _allocatorAnalysis;
final NativeResolutionEnqueuer _nativeResolutionEnqueuer;
final NoSuchMethodRegistry _noSuchMethodRegistry;
@@ -401,6 +402,7 @@
this._interceptorDataBuilder,
this._backendUsageBuilder,
this._rtiNeedBuilder,
+ this._allocatorAnalysis,
this._nativeResolutionEnqueuer,
this._noSuchMethodRegistry,
this.selectorConstraintsStrategy,
@@ -994,6 +996,7 @@
InterceptorDataBuilder interceptorDataBuilder,
BackendUsageBuilder backendUsageBuilder,
RuntimeTypesNeedBuilder rtiNeedBuilder,
+ KAllocatorAnalysis allocatorAnalysis,
NativeResolutionEnqueuer nativeResolutionEnqueuer,
NoSuchMethodRegistry noSuchMethodRegistry,
SelectorConstraintsStrategy selectorConstraintsStrategy,
@@ -1009,6 +1012,7 @@
interceptorDataBuilder,
backendUsageBuilder,
rtiNeedBuilder,
+ allocatorAnalysis,
nativeResolutionEnqueuer,
noSuchMethodRegistry,
selectorConstraintsStrategy,
@@ -1043,6 +1047,7 @@
noSuchMethodData: _noSuchMethodRegistry.close(),
resolutionWorldBuilder: this,
rtiNeedBuilder: _rtiNeedBuilder,
+ allocatorAnalysis: _allocatorAnalysis,
implementedClasses: _implementedClasses,
liveNativeClasses: _nativeResolutionEnqueuer.liveNativeClasses,
liveInstanceMembers: _liveInstanceMembers,
diff --git a/pkg/compiler/lib/src/universe/target_checks.dart b/pkg/compiler/lib/src/universe/target_checks.dart
new file mode 100644
index 0000000..6d4ac79
--- /dev/null
+++ b/pkg/compiler/lib/src/universe/target_checks.dart
@@ -0,0 +1,52 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.target_checks;
+
+/// A summary of the checks required when entering a target method.
+///
+/// The target checks are used to annotate call sites with the checking required
+/// from that call site.
+///
+/// The target can either perform worst-case checks over all call sites, or can
+/// be generated as multiple entry points for different TargetChecks.
+///
+/// The TargetChecks at a call site can be refined by analysis. For example,
+/// the generic covariant check for writing into a List might not be required
+/// when copying values from a List allocated with the same type variable value.
+///
+/// The TargetChecks at a call site can be used to inform optimizations, for
+/// example, only lowering to simpler instructions when generic covariant check
+/// is required.
+///
+/// Unsound modes can be implemented in a scoped manner by using a TargetChecks
+/// that has fewer checks than required (or no checks) in the unsound region.
+class TargetChecks {
+ // Typical of direct static call sites.
+ // Typical of static method targets with no tear-offs.
+ static final TargetChecks none = const TargetChecks._(false, false, false);
+
+ // Typical of closure calls and dynamic calls.
+ static final TargetChecks dynamicChecks =
+ const TargetChecks._(true, true, true);
+
+ // Typical of method calls.
+ static final TargetChecks covariantChecks =
+ const TargetChecks._(false, true, false);
+
+ // TODO(sra): This can be more fine-grained, talking about individual
+ // parameters.
+ final bool _checkOtherParameters;
+ final bool _checkCovariantParameters;
+ final bool _checkTypeParameters;
+ const TargetChecks._(
+ this._checkOtherParameters,
+ this._checkCovariantParameters,
+ this._checkTypeParameters,
+ );
+
+ bool get checkTypeParameters => _checkTypeParameters;
+ bool get checkCovariantParameters => _checkCovariantParameters;
+ bool get checkAllParameters => _checkOtherParameters;
+}
diff --git a/pkg/compiler/lib/src/universe/world_builder.dart b/pkg/compiler/lib/src/universe/world_builder.dart
index 088849b..d43fb15 100644
--- a/pkg/compiler/lib/src/universe/world_builder.dart
+++ b/pkg/compiler/lib/src/universe/world_builder.dart
@@ -12,6 +12,7 @@
import '../constants/values.dart';
import '../elements/entities.dart';
import '../elements/types.dart';
+import '../js_backend/allocator_analysis.dart' show KAllocatorAnalysis;
import '../js_backend/backend_usage.dart' show BackendUsageBuilder;
import '../js_backend/interceptor_data.dart' show InterceptorDataBuilder;
import '../js_backend/native_data.dart' show NativeBasicData, NativeDataBuilder;
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index 4dde4f2..3cc5ee8 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -4,8 +4,6 @@
library dart2js.world;
-import 'dart:collection' show Queue;
-
import 'package:front_end/src/fasta/util/link.dart' show Link;
import 'common.dart';
@@ -14,6 +12,8 @@
import 'constants/constant_system.dart';
import 'elements/entities.dart';
import 'elements/types.dart';
+import 'js_backend/allocator_analysis.dart'
+ show JAllocatorAnalysis, KAllocatorAnalysis;
import 'js_backend/backend_usage.dart' show BackendUsage;
import 'js_backend/interceptor_data.dart' show InterceptorData;
import 'js_backend/native_data.dart' show NativeData;
@@ -26,7 +26,6 @@
import 'universe/class_set.dart';
import 'universe/function_set.dart' show FunctionSet;
import 'universe/selector.dart' show Selector;
-import 'universe/side_effects.dart' show SideEffects, SideEffectsBuilder;
import 'universe/world_builder.dart';
/// Common superinterface for [OpenWorld] and [JClosedWorld].
@@ -42,6 +41,8 @@
/// optimizations and other compiler decisions during code generation.
// TODO(johnniwinther): Maybe this should just be called the JWorld.
abstract class JClosedWorld implements World {
+ JAllocatorAnalysis get allocatorAnalysis;
+
BackendUsage get backendUsage;
NativeData get nativeData;
@@ -318,56 +319,11 @@
/// `null` is returned.
FieldEntity locateSingleField(Selector selector, AbstractValue receiver);
- /// Returns the side effects of executing [element].
- SideEffects getSideEffectsOfElement(FunctionEntity element);
-
- /// Returns the side effects of calling [selector] on the [receiver].
- SideEffects getSideEffectsOfSelector(
- Selector selector, AbstractValue receiver);
-
- /// Returns `true` if [element] is guaranteed not to throw an exception.
- bool getCannotThrow(FunctionEntity element);
-
- /// Returns `true` if [element] is called in a loop.
- // TODO(johnniwinther): Is this 'potentially called' or 'known to be called'?
- // TODO(johnniwinther): Change [MemberEntity] to [FunctionEntity].
- bool isCalledInLoop(MemberEntity element);
-
- /// Returns `true` if [element] might be passed to `Function.apply`.
- // TODO(johnniwinther): Is this 'passed invocation target` or
- // `passed as argument`?
- bool getMightBePassedToApply(FunctionEntity element);
-
/// Returns a string representation of the closed world.
///
/// If [cls] is provided, the dump will contain only classes related to [cls].
String dump([ClassEntity cls]);
- /// Registers the executing of [element] as without side effects.
- void registerSideEffectsFree(FunctionEntity element);
-
- /// Returns the [SideEffectBuilder] associated with [element].
- SideEffectsBuilder getSideEffectsBuilder(FunctionEntity member);
-
- /// Compute [SideEffects] for all registered [SideEffectBuilder]s.
- void computeSideEffects();
-
- /// Registers that [element] might be passed to `Function.apply`.
- // TODO(johnniwinther): Is this 'passed invocation target` or
- // `passed as argument`?
- void registerMightBePassedToApply(FunctionEntity element);
-
- /// Returns `true` if [element] might be passed to `Function.apply` given the
- /// currently inferred information.
- bool getCurrentlyKnownMightBePassedToApply(FunctionEntity element);
-
- /// Registers that [element] is called in a loop.
- // TODO(johnniwinther): Is this 'potentially called' or 'known to be called'?
- void addFunctionCalledInLoop(MemberEntity element);
-
- /// Registers that [element] is guaranteed not to throw an exception.
- void registerCannotThrow(FunctionEntity element);
-
/// Adds the closure class [cls] to the inference world. The class is
/// considered directly instantiated. If [fromInstanceMember] is true, this
/// closure class represents a closure that is inside an instance member, thus
@@ -432,22 +388,6 @@
final Map<ClassEntity, Map<ClassEntity, bool>> _subtypeCoveredByCache =
<ClassEntity, Map<ClassEntity, bool>>{};
- final Set<MemberEntity> _functionsCalledInLoop = new Set<MemberEntity>();
- Map<FunctionEntity, SideEffects> _sideEffects;
- Map<MemberEntity, SideEffectsBuilder> _sideEffectsBuilders =
- <MemberEntity, SideEffectsBuilder>{};
- final Set<FunctionEntity> prematureSideEffectAccesses =
- new Set<FunctionEntity>();
-
- final Set<FunctionEntity> _sideEffectsFreeElements =
- new Set<FunctionEntity>();
-
- final Set<FunctionEntity> _elementsThatCannotThrow =
- new Set<FunctionEntity>();
-
- final Set<FunctionEntity> _functionsThatMightBePassedToApply =
- new Set<FunctionEntity>();
-
final ElementEnvironment elementEnvironment;
final DartTypes dartTypes;
final CommonElements commonElements;
@@ -1053,139 +993,6 @@
return false;
}
- SideEffects getSideEffectsOfSelector(
- Selector selector, AbstractValue receiver) {
- // We're not tracking side effects of closures.
- if (selector.isClosureCall || includesClosureCall(selector, receiver)) {
- return new SideEffects();
- }
- SideEffects sideEffects = new SideEffects.empty();
- _ensureFunctionSet();
- for (MemberEntity e
- in _allFunctions.filter(selector, receiver, abstractValueDomain)) {
- if (e.isField) {
- if (selector.isGetter) {
- if (!fieldNeverChanges(e)) {
- sideEffects.setDependsOnInstancePropertyStore();
- }
- } else if (selector.isSetter) {
- sideEffects.setChangesInstanceProperty();
- } else {
- assert(selector.isCall);
- sideEffects.setAllSideEffects();
- sideEffects.setDependsOnSomething();
- }
- } else {
- sideEffects.add(getSideEffectsOfElement(e));
- }
- }
- return sideEffects;
- }
-
- SideEffects getSideEffectsOfElement(FunctionEntity element) {
- assert(checkEntity(element));
- assert(_sideEffects != null,
- failedAt(element, "Side effects have not been computed yet."));
- // TODO(johnniwinther): Check that [_makeSideEffects] is only called if
- // type inference has been disabled (explicitly or because of compile time
- // errors).
- return _sideEffects.putIfAbsent(element, _makeSideEffects);
- }
-
- static SideEffects _makeSideEffects() => new SideEffects();
-
- @override
- SideEffectsBuilder getSideEffectsBuilder(MemberEntity member) {
- return _sideEffectsBuilders.putIfAbsent(
- member, () => new SideEffectsBuilder(member));
- }
-
- void registerSideEffectsFree(FunctionEntity element) {
- assert(checkEntity(element));
- _sideEffectsFreeElements.add(element);
- assert(!_sideEffectsBuilders.containsKey(element));
- _sideEffectsBuilders[element] = new SideEffectsBuilder.free(element);
- }
-
- void computeSideEffects() {
- assert(
- _sideEffects == null, "Side effects have already been computed yet.");
- _sideEffects = <FunctionEntity, SideEffects>{};
- Iterable<SideEffectsBuilder> sideEffectsBuilders =
- _sideEffectsBuilders.values;
- emptyWorkList(sideEffectsBuilders);
- for (SideEffectsBuilder sideEffectsBuilder in sideEffectsBuilders) {
- _sideEffects[sideEffectsBuilder.member] = sideEffectsBuilder.sideEffects;
- }
- _sideEffectsBuilders = null;
- }
-
- static void emptyWorkList(Iterable<SideEffectsBuilder> sideEffectsBuilders) {
- // TODO(johnniwinther): Optimize this algorithm, possibly by using
- // `pkg/front_end/lib/src/dependency_walker.dart`.
- Queue<SideEffectsBuilder> queue = new Queue<SideEffectsBuilder>();
- Set<SideEffectsBuilder> inQueue = new Set<SideEffectsBuilder>();
-
- for (SideEffectsBuilder builder in sideEffectsBuilders) {
- queue.addLast(builder);
- inQueue.add(builder);
- }
- while (queue.isNotEmpty) {
- SideEffectsBuilder sideEffectsBuilder = queue.removeFirst();
- inQueue.remove(sideEffectsBuilder);
- for (SideEffectsBuilder dependent in sideEffectsBuilder.depending) {
- if (dependent.add(sideEffectsBuilder.sideEffects)) {
- if (inQueue.add(dependent)) {
- queue.addLast(dependent);
- }
- }
- }
- }
- }
-
- void addFunctionCalledInLoop(MemberEntity element) {
- assert(checkEntity(element));
- _functionsCalledInLoop.add(element);
- }
-
- bool isCalledInLoop(MemberEntity element) {
- assert(checkEntity(element));
- return _functionsCalledInLoop.contains(element);
- }
-
- void registerCannotThrow(FunctionEntity element) {
- assert(checkEntity(element));
- _elementsThatCannotThrow.add(element);
- }
-
- bool getCannotThrow(FunctionEntity element) {
- return _elementsThatCannotThrow.contains(element);
- }
-
- void registerMightBePassedToApply(FunctionEntity element) {
- _functionsThatMightBePassedToApply.add(element);
- }
-
- bool getMightBePassedToApply(FunctionEntity element) {
- // We assume all functions reach Function.apply if no functions are
- // registered so. We get an empty set in two circumstances (1) a trivial
- // program and (2) when compiling without type inference
- // (i.e. --disable-type-inference). Returning `true` has consequences (extra
- // metadata for Function.apply) only when Function.apply is also part of the
- // program. It is an unusual trivial program that includes Function.apply
- // but does not call it on a function.
- //
- // TODO(sra): We should reverse the sense of this set and register functions
- // that we have proven do not reach Function.apply.
- if (_functionsThatMightBePassedToApply.isEmpty) return true;
- return _functionsThatMightBePassedToApply.contains(element);
- }
-
- @override
- bool getCurrentlyKnownMightBePassedToApply(FunctionEntity element) {
- return _functionsThatMightBePassedToApply.contains(element);
- }
-
@override
String dump([ClassEntity cls]) {
StringBuffer sb = new StringBuffer();
@@ -1224,6 +1031,7 @@
abstract class KClosedWorld {
DartTypes get dartTypes;
+ KAllocatorAnalysis get allocatorAnalysis;
BackendUsage get backendUsage;
NativeData get nativeData;
InterceptorData get interceptorData;
diff --git a/pkg/dev_compiler/bin/dartdevk.dart b/pkg/dev_compiler/bin/dartdevk.dart
index 0d01d78..98f3907 100755
--- a/pkg/dev_compiler/bin/dartdevk.dart
+++ b/pkg/dev_compiler/bin/dartdevk.dart
@@ -21,8 +21,7 @@
await new _CompilerWorker(parsedArgs.args).run();
} else {
var result = await compile(parsedArgs.args);
- var succeeded = result.result;
- exitCode = succeeded ? 0 : 1;
+ exitCode = result.success ? 0 : 1;
}
}
@@ -45,8 +44,7 @@
try {
var result = await compile(args, compilerState: compilerState);
compilerState = result.compilerState;
- var succeeded = result.result;
- outcome = succeeded ? 'PASS' : 'FAIL';
+ outcome = result.success ? 'PASS' : 'FAIL';
} catch (e, s) {
outcome = 'CRASH';
print('Unhandled exception:');
@@ -82,7 +80,7 @@
output.writeln(message.toString());
}));
return new WorkResponse()
- ..exitCode = result.result ? 0 : 1
+ ..exitCode = result.success ? 0 : 1
..output = output.toString();
}
}
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index c53371c..707576a 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -49,7 +49,7 @@
import 'extension_types.dart' show ExtensionTypeSet;
import 'js_interop.dart';
import 'js_typeref_codegen.dart' show JSTypeRefCodegen;
-import 'js_typerep.dart' show JSTypeRep, JSType;
+import 'js_typerep.dart';
import 'module_compiler.dart' show BuildUnit, CompilerOptions, JSModuleFile;
import 'nullable_type_inference.dart' show NullableTypeInference;
import 'property_model.dart';
@@ -84,7 +84,7 @@
final CompilerOptions options;
final StrongTypeSystemImpl rules;
- JSTypeRep _typeRep;
+ JSTypeRep jsTypeRep;
/// The set of libraries we are currently compiling, and the temporaries used
/// to refer to them.
@@ -136,12 +136,8 @@
/// The dart:core `identical` element.
final FunctionElement _coreIdentical;
- /// The dart:_interceptors implementation elements.
+ /// Classes and types defined in the SDK.
final ClassElement _jsArray;
- final ClassElement _jsBool;
- final ClassElement _jsNumber;
- final ClassElement _jsString;
-
final ClassElement boolClass;
final ClassElement intClass;
final ClassElement doubleClass;
@@ -213,40 +209,32 @@
: context = c,
rules = new StrongTypeSystemImpl(c.typeProvider),
types = c.typeProvider,
- _asyncStreamIterator =
- _getLibrary(c, 'dart:async').getType('StreamIterator').type,
+ _asyncStreamIterator = getClass(c, 'dart:async', 'StreamIterator').type,
_coreIdentical = _getLibrary(c, 'dart:core')
.publicNamespace
.get('identical') as FunctionElement,
- _jsArray = _getLibrary(c, 'dart:_interceptors').getType('JSArray'),
- _jsBool = _getLibrary(c, 'dart:_interceptors').getType('JSBool'),
- _jsString = _getLibrary(c, 'dart:_interceptors').getType('JSString'),
- _jsNumber = _getLibrary(c, 'dart:_interceptors').getType('JSNumber'),
- interceptorClass =
- _getLibrary(c, 'dart:_interceptors').getType('Interceptor'),
+ _jsArray = getClass(c, 'dart:_interceptors', 'JSArray'),
+ interceptorClass = getClass(c, 'dart:_interceptors', 'Interceptor'),
coreLibrary = _getLibrary(c, 'dart:core'),
- boolClass = _getLibrary(c, 'dart:core').getType('bool'),
- intClass = _getLibrary(c, 'dart:core').getType('int'),
- doubleClass = _getLibrary(c, 'dart:core').getType('double'),
- numClass = _getLibrary(c, 'dart:core').getType('num'),
- nullClass = _getLibrary(c, 'dart:core').getType('Null'),
- objectClass = _getLibrary(c, 'dart:core').getType('Object'),
- stringClass = _getLibrary(c, 'dart:core').getType('String'),
- functionClass = _getLibrary(c, 'dart:core').getType('Function'),
- privateSymbolClass =
- _getLibrary(c, 'dart:_js_helper').getType('PrivateSymbol'),
+ boolClass = getClass(c, 'dart:core', 'bool'),
+ intClass = getClass(c, 'dart:core', 'int'),
+ doubleClass = getClass(c, 'dart:core', 'double'),
+ numClass = getClass(c, 'dart:core', 'num'),
+ nullClass = getClass(c, 'dart:core', 'Null'),
+ objectClass = getClass(c, 'dart:core', 'Object'),
+ stringClass = getClass(c, 'dart:core', 'String'),
+ functionClass = getClass(c, 'dart:core', 'Function'),
+ privateSymbolClass = getClass(c, 'dart:_js_helper', 'PrivateSymbol'),
linkedHashMapImplType =
- _getLibrary(c, 'dart:_js_helper').getType('LinkedMap').type,
+ getClass(c, 'dart:_js_helper', 'LinkedMap').type,
identityHashMapImplType =
- _getLibrary(c, 'dart:_js_helper').getType('IdentityMap').type,
- linkedHashSetImplType =
- _getLibrary(c, 'dart:collection').getType('_HashSet').type,
+ getClass(c, 'dart:_js_helper', 'IdentityMap').type,
+ linkedHashSetImplType = getClass(c, 'dart:collection', '_HashSet').type,
identityHashSetImplType =
- _getLibrary(c, 'dart:collection').getType('_IdentityHashSet').type,
- syncIterableType =
- _getLibrary(c, 'dart:_js_helper').getType('SyncIterable').type,
+ getClass(c, 'dart:collection', '_IdentityHashSet').type,
+ syncIterableType = getClass(c, 'dart:_js_helper', 'SyncIterable').type,
dartJSLibrary = _getLibrary(c, 'dart:js') {
- _typeRep = new JSTypeRep(rules, types);
+ jsTypeRep = new JSTypeRep(rules, c);
}
LibraryElement get currentLibrary => _currentElement.library;
@@ -782,7 +770,7 @@
}
// All Dart number types map to a JS double.
- if (_typeRep.isNumber(from) && _typeRep.isNumber(to)) {
+ if (jsTypeRep.isNumber(from) && jsTypeRep.isNumber(to)) {
// Make sure to check when converting to int.
if (from != types.intType && to == types.intType) {
// TODO(jmesserly): fuse this with notNull check.
@@ -805,7 +793,7 @@
JS.Expression result;
var type = node.type.type;
var lhs = _visitExpression(node.expression);
- var typeofName = _jsTypeofName(type);
+ var typeofName = jsTypeRep.typeFor(type).primitiveTypeOf;
// Inline primitives other than int (which requires a Math.floor check).
if (typeofName != null && type != types.intType) {
result = js.call('typeof # == #', [lhs, js.string(typeofName, "'")]);
@@ -821,13 +809,6 @@
return result;
}
- String _jsTypeofName(DartType t) {
- if (_typeRep.isNumber(t)) return 'number';
- if (t == types.stringType) return 'string';
- if (t == types.boolType) return 'boolean';
- return null;
- }
-
@override
visitFunctionTypeAlias(FunctionTypeAlias node) => _emitTypedef(node);
@@ -1673,7 +1654,7 @@
// Pass along all arguments verbatim, and let the callee handle them.
// TODO(jmesserly): we'll need something different once we have
// rest/spread support, but this should work for now.
- var params = _emitFormalParameters(node.parameters?.parameters);
+ var params = _emitParameters(node.parameters?.parameters);
fun = new JS.Fun(
params,
@@ -1690,7 +1671,7 @@
if (init != null) body.add(init);
body.add(_visitStatement(node.body));
- var params = _emitFormalParameters(node.parameters?.parameters);
+ var params = _emitParameters(node.parameters?.parameters);
fun = new JS.Fun(params, new JS.Block(body), returnType: returnType);
}
@@ -1909,7 +1890,7 @@
void _registerExtensionType(
ClassElement classElem, String jsPeerName, List<JS.Statement> body) {
var className = _emitTopLevelName(classElem);
- if (isPrimitiveType(classElem.type)) {
+ if (jsTypeRep.isPrimitive(classElem.type)) {
body.add(
runtimeStatement('definePrimitiveHashCode(#.prototype)', className));
}
@@ -2291,7 +2272,7 @@
JS.Expression _emitConstructor(ConstructorDeclaration node,
List<VariableDeclaration> fields, JS.Expression className) {
- var params = _emitFormalParameters(node.parameters?.parameters);
+ var params = _emitParameters(node.parameters?.parameters);
var savedFunction = _currentFunction;
_currentFunction = node.body;
@@ -2603,7 +2584,7 @@
if (node.isGetter) {
return new JS.Fun([], js.block('{ return this.#; }', [name]));
} else if (node.isSetter) {
- var params = _emitFormalParameters(node.parameters?.parameters);
+ var params = _emitParameters(node.parameters?.parameters);
return new JS.Fun(
params, js.block('{ this.# = #; }', [name, params.last]));
} else {
@@ -2807,7 +2788,7 @@
// normal function (sync), vs (sync*, async, async*)
var isSync = !(element.isAsynchronous || element.isGenerator);
- var formals = _emitFormalParameters(parameters?.parameters);
+ var formals = _emitParameters(parameters?.parameters);
var typeFormals = _emitTypeFormals(type.typeFormals);
if (_reifyGeneric(element)) formals.insertAll(0, typeFormals);
@@ -2936,7 +2917,7 @@
var params = parameters?.parameters;
- var jsParams = _emitFormalParameters(
+ var jsParams = _emitParameters(
params?.where((p) => isPotentiallyMutated(body, p.element)));
var gen = emitGeneratorFn(jsParams);
@@ -3847,7 +3828,7 @@
if (_isNull(left) || _isNull(right)) return true;
// If the representation of the two types will not induce conversion in
// JS then we can use == .
- return !_typeRep.equalityMayConvert(left.staticType, right.staticType);
+ return !jsTypeRep.equalityMayConvert(left.staticType, right.staticType);
}
bool _tripleEqIsIdentity(Expression left, Expression right) {
@@ -4111,8 +4092,7 @@
return jsParams;
}
- List<JS.Parameter> _emitFormalParameters(
- Iterable<FormalParameter> parameters) {
+ List<JS.Parameter> _emitParameters(Iterable<FormalParameter> parameters) {
if (parameters == null) return [];
var result = <JS.Parameter>[];
@@ -4579,21 +4559,6 @@
ctorNode: constructor);
}
- bool isPrimitiveType(DartType t) => _typeRep.isPrimitive(t);
-
- /// Given a Dart type return the known implementation type, if any.
- /// Given `bool`, `String`, or `num`/`int`/`double`,
- /// returns the corresponding type in `dart:_interceptors`:
- /// `JSBool`, `JSString`, and `JSNumber` respectively, otherwise null.
- InterfaceType getImplementationType(DartType t) {
- JSType rep = _typeRep.typeFor(t);
- // Number, String, and Bool are final
- if (rep == JSType.jsNumber) return _jsNumber.type;
- if (rep == JSType.jsBoolean) return _jsBool.type;
- if (rep == JSType.jsString) return _jsString.type;
- return null;
- }
-
JS.Statement _nullParameterCheck(JS.Expression param) {
var call = runtimeCall('argumentError((#))', [param]);
return js.statement('if (# == null) #;', [param, call]);
@@ -4633,7 +4598,7 @@
// if `operator ==` was overridden, similar to how we devirtualize private
// fields.
var isEnum = leftType is InterfaceType && leftType.element.isEnum;
- var usesIdentity = _typeRep.isPrimitive(leftType) ||
+ var usesIdentity = jsTypeRep.isPrimitive(leftType) ||
isEnum ||
_isNull(left) ||
_isNull(right);
@@ -4699,7 +4664,7 @@
..sourceInformation = _getLocation(node.operator.offset);
}
- if (_typeRep.binaryOperationIsPrimitive(leftType, rightType) ||
+ if (jsTypeRep.binaryOperationIsPrimitive(leftType, rightType) ||
leftType == types.stringType && op.type == TokenType.PLUS) {
// special cases where we inline the operation
// these values are assumed to be non-null (determined by the checker)
@@ -5087,7 +5052,7 @@
var expr = node.operand;
var dispatchType = getStaticType(expr);
- if (_typeRep.unaryOperationIsPrimitive(dispatchType)) {
+ if (jsTypeRep.unaryOperationIsPrimitive(dispatchType)) {
if (!isNullable(expr)) {
return js.call('#$op', _visitExpression(expr));
}
@@ -5124,9 +5089,9 @@
var expr = node.operand;
var dispatchType = getStaticType(expr);
- if (_typeRep.unaryOperationIsPrimitive(dispatchType)) {
+ if (jsTypeRep.unaryOperationIsPrimitive(dispatchType)) {
if (op.lexeme == '~') {
- if (_typeRep.isNumber(dispatchType)) {
+ if (jsTypeRep.isNumber(dispatchType)) {
JS.Expression jsExpr = js.call('~#', notNull(expr));
return _coerceBitOperationResultToUnsigned(node, jsExpr);
}
@@ -5793,7 +5758,7 @@
JS.Expression _emitMapImplType(InterfaceType type, {bool identity}) {
var typeArgs = type.typeArguments;
if (typeArgs.isEmpty) return _emitType(type);
- identity ??= isPrimitiveType(typeArgs[0]);
+ identity ??= jsTypeRep.isPrimitive(typeArgs[0]);
type = identity ? identityHashMapImplType : linkedHashMapImplType;
return _emitType(type.instantiate(typeArgs));
}
@@ -5801,7 +5766,7 @@
JS.Expression _emitSetImplType(InterfaceType type, {bool identity}) {
var typeArgs = type.typeArguments;
if (typeArgs.isEmpty) return _emitType(type);
- identity ??= isPrimitiveType(typeArgs[0]);
+ identity ??= jsTypeRep.isPrimitive(typeArgs[0]);
type = identity ? identityHashSetImplType : linkedHashSetImplType;
return _emitType(type.instantiate(typeArgs));
}
@@ -5819,27 +5784,21 @@
@override
JS.Expression visitStringInterpolation(StringInterpolation node) {
- var strings = <String>[];
- var interpolations = <JS.Expression>[];
-
- var expectString = true;
- for (var e in node.elements) {
- if (e is InterpolationString) {
- assert(expectString);
- expectString = false;
-
- // Escape the string as necessary for use in the eventual `` quotes.
- // TODO(jmesserly): this call adds quotes, and then we strip them off.
- var str = js.escapedString(e.value, '`').value;
- strings.add(str.substring(1, str.length - 1));
+ var parts = <JS.Expression>[];
+ for (var elem in node.elements) {
+ if (elem is InterpolationString) {
+ if (elem.value.isEmpty) continue;
+ parts.add(js.escapedString(elem.value, '"'));
} else {
- assert(!expectString);
- expectString = true;
- interpolations.add(_visitExpression(e));
+ var e = (elem as InterpolationExpression).expression;
+ var jsExpr = _visitExpression(e);
+ parts.add(e.staticType == types.stringType && !isNullable(e)
+ ? jsExpr
+ : runtimeCall('str(#)', jsExpr));
}
}
- return new JS.TaggedTemplate(
- runtimeCall('str'), new JS.TemplateString(strings, interpolations));
+ if (parts.isEmpty) return js.string('');
+ return new JS.Expression.binary(parts, '+');
}
@override
@@ -6172,7 +6131,7 @@
if (type == null || type.isDynamic || type.isObject) {
return isObjectMember(name);
} else if (type is InterfaceType) {
- var interfaceType = getImplementationType(type) ?? type;
+ var interfaceType = jsTypeRep.getImplementationType(type) ?? type;
var element = interfaceType.element;
if (_extensionTypes.isNativeClass(element)) {
var member = _lookupForwardedMember(element, name);
@@ -6355,7 +6314,7 @@
@override
visitExtendsClause(node) => _unreachable(node);
- /// Unused, see [_emitFormalParameters].
+ /// Unused, see [_emitParameters].
@override
visitFormalParameterList(node) => _unreachable(node);
diff --git a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
index 928e5e4..8ecdd13 100644
--- a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:collection';
+import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
/// Helpers for Analyzer's Element model and corelib model.
@@ -45,6 +46,7 @@
/// (v) => v.type.name == 'Deprecated' && v.type.element.library.isDartCore
///
DartObject findAnnotation(Element element, bool test(DartObjectImpl value)) {
+ if (element == null) return null;
for (var metadata in element.metadata) {
var value = metadata.computeConstantValue();
if (value is DartObjectImpl && test(value)) return value;
@@ -339,3 +341,6 @@
var path = uri.pathSegments[0];
return uri.scheme == 'dart' && path == libraryName;
}
+
+ClassElement getClass(AnalysisContext c, String uri, String name) =>
+ c.computeLibraryElement(c.sourceFactory.forUri(uri)).getType(name);
diff --git a/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart b/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart
index 2d73cb0..ba24ee2 100644
--- a/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart
@@ -3,95 +3,29 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/dart/element/element.dart' show ClassElement;
+import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
import 'package:analyzer/src/generated/type_system.dart'
show StrongTypeSystemImpl;
+import '../compiler/js_typerep.dart';
+import 'element_helpers.dart' show getClass;
-/// An abstraction of the JS types
-abstract class JSType {
- const JSType();
-
- /// True if this type is built-in to JS, and we use the values unwrapped.
- /// For these types we generate a calling convention via static
- /// "extension methods". This allows types to be extended without adding
- /// extensions directly on the prototype.
- bool get isPrimitive;
-
- /// Is this type known to be definitively primitive
- /// (using the JS notion of primitive)
- bool get isPrimitiveInJS;
-
- /// Can a non-null element of this type potentially be interpreted
- /// as false in JS.
- bool get isFalsey;
-
- static const jsBoolean = const JSBoolean();
- static const jsNumber = const JSNumber();
- static const jsNull = const JSNull();
- static const jsObject = const JSObject();
- static const jsString = const JSString();
- static const jsUnknown = const JSUnknown();
-}
-
-/// Inhabited by booleans (including JSBool), null, and undefined
-class JSBoolean extends JSType {
- const JSBoolean();
- bool get isPrimitive => true;
- bool get isPrimitiveInJS => true;
- bool get isFalsey => true;
-}
-
-/// Inhabited by numbers, null, and undefined
-/// In practice, this is 4 types: num, int, double, and _interceptors.JSNumber.
-///
-/// _interceptors.JSNumber is the type that actually "implements" all numbers,
-/// hence it's a subtype of int and double (and num).
-/// It's defined in our "dart:_interceptors".
-class JSNumber extends JSType {
- const JSNumber();
- bool get isPrimitive => true;
- bool get isPrimitiveInJS => true;
- bool get isFalsey => true;
-}
-
-/// Inhabited by null and undefined
-class JSNull extends JSType {
- const JSNull();
- bool get isPrimitive => false;
- bool get isPrimitiveInJS => false;
- bool get isFalsey => true;
-}
-
-/// Inhabited by objects, null, and undefined
-class JSObject extends JSType {
- const JSObject();
- bool get isPrimitive => false;
- bool get isPrimitiveInJS => false;
- bool get isFalsey => false;
-}
-
-/// Inhabited by strings (including JSString), null, and undefined
-class JSString extends JSType {
- const JSString();
- bool get isPrimitive => true;
- bool get isPrimitiveInJS => false;
- bool get isFalsey => true;
-}
-
-/// Inhabitance not statically known
-class JSUnknown extends JSType {
- const JSUnknown();
- bool get isPrimitive => false;
- bool get isPrimitiveInJS => false;
- bool get isFalsey => true;
-}
-
-class JSTypeRep {
+class JSTypeRep extends SharedJSTypeRep<DartType> {
final StrongTypeSystemImpl rules;
final TypeProvider types;
- JSTypeRep(this.rules, this.types);
+ final ClassElement _jsBool;
+ final ClassElement _jsNumber;
+ final ClassElement _jsString;
+ JSTypeRep(this.rules, AnalysisContext c)
+ : types = c.typeProvider,
+ _jsBool = getClass(c, 'dart:_interceptors', 'JSBool'),
+ _jsString = getClass(c, 'dart:_interceptors', 'JSString'),
+ _jsNumber = getClass(c, 'dart:_interceptors', 'JSNumber');
+
+ @override
JSType typeFor(DartType type) {
while (type is TypeParameterType) {
type = (type as TypeParameterType).element.bound;
@@ -115,40 +49,16 @@
return JSType.jsObject;
}
- /// If the type [t] is [int] or [double], or a type parameter
- /// bounded by [int], [double] or [num] returns [num].
- /// Otherwise returns [t].
- DartType canonicalizeNumTypes(DartType t) => isNumber(t) ? types.numType : t;
-
- bool isNumber(DartType type) => typeFor(type) is JSNumber;
-
- /// Is this type known to be represented as Object or Null in JS.
- bool isObjectOrNull(DartType t) {
+ /// Given a Dart type return the known implementation type, if any.
+ /// Given `bool`, `String`, or `num`/`int`/`double`,
+ /// returns the corresponding type in `dart:_interceptors`:
+ /// `JSBool`, `JSString`, and `JSNumber` respectively, otherwise null.
+ InterfaceType getImplementationType(DartType t) {
var rep = typeFor(t);
- return rep is JSObject || rep is JSNull;
- }
-
- bool isUnknown(DartType t) => typeFor(t) is JSUnknown;
-
- bool isPrimitive(DartType t) => typeFor(t).isPrimitive;
-
- bool isPrimitiveInJS(DartType t) => typeFor(t).isPrimitiveInJS;
-
- bool binaryOperationIsPrimitive(DartType leftT, DartType rightT) =>
- isPrimitiveInJS(leftT) && isPrimitiveInJS(rightT);
-
- bool unaryOperationIsPrimitive(DartType t) => isPrimitiveInJS(t);
-
- /// True if the JS double equals (`==`) comparison on the representation
- /// of these two types could potentially cause a conversion.
- bool equalityMayConvert(DartType t0, DartType t1) => !equalOrNull(t0, t1);
-
- // Are t0 and t1 known to either be represented by the same type
- // or else one or both of them is represented by Null
- bool equalOrNull(DartType t0, DartType t1) {
- var rep0 = typeFor(t0);
- var rep1 = typeFor(t1);
- if (rep0 is JSNull || rep1 is JSNull) return true;
- return rep0 == rep1 && rep0 is! JSUnknown;
+ // Number, String, and Bool are final
+ if (rep == JSType.jsNumber) return _jsNumber.type;
+ if (rep == JSType.jsBoolean) return _jsBool.type;
+ if (rep == JSType.jsString) return _jsString.type;
+ return null;
}
}
diff --git a/pkg/dev_compiler/lib/src/analyzer/nullable_type_inference.dart b/pkg/dev_compiler/lib/src/analyzer/nullable_type_inference.dart
index 5006b76..6ef6e1f 100644
--- a/pkg/dev_compiler/lib/src/analyzer/nullable_type_inference.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/nullable_type_inference.dart
@@ -11,6 +11,7 @@
import 'package:analyzer/dart/element/type.dart';
import 'element_helpers.dart' show getStaticType, isInlineJS, findAnnotation;
import 'js_interop.dart' show isNotNullAnnotation, isNullCheckAnnotation;
+import 'js_typerep.dart';
import 'property_model.dart';
/// An inference engine for nullable types.
@@ -27,8 +28,7 @@
LibraryElement get coreLibrary;
VirtualFieldModel get virtualFields;
- InterfaceType getImplementationType(DartType type);
- bool isPrimitiveType(DartType type);
+ JSTypeRep get jsTypeRep;
bool isObjectMember(String name);
/// Known non-null local variables.
@@ -85,7 +85,7 @@
Element container = e.enclosingElement;
if (container is ClassElement) {
DartType targetType = container.type;
- InterfaceType implType = getImplementationType(targetType);
+ InterfaceType implType = jsTypeRep.getImplementationType(targetType);
if (implType != null) {
MethodElement method = implType.lookUpMethod(e.name, coreLibrary);
if (method != null) e = method;
@@ -109,7 +109,7 @@
Element container = element.enclosingElement;
if (container is ClassElement) {
var targetType = container.type;
- var implType = getImplementationType(targetType);
+ var implType = jsTypeRep.getImplementationType(targetType);
if (implType != null) {
var getter = implType.lookUpGetter(name, coreLibrary);
if (getter != null) element = getter;
@@ -237,36 +237,51 @@
return true;
}
-
- DartType type = null;
- if (expr is BinaryExpression) {
- switch (expr.operator.type) {
- case TokenType.EQ_EQ:
- case TokenType.BANG_EQ:
- case TokenType.AMPERSAND_AMPERSAND:
- case TokenType.BAR_BAR:
- return false;
- case TokenType.QUESTION_QUESTION:
- return _isNullable(expr.leftOperand, localIsNullable) &&
- _isNullable(expr.rightOperand, localIsNullable);
- }
- type = getStaticType(expr.leftOperand);
- } else if (expr is PrefixExpression) {
- if (expr.operator.type == TokenType.BANG) return false;
- type = getStaticType(expr.operand);
- } else if (expr is PostfixExpression) {
- type = getStaticType(expr.operand);
- }
- if (type != null && isPrimitiveType(type)) {
- return false;
- }
if (expr is MethodInvocation &&
- (expr.operator?.type != TokenType.QUESTION_PERIOD ||
+ (expr.operator?.lexeme != '?.' ||
!_isNullable(expr.target, localIsNullable)) &&
_isNonNullMethodInvocation(expr)) {
return false;
}
+ Expression operand, rightOperand;
+ String op;
+ if (expr is AssignmentExpression) {
+ op = expr.operator.lexeme;
+ assert(op.endsWith('='));
+ if (op == '=') {
+ return _isNullable(expr.rightHandSide, localIsNullable);
+ }
+ // op assignment like +=, remove trailing '='
+ op = op.substring(0, op.length - 1);
+ operand = expr.leftHandSide;
+ rightOperand = expr.rightHandSide;
+ } else if (expr is BinaryExpression) {
+ operand = expr.leftOperand;
+ rightOperand = expr.rightOperand;
+ op = expr.operator.lexeme;
+ } else if (expr is PrefixExpression) {
+ operand = expr.operand;
+ op = expr.operator.lexeme;
+ } else if (expr is PostfixExpression) {
+ operand = expr.operand;
+ op = expr.operator.lexeme;
+ }
+ switch (op) {
+ case '==':
+ case '!=':
+ case '&&':
+ case '||':
+ case '!':
+ return false;
+ case '??':
+ return _isNullable(operand, localIsNullable) &&
+ _isNullable(rightOperand, localIsNullable);
+ }
+ if (operand != null && jsTypeRep.isPrimitive(getStaticType(operand))) {
+ return false;
+ }
+
// TODO(ochafik,jmesserly): handle other cases such as: refs to top-level
// finals that have been assigned non-nullable values.
@@ -370,17 +385,12 @@
@override
visitAssignmentExpression(AssignmentExpression node) {
- _visitAssignment(node.leftHandSide, node.rightHandSide);
- super.visitAssignmentExpression(node);
- }
-
- @override
- visitBinaryExpression(BinaryExpression node) {
- var op = node.operator.type;
- if (op.isAssignmentOperator) {
- _visitAssignment(node.leftOperand, node);
+ if (node.operator.lexeme == '=') {
+ _visitAssignment(node.leftHandSide, node.rightHandSide);
+ } else {
+ _visitAssignment(node.leftHandSide, node);
}
- super.visitBinaryExpression(node);
+ super.visitAssignmentExpression(node);
}
@override
diff --git a/pkg/dev_compiler/lib/src/compiler/js_typerep.dart b/pkg/dev_compiler/lib/src/compiler/js_typerep.dart
new file mode 100644
index 0000000..56a0545
--- /dev/null
+++ b/pkg/dev_compiler/lib/src/compiler/js_typerep.dart
@@ -0,0 +1,121 @@
+/// An abstraction of the JS types
+abstract class JSType {
+ const JSType();
+
+ /// True if this type is built-in to JS, and we use the values unwrapped.
+ /// For these types we generate a calling convention via static
+ /// "extension methods". This allows types to be extended without adding
+ /// extensions directly on the prototype.
+ bool get isPrimitive;
+
+ /// Is this type known to be definitively primitive
+ /// (using the JS notion of primitive)
+ bool get isPrimitiveInJS;
+
+ /// Can a non-null element of this type potentially be interpreted
+ /// as false in JS.
+ bool get isFalsey;
+
+ /// The JS `typeof` value, if unambiguous.
+ String get primitiveTypeOf => null;
+
+ static const jsBoolean = const JSBoolean();
+ static const jsNumber = const JSNumber();
+ static const jsNull = const JSNull();
+ static const jsObject = const JSObject();
+ static const jsString = const JSString();
+ static const jsUnknown = const JSUnknown();
+ // TODO(jmesserly): add JSFunction that maps to Dart's `Function` type.
+}
+
+/// Inhabited by booleans (including JSBool), null, and undefined
+class JSBoolean extends JSType {
+ const JSBoolean();
+ bool get isPrimitive => true;
+ bool get isPrimitiveInJS => true;
+ bool get isFalsey => true;
+ String get primitiveTypeOf => 'boolean';
+}
+
+/// Inhabited by numbers, null, and undefined
+/// In practice, this is 4 types: num, int, double, and _interceptors.JSNumber.
+///
+/// _interceptors.JSNumber is the type that actually "implements" all numbers,
+/// hence it's a subtype of int and double (and num).
+/// It's defined in our "dart:_interceptors".
+class JSNumber extends JSType {
+ const JSNumber();
+ bool get isPrimitive => true;
+ bool get isPrimitiveInJS => true;
+ bool get isFalsey => true;
+ String get primitiveTypeOf => 'number';
+}
+
+/// Inhabited by null and undefined
+class JSNull extends JSType {
+ const JSNull();
+ bool get isPrimitive => false;
+ bool get isPrimitiveInJS => false;
+ bool get isFalsey => true;
+}
+
+/// Inhabited by objects, null, and undefined
+class JSObject extends JSType {
+ const JSObject();
+ bool get isPrimitive => false;
+ bool get isPrimitiveInJS => false;
+ bool get isFalsey => false;
+}
+
+/// Inhabited by strings (including JSString), null, and undefined
+class JSString extends JSType {
+ const JSString();
+ bool get isPrimitive => true;
+ bool get isPrimitiveInJS => false;
+ bool get isFalsey => true;
+ String get primitiveTypeOf => 'string';
+}
+
+/// Inhabitance not statically known
+class JSUnknown extends JSType {
+ const JSUnknown();
+ bool get isPrimitive => false;
+ bool get isPrimitiveInJS => false;
+ bool get isFalsey => true;
+}
+
+abstract class SharedJSTypeRep<DartType> {
+ JSType typeFor(DartType type);
+
+ bool isNumber(DartType type) => typeFor(type) is JSNumber;
+
+ /// Is this type known to be represented as Object or Null in JS.
+ bool isObjectOrNull(DartType t) {
+ var rep = typeFor(t);
+ return rep is JSObject || rep is JSNull;
+ }
+
+ bool isUnknown(DartType t) => typeFor(t) is JSUnknown;
+
+ bool isPrimitive(DartType t) => typeFor(t).isPrimitive;
+
+ bool isPrimitiveInJS(DartType t) => typeFor(t).isPrimitiveInJS;
+
+ bool binaryOperationIsPrimitive(DartType leftT, DartType rightT) =>
+ isPrimitiveInJS(leftT) && isPrimitiveInJS(rightT);
+
+ bool unaryOperationIsPrimitive(DartType t) => isPrimitiveInJS(t);
+
+ /// True if the JS double equals (`==`) comparison on the representation
+ /// of these two types could potentially cause a conversion.
+ bool equalityMayConvert(DartType t0, DartType t1) => !equalOrNull(t0, t1);
+
+ // Are t0 and t1 known to either be represented by the same type
+ // or else one or both of them is represented by Null
+ bool equalOrNull(DartType t0, DartType t1) {
+ var rep0 = typeFor(t0);
+ var rep1 = typeFor(t1);
+ if (rep0 is JSNull || rep1 is JSNull) return true;
+ return rep0 == rep1 && rep0 is! JSUnknown;
+ }
+}
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index f8a4624..cd9aaf9 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -11,8 +11,10 @@
import 'package:front_end/src/api_prototype/standard_file_system.dart';
import 'package:front_end/src/api_unstable/ddc.dart' as fe;
import 'package:kernel/kernel.dart';
+import 'package:kernel/text/ast_to_text.dart' as kernel show Printer;
+import 'package:kernel/binary/ast_to_binary.dart' as kernel show BinaryPrinter;
import 'package:path/path.dart' as path;
-import 'package:source_maps/source_maps.dart';
+import 'package:source_maps/source_maps.dart' show SourceMapBuilder;
import '../compiler/js_names.dart' as JS;
import '../compiler/module_builder.dart';
@@ -98,11 +100,11 @@
class CompilerResult {
final fe.InitializedCompilerState compilerState;
- final bool result;
+ final bool success;
- CompilerResult(this.compilerState, this.result);
+ CompilerResult(this.compilerState, this.success);
- CompilerResult.noState(this.result) : compilerState = null;
+ CompilerResult.noState(this.success) : compilerState = null;
}
Future<CompilerResult> _compile(List<String> args,
@@ -113,9 +115,31 @@
abbr: 'h', help: 'Display this message.', negatable: false)
..addOption('out', abbr: 'o', help: 'Output file (required).')
..addOption('packages', help: 'The package spec file to use.')
+ ..addFlag('summarize',
+ help: 'emit API summary in a .dill file', defaultsTo: true)
+ // TODO(jmesserly): should default to `false` and be hidden.
+ // For now this is very helpful in debugging the compiler.
+ ..addFlag('summarize-text',
+ help: 'emit API summary in a .js.txt file', defaultsTo: true)
// TODO(jmesserly): add verbose help to show hidden options
..addOption('dart-sdk-summary',
help: 'The path to the Dart SDK summary file.', hide: true)
+ // TODO(jmesserly): this help description length is too long.
+ //
+ // Also summary-input-dir and custom-app-scheme should be removed.
+ // They are undocumented and not necessary.
+ //
+ // URIs can be passed to `--summary` (including relative ones if desired),
+ // and we can easily add logic to prevert absolute file URIs in source maps.
+ //
+ // It appears to have been added in this change, but none of the flags are
+ // described there:
+ // https://github.com/dart-lang/sdk/commit/226602dc189555d9a43785c2a2f599b1622c1890
+ //
+ // Looking at the code, it appears to be solving a similar problem as
+ // `--module-root` in our old Analyzer-based backend.
+ // See https://github.com/dart-lang/sdk/issues/32272 for context on removing
+ // --module-root.
..addMultiOption('summary',
abbr: 's',
help: 'path to a summary of a transitive dependency of this module.\n'
@@ -186,8 +210,9 @@
var fileSystem = new MultiRootFileSystem(
customScheme, multiRoots, StandardFileSystem.instance);
+ var oldCompilerState = compilerState;
compilerState = await fe.initializeCompiler(
- compilerState,
+ oldCompilerState,
stringToUri(sdkSummaryPath),
stringToUri(packageFile),
summaryUris,
@@ -206,13 +231,29 @@
String output = argResults['out'];
var file = new File(output);
- if (!file.parent.existsSync()) file.parent.createSync(recursive: true);
+ await file.parent.create(recursive: true);
- // TODO(jmesserly): Save .dill file so other modules can link in this one.
- //await writeComponentToBinary(component, output);
-
- // Useful for debugging:
- writeComponentToText(component, path: output + '.txt');
+ // Output files can be written in parallel, so collect the futures.
+ var outFiles = <Future>[];
+ if (argResults['summarize'] as bool) {
+ // TODO(jmesserly): CFE mutates the Kernel tree, so we can't save the dill
+ // file if we successfully reused a cached library. If compiler state is
+ // unchanged, it means we used the cache.
+ //
+ // In that case, we need to unbind canonical names, because they could be
+ // bound already from the previous compile.
+ if (identical(compilerState, oldCompilerState)) {
+ component.unbindCanonicalNames();
+ }
+ var sink = new File(path.withoutExtension(output) + '.dill').openWrite();
+ new kernel.BinaryPrinter(sink).writeComponentFile(component);
+ outFiles.add(sink.flush().then((_) => sink.close()));
+ }
+ if (argResults['summarize-text'] as bool) {
+ var sink = new File(output + '.txt').openWrite();
+ new kernel.Printer(sink, showExternal: false).writeComponentFile(component);
+ outFiles.add(sink.flush().then((_) => sink.close()));
+ }
var compiler = new ProgramCompiler(component,
declaredVariables: declaredVariables,
@@ -226,14 +267,14 @@
jsUrl: path.toUri(output).toString(),
mapUrl: path.toUri(output + '.map').toString(),
customScheme: customScheme);
- file.writeAsStringSync(jsCode.code);
+ outFiles.add(file.writeAsString(jsCode.code));
if (jsCode.sourceMap != null) {
- file = new File(output + '.map');
- if (!file.parent.existsSync()) file.parent.createSync(recursive: true);
- file.writeAsStringSync(json.encode(jsCode.sourceMap));
+ outFiles.add(
+ new File(output + '.map').writeAsString(json.encode(jsCode.sourceMap)));
}
+ await Future.wait(outFiles);
return new CompilerResult(compilerState, true);
}
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index a8478d6..bf7fea8 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -181,9 +181,6 @@
final _labelNames = new HashMap<Statement, String>.identity();
final Class _jsArrayClass;
- final Class _jsBoolClass;
- final Class _jsNumberClass;
- final Class _jsStringClass;
final Class privateSymbolClass;
final Class linkedHashMapImplClass;
final Class identityHashMapImplClass;
@@ -220,9 +217,6 @@
this._constants, this.types, this._typeRep, this._nullableInference,
{this.emitMetadata, this.enableAsserts, this.replCompile})
: _jsArrayClass = sdk.getClass('dart:_interceptors', 'JSArray'),
- _jsBoolClass = sdk.getClass('dart:_interceptors', 'JSBool'),
- _jsNumberClass = sdk.getClass('dart:_interceptors', 'JSNumber'),
- _jsStringClass = sdk.getClass('dart:_interceptors', 'JSString'),
_asyncStreamIteratorClass =
sdk.getClass('dart:async', 'StreamIterator'),
privateSymbolClass = sdk.getClass('dart:_js_helper', 'PrivateSymbol'),
@@ -718,7 +712,7 @@
for (var ctor in superclass.constructors) {
var savedUri = _currentUri;
_currentUri = ctor.enclosingClass.fileUri;
- var jsParams = _emitFormalParameters(ctor.function);
+ var jsParams = _emitParameters(ctor.function);
_currentUri = savedUri;
var ctorBody = <JS.Statement>[];
if (mixinCtor != null) ctorBody.add(mixinCtor);
@@ -1177,7 +1171,8 @@
]));
}
- var extMembers = _classProperties.extensionMethods;
+ var extMethods = _classProperties.extensionMethods;
+ var extAccessors = _classProperties.extensionAccessors;
var staticMethods = <JS.Property>[];
var instanceMethods = <JS.Property>[];
var staticGetters = <JS.Property>[];
@@ -1241,7 +1236,8 @@
var property = new JS.Property(_declareMemberName(member), type);
var signatures = getSignatureList(member);
signatures.add(property);
- if (!member.isStatic && extMembers.contains(name)) {
+ if (!member.isStatic &&
+ (extMethods.contains(name) || extAccessors.contains(name))) {
signatures.add(new JS.Property(
_declareMemberName(member, useExtension: true), type));
}
@@ -1349,7 +1345,7 @@
Constructor node, List<Field> fields, JS.Expression className) {
var savedUri = _currentUri;
_currentUri = node.fileUri ?? savedUri;
- var params = _emitFormalParameters(node.function);
+ var params = _emitParameters(node.function);
var body = _withCurrentFunction(
node.function,
() => _superDisallowed(
@@ -1421,7 +1417,7 @@
return js.statement('#.#.call(this, #);', [
className,
_constructorName(ctor.name.name),
- _emitArgumentList(node.arguments)
+ _emitArgumentList(node.arguments, types: false)
]);
}
@@ -1437,7 +1433,7 @@
args = [];
} else {
ctor = superInit.target;
- args = _emitArgumentList(superInit.arguments);
+ args = _emitArgumentList(superInit.arguments, types: false);
}
// We can skip the super call if it's empty. Most commonly this happens for
// things that extend Object, and don't have any field initializers or their
@@ -1604,7 +1600,7 @@
var savedUri = _currentUri;
for (var m in c.procedures) {
_currentUri = m.fileUri ?? savedUri;
- if (m.isForwardingStub) {
+ if (_isForwardingStub(m)) {
// TODO(jmesserly): is there any other kind of forwarding stub?
jsMethods.addAll(_emitCovarianceCheckStub(m));
} else if (m.isFactory) {
@@ -1642,6 +1638,27 @@
return jsMethods.where((m) => m != null).toList();
}
+ bool _isForwardingStub(Procedure member) {
+ if (member.isForwardingStub || member.isForwardingSemiStub) {
+ if (_currentLibrary.importUri.scheme != 'dart') return true;
+ // TODO(jmesserly): external methods in the SDK seem to get incorrectly
+ // tagged as forwarding stubs even if they are patched. Perhaps there is
+ // an ordering issue in CFE. So for now we pattern match to see if it
+ // looks like an actual forwarding stub.
+ //
+ // We may be able to work around this in a cleaner way by simply emitting
+ // the code, and letting the normal covariance check logic handle things.
+ // But currently we use _emitCovarianceCheckStub to work around some
+ // issues in the stubs.
+ var body = member.function.body;
+ if (body is ReturnStatement) {
+ var expr = body.expression;
+ return expr is SuperMethodInvocation || expr is SuperPropertySet;
+ }
+ }
+ return false;
+ }
+
/// Emits a method, getter, or setter.
JS.Method _emitMethodDeclaration(Procedure member) {
if (member.isAbstract) {
@@ -1671,7 +1688,7 @@
if (node.isGetter) {
return new JS.Fun([], js.block('{ return this.#; }', [name]));
} else if (node.isSetter) {
- var params = _emitFormalParameters(node.function);
+ var params = _emitParameters(node.function);
return new JS.Fun(
params, js.block('{ this.# = #; }', [name, params.last]));
} else {
@@ -1687,13 +1704,13 @@
// ensure soundness of the super member, so we must lookup the super
// member and determine checks ourselves.
// - it generates getter stubs, but these are not used
- if (member.isGetter) return [];
+ if (member.isGetter) return const [];
var enclosingClass = member.enclosingClass;
var superMember = member.forwardingStubSuperTarget ??
member.forwardingStubInterfaceTarget;
- if (superMember == null) return [];
+ if (superMember == null) return const [];
substituteType(DartType t) {
return _getTypeFromClass(t, superMember.enclosingClass, enclosingClass);
@@ -1704,16 +1721,15 @@
if (superMember is Field && superMember.isGenericCovariantImpl ||
superMember is Procedure &&
isCovariant(superMember.function.positionalParameters[0])) {
- return [];
+ return const [];
}
+ var setterType = substituteType(superMember.setterType);
+ if (types.isTop(setterType)) return const [];
return [
new JS.Method(
name,
- js.fun('function(x) { return super.# = #; }', [
- name,
- _emitImplicitCast(new JS.Identifier('x'),
- substituteType(superMember.setterType))
- ]),
+ js.fun('function(x) { return super.# = #; }',
+ [name, _emitImplicitCast(new JS.Identifier('x'), setterType)]),
isSetter: true),
new JS.Method(name, js.fun('function() { return super.#; }', [name]),
isGetter: true)
@@ -1765,16 +1781,11 @@
}
}
- if (namedParameters.isNotEmpty) jsParams.add(namedArgumentTemp);
+ if (body.isEmpty) return const []; // No checks were needed.
- if (typeFormals.isEmpty) {
- body.add(js.statement('return super.#(#);', [name, jsParams]));
- } else {
- body.add(
- js.statement('return super.#(#)(#);', [name, typeFormals, jsParams]));
- }
- var fn = new JS.Fun(jsParams, new JS.Block(body));
- return [new JS.Method(name, fn)];
+ if (namedParameters.isNotEmpty) jsParams.add(namedArgumentTemp);
+ body.add(js.statement('return super.#(#);', [name, jsParams]));
+ return [new JS.Method(name, new JS.Fun(jsParams, new JS.Block(body)))];
}
/// Emits a Dart factory constructor to a JS static method.
@@ -1782,10 +1793,8 @@
if (isUnsupportedFactoryConstructor(node)) return null;
var function = node.function;
- return new JS.Method(
- _constructorName(node.name.name),
- new JS.Fun(
- _emitFormalParameters(function), _emitFunctionBody(function)),
+ return new JS.Method(_constructorName(node.name.name),
+ new JS.Fun(_emitParameters(function), _emitFunctionBody(function)),
isStatic: true)
..sourceInformation = _nodeEnd(node.fileEndOffset);
}
@@ -1919,7 +1928,7 @@
js.call('Symbol.iterator'),
js.call('function() { return new #.JsIterator(this.#); }', [
runtimeModule,
- _emitMemberName('iterator', type: iterable.asInterfaceType)
+ _emitMemberName('iterator', memberClass: coreTypes.iterableClass)
]) as JS.Fun);
}
@@ -1929,7 +1938,7 @@
void _registerExtensionType(
Class c, String jsPeerName, List<JS.Statement> body) {
var className = _emitTopLevelName(c);
- if (isPrimitiveType(c.rawType)) {
+ if (_typeRep.isPrimitive(c.rawType)) {
body.add(
runtimeStatement('definePrimitiveHashCode(#.prototype)', className));
}
@@ -2116,10 +2125,10 @@
/// helper, that checks for null. The user defined method is called '=='.
///
JS.Expression _emitMemberName(String name,
- {DartType type,
- bool isStatic: false,
+ {bool isStatic: false,
bool useExtension,
- NamedNode member}) {
+ Member member,
+ Class memberClass}) {
// Static members skip the rename steps and may require JS interop renames.
if (isStatic) {
return _emitStaticMemberName(name, member);
@@ -2146,7 +2155,8 @@
return emitPrivateNameSymbol(_currentLibrary, name);
}
- useExtension ??= _isSymbolizedMember(type, name);
+ memberClass ??= member?.enclosingClass;
+ useExtension ??= _isSymbolizedMember(memberClass, name);
name = JS.memberNameForDartMember(
name, member is Procedure && member.isExternal);
if (useExtension) {
@@ -2175,38 +2185,29 @@
/// Note, this is an underlying assumption here that, if another native type
/// subtypes this one, it also forwards this member to its underlying native
/// one without renaming.
- bool _isSymbolizedMember(DartType type, String name) {
- while (type is TypeParameterType) {
- type = (type as TypeParameterType).bound;
- }
- if (type == null ||
- type == const DynamicType() ||
- type == coreTypes.objectClass) {
+ bool _isSymbolizedMember(Class c, String name) {
+ if (c == null) {
return isObjectMember(name);
- } else if (type is InterfaceType) {
- var c = getImplementationClass(type) ?? type.classNode;
- if (_extensionTypes.isNativeClass(c)) {
- var member = _lookupForwardedMember(c, name);
-
- // Fields on a native class are implicitly native.
- // Methods/getters/setters are marked external/native.
- if (member is Field || member is Procedure && member.isExternal) {
- var jsName = getAnnotationName(member, isJSName);
- return jsName != null && jsName != name;
- } else {
- // Non-external members must be symbolized.
- return true;
- }
- }
- // If the receiver *may* be a native type (i.e., an interface allowed to
- // be implemented by a native class), conservatively symbolize - we don't
- // know whether it'll be implemented via forwarding.
- // TODO(vsm): Consider CHA here to be less conservative.
- return _extensionTypes.isNativeInterface(c);
- } else if (type is FunctionType) {
- return true;
}
- return false;
+ c = _typeRep.getImplementationClass(c.rawType) ?? c;
+ if (_extensionTypes.isNativeClass(c)) {
+ var member = _lookupForwardedMember(c, name);
+
+ // Fields on a native class are implicitly native.
+ // Methods/getters/setters are marked external/native.
+ if (member is Field || member is Procedure && member.isExternal) {
+ var jsName = getAnnotationName(member, isJSName);
+ return jsName != null && jsName != name;
+ } else {
+ // Non-external members must be symbolized.
+ return true;
+ }
+ }
+ // If the receiver *may* be a native type (i.e., an interface allowed to
+ // be implemented by a native class), conservatively symbolize - we don't
+ // know whether it'll be implemented via forwarding.
+ // TODO(vsm): Consider CHA here to be less conservative.
+ return _extensionTypes.isNativeInterface(c);
}
var _forwardingCache = new HashMap<Class, Map<String, Member>>();
@@ -2640,9 +2641,13 @@
JS.Fun _emitFunction(FunctionNode f, String name) {
// normal function (sync), vs (sync*, async, async*)
var isSync = f.asyncMarker == AsyncMarker.Sync;
- var formals = _emitFormalParameters(f);
+ var formals = _emitParameters(f);
var typeFormals = _emitTypeFormals(f.typeParameters);
- formals.insertAll(0, typeFormals);
+
+ var parent = f.parent;
+ if (_reifyGenericFunction(parent is Member ? parent : null)) {
+ formals.insertAll(0, typeFormals);
+ }
// TODO(jmesserly): need a way of determining if parameters are
// potentially mutated in Kernel. For now we assume all parameters are.
@@ -2660,9 +2665,14 @@
return new JS.Fun(formals, code);
}
- // TODO(jmesserly): rename _emitParameters
- List<JS.Parameter> _emitFormalParameters(FunctionNode f) {
- var result = f.positionalParameters.map(_emitVariableDef).toList();
+ List<JS.Parameter> _emitParameters(FunctionNode f) {
+ var positional = f.positionalParameters;
+ var result = new List<JS.Parameter>.from(positional.map(_emitVariableDef));
+ if (positional.isNotEmpty &&
+ f.requiredParameterCount == positional.length &&
+ positional.last.annotations.any(isJsRestAnnotation)) {
+ result.last = new JS.RestParameter(result.last);
+ }
if (f.namedParameters.isNotEmpty) result.add(namedArgumentTemp);
return result;
}
@@ -2736,7 +2746,7 @@
//
// In the future, we might be able to simplify this, see:
// https://github.com/dart-lang/sdk/issues/28320
- var jsParams = _emitFormalParameters(function);
+ var jsParams = _emitParameters(function);
var gen = emitGeneratorFn((fnBody) => jsParams =
jsParams.where(JS.findMutatedVariables(fnBody).contains).toList());
if (jsParams.isNotEmpty) gen = js.call('() => #(#)', [gen, jsParams]);
@@ -2886,6 +2896,12 @@
bool _annotatedNullCheck(List<Expression> annotations) =>
annotations.any(_nullableInference.isNullCheckAnnotation);
+ bool _reifyGenericFunction(Member m) =>
+ m == null ||
+ m.enclosingLibrary.importUri.scheme != 'dart' ||
+ !m.annotations
+ .any((a) => isBuiltinAnnotation(a, '_js_helper', 'NoReifyGeneric'));
+
JS.Statement _nullParameterCheck(JS.Expression param) {
var call = runtimeCall('argumentError((#))', [param]);
return js.statement('if (# == null) #;', [param, call]);
@@ -3634,32 +3650,36 @@
JS.Expression _emitPropertyGet(Expression receiver, Member member,
[String memberName]) {
memberName ??= member.name.name;
- var receiverType = receiver.getStaticType(types);
// TODO(jmesserly): should tearoff of `.call` on a function type be
// encoded as a different node, or possibly eliminated?
// (Regardless, we'll still need to handle the callable JS interop classes.)
- if (memberName == 'call' && _isDirectCallable(receiverType)) {
+ if (memberName == 'call' &&
+ _isDirectCallable(receiver.getStaticType(types))) {
// Tearoff of `call` on a function type is a no-op;
return _visitExpression(receiver);
}
- var jsName =
- _emitMemberName(memberName, type: receiverType, member: member);
+ var jsName = _emitMemberName(memberName, member: member);
var jsReceiver = _visitExpression(receiver);
// TODO(jmesserly): we need to mark an end span for property accessors so
// they can be hovered. Unfortunately this is not possible as Kernel does
// not store this data.
- if (member == null) {
+ if (isObjectMember(memberName)) {
+ if (isNullable(receiver)) {
+ // If the receiver is nullable, use a helper so calls like
+ // `null.hashCode` and `null.runtimeType` will work.
+ // Also method tearoffs like `null.toString`.
+ if (_isObjectMethod(memberName)) {
+ return runtimeCall('bind(#, #)', [jsReceiver, jsName]);
+ }
+ return runtimeCall('#(#)', [memberName, jsReceiver]);
+ }
+ // Otherwise generate this as a normal typed property get.
+ } else if (member == null) {
return runtimeCall('dload$_replSuffix(#, #)', [jsReceiver, jsName]);
}
- if (_isObjectMemberCall(receiver, memberName)) {
- if (_isObjectMethod(memberName)) {
- return runtimeCall('bind(#, #)', [jsReceiver, jsName]);
- } else {
- return runtimeCall('#(#)', [memberName, jsReceiver]);
- }
- } else if (_reifyTearoff(member)) {
+ if (_reifyTearoff(member)) {
return runtimeCall('bind(#, #)', [jsReceiver, jsName]);
} else {
return new JS.PropertyAccess(jsReceiver, jsName);
@@ -3674,8 +3694,8 @@
JS.Expression _emitPropertySet(
Expression receiver, Member member, Expression value,
[String memberName]) {
- var jsName = _emitMemberName(memberName ?? member.name.name,
- type: receiver.getStaticType(types), member: member);
+ var jsName =
+ _emitMemberName(memberName ?? member.name.name, member: member);
var jsReceiver = _visitExpression(receiver);
var jsValue = _visitExpression(value);
@@ -3754,13 +3774,13 @@
}
var jsReceiver = _visitExpression(receiver);
- var args = _emitArgumentList(arguments);
- var receiverType = receiver.getStaticType(types);
+ var args = _emitArgumentList(arguments, target: target);
bool isCallingDynamicField = target is Member &&
target.hasGetter &&
_isDynamicOrFunction(target.getterType);
if (name == 'call') {
+ var receiverType = receiver.getStaticType(types);
if (isCallingDynamicField || _isDynamicOrFunction(receiverType)) {
return _emitDynamicInvoke(jsReceiver, null, args, arguments);
} else if (_isDirectCallable(receiverType)) {
@@ -3769,13 +3789,17 @@
}
}
- var jsName = _emitMemberName(name, type: receiverType, member: target);
- if (target == null || isCallingDynamicField) {
- return _emitDynamicInvoke(jsReceiver, jsName, args, arguments);
- }
- if (_isObjectMemberCall(receiver, name)) {
+ var jsName = _emitMemberName(name, member: target);
+ if (isObjectMember(name)) {
assert(arguments.types.isEmpty); // Object methods don't take type args.
- return runtimeCall('#(#, #)', [name, jsReceiver, args]);
+ if (isNullable(receiver)) {
+ // If the receiver is nullable, use a helper so calls like
+ // `null.toString()` will work.
+ return runtimeCall('#(#, #)', [name, jsReceiver, args]);
+ }
+ // Otherwise generate this as a normal typed method call.
+ } else if (target == null || isCallingDynamicField) {
+ return _emitDynamicInvoke(jsReceiver, jsName, args, arguments);
}
// TODO(jmesserly): remove when Kernel desugars this for us.
// Handle `o.m(a)` where `o.m` is a getter returning a class with `call`.
@@ -3833,7 +3857,7 @@
var c = from.classNode;
var member = hierarchy.getInterfaceMember(c, new Name("call"));
if (member is Procedure && !member.isAccessor && !usesJSInterop(c)) {
- return _emitMemberName('call', type: from, member: member);
+ return _emitMemberName('call', member: member);
}
return null;
}
@@ -3844,19 +3868,20 @@
JS.Expression _emitUnaryOperator(
Expression expr, Member target, InvocationExpression node) {
var op = node.name.name;
- var dispatchType = expr.getStaticType(types);
- if (_typeRep.unaryOperationIsPrimitive(dispatchType)) {
- if (op == '~') {
- if (_typeRep.isNumber(dispatchType)) {
- return _coerceBitOperationResultToUnsigned(
- node, js.call('~#', notNull(expr)));
+ if (target != null) {
+ var dispatchType = target.enclosingClass.rawType;
+ if (_typeRep.unaryOperationIsPrimitive(dispatchType)) {
+ if (op == '~') {
+ if (_typeRep.isNumber(dispatchType)) {
+ return _coerceBitOperationResultToUnsigned(
+ node, js.call('~#', notNull(expr)));
+ }
+ return _emitOperatorCall(expr, target, op, []);
}
- return _emitOperatorCall(expr, target, op, []);
+ if (op == 'unary-') op = '-';
+ return js.call('$op#', notNull(expr));
}
- if (op == 'unary-') op = '-';
- return js.call('$op#', notNull(expr));
}
-
return _emitOperatorCall(expr, target, op, []);
}
@@ -4010,76 +4035,82 @@
var op = node.name.name;
if (op == '==') return _emitEqualityOperator(left, target, right);
- var leftType = left.getStaticType(types);
- var rightType = right.getStaticType(types);
+ // TODO(jmesserly): using the target type here to work around:
+ // https://github.com/dart-lang/sdk/issues/33293
+ if (target != null) {
+ var targetClass = target.enclosingClass;
+ var leftType = targetClass.rawType;
+ var rightType = right.getStaticType(types);
- if (_typeRep.binaryOperationIsPrimitive(leftType, rightType) ||
- leftType == types.stringType && op == '+') {
- // special cases where we inline the operation
- // these values are assumed to be non-null (determined by the checker)
- // TODO(jmesserly): it would be nice to just inline the method from core,
- // instead of special cases here.
- JS.Expression binary(String code) {
- return js.call(code, [notNull(left), notNull(right)]);
- }
+ if (_typeRep.binaryOperationIsPrimitive(leftType, rightType) ||
+ leftType == types.stringType && op == '+') {
+ // special cases where we inline the operation
+ // these values are assumed to be non-null (determined by the checker)
+ // TODO(jmesserly): it would be nice to just inline the method from core,
+ // instead of special cases here.
+ JS.Expression binary(String code) {
+ return js.call(code, [notNull(left), notNull(right)]);
+ }
- JS.Expression bitwise(String code) {
- return _coerceBitOperationResultToUnsigned(node, binary(code));
- }
+ JS.Expression bitwise(String code) {
+ return _coerceBitOperationResultToUnsigned(node, binary(code));
+ }
- switch (op) {
- case '~/':
- // `a ~/ b` is equivalent to `(a / b).truncate()`
- return js.call('(# / #).#()', [
- notNull(left),
- notNull(right),
- _emitMemberName('truncate', type: leftType)
- ]);
+ switch (op) {
+ case '~/':
+ // `a ~/ b` is equivalent to `(a / b).truncate()`
+ return js.call('(# / #).#()', [
+ notNull(left),
+ notNull(right),
+ _emitMemberName('truncate', memberClass: targetClass)
+ ]);
- case '%':
- // TODO(sra): We can generate `a % b + 0` if both are non-negative
- // (the `+ 0` is to coerce -0.0 to 0).
- return _emitOperatorCall(left, target, op, [right]);
+ case '%':
+ // TODO(sra): We can generate `a % b + 0` if both are non-negative
+ // (the `+ 0` is to coerce -0.0 to 0).
+ return _emitOperatorCall(left, target, op, [right]);
- case '&':
- return bitwise('# & #');
+ case '&':
+ return bitwise('# & #');
- case '|':
- return bitwise('# | #');
+ case '|':
+ return bitwise('# | #');
- case '^':
- return bitwise('# ^ #');
+ case '^':
+ return bitwise('# ^ #');
- case '>>':
- int shiftCount = _asIntInRange(right, 0, 31);
- if (_is31BitUnsigned(left) && shiftCount != null) {
- return binary('# >> #');
- }
- if (_isDefinitelyNonNegative(left) && shiftCount != null) {
- return binary('# >>> #');
- }
- // If the context selects out only bits that can't be affected by the
- // sign position we can use any JavaScript shift, `(x >> 6) & 3`.
- if (shiftCount != null &&
- _parentMasksToWidth(node, 31 - shiftCount)) {
- return binary('# >> #');
- }
- return _emitOperatorCall(left, target, op, [right]);
+ case '>>':
+ int shiftCount = _asIntInRange(right, 0, 31);
+ if (_is31BitUnsigned(left) && shiftCount != null) {
+ return binary('# >> #');
+ }
+ if (_isDefinitelyNonNegative(left) && shiftCount != null) {
+ return binary('# >>> #');
+ }
+ // If the context selects out only bits that can't be affected by the
+ // sign position we can use any JavaScript shift, `(x >> 6) & 3`.
+ if (shiftCount != null &&
+ _parentMasksToWidth(node, 31 - shiftCount)) {
+ return binary('# >> #');
+ }
+ return _emitOperatorCall(left, target, op, [right]);
- case '<<':
- if (_is31BitUnsigned(node)) {
- // Result is 31 bit unsigned which implies the shift count was small
- // enough not to pollute the sign bit.
- return binary('# << #');
- }
- if (_asIntInRange(right, 0, 31) != null) {
- return _coerceBitOperationResultToUnsigned(node, binary('# << #'));
- }
- return _emitOperatorCall(left, target, op, [right]);
+ case '<<':
+ if (_is31BitUnsigned(node)) {
+ // Result is 31 bit unsigned which implies the shift count was small
+ // enough not to pollute the sign bit.
+ return binary('# << #');
+ }
+ if (_asIntInRange(right, 0, 31) != null) {
+ return _coerceBitOperationResultToUnsigned(
+ node, binary('# << #'));
+ }
+ return _emitOperatorCall(left, target, op, [right]);
- default:
- // TODO(vsm): When do Dart ops not map to JS?
- return binary('# $op #');
+ default:
+ // TODO(vsm): When do Dart ops not map to JS?
+ return binary('# $op #');
+ }
}
}
@@ -4089,7 +4120,8 @@
JS.Expression _emitEqualityOperator(
Expression left, Member target, Expression right,
{bool negated = false}) {
- var leftType = left.getStaticType(types);
+ var targetClass = target?.enclosingClass;
+ var leftType = targetClass?.rawType ?? left.getStaticType(types);
// Conceptually `x == y` in Dart is defined as:
//
@@ -4107,14 +4139,15 @@
// TODO(leafp,jmesserly): we could use class hierarchy analysis to check
// if `operator ==` was overridden, similar to how we devirtualize private
// fields.
+ //
+ // If we know that the left type uses identity for equality, we can
+ // sometimes emit better code, either `===` or `==`.
var isEnum = leftType is InterfaceType && leftType.classNode.isEnum;
var usesIdentity = _typeRep.isPrimitive(leftType) ||
isEnum ||
_isNull(left) ||
_isNull(right);
- // If we know that the left type uses identity for equality, we can
- // sometimes emit better code, either `===` or `==`.
if (usesIdentity) {
return _emitCoreIdenticalCall([left, right], negated: negated);
}
@@ -4131,7 +4164,7 @@
// Otherwise we emit a call to the == method.
return js.call(negated ? '!#[#](#)' : '#[#](#)', [
_visitExpression(left),
- _emitMemberName('==', type: leftType),
+ _emitMemberName('==', memberClass: targetClass),
_visitExpression(right)
]);
}
@@ -4145,8 +4178,7 @@
Expression receiver, Member target, String name, List<Expression> args) {
// TODO(jmesserly): calls that don't pass `element` are probably broken for
// `super` calls from disallowed super locations.
- var type = receiver.getStaticType(types);
- var memberName = _emitMemberName(name, type: type, member: target);
+ var memberName = _emitMemberName(name, member: target);
if (target == null) {
// dynamic dispatch
var dynamicHelper = const {'[]': 'dindex', '[]=': 'dsetindex'}[name];
@@ -4170,15 +4202,15 @@
// TODO(jmesserly): optimize super operators for kernel
@override
visitSuperMethodInvocation(SuperMethodInvocation node) {
- return new JS.Call(_emitSuperTarget(node.interfaceTarget),
- _emitArgumentList(node.arguments));
+ var target = node.interfaceTarget;
+ return new JS.Call(_emitSuperTarget(target),
+ _emitArgumentList(node.arguments, target: target));
}
/// Emits the [JS.PropertyAccess] for accessors or method calls to
/// [jsTarget].[jsName], replacing `super` if it is not allowed in scope.
JS.PropertyAccess _emitSuperTarget(Member member, {bool setter: false}) {
- var type = member.enclosingClass.rawType;
- var jsName = _emitMemberName(member.name.name, type: type, member: member);
+ var jsName = _emitMemberName(member.name.name, member: member);
if (member is Field && !virtualFields.isVirtual(member)) {
return new JS.PropertyAccess(new JS.This(), jsName);
}
@@ -4252,7 +4284,7 @@
}
var fn = _emitStaticTarget(target);
- var args = _emitArgumentList(node.arguments);
+ var args = _emitArgumentList(node.arguments, target: target);
return new JS.Call(fn, args);
}
@@ -4302,13 +4334,25 @@
JS.Expression _emitStaticTarget(Member target) {
var c = target.enclosingClass;
if (c != null) {
+ // A static native element should just forward directly to the
+ // JS type's member.
+ if (target is Procedure && target.isStatic && target.isExternal) {
+ var nativeName = _extensionTypes.getNativePeers(c);
+ if (nativeName.isNotEmpty) {
+ var memberName = getAnnotationName(target, isJSName) ??
+ _emitStaticMemberName(target.name.name, target);
+ return runtimeCall('global.#.#', [nativeName[0], memberName]);
+ }
+ }
return new JS.PropertyAccess(_emitStaticClassName(c),
_emitStaticMemberName(target.name.name, target));
}
return _emitTopLevelName(target);
}
- List<JS.Expression> _emitArgumentList(Arguments node, {bool types: true}) {
+ List<JS.Expression> _emitArgumentList(Arguments node,
+ {bool types: true, Member target}) {
+ types = types && _reifyGenericFunction(target);
var args = <JS.Expression>[];
if (types) {
for (var typeArg in node.types) {
@@ -4410,8 +4454,6 @@
/// [_notNullLocals].
bool isNullable(Expression expr) => _nullableInference.isNullable(expr);
- bool isPrimitiveType(DartType t) => _typeRep.isPrimitive(t);
-
JS.Expression _emitJSDoubleEq(List<JS.Expression> args,
{bool negated = false}) {
var op = negated ? '# != #' : '# == #';
@@ -4525,7 +4567,7 @@
JS.Expression _emitMapImplType(InterfaceType type, {bool identity}) {
var typeArgs = type.typeArguments;
if (typeArgs.isEmpty) return _emitType(type);
- identity ??= isPrimitiveType(typeArgs[0]);
+ identity ??= _typeRep.isPrimitive(typeArgs[0]);
var c = identity ? identityHashMapImplClass : linkedHashMapImplClass;
return _emitType(new InterfaceType(c, typeArgs));
}
@@ -4533,13 +4575,13 @@
JS.Expression _emitSetImplType(InterfaceType type, {bool identity}) {
var typeArgs = type.typeArguments;
if (typeArgs.isEmpty) return _emitType(type);
- identity ??= isPrimitiveType(typeArgs[0]);
+ identity ??= _typeRep.isPrimitive(typeArgs[0]);
var c = identity ? identityHashSetImplClass : linkedHashSetImplClass;
return _emitType(new InterfaceType(c, typeArgs));
}
JS.Expression _emitObjectLiteral(Arguments node) {
- var args = _emitArgumentList(node);
+ var args = _emitArgumentList(node, types: false);
if (args.isEmpty) return js.call('{}');
assert(args.single is JS.ObjectInitializer);
return args.single;
@@ -4586,37 +4628,18 @@
@override
visitStringConcatenation(StringConcatenation node) {
- var expressions = node.expressions;
- if (expressions.every((e) => e is StringLiteral)) {
- return new JS.Expression.binary(_visitExpressionList(expressions), '+');
- }
-
- var strings = <String>[];
- var interpolations = <JS.Expression>[];
-
- var expectString = true;
- for (var e in expressions) {
- if (e is StringLiteral) {
- // Escape the string as necessary for use in the eventual `` quotes.
- // TODO(jmesserly): this call adds quotes, and then we strip them off.
- var str = js.escapedString(e.value, '`').value;
- str = str.substring(1, str.length - 1);
- if (expectString) {
- strings.add(str);
- } else {
- var last = strings.length - 1;
- strings[last] = strings[last] + str;
- }
- expectString = false;
- } else {
- if (expectString) strings.add('');
- interpolations.add(_visitExpression(e));
- expectString = true;
+ var parts = <JS.Expression>[];
+ for (var e in node.expressions) {
+ var jsExpr = _visitExpression(e);
+ if (jsExpr is JS.LiteralString && jsExpr.valueWithoutQuotes.isEmpty) {
+ continue;
}
+ parts.add(e.getStaticType(types) == types.stringType && !isNullable(e)
+ ? jsExpr
+ : runtimeCall('str(#)', jsExpr));
}
- if (expectString) strings.add('');
- return new JS.TaggedTemplate(
- runtimeCall('str'), new JS.TemplateString(strings, interpolations));
+ if (parts.isEmpty) return js.string('');
+ return new JS.Expression.binary(parts, '+');
}
@override
@@ -4625,7 +4648,7 @@
JS.Expression result;
var type = node.type;
var lhs = _visitExpression(node.operand);
- var typeofName = _jsTypeofName(type);
+ var typeofName = _typeRep.typeFor(type).primitiveTypeOf;
// Inline primitives other than int (which requires a Math.floor check).
if (typeofName != null && type != coreTypes.intClass.rawType) {
result = js.call('typeof # == #', [lhs, js.string(typeofName, "'")]);
@@ -4637,22 +4660,6 @@
return result;
}
- String _jsTypeofName(DartType type) {
- var t = _typeRep.typeFor(type);
- if (t is JSNumber) return 'number';
- if (t is JSString) return 'string';
- if (t is JSBoolean) return 'boolean';
- return null;
- }
-
- Class getImplementationClass(DartType type) {
- var t = _typeRep.typeFor(type);
- if (t is JSNumber) return _jsNumberClass;
- if (t is JSString) return _jsStringClass;
- if (t is JSBoolean) return _jsBoolClass;
- return null;
- }
-
@override
visitAsExpression(AsExpression node) {
Expression fromExpr = node.operand;
@@ -4720,8 +4727,10 @@
nativeSymbol
]);
} else {
- return js.call('#.new(#)',
- [_emitConstructorAccess(coreTypes.symbolClass.rawType), name]);
+ return js.call('new #.new(#)', [
+ _emitConstructorAccess(coreTypes.internalSymbolClass.rawType),
+ name
+ ]);
}
}
@@ -4957,16 +4966,6 @@
_reifyFunctionType(member.function);
}
- /// Everything in Dart is an Object and supports the 4 members on Object,
- /// so we have to use a runtime helper to handle values such as `null` and
- /// native types.
- ///
- /// For example `null.toString()` is legal in Dart, so we need to generate
- /// that as `dart.toString(obj)`.
- bool _isObjectMemberCall(Expression target, String memberName) {
- return isObjectMember(memberName) && isNullable(target);
- }
-
/// Returns the name value of the `JSExportName` annotation (when compiling
/// the SDK), or `null` if there's none. This is used to control the name
/// under which functions are compiled and exported.
diff --git a/pkg/dev_compiler/lib/src/kernel/js_typerep.dart b/pkg/dev_compiler/lib/src/kernel/js_typerep.dart
index 103e981..b43b1b0 100644
--- a/pkg/dev_compiler/lib/src/kernel/js_typerep.dart
+++ b/pkg/dev_compiler/lib/src/kernel/js_typerep.dart
@@ -5,87 +5,9 @@
import 'package:kernel/core_types.dart';
import 'package:kernel/kernel.dart';
import 'package:kernel/type_environment.dart';
+import '../compiler/js_typerep.dart';
-/// An abstraction of the JS types
-abstract class JSType {
- const JSType();
-
- /// True if this type is built-in to JS, and we use the values unwrapped.
- /// For these types we generate a calling convention via static
- /// "extension methods". This allows types to be extended without adding
- /// extensions directly on the prototype.
- bool get isPrimitive;
-
- /// Is this type known to be definitively primitive
- /// (using the JS notion of primitive)
- bool get isPrimitiveInJS;
-
- /// Can a non-null element of this type potentially be interpreted
- /// as false in JS.
- bool get isFalsey;
-
- static const jsBoolean = const JSBoolean();
- static const jsNumber = const JSNumber();
- static const jsNull = const JSNull();
- static const jsObject = const JSObject();
- static const jsString = const JSString();
- static const jsUnknown = const JSUnknown();
-}
-
-/// Inhabited by booleans (including JSBool), null, and undefined
-class JSBoolean extends JSType {
- const JSBoolean();
- bool get isPrimitive => true;
- bool get isPrimitiveInJS => true;
- bool get isFalsey => true;
-}
-
-/// Inhabited by numbers, null, and undefined
-/// In practice, this is 4 types: num, int, double, and _interceptors.JSNumber.
-///
-/// _interceptors.JSNumber is the type that actually "implements" all numbers,
-/// hence it's a subtype of int and double (and num).
-/// It's defined in our "dart:_interceptors".
-class JSNumber extends JSType {
- const JSNumber();
- bool get isPrimitive => true;
- bool get isPrimitiveInJS => true;
- bool get isFalsey => true;
-}
-
-/// Inhabited by null and undefined
-class JSNull extends JSType {
- const JSNull();
- bool get isPrimitive => false;
- bool get isPrimitiveInJS => false;
- bool get isFalsey => true;
-}
-
-/// Inhabited by objects, null, and undefined
-class JSObject extends JSType {
- const JSObject();
- bool get isPrimitive => false;
- bool get isPrimitiveInJS => false;
- bool get isFalsey => false;
-}
-
-/// Inhabited by strings (including JSString), null, and undefined
-class JSString extends JSType {
- const JSString();
- bool get isPrimitive => true;
- bool get isPrimitiveInJS => false;
- bool get isFalsey => true;
-}
-
-/// Inhabitance not statically known
-class JSUnknown extends JSType {
- const JSUnknown();
- bool get isPrimitive => false;
- bool get isPrimitiveInJS => false;
- bool get isFalsey => true;
-}
-
-class JSTypeRep {
+class JSTypeRep extends SharedJSTypeRep<DartType> {
final TypeEnvironment types;
final CoreTypes coreTypes;
@@ -102,6 +24,7 @@
_jsString =
types.coreTypes.index.getClass('dart:_interceptors', 'JSString');
+ @override
JSType typeFor(DartType type) {
while (type is TypeParameterType) {
type = (type as TypeParameterType).parameter.bound;
@@ -148,42 +71,4 @@
if (rep == JSType.jsString) return _jsString;
return null;
}
-
- /// If the type [t] is [int] or [double], or a type parameter
- /// bounded by [int], [double] or [num] returns [num].
- /// Otherwise returns [t].
- DartType canonicalizeNumTypes(DartType t) =>
- isNumber(t) ? coreTypes.nullClass.rawType : t;
-
- bool isNumber(DartType type) => typeFor(type) is JSNumber;
-
- /// Is this type known to be represented as Object or Null in JS.
- bool isObjectOrNull(DartType t) {
- var rep = typeFor(t);
- return rep is JSObject || rep is JSNull;
- }
-
- bool isUnknown(DartType t) => typeFor(t) is JSUnknown;
-
- bool isPrimitive(DartType t) => typeFor(t).isPrimitive;
-
- bool isPrimitiveInJS(DartType t) => typeFor(t).isPrimitiveInJS;
-
- bool binaryOperationIsPrimitive(DartType leftT, DartType rightT) =>
- isPrimitiveInJS(leftT) && isPrimitiveInJS(rightT);
-
- bool unaryOperationIsPrimitive(DartType t) => isPrimitiveInJS(t);
-
- /// True if the JS double equals (`==`) comparison on the representation
- /// of these two types could potentially cause a conversion.
- bool equalityMayConvert(DartType t0, DartType t1) => !equalOrNull(t0, t1);
-
- // Are t0 and t1 known to either be represented by the same type
- // or else one or both of them is represented by Null
- bool equalOrNull(DartType t0, DartType t1) {
- var rep0 = typeFor(t0);
- var rep1 = typeFor(t1);
- if (rep0 is JSNull || rep1 is JSNull) return true;
- return rep0 == rep1 && rep0 is! JSUnknown;
- }
}
diff --git a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
index 44a8f0f..b9b6412 100644
--- a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
+++ b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
@@ -83,8 +83,10 @@
Expression value, String libraryName, String expectedName) {
if (value is ConstructorInvocation) {
var c = value.target.enclosingClass;
- return c.name == expectedName &&
- c.enclosingLibrary.importUri.toString() == libraryName;
+ if (c.name == expectedName) {
+ var uri = c.enclosingLibrary.importUri;
+ return uri.scheme == 'dart' && uri.path == libraryName;
+ }
}
return false;
}
diff --git a/pkg/dev_compiler/lib/src/kernel/native_types.dart b/pkg/dev_compiler/lib/src/kernel/native_types.dart
index 78876b4..cde8c08 100644
--- a/pkg/dev_compiler/lib/src/kernel/native_types.dart
+++ b/pkg/dev_compiler/lib/src/kernel/native_types.dart
@@ -83,7 +83,7 @@
void _addExtensionTypesForLibrary(String library, List<String> classNames) {
var sdk = coreTypes.index;
for (var className in classNames) {
- _addExtensionType(sdk.getClass(library, className), true);
+ _addExtensionType(sdk.getClass(library, className));
}
}
diff --git a/pkg/dev_compiler/lib/src/kernel/property_model.dart b/pkg/dev_compiler/lib/src/kernel/property_model.dart
index e630821..1edc3b7 100644
--- a/pkg/dev_compiler/lib/src/kernel/property_model.dart
+++ b/pkg/dev_compiler/lib/src/kernel/property_model.dart
@@ -310,13 +310,13 @@
///
/// By tracking the set of seen members, we can visit superclasses and mixins
/// and ultimately collect every most-derived member exposed by a given type.
- void _findExtensionMembers(Class class_, HashSet<String> seenConcreteMembers,
- Set<String> allNatives) {
+ void _findExtensionMembers(
+ Class c, HashSet<String> seenConcreteMembers, Set<String> allNatives) {
// We only visit each most derived concrete member.
// To avoid visiting an overridden superclass member, we skip members
// we've seen, and visit starting from the class, then mixins in
// reverse order, then superclasses.
- for (var m in class_.members) {
+ for (var m in c.members) {
var name = m.name.name;
if (m.isAbstract || m is Constructor) continue;
if (m is Procedure) {
@@ -338,8 +338,11 @@
/// types.
void _collectNativeMembers(Class c, Set<String> members) {
if (extensionTypes.hasNativeSubtype(c)) {
- for (var m in c.procedures) {
- if (!m.name.isPrivate && !m.isStatic) members.add(m.name.name);
+ for (var m in c.members) {
+ if (!m.name.isPrivate &&
+ (m is Procedure && !m.isStatic || m is Field && !m.isStatic)) {
+ members.add(m.name.name);
+ }
}
}
var m = c.mixedInClass;
diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart
index 26dbc21..5996ea5 100644
--- a/pkg/dev_compiler/lib/src/kernel/target.dart
+++ b/pkg/dev_compiler/lib/src/kernel/target.dart
@@ -77,9 +77,15 @@
// to the file where the class resides, or the file where the method we're
// mocking resides).
Expression createInvocation(String name, List<Expression> positional) {
- var ctor = coreTypes.invocationClass.procedures
+ // TODO(jmesserly): this uses the implementation _Invocation class,
+ // because the CFE does not resolve the redirecting factory constructors
+ // like it would for user code. Our code generator expects all redirecting
+ // factories to be resolved to the real constructor.
+ var ctor = coreTypes.index
+ .getClass('dart:core', '_Invocation')
+ .constructors
.firstWhere((c) => c.name.name == name);
- return new StaticInvocation(ctor, new Arguments(positional));
+ return new ConstructorInvocation(ctor, new Arguments(positional));
}
if (name.startsWith('get:')) {
@@ -96,6 +102,8 @@
if (isGeneric) {
ctorArgs.add(new ListLiteral(
arguments.types.map((t) => new TypeLiteral(t)).toList()));
+ } else {
+ ctorArgs.add(new NullLiteral());
}
ctorArgs.add(new ListLiteral(arguments.positional));
if (arguments.named.isNotEmpty) {
@@ -105,7 +113,7 @@
.toList(),
keyType: coreTypes.symbolClass.rawType));
}
- return createInvocation(isGeneric ? 'genericMethod' : 'method', ctorArgs);
+ return createInvocation('method', ctorArgs);
}
@override
diff --git a/pkg/dev_compiler/test/browser/language_tests.js b/pkg/dev_compiler/test/browser/language_tests.js
deleted file mode 100644
index 0d33cb0..0000000
--- a/pkg/dev_compiler/test/browser/language_tests.js
+++ /dev/null
@@ -1,796 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-define(['dart_sdk', 'async_helper', 'expect', 'unittest', 'is', 'require',
- 'test_status'],
- function(dart_sdk, async_helper, expect, unittest, is, require,
- test_status) {
- 'use strict';
-
- async_helper = async_helper.async_helper;
- let minitest = expect.minitest;
- let mochaOnError = window.onerror;
- dart_sdk.dart.trapRuntimeErrors(false);
- dart_sdk.dart.ignoreWhitelistedErrors(false);
- dart_sdk._isolate_helper.startRootIsolate(function() {}, []);
- // Make it easier to debug test failures and required for formatter test that
- // assumes custom formatters are enabled.
- dart_sdk._debugger.registerDevtoolsFormatter();
-
- let html_config = unittest.html_config;
- // Test attributes are a list of strings, or a string for a single
- // attribute. Valid attributes are:
- //
- // 'pass' - test passes (default)
- // 'skip' - don't run the test
- // 'fail' - test fails
- // 'timeout' - test times out
- // 'slow' - use 5s timeout instead of default 2s.
- //
- // Common combinations:
- const pass = 'pass';
- const fail = 'fail';
- const skip_timeout = ['skip', 'timeout'];
-
- // Browsers
- const firefox_fail = is.firefox() ? fail : pass;
- const chrome_fail = is.chrome() ? fail : pass;
-
- // These are typically tests with asynchronous exceptions that our
- // test framework doesn't always catch.
- const flaky = 'skip';
-
- // Tests marked with this are still using the deprecated unittest package
- // because they rely on its support for futures and asynchronous tests, which
- // expect and minitest do not handle.
- // TODO(rnystrom): Move all of these away from using the async test API so
- // they can stop using unittest.
- const async_unittest = ['skip', 'fail'];
-
- // The number of expected unittest errors should be zero but unfortunately
- // there are a lot of broken html unittests.
- let num_expected_unittest_fails = 4;
- let num_expected_unittest_errors = 0;
-
- // TODO(jmesserly): separate StrongModeError from other errors.
- let all_status = {
- 'language': {
- // Flaky on travis (https://github.com/dart-lang/sdk/issues/27224)
- 'async_await_test_03_multi': async_unittest,
-
- 'async_star_pause_test': fail,
- 'async_star_await_pauses_test': skip_timeout,
-
- // TODO(jmesserly): figure out why this test is hanging.
- 'async_star_cancel_and_throw_in_finally_test': skip_timeout,
-
- 'async_star_cancel_while_paused_test': fail,
-
- // TODO(vsm): Re-enable (https://github.com/dart-lang/sdk/issues/28319)
- 'async_star_test_none_multi': async_unittest,
- 'async_star_test_01_multi': async_unittest,
- 'async_star_test_02_multi': async_unittest,
- 'async_star_test_03_multi': async_unittest,
- 'async_star_test_04_multi': async_unittest,
- 'async_star_test_05_multi': async_unittest,
-
- 'async_switch_test': fail,
- 'asyncstar_throw_in_catch_test': ['skip', 'fail'],
- 'await_future_test': skip_timeout,
- 'await_for_test': 'slow',
- 'bit_operations_test_none_multi': fail, // DDC/dart2js canonicalize bitop results to unsigned
- 'branch_canonicalization_test': fail, // JS bit operations truncate to 32 bits.
- 'call_test': fail,
- 'call_closurization_test': fail, // Functions do not expose a "call" method.
- 'call_test': fail,
- 'canonical_const2_test': fail,
- 'canonical_const_test': fail,
- 'compile_time_constant10_test_none_multi': fail,
- 'compile_time_constant_a_test': fail,
- 'compile_time_constant_b_test': fail,
- 'compile_time_constant_d_test': fail,
- 'compile_time_constant_k_test_none_multi': fail,
- 'compile_time_constant_o_test_none_multi': fail,
- 'const_evaluation_test_01_multi': fail,
- 'const_switch_test_02_multi': fail,
- 'const_switch_test_04_multi': fail,
- 'constructor12_test': fail,
- 'covariant_subtyping_with_substitution_test': fail,
- 'custom_await_stack_trace_test': fail,
- 'cyclic_type2_test': fail,
- 'cyclic_type_test_02_multi': fail,
- 'cyclic_type_test_03_multi': fail,
- 'cyclic_type_test_04_multi': fail,
-
- // Deferred libraries are not actually deferred. These tests all test
- // that synchronous access to the library fails.
- 'deferred_call_empty_before_load_test': fail,
- 'deferred_load_library_wrong_args_test_01_multi': fail,
- 'deferred_not_loaded_check_test': fail,
- 'deferred_redirecting_factory_test': fail,
- 'deferred_static_seperate_test': fail,
-
- 'double_int_to_string_test': fail,
- 'dynamic_test': fail,
- 'exception_test': fail,
- 'execute_finally6_test': fail,
- 'expect_test': fail,
- 'extends_test_lib': fail,
- 'f_bounded_quantification3_test': fail,
- 'field_increment_bailout_test': fail,
- 'field_optimization3_test': fail,
- 'first_class_types_test': fail,
- 'flatten_test_01_multi': fail,
- 'flatten_test_04_multi': fail,
- 'flatten_test_05_multi': fail,
- 'flatten_test_08_multi': fail,
- 'flatten_test_09_multi': fail,
- 'flatten_test_12_multi': fail,
- 'for_variable_capture_test': is.firefox('<=50') ? pass : fail,
- 'function_subtype_inline2_test': fail,
- 'function_subtype_named1_test': fail,
- 'function_subtype_named2_test': fail,
- 'function_subtype_optional1_test': fail,
- 'function_subtype_optional2_test': fail,
- 'function_subtype_typearg2_test': fail,
- 'function_subtype_typearg4_test': fail,
- 'function_type_alias6_test_none_multi': fail,
- 'generic_instanceof_test': fail, // runtime strong mode reject
- 'generic_instanceof2_test': fail,
- 'generic_is_check_test': fail,
- 'getter_closure_execution_order_test': fail,
- 'gc_test': 'slow',
- 'identical_closure2_test': fail,
- 'infinite_switch_label_test': fail,
- 'infinity_test': fail,
- 'initializing_formal_final_test': fail,
- 'instance_creation_in_function_annotation_test': fail,
- 'instanceof2_test': fail,
- 'instanceof4_test_01_multi': fail,
- 'instanceof4_test_none_multi': fail,
- 'integer_division_by_zero_test': fail,
- 'issue23244_test': fail,
- 'invocation_mirror_test': fail, // dcall does not correctly detect named arguments
- 'invocation_mirror2_test': fail, // JsInstanceMirror.delegate unimplemented
- 'lazy_static3_test': fail,
- 'least_upper_bound_expansive_test_none_multi': fail,
- 'left_shift_test': fail,
- 'list_is_test': fail,
- 'list_literal3_test': fail,
- 'main_test_03_multi': fail,
- 'many_generic_instanceof_test': fail,
- 'map_literal10_test': fail,
- 'map_literal7_test': fail,
- 'memory_swap_test': skip_timeout,
- 'mint_arithmetic_test': fail,
- 'modulo_test': fail,
- 'named_parameter_clash_test': fail,
- 'named_parameters_passing_falsy_test': is.firefox('<=50') ? fail : pass,
- 'nan_identical_test': fail,
- 'nested_switch_label_test': fail,
- 'number_identifier_test_05_multi': fail,
- 'number_identity2_test': fail,
- 'numbers_test': fail,
- 'regress_16640_test': fail,
- 'regress_22445_test': fail,
- 'regress_22777_test': flaky,
- 'stack_overflow_stacktrace_test': fail,
- 'stack_overflow_test': fail,
- 'stacktrace_test': chrome_fail,
- 'switch_label2_test': fail,
- 'switch_label_test': fail,
- 'switch_try_catch_test': fail,
- 'throwing_lazy_variable_test': fail,
- 'truncdiv_test': fail, // did not throw
- 'try_catch_on_syntax_test_10_multi': fail,
- 'try_catch_on_syntax_test_11_multi': fail,
- 'type_variable_nested_test': fail,
-
- 'bit_operations_test_01_multi': fail,
- 'bit_operations_test_02_multi': fail,
- 'bit_operations_test_03_multi': fail,
- 'bit_operations_test_04_multi': fail,
- 'deferred_load_constants_test_none_multi': fail,
- 'external_test_21_multi': fail,
- 'external_test_24_multi': fail,
- 'multiline_newline_test_04_multi': fail,
- 'multiline_newline_test_05_multi': fail,
- 'multiline_newline_test_06_multi': fail,
- 'multiline_newline_test_none_multi': fail,
-
- // https://github.com/dart-lang/sdk/issues/26124
- 'prefix10_negative_test': fail,
-
- 'library_prefixes_test1': 'skip', // not a test
- 'library_prefixes_test2': 'skip', // not a test
- 'top_level_prefixed_library_test': 'skip', // not a test
-
- },
-
- 'language/function_type': {},
-
- 'language/covariant_override': {},
-
- 'language/function_type': {
- 'function_type50_test': fail,
- 'function_type58_test': fail,
- },
-
- 'codegen': {},
-
- 'corelib_2': {},
-
- 'corelib_2/regexp': {},
-
- 'lib/async': {
- 'async_await_zones_test': fail,
- 'first_regression_test': async_unittest,
- 'future_or_bad_type_test_implements_multi': fail,
- 'future_or_bad_type_test_none_multi': fail,
- 'future_or_non_strong_test': fail,
- 'future_test_none_multi': fail,
- 'future_timeout_test': async_unittest,
- 'intercept_schedule_microtask5_test': async_unittest,
- 'multiple_timer_test': async_unittest,
- 'futures_test': fail,
- 'schedule_microtask2_test': async_unittest,
- 'schedule_microtask3_test': async_unittest,
- 'schedule_microtask5_test': async_unittest,
- 'stream_controller_async_test': async_unittest,
- 'stream_first_where_test': async_unittest,
- 'stream_from_iterable_test': async_unittest,
- 'stream_iterator_test': async_unittest,
- 'stream_join_test': async_unittest,
- 'stream_last_where_test': async_unittest,
- 'stream_periodic2_test': async_unittest,
- 'stream_periodic3_test': async_unittest,
- 'stream_periodic4_test': async_unittest,
- 'stream_periodic5_test': async_unittest,
- 'stream_periodic6_test': async_unittest,
- 'stream_periodic_test': async_unittest,
- 'stream_single_test': async_unittest,
- 'stream_single_to_multi_subscriber_test': async_unittest,
- 'stream_state_helper': async_unittest,
- 'stream_state_nonzero_timer_test': async_unittest,
- 'stream_state_test': async_unittest,
- 'stream_subscription_as_future_test': async_unittest,
- 'stream_subscription_cancel_test': async_unittest,
- 'stream_timeout_test': async_unittest,
- 'stream_transform_test': async_unittest,
- 'stream_transformation_broadcast_test': async_unittest,
- 'stream_transformer_from_handlers_test': fail,
- 'timer_cancel1_test': async_unittest,
- 'timer_cancel2_test': async_unittest,
- 'timer_cancel_test': async_unittest,
- 'timer_isActive_test': async_unittest,
- 'timer_not_available_test': fail,
- 'timer_repeat_test': async_unittest,
- 'timer_test': async_unittest,
- 'zone_error_callback_test': fail,
- 'zone_run_unary_test': fail,
- },
-
- 'lib/collection': {},
-
- 'lib/convert': {
- 'base64_test_01_multi': 'slow',
- 'chunked_conversion_utf85_test': 'slow',
-
- 'encoding_test': skip_timeout,
-
- 'json_utf8_chunk_test': skip_timeout,
- 'latin1_test': skip_timeout,
-
- 'streamed_conversion_json_encode1_test': skip_timeout,
- 'streamed_conversion_json_utf8_decode_test': skip_timeout,
- 'streamed_conversion_json_utf8_encode_test': skip_timeout,
- 'streamed_conversion_utf8_decode_test': skip_timeout,
- 'streamed_conversion_utf8_encode_test': skip_timeout,
- 'utf85_test': skip_timeout,
- },
-
- 'lib/html': {
- 'async_spawnuri_test': async_unittest,
- 'async_test': async_unittest,
-
- // was https://github.com/dart-lang/sdk/issues/27578, needs triage
- 'audiocontext_test': is.chrome('<=54') ? fail : pass,
-
- 'cross_domain_iframe_test': async_unittest,
- 'cssstyledeclaration_test': async_unittest,
- 'css_test': async_unittest,
-
- // This is failing with a range error, I'm guessing because it's looking
- // for a stylesheet and the page has none.
- 'css_rule_list_test': 'fail',
-
- 'custom_element_method_clash_test': async_unittest,
- 'custom_element_name_clash_test': async_unittest,
- 'custom_elements_23127_test': async_unittest,
- 'custom_elements_test': async_unittest,
-
- // Please do not mark this test as fail. If your change breaks this test,
- // please look at the test for instructions on how to generate a new
- // golden file.
- 'debugger_test': firefox_fail,
-
- // https://github.com/dart-lang/sdk/issues/27579.
- 'element_classes_test': 'fail',
- 'element_classes_svg_test': 'fail',
-
- // Failure: 'Expected 56 to be in the inclusive range [111, 160].'.
- 'element_offset_test': 'fail',
-
- 'element_test': async_unittest,
- // This may no longer be a valid test?
- 'element_types_test': is.chrome('<=56') ? pass : fail,
- 'event_customevent_test': async_unittest,
- 'events_test': async_unittest,
- 'fileapi_test': async_unittest,
- 'filereader_test': async_unittest,
- 'fontface_loaded_test': async_unittest,
- 'fontface_test': firefox_fail,
- 'form_data_test': async_unittest,
- 'history_test': async_unittest,
- 'indexeddb_1_test': async_unittest,
- 'indexeddb_2_test': async_unittest,
- 'indexeddb_3_test': async_unittest,
- 'indexeddb_4_test': async_unittest,
- 'indexeddb_5_test': async_unittest,
-
- // was https://github.com/dart-lang/sdk/issues/27578, needs triage
- 'input_element_test': 'fail',
-
- 'interactive_test': async_unittest,
- 'isolates_test': async_unittest,
-
- 'js_interop_1_test': async_unittest,
-
- // The "typed literal" test fails because the object does not have "_c".
- 'js_util_test': 'fail',
- 'keyboard_event_test': async_unittest,
-
- // was https://github.com/dart-lang/sdk/issues/27578, needs triage
- 'mediasource_test': 'fail',
- 'media_stream_test': 'fail',
-
- // https://github.com/dart-lang/sdk/issues/29071
- 'messageevent_test': firefox_fail,
-
- 'mutationobserver_test': async_unittest,
- 'native_gc_test': async_unittest,
- 'postmessage_structured_test': async_unittest,
-
- // this is timing out on Chrome Canary only
- // pinning this skip in case it's a transient canary issue
- 'queryall_test': is.chrome('59') ? ['skip'] : ['slow'], // see sdk #27794
-
- 'request_animation_frame_test': async_unittest,
- 'resource_http_test': async_unittest,
-
- // was https://github.com/dart-lang/sdk/issues/27578, needs triage
- 'rtc_test': is.chrome('<=55') ? fail : pass,
-
- // https://github.com/dart-lang/sdk/issues/29071
- 'serialized_script_value_test': firefox_fail,
-
- 'shadow_dom_test': firefox_fail,
-
- // was https://github.com/dart-lang/sdk/issues/27578, needs triage
- 'speechrecognition_test': firefox_fail,
- 'text_event_test': firefox_fail,
-
- // was https://github.com/dart-lang/sdk/issues/27578, needs triage
- 'touchevent_test': 'fail',
-
- 'transferables_test': async_unittest,
- 'transition_event_test': async_unittest,
- 'url_test': async_unittest,
- 'websocket_test': async_unittest,
- 'websql_test': async_unittest,
- 'wheelevent_test': async_unittest,
- 'worker_api_test': async_unittest,
- 'worker_test': async_unittest,
-
- 'xhr_cross_origin_test': async_unittest,
- 'xhr_test': async_unittest,
-
- // Failing when it gets 3 instead of 42.
- 'js_typed_interop_default_arg_test_default_value_multi': 'fail',
- },
-
- 'lib/html/custom': {
- 'attribute_changed_callback_test': async_unittest,
- 'constructor_calls_created_synchronously_test': async_unittest,
- 'created_callback_test': async_unittest,
- 'entered_left_view_test': async_unittest,
- 'js_custom_test': async_unittest,
- 'mirrors_test': async_unittest,
- 'regress_194523002_test': async_unittest,
- },
-
- 'lib/math': {
- // TODO(het): triage
- 'double_pow_test': fail,
- 'low_test': fail,
- 'pi_test': skip_timeout,
- 'random_big_test': fail,
- },
-
- 'lib/typed_data': {
- // No bigint or int64 support
- 'int32x4_bigint_test': fail,
- 'int64_list_load_store_test': fail,
- 'typed_data_hierarchy_int64_test': fail,
- 'typed_data_list_test': fail,
- },
-
- 'lib/mirrors': {
- 'abstract_class_test_none_multi': fail,
- 'accessor_cache_overflow_test': fail,
- 'basic_types_in_dart_core_test': fail,
- 'class_mirror_location_test': fail,
- 'class_mirror_type_variables_test': fail,
- 'closurization_equivalence_test': fail,
- 'constructor_kinds_test_01_multi': fail,
- 'constructor_kinds_test_none_multi': fail,
- 'constructor_private_name_test': fail,
- 'declarations_type_test': fail,
- 'deferred_mirrors_metadata_test': skip_timeout,
- 'deferred_mirrors_metatarget_test': skip_timeout,
- 'deferred_mirrors_update_test': fail,
- 'empty_test': fail,
- 'equality_test': fail,
- 'fake_function_with_call_test': fail,
- 'field_type_test': fail,
- 'function_type_mirror_test': fail,
- 'generic_f_bounded_test_01_multi': fail,
- 'generic_f_bounded_test_none_multi': fail,
- 'generic_function_typedef_test': fail,
- 'generic_interface_test_none_multi': fail,
- 'generic_local_function_test': fail,
- 'generic_mixin_applications_test': fail,
- 'generic_mixin_test': fail,
- 'generic_superclass_test_01_multi': fail,
- 'generic_superclass_test_none_multi': fail,
- 'generic_type_mirror_test': fail,
- 'generics_double_substitution_test_01_multi': fail,
- 'generics_double_substitution_test_none_multi': fail,
- 'generics_dynamic_test': fail,
- 'generics_special_types_test': fail,
- 'generics_substitution_test': fail,
- 'generics_test_none_multi': fail,
- 'globalized_closures2_test_00_multi': fail,
- 'globalized_closures2_test_none_multi': fail,
- 'globalized_closures_test_00_multi': fail,
- 'globalized_closures_test_none_multi': fail,
- 'hot_get_field_test': fail,
- 'hot_set_field_test': fail,
- 'inherited_metadata_test': fail,
- 'instance_members_unimplemented_interface_test': fail,
- 'instance_members_with_override_test': fail, // JsClassMirror.instanceMembers unimplemented
- 'instantiate_abstract_class_test': fail,
- 'invocation_fuzz_test_emptyarray_multi': fail,
- 'invocation_fuzz_test_false_multi': fail,
- 'invocation_fuzz_test_none_multi': fail,
- 'invocation_fuzz_test_smi_multi': fail,
- 'invocation_fuzz_test_string_multi': fail,
- 'invoke_call_on_closure_test': fail,
- 'invoke_closurization2_test': fail,
- 'invoke_closurization_test': fail,
- 'invoke_import_test': fail,
- 'invoke_named_test_01_multi': fail,
- 'invoke_named_test_none_multi': fail,
- 'invoke_natives_malicious_test': fail,
- 'invoke_private_test': fail,
- 'invoke_private_wrong_library_test': fail,
- 'invoke_test': fail,
- 'invoke_throws_test': fail,
- 'libraries_test': fail,
- 'library_imports_bad_metadata_test_none_multi': fail,
- 'library_metadata_test': fail,
- 'library_uri_io_test': async_unittest,
- 'library_uri_package_test': async_unittest,
- 'list_constructor_test_01_multi': fail,
- 'list_constructor_test_none_multi': fail,
- 'load_library_test': fail,
- 'local_function_is_static_test': fail,
- 'local_isolate_test': fail,
- 'metadata_allowed_values_test_none_multi': fail,
- 'metadata_scope_test_none_multi': fail,
- 'metadata_test': fail,
- 'method_mirror_location_test': fail,
- 'method_mirror_returntype_test': fail,
- 'method_mirror_source_line_ending_test': fail,
- 'method_mirror_source_test': fail,
- 'mirrors_reader_test': fail,
- 'mirrors_used_typedef_declaration_test_01_multi': fail,
- 'mirrors_used_typedef_declaration_test_none_multi': fail,
- 'mixin_test': fail,
- 'null2_test': fail,
- 'null_test': fail,
- 'other_declarations_location_test': fail,
- 'parameter_annotation_mirror_test': fail,
- 'parameter_is_const_test_none_multi': fail,
- 'parameter_metadata_test': fail,
- 'private_class_field_test': fail,
- 'private_symbol_mangling_test': fail,
- 'private_types_test': fail,
- 'reflect_class_test_none_multi': fail,
- 'reflect_runtime_type_test': fail,
- 'reflect_uninstantiated_class_test': fail,
- 'reflected_type_classes_test_none_multi': fail,
- 'reflected_type_function_type_test': fail,
- 'reflected_type_special_types_test': fail,
- 'reflected_type_test_none_multi': fail,
- 'reflected_type_typedefs_test': fail,
- 'reflected_type_typevars_test': fail,
- 'regress_14304_test': fail,
- 'regress_26187_test': fail,
- 'relation_assignable_test': fail,
- 'relation_subtype_test': fail,
- 'set_field_with_final_test': fail,
- 'set_field_with_final_inheritance_test': fail,
- 'symbol_validation_test_01_multi': fail,
- 'symbol_validation_test_none_multi': fail,
- 'to_string_test': fail,
- 'type_argument_is_type_variable_test': fail,
- 'type_variable_is_static_test': fail,
- 'type_variable_owner_test_01_multi': fail,
- 'type_variable_owner_test_none_multi': fail,
- 'typedef_deferred_library_test': fail, // Isolate spawn not support
- 'typedef_library_test': fail,
- 'typedef_metadata_test': fail,
- 'typedef_test': fail,
- 'typevariable_mirror_metadata_test': fail,
- 'unnamed_library_test': fail,
- 'variable_is_const_test_none_multi': fail,
- },
- };
-
- function countMatches(text, regex) {
- let matches = text.match(regex);
- return matches ? matches.length : 0;
- }
- function libraryName(name) {
- return name.replace(/-/g, '$45');
- }
-
- let unittest_tests = [];
- let unittestAccidentallyInitialized = false;
-
- // Pattern for selecting out generated test files in sub-directories
- // of the codegen directory. These are the language, corelib, etc
- // tests
- let languageTestPattern =
- new RegExp('gen/codegen_output/(.*)/([^/]*_test[^/]*)');
- // Pattern for selecting out generated test files in the toplevel
- // codegen directory. These are codegen tests that should be
- // executed.
- let codegenTestPattern =
- new RegExp('gen/codegen_output/([^/]*_test[^/]*)');
- // We need to let Dart unittest control when tests are run not mocha.
- // mocha.allowUncaught(true);
- for (let testFile of allTestFiles) {
- let status_group;
- let name;
- let module;
- let match = languageTestPattern.exec(testFile);
- if (match != null) {
- status_group = match[1];
- name = match[2];
- module = match[0];
- } else if ((match = codegenTestPattern.exec(testFile)) != null) {
- status_group = 'codegen';
- name = match[1];
- module = match[0];
- }
- if (match != null) {
- let status = all_status[status_group];
- if (status == null) throw "No status for '" + status_group + "'";
-
- let expectation = status[name];
- if (expectation == null) expectation = [];
- if (typeof expectation == 'string') expectation = [expectation];
- let has = (tag) => expectation.indexOf(tag) >= 0;
-
- if (has('skip')) {
- let why = 'for unknown reason';
- if (has('timeout')) why = 'known timeout';
- if (has('fail')) why = 'known failure';
- console.debug('Skipping ' + why + ': ' + name);
- continue;
- }
-
- // A few tests are special because they use package:unittest.
- // We run them below.
- let mainLibrary = require(module)[libraryName(name)];
- if (mainLibrary._usesUnittestPackage) {
- unittest_tests.push(() => {
- console.log('Running unittest test ' + testFile);
- mainLibrary.main();
- });
- continue;
- }
-
- var fullName = status_group + '/' + name;
- test(fullName, function(done) { // 'function' to allow `this.timeout`.
- console.debug('Running test: ' + fullName);
-
- // Many tests are async. Currently, tests can indicate this in
- // two different ways. First, `main` can call (in Dart)
- // `async_helper.asyncStart`. We can check if this happened by
- // querying `async_helper.asyncTestStarted` afterward and waiting for
- // the callback if so. Second, `main` can return a `Future`. If so,
- // we wait for that to complete. If neither is true, we assume the
- // test is synchronous.
- //
- // A 'failing' test will throw an exception. This exception may be
- // synchronous (i.e., during `main`) or asynchronous (after `main` in
- // lieu of the callback/future). The latter exceptions are not
- // directly caught. Instead, we intercept `window.onerror` to detect
- // them.
- //
- // Note, if the test is marked 'negative' or 'fail', than pass and fail
- // are effectively inverted: only a success is reported.
- //
- // In all cases, we funnel test completion through the `finish` handler
- // below to handle reporting (based on status) and cleanup state.
- //
- // A test can finish in one of several ways:
- // 1. Synchronous without an error. In this case, `main` returns
- // null and did not set `async_helper`. `finish` is invoked
- // immediately.
- // 2. Synchronous error. `main` throws an error. `finish`
- // is invoked immediately with the error.
- // 3. `Future` without an error. In this case, the future completes
- // and asynchronously invokes `finish`.
- // 4. Via `async_helper` without an error. In this case, the
- // `async_helper` library triggers `finish` via its callback.
- // 5. Asynchronously with an error. In this case, `window.onerror`
- // triggers `finish` with the error.
- // 6. Hangs. In this case, we rely on the underlying mocha framework
- // timeout.
- //
- // TODO(vsm): This currently doesn't handle tests that trigger multiple
- // asynchronous exceptions.
-
- let negative = /negative_test/.test(name) ||
- mainLibrary._expectRuntimeError;
- let fail = has('fail');
-
- function finish(error) {
- // If the test left any lingering detritus in the DOM, blow it away
- // so it doesn't interfere with later tests.
- if (fail) {
- if (negative) {
- if (error) {
- error = new Error(
- "negative test marked as 'fail' " +
- "but passed by throwing:\n" + error);
- }
- } else if (error) {
- error = null
- } else {
- error = new Error("test marked as 'fail' but passed");
- }
- } else if (negative) {
- if (!error) {
- error = new Error("test marked as 'negative' but did not throw");
- } else {
- error = null;
- }
- }
- minitest.finishTests();
- document.body.innerHTML = '';
- console.log("cleared");
- if (error && !(error instanceof Error)) error = new Error(error);
- done(error);
- }
-
- // Intercept uncaught exceptions
- window.onerror = function(message, url, line, column, error) {
- console.warn('Asynchronous error in ' + name + ': ' + message);
- if (!error) {
- error = new Error(message);
- }
- finish(error);
- };
-
- async_helper.asyncTestInitialize(finish);
- if (has('slow')) this.timeout(10000);
-
- var result;
- try {
- var result = mainLibrary.main();
- if (result && !(dart_sdk.async.Future.is(result))) {
- result = null;
- }
- } catch (e) {
- finish(e);
- }
-
- // Ensure this isn't a unittest
- if (!unittestAccidentallyInitialized &&
- unittest.src__test_environment.environment.initialized) {
- // This suppresses duplicate messages for later tests
- unittestAccidentallyInitialized = true;
- finish(new Error('Test ' + name + ' must be marked as a unittest'));
- } else if (!async_helper.asyncTestStarted) {
- if (!result) {
- finish();
- } else {
- result.then(dart_sdk.dart.dynamic)(() => finish(),
- { onError: (e) => finish(e) });
- }
- }
- });
- }
- }
-
- // We run these tests in a mocha test wrapper to avoid the confusing failure
- // case of dart unittests being interleaved with mocha tests.
- // In practice we are really just suppressing all mocha test behavior while
- // Dart unittests run and then re-enabling it when the dart tests complete.
- html_config.useHtmlConfiguration();
- test('run all dart unittests', function(done) { // 'function' to allow `this.timeout`
- // Use the whitelist for all unittests - there may be an error in the framework
- // itself.
- dart_sdk.dart.ignoreWhitelistedErrors(true);
- if (unittest_tests.length == 0) return done();
-
- // TODO(vsm): We're using an old deprecated version of unittest.
- // We need to migrate all tests (in the SDK itself) off of
- // unittest.
-
- // All unittests need to be explicitly marked as such above. If
- // not, the unittest framework will be run in a 'normal' test and
- // left in an inconsistent state at this point triggering spurious
- // failures. This check ensures we're not in such a state. If it fails,
- // we've likely added a new unittest and need to categorize it as such.
- if (unittest.src__test_environment.environment.testCases[dart_sdk.dartx.length] != 0) {
- return done(new Error('Unittest framework in an invalid state'));
- }
-
- this.timeout(100000000);
- this.enableTimeouts(false);
- // Suppress mocha on-error handling because it will mess up unittests.
- window.onerror = function(err, url, line) {
- console.error(err, url, line);
- };
- window.addEventListener('message', (event) => {
- if (event.data == 'unittest-suite-done') {
- window.console.log("Done running unittests");
- let output = document.body.textContent;
- // Restore the Mocha onerror handler in case future tests need to run.
- window.onerror = mochaOnError;
- this.enableTimeouts(true);
- dart_sdk.dart.ignoreWhitelistedErrors(false);
-
- let numErrors = countMatches(output, /\d\s+ERROR/g);
- let numFails = countMatches(output, /\d\s+FAIL/g);
- if (numErrors != num_expected_unittest_errors ||
- numFails != num_expected_unittest_fails) {
- output = "Expected " + num_expected_unittest_fails +
- " fail and " + num_expected_unittest_errors +
- " error unittests, got " + numFails + " fail and " +
- numErrors + "error tests.\n" + output;
- console.error(output);
- done(new Error(output));
- } else {
- console.log(output);
- done();
- }
- }
- });
-
- for (let action of unittest_tests) {
- try {
- action();
- } catch (e) {
- console.error("Caught error tying to setup test:", e);
- }
- }
- });
-});
diff --git a/pkg/dev_compiler/test/browser/runtime_tests.js b/pkg/dev_compiler/test/browser/runtime_tests.js
deleted file mode 100644
index a4b29fe..0000000
--- a/pkg/dev_compiler/test/browser/runtime_tests.js
+++ /dev/null
@@ -1,1254 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-define(['dart_sdk'], function(dart_sdk) {
- const assert = chai.assert;
- const async = dart_sdk.async;
- const core = dart_sdk.core;
- const collection = dart_sdk.collection;
- const dart = dart_sdk.dart;
- const dartx = dart.dartx;
-
- dart.trapRuntimeErrors(false);
-
- suite('ignore', () => {
- "use strict";
-
- let FutureOr = async.FutureOr$;
- let Future = async.Future$;
- let List = core.List$;
-
- setup(() => {
- dart_sdk.dart.ignoreWhitelistedErrors(false);
- });
-
- teardown(() => {
- dart_sdk.dart.ignoreWhitelistedErrors(false);
- });
-
- test('FutureOr', () => {
- let f = Future(dart.dynamic).value(42);
- let l = [1, 2, 3];
-
- assert.throws(() => { dart.as(f, FutureOr(core.int)); });
- assert.throws(() => { dart.as(l, FutureOr(List(core.int)))});
-
- dart_sdk.dart.ignoreWhitelistedErrors(true);
- assert.equal(f, dart.as(f, FutureOr(core.int)));
- assert.equal(l, dart.as(l, FutureOr(List(core.int))));
- });
- });
-
- suite('generic', () => {
- "use strict";
-
- let generic = dart.generic;
-
- test('zero arguments is not allowed', () => {
- assert.throws(() => { generic(function(){}); });
- });
-
- test('dcall noSuchMethod has correct error target', () => {
- assert.throws(() => dart.dcall(42),
- new RegExp('NoSuchMethodError.*\nReceiver: 42', 'm'),
- 'Calls with non-function receiver should throw a NoSuchMethodError' +
- ' with correct target');
-
- // TODO(jmesserly): we should show the name "print" in there somewhere.
- assert.throws(() => dart.dcall(core.print, 1, 2, 3),
- new RegExp('NoSuchMethodError.*\n' +
- "Receiver: Instance of '\\(Object\\) -> void'", 'm'),
- 'Calls with incorrect argument types should throw a NoSuchMethodError' +
- ' with correct target');
- });
-
- test('can throw number', () => {
- try {
- dart.throw(42);
- } catch (e) {
- assert.equal(e, 42);
- }
- });
-
- test('argument count cannot change', () => {
- let SomeType = generic(function(x) { return {x: x}; });
- assert.throws(() => { SomeType(1,2) });
- let obj = {};
- assert.equal(SomeType(obj).x, obj);
- assert.equal(SomeType(obj).x, obj);
- assert.equal(SomeType().x, dart.dynamic);
- });
-
- test('undefined/null are not allowed', () => {
- let SomeType = generic(function(x) {});
- assert.throws(() => { SomeType(void 0) });
- SomeType(1);
- assert.throws(() => { SomeType(void 0) });
- SomeType(1);
- assert.throws(() => { SomeType(null) });
- });
-
- test('result is memoized', () => {
- let t1 = Object.create(null);
- let t2 = Object.create(null);
-
- let count = 0;
- let SomeType = generic(function(x, y) {
- count++;
- return Object.create(null);
- });
-
- let x12 = SomeType(1, 2);
- assert.strictEqual(SomeType(1, 2), x12);
- assert.strictEqual(SomeType(1, 2), x12);
- assert.strictEqual(count, 1);
- let x11 = SomeType(1, 1);
- assert.strictEqual(count, 2);
- assert.strictEqual(SomeType(1, 1), x11);
- assert.strictEqual(count, 2);
- count = 0;
-
- let t1t2 = SomeType(t1, t2);
- assert.strictEqual(count, 1);
- let t2t1 = SomeType(t2, t1);
- assert.strictEqual(count, 2);
- assert.notStrictEqual(t1t2, t2t1);
- assert.strictEqual(SomeType(t1, t2), t1t2);
- assert.strictEqual(SomeType(t2, t1), t2t1);
- assert.strictEqual(SomeType(t1, t2), t1t2);
- count = 0;
-
- // Nothing has been stored on the object
- assert.strictEqual(Object.keys(t1).length, 0);
- assert.strictEqual(Object.keys(t2).length, 0);
- });
-
- test('type constructor is reflectable', () => {
- let SomeType = generic(function(x, y) { return Object.create(null); });
- let someValue = SomeType('hi', 123);
- assert.equal(dart.getGenericClass(someValue), SomeType);
- assert.deepEqual(dart.getGenericArgs(someValue), ['hi', 123]);
- });
-
- test('proper type constructor is called', () => {
- // This tests https://github.com/dart-lang/dev_compiler/issues/178
- let l = dart_sdk._interceptors.JSArray$(core.int).of([1, 2, 3]);
- let s = l[dartx.join]();
- assert.equal(s, '123');
- });
- });
-
-
- suite('instanceOf', () => {
- "use strict";
-
- let expect = assert.equal;
- let generic = dart.generic;
- let intIsNonNullable = false;
- let cast = dart.as;
- let instanceOf = dart.is;
- let strongInstanceOf = dart.strongInstanceOf;
- let getReifiedType = dart.getReifiedType;
- let fnTypeFuzzy = dart.fnTypeFuzzy;
- let typedef = dart.typedef;
- let isSubtype = dart.isSubtype;
-
- let Object = core.Object;
- let String = core.String;
- let dynamic = dart.dynamic;
- let List = core.List;
- let Map = core.Map;
- let Map$ = core.Map$;
- let double = core.double;
- let int = core.int;
- let num = core.num;
- let bool = core.bool;
-
- class A {}
- class B extends A {}
- class C extends B {}
-
- let AA$ = generic((T, U) => {
- class AA extends core.Object {}
- (AA.new = function() {}).prototype = AA.prototype;
- return AA;
- });
- let AA = AA$();
- let BB$ = generic((T, U) => {
- class BB extends AA$(U, T) {}
- (BB.new = function() {}).prototype = BB.prototype;
- return BB;
- });
- let BB = BB$();
- class CC extends BB$(String, List) {}
- (CC.new = function() {}).prototype = CC.prototype;
-
- let Func2 = typedef('Func2', () => fnTypeFuzzy(dynamic, [dynamic, dynamic]));
- let Foo = typedef('Foo', () => fnTypeFuzzy(B, [B, String]));
-
- let FuncG$ = generic((T, U) => typedef('FuncG', () => fnTypeFuzzy(T, [T, U])))
- let FuncG = FuncG$();
-
- // TODO(vsm): Revisit when we encode types on functions properly.
- // A bar1(C c, String s) => null;
- function bar1(c, s) { return null; }
- dart.fn(bar1, dart.fnType(A, [C, String]));
-
- // bar2(B b, String s) => null;
- function bar2(b, s) { return null; }
- dart.fn(bar2, dart.fnType(dynamic, [B, String]));
-
- // B bar3(B b, Object o) => null;
- function bar3(b, o) { return null; }
- dart.fn(bar3, dart.fnType(B, [B, Object]));
-
- // B bar4(B b, o) => null;
- function bar4(b, o) { return null; }
- dart.fn(bar4, dart.fnType(B, [B, dynamic]));
-
- // C bar5(A a, Object o) => null;
- function bar5(a, o) { return null; }
- dart.fn(bar5, dart.fnType(C, [A, Object]));
-
- // B bar6(B b, String s, String o) => null;
- function bar6(b, s, o) { return null; }
- dart.fn(bar6, dart.fnType(B, [B, String, String]));
-
- // B bar7(B b, String s, [Object o]) => null;
- function bar7(b, s, o) { return null; }
- dart.fn(bar7, dart.fnType(B, [B, String], [Object]));
-
- // B bar8(B b, String s, {Object p}) => null;
- function bar8(b, s, o) { return null; }
- dart.fn(bar8, dart.fnType(B, [B, String], {p: Object}));
-
- let cls1 = dart.fn((c, s) => { return null; },
- dart.fnType(A, [C, String]));
-
- let cls2 = dart.fn((b, s) => { return null; },
- dart.fnType(dynamic, [B, String]));
-
- let cls3 = dart.fn((b, o) => { return null; },
- dart.fnType(B, [B, Object]));
-
- let cls4 = dart.fn((b, o) => { return null; },
- dart.fnType(B, [B, dynamic]));
-
- let cls5 = dart.fn((a, o) => { return null; },
- dart.fnType(C, [A, Object]));
-
- let cls6 = dart.fn((b, s, o) => { return null; },
- dart.fnType(B, [B, String, String]));
-
- let cls7 = dart.fn((b, s, o) => { return null; },
- dart.fnType(B, [B, String], [Object]));
-
- let cls8 =
- dart.fn((b, s, o) => { return null; },
- dart.fnType(B, [B, String], {p: Object}));
-
- function checkType(x, type, expectedTrue) {
- if (expectedTrue === undefined) expectedTrue = true;
- expect(instanceOf(x, type), expectedTrue,
- '"' + x + '" ' +
- (expectedTrue ? 'should' : 'should not') +
- ' be an instance of "' + dart.typeName(type) + '"');
- }
-
- test('int', () => {
- checkType(5, int);
- checkType(5, dynamic);
- checkType(5, Object);
- checkType(5, num);
-
- checkType(5, bool, false);
- checkType(5, String, false);
-
- expect(cast(5, int), 5);
- if (intIsNonNullable) {
- expect(() => cast(null, int), throws);
- } else {
- expect(cast(null, int), null);
- }
- });
-
- test('dynamic', () => {
- checkType(new Object.new(), dynamic);
- checkType(null, dynamic);
-
- expect(cast(null, dynamic), null);
- });
-
- test('Object', () => {
- checkType(new Object.new(), dynamic);
- checkType(null, Object);
-
- expect(cast(null, Object), null);
- });
-
- test('null', () => {
- // Object, dynamic cases are already handled above.
- checkType(null, core.Null);
- checkType(null, core.String, false);
- checkType(null, core.int, false);
- checkType(null, Map, false);
- checkType(void 0, core.Null);
- checkType(void 0, core.Object);
- checkType(void 0, dart.dynamic);
- });
-
- test('String', () => {
- checkType("foo", String);
- checkType("foo", Object);
- checkType("foo", dynamic);
-
- expect(cast(null, String), null);
- });
-
- test('FutureOr', () => {
- let FutureOr = async.FutureOr$;
-
- assert.equal(dart.as(3, FutureOr(int)), 3);
- assert.equal(dart.as(3, FutureOr(double)), 3);
- assert.throws(() => dart.as(3.5, FutureOr(int)));
- assert.equal(dart.as(3.5, FutureOr(double)), 3.5);
- assert.isTrue(dart.is(3, FutureOr(int)));
- assert.isTrue(dart.is(3, FutureOr(double)));
- assert.isFalse(dart.is(3.5, FutureOr(int)));
- assert.isTrue(dart.is(3.5, FutureOr(double)));
-
- assert.equal(dart.as(3, FutureOr(FutureOr(double))), 3);
- assert.isTrue(dart.is(3, FutureOr(FutureOr(double))));
-
- });
-
- test('Map', () => {
- let m1 = Map$(String, String).new();
- let m2 = Map$(Object, Object).new();
- let m3 = Map.new();
- let m4 = collection.HashMap$(dart.dynamic, dart.dynamic).new();
- let m5 = collection.LinkedHashMap.new();
- let m6 = Map$(String, dart.dynamic).new();
-
- // Map<T1,T2> <: Map
- checkType(m1, Map);
- checkType(m1, Object);
-
- // Instance of self
- checkType(m1, getReifiedType(m1));
- checkType(m1, Map$(String, String));
-
- // Covariance on generics
- checkType(m1, getReifiedType(m2));
- checkType(m1, Map$(Object, Object));
-
- // No contravariance on generics.
- checkType(m2, getReifiedType(m1), false);
- checkType(m2, Map$(String, String), false);
-
- // null is! Map
- checkType(null, Map, false);
-
- // Raw generic types
- checkType(m5, Map);
- checkType(m4, Map);
-
- // Is checks
- assert.isFalse(dart.is(m3, Map$(String, String)));
- assert.isFalse(dart.is(m6, Map$(String, String)));
- assert.isTrue(dart.is(m1, Map$(String, String)));
- assert.isFalse(dart.is(m2, Map$(String, String)));
-
- // As checks
- // TODO(vsm): Enable these. We're currently only logging warnings on
- // StrongModeErrors.
- // assert.throws(() => dart.as(m3, Map$(String, String)),
- // dart.StrongModeError);
- // assert.throws(() => dart.as(m6, Map$(String, String)),
- // dart.StrongModeError);
- assert.equal(dart.as(m1, Map$(String, String)), m1);
- // assert.throws(() => dart.as(m2, Map$(String, String)),
- // dart.StrongModeError);
- });
-
- test('constructors', () => {
- class C extends core.Object {
- }
- (C.new = function(x) {}).prototype = C.prototype;
- (C.named = function(x, y) {}).prototype = C.prototype;
- dart.setSignature(C, {
- constructors: () => ({
- new: dart.fnType(C, [core.int]),
- named: dart.fnType(C, [core.int, core.int])
- })
- });
- let getType = dart.classGetConstructorType;
- isSubtype(getType(C), dart.fnTypeFuzzy(C, [core.int]));
- isSubtype(getType(C), dart.fnTypeFuzzy(C, [core.String]), false);
- isSubtype(getType(C, 'new'), dart.fnTypeFuzzy(C, [core.int]));
- isSubtype(getType(C, 'new'), dart.fnTypeFuzzy(C, [core.String]), false);
- isSubtype(getType(C, 'named'), dart.fnTypeFuzzy(C, [core.int, core.int]));
- isSubtype(getType(C, 'named'),
- dart.fnTypeFuzzy(C, [core.int, core.String]), false);
- });
-
- test('generic and inheritance', () => {
- let aaraw = new AA.new();
- let aarawtype = getReifiedType(aaraw);
- let aadynamic = new (AA$(dynamic, dynamic).new)();
- let aadynamictype = getReifiedType(aadynamic);
- let aa = new (AA$(String, List).new)();
- let aatype = getReifiedType(aa);
- let bb = new (BB$(String, List).new)();
- let bbtype = getReifiedType(bb);
- let cc = new CC.new();
- let cctype = getReifiedType(cc);
- // We don't allow constructing bad types.
- // This was AA<String> in Dart (wrong number of type args).
- let aabad = new (AA$(dart.dynamic, dart.dynamic).new)();
- let aabadtype = getReifiedType(aabad);
-
- checkType(cc, aatype, false);
- checkType(cc, AA$(String, List), false);
- checkType(cc, bbtype);
- checkType(cc, BB$(String, List));
- checkType(aa, cctype, false);
- checkType(aa, CC, false);
- checkType(aa, bbtype, false);
- checkType(aa, BB$(String, List), false);
- checkType(bb, cctype, false);
- checkType(bb, CC, false);
- checkType(aa, aabadtype);
- checkType(aa, dynamic);
- checkType(aabad, aatype, false);
- checkType(aabad, AA$(String, List), false);
- checkType(aabad, aarawtype);
- checkType(aabad, AA);
- checkType(aaraw, aabadtype);
- checkType(aaraw, AA$(dart.dynamic, dart.dynamic));
- checkType(aaraw, aadynamictype);
- checkType(aaraw, AA$(dynamic, dynamic));
- checkType(aadynamic, aarawtype);
- checkType(aadynamic, AA);
- });
-
- test('void', () => {
- //checkType((x) => x, type((void _(x)) {}));
- });
-
- test('mixins', () => {
- let c = collection;
- var s1 = new (c.SplayTreeSet$(String).new)();
-
- checkType(s1, c.IterableMixin);
- checkType(s1, c.IterableMixin$(String));
- checkType(s1, c.IterableMixin$(int), false);
-
- checkType(s1, c.SetMixin);
- checkType(s1, c.SetMixin$(String));
- checkType(s1, c.SetMixin$(int), false);
- });
-
- test('Type', () => {
- checkType(int, core.Type, true);
- checkType(num, core.Type, true);
- checkType(bool, core.Type, true);
- checkType(String, core.Type, true);
- checkType(dynamic, core.Type, true);
- checkType(Object, core.Type, true);
- checkType(List, core.Type, true);
- checkType(Map, core.Type, true);
- checkType(Map$(int, String), core.Type, true);
- checkType(Func2, core.Type, true);
- checkType(fnTypeFuzzy(dynamic, [dynamic]), core.Type, true);
- checkType(core.Type, core.Type, true);
-
- checkType(3, core.Type, false);
- checkType("hello", core.Type, false);
- })
-
- test('Functions', () => {
- // - return type: Dart is bivariant. We're covariant.
- // - param types: Dart is bivariant. We're contravariant.
- checkType(bar1, Foo, false);
- checkType(cls1, Foo, false);
- checkType(bar1, fnTypeFuzzy(B, [B, String]), false);
- checkType(cls1, fnTypeFuzzy(B, [B, String]), false);
- checkType(bar2, Foo, false);
- checkType(cls2, Foo, false);
- checkType(bar2, fnTypeFuzzy(B, [B, String]), false);
- checkType(cls2, fnTypeFuzzy(B, [B, String]), false);
- checkType(bar3, Foo);
- checkType(cls3, Foo);
- checkType(bar3, fnTypeFuzzy(B, [B, String]));
- checkType(cls3, fnTypeFuzzy(B, [B, String]));
- checkType(bar4, Foo, true);
- checkType(cls4, Foo, true);
- checkType(bar4, fnTypeFuzzy(B, [B, String]), true);
- checkType(cls4, fnTypeFuzzy(B, [B, String]), true);
- checkType(bar5, Foo);
- checkType(cls5, Foo);
- checkType(bar5, fnTypeFuzzy(B, [B, String]));
- checkType(cls5, fnTypeFuzzy(B, [B, String]));
- checkType(bar6, Foo, false);
- checkType(cls6, Foo, false);
- checkType(bar6, fnTypeFuzzy(B, [B, String]), false);
- checkType(cls6, fnTypeFuzzy(B, [B, String]), false);
- checkType(bar7, Foo);
- checkType(cls7, Foo);
- checkType(bar7, fnTypeFuzzy(B, [B, String]));
- checkType(cls7, fnTypeFuzzy(B, [B, String]));
- checkType(bar7, getReifiedType(bar6));
- checkType(cls7, getReifiedType(bar6));
- checkType(bar8, Foo);
- checkType(cls8, Foo);
- checkType(bar8, fnTypeFuzzy(B, [B, String]));
- checkType(cls8, fnTypeFuzzy(B, [B, String]));
- checkType(bar8, getReifiedType(bar6), false);
- checkType(cls8, getReifiedType(bar6), false);
- checkType(bar7, getReifiedType(bar8), false);
- checkType(cls7, getReifiedType(bar8), false);
- checkType(bar8, getReifiedType(bar7), false);
- checkType(cls8, getReifiedType(bar7), false);
-
- // Parameterized typedefs
- checkType(bar1, FuncG$(B, String), false);
- checkType(cls1, FuncG$(B, String), false);
- checkType(bar3, FuncG$(B, String));
- checkType(cls3, FuncG$(B, String));
- });
-
- test('dcall', () => {
- function dd2d(x, y) {return x};
- dart.fn(dd2d);
- function ii2i(x, y) {return x};
- dart.fn(ii2i, dart.fnType(core.int, [core.int, core.int]));
- function ii_2i(x, y) {return x};
- dart.fn(ii_2i, dart.fnType(core.int, [core.int], [core.int]));
- function i_i2i(x, opts) {return x};
- dart.fn(i_i2i,
- dart.fnType(core.int, [core.int], {extra: core.int}));
-
- assert.equal(dart.dcall(dd2d, 0, 1), 0);
- assert.equal(dart.dcall(dd2d, "hello", "world"), "hello");
- assert.throws(() => dart.dcall(dd2d, 0));
- assert.throws(() => dart.dcall(dd2d, 0, 1, 2));
- assert.throws(() => dart.dcall(dd2d, 0, 1, {extra : 3}));
- // This should throw but currently doesn't.
- // assert.throws(() => dart.dcall(dd2d, 0, {extra:3}));
-
- assert.equal(dart.dcall(ii2i, 0, 1), 0);
- assert.throws(() => dart.dcall(ii2i, "hello", "world"));
- assert.throws(() => dart.dcall(ii2i, 0));
- assert.throws(() => dart.dcall(ii2i, 0, 1, 2));
-
- assert.equal(dart.dcall(ii_2i, 0, 1), 0);
- assert.throws(() => dart.dcall(ii_2i, "hello", "world"));
- assert.equal(dart.dcall(ii_2i, 0), 0);
- assert.throws(() => dart.dcall(ii_2i, 0, 1, 2));
-
- assert.throws(() => dart.dcall(i_i2i, 0, 1));
- assert.throws(() => dart.dcall(i_i2i, "hello", "world"));
- assert.equal(dart.dcall(i_i2i, 0), 0);
- assert.throws(() => dart.dcall(i_i2i, 0, 1, 2));
- assert.equal(dart.dcall(i_i2i, 0, {extra: 3}), 0);
- });
-
- test('dsend', () => {
- class Tester extends core.Object {
- m(x, y) {return x;}
- call(x) {return x;}
- static s(x, y) { return x;}
- }
- (Tester.new = function() {
- this.f = dart.fn(x => x,
- dart.fnType(core.int, [core.int]));
- this.me = this;
- }).prototype = Tester.prototype;
- dart.setSignature(Tester, {
- methods: () => ({
- m: dart.fnType(core.int, [core.int, core.int]),
- call: dart.fnType(core.int, [core.int])
- }),
- statics: () => ({
- s: dart.fnType(core.String, [core.String])
- }),
- names: ['s']
- })
- let o = new Tester.new();
-
- // Method send
- assert.equal(dart.dsend(o, 'm', 3, 4), 3);
- assert.equal(dart.dsend(o, 'm', null, 4), null);
- assert.throws(() => dart.dsend(o, 'm', 3));
- assert.throws(() => dart.dsend(o, 'm', "hello", "world"));
- assert.throws(() => dart.dsend(o, 'q', 3));
-
- // Method send through a field
- assert.equal(dart.dsend(o, 'f', 3), 3);
- assert.equal(dart.dsend(o, 'f', null), null);
- assert.throws(() => dart.dsend(o, 'f', "hello"));
- assert.throws(() => dart.dsend(o, 'f', 3, 4));
-
- // Static method call
- assert.equal(dart.dcall(Tester.s, "hello"), "hello");
- assert.equal(dart.dcall(Tester.s, null), null);
- assert.throws(() => dart.dcall(Tester.s, "hello", "world"));
- assert.throws(() => dart.dcall(Tester.s, 0, 1));
-
- // Calling an object with a call method
- assert.equal(dart.dcall(o, 3), 3);
- assert.equal(dart.dcall(o, null), null);
- assert.throws(() => dart.dcall(o, "hello"));
- assert.throws(() => dart.dcall(o, 3, 4));
-
- // Calling through a field containing an object with a call method
- assert.equal(dart.dsend(o, 'me', 3), 3);
- assert.equal(dart.dsend(o, 'me', null), null);
- assert.throws(() => dart.dsend(o, 'me', "hello"));
- assert.throws(() => dart.dsend(o, 'me', 3, 4));
- });
-
- test('Types on top level functions', () => {
- // Test some generated code
- // Test the lazy path
- checkType(core.identityHashCode,
- dart.fnTypeFuzzy(core.int, [core.Object]));
- // Test the normal path
- checkType(core.identical,
- dart.fnTypeFuzzy(core.bool,
- [core.Object, core.Object]));
-
- // Hand crafted tests
- // All dynamic
- function dd2d(x, y) {return x};
- dart.fn(dd2d);
- checkType(dd2d, dart.fnTypeFuzzy(dart.dynamic,
- [dart.dynamic, dart.dynamic]));
-
- // Set the type eagerly
- function ii2i(x, y) {return x};
- dart.fn(ii2i, dart.fnType(core.int, [core.int, core.int]));
- checkType(ii2i, dart.fnTypeFuzzy(core.int,
- [core.int, core.int]));
-
- // Set the type lazily
- function ss2s(x, y) {return x};
- var coreString;
- dart.lazyFn(ss2s,
- () => dart.fnType(coreString,
- [coreString, coreString]));
- coreString = core.String;
- checkType(ss2s, dart.fnTypeFuzzy(core.String,
- [core.String, core.String]));
-
- // Optional types
- function ii_2i(x, y) {return x};
- dart.fn(ii_2i, dart.fnType(core.int, [core.int], [core.int]));
- checkType(ii_2i, dart.fnTypeFuzzy(core.int, [core.int],
- [core.int]));
- checkType(ii_2i, dart.fnTypeFuzzy(core.int, [core.int,
- core.int]));
- checkType(ii_2i, dart.fnTypeFuzzy(core.int, [], [core.int,
- core.int]),
- false);
- checkType(ii_2i, dart.fnTypeFuzzy(core.int, [core.int],
- {extra: core.int}), false);
-
- // Named types
- function i_i2i(x, opts) {return x};
- dart.fn(i_i2i, dart.fnType(core.int, [core.int],
- {extra: core.int}));
- checkType(i_i2i, dart.fnTypeFuzzy(core.int, [core.int],
- {extra: core.int}));
- checkType(i_i2i, dart.fnTypeFuzzy(core.int,
- [core.int, core.int]), false);
- checkType(i_i2i, dart.fnTypeFuzzy(core.int, [core.int], {}));
- checkType(i_i2i,
- dart.fnTypeFuzzy(core.int, [], {extra: core.int,
- also: core.int}), false);
- checkType(i_i2i,
- dart.fnTypeFuzzy(core.int, [core.int], [core.int]), false);
- });
-
- test('Method tearoffs', () => {
- let c = collection;
- // Tear off of an inherited method
- let map = Map$(core.int, core.String).new();
- checkType(dart.bind(map, 'toString'),
- dart.fnTypeFuzzy(String, []));
- checkType(dart.bind(map, 'toString'),
- dart.fnTypeFuzzy(int, []), false, true);
-
- // Tear off of a method directly on the object
- let smap = new (c.SplayTreeMap$(core.int, core.String).new)();
- checkType(dart.bind(smap, 'forEach'),
- dart.fnTypeFuzzy(dart.void,
- [dart.fnTypeFuzzy(dart.void, [core.int, core.String])]));
- checkType(dart.bind(smap, 'forEach'),
- dart.fnTypeFuzzy(dart.void,
- [dart.fnTypeFuzzy(dart.void,
- [core.String, core.String])]), false, true);
-
- // Tear off of a mixed in method
- let mapB = new (c.MapBase$(core.int, core.int).new)();
- checkType(dart.bind(mapB, 'forEach'),
- dart.fnTypeFuzzy(dart.void, [
- dart.fnTypeFuzzy(dart.void, [core.int, core.int])]));
- checkType(dart.bind(mapB, 'forEach'),
- dart.fnTypeFuzzy(dart.void, [
- dart.fnTypeFuzzy(dart.void, [core.int, core.String])]),
- false, true);
-
- // Tear off of a method with a symbol name
- let listB = new (c.ListBase$(core.int).new)();
- // List.add is reified as taking Object
- checkType(dart.bind(listB, dartx.add),
- dart.fnTypeFuzzy(dart.void, [core.int]));
- checkType(dart.bind(listB, dartx.add),
- dart.fnTypeFuzzy(dart.void, [core.String]), true);
- checkType(dart.bind(listB, dartx.removeAt),
- dart.fnTypeFuzzy(dart.void, [core.String]), false);
-
- // Tear off of a static method
- checkType(c.ListBase.listToString,
- dart.fnTypeFuzzy(core.String, [core.List]));
- checkType(c.ListBase.listToString,
- dart.fnTypeFuzzy(core.String, [core.String]), false);
-
- // Tear-off of extension methods on primitives
- checkType(dart.bind(3.0, dartx.floor),
- dart.fnTypeFuzzy(core.int, []));
- checkType(dart.bind(3.0, dartx.floor),
- dart.fnTypeFuzzy(core.String, []), false);
- checkType(dart.bind("", dartx.endsWith),
- dart.fnTypeFuzzy(core.bool, [core.String]));
- checkType(dart.bind("", dartx.endsWith),
- dart.fnTypeFuzzy(core.bool, [core.int]), false);
-
- // Tear off a mixin method
- class Base {
- m(x) {return x;}
- };
- dart.setSignature(Base, {
- methods: () => ({
- m: dart.fnType(core.int, [core.int]),
- })
- });
-
- class M1 {
- m(x) {return x;}
- };
- dart.setSignature(M1, {
- methods: () => ({
- m: dart.fnType(core.num, [core.int]),
- })
- });
-
- class M2 {
- m(x) {return x;}
- };
- dart.setSignature(M2, {
- methods: () => ({
- m: dart.fnType(core.Object, [core.int]),
- })
- });
-
- class O extends dart.mixin(Base, M1, M2) {}
- (O.new = function() {}).prototype = O.prototype;
- dart.setSignature(O, {});
- var obj = new O.new();
- var m = dart.bind(obj, 'm');
- checkType(m, dart.fnTypeFuzzy(core.Object, [core.int]));
- checkType(m, dart.fnTypeFuzzy(core.int, [core.int]), false);
-
- // Test inherited signatures
- class P extends O {
- m(x) {return x;};
- };
- (P.new = function() {}).prototype = P.prototype;
- dart.setSignature(P, {});
- var obj = new P.new();
- var m = dart.bind(obj, 'm');
- checkType(m, dart.fnTypeFuzzy(core.Object, [core.int]));
- checkType(m, dart.fnTypeFuzzy(core.int, [core.int]), false);
- });
-
- test('Object members', () => {
- let nullHash = dart.hashCode(null);
- assert.equal(nullHash, 0);
- let nullString = dart.toString(null);
- assert.equal(nullString, 'null');
-
- let map = Map.new();
- let mapHash = dart.hashCode(map);
- checkType(mapHash, core.int);
- assert.equal(mapHash, map.hashCode);
-
- let mapString = dart.toString(map);
- assert.equal(mapString, map.toString());
- checkType(mapString, core.String);
-
- let str = "A string";
- let strHash = dart.hashCode(str);
- checkType(strHash, core.int);
-
- let strString = dart.toString(str);
- checkType(strString, core.String);
- assert.equal(str, strString);
-
- let n = 42;
- let intHash = dart.hashCode(n);
- checkType(intHash, core.int);
-
- let intString = dart.toString(n);
- assert.equal(intString, '42');
- });
- });
-
- suite('subtyping', function() {
- 'use strict';
-
- let fnTypeFuzzy = dart.fnTypeFuzzy;
- let fnType = dart.fnType;
- let typedef = dart.typedef;
- let isSubtype = dart.isSubtype;
- let int = core.int;
- let num = core.num;
- let dyn = dart.dynamic;
-
- function always(t1, t2) {
- assert.equal(isSubtype(t1, t2), true,
- dart.toString(t1) +
- " should always be a subtype of " +
- dart.toString(t2));
- }
- function never(t1, t2) {
- assert.equal(isSubtype(t1, t2), false,
- dart.toString(t1) +
- " should never be a subtype of " +
- dart.toString(t2));
- }
- function maybe(t1, t2) {
- assert.equal(isSubtype(t1, t2), null,
- dart.toString(t1) +
- " should maybe be a subtype of " +
- dart.toString(t2));
- }
-
- function always2(t1, t2) {
- always(t1, t2);
- always(fnTypeFuzzy(t1, [t2]), fnTypeFuzzy(t2, [t1]));
- }
- function never2(t1, t2) {
- never(t1, t2);
- maybe(fnTypeFuzzy(t1, [t2]), fnTypeFuzzy(t2, [t1]));
- }
- function maybe2(t1, t2) {
- maybe(t1, t2);
- maybe(fnTypeFuzzy(t1, [t2]), fnTypeFuzzy(t2, [t1]));
- }
-
- function run_test(func1, func2, func2opt, func1extra, func2extra) {
- always2(func2(int, int), func2(int, int));
- always2(func2(int, num), func2(int, int));
- always2(func2(int, int), func2(num, int));
-
- always2(func2opt(int, int), func2opt(int, int));
- always2(func2opt(int, num), func2opt(int, int));
- always2(func2opt(int, int), func2opt(num, int));
-
- always2(func2opt(int, int), func2(int, int));
- always2(func2opt(int, num), func2(int, int));
- always2(func2opt(int, int), func2(num, int));
-
- always2(func2opt(int, int), func1(int));
- always2(func2opt(int, num), func1(int));
- always2(func2opt(int, int), func1(num));
-
- always2(func2extra(int, int), func2(int, int));
- always2(func2extra(int, num), func2(int, int));
- always2(func2extra(int, int), func2(num, int));
-
- maybe2(func2(int, int), func2(int, num));
- maybe2(func2(num, int), func2(int, int));
-
- maybe2(func2opt(num, num), func1(int));
-
- maybe2(func2opt(int, int), func2opt(int, num));
- maybe2(func2opt(num, int), func2opt(int, int));
-
- maybe2(func2opt(int, int), func2(int, num));
- maybe2(func2opt(num, int), func2(int, int));
-
- maybe2(func2extra(int, int), func2(int, num));
- maybe2(func2extra(num, int), func2(int, int));
-
- never2(func1(int), func2(int, num));
- never2(func1(num), func2(int, int));
- never2(func1(num), func2(num, num));
-
- never2(func2(int, int), func1(int));
- never2(func2(num, int), func1(int));
- never2(func2(num, num), func1(num));
-
- never2(func1(int), func2opt(int, num));
- never2(func1(num), func2opt(int, int));
- never2(func1(num), func2opt(num, num));
-
- never2(func2(int, int), func2opt(int, num));
- never2(func2(num, int), func2opt(int, int));
- never2(func2(num, num), func2opt(num, num));
-
- never2(func1extra(int), func2(int, num));
- never2(func1extra(num), func2(int, int));
- never2(func1extra(num), func2(num, num));
-
- never2(func1extra(int), func2opt(int, num));
- never2(func1extra(num), func2opt(int, int));
- never2(func1extra(num), func2opt(num, num));
-
- never2(func1(int), func1extra(int));
- never2(func1(num), func1extra(int));
- never2(func1(num), func1extra(num));
-
- never2(func2(int, int), func1extra(int));
- never2(func2(num, int), func1extra(int));
- never2(func2(num, num), func1extra(num));
-
- never2(func2(int, int), func2extra(int, int));
- never2(func2(num, int), func2extra(int, int));
- never2(func2(num, num), func2extra(num, num));
- };
-
- test('basic function types', () => {
- function func1(S) {
- return fnTypeFuzzy(S, []);
- }
-
- function func2(S, T) {
- return fnTypeFuzzy(S, [T]);
- }
-
- function func2opt(S, T) {
- return fnTypeFuzzy(S, [], [T]);
- }
-
- function func1extra(S) {
- return fnTypeFuzzy(S, [], {extra: int});
- }
-
- function func2extra(S, T) {
- return fnTypeFuzzy(S, [T], {extra: int});
- }
-
- run_test(func1, func2, func2opt, func1extra, func2extra);
- });
-
- test('top and bottom types', () => {
- let FutureOr = async.FutureOr$;
- let tops = [
- dart.dynamic,
- core.Object,
- dart.void,
- FutureOr(dart.dynamic),
- FutureOr(core.Object),
- FutureOr(dart.void),
- FutureOr(FutureOr(core.Object)),
- // ... skip the (infinite) rest of the top types :D
- ];
- let bottoms = [dart.bottom, core.Null];
-
- for (let top of tops) {
- for (let bottom of bottoms) {
- always(bottom, top);
- always(
- fnType(bottom, [top]),
- fnType(top, [bottom]));
- }
- }
-
- for (let equalTypes of [tops, bottoms]) {
- for (let t1 of equalTypes) {
- for (let t2 of equalTypes) {
- always(t1, t2);
- always(t2, t1);
-
- let t11 = fnType(t1, [t1]);
- let t22 = fnType(t2, [t2]);
- always(t11, t22);
- always(t22, t11);
- }
- }
- }
- });
-
- test('basic typedefs', () => {
- function func1(S) {
- return dart.typedef('Func1', () => fnTypeFuzzy(S, []))
- }
-
- function func2(S, T) {
- return dart.typedef('Func2', () => fnTypeFuzzy(S, [T]))
- }
-
- function func2opt(S, T) {
- return dart.typedef('Func2', () => fnTypeFuzzy(S, [], [T]))
- }
-
- function func1extra(S) {
- return dart.typedef('Func1', () => fnTypeFuzzy(S, [], {extra: int}))
- }
-
- function func2extra(S, T) {
- return dart.typedef('Func2', () => fnTypeFuzzy(S, [T], {extra: int}))
- }
-
- run_test(func1, func2, func2opt, func1extra, func2extra);
- });
-
- test('basic generic typedefs', () => {
- let func1 = dart.generic(
- (S) => dart.typedef('Func1', () => fnTypeFuzzy(S, [])));
-
- let func2 = dart.generic(
- (S, T) => dart.typedef('Func2', () => fnTypeFuzzy(S, [T])));
-
- let func2opt = dart.generic(
- (S, T) => dart.typedef('Func2', () => fnTypeFuzzy(S, [], [T])));
-
- let func1extra = dart.generic(
- (S) => dart.typedef('Func1', () => fnTypeFuzzy(S, [], {extra: int})));
-
- let func2extra = dart.generic(
- (S, T) => dart.typedef('Func2',
- () => fnTypeFuzzy(S, [T], {extra: int})));
-
- run_test(func1, func2, func2opt, func1extra, func2extra);
- });
-
- test('fuzzy function types', () => {
- always(fnTypeFuzzy(int, [int]), fnTypeFuzzy(dyn, [dyn]));
- always(fnTypeFuzzy(int, [], [int]), fnTypeFuzzy(dyn, [], [dyn]));
- always(fnTypeFuzzy(int, [], [int]), fnTypeFuzzy(dyn, [dyn]));
- always(fnTypeFuzzy(int, [], [int]), fnTypeFuzzy(dyn, []));
- always(fnTypeFuzzy(int, [int], {extra: int}), fnTypeFuzzy(dyn, [dyn]));
-
- always(fnTypeFuzzy(dyn, [dyn]), fnTypeFuzzy(dyn, [dyn]));
- always(fnTypeFuzzy(dyn, [], [dyn]), fnTypeFuzzy(dyn, [], [dyn]));
- always(fnTypeFuzzy(dyn, [], [dyn]), fnTypeFuzzy(dyn, [dyn]));
- always(fnTypeFuzzy(dyn, [], [dyn]), fnTypeFuzzy(dyn, []));
- always(fnTypeFuzzy(dyn, [dyn], {extra: dyn}), fnTypeFuzzy(dyn, [dyn]));
- });
-
- test('void function types', () => {
- always(fnTypeFuzzy(int, [int]), fnTypeFuzzy(dart.void, [dyn]));
- always(fnTypeFuzzy(int, [], [int]), fnTypeFuzzy(dart.void, [], [dyn]));
- always(fnTypeFuzzy(int, [], [int]), fnTypeFuzzy(dart.void, [dyn]));
- always(fnTypeFuzzy(int, [], [int]), fnTypeFuzzy(dart.void, []));
- always(fnTypeFuzzy(int, [int], {extra: int}), fnTypeFuzzy(dart.void, [dyn]));
-
- always(fnTypeFuzzy(dart.void, [int]), fnTypeFuzzy(dart.void, [dyn]));
- always(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(dart.void, [], [dyn]));
- always(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(dart.void, [dyn]));
- always(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(dart.void, []));
- always(fnTypeFuzzy(dart.void, [int], {extra: int}), fnTypeFuzzy(dart.void, [dyn]));
-
- always(fnTypeFuzzy(dyn, [dyn]), fnTypeFuzzy(dart.void, [dyn]));
- always(fnTypeFuzzy(dyn, [], [dyn]), fnTypeFuzzy(dart.void, [], [dyn]));
- always(fnTypeFuzzy(dyn, [], [dyn]), fnTypeFuzzy(dart.void, [dyn]));
- always(fnTypeFuzzy(dyn, [], [dyn]), fnTypeFuzzy(dart.void, []));
- always(fnTypeFuzzy(dyn, [dyn], {extra: dyn}), fnTypeFuzzy(dart.void, [dyn]));
-
- always(fnTypeFuzzy(dart.void, [dyn]), fnTypeFuzzy(dart.void, [dyn]));
- always(fnTypeFuzzy(dart.void, [], [dyn]), fnTypeFuzzy(dart.void, [], [dyn]));
- always(fnTypeFuzzy(dart.void, [], [dyn]), fnTypeFuzzy(dart.void, [dyn]));
- always(fnTypeFuzzy(dart.void, [], [dyn]), fnTypeFuzzy(dart.void, []));
- always(fnTypeFuzzy(dart.void, [dyn], {extra: dyn}), fnTypeFuzzy(dart.void, [dyn]));
-
- always(fnTypeFuzzy(dart.void, [int]), fnTypeFuzzy(dyn, [dyn]));
- always(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(dyn, [], [dyn]));
- always(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(dyn, [dyn]));
- always(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(dyn, []));
- always(fnTypeFuzzy(dart.void, [int], {extra: int}), fnTypeFuzzy(dyn, [dyn]));
-
- never(fnTypeFuzzy(dart.void, [int]), fnTypeFuzzy(int, [dyn]));
- never(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(int, [], [dyn]));
- never(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(int, [dyn]));
- never(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(int, []));
- never(fnTypeFuzzy(dart.void, [int], {extra: int}), fnTypeFuzzy(int, [dyn]));
-
- never(fnTypeFuzzy(dart.void, [int]), fnTypeFuzzy(int, [int]));
- never(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(int, [], [int]));
- never(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(int, [int]));
- never(fnTypeFuzzy(dart.void, [], [int]), fnTypeFuzzy(int, []));
- never(fnTypeFuzzy(dart.void, [int], {extra: int}), fnTypeFuzzy(int, [int]));
- });
-
- test('higher-order typedef', () => {
- let Func$ = dart.generic((S, T) =>
- dart.typedef('Func', () =>
- fnTypeFuzzy(T, [S])));
- let Func2$ = dart.generic((R, S, T) =>
- dart.typedef('Func2', () =>
- fnTypeFuzzy(T, [Func$(R, S)])));
-
- maybe(fnTypeFuzzy(int, [fnTypeFuzzy(int, [num])]),
- fnTypeFuzzy(num, [fnTypeFuzzy(int, [int])]));
- maybe(fnTypeFuzzy(int, [Func$(num, int)]),
- fnTypeFuzzy(num, [Func$(int, int)]));
- maybe(Func2$(num, int, int), Func2$(int, int, num));
- });
-
- test('mixed types', () => {
- let AA$ = dart.generic((T) => {
- class AA extends core.Object {}
- (AA.new = function() {}).prototype = AA.prototype;
- return AA;
- });
-
- always(int, dyn);
- maybe(dyn, int);
-
- never(fnTypeFuzzy(int, [int]), int);
-
- never(int, fnTypeFuzzy(int, [int]));
-
- always(AA$(int), AA$(dyn));
- maybe(AA$(dyn), AA$(int));
- never(AA$(core.Object), AA$(int));
-
- always(AA$(fnTypeFuzzy(int, [int])), AA$(dyn));
- maybe(AA$(dyn), AA$(fnTypeFuzzy(int, [int])));
- never(AA$(core.Object), AA$(fnTypeFuzzy(int, [int])));
-
- always(AA$(fnTypeFuzzy(int, [int])), AA$(fnTypeFuzzy(dyn, [dyn])));
- maybe(AA$(fnTypeFuzzy(dyn, [dyn])), AA$(fnTypeFuzzy(int, [int])));
- maybe(AA$(fnTypeFuzzy(core.Object, [core.Object])),
- AA$(fnTypeFuzzy(int, [int])));
- });
- });
-
- suite('canonicalization', function() {
- 'use strict';
- let fnTypeFuzzy = dart.fnTypeFuzzy;
- let fnType = dart.fnType;
- let typedef = dart.typedef;
- let generic = dart.generic;
-
- let Object = core.Object;
- let String = core.String;
- let int = core.int;
- let dynamic = dart.dynamic;
- let bottom = dart.bottom;
- let Map = core.Map;
- let Map$ = core.Map$;
-
- class A {}
-
- let AA$ = generic((T, U) => {
- class AA extends core.Object {}
- (AA.new = function() {}).prototype = AA.prototype;
- return AA;
- });
- let AA = AA$();
-
- let Func2 = typedef('Func2', () => fnTypeFuzzy(dynamic, [dynamic, dynamic]));
-
- let FuncG$ = generic((T, U) => typedef('FuncG', () => fnTypeFuzzy(T, [T, U])))
- let FuncG = FuncG$();
-
- test('base types', () => {
- assert.equal(Object, Object);
- assert.equal(String, String);
- assert.equal(dynamic, dynamic);
- });
-
- test('class types', () => {
- assert.equal(A, A);
- });
-
- test('generic class types', () => {
- assert.equal(AA, AA);
- assert.equal(AA, AA$(dynamic, dynamic));
- assert.equal(AA$(dynamic, dynamic), AA$(dynamic, dynamic));
- assert.equal(AA$(AA, Object), AA$(AA, Object));
- assert.equal(Map, Map);
- assert.equal(Map$(dynamic, dynamic), Map);
- assert.equal(Map$(int, Map$(int, int)), Map$(int, Map$(int, int)));
- });
-
- test('typedefs', () => {
- assert.equal(Func2, Func2);
- assert.equal(FuncG, FuncG$(dynamic, dynamic));
- assert.equal(FuncG$(dynamic, dynamic), FuncG$(dynamic, dynamic));
- assert.equal(FuncG$(String, Func2), FuncG$(String, Func2));
- });
-
- test('function types', () => {
- assert.equal(fnTypeFuzzy(dynamic, [dynamic, dynamic]),
- fnTypeFuzzy(dynamic, [dynamic, dynamic]))
-
- assert.notEqual(fnType(dynamic, [dynamic, dynamic]),
- fnTypeFuzzy(dynamic, [dynamic, dynamic]))
-
- assert.equal(fnTypeFuzzy(dynamic, [dynamic, dynamic]),
- fnTypeFuzzy(dynamic, [bottom, bottom]))
-
- assert.equal(fnTypeFuzzy(dynamic, [], [dynamic, dynamic]),
- fnTypeFuzzy(dynamic, [], [dynamic, dynamic]))
-
- assert.notEqual(fnType(dynamic, [], [dynamic, dynamic]),
- fnTypeFuzzy(dynamic, [], [dynamic, dynamic]))
-
- assert.equal(fnTypeFuzzy(dynamic, [], [dynamic, dynamic]),
- fnTypeFuzzy(dynamic, [], [bottom, bottom]))
-
- assert.equal(fnTypeFuzzy(dynamic, [], {extra: dynamic}),
- fnTypeFuzzy(dynamic, [], {extra: dynamic}))
-
- assert.notEqual(fnType(dynamic, [], {extra: dynamic}),
- fnTypeFuzzy(dynamic, [], {extra: dynamic}))
-
- assert.equal(fnTypeFuzzy(dynamic, [], {extra: dynamic}),
- fnTypeFuzzy(dynamic, [], {extra: bottom}))
-
- assert.equal(fnTypeFuzzy(int, [int, int]),
- fnTypeFuzzy(int, [int, int]))
-
- assert.equal(fnTypeFuzzy(int, [], [int, int]),
- fnTypeFuzzy(int, [], [int, int]))
-
- assert.equal(fnTypeFuzzy(int, [int, int], {extra: int}),
- fnTypeFuzzy(int, [int, int], {extra: int}))
-
- assert.equal(fnTypeFuzzy(int, [int, int, int, int, int]),
- fnTypeFuzzy(int, [int, int, int, int, int]))
-
- assert.notEqual(fnTypeFuzzy(int, [int, int, int, int, int]),
- fnTypeFuzzy(int, [int, int, int], [int, int]))
-
- assert.notEqual(fnTypeFuzzy(String, [int, int, int, int, int]),
- fnTypeFuzzy(int, [int, int, int, int, int]))
-
- assert.notEqual(fnTypeFuzzy(String, []),
- fnTypeFuzzy(int, []))
- });
- });
-
- suite('primitives', function() {
- 'use strict';
-
- test('fixed length list', () => {
- let list = core.List.new(10);
- list[0] = 42;
- assert.throws(() => list.add(42));
- });
-
- test('toString on ES Symbol', () => {
- let sym = Symbol('_foobar');
- assert.equal(dart.toString(sym), 'Symbol(_foobar)');
- });
- });
-});
diff --git a/pkg/dev_compiler/test/codegen/async_helper.dart b/pkg/dev_compiler/test/codegen/async_helper.dart
deleted file mode 100644
index 49e33ca..0000000
--- a/pkg/dev_compiler/test/codegen/async_helper.dart
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// This library is used for testing asynchronous tests.
-/// If a test is asynchronous, it needs to notify the testing driver
-/// about this (otherwise tests may get reported as passing [after main()
-/// finished] even if the asynchronous operations fail).
-/// Tests which can't use the unittest framework should use the helper functions
-/// in this library.
-/// This library provides four methods
-/// - asyncStart(): Needs to be called before an asynchronous operation is
-/// scheduled.
-/// - asyncEnd(): Needs to be called as soon as the asynchronous operation
-/// ended.
-/// - asyncSuccess(_): Variant of asyncEnd useful together with Future.then.
-/// - asyncTest(f()): Helper method that wraps a computation that returns a
-/// Future with matching calls to asyncStart() and
-/// asyncSuccess(_).
-/// After the last asyncStart() called was matched with a corresponding
-/// asyncEnd() or asyncSuccess(_) call, the testing driver will be notified that
-/// the tests is done.
-
-library async_helper;
-
-bool _initialized = false;
-
-typedef void _Action0();
-_Action0 _onAsyncEnd;
-
-int _asyncLevel = 0;
-
-Exception _buildException(String msg) {
- return new Exception('Fatal: $msg. This is most likely a bug in your test.');
-}
-
-/// Implementation method called from language_tests.js.
-/// Registers the callback that will be used to complete the test.
-void asyncTestInitialize(_Action0 callback) {
- _asyncLevel = 0;
- _initialized = false;
- _onAsyncEnd = callback;
-}
-
-/// Implementation method called from language_tests.js.
-/// Returns true if an asyncTest was started.
-bool get asyncTestStarted => _initialized;
-
-/// Call this method before an asynchronous test is created.
-///
-/// If [count] is provided, expect [count] [asyncEnd] calls instead of just one.
-void asyncStart([int count = 1]) {
- if (count <= 0) return;
- if (_initialized && _asyncLevel == 0) {
- throw _buildException('asyncStart() was called even though we are done '
- 'with testing.');
- }
- if (!_initialized) {
- if (_onAsyncEnd == null) {
- throw _buildException(
- 'asyncStart() was called before asyncTestInitialize()');
- }
-
- print('unittest-suite-wait-for-done');
- _initialized = true;
- }
- _asyncLevel += count;
-}
-
-/// Call this after an asynchronous test has ended successfully.
-void asyncEnd() {
- if (_asyncLevel <= 0) {
- if (!_initialized) {
- throw _buildException('asyncEnd() was called before asyncStart().');
- } else {
- throw _buildException('asyncEnd() was called more often than '
- 'asyncStart().');
- }
- }
- _asyncLevel--;
- if (_asyncLevel == 0) {
- var callback = _onAsyncEnd;
- _onAsyncEnd = null;
- callback();
- print('unittest-suite-success');
- }
-}
-
-/**
- * Call this after an asynchronous test has ended successfully. This is a helper
- * for calling [asyncEnd].
- *
- * This method intentionally has a signature that matches [:Future.then:] as a
- * convenience for calling [asyncEnd] when a [:Future:] completes without error,
- * like this:
- *
- * asyncStart();
- * Future result = test();
- * result.then(asyncSuccess);
- */
-void asyncSuccess(_) => asyncEnd();
-
-/**
- * Helper method for performing asynchronous tests involving [:Future:].
- *
- * [f] must return a [:Future:] for the test computation.
- */
-void asyncTest(f()) {
- asyncStart();
- f().then(asyncSuccess);
-}
diff --git a/pkg/dev_compiler/test/codegen_expected/async_helper.js b/pkg/dev_compiler/test/codegen_expected/async_helper.js
deleted file mode 100644
index d3a0723..0000000
--- a/pkg/dev_compiler/test/codegen_expected/async_helper.js
+++ /dev/null
@@ -1,94 +0,0 @@
-define(['dart_sdk'], function(dart_sdk) {
- 'use strict';
- const core = dart_sdk.core;
- const dart = dart_sdk.dart;
- const dartx = dart_sdk.dartx;
- const _root = Object.create(null);
- const async_helper = Object.create(_root);
- let VoidTovoid = () => (VoidTovoid = dart.constFn(dart.fnTypeFuzzy(dart.void, [])))();
- let VoidTodynamic = () => (VoidTodynamic = dart.constFn(dart.fnTypeFuzzy(dart.dynamic, [])))();
- let StringToException = () => (StringToException = dart.constFn(dart.fnType(core.Exception, [core.String])))();
- let FnTovoid = () => (FnTovoid = dart.constFn(dart.fnType(dart.void, [VoidTovoid()])))();
- let VoidTovoid$ = () => (VoidTovoid$ = dart.constFn(dart.fnType(dart.void, [])))();
- let dynamicTovoid = () => (dynamicTovoid = dart.constFn(dart.fnType(dart.void, [dart.dynamic])))();
- let FnTovoid$ = () => (FnTovoid$ = dart.constFn(dart.fnType(dart.void, [VoidTodynamic()])))();
- dart.defineLazy(async_helper, {
- get _initialized() {
- return false;
- },
- set _initialized(_) {}
- });
- async_helper._Action0 = dart.typedef('_Action0', () => dart.fnTypeFuzzy(dart.void, []));
- dart.defineLazy(async_helper, {
- get _onAsyncEnd() {
- return null;
- },
- set _onAsyncEnd(_) {},
- get _asyncLevel() {
- return 0;
- },
- set _asyncLevel(_) {}
- });
- async_helper._buildException = function(msg) {
- return core.Exception.new(dart.str`Fatal: ${msg}. This is most likely a bug in your test.`);
- };
- dart.fn(async_helper._buildException, StringToException());
- async_helper.asyncTestInitialize = function(callback) {
- async_helper._asyncLevel = 0;
- async_helper._initialized = false;
- async_helper._onAsyncEnd = callback;
- };
- dart.fn(async_helper.asyncTestInitialize, FnTovoid());
- dart.copyProperties(async_helper, {
- get asyncTestStarted() {
- return async_helper._initialized;
- }
- });
- async_helper.asyncStart = function() {
- if (dart.test(async_helper._initialized) && async_helper._asyncLevel === 0) {
- dart.throw(async_helper._buildException('asyncStart() was called even though we are done ' + 'with testing.'));
- }
- if (!dart.test(async_helper._initialized)) {
- if (async_helper._onAsyncEnd == null) {
- dart.throw(async_helper._buildException('asyncStart() was called before asyncTestInitialize()'));
- }
- core.print('unittest-suite-wait-for-done');
- async_helper._initialized = true;
- }
- async_helper._asyncLevel = dart.notNull(async_helper._asyncLevel) + 1;
- };
- dart.fn(async_helper.asyncStart, VoidTovoid$());
- async_helper.asyncEnd = function() {
- if (dart.notNull(async_helper._asyncLevel) <= 0) {
- if (!dart.test(async_helper._initialized)) {
- dart.throw(async_helper._buildException('asyncEnd() was called before asyncStart().'));
- } else {
- dart.throw(async_helper._buildException('asyncEnd() was called more often than ' + 'asyncStart().'));
- }
- }
- async_helper._asyncLevel = dart.notNull(async_helper._asyncLevel) - 1;
- if (async_helper._asyncLevel === 0) {
- let callback = async_helper._onAsyncEnd;
- async_helper._onAsyncEnd = null;
- callback();
- core.print('unittest-suite-success');
- }
- };
- dart.fn(async_helper.asyncEnd, VoidTovoid$());
- async_helper.asyncSuccess = function(_) {
- return async_helper.asyncEnd();
- };
- dart.fn(async_helper.asyncSuccess, dynamicTovoid());
- async_helper.asyncTest = function(f) {
- async_helper.asyncStart();
- dart.dsend(f(), 'then', async_helper.asyncSuccess);
- };
- dart.fn(async_helper.asyncTest, FnTovoid$());
- dart.trackLibraries("async_helper", {
- "async_helper.dart": async_helper
- }, null);
- // Exports:
- return {
- async_helper: async_helper
- };
-});
diff --git a/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart b/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart
index d93083c..0870331 100644
--- a/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart
+++ b/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart
@@ -69,7 +69,7 @@
try {
var result = await compile(args, compilerState: context.compilerState);
context.compilerState = result.compilerState;
- succeeded = result.result;
+ succeeded = result.success;
} catch (e, s) {
print('Unhandled exception:');
print(e);
diff --git a/pkg/dev_compiler/tool/build_pkgs.dart b/pkg/dev_compiler/tool/build_pkgs.dart
index c8b3bf12..57c7e30 100755
--- a/pkg/dev_compiler/tool/build_pkgs.dart
+++ b/pkg/dev_compiler/tool/build_pkgs.dart
@@ -3,13 +3,10 @@
import 'dart:io';
import 'package:args/args.dart';
-import 'package:front_end/src/api_prototype/compilation_message.dart';
-import 'package:front_end/src/api_prototype/compiler_options.dart';
-import 'package:front_end/src/api_prototype/summary_generator.dart';
import 'package:path/path.dart' as p;
-import 'package:dev_compiler/src/analyzer/command.dart' as analyzer;
-import 'package:dev_compiler/src/kernel/target.dart';
+import 'package:dev_compiler/src/analyzer/command.dart' as dartdevc;
+import 'package:dev_compiler/src/kernel/command.dart' as dartdevk;
final String scriptDirectory = p.dirname(p.fromUri(Platform.script));
@@ -27,8 +24,6 @@
/// packages will be placed in a "pkg" subdirectory of this.
String outputDirectory;
-String get pkgDirectory => p.join(outputDirectory, "pkg");
-
/// Compiles the packages that the DDC tests use to JS into the given output
/// directory.
///
@@ -70,8 +65,6 @@
kernelSummary = argResults["kernel-sdk"] as String;
outputDirectory = argResults["output"] as String;
- new Directory(pkgDirectory).createSync(recursive: true);
-
// Build leaf packages. These have no other package dependencies.
// Under pkg.
@@ -108,7 +101,6 @@
if (!isTravis) {
await compileModule('unittest', deps: [
- 'matcher',
'path',
'stack_trace'
], libs: [
@@ -134,113 +126,36 @@
/// Compiles a [module] with a single matching ".dart" library and additional
/// [libs] and [deps] on other modules.
Future compileModule(String module,
- {List<String> libs, List<String> deps}) async {
- if (analyzerSummary != null) compileModuleUsingAnalyzer(module, libs, deps);
- if (kernelSummary != null) await compileKernelSummary(module, libs, deps);
-}
+ {List<String> libs = const [], List<String> deps = const []}) async {
+ makeArgs(bool kernel) {
+ var pkgDirectory = p.join(outputDirectory, kernel ? 'pkg_kernel' : 'pkg');
+ new Directory(pkgDirectory).createSync(recursive: true);
-void compileModuleUsingAnalyzer(
- String module, List<String> libraries, List<String> dependencies) {
- var args = [
- '--dart-sdk-summary=$analyzerSummary',
- '-o${pkgDirectory}/$module.js'
- ];
-
- // There is always a library that matches the module.
- args.add('package:$module/$module.dart');
-
- // Add any additional libraries.
- if (libraries != null) {
- for (var lib in libraries) {
+ var args = [
+ '--dart-sdk-summary=${kernel ? kernelSummary : analyzerSummary}',
+ '-o${pkgDirectory}/$module.js',
+ 'package:$module/$module.dart'
+ ];
+ for (var lib in libs) {
args.add('package:$module/$lib.dart');
}
- }
-
- // Add summaries for any modules this depends on.
- if (dependencies != null) {
- for (var dep in dependencies) {
- args.add('-s${pkgDirectory}/$dep.sum');
+ for (var dep in deps) {
+ args.add('-s${pkgDirectory}/$dep.${kernel ? "dill" : "sum"}');
}
- }
-
- // TODO(rnystrom): Hack. DDC has its own forked copy of async_helper that
- // has a couple of differences from pkg/async_helper. We should unfork them,
- // but I'm not sure how they'll affect the other non-DDC tests. For now, just
- // use ours.
- if (module == 'async_helper') {
- args.add('--url-mapping=package:async_helper/async_helper.dart,' +
- p.join(scriptDirectory, "../test/codegen/async_helper.dart"));
- }
-
- var exitCode = analyzer.compile(args);
- if (exitCode != 0) exit(exitCode);
-}
-
-Future compileKernelSummary(
- String module, List<String> libraries, List<String> dependencies) async {
- var succeeded = true;
-
- void errorHandler(CompilationMessage error) {
- if (error.severity == Severity.error) succeeded = false;
- }
-
- var options = new CompilerOptions()
- ..sdkSummary = p.toUri(kernelSummary)
- ..packagesFileUri = _uriInRepo(".packages")
- ..strongMode = true
- ..debugDump = true
- ..onError = errorHandler
- ..reportMessages = true
- ..target = new DevCompilerTarget();
-
- var inputs = <Uri>[];
-
- if (module == "async_helper") {
- // TODO(rnystrom): Hack. DDC has its own forked copy of async_helper that
- // has a couple of differences from pkg/async_helper. We should unfork them,
- // but I'm not sure how they'll affect the other non-DDC tests. For now,
- // just use ours.
- inputs.add(_uriInRepo("pkg/dev_compiler/test/codegen/async_helper.dart"));
- } else {
- // There is always a library that matches the module.
- inputs.add(Uri.parse("package:$module/$module.dart"));
-
- // Add any other libraries too.
- if (libraries != null) {
- for (var lib in libraries) {
- inputs.add(Uri.parse("package:$module/$lib.dart"));
- }
+ if (kernel) {
+ args.add('--summary-input-dir=$pkgDirectory');
}
+ return args;
}
- // Add summaries for any modules this depends on.
- if (dependencies != null) {
- var uris = <Uri>[];
-
- for (var dep in dependencies) {
- uris.add(p.toUri(p.absolute(p.join(pkgDirectory, "$dep.dill"))));
- }
-
- options.inputSummaries = uris;
+ if (analyzerSummary != null) {
+ var args = makeArgs(false);
+ var exitCode = dartdevc.compile(args);
+ if (exitCode != 0) exit(exitCode);
}
-
- // Compile the summary.
- var bytes = await summaryFor(inputs, options);
- var dillFile = new File(p.join(pkgDirectory, "$module.dill"));
- if (succeeded) {
- dillFile.writeAsBytesSync(bytes);
- } else {
- // Don't leave the previous version of the file on failure.
- if (dillFile.existsSync()) dillFile.deleteSync();
-
- stderr.writeln("Could not generate kernel summary for $module.");
- exit(1);
+ if (kernelSummary != null) {
+ var args = makeArgs(true);
+ var result = await dartdevk.compile(args);
+ if (!result.success) exit(1);
}
}
-
-Uri _uriInRepo(String pathInRepo) {
- // Walk up to repo root.
- var result = p.join(scriptDirectory, "../../../");
- result = p.join(result, pathInRepo);
- return p.toUri(p.absolute(p.normalize(result)));
-}
diff --git a/pkg/dev_compiler/tool/ddb b/pkg/dev_compiler/tool/ddb
index a02b4cf..c6e5ab7 100755
--- a/pkg/dev_compiler/tool/ddb
+++ b/pkg/dev_compiler/tool/ddb
@@ -59,7 +59,11 @@
ProcessResult runDdc(String command, List<String> args) {
if (debug) {
// Use unbuilt script. This only works from a source checkout.
- args.insertAll(0, ['--preview-dart-2', '--enable-asserts', path.join(ddcPath, 'bin', '${command}.dart')]);
+ args.insertAll(0, [
+ '--preview-dart-2',
+ '--enable-asserts',
+ path.join(ddcPath, 'bin', '${command}.dart')
+ ]);
command = dartBinary;
} else {
// Use built snapshot.
@@ -86,8 +90,17 @@
mod = 'amd';
break;
}
- var sdkJsPath = path.join(dartSdk, 'lib', 'dev_compiler', mod);
+ String sdkJsPath;
+ if (debug) {
+ var sdkRoot = path.dirname(path.dirname(ddcPath));
+ var buildDir = path.join(sdkRoot, Platform.isMacOS ? 'xcodebuild' : 'out');
+ var genDir = path.join(buildDir, 'ReleaseX64', 'gen', 'utils', 'dartdevc');
+ sdkJsPath = path.join(genDir, kernel ? 'kernel' : 'js', mod);
+ } else {
+ var suffix = kernel ? path.join('kernel', mod) : mod;
+ sdkJsPath = path.join(dartSdk, 'lib', 'dev_compiler', suffix);
+ }
ProcessResult result;
if (kernel) {
var ddcSdk = path.join(dartSdk, 'lib', '_internal', 'ddc_sdk.dill');
diff --git a/pkg/dev_compiler/tool/ddc b/pkg/dev_compiler/tool/ddc
index addb332..937accd 100755
--- a/pkg/dev_compiler/tool/ddc
+++ b/pkg/dev_compiler/tool/ddc
@@ -63,8 +63,6 @@
BASENAME=$( basename "${1%.*}")
LIBROOT=$(cd $( dirname "${1%.*}") && pwd)
-export NODE_PATH=$GEN_DIR/js/common:$LIBROOT:$NODE_PATH
-
if [ "$KERNEL" = true ]; then
if [ ! -e $GEN_DIR/kernel/ddc_sdk.dill ]; then
@@ -74,6 +72,8 @@
exit 1
fi
+ NODE_PATH=$GEN_DIR/kernel/common:$LIBROOT:$NODE_PATH
+
$SDK_DIR/sdk/bin/dartdevk --modules=node \
--dart-sdk-summary=$GEN_DIR/kernel/ddc_sdk.dill \
-o $LIBROOT/$BASENAME.js $*
@@ -86,6 +86,8 @@
exit 1
fi
+ NODE_PATH=$GEN_DIR/js/common:$LIBROOT:$NODE_PATH
+
$SDK_DIR/sdk/bin/dartdevc --modules=node \
--library-root=$LIBROOT --dart-sdk-summary=$GEN_DIR/ddc_sdk.sum \
-o $LIBROOT/$BASENAME.js $*
diff --git a/pkg/dev_compiler/tool/ddw b/pkg/dev_compiler/tool/ddw
index 4941c00..86ecf9b 100755
--- a/pkg/dev_compiler/tool/ddw
+++ b/pkg/dev_compiler/tool/ddw
@@ -63,8 +63,6 @@
BASENAME=$( basename "${1%.*}")
LIBROOT=$(cd $( dirname "${1%.*}") && pwd)
-export NODE_PATH=$GEN_DIR/js/common:$LIBROOT:$NODE_PATH
-
if [ "$KERNEL" = true ]; then
if [ ! -e $GEN_DIR/kernel/ddc_sdk.dill ]; then
@@ -74,6 +72,8 @@
exit 1
fi
+ NODE_PATH=$GEN_DIR/kernel/common:$LIBROOT:$NODE_PATH
+
dart -c $SDK_DIR/pkg/dev_compiler/bin/dartdevk.dart --modules=node \
--dart-sdk-summary=$GEN_DIR/kernel/ddc_sdk.dill \
-o $LIBROOT/$BASENAME.js $*
@@ -86,6 +86,8 @@
exit 1
fi
+ NODE_PATH=$GEN_DIR/js/common:$LIBROOT:$NODE_PATH
+
dart -c $SDK_DIR/pkg/dev_compiler/bin/dartdevc.dart --modules=node \
--library-root=$LIBROOT --dart-sdk-summary=$GEN_DIR/ddc_sdk.sum \
-o $LIBROOT/$BASENAME.js $*
diff --git a/pkg/dev_compiler/tool/input_sdk/lib/js/dart2js/js_dart2js.dart b/pkg/dev_compiler/tool/input_sdk/lib/js/dart2js/js_dart2js.dart
index a3de057..8d7ad6e 100644
--- a/pkg/dev_compiler/tool/input_sdk/lib/js/dart2js/js_dart2js.dart
+++ b/pkg/dev_compiler/tool/input_sdk/lib/js/dart2js/js_dart2js.dart
@@ -91,9 +91,9 @@
import 'dart:_js_helper' show Primitives;
import 'dart:_foreign_helper' show JS;
+import 'dart:_runtime' as dart;
-final _global = JS('', 'dart.global');
-final JsObject context = _wrapToDart(_global);
+final JsObject context = _wrapToDart(dart.global_);
/**
* Proxies a JavaScript object to Dart.
@@ -503,17 +503,13 @@
// converts a Dart object to a reference to a native JS object
// which might be a DartObject JS->Dart proxy
Object _convertToDart(o) {
- if (JS('bool', '# == null', o) ||
- JS('bool', 'typeof # == "string"', o) ||
- JS('bool', 'typeof # == "number"', o) ||
- JS('bool', 'typeof # == "boolean"', o) ||
- _isBrowserType(o)) {
+ if (o == null || o is String || o is num || o is bool || _isBrowserType(o)) {
return o;
- } else if (JS('bool', '# instanceof Date', o)) {
+ } else if (JS('!', '# instanceof Date', o)) {
num ms = JS('!', '#.getTime()', o);
return new DateTime.fromMillisecondsSinceEpoch(ms);
} else if (o is _DartObject &&
- JS('bool', 'dart.jsobject != dart.getReifiedType(#)', o)) {
+ !identical(dart.getReifiedType(o), dart.jsobject)) {
return o._dartObj;
} else {
return _wrapToDart(o);
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart
index 163e26c..0dd4e3e 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart
@@ -28,8 +28,8 @@
void _copyMembers(to, from) {
var names = getOwnNamesAndSymbols(from);
- for (var i = 0, n = JS('int', '#.length', names); i < n; ++i) {
- var name = JS('', '#[#]', names, i);
+ for (int i = 0, n = JS('!', '#.length', names); i < n; ++i) {
+ String name = JS('', '#[#]', names, i);
if (name == 'constructor') continue;
_copyMember(to, from, name);
}
@@ -38,14 +38,14 @@
void _copyMember(to, from, name) {
var desc = getOwnPropertyDescriptor(from, name);
- if (JS('bool', '# == Symbol.iterator', name)) {
+ if (JS('!', '# == Symbol.iterator', name)) {
// On native types, Symbol.iterator may already be present.
// TODO(jmesserly): investigate if we still need this.
// If so, we need to find a better solution.
// See https://github.com/dart-lang/sdk/issues/28324
var existing = getOwnPropertyDescriptor(to, name);
if (existing != null) {
- if (JS('bool', '#.writable', existing)) {
+ if (JS('!', '#.writable', existing)) {
JS('', '#[#] = #.value', to, name, desc);
}
return;
@@ -201,18 +201,18 @@
bool isJsInterop(obj) {
if (obj == null) return false;
- if (JS('bool', 'typeof # === "function"', obj)) {
+ if (JS('!', 'typeof # === "function"', obj)) {
// A function is a Dart function if it has runtime type information.
- return JS('bool', '#[#] == null', obj, _runtimeType);
+ return JS('!', '#[#] == null', obj, _runtimeType);
}
// Primitive types are not JS interop types.
- if (JS('bool', 'typeof # !== "object"', obj)) return false;
+ if (JS('!', 'typeof # !== "object"', obj)) return false;
// Extension types are not considered JS interop types.
// Note that it is still possible to call typed JS interop methods on
// extension types but the calls must be statically typed.
- if (JS('bool', '#[#] != null', obj, _extensionType)) return false;
- return JS('bool', '!($obj instanceof $Object)');
+ if (JS('!', '#[#] != null', obj, _extensionType)) return false;
+ return JS('!', '!($obj instanceof $Object)');
}
/// Get the type of a method from a type using the stored signature
@@ -227,7 +227,7 @@
if (setters != null) {
var type = JS('', '#[#]', setters, name);
if (type != null) {
- if (JS('bool', '# instanceof Array', type)) {
+ if (JS('!', '# instanceof Array', type)) {
// The type has metadata attached. Pull out just the type.
// TODO(jmesserly): remove when we remove mirrors
return JS('', '#[0]', type);
@@ -238,7 +238,7 @@
var fields = getFields(type);
if (fields != null) {
var fieldInfo = JS('', '#[#]', fields, name);
- if (fieldInfo != null && JS('bool', '!#.isFinal', fieldInfo)) {
+ if (fieldInfo != null && JS<bool>('!', '!#.isFinal', fieldInfo)) {
return JS('', '#.type', fieldInfo);
}
}
@@ -285,14 +285,14 @@
_getMembers(type, kind) {
var sig = JS('', '#[#]', type, kind);
- return JS('bool', 'typeof # == "function"', sig)
- ? JS('', '#[#] = #', type, kind, sig())
+ return JS<bool>('!', 'typeof # == "function"', sig)
+ ? JS('', '#[#] = #()', type, kind, sig)
: sig;
}
bool _hasMember(type, kind, name) {
var sig = _getMembers(type, kind);
- return sig != null && JS('bool', '# in #', name, sig);
+ return sig != null && JS<bool>('!', '# in #', name, sig);
}
bool hasMethod(type, name) => _hasMember(type, _methodSig, name);
@@ -307,14 +307,14 @@
/// Install properties in prototype-first order. Properties / descriptors from
/// more specific types should overwrite ones from less specific types.
void _installProperties(jsProto, dartType, installedParent) {
- if (JS('bool', '# === #', dartType, Object)) {
+ if (JS('!', '# === #', dartType, Object)) {
_installPropertiesForObject(jsProto);
return;
}
// If the extension methods of the parent have been installed on the parent
// of [jsProto], the methods will be available via prototype inheritance.
var dartSupertype = JS('', '#.__proto__', dartType);
- if (JS('bool', '# !== #', dartSupertype, installedParent)) {
+ if (JS('!', '# !== #', dartSupertype, installedParent)) {
_installProperties(jsProto, dartSupertype, installedParent);
}
@@ -350,7 +350,7 @@
var jsProto = JS('', '#.prototype', jsType);
if (jsProto == null) return;
- if (JS('bool', '# === #', dartExtType, Object)) {
+ if (JS('!', '# === #', dartExtType, Object)) {
_installPropertiesForGlobalObject(jsProto);
return;
}
@@ -359,7 +359,7 @@
jsProto, dartExtType, JS('', '#[#]', jsProto, _extensionType));
// Mark the JS type's instances so we can easily check for extensions.
- if (JS('bool', '# !== #', dartExtType, JSFunction)) {
+ if (JS('!', '# !== #', dartExtType, JSFunction)) {
JS('', '#[#] = #', jsProto, _extensionType, dartExtType);
}
JS('', '#[#] = #[#]', jsType, _methodSig, dartExtType, _methodSig);
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart
index b0b39e3..115a550 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart
@@ -23,22 +23,22 @@
}
argumentError(value) {
- if (JS('bool', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
+ if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
throw new ArgumentError.value(value);
}
throwUnimplementedError(String message) {
- if (JS('bool', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
+ if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
throw new UnimplementedError(message);
}
assertFailed(message) {
- if (JS('bool', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
+ if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
throw new AssertionErrorImpl(message);
}
throwCyclicInitializationError([Object field]) {
- if (JS('bool', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
+ if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
throw new CyclicInitializationError(field);
}
@@ -46,12 +46,12 @@
// TODO(vsm): Per spec, we should throw an NSM here. Technically, we ought
// to thread through method info, but that uglifies the code and can't
// actually be queried ... it only affects how the error is printed.
- if (JS('bool', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
+ if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
throw new NoSuchMethodError(
null, new Symbol('<Unexpected Null Value>'), null, null, null);
}
-castError(obj, expectedType, [@js_helper.notNull bool isImplicit = false]) {
+castError(obj, expectedType, [@notNull bool isImplicit = false]) {
var actualType = getReifiedType(obj);
var message = _castErrorMessage(actualType, expectedType);
if (JS('!', 'dart.__ignoreAllErrors')) {
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
index 0723a7b..cbeda90 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
@@ -98,7 +98,7 @@
// implemented by the Object base class as those methods can always be
// statically resolved.
dload(obj, field, [mirrors = undefined]) {
- if (JS('bool', 'typeof # == "function" && # == "call"', obj, field)) {
+ if (JS('!', 'typeof # == "function" && # == "call"', obj, field)) {
return obj;
}
var f = _canonicalMember(obj, field);
@@ -111,7 +111,7 @@
if (hasMethod(type, f)) return bind(obj, f, null);
// Always allow for JS interop objects.
- if (!JS('bool', '#', mirrors) && isJsInterop(obj)) {
+ if (!JS<bool>('!', '#', mirrors) && isJsInterop(obj)) {
return JS('', '#[#]', obj, f);
}
}
@@ -143,12 +143,12 @@
if (f != null) {
var setterType = getSetterType(getType(obj), f);
if (setterType != null) {
- if (JS('bool', '#', mirrors))
+ if (JS('!', '#', mirrors))
setterType = _stripGenericArguments(setterType);
return JS('', '#[#] = #._check(#)', obj, f, setterType, value);
}
// Always allow for JS interop objects.
- if (!JS('bool', '#', mirrors) && isJsInterop(obj)) {
+ if (!JS<bool>('!', '#', mirrors) && isJsInterop(obj)) {
return JS('', '#[#] = #', obj, f, value);
}
}
@@ -161,15 +161,15 @@
/// actuals.
bool _checkApply(FunctionType type, List actuals, namedActuals) {
// Check for too few required arguments.
- var actualsCount = JS('int', '#.length', actuals);
+ int actualsCount = JS('!', '#.length', actuals);
var required = type.args;
- var requiredCount = JS('int', '#.length', required);
+ int requiredCount = JS('!', '#.length', required);
if (actualsCount < requiredCount) return false;
// Check for too many postional arguments.
var extras = actualsCount - requiredCount;
var optionals = type.optionals;
- if (extras > JS('int', '#.length', optionals)) return false;
+ if (extras > JS<int>('!', '#.length', optionals)) return false;
// Check if we have invalid named arguments.
Iterable names;
@@ -177,7 +177,7 @@
if (namedActuals != null) {
names = getOwnPropertyNames(namedActuals);
for (var name in names) {
- if (!JS('bool', '#.hasOwnProperty(#)', named, name)) return false;
+ if (!JS('!', '#.hasOwnProperty(#)', named, name)) return false;
}
}
// Now that we know the signature matches, we can perform type checks.
@@ -222,17 +222,19 @@
})()''');
Symbol _dartSymbol(name) {
- return (JS('bool', 'typeof # === "symbol"', name))
+ return (JS<bool>('!', 'typeof # === "symbol"', name))
? JS('Symbol', '#(new #.new(#, #))', const_, PrivateSymbol,
_toSymbolName(name), name)
- : JS('Symbol', '#(#.new(#))', const_, Symbol, _toDisplayName(name));
+ : JS('Symbol', '#(new #.new(#))', const_, internal.Symbol,
+ _toDisplayName(name));
}
Symbol _setterSymbol(name) {
- return (JS('bool', 'typeof # === "symbol"', name))
+ return (JS<bool>('!', 'typeof # === "symbol"', name))
? JS('Symbol', '#(new #.new(# + "=", #))', const_, PrivateSymbol,
_toSymbolName(name), name)
- : JS('Symbol', '#(#.new(# + "="))', const_, Symbol, _toDisplayName(name));
+ : JS('Symbol', '#(new #.new(# + "="))', const_, internal.Symbol,
+ _toDisplayName(name));
}
_checkAndCall(f, ftype, obj, typeArgs, args, named, displayName) =>
@@ -358,7 +360,7 @@
/// Shared code for dsend, dindex, and dsetindex.
callMethod(obj, name, typeArgs, args, named, displayName) {
- if (JS('bool', 'typeof # == "function" && # == "call"', obj, name)) {
+ if (JS('!', 'typeof # == "function" && # == "call"', obj, name)) {
return dgcall(obj, typeArgs, args, named);
}
var symbol = _canonicalMember(obj, name);
@@ -434,21 +436,22 @@
});
})()''');
+@notNull
@JSExportName('is')
bool instanceOf(obj, type) {
if (obj == null) {
- return JS('bool', '# == # || #', type, Null, _isTop(type));
+ return JS('!', '# == # || #', type, Null, _isTop(type));
}
- return JS('#', '!!#', isSubtype(getReifiedType(obj), type));
+ return JS('!', '!!#', isSubtype(getReifiedType(obj), type));
}
@JSExportName('as')
-cast(obj, type, @js_helper.notNull bool isImplicit) {
+cast(obj, type, @notNull bool isImplicit) {
if (obj == null) return obj;
var actual = getReifiedType(obj);
var result = isSubtype(actual, type);
if (JS(
- 'bool',
+ '!',
'# === true || # === null && # && '
'dart.__ignoreWhitelistedErrors && #(#, #)',
result,
@@ -484,15 +487,21 @@
asInt(obj) {
if (obj == null) return null;
- if (JS('bool', 'Math.floor(#) != #', obj, obj)) {
+ if (JS('!', 'Math.floor(#) != #', obj, obj)) {
castError(obj, JS('', '#', int), false);
}
return obj;
}
/// Checks that `x` is not null or undefined.
-// TODO(jmesserly): should we inline this?
-notNull(x) {
+//
+// TODO(jmesserly): inline this, either by generating it as a function into
+// the module, or via some other pattern such as:
+//
+// <expr> || nullErr()
+// (t0 = <expr>) != null ? t0 : nullErr()
+@JSExportName('notNull')
+_notNull(x) {
if (x == null) throwNullValueError();
return x;
}
@@ -521,7 +530,7 @@
}
bool dassert(value) {
- if (JS('bool', '# != null && #[#] instanceof #', value, value, _runtimeType,
+ if (JS('!', '# != null && #[#] instanceof #', value, value, _runtimeType,
AbstractFunctionType)) {
value = dcall(value, []);
}
@@ -536,8 +545,8 @@
const _maxErrorCache = 10;
bool _isJsError(exception) {
- return JS('bool', '#.Error != null && # instanceof #.Error', global_,
- exception, global_);
+ return JS('!', '#.Error != null && # instanceof #.Error', global_, exception,
+ global_);
}
// Record/return the JS error for an exception. If an error was already
@@ -546,7 +555,7 @@
if (_isJsError(exception)) return exception;
var useExpando =
- exception != null && JS('bool', 'typeof # == "object"', exception);
+ exception != null && JS<bool>('!', 'typeof # == "object"', exception);
var error;
if (useExpando) {
error = JS('', '#[#]', exception, _error);
@@ -728,29 +737,30 @@
// function minimal.
// This pattern resulted from performance testing; it found that dispatching
// was the fastest solution, even for primitive types.
- return JS('bool', '# == null ? # == null : #[#](#)', x, y, x,
+ return JS('!', '# == null ? # == null : #[#](#)', x, y, x,
extensionSymbol('_equals'), y);
}
int hashCode(obj) {
- return obj == null ? 0 : JS('int', '#[#]', obj, extensionSymbol('hashCode'));
-}
-
-hashKey(k) {
- if (k == null) return 0;
- switch (JS('String', 'typeof #', k)) {
- case "object":
- case "function":
- return JS('int', '#[#] & 0x3ffffff', k, extensionSymbol('hashCode'));
- }
- // For primitive types we can store the key directly in an ES6 Map.
- return k;
+ return obj == null ? 0 : JS('!', '#[#]', obj, extensionSymbol('hashCode'));
}
@JSExportName('toString')
String _toString(obj) {
if (obj == null) return "null";
- return JS('String', '#[#]()', obj, extensionSymbol('toString'));
+ if (obj is String) return obj;
+ return JS('!', '#[#]()', obj, extensionSymbol('toString'));
+}
+
+/// Converts to a non-null [String], equivalent to
+/// `dart.notNull(dart.toString(obj))`.
+///
+/// This is commonly used in string interpolation.
+@notNull
+String str(obj) {
+ if (obj == null) return "null";
+ if (obj is String) return obj;
+ return _notNull(JS('!', '#[#]()', obj, extensionSymbol('toString')));
}
// TODO(jmesserly): is the argument type verified statically?
@@ -761,7 +771,7 @@
/// The default implementation of `noSuchMethod` to match `Object.noSuchMethod`.
defaultNoSuchMethod(obj, Invocation i) {
- if (JS('bool', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
+ if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
throw new NoSuchMethodError.withInvocation(obj, i);
}
@@ -769,17 +779,6 @@
return obj == null ? Null : JS('', '#[dartx.runtimeType]', obj);
}
-/// Implements Dart's interpolated strings as ES2015 tagged template literals.
-///
-/// For example: dart.str`hello ${name}`
-String str(strings, @rest values) => JS('', '''(() => {
- let s = $strings[0];
- for (let i = 0, len = $values.length; i < len; ) {
- s += $notNull($_toString($values[i])) + $strings[++i];
- }
- return s;
-})()''');
-
final identityHashCode_ = JS('', 'Symbol("_identityHashCode")');
/// Adapts a Dart `get iterator` into a JS `[Symbol.iterator]`.
@@ -801,14 +800,14 @@
_canonicalMember(obj, name) {
// Private names are symbols and are already canonical.
- if (JS('bool', 'typeof # === "symbol"', name)) return name;
+ if (JS('!', 'typeof # === "symbol"', name)) return name;
- if (obj != null && JS('bool', '#[#] != null', obj, _extensionType)) {
+ if (obj != null && JS<bool>('!', '#[#] != null', obj, _extensionType)) {
return JS('', 'dartx.#', name);
}
// Check for certain names that we can't use in JS
- if (JS('bool', '# == "constructor" || # == "prototype"', name, name)) {
+ if (JS('!', '# == "constructor" || # == "prototype"', name, name)) {
JS('', '# = "+" + #', name, name);
}
return name;
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/rtti.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/rtti.dart
index 874a3fa..95af629 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/rtti.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/rtti.dart
@@ -85,10 +85,10 @@
/// different from the user-visible Type object returned by calling
/// `runtimeType` on some Dart object.
getReifiedType(obj) {
- switch (JS('String', 'typeof #', obj)) {
+ switch (JS<String>('!', 'typeof #', obj)) {
case "object":
if (obj == null) return JS('', '#', Null);
- if (JS('bool', '# instanceof #', obj, Object)) {
+ if (JS('!', '# instanceof #', obj, Object)) {
return JS('', '#.constructor', obj);
}
var result = JS('', '#[#]', obj, _extensionType);
@@ -118,7 +118,7 @@
Type wrapType(type) {
// If we've already wrapped this type once, use the previous wrapper. This
// way, multiple references to the same type return an identical Type.
- if (JS('bool', '#.hasOwnProperty(#)', type, _typeObject)) {
+ if (JS('!', '#.hasOwnProperty(#)', type, _typeObject)) {
return JS('', '#[#]', type, _typeObject);
}
return JS('Type', '#[#] = #', type, _typeObject, new WrappedType(type));
@@ -141,7 +141,7 @@
}
String getSourceMap(module) {
- return JS('String', '#.get(#)', _loadedSourceMaps, module);
+ return JS<String>('!', '#.get(#)', _loadedSourceMaps, module);
}
/// Return all library objects in the specified module.
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/runtime.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/runtime.dart
index 15b4326..fd5a32b 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/runtime.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/runtime.dart
@@ -10,6 +10,7 @@
import 'dart:_foreign_helper' show JS, JSExportName, rest, spread;
import 'dart:_interceptors' show JSArray, jsNull, JSFunction;
+import 'dart:_internal' as internal show Symbol;
import 'dart:_js_helper'
show
AssertionErrorImpl,
@@ -22,8 +23,8 @@
ImmutableMap,
PrivateSymbol,
ReifyFunctionTypes,
- NoReifyGeneric;
-import 'dart:_js_helper' as js_helper show notNull;
+ NoReifyGeneric,
+ notNull;
import 'dart:_debugger' show trackCall;
export 'dart:_debugger'
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart
index 2d0df1b..8ac9b89 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart
@@ -79,7 +79,7 @@
check_T(object) => object;
}
-bool _isJsObject(obj) => JS('bool', '# === #', getReifiedType(obj), jsobject);
+bool _isJsObject(obj) => JS('!', '# === #', getReifiedType(obj), jsobject);
class LazyJSType extends TypeRep {
final Function() _rawJSType;
@@ -106,7 +106,7 @@
bool isRawType(obj) {
var raw = _raw();
- if (raw != null) return JS('bool', '# instanceof #', obj, raw);
+ if (raw != null) return JS('!', '# instanceof #', obj, raw);
// Treat as anonymous: return true for any JS object.
return _isJsObject(obj);
}
@@ -302,7 +302,7 @@
// identical function types that don't canonicalize
// to the same object since we won't fall into this
// fast path.
- if (extra == null && JS('bool', '#.length < 3', args)) {
+ if (extra == null && JS<bool>('!', '#.length < 3', args)) {
return _createSmall(returnType, args);
}
args = _canonicalizeArray(args, _fnTypeArrayArgMap);
@@ -311,7 +311,7 @@
if (extra == null) {
keys = [returnType, args];
create = () => new FunctionType(returnType, args, [], JS('', '{}'));
- } else if (JS('bool', '# instanceof Array', extra)) {
+ } else if (JS('!', '# instanceof Array', extra)) {
var optionals =
_canonicalizeArray(JS('', '#', extra), _fnTypeArrayArgMap);
keys = [returnType, args, optionals];
@@ -327,9 +327,9 @@
List _process(List array) {
var result = [];
- for (var i = 0; JS('bool', '# < #.length', i, array); ++i) {
+ for (var i = 0; JS<bool>('!', '# < #.length', i, array); ++i) {
var arg = JS('', '#[#]', array, i);
- if (JS('bool', '# instanceof Array', arg)) {
+ if (JS('!', '# instanceof Array', arg)) {
JS('', '#.push(#.slice(1))', metadata, arg);
JS('', '#.push(#[0])', result, arg);
} else {
@@ -360,7 +360,7 @@
var result = <String, Object>{};
var names = getOwnPropertyNames(named);
JS('', '#.sort()', names);
- for (var i = 0; JS('bool', '# < #.length', i, names); ++i) {
+ for (var i = 0; JS<bool>('!', '# < #.length', i, names); ++i) {
String name = JS('!', '#[#]', names, i);
result[name] = JS('', '#[#]', named, name);
}
@@ -371,28 +371,28 @@
if (_stringValue != null) return _stringValue;
var buffer = '(';
- for (var i = 0; JS('bool', '# < #.length', i, args); ++i) {
+ for (var i = 0; JS<bool>('!', '# < #.length', i, args); ++i) {
if (i > 0) {
buffer += ', ';
}
buffer += typeName(JS('', '#[#]', args, i));
}
- if (JS('bool', '#.length > 0', optionals)) {
- if (JS('bool', '#.length > 0', args)) buffer += ', ';
+ if (JS('!', '#.length > 0', optionals)) {
+ if (JS('!', '#.length > 0', args)) buffer += ', ';
buffer += '[';
- for (var i = 0; JS('bool', '# < #.length', i, optionals); ++i) {
+ for (var i = 0; JS<bool>('!', '# < #.length', i, optionals); ++i) {
if (i > 0) {
buffer += ', ';
}
buffer += typeName(JS('', '#[#]', optionals, i));
}
buffer += ']';
- } else if (JS('bool', 'Object.keys(#).length > 0', named)) {
- if (JS('bool', '#.length > 0', args)) buffer += ', ';
+ } else if (JS('!', 'Object.keys(#).length > 0', named)) {
+ if (JS('!', '#.length > 0', args)) buffer += ', ';
buffer += '{';
var names = getOwnPropertyNames(named);
JS('', '#.sort()', names);
- for (var i = 0; JS('bool', '# < #.length', i, names); ++i) {
+ for (var i = 0; JS<bool>('!', '# < #.length', i, names); ++i) {
if (i > 0) {
buffer += ', ';
}
@@ -410,11 +410,11 @@
@JSExportName('is')
bool is_T(obj) {
- if (JS('bool', 'typeof # == "function"', obj)) {
+ if (JS('!', 'typeof # == "function"', obj)) {
var actual = JS('', '#[#]', obj, _runtimeType);
// If there's no actual type, it's a JS function.
// Allow them to subtype all Dart function types.
- return JS('bool', '# == null || !!#', actual, isSubtype(actual, this));
+ return JS('!', '# == null || !!#', actual, isSubtype(actual, this));
}
return false;
}
@@ -427,9 +427,9 @@
}))()''');
@JSExportName('as')
- as_T(obj, [@js_helper.notNull bool isImplicit = false]) {
+ as_T(obj, [@notNull bool isImplicit = false]) {
if (obj == null) return obj;
- if (JS('bool', 'typeof # == "function"', obj)) {
+ if (JS('!', 'typeof # == "function"', obj)) {
var actual = JS('', '#[#]', obj, _runtimeType);
// If there's no actual type, it's a JS function.
// Allow them to subtype all Dart function types.
@@ -466,14 +466,14 @@
for (int i = 0, n = JS('!', '#.length', typeArgs); i < n; ++i) {
if (i > 0) result += ', ';
var typeArg = JS('', '#[#]', typeArgs, i);
- if (JS('bool', '# !== #', typeArg, _dynamic)) allDynamic = false;
+ if (JS('!', '# !== #', typeArg, _dynamic)) allDynamic = false;
result += typeName(typeArg);
}
result += '>';
return allDynamic ? name : result;
}
- String get name => JS('String', '#', _name);
+ String get name => JS('!', '#', _name);
AbstractFunctionType get functionType {
var ft = _functionType;
@@ -507,7 +507,7 @@
GenericFunctionType(instantiateTypeParts, this._instantiateTypeBounds)
: _instantiateTypeParts = instantiateTypeParts,
- formalCount = JS('int', '#.length', instantiateTypeParts);
+ formalCount = JS('!', '#.length', instantiateTypeParts);
List<TypeVariable> get typeFormals {
if (_typeFormals != null) return _typeFormals;
@@ -548,7 +548,7 @@
if (i != 0) s += ", ";
s += JS<String>('!', '#[#].name', typeFormals, i);
var bound = typeBounds[i];
- if (JS('bool', '# !== # && # !== #', bound, dynamic, bound, Object)) {
+ if (JS('!', '# !== # && # !== #', bound, dynamic, bound, Object)) {
s += " extends $bound";
}
}
@@ -635,24 +635,25 @@
return defaults;
}
+ @notNull
@JSExportName('is')
bool is_T(obj) {
- if (JS('bool', 'typeof # == "function"', obj)) {
+ if (JS('!', 'typeof # == "function"', obj)) {
var actual = JS('', '#[#]', obj, _runtimeType);
- return JS('bool', '# != null && !!#', actual, isSubtype(actual, this));
+ return JS('!', '# != null && !!#', actual, isSubtype(actual, this));
}
return false;
}
@JSExportName('as')
as_T(obj) {
- if (obj == null || JS('bool', '#', is_T(obj))) return obj;
+ if (obj == null || is_T(obj)) return obj;
return castError(obj, this, false);
}
@JSExportName('_check')
check_T(obj) {
- if (obj == null || JS('bool', '#', is_T(obj))) return obj;
+ if (obj == null || is_T(obj)) return obj;
return castError(obj, this, true);
}
}
@@ -715,7 +716,7 @@
bool isType(obj) => JS('', '#[#] === #', obj, _runtimeType, Type);
void checkTypeBound(type, bound, name) {
- if (JS('bool', '#', isSubtype(type, bound))) return;
+ if (JS('!', '#', isSubtype(type, bound))) return;
throwTypeError('type `$type` does not extend `$bound`'
' of `$name`.');
@@ -835,12 +836,12 @@
// code generator happy though.
var map;
bool result;
- if (JS('bool', '!#.hasOwnProperty(#)', t1, _subtypeCache)) {
+ if (JS('!', '!#.hasOwnProperty(#)', t1, _subtypeCache)) {
JS('', '#[#] = # = new Map()', t1, _subtypeCache, map);
} else {
map = JS('', '#[#]', t1, _subtypeCache);
result = JS('bool|Null', '#.get(#)', map, t2);
- if (JS('bool', '# !== void 0', result)) return result;
+ if (JS('!', '# !== void 0', result)) return result;
}
result =
JS('bool|Null', '# === # || #(#, #, true)', t1, t2, _isSubtype, t1, t2);
@@ -850,13 +851,15 @@
final _subtypeCache = JS('', 'Symbol("_subtypeCache")');
-_isBottom(type) => JS('bool', '# == # || # == #', type, bottom, type, Null);
+@notNull
+bool _isBottom(type) => JS('!', '# == # || # == #', type, bottom, type, Null);
-_isTop(type) {
+@notNull
+bool _isTop(type) {
if (_isFutureOr(type)) {
return _isTop(JS('', '#[0]', getGenericArgs(type)));
}
- return JS('bool', '# == # || # == # || # == #', type, Object, type, dynamic,
+ return JS('!', '# == # || # == # || # == #', type, Object, type, dynamic,
type, void_);
}
@@ -979,7 +982,7 @@
return ${_isFunctionSubtype(t1, t2, isCovariant)};
})()''');
-_isInterfaceSubtype(t1, t2, isCovariant) => JS('', '''(() => {
+bool _isInterfaceSubtype(t1, t2, isCovariant) => JS('', '''(() => {
// We support Dart's covariant generics with the caveat that we do not
// substitute bottom for dynamic in subtyping rules.
// I.e., given T1, ..., Tn where at least one Ti != dynamic we disallow:
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/utils.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/utils.dart
index 87b3cbb..8e3b738 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/utils.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/utils.dart
@@ -39,13 +39,13 @@
/// This error indicates a strong mode specific failure, other than a type
/// assertion failure (TypeError) or CastError.
void throwTypeError(String message) {
- if (JS('bool', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
+ if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
throw new TypeErrorImpl(message);
}
/// This error indicates a bug in the runtime or the compiler.
void throwInternalError(String message) {
- if (JS('bool', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
+ if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
JS('', 'throw Error(#)', message);
}
@@ -103,14 +103,14 @@
copyProperty(to, from, name) {
var desc = getOwnPropertyDescriptor(from, name);
- if (JS('bool', '# == Symbol.iterator', name)) {
+ if (JS('!', '# == Symbol.iterator', name)) {
// On native types, Symbol.iterator may already be present.
// TODO(jmesserly): investigate if we still need this.
// If so, we need to find a better solution.
// See https://github.com/dart-lang/sdk/issues/28324
var existing = getOwnPropertyDescriptor(to, name);
if (existing != null) {
- if (JS('bool', '#.writable', existing)) {
+ if (JS('!', '#.writable', existing)) {
JS('', '#[#] = #.value', to, name, desc);
}
return;
diff --git a/pkg/dev_compiler/tool/input_sdk/private/debugger.dart b/pkg/dev_compiler/tool/input_sdk/private/debugger.dart
index 2d9982b..7b68c31 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/debugger.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/debugger.dart
@@ -918,15 +918,14 @@
/// Raw JS stack traces are used if $dartStackTraceUtility has not been
/// specified.
StackTraceMapper get stackTraceMapper {
- var _util = JS('', r'dart.global.$dartStackTraceUtility');
- return _util != null ? JS('StackTraceMapper', '#.mapper', _util) : null;
+ var _util = JS('', r'#.$dartStackTraceUtility', dart.global_);
+ return _util != null ? JS('!', '#.mapper', _util) : null;
}
/// This entry point is automatically invoked by the code generated by
/// Dart Dev Compiler
registerDevtoolsFormatter() {
- var formatters = [_devtoolsFormatter];
- JS('', 'dart.global.devtoolsFormatters = #', formatters);
+ JS('', '#.devtoolsFormatters = [#]', dart.global_, _devtoolsFormatter);
}
// Expose these methods here to facilitate writing debugger tests.
diff --git a/pkg/dev_compiler/tool/kernel_sdk.dart b/pkg/dev_compiler/tool/kernel_sdk.dart
index 38e9e65..ae5273a 100755
--- a/pkg/dev_compiler/tool/kernel_sdk.dart
+++ b/pkg/dev_compiler/tool/kernel_sdk.dart
@@ -22,10 +22,18 @@
var parserOptions = parser.parse(args);
var rest = parserOptions.rest;
- Directory.current = path.dirname(path.dirname(path.fromUri(Platform.script)));
+ var ddcPath = path.dirname(path.dirname(path.fromUri(Platform.script)));
+ Directory.current = ddcPath;
- var outputPath =
- path.absolute(rest.length > 0 ? rest[0] : 'gen/sdk/kernel/ddc_sdk.dill');
+ String outputPath;
+ if (rest.isNotEmpty) {
+ outputPath = path.absolute(rest[0]);
+ } else {
+ var sdkRoot = path.absolute(path.dirname(path.dirname(ddcPath)));
+ var buildDir = path.join(sdkRoot, Platform.isMacOS ? 'xcodebuild' : 'out');
+ var genDir = path.join(buildDir, 'ReleaseX64', 'gen', 'utils', 'dartdevc');
+ outputPath = path.join(genDir, 'kernel', 'ddc_sdk.dill');
+ }
var inputPath = path.absolute('tool/input_sdk');
var target = new DevCompilerTarget();
diff --git a/pkg/dev_compiler/tool/run.js b/pkg/dev_compiler/tool/run.js
deleted file mode 100644
index ec9eb24..0000000
--- a/pkg/dev_compiler/tool/run.js
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// This is a utility to run and debug an individual DDC compiled test.
-/// Tests can be run with either node or devtool (a Chrome-based utility with
-/// DOM APIs and developer tools support).
-///
-/// Install devtool via:
-/// > npm install -g devtool
-///
-/// Run via:
-/// > devtool tool/run.js -- corelib_2/apply2_test
-/// or
-/// > node tool/run.js corelib_2/apply2_test
-///
-/// See TODO below on async / unittest support.
-
-var args = process.argv.slice(2);
-if (args.length != 1) {
- throw new Error("Usage: devtool tool/run.js <test-module-name>");
-}
-var test = args[0];
-
-var requirejs = require('requirejs');
-var ddcdir = __dirname + '/../';
-requirejs.config({
- baseUrl: ddcdir + 'gen/codegen_output',
- paths: {
- dart_sdk: ddcdir + 'lib/js/amd/dart_sdk',
- async_helper: ddcdir + 'gen/codegen_output/pkg/async_helper',
- expect: ddcdir + 'gen/codegen_output/pkg/expect',
- js: ddcdir + 'gen/codegen_output/pkg/js',
- matcher: ddcdir + 'gen/codegen_output/pkg/matcher',
- minitest: ddcdir + 'gen/codegen_output/pkg/minitest',
- path: ddcdir + 'gen/codegen_output/pkg/path',
- stack_trace: ddcdir + 'gen/codegen_output/pkg/stack_trace',
- unittest: ddcdir + 'gen/codegen_output/pkg/unittest',
- }
-});
-
-// TODO(vsm): Factor out test framework code in test/browser/language_tests.js
-// and use here. Async tests and unittests won't work without it.
-var sdk = requirejs('dart_sdk');
-sdk.dart.ignoreWhitelistedErrors(false);
-
-let negative = /negative_test/.test(test);
-function finish(e) {
- if (negative) {
- if (e) {
- e = null;
- } else {
- e = new Error("test marked as 'negative' but did not throw");
- }
- }
- if (e) {
- console.log('Test ' + test + ' failed:\n' + e.toString());
- sdk.dart.stackPrint(e);
- } else {
- console.log('Test ' + test + ' passed.');
- }
-}
-
-sdk.dart.ignoreWhitelistedErrors(false);
-sdk._isolate_helper.startRootIsolate(() => {}, []);
-// Make it easier to debug test failures and required for formatter test that
-// assumes custom formatters are enabled.
-sdk._debugger.registerDevtoolsFormatter();
-
-var async_helper = requirejs('async_helper').async_helper;
-async_helper.asyncTestInitialize(finish);
-
-var module = requirejs(test);
-var lib = test.split('/').slice(-1)[0];
-try {
- if (module[lib]._expectRuntimeError) negative = true;
- var result = module[lib].main();
- // async_helper tests call finish directly - call here for all other
- // tests.
- if (!async_helper.asyncTestStarted) {
- if (!result || !(sdk.async.Future.is(result))) {
- finish();
- } else {
- // Wait iff result is a future
- result.then(sdk.dart.dynamic)(() => finish(), { onError: (e) => finish(e) });
- }
- }
-} catch (e) {
- finish(e);
-}
diff --git a/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart
index 49bcf07..b266feb 100644
--- a/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart
@@ -37,17 +37,17 @@
buffer.write("(");
if (formals != null) {
bool isFirst = true;
- for (TypeBuilder t in formals) {
+ for (dynamic t in formals) {
if (!isFirst) {
buffer.write(", ");
} else {
isFirst = false;
}
- buffer.write(t.fullNameForErrors);
+ buffer.write(t?.fullNameForErrors);
}
}
buffer.write(") -> ");
- buffer.write(returnType.fullNameForErrors);
+ buffer.write(returnType?.fullNameForErrors);
return buffer;
}
diff --git a/pkg/front_end/lib/src/fasta/compiler_context.dart b/pkg/front_end/lib/src/fasta/compiler_context.dart
index 1795c7e..2eda950 100644
--- a/pkg/front_end/lib/src/fasta/compiler_context.dart
+++ b/pkg/front_end/lib/src/fasta/compiler_context.dart
@@ -4,7 +4,7 @@
library fasta.compiler_context;
-import 'dart:async' show Zone, runZoned;
+import 'dart:async' show Future, Zone, runZoned;
import 'package:kernel/ast.dart' show Source;
@@ -101,25 +101,23 @@
/// Perform [action] in a [Zone] where [this] will be available as
/// `CompilerContext.current`.
- T runInContext<T>(T action(CompilerContext c)) {
- try {
- return runZoned(() => action(this),
- zoneValues: {compilerContextKey: this});
- } finally {
- clear();
- }
+ Future<T> runInContext<T>(Future<T> action(CompilerContext c)) {
+ return runZoned(
+ () => new Future<T>.sync(() => action(this)).whenComplete(clear),
+ zoneValues: {compilerContextKey: this});
}
/// Perform [action] in a [Zone] where [options] will be available as
/// `CompilerContext.current.options`.
- static T runWithOptions<T>(
- ProcessedOptions options, T action(CompilerContext c)) {
+ static Future<T> runWithOptions<T>(
+ ProcessedOptions options, Future<T> action(CompilerContext c)) {
return new CompilerContext(options).runInContext(action);
}
- static T runWithDefaultOptions<T>(T action(CompilerContext c)) {
- var options = new ProcessedOptions(new CompilerOptions());
- return new CompilerContext(options).runInContext(action);
+ static Future<T> runWithDefaultOptions<T>(
+ Future<T> action(CompilerContext c)) {
+ return new CompilerContext(new ProcessedOptions(new CompilerOptions()))
+ .runInContext(action);
}
static bool get enableColors {
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index 1f491c2..a9ab933 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -1056,6 +1056,38 @@
message: r"""Constructors can't have type parameters.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstructorWithWrongName = messageConstructorWithWrongName;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstructorWithWrongName = const MessageCode(
+ "ConstructorWithWrongName",
+ analyzerCode: "INVALID_CONSTRUCTOR_NAME",
+ dart2jsCode: "*fatal*",
+ severity: Severity.error,
+ message:
+ r"""The name of a constructor must match the name of the enclosing class.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+ templateConstructorWithWrongNameContext =
+ const Template<Message Function(String name)>(
+ messageTemplate: r"""The name of the enclosing class is '#name'.""",
+ withArguments: _withArgumentsConstructorWithWrongNameContext);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeConstructorWithWrongNameContext =
+ const Code<Message Function(String name)>("ConstructorWithWrongNameContext",
+ templateConstructorWithWrongNameContext,
+ severity: Severity.context);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConstructorWithWrongNameContext(String name) {
+ return new Message(codeConstructorWithWrongNameContext,
+ message: """The name of the enclosing class is '$name'.""",
+ arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeContinueOutsideOfLoop = messageContinueOutsideOfLoop;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2607,29 +2639,6 @@
message: r"""Illegal assignment to non-assignable expression.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name, String name2)>
- templateIllegalMethodName =
- const Template<Message Function(String name, String name2)>(
- messageTemplate: r"""'#name' isn't a legal method name.""",
- tipTemplate: r"""Did you mean '#name2'?""",
- withArguments: _withArgumentsIllegalMethodName);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, String name2)> codeIllegalMethodName =
- const Code<Message Function(String name, String name2)>(
- "IllegalMethodName",
- templateIllegalMethodName,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsIllegalMethodName(String name, String name2) {
- return new Message(codeIllegalMethodName,
- message: """'$name' isn't a legal method name.""",
- tip: """Did you mean '$name2'?""",
- arguments: {'name': name, 'name2': name2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(String name)> templateIllegalMixin =
const Template<Message Function(String name)>(
messageTemplate: r"""The type '#name' can't be mixed in.""",
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 0cfc1d8a..2a95602 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -89,7 +89,7 @@
{Uri entryPoint, bool fullComponent: false}) async {
ticker.reset();
entryPoint ??= context.options.inputs.single;
- return context.runInContext<Future<Component>>((CompilerContext c) async {
+ return context.runInContext<Component>((CompilerContext c) async {
IncrementalCompilerData data = new IncrementalCompilerData();
bool bypassCache = false;
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 0c388d7..c5612e8 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -3691,6 +3691,12 @@
}
@override
+ void beginTypeVariable(Token name) {
+ debugEvent("beginTypeVariable");
+ push(new Identifier(name));
+ }
+
+ @override
void handleNoTypeVariables(Token token) {
debugEvent("NoTypeVariables");
enterFunctionTypeScope(null);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
index c5291df..b2905ca 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
@@ -576,7 +576,7 @@
String documentationComment,
List<MetadataBuilder> metadata,
int modifiers,
- ConstructorReferenceBuilder constructorNameReference,
+ Object name,
List<FormalParameterBuilder> formals,
ConstructorReferenceBuilder redirectionTarget,
int charOffset,
@@ -588,19 +588,17 @@
// Nested declaration began in `OutlineBuilder.beginFactoryMethod`.
DeclarationBuilder<KernelTypeBuilder> factoryDeclaration =
endNestedDeclaration("#factory_method");
- Object name = constructorNameReference.name;
// Prepare the simple procedure name.
String procedureName;
String constructorName =
- computeAndValidateConstructorName(name, charOffset);
+ computeAndValidateConstructorName(name, charOffset, isFactory: true);
if (constructorName != null) {
procedureName = constructorName;
} else {
procedureName = name;
}
- assert(constructorNameReference.suffix == null);
KernelProcedureBuilder procedure;
if (redirectionTarget != null) {
procedure = new KernelRedirectingFactoryBuilder(
diff --git a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
index 65b8b20..9e8809f 100644
--- a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
@@ -392,8 +392,8 @@
}
@override
- void beginTypeVariable(Token token) {
- listener?.beginTypeVariable(token);
+ void beginTypeVariable(Token name) {
+ listener?.beginTypeVariable(name);
}
@override
diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart
index e7bcb52..8e26b03 100644
--- a/pkg/front_end/lib/src/fasta/parser/listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/listener.dart
@@ -898,13 +898,16 @@
logEvent("NoTypeArguments");
}
- void beginTypeVariable(Token token) {}
+ /// Handle the begin of a type formal parameter (e.g. "X extends Y").
+ /// Substructures:
+ /// - Metadata
+ void beginTypeVariable(Token name) {}
/// Handle the end of a type formal parameter (e.g. "X extends Y").
/// Substructures:
- /// - Metadata
- /// - Name (identifier)
/// - Type bound
+ ///
+ /// See [beginTypeVariable] for additional substructures.
void endTypeVariable(Token token, Token extendsOrSuper) {
logEvent("TypeVariable");
}
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index d1d73b2..e4e0063 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -1961,9 +1961,12 @@
/// ;
/// ```
Token parseTypeVariable(Token token) {
- listener.beginTypeVariable(token.next);
token = parseMetadataStar(token);
- token = ensureIdentifier(token, IdentifierContext.typeVariableDeclaration);
+ token = token.next.kind == IDENTIFIER_TOKEN
+ ? token.next
+ : IdentifierContext.typeVariableDeclaration
+ .ensureIdentifier(token, this);
+ listener.beginTypeVariable(token);
Token extendsOrSuper = null;
Token next = token.next;
if (optional('extends', next) || optional('super', next)) {
@@ -3232,7 +3235,10 @@
}
listener.beginFactoryMethod(beforeStart, externalToken, varFinalOrConst);
- token = parseConstructorReference(token);
+ token = ensureIdentifier(token, IdentifierContext.methodDeclaration);
+ token = parseQualifiedRestOpt(
+ token, IdentifierContext.methodDeclarationContinuation);
+ token = parseMethodTypeVar(token);
token = parseFormalParametersRequiredOpt(token, MemberKind.Factory);
Token asyncToken = token.next;
token = parseAsyncModifierOpt(token);
@@ -4276,25 +4282,55 @@
Token beginToken = token = token.next;
assert(optional('[', token) || optional('[]', token));
int count = 0;
- if (optional('[', token)) {
- bool old = mayParseFunctionExpressions;
- mayParseFunctionExpressions = true;
- do {
- if (optional(']', token.next)) {
- token = token.next;
+ if (optional('[]', token)) {
+ token = rewriteSquareBrackets(beforeToken).next;
+ listener.handleLiteralList(0, token, constKeyword, token.next);
+ return token.next;
+ }
+ bool old = mayParseFunctionExpressions;
+ mayParseFunctionExpressions = true;
+ while (true) {
+ Token next = token.next;
+ if (optional(']', next)) {
+ token = next;
+ break;
+ }
+ token = parseExpression(token);
+ next = token.next;
+ ++count;
+ if (!optional(',', next)) {
+ if (optional(']', next)) {
+ token = next;
break;
}
- token = parseExpression(token).next;
- ++count;
- } while (optional(',', token));
- mayParseFunctionExpressions = old;
- listener.handleLiteralList(count, beginToken, constKeyword, token);
- expect(']', token);
- return token;
+
+ // Recovery
+ if (!isExpressionStartForRecovery(next)) {
+ if (beginToken.endGroup.isSynthetic) {
+ // The scanner has already reported an error,
+ // but inserted `]` in the wrong place.
+ token = rewriter.moveSynthetic(token, beginToken.endGroup);
+ } else {
+ // Report an error and jump to the end of the list.
+ reportRecoverableError(
+ next, fasta.templateExpectedButGot.withArguments(']'));
+ token = beginToken.endGroup;
+ }
+ break;
+ }
+ // This looks like the start of an expression.
+ // Report an error, insert the comma, and continue parsing.
+ next = rewriteAndRecover(
+ token,
+ fasta.templateExpectedButGot.withArguments(','),
+ new SyntheticToken(TokenType.COMMA, next.offset))
+ .next;
+ }
+ token = next;
}
- token = rewriteSquareBrackets(beforeToken).next;
- listener.handleLiteralList(0, token, constKeyword, token.next);
- return token.next;
+ mayParseFunctionExpressions = old;
+ listener.handleLiteralList(count, beginToken, constKeyword, token);
+ return token;
}
/// This method parses the portion of a map literal that starts with the left
diff --git a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
index 771ed1c..2b8f311 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
@@ -138,10 +138,9 @@
@override
Token skipType(Token token) {
- token = token.next.next;
- assert(optional('<', token));
- assert(token.endGroup != null || optional('>>', token.next.next));
- return token.endGroup ?? token.next;
+ token = token.next;
+ assert(token.isKeywordOrIdentifier);
+ return simpleTypeArgument1.skip(token);
}
}
@@ -510,10 +509,9 @@
Listener listener = parser.listener;
listener.beginTypeVariables(token);
token = token.next;
- listener.beginTypeVariable(token);
listener.beginMetadataStar(token);
listener.endMetadataStar(0);
- listener.handleIdentifier(token, IdentifierContext.typeVariableDeclaration);
+ listener.beginTypeVariable(token);
listener.handleNoType(token);
token = processEndGroup(token, start, parser);
listener.endTypeVariable(token, null);
@@ -527,9 +525,9 @@
assert(optional('<', token));
assert(token.endGroup != null ||
(optional('>', token.next.next) || optional('>>', token.next.next)));
- return (optional('>>', token.endGroup ?? token.next.next)
- ? token.next
- : token.next.next);
+ return (optional('>', token.endGroup ?? token.next.next)
+ ? token.next.next
+ : token.next);
}
}
@@ -659,10 +657,12 @@
parser.listener.beginTypeVariables(start);
int count = 0;
while (true) {
- parser.listener.beginTypeVariable(next.next);
token = parser.parseMetadataStar(next);
- token = parser.ensureIdentifier(
- token, IdentifierContext.typeVariableDeclaration);
+ token = token.next.kind == IDENTIFIER_TOKEN
+ ? token.next
+ : IdentifierContext.typeVariableDeclaration
+ .ensureIdentifier(token, parser);
+ parser.listener.beginTypeVariable(token);
Token extendsOrSuper = null;
next = token.next;
if (optional('extends', next) || optional('super', next)) {
diff --git a/pkg/front_end/lib/src/fasta/source/diet_listener.dart b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
index a00fc34..eeef8b1 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -444,7 +444,7 @@
@override
void endTypeVariable(Token token, Token extendsOrSuper) {
debugEvent("TypeVariable");
- discard(2); // Name and metadata.
+ discard(1); // Metadata.
}
@override
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index 5086d9e..e65dcf6 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -397,6 +397,7 @@
push(typeVariables ?? NullValue.TypeVariables);
library.currentDeclaration
..name = name.lexeme
+ ..charOffset = name.charOffset
..typeVariables = typeVariables;
push(abstractToken != null ? abstractMask : 0);
}
@@ -409,6 +410,7 @@
push(typeVariables ?? NullValue.TypeVariables);
library.currentDeclaration
..name = name.lexeme
+ ..charOffset = name.charOffset
..typeVariables = typeVariables;
push(abstractToken != null ? abstractMask : 0);
}
@@ -1095,6 +1097,13 @@
}
@override
+ void beginTypeVariable(Token token) {
+ debugEvent("beginTypeVariable");
+ push(token.lexeme);
+ push(token.charOffset);
+ }
+
+ @override
void endTypeVariable(Token token, Token extendsOrSuper) {
debugEvent("endTypeVariable");
TypeBuilder bound = pop();
@@ -1136,6 +1145,7 @@
@override
void beginFactoryMethod(
Token lastConsumed, Token externalToken, Token constToken) {
+ inConstructor = true;
library.beginNestedDeclaration("#factory_method", hasMembers: false);
push((externalToken != null ? externalMask : 0) |
(constToken != null ? constMask : 0));
@@ -1152,7 +1162,9 @@
}
List<FormalParameterBuilder> formals = pop();
int formalsOffset = pop();
- var name = pop();
+ pop(); // type variables
+ int charOffset = pop();
+ Object name = pop();
int modifiers = pop();
List<MetadataBuilder> metadata = pop();
String documentationComment = getDocumentationComment(beginToken);
@@ -1163,11 +1175,12 @@
name,
formals,
redirectionTarget,
- factoryKeyword.next.charOffset,
+ charOffset,
formalsOffset,
endToken.charOffset,
nativeMethodName);
nativeMethodName = null;
+ inConstructor = false;
}
@override
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 8e28bcc..93390f9 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -39,6 +39,7 @@
import '../fasta_codes.dart'
show
+ messageConstructorWithWrongName,
messageExpectedUri,
messageMemberWithSameNameAsClass,
messagePartOfSelf,
@@ -49,7 +50,7 @@
templateDeferredPrefixDuplicated,
templateDeferredPrefixDuplicatedCause,
templateDuplicatedDefinition,
- templateIllegalMethodName,
+ templateConstructorWithWrongNameContext,
templateMissingPartOf,
templatePartOfLibraryNameMismatch,
templatePartOfUriMismatch,
@@ -193,7 +194,8 @@
}
}
- String computeAndValidateConstructorName(Object name, int charOffset) {
+ String computeAndValidateConstructorName(Object name, int charOffset,
+ {isFactory: false}) {
String className = currentDeclaration.name;
String prefix;
String suffix;
@@ -207,15 +209,20 @@
if (prefix == className) {
return suffix ?? "";
}
- if (suffix == null) {
+ if (suffix == null && !isFactory) {
// A legal name for a regular method, but not for a constructor.
return null;
}
- addCompileTimeError(
- templateIllegalMethodName.withArguments("$name", "$className.$suffix"),
- charOffset,
- noLength,
- fileUri);
+
+ addProblem(
+ messageConstructorWithWrongName, charOffset, prefix.length, fileUri,
+ context: [
+ templateConstructorWithWrongNameContext
+ .withArguments(currentDeclaration.name)
+ .withLocation(uri, currentDeclaration.charOffset,
+ currentDeclaration.name.length)
+ ]);
+
return suffix;
}
@@ -424,7 +431,7 @@
String documentationComment,
List<MetadataBuilder> metadata,
int modifiers,
- ConstructorReferenceBuilder name,
+ Object name,
List<FormalParameterBuilder> formals,
ConstructorReferenceBuilder redirectionTarget,
int charOffset,
@@ -747,16 +754,20 @@
String name;
+ // Offset of name token, updated by the outline builder along
+ // with the name as the current declaration changes.
+ int charOffset;
+
List<TypeVariableBuilder> typeVariables;
- DeclarationBuilder(
- this.members, this.setters, this.constructors, this.name, this.parent) {
+ DeclarationBuilder(this.members, this.setters, this.constructors, this.name,
+ this.charOffset, this.parent) {
assert(name != null);
}
DeclarationBuilder.library()
: this(<String, Declaration>{}, <String, Declaration>{}, null, "library",
- null);
+ -1, null);
DeclarationBuilder createNested(String name, bool hasMembers) {
return new DeclarationBuilder<T>(
@@ -764,6 +775,7 @@
hasMembers ? <String, MemberBuilder>{} : null,
hasMembers ? <String, MemberBuilder>{} : null,
name,
+ -1,
this);
}
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index c836042..47d7166 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -201,8 +201,6 @@
GetterNotFound/example: Fail
GetterWithFormals/example: Fail
IllegalAssignmentToNonAssignable/script1: Fail
-IllegalMethodName/analyzerCode: Fail
-IllegalMethodName/example: Fail
IllegalMixin/analyzerCode: Fail
IllegalMixin/example: Fail
IllegalMixinDueToConstructors/analyzerCode: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index e37ae4a..4eb8ac6 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -1028,6 +1028,22 @@
script:
- "class C { C<T>() {} }"
- "class C { C.foo<T>() {} }"
+ - "class C { factory C<T>() => null; }"
+ - "class C { factory C.foo<T>() => null; }"
+
+ConstructorWithWrongName:
+ template: "The name of a constructor must match the name of the enclosing class."
+ severity: ERROR
+ analyzerCode: INVALID_CONSTRUCTOR_NAME
+ dart2jsCode: "*fatal*"
+ script:
+ - "class A { B.foo() {} }"
+ - "class A { factory B() => null; }"
+ - "class A { factory B.foo() => null; }"
+
+ConstructorWithWrongNameContext:
+ template: "The name of the enclosing class is '#name'."
+ severity: CONTEXT
FieldInitializerOutsideConstructor:
template: "Field formal parameters can only be used in a constructor."
@@ -1557,10 +1573,6 @@
analyzerCode: INVALID_METHOD_OVERRIDE
dart2jsCode: "*ignored*"
-IllegalMethodName:
- template: "'#name' isn't a legal method name."
- tip: "Did you mean '#name2'?"
-
PartOfSelf:
template: "A file can't be a part of itself."
diff --git a/pkg/front_end/test/fasta/expression_test.dart b/pkg/front_end/test/fasta/expression_test.dart
index ee56f71..91f716e 100644
--- a/pkg/front_end/test/fasta/expression_test.dart
+++ b/pkg/front_end/test/fasta/expression_test.dart
@@ -66,7 +66,7 @@
MemoryFileSystem get fileSystem => options.fileSystem;
- T runInContext<T>(T action(CompilerContext c)) {
+ Future<T> runInContext<T>(Future<T> action(CompilerContext c)) {
return compilerContext.runInContext<T>(action);
}
diff --git a/pkg/front_end/test/fasta/incremental_test.dart b/pkg/front_end/test/fasta/incremental_test.dart
index 401d89b..d6e5f8d 100644
--- a/pkg/front_end/test/fasta/incremental_test.dart
+++ b/pkg/front_end/test/fasta/incremental_test.dart
@@ -70,7 +70,7 @@
MemoryFileSystem get fileSystem => options.fileSystem;
- T runInContext<T>(T action(CompilerContext c)) {
+ Future<T> runInContext<T>(Future<T> action(CompilerContext c)) {
return compilerContext.runInContext<T>(action);
}
diff --git a/pkg/front_end/test/fasta/parser/type_info_test.dart b/pkg/front_end/test/fasta/parser/type_info_test.dart
index f208149..1299b8d 100644
--- a/pkg/front_end/test/fasta/parser/type_info_test.dart
+++ b/pkg/front_end/test/fasta/parser/type_info_test.dart
@@ -282,10 +282,9 @@
]);
expectComplexInfo('Function<T>() m', expectedAfter: 'm', expectedCalls: [
'beginTypeVariables <',
- 'beginTypeVariable T',
'beginMetadataStar T',
'endMetadataStar 0',
- 'handleIdentifier T typeVariableDeclaration',
+ 'beginTypeVariable T',
'handleNoType T',
'endTypeVariable > null',
'endTypeVariables 1 < >',
@@ -315,10 +314,9 @@
]);
expectComplexInfo('Function<T>(int) m', expectedAfter: 'm', expectedCalls: [
'beginTypeVariables <',
- 'beginTypeVariable T',
'beginMetadataStar T',
'endMetadataStar 0',
- 'handleIdentifier T typeVariableDeclaration',
+ 'beginTypeVariable T',
'handleNoType T',
'endTypeVariable > null',
'endTypeVariables 1 < >',
@@ -684,19 +682,17 @@
required: true,
expectedCalls: [
'beginTypeVariables <',
- 'beginTypeVariable T',
'beginMetadataStar T',
'endMetadataStar 0',
- 'handleIdentifier T typeVariableDeclaration',
+ 'beginTypeVariable T',
'handleNoType T',
'endTypeVariable > null',
'endTypeVariables 1 < >',
'beginFunctionType C',
'beginTypeVariables <',
- 'beginTypeVariable T',
'beginMetadataStar T',
'endMetadataStar 0',
- 'handleIdentifier T typeVariableDeclaration',
+ 'beginTypeVariable T',
'handleNoType T',
'endTypeVariable > null',
'endTypeVariables 1 < >',
@@ -863,10 +859,9 @@
expect(simpleTypeArgument1.parseVariables(start, new Parser(listener)), gt);
expect(listener.calls, [
'beginTypeVariables <',
- 'beginTypeVariable T',
'beginMetadataStar T',
'endMetadataStar 0',
- 'handleIdentifier T typeVariableDeclaration',
+ 'beginTypeVariable T',
'handleNoType T',
'endTypeVariable > null',
'endTypeVariables 1 < >',
@@ -1041,26 +1036,23 @@
void test_computeTypeParam_complex() {
expectComplexTypeParam('<S,T>', expectedCalls: [
'beginTypeVariables <',
- 'beginTypeVariable S',
'beginMetadataStar S',
'endMetadataStar 0',
- 'handleIdentifier S typeVariableDeclaration',
+ 'beginTypeVariable S',
'handleNoType S',
'endTypeVariable , null',
- 'beginTypeVariable T',
'beginMetadataStar T',
'endMetadataStar 0',
- 'handleIdentifier T typeVariableDeclaration',
+ 'beginTypeVariable T',
'handleNoType T',
'endTypeVariable > null',
'endTypeVariables 2 < >',
]);
expectComplexTypeParam('<S extends T>', expectedCalls: [
'beginTypeVariables <',
- 'beginTypeVariable S',
'beginMetadataStar S',
'endMetadataStar 0',
- 'handleIdentifier S typeVariableDeclaration',
+ 'beginTypeVariable S',
'handleIdentifier T typeReference',
'handleNoTypeArguments >',
'handleType T >',
@@ -1069,10 +1061,9 @@
]);
expectComplexTypeParam('<S super T>', expectedCalls: [
'beginTypeVariables <',
- 'beginTypeVariable S',
'beginMetadataStar S',
'endMetadataStar 0',
- 'handleIdentifier S typeVariableDeclaration',
+ 'beginTypeVariable S',
'handleIdentifier T typeReference',
'handleNoTypeArguments >',
'handleType T >',
@@ -1081,10 +1072,9 @@
]);
expectComplexTypeParam('<S extends List<T>>', expectedCalls: [
'beginTypeVariables <',
- 'beginTypeVariable S',
'beginMetadataStar S',
'endMetadataStar 0',
- 'handleIdentifier S typeVariableDeclaration',
+ 'beginTypeVariable S',
'handleIdentifier List typeReference',
'beginTypeArguments <',
'handleIdentifier T typeReference',
@@ -1097,16 +1087,14 @@
]);
expectComplexTypeParam('<R, S extends void Function()>', expectedCalls: [
'beginTypeVariables <',
- 'beginTypeVariable R',
'beginMetadataStar R',
'endMetadataStar 0',
- 'handleIdentifier R typeVariableDeclaration',
+ 'beginTypeVariable R',
'handleNoType R',
'endTypeVariable , null',
- 'beginTypeVariable S',
'beginMetadataStar S',
'endMetadataStar 0',
- 'handleIdentifier S typeVariableDeclaration',
+ 'beginTypeVariable S',
'handleNoTypeVariables (',
'beginFunctionType void',
'handleVoidKeyword void',
@@ -1118,7 +1106,6 @@
]);
expectComplexTypeParam('<@A S,T>', expectedCalls: [
'beginTypeVariables <',
- 'beginTypeVariable @',
'beginMetadataStar @',
'beginMetadata @',
'handleIdentifier A metadataReference',
@@ -1126,20 +1113,18 @@
'handleNoArguments S',
'endMetadata @ null S',
'endMetadataStar 1',
- 'handleIdentifier S typeVariableDeclaration',
+ 'beginTypeVariable S',
'handleNoType S',
'endTypeVariable , null',
- 'beginTypeVariable T',
'beginMetadataStar T',
'endMetadataStar 0',
- 'handleIdentifier T typeVariableDeclaration',
+ 'beginTypeVariable T',
'handleNoType T',
'endTypeVariable > null',
'endTypeVariables 2 < >',
]);
expectComplexTypeParam('<@A() S,T>', expectedCalls: [
'beginTypeVariables <',
- 'beginTypeVariable @',
'beginMetadataStar @',
'beginMetadata @',
'handleIdentifier A metadataReference',
@@ -1148,20 +1133,18 @@
'endArguments 0 ( )',
'endMetadata @ null S',
'endMetadataStar 1',
- 'handleIdentifier S typeVariableDeclaration',
+ 'beginTypeVariable S',
'handleNoType S',
'endTypeVariable , null',
- 'beginTypeVariable T',
'beginMetadataStar T',
'endMetadataStar 0',
- 'handleIdentifier T typeVariableDeclaration',
+ 'beginTypeVariable T',
'handleNoType T',
'endTypeVariable > null',
'endTypeVariables 2 < >',
]);
expectComplexTypeParam('<@A() @B S,T>', expectedCalls: [
'beginTypeVariables <',
- 'beginTypeVariable @',
'beginMetadataStar @',
'beginMetadata @',
'handleIdentifier A metadataReference',
@@ -1175,13 +1158,12 @@
'handleNoArguments S',
'endMetadata @ null S',
'endMetadataStar 2',
- 'handleIdentifier S typeVariableDeclaration',
+ 'beginTypeVariable S',
'handleNoType S',
'endTypeVariable , null',
- 'beginTypeVariable T',
'beginMetadataStar T',
'endMetadataStar 0',
- 'handleIdentifier T typeVariableDeclaration',
+ 'beginTypeVariable T',
'handleNoType T',
'endTypeVariable > null',
'endTypeVariables 2 < >',
@@ -1193,10 +1175,9 @@
error(codeUnexpectedToken, 3, 8),
], expectedCalls: [
'beginTypeVariables <',
- 'beginTypeVariable S',
'beginMetadataStar S',
'endMetadataStar 0',
- 'handleIdentifier S typeVariableDeclaration',
+ 'beginTypeVariable S',
'handleNoType S',
'endTypeVariable Function null',
'endTypeVariables 1 < >',
@@ -1206,10 +1187,9 @@
error(codeUnexpectedToken, 1, 4),
], expectedCalls: [
'beginTypeVariables <',
- 'beginTypeVariable void',
'beginMetadataStar void',
'endMetadataStar 0',
- 'handleIdentifier typeVariableDeclaration',
+ 'beginTypeVariable ',
'handleNoType ',
'endTypeVariable void null',
'endTypeVariables 1 < >',
@@ -1218,10 +1198,9 @@
error(codeUnexpectedToken, 2, 1),
], expectedCalls: [
'beginTypeVariables <',
- 'beginTypeVariable S',
'beginMetadataStar S',
'endMetadataStar 0',
- 'handleIdentifier S typeVariableDeclaration',
+ 'beginTypeVariable S',
'handleNoType S',
'endTypeVariable < null',
'endTypeVariables 1 < >',
@@ -1513,8 +1492,8 @@
}
@override
- void beginTypeVariable(Token token) {
- calls.add('beginTypeVariable $token');
+ void beginTypeVariable(Token name) {
+ calls.add('beginTypeVariable $name');
}
@override
diff --git a/pkg/front_end/test/scanner_test.dart b/pkg/front_end/test/scanner_test.dart
index d03ee59..3878155 100644
--- a/pkg/front_end/test/scanner_test.dart
+++ b/pkg/front_end/test/scanner_test.dart
@@ -1279,7 +1279,7 @@
new StringToken(TokenType.STRING, "", 3),
new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 3),
];
- var expectedErrors = [];
+ var expectedErrors = <TestError>[];
if (usingFasta) {
// Fasta scanner inserts a synthetic identifier
expectedTokens.addAll([
@@ -1305,7 +1305,7 @@
new StringToken(TokenType.STRING, "'", 0),
new StringToken(TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 1),
];
- var expectedErrors = [];
+ var expectedErrors = <TestError>[];
if (usingFasta) {
expectedTokens.addAll([
new SyntheticStringToken(TokenType.IDENTIFIER, "", 2),
diff --git a/pkg/front_end/testcases/inference/bug33324.dart b/pkg/front_end/testcases/inference/bug33324.dart
new file mode 100644
index 0000000..cdce5f17
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug33324.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test checks that the greatest closure uses 'dynamic' and not Object as
+// the top type.
+
+int foo() {
+ Function f = (x) => x;
+ var l = ["bar"].map(f).toList();
+ l.add(42);
+ return l.first.length;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/inference/bug33324.dart.direct.expect b/pkg/front_end/testcases/inference/bug33324.dart.direct.expect
new file mode 100644
index 0000000..2e1ecb9
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug33324.dart.direct.expect
@@ -0,0 +1,11 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method foo() → core::int {
+ core::Function f = (dynamic x) → dynamic => x;
+ dynamic l = <dynamic>["bar"].map(f).toList();
+ l.add(42);
+ return l.first.length;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/bug33324.dart.direct.transformed.expect b/pkg/front_end/testcases/inference/bug33324.dart.direct.transformed.expect
new file mode 100644
index 0000000..2e1ecb9
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug33324.dart.direct.transformed.expect
@@ -0,0 +1,11 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method foo() → core::int {
+ core::Function f = (dynamic x) → dynamic => x;
+ dynamic l = <dynamic>["bar"].map(f).toList();
+ l.add(42);
+ return l.first.length;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/bug33324.dart.outline.expect b/pkg/front_end/testcases/inference/bug33324.dart.outline.expect
new file mode 100644
index 0000000..06c9cfc
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug33324.dart.outline.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method foo() → core::int
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/inference/bug33324.dart.strong.expect b/pkg/front_end/testcases/inference/bug33324.dart.strong.expect
new file mode 100644
index 0000000..f88135b
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug33324.dart.strong.expect
@@ -0,0 +1,11 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method foo() → core::int {
+ core::Function f = (dynamic x) → dynamic => x;
+ core::List<dynamic> l = <core::String>["bar"].{core::Iterable::map}<dynamic>(f as{TypeError} (core::String) → dynamic).{core::Iterable::toList}();
+ l.{core::List::add}(42);
+ return l.{core::Iterable::first}.length as{TypeError} core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/bug33324.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/bug33324.dart.strong.transformed.expect
new file mode 100644
index 0000000..f88135b
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug33324.dart.strong.transformed.expect
@@ -0,0 +1,11 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method foo() → core::int {
+ core::Function f = (dynamic x) → dynamic => x;
+ core::List<dynamic> l = <core::String>["bar"].{core::Iterable::map}<dynamic>(f as{TypeError} (core::String) → dynamic).{core::Iterable::toList}();
+ l.{core::List::add}(42);
+ return l.{core::Iterable::first}.length as{TypeError} core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.expect b/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.expect
index e3ccda9..e9adaf2 100644
--- a/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.expect
@@ -10,6 +10,6 @@
return (self::C::T y) → core::Null {};
}
static method test(self::C<core::String> c) → void {
- (core::int) → (core::String) → void tearoff = c.{self::C::f} as{TypeError} <U extends core::Object>(U) → (core::String) → void<core::int>;
+ (core::int) → (core::String) → void tearoff = c.{self::C::f} as{TypeError} <U extends core::Object = dynamic>(U) → (core::String) → void<core::int>;
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.transformed.expect
index e3ccda9..e9adaf2 100644
--- a/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/instantiate_tearoff_after_contravariance_check.dart.strong.transformed.expect
@@ -10,6 +10,6 @@
return (self::C::T y) → core::Null {};
}
static method test(self::C<core::String> c) → void {
- (core::int) → (core::String) → void tearoff = c.{self::C::f} as{TypeError} <U extends core::Object>(U) → (core::String) → void<core::int>;
+ (core::int) → (core::String) → void tearoff = c.{self::C::f} as{TypeError} <U extends core::Object = dynamic>(U) → (core::String) → void<core::int>;
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/qualified.dart.direct.expect b/pkg/front_end/testcases/qualified.dart.direct.expect
index 545aedf..9d40d19 100644
--- a/pkg/front_end/testcases/qualified.dart.direct.expect
+++ b/pkg/front_end/testcases/qualified.dart.direct.expect
@@ -25,7 +25,9 @@
static factory b<T extends core::Object = dynamic>() → self::C<self::C::b::T>
let dynamic #redirecting_factory = lib::C::b in let self::C::b::T #typeArg0 = null in invalid-expression;
}
-static const field dynamic #errors = const <dynamic>["pkg/front_end/testcases/qualified.dart:11:19: Error: Type 'lib.Missing' not found.
+static const field dynamic #errors = const <dynamic>["pkg/front_end/testcases/qualified.dart:13:11: Error: The name of a constructor must match the name of the enclosing class.
+ factory WrongName() {}
+ ^^^^^^^^^", "pkg/front_end/testcases/qualified.dart:11:19: Error: Type 'lib.Missing' not found.
class Bad extends lib.Missing {
^"]/* from null */;
static method main() → dynamic {
diff --git a/pkg/front_end/testcases/qualified.dart.direct.transformed.expect b/pkg/front_end/testcases/qualified.dart.direct.transformed.expect
index de3c17e..34fd3f9 100644
--- a/pkg/front_end/testcases/qualified.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/qualified.dart.direct.transformed.expect
@@ -31,7 +31,9 @@
static factory b<T extends core::Object = dynamic>() → self::C<self::C::b::T>
let dynamic #redirecting_factory = lib::C::b in let self::C::b::T #typeArg0 = null in invalid-expression;
}
-static const field dynamic #errors = const <dynamic>["pkg/front_end/testcases/qualified.dart:11:19: Error: Type 'lib.Missing' not found.
+static const field dynamic #errors = const <dynamic>["pkg/front_end/testcases/qualified.dart:13:11: Error: The name of a constructor must match the name of the enclosing class.
+ factory WrongName() {}
+ ^^^^^^^^^", "pkg/front_end/testcases/qualified.dart:11:19: Error: Type 'lib.Missing' not found.
class Bad extends lib.Missing {
^"]/* from null */;
static method main() → dynamic {
diff --git a/pkg/front_end/testcases/qualified.dart.strong.expect b/pkg/front_end/testcases/qualified.dart.strong.expect
index 9dceec4..1b186df 100644
--- a/pkg/front_end/testcases/qualified.dart.strong.expect
+++ b/pkg/front_end/testcases/qualified.dart.strong.expect
@@ -25,13 +25,13 @@
static factory b<T extends core::Object = dynamic>() → self::C<self::C::b::T>
let dynamic #redirecting_factory = lib::C::b in let self::C::b::T #typeArg0 = null in invalid-expression;
}
-static const field dynamic #errors = const <dynamic>["pkg/front_end/testcases/qualified.dart:12:3: Error: Type 'lib.Missing' not found.
+static const field dynamic #errors = const <dynamic>["pkg/front_end/testcases/qualified.dart:13:11: Error: The name of a constructor must match the name of the enclosing class.
+ factory WrongName() {}
+ ^^^^^^^^^", "pkg/front_end/testcases/qualified.dart:12:3: Error: Type 'lib.Missing' not found.
lib.Missing method() {}
^", "pkg/front_end/testcases/qualified.dart:11:19: Error: Type 'lib.Missing' not found.
class Bad extends lib.Missing {
- ^", "pkg/front_end/testcases/qualified.dart:13:11: Error: Couldn't find constructor 'WrongName'.
- factory WrongName() {}
- ^"]/* from null */;
+ ^"]/* from null */;
static method main() → dynamic {
new self::C::•<core::String>();
new self::C::a<core::String>();
diff --git a/pkg/front_end/testcases/qualified.dart.strong.transformed.expect b/pkg/front_end/testcases/qualified.dart.strong.transformed.expect
index 2c96429..b00d2b5 100644
--- a/pkg/front_end/testcases/qualified.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/qualified.dart.strong.transformed.expect
@@ -31,13 +31,13 @@
static factory b<T extends core::Object = dynamic>() → self::C<self::C::b::T>
let <T extends core::Object = dynamic>() → lib::C<lib::C::b::T> #redirecting_factory = lib::C::b in let self::C::b::T #typeArg0 = null in invalid-expression;
}
-static const field dynamic #errors = const <dynamic>["pkg/front_end/testcases/qualified.dart:12:3: Error: Type 'lib.Missing' not found.
+static const field dynamic #errors = const <dynamic>["pkg/front_end/testcases/qualified.dart:13:11: Error: The name of a constructor must match the name of the enclosing class.
+ factory WrongName() {}
+ ^^^^^^^^^", "pkg/front_end/testcases/qualified.dart:12:3: Error: Type 'lib.Missing' not found.
lib.Missing method() {}
^", "pkg/front_end/testcases/qualified.dart:11:19: Error: Type 'lib.Missing' not found.
class Bad extends lib.Missing {
- ^", "pkg/front_end/testcases/qualified.dart:13:11: Error: Couldn't find constructor 'WrongName'.
- factory WrongName() {}
- ^"]/* from null */;
+ ^"]/* from null */;
static method main() → dynamic {
new self::C::•<core::String>();
new self::C::a<core::String>();
diff --git a/pkg/front_end/testcases/regress/issue_30838.dart.direct.expect b/pkg/front_end/testcases/regress/issue_30838.dart.direct.expect
index 9e4af92..9efb697 100644
--- a/pkg/front_end/testcases/regress/issue_30838.dart.direct.expect
+++ b/pkg/front_end/testcases/regress/issue_30838.dart.direct.expect
@@ -4,7 +4,7 @@
typedef Foo<S extends core::Object = dynamic> = <T extends core::Object = dynamic>(T) → S;
class A extends core::Object {
- field <T extends core::Object>(T) → core::int f = null;
+ field <T extends core::Object = dynamic>(T) → core::int f = null;
synthetic constructor •() → void
: super core::Object::•()
;
@@ -14,7 +14,7 @@
}
static method foo<T extends core::Object = dynamic>(self::foo::T x) → core::int
return 3;
-static method bar() → <T extends core::Object>(T) → core::int
+static method bar() → <T extends core::Object = dynamic>(T) → core::int
return self::foo;
static method test1() → void {
self::bar().call<core::String>("hello");
diff --git a/pkg/front_end/testcases/regress/issue_30838.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_30838.dart.direct.transformed.expect
index 9e4af92..9efb697 100644
--- a/pkg/front_end/testcases/regress/issue_30838.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_30838.dart.direct.transformed.expect
@@ -4,7 +4,7 @@
typedef Foo<S extends core::Object = dynamic> = <T extends core::Object = dynamic>(T) → S;
class A extends core::Object {
- field <T extends core::Object>(T) → core::int f = null;
+ field <T extends core::Object = dynamic>(T) → core::int f = null;
synthetic constructor •() → void
: super core::Object::•()
;
@@ -14,7 +14,7 @@
}
static method foo<T extends core::Object = dynamic>(self::foo::T x) → core::int
return 3;
-static method bar() → <T extends core::Object>(T) → core::int
+static method bar() → <T extends core::Object = dynamic>(T) → core::int
return self::foo;
static method test1() → void {
self::bar().call<core::String>("hello");
diff --git a/pkg/front_end/testcases/regress/issue_30838.dart.outline.expect b/pkg/front_end/testcases/regress/issue_30838.dart.outline.expect
index 55709ba..10ab505 100644
--- a/pkg/front_end/testcases/regress/issue_30838.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_30838.dart.outline.expect
@@ -4,7 +4,7 @@
typedef Foo<S extends core::Object = dynamic> = <T extends core::Object = dynamic>(T) → S;
class A extends core::Object {
- field <T extends core::Object>(T) → core::int f;
+ field <T extends core::Object = dynamic>(T) → core::int f;
synthetic constructor •() → void
;
method test() → void
@@ -12,7 +12,7 @@
}
static method foo<T extends core::Object = dynamic>(self::foo::T x) → core::int
;
-static method bar() → <T extends core::Object>(T) → core::int
+static method bar() → <T extends core::Object = dynamic>(T) → core::int
;
static method test1() → void
;
diff --git a/pkg/front_end/testcases/regress/issue_30838.dart.strong.expect b/pkg/front_end/testcases/regress/issue_30838.dart.strong.expect
index f08b8e7..7526f86 100644
--- a/pkg/front_end/testcases/regress/issue_30838.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_30838.dart.strong.expect
@@ -4,7 +4,7 @@
typedef Foo<S extends core::Object = dynamic> = <T extends core::Object = dynamic>(T) → S;
class A extends core::Object {
- field <T extends core::Object>(T) → core::int f = null;
+ field <T extends core::Object = dynamic>(T) → core::int f = null;
synthetic constructor •() → void
: super core::Object::•()
;
@@ -14,7 +14,7 @@
}
static method foo<T extends core::Object = dynamic>(self::foo::T x) → core::int
return 3;
-static method bar() → <T extends core::Object>(T) → core::int
+static method bar() → <T extends core::Object = dynamic>(T) → core::int
return self::foo;
static method test1() → void {
self::bar().call<core::String>("hello");
diff --git a/pkg/front_end/testcases/regress/issue_30838.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_30838.dart.strong.transformed.expect
index f08b8e7..7526f86 100644
--- a/pkg/front_end/testcases/regress/issue_30838.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_30838.dart.strong.transformed.expect
@@ -4,7 +4,7 @@
typedef Foo<S extends core::Object = dynamic> = <T extends core::Object = dynamic>(T) → S;
class A extends core::Object {
- field <T extends core::Object>(T) → core::int f = null;
+ field <T extends core::Object = dynamic>(T) → core::int f = null;
synthetic constructor •() → void
: super core::Object::•()
;
@@ -14,7 +14,7 @@
}
static method foo<T extends core::Object = dynamic>(self::foo::T x) → core::int
return 3;
-static method bar() → <T extends core::Object>(T) → core::int
+static method bar() → <T extends core::Object = dynamic>(T) → core::int
return self::foo;
static method test1() → void {
self::bar().call<core::String>("hello");
diff --git a/pkg/front_end/testcases/regress/issue_31213.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31213.dart.direct.expect
index a54adf0..da2a301 100644
--- a/pkg/front_end/testcases/regress/issue_31213.dart.direct.expect
+++ b/pkg/front_end/testcases/regress/issue_31213.dart.direct.expect
@@ -3,12 +3,12 @@
import "dart:core" as core;
typedef C<A extends core::Object = dynamic, K extends core::Object = dynamic> = <B extends core::Object = dynamic>(A, K, B) → core::int;
-typedef D<K extends core::Object = dynamic> = <A extends core::Object = dynamic>(core::int) → <B extends core::Object>(A, K, B) → core::int;
+typedef D<K extends core::Object = dynamic> = <A extends core::Object = dynamic>(core::int) → <B extends core::Object = dynamic>(A, K, B) → core::int;
static method producer<K extends core::Object = dynamic>() → dynamic {
return <A extends core::Object = dynamic>(core::int v1) → dynamic {
return <B extends core::Object = dynamic>(A v2, self::producer::K v3, B v4) → dynamic => 0;
};
}
static method main() → dynamic {
- assert(self::producer<core::String>() is <A extends core::Object>(core::int) → <B extends core::Object>(A, core::String, B) → core::int);
+ assert(self::producer<core::String>() is <A extends core::Object = dynamic>(core::int) → <B extends core::Object = dynamic>(A, core::String, B) → core::int);
}
diff --git a/pkg/front_end/testcases/regress/issue_31213.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31213.dart.direct.transformed.expect
index a54adf0..da2a301 100644
--- a/pkg/front_end/testcases/regress/issue_31213.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31213.dart.direct.transformed.expect
@@ -3,12 +3,12 @@
import "dart:core" as core;
typedef C<A extends core::Object = dynamic, K extends core::Object = dynamic> = <B extends core::Object = dynamic>(A, K, B) → core::int;
-typedef D<K extends core::Object = dynamic> = <A extends core::Object = dynamic>(core::int) → <B extends core::Object>(A, K, B) → core::int;
+typedef D<K extends core::Object = dynamic> = <A extends core::Object = dynamic>(core::int) → <B extends core::Object = dynamic>(A, K, B) → core::int;
static method producer<K extends core::Object = dynamic>() → dynamic {
return <A extends core::Object = dynamic>(core::int v1) → dynamic {
return <B extends core::Object = dynamic>(A v2, self::producer::K v3, B v4) → dynamic => 0;
};
}
static method main() → dynamic {
- assert(self::producer<core::String>() is <A extends core::Object>(core::int) → <B extends core::Object>(A, core::String, B) → core::int);
+ assert(self::producer<core::String>() is <A extends core::Object = dynamic>(core::int) → <B extends core::Object = dynamic>(A, core::String, B) → core::int);
}
diff --git a/pkg/front_end/testcases/regress/issue_31213.dart.outline.expect b/pkg/front_end/testcases/regress/issue_31213.dart.outline.expect
index 2626a19..a1d78e7 100644
--- a/pkg/front_end/testcases/regress/issue_31213.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_31213.dart.outline.expect
@@ -3,7 +3,7 @@
import "dart:core" as core;
typedef C<A extends core::Object = dynamic, K extends core::Object = dynamic> = <B extends core::Object = dynamic>(A, K, B) → core::int;
-typedef D<K extends core::Object = dynamic> = <A extends core::Object = dynamic>(core::int) → <B extends core::Object>(A, K, B) → core::int;
+typedef D<K extends core::Object = dynamic> = <A extends core::Object = dynamic>(core::int) → <B extends core::Object = dynamic>(A, K, B) → core::int;
static method producer<K extends core::Object = dynamic>() → dynamic
;
static method main() → dynamic
diff --git a/pkg/front_end/testcases/regress/issue_31213.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31213.dart.strong.expect
index 730da9b..2bb9fe5 100644
--- a/pkg/front_end/testcases/regress/issue_31213.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31213.dart.strong.expect
@@ -3,12 +3,12 @@
import "dart:core" as core;
typedef C<A extends core::Object = dynamic, K extends core::Object = dynamic> = <B extends core::Object = dynamic>(A, K, B) → core::int;
-typedef D<K extends core::Object = dynamic> = <A extends core::Object = dynamic>(core::int) → <B extends core::Object>(A, K, B) → core::int;
+typedef D<K extends core::Object = dynamic> = <A extends core::Object = dynamic>(core::int) → <B extends core::Object = dynamic>(A, K, B) → core::int;
static method producer<K extends core::Object = dynamic>() → dynamic {
return <A extends core::Object = dynamic>(core::int v1) → <B extends core::Object = dynamic>(A, self::producer::K, B) → core::int {
return <B extends core::Object = dynamic>(A v2, self::producer::K v3, B v4) → core::int => 0;
};
}
static method main() → dynamic {
- assert(self::producer<core::String>() is <A extends core::Object>(core::int) → <B extends core::Object>(A, core::String, B) → core::int);
+ assert(self::producer<core::String>() is <A extends core::Object = dynamic>(core::int) → <B extends core::Object = dynamic>(A, core::String, B) → core::int);
}
diff --git a/pkg/front_end/testcases/regress/issue_31213.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31213.dart.strong.transformed.expect
index 730da9b..2bb9fe5 100644
--- a/pkg/front_end/testcases/regress/issue_31213.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31213.dart.strong.transformed.expect
@@ -3,12 +3,12 @@
import "dart:core" as core;
typedef C<A extends core::Object = dynamic, K extends core::Object = dynamic> = <B extends core::Object = dynamic>(A, K, B) → core::int;
-typedef D<K extends core::Object = dynamic> = <A extends core::Object = dynamic>(core::int) → <B extends core::Object>(A, K, B) → core::int;
+typedef D<K extends core::Object = dynamic> = <A extends core::Object = dynamic>(core::int) → <B extends core::Object = dynamic>(A, K, B) → core::int;
static method producer<K extends core::Object = dynamic>() → dynamic {
return <A extends core::Object = dynamic>(core::int v1) → <B extends core::Object = dynamic>(A, self::producer::K, B) → core::int {
return <B extends core::Object = dynamic>(A v2, self::producer::K v3, B v4) → core::int => 0;
};
}
static method main() → dynamic {
- assert(self::producer<core::String>() is <A extends core::Object>(core::int) → <B extends core::Object>(A, core::String, B) → core::int);
+ assert(self::producer<core::String>() is <A extends core::Object = dynamic>(core::int) → <B extends core::Object = dynamic>(A, core::String, B) → core::int);
}
diff --git a/pkg/front_end/testcases/regress/issue_31846.dart b/pkg/front_end/testcases/regress/issue_31846.dart
index 6ec5564..593212f 100644
--- a/pkg/front_end/testcases/regress/issue_31846.dart
+++ b/pkg/front_end/testcases/regress/issue_31846.dart
@@ -7,4 +7,7 @@
print((<T>(T x) => x).runtimeType);
print((<T extends num>(T x) => x).runtimeType);
print((<T extends Comparable<T>>(T x) => x).runtimeType);
+ print((<T extends Comparable<S>, S>(T x) => x).runtimeType);
+ print((<T extends Function(T)>(T x) => x).runtimeType);
+ print((<T extends List<List<T>>>(T x) => x).runtimeType);
}
diff --git a/pkg/front_end/testcases/regress/issue_31846.dart.direct.expect b/pkg/front_end/testcases/regress/issue_31846.dart.direct.expect
index 710cc04..f71d395 100644
--- a/pkg/front_end/testcases/regress/issue_31846.dart.direct.expect
+++ b/pkg/front_end/testcases/regress/issue_31846.dart.direct.expect
@@ -7,4 +7,7 @@
core::print((<T extends core::Object = dynamic>(T x) → dynamic => x).runtimeType);
core::print((<T extends core::num = dynamic>(T x) → dynamic => x).runtimeType);
core::print((<T extends core::Comparable<T> = dynamic>(T x) → dynamic => x).runtimeType);
+ core::print((<T extends core::Comparable<S> = dynamic, S extends core::Object = dynamic>(T x) → dynamic => x).runtimeType);
+ core::print((<T extends (T) → dynamic = dynamic>(T x) → dynamic => x).runtimeType);
+ core::print((<T extends core::List<core::List<T>> = dynamic>(T x) → dynamic => x).runtimeType);
}
diff --git a/pkg/front_end/testcases/regress/issue_31846.dart.direct.transformed.expect b/pkg/front_end/testcases/regress/issue_31846.dart.direct.transformed.expect
index 710cc04..f71d395 100644
--- a/pkg/front_end/testcases/regress/issue_31846.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31846.dart.direct.transformed.expect
@@ -7,4 +7,7 @@
core::print((<T extends core::Object = dynamic>(T x) → dynamic => x).runtimeType);
core::print((<T extends core::num = dynamic>(T x) → dynamic => x).runtimeType);
core::print((<T extends core::Comparable<T> = dynamic>(T x) → dynamic => x).runtimeType);
+ core::print((<T extends core::Comparable<S> = dynamic, S extends core::Object = dynamic>(T x) → dynamic => x).runtimeType);
+ core::print((<T extends (T) → dynamic = dynamic>(T x) → dynamic => x).runtimeType);
+ core::print((<T extends core::List<core::List<T>> = dynamic>(T x) → dynamic => x).runtimeType);
}
diff --git a/pkg/front_end/testcases/regress/issue_31846.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31846.dart.strong.expect
index 6f08277..b07df45 100644
--- a/pkg/front_end/testcases/regress/issue_31846.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31846.dart.strong.expect
@@ -7,4 +7,7 @@
core::print((<T extends core::Object = dynamic>(T x) → T => x).{core::Object::runtimeType});
core::print((<T extends core::num = core::num>(T x) → T => x).{core::Object::runtimeType});
core::print((<T extends core::Comparable<T> = core::Comparable<dynamic>>(T x) → T => x).{core::Object::runtimeType});
+ core::print((<T extends core::Comparable<S> = core::Comparable<dynamic>, S extends core::Object = dynamic>(T x) → T => x).{core::Object::runtimeType});
+ core::print((<T extends (T) → dynamic = (core::Null) → dynamic>(T x) → T => x).{core::Object::runtimeType});
+ core::print((<T extends core::List<core::List<T>> = core::List<core::List<dynamic>>>(T x) → T => x).{core::Object::runtimeType});
}
diff --git a/pkg/front_end/testcases/regress/issue_31846.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31846.dart.strong.transformed.expect
index 6f08277..b07df45 100644
--- a/pkg/front_end/testcases/regress/issue_31846.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31846.dart.strong.transformed.expect
@@ -7,4 +7,7 @@
core::print((<T extends core::Object = dynamic>(T x) → T => x).{core::Object::runtimeType});
core::print((<T extends core::num = core::num>(T x) → T => x).{core::Object::runtimeType});
core::print((<T extends core::Comparable<T> = core::Comparable<dynamic>>(T x) → T => x).{core::Object::runtimeType});
+ core::print((<T extends core::Comparable<S> = core::Comparable<dynamic>, S extends core::Object = dynamic>(T x) → T => x).{core::Object::runtimeType});
+ core::print((<T extends (T) → dynamic = (core::Null) → dynamic>(T x) → T => x).{core::Object::runtimeType});
+ core::print((<T extends core::List<core::List<T>> = core::List<core::List<dynamic>>>(T x) → T => x).{core::Object::runtimeType});
}
diff --git a/pkg/front_end/tool/_fasta/command_line.dart b/pkg/front_end/tool/_fasta/command_line.dart
index c804b1e..b34bcdf 100644
--- a/pkg/front_end/tool/_fasta/command_line.dart
+++ b/pkg/front_end/tool/_fasta/command_line.dart
@@ -212,7 +212,7 @@
"--sdk": Uri,
"--strong": "--strong-mode",
"--strong-mode": false,
- "--sync-async": false,
+ "--sync-async": true,
"--target": String,
"--verbose": false,
"--verify": false,
diff --git a/pkg/front_end/tool/_fasta/compile_platform.dart b/pkg/front_end/tool/_fasta/compile_platform.dart
index 1b47a33..fd26f5f 100644
--- a/pkg/front_end/tool/_fasta/compile_platform.dart
+++ b/pkg/front_end/tool/_fasta/compile_platform.dart
@@ -44,8 +44,8 @@
await compilePlatform(arguments);
} on deprecated_InputError catch (e) {
exitCode = 1;
- CompilerContext.runWithDefaultOptions(
- (c) => c.report(deprecated_InputError.toMessage(e), Severity.error));
+ await CompilerContext.runWithDefaultOptions((c) => new Future<void>.sync(
+ () => c.report(deprecated_InputError.toMessage(e), Severity.error)));
return null;
}
}
diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart
index 026bccd..b2a1d8f 100644
--- a/pkg/front_end/tool/_fasta/entry_points.dart
+++ b/pkg/front_end/tool/_fasta/entry_points.dart
@@ -121,8 +121,8 @@
return await withGlobalOptions("compile", arguments, true,
(CompilerContext c, _) => batchCompileImpl(c));
} on deprecated_InputError catch (e) {
- CompilerContext.runWithDefaultOptions(
- (c) => c.report(deprecated_InputError.toMessage(e), Severity.error));
+ await CompilerContext.runWithDefaultOptions((c) => new Future<void>.sync(
+ () => c.report(deprecated_InputError.toMessage(e), Severity.error)));
return false;
}
}
@@ -173,8 +173,8 @@
});
} on deprecated_InputError catch (e) {
exitCode = 1;
- CompilerContext.runWithDefaultOptions(
- (c) => c.report(deprecated_InputError.toMessage(e), Severity.error));
+ await CompilerContext.runWithDefaultOptions((c) => new Future<void>.sync(
+ () => c.report(deprecated_InputError.toMessage(e), Severity.error)));
return null;
}
}
@@ -192,8 +192,8 @@
});
} on deprecated_InputError catch (e) {
exitCode = 1;
- CompilerContext.runWithDefaultOptions(
- (c) => c.report(deprecated_InputError.toMessage(e), Severity.error));
+ await CompilerContext.runWithDefaultOptions((c) => new Future<void>.sync(
+ () => c.report(deprecated_InputError.toMessage(e), Severity.error)));
return null;
}
}
diff --git a/pkg/kernel/lib/type_algebra.dart b/pkg/kernel/lib/type_algebra.dart
index 821f9d5..8b47a74 100644
--- a/pkg/kernel/lib/type_algebra.dart
+++ b/pkg/kernel/lib/type_algebra.dart
@@ -229,12 +229,9 @@
}
for (int i = 0; i < typeParameters.length; ++i) {
freshParameters[i].bound = substitute(typeParameters[i].bound, map);
-
- // [defaultType] is populated using instantiate-to-bound algorithm, so it
- // shouldn't refer to type parameters from the same declaration. However,
- // if a transformation changes [defaultType], it may get such references,
- // and the line below should invoke [substitute], like for [bound] above.
- freshParameters[i].defaultType = typeParameters[i].defaultType;
+ freshParameters[i].defaultType = typeParameters[i].defaultType != null
+ ? substitute(typeParameters[i].defaultType, map)
+ : null;
}
return new FreshTypeParameters(freshParameters, Substitution.fromMap(map));
}
@@ -479,6 +476,9 @@
var fresh = new TypeParameter(node.name);
substitution[node] = new TypeParameterType(fresh);
fresh.bound = visit(node.bound);
+ if (node.defaultType != null) {
+ fresh.defaultType = visit(node.defaultType);
+ }
return fresh;
}
}
@@ -846,7 +846,9 @@
bool handleTypeParameter(TypeParameter node) {
assert(!variables.contains(node));
- return node.bound.accept(this);
+ if (node.bound.accept(this)) return true;
+ if (node.defaultType == null) return false;
+ return node.defaultType.accept(this);
}
}
@@ -882,6 +884,7 @@
visitFunctionType(FunctionType node) {
for (TypeParameter typeParameter in node.typeParameters) {
typeParameter.bound.accept(this);
+ typeParameter.defaultType?.accept(this);
}
for (DartType parameter in node.positionalParameters) {
parameter.accept(this);
diff --git a/pkg/kernel/test/class_hierarchy_test.dart b/pkg/kernel/test/class_hierarchy_test.dart
index 439da52..2327eca 100644
--- a/pkg/kernel/test/class_hierarchy_test.dart
+++ b/pkg/kernel/test/class_hierarchy_test.dart
@@ -237,7 +237,7 @@
var supertype =
extends_ != null ? extends_(typeParameterTypes) : objectSuper;
var implementedTypes =
- implements_ != null ? implements_(typeParameterTypes) : [];
+ implements_ != null ? implements_(typeParameterTypes) : <Supertype>[];
return addClass(new Class(
name: name,
typeParameters: typeParameters,
diff --git a/pkg/pkg.status b/pkg/pkg.status
index ded000c..1ff41ca 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -113,6 +113,9 @@
front_end/test/src/incremental/hot_reload_e2e_test: Skip
vm/test/*: SkipByDesign # Only meant to run on vm
+[ $system == linux ]
+analysis_server/test/integration/analysis/package_root_test: Pass, RuntimeError # Issue 33382
+
[ $system == windows ]
front_end/test/fasta/ast_builder_test: Pass, Slow, Timeout
front_end/test/fasta/bootstrap_test: Skip # Issue 31902
diff --git a/pkg/status_file/lib/canonical_status_file.dart b/pkg/status_file/lib/canonical_status_file.dart
index 148b4ca..dd55368 100644
--- a/pkg/status_file/lib/canonical_status_file.dart
+++ b/pkg/status_file/lib/canonical_status_file.dart
@@ -161,7 +161,7 @@
}
var implicitSectionHeaderComments = sectionHeaderComments;
- var entries = [];
+ var entries = <Entry>[];
if (lastEmptyLine > 0 && sectionHeaderMatch(_lineCount) != null) {
// Comments after the last empty line belong to the next section's header.
// The empty line is not added to the section header, because it will be
diff --git a/pkg/status_file/lib/expectation.dart b/pkg/status_file/lib/expectation.dart
index bedbabd..6e94845 100644
--- a/pkg/status_file/lib/expectation.dart
+++ b/pkg/status_file/lib/expectation.dart
@@ -188,7 +188,7 @@
skipByDesign,
ignore,
verificationError,
- ], key: (Expectation expectation) => expectation._name.toLowerCase());
+ ], key: (expectation) => expectation._name.toLowerCase());
/// Looks up the expectation with [name].
static Expectation find(String name) {
diff --git a/pkg/vm/bin/gen_kernel.dart b/pkg/vm/bin/gen_kernel.dart
index 16212bf..151be0e 100644
--- a/pkg/vm/bin/gen_kernel.dart
+++ b/pkg/vm/bin/gen_kernel.dart
@@ -28,7 +28,8 @@
'Produce kernel file for AOT compilation (enables global transformations).',
defaultsTo: false)
..addFlag('strong-mode', help: 'Enable strong mode', defaultsTo: true)
- ..addFlag('sync-async', help: 'Start `async` functions synchronously')
+ ..addFlag('sync-async',
+ help: 'Start `async` functions synchronously', defaultsTo: true)
..addFlag('embed-sources',
help: 'Embed source files in the generated kernel component',
defaultsTo: true)
diff --git a/pkg/vm/lib/bytecode/constant_pool.dart b/pkg/vm/lib/bytecode/constant_pool.dart
index a6fdf12..6de7663 100644
--- a/pkg/vm/lib/bytecode/constant_pool.dart
+++ b/pkg/vm/lib/bytecode/constant_pool.dart
@@ -405,9 +405,18 @@
ConstantArgDesc(this.numArguments,
{this.numTypeArgs = 0, this.argNames = const <String>[]});
- ConstantArgDesc.fromArguments(Arguments args, {bool hasReceiver: false})
- : this(args.positional.length + args.named.length + (hasReceiver ? 1 : 0),
- numTypeArgs: args.types.length,
+ ConstantArgDesc.fromArguments(Arguments args,
+ {bool hasReceiver: false, bool isFactory: false})
+ : this(
+ args.positional.length +
+ args.named.length +
+ (hasReceiver ? 1 : 0) +
+ // VM expects that type arguments vector passed to a factory
+ // constructor is counted in numArguments, and not counted in
+ // numTypeArgs.
+ // TODO(alexmarkov): Clean this up.
+ (isFactory ? 1 : 0),
+ numTypeArgs: isFactory ? 0 : args.types.length,
argNames: new List<String>.from(args.named.map((ne) => ne.name)));
@override
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index 51f5fdc..d2d12b3 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -11,6 +11,8 @@
import 'package:kernel/library_index.dart' show LibraryIndex;
import 'package:kernel/transformations/constants.dart'
show ConstantEvaluator, ConstantsBackend, EvaluationEnvironment;
+import 'package:kernel/type_algebra.dart'
+ show Substitution, containsTypeVariable;
import 'package:kernel/type_environment.dart' show TypeEnvironment;
import 'package:kernel/vm/constants_native_effects.dart'
show VmConstantsBackend;
@@ -57,6 +59,9 @@
Class enclosingClass;
Member enclosingMember;
+ Set<TypeParameter> classTypeParameters;
+ Set<TypeParameter> functionTypeParameters;
+ List<DartType> instantiatorTypeArguments;
LocalVariables locals;
ConstantEvaluator constantEvaluator;
Map<LabeledStatement, Label> labeledStatements;
@@ -259,15 +264,17 @@
}
void _genStaticCallWithArgs(Member target, Arguments args,
- {bool hasReceiver: false, bool alwaysPassTypeArgs: false}) {
- final ConstantArgDesc argDesc =
- new ConstantArgDesc.fromArguments(args, hasReceiver: hasReceiver);
+ {bool hasReceiver: false, bool isFactory: false}) {
+ final ConstantArgDesc argDesc = new ConstantArgDesc.fromArguments(args,
+ hasReceiver: hasReceiver, isFactory: isFactory);
int totalArgCount = args.positional.length + args.named.length;
if (hasReceiver) {
totalArgCount++;
}
- if (args.types.isNotEmpty || alwaysPassTypeArgs) {
+ if (args.types.isNotEmpty || isFactory) {
+ // VM needs type arguments for every invocation of a factory constructor.
+ // TODO(alexmarkov): Clean this up.
totalArgCount++;
}
@@ -285,31 +292,45 @@
}
void _genTypeArguments(List<DartType> typeArgs, {Class instantiatingClass}) {
- int typeArgsCPIndex = cp.add(new ConstantTypeArguments(typeArgs));
- if (instantiatingClass != null) {
- typeArgsCPIndex = cp.add(new ConstantTypeArgumentsForInstanceAllocation(
- instantiatingClass, typeArgsCPIndex));
+ int typeArgsCPIndex() {
+ int cpIndex = cp.add(new ConstantTypeArguments(typeArgs));
+ if (instantiatingClass != null) {
+ cpIndex = cp.add(new ConstantTypeArgumentsForInstanceAllocation(
+ instantiatingClass, cpIndex));
+ }
+ return cpIndex;
}
+
if (typeArgs.isEmpty || !hasTypeParameters(typeArgs)) {
- asm.emitPushConstant(typeArgsCPIndex);
+ asm.emitPushConstant(typeArgsCPIndex());
} else {
- // TODO(alexmarkov): try to reuse instantiator type arguments
- _genPushInstantiatorAndFunctionTypeArguments(typeArgs);
- asm.emitInstantiateTypeArgumentsTOS(1, typeArgsCPIndex);
+ if (_canReuseInstantiatorTypeArguments(typeArgs, instantiatingClass)) {
+ _genPushInstantiatorTypeArguments();
+ } else {
+ _genPushInstantiatorAndFunctionTypeArguments(typeArgs);
+ asm.emitInstantiateTypeArgumentsTOS(1, typeArgsCPIndex());
+ }
}
}
void _genPushInstantiatorAndFunctionTypeArguments(List<DartType> types) {
- // TODO(alexmarkov): do not load instantiator type arguments / function type
- // arguments if they are not needed for these particular [types].
- _genPushInstantiatorTypeArguments();
- _genPushFunctionTypeArguments();
+ if (classTypeParameters != null &&
+ types.any((t) => containsTypeVariable(t, classTypeParameters))) {
+ assert(instantiatorTypeArguments != null);
+ _genPushInstantiatorTypeArguments();
+ } else {
+ _genPushNull();
+ }
+ if (functionTypeParameters != null &&
+ types.any((t) => containsTypeVariable(t, functionTypeParameters))) {
+ _genPushFunctionTypeArguments();
+ } else {
+ _genPushNull();
+ }
}
void _genPushInstantiatorTypeArguments() {
- // TODO(alexmarkov): access to type arguments in factory constructors.
- if ((enclosingMember.isInstanceMember || enclosingMember is Constructor) &&
- hasInstantiatorTypeArguments(enclosingClass)) {
+ if (instantiatorTypeArguments != null) {
_genPushReceiver();
final int cpIndex =
cp.add(new ConstantTypeArgumentsFieldOffset(enclosingClass));
@@ -319,6 +340,48 @@
}
}
+ List<DartType> _flattenInstantiatorTypeArguments(
+ Class instantiatedClass, List<DartType> typeArgs) {
+ assert(typeArgs.length == instantiatedClass.typeParameters.length);
+
+ List<DartType> flatTypeArgs;
+ final supertype = instantiatedClass.supertype;
+ if (supertype == null) {
+ flatTypeArgs = <DartType>[];
+ } else {
+ final substitution =
+ Substitution.fromPairs(instantiatedClass.typeParameters, typeArgs);
+ flatTypeArgs = _flattenInstantiatorTypeArguments(supertype.classNode,
+ substitution.substituteSupertype(supertype).typeArguments);
+ }
+ flatTypeArgs.addAll(typeArgs);
+ return flatTypeArgs;
+ }
+
+ bool _canReuseInstantiatorTypeArguments(
+ List<DartType> typeArgs, Class instantiatingClass) {
+ if (instantiatorTypeArguments == null) {
+ return false;
+ }
+
+ if (instantiatingClass != null) {
+ typeArgs =
+ _flattenInstantiatorTypeArguments(instantiatingClass, typeArgs);
+ }
+
+ if (typeArgs.length > instantiatorTypeArguments.length) {
+ return false;
+ }
+
+ for (int i = 0; i < typeArgs.length; ++i) {
+ if (typeArgs[i] != instantiatorTypeArguments[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
void _genPushFunctionTypeArguments() {
if (locals.hasTypeArgsVar) {
asm.emitPush(locals.typeArgsVarIndexInFrame);
@@ -440,6 +503,24 @@
void start(Member node) {
enclosingClass = node.enclosingClass;
enclosingMember = node;
+ if (enclosingMember.isInstanceMember || enclosingMember is Constructor) {
+ if (enclosingClass.typeParameters.isNotEmpty) {
+ classTypeParameters =
+ new Set<TypeParameter>.from(enclosingClass.typeParameters);
+ }
+ if (hasInstantiatorTypeArguments(enclosingClass)) {
+ final typeParameters = enclosingClass.typeParameters
+ .map((p) => new TypeParameterType(p))
+ .toList();
+ instantiatorTypeArguments =
+ _flattenInstantiatorTypeArguments(enclosingClass, typeParameters);
+ }
+ }
+ if (enclosingMember.function != null &&
+ enclosingMember.function.typeParameters.isNotEmpty) {
+ functionTypeParameters =
+ new Set<TypeParameter>.from(enclosingMember.function.typeParameters);
+ }
locals = new LocalVariables(node);
// TODO(alexmarkov): improve caching in ConstantEvaluator and reuse it
constantEvaluator = new ConstantEvaluator(constantsBackend, typeEnvironment,
@@ -496,6 +577,9 @@
enclosingClass = null;
enclosingMember = null;
+ classTypeParameters = null;
+ functionTypeParameters = null;
+ instantiatorTypeArguments = null;
locals = null;
constantEvaluator = null;
labeledStatements = null;
@@ -610,6 +694,12 @@
_pushAssemblerState();
locals.enterScope(node);
+
+ if (function.typeParameters.isNotEmpty) {
+ functionTypeParameters ??= new Set<TypeParameter>();
+ functionTypeParameters.addAll(function.typeParameters);
+ }
+
List<Label> savedYieldPoints = yieldPoints;
yieldPoints = locals.isSyncYieldingFrame ? <Label>[] : null;
@@ -644,6 +734,10 @@
cp.add(new ConstantEndClosureFunctionScope());
+ if (function.typeParameters.isNotEmpty) {
+ functionTypeParameters.removeAll(function.typeParameters);
+ }
+
locals.leaveScope();
closures.add(new ClosureBytecode(
@@ -1217,16 +1311,13 @@
@override
visitStaticInvocation(StaticInvocation node) {
final args = node.arguments;
- bool alwaysPassTypeArgs = false;
if (node.target.isFactory && args.types.isEmpty) {
// VM needs type arguments for every invocation of a factory constructor.
- // TODO(alexmarkov): Why? Clean this up.
+ // TODO(alexmarkov): Clean this up.
_genPushNull();
- alwaysPassTypeArgs = true;
}
_genArguments(null, args);
- _genStaticCallWithArgs(node.target, args,
- alwaysPassTypeArgs: alwaysPassTypeArgs);
+ _genStaticCallWithArgs(node.target, args, isFactory: node.target.isFactory);
}
@override
diff --git a/pkg/vm/lib/bytecode/local_vars.dart b/pkg/vm/lib/bytecode/local_vars.dart
index 14ed800..d779939 100644
--- a/pkg/vm/lib/bytecode/local_vars.dart
+++ b/pkg/vm/lib/bytecode/local_vars.dart
@@ -724,6 +724,7 @@
void _allocateParameters(TreeNode node, FunctionNode function) {
final bool hasTypeArgs = function.typeParameters.isNotEmpty;
+ final bool isFactory = node is Procedure && node.isFactory;
final bool hasReceiver =
node is Constructor || (node is Procedure && !node.isStatic);
final bool hasClosureArg =
@@ -731,7 +732,7 @@
_currentFrame.numParameters = function.positionalParameters.length +
function.namedParameters.length +
- (hasTypeArgs ? 1 : 0) +
+ (hasTypeArgs || isFactory ? 1 : 0) +
(hasReceiver ? 1 : 0) +
(hasClosureArg ? 1 : 0);
@@ -748,6 +749,10 @@
if (hasTypeArgs) {
assert(!locals.isCaptured(_currentFrame.typeArgsVar));
_allocateParameter(_currentFrame.typeArgsVar, count++);
+ } else if (isFactory) {
+ // Null type arguments are passed to factory constructors even if class
+ // is not generic. TODO(alexmarkov): Clean this up.
+ count++;
}
if (hasReceiver) {
_allocateParameter(_currentFrame.receiverVar, count++);
diff --git a/pkg/vm/lib/frontend_server.dart b/pkg/vm/lib/frontend_server.dart
index 0bf5ffb..38b2e10 100644
--- a/pkg/vm/lib/frontend_server.dart
+++ b/pkg/vm/lib/frontend_server.dart
@@ -48,7 +48,7 @@
help: 'Run compiler in strong mode (uses strong mode semantics)',
defaultsTo: false)
..addFlag('sync-async',
- help: 'Start `async` functions synchronously.', defaultsTo: false)
+ help: 'Start `async` functions synchronously.', defaultsTo: true)
..addFlag('tfa',
help:
'Enable global type flow analysis and related transformations in AOT mode.',
diff --git a/pkg/vm/lib/transformations/type_flow/entry_points.json b/pkg/vm/lib/transformations/type_flow/entry_points.json
index 5465003..49ac98a 100644
--- a/pkg/vm/lib/transformations/type_flow/entry_points.json
+++ b/pkg/vm/lib/transformations/type_flow/entry_points.json
@@ -52,11 +52,6 @@
},
{
"library": "dart:core",
- "class": "_Bigint",
- "action": "create-instance"
- },
- {
- "library": "dart:core",
"class": "_Double",
"action": "create-instance"
},
@@ -970,11 +965,6 @@
"action": "call"
},
{
- "library": "dart:vmservice_io",
- "name": "main",
- "action": "call"
- },
- {
"library": "dart:_builtin",
"name": "_isolateId",
"action": "get"
@@ -1016,6 +1006,16 @@
},
{
"library": "dart:vmservice_io",
+ "name": "_deterministic",
+ "action": "get"
+ },
+ {
+ "library": "dart:vmservice_io",
+ "name": "_deterministic",
+ "action": "set"
+ },
+ {
+ "library": "dart:vmservice_io",
"name": "_ip",
"action": "get"
},
@@ -1638,30 +1638,6 @@
"nullable": false
}
],
- "Bigint_getNeg": [
- {
- "action": "return",
- "library": "dart:core",
- "class": "bool",
- "nullable": false
- }
- ],
- "Bigint_getUsed": [
- {
- "action": "return",
- "library": "dart:core",
- "class": "_Smi",
- "nullable": false
- }
- ],
- "Bigint_getDigits": [
- {
- "action": "return",
- "library": "dart:typed_data",
- "class": "_Uint32List",
- "nullable": false
- }
- ],
"LinkedHashMap_getIndex": [
{
"action": "return",
diff --git a/pkg/vm/test/frontend_server_test.dart b/pkg/vm/test/frontend_server_test.dart
index bfd1219..997bdf9 100644
--- a/pkg/vm/test/frontend_server_test.dart
+++ b/pkg/vm/test/frontend_server_test.dart
@@ -69,16 +69,16 @@
)).captured;
expect(capturedArgs.single['sdk-root'], equals('sdkroot'));
expect(capturedArgs.single['strong'], equals(true));
- expect(capturedArgs.single['sync-async'], equals(false));
+ expect(capturedArgs.single['sync-async'], equals(true));
});
- test('compile from command line (sync-async)', () async {
+ test('compile from command line (no-sync-async)', () async {
final List<String> args = <String>[
'server.dart',
'--sdk-root',
'sdkroot',
'--strong',
- '--sync-async',
+ '--no-sync-async',
];
final int exitcode = await starter(args, compiler: compiler);
expect(exitcode, equals(0));
@@ -89,7 +89,7 @@
)).captured;
expect(capturedArgs.single['sdk-root'], equals('sdkroot'));
expect(capturedArgs.single['strong'], equals(true));
- expect(capturedArgs.single['sync-async'], equals(true));
+ expect(capturedArgs.single['sync-async'], equals(false));
});
test('compile from command line with link platform', () async {
diff --git a/pkg/vm/testcases/bytecode/async.dart.expect b/pkg/vm/testcases/bytecode/async.dart.expect
index cf1e13f..f9bc6de 100644
--- a/pkg/vm/testcases/bytecode/async.dart.expect
+++ b/pkg/vm/testcases/bytecode/async.dart.expect
@@ -49,28 +49,28 @@
StoreFieldTOS CP#11
PopLocal r5
Push r5
- PushConstant CP#24
- IndirectStaticCall 1, CP#23
+ PushConstant CP#23
+ IndirectStaticCall 1, CP#2
StoreLocal r2
Drop1
Push r5
- PushConstant CP#25
- IndirectStaticCall 1, CP#23
+ PushConstant CP#24
+ IndirectStaticCall 1, CP#2
StoreLocal r3
Drop1
Push r5
- PushConstant CP#26
- IndirectStaticCall 1, CP#23
+ PushConstant CP#25
+ IndirectStaticCall 1, CP#2
StoreLocal r4
Drop1
- PushConstant CP#27
+ PushConstant CP#26
Push r5
- PushConstant CP#29
- IndirectStaticCall 2, CP#28
+ PushConstant CP#27
+ IndirectStaticCall 2, CP#13
Drop1
Push r0
LoadFieldTOS CP#4
- InstanceCall1 1, CP#30
+ InstanceCall1 1, CP#28
ReturnTOS
Push r0
LoadFieldTOS CP#0
@@ -81,7 +81,7 @@
ConstantPool {
[0] = ContextOffset parent
[1] = TypeArgs [dart.core::int]
- [2] = ArgDesc num-args 0, num-type-args 1, names []
+ [2] = ArgDesc num-args 1, num-type-args 0, names []
[3] = StaticICData target 'dart.async::Completer::sync', arg-desc CP#2
[4] = ContextOffset var [3]
[5] = Null
@@ -102,14 +102,12 @@
[20] = FieldOffset dart.core::_Closure::_instantiator_type_arguments
[21] = FieldOffset dart.core::_Closure::_function_type_arguments
[22] = FieldOffset dart.core::_Closure::_function
- [23] = ArgDesc num-args 1, num-type-args 0, names []
- [24] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#23
- [25] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#23
- [26] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#23
- [27] = TypeArgs [dynamic]
- [28] = ArgDesc num-args 1, num-type-args 1, names []
- [29] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#28
- [30] = ICData get target-name 'future', arg-desc CP#23
+ [23] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#2
+ [24] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#2
+ [25] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#2
+ [26] = TypeArgs [dynamic]
+ [27] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#13
+ [28] = ICData get target-name 'future', arg-desc CP#2
}
Closure CP#10 {
EntryOptional 1, 3, 0
@@ -266,15 +264,15 @@
StoreFieldTOS CP#17
Push r0
LoadFieldTOS CP#17
- PushConstant CP#34
- IndirectStaticCall 1, CP#33
+ PushConstant CP#33
+ IndirectStaticCall 1, CP#4
StoreLocal r2
Drop1
Push r0
Push r0
LoadFieldTOS CP#17
- PushConstant CP#35
- IndirectStaticCall 1, CP#33
+ PushConstant CP#34
+ IndirectStaticCall 1, CP#4
StoreLocal r3
StoreFieldTOS CP#9
Push r3
@@ -282,21 +280,21 @@
Push r0
Push r0
LoadFieldTOS CP#17
- PushConstant CP#36
- IndirectStaticCall 1, CP#33
+ PushConstant CP#35
+ IndirectStaticCall 1, CP#4
StoreLocal r3
StoreFieldTOS CP#10
Push r3
Drop1
- PushConstant CP#37
+ PushConstant CP#36
Push r0
LoadFieldTOS CP#17
- PushConstant CP#39
- IndirectStaticCall 2, CP#38
+ PushConstant CP#37
+ IndirectStaticCall 2, CP#22
Drop1
Push r0
LoadFieldTOS CP#6
- InstanceCall1 1, CP#40
+ InstanceCall1 1, CP#38
ReturnTOS
Push r0
LoadFieldTOS CP#0
@@ -309,7 +307,7 @@
[1] = ContextOffset var [0]
[2] = ContextOffset var [1]
[3] = TypeArgs [dart.core::int]
- [4] = ArgDesc num-args 0, num-type-args 1, names []
+ [4] = ArgDesc num-args 1, num-type-args 0, names []
[5] = StaticICData target 'dart.async::Completer::sync', arg-desc CP#4
[6] = ContextOffset var [8]
[7] = Null
@@ -338,14 +336,12 @@
[30] = FieldOffset dart.core::_Closure::_instantiator_type_arguments
[31] = FieldOffset dart.core::_Closure::_function_type_arguments
[32] = FieldOffset dart.core::_Closure::_function
- [33] = ArgDesc num-args 1, num-type-args 0, names []
- [34] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#33
- [35] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#33
- [36] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#33
- [37] = TypeArgs [dynamic]
- [38] = ArgDesc num-args 1, num-type-args 1, names []
- [39] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#38
- [40] = ICData get target-name 'future', arg-desc CP#33
+ [33] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#4
+ [34] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#4
+ [35] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#4
+ [36] = TypeArgs [dynamic]
+ [37] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#22
+ [38] = ICData get target-name 'future', arg-desc CP#4
}
Closure CP#14 {
EntryOptional 1, 3, 0
@@ -565,54 +561,54 @@
PushConstant CP#6
StoreFieldTOS CP#14
Push r0
- Allocate CP#43
+ Allocate CP#42
StoreLocal r3
Push r3
PushConstant CP#6
+ StoreFieldTOS CP#43
+ Push r3
+ PushConstant CP#6
StoreFieldTOS CP#44
Push r3
- PushConstant CP#6
- StoreFieldTOS CP#45
- Push r3
PushConstant CP#15
- StoreFieldTOS CP#46
+ StoreFieldTOS CP#45
Push r3
Push r0
StoreFieldTOS CP#16
- StoreFieldTOS CP#29
+ StoreFieldTOS CP#28
Push r0
- LoadFieldTOS CP#29
- PushConstant CP#47
- IndirectStaticCall 1, CP#21
+ LoadFieldTOS CP#28
+ PushConstant CP#46
+ IndirectStaticCall 1, CP#3
StoreLocal r2
Drop1
Push r0
Push r0
- LoadFieldTOS CP#29
- PushConstant CP#48
- IndirectStaticCall 1, CP#21
+ LoadFieldTOS CP#28
+ PushConstant CP#47
+ IndirectStaticCall 1, CP#3
StoreLocal r3
StoreFieldTOS CP#8
Push r3
Drop1
Push r0
Push r0
- LoadFieldTOS CP#29
- PushConstant CP#49
- IndirectStaticCall 1, CP#21
+ LoadFieldTOS CP#28
+ PushConstant CP#48
+ IndirectStaticCall 1, CP#3
StoreLocal r3
StoreFieldTOS CP#9
Push r3
Drop1
- PushConstant CP#50
+ PushConstant CP#49
Push r0
- LoadFieldTOS CP#29
- PushConstant CP#52
- IndirectStaticCall 2, CP#51
+ LoadFieldTOS CP#28
+ PushConstant CP#50
+ IndirectStaticCall 2, CP#18
Drop1
Push r0
LoadFieldTOS CP#5
- InstanceCall1 1, CP#53
+ InstanceCall1 1, CP#51
ReturnTOS
Push r0
LoadFieldTOS CP#0
@@ -624,7 +620,7 @@
[0] = ContextOffset parent
[1] = ContextOffset var [0]
[2] = TypeArgs [dart.core::int]
- [3] = ArgDesc num-args 0, num-type-args 1, names []
+ [3] = ArgDesc num-args 1, num-type-args 0, names []
[4] = StaticICData target 'dart.async::Completer::sync', arg-desc CP#3
[5] = ContextOffset var [9]
[6] = Null
@@ -642,39 +638,37 @@
[18] = ArgDesc num-args 2, num-type-args 0, names []
[19] = ICData target-name '<', arg-desc CP#18
[20] = Bool true
- [21] = ArgDesc num-args 1, num-type-args 0, names []
- [22] = ICData get target-name 'iterator', arg-desc CP#21
- [23] = ICData target-name 'moveNext', arg-desc CP#21
- [24] = ICData get target-name 'current', arg-desc CP#21
- [25] = ICData target-name '+', arg-desc CP#18
- [26] = Int 1
- [27] = ArgDesc num-args 0, num-type-args 0, names []
- [28] = StaticICData target '#lib::foo', arg-desc CP#27
- [29] = ContextOffset var [7]
- [30] = ArgDesc num-args 4, num-type-args 0, names []
- [31] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#30
+ [21] = ICData get target-name 'iterator', arg-desc CP#3
+ [22] = ICData target-name 'moveNext', arg-desc CP#3
+ [23] = ICData get target-name 'current', arg-desc CP#3
+ [24] = ICData target-name '+', arg-desc CP#18
+ [25] = Int 1
+ [26] = ArgDesc num-args 0, num-type-args 0, names []
+ [27] = StaticICData target '#lib::foo', arg-desc CP#26
+ [28] = ContextOffset var [7]
+ [29] = ArgDesc num-args 4, num-type-args 0, names []
+ [30] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#29
+ [31] = ICData target-name '+', arg-desc CP#18
[32] = ICData target-name '+', arg-desc CP#18
[33] = ICData target-name '+', arg-desc CP#18
- [34] = ICData target-name '+', arg-desc CP#18
- [35] = ICData target-name '<', arg-desc CP#18
+ [34] = ICData target-name '<', arg-desc CP#18
+ [35] = ICData target-name '+', arg-desc CP#18
[36] = ICData target-name '+', arg-desc CP#18
- [37] = ICData target-name '+', arg-desc CP#18
- [38] = ICData target-name 'complete', arg-desc CP#18
- [39] = Type dynamic
- [40] = ArgDesc num-args 3, num-type-args 0, names []
- [41] = ICData target-name 'completeError', arg-desc CP#40
- [42] = EndClosureFunctionScope
- [43] = Class dart.core::_Closure
- [44] = FieldOffset dart.core::_Closure::_instantiator_type_arguments
- [45] = FieldOffset dart.core::_Closure::_function_type_arguments
- [46] = FieldOffset dart.core::_Closure::_function
- [47] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#21
- [48] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#21
- [49] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#21
- [50] = TypeArgs [dynamic]
- [51] = ArgDesc num-args 1, num-type-args 1, names []
- [52] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#51
- [53] = ICData get target-name 'future', arg-desc CP#21
+ [37] = ICData target-name 'complete', arg-desc CP#18
+ [38] = Type dynamic
+ [39] = ArgDesc num-args 3, num-type-args 0, names []
+ [40] = ICData target-name 'completeError', arg-desc CP#39
+ [41] = EndClosureFunctionScope
+ [42] = Class dart.core::_Closure
+ [43] = FieldOffset dart.core::_Closure::_instantiator_type_arguments
+ [44] = FieldOffset dart.core::_Closure::_function_type_arguments
+ [45] = FieldOffset dart.core::_Closure::_function
+ [46] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#3
+ [47] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#3
+ [48] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#3
+ [49] = TypeArgs [dynamic]
+ [50] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#18
+ [51] = ICData get target-name 'future', arg-desc CP#3
}
Closure CP#15 {
EntryOptional 1, 3, 0
@@ -735,7 +729,7 @@
LoadFieldTOS CP#0
LoadFieldTOS CP#0
LoadFieldTOS CP#1
- InstanceCall1 1, CP#22
+ InstanceCall1 1, CP#21
PopLocal r8
Push r4
Push r8
@@ -745,7 +739,7 @@
Push r4
LoadFieldTOS CP#1
StoreLocal r8
- InstanceCall1 1, CP#23
+ InstanceCall1 1, CP#22
PushConstant CP#20
IfNeStrictTOS
Jump L3
@@ -757,7 +751,7 @@
PopLocal r4
Push r4
Push r8
- InstanceCall1 1, CP#24
+ InstanceCall1 1, CP#23
StoreFieldTOS CP#1
Push r4
LoadFieldTOS CP#0
@@ -784,7 +778,7 @@
LoadFieldTOS CP#1
Push r4
LoadFieldTOS CP#1
- InstanceCall1 2, CP#25
+ InstanceCall1 2, CP#24
StoreLocal r9
StoreFieldTOS CP#13
Push r9
@@ -794,7 +788,7 @@
LoadFieldTOS CP#0
LoadFieldTOS CP#0
LoadFieldTOS CP#0
- PushConstant CP#26
+ PushConstant CP#25
StoreFieldTOS CP#1
Push r4
LoadFieldTOS CP#0
@@ -803,8 +797,8 @@
LoadFieldTOS CP#0
Push r4
StoreFieldTOS CP#11
- PushConstant CP#28
- IndirectStaticCall 0, CP#27
+ PushConstant CP#27
+ IndirectStaticCall 0, CP#26
Push r4
LoadFieldTOS CP#0
LoadFieldTOS CP#0
@@ -822,9 +816,9 @@
LoadFieldTOS CP#0
LoadFieldTOS CP#0
LoadFieldTOS CP#0
- LoadFieldTOS CP#29
- PushConstant CP#31
- IndirectStaticCall 4, CP#30
+ LoadFieldTOS CP#28
+ PushConstant CP#30
+ IndirectStaticCall 4, CP#29
PopLocal r10
PushConstant CP#6
ReturnTOS
@@ -852,8 +846,8 @@
LoadFieldTOS CP#0
LoadFieldTOS CP#13
Push r1
+ InstanceCall1 2, CP#31
InstanceCall1 2, CP#32
- InstanceCall1 2, CP#33
StoreLocal r9
StoreFieldTOS CP#1
Push r9
@@ -872,8 +866,8 @@
Push r4
Push r4
LoadFieldTOS CP#1
- PushConstant CP#26
- InstanceCall1 2, CP#34
+ PushConstant CP#25
+ InstanceCall1 2, CP#33
StoreLocal r8
StoreFieldTOS CP#1
Push r8
@@ -889,7 +883,7 @@
CheckStack
Push r8
PushConstant CP#17
- InstanceCall1 2, CP#35
+ InstanceCall1 2, CP#34
PushConstant CP#20
IfNeStrictTOS
Jump L7
@@ -897,14 +891,14 @@
Push r4
LoadFieldTOS CP#1
Push r8
- InstanceCall1 2, CP#36
+ InstanceCall1 2, CP#35
StoreLocal r9
StoreFieldTOS CP#1
Push r9
Drop1
Push r8
- PushConstant CP#26
- InstanceCall1 2, CP#37
+ PushConstant CP#25
+ InstanceCall1 2, CP#36
StoreLocal r8
Drop1
Jump L8
@@ -929,7 +923,7 @@
LoadFieldTOS CP#5
Push r4
LoadFieldTOS CP#7
- InstanceCall1 2, CP#38
+ InstanceCall1 2, CP#37
Drop1
PushConstant CP#6
ReturnTOS
@@ -952,7 +946,7 @@
LoadFieldTOS CP#5
Push r8
Push r9
- InstanceCall1 3, CP#41
+ InstanceCall1 3, CP#40
Drop1
Jump L10
L10:
@@ -1073,32 +1067,32 @@
PushConstant CP#8
StoreFieldTOS CP#3
Push r0
- Allocate CP#52
+ Allocate CP#51
StoreLocal r3
Push r3
PushConstant CP#8
+ StoreFieldTOS CP#52
+ Push r3
+ PushConstant CP#8
StoreFieldTOS CP#53
Push r3
- PushConstant CP#8
- StoreFieldTOS CP#54
- Push r3
PushConstant CP#18
- StoreFieldTOS CP#55
+ StoreFieldTOS CP#54
Push r3
Push r0
StoreFieldTOS CP#19
StoreFieldTOS CP#21
Push r0
LoadFieldTOS CP#21
- PushConstant CP#56
- IndirectStaticCall 1, CP#35
+ PushConstant CP#55
+ IndirectStaticCall 1, CP#5
StoreLocal r2
Drop1
Push r0
Push r0
LoadFieldTOS CP#21
- PushConstant CP#57
- IndirectStaticCall 1, CP#35
+ PushConstant CP#56
+ IndirectStaticCall 1, CP#5
StoreLocal r3
StoreFieldTOS CP#10
Push r3
@@ -1106,21 +1100,21 @@
Push r0
Push r0
LoadFieldTOS CP#21
- PushConstant CP#58
- IndirectStaticCall 1, CP#35
+ PushConstant CP#57
+ IndirectStaticCall 1, CP#5
StoreLocal r3
StoreFieldTOS CP#11
Push r3
Drop1
- PushConstant CP#59
+ PushConstant CP#58
Push r0
LoadFieldTOS CP#21
- PushConstant CP#61
- IndirectStaticCall 2, CP#60
+ PushConstant CP#59
+ IndirectStaticCall 2, CP#24
Drop1
Push r0
LoadFieldTOS CP#7
- InstanceCall1 1, CP#62
+ InstanceCall1 1, CP#60
ReturnTOS
Push r0
LoadFieldTOS CP#0
@@ -1134,7 +1128,7 @@
[2] = ContextOffset var [1]
[3] = ContextOffset var [2]
[4] = TypeArgs [dart.core::int]
- [5] = ArgDesc num-args 0, num-type-args 1, names []
+ [5] = ArgDesc num-args 1, num-type-args 0, names []
[6] = StaticICData target 'dart.async::Completer::sync', arg-desc CP#5
[7] = ContextOffset var [12]
[8] = Null
@@ -1164,34 +1158,32 @@
[32] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#22
[33] = ICData target-name '+', arg-desc CP#24
[34] = String 'fin'
- [35] = ArgDesc num-args 1, num-type-args 0, names []
- [36] = StaticICData target 'dart.core::print', arg-desc CP#35
- [37] = Int 3
- [38] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#22
- [39] = ICData target-name '+', arg-desc CP#24
- [40] = StaticICData target 'dart.core::print', arg-desc CP#35
- [41] = Int 4
- [42] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#22
- [43] = ICData target-name '+', arg-desc CP#24
- [44] = StaticICData target 'dart.core::print', arg-desc CP#35
- [45] = Int 5
- [46] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#22
- [47] = ICData target-name '+', arg-desc CP#24
- [48] = ICData target-name 'complete', arg-desc CP#24
- [49] = ArgDesc num-args 3, num-type-args 0, names []
- [50] = ICData target-name 'completeError', arg-desc CP#49
- [51] = EndClosureFunctionScope
- [52] = Class dart.core::_Closure
- [53] = FieldOffset dart.core::_Closure::_instantiator_type_arguments
- [54] = FieldOffset dart.core::_Closure::_function_type_arguments
- [55] = FieldOffset dart.core::_Closure::_function
- [56] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#35
- [57] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#35
- [58] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#35
- [59] = TypeArgs [dynamic]
- [60] = ArgDesc num-args 1, num-type-args 1, names []
- [61] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#60
- [62] = ICData get target-name 'future', arg-desc CP#35
+ [35] = StaticICData target 'dart.core::print', arg-desc CP#5
+ [36] = Int 3
+ [37] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#22
+ [38] = ICData target-name '+', arg-desc CP#24
+ [39] = StaticICData target 'dart.core::print', arg-desc CP#5
+ [40] = Int 4
+ [41] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#22
+ [42] = ICData target-name '+', arg-desc CP#24
+ [43] = StaticICData target 'dart.core::print', arg-desc CP#5
+ [44] = Int 5
+ [45] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#22
+ [46] = ICData target-name '+', arg-desc CP#24
+ [47] = ICData target-name 'complete', arg-desc CP#24
+ [48] = ArgDesc num-args 3, num-type-args 0, names []
+ [49] = ICData target-name 'completeError', arg-desc CP#48
+ [50] = EndClosureFunctionScope
+ [51] = Class dart.core::_Closure
+ [52] = FieldOffset dart.core::_Closure::_instantiator_type_arguments
+ [53] = FieldOffset dart.core::_Closure::_function_type_arguments
+ [54] = FieldOffset dart.core::_Closure::_function
+ [55] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#5
+ [56] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#5
+ [57] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#5
+ [58] = TypeArgs [dynamic]
+ [59] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#24
+ [60] = ICData get target-name 'future', arg-desc CP#5
}
Closure CP#18 {
EntryOptional 1, 3, 0
@@ -1426,8 +1418,8 @@
Push r9
StoreFieldTOS CP#17
PushConstant CP#34
- PushConstant CP#36
- IndirectStaticCall 1, CP#35
+ PushConstant CP#35
+ IndirectStaticCall 1, CP#5
Drop1
Push r4
LoadFieldTOS CP#0
@@ -1439,7 +1431,7 @@
Drop1
Push r4
LoadFieldTOS CP#0
- PushConstant CP#37
+ PushConstant CP#36
StoreFieldTOS CP#1
Push r4
LoadFieldTOS CP#0
@@ -1458,7 +1450,7 @@
Push r4
LoadFieldTOS CP#0
LoadFieldTOS CP#21
- PushConstant CP#38
+ PushConstant CP#37
IndirectStaticCall 4, CP#22
PopLocal r12
PushConstant CP#8
@@ -1475,7 +1467,7 @@
LoadFieldTOS CP#0
LoadFieldTOS CP#3
Push r1
- InstanceCall1 2, CP#39
+ InstanceCall1 2, CP#38
StoreLocal r10
StoreFieldTOS CP#1
Push r10
@@ -1507,8 +1499,8 @@
LoadFieldTOS CP#14
PopLocal r4
PushConstant CP#34
- PushConstant CP#40
- IndirectStaticCall 1, CP#35
+ PushConstant CP#39
+ IndirectStaticCall 1, CP#5
Drop1
Push r4
LoadFieldTOS CP#0
@@ -1520,7 +1512,7 @@
Drop1
Push r4
LoadFieldTOS CP#0
- PushConstant CP#41
+ PushConstant CP#40
StoreFieldTOS CP#1
Push r4
LoadFieldTOS CP#0
@@ -1539,7 +1531,7 @@
Push r4
LoadFieldTOS CP#0
LoadFieldTOS CP#21
- PushConstant CP#42
+ PushConstant CP#41
IndirectStaticCall 4, CP#22
PopLocal r12
PushConstant CP#8
@@ -1556,7 +1548,7 @@
LoadFieldTOS CP#0
LoadFieldTOS CP#3
Push r1
- InstanceCall1 2, CP#43
+ InstanceCall1 2, CP#42
StoreLocal r10
StoreFieldTOS CP#1
Push r10
@@ -1585,8 +1577,8 @@
LoadFieldTOS CP#14
PopLocal r4
PushConstant CP#34
- PushConstant CP#44
- IndirectStaticCall 1, CP#35
+ PushConstant CP#43
+ IndirectStaticCall 1, CP#5
Drop1
Push r4
LoadFieldTOS CP#0
@@ -1598,7 +1590,7 @@
Drop1
Push r4
LoadFieldTOS CP#0
- PushConstant CP#45
+ PushConstant CP#44
StoreFieldTOS CP#1
Push r4
LoadFieldTOS CP#0
@@ -1617,7 +1609,7 @@
Push r4
LoadFieldTOS CP#0
LoadFieldTOS CP#21
- PushConstant CP#46
+ PushConstant CP#45
IndirectStaticCall 4, CP#22
PopLocal r12
PushConstant CP#8
@@ -1634,7 +1626,7 @@
LoadFieldTOS CP#0
LoadFieldTOS CP#3
Push r1
- InstanceCall1 2, CP#47
+ InstanceCall1 2, CP#46
StoreLocal r10
StoreFieldTOS CP#1
Push r10
@@ -1659,7 +1651,7 @@
LoadFieldTOS CP#7
Push r4
LoadFieldTOS CP#9
- InstanceCall1 2, CP#48
+ InstanceCall1 2, CP#47
Drop1
PushConstant CP#8
ReturnTOS
@@ -1682,7 +1674,7 @@
LoadFieldTOS CP#7
Push r8
Push r9
- InstanceCall1 3, CP#50
+ InstanceCall1 3, CP#49
Drop1
Jump L12
L12:
@@ -1701,11 +1693,11 @@
IfEqStrictNumTOS
Jump L14
Push r5
- PushConstant CP#37
+ PushConstant CP#36
IfEqStrictNumTOS
Jump L15
Push r5
- PushConstant CP#41
+ PushConstant CP#40
IfEqStrictNumTOS
Jump L16
Jump L17
@@ -1789,17 +1781,17 @@
Push r0
PushConstant CP#2
StoreFieldTOS CP#1
- Allocate CP#36
+ Allocate CP#35
StoreLocal r3
Push r3
PushConstant CP#9
+ StoreFieldTOS CP#36
+ Push r3
+ PushConstant CP#9
StoreFieldTOS CP#37
Push r3
- PushConstant CP#9
- StoreFieldTOS CP#38
- Push r3
PushConstant CP#3
- StoreFieldTOS CP#39
+ StoreFieldTOS CP#38
Push r3
Push r0
StoreFieldTOS CP#4
@@ -1819,7 +1811,7 @@
[3] = ClosureFunction nested () → dart.async::Future<dart.core::int> /* originally async */ ;
[4] = FieldOffset dart.core::_Closure::_context
[5] = TypeArgs [dart.core::int]
- [6] = ArgDesc num-args 0, num-type-args 1, names []
+ [6] = ArgDesc num-args 1, num-type-args 0, names []
[7] = StaticICData target 'dart.async::Completer::sync', arg-desc CP#6
[8] = ContextOffset var [8]
[9] = Null
@@ -1841,26 +1833,24 @@
[25] = ICData target-name '+', arg-desc CP#24
[26] = Type dynamic
[27] = String 'fin'
- [28] = ArgDesc num-args 1, num-type-args 0, names []
- [29] = StaticICData target 'dart.core::print', arg-desc CP#28
- [30] = StaticICData target 'dart.core::print', arg-desc CP#28
- [31] = StaticICData target 'dart.core::print', arg-desc CP#28
- [32] = ICData target-name 'complete', arg-desc CP#24
- [33] = ArgDesc num-args 3, num-type-args 0, names []
- [34] = ICData target-name 'completeError', arg-desc CP#33
- [35] = EndClosureFunctionScope
- [36] = Class dart.core::_Closure
- [37] = FieldOffset dart.core::_Closure::_instantiator_type_arguments
- [38] = FieldOffset dart.core::_Closure::_function_type_arguments
- [39] = FieldOffset dart.core::_Closure::_function
- [40] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#28
- [41] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#28
- [42] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#28
- [43] = TypeArgs [dynamic]
- [44] = ArgDesc num-args 1, num-type-args 1, names []
- [45] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#44
- [46] = ICData get target-name 'future', arg-desc CP#28
- [47] = EndClosureFunctionScope
+ [28] = StaticICData target 'dart.core::print', arg-desc CP#6
+ [29] = StaticICData target 'dart.core::print', arg-desc CP#6
+ [30] = StaticICData target 'dart.core::print', arg-desc CP#6
+ [31] = ICData target-name 'complete', arg-desc CP#24
+ [32] = ArgDesc num-args 3, num-type-args 0, names []
+ [33] = ICData target-name 'completeError', arg-desc CP#32
+ [34] = EndClosureFunctionScope
+ [35] = Class dart.core::_Closure
+ [36] = FieldOffset dart.core::_Closure::_instantiator_type_arguments
+ [37] = FieldOffset dart.core::_Closure::_function_type_arguments
+ [38] = FieldOffset dart.core::_Closure::_function
+ [39] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#6
+ [40] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#6
+ [41] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#6
+ [42] = TypeArgs [dynamic]
+ [43] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#24
+ [44] = ICData get target-name 'future', arg-desc CP#6
+ [45] = EndClosureFunctionScope
}
Closure CP#17 {
EntryOptional 1, 3, 0
@@ -1964,8 +1954,8 @@
MoveSpecial r8, exception
MoveSpecial r9, stackTrace
PushConstant CP#27
- PushConstant CP#29
- IndirectStaticCall 1, CP#28
+ PushConstant CP#28
+ IndirectStaticCall 1, CP#6
Drop1
Push r8
Push r9
@@ -1978,8 +1968,8 @@
LoadFieldTOS CP#16
PopLocal r4
PushConstant CP#27
- PushConstant CP#30
- IndirectStaticCall 1, CP#28
+ PushConstant CP#29
+ IndirectStaticCall 1, CP#6
Drop1
Push r4
LoadFieldTOS CP#0
@@ -1993,8 +1983,8 @@
LoadFieldTOS CP#16
PopLocal r4
PushConstant CP#27
- PushConstant CP#31
- IndirectStaticCall 1, CP#28
+ PushConstant CP#30
+ IndirectStaticCall 1, CP#6
Drop1
Push r4
LoadFieldTOS CP#0
@@ -2004,7 +1994,7 @@
LoadFieldTOS CP#8
Push r4
LoadFieldTOS CP#10
- InstanceCall1 2, CP#32
+ InstanceCall1 2, CP#31
Drop1
PushConstant CP#9
ReturnTOS
@@ -2027,7 +2017,7 @@
LoadFieldTOS CP#8
Push r8
Push r9
- InstanceCall1 3, CP#34
+ InstanceCall1 3, CP#33
Drop1
Jump L5
L5:
@@ -2082,32 +2072,32 @@
PushConstant CP#9
StoreFieldTOS CP#16
Push r0
- Allocate CP#36
+ Allocate CP#35
StoreLocal r3
Push r3
PushConstant CP#9
+ StoreFieldTOS CP#36
+ Push r3
+ PushConstant CP#9
StoreFieldTOS CP#37
Push r3
- PushConstant CP#9
- StoreFieldTOS CP#38
- Push r3
PushConstant CP#17
- StoreFieldTOS CP#39
+ StoreFieldTOS CP#38
Push r3
Push r0
StoreFieldTOS CP#4
StoreFieldTOS CP#21
Push r0
LoadFieldTOS CP#21
- PushConstant CP#40
- IndirectStaticCall 1, CP#28
+ PushConstant CP#39
+ IndirectStaticCall 1, CP#6
StoreLocal r2
Drop1
Push r0
Push r0
LoadFieldTOS CP#21
- PushConstant CP#41
- IndirectStaticCall 1, CP#28
+ PushConstant CP#40
+ IndirectStaticCall 1, CP#6
StoreLocal r3
StoreFieldTOS CP#11
Push r3
@@ -2115,21 +2105,21 @@
Push r0
Push r0
LoadFieldTOS CP#21
- PushConstant CP#42
- IndirectStaticCall 1, CP#28
+ PushConstant CP#41
+ IndirectStaticCall 1, CP#6
StoreLocal r3
StoreFieldTOS CP#12
Push r3
Drop1
- PushConstant CP#43
+ PushConstant CP#42
Push r0
LoadFieldTOS CP#21
- PushConstant CP#45
- IndirectStaticCall 2, CP#44
+ PushConstant CP#43
+ IndirectStaticCall 2, CP#24
Drop1
Push r0
LoadFieldTOS CP#8
- InstanceCall1 1, CP#46
+ InstanceCall1 1, CP#44
ReturnTOS
Push r0
LoadFieldTOS CP#0
diff --git a/pkg/vm/testcases/bytecode/bootstrapping.dart.expect b/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
index 5ff4e07..c6c2c4e 100644
--- a/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
+++ b/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
@@ -654,7 +654,7 @@
PushConstant CP#0
PushStatic CP#0
PushConstant CP#14
- IndirectStaticCall 2, CP#9
+ IndirectStaticCall 2, CP#2
InstanceCall1 2, CP#15
ReturnTOS
L6:
@@ -676,7 +676,7 @@
[11] = ArgDesc num-args 0, num-type-args 0, names []
[12] = StaticICData get target 'dart.core::Uri::base', arg-desc CP#11
[13] = Null
- [14] = StaticICData target 'dart.core::_Uri::file', arg-desc CP#9
+ [14] = StaticICData target 'dart.core::_Uri::file', arg-desc CP#2
[15] = ICData target-name 'resolveUri', arg-desc CP#2
}
]static method _scriptUri() → core::Uri {
diff --git a/pkg/vm/testcases/bytecode/closures.dart.expect b/pkg/vm/testcases/bytecode/closures.dart.expect
index 7bf2d87..6f72b9f 100644
--- a/pkg/vm/testcases/bytecode/closures.dart.expect
+++ b/pkg/vm/testcases/bytecode/closures.dart.expect
@@ -228,7 +228,7 @@
Push r2
InstanceCall1 1, CP#52
Drop1
- PushConstant CP#36
+ PushConstant CP#18
ReturnTOS
}
ConstantPool {
@@ -250,30 +250,30 @@
[15] = Int 0
[16] = Type #lib::A::T1
[17] = TypeArgumentsFieldOffset #lib::A
- [18] = Int 1
- [19] = Type #lib::A::T2
- [20] = Type #lib::A::foo::T3
- [21] = Int 3
- [22] = Type #lib::A::foo::T4
- [23] = Type T5
- [24] = Int 5
- [25] = Type T6
- [26] = Type T7
- [27] = Int 7
- [28] = Type T8
- [29] = ArgDesc num-args 1, num-type-args 1, names []
- [30] = StaticICData target 'dart.core::List::_fromLiteral', arg-desc CP#29
- [31] = ArgDesc num-args 1, num-type-args 0, names []
- [32] = StaticICData target 'dart.core::print', arg-desc CP#31
- [33] = TypeArgs [#lib::A::T1, #lib::A::T2, #lib::A::foo::T3, #lib::A::foo::T4, T5, T6, T7, T8]
- [34] = ArgDesc num-args 0, num-type-args 8, names []
- [35] = StaticICData target '#lib::callWithArgs', arg-desc CP#34
- [36] = Null
+ [18] = Null
+ [19] = Int 1
+ [20] = Type #lib::A::T2
+ [21] = Type #lib::A::foo::T3
+ [22] = Int 3
+ [23] = Type #lib::A::foo::T4
+ [24] = Type T5
+ [25] = Int 5
+ [26] = Type T6
+ [27] = Type T7
+ [28] = Int 7
+ [29] = Type T8
+ [30] = ArgDesc num-args 1, num-type-args 1, names []
+ [31] = StaticICData target 'dart.core::List::_fromLiteral', arg-desc CP#30
+ [32] = ArgDesc num-args 1, num-type-args 0, names []
+ [33] = StaticICData target 'dart.core::print', arg-desc CP#32
+ [34] = TypeArgs [#lib::A::T1, #lib::A::T2, #lib::A::foo::T3, #lib::A::foo::T4, T5, T6, T7, T8]
+ [35] = ArgDesc num-args 0, num-type-args 8, names []
+ [36] = StaticICData target '#lib::callWithArgs', arg-desc CP#35
[37] = EndClosureFunctionScope
[38] = Class dart.core::_Closure
[39] = FieldOffset dart.core::_Closure::_instantiator_type_arguments
[40] = FieldOffset dart.core::_Closure::_function
- [41] = ICData target-name 'call', arg-desc CP#31
+ [41] = ICData target-name 'call', arg-desc CP#32
[42] = EndClosureFunctionScope
[43] = TypeArgs [#lib::C7, #lib::C8]
[44] = ArgDesc num-args 1, num-type-args 2, names []
@@ -306,79 +306,67 @@
Push r1
LoadFieldTOS CP#1
LoadFieldTOS CP#17
- Push r0
+ PushConstant CP#18
InstantiateType CP#16
StoreIndexedTOS
Push r3
+ PushConstant CP#19
+ Push r1
+ LoadFieldTOS CP#1
+ LoadFieldTOS CP#17
PushConstant CP#18
- Push r1
- LoadFieldTOS CP#1
- LoadFieldTOS CP#17
- Push r0
- InstantiateType CP#19
- StoreIndexedTOS
- Push r3
- PushConstant CP#5
- Push r1
- LoadFieldTOS CP#1
- LoadFieldTOS CP#17
- Push r0
InstantiateType CP#20
StoreIndexedTOS
Push r3
- PushConstant CP#21
- Push r1
- LoadFieldTOS CP#1
- LoadFieldTOS CP#17
+ PushConstant CP#5
+ PushConstant CP#18
Push r0
- InstantiateType CP#22
+ InstantiateType CP#21
StoreIndexedTOS
Push r3
- PushConstant CP#6
- Push r1
- LoadFieldTOS CP#1
- LoadFieldTOS CP#17
+ PushConstant CP#22
+ PushConstant CP#18
Push r0
InstantiateType CP#23
StoreIndexedTOS
Push r3
- PushConstant CP#24
- Push r1
- LoadFieldTOS CP#1
- LoadFieldTOS CP#17
+ PushConstant CP#6
+ PushConstant CP#18
Push r0
- InstantiateType CP#25
+ InstantiateType CP#24
StoreIndexedTOS
Push r3
- PushConstant CP#10
- Push r1
- LoadFieldTOS CP#1
- LoadFieldTOS CP#17
+ PushConstant CP#25
+ PushConstant CP#18
Push r0
InstantiateType CP#26
StoreIndexedTOS
Push r3
- PushConstant CP#27
- Push r1
- LoadFieldTOS CP#1
- LoadFieldTOS CP#17
+ PushConstant CP#10
+ PushConstant CP#18
Push r0
- InstantiateType CP#28
+ InstantiateType CP#27
StoreIndexedTOS
- PushConstant CP#30
- IndirectStaticCall 2, CP#29
- PushConstant CP#32
- IndirectStaticCall 1, CP#31
+ Push r3
+ PushConstant CP#28
+ PushConstant CP#18
+ Push r0
+ InstantiateType CP#29
+ StoreIndexedTOS
+ PushConstant CP#31
+ IndirectStaticCall 2, CP#30
+ PushConstant CP#33
+ IndirectStaticCall 1, CP#32
Drop1
Push r1
LoadFieldTOS CP#1
LoadFieldTOS CP#17
Push r0
- InstantiateTypeArgumentsTOS 1, CP#33
- PushConstant CP#35
- IndirectStaticCall 1, CP#34
- Drop1
+ InstantiateTypeArgumentsTOS 1, CP#34
PushConstant CP#36
+ IndirectStaticCall 1, CP#35
+ Drop1
+ PushConstant CP#18
ReturnTOS
}
@@ -417,7 +405,7 @@
Push r2
InstanceCall1 1, CP#41
Drop1
- PushConstant CP#36
+ PushConstant CP#18
ReturnTOS
}
@@ -461,7 +449,7 @@
Push r2
InstanceCall1 1, CP#47
Drop1
- PushConstant CP#36
+ PushConstant CP#18
ReturnTOS
}
diff --git a/pkg/vm/testcases/bytecode/instance_creation.dart b/pkg/vm/testcases/bytecode/instance_creation.dart
index 98259da..5821f59 100644
--- a/pkg/vm/testcases/bytecode/instance_creation.dart
+++ b/pkg/vm/testcases/bytecode/instance_creation.dart
@@ -38,6 +38,35 @@
new B<List<T>>();
}
+class E<K, V> {
+ test_reuse1() => new Map<K, V>();
+}
+
+class F<K, V> extends E<String, List<V>> {
+ test_reuse2() => new Map<String, List<V>>();
+}
+
+class G<K, V> {
+ G();
+ factory G.test_factory() => new H<String, K, V>();
+}
+
+class H<P1, P2, P3> extends G<P2, P3> {}
+
+void foo4() {
+ new G<int, List<String>>.test_factory();
+}
+
+class I {
+ I(param);
+ factory I.test_factory2({param}) => new I(param);
+}
+
+void foo5() {
+ new I.test_factory2();
+ new I.test_factory2(param: 42);
+}
+
main() {
foo1();
foo2();
diff --git a/pkg/vm/testcases/bytecode/instance_creation.dart.expect b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
index 239c9ac..32c2c32 100644
--- a/pkg/vm/testcases/bytecode/instance_creation.dart.expect
+++ b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
@@ -185,6 +185,206 @@
core::print("C: ${s}");
}
}
+class E<K extends core::Object = dynamic, V extends core::Object = dynamic> extends core::Object {
+[@vm.bytecode=
+Bytecode {
+ Entry 0
+ CheckStack
+ Push FP[-5]
+ PushConstant CP#1
+ IndirectStaticCall 1, CP#0
+ Drop1
+ PushConstant CP#2
+ ReturnTOS
+}
+ConstantPool {
+ [0] = ArgDesc num-args 1, num-type-args 0, names []
+ [1] = StaticICData target 'dart.core::Object::', arg-desc CP#0
+ [2] = Null
+}
+] synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+[@vm.bytecode=
+Bytecode {
+ Entry 0
+ CheckStack
+ Push FP[-5]
+ LoadFieldTOS CP#0
+ PushConstant CP#2
+ IndirectStaticCall 1, CP#1
+ ReturnTOS
+ PushConstant CP#3
+ ReturnTOS
+}
+ConstantPool {
+ [0] = TypeArgumentsFieldOffset #lib::E
+ [1] = ArgDesc num-args 1, num-type-args 0, names []
+ [2] = StaticICData target 'dart.core::Map::', arg-desc CP#1
+ [3] = Null
+}
+] method test_reuse1() → dynamic
+ return core::Map::•<self::E::K, self::E::V>();
+}
+class F<K extends core::Object = dynamic, V extends core::Object = dynamic> extends self::E<core::String, core::List<self::F::V>> {
+[@vm.bytecode=
+Bytecode {
+ Entry 0
+ CheckStack
+ Push FP[-5]
+ PushConstant CP#1
+ IndirectStaticCall 1, CP#0
+ Drop1
+ PushConstant CP#2
+ ReturnTOS
+}
+ConstantPool {
+ [0] = ArgDesc num-args 1, num-type-args 0, names []
+ [1] = StaticICData target '#lib::E::', arg-desc CP#0
+ [2] = Null
+}
+] synthetic constructor •() → void
+ : super self::E::•()
+ ;
+[@vm.bytecode=
+Bytecode {
+ Entry 0
+ CheckStack
+ Push FP[-5]
+ LoadFieldTOS CP#0
+ PushConstant CP#2
+ IndirectStaticCall 1, CP#1
+ ReturnTOS
+ PushConstant CP#3
+ ReturnTOS
+}
+ConstantPool {
+ [0] = TypeArgumentsFieldOffset #lib::F
+ [1] = ArgDesc num-args 1, num-type-args 0, names []
+ [2] = StaticICData target 'dart.core::Map::', arg-desc CP#1
+ [3] = Null
+}
+] method test_reuse2() → dynamic
+ return core::Map::•<core::String, core::List<self::F::V>>();
+}
+class G<K extends core::Object = dynamic, V extends core::Object = dynamic> extends core::Object {
+[@vm.bytecode=
+Bytecode {
+ Entry 0
+ CheckStack
+ Push FP[-5]
+ PushConstant CP#1
+ IndirectStaticCall 1, CP#0
+ Drop1
+ PushConstant CP#2
+ ReturnTOS
+}
+ConstantPool {
+ [0] = ArgDesc num-args 1, num-type-args 0, names []
+ [1] = StaticICData target 'dart.core::Object::', arg-desc CP#0
+ [2] = Null
+}
+] constructor •() → void
+ : super core::Object::•()
+ ;
+[@vm.bytecode=
+Bytecode {
+ Entry 1
+ CheckStack
+ PushConstant CP#1
+ Push FP[-5]
+ InstantiateTypeArgumentsTOS 1, CP#3
+ PushConstant CP#0
+ AllocateT
+ StoreLocal r0
+ Push r0
+ PushConstant CP#5
+ IndirectStaticCall 1, CP#4
+ Drop1
+ ReturnTOS
+ PushConstant CP#1
+ ReturnTOS
+}
+ConstantPool {
+ [0] = Class #lib::H
+ [1] = Null
+ [2] = TypeArgs [dart.core::String, #lib::G::test_factory::K, #lib::G::test_factory::V]
+ [3] = TypeArgumentsForInstanceAllocation #lib::H type-args CP#2
+ [4] = ArgDesc num-args 1, num-type-args 0, names []
+ [5] = StaticICData target '#lib::H::', arg-desc CP#4
+}
+] static factory test_factory<K extends core::Object = dynamic, V extends core::Object = dynamic>() → self::G<self::G::test_factory::K, self::G::test_factory::V>
+ return new self::H::•<core::String, self::G::test_factory::K, self::G::test_factory::V>();
+}
+class H<P1 extends core::Object = dynamic, P2 extends core::Object = dynamic, P3 extends core::Object = dynamic> extends self::G<self::H::P2, self::H::P3> {
+[@vm.bytecode=
+Bytecode {
+ Entry 0
+ CheckStack
+ Push FP[-5]
+ PushConstant CP#1
+ IndirectStaticCall 1, CP#0
+ Drop1
+ PushConstant CP#2
+ ReturnTOS
+}
+ConstantPool {
+ [0] = ArgDesc num-args 1, num-type-args 0, names []
+ [1] = StaticICData target '#lib::G::', arg-desc CP#0
+ [2] = Null
+}
+] synthetic constructor •() → void
+ : super self::G::•()
+ ;
+}
+class I extends core::Object {
+[@vm.bytecode=
+Bytecode {
+ Entry 0
+ CheckStack
+ Push FP[-6]
+ PushConstant CP#1
+ IndirectStaticCall 1, CP#0
+ Drop1
+ PushConstant CP#2
+ ReturnTOS
+}
+ConstantPool {
+ [0] = ArgDesc num-args 1, num-type-args 0, names []
+ [1] = StaticICData target 'dart.core::Object::', arg-desc CP#0
+ [2] = Null
+}
+] constructor •(dynamic param) → void
+ : super core::Object::•()
+ ;
+[@vm.bytecode=
+Bytecode {
+ EntryOptional 1, 0, 1
+ LoadConstant r1, CP#0
+ LoadConstant r1, CP#1
+ Frame 1
+ CheckStack
+ Allocate CP#2
+ StoreLocal r2
+ Push r2
+ Push r1
+ PushConstant CP#4
+ IndirectStaticCall 2, CP#3
+ Drop1
+ ReturnTOS
+ PushConstant CP#1
+ ReturnTOS
+}
+ConstantPool {
+ [0] = String 'param'
+ [1] = Null
+ [2] = Class #lib::I
+ [3] = ArgDesc num-args 2, num-type-args 0, names []
+ [4] = StaticICData target '#lib::I::', arg-desc CP#3
+}
+] static factory test_factory2({dynamic param = null}) → self::I
+ return new self::I::•(param);
+}
[@vm.bytecode=
Bytecode {
Entry 1
@@ -257,9 +457,9 @@
Bytecode {
Entry 1
CheckStack
- PushConstant CP#3
+ PushConstant CP#1
Push FP[-5]
- InstantiateTypeArgumentsTOS 1, CP#2
+ InstantiateTypeArgumentsTOS 1, CP#3
PushConstant CP#0
AllocateT
StoreLocal r0
@@ -268,14 +468,14 @@
IndirectStaticCall 1, CP#4
Drop1
Drop1
- PushConstant CP#3
+ PushConstant CP#1
ReturnTOS
}
ConstantPool {
[0] = Class #lib::B
- [1] = TypeArgs [dart.core::List<#lib::foo3::T>]
- [2] = TypeArgumentsForInstanceAllocation #lib::B type-args CP#1
- [3] = Null
+ [1] = Null
+ [2] = TypeArgs [dart.core::List<#lib::foo3::T>]
+ [3] = TypeArgumentsForInstanceAllocation #lib::B type-args CP#2
[4] = ArgDesc num-args 1, num-type-args 0, names []
[5] = StaticICData target '#lib::B::', arg-desc CP#4
}
@@ -286,6 +486,54 @@
Bytecode {
Entry 0
CheckStack
+ PushConstant CP#0
+ PushConstant CP#2
+ IndirectStaticCall 1, CP#1
+ Drop1
+ PushConstant CP#3
+ ReturnTOS
+}
+ConstantPool {
+ [0] = TypeArgs [dart.core::int, dart.core::List<dart.core::String>]
+ [1] = ArgDesc num-args 1, num-type-args 0, names []
+ [2] = StaticICData target '#lib::G::test_factory', arg-desc CP#1
+ [3] = Null
+}
+]static method foo4() → void {
+ self::G::test_factory<core::int, core::List<core::String>>();
+}
+[@vm.bytecode=
+Bytecode {
+ Entry 0
+ CheckStack
+ PushConstant CP#0
+ PushConstant CP#2
+ IndirectStaticCall 1, CP#1
+ Drop1
+ PushConstant CP#0
+ PushConstant CP#3
+ PushConstant CP#5
+ IndirectStaticCall 2, CP#4
+ Drop1
+ PushConstant CP#0
+ ReturnTOS
+}
+ConstantPool {
+ [0] = Null
+ [1] = ArgDesc num-args 1, num-type-args 0, names []
+ [2] = StaticICData target '#lib::I::test_factory2', arg-desc CP#1
+ [3] = Int 42
+ [4] = ArgDesc num-args 2, num-type-args 0, names [param]
+ [5] = StaticICData target '#lib::I::test_factory2', arg-desc CP#4
+}
+]static method foo5() → void {
+ self::I::test_factory2();
+ self::I::test_factory2(param: 42);
+}
+[@vm.bytecode=
+Bytecode {
+ Entry 0
+ CheckStack
PushConstant CP#1
IndirectStaticCall 0, CP#0
Drop1
diff --git a/pkg/vm/testcases/bytecode/literals.dart.expect b/pkg/vm/testcases/bytecode/literals.dart.expect
index 1d49cf2..c248ce0 100644
--- a/pkg/vm/testcases/bytecode/literals.dart.expect
+++ b/pkg/vm/testcases/bytecode/literals.dart.expect
@@ -551,16 +551,16 @@
PushConstant CP#15
IndirectStaticCall 1, CP#9
Drop1
- PushConstant CP#17
+ PushConstant CP#16
Push FP[-8]
- InstantiateTypeArgumentsTOS 1, CP#16
+ InstantiateTypeArgumentsTOS 1, CP#17
PushConstant CP#18
PushConstant CP#19
IndirectStaticCall 2, CP#7
PushConstant CP#20
IndirectStaticCall 1, CP#9
Drop1
- PushConstant CP#17
+ PushConstant CP#16
Push FP[-8]
InstantiateTypeArgumentsTOS 1, CP#21
PushConstant CP#1
@@ -580,7 +580,7 @@
PushConstant CP#23
IndirectStaticCall 1, CP#9
Drop1
- PushConstant CP#17
+ PushConstant CP#16
ReturnTOS
}
ConstantPool {
@@ -600,8 +600,8 @@
[13] = ICData target-name 'toString', arg-desc CP#9
[14] = StaticICData target 'dart.core::Map::_fromLiteral', arg-desc CP#7
[15] = StaticICData target 'dart.core::print', arg-desc CP#9
- [16] = TypeArgs [dart.core::String, #lib::test_map_literal::T]
- [17] = Null
+ [16] = Null
+ [17] = TypeArgs [dart.core::String, #lib::test_map_literal::T]
[18] = List type-arg dynamic, entries CP# []
[19] = StaticICData target 'dart.core::Map::_fromLiteral', arg-desc CP#7
[20] = StaticICData target 'dart.core::print', arg-desc CP#9
diff --git a/pkg/vm/testcases/bytecode/type_ops.dart.expect b/pkg/vm/testcases/bytecode/type_ops.dart.expect
index fe9a2d4..16f4aaf 100644
--- a/pkg/vm/testcases/bytecode/type_ops.dart.expect
+++ b/pkg/vm/testcases/bytecode/type_ops.dart.expect
@@ -159,8 +159,7 @@
Entry 0
CheckStack
Push FP[-5]
- Push FP[-6]
- LoadFieldTOS CP#0
+ PushConstant CP#0
Push FP[-7]
PushConstant CP#1
InstanceCall1 4, CP#3
@@ -174,31 +173,31 @@
L1:
Push FP[-5]
Push FP[-6]
- LoadFieldTOS CP#0
+ LoadFieldTOS CP#8
Push FP[-7]
- PushConstant CP#8
- InstanceCall1 4, CP#9
+ PushConstant CP#9
+ InstanceCall1 4, CP#10
PushConstant CP#4
IfNeStrictTOS
Jump L2
- PushConstant CP#10
PushConstant CP#11
+ PushConstant CP#12
IndirectStaticCall 1, CP#6
Drop1
L2:
Push FP[-5]
Push FP[-6]
- LoadFieldTOS CP#0
+ LoadFieldTOS CP#8
Push FP[-7]
- PushConstant CP#12
- InstanceCall1 4, CP#13
- InstanceCall1 1, CP#14
+ PushConstant CP#13
+ InstanceCall1 4, CP#14
+ InstanceCall1 1, CP#15
ReturnTOS
- PushConstant CP#15
+ PushConstant CP#0
ReturnTOS
}
ConstantPool {
- [0] = TypeArgumentsFieldOffset #lib::D
+ [0] = Null
[1] = Type #lib::A<#lib::D::foo3::T1>
[2] = ArgDesc num-args 4, num-type-args 0, names []
[3] = ICData target-name 'dart.core::_instanceOf', arg-desc CP#2
@@ -206,14 +205,14 @@
[5] = String '31'
[6] = ArgDesc num-args 1, num-type-args 0, names []
[7] = StaticICData target 'dart.core::print', arg-desc CP#6
- [8] = Type #lib::C<dart.core::Map<#lib::D::foo3::T1, #lib::D::P>, dart.core::List<#lib::D::foo3::T2>, #lib::D::Q>
- [9] = ICData target-name 'dart.core::_instanceOf', arg-desc CP#2
- [10] = String '32'
- [11] = StaticICData target 'dart.core::print', arg-desc CP#6
- [12] = Type dart.core::Map<#lib::D::foo3::T2, #lib::D::Q>
- [13] = ICData target-name 'dart.core::_as', arg-desc CP#2
- [14] = ICData get target-name 'values', arg-desc CP#6
- [15] = Null
+ [8] = TypeArgumentsFieldOffset #lib::D
+ [9] = Type #lib::C<dart.core::Map<#lib::D::foo3::T1, #lib::D::P>, dart.core::List<#lib::D::foo3::T2>, #lib::D::Q>
+ [10] = ICData target-name 'dart.core::_instanceOf', arg-desc CP#2
+ [11] = String '32'
+ [12] = StaticICData target 'dart.core::print', arg-desc CP#6
+ [13] = Type dart.core::Map<#lib::D::foo3::T2, #lib::D::Q>
+ [14] = ICData target-name 'dart.core::_as', arg-desc CP#2
+ [15] = ICData get target-name 'values', arg-desc CP#6
}
] method foo3<T1 extends core::Object = dynamic, T2 extends core::Object = dynamic>(dynamic z) → dynamic {
if(z is self::A<self::D::foo3::T1>) {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
index 34dfa36..925603f 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/annotation.dart.expect
@@ -37,7 +37,7 @@
}
static method foo([@vm.inferred-type.metadata=dart.core::Null?] (core::List<core::int>) → void a) → core::int {
@self::VarAnnotation::•() core::int x = 2;
- return x.{core::num::+}(2);
+ return [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+] x.{core::num::+}(2);
}
@self::ParametrizedAnnotation::•<core::Null>(null)
static method main(core::List<core::String> args) → dynamic {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
index 49b8a68..86cc1b1 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
@@ -11,13 +11,10 @@
: self::_Vector::_offset = 0, self::_Vector::_length = size, self::_Vector::_elements = [@vm.inferred-type.metadata=dart.typed_data::_Float64List] typ::Float64List::•(size), super core::Object::•()
;
operator [](core::int i) → core::double
- return [@vm.direct-call.metadata=dart.typed_data::_Float64List::[]] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.direct-call.metadata=#lib::_Vector::_elements] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements}.{core::List::[]}(i.{core::num::+}([@vm.direct-call.metadata=#lib::_Vector::_offset] [@vm.inferred-type.metadata=!] this.{self::_Vector::_offset}));
- operator []=([@vm.inferred-type.metadata=!] core::int i, core::double value) → void {
- let dynamic #t1 = [@vm.direct-call.metadata=#lib::_Vector::_elements] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements} in let dynamic #t2 = i in let dynamic #t3 = [@vm.direct-call.metadata=#lib::_Vector::_offset] [@vm.inferred-type.metadata=!] this.{self::_Vector::_offset} in throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
- }
+ return [@vm.direct-call.metadata=dart.typed_data::_Float64List::[]] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.direct-call.metadata=#lib::_Vector::_elements] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements}.{core::List::[]}([@vm.direct-call.metadata=dart.core::_IntegerImplementation::+??] i.{core::num::+}([@vm.direct-call.metadata=#lib::_Vector::_offset] [@vm.inferred-type.metadata=!] this.{self::_Vector::_offset}));
operator *([@vm.inferred-type.metadata=#lib::_Vector?] self::_Vector a) → core::double {
core::double result = 0.0;
- for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<??] [@vm.inferred-type.metadata=dart.core::bool?] i.{core::num::<}([@vm.direct-call.metadata=#lib::_Vector::_length] [@vm.inferred-type.metadata=!] this.{self::_Vector::_length}); i = i.{core::num::+}(1))
+ for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<??] [@vm.inferred-type.metadata=dart.core::bool] i.{core::num::<}([@vm.direct-call.metadata=#lib::_Vector::_length] [@vm.inferred-type.metadata=!] this.{self::_Vector::_length}); i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+??] i.{core::num::+}(1))
result = [@vm.direct-call.metadata=dart.core::_Double::+??] [@vm.inferred-type.metadata=dart.core::_Double] result.{core::double::+}([@vm.direct-call.metadata=dart.core::_Double::*] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.direct-call.metadata=#lib::_Vector::[]] [@vm.inferred-type.metadata=dart.core::_Double] this.{self::_Vector::[]}(i).{core::double::*}([@vm.direct-call.metadata=#lib::_Vector::[]??] [@vm.inferred-type.metadata=dart.core::_Double] a.{self::_Vector::[]}(i)));
return result;
}
@@ -25,8 +22,8 @@
[@vm.inferred-type.metadata=#lib::_Vector?]static field self::_Vector v = new self::_Vector::•(10);
[@vm.inferred-type.metadata=dart.core::_Double?]static field core::double x = 0.0;
static method main(core::List<core::String> args) → dynamic {
- core::Stopwatch timer = let final core::Stopwatch #t4 = new core::Stopwatch::•() in let final dynamic #t5 = [@vm.direct-call.metadata=dart.core::Stopwatch::start] #t4.{core::Stopwatch::start}() in #t4;
- for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<??] [@vm.inferred-type.metadata=dart.core::bool?] i.{core::num::<}(100000000); i = i.{core::num::+}(1)) {
+ core::Stopwatch timer = let final core::Stopwatch #t1 = new core::Stopwatch::•() in let final dynamic #t2 = [@vm.direct-call.metadata=dart.core::Stopwatch::start] #t1.{core::Stopwatch::start}() in #t1;
+ for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<??] [@vm.inferred-type.metadata=dart.core::bool] i.{core::num::<}(100000000); i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+??] i.{core::num::+}(1)) {
self::x = [@vm.direct-call.metadata=dart.core::_Double::+??] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.inferred-type.metadata=dart.core::_Double?] self::x.{core::double::+}([@vm.direct-call.metadata=#lib::_Vector::*??] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.inferred-type.metadata=#lib::_Vector?] self::v.{self::_Vector::*}([@vm.inferred-type.metadata=#lib::_Vector?] self::v));
}
[@vm.direct-call.metadata=dart.core::Stopwatch::stop] timer.{core::Stopwatch::stop}();
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect
index 3bbe8aa..002fca8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect
@@ -12,7 +12,7 @@
: super self::A::•()
;
method foo() → core::int
- return 1.{core::num::+}([@vm.inferred-type.metadata=#lib::B] self::knownResult().foo() as{TypeError} core::num) as{TypeError} core::int;
+ return [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+] 1.{core::num::+}([@vm.inferred-type.metadata=#lib::B] self::knownResult().foo() as{TypeError} core::num) as{TypeError} core::int;
}
class TearOffDynamicMethod extends core::Object {
field dynamic bazz;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart.expect
index fb289be..00d3f0f 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_interface_method.dart.expect
@@ -13,7 +13,7 @@
: super self::A::•()
;
method foo() → core::int
- return 1.{core::num::+}([@vm.inferred-type.metadata=#lib::B] self::knownResult().foo() as{TypeError} core::num) as{TypeError} core::int;
+ return [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+] 1.{core::num::+}([@vm.inferred-type.metadata=#lib::B] self::knownResult().foo() as{TypeError} core::num) as{TypeError} core::int;
}
class TearOffInterfaceMethod extends core::Object {
field dynamic bazz;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect
index 2bb45cc..72d0517 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect
@@ -13,14 +13,14 @@
: super self::A::•()
;
method foo() → core::int
- return 1.{core::num::+}([@vm.inferred-type.metadata=#lib::B] self::knownResult().foo() as{TypeError} core::num) as{TypeError} core::int;
+ return [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+] 1.{core::num::+}([@vm.inferred-type.metadata=#lib::B] self::knownResult().foo() as{TypeError} core::num) as{TypeError} core::int;
}
abstract class Base extends core::Object {
synthetic constructor •() → void
: super core::Object::•()
;
method foo() → core::int
- return 3.{core::num::+}([@vm.inferred-type.metadata=#lib::B] self::knownResult().foo() as{TypeError} core::num) as{TypeError} core::int;
+ return [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+] 3.{core::num::+}([@vm.inferred-type.metadata=#lib::B] self::knownResult().foo() as{TypeError} core::num) as{TypeError} core::int;
method doCall(dynamic x) → core::int
return x.call() as{TypeError} core::int;
}
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index df3d515..e7c7886 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -856,131 +856,6 @@
return cobject;
}
-static bool IsHexDigit(char c) {
- return (('0' <= c) && (c <= '9')) || (('A' <= c) && (c <= 'F')) ||
- (('a' <= c) && (c <= 'f'));
-}
-
-static int HexDigitToInt(char c) {
- if (('0' <= c) && (c <= '9')) return c - '0';
- if (('A' <= c) && (c <= 'F')) return 10 + (c - 'A');
- return 10 + (c - 'a');
-}
-
-Dart_CObject* CObject::NewBigint(const char* hex_value) {
- if (hex_value == NULL) {
- return NULL;
- }
- bool neg = false;
- if (hex_value[0] == '-') {
- neg = true;
- hex_value++;
- }
- if ((hex_value[0] != '0') ||
- ((hex_value[1] != 'x') && (hex_value[1] != 'X'))) {
- return NULL;
- }
- hex_value += 2;
- intptr_t hex_i = strlen(hex_value); // Terminating byte excluded.
- if (hex_i == 0) {
- return NULL;
- }
- const int kBitsPerHexDigit = 4;
- const int kHexDigitsPerDigit = 8;
- const int kBitsPerDigit = kBitsPerHexDigit * kHexDigitsPerDigit;
- const intptr_t len = (hex_i + kHexDigitsPerDigit - 1) / kHexDigitsPerDigit;
- Dart_CObject* cobject = New(Dart_CObject_kBigint);
- cobject->value.as_bigint.digits = NewUint32Array(len);
- uint32_t* digits = reinterpret_cast<uint32_t*>(
- cobject->value.as_bigint.digits->value.as_typed_data.values);
- intptr_t used = 0;
- uint32_t digit = 0;
- intptr_t bit_i = 0;
- while (--hex_i >= 0) {
- if (!IsHexDigit(hex_value[hex_i])) {
- return NULL;
- }
- digit += HexDigitToInt(hex_value[hex_i]) << bit_i;
- bit_i += kBitsPerHexDigit;
- if (bit_i == kBitsPerDigit) {
- bit_i = 0;
- digits[used++] = digit;
- digit = 0;
- }
- }
- if (bit_i != 0) {
- digits[used++] = digit;
- }
- while ((used > 0) && (digits[used - 1] == 0)) {
- used--;
- }
- cobject->value.as_bigint.used = used;
- if (used == 0) {
- neg = false;
- }
- cobject->value.as_bigint.neg = neg;
- return cobject;
-}
-
-static char IntToHexDigit(int i) {
- ASSERT(0 <= i && i < 16);
- if (i < 10) return static_cast<char>('0' + i);
- return static_cast<char>('A' + (i - 10));
-}
-
-char* CObject::BigintToHexValue(Dart_CObject* bigint) {
- ASSERT(bigint->type == Dart_CObject_kBigint);
- const intptr_t used = bigint->value.as_bigint.used;
- if (used == 0) {
- const char* zero = "0x0";
- const size_t len = strlen(zero) + 1;
- char* hex_value = reinterpret_cast<char*>(malloc(len));
- strncpy(hex_value, zero, len);
- return hex_value;
- }
- const int kBitsPerHexDigit = 4;
- const int kHexDigitsPerDigit = 8;
- const intptr_t kMaxUsed = (kIntptrMax - 4) / kHexDigitsPerDigit;
- if (used > kMaxUsed) {
- return NULL;
- }
- intptr_t hex_len = (used - 1) * kHexDigitsPerDigit;
- const uint32_t* digits = reinterpret_cast<uint32_t*>(
- bigint->value.as_bigint.digits->value.as_typed_data.values);
- // The most significant digit may use fewer than kHexDigitsPerDigit digits.
- uint32_t digit = digits[used - 1];
- ASSERT(digit != 0); // Value must be clamped.
- while (digit != 0) {
- hex_len++;
- digit >>= kBitsPerHexDigit;
- }
- const bool neg = bigint->value.as_bigint.neg;
- // Add bytes for '0x', for the minus sign, and for the trailing \0 character.
- const int32_t len = (neg ? 1 : 0) + 2 + hex_len + 1;
- char* hex_value = reinterpret_cast<char*>(malloc(len));
- intptr_t pos = len;
- hex_value[--pos] = '\0';
- for (intptr_t i = 0; i < (used - 1); i++) {
- digit = digits[i];
- for (intptr_t j = 0; j < kHexDigitsPerDigit; j++) {
- hex_value[--pos] = IntToHexDigit(digit & 0xf);
- digit >>= kBitsPerHexDigit;
- }
- }
- digit = digits[used - 1];
- while (digit != 0) {
- hex_value[--pos] = IntToHexDigit(digit & 0xf);
- digit >>= kBitsPerHexDigit;
- }
- hex_value[--pos] = 'x';
- hex_value[--pos] = '0';
- if (neg) {
- hex_value[--pos] = '-';
- }
- ASSERT(pos == 0);
- return hex_value;
-}
-
Dart_CObject* CObject::NewDouble(double value) {
Dart_CObject* cobject = New(Dart_CObject_kDouble);
cobject->value.as_double = value;
diff --git a/runtime/bin/dartutils.h b/runtime/bin/dartutils.h
index 7c4a735..661ec7f 100644
--- a/runtime/bin/dartutils.h
+++ b/runtime/bin/dartutils.h
@@ -298,7 +298,6 @@
bool IsInt64() { return type() == Dart_CObject_kInt64; }
bool IsInt32OrInt64() { return IsInt32() || IsInt64(); }
bool IsIntptr() { return IsInt32OrInt64(); }
- bool IsBigint() { return type() == Dart_CObject_kBigint; }
bool IsDouble() { return type() == Dart_CObject_kDouble; }
bool IsString() { return type() == Dart_CObject_kString; }
bool IsArray() { return type() == Dart_CObject_kArray; }
@@ -326,8 +325,6 @@
static Dart_CObject* NewInt32(int32_t value);
static Dart_CObject* NewInt64(int64_t value);
static Dart_CObject* NewIntptr(intptr_t value);
- static Dart_CObject* NewBigint(const char* hex_value);
- static char* BigintToHexValue(Dart_CObject* bigint);
static Dart_CObject* NewDouble(double value);
static Dart_CObject* NewString(intptr_t length);
static Dart_CObject* NewString(const char* str);
@@ -468,36 +465,6 @@
DISALLOW_COPY_AND_ASSIGN(CObjectIntptr);
};
-class CObjectBigint : public CObject {
- public:
- // DECLARE_COBJECT_CONSTRUCTORS(Bigint) would miss hex_value_ initialization.
- explicit CObjectBigint(Dart_CObject* cobject) : CObject(cobject) {
- ASSERT(type() == Dart_CObject_kBigint);
- cobject_ = cobject;
- hex_value_ = NULL;
- }
- explicit CObjectBigint(CObject* cobject) : CObject() {
- ASSERT(cobject != NULL);
- ASSERT(cobject->type() == Dart_CObject_kBigint);
- cobject_ = cobject->AsApiCObject();
- hex_value_ = NULL;
- }
-
- char* Value() {
- if (hex_value_ == NULL) {
- hex_value_ = BigintToHexValue(cobject_);
- }
- ASSERT(hex_value_ != NULL);
- return hex_value_;
- }
-
- ~CObjectBigint() { free(hex_value_); }
-
- private:
- char* hex_value_;
- DISALLOW_COPY_AND_ASSIGN(CObjectBigint);
-};
-
class CObjectDouble : public CObject {
public:
DECLARE_COBJECT_CONSTRUCTORS(Double)
diff --git a/runtime/bin/directory_fuchsia.cc b/runtime/bin/directory_fuchsia.cc
index 858ccac..999a6d4 100644
--- a/runtime/bin/directory_fuchsia.cc
+++ b/runtime/bin/directory_fuchsia.cc
@@ -10,7 +10,7 @@
#include <dirent.h> // NOLINT
#include <errno.h> // NOLINT
#include <fcntl.h> // NOLINT
-#include <fdio/namespace.h> // NOLINT
+#include <lib/fdio/namespace.h> // NOLINT
#include <stdlib.h> // NOLINT
#include <string.h> // NOLINT
#include <sys/param.h> // NOLINT
diff --git a/runtime/bin/eventhandler_fuchsia.cc b/runtime/bin/eventhandler_fuchsia.cc
index 16eee9d..b2dd6e2 100644
--- a/runtime/bin/eventhandler_fuchsia.cc
+++ b/runtime/bin/eventhandler_fuchsia.cc
@@ -10,7 +10,7 @@
#include <errno.h>
#include <fcntl.h>
-#include <fdio/private.h>
+#include <lib/fdio/private.h>
#include <poll.h>
#include <pthread.h>
#include <stdio.h>
diff --git a/runtime/bin/eventhandler_fuchsia.h b/runtime/bin/eventhandler_fuchsia.h
index 50f4520..170f7bd 100644
--- a/runtime/bin/eventhandler_fuchsia.h
+++ b/runtime/bin/eventhandler_fuchsia.h
@@ -10,7 +10,7 @@
#endif
#include <errno.h>
-#include <fdio/private.h>
+#include <lib/fdio/private.h>
#include <sys/socket.h>
#include <unistd.h>
#include <zircon/status.h>
diff --git a/runtime/bin/extensions_fuchsia.cc b/runtime/bin/extensions_fuchsia.cc
index 34aa8d0..db447a3 100644
--- a/runtime/bin/extensions_fuchsia.cc
+++ b/runtime/bin/extensions_fuchsia.cc
@@ -9,7 +9,7 @@
#include <dlfcn.h>
#include <fcntl.h>
-#include <fdio/io.h>
+#include <lib/fdio/io.h>
#include <launchpad/vmo.h>
#include <zircon/dlfcn.h>
diff --git a/runtime/bin/file_fuchsia.cc b/runtime/bin/file_fuchsia.cc
index dbec7d8..5d3dffb 100644
--- a/runtime/bin/file_fuchsia.cc
+++ b/runtime/bin/file_fuchsia.cc
@@ -9,7 +9,7 @@
#include <errno.h> // NOLINT
#include <fcntl.h> // NOLINT
-#include <fdio/namespace.h> // NOLINT
+#include <lib/fdio/namespace.h> // NOLINT
#include <libgen.h> // NOLINT
#include <sys/mman.h> // NOLINT
#include <sys/stat.h> // NOLINT
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 7b8346b..59b994e 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -88,6 +88,8 @@
static Dart_Isolate main_isolate = NULL;
+static void ReadFile(const char* filename, uint8_t** buffer, intptr_t* size);
+
static Dart_Handle CreateRuntimeOptions(CommandLineOptions* options) {
int options_count = options->count();
Dart_Handle dart_arguments =
@@ -213,6 +215,54 @@
}
}
+static Dart_Isolate IsolateSetupHelperAotCompilationDart2(
+ const char* script_uri,
+ const char* main,
+ const char* package_root,
+ const char* packages_config,
+ Dart_IsolateFlags* flags,
+ char** error,
+ int* exit_code) {
+ uint8_t* payload = NULL;
+ intptr_t payload_length = -1;
+ if (File::GetType(NULL, script_uri, true) == File::kIsFile) {
+ ReadFile(script_uri, &payload, &payload_length);
+ }
+ if (payload == NULL ||
+ DartUtils::SniffForMagicNumber(payload, payload_length) !=
+ DartUtils::kKernelMagicNumber) {
+ FATAL1(
+ "Dart 2.0 AOT compilations only accept Kernel IR files as "
+ "input ('%s' is not a valid Kernel IR file).\n",
+ script_uri);
+ }
+
+ auto isolate_data = new IsolateData(script_uri, NULL, NULL, NULL);
+
+ // We bootstrap the isolate from the Kernel file (instead of using a
+ // potentially linked-in kernel file).
+ Dart_Isolate isolate = Dart_CreateIsolateFromKernel(
+ script_uri, main, payload, payload_length, flags, isolate_data, error);
+ if (isolate == NULL) {
+ free(payload);
+ return NULL;
+ }
+
+ Dart_EnterScope();
+ Dart_Handle library = Dart_LoadScriptFromKernel(payload, payload_length);
+ free(payload);
+ CHECK_RESULT(library);
+ Dart_Handle url = DartUtils::NewString("dart:_builtin");
+ CHECK_RESULT(url);
+ Dart_Handle builtin_lib = Dart_LookupLibrary(url);
+ CHECK_RESULT(builtin_lib);
+ isolate_data->set_builtin_lib(builtin_lib);
+ Dart_ExitScope();
+ Dart_ExitIsolate();
+
+ return isolate;
+}
+
static Dart_Isolate IsolateSetupHelper(Dart_Isolate isolate,
bool is_main_isolate,
const char* script_uri,
@@ -655,6 +705,7 @@
#else
bool set_native_resolvers = isolate_snapshot_data != NULL;
#endif // !defined(DART_PRECOMPILED_RUNTIME)
+
created_isolate =
IsolateSetupHelper(isolate, is_main_isolate, script_uri, package_root,
packages_config, set_native_resolvers,
@@ -888,9 +939,17 @@
flags.entry_points = standalone_entry_points;
}
- Dart_Isolate isolate = CreateIsolateAndSetupHelper(
- is_main_isolate, script_name, "main", Options::package_root(),
- Options::packages_file(), &flags, &error, &exit_code);
+ Dart_Isolate isolate = NULL;
+ if (flags.strong && Options::gen_snapshot_kind() == kAppAOT) {
+ isolate = IsolateSetupHelperAotCompilationDart2(
+ script_name, "main", Options::package_root(), Options::packages_file(),
+ &flags, &error, &exit_code);
+ } else {
+ isolate = CreateIsolateAndSetupHelper(
+ is_main_isolate, script_name, "main", Options::package_root(),
+ Options::packages_file(), &flags, &error, &exit_code);
+ }
+
if (isolate == NULL) {
delete[] isolate_name;
Log::PrintErr("%s\n", error);
diff --git a/runtime/bin/namespace_fuchsia.cc b/runtime/bin/namespace_fuchsia.cc
index b84ccb4..ff8ea79 100644
--- a/runtime/bin/namespace_fuchsia.cc
+++ b/runtime/bin/namespace_fuchsia.cc
@@ -9,8 +9,8 @@
#include <errno.h>
#include <fcntl.h>
-#include <fdio/namespace.h>
-#include <fdio/private.h>
+#include <lib/fdio/namespace.h>
+#include <lib/fdio/private.h>
#include <zircon/status.h>
#include "bin/file.h"
diff --git a/runtime/bin/process_fuchsia.cc b/runtime/bin/process_fuchsia.cc
index d8ff3d0..fb52be3 100644
--- a/runtime/bin/process_fuchsia.cc
+++ b/runtime/bin/process_fuchsia.cc
@@ -9,10 +9,10 @@
#include <errno.h>
#include <fcntl.h>
-#include <fdio/io.h>
-#include <fdio/namespace.h>
-#include <fdio/private.h>
-#include <fdio/util.h>
+#include <lib/fdio/io.h>
+#include <lib/fdio/namespace.h>
+#include <lib/fdio/private.h>
+#include <lib/fdio/util.h>
#include <launchpad/launchpad.h>
#include <launchpad/vmo.h>
#include <poll.h>
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index c52f569..b5bdd1a 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -261,7 +261,6 @@
void* isolate_callback_data,
Dart_WeakPersistentHandle handle,
void* peer);
-typedef void (*Dart_PeerFinalizer)(void* peer);
/**
* Is this an error handle?
@@ -1760,7 +1759,9 @@
* \param latin1_array Array of Latin-1 encoded characters. This must not move.
* \param length The length of the characters array.
* \param peer An external pointer to associate with this string.
- * \param cback A callback to be called when this string is finalized.
+ * \param external_allocation_size The number of externally allocated
+ * bytes for peer. Used to inform the garbage collector.
+ * \param callback A callback to be called when this string is finalized.
*
* \return The String object if no error occurs. Otherwise returns
* an error handle.
@@ -1769,7 +1770,8 @@
Dart_NewExternalLatin1String(const uint8_t* latin1_array,
intptr_t length,
void* peer,
- Dart_PeerFinalizer cback);
+ intptr_t external_allocation_size,
+ Dart_WeakPersistentHandleFinalizer callback);
/**
* Returns a String which references an external array of UTF-16 encoded
@@ -1778,15 +1780,19 @@
* \param utf16_array An array of UTF-16 encoded characters. This must not move.
* \param length The length of the characters array.
* \param peer An external pointer to associate with this string.
- * \param cback A callback to be called when this string is finalized.
+ * \param external_allocation_size The number of externally allocated
+ * bytes for peer. Used to inform the garbage collector.
+ * \param callback A callback to be called when this string is finalized.
*
* \return The String object if no error occurs. Otherwise returns
* an error handle.
*/
-DART_EXPORT Dart_Handle Dart_NewExternalUTF16String(const uint16_t* utf16_array,
- intptr_t length,
- void* peer,
- Dart_PeerFinalizer cback);
+DART_EXPORT Dart_Handle
+Dart_NewExternalUTF16String(const uint16_t* utf16_array,
+ intptr_t length,
+ void* peer,
+ intptr_t external_allocation_size,
+ Dart_WeakPersistentHandleFinalizer callback);
/**
* Gets the C string representation of a String.
diff --git a/runtime/include/dart_native_api.h b/runtime/include/dart_native_api.h
index 934ef3d..eea02fd 100644
--- a/runtime/include/dart_native_api.h
+++ b/runtime/include/dart_native_api.h
@@ -7,7 +7,7 @@
#ifndef RUNTIME_INCLUDE_DART_NATIVE_API_H_
#define RUNTIME_INCLUDE_DART_NATIVE_API_H_
-#include "dart_api.h"
+#include "dart_api.h" /* NOLINT */
/*
* ==========================================
@@ -33,7 +33,6 @@
Dart_CObject_kBool,
Dart_CObject_kInt32,
Dart_CObject_kInt64,
- Dart_CObject_kBigint,
Dart_CObject_kDouble,
Dart_CObject_kString,
Dart_CObject_kArray,
@@ -54,11 +53,6 @@
double as_double;
char* as_string;
struct {
- bool neg;
- intptr_t used;
- struct _Dart_CObject* digits;
- } as_bigint;
- struct {
Dart_Port id;
Dart_Port origin_id;
} as_send_port;
diff --git a/runtime/lib/bigint.dart b/runtime/lib/bigint.dart
deleted file mode 100644
index b6a9db3..0000000
--- a/runtime/lib/bigint.dart
+++ /dev/null
@@ -1,2134 +0,0 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// part of "core_patch.dart";
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
- * Copyright (c) 2003-2005 Tom Wu
- * Copyright (c) 2012 Adam Singer (adam@solvr.io)
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
- * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
- *
- * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
- * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
- * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
- * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
- * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * In addition, the following condition applies:
- *
- * All redistributions must retain an intact copy of this copyright notice
- * and disclaimer.
- */
-
-// A big integer number is represented by a sign, an array of 32-bit unsigned
-// integers in little endian format, and a number of used digits in that array.
-// The code makes sure that an even number of digits is always accessible and
-// meaningful, so that pairs of digits can be processed as 64-bit unsigned
-// numbers on a 64-bit platform. This requires the initialization of a leading
-// zero if the number of used digits is odd.
-class _Bigint extends _IntegerImplementation {
- // Bits per digit.
- static const int _DIGIT_BITS = 32;
- static const int _LOG2_DIGIT_BITS = 5;
- static const int _DIGIT_BASE = 1 << _DIGIT_BITS;
- static const int _DIGIT_MASK = (1 << _DIGIT_BITS) - 1;
-
- // Bits per half digit.
- static const int _DIGIT2_BITS = _DIGIT_BITS >> 1;
- static const int _DIGIT2_MASK = (1 << _DIGIT2_BITS) - 1;
-
- // Bits per 2 digits. Used to perform modulo 2^64 arithmetic.
- // Note: in --limit-ints-to-64-bits mode most arithmetic operations are
- // already modulo 2^64. Still, it is harmless to apply _TWO_DIGITS_MASK:
- // (1 << _TWO_DIGITS_BITS) is 0 (all bits are shifted out), so
- // _TWO_DIGITS_MASK is -1 (its bit pattern is 0xffffffffffffffff).
- static const int _TWO_DIGITS_BITS = _DIGIT_BITS << 1;
- static const int _TWO_DIGITS_MASK = (1 << _TWO_DIGITS_BITS) - 1;
-
- // Min and max of non bigint values.
- static const int _MIN_INT64 = (-1) << 63;
- static const int _MAX_INT64 = 0x7fffffffffffffff;
-
- // Bigint constant values.
- // Note: Not declared as final in order to satisfy optimizer, which expects
- // constants to be in canonical form (Smi).
- static _Bigint _MINUS_ONE = new _Bigint._fromInt(-1);
- static _Bigint _ZERO = new _Bigint._fromInt(0);
- static _Bigint _ONE = new _Bigint._fromInt(1);
-
- // Result cache for last _divRem call.
- static Uint32List _lastDividend_digits;
- static int _lastDividend_used;
- static Uint32List _lastDivisor_digits;
- static int _lastDivisor_used;
- static Uint32List _lastQuoRem_digits;
- static int _lastQuoRem_used;
- static int _lastRem_used;
- static int _lastRem_nsh;
-
- // Internal data structure.
- bool get _neg native "Bigint_getNeg";
- int get _used native "Bigint_getUsed";
- Uint32List get _digits native "Bigint_getDigits";
-
- // Factory returning an instance initialized with the given field values.
- // The 'digits' array is first clamped and 'used' is reduced accordingly.
- // A leading zero digit may be initialized to guarantee that digit pairs can
- // be processed as 64-bit values on 64-bit platforms.
- factory _Bigint(bool neg, int used, Uint32List digits)
- native "Bigint_allocate";
-
- // Factory returning an instance initialized to an integer value no larger
- // than a Mint.
- factory _Bigint._fromInt(int i) {
- assert(i is! _Bigint);
- var neg;
- var l, h;
- if (i < 0) {
- neg = true;
- if (i == _MIN_INT64) {
- l = 0;
- h = 0x80000000;
- } else {
- l = (-i) & _DIGIT_MASK;
- h = (-i) >> _DIGIT_BITS;
- }
- } else {
- neg = false;
- l = i & _DIGIT_MASK;
- h = i >> _DIGIT_BITS;
- }
- var digits = new Uint32List(2);
- digits[0] = l;
- digits[1] = h;
- return new _Bigint(neg, 2, digits);
- }
-
- // Allocate an array of the given length (+1 for at least one leading zero
- // digit if odd) and copy digits[from..to-1] starting at index 0, followed by
- // leading zero digits.
- static Uint32List _cloneDigits(
- Uint32List digits, int from, int to, int length) {
- length += length & 1; // Even number of digits.
- var r_digits = new Uint32List(length);
- var n = to - from;
- for (var i = 0; i < n; i++) {
- r_digits[i] = digits[from + i];
- }
- return r_digits;
- }
-
- // Return most compact integer (i.e. possibly Smi or Mint).
- int _toValidInt() {
- assert(_DIGIT_BITS == 32); // Otherwise this code needs to be revised.
- var used = _used;
- if (used == 0) return 0;
- var digits = _digits;
- if (used == 1) return _neg ? -digits[0] : digits[0];
- if (used > 2) return this;
- if (_neg) {
- if (digits[1] > 0x80000000) return this;
- if (digits[1] == 0x80000000) {
- if (digits[0] > 0) return this;
- return _MIN_INT64;
- }
- return -((digits[1] << _DIGIT_BITS) | digits[0]);
- }
- if (digits[1] >= 0x80000000) return this;
- return (digits[1] << _DIGIT_BITS) | digits[0];
- }
-
- // Conversion from int to bigint.
- _Bigint _toBigint() => this;
-
- // Return -this.
- _Bigint _negate() {
- var used = _used;
- if (used == 0) {
- return this;
- }
- return new _Bigint(!_neg, used, _digits);
- }
-
- // Return abs(this).
- _Bigint _abs() {
- var neg = _neg;
- if (!neg) {
- return this;
- }
- return new _Bigint(!neg, _used, _digits);
- }
-
- // Return the bit length of digit x.
- static int _nbits(int x) {
- var r = 1, t;
- if ((t = x >> 16) != 0) {
- x = t;
- r += 16;
- }
- if ((t = x >> 8) != 0) {
- x = t;
- r += 8;
- }
- if ((t = x >> 4) != 0) {
- x = t;
- r += 4;
- }
- if ((t = x >> 2) != 0) {
- x = t;
- r += 2;
- }
- if ((x >> 1) != 0) {
- r += 1;
- }
- return r;
- }
-
- // Return this << n*_DIGIT_BITS.
- _Bigint _dlShift(int n) {
- final used = _used;
- if (used == 0) {
- return _ZERO;
- }
- final r_used = used + n;
- final digits = _digits;
- final r_digits = new Uint32List(r_used + (r_used & 1));
- var i = used;
- while (--i >= 0) {
- r_digits[i + n] = digits[i];
- }
- return new _Bigint(_neg, r_used, r_digits);
- }
-
- // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n*_DIGIT_BITS.
- // Return r_used.
- static int _dlShiftDigits(
- Uint32List x_digits, int x_used, int n, Uint32List r_digits) {
- if (x_used == 0) {
- return 0;
- }
- if (n == 0 && identical(r_digits, x_digits)) {
- return x_used;
- }
- final r_used = x_used + n;
- assert(r_digits.length >= r_used + (r_used & 1));
- var i = x_used;
- while (--i >= 0) {
- r_digits[i + n] = x_digits[i];
- }
- i = n;
- while (--i >= 0) {
- r_digits[i] = 0;
- }
- if (r_used.isOdd) {
- r_digits[r_used] = 0;
- }
- return r_used;
- }
-
- // Return this >> n*_DIGIT_BITS.
- _Bigint _drShift(int n) {
- final used = _used;
- if (used == 0) {
- return _ZERO;
- }
- final r_used = used - n;
- if (r_used <= 0) {
- return _neg ? _MINUS_ONE : _ZERO;
- }
- final digits = _digits;
- final r_digits = new Uint32List(r_used + (r_used & 1));
- for (var i = n; i < used; i++) {
- r_digits[i - n] = digits[i];
- }
- final r = new _Bigint(_neg, r_used, r_digits);
- if (_neg) {
- // Round down if any bit was shifted out.
- for (var i = 0; i < n; i++) {
- if (digits[i] != 0) {
- return r._sub(_ONE);
- }
- }
- }
- return r;
- }
-
- // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n*_DIGIT_BITS.
- // Return r_used.
- static int _drShiftDigits(
- Uint32List x_digits, int x_used, int n, Uint32List r_digits) {
- final r_used = x_used - n;
- if (r_used <= 0) {
- return 0;
- }
- assert(r_digits.length >= r_used + (r_used & 1));
- for (var i = n; i < x_used; i++) {
- r_digits[i - n] = x_digits[i];
- }
- if (r_used.isOdd) {
- r_digits[r_used] = 0;
- }
- return r_used;
- }
-
- // r_digits[ds..x_used+ds] = x_digits[0..x_used-1] << (n % _DIGIT_BITS)
- // where ds = ceil(n / _DIGIT_BITS)
- // Doesn't clear digits below ds.
- static void _lsh(
- Uint32List x_digits, int x_used, int n, Uint32List r_digits) {
- final ds = n ~/ _DIGIT_BITS;
- final bs = n % _DIGIT_BITS;
- final cbs = _DIGIT_BITS - bs;
- final bm = (1 << cbs) - 1;
- var c = 0;
- var i = x_used;
- while (--i >= 0) {
- final d = x_digits[i];
- r_digits[i + ds + 1] = (d >> cbs) | c;
- c = (d & bm) << bs;
- }
- r_digits[ds] = c;
- }
-
- // Return this << n.
- _Bigint _lShift(int n) {
- final ds = n ~/ _DIGIT_BITS;
- final bs = n % _DIGIT_BITS;
- if (bs == 0) {
- return _dlShift(ds);
- }
- var r_used = _used + ds + 1;
- var r_digits = new Uint32List(r_used + 2 - (r_used & 1)); // for 64-bit.
- _lsh(_digits, _used, n, r_digits);
- return new _Bigint(_neg, r_used, r_digits);
- }
-
- // r_digits[0..r_used-1] = x_digits[0..x_used-1] << n.
- // Return r_used.
- static int _lShiftDigits(
- Uint32List x_digits, int x_used, int n, Uint32List r_digits) {
- final ds = n ~/ _DIGIT_BITS;
- final bs = n % _DIGIT_BITS;
- if (bs == 0) {
- return _dlShiftDigits(x_digits, x_used, ds, r_digits);
- }
- var r_used = x_used + ds + 1;
- assert(r_digits.length >= r_used + 2 - (r_used & 1)); // for 64-bit.
- _lsh(x_digits, x_used, n, r_digits);
- var i = ds;
- while (--i >= 0) {
- r_digits[i] = 0;
- }
- if (r_digits[r_used - 1] == 0) {
- r_used--; // Clamp result.
- } else if (r_used.isOdd) {
- r_digits[r_used] = 0;
- }
- return r_used;
- }
-
- // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n.
- static void _rsh(
- Uint32List x_digits, int x_used, int n, Uint32List r_digits) {
- final ds = n ~/ _DIGIT_BITS;
- final bs = n % _DIGIT_BITS;
- final cbs = _DIGIT_BITS - bs;
- final bm = (1 << bs) - 1;
- var c = x_digits[ds] >> bs;
- final last = x_used - ds - 1;
- for (var i = 0; i < last; i++) {
- final d = x_digits[i + ds + 1];
- r_digits[i] = ((d & bm) << cbs) | c;
- c = d >> bs;
- }
- r_digits[last] = c;
- }
-
- // Return this >> n.
- _Bigint _rShift(int n) {
- final ds = n ~/ _DIGIT_BITS;
- final bs = n % _DIGIT_BITS;
- if (bs == 0) {
- return _drShift(ds);
- }
- final used = _used;
- final r_used = used - ds;
- if (r_used <= 0) {
- return _neg ? _MINUS_ONE : _ZERO;
- }
- final digits = _digits;
- final r_digits = new Uint32List(r_used + (r_used & 1));
- _rsh(digits, used, n, r_digits);
- final r = new _Bigint(_neg, r_used, r_digits);
- if (_neg) {
- // Round down if any bit was shifted out.
- if ((digits[ds] & ((1 << bs) - 1)) != 0) {
- return r._sub(_ONE);
- }
- for (var i = 0; i < ds; i++) {
- if (digits[i] != 0) {
- return r._sub(_ONE);
- }
- }
- }
- return r;
- }
-
- // r_digits[0..r_used-1] = x_digits[0..x_used-1] >> n.
- // Return r_used.
- static int _rShiftDigits(
- Uint32List x_digits, int x_used, int n, Uint32List r_digits) {
- final ds = n ~/ _DIGIT_BITS;
- final bs = n % _DIGIT_BITS;
- if (bs == 0) {
- return _drShiftDigits(x_digits, x_used, ds, r_digits);
- }
- var r_used = x_used - ds;
- if (r_used <= 0) {
- return 0;
- }
- assert(r_digits.length >= r_used + (r_used & 1));
- _rsh(x_digits, x_used, n, r_digits);
- if (r_digits[r_used - 1] == 0) {
- r_used--; // Clamp result.
- } else if (r_used.isOdd) {
- r_digits[r_used] = 0;
- }
- return r_used;
- }
-
- // Return 0 if abs(this) == abs(a).
- // Return a positive number if abs(this) > abs(a).
- // Return a negative number if abs(this) < abs(a).
- int _absCompare(_Bigint a) {
- var r = _used - a._used;
- if (r == 0) {
- var i = _used;
- var digits = _digits;
- var a_digits = a._digits;
- while (--i >= 0 && (r = digits[i] - a_digits[i]) == 0);
- }
- return r;
- }
-
- // Return 0 if this == a.
- // Return a positive number if this > a.
- // Return a negative number if this < a.
- int _compare(_Bigint a) {
- if (_neg == a._neg) {
- var r = _absCompare(a);
- return _neg ? -r : r;
- }
- return _neg ? -1 : 1;
- }
-
- // Compare digits[0..used-1] with a_digits[0..a_used-1].
- // Return 0 if equal.
- // Return a positive number if larger.
- // Return a negative number if smaller.
- static int _compareDigits(
- Uint32List digits, int used, Uint32List a_digits, int a_used) {
- var r = used - a_used;
- if (r == 0) {
- var i = a_used;
- while (--i >= 0 && (r = digits[i] - a_digits[i]) == 0);
- }
- return r;
- }
-
- // r_digits[0..used] = digits[0..used-1] + a_digits[0..a_used-1].
- // used >= a_used > 0.
- // Note: Intrinsics on 64-bit platforms process digit pairs at even indices.
- static void _absAdd(Uint32List digits, int used, Uint32List a_digits,
- int a_used, Uint32List r_digits) {
- assert(used >= a_used && a_used > 0);
- // Verify that digit pairs are accessible for 64-bit processing.
- assert(digits.length > ((used - 1) | 1));
- assert(a_digits.length > ((a_used - 1) | 1));
- assert(r_digits.length > (used | 1));
- var c = 0;
- for (var i = 0; i < a_used; i++) {
- c += digits[i] + a_digits[i];
- r_digits[i] = c & _DIGIT_MASK;
- c >>= _DIGIT_BITS;
- }
- for (var i = a_used; i < used; i++) {
- c += digits[i];
- r_digits[i] = c & _DIGIT_MASK;
- c >>= _DIGIT_BITS;
- }
- r_digits[used] = c;
- }
-
- // r_digits[0..used-1] = digits[0..used-1] - a_digits[0..a_used-1].
- // used >= a_used > 0.
- // Note: Intrinsics on 64-bit platforms process digit pairs at even indices.
- static void _absSub(Uint32List digits, int used, Uint32List a_digits,
- int a_used, Uint32List r_digits) {
- assert(used >= a_used && a_used > 0);
- // Verify that digit pairs are accessible for 64-bit processing.
- assert(digits.length > ((used - 1) | 1));
- assert(a_digits.length > ((a_used - 1) | 1));
- assert(r_digits.length > ((used - 1) | 1));
- var c = 0;
- for (var i = 0; i < a_used; i++) {
- c += digits[i] - a_digits[i];
- r_digits[i] = c & _DIGIT_MASK;
- c >>= _DIGIT_BITS;
- }
- for (var i = a_used; i < used; i++) {
- c += digits[i];
- r_digits[i] = c & _DIGIT_MASK;
- c >>= _DIGIT_BITS;
- }
- }
-
- // Return abs(this) + abs(a) with sign set according to neg.
- _Bigint _absAddSetSign(_Bigint a, bool neg) {
- var used = _used;
- var a_used = a._used;
- if (used < a_used) {
- return a._absAddSetSign(this, neg);
- }
- if (used == 0) {
- assert(!neg);
- return _ZERO;
- }
- if (a_used == 0) {
- return _neg == neg ? this : this._negate();
- }
- var r_used = used + 1;
- var r_digits = new Uint32List(r_used + (r_used & 1));
- _absAdd(_digits, used, a._digits, a_used, r_digits);
- return new _Bigint(neg, r_used, r_digits);
- }
-
- // Return abs(this) - abs(a) with sign set according to neg.
- // Requirement: abs(this) >= abs(a).
- _Bigint _absSubSetSign(_Bigint a, bool neg) {
- assert(_absCompare(a) >= 0);
- var used = _used;
- if (used == 0) {
- assert(!neg);
- return _ZERO;
- }
- var a_used = a._used;
- if (a_used == 0) {
- return _neg == neg ? this : this._negate();
- }
- var r_digits = new Uint32List(used + (used & 1));
- _absSub(_digits, used, a._digits, a_used, r_digits);
- return new _Bigint(neg, used, r_digits);
- }
-
- // Return abs(this) & abs(a) with sign set according to neg.
- _Bigint _absAndSetSign(_Bigint a, bool neg) {
- var r_used = (_used < a._used) ? _used : a._used;
- var digits = _digits;
- var a_digits = a._digits;
- var r_digits = new Uint32List(r_used + (r_used & 1));
- for (var i = 0; i < r_used; i++) {
- r_digits[i] = digits[i] & a_digits[i];
- }
- return new _Bigint(neg, r_used, r_digits);
- }
-
- // Return abs(this) &~ abs(a) with sign set according to neg.
- _Bigint _absAndNotSetSign(_Bigint a, bool neg) {
- var r_used = _used;
- var digits = _digits;
- var a_digits = a._digits;
- var r_digits = new Uint32List(r_used + (r_used & 1));
- var m = (r_used < a._used) ? r_used : a._used;
- for (var i = 0; i < m; i++) {
- r_digits[i] = digits[i] & ~a_digits[i];
- }
- for (var i = m; i < r_used; i++) {
- r_digits[i] = digits[i];
- }
- return new _Bigint(neg, r_used, r_digits);
- }
-
- // Return abs(this) | abs(a) with sign set according to neg.
- _Bigint _absOrSetSign(_Bigint a, bool neg) {
- var used = _used;
- var a_used = a._used;
- var r_used = (used > a_used) ? used : a_used;
- var digits = _digits;
- var a_digits = a._digits;
- var r_digits = new Uint32List(r_used + (r_used & 1));
- var l, m;
- if (used < a_used) {
- l = a;
- m = used;
- } else {
- l = this;
- m = a_used;
- }
- for (var i = 0; i < m; i++) {
- r_digits[i] = digits[i] | a_digits[i];
- }
- var l_digits = l._digits;
- for (var i = m; i < r_used; i++) {
- r_digits[i] = l_digits[i];
- }
- return new _Bigint(neg, r_used, r_digits);
- }
-
- // Return abs(this) ^ abs(a) with sign set according to neg.
- _Bigint _absXorSetSign(_Bigint a, bool neg) {
- var used = _used;
- var a_used = a._used;
- var r_used = (used > a_used) ? used : a_used;
- var digits = _digits;
- var a_digits = a._digits;
- var r_digits = new Uint32List(r_used + (r_used & 1));
- var l, m;
- if (used < a_used) {
- l = a;
- m = used;
- } else {
- l = this;
- m = a_used;
- }
- for (var i = 0; i < m; i++) {
- r_digits[i] = digits[i] ^ a_digits[i];
- }
- var l_digits = l._digits;
- for (var i = m; i < r_used; i++) {
- r_digits[i] = l_digits[i];
- }
- return new _Bigint(neg, r_used, r_digits);
- }
-
- // Return this & a.
- _Bigint _and(_Bigint a) {
- if (_neg == a._neg) {
- if (_neg) {
- // (-this) & (-a) == ~(this-1) & ~(a-1)
- // == ~((this-1) | (a-1))
- // == -(((this-1) | (a-1)) + 1)
- _Bigint t1 = _absSubSetSign(_ONE, true);
- _Bigint a1 = a._absSubSetSign(_ONE, true);
- // Result cannot be zero if this and a are negative.
- return t1._absOrSetSign(a1, true)._absAddSetSign(_ONE, true);
- }
- return _absAndSetSign(a, false);
- }
- // _neg != a._neg
- var p, n;
- if (_neg) {
- p = a;
- n = this;
- } else {
- // & is symmetric.
- p = this;
- n = a;
- }
- // p & (-n) == p & ~(n-1) == p &~ (n-1)
- _Bigint n1 = n._absSubSetSign(_ONE, false);
- return p._absAndNotSetSign(n1, false);
- }
-
- // Return this &~ a.
- _Bigint _andNot(_Bigint a) {
- if (_neg == a._neg) {
- if (_neg) {
- // (-this) &~ (-a) == ~(this-1) &~ ~(a-1)
- // == ~(this-1) & (a-1)
- // == (a-1) &~ (this-1)
- _Bigint t1 = _absSubSetSign(_ONE, true);
- _Bigint a1 = a._absSubSetSign(_ONE, true);
- return a1._absAndNotSetSign(t1, false);
- }
- return _absAndNotSetSign(a, false);
- }
- if (_neg) {
- // (-this) &~ a == ~(this-1) &~ a
- // == ~(this-1) & ~a
- // == ~((this-1) | a)
- // == -(((this-1) | a) + 1)
- _Bigint t1 = _absSubSetSign(_ONE, true);
- // Result cannot be zero if this is negative and a is positive.
- return t1._absOrSetSign(a, true)._absAddSetSign(_ONE, true);
- }
- // this &~ (-a) == this &~ ~(a-1) == this & (a-1)
- _Bigint a1 = a._absSubSetSign(_ONE, true);
- return _absAndSetSign(a1, false);
- }
-
- // Return this | a.
- _Bigint _or(_Bigint a) {
- if (_neg == a._neg) {
- if (_neg) {
- // (-this) | (-a) == ~(this-1) | ~(a-1)
- // == ~((this-1) & (a-1))
- // == -(((this-1) & (a-1)) + 1)
- _Bigint t1 = _absSubSetSign(_ONE, true);
- _Bigint a1 = a._absSubSetSign(_ONE, true);
- // Result cannot be zero if this and a are negative.
- return t1._absAndSetSign(a1, true)._absAddSetSign(_ONE, true);
- }
- return _absOrSetSign(a, false);
- }
- // _neg != a._neg
- var p, n;
- if (_neg) {
- p = a;
- n = this;
- } else {
- // | is symmetric.
- p = this;
- n = a;
- }
- // p | (-n) == p | ~(n-1) == ~((n-1) &~ p) == -(~((n-1) &~ p) + 1)
- _Bigint n1 = n._absSubSetSign(_ONE, true);
- // Result cannot be zero if only one of this or a is negative.
- return n1._absAndNotSetSign(p, true)._absAddSetSign(_ONE, true);
- }
-
- // Return this ^ a.
- _Bigint _xor(_Bigint a) {
- if (_neg == a._neg) {
- if (_neg) {
- // (-this) ^ (-a) == ~(this-1) ^ ~(a-1) == (this-1) ^ (a-1)
- _Bigint t1 = _absSubSetSign(_ONE, true);
- _Bigint a1 = a._absSubSetSign(_ONE, true);
- return t1._absXorSetSign(a1, false);
- }
- return _absXorSetSign(a, false);
- }
- // _neg != a._neg
- var p, n;
- if (_neg) {
- p = a;
- n = this;
- } else {
- // ^ is symmetric.
- p = this;
- n = a;
- }
- // p ^ (-n) == p ^ ~(n-1) == ~(p ^ (n-1)) == -((p ^ (n-1)) + 1)
- _Bigint n1 = n._absSubSetSign(_ONE, true);
- // Result cannot be zero if only one of this or a is negative.
- return p._absXorSetSign(n1, true)._absAddSetSign(_ONE, true);
- }
-
- // Return ~this.
- _Bigint _not() {
- if (_neg) {
- // ~(-this) == ~(~(this-1)) == this-1
- return _absSubSetSign(_ONE, false);
- }
- // ~this == -this-1 == -(this+1)
- // Result cannot be zero if this is positive.
- return _absAddSetSign(_ONE, true);
- }
-
- // Return this + a.
- _Bigint _add(_Bigint a) {
- var neg = _neg;
- if (neg == a._neg) {
- // this + a == this + a
- // (-this) + (-a) == -(this + a)
- return _absAddSetSign(a, neg);
- }
- // this + (-a) == this - a == -(this - a)
- // (-this) + a == a - this == -(this - a)
- if (_absCompare(a) >= 0) {
- return _absSubSetSign(a, neg);
- }
- return a._absSubSetSign(this, !neg);
- }
-
- // Return this - a.
- _Bigint _sub(_Bigint a) {
- var neg = _neg;
- if (neg != a._neg) {
- // this - (-a) == this + a
- // (-this) - a == -(this + a)
- return _absAddSetSign(a, neg);
- }
- // this - a == this - a == -(this - a)
- // (-this) - (-a) == a - this == -(this - a)
- if (_absCompare(a) >= 0) {
- return _absSubSetSign(a, neg);
- }
- return a._absSubSetSign(this, !neg);
- }
-
- // Multiply and accumulate.
- // Input:
- // x_digits[xi]: multiplier digit x.
- // m_digits[i..i+n-1]: multiplicand digits.
- // a_digits[j..j+n-1]: accumulator digits.
- // Operation:
- // a_digits[j..j+n] += x_digits[xi]*m_digits[i..i+n-1].
- // return 1.
- // Note: Intrinsics on 64-bit platforms process digit pairs at even indices
- // and return 2.
- static int _mulAdd(Uint32List x_digits, int xi, Uint32List m_digits, int i,
- Uint32List a_digits, int j, int n) {
- // Verify that digit pairs are accessible for 64-bit processing.
- assert(x_digits.length > (xi | 1));
- assert(m_digits.length > ((i + n - 1) | 1));
- assert(a_digits.length > ((j + n) | 1));
- int x = x_digits[xi];
- if (x == 0) {
- // No-op if x is 0.
- return 1;
- }
- int c = 0;
- int xl = x & _DIGIT2_MASK;
- int xh = x >> _DIGIT2_BITS;
- while (--n >= 0) {
- int l = m_digits[i] & _DIGIT2_MASK;
- int h = m_digits[i++] >> _DIGIT2_BITS;
- int m = xh * l + h * xl;
- l = xl * l + ((m & _DIGIT2_MASK) << _DIGIT2_BITS) + a_digits[j] + c;
- c = (l >> _DIGIT_BITS) + (m >> _DIGIT2_BITS) + xh * h;
- a_digits[j++] = l & _DIGIT_MASK;
- }
- while (c != 0) {
- int l = a_digits[j] + c;
- c = l >> _DIGIT_BITS;
- a_digits[j++] = l & _DIGIT_MASK;
- }
- return 1;
- }
-
- // Square and accumulate.
- // Input:
- // x_digits[i..used-1]: digits of operand being squared.
- // a_digits[2*i..i+used-1]: accumulator digits.
- // Operation:
- // a_digits[2*i..i+used-1] += x_digits[i]*x_digits[i] +
- // 2*x_digits[i]*x_digits[i+1..used-1].
- // return 1.
- // Note: Intrinsics on 64-bit platforms process digit pairs at even indices
- // and return 2.
- static int _sqrAdd(
- Uint32List x_digits, int i, Uint32List a_digits, int used) {
- // Verify that digit pairs are accessible for 64-bit processing.
- assert(x_digits.length > ((used - 1) | 1));
- assert(a_digits.length > ((i + used - 1) | 1));
- int x = x_digits[i];
- if (x == 0) return 1;
- int j = 2 * i;
- int c = 0;
- int xl = x & _DIGIT2_MASK;
- int xh = x >> _DIGIT2_BITS;
- int m = 2 * xh * xl;
- int l = xl * xl + ((m & _DIGIT2_MASK) << _DIGIT2_BITS) + a_digits[j];
- c = (l >> _DIGIT_BITS) + (m >> _DIGIT2_BITS) + xh * xh;
- a_digits[j] = l & _DIGIT_MASK;
- x <<= 1;
- xl = x & _DIGIT2_MASK;
- xh = x >> _DIGIT2_BITS;
- int n = used - i - 1;
- int k = i + 1;
- j++;
- while (--n >= 0) {
- int l = x_digits[k] & _DIGIT2_MASK;
- int h = x_digits[k++] >> _DIGIT2_BITS;
- int m = xh * l + h * xl;
- l = xl * l + ((m & _DIGIT2_MASK) << _DIGIT2_BITS) + a_digits[j] + c;
- c = (l >> _DIGIT_BITS) + (m >> _DIGIT2_BITS) + xh * h;
- a_digits[j++] = l & _DIGIT_MASK;
- }
- c += a_digits[i + used];
- if (c >= _DIGIT_BASE) {
- a_digits[i + used] = c - _DIGIT_BASE;
- a_digits[i + used + 1] = 1;
- } else {
- a_digits[i + used] = c;
- }
- return 1;
- }
-
- // Return this * a.
- _Bigint _mul(_Bigint a) {
- // TODO(regis): Use karatsuba multiplication when appropriate.
- var used = _used;
- var a_used = a._used;
- if (used == 0 || a_used == 0) {
- return _ZERO;
- }
- var r_used = used + a_used;
- var digits = _digits;
- var a_digits = a._digits;
- var r_digits = new Uint32List(r_used + (r_used & 1));
- var i = 0;
- while (i < a_used) {
- i += _mulAdd(a_digits, i, digits, 0, r_digits, i, used);
- }
- return new _Bigint(_neg != a._neg, r_used, r_digits);
- }
-
- // r_digits[0..r_used-1] = x_digits[0..x_used-1]*a_digits[0..a_used-1].
- // Return r_used = x_used + a_used.
- static int _mulDigits(Uint32List x_digits, int x_used, Uint32List a_digits,
- int a_used, Uint32List r_digits) {
- var r_used = x_used + a_used;
- var i = r_used + (r_used & 1);
- assert(r_digits.length >= i);
- while (--i >= 0) {
- r_digits[i] = 0;
- }
- i = 0;
- while (i < a_used) {
- i += _mulAdd(a_digits, i, x_digits, 0, r_digits, i, x_used);
- }
- return r_used;
- }
-
- // Return this^2.
- _Bigint _sqr() {
- var used = _used;
- if (used == 0) {
- return _ZERO;
- }
- var r_used = 2 * used;
- var digits = _digits;
- var r_digits = new Uint32List(r_used);
- // Since r_used is even, no need for a leading zero for 64-bit processing.
- var i = 0;
- while (i < used - 1) {
- i += _sqrAdd(digits, i, r_digits, used);
- }
- // The last step is already done if digit pairs were processed above.
- if (i < used) {
- _mulAdd(digits, i, digits, i, r_digits, 2 * i, 1);
- }
- return new _Bigint(false, r_used, r_digits);
- }
-
- // r_digits[0..r_used-1] = x_digits[0..x_used-1]*x_digits[0..x_used-1].
- // Return r_used = 2*x_used.
- static int _sqrDigits(Uint32List x_digits, int x_used, Uint32List r_digits) {
- var r_used = 2 * x_used;
- assert(r_digits.length >= r_used);
- // Since r_used is even, no need for a leading zero for 64-bit processing.
- var i = r_used;
- while (--i >= 0) {
- r_digits[i] = 0;
- }
- i = 0;
- while (i < x_used - 1) {
- i += _sqrAdd(x_digits, i, r_digits, x_used);
- }
- // The last step is already done if digit pairs were processed above.
- if (i < x_used) {
- _mulAdd(x_digits, i, x_digits, i, r_digits, 2 * i, 1);
- }
- return r_used;
- }
-
- // Indices of the arguments of _estQuotientDigit.
- // For 64-bit processing by intrinsics on 64-bit platforms, the top digit pair
- // of divisor y is provided in the args array, and a 64-bit estimated quotient
- // is returned. However, on 32-bit platforms, the low 32-bit digit is ignored
- // and only one 32-bit digit is returned as the estimated quotient.
- static const int _YT_LO = 0; // Low digit of top digit pair of y, for 64-bit.
- static const int _YT = 1; // Top digit of divisor y.
- static const int _QD = 2; // Estimated quotient.
- static const int _QD_HI = 3; // High digit of estimated quotient, for 64-bit.
-
- // Operation:
- // Estimate args[_QD] = digits[i-1..i] ~/ args[_YT]
- // return 1
- // Note: Intrinsics on 64-bit platforms process a digit pair (i always odd):
- // Estimate args[_QD.._QD_HI] = digits[i-3..i] ~/ args[_YT_LO.._YT]
- // return 2
- static int _estQuotientDigit(Uint32List args, Uint32List digits, int i) {
- // Verify that digit pairs are accessible for 64-bit processing.
- assert(digits.length >= 4);
- if (digits[i] == args[_YT]) {
- args[_QD] = _DIGIT_MASK;
- } else {
- // Chop off one bit, since a Mint cannot hold 2 DIGITs.
- var qd = ((digits[i] << (_DIGIT_BITS - 1)) | (digits[i - 1] >> 1)) ~/
- (args[_YT] >> 1);
- if (qd > _DIGIT_MASK) {
- args[_QD] = _DIGIT_MASK;
- } else {
- args[_QD] = qd;
- }
- }
- return 1;
- }
-
- // Return trunc(this / a), a != 0.
- _Bigint _div(_Bigint a) {
- assert(a._used > 0);
- if (_used < a._used) {
- return _ZERO;
- }
- _divRem(a);
- // Return quotient, i.e.
- // _lastQuoRem_digits[_lastRem_used.._lastQuoRem_used-1] with proper sign.
- var lastQuo_used = _lastQuoRem_used - _lastRem_used;
- var quo_digits = _cloneDigits(
- _lastQuoRem_digits, _lastRem_used, _lastQuoRem_used, lastQuo_used);
- var quo = new _Bigint(false, lastQuo_used, quo_digits);
- if ((_neg != a._neg) && (quo._used > 0)) {
- quo = quo._negate();
- }
- return quo;
- }
-
- // Return this - a * trunc(this / a), a != 0.
- _Bigint _rem(_Bigint a) {
- assert(a._used > 0);
- if (_used < a._used) {
- return this;
- }
- _divRem(a);
- // Return remainder, i.e.
- // denormalized _lastQuoRem_digits[0.._lastRem_used-1] with proper sign.
- var rem_digits =
- _cloneDigits(_lastQuoRem_digits, 0, _lastRem_used, _lastRem_used);
- var rem = new _Bigint(false, _lastRem_used, rem_digits);
- if (_lastRem_nsh > 0) {
- rem = rem._rShift(_lastRem_nsh); // Denormalize remainder.
- }
- if (_neg && (rem._used > 0)) {
- rem = rem._negate();
- }
- return rem;
- }
-
- // Cache concatenated positive quotient and normalized positive remainder.
- void _divRem(_Bigint a) {
- // Check if result is already cached (identical on Bigint is too expensive).
- if ((this._used == _lastDividend_used) &&
- (a._used == _lastDivisor_used) &&
- identical(this._digits, _lastDividend_digits) &&
- identical(a._digits, _lastDivisor_digits)) {
- return;
- }
- var nsh = _DIGIT_BITS - _nbits(a._digits[a._used - 1]);
- // For 64-bit processing, make sure y has an even number of digits.
- if (a._used.isOdd) {
- nsh += _DIGIT_BITS;
- }
- // Concatenated positive quotient and normalized positive remainder.
- var r_digits;
- var r_used;
- // Normalized positive divisor.
- var y_digits;
- var y_used;
- if (nsh > 0) {
- y_digits = new Uint32List(a._used + 5); // +5 for norm. and 64-bit.
- y_used = _lShiftDigits(a._digits, a._used, nsh, y_digits);
- r_digits = new Uint32List(_used + 5); // +5 for normalization and 64-bit.
- r_used = _lShiftDigits(_digits, _used, nsh, r_digits);
- } else {
- y_digits = a._digits;
- y_used = a._used;
- r_digits = _cloneDigits(_digits, 0, _used, _used + 2);
- r_used = _used;
- }
- Uint32List yt_qd = new Uint32List(4);
- yt_qd[_YT_LO] = y_digits[y_used - 2];
- yt_qd[_YT] = y_digits[y_used - 1];
- // For 64-bit processing, make sure y_used, i, and j are even.
- assert(y_used.isEven);
- var i = r_used + (r_used & 1);
- var j = i - y_used;
- // t_digits is a temporary array of i digits.
- var t_digits = new Uint32List(i);
- var t_used = _dlShiftDigits(y_digits, y_used, j, t_digits);
- // Explicit first division step in case normalized dividend is larger or
- // equal to shifted normalized divisor.
- if (_compareDigits(r_digits, r_used, t_digits, t_used) >= 0) {
- assert(i == r_used);
- r_digits[r_used++] = 1; // Quotient = 1.
- // Subtract divisor from remainder.
- _absSub(r_digits, r_used, t_digits, t_used, r_digits);
- } else {
- // Account for possible carry in _mulAdd step.
- r_digits[r_used++] = 0;
- }
- r_digits[r_used] = 0; // Leading zero for 64-bit processing.
- // Negate y so we can later use _mulAdd instead of non-existent _mulSub.
- var ny_digits = new Uint32List(y_used + 2);
- ny_digits[y_used] = 1;
- _absSub(ny_digits, y_used + 1, y_digits, y_used, ny_digits);
- // ny_digits is read-only and has y_used digits (possibly including several
- // leading zeros) plus a leading zero for 64-bit processing.
- // r_digits is modified during iteration.
- // r_digits[0..y_used-1] is the current remainder.
- // r_digits[y_used..r_used-1] is the current quotient.
- --i;
- while (j > 0) {
- var d0 = _estQuotientDigit(yt_qd, r_digits, i);
- j -= d0;
- var d1 = _mulAdd(yt_qd, _QD, ny_digits, 0, r_digits, j, y_used);
- // _estQuotientDigit and _mulAdd must agree on the number of digits to
- // process.
- assert(d0 == d1);
- if (d0 == 1) {
- if (r_digits[i] < yt_qd[_QD]) {
- var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits);
- _absSub(r_digits, r_used, t_digits, t_used, r_digits);
- while (r_digits[i] < --yt_qd[_QD]) {
- _absSub(r_digits, r_used, t_digits, t_used, r_digits);
- }
- }
- } else {
- assert(d0 == 2);
- assert(r_digits[i] <= yt_qd[_QD_HI]);
- if ((r_digits[i] < yt_qd[_QD_HI]) || (r_digits[i - 1] < yt_qd[_QD])) {
- var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits);
- _absSub(r_digits, r_used, t_digits, t_used, r_digits);
- if (yt_qd[_QD] == 0) {
- --yt_qd[_QD_HI];
- }
- --yt_qd[_QD];
- assert(r_digits[i] <= yt_qd[_QD_HI]);
- while (
- (r_digits[i] < yt_qd[_QD_HI]) || (r_digits[i - 1] < yt_qd[_QD])) {
- _absSub(r_digits, r_used, t_digits, t_used, r_digits);
- if (yt_qd[_QD] == 0) {
- --yt_qd[_QD_HI];
- }
- --yt_qd[_QD];
- assert(r_digits[i] <= yt_qd[_QD_HI]);
- }
- }
- }
- i -= d0;
- }
- // Cache result.
- _lastDividend_digits = _digits;
- _lastDividend_used = _used;
- _lastDivisor_digits = a._digits;
- _lastDivisor_used = a._used;
- _lastQuoRem_digits = r_digits;
- _lastQuoRem_used = r_used;
- _lastRem_used = y_used;
- _lastRem_nsh = nsh;
- }
-
- // Customized version of _rem() minimizing allocations for use in reduction.
- // Input:
- // x_digits[0..x_used-1]: positive dividend.
- // y_digits[0..y_used-1]: normalized positive divisor.
- // ny_digits[0..y_used-1]: negated y_digits.
- // nsh: normalization shift amount.
- // yt_qd: top y digit(s) and place holder for estimated quotient digit(s).
- // t_digits: temp array of 2*y_used digits.
- // r_digits: result digits array large enough to temporarily hold
- // concatenated quotient and normalized remainder.
- // Output:
- // r_digits[0..r_used-1]: positive remainder.
- // Returns r_used.
- static int _remDigits(
- Uint32List x_digits,
- int x_used,
- Uint32List y_digits,
- int y_used,
- Uint32List ny_digits,
- int nsh,
- Uint32List yt_qd,
- Uint32List t_digits,
- Uint32List r_digits) {
- // Initialize r_digits to normalized positive dividend.
- var r_used = _lShiftDigits(x_digits, x_used, nsh, r_digits);
- // For 64-bit processing, make sure y_used, i, and j are even.
- assert(y_used.isEven);
- var i = r_used + (r_used & 1);
- var j = i - y_used;
- var t_used = _dlShiftDigits(y_digits, y_used, j, t_digits);
- // Explicit first division step in case normalized dividend is larger or
- // equal to shifted normalized divisor.
- if (_compareDigits(r_digits, r_used, t_digits, t_used) >= 0) {
- assert(i == r_used);
- r_digits[r_used++] = 1; // Quotient = 1.
- // Subtract divisor from remainder.
- _absSub(r_digits, r_used, t_digits, t_used, r_digits);
- } else {
- // Account for possible carry in _mulAdd step.
- r_digits[r_used++] = 0;
- }
- r_digits[r_used] = 0; // Leading zero for 64-bit processing.
- // Negated y_digits passed in ny_digits allow the use of _mulAdd instead of
- // unimplemented _mulSub.
- // ny_digits is read-only and has y_used digits (possibly including several
- // leading zeros) plus a leading zero for 64-bit processing.
- // r_digits is modified during iteration.
- // r_digits[0..y_used-1] is the current remainder.
- // r_digits[y_used..r_used-1] is the current quotient.
- --i;
- while (j > 0) {
- var d0 = _estQuotientDigit(yt_qd, r_digits, i);
- j -= d0;
- var d1 = _mulAdd(yt_qd, _QD, ny_digits, 0, r_digits, j, y_used);
- // _estQuotientDigit and _mulAdd must agree on the number of digits to
- // process.
- assert(d0 == d1);
- if (d0 == 1) {
- if (r_digits[i] < yt_qd[_QD]) {
- var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits);
- _absSub(r_digits, r_used, t_digits, t_used, r_digits);
- while (r_digits[i] < --yt_qd[_QD]) {
- _absSub(r_digits, r_used, t_digits, t_used, r_digits);
- }
- }
- } else {
- assert(d0 == 2);
- assert(r_digits[i] <= yt_qd[_QD_HI]);
- if ((r_digits[i] < yt_qd[_QD_HI]) || (r_digits[i - 1] < yt_qd[_QD])) {
- var t_used = _dlShiftDigits(ny_digits, y_used, j, t_digits);
- _absSub(r_digits, r_used, t_digits, t_used, r_digits);
- if (yt_qd[_QD] == 0) {
- --yt_qd[_QD_HI];
- }
- --yt_qd[_QD];
- assert(r_digits[i] <= yt_qd[_QD_HI]);
- while (
- (r_digits[i] < yt_qd[_QD_HI]) || (r_digits[i - 1] < yt_qd[_QD])) {
- _absSub(r_digits, r_used, t_digits, t_used, r_digits);
- if (yt_qd[_QD] == 0) {
- --yt_qd[_QD_HI];
- }
- --yt_qd[_QD];
- assert(r_digits[i] <= yt_qd[_QD_HI]);
- }
- }
- }
- i -= d0;
- }
- // Return remainder, i.e. denormalized r_digits[0..y_used-1].
- r_used = y_used;
- if (nsh > 0) {
- // Denormalize remainder.
- r_used = _rShiftDigits(r_digits, r_used, nsh, r_digits);
- }
- return r_used;
- }
-
- int get hashCode => this;
- int get _identityHashCode => this;
-
- int operator ~() {
- return _not()._toValidInt();
- }
-
- int get bitLength {
- if (_used == 0) return 0;
- if (_neg) return (~this).bitLength;
- return _DIGIT_BITS * (_used - 1) + _nbits(_digits[_used - 1]);
- }
-
- // This method must support smi._toBigint()._shrFromInt(int).
- int _shrFromInt(int other) {
- if (_used == 0) return other; // Shift amount is zero.
- if (_neg) throw new RangeError.range(this, 0, null);
- assert(_DIGIT_BITS == 32); // Otherwise this code needs to be revised.
- var shift;
- if ((_used > 2) || ((_used == 2) && (_digits[1] > 0x10000000))) {
- if (other < 0) {
- return -1;
- } else {
- return 0;
- }
- } else {
- shift = ((_used == 2) ? (_digits[1] << _DIGIT_BITS) : 0) + _digits[0];
- }
- return other._toBigint()._rShift(shift)._toValidInt();
- }
-
- // This method must support smi._toBigint()._shlFromInt(int).
- // An out of memory exception is thrown if the result cannot be allocated.
- int _shlFromInt(int other) {
- if (_used == 0) return other; // Shift amount is zero.
- if (_neg) throw new RangeError.range(this, 0, null);
- assert(_DIGIT_BITS == 32); // Otherwise this code needs to be revised.
- var shift;
- if (_used > 2 || (_used == 2 && _digits[1] > 0x10000000)) {
- if (other == 0) return 0; // Shifted value is zero.
- throw new OutOfMemoryError();
- } else {
- shift = ((_used == 2) ? (_digits[1] << _DIGIT_BITS) : 0) + _digits[0];
- }
- return other._toBigint()._lShift(shift)._toValidInt();
- }
-
- // Overriden operators and methods.
-
- // The following operators override operators of _IntegerImplementation for
- // efficiency, but are not necessary for correctness. They shortcut native
- // calls that would return null because the receiver is _Bigint.
- num operator +(num other) {
- return other._toBigintOrDouble()._addFromInteger(this);
- }
-
- num operator -(num other) {
- return other._toBigintOrDouble()._subFromInteger(this);
- }
-
- num operator *(num other) {
- return other._toBigintOrDouble()._mulFromInteger(this);
- }
-
- int operator ~/(num other) {
- return other._toBigintOrDouble()._truncDivFromInteger(this);
- }
-
- num operator %(num other) {
- return other._toBigintOrDouble()._moduloFromInteger(this);
- }
-
- int operator &(int other) {
- return other._toBigint()._bitAndFromInteger(this);
- }
-
- int operator |(int other) {
- return other._toBigint()._bitOrFromInteger(this);
- }
-
- int operator ^(int other) {
- return other._toBigint()._bitXorFromInteger(this);
- }
-
- int operator >>(int other) {
- return other._toBigint()._shrFromInt(this);
- }
-
- int operator <<(int other) {
- return other._toBigint()._shlFromInt(this);
- }
- // End of operator shortcuts.
-
- int operator -() {
- return _negate()._toValidInt();
- }
-
- int get sign {
- return (_used == 0) ? 0 : _neg ? -1 : 1;
- }
-
- bool get isEven => _used == 0 || (_digits[0] & 1) == 0;
- bool get isNegative => _neg;
-
- String _toPow2String(int radix) {
- if (_used == 0) return "0";
- assert(radix & (radix - 1) == 0);
- final bitsPerChar = radix.bitLength - 1;
- final firstcx = _neg ? 1 : 0; // Index of first char in str after the sign.
- final lastdx = _used - 1; // Index of last digit in bigint.
- final bitLength = lastdx * _DIGIT_BITS + _nbits(_digits[lastdx]);
- // Index of char in str. Initialize with str length.
- var cx = firstcx + (bitLength + bitsPerChar - 1) ~/ bitsPerChar;
- _OneByteString str = _OneByteString._allocate(cx);
- str._setAt(0, 0x2d); // '-'. Is overwritten if not negative.
- final mask = radix - 1;
- var dx = 0; // Digit index in bigint.
- var bx = 0; // Bit index in bigint digit.
- do {
- var ch;
- if (bx > (_DIGIT_BITS - bitsPerChar)) {
- ch = _digits[dx++] >> bx;
- bx += bitsPerChar - _DIGIT_BITS;
- if (dx <= lastdx) {
- ch |= (_digits[dx] & ((1 << bx) - 1)) << (bitsPerChar - bx);
- }
- } else {
- ch = (_digits[dx] >> bx) & mask;
- bx += bitsPerChar;
- if (bx >= _DIGIT_BITS) {
- bx -= _DIGIT_BITS;
- dx++;
- }
- }
- str._setAt(--cx, _IntegerImplementation._digits.codeUnitAt(ch));
- } while (cx > firstcx);
- return str;
- }
-
- int _bitAndFromSmi(_Smi other) => _bitAndFromInteger(other);
-
- int _bitAndFromInteger(int other) {
- return other._toBigint()._and(this)._toValidInt();
- }
-
- int _bitOrFromInteger(int other) {
- return other._toBigint()._or(this)._toValidInt();
- }
-
- int _bitXorFromInteger(int other) {
- return other._toBigint()._xor(this)._toValidInt();
- }
-
- int _addFromInteger(int other) {
- return other._toBigint()._add(this)._toValidInt();
- }
-
- int _subFromInteger(int other) {
- return other._toBigint()._sub(this)._toValidInt();
- }
-
- int _mulFromInteger(int other) {
- return other._toBigint()._mul(this)._toValidInt();
- }
-
- int _truncDivFromInteger(int other) {
- if (_used == 0) {
- throw const IntegerDivisionByZeroException();
- }
- return other._toBigint()._div(this)._toValidInt();
- }
-
- int _moduloFromInteger(int other) {
- if (_used == 0) {
- throw const IntegerDivisionByZeroException();
- }
- _Bigint result = other._toBigint()._rem(this);
- if (result._neg) {
- if (_neg) {
- result = result._sub(this);
- } else {
- result = result._add(this);
- }
- }
- return result._toValidInt();
- }
-
- int _remainderFromInteger(int other) {
- if (_used == 0) {
- throw const IntegerDivisionByZeroException();
- }
- return other._toBigint()._rem(this)._toValidInt();
- }
-
- bool _greaterThanFromInteger(int other) {
- return other._toBigint()._compare(this) > 0;
- }
-
- bool _equalToInteger(int other) {
- return other._toBigint()._compare(this) == 0;
- }
-
- // Returns pow(this, e) % m, with e >= 0, m > 0.
- int modPow(int e, int m) {
- if (e is! int) {
- throw new ArgumentError.value(e, "exponent", "not an integer");
- }
- if (m is! int) {
- throw new ArgumentError.value(m, "modulus", "not an integer");
- }
- if (e < 0) throw new RangeError.range(e, 0, null, "exponent");
- if (m <= 0) throw new RangeError.range(m, 1, null, "modulus");
- if (e == 0) return 1;
- final mAsBigint = m._toBigint();
- final m_used = mAsBigint._used;
- final m_used2p4 = 2 * m_used + 4;
- final e_bitlen = e.bitLength;
- if (e_bitlen <= 0) return 1;
- final bool cannotUseMontgomery = mAsBigint.isEven || _abs() >= mAsBigint;
- if (cannotUseMontgomery || e_bitlen < 64) {
- _Reduction z = (cannotUseMontgomery || e_bitlen < 8)
- ? new _Classic(mAsBigint)
- : new _Montgomery(mAsBigint);
- // TODO(regis): Should we use Barrett reduction for an even modulus and a
- // large exponent?
- var r_digits = new Uint32List(m_used2p4);
- var r2_digits = new Uint32List(m_used2p4);
- var g_digits = new Uint32List(m_used + (m_used & 1));
- var g_used = z._convert(this, g_digits);
- // Initialize r with g.
- var j = g_used + (g_used & 1); // Copy leading zero if any.
- while (--j >= 0) {
- r_digits[j] = g_digits[j];
- }
- var r_used = g_used;
- var r2_used;
- var i = e_bitlen - 1;
- while (--i >= 0) {
- r2_used = z._sqr(r_digits, r_used, r2_digits);
- if ((e & (1 << i)) != 0) {
- r_used = z._mul(r2_digits, r2_used, g_digits, g_used, r_digits);
- } else {
- var t_digits = r_digits;
- var t_used = r_used;
- r_digits = r2_digits;
- r_used = r2_used;
- r2_digits = t_digits;
- r2_used = t_used;
- }
- }
- return z._revert(r_digits, r_used)._toValidInt();
- }
- final eAsBigint = e._toBigint();
- var k;
- if (e_bitlen < 18)
- k = 1;
- else if (e_bitlen < 48)
- k = 3;
- else if (e_bitlen < 144)
- k = 4;
- else if (e_bitlen < 768)
- k = 5;
- else
- k = 6;
- _Reduction z = new _Montgomery(mAsBigint);
- var n = 3;
- final k1 = k - 1;
- final km = (1 << k) - 1;
- List g_digits = new List(km + 1);
- List g_used = new List(km + 1);
- g_digits[1] = new Uint32List(m_used + (m_used & 1));
- g_used[1] = z._convert(this, g_digits[1]);
- if (k > 1) {
- var g2_digits = new Uint32List(m_used2p4);
- var g2_used = z._sqr(g_digits[1], g_used[1], g2_digits);
- while (n <= km) {
- g_digits[n] = new Uint32List(m_used2p4);
- g_used[n] = z._mul(
- g2_digits, g2_used, g_digits[n - 2], g_used[n - 2], g_digits[n]);
- n += 2;
- }
- }
- var w;
- var is1 = true;
- var r_digits = _ONE._digits;
- var r_used = _ONE._used;
- var r2_digits = new Uint32List(m_used2p4);
- var r2_used;
- var e_digits = eAsBigint._digits;
- var j = eAsBigint._used - 1;
- var i = _nbits(e_digits[j]) - 1;
- while (j >= 0) {
- if (i >= k1) {
- w = (e_digits[j] >> (i - k1)) & km;
- } else {
- w = (e_digits[j] & ((1 << (i + 1)) - 1)) << (k1 - i);
- if (j > 0) {
- w |= e_digits[j - 1] >> (_DIGIT_BITS + i - k1);
- }
- }
- n = k;
- while ((w & 1) == 0) {
- w >>= 1;
- --n;
- }
- if ((i -= n) < 0) {
- i += _DIGIT_BITS;
- --j;
- }
- if (is1) {
- // r == 1, don't bother squaring or multiplying it.
- r_digits = new Uint32List(m_used2p4);
- r_used = g_used[w];
- var gw_digits = g_digits[w];
- var ri = r_used + (r_used & 1); // Copy leading zero if any.
- while (--ri >= 0) {
- r_digits[ri] = gw_digits[ri];
- }
- is1 = false;
- } else {
- while (n > 1) {
- r2_used = z._sqr(r_digits, r_used, r2_digits);
- r_used = z._sqr(r2_digits, r2_used, r_digits);
- n -= 2;
- }
- if (n > 0) {
- r2_used = z._sqr(r_digits, r_used, r2_digits);
- } else {
- var t_digits = r_digits;
- var t_used = r_used;
- r_digits = r2_digits;
- r_used = r2_used;
- r2_digits = t_digits;
- r2_used = t_used;
- }
- r_used = z._mul(r2_digits, r2_used, g_digits[w], g_used[w], r_digits);
- }
- while (j >= 0 && (e_digits[j] & (1 << i)) == 0) {
- r2_used = z._sqr(r_digits, r_used, r2_digits);
- var t_digits = r_digits;
- var t_used = r_used;
- r_digits = r2_digits;
- r_used = r2_used;
- r2_digits = t_digits;
- r2_used = t_used;
- if (--i < 0) {
- i = _DIGIT_BITS - 1;
- --j;
- }
- }
- }
- assert(!is1);
- return z._revert(r_digits, r_used)._toValidInt();
- }
-
- // If inv is false, returns gcd(x, y).
- // If inv is true and gcd(x, y) = 1, returns d, so that c*x + d*y = 1.
- // If inv is true and gcd(x, y) != 1, throws Exception("Not coprime").
- static int _binaryGcd(_Bigint x, _Bigint y, bool inv) {
- var x_digits = x._digits;
- var y_digits = y._digits;
- var x_used = x._used;
- var y_used = y._used;
- var m_used = x_used > y_used ? x_used : y_used;
- final m_len = m_used + (m_used & 1);
- x_digits = _cloneDigits(x_digits, 0, x_used, m_len);
- y_digits = _cloneDigits(y_digits, 0, y_used, m_len);
- int s = 0;
- if (inv) {
- if ((y_used == 1) && (y_digits[0] == 1)) return 1;
- if ((y_used == 0) || (y_digits[0].isEven && x_digits[0].isEven)) {
- throw new Exception("Not coprime");
- }
- } else {
- if (x_used == 0) {
- throw new ArgumentError.value(0, "this", "must not be zero");
- }
- if (y_used == 0) {
- throw new ArgumentError.value(0, "other", "must not be zero");
- }
- if (((x_used == 1) && (x_digits[0] == 1)) ||
- ((y_used == 1) && (y_digits[0] == 1))) return 1;
- bool xy_cloned = false;
- while (((x_digits[0] & 1) == 0) && ((y_digits[0] & 1) == 0)) {
- _rsh(x_digits, x_used, 1, x_digits);
- _rsh(y_digits, y_used, 1, y_digits);
- s++;
- }
- if (s >= _DIGIT_BITS) {
- var sd = s >> _LOG2_DIGIT_BITS;
- x_used -= sd;
- y_used -= sd;
- m_used -= sd;
- }
- if ((y_digits[0] & 1) == 1) {
- var t_digits = x_digits;
- var t_used = x_used;
- x_digits = y_digits;
- x_used = y_used;
- y_digits = t_digits;
- y_used = t_used;
- }
- }
- var u_digits = _cloneDigits(x_digits, 0, x_used, m_len);
- var v_digits = _cloneDigits(y_digits, 0, y_used, m_len + 2); // +2 for lsh.
- final bool ac = (x_digits[0] & 1) == 0;
-
- // Variables a, b, c, and d require one more digit.
- final abcd_used = m_used + 1;
- final abcd_len = abcd_used + (abcd_used & 1) + 2; // +2 to satisfy _absAdd.
- var a_digits, b_digits, c_digits, d_digits;
- bool a_neg, b_neg, c_neg, d_neg;
- if (ac) {
- a_digits = new Uint32List(abcd_len);
- a_neg = false;
- a_digits[0] = 1;
- c_digits = new Uint32List(abcd_len);
- c_neg = false;
- }
- b_digits = new Uint32List(abcd_len);
- b_neg = false;
- d_digits = new Uint32List(abcd_len);
- d_neg = false;
- d_digits[0] = 1;
-
- while (true) {
- while ((u_digits[0] & 1) == 0) {
- _rsh(u_digits, m_used, 1, u_digits);
- if (ac) {
- if (((a_digits[0] & 1) == 1) || ((b_digits[0] & 1) == 1)) {
- if (a_neg) {
- if ((a_digits[m_used] != 0) ||
- (_compareDigits(a_digits, m_used, y_digits, m_used)) > 0) {
- _absSub(a_digits, abcd_used, y_digits, m_used, a_digits);
- } else {
- _absSub(y_digits, m_used, a_digits, m_used, a_digits);
- a_neg = false;
- }
- } else {
- _absAdd(a_digits, abcd_used, y_digits, m_used, a_digits);
- }
- if (b_neg) {
- _absAdd(b_digits, abcd_used, x_digits, m_used, b_digits);
- } else if ((b_digits[m_used] != 0) ||
- (_compareDigits(b_digits, m_used, x_digits, m_used) > 0)) {
- _absSub(b_digits, abcd_used, x_digits, m_used, b_digits);
- } else {
- _absSub(x_digits, m_used, b_digits, m_used, b_digits);
- b_neg = true;
- }
- }
- _rsh(a_digits, abcd_used, 1, a_digits);
- } else if ((b_digits[0] & 1) == 1) {
- if (b_neg) {
- _absAdd(b_digits, abcd_used, x_digits, m_used, b_digits);
- } else if ((b_digits[m_used] != 0) ||
- (_compareDigits(b_digits, m_used, x_digits, m_used) > 0)) {
- _absSub(b_digits, abcd_used, x_digits, m_used, b_digits);
- } else {
- _absSub(x_digits, m_used, b_digits, m_used, b_digits);
- b_neg = true;
- }
- }
- _rsh(b_digits, abcd_used, 1, b_digits);
- }
- while ((v_digits[0] & 1) == 0) {
- _rsh(v_digits, m_used, 1, v_digits);
- if (ac) {
- if (((c_digits[0] & 1) == 1) || ((d_digits[0] & 1) == 1)) {
- if (c_neg) {
- if ((c_digits[m_used] != 0) ||
- (_compareDigits(c_digits, m_used, y_digits, m_used) > 0)) {
- _absSub(c_digits, abcd_used, y_digits, m_used, c_digits);
- } else {
- _absSub(y_digits, m_used, c_digits, m_used, c_digits);
- c_neg = false;
- }
- } else {
- _absAdd(c_digits, abcd_used, y_digits, m_used, c_digits);
- }
- if (d_neg) {
- _absAdd(d_digits, abcd_used, x_digits, m_used, d_digits);
- } else if ((d_digits[m_used] != 0) ||
- (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) {
- _absSub(d_digits, abcd_used, x_digits, m_used, d_digits);
- } else {
- _absSub(x_digits, m_used, d_digits, m_used, d_digits);
- d_neg = true;
- }
- }
- _rsh(c_digits, abcd_used, 1, c_digits);
- } else if ((d_digits[0] & 1) == 1) {
- if (d_neg) {
- _absAdd(d_digits, abcd_used, x_digits, m_used, d_digits);
- } else if ((d_digits[m_used] != 0) ||
- (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) {
- _absSub(d_digits, abcd_used, x_digits, m_used, d_digits);
- } else {
- _absSub(x_digits, m_used, d_digits, m_used, d_digits);
- d_neg = true;
- }
- }
- _rsh(d_digits, abcd_used, 1, d_digits);
- }
- if (_compareDigits(u_digits, m_used, v_digits, m_used) >= 0) {
- _absSub(u_digits, m_used, v_digits, m_used, u_digits);
- if (ac) {
- if (a_neg == c_neg) {
- var a_cmp_c =
- _compareDigits(a_digits, abcd_used, c_digits, abcd_used);
- if (a_cmp_c > 0) {
- _absSub(a_digits, abcd_used, c_digits, abcd_used, a_digits);
- } else {
- _absSub(c_digits, abcd_used, a_digits, abcd_used, a_digits);
- a_neg = !a_neg && (a_cmp_c != 0);
- }
- } else {
- _absAdd(a_digits, abcd_used, c_digits, abcd_used, a_digits);
- }
- }
- if (b_neg == d_neg) {
- var b_cmp_d =
- _compareDigits(b_digits, abcd_used, d_digits, abcd_used);
- if (b_cmp_d > 0) {
- _absSub(b_digits, abcd_used, d_digits, abcd_used, b_digits);
- } else {
- _absSub(d_digits, abcd_used, b_digits, abcd_used, b_digits);
- b_neg = !b_neg && (b_cmp_d != 0);
- }
- } else {
- _absAdd(b_digits, abcd_used, d_digits, abcd_used, b_digits);
- }
- } else {
- _absSub(v_digits, m_used, u_digits, m_used, v_digits);
- if (ac) {
- if (c_neg == a_neg) {
- var c_cmp_a =
- _compareDigits(c_digits, abcd_used, a_digits, abcd_used);
- if (c_cmp_a > 0) {
- _absSub(c_digits, abcd_used, a_digits, abcd_used, c_digits);
- } else {
- _absSub(a_digits, abcd_used, c_digits, abcd_used, c_digits);
- c_neg = !c_neg && (c_cmp_a != 0);
- }
- } else {
- _absAdd(c_digits, abcd_used, a_digits, abcd_used, c_digits);
- }
- }
- if (d_neg == b_neg) {
- var d_cmp_b =
- _compareDigits(d_digits, abcd_used, b_digits, abcd_used);
- if (d_cmp_b > 0) {
- _absSub(d_digits, abcd_used, b_digits, abcd_used, d_digits);
- } else {
- _absSub(b_digits, abcd_used, d_digits, abcd_used, d_digits);
- d_neg = !d_neg && (d_cmp_b != 0);
- }
- } else {
- _absAdd(d_digits, abcd_used, b_digits, abcd_used, d_digits);
- }
- }
- // Exit loop if u == 0.
- var i = m_used;
- while ((i > 0) && (u_digits[i - 1] == 0)) --i;
- if (i == 0) break;
- }
- if (!inv) {
- if (s > 0) {
- m_used = _lShiftDigits(v_digits, m_used, s, v_digits);
- }
- return new _Bigint(false, m_used, v_digits)._toValidInt();
- }
- // No inverse if v != 1.
- var i = m_used - 1;
- while ((i > 0) && (v_digits[i] == 0)) --i;
- if ((i != 0) || (v_digits[0] != 1)) {
- throw new Exception("Not coprime");
- }
-
- if (d_neg) {
- if ((d_digits[m_used] != 0) ||
- (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) {
- _absSub(d_digits, abcd_used, x_digits, m_used, d_digits);
- if ((d_digits[m_used] != 0) ||
- (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) {
- _absSub(d_digits, abcd_used, x_digits, m_used, d_digits);
- } else {
- _absSub(x_digits, m_used, d_digits, m_used, d_digits);
- d_neg = false;
- }
- } else {
- _absSub(x_digits, m_used, d_digits, m_used, d_digits);
- d_neg = false;
- }
- } else if ((d_digits[m_used] != 0) ||
- (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) {
- _absSub(d_digits, abcd_used, x_digits, m_used, d_digits);
- if ((d_digits[m_used] != 0) ||
- (_compareDigits(d_digits, m_used, x_digits, m_used) > 0)) {
- _absSub(d_digits, abcd_used, x_digits, m_used, d_digits);
- }
- }
- return new _Bigint(false, m_used, d_digits)._toValidInt();
- }
-
- // Returns 1/this % m, with m > 0.
- int modInverse(int m) {
- if (m is! int) {
- throw new ArgumentError.value(m, "modulus", "not an integer");
- }
- if (m <= 0) throw new RangeError.range(m, 1, null, "modulus");
- if (m == 1) return 0;
- final mAsBigint = m._toBigint();
- int t = this;
- if (this._neg || (this._absCompare(mAsBigint) >= 0)) {
- t %= mAsBigint;
- t = t._toBigint();
- }
- return _binaryGcd(mAsBigint, t, true);
- }
-
- // Returns gcd of abs(this) and abs(other).
- int gcd(int other) {
- if (other is! int) {
- throw new ArgumentError.value(other, "other", "not an integer");
- }
- if (other == 0) {
- return this.abs();
- }
- return _binaryGcd(this, other._toBigint(), false);
- }
-}
-
-// Interface for modular reduction.
-abstract class _Reduction {
- // Return the number of digits used by r_digits.
- int _convert(_Bigint x, Uint32List r_digits);
- int _mul(Uint32List x_digits, int x_used, Uint32List y_digits, int y_used,
- Uint32List r_digits);
- int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits);
-
- // Return x reverted to _Bigint.
- _Bigint _revert(Uint32List x_digits, int x_used);
-}
-
-// Montgomery reduction on _Bigint.
-class _Montgomery implements _Reduction {
- final _Bigint _m; // Modulus.
- int _mused2p2;
- Uint32List _args;
- int _digits_per_step; // Number of digits processed in one step. 1 or 2.
- static const int _X = 0; // Index of x.
- static const int _X_HI = 1; // Index of high 32-bits of x (64-bit only).
- static const int _RHO = 2; // Index of rho.
- static const int _RHO_HI = 3; // Index of high 32-bits of rho (64-bit only).
- static const int _MU = 4; // Index of mu.
- static const int _MU_HI = 5; // Index of high 32-bits of mu (64-bit only).
-
- _Montgomery(this._m) {
- _mused2p2 = 2 * _m._used + 2;
- _args = new Uint32List(6);
- // Determine if we can process digit pairs by calling an intrinsic.
- _digits_per_step = _mulMod(_args, _args, 0);
- _args[_X] = _m._digits[0];
- if (_digits_per_step == 1) {
- _invDigit(_args);
- } else {
- assert(_digits_per_step == 2);
- _args[_X_HI] = _m._digits[1];
- _invDigitPair(_args);
- }
- }
-
- // Calculates -1/x % _DIGIT_BASE, x is 32-bit digit.
- // xy == 1 (mod m)
- // xy = 1+km
- // xy(2-xy) = (1+km)(1-km)
- // x(y(2-xy)) = 1-k^2 m^2
- // x(y(2-xy)) == 1 (mod m^2)
- // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
- // Should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
- //
- // Operation:
- // args[_RHO] = 1/args[_X] mod _DIGIT_BASE.
- static void _invDigit(Uint32List args) {
- var x = args[_X];
- var y = x & 3; // y == 1/x mod 2^2
- y = (y * (2 - (x & 0xf) * y)) & 0xf; // y == 1/x mod 2^4
- y = (y * (2 - (x & 0xff) * y)) & 0xff; // y == 1/x mod 2^8
- y = (y * (2 - (((x & 0xffff) * y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16
- // Last step - calculate inverse mod _DIGIT_BASE directly;
- // Assumes 16 < _DIGIT_BITS <= 32 and assumes ability to handle 48-bit ints.
- y = (y * (2 - x * y % _Bigint._DIGIT_BASE)) % _Bigint._DIGIT_BASE;
- // y == 1/x mod _DIGIT_BASE
- y = -y; // We really want the negative inverse.
- args[_RHO] = y & _Bigint._DIGIT_MASK;
- assert(((x * y) & _Bigint._DIGIT_MASK) == _Bigint._DIGIT_MASK);
- }
-
- // Calculates -1/x % _DIGIT_BASE^2, x is a pair of 32-bit digits.
- // Operation:
- // args[_RHO.._RHO_HI] = 1/args[_X.._X_HI] mod _DIGIT_BASE^2.
- static void _invDigitPair(Uint32List args) {
- var xl = args[_X]; // Lower 32-bit digit of x.
- var y = xl & 3; // y == 1/x mod 2^2
- y = (y * (2 - (xl & 0xf) * y)) & 0xf; // y == 1/x mod 2^4
- y = (y * (2 - (xl & 0xff) * y)) & 0xff; // y == 1/x mod 2^8
- y = (y * (2 - (((xl & 0xffff) * y) & 0xffff))) &
- 0xffff; // y == 1/x mod 2^16
- y = (y * (2 - ((xl * y) & 0xffffffff))) & 0xffffffff; // y == 1/x mod 2^32
- // Warning: The following expressions involve bigint arithmetic.
- var x = (args[_X_HI] << _Bigint._DIGIT_BITS) | xl;
- y = (y * (2 - ((x * y) & _Bigint._TWO_DIGITS_MASK))) &
- _Bigint._TWO_DIGITS_MASK;
- // y == 1/x mod _DIGIT_BASE^2
- y = -y; // We really want the negative inverse.
- args[_RHO] = y & _Bigint._DIGIT_MASK;
- args[_RHO_HI] = (y >> _Bigint._DIGIT_BITS) & _Bigint._DIGIT_MASK;
- assert(((x * y) & _Bigint._TWO_DIGITS_MASK) == _Bigint._TWO_DIGITS_MASK);
- }
-
- // Operation:
- // args[_MU] = args[_RHO]*digits[i] mod _DIGIT_BASE.
- // return 1.
- // Note: Intrinsics on 64-bit platforms process digit pairs at even indices:
- // args[_MU.._MU_HI] = args[_RHO.._RHO_HI]*digits[i..i+1] mod _DIGIT_BASE^2.
- // return 2.
- static int _mulMod(Uint32List args, Uint32List digits, int i) {
- // Verify that digit pairs are accessible for 64-bit processing.
- assert(digits.length > (i | 1));
- const int MU_MASK = (1 << (_Bigint._DIGIT_BITS - _Bigint._DIGIT2_BITS)) - 1;
- var rhol = args[_RHO] & _Bigint._DIGIT2_MASK;
- var rhoh = args[_RHO] >> _Bigint._DIGIT2_BITS;
- var dh = digits[i] >> _Bigint._DIGIT2_BITS;
- var dl = digits[i] & _Bigint._DIGIT2_MASK;
- args[_MU] = (dl * rhol +
- (((dl * rhoh + dh * rhol) & MU_MASK) << _Bigint._DIGIT2_BITS)) &
- _Bigint._DIGIT_MASK;
- return 1;
- }
-
- // r = x*R mod _m.
- // Return r_used.
- int _convert(_Bigint x, Uint32List r_digits) {
- // Montgomery reduction only works if abs(x) < _m.
- assert(x._abs() < _m);
- assert(_digits_per_step == 1 || _m._used.isEven);
- var r = x._abs()._dlShift(_m._used)._rem(_m);
- if (x._neg && !r._neg && r._used > 0) {
- r = _m._sub(r);
- }
- var used = r._used;
- var digits = r._digits;
- var i = used + (used & 1);
- while (--i >= 0) {
- r_digits[i] = digits[i];
- }
- return used;
- }
-
- _Bigint _revert(Uint32List x_digits, int x_used) {
- var r_digits = new Uint32List(_mused2p2);
- var i = x_used + (x_used & 1);
- while (--i >= 0) {
- r_digits[i] = x_digits[i];
- }
- var r_used = _reduce(r_digits, x_used);
- return new _Bigint(false, r_used, r_digits);
- }
-
- // x = x/R mod _m.
- // Return x_used.
- int _reduce(Uint32List x_digits, int x_used) {
- while (x_used < _mused2p2) {
- // Pad x so _mulAdd has enough room later.
- x_digits[x_used++] = 0;
- }
- var m_used = _m._used;
- var m_digits = _m._digits;
- var i = 0;
- while (i < m_used) {
- var d = _mulMod(_args, x_digits, i);
- assert(d == _digits_per_step);
- d = _Bigint._mulAdd(_args, _MU, m_digits, 0, x_digits, i, m_used);
- assert(d == _digits_per_step);
- i += d;
- }
- // Clamp x.
- while (x_used > 0 && x_digits[x_used - 1] == 0) {
- --x_used;
- }
- // Shift right by m_used digits or, if processing pairs, by i (even) digits.
- x_used = _Bigint._drShiftDigits(x_digits, x_used, i, x_digits);
- if (_Bigint._compareDigits(x_digits, x_used, m_digits, m_used) >= 0) {
- _Bigint._absSub(x_digits, x_used, m_digits, m_used, x_digits);
- }
- // Clamp x.
- while (x_used > 0 && x_digits[x_used - 1] == 0) {
- --x_used;
- }
- return x_used;
- }
-
- int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits) {
- var r_used = _Bigint._sqrDigits(x_digits, x_used, r_digits);
- return _reduce(r_digits, r_used);
- }
-
- int _mul(Uint32List x_digits, int x_used, Uint32List y_digits, int y_used,
- Uint32List r_digits) {
- var r_used =
- _Bigint._mulDigits(x_digits, x_used, y_digits, y_used, r_digits);
- return _reduce(r_digits, r_used);
- }
-}
-
-// Modular reduction using "classic" algorithm.
-class _Classic implements _Reduction {
- final _Bigint _m; // Modulus.
- _Bigint _norm_m; // Normalized _m.
- Uint32List _neg_norm_m_digits; // Negated _norm_m digits.
- int _m_nsh; // Normalization shift amount.
- Uint32List _mt_qd; // Top _norm_m digit(s) and place holder for
- // estimated quotient digit(s).
- Uint32List _t_digits; // Temporary digits used during reduction.
-
- _Classic(this._m) {
- // Preprocess arguments to _remDigits.
- var nsh = _Bigint._DIGIT_BITS - _Bigint._nbits(_m._digits[_m._used - 1]);
- // For 64-bit processing, make sure _norm_m_digits has an even number of
- // digits.
- if (_m._used.isOdd) {
- nsh += _Bigint._DIGIT_BITS;
- }
- _m_nsh = nsh;
- _norm_m = _m._lShift(nsh);
- var nm_used = _norm_m._used;
- assert(nm_used.isEven);
- _mt_qd = new Uint32List(4);
- _mt_qd[_Bigint._YT_LO] = _norm_m._digits[nm_used - 2];
- _mt_qd[_Bigint._YT] = _norm_m._digits[nm_used - 1];
- // Negate _norm_m so we can use _mulAdd instead of unimplemented _mulSub.
- var neg_norm_m = _Bigint._ONE._dlShift(nm_used)._sub(_norm_m);
- if (neg_norm_m._used < nm_used) {
- _neg_norm_m_digits =
- _Bigint._cloneDigits(neg_norm_m._digits, 0, nm_used, nm_used);
- } else {
- _neg_norm_m_digits = neg_norm_m._digits;
- }
- // _neg_norm_m_digits is read-only and has nm_used digits (possibly
- // including several leading zeros) plus a leading zero for 64-bit
- // processing.
- _t_digits = new Uint32List(2 * nm_used);
- }
-
- int _convert(_Bigint x, Uint32List r_digits) {
- var digits;
- var used;
- if (x._neg || x._compare(_m) >= 0) {
- var r = x._rem(_m);
- if (x._neg && !r._neg && r._used > 0) {
- r = _m._sub(r);
- }
- assert(!r._neg);
- used = r._used;
- digits = r._digits;
- } else {
- used = x._used;
- digits = x._digits;
- }
- var i = used + (used & 1); // Copy leading zero if any.
- while (--i >= 0) {
- r_digits[i] = digits[i];
- }
- return used;
- }
-
- _Bigint _revert(Uint32List x_digits, int x_used) {
- return new _Bigint(false, x_used, x_digits);
- }
-
- int _reduce(Uint32List x_digits, int x_used) {
- if (x_used < _m._used) {
- return x_used;
- }
- // The function _remDigits(...) is optimized for reduction and equivalent to
- // calling _convert(_revert(x_digits, x_used)._rem(_m), x_digits);
- return _Bigint._remDigits(x_digits, x_used, _norm_m._digits, _norm_m._used,
- _neg_norm_m_digits, _m_nsh, _mt_qd, _t_digits, x_digits);
- }
-
- int _sqr(Uint32List x_digits, int x_used, Uint32List r_digits) {
- var r_used = _Bigint._sqrDigits(x_digits, x_used, r_digits);
- return _reduce(r_digits, r_used);
- }
-
- int _mul(Uint32List x_digits, int x_used, Uint32List y_digits, int y_used,
- Uint32List r_digits) {
- var r_used =
- _Bigint._mulDigits(x_digits, x_used, y_digits, y_used, r_digits);
- return _reduce(r_digits, r_used);
- }
-}
diff --git a/runtime/lib/class_id_fasta.dart b/runtime/lib/class_id_fasta.dart
index b7a6e54..150488e 100644
--- a/runtime/lib/class_id_fasta.dart
+++ b/runtime/lib/class_id_fasta.dart
@@ -13,5 +13,4 @@
static final int cidImmutableArray = 0;
static final int cidOneByteString = 0;
static final int cidTwoByteString = 0;
- static final int cidBigint = 0;
}
diff --git a/runtime/lib/core_patch.dart b/runtime/lib/core_patch.dart
index 3bbb755..1b0f849 100644
--- a/runtime/lib/core_patch.dart
+++ b/runtime/lib/core_patch.dart
@@ -53,7 +53,6 @@
/// These are the additional parts of this patch library:
// part "array.dart";
// part "array_patch.dart";
-// part "bigint.dart";
// part "bigint_patch.dart";
// part "bool_patch.dart";
// part "date_patch.dart";
@@ -92,7 +91,6 @@
num _remainderFromInteger(int other);
bool _greaterThanFromInteger(int other);
bool _equalToInteger(int other);
- num _toBigintOrDouble();
}
// The members of this class are cloned and added to each class that
diff --git a/runtime/lib/core_sources.gni b/runtime/lib/core_sources.gni
index dc4f7c8..2f9a7a9 100644
--- a/runtime/lib/core_sources.gni
+++ b/runtime/lib/core_sources.gni
@@ -10,7 +10,6 @@
"array.cc",
"array.dart",
"array_patch.dart",
- "bigint.dart",
"bigint_patch.dart",
"bool.cc",
"bool_patch.dart",
diff --git a/runtime/lib/double.cc b/runtime/lib/double.cc
index 9787af0..4fc5baa 100644
--- a/runtime/lib/double.cc
+++ b/runtime/lib/double.cc
@@ -74,46 +74,15 @@
args.SetAt(0, String::Handle(String::New(error_msg)));
Exceptions::ThrowByType(Exceptions::kUnsupported, args);
}
- if (FLAG_limit_ints_to_64_bits) {
- int64_t ival = 0;
- if (val <= static_cast<double>(kMinInt64)) {
- ival = kMinInt64;
- } else if (val >= static_cast<double>(kMaxInt64)) {
- ival = kMaxInt64;
- } else { // Representable in int64_t.
- ival = static_cast<int64_t>(val);
- }
- return Integer::New(ival);
+ int64_t ival = 0;
+ if (val <= static_cast<double>(kMinInt64)) {
+ ival = kMinInt64;
+ } else if (val >= static_cast<double>(kMaxInt64)) {
+ ival = kMaxInt64;
+ } else { // Representable in int64_t.
+ ival = static_cast<int64_t>(val);
}
- if ((-1.0 < val) && (val < 1.0)) {
- return Smi::New(0);
- }
- DoubleInternals internals = DoubleInternals(val);
- ASSERT(!internals.IsSpecial()); // Only Infinity and NaN are special.
- uint64_t significand = internals.Significand();
- intptr_t exponent = internals.Exponent();
- if (exponent <= 0) {
- significand >>= -exponent;
- exponent = 0;
- } else if (exponent <= 10) {
- // A double significand has at most 53 bits. The following shift will
- // hence not overflow, and yield an integer of at most 63 bits.
- significand <<= exponent;
- exponent = 0;
- }
- // A significand has at most 63 bits (after the shift above).
- // The cast to int64_t is hence safe.
- int64_t ival = static_cast<int64_t>(significand);
- if (internals.Sign() < 0) {
- ival = -ival;
- }
- if (exponent == 0) {
- // The double fits in a Smi or Mint.
- return Integer::New(ival);
- }
- Integer& result = Integer::Handle();
- result = Bigint::NewFromShiftedInt64(ival, exponent);
- return result.AsValidInteger();
+ return Integer::New(ival);
}
DEFINE_NATIVE_ENTRY(Double_hashCode, 1) {
@@ -127,14 +96,6 @@
if (static_cast<double>(ival) == val) {
return Integer::New(ival);
}
- } else if (!FLAG_limit_ints_to_64_bits && !isinf(val) && !isnan(val)) {
- // Since this code is temporary until we limit ints to 64 bits, we
- // reuse the existing DoubleToInteger helper function and pass it
- // an empty error message ("") because it cannot fail.
- const Integer& bigint = Integer::Handle(DoubleToInteger(val, ""));
- if (bigint.AsDoubleValue() == val) {
- return bigint.raw();
- }
}
uint64_t uval = bit_cast<uint64_t>(val);
diff --git a/runtime/lib/double.dart b/runtime/lib/double.dart
index 86ad7ca..151bf24 100644
--- a/runtime/lib/double.dart
+++ b/runtime/lib/double.dart
@@ -149,9 +149,6 @@
}
int toInt() native "Double_toInt";
- num _toBigintOrDouble() {
- return this;
- }
double toDouble() {
return this;
diff --git a/runtime/lib/integers.cc b/runtime/lib/integers.cc
index 5443197..4b93733 100644
--- a/runtime/lib/integers.cc
+++ b/runtime/lib/integers.cc
@@ -23,14 +23,9 @@
// Smi natives.
-// Returns false if integer is in wrong representation, e.g., as is a Bigint
+// Returns false if integer is in wrong representation, e.g., as is a Mint
// when it could have been a Smi.
static bool CheckInteger(const Integer& i) {
- if (i.IsBigint()) {
- ASSERT(!Bigint::IsDisabled());
- const Bigint& bigint = Bigint::Cast(i);
- return !bigint.FitsIntoSmi() && !bigint.FitsIntoInt64();
- }
if (i.IsMint()) {
const Mint& mint = Mint::Cast(i);
return !Smi::IsValid(mint.value());
@@ -245,35 +240,20 @@
const Smi& smi_value = Smi::Cast(value);
return smi_value.ShiftOp(kind, amount, Heap::kNew);
}
- if (value.IsMint()) {
- const int64_t mint_value = value.AsInt64Value();
- intptr_t shift_count = amount.Value();
- switch (kind) {
- case Token::kSHL:
- if (FLAG_limit_ints_to_64_bits) {
- return Integer::New(
- Utils::ShiftLeftWithTruncation(mint_value, shift_count),
- Heap::kNew);
- } else {
- const int count = Utils::HighestBit(mint_value);
- if (shift_count < (Mint::kBits - count)) {
- return Integer::New(mint_value << shift_count, Heap::kNew);
- } else {
- // Overflow in shift, use Bigints
- return Integer::null();
- }
- }
- case Token::kSHR:
- shift_count = Utils::Minimum(shift_count, Mint::kBits);
- return Integer::New(mint_value >> shift_count, Heap::kNew);
- default:
- UNIMPLEMENTED();
- }
- } else {
- ASSERT(value.IsBigint());
+ ASSERT(value.IsMint());
+ const int64_t mint_value = value.AsInt64Value();
+ intptr_t shift_count = amount.Value();
+ switch (kind) {
+ case Token::kSHL:
+ return Integer::New(
+ Utils::ShiftLeftWithTruncation(mint_value, shift_count), Heap::kNew);
+ case Token::kSHR:
+ shift_count = Utils::Minimum(shift_count, Mint::kBits);
+ return Integer::New(mint_value >> shift_count, Heap::kNew);
+ default:
+ UNIMPLEMENTED();
+ return Integer::null();
}
- ASSERT(!Bigint::IsDisabled());
- return Integer::null();
}
DEFINE_NATIVE_ENTRY(Smi_bitAndFromSmi, 2) {
@@ -369,31 +349,4 @@
return 0;
}
-// Bigint natives.
-
-DEFINE_NATIVE_ENTRY(Bigint_getNeg, 1) {
- const Bigint& bigint = Bigint::CheckedHandle(arguments->NativeArgAt(0));
- return bigint.neg();
-}
-
-DEFINE_NATIVE_ENTRY(Bigint_getUsed, 1) {
- const Bigint& bigint = Bigint::CheckedHandle(arguments->NativeArgAt(0));
- return bigint.used();
-}
-
-DEFINE_NATIVE_ENTRY(Bigint_getDigits, 1) {
- const Bigint& bigint = Bigint::CheckedHandle(arguments->NativeArgAt(0));
- return bigint.digits();
-}
-
-DEFINE_NATIVE_ENTRY(Bigint_allocate, 4) {
- ASSERT(!Bigint::IsDisabled());
- // First arg is null type arguments, since class Bigint is not parameterized.
- const Bool& neg = Bool::CheckedHandle(arguments->NativeArgAt(1));
- const Smi& used = Smi::CheckedHandle(arguments->NativeArgAt(2));
- const TypedData& digits = TypedData::CheckedHandle(arguments->NativeArgAt(3));
- ASSERT(!digits.IsNull());
- return Bigint::New(neg.value(), used.Value(), digits);
-}
-
} // namespace dart
diff --git a/runtime/lib/integers.dart b/runtime/lib/integers.dart
index d779bc7..fe33e66 100644
--- a/runtime/lib/integers.dart
+++ b/runtime/lib/integers.dart
@@ -9,35 +9,15 @@
abstract class _int64 implements int {}
abstract class _IntegerImplementation implements int {
- num operator +(num other) {
- var result = other._addFromInteger(this);
- if (result != null) return result;
- final _IntegerImplementation otherAsIntImpl = other;
- return otherAsIntImpl._toBigint()._addFromInteger(this);
- }
-
- num operator -(num other) {
- var result = other._subFromInteger(this);
- if (result != null) return result;
- final _IntegerImplementation otherAsIntImpl = other;
- return otherAsIntImpl._toBigint()._subFromInteger(this);
- }
-
- num operator *(num other) {
- var result = other._mulFromInteger(this);
- if (result != null) return result;
- final _IntegerImplementation otherAsIntImpl = other;
- return otherAsIntImpl._toBigint()._mulFromInteger(this);
- }
+ num operator +(num other) => other._addFromInteger(this);
+ num operator -(num other) => other._subFromInteger(this);
+ num operator *(num other) => other._mulFromInteger(this);
int operator ~/(num other) {
if ((other is int) && (other == 0)) {
throw const IntegerDivisionByZeroException();
}
- var result = other._truncDivFromInteger(this);
- if (result != null) return result;
- final _IntegerImplementation otherAsIntImpl = other;
- return otherAsIntImpl._toBigint()._truncDivFromInteger(this);
+ return other._truncDivFromInteger(this);
}
double operator /(num other) {
@@ -48,33 +28,16 @@
if ((other is int) && (other == 0)) {
throw const IntegerDivisionByZeroException();
}
- var result = other._moduloFromInteger(this);
- if (result != null) return result;
- final _IntegerImplementation otherAsIntImpl = other;
- return otherAsIntImpl._toBigint()._moduloFromInteger(this);
+ return other._moduloFromInteger(this);
}
int operator -() {
return 0 - this;
}
- int operator &(int other) {
- var result = other._bitAndFromInteger(this);
- if (result != null) return result;
- return other._toBigint()._bitAndFromInteger(this);
- }
-
- int operator |(int other) {
- var result = other._bitOrFromInteger(this);
- if (result != null) return result;
- return other._toBigint()._bitOrFromInteger(this);
- }
-
- int operator ^(int other) {
- var result = other._bitXorFromInteger(this);
- if (result != null) return result;
- return other._toBigint()._bitXorFromInteger(this);
- }
+ int operator &(int other) => other._bitAndFromInteger(this);
+ int operator |(int other) => other._bitOrFromInteger(this);
+ int operator ^(int other) => other._bitXorFromInteger(this);
num remainder(num other) {
return other._remainderFromInteger(this);
@@ -93,17 +56,8 @@
return other - (other ~/ this) * this;
}
- int operator >>(int other) {
- var result = other._shrFromInt(this);
- if (result != null) return result;
- return other._toBigint()._shrFromInt(this);
- }
-
- int operator <<(int other) {
- var result = other._shlFromInt(this);
- if (result != null) return result;
- return other._toBigint()._shlFromInt(this);
- }
+ int operator >>(int other) => other._shrFromInt(this);
+ int operator <<(int other) => other._shlFromInt(this);
bool operator <(num other) {
return other > this;
@@ -272,14 +226,6 @@
return new _Double.fromInteger(this);
}
- _Bigint _toBigint() {
- return new _Bigint._fromInt(this);
- }
-
- num _toBigintOrDouble() {
- return _toBigint();
- }
-
String toStringAsFixed(int fractionDigits) {
return this.toDouble().toStringAsFixed(fractionDigits);
}
@@ -386,9 +332,6 @@
if (e < 0) throw new RangeError.range(e, 0, null, "exponent");
if (m <= 0) throw new RangeError.range(m, 1, null, "modulus");
if (e == 0) return 1;
- if (e is _Bigint || m is _Bigint) {
- return _toBigint().modPow(e, m);
- }
int b = this;
if (b < 0 || b > m) {
b %= m;
@@ -483,9 +426,6 @@
}
if (m <= 0) throw new RangeError.range(m, 1, null, "modulus");
if (m == 1) return 0;
- if (m is _Bigint) {
- return _toBigint().modInverse(m);
- }
int t = this;
if ((t < 0) || (t >= m)) t %= m;
if (t == 1) return 1;
@@ -505,9 +445,6 @@
if (x == 0) return y;
if (y == 0) return x;
if ((x == 1) || (y == 1)) return 1;
- if (y is _Bigint) {
- return x._toBigint().gcd(y);
- }
return _binaryGcd(x, y, false);
}
}
diff --git a/runtime/lib/integers_patch.dart b/runtime/lib/integers_patch.dart
index d1c13be..9d2f62d 100644
--- a/runtime/lib/integers_patch.dart
+++ b/runtime/lib/integers_patch.dart
@@ -11,7 +11,6 @@
const factory int.fromEnvironment(String name, {int defaultValue})
native "Integer_fromEnvironment";
- _Bigint _toBigint();
int _shrFromInt(int other);
int _shlFromInt(int other);
int _bitAndFromSmi(_Smi other);
@@ -158,41 +157,36 @@
int multiplier = _PARSE_LIMITS[tableIndex + 1];
int positiveOverflowLimit = 0;
int negativeOverflowLimit = 0;
- if (_limitIntsTo64Bits) {
- tableIndex = tableIndex << 1; // pre-multiply by 2 for simpler indexing
- positiveOverflowLimit = _int64OverflowLimits[tableIndex];
- if (positiveOverflowLimit == 0) {
- positiveOverflowLimit =
- _initInt64OverflowLimits(tableIndex, multiplier);
- }
- negativeOverflowLimit = _int64OverflowLimits[tableIndex + 1];
+ tableIndex = tableIndex << 1; // pre-multiply by 2 for simpler indexing
+ positiveOverflowLimit = _int64OverflowLimits[tableIndex];
+ if (positiveOverflowLimit == 0) {
+ positiveOverflowLimit = _initInt64OverflowLimits(tableIndex, multiplier);
}
+ negativeOverflowLimit = _int64OverflowLimits[tableIndex + 1];
int blockEnd = start + blockSize;
do {
_Smi smi = _parseBlock(source, radix, start, blockEnd);
if (smi == null) return null;
- if (_limitIntsTo64Bits) {
- if (result >= positiveOverflowLimit) {
- if ((result > positiveOverflowLimit) ||
- (smi > _int64OverflowLimits[tableIndex + 2])) {
- // Although the unsigned overflow limits do not depend on the
- // platform, the multiplier and block size, which are used to
- // compute it, do.
- int X = is64Bit ? 1 : 0;
- if (radix == 16 &&
- !(result >= _int64UnsignedOverflowLimits[X] &&
- (result > _int64UnsignedOverflowLimits[X] ||
- smi > _int64UnsignedSmiOverflowLimits[X])) &&
- blockEnd + blockSize > end) {
- return (result * multiplier) + smi;
- }
- return null;
+ if (result >= positiveOverflowLimit) {
+ if ((result > positiveOverflowLimit) ||
+ (smi > _int64OverflowLimits[tableIndex + 2])) {
+ // Although the unsigned overflow limits do not depend on the
+ // platform, the multiplier and block size, which are used to
+ // compute it, do.
+ int X = is64Bit ? 1 : 0;
+ if (radix == 16 &&
+ !(result >= _int64UnsignedOverflowLimits[X] &&
+ (result > _int64UnsignedOverflowLimits[X] ||
+ smi > _int64UnsignedSmiOverflowLimits[X])) &&
+ blockEnd + blockSize > end) {
+ return (result * multiplier) + smi;
}
- } else if (result <= negativeOverflowLimit) {
- if ((result < negativeOverflowLimit) ||
- (smi > _int64OverflowLimits[tableIndex + 3])) {
- return null;
- }
+ return null;
+ }
+ } else if (result <= negativeOverflowLimit) {
+ if ((result < negativeOverflowLimit) ||
+ (smi > _int64OverflowLimits[tableIndex + 3])) {
+ return null;
}
}
result = (result * multiplier) + (sign * smi);
@@ -266,12 +260,8 @@
5, 60466176, 11, 131621703842267136,
];
- /// Flag indicating if integers are limited by 64 bits
- /// (`--limit-ints-to-64-bits` mode is enabled).
- static const _limitIntsTo64Bits = ((1 << 64) == 0);
-
static const _maxInt64 = 0x7fffffffffffffff;
- static const _minInt64 = -_maxInt64 - 1;
+ static const _minInt64 = -0x8000000000000000;
static const _int64UnsignedOverflowLimits = const [0xfffffffff, 0xf];
static const _int64UnsignedSmiOverflowLimits = const [
@@ -279,7 +269,7 @@
0xfffffffffffffff
];
- /// In the `--limit-ints-to-64-bits` mode calculation of the expression
+ /// Calculation of the expression
///
/// result = (result * multiplier) + (sign * smi)
///
diff --git a/runtime/lib/math.cc b/runtime/lib/math.cc
index 6ca9793..6b6ac56 100644
--- a/runtime/lib/math.cc
+++ b/runtime/lib/math.cc
@@ -146,39 +146,7 @@
// return result;
DEFINE_NATIVE_ENTRY(Random_setupSeed, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(Integer, seed_int, arguments->NativeArgAt(0));
- uint64_t seed = 0;
- if (seed_int.IsBigint()) {
- Bigint& big_seed = Bigint::Handle();
- big_seed ^= seed_int.raw();
- uint64_t negate_mask = 0;
- uint64_t borrow = 0;
- if (big_seed.IsNegative()) {
- // Negate bits to make seed positive.
- // Negate bits again (by xor with negate_mask) when extracted below,
- // to get original bits.
- negate_mask = 0xffffffffffffffffLL;
-
- // Instead of computing ~big_seed here, we compute it on the fly below as
- // follows: ~(-big_seed) == ~(~(big_seed-1)) == big_seed-1
- borrow = 1;
- }
- const intptr_t used = big_seed.Used();
- intptr_t digit = 0;
- do {
- uint64_t low64 = ((digit + 1) < used) ? big_seed.DigitAt(digit + 1) : 0;
- low64 <<= 32;
- low64 |= (digit < used) ? big_seed.DigitAt(digit) : 0;
- low64 -= borrow;
- if ((borrow == 1) && (low64 != 0xffffffffffffffffLL)) {
- borrow = 0;
- }
- low64 ^= negate_mask;
- seed = (seed * 1037) ^ mix64(low64);
- digit += 2;
- } while (digit < used);
- } else {
- seed = mix64(static_cast<uint64_t>(seed_int.AsInt64Value()));
- }
+ uint64_t seed = mix64(static_cast<uint64_t>(seed_int.AsInt64Value()));
if (seed == 0) {
seed = 0x5a17;
diff --git a/runtime/lib/math_patch.dart b/runtime/lib/math_patch.dart
index 8888042..ad400a4 100644
--- a/runtime/lib/math_patch.dart
+++ b/runtime/lib/math_patch.dart
@@ -116,7 +116,7 @@
result *= base;
}
exponent >>= 1;
- // Skip unnecessary operation (can overflow to Mint or Bigint).
+ // Skip unnecessary operation (can overflow to Mint).
if (exponent != 0) {
base *= base;
}
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index 639d6d8..902e7ff 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -793,7 +793,8 @@
List<ParameterMirror> _parameters;
List<ParameterMirror> get parameters {
if (_parameters == null) {
- _parameters = _FunctionTypeMirror_parameters(_functionReflectee);
+ _parameters = _FunctionTypeMirror_parameters(_functionReflectee)
+ .cast<ParameterMirror>();
_parameters = new UnmodifiableListView<ParameterMirror>(_parameters);
}
return _parameters;
diff --git a/runtime/lib/typed_data_patch.dart b/runtime/lib/typed_data_patch.dart
index b868a2d..b3aaf23 100644
--- a/runtime/lib/typed_data_patch.dart
+++ b/runtime/lib/typed_data_patch.dart
@@ -2501,7 +2501,7 @@
if (index < 0 || index >= length) {
throw new RangeError.index(index, this, "index");
}
- _setIndexedInt64(index, _toInt64(value));
+ _setIndexedInt64(index, value);
}
// Method(s) implementing the TypedData interface.
@@ -2548,7 +2548,7 @@
if (index < 0 || index >= length) {
throw new RangeError.index(index, this, "index");
}
- _setIndexedUint64(index, _toUint64(value));
+ _setIndexedUint64(index, value);
}
// Method(s) implementing the TypedData interface.
@@ -3066,7 +3066,7 @@
if (index < 0 || index >= length) {
throw new RangeError.index(index, this, "index");
}
- _setIndexedInt64(index, _toInt64(value));
+ _setIndexedInt64(index, value);
}
// Method(s) implementing the TypedData interface.
@@ -3104,7 +3104,7 @@
if (index < 0 || index >= length) {
throw new RangeError.index(index, this, "index");
}
- _setIndexedUint64(index, _toUint64(value));
+ _setIndexedUint64(index, value);
}
// Method(s) implementing the TypedData interface.
@@ -3867,7 +3867,7 @@
throw new RangeError.index(index, this, "index");
}
_typedData._setInt64(
- offsetInBytes + (index * Int64List.bytesPerElement), _toInt64(value));
+ offsetInBytes + (index * Int64List.bytesPerElement), value);
}
// Method(s) implementing TypedData interface.
@@ -3912,7 +3912,7 @@
throw new RangeError.index(index, this, "index");
}
_typedData._setUint64(
- offsetInBytes + (index * Uint64List.bytesPerElement), _toUint64(value));
+ offsetInBytes + (index * Uint64List.bytesPerElement), value);
}
// Method(s) implementing TypedData interface.
@@ -4444,25 +4444,6 @@
return value & 0xFFFFFFFF;
}
-// Note: in --limit-ints-to-64-bits mode all integers are 64-bit already.
-// Still, it is harmless to apply _uint64Mask because (1 << 64) is 0 (all bits
-// are shifted out), so _uint64Mask is -1 (its bit pattern is 0xffffffffffffffff).
-const _uint64Mask = (1 << 64) - 1;
-
-int _toInt64(int value) {
- // Avoid bigint mask when possible.
- return (ClassID.getID(value) == ClassID.cidBigint)
- ? _toInt(value, _uint64Mask)
- : value;
-}
-
-int _toUint64(int value) {
- // Avoid bigint mask when possible.
- return (ClassID.getID(value) == ClassID.cidBigint)
- ? _toInt(value, _uint64Mask)
- : value;
-}
-
void _rangeCheck(int listLength, int start, int length) {
if (length < 0) {
throw new RangeError.value(length);
diff --git a/runtime/lib/vmservice.cc b/runtime/lib/vmservice.cc
index fce6e21..d5092c7 100644
--- a/runtime/lib/vmservice.cc
+++ b/runtime/lib/vmservice.cc
@@ -356,7 +356,9 @@
delete[] data;
}
-static void FilenameFinalizer(void* peer) {
+static void FilenameFinalizer(void* isolate_callback_data,
+ Dart_WeakPersistentHandle handle,
+ void* peer) {
char* filename = reinterpret_cast<char*>(peer);
delete[] filename;
}
@@ -395,12 +397,13 @@
intptr_t idx = 0;
while (archive.HasMore()) {
char* filename = archive.NextFilename();
+ intptr_t filename_length = strlen(filename);
uint8_t* contents = archive.NextContent();
intptr_t contents_length = archive.NextContentLength();
Dart_Handle dart_filename = Dart_NewExternalLatin1String(
- reinterpret_cast<uint8_t*>(filename), strlen(filename), filename,
- FilenameFinalizer);
+ reinterpret_cast<uint8_t*>(filename), filename_length, filename,
+ filename_length, FilenameFinalizer);
ASSERT(!Dart_IsError(dart_filename));
Dart_Handle dart_contents = Dart_NewExternalTypedDataWithFinalizer(
diff --git a/runtime/observatory/BUILD.gn b/runtime/observatory/BUILD.gn
index 61ddc8f..af4db77 100644
--- a/runtime/observatory/BUILD.gn
+++ b/runtime/observatory/BUILD.gn
@@ -118,10 +118,42 @@
compress = true
}
+copy("copy_compressed_observatory_archive") {
+ archive_target = ":compressed_observatory_archive"
+ deps = [
+ archive_target,
+ ]
+ archive_dir = get_label_info(archive_target, "target_gen_dir")
+ archive_name = get_label_info(archive_target, "name")
+ archive_file = "${archive_dir}/${archive_name}.tar"
+ sources = [
+ archive_file,
+ ]
+ outputs = [
+ "$root_out_dir/${archive_name}.tar",
+ ]
+}
+
observatory_archive("observatory_archive") {
compress = false
}
+copy("copy_observatory_archive") {
+ archive_target = ":observatory_archive"
+ deps = [
+ archive_target,
+ ]
+ archive_dir = get_label_info(archive_target, "target_gen_dir")
+ archive_name = get_label_info(archive_target, "name")
+ archive_file = "${archive_dir}/${archive_name}.tar"
+ sources = [
+ archive_file,
+ ]
+ outputs = [
+ "$root_out_dir/${archive_name}.tar",
+ ]
+}
+
# Generates a .cc file containing the bytes of the observatory archive in a C
# array.
#
diff --git a/runtime/observatory/lib/src/debugger/debugger_location.dart b/runtime/observatory/lib/src/debugger/debugger_location.dart
index 9ba4bac..1904e43 100644
--- a/runtime/observatory/lib/src/debugger/debugger_location.dart
+++ b/runtime/observatory/lib/src/debugger/debugger_location.dart
@@ -75,8 +75,8 @@
if (colStr != null) {
colStr = colStr.substring(1);
}
- var line = int.parse(lineStr, onError: (_) => -1);
- var col = (colStr != null ? int.parse(colStr, onError: (_) => -1) : null);
+ var line = int.tryParse(lineStr) ?? -1;
+ var col = (colStr != null ? int.tryParse(colStr) ?? -1 : null);
if (line == -1) {
return new Future.value(
new DebuggerLocation.error("Line '${lineStr}' must be an integer"));
diff --git a/runtime/observatory/lib/src/elements/debugger.dart b/runtime/observatory/lib/src/elements/debugger.dart
index 5cc6896..5b15543 100644
--- a/runtime/observatory/lib/src/elements/debugger.dart
+++ b/runtime/observatory/lib/src/elements/debugger.dart
@@ -1008,7 +1008,7 @@
return new Future.value(null);
}
var arg = args[0].trim();
- var num = int.parse(arg, onError: (_) => null);
+ var num = int.tryParse(arg);
var candidate;
for (var isolate in debugger.vm.isolates) {
diff --git a/runtime/observatory/lib/src/elements/function_view.dart b/runtime/observatory/lib/src/elements/function_view.dart
index a829ded..93cc57c 100644
--- a/runtime/observatory/lib/src/elements/function_view.dart
+++ b/runtime/observatory/lib/src/elements/function_view.dart
@@ -58,7 +58,7 @@
M.IsolateRef _isolate;
M.EventRepository _events;
M.NotificationRepository _notifications;
- M.Function _function;
+ M.ServiceFunction _function;
M.LibraryRef _library;
M.FunctionRepository _functions;
M.ClassRepository _classes;
@@ -72,12 +72,12 @@
M.VMRef get vm => _vm;
M.IsolateRef get isolate => _isolate;
M.NotificationRepository get notifications => _notifications;
- M.Function get function => _function;
+ M.ServiceFunction get function => _function;
factory FunctionViewElement(
M.VM vm,
M.IsolateRef isolate,
- M.Function function,
+ M.ServiceFunction function,
M.EventRepository events,
M.NotificationRepository notifications,
M.FunctionRepository functions,
diff --git a/runtime/observatory/lib/src/elements/heap_map.dart b/runtime/observatory/lib/src/elements/heap_map.dart
index a5545d0..b2f7f81 100644
--- a/runtime/observatory/lib/src/elements/heap_map.dart
+++ b/runtime/observatory/lib/src/elements/heap_map.dart
@@ -223,9 +223,7 @@
final address = _objectAt(event.offset).address.toRadixString(16);
isolate.getObjectByAddress(address).then((result) {
if (result.type != 'Sentinel') {
- new AnchorElement(
- href: Uris.inspect(_isolate, object: result as S.HeapObject))
- .click();
+ new AnchorElement(href: Uris.inspect(_isolate, object: result)).click();
}
});
}
diff --git a/runtime/observatory/lib/src/elements/isolate_view.dart b/runtime/observatory/lib/src/elements/isolate_view.dart
index edcc6e8..e199135 100644
--- a/runtime/observatory/lib/src/elements/isolate_view.dart
+++ b/runtime/observatory/lib/src/elements/isolate_view.dart
@@ -65,7 +65,7 @@
M.LibraryRepository _libraries;
M.ObjectRepository _objects;
M.EvalRepository _eval;
- M.Function _function;
+ M.ServiceFunction _function;
M.ScriptRef _rootScript;
StreamSubscription _subscription;
diff --git a/runtime/observatory/lib/src/elements/timeline_page.dart b/runtime/observatory/lib/src/elements/timeline_page.dart
index a751329..608a789 100644
--- a/runtime/observatory/lib/src/elements/timeline_page.dart
+++ b/runtime/observatory/lib/src/elements/timeline_page.dart
@@ -78,6 +78,9 @@
IFrameElement _frame;
DivElement _content;
+ bool get usingVMRecorder =>
+ _recorder.name != "Fuchsia" && _recorder.name != "Systrace";
+
void render() {
if (_frame == null) {
_frame = new IFrameElement()..src = 'timeline.html';
@@ -125,44 +128,85 @@
]
])
];
- if (children.isEmpty) {
- children = [
- navBar([
- new NavTopMenuElement(queue: _r.queue),
- new NavVMMenuElement(vm, _events, queue: _r.queue),
- navMenu('timeline', link: Uris.timeline()),
- new NavRefreshElement(queue: _r.queue)
- ..onRefresh.listen((e) async {
- e.element.disabled = true;
- await _refresh();
- e.element.disabled = false;
- }),
- new NavRefreshElement(label: 'clear', queue: _r.queue)
- ..onRefresh.listen((e) async {
- e.element.disabled = true;
- await _clear();
- e.element.disabled = false;
- }),
- new NavRefreshElement(label: 'save', queue: _r.queue)
- ..onRefresh.listen((e) async {
- e.element.disabled = true;
- await _save();
- e.element.disabled = false;
- }),
- new NavRefreshElement(label: 'load', queue: _r.queue)
- ..onRefresh.listen((e) async {
- e.element.disabled = true;
- await _load();
- e.element.disabled = false;
- }),
- new NavNotifyElement(_notifications, queue: _r.queue)
- ]),
- _content,
- new DivElement()
- ..classes = ['iframe']
- ..children = [_frame]
- ];
+
+ children = [
+ navBar([
+ new NavTopMenuElement(queue: _r.queue),
+ new NavVMMenuElement(vm, _events, queue: _r.queue),
+ navMenu('timeline', link: Uris.timeline()),
+ new NavRefreshElement(queue: _r.queue)
+ ..onRefresh.listen((e) async {
+ e.element.disabled = true;
+ await _refresh();
+ e.element.disabled = !usingVMRecorder;
+ }),
+ new NavRefreshElement(label: 'clear', queue: _r.queue)
+ ..onRefresh.listen((e) async {
+ e.element.disabled = true;
+ await _clear();
+ e.element.disabled = !usingVMRecorder;
+ }),
+ new NavRefreshElement(label: 'save', queue: _r.queue)
+ ..onRefresh.listen((e) async {
+ e.element.disabled = true;
+ await _save();
+ e.element.disabled = !usingVMRecorder;
+ }),
+ new NavRefreshElement(label: 'load', queue: _r.queue)
+ ..onRefresh.listen((e) async {
+ e.element.disabled = true;
+ await _load();
+ e.element.disabled = !usingVMRecorder;
+ }),
+ new NavNotifyElement(_notifications, queue: _r.queue)
+ ]),
+ _content,
+ _createIFrameOrMessage(),
+ ];
+ }
+
+ HtmlElement _createIFrameOrMessage() {
+ if (_recorder == null) {
+ return new DivElement()
+ ..classes = ['content-centered-big']
+ ..text = 'Loading...';
}
+
+ if (_recorder.name == "Fuchsia") {
+ return new DivElement()
+ ..classes = ['content-centered-big']
+ ..children = [
+ new BRElement(),
+ new SpanElement()
+ ..text =
+ "This VM is forwarding timeline events to Fuchsia's system tracing. See the ",
+ new AnchorElement()
+ ..text = "Fuchsia Tracing Usage Guide"
+ ..href =
+ "https://fuchsia.googlesource.com/garnet/+/master/docs/tracing_usage_guide.md",
+ new SpanElement()..text = ".",
+ ];
+ }
+
+ if (_recorder.name == "Systrace") {
+ return new DivElement()
+ ..classes = ['content-centered-big']
+ ..children = [
+ new BRElement(),
+ new SpanElement()
+ ..text =
+ "This VM is forwarding timeline events to Android's systrace. See the ",
+ new AnchorElement()
+ ..text = "systrace usage guide"
+ ..href =
+ "https://developer.android.com/studio/command-line/systrace",
+ new SpanElement()..text = ".",
+ ];
+ }
+
+ return new DivElement()
+ ..classes = ['iframe']
+ ..children = [_frame];
}
List<Element> _createProfileSelect() {
@@ -202,6 +246,9 @@
Future _postMessage(String method,
[Map<String, dynamic> params = const <String, dynamic>{}]) async {
+ if (_frame.contentWindow == null) {
+ return null;
+ }
var message = {'method': method, 'params': params};
_frame.contentWindow
.postMessage(json.encode(message), window.location.href);
diff --git a/runtime/observatory/lib/src/models/objects/function.dart b/runtime/observatory/lib/src/models/objects/function.dart
index 0d4a997..904038d 100644
--- a/runtime/observatory/lib/src/models/objects/function.dart
+++ b/runtime/observatory/lib/src/models/objects/function.dart
@@ -75,7 +75,7 @@
FunctionKind get kind;
}
-abstract class Function extends Object implements FunctionRef {
+abstract class ServiceFunction extends Object implements FunctionRef {
/// The location of this function in the source code. [optional]
SourceLocation get location;
diff --git a/runtime/observatory/lib/src/models/repositories/function.dart b/runtime/observatory/lib/src/models/repositories/function.dart
index 38b7cc4..56298d7 100644
--- a/runtime/observatory/lib/src/models/repositories/function.dart
+++ b/runtime/observatory/lib/src/models/repositories/function.dart
@@ -5,5 +5,5 @@
part of models;
abstract class FunctionRepository {
- Future<Function> get(IsolateRef isolate, String id);
+ Future<ServiceFunction> get(IsolateRef isolate, String id);
}
diff --git a/runtime/observatory/lib/src/repositories/function.dart b/runtime/observatory/lib/src/repositories/function.dart
index 5906a2a..68527c5 100644
--- a/runtime/observatory/lib/src/repositories/function.dart
+++ b/runtime/observatory/lib/src/repositories/function.dart
@@ -5,7 +5,7 @@
part of repositories;
class FunctionRepository extends M.FunctionRepository {
- Future<M.Function> get(M.IsolateRef i, String id) async {
+ Future<M.ServiceFunction> get(M.IsolateRef i, String id) async {
S.Isolate isolate = i as S.Isolate;
assert(isolate != null);
return (await isolate.getObject(id)) as S.ServiceFunction;
diff --git a/runtime/observatory/lib/src/repositories/target.dart b/runtime/observatory/lib/src/repositories/target.dart
index 35d0dde..56c6246 100644
--- a/runtime/observatory/lib/src/repositories/target.dart
+++ b/runtime/observatory/lib/src/repositories/target.dart
@@ -117,7 +117,7 @@
final Uri wsAddress = new Uri(
scheme: 'ws',
host: host ?? serverAddress.host,
- port: int.parse(port ?? '', onError: (_) => serverAddress.port),
+ port: int.tryParse(port ?? '') ?? serverAddress.port,
path: '/ws',
);
return wsAddress.toString();
diff --git a/runtime/observatory/lib/src/sample_profile/sample_profile.dart b/runtime/observatory/lib/src/sample_profile/sample_profile.dart
index e2f71e2..a06e5e7 100644
--- a/runtime/observatory/lib/src/sample_profile/sample_profile.dart
+++ b/runtime/observatory/lib/src/sample_profile/sample_profile.dart
@@ -236,8 +236,7 @@
CallTreeNode _findInChildren(CallTreeNode current, CallTreeNode needle) {
for (var child in current.children) {
- if ((child as CallTreeNode).profileData ==
- (needle as CallTreeNode).profileData) {
+ if ((child as CallTreeNode).profileData == needle.profileData) {
return child;
}
}
@@ -332,8 +331,8 @@
new FunctionCallTree(
tree.inclusive,
new FunctionCallTreeNode(
- (tree.root as CallTreeNode).profileData,
- (tree.root as CallTreeNode).count,
+ tree.root.profileData,
+ tree.root.count,
tree.root.inclusiveNativeAllocations,
tree.root.exclusiveNativeAllocations)));
@@ -444,7 +443,7 @@
_markFunctionCalls() {
for (var child in root.children) {
- _markFunctionCallsInner(null, child as FunctionCallTreeNode);
+ _markFunctionCallsInner(null, child);
}
}
}
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index 58503e1..ace655c 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -46,6 +46,9 @@
static const kIsolateIsReloading = 108;
static const kIsolateReloadBarred = 109;
static const kIsolateMustHaveReloaded = 110;
+ static const kServiceAlreadyRegistered = 111;
+ static const kServiceDisappeared = 112;
+ static const kExpressionCompilationError = 113;
static const kFileSystemAlreadyExists = 1001;
static const kFileSystemDoesNotExist = 1002;
@@ -1624,7 +1627,7 @@
void _update(Map map, bool mapIsRef) {
name = map['name'];
vmName = map.containsKey('_vmName') ? map['_vmName'] : name;
- number = int.parse(map['number'], onError: (_) => null);
+ number = int.tryParse(map['number']);
if (mapIsRef) {
return;
}
@@ -1632,7 +1635,7 @@
loading = false;
runnable = map['runnable'] == true;
_upgradeCollection(map, isolate);
- originNumber = int.parse(map['_originNumber'], onError: (_) => null);
+ originNumber = int.tryParse(map['_originNumber']);
rootLibrary = map['rootLib'];
if (map['entry'] != null) {
entry = map['entry'];
@@ -1904,7 +1907,7 @@
}
Future<ServiceObject> evalFrame(int frameIndex, String expression,
- {Map<String, ServiceObject> scope}) {
+ {Map<String, ServiceObject> scope}) async {
Map params = {
'frameIndex': frameIndex,
'expression': expression,
@@ -1916,7 +1919,22 @@
});
params["scope"] = scopeWithIds;
}
- return invokeRpc('evaluateInFrame', params);
+
+ try {
+ return await invokeRpc('evaluateInFrame', params);
+ } on ServerRpcException catch (error) {
+ if (error.code == ServerRpcException.kExpressionCompilationError) {
+ Map map = {
+ 'type': 'Error',
+ 'message': error.data.toString(),
+ 'kind': 'LanguageError',
+ 'exception': null,
+ 'stacktrace': null,
+ };
+ return new ServiceObject._fromMap(null, map);
+ } else
+ rethrow;
+ }
}
Future<ServiceObject> getReachableSize(ServiceObject target) {
@@ -2035,8 +2053,9 @@
}
/// A [ServiceObject] which implements [Map].
-class ServiceMap extends ServiceObject implements Map, M.UnknownObjectRef {
- final Map _map = {};
+class ServiceMap extends ServiceObject
+ implements Map<String, dynamic>, M.UnknownObjectRef {
+ final Map<String, dynamic> _map = {};
static String objectIdRingPrefix = 'objects/';
bool get immutable => false;
@@ -2074,7 +2093,7 @@
operator []=(k, v) => _map[k] = v;
bool get isEmpty => _map.isEmpty;
bool get isNotEmpty => _map.isNotEmpty;
- Iterable get keys => _map.keys;
+ Iterable<String> get keys => _map.keys;
Iterable get values => _map.values;
int get length => _map.length;
@@ -3098,7 +3117,7 @@
throw new FallThroughError();
}
-class ServiceFunction extends HeapObject implements M.Function {
+class ServiceFunction extends HeapObject implements M.ServiceFunction {
// owner is a Library, Class, or ServiceFunction.
M.ObjectRef dartOwner;
Library library;
@@ -3599,7 +3618,7 @@
library = map['library'];
}
- void _parseTokenPosTable(List/*<List<int>>*/ table) {
+ void _parseTokenPosTable(List table) {
if (table == null) {
return;
}
@@ -3609,14 +3628,14 @@
lastTokenPos = null;
var lineSet = new Set();
- for (var line in table) {
+ for (List line in table) {
// Each entry begins with a line number...
- var lineNumber = line[0];
+ int lineNumber = line[0];
lineSet.add(lineNumber);
for (var pos = 1; pos < line.length; pos += 2) {
// ...and is followed by (token offset, col number) pairs.
- var tokenOffset = line[pos];
- var colNumber = line[pos + 1];
+ int tokenOffset = line[pos];
+ int colNumber = line[pos + 1];
if (firstTokenPos == null) {
// Mark first token position.
firstTokenPos = tokenOffset;
@@ -4409,7 +4428,7 @@
}
}
- void _processDescriptors(List/*<Map>*/ descriptors) {
+ void _processDescriptors(List descriptors) {
for (Map descriptor in descriptors) {
var pcOffset = int.parse(descriptor['pcOffset'], radix: 16);
var address = startAddress + pcOffset;
@@ -4569,7 +4588,7 @@
String toString() => "ServiceMetric($_id)";
}
-Future<Null> printFrames(List/*<Frame>*/ frames) async {
+Future<Null> printFrames(List frames) async {
for (int i = 0; i < frames.length; i++) {
final Frame frame = frames[i];
String frameText = await frame.toUserString();
diff --git a/runtime/observatory/tests/observatory_ui/mocks/objects/function.dart b/runtime/observatory/tests/observatory_ui/mocks/objects/function.dart
index 7733e1d..bbe2c28 100644
--- a/runtime/observatory/tests/observatory_ui/mocks/objects/function.dart
+++ b/runtime/observatory/tests/observatory_ui/mocks/objects/function.dart
@@ -21,7 +21,7 @@
this.kind});
}
-class FunctionMock implements M.Function {
+class FunctionMock implements M.ServiceFunction {
final String id;
final String name;
final M.ClassRef clazz;
diff --git a/runtime/observatory/tests/service/async_single_step_out_test.dart b/runtime/observatory/tests/service/async_single_step_out_test.dart
index 5f0777f..7da09fb 100644
--- a/runtime/observatory/tests/service/async_single_step_out_test.dart
+++ b/runtime/observatory/tests/service/async_single_step_out_test.dart
@@ -1,7 +1,7 @@
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// VMOptions=--error_on_bad_type --error_on_bad_override --verbose_debug --async_debugger
+// VMOptions=--error_on_bad_type --error_on_bad_override --verbose_debug --async_debugger --no-sync-async
import 'dart:developer';
import 'service_test_common.dart';
diff --git a/runtime/observatory/tests/service/bad_reload_test.dart b/runtime/observatory/tests/service/bad_reload_test.dart
index 23927e9..660e683 100644
--- a/runtime/observatory/tests/service/bad_reload_test.dart
+++ b/runtime/observatory/tests/service/bad_reload_test.dart
@@ -66,9 +66,9 @@
);
// Observe that it failed.
expect(response['success'], isFalse);
- List/*<Map<String, dynamic>>*/ notices = response['details']['notices'];
+ List notices = response['details']['notices'];
expect(notices.length, equals(1));
- Map/*<String, dynamic>*/ reasonForCancelling = notices[0];
+ Map<String, dynamic> reasonForCancelling = notices[0];
expect(reasonForCancelling['type'], equals('ReasonForCancelling'));
expect(reasonForCancelling['message'], contains('library_isnt_here_man'));
diff --git a/runtime/observatory/tests/service/eval_internal_class_test.dart b/runtime/observatory/tests/service/eval_internal_class_test.dart
index 3027965..0e7beb1 100644
--- a/runtime/observatory/tests/service/eval_internal_class_test.dart
+++ b/runtime/observatory/tests/service/eval_internal_class_test.dart
@@ -15,14 +15,14 @@
dynamic result = await classLibrary.evaluate('3 + 4');
print(result);
expect(result is DartError, isTrue);
- expect(result.message, contains('Cannot evaluate'));
+ expect(result.message, contains('can be evaluated only'));
Class classClass = await classLibrary.clazz.load();
print(classClass);
result = await classClass.evaluate('3 + 4');
print(result);
expect(result is DartError, isTrue);
- expect(result.message, contains('Cannot evaluate'));
+ expect(result.message, contains('can be evaluated only'));
Instance someArray = await root.evaluate("new List(2)");
print(someArray);
diff --git a/runtime/observatory/tests/service/evaluate_in_frame_with_scope_test.dart b/runtime/observatory/tests/service/evaluate_in_frame_with_scope_test.dart
index bb8cd78..ade53db 100644
--- a/runtime/observatory/tests/service/evaluate_in_frame_with_scope_test.dart
+++ b/runtime/observatory/tests/service/evaluate_in_frame_with_scope_test.dart
@@ -45,21 +45,26 @@
var thing2 = thing2Field.staticValue;
print(thing2);
- Instance result = await isolate.evalFrame(0, "x + y + a + b",
+ final isInstanceOf<Instance> isInstanceOfInstance =
+ new isInstanceOf<Instance>();
+ ServiceObject result = await isolate.evalFrame(0, "x + y + a + b",
scope: <String, ServiceObject>{"a": thing1, "b": thing2});
+ expect(result, isInstanceOfInstance);
print(result);
- expect(result.valueAsString, equals('2033'));
+ expect((result as Instance).valueAsString, equals('2033'));
result = await isolate.evalFrame(0, "local + a + b",
scope: <String, ServiceObject>{"a": thing1, "b": thing2});
+ expect(result, isInstanceOfInstance);
print(result);
- expect(result.valueAsString, equals('2033'));
+ expect((result as Instance).valueAsString, equals('2033'));
// Note the eval's scope is shadowing the locals' scope.
result = await isolate.evalFrame(0, "x + y",
scope: <String, ServiceObject>{"x": thing1, "y": thing2});
+ expect(result, isInstanceOfInstance);
print(result);
- expect(result.valueAsString, equals('7'));
+ expect((result as Instance).valueAsString, equals('7'));
bool didThrow = false;
try {
diff --git a/runtime/observatory/tests/service/external_service_disappear_test.dart b/runtime/observatory/tests/service/external_service_disappear_test.dart
index 9e9931e..7f39fad 100644
--- a/runtime/observatory/tests/service/external_service_disappear_test.dart
+++ b/runtime/observatory/tests/service/external_service_disappear_test.dart
@@ -32,7 +32,7 @@
final client = _socket.map(_decoder).asBroadcastStream();
// Note: keep this in sync with sdk/lib/vmservice.dart
- const kServiceDisappeared = 111;
+ const kServiceDisappeared = 112;
const kServiceDisappeared_Msg = 'Service has disappeared';
const serviceName = 'disapearService';
diff --git a/runtime/observatory/tests/service/external_service_registration_test.dart b/runtime/observatory/tests/service/external_service_registration_test.dart
index 083c6d6..3b6cfa0 100644
--- a/runtime/observatory/tests/service/external_service_registration_test.dart
+++ b/runtime/observatory/tests/service/external_service_registration_test.dart
@@ -35,7 +35,7 @@
final client = _socket.map(_decoder).asBroadcastStream();
// Note: keep this in sync with sdk/lib/vmservice.dart
- const kServiceAlreadyRegistered = 110;
+ const kServiceAlreadyRegistered = 111;
const kServiceAlreadyRegistered_Msg = 'Service already registered';
const serviceName = 'serviceName';
diff --git a/runtime/observatory/tests/service/external_service_registration_via_notification_test.dart b/runtime/observatory/tests/service/external_service_registration_via_notification_test.dart
index 11d478e..846f28b 100644
--- a/runtime/observatory/tests/service/external_service_registration_via_notification_test.dart
+++ b/runtime/observatory/tests/service/external_service_registration_via_notification_test.dart
@@ -35,7 +35,7 @@
final client = _socket.map(_decoder).asBroadcastStream();
// Note: keep this in sync with sdk/lib/vmservice.dart
- const kServiceAlreadyRegistered = 110;
+ const kServiceAlreadyRegistered = 111;
const kServiceAlreadyRegistered_Msg = 'Service already registered';
const serviceName = 'serviceName';
diff --git a/runtime/observatory/tests/service/get_version_rpc_test.dart b/runtime/observatory/tests/service/get_version_rpc_test.dart
index 3fb4084..e6aea8a 100644
--- a/runtime/observatory/tests/service/get_version_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_version_rpc_test.dart
@@ -13,7 +13,7 @@
var result = await vm.invokeRpcNoUpgrade('getVersion', {});
expect(result['type'], equals('Version'));
expect(result['major'], equals(3));
- expect(result['minor'], equals(8));
+ expect(result['minor'], equals(9));
expect(result['_privateMajor'], equals(0));
expect(result['_privateMinor'], equals(0));
},
diff --git a/runtime/observatory/tests/service/service.status b/runtime/observatory/tests/service/service.status
index 8a40809..aa06e10 100644
--- a/runtime/observatory/tests/service/service.status
+++ b/runtime/observatory/tests/service/service.status
@@ -16,6 +16,8 @@
process_service_test: Pass, Fail # Issue 24344
[ $compiler == app_jit ]
+async_step_out_test: RuntimeError # Issue 29158, Async debugging
+awaiter_async_stack_contents_test: RuntimeError # Issue 29158, Async debugging
bad_reload_test: RuntimeError # Issue 27806
complex_reload_test: RuntimeError # Issue 27806
debugger_location_second_test: Skip # Issue 28180
@@ -28,6 +30,8 @@
next_through_for_each_loop_test: RuntimeError # Snapshots don't include source and generated source is not 1-to-1. The column offsets are thus off.
next_through_implicit_call_test: RuntimeError # Snapshots don't include source and generated source is not 1-to-1. The column offsets are thus off.
pause_on_unhandled_async_exceptions2_test: Pass, RuntimeError, Timeout, Crash # Issue 29178
+regress_28980_test: RuntimeError # Issue 29158, Async debugging
+set_library_debuggable_test: RuntimeError # Issue 29158, Async debugging
set_name_rpc_test: RuntimeError # Issue 27806
step_through_constructor_calls_test: RuntimeError # Snapshots don't include source and generated source is not 1-to-1. The column offsets are thus off.
step_through_function_test: RuntimeError # Snapshots don't include source and generated source is not 1-to-1. The column offsets are thus off.
@@ -62,6 +66,9 @@
dev_fs_http_put_weird_char_test: Skip # Windows disallows carriage returns in paths
dev_fs_weird_char_test: Skip # Windows disallows question mark in paths
+[ $builder_tag == optimization_counter_threshold && $compiler != dartk ]
+pause_on_unhandled_async_exceptions_test: Pass, RuntimeError # Issue 33365
+
[ $compiler == dart2analyzer && $strong ]
*: Skip # Issue 28649
@@ -78,8 +85,12 @@
*: Skip
[ ($compiler == none || $compiler == precompiler) && ($runtime == dart_precompiled || $runtime == vm) ]
+async_step_out_test: RuntimeError # Issue 29158, Async debugging
+awaiter_async_stack_contents_test: RuntimeError # Issue 29158, Async debugging
evaluate_activation_test/instance: RuntimeError # http://dartbug.com/20047
evaluate_activation_test/scope: RuntimeError # http://dartbug.com/20047
+regress_28980_test: RuntimeError # Issue 29158, Async debugging
+set_library_debuggable_test: RuntimeError # Issue 29158, Async debugging
[ $arch != ia32 || $arch != x64 || $system != linux ]
get_native_allocation_samples_test: Skip # Unsupported.
diff --git a/runtime/observatory/tests/service/service_kernel.status b/runtime/observatory/tests/service/service_kernel.status
index afebf2f..fd0455f 100644
--- a/runtime/observatory/tests/service/service_kernel.status
+++ b/runtime/observatory/tests/service/service_kernel.status
@@ -156,6 +156,7 @@
break_on_default_constructor_test: Skip # Issues 32137 and 32138.
coverage_leaf_function_test: RuntimeError
coverage_optimized_function_test: Skip # Timeout
+field_script_test: Skip # Timeout
get_source_report_test: RuntimeError
get_vm_timeline_rpc_test: Skip # Issue 32137.
issue_25465_test: Skip # Issues 32137 and 32138.
@@ -166,6 +167,7 @@
next_through_call_on_field_test: Skip # Issues 32137 and 32138.
next_through_catch_test: Skip # Issues 32137 and 32138.
next_through_create_list_and_map_test: Skip # Issues 32137 and 32138.
+next_through_for_loop_with_break_and_continue_test: Skip # Timeout
next_through_function_expression_test: Skip # Issues 32137 and 32138.
next_through_is_and_as_test: Skip # Issues 32137 and 32138.
next_through_multi_catch_test: Skip # Issues 32137 and 32138.
@@ -180,7 +182,7 @@
reload_sources_test: RuntimeError
set_vm_name_rpc_test: Skip # Times out. Issue 32137.
step_test: Skip # Issues 32137 and 32138.
-step_through_constructor_test: Pass, Slow
+step_through_constructor_test: Skip # Timeout
step_through_function_2_test: Skip # Issues 32137 and 32138.
step_through_function_test: Skip # Issues 32137 and 32138.
step_through_property_get_test: Skip # Times out. Issue 32137.
@@ -190,23 +192,28 @@
[ $compiler == dartk && $system == windows && $strong ]
add_breakpoint_rpc_kernel_test: Skip # Timeout
+breakpoint_in_parts_class_test: Skip # Timeout
code_test: RuntimeError
get_object_rpc_test: RuntimeError
get_stack_rpc_test: RuntimeError
+next_through_call_on_static_field_in_class_test: Skip # Timeout
+next_through_closure_test: Skip # Timeout
+next_through_for_each_loop_test: Skip # Timeout
next_through_implicit_call_test: Skip # Timeout
+next_through_new_test: Skip # Timeout
next_through_operator_bracket_on_super_test: Skip # Timeout
next_through_operator_bracket_on_this_test: Skip # Timeout
next_through_operator_bracket_test: Skip # Timeout
next_through_simple_async_test: Skip # Timeout
+pause_on_start_and_exit_with_child_test: Skip # Timeout
step_through_constructor_calls_test: Skip # Timeout
+step_through_getter_test: Skip # Timeout
step_through_property_set_test: Skip # Timeout
[ $compiler == dartk && $system == windows && !$strong ]
code_test: RuntimeError
-field_script_test: Skip # Timeout
get_object_rpc_test: RuntimeError
get_stack_rpc_test: RuntimeError
-next_through_for_loop_with_break_and_continue_test: Skip # Timeout
next_through_simple_async_test: Skip # Timeout
step_test: Skip # Timeout
step_through_constructor_test: Skip # Timeout
diff --git a/runtime/observatory/tests/service/service_test_common.dart b/runtime/observatory/tests/service/service_test_common.dart
index 71eea66..bf3dca8 100644
--- a/runtime/observatory/tests/service/service_test_common.dart
+++ b/runtime/observatory/tests/service/service_test_common.dart
@@ -116,7 +116,8 @@
(event.breakpoint == syntheticBreakpoint);
if (isAdd) {
syntheticBreakpoint = event.breakpoint;
- } else if (isResume) {} else if (isPaused) {
+ } else if (isResume) {
+ } else if (isPaused) {
pausedAtSyntheticBreakpoint.complete(isolate);
syntheticBreakpoint = null;
cancelSubscription();
@@ -269,7 +270,7 @@
ServiceMap stack = await isolate.getStack();
expect(stack.type, equals('Stack'));
- List/*<Frame>*/ frames = stack['frames'];
+ List frames = stack['frames'];
expect(frames.length, greaterThanOrEqualTo(1));
Frame top = frames[0];
@@ -297,10 +298,10 @@
ServiceMap stack = await isolate.getStack();
expect(stack.type, equals('Stack'));
- List/*<Frame>*/ frames = stack['frames'];
+ List frames = stack['frames'];
expect(frames.length, greaterThanOrEqualTo(1));
- Frame topFrame = stack['frames'][0];
+ Frame topFrame = frames[0];
ServiceFunction function = await topFrame.function.load();
String name = function.name;
if (includeOwner) {
@@ -315,7 +316,7 @@
sb.write("Expected to be in function $functionName but "
"actually in function $name");
sb.write("\nFull stack trace:\n");
- for (Frame f in stack['frames']) {
+ for (Frame f in frames) {
await f.function.load();
await (f.function.dartOwner as ServiceObject).load();
String name = f.function.name;
@@ -444,7 +445,7 @@
// We are paused: Resume after recording.
ServiceMap stack = await isolate.getStack();
expect(stack.type, equals('Stack'));
- List/*<Frame>*/ frames = stack['frames'];
+ List frames = stack['frames'];
expect(frames.length, greaterThanOrEqualTo(2));
Frame frame = frames[0];
String brokeAt = await frame.location.toUserString();
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index df6a616..d129fcb 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -67,6 +67,8 @@
cc/IsolateReload_KernelIncrementalCompileGenerics: SkipByDesign
cc/Mixin_PrivateSuperResolution: Skip
cc/Mixin_PrivateSuperResolutionCrossLibraryShouldFail: Skip
+dart/appjit_determinism_test: Pass, Fail # Issue 31427 - Lingering non-determinism.
+dart/script_determinism_test: Pass, Fail # Issue 31427 - Lingering non-determinism.
[ $compiler == fasta ]
dart/data_uri_import_test/badencodeddate: CompileTimeError
@@ -128,6 +130,7 @@
[ $arch == x64 && $compiler == dartk && $system == windows && $strong ]
cc/Profiler_BasicSourcePosition: Fail # http://dartbug.com/33224
+cc/Profiler_CodeTicks: Fail # dartbug.com/33337
[ $arch == x64 && $system == windows ]
cc/Profiler_BinaryOperatorSourcePositionOptimized: Pass, Fail # Issue 31137
@@ -353,10 +356,6 @@
cc/StandaloneSnapshotSize: SkipByDesign # Imports dart:mirrors
dart/redirection_type_shuffling_test: SkipByDesign # Imports dart:mirrors
-[ $system == windows || $checked ]
-dart/appjit_determinism_test: Skip # Issue 31427 - Lingering non-determinism in checked mode and Windows.
-dart/script_determinism_test: Skip # Issue 31427 - Lingering non-determinism in checked mode and Windows.
-
[ $hot_reload || $hot_reload_rollback ]
dart/appjit_determinism_test: Skip # Reload affects determinisim
dart/script_determinism_test: Skip # We can shutdown an isolate before it reloads.
diff --git a/runtime/vm/ast_printer.cc b/runtime/vm/ast_printer.cc
index 62b9a3b..f9b190e 100644
--- a/runtime/vm/ast_printer.cc
+++ b/runtime/vm/ast_printer.cc
@@ -124,11 +124,12 @@
String::Handle(variable->type().Name()).ToCString(),
variable->name().ToCString());
if (variable->HasIndex()) {
+ const int index = variable->index().value();
if (variable->is_captured()) {
logger_->Print(" (context %d %d)", variable->owner()->context_level(),
- variable->index());
+ index);
} else {
- logger_->Print(" (stack %d)", variable->index());
+ logger_->Print(" (stack %d)", index);
}
}
}
@@ -415,7 +416,7 @@
logger_->Print(" alias");
}
if (var->HasIndex()) {
- logger_->Print(" @%d", var->index());
+ logger_->Print(" @%d", var->index().value());
if (var->is_captured()) {
logger_->Print(" ctx %d", var->owner()->context_level());
}
@@ -484,7 +485,7 @@
logger_->Print(" =%s", default_parameter_value.ToCString());
}
if (param->HasIndex()) {
- logger_->Print(" @%d", param->index());
+ logger_->Print(" @%d", param->index().value());
if (param->is_captured()) {
logger_->Print(" ctx %d", param->owner()->context_level());
}
diff --git a/runtime/vm/ast_printer_test.cc b/runtime/vm/ast_printer_test.cc
index 128317a..7f73a8d 100644
--- a/runtime/vm/ast_printer_test.cc
+++ b/runtime/vm/ast_printer_test.cc
@@ -19,7 +19,7 @@
LocalVariable* v = new LocalVariable(
kPos, kPos, String::ZoneHandle(Symbols::New(thread, "wurscht")),
Type::ZoneHandle(Type::DynamicType()));
- v->set_index(5);
+ v->set_index(VariableIndex(5));
AstPrinter ast_printer;
LoadLocalNode* ll = new LoadLocalNode(kPos, v);
ReturnNode* r = new ReturnNode(kPos, ll);
diff --git a/runtime/vm/ast_test.cc b/runtime/vm/ast_test.cc
index 2ade4e7..302c1d9 100644
--- a/runtime/vm/ast_test.cc
+++ b/runtime/vm/ast_test.cc
@@ -22,17 +22,17 @@
EXPECT(!ll->IsLiteralNode());
LoadLocalNode* lln = ll->AsLoadLocalNode();
EXPECT(NULL != lln);
- v->set_index(1);
- EXPECT_EQ(1, v->index());
+ v->set_index(VariableIndex(1));
+ EXPECT_EQ(1, v->index().value());
LocalVariable* p =
new LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
String::ZoneHandle(Symbols::New(thread, "p")),
Type::ZoneHandle(Type::DynamicType()));
EXPECT(!p->HasIndex());
- p->set_index(-1);
+ p->set_index(VariableIndex(-1));
EXPECT(p->HasIndex());
- EXPECT_EQ(-1, p->index());
+ EXPECT_EQ(-1, p->index().value());
ReturnNode* r = new ReturnNode(TokenPosition::kNoSource, lln);
EXPECT_EQ(lln, r->value());
diff --git a/runtime/vm/base64.cc b/runtime/vm/base64.cc
new file mode 100644
index 0000000..60e919d
--- /dev/null
+++ b/runtime/vm/base64.cc
@@ -0,0 +1,75 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/base64.h"
+
+#include "vm/os.h"
+
+namespace dart {
+
+// Taken from lib/_http/crypto.dart
+
+// Lookup table used for finding Base 64 alphabet index of a given byte.
+// -2 : Outside Base 64 alphabet.
+// -1 : '\r' or '\n'
+// 0 : = (Padding character).
+// >0 : Base 64 alphabet index of given byte.
+static const int8_t decode_table[] = {
+ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -2, -2, -1, -2, -2, //
+ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, //
+ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 62, -2, 62, -2, 63, //
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -2, -2, -2, 00, -2, -2, //
+ -2, 00, 01, 02, 03, 04, 05, 06, 07, 8, 9, 10, 11, 12, 13, 14, //
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -2, -2, -2, -2, 63, //
+ -2, 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, -2, -2, -2, -2, -2, //
+ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, //
+ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, //
+ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, //
+ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, //
+ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, //
+ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, //
+ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, //
+ -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2};
+
+static const char PAD = '=';
+
+uint8_t* DecodeBase64(Zone* zone, const char* str, intptr_t* out_decoded_len) {
+ intptr_t len = strlen(str);
+ if (len == 0 || (len % 4 != 0)) {
+ return nullptr;
+ }
+
+ int pad_length = 0;
+ for (intptr_t i = len - 1; i >= 0; i--) {
+ const uint8_t current_code_unit = str[i];
+ if (decode_table[current_code_unit] > 0) break;
+ if (current_code_unit == PAD) pad_length++;
+ }
+ intptr_t decoded_en = ((len * 6) >> 3) - pad_length;
+ uint8_t* bytes = zone->Alloc<uint8_t>(decoded_en);
+
+ for (int i = 0, o = 0; o < decoded_en;) {
+ // Accumulate 4 valid 6 bit Base 64 characters into an int.
+ int x = 0;
+ for (int j = 4; j > 0;) {
+ int c = decode_table[(uint8_t)str[i++]];
+ if (c >= 0) {
+ x = ((x << 6) & 0xFFFFFF) | c;
+ j--;
+ }
+ }
+ bytes[o++] = x >> 16;
+ if (o < decoded_en) {
+ bytes[o++] = (x >> 8) & 0xFF;
+ if (o < decoded_en) bytes[o++] = x & 0xFF;
+ }
+ }
+ if (out_decoded_len != nullptr) {
+ *out_decoded_len = decoded_en;
+ }
+ return bytes;
+}
+
+} // namespace dart
diff --git a/runtime/vm/base64.h b/runtime/vm/base64.h
new file mode 100644
index 0000000..575b61b
--- /dev/null
+++ b/runtime/vm/base64.h
@@ -0,0 +1,16 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_VM_BASE64_H_
+#define RUNTIME_VM_BASE64_H_
+
+#include "vm/zone.h"
+
+namespace dart {
+
+uint8_t* DecodeBase64(Zone* zone, const char* str, intptr_t* out_decoded_len);
+
+} // namespace dart
+
+#endif // RUNTIME_VM_BASE64_H_
diff --git a/runtime/vm/base64_test.cc b/runtime/vm/base64_test.cc
new file mode 100644
index 0000000..406a431
--- /dev/null
+++ b/runtime/vm/base64_test.cc
@@ -0,0 +1,32 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/base64.h"
+
+#include "platform/assert.h"
+#include "vm/unit_test.h"
+
+namespace dart {
+
+TEST_CASE(Base64Decode) {
+ intptr_t decoded_len;
+ uint8_t* decoded_bytes =
+ DecodeBase64(thread->zone(), "SGVsbG8sIHdvcmxkIQo=", &decoded_len);
+ const char expected_bytes[] = "Hello, world!\n";
+ intptr_t expected_len = strlen(expected_bytes);
+ EXPECT(!memcmp(expected_bytes, decoded_bytes, expected_len));
+ EXPECT_EQ(expected_len, decoded_len);
+}
+
+TEST_CASE(Base64DecodeMalformed) {
+ intptr_t decoded_len;
+ EXPECT(DecodeBase64(thread->zone(), "SomethingMalformed", &decoded_len) ==
+ nullptr);
+}
+
+TEST_CASE(Base64DecodeEmpty) {
+ intptr_t decoded_len;
+ EXPECT(DecodeBase64(thread->zone(), "", &decoded_len) == nullptr);
+}
+} // namespace dart
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index ffd9821..c7cb303 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -301,6 +301,10 @@
benchmark->set_score(elapsed_time);
}
+static void NoopFinalizer(void* isolate_callback_data,
+ Dart_WeakPersistentHandle handle,
+ void* peer) {}
+
//
// Measure time accessing internal and external strings.
//
@@ -316,7 +320,8 @@
intptr_t char_size;
intptr_t str_len;
Dart_Handle external_string = Dart_NewExternalLatin1String(
- data8, ARRAY_SIZE(data8), &external_peer_data, NULL);
+ data8, ARRAY_SIZE(data8), &external_peer_data, sizeof(data8),
+ NoopFinalizer);
Dart_Handle internal_string = NewString("two");
// Run benchmark.
diff --git a/runtime/vm/bigint_test.cc b/runtime/vm/bigint_test.cc
deleted file mode 100644
index 4644a4c..0000000
--- a/runtime/vm/bigint_test.cc
+++ /dev/null
@@ -1,675 +0,0 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#include "platform/assert.h"
-#include "vm/object.h"
-#include "vm/object_store.h"
-#include "vm/unit_test.h"
-
-namespace dart {
-
-TEST_CASE(BigintSmi) {
- if (Bigint::IsDisabled()) {
- return;
- }
-
- {
- const Smi& smi = Smi::Handle(Smi::New(5));
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromInt64(smi.Value()));
- EXPECT_EQ(5, bigint.AsInt64Value());
- EXPECT(bigint.FitsIntoSmi());
- Smi& smi_back = Smi::Handle();
- smi_back ^= bigint.AsValidInteger();
- EXPECT_EQ(5, smi_back.Value());
- }
-
- {
- const Smi& smi = Smi::Handle(Smi::New(Smi::kMaxValue));
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromInt64(smi.Value()));
- EXPECT(Smi::kMaxValue == bigint.AsInt64Value());
- EXPECT(bigint.FitsIntoSmi());
- Smi& smi_back = Smi::Handle();
- smi_back ^= bigint.AsValidInteger();
- EXPECT(Smi::kMaxValue == smi_back.Value());
- }
-
- {
- const Smi& smi = Smi::Handle(Smi::New(Smi::kMinValue));
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromInt64(smi.Value()));
- EXPECT(bigint.IsNegative());
- EXPECT(Smi::kMinValue == bigint.AsInt64Value());
- EXPECT(bigint.FitsIntoSmi());
- Smi& smi_back = Smi::Handle();
- smi_back ^= bigint.AsValidInteger();
- EXPECT(Smi::kMinValue == smi_back.Value());
- }
-
- {
- ASSERT(0xFFFFFFF < Smi::kMaxValue);
- const Smi& smi = Smi::Handle(Smi::New(0xFFFFFFF));
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromInt64(smi.Value()));
- EXPECT_EQ(0xFFFFFFF, bigint.AsInt64Value());
- EXPECT(bigint.FitsIntoSmi());
- Smi& smi_back = Smi::Handle();
- smi_back ^= bigint.AsValidInteger();
- EXPECT_EQ(0xFFFFFFF, smi_back.Value());
- }
-
- {
- ASSERT(0x10000000 < Smi::kMaxValue);
- const Smi& smi = Smi::Handle(Smi::New(0x10000000));
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromInt64(smi.Value()));
- EXPECT_EQ(0x10000000, bigint.AsInt64Value());
- EXPECT(bigint.FitsIntoSmi());
- Smi& smi_back = Smi::Handle();
- smi_back ^= bigint.AsValidInteger();
- EXPECT(0x10000000 == smi_back.Value());
- }
-}
-
-TEST_CASE(BigintInt64) {
- if (Bigint::IsDisabled()) {
- return;
- }
-
- const int64_t kValue = 100000000;
- const int64_t kValue64 = kValue * kValue;
- Bigint& bigint = Bigint::Handle(Bigint::NewFromInt64(kValue));
- EXPECT_EQ(kValue, bigint.AsInt64Value());
- bigint = Bigint::NewFromInt64(kValue64);
- EXPECT_EQ(kValue64, bigint.AsInt64Value());
- bigint = Bigint::NewFromInt64(-kValue64);
- EXPECT_EQ(-kValue64, bigint.AsInt64Value());
- bigint = Bigint::NewFromInt64(kMinInt64);
- EXPECT(bigint.FitsIntoInt64());
- EXPECT_EQ(kMinInt64, bigint.AsInt64Value());
-}
-
-TEST_CASE(BigintUint64) {
- if (Bigint::IsDisabled()) {
- return;
- }
-
- const Bigint& one = Bigint::Handle(Bigint::NewFromUint64(1));
- EXPECT(one.FitsIntoInt64());
- EXPECT(one.FitsIntoUint64());
-
- const Bigint& big = Bigint::Handle(Bigint::NewFromUint64(kMaxUint64));
- EXPECT(!big.FitsIntoInt64());
- EXPECT(big.FitsIntoUint64());
-
- uint64_t back = big.AsUint64Value();
- EXPECT_EQ(kMaxUint64, back);
-}
-
-TEST_CASE(BigintDouble) {
- if (Bigint::IsDisabled()) {
- return;
- }
-
- Bigint& bigint = Bigint::Handle(Bigint::NewFromInt64(5));
- EXPECT_EQ(5.0, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromInt64(0);
- EXPECT_EQ(0.0, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromInt64(-12345678);
- EXPECT_EQ(-1.2345678e+7, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromCString("1");
- EXPECT_EQ(1.0, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromCString("123456");
- EXPECT_EQ(123456.0, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromCString("123456789");
- EXPECT_EQ(123456789.0, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromCString("12345678901234567");
- EXPECT_EQ(12345678901234568.0, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromCString("98765432109876");
- EXPECT_EQ(9.8765432109876e+13, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromCString("0x17777777777778");
- EXPECT_EQ(6605279453476728.0, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromCString("0x37777777777778");
- EXPECT_EQ(15612478708217720.0, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromCString("0x177777777777781234567");
- EXPECT_EQ(1.7730912021014563e+24, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromCString("0x177777777777788000000");
- EXPECT_EQ(1.7730912021014563e+24, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromCString("0x177777777777788000001");
- EXPECT_EQ(1.7730912021014565e+24, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromCString("0x177777777777798000000");
- EXPECT_EQ(1.7730912021014568e+24, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromCString("0x177777777777798000001");
- EXPECT_EQ(1.7730912021014568e+24, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromCString("0x377777777777790000000");
- EXPECT_EQ(4.1909428413307146e+24, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromCString("0x377777777777790000001");
- EXPECT_EQ(4.190942841330715e+24, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromCString("0x377777777777730000000");
- EXPECT_EQ(4.1909428413307135e+24, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromCString("0x377777777777730000001");
- EXPECT_EQ(4.1909428413307135e+24, bigint.AsDoubleValue());
-
- // Reduced precision.
- bigint = Bigint::NewFromCString("9876543210987654321098765432109876543210");
- EXPECT_EQ(9.8765432109876546e+39, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromCString(
- "12345678901234567890123456789012345678901234567890"
- "12345678901234567890123456789012345678901234567890"
- "12345678901234567890123456789012345678901234567890"
- "12345678901234567890123456789012345678901234567890"
- "12345678901234567890123456789012345678901234567890"
- "12345678901234567890123456789012345678901234567890"
- "12345678901234567890123456789012345678901234567890"
- "12345678901234567890123456789012345678901234567890"
- "12345678901234567890123456789012345678901234567890"
- "12345678901234567890123456789012345678901234567890");
- double zero = 0.0;
- EXPECT_EQ(1.0 / zero, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromCString(
- "17976931348623157081452742373170435679807056752584"
- "49965989174768031572607800285387605895586327668781"
- "71540458953514382464234321326889464182768467546703"
- "53751698604991057655128207624549009038932894407586"
- "85084551339423045832369032229481658085593321233482"
- "74797826204144723168738177180919299881250404026184"
- "124858368");
- EXPECT_EQ(1.7976931348623157e308, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromCString(
- "17976931348623159077293051907890247336179769789423"
- "06572734300811577326758055009631327084773224075360"
- "21120113879871393357658789768814416622492847430639"
- "47412437776789342486548527630221960124609411945308"
- "29520850057688381506823424628814739131105408272371"
- "63350510684586298239947245938479716304835356329624"
- "224137216");
- EXPECT_EQ(1.0 / zero, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromCString(
- "17976931348623158079372897140530341507993413271003"
- "78269361737789804449682927647509466490179775872070"
- "96330286416692887910946555547851940402630657488671"
- "50582068190890200070838367627385484581771153176447"
- "57302700698555713669596228429148198608349364752927"
- "19074168444365510704342711559699508093042880177904"
- "174497792");
- EXPECT_EQ(1.0 / zero, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromCString(
- "17976931348623158079372897140530341507993413271003"
- "78269361737789804449682927647509466490179775872070"
- "96330286416692887910946555547851940402630657488671"
- "50582068190890200070838367627385484581771153176447"
- "57302700698555713669596228429148198608349364752927"
- "19074168444365510704342711559699508093042880177904"
- "174497791");
- EXPECT_EQ(1.7976931348623157e308, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromCString("100000000000000000000000");
- EXPECT_EQ(1e+23, bigint.AsDoubleValue());
-
- bigint = Bigint::NewFromCString("100000000000000000000001");
- EXPECT_EQ(1.0000000000000001e+23, bigint.AsDoubleValue());
-
- // Same but shifted 64 bits to the left.
- bigint =
- Bigint::NewFromCString("1844674407370955161600000000000000000000000");
- EXPECT_EQ(1.844674407370955e+42, bigint.AsDoubleValue());
-
- bigint =
- Bigint::NewFromCString("1844674407370955161600000000000000000000001");
- EXPECT_EQ(1.8446744073709553e+42, bigint.AsDoubleValue());
-}
-
-TEST_CASE(BigintHexStrings) {
- if (Bigint::IsDisabled()) {
- return;
- }
-
- Zone* zone = Thread::Current()->zone();
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("0x0"));
- EXPECT(bigint.FitsIntoSmi());
- EXPECT_EQ(0, bigint.AsInt64Value());
- }
-
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("0x1"));
- EXPECT(bigint.FitsIntoSmi());
- EXPECT_EQ(1, bigint.AsInt64Value());
- }
-
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("0x123"));
- EXPECT(bigint.FitsIntoSmi());
- EXPECT_EQ(0x123, bigint.AsInt64Value());
- }
-
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("0x123"));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ("0x123", str);
- }
-
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("0xaBcEf"));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ("0xABCEF", str);
- }
-
- {
- const char* in = "0x123456789";
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString(in));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ(in, str);
- }
-
- {
- const char* in = "0xFFFFFFF";
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString(in));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ(in, str);
- }
-
- {
- const char* in = "0x10000000";
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString(in));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ(in, str);
- }
-
- {
- const char* in = "0x123456789ABCDEF01234567890ABCDEF0123456789ABCDEF0";
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString(in));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ(in, str);
- }
-
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("-0x123"));
- EXPECT(bigint.FitsIntoSmi());
- EXPECT_EQ(-0x123, bigint.AsInt64Value());
- }
-
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("-0x123"));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ("-0x123", str);
- }
-
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("-0xaBcEf"));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ("-0xABCEF", str);
- }
-
- {
- const char* in = "-0x123456789";
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString(in));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ(in, str);
- }
-
- {
- const char* in = "-0x123456789ABCDEF01234567890ABCDEF0123456789ABCDEF0";
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString(in));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ(in, str);
- }
-
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("0x00000123"));
- EXPECT(bigint.FitsIntoSmi());
- EXPECT_EQ(0x123, bigint.AsInt64Value());
- }
-
- {
- const Bigint& bigint =
- Bigint::Handle(Bigint::NewFromCString("0x000000123"));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ("0x123", str);
- }
-
- {
- const Bigint& bigint =
- Bigint::Handle(Bigint::NewFromCString("0x0000aBcEf"));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ("0xABCEF", str);
- }
-
- {
- const char* in = "0x00000000000000000000000000000000000000000000123456789";
- const char* out = "0x123456789";
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString(in));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ(out, str);
- }
-
- {
- const char* in = "0x00000123456789ABCDEF01234567890ABCDEF0123456789ABCDEF0";
- const char* out = "0x123456789ABCDEF01234567890ABCDEF0123456789ABCDEF0";
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString(in));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ(out, str);
- }
-
- {
- const Bigint& bigint =
- Bigint::Handle(Bigint::NewFromCString("-0x00000123"));
- EXPECT(bigint.FitsIntoSmi());
- EXPECT_EQ(-0x123, bigint.AsInt64Value());
- }
-
- {
- const Bigint& bigint =
- Bigint::Handle(Bigint::NewFromCString("-0x00000123"));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ("-0x123", str);
- }
-
- {
- const Bigint& bigint =
- Bigint::Handle(Bigint::NewFromCString("-0x000aBcEf"));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ("-0xABCEF", str);
- }
-
- {
- const char* in = "-0x00000000000000000000000000000000000000000000123456789";
- const char* out = "-0x123456789";
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString(in));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ(out, str);
- }
-
- {
- const char* in = "-0x0000123456789ABCDEF01234567890ABCDEF0123456789ABCDEF0";
- const char* out = "-0x123456789ABCDEF01234567890ABCDEF0123456789ABCDEF0";
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString(in));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ(out, str);
- }
- {
- const char* test = "12345678901234567890";
- const char* out = "0xAB54A98CEB1F0AD2";
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString(test));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ(out, str);
- }
- {
- const char* test = "-12345678901234567890";
- const char* out = "-0xAB54A98CEB1F0AD2";
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString(test));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ(out, str);
- }
-}
-
-TEST_CASE(BigintDecStrings) {
- if (Bigint::IsDisabled()) {
- return;
- }
-
- Zone* zone = Thread::Current()->zone();
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("0x0"));
- const char* str = bigint.ToDecCString(zone);
- EXPECT_STREQ("0", str);
- }
-
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("0x123"));
- const char* str = bigint.ToDecCString(zone);
- EXPECT_STREQ("291", str);
- }
-
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("0xaBcEf"));
- const char* str = bigint.ToDecCString(zone);
- EXPECT_STREQ("703727", str);
- }
-
- {
- const char* in = "0x123456789";
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString(in));
- const char* str = bigint.ToDecCString(zone);
- EXPECT_STREQ("4886718345", str);
- }
-
- {
- const char* in = "0xFFFFFFF";
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString(in));
- const char* str = bigint.ToDecCString(zone);
- EXPECT_STREQ("268435455", str);
- }
-
- {
- const char* in = "0x10000000";
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString(in));
- const char* str = bigint.ToDecCString(zone);
- EXPECT_STREQ("268435456", str);
- }
-
- {
- const char* in = "0x123456789ABCDEF01234567890ABCDEF0123456789ABCDEF0";
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString(in));
- const char* str = bigint.ToDecCString(zone);
- EXPECT_STREQ("7141946863373290020600059860922167424469804758405880798960",
- str);
- }
-
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("-0x123"));
- EXPECT(bigint.FitsIntoSmi());
- EXPECT_EQ(-291, bigint.AsInt64Value());
- }
-
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("-0x123"));
- const char* str = bigint.ToDecCString(zone);
- EXPECT_STREQ("-291", str);
- }
-
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("-0xaBcEf"));
- const char* str = bigint.ToDecCString(zone);
- EXPECT_STREQ("-703727", str);
- }
-
- {
- const char* in = "-0x123456789";
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString(in));
- const char* str = bigint.ToDecCString(zone);
- EXPECT_STREQ("-4886718345", str);
- }
-
- {
- const char* in = "-0x123456789ABCDEF01234567890ABCDEF0123456789ABCDEF0";
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString(in));
- const char* str = bigint.ToDecCString(zone);
- EXPECT_STREQ("-7141946863373290020600059860922167424469804758405880798960",
- str);
- }
-
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("0x00000123"));
- EXPECT(bigint.FitsIntoSmi());
- EXPECT_EQ(0x123, bigint.AsInt64Value());
- }
-
- {
- const Bigint& bigint =
- Bigint::Handle(Bigint::NewFromCString("0x000000123"));
- const char* str = bigint.ToDecCString(zone);
- EXPECT_STREQ("291", str);
- }
-
- {
- const Bigint& bigint = Bigint::Handle(
- Bigint::NewFromCString("100000000000000000000000000000000"));
- const char* str = bigint.ToDecCString(zone);
- EXPECT_STREQ("100000000000000000000000000000000", str);
- }
-}
-
-static void TestBigintCompare(const char* a, const char* b, int compare) {
- const Bigint& bigint_a = Bigint::Handle(Bigint::NewFromCString(a));
- const Bigint& bigint_b = Bigint::Handle(Bigint::NewFromCString(b));
- const Integer& int_a = Integer::Handle(bigint_a.AsValidInteger());
- const Integer& int_b = Integer::Handle(bigint_b.AsValidInteger());
- int computed_compare = int_a.CompareWith(int_b);
- int inverted_compare = int_b.CompareWith(int_a);
- if (compare == 0) {
- EXPECT(computed_compare == 0);
- EXPECT(inverted_compare == 0);
- } else if (compare < 0) {
- ASSERT(computed_compare < 0);
- EXPECT(computed_compare < 0);
- EXPECT(inverted_compare > 0);
- } else {
- ASSERT(compare > 0);
- EXPECT(computed_compare > 0);
- EXPECT(inverted_compare < 0);
- }
-}
-
-TEST_CASE(BigintCompare) {
- if (Bigint::IsDisabled()) {
- return;
- }
-
- TestBigintCompare("0x0", "0x0", 0);
- TestBigintCompare("0x1", "0x1", 0);
- TestBigintCompare("-0x1", "-0x1", 0);
- TestBigintCompare("0x1234567", "0x1234567", 0);
- TestBigintCompare("-0x1234567", "-0x1234567", 0);
- TestBigintCompare("0x12345678", "0x12345678", 0);
- TestBigintCompare("-0x12345678", "-0x12345678", 0);
- TestBigintCompare("0x123456789ABCDEF0", "0x123456789ABCDEF0", 0);
- TestBigintCompare("-0x123456789ABCDEF0", "-0x123456789ABCDEF0", 0);
- TestBigintCompare("0x123456789ABCDEF01", "0x123456789ABCDEF01", 0);
- TestBigintCompare("-0x123456789ABCDEF01", "-0x123456789ABCDEF01", 0);
- TestBigintCompare("0x1", "0x0", 1);
- TestBigintCompare("-0x1", "-0x2", 1);
- TestBigintCompare("0x1234567", "0x1234566", 1);
- TestBigintCompare("-0x1234567", "-0x1234568", 1);
- TestBigintCompare("0x12345678", "0x12345677", 1);
- TestBigintCompare("-0x12345678", "-0x12345679", 1);
- TestBigintCompare("0x123456789ABCDEF1", "0x123456789ABCDEF0", 1);
- TestBigintCompare("-0x123456789ABCDEF0", "-0x123456789ABCDEF1", 1);
- TestBigintCompare("0x123456789ABCDEF02", "0x123456789ABCDEF01", 1);
- TestBigintCompare("-0x123456789ABCDEF00", "-0x123456789ABCDEF01", 1);
- TestBigintCompare("0x10000000", "0xFFFFFFF", 1);
- TestBigintCompare("-0x10000000", "-0xFFFFFFF", -1);
- TestBigintCompare("0x100000000", "0xFFFFFFFF", 1);
- TestBigintCompare("-0x100000000", "-0xFFFFFFFF", -1);
- TestBigintCompare("0x10000000000000000", "0xFFFFFFFFFFFFFFFF", 1);
- TestBigintCompare("-0x10000000000000000", "-0xFFFFFFFFFFFFFFFF", -1);
- TestBigintCompare("0x10000000000000000", "0x0", 1);
- TestBigintCompare("-0x10000000000000000", "0x0", -1);
- TestBigintCompare("-0x1234567", "0x1234566", -1);
- TestBigintCompare("-0x1234567", "0x1234568", -1);
- TestBigintCompare("-0x12345678", "0x12345677", -1);
- TestBigintCompare("-0x12345678", "0x12345670", -1);
- TestBigintCompare("-0x123456789ABCDEF1", "0x123456789ABCDEF0", -1);
- TestBigintCompare("-0x123456789ABCDEF0", "0x123456789ABCDEF1", -1);
- TestBigintCompare("-0x123456789ABCDEF02", "0x123456789ABCDEF01", -1);
- TestBigintCompare("-0x123456789ABCDEF00", "0x123456789ABCDEF01", -1);
- TestBigintCompare("-0x10000000", "0xFFFFFFF", -1);
- TestBigintCompare("-0x10000000", "0xFFFFFFF", -1);
- TestBigintCompare("-0x100000000", "0xFFFFFFFF", -1);
- TestBigintCompare("-0x100000000", "0xFFFFFFFF", -1);
- TestBigintCompare("-0x10000000000000000", "0xFFFFFFFFFFFFFFFF", -1);
- TestBigintCompare("-0x10000000000000000", "0xFFFFFFFFFFFFFFFF", -1);
- TestBigintCompare("-0x10000000000000000", "0x0", -1);
- TestBigintCompare("-0x10000000000000000", "0x0", -1);
-}
-
-TEST_CASE(BigintDecimalStrings) {
- if (Bigint::IsDisabled()) {
- return;
- }
-
- Zone* zone = Thread::Current()->zone();
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("0"));
- EXPECT(bigint.FitsIntoSmi());
- EXPECT_EQ(0, bigint.AsInt64Value());
- }
-
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("1"));
- EXPECT(bigint.FitsIntoSmi());
- EXPECT_EQ(1, bigint.AsInt64Value());
- }
-
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("703710"));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ("0xABCDE", str);
- }
-
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("11259375"));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ("0xABCDEF", str);
- }
-
- {
- const Bigint& bigint =
- Bigint::Handle(Bigint::NewFromCString("1311768467463790320"));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ("0x123456789ABCDEF0", str);
- }
-
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("-0"));
- EXPECT(bigint.FitsIntoSmi());
- EXPECT_EQ(0, bigint.AsInt64Value());
- }
-
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("-1"));
- EXPECT(bigint.FitsIntoSmi());
- EXPECT_EQ(-1, bigint.AsInt64Value());
- }
-
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("-703710"));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ("-0xABCDE", str);
- }
-
- {
- const Bigint& bigint = Bigint::Handle(Bigint::NewFromCString("-11259375"));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ("-0xABCDEF", str);
- }
-
- {
- const Bigint& bigint =
- Bigint::Handle(Bigint::NewFromCString("-1311768467463790320"));
- const char* str = bigint.ToHexCString(zone);
- EXPECT_STREQ("-0x123456789ABCDEF0", str);
- }
-}
-
-} // namespace dart
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index eb76282..cdbb56d 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -62,10 +62,6 @@
V(Mint_bitNegate, 1) \
V(Mint_bitLength, 1) \
V(Mint_shlFromInt, 2) \
- V(Bigint_getNeg, 1) \
- V(Bigint_getUsed, 1) \
- V(Bigint_getDigits, 1) \
- V(Bigint_allocate, 4) \
V(Developer_debugger, 2) \
V(Developer_getIsolateIDFromSendPort, 1) \
V(Developer_getServerInfo, 1) \
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 92ba3ed..bceab3b 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -3266,7 +3266,6 @@
case kIntegerCid: // Class Integer, not int.
case kSmiCid:
case kMintCid:
- case kBigintCid:
case kDoubleCid: // Class Double, not double.
case kOneByteStringCid:
case kTwoByteStringCid:
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 4cce63f..869d283 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -3685,83 +3685,6 @@
};
#if !defined(DART_PRECOMPILED_RUNTIME)
-class BigintSerializationCluster : public SerializationCluster {
- public:
- BigintSerializationCluster() : SerializationCluster("Bigint") {}
- virtual ~BigintSerializationCluster() {}
-
- void Trace(Serializer* s, RawObject* object) {
- RawBigint* bigint = Bigint::RawCast(object);
- objects_.Add(bigint);
-
- RawObject** from = bigint->from();
- RawObject** to = bigint->to();
- for (RawObject** p = from; p <= to; p++) {
- s->Push(*p);
- }
- }
-
- void WriteAlloc(Serializer* s) {
- s->WriteCid(kBigintCid);
- intptr_t count = objects_.length();
- s->WriteUnsigned(count);
- for (intptr_t i = 0; i < count; i++) {
- RawBigint* bigint = objects_[i];
- s->AssignRef(bigint);
- }
- }
-
- void WriteFill(Serializer* s) {
- intptr_t count = objects_.length();
- for (intptr_t i = 0; i < count; i++) {
- RawBigint* bigint = objects_[i];
- s->Write<bool>(bigint->IsCanonical());
- RawObject** from = bigint->from();
- RawObject** to = bigint->to();
- for (RawObject** p = from; p <= to; p++) {
- s->WriteRef(*p);
- }
- }
- }
-
- private:
- GrowableArray<RawBigint*> objects_;
-};
-#endif // !DART_PRECOMPILED_RUNTIME
-
-class BigintDeserializationCluster : public DeserializationCluster {
- public:
- BigintDeserializationCluster() {}
- virtual ~BigintDeserializationCluster() {}
-
- void ReadAlloc(Deserializer* d) {
- start_index_ = d->next_index();
- PageSpace* old_space = d->heap()->old_space();
- intptr_t count = d->ReadUnsigned();
- for (intptr_t i = 0; i < count; i++) {
- d->AssignRef(AllocateUninitialized(old_space, Bigint::InstanceSize()));
- }
- stop_index_ = d->next_index();
- }
-
- void ReadFill(Deserializer* d) {
- bool is_vm_object = d->isolate() == Dart::vm_isolate();
-
- for (intptr_t id = start_index_; id < stop_index_; id++) {
- RawBigint* bigint = reinterpret_cast<RawBigint*>(d->Ref(id));
- bool is_canonical = d->Read<bool>();
- Deserializer::InitializeHeader(bigint, kBigintCid, Bigint::InstanceSize(),
- is_vm_object, is_canonical);
- RawObject** from = bigint->from();
- RawObject** to = bigint->to();
- for (RawObject** p = from; p <= to; p++) {
- *p = d->ReadRef();
- }
- }
- }
-};
-
-#if !defined(DART_PRECOMPILED_RUNTIME)
class DoubleSerializationCluster : public SerializationCluster {
public:
DoubleSerializationCluster() : SerializationCluster("Double") {}
@@ -4813,8 +4736,6 @@
return new (Z) ClosureSerializationCluster();
case kMintCid:
return new (Z) MintSerializationCluster();
- case kBigintCid:
- return new (Z) BigintSerializationCluster();
case kDoubleCid:
return new (Z) DoubleSerializationCluster();
case kGrowableObjectArrayCid:
@@ -5338,8 +5259,6 @@
return new (Z) ClosureDeserializationCluster();
case kMintCid:
return new (Z) MintDeserializationCluster();
- case kBigintCid:
- return new (Z) BigintDeserializationCluster();
case kDoubleCid:
return new (Z) DoubleDeserializationCluster();
case kGrowableObjectArrayCid:
diff --git a/runtime/vm/compiler/aot/aot_call_specializer.cc b/runtime/vm/compiler/aot/aot_call_specializer.cc
index 4fea9a6..83f76d1 100644
--- a/runtime/vm/compiler/aot/aot_call_specializer.cc
+++ b/runtime/vm/compiler/aot/aot_call_specializer.cc
@@ -272,8 +272,7 @@
return true;
}
- if (FLAG_limit_ints_to_64_bits &&
- FlowGraphCompiler::SupportsUnboxedInt64() &&
+ if (FlowGraphCompiler::SupportsUnboxedInt64() &&
FlowGraphCompiler::CanConvertInt64ToDouble()) {
return true;
}
@@ -286,8 +285,7 @@
intptr_t cid,
Instruction* call) {
ASSERT(I->strong() && FLAG_use_strong_mode_types);
- ASSERT((cid == kDoubleCid) ||
- (FLAG_limit_ints_to_64_bits && (cid == kMintCid)));
+ ASSERT((cid == kDoubleCid) || (cid == kMintCid));
const String& function_name =
(call->IsInstanceCall()
@@ -303,8 +301,7 @@
if (input->Type()->ToNullableCid() == kSmiCid) {
conversion = new (Z) SmiToDoubleInstr(input, call->token_pos());
- } else if (FLAG_limit_ints_to_64_bits &&
- FlowGraphCompiler::SupportsUnboxedInt64() &&
+ } else if (FlowGraphCompiler::SupportsUnboxedInt64() &&
FlowGraphCompiler::CanConvertInt64ToDouble()) {
conversion = new (Z) Int64ToDoubleInstr(input, Thread::kNoDeoptId,
Instruction::kNotSpeculative);
@@ -325,8 +322,7 @@
Value* AotCallSpecializer::PrepareReceiverOfDevirtualizedCall(Value* input,
intptr_t cid) {
ASSERT(I->strong() && FLAG_use_strong_mode_types);
- ASSERT((cid == kDoubleCid) ||
- (FLAG_limit_ints_to_64_bits && (cid == kMintCid)));
+ ASSERT((cid == kDoubleCid) || (cid == kMintCid));
// Can't assert !input->Type()->is_nullable() here as PushArgument receives
// value prior to a CheckNull in case of devirtualized call.
@@ -374,8 +370,7 @@
CompileType* left_type = left_value->Type();
CompileType* right_type = right_value->Type();
if (left_type->IsNullableInt() && right_type->IsNullableInt()) {
- if (FLAG_limit_ints_to_64_bits &&
- FlowGraphCompiler::SupportsUnboxedInt64()) {
+ if (FlowGraphCompiler::SupportsUnboxedInt64()) {
if (Token::IsRelationalOperator(op_kind)) {
left_value = PrepareStaticOpInput(left_value, kMintCid, instr);
right_value = PrepareStaticOpInput(right_value, kMintCid, instr);
@@ -445,8 +440,7 @@
CompileType* right_type = right_value->Type();
if (left_type->IsNullableInt() && right_type->IsNullableInt() &&
(op_kind != Token::kDIV)) {
- if (FLAG_limit_ints_to_64_bits &&
- FlowGraphCompiler::SupportsUnboxedInt64()) {
+ if (FlowGraphCompiler::SupportsUnboxedInt64()) {
if ((op_kind == Token::kSHR) || (op_kind == Token::kSHL)) {
// TODO(dartbug.com/30480): Enable 64-bit integer shifts.
// replacement = new ShiftInt64OpInstr(
@@ -526,8 +520,7 @@
// instance calls of these operators into static calls.
if (owner.id() == kIntegerCid) {
- if (!FLAG_limit_ints_to_64_bits ||
- !FlowGraphCompiler::SupportsUnboxedInt64()) {
+ if (!FlowGraphCompiler::SupportsUnboxedInt64()) {
return false;
}
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 414b63a..e419327 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -2132,11 +2132,7 @@
}
}
intptr_t cid = cls.id();
- if (cid == kBigintCid) {
- // Constants stored as a plain list, no rehashing needed.
- constants = Array::MakeFixedLength(retained_constants);
- cls.set_constants(constants);
- } else if (cid == kDoubleCid) {
+ if (cid == kDoubleCid) {
// Rehash.
cls.set_constants(Object::empty_array());
for (intptr_t j = 0; j < retained_constants.Length(); j++) {
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index 39858e9..55fcc83 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -493,9 +493,7 @@
if (IsNonConstant(left) || IsNonConstant(right)) {
SetValue(instr, non_constant_);
} else if (IsConstant(left) && IsConstant(right)) {
- // BitOp does not work on Bigints.
- if (left.IsInteger() && right.IsInteger() && !left.IsBigint() &&
- !right.IsBigint()) {
+ if (left.IsInteger() && right.IsInteger()) {
const bool result = CompareIntegers(
instr->kind(),
Integer::Handle(Z, Integer::Cast(left).BitOp(Token::kBIT_AND,
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index c4740e2..510052d 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -612,7 +612,6 @@
explicit VariableLivenessAnalysis(FlowGraph* flow_graph)
: LivenessAnalysis(flow_graph->variable_count(), flow_graph->postorder()),
flow_graph_(flow_graph),
- num_direct_parameters_(flow_graph->num_direct_parameters()),
assigned_vars_() {}
// For every block (in preorder) compute and return set of variables that
@@ -657,7 +656,7 @@
return false;
}
if (store->is_last()) {
- const intptr_t index = store->local().BitIndexIn(num_direct_parameters_);
+ const intptr_t index = flow_graph_->EnvIndex(&store->local());
return GetLiveOutSet(block)->Contains(index);
}
@@ -670,7 +669,7 @@
if (load->local().Equals(*flow_graph_->CurrentContextVar())) {
return false;
}
- const intptr_t index = load->local().BitIndexIn(num_direct_parameters_);
+ const intptr_t index = flow_graph_->EnvIndex(&load->local());
return load->is_last() && !GetLiveOutSet(block)->Contains(index);
}
@@ -678,7 +677,6 @@
virtual void ComputeInitialSets();
const FlowGraph* flow_graph_;
- const intptr_t num_direct_parameters_;
GrowableArray<BitVector*> assigned_vars_;
};
@@ -710,7 +708,7 @@
LoadLocalInstr* load = current->AsLoadLocal();
if (load != NULL) {
- const intptr_t index = load->local().BitIndexIn(num_direct_parameters_);
+ const intptr_t index = flow_graph_->EnvIndex(&load->local());
if (index >= live_in->length()) continue; // Skip tmp_locals.
live_in->Add(index);
if (!last_loads->Contains(index)) {
@@ -722,8 +720,7 @@
StoreLocalInstr* store = current->AsStoreLocal();
if (store != NULL) {
- const intptr_t index =
- store->local().BitIndexIn(num_direct_parameters_);
+ const intptr_t index = flow_graph_->EnvIndex(&store->local());
if (index >= live_in->length()) continue; // Skip tmp_locals.
if (kill->Contains(index)) {
if (!live_in->Contains(index)) {
@@ -989,8 +986,7 @@
AllocateSSAIndexes(defn);
AddToInitialDefinitions(defn);
- intptr_t index = parsed_function_.RawParameterVariable(i)->BitIndexIn(
- num_direct_parameters_);
+ intptr_t index = EnvIndex(parsed_function_.RawParameterVariable(i));
env[index] = defn;
}
}
@@ -1086,13 +1082,11 @@
block_entry->AsCatchBlockEntry()) {
const intptr_t raw_exception_var_envindex =
catch_entry->raw_exception_var() != nullptr
- ? catch_entry->raw_exception_var()->BitIndexIn(
- num_direct_parameters_)
+ ? EnvIndex(catch_entry->raw_exception_var())
: -1;
const intptr_t raw_stacktrace_var_envindex =
catch_entry->raw_stacktrace_var() != nullptr
- ? catch_entry->raw_stacktrace_var()->BitIndexIn(
- num_direct_parameters_)
+ ? EnvIndex(catch_entry->raw_stacktrace_var())
: -1;
// Add real definitions for all locals and parameters.
@@ -1143,13 +1137,11 @@
const LocalVariable* raw_exception_var = catch_entry->raw_exception_var();
const LocalVariable* raw_stacktrace_var = catch_entry->raw_stacktrace_var();
if (raw_exception_var != nullptr) {
- Value* value = deopt_env->ValueAt(
- raw_exception_var->BitIndexIn(num_direct_parameters_));
+ Value* value = deopt_env->ValueAt(EnvIndex(raw_exception_var));
value->BindToEnvironment(constant_null());
}
if (raw_stacktrace_var != nullptr) {
- Value* value = deopt_env->ValueAt(
- raw_stacktrace_var->BitIndexIn(num_direct_parameters_));
+ Value* value = deopt_env->ValueAt(EnvIndex(raw_stacktrace_var));
value->BindToEnvironment(constant_null());
}
}
@@ -1201,10 +1193,11 @@
switch (current->tag()) {
case Instruction::kLoadLocal: {
LoadLocalInstr* load = current->Cast<LoadLocalInstr>();
+
// The graph construction ensures we do not have an unused LoadLocal
// computation.
ASSERT(load->HasTemp());
- const intptr_t index = load->local().BitIndexIn(num_direct_parameters_);
+ const intptr_t index = EnvIndex(&load->local());
result = (*env)[index];
PhiInstr* phi = result->AsPhi();
@@ -1245,8 +1238,7 @@
case Instruction::kStoreLocal: {
StoreLocalInstr* store = current->Cast<StoreLocalInstr>();
- const intptr_t index =
- store->local().BitIndexIn(num_direct_parameters_);
+ const intptr_t index = EnvIndex(&store->local());
result = store->value()->definition();
if (!FLAG_prune_dead_locals ||
diff --git a/runtime/vm/compiler/backend/flow_graph.h b/runtime/vm/compiler/backend/flow_graph.h
index ac09be0..dbd7564 100644
--- a/runtime/vm/compiler/backend/flow_graph.h
+++ b/runtime/vm/compiler/backend/flow_graph.h
@@ -130,17 +130,20 @@
}
intptr_t CurrentContextEnvIndex() const {
- return parsed_function().current_context_var()->BitIndexIn(
- num_direct_parameters_);
+ return EnvIndex(parsed_function().current_context_var());
}
intptr_t RawTypeArgumentEnvIndex() const {
- return parsed_function().RawTypeArgumentsVariable()->BitIndexIn(
- num_direct_parameters_);
+ return EnvIndex(parsed_function().RawTypeArgumentsVariable());
}
intptr_t ArgumentDescriptorEnvIndex() const {
- return parsed_function().arg_desc_var()->BitIndexIn(num_direct_parameters_);
+ return EnvIndex(parsed_function().arg_desc_var());
+ }
+
+ intptr_t EnvIndex(const LocalVariable* variable) const {
+ ASSERT(!variable->is_captured());
+ return num_direct_parameters_ - variable->index().value();
}
// Flow graph orders.
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 187e12f..9b611ee 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -77,7 +77,9 @@
for (Environment::ShallowIterator it(env); !it.Done(); it.Advance()) {
if (it.CurrentLocation().IsInvalid() &&
it.CurrentValue()->definition()->IsPushArgument()) {
- it.SetCurrentLocation(Location::StackSlot((*stack_height)++));
+ it.SetCurrentLocation(
+ Location::StackSlot(FrameSlotForVariableIndex(-*stack_height)));
+ (*stack_height)++;
}
}
}
@@ -361,16 +363,17 @@
catch_entry_state_maps_builder_->AppendConstant(id, dest_index);
continue;
}
- if (src.stack_index() != dest_index) {
- catch_entry_state_maps_builder_->AppendMove(src.stack_index(),
- dest_index);
+ const intptr_t src_index = -VariableIndexForFrameSlot(src.stack_index());
+ if (src_index != dest_index) {
+ catch_entry_state_maps_builder_->AppendMove(src_index, dest_index);
}
}
// Process locals. Skip exception_var and stacktrace_var.
- intptr_t local_base = kFirstLocalSlotFromFp + num_direct_parameters;
- intptr_t ex_idx = local_base - catch_block->exception_var().index();
- intptr_t st_idx = local_base - catch_block->stacktrace_var().index();
+ intptr_t local_base = num_direct_parameters;
+ intptr_t ex_idx = local_base - catch_block->exception_var().index().value();
+ intptr_t st_idx =
+ local_base - catch_block->stacktrace_var().index().value();
for (; i < flow_graph().variable_count(); ++i) {
// Don't sync captured parameters. They are not in the environment.
if (flow_graph().captured_parameters()->Contains(i)) continue;
@@ -390,9 +393,9 @@
catch_entry_state_maps_builder_->AppendConstant(id, dest_index);
continue;
}
- if (src.stack_index() != dest_index) {
- catch_entry_state_maps_builder_->AppendMove(src.stack_index(),
- dest_index);
+ const intptr_t src_index = -VariableIndexForFrameSlot(src.stack_index());
+ if (src_index != dest_index) {
+ catch_entry_state_maps_builder_->AppendMove(src_index, dest_index);
}
}
catch_entry_state_maps_builder_->EndMapping();
@@ -940,7 +943,8 @@
info.scope_id = 0;
info.begin_pos = TokenPosition::kMinSource;
info.end_pos = TokenPosition::kMinSource;
- info.set_index(parsed_function().current_context_var()->index());
+ info.set_index(
+ FrameSlotForVariable(parsed_function().current_context_var()));
var_descs.SetVar(0, Symbols::CurrentContextVar(), &info);
}
code.set_var_descriptors(var_descs);
@@ -1184,10 +1188,8 @@
if (type.IsNumberType()) {
args.Add(kDoubleCid);
args.Add(kMintCid);
- args.Add(kBigintCid);
} else if (type.IsIntType()) {
args.Add(kMintCid);
- args.Add(kBigintCid);
} else if (type.IsDoubleType()) {
args.Add(kDoubleCid);
}
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index 8185f32..f31d130 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -597,11 +597,6 @@
// If the cid does not fit in 16 bits, then this will cause a bailout.
uint16_t ToEmbeddableCid(intptr_t cid, Instruction* instruction);
-
- // In optimized code, variables at the catch block entry reside at the top
- // of the allocatable register range.
- // Must be in sync with FlowGraphAllocator::ProcessInitialDefinition.
- intptr_t CatchEntryRegForVariable(const LocalVariable& var);
#endif // defined(TARGET_ARCH_DBC)
CompilerDeoptInfo* AddDeoptIndexAtCall(intptr_t deopt_id);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index e41694f..6d150d3 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -361,7 +361,7 @@
__ b(is_not_instance_lbl);
return false;
}
- // Custom checking for numbers (Smi, Mint, Bigint and Double).
+ // Custom checking for numbers (Smi, Mint and Double).
// Note that instance is not Smi (checked above).
if (type.IsNumberType() || type.IsIntType() || type.IsDoubleType()) {
GenerateNumberTypeCheck(kClassIdReg, type, is_instance_lbl,
@@ -848,20 +848,19 @@
if (!is_optimizing()) {
const int num_locals = parsed_function().num_stack_locals();
- intptr_t args_desc_index = -1;
+ intptr_t args_desc_slot = -1;
if (parsed_function().has_arg_desc_var()) {
- args_desc_index =
- -(parsed_function().arg_desc_var()->index() - kFirstLocalSlotFromFp);
+ args_desc_slot = FrameSlotForVariable(parsed_function().arg_desc_var());
}
__ Comment("Initialize spill slots");
- if (num_locals > 1 || (num_locals == 1 && args_desc_index == -1)) {
+ if (num_locals > 1 || (num_locals == 1 && args_desc_slot == -1)) {
__ LoadObject(R0, Object::null_object());
}
for (intptr_t i = 0; i < num_locals; ++i) {
- Register value_reg = i == args_desc_index ? ARGS_DESC_REG : R0;
- __ StoreToOffset(kWord, value_reg, FP,
- (kFirstLocalSlotFromFp - i) * kWordSize);
+ const intptr_t slot_index = FrameSlotForVariableIndex(-i);
+ Register value_reg = slot_index == args_desc_slot ? ARGS_DESC_REG : R0;
+ __ StoreToOffset(kWord, value_reg, FP, slot_index * kWordSize);
}
}
@@ -1085,7 +1084,7 @@
TokenPosition token_pos,
intptr_t deopt_id) {
if (needs_number_check) {
- ASSERT(!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint());
+ ASSERT(!obj.IsMint() && !obj.IsDouble());
__ Push(reg);
__ PushObject(obj);
if (is_optimizing()) {
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index a74cec8..cef314e 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -347,7 +347,7 @@
__ b(is_not_instance_lbl);
return false;
}
- // Custom checking for numbers (Smi, Mint, Bigint and Double).
+ // Custom checking for numbers (Smi, Mint and Double).
// Note that instance is not Smi (checked above).
if (type.IsNumberType() || type.IsIntType() || type.IsDoubleType()) {
GenerateNumberTypeCheck(kClassIdReg, type, is_instance_lbl,
@@ -830,19 +830,19 @@
if (!is_optimizing()) {
const int num_locals = parsed_function().num_stack_locals();
- intptr_t args_desc_index = -1;
+ intptr_t args_desc_slot = -1;
if (parsed_function().has_arg_desc_var()) {
- args_desc_index =
- -(parsed_function().arg_desc_var()->index() - kFirstLocalSlotFromFp);
+ args_desc_slot = FrameSlotForVariable(parsed_function().arg_desc_var());
}
__ Comment("Initialize spill slots");
- if (num_locals > 1 || (num_locals == 1 && args_desc_index == -1)) {
+ if (num_locals > 1 || (num_locals == 1 && args_desc_slot == -1)) {
__ LoadObject(R0, Object::null_object());
}
for (intptr_t i = 0; i < num_locals; ++i) {
- Register value_reg = i == args_desc_index ? ARGS_DESC_REG : R0;
- __ StoreToOffset(value_reg, FP, (kFirstLocalSlotFromFp - i) * kWordSize);
+ const intptr_t slot_index = FrameSlotForVariableIndex(-i);
+ Register value_reg = slot_index == args_desc_slot ? ARGS_DESC_REG : R0;
+ __ StoreToOffset(value_reg, FP, slot_index * kWordSize);
}
}
@@ -1059,7 +1059,7 @@
TokenPosition token_pos,
intptr_t deopt_id) {
if (needs_number_check) {
- ASSERT(!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint());
+ ASSERT(!obj.IsMint() && !obj.IsDouble());
__ Push(reg);
__ PushObject(obj);
if (is_optimizing()) {
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_dbc.cc b/runtime/vm/compiler/backend/flow_graph_compiler_dbc.cc
index 557f69a..1d6c20e 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_dbc.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_dbc.cc
@@ -108,7 +108,9 @@
if (lazy_deopt_with_result_) {
ASSERT(reason() == ICData::kDeoptAtCall);
- builder->AddCopy(NULL, Location::StackSlot(stack_height), slot_ix++);
+ builder->AddCopy(
+ NULL, Location::StackSlot(FrameSlotForVariableIndex(-stack_height)),
+ slot_ix++);
}
// For the innermost environment, set outgoing arguments and the locals.
@@ -327,10 +329,10 @@
if (parsed_function().has_arg_desc_var()) {
// TODO(kustermann): If dbc simulator put the args_desc_ into the
// _special_regs, we could replace these 3 with the MoveSpecial bytecode.
- const intptr_t args_desc_index =
- -(parsed_function().arg_desc_var()->index() - kFirstLocalSlotFromFp);
+ const intptr_t slot_index =
+ FrameSlotForVariable(parsed_function().arg_desc_var());
__ LoadArgDescriptor();
- __ StoreLocal(args_desc_index);
+ __ StoreLocal(LocalVarIndex(0, slot_index));
__ Drop(1);
}
}
@@ -357,16 +359,6 @@
return static_cast<uint16_t>(cid);
}
-intptr_t FlowGraphCompiler::CatchEntryRegForVariable(const LocalVariable& var) {
- const Function& function = parsed_function().function();
- const intptr_t num_non_copied_params =
- function.HasOptionalParameters() ? 0 : function.NumParameters();
-
- ASSERT(is_optimizing());
- ASSERT(var.index() <= 0);
- return kNumberOfCpuRegisters - (num_non_copied_params - var.index());
-}
-
#undef __
#define __ compiler_->assembler()->
@@ -375,10 +367,11 @@
const Location source = move->src();
const Location destination = move->dest();
if (source.IsStackSlot() && destination.IsRegister()) {
- // Only allow access to the arguments.
+ // Only allow access to the arguments (which have in the non-inverted stack
+ // positive indices).
ASSERT(source.base_reg() == FPREG);
- ASSERT(source.stack_index() < 0);
- __ Move(destination.reg(), -kParamEndSlotFromFp + source.stack_index());
+ ASSERT(source.stack_index() > kParamEndSlotFromFp);
+ __ Move(destination.reg(), -source.stack_index());
} else if (source.IsRegister() && destination.IsRegister()) {
__ Move(destination.reg(), source.reg());
} else if (source.IsArgsDescRegister()) {
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index f19eea3..6e4f305 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -364,7 +364,7 @@
__ jmp(is_not_instance_lbl);
return false;
}
- // Custom checking for numbers (Smi, Mint, Bigint and Double).
+ // Custom checking for numbers (Smi, Mint and Double).
// Note that instance is not Smi (checked above).
if (type.IsNumberType() || type.IsIntType() || type.IsDoubleType()) {
GenerateNumberTypeCheck(kClassIdReg, type, is_instance_lbl,
@@ -786,21 +786,21 @@
if (!is_optimizing()) {
const int num_locals = parsed_function().num_stack_locals();
- intptr_t args_desc_index = -1;
+ intptr_t args_desc_slot = -1;
if (parsed_function().has_arg_desc_var()) {
- args_desc_index =
- -(parsed_function().arg_desc_var()->index() - kFirstLocalSlotFromFp);
+ args_desc_slot = FrameSlotForVariable(parsed_function().arg_desc_var());
}
__ Comment("Initialize spill slots");
- if (num_locals > 1 || args_desc_index != 0) {
+ if (num_locals > 1 || (num_locals == 1 && args_desc_slot == -1)) {
const Immediate& raw_null =
Immediate(reinterpret_cast<intptr_t>(Object::null()));
__ movl(EAX, raw_null);
}
for (intptr_t i = 0; i < num_locals; ++i) {
- Register value_reg = i == args_desc_index ? ARGS_DESC_REG : EAX;
- __ movl(Address(EBP, (kFirstLocalSlotFromFp - i) * kWordSize), value_reg);
+ const intptr_t slot_index = FrameSlotForVariableIndex(-i);
+ Register value_reg = slot_index == args_desc_slot ? ARGS_DESC_REG : EAX;
+ __ movl(Address(EBP, slot_index * kWordSize), value_reg);
}
}
@@ -977,8 +977,7 @@
bool needs_number_check,
TokenPosition token_pos,
intptr_t deopt_id) {
- ASSERT(!needs_number_check ||
- (!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint()));
+ ASSERT(!needs_number_check || (!obj.IsMint() && !obj.IsDouble()));
if (obj.IsSmi() && (Smi::Cast(obj).Value() == 0)) {
ASSERT(!needs_number_check);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index 0ef54a5..6a91d21 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -362,7 +362,7 @@
__ jmp(is_not_instance_lbl);
return false;
}
- // Custom checking for numbers (Smi, Mint, Bigint and Double).
+ // Custom checking for numbers (Smi, Mint and Double).
// Note that instance is not Smi (checked above).
if (type.IsNumberType() || type.IsIntType() || type.IsDoubleType()) {
GenerateNumberTypeCheck(kClassIdReg, type, is_instance_lbl,
@@ -828,19 +828,19 @@
if (!is_optimizing()) {
const int num_locals = parsed_function().num_stack_locals();
- intptr_t args_desc_index = -1;
+ intptr_t args_desc_slot = -1;
if (parsed_function().has_arg_desc_var()) {
- args_desc_index =
- -(parsed_function().arg_desc_var()->index() - kFirstLocalSlotFromFp);
+ args_desc_slot = FrameSlotForVariable(parsed_function().arg_desc_var());
}
__ Comment("Initialize spill slots");
- if (num_locals > 1 || (num_locals == 1 && args_desc_index == -1)) {
+ if (num_locals > 1 || (num_locals == 1 && args_desc_slot == -1)) {
__ LoadObject(RAX, Object::null_object());
}
for (intptr_t i = 0; i < num_locals; ++i) {
- Register value_reg = i == args_desc_index ? ARGS_DESC_REG : RAX;
- __ movq(Address(RBP, (kFirstLocalSlotFromFp - i) * kWordSize), value_reg);
+ const intptr_t slot_index = FrameSlotForVariableIndex(-i);
+ Register value_reg = slot_index == args_desc_slot ? ARGS_DESC_REG : RAX;
+ __ movq(Address(RBP, slot_index * kWordSize), value_reg);
}
}
@@ -1050,8 +1050,7 @@
bool needs_number_check,
TokenPosition token_pos,
intptr_t deopt_id) {
- ASSERT(!needs_number_check ||
- (!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint()));
+ ASSERT(!needs_number_check || (!obj.IsMint() && !obj.IsDouble()));
if (obj.IsSmi() && (Smi::Cast(obj).Value() == 0)) {
ASSERT(!needs_number_check);
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index ce25835a..1b2910b 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -739,8 +739,6 @@
ConstantInstr::ConstantInstr(const Object& value, TokenPosition token_pos)
: value_(value), token_pos_(token_pos) {
// Check that the value is not an incorrect Integer representation.
- ASSERT(!value.IsBigint() || !Bigint::Cast(value).FitsIntoSmi());
- ASSERT(!value.IsBigint() || !Bigint::Cast(value).FitsIntoInt64());
ASSERT(!value.IsMint() || !Smi::IsValid(Mint::Cast(value).AsInt64Value()));
ASSERT(!value.IsField() || Field::Cast(value).IsOriginal());
}
@@ -1505,7 +1503,6 @@
} else if (is_truncating() && value()->definition()->IsBoxInteger()) {
return false;
} else if ((kSmiBits < 32) && value()->Type()->IsInt()) {
- // Note: we don't support truncation of Bigint values.
return !RangeUtils::Fits(value()->definition()->range(),
RangeBoundary::kRangeBoundaryInt32);
} else {
@@ -2003,7 +2000,6 @@
if ((left_type->ToCid() == kSmiCid) && (right_type->ToCid() == kSmiCid)) {
op_cid = kSmiCid;
} else if (Isolate::Current()->strong() && FLAG_use_strong_mode_types &&
- FLAG_limit_ints_to_64_bits &&
FlowGraphCompiler::SupportsUnboxedInt64() &&
// TODO(dartbug.com/30480): handle nullable types here
left_type->IsNullableInt() && !left_type->is_nullable() &&
@@ -2688,8 +2684,7 @@
}
static bool MayBeBoxableNumber(intptr_t cid) {
- return (cid == kDynamicCid) || (cid == kMintCid) || (cid == kBigintCid) ||
- (cid == kDoubleCid);
+ return (cid == kDynamicCid) || (cid == kMintCid) || (cid == kDoubleCid);
}
static bool MaybeNumber(CompileType* type) {
@@ -2708,7 +2703,7 @@
bool* negated,
bool is_branch) {
// Use propagated cid and type information to eliminate number checks.
- // If one of the inputs is not a boxable number (Mint, Double, Bigint), or
+ // If one of the inputs is not a boxable number (Mint, Double), or
// is not a subtype of num, no need for number checks.
if (compare->needs_number_check()) {
if (!MayBeBoxableNumber(compare->left()->Type()->ToCid()) ||
@@ -4122,7 +4117,6 @@
break;
case kUnboxedInt64: {
- ASSERT(FLAG_limit_ints_to_64_bits);
if (value()->Type()->ToCid() == kSmiCid) {
// Smi -> int64 conversion is more efficient than
// handling arbitrary smi/mint.
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 4806355..3ce1bb1 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -177,7 +177,7 @@
// Returns true if value of this type is either int or null.
bool IsNullableInt() {
- if ((cid_ == kSmiCid) || (cid_ == kMintCid) || (cid_ == kBigintCid)) {
+ if ((cid_ == kSmiCid) || (cid_ == kMintCid)) {
return true;
}
if ((cid_ == kIllegalCid) || (cid_ == kDynamicCid)) {
@@ -3426,7 +3426,7 @@
PRINT_OPERANDS_TO_SUPPORT
private:
- // True if the comparison must check for double, Mint or Bigint and
+ // True if the comparison must check for double or Mint and
// use value comparison instead.
bool needs_number_check_;
@@ -6214,28 +6214,17 @@
SpeculativeMode speculative_mode = kGuardInputs)
: BinaryIntegerOpInstr(op_kind, left, right, deopt_id),
speculative_mode_(speculative_mode) {
- if (FLAG_limit_ints_to_64_bits) {
- mark_truncating();
- }
+ mark_truncating();
}
virtual bool ComputeCanDeoptimize() const {
- switch (op_kind()) {
- case Token::kADD:
- case Token::kSUB:
- return can_overflow();
- case Token::kMUL:
-// Note that ARM64 does not support operations with unboxed mints,
-// so it is not handled here.
-#if defined(TARGET_ARCH_X64)
- return can_overflow(); // Deopt if overflow.
-#else
- // IA32, ARM
- return true; // Deopt if inputs are not int32.
-#endif
- default:
- return false;
+ ASSERT(!can_overflow());
+#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM)
+ if (op_kind() == Token::kMUL) {
+ return true; // Deopt if inputs are not int32.
}
+#endif
+ return false;
}
virtual Representation representation() const { return kUnboxedInt64; }
@@ -6271,16 +6260,14 @@
: BinaryIntegerOpInstr(op_kind, left, right, deopt_id),
shift_range_(NULL) {
ASSERT((op_kind == Token::kSHR) || (op_kind == Token::kSHL));
- if (FLAG_limit_ints_to_64_bits) {
- mark_truncating();
- }
+ mark_truncating();
}
Range* shift_range() const { return shift_range_; }
virtual bool ComputeCanDeoptimize() const {
- return (!IsShiftCountInRange()) ||
- (can_overflow() && (op_kind() == Token::kSHL));
+ ASSERT(!can_overflow());
+ return !IsShiftCountInRange();
}
virtual Representation representation() const { return kUnboxedInt64; }
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index e9a04e7..269f1b4 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -294,7 +294,7 @@
void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Register result = locs()->out(0).reg();
- __ LoadFromOffset(kWord, result, FP, local().index() * kWordSize);
+ __ LoadFromOffset(kWord, result, FP, FrameOffsetInBytesForVariable(&local()));
}
LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone,
@@ -307,7 +307,7 @@
const Register value = locs()->in(0).reg();
const Register result = locs()->out(0).reg();
ASSERT(result == value); // Assert that register assignment is correct.
- __ StoreToOffset(kWord, value, FP, local().index() * kWordSize);
+ __ StoreToOffset(kWord, value, FP, FrameOffsetInBytesForVariable(&local()));
}
LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone,
@@ -2912,11 +2912,11 @@
if (!compiler->is_optimizing()) {
if (raw_exception_var_ != nullptr) {
__ StoreToOffset(kWord, kExceptionObjectReg, FP,
- raw_exception_var_->index() * kWordSize);
+ FrameOffsetInBytesForVariable(raw_exception_var_));
}
if (raw_stacktrace_var_ != nullptr) {
__ StoreToOffset(kWord, kStackTraceObjectReg, FP,
- raw_stacktrace_var_->index() * kWordSize);
+ FrameOffsetInBytesForVariable(raw_stacktrace_var_));
}
}
}
@@ -5750,6 +5750,7 @@
PairLocation* out_pair = locs()->out(0).AsPairLocation();
Register out_lo = out_pair->At(0).reg();
Register out_hi = out_pair->At(1).reg();
+ ASSERT(!can_overflow());
Label* deopt = NULL;
if (CanDeoptimize()) {
@@ -5781,10 +5782,6 @@
__ subs(out_lo, left_lo, Operand(right_lo));
__ sbcs(out_hi, left_hi, Operand(right_hi));
}
- if (can_overflow()) {
- // Deopt on overflow.
- __ b(deopt, VS);
- }
break;
}
case Token::kMUL: {
@@ -5824,6 +5821,7 @@
PairLocation* out_pair = locs()->out(0).AsPairLocation();
Register out_lo = out_pair->At(0).reg();
Register out_hi = out_pair->At(1).reg();
+ ASSERT(!can_overflow());
Label* deopt = NULL;
if (CanDeoptimize()) {
@@ -5866,22 +5864,6 @@
}
__ mov(out_lo, Operand(0));
}
- // Check for overflow.
- if (can_overflow()) {
- // Compare high word from input with shifted high word from output.
- // If shift > 32, also compare low word from input with high word from
- // output shifted back shift - 32.
- if (shift > 32) {
- __ cmp(left_lo, Operand(out_hi, ASR, shift - 32));
- __ cmp(left_hi, Operand(out_hi, ASR, 31), EQ);
- } else if (shift == 32) {
- __ cmp(left_hi, Operand(out_hi, ASR, 31));
- } else {
- __ cmp(left_hi, Operand(out_hi, ASR, shift));
- }
- // Overflow if they aren't equal.
- __ b(deopt, NE);
- }
break;
}
default:
@@ -5917,19 +5899,6 @@
__ mov(out_hi, Operand(left_hi, LSL, shift), PL);
__ orr(out_hi, out_hi, Operand(left_lo, LSR, IP), PL);
__ mov(out_lo, Operand(left_lo, LSL, shift));
-
- // Check for overflow.
- if (can_overflow()) {
- // If shift > 32, compare low word from input with high word from
- // output shifted back shift - 32.
- __ mov(IP, Operand(out_hi, ASR, IP), MI);
- __ mov(IP, Operand(left_lo), PL); // No test if shift <= 32.
- __ cmp(left_lo, Operand(IP));
- // Compare high word from input with shifted high word from output.
- __ cmp(left_hi, Operand(out_hi, ASR, shift), EQ);
- // Overflow if they aren't equal.
- __ b(deopt, NE);
- }
break;
}
default:
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 204dd69..d8bbde3 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -291,7 +291,7 @@
void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Register result = locs()->out(0).reg();
- __ LoadFromOffset(result, FP, local().index() * kWordSize);
+ __ LoadFromOffset(result, FP, FrameOffsetInBytesForVariable(&local()));
}
LocationSummary* StoreLocalInstr::MakeLocationSummary(Zone* zone,
@@ -304,7 +304,7 @@
const Register value = locs()->in(0).reg();
const Register result = locs()->out(0).reg();
ASSERT(result == value); // Assert that register assignment is correct.
- __ StoreToOffset(value, FP, local().index() * kWordSize);
+ __ StoreToOffset(value, FP, FrameOffsetInBytesForVariable(&local()));
}
LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone,
@@ -2659,11 +2659,11 @@
if (!compiler->is_optimizing()) {
if (raw_exception_var_ != nullptr) {
__ StoreToOffset(kExceptionObjectReg, FP,
- raw_exception_var_->index() * kWordSize);
+ FrameOffsetInBytesForVariable(raw_exception_var_));
}
if (raw_stacktrace_var_ != nullptr) {
__ StoreToOffset(kStackTraceObjectReg, FP,
- raw_stacktrace_var_->index() * kWordSize);
+ FrameOffsetInBytesForVariable(raw_stacktrace_var_));
}
}
}
@@ -4988,10 +4988,8 @@
}
void BinaryInt64OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- Label* deopt = NULL;
- if (CanDeoptimize()) {
- deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryInt64Op);
- }
+ ASSERT(!can_overflow());
+ ASSERT(!CanDeoptimize());
const Register left = locs()->in(0).reg();
const Location right = locs()->in(1);
@@ -5008,12 +5006,6 @@
r = right.reg();
}
__ mul(out, left, r);
- if (CanDeoptimize()) {
- __ smulh(TMP, left, r);
- // TMP: result bits 64..127.
- __ cmp(TMP, Operand(out, ASR, 63));
- __ b(deopt, NE);
- }
return;
}
@@ -5023,20 +5015,10 @@
constant_instr->GetUnboxedSignedIntegerConstantValue();
switch (op_kind()) {
case Token::kADD:
- if (CanDeoptimize()) {
- __ AddImmediateSetFlags(out, left, value);
- __ b(deopt, VS);
- } else {
- __ AddImmediate(out, left, value);
- }
+ __ AddImmediate(out, left, value);
break;
case Token::kSUB:
- if (CanDeoptimize()) {
- __ SubImmediateSetFlags(out, left, value);
- __ b(deopt, VS);
- } else {
- __ AddImmediate(out, left, -value);
- }
+ __ AddImmediate(out, left, -value);
break;
case Token::kBIT_AND:
__ AndImmediate(out, left, value);
@@ -5054,20 +5036,10 @@
Operand r = Operand(right.reg());
switch (op_kind()) {
case Token::kADD:
- if (CanDeoptimize()) {
- __ adds(out, left, r);
- __ b(deopt, VS);
- } else {
- __ add(out, left, r);
- }
+ __ add(out, left, r);
break;
case Token::kSUB:
- if (CanDeoptimize()) {
- __ subs(out, left, r);
- __ b(deopt, VS);
- } else {
- __ sub(out, left, r);
- }
+ __ sub(out, left, r);
break;
case Token::kBIT_AND:
__ and_(out, left, r);
@@ -5099,6 +5071,7 @@
void ShiftInt64OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Register left = locs()->in(0).reg();
const Register out = locs()->out(0).reg();
+ ASSERT(!can_overflow());
Label* deopt = NULL;
if (CanDeoptimize()) {
@@ -5117,11 +5090,6 @@
case Token::kSHL: {
ASSERT(shift < 64);
__ LslImmediate(out, left, shift);
- // Check for overflow.
- if (can_overflow()) {
- __ cmp(left, Operand(out, ASR, shift));
- __ b(deopt, NE);
- }
break;
}
default:
@@ -5147,13 +5115,6 @@
}
case Token::kSHL: {
__ lslv(out, left, TMP);
-
- // Check for overflow.
- if (can_overflow()) {
- __ asrv(TMP2, out, TMP);
- __ cmp(left, Operand(TMP2));
- __ b(deopt, NE);
- }
break;
}
default:
diff --git a/runtime/vm/compiler/backend/il_dbc.cc b/runtime/vm/compiler/backend/il_dbc.cc
index c00e4e9..0451944 100644
--- a/runtime/vm/compiler/backend/il_dbc.cc
+++ b/runtime/vm/compiler/backend/il_dbc.cc
@@ -328,19 +328,17 @@
EMIT_NATIVE_CODE(LoadLocal, 0) {
ASSERT(!compiler->is_optimizing());
- ASSERT(local().index() != 0);
- __ Push((local().index() > 0) ? (-local().index()) : (-local().index() - 1));
+ const intptr_t slot_index = FrameSlotForVariable(&local());
+ __ Push(LocalVarIndex(0, slot_index));
}
EMIT_NATIVE_CODE(StoreLocal, 0) {
ASSERT(!compiler->is_optimizing());
- ASSERT(local().index() != 0);
+ const intptr_t slot_index = FrameSlotForVariable(&local());
if (HasTemp()) {
- __ StoreLocal((local().index() > 0) ? (-local().index())
- : (-local().index() - 1));
+ __ StoreLocal(LocalVarIndex(0, slot_index));
} else {
- __ PopLocal((local().index() > 0) ? (-local().index())
- : (-local().index() - 1));
+ __ PopLocal(LocalVarIndex(0, slot_index));
}
}
@@ -1188,12 +1186,13 @@
if (!compiler->is_optimizing()) {
if (raw_exception_var_ != nullptr) {
- __ MoveSpecial(LocalVarIndex(0, raw_exception_var_->index()),
+ __ MoveSpecial(LocalVarIndex(0, FrameSlotForVariable(raw_exception_var_)),
Simulator::kExceptionSpecialIndex);
}
if (raw_stacktrace_var_ != nullptr) {
- __ MoveSpecial(LocalVarIndex(0, raw_stacktrace_var_->index()),
- Simulator::kStackTraceSpecialIndex);
+ __ MoveSpecial(
+ LocalVarIndex(0, FrameSlotForVariable(raw_stacktrace_var_)),
+ Simulator::kStackTraceSpecialIndex);
}
}
}
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index e8ec6e3..e400614 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -134,9 +134,7 @@
LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 0;
- const intptr_t stack_index = (local().index() < 0)
- ? kFirstLocalSlotFromFp - local().index()
- : kParamEndSlotFromFp - local().index();
+ const intptr_t stack_index = FrameSlotForVariable(&local());
return LocationSummary::Make(zone, kNumInputs,
Location::StackSlot(stack_index),
LocationSummary::kNoCall);
@@ -158,7 +156,7 @@
Register value = locs()->in(0).reg();
Register result = locs()->out(0).reg();
ASSERT(result == value); // Assert that register assignment is correct.
- __ movl(Address(EBP, local().index() * kWordSize), value);
+ __ movl(Address(EBP, FrameOffsetInBytesForVariable(&local())), value);
}
LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone,
@@ -2498,11 +2496,11 @@
if (!compiler->is_optimizing()) {
if (raw_exception_var_ != nullptr) {
- __ movl(Address(EBP, raw_exception_var_->index() * kWordSize),
+ __ movl(Address(EBP, FrameOffsetInBytesForVariable(raw_exception_var_)),
kExceptionObjectReg);
}
if (raw_stacktrace_var_ != nullptr) {
- __ movl(Address(EBP, raw_stacktrace_var_->index() * kWordSize),
+ __ movl(Address(EBP, FrameOffsetInBytesForVariable(raw_stacktrace_var_)),
kStackTraceObjectReg);
}
}
@@ -5193,6 +5191,7 @@
Register out_hi = out_pair->At(1).reg();
ASSERT(out_lo == left_lo);
ASSERT(out_hi == left_hi);
+ ASSERT(!can_overflow());
Label* deopt = NULL;
if (CanDeoptimize()) {
@@ -5220,9 +5219,6 @@
__ subl(left_lo, right_lo);
__ sbbl(left_hi, right_hi);
}
- if (can_overflow()) {
- __ j(OVERFLOW, deopt);
- }
break;
}
case Token::kMUL: {
@@ -5253,17 +5249,12 @@
LocationSummary* ShiftInt64OpInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 2;
- const intptr_t kNumTemps =
- (op_kind() == Token::kSHL) && CanDeoptimize() ? 2 : 0;
+ const intptr_t kNumTemps = 0;
LocationSummary* summary = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
summary->set_in(0, Location::Pair(Location::RequiresRegister(),
Location::RequiresRegister()));
summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX));
- if ((op_kind() == Token::kSHL) && CanDeoptimize()) {
- summary->set_temp(0, Location::RequiresRegister());
- summary->set_temp(1, Location::RequiresRegister());
- }
summary->set_out(0, Location::SameAsFirstInput());
return summary;
}
@@ -5277,6 +5268,7 @@
Register out_hi = out_pair->At(1).reg();
ASSERT(out_lo == left_lo);
ASSERT(out_hi == left_hi);
+ ASSERT(!can_overflow());
Label* deopt = NULL;
if (CanDeoptimize()) {
@@ -5303,51 +5295,15 @@
}
case Token::kSHL: {
ASSERT(shift < 64);
- if (can_overflow()) {
- Register temp1 = locs()->temp(0).reg();
- Register temp2 = locs()->temp(1).reg();
- __ movl(temp1, left_hi); // Preserve high 32 bits.
- if (shift > 31) {
- __ movl(left_hi, left_lo); // Shift by 32.
- if (shift > 32) {
- __ shll(left_hi, Immediate(shift - 32));
- }
- // Check for overflow by sign extending the high 32 bits
- // and comparing with the input.
- __ movl(temp2, left_hi);
- __ sarl(temp2, Immediate(31));
- __ cmpl(temp1, temp2);
- __ j(NOT_EQUAL, deopt);
- if (shift > 32) {
- // Also compare low word from input with high word from
- // output shifted back shift - 32.
- __ movl(temp2, left_hi);
- __ sarl(temp2, Immediate(shift - 32));
- __ cmpl(left_lo, temp2);
- __ j(NOT_EQUAL, deopt);
- }
- __ xorl(left_lo, left_lo); // Zero left_lo.
- } else {
- __ shldl(left_hi, left_lo, Immediate(shift));
- __ shll(left_lo, Immediate(shift));
- // Check for overflow by shifting back the high 32 bits
- // and comparing with the input.
- __ movl(temp2, left_hi);
- __ sarl(temp2, Immediate(shift));
- __ cmpl(temp1, temp2);
- __ j(NOT_EQUAL, deopt);
+ if (shift > 31) {
+ __ movl(left_hi, left_lo); // Shift by 32.
+ __ xorl(left_lo, left_lo); // Zero left_lo.
+ if (shift > 32) {
+ __ shll(left_hi, Immediate(shift - 32));
}
} else {
- if (shift > 31) {
- __ movl(left_hi, left_lo); // Shift by 32.
- __ xorl(left_lo, left_lo); // Zero left_lo.
- if (shift > 32) {
- __ shll(left_hi, Immediate(shift - 32));
- }
- } else {
- __ shldl(left_hi, left_lo, Immediate(shift));
- __ shll(left_lo, Immediate(shift));
- }
+ __ shldl(left_hi, left_lo, Immediate(shift));
+ __ shll(left_lo, Immediate(shift));
}
break;
}
@@ -5382,54 +5338,18 @@
break;
}
case Token::kSHL: {
- if (can_overflow()) {
- Register temp1 = locs()->temp(0).reg();
- Register temp2 = locs()->temp(1).reg();
- __ movl(temp1, left_hi); // Preserve high 32 bits.
- __ cmpl(ECX, Immediate(31));
- __ j(ABOVE, &large_shift);
+ __ cmpl(ECX, Immediate(31));
+ __ j(ABOVE, &large_shift);
- __ shldl(left_hi, left_lo, ECX); // Shift count in CL.
- __ shll(left_lo, ECX); // Shift count in CL.
- // Check for overflow by shifting back the high 32 bits
- // and comparing with the input.
- __ movl(temp2, left_hi);
- __ sarl(temp2, ECX);
- __ cmpl(temp1, temp2);
- __ j(NOT_EQUAL, deopt);
- __ jmp(&done, Assembler::kNearJump);
+ __ shldl(left_hi, left_lo, ECX); // Shift count in CL.
+ __ shll(left_lo, ECX); // Shift count in CL.
+ __ jmp(&done, Assembler::kNearJump);
- __ Bind(&large_shift);
- // No need to subtract 32 from CL, only 5 bits used by shll.
- __ movl(left_hi, left_lo); // Shift by 32.
- __ shll(left_hi, ECX); // Shift count: CL % 32.
- // Check for overflow by sign extending the high 32 bits
- // and comparing with the input.
- __ movl(temp2, left_hi);
- __ sarl(temp2, Immediate(31));
- __ cmpl(temp1, temp2);
- __ j(NOT_EQUAL, deopt);
- // Also compare low word from input with high word from
- // output shifted back shift - 32.
- __ movl(temp2, left_hi);
- __ sarl(temp2, ECX); // Shift count: CL % 32.
- __ cmpl(left_lo, temp2);
- __ j(NOT_EQUAL, deopt);
- __ xorl(left_lo, left_lo); // Zero left_lo.
- } else {
- __ cmpl(ECX, Immediate(31));
- __ j(ABOVE, &large_shift);
-
- __ shldl(left_hi, left_lo, ECX); // Shift count in CL.
- __ shll(left_lo, ECX); // Shift count in CL.
- __ jmp(&done, Assembler::kNearJump);
-
- __ Bind(&large_shift);
- // No need to subtract 32 from CL, only 5 bits used by shll.
- __ movl(left_hi, left_lo); // Shift by 32.
- __ xorl(left_lo, left_lo); // Zero left_lo.
- __ shll(left_hi, ECX); // Shift count: CL % 32.
- }
+ __ Bind(&large_shift);
+ // No need to subtract 32 from CL, only 5 bits used by shll.
+ __ movl(left_hi, left_lo); // Shift by 32.
+ __ xorl(left_lo, left_lo); // Zero left_lo.
+ __ shll(left_hi, ECX); // Shift count: CL % 32.
break;
}
default:
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index c77e7d6..44e1b37 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -563,11 +563,11 @@
}
void LoadLocalInstr::PrintOperandsTo(BufferFormatter* f) const {
- f->Print("%s @%d", local().name().ToCString(), local().index());
+ f->Print("%s @%d", local().name().ToCString(), local().index().value());
}
void StoreLocalInstr::PrintOperandsTo(BufferFormatter* f) const {
- f->Print("%s @%d, ", local().name().ToCString(), local().index());
+ f->Print("%s @%d, ", local().name().ToCString(), local().index().value());
value()->PrintTo(f);
}
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index aeb619b..2d410db 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -236,9 +236,7 @@
LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 0;
- const intptr_t stack_index = (local().index() < 0)
- ? kFirstLocalSlotFromFp - local().index()
- : kParamEndSlotFromFp - local().index();
+ const intptr_t stack_index = FrameSlotForVariable(&local());
return LocationSummary::Make(zone, kNumInputs,
Location::StackSlot(stack_index),
LocationSummary::kNoCall);
@@ -260,7 +258,7 @@
Register value = locs()->in(0).reg();
Register result = locs()->out(0).reg();
ASSERT(result == value); // Assert that register assignment is correct.
- __ movq(Address(RBP, local().index() * kWordSize), value);
+ __ movq(Address(RBP, FrameOffsetInBytesForVariable(&local())), value);
}
LocationSummary* ConstantInstr::MakeLocationSummary(Zone* zone,
@@ -2591,11 +2589,11 @@
if (!compiler->is_optimizing()) {
if (raw_exception_var_ != nullptr) {
- __ movq(Address(RBP, raw_exception_var_->index() * kWordSize),
+ __ movq(Address(RBP, FrameOffsetInBytesForVariable(raw_exception_var_)),
kExceptionObjectReg);
}
if (raw_stacktrace_var_ != nullptr) {
- __ movq(Address(RBP, raw_stacktrace_var_->index() * kWordSize),
+ __ movq(Address(RBP, FrameOffsetInBytesForVariable(raw_stacktrace_var_)),
kStackTraceObjectReg);
}
}
@@ -5153,8 +5151,7 @@
static void EmitInt64Arithmetic(FlowGraphCompiler* compiler,
Token::Kind op_kind,
Register left,
- const OperandType& right,
- Label* deopt) {
+ const OperandType& right) {
switch (op_kind) {
case Token::kADD:
__ addq(left, right);
@@ -5177,7 +5174,6 @@
default:
UNREACHABLE();
}
- if (deopt != NULL) __ j(OVERFLOW, deopt);
}
LocationSummary* BinaryInt64OpInstr::MakeLocationSummary(Zone* zone,
@@ -5193,23 +5189,20 @@
}
void BinaryInt64OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- Label* deopt = NULL;
- if (CanDeoptimize()) {
- deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryInt64Op);
- }
const Location left = locs()->in(0);
const Location right = locs()->in(1);
const Location out = locs()->out(0);
ASSERT(out.reg() == left.reg());
+ ASSERT(!can_overflow());
+ ASSERT(!CanDeoptimize());
if (right.IsConstant()) {
ConstantInstr* constant_instr = right.constant_instruction();
const int64_t value =
constant_instr->GetUnboxedSignedIntegerConstantValue();
- EmitInt64Arithmetic(compiler, op_kind(), left.reg(), Immediate(value),
- deopt);
+ EmitInt64Arithmetic(compiler, op_kind(), left.reg(), Immediate(value));
} else {
- EmitInt64Arithmetic(compiler, op_kind(), left.reg(), right.reg(), deopt);
+ EmitInt64Arithmetic(compiler, op_kind(), left.reg(), right.reg());
}
}
@@ -5235,14 +5228,11 @@
LocationSummary* ShiftInt64OpInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 2;
- const intptr_t kNumTemps = can_overflow() ? 1 : 0;
+ const intptr_t kNumTemps = 0;
LocationSummary* summary = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
summary->set_in(0, Location::RequiresRegister());
summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), RCX));
- if (kNumTemps > 0) {
- summary->set_temp(0, Location::RequiresRegister());
- }
summary->set_out(0, Location::SameAsFirstInput());
return summary;
}
@@ -5251,6 +5241,7 @@
const Register left = locs()->in(0).reg();
const Register out = locs()->out(0).reg();
ASSERT(left == out);
+ ASSERT(!can_overflow());
Label* deopt = NULL;
if (CanDeoptimize()) {
@@ -5268,16 +5259,6 @@
break;
case Token::kSHL: {
ASSERT(shift < 64);
- if (can_overflow()) {
- // Check for overflow.
- Register temp = locs()->temp(0).reg();
- __ movq(temp, left);
- __ shlq(left, Immediate(shift));
- __ sarq(left, Immediate(shift));
- __ cmpq(left, temp);
- __ j(NOT_EQUAL, deopt); // Overflow.
- }
- // Shift for result now we know there is no overflow.
__ shlq(left, Immediate(shift));
break;
}
@@ -5300,16 +5281,6 @@
break;
}
case Token::kSHL: {
- if (can_overflow()) {
- // Check for overflow.
- Register temp = locs()->temp(0).reg();
- __ movq(temp, left);
- __ shlq(left, RCX);
- __ sarq(left, RCX);
- __ cmpq(left, temp);
- __ j(NOT_EQUAL, deopt); // Overflow.
- }
- // Shift for result now we know there is no overflow.
__ shlq(left, RCX);
break;
}
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index 5512de8..2643894 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -2856,16 +2856,10 @@
str = new LoadUntaggedInstr(new Value(str),
ExternalOneByteString::external_data_offset());
cursor = flow_graph->AppendTo(cursor, str, NULL, FlowGraph::kValue);
- str = new LoadUntaggedInstr(
- new Value(str), RawExternalOneByteString::ExternalData::data_offset());
- cursor = flow_graph->AppendTo(cursor, str, NULL, FlowGraph::kValue);
} else if (cid == kExternalTwoByteStringCid) {
str = new LoadUntaggedInstr(new Value(str),
ExternalTwoByteString::external_data_offset());
cursor = flow_graph->AppendTo(cursor, str, NULL, FlowGraph::kValue);
- str = new LoadUntaggedInstr(
- new Value(str), RawExternalTwoByteString::ExternalData::data_offset());
- cursor = flow_graph->AppendTo(cursor, str, NULL, FlowGraph::kValue);
}
LoadIndexedInstr* load_indexed = new (Z) LoadIndexedInstr(
diff --git a/runtime/vm/compiler/backend/linearscan.cc b/runtime/vm/compiler/backend/linearscan.cc
index f96a09d..4b6a94d 100644
--- a/runtime/vm/compiler/backend/linearscan.cc
+++ b/runtime/vm/compiler/backend/linearscan.cc
@@ -39,7 +39,9 @@
// SSA index to the second.
static intptr_t ToSecondPairVreg(intptr_t vreg) {
// Map vreg to its pair vreg.
- return vreg + kPairVirtualRegisterOffset;
+ ASSERT((vreg == kNoVirtualRegister) || vreg >= 0);
+ return (vreg == kNoVirtualRegister) ? kNoVirtualRegister
+ : (vreg + kPairVirtualRegisterOffset);
}
static intptr_t MinPosition(intptr_t a, intptr_t b) {
@@ -446,7 +448,8 @@
End());
assigned_location().Print();
if (spill_slot_.HasStackIndex()) {
- intptr_t stack_slot = spill_slot_.stack_index();
+ const intptr_t stack_slot =
+ -VariableIndexForFrameSlot(spill_slot_.stack_index());
THR_Print(" allocated spill slot: %" Pd "", stack_slot);
}
THR_Print("\n");
@@ -657,7 +660,6 @@
return;
#if defined(TARGET_ARCH_DBC)
} else if (ParameterInstr* param = defn->AsParameter()) {
- // This must be in sync with FlowGraphCompiler::CatchEntryRegForVariable.
intptr_t slot_index = param->index();
AssignSafepoints(defn, range);
range->finger()->Initialize(range);
@@ -708,6 +710,9 @@
return;
}
#endif // defined(TARGET_ARCH_DBC)
+ if (param->base_reg() == FPREG) {
+ slot_index = FrameSlotForVariableIndex(-slot_index);
+ }
range->set_assigned_location(
Location::StackSlot(slot_index, param->base_reg()));
range->set_spill_slot(Location::StackSlot(slot_index, param->base_reg()));
@@ -745,8 +750,9 @@
CompleteRange(tail, Location::kRegister);
}
ConvertAllUses(range);
- if (range->spill_slot().IsStackSlot() &&
- (range->spill_slot().stack_index() >= 0)) {
+ Location spill_slot = range->spill_slot();
+ if (spill_slot.IsStackSlot() && spill_slot.base_reg() == FPREG &&
+ spill_slot.stack_index() <= kFirstLocalSlotFromFp) {
// On entry to the function, range is stored on the stack above the FP in
// the same space which is used for spill slots. Update spill slot state to
// reflect that and prevent register allocator from reusing this space as a
@@ -2005,13 +2011,15 @@
// Assign spill slot to the range.
if (register_kind_ == Location::kRegister) {
- range->set_spill_slot(Location::StackSlot(idx));
+ const intptr_t slot_index = FrameSlotForVariableIndex(-idx);
+ range->set_spill_slot(Location::StackSlot(slot_index));
} else {
// We use the index of the slot with the lowest address as an index for the
// FPU register spill slot. In terms of indexes this relation is inverted:
// so we have to take the highest index.
- const intptr_t slot_idx = cpu_spill_slot_count_ + idx * kDoubleSpillFactor +
- (kDoubleSpillFactor - 1);
+ const intptr_t slot_idx = FrameSlotForVariableIndex(
+ -(cpu_spill_slot_count_ + idx * kDoubleSpillFactor +
+ (kDoubleSpillFactor - 1)));
Location location;
if ((range->representation() == kUnboxedFloat32x4) ||
@@ -2030,9 +2038,12 @@
}
void FlowGraphAllocator::MarkAsObjectAtSafepoints(LiveRange* range) {
- intptr_t stack_index = range->spill_slot().stack_index();
+ Location spill_slot = range->spill_slot();
+ intptr_t stack_index = spill_slot.stack_index();
+ if (spill_slot.base_reg() == FPREG) {
+ stack_index = -VariableIndexForFrameSlot(spill_slot.stack_index());
+ }
ASSERT(stack_index >= 0);
-
while (range != NULL) {
for (SafepointPosition* safepoint = range->first_safepoint();
safepoint != NULL; safepoint = safepoint->next()) {
diff --git a/runtime/vm/compiler/backend/locations.cc b/runtime/vm/compiler/backend/locations.cc
index 44c88ee..f1435e5 100644
--- a/runtime/vm/compiler/backend/locations.cc
+++ b/runtime/vm/compiler/backend/locations.cc
@@ -112,37 +112,12 @@
// DBC does not have an notion of 'address' in its instruction set.
#if !defined(TARGET_ARCH_DBC)
Address Location::ToStackSlotAddress() const {
- const intptr_t index = stack_index();
- const Register base = base_reg();
- if (base == FPREG) {
- if (index < 0) {
- const intptr_t offset = (kParamEndSlotFromFp - index) * kWordSize;
- return Address(base, offset);
- } else {
- const intptr_t offset = (kFirstLocalSlotFromFp - index) * kWordSize;
- return Address(base, offset);
- }
- } else {
- ASSERT(base == SPREG);
- return Address(base, index * kWordSize);
- }
+ return Address(base_reg(), ToStackSlotOffset());
}
#endif
intptr_t Location::ToStackSlotOffset() const {
- const intptr_t index = stack_index();
- if (base_reg() == FPREG) {
- if (index < 0) {
- const intptr_t offset = (kParamEndSlotFromFp - index) * kWordSize;
- return offset;
- } else {
- const intptr_t offset = (kFirstLocalSlotFromFp - index) * kWordSize;
- return offset;
- }
- } else {
- ASSERT(base_reg() == SPREG);
- return index * kWordSize;
- }
+ return stack_index() * kWordSize;
}
const Object& Location::constant() const {
@@ -257,18 +232,18 @@
if (IsRegister()) {
intptr_t index = cpu_reg_slots[reg()];
ASSERT(index >= 0);
- return Location::StackSlot(index);
+ return Location::StackSlot(FrameSlotForVariableIndex(-index));
} else if (IsFpuRegister()) {
intptr_t index = fpu_reg_slots[fpu_reg()];
ASSERT(index >= 0);
switch (def->representation()) {
case kUnboxedDouble:
- return Location::DoubleStackSlot(index);
+ return Location::DoubleStackSlot(FrameSlotForVariableIndex(-index));
case kUnboxedFloat32x4:
case kUnboxedInt32x4:
case kUnboxedFloat64x2:
- return Location::QuadStackSlot(index);
+ return Location::QuadStackSlot(FrameSlotForVariableIndex(-index));
default:
UNREACHABLE();
@@ -280,14 +255,16 @@
intptr_t index_hi;
if (value_pair->At(0).IsRegister()) {
- index_lo = cpu_reg_slots[value_pair->At(0).reg()];
+ index_lo =
+ FrameSlotForVariableIndex(-cpu_reg_slots[value_pair->At(0).reg()]);
} else {
ASSERT(value_pair->At(0).IsStackSlot());
index_lo = value_pair->At(0).stack_index();
}
if (value_pair->At(1).IsRegister()) {
- index_hi = cpu_reg_slots[value_pair->At(1).reg()];
+ index_hi =
+ FrameSlotForVariableIndex(-cpu_reg_slots[value_pair->At(1).reg()]);
} else {
ASSERT(value_pair->At(1).IsStackSlot());
index_hi = value_pair->At(1).stack_index();
diff --git a/runtime/vm/compiler/backend/locations.h b/runtime/vm/compiler/backend/locations.h
index fd4d576..ec6ab97 100644
--- a/runtime/vm/compiler/backend/locations.h
+++ b/runtime/vm/compiler/backend/locations.h
@@ -327,7 +327,6 @@
return static_cast<uword>(kStackIndexBias + stack_index);
}
- // Spill slots.
static Location StackSlot(intptr_t stack_index, Register base = FPREG) {
uword payload = StackSlotBaseField::encode(base) |
StackIndexField::encode(EncodeStackIndex(stack_index));
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index 0a01b69..b39e2be 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -460,10 +460,6 @@
// However the definition itself is not a int-definition and
// thus it will never have range assigned to it. Just return the widest
// range possible for this value.
- // It is safe to return Int64 range as this is the widest possible range
- // supported by our unboxing operations - if this definition produces
- // Bigint outside of Int64 we will deoptimize whenever we actually try
- // to unbox it.
// Note: that we can't return NULL here because it is used as lattice's
// bottom element to indicate that the range was not computed *yet*.
return &int64_range_;
diff --git a/runtime/vm/compiler/backend/range_analysis.h b/runtime/vm/compiler/backend/range_analysis.h
index 33f53b6..e8140f8 100644
--- a/runtime/vm/compiler/backend/range_analysis.h
+++ b/runtime/vm/compiler/backend/range_analysis.h
@@ -64,12 +64,9 @@
static RangeBoundary FromDefinition(Definition* defn, int64_t offs = 0);
static bool IsValidOffsetForSymbolicRangeBoundary(int64_t offset) {
- if (FLAG_limit_ints_to_64_bits) {
- if ((offset > (kMaxInt64 - kSmiMax)) ||
- (offset < (kMinInt64 - kSmiMin))) {
- // Avoid creating symbolic range boundaries which can wrap around.
- return false;
- }
+ if ((offset > (kMaxInt64 - kSmiMax)) || (offset < (kMinInt64 - kSmiMin))) {
+ // Avoid creating symbolic range boundaries which can wrap around.
+ return false;
}
return true;
}
@@ -297,8 +294,7 @@
Range(RangeBoundary min, RangeBoundary max) : min_(min), max_(max) {
ASSERT(min_.IsUnknown() == max_.IsUnknown());
- if (FLAG_limit_ints_to_64_bits &&
- (min_.IsInfinity() || max_.IsInfinity())) {
+ if (min_.IsInfinity() || max_.IsInfinity()) {
// Value can wrap around, so fall back to the full 64-bit range.
SetInt64Range();
}
@@ -342,7 +338,7 @@
void set_min(const RangeBoundary& value) {
min_ = value;
- if (FLAG_limit_ints_to_64_bits && min_.IsInfinity()) {
+ if (min_.IsInfinity()) {
// Value can wrap around, so fall back to the full 64-bit range.
SetInt64Range();
}
@@ -351,7 +347,7 @@
void set_max(const RangeBoundary& value) {
max_ = value;
- if (FLAG_limit_ints_to_64_bits && max_.IsInfinity()) {
+ if (max_.IsInfinity()) {
// Value can wrap around, so fall back to the full 64-bit range.
SetInt64Range();
}
@@ -529,10 +525,6 @@
// inference.
// Returns meaningful results for uses of non-smi/non-int definitions that
// have smi/int as a reaching type.
- // For Int typed definitions we use full Int64 range as a safe approximation
- // even though they might contain Bigint values because we only support
- // 64-bit operations in the optimized code - which means that Bigint will
- // cause deoptimization.
const Range* GetSmiRange(Value* value) const;
const Range* GetIntRange(Value* value) const;
diff --git a/runtime/vm/compiler/backend/range_analysis_test.cc b/runtime/vm/compiler/backend/range_analysis_test.cc
index 081c7e8..52c8694 100644
--- a/runtime/vm/compiler/backend/range_analysis_test.cc
+++ b/runtime/vm/compiler/backend/range_analysis_test.cc
@@ -106,42 +106,27 @@
Range* all = new Range(RangeBoundary::NegativeInfinity(),
RangeBoundary::PositiveInfinity());
- if (FLAG_limit_ints_to_64_bits) {
- EXPECT(all->Equals(&fullInt64Range));
- }
+ EXPECT(all->Equals(&fullInt64Range));
EXPECT(all->Overlaps(0, 0));
EXPECT(all->Overlaps(-1, 1));
EXPECT(!all->IsWithin(0, 100));
Range* positive = new Range(RangeBoundary::FromConstant(0),
RangeBoundary::PositiveInfinity());
- if (FLAG_limit_ints_to_64_bits) {
- EXPECT(positive->Equals(&fullInt64Range));
- } else {
- EXPECT(positive->IsPositive());
- EXPECT(!positive->Overlaps(-2, -1));
- }
+ EXPECT(positive->Equals(&fullInt64Range));
EXPECT(positive->Overlaps(0, 1));
EXPECT(positive->Overlaps(1, 100));
EXPECT(positive->Overlaps(-1, 0));
Range* negative = new Range(RangeBoundary::NegativeInfinity(),
RangeBoundary::FromConstant(-1));
- if (FLAG_limit_ints_to_64_bits) {
- EXPECT(positive->Equals(&fullInt64Range));
- } else {
- EXPECT(!negative->IsPositive());
- EXPECT(!negative->Overlaps(0, 1));
- EXPECT(!negative->Overlaps(1, 100));
- }
+ EXPECT(positive->Equals(&fullInt64Range));
EXPECT(negative->Overlaps(-1, 0));
EXPECT(negative->Overlaps(-2, -1));
Range* negpos = new Range(RangeBoundary::NegativeInfinity(),
RangeBoundary::FromConstant(0));
- if (FLAG_limit_ints_to_64_bits) {
- EXPECT(negpos->Equals(&fullInt64Range));
- }
+ EXPECT(negpos->Equals(&fullInt64Range));
EXPECT(!negpos->IsPositive());
Range* a = new Range(RangeBoundary::NegativeInfinity(),
@@ -153,53 +138,31 @@
Range* c = new Range(RangeBoundary::NegativeInfinity(),
RangeBoundary::FromConstant(32));
- if (FLAG_limit_ints_to_64_bits) {
- EXPECT(a->Equals(&fullInt64Range));
- EXPECT(b->Equals(&fullInt64Range));
- EXPECT(c->Equals(&fullInt64Range));
- } else {
- EXPECT(a->OnlyLessThanOrEqualTo(31));
- EXPECT(b->OnlyLessThanOrEqualTo(31));
- }
+ EXPECT(a->Equals(&fullInt64Range));
+ EXPECT(b->Equals(&fullInt64Range));
+ EXPECT(c->Equals(&fullInt64Range));
EXPECT(!c->OnlyLessThanOrEqualTo(31));
Range* unsatisfiable = new Range(RangeBoundary::PositiveInfinity(),
RangeBoundary::NegativeInfinity());
- if (FLAG_limit_ints_to_64_bits) {
- EXPECT(unsatisfiable->Equals(&fullInt64Range));
- } else {
- EXPECT(unsatisfiable->IsUnsatisfiable());
- }
+ EXPECT(unsatisfiable->Equals(&fullInt64Range));
Range* unsatisfiable_right = new Range(RangeBoundary::PositiveInfinity(),
RangeBoundary::FromConstant(0));
- if (FLAG_limit_ints_to_64_bits) {
- EXPECT(unsatisfiable_right->Equals(&fullInt64Range));
- } else {
- EXPECT(unsatisfiable_right->IsUnsatisfiable());
- }
+ EXPECT(unsatisfiable_right->Equals(&fullInt64Range));
Range* unsatisfiable_left = new Range(RangeBoundary::FromConstant(0),
RangeBoundary::NegativeInfinity());
- if (FLAG_limit_ints_to_64_bits) {
- EXPECT(unsatisfiable_left->Equals(&fullInt64Range));
- } else {
- EXPECT(unsatisfiable_left->IsUnsatisfiable());
- }
+ EXPECT(unsatisfiable_left->Equals(&fullInt64Range));
}
TEST_CASE(RangeUtils) {
- // Use kMin/kMax instead of +/-inf with limited 64-bit integers, as
- // any range with a +/-inf bound is converted to the full int64
- // range due to wrap-around.
+ // Use kMin/kMax instead of +/-inf as any range with a +/-inf bound is
+ // converted to the full int64 range due to wrap-around.
const RangeBoundary negativeInfinity =
- (FLAG_limit_ints_to_64_bits
- ? RangeBoundary::FromConstant(RangeBoundary::kMin)
- : RangeBoundary::NegativeInfinity());
+ RangeBoundary::FromConstant(RangeBoundary::kMin);
const RangeBoundary positiveInfinity =
- (FLAG_limit_ints_to_64_bits
- ? RangeBoundary::FromConstant(RangeBoundary::kMax)
- : RangeBoundary::PositiveInfinity());
+ RangeBoundary::FromConstant(RangeBoundary::kMax);
// [-inf, +inf].
const Range& range_0 = *(new Range(negativeInfinity, positiveInfinity));
@@ -285,53 +248,30 @@
}
TEST_CASE(RangeBinaryOp) {
- if (FLAG_limit_ints_to_64_bits) {
- Range* range_a =
- new Range(RangeBoundary::FromConstant(-1),
- RangeBoundary::FromConstant(RangeBoundary::kMax));
- range_a->Clamp(RangeBoundary::kRangeBoundaryInt32);
- EXPECT(range_a->min().ConstantValue() == -1);
- EXPECT(range_a->max().ConstantValue() == kMaxInt32);
- range_a->set_max(RangeBoundary::FromConstant(RangeBoundary::kMax));
+ Range* range_a = new Range(RangeBoundary::FromConstant(-1),
+ RangeBoundary::FromConstant(RangeBoundary::kMax));
+ range_a->Clamp(RangeBoundary::kRangeBoundaryInt32);
+ EXPECT(range_a->min().ConstantValue() == -1);
+ EXPECT(range_a->max().ConstantValue() == kMaxInt32);
+ range_a->set_max(RangeBoundary::FromConstant(RangeBoundary::kMax));
- Range* range_b = new Range(RangeBoundary::FromConstant(RangeBoundary::kMin),
- RangeBoundary::FromConstant(1));
- range_b->Clamp(RangeBoundary::kRangeBoundaryInt32);
- EXPECT(range_b->min().ConstantValue() == kMinInt32);
- EXPECT(range_b->max().ConstantValue() == 1);
- range_b->set_min(RangeBoundary::FromConstant(RangeBoundary::kMin));
+ Range* range_b = new Range(RangeBoundary::FromConstant(RangeBoundary::kMin),
+ RangeBoundary::FromConstant(1));
+ range_b->Clamp(RangeBoundary::kRangeBoundaryInt32);
+ EXPECT(range_b->min().ConstantValue() == kMinInt32);
+ EXPECT(range_b->max().ConstantValue() == 1);
+ range_b->set_min(RangeBoundary::FromConstant(RangeBoundary::kMin));
- {
- Range result;
- Range::BinaryOp(Token::kADD, range_a, range_b, NULL, &result);
- ASSERT(!Range::IsUnknown(&result));
- EXPECT(!result.min().IsNegativeInfinity());
- EXPECT(!result.max().IsPositiveInfinity());
- EXPECT(result.min().Equals(
- RangeBoundary::MinConstant(RangeBoundary::kRangeBoundaryInt64)));
- EXPECT(result.max().Equals(
- RangeBoundary::MaxConstant(RangeBoundary::kRangeBoundaryInt64)));
- }
- } else {
- Range* range_a = new Range(RangeBoundary::FromConstant(-1),
- RangeBoundary::PositiveInfinity());
- range_a->Clamp(RangeBoundary::kRangeBoundaryInt64);
- EXPECT(range_a->min().ConstantValue() == -1);
- EXPECT(range_a->max().ConstantValue() == RangeBoundary::kMax);
-
- Range* range_b = new Range(RangeBoundary::NegativeInfinity(),
- RangeBoundary::FromConstant(1));
- range_b->Clamp(RangeBoundary::kRangeBoundaryInt64);
- EXPECT(range_b->min().ConstantValue() == RangeBoundary::kMin);
- EXPECT(range_b->max().ConstantValue() == 1);
-
- {
- Range result;
- Range::BinaryOp(Token::kADD, range_a, range_b, NULL, &result);
- ASSERT(!Range::IsUnknown(&result));
- EXPECT(result.min().IsNegativeInfinity());
- EXPECT(result.max().IsPositiveInfinity());
- }
+ {
+ Range result;
+ Range::BinaryOp(Token::kADD, range_a, range_b, NULL, &result);
+ ASSERT(!Range::IsUnknown(&result));
+ EXPECT(!result.min().IsNegativeInfinity());
+ EXPECT(!result.max().IsPositiveInfinity());
+ EXPECT(result.min().Equals(
+ RangeBoundary::MinConstant(RangeBoundary::kRangeBoundaryInt64)));
+ EXPECT(result.max().Equals(
+ RangeBoundary::MaxConstant(RangeBoundary::kRangeBoundaryInt64)));
}
// Test that [5, 10] + [0, 5] = [5, 15].
diff --git a/runtime/vm/compiler/backend/redundancy_elimination.cc b/runtime/vm/compiler/backend/redundancy_elimination.cc
index faadfa6..651a3e6 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination.cc
@@ -3156,10 +3156,8 @@
// generator functions they may be context-allocated in which case they are
// not tracked in the environment anyway.
- const intptr_t parameter_count = flow_graph->num_direct_parameters();
- cdefs[catch_entry->raw_exception_var()->BitIndexIn(parameter_count)] = NULL;
- cdefs[catch_entry->raw_stacktrace_var()->BitIndexIn(parameter_count)] =
- NULL;
+ cdefs[flow_graph->EnvIndex(catch_entry->raw_exception_var())] = NULL;
+ cdefs[flow_graph->EnvIndex(catch_entry->raw_stacktrace_var())] = NULL;
for (BlockIterator block_it = flow_graph->reverse_postorder_iterator();
!block_it.Done(); block_it.Advance()) {
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index 637823d..f6d8cac 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -1626,14 +1626,12 @@
} else if (type.IsIntType()) {
ASSERT((*results)[0] == kSmiCid);
TryAddTest(results, kMintCid, true);
- TryAddTest(results, kBigintCid, true);
// Cannot deoptimize since all tests returning true have been added.
PurgeNegativeTestCidsEntries(results);
return false;
} else if (type.IsNumberType()) {
ASSERT((*results)[0] == kSmiCid);
TryAddTest(results, kMintCid, true);
- TryAddTest(results, kBigintCid, true);
TryAddTest(results, kDoubleCid, true);
PurgeNegativeTestCidsEntries(results);
return false;
diff --git a/runtime/vm/compiler/frontend/flow_graph_builder.cc b/runtime/vm/compiler/frontend/flow_graph_builder.cc
index e7ecaac..d950842 100644
--- a/runtime/vm/compiler/frontend/flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/flow_graph_builder.cc
@@ -837,7 +837,7 @@
}
Value* tmp_val = Bind(new (Z) LoadLocalInstr(*tmp_var, token_pos));
StoreInstanceFieldInstr* store = new (Z)
- StoreInstanceFieldInstr(Context::variable_offset(local.index()),
+ StoreInstanceFieldInstr(Context::variable_offset(local.index().value()),
context, tmp_val, kEmitStoreBarrier, token_pos);
Do(store);
return ExitTempLocalScope(value);
@@ -859,9 +859,9 @@
Type::ZoneHandle(Z, Type::null()),
token_pos));
}
- LoadFieldInstr* load =
- new (Z) LoadFieldInstr(context, Context::variable_offset(local.index()),
- local.type(), token_pos);
+ LoadFieldInstr* load = new (Z)
+ LoadFieldInstr(context, Context::variable_offset(local.index().value()),
+ local.type(), token_pos);
load->set_is_immutable(local.is_final());
return load;
} else {
@@ -2104,8 +2104,8 @@
}
intptr_t EffectGraphVisitor::GetCurrentTempLocalIndex() const {
- return kFirstLocalSlotFromFp - owner()->num_stack_locals() -
- owner()->args_pushed() - owner()->temp_count() + 1;
+ return -owner()->num_stack_locals() - owner()->args_pushed() -
+ owner()->temp_count() + 1;
}
LocalVariable* EffectGraphVisitor::EnterTempLocalScope(Value* value) {
@@ -2117,7 +2117,7 @@
new (Z) LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
String::ZoneHandle(Z, Symbols::New(T, name)),
*value->Type()->ToAbstractType());
- var->set_index(index);
+ var->set_index(VariableIndex(index));
return var;
}
@@ -2132,8 +2132,8 @@
node->InitializerAt(i)->Visit(&for_value);
Append(for_value);
ASSERT(!node->TempAt(i)->HasIndex() ||
- (node->TempAt(i)->index() == GetCurrentTempLocalIndex()));
- node->TempAt(i)->set_index(GetCurrentTempLocalIndex());
+ (node->TempAt(i)->index().value() == GetCurrentTempLocalIndex()));
+ node->TempAt(i)->set_index(VariableIndex(GetCurrentTempLocalIndex()));
}
}
@@ -3341,16 +3341,6 @@
token_pos, element_type, length, owner()->GetNextDeoptId());
return ReturnDefinition(create_array);
}
- case MethodRecognizer::kBigint_getDigits: {
- return ReturnDefinition(BuildNativeGetter(
- node, kind, Bigint::digits_offset(), Object::dynamic_type(),
- kTypedDataUint32ArrayCid));
- }
- case MethodRecognizer::kBigint_getUsed: {
- return ReturnDefinition(
- BuildNativeGetter(node, kind, Bigint::used_offset(),
- Type::ZoneHandle(Z, Type::SmiType()), kSmiCid));
- }
case MethodRecognizer::kLinkedHashMap_getIndex: {
return ReturnDefinition(BuildNativeGetter(
node, kind, LinkedHashMap::index_offset(), Object::dynamic_type(),
@@ -3399,11 +3389,6 @@
return ReturnDefinition(DoNativeSetterStoreValue(
node, LinkedHashMap::deleted_keys_offset(), kNoStoreBarrier));
}
- case MethodRecognizer::kBigint_getNeg: {
- return ReturnDefinition(
- BuildNativeGetter(node, kind, Bigint::neg_offset(),
- Type::ZoneHandle(Z, Type::BoolType()), kBoolCid));
- }
default:
break;
}
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 501c73f..23c595e 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -1007,6 +1007,7 @@
Field& field = Field::Handle(builder_->zone_);
Class& cls = Class::Handle(builder_->zone_);
String& name = String::Handle(builder_->zone_);
+ TypeArguments& type_args = TypeArguments::Handle(builder_->zone_);
const intptr_t obj_count = pool.Length();
for (intptr_t i = from_index; i < obj_count; ++i) {
const intptr_t tag = builder_->ReadTag();
@@ -1056,8 +1057,15 @@
}
} break;
case ConstantPoolTag::kICData: {
- StringIndex target = builder_->ReadStringReference();
- name = H.DartSymbolPlain(target).raw();
+ InvocationKind kind = static_cast<InvocationKind>(builder_->ReadByte());
+ if (kind == InvocationKind::getter) {
+ name = builder_->ReadNameAsGetterName().raw();
+ } else if (kind == InvocationKind::setter) {
+ name = builder_->ReadNameAsSetterName().raw();
+ } else {
+ ASSERT(kind == InvocationKind::method);
+ name = builder_->ReadNameAsMethodName().raw();
+ }
intptr_t arg_desc_index = builder_->ReadUInt();
ASSERT(arg_desc_index < i);
array ^= pool.ObjectAt(arg_desc_index);
@@ -1167,12 +1175,11 @@
cls =
H.LookupClassByKernelClass(builder_->ReadCanonicalNameReference());
obj = Instance::New(cls, Heap::kOld);
- intptr_t elem_index = builder_->ReadUInt();
- ASSERT(elem_index < i);
- elem = pool.ObjectAt(elem_index);
- if (!elem.IsNull()) {
- ASSERT(elem.IsTypeArguments());
- Instance::Cast(obj).SetTypeArguments(TypeArguments::Cast(elem));
+ intptr_t type_args_index = builder_->ReadUInt();
+ ASSERT(type_args_index < i);
+ type_args ^= pool.ObjectAt(type_args_index);
+ if (!type_args.IsNull()) {
+ Instance::Cast(obj).SetTypeArguments(type_args);
}
intptr_t num_fields = builder_->ReadUInt();
for (intptr_t j = 0; j < num_fields; j++) {
@@ -1193,12 +1200,10 @@
case kTypeArgumentsForInstanceAllocation: {
cls =
H.LookupClassByKernelClass(builder_->ReadCanonicalNameReference());
- intptr_t elem_index = builder_->ReadUInt();
- ASSERT(elem_index < i);
- elem = pool.ObjectAt(elem_index);
- ASSERT(elem.IsNull() || elem.IsTypeArguments());
- elem =
- Type::New(cls, TypeArguments::Cast(elem), TokenPosition::kNoSource);
+ intptr_t type_args_index = builder_->ReadUInt();
+ ASSERT(type_args_index < i);
+ type_args ^= pool.ObjectAt(type_args_index);
+ elem = Type::New(cls, type_args, TokenPosition::kNoSource);
elem = ClassFinalizer::FinalizeType(cls, Type::Cast(elem));
obj = Type::Cast(elem).arguments();
} break;
@@ -1264,6 +1269,8 @@
closure.SetParameterNameAt(pos, Symbols::ClosureParameter());
pos++;
+ const Library& lib = Library::Handle(
+ builder_->zone_, builder_->active_class()->klass->library());
for (intptr_t j = 0; j < positional_parameter_count; ++j, ++pos) {
VariableDeclarationHelper helper(builder_);
helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
@@ -1276,7 +1283,7 @@
closure.SetParameterTypeAt(pos, type);
closure.SetParameterNameAt(pos,
- H.DartSymbolObfuscate(helper.name_index_));
+ H.DartIdentifier(lib, helper.name_index_));
}
intptr_t named_parameter_count_check = builder_->ReadListLength();
@@ -1293,7 +1300,7 @@
closure.SetParameterTypeAt(pos, type);
closure.SetParameterNameAt(pos,
- H.DartSymbolObfuscate(helper.name_index_));
+ H.DartIdentifier(lib, helper.name_index_));
}
function_node_helper.SetJustRead(FunctionNodeHelper::kNamedParameters);
@@ -1396,11 +1403,12 @@
Script::Handle(Z, parsed_function->function().script()),
zone_,
TypedData::Handle(Z, parsed_function->function().KernelData()),
- parsed_function->function().KernelDataProgramOffset())),
+ parsed_function->function().KernelDataProgramOffset(),
+ &active_class_)),
type_translator_(builder_, /*finalize=*/true) {
H.InitFromScript(builder_->script());
- type_translator_.active_class_ = &active_class_;
- builder_->type_translator_.active_class_ = &active_class_;
+ ASSERT(type_translator_.active_class_ == &active_class_);
+ ASSERT(builder_->type_translator_.active_class_ == &active_class_);
}
StreamingScopeBuilder::~StreamingScopeBuilder() {
@@ -1436,7 +1444,7 @@
result_->this_variable =
MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
Symbols::This(), klass_type);
- result_->this_variable->set_index(0);
+ result_->this_variable->set_index(VariableIndex(0));
result_->this_variable->set_is_captured();
enclosing_scope = new (Z) LocalScope(NULL, 0, 0);
enclosing_scope->set_context_level(0);
@@ -3967,10 +3975,10 @@
}
void StreamingConstantEvaluator::EvaluateSymbolLiteral() {
- // The symbol value is read plain and obfuscated later.
- const String& symbol_value = H.DartSymbolPlain(
- builder_->ReadStringReference()); // read index into string table.
-
+ const Class& owner =
+ Class::Handle(Z, builder_->parsed_function()->function().Owner());
+ const Library& lib = Library::Handle(Z, owner.library());
+ String& symbol_value = H.DartIdentifier(lib, builder_->ReadStringReference());
const Class& symbol_class =
Class::ZoneHandle(Z, I->object_store()->symbol_class());
ASSERT(!symbol_class.IsNull());
@@ -6064,12 +6072,10 @@
// Copy captured parameters from the stack into the context.
LocalScope* scope = parsed_function()->node_sequence()->scope();
intptr_t parameter_count = dart_function.NumParameters();
- intptr_t parameter_index = parsed_function()->first_parameter_index();
-
const ParsedFunction& pf = *flow_graph_builder_->parsed_function_;
const Function& function = pf.function();
- for (intptr_t i = 0; i < parameter_count; ++i, --parameter_index) {
+ for (intptr_t i = 0; i < parameter_count; ++i) {
LocalVariable* variable = scope->VariableAt(i);
if (variable->is_captured()) {
LocalVariable& raw_parameter = *pf.RawParameterVariable(i);
@@ -6086,7 +6092,7 @@
body += LoadLocal(&raw_parameter);
body += flow_graph_builder_->StoreInstanceField(
TokenPosition::kNoSource,
- Context::variable_offset(variable->index()));
+ Context::variable_offset(variable->index().value()));
body += NullConstant();
body += StoreLocal(TokenPosition::kNoSource, &raw_parameter);
body += Drop();
@@ -7419,8 +7425,7 @@
}
ActiveClass* StreamingFlowGraphBuilder::active_class() {
- return (flow_graph_builder_ != NULL) ? &flow_graph_builder_->active_class_
- : NULL;
+ return active_class_;
}
ScopeBuildingResult* StreamingFlowGraphBuilder::scopes() {
@@ -10866,6 +10871,7 @@
// Step a) Create array of [TypeParameter] objects (without bound).
type_parameters = TypeArguments::New(type_parameter_count);
+ const Library& lib = Library::Handle(Z, active_class->klass->library());
{
AlternativeReadingScope alt(&reader_);
for (intptr_t i = 0; i < type_parameter_count; i++) {
@@ -10874,7 +10880,7 @@
parameter = TypeParameter::New(
set_on_class ? *active_class->klass : Class::Handle(Z),
parameterized_function, i,
- H.DartSymbolObfuscate(helper.name_index_), // read ith name index.
+ H.DartIdentifier(lib, helper.name_index_), // read ith name index.
null_bound, TokenPosition::kNoSource);
type_parameters.SetTypeAt(i, parameter);
}
@@ -10979,6 +10985,7 @@
pos++;
}
+ const Library& lib = Library::Handle(Z, active_class->klass->library());
for (intptr_t i = 0; i < positional_parameter_count; ++i, ++pos) {
// Read ith variable declaration.
VariableDeclarationHelper helper(this);
@@ -10991,7 +10998,7 @@
function.SetParameterTypeAt(
pos, type.IsMalformed() ? Type::dynamic_type() : type);
- function.SetParameterNameAt(pos, H.DartSymbolObfuscate(helper.name_index_));
+ function.SetParameterNameAt(pos, H.DartIdentifier(lib, helper.name_index_));
}
intptr_t named_parameter_count_check = ReadListLength(); // read list length.
@@ -11008,7 +11015,7 @@
function.SetParameterTypeAt(
pos, type.IsMalformed() ? Type::dynamic_type() : type);
- function.SetParameterNameAt(pos, H.DartSymbolObfuscate(helper.name_index_));
+ function.SetParameterNameAt(pos, H.DartIdentifier(lib, helper.name_index_));
}
function_node_helper->SetJustRead(FunctionNodeHelper::kNamedParameters);
@@ -11071,16 +11078,11 @@
return param_descriptor.raw();
}
-RawObject* StreamingFlowGraphBuilder::EvaluateMetadata(
- intptr_t kernel_offset,
- const Class& owner_class) {
+RawObject* StreamingFlowGraphBuilder::EvaluateMetadata(intptr_t kernel_offset) {
SetOffset(kernel_offset);
const Tag tag = PeekTag();
- // Setup active_class in type translator for type finalization.
- ActiveClass active_class;
- active_class.klass = &owner_class;
- type_translator_.set_active_class(&active_class);
+ ASSERT(active_class() != NULL);
if (tag == kClass) {
ClassHelper class_helper(this);
@@ -11109,8 +11111,6 @@
metadata_values.SetAt(i, value);
}
- type_translator_.set_active_class(NULL);
-
return metadata_values.raw();
}
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index 859d443..662514f 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -713,10 +713,6 @@
const Type& ReceiverType(const Class& klass);
- void set_active_class(ActiveClass* active_class) {
- active_class_ = active_class;
- }
-
private:
// Can build a malformed type.
void BuildTypeInternal(bool invalid_as_dynamic = false);
@@ -753,7 +749,7 @@
StreamingFlowGraphBuilder* builder_;
TranslationHelper& translation_helper_;
- ActiveClass* active_class_;
+ ActiveClass* const active_class_;
TypeParameterScope* type_parameter_scope_;
Zone* zone_;
AbstractType& result_;
@@ -1205,6 +1201,7 @@
data,
data_program_offset),
flow_graph_builder_(flow_graph_builder),
+ active_class_(&flow_graph_builder->active_class_),
constant_evaluator_(this),
type_translator_(this, /* finalize= */ true),
current_script_id_(-1),
@@ -1221,13 +1218,15 @@
Zone* zone,
const uint8_t* data_buffer,
intptr_t buffer_length,
- intptr_t data_program_offset)
+ intptr_t data_program_offset,
+ ActiveClass* active_class)
: KernelReaderHelper(zone,
translation_helper,
data_buffer,
buffer_length,
data_program_offset),
flow_graph_builder_(NULL),
+ active_class_(active_class),
constant_evaluator_(this),
type_translator_(this, /* finalize= */ true),
current_script_id_(-1),
@@ -1244,13 +1243,15 @@
const Script& script,
Zone* zone,
const TypedData& data,
- intptr_t data_program_offset)
+ intptr_t data_program_offset,
+ ActiveClass* active_class)
: KernelReaderHelper(zone,
translation_helper,
script,
data,
data_program_offset),
flow_graph_builder_(NULL),
+ active_class_(active_class),
constant_evaluator_(this),
type_translator_(this, /* finalize= */ true),
current_script_id_(-1),
@@ -1271,7 +1272,7 @@
Fragment BuildStatementAt(intptr_t kernel_offset);
RawObject* BuildParameterDescriptor(intptr_t kernel_offset);
- RawObject* EvaluateMetadata(intptr_t kernel_offset, const Class& owner_class);
+ RawObject* EvaluateMetadata(intptr_t kernel_offset);
void CollectTokenPositionsFor(
intptr_t script_index,
intptr_t initial_script_index,
@@ -1586,6 +1587,7 @@
void EnsureMetadataIsScanned();
FlowGraphBuilder* flow_graph_builder_;
+ ActiveClass* const active_class_;
StreamingConstantEvaluator constant_evaluator_;
StreamingDartTypeTranslator type_translator_;
intptr_t current_script_id_;
@@ -1735,7 +1737,7 @@
bool ShouldSkipConstant(NameIndex index);
NameIndex skip_vmservice_library_;
- ActiveClass* active_class_;
+ ActiveClass* const active_class_;
StreamingFlowGraphBuilder& builder_;
StreamingDartTypeTranslator& type_translator_;
StreamingConstantEvaluator const_evaluator_;
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 73619a7..4d9b1c6 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -487,6 +487,13 @@
return result;
}
+String& TranslationHelper::DartIdentifier(const Library& lib,
+ StringIndex string_index) {
+ String& name = DartString(string_index);
+ ManglePrivateName(lib, &name);
+ return name;
+}
+
const String& TranslationHelper::DartClassName(NameIndex kernel_class) {
ASSERT(IsClass(kernel_class));
String& name = DartString(CanonicalNameString(kernel_class));
@@ -1214,16 +1221,16 @@
if (exception_var->is_captured()) {
instructions += LoadLocal(context_variable);
instructions += LoadLocal(raw_exception_var);
- instructions +=
- StoreInstanceField(TokenPosition::kNoSource,
- Context::variable_offset(exception_var->index()));
+ instructions += StoreInstanceField(
+ TokenPosition::kNoSource,
+ Context::variable_offset(exception_var->index().value()));
}
if (stacktrace_var->is_captured()) {
instructions += LoadLocal(context_variable);
instructions += LoadLocal(raw_stacktrace_var);
- instructions +=
- StoreInstanceField(TokenPosition::kNoSource,
- Context::variable_offset(stacktrace_var->index()));
+ instructions += StoreInstanceField(
+ TokenPosition::kNoSource,
+ Context::variable_offset(stacktrace_var->index().value()));
}
// :saved_try_context_var can be captured in the context of
@@ -1532,7 +1539,8 @@
if (variable->is_captured()) {
Fragment instructions;
instructions += LoadContextAt(variable->owner()->context_level());
- instructions += LoadField(Context::variable_offset(variable->index()));
+ instructions +=
+ LoadField(Context::variable_offset(variable->index().value()));
return instructions;
} else {
return BaseFlowGraphBuilder::LoadLocal(variable);
@@ -1800,7 +1808,7 @@
instructions += LoadContextAt(variable->owner()->context_level());
instructions += LoadLocal(value);
instructions += StoreInstanceField(
- position, Context::variable_offset(variable->index()));
+ position, Context::variable_offset(variable->index().value()));
return instructions;
}
return StoreLocalRaw(position, variable);
@@ -1962,9 +1970,8 @@
symbol_name, Object::dynamic_type());
// Set the index relative to the base of the expression stack including
// outgoing arguments.
- variable->set_index(kFirstLocalSlotFromFp -
- parsed_function_->num_stack_locals() -
- pending_argument_count_ - index);
+ variable->set_index(VariableIndex(-parsed_function_->num_stack_locals() -
+ pending_argument_count_ - index));
// The value has uses as if it were a local variable. Mark the definition
// as used so that its temp index will not be cleared (causing it to never
@@ -2205,16 +2212,6 @@
body += LoadLocal(LookupVariable(first_positional_offset));
body += CreateArray();
break;
- case MethodRecognizer::kBigint_getDigits:
- body += LoadLocal(scopes_->this_variable);
- body += LoadNativeField(kind, Bigint::digits_offset(),
- Object::dynamic_type(), kTypedDataUint32ArrayCid);
- break;
- case MethodRecognizer::kBigint_getUsed:
- body += LoadLocal(scopes_->this_variable);
- body += LoadNativeField(kind, Bigint::used_offset(),
- Type::ZoneHandle(Z, Type::SmiType()), kSmiCid);
- break;
case MethodRecognizer::kLinkedHashMap_getIndex:
body += LoadLocal(scopes_->this_variable);
body += LoadNativeField(kind, LinkedHashMap::index_offset(),
@@ -2278,11 +2275,6 @@
kNoStoreBarrier);
body += NullConstant();
break;
- case MethodRecognizer::kBigint_getNeg:
- body += LoadLocal(scopes_->this_variable);
- body += LoadNativeField(kind, Bigint::neg_offset(),
- Type::ZoneHandle(Z, Type::BoolType()), kBoolCid);
- break;
default: {
String& name = String::ZoneHandle(Z, function.native_name());
if (function.IsGeneric() &&
@@ -2837,13 +2829,16 @@
Script& script = Script::Handle(Z, metadata_field.Script());
helper.InitFromScript(script);
+ const Class& owner_class = Class::Handle(Z, metadata_field.Owner());
+ ActiveClass active_class;
+ ActiveClassScope active_class_scope(&active_class, &owner_class);
+
StreamingFlowGraphBuilder streaming_flow_graph_builder(
&helper, Script::Handle(Z, metadata_field.Script()), Z,
TypedData::Handle(Z, metadata_field.KernelData()),
- metadata_field.KernelDataProgramOffset());
- const Class& owner_class = Class::Handle(Z, metadata_field.Owner());
+ metadata_field.KernelDataProgramOffset(), &active_class);
return streaming_flow_graph_builder.EvaluateMetadata(
- metadata_field.kernel_offset(), owner_class);
+ metadata_field.kernel_offset());
} else {
Thread* thread = Thread::Current();
Error& error = Error::Handle();
@@ -2865,7 +2860,7 @@
StreamingFlowGraphBuilder streaming_flow_graph_builder(
&helper, Script::Handle(Z, function.script()), Z,
TypedData::Handle(Z, function.KernelData()),
- function.KernelDataProgramOffset());
+ function.KernelDataProgramOffset(), /* active_class = */ NULL);
return streaming_flow_graph_builder.BuildParameterDescriptor(
function.kernel_offset());
} else {
@@ -2928,7 +2923,8 @@
}
StreamingFlowGraphBuilder streaming_flow_graph_builder(
- helper, script, zone_, kernel_data, data_kernel_offset);
+ helper, script, zone_, kernel_data, data_kernel_offset,
+ /* active_class = */ NULL);
streaming_flow_graph_builder.CollectTokenPositionsFor(
script.kernel_script_index(), entry_script.kernel_script_index(),
kernel_offset, token_positions, yield_positions);
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index 97e4aaa..1559f4f 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -395,6 +395,8 @@
const String& DartSymbolObfuscate(const char* content) const;
String& DartSymbolObfuscate(StringIndex string_index) const;
+ String& DartIdentifier(const Library& lib, StringIndex string_index);
+
const String& DartClassName(NameIndex kernel_class);
const String& DartConstructorName(NameIndex constructor);
@@ -911,7 +913,6 @@
friend class BreakableBlock;
friend class CatchBlock;
- friend class ConstantEvaluator;
friend class KernelReaderHelper;
friend class StreamingFlowGraphBuilder;
friend class ScopeBuilder;
diff --git a/runtime/vm/compiler/intrinsifier.cc b/runtime/vm/compiler/intrinsifier.cc
index d7ffab5..2e28b70 100644
--- a/runtime/vm/compiler/intrinsifier.cc
+++ b/runtime/vm/compiler/intrinsifier.cc
@@ -741,13 +741,9 @@
if (cid == kExternalOneByteStringCid) {
str = builder.AddDefinition(new LoadUntaggedInstr(
new Value(str), ExternalOneByteString::external_data_offset()));
- str = builder.AddDefinition(new LoadUntaggedInstr(
- new Value(str), RawExternalOneByteString::ExternalData::data_offset()));
} else if (cid == kExternalTwoByteStringCid) {
str = builder.AddDefinition(new LoadUntaggedInstr(
new Value(str), ExternalTwoByteString::external_data_offset()));
- str = builder.AddDefinition(new LoadUntaggedInstr(
- new Value(str), RawExternalTwoByteString::ExternalData::data_offset()));
}
Definition* result = builder.AddDefinition(new LoadIndexedInstr(
diff --git a/runtime/vm/compiler/intrinsifier_arm.cc b/runtime/vm/compiler/intrinsifier_arm.cc
index 201306d..9256dc6 100644
--- a/runtime/vm/compiler/intrinsifier_arm.cc
+++ b/runtime/vm/compiler/intrinsifier_arm.cc
@@ -634,8 +634,8 @@
CompareIntegers(assembler, GE);
}
-// This is called for Smi, Mint and Bigint receivers. The right argument
-// can be Smi, Mint, Bigint or double.
+// This is called for Smi and Mint receivers. The right argument
+// can be Smi, Mint or double.
void Intrinsifier::Integer_equalToInteger(Assembler* assembler) {
Label fall_through, true_label, check_for_mint;
// For integer receiver '===' check first.
@@ -663,7 +663,7 @@
__ b(&receiver_not_smi, NE);
// Left (receiver) is Smi, return false if right is not Double.
- // Note that an instance of Mint or Bigint never contains a value that can be
+ // Note that an instance of Mint never contains a value that can be
// represented by Smi.
__ CompareClassId(R0, kDoubleCid, R2);
@@ -1143,7 +1143,7 @@
__ Ret();
}
-void Intrinsifier::Bigint_estQuotientDigit(Assembler* assembler) {
+void Intrinsifier::Bigint_estimateQuotientDigit(Assembler* assembler) {
// No unsigned 64-bit / 32-bit divide instruction.
}
@@ -1305,7 +1305,7 @@
DoubleArithmeticOperations(assembler, Token::kDIV);
}
-// Left is double right is integer (Bigint, Mint or Smi)
+// Left is double, right is integer (Mint or Smi)
void Intrinsifier::Double_mulFromInteger(Assembler* assembler) {
if (TargetCPUFeatures::vfp_supported()) {
Label fall_through;
@@ -1576,14 +1576,14 @@
Register cid,
Register tmp,
Label* target) {
- RangeCheck(assembler, cid, tmp, kSmiCid, kBigintCid, kIfInRange, target);
+ RangeCheck(assembler, cid, tmp, kSmiCid, kMintCid, kIfInRange, target);
}
static void JumpIfNotInteger(Assembler* assembler,
Register cid,
Register tmp,
Label* target) {
- RangeCheck(assembler, cid, tmp, kSmiCid, kBigintCid, kIfNotInRange, target);
+ RangeCheck(assembler, cid, tmp, kSmiCid, kMintCid, kIfNotInRange, target);
}
static void JumpIfString(Assembler* assembler,
diff --git a/runtime/vm/compiler/intrinsifier_arm64.cc b/runtime/vm/compiler/intrinsifier_arm64.cc
index ef7fb20..ff9ef0e 100644
--- a/runtime/vm/compiler/intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/intrinsifier_arm64.cc
@@ -530,8 +530,8 @@
CompareIntegers(assembler, GE);
}
-// This is called for Smi, Mint and Bigint receivers. The right argument
-// can be Smi, Mint, Bigint or double.
+// This is called for Smi and Mint receivers. The right argument
+// can be Smi, Mint or double.
void Intrinsifier::Integer_equalToInteger(Assembler* assembler) {
Label fall_through, true_label, check_for_mint;
// For integer receiver '===' check first.
@@ -558,7 +558,7 @@
__ BranchIfNotSmi(R1, &receiver_not_smi); // Check receiver.
// Left (receiver) is Smi, return false if right is not Double.
- // Note that an instance of Mint or Bigint never contains a value that can be
+ // Note that an instance of Mint never contains a value that can be
// represented by Smi.
__ CompareClassId(R0, kDoubleCid);
@@ -1068,7 +1068,7 @@
__ ret();
}
-void Intrinsifier::Bigint_estQuotientDigit(Assembler* assembler) {
+void Intrinsifier::Bigint_estimateQuotientDigit(Assembler* assembler) {
// There is no 128-bit by 64-bit division instruction on arm64, so we use two
// 64-bit by 32-bit divisions and two 64-bit by 64-bit multiplications to
// adjust the two 32-bit digits of the estimated quotient.
@@ -1402,7 +1402,7 @@
DoubleArithmeticOperations(assembler, Token::kDIV);
}
-// Left is double right is integer (Bigint, Mint or Smi)
+// Left is double, right is integer (Mint or Smi)
void Intrinsifier::Double_mulFromInteger(Assembler* assembler) {
Label fall_through;
// Only smis allowed.
@@ -1637,14 +1637,14 @@
Register cid,
Register tmp,
Label* target) {
- RangeCheck(assembler, cid, tmp, kSmiCid, kBigintCid, kIfInRange, target);
+ RangeCheck(assembler, cid, tmp, kSmiCid, kMintCid, kIfInRange, target);
}
static void JumpIfNotInteger(Assembler* assembler,
Register cid,
Register tmp,
Label* target) {
- RangeCheck(assembler, cid, tmp, kSmiCid, kBigintCid, kIfNotInRange, target);
+ RangeCheck(assembler, cid, tmp, kSmiCid, kMintCid, kIfNotInRange, target);
}
static void JumpIfString(Assembler* assembler,
diff --git a/runtime/vm/compiler/intrinsifier_ia32.cc b/runtime/vm/compiler/intrinsifier_ia32.cc
index 2e46b55..931cdbf 100644
--- a/runtime/vm/compiler/intrinsifier_ia32.cc
+++ b/runtime/vm/compiler/intrinsifier_ia32.cc
@@ -628,8 +628,8 @@
CompareIntegers(assembler, GREATER_EQUAL);
}
-// This is called for Smi, Mint and Bigint receivers. The right argument
-// can be Smi, Mint, Bigint or double.
+// This is called for Smi and Mint receivers. The right argument
+// can be Smi, Mint or double.
void Intrinsifier::Integer_equalToInteger(Assembler* assembler) {
Label fall_through, true_label, check_for_mint;
// For integer receiver '===' check first.
@@ -655,7 +655,7 @@
__ j(NOT_ZERO, &receiver_not_smi);
// Left (receiver) is Smi, return false if right is not Double.
- // Note that an instance of Mint or Bigint never contains a value that can be
+ // Note that an instance of Mint never contains a value that can be
// represented by Smi.
__ movl(EAX, Address(ESP, +1 * kWordSize)); // Right argument.
__ CompareClassId(EAX, kDoubleCid, EDI);
@@ -1188,7 +1188,7 @@
__ ret();
}
-void Intrinsifier::Bigint_estQuotientDigit(Assembler* assembler) {
+void Intrinsifier::Bigint_estimateQuotientDigit(Assembler* assembler) {
// Pseudo code:
// static int _estQuotientDigit(Uint32List args, Uint32List digits, int i) {
// uint32_t yt = args[_YT]; // _YT == 1.
@@ -1402,7 +1402,7 @@
DoubleArithmeticOperations(assembler, Token::kDIV);
}
-// Left is double right is integer (Bigint, Mint or Smi)
+// Left is double, right is integer (Mint or Smi)
void Intrinsifier::Double_mulFromInteger(Assembler* assembler) {
Label fall_through;
// Only smis allowed.
@@ -1642,13 +1642,13 @@
const Condition kIfInRange = BELOW_EQUAL;
static void JumpIfInteger(Assembler* assembler, Register cid, Label* target) {
- RangeCheck(assembler, cid, kSmiCid, kBigintCid, kIfInRange, target);
+ RangeCheck(assembler, cid, kSmiCid, kMintCid, kIfInRange, target);
}
static void JumpIfNotInteger(Assembler* assembler,
Register cid,
Label* target) {
- RangeCheck(assembler, cid, kSmiCid, kBigintCid, kIfNotInRange, target);
+ RangeCheck(assembler, cid, kSmiCid, kMintCid, kIfNotInRange, target);
}
static void JumpIfString(Assembler* assembler, Register cid, Label* target) {
diff --git a/runtime/vm/compiler/intrinsifier_x64.cc b/runtime/vm/compiler/intrinsifier_x64.cc
index a3a0c9b..0d41621 100644
--- a/runtime/vm/compiler/intrinsifier_x64.cc
+++ b/runtime/vm/compiler/intrinsifier_x64.cc
@@ -591,8 +591,8 @@
CompareIntegers(assembler, GREATER_EQUAL);
}
-// This is called for Smi, Mint and Bigint receivers. The right argument
-// can be Smi, Mint, Bigint or double.
+// This is called for Smi and Mint receivers. The right argument
+// can be Smi, Mint or double.
void Intrinsifier::Integer_equalToInteger(Assembler* assembler) {
Label fall_through, true_label, check_for_mint;
const intptr_t kReceiverOffset = 2;
@@ -621,7 +621,7 @@
__ j(NOT_ZERO, &receiver_not_smi);
// Left (receiver) is Smi, return false if right is not Double.
- // Note that an instance of Mint or Bigint never contains a value that can be
+ // Note that an instance of Mint never contains a value that can be
// represented by Smi.
__ movq(RAX, Address(RSP, +kArgumentOffset * kWordSize));
__ CompareClassId(RAX, kDoubleCid);
@@ -1104,7 +1104,7 @@
__ ret();
}
-void Intrinsifier::Bigint_estQuotientDigit(Assembler* assembler) {
+void Intrinsifier::Bigint_estimateQuotientDigit(Assembler* assembler) {
// Pseudo code:
// static int _estQuotientDigit(Uint32List args, Uint32List digits, int i) {
// uint64_t yt = args[_YT_LO .. _YT]; // _YT_LO == 0, _YT == 1.
@@ -1335,7 +1335,7 @@
__ Bind(&fall_through);
}
-// Left is double right is integer (Bigint, Mint or Smi)
+// Left is double, right is integer (Mint or Smi)
void Intrinsifier::DoubleFromInteger(Assembler* assembler) {
Label fall_through;
__ movq(RAX, Address(RSP, +1 * kWordSize));
@@ -1551,13 +1551,13 @@
const Condition kIfInRange = BELOW_EQUAL;
static void JumpIfInteger(Assembler* assembler, Register cid, Label* target) {
- RangeCheck(assembler, cid, kSmiCid, kBigintCid, kIfInRange, target);
+ RangeCheck(assembler, cid, kSmiCid, kMintCid, kIfInRange, target);
}
static void JumpIfNotInteger(Assembler* assembler,
Register cid,
Label* target) {
- RangeCheck(assembler, cid, kSmiCid, kBigintCid, kIfNotInRange, target);
+ RangeCheck(assembler, cid, kSmiCid, kMintCid, kIfNotInRange, target);
}
static void JumpIfString(Assembler* assembler, Register cid, Label* target) {
diff --git a/runtime/vm/compiler/method_recognizer.h b/runtime/vm/compiler/method_recognizer.h
index 6f97c60..952a9d7 100644
--- a/runtime/vm/compiler/method_recognizer.h
+++ b/runtime/vm/compiler/method_recognizer.h
@@ -118,10 +118,7 @@
V(_Int32x4, withFlagZ, Int32x4WithFlagZ, Int32x4, 0x267acdfa) \
V(_Int32x4, withFlagW, Int32x4WithFlagW, Int32x4, 0x345ac675) \
V(_Int64List, [], Int64ArrayGetIndexed, Dynamic, 0x51eafb97) \
- V(_Int64List, []=, Int64ArraySetIndexed, Dynamic, 0x4ddf27d5) \
- V(_Bigint, get:_neg, Bigint_getNeg, Bool, 0x35608e23) \
- V(_Bigint, get:_used, Bigint_getUsed, Smi, 0x33bac590) \
- V(_Bigint, get:_digits, Bigint_getDigits, TypedDataUint32Array, 0x68df70f8) \
+ V(_Int64List, []=, Int64ArraySetIndexed, Dynamic, 0x376181fb) \
V(_HashVMBase, get:_index, LinkedHashMap_getIndex, TypedDataUint32Array, \
0x02477157) \
V(_HashVMBase, set:_index, LinkedHashMap_setIndex, Dynamic, 0x4fc8d5e0) \
@@ -153,7 +150,7 @@
V(_BigIntImpl, _absSub, Bigint_absSub, Dynamic, 0x1de5bd32) \
V(_BigIntImpl, _mulAdd, Bigint_mulAdd, Smi, 0x6f277966) \
V(_BigIntImpl, _sqrAdd, Bigint_sqrAdd, Smi, 0x68e4c8ea) \
- V(_BigIntImpl, _estimateQuotientDigit, Bigint_estQuotientDigit, Smi, \
+ V(_BigIntImpl, _estimateQuotientDigit, Bigint_estimateQuotientDigit, Smi, \
0x35456d91) \
V(_BigIntMontgomeryReduction, _mulMod, Montgomery_mulMod, Smi, 0x0f7b0375) \
V(_Double, >, Double_greaterThan, Bool, 0x4f1375a3) \
@@ -204,26 +201,26 @@
#define CORE_INTEGER_LIB_INTRINSIC_LIST(V) \
V(_IntegerImplementation, _addFromInteger, Integer_addFromInteger, \
Dynamic, 0x6a10c54a) \
- V(_IntegerImplementation, +, Integer_add, Dynamic, 0x4f5804de) \
+ V(_IntegerImplementation, +, Integer_add, Dynamic, 0x43d53af7) \
V(_IntegerImplementation, _subFromInteger, Integer_subFromInteger, Dynamic, \
0x3fa4b1ed) \
- V(_IntegerImplementation, -, Integer_sub, Dynamic, 0x183b13bf) \
+ V(_IntegerImplementation, -, Integer_sub, Dynamic, 0x2dc22e03) \
V(_IntegerImplementation, _mulFromInteger, Integer_mulFromInteger, \
Dynamic, 0x3216e299) \
- V(_IntegerImplementation, *, Integer_mul, Dynamic, 0x4014c3c0) \
+ V(_IntegerImplementation, *, Integer_mul, Dynamic, 0x4e7a1c24) \
V(_IntegerImplementation, _moduloFromInteger, Integer_moduloFromInteger, \
Dynamic, 0x6348b974) \
- V(_IntegerImplementation, ~/, Integer_truncDivide, Dynamic, 0x082b321e) \
+ V(_IntegerImplementation, ~/, Integer_truncDivide, Dynamic, 0x4efb2d39) \
V(_IntegerImplementation, unary-, Integer_negate, Dynamic, 0x428bf6fa) \
V(_IntegerImplementation, _bitAndFromInteger, Integer_bitAndFromInteger, \
Dynamic, 0x395b1678) \
- V(_IntegerImplementation, &, Integer_bitAnd, Dynamic, 0x32c46c28) \
+ V(_IntegerImplementation, &, Integer_bitAnd, Dynamic, 0x5ab35f30) \
V(_IntegerImplementation, _bitOrFromInteger, Integer_bitOrFromInteger, \
Dynamic, 0x6a36b395) \
- V(_IntegerImplementation, |, Integer_bitOr, Dynamic, 0x22d38a06) \
+ V(_IntegerImplementation, |, Integer_bitOr, Dynamic, 0x267fa107) \
V(_IntegerImplementation, _bitXorFromInteger, Integer_bitXorFromInteger, \
Dynamic, 0x72da93f0) \
- V(_IntegerImplementation, ^, Integer_bitXor, Dynamic, 0x79078347) \
+ V(_IntegerImplementation, ^, Integer_bitXor, Dynamic, 0x0c7b0230) \
V(_IntegerImplementation, _greaterThanFromInteger, \
Integer_greaterThanFromInt, Bool, 0x4a50ed58) \
V(_IntegerImplementation, >, Integer_greaterThan, Bool, 0x6599a6e1) \
@@ -233,8 +230,8 @@
V(_IntegerImplementation, <, Integer_lessThan, Bool, 0x365d1eba) \
V(_IntegerImplementation, <=, Integer_lessEqualThan, Bool, 0x74b5eb64) \
V(_IntegerImplementation, >=, Integer_greaterEqualThan, Bool, 0x4260c184) \
- V(_IntegerImplementation, <<, Integer_shl, Dynamic, 0x415da44a) \
- V(_IntegerImplementation, >>, Integer_sar, Dynamic, 0x6abbf70b) \
+ V(_IntegerImplementation, <<, Integer_shl, Dynamic, 0x4db3bf69) \
+ V(_IntegerImplementation, >>, Integer_sar, Dynamic, 0x70172b76) \
V(_Double, toInt, DoubleToInteger, Dynamic, 0x26ef344b) \
#define MATH_LIB_INTRINSIC_LIST(V) \
@@ -437,10 +434,15 @@
V(::, _classRangeCheckNegative, ClassRangeCheckNegated, 0x5acdfb75) \
V(::, _classRangeAssert, ClassRangeAssert, 0x6c77116e) \
V(::, _classIdEqualsAssert, ClassIdEqualsAssert, 0x09e0ae72) \
+ V(::, _toInt, ConvertMaskedInt, 0x713908fd) \
+ V(::, _toInt8, ConvertIntToInt8, 0x7484a780) \
+ V(::, _toUint8, ConvertIntToUint8, 0x0a15b522) \
+ V(::, _toClampedUint8, ConvertIntToClampedUint8, 0x564b0435) \
+ V(::, _toInt16, ConvertIntToInt16, 0x0a83fcc6) \
+ V(::, _toUint16, ConvertIntToUint16, 0x6087d1af) \
+ V(::, _toInt32, ConvertIntToInt32, 0x62b451b9) \
+ V(::, _toUint32, ConvertIntToUint32, 0x17a8e085) \
V(Lists, copy, ListsCopy, 0x40e974f6) \
- V(_Bigint, get:_neg, Bigint_getNeg, 0x35608e23) \
- V(_Bigint, get:_used, Bigint_getUsed, 0x33bac590) \
- V(_Bigint, get:_digits, Bigint_getDigits, 0x68df70f8) \
V(_HashVMBase, get:_index, LinkedHashMap_getIndex, 0x02477157) \
V(_HashVMBase, set:_index, LinkedHashMap_setIndex, 0x4fc8d5e0) \
V(_HashVMBase, get:_data, LinkedHashMap_getData, 0x2d7a70ac) \
@@ -468,7 +470,8 @@
V(_BigIntImpl, _absSub, Bigint_absSub, 0x1de5bd32) \
V(_BigIntImpl, _mulAdd, Bigint_mulAdd, 0x6f277966) \
V(_BigIntImpl, _sqrAdd, Bigint_sqrAdd, 0x68e4c8ea) \
- V(_BigIntImpl, _estimateQuotientDigit, Bigint_estQuotientDigit, 0x35456d91) \
+ V(_BigIntImpl, _estimateQuotientDigit, Bigint_estimateQuotientDigit, \
+ 0x35456d91) \
V(_BigIntMontgomeryReduction, _mulMod, Montgomery_mulMod, 0x0f7b0375) \
V(_Double, >, Double_greaterThan, 0x4f1375a3) \
V(_Double, >=, Double_greaterEqualThan, 0x4260c184) \
@@ -479,21 +482,21 @@
V(_Double, -, Double_sub, 0x3b69d466) \
V(_Double, *, Double_mul, 0x2bb9bd5d) \
V(_Double, /, Double_div, 0x483eee28) \
- V(_IntegerImplementation, +, Integer_add, 0x4f5804de) \
- V(_IntegerImplementation, -, Integer_sub, 0x183b13bf) \
- V(_IntegerImplementation, *, Integer_mul, 0x4014c3c0) \
- V(_IntegerImplementation, ~/, Integer_truncDivide, 0x082b321e) \
+ V(_IntegerImplementation, +, Integer_add, 0x43d53af7) \
+ V(_IntegerImplementation, -, Integer_sub, 0x2dc22e03) \
+ V(_IntegerImplementation, *, Integer_mul, 0x4e7a1c24) \
+ V(_IntegerImplementation, ~/, Integer_truncDivide, 0x4efb2d39) \
V(_IntegerImplementation, unary-, Integer_negate, 0x428bf6fa) \
- V(_IntegerImplementation, &, Integer_bitAnd, 0x32c46c28) \
- V(_IntegerImplementation, |, Integer_bitOr, 0x22d38a06) \
- V(_IntegerImplementation, ^, Integer_bitXor, 0x79078347) \
+ V(_IntegerImplementation, &, Integer_bitAnd, 0x5ab35f30) \
+ V(_IntegerImplementation, |, Integer_bitOr, 0x267fa107) \
+ V(_IntegerImplementation, ^, Integer_bitXor, 0x0c7b0230) \
V(_IntegerImplementation, >, Integer_greaterThan, 0x6599a6e1) \
V(_IntegerImplementation, ==, Integer_equal, 0x58abc487) \
V(_IntegerImplementation, <, Integer_lessThan, 0x365d1eba) \
V(_IntegerImplementation, <=, Integer_lessEqualThan, 0x74b5eb64) \
V(_IntegerImplementation, >=, Integer_greaterEqualThan, 0x4260c184) \
- V(_IntegerImplementation, <<, Integer_shl, 0x415da44a) \
- V(_IntegerImplementation, >>, Integer_sar, 0x6abbf70b) \
+ V(_IntegerImplementation, <<, Integer_shl, 0x4db3bf69) \
+ V(_IntegerImplementation, >>, Integer_sar, 0x70172b76) \
// A list of core functions that internally dispatch based on received id.
#define POLYMORPHIC_TARGET_LIST(V) \
diff --git a/runtime/vm/compiler_test.cc b/runtime/vm/compiler_test.cc
index bbc4d16..c73e135 100644
--- a/runtime/vm/compiler_test.cc
+++ b/runtime/vm/compiler_test.cc
@@ -7,6 +7,7 @@
#include "vm/class_finalizer.h"
#include "vm/code_patcher.h"
#include "vm/dart_api_impl.h"
+#include "vm/kernel_isolate.h"
#include "vm/object.h"
#include "vm/safepoint.h"
#include "vm/symbols.h"
@@ -170,8 +171,31 @@
expr_text = String::New("apa + ' ${calc(10)}' + dot");
Object& val = Object::Handle();
const Class& receiver_cls = Class::Handle(obj.clazz());
- val = Instance::Cast(obj).Evaluate(
- receiver_cls, expr_text, Array::empty_array(), Array::empty_array());
+
+ if (!KernelIsolate::IsRunning()) {
+ val = Instance::Cast(obj).Evaluate(
+ receiver_cls, expr_text, Array::empty_array(), Array::empty_array());
+ } else {
+ RawLibrary* raw_library = Library::RawCast(Api::UnwrapHandle(lib));
+ Library& lib_handle = Library::ZoneHandle(raw_library);
+
+ Dart_KernelCompilationResult compilation_result;
+ {
+ TransitionVMToNative transition(thread);
+ compilation_result = KernelIsolate::CompileExpressionToKernel(
+ expr_text.ToCString(), Array::empty_array(), Array::empty_array(),
+ String::Handle(lib_handle.url()).ToCString(), "A",
+ /* is_static= */ false);
+ }
+ EXPECT_EQ(Dart_KernelCompilationStatus_Ok, compilation_result.status);
+
+ const uint8_t* kernel_bytes = compilation_result.kernel;
+ intptr_t kernel_length = compilation_result.kernel_size;
+
+ val = Instance::Cast(obj).EvaluateCompiledExpression(
+ receiver_cls, kernel_bytes, kernel_length, Array::empty_array(),
+ Array::empty_array(), TypeArguments::null_type_arguments());
+ }
EXPECT(!val.IsNull());
EXPECT(!val.IsError());
EXPECT(val.IsString());
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index e845697..034de31 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -43,6 +43,7 @@
DECLARE_FLAG(bool, trace_time_all);
DEFINE_FLAG(bool, keep_code, false, "Keep deoptimized code for profiling.");
DEFINE_FLAG(bool, trace_shutdown, false, "Trace VM shutdown on stderr");
+DECLARE_FLAG(bool, strong);
Isolate* Dart::vm_isolate_ = NULL;
int64_t Dart::start_time_micros_ = 0;
@@ -306,7 +307,17 @@
Service::SetGetServiceAssetsCallback(get_service_assets);
}
- ServiceIsolate::Run();
+#if defined(DART_PRECOMPILED_RUNTIME)
+ const bool is_precompiled_runtime = true;
+#else
+ const bool is_precompiled_runtime = false;
+#endif
+
+ const bool is_dart2_aot_precompiler =
+ FLAG_strong && FLAG_precompiled_mode && !is_precompiled_runtime;
+ if (!is_dart2_aot_precompiler) {
+ ServiceIsolate::Run();
+ }
#ifndef DART_PRECOMPILED_RUNTIME
if (start_kernel_isolate) {
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 88854cd..201b5b9 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -211,23 +211,7 @@
int arg_index,
int64_t* value) {
ASSERT(value != NULL);
- if (Api::GetNativeIntegerArgument(arguments, arg_index, value)) {
- return true;
- }
- Thread* thread = arguments->thread();
- ASSERT(thread == Thread::Current());
- REUSABLE_OBJECT_HANDLESCOPE(thread);
- Object& obj = thread->ObjectHandle();
- obj = arguments->NativeArgAt(arg_index);
- intptr_t cid = obj.GetClassId();
- if (cid == kBigintCid) {
- const Bigint& bigint = Bigint::Cast(obj);
- if (bigint.FitsIntoInt64()) {
- *value = bigint.AsInt64Value();
- return true;
- }
- }
- return false;
+ return Api::GetNativeIntegerArgument(arguments, arg_index, value);
}
static bool GetNativeUnsignedIntegerArgument(NativeArguments* arguments,
@@ -239,20 +223,6 @@
*value = static_cast<uint64_t>(arg_value);
return true;
}
- Thread* thread = arguments->thread();
- ASSERT(thread == Thread::Current());
- REUSABLE_OBJECT_HANDLESCOPE(thread);
- Object& obj = thread->ObjectHandle();
- obj = arguments->NativeArgAt(arg_index);
- intptr_t cid = obj.GetClassId();
- if (cid == kBigintCid) {
- ASSERT(!Bigint::IsDisabled());
- const Bigint& bigint = Bigint::Cast(obj);
- if (bigint.FitsIntoUint64()) {
- *value = bigint.AsUint64Value();
- return true;
- }
- }
return false;
}
@@ -260,20 +230,7 @@
int arg_index,
double* value) {
ASSERT(value != NULL);
- if (Api::GetNativeDoubleArgument(arguments, arg_index, value)) {
- return true;
- }
- Thread* thread = arguments->thread();
- ASSERT(thread == Thread::Current());
- REUSABLE_OBJECT_HANDLESCOPE(thread);
- Object& obj = thread->ObjectHandle();
- obj = arguments->NativeArgAt(arg_index);
- intptr_t cid = obj.GetClassId();
- if (cid == kBigintCid) {
- *value = Bigint::Cast(obj).AsDoubleValue();
- return true;
- }
- return false;
+ return Api::GetNativeDoubleArgument(arguments, arg_index, value);
}
static Dart_Handle GetNativeFieldsOfArgument(NativeArguments* arguments,
@@ -565,9 +522,8 @@
intptr_t cid = raw_obj->GetClassId();
if (cid == kExternalOneByteStringCid) {
RawExternalOneByteString* raw_string =
- reinterpret_cast<RawExternalOneByteString*>(raw_obj)->ptr();
- ExternalStringData<uint8_t>* data = raw_string->external_data_;
- *peer = data->peer();
+ reinterpret_cast<RawExternalOneByteString*>(raw_obj);
+ *peer = raw_string->ptr()->peer_;
return true;
}
if (cid == kOneByteStringCid || cid == kTwoByteStringCid) {
@@ -577,9 +533,8 @@
}
if (cid == kExternalTwoByteStringCid) {
RawExternalTwoByteString* raw_string =
- reinterpret_cast<RawExternalTwoByteString*>(raw_obj)->ptr();
- ExternalStringData<uint16_t>* data = raw_string->external_data_;
- *peer = data->peer();
+ reinterpret_cast<RawExternalTwoByteString*>(raw_obj);
+ *peer = raw_string->ptr()->peer_;
return true;
}
return false;
@@ -2116,15 +2071,11 @@
*fits = true;
return Api::Success();
}
- // Slow path for Mints and Bigints.
+ // Slow path for type error.
DARTSCOPE(thread);
const Integer& int_obj = Api::UnwrapIntegerHandle(Z, integer);
- if (int_obj.IsNull()) {
- RETURN_TYPE_ERROR(Z, integer, Integer);
- }
- ASSERT(!Bigint::Cast(int_obj).FitsIntoInt64());
- *fits = false;
- return Api::Success();
+ ASSERT(int_obj.IsNull());
+ RETURN_TYPE_ERROR(Z, integer, Integer);
}
DART_EXPORT Dart_Handle Dart_IntegerFitsIntoUint64(Dart_Handle integer,
@@ -2138,19 +2089,14 @@
*fits = (Api::SmiValue(integer) >= 0);
return Api::Success();
}
- // Slow path for Mints and Bigints.
+ // Slow path for Mints.
DARTSCOPE(thread);
const Integer& int_obj = Api::UnwrapIntegerHandle(Z, integer);
if (int_obj.IsNull()) {
RETURN_TYPE_ERROR(Z, integer, Integer);
}
- ASSERT(!int_obj.IsSmi());
- if (int_obj.IsMint()) {
- *fits = !int_obj.IsNegative();
- } else {
- ASSERT(!Bigint::IsDisabled());
- *fits = Bigint::Cast(int_obj).FitsIntoUint64();
- }
+ ASSERT(int_obj.IsMint());
+ *fits = !int_obj.IsNegative();
return Api::Success();
}
@@ -2164,7 +2110,7 @@
NOHANDLESCOPE(thread);
return Api::NewHandle(thread, Smi::New(static_cast<intptr_t>(value)));
}
- // Slow path for Mints and Bigints.
+ // Slow path for Mints.
DARTSCOPE(thread);
CHECK_CALLBACK_STATE(thread);
return Api::NewHandle(thread, Integer::New(value));
@@ -2204,26 +2150,15 @@
*value = Api::SmiValue(integer);
return Api::Success();
}
- // Slow path for Mints and Bigints.
+ // Slow path for Mints.
DARTSCOPE(thread);
const Integer& int_obj = Api::UnwrapIntegerHandle(Z, integer);
if (int_obj.IsNull()) {
RETURN_TYPE_ERROR(Z, integer, Integer);
}
- ASSERT(!int_obj.IsSmi());
- if (int_obj.IsMint()) {
- *value = int_obj.AsInt64Value();
- return Api::Success();
- } else {
- ASSERT(!Bigint::IsDisabled());
- const Bigint& bigint = Bigint::Cast(int_obj);
- if (bigint.FitsIntoInt64()) {
- *value = bigint.AsInt64Value();
- return Api::Success();
- }
- }
- return Api::NewError("%s: Integer %s cannot be represented as an int64_t.",
- CURRENT_FUNC, int_obj.ToCString());
+ ASSERT(int_obj.IsMint());
+ *value = int_obj.AsInt64Value();
+ return Api::Success();
}
DART_EXPORT Dart_Handle Dart_IntegerToUint64(Dart_Handle integer,
@@ -2239,7 +2174,7 @@
return Api::Success();
}
}
- // Slow path for Mints and Bigints.
+ // Slow path for Mints.
DARTSCOPE(thread);
const Integer& int_obj = Api::UnwrapIntegerHandle(Z, integer);
if (int_obj.IsNull()) {
@@ -2247,18 +2182,12 @@
}
if (int_obj.IsSmi()) {
ASSERT(int_obj.IsNegative());
- } else if (int_obj.IsMint()) {
+ } else {
+ ASSERT(int_obj.IsMint());
if (!int_obj.IsNegative()) {
*value = int_obj.AsInt64Value();
return Api::Success();
}
- } else {
- ASSERT(!Bigint::IsDisabled());
- const Bigint& bigint = Bigint::Cast(int_obj);
- if (bigint.FitsIntoUint64()) {
- *value = bigint.AsUint64Value();
- return Api::Success();
- }
}
return Api::NewError("%s: Integer %s cannot be represented as a uint64_t.",
CURRENT_FUNC, int_obj.ToCString());
@@ -2404,32 +2333,44 @@
Dart_NewExternalLatin1String(const uint8_t* latin1_array,
intptr_t length,
void* peer,
- Dart_PeerFinalizer cback) {
+ intptr_t external_allocation_size,
+ Dart_WeakPersistentHandleFinalizer callback) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
if (latin1_array == NULL && length != 0) {
RETURN_NULL_ERROR(latin1_array);
}
+ if (callback == NULL) {
+ RETURN_NULL_ERROR(callback);
+ }
CHECK_LENGTH(length, String::kMaxElements);
CHECK_CALLBACK_STATE(T);
- return Api::NewHandle(T,
- String::NewExternal(latin1_array, length, peer, cback,
- SpaceForExternal(T, length)));
+ return Api::NewHandle(
+ T,
+ String::NewExternal(latin1_array, length, peer, external_allocation_size,
+ callback, SpaceForExternal(T, length)));
}
-DART_EXPORT Dart_Handle Dart_NewExternalUTF16String(const uint16_t* utf16_array,
- intptr_t length,
- void* peer,
- Dart_PeerFinalizer cback) {
+DART_EXPORT Dart_Handle
+Dart_NewExternalUTF16String(const uint16_t* utf16_array,
+ intptr_t length,
+ void* peer,
+ intptr_t external_allocation_size,
+ Dart_WeakPersistentHandleFinalizer callback) {
DARTSCOPE(Thread::Current());
if (utf16_array == NULL && length != 0) {
RETURN_NULL_ERROR(utf16_array);
}
+ if (callback == NULL) {
+ RETURN_NULL_ERROR(callback);
+ }
CHECK_LENGTH(length, String::kMaxElements);
CHECK_CALLBACK_STATE(T);
intptr_t bytes = length * sizeof(*utf16_array);
- return Api::NewHandle(T, String::NewExternal(utf16_array, length, peer, cback,
- SpaceForExternal(T, bytes)));
+ return Api::NewHandle(
+ T,
+ String::NewExternal(utf16_array, length, peer, external_allocation_size,
+ callback, SpaceForExternal(T, bytes)));
}
DART_EXPORT Dart_Handle Dart_StringToCString(Dart_Handle object,
@@ -2666,22 +2607,11 @@
if (retval.IsSmi()) {
*len = Smi::Cast(retval).Value();
return Api::Success();
- } else if (retval.IsMint() || retval.IsBigint()) {
- if (retval.IsMint()) {
- int64_t mint_value = Mint::Cast(retval).value();
- if (mint_value >= kIntptrMin && mint_value <= kIntptrMax) {
- *len = static_cast<intptr_t>(mint_value);
- }
- } else {
- // Check for a non-canonical Mint range value.
- ASSERT(retval.IsBigint());
- const Bigint& bigint = Bigint::Handle();
- if (bigint.FitsIntoInt64()) {
- int64_t bigint_value = bigint.AsInt64Value();
- if (bigint_value >= kIntptrMin && bigint_value <= kIntptrMax) {
- *len = static_cast<intptr_t>(bigint_value);
- }
- }
+ } else if (retval.IsMint()) {
+ int64_t mint_value = Mint::Cast(retval).value();
+ if (mint_value >= kIntptrMin && mint_value <= kIntptrMax) {
+ *len = static_cast<intptr_t>(mint_value);
+ return Api::Success();
}
return Api::NewError(
"Length of List object is greater than the "
@@ -5087,7 +5017,7 @@
if (Smi::IsValid(retval)) {
Api::SetSmiReturnValue(arguments, static_cast<intptr_t>(retval));
} else {
- // Slow path for Mints and Bigints.
+ // Slow path for Mints.
ASSERT_CALLBACK_STATE(arguments->thread());
TransitionNativeToVM transition(arguments->thread());
Api::SetIntegerReturnValue(arguments, retval);
@@ -5316,7 +5246,7 @@
CHECK_COMPILATION_ALLOWED(I);
kernel::Program* program = kernel::Program::ReadFromBuffer(
- buffer, buffer_size, false /* take_buffer_ownership */);
+ buffer, buffer_size, /*take_buffer_ownership=*/false);
const Object& tmp = kernel::KernelLoader::LoadEntireProgram(program);
delete program;
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 5867cf5..7569556 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -908,30 +908,10 @@
EXPECT_EQ(kIntegerVal2, out);
Dart_Handle val3 = Dart_NewIntegerFromHexCString(kIntegerVal3);
- if (FLAG_limit_ints_to_64_bits) {
- EXPECT(Dart_IsApiError(val3));
- } else {
- EXPECT(Dart_IsInteger(val3));
- result = Dart_IntegerFitsIntoInt64(val3, &fits);
- EXPECT_VALID(result);
- EXPECT(!fits);
-
- const char* chars = NULL;
- result = Dart_IntegerToHexCString(val3, &chars);
- EXPECT_VALID(result);
- EXPECT(!strcmp(kIntegerVal3, chars));
- }
+ EXPECT(Dart_IsApiError(val3));
Dart_Handle val4 = Dart_NewIntegerFromUint64(kIntegerVal4);
- if (FLAG_limit_ints_to_64_bits) {
- EXPECT(Dart_IsApiError(val4));
- } else {
- EXPECT_VALID(val4);
- uint64_t out4 = 0;
- result = Dart_IntegerToUint64(val4, &out4);
- EXPECT_VALID(result);
- EXPECT_EQ(kIntegerVal4, out4);
- }
+ EXPECT(Dart_IsApiError(val4));
Dart_Handle val5 = Dart_NewInteger(-1);
EXPECT_VALID(val5);
@@ -972,29 +952,6 @@
EXPECT_VALID(result);
EXPECT_STREQ(kIntTestCases[i].s, chars);
}
-
- if (!FLAG_limit_ints_to_64_bits) {
- const char* kStrTestCases[] = {
- "0x8000000000000000",
- "-0x8000000000000000",
- "0xFFFFFFFFFFFFFFFF",
- "-0xFFFFFFFFFFFFFFFF",
- "0xAABBCCDDEEFF00112233445566778899",
- "-0x1234567890ABCDEF1234567890ABCDEF",
- };
-
- const size_t kNumberOfStrTestCases =
- sizeof(kStrTestCases) / sizeof(kStrTestCases[0]);
-
- for (size_t i = 0; i < kNumberOfStrTestCases; ++i) {
- Dart_Handle val = Dart_NewIntegerFromHexCString(kStrTestCases[i]);
- EXPECT_VALID(val);
- const char* chars = NULL;
- Dart_Handle result = Dart_IntegerToHexCString(val, &chars);
- EXPECT_VALID(result);
- EXPECT_STREQ(kStrTestCases[i], chars);
- }
- }
}
TEST_CASE(DartAPI_IntegerFitsIntoInt64) {
@@ -1006,15 +963,7 @@
EXPECT(fits);
Dart_Handle above_max = Dart_NewIntegerFromHexCString("0x10000000000000000");
- if (FLAG_limit_ints_to_64_bits) {
- EXPECT(Dart_IsApiError(above_max));
- } else {
- EXPECT(Dart_IsInteger(above_max));
- fits = true;
- result = Dart_IntegerFitsIntoInt64(above_max, &fits);
- EXPECT_VALID(result);
- EXPECT(!fits);
- }
+ EXPECT(Dart_IsApiError(above_max));
Dart_Handle min = Dart_NewInteger(kMinInt64);
EXPECT(Dart_IsInteger(min));
@@ -1024,39 +973,15 @@
EXPECT(fits);
Dart_Handle below_min = Dart_NewIntegerFromHexCString("-0x10000000000000001");
- if (FLAG_limit_ints_to_64_bits) {
- EXPECT(Dart_IsApiError(below_min));
- } else {
- EXPECT(Dart_IsInteger(below_min));
- fits = true;
- result = Dart_IntegerFitsIntoInt64(below_min, &fits);
- EXPECT_VALID(result);
- EXPECT(!fits);
- }
+ EXPECT(Dart_IsApiError(below_min));
}
TEST_CASE(DartAPI_IntegerFitsIntoUint64) {
Dart_Handle max = Dart_NewIntegerFromUint64(kMaxUint64);
- if (FLAG_limit_ints_to_64_bits) {
- EXPECT(Dart_IsApiError(max));
- } else {
- EXPECT(Dart_IsInteger(max));
- bool fits = false;
- Dart_Handle result = Dart_IntegerFitsIntoUint64(max, &fits);
- EXPECT_VALID(result);
- EXPECT(fits);
- }
+ EXPECT(Dart_IsApiError(max));
Dart_Handle above_max = Dart_NewIntegerFromHexCString("0x10000000000000000");
- if (FLAG_limit_ints_to_64_bits) {
- EXPECT(Dart_IsApiError(above_max));
- } else {
- EXPECT(Dart_IsInteger(above_max));
- bool fits = true;
- Dart_Handle result = Dart_IntegerFitsIntoUint64(above_max, &fits);
- EXPECT_VALID(result);
- EXPECT(!fits);
- }
+ EXPECT(Dart_IsApiError(above_max));
Dart_Handle min = Dart_NewInteger(0);
EXPECT(Dart_IsInteger(min));
@@ -1109,6 +1034,10 @@
}
}
+static void NoopFinalizer(void* isolate_callback_data,
+ Dart_WeakPersistentHandle handle,
+ void* peer) {}
+
TEST_CASE(DartAPI_IsString) {
uint8_t latin1[] = {'o', 'n', 'e', 0xC2, 0xA2};
@@ -1147,8 +1076,8 @@
EXPECT_EQ(data8[i], latin1_array[i]);
}
- Dart_Handle ext8 =
- Dart_NewExternalLatin1String(data8, ARRAY_SIZE(data8), data8, NULL);
+ Dart_Handle ext8 = Dart_NewExternalLatin1String(
+ data8, ARRAY_SIZE(data8), data8, sizeof(data8), NoopFinalizer);
EXPECT_VALID(ext8);
EXPECT(Dart_IsString(ext8));
EXPECT(Dart_IsExternalString(ext8));
@@ -1169,8 +1098,8 @@
EXPECT_EQ(4, str_len);
EXPECT(!peer);
- Dart_Handle ext16 =
- Dart_NewExternalUTF16String(data16, ARRAY_SIZE(data16), data16, NULL);
+ Dart_Handle ext16 = Dart_NewExternalUTF16String(
+ data16, ARRAY_SIZE(data16), data16, sizeof(data16), NoopFinalizer);
EXPECT_VALID(ext16);
EXPECT(Dart_IsString(ext16));
EXPECT(Dart_IsExternalString(ext16));
@@ -1273,7 +1202,9 @@
}
};
-static void ExternalStringCallbackFinalizer(void* peer) {
+static void ExternalStringCallbackFinalizer(void* isolate_callback_data,
+ Dart_WeakPersistentHandle handle,
+ void* peer) {
*static_cast<int*>(peer) *= 2;
}
@@ -1286,12 +1217,14 @@
uint8_t data8[] = {'h', 'e', 'l', 'l', 'o'};
Dart_Handle obj8 = Dart_NewExternalLatin1String(
- data8, ARRAY_SIZE(data8), &peer8, ExternalStringCallbackFinalizer);
+ data8, ARRAY_SIZE(data8), &peer8, sizeof(data8),
+ ExternalStringCallbackFinalizer);
EXPECT_VALID(obj8);
uint16_t data16[] = {'h', 'e', 'l', 'l', 'o'};
Dart_Handle obj16 = Dart_NewExternalUTF16String(
- data16, ARRAY_SIZE(data16), &peer16, ExternalStringCallbackFinalizer);
+ data16, ARRAY_SIZE(data16), &peer16, sizeof(data16),
+ ExternalStringCallbackFinalizer);
EXPECT_VALID(obj16);
Dart_ExitScope();
@@ -1318,21 +1251,25 @@
static const uint8_t big_data8[16 * MB] = {
0,
};
- Dart_Handle big8 = Dart_NewExternalLatin1String(
- big_data8, ARRAY_SIZE(big_data8), NULL, NULL);
+ Dart_Handle big8 =
+ Dart_NewExternalLatin1String(big_data8, ARRAY_SIZE(big_data8), NULL,
+ sizeof(big_data8), NoopFinalizer);
EXPECT_VALID(big8);
static const uint16_t big_data16[16 * MB / 2] = {
0,
};
- Dart_Handle big16 = Dart_NewExternalUTF16String(
- big_data16, ARRAY_SIZE(big_data16), NULL, NULL);
+ Dart_Handle big16 =
+ Dart_NewExternalUTF16String(big_data16, ARRAY_SIZE(big_data16), NULL,
+ sizeof(big_data16), NoopFinalizer);
static const uint8_t small_data8[] = {'f', 'o', 'o'};
- Dart_Handle small8 = Dart_NewExternalLatin1String(
- small_data8, ARRAY_SIZE(small_data8), NULL, NULL);
+ Dart_Handle small8 =
+ Dart_NewExternalLatin1String(small_data8, ARRAY_SIZE(small_data8), NULL,
+ sizeof(small_data8), NoopFinalizer);
EXPECT_VALID(small8);
static const uint16_t small_data16[] = {'b', 'a', 'r'};
- Dart_Handle small16 = Dart_NewExternalUTF16String(
- small_data16, ARRAY_SIZE(small_data16), NULL, NULL);
+ Dart_Handle small16 =
+ Dart_NewExternalUTF16String(small_data16, ARRAY_SIZE(small_data16),
+ NULL, sizeof(small_data16), NoopFinalizer);
EXPECT_VALID(small16);
{
CHECK_API_SCOPE(thread);
@@ -4408,43 +4345,6 @@
EXPECT(Dart_IsError(result));
}
-TEST_CASE(DartAPI_NegativeNativeFieldInIsolateMessage) {
- const char* kScriptChars =
- "import 'dart:isolate';\n"
- "import 'dart:nativewrappers';\n"
- "echo(msg) {\n"
- " var data = msg[0];\n"
- " var reply = msg[1];\n"
- " reply.send('echoing ${data(1)}}');\n"
- "}\n"
- "class Test extends NativeFieldWrapperClass2 {\n"
- " Test(this.i, this.j);\n"
- " int i, j;\n"
- "}\n"
- "main() {\n"
- " var port = new RawReceivePort();\n"
- " var obj = new Test(1,2);\n"
- " var msg = [obj, port.sendPort];\n"
- " var snd = Isolate.spawn(echo, msg);\n"
- " port.handler = (msg) {\n"
- " port.close();\n"
- " print('from worker ${msg}');\n"
- " };\n"
- "}\n";
-
- CHECK_API_SCOPE(thread);
- HANDLESCOPE(thread);
-
- // Create a test library and Load up a test script in it.
- Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
-
- // Invoke 'main' which should spawn an isolate and try to send an
- // object with native fields over to the spawned isolate. This
- // should result in an unhandled exception which is checked.
- Dart_Handle retobj = Dart_Invoke(lib, NewString("main"), 0, NULL);
- EXPECT(Dart_IsError(retobj));
-}
-
TEST_CASE(DartAPI_GetStaticField_RunsInitializer) {
const char* kScriptChars =
"class TestClass {\n"
@@ -5312,14 +5212,8 @@
EXPECT(arg_values[1].as_int32 == 77);
- // Note: this particular value is chosen for the following reasons.
- // 1) When wrapped-around, it should not fit into int32, because this unit
- // test verifies that getting it as int32 produces error.
- // 2) It should be large enough to exercise Bigints with unlimited ints, so
- // it should be > MaxInt64.
- // Given these constraints, any value between MaxInt64+1 and
- // MaxUint64-MaxInt32-1 would work. Value 0x8000000000000000 is in this
- // range and easy to produce without using a large integer literal.
+ // When wrapped-around, this value should not fit into int32, because this
+ // unit test verifies that getting it as int32 produces error.
EXPECT(arg_values[2].as_uint64 == 0x8000000000000000LL);
EXPECT(arg_values[3].as_bool == true);
@@ -5423,7 +5317,7 @@
" MyObject obj1 = MyObject.createObject();"
" MyObject obj2 = MyObject.createObject();"
" return obj1.accessFields(77,"
- " 1 << 63,"
+ " 0x8000000000000000,"
" true,"
" 3.14,"
" str,"
@@ -5436,9 +5330,11 @@
reinterpret_cast<Dart_NativeEntryResolver>(native_args_lookup));
const char* ascii_str = "string";
+ intptr_t ascii_str_length = strlen(ascii_str);
Dart_Handle extstr = Dart_NewExternalLatin1String(
- reinterpret_cast<const uint8_t*>(ascii_str), strlen(ascii_str),
- reinterpret_cast<void*>(&native_arg_str_peer), NULL);
+ reinterpret_cast<const uint8_t*>(ascii_str), ascii_str_length,
+ reinterpret_cast<void*>(&native_arg_str_peer), ascii_str_length,
+ NoopFinalizer);
Dart_Handle args[1];
args[0] = extstr;
@@ -7613,13 +7509,7 @@
EXPECT(Dart_IsError(Dart_SetPeer(smi, &out)));
out = &out;
Dart_Handle big = Dart_NewIntegerFromHexCString("0x10000000000000000");
- if (FLAG_limit_ints_to_64_bits) {
- EXPECT(Dart_IsApiError(big));
- } else {
- EXPECT(Dart_IsError(Dart_GetPeer(big, &out)));
- EXPECT(out == &out);
- EXPECT(Dart_IsError(Dart_SetPeer(big, &out)));
- }
+ EXPECT(Dart_IsApiError(big));
out = &out;
Dart_Handle dbl = Dart_NewDouble(0.0);
EXPECT(Dart_IsError(Dart_GetPeer(dbl, &out)));
@@ -8056,8 +7946,8 @@
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
uint8_t data8[] = {'W'};
- Dart_Handle ext8 =
- Dart_NewExternalLatin1String(data8, ARRAY_SIZE(data8), data8, NULL);
+ Dart_Handle ext8 = Dart_NewExternalLatin1String(
+ data8, ARRAY_SIZE(data8), data8, sizeof(data8), NoopFinalizer);
EXPECT_VALID(ext8);
EXPECT(Dart_IsString(ext8));
EXPECT(Dart_IsExternalString(ext8));
diff --git a/runtime/vm/dart_api_message.cc b/runtime/vm/dart_api_message.cc
index f28e915..aeb24be 100644
--- a/runtime/vm/dart_api_message.cc
+++ b/runtime/vm/dart_api_message.cc
@@ -101,19 +101,6 @@
_Dart_CObject* ApiMessageReader::singleton_uint32_typed_data_ = NULL;
-Dart_CObject* ApiMessageReader::AllocateDartCObjectBigint() {
- Dart_CObject* value = AllocateDartCObject(Dart_CObject_kBigint);
- value->value.as_bigint.neg = false;
- value->value.as_bigint.used = 0;
- if (singleton_uint32_typed_data_ == NULL) {
- singleton_uint32_typed_data_ =
- AllocateDartCObjectTypedData(Dart_TypedData_kUint32, 0);
- }
- value->value.as_bigint.digits = singleton_uint32_typed_data_;
- value->type = Dart_CObject_kBigint;
- return value;
-}
-
Dart_CObject* ApiMessageReader::AllocateDartCObjectDouble(double val) {
Dart_CObject* value = AllocateDartCObject(Dart_CObject_kDouble);
value->value.as_double = val;
@@ -572,27 +559,6 @@
AddBackRef(object_id, object, kIsDeserialized);
return object;
}
- case kBigintCid: {
- // Allocate an empty bigint which will be updated when its contents
- // has been deserialized.
- Dart_CObject* object = AllocateDartCObjectBigint();
- AddBackRef(object_id, object, kIsDeserialized);
- Dart_CObject* neg_obj = ReadObjectImpl();
- ASSERT(neg_obj->type == Dart_CObject_kBool);
- const bool neg = neg_obj->value.as_bool;
- Dart_CObject* used_obj = ReadObjectImpl();
- ASSERT(used_obj->type == Dart_CObject_kInt32);
- const intptr_t used = used_obj->value.as_int32;
- Dart_CObject* digits = ReadObjectImpl();
- ASSERT(digits->type == Dart_CObject_kTypedData);
- ASSERT(digits->value.as_typed_data.type == Dart_TypedData_kUint32);
- ASSERT(digits->value.as_typed_data.length >= 4 * used);
- // Update the bigint object.
- object->value.as_bigint.neg = neg;
- object->value.as_bigint.used = used;
- object->value.as_bigint.digits = digits;
- return object;
- }
case kDoubleCid: {
// Doubles are handled specially when being sent as part of message
// snapshots.
@@ -1092,24 +1058,6 @@
case Dart_CObject_kInt64:
WriteInt64(object);
break;
- case Dart_CObject_kBigint: {
- // Write out the serialization header value for this object.
- WriteInlinedHeader(object);
- // Write out the class and tags information.
- WriteIndexedObject(kBigintCid);
- WriteTags(0);
- // Write neg field.
- if (object->value.as_bigint.neg) {
- WriteVMIsolateObject(kTrueValue);
- } else {
- WriteVMIsolateObject(kFalseValue);
- }
- // Write used field.
- WriteSmi(object->value.as_bigint.used);
- // Write digits as TypedData (or NullObject).
- WriteCObject(object->value.as_bigint.digits);
- break;
- }
case Dart_CObject_kDouble:
WriteVMIsolateObject(kDoubleObject);
WriteDouble(object->value.as_double);
diff --git a/runtime/vm/dart_api_message.h b/runtime/vm/dart_api_message.h
index 9c9a3ab..082fc08 100644
--- a/runtime/vm/dart_api_message.h
+++ b/runtime/vm/dart_api_message.h
@@ -84,8 +84,6 @@
Dart_CObject* AllocateDartCObjectInt32(int32_t value);
// Allocates a Dart_CObject object for for a 64-bit integer.
Dart_CObject* AllocateDartCObjectInt64(int64_t value);
- // Allocates an empty Dart_CObject object for a bigint to be filled up later.
- Dart_CObject* AllocateDartCObjectBigint();
// Allocates a Dart_CObject object for a double.
Dart_CObject* AllocateDartCObjectDouble(double value);
// Allocates a Dart_CObject object for string data.
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 2d50aad..c157f1a 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -25,6 +25,16 @@
RawObject* DartEntry::InvokeFunction(const Function& function,
const Array& arguments) {
ASSERT(Thread::Current()->IsMutatorThread());
+
+ // We use a kernel2kernel constant evaluator in Dart 2.0 AOT compilation
+ // and never start the VM service isolate. So we should never end up invoking
+ // any dart code in the Dart 2.0 AOT compiler.
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ if (Isolate::Current()->strong() && FLAG_precompiled_mode) {
+ UNREACHABLE();
+ }
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
+
const int kTypeArgsLen = 0; // No support to pass type args to generic func.
const Array& arguments_descriptor =
Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, arguments.Length()));
@@ -52,11 +62,15 @@
ASSERT(os_thread != NULL);
os_thread->RefineStackBoundsFromSP(current_sp);
- // Save the Thread's current stack limit and adjust the stack
- // limit based on the thread's stack_base.
+ // Save the Thread's current stack limit and adjust the stack limit.
ASSERT(thread->isolate() == Isolate::Current());
saved_stack_limit_ = thread->saved_stack_limit();
- thread->SetStackLimitFromStackBase(os_thread->stack_base());
+#if defined(USING_SIMULATOR)
+ thread->SetStackLimit(Simulator::Current()->stack_limit());
+#else
+ thread->SetStackLimit(OSThread::Current()->stack_limit_with_headroom());
+ // TODO(regis): For now, the interpreter is using its own stack limit.
+#endif
#if defined(USING_SAFE_STACK)
saved_safestack_limit_ = OSThread::GetCurrentSafestackPointer();
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index f6587d6..e922ec77 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -260,7 +260,16 @@
vars_initialized_(false),
var_descriptors_(LocalVarDescriptors::ZoneHandle()),
desc_indices_(8),
- pc_desc_(PcDescriptors::ZoneHandle()) {}
+ pc_desc_(PcDescriptors::ZoneHandle()) {
+ // TODO(regis): If debugging of interpreted code is required, recognize an
+ // interpreted activation frame and respect alternate frame layout.
+ // For now, punt.
+#if defined(DART_USE_INTERPRETER)
+ if (function_.Bytecode() == code_.raw()) {
+ UNIMPLEMENTED();
+ }
+#endif
+}
ActivationFrame::ActivationFrame(Kind kind)
: pc_(0),
@@ -732,15 +741,16 @@
if (!live_frame_) {
ASSERT(kind == RawLocalVarDescriptors::kContextVar);
}
+ const auto variable_index = VariableIndex(var_info.index());
if (kind == RawLocalVarDescriptors::kStackVar) {
- return GetStackVar(var_info.index());
+ return GetStackVar(variable_index);
} else {
ASSERT(kind == RawLocalVarDescriptors::kContextVar);
if (!live_frame_) {
ASSERT(!ctx_.IsNull());
- return ctx_.At(var_info.index());
+ return ctx_.At(variable_index.value());
}
- return GetContextVar(var_info.scope_id, var_info.index());
+ return GetContextVar(var_info.scope_id, variable_index.value());
}
}
}
@@ -959,7 +969,8 @@
OS::PrintErr("\tFound saved current ctx at index %d\n",
var_info.index());
}
- obj = GetStackVar(var_info.index());
+ const auto variable_index = VariableIndex(var_info.index());
+ obj = GetStackVar(variable_index);
if (obj.IsClosure()) {
ASSERT(function().name() == Symbols::Call().raw());
ASSERT(function().IsInvokeFieldDispatcher());
@@ -984,11 +995,12 @@
var_descriptors_.GetInfo(i, &var_info);
if (var_descriptors_.GetName(i) == Symbols::AsyncOperation().raw()) {
const int8_t kind = var_info.kind();
+ const auto variable_index = VariableIndex(var_info.index());
if (kind == RawLocalVarDescriptors::kStackVar) {
- return GetStackVar(var_info.index());
+ return GetStackVar(variable_index);
} else {
ASSERT(kind == RawLocalVarDescriptors::kContextVar);
- return GetContextVar(var_info.scope_id, var_info.index());
+ return GetContextVar(var_info.scope_id, variable_index.value());
}
}
}
@@ -1099,8 +1111,9 @@
// can be in a number of places in the caller's frame depending on how many
// were actually supplied at the call site, but they are copied to a fixed
// place in the callee's frame.
+
return GetVariableValue(
- LocalVarAddress(fp(), (kFirstLocalSlotFromFp - index)));
+ LocalVarAddress(fp(), FrameSlotForVariableIndex(-index)));
} else {
intptr_t reverse_index = num_parameters - index;
return GetVariableValue(ParamAddress(fp(), reverse_index));
@@ -1112,7 +1125,8 @@
return GetParameter(0);
}
-RawObject* ActivationFrame::GetStackVar(intptr_t slot_index) {
+RawObject* ActivationFrame::GetStackVar(VariableIndex variable_index) {
+ const intptr_t slot_index = FrameSlotForVariableIndex(variable_index.value());
if (deopt_frame_.IsNull()) {
return GetVariableValue(LocalVarAddress(fp(), slot_index));
} else {
@@ -1208,11 +1222,12 @@
*visible_end_token_pos = var_info.end_pos;
ASSERT(value != NULL);
const int8_t kind = var_info.kind();
+ const auto variable_index = VariableIndex(var_info.index());
if (kind == RawLocalVarDescriptors::kStackVar) {
- *value = GetStackVar(var_info.index());
+ *value = GetStackVar(variable_index);
} else {
ASSERT(kind == RawLocalVarDescriptors::kContextVar);
- *value = GetContextVar(var_info.scope_id, var_info.index());
+ *value = GetContextVar(var_info.scope_id, variable_index.value());
}
}
@@ -1286,22 +1301,48 @@
return (var_name.Length() >= 1) && (var_name.CharAt(0) == '_');
}
-RawObject* ActivationFrame::Evaluate(const String& expr,
- const GrowableObjectArray& param_names,
- const GrowableObjectArray& param_values) {
+RawObject* ActivationFrame::EvaluateCompiledExpression(
+ const uint8_t* kernel_bytes,
+ intptr_t kernel_length,
+ const Array& type_definitions,
+ const Array& arguments,
+ const TypeArguments& type_arguments) {
+ if (function().is_static()) {
+ const Class& cls = Class::Handle(function().Owner());
+ return cls.EvaluateCompiledExpression(kernel_bytes, kernel_length,
+ type_definitions, arguments,
+ type_arguments);
+ } else {
+ const Object& receiver = Object::Handle(GetReceiver());
+ const Class& method_cls = Class::Handle(function().origin());
+ ASSERT(receiver.IsInstance() || receiver.IsNull());
+ if (!(receiver.IsInstance() || receiver.IsNull())) {
+ return Object::null();
+ }
+ const Instance& inst = Instance::Cast(receiver);
+ return inst.EvaluateCompiledExpression(method_cls, kernel_bytes,
+ kernel_length, type_definitions,
+ arguments, type_arguments);
+ }
+}
+
+RawTypeArguments* ActivationFrame::BuildParameters(
+ const GrowableObjectArray& param_names,
+ const GrowableObjectArray& param_values,
+ const GrowableObjectArray& type_params_names) {
GetDescIndices();
bool type_arguments_available = false;
- TypeArguments& type_arguments = TypeArguments::Handle();
String& name = String::Handle();
String& existing_name = String::Handle();
Object& value = Instance::Handle();
+ TypeArguments& type_arguments = TypeArguments::Handle();
intptr_t num_variables = desc_indices_.length();
for (intptr_t i = 0; i < num_variables; i++) {
TokenPosition ignore;
VariableAt(i, &name, &ignore, &ignore, &ignore, &value);
if (name.Equals(Symbols::FunctionTypeArgumentsVar())) {
type_arguments_available = true;
- type_arguments = TypeArguments::RawCast(value.raw());
+ type_arguments ^= value.raw();
} else if (!name.Equals(Symbols::This()) &&
!IsSyntheticVariableName(name)) {
if (IsPrivateVariableName(name)) {
@@ -1325,15 +1366,14 @@
}
}
- Array& type_param_names = Array::Handle();
if ((function().IsGeneric() || function().HasGenericParent()) &&
type_arguments_available) {
intptr_t num_vars =
function().NumTypeParameters() + function().NumParentTypeParameters();
- type_param_names = Array::New(num_vars);
+ type_params_names.Grow(num_vars);
+ type_params_names.SetLength(num_vars);
TypeArguments& type_params = TypeArguments::Handle();
TypeParameter& type_param = TypeParameter::Handle();
- String& name = String::Handle();
Function& current = Function::Handle(function().raw());
for (intptr_t i = 0; !current.IsNull(); i += current.NumTypeParameters(),
current = current.parent_function()) {
@@ -1343,26 +1383,41 @@
name = type_param.Name();
// Write the names in backwards so they match up with the order of the
// types in 'type_arguments'.
- type_param_names.SetAt(num_vars - (i + j) - 1, name);
+ type_params_names.SetAt(num_vars - (i + j) - 1, name);
}
}
- if (type_arguments.IsNull()) {
- type_arguments = TypeArguments::New(num_vars);
- for (intptr_t i = 0; i < num_vars; ++i) {
- type_arguments.SetTypeAt(i, Object::dynamic_type());
+ if (!type_arguments.IsNull()) {
+ if (type_arguments.Length() == 0) {
+ for (intptr_t i = 0; i < num_vars; ++i) {
+ type_arguments.SetTypeAt(i, Object::dynamic_type());
+ }
}
+ ASSERT(type_arguments.Length() == num_vars);
}
- ASSERT(type_arguments.Length() == num_vars);
- } else {
- type_param_names = Object::empty_array().raw();
}
+ return type_arguments.raw();
+}
+
+RawObject* ActivationFrame::Evaluate(const String& expr,
+ const GrowableObjectArray& param_names,
+ const GrowableObjectArray& param_values) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+ return Object::null();
+#else
+ Zone* zone = Thread::Current()->zone();
+ const GrowableObjectArray& type_params_names =
+ GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
+ TypeArguments& type_arguments = TypeArguments::Handle(
+ zone, BuildParameters(param_names, param_values, type_params_names));
+
if (function().is_static()) {
const Class& cls = Class::Handle(function().Owner());
- return cls.Evaluate(expr,
- Array::Handle(Array::MakeFixedLength(param_names)),
- Array::Handle(Array::MakeFixedLength(param_values)),
- type_param_names, type_arguments);
+ return cls.Evaluate(
+ expr, Array::Handle(zone, Array::MakeFixedLength(param_names)),
+ Array::Handle(zone, Array::MakeFixedLength(param_values)),
+ Array::Handle(zone, Array::MakeFixedLength(type_params_names)),
+ type_arguments);
} else {
const Object& receiver = Object::Handle(GetReceiver());
const Class& method_cls = Class::Handle(function().origin());
@@ -1371,13 +1426,14 @@
return Object::null();
}
const Instance& inst = Instance::Cast(receiver);
- return inst.Evaluate(method_cls, expr,
- Array::Handle(Array::MakeFixedLength(param_names)),
- Array::Handle(Array::MakeFixedLength(param_values)),
- type_param_names, type_arguments);
+ return inst.Evaluate(
+ method_cls, expr,
+ Array::Handle(zone, Array::MakeFixedLength(param_names)),
+ Array::Handle(zone, Array::MakeFixedLength(param_values)),
+ Array::Handle(zone, Array::MakeFixedLength(type_params_names)),
+ type_arguments);
}
- UNREACHABLE();
- return Object::null();
+#endif
}
const char* ActivationFrame::ToCString() {
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index b88d742..fedfed1 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -7,8 +7,10 @@
#include "include/dart_tools_api.h"
+#include "vm/kernel_isolate.h"
#include "vm/object.h"
#include "vm/port.h"
+#include "vm/scopes.h"
#include "vm/service_event.h"
#include "vm/simulator.h"
@@ -325,10 +327,21 @@
const Context& GetSavedCurrentContext();
RawObject* GetAsyncOperation();
+ RawTypeArguments* BuildParameters(
+ const GrowableObjectArray& param_names,
+ const GrowableObjectArray& param_values,
+ const GrowableObjectArray& type_params_names);
+
RawObject* Evaluate(const String& expr,
const GrowableObjectArray& names,
const GrowableObjectArray& values);
+ RawObject* EvaluateCompiledExpression(const uint8_t* kernel_bytes,
+ intptr_t kernel_length,
+ const Array& arguments,
+ const Array& type_definitions,
+ const TypeArguments& type_arguments);
+
// Print the activation frame into |jsobj|. if |full| is false, script
// and local variable objects are only references. if |full| is true,
// the complete script, function, and, local variable objects are included.
@@ -380,7 +393,7 @@
}
}
- RawObject* GetStackVar(intptr_t slot_index);
+ RawObject* GetStackVar(VariableIndex var_index);
RawObject* GetContextVar(intptr_t ctxt_level, intptr_t slot_index);
uword pc_;
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index ee069b2..1694109 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -1016,9 +1016,9 @@
intptr_t DeoptInfoBuilder::CalculateStackIndex(
const Location& source_loc) const {
- return source_loc.stack_index() < 0
- ? source_loc.stack_index() + num_args_
- : source_loc.stack_index() + num_args_ + kDartFrameFixedSize;
+ intptr_t index = -VariableIndexForFrameSlot(source_loc.stack_index());
+ return index < 0 ? index + num_args_
+ : index + num_args_ + kDartFrameFixedSize;
}
CpuRegisterSource DeoptInfoBuilder::ToCpuRegisterSource(const Location& loc) {
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index c5bfcce..d1b1606 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -466,6 +466,15 @@
Simulator::Current()->JumpToFrame(program_counter, stack_pointer,
frame_pointer, thread);
#else
+#if defined(DART_USE_INTERPRETER)
+ Interpreter* interpreter = thread->isolate()->interpreter();
+ if ((interpreter != NULL) && interpreter->HasFrame(frame_pointer)) {
+ interpreter->JumpToFrame(program_counter, stack_pointer, frame_pointer,
+ thread);
+ }
+ // TODO(regis): We still possibly need to unwind interpreter frames if they
+ // are callee frames of the C++ frame handling the exception.
+#endif
// Prepare for unwinding frames by destroying all the stack resources
// in the previous frames.
StackResource::Unwind(thread);
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index 36452aa..432e3d3 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -83,9 +83,6 @@
"Report error for bad overrides. Ignored in strong mode.") \
R(error_on_bad_type, false, bool, false, \
"Report error for malformed types.") \
- P(external_max_size, int, (kWordSize <= 4) ? 512 : 1024, \
- "Max total size of external allocations in MB, or 0 for unlimited," \
- "e.g: --external_max_size=1024 allows up to 1024MB of externals") \
P(fields_may_be_reset, bool, false, \
"Don't optimize away static field initialization") \
C(force_clone_compiler_objects, false, false, bool, false, \
@@ -104,7 +101,6 @@
P(interpret_irregexp, bool, USING_DBC, "Use irregexp bytecode interpreter") \
P(lazy_dispatchers, bool, true, "Generate dispatchers lazily") \
P(link_natives_lazily, bool, false, "Link native calls lazily") \
- P(limit_ints_to_64_bits, bool, true, "Truncate integers to 64 bits") \
C(load_deferred_eagerly, true, true, bool, false, \
"Load deferred libraries eagerly.") \
R(log_marker_tasks, false, bool, false, \
@@ -116,8 +112,6 @@
"Maximum number of polymorphic check, otherwise it is megamorphic.") \
P(max_equality_polymorphic_checks, int, 32, \
"Maximum number of polymorphic checks in equality operator,") \
- P(new_gen_ext_limit, int, 64, \
- "maximum total external size (MB) in new gen before triggering GC") \
P(new_gen_semi_max_size, int, (kWordSize <= 4) ? 16 : 32, \
"Max size of new gen semi space in MB") \
P(optimization_counter_threshold, int, 30000, \
@@ -157,7 +151,7 @@
C(stress_async_stacks, false, false, bool, false, \
"Stress test async stack traces") \
P(strong, bool, false, "Enable strong mode.") \
- P(sync_async, bool, false, "Start `async` functions synchronously.") \
+ P(sync_async, bool, true, "Start `async` functions synchronously.") \
R(support_ast_printer, false, bool, true, "Support the AST printer.") \
R(support_compiler_stats, false, bool, true, "Support compiler stats.") \
R(support_disassembler, false, bool, true, "Support the disassembler.") \
diff --git a/runtime/vm/heap.cc b/runtime/vm/heap.cc
index 905ba26..cd47729 100644
--- a/runtime/vm/heap.cc
+++ b/runtime/vm/heap.cc
@@ -33,11 +33,10 @@
Heap::Heap(Isolate* isolate,
intptr_t max_new_gen_semi_words,
- intptr_t max_old_gen_words,
- intptr_t max_external_words)
+ intptr_t max_old_gen_words)
: isolate_(isolate),
new_space_(this, max_new_gen_semi_words, kNewObjectAlignmentOffset),
- old_space_(this, max_old_gen_words, max_external_words),
+ old_space_(this, max_old_gen_words),
barrier_(new Monitor()),
barrier_done_(new Monitor()),
read_only_(false),
@@ -132,10 +131,10 @@
if (space == kNew) {
isolate()->AssertCurrentThreadIsMutator();
new_space_.AllocateExternal(cid, size);
- if (new_space_.ExternalInWords() > (FLAG_new_gen_ext_limit * MBInWords)) {
+ if (new_space_.ExternalInWords() > (4 * new_space_.CapacityInWords())) {
// Attempt to free some external allocation by a scavenge. (If the total
// remains above the limit, next external alloc will trigger another.)
- CollectGarbage(kNew);
+ CollectGarbage(kScavenge, kExternal);
}
} else {
ASSERT(space == kOld);
@@ -145,7 +144,7 @@
// As a workaround, we check here on every external allocation. See issue
// dartbug.com/33314.
if (old_space_.NeedsGarbageCollection()) {
- CollectAllGarbage();
+ CollectAllGarbage(kExternal);
}
}
@@ -368,10 +367,10 @@
// a mark-sweep on time.
if (old_space_.ShouldPerformIdleMarkCompact(deadline)) {
TIMELINE_FUNCTION_GC_DURATION(thread, "IdleGC");
- CollectOldSpaceGarbage(thread, kCompaction);
+ CollectOldSpaceGarbage(thread, kMarkCompact, kIdle);
} else if (old_space_.ShouldPerformIdleMarkSweep(deadline)) {
TIMELINE_FUNCTION_GC_DURATION(thread, "IdleGC");
- CollectOldSpaceGarbage(thread, kIdle);
+ CollectOldSpaceGarbage(thread, kMarkSweep, kIdle);
}
}
@@ -380,50 +379,52 @@
}
void Heap::EvacuateNewSpace(Thread* thread, GCReason reason) {
- ASSERT((reason == kFull) || (reason == kLowMemory));
+ ASSERT((reason != kOldSpace) && (reason != kPromotion));
if (BeginNewSpaceGC(thread)) {
- RecordBeforeGC(kNew, reason);
+ RecordBeforeGC(kScavenge, reason);
VMTagScope tagScope(thread, VMTag::kGCNewSpaceTagId);
TIMELINE_FUNCTION_GC_DURATION(thread, "EvacuateNewGeneration");
new_space_.Evacuate();
- RecordAfterGC(kNew);
+ RecordAfterGC(kScavenge);
PrintStats();
NOT_IN_PRODUCT(PrintStatsToTimeline(&tds, reason));
EndNewSpaceGC();
}
}
-void Heap::CollectNewSpaceGarbage(Thread* thread,
- GCReason reason) {
+void Heap::CollectNewSpaceGarbage(Thread* thread, GCReason reason) {
ASSERT((reason != kOldSpace) && (reason != kPromotion));
if (BeginNewSpaceGC(thread)) {
- RecordBeforeGC(kNew, reason);
+ RecordBeforeGC(kScavenge, reason);
{
VMTagScope tagScope(thread, VMTag::kGCNewSpaceTagId);
TIMELINE_FUNCTION_GC_DURATION_BASIC(thread, "CollectNewGeneration");
new_space_.Scavenge();
- RecordAfterGC(kNew);
+ RecordAfterGC(kScavenge);
PrintStats();
NOT_IN_PRODUCT(PrintStatsToTimeline(&tds, reason));
EndNewSpaceGC();
}
if ((reason == kNewSpace) && old_space_.NeedsGarbageCollection()) {
- CollectOldSpaceGarbage(thread, kPromotion);
+ CollectOldSpaceGarbage(thread, kMarkSweep, kPromotion);
}
}
}
void Heap::CollectOldSpaceGarbage(Thread* thread,
+ GCType type,
GCReason reason) {
- ASSERT((reason != kNewSpace));
+ ASSERT(reason != kNewSpace);
+ ASSERT(type != kScavenge);
+ if (FLAG_use_compactor) {
+ type = kMarkCompact;
+ }
if (BeginOldSpaceGC(thread)) {
- RecordBeforeGC(kOld, reason);
+ RecordBeforeGC(type, reason);
VMTagScope tagScope(thread, VMTag::kGCOldSpaceTagId);
TIMELINE_FUNCTION_GC_DURATION_BASIC(thread, "CollectOldGeneration");
- bool compact =
- (reason == kCompaction) || (reason == kLowMemory) || FLAG_use_compactor;
- old_space_.CollectGarbage(compact);
- RecordAfterGC(kOld);
+ old_space_.CollectGarbage(type == kMarkCompact);
+ RecordAfterGC(type);
PrintStats();
NOT_IN_PRODUCT(PrintStatsToTimeline(&tds, reason));
// Some Code objects may have been collected so invalidate handler cache.
@@ -433,19 +434,16 @@
}
}
-void Heap::CollectGarbage(Space space,
- GCReason reason) {
+void Heap::CollectGarbage(GCType type, GCReason reason) {
Thread* thread = Thread::Current();
- switch (space) {
- case kNew: {
+ switch (type) {
+ case kScavenge:
CollectNewSpaceGarbage(thread, reason);
break;
- }
- case kOld:
- case kCode: {
- CollectOldSpaceGarbage(thread, reason);
+ case kMarkSweep:
+ case kMarkCompact:
+ CollectOldSpaceGarbage(thread, type, reason);
break;
- }
default:
UNREACHABLE();
}
@@ -454,7 +452,7 @@
void Heap::CollectGarbage(Space space) {
Thread* thread = Thread::Current();
if (space == kOld) {
- CollectOldSpaceGarbage(thread, kOldSpace);
+ CollectOldSpaceGarbage(thread, kMarkSweep, kOldSpace);
} else {
ASSERT(space == kNew);
CollectNewSpaceGarbage(thread, kNewSpace);
@@ -467,7 +465,8 @@
// New space is evacuated so this GC will collect all dead objects
// kept alive by a cross-generational pointer.
EvacuateNewSpace(thread, reason);
- CollectOldSpaceGarbage(thread, reason);
+ CollectOldSpaceGarbage(
+ thread, reason == kLowMemory ? kMarkCompact : kMarkSweep, reason);
}
void Heap::WaitForSweeperTasks(Thread* thread) {
@@ -508,11 +507,9 @@
void Heap::Init(Isolate* isolate,
intptr_t max_new_gen_words,
- intptr_t max_old_gen_words,
- intptr_t max_external_words) {
+ intptr_t max_old_gen_words) {
ASSERT(isolate->heap() == NULL);
- Heap* heap = new Heap(isolate, max_new_gen_words, max_old_gen_words,
- max_external_words);
+ Heap* heap = new Heap(isolate, max_new_gen_words, max_old_gen_words);
isolate->set_heap(heap);
}
@@ -629,6 +626,20 @@
return old_space_.collections();
}
+const char* Heap::GCTypeToString(GCType type) {
+ switch (type) {
+ case kScavenge:
+ return "Scavenge";
+ case kMarkSweep:
+ return "MarkSweep";
+ case kMarkCompact:
+ return "MarkCompact";
+ default:
+ UNREACHABLE();
+ return "";
+ }
+}
+
const char* Heap::GCReasonToString(GCReason gc_reason) {
switch (gc_reason) {
case kNewSpace:
@@ -637,18 +648,16 @@
return "promotion";
case kOldSpace:
return "old space";
- case kCompaction:
- return "compact";
case kFull:
return "full";
+ case kExternal:
+ return "external";
case kIdle:
return "idle";
case kLowMemory:
return "low memory";
- case kGCAtAlloc:
+ case kDebugging:
return "debugging";
- case kGCTestCase:
- return "test case";
default:
UNREACHABLE();
return "";
@@ -727,11 +736,12 @@
}
#endif // PRODUCT
-void Heap::RecordBeforeGC(Space space, GCReason reason) {
- ASSERT((space == kNew && gc_new_space_in_progress_) ||
- (space == kOld && gc_old_space_in_progress_));
+void Heap::RecordBeforeGC(GCType type, GCReason reason) {
+ ASSERT((type == kScavenge && gc_new_space_in_progress_) ||
+ (type == kMarkSweep && gc_old_space_in_progress_) ||
+ (type == kMarkCompact && gc_old_space_in_progress_));
stats_.num_++;
- stats_.space_ = space;
+ stats_.type_ = type;
stats_.reason_ = reason;
stats_.before_.micros_ = OS::GetCurrentMonotonicMicros();
stats_.before_.new_ = new_space_.GetCurrentUsage();
@@ -742,10 +752,10 @@
stats_.data_[i] = 0;
}
-void Heap::RecordAfterGC(Space space) {
+void Heap::RecordAfterGC(GCType type) {
stats_.after_.micros_ = OS::GetCurrentMonotonicMicros();
int64_t delta = stats_.after_.micros_ - stats_.before_.micros_;
- if (stats_.space_ == kNew) {
+ if (stats_.type_ == kScavenge) {
new_space_.AddGCTime(delta);
new_space_.IncrementCollections();
} else {
@@ -754,8 +764,9 @@
}
stats_.after_.new_ = new_space_.GetCurrentUsage();
stats_.after_.old_ = old_space_.GetCurrentUsage();
- ASSERT((space == kNew && gc_new_space_in_progress_) ||
- (space == kOld && gc_old_space_in_progress_));
+ ASSERT((type == kScavenge && gc_new_space_in_progress_) ||
+ (type == kMarkSweep && gc_old_space_in_progress_) ||
+ (type == kMarkCompact && gc_old_space_in_progress_));
#ifndef PRODUCT
if (FLAG_support_service && Service::gc_stream.enabled() &&
!ServiceIsolate::IsServiceIsolateDescendant(Isolate::Current())) {
@@ -788,9 +799,8 @@
}
// clang-format off
- const char* space_str = stats_.space_ == kNew ? "Scavenge" : "Mark-Sweep";
OS::PrintErr(
- "[ %-13.13s, %10s(%9s), " // GC(isolate), space(reason)
+ "[ %-13.13s, %10s(%9s), " // GC(isolate), type(reason)
"%4" Pd ", " // count
"%6.2f, " // start time
"%5.1f, " // total time
@@ -803,11 +813,13 @@
"%6.2f, %6.2f, %6.2f, %6.2f, %6.2f, %6.2f, " // times
"%" Pd ", %" Pd ", %" Pd ", %" Pd ", " // data
"]\n", // End with a comma to make it easier to import in spreadsheets.
- isolate()->name(), space_str, GCReasonToString(stats_.reason_),
+ isolate()->name(),
+ GCTypeToString(stats_.type_),
+ GCReasonToString(stats_.reason_),
stats_.num_,
MicrosecondsToSeconds(isolate()->UptimeMicros()),
MicrosecondsToMilliseconds(stats_.after_.micros_ -
- stats_.before_.micros_),
+ stats_.before_.micros_),
RoundWordsToKB(stats_.before_.new_.used_in_words),
RoundWordsToKB(stats_.after_.new_.used_in_words),
RoundWordsToKB(stats_.before_.new_.capacity_in_words),
diff --git a/runtime/vm/heap.h b/runtime/vm/heap.h
index 9678e61..2edf4cf 100644
--- a/runtime/vm/heap.h
+++ b/runtime/vm/heap.h
@@ -41,16 +41,21 @@
kNumWeakSelectors
};
+ enum GCType {
+ kScavenge,
+ kMarkSweep,
+ kMarkCompact,
+ };
+
enum GCReason {
- kNewSpace,
- kPromotion,
- kOldSpace,
- kCompaction,
- kFull,
- kIdle,
- kLowMemory,
- kGCAtAlloc,
- kGCTestCase,
+ kNewSpace, // New space is full.
+ kPromotion, // Old space limit crossed after a scavenge.
+ kOldSpace, // Old space limit crossed.
+ kFull, // Heap::CollectAllGarbage
+ kExternal, // Dart_NewWeakPersistentHandle
+ kIdle, // Dart_NotifyIdle
+ kLowMemory, // Dart_NotifyLowMemory
+ kDebugging, // service request, --gc_at_instance_allocation, etc.
};
// Pattern for unused new space and swept old space.
@@ -110,7 +115,7 @@
void NotifyLowMemory();
void CollectGarbage(Space space);
- void CollectGarbage(Space space, GCReason reason);
+ void CollectGarbage(GCType type, GCReason reason);
void CollectAllGarbage(GCReason reason = kFull);
bool NeedsGarbageCollection() const {
return old_space_.NeedsGarbageCollection();
@@ -136,8 +141,7 @@
// Initialize the heap and register it with the isolate.
static void Init(Isolate* isolate,
intptr_t max_new_gen_words,
- intptr_t max_old_gen_words,
- intptr_t max_external_words);
+ intptr_t max_old_gen_words);
// Writes a suitable name for a VM region in the heap into the buffer `name`.
static void RegionName(Heap* heap,
@@ -163,7 +167,8 @@
ObjectSet* CreateAllocatedObjectSet(Zone* zone,
MarkExpectation mark_expectation) const;
- static const char* GCReasonToString(GCReason gc_reason);
+ static const char* GCTypeToString(GCType type);
+ static const char* GCReasonToString(GCReason reason);
// Associate a peer with an object. A non-existent peer is equal to NULL.
void SetPeer(RawObject* raw_obj, void* peer) {
@@ -264,7 +269,7 @@
public:
GCStats() {}
intptr_t num_;
- Heap::Space space_;
+ Heap::GCType type_;
Heap::GCReason reason_;
class Data : public ValueObject {
@@ -292,8 +297,7 @@
Heap(Isolate* isolate,
intptr_t max_new_gen_semi_words, // Max capacity of new semi-space.
- intptr_t max_old_gen_words,
- intptr_t max_external_words);
+ intptr_t max_old_gen_words);
uword AllocateNew(intptr_t size);
uword AllocateOld(intptr_t size, HeapPage::PageType type);
@@ -315,13 +319,12 @@
// Helper functions for garbage collection.
void CollectNewSpaceGarbage(Thread* thread,
GCReason reason);
- void CollectOldSpaceGarbage(Thread* thread,
- GCReason reason);
+ void CollectOldSpaceGarbage(Thread* thread, GCType type, GCReason reason);
void EvacuateNewSpace(Thread* thread, GCReason reason);
// GC stats collection.
- void RecordBeforeGC(Space space, GCReason reason);
- void RecordAfterGC(Space space);
+ void RecordBeforeGC(GCType type, GCReason reason);
+ void RecordAfterGC(GCType type);
void PrintStats();
void PrintStatsToTimeline(TimelineEventScope* event, GCReason reason);
diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc
index dba91ad..fdbc665 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -144,10 +144,6 @@
case kMintCid:
return (static_cast<RawMint*>(lhs)->ptr()->value_ ==
static_cast<RawMint*>(rhs)->ptr()->value_);
-
- case kBigintCid:
- return (DLRT_BigintCompare(static_cast<RawBigint*>(lhs),
- static_cast<RawBigint*>(rhs)) == 0);
}
}
}
@@ -627,6 +623,7 @@
thread->set_top_exit_frame_info(reinterpret_cast<uword>(fp_));
#if defined(DEBUG)
if (IsTracingExecution()) {
+ THR_Print("%" Pu64 " ", icount_);
THR_Print("Exiting interpreter 0x%" Px " at fp_ 0x%" Px "\n",
reinterpret_cast<uword>(this), reinterpret_cast<uword>(fp_));
}
@@ -870,16 +867,18 @@
if (Function::HasCode(function)) {
RawCode* code = function->ptr()->code_;
ASSERT(code != StubCode::LazyCompile_entry()->code());
- // TODO(regis): Do we really need a stub? Try to invoke directly.
+ // TODO(regis): Once we share the same stack, try to invoke directly.
// On success, returns a RawInstance. On failure, a RawError.
typedef RawObject* (*invokestub)(RawCode * code, RawArray * argdesc,
RawObject * *arg0, Thread * thread);
invokestub entrypoint = reinterpret_cast<invokestub>(
StubCode::InvokeDartCodeFromBytecode_entry()->EntryPoint());
- *call_base = entrypoint(code, argdesc, call_base, thread);
- // Result is at call_base;
+ RawObject* result = entrypoint(code, argdesc, call_base, thread);
+
+ // Pop args and push result.
*SP = call_base;
+ **SP = result;
} else {
ASSERT(Function::HasBytecode(function));
// Bytecode was loaded in the above compilation step.
@@ -916,6 +915,12 @@
RawObject** callee_fp = call_top + kKBCDartFrameFixedSize;
RawFunction* function = FrameFunction(callee_fp);
+#if defined(DEBUG)
+ if (IsTracingExecution()) {
+ THR_Print("%" Pu64 " ", icount_);
+ THR_Print("invoking %s\n", Function::Handle(function).ToCString());
+ }
+#endif
if (Function::HasCode(function) || !Function::HasBytecode(function)) {
// TODO(regis): If the function is a dispatcher, execute the dispatch here.
if (!InvokeCompiled(thread, function, argdesc_, call_base, call_top, pc, FP,
@@ -1254,16 +1259,18 @@
FP = reinterpret_cast<RawObject**>(fp_); \
pc = reinterpret_cast<uint32_t*>(pc_); \
if ((reinterpret_cast<uword>(pc) & 2) != 0) { /* Entry frame? */ \
- fp_ = reinterpret_cast<RawObject**>(fp_[0]); \
- thread->set_top_exit_frame_info(reinterpret_cast<uword>(fp_)); \
+ uword exit_fp = reinterpret_cast<uword>(fp_[0]); \
+ thread->set_top_exit_frame_info(exit_fp); \
thread->set_top_resource(top_resource); \
thread->set_vm_tag(vm_tag); \
if (IsTracingExecution()) { \
+ THR_Print("%" Pu64 " ", icount_); \
THR_Print("Returning exception from interpreter 0x%" Px \
" at fp_ 0x%" Px "\n", \
reinterpret_cast<uword>(this), \
reinterpret_cast<uword>(fp_)); \
} \
+ ASSERT(reinterpret_cast<uword>(fp_) < stack_limit()); \
return special_[kExceptionSpecialIndex]; \
} \
pp_ = InterpreterHelpers::FrameCode(FP)->ptr()->object_pool_; \
@@ -1277,8 +1284,8 @@
FP = reinterpret_cast<RawObject**>(fp_); \
pc = reinterpret_cast<uint32_t*>(pc_); \
if ((reinterpret_cast<uword>(pc) & 2) != 0) { /* Entry frame? */ \
- fp_ = reinterpret_cast<RawObject**>(fp_[0]); \
- thread->set_top_exit_frame_info(reinterpret_cast<uword>(fp_)); \
+ uword exit_fp = reinterpret_cast<uword>(fp_[0]); \
+ thread->set_top_exit_frame_info(exit_fp); \
thread->set_top_resource(top_resource); \
thread->set_vm_tag(vm_tag); \
return special_[kExceptionSpecialIndex]; \
@@ -1388,13 +1395,15 @@
bool reentering = fp_ != NULL;
if (!reentering) {
- fp_ = reinterpret_cast<RawObject**>(stack_);
+ fp_ = reinterpret_cast<RawObject**>(stack_base_);
}
#if defined(DEBUG)
if (IsTracingExecution()) {
- THR_Print("%s interpreter 0x%" Px " at fp_ 0x%" Px "\n",
+ THR_Print("%" Pu64 " ", icount_);
+ THR_Print("%s interpreter 0x%" Px " at fp_ 0x%" Px " %s\n",
reentering ? "Re-entering" : "Entering",
- reinterpret_cast<uword>(this), reinterpret_cast<uword>(fp_));
+ reinterpret_cast<uword>(this), reinterpret_cast<uword>(fp_),
+ Function::Handle(code.function()).ToCString());
}
#endif
@@ -1420,7 +1429,7 @@
// | arg 1 | -+
// | function | -+
// | code | |
- // | callee PC | ---> special fake PC marking an entry frame
+ // | caller PC | ---> special fake PC marking an entry frame
// SP > | fp_ | |
// FP > | ........... | > normal Dart frame (see stack_frame_kbc.h)
// |
@@ -1705,14 +1714,12 @@
{
BYTECODE(CheckStack, A);
{
- // TODO(regis): Support a second stack limit or can we share the DBC one?
-#if 0
- if (reinterpret_cast<uword>(SP) >= thread->stack_limit()) {
+ // Using the interpreter stack limit and not the thread stack limit.
+ if (reinterpret_cast<uword>(SP) >= stack_limit()) {
Exit(thread, FP, SP + 1, pc);
NativeArguments args(thread, 0, NULL, NULL);
INVOKE_RUNTIME(DRT_StackOverflow, args);
}
-#endif
}
DISPATCH();
}
@@ -2908,16 +2915,22 @@
// Check if it is a fake PC marking the entry frame.
if ((reinterpret_cast<uword>(pc) & 2) != 0) {
- const intptr_t argc = reinterpret_cast<uword>(pc) >> 2;
- fp_ = reinterpret_cast<RawObject**>(FrameArguments(FP, argc + 1)[0]);
- thread->set_top_exit_frame_info(reinterpret_cast<uword>(fp_));
+ // Pop entry frame.
+ fp_ = SavedCallerFP(FP);
+ // Restore exit frame info saved in entry frame.
+ uword exit_fp = reinterpret_cast<uword>(fp_[0]);
+ thread->set_top_exit_frame_info(exit_fp);
thread->set_top_resource(top_resource);
thread->set_vm_tag(vm_tag);
#if defined(DEBUG)
if (IsTracingExecution()) {
+ THR_Print("%" Pu64 " ", icount_);
THR_Print("Returning from interpreter 0x%" Px " at fp_ 0x%" Px "\n",
reinterpret_cast<uword>(this), reinterpret_cast<uword>(fp_));
}
+ ASSERT(reinterpret_cast<uword>(fp_) < stack_limit());
+ const intptr_t argc = reinterpret_cast<uword>(pc) >> 2;
+ ASSERT(fp_ == FrameArguments(FP, argc + 1));
#endif
return result;
}
diff --git a/runtime/vm/interpreter.h b/runtime/vm/interpreter.h
index def46e6..517cbaa 100644
--- a/runtime/vm/interpreter.h
+++ b/runtime/vm/interpreter.h
@@ -5,6 +5,9 @@
#ifndef RUNTIME_VM_INTERPRETER_H_
#define RUNTIME_VM_INTERPRETER_H_
+#include "vm/globals.h"
+#if defined(DART_USE_INTERPRETER)
+
#include "vm/compiler/method_recognizer.h"
#include "vm/constants_kbc.h"
@@ -54,6 +57,14 @@
uword top_exit_frame_info() const { return top_exit_frame_info_; }
void set_top_exit_frame_info(uword value) { top_exit_frame_info_ = value; }
+ // Returns true if the interpreter's stack contains the given frame.
+ // TODO(regis): Once the interpreter shares the native stack, we may rely on
+ // a new thread vm_tag to identify an interpreter frame and we will not need
+ // this HasFrame() method.
+ bool HasFrame(uword frame) const {
+ return frame >= stack_base() && frame <= get_fp();
+ }
+
// Call on program start.
static void InitOnce();
@@ -196,4 +207,6 @@
} // namespace dart
+#endif // defined(DART_USE_INTERPRETER)
+
#endif // RUNTIME_VM_INTERPRETER_H_
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index c00b259..5337d5a 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -1066,8 +1066,7 @@
: FLAG_new_gen_semi_max_size * MBInWords,
(is_service_or_kernel_isolate ? kDefaultMaxOldGenHeapSize
: FLAG_old_gen_heap_size) *
- MBInWords,
- FLAG_external_max_size * MBInWords);
+ MBInWords);
// TODO(5411455): For now just set the recently created isolate as
// the current isolate.
diff --git a/runtime/vm/json_stream.h b/runtime/vm/json_stream.h
index 3fa5e36..42848bb 100644
--- a/runtime/vm/json_stream.h
+++ b/runtime/vm/json_stream.h
@@ -58,6 +58,9 @@
kIsolateIsReloading = 108,
kIsolateReloadBarred = 109,
kIsolateMustHaveReloaded = 110,
+ kServiceAlreadyRegistered = 111,
+ kServiceDisappeared = 112,
+ kExpressionCompilationError = 113,
// Experimental (used in private rpcs).
kFileSystemAlreadyExists = 1001,
diff --git a/runtime/vm/kernel.cc b/runtime/vm/kernel.cc
index 5394e53..7b7ac73 100644
--- a/runtime/vm/kernel.cc
+++ b/runtime/vm/kernel.cc
@@ -22,7 +22,8 @@
StreamingFlowGraphBuilder builder(&translation_helper,
Script::Handle(zone, field.Script()), zone,
TypedData::Handle(zone, field.KernelData()),
- field.KernelDataProgramOffset());
+ field.KernelDataProgramOffset(),
+ /* active_class = */ NULL);
builder.SetOffset(field.kernel_offset());
kernel::FieldHelper field_helper(&builder);
field_helper.ReadUntilExcluding(kernel::FieldHelper::kEnd, true);
diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc
index bdba931..f0b47d5 100644
--- a/runtime/vm/kernel_isolate.cc
+++ b/runtime/vm/kernel_isolate.cc
@@ -88,7 +88,7 @@
api_flags.enable_error_on_bad_override = false;
api_flags.reify_generic_functions = false;
api_flags.strong = false;
- api_flags.sync_async = false;
+ api_flags.sync_async = true;
#if !defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC)
api_flags.use_field_guards = true;
#endif
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index e473239..5b5dfc4 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -175,7 +175,8 @@
zone_,
program_->kernel_data(),
program_->kernel_data_size(),
- 0),
+ 0,
+ &active_class_),
external_name_class_(Class::Handle(Z)),
external_name_field_(Field::Handle(Z)),
potential_natives_(GrowableObjectArray::Handle(Z)),
@@ -185,7 +186,7 @@
"Trying to load a concatenated dill file at a time where that is "
"not allowed");
}
- T.active_class_ = &active_class_;
+ ASSERT(T.active_class_ == &active_class_);
T.finalize_ = false;
initialize_fields();
@@ -340,12 +341,17 @@
kernel_program_info_(
KernelProgramInfo::ZoneHandle(zone_, script.kernel_program_info())),
translation_helper_(this, thread_),
- builder_(&translation_helper_, script, zone_, kernel_data, 0),
+ builder_(&translation_helper_,
+ script,
+ zone_,
+ kernel_data,
+ 0,
+ &active_class_),
external_name_class_(Class::Handle(Z)),
external_name_field_(Field::Handle(Z)),
potential_natives_(GrowableObjectArray::Handle(Z)),
potential_extension_libraries_(GrowableObjectArray::Handle(Z)) {
- T.active_class_ = &active_class_;
+ ASSERT(T.active_class_ == &active_class_);
T.finalize_ = false;
const Array& scripts = Array::Handle(Z, kernel_program_info_.scripts());
@@ -369,7 +375,7 @@
builder_.SetOffset(program_->constant_table_offset());
StreamingDartTypeTranslator type_translator_(&builder_, true /* finalize */);
- type_translator_.active_class_ = &active_class_;
+ ASSERT(type_translator_.active_class_ == &active_class_);
ConstantHelper helper(&active_class_, &builder_, &type_translator_,
&translation_helper_, Z, skip_vmservice_library_);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index ed6ecb1..beb89ec 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -740,8 +740,6 @@
isolate->object_store()->set_two_byte_string_class(cls);
cls = Class::New<Mint>();
isolate->object_store()->set_mint_class(cls);
- cls = Class::New<Bigint>();
- isolate->object_store()->set_bigint_class(cls);
cls = Class::New<Double>();
isolate->object_store()->set_double_class(cls);
@@ -1036,8 +1034,8 @@
// Some classes have identity hash codes that depend on their contents,
// not per object.
ASSERT(!obj->IsStringInstance());
- if (!obj->IsMint() && !obj->IsDouble() && !obj->IsBigint() &&
- !obj->IsRawNull() && !obj->IsBool()) {
+ if (!obj->IsMint() && !obj->IsDouble() && !obj->IsRawNull() &&
+ !obj->IsBool()) {
counter_ += 2011; // The year Dart was announced and a prime.
counter_ &= 0x3fffffff;
if (counter_ == 0) counter_++;
@@ -1550,11 +1548,6 @@
RegisterPrivateClass(cls, Symbols::_Mint(), core_lib);
pending_classes.Add(cls);
- cls = Class::New<Bigint>();
- object_store->set_bigint_class(cls);
- RegisterPrivateClass(cls, Symbols::_Bigint(), core_lib);
- pending_classes.Add(cls);
-
cls = Class::New<Double>();
object_store->set_double_class(cls);
RegisterPrivateClass(cls, Symbols::_Double(), core_lib);
@@ -1918,9 +1911,6 @@
cls = Class::New<Closure>();
object_store->set_closure_class(cls);
- cls = Class::New<Bigint>();
- object_store->set_bigint_class(cls);
-
cls = Class::NewStringClass(kOneByteStringCid);
object_store->set_one_byte_string_class(cls);
@@ -3253,25 +3243,48 @@
const Array& type_param_names,
const TypeArguments& type_param_values) const {
ASSERT(Thread::Current()->IsMutatorThread());
- if (id() < kInstanceCid) {
- const Instance& exception = Instance::Handle(
- String::New("Cannot evaluate against a VM internal class"));
+ if (id() < kInstanceCid || id() == kTypeArgumentsCid) {
+ const Instance& exception = Instance::Handle(String::New(
+ "Expressions can be evaluated only with regular Dart instances"));
const Instance& stacktrace = Instance::Handle();
return UnhandledException::New(exception, stacktrace);
}
- if (Library::Handle(library()).kernel_data() == TypedData::null() ||
- !FLAG_enable_kernel_expression_compilation) {
- const Function& eval_func = Function::Handle(
- Function::EvaluateHelper(*this, expr, param_names, true));
- return DartEntry::InvokeFunction(eval_func, param_values);
+ ASSERT(Library::Handle(library()).kernel_data() == TypedData::null() ||
+ !FLAG_enable_kernel_expression_compilation);
+ const Function& eval_func = Function::Handle(
+ Function::EvaluateHelper(*this, expr, param_names, true));
+ return DartEntry::InvokeFunction(eval_func, param_values);
+}
+
+static RawObject* EvaluateCompiledExpressionHelper(
+ const uint8_t* kernel_bytes,
+ intptr_t kernel_length,
+ const Array& type_definitions,
+ const String& library_url,
+ const String& klass,
+ const Array& arguments,
+ const TypeArguments& type_arguments);
+
+RawObject* Class::EvaluateCompiledExpression(
+ const uint8_t* kernel_bytes,
+ intptr_t kernel_length,
+ const Array& type_definitions,
+ const Array& arguments,
+ const TypeArguments& type_arguments) const {
+ ASSERT(Thread::Current()->IsMutatorThread());
+ if (id() < kInstanceCid || id() == kTypeArgumentsCid) {
+ const Instance& exception = Instance::Handle(String::New(
+ "Expressions can be evaluated only with regular Dart instances"));
+ const Instance& stacktrace = Instance::Handle();
+ return UnhandledException::New(exception, stacktrace);
}
- return EvaluateWithDFEHelper(
- expr, param_names, type_param_names,
+ return EvaluateCompiledExpressionHelper(
+ kernel_bytes, kernel_length, type_definitions,
String::Handle(Library::Handle(library()).url()),
IsTopLevel() ? String::Handle() : String::Handle(UserVisibleName()),
- !IsTopLevel(), param_values, type_param_values);
+ arguments, type_arguments);
}
// Ensure that top level parsing of the class has been done.
@@ -3637,7 +3650,6 @@
case kIntegerCid:
case kSmiCid:
case kMintCid:
- case kBigintCid:
return Symbols::Int().raw();
case kDoubleCid:
return Symbols::Double().raw();
@@ -3696,7 +3708,7 @@
kernel::TranslationHelper helper(thread);
helper.InitFromScript(scr);
kernel::StreamingFlowGraphBuilder builder_(&helper, scr, zone, kernel_data,
- 0);
+ 0, /* active_class = */ NULL);
builder_.SetOffset(class_offset);
kernel::ClassHelper class_helper(&builder_);
class_helper.ReadUntilIncluding(kernel::ClassHelper::kEndPosition);
@@ -4161,7 +4173,7 @@
return true;
}
}
- if (other_type_arg.IsType() &&
+ if (other_type_arg.HasResolvedTypeClass() &&
TypeTest(Class::kIsSubtypeOf, type_arguments,
Class::Handle(zone, other_type_arg.type_class()),
TypeArguments::Handle(other_type_arg.arguments()), bound_error,
@@ -4641,29 +4653,6 @@
return canonical_value.raw();
}
-RawBigint* Class::LookupCanonicalBigint(Zone* zone,
- const Bigint& value,
- intptr_t* index) const {
- ASSERT(this->raw() == Isolate::Current()->object_store()->bigint_class());
- const Array& constants = Array::Handle(zone, this->constants());
- const intptr_t constants_len = constants.Length();
- // Linear search to see whether this value is already present in the
- // list of canonicalized constants.
- Bigint& canonical_value = Bigint::Handle(zone);
- while (*index < constants_len) {
- canonical_value ^= constants.At(*index);
- if (canonical_value.IsNull()) {
- break;
- }
- if (canonical_value.Equals(value)) {
- ASSERT(canonical_value.IsCanonical());
- return canonical_value.raw();
- }
- *index = *index + 1;
- }
- return Bigint::null();
-}
-
class CanonicalInstanceKey {
public:
explicit CanonicalInstanceKey(const Instance& key) : key_(key) {
@@ -4762,23 +4751,9 @@
this->set_constants(constants.Release());
}
-void Class::InsertCanonicalBigint(Zone* zone,
- intptr_t index,
- const Bigint& constant) const {
- // The constant needs to be added to the list. Grow the list if it is full.
- Array& canonical_list = Array::Handle(zone, constants());
- const intptr_t list_len = canonical_list.Length();
- if (index >= list_len) {
- const intptr_t new_length = list_len + 4 + (list_len >> 2);
- canonical_list ^= Array::Grow(canonical_list, new_length, Heap::kOld);
- set_constants(canonical_list);
- }
- canonical_list.SetAt(index, constant);
-}
-
void Class::RehashConstants(Zone* zone) const {
intptr_t cid = id();
- if ((cid == kMintCid) || (cid == kBigintCid) || (cid == kDoubleCid)) {
+ if ((cid == kMintCid) || (cid == kDoubleCid)) {
// Constants stored as a plain list or in a hashset with a stable hashcode,
// which only depends on the actual value of the constant.
return;
@@ -5650,7 +5625,7 @@
// We should not have loaded the bytecode if the function had code.
ASSERT(!HasCode());
- // Set the code entry_point to to InterpretCall stub.
+ // Set the code entry_point to InterpretCall stub.
SetInstructions(Code::Handle(StubCode::InterpretCall_entry()->code()));
}
@@ -7331,7 +7306,8 @@
kernel::TranslationHelper translation_helper(thread);
kernel::StreamingFlowGraphBuilder builder(
&translation_helper, function_script, zone,
- TypedData::Handle(zone, KernelData()), KernelDataProgramOffset());
+ TypedData::Handle(zone, KernelData()), KernelDataProgramOffset(),
+ /* active_class = */ NULL);
translation_helper.InitFromScript(function_script);
builder.SetOffset(kernel_offset());
@@ -9191,7 +9167,6 @@
if (lit.IsNull()) {
// Convert token to an error.
ASSERT(descriptor.kind == Token::kINTEGER);
- ASSERT(FLAG_limit_ints_to_64_bits);
Scanner::TokenDescriptor errorDesc = descriptor;
errorDesc.kind = Token::kERROR;
errorDesc.literal = &String::Handle(Symbols::NewFormatted(
@@ -11441,6 +11416,17 @@
param_values, type_param_values);
}
+RawObject* Library::EvaluateCompiledExpression(
+ const uint8_t* kernel_bytes,
+ intptr_t kernel_length,
+ const Array& type_definitions,
+ const Array& arguments,
+ const TypeArguments& type_arguments) const {
+ return EvaluateCompiledExpressionHelper(
+ kernel_bytes, kernel_length, type_definitions, String::Handle(url()),
+ String::Handle(), arguments, type_arguments);
+}
+
void Library::InitNativeWrappersLibrary(Isolate* isolate, bool is_kernel) {
static const int kNumNativeWrappersClasses = 4;
COMPILE_ASSERT((kNumNativeWrappersClasses > 0) &&
@@ -11520,10 +11506,12 @@
is_static);
}
+ GrowableObjectArray& libraries =
+ GrowableObjectArray::Handle(T->zone(), I->object_store()->libraries());
+
Function& callee = Function::Handle();
intptr_t num_cids = I->class_table()->NumCids();
- intptr_t num_libs =
- GrowableObjectArray::Handle(I->object_store()->libraries()).Length();
+ intptr_t num_libs = libraries.Length();
if (compilation_result.status != Dart_KernelCompilationStatus_Ok) {
const String& prefix =
@@ -11554,12 +11542,9 @@
const Object& result = Object::Handle(loader.LoadProgram());
if (result.IsError()) return result.raw();
ASSERT(I->class_table()->NumCids() > num_cids &&
- GrowableObjectArray::Handle(I->object_store()->libraries()).Length() ==
- num_libs + 1);
- const String& fake_library_url =
- String::Handle(String::New("evaluate:source"));
+ libraries.Length() == num_libs + 1);
const Library& loaded =
- Library::Handle(Library::LookupLibrary(T, fake_library_url));
+ Library::Handle(Library::LookupLibrary(T, Symbols::EvalSourceUri()));
ASSERT(!loaded.IsNull());
String& debug_name = String::Handle(
@@ -11597,14 +11582,13 @@
callee.set_owner(real_class);
// Unlink the fake library and class from the object store.
- GrowableObjectArray::Handle(I->object_store()->libraries())
- .SetLength(num_libs);
+ libraries.SetLength(num_libs);
I->class_table()->SetNumCids(num_cids);
if (!fake_class.IsNull()) {
fake_class.set_id(kIllegalCid);
}
LibraryLookupMap libraries_map(I->object_store()->libraries_map());
- bool removed = libraries_map.Remove(fake_library_url);
+ bool removed = libraries_map.Remove(Symbols::EvalSourceUri());
ASSERT(removed);
I->object_store()->set_libraries_map(libraries_map.Release());
@@ -11626,6 +11610,113 @@
#endif
}
+static RawObject* EvaluateCompiledExpressionHelper(
+ const uint8_t* kernel_bytes,
+ intptr_t kernel_length,
+ const Array& type_definitions,
+ const String& library_url,
+ const String& klass,
+ const Array& arguments,
+ const TypeArguments& type_arguments) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+ const String& error_str = String::Handle(
+ String::New("Expression evaluation not available in precompiled mode."));
+ return ApiError::New(error_str);
+#else
+ Isolate* I = Isolate::Current();
+ Thread* T = Thread::Current();
+
+ kernel::Program* kernel_pgm =
+ kernel::Program::ReadFromBuffer(kernel_bytes, kernel_length, true);
+
+ if (kernel_pgm == NULL) {
+ return ApiError::New(String::Handle(
+ String::New("Kernel isolate returned ill-formed kernel.")));
+ }
+
+ kernel_pgm->set_release_buffer_callback(ReleaseFetchedBytes);
+
+ Function& callee = Function::Handle();
+ intptr_t num_cids = I->class_table()->NumCids();
+ GrowableObjectArray& libraries =
+ GrowableObjectArray::Handle(T->zone(), I->object_store()->libraries());
+ intptr_t num_libs = libraries.Length();
+
+ // Load the program with the debug procedure as a regular, independent
+ // program.
+ kernel::KernelLoader loader(kernel_pgm);
+ const Object& result = Object::Handle(loader.LoadProgram());
+ if (result.IsError()) return result.raw();
+ ASSERT(I->class_table()->NumCids() > num_cids &&
+ libraries.Length() == num_libs + 1);
+ const Library& loaded =
+ Library::Handle(Library::LookupLibrary(T, Symbols::EvalSourceUri()));
+ ASSERT(!loaded.IsNull());
+
+ String& debug_name = String::Handle(
+ String::New(Symbols::Symbol(Symbols::kDebugProcedureNameId)));
+ Class& fake_class = Class::Handle();
+ if (!klass.IsNull()) {
+ fake_class = loaded.LookupClass(Symbols::DebugClassName());
+ ASSERT(!fake_class.IsNull());
+ callee = fake_class.LookupFunctionAllowPrivate(debug_name);
+ } else {
+ callee = loaded.LookupFunctionAllowPrivate(debug_name);
+ }
+ ASSERT(!callee.IsNull());
+
+ // Save the loaded library's kernel data to the generic "data" field of the
+ // callee, so it doesn't require access it's parent library during
+ // compilation.
+ callee.SetKernelDataAndScript(Script::Handle(callee.script()),
+ TypedData::Handle(loaded.kernel_data()),
+ loaded.kernel_offset());
+
+ // Reparent the callee to the real enclosing class so we can remove the fake
+ // class and library from the object store.
+ const Library& real_library =
+ Library::Handle(Library::LookupLibrary(T, library_url));
+ ASSERT(!real_library.IsNull());
+ Class& real_class = Class::Handle();
+ if (!klass.IsNull()) {
+ real_class = real_library.LookupClassAllowPrivate(klass);
+ } else {
+ real_class = real_library.toplevel_class();
+ }
+ ASSERT(!real_class.IsNull());
+
+ callee.set_owner(real_class);
+
+ // Unlink the fake library and class from the object store.
+ libraries.SetLength(num_libs);
+ I->class_table()->SetNumCids(num_cids);
+ if (!fake_class.IsNull()) {
+ fake_class.set_id(kIllegalCid);
+ }
+ LibraryLookupMap libraries_map(I->object_store()->libraries_map());
+ bool removed = libraries_map.Remove(Symbols::EvalSourceUri());
+ ASSERT(removed);
+ I->object_store()->set_libraries_map(libraries_map.Release());
+
+ if (type_definitions.Length() == 0) {
+ return DartEntry::InvokeFunction(callee, arguments);
+ }
+
+ intptr_t num_type_args = type_arguments.Length();
+ Array& real_arguments = Array::Handle(Array::New(arguments.Length() + 1));
+ real_arguments.SetAt(0, type_arguments);
+ Object& arg = Object::Handle();
+ for (intptr_t i = 0; i < arguments.Length(); ++i) {
+ arg = arguments.At(i);
+ real_arguments.SetAt(i + 1, arg);
+ }
+
+ const Array& args_desc = Array::Handle(
+ ArgumentsDescriptor::New(num_type_args, arguments.Length()));
+ return DartEntry::InvokeFunction(callee, real_arguments, args_desc);
+#endif
+}
+
// Returns library with given url in current isolate, or NULL.
RawLibrary* Library::LookupLibrary(Thread* thread, const String& url) {
Zone* zone = thread->zone();
@@ -14881,6 +14972,8 @@
code.SetPrologueOffset(bytecode_size); // TODO(regis): Correct?
INC_STAT(Thread::Current(), total_code_size,
code.comments().comments_.Length());
+ // TODO(regis): Until we support exception handling.
+ code.set_exception_handlers(Object::empty_exception_handlers());
return code.raw();
}
#endif // defined(DART_USE_INTERPRETER)
@@ -15861,17 +15954,34 @@
}
const Library& library = Library::Handle(method_cls.library());
- if (library.kernel_data() == TypedData::null() ||
- !FLAG_enable_kernel_expression_compilation) {
- const Function& eval_func = Function::Handle(
- Function::EvaluateHelper(method_cls, expr, param_names, false));
- return DartEntry::InvokeFunction(eval_func, args);
+ ASSERT(library.kernel_data() == TypedData::null() ||
+ !FLAG_enable_kernel_expression_compilation);
+ const Function& eval_func = Function::Handle(
+ Function::EvaluateHelper(method_cls, expr, param_names, false));
+ return DartEntry::InvokeFunction(eval_func, args);
+}
+
+RawObject* Instance::EvaluateCompiledExpression(
+ const Class& method_cls,
+ const uint8_t* kernel_bytes,
+ intptr_t kernel_length,
+ const Array& type_definitions,
+ const Array& arguments,
+ const TypeArguments& type_arguments) const {
+ const Array& arguments_with_receiver =
+ Array::Handle(Array::New(1 + arguments.Length()));
+ PassiveObject& param = PassiveObject::Handle();
+ arguments_with_receiver.SetAt(0, *this);
+ for (intptr_t i = 0; i < arguments.Length(); i++) {
+ param = arguments.At(i);
+ arguments_with_receiver.SetAt(i + 1, param);
}
- return EvaluateWithDFEHelper(
- expr, param_names, type_param_names,
+
+ return EvaluateCompiledExpressionHelper(
+ kernel_bytes, kernel_length, type_definitions,
String::Handle(Library::Handle(method_cls.library()).url()),
- String::Handle(method_cls.UserVisibleName()), false, args,
- type_param_values);
+ String::Handle(method_cls.UserVisibleName()), arguments_with_receiver,
+ type_arguments);
}
RawObject* Instance::HashCode() const {
@@ -18985,44 +19095,6 @@
return Mint::NewCanonical(Mint::Cast(*this).value());
case kDoubleCid:
return Double::NewCanonical(Double::Cast(*this).value());
- case kBigintCid: {
- if (this->IsCanonical()) {
- return this->raw();
- }
- Zone* zone = thread->zone();
- Isolate* isolate = thread->isolate();
- Bigint& result = Bigint::Handle(zone);
- const Class& cls = Class::Handle(zone, this->clazz());
- intptr_t index = 0;
- result ^= cls.LookupCanonicalBigint(zone, Bigint::Cast(*this), &index);
- if (!result.IsNull()) {
- return result.raw();
- }
- {
- SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
- // Retry lookup.
- {
- result ^=
- cls.LookupCanonicalBigint(zone, Bigint::Cast(*this), &index);
- if (!result.IsNull()) {
- return result.raw();
- }
- }
-
- // The value needs to be added to the list. Grow the list if
- // it is full.
- result ^= this->raw();
- ASSERT((isolate == Dart::vm_isolate()) || !result.InVMHeap());
- if (result.IsNew()) {
- // Create a canonical object in old space.
- result ^= Object::Clone(result, Heap::kOld);
- }
- ASSERT(result.IsOld());
- result.SetCanonical();
- cls.InsertCanonicalBigint(zone, index, result);
- return result.raw();
- }
- }
default:
UNREACHABLE();
}
@@ -19032,7 +19104,6 @@
#if defined(DEBUG)
bool Number::CheckIsCanonical(Thread* thread) const {
intptr_t cid = GetClassId();
- intptr_t idx = 0;
Zone* zone = thread->zone();
const Class& cls = Class::Handle(zone, this->clazz());
switch (cid) {
@@ -19048,11 +19119,6 @@
dbl ^= cls.LookupCanonicalDouble(zone, Double::Cast(*this).value());
return (dbl.raw() == this->raw());
}
- case kBigintCid: {
- Bigint& result = Bigint::Handle(zone);
- result ^= cls.LookupCanonicalBigint(zone, Bigint::Cast(*this), &idx);
- return (result.raw() == this->raw());
- }
default:
UNREACHABLE();
}
@@ -19083,21 +19149,14 @@
if (!OS::StringToInt64(cstr, &value)) {
// TODO(T31600): Remove overflow checking code when 64-bit ints semantics
// are only supported through the Kernel FE.
- if (FLAG_limit_ints_to_64_bits) {
- if (strcmp(cstr, kMaxInt64Plus1) == 0) {
- // Allow MAX_INT64 + 1 integer literal as it can be used as an argument
- // of unary minus to produce MIN_INT64 value. The value is automatically
- // wrapped to MIN_INT64.
- return Integer::New(kMinInt64, space);
- }
- // Out of range.
- return Integer::null();
+ if (strcmp(cstr, kMaxInt64Plus1) == 0) {
+ // Allow MAX_INT64 + 1 integer literal as it can be used as an argument
+ // of unary minus to produce MIN_INT64 value. The value is automatically
+ // wrapped to MIN_INT64.
+ return Integer::New(kMinInt64, space);
}
- const Bigint& big =
- Bigint::Handle(Bigint::NewFromCString(str.ToCString(), space));
- ASSERT(!big.FitsIntoSmi());
- ASSERT(!big.FitsIntoInt64());
- return big.raw();
+ // Out of range.
+ return Integer::null();
}
return Integer::New(value, space);
}
@@ -19110,20 +19169,14 @@
if (!OS::StringToInt64(cstr, &value)) {
// TODO(T31600): Remove overflow checking code when 64-bit ints semantics
// are only supported through the Kernel FE.
- if (FLAG_limit_ints_to_64_bits) {
- if (strcmp(cstr, kMaxInt64Plus1) == 0) {
- // Allow MAX_INT64 + 1 integer literal as it can be used as an argument
- // of unary minus to produce MIN_INT64 value. The value is automatically
- // wrapped to MIN_INT64.
- return Mint::NewCanonical(kMinInt64);
- }
- // Out of range.
- return Integer::null();
+ if (strcmp(cstr, kMaxInt64Plus1) == 0) {
+ // Allow MAX_INT64 + 1 integer literal as it can be used as an argument
+ // of unary minus to produce MIN_INT64 value. The value is automatically
+ // wrapped to MIN_INT64.
+ return Mint::NewCanonical(kMinInt64);
}
- const Bigint& big = Bigint::Handle(Bigint::NewCanonical(str));
- ASSERT(!big.FitsIntoSmi());
- ASSERT(!big.FitsIntoInt64());
- return big.raw();
+ // Out of range.
+ return Integer::null();
}
if (Smi::IsValid(value)) {
return Smi::New(static_cast<intptr_t>(value));
@@ -19140,19 +19193,11 @@
}
RawInteger* Integer::NewFromUint64(uint64_t value, Heap::Space space) {
- if (!FLAG_limit_ints_to_64_bits &&
- (value > static_cast<uint64_t>(Mint::kMaxValue))) {
- return Bigint::NewFromUint64(value, space);
- }
return Integer::New(static_cast<int64_t>(value), space);
}
bool Integer::IsValueInRange(uint64_t value) {
- if (FLAG_limit_ints_to_64_bits) {
- return (value <= static_cast<uint64_t>(Mint::kMaxValue));
- } else {
- return true;
- }
+ return (value <= static_cast<uint64_t>(Mint::kMaxValue));
}
bool Integer::Equals(const Instance& other) const {
@@ -19214,20 +19259,11 @@
return raw();
}
}
- if (Bigint::Cast(*this).FitsIntoInt64()) {
- const int64_t value = AsInt64Value();
- if (Smi::IsValid(value)) {
- // This cast is safe because Smi::IsValid verifies that value will fit.
- intptr_t val = static_cast<intptr_t>(value);
- return Smi::New(val);
- }
- return Mint::New(value);
- }
return raw();
}
const char* Integer::ToHexCString(Zone* zone) const {
- ASSERT(IsSmi() || IsMint()); // Bigint has its own implementation.
+ ASSERT(IsSmi() || IsMint());
int64_t value = AsInt64Value();
if (value < 0) {
return OS::SCreate(zone, "-0x%" PX64, static_cast<uint64_t>(-value));
@@ -19259,21 +19295,9 @@
space);
} else {
ASSERT(sizeof(intptr_t) == sizeof(int64_t));
- if (FLAG_limit_ints_to_64_bits) {
- return Integer::New(
- Utils::MulWithWrapAround(left_value, right_value), space);
- } else {
- // In 64-bit mode, the product of two signed integers fits in a
- // 64-bit result if the sum of the highest bits of their absolute
- // values is smaller than 62.
- if ((Utils::HighestBit(left_value) +
- Utils::HighestBit(right_value)) < 62) {
- return Integer::New(left_value * right_value, space);
- }
- }
+ return Integer::New(Utils::MulWithWrapAround(left_value, right_value),
+ space);
}
- // Perform a Bigint multiplication below.
- break;
}
case Token::kTRUNCDIV:
return Integer::New(left_value / right_value, space);
@@ -19292,77 +19316,45 @@
UNIMPLEMENTED();
}
}
- if (!IsBigint() && !other.IsBigint()) {
- const int64_t left_value = AsInt64Value();
- const int64_t right_value = other.AsInt64Value();
- switch (operation) {
- case Token::kADD: {
- if (FLAG_limit_ints_to_64_bits) {
- return Integer::New(Utils::AddWithWrapAround(left_value, right_value),
- space);
- } else {
- if (!Utils::WillAddOverflow(left_value, right_value)) {
- return Integer::New(left_value + right_value, space);
- }
- }
- break;
- }
- case Token::kSUB: {
- if (FLAG_limit_ints_to_64_bits) {
- return Integer::New(Utils::SubWithWrapAround(left_value, right_value),
- space);
- } else {
- if (!Utils::WillSubOverflow(left_value, right_value)) {
- return Integer::New(left_value - right_value, space);
- }
- }
- break;
- }
- case Token::kMUL: {
- if (FLAG_limit_ints_to_64_bits) {
- return Integer::New(Utils::MulWithWrapAround(left_value, right_value),
- space);
- } else {
- if ((Utils::HighestBit(left_value) + Utils::HighestBit(right_value)) <
- 62) {
- return Integer::New(left_value * right_value, space);
- }
- }
- break;
- }
- case Token::kTRUNCDIV: {
- if ((left_value == Mint::kMinValue) && (right_value == -1)) {
- // Division special case: overflow in int64_t.
- if (FLAG_limit_ints_to_64_bits) {
- // MIN_VALUE / -1 = (MAX_VALUE + 1), which wraps around to MIN_VALUE
- return Integer::New(Mint::kMinValue, space);
- }
- } else {
- return Integer::New(left_value / right_value, space);
- }
- break;
- }
- case Token::kMOD: {
- const int64_t remainder = left_value % right_value;
- if (remainder < 0) {
- if (right_value < 0) {
- return Integer::New(remainder - right_value, space);
- } else {
- return Integer::New(remainder + right_value, space);
- }
- }
- return Integer::New(remainder, space);
- }
- default:
- UNIMPLEMENTED();
- }
- }
- ASSERT(!Bigint::IsDisabled());
- return Integer::null(); // Notify caller that a bigint operation is required.
-}
+ const int64_t left_value = AsInt64Value();
+ const int64_t right_value = other.AsInt64Value();
+ switch (operation) {
+ case Token::kADD:
+ return Integer::New(Utils::AddWithWrapAround(left_value, right_value),
+ space);
-static bool Are64bitOperands(const Integer& op1, const Integer& op2) {
- return !op1.IsBigint() && !op2.IsBigint();
+ case Token::kSUB:
+ return Integer::New(Utils::SubWithWrapAround(left_value, right_value),
+ space);
+
+ case Token::kMUL:
+ return Integer::New(Utils::MulWithWrapAround(left_value, right_value),
+ space);
+
+ case Token::kTRUNCDIV:
+ if ((left_value == Mint::kMinValue) && (right_value == -1)) {
+ // Division special case: overflow in int64_t.
+ // MIN_VALUE / -1 = (MAX_VALUE + 1), which wraps around to MIN_VALUE
+ return Integer::New(Mint::kMinValue, space);
+ } else {
+ return Integer::New(left_value / right_value, space);
+ }
+
+ case Token::kMOD: {
+ const int64_t remainder = left_value % right_value;
+ if (remainder < 0) {
+ if (right_value < 0) {
+ return Integer::New(remainder - right_value, space);
+ } else {
+ return Integer::New(remainder + right_value, space);
+ }
+ }
+ return Integer::New(remainder, space);
+ }
+ default:
+ UNIMPLEMENTED();
+ return Integer::null();
+ }
}
RawInteger* Integer::BitOp(Token::Kind kind,
@@ -19387,7 +19379,7 @@
}
ASSERT(Smi::IsValid(result));
return Smi::New(result);
- } else if (Are64bitOperands(*this, other)) {
+ } else {
int64_t a = AsInt64Value();
int64_t b = other.AsInt64Value();
switch (kind) {
@@ -19399,10 +19391,9 @@
return Integer::New(a ^ b, space);
default:
UNIMPLEMENTED();
+ return Integer::null();
}
}
- ASSERT(!Bigint::IsDisabled());
- return Integer::null(); // Notify caller that a bigint operation is required.
}
// TODO(srdjan): Clarify handling of negative right operand in a shift op.
@@ -19421,18 +19412,8 @@
{ // Check for overflow.
int cnt = Utils::BitLength(left_value);
if (right_value > (Smi::kBits - cnt)) {
- if (FLAG_limit_ints_to_64_bits) {
- return Integer::New(
- Utils::ShiftLeftWithTruncation(left_value, right_value), space);
- } else {
- if (right_value > (Mint::kBits - cnt)) {
- return Bigint::NewFromShiftedInt64(left_value, right_value,
- space);
- } else {
- int64_t left_64 = left_value;
- return Integer::New(left_64 << right_value, space);
- }
- }
+ return Integer::New(
+ Utils::ShiftLeftWithTruncation(left_value, right_value), space);
}
}
result = left_value << right_value;
@@ -19482,7 +19463,7 @@
}
}
ASSERT(!other.FitsIntoSmi());
- if (other.IsMint() || other.IsBigint()) {
+ if (other.IsMint()) {
if (this->IsNegative() == other.IsNegative()) {
return this->IsNegative() ? 1 : -1;
}
@@ -19578,23 +19559,16 @@
int Mint::CompareWith(const Integer& other) const {
ASSERT(!FitsIntoSmi());
- if (other.IsMint() || other.IsSmi()) {
- int64_t a = AsInt64Value();
- int64_t b = other.AsInt64Value();
- if (a < b) {
- return -1;
- } else if (a > b) {
- return 1;
- } else {
- return 0;
- }
+ ASSERT(other.IsMint() || other.IsSmi());
+ int64_t a = AsInt64Value();
+ int64_t b = other.AsInt64Value();
+ if (a < b) {
+ return -1;
+ } else if (a > b) {
+ return 1;
+ } else {
+ return 0;
}
- ASSERT(other.IsBigint());
- ASSERT(!Bigint::Cast(other).FitsIntoInt64());
- if (this->IsNegative() == other.IsNegative()) {
- return this->IsNegative() ? 1 : -1;
- }
- return this->IsNegative() ? -1 : 1;
}
const char* Mint::ToCString() const {
@@ -19724,730 +19698,6 @@
return buffer;
}
-bool Bigint::Neg() const {
- return Bool::Handle(neg()).value();
-}
-
-void Bigint::SetNeg(bool value) const {
- StorePointer(&raw_ptr()->neg_, Bool::Get(value).raw());
-}
-
-intptr_t Bigint::Used() const {
- return Smi::Value(used());
-}
-
-void Bigint::SetUsed(intptr_t value) const {
- StoreSmi(&raw_ptr()->used_, Smi::New(value));
-}
-
-uint32_t Bigint::DigitAt(intptr_t index) const {
- const TypedData& typed_data = TypedData::Handle(digits());
- return typed_data.GetUint32(index << 2);
-}
-
-void Bigint::set_digits(const TypedData& value) const {
- // The VM expects digits_ to be a Uint32List (not null).
- ASSERT(!value.IsNull() && (value.GetClassId() == kTypedDataUint32ArrayCid));
- StorePointer(&raw_ptr()->digits_, value.raw());
-}
-
-RawTypedData* Bigint::NewDigits(intptr_t length, Heap::Space space) {
- ASSERT(length > 0);
- // Account for leading zero for 64-bit processing.
- return TypedData::New(kTypedDataUint32ArrayCid, length + 1, space);
-}
-
-uint32_t Bigint::DigitAt(const TypedData& digits, intptr_t index) {
- return digits.GetUint32(index << 2);
-}
-
-void Bigint::SetDigitAt(const TypedData& digits,
- intptr_t index,
- uint32_t value) {
- digits.SetUint32(index << 2, value);
-}
-
-bool Bigint::Equals(const Instance& other) const {
- if (this->raw() == other.raw()) {
- // Both handles point to the same raw instance.
- return true;
- }
-
- if (!other.IsBigint() || other.IsNull()) {
- return false;
- }
-
- const Bigint& other_bgi = Bigint::Cast(other);
-
- if (this->Neg() != other_bgi.Neg()) {
- return false;
- }
-
- const intptr_t used = this->Used();
- if (used != other_bgi.Used()) {
- return false;
- }
-
- for (intptr_t i = 0; i < used; i++) {
- if (this->DigitAt(i) != other_bgi.DigitAt(i)) {
- return false;
- }
- }
- return true;
-}
-
-bool Bigint::CheckAndCanonicalizeFields(Thread* thread,
- const char** error_str) const {
- Zone* zone = thread->zone();
- // Bool field neg should always be canonical.
- ASSERT(Bool::Handle(zone, neg()).IsCanonical());
- // Smi field used is canonical by definition.
- if (Used() > 0) {
- // Canonicalize TypedData field digits.
- TypedData& digits_ = TypedData::Handle(zone, digits());
- digits_ ^= digits_.CheckAndCanonicalize(thread, NULL);
- ASSERT(!digits_.IsNull());
- set_digits(digits_);
- } else {
- ASSERT(digits() == TypedData::EmptyUint32Array(Thread::Current()));
- }
- return true;
-}
-
-RawBigint* Bigint::New(Heap::Space space) {
- ASSERT(!Bigint::IsDisabled());
- Thread* thread = Thread::Current();
- Zone* zone = thread->zone();
- Isolate* isolate = thread->isolate();
- ASSERT(isolate->object_store()->bigint_class() != Class::null());
- Bigint& result = Bigint::Handle(zone);
- {
- RawObject* raw =
- Object::Allocate(Bigint::kClassId, Bigint::InstanceSize(), space);
- NoSafepointScope no_safepoint;
- result ^= raw;
- }
- result.SetNeg(false);
- result.SetUsed(0);
- result.set_digits(
- TypedData::Handle(zone, TypedData::EmptyUint32Array(thread)));
- return result.raw();
-}
-
-RawBigint* Bigint::New(bool neg,
- intptr_t used,
- const TypedData& digits,
- Heap::Space space) {
- ASSERT(!Bigint::IsDisabled());
- ASSERT((used == 0) ||
- (!digits.IsNull() && (digits.Length() >= (used + (used & 1)))));
- Thread* thread = Thread::Current();
- Zone* zone = thread->zone();
- Isolate* isolate = thread->isolate();
- ASSERT(isolate->object_store()->bigint_class() != Class::null());
- Bigint& result = Bigint::Handle(zone);
- {
- RawObject* raw =
- Object::Allocate(Bigint::kClassId, Bigint::InstanceSize(), space);
- NoSafepointScope no_safepoint;
- result ^= raw;
- }
- // Clamp the digits array.
- while ((used > 0) && (digits.GetUint32((used - 1) << 2) == 0)) {
- --used;
- }
- if (used > 0) {
- if (((used & 1) != 0) && (digits.GetUint32(used << 2) != 0)) {
- // Set leading zero for 64-bit processing of digit pairs if not set.
- // The check above ensures that we avoid a write access to a possibly
- // reused digits array that could be marked read only.
- digits.SetUint32(used << 2, 0);
- }
- result.set_digits(digits);
- } else {
- neg = false;
- result.set_digits(
- TypedData::Handle(zone, TypedData::EmptyUint32Array(thread)));
- }
- result.SetNeg(neg);
- result.SetUsed(used);
- return result.raw();
-}
-
-RawBigint* Bigint::NewFromInt64(int64_t value, Heap::Space space) {
- ASSERT(!Bigint::IsDisabled());
- const TypedData& digits = TypedData::Handle(NewDigits(2, space));
- bool neg;
- uint64_t abs_value;
- if (value < 0) {
- neg = true;
- abs_value = -value;
- } else {
- neg = false;
- abs_value = value;
- }
- SetDigitAt(digits, 0, static_cast<uint32_t>(abs_value));
- SetDigitAt(digits, 1, static_cast<uint32_t>(abs_value >> 32));
- return New(neg, 2, digits, space);
-}
-
-RawBigint* Bigint::NewFromUint64(uint64_t value, Heap::Space space) {
- ASSERT(!Bigint::IsDisabled());
- const TypedData& digits = TypedData::Handle(NewDigits(2, space));
- SetDigitAt(digits, 0, static_cast<uint32_t>(value));
- SetDigitAt(digits, 1, static_cast<uint32_t>(value >> 32));
- return New(false, 2, digits, space);
-}
-
-RawBigint* Bigint::NewFromShiftedInt64(int64_t value,
- intptr_t shift,
- Heap::Space space) {
- ASSERT(!Bigint::IsDisabled());
- ASSERT(kBitsPerDigit == 32);
- ASSERT(shift >= 0);
- const intptr_t digit_shift = shift / kBitsPerDigit;
- const intptr_t bit_shift = shift % kBitsPerDigit;
- const intptr_t used = 3 + digit_shift;
- const TypedData& digits = TypedData::Handle(NewDigits(used, space));
- bool neg;
- uint64_t abs_value;
- if (value < 0) {
- neg = true;
- abs_value = -value;
- } else {
- neg = false;
- abs_value = value;
- }
- for (intptr_t i = 0; i < digit_shift; i++) {
- SetDigitAt(digits, i, 0);
- }
- SetDigitAt(digits, 0 + digit_shift,
- static_cast<uint32_t>(abs_value << bit_shift));
- SetDigitAt(digits, 1 + digit_shift,
- static_cast<uint32_t>(abs_value >> (32 - bit_shift)));
- SetDigitAt(digits, 2 + digit_shift,
- (bit_shift == 0)
- ? 0
- : static_cast<uint32_t>(abs_value >> (64 - bit_shift)));
- return New(neg, used, digits, space);
-}
-
-RawBigint* Bigint::NewFromCString(const char* str, Heap::Space space) {
- ASSERT(!Bigint::IsDisabled());
- ASSERT(str != NULL);
- bool neg = false;
- TypedData& digits = TypedData::Handle();
- if (str[0] == '-') {
- ASSERT(str[1] != '-');
- neg = true;
- str++;
- }
- intptr_t used;
- const intptr_t str_length = strlen(str);
- if ((str_length >= 2) && (str[0] == '0') &&
- ((str[1] == 'x') || (str[1] == 'X'))) {
- digits = NewDigitsFromHexCString(&str[2], &used, space);
- } else {
- digits = NewDigitsFromDecCString(str, &used, space);
- }
- return New(neg, used, digits, space);
-}
-
-RawBigint* Bigint::NewCanonical(const String& str) {
- ASSERT(!Bigint::IsDisabled());
- Thread* thread = Thread::Current();
- Zone* zone = thread->zone();
- Isolate* isolate = thread->isolate();
- const Bigint& value =
- Bigint::Handle(zone, Bigint::NewFromCString(str.ToCString(), Heap::kOld));
- const Class& cls =
- Class::Handle(zone, isolate->object_store()->bigint_class());
- intptr_t index = 0;
- Bigint& canonical_value = Bigint::Handle(zone);
- canonical_value ^= cls.LookupCanonicalBigint(zone, value, &index);
- if (!canonical_value.IsNull()) {
- return canonical_value.raw();
- }
- {
- SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
- // Retry lookup.
- {
- canonical_value ^= cls.LookupCanonicalBigint(zone, value, &index);
- if (!canonical_value.IsNull()) {
- return canonical_value.raw();
- }
- }
- value.SetCanonical();
- // The value needs to be added to the constants list. Grow the list if
- // it is full.
- cls.InsertCanonicalBigint(zone, index, value);
- return value.raw();
- }
-}
-
-RawTypedData* Bigint::NewDigitsFromHexCString(const char* str,
- intptr_t* used,
- Heap::Space space) {
- const int kBitsPerHexDigit = 4;
- const int kHexDigitsPerDigit = 8;
- const int kBitsPerDigit = kBitsPerHexDigit * kHexDigitsPerDigit;
- intptr_t hex_i = strlen(str); // Terminating byte excluded.
- if ((hex_i <= 0) || (hex_i >= kMaxInt32)) {
- FATAL("Fatal error parsing hex bigint: string too long or empty");
- }
- const intptr_t length = (hex_i + kHexDigitsPerDigit - 1) / kHexDigitsPerDigit;
- const TypedData& digits = TypedData::Handle(NewDigits(length, space));
- intptr_t used_ = 0;
- uint32_t digit = 0;
- intptr_t bit_i = 0;
- while (--hex_i >= 0) {
- digit += Utils::HexDigitToInt(str[hex_i]) << bit_i;
- bit_i += kBitsPerHexDigit;
- if (bit_i == kBitsPerDigit) {
- bit_i = 0;
- SetDigitAt(digits, used_++, digit);
- digit = 0;
- }
- }
- if (bit_i != 0) {
- SetDigitAt(digits, used_++, digit);
- }
- *used = used_;
- return digits.raw();
-}
-
-RawTypedData* Bigint::NewDigitsFromDecCString(const char* str,
- intptr_t* used,
- Heap::Space space) {
- // Read 9 digits a time. 10^9 < 2^32.
- const int kDecDigitsPerIteration = 9;
- const uint32_t kTenMultiplier = 1000000000;
- ASSERT(kBitsPerDigit == 32);
- const intptr_t str_length = strlen(str);
- if ((str_length <= 0) || (str_length >= kMaxInt32)) {
- FATAL("Fatal error parsing dec bigint: string too long or empty");
- }
- // One decimal digit takes log2(10) bits, i.e. ~3.32192809489 bits.
- // That is a theoretical limit for large numbers.
- // The extra 5 digits allocated take care of variations.
- const int64_t kLog10Dividend = 33219281;
- const int64_t kLog10Divisor = 10000000;
- const intptr_t length =
- (kLog10Dividend * str_length) / (kLog10Divisor * kBitsPerDigit) + 5;
- const TypedData& digits = TypedData::Handle(NewDigits(length, space));
- // Read first digit separately. This avoids a multiplication and addition.
- // The first digit might also not have kDecDigitsPerIteration decimal digits.
- const intptr_t lsdigit_length = str_length % kDecDigitsPerIteration;
- uint32_t digit = 0;
- intptr_t str_pos = 0;
- for (intptr_t i = 0; i < lsdigit_length; i++) {
- char c = str[str_pos++];
- ASSERT(('0' <= c) && (c <= '9'));
- digit = digit * 10 + c - '0';
- }
- SetDigitAt(digits, 0, digit);
- intptr_t used_ = 1;
- // Read kDecDigitsPerIteration at a time, and store it in 'digit'.
- // Then multiply the temporary result by 10^kDecDigitsPerIteration and add
- // 'digit' to the new result.
- while (str_pos < str_length - 1) {
- digit = 0;
- for (intptr_t i = 0; i < kDecDigitsPerIteration; i++) {
- char c = str[str_pos++];
- ASSERT(('0' <= c) && (c <= '9'));
- digit = digit * 10 + c - '0';
- }
- // Multiply result with kTenMultiplier and add digit.
- for (intptr_t i = 0; i < used_; i++) {
- uint64_t product =
- (static_cast<uint64_t>(DigitAt(digits, i)) * kTenMultiplier) + digit;
- SetDigitAt(digits, i, static_cast<uint32_t>(product & kDigitMask));
- digit = static_cast<uint32_t>(product >> kBitsPerDigit);
- }
- SetDigitAt(digits, used_++, digit);
- }
- *used = used_;
- return digits.raw();
-}
-
-static double Uint64ToDouble(uint64_t x) {
-#if _WIN64
- // For static_cast<double>(x) MSVC x64 generates
- //
- // cvtsi2sd xmm0, rax
- // test rax, rax
- // jns done
- // addsd xmm0, static_cast<double>(2^64)
- // done:
- //
- // while GCC -m64 generates
- //
- // test rax, rax
- // js negative
- // cvtsi2sd xmm0, rax
- // jmp done
- // negative:
- // mov rdx, rax
- // shr rdx, 1
- // and eax, 0x1
- // or rdx, rax
- // cvtsi2sd xmm0, rdx
- // addsd xmm0, xmm0
- // done:
- //
- // which results in a different rounding.
- //
- // For consistency between platforms fallback to GCC style conversion
- // on Win64.
- //
- const int64_t y = static_cast<int64_t>(x);
- if (y > 0) {
- return static_cast<double>(y);
- } else {
- const double half =
- static_cast<double>(static_cast<int64_t>(x >> 1) | (y & 1));
- return half + half;
- }
-#else
- return static_cast<double>(x);
-#endif
-}
-
-double Bigint::AsDoubleValue() const {
- ASSERT(kBitsPerDigit == 32);
- const intptr_t used = Used();
- if (used == 0) {
- return 0.0;
- }
- if (used <= 2) {
- const uint64_t digit1 = (used > 1) ? DigitAt(1) : 0;
- const uint64_t abs_value = (digit1 << 32) + DigitAt(0);
- const double abs_double_value = Uint64ToDouble(abs_value);
- return Neg() ? -abs_double_value : abs_double_value;
- }
-
- static const int kPhysicalSignificandSize = 52;
- // The significand size has an additional hidden bit.
- static const int kSignificandSize = kPhysicalSignificandSize + 1;
- static const int kExponentBias = 0x3FF + kPhysicalSignificandSize;
- static const int kMaxExponent = 0x7FF - kExponentBias;
- static const uint64_t kOne64 = 1;
- static const uint64_t kInfinityBits =
- DART_2PART_UINT64_C(0x7FF00000, 00000000);
-
- // A double is composed of an exponent e and a significand s. Its value equals
- // s * 2^e. The significand has 53 bits of which the first one must always be
- // 1 (at least for then numbers we are working with here) and is therefore
- // omitted. The physical size of the significand is thus 52 bits.
- // The exponent has 11 bits and is biased by 0x3FF + 52. For example an
- // exponent e = 10 is written as 0x3FF + 52 + 10 (in the 11 bits that are
- // reserved for the exponent).
- // When converting the given bignum to a double we have to pay attention to
- // the rounding. In particular we have to decide which double to pick if an
- // input lies exactly between two doubles. As usual with double operations
- // we pick the double with an even significand in such cases.
- //
- // General approach of this algorithm: Get 54 bits (one more than the
- // significand size) of the bigint. If the last bit is then 1, then (without
- // knowledge of the remaining bits) we could have a half-way number.
- // If the second-to-last bit is odd then we know that we have to round up:
- // if the remaining bits are not zero then the input lies closer to the higher
- // double. If the remaining bits are zero then we have a half-way case and
- // we need to round up too (rounding to the even double).
- // If the second-to-last bit is even then we need to look at the remaining
- // bits to determine if any of them is not zero. If that's the case then the
- // number lies closer to the next-higher double. Otherwise we round the
- // half-way case down to even.
-
- if (((used - 1) * kBitsPerDigit) > (kMaxExponent + kSignificandSize)) {
- // Does not fit into a double.
- const double infinity = bit_cast<double>(kInfinityBits);
- return Neg() ? -infinity : infinity;
- }
-
- intptr_t digit_index = used - 1;
- // In order to round correctly we need to look at half-way cases. Therefore we
- // get kSignificandSize + 1 bits. If the last bit is 1 then we have to look
- // at the remaining bits to know if we have to round up.
- int needed_bits = kSignificandSize + 1;
- ASSERT((kBitsPerDigit < needed_bits) && (2 * kBitsPerDigit >= needed_bits));
- bool discarded_bits_were_zero = true;
-
- const uint32_t firstDigit = DigitAt(digit_index--);
- ASSERT(firstDigit > 0);
- uint64_t twice_significand_floor = firstDigit;
- intptr_t twice_significant_exponent = (digit_index + 1) * kBitsPerDigit;
- needed_bits -= Utils::HighestBit(firstDigit) + 1;
-
- if (needed_bits >= kBitsPerDigit) {
- twice_significand_floor <<= kBitsPerDigit;
- twice_significand_floor |= DigitAt(digit_index--);
- twice_significant_exponent -= kBitsPerDigit;
- needed_bits -= kBitsPerDigit;
- }
- if (needed_bits > 0) {
- ASSERT(needed_bits <= kBitsPerDigit);
- uint32_t digit = DigitAt(digit_index--);
- int discarded_bits_count = kBitsPerDigit - needed_bits;
- twice_significand_floor <<= needed_bits;
- twice_significand_floor |= digit >> discarded_bits_count;
- twice_significant_exponent -= needed_bits;
- uint64_t discarded_bits_mask = (kOne64 << discarded_bits_count) - 1;
- discarded_bits_were_zero = ((digit & discarded_bits_mask) == 0);
- }
- ASSERT((twice_significand_floor >> kSignificandSize) == 1);
-
- // We might need to round up the significand later.
- uint64_t significand = twice_significand_floor >> 1;
- const intptr_t exponent = twice_significant_exponent + 1;
-
- if (exponent >= kMaxExponent) {
- // Infinity.
- // Does not fit into a double.
- const double infinity = bit_cast<double>(kInfinityBits);
- return Neg() ? -infinity : infinity;
- }
-
- if ((twice_significand_floor & 1) == 1) {
- bool round_up = false;
-
- if ((significand & 1) != 0 || !discarded_bits_were_zero) {
- // Even if the remaining bits are zero we still need to round up since we
- // want to round to even for half-way cases.
- round_up = true;
- } else {
- // Could be a half-way case. See if the remaining bits are non-zero.
- for (intptr_t i = 0; i <= digit_index; i++) {
- if (DigitAt(i) != 0) {
- round_up = true;
- break;
- }
- }
- }
-
- if (round_up) {
- significand++;
- // It might be that we just went from 53 bits to 54 bits.
- // Example: After adding 1 to 1FFF..FF (with 53 bits set to 1) we have
- // 2000..00 (= 2 ^ 54). When adding the exponent and significand together
- // this will increase the exponent by 1 which is exactly what we want.
- }
- }
-
- ASSERT(((significand >> (kSignificandSize - 1)) == 1) ||
- (significand == (kOne64 << kSignificandSize)));
- // The significand still has the hidden bit. We simply decrement the biased
- // exponent by one instead of playing around with the significand.
- const uint64_t biased_exponent = exponent + kExponentBias - 1;
- // Note that we must use the plus operator instead of bit-or.
- const uint64_t double_bits =
- (biased_exponent << kPhysicalSignificandSize) + significand;
-
- const double value = bit_cast<double>(double_bits);
- return Neg() ? -value : value;
-}
-
-bool Bigint::FitsIntoSmi() const {
- return FitsIntoInt64() && Smi::IsValid(AsInt64Value());
-}
-
-bool Bigint::FitsIntoInt64() const {
- ASSERT(Bigint::kBitsPerDigit == 32);
- const intptr_t used = Used();
- if (used < 2) return true;
- if (used > 2) return false;
- const uint64_t digit1 = DigitAt(1);
- const uint64_t value = (digit1 << 32) + DigitAt(0);
- uint64_t limit = Mint::kMaxValue;
- if (Neg()) {
- limit++;
- }
- return value <= limit;
-}
-
-int64_t Bigint::AsTruncatedInt64Value() const {
- const intptr_t used = Used();
- if (used == 0) return 0;
- const int64_t digit1 = (used > 1) ? DigitAt(1) : 0;
- const int64_t value = (digit1 << 32) + DigitAt(0);
- return Neg() ? -value : value;
-}
-
-int64_t Bigint::AsInt64Value() const {
- ASSERT(FitsIntoInt64());
- return AsTruncatedInt64Value();
-}
-
-bool Bigint::FitsIntoUint64() const {
- ASSERT(Bigint::kBitsPerDigit == 32);
- return !Neg() && (Used() <= 2);
-}
-
-uint64_t Bigint::AsUint64Value() const {
- ASSERT(FitsIntoUint64());
- const intptr_t used = Used();
- if (used == 0) return 0;
- const uint64_t digit1 = (used > 1) ? DigitAt(1) : 0;
- return (digit1 << 32) + DigitAt(0);
-}
-
-uint32_t Bigint::AsTruncatedUint32Value() const {
- // Note: the previous implementation of Bigint returned the absolute value
- // truncated to 32 bits, which is not consistent with Smi and Mint behavior.
- ASSERT(Bigint::kBitsPerDigit == 32);
- const intptr_t used = Used();
- if (used == 0) return 0;
- const uint32_t digit0 = DigitAt(0);
- return Neg() ? static_cast<uint32_t>(-static_cast<int32_t>(digit0)) : digit0;
-}
-
-// For positive values: Smi < Mint < Bigint.
-int Bigint::CompareWith(const Integer& other) const {
- ASSERT(!FitsIntoSmi());
- ASSERT(!FitsIntoInt64());
- if (other.IsBigint() && (IsNegative() == other.IsNegative())) {
- const Bigint& other_bgi = Bigint::Cast(other);
- int64_t result = Used() - other_bgi.Used();
- if (result == 0) {
- for (intptr_t i = Used(); --i >= 0;) {
- result = DigitAt(i);
- result -= other_bgi.DigitAt(i);
- if (result != 0) break;
- }
- }
- if (IsNegative()) {
- result = -result;
- }
- return result > 0 ? 1 : result < 0 ? -1 : 0;
- }
- return this->IsNegative() ? -1 : 1;
-}
-
-const char* Bigint::ToDecCString(Zone* zone) const {
- // log10(2) ~= 0.30102999566398114.
- const intptr_t kLog2Dividend = 30103;
- const intptr_t kLog2Divisor = 100000;
- intptr_t used = Used();
- const intptr_t kMaxUsed =
- kIntptrMax / kBitsPerDigit / kLog2Dividend * kLog2Divisor;
- if (used > kMaxUsed) {
- Exceptions::ThrowOOM();
- UNREACHABLE();
- }
- const int64_t bit_len = used * kBitsPerDigit;
- const int64_t dec_len = (bit_len * kLog2Dividend / kLog2Divisor) + 1;
- // Add one byte for the minus sign and for the trailing \0 character.
- const int64_t len = (Neg() ? 1 : 0) + dec_len + 1;
- char* chars = zone->Alloc<char>(len);
- intptr_t pos = 0;
- const intptr_t kDivisor = 100000000;
- const intptr_t kDigits = 8;
- ASSERT(pow(10.0, 1.0 * kDigits) == kDivisor);
- ASSERT(kDivisor < kDigitBase);
- ASSERT(Smi::IsValid(kDivisor));
- // Allocate a copy of the digits.
- uint32_t* rest_digits = zone->Alloc<uint32_t>(used);
- for (intptr_t i = 0; i < used; i++) {
- rest_digits[i] = DigitAt(i);
- }
- if (used == 0) {
- chars[pos++] = '0';
- }
- while (used > 0) {
- uint32_t remainder = 0;
- for (intptr_t i = used - 1; i >= 0; i--) {
- uint64_t dividend =
- (static_cast<uint64_t>(remainder) << kBitsPerDigit) + rest_digits[i];
- uint32_t quotient = static_cast<uint32_t>(dividend / kDivisor);
- remainder = static_cast<uint32_t>(
- dividend - static_cast<uint64_t>(quotient) * kDivisor);
- rest_digits[i] = quotient;
- }
- // Clamp rest_digits.
- while ((used > 0) && (rest_digits[used - 1] == 0)) {
- used--;
- }
- for (intptr_t i = 0; i < kDigits; i++) {
- chars[pos++] = '0' + (remainder % 10);
- remainder /= 10;
- }
- ASSERT(remainder == 0);
- }
- // Remove leading zeros.
- while ((pos > 1) && (chars[pos - 1] == '0')) {
- pos--;
- }
- if (Neg()) {
- chars[pos++] = '-';
- }
- // Reverse the string.
- intptr_t i = 0;
- intptr_t j = pos - 1;
- while (i < j) {
- char tmp = chars[i];
- chars[i] = chars[j];
- chars[j] = tmp;
- i++;
- j--;
- }
- chars[pos] = '\0';
- return chars;
-}
-
-const char* Bigint::ToHexCString(Zone* zone) const {
- const intptr_t used = Used();
- if (used == 0) {
- const char* zero = "0x0";
- const size_t len = strlen(zero) + 1;
- char* chars = zone->Alloc<char>(len);
- strncpy(chars, zero, len);
- return chars;
- }
- const int kBitsPerHexDigit = 4;
- const int kHexDigitsPerDigit = 8;
- const intptr_t kMaxUsed = (kIntptrMax - 4) / kHexDigitsPerDigit;
- if (used > kMaxUsed) {
- Exceptions::ThrowOOM();
- UNREACHABLE();
- }
- intptr_t hex_len = (used - 1) * kHexDigitsPerDigit;
- // The most significant digit may use fewer than kHexDigitsPerDigit digits.
- uint32_t digit = DigitAt(used - 1);
- ASSERT(digit != 0); // Value must be clamped.
- while (digit != 0) {
- hex_len++;
- digit >>= kBitsPerHexDigit;
- }
- // Add bytes for '0x', for the minus sign, and for the trailing \0 character.
- const int32_t len = (Neg() ? 1 : 0) + 2 + hex_len + 1;
- char* chars = zone->Alloc<char>(len);
- intptr_t pos = len;
- chars[--pos] = '\0';
- for (intptr_t i = 0; i < (used - 1); i++) {
- digit = DigitAt(i);
- for (intptr_t j = 0; j < kHexDigitsPerDigit; j++) {
- chars[--pos] = Utils::IntToHexDigit(digit & 0xf);
- digit >>= kBitsPerHexDigit;
- }
- }
- digit = DigitAt(used - 1);
- while (digit != 0) {
- chars[--pos] = Utils::IntToHexDigit(digit & 0xf);
- digit >>= kBitsPerHexDigit;
- }
- chars[--pos] = 'x';
- chars[--pos] = '0';
- if (Neg()) {
- chars[--pos] = '-';
- }
- ASSERT(pos == 0);
- return chars;
-}
-
-const char* Bigint::ToCString() const {
- return ToDecCString(Thread::Current()->zone());
-}
-
// Synchronize with implementation in compiler (intrinsifier).
class StringHasher : ValueObject {
public:
@@ -20531,7 +19781,7 @@
ASSERT(raw->IsExternalOneByteString());
RawExternalOneByteString* str =
reinterpret_cast<RawExternalOneByteString*>(raw);
- data = str->ptr()->external_data_->data();
+ data = str->ptr()->external_data_;
}
return String::Hash(data, length);
} else {
@@ -20542,7 +19792,7 @@
ASSERT(raw->IsExternalTwoByteString());
RawExternalTwoByteString* str =
reinterpret_cast<RawExternalTwoByteString*>(raw);
- data = str->ptr()->external_data_->data();
+ data = str->ptr()->external_data_;
}
return String::Hash(data, length);
}
@@ -20868,17 +20118,21 @@
RawString* String::NewExternal(const uint8_t* characters,
intptr_t len,
void* peer,
- Dart_PeerFinalizer callback,
+ intptr_t external_allocation_size,
+ Dart_WeakPersistentHandleFinalizer callback,
Heap::Space space) {
- return ExternalOneByteString::New(characters, len, peer, callback, space);
+ return ExternalOneByteString::New(characters, len, peer,
+ external_allocation_size, callback, space);
}
RawString* String::NewExternal(const uint16_t* characters,
intptr_t len,
void* peer,
- Dart_PeerFinalizer callback,
+ intptr_t external_allocation_size,
+ Dart_WeakPersistentHandleFinalizer callback,
Heap::Space space) {
- return ExternalTwoByteString::New(characters, len, peer, callback, space);
+ return ExternalTwoByteString::New(characters, len, peer,
+ external_allocation_size, callback, space);
}
void String::Copy(const String& dst,
@@ -21264,8 +20518,7 @@
void* peer,
Dart_WeakPersistentHandleFinalizer callback,
intptr_t external_size) {
- ASSERT((callback != NULL && peer != NULL) ||
- (callback == NULL && peer == NULL));
+ ASSERT(callback != NULL);
return FinalizablePersistentHandle::New(Isolate::Current(), referent, peer,
callback, external_size);
}
@@ -21689,24 +20942,6 @@
return result;
}
-void OneByteString::SetPeer(const String& str,
- intptr_t external_size,
- void* peer,
- Dart_PeerFinalizer cback) {
- ASSERT(!str.IsNull() && str.IsOneByteString());
- ASSERT(peer != NULL);
- ExternalStringData<uint8_t>* ext_data =
- new ExternalStringData<uint8_t>(NULL, peer, cback);
- AddFinalizer(str, ext_data, OneByteString::Finalize, external_size);
- Isolate::Current()->heap()->SetPeer(str.raw(), peer);
-}
-
-void OneByteString::Finalize(void* isolate_callback_data,
- Dart_WeakPersistentHandle handle,
- void* peer) {
- delete reinterpret_cast<ExternalStringData<uint8_t>*>(peer);
-}
-
RawTwoByteString* TwoByteString::EscapeSpecialCharacters(const String& str) {
intptr_t len = str.Length();
if (len > 0) {
@@ -21886,29 +21121,12 @@
return TwoByteString::raw(result);
}
-void TwoByteString::SetPeer(const String& str,
- intptr_t external_size,
- void* peer,
- Dart_PeerFinalizer cback) {
- ASSERT(!str.IsNull() && str.IsTwoByteString());
- ASSERT(peer != NULL);
- ExternalStringData<uint16_t>* ext_data =
- new ExternalStringData<uint16_t>(NULL, peer, cback);
- AddFinalizer(str, ext_data, TwoByteString::Finalize, external_size);
- Isolate::Current()->heap()->SetPeer(str.raw(), peer);
-}
-
-void TwoByteString::Finalize(void* isolate_callback_data,
- Dart_WeakPersistentHandle handle,
- void* peer) {
- delete reinterpret_cast<ExternalStringData<uint16_t>*>(peer);
-}
-
RawExternalOneByteString* ExternalOneByteString::New(
const uint8_t* data,
intptr_t len,
void* peer,
- Dart_PeerFinalizer callback,
+ intptr_t external_allocation_size,
+ Dart_WeakPersistentHandleFinalizer callback,
Heap::Space space) {
ASSERT(Isolate::Current()->object_store()->external_one_byte_string_class() !=
Class::null());
@@ -21918,8 +21136,6 @@
len);
}
String& result = String::Handle();
- ExternalStringData<uint8_t>* external_data =
- new ExternalStringData<uint8_t>(data, peer, callback);
{
RawObject* raw =
Object::Allocate(ExternalOneByteString::kClassId,
@@ -21928,25 +21144,18 @@
result ^= raw;
result.SetLength(len);
result.SetHash(0);
- SetExternalData(result, external_data);
+ SetExternalData(result, data, peer);
}
- intptr_t external_size = len;
- AddFinalizer(result, external_data, ExternalOneByteString::Finalize,
- external_size);
+ AddFinalizer(result, peer, callback, external_allocation_size);
return ExternalOneByteString::raw(result);
}
-void ExternalOneByteString::Finalize(void* isolate_callback_data,
- Dart_WeakPersistentHandle handle,
- void* peer) {
- delete reinterpret_cast<ExternalStringData<uint8_t>*>(peer);
-}
-
RawExternalTwoByteString* ExternalTwoByteString::New(
const uint16_t* data,
intptr_t len,
void* peer,
- Dart_PeerFinalizer callback,
+ intptr_t external_allocation_size,
+ Dart_WeakPersistentHandleFinalizer callback,
Heap::Space space) {
ASSERT(Isolate::Current()->object_store()->external_two_byte_string_class() !=
Class::null());
@@ -21956,8 +21165,6 @@
len);
}
String& result = String::Handle();
- ExternalStringData<uint16_t>* external_data =
- new ExternalStringData<uint16_t>(data, peer, callback);
{
RawObject* raw =
Object::Allocate(ExternalTwoByteString::kClassId,
@@ -21966,20 +21173,12 @@
result ^= raw;
result.SetLength(len);
result.SetHash(0);
- SetExternalData(result, external_data);
+ SetExternalData(result, data, peer);
}
- intptr_t external_size = len * 2;
- AddFinalizer(result, external_data, ExternalTwoByteString::Finalize,
- external_size);
+ AddFinalizer(result, peer, callback, external_allocation_size);
return ExternalTwoByteString::raw(result);
}
-void ExternalTwoByteString::Finalize(void* isolate_callback_data,
- Dart_WeakPersistentHandle handle,
- void* peer) {
- delete reinterpret_cast<ExternalStringData<uint16_t>*>(peer);
-}
-
RawBool* Bool::New(bool value) {
ASSERT(Isolate::Current()->object_store()->bool_class() != Class::null());
Bool& result = Bool::Handle();
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 41efcde..e09544a 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1221,13 +1221,6 @@
RawDouble* LookupCanonicalDouble(Zone* zone, double value) const;
RawMint* LookupCanonicalMint(Zone* zone, int64_t value) const;
- // Returns an instance of Bigint or Bigint::null().
- // 'index' points to either:
- // - constants_list_ position of found element, or
- // - constants_list_ position where new canonical can be inserted.
- RawBigint* LookupCanonicalBigint(Zone* zone,
- const Bigint& value,
- intptr_t* index) const;
// The methods above are more efficient than this generic one.
RawInstance* LookupCanonicalInstance(Zone* zone, const Instance& value) const;
@@ -1235,9 +1228,6 @@
const Instance& constant) const;
void InsertCanonicalDouble(Zone* zone, const Double& constant) const;
void InsertCanonicalMint(Zone* zone, const Mint& constant) const;
- void InsertCanonicalBigint(Zone* zone,
- intptr_t index,
- const Bigint& constant) const;
void RehashConstants(Zone* zone) const;
@@ -1389,6 +1379,12 @@
const Array& param_values,
const Array& type_param_names,
const TypeArguments& type_param_values) const;
+ RawObject* EvaluateCompiledExpression(
+ const uint8_t* kernel_bytes,
+ intptr_t kernel_length,
+ const Array& type_definitions,
+ const Array& param_values,
+ const TypeArguments& type_param_values) const;
RawError* EnsureIsFinalized(Thread* thread) const;
@@ -3759,6 +3755,13 @@
const Array& type_param_names,
const TypeArguments& type_arguments) const;
+ RawObject* EvaluateCompiledExpression(
+ const uint8_t* kernel_bytes,
+ intptr_t kernel_length,
+ const Array& type_definitions,
+ const Array& param_values,
+ const TypeArguments& type_param_values) const;
+
// Library scope name dictionary.
//
// TODO(turnidge): The Lookup functions are not consistent in how
@@ -5633,6 +5636,14 @@
const Array& type_param_names,
const TypeArguments& type_param_values) const;
+ RawObject* EvaluateCompiledExpression(
+ const Class& method_cls,
+ const uint8_t* kernel_bytes,
+ intptr_t kernel_length,
+ const Array& type_definitions,
+ const Array& param_values,
+ const TypeArguments& type_param_values) const;
+
// Equivalent to invoking hashCode on this instance.
virtual RawObject* HashCode() const;
@@ -6780,13 +6791,13 @@
static RawInteger* New(const String& str, Heap::Space space = Heap::kNew);
// Creates a new Integer by given uint64_t value.
- // In the --limit-ints-to-64-bits mode silently casts value to int64_t
- // (with wrap-around if it is greater than kMaxInt64).
+ // Silently casts value to int64_t with wrap-around if it is greater
+ // than kMaxInt64.
static RawInteger* NewFromUint64(uint64_t value,
Heap::Space space = Heap::kNew);
// Returns a canonical Integer object allocated in the old gen space.
- // Returns null if integer is out of range (in --limit-ints-to-64-bits mode).
+ // Returns null if integer is out of range.
static RawInteger* NewCanonical(const String& str);
static RawInteger* New(int64_t value, Heap::Space space = Heap::kNew);
@@ -6819,9 +6830,7 @@
virtual int CompareWith(const Integer& other) const;
// Converts integer to hex string.
- // TODO(alexmarkov): this method can become non-virtual once Bigint class is
- // decoupled from Integer hierarchy.
- virtual const char* ToHexCString(Zone* zone) const;
+ const char* ToHexCString(Zone* zone) const;
// Return the most compact presentation of an integer.
RawInteger* AsValidInteger() const;
@@ -6967,107 +6976,6 @@
friend class Number;
};
-class Bigint : public Integer {
- public:
- virtual bool IsZero() const { return Used() == 0; }
- virtual bool IsNegative() const { return Neg(); }
- virtual bool Equals(const Instance& other) const;
-
- virtual double AsDoubleValue() const;
- virtual int64_t AsInt64Value() const;
- virtual int64_t AsTruncatedInt64Value() const;
- virtual uint32_t AsTruncatedUint32Value() const;
-
- virtual int CompareWith(const Integer& other) const;
-
- virtual const char* ToHexCString(Zone* zone) const;
-
- virtual bool CheckAndCanonicalizeFields(Thread* thread,
- const char** error_str) const;
-
- virtual bool FitsIntoSmi() const;
- bool FitsIntoInt64() const;
- bool FitsIntoUint64() const;
- uint64_t AsUint64Value() const;
-
- static intptr_t InstanceSize() {
- return RoundedAllocationSize(sizeof(RawBigint));
- }
-
- // Offsets of fields accessed directly by optimized code.
- static intptr_t neg_offset() { return OFFSET_OF(RawBigint, neg_); }
- static intptr_t used_offset() { return OFFSET_OF(RawBigint, used_); }
- static intptr_t digits_offset() { return OFFSET_OF(RawBigint, digits_); }
-
- // Accessors used by native calls from Dart.
- RawBool* neg() const { return raw_ptr()->neg_; }
- RawSmi* used() const { return raw_ptr()->used_; }
- RawTypedData* digits() const { return raw_ptr()->digits_; }
-
- // Accessors used by runtime calls from C++.
- bool Neg() const;
- intptr_t Used() const;
- uint32_t DigitAt(intptr_t index) const;
-
- const char* ToDecCString(Zone* zone) const;
-
- static const intptr_t kBitsPerDigit = 32; // Same as _Bigint._DIGIT_BITS
- static const intptr_t kBytesPerDigit = 4;
- static const int64_t kDigitBase = 1LL << kBitsPerDigit;
- static const int64_t kDigitMask = kDigitBase - 1;
-
- static RawBigint* New(Heap::Space space = Heap::kNew); // For snapshots.
-
- static RawBigint* New(bool neg,
- intptr_t used,
- const TypedData& digits,
- Heap::Space space = Heap::kNew);
-
- static RawBigint* NewFromInt64(int64_t value, Heap::Space space = Heap::kNew);
-
- static RawBigint* NewFromUint64(uint64_t value,
- Heap::Space space = Heap::kNew);
-
- static RawBigint* NewFromShiftedInt64(int64_t value,
- intptr_t shift,
- Heap::Space space = Heap::kNew);
-
- static RawBigint* NewFromCString(const char* str,
- Heap::Space space = Heap::kNew);
-
- // Returns a canonical Bigint object allocated in the old gen space.
- static RawBigint* NewCanonical(const String& str);
-
- // Returns true if Bigint can't be instantiated.
- static bool IsDisabled() { return FLAG_limit_ints_to_64_bits; }
-
- private:
- void SetNeg(bool value) const;
- void SetUsed(intptr_t value) const;
- void set_digits(const TypedData& value) const;
-
- // Convenience helpers.
- static RawTypedData* NewDigits(intptr_t length,
- Heap::Space space = Heap::kNew);
- static uint32_t DigitAt(const TypedData& digits, intptr_t index);
- static void SetDigitAt(const TypedData& digits,
- intptr_t index,
- uint32_t value);
-
- static RawTypedData* NewDigitsFromHexCString(const char* str,
- intptr_t* used,
- Heap::Space space = Heap::kNew);
-
- static RawTypedData* NewDigitsFromDecCString(const char* str,
- intptr_t* used,
- Heap::Space space = Heap::kNew);
-
- static RawBigint* Allocate(intptr_t length, Heap::Space space = Heap::kNew);
-
- FINAL_HEAP_OBJECT_IMPLEMENTATION(Bigint, Integer);
- friend class Class;
-};
-
// Class Double represents class Double in corelib_impl, which implements
// abstract class double in corelib.
class Double : public Number {
@@ -7303,7 +7211,8 @@
static RawString* NewExternal(const uint8_t* utf8_array,
intptr_t array_len,
void* peer,
- Dart_PeerFinalizer callback,
+ intptr_t external_allocation_size,
+ Dart_WeakPersistentHandleFinalizer callback,
Heap::Space = Heap::kNew);
// Creates a new External String object using the specified array of
@@ -7311,7 +7220,8 @@
static RawString* NewExternal(const uint16_t* utf16_array,
intptr_t array_len,
void* peer,
- Dart_PeerFinalizer callback,
+ intptr_t external_allocation_size,
+ Dart_WeakPersistentHandleFinalizer callback,
Heap::Space = Heap::kNew);
static void Copy(const String& dst,
@@ -7537,13 +7447,9 @@
Heap::Space space);
static void SetPeer(const String& str,
- intptr_t external_size,
void* peer,
- Dart_PeerFinalizer cback);
-
- static void Finalize(void* isolate_callback_data,
- Dart_WeakPersistentHandle handle,
- void* peer);
+ intptr_t external_allocation_size,
+ Dart_WeakPersistentHandleFinalizer callback);
static const ClassId kClassId = kOneByteStringCid;
@@ -7664,13 +7570,9 @@
Heap::Space space);
static void SetPeer(const String& str,
- intptr_t external_size,
void* peer,
- Dart_PeerFinalizer cback);
-
- static void Finalize(void* isolate_callback_data,
- Dart_WeakPersistentHandle handle,
- void* peer);
+ intptr_t external_allocation_size,
+ Dart_WeakPersistentHandleFinalizer callback);
static RawTwoByteString* null() {
return reinterpret_cast<RawTwoByteString*>(Object::null());
@@ -7719,9 +7621,7 @@
return *CharAddr(str, index);
}
- static void* GetPeer(const String& str) {
- return raw_ptr(str)->external_data_->peer();
- }
+ static void* GetPeer(const String& str) { return raw_ptr(str)->peer_; }
static intptr_t external_data_offset() {
return OFFSET_OF(RawExternalOneByteString, external_data_);
@@ -7735,11 +7635,13 @@
return String::RoundedAllocationSize(sizeof(RawExternalOneByteString));
}
- static RawExternalOneByteString* New(const uint8_t* characters,
- intptr_t len,
- void* peer,
- Dart_PeerFinalizer callback,
- Heap::Space space);
+ static RawExternalOneByteString* New(
+ const uint8_t* characters,
+ intptr_t len,
+ void* peer,
+ intptr_t external_allocation_size,
+ Dart_WeakPersistentHandleFinalizer callback,
+ Heap::Space space);
static RawExternalOneByteString* null() {
return reinterpret_cast<RawExternalOneByteString*>(Object::null());
@@ -7763,20 +7665,22 @@
static const uint8_t* CharAddr(const String& str, intptr_t index) {
ASSERT((index >= 0) && (index < str.Length()));
ASSERT(str.IsExternalOneByteString());
- return &(raw_ptr(str)->external_data_->data()[index]);
+ return &(raw_ptr(str)->external_data_[index]);
}
static const uint8_t* DataStart(const String& str) {
ASSERT(str.IsExternalOneByteString());
- return &(raw_ptr(str)->external_data_->data()[0]);
+ return raw_ptr(str)->external_data_;
}
static void SetExternalData(const String& str,
- ExternalStringData<uint8_t>* data) {
+ const uint8_t* data,
+ void* peer) {
ASSERT(str.IsExternalOneByteString());
- ASSERT(!Isolate::Current()->heap()->Contains(
- reinterpret_cast<uword>(data->data())));
+ ASSERT(
+ !Isolate::Current()->heap()->Contains(reinterpret_cast<uword>(data)));
str.StoreNonPointer(&raw_ptr(str)->external_data_, data);
+ str.StoreNonPointer(&raw_ptr(str)->peer_, peer);
}
static void Finalize(void* isolate_callback_data,
@@ -7808,9 +7712,7 @@
return *CharAddr(str, index);
}
- static void* GetPeer(const String& str) {
- return raw_ptr(str)->external_data_->peer();
- }
+ static void* GetPeer(const String& str) { return raw_ptr(str)->peer_; }
static intptr_t external_data_offset() {
return OFFSET_OF(RawExternalTwoByteString, external_data_);
@@ -7824,11 +7726,13 @@
return String::RoundedAllocationSize(sizeof(RawExternalTwoByteString));
}
- static RawExternalTwoByteString* New(const uint16_t* characters,
- intptr_t len,
- void* peer,
- Dart_PeerFinalizer callback,
- Heap::Space space = Heap::kNew);
+ static RawExternalTwoByteString* New(
+ const uint16_t* characters,
+ intptr_t len,
+ void* peer,
+ intptr_t external_allocation_size,
+ Dart_WeakPersistentHandleFinalizer callback,
+ Heap::Space space = Heap::kNew);
static RawExternalTwoByteString* null() {
return reinterpret_cast<RawExternalTwoByteString*>(Object::null());
@@ -7848,20 +7752,22 @@
static const uint16_t* CharAddr(const String& str, intptr_t index) {
ASSERT((index >= 0) && (index < str.Length()));
ASSERT(str.IsExternalTwoByteString());
- return &(raw_ptr(str)->external_data_->data()[index]);
+ return &(raw_ptr(str)->external_data_[index]);
}
static const uint16_t* DataStart(const String& str) {
ASSERT(str.IsExternalTwoByteString());
- return &(raw_ptr(str)->external_data_->data()[0]);
+ return raw_ptr(str)->external_data_;
}
static void SetExternalData(const String& str,
- ExternalStringData<uint16_t>* data) {
+ const uint16_t* data,
+ void* peer) {
ASSERT(str.IsExternalTwoByteString());
- ASSERT(!Isolate::Current()->heap()->Contains(
- reinterpret_cast<uword>(data->data())));
+ ASSERT(
+ !Isolate::Current()->heap()->Contains(reinterpret_cast<uword>(data)));
str.StoreNonPointer(&raw_ptr(str)->external_data_, data);
+ str.StoreNonPointer(&raw_ptr(str)->peer_, peer);
}
static void Finalize(void* isolate_callback_data,
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index aa21aa8..89661ef 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -1179,10 +1179,6 @@
jsobj.AddProperty("valueAsString", ToCString());
}
-void Bigint::PrintJSONImpl(JSONStream* stream, bool ref) const {
- Integer::PrintJSONImpl(stream, ref);
-}
-
void String::PrintJSONImpl(JSONStream* stream, bool ref) const {
JSONObject jsobj(stream);
if (raw() == Symbols::OptimizedOut().raw()) {
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 5c9e90f..74f3dfb 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -46,7 +46,6 @@
RW(Type, smi_type) \
RW(Class, mint_class) \
RW(Type, mint_type) \
- RW(Class, bigint_class) \
RW(Class, double_class) \
RW(Type, double_type) \
RW(Type, float32x4_type) \
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 0fc1385..ed8d624 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -338,17 +338,6 @@
EXPECT_EQ(1, a.CompareWith(mint2));
EXPECT_EQ(-1, c.CompareWith(mint1));
EXPECT_EQ(1, c.CompareWith(mint2));
-
- if (!Bigint::IsDisabled()) {
- Bigint& big1 =
- Bigint::Handle(Bigint::NewFromCString("10000000000000000000"));
- Bigint& big2 =
- Bigint::Handle(Bigint::NewFromCString("-10000000000000000000"));
- EXPECT_EQ(-1, a.CompareWith(big1));
- EXPECT_EQ(1, a.CompareWith(big2));
- EXPECT_EQ(-1, c.CompareWith(big1));
- EXPECT_EQ(1, c.CompareWith(big2));
- }
}
ISOLATE_UNIT_TEST_CASE(StringCompareTo) {
@@ -497,17 +486,6 @@
EXPECT_EQ(-1, c.CompareWith(smi1));
EXPECT_EQ(-1, c.CompareWith(smi2));
- if (!Bigint::IsDisabled()) {
- Bigint& big1 =
- Bigint::Handle(Bigint::NewFromCString("10000000000000000000"));
- Bigint& big2 =
- Bigint::Handle(Bigint::NewFromCString("-10000000000000000000"));
- EXPECT_EQ(-1, a.CompareWith(big1));
- EXPECT_EQ(1, a.CompareWith(big2));
- EXPECT_EQ(-1, c.CompareWith(big1));
- EXPECT_EQ(1, c.CompareWith(big2));
- }
-
int64_t mint_value = DART_2PART_UINT64_C(0x7FFFFFFF, 64);
const String& mint_string = String::Handle(String::New("0x7FFFFFFF00000064"));
Mint& mint1 = Mint::Handle();
@@ -603,48 +581,6 @@
}
}
-ISOLATE_UNIT_TEST_CASE(Bigint) {
- if (Bigint::IsDisabled()) {
- return;
- }
-
- Bigint& b = Bigint::Handle();
- EXPECT(b.IsNull());
- const char* cstr = "18446744073709551615000";
- const String& test = String::Handle(String::New(cstr));
- b ^= Integer::NewCanonical(test);
- const char* str = b.ToCString();
- EXPECT_STREQ(cstr, str);
-
- int64_t t64 = DART_2PART_UINT64_C(1, 0);
- Bigint& big = Bigint::Handle(Bigint::NewFromInt64(t64));
- EXPECT_EQ(t64, big.AsInt64Value());
- big = Bigint::NewFromCString("10000000000000000000");
- EXPECT_EQ(1e19, big.AsDoubleValue());
-
- Bigint& big1 =
- Bigint::Handle(Bigint::NewFromCString("100000000000000000000"));
- Bigint& big2 =
- Bigint::Handle(Bigint::NewFromCString("100000000000000000010"));
- Bigint& big3 =
- Bigint::Handle(Bigint::NewFromCString("-10000000000000000000"));
-
- EXPECT_EQ(0, big1.CompareWith(big1));
- EXPECT_EQ(-1, big1.CompareWith(big2));
- EXPECT_EQ(1, big2.CompareWith(big1));
- EXPECT_EQ(1, big1.CompareWith(big3));
- EXPECT_EQ(-1, big3.CompareWith(big1));
-
- Smi& smi1 = Smi::Handle(Smi::New(5));
- Smi& smi2 = Smi::Handle(Smi::New(-2));
-
- EXPECT_EQ(-1, smi1.CompareWith(big1));
- EXPECT_EQ(-1, smi2.CompareWith(big1));
-
- EXPECT_EQ(1, smi1.CompareWith(big3));
- EXPECT_EQ(1, smi2.CompareWith(big3));
-}
-
ISOLATE_UNIT_TEST_CASE(Integer) {
Integer& i = Integer::Handle();
i = Integer::NewCanonical(String::Handle(String::New("12")));
@@ -655,10 +591,10 @@
EXPECT(i.IsSmi());
i = Integer::NewCanonical(
String::Handle(String::New("12345678901234567890")));
- EXPECT(FLAG_limit_ints_to_64_bits ? i.IsNull() : i.IsBigint());
+ EXPECT(i.IsNull());
i = Integer::NewCanonical(
String::Handle(String::New("-12345678901234567890111222")));
- EXPECT(FLAG_limit_ints_to_64_bits ? i.IsNull() : i.IsBigint());
+ EXPECT(i.IsNull());
}
ISOLATE_UNIT_TEST_CASE(String) {
@@ -1630,12 +1566,16 @@
EXPECT(!th_str.Equals(chars, 3));
}
+static void NoopFinalizer(void* isolate_callback_data,
+ Dart_WeakPersistentHandle handle,
+ void* peer) {}
+
ISOLATE_UNIT_TEST_CASE(ExternalOneByteString) {
uint8_t characters[] = {0xF6, 0xF1, 0xE9};
intptr_t len = ARRAY_SIZE(characters);
- const String& str = String::Handle(
- ExternalOneByteString::New(characters, len, NULL, NULL, Heap::kNew));
+ const String& str = String::Handle(ExternalOneByteString::New(
+ characters, len, NULL, 0, NoopFinalizer, Heap::kNew));
EXPECT(!str.IsOneByteString());
EXPECT(str.IsExternalOneByteString());
EXPECT_EQ(str.Length(), len);
@@ -1684,8 +1624,8 @@
'\v', '\r', '\\', '$', 'z'};
intptr_t len = ARRAY_SIZE(characters);
- const String& str = String::Handle(
- ExternalOneByteString::New(characters, len, NULL, NULL, Heap::kNew));
+ const String& str = String::Handle(ExternalOneByteString::New(
+ characters, len, NULL, 0, NoopFinalizer, Heap::kNew));
EXPECT(!str.IsOneByteString());
EXPECT(str.IsExternalOneByteString());
EXPECT_EQ(str.Length(), len);
@@ -1694,8 +1634,8 @@
String::Handle(String::EscapeSpecialCharacters(str));
EXPECT(escaped_str.Equals("a\\n\\f\\b\\t\\v\\r\\\\\\$z"));
- const String& empty_str = String::Handle(
- ExternalOneByteString::New(characters, 0, NULL, NULL, Heap::kNew));
+ const String& empty_str = String::Handle(ExternalOneByteString::New(
+ characters, 0, NULL, 0, NoopFinalizer, Heap::kNew));
const String& escaped_empty_str =
String::Handle(String::EscapeSpecialCharacters(empty_str));
EXPECT_EQ(empty_str.Length(), 0);
@@ -1729,8 +1669,8 @@
'\v', '\r', '\\', '$', 'z'};
intptr_t len = ARRAY_SIZE(characters);
- const String& str = String::Handle(
- ExternalTwoByteString::New(characters, len, NULL, NULL, Heap::kNew));
+ const String& str = String::Handle(ExternalTwoByteString::New(
+ characters, len, NULL, 0, NoopFinalizer, Heap::kNew));
EXPECT(str.IsExternalTwoByteString());
EXPECT_EQ(str.Length(), len);
EXPECT(str.Equals("a\n\f\b\t\v\r\\$z"));
@@ -1738,8 +1678,8 @@
String::Handle(String::EscapeSpecialCharacters(str));
EXPECT(escaped_str.Equals("a\\n\\f\\b\\t\\v\\r\\\\\\$z"));
- const String& empty_str = String::Handle(
- ExternalTwoByteString::New(characters, 0, NULL, NULL, Heap::kNew));
+ const String& empty_str = String::Handle(ExternalTwoByteString::New(
+ characters, 0, NULL, 0, NoopFinalizer, Heap::kNew));
const String& escaped_empty_str =
String::Handle(String::EscapeSpecialCharacters(empty_str));
EXPECT_EQ(empty_str.Length(), 0);
@@ -1750,8 +1690,8 @@
uint16_t characters[] = {0x1E6B, 0x1E85, 0x1E53};
intptr_t len = ARRAY_SIZE(characters);
- const String& str = String::Handle(
- ExternalTwoByteString::New(characters, len, NULL, NULL, Heap::kNew));
+ const String& str = String::Handle(ExternalTwoByteString::New(
+ characters, len, NULL, 0, NoopFinalizer, Heap::kNew));
EXPECT(!str.IsTwoByteString());
EXPECT(str.IsExternalTwoByteString());
EXPECT_EQ(str.Length(), len);
@@ -2537,16 +2477,17 @@
EXPECT_EQ(4, local_scope->num_variables()); // ta, a, b, c.
EXPECT_EQ(3, local_scope->NumCapturedVariables()); // ta, a, c.
- const int first_parameter_index = 0;
+ const VariableIndex first_parameter_index(0);
const int num_parameters = 0;
- const int first_frame_index = -1;
+ const VariableIndex first_local_index(-1);
bool found_captured_vars = false;
- int next_frame_index = parent_scope->AllocateVariables(
- first_parameter_index, num_parameters, first_frame_index, NULL,
+ VariableIndex next_index = parent_scope->AllocateVariables(
+ first_parameter_index, num_parameters, first_local_index, NULL,
&found_captured_vars);
// Variables a, c and var_ta are captured, therefore are not allocated in
// frame.
- EXPECT_EQ(0, next_frame_index - first_frame_index); // Indices in frame < 0.
+ EXPECT_EQ(0, next_index.value() -
+ first_local_index.value()); // Indices in frame < 0.
const intptr_t parent_scope_context_level = 1;
EXPECT_EQ(parent_scope_context_level, parent_scope->context_level());
EXPECT(found_captured_vars);
@@ -2559,13 +2500,13 @@
var_ta = outer_scope->LocalLookupVariable(ta);
EXPECT(var_ta->is_captured());
- EXPECT_EQ(0, var_ta->index()); // First index.
+ EXPECT_EQ(0, var_ta->index().value()); // First index.
EXPECT_EQ(parent_scope_context_level - local_scope_context_level,
var_ta->owner()->context_level()); // Adjusted context level.
var_a = outer_scope->LocalLookupVariable(a);
EXPECT(var_a->is_captured());
- EXPECT_EQ(1, var_a->index()); // First index.
+ EXPECT_EQ(1, var_a->index().value()); // First index.
EXPECT_EQ(parent_scope_context_level - local_scope_context_level,
var_a->owner()->context_level()); // Adjusted context level.
@@ -2574,7 +2515,7 @@
var_c = outer_scope->LocalLookupVariable(c);
EXPECT(var_c->is_captured());
- EXPECT_EQ(2, var_c->index());
+ EXPECT_EQ(2, var_c->index().value());
EXPECT_EQ(parent_scope_context_level - local_scope_context_level,
var_c->owner()->context_level()); // Adjusted context level.
}
@@ -3219,15 +3160,15 @@
mangled_name = OneByteString::New("foo@12345.name@12345");
ext_mangled_name = ExternalOneByteString::New(
reinterpret_cast<const uint8_t*>(ext_mangled_str),
- strlen(ext_mangled_str), NULL, NULL, Heap::kNew);
+ strlen(ext_mangled_str), NULL, 0, NoopFinalizer, Heap::kNew);
EXPECT(ext_mangled_name.IsExternalOneByteString());
- ext_bare_name =
- ExternalOneByteString::New(reinterpret_cast<const uint8_t*>(ext_bare_str),
- strlen(ext_bare_str), NULL, NULL, Heap::kNew);
+ ext_bare_name = ExternalOneByteString::New(
+ reinterpret_cast<const uint8_t*>(ext_bare_str), strlen(ext_bare_str),
+ NULL, 0, NoopFinalizer, Heap::kNew);
EXPECT(ext_bare_name.IsExternalOneByteString());
ext_bad_bare_name = ExternalOneByteString::New(
reinterpret_cast<const uint8_t*>(ext_bad_bare_str),
- strlen(ext_bad_bare_str), NULL, NULL, Heap::kNew);
+ strlen(ext_bad_bare_str), NULL, 0, NoopFinalizer, Heap::kNew);
EXPECT(ext_bad_bare_name.IsExternalOneByteString());
// str1 - OneByteString, str2 - ExternalOneByteString.
@@ -4186,25 +4127,6 @@
"\"id\":\"\",\"valueAsString\":\"-9223372036854775808\"}",
buffer);
}
- // Bigint reference
- if (!Bigint::IsDisabled()) {
- JSONStream js;
- const String& bigint_str =
- String::Handle(String::New("44444444444444444444444444444444"));
- const Integer& bigint = Integer::Handle(Integer::New(bigint_str));
- bigint.PrintJSON(&js, true);
- ElideJSONSubstring("classes", js.ToCString(), buffer);
- ElideJSONSubstring("objects", buffer, buffer);
- ElideJSONSubstring("_Bigint@", buffer, buffer);
- EXPECT_STREQ(
- "{\"type\":\"@Instance\","
- "\"_vmType\":\"Bigint\","
- "\"class\":{\"type\":\"@Class\",\"fixedId\":true,\"id\":\"\","
- "\"name\":\"_Bigint\",\"_vmName\":\"\"},"
- "\"kind\":\"Int\","
- "\"id\":\"\",\"valueAsString\":\"44444444444444444444444444444444\"}",
- buffer);
- }
// Double reference
{
JSONStream js;
@@ -4576,8 +4498,8 @@
uint8_t characters[] = {0xF6, 0xF1, 0xE9};
intptr_t len = ARRAY_SIZE(characters);
- const String& str = String::Handle(
- ExternalOneByteString::New(characters, len, NULL, NULL, Heap::kNew));
+ const String& str = String::Handle(ExternalOneByteString::New(
+ characters, len, NULL, 0, NoopFinalizer, Heap::kNew));
const String* data[3] = {&str, &Symbols::Dot(), &str};
CheckConcatAll(data, 3);
}
@@ -4587,8 +4509,8 @@
'\v', '\r', '\\', '$', 'z'};
intptr_t len = ARRAY_SIZE(characters);
- const String& str = String::Handle(
- ExternalTwoByteString::New(characters, len, NULL, NULL, Heap::kNew));
+ const String& str = String::Handle(ExternalTwoByteString::New(
+ characters, len, NULL, 0, NoopFinalizer, Heap::kNew));
const String* data[3] = {&str, &Symbols::Dot(), &str};
CheckConcatAll(data, 3);
}
@@ -4597,15 +4519,15 @@
uint8_t characters1[] = {0xF6, 0xF1, 0xE9};
intptr_t len1 = ARRAY_SIZE(characters1);
- const String& str1 = String::Handle(
- ExternalOneByteString::New(characters1, len1, NULL, NULL, Heap::kNew));
+ const String& str1 = String::Handle(ExternalOneByteString::New(
+ characters1, len1, NULL, 0, NoopFinalizer, Heap::kNew));
uint16_t characters2[] = {'a', '\n', '\f', '\b', '\t',
'\v', '\r', '\\', '$', 'z'};
intptr_t len2 = ARRAY_SIZE(characters2);
- const String& str2 = String::Handle(
- ExternalTwoByteString::New(characters2, len2, NULL, NULL, Heap::kNew));
+ const String& str2 = String::Handle(ExternalTwoByteString::New(
+ characters2, len2, NULL, 0, NoopFinalizer, Heap::kNew));
const String* data[3] = {&str1, &Symbols::Dot(), &str2};
CheckConcatAll(data, 3);
}
diff --git a/runtime/vm/os_android.cc b/runtime/vm/os_android.cc
index 4481f19..a8ec5a9 100644
--- a/runtime/vm/os_android.cc
+++ b/runtime/vm/os_android.cc
@@ -329,7 +329,7 @@
base = 16;
}
errno = 0;
- if (FLAG_limit_ints_to_64_bits && (base == 16)) {
+ if (base == 16) {
// Unsigned 64-bit hexadecimal integer literals are allowed but
// immediately interpreted as signed 64-bit integers.
*value = static_cast<int64_t>(strtoull(str, &endptr, base));
diff --git a/runtime/vm/os_fuchsia.cc b/runtime/vm/os_fuchsia.cc
index 6284307..605e2dd 100644
--- a/runtime/vm/os_fuchsia.cc
+++ b/runtime/vm/os_fuchsia.cc
@@ -8,7 +8,7 @@
#include "vm/os.h"
#include <errno.h>
-#include <fdio/util.h>
+#include <lib/fdio/util.h>
#include <zircon/process.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/object.h>
@@ -221,7 +221,7 @@
base = 16;
}
errno = 0;
- if (FLAG_limit_ints_to_64_bits && (base == 16)) {
+ if (base == 16) {
// Unsigned 64-bit hexadecimal integer literals are allowed but
// immediately interpreted as signed 64-bit integers.
*value = static_cast<int64_t>(strtoull(str, &endptr, base));
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index a73de36..8a9c69e 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -523,7 +523,7 @@
base = 16;
}
errno = 0;
- if (FLAG_limit_ints_to_64_bits && (base == 16)) {
+ if (base == 16) {
// Unsigned 64-bit hexadecimal integer literals are allowed but
// immediately interpreted as signed 64-bit integers.
*value = static_cast<int64_t>(strtoull(str, &endptr, base));
diff --git a/runtime/vm/os_macos.cc b/runtime/vm/os_macos.cc
index 8c5e2c9..e423c7a 100644
--- a/runtime/vm/os_macos.cc
+++ b/runtime/vm/os_macos.cc
@@ -276,7 +276,7 @@
base = 16;
}
errno = 0;
- if (FLAG_limit_ints_to_64_bits && (base == 16)) {
+ if (base == 16) {
// Unsigned 64-bit hexadecimal integer literals are allowed but
// immediately interpreted as signed 64-bit integers.
*value = static_cast<int64_t>(strtoull(str, &endptr, base));
diff --git a/runtime/vm/os_win.cc b/runtime/vm/os_win.cc
index d8a0a9a..c9a102b 100644
--- a/runtime/vm/os_win.cc
+++ b/runtime/vm/os_win.cc
@@ -293,7 +293,7 @@
base = 16;
}
errno = 0;
- if (FLAG_limit_ints_to_64_bits && (base == 16)) {
+ if (base == 16) {
// Unsigned 64-bit hexadecimal integer literals are allowed but
// immediately interpreted as signed 64-bit integers.
*value = static_cast<int64_t>(_strtoui64(str, &endptr, base));
diff --git a/runtime/vm/pages.cc b/runtime/vm/pages.cc
index df7e04a..2beff46 100644
--- a/runtime/vm/pages.cc
+++ b/runtime/vm/pages.cc
@@ -12,6 +12,7 @@
#include "vm/gc_marker.h"
#include "vm/gc_sweeper.h"
#include "vm/lockers.h"
+#include "vm/log.h"
#include "vm/object.h"
#include "vm/object_set.h"
#include "vm/os_thread.h"
@@ -165,9 +166,7 @@
// based on the device's actual speed.
static const intptr_t kConservativeInitialMarkSpeed = 20;
-PageSpace::PageSpace(Heap* heap,
- intptr_t max_capacity_in_words,
- intptr_t max_external_in_words)
+PageSpace::PageSpace(Heap* heap, intptr_t max_capacity_in_words)
: freelist_(),
heap_(heap),
pages_lock_(new Mutex()),
@@ -180,7 +179,6 @@
bump_top_(0),
bump_end_(0),
max_capacity_in_words_(max_capacity_in_words),
- max_external_in_words_(max_external_in_words),
tasks_lock_(new Monitor()),
tasks_(0),
#if defined(DEBUG)
@@ -445,7 +443,6 @@
AtomicOperations::IncrementBy(&(usage_.external_in_words), size_in_words);
NOT_IN_PRODUCT(
heap_->isolate()->class_table()->UpdateAllocatedExternalOld(cid, size));
- // TODO(koda): Control growth.
}
void PageSpace::FreeExternal(intptr_t size) {
@@ -1233,13 +1230,19 @@
int garbage_collection_time_ratio)
: heap_(heap),
is_enabled_(false),
- grow_heap_(heap_growth_max / 2),
heap_growth_ratio_(heap_growth_ratio),
desired_utilization_((100.0 - heap_growth_ratio) / 100.0),
heap_growth_max_(heap_growth_max),
garbage_collection_time_ratio_(garbage_collection_time_ratio),
last_code_collection_in_us_(OS::GetCurrentMonotonicMicros()),
- idle_gc_threshold_in_words_(0) {}
+ idle_gc_threshold_in_words_(0) {
+ intptr_t grow_heap = heap_growth_max / 2;
+ gc_threshold_in_words_ =
+ last_usage_.capacity_in_words + (kPageSizeInWords * grow_heap);
+ intptr_t grow_external = heap_growth_max / 2;
+ gc_external_threshold_in_words_ =
+ last_usage_.external_in_words + (kPageSizeInWords * grow_external);
+}
PageSpaceController::~PageSpaceController() {}
@@ -1250,22 +1253,12 @@
if (heap_growth_ratio_ == 100) {
return false;
}
- intptr_t capacity_increase_in_words =
- after.capacity_in_words - last_usage_.capacity_in_words;
- // The concurrent sweeper might have freed more capacity than was allocated.
- capacity_increase_in_words =
- Utils::Maximum<intptr_t>(0, capacity_increase_in_words);
- capacity_increase_in_words =
- Utils::RoundUp(capacity_increase_in_words, kPageSizeInWords);
- intptr_t capacity_increase_in_pages =
- capacity_increase_in_words / kPageSizeInWords;
- bool needs_gc = capacity_increase_in_pages > grow_heap_;
- if (FLAG_log_growth) {
- OS::PrintErr("%s: allocate %s %" Pd " %s %" Pd "\n",
- heap_->isolate()->name(), needs_gc ? "collect" : "grow",
- capacity_increase_in_pages, needs_gc ? ">" : "<=", grow_heap_);
- }
- return needs_gc;
+ return (after.capacity_in_words > gc_threshold_in_words_) ||
+ NeedsExternalCollection(after);
+}
+
+bool PageSpaceController::NeedsExternalCollection(SpaceUsage after) const {
+ return after.external_in_words > gc_external_threshold_in_words_;
}
bool PageSpaceController::NeedsIdleGarbageCollection(SpaceUsage current) const {
@@ -1275,13 +1268,7 @@
if (heap_growth_ratio_ == 100) {
return false;
}
- bool needs_gc = current.used_in_words > idle_gc_threshold_in_words_;
- if (FLAG_log_growth) {
- OS::PrintErr("%s: idle %s %" Pd " %s %" Pd "\n", heap_->isolate()->name(),
- needs_gc ? "collect" : "grow", current.used_in_words,
- needs_gc ? ">" : "<=", idle_gc_threshold_in_words_);
- }
- return needs_gc;
+ return current.capacity_in_words > idle_gc_threshold_in_words_;
}
void PageSpaceController::EvaluateGarbageCollection(SpaceUsage before,
@@ -1293,10 +1280,32 @@
const int gc_time_fraction = history_.GarbageCollectionTimeFraction();
heap_->RecordData(PageSpace::kGCTimeFraction, gc_time_fraction);
+ // Decide how much external allocations can grow before triggering a GC.
+ {
+ const intptr_t external_after_in_pages =
+ Utils::RoundUp(after.external_in_words, kPageSizeInWords) /
+ kPageSizeInWords;
+ const intptr_t external_growth_in_pages =
+ Utils::RoundUp(before.external_in_words - last_usage_.external_in_words,
+ kPageSizeInWords) /
+ kPageSizeInWords;
+ // Trigger GC when external allocations grow:
+ // - 25% of the external allocations after this GC, or
+ // - half of the growth since the last collection
+ // whichever is bigger. The second case prevents shrinking the limit too
+ // much. See similar handling of the Dart heap below.
+ intptr_t grow_external = Utils::Maximum<intptr_t>(
+ external_after_in_pages >> 2, external_growth_in_pages >> 1);
+
+ gc_external_threshold_in_words_ =
+ after.external_in_words + (kPageSizeInWords * grow_external);
+ }
+
// Assume garbage increases linearly with allocation:
// G = kA, and estimate k from the previous cycle.
const intptr_t allocated_since_previous_gc =
before.used_in_words - last_usage_.used_in_words;
+ intptr_t grow_heap;
if (allocated_since_previous_gc > 0) {
const intptr_t garbage = before.used_in_words - after.used_in_words;
ASSERT(garbage >= 0);
@@ -1323,13 +1332,13 @@
kPageSizeInWords;
if (garbage_ratio == 0) {
// No garbage in the previous cycle so it would be hard to compute a
- // grow_heap_ size based on estimated garbage so we use growth ratio
+ // grow_heap size based on estimated garbage so we use growth ratio
// heuristics instead.
- grow_heap_ =
+ grow_heap =
Utils::Maximum(static_cast<intptr_t>(heap_growth_max_), grow_pages);
} else {
- // Find minimum 'grow_heap_' such that after increasing capacity by
- // 'grow_heap_' pages and filling them, we expect a GC to be worthwhile.
+ // Find minimum 'grow_heap' such that after increasing capacity by
+ // 'grow_heap' pages and filling them, we expect a GC to be worthwhile.
intptr_t max = heap_growth_max_;
intptr_t min = 0;
intptr_t local_grow_heap = 0;
@@ -1346,33 +1355,43 @@
}
}
local_grow_heap = (max + min) / 2;
- grow_heap_ = local_grow_heap;
- ASSERT(grow_heap_ >= 0);
+ grow_heap = local_grow_heap;
+ ASSERT(grow_heap >= 0);
// If we are going to grow by heap_grow_max_ then ensure that we
// will be growing the heap at least by the growth ratio heuristics.
- if (grow_heap_ >= heap_growth_max_) {
- grow_heap_ = Utils::Maximum(grow_pages, grow_heap_);
+ if (grow_heap >= heap_growth_max_) {
+ grow_heap = Utils::Maximum(grow_pages, grow_heap);
}
}
} else {
heap_->RecordData(PageSpace::kGarbageRatio, 100);
- grow_heap_ = 0;
+ grow_heap = 0;
}
- heap_->RecordData(PageSpace::kPageGrowth, grow_heap_);
+ heap_->RecordData(PageSpace::kPageGrowth, grow_heap);
// Limit shrinkage: allow growth by at least half the pages freed by GC.
const intptr_t freed_pages =
(before.capacity_in_words - after.capacity_in_words) / kPageSizeInWords;
- grow_heap_ = Utils::Maximum(grow_heap_, freed_pages / 2);
- heap_->RecordData(PageSpace::kAllowedGrowth, grow_heap_);
+ grow_heap = Utils::Maximum(grow_heap, freed_pages / 2);
+ heap_->RecordData(PageSpace::kAllowedGrowth, grow_heap);
last_usage_ = after;
- // Set the idle threshold halfway between the current size and the capacity
- // at which we'd block for a GC.
- intptr_t gc_threshold_in_words =
- after.capacity_in_words + (kPageSizeInWords * grow_heap_);
+ // Save final threshold compared before growing.
+ gc_threshold_in_words_ =
+ after.capacity_in_words + (kPageSizeInWords * grow_heap);
+
+ // Set the idle threshold halfway between the current capacity and the
+ // capacity at which we'd block for a GC.
idle_gc_threshold_in_words_ =
- (after.used_in_words + gc_threshold_in_words) / 2;
+ (after.capacity_in_words + gc_threshold_in_words_) / 2;
+
+ if (FLAG_log_growth) {
+ THR_Print("%s: threshold=%" Pd "kB, idle_threshold=%" Pd
+ "kB, external_threshold=%" Pd "kB\n",
+ heap_->isolate()->name(), gc_threshold_in_words_ / KBInWords,
+ idle_gc_threshold_in_words_ / KBInWords,
+ gc_external_threshold_in_words_ / KBInWords);
+ }
}
void PageSpaceGarbageCollectionHistory::AddGarbageCollectionTime(int64_t start,
diff --git a/runtime/vm/pages.h b/runtime/vm/pages.h
index 06fbf27..b0dfc7a 100644
--- a/runtime/vm/pages.h
+++ b/runtime/vm/pages.h
@@ -151,6 +151,8 @@
// (e.g., promotion), as it does not change the state of the controller.
bool NeedsGarbageCollection(SpaceUsage after) const;
+ bool NeedsExternalCollection(SpaceUsage after) const;
+
// Returns whether an idle GC is worthwhile.
bool NeedsIdleGarbageCollection(SpaceUsage current) const;
@@ -179,29 +181,32 @@
// Usage after last evaluated GC or last enabled.
SpaceUsage last_usage_;
- // Pages of capacity growth allowed before next GC is advised.
- intptr_t grow_heap_;
-
// If the garbage collector was not able to free more than heap_growth_ratio_
// memory, then the heap is grown. Otherwise garbage collection is performed.
- int heap_growth_ratio_;
+ const int heap_growth_ratio_;
// The desired percent of heap in-use after a garbage collection.
// Equivalent to \frac{100-heap_growth_ratio_}{100}.
- double desired_utilization_;
+ const double desired_utilization_;
// Max number of pages we grow.
- int heap_growth_max_;
+ const int heap_growth_max_;
// If the relative GC time goes above garbage_collection_time_ratio_ %,
// we grow the heap more aggressively.
- int garbage_collection_time_ratio_;
+ const int garbage_collection_time_ratio_;
// The time in microseconds of the last time we tried to collect unused
// code.
int64_t last_code_collection_in_us_;
- // We start considering idle mark-sweeps when old space crosses this size.
+ // Perform a synchronous GC when capacity exceeds this amount.
+ intptr_t gc_threshold_in_words_;
+
+ // Perform a synchronous GC when external allocations exceed this amount.
+ intptr_t gc_external_threshold_in_words_;
+
+ // Start considering idle GC when capacity exceeds this amount.
intptr_t idle_gc_threshold_in_words_;
PageSpaceGarbageCollectionHistory history_;
@@ -213,9 +218,7 @@
public:
enum GrowthPolicy { kControlGrowth, kForceGrowth };
- PageSpace(Heap* heap,
- intptr_t max_capacity_in_words,
- intptr_t max_external_in_words);
+ PageSpace(Heap* heap, intptr_t max_capacity_in_words);
~PageSpace();
uword TryAllocate(intptr_t size,
@@ -229,8 +232,7 @@
}
bool NeedsGarbageCollection() const {
- return page_space_controller_.NeedsGarbageCollection(usage_) ||
- NeedsExternalGC();
+ return page_space_controller_.NeedsGarbageCollection(usage_);
}
int64_t UsedInWords() const { return usage_.used_in_words; }
@@ -294,11 +296,6 @@
bool GrowthControlState() { return page_space_controller_.is_enabled(); }
- bool NeedsExternalGC() const {
- return (max_external_in_words_ != 0) &&
- (ExternalInWords() > max_external_in_words_);
- }
-
// Note: Code pages are made executable/non-executable when 'read_only' is
// true/false, respectively.
void WriteProtect(bool read_only);
@@ -432,7 +429,7 @@
// Various sizes being tracked for this generation.
intptr_t max_capacity_in_words_;
- intptr_t max_external_in_words_;
+
// NOTE: The capacity component of usage_ is updated by the concurrent
// sweeper. Use (Increase)CapacityInWords(Locked) for thread-safe access.
SpaceUsage usage_;
diff --git a/runtime/vm/pages_test.cc b/runtime/vm/pages_test.cc
index 82321b3..85a0d30 100644
--- a/runtime/vm/pages_test.cc
+++ b/runtime/vm/pages_test.cc
@@ -9,7 +9,7 @@
namespace dart {
TEST_CASE(Pages) {
- PageSpace* space = new PageSpace(NULL, 4 * MBInWords, 8 * MBInWords);
+ PageSpace* space = new PageSpace(NULL, 4 * MBInWords);
EXPECT(!space->Contains(reinterpret_cast<uword>(&space)));
uword block = space->TryAllocate(8 * kWordSize);
EXPECT(block != 0);
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 0226504..80b7358 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -184,7 +184,7 @@
guarded_fields_(new ZoneGrowableArray<const Field*>()),
default_parameter_values_(NULL),
raw_type_arguments_var_(NULL),
- first_parameter_index_(0),
+ first_parameter_index_(),
num_stack_locals_(0),
have_seen_await_expr_(false),
kernel_scopes_(NULL) {
@@ -320,7 +320,7 @@
const intptr_t num_opt_params = function().NumOptionalParameters();
const intptr_t num_params = num_fixed_params + num_opt_params;
- // Before we start allocating frame indices to variables, we'll setup the
+ // Before we start allocating indices to variables, we'll setup the
// parameters array, which can be used to access the raw parameters (i.e. not
// the potentially variables which are in the context)
@@ -349,8 +349,8 @@
raw_parameter->set_is_captured_parameter(true);
} else {
- raw_parameter->set_index(kParamEndSlotFromFp +
- function().NumParameters() - param);
+ raw_parameter->set_index(
+ VariableIndex(function().NumParameters() - param));
}
}
raw_parameters_.Add(raw_parameter);
@@ -375,41 +375,36 @@
// The copy parameters implementation will still write to local variables
// which we assign indices as with the old CopyParams implementation.
- intptr_t parameter_frame_index_start;
- intptr_t reamining_local_variables_start;
+ VariableIndex parameter_index_start;
+ VariableIndex reamining_local_variables_start;
{
// Compute start indices to parameters and locals, and the number of
// parameters to copy.
if (num_opt_params == 0) {
- // Parameter i will be at fp[kParamEndSlotFromFp + num_params - i] and
- // local variable j will be at fp[kFirstLocalSlotFromFp - j].
- parameter_frame_index_start = first_parameter_index_ =
- kParamEndSlotFromFp + num_params;
- reamining_local_variables_start = kFirstLocalSlotFromFp;
+ parameter_index_start = first_parameter_index_ =
+ VariableIndex(num_params);
+ reamining_local_variables_start = VariableIndex(0);
} else {
- // Parameter i will be at fp[kFirstLocalSlotFromFp - i] and local variable
- // j will be at fp[kFirstLocalSlotFromFp - num_params - j].
- parameter_frame_index_start = first_parameter_index_ =
- kFirstLocalSlotFromFp;
- reamining_local_variables_start = first_parameter_index_ - num_params;
+ parameter_index_start = first_parameter_index_ = VariableIndex(0);
+ reamining_local_variables_start = VariableIndex(-num_params);
}
}
if (function_type_arguments_ != NULL && num_opt_params > 0) {
- reamining_local_variables_start--;
+ reamining_local_variables_start =
+ VariableIndex(reamining_local_variables_start.value() - 1);
}
// Allocate parameters and local variables, either in the local frame or
// in the context(s).
bool found_captured_variables = false;
- int next_free_frame_index = scope->AllocateVariables(
- parameter_frame_index_start, num_params,
- parameter_frame_index_start > 0 ? kFirstLocalSlotFromFp
- : kFirstLocalSlotFromFp - num_params,
- NULL, &found_captured_variables);
+ VariableIndex first_local_index =
+ VariableIndex(parameter_index_start.value() > 0 ? 0 : -num_params);
+ VariableIndex next_free_index = scope->AllocateVariables(
+ parameter_index_start, num_params, first_local_index, NULL,
+ &found_captured_variables);
- // Frame indices are relative to the frame pointer and are decreasing.
- num_stack_locals_ = -(next_free_frame_index - kFirstLocalSlotFromFp);
+ num_stack_locals_ = -next_free_index.value();
}
struct CatchParamDesc {
@@ -431,9 +426,7 @@
ASSERT(num_params == RegExpMacroAssembler::kParamCount);
// Compute start indices to parameters and locals, and the number of
// parameters to copy.
- // Parameter i will be at fp[kParamEndSlotFromFp + num_params - i] and
- // local variable j will be at fp[kFirstLocalSlotFromFp - j].
- first_parameter_index_ = kParamEndSlotFromFp + num_params;
+ first_parameter_index_ = VariableIndex(num_params);
// Frame indices are relative to the frame pointer and are decreasing.
num_stack_locals_ = num_stack_locals;
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index ca45d6c..2a4952e 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -182,7 +182,7 @@
return guarded_fields_;
}
- int first_parameter_index() const { return first_parameter_index_; }
+ VariableIndex first_parameter_index() const { return first_parameter_index_; }
int num_stack_locals() const { return num_stack_locals_; }
void AllocateVariables();
@@ -240,7 +240,7 @@
LocalVariable* raw_type_arguments_var_;
ZoneGrowableArray<LocalVariable*> raw_parameters_;
- int first_parameter_index_;
+ VariableIndex first_parameter_index_;
int num_stack_locals_;
bool have_seen_await_expr_;
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 7d83c25..13ab5b0 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -561,6 +561,7 @@
pc_ = reinterpret_cast<uword*>(frame->pc());
fp_ = reinterpret_cast<uword*>(frame->fp());
sp_ = reinterpret_cast<uword*>(frame->sp());
+ is_interpreted_frame_ = frame->is_interpreted();
}
}
@@ -572,7 +573,7 @@
}
ASSERT(ValidFramePointer());
uword return_pc = InitialReturnAddress();
- if (StubCode::InInvocationStub(return_pc)) {
+ if (StubCode::InInvocationStub(return_pc, is_interpreted_frame_)) {
// Edge case- we have called out from the Invocation Stub but have not
// created the stack frame of the callee. Attempt to locate the exit
// frame before walking the stack.
@@ -597,14 +598,16 @@
if (!ValidFramePointer()) {
return false;
}
- if (StubCode::InInvocationStub(reinterpret_cast<uword>(pc_))) {
+ if (StubCode::InInvocationStub(reinterpret_cast<uword>(pc_),
+ is_interpreted_frame_)) {
// In invocation stub.
return NextExit();
}
// In regular Dart frame.
uword* new_pc = CallerPC();
// Check if we've moved into the invocation stub.
- if (StubCode::InInvocationStub(reinterpret_cast<uword>(new_pc))) {
+ if (StubCode::InInvocationStub(reinterpret_cast<uword>(new_pc),
+ is_interpreted_frame_)) {
// New PC is inside invocation stub, skip.
return NextExit();
}
@@ -691,6 +694,7 @@
uword* pc_;
uword* fp_;
uword* sp_;
+ bool is_interpreted_frame_;
const uword stack_upper_;
const uword stack_lower_;
bool has_exit_frame_;
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 2f92257..31ae26e 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -378,7 +378,6 @@
REGULAR_VISITOR(LanguageError)
REGULAR_VISITOR(UnhandledException)
REGULAR_VISITOR(UnwindError)
-REGULAR_VISITOR(Bigint)
REGULAR_VISITOR(ExternalOneByteString)
REGULAR_VISITOR(ExternalTwoByteString)
COMPRESSED_VISITOR(GrowableObjectArray)
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index f1c80c5..d8b7048 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -68,7 +68,6 @@
V(Integer) \
V(Smi) \
V(Mint) \
- V(Bigint) \
V(Double) \
V(Bool) \
V(GrowableObjectArray) \
@@ -677,7 +676,6 @@
friend class Array;
friend class Become; // GetClassId
friend class CompactorTask; // GetClassId
- friend class Bigint;
friend class ByteBuffer;
friend class CidRewriteVisitor;
friend class Closure;
@@ -1969,16 +1967,6 @@
};
COMPILE_ASSERT(sizeof(RawMint) == 16);
-class RawBigint : public RawInteger {
- RAW_HEAP_OBJECT_IMPLEMENTATION(Bigint);
-
- VISIT_FROM(RawObject*, neg_)
- RawBool* neg_;
- RawSmi* used_;
- RawTypedData* digits_;
- VISIT_TO(RawObject*, digits_)
-};
-
class RawDouble : public RawNumber {
RAW_HEAP_OBJECT_IMPLEMENTATION(Double);
VISIT_NOTHING();
@@ -2039,36 +2027,11 @@
friend class String;
};
-template <typename T>
-class ExternalStringData {
- public:
- ExternalStringData(const T* data, void* peer, Dart_PeerFinalizer callback)
- : data_(data), peer_(peer), callback_(callback) {}
- ~ExternalStringData() {
- if (callback_ != NULL) (*callback_)(peer_);
- }
-
- const T* data() { return data_; }
- void* peer() { return peer_; }
-
- static intptr_t data_offset() {
- return OFFSET_OF(ExternalStringData<T>, data_);
- }
-
- private:
- const T* data_;
- void* peer_;
- Dart_PeerFinalizer callback_;
-};
-
class RawExternalOneByteString : public RawString {
RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalOneByteString);
- public:
- typedef ExternalStringData<uint8_t> ExternalData;
-
- private:
- ExternalData* external_data_;
+ const uint8_t* external_data_;
+ void* peer_;
friend class Api;
friend class String;
};
@@ -2076,11 +2039,8 @@
class RawExternalTwoByteString : public RawString {
RAW_HEAP_OBJECT_IMPLEMENTATION(ExternalTwoByteString);
- public:
- typedef ExternalStringData<uint16_t> ExternalData;
-
- private:
- ExternalData* external_data_;
+ const uint16_t* external_data_;
+ void* peer_;
friend class Api;
friend class String;
};
@@ -2382,17 +2342,14 @@
inline bool RawObject::IsNumberClassId(intptr_t index) {
// Make sure this function is updated when new Number types are added.
COMPILE_ASSERT(kIntegerCid == kNumberCid + 1 && kSmiCid == kNumberCid + 2 &&
- kMintCid == kNumberCid + 3 && kBigintCid == kNumberCid + 4 &&
- kDoubleCid == kNumberCid + 5);
- return (index >= kNumberCid && index < kBoolCid);
+ kMintCid == kNumberCid + 3 && kDoubleCid == kNumberCid + 4);
+ return (index >= kNumberCid && index <= kDoubleCid);
}
inline bool RawObject::IsIntegerClassId(intptr_t index) {
// Make sure this function is updated when new Integer types are added.
- COMPILE_ASSERT(kSmiCid == kIntegerCid + 1 && kMintCid == kIntegerCid + 2 &&
- kBigintCid == kIntegerCid + 3 &&
- kDoubleCid == kIntegerCid + 4);
- return (index >= kIntegerCid && index < kDoubleCid);
+ COMPILE_ASSERT(kSmiCid == kIntegerCid + 1 && kMintCid == kIntegerCid + 2);
+ return (index >= kIntegerCid && index <= kMintCid);
}
inline bool RawObject::IsStringClassId(intptr_t index) {
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index e5571e4..fce31ee 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -1942,51 +1942,6 @@
writer->Write<int64_t>(ptr()->value_);
}
-RawBigint* Bigint::ReadFrom(SnapshotReader* reader,
- intptr_t object_id,
- intptr_t tags,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(reader != NULL);
-
- // Allocate bigint object.
- Bigint& obj = Bigint::ZoneHandle(reader->zone(), Bigint::New());
- reader->AddBackRef(object_id, &obj, kIsDeserialized);
-
- // Set all the object fields.
- READ_OBJECT_FIELDS(obj, obj.raw()->from(), obj.raw()->to(), kAsInlinedObject);
-
- // If it is a canonical constant make it one.
- // When reading a full snapshot we don't need to canonicalize the object
- // as it would already be a canonical object.
- // When reading a script snapshot or a message snapshot we always have
- // to canonicalize the object.
- if (RawObject::IsCanonical(tags)) {
- obj ^= obj.CheckAndCanonicalize(reader->thread(), NULL);
- ASSERT(!obj.IsNull());
- ASSERT(obj.IsCanonical());
- }
- return obj.raw();
-}
-
-void RawBigint::WriteTo(SnapshotWriter* writer,
- intptr_t object_id,
- Snapshot::Kind kind,
- bool as_reference) {
- ASSERT(writer != NULL);
-
- // Write out the serialization header value for this object.
- writer->WriteInlinedObjectHeader(object_id);
-
- // Write out the class and tags information.
- writer->WriteIndexedObject(kBigintCid);
- writer->WriteTags(writer->GetObjectTags(this));
-
- // Write out all the object pointer fields.
- SnapshotWriterVisitor visitor(writer, kAsInlinedObject);
- visitor.VisitPointers(from(), to());
-}
-
RawDouble* Double::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
@@ -2186,7 +2141,7 @@
// Serialize as a non-external one byte string.
StringWriteTo(writer, object_id, kind, kOneByteStringCid,
writer->GetObjectTags(this), ptr()->length_,
- ptr()->external_data_->data());
+ ptr()->external_data_);
}
void RawExternalTwoByteString::WriteTo(SnapshotWriter* writer,
@@ -2196,7 +2151,7 @@
// Serialize as a non-external two byte string.
StringWriteTo(writer, object_id, kind, kTwoByteStringCid,
writer->GetObjectTags(this), ptr()->length_,
- ptr()->external_data_->data());
+ ptr()->external_data_);
}
RawBool* Bool::ReadFrom(SnapshotReader* reader,
diff --git a/runtime/vm/regexp_assembler_ir.cc b/runtime/vm/regexp_assembler_ir.cc
index 777e8b4..64753cb 100644
--- a/runtime/vm/regexp_assembler_ir.cc
+++ b/runtime/vm/regexp_assembler_ir.cc
@@ -148,7 +148,8 @@
void IRRegExpMacroAssembler::InitializeLocals() {
// All generated functions are expected to have a current-context variable.
// This variable is unused in irregexp functions.
- parsed_function_->current_context_var()->set_index(GetNextLocalIndex());
+ parsed_function_->current_context_var()->set_index(
+ VariableIndex(GetNextLocalIndex()));
// Create local variables and parameters.
stack_ = Local(Symbols::stack());
@@ -341,8 +342,8 @@
new (Z) LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
name, Object::dynamic_type());
- intptr_t param_frame_index = kParamEndSlotFromFp + kParamCount - index;
- local->set_index(param_frame_index);
+ intptr_t param_frame_index = kParamCount - index;
+ local->set_index(VariableIndex(param_frame_index));
return local;
}
@@ -351,7 +352,7 @@
LocalVariable* local =
new (Z) LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
name, Object::dynamic_type());
- local->set_index(GetNextLocalIndex());
+ local->set_index(VariableIndex(GetNextLocalIndex()));
return local;
}
@@ -709,7 +710,7 @@
intptr_t IRRegExpMacroAssembler::GetNextLocalIndex() {
intptr_t id = local_id_.Alloc();
- return kFirstLocalSlotFromFp - id;
+ return -id;
}
Value* IRRegExpMacroAssembler::LoadRegister(intptr_t index) {
@@ -1708,24 +1709,18 @@
// Bind the pattern as the load receiver.
Value* pattern_val = BindLoadLocal(*string_param_);
if (RawObject::IsExternalStringClassId(specialization_cid_)) {
- // The data of an external string is stored through two indirections.
+ // The data of an external string is stored through one indirection.
intptr_t external_offset = 0;
- intptr_t data_offset = 0;
if (specialization_cid_ == kExternalOneByteStringCid) {
external_offset = ExternalOneByteString::external_data_offset();
- data_offset = RawExternalOneByteString::ExternalData::data_offset();
} else if (specialization_cid_ == kExternalTwoByteStringCid) {
external_offset = ExternalTwoByteString::external_data_offset();
- data_offset = RawExternalTwoByteString::ExternalData::data_offset();
} else {
UNREACHABLE();
}
- // This pushes untagged values on the stack which are immediately consumed:
- // the first value is consumed to obtain the second value which is consumed
+ // This pushes an untagged value on the stack which is immediately consumed
// by LoadCodeUnitsAtInstr below.
- Value* external_val =
- Bind(new (Z) LoadUntaggedInstr(pattern_val, external_offset));
- pattern_val = Bind(new (Z) LoadUntaggedInstr(external_val, data_offset));
+ pattern_val = Bind(new (Z) LoadUntaggedInstr(pattern_val, external_offset));
}
// Here pattern_val might be untagged so this must not trigger a GC.
diff --git a/runtime/vm/regexp_test.cc b/runtime/vm/regexp_test.cc
index 7eb55ad..c4646d4 100644
--- a/runtime/vm/regexp_test.cc
+++ b/runtime/vm/regexp_test.cc
@@ -64,11 +64,15 @@
EXPECT_EQ(3, smi_2.Value());
}
+static void NoopFinalizer(void* isolate_callback_data,
+ Dart_WeakPersistentHandle handle,
+ void* peer) {}
+
TEST_CASE(RegExp_ExternalOneByteString) {
uint8_t chars[] = {'a', 'b', 'c', 'b', 'a'};
intptr_t len = ARRAY_SIZE(chars);
- const String& str = String::Handle(
- ExternalOneByteString::New(chars, len, NULL, NULL, Heap::kNew));
+ const String& str = String::Handle(ExternalOneByteString::New(
+ chars, len, NULL, 0, NoopFinalizer, Heap::kNew));
const String& pat = String::Handle(String::New("bc"));
const Array& res = Array::Handle(Match(pat, str));
@@ -88,8 +92,8 @@
TEST_CASE(RegExp_ExternalTwoByteString) {
uint16_t chars[] = {'a', 'b', 'c', 'b', 'a'};
intptr_t len = ARRAY_SIZE(chars);
- const String& str = String::Handle(
- ExternalTwoByteString::New(chars, len, NULL, NULL, Heap::kNew));
+ const String& str = String::Handle(ExternalTwoByteString::New(
+ chars, len, NULL, 0, NoopFinalizer, Heap::kNew));
const String& pat = String::Handle(String::New("bc"));
const Array& res = Array::Handle(Match(pat, str));
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index bc13a5b..ede255c 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -277,7 +277,7 @@
if (String::EqualsIgnoringPrivateKey(
name,
String::Handle(String::New(FLAG_gc_at_instance_allocation)))) {
- Isolate::Current()->heap()->CollectAllGarbage();
+ Isolate::Current()->heap()->CollectAllGarbage(Heap::kDebugging);
}
}
#endif
@@ -357,9 +357,13 @@
instantiator_type_arguments.IsInstantiated());
ASSERT(function_type_arguments.IsNull() ||
function_type_arguments.IsInstantiated());
+#if !defined(DART_USE_INTERPRETER)
// Code inlined in the caller should have optimized the case where the
// instantiator can be reused as type argument vector.
+ // However, it is non-trivial for the bytecode generator to implement this
+ // optimization, so we do not require it when the interpreter is used.
ASSERT(!type_arguments.IsUninstantiatedIdentity());
+#endif
if (isolate->type_checks()) {
Error& bound_error = Error::Handle(zone);
type_arguments = type_arguments.InstantiateAndCanonicalizeFrom(
@@ -1936,10 +1940,22 @@
// persist.
uword stack_overflow_flags = thread->GetAndClearStackOverflowFlags();
+ bool interpreter_stack_overflow = false;
+#if defined(DART_USE_INTERPRETER)
+ // Do not allocate an interpreter, if none is allocated yet.
+ Interpreter* interpreter = Isolate::Current()->interpreter();
+ if (interpreter != NULL) {
+ interpreter_stack_overflow =
+ interpreter->get_sp() >= interpreter->stack_limit();
+ }
+#endif
+
// If an interrupt happens at the same time as a stack overflow, we
// process the stack overflow now and leave the interrupt for next
// time.
- if (IsCalleeFrameOf(thread->saved_stack_limit(), stack_pos)) {
+ // TODO(regis): Warning: IsCalleeFrameOf is overridden in stack_frame_dbc.h.
+ if (interpreter_stack_overflow ||
+ IsCalleeFrameOf(thread->saved_stack_limit(), stack_pos)) {
// Use the preallocated stack overflow exception to avoid calling
// into dart code.
const Instance& exception =
@@ -2430,20 +2446,6 @@
UNREACHABLE();
}
-DEFINE_LEAF_RUNTIME_ENTRY(intptr_t,
- BigintCompare,
- 2,
- RawBigint* left,
- RawBigint* right) {
- Thread* thread = Thread::Current();
- StackZone zone(thread);
- HANDLESCOPE(thread);
- const Bigint& big_left = Bigint::Handle(left);
- const Bigint& big_right = Bigint::Handle(right);
- return big_left.CompareWith(big_right);
-}
-END_LEAF_RUNTIME_ENTRY
-
double DartModulo(double left, double right) {
double remainder = fmod_ieee(left, right);
if (remainder == 0.0) {
diff --git a/runtime/vm/runtime_entry_list.h b/runtime/vm/runtime_entry_list.h
index d9c7367..2c5f7f5 100644
--- a/runtime/vm/runtime_entry_list.h
+++ b/runtime/vm/runtime_entry_list.h
@@ -55,7 +55,6 @@
V(intptr_t, DeoptimizeCopyFrame, uword, uword) \
V(void, DeoptimizeFillFrame, uword) \
V(void, StoreBufferBlockProcess, Thread*) \
- V(intptr_t, BigintCompare, RawBigint*, RawBigint*) \
V(double, LibcPow, double, double) \
V(double, DartModulo, double, double) \
V(double, LibcFloor, double) \
diff --git a/runtime/vm/scopes.cc b/runtime/vm/scopes.cc
index e38d191..0af2a71 100644
--- a/runtime/vm/scopes.cc
+++ b/runtime/vm/scopes.cc
@@ -178,14 +178,15 @@
ASSERT(context_level() == (*context_owner)->context_level());
}
}
- variable->set_index((*context_owner)->num_context_variables_++);
+ variable->set_index(
+ VariableIndex((*context_owner)->num_context_variables_++));
}
-int LocalScope::AllocateVariables(int first_parameter_index,
- int num_parameters,
- int first_frame_index,
- LocalScope* context_owner,
- bool* found_captured_variables) {
+VariableIndex LocalScope::AllocateVariables(VariableIndex first_parameter_index,
+ int num_parameters,
+ VariableIndex first_local_index,
+ LocalScope* context_owner,
+ bool* found_captured_variables) {
// We should not allocate variables of nested functions while compiling an
// enclosing function.
ASSERT(function_level() == 0);
@@ -193,7 +194,8 @@
// Parameters must be listed first and must all appear in the top scope.
ASSERT(num_parameters <= num_variables());
int pos = 0; // Current variable position.
- int frame_index = first_parameter_index; // Current free frame index.
+ VariableIndex next_index =
+ first_parameter_index; // Current free frame index.
while (pos < num_parameters) {
LocalVariable* parameter = VariableAt(pos);
pos++;
@@ -206,16 +208,17 @@
// A captured parameter has a slot allocated in the frame and one in the
// context, where it gets copied to. The parameter index reflects the
// context allocation index.
- frame_index--;
+ next_index = VariableIndex(next_index.value() - 1);
AllocateContextVariable(parameter, &context_owner);
*found_captured_variables = true;
} else {
- parameter->set_index(frame_index--);
+ parameter->set_index(next_index);
+ next_index = VariableIndex(next_index.value() - 1);
}
}
// No overlapping of parameters and locals.
- ASSERT(frame_index >= first_frame_index);
- frame_index = first_frame_index;
+ ASSERT(next_index.value() >= first_local_index.value());
+ next_index = first_local_index;
while (pos < num_variables()) {
LocalVariable* variable = VariableAt(pos);
if (variable->owner() == this) {
@@ -223,26 +226,30 @@
AllocateContextVariable(variable, &context_owner);
*found_captured_variables = true;
} else {
- variable->set_index(frame_index--);
+ variable->set_index(next_index);
+ next_index = VariableIndex(next_index.value() - 1);
}
}
pos++;
}
// Allocate variables of all children.
- int min_frame_index = frame_index; // Frame index decreases with allocations.
+ VariableIndex min_index = next_index;
LocalScope* child = this->child();
while (child != NULL) {
- const int dummy_parameter_index = 0; // Ignored, since no parameters.
- const int num_parameters_in_child = 0; // No parameters in children scopes.
- int child_frame_index = child->AllocateVariables(
- dummy_parameter_index, num_parameters_in_child, frame_index,
+ // Ignored, since no parameters.
+ const VariableIndex dummy_parameter_index(0);
+
+ // No parameters in children scopes.
+ const int num_parameters_in_child = 0;
+ VariableIndex child_next_index = child->AllocateVariables(
+ dummy_parameter_index, num_parameters_in_child, next_index,
context_owner, found_captured_variables);
- if (child_frame_index < min_frame_index) {
- min_frame_index = child_frame_index;
+ if (child_next_index.value() < min_index.value()) {
+ min_index = child_next_index;
}
child = child->sibling();
}
- return min_frame_index;
+ return min_index;
}
// The parser creates internal variables that start with ":"
@@ -370,7 +377,7 @@
desc.info.declaration_pos = TokenPosition::kMinSource;
desc.info.begin_pos = TokenPosition::kMinSource;
desc.info.end_pos = TokenPosition::kMinSource;
- desc.info.set_index(var->index());
+ desc.info.set_index(var->index().value());
vars->Add(desc);
} else if (!IsFilteredIdentifier(var->name())) {
// This is a regular Dart variable, either stack-based or captured.
@@ -385,10 +392,10 @@
desc.info.set_kind(RawLocalVarDescriptors::kStackVar);
desc.info.scope_id = *scope_id;
}
+ desc.info.set_index(var->index().value());
desc.info.declaration_pos = var->declaration_token_pos();
desc.info.begin_pos = var->token_pos();
desc.info.end_pos = var->owner()->end_token_pos();
- desc.info.set_index(var->index());
vars->Add(desc);
}
}
@@ -585,7 +592,7 @@
} else {
context_scope.SetTypeAt(captured_idx, variable->type());
}
- context_scope.SetContextIndexAt(captured_idx, variable->index());
+ context_scope.SetContextIndexAt(captured_idx, variable->index().value());
// Adjust the context level relative to the current context level,
// since the context of the current scope will be at level 0 when
// compiling the nested function.
@@ -621,7 +628,7 @@
AbstractType::ZoneHandle(context_scope.TypeAt(i)));
}
variable->set_is_captured();
- variable->set_index(context_scope.ContextIndexAt(i));
+ variable->set_index(VariableIndex(context_scope.ContextIndexAt(i)));
if (context_scope.IsFinalAt(i)) {
variable->set_is_final();
}
@@ -695,19 +702,4 @@
return false;
}
-int LocalVariable::BitIndexIn(intptr_t fixed_parameter_count) const {
- ASSERT(!is_captured());
- // Parameters have positive indexes with the lowest index being
- // kParamEndSlotFromFp + 1. Locals have negative indexes with the lowest
- // (closest to 0) index being kFirstLocalSlotFromFp.
- if (index() > 0) {
- // Shift non-negative indexes so that the lowest one is 0.
- return fixed_parameter_count - (index() - kParamEndSlotFromFp);
- } else {
- // Shift negative indexes so that the lowest one is 0 (they are still
- // non-positive).
- return fixed_parameter_count - (index() - kFirstLocalSlotFromFp);
- }
-}
-
} // namespace dart
diff --git a/runtime/vm/scopes.h b/runtime/vm/scopes.h
index e739416..15548dc 100644
--- a/runtime/vm/scopes.h
+++ b/runtime/vm/scopes.h
@@ -5,6 +5,8 @@
#ifndef RUNTIME_VM_SCOPES_H_
#define RUNTIME_VM_SCOPES_H_
+#include <limits>
+
#include "platform/assert.h"
#include "platform/globals.h"
#include "vm/allocation.h"
@@ -19,6 +21,54 @@
class CompileType;
class LocalScope;
+// Indices of [LocalVariable]s are abstract and have little todo with the
+// actual frame layout!
+//
+// There are generally 4 different kinds of [LocalVariable]s:
+//
+// a) [LocalVariable]s refering to a parameter: The indices for those
+// variables are assigned by the flow graph builder. Parameter n gets
+// assigned the index (function.num_parameters - n - 1). I.e. the last
+// parameter has index 1.
+//
+// b) [LocalVariable]s referring to actual variables in the body of a
+// function (either from Dart code or specially injected ones. The
+// indices of those variables are assigned by the scope builder
+// from 0, -1, ... -(M-1) for M local variables.
+//
+// -> These variables participate in full SSA renaming and can therefore
+// be used with [StoreLocalInstr]s (in addition to [LoadLocal]s).
+//
+// c) [LocalVariable]s referring to values on the expression stack. Those are
+// assigned by the flow graph builder. The indices of those variables are
+// assigned by the flow graph builder (it simulates the expression stack
+// height), they go from -NumVariabables - ExpressionHeight.
+//
+// -> These variables participate only partially in SSA renaming and can
+// therefore only be used with [LoadLocalInstr]s and with
+// [StoreLocalInstr]s **where no phis are necessary**.
+//
+// b) [LocalVariable]s referring to captured variables. Those are never
+// loaded/stored directly. Their only purpose is to tell the flow graph
+// builder how many parent links to follow and into which context index to
+// store. The indices of those variables are assigned by the scope
+// builder and they refer to indices into context objects.
+class VariableIndex {
+ public:
+ static const int kInvalidIndex = std::numeric_limits<int>::min();
+
+ explicit VariableIndex(int value = kInvalidIndex) : value_(value) {}
+
+ int operator==(const VariableIndex& other) { return value_ == other.value_; }
+
+ bool IsValid() const { return value_ != kInvalidIndex; }
+
+ int value() const { return value_; }
+
+ private:
+ int value_;
+};
+
class LocalVariable : public ZoneAllocated {
public:
LocalVariable(TokenPosition declaration_pos,
@@ -39,7 +89,7 @@
is_captured_parameter_(false),
is_forced_stack_(false),
type_check_mode_(kDoTypeCheck),
- index_(LocalVariable::kUninitializedIndex) {
+ index_() {
ASSERT(type.IsZoneHandle() || type.IsReadOnlyHandle());
ASSERT(type.IsFinalized());
ASSERT(name.IsSymbol());
@@ -89,15 +139,15 @@
void set_type_check_mode(TypeCheckMode mode) { type_check_mode_ = mode; }
- bool HasIndex() const { return index_ != kUninitializedIndex; }
- int index() const {
+ bool HasIndex() const { return index_.IsValid(); }
+ VariableIndex index() const {
ASSERT(HasIndex());
return index_;
}
// Assign an index to a local.
- void set_index(int index) {
- ASSERT(index != kUninitializedIndex);
+ void set_index(VariableIndex index) {
+ ASSERT(index.IsValid());
index_ = index;
}
@@ -124,12 +174,6 @@
bool Equals(const LocalVariable& other) const;
- // Map the frame index to a bit-vector index. Assumes the variable is
- // allocated to the frame.
- // var_count is the total number of stack-allocated variables including
- // all parameters.
- int BitIndexIn(intptr_t fixed_parameter_count) const;
-
private:
static const int kUninitializedIndex = INT_MIN;
@@ -151,8 +195,7 @@
bool is_captured_parameter_;
bool is_forced_stack_;
TypeCheckMode type_check_mode_;
- int index_; // Allocation index in words relative to frame pointer (if not
- // captured), or relative to the context pointer (if captured).
+ VariableIndex index_;
friend class LocalScope;
DISALLOW_COPY_AND_ASSIGN(LocalVariable);
@@ -334,12 +377,13 @@
// and not in its children (we do not yet handle register parameters).
// Locals must be listed after parameters in top scope and in its children.
// Two locals in different sibling scopes may share the same frame slot.
+ //
// Return the index of the next available frame slot.
- int AllocateVariables(int first_parameter_index,
- int num_parameters,
- int first_frame_index,
- LocalScope* context_owner,
- bool* found_captured_variables);
+ VariableIndex AllocateVariables(VariableIndex first_parameter_index,
+ int num_parameters,
+ VariableIndex first_local_index,
+ LocalScope* context_owner,
+ bool* found_captured_variables);
// Creates variable info for the scope and all its nested scopes.
// Must be called after AllocateVariables() has been called.
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index cf08ad6..9308a89 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -8,6 +8,7 @@
#include "include/dart_native_api.h"
#include "platform/globals.h"
+#include "vm/base64.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/cpu.h"
#include "vm/dart_api_impl.h"
@@ -233,6 +234,28 @@
jsobj.AddProperty("type", "Success");
}
+static bool CheckDebuggerDisabled(Thread* thread, JSONStream* js) {
+ Isolate* isolate = thread->isolate();
+ if (!isolate->compilation_allowed()) {
+ js->PrintError(kFeatureDisabled, "Debugger is disabled in AOT mode.");
+ return true;
+ }
+ if (isolate->debugger() == NULL) {
+ js->PrintError(kFeatureDisabled, "Debugger is disabled.");
+ return true;
+ }
+ return false;
+}
+
+static bool CheckCompilerDisabled(Thread* thread, JSONStream* js) {
+ Isolate* isolate = thread->isolate();
+ if (!isolate->compilation_allowed()) {
+ js->PrintError(kFeatureDisabled, "Compiler is disabled in AOT mode.");
+ return true;
+ }
+ return false;
+}
+
static bool GetIntegerId(const char* s, intptr_t* id, int base = 10) {
if ((s == NULL) || (*s == '\0')) {
// Empty string.
@@ -1311,7 +1334,10 @@
};
static bool GetUnusedChangesInLastReload(Thread* thread, JSONStream* js) {
-#if !defined(DART_PRECOMPILED_RUNTIME)
+ if (CheckCompilerDisabled(thread, js)) {
+ return true;
+ }
+
const GrowableObjectArray& changed_in_last_reload =
GrowableObjectArray::Handle(
thread->isolate()->object_store()->changed_in_last_reload());
@@ -1365,11 +1391,6 @@
}
}
return true;
-#else // !defined(DART_PRECOMPILED_RUNTIME)
- js->PrintError(kFeatureDisabled,
- "Cannot reload source when running a precompiled program.");
- return true;
-#endif
}
static const MethodParameter* get_stack_params[] = {
@@ -1377,13 +1398,11 @@
};
static bool GetStack(Thread* thread, JSONStream* js) {
- Isolate* isolate = thread->isolate();
- if (isolate->debugger() == NULL) {
- js->PrintError(kFeatureDisabled,
- "Cannot get stack when debugger disabled.");
+ if (CheckDebuggerDisabled(thread, js)) {
return true;
}
- ASSERT(isolate->compilation_allowed());
+
+ Isolate* isolate = thread->isolate();
DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
DebuggerStackTrace* async_causal_stack =
isolate->debugger()->AsyncCausalStackTrace();
@@ -2341,11 +2360,10 @@
}
static bool Evaluate(Thread* thread, JSONStream* js) {
- if (!thread->isolate()->compilation_allowed()) {
- js->PrintError(kFeatureDisabled,
- "Cannot evaluate when running a precompiled program.");
+ if (CheckDebuggerDisabled(thread, js)) {
return true;
}
+
const char* target_id = js->LookupParam("targetId");
if (target_id == NULL) {
PrintMissingParamError(js, "targetId");
@@ -2415,18 +2433,253 @@
return true;
}
+static const MethodParameter* build_expression_evaluation_scope_params[] = {
+ RUNNABLE_ISOLATE_PARAMETER,
+ new IdParameter("frameIndex", true),
+ NULL,
+};
+
+static bool BuildExpressionEvaluationScope(Thread* thread, JSONStream* js) {
+ if (CheckDebuggerDisabled(thread, js)) {
+ return true;
+ }
+
+ Isolate* isolate = thread->isolate();
+ DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
+ intptr_t framePos = UIntParameter::Parse(js->LookupParam("frameIndex"));
+ if (framePos >= stack->Length()) {
+ PrintInvalidParamError(js, "frameIndex");
+ return true;
+ }
+
+ Zone* zone = thread->zone();
+ const GrowableObjectArray& param_names =
+ GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
+ const GrowableObjectArray& param_values =
+ GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
+ if (BuildScope(thread, js, param_names, param_values)) {
+ return true;
+ }
+
+ ActivationFrame* frame = stack->FrameAt(framePos);
+ const GrowableObjectArray& type_params_names =
+ GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
+ frame->BuildParameters(param_names, param_values, type_params_names);
+
+ JSONObject report(js);
+ {
+ JSONArray jsonParamNames(&report, "param_names");
+
+ String& param_name = String::Handle(zone);
+ for (intptr_t i = 0; i < param_names.Length(); i++) {
+ param_name ^= param_names.At(i);
+ jsonParamNames.AddValue(param_name.ToCString());
+ }
+ }
+
+ {
+ JSONArray jsonTypeParamsNames(&report, "type_params_names");
+ String& type_param_name = String::Handle(zone);
+ for (intptr_t i = 0; i < type_params_names.Length(); i++) {
+ type_param_name ^= type_params_names.At(i);
+ jsonTypeParamsNames.AddValue(type_param_name.ToCString());
+ }
+ }
+ String& klass_name = String::Handle(zone);
+ String& library_uri = String::Handle(zone);
+ bool isStatic = false;
+ if (frame->function().is_static()) {
+ const Class& cls = Class::Handle(zone, frame->function().Owner());
+ if (!cls.IsTopLevel()) {
+ klass_name ^= cls.UserVisibleName();
+ }
+ library_uri ^= Library::Handle(zone, cls.library()).url();
+ isStatic = !cls.IsTopLevel();
+ } else {
+ const Class& method_cls = Class::Handle(zone, frame->function().origin());
+ library_uri ^= Library::Handle(zone, method_cls.library()).url();
+ klass_name ^= method_cls.UserVisibleName();
+ }
+ report.AddProperty("libraryUri", library_uri.ToCString());
+ if (!klass_name.IsNull()) {
+ report.AddProperty("klass", klass_name.ToCString());
+ }
+ report.AddProperty("isStatic", isStatic);
+
+ return true;
+}
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
+// Parse comma-separated list of values, put them into values
+static bool ParseCSVList(const char* csv_list,
+ const GrowableObjectArray& values) {
+ Zone* zone = Thread::Current()->zone();
+ String& s = String::Handle(zone);
+ const char* c = csv_list;
+ if (*c++ != '[') return false;
+ while (IsWhitespace(*c) && *c != '\0') {
+ c++;
+ }
+ while (*c != '\0') {
+ const char* value = c;
+ while (*c != '\0' && *c != ']' && *c != ',' && !IsWhitespace(*c)) {
+ c++;
+ }
+ if (c > value) {
+ s ^= String::New(zone->MakeCopyOfStringN(value, c - value));
+ values.Add(s);
+ }
+ switch (*c) {
+ case '\0':
+ return false;
+ case ',':
+ c++;
+ break;
+ case ']':
+ return true;
+ }
+ while (IsWhitespace(*c) && *c != '\0') {
+ c++;
+ }
+ }
+ return false;
+}
+#endif
+
+static const MethodParameter* compile_expression_params[] = {
+ RUNNABLE_ISOLATE_PARAMETER,
+ new StringParameter("expression", true),
+ new StringParameter("definitions", false),
+ new StringParameter("typeDefinitions", false),
+ new StringParameter("libraryUri", true),
+ new StringParameter("klass", false),
+ new BoolParameter("isStatic", false),
+ NULL,
+};
+
+static bool CompileExpression(Thread* thread, JSONStream* js) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+ js->PrintError(kFeatureDisabled, "Debugger is disabled in AOT mode.");
+ return true;
+#else
+ if (CheckDebuggerDisabled(thread, js)) {
+ return true;
+ }
+
+ if (!KernelIsolate::IsRunning()) {
+ // Assume we are in dart1 mode where separate compilation is not required.
+ // 0-length kernelBytes signals that we should evaluate expression in dart1
+ // mode.
+ // TODO(aam): When dart1 is no longer supported we need to return error
+ // here.
+ JSONObject report(js);
+ const uint8_t kernel_bytes[] = {0};
+ report.AddPropertyBase64("kernelBytes", kernel_bytes, 0);
+ return true;
+ }
+
+ bool is_static = BoolParameter::Parse(js->LookupParam("isStatic"), false);
+
+ Dart_KernelCompilationResult compilation_result;
+ const GrowableObjectArray& params =
+ GrowableObjectArray::Handle(thread->zone(), GrowableObjectArray::New());
+ if (!ParseCSVList(js->LookupParam("definitions"), params)) {
+ PrintInvalidParamError(js, "definitions");
+ return true;
+ }
+
+ const GrowableObjectArray& type_params =
+ GrowableObjectArray::Handle(thread->zone(), GrowableObjectArray::New());
+ if (!ParseCSVList(js->LookupParam("typeDefinitions"), type_params)) {
+ PrintInvalidParamError(js, "typedDefinitions");
+ return true;
+ }
+
+ {
+ TransitionVMToNative transition(thread);
+ compilation_result = KernelIsolate::CompileExpressionToKernel(
+ js->LookupParam("expression"),
+ Array::Handle(Array::MakeFixedLength(params)),
+ Array::Handle(Array::MakeFixedLength(type_params)),
+ js->LookupParam("libraryUri"), js->LookupParam("klass"), is_static);
+ }
+
+ if (compilation_result.status != Dart_KernelCompilationStatus_Ok) {
+ js->PrintError(kExpressionCompilationError, compilation_result.error);
+ free(compilation_result.error);
+ return true;
+ }
+
+ const uint8_t* kernel_bytes = compilation_result.kernel;
+ intptr_t kernel_length = compilation_result.kernel_size;
+ ASSERT(kernel_bytes != NULL);
+
+ JSONObject report(js);
+ report.AddPropertyBase64("kernelBytes", kernel_bytes, kernel_length);
+ return true;
+#endif
+}
+
+static const MethodParameter* evaluate_compiled_expression_params[] = {
+ RUNNABLE_ISOLATE_PARAMETER,
+ new UIntParameter("frameIndex", true),
+ new StringParameter("kernelBytes", true),
+ NULL,
+};
+
+static bool EvaluateCompiledExpression(Thread* thread, JSONStream* js) {
+ if (CheckDebuggerDisabled(thread, js)) {
+ return true;
+ }
+
+ Isolate* isolate = thread->isolate();
+ DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
+ intptr_t frame_pos = UIntParameter::Parse(js->LookupParam("frameIndex"));
+ if (frame_pos >= stack->Length()) {
+ PrintInvalidParamError(js, "frameIndex");
+ return true;
+ }
+ Zone* zone = thread->zone();
+ const GrowableObjectArray& param_names =
+ GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
+ const GrowableObjectArray& param_values =
+ GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
+ if (BuildScope(thread, js, param_names, param_values)) {
+ return true;
+ }
+
+ ActivationFrame* frame = stack->FrameAt(frame_pos);
+ const GrowableObjectArray& type_params_names =
+ GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
+ TypeArguments& type_arguments = TypeArguments::Handle(
+ zone,
+ frame->BuildParameters(param_names, param_values, type_params_names));
+
+ intptr_t kernel_length;
+ const char* kernel_bytes_str = js->LookupParam("kernelBytes");
+ uint8_t* kernel_bytes = DecodeBase64(zone, kernel_bytes_str, &kernel_length);
+
+ const Object& result = Object::Handle(
+ zone, frame->EvaluateCompiledExpression(
+ kernel_bytes, kernel_length,
+ Array::Handle(zone, Array::MakeFixedLength(type_params_names)),
+ Array::Handle(zone, Array::MakeFixedLength(param_values)),
+ type_arguments));
+ result.PrintJSON(js, true);
+ return true;
+}
+
static const MethodParameter* evaluate_in_frame_params[] = {
RUNNABLE_ISOLATE_PARAMETER, new UIntParameter("frameIndex", true),
new MethodParameter("expression", true), NULL,
};
static bool EvaluateInFrame(Thread* thread, JSONStream* js) {
- Isolate* isolate = thread->isolate();
- if (!isolate->compilation_allowed()) {
- js->PrintError(kFeatureDisabled,
- "Cannot evaluate when running a precompiled program.");
+ if (CheckDebuggerDisabled(thread, js)) {
return true;
}
+
+ Isolate* isolate = thread->isolate();
DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
intptr_t framePos = UIntParameter::Parse(js->LookupParam("frameIndex"));
if (framePos >= stack->Length()) {
@@ -2556,12 +2809,10 @@
};
static bool GetSourceReport(Thread* thread, JSONStream* js) {
- if (!thread->isolate()->compilation_allowed()) {
- js->PrintError(
- kFeatureDisabled,
- "Cannot get source report when running a precompiled program.");
+ if (CheckCompilerDisabled(thread, js)) {
return true;
}
+
const char* reports_str = js->LookupParam("reports");
const EnumListParameter* reports_parameter =
static_cast<const EnumListParameter*>(get_source_report_params[1]);
@@ -2631,13 +2882,15 @@
};
static bool ReloadSources(Thread* thread, JSONStream* js) {
-#if !defined(DART_PRECOMPILED_RUNTIME)
- Isolate* isolate = thread->isolate();
- if (!isolate->compilation_allowed()) {
- js->PrintError(kFeatureDisabled,
- "Cannot reload source when running a precompiled program.");
+#if defined(DART_PRECOMPILED_RUNTIME)
+ js->PrintError(kFeatureDisabled, "Compiler is disabled in AOT mode.");
+ return true;
+#else
+ if (CheckCompilerDisabled(thread, js)) {
return true;
}
+
+ Isolate* isolate = thread->isolate();
Dart_LibraryTagHandler handler = isolate->library_tag_handler();
if (handler == NULL) {
js->PrintError(kFeatureDisabled,
@@ -2669,11 +2922,7 @@
Service::CheckForPause(isolate, js);
return true;
-#else // !defined(DART_PRECOMPILED_RUNTIME)
- js->PrintError(kFeatureDisabled,
- "Cannot reload source when running a precompiled program.");
- return true;
-#endif // !defined(DART_PRECOMPILED_RUNTIME)
+#endif
}
void Service::CheckForPause(Isolate* isolate, JSONStream* stream) {
@@ -2701,12 +2950,10 @@
static bool AddBreakpointCommon(Thread* thread,
JSONStream* js,
const String& script_uri) {
- if (!thread->isolate()->compilation_allowed()) {
- js->PrintError(
- kFeatureDisabled,
- "Cannot use breakpoints when running a precompiled program.");
+ if (CheckDebuggerDisabled(thread, js)) {
return true;
}
+
const char* line_param = js->LookupParam("line");
intptr_t line = UIntParameter::Parse(line_param);
const char* col_param = js->LookupParam("column");
@@ -2742,12 +2989,10 @@
};
static bool AddBreakpoint(Thread* thread, JSONStream* js) {
- if (!thread->isolate()->compilation_allowed()) {
- js->PrintError(
- kFeatureDisabled,
- "Cannot use breakpoints when running a precompiled program.");
+ if (CheckDebuggerDisabled(thread, js)) {
return true;
}
+
const char* script_id_param = js->LookupParam("scriptId");
Object& obj = Object::Handle(LookupHeapObject(thread, script_id_param, NULL));
if (obj.raw() == Object::sentinel().raw() || !obj.IsScript()) {
@@ -2769,12 +3014,10 @@
};
static bool AddBreakpointWithScriptUri(Thread* thread, JSONStream* js) {
- if (!thread->isolate()->compilation_allowed()) {
- js->PrintError(
- kFeatureDisabled,
- "Cannot use breakpoints when running a precompiled program.");
+ if (CheckDebuggerDisabled(thread, js)) {
return true;
}
+
const char* script_uri_param = js->LookupParam("scriptUri");
const String& script_uri = String::Handle(String::New(script_uri_param));
return AddBreakpointCommon(thread, js, script_uri);
@@ -2785,12 +3028,10 @@
};
static bool AddBreakpointAtEntry(Thread* thread, JSONStream* js) {
- if (!thread->isolate()->compilation_allowed()) {
- js->PrintError(
- kFeatureDisabled,
- "Cannot use breakpoints when running a precompiled program.");
+ if (CheckDebuggerDisabled(thread, js)) {
return true;
}
+
const char* function_id = js->LookupParam("functionId");
Object& obj = Object::Handle(LookupHeapObject(thread, function_id, NULL));
if (obj.raw() == Object::sentinel().raw() || !obj.IsFunction()) {
@@ -2815,12 +3056,10 @@
};
static bool AddBreakpointAtActivation(Thread* thread, JSONStream* js) {
- if (!thread->isolate()->compilation_allowed()) {
- js->PrintError(
- kFeatureDisabled,
- "Cannot use breakpoints when running a precompiled program.");
+ if (CheckDebuggerDisabled(thread, js)) {
return true;
}
+
const char* object_id = js->LookupParam("objectId");
Object& obj = Object::Handle(LookupHeapObject(thread, object_id, NULL));
if (obj.raw() == Object::sentinel().raw() || !obj.IsInstance()) {
@@ -2844,12 +3083,10 @@
};
static bool RemoveBreakpoint(Thread* thread, JSONStream* js) {
- if (!thread->isolate()->compilation_allowed()) {
- js->PrintError(
- kFeatureDisabled,
- "Cannot use breakpoints when running a precompiled program.");
+ if (CheckDebuggerDisabled(thread, js)) {
return true;
}
+
if (!js->HasParam("breakpointId")) {
PrintMissingParamError(js, "breakpointId");
return true;
@@ -3456,11 +3693,11 @@
Isolate* isolate = thread->isolate();
if (js->HasParam("gc")) {
if (js->ParamIs("gc", "scavenge")) {
- isolate->heap()->CollectGarbage(Heap::kNew);
+ isolate->heap()->CollectGarbage(Heap::kScavenge, Heap::kDebugging);
} else if (js->ParamIs("gc", "mark-sweep")) {
- isolate->heap()->CollectGarbage(Heap::kOld, Heap::kOldSpace);
+ isolate->heap()->CollectGarbage(Heap::kMarkSweep, Heap::kDebugging);
} else if (js->ParamIs("gc", "mark-compact")) {
- isolate->heap()->CollectGarbage(Heap::kOld, Heap::kCompaction);
+ isolate->heap()->CollectGarbage(Heap::kMarkCompact, Heap::kDebugging);
} else {
PrintInvalidParamError(js, "gc");
return true;
@@ -4173,12 +4410,10 @@
};
static bool SetTraceClassAllocation(Thread* thread, JSONStream* js) {
- if (!thread->isolate()->compilation_allowed()) {
- js->PrintError(
- kFeatureDisabled,
- "Cannot trace allocation when running a precompiled program.");
+ if (CheckCompilerDisabled(thread, js)) {
return true;
}
+
const char* class_id = js->LookupParam("classId");
const bool enable = BoolParameter::Parse(js->LookupParam("enable"));
intptr_t cid = -1;
@@ -4232,7 +4467,7 @@
}
{
JSONArray internals(&map, "Int");
- for (intptr_t id = kIntegerCid; id <= kBigintCid; ++id) {
+ for (intptr_t id = kIntegerCid; id <= kMintCid; ++id) {
DEFINE_ADD_VALUE_F(id);
}
}
@@ -4288,10 +4523,13 @@
add_breakpoint_at_entry_params },
{ "_addBreakpointAtActivation", AddBreakpointAtActivation,
add_breakpoint_at_activation_params },
+ { "_buildExpressionEvaluationScope", BuildExpressionEvaluationScope,
+ build_expression_evaluation_scope_params },
{ "_clearCpuProfile", ClearCpuProfile,
clear_cpu_profile_params },
{ "_clearVMTimeline", ClearVMTimeline,
clear_vm_timeline_params, },
+ { "_compileExpression", CompileExpression, compile_expression_params },
{ "_enableProfiler", EnableProfiler,
enable_profiler_params, },
{ "evaluate", Evaluate,
@@ -4375,6 +4613,8 @@
resume_params },
{ "_requestHeapSnapshot", RequestHeapSnapshot,
request_heap_snapshot_params },
+ { "_evaluateCompiledExpression", EvaluateCompiledExpression,
+ evaluate_compiled_expression_params },
{ "setExceptionPauseMode", SetExceptionPauseMode,
set_exception_pause_mode_params },
{ "setFlag", SetFlag,
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index e084402..6edc8f2 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -15,7 +15,7 @@
namespace dart {
#define SERVICE_PROTOCOL_MAJOR_VERSION 3
-#define SERVICE_PROTOCOL_MINOR_VERSION 8
+#define SERVICE_PROTOCOL_MINOR_VERSION 9
class Array;
class EmbedderServiceHandler;
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index cf548a5..baa0df8 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.8
+# Dart VM Service Protocol 3.9
> Please post feedback to the [observatory-discuss group][discuss-list]
-This document describes of _version 3.8_ of the Dart VM Service Protocol. This
+This document describes of _version 3.9_ of the Dart VM Service Protocol. This
protocol is used to communicate with a running Dart Virtual Machine.
To use the Service Protocol, start the VM with the *--observe* flag.
@@ -190,6 +190,10 @@
107 | Cannot resume execution | The isolate could not be resumed
108 | Isolate is reloading | The isolate is currently processing another reload request
109 | Isolate cannot be reloaded | The isolate has an unhandled exception and can no longer be reloaded
+110 | Isolate must have reloaded | Failed to find differences in last hot reload request
+111 | Service already registered | Service with such name has already been registered by this client
+112 | Service disappeared | Failed to fulfill service request, likely service handler is no longer available
+113 | Expression compilation error | Request to compile expression failed
@@ -494,6 +498,9 @@
targets respectively. This means bindings provided in _scope_ may shadow
instance members, class members and top-level members.
+If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
+"Expression compilation error" is returned.
+
If an error occurs while evaluating the expression, an [@Error](#error)
reference will be returned.
@@ -520,6 +527,9 @@
provided in _scope_ may shadow instance members, class members, top-level
members, parameters and locals.
+If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
+"Expression compilation error" is returned.
+
If an error occurs while evaluating the expression, an [@Error](#error)
reference will be returned.
diff --git a/runtime/vm/service/service_dev.md b/runtime/vm/service/service_dev.md
index 9426433..b4bc314 100644
--- a/runtime/vm/service/service_dev.md
+++ b/runtime/vm/service/service_dev.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.9-dev
+# Dart VM Service Protocol 3.10-dev
> Please post feedback to the [observatory-discuss group][discuss-list]
-This document describes of _version 3.9-dev_ of the Dart VM Service Protocol. This
+This document describes of _version 3.10-dev_ of the Dart VM Service Protocol. This
protocol is used to communicate with a running Dart Virtual Machine.
To use the Service Protocol, start the VM with the *--observe* flag.
@@ -190,6 +190,10 @@
107 | Cannot resume execution | The isolate could not be resumed
108 | Isolate is reloading | The isolate is currently processing another reload request
109 | Isolate cannot be reloaded | The isolate has an unhandled exception and can no longer be reloaded
+110 | Isolate must have reloaded | Failed to find differences in last hot reload request
+111 | Service already registered | Service with such name has already been registered by this client
+112 | Service disappeared | Failed to fulfill service request, likely service handler is no longer available
+113 | Expression compilation error | Request to compile expression failed
@@ -494,6 +498,9 @@
targets respectively. This means bindings provided in _scope_ may shadow
instance members, class members and top-level members.
+If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
+"Expression compilation error" is returned.
+
If an error occurs while evaluating the expression, an [@Error](#error)
reference will be returned.
@@ -520,6 +527,9 @@
provided in _scope_ may shadow instance members, class members, top-level
members, parameters and locals.
+If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
+"Expression compilation error" is returned.
+
If an error occurs while evaluating the expression, an [@Error](#error)
reference will be returned.
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index 46e467b..7e4ca4e 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -152,10 +152,6 @@
case kMintCid:
return (static_cast<RawMint*>(lhs)->ptr()->value_ ==
static_cast<RawMint*>(rhs)->ptr()->value_);
-
- case kBigintCid:
- return (DLRT_BigintCompare(static_cast<RawBigint*>(lhs),
- static_cast<RawBigint*>(rhs)) == 0);
}
}
}
@@ -1222,7 +1218,7 @@
uint16_t rA; // A component of the currently executing op.
if (fp_ == NULL) {
- fp_ = reinterpret_cast<RawObject**>(stack_);
+ fp_ = reinterpret_cast<RawObject**>(stack_base_);
}
// Save current VM tag and mark thread as executing Dart code.
@@ -1247,7 +1243,7 @@
// | arg 1 | -+
// | function | -+
// | code | |
- // | callee PC | ---> special fake PC marking an entry frame
+ // | caller PC | ---> special fake PC marking an entry frame
// SP > | fp_ | |
// FP > | ........... | > normal Dart frame (see stack_frame_dbc.h)
// |
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index d1fb4ba..68ebca2 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -992,7 +992,6 @@
V(OneByteString) \
V(TwoByteString) \
V(Mint) \
- V(Bigint) \
V(Double) \
V(ImmutableArray)
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index b630cc3..605d300 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -39,7 +39,6 @@
class PageSpace;
class RawApiError;
class RawArray;
-class RawBigint;
class RawBoundedType;
class RawCapability;
class RawClass;
@@ -69,7 +68,6 @@
class RawMegamorphicCache;
class RawMint;
class RawMixinAppType;
-class RawBigint;
class RawNamespace;
class RawObject;
class RawObjectPool;
@@ -470,7 +468,6 @@
friend class ApiError;
friend class Array;
- friend class Bigint;
friend class BoundedType;
friend class Class;
friend class Closure;
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index dc70397..e3d9d82 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -79,14 +79,6 @@
case Dart_CObject_kInt64:
EXPECT_EQ(first->value.as_int64, second->value.as_int64);
break;
- case Dart_CObject_kBigint: {
- char* first_hex_value = TestCase::BigintToHexValue(first);
- char* second_hex_value = TestCase::BigintToHexValue(second);
- EXPECT_STREQ(first_hex_value, second_hex_value);
- free(first_hex_value);
- free(second_hex_value);
- break;
- }
case Dart_CObject_kDouble:
EXPECT_EQ(first->value.as_double, second->value.as_double);
break;
@@ -392,97 +384,6 @@
delete message;
}
-TEST_CASE(SerializeBigint) {
- if (Bigint::IsDisabled()) {
- return;
- }
- // Write snapshot with object content.
- const char* cstr = "0x270FFFFFFFFFFFFFD8F0";
- const String& str = String::Handle(String::New(cstr));
- Bigint& bigint = Bigint::Handle();
- bigint ^= Integer::NewCanonical(str);
- MessageWriter writer(true);
- Message* message =
- writer.WriteMessage(bigint, ILLEGAL_PORT, Message::kNormalPriority);
-
- // Read object back from the snapshot.
- MessageSnapshotReader reader(message, thread);
- Bigint& obj = Bigint::Handle();
- obj ^= reader.ReadObject();
-
- Zone* zone = Thread::Current()->zone();
- EXPECT_STREQ(bigint.ToHexCString(zone), obj.ToHexCString(zone));
-
- // Read object back from the snapshot into a C structure.
- ApiNativeScope scope;
- ApiMessageReader api_reader(message);
- Dart_CObject* root = api_reader.ReadMessage();
- EXPECT_NOTNULL(root);
- EXPECT_EQ(Dart_CObject_kBigint, root->type);
- char* hex_value = TestCase::BigintToHexValue(root);
- EXPECT_STREQ(cstr, hex_value);
- free(hex_value);
- CheckEncodeDecodeMessage(root);
-
- delete message;
-}
-
-Dart_CObject* SerializeAndDeserializeBigint(const Bigint& bigint) {
- // Write snapshot with object content.
- MessageWriter writer(true);
- Message* message =
- writer.WriteMessage(bigint, ILLEGAL_PORT, Message::kNormalPriority);
-
- {
- // Switch to a regular zone, where VM handle allocation is allowed.
- Thread* thread = Thread::Current();
- StackZone zone(thread);
- // Read object back from the snapshot.
- MessageSnapshotReader reader(message, thread);
- Bigint& serialized_bigint = Bigint::Handle();
- serialized_bigint ^= reader.ReadObject();
- const char* str1 = bigint.ToHexCString(thread->zone());
- const char* str2 = serialized_bigint.ToHexCString(thread->zone());
- EXPECT_STREQ(str1, str2);
- }
-
- // Read object back from the snapshot into a C structure.
- ApiMessageReader api_reader(message);
- Dart_CObject* root = api_reader.ReadMessage();
- // Bigint not supported.
- EXPECT_NOTNULL(root);
- CheckEncodeDecodeMessage(root);
-
- delete message;
-
- return root;
-}
-
-void CheckBigint(const char* bigint_value) {
- ApiNativeScope scope;
- StackZone zone(Thread::Current());
- Bigint& bigint = Bigint::Handle();
- bigint ^= Bigint::NewFromCString(bigint_value);
- Dart_CObject* bigint_cobject = SerializeAndDeserializeBigint(bigint);
- EXPECT_EQ(Dart_CObject_kBigint, bigint_cobject->type);
- char* hex_value = TestCase::BigintToHexValue(bigint_cobject);
- EXPECT_STREQ(bigint_value, hex_value);
- free(hex_value);
-}
-
-TEST_CASE(SerializeBigint2) {
- if (Bigint::IsDisabled()) {
- return;
- }
- CheckBigint("0x0");
- CheckBigint("0x1");
- CheckBigint("-0x1");
- CheckBigint("0x11111111111111111111");
- CheckBigint("-0x11111111111111111111");
- CheckBigint("0x9876543210987654321098765432109876543210");
- CheckBigint("-0x9876543210987654321098765432109876543210");
-}
-
#define TEST_ROUND_TRIP_IDENTICAL(object) \
{ \
MessageWriter writer(true); \
@@ -1891,7 +1792,7 @@
}
VM_UNIT_TEST_CASE(DartGeneratedMessages) {
- static const char* kCustomIsolateScriptCommonChars =
+ static const char* kCustomIsolateScriptChars =
"final int kArrayLength = 10;\n"
"getSmi() {\n"
" return 42;\n"
@@ -1920,34 +1821,18 @@
"getList() {\n"
" return new List(kArrayLength);\n"
"}\n";
- static const char* kCustomIsolateScriptBigintChars =
- "getBigint() {\n"
- " return -0x424242424242424242424242424242424242;\n"
- "}\n";
TestCase::CreateTestIsolate();
Isolate* isolate = Isolate::Current();
EXPECT(isolate != NULL);
Dart_EnterScope();
- const char* scriptChars = kCustomIsolateScriptCommonChars;
- if (!Bigint::IsDisabled()) {
- scriptChars = OS::SCreate(Thread::Current()->zone(), "%s%s", scriptChars,
- kCustomIsolateScriptBigintChars);
- }
-
- Dart_Handle lib = TestCase::LoadTestScript(scriptChars, NULL);
+ Dart_Handle lib = TestCase::LoadTestScript(kCustomIsolateScriptChars, NULL);
EXPECT_VALID(lib);
Dart_Handle smi_result;
smi_result = Dart_Invoke(lib, NewString("getSmi"), 0, NULL);
EXPECT_VALID(smi_result);
- Dart_Handle bigint_result = NULL;
- if (!Bigint::IsDisabled()) {
- bigint_result = Dart_Invoke(lib, NewString("getBigint"), 0, NULL);
- EXPECT_VALID(bigint_result);
- }
-
Dart_Handle ascii_string_result;
ascii_string_result = Dart_Invoke(lib, NewString("getAsciiString"), 0, NULL);
EXPECT_VALID(ascii_string_result);
@@ -2012,26 +1897,6 @@
CheckEncodeDecodeMessage(root);
delete message;
}
- if (!Bigint::IsDisabled()) {
- StackZone zone(thread);
- Bigint& bigint = Bigint::Handle();
- bigint ^= Api::UnwrapHandle(bigint_result);
- MessageWriter writer(false);
- Message* message =
- writer.WriteMessage(bigint, ILLEGAL_PORT, Message::kNormalPriority);
-
- // Read object back from the snapshot into a C structure.
- ApiNativeScope scope;
- ApiMessageReader api_reader(message);
- Dart_CObject* root = api_reader.ReadMessage();
- EXPECT_NOTNULL(root);
- EXPECT_EQ(Dart_CObject_kBigint, root->type);
- char* hex_value = TestCase::BigintToHexValue(root);
- EXPECT_STREQ("-0x424242424242424242424242424242424242", hex_value);
- free(hex_value);
- CheckEncodeDecodeMessage(root);
- delete message;
- }
CheckString(ascii_string_result, "Hello, world!");
CheckString(non_ascii_string_result, "Blåbærgrød");
CheckString(non_bmp_string_result,
@@ -2387,7 +2252,7 @@
VM_UNIT_TEST_CASE(DartGeneratedListMessagesWithBackref) {
const int kArrayLength = 10;
- static const char* kScriptCommonChars =
+ static const char* kScriptChars =
"import 'dart:typed_data';\n"
"final int kArrayLength = 10;\n"
"getStringList() {\n"
@@ -2437,26 +2302,13 @@
" }\n"
" return list;\n"
"}\n";
- static const char* kScriptBigintChars =
- "getBigintList() {\n"
- " var bigint = 0x1234567890123456789012345678901234567890;\n"
- " var list = new List(kArrayLength);\n"
- " for (var i = 0; i < kArrayLength; i++) list[i] = bigint;\n"
- " return list;\n"
- "}\n";
TestCase::CreateTestIsolate();
Thread* thread = Thread::Current();
EXPECT(thread->isolate() != NULL);
Dart_EnterScope();
- const char* scriptChars = kScriptCommonChars;
- if (!Bigint::IsDisabled()) {
- scriptChars =
- OS::SCreate(thread->zone(), "%s%s", scriptChars, kScriptBigintChars);
- }
-
- Dart_Handle lib = TestCase::LoadTestScript(scriptChars, NULL);
+ Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
EXPECT_VALID(lib);
{
@@ -2495,24 +2347,6 @@
}
delete message;
}
- if (!Bigint::IsDisabled()) {
- // Generate a list of bigints from Dart code.
- Message* message = GetSerialized(lib, "getBigintList");
- ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message);
- EXPECT_NOTNULL(root);
- EXPECT_EQ(Dart_CObject_kArray, root->type);
- EXPECT_EQ(kArrayLength, root->value.as_array.length);
- for (int i = 0; i < kArrayLength; i++) {
- Dart_CObject* element = root->value.as_array.values[i];
- EXPECT_EQ(root->value.as_array.values[0], element);
- EXPECT_EQ(Dart_CObject_kBigint, element->type);
- char* hex_value = TestCase::BigintToHexValue(element);
- EXPECT_STREQ("0x1234567890123456789012345678901234567890", hex_value);
- free(hex_value);
- }
- delete message;
- }
{
// Generate a list of doubles from Dart code.
Message* message = GetSerialized(lib, "getDoubleList");
@@ -2620,7 +2454,7 @@
VM_UNIT_TEST_CASE(DartGeneratedArrayLiteralMessagesWithBackref) {
const int kArrayLength = 10;
- static const char* kScriptCommonChars =
+ static const char* kScriptChars =
"import 'dart:typed_data';\n"
"final int kArrayLength = 10;\n"
"getStringList() {\n"
@@ -2676,25 +2510,13 @@
" }\n"
" return list;\n"
"}\n";
- static const char* kScriptBigintChars =
- "getBigintList() {\n"
- " var bigint = 0x1234567890123456789012345678901234567890;\n"
- " var list = [bigint, bigint, bigint, bigint, bigint,\n"
- " bigint, bigint, bigint, bigint, bigint];\n"
- " return list;\n"
- "}\n";
TestCase::CreateTestIsolate();
Thread* thread = Thread::Current();
EXPECT(thread->isolate() != NULL);
Dart_EnterScope();
- const char* scriptChars = kScriptCommonChars;
- if (!Bigint::IsDisabled()) {
- scriptChars =
- OS::SCreate(thread->zone(), "%s%s", scriptChars, kScriptBigintChars);
- }
- Dart_Handle lib = TestCase::LoadTestScript(scriptChars, NULL);
+ Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
EXPECT_VALID(lib);
{
@@ -2733,24 +2555,6 @@
}
delete message;
}
- if (!Bigint::IsDisabled()) {
- // Generate a list of bigints from Dart code.
- Message* message = GetSerialized(lib, "getBigintList");
- ApiNativeScope scope;
- Dart_CObject* root = GetDeserialized(message);
- EXPECT_NOTNULL(root);
- EXPECT_EQ(Dart_CObject_kArray, root->type);
- EXPECT_EQ(kArrayLength, root->value.as_array.length);
- for (int i = 0; i < kArrayLength; i++) {
- Dart_CObject* element = root->value.as_array.values[i];
- EXPECT_EQ(root->value.as_array.values[0], element);
- EXPECT_EQ(Dart_CObject_kBigint, element->type);
- char* hex_value = TestCase::BigintToHexValue(element);
- EXPECT_STREQ("0x1234567890123456789012345678901234567890", hex_value);
- free(hex_value);
- }
- delete message;
- }
{
// Generate a list of doubles from Dart code.
Message* message = GetSerialized(lib, "getDoubleList");
diff --git a/runtime/vm/snapshot_test.dart b/runtime/vm/snapshot_test.dart
index 8c0d8d9..a8e037d 100644
--- a/runtime/vm/snapshot_test.dart
+++ b/runtime/vm/snapshot_test.dart
@@ -1332,6 +1332,7 @@
Expect.equals(true, identical(replyObject[0], replyObject[2][2]));
Expect.equals(true, identical(replyObject[2], replyObject[4][0]));
Expect.equals(true, identical(replyObject[0][0], replyObject[0][2]));
+ // TODO(alexmarkov): Revise this comment.
// Bigint literals are not canonicalized so do a == check.
Expect.equals(true, replyObject[0][3] == replyObject[4][4]);
});
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index 578129c..9cec45e 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -15,12 +15,43 @@
#include "vm/parser.h"
#include "vm/raw_object.h"
#include "vm/reusable_handles.h"
+#include "vm/scopes.h"
#include "vm/stub_code.h"
#include "vm/visitor.h"
namespace dart {
+intptr_t FrameSlotForVariable(const LocalVariable* variable) {
+ ASSERT(!variable->is_captured());
+ return FrameSlotForVariableIndex(variable->index().value());
+}
+
+intptr_t FrameOffsetInBytesForVariable(const LocalVariable* variable) {
+ return FrameSlotForVariable(variable) * kWordSize;
+}
+
+intptr_t FrameSlotForVariableIndex(intptr_t variable_index) {
+ // Variable indices are:
+ // [1, 2, ..., M] for the M parameters.
+ // [0, -1, -2, ... -(N-1)] for the N [LocalVariable]s
+ // See (runtime/vm/scopes.h)
+ return variable_index <= 0 ? (variable_index + kFirstLocalSlotFromFp)
+ : (variable_index + kParamEndSlotFromFp);
+}
+
+intptr_t VariableIndexForFrameSlot(intptr_t frame_slot) {
+ if (frame_slot <= kFirstLocalSlotFromFp) {
+ return frame_slot - kFirstLocalSlotFromFp;
+ } else {
+ ASSERT(frame_slot > kParamEndSlotFromFp);
+ return frame_slot - kParamEndSlotFromFp;
+ }
+}
+
bool StackFrame::IsStubFrame() const {
+ if (is_interpreted()) {
+ return false;
+ }
ASSERT(!(IsEntryFrame() || IsExitFrame()));
#if !defined(HOST_OS_WINDOWS) && !defined(HOST_OS_FUCHSIA)
// On Windows and Fuchsia, the profiler calls this from a separate thread
@@ -116,6 +147,9 @@
map = code.GetStackMap(pc() - start, &maps, &map);
if (!map.IsNull()) {
#if !defined(TARGET_ARCH_DBC)
+ if (is_interpreted()) {
+ UNIMPLEMENTED();
+ }
RawObject** first = reinterpret_cast<RawObject**>(sp());
RawObject** last = reinterpret_cast<RawObject**>(
fp() + (kFirstLocalSlotFromFp * kWordSize));
@@ -204,9 +238,10 @@
#if !defined(TARGET_ARCH_DBC)
// For normal unoptimized Dart frames and Stub frames each slot
// between the first and last included are tagged objects.
- RawObject** first = reinterpret_cast<RawObject**>(sp());
+ RawObject** first = reinterpret_cast<RawObject**>(
+ is_interpreted() ? fp() + (kKBCFirstObjectSlotFromFp * kWordSize) : sp());
RawObject** last = reinterpret_cast<RawObject**>(
- fp() + (kFirstObjectSlotFromFp * kWordSize));
+ is_interpreted() ? sp() : fp() + (kFirstObjectSlotFromFp * kWordSize));
#else
// On DBC stack grows upwards: fp() <= sp().
RawObject** first = reinterpret_cast<RawObject**>(
@@ -250,8 +285,10 @@
}
RawCode* StackFrame::UncheckedGetCodeObject() const {
- return *(
- reinterpret_cast<RawCode**>(fp() + (kPcMarkerSlotFromFp * kWordSize)));
+ return *(reinterpret_cast<RawCode**>(
+ fp() +
+ ((is_interpreted() ? kKBCPcMarkerSlotFromFp : kPcMarkerSlotFromFp) *
+ kWordSize)));
}
bool StackFrame::FindExceptionHandler(Thread* thread,
@@ -332,14 +369,23 @@
ASSERT(thread_ != NULL);
uword exit_marker = thread_->top_exit_frame_info();
frames_.fp_ = exit_marker;
+#if defined(DART_USE_INTERPRETER)
+ frames_.CheckIfInterpreted(exit_marker);
+#endif
}
void StackFrameIterator::SetupNextExitFrameData() {
- uword exit_address = entry_.fp() + (kExitLinkSlotFromEntryFp * kWordSize);
+ uword exit_address =
+ entry_.fp() + ((entry_.is_interpreted() ? kKBCExitLinkSlotFromEntryFp
+ : kExitLinkSlotFromEntryFp) *
+ kWordSize);
uword exit_marker = *reinterpret_cast<uword*>(exit_address);
frames_.fp_ = exit_marker;
frames_.sp_ = 0;
frames_.pc_ = 0;
+#if defined(DART_USE_INTERPRETER)
+ frames_.CheckIfInterpreted(exit_marker);
+#endif
}
// Tell MemorySanitizer that generated code initializes part of the stack.
@@ -379,6 +425,9 @@
frames_.fp_ = last_fp;
frames_.sp_ = 0;
frames_.pc_ = 0;
+#if defined(DART_USE_INTERPRETER)
+ frames_.CheckIfInterpreted(last_fp);
+#endif
}
#if !defined(TARGET_ARCH_DBC)
@@ -399,6 +448,9 @@
frames_.fp_ = fp;
frames_.sp_ = sp;
frames_.pc_ = pc;
+#if defined(DART_USE_INTERPRETER)
+ frames_.CheckIfInterpreted(fp);
+#endif
}
#endif
@@ -425,8 +477,10 @@
// Iteration starts from an exit frame given by its fp.
current_frame_ = NextExitFrame();
} else if (*(reinterpret_cast<uword*>(
- frames_.fp_ + (kSavedCallerFpSlotFromFp * kWordSize))) ==
- 0) {
+ frames_.fp_ +
+ ((frames_.is_interpreted() ? kKBCSavedCallerFpSlotFromFp
+ : kSavedCallerFpSlotFromFp) *
+ kWordSize))) == 0) {
// Iteration starts from an entry frame given by its fp, sp, and pc.
current_frame_ = NextEntryFrame();
} else {
@@ -462,6 +516,16 @@
return current_frame_;
}
+#if defined(DART_USE_INTERPRETER)
+void StackFrameIterator::FrameSetIterator::CheckIfInterpreted(
+ uword exit_marker) {
+ // TODO(regis): Once the interpreter shares the native stack, we may rely on
+ // a new thread vm_tag to identify an interpreter frame.
+ Interpreter* interpreter = thread_->isolate()->interpreter();
+ is_interpreted_ = (interpreter != NULL) && interpreter->HasFrame(exit_marker);
+}
+#endif
+
StackFrame* StackFrameIterator::FrameSetIterator::NextFrame(bool validate) {
StackFrame* frame;
ASSERT(HasNext());
@@ -469,9 +533,15 @@
frame->sp_ = sp_;
frame->fp_ = fp_;
frame->pc_ = pc_;
+#if defined(DART_USE_INTERPRETER)
+ frame->is_interpreted_ = is_interpreted_;
+#endif
sp_ = frame->GetCallerSp();
fp_ = frame->GetCallerFp();
pc_ = frame->GetCallerPc();
+#if defined(DART_USE_INTERPRETER)
+ ASSERT(is_interpreted_ == frame->is_interpreted_);
+#endif
ASSERT(!validate || frame->IsValid());
return frame;
}
@@ -480,9 +550,15 @@
exit_.sp_ = frames_.sp_;
exit_.fp_ = frames_.fp_;
exit_.pc_ = frames_.pc_;
+#if defined(DART_USE_INTERPRETER)
+ exit_.is_interpreted_ = frames_.is_interpreted_;
+#endif
frames_.sp_ = exit_.GetCallerSp();
frames_.fp_ = exit_.GetCallerFp();
frames_.pc_ = exit_.GetCallerPc();
+#if defined(DART_USE_INTERPRETER)
+ ASSERT(frames_.is_interpreted_ == exit_.is_interpreted_);
+#endif
ASSERT(!validate_ || exit_.IsValid());
return &exit_;
}
@@ -492,6 +568,9 @@
entry_.sp_ = frames_.sp_;
entry_.fp_ = frames_.fp_;
entry_.pc_ = frames_.pc_;
+#if defined(DART_USE_INTERPRETER)
+ entry_.is_interpreted_ = frames_.is_interpreted_;
+#endif
SetupNextExitFrameData(); // Setup data for next exit frame in chain.
ASSERT(!validate_ || entry_.IsValid());
return &entry_;
diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h
index cfc3d71..8071323 100644
--- a/runtime/vm/stack_frame.h
+++ b/runtime/vm/stack_frame.h
@@ -6,7 +6,9 @@
#define RUNTIME_VM_STACK_FRAME_H_
#include "vm/allocation.h"
+#include "vm/interpreter.h"
#include "vm/object.h"
+#include "vm/stack_frame_kbc.h"
#include "vm/stub_code.h"
#if defined(TARGET_ARCH_IA32)
@@ -28,6 +30,23 @@
// Forward declarations.
class ObjectPointerVisitor;
class RawContext;
+class LocalVariable;
+
+// Returns the FP-relative index where [variable] can be found (assumes
+// [variable] is not captured), in words.
+intptr_t FrameSlotForVariable(const LocalVariable* variable);
+
+// Returns the FP-relative index where [variable] can be found (assumes
+// [variable] is not captured), in bytes.
+intptr_t FrameOffsetInBytesForVariable(const LocalVariable* variable);
+
+// Returns the FP-relative index where [variable_index] can be found (assumes
+// [variable_index] comes from a [LocalVariable::index()], which is not
+// captured).
+intptr_t FrameSlotForVariableIndex(intptr_t variable_index);
+
+// Returns the variable index from a FP-relative index.
+intptr_t VariableIndexForFrameSlot(intptr_t frame_slot);
// Generic stack frame.
class StackFrame : public ValueObject {
@@ -41,6 +60,7 @@
// The pool pointer is not implemented on all architectures.
static int SavedCallerPpSlotFromFp() {
+ // Never called on an interpreter frame.
if (kSavedCallerPpSlotFromFp != kSavedCallerFpSlotFromFp) {
return kSavedCallerPpSlotFromFp;
}
@@ -49,17 +69,20 @@
}
uword IsMarkedForLazyDeopt() const {
+ ASSERT(!is_interpreted());
uword raw_pc =
*reinterpret_cast<uword*>(sp() + (kSavedPcSlotFromSp * kWordSize));
return raw_pc == StubCode::DeoptimizeLazyFromReturn_entry()->EntryPoint();
}
void MarkForLazyDeopt() {
+ ASSERT(!is_interpreted());
set_pc(StubCode::DeoptimizeLazyFromReturn_entry()->EntryPoint());
}
void UnmarkForLazyDeopt() {
// If this frame was marked for lazy deopt, pc_ was computed to be the
// original return address using the pending deopts table in GetCallerPc.
// Write this value back into the frame.
+ ASSERT(!is_interpreted());
uword original_pc = pc();
ASSERT(original_pc !=
StubCode::DeoptimizeLazyFromReturn_entry()->EntryPoint());
@@ -67,13 +90,17 @@
}
void set_pc(uword value) {
- *reinterpret_cast<uword*>(sp() + (kSavedPcSlotFromSp * kWordSize)) = value;
+ *reinterpret_cast<uword*>(sp() + ((is_interpreted() ? kKBCSavedPcSlotFromSp
+ : kSavedPcSlotFromSp) *
+ kWordSize)) = value;
pc_ = value;
}
void set_pc_marker(RawCode* code) {
- *reinterpret_cast<RawCode**>(fp() + (kPcMarkerSlotFromFp * kWordSize)) =
- code;
+ *reinterpret_cast<RawCode**>(
+ fp() +
+ ((is_interpreted() ? kKBCPcMarkerSlotFromFp : kPcMarkerSlotFromFp) *
+ kWordSize)) = code;
}
// Visit objects in the frame.
@@ -92,6 +119,11 @@
virtual bool IsStubFrame() const;
virtual bool IsEntryFrame() const { return false; }
virtual bool IsExitFrame() const { return false; }
+#if defined(DART_USE_INTERPRETER)
+ virtual bool is_interpreted() const { return is_interpreted_; }
+#else
+ virtual bool is_interpreted() const { return false; }
+#endif
RawFunction* LookupDartFunction() const;
RawCode* LookupDartCode() const;
@@ -105,7 +137,13 @@
protected:
explicit StackFrame(Thread* thread)
- : fp_(0), sp_(0), pc_(0), thread_(thread) {}
+#if defined(DART_USE_INTERPRETER)
+ : fp_(0), sp_(0), pc_(0), thread_(thread), is_interpreted_(false) {
+ }
+#else
+ : fp_(0), sp_(0), pc_(0), thread_(thread) {
+ }
+#endif
// Name of the frame, used for generic frame printing functionality.
virtual const char* GetName() const {
@@ -120,16 +158,24 @@
RawCode* GetCodeObject() const;
RawCode* UncheckedGetCodeObject() const;
- uword GetCallerSp() const { return fp() + (kCallerSpSlotFromFp * kWordSize); }
+ uword GetCallerSp() const {
+ return fp() +
+ ((is_interpreted() ? kKBCCallerSpSlotFromFp : kCallerSpSlotFromFp) *
+ kWordSize);
+ }
uword GetCallerFp() const {
- return *(reinterpret_cast<uword*>(fp() +
- (kSavedCallerFpSlotFromFp * kWordSize)));
+ return *(reinterpret_cast<uword*>(
+ fp() + ((is_interpreted() ? kKBCSavedCallerFpSlotFromFp
+ : kSavedCallerFpSlotFromFp) *
+ kWordSize)));
}
uword GetCallerPc() const {
uword raw_pc = *(reinterpret_cast<uword*>(
- fp() + (kSavedCallerPcSlotFromFp * kWordSize)));
+ fp() + ((is_interpreted() ? kKBCSavedCallerPcSlotFromFp
+ : kSavedCallerPcSlotFromFp) *
+ kWordSize)));
ASSERT(raw_pc != StubCode::DeoptimizeLazyFromThrow_entry()->EntryPoint());
if (raw_pc == StubCode::DeoptimizeLazyFromReturn_entry()->EntryPoint()) {
return isolate()->FindPendingDeopt(GetCallerFp());
@@ -141,6 +187,9 @@
uword sp_;
uword pc_;
Thread* thread_;
+#if defined(DART_USE_INTERPRETER)
+ bool is_interpreted_;
+#endif
// The iterators FrameSetIterator and StackFrameIterator set the private
// fields fp_ and sp_ when they return the respective frame objects.
@@ -176,7 +225,9 @@
// dart code.
class EntryFrame : public StackFrame {
public:
- bool IsValid() const { return StubCode::InInvocationStub(pc()); }
+ bool IsValid() const {
+ return StubCode::InInvocationStub(pc(), is_interpreted());
+ }
bool IsDartFrame(bool validate = true) const { return false; }
bool IsStubFrame() const { return false; }
bool IsEntryFrame() const { return true; }
@@ -245,22 +296,41 @@
if (fp_ == 0) {
return false;
}
- const uword pc =
- *(reinterpret_cast<uword*>(sp_ + (kSavedPcSlotFromSp * kWordSize)));
- return !StubCode::InInvocationStub(pc);
+ const uword pc = *(reinterpret_cast<uword*>(
+ sp_ +
+ ((is_interpreted() ? kKBCSavedPcSlotFromSp : kSavedPcSlotFromSp) *
+ kWordSize)));
+ return !StubCode::InInvocationStub(pc, is_interpreted());
}
// Get next non entry/exit frame in the set (assumes a next frame exists).
StackFrame* NextFrame(bool validate);
private:
+#if defined(DART_USE_INTERPRETER)
+ explicit FrameSetIterator(Thread* thread)
+ : fp_(0),
+ sp_(0),
+ pc_(0),
+ stack_frame_(thread),
+ thread_(thread),
+ is_interpreted_(false) {}
+ bool is_interpreted() const { return is_interpreted_; }
+ void CheckIfInterpreted(uword exit_marker);
+#else
explicit FrameSetIterator(Thread* thread)
: fp_(0), sp_(0), pc_(0), stack_frame_(thread), thread_(thread) {}
+ bool is_interpreted() const { return false; }
+#endif
+
uword fp_;
uword sp_;
uword pc_;
StackFrame stack_frame_; // Singleton frame returned by NextFrame().
Thread* thread_;
+#if defined(DART_USE_INTERPRETER)
+ bool is_interpreted_;
+#endif
friend class StackFrameIterator;
DISALLOW_COPY_AND_ASSIGN(FrameSetIterator);
@@ -281,6 +351,10 @@
void SetupLastExitFrameData();
void SetupNextExitFrameData();
+#if defined(DART_USE_INTERPRETER)
+ void CheckInterpreterExitFrame(uword exit_marker);
+#endif
+
bool validate_; // Validate each frame as we traverse the frames.
EntryFrame entry_; // Singleton entry frame returned by NextEntryFrame().
ExitFrame exit_; // Singleton exit frame returned by NextExitFrame().
diff --git a/runtime/vm/stack_frame_dbc.h b/runtime/vm/stack_frame_dbc.h
index 64a7cb3..475d9b7 100644
--- a/runtime/vm/stack_frame_dbc.h
+++ b/runtime/vm/stack_frame_dbc.h
@@ -58,7 +58,6 @@
DART_FORCE_INLINE static intptr_t LocalVarIndex(intptr_t fp_offset,
intptr_t var_index) {
- ASSERT(var_index != 0);
if (var_index > 0) {
return fp_offset - var_index;
} else {
diff --git a/runtime/vm/stack_frame_kbc.h b/runtime/vm/stack_frame_kbc.h
index c4e81b5..73ca527 100644
--- a/runtime/vm/stack_frame_kbc.h
+++ b/runtime/vm/stack_frame_kbc.h
@@ -42,7 +42,6 @@
static const int kKBCLastFixedObjectSlotFromFp = -3;
static const int kKBCSavedCallerFpSlotFromFp = -1;
-static const int kKBCSavedCallerPpSlotFromFp = kKBCSavedCallerFpSlotFromFp;
static const int kKBCSavedCallerPcSlotFromFp = -2;
static const int kKBCCallerSpSlotFromFp = -kKBCDartFrameFixedSize - 1;
static const int kKBCPcMarkerSlotFromFp = -3;
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index a664808..05baaee 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -86,12 +86,27 @@
return StubCode::AsynchronousGapMarker_entry() != NULL;
}
-bool StubCode::InInvocationStub(uword pc) {
+bool StubCode::InInvocationStub(uword pc, bool is_interpreted_frame) {
#if !defined(TARGET_ARCH_DBC)
ASSERT(HasBeenInitialized());
+#if defined(DART_USE_INTERPRETER)
+ // Recognize special marker set up by interpreter in entry frame.
+ if (is_interpreted_frame && (pc & 2) != 0) {
+ return true;
+ }
+ {
+ uword entry = StubCode::InvokeDartCodeFromBytecode_entry()->EntryPoint();
+ uword size = StubCode::InvokeDartCodeFromBytecodeSize();
+ if ((pc >= entry) && (pc < (entry + size))) {
+ return true;
+ }
+ }
+#endif
uword entry = StubCode::InvokeDartCode_entry()->EntryPoint();
uword size = StubCode::InvokeDartCodeSize();
return (pc >= entry) && (pc < (entry + size));
+#elif defined(DART_USE_INTERPRETER)
+#error "Simultaneous usage of simulator and interpreter not yet supported."
#else
// On DBC we use a special marker PC to signify entry frame because there is
// no such thing as invocation stub.
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index b6c1c3c..1f836fb 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -147,7 +147,7 @@
// Check if specified pc is in the dart invocation stub used for
// transitioning into dart code.
- static bool InInvocationStub(uword pc);
+ static bool InInvocationStub(uword pc, bool is_interpreted_frame);
// Check if the specified pc is in the jump to frame stub.
static bool InJumpToFrameStub(uword pc);
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index 6aa0494..70e9cb6 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -2177,13 +2177,12 @@
// checks for boxed numbers.
// LR: return address.
// Return Zero condition flag set if equal.
-// Note: A Mint cannot contain a value that would fit in Smi, a Bigint
-// cannot contain a value that fits in Mint or Smi.
+// Note: A Mint cannot contain a value that would fit in Smi.
static void GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
const Register left,
const Register right,
const Register temp) {
- Label reference_compare, done, check_mint, check_bigint;
+ Label reference_compare, done, check_mint;
// If any of the arguments is Smi do reference compare.
__ tst(left, Operand(kSmiTagMask));
__ b(&reference_compare, EQ);
@@ -2208,7 +2207,7 @@
__ Bind(&check_mint);
__ CompareClassId(left, kMintCid, temp);
- __ b(&check_bigint, NE);
+ __ b(&reference_compare, NE);
__ CompareClassId(right, kMintCid, temp);
__ b(&done, NE);
__ ldr(temp, FieldAddress(left, Mint::value_offset() + 0 * kWordSize));
@@ -2220,20 +2219,6 @@
__ cmp(temp, Operand(IP));
__ b(&done);
- __ Bind(&check_bigint);
- __ CompareClassId(left, kBigintCid, temp);
- __ b(&reference_compare, NE);
- __ CompareClassId(right, kBigintCid, temp);
- __ b(&done, NE);
- __ EnterStubFrame();
- __ ReserveAlignedFrameSpace(2 * kWordSize);
- __ stm(IA, SP, (1 << R0) | (1 << R1));
- __ CallRuntime(kBigintCompareRuntimeEntry, 2);
- // Result in R0, 0 means equal.
- __ LeaveStubFrame();
- __ cmp(R0, Operand(0));
- __ b(&done);
-
__ Bind(&reference_compare);
__ cmp(left, Operand(right));
__ Bind(&done);
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index 5d07eb1..b7c6f15 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -2227,12 +2227,11 @@
// checks for boxed numbers.
// Left and right are pushed on stack.
// Return Zero condition flag set if equal.
-// Note: A Mint cannot contain a value that would fit in Smi, a Bigint
-// cannot contain a value that fits in Mint or Smi.
+// Note: A Mint cannot contain a value that would fit in Smi.
static void GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
const Register left,
const Register right) {
- Label reference_compare, done, check_mint, check_bigint;
+ Label reference_compare, done, check_mint;
// If any of the arguments is Smi do reference compare.
__ BranchIfSmi(left, &reference_compare);
__ BranchIfSmi(right, &reference_compare);
@@ -2250,27 +2249,11 @@
__ Bind(&check_mint);
__ CompareClassId(left, kMintCid);
- __ b(&check_bigint, NE);
+ __ b(&reference_compare, NE);
__ CompareClassId(right, kMintCid);
__ b(&done, NE);
__ LoadFieldFromOffset(left, left, Mint::value_offset());
__ LoadFieldFromOffset(right, right, Mint::value_offset());
- __ b(&reference_compare);
-
- __ Bind(&check_bigint);
- __ CompareClassId(left, kBigintCid);
- __ b(&reference_compare, NE);
- __ CompareClassId(right, kBigintCid);
- __ b(&done, NE);
- __ EnterStubFrame();
- __ ReserveAlignedFrameSpace(2 * kWordSize);
- __ StoreToOffset(left, SP, 0 * kWordSize);
- __ StoreToOffset(right, SP, 1 * kWordSize);
- __ CallRuntime(kBigintCompareRuntimeEntry, 2);
- // Result in R0, 0 means equal.
- __ LeaveStubFrame();
- __ cmp(R0, Operand(0));
- __ b(&done);
__ Bind(&reference_compare);
__ CompareRegisters(left, right);
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index ae5b070..bae80ce 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -1903,13 +1903,12 @@
// Does identical check (object references are equal or not equal) with special
// checks for boxed numbers.
// Return ZF set.
-// Note: A Mint cannot contain a value that would fit in Smi, a Bigint
-// cannot contain a value that fits in Mint or Smi.
+// Note: A Mint cannot contain a value that would fit in Smi.
static void GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
const Register left,
const Register right,
const Register temp) {
- Label reference_compare, done, check_mint, check_bigint;
+ Label reference_compare, done, check_mint;
// If any of the arguments is Smi do reference compare.
__ testl(left, Immediate(kSmiTagMask));
__ j(ZERO, &reference_compare, Assembler::kNearJump);
@@ -1932,7 +1931,7 @@
__ Bind(&check_mint);
__ CompareClassId(left, kMintCid, temp);
- __ j(NOT_EQUAL, &check_bigint, Assembler::kNearJump);
+ __ j(NOT_EQUAL, &reference_compare, Assembler::kNearJump);
__ CompareClassId(right, kMintCid, temp);
__ j(NOT_EQUAL, &done, Assembler::kNearJump);
__ movl(temp, FieldAddress(left, Mint::value_offset() + 0 * kWordSize));
@@ -1942,21 +1941,6 @@
__ cmpl(temp, FieldAddress(right, Mint::value_offset() + 1 * kWordSize));
__ jmp(&done, Assembler::kNearJump);
- __ Bind(&check_bigint);
- __ CompareClassId(left, kBigintCid, temp);
- __ j(NOT_EQUAL, &reference_compare, Assembler::kNearJump);
- __ CompareClassId(right, kBigintCid, temp);
- __ j(NOT_EQUAL, &done, Assembler::kNearJump);
- __ EnterFrame(0);
- __ ReserveAlignedFrameSpace(2 * kWordSize);
- __ movl(Address(ESP, 1 * kWordSize), left);
- __ movl(Address(ESP, 0 * kWordSize), right);
- __ CallRuntime(kBigintCompareRuntimeEntry, 2);
- // Result in EAX, 0 means equal.
- __ LeaveFrame();
- __ cmpl(EAX, Immediate(0));
- __ jmp(&done);
-
__ Bind(&reference_compare);
__ cmpl(left, right);
__ Bind(&done);
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index c5d5151..532a4ea 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -2336,12 +2336,11 @@
// checks for boxed numbers.
// Left and right are pushed on stack.
// Return ZF set.
-// Note: A Mint cannot contain a value that would fit in Smi, a Bigint
-// cannot contain a value that fits in Mint or Smi.
+// Note: A Mint cannot contain a value that would fit in Smi.
static void GenerateIdenticalWithNumberCheckStub(Assembler* assembler,
const Register left,
const Register right) {
- Label reference_compare, done, check_mint, check_bigint;
+ Label reference_compare, done, check_mint;
// If any of the arguments is Smi do reference compare.
__ testq(left, Immediate(kSmiTagMask));
__ j(ZERO, &reference_compare);
@@ -2361,28 +2360,13 @@
__ Bind(&check_mint);
__ CompareClassId(left, kMintCid);
- __ j(NOT_EQUAL, &check_bigint, Assembler::kNearJump);
+ __ j(NOT_EQUAL, &reference_compare, Assembler::kNearJump);
__ CompareClassId(right, kMintCid);
__ j(NOT_EQUAL, &done, Assembler::kFarJump);
__ movq(left, FieldAddress(left, Mint::value_offset()));
__ cmpq(left, FieldAddress(right, Mint::value_offset()));
__ jmp(&done, Assembler::kFarJump);
- __ Bind(&check_bigint);
- __ CompareClassId(left, kBigintCid);
- __ j(NOT_EQUAL, &reference_compare, Assembler::kFarJump);
- __ CompareClassId(right, kBigintCid);
- __ j(NOT_EQUAL, &done, Assembler::kFarJump);
- __ EnterStubFrame();
- __ ReserveAlignedFrameSpace(0);
- __ movq(CallingConventions::kArg1Reg, left);
- __ movq(CallingConventions::kArg2Reg, right);
- __ CallRuntime(kBigintCompareRuntimeEntry, 2);
- // Result in RAX, 0 means equal.
- __ LeaveStubFrame();
- __ cmpq(RAX, Immediate(0));
- __ jmp(&done);
-
__ Bind(&reference_compare);
__ cmpq(left, right);
__ Bind(&done);
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 4613aff..50e5b36 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -213,7 +213,6 @@
V(Number, "num") \
V(_Smi, "_Smi") \
V(_Mint, "_Mint") \
- V(_Bigint, "_Bigint") \
V(_Double, "_Double") \
V(Bool, "bool") \
V(_List, "_List") \
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index aec2bf7..7f1c0d3 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -390,14 +390,6 @@
store_buffer_block_ = isolate()->store_buffer()->PopEmptyBlock();
}
-void Thread::SetStackLimitFromStackBase(uword stack_base) {
-#if defined(USING_SIMULATOR)
- SetStackLimit(Simulator::Current()->stack_limit());
-#else
- SetStackLimit(OSThread::Current()->stack_limit_with_headroom());
-#endif
-}
-
void Thread::SetStackLimit(uword limit) {
// The thread setting the stack limit is not necessarily the thread which
// the stack limit is being set on.
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 063c4ef..d524b9d 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -221,7 +221,6 @@
void PrepareForGC();
void SetStackLimit(uword value);
- void SetStackLimitFromStackBase(uword stack_base);
void ClearStackLimit();
// Access to the current stack limit for generated code. This may be
diff --git a/runtime/vm/thread_interrupter_fuchsia.cc b/runtime/vm/thread_interrupter_fuchsia.cc
index 26409ca..375f98d 100644
--- a/runtime/vm/thread_interrupter_fuchsia.cc
+++ b/runtime/vm/thread_interrupter_fuchsia.cc
@@ -174,6 +174,11 @@
private:
static const char* ThreadStateGetString(uint32_t state) {
+// TODO(dje): This #ifdef is temporary to handle the transition.
+// It can be deleted once the new version of zircon rolls out.
+#ifdef ZX_THREAD_STATE_BASIC
+ state = ZX_THREAD_STATE_BASIC(state);
+#endif
switch (state) {
case ZX_THREAD_STATE_NEW:
return "ZX_THREAD_STATE_NEW";
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index bbf3561..a88106a 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -689,10 +689,6 @@
return Api::Success();
}
-char* TestCase::BigintToHexValue(Dart_CObject* bigint) {
- return bin::CObject::BigintToHexValue(bigint);
-}
-
#if !defined(PRODUCT)
static bool IsHex(int c) {
return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f');
diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h
index d3f2870..ee2c328 100644
--- a/runtime/vm/unit_test.h
+++ b/runtime/vm/unit_test.h
@@ -361,7 +361,6 @@
static Dart_Handle library_handler(Dart_LibraryTag tag,
Dart_Handle library,
Dart_Handle url);
- static char* BigintToHexValue(Dart_CObject* bigint);
virtual void Run();
diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni
index f15b129..d227772 100644
--- a/runtime/vm/vm_sources.gni
+++ b/runtime/vm/vm_sources.gni
@@ -13,6 +13,8 @@
"ast_printer.h",
"ast_transformer.cc",
"ast_transformer.h",
+ "base64.cc",
+ "base64.h",
"base_isolate.h",
"become.cc",
"become.h",
@@ -385,7 +387,7 @@
"atomic_test.cc",
"benchmark_test.cc",
"benchmark_test.h",
- "bigint_test.cc",
+ "base64_test.cc",
"bit_set_test.cc",
"bit_vector_test.cc",
"bitfield_test.cc",
diff --git a/sdk/lib/_http/http.dart b/sdk/lib/_http/http.dart
index 1cb1b53..fa90619 100644
--- a/sdk/lib/_http/http.dart
+++ b/sdk/lib/_http/http.dart
@@ -34,50 +34,138 @@
* HTTP status codes.
*/
abstract class HttpStatus {
- static const int CONTINUE = 100;
- static const int SWITCHING_PROTOCOLS = 101;
- static const int OK = 200;
- static const int CREATED = 201;
- static const int ACCEPTED = 202;
- static const int NON_AUTHORITATIVE_INFORMATION = 203;
- static const int NO_CONTENT = 204;
- static const int RESET_CONTENT = 205;
- static const int PARTIAL_CONTENT = 206;
- static const int MULTIPLE_CHOICES = 300;
- static const int MOVED_PERMANENTLY = 301;
- static const int FOUND = 302;
- static const int MOVED_TEMPORARILY = 302; // Common alias for FOUND.
- static const int SEE_OTHER = 303;
- static const int NOT_MODIFIED = 304;
- static const int USE_PROXY = 305;
- static const int TEMPORARY_REDIRECT = 307;
- static const int BAD_REQUEST = 400;
- static const int UNAUTHORIZED = 401;
- static const int PAYMENT_REQUIRED = 402;
- static const int FORBIDDEN = 403;
- static const int NOT_FOUND = 404;
- static const int METHOD_NOT_ALLOWED = 405;
- static const int NOT_ACCEPTABLE = 406;
- static const int PROXY_AUTHENTICATION_REQUIRED = 407;
- static const int REQUEST_TIMEOUT = 408;
- static const int CONFLICT = 409;
- static const int GONE = 410;
- static const int LENGTH_REQUIRED = 411;
- static const int PRECONDITION_FAILED = 412;
- static const int REQUEST_ENTITY_TOO_LARGE = 413;
- static const int REQUEST_URI_TOO_LONG = 414;
- static const int UNSUPPORTED_MEDIA_TYPE = 415;
- static const int REQUESTED_RANGE_NOT_SATISFIABLE = 416;
- static const int EXPECTATION_FAILED = 417;
- static const int UPGRADE_REQUIRED = 426;
- static const int INTERNAL_SERVER_ERROR = 500;
- static const int NOT_IMPLEMENTED = 501;
- static const int BAD_GATEWAY = 502;
- static const int SERVICE_UNAVAILABLE = 503;
- static const int GATEWAY_TIMEOUT = 504;
- static const int HTTP_VERSION_NOT_SUPPORTED = 505;
+ static const int continue_ = 100;
+ static const int switchingProtocols = 101;
+ static const int ok = 200;
+ static const int created = 201;
+ static const int accepted = 202;
+ static const int nonAuthoritativeInformation = 203;
+ static const int noContent = 204;
+ static const int resetContent = 205;
+ static const int partialContent = 206;
+ static const int multipleChoices = 300;
+ static const int movedPermanently = 301;
+ static const int found = 302;
+ static const int movedTemporarily = 302; // Common alias for found.
+ static const int seeOther = 303;
+ static const int notModified = 304;
+ static const int useProxy = 305;
+ static const int temporaryRedirect = 307;
+ static const int badRequest = 400;
+ static const int unauthorized = 401;
+ static const int paymentRequired = 402;
+ static const int forbidden = 403;
+ static const int notFound = 404;
+ static const int methodNotAllowed = 405;
+ static const int notAcceptable = 406;
+ static const int proxyAuthenticationRequired = 407;
+ static const int requestTimeout = 408;
+ static const int conflict = 409;
+ static const int gone = 410;
+ static const int lengthRequired = 411;
+ static const int preconditionFailed = 412;
+ static const int requestEntityTooLarge = 413;
+ static const int requestUriTooLong = 414;
+ static const int unsupportedMediaType = 415;
+ static const int requestedRangeNotSatisfiable = 416;
+ static const int expectationFailed = 417;
+ static const int upgradeRequired = 426;
+ static const int internalServerError = 500;
+ static const int notImplemented = 501;
+ static const int badGateway = 502;
+ static const int serviceUnavailable = 503;
+ static const int gatewayTimeout = 504;
+ static const int httpVersionNotSupported = 505;
// Client generated status code.
- static const int NETWORK_CONNECT_TIMEOUT_ERROR = 599;
+ static const int networkConnectTimeoutError = 599;
+
+ @Deprecated("Use continue_ instead")
+ static const int CONTINUE = continue_;
+ @Deprecated("Use switchingProtocols instead")
+ static const int SWITCHING_PROTOCOLS = switchingProtocols;
+ @Deprecated("Use ok instead")
+ static const int OK = ok;
+ @Deprecated("Use created instead")
+ static const int CREATED = created;
+ @Deprecated("Use accepted instead")
+ static const int ACCEPTED = accepted;
+ @Deprecated("Use nonAuthoritativeInformation instead")
+ static const int NON_AUTHORITATIVE_INFORMATION = nonAuthoritativeInformation;
+ @Deprecated("Use noContent instead")
+ static const int NO_CONTENT = noContent;
+ @Deprecated("Use resetContent instead")
+ static const int RESET_CONTENT = resetContent;
+ @Deprecated("Use partialContent instead")
+ static const int PARTIAL_CONTENT = partialContent;
+ @Deprecated("Use multipleChoices instead")
+ static const int MULTIPLE_CHOICES = multipleChoices;
+ @Deprecated("Use movedPermanently instead")
+ static const int MOVED_PERMANENTLY = movedPermanently;
+ @Deprecated("Use found instead")
+ static const int FOUND = found;
+ @Deprecated("Use movedTemporarily instead")
+ static const int MOVED_TEMPORARILY = movedTemporarily;
+ @Deprecated("Use seeOther instead")
+ static const int SEE_OTHER = seeOther;
+ @Deprecated("Use notModified instead")
+ static const int NOT_MODIFIED = notModified;
+ @Deprecated("Use useProxy instead")
+ static const int USE_PROXY = useProxy;
+ @Deprecated("Use temporaryRedirect instead")
+ static const int TEMPORARY_REDIRECT = temporaryRedirect;
+ @Deprecated("Use badRequest instead")
+ static const int BAD_REQUEST = badRequest;
+ @Deprecated("Use unauthorized instead")
+ static const int UNAUTHORIZED = unauthorized;
+ @Deprecated("Use paymentRequired instead")
+ static const int PAYMENT_REQUIRED = paymentRequired;
+ @Deprecated("Use forbidden instead")
+ static const int FORBIDDEN = forbidden;
+ @Deprecated("Use notFound instead")
+ static const int NOT_FOUND = notFound;
+ @Deprecated("Use methodNotAllowed instead")
+ static const int METHOD_NOT_ALLOWED = methodNotAllowed;
+ @Deprecated("Use notAcceptable instead")
+ static const int NOT_ACCEPTABLE = notAcceptable;
+ @Deprecated("Use proxyAuthenticationRequired instead")
+ static const int PROXY_AUTHENTICATION_REQUIRED = proxyAuthenticationRequired;
+ @Deprecated("Use requestTimeout instead")
+ static const int REQUEST_TIMEOUT = requestTimeout;
+ @Deprecated("Use conflict instead")
+ static const int CONFLICT = conflict;
+ @Deprecated("Use gone instead")
+ static const int GONE = gone;
+ @Deprecated("Use lengthRequired instead")
+ static const int LENGTH_REQUIRED = lengthRequired;
+ @Deprecated("Use preconditionFailed instead")
+ static const int PRECONDITION_FAILED = preconditionFailed;
+ @Deprecated("Use requestEntityTooLarge instead")
+ static const int REQUEST_ENTITY_TOO_LARGE = requestEntityTooLarge;
+ @Deprecated("Use requestUriTooLong instead")
+ static const int REQUEST_URI_TOO_LONG = requestUriTooLong;
+ @Deprecated("Use unsupportedMediaType instead")
+ static const int UNSUPPORTED_MEDIA_TYPE = unsupportedMediaType;
+ @Deprecated("Use requestedRangeNotSatisfiable instead")
+ static const int REQUESTED_RANGE_NOT_SATISFIABLE =
+ requestedRangeNotSatisfiable;
+ @Deprecated("Use expectationFailed instead")
+ static const int EXPECTATION_FAILED = expectationFailed;
+ @Deprecated("Use upgradeRequired instead")
+ static const int UPGRADE_REQUIRED = upgradeRequired;
+ @Deprecated("Use internalServerError instead")
+ static const int INTERNAL_SERVER_ERROR = internalServerError;
+ @Deprecated("Use notImplemented instead")
+ static const int NOT_IMPLEMENTED = notImplemented;
+ @Deprecated("Use badGateway instead")
+ static const int BAD_GATEWAY = badGateway;
+ @Deprecated("Use serviceUnavailable instead")
+ static const int SERVICE_UNAVAILABLE = serviceUnavailable;
+ @Deprecated("Use gatewayTimeout instead")
+ static const int GATEWAY_TIMEOUT = gatewayTimeout;
+ @Deprecated("Use httpVersionNotSupported instead")
+ static const int HTTP_VERSION_NOT_SUPPORTED = httpVersionNotSupported;
+ @Deprecated("Use networkConnectTimeoutError instead")
+ static const int NETWORK_CONNECT_TIMEOUT_ERROR = networkConnectTimeoutError;
}
/**
@@ -97,7 +185,7 @@
*
* main() {
* HttpServer
- * .bind(InternetAddress.ANY_IP_V6, 80)
+ * .bind(InternetAddress.anyIPv6, 80)
* .then((server) {
* server.listen((HttpRequest request) {
* request.response.write('Hello, world!');
@@ -138,7 +226,7 @@
* context.usePrivateKey(key, password: 'dartdart');
*
* HttpServer
- * .bindSecure(InternetAddress.ANY_IP_V6,
+ * .bindSecure(InternetAddress.anyIPv6,
* 443,
* context)
* .then((server) {
@@ -160,7 +248,7 @@
* import 'dart:io';
*
* main() {
- * ServerSocket.bind(InternetAddress.ANY_IP_V6, 80)
+ * ServerSocket.bind(InternetAddress.anyIPv6, 80)
* .then((serverSocket) {
* HttpServer httpserver = new HttpServer.listenOn(serverSocket);
* serverSocket.listen((Socket socket) {
@@ -242,17 +330,17 @@
* perform a [InternetAddress.lookup] and use the first value in the
* list. To listen on the loopback adapter, which will allow only
* incoming connections from the local host, use the value
- * [InternetAddress.LOOPBACK_IP_V4] or
- * [InternetAddress.LOOPBACK_IP_V6]. To allow for incoming
+ * [InternetAddress.loopbackIPv4] or
+ * [InternetAddress.loopbackIPv6]. To allow for incoming
* connection from the network use either one of the values
- * [InternetAddress.ANY_IP_V4] or [InternetAddress.ANY_IP_V6] to
+ * [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] to
* bind to all interfaces or the IP address of a specific interface.
*
* If an IP version 6 (IPv6) address is used, both IP version 6
* (IPv6) and version 4 (IPv4) connections will be accepted. To
* restrict this to version 6 (IPv6) only, use [v6Only] to set
* version 6 only. However, if the address is
- * [InternetAddress.LOOPBACK_IP_V6], only IP version 6 (IPv6) connections
+ * [InternetAddress.loopbackIPv6], only IP version 6 (IPv6) connections
* will be accepted.
*
* If [port] has the value [:0:] an ephemeral port will be chosen by
@@ -281,10 +369,10 @@
* perform a [InternetAddress.lookup] and use the first value in the
* list. To listen on the loopback adapter, which will allow only
* incoming connections from the local host, use the value
- * [InternetAddress.LOOPBACK_IP_V4] or
- * [InternetAddress.LOOPBACK_IP_V6]. To allow for incoming
+ * [InternetAddress.loopbackIPv4] or
+ * [InternetAddress.loopbackIPv6]. To allow for incoming
* connection from the network use either one of the values
- * [InternetAddress.ANY_IP_V4] or [InternetAddress.ANY_IP_V6] to
+ * [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] to
* bind to all interfaces or the IP address of a specific interface.
*
* If an IP version 6 (IPv6) address is used, both IP version 6
@@ -415,12 +503,12 @@
*
* To set the value of a header use the `set()` method:
*
- * request.headers.set(HttpHeaders.CACHE_CONTROL,
+ * request.headers.set(HttpHeaders.cacheControlHeader,
* 'max-age=3600, must-revalidate');
*
* To retrieve the value of a header use the `value()` method:
*
- * print(request.headers.value(HttpHeaders.USER_AGENT));
+ * print(request.headers.value(HttpHeaders.userAgentHeader));
*
* An HttpHeaders object holds a list of values for each name
* as the standard allows. In most cases a name holds only a single value,
@@ -428,117 +516,229 @@
* and `value()` for retrieving a value.
*/
abstract class HttpHeaders {
- static const ACCEPT = "accept";
- static const ACCEPT_CHARSET = "accept-charset";
- static const ACCEPT_ENCODING = "accept-encoding";
- static const ACCEPT_LANGUAGE = "accept-language";
- static const ACCEPT_RANGES = "accept-ranges";
- static const AGE = "age";
- static const ALLOW = "allow";
- static const AUTHORIZATION = "authorization";
- static const CACHE_CONTROL = "cache-control";
- static const CONNECTION = "connection";
- static const CONTENT_ENCODING = "content-encoding";
- static const CONTENT_LANGUAGE = "content-language";
- static const CONTENT_LENGTH = "content-length";
- static const CONTENT_LOCATION = "content-location";
- static const CONTENT_MD5 = "content-md5";
- static const CONTENT_RANGE = "content-range";
- static const CONTENT_TYPE = "content-type";
- static const DATE = "date";
- static const ETAG = "etag";
- static const EXPECT = "expect";
- static const EXPIRES = "expires";
- static const FROM = "from";
- static const HOST = "host";
- static const IF_MATCH = "if-match";
- static const IF_MODIFIED_SINCE = "if-modified-since";
- static const IF_NONE_MATCH = "if-none-match";
- static const IF_RANGE = "if-range";
- static const IF_UNMODIFIED_SINCE = "if-unmodified-since";
- static const LAST_MODIFIED = "last-modified";
- static const LOCATION = "location";
- static const MAX_FORWARDS = "max-forwards";
- static const PRAGMA = "pragma";
- static const PROXY_AUTHENTICATE = "proxy-authenticate";
- static const PROXY_AUTHORIZATION = "proxy-authorization";
- static const RANGE = "range";
- static const REFERER = "referer";
- static const RETRY_AFTER = "retry-after";
- static const SERVER = "server";
- static const TE = "te";
- static const TRAILER = "trailer";
- static const TRANSFER_ENCODING = "transfer-encoding";
- static const UPGRADE = "upgrade";
- static const USER_AGENT = "user-agent";
- static const VARY = "vary";
- static const VIA = "via";
- static const WARNING = "warning";
- static const WWW_AUTHENTICATE = "www-authenticate";
+ static const acceptHeader = "accept";
+ static const acceptCharsetHeader = "accept-charset";
+ static const acceptEncodingHeader = "accept-encoding";
+ static const acceptLanguageHeader = "accept-language";
+ static const acceptRangesHeader = "accept-ranges";
+ static const ageHeader = "age";
+ static const allowHeader = "allow";
+ static const authorizationHeader = "authorization";
+ static const cacheControlHeader = "cache-control";
+ static const connectionHeader = "connection";
+ static const contentEncodingHeader = "content-encoding";
+ static const contentLanguageHeader = "content-language";
+ static const contentLengthHeader = "content-length";
+ static const contentLocationHeader = "content-location";
+ static const contentMD5Header = "content-md5";
+ static const contentRangeHeader = "content-range";
+ static const contentTypeHeader = "content-type";
+ static const dateHeader = "date";
+ static const etagHeader = "etag";
+ static const expectHeader = "expect";
+ static const expiresHeader = "expires";
+ static const fromHeader = "from";
+ static const hostHeader = "host";
+ static const ifMatchHeader = "if-match";
+ static const ifModifiedSinceHeader = "if-modified-since";
+ static const ifNoneMatchHeader = "if-none-match";
+ static const ifRangeHeader = "if-range";
+ static const ifUnmodifiedSinceHeader = "if-unmodified-since";
+ static const lastModifiedHeader = "last-modified";
+ static const locationHeader = "location";
+ static const maxForwardsHeader = "max-forwards";
+ static const pragmaHeader = "pragma";
+ static const proxyAuthenticateHeader = "proxy-authenticate";
+ static const proxyAuthorizationHeader = "proxy-authorization";
+ static const rangeHeader = "range";
+ static const refererHeader = "referer";
+ static const retryAfterHeader = "retry-after";
+ static const serverHeader = "server";
+ static const teHeader = "te";
+ static const trailerHeader = "trailer";
+ static const transferEncodingHeader = "transfer-encoding";
+ static const upgradeHeader = "upgrade";
+ static const userAgentHeader = "user-agent";
+ static const varyHeader = "vary";
+ static const viaHeader = "via";
+ static const warningHeader = "warning";
+ static const wwwAuthenticateHeader = "www-authenticate";
+
+ @Deprecated("Use acceptHeader instead")
+ static const ACCEPT = acceptHeader;
+ @Deprecated("Use acceptCharsetHeader instead")
+ static const ACCEPT_CHARSET = acceptCharsetHeader;
+ @Deprecated("Use acceptEncodingHeader instead")
+ static const ACCEPT_ENCODING = acceptEncodingHeader;
+ @Deprecated("Use acceptLanguageHeader instead")
+ static const ACCEPT_LANGUAGE = acceptLanguageHeader;
+ @Deprecated("Use acceptRangesHeader instead")
+ static const ACCEPT_RANGES = acceptRangesHeader;
+ @Deprecated("Use ageHeader instead")
+ static const AGE = ageHeader;
+ @Deprecated("Use allowHeader instead")
+ static const ALLOW = allowHeader;
+ @Deprecated("Use authorizationHeader instead")
+ static const AUTHORIZATION = authorizationHeader;
+ @Deprecated("Use cacheControlHeader instead")
+ static const CACHE_CONTROL = cacheControlHeader;
+ @Deprecated("Use connectionHeader instead")
+ static const CONNECTION = connectionHeader;
+ @Deprecated("Use contentEncodingHeader instead")
+ static const CONTENT_ENCODING = contentEncodingHeader;
+ @Deprecated("Use contentLanguageHeader instead")
+ static const CONTENT_LANGUAGE = contentLanguageHeader;
+ @Deprecated("Use contentLengthHeader instead")
+ static const CONTENT_LENGTH = contentLengthHeader;
+ @Deprecated("Use contentLocationHeader instead")
+ static const CONTENT_LOCATION = contentLocationHeader;
+ @Deprecated("Use contentMD5Header instead")
+ static const CONTENT_MD5 = contentMD5Header;
+ @Deprecated("Use contentRangeHeader instead")
+ static const CONTENT_RANGE = contentRangeHeader;
+ @Deprecated("Use contentTypeHeader instead")
+ static const CONTENT_TYPE = contentTypeHeader;
+ @Deprecated("Use dateHeader instead")
+ static const DATE = dateHeader;
+ @Deprecated("Use etagHeader instead")
+ static const ETAG = etagHeader;
+ @Deprecated("Use expectHeader instead")
+ static const EXPECT = expectHeader;
+ @Deprecated("Use expiresHeader instead")
+ static const EXPIRES = expiresHeader;
+ @Deprecated("Use fromHeader instead")
+ static const FROM = fromHeader;
+ @Deprecated("Use hostHeader instead")
+ static const HOST = hostHeader;
+ @Deprecated("Use ifMatchHeader instead")
+ static const IF_MATCH = ifMatchHeader;
+ @Deprecated("Use ifModifiedSinceHeader instead")
+ static const IF_MODIFIED_SINCE = ifModifiedSinceHeader;
+ @Deprecated("Use ifNoneMatchHeader instead")
+ static const IF_NONE_MATCH = ifNoneMatchHeader;
+ @Deprecated("Use ifRangeHeader instead")
+ static const IF_RANGE = ifRangeHeader;
+ @Deprecated("Use ifUnmodifiedSinceHeader instead")
+ static const IF_UNMODIFIED_SINCE = ifUnmodifiedSinceHeader;
+ @Deprecated("Use lastModifiedHeader instead")
+ static const LAST_MODIFIED = lastModifiedHeader;
+ @Deprecated("Use locationHeader instead")
+ static const LOCATION = locationHeader;
+ @Deprecated("Use maxForwardsHeader instead")
+ static const MAX_FORWARDS = maxForwardsHeader;
+ @Deprecated("Use pragmaHeader instead")
+ static const PRAGMA = pragmaHeader;
+ @Deprecated("Use proxyAuthenticateHeader instead")
+ static const PROXY_AUTHENTICATE = proxyAuthenticateHeader;
+ @Deprecated("Use proxyAuthorizationHeader instead")
+ static const PROXY_AUTHORIZATION = proxyAuthorizationHeader;
+ @Deprecated("Use rangeHeader instead")
+ static const RANGE = rangeHeader;
+ @Deprecated("Use refererHeader instead")
+ static const REFERER = refererHeader;
+ @Deprecated("Use retryAfterHeader instead")
+ static const RETRY_AFTER = retryAfterHeader;
+ @Deprecated("Use serverHeader instead")
+ static const SERVER = serverHeader;
+ @Deprecated("Use teHeader instead")
+ static const TE = teHeader;
+ @Deprecated("Use trailerHeader instead")
+ static const TRAILER = trailerHeader;
+ @Deprecated("Use transferEncodingHeader instead")
+ static const TRANSFER_ENCODING = transferEncodingHeader;
+ @Deprecated("Use upgradeHeader instead")
+ static const UPGRADE = upgradeHeader;
+ @Deprecated("Use userAgentHeader instead")
+ static const USER_AGENT = userAgentHeader;
+ @Deprecated("Use varyHeader instead")
+ static const VARY = varyHeader;
+ @Deprecated("Use viaHeader instead")
+ static const VIA = viaHeader;
+ @Deprecated("Use warningHeader instead")
+ static const WARNING = warningHeader;
+ @Deprecated("Use wwwAuthenticateHeader instead")
+ static const WWW_AUTHENTICATE = wwwAuthenticateHeader;
// Cookie headers from RFC 6265.
- static const COOKIE = "cookie";
- static const SET_COOKIE = "set-cookie";
+ static const cookieHeader = "cookie";
+ static const setCookieHeader = "set-cookie";
- static const GENERAL_HEADERS = const [
- CACHE_CONTROL,
- CONNECTION,
- DATE,
- PRAGMA,
- TRAILER,
- TRANSFER_ENCODING,
- UPGRADE,
- VIA,
- WARNING
+ @Deprecated("Use cookieHeader instead")
+ static const COOKIE = cookieHeader;
+ @Deprecated("Use setCookieHeader instead")
+ static const SET_COOKIE = setCookieHeader;
+
+ static const generalHeaders = const [
+ cacheControlHeader,
+ connectionHeader,
+ dateHeader,
+ pragmaHeader,
+ trailerHeader,
+ transferEncodingHeader,
+ upgradeHeader,
+ viaHeader,
+ warningHeader
];
- static const ENTITY_HEADERS = const [
- ALLOW,
- CONTENT_ENCODING,
- CONTENT_LANGUAGE,
- CONTENT_LENGTH,
- CONTENT_LOCATION,
- CONTENT_MD5,
- CONTENT_RANGE,
- CONTENT_TYPE,
- EXPIRES,
- LAST_MODIFIED
+ @Deprecated("Use generalHeaders instead")
+ static const GENERAL_HEADERS = generalHeaders;
+
+ static const entityHeaders = const [
+ allowHeader,
+ contentEncodingHeader,
+ contentLanguageHeader,
+ contentLengthHeader,
+ contentLocationHeader,
+ contentMD5Header,
+ contentRangeHeader,
+ contentTypeHeader,
+ expiresHeader,
+ lastModifiedHeader
];
- static const RESPONSE_HEADERS = const [
- ACCEPT_RANGES,
- AGE,
- ETAG,
- LOCATION,
- PROXY_AUTHENTICATE,
- RETRY_AFTER,
- SERVER,
- VARY,
- WWW_AUTHENTICATE
+ @Deprecated("Use entityHeaders instead")
+ static const ENTITY_HEADERS = entityHeaders;
+
+ static const responseHeaders = const [
+ acceptRangesHeader,
+ ageHeader,
+ etagHeader,
+ locationHeader,
+ proxyAuthenticateHeader,
+ retryAfterHeader,
+ serverHeader,
+ varyHeader,
+ wwwAuthenticateHeader
];
- static const REQUEST_HEADERS = const [
- ACCEPT,
- ACCEPT_CHARSET,
- ACCEPT_ENCODING,
- ACCEPT_LANGUAGE,
- AUTHORIZATION,
- EXPECT,
- FROM,
- HOST,
- IF_MATCH,
- IF_MODIFIED_SINCE,
- IF_NONE_MATCH,
- IF_RANGE,
- IF_UNMODIFIED_SINCE,
- MAX_FORWARDS,
- PROXY_AUTHORIZATION,
- RANGE,
- REFERER,
- TE,
- USER_AGENT
+ @Deprecated("Use responseHeaders instead")
+ static const RESPONSE_HEADERS = responseHeaders;
+
+ static const requestHeaders = const [
+ acceptHeader,
+ acceptCharsetHeader,
+ acceptEncodingHeader,
+ acceptLanguageHeader,
+ authorizationHeader,
+ expectHeader,
+ fromHeader,
+ hostHeader,
+ ifMatchHeader,
+ ifModifiedSinceHeader,
+ ifNoneMatchHeader,
+ ifRangeHeader,
+ ifUnmodifiedSinceHeader,
+ maxForwardsHeader,
+ proxyAuthorizationHeader,
+ rangeHeader,
+ refererHeader,
+ teHeader,
+ userAgentHeader
];
+ @Deprecated("Use requestHeaders instead")
+ static const REQUEST_HEADERS = requestHeaders;
+
/**
* Gets and sets the date. The value of this property will
* reflect the 'date' header.
@@ -677,13 +877,13 @@
*
* HttpClientRequest request = ...;
* var v = new HeaderValue("text/plain", {"q": "0.3"});
- * request.headers.add(HttpHeaders.ACCEPT, v);
- * request.headers.add(HttpHeaders.ACCEPT, "text/html");
+ * request.headers.add(HttpHeaders.acceptHeader, v);
+ * request.headers.add(HttpHeaders.acceptHeader, "text/html");
*
* To parse the header values use the [:parse:] static method.
*
* HttpRequest request = ...;
- * List<String> values = request.headers[HttpHeaders.ACCEPT];
+ * List<String> values = request.headers[HttpHeaders.acceptHeader];
* values.forEach((value) {
* HeaderValue v = HeaderValue.parse(value);
* // Use v.value and v.parameters
@@ -767,28 +967,36 @@
*
* text/plain; charset=utf-8
*/
- static final TEXT = new ContentType("text", "plain", charset: "utf-8");
+ static final text = new ContentType("text", "plain", charset: "utf-8");
+ @Deprecated("Use text instead")
+ static final TEXT = text;
/**
* Content type for HTML using UTF-8 encoding.
*
* text/html; charset=utf-8
*/
- static final HTML = new ContentType("text", "html", charset: "utf-8");
+ static final html = new ContentType("text", "html", charset: "utf-8");
+ @Deprecated("Use html instead")
+ static final HTML = html;
/**
* Content type for JSON using UTF-8 encoding.
*
* application/json; charset=utf-8
*/
- static final JSON = new ContentType("application", "json", charset: "utf-8");
+ static final json = new ContentType("application", "json", charset: "utf-8");
+ @Deprecated("Use json instead")
+ static final JSON = json;
/**
* Content type for binary data.
*
* application/octet-stream
*/
- static final BINARY = new ContentType("application", "octet-stream");
+ static final binary = new ContentType("application", "octet-stream");
+ @Deprecated("Use binary instead")
+ static final BINARY = binary;
/**
* Creates a new content type object setting the primary type and
@@ -935,7 +1143,7 @@
* for HTTP requests. When the server receives a request,
* it uses the HttpRequest object's `method` property to dispatch requests.
*
- * final HOST = InternetAddress.LOOPBACK_IP_V4;
+ * final HOST = InternetAddress.loopbackIPv4;
* final PORT = 80;
*
* HttpServer.bind(HOST, PORT).then((_server) {
@@ -1101,7 +1309,7 @@
* be used.
*
* HttpResponse response = ...
- * response.headers.add(HttpHeaders.CONTENT_TYPE, "text/plain");
+ * response.headers.add(HttpHeaders.contentTypeHeader, "text/plain");
* response.write(...); // Strings written will be ISO-8859-1 encoded.
*
* An exception is thrown if you use the `write()` method
@@ -1120,7 +1328,7 @@
* Gets and sets the status code. Any integer value is accepted. For
* the official HTTP status codes use the fields from
* [HttpStatus]. If no status code is explicitly set the default
- * value [HttpStatus.OK] is used.
+ * value [HttpStatus.ok] is used.
*
* The status code must be set before the body is written
* to. Setting the status code after writing to the response body or
@@ -1186,14 +1394,14 @@
* The URI in [location] should be absolute, but there are no checks
* to enforce that.
*
- * By default the HTTP status code `HttpStatus.MOVED_TEMPORARILY`
+ * By default the HTTP status code `HttpStatus.movedTemporarily`
* (`302`) is used for the redirect, but an alternative one can be
* specified using the [status] argument.
*
* This method will also call `close`, and the returned future is
* the future returned by `close`.
*/
- Future redirect(Uri location, {int status: HttpStatus.MOVED_TEMPORARILY});
+ Future redirect(Uri location, {int status: HttpStatus.movedTemporarily});
/**
* Detaches the underlying socket from the HTTP server. When the
@@ -1283,7 +1491,7 @@
* `Accept-Encoding` header to something else.
* To turn off gzip compression of the response, clear this header:
*
- * request.headers.removeAll(HttpHeaders.ACCEPT_ENCODING)
+ * request.headers.removeAll(HttpHeaders.acceptEncodingHeader)
*
* ## Closing the HttpClient
*
@@ -1305,8 +1513,13 @@
* client.findProxy = null;
*/
abstract class HttpClient {
- static const int DEFAULT_HTTP_PORT = 80;
- static const int DEFAULT_HTTPS_PORT = 443;
+ static const int defaultHttpPort = 80;
+ @Deprecated("Use defaultHttpPort instead")
+ static const int DEFAULT_HTTP_PORT = defaultHttpPort;
+
+ static const int defaultHttpsPort = 443;
+ @Deprecated("Use defaultHttpsPort instead")
+ static const int DEFAULT_HTTPS_PORT = defaultHttpsPort;
/// Gets and sets the idle timeout of non-active persistent (keep-alive)
/// connections.
@@ -1722,7 +1935,7 @@
* be used.
*
* HttpClientRequest request = ...
- * request.headers.add(HttpHeaders.CONTENT_TYPE, "text/plain");
+ * request.headers.add(HttpHeaders.contentTypeHeader, "text/plain");
* request.write(...); // Strings written will be ISO-8859-1 encoded.
*
* An exception is thrown if you use an unsupported encoding and the
@@ -1741,12 +1954,12 @@
* automatically follow redirects. The default is [:true:].
*
* Automatic redirect will only happen for "GET" and "HEAD" requests
- * and only for the status codes [:HttpStatus.MOVED_PERMANENTLY:]
- * (301), [:HttpStatus.FOUND:] (302),
- * [:HttpStatus.MOVED_TEMPORARILY:] (302, alias for
- * [:HttpStatus.FOUND:]), [:HttpStatus.SEE_OTHER:] (303) and
- * [:HttpStatus.TEMPORARY_REDIRECT:] (307). For
- * [:HttpStatus.SEE_OTHER:] (303) automatic redirect will also happen
+ * and only for the status codes [:HttpStatus.movedPermanently:]
+ * (301), [:HttpStatus.found:] (302),
+ * [:HttpStatus.movedTemporarily:] (302, alias for
+ * [:HttpStatus.found:]), [:HttpStatus.seeOther:] (303) and
+ * [:HttpStatus.temporaryRedirect:] (307). For
+ * [:HttpStatus.seeOther:] (303) automatic redirect will also happen
* for "POST" requests with the method changed to "GET" when
* following the redirect.
*
@@ -1878,9 +2091,9 @@
/**
* Returns whether the status code is one of the normal redirect
- * codes [HttpStatus.MOVED_PERMANENTLY], [HttpStatus.FOUND],
- * [HttpStatus.MOVED_TEMPORARILY], [HttpStatus.SEE_OTHER] and
- * [HttpStatus.TEMPORARY_REDIRECT].
+ * codes [HttpStatus.movedPermanently], [HttpStatus.found],
+ * [HttpStatus.movedTemporarily], [HttpStatus.seeOther] and
+ * [HttpStatus.temporaryRedirect].
*/
bool get isRedirect;
@@ -1894,7 +2107,7 @@
/**
* Redirects this connection to a new URL. The default value for
* [method] is the method for the current request. The default value
- * for [url] is the value of the [HttpHeaders.LOCATION] header of
+ * for [url] is the value of the [HttpHeaders.locationHeader] header of
* the current response. All body data must have been read from the
* current response before calling [redirect].
*
diff --git a/sdk/lib/_http/http_headers.dart b/sdk/lib/_http/http_headers.dart
index 0e1d91f..bb607ba 100644
--- a/sdk/lib/_http/http_headers.dart
+++ b/sdk/lib/_http/http_headers.dart
@@ -20,7 +20,7 @@
final int _defaultPortForScheme;
_HttpHeaders(this.protocolVersion,
- {int defaultPortForScheme: HttpClient.DEFAULT_HTTP_PORT,
+ {int defaultPortForScheme: HttpClient.defaultHttpPort,
_HttpHeaders initialHeaders})
: _headers = new HashMap<String, List<String>>(),
_defaultPortForScheme = defaultPortForScheme {
@@ -70,7 +70,7 @@
_checkMutable();
name = _validateField(name);
_headers.remove(name);
- if (name == HttpHeaders.TRANSFER_ENCODING) {
+ if (name == HttpHeaders.transferEncodingHeader) {
_chunkedTransferEncoding = false;
}
_addAll(name, value);
@@ -88,7 +88,7 @@
}
if (values.length == 0) _headers.remove(name);
}
- if (name == HttpHeaders.TRANSFER_ENCODING && value == "chunked") {
+ if (name == HttpHeaders.transferEncodingHeader && value == "chunked") {
_chunkedTransferEncoding = false;
}
}
@@ -115,20 +115,20 @@
if (persistentConnection == _persistentConnection) return;
if (persistentConnection) {
if (protocolVersion == "1.1") {
- remove(HttpHeaders.CONNECTION, "close");
+ remove(HttpHeaders.connectionHeader, "close");
} else {
if (_contentLength == -1) {
throw new HttpException(
"Trying to set 'Connection: Keep-Alive' on HTTP 1.0 headers with "
"no ContentLength");
}
- add(HttpHeaders.CONNECTION, "keep-alive");
+ add(HttpHeaders.connectionHeader, "keep-alive");
}
} else {
if (protocolVersion == "1.1") {
- add(HttpHeaders.CONNECTION, "close");
+ add(HttpHeaders.connectionHeader, "close");
} else {
- remove(HttpHeaders.CONNECTION, "keep-alive");
+ remove(HttpHeaders.connectionHeader, "keep-alive");
}
}
_persistentConnection = persistentConnection;
@@ -149,9 +149,9 @@
_contentLength = contentLength;
if (_contentLength >= 0) {
if (chunkedTransferEncoding) chunkedTransferEncoding = false;
- _set(HttpHeaders.CONTENT_LENGTH, contentLength.toString());
+ _set(HttpHeaders.contentLengthHeader, contentLength.toString());
} else {
- removeAll(HttpHeaders.CONTENT_LENGTH);
+ removeAll(HttpHeaders.contentLengthHeader);
if (protocolVersion == "1.1") {
chunkedTransferEncoding = true;
}
@@ -168,15 +168,15 @@
}
if (chunkedTransferEncoding == _chunkedTransferEncoding) return;
if (chunkedTransferEncoding) {
- List<String> values = _headers[HttpHeaders.TRANSFER_ENCODING];
+ List<String> values = _headers[HttpHeaders.transferEncodingHeader];
if ((values == null || values.last != "chunked")) {
// Headers does not specify chunked encoding - add it if set.
- _addValue(HttpHeaders.TRANSFER_ENCODING, "chunked");
+ _addValue(HttpHeaders.transferEncodingHeader, "chunked");
}
contentLength = -1;
} else {
// Headers does specify chunked encoding - remove it if not set.
- remove(HttpHeaders.TRANSFER_ENCODING, "chunked");
+ remove(HttpHeaders.transferEncodingHeader, "chunked");
}
_chunkedTransferEncoding = chunkedTransferEncoding;
}
@@ -198,7 +198,7 @@
}
DateTime get ifModifiedSince {
- List<String> values = _headers[HttpHeaders.IF_MODIFIED_SINCE];
+ List<String> values = _headers[HttpHeaders.ifModifiedSinceHeader];
if (values != null) {
try {
return HttpDate.parse(values[0]);
@@ -213,11 +213,11 @@
_checkMutable();
// Format "ifModifiedSince" header with date in Greenwich Mean Time (GMT).
String formatted = HttpDate.format(ifModifiedSince.toUtc());
- _set(HttpHeaders.IF_MODIFIED_SINCE, formatted);
+ _set(HttpHeaders.ifModifiedSinceHeader, formatted);
}
DateTime get date {
- List<String> values = _headers[HttpHeaders.DATE];
+ List<String> values = _headers[HttpHeaders.dateHeader];
if (values != null) {
try {
return HttpDate.parse(values[0]);
@@ -236,7 +236,7 @@
}
DateTime get expires {
- List<String> values = _headers[HttpHeaders.EXPIRES];
+ List<String> values = _headers[HttpHeaders.expiresHeader];
if (values != null) {
try {
return HttpDate.parse(values[0]);
@@ -251,7 +251,7 @@
_checkMutable();
// Format "Expires" header with date in Greenwich Mean Time (GMT).
String formatted = HttpDate.format(expires.toUtc());
- _set(HttpHeaders.EXPIRES, formatted);
+ _set(HttpHeaders.expiresHeader, formatted);
}
ContentType get contentType {
@@ -265,7 +265,7 @@
void set contentType(ContentType contentType) {
_checkMutable();
- _set(HttpHeaders.CONTENT_TYPE, contentType.toString());
+ _set(HttpHeaders.contentTypeHeader, contentType.toString());
}
void clear() {
@@ -285,45 +285,45 @@
// faster than computing hash and looking up in a hash-map.
switch (name.length) {
case 4:
- if (HttpHeaders.DATE == name) {
+ if (HttpHeaders.dateHeader == name) {
_addDate(name, value);
return;
}
- if (HttpHeaders.HOST == name) {
+ if (HttpHeaders.hostHeader == name) {
_addHost(name, value);
return;
}
break;
case 7:
- if (HttpHeaders.EXPIRES == name) {
+ if (HttpHeaders.expiresHeader == name) {
_addExpires(name, value);
return;
}
break;
case 10:
- if (HttpHeaders.CONNECTION == name) {
+ if (HttpHeaders.connectionHeader == name) {
_addConnection(name, value);
return;
}
break;
case 12:
- if (HttpHeaders.CONTENT_TYPE == name) {
+ if (HttpHeaders.contentTypeHeader == name) {
_addContentType(name, value);
return;
}
break;
case 14:
- if (HttpHeaders.CONTENT_LENGTH == name) {
+ if (HttpHeaders.contentLengthHeader == name) {
_addContentLength(name, value);
return;
}
break;
case 17:
- if (HttpHeaders.TRANSFER_ENCODING == name) {
+ if (HttpHeaders.transferEncodingHeader == name) {
_addTransferEncoding(name, value);
return;
}
- if (HttpHeaders.IF_MODIFIED_SINCE == name) {
+ if (HttpHeaders.ifModifiedSinceHeader == name) {
_addIfModifiedSince(name, value);
return;
}
@@ -345,7 +345,7 @@
if (value == "chunked") {
chunkedTransferEncoding = true;
} else {
- _addValue(HttpHeaders.TRANSFER_ENCODING, value);
+ _addValue(HttpHeaders.transferEncodingHeader, value);
}
}
@@ -353,7 +353,7 @@
if (value is DateTime) {
date = value;
} else if (value is String) {
- _set(HttpHeaders.DATE, value);
+ _set(HttpHeaders.dateHeader, value);
} else {
throw new HttpException("Unexpected type for header named $name");
}
@@ -363,7 +363,7 @@
if (value is DateTime) {
expires = value;
} else if (value is String) {
- _set(HttpHeaders.EXPIRES, value);
+ _set(HttpHeaders.expiresHeader, value);
} else {
throw new HttpException("Unexpected type for header named $name");
}
@@ -373,7 +373,7 @@
if (value is DateTime) {
ifModifiedSince = value;
} else if (value is String) {
- _set(HttpHeaders.IF_MODIFIED_SINCE, value);
+ _set(HttpHeaders.ifModifiedSinceHeader, value);
} else {
throw new HttpException("Unexpected type for header named $name");
}
@@ -384,7 +384,7 @@
int pos = value.indexOf(":");
if (pos == -1) {
_host = value;
- _port = HttpClient.DEFAULT_HTTP_PORT;
+ _port = HttpClient.defaultHttpPort;
} else {
if (pos > 0) {
_host = value.substring(0, pos);
@@ -392,7 +392,7 @@
_host = null;
}
if (pos + 1 == value.length) {
- _port = HttpClient.DEFAULT_HTTP_PORT;
+ _port = HttpClient.defaultHttpPort;
} else {
try {
_port = int.parse(value.substring(pos + 1));
@@ -401,7 +401,7 @@
}
}
}
- _set(HttpHeaders.HOST, value);
+ _set(HttpHeaders.hostHeader, value);
} else {
throw new HttpException("Unexpected type for header named $name");
}
@@ -418,7 +418,7 @@
}
void _addContentType(String name, value) {
- _set(HttpHeaders.CONTENT_TYPE, value);
+ _set(HttpHeaders.contentTypeHeader, value);
}
void _addValue(String name, Object value) {
@@ -453,7 +453,7 @@
}
_foldHeader(String name) {
- if (name == HttpHeaders.SET_COOKIE ||
+ if (name == HttpHeaders.setCookieHeader ||
(_noFoldingHeaders != null && _noFoldingHeaders.indexOf(name) != -1)) {
return false;
}
@@ -577,7 +577,7 @@
}
}
- List<String> values = _headers[HttpHeaders.COOKIE];
+ List<String> values = _headers[HttpHeaders.cookieHeader];
if (values != null) {
values.forEach((headerValue) => parseCookieString(headerValue));
}
diff --git a/sdk/lib/_http/http_impl.dart b/sdk/lib/_http/http_impl.dart
index 8061440..3a1ec29 100644
--- a/sdk/lib/_http/http_impl.dart
+++ b/sdk/lib/_http/http_impl.dart
@@ -311,7 +311,7 @@
List<Cookie> get cookies {
if (_cookies != null) return _cookies;
_cookies = new List<Cookie>();
- List<String> values = headers[HttpHeaders.SET_COOKIE];
+ List<String> values = headers[HttpHeaders.setCookieHeader];
if (values != null) {
values.forEach((value) {
_cookies.add(new Cookie.fromSetCookieValue(value));
@@ -322,12 +322,12 @@
bool get isRedirect {
if (_httpRequest.method == "GET" || _httpRequest.method == "HEAD") {
- return statusCode == HttpStatus.MOVED_PERMANENTLY ||
- statusCode == HttpStatus.FOUND ||
- statusCode == HttpStatus.SEE_OTHER ||
- statusCode == HttpStatus.TEMPORARY_REDIRECT;
+ return statusCode == HttpStatus.movedPermanently ||
+ statusCode == HttpStatus.found ||
+ statusCode == HttpStatus.seeOther ||
+ statusCode == HttpStatus.temporaryRedirect;
} else if (_httpRequest.method == "POST") {
- return statusCode == HttpStatus.SEE_OTHER;
+ return statusCode == HttpStatus.seeOther;
}
return false;
}
@@ -336,14 +336,14 @@
[String method, Uri url, bool followLoops]) {
if (method == null) {
// Set method as defined by RFC 2616 section 10.3.4.
- if (statusCode == HttpStatus.SEE_OTHER && _httpRequest.method == "POST") {
+ if (statusCode == HttpStatus.seeOther && _httpRequest.method == "POST") {
method = "GET";
} else {
method = _httpRequest.method;
}
}
if (url == null) {
- String location = headers.value(HttpHeaders.LOCATION);
+ String location = headers.value(HttpHeaders.locationHeader);
if (location == null) {
throw new StateError("Response has no Location header for redirect");
}
@@ -378,8 +378,8 @@
}
Stream<List<int>> stream = _incoming;
if (_httpClient.autoUncompress &&
- headers.value(HttpHeaders.CONTENT_ENCODING) == "gzip") {
- stream = stream.transform(GZIP.decoder);
+ headers.value(HttpHeaders.contentEncodingHeader) == "gzip") {
+ stream = stream.transform(gzip.decoder);
}
return stream.listen(onData,
onError: onError, onDone: onDone, cancelOnError: cancelOnError);
@@ -394,16 +394,16 @@
bool get _shouldAuthenticateProxy {
// Only try to authenticate if there is a challenge in the response.
- List<String> challenge = headers[HttpHeaders.PROXY_AUTHENTICATE];
- return statusCode == HttpStatus.PROXY_AUTHENTICATION_REQUIRED &&
+ List<String> challenge = headers[HttpHeaders.proxyAuthenticateHeader];
+ return statusCode == HttpStatus.proxyAuthenticationRequired &&
challenge != null &&
challenge.length == 1;
}
bool get _shouldAuthenticate {
// Only try to authenticate if there is a challenge in the response.
- List<String> challenge = headers[HttpHeaders.WWW_AUTHENTICATE];
- return statusCode == HttpStatus.UNAUTHORIZED &&
+ List<String> challenge = headers[HttpHeaders.wwwAuthenticateHeader];
+ return statusCode == HttpStatus.unauthorized &&
challenge != null &&
challenge.length == 1;
}
@@ -421,8 +421,8 @@
List<String> authChallenge() {
return proxyAuth
- ? headers[HttpHeaders.PROXY_AUTHENTICATE]
- : headers[HttpHeaders.WWW_AUTHENTICATE];
+ ? headers[HttpHeaders.proxyAuthenticateHeader]
+ : headers[HttpHeaders.wwwAuthenticateHeader];
}
_Credentials findCredentials(_AuthenticationScheme scheme) {
@@ -722,8 +722,8 @@
: _uri = uri,
headers = new _HttpHeaders(protocolVersion,
defaultPortForScheme: uri.scheme == 'https'
- ? HttpClient.DEFAULT_HTTPS_PORT
- : HttpClient.DEFAULT_HTTP_PORT,
+ ? HttpClient.defaultHttpsPort
+ : HttpClient.defaultHttpPort,
initialHeaders: initialHeaders),
_outgoing = outgoing,
super(outgoing, null) {
@@ -812,7 +812,7 @@
_reasonPhrase = reasonPhrase;
}
- Future redirect(Uri location, {int status: HttpStatus.MOVED_TEMPORARILY}) {
+ Future redirect(Uri location, {int status: HttpStatus.movedTemporarily}) {
if (_outgoing.headersWritten) throw new StateError("Header already sent");
statusCode = status;
headers.set("location", location.toString());
@@ -895,7 +895,7 @@
// Add all the cookies set to the headers.
if (_cookies != null) {
_cookies.forEach((cookie) {
- headers.add(HttpHeaders.SET_COOKIE, cookie);
+ headers.add(HttpHeaders.setCookieHeader, cookie);
});
}
@@ -915,85 +915,85 @@
}
switch (statusCode) {
- case HttpStatus.CONTINUE:
+ case HttpStatus.continue_:
return "Continue";
- case HttpStatus.SWITCHING_PROTOCOLS:
+ case HttpStatus.switchingProtocols:
return "Switching Protocols";
- case HttpStatus.OK:
+ case HttpStatus.ok:
return "OK";
- case HttpStatus.CREATED:
+ case HttpStatus.created:
return "Created";
- case HttpStatus.ACCEPTED:
+ case HttpStatus.accepted:
return "Accepted";
- case HttpStatus.NON_AUTHORITATIVE_INFORMATION:
+ case HttpStatus.nonAuthoritativeInformation:
return "Non-Authoritative Information";
- case HttpStatus.NO_CONTENT:
+ case HttpStatus.noContent:
return "No Content";
- case HttpStatus.RESET_CONTENT:
+ case HttpStatus.resetContent:
return "Reset Content";
- case HttpStatus.PARTIAL_CONTENT:
+ case HttpStatus.partialContent:
return "Partial Content";
- case HttpStatus.MULTIPLE_CHOICES:
+ case HttpStatus.multipleChoices:
return "Multiple Choices";
- case HttpStatus.MOVED_PERMANENTLY:
+ case HttpStatus.movedPermanently:
return "Moved Permanently";
- case HttpStatus.FOUND:
+ case HttpStatus.found:
return "Found";
- case HttpStatus.SEE_OTHER:
+ case HttpStatus.seeOther:
return "See Other";
- case HttpStatus.NOT_MODIFIED:
+ case HttpStatus.notModified:
return "Not Modified";
- case HttpStatus.USE_PROXY:
+ case HttpStatus.useProxy:
return "Use Proxy";
- case HttpStatus.TEMPORARY_REDIRECT:
+ case HttpStatus.temporaryRedirect:
return "Temporary Redirect";
- case HttpStatus.BAD_REQUEST:
+ case HttpStatus.badRequest:
return "Bad Request";
- case HttpStatus.UNAUTHORIZED:
+ case HttpStatus.unauthorized:
return "Unauthorized";
- case HttpStatus.PAYMENT_REQUIRED:
+ case HttpStatus.paymentRequired:
return "Payment Required";
- case HttpStatus.FORBIDDEN:
+ case HttpStatus.forbidden:
return "Forbidden";
- case HttpStatus.NOT_FOUND:
+ case HttpStatus.notFound:
return "Not Found";
- case HttpStatus.METHOD_NOT_ALLOWED:
+ case HttpStatus.methodNotAllowed:
return "Method Not Allowed";
- case HttpStatus.NOT_ACCEPTABLE:
+ case HttpStatus.notAcceptable:
return "Not Acceptable";
- case HttpStatus.PROXY_AUTHENTICATION_REQUIRED:
+ case HttpStatus.proxyAuthenticationRequired:
return "Proxy Authentication Required";
- case HttpStatus.REQUEST_TIMEOUT:
+ case HttpStatus.requestTimeout:
return "Request Time-out";
- case HttpStatus.CONFLICT:
+ case HttpStatus.conflict:
return "Conflict";
- case HttpStatus.GONE:
+ case HttpStatus.gone:
return "Gone";
- case HttpStatus.LENGTH_REQUIRED:
+ case HttpStatus.lengthRequired:
return "Length Required";
- case HttpStatus.PRECONDITION_FAILED:
+ case HttpStatus.preconditionFailed:
return "Precondition Failed";
- case HttpStatus.REQUEST_ENTITY_TOO_LARGE:
+ case HttpStatus.requestEntityTooLarge:
return "Request Entity Too Large";
- case HttpStatus.REQUEST_URI_TOO_LONG:
- return "Request-URI Too Large";
- case HttpStatus.UNSUPPORTED_MEDIA_TYPE:
+ case HttpStatus.requestUriTooLong:
+ return "Request-URI Too Long";
+ case HttpStatus.unsupportedMediaType:
return "Unsupported Media Type";
- case HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE:
+ case HttpStatus.requestedRangeNotSatisfiable:
return "Requested range not satisfiable";
- case HttpStatus.EXPECTATION_FAILED:
+ case HttpStatus.expectationFailed:
return "Expectation Failed";
- case HttpStatus.INTERNAL_SERVER_ERROR:
+ case HttpStatus.internalServerError:
return "Internal Server Error";
- case HttpStatus.NOT_IMPLEMENTED:
+ case HttpStatus.notImplemented:
return "Not Implemented";
- case HttpStatus.BAD_GATEWAY:
+ case HttpStatus.badGateway:
return "Bad Gateway";
- case HttpStatus.SERVICE_UNAVAILABLE:
+ case HttpStatus.serviceUnavailable:
return "Service Unavailable";
- case HttpStatus.GATEWAY_TIMEOUT:
+ case HttpStatus.gatewayTimeout:
return "Gateway Time-out";
- case HttpStatus.HTTP_VERSION_NOT_SUPPORTED:
+ case HttpStatus.httpVersionNotSupported:
return "Http Version not supported";
default:
return "Status $statusCode";
@@ -1146,7 +1146,7 @@
if (i > 0) sb.write("; ");
sb..write(cookies[i].name)..write("=")..write(cookies[i].value);
}
- headers.add(HttpHeaders.COOKIE, sb.toString());
+ headers.add(HttpHeaders.cookieHeader, sb.toString());
}
headers._finalize();
@@ -1253,14 +1253,14 @@
outbound.bufferOutput &&
outbound.headers.chunkedTransferEncoding) {
List acceptEncodings =
- response._httpRequest.headers[HttpHeaders.ACCEPT_ENCODING];
- List contentEncoding = outbound.headers[HttpHeaders.CONTENT_ENCODING];
+ response._httpRequest.headers[HttpHeaders.acceptEncodingHeader];
+ List contentEncoding = outbound.headers[HttpHeaders.contentEncodingHeader];
if (acceptEncodings != null &&
acceptEncodings
.expand((list) => list.split(","))
.any((encoding) => encoding.trim().toLowerCase() == "gzip") &&
contentEncoding == null) {
- outbound.headers.set(HttpHeaders.CONTENT_ENCODING, "gzip");
+ outbound.headers.set(HttpHeaders.contentEncodingHeader, "gzip");
gzip = true;
}
}
@@ -1650,7 +1650,7 @@
request.headers
..host = host
..port = port
- .._add(HttpHeaders.ACCEPT_ENCODING, "gzip");
+ .._add(HttpHeaders.acceptEncodingHeader, "gzip");
if (_httpClient.userAgent != null) {
request.headers._add('user-agent', _httpClient.userAgent);
}
@@ -1659,7 +1659,7 @@
// for proxy basic authorization.
String auth = _CryptoUtils
.bytesToBase64(utf8.encode("${proxy.username}:${proxy.password}"));
- request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth");
+ request.headers.set(HttpHeaders.proxyAuthorizationHeader, "Basic $auth");
} else if (!proxy.isDirect && _httpClient._proxyCredentials.length > 0) {
proxyCreds = _httpClient._findProxyCredentials(proxy);
if (proxyCreds != null) {
@@ -1670,7 +1670,7 @@
// If the URL contains user information use that for basic
// authorization.
String auth = _CryptoUtils.bytesToBase64(utf8.encode(uri.userInfo));
- request.headers.set(HttpHeaders.AUTHORIZATION, "Basic $auth");
+ request.headers.set(HttpHeaders.authorizationHeader, "Basic $auth");
} else {
// Look for credentials.
creds = _httpClient._findCredentials(uri);
@@ -1779,10 +1779,10 @@
// for proxy basic authorization.
String auth = _CryptoUtils
.bytesToBase64(utf8.encode("${proxy.username}:${proxy.password}"));
- request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth");
+ request.headers.set(HttpHeaders.proxyAuthorizationHeader, "Basic $auth");
}
return request.close().then((response) {
- if (response.statusCode != HttpStatus.OK) {
+ if (response.statusCode != HttpStatus.ok) {
throw "Proxy failed to establish tunnel "
"(${response.statusCode} ${response.reasonPhrase})";
}
@@ -1927,7 +1927,7 @@
_connecting++;
return socketFuture.then((socket) {
_connecting--;
- socket.setOption(SocketOption.TCP_NODELAY, true);
+ socket.setOption(SocketOption.tcpNoDelay, true);
var connection =
new _HttpClientConnection(key, socket, client, false, context);
if (isSecure && !proxy.isDirect) {
@@ -2101,8 +2101,8 @@
int port = uri.port;
if (port == 0) {
port = isSecure
- ? HttpClient.DEFAULT_HTTPS_PORT
- : HttpClient.DEFAULT_HTTP_PORT;
+ ? HttpClient.defaultHttpsPort
+ : HttpClient.defaultHttpPort;
}
// Check to see if a proxy server should be used for this connection.
var proxyConf = const _ProxyConfiguration.direct();
@@ -2541,7 +2541,7 @@
static HttpHeaders _initDefaultResponseHeaders() {
var defaultResponseHeaders = new _HttpHeaders('1.1');
- defaultResponseHeaders.contentType = ContentType.TEXT;
+ defaultResponseHeaders.contentType = ContentType.text;
defaultResponseHeaders.set('X-Frame-Options', 'SAMEORIGIN');
defaultResponseHeaders.set('X-Content-Type-Options', 'nosniff');
defaultResponseHeaders.set('X-XSS-Protection', '1; mode=block');
@@ -2572,7 +2572,7 @@
StreamSubscription<HttpRequest> listen(void onData(HttpRequest event),
{Function onError, void onDone(), bool cancelOnError}) {
_serverSocket.listen((Socket socket) {
- socket.setOption(SocketOption.TCP_NODELAY, true);
+ socket.setOption(SocketOption.tcpNoDelay, true);
// Accept the client connection.
_HttpConnection connection = new _HttpConnection(socket, this);
_idleConnections.add(connection);
@@ -2974,8 +2974,8 @@
if (scheme != null && credentials.scheme != scheme) return false;
if (uri.host != this.uri.host) return false;
int thisPort =
- this.uri.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : this.uri.port;
- int otherPort = uri.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : uri.port;
+ this.uri.port == 0 ? HttpClient.defaultHttpPort: this.uri.port;
+ int otherPort = uri.port == 0 ? HttpClient.defaultHttpPort: uri.port;
if (otherPort != thisPort) return false;
return uri.path.startsWith(this.uri.path);
}
@@ -3041,11 +3041,11 @@
}
void authorize(_Credentials _, HttpClientRequest request) {
- request.headers.set(HttpHeaders.AUTHORIZATION, authorization());
+ request.headers.set(HttpHeaders.authorizationHeader, authorization());
}
void authorizeProxy(_ProxyCredentials _, HttpClientRequest request) {
- request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, authorization());
+ request.headers.set(HttpHeaders.proxyAuthorizationHeader, authorization());
}
}
@@ -3114,13 +3114,13 @@
void authorize(_Credentials credentials, HttpClientRequest request) {
request.headers
- .set(HttpHeaders.AUTHORIZATION, authorization(credentials, request));
+ .set(HttpHeaders.authorizationHeader, authorization(credentials, request));
}
void authorizeProxy(
_ProxyCredentials credentials, HttpClientRequest request) {
request.headers.set(
- HttpHeaders.PROXY_AUTHORIZATION, authorization(credentials, request));
+ HttpHeaders.proxyAuthorizationHeader, authorization(credentials, request));
}
}
diff --git a/sdk/lib/_http/http_parser.dart b/sdk/lib/_http/http_parser.dart
index be26555..eb7663b 100644
--- a/sdk/lib/_http/http_parser.dart
+++ b/sdk/lib/_http/http_parser.dart
@@ -666,8 +666,8 @@
List<String> tokens = _tokenizeFieldValue(headerValue);
final bool isResponse = _messageType == _MessageType.RESPONSE;
final bool isUpgradeCode =
- (_statusCode == HttpStatus.UPGRADE_REQUIRED) ||
- (_statusCode == HttpStatus.SWITCHING_PROTOCOLS);
+ (_statusCode == HttpStatus.upgradeRequired) ||
+ (_statusCode == HttpStatus.switchingProtocols);
for (int i = 0; i < tokens.length; i++) {
final bool isUpgrade = _caseInsensitiveCompare(
"upgrade".codeUnits, tokens[i].codeUnits);
diff --git a/sdk/lib/_http/websocket.dart b/sdk/lib/_http/websocket.dart
index 33a4f18..35f4690 100644
--- a/sdk/lib/_http/websocket.dart
+++ b/sdk/lib/_http/websocket.dart
@@ -8,19 +8,46 @@
* WebSocket status codes used when closing a WebSocket connection.
*/
abstract class WebSocketStatus {
- static const int NORMAL_CLOSURE = 1000;
- static const int GOING_AWAY = 1001;
- static const int PROTOCOL_ERROR = 1002;
- static const int UNSUPPORTED_DATA = 1003;
- static const int RESERVED_1004 = 1004;
- static const int NO_STATUS_RECEIVED = 1005;
- static const int ABNORMAL_CLOSURE = 1006;
- static const int INVALID_FRAME_PAYLOAD_DATA = 1007;
- static const int POLICY_VIOLATION = 1008;
- static const int MESSAGE_TOO_BIG = 1009;
- static const int MISSING_MANDATORY_EXTENSION = 1010;
- static const int INTERNAL_SERVER_ERROR = 1011;
- static const int RESERVED_1015 = 1015;
+ static const int normalClosure = 1000;
+ static const int goingAway = 1001;
+ static const int protocolError = 1002;
+ static const int unsupportedData = 1003;
+ static const int reserved1004 = 1004;
+ static const int noStatusReceived = 1005;
+ static const int abnormalClosure = 1006;
+ static const int invalidFramePayloadData = 1007;
+ static const int policyViolation = 1008;
+ static const int messageTooBig = 1009;
+ static const int missingMandatoryExtension = 1010;
+ static const int internalServerError = 1011;
+ static const int reserved1015 = 1015;
+
+ @Deprecated("Use normalClosure instead")
+ static const int NORMAL_CLOSURE = normalClosure;
+ @Deprecated("Use goingAway instead")
+ static const int GOING_AWAY = goingAway;
+ @Deprecated("Use protocolError instead")
+ static const int PROTOCOL_ERROR = protocolError;
+ @Deprecated("Use unsupportedData instead")
+ static const int UNSUPPORTED_DATA = unsupportedData;
+ @Deprecated("Use reserved1004 instead")
+ static const int RESERVED_1004 = reserved1004;
+ @Deprecated("Use noStatusReceived instead")
+ static const int NO_STATUS_RECEIVED = noStatusReceived;
+ @Deprecated("Use abnormalClosure instead")
+ static const int ABNORMAL_CLOSURE = abnormalClosure;
+ @Deprecated("Use invalidFramePayloadData instead")
+ static const int INVALID_FRAME_PAYLOAD_DATA = invalidFramePayloadData;
+ @Deprecated("Use policyViolation instead")
+ static const int POLICY_VIOLATION = policyViolation;
+ @Deprecated("Use messageTooBig instead")
+ static const int MESSAGE_TOO_BIG = messageTooBig;
+ @Deprecated("Use missingMandatoryExtension instead")
+ static const int MISSING_MANDATORY_EXTENSION = missingMandatoryExtension;
+ @Deprecated("Use internalServerError instead")
+ static const int INTERNAL_SERVER_ERROR = internalServerError;
+ @Deprecated("Use reserved1015 instead")
+ static const int RESERVED_1015 = reserved1015;
}
/**
@@ -36,13 +63,18 @@
* clientMaxWindowBits: 15
* serverMaxWindowBits: 15
*/
- static const CompressionOptions DEFAULT = const CompressionOptions();
+ static const CompressionOptions compressionDefault =
+ const CompressionOptions();
+ @Deprecated("Use compressionDefault instead")
+ static const CompressionOptions DEFAULT = compressionDefault;
/**
* Disables WebSocket Compression.
*/
- static const CompressionOptions OFF =
+ static const CompressionOptions compressionOff =
const CompressionOptions(enabled: false);
+ @Deprecated("Use compressionOff instead")
+ static const CompressionOptions OFF = compressionOff;
/**
* Control whether the client will reuse it's compression instances.
@@ -215,7 +247,7 @@
*/
factory WebSocketTransformer(
{/*String|Future<String>*/ protocolSelector(List<String> protocols),
- CompressionOptions compression: CompressionOptions.DEFAULT}) {
+ CompressionOptions compression: CompressionOptions.compressionDefault}) {
return new _WebSocketTransformerImpl(protocolSelector, compression);
}
@@ -238,7 +270,7 @@
*/
static Future<WebSocket> upgrade(HttpRequest request,
{protocolSelector(List<String> protocols),
- CompressionOptions compression: CompressionOptions.DEFAULT}) {
+ CompressionOptions compression: CompressionOptions.compressionDefault}) {
return _WebSocketTransformerImpl._upgrade(
request, protocolSelector, compression);
}
@@ -264,10 +296,19 @@
/**
* Possible states of the connection.
*/
- static const int CONNECTING = 0;
- static const int OPEN = 1;
- static const int CLOSING = 2;
- static const int CLOSED = 3;
+ static const int connecting = 0;
+ static const int open = 1;
+ static const int closing = 2;
+ static const int closed = 3;
+
+ @Deprecated("Use connecting instead")
+ static const int CONNECTING = connecting;
+ @Deprecated("Use open instead")
+ static const int OPEN = open;
+ @Deprecated("Use closing instead")
+ static const int CLOSING = closing;
+ @Deprecated("Use closed instead")
+ static const int CLOSED = closed;
/**
* Set and get the interval for sending ping signals. If a ping message is not
@@ -315,7 +356,8 @@
static Future<WebSocket> connect(String url,
{Iterable<String> protocols,
Map<String, dynamic> headers,
- CompressionOptions compression: CompressionOptions.DEFAULT}) =>
+ CompressionOptions compression:
+ CompressionOptions.compressionDefault}) =>
_WebSocketImpl.connect(url, protocols, headers, compression: compression);
@Deprecated('This constructor will be removed in Dart 2.0. Use `implements`'
@@ -344,7 +386,7 @@
factory WebSocket.fromUpgradedSocket(Socket socket,
{String protocol,
bool serverSide,
- CompressionOptions compression: CompressionOptions.DEFAULT}) {
+ CompressionOptions compression: CompressionOptions.compressionDefault}) {
if (serverSide == null) {
throw new ArgumentError("The serverSide argument must be passed "
"explicitly to WebSocket.fromUpgradedSocket.");
diff --git a/sdk/lib/_http/websocket_impl.dart b/sdk/lib/_http/websocket_impl.dart
index fa89b00..330f9ea 100644
--- a/sdk/lib/_http/websocket_impl.dart
+++ b/sdk/lib/_http/websocket_impl.dart
@@ -449,7 +449,7 @@
if (!_isUpgradeRequest(request)) {
// Send error response.
response
- ..statusCode = HttpStatus.BAD_REQUEST
+ ..statusCode = HttpStatus.badRequest
..close();
return new Future.error(
new WebSocketException("Invalid WebSocket upgrade request"));
@@ -458,9 +458,9 @@
Future<WebSocket> upgrade(String protocol) {
// Send the upgrade response.
response
- ..statusCode = HttpStatus.SWITCHING_PROTOCOLS
- ..headers.add(HttpHeaders.CONNECTION, "Upgrade")
- ..headers.add(HttpHeaders.UPGRADE, "websocket");
+ ..statusCode = HttpStatus.switchingProtocols
+ ..headers.add(HttpHeaders.connectionHeader, "Upgrade")
+ ..headers.add(HttpHeaders.upgradeHeader, "websocket");
String key = request.headers.value("Sec-WebSocket-Key");
_SHA1 sha1 = new _SHA1();
sha1.add("$key$_webSocketGUID".codeUnits);
@@ -493,7 +493,7 @@
return protocol;
}).catchError((error) {
response
- ..statusCode = HttpStatus.INTERNAL_SERVER_ERROR
+ ..statusCode = HttpStatus.internalServerError
..close();
throw error;
}).then<WebSocket>(upgrade);
@@ -536,15 +536,15 @@
if (request.method != "GET") {
return false;
}
- if (request.headers[HttpHeaders.CONNECTION] == null) {
+ if (request.headers[HttpHeaders.connectionHeader] == null) {
return false;
}
bool isUpgrade = false;
- request.headers[HttpHeaders.CONNECTION].forEach((String value) {
+ request.headers[HttpHeaders.connectionHeader].forEach((String value) {
if (value.toLowerCase() == "upgrade") isUpgrade = true;
});
if (!isUpgrade) return false;
- String upgrade = request.headers.value(HttpHeaders.UPGRADE);
+ String upgrade = request.headers.value(HttpHeaders.upgradeHeader);
if (upgrade == null || upgrade.toLowerCase() != "websocket") {
return false;
}
@@ -964,7 +964,7 @@
final _socket;
final bool _serverSide;
- int _readyState = WebSocket.CONNECTING;
+ int _readyState = WebSocket.connecting;
bool _writeClosed = false;
int _closeCode;
String _closeReason;
@@ -981,7 +981,7 @@
static Future<WebSocket> connect(
String url, Iterable<String> protocols, Map<String, dynamic> headers,
- {CompressionOptions compression: CompressionOptions.DEFAULT}) {
+ {CompressionOptions compression: CompressionOptions.compressionDefault}) {
Uri uri = Uri.parse(url);
if (uri.scheme != "ws" && uri.scheme != "wss") {
throw new WebSocketException("Unsupported URL scheme '${uri.scheme}'");
@@ -1008,15 +1008,15 @@
// If the URL contains user information use that for basic
// authorization.
String auth = _CryptoUtils.bytesToBase64(utf8.encode(uri.userInfo));
- request.headers.set(HttpHeaders.AUTHORIZATION, "Basic $auth");
+ request.headers.set(HttpHeaders.authorizationHeader, "Basic $auth");
}
if (headers != null) {
headers.forEach((field, value) => request.headers.add(field, value));
}
// Setup the initial handshake.
request.headers
- ..set(HttpHeaders.CONNECTION, "Upgrade")
- ..set(HttpHeaders.UPGRADE, "websocket")
+ ..set(HttpHeaders.connectionHeader, "Upgrade")
+ ..set(HttpHeaders.upgradeHeader, "websocket")
..set("Sec-WebSocket-Key", nonce)
..set("Cache-Control", "no-cache")
..set("Sec-WebSocket-Version", "13");
@@ -1039,11 +1039,11 @@
throw new WebSocketException(message);
}
- if (response.statusCode != HttpStatus.SWITCHING_PROTOCOLS ||
- response.headers[HttpHeaders.CONNECTION] == null ||
- !response.headers[HttpHeaders.CONNECTION]
+ if (response.statusCode != HttpStatus.switchingProtocols ||
+ response.headers[HttpHeaders.connectionHeader] == null ||
+ !response.headers[HttpHeaders.connectionHeader]
.any((value) => value.toLowerCase() == "upgrade") ||
- response.headers.value(HttpHeaders.UPGRADE).toLowerCase() !=
+ response.headers.value(HttpHeaders.upgradeHeader).toLowerCase() !=
"websocket") {
error("Connection to '$uri' was not upgraded to websocket");
}
@@ -1114,7 +1114,7 @@
[this._serverSide = false, _WebSocketPerMessageDeflate deflate]) {
_consumer = new _WebSocketConsumer(this, _socket);
_sink = new _StreamSinkImpl(_consumer);
- _readyState = WebSocket.OPEN;
+ _readyState = WebSocket.open;
_deflate = deflate;
var transformer = new _WebSocketProtocolTransformer(_serverSide, _deflate);
@@ -1140,14 +1140,14 @@
_controller.close();
}, onDone: () {
if (_closeTimer != null) _closeTimer.cancel();
- if (_readyState == WebSocket.OPEN) {
- _readyState = WebSocket.CLOSING;
+ if (_readyState == WebSocket.open) {
+ _readyState = WebSocket.closing;
if (!_isReservedStatusCode(transformer.closeCode)) {
_close(transformer.closeCode, transformer.closeReason);
} else {
_close();
}
- _readyState = WebSocket.CLOSED;
+ _readyState = WebSocket.closed;
}
// Protocol close, use close code from transformer.
_closeCode = transformer.closeCode;
diff --git a/sdk/lib/_internal/js_runtime/lib/constant_map.dart b/sdk/lib/_internal/js_runtime/lib/constant_map.dart
index 3d92fd8..6047b2d 100644
--- a/sdk/lib/_internal/js_runtime/lib/constant_map.dart
+++ b/sdk/lib/_internal/js_runtime/lib/constant_map.dart
@@ -12,7 +12,7 @@
abstract class ConstantMap<K, V> implements Map<K, V> {
// Used to create unmodifiable maps from other maps.
factory ConstantMap.from(Map other) {
- List keys = other.keys.toList();
+ List keys = new List<K>.from(other.keys);
bool allStrings = true;
for (var k in keys) {
if (k is! String) {
@@ -26,7 +26,7 @@
var object = JS('=Object', '{}');
int length = 0;
for (var k in keys) {
- var v = other[k];
+ V v = other[k];
if (k != '__proto__') {
if (!jsHasOwnProperty(object, k)) length++;
JS('void', '#[#] = #', object, k, v);
diff --git a/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart b/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart
index e93af8f..7889c36 100644
--- a/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart
+++ b/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart
@@ -379,8 +379,9 @@
// because passing unvalidated values to the native constructors can cause
// conversions or create views.
int _checkLength(length) {
- if (length is! int) throw new ArgumentError('Invalid length $length');
- return length;
+ return length is int
+ ? length
+ : throw new ArgumentError('Invalid length $length');
}
// Validates `.view` constructor arguments. Checking is necessary because
diff --git a/sdk/lib/async/async.dart b/sdk/lib/async/async.dart
index c616cda..2fa3f1df8 100644
--- a/sdk/lib/async/async.dart
+++ b/sdk/lib/async/async.dart
@@ -88,6 +88,8 @@
* [futures-tutorial]: https://www.dartlang.org/docs/tutorials/futures/
* [futures-error-handling]: https://www.dartlang.org/articles/futures-and-error-handling/
* [test-readme]: https://pub.dartlang.org/packages/test
+ *
+ * {@category Core}
*/
library dart.async;
diff --git a/sdk/lib/collection/collection.dart b/sdk/lib/collection/collection.dart
index fd78f9a..7c667ec 100644
--- a/sdk/lib/collection/collection.dart
+++ b/sdk/lib/collection/collection.dart
@@ -4,10 +4,12 @@
/**
* Classes and utilities that supplement the collection support in dart:core.
- *
+ *
* To use this library in your code:
*
* import 'dart:collection';
+ *
+ * {@category Core}
*/
library dart.collection;
diff --git a/sdk/lib/convert/convert.dart b/sdk/lib/convert/convert.dart
index 1255c22..8125f34 100644
--- a/sdk/lib/convert/convert.dart
+++ b/sdk/lib/convert/convert.dart
@@ -50,6 +50,8 @@
*
* See the documentation for the [Codec] and [Converter] classes
* for information about creating your own converters.
+ *
+ * {@category Core}
*/
library dart.convert;
diff --git a/sdk/lib/core/core.dart b/sdk/lib/core/core.dart
index ca55d4a..7b5c901 100644
--- a/sdk/lib/core/core.dart
+++ b/sdk/lib/core/core.dart
@@ -149,6 +149,8 @@
* The
* [Dart Language Specification](http://www.dartlang.org/docs/spec/)
* provides technical details.
+ *
+ * {@category Core}
*/
library dart.core;
diff --git a/sdk/lib/developer/developer.dart b/sdk/lib/developer/developer.dart
index b6ec40d..6c3fa82 100644
--- a/sdk/lib/developer/developer.dart
+++ b/sdk/lib/developer/developer.dart
@@ -12,6 +12,7 @@
///
/// import 'dart:developer';
///
+/// {@category Core}
library dart.developer;
import 'dart:async';
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index c440394..a695e1f 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -102,40 +102,28 @@
JS('returns:HtmlDocument;depends:none;effects:none;gvn:true', 'document');
// Supoort to convert JS Promise to a Dart Future.
-Future<T> promiseToFuture<T>(thePromise) {
+Future<T> promiseToFuture<T>(jsPromise) {
var completer = new Completer<T>();
var thenSuccessCode = (promiseValue) => completer.complete(promiseValue);
var thenErrorCode = (promiseError) => completer.completeError(promiseError);
- JS("", "#.then(#, #)", thePromise, convertDartClosureToJS(thenSuccessCode, 1),
+ JS("", "#.then(#, #)", jsPromise, convertDartClosureToJS(thenSuccessCode, 1),
convertDartClosureToJS(thenErrorCode, 1));
return completer.future;
}
-// Supoort to convert JS Promise to a Dart Future that returns a MapLike (Class with Map mixin).
-Future promiseToFutureMap(thePromise) {
- var completer = new Completer();
-
- var thenSuccessCode = (promiseValue) => completer.complete(promiseValue);
- var thenErrorCode = (promiseError) => completer.completeError(promiseError);
-
- JS("", "#.then(#, #)", thePromise, convertDartClosureToJS(thenSuccessCode, 1),
- convertDartClosureToJS(thenErrorCode, 1));
-
- return completer.future;
-}
-
-// Supoort to convert JS Promise to a Dart Future that returns a Dictionary as a Dart Map.
-Future<Map> promiseToFutureDictionary(thePromise) {
- var completer = new Completer<Map>();
+// Supoort to convert JS Promise to a Dart Future<Map<String, dynamic>>. Each property of the JS
+// object is added to the Map as a key of type String with a value of type dynamic.
+Future<Map<String, dynamic>> promiseToFutureAsMap(jsPromise) {
+ var completer = new Completer<Map<String, dynamic>>();
var thenSuccessCode = (promiseValue) =>
completer.complete(convertNativeToDart_Dictionary(promiseValue));
var thenErrorCode = (promiseError) => completer.completeError(promiseError);
- JS("", "#.then(#, #)", thePromise, convertDartClosureToJS(thenSuccessCode, 1),
+ JS("", "#.then(#, #)", jsPromise, convertDartClosureToJS(thenSuccessCode, 1),
convertDartClosureToJS(thenErrorCode, 1));
return completer.future;
@@ -23376,8 +23364,8 @@
@DomName('ImageCapture.getPhotoSettings')
@DocsEditable()
@Experimental() // untriaged
- Future<Map> getPhotoSettings() =>
- promiseToFutureDictionary(JS("", "#.getPhotoSettings()", this));
+ Future<Map<String, dynamic>> getPhotoSettings() =>
+ promiseToFutureAsMap(JS("", "#.getPhotoSettings()", this));
@DomName('ImageCapture.grabFrame')
@DocsEditable()
@@ -28253,8 +28241,8 @@
@DomName('NavigationPreloadManager.getState')
@DocsEditable()
@Experimental() // untriaged
- Future<Map> getState() =>
- promiseToFutureDictionary(JS("", "#.getState()", this));
+ Future<Map<String, dynamic>> getState() =>
+ promiseToFutureAsMap(JS("", "#.getState()", this));
}
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
@@ -31582,8 +31570,8 @@
@DomName('PaymentInstruments.get')
@DocsEditable()
@Experimental() // untriaged
- Future<Map> get(String instrumentKey) =>
- promiseToFutureDictionary(JS("", "#.get(#)", this, instrumentKey));
+ Future<Map<String, dynamic>> get(String instrumentKey) =>
+ promiseToFutureAsMap(JS("", "#.get(#)", this, instrumentKey));
@DomName('PaymentInstruments.has')
@DocsEditable()
@@ -34806,7 +34794,7 @@
@DomName('RTCPeerConnection.getStats')
@DocsEditable()
- Future getStats() => promiseToFutureMap(JS("", "#.getStats()", this));
+ Future getStats() => promiseToFuture<dynamic>(JS("", "#.getStats()", this));
@DomName('RTCPeerConnection.removeStream')
@DocsEditable()
@@ -37903,8 +37891,8 @@
@DomName('StorageManager.estimate')
@DocsEditable()
@Experimental() // untriaged
- Future<Map> estimate() =>
- promiseToFutureDictionary(JS("", "#.estimate()", this));
+ Future<Map<String, dynamic>> estimate() =>
+ promiseToFutureAsMap(JS("", "#.estimate()", this));
@DomName('StorageManager.persist')
@DocsEditable()
@@ -47644,8 +47632,8 @@
final List<CssClassSetImpl> _sets;
factory _MultiElementCssClassSet(Iterable<Element> elements) {
- return new _MultiElementCssClassSet._(
- elements, elements.map((Element e) => e.classes).toList());
+ return new _MultiElementCssClassSet._(elements,
+ new List<CssClassSetImpl>.from(elements.map((Element e) => e.classes)));
}
_MultiElementCssClassSet._(this._elementIterable, this._sets);
diff --git a/sdk/lib/html/html_common/conversions_dart2js.dart b/sdk/lib/html/html_common/conversions_dart2js.dart
index 0a315ec..f99b357 100644
--- a/sdk/lib/html/html_common/conversions_dart2js.dart
+++ b/sdk/lib/html/html_common/conversions_dart2js.dart
@@ -2,9 +2,9 @@
/// Converts a JavaScript object with properties into a Dart Map.
/// Not suitable for nested objects.
-Map convertNativeToDart_Dictionary(object) {
+Map<String, dynamic> convertNativeToDart_Dictionary(object) {
if (object == null) return null;
- var dict = {};
+ var dict = <String, dynamic>{};
var keys = JS('JSExtendableArray', 'Object.getOwnPropertyNames(#)', object);
for (final key in keys) {
dict[key] = JS('var', '#[#]', object, key);
diff --git a/sdk/lib/js_util/dart2js/js_util_dart2js.dart b/sdk/lib/js_util/dart2js/js_util_dart2js.dart
index ac832ff..6b605fb 100644
--- a/sdk/lib/js_util/dart2js/js_util_dart2js.dart
+++ b/sdk/lib/js_util/dart2js/js_util_dart2js.dart
@@ -60,14 +60,14 @@
newObject() => JS('=Object', '{}');
-hasProperty(o, name) => JS('bool', '# in #', name, o);
+bool hasProperty(o, name) => JS('bool', '# in #', name, o);
getProperty(o, name) => JS('Object|Null', '#[#]', o, name);
setProperty(o, name, value) => JS('', '#[#]=#', o, name, value);
callMethod(o, String method, List args) =>
JS('Object|Null', '#[#].apply(#, #)', o, method, o, args);
-instanceof(o, Function type) => JS('bool', '# instanceof #', o, type);
+bool instanceof(o, Function type) => JS('bool', '# instanceof #', o, type);
callConstructor(Function constr, List arguments) {
if (arguments == null) {
return JS('Object', 'new #()', constr);
diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json
index 9f3f684..d7ed7b0 100644
--- a/sdk/lib/libraries.json
+++ b/sdk/lib/libraries.json
@@ -17,7 +17,6 @@
"../../runtime/lib/core_patch.dart",
"../../runtime/lib/array.dart",
"../../runtime/lib/array_patch.dart",
- "../../runtime/lib/bigint.dart",
"../../runtime/lib/bigint_patch.dart",
"../../runtime/lib/bool_patch.dart",
"../../runtime/lib/date_patch.dart",
diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml
index 92c2391..82a6466 100644
--- a/sdk/lib/libraries.yaml
+++ b/sdk/lib/libraries.yaml
@@ -49,7 +49,6 @@
- "../../runtime/lib/core_patch.dart"
- "../../runtime/lib/array.dart"
- "../../runtime/lib/array_patch.dart"
- - "../../runtime/lib/bigint.dart"
- "../../runtime/lib/bigint_patch.dart"
- "../../runtime/lib/bool_patch.dart"
- "../../runtime/lib/date_patch.dart"
diff --git a/sdk/lib/math/math.dart b/sdk/lib/math/math.dart
index 8e0a30f..c975413 100644
--- a/sdk/lib/math/math.dart
+++ b/sdk/lib/math/math.dart
@@ -8,6 +8,8 @@
* To use this library in your code:
*
* import 'dart:math';
+ *
+ * {@category Core}
*/
library dart.math;
diff --git a/sdk/lib/typed_data/typed_data.dart b/sdk/lib/typed_data/typed_data.dart
index d4a1e0e..3b284b5 100644
--- a/sdk/lib/typed_data/typed_data.dart
+++ b/sdk/lib/typed_data/typed_data.dart
@@ -8,6 +8,8 @@
/// To use this library in your code:
///
/// import 'dart:typed_data';
+///
+/// {@category Core}
library dart.typed_data;
import "dart:_internal" show UnmodifiableListBase;
diff --git a/sdk/lib/vmservice/client.dart b/sdk/lib/vmservice/client.dart
index 7e0fdd8..efe33c0 100644
--- a/sdk/lib/vmservice/client.dart
+++ b/sdk/lib/vmservice/client.dart
@@ -41,7 +41,7 @@
void onRequest(Message message) {
// In JSON-RPC 2.0 messages with and id are Request and must be answered
// http://www.jsonrpc.org/specification#notification
- service.routeRequest(message).then(post);
+ service.routeRequest(service, message).then(post);
}
void onResponse(Message message) {
@@ -53,7 +53,7 @@
// In JSON-RPC 2.0 messages without an id are Notification
// and should not be answered
// http://www.jsonrpc.org/specification#notification
- service.routeRequest(message);
+ service.routeRequest(service, message);
}
// Sends a result to the client. Implemented in subclasses.
diff --git a/sdk/lib/vmservice/message_router.dart b/sdk/lib/vmservice/message_router.dart
index 21368a6..7248303 100644
--- a/sdk/lib/vmservice/message_router.dart
+++ b/sdk/lib/vmservice/message_router.dart
@@ -5,7 +5,7 @@
part of dart._vmservice;
abstract class MessageRouter {
- Future<Response> routeRequest(Message message);
+ Future<Response> routeRequest(VMService service, Message message);
void routeResponse(Message message);
}
diff --git a/sdk/lib/vmservice/running_isolate.dart b/sdk/lib/vmservice/running_isolate.dart
index a1339f0..8a6dd36 100644
--- a/sdk/lib/vmservice/running_isolate.dart
+++ b/sdk/lib/vmservice/running_isolate.dart
@@ -13,10 +13,12 @@
String get serviceId => 'isolates/$portId';
- Future<Response> routeRequest(Message message) {
+ @override
+ Future<Response> routeRequest(VMService service, Message message) {
// Send message to isolate.
return message.sendToIsolate(sendPort);
}
+ @override
void routeResponse(Message message) {}
}
diff --git a/sdk/lib/vmservice/running_isolates.dart b/sdk/lib/vmservice/running_isolates.dart
index 8f284d8..1b44ee3 100644
--- a/sdk/lib/vmservice/running_isolates.dart
+++ b/sdk/lib/vmservice/running_isolates.dart
@@ -25,7 +25,8 @@
isolates.remove(portId);
}
- Future<Response> routeRequest(Message message) {
+ @override
+ Future<Response> routeRequest(VMService service, Message message) {
String isolateParam = message.params['isolateId'];
int isolateId;
if (!isolateParam.startsWith('isolates/')) {
@@ -57,8 +58,139 @@
message.setResponse(encodeResult(message, result));
return message.response;
}
- return isolate.routeRequest(message);
+
+ if (message.method == 'evaluateInFrame') {
+ return new _Evaluator(message, isolate, service).run();
+ } else {
+ return isolate.routeRequest(service, message);
+ }
}
+ @override
void routeResponse(Message message) {}
}
+
+/// Class that knows how to orchestrate expression evaluation in dart2 world.
+class _Evaluator {
+ _Evaluator(this._message, this._isolate, this._service);
+
+ Future<Response> run() async {
+ Response buildScopeResponse = await _buildScope();
+ dynamic responseJson = buildScopeResponse.decodeJson();
+ String kernelBase64;
+ try {
+ kernelBase64 = await _compileExpression(responseJson['result']);
+ } catch (e) {
+ return Response.from(encodeCompilationError(_message, e.toString()));
+ }
+ return _evaluateCompiledExpression(kernelBase64);
+ }
+
+ Message _message;
+ RunningIsolate _isolate;
+ VMService _service;
+
+ Future<Response> _buildScope() {
+ Map buildScopeParams = {
+ 'method': '_buildExpressionEvaluationScope',
+ 'id': _message.serial,
+ 'params': {
+ 'isolateId': _message.params['isolateId'],
+ 'frameIndex': _message.params['frameIndex'],
+ },
+ };
+ if (_message.params['scope'] != null) {
+ buildScopeParams['params']['scope'] = _message.params['scope'];
+ }
+ var buildScope =
+ new Message._fromJsonRpcRequest(_message.client, buildScopeParams);
+
+ // Decode the JSON and and insert it into the map. The map key
+ // is the request Uri.
+ return _isolate.routeRequest(_service, buildScope);
+ }
+
+ Future<String> _compileExpression(
+ Map<String, dynamic> buildScopeResponseResult) {
+ Client externalClient =
+ _service._findFirstClientThatHandlesService('compileExpression');
+
+ Map compileParams = {
+ 'isolateId': _message.params['isolateId'],
+ 'expression': _message.params['expression'],
+ 'definitions': buildScopeResponseResult['param_names'],
+ 'typeDefinitions': buildScopeResponseResult['type_params_names'],
+ 'libraryUri': buildScopeResponseResult['libraryUri'],
+ 'isStatic': buildScopeResponseResult['isStatic'],
+ };
+ dynamic klass = buildScopeResponseResult['klass'];
+ if (klass != null) {
+ compileParams['klass'] = klass;
+ }
+ if (externalClient != null) {
+ var compileExpression = new Message.forMethod('compileExpression');
+ compileExpression.client = externalClient;
+ compileExpression.params.addAll(compileParams);
+
+ final id = _service._serviceRequests.newId();
+ final oldId = _message.serial;
+ final completer = new Completer<String>();
+ externalClient.serviceHandles[id] = (Message m) {
+ if (m != null) {
+ completer.complete(json.encode(m.forwardToJson({'id': oldId})));
+ } else {
+ completer.complete(encodeRpcError(_message, kServiceDisappeared));
+ }
+ };
+ externalClient.post(new Response.json(compileExpression
+ .forwardToJson({'id': id, 'method': 'compileExpression'})));
+ return completer.future
+ .then((String s) => jsonDecode(s))
+ .then((dynamic json) {
+ return json['result']['result']['kernelBytes'];
+ });
+ } else {
+ // fallback to compile using kernel service
+ Map compileExpressionParams = {
+ 'method': '_compileExpression',
+ 'id': _message.serial,
+ 'params': compileParams,
+ };
+ var compileExpression = new Message._fromJsonRpcRequest(
+ _message.client, compileExpressionParams);
+
+ return _isolate
+ .routeRequest(_service, compileExpression)
+ .then((Response response) => response.decodeJson())
+ .then((dynamic json) {
+ if (json['result'] != null) {
+ return json['result']['kernelBytes'];
+ }
+ throw json['error']['data']['details'];
+ });
+ }
+ }
+
+ Future<Response> _evaluateCompiledExpression(String kernelBase64) {
+ if (kernelBase64.isNotEmpty) {
+ Map runParams = {
+ 'method': '_evaluateCompiledExpression',
+ 'id': _message.serial,
+ 'params': {
+ 'isolateId': _message.params['isolateId'],
+ 'frameIndex': _message.params['frameIndex'],
+ 'kernelBytes': kernelBase64,
+ },
+ };
+ if (_message.params['scope'] != null) {
+ runParams['params']['scope'] = _message.params['scope'];
+ }
+ var runExpression =
+ new Message._fromJsonRpcRequest(_message.client, runParams);
+ return _isolate.routeRequest(_service, runExpression); // _message
+ } else {
+ // empty kernel indicates dart1 mode
+ return _isolate.routeRequest(_service, _message);
+ }
+ }
+}
diff --git a/sdk/lib/vmservice/vmservice.dart b/sdk/lib/vmservice/vmservice.dart
index a59e7ca..f321876 100644
--- a/sdk/lib/vmservice/vmservice.dart
+++ b/sdk/lib/vmservice/vmservice.dart
@@ -68,8 +68,10 @@
const kCannotResume = 107;
const kIsolateIsReloading = 108;
const kIsolateReloadBarred = 109;
-const kServiceAlreadyRegistered = 110;
-const kServiceDisappeared = 111;
+const kIsolateMustHaveReloaded = 110;
+const kServiceAlreadyRegistered = 111;
+const kServiceDisappeared = 112;
+const kExpressionCompilationError = 113;
// Experimental (used in private rpcs).
const kFileSystemAlreadyExists = 1001;
@@ -87,6 +89,7 @@
kFileDoesNotExist: 'File does not exist',
kServiceAlreadyRegistered: 'Service already registered',
kServiceDisappeared: 'Service has disappeared',
+ kExpressionCompilationError: 'Expression compilation error',
};
String encodeRpcError(Message message, int code, {String details}) {
@@ -117,6 +120,11 @@
details: "${message.method}: invalid '${param}' parameter: ${value}");
}
+String encodeCompilationError(Message message, String diagnostic) {
+ return encodeRpcError(message, kExpressionCompilationError,
+ details: diagnostic);
+}
+
String encodeResult(Message message, Map result) {
var response = {
'jsonrpc': '2.0',
@@ -233,7 +241,7 @@
}
}));
}
- // Complete all requestes as failed
+ // Complete all requests as failed
for (var handle in client.serviceHandles.values) {
handle(null);
}
@@ -358,6 +366,17 @@
return false;
}
+ Client _findFirstClientThatHandlesService(String service) {
+ if (clients != null) {
+ for (Client c in clients) {
+ if (c.services.containsKey(service)) {
+ return c;
+ }
+ }
+ }
+ return null;
+ }
+
static const kServiceStream = '_Service';
static const serviceStreams = const [kServiceStream];
@@ -571,13 +590,13 @@
var message = new Message.forIsolate(client, request, isolate);
// Decode the JSON and and insert it into the map. The map key
// is the request Uri.
- var response = (await isolate.routeRequest(message)).decodeJson();
+ var response = (await isolate.routeRequest(this, message)).decodeJson();
responses[message.toUri().toString()] = response['result'];
}
// Dump the object id ring requests.
var message =
new Message.forIsolate(client, Uri.parse('_dumpIdZone'), isolate);
- var response = (await isolate.routeRequest(message)).decodeJson();
+ var response = (await isolate.routeRequest(this, message)).decodeJson();
// Insert getObject requests into responses map.
for (var object in response['result']['objects']) {
final requestUri =
@@ -590,7 +609,7 @@
return encodeResult(message, responses);
}
- Future<Response> routeRequest(Message message) async {
+ Future<Response> routeRequest(VMService _, Message message) async {
return new Response.from(await _routeRequestImpl(message));
}
@@ -622,7 +641,7 @@
return await _handleService(message);
}
if (message.params['isolateId'] != null) {
- return await runningIsolates.routeRequest(message);
+ return await runningIsolates.routeRequest(this, message);
}
return await message.sendToVM();
} catch (e, st) {
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 74c7866..e85002f 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -1367,15 +1367,12 @@
WebPlatformTest/shadow-dom/shadow-trees/upper-boundary-encapsulation/ownerdocument-001_t01: RuntimeError # Please triage this failure
[ $compiler == dart2js && $runtime == chrome && $csp && $minified ]
-LayoutTests/fast/css/fontface-properties_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/css/inherited-properties-rare-text_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/HTMLScriptElement/isURLAttribute_t01: SkipByDesign # Uses script injection
LayoutTests/fast/dom/HTMLScriptElement/remove-source_t01: Pass # Please triage this failure
LayoutTests/fast/dom/HTMLScriptElement/script-for-attribute-unexpected-execution_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/HTMLScriptElement/script-reexecution_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/HTMLTemplateElement/inertContents_t01: RuntimeError # Please triage this failure
LayoutTests/fast/dom/Range/create-contextual-fragment-script-unmark-already-started_t01: RuntimeError # Please triage this failure
-LayoutTests/fast/dom/shadow/elementfrompoint_t01: RuntimeError # Please triage this failure
LayoutTests/fast/files/workers/inline-worker-via-blob-url_t01: SkipByDesign # inlined script
LayoutTests/fast/loader/scroll-position-restored-on-back_t01: Skip # Timeout. Please triage this failure
WebPlatformTest/webstorage/event_local_key_t01: Skip # Timeout. Please triage this failure.
@@ -7053,6 +7050,7 @@
LayoutTests/fast/canvas/rgba-parsing_t01: Pass, RuntimeError
LibTest/core/Invocation/namedArguments_A01_t01: RuntimeError
LibTest/core/double/isInfinite_A01_t03: CompileTimeError # Larger than 64 bit int
+LibTest/core/double/operator_GE_A01_t02: RuntimeError # WontFix: Not representable in JS.
LibTest/core/int/abs_A01_t01: CompileTimeError # Larger than 64 bit int
LibTest/core/int/ceilToDouble_A01_t01: CompileTimeError # Larger than 64 bit int
LibTest/core/int/ceil_A01_t01: CompileTimeError # Larger than 64 bit int
@@ -7105,6 +7103,7 @@
LibTest/html/Window/requestFileSystem_A01_t01: Crash
LibTest/html/Window/requestFileSystem_A01_t02: Crash
LibTest/html/Window/requestFileSystem_A02_t01: Crash
+LibTest/math/pow_A09_t01: RuntimeError # WontFix: Not representable in JS.
LibTest/math/pow_A10_t01: CompileTimeError # Larger than 64 bit int
WebPlatformTest/html/semantics/embedded-content/the-audio-element/audio_constructor_t01: RuntimeError
diff --git a/tests/co19/co19-kernel.status b/tests/co19/co19-kernel.status
index 94f990f..4f64cd4 100644
--- a/tests/co19/co19-kernel.status
+++ b/tests/co19/co19-kernel.status
@@ -147,8 +147,6 @@
Language/Classes/Constructors/Factories/default_value_t01: MissingCompileTimeError
Language/Classes/Constructors/Factories/default_value_t02: MissingCompileTimeError
Language/Classes/Constructors/Factories/function_type_t02: CompileTimeError
-Language/Classes/Constructors/Factories/name_t03: MissingCompileTimeError
-Language/Classes/Constructors/Factories/name_t05: MissingCompileTimeError
Language/Classes/Constructors/Factories/redirecting_constructor_call_t01: CompileTimeError
Language/Classes/Constructors/Factories/redirecting_constructor_call_t02: CompileTimeError
Language/Classes/Constructors/Factories/return_type_t02: CompileTimeError
@@ -1686,10 +1684,6 @@
Language/Classes/Constructors/Factories/const_modifier_t02: MissingCompileTimeError
Language/Classes/Constructors/Factories/default_value_t01: MissingCompileTimeError
Language/Classes/Constructors/Factories/default_value_t02: MissingCompileTimeError
-Language/Classes/Constructors/Factories/name_t01: MissingCompileTimeError
-Language/Classes/Constructors/Factories/name_t03: MissingCompileTimeError
-Language/Classes/Constructors/Factories/name_t04: MissingCompileTimeError
-Language/Classes/Constructors/Factories/name_t05: MissingCompileTimeError
Language/Classes/Constructors/Generative_Constructors/execution_t04: MissingCompileTimeError
Language/Classes/Constructors/Generative_Constructors/execution_t06: MissingCompileTimeError
Language/Classes/Constructors/Generative_Constructors/execution_t07: MissingCompileTimeError
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 2dd3260..3ff64e2 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -244,6 +244,9 @@
LibTest/collection/ListMixin/ListMixin_class_A01_t02: Skip # Timeout
LibTest/core/Uri/Uri_A06_t03: Skip # Timeout
+[ $compiler == app_jit || $compiler == none || $compiler == precompiler ]
+Language/Expressions/Function_Invocation/async_invokation_t02: RuntimeError # sync-async is on by default.
+
[ $compiler == app_jit || $compiler == precompiler ]
Language/Mixins/Mixin_Application/error_t01: Pass
Language/Mixins/Mixin_Application/error_t02: Pass
@@ -420,3 +423,8 @@
LibTest/core/Uri/encodeQueryComponent_A01_t02: Pass, Timeout
LibTest/isolate/Isolate/spawn_A01_t04: Pass, Timeout
LibTest/isolate/ReceivePort/take_A01_t02: Skip # Issue 27773
+
+[ $hot_reload || $hot_reload_rollback ]
+LibTest/isolate/ReceivePort/firstWhere_A01_t01: Crash # Issue 33363
+LibTest/isolate/ReceivePort/firstWhere_A02_t01: Crash # Issue 33363
+LibTest/isolate/ReceivePort/lastWhere_A02_t01: Crash # Issue 33363
diff --git a/tests/compiler/dart2js/codegen/class_codegen_test.dart b/tests/compiler/dart2js/codegen/class_codegen_test.dart
index b27fda4..63f28ba 100644
--- a/tests/compiler/dart2js/codegen/class_codegen_test.dart
+++ b/tests/compiler/dart2js/codegen/class_codegen_test.dart
@@ -38,13 +38,14 @@
""";
const String TEST_FOUR = r"""
+var g = 0;
class A {
- var x;
+ var x = g++;
}
class B extends A {
- var y;
- var z;
+ var y = g++;
+ var z = g++;
}
main() {
diff --git a/tests/compiler/dart2js/impact/data/jsinterop.dart b/tests/compiler/dart2js/impact/data/jsinterop.dart
index b063cee..3c966dd 100644
--- a/tests/compiler/dart2js/impact/data/jsinterop.dart
+++ b/tests/compiler/dart2js/impact/data/jsinterop.dart
@@ -7,8 +7,9 @@
import 'package:js/js.dart';
-/*element: main:static=[testJsInteropClass(0),testJsInteropMethod(0)]*/
+/*element: main:static=[testJsInteropClass(0),testJsInteropMethod(0),testOptionalGenericFunctionTypeArgument(0)]*/
main() {
+ testOptionalGenericFunctionTypeArgument();
testJsInteropMethod();
testJsInteropClass();
}
@@ -30,6 +31,7 @@
native:DomError,
native:DomException,
native:ErrorEvent,
+ native:GenericClass<dynamic>,
native:JsInteropClass,
native:MediaError,
native:NavigatorUserMediaError,
@@ -45,6 +47,7 @@
native:DomError,
native:DomException,
native:ErrorEvent,
+ native:GenericClass<dynamic>,
native:JsInteropClass,
native:MediaError,
native:NavigatorUserMediaError,
@@ -60,3 +63,38 @@
/*element: testJsInteropClass:dynamic=[method(0)],static=[JsInteropClass.(0)]*/
testJsInteropClass() => new JsInteropClass().method();
+
+typedef void Callback<T>(T value);
+
+/*element: GenericClass.:static=[JavaScriptObject.(0)]*/
+@JS()
+class GenericClass<T> {
+ /*kernel.element: GenericClass.method:
+ type=[
+ check:GenericClass<dynamic>,
+ check:void Function(GenericClass.T),
+ inst:JSNull]
+ */
+ /*strong.element: GenericClass.method:
+ static=[
+ checkSubtype,
+ getRuntimeTypeArgument,
+ getRuntimeTypeArgumentIntercepted,
+ getRuntimeTypeInfo,
+ getTypeArgumentByIndex,
+ setRuntimeTypeInfo],
+ type=[
+ inst:JSArray<dynamic>,
+ inst:JSBool,
+ inst:JSExtendableArray<dynamic>,
+ inst:JSFixedArray<dynamic>,
+ inst:JSMutableArray<dynamic>,
+ inst:JSNull,
+ inst:JSUnmodifiableArray<dynamic>,
+ param:void Function(GenericClass.T)]
+ */
+ external GenericClass method([Callback<T> callback]);
+}
+
+/*element: testOptionalGenericFunctionTypeArgument:dynamic=[method(0)],static=[GenericClass.(0)]*/
+testOptionalGenericFunctionTypeArgument() => new GenericClass().method();
diff --git a/tests/compiler/dart2js/inference/side_effects_test.dart b/tests/compiler/dart2js/inference/side_effects_test.dart
index 05f713e..3920656 100644
--- a/tests/compiler/dart2js/inference/side_effects_test.dart
+++ b/tests/compiler/dart2js/inference/side_effects_test.dart
@@ -9,6 +9,7 @@
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
import 'package:compiler/src/elements/entities.dart';
+import 'package:compiler/src/js_backend/inferred_data.dart';
import 'package:compiler/src/kernel/element_map.dart';
import 'package:compiler/src/kernel/kernel_backend_strategy.dart';
import 'package:compiler/src/world.dart';
@@ -28,11 +29,11 @@
}
abstract class ComputeValueMixin<T> {
- JClosedWorld get closedWorld;
+ InferredData get inferredData;
String getMemberValue(MemberEntity member) {
if (member is FunctionEntity) {
- return closedWorld.getSideEffectsOfElement(member).toString();
+ return inferredData.getSideEffectsOfElement(member).toString();
}
return null;
}
@@ -52,7 +53,8 @@
actualMap,
elementMap,
compiler.backendClosedWorldForTesting,
- backendStrategy.closureDataLookup as ClosureDataLookup<ir.Node>)
+ backendStrategy.closureDataLookup as ClosureDataLookup<ir.Node>,
+ compiler.globalInference.inferredData)
.run(definition.node);
}
@@ -62,13 +64,15 @@
final JClosedWorld closedWorld;
final KernelToElementMapForBuilding _elementMap;
final ClosureDataLookup<ir.Node> _closureDataLookup;
+ final InferredData inferredData;
SideEffectsIrComputer(
DiagnosticReporter reporter,
Map<Id, ActualData> actualMap,
this._elementMap,
this.closedWorld,
- this._closureDataLookup)
+ this._closureDataLookup,
+ this.inferredData)
: super(reporter, actualMap);
@override
diff --git a/tests/compiler/dart2js/rti/emission/constructor_argument_static_strong.dart b/tests/compiler/dart2js/rti/emission/constructor_argument_static_strong.dart
new file mode 100644
index 0000000..37dfefe
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/constructor_argument_static_strong.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:meta/dart2js.dart';
+
+/*class: A1:checks=[],instance*/
+class A1 {}
+
+// Constructor calls are always statically invoked, so there is no checks at the
+// entry and the `Test1` constructor does not cause any checks.
+/*class: B1:checks=[],instance*/
+class B1 implements A1 {}
+
+/*class: Test1:checks=[],instance*/
+class Test1 {
+ A1 x;
+ @noInline
+ Test1(this.x);
+}
+
+/*class: A2:checks=[],instance*/
+class A2 {}
+
+// Constructor bodies are always statically resolved, so there is no checks at
+// the entry and the `Test2` constructor body does not cause any checks.
+/*class: B2:checks=[],instance*/
+class B2 implements A2 {}
+
+/*class: Test2:checks=[]*/
+abstract class Test2 {
+ @noInline
+ Test2(A2 x) {
+ print(x);
+ }
+}
+
+/*class: Use:checks=[],instance*/
+class Use extends Test2 {
+ Use.A2() : super(new A2());
+ Use.B2() : super(new B2());
+}
+
+main() {
+ new Test1(new A1());
+ new Test1(new B1());
+ new Test1(null);
+
+ new Use.A2();
+ new Use.B2();
+}
diff --git a/tests/compiler/dart2js/rti/emission/static_argument_strong.dart b/tests/compiler/dart2js/rti/emission/static_argument_strong.dart
new file mode 100644
index 0000000..7bdc190
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/static_argument_strong.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:meta/dart2js.dart';
+
+/*class: I1:checkedInstance*/
+class I1 {}
+
+/*class: I2:checkedInstance,checkedTypeArgument,checks=[],typeArgument*/
+class I2 {}
+
+// TODO(32954): Exclude $isI1 because foo is only called directly.
+/*class: A:checks=[$isI1,$isI2],instance*/
+class A implements I1, I2 {}
+
+// TODO(32954): Exclude $isI1 because foo is only called directly.
+/*class: B:checks=[$isI1,$isI2],instance*/
+class B implements I1, I2 {}
+
+@noInline
+void foo(I1 x) {}
+
+@noInline
+void bar(I2 x) {}
+
+main() {
+ dynamic f = bar;
+
+ foo(new A());
+ foo(new B());
+ f(new A());
+ f(new B());
+}
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index c89576d..a6970b9 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -66,6 +66,7 @@
from_environment_const_type_test/16: MissingCompileTimeError # Flutter Issue 9111
from_environment_const_type_test/none: Fail # Flutter Issue 9111
int_from_environment2_test: Fail # Flutter Issue 9111
+int_from_environment_int64_test: Fail # Flutter Issue 9111
int_from_environment_test: Fail # Flutter Issue 9111
main_test: RuntimeError # Flutter Issue 9111
string_from_environment2_test: Fail # Flutter Issue 9111
@@ -212,8 +213,6 @@
cast_test: RuntimeError
error_stack_trace1_test: RuntimeError
growable_list_test: RuntimeError
-int_parse_radix_test/01: RuntimeError
-int_parse_radix_test/02: RuntimeError
integer_to_radix_string_test/01: RuntimeError
integer_to_radix_string_test/02: RuntimeError
integer_to_radix_string_test/none: RuntimeError
@@ -225,19 +224,21 @@
string_split_test/checkedstore: RuntimeError
symbol_reserved_word_test/03: RuntimeError # Issue 19972, new Symbol('void') should be allowed.
uri_base_test: Crash # RangeError (index): Invalid value: Valid value range is empty: 0
-uri_parameters_all_test: RuntimeError
-uri_test: RuntimeError
[ $compiler == dart2js && $fasta ]
-int_from_environment_test: Pass # Issue 31762
-int_parse_radix_test/none: Pass # Issue 31762
+int_from_environment_int64_test: RuntimeError # WontFix: Int not precisely representable in JS
+int_parse_radix_int64_test/01: RuntimeError # WontFix: Int not precisely representable in JS
+int_parse_radix_int64_test/02: RuntimeError # WontFix: Int not precisely representable in JS
+int_parse_radix_int64_test/none: RuntimeError # WontFix: Int not precisely representable in JS
+int_parse_radix_test/01: RuntimeError
+int_parse_radix_test/badTypes: RuntimeError # Issue 33351
+int_parse_radix_test/none: RuntimeError # Issue 33351
+int_try_parse_int64_test: RuntimeError # WontFix: Int not precisely representable in JS
[ $compiler == dart2js && $fasta && $host_checked && $strong ]
cast_test: RuntimeError
error_stack_trace1_test: RuntimeError # Issue 12399
growable_list_test: RuntimeError # Concurrent modifications test always runs
-int_parse_radix_test/01: RuntimeError
-int_parse_radix_test/02: RuntimeError
integer_to_radix_string_test/01: RuntimeError
integer_to_radix_string_test/02: RuntimeError
integer_to_radix_string_test/none: RuntimeError
@@ -251,8 +252,6 @@
string_split_test/checkedstore: RuntimeError # Issue 30548: does not check stores into List<String>
symbol_reserved_word_test/03: RuntimeError # Issue 19972, new Symbol('void') should be allowed.
uri_base_test: RuntimeError
-uri_parameters_all_test: RuntimeError
-uri_test: RuntimeError
[ $compiler == dart2js && $fasta && $minified && $strong ]
cast_test: RuntimeError
@@ -260,7 +259,6 @@
error_stack_trace1_test: RuntimeError # Issue 12399
growable_list_test: RuntimeError # Concurrent modifications test always runs
hash_set_test/01: Crash # Assertion failure: Cannot find value Instance of 'ThisLocal' in (local(_CustomHashSet.#x), local(_CustomHashSet.#)) for j:closure_call(_CustomHashSet__CustomHashSet_closure.call).
-int_parse_radix_test/01: RuntimeError
int_parse_radix_test/02: RuntimeError
integer_to_radix_string_test/01: RuntimeError
integer_to_radix_string_test/02: RuntimeError
@@ -278,8 +276,6 @@
symbol_operator_test/none: RuntimeError
symbol_reserved_word_test/03: RuntimeError # Issue 19972, new Symbol('void') should be allowed.
uri_base_test: RuntimeError
-uri_parameters_all_test: RuntimeError
-uri_test: RuntimeError
[ $compiler == dart2js && $fasta && !$strong ]
*: SkipByDesign
@@ -304,9 +300,6 @@
string_replace_static_test: MissingCompileTimeError
string_static_test: MissingCompileTimeError
-[ $compiler == dartk && $mode == debug && $hot_reload ]
-map_test: Crash
-
[ $compiler == dartk && $mode == release && $hot_reload ]
bigint_parse_radix_test: Crash
@@ -408,14 +401,14 @@
typed_data_with_limited_ints_test: Skip # Requires fixed-size int64 support.
[ $runtime != none && ($compiler == dartdevc || $compiler == dartdevk) ]
-bigint_test: Pass, Slow
+bigint_test: Pass, Slow, Timeout
compare_to2_test: RuntimeError # Issue 30170
date_time10_test: RuntimeError # Issue 29921
error_stack_trace_test/nullThrown: RuntimeError # .stackTrace not present for exception caught from 'throw null;'
hash_set_test/01: RuntimeError # Issue 29921
int_modulo_arith_test/none: RuntimeError # Issue 29921
+int_parse_radix_int64_test/02: RuntimeError
int_parse_radix_test/01: RuntimeError # Issue 29921
-int_parse_radix_test/02: RuntimeError # Issue 29921
int_parse_with_limited_ints_test: Skip # Requires fixed-size int64 support.
integer_arith_vm_test/modPow: RuntimeError # Issue 30170
integer_parsed_arith_vm_test: RuntimeError # Issue 29921
@@ -473,6 +466,7 @@
symbol_reserved_word_test/12: RuntimeError # Issue 29921
symbol_test/none: RuntimeError # Issue 29921
typed_data_with_limited_ints_test: Skip # Requires fixed-size int64 support.
+uri_parse_test: Pass, Slow
[ $runtime == vm && !$strong ]
collection_of_test: RuntimeError
diff --git a/tests/corelib_2/int_from_environment_int64_test.dart b/tests/corelib_2/int_from_environment_int64_test.dart
new file mode 100644
index 0000000..b734556
--- /dev/null
+++ b/tests/corelib_2/int_from_environment_int64_test.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// SharedOptions=-Df=-9223372036854775808 -Dg=9223372036854775807
+
+import "package:expect/expect.dart";
+
+main() {
+ Expect.equals(-9223372036854775808, const int.fromEnvironment('f'));
+ Expect.equals(9223372036854775807, const int.fromEnvironment('g'));
+}
diff --git a/tests/corelib_2/int_from_environment_test.dart b/tests/corelib_2/int_from_environment_test.dart
index 5628ccd..62b1f1a 100644
--- a/tests/corelib_2/int_from_environment_test.dart
+++ b/tests/corelib_2/int_from_environment_test.dart
@@ -1,7 +1,7 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// SharedOptions=-Da=1 -Db=-12 -Dc=0x123 -Dd=-0x1234 -De=+0x112296 -Df=-9223372036854775808 -Dg=9223372036854775807
+// SharedOptions=-Da=1 -Db=-12 -Dc=0x123 -Dd=-0x1234 -De=+0x112296 -Df=-9007199254740991 -Dg=9007199254740991
import "package:expect/expect.dart";
@@ -11,6 +11,6 @@
Expect.equals(0x123, const int.fromEnvironment('c'));
Expect.equals(-0x1234, const int.fromEnvironment('d'));
Expect.equals(0x112296, const int.fromEnvironment('e'));
- Expect.equals(-9223372036854775808, const int.fromEnvironment('f'));
- Expect.equals(9223372036854775807, const int.fromEnvironment('g'));
+ Expect.equals(-9007199254740991, const int.fromEnvironment('f'));
+ Expect.equals(9007199254740991, const int.fromEnvironment('g'));
}
diff --git a/tests/corelib_2/int_parse_radix_int64_test.dart b/tests/corelib_2/int_parse_radix_int64_test.dart
new file mode 100644
index 0000000..7a6fe18
--- /dev/null
+++ b/tests/corelib_2/int_parse_radix_int64_test.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+import "dart:math" show pow, log;
+
+void main() {
+ const String oneByteWhiteSpace = "\x09\x0a\x0b\x0c\x0d\x20"
+ "\x85" //# 01: ok
+ "\xa0";
+ const String whiteSpace = "$oneByteWhiteSpace\u1680"
+ "\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a"
+ "\u2028\u2029\u202f\u205f\u3000\ufeff";
+
+ var digits = "0123456789abcdefghijklmnopqrstuvwxyz";
+ var zeros = "0" * 64;
+
+ void testParse(int result, String radixString, int radix) {
+ var m = "$radixString/$radix->$result";
+ Expect.equals(
+ result, int.parse(radixString.toLowerCase(), radix: radix), m);
+ Expect.equals(
+ result, int.parse(radixString.toUpperCase(), radix: radix), m);
+ Expect.equals(result, int.parse(" $radixString", radix: radix), m);
+ Expect.equals(result, int.parse("$radixString ", radix: radix), m);
+ Expect.equals(result, int.parse(" $radixString ", radix: radix), m);
+ Expect.equals(result, int.parse("+$radixString", radix: radix), m);
+ Expect.equals(result, int.parse(" +$radixString", radix: radix), m);
+ Expect.equals(result, int.parse("+$radixString ", radix: radix), m);
+ Expect.equals(result, int.parse(" +$radixString ", radix: radix), m);
+ Expect.equals(-result, int.parse("-$radixString", radix: radix), m);
+ Expect.equals(-result, int.parse(" -$radixString", radix: radix), m);
+ Expect.equals(-result, int.parse("-$radixString ", radix: radix), m);
+ Expect.equals(-result, int.parse(" -$radixString ", radix: radix), m);
+ Expect.equals(
+ result,
+ int.parse("$oneByteWhiteSpace$radixString$oneByteWhiteSpace",
+ radix: radix),
+ m);
+ Expect.equals(
+ -result,
+ int.parse("$oneByteWhiteSpace-$radixString$oneByteWhiteSpace",
+ radix: radix),
+ m);
+ Expect.equals(result,
+ int.parse("$whiteSpace$radixString$whiteSpace", radix: radix), m);
+ Expect.equals(-result,
+ int.parse("$whiteSpace-$radixString$whiteSpace", radix: radix), m);
+
+ Expect.equals(result, int.parse("$zeros$radixString", radix: radix), m);
+ Expect.equals(result, int.parse("+$zeros$radixString", radix: radix), m);
+ Expect.equals(-result, int.parse("-$zeros$radixString", radix: radix), m);
+ }
+
+ final max = 9223372036854775807;
+ for (int i = 2; i <= 36; i++) { // //# 02: ok
+ // Test with bignums. // //# 02: continued
+ final n = (log(max) / log(i)).truncate(); // //# 02: continued
+ var digit = digits[i - 1]; // //# 02: continued
+ testParse(pow(i, n) - 1, digit * n, i); // //# 02: continued
+ testParse(0, zeros, i); // //# 02: continued
+ } // //# 02: continued
+
+ // Big number.
+ Expect.equals(9223372036854775807, int.parse("9223372036854775807"));
+ Expect.equals(-9223372036854775808, int.parse("-9223372036854775808"));
+}
diff --git a/tests/corelib_2/int_parse_radix_test.dart b/tests/corelib_2/int_parse_radix_test.dart
index cf49135..d7ca92a 100644
--- a/tests/corelib_2/int_parse_radix_test.dart
+++ b/tests/corelib_2/int_parse_radix_test.dart
@@ -65,7 +65,7 @@
}
}
- final max = 9223372036854775807;
+ final max = 0x1FFFFFFFFFFFFF;
for (int i = 2; i <= 36; i++) { // //# 02: ok
// Test with bignums. // //# 02: continued
final n = (log(max) / log(i)).truncate(); // //# 02: continued
@@ -78,8 +78,9 @@
Expect.equals(0xABCD, int.parse("ABCD", radix: 16));
Expect.equals(0xABCD, int.parse("abcd", radix: 16));
Expect.equals(15628859, int.parse("09azAZ", radix: 36));
- // Big number.
- Expect.equals(9223372036854775807, int.parse("9223372036854775807"));
+ // Big-ish number. (2^53)
+ Expect.equals(9007199254740991, int.parse("9007199254740991"));
+ Expect.equals(-9007199254740991, int.parse("-9007199254740991"));
Expect.equals(-9223372036854775808, int.parse("-9223372036854775808"));
// Allow whitespace before and after the number.
Expect.equals(1, int.parse(" 1", radix: 2));
diff --git a/tests/corelib_2/int_try_parse_int64_test.dart b/tests/corelib_2/int_try_parse_int64_test.dart
new file mode 100644
index 0000000..419da75
--- /dev/null
+++ b/tests/corelib_2/int_try_parse_int64_test.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+import "dart:math" show pow, log;
+
+void main() {
+ // Big numbers (representable as both Int64 and double).
+ Expect.equals(9223372036854774784, int.tryParse("9223372036854774784"));
+ Expect.equals(-9223372036854775808, int.tryParse("-9223372036854775808"));
+}
diff --git a/tests/corelib_2/int_try_parse_test.dart b/tests/corelib_2/int_try_parse_test.dart
index eb1fc86..3d9d294 100644
--- a/tests/corelib_2/int_try_parse_test.dart
+++ b/tests/corelib_2/int_try_parse_test.dart
@@ -87,9 +87,9 @@
Expect.equals(0xABCD, int.tryParse("ABCD", radix: 16));
Expect.equals(0xABCD, int.tryParse("abcd", radix: 16));
Expect.equals(15628859, int.tryParse("09azAZ", radix: 36));
- // Big numbers (representable as both Int64 and double).
- Expect.equals(9223372036854774784, int.tryParse("9223372036854774784"));
- Expect.equals(-9223372036854775808, int.tryParse("-9223372036854775808"));
+ // Bigish numbers (representable precisely as both Int64 and double (2^53)).
+ Expect.equals(9007199254740991, int.tryParse("9007199254740991"));
+ Expect.equals(-9007199254740991, int.tryParse("-9007199254740991"));
// Allow whitespace before and after the number.
Expect.equals(1, int.tryParse(" 1", radix: 2));
Expect.equals(1, int.tryParse("1 ", radix: 2));
diff --git a/tests/isolate/message_test.dart b/tests/isolate/message_test.dart
index 525ea52..fb1314b 100644
--- a/tests/isolate/message_test.dart
+++ b/tests/isolate/message_test.dart
@@ -137,7 +137,6 @@
expect(replyObject[0], same(replyObject[2][2]));
expect(replyObject[2], same(replyObject[4][0]));
expect(replyObject[0][0], same(replyObject[0][2]));
- // Bigint literals are not canonicalized so do a == check.
expect(replyObject[0][3], equals(replyObject[4][4]));
});
diff --git a/tests/language/language.status b/tests/language/language.status
index a228688..6032632 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -366,6 +366,7 @@
[ $mode == debug && ($hot_reload || $hot_reload_rollback) ]
enum_duplicate_test/01: Pass, Crash # http://dartbug.com/33156
+enum_private_test/02: Pass, Crash # dartbug.com/33339
[ $runtime == dart_precompiled && $minified ]
cyclic_type_test/*: Skip # Tests below rely on Type.toString()
@@ -474,6 +475,10 @@
[ $runtime == dart_precompiled || $runtime == vm ]
arithmetic_test: CompileTimeError # Large integer literal
+async_await_test: RuntimeError # sync-async is on by default
+asyncstar_throw_in_catch_test: RuntimeError # sync-async is on by default
+await_nonfuture_test: RuntimeError # sync-async is on by default
+await_not_started_immediately_test: RuntimeError # sync-async is on by default
bit_operations_test: CompileTimeError # Large integer literal
deopt_inlined_function_lazy_test: CompileTimeError # Large integer literal
guess_cid_test: CompileTimeError # Large integer literal
diff --git a/tests/language/language_kernel.status b/tests/language/language_kernel.status
index 7b7cd78..8c89d8c 100644
--- a/tests/language/language_kernel.status
+++ b/tests/language/language_kernel.status
@@ -153,7 +153,6 @@
compile_time_constant_c_test/02: MissingCompileTimeError
const_conditional_test/08: MissingCompileTimeError
const_constructor_nonconst_field_test/01: MissingCompileTimeError
-const_native_factory_test/01: MissingCompileTimeError
const_optional_args_negative_test: Fail
const_syntax_test/05: MissingCompileTimeError
const_syntax_test/08: MissingCompileTimeError
diff --git a/tests/language_2/arithmetic_int64_test.dart b/tests/language_2/arithmetic_int64_test.dart
new file mode 100644
index 0000000..6354af0
--- /dev/null
+++ b/tests/language_2/arithmetic_int64_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program to test arithmetic operations.
+// VMOptions=--optimization-counter-threshold=10 --no-use-osr --no-background-compilation
+
+library arithmetic_test;
+
+import "package:expect/expect.dart";
+import 'dart:math';
+
+class ArithmeticTest {
+ static runOne() {
+ // Math functions.
+ Expect.equals(1234567890123456789, int.parse("1234567890123456789"));
+ Expect.equals(-1234567890123456789, int.parse("-1234567890123456789"));
+ Expect.equals(9223372036854775807, int.parse("9223372036854775807"));
+ Expect.equals(-9223372036854775808, int.parse("-9223372036854775808"));
+ }
+
+ static testMain() {
+ runOne();
+ }
+}
+
+main() {
+ ArithmeticTest.testMain();
+}
diff --git a/tests/language_2/arithmetic_test.dart b/tests/language_2/arithmetic_test.dart
index 6ec3a6a..7784f35 100644
--- a/tests/language_2/arithmetic_test.dart
+++ b/tests/language_2/arithmetic_test.dart
@@ -403,10 +403,8 @@
Expect.equals(12, int.parse("12"));
Expect.equals(-12, int.parse("-12"));
- Expect.equals(1234567890123456789, int.parse("1234567890123456789"));
- Expect.equals(-1234567890123456789, int.parse("-1234567890123456789"));
- Expect.equals(9223372036854775807, int.parse("9223372036854775807"));
- Expect.equals(-9223372036854775808, int.parse("-9223372036854775808"));
+ Expect.equals(9007199254740991, int.parse("9007199254740991"));
+ Expect.equals(-9007199254740991, int.parse("-9007199254740991"));
// Type checks.
{
int i = int.parse("12");
diff --git a/tests/language_2/constructor_call_wrong_argument_count_negative_test.dart b/tests/language_2/constructor_call_wrong_argument_count_negative_test.dart
deleted file mode 100644
index 183a640..0000000
--- a/tests/language_2/constructor_call_wrong_argument_count_negative_test.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-// Test mismatch in argument counts.
-
-class ConstructorCallWrongArgumentCountNegativeTest {
- static void testMain() {
- Stockhorn nh = new Stockhorn(1);
- nh.goodCall(1, 2, 3);
- nh = new Stockhorn();
- }
-}
-
-class Stockhorn {
- Stockhorn(int a) {}
- int goodCall(int a, int b, int c) {
- return a + b;
- }
-}
-
-main() {
- ConstructorCallWrongArgumentCountNegativeTest.testMain();
-}
diff --git a/tests/language_2/constructor_call_wrong_argument_count_test.dart b/tests/language_2/constructor_call_wrong_argument_count_test.dart
new file mode 100644
index 0000000..8855749
--- /dev/null
+++ b/tests/language_2/constructor_call_wrong_argument_count_test.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Stockhorn {
+ Stockhorn(int a);
+}
+
+main() {
+ new Stockhorn(1);
+ new Stockhorn(); //# 01: compile-time error
+}
diff --git a/tests/language_2/constructor_redirect1_negative_test.dart b/tests/language_2/constructor_redirect1_negative_test.dart
deleted file mode 100644
index ccd4a83..0000000
--- a/tests/language_2/constructor_redirect1_negative_test.dart
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-// Redirection constructors must not be cyclic.
-
-class A {
- var x;
- A(x) : this.named(x, 0); //# none: compile-time error
- A.named(x, int y) : this(x + y); //# 01: compile-time error
-}
-
-class ConstructorRedirect1NegativeTest {
- static testMain() {
- new A(10);
- }
-}
-
-main() {
- ConstructorRedirect1NegativeTest.testMain();
-}
diff --git a/tests/language_2/constructor_redirect2_negative_test.dart b/tests/language_2/constructor_redirect_cycle_test.dart
similarity index 62%
rename from tests/language_2/constructor_redirect2_negative_test.dart
rename to tests/language_2/constructor_redirect_cycle_test.dart
index c0d17d2..a8e6353 100644
--- a/tests/language_2/constructor_redirect2_negative_test.dart
+++ b/tests/language_2/constructor_redirect_cycle_test.dart
@@ -5,15 +5,11 @@
class A {
var x;
- A(x) : this(0); /*@compile-error=unspecified*/
-}
-
-class ConstructorRedirect2NegativeTest {
- static testMain() {
- new A(10);
- }
+ A(x)
+ : this(0) //# 01: compile-time error
+ ;
}
main() {
- ConstructorRedirect2NegativeTest.testMain();
+ new A(10);
}
diff --git a/tests/language_2/constructor_redirect_indirect_cycle_test.dart b/tests/language_2/constructor_redirect_indirect_cycle_test.dart
new file mode 100644
index 0000000..50c6d64
--- /dev/null
+++ b/tests/language_2/constructor_redirect_indirect_cycle_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A {
+ var x;
+ A(x) : this.named(x, 0);
+ A.named(x, int y)
+ // Redirecting constructors must not be cyclic.
+ : this(x + y) //# 01: compile-time error
+ ;
+}
+
+main() {
+ new A(10);
+}
diff --git a/tests/language_2/constructor_setter_negative_test.dart b/tests/language_2/constructor_setter_test.dart
similarity index 100%
rename from tests/language_2/constructor_setter_negative_test.dart
rename to tests/language_2/constructor_setter_test.dart
diff --git a/tests/language_2/deep_nesting2_negative_test.dart b/tests/language_2/deep_nesting2_negative_test.dart
deleted file mode 100644
index cd49a07..0000000
--- a/tests/language_2/deep_nesting2_negative_test.dart
+++ /dev/null
@@ -1,10012 +0,0 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Deeply nested statements must not crash compiler due to stack overflow.
-
-var x = 0;
-
-main() {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- if (x == 0) {
- }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}
- print("survived!");
-}
diff --git a/tests/language_2/deep_nesting1_negative_test.dart b/tests/language_2/deep_nesting_expression_test.dart
similarity index 99%
rename from tests/language_2/deep_nesting1_negative_test.dart
rename to tests/language_2/deep_nesting_expression_test.dart
index e85c11c..5ab1db5 100644
--- a/tests/language_2/deep_nesting1_negative_test.dart
+++ b/tests/language_2/deep_nesting_expression_test.dart
@@ -6,6 +6,8 @@
main() {
var x =
-[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]];
+[
+[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] //# 01: ok, compile-time error
+];
print('okay');
}
diff --git a/tests/language_2/deep_nesting_statement_test.dart b/tests/language_2/deep_nesting_statement_test.dart
new file mode 100644
index 0000000..bb00024
--- /dev/null
+++ b/tests/language_2/deep_nesting_statement_test.dart
@@ -0,0 +1,10013 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Deeply nested statements must not crash compiler due to stack overflow.
+
+var x = 0;
+
+main() {
+ if (x == 0) {
+ if (x == 0) { //# 01: ok, compile-time error
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ if (x == 0) { //# 01: continued
+ }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} //# 01: continued
+ }
+ print("survived!");
+}
diff --git a/tests/language_2/duplicate_export_negative_test.dart b/tests/language_2/duplicate_export_collision_test.dart
similarity index 74%
rename from tests/language_2/duplicate_export_negative_test.dart
rename to tests/language_2/duplicate_export_collision_test.dart
index 4cda438..5948d9b 100644
--- a/tests/language_2/duplicate_export_negative_test.dart
+++ b/tests/language_2/duplicate_export_collision_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-library duplicate_export_negative_test;
-
-import 'duplicate_import_libd.dart';
+import 'duplicate_import_libd.dart'; //# 01: compile-time error
void main() {}
diff --git a/tests/language_2/duplicate_interface_negative_test.dart b/tests/language_2/duplicate_interface_implements_test.dart
similarity index 61%
rename from tests/language_2/duplicate_interface_negative_test.dart
rename to tests/language_2/duplicate_interface_implements_test.dart
index b83a8fd..e674f1e 100644
--- a/tests/language_2/duplicate_interface_negative_test.dart
+++ b/tests/language_2/duplicate_interface_implements_test.dart
@@ -1,17 +1,15 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// Check fail because of cycles in super class relationship.
-
-library duplicateInterfaceNegativeTest;
import "duplicate_interface_lib.dart" as alib;
import "duplicate_interface_lib.dart" show InterfA;
// Expect error since InterfA and alib.InterfA refer to the same interface.
-class Foo implements InterfA, alib.InterfA { } //# compile-time error
+class Foo implements InterfA
+ , alib.InterfA //# 01: compile-time error
+{}
main() {
- Expect.isTrue(new Foo() is InterfA);
- Expect.isTrue(new Foo() is alib.InterfA);
+ new Foo();
}
diff --git a/tests/language_2/factory_with_type_parameters_test.dart b/tests/language_2/factory_with_type_parameters_test.dart
new file mode 100644
index 0000000..5ebba7d
--- /dev/null
+++ b/tests/language_2/factory_with_type_parameters_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Foo<T> {
+ Foo._();
+
+ factory Foo
+ <X> //# 01: compile-time error
+ <X extends T> //# 02: compile-time error
+ () => new Bar<T>();
+
+ factory Foo
+ <X> //# 03: compile-time error
+ <X extends T> //# 04: compile-time error
+ .far
+ <X> //# 05: compile-time error
+ <X extends T> //# 06: compile-time error
+ <X>.fip //# 07: compile-time error
+ <X extends T>.fip //# 08: compile-time error
+ () => new Bar<T>();
+}
+
+class Bar<T> extends Foo<T> {
+ Bar(): super._() {}
+}
+
+main() {
+ new Foo<String>();
+ new Foo<String>.far();
+}
diff --git a/tests/language_2/language_2_analyzer.status b/tests/language_2/language_2_analyzer.status
index 71dfbfc..3c2b597 100644
--- a/tests/language_2/language_2_analyzer.status
+++ b/tests/language_2/language_2_analyzer.status
@@ -17,7 +17,7 @@
const_cast2_test/none: CompileTimeError
const_for_in_variable_test/01: MissingCompileTimeError # Issue 25161
constructor_call_wrong_argument_count_negative_test: Fail # Issue 11585
-constructor_type_parameter_test/00: MissingCompileTimeError
+constructor_type_parameter_test/00: MissingCompileTimeError # Issue 33110
constructor_with_type_parameters_test/03: MissingCompileTimeError
deep_nesting1_negative_test: CompileTimeError # Issue 25558
deep_nesting2_negative_test: CompileTimeError # Issue 25558
@@ -1341,6 +1341,7 @@
constructor13_test/01: MissingCompileTimeError
constructor13_test/02: MissingCompileTimeError
constructor_call_as_function_test: StaticWarning
+constructor_call_wrong_argument_count_test/01: MissingCompileTimeError
constructor_duplicate_final_test/03: MissingCompileTimeError
constructor_with_type_parameters_test/09: MissingCompileTimeError
constructor_with_type_parameters_test/15: MissingCompileTimeError
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index 59f8197..fae79c4 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -269,10 +269,8 @@
constructor_duplicate_final_test/02: MissingCompileTimeError
constructor_named_arguments_test/01: MissingCompileTimeError
constructor_named_arguments_test/none: RuntimeError
-constructor_redirect1_negative_test/01: Crash # Stack Overflow
-constructor_redirect1_negative_test/none: MissingCompileTimeError
-constructor_redirect2_negative_test: Crash # Stack Overflow
-constructor_redirect2_test/01: MissingCompileTimeError
+constructor_redirect_cycle_test/01: MissingCompileTimeError
+constructor_redirect_indirect_cycle_test/01: Crash # Stack Overflow
constructor_redirect_test/01: Crash # Assertion failure: Cannot find value Instance of 'ThisLocal' in (local(A.named2#x), local(A.named2#y), local(A.named2#z)) for j:constructor(A.named2).
covariance_type_parameter_test/02: Crash # NoSuchMethodError: The method 'hasSubclass' was called on null.
covariant_override/runtime_check_test: RuntimeError
@@ -298,7 +296,6 @@
deferred_not_loaded_check_test: RuntimeError # Test out of date. Issue 31933
deferred_redirecting_factory_test: RuntimeError
double_int_to_string_test: RuntimeError, OK # non JS number semantics
-duplicate_export_negative_test: Fail
duplicate_implements_test/01: MissingCompileTimeError
duplicate_implements_test/02: MissingCompileTimeError
duplicate_implements_test/03: MissingCompileTimeError
@@ -569,8 +566,8 @@
constants_test/05: MissingCompileTimeError
constructor12_test: RuntimeError
constructor_named_arguments_test/none: RuntimeError
-constructor_redirect1_negative_test/01: Crash # Stack Overflow
-constructor_redirect2_negative_test: Crash # Stack Overflow
+constructor_redirect_cycle_test/01: Crash # Stack Overflow
+constructor_redirect_indirect_cycle_test/01: Crash # Stack Overflow
constructor_redirect_test/01: Crash # Assertion failure: Cannot find value Instance of 'ThisLocal' in (local(A.named2#x), local(A.named2#y), local(A.named2#z)) for j:constructor(A.named2).
covariance_type_parameter_test/02: RuntimeError
covariant_override/tear_off_type_test: RuntimeError
@@ -589,7 +586,6 @@
deferred_not_loaded_check_test: RuntimeError # Test out of date. Issue 31933
deferred_redirecting_factory_test: RuntimeError
double_int_to_string_test: RuntimeError, OK # non JS number semantics
-duplicate_export_negative_test: Fail
duplicate_implements_test/01: MissingCompileTimeError
duplicate_implements_test/02: MissingCompileTimeError
dynamic_prefix_core_test/none: CompileTimeError
@@ -844,6 +840,7 @@
type_variable_promotion_test: RuntimeError
[ $compiler == dart2js && $fasta ]
+arithmetic_int64_test: RuntimeError # WontFix: Int not precisely representable in JS
call_method_as_cast_test/06: RuntimeError
call_method_implicit_tear_off_implements_function_test/05: RuntimeError
call_method_implicit_tear_off_implements_function_test/06: RuntimeError
@@ -853,9 +850,13 @@
checked_setter2_test: RuntimeError # Issue 31128
checked_setter_test: RuntimeError # Issue 31128
const_dynamic_type_literal_test/03: Pass # but it shouldn't until we fix issue 17207
+constructor_redirect_cycle_test/01: Crash # Stack Overflow
+constructor_redirect_indirect_cycle_test/01: Crash # Stack Overflow
+duplicate_interface_implements_test/01: MissingCompileTimeError
function_propagation_test: RuntimeError
generic_test/01: MissingCompileTimeError # front end does not validate `extends`
instantiate_tearoff_of_call_test: RuntimeError
+mint_compares_test: RuntimeError # WontFix: Int not precisely representable in JS
mixin_type_parameter_inference_error_test/none: CompileTimeError
mixin_type_parameter_inference_previous_mixin_test/01: CompileTimeError
mixin_type_parameter_inference_previous_mixin_test/02: CompileTimeError
@@ -940,8 +941,8 @@
constants_test/05: MissingCompileTimeError
constructor12_test: RuntimeError
constructor_named_arguments_test/none: RuntimeError
-constructor_redirect1_negative_test/01: Crash # Stack Overflow
-constructor_redirect2_negative_test: Crash # Issue 30856
+constructor_redirect_cycle_test/01: Crash # Issue 30856
+constructor_redirect_indirect_cycle_test/01: Crash # Stack Overflow
constructor_redirect_test/01: Crash # Assertion failure: Cannot find value Instance of 'ThisLocal' in (local(A.named2#x), local(A.named2#y), local(A.named2#z)) for j:constructor(A.named2).
covariance_type_parameter_test/02: RuntimeError
covariant_override/tear_off_type_test: RuntimeError
@@ -967,7 +968,6 @@
deferred_not_loaded_check_test: RuntimeError # Test out of date. Issue 31933
deferred_redirecting_factory_test: RuntimeError
double_int_to_string_test: RuntimeError, OK # non JS number semantics
-duplicate_export_negative_test: Fail
duplicate_implements_test/01: MissingCompileTimeError
duplicate_implements_test/02: MissingCompileTimeError
dynamic_prefix_core_test/none: CompileTimeError
@@ -1455,8 +1455,8 @@
constants_test/05: MissingCompileTimeError
constructor12_test: RuntimeError
constructor_named_arguments_test/none: RuntimeError
-constructor_redirect1_negative_test/01: Crash # Stack Overflow
-constructor_redirect2_negative_test: Crash # Issue 30856
+constructor_redirect_cycle_test/01: Crash # Issue 30856
+constructor_redirect_indirect_cycle_test/01: Crash # Stack Overflow
constructor_redirect_test/01: Crash # Assertion failure: Cannot find value Instance of 'ThisLocal' in (local(A.named2#x), local(A.named2#y), local(A.named2#z)) for j:constructor(A.named2).
covariance_type_parameter_test/02: RuntimeError
covariant_override/tear_off_type_test: RuntimeError
@@ -1478,7 +1478,6 @@
deferred_not_loaded_check_test: RuntimeError # Test out of date. Issue 31933
deferred_redirecting_factory_test: RuntimeError
double_int_to_string_test: RuntimeError, OK # non JS number semantics
-duplicate_export_negative_test: Fail
duplicate_implements_test/01: MissingCompileTimeError
duplicate_implements_test/02: MissingCompileTimeError
dynamic_prefix_core_test/none: CompileTimeError
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index d534e75..b6bc7b9 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -298,9 +298,9 @@
bad_override_test/01: MissingCompileTimeError
bad_override_test/02: MissingCompileTimeError
bad_override_test/03: MissingCompileTimeError
-built_in_identifier_type_annotation_test/dynamic-funarg: RuntimeError # Issue 32194
-built_in_identifier_type_annotation_test/dynamic-funret: RuntimeError # Issue 32194
-built_in_identifier_type_annotation_test/dynamic-list: RuntimeError # Issue 32194
+built_in_identifier_type_annotation_test/dynamic-funarg: RuntimeError # Issue 30450, test name contains hyphen
+built_in_identifier_type_annotation_test/dynamic-funret: RuntimeError # Issue 30450, test name contains hyphen
+built_in_identifier_type_annotation_test/dynamic-list: RuntimeError # Issue 30450, test name contains hyphen
call_method_as_cast_test/06: RuntimeError # Kernel allows classes to subtype `Function` so DDK elides the explicit cast.
call_method_implicit_tear_off_implements_function_test/05: RuntimeError # Kernel is missing the implicit `call` tearoff for assignment `Function`
call_method_implicit_tear_off_implements_function_test/06: RuntimeError # Kernel is missing the implicit `call` tearoff for assignment `Function`
@@ -340,8 +340,6 @@
const_types_test/34: MissingCompileTimeError
const_types_test/39: MissingCompileTimeError
constants_test/05: MissingCompileTimeError
-constructor_redirect1_negative_test/01: MissingCompileTimeError
-constructor_redirect2_negative_test: MissingCompileTimeError
constructor_redirect_test/01: MissingCompileTimeError
covariant_subtyping_test: RuntimeError
cyclic_constructor_test/01: MissingCompileTimeError
@@ -359,9 +357,9 @@
deferred_inheritance_constraints_test/redirecting_constructor: MissingCompileTimeError
deferred_load_library_wrong_args_test/01: CompileTimeError
double_identical_test: RuntimeError # Negative and positive zero are distinct, but not in ddk
-duplicate_export_negative_test: Fail
duplicate_implements_test/01: MissingCompileTimeError
duplicate_implements_test/02: MissingCompileTimeError
+duplicate_interface_implements_test/01: MissingCompileTimeError
dynamic_prefix_core_test/none: CompileTimeError
emit_const_fields_test: CompileTimeError # Issue 31533
export_ambiguous_main_test: MissingCompileTimeError
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index 92bc089..a24b3c2 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -245,8 +245,8 @@
const_switch2_test/01: MissingCompileTimeError # KernelVM bug: Constant evaluation.
const_types_test/34: MissingCompileTimeError # Issue 32988
const_types_test/39: MissingCompileTimeError # Issue 32988
-constructor_redirect1_negative_test/01: MissingCompileTimeError # Issue 30856
-constructor_redirect2_negative_test: MissingCompileTimeError # Issue 30856
+constructor_redirect_cycle_test/01: MissingCompileTimeError # Issue 30856
+constructor_redirect_indirect_cycle_test/01: MissingCompileTimeError # Issue 30856
constructor_redirect_test/01: MissingCompileTimeError # Fasta bug: Initializer refers to this.
cyclic_constructor_test/01: MissingCompileTimeError # Issue 30856 (cyclic constructor redirection)
cyclic_type_variable_test/01: MissingCompileTimeError # Issue 32989 (missing cycle check in bounds)
@@ -259,7 +259,7 @@
deferred_inheritance_constraints_test/implements: MissingCompileTimeError # Fasta/KernelVM bug: Deferred loading kernel issue 30273.
deferred_inheritance_constraints_test/mixin: MissingCompileTimeError # Fasta/KernelVM bug: Deferred loading kernel issue 30273.
deferred_inheritance_constraints_test/redirecting_constructor: MissingCompileTimeError # Fasta/KernelVM bug: Deferred loading kernel issue 30273.
-duplicate_export_negative_test: Fail # Issue 12916
+duplicate_export_collision_test/01: MissingCompileTimeError # Issue 12916
f_bounded_quantification_test/01: MissingCompileTimeError # Issue 33018
f_bounded_quantification_test/02: MissingCompileTimeError # Issue 33018
factory4_test/00: MissingCompileTimeError # Issue 32988
@@ -892,7 +892,7 @@
covariant_subtyping_test: RuntimeError
redirecting_factory_reflection_test: RuntimeError
-# Enabling of dartk for sim{arm,arm64,dbc64} revelaed these test failures, which
+# Enabling of dartk for sim{arm,arm64,dbc64} revealed these test failures, which
# are to be triaged. Isolate tests are skipped on purpose due to the usage of
# batch mode.
[ $compiler == dartk && $strong && ($arch == simarm || $arch == simarm64 || $arch == simdbc64) ]
@@ -1062,8 +1062,6 @@
cyclic_type_test/04: Fail, OK
cyclic_typedef_test/10: Crash # Issue 32416.
cyclic_typedef_test/11: Crash # Issue 32416.
-deep_nesting1_negative_test: Skip # Issue 31158
-deep_nesting2_negative_test: Skip # Issue 31158
deferred_call_empty_before_load_test: RuntimeError # Fasta/KernelVM bug: Deferred loading kernel issue 30273.
deferred_load_constants_test/none: RuntimeError # KernelVM bug: Deferred loading kernel issue 30273.
deferred_load_library_wrong_args_test/01: Pass # Passes by mistake. KernelVM bug: Deferred loading kernel issue 30273.
@@ -1658,7 +1656,6 @@
const_constructor3_test/02: MissingCompileTimeError
const_constructor3_test/04: MissingCompileTimeError
const_init2_test/02: MissingCompileTimeError
-const_native_factory_test: MissingCompileTimeError
const_syntax_test/08: MissingCompileTimeError
const_syntax_test/10: MissingCompileTimeError
const_types_test/01: MissingCompileTimeError
@@ -1673,11 +1670,10 @@
constants_test/05: MissingCompileTimeError
constructor13_test/01: MissingCompileTimeError
constructor13_test/02: MissingCompileTimeError
-constructor_call_wrong_argument_count_negative_test: Fail
+constructor_call_wrong_argument_count_test/01: MissingCompileTimeError
constructor_duplicate_final_test/01: MissingCompileTimeError
constructor_duplicate_final_test/02: MissingCompileTimeError
constructor_named_arguments_test/01: MissingCompileTimeError
-constructor_redirect1_negative_test/none: MissingCompileTimeError
create_unresolved_type_test/01: MissingCompileTimeError
cyclic_typedef_test/13: MissingCompileTimeError
deferred_constraints_type_annotation_test/as_operation: MissingCompileTimeError
@@ -1697,7 +1693,6 @@
duplicate_implements_test/02: MissingCompileTimeError
duplicate_implements_test/03: MissingCompileTimeError
duplicate_implements_test/04: MissingCompileTimeError
-duplicate_interface_negative_test: Fail
dynamic_field_test/01: MissingCompileTimeError
dynamic_field_test/02: MissingCompileTimeError
dynamic_prefix_core_test/01: MissingCompileTimeError
@@ -2291,3 +2286,6 @@
[ $compiler == dartk || $compiler == dartkp ]
generic_function_bounds_test: RuntimeError # Issue 32076
generic_test/01: MissingCompileTimeError
+
+[ $compiler == dartkp || $compiler == fasta ]
+duplicate_interface_implements_test/01: MissingCompileTimeError
diff --git a/tests/language_2/language_2_precompiled.status b/tests/language_2/language_2_precompiled.status
index 33d21dd..e2eb29e 100644
--- a/tests/language_2/language_2_precompiled.status
+++ b/tests/language_2/language_2_precompiled.status
@@ -258,8 +258,6 @@
cyclic_type_variable_test/03: MissingCompileTimeError
cyclic_type_variable_test/04: MissingCompileTimeError
cyclic_typedef_test/13: MissingCompileTimeError
-deep_nesting1_negative_test: Skip # Issue 31158
-deep_nesting2_negative_test: Skip # Issue 31158
default_factory2_test/01: MissingCompileTimeError
default_factory_test/01: MissingCompileTimeError
deferred_constraints_constants_test: SkipByDesign
@@ -284,7 +282,6 @@
deferred_not_loaded_check_test: RuntimeError
deferred_redirecting_factory_test: Fail, Crash # Issue 23408
deopt_inlined_function_lazy_test: Skip # Incompatible flag: --deoptimize-alot
-duplicate_export_negative_test: Fail # Issue 6134
dynamic_field_test/01: MissingCompileTimeError
dynamic_field_test/02: MissingCompileTimeError
dynamic_prefix_core_test/01: MissingCompileTimeError
diff --git a/tests/language_2/language_2_spec_parser.status b/tests/language_2/language_2_spec_parser.status
index 1504f8f..0cc7246 100644
--- a/tests/language_2/language_2_spec_parser.status
+++ b/tests/language_2/language_2_spec_parser.status
@@ -10,16 +10,7 @@
config_import_corelib_test: Fail # Uses conditional import.
config_import_test: Fail # Uses conditional import.
const_native_factory_test: Skip # Uses `native`.
-constructor_call_wrong_argument_count_negative_test: Skip # Negative, not syntax.
-constructor_redirect1_negative_test/01: Skip # Negative, not syntax.
-constructor_redirect1_negative_test/none: Skip # Negative, not syntax.
-constructor_redirect2_negative_test: Skip # Negative, not syntax.
-constructor_setter_negative_test: Skip # Negative, not syntax.
-deep_nesting1_negative_test: Skip # Stack overflow.
-deep_nesting2_negative_test: Skip # Stack overflow.
double_invalid_test: Skip # Contains illegaly formatted double.
-duplicate_export_negative_test: Skip # Negative, not syntax.
-duplicate_interface_negative_test: Skip # Negative, not syntax.
external_test/21: Fail # Test expects `runtime error`, it is a syntax error.
getter_declaration_negative_test: Fail # Negative, uses getter with parameter.
inst_field_initializer1_negative_test: Skip # Negative, not syntax.
diff --git a/tests/language_2/language_2_vm.status b/tests/language_2/language_2_vm.status
index 3674357..8bcfb7a4c 100644
--- a/tests/language_2/language_2_vm.status
+++ b/tests/language_2/language_2_vm.status
@@ -21,7 +21,7 @@
large_class_declaration_test: SkipSlow # Uses too much memory.
[ $arch == ia32 && $mode == release && $runtime == vm ]
-deep_nesting1_negative_test: Crash, Pass # Issue 31496
+deep_nesting_expression_test/01: Crash, Pass # Issue 31496
[ !$strong && ($runtime == dart_precompiled || $runtime == vm) ]
*: SkipByDesign # tests/language has the non-strong mode versions of these tests.
diff --git a/tests/language_2/regress_33392_test.dart b/tests/language_2/regress_33392_test.dart
new file mode 100644
index 0000000..18e2b73
--- /dev/null
+++ b/tests/language_2/regress_33392_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'package:expect/expect.dart';
+
+class B extends A<B> {}
+
+class A<T> {
+ int x(FutureOr<T> v) => 42;
+}
+
+void main() {
+ Expect.equals(new B().x(new B()), 42);
+}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 116c44e..fc51aee 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -367,6 +367,7 @@
convert/utf85_test: Skip # Pass, Slow Issue 12644.
[ $compiler == app_jit || $compiler == none || $compiler == precompiler ]
+async/async_await_sync_completer_test: RuntimeError # sync-async is on by default.
async/timer_not_available_test: SkipByDesign # only meant to test when there is no way to implement timer (currently only in d8)
async/timer_regress22626_test: Pass, RuntimeError # Issue 28254
mirrors/mirrors_used*: SkipByDesign # Invalid tests. MirrorsUsed does not have a specification, and dart:mirrors is not required to hide declarations that are not covered by any MirrorsUsed annotation.
diff --git a/tests/lib_2/isolate/message_test.dart b/tests/lib_2/isolate/message_test.dart
index 525ea52..fb1314b 100644
--- a/tests/lib_2/isolate/message_test.dart
+++ b/tests/lib_2/isolate/message_test.dart
@@ -137,7 +137,6 @@
expect(replyObject[0], same(replyObject[2][2]));
expect(replyObject[2], same(replyObject[4][0]));
expect(replyObject[0][0], same(replyObject[0][2]));
- // Bigint literals are not canonicalized so do a == check.
expect(replyObject[0][3], equals(replyObject[4][4]));
});
diff --git a/tests/lib_2/isolate/native_wrapper_message_test.dart b/tests/lib_2/isolate/native_wrapper_message_test.dart
new file mode 100644
index 0000000..09dcb40
--- /dev/null
+++ b/tests/lib_2/isolate/native_wrapper_message_test.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:isolate';
+import 'dart:nativewrappers';
+import 'package:expect/expect.dart';
+import 'package:async_helper/async_helper.dart';
+
+echo(msg) {
+ var data = msg[0];
+ var reply = msg[1];
+ reply.send('echoing ${data(1)}}');
+}
+
+class Test extends NativeFieldWrapperClass2 {
+ Test(this.i, this.j);
+ int i, j;
+}
+
+main() {
+ var port = new RawReceivePort();
+ var obj = new Test(1, 2);
+ var msg = [obj, port.sendPort];
+ var snd = Isolate.spawn(echo, msg);
+
+ asyncStart();
+ snd.catchError((e) {
+ Expect.isTrue(e is ArgumentError);
+ Expect.isTrue("$e".contains("NativeWrapper"));
+ port.close();
+ asyncEnd();
+ });
+}
diff --git a/tests/lib_2/lib_2_dartdevc.status b/tests/lib_2/lib_2_dartdevc.status
index 9cdf0ea..bbfa3a4 100644
--- a/tests/lib_2/lib_2_dartdevc.status
+++ b/tests/lib_2/lib_2_dartdevc.status
@@ -4,6 +4,7 @@
[ $compiler == dartdevc ]
html/element_types_keygen_test: CompileTimeError # Chrome 57 keygen removed
+html/mediasource_test: RuntimeError # Issue 29922
html/xhr_test: Pass, Slow
[ $compiler == dartdevk ]
@@ -31,6 +32,7 @@
html/client_rect_test: Pass, RuntimeError # Issue 31019
html/css_test: Pass, RuntimeError # Issue 31019
html/fileapi_entry_test: Pass, RuntimeError # Issue 31019
+html/interactive_media_test: Skip # Requires interactive camera, microphone permissions.
[ $system == windows && ($compiler == dartdevc || $compiler == dartdevk) ]
html/xhr_test: Skip # Times out. Issue 21527
@@ -79,7 +81,6 @@
html/custom_elements_23127_test: Skip # Issue 29922
html/custom_elements_test: Skip # Issue 29922
html/deferred_multi_app_htmltest: Skip # Issue 29919
-html/element_classes_svg_test: RuntimeError # Issue 29922
html/element_classes_test: RuntimeError # Issue 29922
html/fontface_loaded_test: RuntimeError
html/isolates_test: RuntimeError # Issue 29922
@@ -89,7 +90,6 @@
html/js_typed_interop_type_test: RuntimeError # Issue 30947
html/js_util_test: RuntimeError # Issue 29922
html/media_stream_test: RuntimeError # Issue 29922
-html/mediasource_test: RuntimeError # Issue 29922
html/no_linked_scripts_htmltest: Skip # Issue 29919
html/notification_permission_test: Timeout # Issue 32002
html/scripts_htmltest: Skip # Issue 29919
diff --git a/tests/lib_2/lib_2_kernel.status b/tests/lib_2/lib_2_kernel.status
index ffc9c90..bef13c5 100644
--- a/tests/lib_2/lib_2_kernel.status
+++ b/tests/lib_2/lib_2_kernel.status
@@ -51,7 +51,6 @@
[ $arch == x64 && $compiler == dartk && $mode == debug && $runtime == vm && $strong ]
mirrors/invocation_fuzz_test: Skip # Because it times out, issue 29439.
-mirrors/variable_is_const_test/01: Crash
[ $builder_tag == optimization_counter_threshold && $compiler == dartk ]
isolate/unresolved_ports_test: CompileTimeError, Pass, Timeout # Fails to compile on opt counter builder (#31838)
@@ -63,7 +62,9 @@
[ $compiler == app_jitk && $mode == product ]
isolate/spawn_function_custom_class_test: Skip # Timeout
-isolate/spawn_uri_nested_vm_test: Skip # Timeout
+
+[ $compiler == app_jitk && ($mode == product || $mode == release) ]
+isolate/spawn_uri_nested_vm_test: Skip # Timeout, Issue 33385
[ $compiler != dart2js && $fasta && !$strong ]
isolate/browser/compute_this_script_browser_test: CompileTimeError
@@ -72,21 +73,13 @@
isolate/browser/package_resolve_browser_test: CompileTimeError
[ $compiler == dartk && $mode == debug && $runtime == vm && $strong ]
-mirrors/other_declarations_location_test: Crash # assertion error, TypeParameter not having position.
+mirrors/other_declarations_location_test: Crash # Issue 33325 (assertion error, TypeParameter not having position).
[ $compiler == dartk && $mode == debug && $hot_reload_rollback ]
isolate/message3_test/constList_identical: Skip # Timeout
[ $compiler == dartk && $mode == debug && $strong ]
-mirrors/instance_members_unimplemented_interface_test: Crash
-mirrors/library_import_deferred_loading_test: Crash # Deferred loading kernel issue 28335.
-mirrors/load_library_test: Crash
-
-# Enabling of dartk for sim{arm,arm64,dbc64} revelaed these test failures, which
-# are to be triaged. Isolate tests are skipped on purpose due to the usage of
-# batch mode.
-[ $compiler == dartk && $mode == debug && $strong && ($arch == simarm || $arch == simarm64 || $arch == simdbc64) ]
-mirrors/variable_is_const_test/01: Crash # Please triage.
+mirrors/variable_is_const_test/01: Crash # Issue 32326
[ $compiler == dartk && $runtime == vm && $checked && $strong ]
mirrors/redirecting_factory_different_type_test/01: MissingCompileTimeError # Issue 28424
@@ -117,11 +110,10 @@
mirrors/class_mirror_location_test: RuntimeError
mirrors/constructor_kinds_test/01: RuntimeError
mirrors/constructor_kinds_test/none: RuntimeError
-mirrors/constructor_private_name_test: RuntimeError
+mirrors/constructor_private_name_test: RuntimeError # Issue 33345 - Incorrect qualified symbol literal from kernel reader
mirrors/constructors_test: CompileTimeError # Issue 31402 (Invocation arguments)
mirrors/dart2js_mirrors_test: RuntimeError # 31916
mirrors/deferred_mirrors_metadata_test: RuntimeError, CompileTimeError # Deferred loading kernel issue 28335.
-mirrors/deferred_mirrors_test: Crash # 31916
mirrors/deferred_type_test: CompileTimeError, RuntimeError
mirrors/empty_test: Crash, RuntimeError
mirrors/enum_test: RuntimeError # Issue 31402 (Invocation arguments)
@@ -133,11 +125,7 @@
mirrors/generic_function_typedef_test: RuntimeError
mirrors/generic_interface_test/01: RuntimeError
mirrors/generic_mixin_applications_test: RuntimeError
-mirrors/hot_get_field_test: RuntimeError
-mirrors/hot_set_field_test: RuntimeError
mirrors/invocation_fuzz_test: RuntimeError, Crash
-mirrors/invoke_private_test: RuntimeError
-mirrors/invoke_private_wrong_library_test: RuntimeError
mirrors/library_declarations_test/none: RuntimeError # Issue 31402 (Invocation arguments)
mirrors/library_enumeration_deferred_loading_test: RuntimeError
mirrors/library_exports_hidden_test: RuntimeError # Issue 33098
@@ -169,14 +157,12 @@
mirrors/mixin_members_test: CompileTimeError # Issue 31402 (Invocation arguments)
mirrors/native_class_test: SkipByDesign # Imports dart:html
mirrors/operator_test: CompileTimeError # Issue 31402 (Invocation arguments)
-mirrors/other_declarations_location_test: RuntimeError
+mirrors/other_declarations_location_test: RuntimeError # Issue 33325 (no source positions for type parameters).
mirrors/parameter_annotation_mirror_test: RuntimeError
mirrors/parameter_metadata_test: RuntimeError
mirrors/parameter_of_mixin_app_constructor_test: RuntimeError # Issue 31402 (Invocation arguments)
-mirrors/private_class_field_test: RuntimeError
-mirrors/private_field_test: RuntimeError
-mirrors/private_symbol_test: RuntimeError
-mirrors/private_types_test: RuntimeError
+mirrors/private_symbol_test: RuntimeError # Issue 33326 - CFE/kernel invalid typedef substitution
+mirrors/private_types_test: RuntimeError # Issue 33326 - CFE/kernel invalid typedef substitution
mirrors/redirecting_factory_different_type_test/01: MissingCompileTimeError
mirrors/redirecting_factory_test/01: RuntimeError
mirrors/redirecting_factory_test/02: RuntimeError
@@ -215,7 +201,7 @@
async/stream_state_nonzero_timer_test: Crash
async/stream_subscription_as_future_test: Crash
async/stream_subscription_cancel_test: Crash
-isolate/message4_test: Crash
+isolate/message4_test: Pass, Timeout
isolate/spawn_uri_multi_test/01: Crash
isolate/spawn_uri_multi_test/none: Crash
@@ -243,7 +229,6 @@
mirrors/fake_function_with_call_test: RuntimeError
mirrors/instance_members_easier_test: RuntimeError
mirrors/instance_members_test: RuntimeError
-mirrors/instance_members_unimplemented_interface_test: RuntimeError
mirrors/instance_members_with_override_test: RuntimeError
mirrors/invoke_closurization2_test: RuntimeError
mirrors/invoke_throws_test: RuntimeError
diff --git a/tests/lib_2/lib_2_vm.status b/tests/lib_2/lib_2_vm.status
index 16463be..6b5454d 100644
--- a/tests/lib_2/lib_2_vm.status
+++ b/tests/lib_2/lib_2_vm.status
@@ -2,6 +2,9 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
+[ $runtime != vm ]
+isolate/native_wrapper_message_test: Skip # A VM specific test.
+
[ $arch == arm64 && $runtime == vm ]
mirrors/immutable_collections_test: Pass, Slow # http://dartbug.com/33057
diff --git a/tests/lib_2/mirrors/dynamic_load_test.dart b/tests/lib_2/mirrors/dynamic_load_test.dart
index 2cc7c3a..2605b8b 100644
--- a/tests/lib_2/mirrors/dynamic_load_test.dart
+++ b/tests/lib_2/mirrors/dynamic_load_test.dart
@@ -43,7 +43,8 @@
}
print(error);
Expect.isTrue(error.toString().contains("Cannot open file") ||
- error.toString().contains("No such file or directory"));
+ error.toString().contains("No such file or directory") ||
+ error.toString().contains("The system cannot find the file specified"));
Expect.isTrue(error.toString().contains("DOES_NOT_EXIST"));
Future<LibraryMirror> bad_load2 = isolate.loadUri(Uri.parse("dart:_builtin"));
diff --git a/tests/lib_2/mirrors/instance_members_unimplemented_interface_test.dart b/tests/lib_2/mirrors/instance_members_unimplemented_interface_test.dart
index 6d2a4dd..5c26410 100644
--- a/tests/lib_2/mirrors/instance_members_unimplemented_interface_test.dart
+++ b/tests/lib_2/mirrors/instance_members_unimplemented_interface_test.dart
@@ -13,7 +13,7 @@
abstract class C implements I {}
-selectKeys(map, predicate) {
+selectKeys<K, V>(Map<K, V> map, bool predicate(V)) {
return map.keys.where((key) => predicate(map[key]));
}
diff --git a/tests/lib_2/mirrors/regress_33259_test.dart b/tests/lib_2/mirrors/regress_33259_test.dart
new file mode 100644
index 0000000..5244a33
--- /dev/null
+++ b/tests/lib_2/mirrors/regress_33259_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for http://dartbug.com/33259.
+
+import 'dart:mirrors';
+import 'package:expect/expect.dart';
+
+void main() {
+ Expect.isTrue(
+ reflectClass(Thing).declarations[#foo].metadata[0].reflectee is Sub);
+}
+
+class Thing {
+ @Sub()
+ String foo;
+}
+
+class Base<T> {
+ const Base();
+}
+
+class Sub extends Base<String> {
+ const Sub();
+}
diff --git a/tests/standalone/io/raw_secure_server_socket_test.dart b/tests/standalone/io/raw_secure_server_socket_test.dart
index a2a1d05..0273c5d 100644
--- a/tests/standalone/io/raw_secure_server_socket_test.dart
+++ b/tests/standalone/io/raw_secure_server_socket_test.dart
@@ -277,7 +277,7 @@
client.writeEventsEnabled = true;
}
if (bytesWritten == data.length) {
- client.shutdown(SocketDirection.SEND);
+ client.shutdown(SocketDirection.send);
}
break;
case RawSocketEvent.readClosed:
diff --git a/tests/standalone_2/http_launch_test.dart b/tests/standalone_2/http_launch_test.dart
index 657ca58..a8852fd 100644
--- a/tests/standalone_2/http_launch_test.dart
+++ b/tests/standalone_2/http_launch_test.dart
@@ -27,7 +27,7 @@
int port;
_sendNotFound(HttpResponse response) {
- response.statusCode = HttpStatus.NOT_FOUND;
+ response.statusCode = HttpStatus.notFound;
response.close();
}
@@ -94,5 +94,5 @@
}
main() {
- HttpServer.bind(InternetAddress.LOOPBACK_IP_V4, 0).then(serverRunning);
+ HttpServer.bind(InternetAddress.loopbackIPv4, 0).then(serverRunning);
}
diff --git a/tests/standalone_2/io/addlatexhash_test.dart b/tests/standalone_2/io/addlatexhash_test.dart
index d586a35..6465852 100755
--- a/tests/standalone_2/io/addlatexhash_test.dart
+++ b/tests/standalone_2/io/addlatexhash_test.dart
@@ -185,7 +185,7 @@
var renewLMHashCmd = r"\renewcommand{\LMHash}[1]{\OriginalLMHash{xxxx}}";
new File(styPath)
.copySync(tmpStyPath)
- .writeAsStringSync(renewLMHashCmd, mode: FileMode.APPEND);
+ .writeAsStringSync(renewLMHashCmd, mode: FileMode.append);
new File(specPath).copySync(tmpSpecPath);
checkAction(runAddHash(), "addlatexhash.dart failed");
diff --git a/tests/standalone_2/io/http_advanced_test.dart b/tests/standalone_2/io/http_advanced_test.dart
index b790584..de25c16 100644
--- a/tests/standalone_2/io/http_advanced_test.dart
+++ b/tests/standalone_2/io/http_advanced_test.dart
@@ -106,7 +106,7 @@
// Return a 404.
void _notFoundHandler(HttpRequest request) {
var response = request.response;
- response.statusCode = HttpStatus.NOT_FOUND;
+ response.statusCode = HttpStatus.notFound;
response.headers.set("Content-Type", "text/html; charset=UTF-8");
response.write("Page not found");
response.close();
@@ -119,7 +119,7 @@
Expect.equals("www.dartlang.org:1234", request.headers["Host"][0]);
Expect.equals("www.dartlang.org", request.headers.host);
Expect.equals(1234, request.headers.port);
- response.statusCode = HttpStatus.OK;
+ response.statusCode = HttpStatus.ok;
response.close();
}
@@ -161,7 +161,7 @@
Expect.equals("utf-8", request.headers.contentType.parameters["charset"]);
response.headers
- .set(HttpHeaders.CONTENT_TYPE, "text/html; charset = utf-8");
+ .set(HttpHeaders.contentTypeHeader, "text/html; charset = utf-8");
response.close();
}
@@ -260,21 +260,21 @@
request.headers.port = 1234;
Expect.equals("www.dartlang.com:1234", request.headers["host"][0]);
Expect.equals(1234, request.headers.port);
- request.headers.port = HttpClient.DEFAULT_HTTP_PORT;
- Expect.equals(HttpClient.DEFAULT_HTTP_PORT, request.headers.port);
+ request.headers.port = HttpClient.defaultHttpPort;
+ Expect.equals(HttpClient.defaultHttpPort, request.headers.port);
Expect.equals("www.dartlang.com", request.headers["host"][0]);
request.headers.set("Host", "www.dartlang.org");
Expect.equals("www.dartlang.org", request.headers.host);
- Expect.equals(HttpClient.DEFAULT_HTTP_PORT, request.headers.port);
+ Expect.equals(HttpClient.defaultHttpPort, request.headers.port);
request.headers.set("Host", "www.dartlang.org:");
Expect.equals("www.dartlang.org", request.headers.host);
- Expect.equals(HttpClient.DEFAULT_HTTP_PORT, request.headers.port);
+ Expect.equals(HttpClient.defaultHttpPort, request.headers.port);
request.headers.set("Host", "www.dartlang.org:1234");
Expect.equals("www.dartlang.org", request.headers.host);
Expect.equals(1234, request.headers.port);
return request.close();
}).then((response) {
- Expect.equals(HttpStatus.OK, response.statusCode);
+ Expect.equals(HttpStatus.ok, response.statusCode);
response.listen((_) {}, onDone: () {
httpClient.close();
server.shutdown();
@@ -294,7 +294,7 @@
HttpClient httpClient = new HttpClient();
void processResponse(HttpClientResponse response) {
- Expect.equals(HttpStatus.OK, response.statusCode);
+ Expect.equals(HttpStatus.ok, response.statusCode);
Expect.equals(
"Fri, 11 Jun 1999 18:46:53 GMT", response.headers["expires"][0]);
Expect.equals(new DateTime.utc(1999, DateTime.june, 11, 18, 46, 53, 0),
@@ -330,7 +330,7 @@
HttpClient httpClient = new HttpClient();
void processResponse(HttpClientResponse response) {
- Expect.equals(HttpStatus.OK, response.statusCode);
+ Expect.equals(HttpStatus.ok, response.statusCode);
Expect.equals(
"text/html; charset=utf-8", response.headers.contentType.toString());
Expect.equals("text/html", response.headers.contentType.value);
@@ -356,7 +356,7 @@
httpClient.get("127.0.0.1", port, "/contenttype2").then((request) {
request.headers
- .set(HttpHeaders.CONTENT_TYPE, "text/html; charset = utf-8");
+ .set(HttpHeaders.contentTypeHeader, "text/html; charset = utf-8");
return request.close();
}).then(processResponse);
});
diff --git a/tests/standalone_2/io/http_auth_digest_test.dart b/tests/standalone_2/io/http_auth_digest_test.dart
index efe18a2..3b4418c 100644
--- a/tests/standalone_2/io/http_auth_digest_test.dart
+++ b/tests/standalone_2/io/http_auth_digest_test.dart
@@ -38,7 +38,7 @@
server = s;
server.listen((HttpRequest request) {
sendUnauthorizedResponse(HttpResponse response, {stale: false}) {
- response.statusCode = HttpStatus.UNAUTHORIZED;
+ response.statusCode = HttpStatus.unauthorized;
StringBuffer authHeader = new StringBuffer();
authHeader.write('Digest');
authHeader.write(', realm="$realm"');
@@ -49,14 +49,16 @@
}
authHeader.write(', domain="/digest/"');
if (serverQop != null) authHeader.write(', qop="$serverQop"');
- response.headers.set(HttpHeaders.WWW_AUTHENTICATE, authHeader);
+ response.headers.set(HttpHeaders.wwwAuthenticateHeader, authHeader);
unauthCount++;
}
var response = request.response;
- if (request.headers[HttpHeaders.AUTHORIZATION] != null) {
- Expect.equals(1, request.headers[HttpHeaders.AUTHORIZATION].length);
- String authorization = request.headers[HttpHeaders.AUTHORIZATION][0];
+ if (request.headers[HttpHeaders.authorizationHeader] != null) {
+ Expect.equals(
+ 1, request.headers[HttpHeaders.authorizationHeader].length);
+ String authorization =
+ request.headers[HttpHeaders.authorizationHeader][0];
HeaderValue header =
HeaderValue.parse(authorization, parameterSeparator: ",");
if (header.value.toLowerCase() == "basic") {
@@ -152,7 +154,7 @@
.getUrl(url)
.then((HttpClientRequest request) => request.close())
.then((HttpClientResponse response) {
- Expect.equals(HttpStatus.UNAUTHORIZED, response.statusCode);
+ Expect.equals(HttpStatus.unauthorized, response.statusCode);
return response.fold(null, (x, y) {});
});
}
@@ -178,7 +180,7 @@
.getUrl(url)
.then((HttpClientRequest request) => request.close())
.then((HttpClientResponse response) {
- Expect.equals(HttpStatus.OK, response.statusCode);
+ Expect.equals(HttpStatus.ok, response.statusCode);
Expect.equals(1, response.headers["Authentication-Info"].length);
return response.fold(null, (x, y) {});
});
@@ -224,7 +226,7 @@
.getUrl(url)
.then((HttpClientRequest request) => request.close())
.then((HttpClientResponse response) {
- Expect.equals(HttpStatus.OK, response.statusCode);
+ Expect.equals(HttpStatus.ok, response.statusCode);
Expect.equals(1, response.headers["Authentication-Info"].length);
return response.fold(null, (x, y) {});
});
@@ -251,7 +253,7 @@
.getUrl(url)
.then((HttpClientRequest request) => request.close())
.then((HttpClientResponse response) {
- Expect.equals(HttpStatus.OK, response.statusCode);
+ Expect.equals(HttpStatus.ok, response.statusCode);
Expect.equals(1, response.headers["Authentication-Info"].length);
return response.fold(null, (x, y) {});
});
@@ -285,7 +287,7 @@
.getUrl(url)
.then((HttpClientRequest request) => request.close())
.then((HttpClientResponse response) {
- Expect.equals(HttpStatus.OK, response.statusCode);
+ Expect.equals(HttpStatus.ok, response.statusCode);
Expect.equals(1, response.headers["Authentication-Info"].length);
return response.fold(null, (x, y) {});
});
@@ -339,7 +341,7 @@
.then((HttpClientResponse response) {
count++;
if (count % 100 == 0) print(count);
- Expect.equals(HttpStatus.OK, response.statusCode);
+ Expect.equals(HttpStatus.ok, response.statusCode);
return response.fold(null, (x, y) {});
});
}
diff --git a/tests/standalone_2/io/http_auth_test.dart b/tests/standalone_2/io/http_auth_test.dart
index 8a3fc36..9ab8161 100644
--- a/tests/standalone_2/io/http_auth_test.dart
+++ b/tests/standalone_2/io/http_auth_test.dart
@@ -36,23 +36,25 @@
password = request.uri.path.substring(1, 6);
}
if (passwordChanged) password = "${password}1";
- if (request.headers[HttpHeaders.AUTHORIZATION] != null) {
- Expect.equals(1, request.headers[HttpHeaders.AUTHORIZATION].length);
- String authorization = request.headers[HttpHeaders.AUTHORIZATION][0];
+ if (request.headers[HttpHeaders.authorizationHeader] != null) {
+ Expect.equals(
+ 1, request.headers[HttpHeaders.authorizationHeader].length);
+ String authorization =
+ request.headers[HttpHeaders.authorizationHeader][0];
List<String> tokens = authorization.split(" ");
Expect.equals("Basic", tokens[0]);
String auth = base64.encode(utf8.encode("$username:$password"));
if (passwordChanged && auth != tokens[1]) {
- response.statusCode = HttpStatus.UNAUTHORIZED;
+ response.statusCode = HttpStatus.unauthorized;
response.headers
- .set(HttpHeaders.WWW_AUTHENTICATE, "Basic, realm=realm");
+ .set(HttpHeaders.wwwAuthenticateHeader, "Basic, realm=realm");
} else {
Expect.equals(auth, tokens[1]);
}
} else {
- response.statusCode = HttpStatus.UNAUTHORIZED;
+ response.statusCode = HttpStatus.unauthorized;
response.headers
- .set(HttpHeaders.WWW_AUTHENTICATE, "Basic, realm=realm");
+ .set(HttpHeaders.wwwAuthenticateHeader, "Basic, realm=realm");
}
response.close();
});
@@ -97,7 +99,7 @@
.getUrl(url)
.then((HttpClientRequest request) => request.close())
.then((HttpClientResponse response) {
- Expect.equals(HttpStatus.UNAUTHORIZED, response.statusCode);
+ Expect.equals(HttpStatus.unauthorized, response.statusCode);
return response.fold(null, (x, y) {});
});
}
@@ -125,7 +127,7 @@
.getUrl(url)
.then((HttpClientRequest request) => request.close())
.then((HttpClientResponse response) {
- Expect.equals(HttpStatus.OK, response.statusCode);
+ Expect.equals(HttpStatus.ok, response.statusCode);
return response.fold(null, (x, y) {});
});
}
@@ -174,7 +176,7 @@
.getUrl(url)
.then((HttpClientRequest request) => request.close())
.then((HttpClientResponse response) {
- Expect.equals(HttpStatus.OK, response.statusCode);
+ Expect.equals(HttpStatus.ok, response.statusCode);
return response.fold(null, (x, y) {});
});
}
@@ -216,7 +218,7 @@
.getUrl(Uri.parse("http://127.0.0.1/basic/test"))
.then((HttpClientRequest request) => request.close())
.then((HttpClientResponse response) {
- Expect.equals(HttpStatus.OK, response.statusCode);
+ Expect.equals(HttpStatus.ok, response.statusCode);
response.fold(null, (x, y) {}).then((_) {
client.close();
});
@@ -237,7 +239,7 @@
.getUrl(Uri.parse("http://127.0.0.1/digest/test"))
.then((HttpClientRequest request) => request.close())
.then((HttpClientResponse response) {
- Expect.equals(HttpStatus.OK, response.statusCode);
+ Expect.equals(HttpStatus.ok, response.statusCode);
response.fold(null, (x, y) {}).then((_) {
client.close();
});
diff --git a/tests/standalone_2/io/http_basic_test.dart b/tests/standalone_2/io/http_basic_test.dart
index ead3aef..573e005 100644
--- a/tests/standalone_2/io/http_basic_test.dart
+++ b/tests/standalone_2/io/http_basic_test.dart
@@ -120,7 +120,7 @@
// Return a 404.
void _notFoundHandler(HttpRequest request) {
var response = request.response;
- response.statusCode = HttpStatus.NOT_FOUND;
+ response.statusCode = HttpStatus.notFound;
response.headers.set("Content-Type", "text/html; charset=UTF-8");
response.write("Page not found");
response.close();
@@ -129,7 +129,7 @@
// Return a 301 with a custom reason phrase.
void _reasonForMovingHandler(HttpRequest request) {
var response = request.response;
- response.statusCode = HttpStatus.MOVED_PERMANENTLY;
+ response.statusCode = HttpStatus.movedPermanently;
response.reasonPhrase = "Don't come looking here any more";
response.close();
}
@@ -141,7 +141,7 @@
Expect.equals("www.dartlang.org:1234", request.headers["Host"][0]);
Expect.equals("www.dartlang.org", request.headers.host);
Expect.equals(1234, request.headers.port);
- response.statusCode = HttpStatus.OK;
+ response.statusCode = HttpStatus.ok;
response.close();
}
@@ -211,7 +211,7 @@
.get("127.0.0.1", port, "/0123456789")
.then((request) => request.close())
.then((response) {
- Expect.equals(HttpStatus.OK, response.statusCode);
+ Expect.equals(HttpStatus.ok, response.statusCode);
StringBuffer body = new StringBuffer();
response.listen((data) => body.write(new String.fromCharCodes(data)),
onDone: () {
@@ -244,7 +244,7 @@
}
return request.close();
}).then((response) {
- Expect.equals(HttpStatus.OK, response.statusCode);
+ Expect.equals(HttpStatus.ok, response.statusCode);
StringBuffer body = new StringBuffer();
response.listen((data) => body.write(new String.fromCharCodes(data)),
onDone: () {
@@ -275,7 +275,7 @@
.get("127.0.0.1", port, "/thisisnotfound")
.then((request) => request.close())
.then((response) {
- Expect.equals(HttpStatus.NOT_FOUND, response.statusCode);
+ Expect.equals(HttpStatus.notFound, response.statusCode);
var body = new StringBuffer();
response.listen((data) => body.write(new String.fromCharCodes(data)),
onDone: () {
@@ -296,7 +296,7 @@
request.followRedirects = false;
return request.close();
}).then((response) {
- Expect.equals(HttpStatus.MOVED_PERMANENTLY, response.statusCode);
+ Expect.equals(HttpStatus.movedPermanently, response.statusCode);
Expect.equals("Don't come looking here any more", response.reasonPhrase);
response.listen((data) => Expect.fail("No data expected"), onDone: () {
httpClient.close();
diff --git a/tests/standalone_2/io/http_compression_test.dart b/tests/standalone_2/io/http_compression_test.dart
index 651d5fa..35afe5a 100644
--- a/tests/standalone_2/io/http_compression_test.dart
+++ b/tests/standalone_2/io/http_compression_test.dart
@@ -22,11 +22,11 @@
var client = new HttpClient();
client.autoUncompress = clientAutoUncompress;
client.get("127.0.0.1", server.port, "/").then((request) {
- request.headers.set(HttpHeaders.ACCEPT_ENCODING, "gzip,deflate");
+ request.headers.set(HttpHeaders.acceptEncodingHeader, "gzip,deflate");
return request.close();
}).then((response) {
Expect.equals(
- "gzip", response.headers.value(HttpHeaders.CONTENT_ENCODING));
+ "gzip", response.headers.value(HttpHeaders.contentEncodingHeader));
response.fold([], (list, b) {
list.addAll(b);
return list;
@@ -34,7 +34,7 @@
if (clientAutoUncompress) {
Expect.listEquals(data, list);
} else {
- Expect.listEquals(data, GZIP.decode(list));
+ Expect.listEquals(data, gzip.decode(list));
}
server.close();
client.close();
@@ -61,11 +61,13 @@
});
var client = new HttpClient();
client.get("127.0.0.1", server.port, "/").then((request) {
- request.headers.set(HttpHeaders.ACCEPT_ENCODING, encoding);
+ request.headers.set(HttpHeaders.acceptEncodingHeader, encoding);
return request.close();
}).then((response) {
- Expect.equals(valid,
- ("gzip" == response.headers.value(HttpHeaders.CONTENT_ENCODING)));
+ Expect.equals(
+ valid,
+ ("gzip" ==
+ response.headers.value(HttpHeaders.contentEncodingHeader)));
response.listen((_) {}, onDone: () {
server.close();
client.close();
@@ -92,7 +94,8 @@
HttpServer.bind("127.0.0.1", 0).then((server) {
Expect.equals(false, server.autoCompress);
server.listen((request) {
- Expect.equals('gzip', request.headers.value(HttpHeaders.ACCEPT_ENCODING));
+ Expect.equals(
+ 'gzip', request.headers.value(HttpHeaders.acceptEncodingHeader));
request.response.write("data");
request.response.close();
});
@@ -101,7 +104,8 @@
.get("127.0.0.1", server.port, "/")
.then((request) => request.close())
.then((response) {
- Expect.equals(null, response.headers.value(HttpHeaders.CONTENT_ENCODING));
+ Expect.equals(
+ null, response.headers.value(HttpHeaders.contentEncodingHeader));
response.listen((_) {}, onDone: () {
server.close();
client.close();
diff --git a/tests/standalone_2/io/http_connection_header_test.dart b/tests/standalone_2/io/http_connection_header_test.dart
index cb2c23d..a42e458 100644
--- a/tests/standalone_2/io/http_connection_header_test.dart
+++ b/tests/standalone_2/io/http_connection_header_test.dart
@@ -8,9 +8,9 @@
import "dart:io";
void setConnectionHeaders(HttpHeaders headers) {
- headers.add(HttpHeaders.CONNECTION, "my-connection-header1");
+ headers.add(HttpHeaders.connectionHeader, "my-connection-header1");
headers.add("My-Connection-Header1", "some-value1");
- headers.add(HttpHeaders.CONNECTION, "my-connection-header2");
+ headers.add(HttpHeaders.connectionHeader, "my-connection-header2");
headers.add("My-Connection-Header2", "some-value2");
}
@@ -18,15 +18,15 @@
HttpHeaders headers, bool persistentConnection) {
Expect.equals("some-value1", headers.value("My-Connection-Header1"));
Expect.equals("some-value2", headers.value("My-Connection-Header2"));
- Expect.isTrue(headers[HttpHeaders.CONNECTION]
+ Expect.isTrue(headers[HttpHeaders.connectionHeader]
.any((value) => value.toLowerCase() == "my-connection-header1"));
- Expect.isTrue(headers[HttpHeaders.CONNECTION]
+ Expect.isTrue(headers[HttpHeaders.connectionHeader]
.any((value) => value.toLowerCase() == "my-connection-header2"));
if (persistentConnection) {
- Expect.equals(2, headers[HttpHeaders.CONNECTION].length);
+ Expect.equals(2, headers[HttpHeaders.connectionHeader].length);
} else {
- Expect.equals(3, headers[HttpHeaders.CONNECTION].length);
- Expect.isTrue(headers[HttpHeaders.CONNECTION]
+ Expect.equals(3, headers[HttpHeaders.connectionHeader].length);
+ Expect.isTrue(headers[HttpHeaders.connectionHeader]
.any((value) => value.toLowerCase() == "close"));
}
}
diff --git a/tests/standalone_2/io/http_content_length_test.dart b/tests/standalone_2/io/http_content_length_test.dart
index dcb6724..6f67664 100644
--- a/tests/standalone_2/io/http_content_length_test.dart
+++ b/tests/standalone_2/io/http_content_length_test.dart
@@ -104,8 +104,8 @@
if (useHeader) {
request.contentLength = 2;
} else {
- request.headers.add(HttpHeaders.CONTENT_LENGTH, "7");
- request.headers.add(HttpHeaders.CONTENT_LENGTH, "2");
+ request.headers.add(HttpHeaders.contentLengthHeader, "7");
+ request.headers.add(HttpHeaders.contentLengthHeader, "2");
}
request.write("x");
Expect.throws(
@@ -165,8 +165,8 @@
request.contentLength = 2;
request.headers.chunkedTransferEncoding = true;
} else {
- request.headers.add(HttpHeaders.CONTENT_LENGTH, "2");
- request.headers.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
+ request.headers.add(HttpHeaders.contentLengthHeader, "2");
+ request.headers.set(HttpHeaders.transferEncodingHeader, "chunked");
}
request.write("x");
Expect.throws(() => request.headers.chunkedTransferEncoding = false,
diff --git a/tests/standalone_2/io/http_cross_process_test.dart b/tests/standalone_2/io/http_cross_process_test.dart
index 7408c8e..547cb92 100644
--- a/tests/standalone_2/io/http_cross_process_test.dart
+++ b/tests/standalone_2/io/http_cross_process_test.dart
@@ -25,7 +25,7 @@
}
Future makeServer() {
- return HttpServer.bind(InternetAddress.LOOPBACK_IP_V4, 0).then((server) {
+ return HttpServer.bind(InternetAddress.loopbackIPv4, 0).then((server) {
server.listen((request) {
request.pipe(request.response);
});
diff --git a/tests/standalone_2/io/http_headers_test.dart b/tests/standalone_2/io/http_headers_test.dart
index 7d08cdd..50a5fc6 100644
--- a/tests/standalone_2/io/http_headers_test.dart
+++ b/tests/standalone_2/io/http_headers_test.dart
@@ -23,39 +23,39 @@
void testMultiValue() {
_HttpHeaders headers = new _HttpHeaders("1.1");
- Expect.isNull(headers[HttpHeaders.PRAGMA]);
- headers.add(HttpHeaders.PRAGMA, "pragma1");
- Expect.equals(1, headers[HttpHeaders.PRAGMA].length);
+ Expect.isNull(headers[HttpHeaders.pragmaHeader]);
+ headers.add(HttpHeaders.pragmaHeader, "pragma1");
+ Expect.equals(1, headers[HttpHeaders.pragmaHeader].length);
Expect.equals(1, headers["pragma"].length);
Expect.equals(1, headers["Pragma"].length);
- Expect.equals(1, headers["PRAGMA"].length);
- Expect.equals("pragma1", headers.value(HttpHeaders.PRAGMA));
+ Expect.equals(1, headers["pragma"].length);
+ Expect.equals("pragma1", headers.value(HttpHeaders.pragmaHeader));
- headers.add(HttpHeaders.PRAGMA, "pragma2");
- Expect.equals(2, headers[HttpHeaders.PRAGMA].length);
+ headers.add(HttpHeaders.pragmaHeader, "pragma2");
+ Expect.equals(2, headers[HttpHeaders.pragmaHeader].length);
Expect.throws(
- () => headers.value(HttpHeaders.PRAGMA), (e) => e is HttpException);
+ () => headers.value(HttpHeaders.pragmaHeader), (e) => e is HttpException);
- headers.add(HttpHeaders.PRAGMA, ["pragma3", "pragma4"]);
+ headers.add(HttpHeaders.pragmaHeader, ["pragma3", "pragma4"]);
Expect.listEquals(["pragma1", "pragma2", "pragma3", "pragma4"],
- headers[HttpHeaders.PRAGMA]);
+ headers[HttpHeaders.pragmaHeader]);
- headers.remove(HttpHeaders.PRAGMA, "pragma3");
- Expect.equals(3, headers[HttpHeaders.PRAGMA].length);
+ headers.remove(HttpHeaders.pragmaHeader, "pragma3");
+ Expect.equals(3, headers[HttpHeaders.pragmaHeader].length);
Expect.listEquals(
- ["pragma1", "pragma2", "pragma4"], headers[HttpHeaders.PRAGMA]);
+ ["pragma1", "pragma2", "pragma4"], headers[HttpHeaders.pragmaHeader]);
- headers.remove(HttpHeaders.PRAGMA, "pragma3");
- Expect.equals(3, headers[HttpHeaders.PRAGMA].length);
+ headers.remove(HttpHeaders.pragmaHeader, "pragma3");
+ Expect.equals(3, headers[HttpHeaders.pragmaHeader].length);
- headers.set(HttpHeaders.PRAGMA, "pragma5");
- Expect.equals(1, headers[HttpHeaders.PRAGMA].length);
+ headers.set(HttpHeaders.pragmaHeader, "pragma5");
+ Expect.equals(1, headers[HttpHeaders.pragmaHeader].length);
- headers.set(HttpHeaders.PRAGMA, ["pragma6", "pragma7"]);
- Expect.equals(2, headers[HttpHeaders.PRAGMA].length);
+ headers.set(HttpHeaders.pragmaHeader, ["pragma6", "pragma7"]);
+ Expect.equals(2, headers[HttpHeaders.pragmaHeader].length);
- headers.removeAll(HttpHeaders.PRAGMA);
- Expect.isNull(headers[HttpHeaders.PRAGMA]);
+ headers.removeAll(HttpHeaders.pragmaHeader);
+ Expect.isNull(headers[HttpHeaders.pragmaHeader]);
}
void testDate() {
@@ -68,19 +68,19 @@
Expect.isNull(headers.date);
headers.date = date1;
Expect.equals(date1, headers.date);
- Expect.equals(httpDate1, headers.value(HttpHeaders.DATE));
- Expect.equals(1, headers[HttpHeaders.DATE].length);
- headers.add(HttpHeaders.DATE, httpDate2);
- Expect.equals(1, headers[HttpHeaders.DATE].length);
+ Expect.equals(httpDate1, headers.value(HttpHeaders.dateHeader));
+ Expect.equals(1, headers[HttpHeaders.dateHeader].length);
+ headers.add(HttpHeaders.dateHeader, httpDate2);
+ Expect.equals(1, headers[HttpHeaders.dateHeader].length);
Expect.equals(date2, headers.date);
- Expect.equals(httpDate2, headers.value(HttpHeaders.DATE));
- headers.set(HttpHeaders.DATE, httpDate1);
- Expect.equals(1, headers[HttpHeaders.DATE].length);
+ Expect.equals(httpDate2, headers.value(HttpHeaders.dateHeader));
+ headers.set(HttpHeaders.dateHeader, httpDate1);
+ Expect.equals(1, headers[HttpHeaders.dateHeader].length);
Expect.equals(date1, headers.date);
- Expect.equals(httpDate1, headers.value(HttpHeaders.DATE));
+ Expect.equals(httpDate1, headers.value(HttpHeaders.dateHeader));
- headers.set(HttpHeaders.DATE, "xxx");
- Expect.equals("xxx", headers.value(HttpHeaders.DATE));
+ headers.set(HttpHeaders.dateHeader, "xxx");
+ Expect.equals("xxx", headers.value(HttpHeaders.dateHeader));
Expect.equals(null, headers.date);
}
@@ -94,19 +94,19 @@
Expect.isNull(headers.expires);
headers.expires = date1;
Expect.equals(date1, headers.expires);
- Expect.equals(httpDate1, headers.value(HttpHeaders.EXPIRES));
- Expect.equals(1, headers[HttpHeaders.EXPIRES].length);
- headers.add(HttpHeaders.EXPIRES, httpDate2);
- Expect.equals(1, headers[HttpHeaders.EXPIRES].length);
+ Expect.equals(httpDate1, headers.value(HttpHeaders.expiresHeader));
+ Expect.equals(1, headers[HttpHeaders.expiresHeader].length);
+ headers.add(HttpHeaders.expiresHeader, httpDate2);
+ Expect.equals(1, headers[HttpHeaders.expiresHeader].length);
Expect.equals(date2, headers.expires);
- Expect.equals(httpDate2, headers.value(HttpHeaders.EXPIRES));
- headers.set(HttpHeaders.EXPIRES, httpDate1);
- Expect.equals(1, headers[HttpHeaders.EXPIRES].length);
+ Expect.equals(httpDate2, headers.value(HttpHeaders.expiresHeader));
+ headers.set(HttpHeaders.expiresHeader, httpDate1);
+ Expect.equals(1, headers[HttpHeaders.expiresHeader].length);
Expect.equals(date1, headers.expires);
- Expect.equals(httpDate1, headers.value(HttpHeaders.EXPIRES));
+ Expect.equals(httpDate1, headers.value(HttpHeaders.expiresHeader));
- headers.set(HttpHeaders.EXPIRES, "xxx");
- Expect.equals("xxx", headers.value(HttpHeaders.EXPIRES));
+ headers.set(HttpHeaders.expiresHeader, "xxx");
+ Expect.equals("xxx", headers.value(HttpHeaders.expiresHeader));
Expect.equals(null, headers.expires);
}
@@ -120,19 +120,19 @@
Expect.isNull(headers.ifModifiedSince);
headers.ifModifiedSince = date1;
Expect.equals(date1, headers.ifModifiedSince);
- Expect.equals(httpDate1, headers.value(HttpHeaders.IF_MODIFIED_SINCE));
- Expect.equals(1, headers[HttpHeaders.IF_MODIFIED_SINCE].length);
- headers.add(HttpHeaders.IF_MODIFIED_SINCE, httpDate2);
- Expect.equals(1, headers[HttpHeaders.IF_MODIFIED_SINCE].length);
+ Expect.equals(httpDate1, headers.value(HttpHeaders.ifModifiedSinceHeader));
+ Expect.equals(1, headers[HttpHeaders.ifModifiedSinceHeader].length);
+ headers.add(HttpHeaders.ifModifiedSinceHeader, httpDate2);
+ Expect.equals(1, headers[HttpHeaders.ifModifiedSinceHeader].length);
Expect.equals(date2, headers.ifModifiedSince);
- Expect.equals(httpDate2, headers.value(HttpHeaders.IF_MODIFIED_SINCE));
- headers.set(HttpHeaders.IF_MODIFIED_SINCE, httpDate1);
- Expect.equals(1, headers[HttpHeaders.IF_MODIFIED_SINCE].length);
+ Expect.equals(httpDate2, headers.value(HttpHeaders.ifModifiedSinceHeader));
+ headers.set(HttpHeaders.ifModifiedSinceHeader, httpDate1);
+ Expect.equals(1, headers[HttpHeaders.ifModifiedSinceHeader].length);
Expect.equals(date1, headers.ifModifiedSince);
- Expect.equals(httpDate1, headers.value(HttpHeaders.IF_MODIFIED_SINCE));
+ Expect.equals(httpDate1, headers.value(HttpHeaders.ifModifiedSinceHeader));
- headers.set(HttpHeaders.IF_MODIFIED_SINCE, "xxx");
- Expect.equals("xxx", headers.value(HttpHeaders.IF_MODIFIED_SINCE));
+ headers.set(HttpHeaders.ifModifiedSinceHeader, "xxx");
+ Expect.equals("xxx", headers.value(HttpHeaders.ifModifiedSinceHeader));
Expect.equals(null, headers.ifModifiedSince);
}
@@ -142,30 +142,30 @@
Expect.isNull(headers.host);
Expect.isNull(headers.port);
headers.host = host;
- Expect.equals(host, headers.value(HttpHeaders.HOST));
+ Expect.equals(host, headers.value(HttpHeaders.hostHeader));
headers.port = 1234;
- Expect.equals("$host:1234", headers.value(HttpHeaders.HOST));
- headers.port = HttpClient.DEFAULT_HTTP_PORT;
- Expect.equals(host, headers.value(HttpHeaders.HOST));
+ Expect.equals("$host:1234", headers.value(HttpHeaders.hostHeader));
+ headers.port = HttpClient.defaultHttpPort;
+ Expect.equals(host, headers.value(HttpHeaders.hostHeader));
headers = new _HttpHeaders("1.1");
- headers.add(HttpHeaders.HOST, host);
+ headers.add(HttpHeaders.hostHeader, host);
Expect.equals(host, headers.host);
- Expect.equals(HttpClient.DEFAULT_HTTP_PORT, headers.port);
- headers.add(HttpHeaders.HOST, "$host:4567");
- Expect.equals(1, headers[HttpHeaders.HOST].length);
+ Expect.equals(HttpClient.defaultHttpPort, headers.port);
+ headers.add(HttpHeaders.hostHeader, "$host:4567");
+ Expect.equals(1, headers[HttpHeaders.hostHeader].length);
Expect.equals(host, headers.host);
Expect.equals(4567, headers.port);
headers = new _HttpHeaders("1.1");
- headers.add(HttpHeaders.HOST, "$host:xxx");
- Expect.equals("$host:xxx", headers.value(HttpHeaders.HOST));
+ headers.add(HttpHeaders.hostHeader, "$host:xxx");
+ Expect.equals("$host:xxx", headers.value(HttpHeaders.hostHeader));
Expect.equals(host, headers.host);
Expect.isNull(headers.port);
headers = new _HttpHeaders("1.1");
- headers.add(HttpHeaders.HOST, ":1234");
- Expect.equals(":1234", headers.value(HttpHeaders.HOST));
+ headers.add(HttpHeaders.hostHeader, ":1234");
+ Expect.equals(":1234", headers.value(HttpHeaders.hostHeader));
Expect.isNull(headers.host);
Expect.equals(1234, headers.port);
}
@@ -218,7 +218,7 @@
void testEnumeration() {
_HttpHeaders headers = new _HttpHeaders("1.1");
- Expect.isNull(headers[HttpHeaders.PRAGMA]);
+ Expect.isNull(headers[HttpHeaders.pragmaHeader]);
headers.add("My-Header-1", "value 1");
headers.add("My-Header-2", "value 2");
headers.add("My-Header-1", "value 3");
@@ -355,10 +355,10 @@
check(contentType, "text", "html", {"charset": null});
// Test builtin content types.
- check(ContentType.TEXT, "text", "plain", {"charset": "utf-8"});
- check(ContentType.HTML, "text", "html", {"charset": "utf-8"});
- check(ContentType.JSON, "application", "json", {"charset": "utf-8"});
- check(ContentType.BINARY, "application", "octet-stream");
+ check(ContentType.text, "text", "plain", {"charset": "utf-8"});
+ check(ContentType.html, "text", "html", {"charset": "utf-8"});
+ check(ContentType.json, "application", "json", {"charset": "utf-8"});
+ check(ContentType.binary, "application", "octet-stream");
}
void testKnownContentTypes() {
@@ -377,15 +377,15 @@
void testContentTypeCache() {
_HttpHeaders headers = new _HttpHeaders("1.1");
- headers.set(HttpHeaders.CONTENT_TYPE, "text/html");
+ headers.set(HttpHeaders.contentTypeHeader, "text/html");
Expect.equals("text", headers.contentType.primaryType);
Expect.equals("html", headers.contentType.subType);
Expect.equals("text/html", headers.contentType.value);
- headers.set(HttpHeaders.CONTENT_TYPE, "text/plain; charset=utf-8");
+ headers.set(HttpHeaders.contentTypeHeader, "text/plain; charset=utf-8");
Expect.equals("text", headers.contentType.primaryType);
Expect.equals("plain", headers.contentType.subType);
Expect.equals("text/plain", headers.contentType.value);
- headers.removeAll(HttpHeaders.CONTENT_TYPE);
+ headers.removeAll(HttpHeaders.contentTypeHeader);
Expect.isNull(headers.contentType);
}
@@ -514,10 +514,10 @@
}
void testHeaderLists() {
- HttpHeaders.GENERAL_HEADERS.forEach((x) => null);
- HttpHeaders.ENTITY_HEADERS.forEach((x) => null);
- HttpHeaders.RESPONSE_HEADERS.forEach((x) => null);
- HttpHeaders.REQUEST_HEADERS.forEach((x) => null);
+ HttpHeaders.generalHeaders.forEach((x) => null);
+ HttpHeaders.entityHeaders.forEach((x) => null);
+ HttpHeaders.responseHeaders.forEach((x) => null);
+ HttpHeaders.requestHeaders.forEach((x) => null);
}
void testInvalidFieldName() {
diff --git a/tests/standalone_2/io/http_ipv6_test.dart b/tests/standalone_2/io/http_ipv6_test.dart
index fe61c08..4c1c1df 100644
--- a/tests/standalone_2/io/http_ipv6_test.dart
+++ b/tests/standalone_2/io/http_ipv6_test.dart
@@ -32,7 +32,7 @@
.openUrl('GET', url)
.then((request) => request.close())
.then((response) {
- Expect.equals(response.statusCode, HttpStatus.OK);
+ Expect.equals(response.statusCode, HttpStatus.ok);
}).whenComplete(() {
server.close();
client.close();
diff --git a/tests/standalone_2/io/http_loopback_test.dart b/tests/standalone_2/io/http_loopback_test.dart
index d240996a..11e2b16 100644
--- a/tests/standalone_2/io/http_loopback_test.dart
+++ b/tests/standalone_2/io/http_loopback_test.dart
@@ -10,19 +10,18 @@
serverListen(RawSocket serverSide) {
serveData(RawSocketEvent event) {
- serverSide.shutdown(SocketDirection.SEND);
+ serverSide.shutdown(SocketDirection.send);
}
serverSide.listen(serveData);
}
IPv4ToIPv6FailureTest() async {
- server = await RawServerSocket.bind(InternetAddress.LOOPBACK_IP_V6, 0);
+ server = await RawServerSocket.bind(InternetAddress.loopbackIPv6, 0);
server.listen(serverListen);
bool testFailure = false;
try {
- client =
- await RawSocket.connect(InternetAddress.LOOPBACK_IP_V4, server.port);
+ client = await RawSocket.connect(InternetAddress.loopbackIPv4, server.port);
await client.close();
testFailure = true;
} on SocketException catch (e) {
@@ -37,12 +36,11 @@
}
IPv6ToIPv4FailureTest() async {
- server = await RawServerSocket.bind(InternetAddress.LOOPBACK_IP_V4, 0);
+ server = await RawServerSocket.bind(InternetAddress.loopbackIPv4, 0);
server.listen(serverListen);
bool testFailure = false;
try {
- client =
- await RawSocket.connect(InternetAddress.LOOPBACK_IP_V6, server.port);
+ client = await RawSocket.connect(InternetAddress.loopbackIPv6, server.port);
await client.close();
testFailure = true;
} on SocketException catch (e) {
@@ -74,6 +72,6 @@
main() async {
await IPv4ToIPv6FailureTest();
await IPv6ToIPv4FailureTest();
- await loopbackSuccessTest(InternetAddress.LOOPBACK_IP_V4);
- await loopbackSuccessTest(InternetAddress.LOOPBACK_IP_V6);
+ await loopbackSuccessTest(InternetAddress.loopbackIPv4);
+ await loopbackSuccessTest(InternetAddress.loopbackIPv6);
}
diff --git a/tests/standalone_2/io/http_no_reason_phrase_test.dart b/tests/standalone_2/io/http_no_reason_phrase_test.dart
index 23e53fc..2a1558e 100644
--- a/tests/standalone_2/io/http_no_reason_phrase_test.dart
+++ b/tests/standalone_2/io/http_no_reason_phrase_test.dart
@@ -37,8 +37,8 @@
}
void main() {
- missingReasonPhrase(HttpStatus.OK, true);
- missingReasonPhrase(HttpStatus.INTERNAL_SERVER_ERROR, true);
- missingReasonPhrase(HttpStatus.OK, false);
- missingReasonPhrase(HttpStatus.INTERNAL_SERVER_ERROR, false);
+ missingReasonPhrase(HttpStatus.ok, true);
+ missingReasonPhrase(HttpStatus.internalServerError, true);
+ missingReasonPhrase(HttpStatus.ok, false);
+ missingReasonPhrase(HttpStatus.internalServerError, false);
}
diff --git a/tests/standalone_2/io/http_outgoing_size_test.dart b/tests/standalone_2/io/http_outgoing_size_test.dart
index c84708a..06a33a8 100644
--- a/tests/standalone_2/io/http_outgoing_size_test.dart
+++ b/tests/standalone_2/io/http_outgoing_size_test.dart
@@ -34,7 +34,7 @@
});
var client = new HttpClient();
client.get('127.0.0.1', server.port, '/').then((request) {
- request.headers.set(HttpHeaders.ACCEPT_ENCODING, "");
+ request.headers.set(HttpHeaders.acceptEncodingHeader, "");
return request.close();
}).then((response) {
var buffer = [];
diff --git a/tests/standalone_2/io/http_proxy_advanced_test.dart b/tests/standalone_2/io/http_proxy_advanced_test.dart
index fda2388..c6d0af2 100644
--- a/tests/standalone_2/io/http_proxy_advanced_test.dart
+++ b/tests/standalone_2/io/http_proxy_advanced_test.dart
@@ -50,12 +50,12 @@
bool direct = directRequestPaths.fold(
false, (prev, path) => prev ? prev : path == request.uri.path);
if (!secure && !direct && proxyHops > 0) {
- Expect.isNotNull(request.headers[HttpHeaders.VIA]);
- Expect.equals(1, request.headers[HttpHeaders.VIA].length);
- Expect.equals(
- proxyHops, request.headers[HttpHeaders.VIA][0].split(",").length);
+ Expect.isNotNull(request.headers[HttpHeaders.viaHeader]);
+ Expect.equals(1, request.headers[HttpHeaders.viaHeader].length);
+ Expect.equals(proxyHops,
+ request.headers[HttpHeaders.viaHeader][0].split(",").length);
} else {
- Expect.isNull(request.headers[HttpHeaders.VIA]);
+ Expect.isNull(request.headers[HttpHeaders.viaHeader]);
}
var body = new StringBuffer();
onRequestComplete() {
@@ -125,8 +125,8 @@
request.fold(null, (x, y) {}).then((_) {
var response = request.response;
response.headers
- .set(HttpHeaders.PROXY_AUTHENTICATE, "Basic, realm=$realm");
- response.statusCode = HttpStatus.PROXY_AUTHENTICATION_REQUIRED;
+ .set(HttpHeaders.proxyAuthenticateHeader, "Basic, realm=$realm");
+ response.statusCode = HttpStatus.proxyAuthenticationRequired;
response.close();
});
}
@@ -134,7 +134,7 @@
digestAuthenticationRequired(request, {stale: false}) {
request.fold(null, (x, y) {}).then((_) {
var response = request.response;
- response.statusCode = HttpStatus.PROXY_AUTHENTICATION_REQUIRED;
+ response.statusCode = HttpStatus.proxyAuthenticationRequired;
StringBuffer authHeader = new StringBuffer();
authHeader.write('Digest');
authHeader.write(', realm="$realm"');
@@ -144,7 +144,7 @@
authHeader.write(', algorithm=$serverAlgorithm');
}
if (serverQop != null) authHeader.write(', qop="$serverQop"');
- response.headers.set(HttpHeaders.PROXY_AUTHENTICATE, authHeader);
+ response.headers.set(HttpHeaders.proxyAuthenticateHeader, authHeader);
response.close();
});
}
@@ -158,7 +158,7 @@
server.listen((HttpRequest request) {
requestCount++;
if (username != null && password != null) {
- if (request.headers[HttpHeaders.PROXY_AUTHORIZATION] == null) {
+ if (request.headers[HttpHeaders.proxyAuthorizationHeader] == null) {
if (authScheme == "Digest") {
digestAuthenticationRequired(request);
} else {
@@ -166,10 +166,10 @@
}
return;
} else {
- Expect.equals(
- 1, request.headers[HttpHeaders.PROXY_AUTHORIZATION].length);
+ Expect.equals(1,
+ request.headers[HttpHeaders.proxyAuthorizationHeader].length);
String authorization =
- request.headers[HttpHeaders.PROXY_AUTHORIZATION][0];
+ request.headers[HttpHeaders.proxyAuthorizationHeader][0];
if (authScheme == "Basic") {
List<String> tokens = authorization.split(" ");
Expect.equals("Basic", tokens[0]);
@@ -251,10 +251,10 @@
});
// Special handling of Content-Length and Via.
clientRequest.contentLength = request.contentLength;
- List<String> via = request.headers[HttpHeaders.VIA];
+ List<String> via = request.headers[HttpHeaders.viaHeader];
String viaPrefix = via == null ? "" : "${via[0]}, ";
clientRequest.headers
- .add(HttpHeaders.VIA, "${viaPrefix}1.1 localhost:$port");
+ .add(HttpHeaders.viaHeader, "${viaPrefix}1.1 localhost:$port");
// Copy all content.
return request.pipe(clientRequest);
}).then((clientResponse) {
@@ -460,7 +460,7 @@
}).then((HttpClientResponse response) {
response.listen((_) {}, onDone: () {
testProxyAuthenticateCount++;
- Expect.equals(HttpStatus.OK, response.statusCode);
+ Expect.equals(HttpStatus.ok, response.statusCode);
if (testProxyAuthenticateCount == loopCount * 2) {
Expect.equals(loopCount, server.requestCount);
Expect.equals(loopCount, secureServer.requestCount);
@@ -502,7 +502,7 @@
}).then((HttpClientResponse response) {
response.listen((_) {}, onDone: () {
testProxyAuthenticateCount++;
- Expect.equals(HttpStatus.OK, response.statusCode);
+ Expect.equals(HttpStatus.ok, response.statusCode);
if (testProxyAuthenticateCount == loopCount * 2) {
Expect.equals(loopCount * 2, server.requestCount);
Expect.equals(loopCount * 2, secureServer.requestCount);
diff --git a/tests/standalone_2/io/http_proxy_test.dart b/tests/standalone_2/io/http_proxy_test.dart
index bd07700..885af5d 100644
--- a/tests/standalone_2/io/http_proxy_test.dart
+++ b/tests/standalone_2/io/http_proxy_test.dart
@@ -49,12 +49,12 @@
bool direct = directRequestPaths.fold(
false, (prev, path) => prev ? prev : path == request.uri.path);
if (!secure && !direct && proxyHops > 0) {
- Expect.isNotNull(request.headers[HttpHeaders.VIA]);
- Expect.equals(1, request.headers[HttpHeaders.VIA].length);
- Expect.equals(
- proxyHops, request.headers[HttpHeaders.VIA][0].split(",").length);
+ Expect.isNotNull(request.headers[HttpHeaders.viaHeader]);
+ Expect.equals(1, request.headers[HttpHeaders.viaHeader].length);
+ Expect.equals(proxyHops,
+ request.headers[HttpHeaders.viaHeader][0].split(",").length);
} else {
- Expect.isNull(request.headers[HttpHeaders.VIA]);
+ Expect.isNull(request.headers[HttpHeaders.viaHeader]);
}
var body = new StringBuffer();
onRequestComplete() {
@@ -114,8 +114,8 @@
request.fold(null, (x, y) {}).then((_) {
var response = request.response;
response.headers
- .set(HttpHeaders.PROXY_AUTHENTICATE, "Basic, realm=$realm");
- response.statusCode = HttpStatus.PROXY_AUTHENTICATION_REQUIRED;
+ .set(HttpHeaders.proxyAuthenticateHeader, "Basic, realm=$realm");
+ response.statusCode = HttpStatus.proxyAuthenticationRequired;
response.close();
});
}
@@ -123,7 +123,7 @@
digestAuthenticationRequired(request, {stale: false}) {
request.fold(null, (x, y) {}).then((_) {
var response = request.response;
- response.statusCode = HttpStatus.PROXY_AUTHENTICATION_REQUIRED;
+ response.statusCode = HttpStatus.proxyAuthenticationRequired;
StringBuffer authHeader = new StringBuffer();
authHeader.write('Digest');
authHeader.write(', realm="$realm"');
@@ -133,7 +133,7 @@
authHeader.write(', algorithm=$serverAlgorithm');
}
if (serverQop != null) authHeader.write(', qop="$serverQop"');
- response.headers.set(HttpHeaders.PROXY_AUTHENTICATE, authHeader);
+ response.headers.set(HttpHeaders.proxyAuthenticateHeader, authHeader);
response.close();
});
}
@@ -147,7 +147,7 @@
server.listen((HttpRequest request) {
requestCount++;
if (username != null && password != null) {
- if (request.headers[HttpHeaders.PROXY_AUTHORIZATION] == null) {
+ if (request.headers[HttpHeaders.proxyAuthorizationHeader] == null) {
if (authScheme == "Digest") {
digestAuthenticationRequired(request);
} else {
@@ -155,10 +155,10 @@
}
return;
} else {
- Expect.equals(
- 1, request.headers[HttpHeaders.PROXY_AUTHORIZATION].length);
+ Expect.equals(1,
+ request.headers[HttpHeaders.proxyAuthorizationHeader].length);
String authorization =
- request.headers[HttpHeaders.PROXY_AUTHORIZATION][0];
+ request.headers[HttpHeaders.proxyAuthorizationHeader][0];
if (authScheme == "Basic") {
List<String> tokens = authorization.split(" ");
Expect.equals("Basic", tokens[0]);
@@ -239,10 +239,10 @@
});
// Special handling of Content-Length and Via.
clientRequest.contentLength = request.contentLength;
- List<String> via = request.headers[HttpHeaders.VIA];
+ List<String> via = request.headers[HttpHeaders.viaHeader];
String viaPrefix = via == null ? "" : "${via[0]}, ";
clientRequest.headers
- .add(HttpHeaders.VIA, "${viaPrefix}1.1 localhost:$port");
+ .add(HttpHeaders.viaHeader, "${viaPrefix}1.1 localhost:$port");
// Copy all content.
return request.pipe(clientRequest);
}).then((clientResponse) {
diff --git a/tests/standalone_2/io/http_read_test.dart b/tests/standalone_2/io/http_read_test.dart
index 3fcab15..aeb2174 100644
--- a/tests/standalone_2/io/http_read_test.dart
+++ b/tests/standalone_2/io/http_read_test.dart
@@ -113,7 +113,7 @@
// Return a 404.
void _notFoundHandler(HttpRequest request) {
var response = request.response;
- response.statusCode = HttpStatus.NOT_FOUND;
+ response.statusCode = HttpStatus.notFound;
response.headers.set("Content-Type", "text/html; charset=UTF-8");
response.write("Page not found");
response.close();
@@ -186,7 +186,7 @@
}
return request.close();
}).then((response) {
- Expect.equals(HttpStatus.OK, response.statusCode);
+ Expect.equals(HttpStatus.ok, response.statusCode);
List<int> body = new List<int>();
response.listen(body.addAll, onDone: () {
Expect.equals(data, new String.fromCharCodes(body));
diff --git a/tests/standalone_2/io/http_redirect_test.dart b/tests/standalone_2/io/http_redirect_test.dart
index 45e778c..9155a42 100644
--- a/tests/standalone_2/io/http_redirect_test.dart
+++ b/tests/standalone_2/io/http_redirect_test.dart
@@ -39,7 +39,7 @@
addRequestHandler("/redirect",
(HttpRequest request, HttpResponse response) {
response.redirect(Uri.parse("http://127.0.0.1:${server.port}/location"),
- status: HttpStatus.MOVED_PERMANENTLY);
+ status: HttpStatus.movedPermanently);
});
addRequestHandler("/location",
(HttpRequest request, HttpResponse response) {
@@ -49,15 +49,15 @@
// Setup redirects with relative url.
addRequestHandler("/redirectUrl",
(HttpRequest request, HttpResponse response) {
- response.headers.set(HttpHeaders.LOCATION, "/some/relativeUrl");
- response.statusCode = HttpStatus.MOVED_PERMANENTLY;
+ response.headers.set(HttpHeaders.locationHeader, "/some/relativeUrl");
+ response.statusCode = HttpStatus.movedPermanently;
response.close();
});
addRequestHandler("/some/redirectUrl",
(HttpRequest request, HttpResponse response) {
- response.headers.set(HttpHeaders.LOCATION, "relativeUrl");
- response.statusCode = HttpStatus.MOVED_PERMANENTLY;
+ response.headers.set(HttpHeaders.locationHeader, "relativeUrl");
+ response.statusCode = HttpStatus.movedPermanently;
response.close();
});
@@ -68,68 +68,68 @@
addRequestHandler("/some/relativeToAbsolute",
(HttpRequest request, HttpResponse response) {
- response.redirect(Uri.parse("xxx"), status: HttpStatus.SEE_OTHER);
+ response.redirect(Uri.parse("xxx"), status: HttpStatus.seeOther);
});
addRequestHandler("/redirectUrl2",
(HttpRequest request, HttpResponse response) {
- response.headers.set(HttpHeaders.LOCATION, "location");
- response.statusCode = HttpStatus.MOVED_PERMANENTLY;
+ response.headers.set(HttpHeaders.locationHeader, "location");
+ response.statusCode = HttpStatus.movedPermanently;
response.close();
});
addRequestHandler("/redirectUrl3",
(HttpRequest request, HttpResponse response) {
- response.headers.set(HttpHeaders.LOCATION, "./location");
- response.statusCode = HttpStatus.MOVED_PERMANENTLY;
+ response.headers.set(HttpHeaders.locationHeader, "./location");
+ response.statusCode = HttpStatus.movedPermanently;
response.close();
});
addRequestHandler("/redirectUrl4",
(HttpRequest request, HttpResponse response) {
- response.headers.set(HttpHeaders.LOCATION, "./a/b/../../location");
- response.statusCode = HttpStatus.MOVED_PERMANENTLY;
+ response.headers.set(HttpHeaders.locationHeader, "./a/b/../../location");
+ response.statusCode = HttpStatus.movedPermanently;
response.close();
});
addRequestHandler("/redirectUrl5",
(HttpRequest request, HttpResponse response) {
- response.headers
- .set(HttpHeaders.LOCATION, "//127.0.0.1:${server.port}/location");
- response.statusCode = HttpStatus.MOVED_PERMANENTLY;
+ response.headers.set(
+ HttpHeaders.locationHeader, "//127.0.0.1:${server.port}/location");
+ response.statusCode = HttpStatus.movedPermanently;
response.close();
});
// Setup redirect chain.
int n = 1;
- addRedirectHandler(n++, HttpStatus.MOVED_PERMANENTLY);
- addRedirectHandler(n++, HttpStatus.MOVED_TEMPORARILY);
- addRedirectHandler(n++, HttpStatus.SEE_OTHER);
- addRedirectHandler(n++, HttpStatus.TEMPORARY_REDIRECT);
+ addRedirectHandler(n++, HttpStatus.movedPermanently);
+ addRedirectHandler(n++, HttpStatus.movedTemporarily);
+ addRedirectHandler(n++, HttpStatus.seeOther);
+ addRedirectHandler(n++, HttpStatus.temporaryRedirect);
for (int i = n; i < 10; i++) {
- addRedirectHandler(i, HttpStatus.MOVED_PERMANENTLY);
+ addRedirectHandler(i, HttpStatus.movedPermanently);
}
// Setup redirect loop.
addRequestHandler("/A", (HttpRequest request, HttpResponse response) {
response.headers
- .set(HttpHeaders.LOCATION, "http://127.0.0.1:${server.port}/B");
- response.statusCode = HttpStatus.MOVED_PERMANENTLY;
+ .set(HttpHeaders.locationHeader, "http://127.0.0.1:${server.port}/B");
+ response.statusCode = HttpStatus.movedPermanently;
response.close();
});
addRequestHandler("/B", (HttpRequest request, HttpResponse response) {
response.headers
- .set(HttpHeaders.LOCATION, "http://127.0.0.1:${server.port}/A");
- response.statusCode = HttpStatus.MOVED_TEMPORARILY;
+ .set(HttpHeaders.locationHeader, "http://127.0.0.1:${server.port}/A");
+ response.statusCode = HttpStatus.movedTemporarily;
response.close();
});
// Setup redirect checking headers.
addRequestHandler("/src", (HttpRequest request, HttpResponse response) {
Expect.equals("value", request.headers.value("X-Request-Header"));
- response.headers
- .set(HttpHeaders.LOCATION, "http://127.0.0.1:${server.port}/target");
- response.statusCode = HttpStatus.MOVED_PERMANENTLY;
+ response.headers.set(
+ HttpHeaders.locationHeader, "http://127.0.0.1:${server.port}/target");
+ response.statusCode = HttpStatus.movedPermanently;
response.close();
});
addRequestHandler("/target", (HttpRequest request, HttpResponse response) {
@@ -141,9 +141,9 @@
addRequestHandler("/301src", (HttpRequest request, HttpResponse response) {
Expect.equals("POST", request.method);
request.listen((_) {}, onDone: () {
- response.headers.set(
- HttpHeaders.LOCATION, "http://127.0.0.1:${server.port}/301target");
- response.statusCode = HttpStatus.MOVED_PERMANENTLY;
+ response.headers.set(HttpHeaders.locationHeader,
+ "http://127.0.0.1:${server.port}/301target");
+ response.statusCode = HttpStatus.movedPermanently;
response.close();
});
});
@@ -156,9 +156,9 @@
addRequestHandler("/303src", (HttpRequest request, HttpResponse response) {
request.listen((_) {}, onDone: () {
Expect.equals("POST", request.method);
- response.headers.set(
- HttpHeaders.LOCATION, "http://127.0.0.1:${server.port}/303target");
- response.statusCode = HttpStatus.SEE_OTHER;
+ response.headers.set(HttpHeaders.locationHeader,
+ "http://127.0.0.1:${server.port}/303target");
+ response.statusCode = HttpStatus.seeOther;
response.close();
});
});
@@ -171,8 +171,8 @@
// Setup redirect where we close the connection.
addRequestHandler("/closing", (HttpRequest request, HttpResponse response) {
response.headers
- .set(HttpHeaders.LOCATION, "http://127.0.0.1:${server.port}/");
- response.statusCode = HttpStatus.FOUND;
+ .set(HttpHeaders.locationHeader, "http://127.0.0.1:${server.port}/");
+ response.statusCode = HttpStatus.found;
response.persistentConnection = false;
response.close();
});
@@ -207,7 +207,7 @@
checkRedirects(redirectCount, response);
response.redirect().then(handleResponse);
} else {
- Expect.equals(HttpStatus.NOT_FOUND, response.statusCode);
+ Expect.equals(HttpStatus.notFound, response.statusCode);
server.close();
client.close();
}
@@ -237,7 +237,7 @@
Expect.isTrue(response.isRedirect);
response.redirect().then(handleResponse);
} else {
- Expect.equals(HttpStatus.OK, response.statusCode);
+ Expect.equals(HttpStatus.ok, response.statusCode);
server.close();
client.close();
}
@@ -302,7 +302,7 @@
.then((HttpClientRequest request) {
return request.close();
}).then((HttpClientResponse response) {
- Expect.equals(HttpStatus.MOVED_PERMANENTLY, response.statusCode);
+ Expect.equals(HttpStatus.movedPermanently, response.statusCode);
response.listen((_) => Expect.fail("Response data not expected"),
onDone: () {
Expect.equals(0, response.redirects.length);
@@ -322,7 +322,7 @@
.then((HttpClientRequest request) {
return request.close();
}).then((HttpClientResponse response) {
- Expect.equals(HttpStatus.OK, response.statusCode);
+ Expect.equals(HttpStatus.ok, response.statusCode);
response.listen((_) => Expect.fail("Response data not expected"),
onDone: () {
Expect.equals(1, response.redirects.length);
@@ -392,7 +392,7 @@
.then((request) => request.close())
.then((response) {
response.listen((_) {}, onDone: () {
- Expect.equals(HttpStatus.OK, response.statusCode);
+ Expect.equals(HttpStatus.ok, response.statusCode);
Expect.equals(1, response.redirects.length);
server.close();
client.close();
@@ -417,7 +417,7 @@
handleResponse(HttpClientResponse response) {
response.listen((_) => Expect.fail("Response data not expected"),
onDone: () {
- Expect.equals(HttpStatus.SEE_OTHER, response.statusCode);
+ Expect.equals(HttpStatus.seeOther, response.statusCode);
Expect.equals("xxx", response.headers["Location"][0]);
Expect.isTrue(response.isRedirect);
server.close();
diff --git a/tests/standalone_2/io/http_server_test.dart b/tests/standalone_2/io/http_server_test.dart
index 1a9829d..b36fd7e 100644
--- a/tests/standalone_2/io/http_server_test.dart
+++ b/tests/standalone_2/io/http_server_test.dart
@@ -12,21 +12,21 @@
void testDefaultResponseHeaders() {
checkDefaultHeaders(headers) {
Expect.listEquals(
- headers[HttpHeaders.CONTENT_TYPE], ['text/plain; charset=utf-8']);
+ headers[HttpHeaders.contentTypeHeader], ['text/plain; charset=utf-8']);
Expect.listEquals(headers['X-Frame-Options'], ['SAMEORIGIN']);
Expect.listEquals(headers['X-Content-Type-Options'], ['nosniff']);
Expect.listEquals(headers['X-XSS-Protection'], ['1; mode=block']);
}
checkDefaultHeadersClear(headers) {
- Expect.isNull(headers[HttpHeaders.CONTENT_TYPE]);
+ Expect.isNull(headers[HttpHeaders.contentTypeHeader]);
Expect.isNull(headers['X-Frame-Options']);
Expect.isNull(headers['X-Content-Type-Options']);
Expect.isNull(headers['X-XSS-Protection']);
}
checkDefaultHeadersClearAB(headers) {
- Expect.isNull(headers[HttpHeaders.CONTENT_TYPE]);
+ Expect.isNull(headers[HttpHeaders.contentTypeHeader]);
Expect.isNull(headers['X-Frame-Options']);
Expect.isNull(headers['X-Content-Type-Options']);
Expect.isNull(headers['X-XSS-Protection']);
diff --git a/tests/standalone_2/io/https_unauthorized_client.dart b/tests/standalone_2/io/https_unauthorized_client.dart
index 57d9bc6..6b7e8f6 100644
--- a/tests/standalone_2/io/https_unauthorized_client.dart
+++ b/tests/standalone_2/io/https_unauthorized_client.dart
@@ -26,7 +26,7 @@
Future runClients(int port) {
HttpClient client = new HttpClient();
- var testFutures = [];
+ var testFutures = <Future>[];
for (int i = 0; i < 20; ++i) {
testFutures.add(client.getUrl(Uri.parse('https://$HOST_NAME:$port/')).then(
(HttpClientRequest request) {
diff --git a/tests/standalone_2/io/issue_22637_test.dart b/tests/standalone_2/io/issue_22637_test.dart
index c464e56..0524ce9 100644
--- a/tests/standalone_2/io/issue_22637_test.dart
+++ b/tests/standalone_2/io/issue_22637_test.dart
@@ -2,7 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
//
-// This test checks that a shutdown(SocketDirection.SEND) of a socket,
+// This test checks that a shutdown(SocketDirection.send) of a socket,
// when the other end is already closed, does not discard unread data
// that remains in the connection.
diff --git a/tests/standalone_2/io/namespace_test.dart b/tests/standalone_2/io/namespace_test.dart
index 426aed7..73ab607 100644
--- a/tests/standalone_2/io/namespace_test.dart
+++ b/tests/standalone_2/io/namespace_test.dart
@@ -91,7 +91,7 @@
Expect.isFalse(dir4.existsSync());
// stat.
FileStat dirstat = dir2.statSync();
- Expect.equals(FileSystemEntityType.DIRECTORY, dirstat.type);
+ Expect.equals(FileSystemEntityType.directory, dirstat.type);
}
doTestAsync() async {
@@ -177,7 +177,7 @@
Expect.isFalse(await dir4.exists());
// stat.
FileStat dirstat = await dir2.stat();
- Expect.equals(FileSystemEntityType.DIRECTORY, dirstat.type);
+ Expect.equals(FileSystemEntityType.directory, dirstat.type);
}
List<String> packageOptions() {
diff --git a/tests/standalone_2/io/platform_resolved_executable_test.dart b/tests/standalone_2/io/platform_resolved_executable_test.dart
index 3dbbd7c..14be3b5 100644
--- a/tests/standalone_2/io/platform_resolved_executable_test.dart
+++ b/tests/standalone_2/io/platform_resolved_executable_test.dart
@@ -40,7 +40,7 @@
void testDartExecShouldNotBeInCurrentDir() {
var type = FileSystemEntity.typeSync(platformExeName);
- expectEquals(FileSystemEntityType.NOT_FOUND, type);
+ expectEquals(FileSystemEntityType.notFound, type);
}
void testShouldFailOutsidePath() {
diff --git a/tests/standalone_2/io/process_check_arguments_script.dart b/tests/standalone_2/io/process_check_arguments_script.dart
index 76cff03..4c19479 100644
--- a/tests/standalone_2/io/process_check_arguments_script.dart
+++ b/tests/standalone_2/io/process_check_arguments_script.dart
@@ -10,13 +10,13 @@
class Expect {
static void isTrue(x) {
if (!x) {
- throw new Error("Not true");
+ throw new StateError("Not true");
}
}
static void equals(x, y) {
if (x != y) {
- throw new Error("Not equal");
+ throw new StateError("Not equal");
}
}
}
diff --git a/tests/standalone_2/io/raw_socket_test.dart b/tests/standalone_2/io/raw_socket_test.dart
index 27ad20c..f5506cc 100644
--- a/tests/standalone_2/io/raw_socket_test.dart
+++ b/tests/standalone_2/io/raw_socket_test.dart
@@ -90,7 +90,7 @@
server.listen((serverConnection) {
serverConnection.listen((event) {
if (toClose == "server" || event == RawSocketEvent.readClosed) {
- serverConnection.shutdown(SocketDirection.SEND);
+ serverConnection.shutdown(SocketDirection.send);
}
}, onDone: () {
serverEndDone.complete(null);
@@ -101,7 +101,7 @@
RawSocket.connect("127.0.0.1", server.port).then((clientConnection) {
clientConnection.listen((event) {
if (toClose == "client" || event == RawSocketEvent.readClosed) {
- clientConnection.shutdown(SocketDirection.SEND);
+ clientConnection.shutdown(SocketDirection.send);
}
}, onDone: () {
clientEndDone.complete(null);
@@ -186,7 +186,7 @@
client.writeEventsEnabled = true;
}
if (bytesWritten == data.length) {
- client.shutdown(SocketDirection.SEND);
+ client.shutdown(SocketDirection.send);
}
break;
case RawSocketEvent.readClosed:
diff --git a/tests/standalone_2/io/regress_7679_test.dart b/tests/standalone_2/io/regress_7679_test.dart
index 6402237..63f11d3 100644
--- a/tests/standalone_2/io/regress_7679_test.dart
+++ b/tests/standalone_2/io/regress_7679_test.dart
@@ -14,7 +14,7 @@
class Expect {
static void isTrue(var x) {
if (!identical(x, true)) {
- throw new Error("Not identical");
+ throw new StateError("Not identical");
}
}
}
diff --git a/tests/standalone_2/io/secure_unauthorized_client.dart b/tests/standalone_2/io/secure_unauthorized_client.dart
index f08e92b..c830c96 100644
--- a/tests/standalone_2/io/secure_unauthorized_client.dart
+++ b/tests/standalone_2/io/secure_unauthorized_client.dart
@@ -28,7 +28,7 @@
const HOST_NAME = "localhost";
Future runClients(int port) {
- var testFutures = [];
+ var testFutures = <Future>[];
for (int i = 0; i < 20; ++i) {
testFutures.add(SecureSocket
.connect(HOST_NAME, port, context: clientContext)
diff --git a/tests/standalone_2/io/socket_info_ipv4_test.dart b/tests/standalone_2/io/socket_info_ipv4_test.dart
index bce4f78..64e373f 100644
--- a/tests/standalone_2/io/socket_info_ipv4_test.dart
+++ b/tests/standalone_2/io/socket_info_ipv4_test.dart
@@ -13,7 +13,7 @@
Expect.equals(clientSocket.port, socket.remotePort);
Expect.equals(clientSocket.remotePort, socket.port);
Expect.equals(socket.remoteAddress.address, "127.0.0.1");
- Expect.equals(socket.remoteAddress.type, InternetAddressType.IP_V4);
+ Expect.equals(socket.remoteAddress.type, InternetAddressType.IPv4);
Expect.listEquals(socket.remoteAddress.rawAddress, [127, 0, 0, 1]);
Expect.equals(clientSocket.remoteAddress.address, "127.0.0.1");
Expect.equals(
diff --git a/tests/standalone_2/io/web_socket_compression_test.dart b/tests/standalone_2/io/web_socket_compression_test.dart
index 1e558ae..7ea3baa 100644
--- a/tests/standalone_2/io/web_socket_compression_test.dart
+++ b/tests/standalone_2/io/web_socket_compression_test.dart
@@ -67,12 +67,12 @@
// If the URL contains user information use that for basic
// authorization.
String auth = base64.encode(utf8.encode(uri.userInfo));
- request.headers.set(HttpHeaders.AUTHORIZATION, "Basic $auth");
+ request.headers.set(HttpHeaders.authorizationHeader, "Basic $auth");
}
// Setup the initial handshake.
request.headers
- ..set(HttpHeaders.CONNECTION, "Upgrade")
- ..set(HttpHeaders.UPGRADE, "websocket")
+ ..set(HttpHeaders.connectionHeader, "Upgrade")
+ ..set(HttpHeaders.upgradeHeader, "websocket")
..set("Sec-WebSocket-Key", nonce)
..set("Cache-Control", "no-cache")
..set("Sec-WebSocket-Version", "13")
@@ -168,16 +168,18 @@
asyncStart();
createServer().then((server) {
server.listen((request) {
- Expect.equals('Upgrade', request.headers.value(HttpHeaders.CONNECTION));
- Expect.equals('websocket', request.headers.value(HttpHeaders.UPGRADE));
+ Expect.equals(
+ 'Upgrade', request.headers.value(HttpHeaders.connectionHeader));
+ Expect.equals(
+ 'websocket', request.headers.value(HttpHeaders.upgradeHeader));
var key = request.headers.value('Sec-WebSocket-Key');
var digest = sha1.convert("$key$WEB_SOCKET_GUID".codeUnits);
var accept = base64.encode(digest.bytes);
request.response
- ..statusCode = HttpStatus.SWITCHING_PROTOCOLS
- ..headers.add(HttpHeaders.CONNECTION, "Upgrade")
- ..headers.add(HttpHeaders.UPGRADE, "websocket")
+ ..statusCode = HttpStatus.switchingProtocols
+ ..headers.add(HttpHeaders.connectionHeader, "Upgrade")
+ ..headers.add(HttpHeaders.upgradeHeader, "websocket")
..headers.add("Sec-WebSocket-Accept", accept)
..headers.add(
"Sec-WebSocket-Extensions",
@@ -207,7 +209,8 @@
}
void testReturnHeaders(String headerValue, String expected,
- {CompressionOptions serverCompression: CompressionOptions.DEFAULT}) {
+ {CompressionOptions serverCompression:
+ CompressionOptions.compressionDefault}) {
asyncStart();
createServer().then((server) {
server.listen((request) {
@@ -227,7 +230,7 @@
var url = '${secure ? "wss" : "ws"}://$HOST_NAME:${server.port}/';
createWebsocket(url, headerValue).then((HttpClientResponse response) {
- Expect.equals(response.statusCode, HttpStatus.SWITCHING_PROTOCOLS);
+ Expect.equals(response.statusCode, HttpStatus.switchingProtocols);
print(response.headers.value('Sec-WebSocket-Extensions'));
Expect.equals(
response.headers.value("Sec-WebSocket-Extensions"), expected);
@@ -361,7 +364,7 @@
'permessage-deflate; client_max_window_bits=15',
serverCompression: compression);
- compression = CompressionOptions.DEFAULT;
+ compression = CompressionOptions.compressionDefault;
testClientRequestHeaders(compression);
compression = new CompressionOptions(
clientNoContextTakeover: true, serverNoContextTakeover: true);
diff --git a/tests/standalone_2/io/web_socket_error_test.dart b/tests/standalone_2/io/web_socket_error_test.dart
index 41c40e0..c757688 100644
--- a/tests/standalone_2/io/web_socket_error_test.dart
+++ b/tests/standalone_2/io/web_socket_error_test.dart
@@ -56,9 +56,9 @@
createServer().then((server) {
server.listen((request) {
var response = request.response;
- response.statusCode = HttpStatus.SWITCHING_PROTOCOLS;
- response.headers.set(HttpHeaders.CONNECTION, "upgrade");
- response.headers.set(HttpHeaders.UPGRADE, "websocket");
+ response.statusCode = HttpStatus.switchingProtocols;
+ response.headers.set(HttpHeaders.connectionHeader, "upgrade");
+ response.headers.set(HttpHeaders.upgradeHeader, "websocket");
String key = request.headers.value("Sec-WebSocket-Key");
_SHA1 sha1 = new _SHA1();
sha1.add("$key$webSocketGUID".codeUnits);
diff --git a/tests/standalone_2/io/web_socket_ping_test.dart b/tests/standalone_2/io/web_socket_ping_test.dart
index 43fc680..1ee03b5 100644
--- a/tests/standalone_2/io/web_socket_ping_test.dart
+++ b/tests/standalone_2/io/web_socket_ping_test.dart
@@ -24,9 +24,9 @@
int closed = 0;
server.listen((request) {
var response = request.response;
- response.statusCode = HttpStatus.SWITCHING_PROTOCOLS;
- response.headers.set(HttpHeaders.CONNECTION, "upgrade");
- response.headers.set(HttpHeaders.UPGRADE, "websocket");
+ response.statusCode = HttpStatus.switchingProtocols;
+ response.headers.set(HttpHeaders.connectionHeader, "upgrade");
+ response.headers.set(HttpHeaders.upgradeHeader, "websocket");
String key = request.headers.value("Sec-WebSocket-Key");
_SHA1 sha1 = new _SHA1();
sha1.add("$key$webSocketGUID".codeUnits);
diff --git a/tests/standalone_2/io/web_socket_test.dart b/tests/standalone_2/io/web_socket_test.dart
index c65434f..11cd47f 100644
--- a/tests/standalone_2/io/web_socket_test.dart
+++ b/tests/standalone_2/io/web_socket_test.dart
@@ -50,7 +50,7 @@
checkCloseStatus(webSocket, closeStatus, closeReason) {
Expect.equals(
- closeStatus == null ? WebSocketStatus.NO_STATUS_RECEIVED : closeStatus,
+ closeStatus == null ? WebSocketStatus.noStatusReceived : closeStatus,
webSocket.closeCode);
Expect.equals(
closeReason == null ? "" : closeReason, webSocket.closeReason);
@@ -283,9 +283,9 @@
void testNoUpgrade() {
createServer().then((server) {
- // Create a server which always responds with NOT_FOUND.
+ // Create a server which always responds with notFound.
server.listen((request) {
- request.response.statusCode = HttpStatus.NOT_FOUND;
+ request.response.statusCode = HttpStatus.notFound;
request.response.close();
});
@@ -310,7 +310,7 @@
"${secure ? 'https:' : 'http:'}//$HOST_NAME:${server.port}/"))
.then((request) => request.close())
.then((response) {
- Expect.equals(HttpStatus.BAD_REQUEST, response.statusCode);
+ Expect.equals(HttpStatus.badRequest, response.statusCode);
client.close();
server.close();
});
@@ -352,12 +352,12 @@
Expect.equals(0, onmessageCalled);
Expect.isFalse(oncloseCalled);
onopenCalled = true;
- Expect.equals(WebSocket.OPEN, webSocket.readyState);
+ Expect.equals(WebSocket.open, webSocket.readyState);
webSocket.listen((message) {
onmessageCalled++;
Expect.isTrue(onopenCalled);
Expect.isFalse(oncloseCalled);
- Expect.equals(WebSocket.OPEN, webSocket.readyState);
+ Expect.equals(WebSocket.open, webSocket.readyState);
webSocket.add(message);
}, onDone: () {
Expect.isTrue(onopenCalled);
@@ -366,7 +366,7 @@
oncloseCalled = true;
Expect.equals(3002, webSocket.closeCode);
Expect.equals("Got tired", webSocket.closeReason);
- Expect.equals(WebSocket.CLOSED, webSocket.readyState);
+ Expect.equals(WebSocket.closed, webSocket.readyState);
});
});
}
@@ -390,7 +390,7 @@
});
} else {
Expect.isFalse(WebSocketTransformer.isUpgradeRequest(request));
- request.response.statusCode = HttpStatus.OK;
+ request.response.statusCode = HttpStatus.ok;
request.response.close();
}
});
@@ -417,7 +417,7 @@
.then((request) => request.close())
.then((response) {
response.listen((_) {});
- Expect.equals(HttpStatus.OK, response.statusCode);
+ Expect.equals(HttpStatus.ok, response.statusCode);
}));
}
@@ -433,16 +433,18 @@
asyncStart();
createServer().then((server) {
server.listen((request) {
- Expect.equals('Upgrade', request.headers.value(HttpHeaders.CONNECTION));
- Expect.equals('websocket', request.headers.value(HttpHeaders.UPGRADE));
+ Expect.equals(
+ 'Upgrade', request.headers.value(HttpHeaders.connectionHeader));
+ Expect.equals(
+ 'websocket', request.headers.value(HttpHeaders.upgradeHeader));
var key = request.headers.value('Sec-WebSocket-Key');
var digest = sha1.convert("$key$WEB_SOCKET_GUID".codeUnits);
var accept = base64.encode(digest.bytes);
request.response
- ..statusCode = HttpStatus.SWITCHING_PROTOCOLS
- ..headers.add(HttpHeaders.CONNECTION, "Upgrade")
- ..headers.add(HttpHeaders.UPGRADE, "websocket")
+ ..statusCode = HttpStatus.switchingProtocols
+ ..headers.add(HttpHeaders.connectionHeader, "Upgrade")
+ ..headers.add(HttpHeaders.upgradeHeader, "websocket")
..headers.add("Sec-WebSocket-Accept", accept);
request.response.contentLength = 0;
request.response.detachSocket().then((socket) {
diff --git a/tests/standalone_2/io/web_socket_typed_data_test.dart b/tests/standalone_2/io/web_socket_typed_data_test.dart
index 59939e2..595ca60 100644
--- a/tests/standalone_2/io/web_socket_typed_data_test.dart
+++ b/tests/standalone_2/io/web_socket_typed_data_test.dart
@@ -18,14 +18,15 @@
Future<WebSocket> createClient(int port, bool compression) => compression
? WebSocket.connect('ws://127.0.0.1:$port/')
: WebSocket.connect('ws://127.0.0.1:$port/',
- compression: CompressionOptions.OFF);
+ compression: CompressionOptions.compressionOff);
void test(expected, testData, compression) {
createServer().then((server) {
var messageCount = 0;
var transformer = compression
? new WebSocketTransformer()
- : new WebSocketTransformer(compression: CompressionOptions.OFF);
+ : new WebSocketTransformer(
+ compression: CompressionOptions.compressionOff);
server.transform(transformer).listen((webSocket) {
webSocket.listen((message) {
Expect.listEquals(expected, message);
@@ -76,7 +77,8 @@
var messageCount = 0;
var transformer = compression
? new WebSocketTransformer()
- : new WebSocketTransformer(compression: CompressionOptions.OFF);
+ : new WebSocketTransformer(
+ compression: CompressionOptions.compressionOff);
server.transform(transformer).listen((webSocket) {
webSocket.listen((message) => Expect.fail("No message expected"));
});
@@ -180,7 +182,8 @@
var messageCount = 0;
var transformer = compression
? new WebSocketTransformer()
- : new WebSocketTransformer(compression: CompressionOptions.OFF);
+ : new WebSocketTransformer(
+ compression: CompressionOptions.compressionOff);
server.transform(transformer).listen((webSocket) {
webSocket.listen((message) {
messageCount++;
diff --git a/tests/standalone_2/map_insert_remove_oom_test.dart b/tests/standalone_2/map_insert_remove_oom_test.dart
index f20126a..143fd18 100644
--- a/tests/standalone_2/map_insert_remove_oom_test.dart
+++ b/tests/standalone_2/map_insert_remove_oom_test.dart
@@ -2,9 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
//
-// VMOptions=--old_gen_heap_size=11
+// VMOptions=--old_gen_heap_size=12
//
-// Notice we set the old gen heap size to 11 MB, which seems to be the minimum
+// Notice we set the old gen heap size to 12 MB, which seems to be the minimum
// (in debug mode) to not cause us run OOM during isolate initialization. The
// problem here is that we pre-allocate certain exceptions, e.g. NullThrownError
// during isolate initialization, but if we have an allocation failure before
diff --git a/tests/standalone_2/packages_file_test.dart b/tests/standalone_2/packages_file_test.dart
index e213110..cc48568 100644
--- a/tests/standalone_2/packages_file_test.dart
+++ b/tests/standalone_2/packages_file_test.dart
@@ -833,7 +833,7 @@
/// The file contents are run through [fixPaths] to allow them to be self-
/// referential.
Future<HttpServer> startServer(Map files) async {
- return (await HttpServer.bind(InternetAddress.LOOPBACK_IP_V4, 0))
+ return (await HttpServer.bind(InternetAddress.loopbackIPv4, 0))
..forEach((request) {
var result = files;
onFailure:
@@ -856,7 +856,7 @@
}
}
request.response
- ..statusCode = HttpStatus.NOT_FOUND
+ ..statusCode = HttpStatus.notFound
..close();
});
}
diff --git a/tests/standalone_2/standalone_2.status b/tests/standalone_2/standalone_2.status
index 90a5707..57e4fee 100644
--- a/tests/standalone_2/standalone_2.status
+++ b/tests/standalone_2/standalone_2.status
@@ -102,7 +102,6 @@
io/socket_many_connections_test: Skip # This test fails with "Too many open files" on the Mac OS buildbot. This is expected as MacOS by default runs with a very low number of allowed open files ('ulimit -n' says something like 256).
[ $strong && ($compiler == dartk || $compiler == dartkp) ]
-io/dependency_graph_test: CompileTimeError
io/directory_test: RuntimeError
io/file_error_test: RuntimeError
io/file_test: RuntimeError
@@ -116,10 +115,7 @@
io/http_server_response_test: RuntimeError
io/regress_10026_test: RuntimeError
io/secure_socket_argument_test: CompileTimeError
-io/skipping_dart2js_compilations_test: CompileTimeError
io/socket_upgrade_to_secure_test: RuntimeError
-io/test_harness_analyzer_test: CompileTimeError
-io/test_runner_test: CompileTimeError
io/web_socket_pipe_test: RuntimeError
io/web_socket_protocol_processor_test: CompileTimeError
io/zlib_test: RuntimeError
diff --git a/tests/standalone_2/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status
index caa9d9b..f3d8db5 100644
--- a/tests/standalone_2/standalone_2_kernel.status
+++ b/tests/standalone_2/standalone_2_kernel.status
@@ -11,7 +11,6 @@
# to add them.
[ $compiler == app_jitk ]
-io/dependency_graph_test: CompileTimeError
io/directory_test: RuntimeError
io/file_error_test: RuntimeError
io/file_test: RuntimeError
@@ -34,12 +33,10 @@
io/platform_test: RuntimeError
io/regress_10026_test: RuntimeError
io/secure_socket_argument_test: CompileTimeError
-io/skipping_dart2js_compilations_test: CompileTimeError
io/socket_upgrade_to_secure_test: RuntimeError
io/test_extension_fail_test: RuntimeError
io/test_extension_test: RuntimeError
-io/test_harness_analyzer_test: CompileTimeError
-io/test_runner_test: CompileTimeError
+io/test_runner_test: RuntimeError
io/web_socket_pipe_test: RuntimeError
io/web_socket_protocol_processor_test: CompileTimeError
io/zlib_test: RuntimeError
@@ -201,14 +198,10 @@
*: SkipByDesign
[ $compiler == fasta && $strong ]
-io/dependency_graph_test: CompileTimeError
io/http_cookie_date_test: CompileTimeError
io/http_headers_test: CompileTimeError
io/http_parser_test: CompileTimeError
io/secure_socket_argument_test: CompileTimeError
-io/skipping_dart2js_compilations_test: CompileTimeError
-io/test_harness_analyzer_test: CompileTimeError
-io/test_runner_test: CompileTimeError
io/web_socket_protocol_processor_test: CompileTimeError
[ $fasta && !$strong ]
diff --git a/tools/VERSION b/tools/VERSION
index 0f5e991..9fbb187 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 0
PATCH 0
-PRERELEASE 60
+PRERELEASE 61
PRERELEASE_PATCH 0
diff --git a/tools/apps/update_homebrew/lib/update_homebrew.dart b/tools/apps/update_homebrew/lib/update_homebrew.dart
index 0d2fcbb..3db0e68 100644
--- a/tools/apps/update_homebrew/lib/update_homebrew.dart
+++ b/tools/apps/update_homebrew/lib/update_homebrew.dart
@@ -23,6 +23,7 @@
const contentShellFile = 'dartium/content_shell-macos-x64-release.zip';
const dartRbFileName = 'dart.rb';
+const dart2RbFileName = 'dart@2.rb';
Future<String> getHash256(
String channel, String revision, String download) async {
@@ -107,6 +108,9 @@
await new File(p.join(repository, dartRbFileName)).writeAsString(
createDartFormula(revisions, hashes, devVersion, stableVersion),
flush: true);
+ await new File(p.join(repository, dart2RbFileName)).writeAsString(
+ createDart2Formula(revisions, hashes, devVersion, stableVersion),
+ flush: true);
}
String createDartFormula(
@@ -200,6 +204,61 @@
end
''';
+/// TODO: Remove this formula after Dart 2 is released as stable.
+/// This is a transitional mechanism to support developers migrating
+/// from Dart 1 to Dart 2 while it's in pre-release.
+String createDart2Formula(
+ Map revisions, Map hashes, String devVersion, String stableVersion) =>
+ '''
+class DartAT2 < Formula
+ desc "The Dart 2 SDK"
+ homepage "https://www.dartlang.org/"
+ version "$devVersion"
+
+ keg_only :versioned_formula
+
+ if MacOS.prefer_64_bit?
+ url "$urlBase/dev/release/${revisions['dev']}/$x64File"
+ sha256 "${hashes['dev'][x64File]}"
+ else
+ url "$urlBase/dev/release/${revisions['dev']}/$ia32File"
+ sha256 "${hashes['dev'][ia32File]}"
+ end
+
+ def install
+ libexec.install Dir["*"]
+ bin.install_symlink "#{libexec}/bin/dart"
+ bin.write_exec_script Dir["#{libexec}/bin/{pub,dart?*}"]
+ end
+
+ def shim_script(target)
+ <<~EOS
+ #!/usr/bin/env bash
+ exec "#{prefix}/#{target}" "$@"
+ EOS
+ end
+
+ def caveats; <<~EOS
+ Note that this is a prerelease version of Dart.
+
+ Please note the path to the Dart SDK:
+ #{opt_libexec}
+ EOS
+ end
+
+ test do
+ (testpath/"sample.dart").write <<~EOS
+ void main() {
+ print(r"test message");
+ }
+ EOS
+
+ assert_equal "test message\n", shell_output("#{bin}/dart sample.dart")
+ end
+end
+''';
+
+
Future runGit(List<String> args, String repository,
Map<String, String> gitEnvironment) async {
print("git ${args.join(' ')}");
diff --git a/tools/bots/README.md b/tools/bots/README.md
new file mode 100644
index 0000000..c430c6d
--- /dev/null
+++ b/tools/bots/README.md
@@ -0,0 +1,124 @@
+# tools/bots
+This folder contains scripts and configuration files used by Dart's continuous
+integration and testing infrastructure.
+
+## Test matrix
+The file `test_matrix.json` defines the test configurations run by Dart's CI
+infrastructure. Changes to the test matrix affect all builds that include them.
+
+### Structure
+The test matrix is a JSON document and consists of the `"filesets"` object and
+the `"configurations"` array.
+
+The file sets define files and/or directories that need to be present for a test
+configuration at runtime. Any directory specified will be included along with
+its subdirectories recursively. Directory names must have a `/` at the end. All
+paths are relative to the SDK checkout's root directory.
+
+```json
+"filesets": {
+ "a_fileset_name": [
+ "a/directory/",
+ "a/file"
+ ],
+ "another_fileset_name": [
+ "another/directory/",
+ "another/file"
+ ]
+}
+```
+
+The builder configurations describe all test configurations a specific builder
+must execute. Each builder configuration is an object that specifies which
+builders it applies to, defines the build steps for the builders, and some
+additional metadata. Only one builder configuration can apply to a builder.
+
+```json
+"configurations": [
+ {
+ "builders": [
+ "a-builder",
+ "another-builder"
+ ],
+ "meta": {
+ "description": "Description of this configuration."
+ },
+ "steps": [
+ ]
+ }
+]
+```
+
+Each step is an object and must have a name. A step may also specify a script to
+run instead of the default script: `tools/test.py`. Additional arguments may be
+specified. These arguments will be passed to the script.
+
+```json
+"steps": [
+ {
+ "name": "build it",
+ "script": "tools/build.py",
+ "arguments": ["--a-flag", "target", "another_target"]
+ },
+ {
+ "name": "test it",
+ }
+]
+```
+
+A step using the default script may also be sharded across many machines using
+the `"shards"` parameter. If a step is sharded, it must specify a `"fileset"`.
+Only the files and directories defined by the file set will be available to the
+script when it's running on a shard.
+
+```json
+{
+ "name": "shard the tests",
+ "shards": 10,
+ "fileset": "a_fileset_name"
+}
+```
+
+### Builder name parsing
+The builder names are split by '-' and each part is then examined if it is an
+option. Options can be runtimes (e.g. "chrome"), architectures (e.g. x64) and
+operating system families (e.g. win). For each valid option, additional
+arguments are passed to the `tools/test.py` and `tools/build.py` scripts.
+
+### Adding a new builder
+To add a builder:
+
+1. Decide on a name.
+2. Add the builder name to a new or existing configuration.
+3. File an issue labelled "area-infrastructure" to get your builder activated.
+
+### Testing a new or modified builder
+Builders can be tested using a tool called `led` that is included in
+depot_tools. Replace buildername and CL number with the correct values and run:
+
+```bash
+led get-builder luci.dart.ci:<builder name> | \
+led edit-cr-cl 'https://dart-review.googlesource.com/c/<cl number>' | \
+led launch
+```
+
+### Adding a builder to the commit queue
+For now, file an issue labeled "area-infrastructure" to get your builder added
+to the commit queue.
+
+## Glossary
+
+### Builder
+A builder has a name and defines the steps the need to be run when it is
+executed by a bot. In general, a builder defines how to build and test software.
+
+### Bot
+A physical or virtual machine (or even a docker container) that executes all
+commands it receives. Often, these commands are the steps defined by a builder.
+
+### Sharding
+Sharded steps copy all files in a file set to as many bots as specified and
+runs the same command on all of the shards. Each shard has a shard number. The
+shard number and the total number of shards are passed as arguments to the
+command. The command is then responsible for running a subset of its work on
+each shard based on these arguments.
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 6302dd7..0ed7709 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -174,10 +174,30 @@
},
{
"builders": [
+ "vm-linux-product-x64",
+ "vm-mac-product-x64",
+ "vm-win-product-x64"
+ ],
+ "meta": {
+ "description": "This configuration is used by the vm product builders."
+ },
+ "steps": [
+ {
+ "name": "build dart",
+ "script": "tools/build.py",
+ "arguments": ["runtime"]
+ },
+ {
+ "name": "vm tests",
+ "arguments": ["--builder-tag=swarming"]
+ }
+ ]
+ },
+ {
+ "builders": [
"vm-linux-debug-ia32",
"vm-linux-debug-simarm",
"vm-linux-debug-x64",
- "vm-linux-product-x64",
"vm-linux-release-ia32",
"vm-linux-release-simarm",
"vm-linux-release-simarm64",
@@ -185,18 +205,16 @@
"vm-mac-debug-ia32",
"vm-mac-debug-simdbc64",
"vm-mac-debug-x64",
- "vm-mac-product-x64",
"vm-mac-release-ia32",
"vm-mac-release-simdbc64",
"vm-mac-release-x64",
"vm-win-debug-ia32",
"vm-win-debug-x64",
- "vm-win-product-x64",
"vm-win-release-ia32",
"vm-win-release-x64"
],
"meta": {
- "description": "This configuration is used by the vm debug, vm product and vm release builders."
+ "description": "This configuration is used by the vm debug and vm release builders."
},
"steps": [
{
@@ -1220,7 +1238,7 @@
]
},
{
- "builders": ["dart2js-csp-minified-linux-x64-drt"],
+ "builders": ["dart2js-csp-minified-linux-x64-chrome"],
"meta": {
"description": "This builder runs the dart2js tests in csp and minified mode."
},
diff --git a/tools/dom/scripts/systemhtml.py b/tools/dom/scripts/systemhtml.py
index 036b320..324900c 100644
--- a/tools/dom/scripts/systemhtml.py
+++ b/tools/dom/scripts/systemhtml.py
@@ -1293,12 +1293,12 @@
promiseCall = 'promiseToFuture'
if promiseFound is not(None):
if 'maplike' in promiseFound:
- promiseCall = 'promiseToFutureMap'
+ promiseCall = 'promiseToFuture<dynamic>'
promiseType = 'Future'
elif promiseFound['type'] == 'dictionary':
# It's a dictionary so return as a Map.
- promiseCall = 'promiseToFutureDictionary'
- promiseType = 'Future<Map>'
+ promiseCall = 'promiseToFutureAsMap'
+ promiseType = 'Future<Map<String, dynamic>>'
else:
paramType = promiseFound['type']
promiseCall = 'promiseToFuture<%s>' % paramType
diff --git a/tools/dom/src/dart2js_CssClassSet.dart b/tools/dom/src/dart2js_CssClassSet.dart
index 244e34c..c3394aa 100644
--- a/tools/dom/src/dart2js_CssClassSet.dart
+++ b/tools/dom/src/dart2js_CssClassSet.dart
@@ -15,8 +15,8 @@
final List<CssClassSetImpl> _sets;
factory _MultiElementCssClassSet(Iterable<Element> elements) {
- return new _MultiElementCssClassSet._(
- elements, elements.map((Element e) => e.classes).toList());
+ return new _MultiElementCssClassSet._(elements,
+ new List<CssClassSetImpl>.from(elements.map((Element e) => e.classes)));
}
_MultiElementCssClassSet._(this._elementIterable, this._sets);
diff --git a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
index 2f5c1e9..d989b1d 100644
--- a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
@@ -122,39 +122,28 @@
JS('returns:HtmlDocument;depends:none;effects:none;gvn:true', 'document');
// Supoort to convert JS Promise to a Dart Future.
-Future<T> promiseToFuture<T>(thePromise) {
+Future<T> promiseToFuture<T>(jsPromise) {
var completer = new Completer<T>();
var thenSuccessCode = (promiseValue) => completer.complete(promiseValue);
var thenErrorCode = (promiseError) => completer.completeError(promiseError);
- JS("", "#.then(#, #)", thePromise, convertDartClosureToJS(thenSuccessCode, 1), convertDartClosureToJS(thenErrorCode, 1));
-
- return completer.future;
-}
-
-// Supoort to convert JS Promise to a Dart Future that returns a MapLike (Class with Map mixin).
-Future promiseToFutureMap(thePromise) {
- var completer = new Completer();
-
- var thenSuccessCode = (promiseValue) => completer.complete(promiseValue);
- var thenErrorCode = (promiseError) => completer.completeError(promiseError);
-
- JS("", "#.then(#, #)", thePromise, convertDartClosureToJS(thenSuccessCode, 1),
+ JS("", "#.then(#, #)", jsPromise, convertDartClosureToJS(thenSuccessCode, 1),
convertDartClosureToJS(thenErrorCode, 1));
return completer.future;
}
-// Supoort to convert JS Promise to a Dart Future that returns a Dictionary as a Dart Map.
-Future<Map> promiseToFutureDictionary(thePromise) {
- var completer = new Completer<Map>();
+// Supoort to convert JS Promise to a Dart Future<Map<String, dynamic>>. Each property of the JS
+// object is added to the Map as a key of type String with a value of type dynamic.
+Future<Map<String, dynamic>> promiseToFutureAsMap(jsPromise) {
+ var completer = new Completer<Map<String, dynamic>>();
var thenSuccessCode = (promiseValue) =>
completer.complete(convertNativeToDart_Dictionary(promiseValue));
var thenErrorCode = (promiseError) => completer.completeError(promiseError);
- JS("", "#.then(#, #)", thePromise, convertDartClosureToJS(thenSuccessCode, 1),
+ JS("", "#.then(#, #)", jsPromise, convertDartClosureToJS(thenSuccessCode, 1),
convertDartClosureToJS(thenErrorCode, 1));
return completer.future;
diff --git a/tools/gardening/bin/results_get.dart b/tools/gardening/bin/results_get.dart
index 73b8bb9..9dccea4 100644
--- a/tools/gardening/bin/results_get.dart
+++ b/tools/gardening/bin/results_get.dart
@@ -129,7 +129,7 @@
statusExpectations.getTestResultsWithExpectation();
var outputTable = getOutputTable(argResults)
- ..addHeader(new Column("Test", width: 38), (TestExpectationResult item) {
+ ..addHeader(new Column("Test", width: 38), (item) {
return item.result.name;
})
..addHeader(new Column("Result", width: 18), (item) {
diff --git a/tools/gardening/lib/src/buildbucket.dart b/tools/gardening/lib/src/buildbucket.dart
index ff4db96..681df1d 100644
--- a/tools/gardening/lib/src/buildbucket.dart
+++ b/tools/gardening/lib/src/buildbucket.dart
@@ -51,11 +51,11 @@
});
}
-List<BuildBucketBuild> _buildsFromJson(Map json) {
+List<BuildBucketBuild> _buildsFromJson(dynamic json) {
if (json == null || !json.containsKey("builds")) {
return null;
}
- return json["builds"].map((build) {
+ return json["builds"].map<BuildBucketBuild>((build) {
var tags = build["tags"];
return new BuildBucketBuild(
build["id"],
diff --git a/tools/gardening/lib/src/logdog_rpc.dart b/tools/gardening/lib/src/logdog_rpc.dart
index 32f1499..f38ab09 100644
--- a/tools/gardening/lib/src/logdog_rpc.dart
+++ b/tools/gardening/lib/src/logdog_rpc.dart
@@ -52,7 +52,7 @@
return <LogdogStream>[];
}
return json["streams"]
- .map((stream) => new LogdogStream(stream["path"]))
+ .map<LogdogStream>((stream) => new LogdogStream(stream["path"]))
.toList();
});
}
diff --git a/tools/gardening/lib/src/logger.dart b/tools/gardening/lib/src/logger.dart
index 8bf1941..4fa5d25 100644
--- a/tools/gardening/lib/src/logger.dart
+++ b/tools/gardening/lib/src/logger.dart
@@ -22,8 +22,8 @@
String _formatMessage(String msg, error, [StackTrace stackTrace]) {
if (error == null) return msg;
- if (stackTrace == null) return msg + ": $error";
- return msg + ": $error\n$stackTrace";
+ if (stackTrace == null) return "$msg: $error";
+ return "$msg: $error\n$stackTrace";
}
class StdOutLogger extends Logger {
diff --git a/tools/gardening/lib/src/results/result_json_models.dart b/tools/gardening/lib/src/results/result_json_models.dart
index 9f96d48..1e3a0da 100644
--- a/tools/gardening/lib/src/results/result_json_models.dart
+++ b/tools/gardening/lib/src/results/result_json_models.dart
@@ -69,7 +69,7 @@
json["csp"],
json["fasta"],
json["system"],
- json["vm_options"],
+ json["vm_options"].cast<String>(),
json["use_sdk"],
json["builder_tag"],
json["fast_startup"],
@@ -80,7 +80,7 @@
json["hot_reload"] ?? false,
json["hot_reload_rollback"] ?? false,
json["preview_dart_2"] ?? false,
- json["selectors"] ?? []);
+ json["selectors"].cast<String>() ?? <String>[]);
}
/// Returns the arguments needed for running test.py with the arguments
@@ -157,8 +157,9 @@
this.testExpectations, this.commands);
static Result getFromJson(dynamic json) {
- var commands = json["commands"].map((x) => Command.getFromJson(x)).toList();
- var testExpectations = json["test_expectation"];
+ var commands =
+ json["commands"].map<Command>((x) => Command.getFromJson(x)).toList();
+ var testExpectations = json["test_expectation"].cast<String>();
return new Result(json["configuration"], json["name"], json["result"],
json["flaky"], json["negative"], testExpectations, commands);
}
@@ -205,8 +206,10 @@
List<Result> _results;
List<Result> get results {
- return _results ??=
- this.jsonObject["results"].map((x) => Result.getFromJson(x)).toList();
+ return _results ??= this
+ .jsonObject["results"]
+ .map<Result>((x) => Result.getFromJson(x))
+ .toList();
}
/// Combines multiple test-results into a single test-result, potentially by
diff --git a/tools/gardening/lib/src/results/test_result_helper.dart b/tools/gardening/lib/src/results/test_result_helper.dart
index b394289..7304fed 100644
--- a/tools/gardening/lib/src/results/test_result_helper.dart
+++ b/tools/gardening/lib/src/results/test_result_helper.dart
@@ -88,7 +88,7 @@
if (arguments.length == 1) {
if (!isSwarmingTaskUrl(firstArgument)) {
print("URI does not match "
- "`https://ci.chromium.org/swarming/task/<taskid>?server...`.");
+ "`https://<hostname>/swarming/task/<taskid>`.");
return null;
}
String swarmingTaskId = getSwarmingTaskId(firstArgument);
diff --git a/tools/gardening/lib/src/util.dart b/tools/gardening/lib/src/util.dart
index 48c3848..4dd25e0 100644
--- a/tools/gardening/lib/src/util.dart
+++ b/tools/gardening/lib/src/util.dart
@@ -305,13 +305,14 @@
/// Gets if the [url] is a swarming task url.
bool isSwarmingTaskUrl(String url) {
- return url.startsWith("https://ci.chromium.org/swarming");
+ return url.startsWith(new RegExp(r"https:\/\/.*\/swarming\/task\/"));
}
/// Gets the swarming task id from the [url].
String getSwarmingTaskId(String url) {
RegExp swarmingTaskIdInPathRegExp =
- new RegExp(r"https:\/\/ci\.chromium\.org\/swarming\/task\/(.*)\?server");
+ new RegExp(r"https:\/\/.*\/swarming\/task\/(.*)");
+ url = url?.split("?")[0];
Match swarmingTaskIdMatch = swarmingTaskIdInPathRegExp.firstMatch(url);
if (swarmingTaskIdMatch == null) {
return null;
diff --git a/tools/gardening/pubspec.yaml b/tools/gardening/pubspec.yaml
index 2b6c4e1..ca78789 100644
--- a/tools/gardening/pubspec.yaml
+++ b/tools/gardening/pubspec.yaml
@@ -4,7 +4,7 @@
#version: do-not-upload
dependencies:
args:
- http: 0.11.3+14
+ http:
path:
status_file:
path: ../../pkg/status_file/
diff --git a/tools/migration/bin/run_tests.dart b/tools/migration/bin/run_tests.dart
index 3fc8498..9fbf645 100644
--- a/tools/migration/bin/run_tests.dart
+++ b/tools/migration/bin/run_tests.dart
@@ -38,6 +38,7 @@
const releaseMode = "--mode=release";
const productMode = "--mode=product";
const strong = "--strong";
+const previewDart2 = "--preview-dart-2";
/// Maps configuration names to a corresponding set of test.dart command line
/// arguments.
@@ -75,6 +76,7 @@
],
"dart2js-jsshell": [dart2js, jsshell, fastStartup, useSdk, dart2jsBatch],
// TODO(rnystrom): Is it worth running dart2js on Firefox too?
+ "dart2js-2": [dart2js, chrome, dart2jsBatch, previewDart2],
"dartdevc": [dartdevc, chrome, useSdk, strong],
"dartdevc-kernel": [dartdevk, chrome, checked, useSdk, strong],
"dartdevc-kernel-noruntime": [dartdevk, noRuntime, checked, useSdk, strong],
diff --git a/tools/patch_sdk.dart b/tools/patch_sdk.dart
index 411442c..e32065c 100644
--- a/tools/patch_sdk.dart
+++ b/tools/patch_sdk.dart
@@ -539,7 +539,6 @@
'ImmutableArray',
'OneByteString',
'TwoByteString',
- 'Bigint'
].map((name) => "static final int cid${name} = 0;").join('\n');
/// Merge `@patch` declarations into `external` declarations.
diff --git a/tools/testing/dart/browser_test.dart b/tools/testing/dart/browser_test.dart
index 4c2d536..1cf0526 100644
--- a/tools/testing/dart/browser_test.dart
+++ b/tools/testing/dart/browser_test.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'utils.dart';
+import 'configuration.dart' show Compiler;
String dart2jsHtml(String title, String scriptPath) {
return """
@@ -40,10 +41,12 @@
/// The [testName] is the short name of the test without any subdirectory path
/// or extension, like "math_test". The [testJSDir] is the relative path to the
/// build directory where the dartdevc-generated JS file is stored.
-String dartdevcHtml(String testName, String testJSDir, String buildDir) {
+String dartdevcHtml(String testName, String testJSDir, Compiler compiler) {
+ var isKernel = compiler == Compiler.dartdevk;
+ var sdkPath = isKernel ? 'kernel/amd/dart_sdk' : 'js/amd/dart_sdk';
+ var pkgDir = isKernel ? 'pkg_kernel' : 'pkg';
var packagePaths = testPackages
- .map((package) => ' "$package": "/root_dart/$buildDir/gen/utils/'
- 'dartdevc/pkg/$package",')
+ .map((p) => ' "$p": "/root_build/gen/utils/dartdevc/$pkgDir/$p",')
.join("\n");
return """
@@ -69,7 +72,7 @@
var require = {
baseUrl: "/root_dart/$testJSDir",
paths: {
- "dart_sdk": "/root_build/gen/utils/dartdevc/js/amd/dart_sdk",
+ "dart_sdk": "/root_build/gen/utils/dartdevc/$sdkPath",
$packagePaths
},
waitSeconds: 30,
@@ -86,9 +89,6 @@
requirejs(["$testName", "dart_sdk", "async_helper"],
function($testName, sdk, async_helper) {
sdk.dart.ignoreWhitelistedErrors(false);
- // TODO(rnystrom): This uses DDC's forked version of async_helper. Unfork
- // these packages when possible.
- async_helper.async_helper.asyncTestInitialize(function() {});
sdk._isolate_helper.startRootIsolate(function() {}, []);
sdk._debugger.registerDevtoolsFormatter();
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index 9661adc..15ac03d 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -605,13 +605,14 @@
.toNativePath();
var summaryInputDir = new Path(_configuration.buildDirectory)
- .append("/gen/utils/dartdevc/pkg")
+ .append("/gen/utils/dartdevc/pkg_kernel")
.absolute
.toNativePath();
args.addAll([
"--dart-sdk-summary",
sdkSummary,
+ "--no-summarize",
"-o",
outputFile,
inputFile,
@@ -622,7 +623,7 @@
// get recompiled into the test's own module.
for (var package in testPackages) {
var summary = new Path(_configuration.buildDirectory)
- .append("/gen/utils/dartdevc/pkg/$package.dill")
+ .append("/gen/utils/dartdevc/pkg_kernel/$package.dill")
.absolute
.toNativePath();
args.add("-s");
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index d7beed3..4a16a03 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -1061,7 +1061,7 @@
// Always run with synchronous starts of `async` functions.
// If we want to make this dependent on other parameters or flags,
// this flag could be become conditional.
- content = dartdevcHtml(nameNoExt, jsDir, buildDir);
+ content = dartdevcHtml(nameNoExt, jsDir, configuration.compiler);
}
}
diff --git a/utils/dartdevc/BUILD.gn b/utils/dartdevc/BUILD.gn
index d6fcbaa..abadd8d 100644
--- a/utils/dartdevc/BUILD.gn
+++ b/utils/dartdevc/BUILD.gn
@@ -128,6 +128,7 @@
# tools/patch_sdk.dart and then change this to use generate_patch_sdk().
deps = [
":dartdevc_files_stamp",
+ ":dartdevc_sdk_patch_stamp",
# The patch script uses several packages, including analyzer, so consider
# it dirty if any of those change.
@@ -252,6 +253,11 @@
output = "$target_gen_dir/dartdevc_files.stamp"
}
+create_timestamp_file("dartdevc_sdk_patch_stamp") {
+ path = rebase_path("../../pkg/dev_compiler/tool/input_sdk")
+ output = "$target_gen_dir/dartdevc_sdk_patch_stamp.stamp"
+}
+
# Compiles the packages used by the tests to JS with dartdevc so that they are
# available for loading by the tests.
prebuilt_dart_action("dartdevc_test_pkg") {
@@ -318,6 +324,7 @@
prebuilt_dart_action("dartdevk_sdk") {
deps = [
":dartdevc_files_stamp",
+ ":dartdevc_sdk_patch_stamp",
]
inputs = [