From de792fe14107fb839e695d3942ce3e23493e63cb Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Sat, 19 Sep 2026 06:06:44 +0700 Subject: [PATCH] A container holding an integer, a float, a string and a boolean at once (vec-new dyn) is not a (Vec dyn). At milestone 1 the heterogeneous container is the dyn runtime's own object and its type is dyn like everything else the runtime hands back, which is what lets push, at and len on it be the dyn operations instead of a type-erased Vec over eight-byte elements. It takes no allocator, and the refusal says why: the storage has to be storage the collector already knows about, where a Flan Vec's block would hold roots inside memory the collector does not own. len answers an i32 and at answers a dyn. The asymmetry is deliberate -- a length is what an index loop compares against, and handing back a boxed number would make (< i (len xs)) a dyn comparison and two allocations an iteration. The operand-order bug, which the first test could not see because both its operands were dyn: (+ n x) over a typed n and a dyn x threaded i64 into the second check, expect did what an annotation site had asked for and unboxed, and the result was a machine add of a value the runtime was never asked about -- the program trapping on a float instead of promoting it, with nothing in the source to say why. (+ x n) boxed correctly, so it was visible in one operand order only. binary now takes dyn_ok from the operators that have a dyn lowering and checks both operands on their own terms, which is safe exactly when neither needs an expectation to check -- a literal still takes the other's type, and a keyword still gets one, since :lo has no meaning without it. Cast had no bool arms, so the bool boundary failed to emit; reachability hid it, because the program that used it dropped the function. dyn does not cross to C: it is one word and would have passed as an integer, and C has no way to ask what the word means. A condition may not carry one either, nor hold one in a field -- a payload crosses a handler boundary and has to stay rooted across the transfer, which is the collector's question and milestone 2's. --- lib/check.ml | 144 ++++++++++++++++++++++++++++++++++--- lib/emit.ml | 11 +++ lib/types.ml | 2 +- mix | Bin 0 -> 83160 bytes test/programs/dyn-vec.flan | 24 +++++++ 5 files changed, 170 insertions(+), 11 deletions(-) create mode 100755 mix create mode 100644 test/programs/dyn-vec.flan diff --git a/lib/check.ml b/lib/check.ml index 9a8deda..50be294 100644 --- a/lib/check.ml +++ b/lib/check.ml @@ -1972,12 +1972,38 @@ let rec check ctx ?want (e : Ast.expr) : Tast.expr = let name = match c.Tast.ty with | Types.Named n -> n + (* Its own arm ahead of the general one, because "a condition is a + struct, not dyn" would read as a rule about shape when the answer is a + milestone. A condition crosses a handler boundary as a pointer to a + frame that is still alive, and a dyn payload has to stay rooted across + that transfer — which is the collector's question, not this one's, and + it is milestone 2's. *) + | Types.Dyn -> + no_dyn_yet c.Tast.loc ~into:false Types.Dyn + " — a condition crosses a handler boundary and a dyn payload has to \ + stay rooted across the transfer, which is milestone 2" | t -> fail c.Tast.loc "a condition is a struct, not %s — matching is by type and there is \ no condition hierarchy" (Types.to_string t) in + (* And the same refusal for a condition that merely *holds* one. The + payload is what crosses, so a dyn field is the dyn payload the note + above is about, whatever the struct around it is called. *) + (match Hashtbl.find_opt ctx.env.structs name with + | Some (s : Tast.structure) -> + List.iter + (fun (f : Tast.field) -> + if f.Tast.fty = Types.Dyn then + no_dyn_yet c.Tast.loc ~into:false Types.Dyn + (Printf.sprintf + " — the field %s of the condition %s is one, and a payload \ + has to stay rooted across a handler transfer, which is \ + milestone 2" + f.Tast.fname name)) + s.Tast.fields + | None -> ()); (* §1 and §2. [signal] is Unit whatever it finds; [error] is Never, because the only way past it is a handler that transfers — one that returns normally has not answered it, and the program stops. *) @@ -3357,12 +3383,10 @@ and fold_left_prim ctx ~want loc name p ok what args = let x, y, rest = match args with x :: y :: rest -> x, y, rest | _ -> assert false in - let a, b = binary ctx name loc ~want:(numeric_want want) [ x; y ] in - (* One dyn operand makes the whole fold dyn. [binary] has already checked the - second against the first, so a mixed pair arrives with the typed side - boxed — [(+ x 1)] over a dyn [x] checked the literal at dyn and got an i64 - five in a box. What is left is to fold with the runtime's operator instead - of the machine's. *) + let a, b = binary ctx ~dyn_ok:true name loc ~want:(numeric_want want) [ x; y ] in + (* One dyn operand makes the whole fold dyn, whichever side it is on. The + typed side is boxed by [dyn_fold]; a literal was already built at dyn by + [binary], so [(+ x 1)] over a dyn x folds an i64 one. *) if a.Tast.ty = Types.Dyn || b.Tast.ty = Types.Dyn then dyn_fold ctx ~want loc name [ a; b ] rest else begin @@ -3695,7 +3719,7 @@ and named_call ctx ~want loc name args = nobody writes on purpose. *) | "%" -> arity loc name 2 args; - let a, b = binary ctx name loc ~want:(numeric_want want) args in + let a, b = binary ctx ~dyn_ok:true name loc ~want:(numeric_want want) args in if a.Tast.ty = Types.Dyn || b.Tast.ty = Types.Dyn then dyn_fold ctx ~want loc name [ a; b ] [] else begin @@ -3710,7 +3734,7 @@ and named_call ctx ~want loc name args = | "<=" -> Tast.Le | ">" -> Tast.Gt | _ -> Tast.Ge in arity loc name 2 args; - let a, b = binary ctx name loc ~want:None args in + let a, b = binary ctx ~dyn_ok:true name loc ~want:None args in (* A comparison with a dyn operand answers a *bool*, not a dyn, even though the runtime's own entry point answers a dyn holding one. The reason is where the result goes: a comparison is overwhelmingly the test of an @@ -4056,6 +4080,25 @@ and named_call ctx ~want loc name args = out. *) | "vec-new" -> let elem, args = vec_new_elem ctx ~want loc args in + (* [(vec-new dyn)] is not a [(Vec dyn)]. At milestone 1 the heterogeneous + container is the dyn runtime's own object, and its type is [dyn] like + everything else the runtime hands back — which is what lets [push], [at] + and [len] on it go through the dyn operations rather than through a + type-erased Vec over eight-byte elements. + + The two could be made to coincide later, and the reason not to now is + the collector: a Flan Vec's storage comes from an allocator the program + named, and the words in it would be roots the collector has to find + inside a block it does not own. The runtime's own vector is storage the + collector already knows about. *) + if elem = Types.Dyn then begin + if args <> [] then + fail loc + "(vec-new dyn) takes no allocator — the dyn container's storage is \ + the dyn runtime's, which is what lets the collector find the values \ + inside it"; + expect loc ~want (rt loc Types.Dyn "flan_dyn_vec_new" []) + end else begin let a = allocator_arg ctx loc args in let v = fresh_slot ctx (Types.Vec elem) in let attempt = @@ -4073,12 +4116,23 @@ and named_call ctx ~want loc name args = region_check ctx.env loc (mk loc (Types.Vec elem) (Tast.Local v)) (mk loc (Types.Vec elem) (Tast.Local v)) ]))) + end (* Unit, not a Result and not an ignorable error code: see [alloc_guard]. *) | "push" -> arity loc name 2 args; (match args with | [ target; x ] -> let target = check ctx target in + (* A push into a dyn container is a call and nothing else: no allocation + guard, no restart, no region check. The dyn runtime owns the storage + and answers a failure to grow it on its own terms — the guard and the + retry restart exist for an allocator the *program* named, and here + there is none to name. *) + if target.Tast.ty = Types.Dyn then + expect loc ~want + (rt loc Types.Unit "flan_dyn_push" + [ target; check ctx ~want:Types.Dyn x ]) + else begin let elem = vec_elem loc "push" target.Tast.ty in let x = check ctx ~want:elem x in (* The element is bound before the loop so that a [retry] re-attempts @@ -4101,6 +4155,7 @@ and named_call ctx ~want loc name args = (with_note loc (alloc_guard ctx loc attempt) (reg_note loc "flan_dev_reg_note_vec" target [ size_of loc elem ] elem)) ]))) + end | _ -> assert false) | "reserve" -> arity loc name 2 args; @@ -4824,6 +4879,14 @@ and named_call ctx ~want loc name args = | Types.Map _ -> let n = rt loc (Types.Int Types.I64) "flan_map_len" [ a; here loc ] in expect loc ~want (mk loc index_ty (Tast.Prim (Tast.Cast index_ty, [ n ]))) + (* A dyn length is an i32 like every other length here, not a dyn holding + one. [len] is what an index loop compares against, and handing back a + boxed number would make [(< i (len xs))] a dyn comparison and a pair of + allocations per iteration. The runtime answers a dyn; it is unboxed at + once and narrowed the way the Vec's i64 above is. *) + | Types.Dyn -> + let n = unbox loc (Types.Int Types.I64) (rt loc Types.Dyn "flan_dyn_len" [ a ]) in + expect loc ~want (mk loc index_ty (Tast.Prim (Tast.Cast index_ty, [ n ]))) | other -> fail loc "len takes an array, a slice, a string, a Vec or a Map, found %s" @@ -4836,6 +4899,19 @@ and named_call ctx ~want loc name args = | Types.Vec _ -> let p, elem = vec_at ctx loc target idx in expect loc ~want (mk loc elem (Tast.Deref p)) + (* One index, because a dyn container is one dimension: the nested + [(at grid r c)] spelling walks a type the compiler can see through, + and here it cannot. [(at (at g r) c)] is the spelling that works and + is what the refusal names. *) + | Types.Dyn -> + (match idx with + | [ i ] -> + expect loc ~want + (rt loc Types.Dyn "flan_dyn_at" [ target; check ctx ~want:Types.Dyn i ]) + | _ -> + fail loc + "(at ...) over a dyn takes one index — the compiler cannot see \ + the shape of a dyn container, so write (at (at x i) j)") | _ -> let idx, ty = indexed ctx target idx in prim Tast.At ty (target :: idx)) @@ -5466,7 +5542,7 @@ and numeric_want want = widening, so one side has to decide it. Check the side that carries the most information first: a non-literal over a literal, and a float literal over an integer one, since an integer constant converts to a float and not back. *) -and binary ctx name loc ~want args = +and binary ctx ?(dyn_ok = false) name loc ~want args = match args with | [ x; y ] -> let y_decides = @@ -5475,11 +5551,46 @@ and binary ctx name loc ~want args = | (Ast.Int _ | Ast.Byte _), Ast.Float _ -> true | _ -> false) in + (* A form that cannot be checked without being told what is wanted. A + literal takes its width from the expectation, and a keyword has no + meaning at all without one — [:lo] resolves against the enum the site + expects and there is no keyword type to fall back on. Everything else + checks on its own terms. *) + let needs_want (f : Ast.expr) = + is_literal f || (match f.Ast.e with Ast.Kw _ -> true | _ -> false) + in if y_decides then begin let b = check ctx ?want y in let a = check ctx ~want:b.Tast.ty x in a, b - end else begin + end + (* [dyn_ok] is set by the operators that have a dyn lowering, and it exists + to stop the second operand being coerced to the first's type before + anybody has asked whether the pair is a dyn one. + + Without it [(+ n x)] over an [i64] n and a dyn x threads [i64] into the + second check, [expect] does what an annotation site asked for and + unboxes, and the result is a *machine* add of a value the runtime was + never asked about: the program traps on a float instead of promoting, + and nothing in the source says why. The mirror image [(+ x n)] boxed + correctly, so the bug was visible only in one operand order. + + Both sides are checked on their own terms here and the caller decides. + That is safe exactly when neither operand needs an expectation, which is + what [needs_want] settles — a literal still gets the first operand's + type, so [(+ x 1)] over a dyn x goes on building an i64 one. *) + else if dyn_ok && not (needs_want y) then begin + let a = check ctx ?want x in + let b = check ctx y in + (* Nothing dyn about this pair after all, so it is put back the way the + typed path built it. Re-checking only when the types actually differ + keeps the common case to one check of each operand. *) + if a.Tast.ty = Types.Dyn || b.Tast.ty = Types.Dyn + || Types.equal a.Tast.ty b.Tast.ty + then a, b + else a, check ctx ~want:a.Tast.ty y + end + else begin let a = check ctx ?want x in let b = check ctx ~want:a.Tast.ty y in a, b @@ -5921,6 +6032,19 @@ let collect env (decls : Ast.decl list) = | Types.Int _ | Types.Float _ | Types.Bool | Types.Ptr _ | Types.Enum _ | Types.Unit -> () | Types.String | Types.Slice _ when what = "a parameter" -> () + (* Its own arm, because the general advice below is wrong for it and + dangerously so. A dyn is one machine word and would cross without + complaint — [(Ptr dyn)] is not the fix and there is nothing for a + shim to read: what the C side would receive is a word whose + meaning only the dyn runtime knows, and C has no way to ask. + Refused by name rather than let through as an integer. *) + | Types.Dyn -> + fail loc + "%s of %s is dyn, which does not cross to C. A dyn is one word \ + and would pass as an integer, but what the word means is the \ + dyn runtime's and there is nothing on the C side that can ask \ + — take the value at a written type and pass that" + what fn.Ast.name | _ -> fail loc "%s of %s is %s, which cannot cross to C directly — pass \ diff --git a/lib/emit.ml b/lib/emit.ml index fcd3cdf..6d4264f 100644 --- a/lib/emit.ml +++ b/lib/emit.ml @@ -2343,6 +2343,17 @@ and cast f ~guard (x : Tast.expr) target = runtime answers a pointer or NULL and the Option is built in the checker, so the null test is one integer compare on the address. *) | Types.Ptr _, Types.Int Types.I64 -> "ptrtoint" + (* Not written in the surface language either — this language has no + conversion between bool and a number, and deliberately. The dyn + boundary needs both halves: runtime/flan_dyn.h takes and answers a + bool as an [int32_t], because a C signature saying [_Bool] is a width + question nobody wants, and [bool] is an [i1] here. + + The truncation is safe in the one direction it runs: what comes back + from [flan_dyn_need_bool] is 0 or 1, because the runtime has already + decided the value was a bool, so the discarded bits are zero. *) + | Types.Bool, Types.Int _ -> "zext" + | Types.Int _, Types.Bool -> "trunc" | _ -> failwith "unsupported cast" in if op = "bitcast" then v diff --git a/lib/types.ml b/lib/types.ml index 18c2ba2..a780fa2 100644 --- a/lib/types.ml +++ b/lib/types.ml @@ -83,7 +83,7 @@ let fkind_of_name = function is spelled [()] in source, and [Parse.texpr] refuses the word. *) let primitive_names = [ "i8"; "i16"; "i32"; "i64"; "u8"; "u16"; "u32"; "u64"; - "f32"; "f64"; "bool"; "string"; "Unit"; "Never"; "Allocator" ] + "f32"; "f64"; "bool"; "string"; "dyn"; "Unit"; "Never"; "Allocator" ] let ikind_name k = (if signed k then "i" else "u") ^ string_of_int (bits k) diff --git a/mix b/mix new file mode 100755 index 0000000000000000000000000000000000000000..362c28db85e76526692f34348dad2bbe5e95bf3d GIT binary patch literal 83160 zcmeFa3w%`7)iypuE=&+SgCIsl8FWxW0g1N~0hxgy=imuOLB%T|7okExn1QGW36m(N zV=Pu$FR!)q`r6u7ZM^_$GD#o_;Dt+7l&Zn1oM8aDR1#2_?|Jqds5R=wG20mK-WpLp#46+U-sFA~gMfr@ca}T;XQXjH_^SKs?ytDiRGpJG9%o9_6egnc)G8%Se*Km+&Sv9V zMEriniB&u%;tLoj8u1rJ{0EGaEb-MMei!4M67iKHek|kgA;xliXDB{Z*@5}fW5x<}D3mA`y_yWc+Wc)=D z{{iEE##f8@U5xi*e5Hur%J@Z$mx%Zcj9<+7d=VeVcz?#Hi1;YRa~Lla@v9ggz<2=h z;LX9Cf)ghcs>Wu`cwaM`G~-)yH`qyyj#!PHm499raOE4vbYoY6aX>RZ%#E3A&~Gyh zET;5vwOjtbW%(&A|8=T-(AZI697OqIl&|XjdcajlwlcHucc#*(49_mtjiSOEiIQ$? zE->me<6X`8t7d$y8pqA?vf|FHcmOKMH}3`B}4u|esrS0FnB}orU_GftR~$;!sDvQBRVT*gPbAjfP}QMCYoO3o7V80KONekpQ55P5Z@Rx{qwj1M&9 z9~#IpQr6g<1>t1$_E(mnl6>Pc-G~>EB&2m$RBqmkd`h1Z)Go$rf@*Bnj3b(nG>=2D zpo6cXhRRA&`jBoM)r=h|y7gOhE!ypAq*V=i6X-pP^6Mzc%%8GWH)>t!=-*4St{8L8w8r0vJ z(=yzyf3);~`DedsX?x`9&TQ#&T&-P13e4Gik4fnWFHNG(Khmfwz*bIpKj@pyjWB$Ys zTM*`WRSBN|tQ5E!^{Vm7ZSh4BF~u!oOR7TMLvFjv@v3e2n@ zGPd4xTky`>m4)UHQM+27?iaK$cALKkez{5WGMEJ57uX(oKvgw5tHy{+@PrOJ<(C>o zLPjqpi18Ql6S6Zpq7z^R<;l?ZP7 zTEWS8ptcf$Q8c3(BP!c}4NvX1|11+k`)fUC1YK*;g(O5E=%Yrnk}WB7z0Q-79u7h>lo-Aoqxndbu0pVV6v{0E>QN4Jupu8^24djXN+=M0pdxl%1Zvb3ja9D-un)d?NL4C{>w$f)8qI3yi6rvA&OfR$ z>Jx~$@*}D;{zJ|9QcRsXNN)2(AXb;&8-led_lWsCyHL8GHE@EnzQ|scl|@dBe0?O_ z?XadFIcr)+8{HgEnnl*DtV`&xl)js(436D@1@s)0@~<$wX#PdF`3RbiG>=@zhLllT zayOR86m1h&MK!Lq_ykDRXBJH@a;@d4C;r}spMkJ24^-o5?mk)l#9C23SYQyUM`dVX zt!$wI^{a2Qa$pE~dLujBw)}4;dMLl|@F~i-*gMAdx{SH-TwDN}E05BJA#Il68+de$ z$=#Q@C|FnK9|C!BJ0EiKuwV_y?$X@rwd96^y!}cUSIb&OnV&X*I>Lp&%JNFUMk}wT zU!uI)P;q@z*oO8zxq3I{%cS9teRPKWKwe5k6;+GS=LiTPA`y0QQ5YhESAG@Bxd|kk;pXm#GuHEpn-lfp!i6Ze7e;jSA zYe6^umZ^Q;u`^iu;Tq-DuAPIq8-ueqJ`RnFsNUJ#Cf=z{Jgp_JMPliCUR`(%=j#C7 zU7vfTHNEpOP~Q*cHUwukuzodJr{*09$Ay^Ze6ZyI>3J&TziM<6#Hxh~vG8-qXDlYf zDu>py9v$@A2^R$QzR+N3#xqj$zaTnSK(m8+b3NgMy0Kd~P6U%TdbP+%S7=w_B8Fif zq|7$R4q|;F%p@pzop$%pLA-@MpH`SQv_wo zJ`K89^l4vcs9rH0ed_6`&mKQ?=t0?`eMEpAx)DYW5&Te@kvu&ku3r@aoT zQQ#zdgk|wTESAihFvq3-X*E9Cn(i!2*c0DK9{avt5%T*I zJz9;2ur~#N&7Rw9N*MUV<`n!T$qW8!8IA{&qysQuX)rpTI|ju%dOzf8#h4S3=1vRF4n~fN*U&gD{{geng^qx{C;Tr0vI5V-b;HeI(7(il)n1lq~U9GIFQS+*mpT|5~l=6I$c{Ie^(N4-EVQ5#~-Jm8LRHItY+Nf5? zeM;H&fFiCwr8OOm>x`6d3!SA_T;4^Ers>fMUd>&j=e@6#9RNN8h5gKAp>UBJUEE(Y z4iylE_e2AAL4iXZaL6YTq`4YhXdw|mOf$CW?swGWJF0O&&uUPsP2h13vtijQ@aQSZ zq@fr@{Ru85@4N@e6eVug=mKD-VnSxCQLG3kDVah?pvW@Be&EQv)Cv^J-KJL8r{P~W z{2PIPm#Gi$%#Bgr!so41N{tpmYNqm4>~K(7c8xC%=L`^fU(Kn@jp^<>Wd+8`r4C!@ zQGT?aPsTzoV%ba6@szFQH0bWJ7>q6Pts=2HcU!Ot{)`4SXUn*Xt|)jd3jRf;U5kR( zih|c>A6Dj#_080jqK28uyfce`&IQYytuvLsZaJ(hyV<9vrNv87$T%SD%XwcnwvDSu z&s2wv_AI*_OCr=YTGTbVO$KEx642Fh@qbRF!iu|q_IsrD#~ zXfl0sWUSW{>W3cLYtN0aI>+R0O!iQdqqA?TRjDT4H=ltNu^zYL5&kfg_n>fkxZ5N< z)8dv)d-3R`2jop&8~K^rCZ5wOZZx-&M;IxL2)q+rQPWxfz*vA;dK?L${Z8$+zo&Kk zmi#@Ulr>Wn88OXhP;QPX-8-xGW2FUPEXI(JhrxE8?=Nofpz>%BEX;zHTz9LHV;Rcw zzoKZc5({$1vy|oQMVzG(@2)I=S;T!Z-d9=vYY`8~cu-lsO2kVTFFjU@Kv`ZYKrj~w z;^InKUL-;IOArEO`E3#eOb9}tELSB6$Pk1;S$>5C0Uv@8D9bO9AfE&wP?jqa6p$bU z%JOf~E)-LV1R+qC$0dk%4C+FlEPvkub&{Y?0M%NcbO}la=tT?UksuF1KeIqy3GxC& zXB$3q8B{nK z8|0B7kFp&8FIksYg1pLd?#_zpeG=qTmVau40umHZmcM0#O7y%#%0q7=s;)(497dO# zw@F#P8V?%Lbb;C~k?V;Rhzun_WhoGO3ZO+{S%@sf=u8>)S<#ziG+;$l87;A*c``~Q zSayIF1psi&snFY!Vb@%3|Yvn2v%S@wN8H6SL zW91^a;vodNJ8e?}8yC8fahJ?7P3D*`0_qkOaw%D(_wT6CQEMYo#w&aw-Inn}f%hGE^Eae%t|e$3gi zu=r3cax~+0l2%m;KExtAW662y8brmYtW@)A7k5$JJJr0y3l1lsps`5Zp=NC<&ceDu zS6-+=zlFP0EU%4>M<8N!PfRsx5}A?|1;&TL>p`)1 znFi`fQKu^f2h~V(`jWwFGNz>{DAbi>y_#3IxJ!Zih?ZAJdeUtQ^N94s_N1Wag{|m0 z{4nWx<_H9!=hX=4+rU02i0PAQeP!AO3~1c-A*s4!)3FsXFA5wS+|Epw!Z)BA zX*!J_7+r7yphyj@6WV4qyP&y}qdnjx%RNgo7_A>@A$`#oLR&c2OP0C`brUXd=vi=O zm)B4L=M@NEZ5@i4|2a$`UBn)8-!Tp2(5*^9C*?-S&dTuYY<$YwjXhio@XxV zswpqLr=^`0zn^eejOYP;1pEVSL<2H<-W&TsmGYfjkkNeryYO5_&n0#G0%n z_a5^;z*79$YP|~9!puHVzOgvncsG%*MVESX*s+CL^cw1Ln;O?hHr_6%@fi|5W6D1- zK3mPJSDvkb+f&ck6;ys!9W2|blt0Ey(K-G}T<>x9D@_$1-tD{316T^$D_$l+518;nEAlplS#y*x9}9dKRR=4nJz$R| z&w{iP=1Rb;bjLa(;6s9o*4eulA>G(&KK~h6IAz~Sdk1^fV&7iwLx%iA>=6)bjfi0D z0+L=eE(cvdm5dD!nphu~#X^29dXop(E$sp8SBqW=Uj4u<`h@HNxG@3qD$z;EMz368 zLcNe<&TWm4S}_X#^XATrFG>10xc&(3{%U7z9>&K*WMS(JPx*LKUK5Xblw)b%kLNO6 z^B4T3Qd8IVyYPat&!0K8Se1|l zU4m<=T5~rhMrx5=-{x+#`9rgO;=9!NoyiYcOYHFtRHxbTRZ{YkOaL^>RheeP6Vb ztVXhy+!)@YMVh}|d^PnW{jG|YOHmqAUJWU3J-3dT0nb-DITF&W1YnyE(<6-OirrcB zd^Pugx_0dspZA_Sc2X5eHgL69ZJw*0`CKOtM!vTUIQ^+0Xbe* zWnwq2HrjcZ2r*VO1}h(%WTFfTFmAn@s(mWFTiX**mgFb$X=*ev-t=nW4ItOQ%vb2a)0}>;kn@E zX7#cqxt!19f%92Ba6V(>uP!y8$Dcf(WqF9~HuD+hd=9kC=Y#fqKGt?V56{(eKM?IC zaaihDJM%eL%WanPc}Xtjb3HS2KIdXSrxGxqMFOzJd_Kha+$`sF^Z#f*ljOs0@`PbF zYzv)@<@883dZqc^4(D*eEAgTm-oE@+V)sAe_3HmMd~z(wIr_nQ;`p(@yHT zGnb58w)Vd7KdZVosqPvz_ZSU4p&7RP%bWy%kHi1+#Ajd-=)<=Dm!=O>PNF$@Y~}yK zfu{4?bGX1FG{*YCcCf0r5;8AkN$g+qK%`|)&l39|m{oEY=W8rH+ZfjHMdraud=qAZ z9(}~WT8I(2R#hY24<|S_(!{UTi$gn|wdi6YIxY(;uU_Y^x|TV%?^f5I_Q9{_kLdEjuQ*$q;;P#s zHV#Q0!=S+H{r-|Z*fbTmV1rU1G70XbvY1j9MJ1@3ZekiMF0I3*8zUFSw`o_5O$F8sH{va^`JNj_l!UtbXA3U}P;Ph@zWYEQX0A=fd(EG@!y6d%y zYiQIdi%+Lf_a_>4X)8J>a&VRjyNss#*JLu$JDO&6PV`bzv3`ylL>g z879nxS&mI4HTtsuMS=4h{^t;ye+9$S9&+$Q>E0)iqGRK0sN4$!-Le5eNBgMtF%pOS zCS@OTSR>2efhv24gJ*2OVj71w_2{qtTacXt7!+L-Kpp83Gajh z#vS@SS+Bo}Q3m&&p>8+P0HnKdWHenI}e!^pzx!anKV1dod zV74ZS6P5_mIkeUYm#!xlI9bOq6Y=)eqosTMWB9qQ1}bl3dq*4)Tbzx#AMSyZVjDkZ zDt1Y@I;Bq}I*k4(MS1nw7XC=2!6(icI)p?IzKN*|<~q@N$%NpWbUJBkYzZL!0a`^t za?MYfX?vsA)TmbP$%Hmv*iVZb@2`}tNAWcS$)BlIEwZ5#axAFRl5fLR0R+0}!|w4a zj~+u_GJB!+21gFRWxDaQKgLD{#%2BnJO{<@VZIU9w&SQoPe{EFu)Pb8GW%k3z=gMN z7lQhX*AN7dUpKB;gGW8DQ7O9uO$4#UODN7xNxxkznCt~Hsg#|CRPqjHTbY=Yy7349 z8e~@M%fw{GBbH!t!s-=eVshzGKT!BmHTG~VIld?QOW6ke&}B9H2Di#Uz}V0hNu*X> zU#<478IzmD@vSBAVyJNzQYm|;6VVD`FcP%JLG!B~%!0FM3n812U~7*@ zm3}Ud`YGj;Q32<#Xc1i?-%th!M=9Wx1;l8F2+RBj7^1($T17xinpvDjL&2$;>RMYW zgE_IH!o=1gv2Y?7H9X>Pv}!P|8hmWF*^10}`okXamk^BoPBb(HU1kphx-lIS*H!~6 z{XaSorr=SHH~cFQrq-{hnH?Dy8Qu&cO#%kgSt>YVHNfFM)^QIw#CrNUkB49$ga4r| zzDUgCezxu})}gF0GrP-~S+BysGE47!JmJ@~Vsc_K2gSc?yqD;bZ!`-ffHMfn3&@R% zl^6D?X>)+I8wX&%;>`B8ZtNf_TLO&KNYWj`sX*O7-)gppY*wgT-9JU|doLZ0wrde4pHZ>c90b(T(jzIP9*C^DQ!SS&4`Lqr3S2`V~IQA z{}`7VGd()pKPh+wmPdMMPyuAB4q?J`D#m{EDNF);mhBdv9n4NBTKIQxw);i54ix~= zE7aO)x^WNG!2{T=SWoHYkaH*b8%y_+#VFsf9S!;RzRDv~J>grWh7$*|IOmM&Lqb}1Q}~!So4@nQc_Fwr`UfkIoYv&-m?-nIm>+s{m7tvtMb$t!4sMXB zv%;ro73sst)!xJ)Fqg7oIg%|TDF5q?c+=L%F1Hv&kM7>ZA>>3VfWuFWSD6$pr~=Ei zW9~4{C3Dbe*+S9BH=w?P@}0%Ei%Rp24^wQEZ)_D+LuWLo?t@mv+4AgM#TYjPcmzk* zl~He_@psuY+okRy%Z(8A!42AUJaLs)G0MuWDWf(CT!8_0%)xlNFr$5;fmQ*n=~!Zb z_1yHe-3{dh?%um`CMBK&nQf&9n+^fHErdhmQ(@!011u;SGDCE1_(KNVPDu-El-=#W zxI6tNFs)#3W(HTJ`x7@|W*5-ycZA&PF+bY`Nhz&Yl+*zW2xU!T0vVjnjAjN66g)4e zyp}mrJf5LNu>k>CR#5R~3fn|8KGBlzU|}s}?b7)|_|dlW(zbg+ATY+YA~SIl+}{Pp zJHn){F{giL>j!m6gh`1DgV8ZABQtR>Fc{;SiKp%wASxa_KwykZ>7J=$wrvp{Rwm>q zT*!Lg!+OQQ9aK9Mb!xQh4sul4uc?qK#y~bmJB(6x2Qz?Rg%~*@w2O0NT16oqSBXii zLT7PO>!9qE_%nP0%`lcp(U%(YzcxxT4#8BVXfuCE0MB@xV9qH5w#dqal|nnTmc6y~ zf3yG=X8~~9q2lyKU%axlQN^SZf+bmttrhf+vx+@KFF!=@J`}yHqq;IaQgb%xeGjR5 zTb9Brf7~5D9RmdCK~sVIL}HMX-?Labe+g?;Uclr=UJWm3K%`(n zgPC-zYJ7~0b1<7AvNkT zb+g*g?{Gc{WjHC%74s3EZkd5N@BDwe{i{ zlsp+~z9M2`4+FVBD=@wlgKPc_@Qx-Cw=U)aYMSg{3 z+hMV+ntWUBD|ynRxxdn|1Vyg?f-@g}4n5@PqhA>DbboL~XOKbpQ4QenA3!TobZ6}l zOa<1KOq;lg0~N$xGqZBN5+8}IVvsN(5?n$s^(qI4`_kpHW%J@^iF_CmkY9jqkK>&U zmz)6-FWNmqvTN=Sh^&}FlR$o3kbEhHa=`|G+LaMR>(M`=ecR*|GxIdmdOMZer-?$& zqw~=nYbptoM@w$f`hJ8}`WBr_bgCe$<6T6@se?KbQA{ONB_|Tpj9jI|jHM(OtMr!y zlVFuTkP;RfHNV7ykS8X4M>FL@J=0pKXIcyOOj3iQtaLpM4W}v6vVIir8$|X_5r@0C zJG?Ui=s9|4aMljTsnKgoX5(BbEHIdmI3Z{pEWn+<|65uS?Z%E3(zei z7Ray%n%&`E=wP!7F*q%E9~dCAehN08?!dcBFmlOW7p2@BAG9nkoNkUf)%`x$v11oU zJ){s^9QePkm5ZaqB3@eJVX+7~WX`BfCgY1S{vcjjya*4R|9G5+M-@{Jk7N%_6s3Dw zyg)!-Ze?Bq4|9K=@Rm9D?`(e?H=qO9uD{u*=WPj}X&+uT_u|+rS7%SfZb8pODF*@; zx7Fs)?dqK4!@( zs2wtYQO&suR1+7{QbNkPQi$UT`}Q!D@Zgbl(in)`VURnw`?Etm=paz*G1D;=+rLno z-b=uTC!%;uo2!hzaZ1N2YP5HQ@JR8z82DYy`A99_qm;dZXhFsO$%2YIAwO>SdmZBs zOP=Hc8(_sj4Fs8Z!X569-BpqezB*9i?E-hT*sw@Kk5gL4*Wr)!-=hd@NkPjT2wN1Y z7H3+U^uD_hIVQY)aJZTvG!u0=WG2}T8R$k3RXAkeMW{}kCP)jX%m6uOq*hR?R& z2CFp7af9kMrkWtS)%bS^r&KwgB1vWOS)-Ev<0Wz^DASKDn-YHj!U0}4vj-e_l$=;t zV@Q~mAD@ggN+-syjPnSXm}MeoZ21f*{X|-U@x{3M zbW_rWvN@^B<2A(&?%Oi=C(v7j@vY9QoV{1;N{eE0d9_c1k3TJJ{o!XcBASt;SD zlvk4xxb`g;Zr{+o*f0=IUU3pj+Ya4)K99ui#H)il^t{7L#e*z?rI$yofDu-}4T!n| z<82tGSQ85`ea!r^$OGR7W@C#yRU^Z9xS)!XwOZaMVZ7lVr#lb9AZC|ZOL&Js9vpCY zhqGWd*J8{P5C>FLFjpYvE|jw`=2TQ0wZ0!>a$|w|4kk=uh;;~^UQ%H<9~C|ksq7CL zTQRp{`1h_VvWpeVG4pNs3WI5la=K z=h2NT+t~r2D5H6_8X;r?RoYusLPMs`w>b6#B7295mzCawlRFj^V=Z6MgV9sHz=Ivu z-@4WXFwP*m9v!J07XqVyV1IQahu+8Y5|PH3a9P0p>(MI4#AL}a%B!!iB+r#$K=#8$ zi_)+-WbSO_#sYG;8H4)~KKp46Yyw8jwLY$)A*!3q-ylhAIafIC0FL7$;ejDkq2z-C z&>qsxS9}X}hMo)QTBGG{Tzu`d6+Qc^$xY?^it(lcYu$bKTi|d#+>0}DH854tB4|`28iN~1Tu`{g3uwbiUk~h&yws=Uyt;Vt)jRmv{wV8*k(UtS?LcrTYIijT7+GeUt z7(__Yl(8`w(LhesF#p`>ERF_<&YD_QE!)Z6HWM9FUW*|v+QBqsJ61U?Vb?p~L2}Gb zOG30VpKj$_mN!sDC}lfw0+#3TgKN2mhn*p#8rwjii}t$h$=7L=Zqu3)=s!1vuv3Oi z)p6c@kjZyd^6HcyJ&t;~dr5YN+Js+5@N4fkTl1@Zo)a$|Wb@!2bP<>*dL7KVhVX1X z`hDoC(C8zh;Wr$iM=x}G?zr2TI&nA=$Vw+7j4{iJcnA|jI1&GfRfyPQ9g77e54QV| z8+4a%rSsUMeO?R>ziP7>v(c8vt>#mI2tauSjao4_7UZrfrVj-@XH*vE#UK1)O1&-z zlRFY$nQOhw1=D6<@ie@LsOEmiSl-)vzS}H8$5HNma&f7J|aUI|4V9BEubEi>>RFA&U9`yO)Bt-)mXBL%^+Nbz zs01lc=?N`TFDmVhO2Nk!*SMj8G9d92S$36>g4KG~QLbTqtamr-t!KT^R@;h)aagmq z7GI{j_skzG1URon0i>_$J~Y2Kw*nFAiNT!@mu591IM7$4DnSg_4lttgbSWJi?aA}f zy*t2f^yR2xwV@hZdEn}vZ)s9w3;k;CA7QJcSg<%I6IMg=U@2x6k2Nag7jjL3_c+SV z!~^Dq^mC#Nc!FFZe6XXiIe_JI@KqcS=5`a`@!&=hz5HeMh(N-Ntquw%DpJ*4jq{v1 z8F`kttK)300)%(hadfL%WT-7HGi`Z6b7;OWf|Rldh6LOS)7~Ar zL0S~#myN}#9UkDd1U66KPw54;c6fx8uXV_Y09xDSWh#j27-hnAo^@EDop;h~Sh~iXW*qiDPGA4i-bT-ydJJc*5 zzqGxdYLl?yJfck)aiUeZv6U)}>xNq9hk9Cw!vMb~4z!RJ&0{!wt|jx)7<_1gmEcy+ z+x}n=Zc=%5ICy=KddiP(z)lsoJ0E6F>3YsAhmCG-cm;e2C(ztig}QRIhYjf7ILQio zLfrDv8Lv`uSfFd_+UUz1H#mt))+SM+jy!U+3Ulg>Dqv;Jh#dQcii8 zi#NVO0EA9g`I5kHXb$s*m*h<$h?=!80*|~M;XBNuFVGQISI=rtVV5UjJy;r z@E1XQ;$DPxY{&cqz<`cK7tHynB1i{@D{&TF!^wt7bC1RQxo?9dS+I)v@sg%7qOb<_ z;z|-A%rTJq_*2s@TPVg`A$6>-FRCjrF89Ca#=dZ({-pJf>@qLmkf>V5uH9w6b%dAQ zanu1PUT9TV9p|F(Ra8ByF8y+L&)kUq>Ujs0@<-UAZ~nyI*SG2Y*Q5^m=_79C`$wh3U3N3T$#HuweVE)J`7{okTmnqw73^$RSd6pV-HA6c;&$o5JDU< zAt45x6BC4BCsQ-GR^Ip4o{c*PYhxVxhr!%{jUo76<_9qUgr85*;MK7#Nnrr~H&*jd zWPQLTOR)=#y?Sg%U}2JV2%A^H4YDBTndI zat=rRyyaH%zWBM}=F>{RJ`$qSSpt>y!7Oj-#xaY#csSM4bwrQrvZhCL_^E8dXi z07T+5sK2hPH)nx3%Oj@4e-jDF#_PU*!T3{N0pp9c zN#aZ@&LKdY6Z{DHTE1lrzP@4<_8id{BHWI==Y0by*>2givKx!1wUOq#fFH{saK0IR&WRYbZ4#z}xdG6&gA{n}y9VhSxV%$J zm3MPV`D2YwVdO+7rK}bdjo>`uJ+SG^|AvUzgxgL!w|7|uo#<^ZtN1No@Z)8P*NHTx z03Nd#O*-tKz^YTq>R85z@%YHWcnlG{=A{L2lH_cXH&Gle$l6|fr-rrCEm~ep5U;rb zlc4f*SQdx%tXk!%+I-*6{Icz#tKcbYbyG#SeiwdKWt0?A4!x`KfvS ze?vMX$NLI$miD)$wKOnL|I&TD`v$lN*Li?gfl>hHTujdryYcch#SoV0z+G!Pl$emu zCyMxY)SUOxq^jf}!hR9m&BnXt2g?UW> zck*30NJlR2f}M#*FdSZm5X-OHH5s5;tytjIuE`Y7ROz*AXuQ;}N#|eQkCM8-mzNK| z(?ee2IXL*nmV1MEgAZ@Z@etT2=I6f^3_gyB%Am{&@=k<5*Gf-tR)+52njHFWB}!jc zF?*_R-|v(!AuTsPt~lNfQzkOjmchh zORbFLBH}n-UnuUeg%|wZ%$2J#sf%qs}*Zj_X@hqK0sJC&YJ?*ZPxvXl&`p0 zjFJ_j$V_u2#%tn^5Rk2uXGJehYfvmsNZR$vv$bH-9JUId9L) zqUV9zYH|51uVYO767#v0KNOyRxSu$zZz8i^F~uz|A_d!9WPYRd;6967b~h`ZsKF9q z1lq!)W+~gky9tk;4H=?W;K&m1PaMqq3dsnSzeHZS-ZM`V*bUNALNoT_9z{Jbp_J`{ zlEj^fT?enw{Ypi!DbjrQ;(TcCl??$*ygB|(Vs)yP9+yn_W(qGo=d-$uOyZSl?B{4K z@q{(Md7on5scTsO7iSGmp@#Sk5Z)z6`zR0N+G3Zu97Wu?h!qZQ&?^50`<*oJK!}lA z#y5qd-4>%3y~6KqL%=n1b~Myw+`(qlinSz)c(=dC{6^H&Z#Yuo`ysPW!c|%R3czi8 z+>;f>pJ^}uf}U;intyio?WgS9qJOI33#|%1!-6BMf|5}>8jnTJf?O>r@pKlH;&g$x zE@L8di20klEzw1*xZQ8Dp3O0WyFOjb8F8KunK6g6Q_I9VTGj_8BeGakI2TOZ{1Wnw zI1X!aE&t#^Y(rh?FG1?TGwVx9^1-+Xt{P6?ZtpN>G^2_EB_Z8`880DLE5^$4esA0P zA`aHV(~W6|NJUf=EH$@d9P^S6bP|Jy~m_(@SY(T+YTk%X6oRPy2TQWIqXd>Fr zjqy^on30iIO+mggnsF?~2ity(X6!*6s%M_i?BYc<gIX|Ms8k-pBY)UC z{s{s=LNUe(!8H~7Y?BofRJ_9Gs7$**3nE0C`vj{*o60Ecw86x|D_6(N_mDQau51MJ zy0rT8)fXegFG!_qWDJfG$t%u6phX|@pWKH7-VYDLe}aAi(49v7VPdJI9%W>ow+9?&qv)$r5R zNWBjpKbrj{OcqJs-~o#{e5ke2 zz64J3=%A;#@P`XmZIc&QOO@!3EwZo%WHbx zbU#*de}`(O*P{O@=vg21Y-dZ)-cHxX#(+@ZWxVPu8ewVa;!{U}|A_yaF~V{-)JGin z<5FMXPld~-hlr-1Z$w6H*d@x?KK1WSd{+hb?mn!DSbaHjbX5Jx_opaQ2c^FOWH2Z^?38yF=T_>*klux@-Uz8}M(#-%U&LO0ocMlYb1WBBXjqEvrv2Bw+N znf2~@GBwPt`8_@ai1UpkC{W%WBc8eP$Mccgow@ts3Nzr;3HD5PVj4;|maak@fyx;2 z2XpG$VdE!i*s(+AY=OXE8j%qa+j$H_oF~h8X)O}!Gk%MJKX6m1FtUaN;R;hHIxzfD{~ zEA;mlm>6Qf>ND!Z91;4v2q5(MzJd{=o0H`fjByaW(-n{@_o9 zHaG*d2=<1F3^}yhTnqUBOe5Tko(0pMZ6peY2sr+)AxcQ3QjUEt+#J5rZ^X!Zp@AEb z$Web?4E=`~`c4@7bkE?y!H7sqbJ!}plT4Z`a?icZk%E-H5X~5XcE5ukE=2M_$q(LD zr{stCxUfba(BD__$RF%EiywZSg0#yIK~&!nKV)D`;1uqFA10$>@PmrrU*-o|E0P~} zJudj66KZM255EKaf5s1E(X*5I;ip)J^Y{NXKb(Vh$qy~|d}J?tUyu#`&O#Dw`a^u5 z-xIp$btxcrJI|*G`2gKW`QZ9-i+!(_*0yKgZ{SKBoh1L`kw5Uma)1C?m4dX`_gclz zZ26Fj>Ra3QvR&HuUnA{1?ECSk84JPhGl)iP0ihc5v0eyz;!+>6<-;LfU*MtHsQmCC zQdBx6TDeZ3Zy`#K(OOJ>jP4aXcb*ETP%di7&5o3MX1KG zHalcqh#uvq{iP8Z^9>PzLJKI9@Qb`|sSCAYv@ckCLdp!;4@!$*CI99d2OUBqB6{wpBhqR96#U-d1@**3-KQAvnHCLlQU_mU@ z%zpnMGjx0ZCGbFf#%2WkNwSu2gnnOZ4OsNCMkJITv-Eo@V;rk>Ldb8c%kM7qdw1%0 zk%$3%Ofu{y=yx3Xvtq5jsM9h&2h?Q7Bs32Lpaj*rp#KrWcujGPm;6u(l>e1T<9JY(r1rMkLVaxICXK+=Bbbp^u+_L5$CQr~JiA?F4Fs1cDTP3>oNIx&Bo0x8xBq zUQ1Hr^)AOt`c^Pr8tP&1FkXESI=v_kDZ3e!bR=beRPmis*8CG`fy-X-wtlzmi2So7 z7O_TbBSxs&8nLJ~Mw`Tl+2i;4caB&LG!r=)S|gUR>3T6@q77gtMi?VjgFM!A_s82G zF{x%K>lLf1?zp3g_YiR?YdgLyX?{P7F-dO520na}JLCs8=o?A`9<0kh4`K@o zS6{FyfCds{f~Ch}cv!DS_}4?aC3?i1nDDsd)t3|{VT zM1DH{ra_fBS`7af2POU39{UOyC^_^pbymqVkOh2S~O#2Ui|LNf%c3M{Bkd?7Sc1y_{YS`0s1QUP%Vv{1`|vS~#;| zBx~)D)2?V|3)<=S>~*4@O$)wvay!}g_iAYZ>lUmWUNg{2PYGoMfMP%97l5i2^1cW* zGu3Wph~3Qh|Ji2n_6nLQY|{*&Xyz(F^@?AM>n21mK)XAI?b5&7{;OMPw`sgZyHodR zH~k+g+V*KT8haa1k_2M|=Q1ybDqL5J9!tK8_U2x$_^@Yi;*I8NWX1~Eiz7;8-p#5q z`a{}8T7tI*!5xj0^SaSr9HYmv@snPorT=G*52NXjmuuFyjzimq{{ax8B7batd*9#7 z!ja$dr19>uuf%bc7WuoD`Ez3_|2Dn{h%>CAfg@Hwm4U&3pl5{r!wOLu+C z)QX-TBS4j(HR8J@8}Y#~<*S|e2Xo}B*h+jOWYy(F84qQb`{aXuxfjvfFZb~(PF`+_ zmoe%9`EaH(fAfAkY{s`nmNwv_29O3q8fL1>(oG4knzrgKR;Q=szvZR>CvS5&fnITw z1-FN~*DS0KxYj<$DXQc*ROX>`=+jS0^T;=yuy04=Rb9-i-v!%`zgGb6gIJkkvs5P+)y;Fk)N zN4^CcQH_J`c=}!(yD-+{P4Oyz_uecAnw%(Qe-`;_;W<7uzZ3fQHjYUQ+KoqSeKdXr zGBCS1pmD?upb&gM#khSLU)+%PI!>&6Vrm4ozQKoN4Xi-VbNurp|E$0q@T>t+sDtUz zo*tPQq0DPC+YbI|U|yy4L+{CTAy9u}8<5lzq z96T9|i*xWMxuQqMd2|CZ2Ola>yrXcj1zt3b-q2q)ZtjowsfMs74R^PofZPoIcE8*| zAWNcEFMON#@|D@@&oc3TObm?vK>S{X<;j_XAqBnTFSK>Jj!2u4M_z^L(Se zbT<$9RqxK!B1^8uH5z5N!i)%36uVDK2-3cQFvd-_C&C*N5v(-Kb4$spxP@!bRG2kz z5aTvT@lG057W#l8O3@(fwU*&4lvu;g|nBD!+<&qJPAbugtz)@ zL1KKYs}WGmeZCgGZKxXAjGfZk@bc?v!RlR^$02GqHZH0-}cquYJLR_0|%K8BR$# zl5m`0Y%#*|>mVnr`2_i3pcaRGfLK_HhK^*YtUVN#=bqE-dto66co9|gp8jH69=qx} z$d|GYjIDBXgSbq+x-oNnRCi%iH--jlc}GJ7D#p3nPsVGVM?nMY~N#fb$aghF{8F07?ODMpG<=G(DQ%9leQ#;!ud)f!r=F zuQ`a16Ki<~g39BuF`kC-JIrKB2Rz_4sP03=%x5H-(G^W3e&2#054L~02Z)8|(X{vh z(E1QjocrIF@IhC4ID1;*Qw@BCm(vz*`omhn3*=?a(Avr=g zowx*i6s}MFnWoXU5Ck103NK_A=MUKE%p)1M6NS(nJUvwi6mF6z>`dTw#NI@~L64U9 zaVBJ<2WG_r9GyPF_9wFaV{CtCs7@7AqNV*;qyvPmz%)!9k&Le@aWwE9HQqj)19u!Y zpLD#3$K$5~+&pjJ)`7PI8^moL?851Zenx}5v7>xj_-yDEd{Vf@|JWOIfUi~b1Xdxj zwy_+O7b5|)Ip;xm4*9u{DD2PC*v_P#gav4o3nv#VV?b!#Win@S3En=z8EU+=HKFt< zG?{B1|0tujf<}9UsOb2l-d3ci4s)?;b3Ph|m-QtiNY7VfeId^6wHn`&5nD}i!$h#- z7CiBz&WUpz^oQRhvIm+$oZY)UEn01=1chwfet?dgAx`us({O1XxM@YoozWFMfFHyet3nC@>-%G@X! zOx6S=$2>|IOjZnK#yLoS&K)-S0$>B*UrBsl^p-c3JW0dg0AC2iD>n=-U!3 z;oZ#-Kz`FuQ4xZ2c;8WcNpUA^d|!>|NXaqKEC+lEM5u=oC#`}zd0QsOEL=CO@8GuTmJnVB#@_0-P^O*(x9L@41*03? zQ6HNKgzyGCq&Y7Yl`RaBd<6N570*PHw>v+o;ZPEg-mTX!ZQ_n`$Nd-_=OG;NLXN#k zF6b}LU|_I%^99n?=pvMKsIw-&^^RTQk`aBrBpa3YrcFqFM_6rAtXqf=nq z6c5p(fuS01NcsRn-J3&AyZ9&g+We8w6TXJ<5;C!i@hF5KI>^m_4P ziiW$n^A3mdIVy$Y@&+CVi*>s?E;<~1j$wTiK1qy(k4qaGok}VI~W8#~EC77?$ovEGM^WMlbk6W;s|_=qKy@^geXg z+=3d(_?>R4t#Z|2-P9F-%uNu|E%IOj&ZCPZZKWvkGpk6~dg0ntjY*!{oP{e`*eOp6 z;aE%eJ8HPis^N@!@kus#zta846Y#V`VhrjL_)cim{P`_~vABX(hxYqPwV}2~!XpZo zAp@jb>U{v5KS(<8*uF@1Uc=J29@Yqkzv2P6IS?&q#x=s7GFZI2uyg6@eBYNZt$t)4 zN2ws+@Zo2}blzCfa;JlXh7UpN!Gz0qxh6Q8oMJUO7%Won%3zcAfou=LD*h42g3Mve zgxC5wFd2BwtQC0&v))$pUH3hdOk}0(Me%A~v~z`eJaY7evV0c!I(mA3Meukq(tKQb zXcFRhdpdkAT|m4J=VqmHTkg(C&CbZNF3Q7aA{pOa^x*UFPi_ieO^aJTM-zs-AF{BR z+T+8yEaJ@<65%Y4e~t)-5bmT%ov6=C2kGgFZVaF`>#+UdJzc4UAK~V0k=V{ibC<;d zoZkwdb~q2={Je83{d+Y?W)T2x*?LI1y(ZBMKJ)5?7xC&u7eJ~L>Bw9y3*kO@`9h=Q z%FbaimP*+Qpp)XOd_VVI0v_D-!>esKC$55}-N1)jzQTyNWpk(yX0~)LbcWTj+QjL6 z_r}ISCHLe!S0>jnX3 zDFg(+tQ)}il@tmxehK3jwZ!`|-YXTKU|t14D+G@&ln9<)@8Tq>PV{LzOLs&1SnCy> zpDc`ahIc7^Rpjb)rTq6OA>4z}$zF1T9$n;xK&Jad(YK42Am1?`Mhjri(bdg;uxd}- zE4gjKz0uPvu0I|*c6`y@ac4(iR@N<;^Szao;Z)!KRpw}g$w0C(>! z2JbC}muWN3jkfgf+UW2vuZ>>5+w6g1hF$p+ewq-g4Y!{6cU&_T{*?Bb@+w%UMKC+{ z5%n4QJtLGsroYS~o~!3eJ^|lfi?M>(gWPMQTK))0Q`NHpOxFj0%x4j8EsqN$BQwH- zB3HY^-&grHH{2M5ZjJRm*hM(Gqv_SqbC=Yif-CXIyrXq};~Bl4)!)hLN7~i5^#2s~ z8$GKhIqN?TVdcPgKcg-6e~PF;zomZi&jj{Cv){GBw-KYuy!xrGd2(ni##UFUEo8cib(2AYu4rJo3G*uI8optsS;43B*pWA?nc_RUl z2fVJOW3VO$vkx^d1;Y~5Y00JXJ!&D}QGX6g`B#;(a1*J%w8Tj*VaTdA+; z#B6sUn~lrCxvY?EjwAZEK8cKU+n>j*8b>y}g=}^NB1GyF@_wgKSI%akqwyV0F_CKv zs|;p;lG*E#-O>+{k!j&{hyN4_;F3AB@4E8xOXf@; zG-q~ExOhYcT%N`p+bU4{mQK!nhRAIq#9)d55CC@!0Nf z51?nXlaki~{1+X-b+p@FJ;OSH-_$`puXg~yp@Vu>b&!8q2XGps?cs@oVC};1=>T5X z0i5ow_Ueb3)-Jrb1Nf#6;1_fN$3}I#^`FxL-7-6X)1lrT{@kZ)4~`Qp?ZO9lP!A92 zw^z@`4&a}507vyMAO5xds8F(ERgc937|0A3Dwch}jjSoa{FTrQ9J>vGi~B)qW=+%5n?h4OzEi9V9V0KYxrfb@qdDHHheD{n{X!hJ0u9*vF zh(A-OyHGZSKMSUZ=euT3D+tPe?}1_ za}dnEXZq{~h)kas4!IW0m^ue-xF*jio*i<{wIY)tX{TBE&7C@16b;RrGY8q{&RaBt zh0%;_riJCyIkWFBnlXK{EIl(c13B-SHg~=Yh|efmfq?6TBj?)OuVm$hWL zbnq1z(@yv=P5k9k>;KZ*#9ODjv2&2wL5|KAoN6o6buW06a*V&9KK4_nv(7Gl-hr@H zBA)5OiBb{&i->2q9<$<4hh^M*!+lq(JnVrR6{26inb|^s+QfJZ`WB(c* z@bhgTLYvPs@J!um|7<=doccEP^UC@=17I~Nk~|JLb+`TVI^gLx5Mj0h&Nl3y&jA;D z-%9B3fU|A;H^c$A=PJ{NI^ZBs>KAapyQHA-gE-))IpBp3cvlB}k^|n&0iWW4pYDLq za=>v&EcKi3fZII6#9{}$dn&ifRpNj<^}z}U96prPZ>0m?GX-_Io^-&^bih|T;JqC1 z=N#~}9Pk$%@N5TsjRStR10Hk0sVnSXg9Co94Me!b0e2dEI~?%y9Qhj^@IDT>>45tj z@B)W|zw($Sk;uRL&-7l8- zUSx%NR@l2u+=km>u9aThUzXoygo45_P!@t?-Lu7eZt_=5C@ncqK$J>UUHu>A8pDOOP$_KBK?Uq^LwO05* zo45_P!yla@-Okrh_@q_7#tJisNjx@N@e@{P$J>V9Hu>A8pDKQ~RX#XEw!6~`r&wW4 zo45_P!(*pNxAS!ro_V!w_iihE+6sSc;kCR?+=koXnp33P`8o>Ux5|$kDe)+=!bU5+ zr%l|3+u;+ZNVoHK6h3E_e+ZiT;U6Sv`Z_|hrT?R*`DYpwDdgR=d&6>hP@ z#x`*qZioLkMY^4@qcCZekB*k@|H%qhS>bQn#BI18t~o`zov)*?+A7~`jBNipE9_^5 z!8UOlZikakk#6VfD4b`NpLvaJ|6wbfYlWq4;x^n4e{_m;J6}iP6IS`76J+~ID{TBX zhj#t{YP~i-2PaDW2Hq&ci~h}_UH`vYuZ>TWh0hf?N&GJPH-~op|7yK9J_jaAyt>^Y z!_NQa(60Yqt=GoqX$zkhtnhdL=FqPHU#&NV&#jVf2Q0iQt@yty{N4X%eKtNLZNjUj*mZkxzaf_vyZQ|tu<$D1?4s#2ihY1j_sw2t z*MFDjpr`^)*}FrtM20SKt@P(${Gh?BsbD-~T6e+Umw~CPV_noR75c4gb1^4Qr84G-& zdGqe^%?|k%hUd?pGaD!YN1H$keV>)A@=Z z3eG^N}&MU~17qR<FpfZX{yc03%vdnc#{rn?n+DbqJetajZWW0^DVlLN{NiK?pX?|+ z@93P>gzUUkn{Vp$>EMus;EJM_R@nkbhNkZZa3M%Fwa9l*(Y(bV%s}75d7{>ZaQAbL zfLgN3#k1zknL!A-16cr`HfzSTdqinC?rk;}DPl8VD(4T;4$qlmG0Xik7R&<`g4~Y~ z$s~^KmSos@MPzgoNM-q7?R|fA9L1Gxc_fSgGYsH>2#|C@CIT!mHijt1K+BeG8H7F9 z#uy?pGt!KH#FA#L8QB(?L|FrIhyjHdFbVsjWC`&u-j_)pA}Zb*&OGE zO=c4|#~YkIB99Pw2Qu%wKWe(CH3H7r^WMHc=yRmo{nf2ow{G3KRn^_orOgo#o61m~ z(C(QYYFT<}(u6{-5A=~(>QB9RfB-kf8QdY47W2vlRo|L{w1hD7n;ab2L3WRctUk)- zqCU6^ML{{gTHTqUJf5JWhd-F}ten|ChAymd9ltR>Ipim5g_Lb%!UmJ5G5j%|%^)an z?;_KXa$aV%E?77bUXIcbu#;#UJb&v&$U^@>j*PPcy^b3a?9SR7I-IW2e3}befwGe+ zsv=A7=^uur&~D}4vMo6_ zBa&k+0IlI|4uVB0Ctk=_K{l!Lz$hx+KTJlz153nSn3cv@iRyWZEyO!Kf;e!AS>W$x zQbf7u_rPmOCdJKORF2D)_}`s`M)`~#D_9v{D8J=IQ!xWDx&B)b1u-c1rc+m-tz{JE zut8Ey=Xs{H({v7*&b;XyHt=JwDLPiRUc13?H*|97o1}jKkTZfFL!Ou!LXFw3((Hpy zUvgX8NntcyNL|M1K^H(t7$>*mF=ron+Az%0YbPZ6WEbKtOk{X0x`ixfE@p|SdB!mq z2$QL$Jj^V}(FnAVyDCNz4BYv2mP@x4PNlc;?1ELz8JZ5ofh~2YPb|P(Wavs3?F{zg zEa#wu?O-|plL~-g6(?wzB|QfAry!-#HbWzP23fX<@8-IPlX-N@?o4)+1B=v*2R}sp zbV?Ku57X{SJ%_?JdgmyavWEtb#sw*jG8b}xT#!TLqL9g98@-n&7px1iBeXcF;Y>D5 zCPqA!wi$p(vMFRDz+(DAafk;(T=Q^?ZYI-1@~Ud;fD8SD1`4zmMFfsKc&H8qa~IlR zfYMP0k3LznD76<4nPerXfa>(62T~^*au&=($bemG(u|&k<5@bKdN?!E+eeS?NfU7Z z$}McxK`3Z>oT53m9SKN*E~jqqELap3%5zeiNH$`rm?}%( zhGcY8QWMo2M&LyqxrccYJ+*BZ(WbDmV3rm*(X1QEuj{#v=jB}a)F|8mQz5(>L5-y5 z*TzZf62i#rTl=)kx=q{Y(8?WIOybk2HJ2}eFlZ|ggiJY{-a67hEO8%=iR$!UzJwiu z+b-|VzUrN1@0m6G@=Rvn?TUB0z!WHceI}E?fx< z)G+WzPQuF}s9+Pj_h7c4CW&1my;L(^g>9tB#%4*BHGg|2jddz!mKdXRFj&E#7*rMvxR)WVaxP~+Z*n(NHZPMaz78d{ri!DJj>s11%_ zfY5fA;lm8|qm?l1n4To<d`5!v14;y-@8(k=8CU6u6uS@0m=fA;k!RnH&wi~ir* zBJ{S8Rnl{3!GnDN+1Hy?Ps7Lb)n@E}KbL#`>J^{4PwMmZ+t7lh|5bqR$-wnfdflY- zL*pWUHu|RW{UN|VH;^x^*Z=xCk@xEWJx{N1Q~I#d=N=IL6%PuXtMq+Jk7@eNdOhdt znk)9=g_)liyhqehDjmW3)Y4L^;Y3_tQ7Rn(O@JN+odR8Wk}=U`rBWYg7IZi0BxnpT zxkRqShG=+sB?ejm9S1!IItkiIkMFO-HmRU4XcRArWI@NzGG+pF;rU3v8u?Iu6!dA( zX;8fKWFl^VOtOUC>uR$3W}qzz=#3 z=oDxavTicrde7D1l^&2~WV zlfegi4rl>%38;G=2L{ z#Ae6^9S6-5y$Sk(7Vu%Nd8eY>kD&cQ3!n+m#4X^XYtTJ(9WRw8=o<7OXf%oTB^>lc z&|(+L1C4Z}ey70>pbek}P#3fax)F3bjdlff`rr?s2EP__PlrDEndTnQB7VC6G-wpR z$Ss0S-Uk1ek9?qQpyuPH(q2$!4C$Z+(APj?pM*W|GSt*A_#tTGQ?MK8IOvO@)1c?j zOHsRFFVJbw-E@67+Mg&stXh92+6%M|)Zml4ouE3IF z;gXJqTI^eV*_K;2(4i+JKj<5)VR8 z(CEXcFX$NPe$a8yr$Ak7M^bw>$^oqhO@J;09s2_MHz@5ZbAYZNfqc-&pF=+A1Zd+q zpkG4!f=0d!JAgWmLQl}>W9Wb9Lf(F~1E~2c$i+*Cw2z<*T6i3KfF}ML<-Z^83|bF5 z2D%V*s(|uAi=g{Jr$G;ZnyJRFGwt%{z9iU^N z3D7CfG0^EJU_VgvP52>b}e(K&L>LfySPL9-s-(G0^cJK~K;EXzc~44`@B8IShM&j)8W97C^J0lc2jP9S3zc zI_BKE-ptt%nRE8M}FGDE?Bwjsv9wYMM6uMHiv%LpTXX zR)y=YIpw77bz|o0_g-<)r46tk-aEtJ0RE05FI*cR90^Bug*Ju}-dVe}{p!Us)>sB>`{m2ie*Dfb^(`({)0R z)g9)f-+sOZv>V_-Y&}fwt9?&+gFEU%fp*n!-+NULi8d0?SqU*Amc`y zzrBoHxV<$Tqudm;o=4tE*4BlO|YyiWVOLw&%HBQpPx+@)$=LH>O(!&ku0f)`tN-q()$IZ z??+kRq4b&U&=!tW=>1^zvSO@v<6Oj3tRL z|E~Zm0{aU3zxs#9lA1js8zokT6Bx+2rlcq7wGeBY&C4-nqfIR_h92mMWA5{J!V4WzB$E|Xou8f<+Hx0i0+wf7{>Q6xZPzL!6 z`Fp3 zs(K8N*tHOA=tGd@%oYPG8qQ*mDXbVl;Xo!~TOaDin_G{3uNk1GE2a3R6ytY(YMZorOWUbC;UITtkMv}R)NMt=jD1a=3oc@)d4weQ3ne_*cp#hmJ`GJ(30Jo>79+lEr< zgVp7&4o_9en;WVwZwm6r{}Pbba6_r|KdH0M)NggT7^=|kyS3HiiL3*Vb?_$m1p07Q zS%pej{dLu4QJ;PdvffByntI*~v;qbjwNDg*d44xOZisWr z_c3+a4qSF1tsQBfs$SQ&aG}z6H&v}`E7)Z0dIa)z_j>)A$|wMP6j*Kb_Gt?T+I#9P z+MC+P;J#C;zf?M7HhC4}dd-_v#X$`9HM+OevIX}BNN#8=_hpJ{Dc}X*`v{*UHe``EL{lV)PUQ^uXO;=W0-{PqY%i4{6hmnt5n+~$)Bf#n!z44XS zQp*{onjYG~3_n166n}J& z^eA|?wFtN2YlmHKKO3Ox%hDm#SOBbVu{QB_X+Ss zc9u%dQd`Z8V}W&D&3~OOCQ^N=0r%p5dyLL;5H=s!6fnDfX#>^>>@cv$iRo?24BcPN z?j$=4IZHlKDj^i}LD(I@qQI~m;bSBI?*q0FSUtt4j@j;^gnGhtKREpNKmH$UF){Qa z&F;!D!yFJp?Jy0wuRv}J=h|Kv_qn|~{q0qc=LyU3++ml;XWMm$pU(x~qi@4UeX$RG z^FCQB-RGAl_pffV@^Ax$+jlQ`v*3NR`Z(1Vt{jtJtU64g9I|Z@vKsEh{c$Q62i5x( zU}M1MlK))mv#s1O46X^b!p6^tkulib6|%PyYf@Dw18nVQsGLqbb7}n4|J`z^UQeT( zsol6wP4x-*3eV^~&loQI3nqGHxMs(k8DkSygC>3+8`UX#Ci=_WrP71smose_j7urc zc5a33YTv?k)NcDw&f(9LN?5+}L1iBRb_m!zEF0@7X}1-01K8JY?|X}~H=~^S6!h*X zmFOE5GwtcSKNjj%b5aSOHJw?k$^9R)H{R>@b?*PbVm^%fKd=s99o72)M!(9r+Uue4 z!BA@$dki6Euv+wy{y@*^+CJ;WHY&gNEX45uRu60$uz5(QgZSv#UJJ1E7!k|`wh`EM zK5QefabV~Bus&c1fHnBAoxlzOLrCI-%An`;&j&DimRJm62Z0>}wpjDh9Oy8x`up)r zkub#QkQ=UBDN`V`1kf?0wL)TDBlhtuO%~PH`Q|EEhB#m&o#E}) z9sza)*cYh1s*SmUwcel2HqawG+}<36yv8r;^E}A2H(V%^+y;6&fhF4?V-r&XQI{+FqpDw%Zkw)+62CK-xj1@pBT^EzL5i?dtJx z@&%;LCtJmqA z&TsLZuk)Q_w9&@|$lPYnNr%q&!;inB&qpy=AS?^)QD7J1+}tb}y-P6(4B;7@u!SR3 zUwW_NFtEzCsMhzRGwXW@{O3I8$)z#n1z;_}sJiwb9bN%W?|@+WQ$8q+Q`&L(TfO!M z6B;vsD5wP zu3zeCfrG=|i?h!naLbjCgI{%-T70u!TfGyUYK*;KYs>#rN$PX-G09)jYgN}w>-All zu44Y5k=L{xf(35V_PtB#gGwJ$`lQlll>SudZ)5f(H5t1J$`lCjvt>(LeruP@riT%pdCNd9OhqzE{--YY6jn`bPAuxKt{T3 zTGHIpy=3u)rghWOCD}!bKfJ`O-?S7z{T-s;gZ6fJ2g@aBsZE%rL(z9u%pB!$*%q;{ER!@+-)|*mR@Q$tXR6ptXQ?QNqp6C){wkfT~bEl?RT8+oXvA0rs_{fL|9NjA$EI0YO^!{ov>K1C&y8gOB*9Guq#UqN>5;G3E_e%Wr z0sgBLcLMk-;33q&3A;Em=1TsL{V+iZPbfa5_|2dsKdN%T!bcbW6Mx}!m#^)(_c2_} z!AoJszAd;N?{8DQsJIC-r7?eKZV&oV7%RNCjOz^UBHdKYKL@H^O`-@@M< z+&#AOu!RzFd=G!5zZ;PA6UEyD_`fI~3*i3_oXT|^1RME}=be`S7C~$~ zew6voGMfYX4=SEe9G86Du6SR7pWf4_a$nN+viuV`;ri-$!|(e*($|1j^Ya@pK_dH4 zZf)iAZ2MjVe!`~|H)8;BY{DP6?+Gqlnv40rY&uE&V*x#XsB(4(@F~T|1ND7D@d?Ex zpc?aQi(k;nCEEUVO!0#O{Ev!HDsK4Y9{ki0H^oWMrvm&nYKQ%bTRWVrcp-qFrTC$& z=!4?;SfKcn;#N*GaI%~8ahLh{87T*lC|$ZCG_7;w^mTH8IY{9jYNc(2O{KYPR3Hx-Y3R&ag>2K;^m z9FkMKU-0>AxNj?e;Q_(<84mcL22S-l5~$aY6+arlpI5vXz<&X}TD|@aIO$`@MHI=$ zONvjP=qe)QPl_A6uF}-`Sa^`0M>S4be{dL|Z|r)=3R?}F$}O+YG+_htpI%;HS^i<* z)$|{o1^+Xa6EVkLcCCmqttN+lmo^8hso;9yVc^D`Vq!mX%lYZ#0P~+&UT4|F?*l&# znvN}Z8RB=ParO_uY5$&RAP)S>@}DC79h?i#uoQQ83O-lydFc2gf2v3Dl;V!!G37r` z@x_emg^#RM{^_$_My>pttem?A$0Z+wiW`mp`xL(o_^F7)=NxbuvHbTizcTsAe^EJ; z&B9ObZP4-G6n9mBbQ3=QPI05-_+KhczkwrrHU{PozgB)n`_WeAf0=Q;@R2YU;ABs8 zq06ZKZN<63sa{7P7u?2^izlPdT8$6RBIh~Aq0hCV&mEfK=Zd@Y1h>yrf2Vjf;GeZ{B(kS-uJBvCovCw zIabfFC>}dUaC=|qDa8|a3C{1|7-N2{cx1KU7XhQ==Zc$)UB0%zqxqfUQyK?ozDoza zq)Pf5)!*9lG%TRW&Qax$3A<@vTrYg&a>7Hk#;$E_J6@@BT-B3*cY%D@DqcvtEQQ}w z#aV)JhARH$teg!l<5tg411J3(1NQ%-@{i9G{>3Wo>xvg5g7a^Tk@f?|mB~l`X%_t7 zRZcV^a(3E0P>kc}y@G>{kCPRj-X!=(6o0?s5w-J~ieCXdg8sEX(7%>jIVXvnHOjvh zIN4$PalvuPN00Jn?-2Z1#p(Bhwv7~G@)_ly>J|Q7n)nxrM?N4p{}vBv^jkuzZ(*+B zUCRF>E9YjxZ9M)@R2sqilF5rh_jMtllwj-*^2mMZw z{Uq%2^?L<2=b__QYnLxue)Z?~DgP6SXB9tN@n;oJ=sfTW#s86Uz3>tG?holRcB9K^ zT+?2ig?}CbAnU(F`1w6k^-K#1tLRj=4J6>?> z59cUehzq_z`4?M$mBYWaN16+q#;Mm-PwW4i6`xcbEx|{x%E`XRqq$C2i3m6mte2!;2L^qPTmK@V{5_Un)MO{$us|UyLi0j~suh*x%eEa;)9vD_+z%aE<0U z4>+~UWMCc9to+XXBFFZNzqaG4>UplpS!&DGab&&Xs}+xGeeJk&3vi16(}8*K7R!Hz zl*`}4fvla3t56>qSN??d-_@G-WyPn}4!0`)q~Zl_cf0<5TJfUmGADnx0B1k3_>F?w zIPlMkM|B*u{_}6ZseesroU#7)2jzFxi5&ioJml9R;M2Ghy+m;S&IIsN8OKTBIA8f) z9WQKuT%!1Ry~{bQomT=UeVjml-=zFSZAUwA>9uk`Dst>Ra697xWpH`7@+Y)^eM?#P zD(?1*oL!0^P<(QS;I_X!qqq|o2Y;b>;e6r0Naei5xL){3?df9ALZk4n(zN#|p4Iz} zdBqzoe@^&q+`a-h*{va9w|3=^>bPm!ca!3g6GV>fFCSw$XPIo^zU!#+7cLThtLI&c z8|^O*s^_;67*XXJ$HU4$o_0ActQ=osdo@{yR8Ung=FYFdw# zvq|uW6yK(}(f-w}IQ=HNnmr!^PVF8EwEN>$&UTUiRUO~IZ}ATbZtvgzlgcRu;=r$z zKek)=r&Z4H6(8FwIRDnx;P)c$5qnO5O7H|QI_US)Wap`r%hz-HzcEYU0H=jQ<@d)F zHVc(MniT%qHQ_47Cyy6=jpAz+&)zHedd1_4Cj#+jtKw6NTfg0{_{4mX^PI|gSn=pX zf}f@M0mUaZF4;EvE^um>`GI!%2P;S8{G}>~zE?}*OEECM{89O{swdo7j_%?7qUMZ= z$MMcgJfG~9EhC2MRTkOAYB*Cc|4IPh5-NZpdym$qVilKlg5 z-t|CI_&Pa&EslKG{VBN^OlIRf_)L6U>q^(X!}tV0ZHW-4tL#9sTlM3_bOs;KA0G7> zcn5|!?J6QzI@=A~VIL2<9LV%8jsugc9(Z>>Q^FZtLrm;5^QTvPxiJgV(1r@!o+Bd$D189U)bF?}KxlcdZ za5y;{$DTRl8MG~0JT)>nIEpO3t2n*>Rlz#gzoQvSL$&l!ihJIw^{v;fjIUhV7LS{F z+f8d*uUoSMQt#dLb6V5u8z^aWoW z&@Mr0vPwDBJC{~P)4cH@7oEnoEj|N~2W1hVVAp~EuI@PAqC;S!eUr)sUaFSC4ikNG z$Pk&$`Q%6wHvcfmE^LHSW~OS#<0ucEm-oVgdKHNyLj(OoTPh$i2^68-Y~mzSnyi8e z`{E42zXMnbfwcmPQ~fFsmM*r+rH8E}Xy}%@ivr~a#^xMeyK~ENn2Os#X}cu7Ng2m> ziPC-?&L|Qigb!{>^$*X~!WKHBTmF?Ro*U`%HG3x8L|fv(6S&=~$jNi}k#a@B0c?yH z=kV)oZd8sN!bmotP{^fjNsq?4L19-xV0Y>W-e}Q0lxxCHRZY1xwg=Nl#i_(btpvAB zrYf|<_K7gRSKJV`K$9!4`*7efC^ny|%*=X~2L&jf%xR33-hfREu^l6v&5jV(oZhG@ zW2>!0_fUSILOn#c?k#b2RN7XjoU-Uco{H4B<0Iu*0H4H8f?6MpNBPW9e|LOHO-yF# zr-6og4fbTx9v4rilKG@$qTK|OGQe4L4)%8sV_P}Trq-QgJb;clPq%Uu@$6TrBHWLQ zo#EJ+kK}x#E8CUbQWVn(hc7T#HQ>SJ0UJ@#^9hdb)NpX3vhm6ak|G)!s87g9;u%)L zB=&)WMFeGyQrNGC933+ZX=M05d6givOIj1X*Q?Q+dj*V5z1|AJd`1005bG4Yvz0&; z<9gF3H^gIO&rIEO1L<^@nsq2Sl;Mk+JYEBo^^22W#MpAZeX&BjQFbJsn<VDb&ijOVRibH19Q!#5A|o{E zOH*OkuX|=4*>yBTlIPHH<<-?2rLCcY;|423jW;-=rlk><4DG8Hr4Oi^S);N|X#Y;H zG#bXK=f-L8I`vcQgXKz*ENl*Cx>-O)g)r4Zw2*O^I@hea+6f_7zOo^ubMd}vws%p9 zwmXt%anvYJayas1I)~p7pkGiZ9;l3zWec&tmGenKn9-nv&eoZzk!2o}$0RgR*WN*i zmY8G2QE<|8;7c#{Y$`42g<*E!UQAHz=uNfb$pUR3=H;Wd=o*dl)`hTZE(33-{f31@ z92(n?ihAfk-PzHyev6g}7pYG(;)+?7-AUK)9$v4K5v}auG_z${Uc?{3CVUd{<7?JY z0P7#}Ee5zh&^m^;%B8uJ^{?J;-#A}xMYNZwO8d*oqOiJNm`4kv7rP|5`(U1hVjd$3 zXZv|d$5ojbpkQ?At2AFMdkE%g!BQ}-t(;Jc-$+OvoY@C@c#&Lgit?Bu3tQ}!>J>ox z(&oN`R9dbaOUpxvZ@?oPQ058?*nUkN7Tf%ZQ0`#f8rEj?cJwpx)Bt4h^fpaB7r#%5 zXR);Jn$dZ&KX8?~u8j}0p{$fi)3Nkc$kK{g4mO-ud+8YE?&!6vZ?qHjp_G@+iw}%7 z_XLx828EbH+t%da$ z{*34>8rbC%l?%72xcNhO!hEYzw2fDw=RWYx8Aj0AD$fQg>=uu2yl#cwJt%vw4R>@q zYlbMA``Zf8=CF3XUk;;ia66cg{FM5FR#w%u3dSVS2m}t+pV)xEjgsxep{|} zS%hWrg&2W&MpXA+y41m`Sui2ac<5rWuh6Hw8g4S7O>{&-mw*y+b3- zU9_Wk6P&!68?TvW;RZ?!^%H_E?z5(u_$WM?X4C*Og(B#4ivCWt;v$YT3^hs0pl4ak zN}Go>yvS@$JQ0RWmpv300=+Z!b`~GT!z94I#_gem-{;uXPt2sdkjtTzHdqc>X{3l)g zM>{TF#c$?qe*2vOXF|9dmANiJ_0rIDB6^l=^V{zTv`+}fm@0e%E~#uQ$G*3CGcYo> z&41`o7gzLs0w%_Ohd{1GhCL_Rg+KZRfX#1z_kY)8!j%wGF4yu|nn5~!Q@~yyeaz(? zM>T&|^9S`;*nAu(R7IQLe#c<*SA`=Xq+EWm{=1P*`Ijr7{Vu{m&2PV>K>5zZUobzp z7unU8Z{OFNd>kN-@%Ib0|AYSbc_jGr+ut3Kvi=zt!Jfe*-7}{y+V)%SqEO3x^}5{6Coghe+|~x4$=z{9dv+<(zU7)c+p=;}I(R zAaU65Y#e=)t~`6om3M9R_$3lf!JmeU^6$>3-(mijke5ts^V{Epy{7q#WLzBNe{|S# zZ9BdKj96^`Bl;bVBPHUdcYP`ko8Qvck?hZJzvFRK^JleuE5+usG=y}2e)~S_<~fov zW-}_a`7B%qHo~m__PwP2nm=j{pcx#SQR&HAel&pF{1jjOhiD}_6Mn`l`9oAO9P4Zb zzVh-}cmYnx|Lie+>Iy#HSR)*LmQfjk{zu8S?^+o|Cu=3+lq2Z-K(5E1wV#cj7({|BfnfbakS literal 0 HcmV?d00001 diff --git a/test/programs/dyn-vec.flan b/test/programs/dyn-vec.flan new file mode 100644 index 0000000..6d74b5a --- /dev/null +++ b/test/programs/dyn-vec.flan @@ -0,0 +1,24 @@ +;;;; A container holding four different types at once. +;;;; +;;;; (vec-new dyn) is not a (Vec dyn) — it is the dyn runtime's own vector, and +;;;; its type is dyn like everything else the runtime hands back. That is what +;;;; lets push, at and len on it be the dyn operations rather than a +;;;; type-erased Vec over eight-byte elements, and it is why no allocator is +;;;; named: the storage is the collector's to walk. + +(defn main [] () + (let [xs (vec-new dyn)] + (push xs 1) + (push xs 2.5) + (push xs "three") + (push xs true) + (print (len xs)) + (print "\n") + (print xs) + (print "\n") + ;; Read back out one at a time, to show that at answers a dyn and that the + ;; four of them are still four different things. + (dotimes [i (len xs)] + (print (at xs i)) + (print " ")) + (print "\n")))