From b1f67dfc1a7372dd665246cf1c203528e5057e42 Mon Sep 17 00:00:00 2001 From: bellard <6490144+bellard@users.noreply.github.com> Date: Sun, 8 Nov 2020 14:30:56 +0100 Subject: [PATCH] 2020-11-08 release --- Changelog | 7 + Makefile | 15 +- TODO | 82 +- VERSION | 2 +- doc/jsbignum.html | 734 ------------ doc/jsbignum.pdf | Bin 153057 -> 0 bytes doc/quickjs.html | 1369 --------------------- doc/quickjs.pdf | Bin 165855 -> 0 bytes doc/quickjs.texi | 12 +- jscompress.c | 918 --------------- libbf.h | 2 +- libregexp.c | 26 +- qjscalc.js | 11 + quickjs-atom.h | 1 + quickjs-libc.c | 95 +- quickjs-opcode.h | 13 +- quickjs.c | 2549 ++++++++++++++++++++++------------------ quickjs.h | 9 +- release.sh | 77 +- test262.conf | 17 +- test262_errors.txt | 65 +- tests/test_builtin.js | 25 +- tests/test_language.js | 155 ++- 23 files changed, 1880 insertions(+), 4304 deletions(-) delete mode 100644 doc/jsbignum.html delete mode 100644 doc/jsbignum.pdf delete mode 100644 doc/quickjs.html delete mode 100644 doc/quickjs.pdf delete mode 100644 jscompress.c diff --git a/Changelog b/Changelog index 1a7533b..0c25b96 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,10 @@ +2020-11-08: + +- improved function parameter initializers +- added std.setenv(), std.unsetenv() and std.getenviron() +- added JS_EvalThis() +- misc bug fixes + 2020-09-06: - added logical assignment operators diff --git a/Makefile b/Makefile index 94c8e31..766a7e1 100644 --- a/Makefile +++ b/Makefile @@ -28,9 +28,9 @@ endif # Windows cross compilation from Linux #CONFIG_WIN32=y # use link time optimization (smaller and faster executables but slower build) -CONFIG_LTO=y +#CONFIG_LTO=y # consider warnings as errors (for development) -#CONFIG_WERROR=y +CONFIG_WERROR=y # force 32 bit build for some utilities #CONFIG_M32=y @@ -53,7 +53,11 @@ CONFIG_BIGNUM=y OBJDIR=.obj ifdef CONFIG_WIN32 - CROSS_PREFIX=i686-w64-mingw32- + ifdef CONFIG_M32 + CROSS_PREFIX=i686-w64-mingw32- + else + CROSS_PREFIX=x86_64-w64-mingw32- + endif EXE=.exe else CROSS_PREFIX= @@ -281,15 +285,12 @@ $(OBJDIR)/%.check.o: %.c | $(OBJDIR) regexp_test: libregexp.c libunicode.c cutils.c $(CC) $(LDFLAGS) $(CFLAGS) -DTEST -o $@ libregexp.c libunicode.c cutils.c $(LIBS) -jscompress: jscompress.c - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ jscompress.c - unicode_gen: $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o libunicode.c unicode_gen_def.h $(HOST_CC) $(LDFLAGS) $(CFLAGS) -o $@ $(OBJDIR)/unicode_gen.host.o $(OBJDIR)/cutils.host.o clean: rm -f repl.c qjscalc.c out.c - rm -f *.a *.o *.d *~ jscompress unicode_gen regexp_test $(PROGS) + rm -f *.a *.o *.d *~ unicode_gen regexp_test $(PROGS) rm -f hello.c test_fib.c rm -f examples/*.so tests/*.so rm -rf $(OBJDIR)/ *.dSYM/ qjs-debug diff --git a/TODO b/TODO index 0eec6d3..b5500c9 100644 --- a/TODO +++ b/TODO @@ -1,13 +1,11 @@ -Misc: -- use realpath in module name normalizer and put it in quickjs-libc -- use custom printf to avoid C library compatibility issues -- rename CONFIG_ALL_UNICODE, CONFIG_BIGNUM, CONFIG_ATOMICS, CONFIG_CHECK_JSVALUE ? +Bugs: +- modules: better error handling with cyclic module references + +Misc ideas: +- use custom printf to avoid compatibility issues with floating point numbers +- consistent naming for preprocessor defines - unify coding style and naming conventions - use names from the ECMA spec in library implementation -- modules: if no ".", use a well known module loading path ? -- use JSHoistedDef only for global variables (JSHoistedDef.var_name != JS_ATOM_NULL) -- add index in JSVarDef and is_arg flag to merge args and vars in JSFunctionDef -- replace most JSVarDef flags with var_type enumeration - use byte code emitters with typed arguments (for clarity) - use 2 bytecode DynBufs in JSFunctionDef, one for reading, one for writing and use the same wrappers in all phases @@ -15,48 +13,18 @@ Misc: - use custom timezone support to avoid C library compatibility issues Memory: +- use memory pools for objects, etc? - test border cases for max number of atoms, object properties, string length - add emergency malloc mode for out of memory exceptions. - test all DynBuf memory errors - test all js_realloc memory errors -- bignum: handle memory errors -- use memory pools for objects, etc? - improve JS_ComputeMemoryUsage() with more info -Optimizations: -- 64-bit atoms in 64-bit mode ? -- use auto-init properties for more global objects -- reuse stack slots for disjoint scopes, if strip -- optimize `for of` iterator for built-in array objects -- add heuristic to avoid some cycles in closures -- small String (0-2 charcodes) with immediate storage -- perform static string concatenation at compile time -- optimize string concatenation with ropes or miniropes? -- add implicit numeric strings for Uint32 numbers? -- optimize `s += a + b`, `s += a.b` and similar simple expressions -- ensure string canonical representation and optimise comparisons and hashes? -- remove JSObject.first_weak_ref, use bit+context based hashed array for weak references -- optimize function storage with length and name accessors? -- property access optimization on the global object, functions, - prototypes and special non extensible objects. -- create object literals with the correct length by backpatching length argument -- remove redundant set_loc_uninitialized/check_uninitialized opcodes -- peephole optim: push_atom_value, to_propkey -> push_atom_value -- peephole optim: put_loc x, get_loc_check x -> set_loc x -- comparative performance benchmark -- use variable name when throwing uninitialized exception if available -- convert slow array to fast array when all properties != length are numeric -- optimize destructuring assignments for global and local variables -- implement some form of tail-call-optimization -- optimize OP_apply -- optimize f(...b) - -Extensions: -- support more features in [features] section -- add built-in preprocessor in compiler, get rid of jscompress - handle #if, #ifdef, #line, limited support for #define -- get rid of __loadScript, use more common name +Built-in standard library: - BSD sockets +- modules: use realpath in module name normalizer and put it in quickjs-libc +- modules: if no ".", use a well known module loading path ? +- get rid of __loadScript, use more common name REPL: - debugger @@ -71,8 +39,32 @@ REPL: - save history - close all predefined methods in repl.js and jscalc.js +Optimization ideas: +- 64-bit atoms in 64-bit mode ? +- 64-bit small bigint in 64-bit mode ? +- reuse stack slots for disjoint scopes, if strip +- add heuristic to avoid some cycles in closures +- small String (0-2 charcodes) with immediate storage +- perform static string concatenation at compile time +- optimize string concatenation with ropes or miniropes? +- add implicit numeric strings for Uint32 numbers? +- optimize `s += a + b`, `s += a.b` and similar simple expressions +- ensure string canonical representation and optimise comparisons and hashes? +- remove JSObject.first_weak_ref, use bit+context based hashed array for weak references +- property access optimization on the global object, functions, + prototypes and special non extensible objects. +- create object literals with the correct length by backpatching length argument +- remove redundant set_loc_uninitialized/check_uninitialized opcodes +- peephole optim: push_atom_value, to_propkey -> push_atom_value +- peephole optim: put_loc x, get_loc_check x -> set_loc x +- convert slow array to fast array when all properties != length are numeric +- optimize destructuring assignments for global and local variables +- implement some form of tail-call-optimization +- optimize OP_apply +- optimize f(...b) + Test262o: 0/11262 errors, 463 excluded Test262o commit: 7da91bceb9ce7613f87db47ddd1292a2dda58b42 (es5-tests branch) -Test262: 30/71748 errors, 868 excluded, 474 skipped -Test262 commit: 24c67328062383079ada85f4d253eb0526fd209b +Result: 51/75119 errors, 899 excluded, 570 skipped +Test262 commit: 1c33fdb0ca60fb9d7392403be769ed0d26209132 diff --git a/VERSION b/VERSION index c67790a..78749b0 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2020-09-06 +2020-11-08 diff --git a/doc/jsbignum.html b/doc/jsbignum.html deleted file mode 100644 index ab31612..0000000 --- a/doc/jsbignum.html +++ /dev/null @@ -1,734 +0,0 @@ - - - -
-The Bignum extensions add the following features to the Javascript -language while being 100% backward compatible: -
-BigFloat
) in base 2 using the IEEE 754 semantics.
-
-BigDecimal
) in base 10 based on the proposal available at
-https://github.com/littledan/proposal-bigdecimal.
-
-math
mode: arbitrarily large integers and floating point numbers are available by default. The integer division and power can be overloaded for example to return a fraction. The modulo operator (%
) is defined as the Euclidian
-remainder. ^
is an alias to the power operator
-(**
). ^^
is used as the exclusive or operator.
-
-The extensions are independent from each other except the math
-mode which relies on BigFloat and operator overloading.
-
Operator overloading is inspired from the proposal available at
-https://github.com/tc39/proposal-operator-overloading/. It
-implements the same dispatch logic but finds the operator sets by
-looking at the Symbol.operatorSet
property in the objects. The
-changes were done in order to simplify the implementation.
-
More precisely, the following modifications were made: -
-with operators from
is not supported. Operator overloading is always enabled.
-
-[[OperatorSet]]
field in all instances. Instead, a dynamic lookup of the Symbol.operatorSet
property is done. This property is typically added in the prototype of each object.
-
-Operators.create(...dictionaries)
is used to create a new OperatorSet object. The Operators
function is supported as an helper to be closer to the TC39 proposal.
-
-[]
cannot be overloaded.
-
-Operators.updateBigIntOperators(dictionary)
.
-
-A few properties are added to the BigInt object: -
-tdiv(a, b)
Return trunc(a/b). b = 0
raises a RangeError
-exception.
-
fdiv(a, b)
Return \lfloor a/b \rfloor. b = 0
raises a RangeError
-exception.
-
cdiv(a, b)
Return \lceil a/b \rceil. b = 0
raises a RangeError
-exception.
-
ediv(a, b)
Return sgn(b) \lfloor a/{|b|} \rfloor (Euclidian
-division). b = 0
raises a RangeError exception.
-
tdivrem(a, b)
fdivrem(a, b)
cdivrem(a, b)
edivrem(a, b)
Return an array of two elements. The first element is the quotient, -the second is the remainder. The same rounding is done as the -corresponding division operation. -
-sqrt(a)
Return \lfloor \sqrt(a) \rfloor. A RangeError exception is -raised if a < 0. -
-sqrtrem(a)
Return an array of two elements. The first element is \lfloor -\sqrt{a} \rfloor. The second element is a-\lfloor \sqrt{a} -\rfloor^2. A RangeError exception is raised if a < 0. -
-floorLog2(a)
Return -1 if a \leq 0 otherwise return \lfloor \log2(a) \rfloor. -
-ctz(a)
Return the number of trailing zeros in the two’s complement binary representation of a. Return -1 if a=0. -
-This extension adds the BigFloat
primitive type. The
-BigFloat
type represents floating point numbers in base 2
-with the IEEE 754 semantics. A floating
-point number is represented as a sign, mantissa and exponent. The
-special values NaN
, +/-Infinity
, +0
and -0
-are supported. The mantissa and exponent can have any bit length with
-an implementation specific minimum and maximum.
-
Each floating point operation operates with infinite precision and
-then rounds the result according to the specified floating point
-environment (BigFloatEnv
object). The status flags of the
-environment are also set according to the result of the operation.
-
If no floating point environment is provided, the global floating -point environment is used. -
-The rounding mode of the global floating point environment is always
-RNDN
(“round to nearest with ties to even”)1. The status flags of the global environment cannot be
-read2. The precision of the global environment is
-BigFloatEnv.prec
. The number of exponent bits of the global
-environment is BigFloatEnv.expBits
. The global environment
-subnormal flag is set to true
.
-
For example, prec = 53
and expBits = 11
exactly give
-the same precision as the IEEE 754 64 bit floating point format. The
-default precision is prec = 113
and expBits = 15
(IEEE
-754 128 bit floating point format).
-
The global floating point environment can only be modified temporarily
-when calling a function (see BigFloatEnv.setPrec
). Hence a
-function can change the global floating point environment for its
-callees but not for its caller.
-
The builtin operators are extended so that a BigFloat is returned if -at least one operand is a BigFloat. The computations are always done -with infinite precision and rounded according to the global floating -point environment. -
-typeof
applied on a BigFloat
returns bigfloat
.
-
BigFloat can be compared with all the other numeric types and the -result follows the expected mathematical relations. -
-However, since BigFloat and Number are different types they are never
-equal when using the strict comparison operators (e.g. 0.0 ===
-0.0l
is false).
-
BigFloat literals are floating point numbers with a trailing l
-suffix. BigFloat literals have an infinite precision. They are rounded
-according to the global floating point environment when they are
-evaluated.3
-
BigFloat
functionThe BigFloat
function cannot be invoked as a constructor. When
-invoked as a function: the parameter is converted to a primitive
-type. If the result is a numeric type, it is converted to BigFloat
-without rounding. If the result is a string, it is converted to
-BigFloat using the precision of the global floating point environment.
-
BigFloat
properties:
-
LN2
PI
Getter. Return the value of the corresponding mathematical constant -rounded to nearest, ties to even with the current global -precision. The constant values are cached for small precisions. -
-MIN_VALUE
MAX_VALUE
EPSILON
Getter. Return the minimum, maximum and epsilon BigFloat
values
-(same definition as the corresponding Number
constants).
-
fpRound(a[, e])
Round the floating point number a
according to the floating
-point environment e
or the global environment if e
is
-undefined.
-
parseFloat(a[, radix[, e]])
Parse the string a
as a floating point number in radix
-radix
. The radix is 0 (default) or from 2 to 36. The radix 0
-means radix 10 unless there is a hexadecimal or binary prefix. The
-result is rounded according to the floating point environment e
-or the global environment if e
is undefined.
-
isFinite(a)
Return true if a
is a finite bigfloat.
-
isNaN(a)
Return true if a
is a NaN bigfloat.
-
add(a, b[, e])
sub(a, b[, e])
mul(a, b[, e])
div(a, b[, e])
Perform the specified floating point operation and round the floating
-point number a
according to the floating point environment
-e
or the global environment if e
is undefined. If
-e
is specified, the floating point status flags are updated.
-
floor(x)
ceil(x)
round(x)
trunc(x)
Round to an integer. No additional rounding is performed. -
-abs(x)
Return the absolute value of x. No additional rounding is performed. -
-fmod(x, y[, e])
remainder(x, y[, e])
Floating point remainder. The quotient is truncated to zero (fmod) or
-to the nearest integer with ties to even (remainder). e
is an
-optional floating point environment.
-
sqrt(x[, e])
Square root. Return a rounded floating point number. e
is an
-optional floating point environment.
-
sin(x[, e])
cos(x[, e])
tan(x[, e])
asin(x[, e])
acos(x[, e])
atan(x[, e])
atan2(x, y[, e])
exp(x[, e])
log(x[, e])
pow(x, y[, e])
Transcendental operations. Return a rounded floating point
-number. e
is an optional floating point environment.
-
BigFloat.prototype
The following properties are modified: -
-valueOf()
Return the bigfloat primitive value corresponding to this
.
-
toString(radix)
For floating point numbers: -
-The exponent letter is e
for base 10, p
for bases 2, 8,
-16 with a binary exponent and @
for the other bases.
-
toPrecision(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)
toFixed(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)
toExponential(p, rnd_mode = BigFloatEnv.RNDNA, radix = 10)
Same semantics as the corresponding Number
functions with
-BigFloats. There is no limit on the accepted precision p
. The
-rounding mode and radix can be optionally specified. The radix must be
-between 2 and 36.
-
BigFloatEnv
constructorThe BigFloatEnv([p, [,rndMode]]
constructor cannot be invoked as a
-function. The floating point environment contains:
-
BigFloatEnv.prototype.clearStatus()
or with the various status flag setters.
-
-new BigFloatEnv([p, [,rndMode]]
creates a new floating point
-environment. The status flags are reset. If no parameter is given the
-precision, exponent bits and subnormal flags are copied from the
-global floating point environment. Otherwise, the precision is set to
-p
, the number of exponent bits is set to expBitsMax
and the
-subnormal flags is set to false
. If rndMode
is
-undefined
, the rounding mode is set to RNDN
.
-
BigFloatEnv
properties:
-
prec
Getter. Return the precision in bits of the global floating point
-environment. The initial value is 113
.
-
expBits
Getter. Return the exponent size in bits of the global floating point
-environment assuming an IEEE 754 representation. The initial value is
-15
.
-
setPrec(f, p[, e])
Set the precision of the global floating point environment to p
-and the exponent size to e
then call the function
-f
. Then the Float precision and exponent size are reset to
-their precious value and the return value of f
is returned (or
-an exception is raised if f
raised an exception). If e
-is undefined
it is set to BigFloatEnv.expBitsMax
.
-
precMin
Read-only integer. Return the minimum allowed precision. Must be at least 2. -
-precMax
Read-only integer. Return the maximum allowed precision. Must be at least 113. -
-expBitsMin
Read-only integer. Return the minimum allowed exponent size in -bits. Must be at least 3. -
-expBitsMax
Read-only integer. Return the maximum allowed exponent size in -bits. Must be at least 15. -
-RNDN
Read-only integer. Round to nearest, with ties to even rounding mode. -
-RNDZ
Read-only integer. Round to zero rounding mode. -
-RNDD
Read-only integer. Round to -Infinity rounding mode. -
-RNDU
Read-only integer. Round to +Infinity rounding mode. -
-RNDNA
Read-only integer. Round to nearest, with ties away from zero rounding mode. -
-RNDA
Read-only integer. Round away from zero rounding mode. -
-RNDF4
Read-only integer. Faithful rounding mode. The result is -non-deterministically rounded to -Infinity or +Infinity. This rounding -mode usually gives a faster and deterministic running time for the -floating point operations. -
-BigFloatEnv.prototype
properties:
-
prec
Getter and setter (Integer). Return or set the precision in bits. -
-expBits
Getter and setter (Integer). Return or set the exponent size in bits -assuming an IEEE 754 representation. -
-rndMode
Getter and setter (Integer). Return or set the rounding mode. -
-subnormal
Getter and setter (Boolean). subnormal flag. It is false when
-expBits = expBitsMax
.
-
clearStatus()
Clear the status flags. -
-invalidOperation
divideByZero
overflow
underflow
inexact
Getter and setter (Boolean). Status flags. -
-This extension adds the BigDecimal
primitive type. The
-BigDecimal
type represents floating point numbers in base
-10. It is inspired from the proposal available at
-https://github.com/littledan/proposal-bigdecimal.
-
The BigDecimal
floating point numbers are always normalized and
-finite. There is no concept of -0
, Infinity
or
-NaN
. By default, all the computations are done with infinite
-precision.
-
The following builtin operators support BigDecimal: -
-+
-
*
Both operands must be BigDecimal. The result is computed with infinite -precision. -
%
Both operands must be BigDecimal. The result is computed with infinite -precision. A range error is throws in case of division by zero. -
-/
Both operands must be BigDecimal. A range error is throws in case of
-division by zero or if the result cannot be represented with infinite
-precision (use BigDecimal.div
to specify the rounding).
-
**
Both operands must be BigDecimal. The exponent must be a positive -integer. The result is computed with infinite precision. -
-===
When one of the operand is a BigDecimal, return true if both operands -are a BigDecimal and if they are equal. -
-==
!=
<=
>=
<
>
Numerical comparison. When one of the operand is not a BigDecimal, it is -converted to BigDecimal by using ToString(). Hence comparisons between -Number and BigDecimal do not use the exact mathematical value of the -Number value. -
-BigDecimal literals are decimal floating point numbers with a trailing
-m
suffix.
-
BigDecimal
function.It returns 0m
if no parameter is provided. Otherwise the first
-parameter is converted to a bigdecimal by using ToString(). Hence
-Number values are not converted to their exact numerical value as
-BigDecimal.
-
BigDecimal
objectadd(a, b[, e])
sub(a, b[, e])
mul(a, b[, e])
div(a, b[, e])
mod(a, b[, e])
sqrt(a, e)
round(a, e)
Perform the specified floating point operation and round the floating
-point result according to the rounding object e
. If the
-rounding object is not present, the operation is executed with
-infinite precision.
-
For div
, a RangeError
exception is thrown in case of
-division by zero or if the result cannot be represented with infinite
-precision if no rounding object is present.
-
For sqrt
, a range error is thrown if a
is less than
-zero.
-
The rounding object must contain the following properties:
-roundingMode
is a string specifying the rounding mode
-("floor"
, "ceiling"
, "down"
, "up"
,
-"half-even"
, "half-up"
). Either
-maximumSignificantDigits
or maximumFractionDigits
must
-be present to specify respectively the number of significant digits
-(must be >= 1) or the number of digits after the decimal point (must
-be >= 0).
-
BigDecimal.prototype
objectvalueOf()
Return the bigdecimal primitive value corresponding to this
.
-
toString()
Convert this
to a string with infinite precision in base 10.
-
toPrecision(p, rnd_mode = "half-up")
toFixed(p, rnd_mode = "half-up")
toExponential(p, rnd_mode = "half-up")
Convert the BigDecimal this
to string with the specified
-precision p
. There is no limit on the accepted precision
-p
. The rounding mode can be optionally
-specified. toPrecision
outputs either in decimal fixed notation
-or in decimal exponential notation with a p
digits of
-precision. toExponential
outputs in decimal exponential
-notation with p
digits after the decimal point. toFixed
-outputs in decimal notation with p
digits after the decimal
-point.
-
A new math mode is enabled with the "use math"
-directive. It propagates the same way as the strict mode. It is
-designed so that arbitrarily large integers and floating point numbers
-are available by default. In order to minimize the number of changes
-in the Javascript semantics, integers are represented either as Number
-or BigInt depending on their magnitude. Floating point numbers are
-always represented as BigFloat.
-
The following changes are made to the Javascript semantics: -
-BigFloat
by default (i.e. a l
suffix is implied). Hence typeof 1.0 === "bigfloat"
.
-
-n
suffix are BigInt
if their value cannot be represented as a safe integer. A safe integer is defined as a integer whose absolute value is smaller or equal to 2**53-1
. Hence typeof 1 === "number "
, typeof 1n === "number"
but typeof 9007199254740992 === "bigint"
.
-
-^
operator is an alias to the power operator (**
).
-
-^
and **
) grammar is modified so that -2^2
is allowed and yields -4
.
-
-^^
operator.
-
-%
) returns the Euclidian remainder (always positive) instead of the truncated remainder.
-
-Operators.updateBigIntOperators(dictionary)
.
-
-Operators.updateBigIntOperators(dictionary)
.
-
-The -rationale is that the rounding mode changes must always be -explicit.
-The rationale is to avoid side effects for the built-in -operators.
-Base 10 floating point literals cannot usually be -exactly represented as base 2 floating point number. In order to -ensure that the literal is represented accurately with the current -precision, it must be evaluated at runtime.
-Could be removed in case a deterministic behavior for floating point operations is required.
-veuDyQQWEF0VZ~~x%;r65hNd1hmCgun{2UR%!k@75Nl=7+R
zXyHtKjG%YKsyhr+WP3?N-0yks_(%lg8If4xJMb0%Z6}tHE8GSMCjn5 gpi6zojkUqg(uPMHG9#Pi9phXM3w
zHEh7AdCTpL7pCQw#b5Ro+u2IV4V5Qo!=yXt+M0ir9!_oEsx8Zm(ZL3#GWyt19KxQ)
zP~TzFoy@aD&Adh;vW$J$+0<(WUc^aDr|CM+lW4g}`po-o;k#i2319%J?(Md)%Ec+X
z`1S`iCtH^$N=JlB+UpJe#0w$(7L4sX?|Bz>j9`cLkNQ0Jtu;w>pi}?6w0IXXA5GLq
z=lZUnBPLIi%B@Q#h~D_=TVz&bC_%e}zy`v_+Y#|ha5$In2+7>ci^oh8u6L{l ^BLE3N*i}aFll6B_1jUZ8zI=P#vI89GODl^=I^N50P3Hrmw41&yZ
zc{K=^i!5j4wV?D9CBdT7I&=rmtPkyB3eULdq38RI8|49^n*qaPnh`g)gpJ|Ye99Ce
z%Dl#l0W#iRYjWeV$%MWJ5eD~MMa5ltZRV?fEK<9kHVdT{Jtc(nHBzxP#D%nrnt&R^?xyCN^({S9I*eqoD2!uNs}z{epB62pev&hZgZNy
z$E-07zm4e4kb%M*{n47B{%8s>&aNd&Y-ZK_l!Mp*;tm$HdfMB)>U1l)S4LwNx@Z+M
zi=Sm2%mZldT=exm_o@}2xzvCyLWg7fid97fM@V>5g+5<_XSv(#Urmld9!{Myv~W42
z#8MyxShKlCs#LFL$B9W$(;>5W>?R{NiP;P;C|jO-3KounO7-(bpM7!+m;=G?8D6yageN^`9pK2*)@`!&tX`&^J#ma)URIN)^#`t?Tw
zSkL{G)t={75AB2$Tf{yl0XPFUm3m@SEvW_gI&stlU9=w2gVW9MD4X5+Vy_=QkJ)%p
zk5mL3Vv}VH=B5tbVzz*oP#~g*LQXj4G-&R}&>;x%y0%-g#D`6)}Q1!NzlAN5gxjCtCXJQ
zqT#0w^=8ZKG531OM<#!TXzZqS@n9|u3TM0(Ha0;W`3{%adYi2t;RqR04(BOEHSgCt
zPhwJZ>&kKDNIr5e8g^{*W$tMA!(xCER9{5Qy7R3VGrmYXL!#d;#7RmRp|
zp5Szi;b8hXx#B97(