From 318d0cc07277fd156cd1add0f06fc94b4d0676cc Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Fri, 22 Dec 2023 17:03:23 +0800 Subject: [PATCH 001/105] Implement `sprintf "%g"` in Crystal (#14123) --- spec/std/float_printer/ryu_printf_spec.cr | 947 ++++++++++ .../float_printer/ryu_printf_test_cases.cr | 1670 +++++++++++++++++ spec/std/sprintf_spec.cr | 211 ++- src/float/printer/ryu_printf.cr | 77 + src/float/printer/ryu_printf_table.cr | 527 ++++++ src/string/formatter.cr | 33 +- 6 files changed, 3458 insertions(+), 7 deletions(-) diff --git a/spec/std/float_printer/ryu_printf_spec.cr b/spec/std/float_printer/ryu_printf_spec.cr index d4ba77bffd94..4610485f2270 100644 --- a/spec/std/float_printer/ryu_printf_spec.cr +++ b/spec/std/float_printer/ryu_printf_spec.cr @@ -4,6 +4,7 @@ # This file contains test cases derived from: # # * https://github.com/ulfjack/ryu +# * https://github.com/microsoft/STL/tree/main/tests/std/tests/P0067R5_charconv # # The following is their license: # @@ -25,6 +26,7 @@ # KIND, either express or implied. require "spec" +require "../../support/number" require "float/printer/ryu_printf" require "big" require "./ryu_printf_test_cases" @@ -118,6 +120,10 @@ private macro expect_exp(float, precision, string) Float::Printer::RyuPrintf.d2exp({{ float }}, {{ precision }}).should eq({{ string }}) end +private macro expect_gen(float, precision, string, *, file = __FILE__, line = __LINE__) + Float::Printer::RyuPrintf.d2gen({{ float }}, {{ precision }}).should eq({{ string }}), file: {{ file }}, line: {{ line }} +end + describe Float::Printer::RyuPrintf do describe ".d2fixed" do it "Basic" do @@ -491,4 +497,945 @@ describe Float::Printer::RyuPrintf do expect_exp(1e+83, 1, "1.0e+83") end end + + describe ".d2gen" do + it "Basic" do + expect_gen(0.0, 4, "0") + expect_gen(1.729, 4, "1.729") + end + + it "corner cases" do + expect_gen(Float64::MIN_SUBNORMAL, 1000, + "4.940656458412465441765687928682213723650598026143247644255856825006755072702087518652998363616359923797965646954457177309266567103559397963987747960107818781263007131903114045278458171678489821036887186360569987307230500063874091535649843873124733972731696151400317153853980741262385655911710266585566867681870395603106249319452715914924553293054565444011274801297099995419319894090804165633245247571478690147267801593552386115501348035264934720193790268107107491703332226844753335720832431936092382893458368060106011506169809753078342277318329247904982524730776375927247874656084778203734469699533647017972677717585125660551199131504891101451037862738167250955837389733598993664809941164205702637090279242767544565229087538682506419718265533447265625e-324") + expect_gen(Float64::MIN_POSITIVE.prev_float, 1000, + "2.2250738585072008890245868760858598876504231122409594654935248025624400092282356951787758888037591552642309780950434312085877387158357291821993020294379224223559819827501242041788969571311791082261043971979604000454897391938079198936081525613113376149842043271751033627391549782731594143828136275113838604094249464942286316695429105080201815926642134996606517803095075913058719846423906068637102005108723282784678843631944515866135041223479014792369585208321597621066375401613736583044193603714778355306682834535634005074073040135602968046375918583163124224521599262546494300836851861719422417646455137135420132217031370496583210154654068035397417906022589503023501937519773030945763173210852507299305089761582519159720757232455434770912461317493580281734466552734375e-308") + expect_gen(Float64::MIN_POSITIVE, 1000, + "2.225073858507201383090232717332404064219215980462331830553327416887204434813918195854283159012511020564067339731035811005152434161553460108856012385377718821130777993532002330479610147442583636071921565046942503734208375250806650616658158948720491179968591639648500635908770118304874799780887753749949451580451605050915399856582470818645113537935804992115981085766051992433352114352390148795699609591288891602992641511063466313393663477586513029371762047325631781485664350872122828637642044846811407613911477062801689853244110024161447421618567166150540154285084716752901903161322778896729707373123334086988983175067838846926092773977972858659654941091369095406136467568702398678315290680984617210924625396728515625e-308") + expect_gen(Float64::MAX, 1000, + "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368") + + expect_gen(Float64::MIN_SUBNORMAL, 6, "4.94066e-324") + expect_gen(Float64::MIN_POSITIVE.prev_float, 6, "2.22507e-308") + expect_gen(Float64::MIN_POSITIVE, 6, "2.22507e-308") + expect_gen(Float64::MAX, 6, "1.79769e+308") + end + + it "maximum-length output" do + expect_gen(hexfloat("0x1.fffffffffffffp-1022"), 1000, + "4.4501477170144022721148195934182639518696390927032912960468522194496444440421538910330590478162701758282983178260792422137401728773891892910553144148156412434867599762821265346585071045737627442980259622449029037796981144446145705102663115100318287949527959668236039986479250965780342141637013812613333119898765515451440315261253813266652951306000184917766328660755595837392240989947807556594098101021612198814605258742579179000071675999344145086087205681577915435923018910334964869420614052182892431445797605163650903606514140377217442262561590244668525767372446430075513332450079650686719491377688478005309963967709758965844137894433796621993967316936280457084866613206797017728916080020698679408551343728867675409720757232455434770912461317493580281734466552734375e-308") + expect_gen(hexfloat("0x1.fffffffffffffp-14"), 1000, + "0.000122070312499999986447472843931194574906839989125728607177734375") + end + + it "varying precision" do + expect_gen(hexfloat("0x1.b04p0"), 0, "2") + expect_gen(hexfloat("0x1.b04p0"), 1, "2") # fixed notation trims decimal point + expect_gen(hexfloat("0x1.b04p0"), 2, "1.7") + expect_gen(hexfloat("0x1.b04p0"), 3, "1.69") + expect_gen(hexfloat("0x1.b04p0"), 4, "1.688") + expect_gen(hexfloat("0x1.b04p0"), 5, "1.6885") + expect_gen(hexfloat("0x1.b04p0"), 6, "1.68848") + expect_gen(hexfloat("0x1.b04p0"), 7, "1.688477") + expect_gen(hexfloat("0x1.b04p0"), 8, "1.6884766") + expect_gen(hexfloat("0x1.b04p0"), 9, "1.68847656") + expect_gen(hexfloat("0x1.b04p0"), 10, "1.688476562") # round to even + expect_gen(hexfloat("0x1.b04p0"), 11, "1.6884765625") # exact + expect_gen(hexfloat("0x1.b04p0"), 12, "1.6884765625") # trim trailing zeros + expect_gen(hexfloat("0x1.b04p0"), 13, "1.6884765625") + + expect_gen(hexfloat("0x1.8p-15"), 0, "5e-5") + expect_gen(hexfloat("0x1.8p-15"), 1, "5e-5") # scientific notation trims decimal point + expect_gen(hexfloat("0x1.8p-15"), 2, "4.6e-5") + expect_gen(hexfloat("0x1.8p-15"), 3, "4.58e-5") + expect_gen(hexfloat("0x1.8p-15"), 4, "4.578e-5") + expect_gen(hexfloat("0x1.8p-15"), 5, "4.5776e-5") + expect_gen(hexfloat("0x1.8p-15"), 6, "4.57764e-5") + expect_gen(hexfloat("0x1.8p-15"), 7, "4.577637e-5") + expect_gen(hexfloat("0x1.8p-15"), 8, "4.5776367e-5") + expect_gen(hexfloat("0x1.8p-15"), 9, "4.57763672e-5") + expect_gen(hexfloat("0x1.8p-15"), 10, "4.577636719e-5") + expect_gen(hexfloat("0x1.8p-15"), 11, "4.5776367188e-5") # round to even + expect_gen(hexfloat("0x1.8p-15"), 12, "4.57763671875e-5") # exact + expect_gen(hexfloat("0x1.8p-15"), 13, "4.57763671875e-5") # trim trailing zeros + expect_gen(hexfloat("0x1.8p-15"), 14, "4.57763671875e-5") + end + + it "trim trailing zeros" do + expect_gen(hexfloat("0x1.80015p0"), 1, "2") # fixed notation trims decimal point + expect_gen(hexfloat("0x1.80015p0"), 2, "1.5") + expect_gen(hexfloat("0x1.80015p0"), 3, "1.5") # general trims trailing zeros + expect_gen(hexfloat("0x1.80015p0"), 4, "1.5") + expect_gen(hexfloat("0x1.80015p0"), 5, "1.5") + expect_gen(hexfloat("0x1.80015p0"), 6, "1.50002") + expect_gen(hexfloat("0x1.80015p0"), 7, "1.50002") + expect_gen(hexfloat("0x1.80015p0"), 8, "1.50002") + expect_gen(hexfloat("0x1.80015p0"), 9, "1.50002003") + expect_gen(hexfloat("0x1.80015p0"), 10, "1.500020027") + expect_gen(hexfloat("0x1.80015p0"), 11, "1.5000200272") + expect_gen(hexfloat("0x1.80015p0"), 12, "1.50002002716") + expect_gen(hexfloat("0x1.80015p0"), 13, "1.500020027161") + expect_gen(hexfloat("0x1.80015p0"), 14, "1.5000200271606") + expect_gen(hexfloat("0x1.80015p0"), 15, "1.50002002716064") + expect_gen(hexfloat("0x1.80015p0"), 16, "1.500020027160645") + expect_gen(hexfloat("0x1.80015p0"), 17, "1.5000200271606445") + expect_gen(hexfloat("0x1.80015p0"), 18, "1.50002002716064453") + expect_gen(hexfloat("0x1.80015p0"), 19, "1.500020027160644531") + expect_gen(hexfloat("0x1.80015p0"), 20, "1.5000200271606445312") # round to even + expect_gen(hexfloat("0x1.80015p0"), 21, "1.50002002716064453125") # exact + end + + it "trim trailing zeros and decimal point" do + expect_gen(hexfloat("0x1.00015p0"), 1, "1") # fixed notation trims decimal point + expect_gen(hexfloat("0x1.00015p0"), 2, "1") # general trims decimal point and trailing zeros + expect_gen(hexfloat("0x1.00015p0"), 3, "1") + expect_gen(hexfloat("0x1.00015p0"), 4, "1") + expect_gen(hexfloat("0x1.00015p0"), 5, "1") + expect_gen(hexfloat("0x1.00015p0"), 6, "1.00002") + expect_gen(hexfloat("0x1.00015p0"), 7, "1.00002") + expect_gen(hexfloat("0x1.00015p0"), 8, "1.00002") + expect_gen(hexfloat("0x1.00015p0"), 9, "1.00002003") + expect_gen(hexfloat("0x1.00015p0"), 10, "1.000020027") + expect_gen(hexfloat("0x1.00015p0"), 11, "1.0000200272") + expect_gen(hexfloat("0x1.00015p0"), 12, "1.00002002716") + expect_gen(hexfloat("0x1.00015p0"), 13, "1.000020027161") + expect_gen(hexfloat("0x1.00015p0"), 14, "1.0000200271606") + expect_gen(hexfloat("0x1.00015p0"), 15, "1.00002002716064") + expect_gen(hexfloat("0x1.00015p0"), 16, "1.000020027160645") + expect_gen(hexfloat("0x1.00015p0"), 17, "1.0000200271606445") + expect_gen(hexfloat("0x1.00015p0"), 18, "1.00002002716064453") + expect_gen(hexfloat("0x1.00015p0"), 19, "1.000020027160644531") + expect_gen(hexfloat("0x1.00015p0"), 20, "1.0000200271606445312") # round to even + expect_gen(hexfloat("0x1.00015p0"), 21, "1.00002002716064453125") # exact + end + + it "trim trailing zeros, scientific notation" do + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 1, "1e-6") # scientific notation trims decimal point + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 2, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 3, "1.3e-6") # general trims trailing zeros + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 4, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 5, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 6, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 7, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 8, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 9, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 10, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 11, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 12, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 13, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 14, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 15, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 16, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 17, "1.3e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 18, "1.30000000000000005e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 19, "1.300000000000000047e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 20, "1.3000000000000000471e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 21, "1.30000000000000004705e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 22, "1.300000000000000047052e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 23, "1.3000000000000000470517e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 24, "1.30000000000000004705166e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 25, "1.300000000000000047051664e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 26, "1.3000000000000000470516638e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 27, "1.30000000000000004705166378e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 28, "1.30000000000000004705166378e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 29, "1.3000000000000000470516637804e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 30, "1.30000000000000004705166378044e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 31, "1.30000000000000004705166378044e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 32, "1.3000000000000000470516637804397e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 33, "1.30000000000000004705166378043968e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 34, "1.300000000000000047051663780439679e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 35, "1.3000000000000000470516637804396787e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 36, "1.30000000000000004705166378043967867e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 37, "1.300000000000000047051663780439678675e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 38, "1.3000000000000000470516637804396786748e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 39, "1.30000000000000004705166378043967867484e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 40, "1.300000000000000047051663780439678674838e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 41, "1.3000000000000000470516637804396786748384e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 42, "1.30000000000000004705166378043967867483843e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 43, "1.300000000000000047051663780439678674838433e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 44, "1.3000000000000000470516637804396786748384329e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 45, "1.30000000000000004705166378043967867483843293e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 46, "1.300000000000000047051663780439678674838432926e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 47, "1.3000000000000000470516637804396786748384329258e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 48, "1.30000000000000004705166378043967867483843292575e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 49, "1.300000000000000047051663780439678674838432925753e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 50, "1.3000000000000000470516637804396786748384329257533e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 51, "1.3000000000000000470516637804396786748384329257533e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 52, "1.300000000000000047051663780439678674838432925753295e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 53, "1.3000000000000000470516637804396786748384329257532954e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 54, "1.30000000000000004705166378043967867483843292575329542e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 55, "1.300000000000000047051663780439678674838432925753295422e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 56, "1.3000000000000000470516637804396786748384329257532954216e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 57, "1.3000000000000000470516637804396786748384329257532954216e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 58, "1.3000000000000000470516637804396786748384329257532954216e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 59, "1.3000000000000000470516637804396786748384329257532954216003e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 60, "1.30000000000000004705166378043967867483843292575329542160034e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 61, "1.300000000000000047051663780439678674838432925753295421600342e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 62, "1.3000000000000000470516637804396786748384329257532954216003418e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 63, "1.3000000000000000470516637804396786748384329257532954216003418e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 64, "1.300000000000000047051663780439678674838432925753295421600341797e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 65, "1.3000000000000000470516637804396786748384329257532954216003417969e-6") + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 66, "1.30000000000000004705166378043967867483843292575329542160034179688e-6") # round to even + expect_gen(hexfloat("0x1.5cf751db94e6bp-20"), 67, "1.300000000000000047051663780439678674838432925753295421600341796875e-6") # exact + end + + it "trim trailing zeros and decimal point, scientific notation" do + expect_gen(hexfloat("0x1.92a737110e454p-19"), 1, "3e-6") # scientific notation trims decimal point + expect_gen(hexfloat("0x1.92a737110e454p-19"), 2, "3e-6") # general trims decimal point and trailing zeros + expect_gen(hexfloat("0x1.92a737110e454p-19"), 3, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 4, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 5, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 6, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 7, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 8, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 9, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 10, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 11, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 12, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 13, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 14, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 15, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 16, "3e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 17, "3.0000000000000001e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 18, "3.00000000000000008e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 19, "3.000000000000000076e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 20, "3.000000000000000076e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 21, "3.000000000000000076e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 22, "3.000000000000000076003e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 23, "3.0000000000000000760026e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 24, "3.00000000000000007600257e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 25, "3.000000000000000076002572e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 26, "3.0000000000000000760025723e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 27, "3.00000000000000007600257229e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 28, "3.000000000000000076002572291e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 29, "3.0000000000000000760025722912e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 30, "3.00000000000000007600257229123e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 31, "3.000000000000000076002572291234e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 32, "3.0000000000000000760025722912339e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 33, "3.00000000000000007600257229123386e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 34, "3.000000000000000076002572291233861e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 35, "3.0000000000000000760025722912338608e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 36, "3.00000000000000007600257229123386082e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 37, "3.000000000000000076002572291233860824e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 38, "3.0000000000000000760025722912338608239e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 39, "3.00000000000000007600257229123386082392e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 40, "3.000000000000000076002572291233860823922e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 41, "3.0000000000000000760025722912338608239224e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 42, "3.00000000000000007600257229123386082392244e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 43, "3.000000000000000076002572291233860823922441e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 44, "3.0000000000000000760025722912338608239224413e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 45, "3.00000000000000007600257229123386082392244134e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 46, "3.000000000000000076002572291233860823922441341e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 47, "3.000000000000000076002572291233860823922441341e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 48, "3.00000000000000007600257229123386082392244134098e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 49, "3.000000000000000076002572291233860823922441340983e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 50, "3.0000000000000000760025722912338608239224413409829e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 51, "3.00000000000000007600257229123386082392244134098291e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 52, "3.000000000000000076002572291233860823922441340982914e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 53, "3.000000000000000076002572291233860823922441340982914e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 54, "3.00000000000000007600257229123386082392244134098291397e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 55, "3.000000000000000076002572291233860823922441340982913971e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 56, "3.0000000000000000760025722912338608239224413409829139709e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 57, "3.00000000000000007600257229123386082392244134098291397095e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 58, "3.000000000000000076002572291233860823922441340982913970947e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 59, "3.0000000000000000760025722912338608239224413409829139709473e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 60, "3.00000000000000007600257229123386082392244134098291397094727e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 61, "3.000000000000000076002572291233860823922441340982913970947266e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 62, "3.0000000000000000760025722912338608239224413409829139709472656e-6") + expect_gen(hexfloat("0x1.92a737110e454p-19"), 63, "3.00000000000000007600257229123386082392244134098291397094726562e-6") # round to even + expect_gen(hexfloat("0x1.92a737110e454p-19"), 64, "3.000000000000000076002572291233860823922441340982913970947265625e-6") # exact + end + + it "large precision with fixed notation and scientific notation" do + expect_gen(hexfloat("0x1.ba9fbe76c8b44p+0"), 5000, "1.72900000000000009237055564881302416324615478515625") + expect_gen(hexfloat("0x1.d01ff9abb93d1p-20"), 5000, "1.729000000000000090107283613749533657255597063340246677398681640625e-6") + end + + it "transitions between fixed notation and scientific notation" do + expect_gen(5555555.0, 1, "6e+6") + expect_gen(555555.0, 1, "6e+5") + expect_gen(55555.0, 1, "6e+4") + expect_gen(5555.0, 1, "6e+3") + expect_gen(555.0, 1, "6e+2") + expect_gen(55.0, 1, "6e+1") # round to even + expect_gen(5.0, 1, "5") + expect_gen(hexfloat("0x1p-3"), 1, "0.1") # 0.125 + expect_gen(hexfloat("0x1p-6"), 1, "0.02") # 0.015625 + expect_gen(hexfloat("0x1p-9"), 1, "0.002") # 0.001953125 + expect_gen(hexfloat("0x1p-13"), 1, "0.0001") # 0.0001220703125 + expect_gen(hexfloat("0x1p-16"), 1, "2e-5") # 1.52587890625e-5 + expect_gen(hexfloat("0x1p-19"), 1, "2e-6") # 1.9073486328125e-6 + + expect_gen(5555555.0, 2, "5.6e+6") + expect_gen(555555.0, 2, "5.6e+5") + expect_gen(55555.0, 2, "5.6e+4") + expect_gen(5555.0, 2, "5.6e+3") + expect_gen(555.0, 2, "5.6e+2") # round to even + expect_gen(55.0, 2, "55") + expect_gen(5.0, 2, "5") + expect_gen(hexfloat("0x1p-3"), 2, "0.12") # round to even + expect_gen(hexfloat("0x1p-6"), 2, "0.016") + expect_gen(hexfloat("0x1p-9"), 2, "0.002") + expect_gen(hexfloat("0x1p-13"), 2, "0.00012") + expect_gen(hexfloat("0x1p-16"), 2, "1.5e-5") + expect_gen(hexfloat("0x1p-19"), 2, "1.9e-6") + + expect_gen(5555555.0, 3, "5.56e+6") + expect_gen(555555.0, 3, "5.56e+5") + expect_gen(55555.0, 3, "5.56e+4") + expect_gen(5555.0, 3, "5.56e+3") # round to even + expect_gen(555.0, 3, "555") + expect_gen(55.0, 3, "55") + expect_gen(5.0, 3, "5") + expect_gen(hexfloat("0x1p-3"), 3, "0.125") + expect_gen(hexfloat("0x1p-6"), 3, "0.0156") + expect_gen(hexfloat("0x1p-9"), 3, "0.00195") + expect_gen(hexfloat("0x1p-13"), 3, "0.000122") + expect_gen(hexfloat("0x1p-16"), 3, "1.53e-5") + expect_gen(hexfloat("0x1p-19"), 3, "1.91e-6") + + expect_gen(5555555.0, 4, "5.556e+6") + expect_gen(555555.0, 4, "5.556e+5") + expect_gen(55555.0, 4, "5.556e+4") # round to even + expect_gen(5555.0, 4, "5555") + expect_gen(555.0, 4, "555") + expect_gen(55.0, 4, "55") + expect_gen(5.0, 4, "5") + expect_gen(hexfloat("0x1p-3"), 4, "0.125") + expect_gen(hexfloat("0x1p-6"), 4, "0.01562") # round to even + expect_gen(hexfloat("0x1p-9"), 4, "0.001953") + expect_gen(hexfloat("0x1p-13"), 4, "0.0001221") + expect_gen(hexfloat("0x1p-16"), 4, "1.526e-5") + expect_gen(hexfloat("0x1p-19"), 4, "1.907e-6") + + expect_gen(5555555.0, 5, "5.5556e+6") + expect_gen(555555.0, 5, "5.5556e+5") # round to even + expect_gen(55555.0, 5, "55555") + expect_gen(5555.0, 5, "5555") + expect_gen(555.0, 5, "555") + expect_gen(55.0, 5, "55") + expect_gen(5.0, 5, "5") + expect_gen(hexfloat("0x1p-3"), 5, "0.125") + expect_gen(hexfloat("0x1p-6"), 5, "0.015625") + expect_gen(hexfloat("0x1p-9"), 5, "0.0019531") + expect_gen(hexfloat("0x1p-13"), 5, "0.00012207") + expect_gen(hexfloat("0x1p-16"), 5, "1.5259e-5") + expect_gen(hexfloat("0x1p-19"), 5, "1.9073e-6") + end + + it "tricky corner cases" do + expect_gen(999.999, 1, "1e+3") # "%.0e" is "1e+3"; X == 3 + expect_gen(999.999, 2, "1e+3") # "%.1e" is "1.0e+3"; X == 3 + expect_gen(999.999, 3, "1e+3") # "%.2e" is "1.00e+3"; X == 3 + expect_gen(999.999, 4, "1000") # "%.3e" is "1.000e+3"; X == 3 + expect_gen(999.999, 5, "1000") # "%.4e" is "1.0000e+3"; X == 3 + expect_gen(999.999, 6, "999.999") # "%.5e" is "9.99999e+2"; X == 2 + + expect_gen(999.99, 1, "1e+3") + expect_gen(999.99, 2, "1e+3") + expect_gen(999.99, 3, "1e+3") + expect_gen(999.99, 4, "1000") + expect_gen(999.99, 5, "999.99") + expect_gen(999.99, 6, "999.99") + + # C11's Standardese is slightly vague about how to perform the trial formatting in scientific notation, + # but the intention is to use precision P - 1, which is what's used when scientific notation is actually chosen. + # This example verifies this behavior. Here, P == 3 performs trial formatting with "%.2e", triggering rounding. + # That increases X to 3, forcing scientific notation to be chosen. + # If P == 3 performed trial formatting with "%.3e", rounding wouldn't happen, + # X would be 2, and fixed notation would be chosen. + expect_gen(999.9, 1, "1e+3") # "%.0e" is "1e+3"; X == 3 + expect_gen(999.9, 2, "1e+3") # "%.1e" is "1.0e+3"; X == 3 + expect_gen(999.9, 3, "1e+3") # "%.2e" is "1.00e+3"; X == 3; SPECIAL CORNER CASE + expect_gen(999.9, 4, "999.9") # "%.3e" is "9.999e+2"; X == 2 + expect_gen(999.9, 5, "999.9") # "%.4e" is "9.9990e+2"; X == 2 + expect_gen(999.9, 6, "999.9") # "%.5e" is "9.99900e+2"; X == 2 + + expect_gen(999.0, 1, "1e+3") + expect_gen(999.0, 2, "1e+3") + expect_gen(999.0, 3, "999") + expect_gen(999.0, 4, "999") + expect_gen(999.0, 5, "999") + expect_gen(999.0, 6, "999") + + expect_gen(99.9999, 1, "1e+2") + expect_gen(99.9999, 2, "1e+2") + expect_gen(99.9999, 3, "100") + expect_gen(99.9999, 4, "100") + expect_gen(99.9999, 5, "100") + expect_gen(99.9999, 6, "99.9999") + + expect_gen(99.999, 1, "1e+2") + expect_gen(99.999, 2, "1e+2") + expect_gen(99.999, 3, "100") + expect_gen(99.999, 4, "100") + expect_gen(99.999, 5, "99.999") + expect_gen(99.999, 6, "99.999") + + expect_gen(99.99, 1, "1e+2") + expect_gen(99.99, 2, "1e+2") + expect_gen(99.99, 3, "100") + expect_gen(99.99, 4, "99.99") + expect_gen(99.99, 5, "99.99") + expect_gen(99.99, 6, "99.99") + + expect_gen(99.9, 1, "1e+2") + expect_gen(99.9, 2, "1e+2") + expect_gen(99.9, 3, "99.9") + expect_gen(99.9, 4, "99.9") + expect_gen(99.9, 5, "99.9") + expect_gen(99.9, 6, "99.9") + + expect_gen(99.0, 1, "1e+2") + expect_gen(99.0, 2, "99") + expect_gen(99.0, 3, "99") + expect_gen(99.0, 4, "99") + expect_gen(99.0, 5, "99") + expect_gen(99.0, 6, "99") + + expect_gen(9.99999, 1, "1e+1") + expect_gen(9.99999, 2, "10") + expect_gen(9.99999, 3, "10") + expect_gen(9.99999, 4, "10") + expect_gen(9.99999, 5, "10") + expect_gen(9.99999, 6, "9.99999") + + expect_gen(9.9999, 1, "1e+1") + expect_gen(9.9999, 2, "10") + expect_gen(9.9999, 3, "10") + expect_gen(9.9999, 4, "10") + expect_gen(9.9999, 5, "9.9999") + expect_gen(9.9999, 6, "9.9999") + + expect_gen(9.999, 1, "1e+1") + expect_gen(9.999, 2, "10") + expect_gen(9.999, 3, "10") + expect_gen(9.999, 4, "9.999") + expect_gen(9.999, 5, "9.999") + expect_gen(9.999, 6, "9.999") + + expect_gen(9.99, 1, "1e+1") + expect_gen(9.99, 2, "10") + expect_gen(9.99, 3, "9.99") + expect_gen(9.99, 4, "9.99") + expect_gen(9.99, 5, "9.99") + expect_gen(9.99, 6, "9.99") + + expect_gen(9.9, 1, "1e+1") + expect_gen(9.9, 2, "9.9") + expect_gen(9.9, 3, "9.9") + expect_gen(9.9, 4, "9.9") + expect_gen(9.9, 5, "9.9") + expect_gen(9.9, 6, "9.9") + + expect_gen(9.0, 1, "9") + expect_gen(9.0, 2, "9") + expect_gen(9.0, 3, "9") + expect_gen(9.0, 4, "9") + expect_gen(9.0, 5, "9") + expect_gen(9.0, 6, "9") + + expect_gen(0.999999, 1, "1") + expect_gen(0.999999, 2, "1") + expect_gen(0.999999, 3, "1") + expect_gen(0.999999, 4, "1") + expect_gen(0.999999, 5, "1") + expect_gen(0.999999, 6, "0.999999") + + expect_gen(0.99999, 1, "1") + expect_gen(0.99999, 2, "1") + expect_gen(0.99999, 3, "1") + expect_gen(0.99999, 4, "1") + expect_gen(0.99999, 5, "0.99999") + expect_gen(0.99999, 6, "0.99999") + + expect_gen(0.9999, 1, "1") + expect_gen(0.9999, 2, "1") + expect_gen(0.9999, 3, "1") + expect_gen(0.9999, 4, "0.9999") + expect_gen(0.9999, 5, "0.9999") + expect_gen(0.9999, 6, "0.9999") + + expect_gen(0.999, 1, "1") + expect_gen(0.999, 2, "1") + expect_gen(0.999, 3, "0.999") + expect_gen(0.999, 4, "0.999") + expect_gen(0.999, 5, "0.999") + expect_gen(0.999, 6, "0.999") + + expect_gen(0.99, 1, "1") + expect_gen(0.99, 2, "0.99") + expect_gen(0.99, 3, "0.99") + expect_gen(0.99, 4, "0.99") + expect_gen(0.99, 5, "0.99") + expect_gen(0.99, 6, "0.99") + + expect_gen(0.9, 1, "0.9") + expect_gen(0.9, 2, "0.9") + expect_gen(0.9, 3, "0.9") + expect_gen(0.9, 4, "0.9") + expect_gen(0.9, 5, "0.9") + expect_gen(0.9, 6, "0.9") + + expect_gen(0.0999999, 1, "0.1") + expect_gen(0.0999999, 2, "0.1") + expect_gen(0.0999999, 3, "0.1") + expect_gen(0.0999999, 4, "0.1") + expect_gen(0.0999999, 5, "0.1") + expect_gen(0.0999999, 6, "0.0999999") + + expect_gen(0.099999, 1, "0.1") + expect_gen(0.099999, 2, "0.1") + expect_gen(0.099999, 3, "0.1") + expect_gen(0.099999, 4, "0.1") + expect_gen(0.099999, 5, "0.099999") + expect_gen(0.099999, 6, "0.099999") + + expect_gen(0.09999, 1, "0.1") + expect_gen(0.09999, 2, "0.1") + expect_gen(0.09999, 3, "0.1") + expect_gen(0.09999, 4, "0.09999") + expect_gen(0.09999, 5, "0.09999") + expect_gen(0.09999, 6, "0.09999") + + expect_gen(0.0999, 1, "0.1") + expect_gen(0.0999, 2, "0.1") + expect_gen(0.0999, 3, "0.0999") + expect_gen(0.0999, 4, "0.0999") + expect_gen(0.0999, 5, "0.0999") + expect_gen(0.0999, 6, "0.0999") + + expect_gen(0.099, 1, "0.1") + expect_gen(0.099, 2, "0.099") + expect_gen(0.099, 3, "0.099") + expect_gen(0.099, 4, "0.099") + expect_gen(0.099, 5, "0.099") + expect_gen(0.099, 6, "0.099") + + expect_gen(0.09, 1, "0.09") + expect_gen(0.09, 2, "0.09") + expect_gen(0.09, 3, "0.09") + expect_gen(0.09, 4, "0.09") + expect_gen(0.09, 5, "0.09") + expect_gen(0.09, 6, "0.09") + + expect_gen(0.00999999, 1, "0.01") + expect_gen(0.00999999, 2, "0.01") + expect_gen(0.00999999, 3, "0.01") + expect_gen(0.00999999, 4, "0.01") + expect_gen(0.00999999, 5, "0.01") + expect_gen(0.00999999, 6, "0.00999999") + + expect_gen(0.0099999, 1, "0.01") + expect_gen(0.0099999, 2, "0.01") + expect_gen(0.0099999, 3, "0.01") + expect_gen(0.0099999, 4, "0.01") + expect_gen(0.0099999, 5, "0.0099999") + expect_gen(0.0099999, 6, "0.0099999") + + expect_gen(0.009999, 1, "0.01") + expect_gen(0.009999, 2, "0.01") + expect_gen(0.009999, 3, "0.01") + expect_gen(0.009999, 4, "0.009999") + expect_gen(0.009999, 5, "0.009999") + expect_gen(0.009999, 6, "0.009999") + + expect_gen(0.00999, 1, "0.01") + expect_gen(0.00999, 2, "0.01") + expect_gen(0.00999, 3, "0.00999") + expect_gen(0.00999, 4, "0.00999") + expect_gen(0.00999, 5, "0.00999") + expect_gen(0.00999, 6, "0.00999") + + expect_gen(0.0099, 1, "0.01") + expect_gen(0.0099, 2, "0.0099") + expect_gen(0.0099, 3, "0.0099") + expect_gen(0.0099, 4, "0.0099") + expect_gen(0.0099, 5, "0.0099") + expect_gen(0.0099, 6, "0.0099") + + expect_gen(0.009, 1, "0.009") + expect_gen(0.009, 2, "0.009") + expect_gen(0.009, 3, "0.009") + expect_gen(0.009, 4, "0.009") + expect_gen(0.009, 5, "0.009") + expect_gen(0.009, 6, "0.009") + + expect_gen(0.000999999, 1, "0.001") + expect_gen(0.000999999, 2, "0.001") + expect_gen(0.000999999, 3, "0.001") + expect_gen(0.000999999, 4, "0.001") + expect_gen(0.000999999, 5, "0.001") + expect_gen(0.000999999, 6, "0.000999999") + + expect_gen(0.00099999, 1, "0.001") + expect_gen(0.00099999, 2, "0.001") + expect_gen(0.00099999, 3, "0.001") + expect_gen(0.00099999, 4, "0.001") + expect_gen(0.00099999, 5, "0.00099999") + expect_gen(0.00099999, 6, "0.00099999") + + expect_gen(0.0009999, 1, "0.001") + expect_gen(0.0009999, 2, "0.001") + expect_gen(0.0009999, 3, "0.001") + expect_gen(0.0009999, 4, "0.0009999") + expect_gen(0.0009999, 5, "0.0009999") + expect_gen(0.0009999, 6, "0.0009999") + + expect_gen(0.000999, 1, "0.001") + expect_gen(0.000999, 2, "0.001") + expect_gen(0.000999, 3, "0.000999") + expect_gen(0.000999, 4, "0.000999") + expect_gen(0.000999, 5, "0.000999") + expect_gen(0.000999, 6, "0.000999") + + expect_gen(0.00099, 1, "0.001") + expect_gen(0.00099, 2, "0.00099") + expect_gen(0.00099, 3, "0.00099") + expect_gen(0.00099, 4, "0.00099") + expect_gen(0.00099, 5, "0.00099") + expect_gen(0.00099, 6, "0.00099") + + expect_gen(0.0009, 1, "0.0009") + expect_gen(0.0009, 2, "0.0009") + expect_gen(0.0009, 3, "0.0009") + expect_gen(0.0009, 4, "0.0009") + expect_gen(0.0009, 5, "0.0009") + expect_gen(0.0009, 6, "0.0009") + + # Having a scientific exponent X == -5 triggers scientific notation. + # If rounding adjusts this to X == -4, then fixed notation will be selected. + expect_gen(0.0000999999, 1, "0.0001") + expect_gen(0.0000999999, 2, "0.0001") + expect_gen(0.0000999999, 3, "0.0001") + expect_gen(0.0000999999, 4, "0.0001") + expect_gen(0.0000999999, 5, "0.0001") + expect_gen(0.0000999999, 6, "9.99999e-5") + + expect_gen(0.000099999, 1, "0.0001") + expect_gen(0.000099999, 2, "0.0001") + expect_gen(0.000099999, 3, "0.0001") + expect_gen(0.000099999, 4, "0.0001") + expect_gen(0.000099999, 5, "9.9999e-5") + expect_gen(0.000099999, 6, "9.9999e-5") + + expect_gen(0.00009999, 1, "0.0001") + expect_gen(0.00009999, 2, "0.0001") + expect_gen(0.00009999, 3, "0.0001") + expect_gen(0.00009999, 4, "9.999e-5") + expect_gen(0.00009999, 5, "9.999e-5") + expect_gen(0.00009999, 6, "9.999e-5") + + expect_gen(0.0000999, 1, "0.0001") + expect_gen(0.0000999, 2, "0.0001") + expect_gen(0.0000999, 3, "9.99e-5") + expect_gen(0.0000999, 4, "9.99e-5") + expect_gen(0.0000999, 5, "9.99e-5") + expect_gen(0.0000999, 6, "9.99e-5") + + expect_gen(0.000099, 1, "0.0001") + expect_gen(0.000099, 2, "9.9e-5") + expect_gen(0.000099, 3, "9.9e-5") + expect_gen(0.000099, 4, "9.9e-5") + expect_gen(0.000099, 5, "9.9e-5") + expect_gen(0.000099, 6, "9.9e-5") + + expect_gen(0.00009, 1, "9e-5") + expect_gen(0.00009, 2, "9e-5") + expect_gen(0.00009, 3, "9e-5") + expect_gen(0.00009, 4, "9e-5") + expect_gen(0.00009, 5, "9e-5") + expect_gen(0.00009, 6, "9e-5") + + # Rounding test cases without exponent-adjusting behavior. + expect_gen(2999.999, 1, "3e+3") + expect_gen(2999.999, 2, "3e+3") + expect_gen(2999.999, 3, "3e+3") + expect_gen(2999.999, 4, "3000") + expect_gen(2999.999, 5, "3000") + expect_gen(2999.999, 6, "3000") + + expect_gen(2999.99, 1, "3e+3") + expect_gen(2999.99, 2, "3e+3") + expect_gen(2999.99, 3, "3e+3") + expect_gen(2999.99, 4, "3000") + expect_gen(2999.99, 5, "3000") + expect_gen(2999.99, 6, "2999.99") + + expect_gen(2999.9, 1, "3e+3") + expect_gen(2999.9, 2, "3e+3") + expect_gen(2999.9, 3, "3e+3") + expect_gen(2999.9, 4, "3000") + expect_gen(2999.9, 5, "2999.9") + expect_gen(2999.9, 6, "2999.9") + + expect_gen(2999.0, 1, "3e+3") + expect_gen(2999.0, 2, "3e+3") + expect_gen(2999.0, 3, "3e+3") + expect_gen(2999.0, 4, "2999") + expect_gen(2999.0, 5, "2999") + expect_gen(2999.0, 6, "2999") + + expect_gen(299.999, 1, "3e+2") + expect_gen(299.999, 2, "3e+2") + expect_gen(299.999, 3, "300") + expect_gen(299.999, 4, "300") + expect_gen(299.999, 5, "300") + expect_gen(299.999, 6, "299.999") + + expect_gen(299.99, 1, "3e+2") + expect_gen(299.99, 2, "3e+2") + expect_gen(299.99, 3, "300") + expect_gen(299.99, 4, "300") + expect_gen(299.99, 5, "299.99") + expect_gen(299.99, 6, "299.99") + + expect_gen(299.9, 1, "3e+2") + expect_gen(299.9, 2, "3e+2") + expect_gen(299.9, 3, "300") + expect_gen(299.9, 4, "299.9") + expect_gen(299.9, 5, "299.9") + expect_gen(299.9, 6, "299.9") + + expect_gen(299.0, 1, "3e+2") + expect_gen(299.0, 2, "3e+2") + expect_gen(299.0, 3, "299") + expect_gen(299.0, 4, "299") + expect_gen(299.0, 5, "299") + expect_gen(299.0, 6, "299") + + expect_gen(29.999, 1, "3e+1") + expect_gen(29.999, 2, "30") + expect_gen(29.999, 3, "30") + expect_gen(29.999, 4, "30") + expect_gen(29.999, 5, "29.999") + expect_gen(29.999, 6, "29.999") + + expect_gen(29.99, 1, "3e+1") + expect_gen(29.99, 2, "30") + expect_gen(29.99, 3, "30") + expect_gen(29.99, 4, "29.99") + expect_gen(29.99, 5, "29.99") + expect_gen(29.99, 6, "29.99") + + expect_gen(29.9, 1, "3e+1") + expect_gen(29.9, 2, "30") + expect_gen(29.9, 3, "29.9") + expect_gen(29.9, 4, "29.9") + expect_gen(29.9, 5, "29.9") + expect_gen(29.9, 6, "29.9") + + expect_gen(29.0, 1, "3e+1") + expect_gen(29.0, 2, "29") + expect_gen(29.0, 3, "29") + expect_gen(29.0, 4, "29") + expect_gen(29.0, 5, "29") + expect_gen(29.0, 6, "29") + + expect_gen(2.999, 1, "3") + expect_gen(2.999, 2, "3") + expect_gen(2.999, 3, "3") + expect_gen(2.999, 4, "2.999") + expect_gen(2.999, 5, "2.999") + expect_gen(2.999, 6, "2.999") + + expect_gen(2.99, 1, "3") + expect_gen(2.99, 2, "3") + expect_gen(2.99, 3, "2.99") + expect_gen(2.99, 4, "2.99") + expect_gen(2.99, 5, "2.99") + expect_gen(2.99, 6, "2.99") + + expect_gen(2.9, 1, "3") + expect_gen(2.9, 2, "2.9") + expect_gen(2.9, 3, "2.9") + expect_gen(2.9, 4, "2.9") + expect_gen(2.9, 5, "2.9") + expect_gen(2.9, 6, "2.9") + + expect_gen(2.0, 1, "2") + expect_gen(2.0, 2, "2") + expect_gen(2.0, 3, "2") + expect_gen(2.0, 4, "2") + expect_gen(2.0, 5, "2") + expect_gen(2.0, 6, "2") + + expect_gen(0.2999, 1, "0.3") + expect_gen(0.2999, 2, "0.3") + expect_gen(0.2999, 3, "0.3") + expect_gen(0.2999, 4, "0.2999") + expect_gen(0.2999, 5, "0.2999") + expect_gen(0.2999, 6, "0.2999") + + expect_gen(0.299, 1, "0.3") + expect_gen(0.299, 2, "0.3") + expect_gen(0.299, 3, "0.299") + expect_gen(0.299, 4, "0.299") + expect_gen(0.299, 5, "0.299") + expect_gen(0.299, 6, "0.299") + + expect_gen(0.29, 1, "0.3") + expect_gen(0.29, 2, "0.29") + expect_gen(0.29, 3, "0.29") + expect_gen(0.29, 4, "0.29") + expect_gen(0.29, 5, "0.29") + expect_gen(0.29, 6, "0.29") + + expect_gen(0.2, 1, "0.2") + expect_gen(0.2, 2, "0.2") + expect_gen(0.2, 3, "0.2") + expect_gen(0.2, 4, "0.2") + expect_gen(0.2, 5, "0.2") + expect_gen(0.2, 6, "0.2") + + expect_gen(0.02999, 1, "0.03") + expect_gen(0.02999, 2, "0.03") + expect_gen(0.02999, 3, "0.03") + expect_gen(0.02999, 4, "0.02999") + expect_gen(0.02999, 5, "0.02999") + expect_gen(0.02999, 6, "0.02999") + + expect_gen(0.0299, 1, "0.03") + expect_gen(0.0299, 2, "0.03") + expect_gen(0.0299, 3, "0.0299") + expect_gen(0.0299, 4, "0.0299") + expect_gen(0.0299, 5, "0.0299") + expect_gen(0.0299, 6, "0.0299") + + expect_gen(0.029, 1, "0.03") + expect_gen(0.029, 2, "0.029") + expect_gen(0.029, 3, "0.029") + expect_gen(0.029, 4, "0.029") + expect_gen(0.029, 5, "0.029") + expect_gen(0.029, 6, "0.029") + + expect_gen(0.02, 1, "0.02") + expect_gen(0.02, 2, "0.02") + expect_gen(0.02, 3, "0.02") + expect_gen(0.02, 4, "0.02") + expect_gen(0.02, 5, "0.02") + expect_gen(0.02, 6, "0.02") + + expect_gen(0.002999, 1, "0.003") + expect_gen(0.002999, 2, "0.003") + expect_gen(0.002999, 3, "0.003") + expect_gen(0.002999, 4, "0.002999") + expect_gen(0.002999, 5, "0.002999") + expect_gen(0.002999, 6, "0.002999") + + expect_gen(0.00299, 1, "0.003") + expect_gen(0.00299, 2, "0.003") + expect_gen(0.00299, 3, "0.00299") + expect_gen(0.00299, 4, "0.00299") + expect_gen(0.00299, 5, "0.00299") + expect_gen(0.00299, 6, "0.00299") + + expect_gen(0.0029, 1, "0.003") + expect_gen(0.0029, 2, "0.0029") + expect_gen(0.0029, 3, "0.0029") + expect_gen(0.0029, 4, "0.0029") + expect_gen(0.0029, 5, "0.0029") + expect_gen(0.0029, 6, "0.0029") + + expect_gen(0.002, 1, "0.002") + expect_gen(0.002, 2, "0.002") + expect_gen(0.002, 3, "0.002") + expect_gen(0.002, 4, "0.002") + expect_gen(0.002, 5, "0.002") + expect_gen(0.002, 6, "0.002") + + expect_gen(0.0002999, 1, "0.0003") + expect_gen(0.0002999, 2, "0.0003") + expect_gen(0.0002999, 3, "0.0003") + expect_gen(0.0002999, 4, "0.0002999") + expect_gen(0.0002999, 5, "0.0002999") + expect_gen(0.0002999, 6, "0.0002999") + + expect_gen(0.000299, 1, "0.0003") + expect_gen(0.000299, 2, "0.0003") + expect_gen(0.000299, 3, "0.000299") + expect_gen(0.000299, 4, "0.000299") + expect_gen(0.000299, 5, "0.000299") + expect_gen(0.000299, 6, "0.000299") + + expect_gen(0.00029, 1, "0.0003") + expect_gen(0.00029, 2, "0.00029") + expect_gen(0.00029, 3, "0.00029") + expect_gen(0.00029, 4, "0.00029") + expect_gen(0.00029, 5, "0.00029") + expect_gen(0.00029, 6, "0.00029") + + expect_gen(0.0002, 1, "0.0002") + expect_gen(0.0002, 2, "0.0002") + expect_gen(0.0002, 3, "0.0002") + expect_gen(0.0002, 4, "0.0002") + expect_gen(0.0002, 5, "0.0002") + expect_gen(0.0002, 6, "0.0002") + + expect_gen(0.00002999, 1, "3e-5") + expect_gen(0.00002999, 2, "3e-5") + expect_gen(0.00002999, 3, "3e-5") + expect_gen(0.00002999, 4, "2.999e-5") + expect_gen(0.00002999, 5, "2.999e-5") + expect_gen(0.00002999, 6, "2.999e-5") + + expect_gen(0.0000299, 1, "3e-5") + expect_gen(0.0000299, 2, "3e-5") + expect_gen(0.0000299, 3, "2.99e-5") + expect_gen(0.0000299, 4, "2.99e-5") + expect_gen(0.0000299, 5, "2.99e-5") + expect_gen(0.0000299, 6, "2.99e-5") + + expect_gen(0.000029, 1, "3e-5") + expect_gen(0.000029, 2, "2.9e-5") + expect_gen(0.000029, 3, "2.9e-5") + expect_gen(0.000029, 4, "2.9e-5") + expect_gen(0.000029, 5, "2.9e-5") + expect_gen(0.000029, 6, "2.9e-5") + + expect_gen(0.00002, 1, "2e-5") + expect_gen(0.00002, 2, "2e-5") + expect_gen(0.00002, 3, "2e-5") + expect_gen(0.00002, 4, "2e-5") + expect_gen(0.00002, 5, "2e-5") + expect_gen(0.00002, 6, "2e-5") + end + + it "transitions between values of the scientific exponent X" do + {% for tc in GEN_TRANSITIONS %} + expect_gen(hexfloat({{ tc[0] }}), {{ tc[1] }}, {{ tc[2] }}, file: {{ tc.filename }}, line: {{ tc.line_number }}) + {% end %} + end + + it "UCRT had trouble with rounding this value" do + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 105, "109995565999999994887854821710219658911365648587951921896774663603198787416706536331386569598149846892544") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 19, "1.099955659999999949e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 18, "1.09995565999999995e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 17, "1.0999556599999999e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 16, "1.09995566e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 15, "1.09995566e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 14, "1.09995566e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 13, "1.09995566e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 12, "1.09995566e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 11, "1.09995566e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 10, "1.09995566e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 9, "1.09995566e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 8, "1.0999557e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 7, "1.099956e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 6, "1.09996e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 5, "1.1e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 4, "1.1e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 3, "1.1e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 2, "1.1e+104") + expect_gen(hexfloat("0x1.88e2d605edc3dp+345"), 1, "1e+104") + end + + it "more cases that the UCRT had trouble with (e.g. DevCom-1093399)" do + expect_gen(hexfloat("0x1.8p+62"), 17, "6.9175290276410819e+18") + expect_gen(hexfloat("0x1.0a2742p+17"), 6, "136271") + expect_gen(hexfloat("0x1.f8b0f962cdffbp+205"), 14, "1.0137595739223e+62") + expect_gen(hexfloat("0x1.f8b0f962cdffbp+205"), 17, "1.0137595739222531e+62") + expect_gen(hexfloat("0x1.f8b0f962cdffbp+205"), 51, "1.01375957392225305727423222620636224221808910954041e+62") + expect_gen(hexfloat("0x1.f8b0f962cdffbp+205"), 55, "1.013759573922253057274232226206362242218089109540405973e+62") + end + end end diff --git a/spec/std/float_printer/ryu_printf_test_cases.cr b/spec/std/float_printer/ryu_printf_test_cases.cr index 6c1a3a155692..32448af3bc4d 100644 --- a/spec/std/float_printer/ryu_printf_test_cases.cr +++ b/spec/std/float_printer/ryu_printf_test_cases.cr @@ -2695,3 +2695,1673 @@ ALL_BINARY_EXPONENTS = [ {6.123699292104195e+307, 0, 307}, {1.7026387749989901e+308, 0, 308}, ] of _ + +# For brevity, we avoid testing all possible combinations of P and X. Instead, we test: +# * All values of P where some X can be affected by rounding. (For double, this is [1, 15].) +# * P == 25, which is arbitrary. +# * P == numeric_limits::max_exponent10 + 1. This selects fixed notation for numeric_limits::max(), +# so it's the largest interesting value of P. +# * Finally, we test the transitions around X == P - 1, ensuring that we can recognize every value of X. +GEN_TRANSITIONS = [ + {"0x1.8e757928e0c9dp-14", 1, "9e-5"}, + {"0x1.8e757928e0c9ep-14", 1, "0.0001"}, + {"0x1.f212d77318fc5p-11", 1, "0.0009"}, + {"0x1.f212d77318fc6p-11", 1, "0.001"}, + {"0x1.374bc6a7ef9dbp-7", 1, "0.009"}, + {"0x1.374bc6a7ef9dcp-7", 1, "0.01"}, + {"0x1.851eb851eb851p-4", 1, "0.09"}, + {"0x1.851eb851eb852p-4", 1, "0.1"}, + {"0x1.e666666666666p-1", 1, "0.9"}, + {"0x1.e666666666667p-1", 1, "1"}, + {"0x1.2ffffffffffffp+3", 1, "9"}, + {"0x1.3000000000000p+3", 1, "1e+1"}, + {"0x1.a1554fbdad751p-14", 2, "9.9e-5"}, + {"0x1.a1554fbdad752p-14", 2, "0.0001"}, + {"0x1.04d551d68c692p-10", 2, "0.00099"}, + {"0x1.04d551d68c693p-10", 2, "0.001"}, + {"0x1.460aa64c2f837p-7", 2, "0.0099"}, + {"0x1.460aa64c2f838p-7", 2, "0.01"}, + {"0x1.978d4fdf3b645p-4", 2, "0.099"}, + {"0x1.978d4fdf3b646p-4", 2, "0.1"}, + {"0x1.fd70a3d70a3d7p-1", 2, "0.99"}, + {"0x1.fd70a3d70a3d8p-1", 2, "1"}, + {"0x1.3e66666666666p+3", 2, "9.9"}, + {"0x1.3e66666666667p+3", 2, "10"}, + {"0x1.8dfffffffffffp+6", 2, "99"}, + {"0x1.8e00000000000p+6", 2, "1e+2"}, + {"0x1.a3387ecc8eb96p-14", 3, "9.99e-5"}, + {"0x1.a3387ecc8eb97p-14", 3, "0.0001"}, + {"0x1.06034f3fd933ep-10", 3, "0.000999"}, + {"0x1.06034f3fd933fp-10", 3, "0.001"}, + {"0x1.4784230fcf80dp-7", 3, "0.00999"}, + {"0x1.4784230fcf80ep-7", 3, "0.01"}, + {"0x1.99652bd3c3611p-4", 3, "0.0999"}, + {"0x1.99652bd3c3612p-4", 3, "0.1"}, + {"0x1.ffbe76c8b4395p-1", 3, "0.999"}, + {"0x1.ffbe76c8b4396p-1", 3, "1"}, + {"0x1.3fd70a3d70a3dp+3", 3, "9.99"}, + {"0x1.3fd70a3d70a3ep+3", 3, "10"}, + {"0x1.8fcccccccccccp+6", 3, "99.9"}, + {"0x1.8fccccccccccdp+6", 3, "100"}, + {"0x1.f3bffffffffffp+9", 3, "999"}, + {"0x1.f3c0000000000p+9", 3, "1e+3"}, + {"0x1.a368d04e0ba6ap-14", 4, "9.999e-5"}, + {"0x1.a368d04e0ba6bp-14", 4, "0.0001"}, + {"0x1.06218230c7482p-10", 4, "0.0009999"}, + {"0x1.06218230c7483p-10", 4, "0.001"}, + {"0x1.47a9e2bcf91a3p-7", 4, "0.009999"}, + {"0x1.47a9e2bcf91a4p-7", 4, "0.01"}, + {"0x1.99945b6c3760bp-4", 4, "0.09999"}, + {"0x1.99945b6c3760cp-4", 4, "0.1"}, + {"0x1.fff972474538ep-1", 4, "0.9999"}, + {"0x1.fff972474538fp-1", 4, "1"}, + {"0x1.3ffbe76c8b439p+3", 4, "9.999"}, + {"0x1.3ffbe76c8b43ap+3", 4, "10"}, + {"0x1.8ffae147ae147p+6", 4, "99.99"}, + {"0x1.8ffae147ae148p+6", 4, "100"}, + {"0x1.f3f9999999999p+9", 4, "999.9"}, + {"0x1.f3f999999999ap+9", 4, "1000"}, + {"0x1.387bfffffffffp+13", 4, "9999"}, + {"0x1.387c000000000p+13", 4, "1e+4"}, + {"0x1.a36da54164f19p-14", 5, "9.9999e-5"}, + {"0x1.a36da54164f1ap-14", 5, "0.0001"}, + {"0x1.06248748df16fp-10", 5, "0.00099999"}, + {"0x1.06248748df170p-10", 5, "0.001"}, + {"0x1.47ada91b16dcbp-7", 5, "0.0099999"}, + {"0x1.47ada91b16dccp-7", 5, "0.01"}, + {"0x1.99991361dc93ep-4", 5, "0.099999"}, + {"0x1.99991361dc93fp-4", 5, "0.1"}, + {"0x1.ffff583a53b8ep-1", 5, "0.99999"}, + {"0x1.ffff583a53b8fp-1", 5, "1"}, + {"0x1.3fff972474538p+3", 5, "9.9999"}, + {"0x1.3fff972474539p+3", 5, "10"}, + {"0x1.8fff7ced91687p+6", 5, "99.999"}, + {"0x1.8fff7ced91688p+6", 5, "100"}, + {"0x1.f3ff5c28f5c28p+9", 5, "999.99"}, + {"0x1.f3ff5c28f5c29p+9", 5, "1000"}, + {"0x1.387f999999999p+13", 5, "9999.9"}, + {"0x1.387f99999999ap+13", 5, "10000"}, + {"0x1.869f7ffffffffp+16", 5, "99999"}, + {"0x1.869f800000000p+16", 5, "1e+5"}, + {"0x1.a36e20f35445dp-14", 6, "9.99999e-5"}, + {"0x1.a36e20f35445ep-14", 6, "0.0001"}, + {"0x1.0624d49814abap-10", 6, "0.000999999"}, + {"0x1.0624d49814abbp-10", 6, "0.001"}, + {"0x1.47ae09be19d69p-7", 6, "0.00999999"}, + {"0x1.47ae09be19d6ap-7", 6, "0.01"}, + {"0x1.99998c2da04c3p-4", 6, "0.0999999"}, + {"0x1.99998c2da04c4p-4", 6, "0.1"}, + {"0x1.ffffef39085f4p-1", 6, "0.999999"}, + {"0x1.ffffef39085f5p-1", 6, "1"}, + {"0x1.3ffff583a53b8p+3", 6, "9.99999"}, + {"0x1.3ffff583a53b9p+3", 6, "10"}, + {"0x1.8ffff2e48e8a7p+6", 6, "99.9999"}, + {"0x1.8ffff2e48e8a8p+6", 6, "100"}, + {"0x1.f3ffef9db22d0p+9", 6, "999.999"}, + {"0x1.f3ffef9db22d1p+9", 6, "1000"}, + {"0x1.387ff5c28f5c2p+13", 6, "9999.99"}, + {"0x1.387ff5c28f5c3p+13", 6, "10000"}, + {"0x1.869ff33333333p+16", 6, "99999.9"}, + {"0x1.869ff33333334p+16", 6, "100000"}, + {"0x1.e847effffffffp+19", 6, "999999"}, + {"0x1.e847f00000000p+19", 6, "1e+6"}, + {"0x1.a36e2d51ec34bp-14", 7, "9.999999e-5"}, + {"0x1.a36e2d51ec34cp-14", 7, "0.0001"}, + {"0x1.0624dc5333a0ep-10", 7, "0.0009999999"}, + {"0x1.0624dc5333a0fp-10", 7, "0.001"}, + {"0x1.47ae136800892p-7", 7, "0.009999999"}, + {"0x1.47ae136800893p-7", 7, "0.01"}, + {"0x1.9999984200ab7p-4", 7, "0.09999999"}, + {"0x1.9999984200ab8p-4", 7, "0.1"}, + {"0x1.fffffe5280d65p-1", 7, "0.9999999"}, + {"0x1.fffffe5280d66p-1", 7, "1"}, + {"0x1.3ffffef39085fp+3", 7, "9.999999"}, + {"0x1.3ffffef390860p+3", 7, "10"}, + {"0x1.8ffffeb074a77p+6", 7, "99.99999"}, + {"0x1.8ffffeb074a78p+6", 7, "100"}, + {"0x1.f3fffe5c91d14p+9", 7, "999.9999"}, + {"0x1.f3fffe5c91d15p+9", 7, "1000"}, + {"0x1.387ffef9db22dp+13", 7, "9999.999"}, + {"0x1.387ffef9db22ep+13", 7, "10000"}, + {"0x1.869ffeb851eb8p+16", 7, "99999.99"}, + {"0x1.869ffeb851eb9p+16", 7, "100000"}, + {"0x1.e847fe6666666p+19", 7, "999999.9"}, + {"0x1.e847fe6666667p+19", 7, "1000000"}, + {"0x1.312cfefffffffp+23", 7, "9999999"}, + {"0x1.312cff0000000p+23", 7, "1e+7"}, + {"0x1.a36e2e8e94ffcp-14", 8, "9.9999999e-5"}, + {"0x1.a36e2e8e94ffdp-14", 8, "0.0001"}, + {"0x1.0624dd191d1fdp-10", 8, "0.00099999999"}, + {"0x1.0624dd191d1fep-10", 8, "0.001"}, + {"0x1.47ae145f6467dp-7", 8, "0.0099999999"}, + {"0x1.47ae145f6467ep-7", 8, "0.01"}, + {"0x1.999999773d81cp-4", 8, "0.099999999"}, + {"0x1.999999773d81dp-4", 8, "0.1"}, + {"0x1.ffffffd50ce23p-1", 8, "0.99999999"}, + {"0x1.ffffffd50ce24p-1", 8, "1"}, + {"0x1.3fffffe5280d6p+3", 8, "9.9999999"}, + {"0x1.3fffffe5280d7p+3", 8, "10"}, + {"0x1.8fffffde7210bp+6", 8, "99.999999"}, + {"0x1.8fffffde7210cp+6", 8, "100"}, + {"0x1.f3ffffd60e94ep+9", 8, "999.99999"}, + {"0x1.f3ffffd60e94fp+9", 8, "1000"}, + {"0x1.387fffe5c91d1p+13", 8, "9999.9999"}, + {"0x1.387fffe5c91d2p+13", 8, "10000"}, + {"0x1.869fffdf3b645p+16", 8, "99999.999"}, + {"0x1.869fffdf3b646p+16", 8, "100000"}, + {"0x1.e847ffd70a3d7p+19", 8, "999999.99"}, + {"0x1.e847ffd70a3d8p+19", 8, "1000000"}, + {"0x1.312cffe666666p+23", 8, "9999999.9"}, + {"0x1.312cffe666667p+23", 8, "10000000"}, + {"0x1.7d783fdffffffp+26", 8, "99999999"}, + {"0x1.7d783fe000000p+26", 8, "1e+8"}, + {"0x1.a36e2eae3f7a7p-14", 9, "9.99999999e-5"}, + {"0x1.a36e2eae3f7a8p-14", 9, "0.0001"}, + {"0x1.0624dd2ce7ac8p-10", 9, "0.000999999999"}, + {"0x1.0624dd2ce7ac9p-10", 9, "0.001"}, + {"0x1.47ae14782197bp-7", 9, "0.00999999999"}, + {"0x1.47ae14782197cp-7", 9, "0.01"}, + {"0x1.9999999629fd9p-4", 9, "0.0999999999"}, + {"0x1.9999999629fdap-4", 9, "0.1"}, + {"0x1.fffffffbb47d0p-1", 9, "0.999999999"}, + {"0x1.fffffffbb47d1p-1", 9, "1"}, + {"0x1.3ffffffd50ce2p+3", 9, "9.99999999"}, + {"0x1.3ffffffd50ce3p+3", 9, "10"}, + {"0x1.8ffffffca501ap+6", 9, "99.9999999"}, + {"0x1.8ffffffca501bp+6", 9, "100"}, + {"0x1.f3fffffbce421p+9", 9, "999.999999"}, + {"0x1.f3fffffbce422p+9", 9, "1000"}, + {"0x1.387ffffd60e94p+13", 9, "9999.99999"}, + {"0x1.387ffffd60e95p+13", 9, "10000"}, + {"0x1.869ffffcb923ap+16", 9, "99999.9999"}, + {"0x1.869ffffcb923bp+16", 9, "100000"}, + {"0x1.e847fffbe76c8p+19", 9, "999999.999"}, + {"0x1.e847fffbe76c9p+19", 9, "1000000"}, + {"0x1.312cfffd70a3dp+23", 9, "9999999.99"}, + {"0x1.312cfffd70a3ep+23", 9, "10000000"}, + {"0x1.7d783ffccccccp+26", 9, "99999999.9"}, + {"0x1.7d783ffcccccdp+26", 9, "100000000"}, + {"0x1.dcd64ffbfffffp+29", 9, "999999999"}, + {"0x1.dcd64ffc00000p+29", 9, "1e+9"}, + {"0x1.a36e2eb16a205p-14", 10, "9.999999999e-5"}, + {"0x1.a36e2eb16a206p-14", 10, "0.0001"}, + {"0x1.0624dd2ee2543p-10", 10, "0.0009999999999"}, + {"0x1.0624dd2ee2544p-10", 10, "0.001"}, + {"0x1.47ae147a9ae94p-7", 10, "0.009999999999"}, + {"0x1.47ae147a9ae95p-7", 10, "0.01"}, + {"0x1.9999999941a39p-4", 10, "0.09999999999"}, + {"0x1.9999999941a3ap-4", 10, "0.1"}, + {"0x1.ffffffff920c8p-1", 10, "0.9999999999"}, + {"0x1.ffffffff920c9p-1", 10, "1"}, + {"0x1.3fffffffbb47dp+3", 10, "9.999999999"}, + {"0x1.3fffffffbb47ep+3", 10, "10"}, + {"0x1.8fffffffaa19cp+6", 10, "99.99999999"}, + {"0x1.8fffffffaa19dp+6", 10, "100"}, + {"0x1.f3ffffff94a03p+9", 10, "999.9999999"}, + {"0x1.f3ffffff94a04p+9", 10, "1000"}, + {"0x1.387fffffbce42p+13", 10, "9999.999999"}, + {"0x1.387fffffbce43p+13", 10, "10000"}, + {"0x1.869fffffac1d2p+16", 10, "99999.99999"}, + {"0x1.869fffffac1d3p+16", 10, "100000"}, + {"0x1.e847ffff97247p+19", 10, "999999.9999"}, + {"0x1.e847ffff97248p+19", 10, "1000000"}, + {"0x1.312cffffbe76cp+23", 10, "9999999.999"}, + {"0x1.312cffffbe76dp+23", 10, "10000000"}, + {"0x1.7d783fffae147p+26", 10, "99999999.99"}, + {"0x1.7d783fffae148p+26", 10, "100000000"}, + {"0x1.dcd64fff99999p+29", 10, "999999999.9"}, + {"0x1.dcd64fff9999ap+29", 10, "1000000000"}, + {"0x1.2a05f1ffbffffp+33", 10, "9999999999"}, + {"0x1.2a05f1ffc0000p+33", 10, "1e+10"}, + {"0x1.a36e2eb1bb30fp-14", 11, "9.9999999999e-5"}, + {"0x1.a36e2eb1bb310p-14", 11, "0.0001"}, + {"0x1.0624dd2f14fe9p-10", 11, "0.00099999999999"}, + {"0x1.0624dd2f14feap-10", 11, "0.001"}, + {"0x1.47ae147ada3e3p-7", 11, "0.0099999999999"}, + {"0x1.47ae147ada3e4p-7", 11, "0.01"}, + {"0x1.9999999990cdcp-4", 11, "0.099999999999"}, + {"0x1.9999999990cddp-4", 11, "0.1"}, + {"0x1.fffffffff5014p-1", 11, "0.99999999999"}, + {"0x1.fffffffff5015p-1", 11, "1"}, + {"0x1.3ffffffff920cp+3", 11, "9.9999999999"}, + {"0x1.3ffffffff920dp+3", 11, "10"}, + {"0x1.8ffffffff768fp+6", 11, "99.999999999"}, + {"0x1.8ffffffff7690p+6", 11, "100"}, + {"0x1.f3fffffff5433p+9", 11, "999.99999999"}, + {"0x1.f3fffffff5434p+9", 11, "1000"}, + {"0x1.387ffffff94a0p+13", 11, "9999.9999999"}, + {"0x1.387ffffff94a1p+13", 11, "10000"}, + {"0x1.869ffffff79c8p+16", 11, "99999.999999"}, + {"0x1.869ffffff79c9p+16", 11, "100000"}, + {"0x1.e847fffff583ap+19", 11, "999999.99999"}, + {"0x1.e847fffff583bp+19", 11, "1000000"}, + {"0x1.312cfffff9724p+23", 11, "9999999.9999"}, + {"0x1.312cfffff9725p+23", 11, "10000000"}, + {"0x1.7d783ffff7cedp+26", 11, "99999999.999"}, + {"0x1.7d783ffff7ceep+26", 11, "100000000"}, + {"0x1.dcd64ffff5c28p+29", 11, "999999999.99"}, + {"0x1.dcd64ffff5c29p+29", 11, "1000000000"}, + {"0x1.2a05f1fff9999p+33", 11, "9999999999.9"}, + {"0x1.2a05f1fff999ap+33", 11, "10000000000"}, + {"0x1.74876e7ff7fffp+36", 11, "99999999999"}, + {"0x1.74876e7ff8000p+36", 11, "1e+11"}, + {"0x1.a36e2eb1c34c3p-14", 12, "9.99999999999e-5"}, + {"0x1.a36e2eb1c34c4p-14", 12, "0.0001"}, + {"0x1.0624dd2f1a0fap-10", 12, "0.000999999999999"}, + {"0x1.0624dd2f1a0fbp-10", 12, "0.001"}, + {"0x1.47ae147ae0938p-7", 12, "0.00999999999999"}, + {"0x1.47ae147ae0939p-7", 12, "0.01"}, + {"0x1.9999999998b86p-4", 12, "0.0999999999999"}, + {"0x1.9999999998b87p-4", 12, "0.1"}, + {"0x1.fffffffffee68p-1", 12, "0.999999999999"}, + {"0x1.fffffffffee69p-1", 12, "1"}, + {"0x1.3fffffffff501p+3", 12, "9.99999999999"}, + {"0x1.3fffffffff502p+3", 12, "10"}, + {"0x1.8fffffffff241p+6", 12, "99.9999999999"}, + {"0x1.8fffffffff242p+6", 12, "100"}, + {"0x1.f3fffffffeed1p+9", 12, "999.999999999"}, + {"0x1.f3fffffffeed2p+9", 12, "1000"}, + {"0x1.387fffffff543p+13", 12, "9999.99999999"}, + {"0x1.387fffffff544p+13", 12, "10000"}, + {"0x1.869fffffff294p+16", 12, "99999.9999999"}, + {"0x1.869fffffff295p+16", 12, "100000"}, + {"0x1.e847fffffef39p+19", 12, "999999.999999"}, + {"0x1.e847fffffef3ap+19", 12, "1000000"}, + {"0x1.312cffffff583p+23", 12, "9999999.99999"}, + {"0x1.312cffffff584p+23", 12, "10000000"}, + {"0x1.7d783fffff2e4p+26", 12, "99999999.9999"}, + {"0x1.7d783fffff2e5p+26", 12, "100000000"}, + {"0x1.dcd64ffffef9dp+29", 12, "999999999.999"}, + {"0x1.dcd64ffffef9ep+29", 12, "1000000000"}, + {"0x1.2a05f1ffff5c2p+33", 12, "9999999999.99"}, + {"0x1.2a05f1ffff5c3p+33", 12, "10000000000"}, + {"0x1.74876e7fff333p+36", 12, "99999999999.9"}, + {"0x1.74876e7fff334p+36", 12, "100000000000"}, + {"0x1.d1a94a1ffefffp+39", 12, "999999999999"}, + {"0x1.d1a94a1fff000p+39", 12, "1e+12"}, + {"0x1.a36e2eb1c41bbp-14", 13, "9.999999999999e-5"}, + {"0x1.a36e2eb1c41bcp-14", 13, "0.0001"}, + {"0x1.0624dd2f1a915p-10", 13, "0.0009999999999999"}, + {"0x1.0624dd2f1a916p-10", 13, "0.001"}, + {"0x1.47ae147ae135ap-7", 13, "0.009999999999999"}, + {"0x1.47ae147ae135bp-7", 13, "0.01"}, + {"0x1.9999999999831p-4", 13, "0.09999999999999"}, + {"0x1.9999999999832p-4", 13, "0.1"}, + {"0x1.ffffffffffe3dp-1", 13, "0.9999999999999"}, + {"0x1.ffffffffffe3ep-1", 13, "1"}, + {"0x1.3fffffffffee6p+3", 13, "9.999999999999"}, + {"0x1.3fffffffffee7p+3", 13, "10"}, + {"0x1.8fffffffffea0p+6", 13, "99.99999999999"}, + {"0x1.8fffffffffea1p+6", 13, "100"}, + {"0x1.f3ffffffffe48p+9", 13, "999.9999999999"}, + {"0x1.f3ffffffffe49p+9", 13, "1000"}, + {"0x1.387fffffffeedp+13", 13, "9999.999999999"}, + {"0x1.387fffffffeeep+13", 13, "10000"}, + {"0x1.869fffffffea8p+16", 13, "99999.99999999"}, + {"0x1.869fffffffea9p+16", 13, "100000"}, + {"0x1.e847ffffffe52p+19", 13, "999999.9999999"}, + {"0x1.e847ffffffe53p+19", 13, "1000000"}, + {"0x1.312cffffffef3p+23", 13, "9999999.999999"}, + {"0x1.312cffffffef4p+23", 13, "10000000"}, + {"0x1.7d783fffffeb0p+26", 13, "99999999.99999"}, + {"0x1.7d783fffffeb1p+26", 13, "100000000"}, + {"0x1.dcd64fffffe5cp+29", 13, "999999999.9999"}, + {"0x1.dcd64fffffe5dp+29", 13, "1000000000"}, + {"0x1.2a05f1ffffef9p+33", 13, "9999999999.999"}, + {"0x1.2a05f1ffffefap+33", 13, "10000000000"}, + {"0x1.74876e7fffeb8p+36", 13, "99999999999.99"}, + {"0x1.74876e7fffeb9p+36", 13, "100000000000"}, + {"0x1.d1a94a1fffe66p+39", 13, "999999999999.9"}, + {"0x1.d1a94a1fffe67p+39", 13, "1000000000000"}, + {"0x1.2309ce53ffeffp+43", 13, "9999999999999"}, + {"0x1.2309ce53fff00p+43", 13, "1e+13"}, + {"0x1.a36e2eb1c4307p-14", 14, "9.9999999999999e-5"}, + {"0x1.a36e2eb1c4308p-14", 14, "0.0001"}, + {"0x1.0624dd2f1a9e4p-10", 14, "0.00099999999999999"}, + {"0x1.0624dd2f1a9e5p-10", 14, "0.001"}, + {"0x1.47ae147ae145ep-7", 14, "0.0099999999999999"}, + {"0x1.47ae147ae145fp-7", 14, "0.01"}, + {"0x1.9999999999975p-4", 14, "0.099999999999999"}, + {"0x1.9999999999976p-4", 14, "0.1"}, + {"0x1.fffffffffffd2p-1", 14, "0.99999999999999"}, + {"0x1.fffffffffffd3p-1", 14, "1"}, + {"0x1.3ffffffffffe3p+3", 14, "9.9999999999999"}, + {"0x1.3ffffffffffe4p+3", 14, "10"}, + {"0x1.8ffffffffffdcp+6", 14, "99.999999999999"}, + {"0x1.8ffffffffffddp+6", 14, "100"}, + {"0x1.f3fffffffffd4p+9", 14, "999.99999999999"}, + {"0x1.f3fffffffffd5p+9", 14, "1000"}, + {"0x1.387ffffffffe4p+13", 14, "9999.9999999999"}, + {"0x1.387ffffffffe5p+13", 14, "10000"}, + {"0x1.869ffffffffddp+16", 14, "99999.999999999"}, + {"0x1.869ffffffffdep+16", 14, "100000"}, + {"0x1.e847fffffffd5p+19", 14, "999999.99999999"}, + {"0x1.e847fffffffd6p+19", 14, "1000000"}, + {"0x1.312cfffffffe5p+23", 14, "9999999.9999999"}, + {"0x1.312cfffffffe6p+23", 14, "10000000"}, + {"0x1.7d783ffffffdep+26", 14, "99999999.999999"}, + {"0x1.7d783ffffffdfp+26", 14, "100000000"}, + {"0x1.dcd64ffffffd6p+29", 14, "999999999.99999"}, + {"0x1.dcd64ffffffd7p+29", 14, "1000000000"}, + {"0x1.2a05f1fffffe5p+33", 14, "9999999999.9999"}, + {"0x1.2a05f1fffffe6p+33", 14, "10000000000"}, + {"0x1.74876e7ffffdfp+36", 14, "99999999999.999"}, + {"0x1.74876e7ffffe0p+36", 14, "100000000000"}, + {"0x1.d1a94a1ffffd7p+39", 14, "999999999999.99"}, + {"0x1.d1a94a1ffffd8p+39", 14, "1000000000000"}, + {"0x1.2309ce53fffe6p+43", 14, "9999999999999.9"}, + {"0x1.2309ce53fffe7p+43", 14, "10000000000000"}, + {"0x1.6bcc41e8fffdfp+46", 14, "99999999999999"}, + {"0x1.6bcc41e8fffe0p+46", 14, "1e+14"}, + {"0x1.a36e2eb1c4328p-14", 15, "9.99999999999999e-5"}, + {"0x1.a36e2eb1c4329p-14", 15, "0.0001"}, + {"0x1.0624dd2f1a9f9p-10", 15, "0.000999999999999999"}, + {"0x1.0624dd2f1a9fap-10", 15, "0.001"}, + {"0x1.47ae147ae1477p-7", 15, "0.00999999999999999"}, + {"0x1.47ae147ae1478p-7", 15, "0.01"}, + {"0x1.9999999999995p-4", 15, "0.0999999999999999"}, + {"0x1.9999999999996p-4", 15, "0.1"}, + {"0x1.ffffffffffffbp-1", 15, "0.999999999999999"}, + {"0x1.ffffffffffffcp-1", 15, "1"}, + {"0x1.3fffffffffffdp+3", 15, "9.99999999999999"}, + {"0x1.3fffffffffffep+3", 15, "10"}, + {"0x1.8fffffffffffcp+6", 15, "99.9999999999999"}, + {"0x1.8fffffffffffdp+6", 15, "100"}, + {"0x1.f3ffffffffffbp+9", 15, "999.999999999999"}, + {"0x1.f3ffffffffffcp+9", 15, "1000"}, + {"0x1.387fffffffffdp+13", 15, "9999.99999999999"}, + {"0x1.387fffffffffep+13", 15, "10000"}, + {"0x1.869fffffffffcp+16", 15, "99999.9999999999"}, + {"0x1.869fffffffffdp+16", 15, "100000"}, + {"0x1.e847ffffffffbp+19", 15, "999999.999999999"}, + {"0x1.e847ffffffffcp+19", 15, "1000000"}, + {"0x1.312cffffffffdp+23", 15, "9999999.99999999"}, + {"0x1.312cffffffffep+23", 15, "10000000"}, + {"0x1.7d783fffffffcp+26", 15, "99999999.9999999"}, + {"0x1.7d783fffffffdp+26", 15, "100000000"}, + {"0x1.dcd64fffffffbp+29", 15, "999999999.999999"}, + {"0x1.dcd64fffffffcp+29", 15, "1000000000"}, + {"0x1.2a05f1ffffffdp+33", 15, "9999999999.99999"}, + {"0x1.2a05f1ffffffep+33", 15, "10000000000"}, + {"0x1.74876e7fffffcp+36", 15, "99999999999.9999"}, + {"0x1.74876e7fffffdp+36", 15, "100000000000"}, + {"0x1.d1a94a1fffffbp+39", 15, "999999999999.999"}, + {"0x1.d1a94a1fffffcp+39", 15, "1000000000000"}, + {"0x1.2309ce53ffffdp+43", 15, "9999999999999.99"}, + {"0x1.2309ce53ffffep+43", 15, "10000000000000"}, + {"0x1.6bcc41e8ffffcp+46", 15, "99999999999999.9"}, + {"0x1.6bcc41e8ffffdp+46", 15, "100000000000000"}, + {"0x1.c6bf52633fffbp+49", 15, "999999999999999"}, + {"0x1.c6bf52633fffcp+49", 15, "1e+15"}, + {"0x1.1c37937e07fffp+53", 16, "9999999999999998"}, + {"0x1.1c37937e08000p+53", 16, "1e+16"}, + {"0x1.6345785d89fffp+56", 17, "99999999999999984"}, + {"0x1.6345785d8a000p+56", 17, "1e+17"}, + {"0x1.bc16d674ec7ffp+59", 18, "999999999999999872"}, + {"0x1.bc16d674ec800p+59", 18, "1e+18"}, + {"0x1.158e460913cffp+63", 19, "9999999999999997952"}, + {"0x1.158e460913d00p+63", 19, "1e+19"}, + {"0x1.5af1d78b58c3fp+66", 20, "99999999999999983616"}, + {"0x1.5af1d78b58c40p+66", 20, "1e+20"}, + {"0x1.b1ae4d6e2ef4fp+69", 21, "999999999999999868928"}, + {"0x1.b1ae4d6e2ef50p+69", 21, "1e+21"}, + {"0x1.0f0cf064dd591p+73", 22, "9999999999999997902848"}, + {"0x1.0f0cf064dd592p+73", 22, "1e+22"}, + {"0x1.52d02c7e14af6p+76", 23, "99999999999999991611392"}, + {"0x1.52d02c7e14af7p+76", 23, "1.0000000000000000838861e+23"}, + {"0x1.a784379d99db4p+79", 24, "999999999999999983222784"}, + {"0x1.a784379d99db5p+79", 24, "1.00000000000000011744051e+24"}, + {"0x1.a36e2eb1c432cp-14", 25, "9.999999999999999123964645e-5"}, + {"0x1.a36e2eb1c432dp-14", 25, "0.0001000000000000000047921736"}, + {"0x1.0624dd2f1a9fbp-10", 25, "0.0009999999999999998039762472"}, + {"0x1.0624dd2f1a9fcp-10", 25, "0.001000000000000000020816682"}, + {"0x1.47ae147ae147ap-7", 25, "0.009999999999999998473443341"}, + {"0x1.47ae147ae147bp-7", 25, "0.01000000000000000020816682"}, + {"0x1.9999999999999p-4", 25, "0.09999999999999999167332732"}, + {"0x1.999999999999ap-4", 25, "0.1000000000000000055511151"}, + {"0x1.fffffffffffffp-1", 25, "0.9999999999999998889776975"}, + {"0x1.0000000000000p+0", 25, "1"}, + {"0x1.3ffffffffffffp+3", 25, "9.999999999999998223643161"}, + {"0x1.4000000000000p+3", 25, "10"}, + {"0x1.8ffffffffffffp+6", 25, "99.99999999999998578914528"}, + {"0x1.9000000000000p+6", 25, "100"}, + {"0x1.f3fffffffffffp+9", 25, "999.9999999999998863131623"}, + {"0x1.f400000000000p+9", 25, "1000"}, + {"0x1.387ffffffffffp+13", 25, "9999.999999999998181010596"}, + {"0x1.3880000000000p+13", 25, "10000"}, + {"0x1.869ffffffffffp+16", 25, "99999.99999999998544808477"}, + {"0x1.86a0000000000p+16", 25, "100000"}, + {"0x1.e847fffffffffp+19", 25, "999999.9999999998835846782"}, + {"0x1.e848000000000p+19", 25, "1000000"}, + {"0x1.312cfffffffffp+23", 25, "9999999.999999998137354851"}, + {"0x1.312d000000000p+23", 25, "10000000"}, + {"0x1.7d783ffffffffp+26", 25, "99999999.99999998509883881"}, + {"0x1.7d78400000000p+26", 25, "100000000"}, + {"0x1.dcd64ffffffffp+29", 25, "999999999.9999998807907104"}, + {"0x1.dcd6500000000p+29", 25, "1000000000"}, + {"0x1.2a05f1fffffffp+33", 25, "9999999999.999998092651367"}, + {"0x1.2a05f20000000p+33", 25, "10000000000"}, + {"0x1.74876e7ffffffp+36", 25, "99999999999.99998474121094"}, + {"0x1.74876e8000000p+36", 25, "100000000000"}, + {"0x1.d1a94a1ffffffp+39", 25, "999999999999.9998779296875"}, + {"0x1.d1a94a2000000p+39", 25, "1000000000000"}, + {"0x1.2309ce53fffffp+43", 25, "9999999999999.998046875"}, + {"0x1.2309ce5400000p+43", 25, "10000000000000"}, + {"0x1.6bcc41e8fffffp+46", 25, "99999999999999.984375"}, + {"0x1.6bcc41e900000p+46", 25, "100000000000000"}, + {"0x1.c6bf52633ffffp+49", 25, "999999999999999.875"}, + {"0x1.c6bf526340000p+49", 25, "1000000000000000"}, + {"0x1.1c37937e07fffp+53", 25, "9999999999999998"}, + {"0x1.1c37937e08000p+53", 25, "10000000000000000"}, + {"0x1.6345785d89fffp+56", 25, "99999999999999984"}, + {"0x1.6345785d8a000p+56", 25, "100000000000000000"}, + {"0x1.bc16d674ec7ffp+59", 25, "999999999999999872"}, + {"0x1.bc16d674ec800p+59", 25, "1000000000000000000"}, + {"0x1.158e460913cffp+63", 25, "9999999999999997952"}, + {"0x1.158e460913d00p+63", 25, "10000000000000000000"}, + {"0x1.5af1d78b58c3fp+66", 25, "99999999999999983616"}, + {"0x1.5af1d78b58c40p+66", 25, "100000000000000000000"}, + {"0x1.b1ae4d6e2ef4fp+69", 25, "999999999999999868928"}, + {"0x1.b1ae4d6e2ef50p+69", 25, "1000000000000000000000"}, + {"0x1.0f0cf064dd591p+73", 25, "9999999999999997902848"}, + {"0x1.0f0cf064dd592p+73", 25, "10000000000000000000000"}, + {"0x1.52d02c7e14af6p+76", 25, "99999999999999991611392"}, + {"0x1.52d02c7e14af7p+76", 25, "100000000000000008388608"}, + {"0x1.a784379d99db4p+79", 25, "999999999999999983222784"}, + {"0x1.a784379d99db5p+79", 25, "1000000000000000117440512"}, + {"0x1.08b2a2c280290p+83", 25, "9999999999999998758486016"}, + {"0x1.08b2a2c280291p+83", 25, "1.000000000000000090596966e+25"}, + {"0x1.4adf4b7320334p+86", 26, "99999999999999987584860160"}, + {"0x1.4adf4b7320335p+86", 26, "1.0000000000000000476472934e+26"}, + {"0x1.9d971e4fe8401p+89", 27, "999999999999999875848601600"}, + {"0x1.9d971e4fe8402p+89", 27, "1.00000000000000001328755507e+27"}, + {"0x1.027e72f1f1281p+93", 28, "9999999999999999583119736832"}, + {"0x1.027e72f1f1282p+93", 28, "1.000000000000000178214299238e+28"}, + {"0x1.431e0fae6d721p+96", 29, "99999999999999991433150857216"}, + {"0x1.431e0fae6d722p+96", 29, "1.0000000000000000902533690163e+29"}, + {"0x1.93e5939a08ce9p+99", 30, "999999999999999879147136483328"}, + {"0x1.93e5939a08ceap+99", 30, "1.00000000000000001988462483866e+30"}, + {"0x1.f8def8808b024p+102", 31, "9999999999999999635896294965248"}, + {"0x1.f8def8808b025p+102", 31, "1.000000000000000076179620180787e+31"}, + {"0x1.3b8b5b5056e16p+106", 32, "99999999999999987351763694911488"}, + {"0x1.3b8b5b5056e17p+106", 32, "1.0000000000000000536616220439347e+32"}, + {"0x1.8a6e32246c99cp+109", 33, "999999999999999945575230987042816"}, + {"0x1.8a6e32246c99dp+109", 33, "1.00000000000000008969041906289869e+33"}, + {"0x1.ed09bead87c03p+112", 34, "9999999999999999455752309870428160"}, + {"0x1.ed09bead87c04p+112", 34, "1.000000000000000060867381447727514e+34"}, + {"0x1.3426172c74d82p+116", 35, "99999999999999996863366107917975552"}, + {"0x1.3426172c74d83p+116", 35, "1.0000000000000001531011018162752717e+35"}, + {"0x1.812f9cf7920e2p+119", 36, "999999999999999894846684784341549056"}, + {"0x1.812f9cf7920e3p+119", 36, "1.00000000000000004242063737401796198e+36"}, + {"0x1.e17b84357691bp+122", 37, "9999999999999999538762658202121142272"}, + {"0x1.e17b84357691cp+122", 37, "1.00000000000000007193542789195324457e+37"}, + {"0x1.2ced32a16a1b1p+126", 38, "99999999999999997748809823456034029568"}, + {"0x1.2ced32a16a1b2p+126", 38, "1.0000000000000001663827575493461488435e+38"}, + {"0x1.78287f49c4a1dp+129", 39, "999999999999999939709166371603178586112"}, + {"0x1.78287f49c4a1ep+129", 39, "1.00000000000000009082489382343182542438e+39"}, + {"0x1.d6329f1c35ca4p+132", 40, "9999999999999999094860208812374492184576"}, + {"0x1.d6329f1c35ca5p+132", 40, "1.000000000000000030378602842700366689075e+40"}, + {"0x1.25dfa371a19e6p+136", 41, "99999999999999981277195531206711524196352"}, + {"0x1.25dfa371a19e7p+136", 41, "1.0000000000000000062000864504077831949517e+41"}, + {"0x1.6f578c4e0a060p+139", 42, "999999999999999890143207767403382423158784"}, + {"0x1.6f578c4e0a061p+139", 42, "1.00000000000000004488571267807591678554931e+42"}, + {"0x1.cb2d6f618c878p+142", 43, "9999999999999998901432077674033824231587840"}, + {"0x1.cb2d6f618c879p+142", 43, "1.000000000000000013937211695941409913071206e+43"}, + {"0x1.1efc659cf7d4bp+146", 44, "99999999999999989014320776740338242315878400"}, + {"0x1.1efc659cf7d4cp+146", 44, "1.0000000000000000882136140530642264070186598e+44"}, + {"0x1.66bb7f0435c9ep+149", 45, "999999999999999929757289024535551219930759168"}, + {"0x1.66bb7f0435c9fp+149", 45, "1.00000000000000008821361405306422640701865984e+45"}, + {"0x1.c06a5ec5433c6p+152", 46, "9999999999999999931398190359470212947659194368"}, + {"0x1.c06a5ec5433c7p+152", 46, "1.000000000000000119904879058769961444436239974e+46"}, + {"0x1.18427b3b4a05bp+156", 47, "99999999999999984102174700855949311516153479168"}, + {"0x1.18427b3b4a05cp+156", 47, "1.0000000000000000438458430450761973546340476518e+47"}, + {"0x1.5e531a0a1c872p+159", 48, "999999999999999881586566215862833963056037363712"}, + {"0x1.5e531a0a1c873p+159", 48, "1.00000000000000004384584304507619735463404765184e+48"}, + {"0x1.b5e7e08ca3a8fp+162", 49, "9999999999999999464902769475481793196872414789632"}, + {"0x1.b5e7e08ca3a90p+162", 49, "1.000000000000000076297698410918870032949649709466e+49"}, + {"0x1.11b0ec57e6499p+166", 50, "99999999999999986860582406952576489172979654066176"}, + {"0x1.11b0ec57e649ap+166", 50, "1.0000000000000000762976984109188700329496497094656e+50"}, + {"0x1.561d276ddfdc0p+169", 51, "999999999999999993220948674361627976461708441944064"}, + {"0x1.561d276ddfdc1p+169", 51, "1.00000000000000015937444814747611208943759097698714e+51"}, + {"0x1.aba4714957d30p+172", 52, "9999999999999999932209486743616279764617084419440640"}, + {"0x1.aba4714957d31p+172", 52, "1.000000000000000126143748252853215266842414469978522e+52"}, + {"0x1.0b46c6cdd6e3ep+176", 53, "99999999999999999322094867436162797646170844194406400"}, + {"0x1.0b46c6cdd6e3fp+176", 53, "1.0000000000000002058974279999481676410708380867991962e+53"}, + {"0x1.4e1878814c9cdp+179", 54, "999999999999999908150356944127012110618056584002011136"}, + {"0x1.4e1878814c9cep+179", 54, "1.00000000000000007829154040459624384230536029988611686e+54"}, + {"0x1.a19e96a19fc40p+182", 55, "9999999999999998741221202520331657642805958408251899904"}, + {"0x1.a19e96a19fc41p+182", 55, "1.000000000000000010235067020408551149630438813532474573e+55"}, + {"0x1.05031e2503da8p+186", 56, "99999999999999987412212025203316576428059584082518999040"}, + {"0x1.05031e2503da9p+186", 56, "1.0000000000000000919028350814337823808403445971568453222e+56"}, + {"0x1.4643e5ae44d12p+189", 57, "999999999999999874122120252033165764280595840825189990400"}, + {"0x1.4643e5ae44d13p+189", 57, "1.00000000000000004834669211555365905752839484589051425587e+57"}, + {"0x1.97d4df19d6057p+192", 58, "9999999999999999438119489974413630815797154428513196965888"}, + {"0x1.97d4df19d6058p+192", 58, "1.000000000000000083191606488257757716177954646903579108966e+58"}, + {"0x1.fdca16e04b86dp+195", 59, "99999999999999997168788049560464200849936328366177157906432"}, + {"0x1.fdca16e04b86ep+195", 59, "1.0000000000000000831916064882577577161779546469035791089664e+59"}, + {"0x1.3e9e4e4c2f344p+199", 60, "999999999999999949387135297074018866963645011013410073083904"}, + {"0x1.3e9e4e4c2f345p+199", 60, "1.00000000000000012779309688531900399924939119220030212092723e+60"}, + {"0x1.8e45e1df3b015p+202", 61, "9999999999999999493871352970740188669636450110134100730839040"}, + {"0x1.8e45e1df3b016p+202", 61, "1.000000000000000092111904567670006972792241955962923711358566e+61"}, + {"0x1.f1d75a5709c1ap+205", 62, "99999999999999992084218144295482124579792562202350734542897152"}, + {"0x1.f1d75a5709c1bp+205", 62, "1.0000000000000000350219968594316117304608031779831182560487014e+62"}, + {"0x1.3726987666190p+209", 63, "999999999999999875170255276364105051932774599639662981181079552"}, + {"0x1.3726987666191p+209", 63, "1.00000000000000005785795994272696982739337868917504043817264742e+63"}, + {"0x1.84f03e93ff9f4p+212", 64, "9999999999999998751702552763641050519327745996396629811810795520"}, + {"0x1.84f03e93ff9f5p+212", 64, "1.00000000000000002132041900945439687230125787126796494677433385e+64"}, + {"0x1.e62c4e38ff872p+215", 65, "99999999999999999209038626283633850822756121694230455365568299008"}, + {"0x1.e62c4e38ff873p+215", 65, "1.0000000000000001090105172493085719645223478342449461261302864282e+65"}, + {"0x1.2fdbb0e39fb47p+219", 66, "999999999999999945322333868247445125709646570021247924665841614848"}, + {"0x1.2fdbb0e39fb48p+219", 66, "1.00000000000000013239454344660301865578130515770547444062520711578e+66"}, + {"0x1.7bd29d1c87a19p+222", 67, "9999999999999999827367757839185598317239782875580932278577147150336"}, + {"0x1.7bd29d1c87a1ap+222", 67, "1.000000000000000132394543446603018655781305157705474440625207115776e+67"}, + {"0x1.dac74463a989fp+225", 68, "99999999999999995280522225138166806691251291352861698530421623488512"}, + {"0x1.dac74463a98a0p+225", 68, "1.000000000000000072531436381529235126158374409646521955518210155479e+68"}, + {"0x1.28bc8abe49f63p+229", 69, "999999999999999880969493773293127831364996015857874003175819882528768"}, + {"0x1.28bc8abe49f64p+229", 69, "1.00000000000000007253143638152923512615837440964652195551821015547904e+69"}, + {"0x1.72ebad6ddc73cp+232", 70, "9999999999999999192818822949403492903236716946156035936442979371188224"}, + {"0x1.72ebad6ddc73dp+232", 70, "1.00000000000000007253143638152923512615837440964652195551821015547904e+70"}, + {"0x1.cfa698c95390bp+235", 71, "99999999999999991928188229494034929032367169461560359364429793711882240"}, + {"0x1.cfa698c95390cp+235", 71, "1.0000000000000000418815255642114579589914338666403382831434277118069965e+71"}, + {"0x1.21c81f7dd43a7p+239", 72, "999999999999999943801810948794571024057224129020550531544123892056457216"}, + {"0x1.21c81f7dd43a8p+239", 72, "1.00000000000000013996124017962834489392564360426012603474273153155753574e+72"}, + {"0x1.6a3a275d49491p+242", 73, "9999999999999999830336967949613257980309080240684656321838454199566729216"}, + {"0x1.6a3a275d49492p+242", 73, "1.000000000000000139961240179628344893925643604260126034742731531557535744e+73"}, + {"0x1.c4c8b1349b9b5p+245", 74, "99999999999999995164818811802792197885196090803013355167206819763650035712"}, + {"0x1.c4c8b1349b9b6p+245", 74, "1.000000000000000077190222825761537255567749372183461873719177086917190615e+74"}, + {"0x1.1afd6ec0e1411p+249", 75, "999999999999999926539781176481198923508803215199467887262646419780362305536"}, + {"0x1.1afd6ec0e1412p+249", 75, "1.00000000000000012740703670885498336625406475784479320253802064262946671821e+75"}, + {"0x1.61bcca7119915p+252", 76, "9999999999999998863663300700064420349597509066704028242075715752105414230016"}, + {"0x1.61bcca7119916p+252", 76, "1.000000000000000047060134495905469589155960140786663076427870953489824953139e+76"}, + {"0x1.ba2bfd0d5ff5bp+255", 77, "99999999999999998278261272554585856747747644714015897553975120217811154108416"}, + {"0x1.ba2bfd0d5ff5cp+255", 77, "1.0000000000000001113376562662650806108344438344331671773159907048015383651942e+77"}, + {"0x1.145b7e285bf98p+259", 78, "999999999999999802805551768538947706777722104929947493053015898505313987330048"}, + {"0x1.145b7e285bf99p+259", 78, "1.00000000000000000849362143368970297614886992459876061589499910270279690590618e+78"}, + {"0x1.59725db272f7fp+262", 79, "9999999999999999673560075006595519222746403606649979913266024618633003221909504"}, + {"0x1.59725db272f80p+262", 79, "1.000000000000000131906463232780156137771558616400048489600189025221286657051853e+79"}, + {"0x1.afcef51f0fb5ep+265", 80, "99999999999999986862573406138718939297648940722396769236245052384850852127440896"}, + {"0x1.afcef51f0fb5fp+265", 80, "1.0000000000000000002660986470836727653740240118120080909813197745348975891631309e+80"}, + {"0x1.0de1593369d1bp+269", 81, "999999999999999921281879895665782741935503249059183851809998224123064148429897728"}, + {"0x1.0de1593369d1cp+269", 81, "1.0000000000000001319064632327801561377715586164000484896001890252212866570518528e+81"}, + {"0x1.5159af8044462p+272", 82, "9999999999999999634067965630886574211027143225273567793680363843427086501542887424"}, + {"0x1.5159af8044463p+272", 82, "1.0000000000000001319064632327801561377715586164000484896001890252212866570518528e+82"}, + {"0x1.a5b01b605557ap+275", 83, "99999999999999989600692989521205793443517660497828009527517532799127744739526311936"}, + {"0x1.a5b01b605557bp+275", 83, "1.0000000000000000308066632309652569077702520400764334634608974406941398529133143654e+83"}, + {"0x1.078e111c3556cp+279", 84, "999999999999999842087036560910778345101146430939018748000886482910132485188042620928"}, + {"0x1.078e111c3556dp+279", 84, "1.00000000000000005776660989811589670243726712709606413709804186323471233401692461466e+84"}, + {"0x1.4971956342ac7p+282", 85, "9999999999999998420870365609107783451011464309390187480008864829101324851880426209280"}, + {"0x1.4971956342ac8p+282", 85, "1.00000000000000001463069523067487303097004298786465505927861078716979636425114821591e+85"}, + {"0x1.9bcdfabc13579p+285", 86, "99999999999999987659576829486359728227492574232414601025643134376206526100066373992448"}, + {"0x1.9bcdfabc1357ap+285", 86, "1.0000000000000000146306952306748730309700429878646550592786107871697963642511482159104e+86"}, + {"0x1.0160bcb58c16cp+289", 87, "999999999999999959416724456350362731491996089648451439669739009806703922950954425516032"}, + {"0x1.0160bcb58c16dp+289", 87, "1.0000000000000001802726075536484039294041836825132659181052261192590736881517295870935e+87"}, + {"0x1.41b8ebe2ef1c7p+292", 88, "9999999999999999594167244563503627314919960896484514396697390098067039229509544255160320"}, + {"0x1.41b8ebe2ef1c8p+292", 88, "1.00000000000000013610143093418879568982174616394030302241812869736859973511157455477801e+88"}, + {"0x1.922726dbaae39p+295", 89, "99999999999999999475366575191804932315794610450682175621941694731908308538307845136842752"}, + {"0x1.922726dbaae3ap+295", 89, "1.0000000000000001361014309341887956898217461639403030224181286973685997351115745547780096e+89"}, + {"0x1.f6b0f092959c7p+298", 90, "999999999999999966484112715463900049825186092620125502979674597309179755437379230686511104"}, + {"0x1.f6b0f092959c8p+298", 90, "1.00000000000000007956232486128049714315622614016691051593864399734879307522017611341417677e+90"}, + {"0x1.3a2e965b9d81cp+302", 91, "9999999999999998986371854279739417938265620640920544952042929572854117635677011010499117056"}, + {"0x1.3a2e965b9d81dp+302", 91, "1.000000000000000079562324861280497143156226140166910515938643997348793075220176113414176768e+91"}, + {"0x1.88ba3bf284e23p+305", 92, "99999999999999989863718542797394179382656206409205449520429295728541176356770110104991170560"}, + {"0x1.88ba3bf284e24p+305", 92, "1.0000000000000000433772969746191860732902933249519393117917737893361168128896811109413237555e+92"}, + {"0x1.eae8caef261acp+308", 93, "999999999999999927585207737302990649719308316264031458521789123695552773432097103028194115584"}, + {"0x1.eae8caef261adp+308", 93, "1.00000000000000004337729697461918607329029332495193931179177378933611681288968111094132375552e+93"}, + {"0x1.32d17ed577d0bp+312", 94, "9999999999999998349515363474500343108625203093137051759058013911831015418660298966976904036352"}, + {"0x1.32d17ed577d0cp+312", 94, "1.000000000000000020218879127155946988576096323214357741137776856208004004998164309358697827533e+94"}, + {"0x1.7f85de8ad5c4ep+315", 95, "99999999999999987200500490339121684640523551209383568895219648418808203449245677922989188841472"}, + {"0x1.7f85de8ad5c4fp+315", 95, "1.0000000000000000202188791271559469885760963232143577411377768562080040049981643093586978275328e+95"}, + {"0x1.df67562d8b362p+318", 96, "999999999999999931290554592897108903273579836542044509826428632996050822694739791281414264061952"}, + {"0x1.df67562d8b363p+318", 96, "1.00000000000000004986165397190889301701026848543846215157489293061198839909930581538445901535642e+96"}, + {"0x1.2ba095dc7701dp+322", 97, "9999999999999998838621148412923952577789043769834774531270429139496757921329133816401963635441664"}, + {"0x1.2ba095dc7701ep+322", 97, "1.000000000000000073575873847711249839757606215217745679924585790135175914380219020205067965615309e+97"}, + {"0x1.7688bb5394c25p+325", 98, "99999999999999999769037024514370800696612547992403838920556863966097586548129676477911932478685184"}, + {"0x1.7688bb5394c26p+325", 98, "1.0000000000000001494613774502787916725490869505114529706436029406093759632791412756310166064437658e+98"}, + {"0x1.d42aea2879f2ep+328", 99, "999999999999999967336168804116691273849533185806555472917961779471295845921727862608739868455469056"}, + {"0x1.d42aea2879f2fp+328", 99, "1.00000000000000008875297456822475820631590236227648713806838922023001592416000347129025769378100019e+99"}, + {"0x1.249ad2594c37cp+332", 100, "9999999999999998216360018871870109548898901740426374747374488505608317520357971321909184780648316928"}, + {"0x1.249ad2594c37dp+332", 100, "1.00000000000000001590289110975991804683608085639452813897813275577478387721703810608134699858568151e+100"}, + {"0x1.6dc186ef9f45cp+335", 101, "99999999999999997704951326524533662844684271992415000612999597473199345218078991130326129448151154688"}, + {"0x1.6dc186ef9f45dp+335", 101, "1.000000000000000132463024643303662302003795265805662537522543098903155152325782690415604110898191401e+101"}, + {"0x1.c931e8ab87173p+338", 102, "999999999999999977049513265245336628446842719924150006129995974731993452180789911303261294481511546880"}, + {"0x1.c931e8ab87174p+338", 102, "1.00000000000000010138032236769199716729240475662936003124403367406892281229678413459313554761485543014e+102"}, + {"0x1.1dbf316b346e7p+342", 103, "9999999999999998029863805218200118740630558685368559709703431956602923480183979986974373400948301103104"}, + {"0x1.1dbf316b346e8p+342", 103, "1.000000000000000001915675085734668736215955127265192011152803514599379324203988755961236145108180323533e+103"}, + {"0x1.652efdc6018a1p+345", 104, "99999999999999984277223943460294324649363572028252317900683525944810974325551615015019710109750015295488"}, + {"0x1.652efdc6018a2p+345", 104, "1.0000000000000000019156750857346687362159551272651920111528035145993793242039887559612361451081803235328e+104"}, + {"0x1.be7abd3781ecap+348", 105, "999999999999999938258300825281978540327027364472124478294416212538871491824599713636820527503908255301632"}, + {"0x1.be7abd3781ecbp+348", 105, "1.00000000000000006557304934618735893210488289005825954401119081665988715658337779828565176271245239176397e+105"}, + {"0x1.170cb642b133ep+352", 106, "9999999999999998873324014169198263836158851542376704520077063708904652259210884797772880334204906007166976"}, + {"0x1.170cb642b133fp+352", 106, "1.000000000000000091035999050368435010460453995175486557154545737484090289535133415215418009754161219056435e+106"}, + {"0x1.5ccfe3d35d80ep+355", 107, "99999999999999996881384047029926983435371269061279689406644211752791525136670645395254002395395884805259264"}, + {"0x1.5ccfe3d35d80fp+355", 107, "1.0000000000000001317767185770581567358293677633630497781839136108028153022579424023030440050208953427243827e+107"}, + {"0x1.b403dcc834e11p+358", 108, "999999999999999903628689227595715073763450661512695740419453520217955231010212074612338431527184250183876608"}, + {"0x1.b403dcc834e12p+358", 108, "1.00000000000000003399899171300282459494397471971289804771343071483787527172320083329274161638073344592130867e+108"}, + {"0x1.108269fd210cbp+362", 109, "9999999999999999818508707188399807864717650964328171247958398369899072554380053298205803424393137676263358464"}, + {"0x1.108269fd210ccp+362", 109, "1.000000000000000190443354695491356020360603589553140816466203348381779320578787343709225438204992480806227149e+109"}, + {"0x1.54a3047c694fdp+365", 110, "99999999999999985669538033284915564613846200056062290979362173015478401635353612148739328497990653971840106496"}, + {"0x1.54a3047c694fep+365", 110, "1.0000000000000000235693675141702558332495327950568818631299125392682816684661617325983093615924495102623141069e+110"}, + {"0x1.a9cbc59b83a3dp+368", 111, "999999999999999956819772641641815758405104477258378281795396215622882607621111488153942930947432322044748890112"}, + {"0x1.a9cbc59b83a3ep+368", 111, "1.00000000000000009031896238669869590809396111285538544446442886291368072931121197704267579223746669847987932365e+111"}, + {"0x1.0a1f5b8132466p+372", 112, "9999999999999999301199346926304397284673331501389768492615896861647229832830913903761963586894254467577228034048"}, + {"0x1.0a1f5b8132467p+372", 112, "1.000000000000000143718638284721447967969503767094188309532041921829999977987252172598168936753480449053931497062e+112"}, + {"0x1.4ca732617ed7fp+375", 113, "99999999999999984468045325579403643266646490335689226515340879189861218540142707748740732746380344583923932594176"}, + {"0x1.4ca732617ed80p+375", 113, "1.0000000000000000155594161294668430242682013969210614333697705804308337811647557032649853899150474476762062808678e+113"}, + {"0x1.9fd0fef9de8dfp+378", 114, "999999999999999878856245830528597750986812202069726098796681149605056504554092802642922939954052246206632716926976"}, + {"0x1.9fd0fef9de8e0p+378", 114, "1.00000000000000001555941612946684302426820139692106143336977058043083378116475570326498538991504744767620628086784e+114"}, + {"0x1.03e29f5c2b18bp+382", 115, "9999999999999997968343436511656505870179786851589248980528274911095901385876950622696854699774551253248885785624576"}, + {"0x1.03e29f5c2b18cp+382", 115, "1.00000000000000001555941612946684302426820139692106143336977058043083378116475570326498538991504744767620628086784e+115"}, + {"0x1.44db473335deep+385", 116, "99999999999999984057935814682588907446802322751135220511621610897383886710310719046874545396497358979515211902353408"}, + {"0x1.44db473335defp+385", 116, "1.00000000000000001555941612946684302426820139692106143336977058043083378116475570326498538991504744767620628086784e+116"}, + {"0x1.961219000356ap+388", 117, "999999999999999910571381339882270654388094495275235896417637897556636832727766595587241428345003132947573783761256448"}, + {"0x1.961219000356bp+388", 117, "1.00000000000000005055542772599503381422823703080300327902048147472223276397708540582423337710506221925241711323670118e+117"}, + {"0x1.fb969f40042c5p+391", 118, "9999999999999999665649998943273759183241515094863428494587753284228752052274941196820382078490267674695111155514343424"}, + {"0x1.fb969f40042c6p+391", 118, "1.000000000000000078552237003217586446196265537908556755541050190155351950226949167871631766857074036513385779131790131e+118"}, + {"0x1.3d3e2388029bbp+395", 119, "99999999999999994416755247254933381274972870380190006824232035607637985622760311004411949604741731366073618283536318464"}, + {"0x1.3d3e2388029bcp+395", 119, "1.0000000000000001233471318467736706573451111492774423179739601348483426482267311871474691904602929441309356445639324467e+119"}, + {"0x1.8c8dac6a0342ap+398", 120, "999999999999999980003468347394201181668805192897008518188648311830772414627428725464789434929992439754776075181077037056"}, + {"0x1.8c8dac6a0342bp+398", 120, "1.00000000000000012334713184677367065734511114927744231797396013484834264822673118714746919046029294413093564456393244672e+120"}, + {"0x1.efb1178484134p+401", 121, "9999999999999999226660029476424133913982828103448349982745235826237443211877077407917175327178722380043122474279348731904"}, + {"0x1.efb1178484135p+401", 121, "1.000000000000000037340933747145988971939327575449182038102773041037800508067149710137861337142112641505239902934219200922e+121"}, + {"0x1.35ceaeb2d28c0p+405", 122, "99999999999999983092605830803955292696544699826135736641192401589249937168415416531480248917847991520357012302290741100544"}, + {"0x1.35ceaeb2d28c1p+405", 122, "1.0000000000000000144059475872452738558311186224283126301371231493549892706912613162686325762572645608050543718329623353754e+122"}, + {"0x1.83425a5f872f1p+408", 123, "999999999999999977709969731404129670057984297594921577392083322662491290889839886077866558841507631684757522070951350501376"}, + {"0x1.83425a5f872f2p+408", 123, "1.00000000000000012449388115476870641315052159692848578837224262943248321009552560684093062850453534816594492111899528999731e+123"}, + {"0x1.e412f0f768fadp+411", 124, "9999999999999999483531874467312143214394768377282087351960514613084929070487027419252537449089020883885200422613425626021888"}, + {"0x1.e412f0f768faep+411", 124, "1.000000000000000065780316585422875715913506677195060103980178906724486442413251318535705000639324261573469961499777714198938e+124"}, + {"0x1.2e8bd69aa19ccp+415", 125, "99999999999999992486776161899288204254467086983483846143922597222529419997579302660316349376281765375153005841365553228283904"}, + {"0x1.2e8bd69aa19cdp+415", 125, "1.0000000000000001127511682408995402737031186129818006514938298848908838565590707491798855029314931308474499291951517748376371e+125"}, + {"0x1.7a2ecc414a03fp+418", 126, "999999999999999924867761618992882042544670869834838461439225972225294199975793026603163493762817653751530058413655532282839040"}, + {"0x1.7a2ecc414a040p+418", 126, "1.0000000000000000751744869165182086274714290643524082134829091023577659252424152046645411010977580354282659550388525263266775e+126"}, + {"0x1.d8ba7f519c84fp+421", 127, "9999999999999999549291066784979473595300225087383524118479625982517885450291174622154390152298057300868772377386949310916067328"}, + {"0x1.d8ba7f519c850p+421", 127, "1.000000000000000075174486916518208627471429064352408213482909102357765925242415204664541101097758035428265955038852526326677504e+127"}, + {"0x1.27748f9301d31p+425", 128, "99999999999999988278187853568579059876517857536991893086699469578820211690113881674597776370903434688204400735860037395056427008"}, + {"0x1.27748f9301d32p+425", 128, "1.000000000000000075174486916518208627471429064352408213482909102357765925242415204664541101097758035428265955038852526326677504e+128"}, + {"0x1.7151b377c247ep+428", 129, "999999999999999998217443564185241415988928868759412500436543339729940401905904649497115766142268560009777175966751665376232210432"}, + {"0x1.7151b377c247fp+428", 129, "1.00000000000000015213153026885117583895392925994540392652927486498559144857892575983196643605324751084675473411095338727712279757e+129"}, + {"0x1.cda62055b2d9dp+431", 130, "9999999999999999366518088823188676468029287122850159299994507296276799832366962053631754981778769796749861527090709766158759755776"}, + {"0x1.cda62055b2d9ep+431", 130, "1.000000000000000059783078246051615185174929025233809070873635949832200820575113093631056034106660140344568199224432354136588445286e+130"}, + {"0x1.2087d4358fc82p+435", 131, "99999999999999991202555500957231813912852864969525730182461368558677581576901282770959939099212034754106974340599870111173348163584"}, + {"0x1.2087d4358fc83p+435", 131, "1.0000000000000001090355859915447142005237291504133263272233100379140091555104798489382082484781734046124010178305769051448734331699e+131"}, + {"0x1.68a9c942f3ba3p+438", 132, "999999999999999990829567402361276563686608849982484911984092226517669151665599636201042933986541570369602253175829982724989462249472"}, + {"0x1.68a9c942f3ba4p+438", 132, "1.00000000000000014843759218793919341280276925055694013230304930837945582345877325318393001997538401602666727271549254595150142347674e+132"}, + {"0x1.c2d43b93b0a8bp+441", 133, "9999999999999998962647525310145264542169126096378117797927179774005971485896954660113106823932361029753632414520324447890822855131136"}, + {"0x1.c2d43b93b0a8cp+441", 133, "1.000000000000000022351172359476859933509840930097375956047883642890026486024234359597620351184310059501015257083762495370291854494925e+133"}, + {"0x1.19c4a53c4e697p+445", 134, "99999999999999992148203649670699315007549827372972461504375111049848301607660324472857261615145089428049364457837845490532419930947584"}, + {"0x1.19c4a53c4e698p+445", 134, "1.0000000000000001232203082222467267169441835864650272970520161752815699559718654744666680862171692247215368695891465358352595096803738e+134"}, + {"0x1.6035ce8b6203dp+448", 135, "999999999999999961829690841814939863449235336276785151445404123455100404055655690676191710164594560368702289580532071091311261383655424"}, + {"0x1.6035ce8b6203ep+448", 135, "1.00000000000000012322030822224672671694418358646502729705201617528156995597186547446666808621716922472153686958914653583525950968037376e+135"}, + {"0x1.b843422e3a84cp+451", 136, "9999999999999999295515673657285824927502456862391367223240817130898064936724137339180964349540796274981353735788091781425216117243117568"}, + {"0x1.b843422e3a84dp+451", 136, "1.000000000000000058664061270074011975546204286389730438809371354550982135205381560950477535796139358980403037585700749937680210361686426e+136"}, + {"0x1.132a095ce492fp+455", 137, "99999999999999982626157224225223890651347880611866174913584999992086598044603947229219155428043184231232124237329592070639473281441202176"}, + {"0x1.132a095ce4930p+455", 137, "1.0000000000000000328415624892049260789870125663596116955123134262587470068987879955440013156277274126839495047843224355786484906342114918e+137"}, + {"0x1.57f48bb41db7bp+458", 138, "999999999999999867577570291642776341008185558166851738411142685188442185736589176942553506549890956386646894855501223680845484378371915776"}, + {"0x1.57f48bb41db7cp+458", 138, "1.00000000000000003284156248920492607898701256635961169551231342625874700689878799554400131562772741268394950478432243557864849063421149184e+138"}, + {"0x1.adf1aea12525ap+461", 139, "9999999999999999006303687311552062886039509598054037298313768334025031499690289406628430683654582476461074168412654660604060856295398309888"}, + {"0x1.adf1aea12525bp+461", 139, "1.00000000000000003284156248920492607898701256635961169551231342625874700689878799554400131562772741268394950478432243557864849063421149184e+139"}, + {"0x1.0cb70d24b7378p+465", 140, "99999999999999984774589122793531837245072631718372054355900219626000560719712531871037976946055058163097058166404267825310912362767116664832"}, + {"0x1.0cb70d24b7379p+465", 140, "1.0000000000000000592838012408148700370636248876704532886485007448299957782847398065202329650801812456915179223729338294822969716351458240102e+140"}, + {"0x1.4fe4d06de5056p+468", 141, "999999999999999847745891227935318372450726317183720543559002196260005607197125318710379769460550581630970581664042678253109123627671166648320"}, + {"0x1.4fe4d06de5057p+468", 141, "1.00000000000000001697621923823895970414104517357310673963060103511599774406721690895826232595625511287940845423115559923645940203365089253786e+141"}, + {"0x1.a3de04895e46cp+471", 142, "9999999999999999154380224320567749051268538597394750219876417318024024619451619548095327920588323941303457306908878466464492349900630570041344"}, + {"0x1.a3de04895e46dp+471", 142, "1.000000000000000050822284840299687970479108944850983978844920802887196171441235227007838837255396019129096028744578183433129457714846837715763e+142"}, + {"0x1.066ac2d5daec3p+475", 143, "99999999999999980713061250546244445284504979165026785650181847493456749434830333705088795590158149413134549224793557721710505681023603243483136"}, + {"0x1.066ac2d5daec4p+475", 143, "1.0000000000000000237454323586511053574086579278286821874734649886702374295420205725681776282160832941293459691338401160757934131698900815734374e+143"}, + {"0x1.4805738b51a74p+478", 144, "999999999999999850453576476100176633757771418885950722696147777681701481387046784154345890364481854130945587625116484988842728082166842262552576"}, + {"0x1.4805738b51a75p+478", 144, "1.00000000000000002374543235865110535740865792782868218747346498867023742954202057256817762821608329412934596913384011607579341316989008157343744e+144"}, + {"0x1.9a06d06e26112p+481", 145, "9999999999999999890870611821409196126784806260401358945180015464725302399110258148854112806457630061296658928320953898584032761523454337112604672"}, + {"0x1.9a06d06e26113p+481", 145, "1.000000000000000127720545888181662591599189833194321066339855315263358998435004845616476670927044158128386198039074294727963824222524025159968358e+145"}, + {"0x1.00444244d7cabp+485", 146, "99999999999999993363366729972462242111019694317846182578926003895619873650143420259298512453325054533017777074930382791057905692427399713177731072"}, + {"0x1.00444244d7cacp+485", 146, "1.0000000000000001554472428293898111873833316746251581007042260690215247501398006517626897489833003885281302590804700757018759338365597434497099366e+146"}, + {"0x1.405552d60dbd6p+488", 147, "999999999999999977996382405657660174364823889467801080772253244969263939229107492426926049423260513969768268415537077468838432306731146395363835904"}, + {"0x1.405552d60dbd7p+488", 147, "1.00000000000000015544724282938981118738333167462515810070422606902152475013980065176268974898330038852813025908047007570187593383655974344970993664e+147"}, + {"0x1.906aa78b912cbp+491", 148, "9999999999999999070160382361647997691574207754048582727994641153483596148648302286926205695992445641464234721495638781756234316947997075736253956096"}, + {"0x1.906aa78b912ccp+491", 148, "1.000000000000000048976726575150520579572227003530743888745042374590168263593384756161231529247276463793113064681510276762053432918662585217102276198e+148"}, + {"0x1.f485516e7577ep+494", 149, "99999999999999993540817590396194393124038202103003539598857976719672134461054113418634276152885094407576139065595315789290943193957228310232077172736"}, + {"0x1.f485516e7577fp+494", 149, "1.0000000000000000489767265751505205795722270035307438887450423745901682635933847561612315292472764637931130646815102767620534329186625852171022761984e+149"}, + {"0x1.38d352e5096afp+498", 150, "999999999999999980835596172437374590573120014030318793091164810154100112203678582976298268616221151962702060266176005440567032331208403948233373515776"}, + {"0x1.38d352e5096b0p+498", 150, "1.00000000000000016254527724633909722790407198603145238150150498198361518257622837813612029696570198351046473870706739563119743389775288733188378066944e+150"}, + {"0x1.8708279e4bc5ap+501", 151, "9999999999999998718097875280963410081745488308296386400449607070563910699801487058804050516065326530340444532016411713261887913912817139180431292235776"}, + {"0x1.8708279e4bc5bp+501", 151, "1.000000000000000017177532387217719118039310408430545510773232844520003126278188542008262674286117318272254595954354283478693112644517300624963454946509e+151"}, + {"0x1.e8ca3185deb71p+504", 152, "99999999999999992995688547174489225212045346187000138833626956204183589249936464033154810067836651912932851030272641618719051989257594860081125951275008"}, + {"0x1.e8ca3185deb72p+504", 152, "1.000000000000000046251081359041994740012262723950726884918887272012725537537796509233834198822034251319896624504896905909193976895164417966347520091095e+152"}, + {"0x1.317e5ef3ab327p+508", 153, "999999999999999999733403004123153744855539019118436686285840188024369679522423761672919759564567158443669378824028710020392594094129030220133015859757056"}, + {"0x1.317e5ef3ab328p+508", 153, "1.00000000000000018580411642379851772548243383844759748081802852397779311158391475191657751659443552994857836154750149357559812529827058120499103278510899e+153"}, + {"0x1.7dddf6b095ff0p+511", 154, "9999999999999998880909749523179353564794021275209402095665271864523156202855291675267251053466461355407239891899450398872692753716440996292182057045458944"}, + {"0x1.7dddf6b095ff1p+511", 154, "1.000000000000000036947545688058226540980917982984268845192277855215054365934721959721651310970540832744651175368723266731433700334957340417104619244827443e+154"}, + {"0x1.dd55745cbb7ecp+514", 155, "99999999999999988809097495231793535647940212752094020956652718645231562028552916752672510534664613554072398918994503988726927537164409962921820570454589440"}, + {"0x1.dd55745cbb7edp+514", 155, "1.0000000000000000071762315409101683040806148118916031180671277214625066168048834012826660698457618933038657381329676213626008153422946922595273365367711334e+155"}, + {"0x1.2a5568b9f52f4p+518", 156, "999999999999999983359180223191721714560372275017470536367007614460468417501012554531477876945938741751237388344363105067534507348164573733465510370326085632"}, + {"0x1.2a5568b9f52f5p+518", 156, "1.0000000000000001738955907649392944307223125700105311899679684704767740119319793285409834201445239541722641866531992354280649713012055219419601197018864681e+156"}, + {"0x1.74eac2e8727b1p+521", 157, "9999999999999999833591802231917217145603722750174705363670076144604684175010125545314778769459387417512373883443631050675345073481645737334655103703260856320"}, + {"0x1.74eac2e8727b2p+521", 157, "1.000000000000000135788308656589779887489924511011919059247776299273512893045785973739082311504806911688058826991432009355958878510597332300261197835574391603e+157"}, + {"0x1.d22573a28f19dp+524", 158, "99999999999999995287335453651211007997446182781858083179085387749785952239205787068995699003416510776387310061494932420984963311567802202010637287727642443776"}, + {"0x1.d22573a28f19ep+524", 158, "1.0000000000000000748166572832305566183181036166141396500954688253482951028278766060560405376812596437133302515326044476405891300456242288735429228494750692147e+158"}, + {"0x1.2357684599702p+528", 159, "999999999999999928484693987168420772305733470059469068129930887927772406304894123616740280504746200573981670431418299523701733729688780649419062882836695482368"}, + {"0x1.2357684599703p+528", 159, "1.0000000000000001235939783819179352336555603321323631774173148044884693350022041002024739567400974580931131118996664970128849288176027116149175428383545271255e+159"}, + {"0x1.6c2d4256ffcc2p+531", 160, "9999999999999998504409802292686149877658027252303114244149773213034936348259701329824468100106056975663290938441190205280284556945232082632196709006295628251136"}, + {"0x1.6c2d4256ffcc3p+531", 160, "1.000000000000000006528407745068226556845664214888626711844884454552051177783818114251033750998886703581634247018717578519375011764854353035618454865043828139622e+160"}, + {"0x1.c73892ecbfbf3p+534", 161, "99999999999999991287595123558845961539774732109363753938694017460291665200910932548988158640591809997245115511395844372456707812265566617217918448639526895091712"}, + {"0x1.c73892ecbfbf4p+534", 161, "1.0000000000000000377458932482281488706616365128202897693308658812017626863753877105047511391965429047846952776536372901176443229789205819900982116579266812025242e+161"}, + {"0x1.1c835bd3f7d78p+538", 162, "999999999999999937849939638116397466450525159438967985375725315922685858882365002492855496964043060934899979621894213003182527093908649335762989920701551401238528"}, + {"0x1.1c835bd3f7d79p+538", 162, "1.00000000000000013764184685833990027487274786620161155328600644648083951386841041851664678142904274863449057568538036723210611886393251464443343339515181100380979e+162"}, + {"0x1.63a432c8f5cd6p+541", 163, "9999999999999999378499396381163974664505251594389679853757253159226858588823650024928554969640430609348999796218942130031825270939086493357629899207015514012385280"}, + {"0x1.63a432c8f5cd7p+541", 163, "1.000000000000000097683465414295199713188303324849082839703950220369208782871201335311888524536042811094572456472683136386321400509927741582699344700261759083295539e+163"}, + {"0x1.bc8d3f7b3340bp+544", 164, "99999999999999987391652932764487656775541389327492204364443535414407668928683046936524228593524316087103098888157864364992697772750101243698844800887746832841572352"}, + {"0x1.bc8d3f7b3340cp+544", 164, "1.0000000000000000017833499485879183651456364256030139271070152777012950284778995356204687079928429609987689703622097823564380764603162862345375318325256344740613325e+164"}, + {"0x1.15d847ad00087p+548", 165, "999999999999999899489893451833484927233458399740540420336951338855520357125044282616287570346763120896578585177704871391229197474064067196498264773607101557544845312"}, + {"0x1.15d847ad00088p+548", 165, "1.00000000000000010407680644534235180305781445146548743387707921654706969983075478862464984563892280110095935554671469332164695544656850527257679889144416739057781965e+165"}, + {"0x1.5b4e5998400a9p+551", 166, "9999999999999999404072760505352583023983296100855298230449769143938302256661863838179600254051950569374547392515068357773127490685649548117139715971745147241514401792"}, + {"0x1.5b4e5998400aap+551", 166, "1.000000000000000104076806445342351803057814451465487433877079216547069699830754788624649845638922801100959355546714693321646955446568505272576798891444167390577819648e+166"}, + {"0x1.b221effe500d3p+554", 167, "99999999999999990767336997157383960226643264180953830087855645396318233083327270285662206135844950810475381599246526426844590779296424471954140613832058419086616428544"}, + {"0x1.b221effe500d4p+554", 167, "1.0000000000000000386089942874195144027940205149135043895442382956857739101649274267019739175454317034355575090286315503039132728953670850882316679737363063240072678605e+167"}, + {"0x1.0f5535fef2084p+558", 168, "999999999999999933860494834742974562371950216430331518611692822307700646699603647625692432595845947170914554599698521475539380813444812793279458505403728617494385000448"}, + {"0x1.0f5535fef2085p+558", 168, "1.00000000000000014335749374009605424321609081339667726047678376906384717363025120577825540249501745970020046345756457913228716497728935738318387744206888403052015072051e+168"}, + {"0x1.532a837eae8a5p+561", 169, "9999999999999999338604948347429745623719502164303315186116928223077006466996036476256924325958459471709145545996985214755393808134448127932794585054037286174943850004480"}, + {"0x1.532a837eae8a6p+561", 169, "1.000000000000000101458093959025438307047262694003408112103765579712617868244121694147742808515183157194343281685991367600937608144520448465202993654735852947914997576499e+169"}, + {"0x1.a7f5245e5a2cep+564", 170, "99999999999999990034097500988648181343688772091571619991327827082671720239070003832128235741197850516622880918243995225045973534722968565889475147553730375141026248523776"}, + {"0x1.a7f5245e5a2cfp+564", 170, "1.0000000000000000344190543093124528091771377029741774747069364767506509796263144755389226581474482731849717908514742291507783172120901941964335795950030032157467525460787e+170"}, + {"0x1.08f936baf85c1p+568", 171, "999999999999999953972206729656870211732987713739100709830741553196290713284945813208338477706166412373726001850053663010587168093173889073910282723323583537144858509574144"}, + {"0x1.08f936baf85c2p+568", 171, "1.00000000000000016849713360873842380491738768503263874950059468267458475686192891275656295888291804120371477252050850605109689907695070273397240771446870268008324260691968e+171"}, + {"0x1.4b378469b6731p+571", 172, "9999999999999999110672213538405594930961077194803931018967709273006319045695491932986935814708160866077282477159626944024852218964185263418978577250945597085571816901050368"}, + {"0x1.4b378469b6732p+571", 172, "1.000000000000000082687162857105802367643627696515223533632653430883267139431135672937273166412217389671719264252326568834893006683439977269947557718010655022907888967981466e+172"}, + {"0x1.9e056584240fdp+574", 173, "99999999999999987674323305318751091818660372407342701554959442658410485759723189737097766448253582599493004440868991951600366493901423615628791772651134064568704023452975104"}, + {"0x1.9e056584240fep+574", 173, "1.0000000000000000140391862557997052178246197057012913609383004294502130454865010810818413324356568684461228576377810190619298927686313968987276777208442168971676060568308941e+173"}, + {"0x1.02c35f729689ep+578", 174, "999999999999999849284042412665072058259000527747854146471853226010883220019378060628804930891911617504691481762871699606818419373090804007799965727644765395390927070069522432"}, + {"0x1.02c35f729689fp+578", 174, "1.0000000000000000689575675368445829376798260983524370990937828305966563206422087545661867996169052854265999829294174588803003839004782611957035817185773673977598323857513513e+174"}, + {"0x1.4374374f3c2c6p+581", 175, "9999999999999999371534524623368764100273307559896873275206250678451924602685103382037576783819090846734548822294900033162112051840457868829614121240178061963384891963422539776"}, + {"0x1.4374374f3c2c7p+581", 175, "1.000000000000000112892272561680485113563991212473353689618168751513810940766774893353663173361904019010981683162726610734996776805955752633284304916763887798233613448887717069e+175"}, + {"0x1.945145230b377p+584", 176, "99999999999999986685792442259943292861266657339622078268160759437774506806920451614379548038991111093844416185619536034869697653528180058283225500691937355558043949532406874112"}, + {"0x1.945145230b378p+584", 176, "1.0000000000000000074489805020743198914419949385831538723596425413126398524678161602637198763739070584084656026027846462837254338328097731830905692411162388370965388973604392141e+176"}, + {"0x1.f965966bce055p+587", 177, "999999999999999894976135638494410321178532246433607400617214583764724024948926844967780359586710300432448450005513217535702667994787395102883917853758746611883659375731342835712"}, + {"0x1.f965966bce056p+587", 177, "1.00000000000000000744898050207431989144199493858315387235964254131263985246781616026371987637390705840846560260278464628372543383280977318309056924111623883709653889736043921408e+177"}, + {"0x1.3bdf7e0360c35p+591", 178, "9999999999999998724815666657784284071258397080036981062687289922551408594451489819085924562292709488372450194860589317860981148271829194868425875762872481668410834714055235600384"}, + {"0x1.3bdf7e0360c36p+591", 178, "1.000000000000000052438118447506283719547380015442972461056613724331806183475371886382095683088785761598872463641693217782934540168018724415173229796059235727181690706012077765427e+178"}, + {"0x1.8ad75d8438f43p+594", 179, "99999999999999998045549773481514159457876389246726271914145983150114005386328272459269439234497983649422148597943950338419997003168440244384097290815044070304544781216945608327168"}, + {"0x1.8ad75d8438f44p+594", 179, "1.0000000000000001244207391601974258445159961384186822029717676171624723130874610481714969738325916867035234413039469321816691103043530463865054866839680307513179335998546994475827e+179"}, + {"0x1.ed8d34e547313p+597", 180, "999999999999999894076352879585771044616424544896411028843275160104340698328775730445412843452412726368640312784735046105718485868083216078242264642659886674081956339558310064685056"}, + {"0x1.ed8d34e547314p+597", 180, "1.00000000000000000924854601989159844456621034165754661590752138863340650570811838930845490864250220653608187704434098914369379808621813123237387566331395871269994496970650475613389e+180"}, + {"0x1.3478410f4c7ecp+601", 181, "9999999999999999171107915076469365246063817042486381462561244058101538598046442622180212564904306224021286256366562347133135483117101991090685868467907010818055540655879490029748224"}, + {"0x1.3478410f4c7edp+601", 181, "1.000000000000000101386300532136260364526038979066455085558918371456659151611592516398888560794573790670035128452025743574074047860726063355679164479837216343594335873825060509292954e+181"}, + {"0x1.819651531f9e7p+604", 182, "99999999999999991711079150764693652460638170424863814625612440581015385980464426221802125649043062240212862563665623471331354831171019910906858684679070108180555406558794900297482240"}, + {"0x1.819651531f9e8p+604", 182, "1.0000000000000000645311987272383955965421075241028916976983595783273580932502028655627150999337451570164538278889518418019219479509228905063570489532279132912365795121776382080293274e+182"}, + {"0x1.e1fbe5a7e7861p+607", 183, "999999999999999946594872951565228338993526868219488856544571440313594706493755982886960025179093529324993666087115356131035228239552737388526279268078143523691759154905886843985723392"}, + {"0x1.e1fbe5a7e7862p+607", 183, "1.00000000000000006453119872723839559654210752410289169769835957832735809325020286556271509993374515701645382788895184180192194795092289050635704895322791329123657951217763820802932736e+183"}, + {"0x1.2d3d6f88f0b3cp+611", 184, "9999999999999998286585471758920610814449462123360860153907833022998313197373091002112049504244419016335335042852788704601485085281825842706955095829283737561469387976341354799421194240"}, + {"0x1.2d3d6f88f0b3dp+611", 184, "1.000000000000000017356668416969128693522675261749530561236844323121852738547624112492413070031884505939869763168217247533567260066374829259224741079168005384218651369268937662411885773e+184"}, + {"0x1.788ccb6b2ce0cp+614", 185, "99999999999999997961704416875371517110712945186684165206763211895744845478556111003617144611039598507860251139162957211888350975873638026151889477992007905860430885494197722591793250304"}, + {"0x1.788ccb6b2ce0dp+614", 185, "1.0000000000000001305755411616153692607693126913975972887444809356150655898338131198611379417963500685236715184979802737776185109892901762523422799769117843610616789122498189718937455821e+185"}, + {"0x1.d6affe45f818fp+617", 186, "999999999999999979617044168753715171107129451866841652067632118957448454785561110036171446110395985078602511391629572118883509758736380261518894779920079058604308854941977225917932503040"}, + {"0x1.d6affe45f8190p+617", 186, "1.00000000000000010038384176304303844283687604349144616140911117228354216282416271789614464265915925183465771707671013344587151074317941705417760293751344330057020490078825062269858296627e+186"}, + {"0x1.262dfeebbb0f9p+621", 187, "9999999999999999071569656121801212080692814968920789464627446869617922299624001453201875281811380250249693879805812353226907091680705581859236698853640605134247712274342131878495422251008"}, + {"0x1.262dfeebbb0fap+621", 187, "1.000000000000000100383841763043038442836876043491446161409111172283542162824162717896144642659159251834657717076710133445871510743179417054177602937513443300570204900788250622698582966272e+187"}, + {"0x1.6fb97ea6a9d37p+624", 188, "99999999999999986851159038200753776111576258757220550347347138989744224339004763080499610528553377966303172216135545569805454885304878641227288327493418395599568449276340570087973407686656"}, + {"0x1.6fb97ea6a9d38p+624", 188, "1.0000000000000000230930913026978715489298382248516992754305645781548421896794576888657617968679507611107823854382585741965991901131358735068760297166536901857120314314466356487589666698035e+188"}, + {"0x1.cba7de5054485p+627", 189, "999999999999999899427890566145604518678577715028104257864890027548922232647929642417149243602017175952581854816736079397763477105066203831193512563278085201938953880500051690455580595453952"}, + {"0x1.cba7de5054486p+627", 189, "1.00000000000000002309309130269787154892983822485169927543056457815484218967945768886576179686795076111078238543825857419659919011313587350687602971665369018571203143144663564875896666980352e+189"}, + {"0x1.1f48eaf234ad3p+631", 190, "9999999999999998746948504188351511126283256130633852543517551174277382412416240331274267329488304589209417486924315804379963345034522698960570091326029642051843383703107348987949033805840384"}, + {"0x1.1f48eaf234ad4p+631", 190, "1.000000000000000072559171597318778361030342428781137282456834398397210172492068907445206818174324195174062597686867572116133475316363741377149036578003932179221262451825269232080321099543347e+190"}, + {"0x1.671b25aec1d88p+634", 191, "99999999999999991426771465453187656230872897620693565997277097362163262749171300799098274999392920617156591849131877877362376266603456419227541462168315779999172318661364176545198692437590016"}, + {"0x1.671b25aec1d89p+634", 191, "1.0000000000000000725591715973187783610303424287811372824568343983972101724920689074452068181743241951740625976868675721161334753163637413771490365780039321792212624518252692320803210995433472e+191"}, + {"0x1.c0e1ef1a724eap+637", 192, "999999999999999914267714654531876562308728976206935659972770973621632627491713007990982749993929206171565918491318778773623762666034564192275414621683157799991723186613641765451986924375900160"}, + {"0x1.c0e1ef1a724ebp+637", 192, "1.00000000000000004090088020876139800128601973826629695796002171344209466349199772755436200453824519737356326184775781344763153278629790594017431218673977730337535459878294373875465426450985779e+192"}, + {"0x1.188d357087712p+641", 193, "9999999999999998636144484328400679867178126713831911407778706776934478130915991201656310481762028096907669811487431649040206546179292274931158555956605099986382706217459209761309199883223171072"}, + {"0x1.188d357087713p+641", 193, "1.000000000000000066227513319607302289081477890678169217557471861406187070692054671467037855447108395613962730519045620382433086810350574289754091699751101204052080881216804133415187732536649318e+193"}, + {"0x1.5eb082cca94d7p+644", 194, "99999999999999994465967438754696170766327875910118237148971115117854351613178134068619377108456504406004528089686414709538562749489776621177115003729674648080379472553427423904462708600804999168"}, + {"0x1.5eb082cca94d8p+644", 194, "1.0000000000000001067501262969607491495542109345371648329133920981487349222121457817273192169012895127986018803931061114781155732488348436490817389205692194451348429331109807648720412813795157606e+194"}, + {"0x1.b65ca37fd3a0dp+647", 195, "999999999999999977077764769429719196041465194188378863774447340572581797347854228894418860247909937807756600796112539971931616645685181699233267813951241073670004367049615544210109925082343145472"}, + {"0x1.b65ca37fd3a0ep+647", 195, "1.00000000000000010675012629696074914955421093453716483291339209814873492221214578172731921690128951279860188039310611147811557324883484364908173892056921944513484293311098076487204128137951576064e+195"}, + {"0x1.11f9e62fe4448p+651", 196, "9999999999999999511432924639235132053389160461186216699466583890573511723749959183278387889172340228095875448767138256706948253250552493092635735926276453993770366538373425000777236538229086224384"}, + {"0x1.11f9e62fe4449p+651", 196, "1.000000000000000158619070907973161130959309230676679220568970001179196172157862402860479359562641342794939992231903540080589155890094708429021127363216410793720778359535526853136813823898384806707e+196"}, + {"0x1.56785fbbdd55ap+654", 197, "99999999999999995114329246392351320533891604611862166994665838905735117237499591832783878891723402280958754487671382567069482532505524930926357359262764539937703665383734250007772365382290862243840"}, + {"0x1.56785fbbdd55bp+654", 197, "1.0000000000000001171239152191632315458352305937650677104445076787548271722012891059539512454335598787978695027608655971986102897770868166050696166090986577148520300183958899825249957898832895698534e+197"}, + {"0x1.ac1677aad4ab0p+657", 198, "999999999999999884751043361827625869140390227060043253747518673178360772444478643277393806310703680414274761723053117059528639544242622390941156386039240473187039308013923507098814799398756243472384"}, + {"0x1.ac1677aad4ab1p+657", 198, "1.00000000000000001753554156601940054153744186517720008614579810493634157230551319337828377152376436520490032803037453428186101110586787622758599079921605032556703399966076149305663250824706100140442e+198"}, + {"0x1.0b8e0acac4eaep+661", 199, "9999999999999998847510433618276258691403902270600432537475186731783607724444786432773938063107036804142747617230531170595286395442426223909411563860392404731870393080139235070988147993987562434723840"}, + {"0x1.0b8e0acac4eafp+661", 199, "1.000000000000000097206240488534465344975672848047494185584765763991130052222133923438817750651600776079275667814767384615260434042843028529572891447122136236995030814648864284631323133556043856163635e+199"}, + {"0x1.4e718d7d7625ap+664", 200, "99999999999999996973312221251036165947450327545502362648241750950346848435554075534196338404706251868027512415973882408182135734368278484639385041047239877871023591066789981811181813306167128854888448"}, + {"0x1.4e718d7d7625bp+664", 200, "1.0000000000000001396972799138758332401427293722449843719522151821536839081776649794711025395197801952122758490331102381264067929425631097572992384593387153897566291159758524401378248003875013787018854e+200"}, + {"0x1.a20df0dcd3af0p+667", 201, "999999999999999901747459131964173027207212836739039328294498440443382314826691065690307721857975448067474834210390258463987183104130654882031695190925872134291678628544718769301415466131339252487684096"}, + {"0x1.a20df0dcd3af1p+667", 201, "1.00000000000000003771878529305655029174179371417100792467033657856355465388439044499361904623614958929307541410908738969965553158323491481075600563001892542312879319279108086692222079999200332461008486e+201"}, + {"0x1.0548b68a044d6p+671", 202, "9999999999999999017474591319641730272072128367390393282944984404433823148266910656903077218579754480674748342103902584639871831041306548820316951909258721342916786285447187693014154661313392524876840960"}, + {"0x1.0548b68a044d7p+671", 202, "1.000000000000000119301580989711976650462542240630189082495839461435658057319010072575605840863054074028435762048305668441056540670697470767990591893474757396431061931338898125494704000308401767883525325e+202"}, + {"0x1.469ae42c8560cp+674", 203, "99999999999999998876910787506329447650934459829549922997503484884029261182361866844442696946000689845185920534555642245481492613075738123641525387194542623914743194966239051177873087980216425864602058752"}, + {"0x1.469ae42c8560dp+674", 203, "1.0000000000000001628124053612615373751136081214084190333361076656341132058174738739526654646640697992206279476158887504364704121840108339451823712339845344488589385918977339967333617071438142709626935706e+203"}, + {"0x1.98419d37a6b8fp+677", 204, "999999999999999988769107875063294476509344598295499229975034848840292611823618668444426969460006898451859205345556422454814926130757381236415253871945426239147431949662390511778730879802164258646020587520"}, + {"0x1.98419d37a6b90p+677", 204, "1.00000000000000012800374586402188879539275541678583507266389310227534908701870283285101776562325721906687419916182228484013931497336014340342894776157671280691663726345066529974243554167548426849935897395e+204"}, + {"0x1.fe52048590672p+680", 205, "9999999999999999052283250816881378851792981072012977243617198967792587267065681698004724917620567060828502090557969050236202928251957239362070375381666542984859087613894256390005080826781722527340175556608"}, + {"0x1.fe52048590673p+680", 205, "1.000000000000000016616035472855013340286026761993566398512806499527303906862635501325745128692656962574862204108809594931879803899277933669817992649871683552701273012420045469371471812176828260616688264806e+205"}, + {"0x1.3ef342d37a407p+684", 206, "99999999999999986067324092522138770313660664528439025470128525568004065464414123719036343698981660348604541103459182906031648839556284004276265549348464259679976306097717770685212259087870984958094927200256"}, + {"0x1.3ef342d37a408p+684", 206, "1.0000000000000000388935775510883884313073724929520201333430238200769129428938489676307996560787770138732646031194121329135317061140943756165401836722126894035443458626261694354456645580765594621932224066355e+206"}, + {"0x1.8eb0138858d09p+687", 207, "999999999999999896317308250394787848770759814817916230429632968559415112294082783278450680807608685563489249451555889830959531939269147157518161129230251958148679621306976052570830984318279772103403898929152"}, + {"0x1.8eb0138858d0ap+687", 207, "1.00000000000000003889357755108838843130737249295202013334302382007691294289384896763079965607877701387326460311941213291353170611409437561654018367221268940354434586262616943544566455807655946219322240663552e+207"}, + {"0x1.f25c186a6f04cp+690", 208, "9999999999999999818630698308109481982927274216983785721776674794699138106539424938898600659703096825493544616522696356805028364441642842329313746550197144253860793660984920822957311285732475861572950035529728"}, + {"0x1.f25c186a6f04dp+690", 208, "1.000000000000000095924085271365828664322017564205661694508380160683912075133755441371739246187244345197174744586554630146560575784024467000148992689405664381702612359153846788595597987579871338229149809718067e+208"}, + {"0x1.37798f428562fp+694", 209, "99999999999999989061425747836704382546929530769255207431309733449871519907009213590435672179676195243109823530484164010765664497227613801915728022751095446033285297165420831725583764136794858449981115862089728"}, + {"0x1.37798f4285630p+694", 209, "1.0000000000000000731118821832548525711161595357042050700422376244411124222377928518753634101438574126676106879996976312533490279160524304467054690825284743904393057605427758473356246157785465878147788484850483e+209"}, + {"0x1.8557f31326bbbp+697", 210, "999999999999999927113782419344605574598668153294882673458925392487194643703632279098558059466181044478400725843812838336795121561031396504666917998514458446354143529431921823271795036250068185162804696593727488"}, + {"0x1.8557f31326bbcp+697", 210, "1.00000000000000007311188218325485257111615953570420507004223762444111242223779285187536341014385741266761068799969763125334902791605243044670546908252847439043930576054277584733562461577854658781477884848504832e+210"}, + {"0x1.e6adefd7f06aap+700", 211, "9999999999999999563134023721266549739021664297767471527755878388779781994104643936539191296017163181162427182749897969201059028320356032930746282153172616351711759756540926280845609521557638656931995269719916544"}, + {"0x1.e6adefd7f06abp+700", 211, "1.00000000000000007311188218325485257111615953570420507004223762444111242223779285187536341014385741266761068799969763125334902791605243044670546908252847439043930576054277584733562461577854658781477884848504832e+211"}, + {"0x1.302cb5e6f642ap+704", 212, "99999999999999990959401044767537593501656918740576398586892792465272451027953301036534141738485988029569553038510666318680865279842887243162229186843277653306392406169861934038413548670665077684456779836676898816"}, + {"0x1.302cb5e6f642bp+704", 212, "1.0000000000000000964715781454804920905589581568896966534955675815537392668032585435196522662522856315778842819446391981199976529328557958774316372559707169414929317175205124911858373485031031322390947127876596531e+212"}, + {"0x1.7c37e360b3d35p+707", 213, "999999999999999984345037526797422397233524775199337052919583787413130412889023223627065756931830180808571031008919677160084252852199641809946030023447952696435527124027376600704816231425231719002378564135125254144"}, + {"0x1.7c37e360b3d36p+707", 213, "1.00000000000000013384709168504151532166743595078648318702089551293394221810800365015051443602577078183432203225654570510663545295974118056659350633347830502317873324868489112134617772086239360331800009567183778611e+213"}, + {"0x1.db45dc38e0c82p+710", 214, "9999999999999999544446266951486038123467425400819078260993214423089680518452271383223760211130420606034208307593944715707740128306913340586165347614418822310868858990958736965765439335377993421392542578277827477504"}, + {"0x1.db45dc38e0c83p+710", 214, "1.000000000000000074046270021743878151893871480551624733380370822725617496020411479541134964388194541424021631757495293928014972916724565063934515809466164092481450798821885313089633125087528849591751483057152773325e+214"}, + {"0x1.290ba9a38c7d1p+714", 215, "99999999999999990660396936451049407652789096389402106318690169014230827417515340183487244380298106827518051036015414262787762879627804165648934234223216948652905993920546904997130825691790753915825536773603473752064"}, + {"0x1.290ba9a38c7d2p+714", 215, "1.0000000000000000979665986870629330198032972686455681148365806988089473848554483477848867530432250375881417919571154583994631649339312112649981120190710204647603637787670876363922509633974747510822509281030267784397e+215"}, + {"0x1.734e940c6f9c5p+717", 216, "999999999999999868331443500000006287872809702943711652856965888408980452039094412644869581954932274412588254040761879473560521568747407734787588406864399290882799171293145332687119715621994096773456255662636329336832"}, + {"0x1.734e940c6f9c6p+717", 216, "1.00000000000000002142154695804195744249313474674494929417670909534229174058333036940488102934712744986295727931833093209082895047886994342159460414833548007346784224294244020182387388080564786631265270395622996207206e+216"}, + {"0x1.d022390f8b837p+720", 217, "9999999999999999601855055748251769806450047292244542376488118125689672251656359867008764503902493796828096692073033110439215789148209291468717978517470477604338250142827222541691722147321863584969741246387925089779712"}, + {"0x1.d022390f8b838p+720", 217, "1.000000000000000082657588341258737904341264764265444350704606378115616256001024752108885608304005520043104889429358553137736322042918957696317410444923912386501859471602158149478575546879109374128331283273667415166157e+217"}, + {"0x1.221563a9b7322p+724", 218, "99999999999999988670225591496504042642724870819986016981533507324097780666440272745607095564199569546663253707407016578763273303796211201720443029584092898479300433989106071698353021544403254911815982945786756526505984"}, + {"0x1.221563a9b7323p+724", 218, "1.0000000000000000826575883412587379043412647642654443507046063781156162560010247521088856083040055200431048894293585531377363220429189576963174104449239123865018594716021581494785755468791093741283312832736674151661568e+218"}, + {"0x1.6a9abc9424febp+727", 219, "999999999999999965084388885482519417592855130626093842171043595190833186399051537317196816706799625297221478016185520727674168639944850288849622355474122345476546392575499689981548348018063279122228410984187505225498624"}, + {"0x1.6a9abc9424fecp+727", 219, "1.00000000000000012184865482651747739992406797547856118688246063909054394586834915703944853883640748495839935990041623060775703984391032683214000647474050906684363049794437763597758461316612473913036557403682738514637619e+219"}, + {"0x1.c5416bb92e3e6p+730", 220, "9999999999999999964372420736895110140590976995965873111133270039707753382929110612616471611327211972294570543930316627036907428807379455975076991793273996897499632136492752791807556010476755711238558435947154812096741376"}, + {"0x1.c5416bb92e3e7p+730", 220, "1.000000000000000121848654826517477399924067975478561186882460639090543945868349157039448538836407484958399359900416230607757039843910326832140006474740509066843630497944377635977584613166124739130365574036827385146376192e+220"}, + {"0x1.1b48e353bce6fp+734", 221, "99999999999999984594354677029595135102113336853821866019036664182705300920238534632828550788829765195472628778417018121881118652493108811594893042483166843723756247249515245102456078650553656951604416706418119648563167232"}, + {"0x1.1b48e353bce70p+734", 221, "1.0000000000000000466018071748206975684050858099493768614209804580186827813230862995727677122141957123210339765959854898653172616660068980913606220974926434405874301273673162218994872058950552383264597357715602427843549594e+221"}, + {"0x1.621b1c28ac20bp+737", 222, "999999999999999886075198851200900594497923856820450300436489405065378963626525536977181948753477264027987825546533242948112401553146250111031268759363863437907536003469585205199546070383440303278127280805657005745376329728"}, + {"0x1.621b1c28ac20cp+737", 222, "1.00000000000000004660180717482069756840508580994937686142098045801868278132308629957276771221419571232103397659598548986531726166600689809136062209749264344058743012736731622189948720589505523832645973577156024278435495936e+222"}, + {"0x1.baa1e332d728ep+740", 223, "9999999999999999181805205159248599892793562474462356126333876156560397271658376894962991014456209536865970557564236923315533735757183797070971394269896194384435148282491314085395342974857632902877937717988376531531720556544"}, + {"0x1.baa1e332d728fp+740", 223, "1.00000000000000004660180717482069756840508580994937686142098045801868278132308629957276771221419571232103397659598548986531726166600689809136062209749264344058743012736731622189948720589505523832645973577156024278435495936e+223"}, + {"0x1.14a52dffc6799p+744", 224, "99999999999999996954903517948319502092964807244749211214842475260109694882873713352688654575305085714037182409224841134505892881183378706080253249519082903930108094789640533388351546084948006950326015738792668900564521713664"}, + {"0x1.14a52dffc679ap+744", 224, "1.0000000000000001750230938337165351475308153724525181102085733003813258354803349096492363229827704709554708974355472873990811497562954164756241047679956674427313454264855010352594401143043471863651256997442828324155378630656e+224"}, + {"0x1.59ce797fb817fp+747", 225, "999999999999999928454223448636526995609414612446486912536395043045051171498417578302416590307106934377352009423588636134254484622941461177838218040629861358615028052178586193608330530158506646130887048916655460323666687950848"}, + {"0x1.59ce797fb8180p+747", 225, "1.00000000000000009283347037202319909689034845245050771098451388126923428081969579920029641209088262542943126809822773697747226137851076470969547585887373208135923963504986275470907025292240033962037948280174037505158080469402e+225"}, + {"0x1.b04217dfa61dfp+750", 226, "9999999999999999613300728333138614158656013804472910722260188106898877933626732224819925546638620725877678611585164563028980399740553218842096696042786355031638703687528415058284784747112853848287855356936724432692495112994816"}, + {"0x1.b04217dfa61e0p+750", 226, "1.000000000000000092833470372023199096890348452450507710984513881269234280819695799200296412090882625429431268098227736977472261378510764709695475858873732081359239635049862754709070252922400339620379482801740375051580804694016e+226"}, + {"0x1.0e294eebc7d2bp+754", 227, "99999999999999988242803431008825880725075313724536108897092176834227990088845967645101024020764974088276981699468968789815350713138205618891818585152157755624664880897462875650012340778461641195382916742883168419985073526276096"}, + {"0x1.0e294eebc7d2cp+754", 227, "1.000000000000000092833470372023199096890348452450507710984513881269234280819695799200296412090882625429431268098227736977472261378510764709695475858873732081359239635049862754709070252922400339620379482801740375051580804694016e+227"}, + {"0x1.51b3a2a6b9c76p+757", 228, "999999999999999924509121522475246865178672200286390413373640190927670776874706901000867474584296317792102107215397297714017257980807797893073643852992008461269166974189675556141912776812173197487139230503413422370196749149011968"}, + {"0x1.51b3a2a6b9c77p+757", 228, "1.000000000000000092833470372023199096890348452450507710984513881269234280819695799200296412090882625429431268098227736977472261378510764709695475858873732081359239635049862754709070252922400339620379482801740375051580804694016e+228"}, + {"0x1.a6208b5068394p+760", 229, "9999999999999999918388610622944277578633427011520373324179896670642961784527024602806390495869308408470337715685294734193992593398889846197223766553446979093051960385337504355687757672562640543404353314227442034427503713670135808"}, + {"0x1.a6208b5068395p+760", 229, "1.000000000000000126498340141932789543232683702883331170506688619337546981608693578840182199592199886956897100274793824830163262058051358073019842260050076805377254167221900194422501748144445768047027533261405765587857615803016806e+229"}, + {"0x1.07d457124123cp+764", 230, "99999999999999988411127779858373832956786989976700226194703050524569553592790956543300452958271560395914310860351799229078805716535908585708440417158039479244754953558323062848579498254571868337516156995181495372666457581821100032"}, + {"0x1.07d457124123dp+764", 230, "1.0000000000000000995664443260051171861588155025370724028889488288828968209774953551282735695911460777349244345335409545480104615144188833823603491391090010261628425414842702426517565519668094253057090928936734531588361669158161613e+230"}, + {"0x1.49c96cd6d16cbp+767", 231, "999999999999999884111277798583738329567869899767002261947030505245695535927909565433004529582715603959143108603517992290788057165359085857084404171580394792447549535583230628485794982545718683375161569951814953726664575818211000320"}, + {"0x1.49c96cd6d16ccp+767", 231, "1.00000000000000005647541102052084141484062638198305837470056516415545656396757819718921976158945998297976816934753636209656598064460692387730516014560327977941978394030406231981856423808259127691959958830530175327240184869629512909e+231"}, + {"0x1.9c3bc80c85c7ep+770", 232, "9999999999999999185841044429711589466224211962102134844977374370276477415358432917842475759840644797632681207523216662519436418612086534611285553663849717898419964165273969667523488336530932020840491736225123136358120303938278260736"}, + {"0x1.9c3bc80c85c7fp+770", 232, "1.000000000000000056475411020520841414840626381983058374700565164155456563967578197189219761589459982979768169347536362096565980644606923877305160145603279779419783940304062319818564238082591276919599588305301753272401848696295129088e+232"}, + {"0x1.01a55d07d39cfp+774", 233, "99999999999999997374062707399103193390970327051935144057886852787877127050853725394623645022622268104986814019040754458979257737456796162759919727807229498567311142603806310797883499542489243201826933949562808949044795771481474727936"}, + {"0x1.01a55d07d39d0p+774", 233, "1.0000000000000001943667175980705238830588315677559032649033928912832653863993131025941919471948554861962682179427510579411883194280051942934817649248215877689975714640807276728847796425120893517551500029880911929089916669987624321024e+233"}, + {"0x1.420eb449c8842p+777", 234, "999999999999999841364972759543336764420226292177420345984153909836074800974071744757463152045042997962028093539001436578955132142505622028069656690022719315678435403212464369035268207172574280176140941400150227439321732144446136385536"}, + {"0x1.420eb449c8843p+777", 234, "1.00000000000000001786584517880693032373952892996666180544377340055967009368669242367582754961994924207914815574087624726007172578525540816077571080742215354233800343364659602096002392484233181596564547219412071017415669957160428424397e+234"}, + {"0x1.9292615c3aa53p+780", 235, "9999999999999999119653217272487741881479473472931169297680017061255129180591200163248089110750054956088761184197513608514017695996055364811520783369824930063422626153861170298051704942404772944919427537177384205332557191153093955289088"}, + {"0x1.9292615c3aa54p+780", 235, "1.000000000000000053166019662659649035603389457524510097335697298704389152229216559459500429134930490902572168181251209396295044513805365387316921630902040387669917039733422351344975068376283323123546378352914806721123693057035913815654e+235"}, + {"0x1.f736f9b3494e8p+783", 236, "99999999999999994020546131433094915763903576933939556328154082464128816489313932495174721468699049466761532837205133056038042458244550226238504699576640248260779350025557809411313140906763850021826347864477369777082931390365469918625792"}, + {"0x1.f736f9b3494e9p+783", 236, "1.0000000000000000531660196626596490356033894575245100973356972987043891522292165594595004291349304909025721681812512093962950445138053653873169216309020403876699170397334223513449750683762833231235463783529148067211236930570359138156544e+236"}, + {"0x1.3a825c100dd11p+787", 237, "999999999999999940205461314330949157639035769339395563281540824641288164893139324951747214686990494667615328372051330560380424582445502262385046995766402482607793500255578094113131409067638500218263478644773697770829313903654699186257920"}, + {"0x1.3a825c100dd12p+787", 237, "1.00000000000000012094235467165686896238200167043557881776819118314224974463086290016415235780369448864354627206677113669784381647262128326227604641198342313070719116342012890568408126396147021686671611817779947209130032054906464259329229e+237"}, + {"0x1.8922f31411455p+790", 238, "9999999999999999040580826428657651966904425891201589123842107529410958489455946099092661860636496958724291396331073693328877462044103460624068471125229983529879139676226679317989414380888721568885729507381685429067351125745727105048510464"}, + {"0x1.8922f31411456p+790", 238, "1.000000000000000048647597328726501040484815309997105515973531039741865112735773470079190300557012891053173894588883214242858459716550970862319646645496614871467432098154308581055701322003937530207335062364589162363111917890900665230478541e+238"}, + {"0x1.eb6bafd91596bp+793", 239, "99999999999999999081179145438220670296706622164632687453780292502155740721970192601122065475966761298087599260657287627887017431169472094235452683230716826407562484594165232135299736843791138087983021771402091458056119576436948334022754304"}, + {"0x1.eb6bafd91596cp+793", 239, "1.0000000000000001064834032030707953780025643983478841574092591544621728182518450141471599463543581691254717965711935522068467451214072207822847664586860614788592393503669648407584052755699636795348399070151574101456626400174318471207295386e+239"}, + {"0x1.33234de7ad7e2p+797", 240, "999999999999999828871535006218182557917368774264146678517764203804695831774701602620905646527100834378441867056103929979702975178097221166452191355376717763378564539746214794185426298453038162762816652692429820789419173810082174047524749312"}, + {"0x1.33234de7ad7e3p+797", 240, "1.00000000000000001394611380411992443797416585698663833111209417090968048942613054363840851307860572420979515339949701146446548847363722091034057475758294690703234774682671482523407894986432184061083215557424821369358148461498195609632794214e+240"}, + {"0x1.7fec216198ddbp+800", 241, "9999999999999999029013665253788793099400876073531433395554961906466896948352731790279067931477027903109831815934611625736079804963132210640075447162592094208400778225784148066048873590175516339020228538451571779510840981320420868670460264448"}, + {"0x1.7fec216198ddcp+800", 241, "1.00000000000000005096102956370027281398552527353113666163096016433067742095641633184190908638890670217606581066817562776141799113274522085911825143802419273576310438824281483144380948014657857618043525615061189227441394677596191250608858071e+241"}, + {"0x1.dfe729b9ff152p+803", 242, "99999999999999993251329913304315801074917514058874200397058898538348724005950180959070725179594357268399970740840405561116998262359962102302968606061220608382468313571129481157267178324335702235770533430624812081575006786082605199485453729792"}, + {"0x1.dfe729b9ff153p+803", 242, "1.0000000000000000509610295637002728139855252735311366616309601643306774209564163318419090863889067021760658106681756277614179911327452208591182514380241927357631043882428148314438094801465785761804352561506118922744139467759619125060885807104e+242"}, + {"0x1.2bf07a143f6d3p+807", 243, "999999999999999885134206960780312089454635087411784140906440513804611167700736000690226517958758320887173266104495426751070779219941381088594259909647411423049314634698686803624216704482068400828613365568502612232284516294771707790360919932928"}, + {"0x1.2bf07a143f6d4p+807", 243, "1.0000000000000000746505756498316957746327953001196155931630344001201154571357992362921494533074993280744790313201299421914675928345743408263359645135065900661507886387491188354180370195272228869449812405194846465661467225589890846083353893929e+243"}, + {"0x1.76ec98994f488p+810", 244, "9999999999999999230374806985905888264902671299533504313577592910677120255877486478106111050285065223246344191476223298391501419428679730361426008304192471516696094355087732099829807674910992980518869405586990190990569575476151831539558138249216"}, + {"0x1.76ec98994f489p+810", 244, "1.000000000000000074650575649831695774632795300119615593163034400120115457135799236292149453307499328074479031320129942191467592834574340826335964513506590066150788638749118835418037019527222886944981240519484646566146722558989084608335389392896e+244"}, + {"0x1.d4a7bebfa31aap+813", 245, "99999999999999992303748069859058882649026712995335043135775929106771202558774864781061110502850652232463441914762232983915014194286797303614260083041924715166960943550877320998298076749109929805188694055869901909905695754761518315395581382492160"}, + {"0x1.d4a7bebfa31abp+813", 245, "1.0000000000000000443279566595834743850042896660863625608019793783096347708261891185958417836517007669245101088856284197210041026562330672682972917768891214832545527981010497103310257691199981691663623805273275210727287695567143043174594742793011e+245"}, + {"0x1.24e8d737c5f0ap+817", 246, "999999999999999874521290314193434603084658115500145579580071256170942927492372459496518833579228824484684143252419893886408557657521935343280724451831297419035632090471862609843762766839539749606096764571247618309588232743975534688554349643169792"}, + {"0x1.24e8d737c5f0bp+817", 246, "1.00000000000000006858605185178205149670709417331296498669082339575801931987387721275288791937633961584448524683322963769737489479890608611472822996618309634957154147061950501040063476944577794338925746852105322146746313195853412855016020637017702e+246"}, + {"0x1.6e230d05b76cdp+820", 247, "9999999999999999521471949292288813605336325386252733424243721120057734844449743607990664678980731410286045846847437914107950925140755956518597266575720169912499958425309195700665115678820350271193610461511698595727381924297989722331966923339726848"}, + {"0x1.6e230d05b76cep+820", 247, "1.00000000000000010739900415929977487543158138487552886811297382367543459835017816340416173653576177411644546754939158645956816222718291626901773106905345613567872334664903349051200916996702558214588960931101434209903811180144584732248137771557847e+247"}, + {"0x1.c9abd04725480p+823", 248, "99999999999999992109683308321470265755404276937522223728665176967184126166393360027804741417053541441103640811181423240104047857145413152842812577527572916236425034170729678597741204746503691611405533351920096306747820855546959721533975525765152768"}, + {"0x1.c9abd04725481p+823", 248, "1.0000000000000000452982804672714174694724018463754266578375331390075701527880966423621236290806863208813091144035324684400589343419399880221545293044608804779072323450017879223338101291330293601352781840470765490885181440527870972867675035629361562e+248"}, + {"0x1.1e0b622c774d0p+827", 249, "999999999999999921096833083214702657554042769375222237286651769671841261663933600278047414170535414411036408111814232401040478571454131528428125775275729162364250341707296785977412047465036916114055333519200963067478208555469597215339755257651527680"}, + {"0x1.1e0b622c774d1p+827", 249, "1.00000000000000011981914889770544635662341729257554931016806196060900748746259446761256935802677686476347273817856341006347000780423150191839037142197197126723302154697848260414764897813382482654801189436380190070114210535117759732962415254610693325e+249"}, + {"0x1.658e3ab795204p+830", 250, "9999999999999999210968330832147026575540427693752222372866517696718412616639336002780474141705354144110364081118142324010404785714541315284281257752757291623642503417072967859774120474650369161140553335192009630674782085554695972153397552576515276800"}, + {"0x1.658e3ab795205p+830", 250, "1.000000000000000080074685734807297616809542387935483895591779922421574242302862294145664969255528574692985472165213574530984101957676027840397922292632722846259267305924245440513601592000067244461220582194881713174409325992035997306767273088415852134e+250"}, + {"0x1.bef1c9657a685p+833", 251, "99999999999999992109683308321470265755404276937522223728665176967184126166393360027804741417053541441103640811181423240104047857145413152842812577527572916236425034170729678597741204746503691611405533351920096306747820855546959721533975525765152768000"}, + {"0x1.bef1c9657a686p+833", 251, "1.0000000000000000482791152044887786249584424642234315639307542918716276461750765553721414582385299426365956593545337061049953772804316485780039629891613241094802639130808557096063636830930611787917875324597455631530231025047227172884817695222629872435e+251"}, + {"0x1.17571ddf6c813p+837", 252, "999999999999999895660376658959887464073162830405580371957831265231883984761705009259228605356936508765924557863270337660249498829658628118512958332498610172941047627432585001251621720339432063578508893731092043050369229765618973200711352404729235767296"}, + {"0x1.17571ddf6c814p+837", 252, "1.00000000000000009915202805299840901192020234216271529458839530075154219997953373740977907586572775392681935985162149558657733676402265539783429787471556208832666934163027927905794433734427088386288041203596340318724106008442396531773857522810757106893e+252"}, + {"0x1.5d2ce55747a18p+840", 253, "9999999999999999363587069377675917736425707327570073564839440723358156278052707548893386994586947577981035182609405692455150664165314335743772262409420005560181719702721238568128862437403998276353831973920663150777435958293799716241167969694049028276224"}, + {"0x1.5d2ce55747a19p+840", 253, "1.000000000000000099152028052998409011920202342162715294588395300751542199979533737409779075865727753926819359851621495586577336764022655397834297874715562088326669341630279279057944337344270883862880412035963403187241060084423965317738575228107571068928e+253"}, + {"0x1.b4781ead1989ep+843", 254, "99999999999999993635870693776759177364257073275700735648394407233581562780527075488933869945869475779810351826094056924551506641653143357437722624094200055601817197027212385681288624374039982763538319739206631507774359582937997162411679696940490282762240"}, + {"0x1.b4781ead1989fp+843", 254, "1.0000000000000000665933638299522455642646760202815737069675050550683968855446811409056910005843211547010761915334853103183648826945244110331428835479608497818649698673586481946089327186234966726173809691071839855653415672334151665790142195763670374206669e+254"}, + {"0x1.10cb132c2ff63p+847", 255, "999999999999999988452569694641453289891412847766833896677368465428848130901034909295879619908945316559292587569958465674654992927728624557883489163749540246356891129106733591931304833693638565628182306078113383272782784390994049606075766012189756664840192"}, + {"0x1.10cb132c2ff64p+847", 255, "1.00000000000000019682802072213689935488678130780614005745106603780097814328409152692204330170994755160404886480603005139121469897251738849190854085497969900771176776444517253240497919350659351759937874082230165605293953863745036153391164218332917201371136e+255"}, + {"0x1.54fdd7f73bf3bp+850", 256, "9999999999999998634272990781441856508941917717432502002131499220055701234712009387201814108283439755324388212283155142447191693008553661974684581490114449895439651479036702276471002178058655944454644452316004196046887318431202624493742403095061074555174912"}, + {"0x1.54fdd7f73bf3cp+850", 256, "1.000000000000000030127659900140542502890486539774695128832107979903274133377646232821112356269145763568243843017172782817966934136686377344688499501995571998627866456174421380026039705656229556022421593026951037828814135240285311991642941246417639734614426e+256"}, + {"0x1.aa3d4df50af0ap+853", 257, "99999999999999989676737124254345702129345072534953918593694153358511092545248999754036759991650433313959982558608696795936872226802156842691246641960827039136074540955782045812288811537593838676085587479067054324951381252255327235782798049688841391133687808"}, + {"0x1.aa3d4df50af0bp+853", 257, "1.0000000000000000301276599001405425028904865397746951288321079799032741333776462328211123562691457635682438430171727828179669341366863773446884995019955719986278664561744213800260397056562295560224215930269510378288141352402853119916429412464176397346144256e+257"}, + {"0x1.0a6650b926d66p+857", 258, "999999999999999843423255779504622828654636399579476808778874955057845642282427503428069697375447760968142218613652642015929437520555644859802053186653349748453896990911180089361627479263821919056229587496158345417793683435460456504301996197076723582025859072"}, + {"0x1.0a6650b926d67p+857", 258, "1.0000000000000000567997176316599595992098937026597263174111412691669067749626774798772613075396740496539726465033899457896865765104193391282437061184730323200812906654977415644066700237122877898747347366742071367446741997838317199184059333963234848992699351e+258"}, + {"0x1.4cffe4e7708c0p+860", 259, "9999999999999999287738405203667575368767393208115766122317814807014700953545274940077463414411382764424743897695475635254322931165011225671787143593812227771048544607458046793796444970432082673836316471673778619485458899748089618699435710767754281089234894848"}, + {"0x1.4cffe4e7708c1p+860", 259, "1.00000000000000009947501000209102695332094516327577621913759453198871900149872747516709962957251930739113873208133740654443800430839207798193203670483696883440676940041505385941567853260198096403843576650981689501005030305350597260122672083617283716271875031e+259"}, + {"0x1.a03fde214caf0p+863", 260, "99999999999999992877384052036675753687673932081157661223178148070147009535452749400774634144113827644247438976954756352543229311650112256717871435938122277710485446074580467937964449704320826738363164716737786194854588997480896186994357107677542810892348948480"}, + {"0x1.a03fde214caf1p+863", 260, "1.0000000000000000653347761057461730700321039947829362977564319217312692202698874789352289719462431012014058636189794379406368620700138868989813722357458196229463864124812040234084717254902264247074749426413290883977494204377665704549700908842933553519596981453e+260"}, + {"0x1.0427ead4cfed6p+867", 261, "999999999999999928773840520366757536876739320811576612231781480701470095354527494007746341441138276442474389769547563525432293116501122567178714359381222777104854460745804679379644497043208267383631647167377861948545889974808961869943571076775428108923489484800"}, + {"0x1.0427ead4cfed7p+867", 261, "1.00000000000000014727133745697382238992532279916575210907122218634914869521910346989171855024930599605676474792863856258975960344212154549806296696156457773045130558352244362982576806255843731910178091992569982426727153871554113560598600276880411169778142334157e+261"}, + {"0x1.4531e58a03e8bp+870", 262, "9999999999999998413748417457239315956573059294699064134960051984423986554086971036541574579178711885967582465059111638997013689862529533948250133185078807957662740116351490992011950708371166466963719380640490770210556304785160923755265983999639546733803159420928"}, + {"0x1.4531e58a03e8cp+870", 262, "1.000000000000000016172839295009583478096172712153246810967557762960541535300357884361335224964405364288190533033183963151163217246749291739532415400254564758443434909856460259558093923249299888070891356270706646876036149471101831364360543753586901544466663027507e+262"}, + {"0x1.967e5eec84e2ep+873", 263, "99999999999999987633444125558106197214507928600657449299031571134602723138702925979559301132717802373504470381136572374999373863835222106376649373485721758830170619127941133127257484131955329497127582170538059099205173427703324017329338747068854404759758535917568"}, + {"0x1.967e5eec84e2fp+873", 263, "1.0000000000000000161728392950095834780961727121532468109675577629605415353003578843613352249644053642881905330331839631511632172467492917395324154002545647584434349098564602595580939232492998880708913562707066468760361494711018313643605437535869015444666630275072e+263"}, + {"0x1.fc1df6a7a61bap+876", 264, "999999999999999932269800471352470574525516656465243420181212531991832952952360709621889896782068959956303035500093019510461530081711049334072862401016156456358397678710230902586782474091451932211122035531511013345645500354660676649720249983847887046345216426508288"}, + {"0x1.fc1df6a7a61bbp+876", 264, "1.0000000000000000441405189028952877792863913973825812745630061732834443960830236092744836676918508323988196988775476110313971129684287058746855997333340341924717806535718700452151977396352492066908144631837718580528330325099155496025739750101665730438404785611735e+264"}, + {"0x1.3d92ba28c7d14p+880", 265, "9999999999999998875215130987353436926211667600983082784284950754751883757000955497608523884181562109792963701491111829020872969270239867178277674680890053619130444887655752455354163678739330224192450644706066754627704874925587274685787599733204126473471115726422016"}, + {"0x1.3d92ba28c7d15p+880", 265, "1.000000000000000066514662589203851220238566345566048845439364901541766684709156189205002421873807206887323031553038529335584229545772237182808147199797609739694457248544197873740880792744008661586752948714224026994270538940966524193144720015430310243339530988106547e+265"}, + {"0x1.8cf768b2f9c59p+883", 266, "99999999999999988752151309873534369262116676009830827842849507547518837570009554976085238841815621097929637014911118290208729692702398671782776746808900536191304448876557524553541636787393302241924506447060667546277048749255872746857875997332041264734711157264220160"}, + {"0x1.8cf768b2f9c5ap+883", 266, "1.0000000000000000307160326911101497147150864284725007320371909363284510229073440613161724151826770077057176992722530600488848430220225870898120712534558888641381746965884733480997879077699935337532513718655005566879705286512849648482315280070083307241410471050136781e+266"}, + {"0x1.f03542dfb8370p+886", 267, "999999999999999973438224854160227305877518561122823750593712591987145964024444656694044404476868689015149167622996309190165824584023146941018349739309135463248122613459314107074039291811569329219648848907543004197890512187794469896370420793533163493423472892065087488"}, + {"0x1.f03542dfb8371p+886", 267, "1.00000000000000008799384052806007212355265429582217771348066928066975608179024346593830042588848532639628623092150981090760386146002202723860579276760264226502822677971763258912553652372841773828685389482345810917805054511477545980009263522048349795485862131796226867e+267"}, + {"0x1.362149cbd3226p+890", 268, "9999999999999999734382248541602273058775185611228237505937125919871459640244446566940444044768686890151491676229963091901658245840231469410183497393091354632481226134593141070740392918115693292196488489075430041978905121877944698963704207935331634934234728920650874880"}, + {"0x1.362149cbd3227p+890", 268, "1.000000000000000156727209932399979014157735736641790091212843293879322152449722751484854038735455308824968468900617911938066683585621355417158258584578746346096289279472623678356434862878526783727176922373007172166146564870964053742325963876653698631719710373500577382e+268"}, + {"0x1.83a99c3ec7eafp+893", 269, "99999999999999990012263082286432662256543169091523721434606031123027548865433341877772055077343404109122144711194766809100548098338386355056238620120129111010885594705399027856108106338478634741663761952135733701058809111452663635798820356028494943810497789949089153024"}, + {"0x1.83a99c3ec7eb0p+893", 269, "1.0000000000000000467538188854561279891896054313304102868413648727440164393945558946103682581803033369390768881340449502893261681846624303314743132774169798163873892798646379355869975202383523110226600782937286713851929332610623034347526380267813775487419678846392834458e+269"}, + {"0x1.e494034e79e5bp+896", 270, "999999999999999929448868435382686895890266438998271828845121223533023678802377913944250092254807900260792535316367124530669618423639576906744771616444428851364562613616119809966264354755499540137842111275831603885509059543833769773341090453584235060232375896520569913344"}, + {"0x1.e494034e79e5cp+896", 270, "1.00000000000000004675381888545612798918960543133041028684136487274401643939455589461036825818030333693907688813404495028932616818466243033147431327741697981638738927986463793558699752023835231102266007829372867138519293326106230343475263802678137754874196788463928344576e+270"}, + {"0x1.2edc82110c2f9p+900", 271, "9999999999999999529098585253973751145501342374646995204443699533752222309208135100774737254399069875964494058799026896824009283758441475916906799486389390443691279468658234350904109878520700943148057046794110173854458342872794765056233999682236635579342942941443126198272"}, + {"0x1.2edc82110c2fap+900", 271, "1.000000000000000140597779245514880863829076625196121053238359792112810647868298279143262790920699686281704370388187210896251407993480713071257946606195020588405650612863452436083584052624634527730514451908046325384940032234845130363881876085339091539549641475134254271693e+271"}, + {"0x1.7a93a2954f3b7p+903", 272, "99999999999999991537227438137387396469434575991841521388557198562770454753131655626431591234374844785939841297824578543963083245231683449577722661712772273556182341366629763489177637489755720763166395523368395578554699469776634573397170474480057796161122485794632428945408"}, + {"0x1.7a93a2954f3b8p+903", 272, "1.0000000000000000655226109574678785641174996701035524401207638566177752810893043715169471647283826068076023845848734024107112161464260868794310399431725879707910415464644008356863148267156087543642309530165922021851423530558188688205784856384929203469035026027382776109466e+272"}, + {"0x1.d9388b3aa30a5p+906", 273, "999999999999999945402341696592674884578976541955442659132610359825718694242914119314842162820675279649039207299571308833846909191138684972507989282336695782607667040225918275050684065261167516978177354790265605065466066369376850351293060923539046438669680406904714953752576"}, + {"0x1.d9388b3aa30a6p+906", 273, "1.00000000000000006552261095746787856411749967010355244012076385661777528108930437151694716472838260680760238458487340241071121614642608687943103994317258797079104154646440083568631482671560875436423095301659220218514235305581886882057848563849292034690350260273827761094656e+273"}, + {"0x1.27c35704a5e67p+910", 274, "9999999999999999213782878444176341486712719163258207029349796604673073768736360688744211624391338142173265718425108901184740478000812045911233791501695173449709921389782217629235579129702792695009666351450002856415308090320884466574359759805482716570229159677380024223137792"}, + {"0x1.27c35704a5e68p+910", 274, "1.000000000000000113570718661817960035932908921362796352516025255334597915827860472397789165491465537671027655498994239841456938928541047642200260207506944846064391348959793859940567131297385249318652392307122841033012867730395676208292655524474469910197031481071702673824154e+274"}, + {"0x1.71b42cc5cf601p+913", 275, "99999999999999995981677400789769932612359931733321583285118877944076548466448094957909476304960015890806678857380756006307062602577317320133875536163700284518967198097453618232695975663570046546450378657742479671982722077174989256760731188933351130765773907040474247261585408"}, + {"0x1.71b42cc5cf602p+913", 275, "1.0000000000000001135707186618179600359329089213627963525160252553345979158278604723977891654914655376710276554989942398414569389285410476422002602075069448460643913489597938599405671312973852493186523923071228410330128677303956762082926555244744699101970314810717026738241536e+275"}, + {"0x1.ce2137f743381p+916", 276, "999999999999999929065985077113647184161737396527299728918221484261998998431805045015355882561227083155474615188770224107393363445219598313166454392463014445014728107377484646804238281703363508693674065431485187857190091380020735839470243162305319587149880588271350432374194176"}, + {"0x1.ce2137f743382p+916", 276, "1.00000000000000005206914080024985575200918507975096414465009066497706494336250866327031140451471938616584330872891956793010241376743389786585565826915896804571450360176569078889512418143271133577699295001524362330773860894693736275201851807041808646918131451680491859334083379e+276"}, + {"0x1.20d4c2fa8a030p+920", 277, "9999999999999998060628293539774386163142897133036353131863523035469330535011014267604003606077347801451059216486208802846843131230052987604772505157670608443149526129892785047133523819740156816103551808477267524066415738131041089269219682541925527051184466597377822714075545600"}, + {"0x1.20d4c2fa8a031p+920", 277, "1.000000000000000002867878510995372324870206006461498378357342992691038565390227215968329195733322464961695831312859830401018793638548178044779976718480586605434593404010408332058769821540972204943665396181740249127519201920170711986999208107172979716368740945391491328954177946e+277"}, + {"0x1.6909f3b92c83dp+923", 278, "99999999999999996350686867959178558315902274782992576532314485486221746301240205812674342870820492799837784938001204037775189753543960218791943147793788145321066524580618236658968633362758090027700335311493754978334367629875739137498376013657689431411868208826074951744485326848"}, + {"0x1.6909f3b92c83ep+923", 278, "1.000000000000000120950908005206132550003755782356216217459937406177501872523702689493086496808675075851649777111403200470819481947873905615361612440108702062106377878623086228466020285281146118943651525382148347160045778784410673823045552018961235923118917516783716763482151977e+278"}, + {"0x1.c34c70a777a4cp+926", 279, "999999999999999932018060814468916189790076140924667674895786344599160581110141931853474815088110898427723463833733808359138380652952741502430995285503717331431522719242801594214419543296867856543673718661495390308003255801626734885371401760100025992318635002556156068237393526784"}, + {"0x1.c34c70a777a4dp+926", 279, "1.00000000000000005797329227496039376326586256854570003660522038565138810871918243694654926956848701671034100601884673643359244818290018424438474005524037381854809282549632468371548670461972003147699225647526402820936493779014936084382083526600749927951882334537452986506723249357e+279"}, + {"0x1.1a0fc668aac6fp+930", 280, "9999999999999998312538756460757341310094469988278417855282391117573785590229095277790152515038100038016294300856434658995751266289947873088679994697143921417382666342399831226135658142385861165970188884104804799869139102108086341186118549553740473625584843283014570307735223533568"}, + {"0x1.1a0fc668aac70p+930", 280, "1.000000000000000032782245982862098248570705283021493564263333577440942603197374335927934378672411793053817497581824150818701634676910695695993991101293042521124778804245620065815273272355149596490328548912510300629092601392444835652130948564826004622078785676810855105701264700211e+280"}, + {"0x1.6093b802d578bp+933", 281, "99999999999999987155954971343300695452169865566657214127525800489409136785780248940879907693753036165206704358487960288340042823857796898629319779603012221761556906824111051125390730586189881257568082051088644411534964844713587442531567367726443881446254459800333664575907082272768"}, + {"0x1.6093b802d578cp+933", 281, "1.0000000000000000327822459828620982485707052830214935642633335774409426031973743359279343786724117930538174975818241508187016346769106956959939911012930425211247788042456200658152732723551495964903285489125103006290926013924448356521309485648260046220787856768108551057012647002112e+281"}, + {"0x1.b8b8a6038ad6ep+936", 282, "999999999999999903804088967318825213331499981137556425872873119403461614925716858712626137284506647932417134384268512470460669526244514328233356457082706278317411015442012422166180499160548969358610366191211215418098239036197666670678728654776751975985792813764840337747509598224384"}, + {"0x1.b8b8a6038ad6fp+936", 282, "1.0000000000000000327822459828620982485707052830214935642633335774409426031973743359279343786724117930538174975818241508187016346769106956959939911012930425211247788042456200658152732723551495964903285489125103006290926013924448356521309485648260046220787856768108551057012647002112e+282"}, + {"0x1.137367c236c65p+940", 283, "9999999999999999553953517735361344274271821018911312812290573026184540102343798495987494338396687059809772796632907678097570555865109868753376103147668407754403581309634554796258176084383892202112976392797308495024959839786965342632596166187964530344229899589832462449290116390191104"}, + {"0x1.137367c236c66p+940", 283, "1.000000000000000161760402998405371283809910584905430702653794035478423591469031813143242620060316938175217860779379789166942599827576877063754625745503378763932146593049227709464366045549750223622046731633809385840086963748692004633583168474875257268171778539856869873655019802198016e+283"}, + {"0x1.585041b2c477ep+943", 284, "99999999999999991412234152856228705615063640528827139694410995604646009398744945688985079659553905954212916344007296353831994673829780883765420722861953317774200043854630103365810792101611701952914782080891514223497778802469744018919490624758069218767323224280852151918381000638332928"}, + {"0x1.585041b2c477fp+943", 284, "1.0000000000000000792143825084576765412568191916997109340838993423344357589751710277254453455720576452975216283329441806240683821311505209883878195732087635685354312082149188175289466707052058222577470946921779713050505718406938164854537477324437355746722631075074204221646165369264538e+284"}, + {"0x1.ae64521f7595ep+946", 285, "999999999999999980159157920520442850193109519852847211800025710561650359982538085224088616186146493844286149397221450372619320895438893697947652166455225334059372746413748147206443420891752540620587530362220273863006901551095990707698442841525909542472844588688081080376132618600579072"}, + {"0x1.ae64521f7595fp+946", 285, "1.00000000000000011223279070443675443827805574898199884151185721959203089197271534189256425536736136244860012131151842404121806920972106341853454204212660964669411736214864237430311442064302358280346694946883053711906512860389309174470551602941634425207206928044720020276077784303507866e+285"}, + {"0x1.0cfeb353a97dap+950", 286, "9999999999999998216707985798208689444911740448978652561458278997251937215943253772219178491686886515191093831000650819703008229183002900332433843156495641588976792075318750746904382211902272900011322274342879579557370290877394694632899550160573878909537749585771381335145583492791795712"}, + {"0x1.0cfeb353a97dbp+950", 286, "1.000000000000000032988611034086967485427088011504507863684758314173802572778608987891478871858632441286011738162940239840058820221151761586182408116723779059113270592707705838045111820792260957493739298004864379165430192372214831122501272116682083426312534465391728729329990708374378906e+286"}, + {"0x1.503e602893dd1p+953", 287, "99999999999999990619792356152730836086553963154052229916140006550463726206803882148974225824466616742587032512521514511820402183944087865441899383607925011898391576160220738003230766103104075699817505566251852643961429440152961412697448185630726610509727876130297437184073129291725930496"}, + {"0x1.503e602893dd2p+953", 287, "1.0000000000000000752521735249401871936142708048258363851925443970635243430154657100253910763966211992393922091755152714140104196817220558967702128769386220391563888697428719907160465407126676909922607121189796634073688250291099034543435355368070225333842863667546468484930771801934187725e+287"}, + {"0x1.a44df832b8d45p+956", 288, "999999999999999872387073568844732594315793396883459481955171199192859845878553443782612494614275161063165948315155119859042742270984643205948750027907375734949421139974074457895559885094715370199357924371226299046063388276013556261500671120207314819439877240212639876510262115462027411456"}, + {"0x1.a44df832b8d46p+956", 288, "1.00000000000000000763047353957503566051477833551171075078008666443996951063649495461113154913583918651398345555539522089568786054480958499982972526059487327108739962648660614644255098884001691739462644953639520862026701277807778772339591406460711996206948332457397785783213882528295498547e+288"}, + {"0x1.06b0bb1fb384bp+960", 289, "9999999999999998453383935746986719810759964091578092281901881061434379129269651416169086837099623559730024468671070996517137186162196548471725549813698762277218254426715681201861616643456550607603042193381925171312226633756007099691216225313273537909139560233403722802458867734978418966528"}, + {"0x1.06b0bb1fb384cp+960", 289, "1.000000000000000061727833527867156886994372310963011258310052850538813376539671558942539170944464796694310458451491261310345907854339561717382115353669872285542591021091618821861347430338137536272733859602462772449948462578903480308154011242367042019121325758318513050360889509211326015078e+289"}, + {"0x1.485ce9e7a065ep+963", 290, "99999999999999988861628156533236896225967158951884963421416105502251300564950642508203478115686284411726404918398393198344015646384363622121446705582987543928597855835557826052119881754415155586279014739104656819496782321626126403692810027353529143655542997033600043426888732064053872033792"}, + {"0x1.485ce9e7a065fp+963", 290, "1.0000000000000000617278335278671568869943723109630112583100528505388133765396715589425391709444647966943104584514912613103459078543395617173821153536698722855425910210916188218613474303381375362727338596024627724499484625789034803081540112423670420191213257583185130503608895092113260150784e+290"}, + {"0x1.9a742461887f6p+966", 291, "999999999999999957860902350346284132153551878096514283852517773229033154005572478626236537071903625148082612890986863714202457020042006419681526374965874177788623543449994485057258262661745948026767632275613049896960078961318150545418464661067991669581788285529005480705688196068853638234112"}, + {"0x1.9a742461887f7p+966", 291, "1.0000000000000000963501439203741144719413124552518435831292312096420734507177045857146400489019851872097197403049927271757270581324387468166156450132378716547939135136388269341293771528969347323547226020447460133009445904514319235623991934361333921356345049159150155735792899469254834740265e+291"}, + {"0x1.008896bcf54f9p+970", 292, "9999999999999997916738124663128877244082391855101191247204616495333847979510139501201523228758057506741180599941798275603729356851659179433605840090394772053822755792233955461707155943795194068332216685526534938121786651731816229250415901309895111103185283290657933692573660950408978352832512"}, + {"0x1.008896bcf54fap+970", 292, "1.000000000000000013256598978357416268068656108958646003563203147794249272690425321461597941803936249972737463856589209098812297465000702578455173830274673168590739531525527464686105818755821461757949620183266235258553883557363659752210756171094151856002874937683409517855128896411505572551066e+292"}, + {"0x1.40aabc6c32a38p+973", 293, "99999999999999992462348437353960485060448933957923525202610654848990348279466077292501969423268405025328970231162545648343655275306678872441733790178059478330735395060467469727994972900530063978805843953102113868000379620369084502134308975505229555772913629423636305841602377586326247764393984"}, + {"0x1.40aabc6c32a39p+973", 293, "1.0000000000000001018897135831752276855328228783380567551002997470985950625861898699981761893751884496921852254015529617141880421769346164324930097587687515538741251124463802320922619085063422837278408008355113318371039709110364744830784225871360081542766135811304559772942340169597486674581914e+293"}, + {"0x1.90d56b873f4c6p+976", 294, "999999999999999924623484373539604850604489339579235252026106548489903482794660772925019694232684050253289702311625456483436552753066788724417337901780594783307353950604674697279949729005300639788058439531021138680003796203690845021343089755052295557729136294236363058416023775863262477643939840"}, + {"0x1.90d56b873f4c7p+976", 294, "1.00000000000000006643646774124810311854715617058629245448546110737685674662788405058354489034668756980440612078356746066803774429216105089087787538737112019976077088007803912512979947260613395493988432857461329320568393596956734859073135602071926563496711812375163739351859196874045142949534106e+294"}, + {"0x1.f50ac6690f1f8p+979", 295, "9999999999999999813486777206230041577815560719820581330098483720446847883279500839884297726782854580737362697004022581572770293687044935910015528960168049498887207223940204684198896264456339658487887951484580004902758521100414464490983962613190835886243290260424727924570510530141380583845003264"}, + {"0x1.f50ac6690f1f9p+979", 295, "1.000000000000000094799064414789802772135689536787703894977332019154247399394528706115249929569488273714629404477955861504957982599979903324169982884489225283051454265972712010699769421326300617970249506383331724110819963922742649304609009273852659650414714489654692260539105607315889219865621299e+295"}, + {"0x1.3926bc01a973bp+983", 296, "99999999999999998134867772062300415778155607198205813300984837204468478832795008398842977267828545807373626970040225815727702936870449359100155289601680494988872072239402046841988962644563396584878879514845800049027585211004144644909839626131908358862432902604247279245705105301413805838450032640"}, + {"0x1.3926bc01a973cp+983", 296, "1.0000000000000001628692964312898819407481696156710913521578222074199849660344758793913420237042099630991652853444880235135665545387451491640710408775726774829490943921199269360676972982547006092431259331242559582831464310103633710179153770813728052874889457678220239413883383398969399167542938829e+296"}, + {"0x1.87706b0213d09p+986", 297, "999999999999999872436306494222877488001587945768638201521064070819504681704034606746682422062730755058478860313950798943503314266680100247159860107083281430052496520558476587831205023360193979812186512362979225814553504769848291707808207769286850569305558980974742103098278680884456943362624192512"}, + {"0x1.87706b0213d0ap+986", 297, "1.0000000000000000176528014627563797143748787807198647768394431391197448238692552430690122228834703590788220728292194112285349344027126247056154504923279794565007954563392017619494511608074472945276562227436175920488499678901058313628617924253298279283972523743983830222433085103906984300584590377e+297"}, + {"0x1.e94c85c298c4cp+989", 298, "9999999999999999595662034753429788238255624467393741467120915117996487670031669885400803025551745174706847878231119663145222863482996149222332143382301002459214758820269116923021527058285459686414683385913622455551313826420028155008403585629126369847605750170289266545852965785882018353801250996224"}, + {"0x1.e94c85c298c4dp+989", 298, "1.00000000000000007573939945016978060492419511470035540696679476643984088073534349759794414321176620068695935783532685614254758245712563448899768664642585866708011503065149183159674961578634862041384410689587293854256855313820884722488322628774701887203392973176783938990132044219319502473679297577e+298"}, + {"0x1.31cfd3999f7afp+993", 299, "99999999999999986662764669548153739894665631237058913850832890808749507601742578129378923002990117089766513181334005445210204946123879926882163649167349350899456456312724758086647517786230384722356772394775369116518164624503799012160606438304513147494189124523779646633247748770420728389479079870464"}, + {"0x1.31cfd3999f7b0p+993", 299, "1.0000000000000000525047602552044202487044685811081591549158541155118024579889081957863713750804478640437044438328838781769425232353604305756447921847867069828483872009265758037378302337947880900593689532349707999450811190389676408800746527427801424945792587888200568428381156694721963868654594005402e+299"}, + {"0x1.7e43c8800759bp+996", 300, "999999999999999903803069407426113968898218766118103141789833949572356552411722264192305659040010509526872994217248819197070144216063125530186267630296136203765329090687113225440746189048800695790727969805197112921161540803823920273299782054992133678869364753954248541633605124057805104488924519071744"}, + {"0x1.7e43c8800759cp+996", 300, "1.00000000000000005250476025520442024870446858110815915491585411551180245798890819578637137508044786404370444383288387817694252323536043057564479218478670698284838720092657580373783023379478809005936895323497079994508111903896764088007465274278014249457925878882005684283811566947219638686545940054016e+300"}, + {"0x1.ddd4baa009302p+999", 301, "9999999999999999335434075769817752248594687291161143444150379827602457335271594505111188022480979804302392841403758309930446200199225865392779725411942503595819407127350057411001629979979981746444561664911518503259454564508526643946547561925497354420113435609274102018745072331406833609642314953654272"}, + {"0x1.ddd4baa009303p+999", 301, "1.00000000000000005250476025520442024870446858110815915491585411551180245798890819578637137508044786404370444383288387817694252323536043057564479218478670698284838720092657580373783023379478809005936895323497079994508111903896764088007465274278014249457925878882005684283811566947219638686545940054016e+301"}, + {"0x1.2aa4f4a405be1p+1003", 302, "99999999999999988595886650569271721532146878831929642021471152965962304374245995240101777311515802698485322026337261211948545873374744892473124468375726771027536211745837771604509610367928220847849105179362427047829119141560667380048679757245757262098417746977035154548906385860807815060374033329553408"}, + {"0x1.2aa4f4a405be2p+1003", 302, "1.0000000000000000762970307908489492534734685515065681170160173420621138028812579448414218896469178407663974757713854876137221038784479993829181561135051983075016764985648898162653636809541460731423515105837345898689082515565906361771586320528262239050928418343985861710308373567384989920457049815751066e+302"}, + {"0x1.754e31cd072d9p+1006", 303, "999999999999999847891233648661470807691068835681842080854450367179124891914700353912936949808806064228544369161770037020638129704807338833093862397807681590830099241237075296001042588224309435545718960035602206600167779387409881325152430676383842364162444596844704620380709158981993982315347403639619584"}, + {"0x1.754e31cd072dap+1006", 303, "1.00000000000000000016176507678645643821266864623165943829549501710111749922573874786526024303421391525377977356818033741602744582056777919964339154160602606861115074612228497617725665004420052727680732706769046211266142750019705122648989826067876339144937608854729232081412795748633065546891912226327757e+303"}, + {"0x1.d2a1be4048f90p+1009", 304, "9999999999999999392535525055364621860040287220117324953190771571323204563013233902843309257440507748436856118056162172578717193742636030530235798840866882774987301441682011041067710253162440905843719802548551599076639682550821832659549112269607949805346034918662572406407604380845959862074904348138143744"}, + {"0x1.d2a1be4048f91p+1009", 304, "1.000000000000000061069977648036450690421308570451586381271912877069914542150154105446189560324377055663873935330744457574183172266871955346263203199125363859723571348076368848247742274772156963969242673880525764317658886745311919187024885294396731802364148685228327400987495476888065324730347809712740762e+304"}, + {"0x1.23a516e82d9bap+1013", 305, "99999999999999993925355250553646218600402872201173249531907715713232045630132339028433092574405077484368561180561621725787171937426360305302357988408668827749873014416820110410677102531624409058437198025485515990766396825508218326595491122696079498053460349186625724064076043808459598620749043481381437440"}, + {"0x1.23a516e82d9bbp+1013", 305, "1.0000000000000001341598327335364437930716764795154987128436143090324709936594525345433047410725728241559869294458214017639700440024369667222069771881485692090584760704212694947323250244457046880001650900559281269636558378394497607396668697348582938954618758012455694971955365001701469278440622346520965939e+305"}, + {"0x1.6c8e5ca239028p+1016", 306, "999999999999999861291040414336469543176969619010226008309262296372260241358071732580741399612641955118765084749534143455432389522994257585350220962461935904874831773666973747856549425664459851618054736334425973085267220421335152276470127823801795414563694568114532338018850013250375609552861714878501486592"}, + {"0x1.6c8e5ca239029p+1016", 306, "1.00000000000000001721606459673645482883108782501323898232889201789238067124457504798792045187545959456860613886169829106031104922553294852069693880571144065012262851466942846035699262496802832955068922417528434673006071608882921425543969463011979454650551241561798214326267086291881636286211915474912726221e+306"}, + {"0x1.c7b1f3cac7433p+1019", 307, "9999999999999999860310597602564577717002641838126363875249660735883565852672743849064846414228960666786379280392654615393353172850252103336275952370615397010730691664689375178569039851073146339641623266071126720011020169553304018596457812688561947201171488461172921822139066929851282122002676667750021070848"}, + {"0x1.c7b1f3cac7434p+1019", 307, "1.000000000000000110771079106176446000223558748615046766740669850804452929176477037232227883233150178238510771328996779623238245047056163081904969511661143497271306559270901287857258544550169416310269916879799370916936813489325651442821434713910594025670603124120052026408963372719880814847673618671502727578e+307"}, + {"0x1.1ccf385ebc89fp+1023", 308, "99999999999999981139503267596847425176765179308926185662298078548582170379439067165044410288854031049481594743364161622187121841818187648603927125262209438639553681654618823985640760188731793867961170022535129351893330180773705244319986644578003569234231285691342840034082734135647456849389933411990123839488"}, + {"0x1.1ccf385ebc8a0p+1023", 308, "1.0000000000000000109790636294404554174049230967731184633681068290315758540491149153716332897849468889906124966972117251561159028374314008832830700919814604603127166450293302718569748969958855904333838446616500117842689762621294517762809119578670745812278397017178441510529180289320787327297488571543022311834e+308"}, + {"0x1.a36e2eb1c432cp-14", 309, "9.99999999999999912396464463171241732197813689708709716796875e-5"}, + {"0x1.a36e2eb1c432dp-14", 309, "0.000100000000000000004792173602385929598312941379845142364501953125"}, + {"0x1.0624dd2f1a9fbp-10", 309, "0.00099999999999999980397624721462079833145253360271453857421875"}, + {"0x1.0624dd2f1a9fcp-10", 309, "0.001000000000000000020816681711721685132943093776702880859375"}, + {"0x1.47ae147ae147ap-7", 309, "0.0099999999999999984734433411404097569175064563751220703125"}, + {"0x1.47ae147ae147bp-7", 309, "0.01000000000000000020816681711721685132943093776702880859375"}, + {"0x1.9999999999999p-4", 309, "0.09999999999999999167332731531132594682276248931884765625"}, + {"0x1.999999999999ap-4", 309, "0.1000000000000000055511151231257827021181583404541015625"}, + {"0x1.fffffffffffffp-1", 309, "0.99999999999999988897769753748434595763683319091796875"}, + {"0x1.0000000000000p+0", 309, "1"}, + {"0x1.3ffffffffffffp+3", 309, "9.9999999999999982236431605997495353221893310546875"}, + {"0x1.4000000000000p+3", 309, "10"}, + {"0x1.8ffffffffffffp+6", 309, "99.9999999999999857891452847979962825775146484375"}, + {"0x1.9000000000000p+6", 309, "100"}, + {"0x1.f3fffffffffffp+9", 309, "999.9999999999998863131622783839702606201171875"}, + {"0x1.f400000000000p+9", 309, "1000"}, + {"0x1.387ffffffffffp+13", 309, "9999.999999999998181010596454143524169921875"}, + {"0x1.3880000000000p+13", 309, "10000"}, + {"0x1.869ffffffffffp+16", 309, "99999.999999999985448084771633148193359375"}, + {"0x1.86a0000000000p+16", 309, "100000"}, + {"0x1.e847fffffffffp+19", 309, "999999.999999999883584678173065185546875"}, + {"0x1.e848000000000p+19", 309, "1000000"}, + {"0x1.312cfffffffffp+23", 309, "9999999.99999999813735485076904296875"}, + {"0x1.312d000000000p+23", 309, "10000000"}, + {"0x1.7d783ffffffffp+26", 309, "99999999.99999998509883880615234375"}, + {"0x1.7d78400000000p+26", 309, "100000000"}, + {"0x1.dcd64ffffffffp+29", 309, "999999999.99999988079071044921875"}, + {"0x1.dcd6500000000p+29", 309, "1000000000"}, + {"0x1.2a05f1fffffffp+33", 309, "9999999999.9999980926513671875"}, + {"0x1.2a05f20000000p+33", 309, "10000000000"}, + {"0x1.74876e7ffffffp+36", 309, "99999999999.9999847412109375"}, + {"0x1.74876e8000000p+36", 309, "100000000000"}, + {"0x1.d1a94a1ffffffp+39", 309, "999999999999.9998779296875"}, + {"0x1.d1a94a2000000p+39", 309, "1000000000000"}, + {"0x1.2309ce53fffffp+43", 309, "9999999999999.998046875"}, + {"0x1.2309ce5400000p+43", 309, "10000000000000"}, + {"0x1.6bcc41e8fffffp+46", 309, "99999999999999.984375"}, + {"0x1.6bcc41e900000p+46", 309, "100000000000000"}, + {"0x1.c6bf52633ffffp+49", 309, "999999999999999.875"}, + {"0x1.c6bf526340000p+49", 309, "1000000000000000"}, + {"0x1.1c37937e07fffp+53", 309, "9999999999999998"}, + {"0x1.1c37937e08000p+53", 309, "10000000000000000"}, + {"0x1.6345785d89fffp+56", 309, "99999999999999984"}, + {"0x1.6345785d8a000p+56", 309, "100000000000000000"}, + {"0x1.bc16d674ec7ffp+59", 309, "999999999999999872"}, + {"0x1.bc16d674ec800p+59", 309, "1000000000000000000"}, + {"0x1.158e460913cffp+63", 309, "9999999999999997952"}, + {"0x1.158e460913d00p+63", 309, "10000000000000000000"}, + {"0x1.5af1d78b58c3fp+66", 309, "99999999999999983616"}, + {"0x1.5af1d78b58c40p+66", 309, "100000000000000000000"}, + {"0x1.b1ae4d6e2ef4fp+69", 309, "999999999999999868928"}, + {"0x1.b1ae4d6e2ef50p+69", 309, "1000000000000000000000"}, + {"0x1.0f0cf064dd591p+73", 309, "9999999999999997902848"}, + {"0x1.0f0cf064dd592p+73", 309, "10000000000000000000000"}, + {"0x1.52d02c7e14af6p+76", 309, "99999999999999991611392"}, + {"0x1.52d02c7e14af7p+76", 309, "100000000000000008388608"}, + {"0x1.a784379d99db4p+79", 309, "999999999999999983222784"}, + {"0x1.a784379d99db5p+79", 309, "1000000000000000117440512"}, + {"0x1.08b2a2c280290p+83", 309, "9999999999999998758486016"}, + {"0x1.08b2a2c280291p+83", 309, "10000000000000000905969664"}, + {"0x1.4adf4b7320334p+86", 309, "99999999999999987584860160"}, + {"0x1.4adf4b7320335p+86", 309, "100000000000000004764729344"}, + {"0x1.9d971e4fe8401p+89", 309, "999999999999999875848601600"}, + {"0x1.9d971e4fe8402p+89", 309, "1000000000000000013287555072"}, + {"0x1.027e72f1f1281p+93", 309, "9999999999999999583119736832"}, + {"0x1.027e72f1f1282p+93", 309, "10000000000000001782142992384"}, + {"0x1.431e0fae6d721p+96", 309, "99999999999999991433150857216"}, + {"0x1.431e0fae6d722p+96", 309, "100000000000000009025336901632"}, + {"0x1.93e5939a08ce9p+99", 309, "999999999999999879147136483328"}, + {"0x1.93e5939a08ceap+99", 309, "1000000000000000019884624838656"}, + {"0x1.f8def8808b024p+102", 309, "9999999999999999635896294965248"}, + {"0x1.f8def8808b025p+102", 309, "10000000000000000761796201807872"}, + {"0x1.3b8b5b5056e16p+106", 309, "99999999999999987351763694911488"}, + {"0x1.3b8b5b5056e17p+106", 309, "100000000000000005366162204393472"}, + {"0x1.8a6e32246c99cp+109", 309, "999999999999999945575230987042816"}, + {"0x1.8a6e32246c99dp+109", 309, "1000000000000000089690419062898688"}, + {"0x1.ed09bead87c03p+112", 309, "9999999999999999455752309870428160"}, + {"0x1.ed09bead87c04p+112", 309, "10000000000000000608673814477275136"}, + {"0x1.3426172c74d82p+116", 309, "99999999999999996863366107917975552"}, + {"0x1.3426172c74d83p+116", 309, "100000000000000015310110181627527168"}, + {"0x1.812f9cf7920e2p+119", 309, "999999999999999894846684784341549056"}, + {"0x1.812f9cf7920e3p+119", 309, "1000000000000000042420637374017961984"}, + {"0x1.e17b84357691bp+122", 309, "9999999999999999538762658202121142272"}, + {"0x1.e17b84357691cp+122", 309, "10000000000000000719354278919532445696"}, + {"0x1.2ced32a16a1b1p+126", 309, "99999999999999997748809823456034029568"}, + {"0x1.2ced32a16a1b2p+126", 309, "100000000000000016638275754934614884352"}, + {"0x1.78287f49c4a1dp+129", 309, "999999999999999939709166371603178586112"}, + {"0x1.78287f49c4a1ep+129", 309, "1000000000000000090824893823431825424384"}, + {"0x1.d6329f1c35ca4p+132", 309, "9999999999999999094860208812374492184576"}, + {"0x1.d6329f1c35ca5p+132", 309, "10000000000000000303786028427003666890752"}, + {"0x1.25dfa371a19e6p+136", 309, "99999999999999981277195531206711524196352"}, + {"0x1.25dfa371a19e7p+136", 309, "100000000000000000620008645040778319495168"}, + {"0x1.6f578c4e0a060p+139", 309, "999999999999999890143207767403382423158784"}, + {"0x1.6f578c4e0a061p+139", 309, "1000000000000000044885712678075916785549312"}, + {"0x1.cb2d6f618c878p+142", 309, "9999999999999998901432077674033824231587840"}, + {"0x1.cb2d6f618c879p+142", 309, "10000000000000000139372116959414099130712064"}, + {"0x1.1efc659cf7d4bp+146", 309, "99999999999999989014320776740338242315878400"}, + {"0x1.1efc659cf7d4cp+146", 309, "100000000000000008821361405306422640701865984"}, + {"0x1.66bb7f0435c9ep+149", 309, "999999999999999929757289024535551219930759168"}, + {"0x1.66bb7f0435c9fp+149", 309, "1000000000000000088213614053064226407018659840"}, + {"0x1.c06a5ec5433c6p+152", 309, "9999999999999999931398190359470212947659194368"}, + {"0x1.c06a5ec5433c7p+152", 309, "10000000000000001199048790587699614444362399744"}, + {"0x1.18427b3b4a05bp+156", 309, "99999999999999984102174700855949311516153479168"}, + {"0x1.18427b3b4a05cp+156", 309, "100000000000000004384584304507619735463404765184"}, + {"0x1.5e531a0a1c872p+159", 309, "999999999999999881586566215862833963056037363712"}, + {"0x1.5e531a0a1c873p+159", 309, "1000000000000000043845843045076197354634047651840"}, + {"0x1.b5e7e08ca3a8fp+162", 309, "9999999999999999464902769475481793196872414789632"}, + {"0x1.b5e7e08ca3a90p+162", 309, "10000000000000000762976984109188700329496497094656"}, + {"0x1.11b0ec57e6499p+166", 309, "99999999999999986860582406952576489172979654066176"}, + {"0x1.11b0ec57e649ap+166", 309, "100000000000000007629769841091887003294964970946560"}, + {"0x1.561d276ddfdc0p+169", 309, "999999999999999993220948674361627976461708441944064"}, + {"0x1.561d276ddfdc1p+169", 309, "1000000000000000159374448147476112089437590976987136"}, + {"0x1.aba4714957d30p+172", 309, "9999999999999999932209486743616279764617084419440640"}, + {"0x1.aba4714957d31p+172", 309, "10000000000000001261437482528532152668424144699785216"}, + {"0x1.0b46c6cdd6e3ep+176", 309, "99999999999999999322094867436162797646170844194406400"}, + {"0x1.0b46c6cdd6e3fp+176", 309, "100000000000000020589742799994816764107083808679919616"}, + {"0x1.4e1878814c9cdp+179", 309, "999999999999999908150356944127012110618056584002011136"}, + {"0x1.4e1878814c9cep+179", 309, "1000000000000000078291540404596243842305360299886116864"}, + {"0x1.a19e96a19fc40p+182", 309, "9999999999999998741221202520331657642805958408251899904"}, + {"0x1.a19e96a19fc41p+182", 309, "10000000000000000102350670204085511496304388135324745728"}, + {"0x1.05031e2503da8p+186", 309, "99999999999999987412212025203316576428059584082518999040"}, + {"0x1.05031e2503da9p+186", 309, "100000000000000009190283508143378238084034459715684532224"}, + {"0x1.4643e5ae44d12p+189", 309, "999999999999999874122120252033165764280595840825189990400"}, + {"0x1.4643e5ae44d13p+189", 309, "1000000000000000048346692115553659057528394845890514255872"}, + {"0x1.97d4df19d6057p+192", 309, "9999999999999999438119489974413630815797154428513196965888"}, + {"0x1.97d4df19d6058p+192", 309, "10000000000000000831916064882577577161779546469035791089664"}, + {"0x1.fdca16e04b86dp+195", 309, "99999999999999997168788049560464200849936328366177157906432"}, + {"0x1.fdca16e04b86ep+195", 309, "100000000000000008319160648825775771617795464690357910896640"}, + {"0x1.3e9e4e4c2f344p+199", 309, "999999999999999949387135297074018866963645011013410073083904"}, + {"0x1.3e9e4e4c2f345p+199", 309, "1000000000000000127793096885319003999249391192200302120927232"}, + {"0x1.8e45e1df3b015p+202", 309, "9999999999999999493871352970740188669636450110134100730839040"}, + {"0x1.8e45e1df3b016p+202", 309, "10000000000000000921119045676700069727922419559629237113585664"}, + {"0x1.f1d75a5709c1ap+205", 309, "99999999999999992084218144295482124579792562202350734542897152"}, + {"0x1.f1d75a5709c1bp+205", 309, "100000000000000003502199685943161173046080317798311825604870144"}, + {"0x1.3726987666190p+209", 309, "999999999999999875170255276364105051932774599639662981181079552"}, + {"0x1.3726987666191p+209", 309, "1000000000000000057857959942726969827393378689175040438172647424"}, + {"0x1.84f03e93ff9f4p+212", 309, "9999999999999998751702552763641050519327745996396629811810795520"}, + {"0x1.84f03e93ff9f5p+212", 309, "10000000000000000213204190094543968723012578712679649467743338496"}, + {"0x1.e62c4e38ff872p+215", 309, "99999999999999999209038626283633850822756121694230455365568299008"}, + {"0x1.e62c4e38ff873p+215", 309, "100000000000000010901051724930857196452234783424494612613028642816"}, + {"0x1.2fdbb0e39fb47p+219", 309, "999999999999999945322333868247445125709646570021247924665841614848"}, + {"0x1.2fdbb0e39fb48p+219", 309, "1000000000000000132394543446603018655781305157705474440625207115776"}, + {"0x1.7bd29d1c87a19p+222", 309, "9999999999999999827367757839185598317239782875580932278577147150336"}, + {"0x1.7bd29d1c87a1ap+222", 309, "10000000000000001323945434466030186557813051577054744406252071157760"}, + {"0x1.dac74463a989fp+225", 309, "99999999999999995280522225138166806691251291352861698530421623488512"}, + {"0x1.dac74463a98a0p+225", 309, "100000000000000007253143638152923512615837440964652195551821015547904"}, + {"0x1.28bc8abe49f63p+229", 309, "999999999999999880969493773293127831364996015857874003175819882528768"}, + {"0x1.28bc8abe49f64p+229", 309, "1000000000000000072531436381529235126158374409646521955518210155479040"}, + {"0x1.72ebad6ddc73cp+232", 309, "9999999999999999192818822949403492903236716946156035936442979371188224"}, + {"0x1.72ebad6ddc73dp+232", 309, "10000000000000000725314363815292351261583744096465219555182101554790400"}, + {"0x1.cfa698c95390bp+235", 309, "99999999999999991928188229494034929032367169461560359364429793711882240"}, + {"0x1.cfa698c95390cp+235", 309, "100000000000000004188152556421145795899143386664033828314342771180699648"}, + {"0x1.21c81f7dd43a7p+239", 309, "999999999999999943801810948794571024057224129020550531544123892056457216"}, + {"0x1.21c81f7dd43a8p+239", 309, "1000000000000000139961240179628344893925643604260126034742731531557535744"}, + {"0x1.6a3a275d49491p+242", 309, "9999999999999999830336967949613257980309080240684656321838454199566729216"}, + {"0x1.6a3a275d49492p+242", 309, "10000000000000001399612401796283448939256436042601260347427315315575357440"}, + {"0x1.c4c8b1349b9b5p+245", 309, "99999999999999995164818811802792197885196090803013355167206819763650035712"}, + {"0x1.c4c8b1349b9b6p+245", 309, "100000000000000007719022282576153725556774937218346187371917708691719061504"}, + {"0x1.1afd6ec0e1411p+249", 309, "999999999999999926539781176481198923508803215199467887262646419780362305536"}, + {"0x1.1afd6ec0e1412p+249", 309, "1000000000000000127407036708854983366254064757844793202538020642629466718208"}, + {"0x1.61bcca7119915p+252", 309, "9999999999999998863663300700064420349597509066704028242075715752105414230016"}, + {"0x1.61bcca7119916p+252", 309, "10000000000000000470601344959054695891559601407866630764278709534898249531392"}, + {"0x1.ba2bfd0d5ff5bp+255", 309, "99999999999999998278261272554585856747747644714015897553975120217811154108416"}, + {"0x1.ba2bfd0d5ff5cp+255", 309, "100000000000000011133765626626508061083444383443316717731599070480153836519424"}, + {"0x1.145b7e285bf98p+259", 309, "999999999999999802805551768538947706777722104929947493053015898505313987330048"}, + {"0x1.145b7e285bf99p+259", 309, "1000000000000000008493621433689702976148869924598760615894999102702796905906176"}, + {"0x1.59725db272f7fp+262", 309, "9999999999999999673560075006595519222746403606649979913266024618633003221909504"}, + {"0x1.59725db272f80p+262", 309, "10000000000000001319064632327801561377715586164000484896001890252212866570518528"}, + {"0x1.afcef51f0fb5ep+265", 309, "99999999999999986862573406138718939297648940722396769236245052384850852127440896"}, + {"0x1.afcef51f0fb5fp+265", 309, "100000000000000000026609864708367276537402401181200809098131977453489758916313088"}, + {"0x1.0de1593369d1bp+269", 309, "999999999999999921281879895665782741935503249059183851809998224123064148429897728"}, + {"0x1.0de1593369d1cp+269", 309, "1000000000000000131906463232780156137771558616400048489600189025221286657051852800"}, + {"0x1.5159af8044462p+272", 309, "9999999999999999634067965630886574211027143225273567793680363843427086501542887424"}, + {"0x1.5159af8044463p+272", 309, "10000000000000001319064632327801561377715586164000484896001890252212866570518528000"}, + {"0x1.a5b01b605557ap+275", 309, "99999999999999989600692989521205793443517660497828009527517532799127744739526311936"}, + {"0x1.a5b01b605557bp+275", 309, "100000000000000003080666323096525690777025204007643346346089744069413985291331436544"}, + {"0x1.078e111c3556cp+279", 309, "999999999999999842087036560910778345101146430939018748000886482910132485188042620928"}, + {"0x1.078e111c3556dp+279", 309, "1000000000000000057766609898115896702437267127096064137098041863234712334016924614656"}, + {"0x1.4971956342ac7p+282", 309, "9999999999999998420870365609107783451011464309390187480008864829101324851880426209280"}, + {"0x1.4971956342ac8p+282", 309, "10000000000000000146306952306748730309700429878646550592786107871697963642511482159104"}, + {"0x1.9bcdfabc13579p+285", 309, "99999999999999987659576829486359728227492574232414601025643134376206526100066373992448"}, + {"0x1.9bcdfabc1357ap+285", 309, "100000000000000001463069523067487303097004298786465505927861078716979636425114821591040"}, + {"0x1.0160bcb58c16cp+289", 309, "999999999999999959416724456350362731491996089648451439669739009806703922950954425516032"}, + {"0x1.0160bcb58c16dp+289", 309, "1000000000000000180272607553648403929404183682513265918105226119259073688151729587093504"}, + {"0x1.41b8ebe2ef1c7p+292", 309, "9999999999999999594167244563503627314919960896484514396697390098067039229509544255160320"}, + {"0x1.41b8ebe2ef1c8p+292", 309, "10000000000000001361014309341887956898217461639403030224181286973685997351115745547780096"}, + {"0x1.922726dbaae39p+295", 309, "99999999999999999475366575191804932315794610450682175621941694731908308538307845136842752"}, + {"0x1.922726dbaae3ap+295", 309, "100000000000000013610143093418879568982174616394030302241812869736859973511157455477800960"}, + {"0x1.f6b0f092959c7p+298", 309, "999999999999999966484112715463900049825186092620125502979674597309179755437379230686511104"}, + {"0x1.f6b0f092959c8p+298", 309, "1000000000000000079562324861280497143156226140166910515938643997348793075220176113414176768"}, + {"0x1.3a2e965b9d81cp+302", 309, "9999999999999998986371854279739417938265620640920544952042929572854117635677011010499117056"}, + {"0x1.3a2e965b9d81dp+302", 309, "10000000000000000795623248612804971431562261401669105159386439973487930752201761134141767680"}, + {"0x1.88ba3bf284e23p+305", 309, "99999999999999989863718542797394179382656206409205449520429295728541176356770110104991170560"}, + {"0x1.88ba3bf284e24p+305", 309, "100000000000000004337729697461918607329029332495193931179177378933611681288968111094132375552"}, + {"0x1.eae8caef261acp+308", 309, "999999999999999927585207737302990649719308316264031458521789123695552773432097103028194115584"}, + {"0x1.eae8caef261adp+308", 309, "1000000000000000043377296974619186073290293324951939311791773789336116812889681110941323755520"}, + {"0x1.32d17ed577d0bp+312", 309, "9999999999999998349515363474500343108625203093137051759058013911831015418660298966976904036352"}, + {"0x1.32d17ed577d0cp+312", 309, "10000000000000000202188791271559469885760963232143577411377768562080040049981643093586978275328"}, + {"0x1.7f85de8ad5c4ep+315", 309, "99999999999999987200500490339121684640523551209383568895219648418808203449245677922989188841472"}, + {"0x1.7f85de8ad5c4fp+315", 309, "100000000000000002021887912715594698857609632321435774113777685620800400499816430935869782753280"}, + {"0x1.df67562d8b362p+318", 309, "999999999999999931290554592897108903273579836542044509826428632996050822694739791281414264061952"}, + {"0x1.df67562d8b363p+318", 309, "1000000000000000049861653971908893017010268485438462151574892930611988399099305815384459015356416"}, + {"0x1.2ba095dc7701dp+322", 309, "9999999999999998838621148412923952577789043769834774531270429139496757921329133816401963635441664"}, + {"0x1.2ba095dc7701ep+322", 309, "10000000000000000735758738477112498397576062152177456799245857901351759143802190202050679656153088"}, + {"0x1.7688bb5394c25p+325", 309, "99999999999999999769037024514370800696612547992403838920556863966097586548129676477911932478685184"}, + {"0x1.7688bb5394c26p+325", 309, "100000000000000014946137745027879167254908695051145297064360294060937596327914127563101660644376576"}, + {"0x1.d42aea2879f2ep+328", 309, "999999999999999967336168804116691273849533185806555472917961779471295845921727862608739868455469056"}, + {"0x1.d42aea2879f2fp+328", 309, "1000000000000000088752974568224758206315902362276487138068389220230015924160003471290257693781000192"}, + {"0x1.249ad2594c37cp+332", 309, "9999999999999998216360018871870109548898901740426374747374488505608317520357971321909184780648316928"}, + {"0x1.249ad2594c37dp+332", 309, "10000000000000000159028911097599180468360808563945281389781327557747838772170381060813469985856815104"}, + {"0x1.6dc186ef9f45cp+335", 309, "99999999999999997704951326524533662844684271992415000612999597473199345218078991130326129448151154688"}, + {"0x1.6dc186ef9f45dp+335", 309, "100000000000000013246302464330366230200379526580566253752254309890315515232578269041560411089819140096"}, + {"0x1.c931e8ab87173p+338", 309, "999999999999999977049513265245336628446842719924150006129995974731993452180789911303261294481511546880"}, + {"0x1.c931e8ab87174p+338", 309, "1000000000000000101380322367691997167292404756629360031244033674068922812296784134593135547614855430144"}, + {"0x1.1dbf316b346e7p+342", 309, "9999999999999998029863805218200118740630558685368559709703431956602923480183979986974373400948301103104"}, + {"0x1.1dbf316b346e8p+342", 309, "10000000000000000019156750857346687362159551272651920111528035145993793242039887559612361451081803235328"}, + {"0x1.652efdc6018a1p+345", 309, "99999999999999984277223943460294324649363572028252317900683525944810974325551615015019710109750015295488"}, + {"0x1.652efdc6018a2p+345", 309, "100000000000000000191567508573466873621595512726519201115280351459937932420398875596123614510818032353280"}, + {"0x1.be7abd3781ecap+348", 309, "999999999999999938258300825281978540327027364472124478294416212538871491824599713636820527503908255301632"}, + {"0x1.be7abd3781ecbp+348", 309, "1000000000000000065573049346187358932104882890058259544011190816659887156583377798285651762712452391763968"}, + {"0x1.170cb642b133ep+352", 309, "9999999999999998873324014169198263836158851542376704520077063708904652259210884797772880334204906007166976"}, + {"0x1.170cb642b133fp+352", 309, "10000000000000000910359990503684350104604539951754865571545457374840902895351334152154180097541612190564352"}, + {"0x1.5ccfe3d35d80ep+355", 309, "99999999999999996881384047029926983435371269061279689406644211752791525136670645395254002395395884805259264"}, + {"0x1.5ccfe3d35d80fp+355", 309, "100000000000000013177671857705815673582936776336304977818391361080281530225794240230304400502089534272438272"}, + {"0x1.b403dcc834e11p+358", 309, "999999999999999903628689227595715073763450661512695740419453520217955231010212074612338431527184250183876608"}, + {"0x1.b403dcc834e12p+358", 309, "1000000000000000033998991713002824594943974719712898047713430714837875271723200833292741616380733445921308672"}, + {"0x1.108269fd210cbp+362", 309, "9999999999999999818508707188399807864717650964328171247958398369899072554380053298205803424393137676263358464"}, + {"0x1.108269fd210ccp+362", 309, "10000000000000001904433546954913560203606035895531408164662033483817793205787873437092254382049924808062271488"}, + {"0x1.54a3047c694fdp+365", 309, "99999999999999985669538033284915564613846200056062290979362173015478401635353612148739328497990653971840106496"}, + {"0x1.54a3047c694fep+365", 309, "100000000000000002356936751417025583324953279505688186312991253926828166846616173259830936159244951026231410688"}, + {"0x1.a9cbc59b83a3dp+368", 309, "999999999999999956819772641641815758405104477258378281795396215622882607621111488153942930947432322044748890112"}, + {"0x1.a9cbc59b83a3ep+368", 309, "1000000000000000090318962386698695908093961112855385444464428862913680729311211977042675792237466698479879323648"}, + {"0x1.0a1f5b8132466p+372", 309, "9999999999999999301199346926304397284673331501389768492615896861647229832830913903761963586894254467577228034048"}, + {"0x1.0a1f5b8132467p+372", 309, "10000000000000001437186382847214479679695037670941883095320419218299999779872521725981689367534804490539314970624"}, + {"0x1.4ca732617ed7fp+375", 309, "99999999999999984468045325579403643266646490335689226515340879189861218540142707748740732746380344583923932594176"}, + {"0x1.4ca732617ed80p+375", 309, "100000000000000001555941612946684302426820139692106143336977058043083378116475570326498538991504744767620628086784"}, + {"0x1.9fd0fef9de8dfp+378", 309, "999999999999999878856245830528597750986812202069726098796681149605056504554092802642922939954052246206632716926976"}, + {"0x1.9fd0fef9de8e0p+378", 309, "1000000000000000015559416129466843024268201396921061433369770580430833781164755703264985389915047447676206280867840"}, + {"0x1.03e29f5c2b18bp+382", 309, "9999999999999997968343436511656505870179786851589248980528274911095901385876950622696854699774551253248885785624576"}, + {"0x1.03e29f5c2b18cp+382", 309, "10000000000000000155594161294668430242682013969210614333697705804308337811647557032649853899150474476762062808678400"}, + {"0x1.44db473335deep+385", 309, "99999999999999984057935814682588907446802322751135220511621610897383886710310719046874545396497358979515211902353408"}, + {"0x1.44db473335defp+385", 309, "100000000000000001555941612946684302426820139692106143336977058043083378116475570326498538991504744767620628086784000"}, + {"0x1.961219000356ap+388", 309, "999999999999999910571381339882270654388094495275235896417637897556636832727766595587241428345003132947573783761256448"}, + {"0x1.961219000356bp+388", 309, "1000000000000000050555427725995033814228237030803003279020481474722232763977085405824233377105062219252417113236701184"}, + {"0x1.fb969f40042c5p+391", 309, "9999999999999999665649998943273759183241515094863428494587753284228752052274941196820382078490267674695111155514343424"}, + {"0x1.fb969f40042c6p+391", 309, "10000000000000000785522370032175864461962655379085567555410501901553519502269491678716317668570740365133857791317901312"}, + {"0x1.3d3e2388029bbp+395", 309, "99999999999999994416755247254933381274972870380190006824232035607637985622760311004411949604741731366073618283536318464"}, + {"0x1.3d3e2388029bcp+395", 309, "100000000000000012334713184677367065734511114927744231797396013484834264822673118714746919046029294413093564456393244672"}, + {"0x1.8c8dac6a0342ap+398", 309, "999999999999999980003468347394201181668805192897008518188648311830772414627428725464789434929992439754776075181077037056"}, + {"0x1.8c8dac6a0342bp+398", 309, "1000000000000000123347131846773670657345111149277442317973960134848342648226731187147469190460292944130935644563932446720"}, + {"0x1.efb1178484134p+401", 309, "9999999999999999226660029476424133913982828103448349982745235826237443211877077407917175327178722380043122474279348731904"}, + {"0x1.efb1178484135p+401", 309, "10000000000000000373409337471459889719393275754491820381027730410378005080671497101378613371421126415052399029342192009216"}, + {"0x1.35ceaeb2d28c0p+405", 309, "99999999999999983092605830803955292696544699826135736641192401589249937168415416531480248917847991520357012302290741100544"}, + {"0x1.35ceaeb2d28c1p+405", 309, "100000000000000001440594758724527385583111862242831263013712314935498927069126131626863257625726456080505437183296233537536"}, + {"0x1.83425a5f872f1p+408", 309, "999999999999999977709969731404129670057984297594921577392083322662491290889839886077866558841507631684757522070951350501376"}, + {"0x1.83425a5f872f2p+408", 309, "1000000000000000124493881154768706413150521596928485788372242629432483210095525606840930628504535348165944921118995289997312"}, + {"0x1.e412f0f768fadp+411", 309, "9999999999999999483531874467312143214394768377282087351960514613084929070487027419252537449089020883885200422613425626021888"}, + {"0x1.e412f0f768faep+411", 309, "10000000000000000657803165854228757159135066771950601039801789067244864424132513185357050006393242615734699614997777141989376"}, + {"0x1.2e8bd69aa19ccp+415", 309, "99999999999999992486776161899288204254467086983483846143922597222529419997579302660316349376281765375153005841365553228283904"}, + {"0x1.2e8bd69aa19cdp+415", 309, "100000000000000011275116824089954027370311861298180065149382988489088385655907074917988550293149313084744992919515177483763712"}, + {"0x1.7a2ecc414a03fp+418", 309, "999999999999999924867761618992882042544670869834838461439225972225294199975793026603163493762817653751530058413655532282839040"}, + {"0x1.7a2ecc414a040p+418", 309, "1000000000000000075174486916518208627471429064352408213482909102357765925242415204664541101097758035428265955038852526326677504"}, + {"0x1.d8ba7f519c84fp+421", 309, "9999999999999999549291066784979473595300225087383524118479625982517885450291174622154390152298057300868772377386949310916067328"}, + {"0x1.d8ba7f519c850p+421", 309, "10000000000000000751744869165182086274714290643524082134829091023577659252424152046645411010977580354282659550388525263266775040"}, + {"0x1.27748f9301d31p+425", 309, "99999999999999988278187853568579059876517857536991893086699469578820211690113881674597776370903434688204400735860037395056427008"}, + {"0x1.27748f9301d32p+425", 309, "100000000000000007517448691651820862747142906435240821348290910235776592524241520466454110109775803542826595503885252632667750400"}, + {"0x1.7151b377c247ep+428", 309, "999999999999999998217443564185241415988928868759412500436543339729940401905904649497115766142268560009777175966751665376232210432"}, + {"0x1.7151b377c247fp+428", 309, "1000000000000000152131530268851175838953929259945403926529274864985591448578925759831966436053247510846754734110953387277122797568"}, + {"0x1.cda62055b2d9dp+431", 309, "9999999999999999366518088823188676468029287122850159299994507296276799832366962053631754981778769796749861527090709766158759755776"}, + {"0x1.cda62055b2d9ep+431", 309, "10000000000000000597830782460516151851749290252338090708736359498322008205751130936310560341066601403445681992244323541365884452864"}, + {"0x1.2087d4358fc82p+435", 309, "99999999999999991202555500957231813912852864969525730182461368558677581576901282770959939099212034754106974340599870111173348163584"}, + {"0x1.2087d4358fc83p+435", 309, "100000000000000010903558599154471420052372915041332632722331003791400915551047984893820824847817340461240101783057690514487343316992"}, + {"0x1.68a9c942f3ba3p+438", 309, "999999999999999990829567402361276563686608849982484911984092226517669151665599636201042933986541570369602253175829982724989462249472"}, + {"0x1.68a9c942f3ba4p+438", 309, "1000000000000000148437592187939193412802769250556940132303049308379455823458773253183930019975384016026667272715492545951501423476736"}, + {"0x1.c2d43b93b0a8bp+441", 309, "9999999999999998962647525310145264542169126096378117797927179774005971485896954660113106823932361029753632414520324447890822855131136"}, + {"0x1.c2d43b93b0a8cp+441", 309, "10000000000000000223511723594768599335098409300973759560478836428900264860242343595976203511843100595010152570837624953702918544949248"}, + {"0x1.19c4a53c4e697p+445", 309, "99999999999999992148203649670699315007549827372972461504375111049848301607660324472857261615145089428049364457837845490532419930947584"}, + {"0x1.19c4a53c4e698p+445", 309, "100000000000000012322030822224672671694418358646502729705201617528156995597186547446666808621716922472153686958914653583525950968037376"}, + {"0x1.6035ce8b6203dp+448", 309, "999999999999999961829690841814939863449235336276785151445404123455100404055655690676191710164594560368702289580532071091311261383655424"}, + {"0x1.6035ce8b6203ep+448", 309, "1000000000000000123220308222246726716944183586465027297052016175281569955971865474466668086217169224721536869589146535835259509680373760"}, + {"0x1.b843422e3a84cp+451", 309, "9999999999999999295515673657285824927502456862391367223240817130898064936724137339180964349540796274981353735788091781425216117243117568"}, + {"0x1.b843422e3a84dp+451", 309, "10000000000000000586640612700740119755462042863897304388093713545509821352053815609504775357961393589804030375857007499376802103616864256"}, + {"0x1.132a095ce492fp+455", 309, "99999999999999982626157224225223890651347880611866174913584999992086598044603947229219155428043184231232124237329592070639473281441202176"}, + {"0x1.132a095ce4930p+455", 309, "100000000000000003284156248920492607898701256635961169551231342625874700689878799554400131562772741268394950478432243557864849063421149184"}, + {"0x1.57f48bb41db7bp+458", 309, "999999999999999867577570291642776341008185558166851738411142685188442185736589176942553506549890956386646894855501223680845484378371915776"}, + {"0x1.57f48bb41db7cp+458", 309, "1000000000000000032841562489204926078987012566359611695512313426258747006898787995544001315627727412683949504784322435578648490634211491840"}, + {"0x1.adf1aea12525ap+461", 309, "9999999999999999006303687311552062886039509598054037298313768334025031499690289406628430683654582476461074168412654660604060856295398309888"}, + {"0x1.adf1aea12525bp+461", 309, "10000000000000000328415624892049260789870125663596116955123134262587470068987879955440013156277274126839495047843224355786484906342114918400"}, + {"0x1.0cb70d24b7378p+465", 309, "99999999999999984774589122793531837245072631718372054355900219626000560719712531871037976946055058163097058166404267825310912362767116664832"}, + {"0x1.0cb70d24b7379p+465", 309, "100000000000000005928380124081487003706362488767045328864850074482999577828473980652023296508018124569151792237293382948229697163514582401024"}, + {"0x1.4fe4d06de5056p+468", 309, "999999999999999847745891227935318372450726317183720543559002196260005607197125318710379769460550581630970581664042678253109123627671166648320"}, + {"0x1.4fe4d06de5057p+468", 309, "1000000000000000016976219238238959704141045173573106739630601035115997744067216908958262325956255112879408454231155599236459402033650892537856"}, + {"0x1.a3de04895e46cp+471", 309, "9999999999999999154380224320567749051268538597394750219876417318024024619451619548095327920588323941303457306908878466464492349900630570041344"}, + {"0x1.a3de04895e46dp+471", 309, "10000000000000000508222848402996879704791089448509839788449208028871961714412352270078388372553960191290960287445781834331294577148468377157632"}, + {"0x1.066ac2d5daec3p+475", 309, "99999999999999980713061250546244445284504979165026785650181847493456749434830333705088795590158149413134549224793557721710505681023603243483136"}, + {"0x1.066ac2d5daec4p+475", 309, "100000000000000002374543235865110535740865792782868218747346498867023742954202057256817762821608329412934596913384011607579341316989008157343744"}, + {"0x1.4805738b51a74p+478", 309, "999999999999999850453576476100176633757771418885950722696147777681701481387046784154345890364481854130945587625116484988842728082166842262552576"}, + {"0x1.4805738b51a75p+478", 309, "1000000000000000023745432358651105357408657927828682187473464988670237429542020572568177628216083294129345969133840116075793413169890081573437440"}, + {"0x1.9a06d06e26112p+481", 309, "9999999999999999890870611821409196126784806260401358945180015464725302399110258148854112806457630061296658928320953898584032761523454337112604672"}, + {"0x1.9a06d06e26113p+481", 309, "10000000000000001277205458881816625915991898331943210663398553152633589984350048456164766709270441581283861980390742947279638242225240251599683584"}, + {"0x1.00444244d7cabp+485", 309, "99999999999999993363366729972462242111019694317846182578926003895619873650143420259298512453325054533017777074930382791057905692427399713177731072"}, + {"0x1.00444244d7cacp+485", 309, "100000000000000015544724282938981118738333167462515810070422606902152475013980065176268974898330038852813025908047007570187593383655974344970993664"}, + {"0x1.405552d60dbd6p+488", 309, "999999999999999977996382405657660174364823889467801080772253244969263939229107492426926049423260513969768268415537077468838432306731146395363835904"}, + {"0x1.405552d60dbd7p+488", 309, "1000000000000000155447242829389811187383331674625158100704226069021524750139800651762689748983300388528130259080470075701875933836559743449709936640"}, + {"0x1.906aa78b912cbp+491", 309, "9999999999999999070160382361647997691574207754048582727994641153483596148648302286926205695992445641464234721495638781756234316947997075736253956096"}, + {"0x1.906aa78b912ccp+491", 309, "10000000000000000489767265751505205795722270035307438887450423745901682635933847561612315292472764637931130646815102767620534329186625852171022761984"}, + {"0x1.f485516e7577ep+494", 309, "99999999999999993540817590396194393124038202103003539598857976719672134461054113418634276152885094407576139065595315789290943193957228310232077172736"}, + {"0x1.f485516e7577fp+494", 309, "100000000000000004897672657515052057957222700353074388874504237459016826359338475616123152924727646379311306468151027676205343291866258521710227619840"}, + {"0x1.38d352e5096afp+498", 309, "999999999999999980835596172437374590573120014030318793091164810154100112203678582976298268616221151962702060266176005440567032331208403948233373515776"}, + {"0x1.38d352e5096b0p+498", 309, "1000000000000000162545277246339097227904071986031452381501504981983615182576228378136120296965701983510464738707067395631197433897752887331883780669440"}, + {"0x1.8708279e4bc5ap+501", 309, "9999999999999998718097875280963410081745488308296386400449607070563910699801487058804050516065326530340444532016411713261887913912817139180431292235776"}, + {"0x1.8708279e4bc5bp+501", 309, "10000000000000000171775323872177191180393104084305455107732328445200031262781885420082626742861173182722545959543542834786931126445173006249634549465088"}, + {"0x1.e8ca3185deb71p+504", 309, "99999999999999992995688547174489225212045346187000138833626956204183589249936464033154810067836651912932851030272641618719051989257594860081125951275008"}, + {"0x1.e8ca3185deb72p+504", 309, "100000000000000004625108135904199474001226272395072688491888727201272553753779650923383419882203425131989662450489690590919397689516441796634752009109504"}, + {"0x1.317e5ef3ab327p+508", 309, "999999999999999999733403004123153744855539019118436686285840188024369679522423761672919759564567158443669378824028710020392594094129030220133015859757056"}, + {"0x1.317e5ef3ab328p+508", 309, "1000000000000000185804116423798517725482433838447597480818028523977793111583914751916577516594435529948578361547501493575598125298270581204991032785108992"}, + {"0x1.7dddf6b095ff0p+511", 309, "9999999999999998880909749523179353564794021275209402095665271864523156202855291675267251053466461355407239891899450398872692753716440996292182057045458944"}, + {"0x1.7dddf6b095ff1p+511", 309, "10000000000000000369475456880582265409809179829842688451922778552150543659347219597216513109705408327446511753687232667314337003349573404171046192448274432"}, + {"0x1.dd55745cbb7ecp+514", 309, "99999999999999988809097495231793535647940212752094020956652718645231562028552916752672510534664613554072398918994503988726927537164409962921820570454589440"}, + {"0x1.dd55745cbb7edp+514", 309, "100000000000000000717623154091016830408061481189160311806712772146250661680488340128266606984576189330386573813296762136260081534229469225952733653677113344"}, + {"0x1.2a5568b9f52f4p+518", 309, "999999999999999983359180223191721714560372275017470536367007614460468417501012554531477876945938741751237388344363105067534507348164573733465510370326085632"}, + {"0x1.2a5568b9f52f5p+518", 309, "1000000000000000173895590764939294430722312570010531189967968470476774011931979328540983420144523954172264186653199235428064971301205521941960119701886468096"}, + {"0x1.74eac2e8727b1p+521", 309, "9999999999999999833591802231917217145603722750174705363670076144604684175010125545314778769459387417512373883443631050675345073481645737334655103703260856320"}, + {"0x1.74eac2e8727b2p+521", 309, "10000000000000001357883086565897798874899245110119190592477762992735128930457859737390823115048069116880588269914320093559588785105973323002611978355743916032"}, + {"0x1.d22573a28f19dp+524", 309, "99999999999999995287335453651211007997446182781858083179085387749785952239205787068995699003416510776387310061494932420984963311567802202010637287727642443776"}, + {"0x1.d22573a28f19ep+524", 309, "100000000000000007481665728323055661831810361661413965009546882534829510282787660605604053768125964371333025153260444764058913004562422887354292284947506921472"}, + {"0x1.2357684599702p+528", 309, "999999999999999928484693987168420772305733470059469068129930887927772406304894123616740280504746200573981670431418299523701733729688780649419062882836695482368"}, + {"0x1.2357684599703p+528", 309, "1000000000000000123593978381917935233655560332132363177417314804488469335002204100202473956740097458093113111899666497012884928817602711614917542838354527125504"}, + {"0x1.6c2d4256ffcc2p+531", 309, "9999999999999998504409802292686149877658027252303114244149773213034936348259701329824468100106056975663290938441190205280284556945232082632196709006295628251136"}, + {"0x1.6c2d4256ffcc3p+531", 309, "10000000000000000065284077450682265568456642148886267118448844545520511777838181142510337509988867035816342470187175785193750117648543530356184548650438281396224"}, + {"0x1.c73892ecbfbf3p+534", 309, "99999999999999991287595123558845961539774732109363753938694017460291665200910932548988158640591809997245115511395844372456707812265566617217918448639526895091712"}, + {"0x1.c73892ecbfbf4p+534", 309, "100000000000000003774589324822814887066163651282028976933086588120176268637538771050475113919654290478469527765363729011764432297892058199009821165792668120252416"}, + {"0x1.1c835bd3f7d78p+538", 309, "999999999999999937849939638116397466450525159438967985375725315922685858882365002492855496964043060934899979621894213003182527093908649335762989920701551401238528"}, + {"0x1.1c835bd3f7d79p+538", 309, "1000000000000000137641846858339900274872747866201611553286006446480839513868410418516646781429042748634490575685380367232106118863932514644433433395151811003809792"}, + {"0x1.63a432c8f5cd6p+541", 309, "9999999999999999378499396381163974664505251594389679853757253159226858588823650024928554969640430609348999796218942130031825270939086493357629899207015514012385280"}, + {"0x1.63a432c8f5cd7p+541", 309, "10000000000000000976834654142951997131883033248490828397039502203692087828712013353118885245360428110945724564726831363863214005099277415826993447002617590832955392"}, + {"0x1.bc8d3f7b3340bp+544", 309, "99999999999999987391652932764487656775541389327492204364443535414407668928683046936524228593524316087103098888157864364992697772750101243698844800887746832841572352"}, + {"0x1.bc8d3f7b3340cp+544", 309, "100000000000000000178334994858791836514563642560301392710701527770129502847789953562046870799284296099876897036220978235643807646031628623453753183252563447406133248"}, + {"0x1.15d847ad00087p+548", 309, "999999999999999899489893451833484927233458399740540420336951338855520357125044282616287570346763120896578585177704871391229197474064067196498264773607101557544845312"}, + {"0x1.15d847ad00088p+548", 309, "1000000000000000104076806445342351803057814451465487433877079216547069699830754788624649845638922801100959355546714693321646955446568505272576798891444167390577819648"}, + {"0x1.5b4e5998400a9p+551", 309, "9999999999999999404072760505352583023983296100855298230449769143938302256661863838179600254051950569374547392515068357773127490685649548117139715971745147241514401792"}, + {"0x1.5b4e5998400aap+551", 309, "10000000000000001040768064453423518030578144514654874338770792165470696998307547886246498456389228011009593555467146933216469554465685052725767988914441673905778196480"}, + {"0x1.b221effe500d3p+554", 309, "99999999999999990767336997157383960226643264180953830087855645396318233083327270285662206135844950810475381599246526426844590779296424471954140613832058419086616428544"}, + {"0x1.b221effe500d4p+554", 309, "100000000000000003860899428741951440279402051491350438954423829568577391016492742670197391754543170343555750902863155030391327289536708508823166797373630632400726786048"}, + {"0x1.0f5535fef2084p+558", 309, "999999999999999933860494834742974562371950216430331518611692822307700646699603647625692432595845947170914554599698521475539380813444812793279458505403728617494385000448"}, + {"0x1.0f5535fef2085p+558", 309, "1000000000000000143357493740096054243216090813396677260476783769063847173630251205778255402495017459700200463457564579132287164977289357383183877442068884030520150720512"}, + {"0x1.532a837eae8a5p+561", 309, "9999999999999999338604948347429745623719502164303315186116928223077006466996036476256924325958459471709145545996985214755393808134448127932794585054037286174943850004480"}, + {"0x1.532a837eae8a6p+561", 309, "10000000000000001014580939590254383070472626940034081121037655797126178682441216941477428085151831571943432816859913676009376081445204484652029936547358529479149975764992"}, + {"0x1.a7f5245e5a2cep+564", 309, "99999999999999990034097500988648181343688772091571619991327827082671720239070003832128235741197850516622880918243995225045973534722968565889475147553730375141026248523776"}, + {"0x1.a7f5245e5a2cfp+564", 309, "100000000000000003441905430931245280917713770297417747470693647675065097962631447553892265814744827318497179085147422915077831721209019419643357959500300321574675254607872"}, + {"0x1.08f936baf85c1p+568", 309, "999999999999999953972206729656870211732987713739100709830741553196290713284945813208338477706166412373726001850053663010587168093173889073910282723323583537144858509574144"}, + {"0x1.08f936baf85c2p+568", 309, "1000000000000000168497133608738423804917387685032638749500594682674584756861928912756562958882918041203714772520508506051096899076950702733972407714468702680083242606919680"}, + {"0x1.4b378469b6731p+571", 309, "9999999999999999110672213538405594930961077194803931018967709273006319045695491932986935814708160866077282477159626944024852218964185263418978577250945597085571816901050368"}, + {"0x1.4b378469b6732p+571", 309, "10000000000000000826871628571058023676436276965152235336326534308832671394311356729372731664122173896717192642523265688348930066834399772699475577180106550229078889679814656"}, + {"0x1.9e056584240fdp+574", 309, "99999999999999987674323305318751091818660372407342701554959442658410485759723189737097766448253582599493004440868991951600366493901423615628791772651134064568704023452975104"}, + {"0x1.9e056584240fep+574", 309, "100000000000000001403918625579970521782461970570129136093830042945021304548650108108184133243565686844612285763778101906192989276863139689872767772084421689716760605683089408"}, + {"0x1.02c35f729689ep+578", 309, "999999999999999849284042412665072058259000527747854146471853226010883220019378060628804930891911617504691481762871699606818419373090804007799965727644765395390927070069522432"}, + {"0x1.02c35f729689fp+578", 309, "1000000000000000068957567536844582937679826098352437099093782830596656320642208754566186799616905285426599982929417458880300383900478261195703581718577367397759832385751351296"}, + {"0x1.4374374f3c2c6p+581", 309, "9999999999999999371534524623368764100273307559896873275206250678451924602685103382037576783819090846734548822294900033162112051840457868829614121240178061963384891963422539776"}, + {"0x1.4374374f3c2c7p+581", 309, "10000000000000001128922725616804851135639912124733536896181687515138109407667748933536631733619040190109816831627266107349967768059557526332843049167638877982336134488877170688"}, + {"0x1.945145230b377p+584", 309, "99999999999999986685792442259943292861266657339622078268160759437774506806920451614379548038991111093844416185619536034869697653528180058283225500691937355558043949532406874112"}, + {"0x1.945145230b378p+584", 309, "100000000000000000744898050207431989144199493858315387235964254131263985246781616026371987637390705840846560260278464628372543383280977318309056924111623883709653889736043921408"}, + {"0x1.f965966bce055p+587", 309, "999999999999999894976135638494410321178532246433607400617214583764724024948926844967780359586710300432448450005513217535702667994787395102883917853758746611883659375731342835712"}, + {"0x1.f965966bce056p+587", 309, "1000000000000000007448980502074319891441994938583153872359642541312639852467816160263719876373907058408465602602784646283725433832809773183090569241116238837096538897360439214080"}, + {"0x1.3bdf7e0360c35p+591", 309, "9999999999999998724815666657784284071258397080036981062687289922551408594451489819085924562292709488372450194860589317860981148271829194868425875762872481668410834714055235600384"}, + {"0x1.3bdf7e0360c36p+591", 309, "10000000000000000524381184475062837195473800154429724610566137243318061834753718863820956830887857615988724636416932177829345401680187244151732297960592357271816907060120777654272"}, + {"0x1.8ad75d8438f43p+594", 309, "99999999999999998045549773481514159457876389246726271914145983150114005386328272459269439234497983649422148597943950338419997003168440244384097290815044070304544781216945608327168"}, + {"0x1.8ad75d8438f44p+594", 309, "100000000000000012442073916019742584451599613841868220297176761716247231308746104817149697383259168670352344130394693218166911030435304638650548668396803075131793359985469944758272"}, + {"0x1.ed8d34e547313p+597", 309, "999999999999999894076352879585771044616424544896411028843275160104340698328775730445412843452412726368640312784735046105718485868083216078242264642659886674081956339558310064685056"}, + {"0x1.ed8d34e547314p+597", 309, "1000000000000000009248546019891598444566210341657546615907521388633406505708118389308454908642502206536081877044340989143693798086218131232373875663313958712699944969706504756133888"}, + {"0x1.3478410f4c7ecp+601", 309, "9999999999999999171107915076469365246063817042486381462561244058101538598046442622180212564904306224021286256366562347133135483117101991090685868467907010818055540655879490029748224"}, + {"0x1.3478410f4c7edp+601", 309, "10000000000000001013863005321362603645260389790664550855589183714566591516115925163988885607945737906700351284520257435740740478607260633556791644798372163435943358738250605092929536"}, + {"0x1.819651531f9e7p+604", 309, "99999999999999991711079150764693652460638170424863814625612440581015385980464426221802125649043062240212862563665623471331354831171019910906858684679070108180555406558794900297482240"}, + {"0x1.819651531f9e8p+604", 309, "100000000000000006453119872723839559654210752410289169769835957832735809325020286556271509993374515701645382788895184180192194795092289050635704895322791329123657951217763820802932736"}, + {"0x1.e1fbe5a7e7861p+607", 309, "999999999999999946594872951565228338993526868219488856544571440313594706493755982886960025179093529324993666087115356131035228239552737388526279268078143523691759154905886843985723392"}, + {"0x1.e1fbe5a7e7862p+607", 309, "1000000000000000064531198727238395596542107524102891697698359578327358093250202865562715099933745157016453827888951841801921947950922890506357048953227913291236579512177638208029327360"}, + {"0x1.2d3d6f88f0b3cp+611", 309, "9999999999999998286585471758920610814449462123360860153907833022998313197373091002112049504244419016335335042852788704601485085281825842706955095829283737561469387976341354799421194240"}, + {"0x1.2d3d6f88f0b3dp+611", 309, "10000000000000000173566684169691286935226752617495305612368443231218527385476241124924130700318845059398697631682172475335672600663748292592247410791680053842186513692689376624118857728"}, + {"0x1.788ccb6b2ce0cp+614", 309, "99999999999999997961704416875371517110712945186684165206763211895744845478556111003617144611039598507860251139162957211888350975873638026151889477992007905860430885494197722591793250304"}, + {"0x1.788ccb6b2ce0dp+614", 309, "100000000000000013057554116161536926076931269139759728874448093561506558983381311986113794179635006852367151849798027377761851098929017625234227997691178436106167891224981897189374558208"}, + {"0x1.d6affe45f818fp+617", 309, "999999999999999979617044168753715171107129451866841652067632118957448454785561110036171446110395985078602511391629572118883509758736380261518894779920079058604308854941977225917932503040"}, + {"0x1.d6affe45f8190p+617", 309, "1000000000000000100383841763043038442836876043491446161409111172283542162824162717896144642659159251834657717076710133445871510743179417054177602937513443300570204900788250622698582966272"}, + {"0x1.262dfeebbb0f9p+621", 309, "9999999999999999071569656121801212080692814968920789464627446869617922299624001453201875281811380250249693879805812353226907091680705581859236698853640605134247712274342131878495422251008"}, + {"0x1.262dfeebbb0fap+621", 309, "10000000000000001003838417630430384428368760434914461614091111722835421628241627178961446426591592518346577170767101334458715107431794170541776029375134433005702049007882506226985829662720"}, + {"0x1.6fb97ea6a9d37p+624", 309, "99999999999999986851159038200753776111576258757220550347347138989744224339004763080499610528553377966303172216135545569805454885304878641227288327493418395599568449276340570087973407686656"}, + {"0x1.6fb97ea6a9d38p+624", 309, "100000000000000002309309130269787154892983822485169927543056457815484218967945768886576179686795076111078238543825857419659919011313587350687602971665369018571203143144663564875896666980352"}, + {"0x1.cba7de5054485p+627", 309, "999999999999999899427890566145604518678577715028104257864890027548922232647929642417149243602017175952581854816736079397763477105066203831193512563278085201938953880500051690455580595453952"}, + {"0x1.cba7de5054486p+627", 309, "1000000000000000023093091302697871548929838224851699275430564578154842189679457688865761796867950761110782385438258574196599190113135873506876029716653690185712031431446635648758966669803520"}, + {"0x1.1f48eaf234ad3p+631", 309, "9999999999999998746948504188351511126283256130633852543517551174277382412416240331274267329488304589209417486924315804379963345034522698960570091326029642051843383703107348987949033805840384"}, + {"0x1.1f48eaf234ad4p+631", 309, "10000000000000000725591715973187783610303424287811372824568343983972101724920689074452068181743241951740625976868675721161334753163637413771490365780039321792212624518252692320803210995433472"}, + {"0x1.671b25aec1d88p+634", 309, "99999999999999991426771465453187656230872897620693565997277097362163262749171300799098274999392920617156591849131877877362376266603456419227541462168315779999172318661364176545198692437590016"}, + {"0x1.671b25aec1d89p+634", 309, "100000000000000007255917159731877836103034242878113728245683439839721017249206890744520681817432419517406259768686757211613347531636374137714903657800393217922126245182526923208032109954334720"}, + {"0x1.c0e1ef1a724eap+637", 309, "999999999999999914267714654531876562308728976206935659972770973621632627491713007990982749993929206171565918491318778773623762666034564192275414621683157799991723186613641765451986924375900160"}, + {"0x1.c0e1ef1a724ebp+637", 309, "1000000000000000040900880208761398001286019738266296957960021713442094663491997727554362004538245197373563261847757813447631532786297905940174312186739777303375354598782943738754654264509857792"}, + {"0x1.188d357087712p+641", 309, "9999999999999998636144484328400679867178126713831911407778706776934478130915991201656310481762028096907669811487431649040206546179292274931158555956605099986382706217459209761309199883223171072"}, + {"0x1.188d357087713p+641", 309, "10000000000000000662275133196073022890814778906781692175574718614061870706920546714670378554471083956139627305190456203824330868103505742897540916997511012040520808812168041334151877325366493184"}, + {"0x1.5eb082cca94d7p+644", 309, "99999999999999994465967438754696170766327875910118237148971115117854351613178134068619377108456504406004528089686414709538562749489776621177115003729674648080379472553427423904462708600804999168"}, + {"0x1.5eb082cca94d8p+644", 309, "100000000000000010675012629696074914955421093453716483291339209814873492221214578172731921690128951279860188039310611147811557324883484364908173892056921944513484293311098076487204128137951576064"}, + {"0x1.b65ca37fd3a0dp+647", 309, "999999999999999977077764769429719196041465194188378863774447340572581797347854228894418860247909937807756600796112539971931616645685181699233267813951241073670004367049615544210109925082343145472"}, + {"0x1.b65ca37fd3a0ep+647", 309, "1000000000000000106750126296960749149554210934537164832913392098148734922212145781727319216901289512798601880393106111478115573248834843649081738920569219445134842933110980764872041281379515760640"}, + {"0x1.11f9e62fe4448p+651", 309, "9999999999999999511432924639235132053389160461186216699466583890573511723749959183278387889172340228095875448767138256706948253250552493092635735926276453993770366538373425000777236538229086224384"}, + {"0x1.11f9e62fe4449p+651", 309, "10000000000000001586190709079731611309593092306766792205689700011791961721578624028604793595626413427949399922319035400805891558900947084290211273632164107937207783595355268531368138238983848067072"}, + {"0x1.56785fbbdd55ap+654", 309, "99999999999999995114329246392351320533891604611862166994665838905735117237499591832783878891723402280958754487671382567069482532505524930926357359262764539937703665383734250007772365382290862243840"}, + {"0x1.56785fbbdd55bp+654", 309, "100000000000000011712391521916323154583523059376506771044450767875482717220128910595395124543355987879786950276086559719861028977708681660506961660909865771485203001839588998252499578988328956985344"}, + {"0x1.ac1677aad4ab0p+657", 309, "999999999999999884751043361827625869140390227060043253747518673178360772444478643277393806310703680414274761723053117059528639544242622390941156386039240473187039308013923507098814799398756243472384"}, + {"0x1.ac1677aad4ab1p+657", 309, "1000000000000000017535541566019400541537441865177200086145798104936341572305513193378283771523764365204900328030374534281861011105867876227585990799216050325567033999660761493056632508247061001404416"}, + {"0x1.0b8e0acac4eaep+661", 309, "9999999999999998847510433618276258691403902270600432537475186731783607724444786432773938063107036804142747617230531170595286395442426223909411563860392404731870393080139235070988147993987562434723840"}, + {"0x1.0b8e0acac4eafp+661", 309, "10000000000000000972062404885344653449756728480474941855847657639911300522221339234388177506516007760792756678147673846152604340428430285295728914471221362369950308146488642846313231335560438561636352"}, + {"0x1.4e718d7d7625ap+664", 309, "99999999999999996973312221251036165947450327545502362648241750950346848435554075534196338404706251868027512415973882408182135734368278484639385041047239877871023591066789981811181813306167128854888448"}, + {"0x1.4e718d7d7625bp+664", 309, "100000000000000013969727991387583324014272937224498437195221518215368390817766497947110253951978019521227584903311023812640679294256310975729923845933871538975662911597585244013782480038750137870188544"}, + {"0x1.a20df0dcd3af0p+667", 309, "999999999999999901747459131964173027207212836739039328294498440443382314826691065690307721857975448067474834210390258463987183104130654882031695190925872134291678628544718769301415466131339252487684096"}, + {"0x1.a20df0dcd3af1p+667", 309, "1000000000000000037718785293056550291741793714171007924670336578563554653884390444993619046236149589293075414109087389699655531583234914810756005630018925423128793192791080866922220799992003324610084864"}, + {"0x1.0548b68a044d6p+671", 309, "9999999999999999017474591319641730272072128367390393282944984404433823148266910656903077218579754480674748342103902584639871831041306548820316951909258721342916786285447187693014154661313392524876840960"}, + {"0x1.0548b68a044d7p+671", 309, "10000000000000001193015809897119766504625422406301890824958394614356580573190100725756058408630540740284357620483056684410565406706974707679905918934747573964310619313388981254947040003084017678835253248"}, + {"0x1.469ae42c8560cp+674", 309, "99999999999999998876910787506329447650934459829549922997503484884029261182361866844442696946000689845185920534555642245481492613075738123641525387194542623914743194966239051177873087980216425864602058752"}, + {"0x1.469ae42c8560dp+674", 309, "100000000000000016281240536126153737511360812140841903333610766563411320581747387395266546466406979922062794761588875043647041218401083394518237123398453444885893859189773399673336170714381427096269357056"}, + {"0x1.98419d37a6b8fp+677", 309, "999999999999999988769107875063294476509344598295499229975034848840292611823618668444426969460006898451859205345556422454814926130757381236415253871945426239147431949662390511778730879802164258646020587520"}, + {"0x1.98419d37a6b90p+677", 309, "1000000000000000128003745864021888795392755416785835072663893102275349087018702832851017765623257219066874199161822284840139314973360143403428947761576712806916637263450665299742435541675484268499358973952"}, + {"0x1.fe52048590672p+680", 309, "9999999999999999052283250816881378851792981072012977243617198967792587267065681698004724917620567060828502090557969050236202928251957239362070375381666542984859087613894256390005080826781722527340175556608"}, + {"0x1.fe52048590673p+680", 309, "10000000000000000166160354728550133402860267619935663985128064995273039068626355013257451286926569625748622041088095949318798038992779336698179926498716835527012730124200454693714718121768282606166882648064"}, + {"0x1.3ef342d37a407p+684", 309, "99999999999999986067324092522138770313660664528439025470128525568004065464414123719036343698981660348604541103459182906031648839556284004276265549348464259679976306097717770685212259087870984958094927200256"}, + {"0x1.3ef342d37a408p+684", 309, "100000000000000003889357755108838843130737249295202013334302382007691294289384896763079965607877701387326460311941213291353170611409437561654018367221268940354434586262616943544566455807655946219322240663552"}, + {"0x1.8eb0138858d09p+687", 309, "999999999999999896317308250394787848770759814817916230429632968559415112294082783278450680807608685563489249451555889830959531939269147157518161129230251958148679621306976052570830984318279772103403898929152"}, + {"0x1.8eb0138858d0ap+687", 309, "1000000000000000038893577551088388431307372492952020133343023820076912942893848967630799656078777013873264603119412132913531706114094375616540183672212689403544345862626169435445664558076559462193222406635520"}, + {"0x1.f25c186a6f04cp+690", 309, "9999999999999999818630698308109481982927274216983785721776674794699138106539424938898600659703096825493544616522696356805028364441642842329313746550197144253860793660984920822957311285732475861572950035529728"}, + {"0x1.f25c186a6f04dp+690", 309, "10000000000000000959240852713658286643220175642056616945083801606839120751337554413717392461872443451971747445865546301465605757840244670001489926894056643817026123591538467885955979875798713382291498097180672"}, + {"0x1.37798f428562fp+694", 309, "99999999999999989061425747836704382546929530769255207431309733449871519907009213590435672179676195243109823530484164010765664497227613801915728022751095446033285297165420831725583764136794858449981115862089728"}, + {"0x1.37798f4285630p+694", 309, "100000000000000007311188218325485257111615953570420507004223762444111242223779285187536341014385741266761068799969763125334902791605243044670546908252847439043930576054277584733562461577854658781477884848504832"}, + {"0x1.8557f31326bbbp+697", 309, "999999999999999927113782419344605574598668153294882673458925392487194643703632279098558059466181044478400725843812838336795121561031396504666917998514458446354143529431921823271795036250068185162804696593727488"}, + {"0x1.8557f31326bbcp+697", 309, "1000000000000000073111882183254852571116159535704205070042237624441112422237792851875363410143857412667610687999697631253349027916052430446705469082528474390439305760542775847335624615778546587814778848485048320"}, + {"0x1.e6adefd7f06aap+700", 309, "9999999999999999563134023721266549739021664297767471527755878388779781994104643936539191296017163181162427182749897969201059028320356032930746282153172616351711759756540926280845609521557638656931995269719916544"}, + {"0x1.e6adefd7f06abp+700", 309, "10000000000000000731118821832548525711161595357042050700422376244411124222377928518753634101438574126676106879996976312533490279160524304467054690825284743904393057605427758473356246157785465878147788484850483200"}, + {"0x1.302cb5e6f642ap+704", 309, "99999999999999990959401044767537593501656918740576398586892792465272451027953301036534141738485988029569553038510666318680865279842887243162229186843277653306392406169861934038413548670665077684456779836676898816"}, + {"0x1.302cb5e6f642bp+704", 309, "100000000000000009647157814548049209055895815688969665349556758155373926680325854351965226625228563157788428194463919811999765293285579587743163725597071694149293171752051249118583734850310313223909471278765965312"}, + {"0x1.7c37e360b3d35p+707", 309, "999999999999999984345037526797422397233524775199337052919583787413130412889023223627065756931830180808571031008919677160084252852199641809946030023447952696435527124027376600704816231425231719002378564135125254144"}, + {"0x1.7c37e360b3d36p+707", 309, "1000000000000000133847091685041515321667435950786483187020895512933942218108003650150514436025770781834322032256545705106635452959741180566593506333478305023178733248684891121346177720862393603318000095671837786112"}, + {"0x1.db45dc38e0c82p+710", 309, "9999999999999999544446266951486038123467425400819078260993214423089680518452271383223760211130420606034208307593944715707740128306913340586165347614418822310868858990958736965765439335377993421392542578277827477504"}, + {"0x1.db45dc38e0c83p+710", 309, "10000000000000000740462700217438781518938714805516247333803708227256174960204114795411349643881945414240216317574952939280149729167245650639345158094661640924814507988218853130896331250875288495917514830571527733248"}, + {"0x1.290ba9a38c7d1p+714", 309, "99999999999999990660396936451049407652789096389402106318690169014230827417515340183487244380298106827518051036015414262787762879627804165648934234223216948652905993920546904997130825691790753915825536773603473752064"}, + {"0x1.290ba9a38c7d2p+714", 309, "100000000000000009796659868706293301980329726864556811483658069880894738485544834778488675304322503758814179195711545839946316493393121126499811201907102046476036377876708763639225096339747475108225092810302677843968"}, + {"0x1.734e940c6f9c5p+717", 309, "999999999999999868331443500000006287872809702943711652856965888408980452039094412644869581954932274412588254040761879473560521568747407734787588406864399290882799171293145332687119715621994096773456255662636329336832"}, + {"0x1.734e940c6f9c6p+717", 309, "1000000000000000021421546958041957442493134746744949294176709095342291740583330369404881029347127449862957279318330932090828950478869943421594604148335480073467842242942440201823873880805647866312652703956229962072064"}, + {"0x1.d022390f8b837p+720", 309, "9999999999999999601855055748251769806450047292244542376488118125689672251656359867008764503902493796828096692073033110439215789148209291468717978517470477604338250142827222541691722147321863584969741246387925089779712"}, + {"0x1.d022390f8b838p+720", 309, "10000000000000000826575883412587379043412647642654443507046063781156162560010247521088856083040055200431048894293585531377363220429189576963174104449239123865018594716021581494785755468791093741283312832736674151661568"}, + {"0x1.221563a9b7322p+724", 309, "99999999999999988670225591496504042642724870819986016981533507324097780666440272745607095564199569546663253707407016578763273303796211201720443029584092898479300433989106071698353021544403254911815982945786756526505984"}, + {"0x1.221563a9b7323p+724", 309, "100000000000000008265758834125873790434126476426544435070460637811561625600102475210888560830400552004310488942935855313773632204291895769631741044492391238650185947160215814947857554687910937412833128327366741516615680"}, + {"0x1.6a9abc9424febp+727", 309, "999999999999999965084388885482519417592855130626093842171043595190833186399051537317196816706799625297221478016185520727674168639944850288849622355474122345476546392575499689981548348018063279122228410984187505225498624"}, + {"0x1.6a9abc9424fecp+727", 309, "1000000000000000121848654826517477399924067975478561186882460639090543945868349157039448538836407484958399359900416230607757039843910326832140006474740509066843630497944377635977584613166124739130365574036827385146376192"}, + {"0x1.c5416bb92e3e6p+730", 309, "9999999999999999964372420736895110140590976995965873111133270039707753382929110612616471611327211972294570543930316627036907428807379455975076991793273996897499632136492752791807556010476755711238558435947154812096741376"}, + {"0x1.c5416bb92e3e7p+730", 309, "10000000000000001218486548265174773999240679754785611868824606390905439458683491570394485388364074849583993599004162306077570398439103268321400064747405090668436304979443776359775846131661247391303655740368273851463761920"}, + {"0x1.1b48e353bce6fp+734", 309, "99999999999999984594354677029595135102113336853821866019036664182705300920238534632828550788829765195472628778417018121881118652493108811594893042483166843723756247249515245102456078650553656951604416706418119648563167232"}, + {"0x1.1b48e353bce70p+734", 309, "100000000000000004660180717482069756840508580994937686142098045801868278132308629957276771221419571232103397659598548986531726166600689809136062209749264344058743012736731622189948720589505523832645973577156024278435495936"}, + {"0x1.621b1c28ac20bp+737", 309, "999999999999999886075198851200900594497923856820450300436489405065378963626525536977181948753477264027987825546533242948112401553146250111031268759363863437907536003469585205199546070383440303278127280805657005745376329728"}, + {"0x1.621b1c28ac20cp+737", 309, "1000000000000000046601807174820697568405085809949376861420980458018682781323086299572767712214195712321033976595985489865317261666006898091360622097492643440587430127367316221899487205895055238326459735771560242784354959360"}, + {"0x1.baa1e332d728ep+740", 309, "9999999999999999181805205159248599892793562474462356126333876156560397271658376894962991014456209536865970557564236923315533735757183797070971394269896194384435148282491314085395342974857632902877937717988376531531720556544"}, + {"0x1.baa1e332d728fp+740", 309, "10000000000000000466018071748206975684050858099493768614209804580186827813230862995727677122141957123210339765959854898653172616660068980913606220974926434405874301273673162218994872058950552383264597357715602427843549593600"}, + {"0x1.14a52dffc6799p+744", 309, "99999999999999996954903517948319502092964807244749211214842475260109694882873713352688654575305085714037182409224841134505892881183378706080253249519082903930108094789640533388351546084948006950326015738792668900564521713664"}, + {"0x1.14a52dffc679ap+744", 309, "100000000000000017502309383371653514753081537245251811020857330038132583548033490964923632298277047095547089743554728739908114975629541647562410476799566744273134542648550103525944011430434718636512569974428283241553786306560"}, + {"0x1.59ce797fb817fp+747", 309, "999999999999999928454223448636526995609414612446486912536395043045051171498417578302416590307106934377352009423588636134254484622941461177838218040629861358615028052178586193608330530158506646130887048916655460323666687950848"}, + {"0x1.59ce797fb8180p+747", 309, "1000000000000000092833470372023199096890348452450507710984513881269234280819695799200296412090882625429431268098227736977472261378510764709695475858873732081359239635049862754709070252922400339620379482801740375051580804694016"}, + {"0x1.b04217dfa61dfp+750", 309, "9999999999999999613300728333138614158656013804472910722260188106898877933626732224819925546638620725877678611585164563028980399740553218842096696042786355031638703687528415058284784747112853848287855356936724432692495112994816"}, + {"0x1.b04217dfa61e0p+750", 309, "10000000000000000928334703720231990968903484524505077109845138812692342808196957992002964120908826254294312680982277369774722613785107647096954758588737320813592396350498627547090702529224003396203794828017403750515808046940160"}, + {"0x1.0e294eebc7d2bp+754", 309, "99999999999999988242803431008825880725075313724536108897092176834227990088845967645101024020764974088276981699468968789815350713138205618891818585152157755624664880897462875650012340778461641195382916742883168419985073526276096"}, + {"0x1.0e294eebc7d2cp+754", 309, "100000000000000009283347037202319909689034845245050771098451388126923428081969579920029641209088262542943126809822773697747226137851076470969547585887373208135923963504986275470907025292240033962037948280174037505158080469401600"}, + {"0x1.51b3a2a6b9c76p+757", 309, "999999999999999924509121522475246865178672200286390413373640190927670776874706901000867474584296317792102107215397297714017257980807797893073643852992008461269166974189675556141912776812173197487139230503413422370196749149011968"}, + {"0x1.51b3a2a6b9c77p+757", 309, "1000000000000000092833470372023199096890348452450507710984513881269234280819695799200296412090882625429431268098227736977472261378510764709695475858873732081359239635049862754709070252922400339620379482801740375051580804694016000"}, + {"0x1.a6208b5068394p+760", 309, "9999999999999999918388610622944277578633427011520373324179896670642961784527024602806390495869308408470337715685294734193992593398889846197223766553446979093051960385337504355687757672562640543404353314227442034427503713670135808"}, + {"0x1.a6208b5068395p+760", 309, "10000000000000001264983401419327895432326837028833311705066886193375469816086935788401821995921998869568971002747938248301632620580513580730198422600500768053772541672219001944225017481444457680470275332614057655878576158030168064"}, + {"0x1.07d457124123cp+764", 309, "99999999999999988411127779858373832956786989976700226194703050524569553592790956543300452958271560395914310860351799229078805716535908585708440417158039479244754953558323062848579498254571868337516156995181495372666457581821100032"}, + {"0x1.07d457124123dp+764", 309, "100000000000000009956644432600511718615881550253707240288894882888289682097749535512827356959114607773492443453354095454801046151441888338236034913910900102616284254148427024265175655196680942530570909289367345315883616691581616128"}, + {"0x1.49c96cd6d16cbp+767", 309, "999999999999999884111277798583738329567869899767002261947030505245695535927909565433004529582715603959143108603517992290788057165359085857084404171580394792447549535583230628485794982545718683375161569951814953726664575818211000320"}, + {"0x1.49c96cd6d16ccp+767", 309, "1000000000000000056475411020520841414840626381983058374700565164155456563967578197189219761589459982979768169347536362096565980644606923877305160145603279779419783940304062319818564238082591276919599588305301753272401848696295129088"}, + {"0x1.9c3bc80c85c7ep+770", 309, "9999999999999999185841044429711589466224211962102134844977374370276477415358432917842475759840644797632681207523216662519436418612086534611285553663849717898419964165273969667523488336530932020840491736225123136358120303938278260736"}, + {"0x1.9c3bc80c85c7fp+770", 309, "10000000000000000564754110205208414148406263819830583747005651641554565639675781971892197615894599829797681693475363620965659806446069238773051601456032797794197839403040623198185642380825912769195995883053017532724018486962951290880"}, + {"0x1.01a55d07d39cfp+774", 309, "99999999999999997374062707399103193390970327051935144057886852787877127050853725394623645022622268104986814019040754458979257737456796162759919727807229498567311142603806310797883499542489243201826933949562808949044795771481474727936"}, + {"0x1.01a55d07d39d0p+774", 309, "100000000000000019436671759807052388305883156775590326490339289128326538639931310259419194719485548619626821794275105794118831942800519429348176492482158776899757146408072767288477964251208935175515000298809119290899166699876243210240"}, + {"0x1.420eb449c8842p+777", 309, "999999999999999841364972759543336764420226292177420345984153909836074800974071744757463152045042997962028093539001436578955132142505622028069656690022719315678435403212464369035268207172574280176140941400150227439321732144446136385536"}, + {"0x1.420eb449c8843p+777", 309, "1000000000000000017865845178806930323739528929966661805443773400559670093686692423675827549619949242079148155740876247260071725785255408160775710807422153542338003433646596020960023924842331815965645472194120710174156699571604284243968"}, + {"0x1.9292615c3aa53p+780", 309, "9999999999999999119653217272487741881479473472931169297680017061255129180591200163248089110750054956088761184197513608514017695996055364811520783369824930063422626153861170298051704942404772944919427537177384205332557191153093955289088"}, + {"0x1.9292615c3aa54p+780", 309, "10000000000000000531660196626596490356033894575245100973356972987043891522292165594595004291349304909025721681812512093962950445138053653873169216309020403876699170397334223513449750683762833231235463783529148067211236930570359138156544"}, + {"0x1.f736f9b3494e8p+783", 309, "99999999999999994020546131433094915763903576933939556328154082464128816489313932495174721468699049466761532837205133056038042458244550226238504699576640248260779350025557809411313140906763850021826347864477369777082931390365469918625792"}, + {"0x1.f736f9b3494e9p+783", 309, "100000000000000005316601966265964903560338945752451009733569729870438915222921655945950042913493049090257216818125120939629504451380536538731692163090204038766991703973342235134497506837628332312354637835291480672112369305703591381565440"}, + {"0x1.3a825c100dd11p+787", 309, "999999999999999940205461314330949157639035769339395563281540824641288164893139324951747214686990494667615328372051330560380424582445502262385046995766402482607793500255578094113131409067638500218263478644773697770829313903654699186257920"}, + {"0x1.3a825c100dd12p+787", 309, "1000000000000000120942354671656868962382001670435578817768191183142249744630862900164152357803694488643546272066771136697843816472621283262276046411983423130707191163420128905684081263961470216866716118177799472091300320549064642593292288"}, + {"0x1.8922f31411455p+790", 309, "9999999999999999040580826428657651966904425891201589123842107529410958489455946099092661860636496958724291396331073693328877462044103460624068471125229983529879139676226679317989414380888721568885729507381685429067351125745727105048510464"}, + {"0x1.8922f31411456p+790", 309, "10000000000000000486475973287265010404848153099971055159735310397418651127357734700791903005570128910531738945888832142428584597165509708623196466454966148714674320981543085810557013220039375302073350623645891623631119178909006652304785408"}, + {"0x1.eb6bafd91596bp+793", 309, "99999999999999999081179145438220670296706622164632687453780292502155740721970192601122065475966761298087599260657287627887017431169472094235452683230716826407562484594165232135299736843791138087983021771402091458056119576436948334022754304"}, + {"0x1.eb6bafd91596cp+793", 309, "100000000000000010648340320307079537800256439834788415740925915446217281825184501414715994635435816912547179657119355220684674512140722078228476645868606147885923935036696484075840527556996367953483990701515741014566264001743184712072953856"}, + {"0x1.33234de7ad7e2p+797", 309, "999999999999999828871535006218182557917368774264146678517764203804695831774701602620905646527100834378441867056103929979702975178097221166452191355376717763378564539746214794185426298453038162762816652692429820789419173810082174047524749312"}, + {"0x1.33234de7ad7e3p+797", 309, "1000000000000000013946113804119924437974165856986638331112094170909680489426130543638408513078605724209795153399497011464465488473637220910340574757582946907032347746826714825234078949864321840610832155574248213693581484614981956096327942144"}, + {"0x1.7fec216198ddbp+800", 309, "9999999999999999029013665253788793099400876073531433395554961906466896948352731790279067931477027903109831815934611625736079804963132210640075447162592094208400778225784148066048873590175516339020228538451571779510840981320420868670460264448"}, + {"0x1.7fec216198ddcp+800", 309, "10000000000000000509610295637002728139855252735311366616309601643306774209564163318419090863889067021760658106681756277614179911327452208591182514380241927357631043882428148314438094801465785761804352561506118922744139467759619125060885807104"}, + {"0x1.dfe729b9ff152p+803", 309, "99999999999999993251329913304315801074917514058874200397058898538348724005950180959070725179594357268399970740840405561116998262359962102302968606061220608382468313571129481157267178324335702235770533430624812081575006786082605199485453729792"}, + {"0x1.dfe729b9ff153p+803", 309, "100000000000000005096102956370027281398552527353113666163096016433067742095641633184190908638890670217606581066817562776141799113274522085911825143802419273576310438824281483144380948014657857618043525615061189227441394677596191250608858071040"}, + {"0x1.2bf07a143f6d3p+807", 309, "999999999999999885134206960780312089454635087411784140906440513804611167700736000690226517958758320887173266104495426751070779219941381088594259909647411423049314634698686803624216704482068400828613365568502612232284516294771707790360919932928"}, + {"0x1.2bf07a143f6d4p+807", 309, "1000000000000000074650575649831695774632795300119615593163034400120115457135799236292149453307499328074479031320129942191467592834574340826335964513506590066150788638749118835418037019527222886944981240519484646566146722558989084608335389392896"}, + {"0x1.76ec98994f488p+810", 309, "9999999999999999230374806985905888264902671299533504313577592910677120255877486478106111050285065223246344191476223298391501419428679730361426008304192471516696094355087732099829807674910992980518869405586990190990569575476151831539558138249216"}, + {"0x1.76ec98994f489p+810", 309, "10000000000000000746505756498316957746327953001196155931630344001201154571357992362921494533074993280744790313201299421914675928345743408263359645135065900661507886387491188354180370195272228869449812405194846465661467225589890846083353893928960"}, + {"0x1.d4a7bebfa31aap+813", 309, "99999999999999992303748069859058882649026712995335043135775929106771202558774864781061110502850652232463441914762232983915014194286797303614260083041924715166960943550877320998298076749109929805188694055869901909905695754761518315395581382492160"}, + {"0x1.d4a7bebfa31abp+813", 309, "100000000000000004432795665958347438500428966608636256080197937830963477082618911859584178365170076692451010888562841972100410265623306726829729177688912148325455279810104971033102576911999816916636238052732752107272876955671430431745947427930112"}, + {"0x1.24e8d737c5f0ap+817", 309, "999999999999999874521290314193434603084658115500145579580071256170942927492372459496518833579228824484684143252419893886408557657521935343280724451831297419035632090471862609843762766839539749606096764571247618309588232743975534688554349643169792"}, + {"0x1.24e8d737c5f0bp+817", 309, "1000000000000000068586051851782051496707094173312964986690823395758019319873877212752887919376339615844485246833229637697374894798906086114728229966183096349571541470619505010400634769445777943389257468521053221467463131958534128550160206370177024"}, + {"0x1.6e230d05b76cdp+820", 309, "9999999999999999521471949292288813605336325386252733424243721120057734844449743607990664678980731410286045846847437914107950925140755956518597266575720169912499958425309195700665115678820350271193610461511698595727381924297989722331966923339726848"}, + {"0x1.6e230d05b76cep+820", 309, "10000000000000001073990041592997748754315813848755288681129738236754345983501781634041617365357617741164454675493915864595681622271829162690177310690534561356787233466490334905120091699670255821458896093110143420990381118014458473224813777155784704"}, + {"0x1.c9abd04725480p+823", 309, "99999999999999992109683308321470265755404276937522223728665176967184126166393360027804741417053541441103640811181423240104047857145413152842812577527572916236425034170729678597741204746503691611405533351920096306747820855546959721533975525765152768"}, + {"0x1.c9abd04725481p+823", 309, "100000000000000004529828046727141746947240184637542665783753313900757015278809664236212362908068632088130911440353246844005893434193998802215452930446088047790723234500178792233381012913302936013527818404707654908851814405278709728676750356293615616"}, + {"0x1.1e0b622c774d0p+827", 309, "999999999999999921096833083214702657554042769375222237286651769671841261663933600278047414170535414411036408111814232401040478571454131528428125775275729162364250341707296785977412047465036916114055333519200963067478208555469597215339755257651527680"}, + {"0x1.1e0b622c774d1p+827", 309, "1000000000000000119819148897705446356623417292575549310168061960609007487462594467612569358026776864763472738178563410063470007804231501918390371421971971267233021546978482604147648978133824826548011894363801900701142105351177597329624152546106933248"}, + {"0x1.658e3ab795204p+830", 309, "9999999999999999210968330832147026575540427693752222372866517696718412616639336002780474141705354144110364081118142324010404785714541315284281257752757291623642503417072967859774120474650369161140553335192009630674782085554695972153397552576515276800"}, + {"0x1.658e3ab795205p+830", 309, "10000000000000000800746857348072976168095423879354838955917799224215742423028622941456649692555285746929854721652135745309841019576760278403979222926327228462592673059242454405136015920000672444612205821948817131744093259920359973067672730884158521344"}, + {"0x1.bef1c9657a685p+833", 309, "99999999999999992109683308321470265755404276937522223728665176967184126166393360027804741417053541441103640811181423240104047857145413152842812577527572916236425034170729678597741204746503691611405533351920096306747820855546959721533975525765152768000"}, + {"0x1.bef1c9657a686p+833", 309, "100000000000000004827911520448877862495844246422343156393075429187162764617507655537214145823852994263659565935453370610499537728043164857800396298916132410948026391308085570960636368309306117879178753245974556315302310250472271728848176952226298724352"}, + {"0x1.17571ddf6c813p+837", 309, "999999999999999895660376658959887464073162830405580371957831265231883984761705009259228605356936508765924557863270337660249498829658628118512958332498610172941047627432585001251621720339432063578508893731092043050369229765618973200711352404729235767296"}, + {"0x1.17571ddf6c814p+837", 309, "1000000000000000099152028052998409011920202342162715294588395300751542199979533737409779075865727753926819359851621495586577336764022655397834297874715562088326669341630279279057944337344270883862880412035963403187241060084423965317738575228107571068928"}, + {"0x1.5d2ce55747a18p+840", 309, "9999999999999999363587069377675917736425707327570073564839440723358156278052707548893386994586947577981035182609405692455150664165314335743772262409420005560181719702721238568128862437403998276353831973920663150777435958293799716241167969694049028276224"}, + {"0x1.5d2ce55747a19p+840", 309, "10000000000000000991520280529984090119202023421627152945883953007515421999795337374097790758657277539268193598516214955865773367640226553978342978747155620883266693416302792790579443373442708838628804120359634031872410600844239653177385752281075710689280"}, + {"0x1.b4781ead1989ep+843", 309, "99999999999999993635870693776759177364257073275700735648394407233581562780527075488933869945869475779810351826094056924551506641653143357437722624094200055601817197027212385681288624374039982763538319739206631507774359582937997162411679696940490282762240"}, + {"0x1.b4781ead1989fp+843", 309, "100000000000000006659336382995224556426467602028157370696750505506839688554468114090569100058432115470107619153348531031836488269452441103314288354796084978186496986735864819460893271862349667261738096910718398556534156723341516657901421957636703742066688"}, + {"0x1.10cb132c2ff63p+847", 309, "999999999999999988452569694641453289891412847766833896677368465428848130901034909295879619908945316559292587569958465674654992927728624557883489163749540246356891129106733591931304833693638565628182306078113383272782784390994049606075766012189756664840192"}, + {"0x1.10cb132c2ff64p+847", 309, "1000000000000000196828020722136899354886781307806140057451066037800978143284091526922043301709947551604048864806030051391214698972517388491908540854979699007711767764445172532404979193506593517599378740822301656052939538637450361533911642183329172013711360"}, + {"0x1.54fdd7f73bf3bp+850", 309, "9999999999999998634272990781441856508941917717432502002131499220055701234712009387201814108283439755324388212283155142447191693008553661974684581490114449895439651479036702276471002178058655944454644452316004196046887318431202624493742403095061074555174912"}, + {"0x1.54fdd7f73bf3cp+850", 309, "10000000000000000301276599001405425028904865397746951288321079799032741333776462328211123562691457635682438430171727828179669341366863773446884995019955719986278664561744213800260397056562295560224215930269510378288141352402853119916429412464176397346144256"}, + {"0x1.aa3d4df50af0ap+853", 309, "99999999999999989676737124254345702129345072534953918593694153358511092545248999754036759991650433313959982558608696795936872226802156842691246641960827039136074540955782045812288811537593838676085587479067054324951381252255327235782798049688841391133687808"}, + {"0x1.aa3d4df50af0bp+853", 309, "100000000000000003012765990014054250289048653977469512883210797990327413337764623282111235626914576356824384301717278281796693413668637734468849950199557199862786645617442138002603970565622955602242159302695103782881413524028531199164294124641763973461442560"}, + {"0x1.0a6650b926d66p+857", 309, "999999999999999843423255779504622828654636399579476808778874955057845642282427503428069697375447760968142218613652642015929437520555644859802053186653349748453896990911180089361627479263821919056229587496158345417793683435460456504301996197076723582025859072"}, + {"0x1.0a6650b926d67p+857", 309, "1000000000000000056799717631659959599209893702659726317411141269166906774962677479877261307539674049653972646503389945789686576510419339128243706118473032320081290665497741564406670023712287789874734736674207136744674199783831719918405933396323484899269935104"}, + {"0x1.4cffe4e7708c0p+860", 309, "9999999999999999287738405203667575368767393208115766122317814807014700953545274940077463414411382764424743897695475635254322931165011225671787143593812227771048544607458046793796444970432082673836316471673778619485458899748089618699435710767754281089234894848"}, + {"0x1.4cffe4e7708c1p+860", 309, "10000000000000000994750100020910269533209451632757762191375945319887190014987274751670996295725193073911387320813374065444380043083920779819320367048369688344067694004150538594156785326019809640384357665098168950100503030535059726012267208361728371627187503104"}, + {"0x1.a03fde214caf0p+863", 309, "99999999999999992877384052036675753687673932081157661223178148070147009535452749400774634144113827644247438976954756352543229311650112256717871435938122277710485446074580467937964449704320826738363164716737786194854588997480896186994357107677542810892348948480"}, + {"0x1.a03fde214caf1p+863", 309, "100000000000000006533477610574617307003210399478293629775643192173126922026988747893522897194624310120140586361897943794063686207001388689898137223574581962294638641248120402340847172549022642470747494264132908839774942043776657045497009088429335535195969814528"}, + {"0x1.0427ead4cfed6p+867", 309, "999999999999999928773840520366757536876739320811576612231781480701470095354527494007746341441138276442474389769547563525432293116501122567178714359381222777104854460745804679379644497043208267383631647167377861948545889974808961869943571076775428108923489484800"}, + {"0x1.0427ead4cfed7p+867", 309, "1000000000000000147271337456973822389925322799165752109071222186349148695219103469891718550249305996056764747928638562589759603442121545498062966961564577730451305583522443629825768062558437319101780919925699824267271538715541135605986002768804111697781423341568"}, + {"0x1.4531e58a03e8bp+870", 309, "9999999999999998413748417457239315956573059294699064134960051984423986554086971036541574579178711885967582465059111638997013689862529533948250133185078807957662740116351490992011950708371166466963719380640490770210556304785160923755265983999639546733803159420928"}, + {"0x1.4531e58a03e8cp+870", 309, "10000000000000000161728392950095834780961727121532468109675577629605415353003578843613352249644053642881905330331839631511632172467492917395324154002545647584434349098564602595580939232492998880708913562707066468760361494711018313643605437535869015444666630275072"}, + {"0x1.967e5eec84e2ep+873", 309, "99999999999999987633444125558106197214507928600657449299031571134602723138702925979559301132717802373504470381136572374999373863835222106376649373485721758830170619127941133127257484131955329497127582170538059099205173427703324017329338747068854404759758535917568"}, + {"0x1.967e5eec84e2fp+873", 309, "100000000000000001617283929500958347809617271215324681096755776296054153530035788436133522496440536428819053303318396315116321724674929173953241540025456475844343490985646025955809392324929988807089135627070664687603614947110183136436054375358690154446666302750720"}, + {"0x1.fc1df6a7a61bap+876", 309, "999999999999999932269800471352470574525516656465243420181212531991832952952360709621889896782068959956303035500093019510461530081711049334072862401016156456358397678710230902586782474091451932211122035531511013345645500354660676649720249983847887046345216426508288"}, + {"0x1.fc1df6a7a61bbp+876", 309, "1000000000000000044140518902895287779286391397382581274563006173283444396083023609274483667691850832398819698877547611031397112968428705874685599733334034192471780653571870045215197739635249206690814463183771858052833032509915549602573975010166573043840478561173504"}, + {"0x1.3d92ba28c7d14p+880", 309, "9999999999999998875215130987353436926211667600983082784284950754751883757000955497608523884181562109792963701491111829020872969270239867178277674680890053619130444887655752455354163678739330224192450644706066754627704874925587274685787599733204126473471115726422016"}, + {"0x1.3d92ba28c7d15p+880", 309, "10000000000000000665146625892038512202385663455660488454393649015417666847091561892050024218738072068873230315530385293355842295457722371828081471997976097396944572485441978737408807927440086615867529487142240269942705389409665241931447200154303102433395309881065472"}, + {"0x1.8cf768b2f9c59p+883", 309, "99999999999999988752151309873534369262116676009830827842849507547518837570009554976085238841815621097929637014911118290208729692702398671782776746808900536191304448876557524553541636787393302241924506447060667546277048749255872746857875997332041264734711157264220160"}, + {"0x1.8cf768b2f9c5ap+883", 309, "100000000000000003071603269111014971471508642847250073203719093632845102290734406131617241518267700770571769927225306004888484302202258708981207125345588886413817469658847334809978790776999353375325137186550055668797052865128496484823152800700833072414104710501367808"}, + {"0x1.f03542dfb8370p+886", 309, "999999999999999973438224854160227305877518561122823750593712591987145964024444656694044404476868689015149167622996309190165824584023146941018349739309135463248122613459314107074039291811569329219648848907543004197890512187794469896370420793533163493423472892065087488"}, + {"0x1.f03542dfb8371p+886", 309, "1000000000000000087993840528060072123552654295822177713480669280669756081790243465938300425888485326396286230921509810907603861460022027238605792767602642265028226779717632589125536523728417738286853894823458109178050545114775459800092635220483497954858621317962268672"}, + {"0x1.362149cbd3226p+890", 309, "9999999999999999734382248541602273058775185611228237505937125919871459640244446566940444044768686890151491676229963091901658245840231469410183497393091354632481226134593141070740392918115693292196488489075430041978905121877944698963704207935331634934234728920650874880"}, + {"0x1.362149cbd3227p+890", 309, "10000000000000001567272099323999790141577357366417900912128432938793221524497227514848540387354553088249684689006179119380666835856213554171582585845787463460962892794726236783564348628785267837271769223730071721661465648709640537423259638766536986317197103735005773824"}, + {"0x1.83a99c3ec7eafp+893", 309, "99999999999999990012263082286432662256543169091523721434606031123027548865433341877772055077343404109122144711194766809100548098338386355056238620120129111010885594705399027856108106338478634741663761952135733701058809111452663635798820356028494943810497789949089153024"}, + {"0x1.83a99c3ec7eb0p+893", 309, "100000000000000004675381888545612798918960543133041028684136487274401643939455589461036825818030333693907688813404495028932616818466243033147431327741697981638738927986463793558699752023835231102266007829372867138519293326106230343475263802678137754874196788463928344576"}, + {"0x1.e494034e79e5bp+896", 309, "999999999999999929448868435382686895890266438998271828845121223533023678802377913944250092254807900260792535316367124530669618423639576906744771616444428851364562613616119809966264354755499540137842111275831603885509059543833769773341090453584235060232375896520569913344"}, + {"0x1.e494034e79e5cp+896", 309, "1000000000000000046753818885456127989189605431330410286841364872744016439394555894610368258180303336939076888134044950289326168184662430331474313277416979816387389279864637935586997520238352311022660078293728671385192933261062303434752638026781377548741967884639283445760"}, + {"0x1.2edc82110c2f9p+900", 309, "9999999999999999529098585253973751145501342374646995204443699533752222309208135100774737254399069875964494058799026896824009283758441475916906799486389390443691279468658234350904109878520700943148057046794110173854458342872794765056233999682236635579342942941443126198272"}, + {"0x1.2edc82110c2fap+900", 309, "10000000000000001405977792455148808638290766251961210532383597921128106478682982791432627909206996862817043703881872108962514079934807130712579466061950205884056506128634524360835840526246345277305144519080463253849400322348451303638818760853390915395496414751342542716928"}, + {"0x1.7a93a2954f3b7p+903", 309, "99999999999999991537227438137387396469434575991841521388557198562770454753131655626431591234374844785939841297824578543963083245231683449577722661712772273556182341366629763489177637489755720763166395523368395578554699469776634573397170474480057796161122485794632428945408"}, + {"0x1.7a93a2954f3b8p+903", 309, "100000000000000006552261095746787856411749967010355244012076385661777528108930437151694716472838260680760238458487340241071121614642608687943103994317258797079104154646440083568631482671560875436423095301659220218514235305581886882057848563849292034690350260273827761094656"}, + {"0x1.d9388b3aa30a5p+906", 309, "999999999999999945402341696592674884578976541955442659132610359825718694242914119314842162820675279649039207299571308833846909191138684972507989282336695782607667040225918275050684065261167516978177354790265605065466066369376850351293060923539046438669680406904714953752576"}, + {"0x1.d9388b3aa30a6p+906", 309, "1000000000000000065522610957467878564117499670103552440120763856617775281089304371516947164728382606807602384584873402410711216146426086879431039943172587970791041546464400835686314826715608754364230953016592202185142353055818868820578485638492920346903502602738277610946560"}, + {"0x1.27c35704a5e67p+910", 309, "9999999999999999213782878444176341486712719163258207029349796604673073768736360688744211624391338142173265718425108901184740478000812045911233791501695173449709921389782217629235579129702792695009666351450002856415308090320884466574359759805482716570229159677380024223137792"}, + {"0x1.27c35704a5e68p+910", 309, "10000000000000001135707186618179600359329089213627963525160252553345979158278604723977891654914655376710276554989942398414569389285410476422002602075069448460643913489597938599405671312973852493186523923071228410330128677303956762082926555244744699101970314810717026738241536"}, + {"0x1.71b42cc5cf601p+913", 309, "99999999999999995981677400789769932612359931733321583285118877944076548466448094957909476304960015890806678857380756006307062602577317320133875536163700284518967198097453618232695975663570046546450378657742479671982722077174989256760731188933351130765773907040474247261585408"}, + {"0x1.71b42cc5cf602p+913", 309, "100000000000000011357071866181796003593290892136279635251602525533459791582786047239778916549146553767102765549899423984145693892854104764220026020750694484606439134895979385994056713129738524931865239230712284103301286773039567620829265552447446991019703148107170267382415360"}, + {"0x1.ce2137f743381p+916", 309, "999999999999999929065985077113647184161737396527299728918221484261998998431805045015355882561227083155474615188770224107393363445219598313166454392463014445014728107377484646804238281703363508693674065431485187857190091380020735839470243162305319587149880588271350432374194176"}, + {"0x1.ce2137f743382p+916", 309, "1000000000000000052069140800249855752009185079750964144650090664977064943362508663270311404514719386165843308728919567930102413767433897865855658269158968045714503601765690788895124181432711335776992950015243623307738608946937362752018518070418086469181314516804918593340833792"}, + {"0x1.20d4c2fa8a030p+920", 309, "9999999999999998060628293539774386163142897133036353131863523035469330535011014267604003606077347801451059216486208802846843131230052987604772505157670608443149526129892785047133523819740156816103551808477267524066415738131041089269219682541925527051184466597377822714075545600"}, + {"0x1.20d4c2fa8a031p+920", 309, "10000000000000000028678785109953723248702060064614983783573429926910385653902272159683291957333224649616958313128598304010187936385481780447799767184805866054345934040104083320587698215409722049436653961817402491275192019201707119869992081071729797163687409453914913289541779456"}, + {"0x1.6909f3b92c83dp+923", 309, "99999999999999996350686867959178558315902274782992576532314485486221746301240205812674342870820492799837784938001204037775189753543960218791943147793788145321066524580618236658968633362758090027700335311493754978334367629875739137498376013657689431411868208826074951744485326848"}, + {"0x1.6909f3b92c83ep+923", 309, "100000000000000012095090800520613255000375578235621621745993740617750187252370268949308649680867507585164977711140320047081948194787390561536161244010870206210637787862308622846602028528114611894365152538214834716004577878441067382304555201896123592311891751678371676348215197696"}, + {"0x1.c34c70a777a4cp+926", 309, "999999999999999932018060814468916189790076140924667674895786344599160581110141931853474815088110898427723463833733808359138380652952741502430995285503717331431522719242801594214419543296867856543673718661495390308003255801626734885371401760100025992318635002556156068237393526784"}, + {"0x1.c34c70a777a4dp+926", 309, "1000000000000000057973292274960393763265862568545700036605220385651388108719182436946549269568487016710341006018846736433592448182900184244384740055240373818548092825496324683715486704619720031476992256475264028209364937790149360843820835266007499279518823345374529865067232493568"}, + {"0x1.1a0fc668aac6fp+930", 309, "9999999999999998312538756460757341310094469988278417855282391117573785590229095277790152515038100038016294300856434658995751266289947873088679994697143921417382666342399831226135658142385861165970188884104804799869139102108086341186118549553740473625584843283014570307735223533568"}, + {"0x1.1a0fc668aac70p+930", 309, "10000000000000000327822459828620982485707052830214935642633335774409426031973743359279343786724117930538174975818241508187016346769106956959939911012930425211247788042456200658152732723551495964903285489125103006290926013924448356521309485648260046220787856768108551057012647002112"}, + {"0x1.6093b802d578bp+933", 309, "99999999999999987155954971343300695452169865566657214127525800489409136785780248940879907693753036165206704358487960288340042823857796898629319779603012221761556906824111051125390730586189881257568082051088644411534964844713587442531567367726443881446254459800333664575907082272768"}, + {"0x1.6093b802d578cp+933", 309, "100000000000000003278224598286209824857070528302149356426333357744094260319737433592793437867241179305381749758182415081870163467691069569599399110129304252112477880424562006581527327235514959649032854891251030062909260139244483565213094856482600462207878567681085510570126470021120"}, + {"0x1.b8b8a6038ad6ep+936", 309, "999999999999999903804088967318825213331499981137556425872873119403461614925716858712626137284506647932417134384268512470460669526244514328233356457082706278317411015442012422166180499160548969358610366191211215418098239036197666670678728654776751975985792813764840337747509598224384"}, + {"0x1.b8b8a6038ad6fp+936", 309, "1000000000000000032782245982862098248570705283021493564263333577440942603197374335927934378672411793053817497581824150818701634676910695695993991101293042521124778804245620065815273272355149596490328548912510300629092601392444835652130948564826004622078785676810855105701264700211200"}, + {"0x1.137367c236c65p+940", 309, "9999999999999999553953517735361344274271821018911312812290573026184540102343798495987494338396687059809772796632907678097570555865109868753376103147668407754403581309634554796258176084383892202112976392797308495024959839786965342632596166187964530344229899589832462449290116390191104"}, + {"0x1.137367c236c66p+940", 309, "10000000000000001617604029984053712838099105849054307026537940354784235914690318131432426200603169381752178607793797891669425998275768770637546257455033787639321465930492277094643660455497502236220467316338093858400869637486920046335831684748752572681717785398568698736550198021980160"}, + {"0x1.585041b2c477ep+943", 309, "99999999999999991412234152856228705615063640528827139694410995604646009398744945688985079659553905954212916344007296353831994673829780883765420722861953317774200043854630103365810792101611701952914782080891514223497778802469744018919490624758069218767323224280852151918381000638332928"}, + {"0x1.585041b2c477fp+943", 309, "100000000000000007921438250845767654125681919169971093408389934233443575897517102772544534557205764529752162833294418062406838213115052098838781957320876356853543120821491881752894667070520582225774709469217797130505057184069381648545374773244373557467226310750742042216461653692645376"}, + {"0x1.ae64521f7595ep+946", 309, "999999999999999980159157920520442850193109519852847211800025710561650359982538085224088616186146493844286149397221450372619320895438893697947652166455225334059372746413748147206443420891752540620587530362220273863006901551095990707698442841525909542472844588688081080376132618600579072"}, + {"0x1.ae64521f7595fp+946", 309, "1000000000000000112232790704436754438278055748981998841511857219592030891972715341892564255367361362448600121311518424041218069209721063418534542042126609646694117362148642374303114420643023582803466949468830537119065128603893091744705516029416344252072069280447200202760777843035078656"}, + {"0x1.0cfeb353a97dap+950", 309, "9999999999999998216707985798208689444911740448978652561458278997251937215943253772219178491686886515191093831000650819703008229183002900332433843156495641588976792075318750746904382211902272900011322274342879579557370290877394694632899550160573878909537749585771381335145583492791795712"}, + {"0x1.0cfeb353a97dbp+950", 309, "10000000000000000329886110340869674854270880115045078636847583141738025727786089878914788718586324412860117381629402398400588202211517615861824081167237790591132705927077058380451118207922609574937392980048643791654301923722148311225012721166820834263125344653917287293299907083743789056"}, + {"0x1.503e602893dd1p+953", 309, "99999999999999990619792356152730836086553963154052229916140006550463726206803882148974225824466616742587032512521514511820402183944087865441899383607925011898391576160220738003230766103104075699817505566251852643961429440152961412697448185630726610509727876130297437184073129291725930496"}, + {"0x1.503e602893dd2p+953", 309, "100000000000000007525217352494018719361427080482583638519254439706352434301546571002539107639662119923939220917551527141401041968172205589677021287693862203915638886974287199071604654071266769099226071211897966340736882502910990345434353553680702253338428636675464684849307718019341877248"}, + {"0x1.a44df832b8d45p+956", 309, "999999999999999872387073568844732594315793396883459481955171199192859845878553443782612494614275161063165948315155119859042742270984643205948750027907375734949421139974074457895559885094715370199357924371226299046063388276013556261500671120207314819439877240212639876510262115462027411456"}, + {"0x1.a44df832b8d46p+956", 309, "1000000000000000007630473539575035660514778335511710750780086664439969510636494954611131549135839186513983455555395220895687860544809584999829725260594873271087399626486606146442550988840016917394626449536395208620267012778077787723395914064607119962069483324573977857832138825282954985472"}, + {"0x1.06b0bb1fb384bp+960", 309, "9999999999999998453383935746986719810759964091578092281901881061434379129269651416169086837099623559730024468671070996517137186162196548471725549813698762277218254426715681201861616643456550607603042193381925171312226633756007099691216225313273537909139560233403722802458867734978418966528"}, + {"0x1.06b0bb1fb384cp+960", 309, "10000000000000000617278335278671568869943723109630112583100528505388133765396715589425391709444647966943104584514912613103459078543395617173821153536698722855425910210916188218613474303381375362727338596024627724499484625789034803081540112423670420191213257583185130503608895092113260150784"}, + {"0x1.485ce9e7a065ep+963", 309, "99999999999999988861628156533236896225967158951884963421416105502251300564950642508203478115686284411726404918398393198344015646384363622121446705582987543928597855835557826052119881754415155586279014739104656819496782321626126403692810027353529143655542997033600043426888732064053872033792"}, + {"0x1.485ce9e7a065fp+963", 309, "100000000000000006172783352786715688699437231096301125831005285053881337653967155894253917094446479669431045845149126131034590785433956171738211535366987228554259102109161882186134743033813753627273385960246277244994846257890348030815401124236704201912132575831851305036088950921132601507840"}, + {"0x1.9a742461887f6p+966", 309, "999999999999999957860902350346284132153551878096514283852517773229033154005572478626236537071903625148082612890986863714202457020042006419681526374965874177788623543449994485057258262661745948026767632275613049896960078961318150545418464661067991669581788285529005480705688196068853638234112"}, + {"0x1.9a742461887f7p+966", 309, "1000000000000000096350143920374114471941312455251843583129231209642073450717704585714640048901985187209719740304992727175727058132438746816615645013237871654793913513638826934129377152896934732354722602044746013300944590451431923562399193436133392135634504915915015573579289946925483474026496"}, + {"0x1.008896bcf54f9p+970", 309, "9999999999999997916738124663128877244082391855101191247204616495333847979510139501201523228758057506741180599941798275603729356851659179433605840090394772053822755792233955461707155943795194068332216685526534938121786651731816229250415901309895111103185283290657933692573660950408978352832512"}, + {"0x1.008896bcf54fap+970", 309, "10000000000000000132565989783574162680686561089586460035632031477942492726904253214615979418039362499727374638565892090988122974650007025784551738302746731685907395315255274646861058187558214617579496201832662352585538835573636597522107561710941518560028749376834095178551288964115055725510656"}, + {"0x1.40aabc6c32a38p+973", 309, "99999999999999992462348437353960485060448933957923525202610654848990348279466077292501969423268405025328970231162545648343655275306678872441733790178059478330735395060467469727994972900530063978805843953102113868000379620369084502134308975505229555772913629423636305841602377586326247764393984"}, + {"0x1.40aabc6c32a39p+973", 309, "100000000000000010188971358317522768553282287833805675510029974709859506258618986999817618937518844969218522540155296171418804217693461643249300975876875155387412511244638023209226190850634228372784080083551133183710397091103647448307842258713600815427661358113045597729423401695974866745819136"}, + {"0x1.90d56b873f4c6p+976", 309, "999999999999999924623484373539604850604489339579235252026106548489903482794660772925019694232684050253289702311625456483436552753066788724417337901780594783307353950604674697279949729005300639788058439531021138680003796203690845021343089755052295557729136294236363058416023775863262477643939840"}, + {"0x1.90d56b873f4c7p+976", 309, "1000000000000000066436467741248103118547156170586292454485461107376856746627884050583544890346687569804406120783567460668037744292161050890877875387371120199760770880078039125129799472606133954939884328574613293205683935969567348590731356020719265634967118123751637393518591968740451429495341056"}, + {"0x1.f50ac6690f1f8p+979", 309, "9999999999999999813486777206230041577815560719820581330098483720446847883279500839884297726782854580737362697004022581572770293687044935910015528960168049498887207223940204684198896264456339658487887951484580004902758521100414464490983962613190835886243290260424727924570510530141380583845003264"}, + {"0x1.f50ac6690f1f9p+979", 309, "10000000000000000947990644147898027721356895367877038949773320191542473993945287061152499295694882737146294044779558615049579825999799033241699828844892252830514542659727120106997694213263006179702495063833317241108199639227426493046090092738526596504147144896546922605391056073158892198656212992"}, + {"0x1.3926bc01a973bp+983", 309, "99999999999999998134867772062300415778155607198205813300984837204468478832795008398842977267828545807373626970040225815727702936870449359100155289601680494988872072239402046841988962644563396584878879514845800049027585211004144644909839626131908358862432902604247279245705105301413805838450032640"}, + {"0x1.3926bc01a973cp+983", 309, "100000000000000016286929643128988194074816961567109135215782220741998496603447587939134202370420996309916528534448802351356655453874514916407104087757267748294909439211992693606769729825470060924312593312425595828314643101036337101791537708137280528748894576782202394138833833989693991675429388288"}, + {"0x1.87706b0213d09p+986", 309, "999999999999999872436306494222877488001587945768638201521064070819504681704034606746682422062730755058478860313950798943503314266680100247159860107083281430052496520558476587831205023360193979812186512362979225814553504769848291707808207769286850569305558980974742103098278680884456943362624192512"}, + {"0x1.87706b0213d0ap+986", 309, "1000000000000000017652801462756379714374878780719864776839443139119744823869255243069012222883470359078822072829219411228534934402712624705615450492327979456500795456339201761949451160807447294527656222743617592048849967890105831362861792425329827928397252374398383022243308510390698430058459037696"}, + {"0x1.e94c85c298c4cp+989", 309, "9999999999999999595662034753429788238255624467393741467120915117996487670031669885400803025551745174706847878231119663145222863482996149222332143382301002459214758820269116923021527058285459686414683385913622455551313826420028155008403585629126369847605750170289266545852965785882018353801250996224"}, + {"0x1.e94c85c298c4dp+989", 309, "10000000000000000757393994501697806049241951147003554069667947664398408807353434975979441432117662006869593578353268561425475824571256344889976866464258586670801150306514918315967496157863486204138441068958729385425685531382088472248832262877470188720339297317678393899013204421931950247367929757696"}, + {"0x1.31cfd3999f7afp+993", 309, "99999999999999986662764669548153739894665631237058913850832890808749507601742578129378923002990117089766513181334005445210204946123879926882163649167349350899456456312724758086647517786230384722356772394775369116518164624503799012160606438304513147494189124523779646633247748770420728389479079870464"}, + {"0x1.31cfd3999f7b0p+993", 309, "100000000000000005250476025520442024870446858110815915491585411551180245798890819578637137508044786404370444383288387817694252323536043057564479218478670698284838720092657580373783023379478809005936895323497079994508111903896764088007465274278014249457925878882005684283811566947219638686545940054016"}, + {"0x1.7e43c8800759bp+996", 309, "999999999999999903803069407426113968898218766118103141789833949572356552411722264192305659040010509526872994217248819197070144216063125530186267630296136203765329090687113225440746189048800695790727969805197112921161540803823920273299782054992133678869364753954248541633605124057805104488924519071744"}, + {"0x1.7e43c8800759cp+996", 309, "1000000000000000052504760255204420248704468581108159154915854115511802457988908195786371375080447864043704443832883878176942523235360430575644792184786706982848387200926575803737830233794788090059368953234970799945081119038967640880074652742780142494579258788820056842838115669472196386865459400540160"}, + {"0x1.ddd4baa009302p+999", 309, "9999999999999999335434075769817752248594687291161143444150379827602457335271594505111188022480979804302392841403758309930446200199225865392779725411942503595819407127350057411001629979979981746444561664911518503259454564508526643946547561925497354420113435609274102018745072331406833609642314953654272"}, + {"0x1.ddd4baa009303p+999", 309, "10000000000000000525047602552044202487044685811081591549158541155118024579889081957863713750804478640437044438328838781769425232353604305756447921847867069828483872009265758037378302337947880900593689532349707999450811190389676408800746527427801424945792587888200568428381156694721963868654594005401600"}, + {"0x1.2aa4f4a405be1p+1003", 309, "99999999999999988595886650569271721532146878831929642021471152965962304374245995240101777311515802698485322026337261211948545873374744892473124468375726771027536211745837771604509610367928220847849105179362427047829119141560667380048679757245757262098417746977035154548906385860807815060374033329553408"}, + {"0x1.2aa4f4a405be2p+1003", 309, "100000000000000007629703079084894925347346855150656811701601734206211380288125794484142188964691784076639747577138548761372210387844799938291815611350519830750167649856488981626536368095414607314235151058373458986890825155659063617715863205282622390509284183439858617103083735673849899204570498157510656"}, + {"0x1.754e31cd072d9p+1006", 309, "999999999999999847891233648661470807691068835681842080854450367179124891914700353912936949808806064228544369161770037020638129704807338833093862397807681590830099241237075296001042588224309435545718960035602206600167779387409881325152430676383842364162444596844704620380709158981993982315347403639619584"}, + {"0x1.754e31cd072dap+1006", 309, "1000000000000000000161765076786456438212668646231659438295495017101117499225738747865260243034213915253779773568180337416027445820567779199643391541606026068611150746122284976177256650044200527276807327067690462112661427500197051226489898260678763391449376088547292320814127957486330655468919122263277568"}, + {"0x1.d2a1be4048f90p+1009", 309, "9999999999999999392535525055364621860040287220117324953190771571323204563013233902843309257440507748436856118056162172578717193742636030530235798840866882774987301441682011041067710253162440905843719802548551599076639682550821832659549112269607949805346034918662572406407604380845959862074904348138143744"}, + {"0x1.d2a1be4048f91p+1009", 309, "10000000000000000610699776480364506904213085704515863812719128770699145421501541054461895603243770556638739353307444575741831722668719553462632031991253638597235713480763688482477422747721569639692426738805257643176588867453119191870248852943967318023641486852283274009874954768880653247303478097127407616"}, + {"0x1.23a516e82d9bap+1013", 309, "99999999999999993925355250553646218600402872201173249531907715713232045630132339028433092574405077484368561180561621725787171937426360305302357988408668827749873014416820110410677102531624409058437198025485515990766396825508218326595491122696079498053460349186625724064076043808459598620749043481381437440"}, + {"0x1.23a516e82d9bbp+1013", 309, "100000000000000013415983273353644379307167647951549871284361430903247099365945253454330474107257282415598692944582140176397004400243696672220697718814856920905847607042126949473232502444570468800016509005592812696365583783944976073966686973485829389546187580124556949719553650017014692784406223465209659392"}, + {"0x1.6c8e5ca239028p+1016", 309, "999999999999999861291040414336469543176969619010226008309262296372260241358071732580741399612641955118765084749534143455432389522994257585350220962461935904874831773666973747856549425664459851618054736334425973085267220421335152276470127823801795414563694568114532338018850013250375609552861714878501486592"}, + {"0x1.6c8e5ca239029p+1016", 309, "1000000000000000017216064596736454828831087825013238982328892017892380671244575047987920451875459594568606138861698291060311049225532948520696938805711440650122628514669428460356992624968028329550689224175284346730060716088829214255439694630119794546505512415617982143262670862918816362862119154749127262208"}, + {"0x1.c7b1f3cac7433p+1019", 309, "9999999999999999860310597602564577717002641838126363875249660735883565852672743849064846414228960666786379280392654615393353172850252103336275952370615397010730691664689375178569039851073146339641623266071126720011020169553304018596457812688561947201171488461172921822139066929851282122002676667750021070848"}, + {"0x1.c7b1f3cac7434p+1019", 309, "10000000000000001107710791061764460002235587486150467667406698508044529291764770372322278832331501782385107713289967796232382450470561630819049695116611434972713065592709012878572585445501694163102699168797993709169368134893256514428214347139105940256706031241200520264089633727198808148476736186715027275776"}, + {"0x1.1ccf385ebc89fp+1023", 309, "99999999999999981139503267596847425176765179308926185662298078548582170379439067165044410288854031049481594743364161622187121841818187648603927125262209438639553681654618823985640760188731793867961170022535129351893330180773705244319986644578003569234231285691342840034082734135647456849389933411990123839488"}, + {"0x1.1ccf385ebc8a0p+1023", 309, "100000000000000001097906362944045541740492309677311846336810682903157585404911491537163328978494688899061249669721172515611590283743140088328307009198146046031271664502933027185697489699588559043338384466165001178426897626212945177628091195786707458122783970171784415105291802893207873272974885715430223118336"}, + {"0x1.fffffffffffffp+1023", 309, "179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368"}, +] of _ diff --git a/spec/std/sprintf_spec.cr b/spec/std/sprintf_spec.cr index f37384d3a70c..d2da4369827b 100644 --- a/spec/std/sprintf_spec.cr +++ b/spec/std/sprintf_spec.cr @@ -583,11 +583,212 @@ describe "::sprintf" do end context "general format" do - pending_win32 "works" do - assert_sprintf "%g", 123, "123" - assert_sprintf "%G", 12345678.45, "1.23457E+07" - assert_sprintf "%100.50g", 123.45, " 123.4500000000000028421709430404007434844970703125" - assert_sprintf "%#.12g", 12345.0, "12345.0000000" + it "works" do + assert_sprintf "%g", 123.45, "123.45" + assert_sprintf "%G", 123.45, "123.45" + + assert_sprintf "%g", 1.2345e-5, "1.2345e-5" + assert_sprintf "%G", 1.2345e-5, "1.2345E-5" + + assert_sprintf "%g", 1.2345e+25, "1.2345e+25" + assert_sprintf "%G", 1.2345e+25, "1.2345E+25" + + assert_sprintf "%g", Float64::MAX, "1.79769e+308" + assert_sprintf "%g", Float64::MIN_POSITIVE, "2.22507e-308" + assert_sprintf "%g", Float64::MIN_SUBNORMAL, "4.94066e-324" + assert_sprintf "%g", 0.0, "0" + assert_sprintf "%g", -0.0, "-0" + assert_sprintf "%g", -Float64::MIN_SUBNORMAL, "-4.94066e-324" + assert_sprintf "%g", -Float64::MIN_POSITIVE, "-2.22507e-308" + assert_sprintf "%g", Float64::MIN, "-1.79769e+308" + end + + context "width specifier" do + it "sets the minimum length of the string" do + assert_sprintf "%10g", 123.45, " 123.45" + assert_sprintf "%10g", -123.45, " -123.45" + assert_sprintf "%+10g", 123.45, " +123.45" + + assert_sprintf "%7g", 123.45, " 123.45" + assert_sprintf "%7g", -123.45, "-123.45" + assert_sprintf "%+7g", 123.45, "+123.45" + + assert_sprintf "%6g", 123.45, "123.45" + assert_sprintf "%6g", -123.45, "-123.45" + assert_sprintf "%+6g", 123.45, "+123.45" + + assert_sprintf "%2g", 123.45, "123.45" + assert_sprintf "%2g", -123.45, "-123.45" + assert_sprintf "%+2g", 123.45, "+123.45" + end + + it "left-justifies on negative width" do + assert_sprintf "%*g", [-10, 123.45], "123.45 " + end + end + + context "precision specifier" do + it "sets the precision of the value" do + assert_sprintf "%.0g", 123.45, "1e+2" + assert_sprintf "%.1g", 123.45, "1e+2" + assert_sprintf "%.2g", 123.45, "1.2e+2" + assert_sprintf "%.3g", 123.45, "123" + assert_sprintf "%.4g", 123.45, "123.5" + assert_sprintf "%.5g", 123.45, "123.45" + assert_sprintf "%.6g", 123.45, "123.45" + assert_sprintf "%.7g", 123.45, "123.45" + assert_sprintf "%.8g", 123.45, "123.45" + + assert_sprintf "%.1000g", 123.45, "123.4500000000000028421709430404007434844970703125" + + assert_sprintf "%.0g", 1.23e-45, "1e-45" + assert_sprintf "%.1g", 1.23e-45, "1e-45" + assert_sprintf "%.2g", 1.23e-45, "1.2e-45" + assert_sprintf "%.3g", 1.23e-45, "1.23e-45" + assert_sprintf "%.4g", 1.23e-45, "1.23e-45" + assert_sprintf "%.5g", 1.23e-45, "1.23e-45" + assert_sprintf "%.6g", 1.23e-45, "1.23e-45" + + assert_sprintf "%.1000g", 1e-5, "1.0000000000000000818030539140313095458623138256371021270751953125e-5" + end + + it "can be used with width" do + assert_sprintf "%10.1g", 123.45, " 1e+2" + assert_sprintf "%10.2g", 123.45, " 1.2e+2" + assert_sprintf "%10.3g", 123.45, " 123" + assert_sprintf "%10.4g", 123.45, " 123.5" + assert_sprintf "%10.5g", 123.45, " 123.45" + assert_sprintf "%10.1g", -123.45, " -1e+2" + assert_sprintf "%10.2g", -123.45, " -1.2e+2" + assert_sprintf "%10.3g", -123.45, " -123" + assert_sprintf "%10.4g", -123.45, " -123.5" + assert_sprintf "%10.5g", -123.45, " -123.45" + assert_sprintf "%10.5g", 0, " 0" + + assert_sprintf "%-10.1g", 123.45, "1e+2 " + assert_sprintf "%-10.2g", 123.45, "1.2e+2 " + assert_sprintf "%-10.3g", 123.45, "123 " + assert_sprintf "%-10.4g", 123.45, "123.5 " + assert_sprintf "%-10.5g", 123.45, "123.45 " + assert_sprintf "%-10.1g", -123.45, "-1e+2 " + assert_sprintf "%-10.2g", -123.45, "-1.2e+2 " + assert_sprintf "%-10.3g", -123.45, "-123 " + assert_sprintf "%-10.4g", -123.45, "-123.5 " + assert_sprintf "%-10.5g", -123.45, "-123.45 " + assert_sprintf "%-10.5g", 0, "0 " + + assert_sprintf "%3.1g", 123.45, "1e+2" + assert_sprintf "%3.2g", 123.45, "1.2e+2" + assert_sprintf "%3.3g", 123.45, "123" + assert_sprintf "%3.4g", 123.45, "123.5" + assert_sprintf "%3.5g", 123.45, "123.45" + assert_sprintf "%3.1g", -123.45, "-1e+2" + assert_sprintf "%3.2g", -123.45, "-1.2e+2" + assert_sprintf "%3.3g", -123.45, "-123" + assert_sprintf "%3.4g", -123.45, "-123.5" + assert_sprintf "%3.5g", -123.45, "-123.45" + + assert_sprintf "%1000.800g", 123.45, "#{" " * 950}123.4500000000000028421709430404007434844970703125" + end + + it "is ignored if precision argument is negative" do + assert_sprintf "%.*g", [-2, 123.45], "123.45" + end + end + + context "sharp flag" do + it "prints decimal point and trailing zeros" do + assert_sprintf "%#.0g", 12345, "1.e+4" + assert_sprintf "%#.6g", 12345, "12345.0" + assert_sprintf "%#.10g", 12345, "12345.00000" + assert_sprintf "%#.100g", 12345, "12345.#{"0" * 95}" + assert_sprintf "%#.1000g", 12345, "12345.#{"0" * 995}" + + assert_sprintf "%#.0g", 1e-5, "1.e-5" + assert_sprintf "%#.6g", 1e-5, "1.00000e-5" + assert_sprintf "%#.10g", 1e-5, "1.000000000e-5" + assert_sprintf "%#.100g", 1e-5, "1.0000000000000000818030539140313095458623138256371021270751953125#{"0" * 35}e-5" + assert_sprintf "%#.1000g", 1e-5, "1.0000000000000000818030539140313095458623138256371021270751953125#{"0" * 935}e-5" + + assert_sprintf "%#15.0g", 12345, " 1.e+4" + assert_sprintf "%#15.6g", 12345, " 12345.0" + assert_sprintf "%#15.10g", 12345, " 12345.00000" + end + end + + context "plus flag" do + it "writes a plus sign for positive values" do + assert_sprintf "%+g", 123.45, "+123.45" + assert_sprintf "%+g", -123.45, "-123.45" + assert_sprintf "%+g", 0.0, "+0" + end + + it "writes plus sign after left space-padding" do + assert_sprintf "%+10g", 123.45, " +123.45" + assert_sprintf "%+10g", -123.45, " -123.45" + assert_sprintf "%+10g", 0.0, " +0" + end + + it "writes plus sign before left zero-padding" do + assert_sprintf "%+010g", 123.45, "+000123.45" + assert_sprintf "%+010g", -123.45, "-000123.45" + assert_sprintf "%+010g", 0.0, "+000000000" + end + end + + context "space flag" do + it "writes a space for positive values" do + assert_sprintf "% g", 123.45, " 123.45" + assert_sprintf "% g", -123.45, "-123.45" + assert_sprintf "% g", 0.0, " 0" + end + + it "writes space before left space-padding" do + assert_sprintf "% 10g", 123.45, " 123.45" + assert_sprintf "% 10g", -123.45, " -123.45" + assert_sprintf "% 10g", 0.0, " 0" + + assert_sprintf "% 010g", 123.45, " 000123.45" + assert_sprintf "% 010g", -123.45, "-000123.45" + assert_sprintf "% 010g", 0.0, " 000000000" + end + + it "is ignored if plus flag is also specified" do + assert_sprintf "% +g", 123.45, "+123.45" + assert_sprintf "%+ g", -123.45, "-123.45" + end + end + + context "zero flag" do + it "left-pads the result with zeros" do + assert_sprintf "%010g", 123.45, "0000123.45" + assert_sprintf "%010g", -123.45, "-000123.45" + assert_sprintf "%010g", 0.0, "0000000000" + end + + it "is ignored if string is left-justified" do + assert_sprintf "%-010g", 123.45, "123.45 " + assert_sprintf "%-010g", -123.45, "-123.45 " + assert_sprintf "%-010g", 0.0, "0 " + end + + it "can be used with precision" do + assert_sprintf "%010.2g", 123.45, "00001.2e+2" + assert_sprintf "%010.2g", -123.45, "-0001.2e+2" + assert_sprintf "%010.2g", 0.0, "0000000000" + end + end + + context "minus flag" do + it "left-justifies the string" do + assert_sprintf "%-10g", 123.45, "123.45 " + assert_sprintf "%-10g", -123.45, "-123.45 " + assert_sprintf "%-10g", 0.0, "0 " + + assert_sprintf "%- 10g", 123.45, " 123.45 " + assert_sprintf "%- 10g", -123.45, "-123.45 " + assert_sprintf "%- 10g", 0.0, " 0 " + end end end diff --git a/src/float/printer/ryu_printf.cr b/src/float/printer/ryu_printf.cr index d44a2fa8739b..005e575c3806 100644 --- a/src/float/printer/ryu_printf.cr +++ b/src/float/printer/ryu_printf.cr @@ -613,6 +613,76 @@ module Float::Printer::RyuPrintf index end + private MAX_FIXED_PRECISION = 66_u32 + private MAX_SCI_PRECISION = 766_u32 + + # Source port of Microsoft STL's `std::to_chars` based on: + # + # * https://github.com/ulfjack/ryu/pull/185/files + # * https://github.com/microsoft/STL/blob/a8888806c6960f1687590ffd4244794c753aa819/stl/inc/charconv#L2324 + # * https://github.com/llvm/llvm-project/blob/701f64790520790f75b1f948a752472d421ddaa3/libcxx/src/include/to_chars_floating_point.h#L836 + def self.d2gen_buffered_n(d : Float64, precision : UInt32, result : UInt8*, alternative : Bool = false) + if d == 0 + result[0] = '0'.ord.to_u8! + return {1, 0} + end + + precision = precision.clamp(1_u32, 1000000_u32) + if precision <= MAX_SPECIAL_P + table_begin = SPECIAL_X.to_unsafe + (precision &- 1) * (precision &+ 10) // 2 + table_length = precision.to_i32! &+ 5 + else + table_begin = ORDINARY_X.to_unsafe + table_length = {precision, MAX_ORDINARY_P}.min.to_i32! &+ 5 + end + + bits = d.unsafe_as(UInt64) + index = 0 + while index < table_length + break if bits <= table_begin[index] + index &+= 1 + end + + sci_exp_x = index &- 5 + use_fixed_notation = precision > sci_exp_x && sci_exp_x >= -4 + + significand_last = exponent_first = exponent_last = Pointer(UInt8).null + + # Write into the local buffer. + if use_fixed_notation + effective_precision = precision &- 1 &- sci_exp_x + max_precision = MAX_FIXED_PRECISION + len = d2fixed_buffered_n(d, {effective_precision, max_precision}.min, result) + significand_last = result + len + else + effective_precision = precision &- 1 + max_precision = MAX_SCI_PRECISION + len = d2exp_buffered_n(d, {effective_precision, max_precision}.min, result) + exponent_first = result + Slice.new(result, len).fast_index('e'.ord.to_u8!, 0).not_nil! + significand_last = exponent_first + exponent_last = result + len + end + + # If we printed a decimal point followed by digits, perform zero-trimming. + if effective_precision > 0 && !alternative + while significand_last[-1] === '0' # will stop at '.' or a nonzero digit + significand_last -= 1 + end + + if significand_last[-1] === '.' + significand_last -= 1 + end + end + + # Copy the exponent to the output range. + unless use_fixed_notation + exponent_first.move_to(significand_last, exponent_last - exponent_first) + end + + extra_zeros = effective_precision > max_precision ? effective_precision &- max_precision : 0_u32 + {(significand_last - result + (exponent_last - exponent_first)).to_i32!, extra_zeros.to_i32!} + end + def self.d2fixed(d : Float64, precision : Int) String.new(2000) do |buffer| len = d2fixed_buffered_n(d, precision.to_u32, buffer) @@ -626,4 +696,11 @@ module Float::Printer::RyuPrintf {len, len} end end + + def self.d2gen(d : Float64, precision : Int) + String.new(773) do |buffer| + len, _ = d2gen_buffered_n(d, precision.to_u32, buffer) + {len, len} + end + end end diff --git a/src/float/printer/ryu_printf_table.cr b/src/float/printer/ryu_printf_table.cr index dc733c492991..6e16b939f16c 100644 --- a/src/float/printer/ryu_printf_table.cr +++ b/src/float/printer/ryu_printf_table.cr @@ -16,6 +16,533 @@ module Float::Printer::RyuPrintf array << values end + # Special constants for `%g` formatting; for details refer to + # https://github.com/ulfjack/ryu/pull/185/files or + # https://github.com/microsoft/STL/blob/a8888806c6960f1687590ffd4244794c753aa819/stl/inc/xcharconv_tables.h + + private MAX_SPECIAL_P = 15_u32 + + private SPECIAL_X = begin + data = Array(UInt64).new(195) + put(data, 0x3F18E757928E0C9Du64) + put(data, 0x3F4F212D77318FC5u64) + put(data, 0x3F8374BC6A7EF9DBu64) + put(data, 0x3FB851EB851EB851u64) + put(data, 0x3FEE666666666666u64) + put(data, 0x4022FFFFFFFFFFFFu64) + put(data, 0x3F1A1554FBDAD751u64) + put(data, 0x3F504D551D68C692u64) + put(data, 0x3F8460AA64C2F837u64) + put(data, 0x3FB978D4FDF3B645u64) + put(data, 0x3FEFD70A3D70A3D7u64) + put(data, 0x4023E66666666666u64) + put(data, 0x4058DFFFFFFFFFFFu64) + put(data, 0x3F1A3387ECC8EB96u64) + put(data, 0x3F506034F3FD933Eu64) + put(data, 0x3F84784230FCF80Du64) + put(data, 0x3FB99652BD3C3611u64) + put(data, 0x3FEFFBE76C8B4395u64) + put(data, 0x4023FD70A3D70A3Du64) + put(data, 0x4058FCCCCCCCCCCCu64) + put(data, 0x408F3BFFFFFFFFFFu64) + put(data, 0x3F1A368D04E0BA6Au64) + put(data, 0x3F506218230C7482u64) + put(data, 0x3F847A9E2BCF91A3u64) + put(data, 0x3FB99945B6C3760Bu64) + put(data, 0x3FEFFF972474538Eu64) + put(data, 0x4023FFBE76C8B439u64) + put(data, 0x4058FFAE147AE147u64) + put(data, 0x408F3F9999999999u64) + put(data, 0x40C387BFFFFFFFFFu64) + put(data, 0x3F1A36DA54164F19u64) + put(data, 0x3F506248748DF16Fu64) + put(data, 0x3F847ADA91B16DCBu64) + put(data, 0x3FB99991361DC93Eu64) + put(data, 0x3FEFFFF583A53B8Eu64) + put(data, 0x4023FFF972474538u64) + put(data, 0x4058FFF7CED91687u64) + put(data, 0x408F3FF5C28F5C28u64) + put(data, 0x40C387F999999999u64) + put(data, 0x40F869F7FFFFFFFFu64) + put(data, 0x3F1A36E20F35445Du64) + put(data, 0x3F50624D49814ABAu64) + put(data, 0x3F847AE09BE19D69u64) + put(data, 0x3FB99998C2DA04C3u64) + put(data, 0x3FEFFFFEF39085F4u64) + put(data, 0x4023FFFF583A53B8u64) + put(data, 0x4058FFFF2E48E8A7u64) + put(data, 0x408F3FFEF9DB22D0u64) + put(data, 0x40C387FF5C28F5C2u64) + put(data, 0x40F869FF33333333u64) + put(data, 0x412E847EFFFFFFFFu64) + put(data, 0x3F1A36E2D51EC34Bu64) + put(data, 0x3F50624DC5333A0Eu64) + put(data, 0x3F847AE136800892u64) + put(data, 0x3FB9999984200AB7u64) + put(data, 0x3FEFFFFFE5280D65u64) + put(data, 0x4023FFFFEF39085Fu64) + put(data, 0x4058FFFFEB074A77u64) + put(data, 0x408F3FFFE5C91D14u64) + put(data, 0x40C387FFEF9DB22Du64) + put(data, 0x40F869FFEB851EB8u64) + put(data, 0x412E847FE6666666u64) + put(data, 0x416312CFEFFFFFFFu64) + put(data, 0x3F1A36E2E8E94FFCu64) + put(data, 0x3F50624DD191D1FDu64) + put(data, 0x3F847AE145F6467Du64) + put(data, 0x3FB999999773D81Cu64) + put(data, 0x3FEFFFFFFD50CE23u64) + put(data, 0x4023FFFFFE5280D6u64) + put(data, 0x4058FFFFFDE7210Bu64) + put(data, 0x408F3FFFFD60E94Eu64) + put(data, 0x40C387FFFE5C91D1u64) + put(data, 0x40F869FFFDF3B645u64) + put(data, 0x412E847FFD70A3D7u64) + put(data, 0x416312CFFE666666u64) + put(data, 0x4197D783FDFFFFFFu64) + put(data, 0x3F1A36E2EAE3F7A7u64) + put(data, 0x3F50624DD2CE7AC8u64) + put(data, 0x3F847AE14782197Bu64) + put(data, 0x3FB9999999629FD9u64) + put(data, 0x3FEFFFFFFFBB47D0u64) + put(data, 0x4023FFFFFFD50CE2u64) + put(data, 0x4058FFFFFFCA501Au64) + put(data, 0x408F3FFFFFBCE421u64) + put(data, 0x40C387FFFFD60E94u64) + put(data, 0x40F869FFFFCB923Au64) + put(data, 0x412E847FFFBE76C8u64) + put(data, 0x416312CFFFD70A3Du64) + put(data, 0x4197D783FFCCCCCCu64) + put(data, 0x41CDCD64FFBFFFFFu64) + put(data, 0x3F1A36E2EB16A205u64) + put(data, 0x3F50624DD2EE2543u64) + put(data, 0x3F847AE147A9AE94u64) + put(data, 0x3FB9999999941A39u64) + put(data, 0x3FEFFFFFFFF920C8u64) + put(data, 0x4023FFFFFFFBB47Du64) + put(data, 0x4058FFFFFFFAA19Cu64) + put(data, 0x408F3FFFFFF94A03u64) + put(data, 0x40C387FFFFFBCE42u64) + put(data, 0x40F869FFFFFAC1D2u64) + put(data, 0x412E847FFFF97247u64) + put(data, 0x416312CFFFFBE76Cu64) + put(data, 0x4197D783FFFAE147u64) + put(data, 0x41CDCD64FFF99999u64) + put(data, 0x4202A05F1FFBFFFFu64) + put(data, 0x3F1A36E2EB1BB30Fu64) + put(data, 0x3F50624DD2F14FE9u64) + put(data, 0x3F847AE147ADA3E3u64) + put(data, 0x3FB9999999990CDCu64) + put(data, 0x3FEFFFFFFFFF5014u64) + put(data, 0x4023FFFFFFFF920Cu64) + put(data, 0x4058FFFFFFFF768Fu64) + put(data, 0x408F3FFFFFFF5433u64) + put(data, 0x40C387FFFFFF94A0u64) + put(data, 0x40F869FFFFFF79C8u64) + put(data, 0x412E847FFFFF583Au64) + put(data, 0x416312CFFFFF9724u64) + put(data, 0x4197D783FFFF7CEDu64) + put(data, 0x41CDCD64FFFF5C28u64) + put(data, 0x4202A05F1FFF9999u64) + put(data, 0x42374876E7FF7FFFu64) + put(data, 0x3F1A36E2EB1C34C3u64) + put(data, 0x3F50624DD2F1A0FAu64) + put(data, 0x3F847AE147AE0938u64) + put(data, 0x3FB9999999998B86u64) + put(data, 0x3FEFFFFFFFFFEE68u64) + put(data, 0x4023FFFFFFFFF501u64) + put(data, 0x4058FFFFFFFFF241u64) + put(data, 0x408F3FFFFFFFEED1u64) + put(data, 0x40C387FFFFFFF543u64) + put(data, 0x40F869FFFFFFF294u64) + put(data, 0x412E847FFFFFEF39u64) + put(data, 0x416312CFFFFFF583u64) + put(data, 0x4197D783FFFFF2E4u64) + put(data, 0x41CDCD64FFFFEF9Du64) + put(data, 0x4202A05F1FFFF5C2u64) + put(data, 0x42374876E7FFF333u64) + put(data, 0x426D1A94A1FFEFFFu64) + put(data, 0x3F1A36E2EB1C41BBu64) + put(data, 0x3F50624DD2F1A915u64) + put(data, 0x3F847AE147AE135Au64) + put(data, 0x3FB9999999999831u64) + put(data, 0x3FEFFFFFFFFFFE3Du64) + put(data, 0x4023FFFFFFFFFEE6u64) + put(data, 0x4058FFFFFFFFFEA0u64) + put(data, 0x408F3FFFFFFFFE48u64) + put(data, 0x40C387FFFFFFFEEDu64) + put(data, 0x40F869FFFFFFFEA8u64) + put(data, 0x412E847FFFFFFE52u64) + put(data, 0x416312CFFFFFFEF3u64) + put(data, 0x4197D783FFFFFEB0u64) + put(data, 0x41CDCD64FFFFFE5Cu64) + put(data, 0x4202A05F1FFFFEF9u64) + put(data, 0x42374876E7FFFEB8u64) + put(data, 0x426D1A94A1FFFE66u64) + put(data, 0x42A2309CE53FFEFFu64) + put(data, 0x3F1A36E2EB1C4307u64) + put(data, 0x3F50624DD2F1A9E4u64) + put(data, 0x3F847AE147AE145Eu64) + put(data, 0x3FB9999999999975u64) + put(data, 0x3FEFFFFFFFFFFFD2u64) + put(data, 0x4023FFFFFFFFFFE3u64) + put(data, 0x4058FFFFFFFFFFDCu64) + put(data, 0x408F3FFFFFFFFFD4u64) + put(data, 0x40C387FFFFFFFFE4u64) + put(data, 0x40F869FFFFFFFFDDu64) + put(data, 0x412E847FFFFFFFD5u64) + put(data, 0x416312CFFFFFFFE5u64) + put(data, 0x4197D783FFFFFFDEu64) + put(data, 0x41CDCD64FFFFFFD6u64) + put(data, 0x4202A05F1FFFFFE5u64) + put(data, 0x42374876E7FFFFDFu64) + put(data, 0x426D1A94A1FFFFD7u64) + put(data, 0x42A2309CE53FFFE6u64) + put(data, 0x42D6BCC41E8FFFDFu64) + put(data, 0x3F1A36E2EB1C4328u64) + put(data, 0x3F50624DD2F1A9F9u64) + put(data, 0x3F847AE147AE1477u64) + put(data, 0x3FB9999999999995u64) + put(data, 0x3FEFFFFFFFFFFFFBu64) + put(data, 0x4023FFFFFFFFFFFDu64) + put(data, 0x4058FFFFFFFFFFFCu64) + put(data, 0x408F3FFFFFFFFFFBu64) + put(data, 0x40C387FFFFFFFFFDu64) + put(data, 0x40F869FFFFFFFFFCu64) + put(data, 0x412E847FFFFFFFFBu64) + put(data, 0x416312CFFFFFFFFDu64) + put(data, 0x4197D783FFFFFFFCu64) + put(data, 0x41CDCD64FFFFFFFBu64) + put(data, 0x4202A05F1FFFFFFDu64) + put(data, 0x42374876E7FFFFFCu64) + put(data, 0x426D1A94A1FFFFFBu64) + put(data, 0x42A2309CE53FFFFDu64) + put(data, 0x42D6BCC41E8FFFFCu64) + put(data, 0x430C6BF52633FFFBu64) + data + end + + private MAX_ORDINARY_P = 309_u32 + + private ORDINARY_X = begin + data = Array(UInt64).new(314) + put(data, 0x3F1A36E2EB1C432Cu64) + put(data, 0x3F50624DD2F1A9FBu64) + put(data, 0x3F847AE147AE147Au64) + put(data, 0x3FB9999999999999u64) + put(data, 0x3FEFFFFFFFFFFFFFu64) + put(data, 0x4023FFFFFFFFFFFFu64) + put(data, 0x4058FFFFFFFFFFFFu64) + put(data, 0x408F3FFFFFFFFFFFu64) + put(data, 0x40C387FFFFFFFFFFu64) + put(data, 0x40F869FFFFFFFFFFu64) + put(data, 0x412E847FFFFFFFFFu64) + put(data, 0x416312CFFFFFFFFFu64) + put(data, 0x4197D783FFFFFFFFu64) + put(data, 0x41CDCD64FFFFFFFFu64) + put(data, 0x4202A05F1FFFFFFFu64) + put(data, 0x42374876E7FFFFFFu64) + put(data, 0x426D1A94A1FFFFFFu64) + put(data, 0x42A2309CE53FFFFFu64) + put(data, 0x42D6BCC41E8FFFFFu64) + put(data, 0x430C6BF52633FFFFu64) + put(data, 0x4341C37937E07FFFu64) + put(data, 0x4376345785D89FFFu64) + put(data, 0x43ABC16D674EC7FFu64) + put(data, 0x43E158E460913CFFu64) + put(data, 0x4415AF1D78B58C3Fu64) + put(data, 0x444B1AE4D6E2EF4Fu64) + put(data, 0x4480F0CF064DD591u64) + put(data, 0x44B52D02C7E14AF6u64) + put(data, 0x44EA784379D99DB4u64) + put(data, 0x45208B2A2C280290u64) + put(data, 0x4554ADF4B7320334u64) + put(data, 0x4589D971E4FE8401u64) + put(data, 0x45C027E72F1F1281u64) + put(data, 0x45F431E0FAE6D721u64) + put(data, 0x46293E5939A08CE9u64) + put(data, 0x465F8DEF8808B024u64) + put(data, 0x4693B8B5B5056E16u64) + put(data, 0x46C8A6E32246C99Cu64) + put(data, 0x46FED09BEAD87C03u64) + put(data, 0x4733426172C74D82u64) + put(data, 0x476812F9CF7920E2u64) + put(data, 0x479E17B84357691Bu64) + put(data, 0x47D2CED32A16A1B1u64) + put(data, 0x48078287F49C4A1Du64) + put(data, 0x483D6329F1C35CA4u64) + put(data, 0x48725DFA371A19E6u64) + put(data, 0x48A6F578C4E0A060u64) + put(data, 0x48DCB2D6F618C878u64) + put(data, 0x4911EFC659CF7D4Bu64) + put(data, 0x49466BB7F0435C9Eu64) + put(data, 0x497C06A5EC5433C6u64) + put(data, 0x49B18427B3B4A05Bu64) + put(data, 0x49E5E531A0A1C872u64) + put(data, 0x4A1B5E7E08CA3A8Fu64) + put(data, 0x4A511B0EC57E6499u64) + put(data, 0x4A8561D276DDFDC0u64) + put(data, 0x4ABABA4714957D30u64) + put(data, 0x4AF0B46C6CDD6E3Eu64) + put(data, 0x4B24E1878814C9CDu64) + put(data, 0x4B5A19E96A19FC40u64) + put(data, 0x4B905031E2503DA8u64) + put(data, 0x4BC4643E5AE44D12u64) + put(data, 0x4BF97D4DF19D6057u64) + put(data, 0x4C2FDCA16E04B86Du64) + put(data, 0x4C63E9E4E4C2F344u64) + put(data, 0x4C98E45E1DF3B015u64) + put(data, 0x4CCF1D75A5709C1Au64) + put(data, 0x4D03726987666190u64) + put(data, 0x4D384F03E93FF9F4u64) + put(data, 0x4D6E62C4E38FF872u64) + put(data, 0x4DA2FDBB0E39FB47u64) + put(data, 0x4DD7BD29D1C87A19u64) + put(data, 0x4E0DAC74463A989Fu64) + put(data, 0x4E428BC8ABE49F63u64) + put(data, 0x4E772EBAD6DDC73Cu64) + put(data, 0x4EACFA698C95390Bu64) + put(data, 0x4EE21C81F7DD43A7u64) + put(data, 0x4F16A3A275D49491u64) + put(data, 0x4F4C4C8B1349B9B5u64) + put(data, 0x4F81AFD6EC0E1411u64) + put(data, 0x4FB61BCCA7119915u64) + put(data, 0x4FEBA2BFD0D5FF5Bu64) + put(data, 0x502145B7E285BF98u64) + put(data, 0x50559725DB272F7Fu64) + put(data, 0x508AFCEF51F0FB5Eu64) + put(data, 0x50C0DE1593369D1Bu64) + put(data, 0x50F5159AF8044462u64) + put(data, 0x512A5B01B605557Au64) + put(data, 0x516078E111C3556Cu64) + put(data, 0x5194971956342AC7u64) + put(data, 0x51C9BCDFABC13579u64) + put(data, 0x5200160BCB58C16Cu64) + put(data, 0x52341B8EBE2EF1C7u64) + put(data, 0x526922726DBAAE39u64) + put(data, 0x529F6B0F092959C7u64) + put(data, 0x52D3A2E965B9D81Cu64) + put(data, 0x53088BA3BF284E23u64) + put(data, 0x533EAE8CAEF261ACu64) + put(data, 0x53732D17ED577D0Bu64) + put(data, 0x53A7F85DE8AD5C4Eu64) + put(data, 0x53DDF67562D8B362u64) + put(data, 0x5412BA095DC7701Du64) + put(data, 0x5447688BB5394C25u64) + put(data, 0x547D42AEA2879F2Eu64) + put(data, 0x54B249AD2594C37Cu64) + put(data, 0x54E6DC186EF9F45Cu64) + put(data, 0x551C931E8AB87173u64) + put(data, 0x5551DBF316B346E7u64) + put(data, 0x558652EFDC6018A1u64) + put(data, 0x55BBE7ABD3781ECAu64) + put(data, 0x55F170CB642B133Eu64) + put(data, 0x5625CCFE3D35D80Eu64) + put(data, 0x565B403DCC834E11u64) + put(data, 0x569108269FD210CBu64) + put(data, 0x56C54A3047C694FDu64) + put(data, 0x56FA9CBC59B83A3Du64) + put(data, 0x5730A1F5B8132466u64) + put(data, 0x5764CA732617ED7Fu64) + put(data, 0x5799FD0FEF9DE8DFu64) + put(data, 0x57D03E29F5C2B18Bu64) + put(data, 0x58044DB473335DEEu64) + put(data, 0x583961219000356Au64) + put(data, 0x586FB969F40042C5u64) + put(data, 0x58A3D3E2388029BBu64) + put(data, 0x58D8C8DAC6A0342Au64) + put(data, 0x590EFB1178484134u64) + put(data, 0x59435CEAEB2D28C0u64) + put(data, 0x59783425A5F872F1u64) + put(data, 0x59AE412F0F768FADu64) + put(data, 0x59E2E8BD69AA19CCu64) + put(data, 0x5A17A2ECC414A03Fu64) + put(data, 0x5A4D8BA7F519C84Fu64) + put(data, 0x5A827748F9301D31u64) + put(data, 0x5AB7151B377C247Eu64) + put(data, 0x5AECDA62055B2D9Du64) + put(data, 0x5B22087D4358FC82u64) + put(data, 0x5B568A9C942F3BA3u64) + put(data, 0x5B8C2D43B93B0A8Bu64) + put(data, 0x5BC19C4A53C4E697u64) + put(data, 0x5BF6035CE8B6203Du64) + put(data, 0x5C2B843422E3A84Cu64) + put(data, 0x5C6132A095CE492Fu64) + put(data, 0x5C957F48BB41DB7Bu64) + put(data, 0x5CCADF1AEA12525Au64) + put(data, 0x5D00CB70D24B7378u64) + put(data, 0x5D34FE4D06DE5056u64) + put(data, 0x5D6A3DE04895E46Cu64) + put(data, 0x5DA066AC2D5DAEC3u64) + put(data, 0x5DD4805738B51A74u64) + put(data, 0x5E09A06D06E26112u64) + put(data, 0x5E400444244D7CABu64) + put(data, 0x5E7405552D60DBD6u64) + put(data, 0x5EA906AA78B912CBu64) + put(data, 0x5EDF485516E7577Eu64) + put(data, 0x5F138D352E5096AFu64) + put(data, 0x5F48708279E4BC5Au64) + put(data, 0x5F7E8CA3185DEB71u64) + put(data, 0x5FB317E5EF3AB327u64) + put(data, 0x5FE7DDDF6B095FF0u64) + put(data, 0x601DD55745CBB7ECu64) + put(data, 0x6052A5568B9F52F4u64) + put(data, 0x60874EAC2E8727B1u64) + put(data, 0x60BD22573A28F19Du64) + put(data, 0x60F2357684599702u64) + put(data, 0x6126C2D4256FFCC2u64) + put(data, 0x615C73892ECBFBF3u64) + put(data, 0x6191C835BD3F7D78u64) + put(data, 0x61C63A432C8F5CD6u64) + put(data, 0x61FBC8D3F7B3340Bu64) + put(data, 0x62315D847AD00087u64) + put(data, 0x6265B4E5998400A9u64) + put(data, 0x629B221EFFE500D3u64) + put(data, 0x62D0F5535FEF2084u64) + put(data, 0x630532A837EAE8A5u64) + put(data, 0x633A7F5245E5A2CEu64) + put(data, 0x63708F936BAF85C1u64) + put(data, 0x63A4B378469B6731u64) + put(data, 0x63D9E056584240FDu64) + put(data, 0x64102C35F729689Eu64) + put(data, 0x6444374374F3C2C6u64) + put(data, 0x647945145230B377u64) + put(data, 0x64AF965966BCE055u64) + put(data, 0x64E3BDF7E0360C35u64) + put(data, 0x6518AD75D8438F43u64) + put(data, 0x654ED8D34E547313u64) + put(data, 0x6583478410F4C7ECu64) + put(data, 0x65B819651531F9E7u64) + put(data, 0x65EE1FBE5A7E7861u64) + put(data, 0x6622D3D6F88F0B3Cu64) + put(data, 0x665788CCB6B2CE0Cu64) + put(data, 0x668D6AFFE45F818Fu64) + put(data, 0x66C262DFEEBBB0F9u64) + put(data, 0x66F6FB97EA6A9D37u64) + put(data, 0x672CBA7DE5054485u64) + put(data, 0x6761F48EAF234AD3u64) + put(data, 0x679671B25AEC1D88u64) + put(data, 0x67CC0E1EF1A724EAu64) + put(data, 0x680188D357087712u64) + put(data, 0x6835EB082CCA94D7u64) + put(data, 0x686B65CA37FD3A0Du64) + put(data, 0x68A11F9E62FE4448u64) + put(data, 0x68D56785FBBDD55Au64) + put(data, 0x690AC1677AAD4AB0u64) + put(data, 0x6940B8E0ACAC4EAEu64) + put(data, 0x6974E718D7D7625Au64) + put(data, 0x69AA20DF0DCD3AF0u64) + put(data, 0x69E0548B68A044D6u64) + put(data, 0x6A1469AE42C8560Cu64) + put(data, 0x6A498419D37A6B8Fu64) + put(data, 0x6A7FE52048590672u64) + put(data, 0x6AB3EF342D37A407u64) + put(data, 0x6AE8EB0138858D09u64) + put(data, 0x6B1F25C186A6F04Cu64) + put(data, 0x6B537798F428562Fu64) + put(data, 0x6B88557F31326BBBu64) + put(data, 0x6BBE6ADEFD7F06AAu64) + put(data, 0x6BF302CB5E6F642Au64) + put(data, 0x6C27C37E360B3D35u64) + put(data, 0x6C5DB45DC38E0C82u64) + put(data, 0x6C9290BA9A38C7D1u64) + put(data, 0x6CC734E940C6F9C5u64) + put(data, 0x6CFD022390F8B837u64) + put(data, 0x6D3221563A9B7322u64) + put(data, 0x6D66A9ABC9424FEBu64) + put(data, 0x6D9C5416BB92E3E6u64) + put(data, 0x6DD1B48E353BCE6Fu64) + put(data, 0x6E0621B1C28AC20Bu64) + put(data, 0x6E3BAA1E332D728Eu64) + put(data, 0x6E714A52DFFC6799u64) + put(data, 0x6EA59CE797FB817Fu64) + put(data, 0x6EDB04217DFA61DFu64) + put(data, 0x6F10E294EEBC7D2Bu64) + put(data, 0x6F451B3A2A6B9C76u64) + put(data, 0x6F7A6208B5068394u64) + put(data, 0x6FB07D457124123Cu64) + put(data, 0x6FE49C96CD6D16CBu64) + put(data, 0x7019C3BC80C85C7Eu64) + put(data, 0x70501A55D07D39CFu64) + put(data, 0x708420EB449C8842u64) + put(data, 0x70B9292615C3AA53u64) + put(data, 0x70EF736F9B3494E8u64) + put(data, 0x7123A825C100DD11u64) + put(data, 0x7158922F31411455u64) + put(data, 0x718EB6BAFD91596Bu64) + put(data, 0x71C33234DE7AD7E2u64) + put(data, 0x71F7FEC216198DDBu64) + put(data, 0x722DFE729B9FF152u64) + put(data, 0x7262BF07A143F6D3u64) + put(data, 0x72976EC98994F488u64) + put(data, 0x72CD4A7BEBFA31AAu64) + put(data, 0x73024E8D737C5F0Au64) + put(data, 0x7336E230D05B76CDu64) + put(data, 0x736C9ABD04725480u64) + put(data, 0x73A1E0B622C774D0u64) + put(data, 0x73D658E3AB795204u64) + put(data, 0x740BEF1C9657A685u64) + put(data, 0x74417571DDF6C813u64) + put(data, 0x7475D2CE55747A18u64) + put(data, 0x74AB4781EAD1989Eu64) + put(data, 0x74E10CB132C2FF63u64) + put(data, 0x75154FDD7F73BF3Bu64) + put(data, 0x754AA3D4DF50AF0Au64) + put(data, 0x7580A6650B926D66u64) + put(data, 0x75B4CFFE4E7708C0u64) + put(data, 0x75EA03FDE214CAF0u64) + put(data, 0x7620427EAD4CFED6u64) + put(data, 0x7654531E58A03E8Bu64) + put(data, 0x768967E5EEC84E2Eu64) + put(data, 0x76BFC1DF6A7A61BAu64) + put(data, 0x76F3D92BA28C7D14u64) + put(data, 0x7728CF768B2F9C59u64) + put(data, 0x775F03542DFB8370u64) + put(data, 0x779362149CBD3226u64) + put(data, 0x77C83A99C3EC7EAFu64) + put(data, 0x77FE494034E79E5Bu64) + put(data, 0x7832EDC82110C2F9u64) + put(data, 0x7867A93A2954F3B7u64) + put(data, 0x789D9388B3AA30A5u64) + put(data, 0x78D27C35704A5E67u64) + put(data, 0x79071B42CC5CF601u64) + put(data, 0x793CE2137F743381u64) + put(data, 0x79720D4C2FA8A030u64) + put(data, 0x79A6909F3B92C83Du64) + put(data, 0x79DC34C70A777A4Cu64) + put(data, 0x7A11A0FC668AAC6Fu64) + put(data, 0x7A46093B802D578Bu64) + put(data, 0x7A7B8B8A6038AD6Eu64) + put(data, 0x7AB137367C236C65u64) + put(data, 0x7AE585041B2C477Eu64) + put(data, 0x7B1AE64521F7595Eu64) + put(data, 0x7B50CFEB353A97DAu64) + put(data, 0x7B8503E602893DD1u64) + put(data, 0x7BBA44DF832B8D45u64) + put(data, 0x7BF06B0BB1FB384Bu64) + put(data, 0x7C2485CE9E7A065Eu64) + put(data, 0x7C59A742461887F6u64) + put(data, 0x7C9008896BCF54F9u64) + put(data, 0x7CC40AABC6C32A38u64) + put(data, 0x7CF90D56B873F4C6u64) + put(data, 0x7D2F50AC6690F1F8u64) + put(data, 0x7D63926BC01A973Bu64) + put(data, 0x7D987706B0213D09u64) + put(data, 0x7DCE94C85C298C4Cu64) + put(data, 0x7E031CFD3999F7AFu64) + put(data, 0x7E37E43C8800759Bu64) + put(data, 0x7E6DDD4BAA009302u64) + put(data, 0x7EA2AA4F4A405BE1u64) + put(data, 0x7ED754E31CD072D9u64) + put(data, 0x7F0D2A1BE4048F90u64) + put(data, 0x7F423A516E82D9BAu64) + put(data, 0x7F76C8E5CA239028u64) + put(data, 0x7FAC7B1F3CAC7433u64) + put(data, 0x7FE1CCF385EBC89Fu64) + put(data, 0x7FEFFFFFFFFFFFFFu64) + data + end + private POW10_OFFSET = [ 0, 2, 5, 8, 12, 16, 21, 26, 32, 39, 46, 54, 62, 71, 80, 90, 100, 111, 122, 134, diff --git a/src/string/formatter.cr b/src/string/formatter.cr index e85322f39d2e..31239f42ee4d 100644 --- a/src/string/formatter.cr +++ b/src/string/formatter.cr @@ -430,8 +430,37 @@ struct String::Formatter(A) # Formats floats with `%g` or `%G` private def float_general(float, flags) - # TODO: implement using `Float::Printer::RyuPrintf` - float_fallback(float, flags) + # `d2gen_buffered_n` will always take care of trailing zeros and return + # the number of stripped digits + precision = flags.precision.try(&.to_u32) || 6_u32 + + printf_buf = uninitialized UInt8[773] + printf_size, trailing_zeros = + Float::Printer::RyuPrintf.d2gen_buffered_n(float.abs, precision, printf_buf.to_unsafe, flags.sharp) + printf_slice = printf_buf.to_slice[0, printf_size] + dot_index = printf_slice.index('.'.ord) + e_index = printf_slice.rindex('e'.ord) + sign = Math.copysign(1.0, float) + + printf_slice[e_index] = 'E'.ord.to_u8! if e_index && flags.uppercase? + + str_size = printf_size + str_size += 1 if sign < 0 || flags.plus || flags.space + str_size += (dot_index.nil? ? 1 : 0) + trailing_zeros if flags.sharp + + pad(str_size, flags) if flags.left_padding? && flags.padding_char != '0' + + # this preserves -0.0's sign correctly + write_plus_or_space(sign, flags) + @io << '-' if sign < 0 + + pad(str_size, flags) if flags.left_padding? && flags.padding_char == '0' + @io.write_string(printf_slice[0...e_index]) + trailing_zeros.times { @io << '0' } if flags.sharp + @io << '.' if flags.sharp && dot_index.nil? + @io.write_string(printf_slice[e_index..]) if e_index + + pad(str_size, flags) if flags.right_padding? end # Formats floats with `%a` or `%A` From ddee6c6c5c277f58bf1017c7b39bba1e31ae3770 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Fri, 22 Dec 2023 17:03:35 +0800 Subject: [PATCH 002/105] Implement most of `Crystal::System.print_error` in native Crystal (#14116) --- spec/std/crystal/system_spec.cr | 46 +++++++++ src/crystal/system/print_error.cr | 153 ++++++++++++++++++++++++++++-- 2 files changed, 191 insertions(+), 8 deletions(-) create mode 100644 spec/std/crystal/system_spec.cr diff --git a/spec/std/crystal/system_spec.cr b/spec/std/crystal/system_spec.cr new file mode 100644 index 000000000000..06bc789055d4 --- /dev/null +++ b/spec/std/crystal/system_spec.cr @@ -0,0 +1,46 @@ +require "spec" + +private def print_error_to_s(format, *args) + io = IO::Memory.new + Crystal::System.print_error(format, *args) do |bytes| + io.write_string(bytes) + end + io.to_s +end + +describe "Crystal::System" do + describe ".print_error" do + it "works" do + print_error_to_s("abcde").should eq("abcde") + end + + it "supports %d" do + print_error_to_s("%d,%d,%d,%d,%d", 0, 1234, Int32::MAX, Int32::MIN, UInt64::MAX).should eq("0,1234,2147483647,-2147483648,-1") + end + + it "supports %u" do + print_error_to_s("%u,%u,%u,%u,%u", 0, 1234, UInt32::MAX, Int32::MIN, UInt64::MAX).should eq("0,1234,4294967295,2147483648,4294967295") + end + + it "supports %x" do + print_error_to_s("%x,%x,%x,%x,%x", 0, 0x1234, UInt32::MAX, Int32::MIN, UInt64::MAX).should eq("0,1234,ffffffff,80000000,ffffffff") + end + + it "supports %p" do + print_error_to_s("%p,%p,%p", Pointer(Void).new(0x0), Pointer(Void).new(0x1234), Pointer(Void).new(UInt64::MAX)).should eq("0x0,0x1234,0xffffffffffffffff") + end + + it "supports %s" do + print_error_to_s("%s,%s,%s", "abc\0def", "ghi".to_unsafe, Pointer(UInt8).null).should eq("abc\0def,ghi,(null)") + end + + it "supports %l width" do + values = {LibC::Long::MIN, LibC::Long::MAX, LibC::LongLong::MIN, LibC::LongLong::MAX} + print_error_to_s("%ld,%ld,%lld,%lld", *values).should eq(values.join(',')) + + values = {LibC::ULong::MIN, LibC::ULong::MAX, LibC::ULongLong::MIN, LibC::ULongLong::MAX} + print_error_to_s("%lu,%lu,%llu,%llu", *values).should eq(values.join(',')) + print_error_to_s("%lx,%lx,%llx,%llx", *values).should eq(values.join(',', &.to_s(16))) + end + end +end diff --git a/src/crystal/system/print_error.cr b/src/crystal/system/print_error.cr index 18f68d923507..3832eed5d9f4 100644 --- a/src/crystal/system/print_error.cr +++ b/src/crystal/system/print_error.cr @@ -1,15 +1,152 @@ module Crystal::System - # Prints directly to stderr without going through an IO. + # Prints directly to stderr without going through an `IO::FileDescriptor`. # This is useful for error messages from components that are required for # IO to work (fibers, scheduler, event_loop). def self.print_error(message, *args) - {% if flag?(:unix) %} - LibC.dprintf 2, message, *args - {% elsif flag?(:win32) %} - buffer = StaticArray(UInt8, 512).new(0_u8) - len = LibC.snprintf(buffer, buffer.size, message, *args) - LibC._write 2, buffer, len - {% end %} + print_error(message, *args) do |bytes| + {% if flag?(:unix) || flag?(:wasm32) %} + LibC.write 2, bytes, bytes.size + {% elsif flag?(:win32) %} + LibC._write 2, bytes, bytes.size + {% end %} + end + end + + # Minimal drop-in replacement for a C `printf` function. Yields successive + # non-empty `Bytes` to the block, which should do the actual printing. + # + # *format* only supports the `%(l|ll)?[dpsux]` format specifiers; more should + # be added only when we need them or an external library passes its own format + # string to here. *format* must also be null-terminated. + # + # Since this method may be called under low memory conditions or even with a + # corrupted heap, its implementation should be as low-level as possible, + # avoiding memory allocations. + # + # NOTE: C's `printf` is incompatible with Crystal's `sprintf`, because the + # latter does not support argument width specifiers nor `%p`. + def self.print_error(format, *args, &) + format = to_string_slice(format) + format_len = format.size + ptr = format.to_unsafe + finish = ptr + format_len + arg_index = 0 + + while ptr < finish + next_percent = ptr + while next_percent < finish && !(next_percent.value === '%') + next_percent += 1 + end + unless next_percent == ptr + yield Slice.new(ptr, next_percent - ptr) + end + + fmt_ptr = next_percent + 1 + width = 0 + if fmt_ptr.value === 'l' + width = 1 + fmt_ptr += 1 + if fmt_ptr.value === 'l' + width = 2 + fmt_ptr += 1 + end + end + + break unless fmt_ptr < finish + + case fmt_ptr.value + when 's' + read_arg(String | Pointer(UInt8)) do |arg| + yield to_string_slice(arg) + end + when 'd' + read_arg(Int::Primitive) do |arg| + to_int_slice(arg, 10, true, width) { |bytes| yield bytes } + end + when 'u' + read_arg(Int::Primitive) do |arg| + to_int_slice(arg, 10, false, width) { |bytes| yield bytes } + end + when 'x' + read_arg(Int::Primitive) do |arg| + to_int_slice(arg, 16, false, width) { |bytes| yield bytes } + end + when 'p' + read_arg(Pointer(Void)) do |arg| + # NOTE: MSVC uses `%X` rather than `0x%x`, we follow the latter on all platforms + yield "0x".to_slice + to_int_slice(arg.address, 16, false, 2) { |bytes| yield bytes } + end + else + yield Slice.new(next_percent, fmt_ptr + 1 - next_percent) + end + + ptr = fmt_ptr + 1 + end + end + + private macro read_arg(type, &block) + {{ block.args[0] }} = args[arg_index].as?({{ type }}) + if !{{ block.args[0] }}.nil? + {{ block.body }} + else + yield "(???)".to_slice + end + arg_index += 1 + end + + private def self.to_string_slice(str) + if str.is_a?(UInt8*) + if str.null? + "(null)".to_slice + else + Slice.new(str, LibC.strlen(str)) + end + else + str.to_s.to_slice + end + end + + # simplified version of `Int#internal_to_s` + private def self.to_int_slice(num, base, signed, width, &) + if num == 0 + yield "0".to_slice + return + end + + # Given sizeof(num) <= 64 bits, we need at most 20 bytes for `%d` or `%u` + # note that `chars` does not have to be null-terminated, since we are + # only yielding a `Bytes` + chars = uninitialized UInt8[20] + ptr_end = chars.to_unsafe + 20 + ptr = ptr_end + + num = case {signed, width} + when {true, 2} then LibC::LongLong.new!(num) + when {true, 1} then LibC::Long.new!(num) + when {true, 0} then LibC::Int.new!(num) + when {false, 2} then LibC::ULongLong.new!(num) + when {false, 1} then LibC::ULong.new!(num) + else LibC::UInt.new!(num) + end + + neg = num < 0 + + # do not assume Crystal constant initialization succeeds, hence not `DIGITS` + digits = "0123456789abcdef".to_unsafe + + while num != 0 + ptr -= 1 + ptr.value = digits[num.remainder(base).abs] + num = num.tdiv(base) + end + + if neg + ptr -= 1 + ptr.value = '-'.ord.to_u8 + end + + yield Slice.new(ptr, ptr_end - ptr) end def self.print_exception(message, ex) From 3ecdf161afab5f810e949560d637b76fa43841b1 Mon Sep 17 00:00:00 2001 From: Erdian718 <erdian718@qq.com> Date: Fri, 22 Dec 2023 17:03:47 +0800 Subject: [PATCH 003/105] Fix UTF-8 console input on Windows (#13758) Co-authored-by: Quinton Miller <nicetas.c@gmail.com> --- src/crystal/system/win32/file_descriptor.cr | 71 ++++++++++++++++++- src/lib_c/x86_64-windows-msvc/c/consoleapi.cr | 8 +++ src/string/utf16.cr | 4 +- 3 files changed, 80 insertions(+), 3 deletions(-) diff --git a/src/crystal/system/win32/file_descriptor.cr b/src/crystal/system/win32/file_descriptor.cr index 6e4f42d46b17..109c353c0325 100644 --- a/src/crystal/system/win32/file_descriptor.cr +++ b/src/crystal/system/win32/file_descriptor.cr @@ -11,7 +11,10 @@ module Crystal::System::FileDescriptor @system_blocking = true private def unbuffered_read(slice : Bytes) - if system_blocking? + handle = windows_handle + if ConsoleUtils.console?(handle) + ConsoleUtils.read(handle, slice) + elsif system_blocking? bytes_read = LibC._read(fd, slice, slice.size) if bytes_read == -1 if Errno.value == Errno::EBADF @@ -22,7 +25,6 @@ module Crystal::System::FileDescriptor end bytes_read else - handle = windows_handle overlapped_operation(handle, "ReadFile", read_timeout) do |overlapped| ret = LibC.ReadFile(handle, slice, slice.size, out byte_count, overlapped) {ret, byte_count} @@ -276,6 +278,71 @@ module Crystal::System::FileDescriptor end end +private module ConsoleUtils + # N UTF-16 code units correspond to no more than 3*N UTF-8 code units. + # NOTE: For very large buffers, `ReadConsoleW` may fail. + private BUFFER_SIZE = 10000 + @@utf8_buffer = Slice(UInt8).new(3 * BUFFER_SIZE) + + # `@@buffer` points to part of `@@utf8_buffer`. + # It represents data that has not been read yet. + @@buffer : Bytes = @@utf8_buffer[0, 0] + + # Remaining UTF-16 code unit. + @@remaining_unit : UInt16? + + # Determines if *handle* is a console. + def self.console?(handle : LibC::HANDLE) : Bool + LibC.GetConsoleMode(handle, out _) != 0 + end + + # Reads to *slice* from the console specified by *handle*, + # and return the actual number of bytes read. + def self.read(handle : LibC::HANDLE, slice : Bytes) : Int32 + return 0 if slice.empty? + fill_buffer(handle) if @@buffer.empty? + + bytes_read = {slice.size, @@buffer.size}.min + @@buffer[0, bytes_read].copy_to(slice) + @@buffer += bytes_read + bytes_read + end + + private def self.fill_buffer(handle : LibC::HANDLE) : Nil + utf16_buffer = uninitialized UInt16[BUFFER_SIZE] + remaining_unit = @@remaining_unit + if remaining_unit + utf16_buffer[0] = remaining_unit + index = read_console(handle, utf16_buffer.to_slice + 1) + else + index = read_console(handle, utf16_buffer.to_slice) - 1 + end + + if index >= 0 && utf16_buffer[index] & 0xFC00 == 0xD800 + @@remaining_unit = utf16_buffer[index] + index -= 1 + else + @@remaining_unit = nil + end + return if index < 0 + + appender = @@utf8_buffer.to_unsafe.appender + String.each_utf16_char(utf16_buffer.to_slice[..index]) do |char| + char.each_byte do |byte| + appender << byte + end + end + @@buffer = @@utf8_buffer[0, appender.size] + end + + private def self.read_console(handle : LibC::HANDLE, slice : Slice(UInt16)) : Int32 + if 0 == LibC.ReadConsoleW(handle, slice, slice.size, out units_read, nil) + raise IO::Error.from_winerror("ReadConsoleW") + end + units_read.to_i32 + end +end + # Enable UTF-8 console I/O for the duration of program execution if LibC.IsValidCodePage(LibC::CP_UTF8) != 0 old_input_cp = LibC.GetConsoleCP diff --git a/src/lib_c/x86_64-windows-msvc/c/consoleapi.cr b/src/lib_c/x86_64-windows-msvc/c/consoleapi.cr index 680e199be2ab..796369c65a85 100644 --- a/src/lib_c/x86_64-windows-msvc/c/consoleapi.cr +++ b/src/lib_c/x86_64-windows-msvc/c/consoleapi.cr @@ -14,6 +14,14 @@ lib LibC fun GetConsoleCP : DWORD fun GetConsoleOutputCP : DWORD + fun ReadConsoleW( + hConsoleInput : HANDLE, + lpBuffer : Void*, + nNumberOfCharsToRead : DWORD, + lpNumberOfCharsRead : DWORD*, + pInputControl : Void* + ) : BOOL + CTRL_C_EVENT = 0 CTRL_BREAK_EVENT = 1 diff --git a/src/string/utf16.cr b/src/string/utf16.cr index b3fdc09301af..042391cca15d 100644 --- a/src/string/utf16.cr +++ b/src/string/utf16.cr @@ -128,8 +128,10 @@ class String {string, pointer + 1} end + # :nodoc: + # # Yields each decoded char in the given slice. - private def self.each_utf16_char(slice : Slice(UInt16), &) + def self.each_utf16_char(slice : Slice(UInt16), &) i = 0 while i < slice.size byte = slice[i].to_i From ac6b56e061bc6b86dd9d8c1045074ca4b7e61500 Mon Sep 17 00:00:00 2001 From: Julien Portalier <julien@portalier.com> Date: Fri, 22 Dec 2023 15:15:23 +0100 Subject: [PATCH 004/105] Workaround regular timeouts in `HTTP::Server` specs with MT (#14097) --- spec/std/http/server/server_spec.cr | 5 +---- spec/std/http/spec_helper.cr | 5 +++++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/spec/std/http/server/server_spec.cr b/spec/std/http/server/server_spec.cr index e5aa0ec261a7..f5a82a514e0b 100644 --- a/spec/std/http/server/server_spec.cr +++ b/spec/std/http/server/server_spec.cr @@ -45,12 +45,9 @@ describe HTTP::Server do server = HTTP::Server.new { } server.bind_unused_port - spawn do + run_server(server) do server.close - sleep 0.001 end - - server.listen end it "closes the server" do diff --git a/spec/std/http/spec_helper.cr b/spec/std/http/spec_helper.cr index 410e211e4dbe..18ec9e0bab46 100644 --- a/spec/std/http/spec_helper.cr +++ b/spec/std/http/spec_helper.cr @@ -46,6 +46,11 @@ def run_server(server, &) wait_for { server.listening? } wait_until_blocked f + {% if flag?(:preview_mt) %} + # avoids fiber synchronization issues in specs, like closing the server + # before we properly listen, ... + sleep 0.001 + {% end %} yield server_done ensure server.close unless server.closed? From 2514ac42b2a1ea0692a7a2ffe7fb37e9ef537e7b Mon Sep 17 00:00:00 2001 From: George Dietrich <george@dietrich.app> Date: Fri, 22 Dec 2023 09:15:40 -0500 Subject: [PATCH 005/105] Add location information to implicit flag enum members (#14127) --- spec/compiler/semantic/doc_spec.cr | 18 ++++++++++++++++++ .../crystal/semantic/top_level_visitor.cr | 15 +++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/spec/compiler/semantic/doc_spec.cr b/spec/compiler/semantic/doc_spec.cr index 9b38339b6485..3338f920a938 100644 --- a/spec/compiler/semantic/doc_spec.cr +++ b/spec/compiler/semantic/doc_spec.cr @@ -353,6 +353,24 @@ describe "Semantic: doc" do a.locations.not_nil!.size.should eq(1) end + it "stores location for implicit flag enum members" do + result = semantic %( + @[Flags] + enum Foo + A = 1 + B = 2 + end + ), wants_doc: true + program = result.program + foo = program.types["Foo"] + + a_loc = foo.types["All"].locations.should_not be_nil + a_loc.should_not be_empty + + b_loc = foo.types["None"].locations.should_not be_nil + b_loc.should_not be_empty + end + it "stores doc for constant" do result = semantic %( # Hello diff --git a/src/compiler/crystal/semantic/top_level_visitor.cr b/src/compiler/crystal/semantic/top_level_visitor.cr index 5d0cbc477260..05d8918f8383 100644 --- a/src/compiler/crystal/semantic/top_level_visitor.cr +++ b/src/compiler/crystal/semantic/top_level_visitor.cr @@ -655,16 +655,27 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor if enum_type.flags? unless enum_type.types.has_key?("None") - enum_type.add_constant("None", 0) + none_member = enum_type.add_constant("None", 0) + + if node_location = node.location + none_member.add_location node_location + end + define_enum_none_question_method(enum_type, node) end unless enum_type.types.has_key?("All") all_value = enum_type.base_type.kind.cast(0).as(Int::Primitive) + enum_type.types.each_value do |member| all_value |= interpret_enum_value(member.as(Const).value, enum_type.base_type) end - enum_type.add_constant("All", all_value) + + all_member = enum_type.add_constant("All", all_value) + + if node_location = node.location + all_member.add_location node_location + end end end From f362827ed2f1766c8f15d480354238a67556ca31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Fri, 22 Dec 2023 15:16:16 +0100 Subject: [PATCH 006/105] Add `--tallies` option to `crystal tool unreachable` (#13969) Co-authored-by: Quinton Miller <nicetas.c@gmail.com> --- .../crystal/tools/unreachable_spec.cr | 44 +++++++++++++--- src/compiler/crystal/command.cr | 10 +++- src/compiler/crystal/tools/unreachable.cr | 50 +++++++++++-------- 3 files changed, 73 insertions(+), 31 deletions(-) diff --git a/spec/compiler/crystal/tools/unreachable_spec.cr b/spec/compiler/crystal/tools/unreachable_spec.cr index 6fffb17e4ca6..12ed82499740 100644 --- a/spec/compiler/crystal/tools/unreachable_spec.cr +++ b/spec/compiler/crystal/tools/unreachable_spec.cr @@ -15,28 +15,37 @@ def processed_unreachable_visitor(code) end private def assert_unreachable(code, file = __FILE__, line = __LINE__) - expected_locations = [] of Location + expected = Hash(String, Int32).new code.lines.each_with_index do |line, line_number_0| - if column_number = line.index('༓') - expected_locations << Location.new(".", line_number_0 + 1, column_number + 1) + if match = line.match(/༓(?:\[(\d+)\])?/) + location = Location.new(".", line_number_0 + 1, match.begin + 1) + expected[location.to_s] = (match[1]? || 0).to_i end end - code = code.gsub('༓', "") + code = code.gsub(/༓(?:\[(\d+)\])?/, "") - defs = processed_unreachable_visitor(code) + tallies = processed_unreachable_visitor(code) - result_location = defs.try &.compact_map(&.location).sort_by! do |loc| + processed_results = [] of {Location, Int32} + tallies.each do |k, v| + location = k.location.not_nil! + next unless v.zero? || expected.has_key?(location.to_s) + processed_results << {location, v} + end + + processed_results = processed_results.sort_by! do |loc, v| {loc.filename.as(String), loc.line_number, loc.column_number} - end.map(&.to_s) + end.map { |k, v| {k.to_s, v} } - result_location.should eq(expected_locations.map(&.to_s)), file: file, line: line + processed_results.should eq(expected.to_a), file: file, line: line end # References # # ༓ marks the expected unreachable code to be found +# ༓[n] marks the expected code to be called n times # describe "unreachable" do it "finds top level methods" do @@ -424,4 +433,23 @@ describe "unreachable" do {% end %} CRYSTAL end + + it "tallies calls" do + assert_unreachable <<-CRYSTAL + ༓def foo + 1 + end + + ༓[2]def bar + 2 + end + + ༓[1]def baz + bar + end + + bar + baz + CRYSTAL + end end diff --git a/src/compiler/crystal/command.cr b/src/compiler/crystal/command.cr index 2c5492445e0b..69b4ab2d221c 100644 --- a/src/compiler/crystal/command.cr +++ b/src/compiler/crystal/command.cr @@ -349,7 +349,8 @@ class Crystal::Command includes : Array(String), excludes : Array(String), verbose : Bool, - check : Bool do + check : Bool, + tallies : Bool do def compile(output_filename = self.output_filename) compiler.emit_base_filename = emit_base_filename || output_filename.rchop(File.extname(output_filename)) compiler.compile sources, output_filename, combine_rpath: combine_rpath @@ -381,6 +382,7 @@ class Crystal::Command includes = [] of String verbose = false check = false + tallies = false option_parser = parse_with_crystal_opts do |opts| opts.banner = "Usage: crystal #{command} [options] [programfile] [--] [arguments]\n\nOptions:" @@ -443,6 +445,10 @@ class Crystal::Command end if unreachable_command + opts.on("--tallies", "Print reachable methods and their call counts as well") do + tallies = true + end + opts.on("--check", "Exits with error if there is any unreachable code") do |f| check = true end @@ -613,7 +619,7 @@ class Crystal::Command combine_rpath = run && !no_codegen @config = CompilerConfig.new compiler, sources, output_filename, emit_base_filename, arguments, specified_output, hierarchy_exp, cursor_location, output_format.not_nil!, - combine_rpath, includes, excludes, verbose, check + combine_rpath, includes, excludes, verbose, check, tallies end private def gather_sources(filenames) diff --git a/src/compiler/crystal/tools/unreachable.cr b/src/compiler/crystal/tools/unreachable.cr index f89f90e4c37d..a8886fecf596 100644 --- a/src/compiler/crystal/tools/unreachable.cr +++ b/src/compiler/crystal/tools/unreachable.cr @@ -15,8 +15,8 @@ module Crystal unreachable.excludes.concat CrystalPath.default_paths.map { |path| ::Path[path].expand.to_posix.to_s } unreachable.excludes.concat config.excludes.map { |path| ::Path[path].expand.to_posix.to_s } - defs = unreachable.process(result) - defs.sort_by! do |a_def| + tallies = unreachable.process(result) + tallies.sort_by! do |a_def, _| location = a_def.location.not_nil! { location.filename.as(String), @@ -25,15 +25,15 @@ module Crystal } end - UnreachablePresenter.new(defs, format: config.output_format).to_s(STDOUT) + UnreachablePresenter.new(tallies, format: config.output_format, print_tallies: config.tallies).to_s(STDOUT) if config.check - exit 1 unless defs.empty? + exit 1 if tallies.any?(&.[1].zero?) end end end - record UnreachablePresenter, defs : Array(Def), format : String? do + record UnreachablePresenter, tallies : Array({Def, Int32}), format : String?, print_tallies : Bool do include JSON::Serializable def to_s(io) @@ -49,16 +49,19 @@ module Crystal def each(&) current_dir = Dir.current - defs.each do |a_def| + tallies.each do |a_def, count| + next unless print_tallies || count.zero? + location = a_def.location.not_nil! filename = ::Path[location.filename.as(String)].relative_to(current_dir).to_s location = Location.new(filename, location.line_number, location.column_number) - yield a_def, location + yield a_def, location, count end end def to_text(io) - each do |a_def, location| + each do |a_def, location, count| + io << count << "\t" if print_tallies io << location << "\t" io << a_def.short_reference << "\t" io << a_def.length << " lines" @@ -72,13 +75,14 @@ module Crystal def to_json(builder : JSON::Builder) builder.array do - each do |a_def, location| + each do |a_def, location, count| builder.object do builder.field "name", a_def.short_reference builder.field "location", location.to_s if lines = a_def.length builder.field "lines", lines end + builder.field "count", count if print_tallies if annotations = a_def.all_annotations builder.field "annotations", annotations.map(&.to_s) end @@ -89,9 +93,14 @@ module Crystal def to_csv(io) CSV.build(io) do |builder| - builder.row %w[name file line column length annotations] - each do |a_def, location| + builder.row do |row| + row << "count" if print_tallies + row.concat %w[name file line column length annotations] + end + + each do |a_def, location, count| builder.row do |row| + row << count if print_tallies row << a_def.short_reference row << location.filename row << location.line_number @@ -111,8 +120,8 @@ module Crystal # Then it traverses all types and their defs and reports those that are not # in `@used_def_locations` (and match the filter). class UnreachableVisitor < Visitor - @used_def_locations = Set(Location).new - @defs : Set(Def) = Set(Def).new.compare_by_identity + @used_def_locations = Hash(Location, Int32).new(0) + @tallies : Hash(Def, Int32) = Hash(Def, Int32).new.compare_by_identity @visited : Set(ASTNode) = Set(ASTNode).new.compare_by_identity property includes = [] of String @@ -130,14 +139,14 @@ module Crystal process_type(type.metaclass) if type.metaclass != type end - def process(result : Compiler::Result) : Array(Def) - @defs.clear + def process(result : Compiler::Result) : Array({Def, Int32}) + @tallies.clear result.node.accept(self) process_type(result.program) - @defs.to_a + @tallies.to_a end def visit(node) @@ -163,7 +172,7 @@ module Crystal node.target_defs.try &.each do |a_def| if (location = a_def.location) - @used_def_locations << location if interested_in(location) + @used_def_locations.update(location, &.+(1)) if interested_in(location) end if @visited.add?(a_def) @@ -199,11 +208,10 @@ module Crystal check_def(previous) if previous && !a_def.calls_previous_def? - return if @used_def_locations.includes?(a_def.location) - - check_def(previous) if previous && a_def.calls_previous_def? + tally = @used_def_locations[a_def.location] + @tallies[a_def] = tally - @defs << a_def + check_def(previous) if previous && a_def.calls_previous_def? && tally == 0 end private def interested_in(location) From a3bedf968c9c60092ed222686c8f1c5d63b43a3f Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Sat, 23 Dec 2023 16:50:26 +0800 Subject: [PATCH 007/105] Avoid double rounding in `Float#format` for nonnegative `decimal_place` (#14129) --- spec/std/humanize_spec.cr | 8 ++++++++ src/humanize.cr | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/spec/std/humanize_spec.cr b/spec/std/humanize_spec.cr index 841fde6cb2ba..c909417aca36 100644 --- a/spec/std/humanize_spec.cr +++ b/spec/std/humanize_spec.cr @@ -99,6 +99,14 @@ describe Number do assert_prints 1.9999998.format, "1.9999998" assert_prints 1111111.999999998.format, "1,111,111.999999998" end + + it "does not perform double rounding when decimal places are given" do + assert_prints 1.2345.format(decimal_places: 24), "1.234499999999999930722083" + assert_prints 1.2345.format(decimal_places: 65), "1.23449999999999993072208326339023187756538391113281250000000000000" + assert_prints 1.2345.format(decimal_places: 71), "1.23449999999999993072208326339023187756538391113281250000000000000000000" + assert_prints 1.2345.format(decimal_places: 83), "1.23449999999999993072208326339023187756538391113281250000000000000000000000000000000" + assert_prints 1.2345.format(decimal_places: 99), "1.234499999999999930722083263390231877565383911132812500000000000000000000000000000000000000000000000" + end end describe "#humanize" do diff --git a/src/humanize.cr b/src/humanize.cr index e0c69a37b3ad..bb285fe3a07d 100644 --- a/src/humanize.cr +++ b/src/humanize.cr @@ -20,7 +20,7 @@ struct Number def format(io : IO, separator = '.', delimiter = ',', decimal_places : Int? = nil, *, group : Int = 3, only_significant : Bool = false) : Nil number = self # TODO: Optimize implementation for Int - if decimal_places + if decimal_places && (decimal_places < 0 || !number.is_a?(Float)) number = number.round(decimal_places) end From 15010d39dd42bc2c10c2597ca19aac5fd0521898 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Sat, 23 Dec 2023 16:50:40 +0800 Subject: [PATCH 008/105] Add `ReferenceStorage` for manual allocation of references (#14106) Co-authored-by: Sijawusz Pur Rahnama <sija@sija.pl> --- .../semantic/reference_storage_spec.cr | 40 ++++++++++++++ spec/primitives/reference_spec.cr | 4 +- src/compiler/crystal/codegen/llvm_typer.cr | 4 ++ src/compiler/crystal/program.cr | 6 ++- src/compiler/crystal/types.cr | 28 +++++++++- src/prelude.cr | 1 + src/reference_storage.cr | 54 +++++++++++++++++++ 7 files changed, 132 insertions(+), 5 deletions(-) create mode 100644 spec/compiler/semantic/reference_storage_spec.cr create mode 100644 src/reference_storage.cr diff --git a/spec/compiler/semantic/reference_storage_spec.cr b/spec/compiler/semantic/reference_storage_spec.cr new file mode 100644 index 000000000000..791fed054275 --- /dev/null +++ b/spec/compiler/semantic/reference_storage_spec.cr @@ -0,0 +1,40 @@ +require "../../spec_helper" + +describe "Semantic: ReferenceStorage" do + it "errors if T is a struct type" do + assert_error <<-CRYSTAL, "Can't instantiate ReferenceStorage(T) with T = Foo (T must be a reference type)" + struct Foo + @x = 1 + end + + ReferenceStorage(Foo) + CRYSTAL + end + + it "errors if T is a value type" do + assert_error <<-CRYSTAL, "Can't instantiate ReferenceStorage(T) with T = Int32 (T must be a reference type)" + ReferenceStorage(Int32) + CRYSTAL + end + + it "errors if T is a union type" do + assert_error <<-CRYSTAL, "Can't instantiate ReferenceStorage(T) with T = (Bar | Foo) (T must be a reference type)" + class Foo + end + + class Bar + end + + ReferenceStorage(Foo | Bar) + CRYSTAL + end + + it "errors if T is a nilable type" do + assert_error <<-CRYSTAL, "Can't instantiate ReferenceStorage(T) with T = (Foo | Nil) (T must be a reference type)" + class Foo + end + + ReferenceStorage(Foo?) + CRYSTAL + end +end diff --git a/spec/primitives/reference_spec.cr b/spec/primitives/reference_spec.cr index b73553748b65..52f179296ee8 100644 --- a/spec/primitives/reference_spec.cr +++ b/spec/primitives/reference_spec.cr @@ -43,9 +43,7 @@ describe "Primitives: reference" do end it "works when address is on the stack" do - # suitably aligned, sufficient storage for type ID + i64 + ptr - # TODO: use `ReferenceStorage` instead - foo_buffer = uninitialized UInt64[3] + foo_buffer = uninitialized ReferenceStorage(Foo) foo = Foo.pre_initialize(pointerof(foo_buffer)) pointerof(foo_buffer).as(typeof(Foo.crystal_instance_type_id)*).value.should eq(Foo.crystal_instance_type_id) foo.str.should eq("abc") diff --git a/src/compiler/crystal/codegen/llvm_typer.cr b/src/compiler/crystal/codegen/llvm_typer.cr index d20fbd59fa9a..d72a25ecd3cb 100644 --- a/src/compiler/crystal/codegen/llvm_typer.cr +++ b/src/compiler/crystal/codegen/llvm_typer.cr @@ -245,6 +245,10 @@ module Crystal llvm_type(type.remove_alias, wants_size) end + private def create_llvm_type(type : ReferenceStorageType, wants_size) + llvm_struct_type(type.reference_type, wants_size) + end + private def create_llvm_type(type : NonGenericModuleType | GenericClassType, wants_size) # This can only be reached if the module or generic class don't have implementors @llvm_context.int1 diff --git a/src/compiler/crystal/program.cr b/src/compiler/crystal/program.cr index 936fc6a0a270..6d3d185774af 100644 --- a/src/compiler/crystal/program.cr +++ b/src/compiler/crystal/program.cr @@ -197,6 +197,10 @@ module Crystal types["Struct"] = struct_t = @struct_t = NonGenericClassType.new self, self, "Struct", value abstract_value_type(struct_t) + types["ReferenceStorage"] = @reference_storage = reference_storage = GenericReferenceStorageType.new self, self, "ReferenceStorage", value, ["T"] + reference_storage.declare_instance_var("@type_id", int32) + reference_storage.can_be_stored = false + types["Enumerable"] = @enumerable = GenericModuleType.new self, self, "Enumerable", ["T"] types["Indexable"] = @indexable = GenericModuleType.new self, self, "Indexable", ["T"] @@ -493,7 +497,7 @@ module Crystal {% for name in %w(object no_return value number reference void nil bool char int int8 int16 int32 int64 int128 uint8 uint16 uint32 uint64 uint128 float float32 float64 string symbol pointer enumerable indexable - array static_array exception tuple named_tuple proc union enum range regex crystal + array static_array reference_storage exception tuple named_tuple proc union enum range regex crystal packed_annotation thread_local_annotation no_inline_annotation always_inline_annotation naked_annotation returns_twice_annotation raises_annotation primitive_annotation call_convention_annotation diff --git a/src/compiler/crystal/types.cr b/src/compiler/crystal/types.cr index ad9f3d391fa6..64bcdda9a3d9 100644 --- a/src/compiler/crystal/types.cr +++ b/src/compiler/crystal/types.cr @@ -550,7 +550,7 @@ module Crystal def allows_instance_vars? case self when program.object, program.value, program.struct, - program.reference, program.class_type, + program.reference, program.class_type, program.reference_storage, program.number, program.int, program.float, program.tuple, program.named_tuple, program.pointer, program.static_array, @@ -2642,6 +2642,32 @@ module Crystal end end + # The non-instantiated ReferenceStorage(T) type. + class GenericReferenceStorageType < GenericClassType + @struct = true + + def new_generic_instance(program, generic_type, type_vars) + t = type_vars["T"].type + + unless t.is_a?(TypeParameter) || (t.class? && !t.struct?) + raise TypeException.new "Can't instantiate ReferenceStorage(T) with T = #{t} (T must be a reference type)" + end + + ReferenceStorageType.new program, t + end + end + + class ReferenceStorageType < GenericClassInstanceType + getter reference_type : Type + + def initialize(program, @reference_type) + t_var = Var.new("T", @reference_type) + t_var.bind_to t_var + + super(program, program.reference_storage, program.struct, {"T" => t_var} of String => ASTNode) + end + end + # A lib type, like `lib LibC`. class LibType < ModuleType getter link_annotations : Array(LinkAnnotation)? diff --git a/src/prelude.cr b/src/prelude.cr index f06f5bc87015..f84bb86cb3c1 100644 --- a/src/prelude.cr +++ b/src/prelude.cr @@ -65,6 +65,7 @@ require "raise" require "random" require "range" require "reference" +require "reference_storage" require "regex" require "set" {% unless flag?(:wasm32) %} diff --git a/src/reference_storage.cr b/src/reference_storage.cr new file mode 100644 index 000000000000..4f6e39a8cca0 --- /dev/null +++ b/src/reference_storage.cr @@ -0,0 +1,54 @@ +# a `ReferenceStorage(T)` provides the minimum storage for the instance data of +# an object of type `T`. The compiler guarantees that +# `sizeof(ReferenceStorage(T)) == instance_sizeof(T)` and +# `alignof(ReferenceStorage(T)) == instance_alignof(T)` always hold, which means +# `Pointer(ReferenceStorage(T))` and `T` are binary-compatible. +# +# `T` must be a non-union reference type. +# +# WARNING: `ReferenceStorage` is only necessary for manual memory management, +# such as creating instances of `T` with a non-default allocator. Therefore, +# this type is unsafe and no public constructors are defined. +# +# WARNING: `ReferenceStorage` is unsuitable when instances of `T` require more +# than `instance_sizeof(T)` bytes, such as `String` and `Log::Metadata`. +@[Experimental("This type's API is still under development. Join the discussion about custom reference allocation at [#13481](https://github.com/crystal-lang/crystal/issues/13481).")] +struct ReferenceStorage(T) + private def initialize + end + + # Returns whether `self` and *other* are bytewise equal. + # + # NOTE: This does not call `T#==`, so it works even if `self` or *other* does + # not represent a valid instance of `T`. If validity is guaranteed, call + # `to_reference == other.to_reference` instead to use `T#==`. + def ==(other : ReferenceStorage(T)) : Bool + to_bytes == other.to_bytes + end + + def ==(other) : Bool + false + end + + def hash(hasher) + to_bytes.hash(hasher) + end + + def to_s(io : IO) : Nil + io << "ReferenceStorage(#<" << T << ":0x" + pointerof(@type_id).address.to_s(io, 16) + io << ">)" + end + + # Returns a `T` whose instance data refers to `self`. + # + # WARNING: The caller is responsible for ensuring that the instance data is + # correctly initialized and outlives the returned `T`. + def to_reference : T + pointerof(@type_id).as(T) + end + + protected def to_bytes + Slice.new(pointerof(@type_id).as(UInt8*), instance_sizeof(T)) + end +end From 899ec69a2bc91169e871002063b37fcb6469cb65 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Sat, 23 Dec 2023 16:51:02 +0800 Subject: [PATCH 009/105] Support `dll` parameter in `@[Link]` (#14131) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Johannes Müller <straightshoota@gmail.com> --- spec/compiler/semantic/lib_spec.cr | 50 +++++++++++++++++++++++++- src/annotations.cr | 9 ++++- src/compiler/crystal/codegen/link.cr | 53 ++++++++++++++++++++++++++-- src/compiler/crystal/compiler.cr | 23 ++++++++++++ src/compiler/crystal/ffi/lib_ffi.cr | 3 ++ src/crystal/lib_iconv.cr | 3 ++ src/gc/boehm.cr | 3 ++ src/lib_z/lib_z.cr | 3 ++ src/llvm/lib_llvm.cr | 3 ++ src/openssl/lib_crypto.cr | 4 +++ src/openssl/lib_ssl.cr | 5 +++ src/regex/lib_pcre.cr | 3 ++ src/regex/lib_pcre2.cr | 3 ++ src/xml/libxml2.cr | 3 ++ src/yaml/lib_yaml.cr | 3 ++ 15 files changed, 166 insertions(+), 5 deletions(-) diff --git a/spec/compiler/semantic/lib_spec.cr b/spec/compiler/semantic/lib_spec.cr index 1ee3c7aa99c6..92526402177d 100644 --- a/spec/compiler/semantic/lib_spec.cr +++ b/spec/compiler/semantic/lib_spec.cr @@ -345,7 +345,55 @@ describe "Semantic: lib" do lib LibFoo end ), - "unknown link argument: 'boo' (valid arguments are 'lib', 'ldflags', 'static', 'pkg_config', 'framework', and 'wasm_import_module')" + "unknown link argument: 'boo' (valid arguments are 'lib', 'ldflags', 'static', 'pkg_config', 'framework', 'wasm_import_module', and 'dll')" + end + + it "allows dll argument" do + assert_no_errors <<-CRYSTAL + @[Link(dll: "foo.dll")] + lib LibFoo + end + CRYSTAL + + assert_no_errors <<-CRYSTAL + @[Link(dll: "BAR.DLL")] + lib LibFoo + end + CRYSTAL + end + + it "errors if dll argument contains directory separators" do + assert_error <<-CRYSTAL, "'dll' link argument must not include directory separators" + @[Link(dll: "foo/bar.dll")] + lib LibFoo + end + CRYSTAL + + assert_error <<-CRYSTAL, "'dll' link argument must not include directory separators" + @[Link(dll: %q(foo\\bar.dll))] + lib LibFoo + end + CRYSTAL + end + + it "errors if dll argument does not end with '.dll'" do + assert_error <<-CRYSTAL, "'dll' link argument must use a '.dll' file extension" + @[Link(dll: "foo")] + lib LibFoo + end + CRYSTAL + + assert_error <<-CRYSTAL, "'dll' link argument must use a '.dll' file extension" + @[Link(dll: "foo.dylib")] + lib LibFoo + end + CRYSTAL + + assert_error <<-CRYSTAL, "'dll' link argument must use a '.dll' file extension" + @[Link(dll: "")] + lib LibFoo + end + CRYSTAL end it "errors if lib already specified with positional argument" do diff --git a/src/annotations.cr b/src/annotations.cr index c906f61b9b79..929ed73533f9 100644 --- a/src/annotations.cr +++ b/src/annotations.cr @@ -27,7 +27,7 @@ end annotation Flags end -# A `lib` can be marked with `@[Link(lib : String, *, ldflags : String, framework : String, pkg_config : String)]` +# A `lib` can be marked with `@[Link(lib : String, *, ldflags : String, static : Bool, framework : String, pkg_config : String, wasm_import_module : String, dll : String)]` # to declare the library that should be linked when compiling the program. # # At least one of the *lib*, *ldflags*, *framework* arguments needs to be specified. @@ -45,6 +45,13 @@ end # # `@[Link(framework: "Cocoa")]` will pass `-framework Cocoa` to the linker. # +# `@[Link(dll: "gc.dll")]` will copy `gc.dll` to any built program. The DLL name +# must use `.dll` as its file extension and cannot contain any directory +# separators. The actual DLL is searched among `CRYSTAL_LIBRARY_PATH`, the +# compiler's own directory, and `PATH` in that order; a warning is printed if +# the DLL isn't found, although it might still run correctly if the DLLs are +# available in other DLL search paths on the system. +# # When an `-l` option is passed to the linker, it will lookup the libraries in # paths passed with the `-L` option. Any paths in `CRYSTAL_LIBRARY_PATH` are # added by default. Custom paths can be passed using `ldflags`: diff --git a/src/compiler/crystal/codegen/link.cr b/src/compiler/crystal/codegen/link.cr index 7ef2ab85f92c..cc703ec81eef 100644 --- a/src/compiler/crystal/codegen/link.cr +++ b/src/compiler/crystal/codegen/link.cr @@ -5,8 +5,9 @@ module Crystal getter ldflags : String? getter framework : String? getter wasm_import_module : String? + getter dll : String? - def initialize(@lib = nil, @pkg_config = @lib, @ldflags = nil, @static = false, @framework = nil, @wasm_import_module = nil) + def initialize(@lib = nil, @pkg_config = @lib, @ldflags = nil, @static = false, @framework = nil, @wasm_import_module = nil, @dll = nil) end def static? @@ -27,6 +28,7 @@ module Crystal lib_pkg_config = nil lib_framework = nil lib_wasm_import_module = nil + lib_dll = nil count = 0 args.each do |arg| @@ -76,12 +78,21 @@ module Crystal when "wasm_import_module" named_arg.raise "'wasm_import_module' link argument must be a String" unless value.is_a?(StringLiteral) lib_wasm_import_module = value.value + when "dll" + named_arg.raise "'dll' link argument must be a String" unless value.is_a?(StringLiteral) + lib_dll = value.value + unless lib_dll.size >= 4 && lib_dll[-4..].compare(".dll", case_insensitive: true) == 0 + named_arg.raise "'dll' link argument must use a '.dll' file extension" + end + if ::Path.separators(::Path::Kind::WINDOWS).any? { |separator| lib_dll.includes?(separator) } + named_arg.raise "'dll' link argument must not include directory separators" + end else - named_arg.raise "unknown link argument: '#{named_arg.name}' (valid arguments are 'lib', 'ldflags', 'static', 'pkg_config', 'framework', and 'wasm_import_module')" + named_arg.raise "unknown link argument: '#{named_arg.name}' (valid arguments are 'lib', 'ldflags', 'static', 'pkg_config', 'framework', 'wasm_import_module', and 'dll')" end end - new(lib_name, lib_pkg_config, lib_ldflags, lib_static, lib_framework, lib_wasm_import_module) + new(lib_name, lib_pkg_config, lib_ldflags, lib_static, lib_framework, lib_wasm_import_module, lib_dll) end end @@ -221,6 +232,42 @@ module Crystal flags.join(" ") end + def each_dll_path(& : String, Bool ->) + executable_path = nil + compiler_origin = nil + paths = nil + + link_annotations.each do |ann| + next unless dll = ann.dll + + dll_path = CrystalLibraryPath.paths.each do |path| + full_path = File.join(path, dll) + break full_path if File.file?(full_path) + end + + unless dll_path + executable_path ||= Process.executable_path + compiler_origin ||= File.dirname(executable_path) if executable_path + + if compiler_origin + full_path = File.join(compiler_origin, dll) + dll_path = full_path if File.file?(full_path) + end + end + + unless dll_path + paths ||= ENV["PATH"]?.try &.split(Process::PATH_DELIMITER, remove_empty: true) + + dll_path = paths.try &.each do |path| + full_path = File.join(path, dll) + break full_path if File.file?(full_path) + end + end + + yield dll_path || dll, !dll_path.nil? + end + end + PKG_CONFIG_PATH = Process.find_executable("pkg-config") # Returns the result of running `pkg-config mod` but returns nil if diff --git a/src/compiler/crystal/compiler.cr b/src/compiler/crystal/compiler.cr index 237783c2ed8c..283f44289468 100644 --- a/src/compiler/crystal/compiler.cr +++ b/src/compiler/crystal/compiler.cr @@ -321,6 +321,10 @@ module Crystal {% if flag?(:darwin) %} run_dsymutil(output_filename) unless debug.none? {% end %} + + {% if flag?(:windows) %} + copy_dlls(program, output_filename) if program.has_flag?("preview_dll") + {% end %} end CacheDir.instance.cleanup if @cleanup @@ -345,6 +349,25 @@ module Crystal end end + private def copy_dlls(program, output_filename) + not_found = nil + output_directory = File.dirname(output_filename) + + program.each_dll_path do |path, found| + if found + FileUtils.cp(path, output_directory) + else + not_found ||= [] of String + not_found << path + end + end + + if not_found + stderr << "Warning: The following DLLs are required at run time, but Crystal is unable to locate them in CRYSTAL_LIBRARY_PATH, the compiler's directory, or PATH: " + not_found.sort!.join(stderr, ", ") + end + end + private def cross_compile(program, units, output_filename) unit = units.first llvm_mod = unit.llvm_mod diff --git a/src/compiler/crystal/ffi/lib_ffi.cr b/src/compiler/crystal/ffi/lib_ffi.cr index 699a0c125468..97163c989ee5 100644 --- a/src/compiler/crystal/ffi/lib_ffi.cr +++ b/src/compiler/crystal/ffi/lib_ffi.cr @@ -1,5 +1,8 @@ module Crystal @[Link("ffi")] + {% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} + @[Link(dll: "libffi.dll")] + {% end %} lib LibFFI {% begin %} enum ABI diff --git a/src/crystal/lib_iconv.cr b/src/crystal/lib_iconv.cr index a180a770a67a..5f1506758454 100644 --- a/src/crystal/lib_iconv.cr +++ b/src/crystal/lib_iconv.cr @@ -5,6 +5,9 @@ require "c/stddef" {% end %} @[Link("iconv")] +{% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} + @[Link(dll: "libiconv.dll")] +{% end %} lib LibIconv type IconvT = Void* diff --git a/src/gc/boehm.cr b/src/gc/boehm.cr index b4dfb0061900..6c1ff5020cbf 100644 --- a/src/gc/boehm.cr +++ b/src/gc/boehm.cr @@ -25,6 +25,9 @@ @[Link("gc")] {% end %} +{% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} + @[Link(dll: "gc.dll")] +{% end %} lib LibGC alias Int = LibC::Int alias SizeT = LibC::SizeT diff --git a/src/lib_z/lib_z.cr b/src/lib_z/lib_z.cr index e261cde29683..1c88cb67bba8 100644 --- a/src/lib_z/lib_z.cr +++ b/src/lib_z/lib_z.cr @@ -1,4 +1,7 @@ @[Link("z")] +{% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} + @[Link(dll: "zlib1.dll")] +{% end %} lib LibZ alias Char = LibC::Char alias Int = LibC::Int diff --git a/src/llvm/lib_llvm.cr b/src/llvm/lib_llvm.cr index ee18eddfbce3..d5e7c2488002 100644 --- a/src/llvm/lib_llvm.cr +++ b/src/llvm/lib_llvm.cr @@ -15,6 +15,9 @@ {% llvm_ldflags = lines[2] %} @[Link("llvm")] + {% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} + @[Link(dll: "LLVM-C.dll")] + {% end %} lib LibLLVM end {% else %} diff --git a/src/openssl/lib_crypto.cr b/src/openssl/lib_crypto.cr index c783aa7903a9..caca9c11c520 100644 --- a/src/openssl/lib_crypto.cr +++ b/src/openssl/lib_crypto.cr @@ -36,6 +36,10 @@ {% else %} @[Link(ldflags: "`command -v pkg-config > /dev/null && pkg-config --libs --silence-errors libcrypto || printf %s '-lcrypto'`")] {% end %} +{% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} + # TODO: if someone brings their own OpenSSL 1.x.y on Windows, will this have a different name? + @[Link(dll: "libcrypto-3-x64.dll")] +{% end %} lib LibCrypto alias Char = LibC::Char alias Int = LibC::Int diff --git a/src/openssl/lib_ssl.cr b/src/openssl/lib_ssl.cr index 37a4cea3a161..27faf9bbe185 100644 --- a/src/openssl/lib_ssl.cr +++ b/src/openssl/lib_ssl.cr @@ -43,6 +43,11 @@ require "./lib_crypto" {% else %} @[Link(ldflags: "`command -v pkg-config > /dev/null && pkg-config --libs --silence-errors libssl || printf %s '-lssl -lcrypto'`")] {% end %} +{% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} + # TODO: if someone brings their own OpenSSL 1.x.y on Windows, will this have a different name? + @[Link(dll: "libssl-3-x64.dll")] + @[Link(dll: "libcrypto-3-x64.dll")] +{% end %} lib LibSSL alias Int = LibC::Int alias Char = LibC::Char diff --git a/src/regex/lib_pcre.cr b/src/regex/lib_pcre.cr index 5f110eba0ce7..647a172a9d43 100644 --- a/src/regex/lib_pcre.cr +++ b/src/regex/lib_pcre.cr @@ -1,4 +1,7 @@ @[Link("pcre")] +{% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} + @[Link(dll: "pcre.dll")] +{% end %} lib LibPCRE alias Int = LibC::Int diff --git a/src/regex/lib_pcre2.cr b/src/regex/lib_pcre2.cr index a04761cbe07e..71a0fd4b6639 100644 --- a/src/regex/lib_pcre2.cr +++ b/src/regex/lib_pcre2.cr @@ -1,4 +1,7 @@ @[Link("pcre2-8")] +{% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} + @[Link(dll: "pcre2-8.dll")] +{% end %} lib LibPCRE2 alias Int = LibC::Int diff --git a/src/xml/libxml2.cr b/src/xml/libxml2.cr index 68c9943425d2..3dff7fb6cb40 100644 --- a/src/xml/libxml2.cr +++ b/src/xml/libxml2.cr @@ -5,6 +5,9 @@ require "./html_parser_options" require "./save_options" @[Link("xml2", pkg_config: "libxml-2.0")] +{% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} + @[Link(dll: "libxml2.dll")] +{% end %} lib LibXML alias Int = LibC::Int diff --git a/src/yaml/lib_yaml.cr b/src/yaml/lib_yaml.cr index 4c0d329f8f36..0b4248afc793 100644 --- a/src/yaml/lib_yaml.cr +++ b/src/yaml/lib_yaml.cr @@ -1,6 +1,9 @@ require "./enums" @[Link("yaml", pkg_config: "yaml-0.1")] +{% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} + @[Link(dll: "yaml.dll")] +{% end %} lib LibYAML alias Int = LibC::Int From 16864334ab92a0e88942b67c68a19ad7a7703e07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Sun, 24 Dec 2023 10:41:15 +0100 Subject: [PATCH 010/105] Update shards 0.17.4 (#14133) --- .github/workflows/win_build_portable.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/win_build_portable.yml b/.github/workflows/win_build_portable.yml index 18eea4f1f317..21d849c2dcf0 100644 --- a/.github/workflows/win_build_portable.yml +++ b/.github/workflows/win_build_portable.yml @@ -120,7 +120,7 @@ jobs: uses: actions/checkout@v4 with: repository: crystal-lang/shards - ref: v0.17.3 + ref: v0.17.4 path: shards - name: Download molinillo release From af31a4e84869e53f1b2a906be4399884936fc1bd Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Sun, 24 Dec 2023 17:41:24 +0800 Subject: [PATCH 011/105] Simplify `String::Formatter` when Ryu Printf is available (#14132) --- spec/std/float_printer/ryu_printf_spec.cr | 3 +- spec/std/sprintf_spec.cr | 1452 +++++++++++---------- src/float/printer/ryu_printf.cr | 3 +- src/float/printer/ryu_printf_table.cr | 3 +- src/string/formatter.cr | 193 +-- 5 files changed, 838 insertions(+), 816 deletions(-) diff --git a/spec/std/float_printer/ryu_printf_spec.cr b/spec/std/float_printer/ryu_printf_spec.cr index 4610485f2270..02ac2944a37d 100644 --- a/spec/std/float_printer/ryu_printf_spec.cr +++ b/spec/std/float_printer/ryu_printf_spec.cr @@ -1,5 +1,4 @@ -# FIXME: this leads to an OOB on wasm32 (#13918) -{% skip_file if flag?(:wasm32) %} +{% skip_file unless String::Formatter::HAS_RYU_PRINTF %} # This file contains test cases derived from: # diff --git a/spec/std/sprintf_spec.cr b/spec/std/sprintf_spec.cr index d2da4369827b..67cc1ac1604c 100644 --- a/spec/std/sprintf_spec.cr +++ b/spec/std/sprintf_spec.cr @@ -378,798 +378,802 @@ describe "::sprintf" do assert_sprintf "1\u{0}%i\u{0}3", 2, "1\u00002\u00003" end - describe "floats" do - context "fixed format" do - it "works" do - assert_sprintf "%f", 123, "123.000000" - - assert_sprintf "%12f", 123.45, " 123.450000" - assert_sprintf "%-12f", 123.45, "123.450000 " - assert_sprintf "% f", 123.45, " 123.450000" - assert_sprintf "%+f", 123, "+123.000000" - assert_sprintf "%012f", 123, "00123.000000" - assert_sprintf "%.f", 1234.56, "1235" - assert_sprintf "%.2f", 1234.5678, "1234.57" - assert_sprintf "%10.2f", 1234.5678, " 1234.57" - assert_sprintf "%*.2f", [10, 1234.5678], " 1234.57" - assert_sprintf "%*.*f", [10, 2, 1234.5678], " 1234.57" - assert_sprintf "%.2f", 2.536_f32, "2.54" - assert_sprintf "%+0*.*f", [10, 2, 2.536_f32], "+000002.54" - assert_sprintf "%#.0f", 1234.56, "1235." - assert_sprintf "%#.1f", 1234.56, "1234.6" - - expect_raises(ArgumentError, "Expected dynamic value '*' to be an Int - \"not a number\" (String)") do - sprintf("%*f", ["not a number", 2.536_f32]) + if String::Formatter::HAS_RYU_PRINTF + describe "floats" do + context "fixed format" do + it "works" do + assert_sprintf "%f", 123, "123.000000" + + assert_sprintf "%12f", 123.45, " 123.450000" + assert_sprintf "%-12f", 123.45, "123.450000 " + assert_sprintf "% f", 123.45, " 123.450000" + assert_sprintf "%+f", 123, "+123.000000" + assert_sprintf "%012f", 123, "00123.000000" + assert_sprintf "%.f", 1234.56, "1235" + assert_sprintf "%.2f", 1234.5678, "1234.57" + assert_sprintf "%10.2f", 1234.5678, " 1234.57" + assert_sprintf "%*.2f", [10, 1234.5678], " 1234.57" + assert_sprintf "%*.*f", [10, 2, 1234.5678], " 1234.57" + assert_sprintf "%.2f", 2.536_f32, "2.54" + assert_sprintf "%+0*.*f", [10, 2, 2.536_f32], "+000002.54" + assert_sprintf "%#.0f", 1234.56, "1235." + assert_sprintf "%#.1f", 1234.56, "1234.6" + + expect_raises(ArgumentError, "Expected dynamic value '*' to be an Int - \"not a number\" (String)") do + sprintf("%*f", ["not a number", 2.536_f32]) + end + + assert_sprintf "%12.2f %12.2f %6.2f %.2f", [2.0, 3.0, 4.0, 5.0], " 2.00 3.00 4.00 5.00" + + assert_sprintf "%f", 1e15, "1000000000000000.000000" end - - assert_sprintf "%12.2f %12.2f %6.2f %.2f", [2.0, 3.0, 4.0, 5.0], " 2.00 3.00 4.00 5.00" - - assert_sprintf "%f", 1e15, "1000000000000000.000000" - end - end - - context "scientific format" do - it "works" do - assert_sprintf "%e", 123.45, "1.234500e+2" - assert_sprintf "%E", 123.45, "1.234500E+2" - - assert_sprintf "%e", Float64::MAX, "1.797693e+308" - assert_sprintf "%e", Float64::MIN_POSITIVE, "2.225074e-308" - assert_sprintf "%e", Float64::MIN_SUBNORMAL, "4.940656e-324" - assert_sprintf "%e", 0.0, "0.000000e+0" - assert_sprintf "%e", -0.0, "-0.000000e+0" - assert_sprintf "%e", -Float64::MIN_SUBNORMAL, "-4.940656e-324" - assert_sprintf "%e", -Float64::MIN_POSITIVE, "-2.225074e-308" - assert_sprintf "%e", Float64::MIN, "-1.797693e+308" end - context "width specifier" do - it "sets the minimum length of the string" do - assert_sprintf "%20e", 123.45, " 1.234500e+2" - assert_sprintf "%20e", -123.45, " -1.234500e+2" - assert_sprintf "%+20e", 123.45, " +1.234500e+2" - - assert_sprintf "%12e", 123.45, " 1.234500e+2" - assert_sprintf "%12e", -123.45, "-1.234500e+2" - assert_sprintf "%+12e", 123.45, "+1.234500e+2" - - assert_sprintf "%11e", 123.45, "1.234500e+2" - assert_sprintf "%11e", -123.45, "-1.234500e+2" - assert_sprintf "%+11e", 123.45, "+1.234500e+2" - - assert_sprintf "%2e", 123.45, "1.234500e+2" - assert_sprintf "%2e", -123.45, "-1.234500e+2" - assert_sprintf "%+2e", 123.45, "+1.234500e+2" + context "scientific format" do + it "works" do + assert_sprintf "%e", 123.45, "1.234500e+2" + assert_sprintf "%E", 123.45, "1.234500E+2" + + assert_sprintf "%e", Float64::MAX, "1.797693e+308" + assert_sprintf "%e", Float64::MIN_POSITIVE, "2.225074e-308" + assert_sprintf "%e", Float64::MIN_SUBNORMAL, "4.940656e-324" + assert_sprintf "%e", 0.0, "0.000000e+0" + assert_sprintf "%e", -0.0, "-0.000000e+0" + assert_sprintf "%e", -Float64::MIN_SUBNORMAL, "-4.940656e-324" + assert_sprintf "%e", -Float64::MIN_POSITIVE, "-2.225074e-308" + assert_sprintf "%e", Float64::MIN, "-1.797693e+308" end - it "left-justifies on negative width" do - assert_sprintf "%*e", [-20, 123.45], "1.234500e+2 " - end - end + context "width specifier" do + it "sets the minimum length of the string" do + assert_sprintf "%20e", 123.45, " 1.234500e+2" + assert_sprintf "%20e", -123.45, " -1.234500e+2" + assert_sprintf "%+20e", 123.45, " +1.234500e+2" - context "precision specifier" do - it "sets the minimum length of the fractional part" do - assert_sprintf "%.0e", 2.0, "2e+0" - assert_sprintf "%.0e", 2.5.prev_float, "2e+0" - assert_sprintf "%.0e", 2.5, "2e+0" - assert_sprintf "%.0e", 2.5.next_float, "3e+0" - assert_sprintf "%.0e", 3.0, "3e+0" - assert_sprintf "%.0e", 3.5.prev_float, "3e+0" - assert_sprintf "%.0e", 3.5, "4e+0" - assert_sprintf "%.0e", 3.5.next_float, "4e+0" - assert_sprintf "%.0e", 4.0, "4e+0" - - assert_sprintf "%.0e", 9.5, "1e+1" - - assert_sprintf "%.100e", 1.1, "1.1000000000000000888178419700125232338905334472656250000000000000000000000000000000000000000000000000e+0" - - assert_sprintf "%.10000e", 1.0, "1.#{"0" * 10000}e+0" - - assert_sprintf "%.1000e", Float64::MIN_POSITIVE.prev_float, - "2.2250738585072008890245868760858598876504231122409594654935248025624400092282356951" \ - "787758888037591552642309780950434312085877387158357291821993020294379224223559819827" \ - "501242041788969571311791082261043971979604000454897391938079198936081525613113376149" \ - "842043271751033627391549782731594143828136275113838604094249464942286316695429105080" \ - "201815926642134996606517803095075913058719846423906068637102005108723282784678843631" \ - "944515866135041223479014792369585208321597621066375401613736583044193603714778355306" \ - "682834535634005074073040135602968046375918583163124224521599262546494300836851861719" \ - "422417646455137135420132217031370496583210154654068035397417906022589503023501937519" \ - "773030945763173210852507299305089761582519159720757232455434770912461317493580281734" \ - "466552734375000000000000000000000000000000000000000000000000000000000000000000000000" \ - "000000000000000000000000000000000000000000000000000000000000000000000000000000000000" \ - "000000000000000000000000000000000000000000000000000000000000000000000000000000e-308" - end + assert_sprintf "%12e", 123.45, " 1.234500e+2" + assert_sprintf "%12e", -123.45, "-1.234500e+2" + assert_sprintf "%+12e", 123.45, "+1.234500e+2" - it "can be used with width" do - assert_sprintf "%20.12e", 123.45, " 1.234500000000e+2" - assert_sprintf "%20.12e", -123.45, " -1.234500000000e+2" - assert_sprintf "%20.12e", 0.0, " 0.000000000000e+0" + assert_sprintf "%11e", 123.45, "1.234500e+2" + assert_sprintf "%11e", -123.45, "-1.234500e+2" + assert_sprintf "%+11e", 123.45, "+1.234500e+2" - assert_sprintf "%-20.12e", 123.45, "1.234500000000e+2 " - assert_sprintf "%-20.12e", -123.45, "-1.234500000000e+2 " - assert_sprintf "%-20.12e", 0.0, "0.000000000000e+0 " - - assert_sprintf "%8.12e", 123.45, "1.234500000000e+2" - assert_sprintf "%8.12e", -123.45, "-1.234500000000e+2" - assert_sprintf "%8.12e", 0.0, "0.000000000000e+0" - end - - it "is ignored if precision argument is negative" do - assert_sprintf "%.*e", [-2, 123.45], "1.234500e+2" - end - end - - context "sharp flag" do - it "prints a decimal point even if no digits follow" do - assert_sprintf "%#.0e", 1.0, "1.e+0" - assert_sprintf "%#.0e", 10000.0, "1.e+4" - assert_sprintf "%#.0e", 1.0e+23, "1.e+23" - assert_sprintf "%#.0e", 1.0e-100, "1.e-100" - assert_sprintf "%#.0e", 0.0, "0.e+0" - assert_sprintf "%#.0e", -0.0, "-0.e+0" - end - end - - context "plus flag" do - it "writes a plus sign for positive values" do - assert_sprintf "%+e", 123.45, "+1.234500e+2" - assert_sprintf "%+e", -123.45, "-1.234500e+2" - assert_sprintf "%+e", 0.0, "+0.000000e+0" - end - - it "writes plus sign after left space-padding" do - assert_sprintf "%+20e", 123.45, " +1.234500e+2" - assert_sprintf "%+20e", -123.45, " -1.234500e+2" - assert_sprintf "%+20e", 0.0, " +0.000000e+0" - end - - it "writes plus sign before left zero-padding" do - assert_sprintf "%+020e", 123.45, "+000000001.234500e+2" - assert_sprintf "%+020e", -123.45, "-000000001.234500e+2" - assert_sprintf "%+020e", 0.0, "+000000000.000000e+0" - end - end - - context "space flag" do - it "writes a space for positive values" do - assert_sprintf "% e", 123.45, " 1.234500e+2" - assert_sprintf "% e", -123.45, "-1.234500e+2" - assert_sprintf "% e", 0.0, " 0.000000e+0" - end - - it "writes space before left space-padding" do - assert_sprintf "% 20e", 123.45, " 1.234500e+2" - assert_sprintf "% 20e", -123.45, " -1.234500e+2" - assert_sprintf "% 20e", 0.0, " 0.000000e+0" - - assert_sprintf "% 020e", 123.45, " 000000001.234500e+2" - assert_sprintf "% 020e", -123.45, "-000000001.234500e+2" - assert_sprintf "% 020e", 0.0, " 000000000.000000e+0" - end - - it "is ignored if plus flag is also specified" do - assert_sprintf "% +e", 123.45, "+1.234500e+2" - assert_sprintf "%+ e", -123.45, "-1.234500e+2" - end - end - - context "zero flag" do - it "left-pads the result with zeros" do - assert_sprintf "%020e", 123.45, "0000000001.234500e+2" - assert_sprintf "%020e", -123.45, "-000000001.234500e+2" - assert_sprintf "%020e", 0.0, "0000000000.000000e+0" - end - - it "is ignored if string is left-justified" do - assert_sprintf "%-020e", 123.45, "1.234500e+2 " - assert_sprintf "%-020e", -123.45, "-1.234500e+2 " - assert_sprintf "%-020e", 0.0, "0.000000e+0 " - end - - it "can be used with precision" do - assert_sprintf "%020.12e", 123.45, "0001.234500000000e+2" - assert_sprintf "%020.12e", -123.45, "-001.234500000000e+2" - assert_sprintf "%020.12e", 0.0, "0000.000000000000e+0" - end - end + assert_sprintf "%2e", 123.45, "1.234500e+2" + assert_sprintf "%2e", -123.45, "-1.234500e+2" + assert_sprintf "%+2e", 123.45, "+1.234500e+2" + end - context "minus flag" do - it "left-justifies the string" do - assert_sprintf "%-20e", 123.45, "1.234500e+2 " - assert_sprintf "%-20e", -123.45, "-1.234500e+2 " - assert_sprintf "%-20e", 0.0, "0.000000e+0 " + it "left-justifies on negative width" do + assert_sprintf "%*e", [-20, 123.45], "1.234500e+2 " + end end - end - end - - context "general format" do - it "works" do - assert_sprintf "%g", 123.45, "123.45" - assert_sprintf "%G", 123.45, "123.45" - - assert_sprintf "%g", 1.2345e-5, "1.2345e-5" - assert_sprintf "%G", 1.2345e-5, "1.2345E-5" - - assert_sprintf "%g", 1.2345e+25, "1.2345e+25" - assert_sprintf "%G", 1.2345e+25, "1.2345E+25" - - assert_sprintf "%g", Float64::MAX, "1.79769e+308" - assert_sprintf "%g", Float64::MIN_POSITIVE, "2.22507e-308" - assert_sprintf "%g", Float64::MIN_SUBNORMAL, "4.94066e-324" - assert_sprintf "%g", 0.0, "0" - assert_sprintf "%g", -0.0, "-0" - assert_sprintf "%g", -Float64::MIN_SUBNORMAL, "-4.94066e-324" - assert_sprintf "%g", -Float64::MIN_POSITIVE, "-2.22507e-308" - assert_sprintf "%g", Float64::MIN, "-1.79769e+308" - end - - context "width specifier" do - it "sets the minimum length of the string" do - assert_sprintf "%10g", 123.45, " 123.45" - assert_sprintf "%10g", -123.45, " -123.45" - assert_sprintf "%+10g", 123.45, " +123.45" - - assert_sprintf "%7g", 123.45, " 123.45" - assert_sprintf "%7g", -123.45, "-123.45" - assert_sprintf "%+7g", 123.45, "+123.45" - assert_sprintf "%6g", 123.45, "123.45" - assert_sprintf "%6g", -123.45, "-123.45" - assert_sprintf "%+6g", 123.45, "+123.45" - - assert_sprintf "%2g", 123.45, "123.45" - assert_sprintf "%2g", -123.45, "-123.45" - assert_sprintf "%+2g", 123.45, "+123.45" + context "precision specifier" do + it "sets the minimum length of the fractional part" do + assert_sprintf "%.0e", 2.0, "2e+0" + assert_sprintf "%.0e", 2.5.prev_float, "2e+0" + assert_sprintf "%.0e", 2.5, "2e+0" + assert_sprintf "%.0e", 2.5.next_float, "3e+0" + assert_sprintf "%.0e", 3.0, "3e+0" + assert_sprintf "%.0e", 3.5.prev_float, "3e+0" + assert_sprintf "%.0e", 3.5, "4e+0" + assert_sprintf "%.0e", 3.5.next_float, "4e+0" + assert_sprintf "%.0e", 4.0, "4e+0" + + assert_sprintf "%.0e", 9.5, "1e+1" + + assert_sprintf "%.100e", 1.1, "1.1000000000000000888178419700125232338905334472656250000000000000000000000000000000000000000000000000e+0" + + assert_sprintf "%.10000e", 1.0, "1.#{"0" * 10000}e+0" + + assert_sprintf "%.1000e", Float64::MIN_POSITIVE.prev_float, + "2.2250738585072008890245868760858598876504231122409594654935248025624400092282356951" \ + "787758888037591552642309780950434312085877387158357291821993020294379224223559819827" \ + "501242041788969571311791082261043971979604000454897391938079198936081525613113376149" \ + "842043271751033627391549782731594143828136275113838604094249464942286316695429105080" \ + "201815926642134996606517803095075913058719846423906068637102005108723282784678843631" \ + "944515866135041223479014792369585208321597621066375401613736583044193603714778355306" \ + "682834535634005074073040135602968046375918583163124224521599262546494300836851861719" \ + "422417646455137135420132217031370496583210154654068035397417906022589503023501937519" \ + "773030945763173210852507299305089761582519159720757232455434770912461317493580281734" \ + "466552734375000000000000000000000000000000000000000000000000000000000000000000000000" \ + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000" \ + "000000000000000000000000000000000000000000000000000000000000000000000000000000e-308" + end + + it "can be used with width" do + assert_sprintf "%20.12e", 123.45, " 1.234500000000e+2" + assert_sprintf "%20.12e", -123.45, " -1.234500000000e+2" + assert_sprintf "%20.12e", 0.0, " 0.000000000000e+0" + + assert_sprintf "%-20.12e", 123.45, "1.234500000000e+2 " + assert_sprintf "%-20.12e", -123.45, "-1.234500000000e+2 " + assert_sprintf "%-20.12e", 0.0, "0.000000000000e+0 " + + assert_sprintf "%8.12e", 123.45, "1.234500000000e+2" + assert_sprintf "%8.12e", -123.45, "-1.234500000000e+2" + assert_sprintf "%8.12e", 0.0, "0.000000000000e+0" + end + + it "is ignored if precision argument is negative" do + assert_sprintf "%.*e", [-2, 123.45], "1.234500e+2" + end end - it "left-justifies on negative width" do - assert_sprintf "%*g", [-10, 123.45], "123.45 " + context "sharp flag" do + it "prints a decimal point even if no digits follow" do + assert_sprintf "%#.0e", 1.0, "1.e+0" + assert_sprintf "%#.0e", 10000.0, "1.e+4" + assert_sprintf "%#.0e", 1.0e+23, "1.e+23" + assert_sprintf "%#.0e", 1.0e-100, "1.e-100" + assert_sprintf "%#.0e", 0.0, "0.e+0" + assert_sprintf "%#.0e", -0.0, "-0.e+0" + end end - end - context "precision specifier" do - it "sets the precision of the value" do - assert_sprintf "%.0g", 123.45, "1e+2" - assert_sprintf "%.1g", 123.45, "1e+2" - assert_sprintf "%.2g", 123.45, "1.2e+2" - assert_sprintf "%.3g", 123.45, "123" - assert_sprintf "%.4g", 123.45, "123.5" - assert_sprintf "%.5g", 123.45, "123.45" - assert_sprintf "%.6g", 123.45, "123.45" - assert_sprintf "%.7g", 123.45, "123.45" - assert_sprintf "%.8g", 123.45, "123.45" - - assert_sprintf "%.1000g", 123.45, "123.4500000000000028421709430404007434844970703125" - - assert_sprintf "%.0g", 1.23e-45, "1e-45" - assert_sprintf "%.1g", 1.23e-45, "1e-45" - assert_sprintf "%.2g", 1.23e-45, "1.2e-45" - assert_sprintf "%.3g", 1.23e-45, "1.23e-45" - assert_sprintf "%.4g", 1.23e-45, "1.23e-45" - assert_sprintf "%.5g", 1.23e-45, "1.23e-45" - assert_sprintf "%.6g", 1.23e-45, "1.23e-45" - - assert_sprintf "%.1000g", 1e-5, "1.0000000000000000818030539140313095458623138256371021270751953125e-5" + context "plus flag" do + it "writes a plus sign for positive values" do + assert_sprintf "%+e", 123.45, "+1.234500e+2" + assert_sprintf "%+e", -123.45, "-1.234500e+2" + assert_sprintf "%+e", 0.0, "+0.000000e+0" + end + + it "writes plus sign after left space-padding" do + assert_sprintf "%+20e", 123.45, " +1.234500e+2" + assert_sprintf "%+20e", -123.45, " -1.234500e+2" + assert_sprintf "%+20e", 0.0, " +0.000000e+0" + end + + it "writes plus sign before left zero-padding" do + assert_sprintf "%+020e", 123.45, "+000000001.234500e+2" + assert_sprintf "%+020e", -123.45, "-000000001.234500e+2" + assert_sprintf "%+020e", 0.0, "+000000000.000000e+0" + end end - it "can be used with width" do - assert_sprintf "%10.1g", 123.45, " 1e+2" - assert_sprintf "%10.2g", 123.45, " 1.2e+2" - assert_sprintf "%10.3g", 123.45, " 123" - assert_sprintf "%10.4g", 123.45, " 123.5" - assert_sprintf "%10.5g", 123.45, " 123.45" - assert_sprintf "%10.1g", -123.45, " -1e+2" - assert_sprintf "%10.2g", -123.45, " -1.2e+2" - assert_sprintf "%10.3g", -123.45, " -123" - assert_sprintf "%10.4g", -123.45, " -123.5" - assert_sprintf "%10.5g", -123.45, " -123.45" - assert_sprintf "%10.5g", 0, " 0" - - assert_sprintf "%-10.1g", 123.45, "1e+2 " - assert_sprintf "%-10.2g", 123.45, "1.2e+2 " - assert_sprintf "%-10.3g", 123.45, "123 " - assert_sprintf "%-10.4g", 123.45, "123.5 " - assert_sprintf "%-10.5g", 123.45, "123.45 " - assert_sprintf "%-10.1g", -123.45, "-1e+2 " - assert_sprintf "%-10.2g", -123.45, "-1.2e+2 " - assert_sprintf "%-10.3g", -123.45, "-123 " - assert_sprintf "%-10.4g", -123.45, "-123.5 " - assert_sprintf "%-10.5g", -123.45, "-123.45 " - assert_sprintf "%-10.5g", 0, "0 " - - assert_sprintf "%3.1g", 123.45, "1e+2" - assert_sprintf "%3.2g", 123.45, "1.2e+2" - assert_sprintf "%3.3g", 123.45, "123" - assert_sprintf "%3.4g", 123.45, "123.5" - assert_sprintf "%3.5g", 123.45, "123.45" - assert_sprintf "%3.1g", -123.45, "-1e+2" - assert_sprintf "%3.2g", -123.45, "-1.2e+2" - assert_sprintf "%3.3g", -123.45, "-123" - assert_sprintf "%3.4g", -123.45, "-123.5" - assert_sprintf "%3.5g", -123.45, "-123.45" - - assert_sprintf "%1000.800g", 123.45, "#{" " * 950}123.4500000000000028421709430404007434844970703125" + context "space flag" do + it "writes a space for positive values" do + assert_sprintf "% e", 123.45, " 1.234500e+2" + assert_sprintf "% e", -123.45, "-1.234500e+2" + assert_sprintf "% e", 0.0, " 0.000000e+0" + end + + it "writes space before left space-padding" do + assert_sprintf "% 20e", 123.45, " 1.234500e+2" + assert_sprintf "% 20e", -123.45, " -1.234500e+2" + assert_sprintf "% 20e", 0.0, " 0.000000e+0" + + assert_sprintf "% 020e", 123.45, " 000000001.234500e+2" + assert_sprintf "% 020e", -123.45, "-000000001.234500e+2" + assert_sprintf "% 020e", 0.0, " 000000000.000000e+0" + end + + it "is ignored if plus flag is also specified" do + assert_sprintf "% +e", 123.45, "+1.234500e+2" + assert_sprintf "%+ e", -123.45, "-1.234500e+2" + end end - it "is ignored if precision argument is negative" do - assert_sprintf "%.*g", [-2, 123.45], "123.45" + context "zero flag" do + it "left-pads the result with zeros" do + assert_sprintf "%020e", 123.45, "0000000001.234500e+2" + assert_sprintf "%020e", -123.45, "-000000001.234500e+2" + assert_sprintf "%020e", 0.0, "0000000000.000000e+0" + end + + it "is ignored if string is left-justified" do + assert_sprintf "%-020e", 123.45, "1.234500e+2 " + assert_sprintf "%-020e", -123.45, "-1.234500e+2 " + assert_sprintf "%-020e", 0.0, "0.000000e+0 " + end + + it "can be used with precision" do + assert_sprintf "%020.12e", 123.45, "0001.234500000000e+2" + assert_sprintf "%020.12e", -123.45, "-001.234500000000e+2" + assert_sprintf "%020.12e", 0.0, "0000.000000000000e+0" + end end - end - context "sharp flag" do - it "prints decimal point and trailing zeros" do - assert_sprintf "%#.0g", 12345, "1.e+4" - assert_sprintf "%#.6g", 12345, "12345.0" - assert_sprintf "%#.10g", 12345, "12345.00000" - assert_sprintf "%#.100g", 12345, "12345.#{"0" * 95}" - assert_sprintf "%#.1000g", 12345, "12345.#{"0" * 995}" - - assert_sprintf "%#.0g", 1e-5, "1.e-5" - assert_sprintf "%#.6g", 1e-5, "1.00000e-5" - assert_sprintf "%#.10g", 1e-5, "1.000000000e-5" - assert_sprintf "%#.100g", 1e-5, "1.0000000000000000818030539140313095458623138256371021270751953125#{"0" * 35}e-5" - assert_sprintf "%#.1000g", 1e-5, "1.0000000000000000818030539140313095458623138256371021270751953125#{"0" * 935}e-5" - - assert_sprintf "%#15.0g", 12345, " 1.e+4" - assert_sprintf "%#15.6g", 12345, " 12345.0" - assert_sprintf "%#15.10g", 12345, " 12345.00000" + context "minus flag" do + it "left-justifies the string" do + assert_sprintf "%-20e", 123.45, "1.234500e+2 " + assert_sprintf "%-20e", -123.45, "-1.234500e+2 " + assert_sprintf "%-20e", 0.0, "0.000000e+0 " + end end end - context "plus flag" do - it "writes a plus sign for positive values" do - assert_sprintf "%+g", 123.45, "+123.45" - assert_sprintf "%+g", -123.45, "-123.45" - assert_sprintf "%+g", 0.0, "+0" + context "general format" do + it "works" do + assert_sprintf "%g", 123.45, "123.45" + assert_sprintf "%G", 123.45, "123.45" + + assert_sprintf "%g", 1.2345e-5, "1.2345e-5" + assert_sprintf "%G", 1.2345e-5, "1.2345E-5" + + assert_sprintf "%g", 1.2345e+25, "1.2345e+25" + assert_sprintf "%G", 1.2345e+25, "1.2345E+25" + + assert_sprintf "%g", Float64::MAX, "1.79769e+308" + assert_sprintf "%g", Float64::MIN_POSITIVE, "2.22507e-308" + assert_sprintf "%g", Float64::MIN_SUBNORMAL, "4.94066e-324" + assert_sprintf "%g", 0.0, "0" + assert_sprintf "%g", -0.0, "-0" + assert_sprintf "%g", -Float64::MIN_SUBNORMAL, "-4.94066e-324" + assert_sprintf "%g", -Float64::MIN_POSITIVE, "-2.22507e-308" + assert_sprintf "%g", Float64::MIN, "-1.79769e+308" end - it "writes plus sign after left space-padding" do - assert_sprintf "%+10g", 123.45, " +123.45" - assert_sprintf "%+10g", -123.45, " -123.45" - assert_sprintf "%+10g", 0.0, " +0" - end + context "width specifier" do + it "sets the minimum length of the string" do + assert_sprintf "%10g", 123.45, " 123.45" + assert_sprintf "%10g", -123.45, " -123.45" + assert_sprintf "%+10g", 123.45, " +123.45" - it "writes plus sign before left zero-padding" do - assert_sprintf "%+010g", 123.45, "+000123.45" - assert_sprintf "%+010g", -123.45, "-000123.45" - assert_sprintf "%+010g", 0.0, "+000000000" - end - end + assert_sprintf "%7g", 123.45, " 123.45" + assert_sprintf "%7g", -123.45, "-123.45" + assert_sprintf "%+7g", 123.45, "+123.45" - context "space flag" do - it "writes a space for positive values" do - assert_sprintf "% g", 123.45, " 123.45" - assert_sprintf "% g", -123.45, "-123.45" - assert_sprintf "% g", 0.0, " 0" - end + assert_sprintf "%6g", 123.45, "123.45" + assert_sprintf "%6g", -123.45, "-123.45" + assert_sprintf "%+6g", 123.45, "+123.45" - it "writes space before left space-padding" do - assert_sprintf "% 10g", 123.45, " 123.45" - assert_sprintf "% 10g", -123.45, " -123.45" - assert_sprintf "% 10g", 0.0, " 0" + assert_sprintf "%2g", 123.45, "123.45" + assert_sprintf "%2g", -123.45, "-123.45" + assert_sprintf "%+2g", 123.45, "+123.45" + end - assert_sprintf "% 010g", 123.45, " 000123.45" - assert_sprintf "% 010g", -123.45, "-000123.45" - assert_sprintf "% 010g", 0.0, " 000000000" + it "left-justifies on negative width" do + assert_sprintf "%*g", [-10, 123.45], "123.45 " + end end - it "is ignored if plus flag is also specified" do - assert_sprintf "% +g", 123.45, "+123.45" - assert_sprintf "%+ g", -123.45, "-123.45" + context "precision specifier" do + it "sets the precision of the value" do + assert_sprintf "%.0g", 123.45, "1e+2" + assert_sprintf "%.1g", 123.45, "1e+2" + assert_sprintf "%.2g", 123.45, "1.2e+2" + assert_sprintf "%.3g", 123.45, "123" + assert_sprintf "%.4g", 123.45, "123.5" + assert_sprintf "%.5g", 123.45, "123.45" + assert_sprintf "%.6g", 123.45, "123.45" + assert_sprintf "%.7g", 123.45, "123.45" + assert_sprintf "%.8g", 123.45, "123.45" + + assert_sprintf "%.1000g", 123.45, "123.4500000000000028421709430404007434844970703125" + + assert_sprintf "%.0g", 1.23e-45, "1e-45" + assert_sprintf "%.1g", 1.23e-45, "1e-45" + assert_sprintf "%.2g", 1.23e-45, "1.2e-45" + assert_sprintf "%.3g", 1.23e-45, "1.23e-45" + assert_sprintf "%.4g", 1.23e-45, "1.23e-45" + assert_sprintf "%.5g", 1.23e-45, "1.23e-45" + assert_sprintf "%.6g", 1.23e-45, "1.23e-45" + + assert_sprintf "%.1000g", 1e-5, "1.0000000000000000818030539140313095458623138256371021270751953125e-5" + end + + it "can be used with width" do + assert_sprintf "%10.1g", 123.45, " 1e+2" + assert_sprintf "%10.2g", 123.45, " 1.2e+2" + assert_sprintf "%10.3g", 123.45, " 123" + assert_sprintf "%10.4g", 123.45, " 123.5" + assert_sprintf "%10.5g", 123.45, " 123.45" + assert_sprintf "%10.1g", -123.45, " -1e+2" + assert_sprintf "%10.2g", -123.45, " -1.2e+2" + assert_sprintf "%10.3g", -123.45, " -123" + assert_sprintf "%10.4g", -123.45, " -123.5" + assert_sprintf "%10.5g", -123.45, " -123.45" + assert_sprintf "%10.5g", 0, " 0" + + assert_sprintf "%-10.1g", 123.45, "1e+2 " + assert_sprintf "%-10.2g", 123.45, "1.2e+2 " + assert_sprintf "%-10.3g", 123.45, "123 " + assert_sprintf "%-10.4g", 123.45, "123.5 " + assert_sprintf "%-10.5g", 123.45, "123.45 " + assert_sprintf "%-10.1g", -123.45, "-1e+2 " + assert_sprintf "%-10.2g", -123.45, "-1.2e+2 " + assert_sprintf "%-10.3g", -123.45, "-123 " + assert_sprintf "%-10.4g", -123.45, "-123.5 " + assert_sprintf "%-10.5g", -123.45, "-123.45 " + assert_sprintf "%-10.5g", 0, "0 " + + assert_sprintf "%3.1g", 123.45, "1e+2" + assert_sprintf "%3.2g", 123.45, "1.2e+2" + assert_sprintf "%3.3g", 123.45, "123" + assert_sprintf "%3.4g", 123.45, "123.5" + assert_sprintf "%3.5g", 123.45, "123.45" + assert_sprintf "%3.1g", -123.45, "-1e+2" + assert_sprintf "%3.2g", -123.45, "-1.2e+2" + assert_sprintf "%3.3g", -123.45, "-123" + assert_sprintf "%3.4g", -123.45, "-123.5" + assert_sprintf "%3.5g", -123.45, "-123.45" + + assert_sprintf "%1000.800g", 123.45, "#{" " * 950}123.4500000000000028421709430404007434844970703125" + end + + it "is ignored if precision argument is negative" do + assert_sprintf "%.*g", [-2, 123.45], "123.45" + end end - end - context "zero flag" do - it "left-pads the result with zeros" do - assert_sprintf "%010g", 123.45, "0000123.45" - assert_sprintf "%010g", -123.45, "-000123.45" - assert_sprintf "%010g", 0.0, "0000000000" + context "sharp flag" do + it "prints decimal point and trailing zeros" do + assert_sprintf "%#.0g", 12345, "1.e+4" + assert_sprintf "%#.6g", 12345, "12345.0" + assert_sprintf "%#.10g", 12345, "12345.00000" + assert_sprintf "%#.100g", 12345, "12345.#{"0" * 95}" + assert_sprintf "%#.1000g", 12345, "12345.#{"0" * 995}" + + assert_sprintf "%#.0g", 1e-5, "1.e-5" + assert_sprintf "%#.6g", 1e-5, "1.00000e-5" + assert_sprintf "%#.10g", 1e-5, "1.000000000e-5" + assert_sprintf "%#.100g", 1e-5, "1.0000000000000000818030539140313095458623138256371021270751953125#{"0" * 35}e-5" + assert_sprintf "%#.1000g", 1e-5, "1.0000000000000000818030539140313095458623138256371021270751953125#{"0" * 935}e-5" + + assert_sprintf "%#15.0g", 12345, " 1.e+4" + assert_sprintf "%#15.6g", 12345, " 12345.0" + assert_sprintf "%#15.10g", 12345, " 12345.00000" + end end - it "is ignored if string is left-justified" do - assert_sprintf "%-010g", 123.45, "123.45 " - assert_sprintf "%-010g", -123.45, "-123.45 " - assert_sprintf "%-010g", 0.0, "0 " + context "plus flag" do + it "writes a plus sign for positive values" do + assert_sprintf "%+g", 123.45, "+123.45" + assert_sprintf "%+g", -123.45, "-123.45" + assert_sprintf "%+g", 0.0, "+0" + end + + it "writes plus sign after left space-padding" do + assert_sprintf "%+10g", 123.45, " +123.45" + assert_sprintf "%+10g", -123.45, " -123.45" + assert_sprintf "%+10g", 0.0, " +0" + end + + it "writes plus sign before left zero-padding" do + assert_sprintf "%+010g", 123.45, "+000123.45" + assert_sprintf "%+010g", -123.45, "-000123.45" + assert_sprintf "%+010g", 0.0, "+000000000" + end end - it "can be used with precision" do - assert_sprintf "%010.2g", 123.45, "00001.2e+2" - assert_sprintf "%010.2g", -123.45, "-0001.2e+2" - assert_sprintf "%010.2g", 0.0, "0000000000" + context "space flag" do + it "writes a space for positive values" do + assert_sprintf "% g", 123.45, " 123.45" + assert_sprintf "% g", -123.45, "-123.45" + assert_sprintf "% g", 0.0, " 0" + end + + it "writes space before left space-padding" do + assert_sprintf "% 10g", 123.45, " 123.45" + assert_sprintf "% 10g", -123.45, " -123.45" + assert_sprintf "% 10g", 0.0, " 0" + + assert_sprintf "% 010g", 123.45, " 000123.45" + assert_sprintf "% 010g", -123.45, "-000123.45" + assert_sprintf "% 010g", 0.0, " 000000000" + end + + it "is ignored if plus flag is also specified" do + assert_sprintf "% +g", 123.45, "+123.45" + assert_sprintf "%+ g", -123.45, "-123.45" + end end - end - - context "minus flag" do - it "left-justifies the string" do - assert_sprintf "%-10g", 123.45, "123.45 " - assert_sprintf "%-10g", -123.45, "-123.45 " - assert_sprintf "%-10g", 0.0, "0 " - assert_sprintf "%- 10g", 123.45, " 123.45 " - assert_sprintf "%- 10g", -123.45, "-123.45 " - assert_sprintf "%- 10g", 0.0, " 0 " + context "zero flag" do + it "left-pads the result with zeros" do + assert_sprintf "%010g", 123.45, "0000123.45" + assert_sprintf "%010g", -123.45, "-000123.45" + assert_sprintf "%010g", 0.0, "0000000000" + end + + it "is ignored if string is left-justified" do + assert_sprintf "%-010g", 123.45, "123.45 " + assert_sprintf "%-010g", -123.45, "-123.45 " + assert_sprintf "%-010g", 0.0, "0 " + end + + it "can be used with precision" do + assert_sprintf "%010.2g", 123.45, "00001.2e+2" + assert_sprintf "%010.2g", -123.45, "-0001.2e+2" + assert_sprintf "%010.2g", 0.0, "0000000000" + end end - end - end - context "hex format" do - it "works" do - assert_sprintf "%a", 1194684.0, "0x1.23abcp+20" - assert_sprintf "%A", 1194684.0, "0X1.23ABCP+20" - assert_sprintf "%a", 12345678.45, "0x1.78c29ce666666p+23" - assert_sprintf "%A", 12345678.45, "0X1.78C29CE666666P+23" - - assert_sprintf "%a", Float64::MAX, "0x1.fffffffffffffp+1023" - assert_sprintf "%a", Float64::MIN_POSITIVE, "0x1p-1022" - assert_sprintf "%a", Float64::MIN_SUBNORMAL, "0x0.0000000000001p-1022" - assert_sprintf "%a", 0.0, "0x0p+0" - assert_sprintf "%a", -0.0, "-0x0p+0" - assert_sprintf "%a", -Float64::MIN_SUBNORMAL, "-0x0.0000000000001p-1022" - assert_sprintf "%a", -Float64::MIN_POSITIVE, "-0x1p-1022" - assert_sprintf "%a", Float64::MIN, "-0x1.fffffffffffffp+1023" - end - - context "width specifier" do - it "sets the minimum length of the string" do - assert_sprintf "%20a", hexfloat("0x1p+0"), " 0x1p+0" - assert_sprintf "%20a", hexfloat("0x1.2p+0"), " 0x1.2p+0" - assert_sprintf "%20a", hexfloat("0x1.23p+0"), " 0x1.23p+0" - assert_sprintf "%20a", hexfloat("0x1.234p+0"), " 0x1.234p+0" - assert_sprintf "%20a", hexfloat("0x1.2345p+0"), " 0x1.2345p+0" - assert_sprintf "%20a", hexfloat("0x1.23456p+0"), " 0x1.23456p+0" - assert_sprintf "%20a", hexfloat("0x1.234567p+0"), " 0x1.234567p+0" - assert_sprintf "%20a", hexfloat("0x1.2345678p+0"), " 0x1.2345678p+0" - assert_sprintf "%20a", hexfloat("0x1.23456789p+0"), " 0x1.23456789p+0" - assert_sprintf "%20a", hexfloat("0x1.23456789ap+0"), " 0x1.23456789ap+0" - assert_sprintf "%20a", hexfloat("0x1.23456789abp+0"), " 0x1.23456789abp+0" - assert_sprintf "%20a", hexfloat("0x1.23456789abcp+0"), " 0x1.23456789abcp+0" - - assert_sprintf "%20a", hexfloat("-0x1p+0"), " -0x1p+0" - assert_sprintf "%20a", hexfloat("-0x1.2p+0"), " -0x1.2p+0" - assert_sprintf "%20a", hexfloat("-0x1.23p+0"), " -0x1.23p+0" - assert_sprintf "%20a", hexfloat("-0x1.234p+0"), " -0x1.234p+0" - assert_sprintf "%20a", hexfloat("-0x1.2345p+0"), " -0x1.2345p+0" - assert_sprintf "%20a", hexfloat("-0x1.23456p+0"), " -0x1.23456p+0" - assert_sprintf "%20a", hexfloat("-0x1.234567p+0"), " -0x1.234567p+0" - assert_sprintf "%20a", hexfloat("-0x1.2345678p+0"), " -0x1.2345678p+0" - assert_sprintf "%20a", hexfloat("-0x1.23456789p+0"), " -0x1.23456789p+0" - assert_sprintf "%20a", hexfloat("-0x1.23456789ap+0"), " -0x1.23456789ap+0" - assert_sprintf "%20a", hexfloat("-0x1.23456789abp+0"), " -0x1.23456789abp+0" - assert_sprintf "%20a", hexfloat("-0x1.23456789abcp+0"), " -0x1.23456789abcp+0" - - assert_sprintf "%+20a", 1194684.0, " +0x1.23abcp+20" - - assert_sprintf "%14a", 1194684.0, " 0x1.23abcp+20" - assert_sprintf "%14a", -1194684.0, "-0x1.23abcp+20" - assert_sprintf "%+14a", 1194684.0, "+0x1.23abcp+20" - - assert_sprintf "%13a", 1194684.0, "0x1.23abcp+20" - assert_sprintf "%13a", -1194684.0, "-0x1.23abcp+20" - assert_sprintf "%+13a", 1194684.0, "+0x1.23abcp+20" - - assert_sprintf "%2a", 1194684.0, "0x1.23abcp+20" - assert_sprintf "%2a", -1194684.0, "-0x1.23abcp+20" - assert_sprintf "%+2a", 1194684.0, "+0x1.23abcp+20" - end + context "minus flag" do + it "left-justifies the string" do + assert_sprintf "%-10g", 123.45, "123.45 " + assert_sprintf "%-10g", -123.45, "-123.45 " + assert_sprintf "%-10g", 0.0, "0 " - it "left-justifies on negative width" do - assert_sprintf "%*a", [-20, 1194684.0], "0x1.23abcp+20 " + assert_sprintf "%- 10g", 123.45, " 123.45 " + assert_sprintf "%- 10g", -123.45, "-123.45 " + assert_sprintf "%- 10g", 0.0, " 0 " + end end end - context "precision specifier" do - it "sets the minimum length of the fractional part" do - assert_sprintf "%.0a", 0.0, "0x0p+0" - - assert_sprintf "%.0a", (Float64::MIN_POSITIVE / 2).prev_float, "0x0p-1022" - assert_sprintf "%.0a", Float64::MIN_POSITIVE / 2, "0x0p-1022" - assert_sprintf "%.0a", (Float64::MIN_POSITIVE / 2).next_float, "0x1p-1022" - assert_sprintf "%.0a", Float64::MIN_POSITIVE.prev_float, "0x1p-1022" - assert_sprintf "%.0a", Float64::MIN_POSITIVE, "0x1p-1022" - - assert_sprintf "%.0a", 0.0625, "0x1p-4" - assert_sprintf "%.0a", 0.0625.next_float, "0x1p-4" - assert_sprintf "%.0a", 0.09375.prev_float, "0x1p-4" - assert_sprintf "%.0a", 0.09375, "0x2p-4" - assert_sprintf "%.0a", 0.09375.next_float, "0x2p-4" - assert_sprintf "%.0a", 0.125.prev_float, "0x2p-4" - assert_sprintf "%.0a", 0.125, "0x1p-3" - - assert_sprintf "%.1a", 2.0, "0x1.0p+1" - assert_sprintf "%.1a", 2.0.next_float, "0x1.0p+1" - assert_sprintf "%.1a", 2.0625.prev_float, "0x1.0p+1" - assert_sprintf "%.1a", 2.0625, "0x1.0p+1" - assert_sprintf "%.1a", 2.0625.next_float, "0x1.1p+1" - assert_sprintf "%.1a", 2.125.prev_float, "0x1.1p+1" - assert_sprintf "%.1a", 2.125, "0x1.1p+1" - assert_sprintf "%.1a", 2.125.next_float, "0x1.1p+1" - assert_sprintf "%.1a", 2.1875.prev_float, "0x1.1p+1" - assert_sprintf "%.1a", 2.1875, "0x1.2p+1" - assert_sprintf "%.1a", 2.1875.next_float, "0x1.2p+1" - assert_sprintf "%.1a", 2.25.prev_float, "0x1.2p+1" - assert_sprintf "%.1a", 2.25, "0x1.2p+1" - - assert_sprintf "%.1a", 60.0, "0x1.ep+5" - assert_sprintf "%.1a", 60.0.next_float, "0x1.ep+5" - assert_sprintf "%.1a", 61.0.prev_float, "0x1.ep+5" - assert_sprintf "%.1a", 61.0, "0x1.ep+5" - assert_sprintf "%.1a", 61.0.next_float, "0x1.fp+5" - assert_sprintf "%.1a", 62.0.prev_float, "0x1.fp+5" - assert_sprintf "%.1a", 62.0, "0x1.fp+5" - assert_sprintf "%.1a", 62.0.next_float, "0x1.fp+5" - assert_sprintf "%.1a", 63.0.prev_float, "0x1.fp+5" - assert_sprintf "%.1a", 63.0, "0x2.0p+5" - assert_sprintf "%.1a", 63.0.next_float, "0x2.0p+5" - assert_sprintf "%.1a", 64.0.prev_float, "0x2.0p+5" - assert_sprintf "%.1a", 64.0, "0x1.0p+6" - - assert_sprintf "%.4a", 65536.0, "0x1.0000p+16" - assert_sprintf "%.4a", 65536.0.next_float, "0x1.0000p+16" - assert_sprintf "%.4a", 65536.5.prev_float, "0x1.0000p+16" - assert_sprintf "%.4a", 65536.5, "0x1.0000p+16" - assert_sprintf "%.4a", 65536.5.next_float, "0x1.0001p+16" - assert_sprintf "%.4a", 65537.0.prev_float, "0x1.0001p+16" - assert_sprintf "%.4a", 65537.0, "0x1.0001p+16" - assert_sprintf "%.4a", 65537.0.next_float, "0x1.0001p+16" - assert_sprintf "%.4a", 65537.5.prev_float, "0x1.0001p+16" - assert_sprintf "%.4a", 65537.5, "0x1.0002p+16" - assert_sprintf "%.4a", 65537.5.next_float, "0x1.0002p+16" - assert_sprintf "%.4a", 65538.0.prev_float, "0x1.0002p+16" - assert_sprintf "%.4a", 65538.0, "0x1.0002p+16" - - assert_sprintf "%.4a", 131070.0, "0x1.fffep+16" - assert_sprintf "%.4a", 131070.0.next_float, "0x1.fffep+16" - assert_sprintf "%.4a", 131070.5.prev_float, "0x1.fffep+16" - assert_sprintf "%.4a", 131070.5, "0x1.fffep+16" - assert_sprintf "%.4a", 131070.5.next_float, "0x1.ffffp+16" - assert_sprintf "%.4a", 131071.0.prev_float, "0x1.ffffp+16" - assert_sprintf "%.4a", 131071.0, "0x1.ffffp+16" - assert_sprintf "%.4a", 131071.0.next_float, "0x1.ffffp+16" - assert_sprintf "%.4a", 131071.5.prev_float, "0x1.ffffp+16" - assert_sprintf "%.4a", 131071.5, "0x2.0000p+16" - assert_sprintf "%.4a", 131071.5.next_float, "0x2.0000p+16" - assert_sprintf "%.4a", 131072.0.prev_float, "0x2.0000p+16" - assert_sprintf "%.4a", 131072.0, "0x1.0000p+17" - - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x01, "0x0.000000000000p-1022" - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x07, "0x0.000000000000p-1022" - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x08, "0x0.000000000000p-1022" - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x09, "0x0.000000000001p-1022" - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x0f, "0x0.000000000001p-1022" - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x10, "0x0.000000000001p-1022" - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x11, "0x0.000000000001p-1022" - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x17, "0x0.000000000001p-1022" - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x18, "0x0.000000000002p-1022" - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x19, "0x0.000000000002p-1022" - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x1f, "0x0.000000000002p-1022" - assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x20, "0x0.000000000002p-1022" - - assert_sprintf "%.17a", Float64::MAX, "0x1.fffffffffffff0000p+1023" - assert_sprintf "%.16a", Float64::MAX, "0x1.fffffffffffff000p+1023" - assert_sprintf "%.15a", Float64::MAX, "0x1.fffffffffffff00p+1023" - assert_sprintf "%.14a", Float64::MAX, "0x1.fffffffffffff0p+1023" - assert_sprintf "%.13a", Float64::MAX, "0x1.fffffffffffffp+1023" - assert_sprintf "%.12a", Float64::MAX, "0x2.000000000000p+1023" - assert_sprintf "%.11a", Float64::MAX, "0x2.00000000000p+1023" - assert_sprintf "%.10a", Float64::MAX, "0x2.0000000000p+1023" - assert_sprintf "%.9a", Float64::MAX, "0x2.000000000p+1023" - assert_sprintf "%.8a", Float64::MAX, "0x2.00000000p+1023" - assert_sprintf "%.7a", Float64::MAX, "0x2.0000000p+1023" - assert_sprintf "%.6a", Float64::MAX, "0x2.000000p+1023" - assert_sprintf "%.5a", Float64::MAX, "0x2.00000p+1023" - assert_sprintf "%.4a", Float64::MAX, "0x2.0000p+1023" - assert_sprintf "%.3a", Float64::MAX, "0x2.000p+1023" - assert_sprintf "%.2a", Float64::MAX, "0x2.00p+1023" - assert_sprintf "%.1a", Float64::MAX, "0x2.0p+1023" - assert_sprintf "%.0a", Float64::MAX, "0x2p+1023" - - assert_sprintf "%.1000a", 1194684.0, "0x1.23abc#{"0" * 995}p+20" + context "hex format" do + it "works" do + assert_sprintf "%a", 1194684.0, "0x1.23abcp+20" + assert_sprintf "%A", 1194684.0, "0X1.23ABCP+20" + assert_sprintf "%a", 12345678.45, "0x1.78c29ce666666p+23" + assert_sprintf "%A", 12345678.45, "0X1.78C29CE666666P+23" + + assert_sprintf "%a", Float64::MAX, "0x1.fffffffffffffp+1023" + assert_sprintf "%a", Float64::MIN_POSITIVE, "0x1p-1022" + assert_sprintf "%a", Float64::MIN_SUBNORMAL, "0x0.0000000000001p-1022" + assert_sprintf "%a", 0.0, "0x0p+0" + assert_sprintf "%a", -0.0, "-0x0p+0" + assert_sprintf "%a", -Float64::MIN_SUBNORMAL, "-0x0.0000000000001p-1022" + assert_sprintf "%a", -Float64::MIN_POSITIVE, "-0x1p-1022" + assert_sprintf "%a", Float64::MIN, "-0x1.fffffffffffffp+1023" end - it "can be used with width" do - assert_sprintf "%20.8a", 1194684.0, " 0x1.23abc000p+20" - assert_sprintf "%20.8a", -1194684.0, " -0x1.23abc000p+20" - assert_sprintf "%20.8a", 0.0, " 0x0.00000000p+0" - - assert_sprintf "%-20.8a", 1194684.0, "0x1.23abc000p+20 " - assert_sprintf "%-20.8a", -1194684.0, "-0x1.23abc000p+20 " - assert_sprintf "%-20.8a", 0.0, "0x0.00000000p+0 " - - assert_sprintf "%4.8a", 1194684.0, "0x1.23abc000p+20" - assert_sprintf "%4.8a", -1194684.0, "-0x1.23abc000p+20" - assert_sprintf "%4.8a", 0.0, "0x0.00000000p+0" - end - - it "is ignored if precision argument is negative" do - assert_sprintf "%.*a", [-2, 1194684.0], "0x1.23abcp+20" - end - end - - context "sharp flag" do - it "prints a decimal point even if no digits follow" do - assert_sprintf "%#a", 1.0, "0x1.p+0" - assert_sprintf "%#a", Float64::MIN_POSITIVE, "0x1.p-1022" - assert_sprintf "%#a", 2.0 ** -234, "0x1.p-234" - assert_sprintf "%#a", 2.0 ** 1021, "0x1.p+1021" - assert_sprintf "%#a", 0.0, "0x0.p+0" - assert_sprintf "%#a", -0.0, "-0x0.p+0" - - assert_sprintf "%#.0a", 1.0, "0x1.p+0" - assert_sprintf "%#.0a", Float64::MIN_POSITIVE, "0x1.p-1022" - assert_sprintf "%#.0a", 2.0 ** -234, "0x1.p-234" - assert_sprintf "%#.0a", 2.0 ** 1021, "0x1.p+1021" - assert_sprintf "%#.0a", 1194684.0, "0x1.p+20" - assert_sprintf "%#.0a", 0.0, "0x0.p+0" - assert_sprintf "%#.0a", -0.0, "-0x0.p+0" + context "width specifier" do + it "sets the minimum length of the string" do + assert_sprintf "%20a", hexfloat("0x1p+0"), " 0x1p+0" + assert_sprintf "%20a", hexfloat("0x1.2p+0"), " 0x1.2p+0" + assert_sprintf "%20a", hexfloat("0x1.23p+0"), " 0x1.23p+0" + assert_sprintf "%20a", hexfloat("0x1.234p+0"), " 0x1.234p+0" + assert_sprintf "%20a", hexfloat("0x1.2345p+0"), " 0x1.2345p+0" + assert_sprintf "%20a", hexfloat("0x1.23456p+0"), " 0x1.23456p+0" + assert_sprintf "%20a", hexfloat("0x1.234567p+0"), " 0x1.234567p+0" + assert_sprintf "%20a", hexfloat("0x1.2345678p+0"), " 0x1.2345678p+0" + assert_sprintf "%20a", hexfloat("0x1.23456789p+0"), " 0x1.23456789p+0" + assert_sprintf "%20a", hexfloat("0x1.23456789ap+0"), " 0x1.23456789ap+0" + assert_sprintf "%20a", hexfloat("0x1.23456789abp+0"), " 0x1.23456789abp+0" + assert_sprintf "%20a", hexfloat("0x1.23456789abcp+0"), " 0x1.23456789abcp+0" + + assert_sprintf "%20a", hexfloat("-0x1p+0"), " -0x1p+0" + assert_sprintf "%20a", hexfloat("-0x1.2p+0"), " -0x1.2p+0" + assert_sprintf "%20a", hexfloat("-0x1.23p+0"), " -0x1.23p+0" + assert_sprintf "%20a", hexfloat("-0x1.234p+0"), " -0x1.234p+0" + assert_sprintf "%20a", hexfloat("-0x1.2345p+0"), " -0x1.2345p+0" + assert_sprintf "%20a", hexfloat("-0x1.23456p+0"), " -0x1.23456p+0" + assert_sprintf "%20a", hexfloat("-0x1.234567p+0"), " -0x1.234567p+0" + assert_sprintf "%20a", hexfloat("-0x1.2345678p+0"), " -0x1.2345678p+0" + assert_sprintf "%20a", hexfloat("-0x1.23456789p+0"), " -0x1.23456789p+0" + assert_sprintf "%20a", hexfloat("-0x1.23456789ap+0"), " -0x1.23456789ap+0" + assert_sprintf "%20a", hexfloat("-0x1.23456789abp+0"), " -0x1.23456789abp+0" + assert_sprintf "%20a", hexfloat("-0x1.23456789abcp+0"), " -0x1.23456789abcp+0" + + assert_sprintf "%+20a", 1194684.0, " +0x1.23abcp+20" + + assert_sprintf "%14a", 1194684.0, " 0x1.23abcp+20" + assert_sprintf "%14a", -1194684.0, "-0x1.23abcp+20" + assert_sprintf "%+14a", 1194684.0, "+0x1.23abcp+20" + + assert_sprintf "%13a", 1194684.0, "0x1.23abcp+20" + assert_sprintf "%13a", -1194684.0, "-0x1.23abcp+20" + assert_sprintf "%+13a", 1194684.0, "+0x1.23abcp+20" + + assert_sprintf "%2a", 1194684.0, "0x1.23abcp+20" + assert_sprintf "%2a", -1194684.0, "-0x1.23abcp+20" + assert_sprintf "%+2a", 1194684.0, "+0x1.23abcp+20" + end + + it "left-justifies on negative width" do + assert_sprintf "%*a", [-20, 1194684.0], "0x1.23abcp+20 " + end end - end - context "plus flag" do - it "writes a plus sign for positive values" do - assert_sprintf "%+a", 1194684.0, "+0x1.23abcp+20" - assert_sprintf "%+a", -1194684.0, "-0x1.23abcp+20" - assert_sprintf "%+a", 0.0, "+0x0p+0" + context "precision specifier" do + it "sets the minimum length of the fractional part" do + assert_sprintf "%.0a", 0.0, "0x0p+0" + + assert_sprintf "%.0a", (Float64::MIN_POSITIVE / 2).prev_float, "0x0p-1022" + assert_sprintf "%.0a", Float64::MIN_POSITIVE / 2, "0x0p-1022" + assert_sprintf "%.0a", (Float64::MIN_POSITIVE / 2).next_float, "0x1p-1022" + assert_sprintf "%.0a", Float64::MIN_POSITIVE.prev_float, "0x1p-1022" + assert_sprintf "%.0a", Float64::MIN_POSITIVE, "0x1p-1022" + + assert_sprintf "%.0a", 0.0625, "0x1p-4" + assert_sprintf "%.0a", 0.0625.next_float, "0x1p-4" + assert_sprintf "%.0a", 0.09375.prev_float, "0x1p-4" + assert_sprintf "%.0a", 0.09375, "0x2p-4" + assert_sprintf "%.0a", 0.09375.next_float, "0x2p-4" + assert_sprintf "%.0a", 0.125.prev_float, "0x2p-4" + assert_sprintf "%.0a", 0.125, "0x1p-3" + + assert_sprintf "%.1a", 2.0, "0x1.0p+1" + assert_sprintf "%.1a", 2.0.next_float, "0x1.0p+1" + assert_sprintf "%.1a", 2.0625.prev_float, "0x1.0p+1" + assert_sprintf "%.1a", 2.0625, "0x1.0p+1" + assert_sprintf "%.1a", 2.0625.next_float, "0x1.1p+1" + assert_sprintf "%.1a", 2.125.prev_float, "0x1.1p+1" + assert_sprintf "%.1a", 2.125, "0x1.1p+1" + assert_sprintf "%.1a", 2.125.next_float, "0x1.1p+1" + assert_sprintf "%.1a", 2.1875.prev_float, "0x1.1p+1" + assert_sprintf "%.1a", 2.1875, "0x1.2p+1" + assert_sprintf "%.1a", 2.1875.next_float, "0x1.2p+1" + assert_sprintf "%.1a", 2.25.prev_float, "0x1.2p+1" + assert_sprintf "%.1a", 2.25, "0x1.2p+1" + + assert_sprintf "%.1a", 60.0, "0x1.ep+5" + assert_sprintf "%.1a", 60.0.next_float, "0x1.ep+5" + assert_sprintf "%.1a", 61.0.prev_float, "0x1.ep+5" + assert_sprintf "%.1a", 61.0, "0x1.ep+5" + assert_sprintf "%.1a", 61.0.next_float, "0x1.fp+5" + assert_sprintf "%.1a", 62.0.prev_float, "0x1.fp+5" + assert_sprintf "%.1a", 62.0, "0x1.fp+5" + assert_sprintf "%.1a", 62.0.next_float, "0x1.fp+5" + assert_sprintf "%.1a", 63.0.prev_float, "0x1.fp+5" + assert_sprintf "%.1a", 63.0, "0x2.0p+5" + assert_sprintf "%.1a", 63.0.next_float, "0x2.0p+5" + assert_sprintf "%.1a", 64.0.prev_float, "0x2.0p+5" + assert_sprintf "%.1a", 64.0, "0x1.0p+6" + + assert_sprintf "%.4a", 65536.0, "0x1.0000p+16" + assert_sprintf "%.4a", 65536.0.next_float, "0x1.0000p+16" + assert_sprintf "%.4a", 65536.5.prev_float, "0x1.0000p+16" + assert_sprintf "%.4a", 65536.5, "0x1.0000p+16" + assert_sprintf "%.4a", 65536.5.next_float, "0x1.0001p+16" + assert_sprintf "%.4a", 65537.0.prev_float, "0x1.0001p+16" + assert_sprintf "%.4a", 65537.0, "0x1.0001p+16" + assert_sprintf "%.4a", 65537.0.next_float, "0x1.0001p+16" + assert_sprintf "%.4a", 65537.5.prev_float, "0x1.0001p+16" + assert_sprintf "%.4a", 65537.5, "0x1.0002p+16" + assert_sprintf "%.4a", 65537.5.next_float, "0x1.0002p+16" + assert_sprintf "%.4a", 65538.0.prev_float, "0x1.0002p+16" + assert_sprintf "%.4a", 65538.0, "0x1.0002p+16" + + assert_sprintf "%.4a", 131070.0, "0x1.fffep+16" + assert_sprintf "%.4a", 131070.0.next_float, "0x1.fffep+16" + assert_sprintf "%.4a", 131070.5.prev_float, "0x1.fffep+16" + assert_sprintf "%.4a", 131070.5, "0x1.fffep+16" + assert_sprintf "%.4a", 131070.5.next_float, "0x1.ffffp+16" + assert_sprintf "%.4a", 131071.0.prev_float, "0x1.ffffp+16" + assert_sprintf "%.4a", 131071.0, "0x1.ffffp+16" + assert_sprintf "%.4a", 131071.0.next_float, "0x1.ffffp+16" + assert_sprintf "%.4a", 131071.5.prev_float, "0x1.ffffp+16" + assert_sprintf "%.4a", 131071.5, "0x2.0000p+16" + assert_sprintf "%.4a", 131071.5.next_float, "0x2.0000p+16" + assert_sprintf "%.4a", 131072.0.prev_float, "0x2.0000p+16" + assert_sprintf "%.4a", 131072.0, "0x1.0000p+17" + + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x01, "0x0.000000000000p-1022" + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x07, "0x0.000000000000p-1022" + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x08, "0x0.000000000000p-1022" + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x09, "0x0.000000000001p-1022" + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x0f, "0x0.000000000001p-1022" + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x10, "0x0.000000000001p-1022" + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x11, "0x0.000000000001p-1022" + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x17, "0x0.000000000001p-1022" + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x18, "0x0.000000000002p-1022" + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x19, "0x0.000000000002p-1022" + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x1f, "0x0.000000000002p-1022" + assert_sprintf "%.12a", Float64::MIN_SUBNORMAL * 0x20, "0x0.000000000002p-1022" + + assert_sprintf "%.17a", Float64::MAX, "0x1.fffffffffffff0000p+1023" + assert_sprintf "%.16a", Float64::MAX, "0x1.fffffffffffff000p+1023" + assert_sprintf "%.15a", Float64::MAX, "0x1.fffffffffffff00p+1023" + assert_sprintf "%.14a", Float64::MAX, "0x1.fffffffffffff0p+1023" + assert_sprintf "%.13a", Float64::MAX, "0x1.fffffffffffffp+1023" + assert_sprintf "%.12a", Float64::MAX, "0x2.000000000000p+1023" + assert_sprintf "%.11a", Float64::MAX, "0x2.00000000000p+1023" + assert_sprintf "%.10a", Float64::MAX, "0x2.0000000000p+1023" + assert_sprintf "%.9a", Float64::MAX, "0x2.000000000p+1023" + assert_sprintf "%.8a", Float64::MAX, "0x2.00000000p+1023" + assert_sprintf "%.7a", Float64::MAX, "0x2.0000000p+1023" + assert_sprintf "%.6a", Float64::MAX, "0x2.000000p+1023" + assert_sprintf "%.5a", Float64::MAX, "0x2.00000p+1023" + assert_sprintf "%.4a", Float64::MAX, "0x2.0000p+1023" + assert_sprintf "%.3a", Float64::MAX, "0x2.000p+1023" + assert_sprintf "%.2a", Float64::MAX, "0x2.00p+1023" + assert_sprintf "%.1a", Float64::MAX, "0x2.0p+1023" + assert_sprintf "%.0a", Float64::MAX, "0x2p+1023" + + assert_sprintf "%.1000a", 1194684.0, "0x1.23abc#{"0" * 995}p+20" + end + + it "can be used with width" do + assert_sprintf "%20.8a", 1194684.0, " 0x1.23abc000p+20" + assert_sprintf "%20.8a", -1194684.0, " -0x1.23abc000p+20" + assert_sprintf "%20.8a", 0.0, " 0x0.00000000p+0" + + assert_sprintf "%-20.8a", 1194684.0, "0x1.23abc000p+20 " + assert_sprintf "%-20.8a", -1194684.0, "-0x1.23abc000p+20 " + assert_sprintf "%-20.8a", 0.0, "0x0.00000000p+0 " + + assert_sprintf "%4.8a", 1194684.0, "0x1.23abc000p+20" + assert_sprintf "%4.8a", -1194684.0, "-0x1.23abc000p+20" + assert_sprintf "%4.8a", 0.0, "0x0.00000000p+0" + end + + it "is ignored if precision argument is negative" do + assert_sprintf "%.*a", [-2, 1194684.0], "0x1.23abcp+20" + end end - it "writes plus sign after left space-padding" do - assert_sprintf "%+20a", 1194684.0, " +0x1.23abcp+20" - assert_sprintf "%+20a", -1194684.0, " -0x1.23abcp+20" - assert_sprintf "%+20a", 0.0, " +0x0p+0" + context "sharp flag" do + it "prints a decimal point even if no digits follow" do + assert_sprintf "%#a", 1.0, "0x1.p+0" + assert_sprintf "%#a", Float64::MIN_POSITIVE, "0x1.p-1022" + assert_sprintf "%#a", 2.0 ** -234, "0x1.p-234" + assert_sprintf "%#a", 2.0 ** 1021, "0x1.p+1021" + assert_sprintf "%#a", 0.0, "0x0.p+0" + assert_sprintf "%#a", -0.0, "-0x0.p+0" + + assert_sprintf "%#.0a", 1.0, "0x1.p+0" + assert_sprintf "%#.0a", Float64::MIN_POSITIVE, "0x1.p-1022" + assert_sprintf "%#.0a", 2.0 ** -234, "0x1.p-234" + assert_sprintf "%#.0a", 2.0 ** 1021, "0x1.p+1021" + assert_sprintf "%#.0a", 1194684.0, "0x1.p+20" + assert_sprintf "%#.0a", 0.0, "0x0.p+0" + assert_sprintf "%#.0a", -0.0, "-0x0.p+0" + end end - it "writes plus sign before left zero-padding" do - assert_sprintf "%+020a", 1194684.0, "+0x0000001.23abcp+20" - assert_sprintf "%+020a", -1194684.0, "-0x0000001.23abcp+20" - assert_sprintf "%+020a", 0.0, "+0x00000000000000p+0" + context "plus flag" do + it "writes a plus sign for positive values" do + assert_sprintf "%+a", 1194684.0, "+0x1.23abcp+20" + assert_sprintf "%+a", -1194684.0, "-0x1.23abcp+20" + assert_sprintf "%+a", 0.0, "+0x0p+0" + end + + it "writes plus sign after left space-padding" do + assert_sprintf "%+20a", 1194684.0, " +0x1.23abcp+20" + assert_sprintf "%+20a", -1194684.0, " -0x1.23abcp+20" + assert_sprintf "%+20a", 0.0, " +0x0p+0" + end + + it "writes plus sign before left zero-padding" do + assert_sprintf "%+020a", 1194684.0, "+0x0000001.23abcp+20" + assert_sprintf "%+020a", -1194684.0, "-0x0000001.23abcp+20" + assert_sprintf "%+020a", 0.0, "+0x00000000000000p+0" + end end - end - context "space flag" do - it "writes a space for positive values" do - assert_sprintf "% a", 1194684.0, " 0x1.23abcp+20" - assert_sprintf "% a", -1194684.0, "-0x1.23abcp+20" - assert_sprintf "% a", 0.0, " 0x0p+0" + context "space flag" do + it "writes a space for positive values" do + assert_sprintf "% a", 1194684.0, " 0x1.23abcp+20" + assert_sprintf "% a", -1194684.0, "-0x1.23abcp+20" + assert_sprintf "% a", 0.0, " 0x0p+0" + end + + it "writes space before left space-padding" do + assert_sprintf "% 20a", 1194684.0, " 0x1.23abcp+20" + assert_sprintf "% 20a", -1194684.0, " -0x1.23abcp+20" + assert_sprintf "% 20a", 0.0, " 0x0p+0" + + assert_sprintf "% 020a", 1194684.0, " 0x0000001.23abcp+20" + assert_sprintf "% 020a", -1194684.0, "-0x0000001.23abcp+20" + assert_sprintf "% 020a", 0.0, " 0x00000000000000p+0" + end + + it "is ignored if plus flag is also specified" do + assert_sprintf "% +a", 1194684.0, "+0x1.23abcp+20" + assert_sprintf "%+ a", -1194684.0, "-0x1.23abcp+20" + end end - it "writes space before left space-padding" do - assert_sprintf "% 20a", 1194684.0, " 0x1.23abcp+20" - assert_sprintf "% 20a", -1194684.0, " -0x1.23abcp+20" - assert_sprintf "% 20a", 0.0, " 0x0p+0" - - assert_sprintf "% 020a", 1194684.0, " 0x0000001.23abcp+20" - assert_sprintf "% 020a", -1194684.0, "-0x0000001.23abcp+20" - assert_sprintf "% 020a", 0.0, " 0x00000000000000p+0" + context "zero flag" do + it "left-pads the result with zeros" do + assert_sprintf "%020a", 1194684.0, "0x00000001.23abcp+20" + assert_sprintf "%020a", -1194684.0, "-0x0000001.23abcp+20" + assert_sprintf "%020a", 0.0, "0x000000000000000p+0" + end + + it "is ignored if string is left-justified" do + assert_sprintf "%-020a", 1194684.0, "0x1.23abcp+20 " + assert_sprintf "%-020a", -1194684.0, "-0x1.23abcp+20 " + assert_sprintf "%-020a", 0.0, "0x0p+0 " + end + + it "can be used with precision" do + assert_sprintf "%020.8a", 1194684.0, "0x00001.23abc000p+20" + assert_sprintf "%020.8a", -1194684.0, "-0x0001.23abc000p+20" + assert_sprintf "%020.8a", 0.0, "0x000000.00000000p+0" + end end - it "is ignored if plus flag is also specified" do - assert_sprintf "% +a", 1194684.0, "+0x1.23abcp+20" - assert_sprintf "%+ a", -1194684.0, "-0x1.23abcp+20" + context "minus flag" do + it "left-justifies the string" do + assert_sprintf "%-20a", 1194684.0, "0x1.23abcp+20 " + assert_sprintf "%-20a", -1194684.0, "-0x1.23abcp+20 " + assert_sprintf "%-20a", 0.0, "0x0p+0 " + end end end - context "zero flag" do - it "left-pads the result with zeros" do - assert_sprintf "%020a", 1194684.0, "0x00000001.23abcp+20" - assert_sprintf "%020a", -1194684.0, "-0x0000001.23abcp+20" - assert_sprintf "%020a", 0.0, "0x000000000000000p+0" + [Float32, Float64].each do |float| + it "infinities" do + pos_inf = float.new(1) / float.new(0) + neg_inf = float.new(-1) / float.new(0) + + assert_sprintf "%f", pos_inf, "inf" + assert_sprintf "%a", pos_inf, "inf" + assert_sprintf "%e", pos_inf, "inf" + assert_sprintf "%g", pos_inf, "inf" + assert_sprintf "%A", pos_inf, "INF" + assert_sprintf "%E", pos_inf, "INF" + assert_sprintf "%G", pos_inf, "INF" + + assert_sprintf "%f", neg_inf, "-inf" + assert_sprintf "%G", neg_inf, "-INF" + + assert_sprintf "%2f", pos_inf, "inf" + assert_sprintf "%4f", pos_inf, " inf" + assert_sprintf "%6f", pos_inf, " inf" + assert_sprintf "%2f", neg_inf, "-inf" + assert_sprintf "%4f", neg_inf, "-inf" + assert_sprintf "%6f", neg_inf, " -inf" + + assert_sprintf "% f", pos_inf, " inf" + assert_sprintf "% 2f", pos_inf, " inf" + assert_sprintf "% 4f", pos_inf, " inf" + assert_sprintf "% 6f", pos_inf, " inf" + assert_sprintf "% f", neg_inf, "-inf" + assert_sprintf "% 2f", neg_inf, "-inf" + assert_sprintf "% 4f", neg_inf, "-inf" + assert_sprintf "% 6f", neg_inf, " -inf" + + assert_sprintf "%+f", pos_inf, "+inf" + assert_sprintf "%+2f", pos_inf, "+inf" + assert_sprintf "%+4f", pos_inf, "+inf" + assert_sprintf "%+6f", pos_inf, " +inf" + assert_sprintf "%+f", neg_inf, "-inf" + assert_sprintf "%+2f", neg_inf, "-inf" + assert_sprintf "%+4f", neg_inf, "-inf" + assert_sprintf "%+6f", neg_inf, " -inf" + + assert_sprintf "%+ f", pos_inf, "+inf" + + assert_sprintf "%-4f", pos_inf, "inf " + assert_sprintf "%-6f", pos_inf, "inf " + assert_sprintf "%-4f", neg_inf, "-inf" + assert_sprintf "%-6f", neg_inf, "-inf " + + assert_sprintf "% -4f", pos_inf, " inf" + assert_sprintf "% -6f", pos_inf, " inf " + assert_sprintf "% -4f", neg_inf, "-inf" + assert_sprintf "% -6f", neg_inf, "-inf " + + assert_sprintf "%-+4f", pos_inf, "+inf" + assert_sprintf "%-+6f", pos_inf, "+inf " + assert_sprintf "%-+4f", neg_inf, "-inf" + assert_sprintf "%-+6f", neg_inf, "-inf " + + assert_sprintf "%-+ 6f", pos_inf, "+inf " + + assert_sprintf "%06f", pos_inf, " inf" + assert_sprintf "%-06f", pos_inf, "inf " + assert_sprintf "%06f", neg_inf, " -inf" + assert_sprintf "%-06f", neg_inf, "-inf " + + assert_sprintf "%.1f", pos_inf, "inf" + + assert_sprintf "%#f", pos_inf, "inf" end - it "is ignored if string is left-justified" do - assert_sprintf "%-020a", 1194684.0, "0x1.23abcp+20 " - assert_sprintf "%-020a", -1194684.0, "-0x1.23abcp+20 " - assert_sprintf "%-020a", 0.0, "0x0p+0 " + it "not-a-numbers" do + pos_nan = Math.copysign(float.new(0) / float.new(0), 1) + neg_nan = Math.copysign(float.new(0) / float.new(0), -1) + + assert_sprintf "%f", pos_nan, "nan" + assert_sprintf "%a", pos_nan, "nan" + assert_sprintf "%e", pos_nan, "nan" + assert_sprintf "%g", pos_nan, "nan" + assert_sprintf "%A", pos_nan, "NAN" + assert_sprintf "%E", pos_nan, "NAN" + assert_sprintf "%G", pos_nan, "NAN" + + assert_sprintf "%f", neg_nan, "nan" + assert_sprintf "%a", neg_nan, "nan" + assert_sprintf "%e", neg_nan, "nan" + assert_sprintf "%g", neg_nan, "nan" + assert_sprintf "%A", neg_nan, "NAN" + assert_sprintf "%E", neg_nan, "NAN" + assert_sprintf "%G", neg_nan, "NAN" + + assert_sprintf "%+f", pos_nan, "+nan" + assert_sprintf "%+f", neg_nan, "+nan" end - - it "can be used with precision" do - assert_sprintf "%020.8a", 1194684.0, "0x00001.23abc000p+20" - assert_sprintf "%020.8a", -1194684.0, "-0x0001.23abc000p+20" - assert_sprintf "%020.8a", 0.0, "0x000000.00000000p+0" - end - end - - context "minus flag" do - it "left-justifies the string" do - assert_sprintf "%-20a", 1194684.0, "0x1.23abcp+20 " - assert_sprintf "%-20a", -1194684.0, "-0x1.23abcp+20 " - assert_sprintf "%-20a", 0.0, "0x0p+0 " - end - end - end - - [Float32, Float64].each do |float| - it "infinities" do - pos_inf = float.new(1) / float.new(0) - neg_inf = float.new(-1) / float.new(0) - - assert_sprintf "%f", pos_inf, "inf" - assert_sprintf "%a", pos_inf, "inf" - assert_sprintf "%e", pos_inf, "inf" - assert_sprintf "%g", pos_inf, "inf" - assert_sprintf "%A", pos_inf, "INF" - assert_sprintf "%E", pos_inf, "INF" - assert_sprintf "%G", pos_inf, "INF" - - assert_sprintf "%f", neg_inf, "-inf" - assert_sprintf "%G", neg_inf, "-INF" - - assert_sprintf "%2f", pos_inf, "inf" - assert_sprintf "%4f", pos_inf, " inf" - assert_sprintf "%6f", pos_inf, " inf" - assert_sprintf "%2f", neg_inf, "-inf" - assert_sprintf "%4f", neg_inf, "-inf" - assert_sprintf "%6f", neg_inf, " -inf" - - assert_sprintf "% f", pos_inf, " inf" - assert_sprintf "% 2f", pos_inf, " inf" - assert_sprintf "% 4f", pos_inf, " inf" - assert_sprintf "% 6f", pos_inf, " inf" - assert_sprintf "% f", neg_inf, "-inf" - assert_sprintf "% 2f", neg_inf, "-inf" - assert_sprintf "% 4f", neg_inf, "-inf" - assert_sprintf "% 6f", neg_inf, " -inf" - - assert_sprintf "%+f", pos_inf, "+inf" - assert_sprintf "%+2f", pos_inf, "+inf" - assert_sprintf "%+4f", pos_inf, "+inf" - assert_sprintf "%+6f", pos_inf, " +inf" - assert_sprintf "%+f", neg_inf, "-inf" - assert_sprintf "%+2f", neg_inf, "-inf" - assert_sprintf "%+4f", neg_inf, "-inf" - assert_sprintf "%+6f", neg_inf, " -inf" - - assert_sprintf "%+ f", pos_inf, "+inf" - - assert_sprintf "%-4f", pos_inf, "inf " - assert_sprintf "%-6f", pos_inf, "inf " - assert_sprintf "%-4f", neg_inf, "-inf" - assert_sprintf "%-6f", neg_inf, "-inf " - - assert_sprintf "% -4f", pos_inf, " inf" - assert_sprintf "% -6f", pos_inf, " inf " - assert_sprintf "% -4f", neg_inf, "-inf" - assert_sprintf "% -6f", neg_inf, "-inf " - - assert_sprintf "%-+4f", pos_inf, "+inf" - assert_sprintf "%-+6f", pos_inf, "+inf " - assert_sprintf "%-+4f", neg_inf, "-inf" - assert_sprintf "%-+6f", neg_inf, "-inf " - - assert_sprintf "%-+ 6f", pos_inf, "+inf " - - assert_sprintf "%06f", pos_inf, " inf" - assert_sprintf "%-06f", pos_inf, "inf " - assert_sprintf "%06f", neg_inf, " -inf" - assert_sprintf "%-06f", neg_inf, "-inf " - - assert_sprintf "%.1f", pos_inf, "inf" - - assert_sprintf "%#f", pos_inf, "inf" - end - - it "not-a-numbers" do - pos_nan = Math.copysign(float.new(0) / float.new(0), 1) - neg_nan = Math.copysign(float.new(0) / float.new(0), -1) - - assert_sprintf "%f", pos_nan, "nan" - assert_sprintf "%a", pos_nan, "nan" - assert_sprintf "%e", pos_nan, "nan" - assert_sprintf "%g", pos_nan, "nan" - assert_sprintf "%A", pos_nan, "NAN" - assert_sprintf "%E", pos_nan, "NAN" - assert_sprintf "%G", pos_nan, "NAN" - - assert_sprintf "%f", neg_nan, "nan" - assert_sprintf "%a", neg_nan, "nan" - assert_sprintf "%e", neg_nan, "nan" - assert_sprintf "%g", neg_nan, "nan" - assert_sprintf "%A", neg_nan, "NAN" - assert_sprintf "%E", neg_nan, "NAN" - assert_sprintf "%G", neg_nan, "NAN" - - assert_sprintf "%+f", pos_nan, "+nan" - assert_sprintf "%+f", neg_nan, "+nan" end end + else + pending "floats" end context "strings" do diff --git a/src/float/printer/ryu_printf.cr b/src/float/printer/ryu_printf.cr index 005e575c3806..feffb98fdb0e 100644 --- a/src/float/printer/ryu_printf.cr +++ b/src/float/printer/ryu_printf.cr @@ -1,5 +1,4 @@ -# FIXME: this leads to an OOB on wasm32 (#13918) -{% skip_file if flag?(:wasm32) %} +{% skip_file unless String::Formatter::HAS_RYU_PRINTF %} require "./ryu_printf_table" diff --git a/src/float/printer/ryu_printf_table.cr b/src/float/printer/ryu_printf_table.cr index 6e16b939f16c..b9db3363f072 100644 --- a/src/float/printer/ryu_printf_table.cr +++ b/src/float/printer/ryu_printf_table.cr @@ -1,5 +1,4 @@ -# FIXME: this leads to an OOB on wasm32 (#13918) -{% skip_file if flag?(:wasm32) %} +{% skip_file unless String::Formatter::HAS_RYU_PRINTF %} module Float::Printer::RyuPrintf {% begin %} diff --git a/src/string/formatter.cr b/src/string/formatter.cr index 31239f42ee4d..b5f80d2aee87 100644 --- a/src/string/formatter.cr +++ b/src/string/formatter.cr @@ -2,6 +2,13 @@ require "c/stdio" # :nodoc: struct String::Formatter(A) + # FIXME: wasm32 appears to run out of memory if we use Ryu Printf, which + # initializes very large lookup tables, so we fall back to `LibC.snprintf` for + # the floating-point format specifiers (#13918) + {% begin %} + HAS_RYU_PRINTF = {{ !flag?(:wasm32) }} + {% end %} + private enum Mode None @@ -15,15 +22,19 @@ struct String::Formatter(A) Named end - @format_buf = Pointer(UInt8).null - @temp_buf = Pointer(UInt8).null + {% unless HAS_RYU_PRINTF %} + @format_buf = Pointer(UInt8).null + @format_buf_len = 0 + + @temp_buf = Pointer(UInt8).null + @temp_buf_len = 0 + {% end %} + @arg_mode : Mode = :none def initialize(string, @args : A, @io : IO) @reader = Char::Reader.new(string) @arg_index = 0 - @temp_buf_len = 0 - @format_buf_len = 0 end def format : Nil @@ -118,13 +129,17 @@ struct String::Formatter(A) next else flags.width = val - flags.width_size = size + {% unless HAS_RYU_PRINTF %} + flags.width_size = size + {% end %} break end when '*' val = consume_dynamic_value flags.width = val - flags.width_size = val.to_s.size + {% unless HAS_RYU_PRINTF %} + flags.width_size = val.to_s.size + {% end %} break else break @@ -141,16 +156,22 @@ struct String::Formatter(A) when '0'..'9' num, size = consume_number flags.precision = num - flags.precision_size = size + {% unless HAS_RYU_PRINTF %} + flags.precision_size = size + {% end %} when '*' val = consume_dynamic_value if val >= 0 flags.precision = val - flags.precision_size = val.to_s.size + {% unless HAS_RYU_PRINTF %} + flags.precision_size = val.to_s.size + {% end %} end else flags.precision = 0 - flags.precision_size = 1 + {% unless HAS_RYU_PRINTF %} + flags.precision_size = 1 + {% end %} end end flags @@ -307,12 +328,7 @@ struct String::Formatter(A) elsif float.nan? float_special("nan", 1, flags) else - # FIXME: wasm32 appears to run out of memory if we use Ryu Printf, which - # initializes very large lookup tables, so we always fall back to - # `LibC.snprintf` (#13918) - {% if flag?(:wasm32) %} - float_fallback(float, flags) - {% else %} + {% if HAS_RYU_PRINTF %} case flags.type when 'f' float_fixed(float, flags) @@ -325,6 +341,8 @@ struct String::Formatter(A) else raise "BUG: Unknown format type '#{flags.type}'" end + {% else %} + float_fallback(float, flags) {% end %} end else @@ -346,7 +364,7 @@ struct String::Formatter(A) pad(str_size, flags) if flags.right_padding? end - {% unless flag?(:wasm32) %} + {% if HAS_RYU_PRINTF %} # Formats floats with `%f` private def float_fixed(float, flags) # the longest string possible is due to `Float64::MIN_SUBNORMAL`, which @@ -485,50 +503,78 @@ struct String::Formatter(A) pad(str_size, flags) if flags.right_padding? end - {% end %} + {% else %} + # Delegate to `LibC.snprintf` for float formats if Ryu Printf is unavailable + private def float_fallback(float, flags) + format_buf = recreate_float_format_string(flags) - # Delegate to `LibC.snprintf` for float formats not yet ported to Crystal - private def float_fallback(float, flags) - format_buf = recreate_float_format_string(flags) + len = LibC.snprintf(nil, 0, format_buf, float) + 1 + temp_buf = temp_buf(len) + LibC.snprintf(temp_buf, len, format_buf, float) - len = LibC.snprintf(nil, 0, format_buf, float) + 1 - temp_buf = temp_buf(len) - LibC.snprintf(temp_buf, len, format_buf, float) + @io.write_string Slice.new(temp_buf, len - 1) + end - @io.write_string Slice.new(temp_buf, len - 1) - end + # Here we rebuild the original format string, like %f or %.2g and use snprintf + private def recreate_float_format_string(flags) + capacity = 3 # percent + type + \0 + capacity += flags.width_size + capacity += flags.precision_size + 1 # size + . + capacity += 1 if flags.sharp + capacity += 1 if flags.plus + capacity += 1 if flags.minus + capacity += 1 if flags.zero + capacity += 1 if flags.space + + format_buf = format_buf(capacity) + original_format_buf = format_buf + + io = IO::Memory.new(Bytes.new(format_buf, capacity)) + io << '%' + io << '#' if flags.sharp + io << '+' if flags.plus + io << '-' if flags.minus + io << '0' if flags.zero + io << ' ' if flags.space + io << flags.width if flags.width > 0 + if precision = flags.precision + io << '.' + io << precision if precision != 0 + end + io << flags.type + io.write_byte 0_u8 - # Here we rebuild the original format string, like %f or %.2g and use snprintf - def recreate_float_format_string(flags) - capacity = 3 # percent + type + \0 - capacity += flags.width_size - capacity += flags.precision_size + 1 # size + . - capacity += 1 if flags.sharp - capacity += 1 if flags.plus - capacity += 1 if flags.minus - capacity += 1 if flags.zero - capacity += 1 if flags.space - - format_buf = format_buf(capacity) - original_format_buf = format_buf - - io = IO::Memory.new(Bytes.new(format_buf, capacity)) - io << '%' - io << '#' if flags.sharp - io << '+' if flags.plus - io << '-' if flags.minus - io << '0' if flags.zero - io << ' ' if flags.space - io << flags.width if flags.width > 0 - if precision = flags.precision - io << '.' - io << precision if precision != 0 + original_format_buf end - io << flags.type - io.write_byte 0_u8 - original_format_buf - end + # We reuse a temporary buffer for snprintf + private def temp_buf(len) + temp_buf = @temp_buf + if temp_buf + if len > @temp_buf_len + @temp_buf_len = len + @temp_buf = temp_buf = temp_buf.realloc(len) + end + temp_buf + else + @temp_buf = Pointer(UInt8).malloc(len) + end + end + + # We reuse a temporary buffer for the float format string + private def format_buf(len) + format_buf = @format_buf + if format_buf + if len > @format_buf_len + @format_buf_len = len + @format_buf = format_buf = format_buf.realloc(len) + end + format_buf + else + @format_buf = Pointer(UInt8).malloc(len) + end + end + {% end %} # HAS_RYU_PRINTF def pad(consumed, flags) : Nil padding_char = flags.padding_char @@ -586,48 +632,23 @@ struct String::Formatter(A) @reader.next_char end - # We reuse a temporary buffer for snprintf - private def temp_buf(len) - temp_buf = @temp_buf - if temp_buf - if len > @temp_buf_len - @temp_buf_len = len - @temp_buf = temp_buf = temp_buf.realloc(len) - end - temp_buf - else - @temp_buf = Pointer(UInt8).malloc(len) - end - end - - # We reuse a temporary buffer for the float format string - private def format_buf(len) - format_buf = @format_buf - if format_buf - if len > @format_buf_len - @format_buf_len = len - @format_buf = format_buf = format_buf.realloc(len) - end - format_buf - else - @format_buf = Pointer(UInt8).malloc(len) - end - end - struct Flags property space : Bool, sharp : Bool, plus : Bool, minus : Bool, zero : Bool, float : Bool, base : Int32 - property width : Int32, width_size : Int32 - property type : Char, precision : Int32?, precision_size : Int32 + property width : Int32 + property type : Char, precision : Int32? property index : Int32? + {% unless HAS_RYU_PRINTF %} + property width_size : Int32 = 0 + property precision_size : Int32 = 0 + {% end %} + def initialize @space = @sharp = @plus = @minus = @zero = @float = false @width = 0 - @width_size = 0 @base = 10 @type = ' ' @precision = nil - @precision_size = 0 end def left_padding? : Bool From e00a0a4f3788a8f5d85484bc22e7f9930b870b2b Mon Sep 17 00:00:00 2001 From: Caspian Baska <email@caspian.computer> Date: Mon, 25 Dec 2023 03:29:35 +1100 Subject: [PATCH 012/105] Add `Enumerable(T)#to_a(& : T -> U) forall U` (#12653) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Johannes Müller <straightshoota@gmail.com> --- spec/std/enumerable_spec.cr | 10 ++++++++++ src/enumerable.cr | 15 ++++++++++++--- src/hash.cr | 18 ++++++++++++++++-- src/indexable.cr | 10 +++++----- src/llvm/parameter_collection.cr | 2 +- src/named_tuple.cr | 15 ++++++++++++++- src/set.cr | 13 +++++++++++++ src/tuple.cr | 22 ++++++++++++++++++++-- 8 files changed, 91 insertions(+), 14 deletions(-) diff --git a/spec/std/enumerable_spec.cr b/spec/std/enumerable_spec.cr index 04d46c7976a3..0bcbac725cb5 100644 --- a/spec/std/enumerable_spec.cr +++ b/spec/std/enumerable_spec.cr @@ -131,6 +131,16 @@ describe "Enumerable" do end end + describe "to_a" do + context "with a block" do + SpecEnumerable.new.to_a { |e| e*2 }.should eq [2, 4, 6] + end + + context "without a block" do + SpecEnumerable.new.to_a.should eq [1, 2, 3] + end + end + describe "#to_set" do context "without block" do it "creates a Set from the unique elements of the collection" do diff --git a/src/enumerable.cr b/src/enumerable.cr index c7b566e647e4..6b24c833f44f 100644 --- a/src/enumerable.cr +++ b/src/enumerable.cr @@ -1997,9 +1997,18 @@ module Enumerable(T) # ``` # (1..5).to_a # => [1, 2, 3, 4, 5] # ``` - def to_a - ary = [] of T - each { |e| ary << e } + def to_a : Array(T) + to_a(&.itself) + end + + # Returns an `Array` with the results of running *block* against each element of the collection. + # + # ``` + # (1..5).to_a { |i| i * 2 } # => [2, 4, 6, 8, 10] + # ``` + def to_a(& : T -> U) : Array(U) forall U + ary = [] of U + each { |e| ary << yield e } ary end diff --git a/src/hash.cr b/src/hash.cr index 8d8ccea22a0b..082f2a0a80e0 100644 --- a/src/hash.cr +++ b/src/hash.cr @@ -2055,16 +2055,30 @@ class Hash(K, V) pp.text "{...}" unless executed end - # Returns an array of tuples with key and values belonging to this Hash. + # Returns an `Array` of `Tuple(K, V)` with key and values belonging to this Hash. # # ``` # h = {1 => 'a', 2 => 'b', 3 => 'c'} # h.to_a # => [{1, 'a'}, {2, 'b'}, {3, 'c'}] # ``` + # # The order of the array follows the order the keys were inserted in the Hash. def to_a : Array({K, V}) + to_a(&.itself) + end + + # Returns an `Array` with the results of running *block* against tuples with key and values + # belonging to this Hash. + # + # ``` + # h = {"first_name" => "foo", "last_name" => "bar"} + # h.to_a { |_k, v| v.capitalize } # => ["Foo", "Bar"] + # ``` + # + # The order of the array follows the order the keys were inserted in the Hash. + def to_a(&block : {K, V} -> U) : Array(U) forall U to_a_impl do |entry| - {entry.key, entry.value} + yield ({entry.key, entry.value}) end end diff --git a/src/indexable.cr b/src/indexable.cr index 3725c1552e38..7496a95e0df0 100644 --- a/src/indexable.cr +++ b/src/indexable.cr @@ -693,14 +693,14 @@ module Indexable(T) end end - # Returns an `Array` with all the elements in the collection. + # Returns an `Array` with the results of running *block* against each element of the collection. # # ``` - # {1, 2, 3}.to_a # => [1, 2, 3] + # {1, 2, 3}.to_a { |i| i * 2 } # => [2, 4, 6] # ``` - def to_a : Array(T) - ary = Array(T).new(size) - each { |e| ary << e } + def to_a(& : T -> U) : Array(U) forall U + ary = Array(U).new(size) + each { |e| ary << yield e } ary end diff --git a/src/llvm/parameter_collection.cr b/src/llvm/parameter_collection.cr index 937d9ec2edcc..dd9a7eae91d7 100644 --- a/src/llvm/parameter_collection.cr +++ b/src/llvm/parameter_collection.cr @@ -8,7 +8,7 @@ struct LLVM::ParameterCollection LibLLVM.get_count_params(@function).to_i end - def to_a + def to_a : Array(LLVM::Value) param_size = size() Array(LLVM::Value).build(param_size) do |buffer| LibLLVM.get_params(@function, buffer.as(LibLLVM::ValueRef*)) diff --git a/src/named_tuple.cr b/src/named_tuple.cr index 7cceb568a260..4ea9df02fd20 100644 --- a/src/named_tuple.cr +++ b/src/named_tuple.cr @@ -588,12 +588,25 @@ struct NamedTuple # # NOTE: `to_a` on an empty named tuple produces an `Array(Tuple(Symbol, NoReturn))` def to_a + to_a(&.itself) + end + + # Returns an `Array` with the results of running *block* against tuples with key and values belonging + # to this `NamedTuple`. + # + # ``` + # tuple = {first_name: "foo", last_name: "bar"} + # tuple.to_a(&.last.capitalize) # => ["Foo", "Bar"] + # ``` + # + # NOTE: `to_a` on an empty named tuple produces an `Array(Tuple(Symbol, NoReturn))` + def to_a(&) {% if T.size == 0 %} [] of {Symbol, NoReturn} {% else %} [ {% for key in T %} - { {{key.symbolize}}, self[{{key.symbolize}}] }, + yield({ {{key.symbolize}}, self[{{key.symbolize}}] }), {% end %} ] {% end %} diff --git a/src/set.cr b/src/set.cr index 091352302c7d..40425e9aa032 100644 --- a/src/set.cr +++ b/src/set.cr @@ -382,6 +382,19 @@ struct Set(T) @hash.keys end + # Returns an `Array` with the results of running *block* against each element of the collection. + # + # ``` + # Set{1, 2, 3, 4, 5}.to_a { |i| i // 2 } # => [0, 1, 2] + # ``` + def to_a(& : T -> U) : Array(U) forall U + array = Array(U).new(size) + @hash.each_key do |key| + array << key + end + array + end + # Alias of `#to_s`. def inspect(io : IO) : Nil to_s(io) diff --git a/src/tuple.cr b/src/tuple.cr index d67578271363..2f9cde352e4f 100644 --- a/src/tuple.cr +++ b/src/tuple.cr @@ -539,10 +539,28 @@ struct Tuple to_s end - def to_a + # Returns an `Array` with all the elements in the tuple. + # + # ``` + # {1, 2, 3, 4, 5}.to_a # => [1, 2, 3, 4, 5] + # ``` + def to_a : Array(Union(*T)) + {% if compare_versions(Crystal::VERSION, "1.1.0") < 0 %} + to_a(&.itself.as(Union(*T))) + {% else %} + to_a(&.itself) + {% end %} + end + + # Returns an `Array` with the results of running *block* against each element of the tuple. + # + # ``` + # {1, 2, 3, 4, 5}).to_a { |i| i * 2 } # => [2, 4, 6, 8, 10] + # ``` + def to_a(& : Union(*T) -> _) Array(Union(*T)).build(size) do |buffer| {% for i in 0...T.size %} - buffer[{{i}}] = self[{{i}}] + buffer[{{i}}] = yield self[{{i}}] {% end %} size end From d1863053d82fa3a570fdf72eaccbc2d8d676876b Mon Sep 17 00:00:00 2001 From: syeopite <70992037+syeopite@users.noreply.github.com> Date: Sat, 30 Dec 2023 12:58:43 +0000 Subject: [PATCH 013/105] Add docs and explicit type restriction for indent parameter of JSON.build (#14140) --- src/json/builder.cr | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/json/builder.cr b/src/json/builder.cr index 9bc074f7c6ef..c1dc2c39c8e8 100644 --- a/src/json/builder.cr +++ b/src/json/builder.cr @@ -430,7 +430,10 @@ module JSON # end # string # => %<{"name":"foo","values":[1,2,3]}> # ``` - def self.build(indent = nil, &) + # + # Accepts an indent parameter which can either be an `Int` (number of spaces to indent) + # or a `String`, which will prefix each level with the string a corresponding amount of times. + def self.build(indent : String | Int | Nil = nil, &) String.build do |str| build(str, indent) do |json| yield json @@ -439,7 +442,7 @@ module JSON end # Writes JSON into the given `IO`. A `JSON::Builder` is yielded to the block. - def self.build(io : IO, indent = nil, &) : Nil + def self.build(io : IO, indent : String | Int | Nil = nil, &) : Nil builder = JSON::Builder.new(io) builder.indent = indent if indent builder.document do From 6e1c631fe24062c5288423b87c79752c07ae3b5b Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Sat, 30 Dec 2023 20:59:03 +0800 Subject: [PATCH 014/105] Do not use `pointerof(Path)` in the standard library (#14144) --- src/crystal/system/win32/path.cr | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/crystal/system/win32/path.cr b/src/crystal/system/win32/path.cr index a5e60db82576..06f9346a2bae 100644 --- a/src/crystal/system/win32/path.cr +++ b/src/crystal/system/win32/path.cr @@ -6,12 +6,16 @@ module Crystal::System::Path def self.home : String if home_path = ENV["USERPROFILE"]?.presence home_path - elsif LibC.SHGetKnownFolderPath(pointerof(LibC::FOLDERID_Profile), 0, nil, out path_ptr) == 0 - home_path, _ = String.from_utf16(path_ptr) - LibC.CoTaskMemFree(path_ptr) - home_path else - raise RuntimeError.from_winerror("SHGetKnownFolderPath") + # TODO: interpreter doesn't implement pointerof(Path)` yet + folderid = LibC::FOLDERID_Profile + if LibC.SHGetKnownFolderPath(pointerof(folderid), 0, nil, out path_ptr) == 0 + home_path, _ = String.from_utf16(path_ptr) + LibC.CoTaskMemFree(path_ptr) + home_path + else + raise RuntimeError.from_winerror("SHGetKnownFolderPath") + end end end end From 24d2c57ea2f61e51dfa6093e24ce13ec9636949c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Sat, 30 Dec 2023 13:59:47 +0100 Subject: [PATCH 015/105] Update distribution-scripts (#14136) --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 957f3979b110..39ae49d81ee3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -8,7 +8,7 @@ parameters: distribution-scripts-version: description: "Git ref for version of https://github.com/crystal-lang/distribution-scripts/" type: string - default: "e15cbd3b6b3e1bac1b16905f1b1a15ba6ae4e554" + default: "535aedb8b09d77caaa1583700f371cd04343b7e8" previous_crystal_base_url: description: "Prefix for URLs to Crystal bootstrap compiler" type: string From f39413637e4ae805f6ce6b95474deec243589a87 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 31 Dec 2023 12:08:03 +0100 Subject: [PATCH 016/105] Update GH Actions to v4 (#14120) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/aarch64.yml | 12 ++++++------ .github/workflows/interpreter.yml | 4 ++-- .github/workflows/win.yml | 6 +++--- .github/workflows/win_build_portable.yml | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/aarch64.yml b/.github/workflows/aarch64.yml index 2671fe5d61d6..da252904fa37 100644 --- a/.github/workflows/aarch64.yml +++ b/.github/workflows/aarch64.yml @@ -18,7 +18,7 @@ jobs: with: args: make crystal - name: Upload Crystal executable - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: crystal-aarch64-musl path: | @@ -32,7 +32,7 @@ jobs: - name: Download Crystal source uses: actions/checkout@v4 - name: Download Crystal executable - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: crystal-aarch64-musl - name: Mark downloaded compiler as executable @@ -49,7 +49,7 @@ jobs: - name: Download Crystal source uses: actions/checkout@v4 - name: Download Crystal executable - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: crystal-aarch64-musl - name: Mark downloaded compiler as executable @@ -69,7 +69,7 @@ jobs: with: args: make crystal - name: Upload Crystal executable - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: crystal-aarch64-gnu path: | @@ -83,7 +83,7 @@ jobs: - name: Download Crystal source uses: actions/checkout@v4 - name: Download Crystal executable - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: crystal-aarch64-gnu - name: Mark downloaded compiler as executable @@ -100,7 +100,7 @@ jobs: - name: Download Crystal source uses: actions/checkout@v4 - name: Download Crystal executable - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: crystal-aarch64-gnu - name: Mark downloaded compiler as executable diff --git a/.github/workflows/interpreter.yml b/.github/workflows/interpreter.yml index a034a9f5b410..2cd37d4b6579 100644 --- a/.github/workflows/interpreter.yml +++ b/.github/workflows/interpreter.yml @@ -33,7 +33,7 @@ jobs: run: make interpreter=1 release=1 - name: Upload compiler artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: crystal-interpreter path: | @@ -52,7 +52,7 @@ jobs: - uses: actions/checkout@v4 - name: Download compiler artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: crystal-interpreter path: .build/ diff --git a/.github/workflows/win.yml b/.github/workflows/win.yml index 90ed0e0c980d..da66d568835a 100644 --- a/.github/workflows/win.yml +++ b/.github/workflows/win.yml @@ -252,7 +252,7 @@ jobs: uses: actions/checkout@v4 - name: Download Crystal executable - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: crystal path: build @@ -303,7 +303,7 @@ jobs: uses: actions/checkout@v4 - name: Download Crystal executable - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: crystal-release path: etc/win-ci/portable @@ -329,7 +329,7 @@ jobs: iscc.exe crystal.iss - name: Upload Crystal installer - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: crystal-installer path: etc/win-ci/Output/crystal-setup.exe diff --git a/.github/workflows/win_build_portable.yml b/.github/workflows/win_build_portable.yml index 21d849c2dcf0..6222aaee3055 100644 --- a/.github/workflows/win_build_portable.yml +++ b/.github/workflows/win_build_portable.yml @@ -144,7 +144,7 @@ jobs: cp README.md crystal/ - name: Upload Crystal binaries - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ inputs.release && 'crystal-release' || 'crystal' }} path: crystal From 6d177399d437bc6cbafa9305dd69a22a8e74e559 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Sun, 31 Dec 2023 19:08:24 +0800 Subject: [PATCH 017/105] Fix interpreter specs on Windows (#14145) --- spec/compiler/interpreter/lib_spec.cr | 24 +++++++++++++++++---- spec/compiler/interpreter/spec_helper.cr | 1 + src/compiler/crystal/interpreter/context.cr | 5 +++++ 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/spec/compiler/interpreter/lib_spec.cr b/spec/compiler/interpreter/lib_spec.cr index 98e1da7fd294..2c1798645645 100644 --- a/spec/compiler/interpreter/lib_spec.cr +++ b/spec/compiler/interpreter/lib_spec.cr @@ -2,6 +2,22 @@ require "./spec_helper" require "../loader/spec_helper" +private def ldflags + {% if flag?(:win32) %} + "/LIBPATH:#{SPEC_CRYSTAL_LOADER_LIB_PATH} sum.lib" + {% else %} + "-L#{SPEC_CRYSTAL_LOADER_LIB_PATH} -lsum" + {% end %} +end + +private def ldflags_with_backtick + {% if flag?(:win32) %} + "/LIBPATH:#{SPEC_CRYSTAL_LOADER_LIB_PATH} `powershell.exe -C Write-Host -NoNewline sum.lib`" + {% else %} + "-L#{SPEC_CRYSTAL_LOADER_LIB_PATH} -l`echo sum`" + {% end %} +end + describe Crystal::Repl::Interpreter do context "variadic calls" do before_all do @@ -11,7 +27,7 @@ describe Crystal::Repl::Interpreter do it "promotes float" do interpret(<<-CRYSTAL).should eq 3.5 - @[Link(ldflags: "-L#{SPEC_CRYSTAL_LOADER_LIB_PATH} -lsum")] + @[Link(ldflags: #{ldflags.inspect})] lib LibSum fun sum_float(count : Int32, ...) : Float32 end @@ -22,7 +38,7 @@ describe Crystal::Repl::Interpreter do it "promotes int" do interpret(<<-CRYSTAL).should eq 5 - @[Link(ldflags: "-L#{SPEC_CRYSTAL_LOADER_LIB_PATH} -lsum")] + @[Link(ldflags: #{ldflags.inspect})] lib LibSum fun sum_int(count : Int32, ...) : Int32 end @@ -33,7 +49,7 @@ describe Crystal::Repl::Interpreter do it "promotes enum" do interpret(<<-CRYSTAL).should eq 5 - @[Link(ldflags: "-L#{SPEC_CRYSTAL_LOADER_LIB_PATH} -lsum")] + @[Link(ldflags: #{ldflags.inspect})] lib LibSum fun sum_int(count : Int32, ...) : Int32 end @@ -63,7 +79,7 @@ describe Crystal::Repl::Interpreter do it "expands ldflags" do interpret(<<-CRYSTAL).should eq 4 - @[Link(ldflags: "-L#{SPEC_CRYSTAL_LOADER_LIB_PATH} -l`echo sum`")] + @[Link(ldflags: #{ldflags_with_backtick.inspect})] lib LibSum fun simple_sum_int(a : Int32, b : Int32) : Int32 end diff --git a/spec/compiler/interpreter/spec_helper.cr b/spec/compiler/interpreter/spec_helper.cr index c3b0dcaca8cd..e6aeb240674c 100644 --- a/spec/compiler/interpreter/spec_helper.cr +++ b/spec/compiler/interpreter/spec_helper.cr @@ -5,6 +5,7 @@ require "compiler/crystal/interpreter/*" def interpret(code, *, prelude = "primitives", file = __FILE__, line = __LINE__) if prelude == "primitives" context, value = interpret_with_context(code) + context.loader?.try &.close_all value.value else interpret_in_separate_process(code, prelude, file: file, line: line) diff --git a/src/compiler/crystal/interpreter/context.cr b/src/compiler/crystal/interpreter/context.cr index f4a4444e105c..94456b4cec0e 100644 --- a/src/compiler/crystal/interpreter/context.cr +++ b/src/compiler/crystal/interpreter/context.cr @@ -46,6 +46,9 @@ class Crystal::Repl::Context def initialize(@program : Program) @program.flags << "interpreted" + {% if flag?(:win32) %} + @program.flags << "preview_dll" + {% end %} @gc_references = [] of Void* @@ -392,6 +395,8 @@ class Crystal::Repl::Context @id_to_type[id] end + getter? loader : Loader? + getter(loader : Loader) { lib_flags = program.lib_flags # Execute and expand `subcommands`. From 866d51d42bdd25839b0c0010fb96948fd795c2d9 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Sun, 31 Dec 2023 19:08:33 +0800 Subject: [PATCH 018/105] Support `-dynamic.lib` in Windows interpreter (#14143) --- spec/compiler/loader/msvc_spec.cr | 26 ++++++++++++++++++++++++++ spec/compiler/loader/spec_helper.cr | 4 ++-- src/compiler/crystal/loader/msvc.cr | 11 ++++++++--- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/spec/compiler/loader/msvc_spec.cr b/spec/compiler/loader/msvc_spec.cr index fedb21c352c4..5893d29aee02 100644 --- a/spec/compiler/loader/msvc_spec.cr +++ b/spec/compiler/loader/msvc_spec.cr @@ -125,4 +125,30 @@ describe Crystal::Loader do end end end + + describe "lib suffix" do + before_all do + FileUtils.mkdir_p(SPEC_CRYSTAL_LOADER_LIB_PATH) + end + + after_all do + FileUtils.rm_rf(SPEC_CRYSTAL_LOADER_LIB_PATH) + end + + it "respects -dynamic" do + build_c_dynlib(compiler_datapath("loader", "foo.c"), lib_name: "foo-dynamic") + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH] of String) + loader.load_library?("foo").should be_true + ensure + loader.close_all if loader + end + + it "ignores -static" do + build_c_dynlib(compiler_datapath("loader", "foo.c"), lib_name: "bar-static") + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH] of String) + loader.load_library?("bar").should be_false + ensure + loader.close_all if loader + end + end end diff --git a/spec/compiler/loader/spec_helper.cr b/spec/compiler/loader/spec_helper.cr index 282af7871f81..0db69dc19752 100644 --- a/spec/compiler/loader/spec_helper.cr +++ b/spec/compiler/loader/spec_helper.cr @@ -2,8 +2,8 @@ require "spec" SPEC_CRYSTAL_LOADER_LIB_PATH = File.join(SPEC_TEMPFILE_PATH, "loader") -def build_c_dynlib(c_filename, target_dir = SPEC_CRYSTAL_LOADER_LIB_PATH) - o_filename = File.join(target_dir, Crystal::Loader.library_filename(File.basename(c_filename, ".c"))) +def build_c_dynlib(c_filename, *, lib_name = nil, target_dir = SPEC_CRYSTAL_LOADER_LIB_PATH) + o_filename = File.join(target_dir, Crystal::Loader.library_filename(lib_name || File.basename(c_filename, ".c"))) {% if flag?(:msvc) %} o_basename = o_filename.rchop(".lib") diff --git a/src/compiler/crystal/loader/msvc.cr b/src/compiler/crystal/loader/msvc.cr index bf0b5c74a36f..d4b899db0e87 100644 --- a/src/compiler/crystal/loader/msvc.cr +++ b/src/compiler/crystal/loader/msvc.cr @@ -60,7 +60,7 @@ class Crystal::Loader result end - private def self.search_library(libname, search_paths, extra_suffix) + protected def self.search_library(libname, search_paths, extra_suffix) if ::Path::SEPARATORS.any? { |separator| libname.includes?(separator) } libname = File.expand_path(libname) library_path = library_filename(libname) @@ -106,7 +106,7 @@ class Crystal::Loader end def self.library_filename(libname : String) : String - "#{libname}.lib" + "#{libname.rchop(".lib")}.lib" end def find_symbol?(name : String) : Handle? @@ -149,8 +149,13 @@ class Crystal::Loader load_library?(libname) || raise LoadError.from_winerror "cannot find #{Loader.library_filename(libname)}" end + def load_library?(libname : String) : Bool + library_path = Loader.search_library(libname, @search_paths, "-dynamic") + !library_path.nil? && load_file?(library_path) + end + private def open_library(path : String) - # TODO: respect Crystal::LIBRARY_RPATH (#13490) + # TODO: respect Crystal::LIBRARY_RPATH (#13490), or `@[Link(dll:)]`'s search order LibC.LoadLibraryExW(System.to_wstr(path), nil, 0) end From 4b5ef59994ed776e46fdfc23e16f1aa885632f67 Mon Sep 17 00:00:00 2001 From: George Dietrich <george@dietrich.app> Date: Mon, 1 Jan 2024 09:53:39 -0500 Subject: [PATCH 019/105] Add reference to book how merging macro expansion and call docs (#14139) --- src/compiler/crystal/macros.cr | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/compiler/crystal/macros.cr b/src/compiler/crystal/macros.cr index 983af69ae4b7..90c802bad25e 100644 --- a/src/compiler/crystal/macros.cr +++ b/src/compiler/crystal/macros.cr @@ -442,6 +442,8 @@ module Crystal::Macros # Returns a `MacroId` that contains the documentation comments attached to this node, or an empty `MacroId` if there are none. # Each line is prefixed with a `#` character to allow the output to be used directly within another node's documentation comment. # + # A common use case is combining this method with the `@caller` macro instance variable in order to allow [merging macro expansion and call comments](https://crystal-lang.org/reference/syntax_and_semantics/macros/index.html#merging-expansion-and-call-comments). + # # WARNING: The return value will be empty when executed outside of the `crystal docs` command. def doc_comment : MacroId end From 6bfc90dfaf5a3f36926b0c4d139691216fd843cf Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Mon, 1 Jan 2024 22:53:46 +0800 Subject: [PATCH 020/105] Support absolute paths in `CRYSTAL_INTERPRETER_LOADER_INFO` (#14147) --- src/compiler/crystal/interpreter/context.cr | 12 ++++-------- src/compiler/crystal/loader/msvc.cr | 16 +++++++++++++++- src/compiler/crystal/loader/unix.cr | 1 + 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/compiler/crystal/interpreter/context.cr b/src/compiler/crystal/interpreter/context.cr index 94456b4cec0e..d597810b36de 100644 --- a/src/compiler/crystal/interpreter/context.cr +++ b/src/compiler/crystal/interpreter/context.cr @@ -410,13 +410,6 @@ class Crystal::Repl::Context args.delete("-lgc") Crystal::Loader.parse(args).tap do |loader| - if ENV["CRYSTAL_INTERPRETER_LOADER_INFO"]?.presence - STDERR.puts "Crystal::Loader loaded libraries:" - loader.loaded_libraries.each do |path| - STDERR.puts " #{path}" - end - end - # FIXME: Part 2: This is a workaround for initial integration of the interpreter: # We append a handle to the current executable (i.e. the compiler program) # to the loader's handle list. This gives the loader access to all the symbols in the compiler program, @@ -426,7 +419,10 @@ class Crystal::Repl::Context loader.load_current_program_handle if ENV["CRYSTAL_INTERPRETER_LOADER_INFO"]?.presence - STDERR.puts " current program handle" + STDERR.puts "Crystal::Loader loaded libraries:" + loader.loaded_libraries.each do |path| + STDERR.puts " #{path}" + end end end } diff --git a/src/compiler/crystal/loader/msvc.cr b/src/compiler/crystal/loader/msvc.cr index d4b899db0e87..e9fdc9af5bbd 100644 --- a/src/compiler/crystal/loader/msvc.cr +++ b/src/compiler/crystal/loader/msvc.cr @@ -139,7 +139,7 @@ class Crystal::Loader return false unless handle @handles << handle - @loaded_libraries << dll + @loaded_libraries << (module_filename(handle) || dll) end true @@ -162,6 +162,7 @@ class Crystal::Loader def load_current_program_handle if LibC.GetModuleHandleExW(0, nil, out hmodule) != 0 @handles << hmodule + @loaded_libraries << (Process.executable_path || "current program handle") end end @@ -172,6 +173,19 @@ class Crystal::Loader @handles.clear end + private def module_filename(handle) + Crystal::System.retry_wstr_buffer do |buffer, small_buf| + len = LibC.GetModuleFileNameW(handle, buffer, buffer.size) + if 0 < len < buffer.size + break String.from_utf16(buffer[0, len]) + elsif small_buf && len == buffer.size + next 32767 # big enough. 32767 is the maximum total path length of UNC path. + else + break nil + end + end + end + # Returns a list of directories used as the default search paths. # # For MSVC this is simply the contents of the `LIB` environment variable, diff --git a/src/compiler/crystal/loader/unix.cr b/src/compiler/crystal/loader/unix.cr index 4c202231d7e6..39fef6e0c318 100644 --- a/src/compiler/crystal/loader/unix.cr +++ b/src/compiler/crystal/loader/unix.cr @@ -120,6 +120,7 @@ class Crystal::Loader def load_current_program_handle if program_handle = LibC.dlopen(nil, LibC::RTLD_LAZY | LibC::RTLD_GLOBAL) @handles << program_handle + @loaded_libraries << (Process.executable_path || "current program handle") end end From f3de7b43714e8ff771fcf838ed6accc27c21da55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Mon, 1 Jan 2024 20:52:06 +0100 Subject: [PATCH 021/105] Merge `samples/.gitignore` into `.gitignore` (#14134) --- .gitignore | 1 + Makefile | 1 - Makefile.win | 1 - samples/.gitignore | 1 - 4 files changed, 1 insertion(+), 3 deletions(-) delete mode 100644 samples/.gitignore diff --git a/.gitignore b/.gitignore index 5d74450c533f..987e8a649620 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ # Build artifacts /.build/ +/samples/.build/ /docs/ /src/llvm/ext/llvm_ext.o /src/llvm/ext/llvm_ext.obj diff --git a/Makefile b/Makefile index 7e8070d16921..4682c7aebec9 100644 --- a/Makefile +++ b/Makefile @@ -182,7 +182,6 @@ install_docs: docs ## Install docs at DESTDIR cp -av docs "$(DATADIR)/docs" cp -av samples "$(DATADIR)/examples" - rm -rf "$(DATADIR)/examples/.gitignore" .PHONY: uninstall_docs uninstall_docs: ## Uninstall docs from DESTDIR diff --git a/Makefile.win b/Makefile.win index e2b18741657e..da1d9fc8328a 100644 --- a/Makefile.win +++ b/Makefile.win @@ -171,7 +171,6 @@ install_docs: docs ## Install docs at prefix $(call MKDIR,"$(DATADIR)") $(call INSTALLDIR,docs,"$(DATADIR)\docs") $(call INSTALLDIR,samples,"$(DATADIR)\examples") - $(call RM,"$(DATADIR)\examples\.gitignore") .PHONY: uninstall_docs uninstall_docs: ## Uninstall docs from prefix diff --git a/samples/.gitignore b/samples/.gitignore deleted file mode 100644 index 0e03e15f2420..000000000000 --- a/samples/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/.build/ From d15435dc822be0b18a7ff2bf823a564d9ef5cc13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Mon, 1 Jan 2024 20:52:13 +0100 Subject: [PATCH 022/105] Fix `make clean` to remove zipped manpages (#14135) --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 4682c7aebec9..2a7f9d43869f 100644 --- a/Makefile +++ b/Makefile @@ -229,6 +229,7 @@ man/%.gz: man/% .PHONY: clean clean: clean_crystal ## Clean up built directories and files rm -rf $(LLVM_EXT_OBJ) + rm -rf man/*.gz .PHONY: clean_crystal clean_crystal: ## Clean up crystal built files From 316422fb800826994c4623edb837f57b74f7a361 Mon Sep 17 00:00:00 2001 From: "Brian J. Cardiff" <bcardiff@gmail.com> Date: Tue, 2 Jan 2024 10:34:25 -0300 Subject: [PATCH 023/105] Add Crystal::Repl#parse_and_interpret (#14138) * Add Crystal::Repl#parse_and_interpret * Use single EvalResult type * skip if without_interpreter --- spec/compiler/crystal/tools/repl_spec.cr | 20 ++++++++++++++++++++ src/compiler/crystal/interpreter/repl.cr | 24 +++++++++++++++++------- 2 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 spec/compiler/crystal/tools/repl_spec.cr diff --git a/spec/compiler/crystal/tools/repl_spec.cr b/spec/compiler/crystal/tools/repl_spec.cr new file mode 100644 index 000000000000..3a1e1275ef12 --- /dev/null +++ b/spec/compiler/crystal/tools/repl_spec.cr @@ -0,0 +1,20 @@ +{% skip_file if flag?(:without_interpreter) %} + +require "../../../spec_helper" + +private def success_value(result : Crystal::Repl::EvalResult) : Crystal::Repl::Value + result.warnings.infos.should be_empty + result.value.should_not be_nil +end + +describe Crystal::Repl do + it "can parse and evaluate snippets" do + repl = Crystal::Repl.new + repl.prelude = "primitives" + repl.load_prelude + + success_value(repl.parse_and_interpret("1 + 2")).value.should eq(3) + success_value(repl.parse_and_interpret("def foo; 1 + 2; end")).value.should eq(nil) + success_value(repl.parse_and_interpret("foo")).value.should eq(3) + end +end diff --git a/src/compiler/crystal/interpreter/repl.cr b/src/compiler/crystal/interpreter/repl.cr index 93b3a6cef65c..2c009a89e87d 100644 --- a/src/compiler/crystal/interpreter/repl.cr +++ b/src/compiler/crystal/interpreter/repl.cr @@ -22,15 +22,13 @@ class Crystal::Repl when "exit" break when .presence - parser = new_parser(expression) - parser.warnings.report(STDOUT) + result = parse_and_interpret(expression) + result.warnings.report(STDOUT) - node = parser.parse - next unless node + next unless result.value - value = interpret(node) print " => " - puts SyntaxHighlighter::Colorize.highlight!(value.to_s) + puts SyntaxHighlighter::Colorize.highlight!(result.value.to_s) end rescue ex : EscapingException print "Unhandled exception: " @@ -44,6 +42,18 @@ class Crystal::Repl end end + record EvalResult, value : Value?, warnings : WarningCollection + + def parse_and_interpret(expression : String) : EvalResult + parser = new_parser(expression) + + node = parser.parse + return EvalResult.new(value: nil, warnings: parser.warnings) unless node + + value = interpret(node) + return EvalResult.new(value: value, warnings: parser.warnings) + end + def run_file(filename, argv) @interpreter.argv = argv @@ -68,7 +78,7 @@ class Crystal::Repl interpret(exps) end - private def load_prelude + def load_prelude node = parse_prelude interpret_and_exit_on_error(node) From 8be53a45193465b0aef87d1623eb9de736daa53f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Wed, 3 Jan 2024 11:07:39 +0100 Subject: [PATCH 024/105] Revert "Add compile time string interpolation for char/num/bool constants" (#14155) --- .../normalize/string_interpolation_spec.cr | 39 ------------- .../crystal/semantic/cleanup_transformer.cr | 55 +++++++++++-------- 2 files changed, 31 insertions(+), 63 deletions(-) diff --git a/spec/compiler/normalize/string_interpolation_spec.cr b/spec/compiler/normalize/string_interpolation_spec.cr index 1347792170b0..f92e6c2a200f 100644 --- a/spec/compiler/normalize/string_interpolation_spec.cr +++ b/spec/compiler/normalize/string_interpolation_spec.cr @@ -52,43 +52,4 @@ describe "Normalize: string interpolation" do string = node.should be_a(StringLiteral) string.value.should eq("hello world") end - - it "replaces char constant" do - result = semantic(%( - def String.interpolation(*args); ""; end - - OBJ = 'l' - - "hello wor\#{OBJ}d" - )) - node = result.node.as(Expressions).last - string = node.should be_a(StringLiteral) - string.value.should eq("hello world") - end - - it "replaces number constant" do - result = semantic(%( - def String.interpolation(*args); ""; end - - OBJ = 9_f32 - - "nine as a float: \#{OBJ}" - )) - node = result.node.as(Expressions).last - string = node.should be_a(StringLiteral) - string.value.should eq("nine as a float: 9.0") - end - - it "replaces boolean constant" do - result = semantic(%( - def String.interpolation(*args); ""; end - - OBJ = false - - "boolean false: \#{OBJ}" - )) - node = result.node.as(Expressions).last - string = node.should be_a(StringLiteral) - string.value.should eq("boolean false: false") - end end diff --git a/src/compiler/crystal/semantic/cleanup_transformer.cr b/src/compiler/crystal/semantic/cleanup_transformer.cr index ad1b570f0cbd..bc3084429ed3 100644 --- a/src/compiler/crystal/semantic/cleanup_transformer.cr +++ b/src/compiler/crystal/semantic/cleanup_transformer.cr @@ -256,28 +256,35 @@ module Crystal end def transform(node : StringInterpolation) - string = node.expressions.join do |exp| - if !(transformed_piece = solve_string_interpolation_expression(exp)).nil? - # Valid piece, continue joining - next transformed_piece - elsif expanded = node.expanded - # Invalid piece, transform expansion and exit early - return expanded.transform(self) - else - # No expansion, return self - return node - end + # See if we can solve all the pieces to string literals. + # If that's the case, we can replace the entire interpolation + # with a single string literal. + pieces = node.expressions.dup + solve_string_interpolation_expressions(pieces) + + if pieces.all?(StringLiteral) + string = pieces.join(&.as(StringLiteral).value) + string_literal = StringLiteral.new(string).at(node) + string_literal.type = @program.string + return string_literal + end + + if expanded = node.expanded + return expanded.transform(self) end - string_literal = StringLiteral.new(string).at(node) - string_literal.type = @program.string - string_literal + node end - # Returns the solved piece for string interpolation, if it can find one. - # For example, this returns a String when given a StringLiteral. - private def solve_string_interpolation_expression(piece : ASTNode) : String | Char | Number::Primitive | Bool | Nil - # Check for ExpandableNode happens first in case any nodes below are - # updated to be ExpandableNodes themselves. + private def solve_string_interpolation_expressions(pieces : Array(ASTNode)) + pieces.each_with_index do |piece, i| + replacement = solve_string_interpolation_expression(piece) + next unless replacement + + pieces[i] = replacement + end + end + + private def solve_string_interpolation_expression(piece : ASTNode) : StringLiteral? if piece.is_a?(ExpandableNode) if expanded = piece.expanded return solve_string_interpolation_expression(expanded) @@ -287,13 +294,13 @@ module Crystal case piece when Path if target_const = piece.target_const - solve_string_interpolation_expression(target_const.value) + return solve_string_interpolation_expression(target_const.value) end - when StringLiteral then piece.value - when CharLiteral then piece.value - when NumberLiteral then piece.to_number - when BoolLiteral then piece.value + when StringLiteral + return piece end + + nil end def transform(node : ExpandableNode) From 382041cc25b025f74938b131ac0960012faeb60f Mon Sep 17 00:00:00 2001 From: Julien Portalier <julien@portalier.com> Date: Wed, 3 Jan 2024 12:54:57 +0100 Subject: [PATCH 025/105] Fix: segfault with next boehm gc (after v8.2.4) (#14130) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Johannes Müller <straightshoota@gmail.com> --- src/gc/boehm.cr | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/gc/boehm.cr b/src/gc/boehm.cr index 6c1ff5020cbf..8278f33b8e94 100644 --- a/src/gc/boehm.cr +++ b/src/gc/boehm.cr @@ -22,13 +22,17 @@ {% if flag?(:freebsd) || flag?(:dragonfly) %} @[Link("gc-threaded")] {% else %} - @[Link("gc")] + @[Link("gc", pkg_config: "bdw-gc")] {% end %} {% if compare_versions(Crystal::VERSION, "1.11.0-dev") >= 0 %} @[Link(dll: "gc.dll")] {% end %} lib LibGC + {% unless flag?(:win32) %} + VERSION = {{ `pkg-config bdw-gc --silence-errors --modversion || printf "0.0.0"`.chomp.stringify }} + {% end %} + alias Int = LibC::Int alias SizeT = LibC::SizeT {% if flag?(:win32) && flag?(:bits64) %} @@ -96,7 +100,7 @@ lib LibGC fun push_all_eager = GC_push_all_eager(bottom : Void*, top : Void*) - {% if flag?(:preview_mt) || flag?(:win32) %} + {% if flag?(:preview_mt) || flag?(:win32) || compare_versions(VERSION, "8.2.0") >= 0 %} fun get_my_stackbottom = GC_get_my_stackbottom(sb : StackBase*) : ThreadHandle fun set_stackbottom = GC_set_stackbottom(th : ThreadHandle, sb : StackBase*) : ThreadHandle {% else %} @@ -277,10 +281,11 @@ module GC # :nodoc: def self.current_thread_stack_bottom - {% if flag?(:preview_mt) || flag?(:win32) %} + {% if LibGC.has_method?(:get_my_stackbottom) %} th = LibGC.get_my_stackbottom(out sb) {th, sb.mem_base} {% else %} + # support for legacy gc releases {Pointer(Void).null, LibGC.stackbottom} {% end %} end @@ -292,10 +297,11 @@ module GC sb.mem_base = stack_bottom LibGC.set_stackbottom(thread_handle, pointerof(sb)) end - {% elsif flag?(:win32) %} + {% elsif LibGC.has_method?(:set_stackbottom) %} # this is necessary because Boehm GC does _not_ use `GC_stackbottom` on - # Windows when pushing all threads' stacks; instead `GC_set_stackbottom` - # must be used to associate the new bottom with the running thread + # Windows when pushing all threads' stacks; it also started crashing on + # Linux with libgc after v8.2.4; instead `GC_set_stackbottom` must be used + # to associate the new bottom with the running thread def self.set_stackbottom(stack_bottom : Void*) sb = LibGC::StackBase.new sb.mem_base = stack_bottom @@ -303,6 +309,7 @@ module GC LibGC.set_stackbottom(nil, pointerof(sb)) end {% else %} + # support for legacy gc releases def self.set_stackbottom(stack_bottom : Void*) LibGC.stackbottom = stack_bottom end From 5e13683544b0a06aa41a41b5f6d22fd56b8d7bcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Wed, 3 Jan 2024 12:55:21 +0100 Subject: [PATCH 026/105] Fix compiler error message for broken source file (#14157) --- src/compiler/crystal/command.cr | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/compiler/crystal/command.cr b/src/compiler/crystal/command.cr index 69b4ab2d221c..97bf46feb663 100644 --- a/src/compiler/crystal/command.cr +++ b/src/compiler/crystal/command.cr @@ -627,6 +627,8 @@ class Crystal::Command filename = File.expand_path(filename) Compiler::Source.new(filename, File.read(filename)) end + rescue exc : IO::Error + error exc end private def setup_simple_compiler_options(compiler, opts) From 07c09cfae7fbe81bf9b6012de4b074c25c5bb686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Wed, 3 Jan 2024 19:44:52 +0100 Subject: [PATCH 027/105] Add optimization levels to manpage (#14162) --- man/crystal.1 | 49 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/man/crystal.1 b/man/crystal.1 index 5f08ce29d07e..508b2ab44cb9 100644 --- a/man/crystal.1 +++ b/man/crystal.1 @@ -140,8 +140,14 @@ Don't do code generation, just parse the file. Specify filename of output. .It Fl -prelude Specify prelude to use. The default one initializes the garbage collector. You can also use --prelude=empty to use no preludes. This can be useful for checking code generation for a specific source code file. +.It Fl O Ar LEVEL +Optimization mode: 0 (default), 1, 2, 3. See +.Sy OPTIMIZATIONS +for details. .It Fl -release -Turn on optimizations for the generated code, which are disabled by default. +Compile in release mode. Equivalent to +.Fl O3 +.Fl -single-module .It Fl -error-trace Show full stack trace. Disabled by default, as the full trace usually makes error messages less readable and not always deliver relevant information. .It Fl s, -stats @@ -152,6 +158,9 @@ Print statistics about the progress for the current build. Print statistics about the execution time. .It Fl -single-module Generate a single LLVM module. +By default, one LLVM module is created for each type in a program. +.Fl -release +implies this option. .It Fl -threads Ar NUM Maximum number of threads to use for code generation. The default is 8 threads. .It Fl -target Ar TRIPLE @@ -265,8 +274,14 @@ Generate the output without any symbolic debug symbols. Define a compile-time flag. This is useful to conditionally define types, methods, or commands based on flags available at compile time. The default flags are from the target triple given with --target-triple or the hosts default, if none is given. .It Fl -error-trace Show full error trace. +.It Fl O Ar LEVEL +Optimization mode: 0 (default), 1, 2, 3. See +.Sy OPTIMIZATIONS +for details. .It Fl -release -Turn on optimizations for the generated code, which are disabled by default. +Compile in release mode. Equivalent to +.Fl O3 +.Fl -single-module .It Fl s, -stats Print statistics about the different compiler stages for the current build. Output time and used memory for each compiler process. .It Fl p, -progress @@ -326,8 +341,14 @@ Generate the output without any symbolic debug symbols. Define a compile-time flag. This is useful to conditionally define types, methods, or commands based on flags available at compile time. The default flags are from the target triple given with --target-triple or the hosts default, if none is given. .It Fl -error-trace Show full error trace. +.It Fl O Ar LEVEL +Optimization mode: 0 (default), 1, 2, 3. See +.Sy OPTIMIZATIONS +for details. .It Fl -release -Turn on optimizations for the generated code, which are disabled by default. +Compile in release mode. Equivalent to +.Fl O3 +.Fl -single-module .It Fl s, -stats Print statistics about the different compiler stages for the current build. Output time and used memory for each compiler process. .It Fl p, -progress @@ -410,6 +431,28 @@ Show help. Option --help or -h can also be added to each command for command-spe Show version. .El . +.Sh OPTIMIZATIONS +.Bl -tag -width "12345678" -compact +.Pp +The optimization level specifies the codegen effort for producing optimal code. +It's a trade-off between compilation performance (decreasing per optimization level) and runtime performance (increasing per optimization level). +.Pp +Production builds should usually have the highest optimization level. +Best results are achieved with +.Fl -release + which also implies +.Fl -single-module +.Pp +.It +.It Fl O0 +No optimization (default) +.It Fl O1 +Low optimization +.It Fl O2 +Middle optimization +.It Fl O3 +High optimization +. .Sh ENVIRONMENT VARIABLES .Bl -tag -width "12345678" -compact .Pp From 2afc7c1cda5295950e045bf00c665552eff3196c Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Thu, 4 Jan 2024 18:06:46 +0800 Subject: [PATCH 028/105] Fix codegen error when discarding `is_a?` or `responds_to?`'s result (#14148) --- spec/compiler/codegen/is_a_spec.cr | 10 ++++++++++ spec/compiler/codegen/responds_to_spec.cr | 12 ++++++++++++ src/compiler/crystal/codegen/codegen.cr | 11 +++++++---- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/spec/compiler/codegen/is_a_spec.cr b/spec/compiler/codegen/is_a_spec.cr index 97d72378be42..86ed570afe20 100644 --- a/spec/compiler/codegen/is_a_spec.cr +++ b/spec/compiler/codegen/is_a_spec.cr @@ -45,6 +45,16 @@ describe "Codegen: is_a?" do run("1.is_a?(Object)").to_b.should be_true end + it "doesn't error if result is discarded (#14113)" do + run(<<-CRYSTAL).to_i.should eq(1) + class Foo + end + + (Foo.new || "").is_a?(Foo) + 1 + CRYSTAL + end + it "evaluate method on filtered type" do run("a = 1; a = 'a'; if a.is_a?(Char); a.ord; else; 0; end").to_i.chr.should eq('a') end diff --git a/spec/compiler/codegen/responds_to_spec.cr b/spec/compiler/codegen/responds_to_spec.cr index e10f024f3682..0384c3e0d838 100644 --- a/spec/compiler/codegen/responds_to_spec.cr +++ b/spec/compiler/codegen/responds_to_spec.cr @@ -51,6 +51,18 @@ describe "Codegen: responds_to?" do )).to_b.should be_false end + it "doesn't error if result is discarded (#14113)" do + run(<<-CRYSTAL).to_i.should eq(1) + class Foo + def foo + end + end + + (Foo.new || "").responds_to?(:foo) + 1 + CRYSTAL + end + it "works with virtual type" do run(%( class Foo diff --git a/src/compiler/crystal/codegen/codegen.cr b/src/compiler/crystal/codegen/codegen.cr index f5c35db9d65a..651afa44ca27 100644 --- a/src/compiler/crystal/codegen/codegen.cr +++ b/src/compiler/crystal/codegen/codegen.cr @@ -1471,12 +1471,15 @@ module Crystal def codegen_type_filter(node, &) accept node.obj - obj_type = node.obj.type - type_id = type_id @last, obj_type - filtered_type = yield(obj_type).not_nil! + if @needs_value + obj_type = node.obj.type + + type_id = type_id @last, obj_type + filtered_type = yield(obj_type).not_nil! - @last = match_type_id obj_type, filtered_type, type_id + @last = match_type_id obj_type, filtered_type, type_id + end false end From e1fefe19d6296152a45d1edfc99c669fa74e05df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Thu, 4 Jan 2024 11:06:54 +0100 Subject: [PATCH 029/105] Add `unreachable` options to manpage (#14164) --- man/crystal.1 | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/man/crystal.1 b/man/crystal.1 index 508b2ab44cb9..bfdb364d932b 100644 --- a/man/crystal.1 +++ b/man/crystal.1 @@ -411,9 +411,49 @@ to specify the cursor position. The format for the cursor position is file:line: .It Cm types Show type of main variables of file. .It Cm unreachable -Show methods that are never called. The output is a list of lines with columns -separated by tab. The first column is the location of the def, the second column -its reference name and the third column is the length in lines. +Show methods that are never called. The text output is a list of lines with columns +separated by tab. + +.Pp +Output fields: + +.Bl -tag -width "1234567890" -compact +.Pp +.It Cm count +sum of all calls to this method (only with +.Fl -tallies + option; otherwise skipped) +.It Cm location +pathname, line and column, all separated by colon +.It Cm name +.It Cm lines +length of the def in lines +.It Cm annotations +.El + +.Pp +Options: +.Bl -tag -width "12345678" -compact +.Pp +.It Fl D Ar FLAG, Fl -define= Ar FLAG +Define a compile-time flag. This is useful to conditionally define types, methods, or commands based on flags available at compile time. The default flags are from the target triple given with --target-triple or the hosts default, if none is given. +.It Fl f Ar FORMAT, Fl -format= Ar FORMAT +Output format 'text' (default), 'json', or 'csv'. +.It Fl -tallies +Print reachable methods and their call counts as well. +.It Fl -check +Exit with error if there is any unreachable code. +.It Fl i Ar PATH, Fl -include= Ar PATH +Include path in output. +.It Fl e Ar PATH, Fl -exclude= Ar PATH +Exclude path in output (default: +.Sy lib +). +.It Fl -error-trace +Show full error trace. +.It Fl -prelude +Specify prelude to use. The default one initializes the garbage collector. You can also use --prelude=empty to use no preludes. This can be useful for checking code generation for a specific source code file. +.El .El .Pp .It From cb333fed295e929a26979b2336e2326c26520290 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Thu, 4 Jan 2024 11:07:04 +0100 Subject: [PATCH 030/105] Configure Renovate Bot to add label `topic:infrastructure/ci` on PRs (#14166) --- .github/renovate.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/renovate.json b/.github/renovate.json index 4e18234dc0ec..39932ec1f648 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -12,5 +12,6 @@ "matchManagers": ["github-actions"], "schedule": ["after 5am and before 8am on Wednesday"] } - ] + ], + "labels": ["topic:infrastructure/ci"] } From 194ffb2b1db671052320e5221ed5cad462c49069 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 13:45:54 +0100 Subject: [PATCH 031/105] Update GH Actions (#14165) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/win.yml | 14 +++++++------- .github/workflows/win_build_portable.yml | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/win.yml b/.github/workflows/win.yml index da66d568835a..c80dcfce8fb6 100644 --- a/.github/workflows/win.yml +++ b/.github/workflows/win.yml @@ -18,7 +18,7 @@ jobs: git config --global core.autocrlf false - name: Enable Developer Command Prompt - uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 # v1.12.1 + uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 - name: Download Crystal source uses: actions/checkout@v4 @@ -77,7 +77,7 @@ jobs: key: win-openssl-libs-3.1.0-${{ hashFiles('etc/win-ci/build-openssl.ps1') }}-msvc - name: Set up NASM if: steps.cache-openssl.outputs.cache-hit != 'true' - uses: ilammy/setup-nasm@321e6ed62a1fc77024a3bd853deb33645e8b22c4 # v1.4.0 + uses: ilammy/setup-nasm@13cbeb366c45c4379d3478cdcbadd8295feb5028 # v1.5.1 - name: Build OpenSSL if: steps.cache-openssl.outputs.cache-hit != 'true' run: .\etc\win-ci\build-openssl.ps1 -BuildTree deps\openssl -Version 3.1.0 @@ -90,7 +90,7 @@ jobs: git config --global core.autocrlf false - name: Enable Developer Command Prompt - uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 # v1.12.1 + uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 - name: Download Crystal source uses: actions/checkout@v4 @@ -159,7 +159,7 @@ jobs: key: win-openssl-dlls-3.1.0-${{ hashFiles('etc/win-ci/build-openssl.ps1') }}-msvc - name: Set up NASM if: steps.cache-openssl-dlls.outputs.cache-hit != 'true' - uses: ilammy/setup-nasm@321e6ed62a1fc77024a3bd853deb33645e8b22c4 # v1.4.0 + uses: ilammy/setup-nasm@13cbeb366c45c4379d3478cdcbadd8295feb5028 # v1.5.1 - name: Build OpenSSL if: steps.cache-openssl-dlls.outputs.cache-hit != 'true' run: .\etc\win-ci\build-openssl.ps1 -BuildTree deps\openssl -Version 3.1.0 -Dynamic @@ -168,7 +168,7 @@ jobs: runs-on: windows-2022 steps: - name: Enable Developer Command Prompt - uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 # v1.12.1 + uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 - name: Cache LLVM id: cache-llvm-libs @@ -212,7 +212,7 @@ jobs: git config --global core.autocrlf false - name: Enable Developer Command Prompt - uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 # v1.12.1 + uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 - name: Download Crystal source uses: actions/checkout@v4 @@ -246,7 +246,7 @@ jobs: git config --global core.autocrlf false - name: Enable Developer Command Prompt - uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 # v1.12.1 + uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 - name: Download Crystal source uses: actions/checkout@v4 diff --git a/.github/workflows/win_build_portable.yml b/.github/workflows/win_build_portable.yml index 6222aaee3055..960606628a9e 100644 --- a/.github/workflows/win_build_portable.yml +++ b/.github/workflows/win_build_portable.yml @@ -19,7 +19,7 @@ jobs: git config --global core.autocrlf false - name: Enable Developer Command Prompt - uses: ilammy/msvc-dev-cmd@cec98b9d092141f74527d0afa6feb2af698cfe89 # v1.12.1 + uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 - name: Install Crystal uses: crystal-lang/install-crystal@v1 From f435981237c527701d1c7c68027a30339ecd40db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Thu, 4 Jan 2024 13:46:11 +0100 Subject: [PATCH 032/105] Fix formatting in manpage (#14163) --- man/crystal.1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/man/crystal.1 b/man/crystal.1 index bfdb364d932b..3a2a3d4a1b2a 100644 --- a/man/crystal.1 +++ b/man/crystal.1 @@ -130,7 +130,7 @@ Specify a specific CPU to generate code for. This will pass a -mcpu flag to LLVM Passing --mcpu native will pass the host CPU name to tune performance for the host. .It Fl -mattr Ar CPU Override or control specific attributes of the target, such as whether SIMD operations are enabled or not. The default set of attributes is set by the current CPU. This will pass a -mattr flag to LLVM, and is only intended to be used for cross-compilation. For a list of available attributes, invoke "llvm-as < /dev/null | llc -march=xyz -mattr=help". -.It Fl -mcmodel default|kernel|small|medium|large +.It Fl -mcmodel Ar default|kernel|small|medium|large Specifies a specific code model to generate code for. This will pass a --code-model flag to LLVM. .It Fl -no-color Disable colored output. @@ -407,7 +407,7 @@ flag. .It Cm implementations Show implementations for a given call. Use .Fl -cursor -to specify the cursor position. The format for the cursor position is file:line:column. + to specify the cursor position. The format for the cursor position is file:line:column. .It Cm types Show type of main variables of file. .It Cm unreachable @@ -493,7 +493,7 @@ Middle optimization .It Fl O3 High optimization . -.Sh ENVIRONMENT VARIABLES +.Sh ENVIRONMENT\ VARIABLES .Bl -tag -width "12345678" -compact .Pp .It From 3e05a2af1782c9951d2133d6c1951fa23c1f4ef0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Thu, 4 Jan 2024 13:46:23 +0100 Subject: [PATCH 033/105] Embed logo image into repository and upgrade to SVG (#14137) --- Makefile | 1 + README.md | 2 +- doc/assets/crystal-born-and-raised.svg | 248 +++++++++++++++++++++++++ 3 files changed, 250 insertions(+), 1 deletion(-) create mode 100644 doc/assets/crystal-born-and-raised.svg diff --git a/Makefile b/Makefile index 2a7f9d43869f..461ee56bd5e5 100644 --- a/Makefile +++ b/Makefile @@ -127,6 +127,7 @@ samples: ## Build example programs docs: ## Generate standard library documentation $(call check_llvm_config) ./bin/crystal docs src/docs_main.cr $(DOCS_OPTIONS) --project-name=Crystal --project-version=$(CRYSTAL_VERSION) --source-refname=$(CRYSTAL_CONFIG_BUILD_COMMIT) + cp -av doc/ docs/ .PHONY: crystal crystal: $(O)/crystal ## Build the compiler diff --git a/README.md b/README.md index 67bf031ed038..70577b822fdc 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ --- -[![Crystal - Born and raised at Manas](https://cloud.githubusercontent.com/assets/209371/13291809/022e2360-daf8-11e5-8be7-d02c1c8b38fb.png)](https://manas.tech/) +[![Crystal - Born and raised at Manas](doc/assets/crystal-born-and-raised.svg)](https://manas.tech/) Crystal is a programming language with the following goals: diff --git a/doc/assets/crystal-born-and-raised.svg b/doc/assets/crystal-born-and-raised.svg new file mode 100644 index 000000000000..98e85d9b46b2 --- /dev/null +++ b/doc/assets/crystal-born-and-raised.svg @@ -0,0 +1,248 @@ +<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="640" viewBox="-120 -30 710 260"> +<defs> + <style> + .crystal { + fill: #020202; + } + @media(prefers-color-scheme: dark) { + .crystal { + fill: #FDFDFD; + } + } + </style> +</defs> +<g fill="#787878"> + <path d="M8.5482,186.8324v-21.2803h6.7861c1.3071,0,2.4331,0.1289,3.3784,0.3867 + c0.9453,0.2568,1.7227,0.623,2.3315,1.0986c0.6089,0.4746,1.0591,1.0566,1.3516,1.7451c0.292,0.6875,0.438,1.4619,0.438,2.3232 + c0,0.5254-0.0815,1.0303-0.2451,1.5146c-0.1631,0.4854-0.4106,0.9355-0.7427,1.3516c-0.3315,0.416-0.7476,0.7871-1.2471,1.1143 + c-0.5,0.3262-1.0869,0.5938-1.7598,0.8018c1.5542,0.3066,2.7271,0.8662,3.5195,1.6777c0.792,0.8125,1.188,1.8809,1.188,3.208 + c0,0.9004-0.166,1.7227-0.4976,2.4648c-0.332,0.7422-0.8169,1.3809-1.4556,1.916c-0.6382,0.5342-1.4204,0.9482-2.3462,1.2393 + c-0.9258,0.293-1.9824,0.4385-3.1704,0.4385H8.5482z M11.4291,175.0863h3.8018c0.8115,0,1.5146-0.0898,2.1084-0.2676 + c0.5942-0.1777,1.0864-0.4258,1.4775-0.7422c0.3911-0.3174,0.6807-0.7002,0.8687-1.1514c0.188-0.4502,0.2822-0.9424,0.2822-1.4775 + c0-1.2471-0.3765-2.1631-1.1284-2.7471c-0.7524-0.584-1.9209-0.876-3.5049-0.876h-3.9053V175.0863z M11.4291,177.1351v7.4102 + h4.6035c0.8218,0,1.5269-0.0938,2.1162-0.2822c0.5889-0.1875,1.0737-0.4531,1.4551-0.7939 + c0.3809-0.3418,0.6611-0.748,0.8389-1.2178c0.1782-0.4707,0.2676-0.9873,0.2676-1.5518c0-1.0996-0.3887-1.9678-1.1655-2.6064 + c-0.7773-0.6387-1.9531-0.958-3.5273-0.958H11.4291z"/> + <path d="M33.4364,171.5521c1.0986,0,2.0908,0.1826,2.9771,0.5488s1.6387,0.8867,2.2573,1.5596 + s1.0938,1.4873,1.4258,2.4424c0.3315,0.9561,0.4971,2.0225,0.4971,3.2002c0,1.1885-0.1655,2.2578-0.4971,3.208 + c-0.332,0.9502-0.8071,1.7627-1.4258,2.4355s-1.3711,1.1904-2.2573,1.5518s-1.8784,0.542-2.9771,0.542 + c-1.0991,0-2.0918-0.1807-2.9775-0.542c-0.8862-0.3613-1.6411-0.8789-2.2646-1.5518c-0.624-0.6729-1.104-1.4854-1.4404-2.4355 + c-0.3369-0.9502-0.5049-2.0195-0.5049-3.208c0-1.1777,0.168-2.2441,0.5049-3.2002c0.3364-0.9551,0.8164-1.7695,1.4404-2.4424 + c0.6235-0.6729,1.3784-1.1934,2.2646-1.5596C31.3446,171.7348,32.3373,171.5521,33.4364,171.5521z M33.4364,184.976 + c1.4849,0,2.5933-0.4971,3.3262-1.4922c0.7324-0.9951,1.0991-2.3838,1.0991-4.165c0-1.792-0.3667-3.1885-1.0991-4.1885 + c-0.7329-0.999-1.8413-1.499-3.3262-1.499c-0.7529,0-1.4062,0.1279-1.9604,0.3857c-0.5547,0.2578-1.0171,0.6289-1.3887,1.1133 + c-0.3711,0.4854-0.6484,1.082-0.8315,1.79s-0.2744,1.5068-0.2744,2.3984c0,0.8906,0.0913,1.6875,0.2744,2.3906 + s0.4604,1.2939,0.8315,1.7744c0.3716,0.4805,0.834,0.8486,1.3887,1.1064C32.0302,184.848,32.6835,184.976,33.4364,184.976z"/> + <path d="M43.8607,186.8324v-15.043h1.5146c0.2871,0,0.4854,0.0547,0.5942,0.1631 + c0.1089,0.1094,0.1831,0.2969,0.2227,0.5645l0.1782,2.3467c0.5146-1.0498,1.1509-1.8691,1.9082-2.458s1.646-0.8838,2.6655-0.8838 + c0.416,0,0.792,0.0469,1.1289,0.1416c0.3364,0.0938,0.6479,0.2246,0.9355,0.3936l-0.3418,1.9746 + c-0.0693,0.248-0.2227,0.3711-0.4604,0.3711c-0.1387,0-0.3516-0.0469-0.6382-0.1406c-0.2876-0.0938-0.6885-0.1416-1.2031-0.1416 + c-0.9209,0-1.6904,0.2676-2.3091,0.8018c-0.6187,0.5352-1.1362,1.3125-1.5518,2.332v9.5781H43.8607z"/> + <path d="M55.83,186.8324v-15.043h1.5742c0.376,0,0.6138,0.1836,0.7129,0.5498l0.208,1.6328 + c0.6533-0.7227,1.3833-1.3066,2.1904-1.752c0.8066-0.4453,1.7397-0.668,2.7988-0.668c0.8218,0,1.5469,0.1357,2.1758,0.4082 + c0.6284,0.2725,1.1533,0.6582,1.5742,1.1582c0.4204,0.5,0.7397,1.1016,0.9575,1.8037c0.2178,0.7031,0.3267,1.4805,0.3267,2.332 + v9.5781h-2.6431v-9.5781c0-1.1387-0.2598-2.0225-0.7798-2.6504c-0.5195-0.6289-1.314-0.9434-2.3833-0.9434 + c-0.7822,0-1.5122,0.1885-2.1904,0.5645s-1.3047,0.8857-1.8784,1.5293v11.0781H55.83z"/> + <path d="M89.1234,186.8324h-1.1729c-0.2578,0-0.4653-0.0391-0.624-0.1191c-0.1582-0.0791-0.2622-0.2471-0.3115-0.5049 + l-0.2969-1.3955c-0.3965,0.3564-0.7822,0.6758-1.1587,0.958c-0.376,0.2822-0.772,0.5195-1.188,0.7129 + c-0.4155,0.1924-0.8589,0.3389-1.3291,0.4375s-0.9927,0.1484-1.5664,0.1484c-0.5845,0-1.1313-0.082-1.6411-0.2451 + c-0.5098-0.1641-0.9526-0.4102-1.3291-0.7383c-0.3765-0.3271-0.6758-0.7422-0.8984-1.2441s-0.334-1.0947-0.334-1.7803 + c0-0.5957,0.1636-1.1699,0.4902-1.7217c0.3267-0.5508,0.8535-1.04,1.5815-1.4678c0.7275-0.4268,1.6802-0.7773,2.8584-1.0498 + c1.1782-0.2734,2.6187-0.4102,4.3213-0.4102v-1.1807c0-1.1758-0.25-2.0645-0.75-2.667s-1.2397-0.9043-2.2197-0.9043 + c-0.644,0-1.186,0.082-1.6265,0.2451s-0.8218,0.3467-1.1431,0.5488c-0.3218,0.2031-0.5991,0.3867-0.832,0.5498 + c-0.2324,0.1631-0.4629,0.2451-0.6904,0.2451c-0.1782,0-0.334-0.0469-0.4678-0.1406c-0.1333-0.0947-0.2402-0.2109-0.3193-0.3496 + l-0.4751-0.8467c0.8315-0.8018,1.7275-1.4004,2.688-1.7969c0.96-0.3955,2.0244-0.5938,3.1929-0.5938 + c0.8413,0,1.5889,0.1387,2.2422,0.416s1.2026,0.6631,1.6484,1.1582c0.4453,0.4951,0.7817,1.0938,1.0098,1.7969 + c0.2275,0.7031,0.3413,1.4756,0.3413,2.3164V186.8324z M82.2631,185.2142c0.4648,0,0.8906-0.0469,1.2769-0.1416 + c0.3862-0.0938,0.75-0.2275,1.0918-0.4014c0.3413-0.1729,0.668-0.3828,0.98-0.6309c0.3115-0.2471,0.6162-0.5293,0.9131-0.8467 + v-3.1035c-1.2178,0-2.2524,0.0771-3.1035,0.2314c-0.8516,0.1553-1.5444,0.3564-2.0791,0.6055s-0.9233,0.543-1.1655,0.8809 + c-0.2427,0.3389-0.3638,0.7168-0.3638,1.1357c0,0.3984,0.064,0.7412,0.1929,1.0303c0.1284,0.2891,0.3018,0.5254,0.5195,0.71 + c0.2178,0.1836,0.4756,0.3184,0.7725,0.4033C81.5946,185.1713,81.9164,185.2142,82.2631,185.2142z"/> + <path d="M93.1327,186.8324v-15.043h1.5742c0.376,0,0.6138,0.1836,0.7129,0.5498l0.208,1.6328 + c0.6533-0.7227,1.3833-1.3066,2.1904-1.752c0.8066-0.4453,1.7397-0.668,2.7988-0.668c0.8218,0,1.5469,0.1357,2.1758,0.4082 + c0.6284,0.2725,1.1533,0.6582,1.5742,1.1582c0.4204,0.5,0.7397,1.1016,0.9575,1.8037c0.2178,0.7031,0.3267,1.4805,0.3267,2.332 + v9.5781h-2.6431v-9.5781c0-1.1387-0.2598-2.0225-0.7798-2.6504c-0.5195-0.6289-1.314-0.9434-2.3833-0.9434 + c-0.7822,0-1.5122,0.1885-2.1904,0.5645s-1.3047,0.8857-1.8784,1.5293v11.0781H93.1327z"/> + <path d="M120.2343,186.8324c-0.3765,0-0.6143-0.1826-0.7129-0.5498l-0.2378-1.8262 + c-0.6436,0.7822-1.3784,1.4082-2.2051,1.8789c-0.8267,0.4697-1.7744,0.7051-2.8438,0.7051c-0.8613,0-1.6436-0.166-2.3462-0.498 + c-0.7031-0.3311-1.3022-0.8184-1.7969-1.4619c-0.4951-0.6436-0.8765-1.4453-1.1436-2.4062 + c-0.2676-0.96-0.4009-2.0635-0.4009-3.3115c0-1.1084,0.1484-2.1406,0.4453-3.0957c0.2969-0.9561,0.7251-1.7842,1.2847-2.4873 + c0.5591-0.7031,1.2397-1.2549,2.042-1.6562c0.8018-0.4014,1.7124-0.6016,2.7324-0.6016c0.9204,0,1.7075,0.1562,2.3608,0.4678 + c0.6533,0.3125,1.2373,0.75,1.7524,1.3145v-8.3457h2.6431v21.874H120.2343z M115.1107,184.9017 + c0.8613,0,1.6162-0.1982,2.2646-0.5938s1.2451-0.9551,1.7896-1.6777v-7.2773c-0.4854-0.6533-1.0171-1.1104-1.5967-1.373 + c-0.5791-0.2627-1.2202-0.3936-1.9229-0.3936c-1.4058,0-2.4849,0.5-3.2373,1.5s-1.1284,2.4258-1.1284,4.2764 + c0,0.9805,0.084,1.8193,0.2524,2.5176c0.168,0.6973,0.4155,1.2715,0.7422,1.7227c0.3267,0.4502,0.728,0.7793,1.2031,0.9873 + S114.497,184.9017,115.1107,184.9017z"/> + <path d="M131.9799,186.8324v-15.043h1.5146c0.2871,0,0.4854,0.0547,0.5942,0.1631 + c0.1089,0.1094,0.1831,0.2969,0.2227,0.5645l0.1782,2.3467c0.5146-1.0498,1.1509-1.8691,1.9082-2.458s1.646-0.8838,2.6655-0.8838 + c0.416,0,0.792,0.0469,1.1289,0.1416c0.3364,0.0938,0.6479,0.2246,0.9355,0.3936l-0.3418,1.9746 + c-0.0693,0.248-0.2227,0.3711-0.4604,0.3711c-0.1387,0-0.3516-0.0469-0.6382-0.1406c-0.2876-0.0938-0.6885-0.1416-1.2031-0.1416 + c-0.9209,0-1.6904,0.2676-2.3091,0.8018c-0.6187,0.5352-1.1362,1.3125-1.5518,2.332v9.5781H131.9799z"/> + <path d="M154.433,186.8324h-1.1729c-0.2578,0-0.4653-0.0391-0.624-0.1191c-0.1582-0.0791-0.2622-0.2471-0.3115-0.5049 + l-0.2969-1.3955c-0.3965,0.3564-0.7822,0.6758-1.1587,0.958c-0.376,0.2822-0.772,0.5195-1.188,0.7129 + c-0.4155,0.1924-0.8589,0.3389-1.3291,0.4375s-0.9927,0.1484-1.5664,0.1484c-0.5845,0-1.1313-0.082-1.6411-0.2451 + c-0.5098-0.1641-0.9526-0.4102-1.3291-0.7383c-0.3765-0.3271-0.6758-0.7422-0.8984-1.2441s-0.334-1.0947-0.334-1.7803 + c0-0.5957,0.1636-1.1699,0.4902-1.7217c0.3267-0.5508,0.8535-1.04,1.5815-1.4678c0.7275-0.4268,1.6802-0.7773,2.8584-1.0498 + c1.1782-0.2734,2.6187-0.4102,4.3213-0.4102v-1.1807c0-1.1758-0.25-2.0645-0.75-2.667s-1.2397-0.9043-2.2197-0.9043 + c-0.644,0-1.186,0.082-1.6265,0.2451s-0.8218,0.3467-1.1431,0.5488c-0.3218,0.2031-0.5991,0.3867-0.832,0.5498 + c-0.2324,0.1631-0.4629,0.2451-0.6904,0.2451c-0.1782,0-0.334-0.0469-0.4678-0.1406c-0.1333-0.0947-0.2402-0.2109-0.3193-0.3496 + l-0.4751-0.8467c0.8315-0.8018,1.7275-1.4004,2.688-1.7969c0.96-0.3955,2.0244-0.5938,3.1929-0.5938 + c0.8413,0,1.5889,0.1387,2.2422,0.416s1.2026,0.6631,1.6484,1.1582c0.4453,0.4951,0.7817,1.0938,1.0098,1.7969 + c0.2275,0.7031,0.3413,1.4756,0.3413,2.3164V186.8324z M147.5727,185.2142c0.4648,0,0.8906-0.0469,1.2769-0.1416 + c0.3862-0.0938,0.75-0.2275,1.0918-0.4014c0.3413-0.1729,0.668-0.3828,0.98-0.6309c0.3115-0.2471,0.6162-0.5293,0.9131-0.8467 + v-3.1035c-1.2178,0-2.2524,0.0771-3.1035,0.2314c-0.8516,0.1553-1.5444,0.3564-2.0791,0.6055s-0.9233,0.543-1.1655,0.8809 + c-0.2427,0.3389-0.3638,0.7168-0.3638,1.1357c0,0.3984,0.064,0.7412,0.1929,1.0303c0.1284,0.2891,0.3018,0.5254,0.5195,0.71 + c0.2178,0.1836,0.4756,0.3184,0.7725,0.4033C146.9042,185.1713,147.226,185.2142,147.5727,185.2142z"/> + <path d="M161.977,167.0668c0,0.2578-0.0522,0.498-0.1562,0.7207s-0.2427,0.4209-0.4155,0.5938 + c-0.1733,0.1738-0.374,0.3096-0.6016,0.4082c-0.228,0.0996-0.4702,0.1484-0.7275,0.1484c-0.2578,0-0.4976-0.0488-0.7202-0.1484 + c-0.2231-0.0986-0.4209-0.2344-0.5942-0.4082c-0.1733-0.1729-0.3096-0.3711-0.4082-0.5938 + c-0.0991-0.2227-0.1484-0.4629-0.1484-0.7207c0-0.2568,0.0493-0.502,0.1484-0.7344c0.0986-0.2334,0.2349-0.4355,0.4082-0.6094 + c0.1733-0.1729,0.3711-0.3096,0.5942-0.4082c0.2227-0.0986,0.4624-0.1484,0.7202-0.1484c0.2573,0,0.4995,0.0498,0.7275,0.1484 + c0.2275,0.0986,0.4282,0.2354,0.6016,0.4082c0.1729,0.1738,0.3115,0.376,0.4155,0.6094 + C161.9247,166.5648,161.977,166.81,161.977,167.0668z M161.3827,171.7894v15.043h-2.6431v-15.043H161.3827z"/> + <path d="M174.6586,174.2689c-0.1191,0.2178-0.3022,0.3271-0.5498,0.3271c-0.1484,0-0.3169-0.0547-0.5049-0.1631 + c-0.188-0.1094-0.418-0.2305-0.6904-0.3643s-0.5967-0.2568-0.9727-0.3711c-0.3765-0.1133-0.8218-0.1709-1.3364-0.1709 + c-0.4453,0-0.8467,0.0576-1.2026,0.1709c-0.3564,0.1143-0.6611,0.2695-0.9136,0.4678s-0.4453,0.4287-0.5791,0.6904 + c-0.1338,0.2627-0.2002,0.5469-0.2002,0.8535c0,0.3867,0.1113,0.708,0.334,0.9658s0.5171,0.4805,0.8833,0.668 + c0.3662,0.1885,0.7822,0.3545,1.2476,0.498s0.9429,0.2969,1.4331,0.46c0.4897,0.1631,0.9673,0.3438,1.4331,0.542 + c0.4648,0.1982,0.8809,0.4453,1.2471,0.7422s0.6611,0.6611,0.8838,1.0918s0.334,0.9482,0.334,1.5518 + c0,0.6934-0.124,1.334-0.3711,1.9229c-0.2476,0.5898-0.6138,1.0996-1.0991,1.5303c-0.4849,0.4297-1.0791,0.7695-1.7817,1.0166 + c-0.7031,0.2471-1.5146,0.3711-2.4355,0.3711c-1.0493,0-2-0.1709-2.8511-0.5117c-0.8516-0.3418-1.5742-0.7803-2.168-1.3145 + l0.6235-1.0098c0.0791-0.1289,0.1729-0.2275,0.2822-0.2969c0.1089-0.0693,0.2524-0.1045,0.4307-0.1045s0.3662,0.0693,0.564,0.208 + c0.1982,0.1387,0.4385,0.292,0.7202,0.4609c0.2822,0.168,0.624,0.3213,1.0249,0.46s0.9033,0.208,1.5073,0.208 + c0.5146,0,0.9653-0.0674,1.3511-0.2002c0.3862-0.1338,0.708-0.3145,0.9653-0.542c0.2573-0.2285,0.4478-0.4902,0.5718-0.7871 + c0.1235-0.2979,0.1855-0.6143,0.1855-0.9512c0-0.415-0.1113-0.7588-0.334-1.0312s-0.5176-0.5049-0.8838-0.6982 + s-0.7847-0.3613-1.2544-0.5049c-0.4707-0.1436-0.9507-0.2949-1.4404-0.4531c-0.4902-0.1582-0.9707-0.3389-1.4409-0.542 + s-0.8887-0.458-1.2544-0.7646c-0.3667-0.3066-0.6611-0.6855-0.8838-1.1357c-0.2227-0.4512-0.334-0.998-0.334-1.6416 + c0-0.5742,0.1187-1.126,0.3564-1.6553c0.2373-0.5293,0.584-0.9951,1.0396-1.3965c0.4551-0.4004,1.0146-0.7197,1.6777-0.957 + c0.6631-0.2383,1.4204-0.3564,2.272-0.3564c0.9902,0,1.8789,0.1553,2.6655,0.4678c0.7871,0.3115,1.4678,0.7402,2.042,1.2842 + L174.6586,174.2689z"/> + <path d="M184.89,171.5521c0.9009,0,1.7324,0.1504,2.4946,0.4521c0.7622,0.3027,1.4204,0.7383,1.9751,1.3076 + c0.5542,0.5693,0.9878,1.2715,1.2993,2.1084c0.312,0.8369,0.4678,1.7891,0.4678,2.8584c0,0.416-0.0444,0.6934-0.1338,0.832 + c-0.0889,0.1387-0.2573,0.208-0.5049,0.208h-10.0088c0.02,0.9502,0.1484,1.7764,0.3862,2.4795s0.5645,1.29,0.98,1.7598 + c0.416,0.4707,0.9106,0.8223,1.4849,1.0547s1.2178,0.3486,1.9307,0.3486c0.6631,0,1.2349-0.0762,1.7153-0.2305 + c0.48-0.1533,0.8931-0.3193,1.2397-0.4971c0.3467-0.1787,0.6362-0.3438,0.8687-0.498c0.2329-0.1533,0.4331-0.2295,0.6016-0.2295 + c0.2178,0,0.3862,0.084,0.5049,0.252l0.7427,0.9658c-0.3267,0.3955-0.7178,0.7402-1.1733,1.0322s-0.9429,0.5322-1.4624,0.7197 + c-0.52,0.1885-1.0571,0.3291-1.6113,0.4229c-0.5547,0.0947-1.104,0.1416-1.6484,0.1416c-1.0396,0-1.9976-0.1758-2.8735-0.5273 + s-1.6333-0.8662-2.272-1.5439c-0.6387-0.6787-1.1362-1.5176-1.4927-2.5176c-0.356-1-0.5342-2.1484-0.5342-3.4453 + c0-1.0488,0.1606-2.0293,0.4824-2.9404c0.3218-0.9102,0.7847-1.7002,1.3887-2.3682c0.6035-0.668,1.3413-1.1934,2.2124-1.5742 + S183.8007,171.5521,184.89,171.5521z M184.9491,173.4975c-1.2769,0-2.2817,0.3682-3.0142,1.1064 + c-0.7329,0.7373-1.188,1.7588-1.3662,3.0664h8.1821c0-0.6143-0.084-1.1758-0.2524-1.6855s-0.4155-0.9502-0.7427-1.3223 + c-0.3267-0.3711-0.7251-0.6582-1.1953-0.8613C186.0902,173.599,185.5531,173.4975,184.9491,173.4975z"/> + <path d="M205.0854,186.8324c-0.3765,0-0.6143-0.1826-0.7129-0.5498l-0.2378-1.8262 + c-0.6436,0.7822-1.3784,1.4082-2.2051,1.8789c-0.8267,0.4697-1.7744,0.7051-2.8438,0.7051c-0.8613,0-1.6436-0.166-2.3462-0.498 + c-0.7031-0.3311-1.3022-0.8184-1.7969-1.4619c-0.4951-0.6436-0.8765-1.4453-1.1436-2.4062 + c-0.2676-0.96-0.4009-2.0635-0.4009-3.3115c0-1.1084,0.1484-2.1406,0.4453-3.0957c0.2969-0.9561,0.7251-1.7842,1.2847-2.4873 + c0.5591-0.7031,1.2397-1.2549,2.042-1.6562c0.8018-0.4014,1.7124-0.6016,2.7324-0.6016c0.9204,0,1.7075,0.1562,2.3608,0.4678 + c0.6533,0.3125,1.2373,0.75,1.7524,1.3145v-8.3457h2.6431v21.874H205.0854z M199.9618,184.9017 + c0.8613,0,1.6162-0.1982,2.2646-0.5938s1.2451-0.9551,1.7896-1.6777v-7.2773c-0.4854-0.6533-1.0171-1.1104-1.5967-1.373 + c-0.5791-0.2627-1.2202-0.3936-1.9229-0.3936c-1.4058,0-2.4849,0.5-3.2373,1.5s-1.1284,2.4258-1.1284,4.2764 + c0,0.9805,0.084,1.8193,0.2524,2.5176c0.168,0.6973,0.4155,1.2715,0.7422,1.7227c0.3267,0.4502,0.728,0.7793,1.2031,0.9873 + S199.3481,184.9017,199.9618,184.9017z"/> + <path d="M227.8803,186.8324h-1.1738c-0.2578,0-0.4648-0.0391-0.623-0.1191c-0.1602-0.0791-0.2637-0.2471-0.3125-0.5049 + l-0.2969-1.3955c-0.3965,0.3564-0.7832,0.6758-1.1582,0.958c-0.377,0.2822-0.7734,0.5195-1.1875,0.7129 + c-0.416,0.1924-0.8594,0.3389-1.3301,0.4375s-0.9922,0.1484-1.5664,0.1484c-0.584,0-1.1309-0.082-1.6406-0.2451 + c-0.5098-0.1641-0.9531-0.4102-1.3301-0.7383c-0.375-0.3271-0.6758-0.7422-0.8984-1.2441s-0.334-1.0947-0.334-1.7803 + c0-0.5957,0.1641-1.1699,0.4902-1.7217c0.3262-0.5508,0.8535-1.04,1.582-1.4678c0.7266-0.4268,1.6797-0.7773,2.8594-1.0498 + c1.1777-0.2734,2.6172-0.4102,4.3203-0.4102v-1.1807c0-1.1758-0.25-2.0645-0.75-2.667s-1.2402-0.9043-2.2207-0.9043 + c-0.6426,0-1.1855,0.082-1.625,0.2451c-0.4414,0.1631-0.8223,0.3467-1.1445,0.5488c-0.3203,0.2031-0.5977,0.3867-0.8301,0.5498 + c-0.2344,0.1631-0.4629,0.2451-0.6914,0.2451c-0.1777,0-0.334-0.0469-0.4668-0.1406c-0.1348-0.0947-0.2402-0.2109-0.3203-0.3496 + l-0.4746-0.8467c0.832-0.8018,1.7266-1.4004,2.6875-1.7969c0.9609-0.3955,2.0254-0.5938,3.1934-0.5938 + c0.8398,0,1.5879,0.1387,2.2422,0.416c0.6523,0.2773,1.2031,0.6631,1.6484,1.1582s0.7812,1.0938,1.0098,1.7969 + c0.2266,0.7031,0.3418,1.4756,0.3418,2.3164V186.8324z M221.019,185.2142c0.4648,0,0.8906-0.0469,1.2773-0.1416 + c0.3848-0.0938,0.75-0.2275,1.0918-0.4014c0.3418-0.1729,0.668-0.3828,0.9785-0.6309c0.3125-0.2471,0.6172-0.5293,0.9141-0.8467 + v-3.1035c-1.2168,0-2.252,0.0771-3.1035,0.2314c-0.8516,0.1553-1.5449,0.3564-2.0781,0.6055 + c-0.5352,0.249-0.9238,0.543-1.166,0.8809c-0.2441,0.3389-0.3652,0.7168-0.3652,1.1357c0,0.3984,0.0645,0.7412,0.1934,1.0303 + s0.3027,0.5254,0.5195,0.71c0.2188,0.1836,0.4766,0.3184,0.7734,0.4033C220.351,185.1713,220.6713,185.2142,221.019,185.2142z"/> + <path d="M236.4472,187.0697c-1.187,0-2.1001-0.3311-2.7388-0.9951c-0.6387-0.6631-0.958-1.6182-0.958-2.8652v-9.207 + h-1.8115c-0.1582,0-0.292-0.0469-0.4014-0.1416c-0.1084-0.0938-0.1631-0.2393-0.1631-0.4375v-1.0547l2.4648-0.3115l0.6094-4.6484 + c0.0195-0.1484,0.084-0.2695,0.1924-0.3643c0.1094-0.0938,0.248-0.1406,0.416-0.1406h1.3369v5.1826h4.3062v1.916h-4.3062v9.0283 + c0,0.6338,0.1533,1.1045,0.46,1.4111c0.3062,0.3066,0.7026,0.46,1.188,0.46c0.2764,0,0.5166-0.0371,0.7197-0.1113 + s0.3789-0.1562,0.5273-0.2451s0.2744-0.1709,0.3789-0.2451c0.1035-0.0742,0.1953-0.1113,0.2744-0.1113 + c0.1387,0,0.2627,0.085,0.3711,0.2529l0.7725,1.2617c-0.4551,0.4258-1.0049,0.7598-1.6484,1.0029 + C237.7939,186.9486,237.1308,187.0697,236.4472,187.0697z"/> +</g> +<path fill="#787878" d="M293.0266,185.993h-2.6754v-6.6887l0,0c0-2.1738-1.7558-4.0132-4.0132-4.0132 + c-2.1738,0-4.0132,1.7558-4.0132,3.9296v1.3377h-2.6754v-1.3377l0,0l0,0l0,0c0-2.1738-1.7558-4.0132-4.0132-4.0132 + c-2.1738,0-4.0132,1.7558-4.0132,4.0132l0,0v1.3377h-2.6754v-13.1265h2.6754v6.6887c1.0869-0.8361,2.5083-1.3377,4.0132-1.3377 + c2.1738,0,4.0968,1.0033,5.351,2.6755c1.2541-1.5886,3.1771-2.6755,5.3509-2.6755c3.6788,0,6.6887,3.0099,6.6887,6.6887l0,0V185.993 + z M293.0266,170.0238h-6.6887l0,0c-1.8394,0-3.4279-0.7525-4.6821-1.923l1.923-1.923c0.7525,0.6689,1.6722,1.0869,2.7591,1.0869 + h6.6887V170.0238z M281.0706,156.73c11.0363,0,19.9824,8.9461,19.9824,19.9824s-8.9461,19.9824-19.9824,19.9824 + s-19.9824-8.9461-19.9824-19.9824S270.0343,156.73,281.0706,156.73 M281.0706,154.0546c-12.4576,0-22.6579,10.1166-22.6579,22.6579 + c0,12.4576,10.1166,22.6579,22.6579,22.6579c12.4576,0,22.6579-10.1166,22.6579-22.6579 + C303.7285,164.2548,293.5283,154.0546,281.0706,154.0546L281.0706,154.0546z M326.2192,171.7795l0.0836,1.6722 + c1.0033-1.2541,2.5083-1.923,4.4312-1.923c1.923,0,3.5116,0.7525,4.264,2.4246c1.0033-1.4213,2.5919-2.4246,4.7657-2.4246 + c3.1771,0,5.0165,1.6722,5.0165,5.4345v9.8658h-2.5919v-9.8658c0-2.5083-1.2541-3.2607-3.1771-3.2607 + c-2.0902,0-3.2607,1.4213-3.5115,3.1771v9.9494h-2.5919v-9.8658c0-2.341-1.2541-3.2607-3.1771-3.2607 + c-1.8394,0-2.9263,0.8361-3.4279,2.1738v10.9527h-2.5919v-15.0495H326.2192z M357.9904,186.829 + c-0.1672-0.3344-0.2508-1.0033-0.3344-1.5885c-1.0033,1.0033-2.4246,1.8394-4.264,1.8394c-3.0935,0-5.1001-1.923-5.1001-4.4312 + c0-3.2607,2.5919-4.9329,6.7723-4.9329h2.5919v-1.1705c0-1.7558-1.0869-2.9263-3.1771-2.9263c-1.923,0-3.2607,1.0869-3.2607,2.341 + h-2.5919c0-2.1738,2.341-4.4312,5.9362-4.4312c3.2607,0,5.6018,1.6722,5.6018,5.0165v7.0231c0,1.0033,0.1672,2.2574,0.5016,3.0935 + v0.2508h-2.6755V186.829z M357.5723,182.6486v-3.0935h-2.1738c-2.9263,0-4.5985,0.9197-4.5985,2.7591 + c0,1.4213,1.0033,2.5919,2.8427,2.5919C355.5657,184.8224,357.0707,183.7355,357.5723,182.6486z M366.602,171.7795l0.0836,1.923 + c1.0869-1.3377,2.5919-2.1738,4.5148-2.1738c2.9263,0,4.7657,1.5049,4.7657,5.4345v9.8658h-2.5919v-9.8658 + c0-2.341-1.0869-3.2607-3.0099-3.2607c-1.6722,0-2.9263,1.0033-3.6788,2.4246v10.7019h-2.5919v-15.0495H366.602z M389.1763,186.829 + c-0.1672-0.3344-0.2508-1.0033-0.3344-1.5885c-1.0033,1.0033-2.4247,1.8394-4.264,1.8394c-3.0935,0-5.1001-1.923-5.1001-4.4312 + c0-3.2607,2.5919-4.9329,6.7723-4.9329h2.5919v-1.1705c0-1.7558-1.0869-2.9263-3.1771-2.9263c-1.923,0-3.2607,1.0869-3.2607,2.341 + h-2.5919c0-2.1738,2.341-4.4312,5.9362-4.4312c3.2607,0,5.6017,1.6722,5.6017,5.0165v7.0231c0,1.0033,0.1672,2.2574,0.5016,3.0935 + v0.2508h-2.6755V186.829z M388.7582,182.6486v-3.0935h-2.1738c-2.9263,0-4.5984,0.9197-4.5984,2.7591 + c0,1.4213,1.0033,2.5919,2.8427,2.5919C386.7516,184.8224,388.173,183.7355,388.7582,182.6486z M400.6306,180.224 + c-3.3443-0.6689-5.4345-1.8394-5.4345-4.3476c0-2.341,2.1738-4.4312,5.5182-4.4312c3.5952,0,5.769,2.0902,5.769,4.6821h-2.5919 + c0-1.2541-1.0869-2.5919-3.1771-2.5919c-2.1738,0-3.0099,1.0869-3.0099,2.1738c0,1.1705,0.5853,1.6722,3.5115,2.341 + c3.6788,0.8361,5.351,2.0902,5.351,4.5148c0,2.5919-2.2574,4.4312-5.769,4.4312c-4.0132,0-6.187-2.4246-6.187-4.9329h2.5919 + c0.0836,2.0902,2.0066,2.8427,3.5952,2.8427c2.0902,0,3.2607-0.9197,3.2607-2.1738 + C404.0586,181.7289,403.5569,180.8929,400.6306,180.224z M411.6669,183.9028c1.0869,0,1.5885,0.6689,1.5885,1.5886 + c0,0.8361-0.5852,1.5049-1.5885,1.5049s-1.5886-0.6689-1.5886-1.5049C410.0784,184.5716,410.58,183.9028,411.6669,183.9028z + M420.9474,168.1844v3.5952h2.8427v2.0066h-2.8427v9.2805c0,1.5886,0.8361,1.8394,1.6722,1.8394 + c0.418,0,0.9197-0.0836,1.2541-0.1672v2.0902c-0.418,0.0836-1.0033,0.2508-2.0066,0.2508c-1.923,0-3.5116-1.0033-3.5116-4.0132 + v-9.2805h-2.7591v-2.0066h2.7591v-3.5952H420.9474z M426.1312,179.8059v-0.5853c0-4.9329,3.1771-7.692,6.6051-7.692 + c4.264,0,6.187,3.1771,6.187,7.3575v1.1705H428.723c0.0836,2.7591,1.7558,4.9329,4.4312,4.9329 + c1.8394,0,3.0099-0.8361,3.9296-2.0066l1.5886,1.2541c-0.9197,1.505-2.6755,2.9263-5.6854,2.9263 + C428.8066,187.0799,426.1312,184.07,426.1312,179.8059z M428.8066,177.9666h7.5247v-0.1672 + c-0.0836-2.0066-1.0033-4.0968-3.5952-4.0968C430.646,173.6189,429.1411,175.1239,428.8066,177.9666z M451.3809,182.0634h2.4247 + c-0.1672,2.6755-2.7591,5.0165-5.9362,5.0165c-4.5148,0-6.6887-3.4279-6.6887-7.5247v-0.5853c0-4.0132,2.1738-7.5247,6.6887-7.5247 + c3.5116,0,5.8526,2.341,6.0198,5.4346h-2.4247c-0.1672-1.8394-1.5049-3.3443-3.5952-3.3443c-3.1771,0-4.0968,2.7591-4.0968,5.3509 + v0.5853c0,2.6755,0.9197,5.4345,4.0968,5.4345C449.7087,184.9897,451.2137,183.7355,451.3809,182.0634z M459.2401,173.6189 + c1.0869-1.3377,2.5919-2.0902,4.4312-2.0902c2.9263,0,4.7657,1.5049,4.7657,5.4345v9.8658h-2.5919v-9.8658 + c0-2.341-1.0869-3.2607-3.0099-3.2607c-1.6722,0-2.9263,1.0033-3.6788,2.4246v10.7019h-2.5919v-21.3201h2.5919v8.11H459.2401z"/> +<g class="crystal"> + <path d="M166.9483,90.4383c-4.744,0-7.8521-1.4723-9.6516-4.2532 + c-1.6359-2.9445-2.6174-8.1793-2.6174-15.8678s0.8179-13.0869,2.6174-15.8678c1.7994-2.9445,4.9076-4.2532,9.6516-4.2532 + c5.3983,0,10.4695,0.1636,15.2135,0.4908l0.9815-7.8521c-4.5804-1.1451-9.9787-1.7994-16.195-1.7994 + c-8.5065,0-14.3956,2.1266-17.8309,6.5434c-3.4353,4.4168-5.2347,11.9418-5.2347,22.5748s1.6358,18.3216,5.2347,22.5749 + c3.4353,4.4168,9.3244,6.5434,17.8309,6.5434c7.0342,0,12.7597-0.6544,17.3401-2.1266l-0.9815-7.6885 + C179.3808,90.1111,173.8189,90.4383,166.9483,90.4383z"/> + <path d="M227.3114,75.0612c-1.4723-1.3087-2.9445-2.2902-4.5804-2.6174v-0.4908 + c3.7625-0.4908,6.5434-1.963,8.1793-4.2532c1.6358-2.2902,2.4538-5.7255,2.4538-9.9787c0-6.2163-1.4723-10.6331-4.4168-12.9233 + c-2.9445-2.2902-8.0157-3.5989-15.2135-3.5989c-8.8336,0-15.7043,0.1636-20.6118,0.6543v56.4371h10.1423V75.7156h10.1423 + c3.2717,0,5.5619,1.6359,6.5434,5.0712l4.5804,17.5037h10.9603l-5.0712-17.6673 + C229.7652,78.333,228.7837,76.3699,227.3114,75.0612z M213.4066,67.3727h-10.1423V49.7054h10.1423 + c3.5989,0,6.2163,0.6543,7.5249,1.7994c1.3087,1.1451,1.963,3.4353,1.963,7.0342c0,3.4353-0.6543,5.7255-1.963,7.0342 + C219.6229,66.7184,217.1691,67.3727,213.4066,67.3727z"/> + <polygon points="378.3012,42.0169 333.3151,42.0169 333.3151,50.687 350.4916,50.687 350.4916,98.454 + 360.7975,98.454 360.7975,50.687 378.3012,50.687 "/> + <path d="M406.2743,42.0169h-9.9787c-1.963,0-3.1081,0.9815-3.7625,2.781L375.6838,98.454h10.4695 + l4.5804-16.0314h20.939l4.5804,16.0314h10.4695l-17.0129-53.6562C409.5461,42.8348,408.2374,42.0169,406.2743,42.0169z + M393.3511,74.0797l5.5619-19.4667l1.3087-4.744h2.1266c0,0.3272,0.4907,1.963,1.3087,4.744l5.7255,19.4667H393.3511z"/> + <path d="M468.1098,89.9476h-19.6303c-1.7995,0-3.1081-0.3272-3.7625-0.9815 + c-0.6543-0.6543-1.1451-1.963-1.1451-3.5989V42.0169h-10.3059v44.8225c0,7.8521,4.2532,11.7782,12.7597,11.7782 + c9.6516,0,17.0129-0.3272,22.4113-0.6543L468.1098,89.9476z"/> + <path d="M263.9547,63.9374c-0.3272,0.8179-1.1451,3.1081-2.2902,6.8706h-0.6544 + c-1.1451-3.5989-1.963-5.8891-2.2902-6.8706L248.414,42.0169h-10.7967l18.4852,37.2976v19.3031h10.3059V79.3145l18.4852-37.2976 + h-10.6331L263.9547,63.9374z"/> + <path d="M316.3022,67.2091l-10.7967-3.4353c-2.4538-0.8179-4.0896-1.6359-4.9076-2.6174 + c-0.9815-0.9815-1.3087-2.6174-1.3087-4.9076c0-2.781,0.6543-4.5804,1.963-5.3983c1.3087-0.6543,3.7625-1.1451,7.525-1.1451 + c4.9076,0,10.6331,0.1636,16.8493,0.3272l0.6544-7.1978c-4.9076-1.3087-10.7967-1.963-17.6673-1.963 + c-7.1978,0-12.2689,0.9815-15.0499,2.9445c-2.9445,1.963-4.2532,6.0527-4.2532,12.2689c0,4.2532,0.8179,7.8521,2.6174,10.4695 + c1.7994,2.6174,4.5804,4.5804,8.67,5.8891l11.451,3.5989c2.2902,0.6543,3.926,1.4723,4.744,2.4538 + c0.8179,0.9815,1.3087,2.6174,1.3087,5.0712c0,2.781-0.6543,4.744-1.7994,5.5619c-1.3087,0.8179-3.7625,1.3087-7.525,1.3087 + c-2.4538,0-8.3429-0.1636-17.8308-0.3272l-0.6543,7.5249c6.0527,1.1451,12.1053,1.7994,18.3216,1.7994 + c7.525,0,12.7597-1.1451,15.5406-3.2717c2.9445-2.1266,4.4168-6.3799,4.4168-12.5961c0-4.2532-0.8179-7.8521-2.6174-10.4695 + C323.6635,70.4808,320.719,68.5178,316.3022,67.2091z"/> + <path d="M114.2736,72.2803l-40.8965,40.7329c-0.1636,0.1636-0.3272,0.1636-0.6544,0.1636 + L16.9401,98.2905c-0.1636,0-0.3272-0.1636-0.4908-0.4908L1.563,42.1805c0-0.1636,0-0.4908,0.1636-0.6543L42.623,0.7933 + c0.1636-0.1636,0.3272-0.1636,0.6543-0.1636l55.7828,15.0499c0.1636,0,0.3272,0.1636,0.4908,0.4908l14.8863,55.6192 + C114.6008,71.9531,114.4372,72.1167,114.2736,72.2803z M59.636,27.9485L4.8347,42.6713c-0.1636,0-0.1636,0.1636,0,0.3272 + L44.9132,83.077c0.1636,0.1636,0.1636,0,0.3272,0l14.7227-54.6377C59.7995,27.9485,59.636,27.9485,59.636,27.9485z"/> +</g> +</svg> From e3200d9eb8814e92849503e646325b09647cfe9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Thu, 4 Jan 2024 13:46:33 +0100 Subject: [PATCH 034/105] Improvements for `github-changelog` script (#14160) --- scripts/github-changelog.cr | 47 ++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/scripts/github-changelog.cr b/scripts/github-changelog.cr index b46adb9c656b..c660a01cd8ca 100755 --- a/scripts/github-changelog.cr +++ b/scripts/github-changelog.cr @@ -110,10 +110,13 @@ record PullRequest, if labels.includes?("breaking-change") io << "**[breaking]** " end + if experimental? + io << "**[experimental]** " + end if deprecated? io << "**[deprecation]** " end - io << title.sub(/^#{type}: /i, "") << " (" + io << title.sub(/^\[?(?:#{type}|#{sub_topic})(?::|\]:?) /i, "") << " (" io << "[#" << number << "](" << permalink << ")" if author = self.author io << ", thanks @" << author @@ -152,9 +155,26 @@ record PullRequest, end def topic - labels.find { |label| - label.starts_with?("topic:") && label != "topic:multithreading" - }.try(&.lchop("topic:").split(/:|\//)) + topics.fetch(0) do + STDERR.puts "Missing topic for ##{number}" + nil + end + end + + def topics + topics = labels.compact_map { |label| + label.lchop?("topic:").try(&.split(/:|\//)) + } + topics.reject! &.[0].==("multithreading") + + topics.sort_by! { |parts| + topic_priority = case parts[0] + when "tools" then 2 + when "lang" then 1 + else 0 + end + {-topic_priority, parts[0]} + } end def deprecated? @@ -165,6 +185,10 @@ record PullRequest, labels.includes?("kind:breaking") end + def experimental? + labels.includes?("experimental") + end + def feature? labels.includes?("kind:feature") end @@ -173,6 +197,10 @@ record PullRequest, labels.includes?("kind:bug") end + def chore? + labels.includes?("kind:chore") + end + def refactor? labels.includes?("kind:refactor") end @@ -196,9 +224,10 @@ record PullRequest, def type case when feature? then "feature" - when fix? then "fix" when docs? then "docs" when specs? then "specs" + when fix? then "fix" + when chore? then "chore" when performance? then "performance" when refactor? then "refactor" else nil @@ -242,16 +271,22 @@ SECTION_TITLES = { "breaking" => "Breaking changes", "feature" => "Features", "fix" => "Bugfixes", + "chore" => "Chores", "performance" => "Performance", "refactor" => "Refactor", "docs" => "Documentation", "specs" => "Specs", "infra" => "Infrastructure", - "" => "Chores", + "" => "other", } TOPIC_ORDER = %w[lang stdlib compiler tools other] +puts "## [#{milestone}] (#{Time.local.to_s("%F")})" +puts +puts "[#{milestone}]: https://github.com/crystal-lang/crystal/releases/#{milestone}" +puts + SECTION_TITLES.each do |id, title| prs = sections[id]? || next puts "### #{title}" From b8a24e7d94bd35999d0bf4eff0aac368f6be7bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Fri, 5 Jan 2024 12:02:17 +0100 Subject: [PATCH 035/105] Fix `String::Buffer` and `IO::Memory` capacity to grow beyond 1GB (#13989) --- spec/std/io/memory_spec.cr | 33 ++++++++++++++++++++++++++++ spec/std/string_builder_spec.cr | 39 +++++++++++++++++++++++++++++++++ src/io/memory.cr | 34 +++++++++++++++++++--------- src/string/builder.cr | 38 ++++++++++++++++++++++---------- 4 files changed, 122 insertions(+), 22 deletions(-) diff --git a/spec/std/io/memory_spec.cr b/spec/std/io/memory_spec.cr index 37ff01e3421d..7d51c09483ed 100644 --- a/spec/std/io/memory_spec.cr +++ b/spec/std/io/memory_spec.cr @@ -18,6 +18,17 @@ describe IO::Memory do io.gets_to_end.should eq(s) end + it "write raises EOFError" do + io = IO::Memory.new + initial_capacity = io.@capacity + expect_raises(IO::EOFError) do + io.write Slice.new(Pointer(UInt8).null, Int32::MAX) + end + # nothing get's written + io.bytesize.should eq 0 + io.@capacity.should eq initial_capacity + end + it "reads byte" do io = IO::Memory.new("abc") io.read_byte.should eq('a'.ord) @@ -494,4 +505,26 @@ describe IO::Memory do end end {% end %} + + it "allocates for > 1 GB", tags: %w[slow] do + io = IO::Memory.new + mbstring = "a" * 1024 * 1024 + 1024.times { io << mbstring } + + io.bytesize.should eq(1 << 30) + io.@capacity.should eq 1 << 30 + + io << mbstring + + io.bytesize.should eq (1 << 30) + (1 << 20) + io.@capacity.should eq Int32::MAX + + 1022.times { io << mbstring } + + io.write mbstring.to_slice[0..-4] + io << "a" + expect_raises(IO::EOFError) do + io << "a" + end + end end diff --git a/spec/std/string_builder_spec.cr b/spec/std/string_builder_spec.cr index 2b5f62c6c03c..250a4b0239f2 100644 --- a/spec/std/string_builder_spec.cr +++ b/spec/std/string_builder_spec.cr @@ -40,4 +40,43 @@ describe String::Builder do str.chomp!(44).to_s.should eq("a,b,c") end end + + it "raises EOFError" do + builder = String::Builder.new + initial_capacity = builder.capacity + expect_raises(IO::EOFError) do + builder.write Slice.new(Pointer(UInt8).null, Int32::MAX) + end + # nothing get's written + builder.bytesize.should eq 0 + builder.capacity.should eq initial_capacity + end + + # FIXME(wasm32): https://github.com/crystal-lang/crystal/issues/14057 + {% if flag?(:wasm32) %} + pending "allocation for > 1 GB" + {% else %} + it "allocates for > 1 GB", tags: %w[slow] do + String::Builder.build do |str| + mbstring = "a" * 1024 * 1024 + 1023.times { str << mbstring } + + str.bytesize.should eq (1 << 30) - (1 << 20) + str.capacity.should eq 1 << 30 + + str << mbstring + + str.bytesize.should eq 1 << 30 + str.capacity.should eq Int32::MAX + + 1023.times { str << mbstring } + + str.write mbstring.to_slice[0..(-4 - String::HEADER_SIZE)] + str << "a" + expect_raises(IO::EOFError) do + str << "a" + end + end + end + {% end %} end diff --git a/src/io/memory.cr b/src/io/memory.cr index d0b925df1d70..bd486f0cbdc2 100644 --- a/src/io/memory.cr +++ b/src/io/memory.cr @@ -90,11 +90,7 @@ class IO::Memory < IO return if count == 0 - new_bytesize = @pos + count - if new_bytesize > @capacity - check_resizeable - resize_to_capacity(Math.pw2ceil(new_bytesize)) - end + increase_capacity_by(count) slice.copy_to(@buffer + @pos, count) @@ -112,11 +108,7 @@ class IO::Memory < IO check_writeable check_open - new_bytesize = @pos + 1 - if new_bytesize > @capacity - check_resizeable - resize_to_capacity(Math.pw2ceil(new_bytesize)) - end + increase_capacity_by(1) (@buffer + @pos).value = byte @@ -458,6 +450,28 @@ class IO::Memory < IO end end + private def increase_capacity_by(count) + raise IO::EOFError.new if count >= Int32::MAX - bytesize + + new_bytesize = @pos + count + return if new_bytesize <= @capacity + + check_resizeable + + new_capacity = calculate_new_capacity(new_bytesize) + resize_to_capacity(new_capacity) + end + + private def calculate_new_capacity(new_bytesize : Int32) + # If the new bytesize is bigger than 1 << 30, the next power of two would + # be 1 << 31, which is out of range for Int32. + # So we limit the capacity to Int32::MAX in order to be able to use the + # range (1 << 30) < new_bytesize < Int32::MAX + return Int32::MAX if new_bytesize > 1 << 30 + + Math.pw2ceil(new_bytesize) + end + private def resize_to_capacity(capacity) @capacity = capacity @buffer = GC.realloc(@buffer, @capacity) diff --git a/src/string/builder.cr b/src/string/builder.cr index 0fb77f4ca41b..a06644b831d1 100644 --- a/src/string/builder.cr +++ b/src/string/builder.cr @@ -41,21 +41,14 @@ class String::Builder < IO return if slice.empty? count = slice.size - new_bytesize = real_bytesize + count - if new_bytesize > @capacity - resize_to_capacity(Math.pw2ceil(new_bytesize)) - end + increase_capacity_by count slice.copy_to(@buffer + real_bytesize, count) @bytesize += count end def write_byte(byte : UInt8) : Nil - new_bytesize = real_bytesize + 1 - if new_bytesize > @capacity - resize_to_capacity(Math.pw2ceil(new_bytesize)) - end - + increase_capacity_by 1 @buffer[real_bytesize] = byte @bytesize += 1 @@ -108,17 +101,18 @@ class String::Builder < IO raise "Can only invoke 'to_s' once on String::Builder" if @finished @finished = true - write_byte 0_u8 + real_bytesize = real_bytesize() + @buffer[real_bytesize] = 0_u8 + real_bytesize += 1 # Try to reclaim some memory if capacity is bigger than what we need - real_bytesize = real_bytesize() if @capacity > real_bytesize resize_to_capacity(real_bytesize) end String.set_crystal_type_id(@buffer) str = @buffer.as(String) - str.initialize_header((bytesize - 1).to_i) + str.initialize_header(bytesize) str end @@ -126,6 +120,26 @@ class String::Builder < IO @bytesize + String::HEADER_SIZE end + private def increase_capacity_by(count) + raise IO::EOFError.new if count >= Int32::MAX - real_bytesize + + new_bytesize = real_bytesize + count + return if new_bytesize <= @capacity + + new_capacity = calculate_new_capacity(new_bytesize) + resize_to_capacity(new_capacity) + end + + private def calculate_new_capacity(new_bytesize) + # If the new bytesize is bigger than 1 << 30, the next power of two would + # be 1 << 31, which is out of range for Int32. + # So we limit the capacity to Int32::MAX in order to be able to use the + # range (1 << 30) < new_bytesize < Int32::MAX + return Int32::MAX if new_bytesize > 1 << 30 + + Math.pw2ceil(new_bytesize) + end + private def resize_to_capacity(capacity) @capacity = capacity @buffer = GC.realloc(@buffer, @capacity) From 7df0b2e9d0b1c735ebc9d30e903fa037f297538c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Sat, 6 Jan 2024 23:03:39 +0100 Subject: [PATCH 036/105] Fix OpenSSL error handling for EOF (support for OpenSSL 3.2) (#14169) Co-authored-by: Beta Ziliani <beta@manas.tech> --- spec/std/openssl/ssl/socket_spec.cr | 8 +++++++- src/openssl.cr | 11 +++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/spec/std/openssl/ssl/socket_spec.cr b/spec/std/openssl/ssl/socket_spec.cr index ccf1046b6949..bbc5b11e4b9b 100644 --- a/spec/std/openssl/ssl/socket_spec.cr +++ b/spec/std/openssl/ssl/socket_spec.cr @@ -160,20 +160,26 @@ describe OpenSSL::SSL::Socket do server_context, client_context = ssl_context_pair server_context.disable_session_resume_tickets # avoid Broken pipe - server_finished_reading = Channel(String).new + server_finished_reading = Channel(String | Exception).new spawn do OpenSSL::SSL::Server.open(tcp_server, server_context, sync_close: true) do |server| server_socket = server.accept received = server_socket.gets_to_end # interprets underlying socket close as a graceful EOF server_finished_reading.send(received) end + rescue exc + server_finished_reading.send exc end + socket = TCPSocket.new(tcp_server.local_address.address, tcp_server.local_address.port) socket_ssl = OpenSSL::SSL::Socket::Client.new(socket, client_context, hostname: "example.com", sync_close: true) socket_ssl.print "hello" socket_ssl.flush # needed today see #5375 socket.close # close underlying socket without gracefully shutting down SSL at all server_received = server_finished_reading.receive + if server_received.is_a?(Exception) + raise server_received + end server_received.should eq("hello") end end diff --git a/src/openssl.cr b/src/openssl.cr index 802c9a05e7d3..f34ee169b4cc 100644 --- a/src/openssl.cr +++ b/src/openssl.cr @@ -89,15 +89,14 @@ module OpenSSL when .syscall? @code, message = fetch_error_details if @code == 0 - case return_code - when 0 + errno = {% if flag?(:win32) %} WinError.wsa_value {% else %} Errno.value {% end %} + success = {% if flag?(:win32) %} errno.error_success? {% else %} errno.none? {% end %} + if success message = "Unexpected EOF" @underlying_eof = true - when -1 - cause = RuntimeError.from_errno(func || "OpenSSL") - message = "I/O error" else - message = "Unknown error" + cause = RuntimeError.from_os_error(func || "OpenSSL", os_error: errno) + message = "I/O error" end end when .ssl? From 2140607a289133926ce5edf8215252d0464fdf20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Mon, 8 Jan 2024 12:34:08 +0100 Subject: [PATCH 037/105] Fix `options` parameter for `String#split`, `#scan` (#14183) --- spec/std/string_spec.cr | 5 +++++ src/string.cr | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/spec/std/string_spec.cr b/spec/std/string_spec.cr index 0d60b3ac2466..ebebcd2c6561 100644 --- a/spec/std/string_spec.cr +++ b/spec/std/string_spec.cr @@ -1416,6 +1416,7 @@ describe "String" do it { "=".split(/\=/, 2).should eq(["", ""]) } it { "=".split(/\=/, 2, remove_empty: true).should eq([] of String) } it { ",".split(/(?:(x)|(,))/).should eq(["", ",", ""]) } + it { "ba".split(/a/, options: :anchored).should eq ["ba"] } it "keeps groups" do s = "split on the word on okay?" @@ -2322,6 +2323,10 @@ describe "String" do it "does with number and string" do "1ab4".scan(/\d+/).map(&.[0]).should eq(["1", "4"]) end + + it "options parameter" do + "ba".scan(/a/, options: :anchored).map(&.[0]).should eq [] of String + end end it "has match" do diff --git a/src/string.cr b/src/string.cr index 98b7ec3884fd..4004f0d34929 100644 --- a/src/string.cr +++ b/src/string.cr @@ -4198,7 +4198,6 @@ class String count = 0 match_offset = slice_offset = 0 - options = Regex::MatchOptions::None while match = separator.match_at_byte_index(self, match_offset, options: options) index = match.byte_begin(0) match_bytesize = match.byte_end(0) - index @@ -4744,7 +4743,6 @@ class String def scan(pattern : Regex, *, options : Regex::MatchOptions = Regex::MatchOptions::None, &) : self byte_offset = 0 - options = Regex::MatchOptions::None while match = pattern.match_at_byte_index(self, byte_offset, options: options) index = match.byte_begin(0) $~ = match From 95d04fab447c48d7cb94f5937e52f6556e3ff858 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Mon, 8 Jan 2024 21:05:33 +0100 Subject: [PATCH 038/105] Changelog for 1.11.0 (#14158) --- CHANGELOG.md | 256 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/VERSION | 2 +- 2 files changed, 257 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d2c17878c9d..1bedb4a96a97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,261 @@ # Changelog +## [1.11.0] (2024-01-08) + +[1.11.0]: https://github.com/crystal-lang/crystal/releases/1.11.0 + +### Features + +#### lang + +- **[breaking]** Support `alignof` and `instance_alignof` ([#14087](https://github.com/crystal-lang/crystal/pull/14087), thanks @HertzDevil) +- *(annotations)* Support `dll` parameter in `@[Link]` ([#14131](https://github.com/crystal-lang/crystal/pull/14131), thanks @HertzDevil) +- *(macros)* Expose macro `Call` context via new `@caller` macro ivar ([#14048](https://github.com/crystal-lang/crystal/pull/14048), thanks @Blacksmoke16) + +#### stdlib + +- *(collection)* Add `Enumerable#present?` ([#13866](https://github.com/crystal-lang/crystal/pull/13866), thanks @straight-shoota) +- *(collection)* Add `Enumerable#each_step` and `Iterable#each_step` ([#13610](https://github.com/crystal-lang/crystal/pull/13610), thanks @baseballlover723) +- *(collection)* Add `Enumerable(T)#to_set(& : T -> U) : Set(U) forall U` ([#12654](https://github.com/crystal-lang/crystal/pull/12654), thanks @caspiano) +- *(collection)* Add `Enumerable(T)#to_a(& : T -> U) forall U` ([#12653](https://github.com/crystal-lang/crystal/pull/12653), thanks @caspiano) +- *(files)* Add `IO::Error#target` ([#13865](https://github.com/crystal-lang/crystal/pull/13865), thanks @straight-shoota) +- *(llvm)* Add `LLVM::OperandBundleDef#dispose` ([#14095](https://github.com/crystal-lang/crystal/pull/14095), thanks @HertzDevil) +- *(llvm)* Windows: Use local configuration for LLVM when linking dynamically ([#14101](https://github.com/crystal-lang/crystal/pull/14101), thanks @HertzDevil) +- *(macros)* Add `CharLiteral#ord` ([#13910](https://github.com/crystal-lang/crystal/pull/13910), thanks @refi64) +- *(macros)* Add macro methods for `MacroIf` and `MacroFor` nodes ([#13902](https://github.com/crystal-lang/crystal/pull/13902), thanks @sbsoftware) +- *(macros)* Expose doc comments on `ASTNode` when generating docs ([#14050](https://github.com/crystal-lang/crystal/pull/14050), thanks @Blacksmoke16) +- *(macros)* Add macro methods for `ModuleDef` ([#14063](https://github.com/crystal-lang/crystal/pull/14063), thanks @HertzDevil) +- *(macros)* Add macro methods for `Include` and `Extend` ([#14064](https://github.com/crystal-lang/crystal/pull/14064), thanks @HertzDevil) +- *(macros)* Add macro methods for `ClassDef`, `EnumDef`, `AnnotationDef` ([#14072](https://github.com/crystal-lang/crystal/pull/14072), thanks @HertzDevil) +- *(numeric)* Implement `BigRational`'s rounding modes ([#13871](https://github.com/crystal-lang/crystal/pull/13871), thanks @HertzDevil) +- *(numeric)* Support full exponent range in `BigFloat#**(BigInt)` ([#13881](https://github.com/crystal-lang/crystal/pull/13881), thanks @HertzDevil) +- *(numeric)* Add `Math.fma` ([#13934](https://github.com/crystal-lang/crystal/pull/13934), thanks @HertzDevil) +- *(numeric)* Add `Number#integer?` ([#13936](https://github.com/crystal-lang/crystal/pull/13936), thanks @HertzDevil) +- *(numeric)* Publish `Int::Primitive#abs_unsigned` and `#neg_signed` ([#13938](https://github.com/crystal-lang/crystal/pull/13938), thanks @HertzDevil) +- *(numeric)* Add `Int::Primitive#to_signed`, `#to_signed!`, `#to_unsigned`, `#to_unsigned!` ([#13960](https://github.com/crystal-lang/crystal/pull/13960), thanks @HertzDevil) +- *(numeric)* Support `BigFloat#**` for all `Int::Primitive` arguments ([#13971](https://github.com/crystal-lang/crystal/pull/13971), thanks @HertzDevil) +- *(numeric)* Add `Float32::MIN_SUBNORMAL` and `Float64::MIN_SUBNORMAL` ([#13961](https://github.com/crystal-lang/crystal/pull/13961), thanks @HertzDevil) +- *(numeric)* Add `Float::Primitive.parse_hexfloat`, `.parse_hexfloat?`, `#to_hexfloat` ([#14027](https://github.com/crystal-lang/crystal/pull/14027), thanks @HertzDevil) +- *(numeric)* Implement `sprintf "%f"` in Crystal using Ryu Printf ([#14067](https://github.com/crystal-lang/crystal/pull/14067), thanks @HertzDevil) +- *(numeric)* Implement `sprintf "%e"` in Crystal ([#14084](https://github.com/crystal-lang/crystal/pull/14084), thanks @HertzDevil) +- *(numeric)* Implement `sprintf "%a"` in Crystal ([#14102](https://github.com/crystal-lang/crystal/pull/14102), thanks @HertzDevil) +- *(numeric)* Implement `sprintf "%g"` in Crystal ([#14123](https://github.com/crystal-lang/crystal/pull/14123), thanks @HertzDevil) +- *(runtime)* Add `Crystal::HOST_TRIPLE` and `TARGET_TRIPLE` ([#13823](https://github.com/crystal-lang/crystal/pull/13823), thanks @HertzDevil) +- *(runtime)* **[experimental]** Add `Reference.pre_initialize` and `.unsafe_construct` ([#14108](https://github.com/crystal-lang/crystal/pull/14108), thanks @HertzDevil) +- *(runtime)* **[experimental]** Add `ReferenceStorage` for manual allocation of references ([#14106](https://github.com/crystal-lang/crystal/pull/14106), thanks @HertzDevil) +- *(serialization)* Fix `StaticArray#to_json` ([#14104](https://github.com/crystal-lang/crystal/pull/14104), thanks @Vendicated) +- *(specs)* Add `crystal spec --dry-run` ([#13804](https://github.com/crystal-lang/crystal/pull/13804), thanks @nobodywasishere) +- *(specs)* Add `crystal spec --list-tags` ([#13616](https://github.com/crystal-lang/crystal/pull/13616), thanks @baseballlover723) +- *(system)* Respect Windows `Path` directory separators in `File.match?` ([#13912](https://github.com/crystal-lang/crystal/pull/13912), thanks @HertzDevil) +- *(text)* Support Unicode 15.1.0 ([#13812](https://github.com/crystal-lang/crystal/pull/13812), thanks @HertzDevil) +- *(text)* Add `UUID.v1`, `.v2`, `.v3`, `.v4`, `.v5` ([#13693](https://github.com/crystal-lang/crystal/pull/13693), thanks @threez) +- *(text)* Add `String` and `Char` patterns to `StringScanner` ([#13806](https://github.com/crystal-lang/crystal/pull/13806), thanks @funny-falcon) +- *(text)* Add `EOL`constant (End-Of-Line) ([#11303](https://github.com/crystal-lang/crystal/pull/11303), thanks @postmodern) +- *(text)* Add `Char::Reader#current_char?`, `#next_char?`, `#previous_char?` ([#14012](https://github.com/crystal-lang/crystal/pull/14012), thanks @HertzDevil) +- *(text)* Add `String#matches_full?` ([#13968](https://github.com/crystal-lang/crystal/pull/13968), thanks @straight-shoota) +- *(text)* Change `Regex::MatchData#to_s` to return matched substring ([#14115](https://github.com/crystal-lang/crystal/pull/14115), thanks @Vendicated) + +#### compiler + +- *(codegen)* Add incremental optimization levels ([#13464](https://github.com/crystal-lang/crystal/pull/13464), thanks @kostya) +- *(debugger)* Support debug information for 64-bit or unsigned enums ([#14081](https://github.com/crystal-lang/crystal/pull/14081), thanks @HertzDevil) +- *(interpreter)* Support `instance_sizeof(T)` in the interpreter ([#14031](https://github.com/crystal-lang/crystal/pull/14031), thanks @HertzDevil) +- *(interpreter)* Support `-dynamic.lib` in Windows interpreter ([#14143](https://github.com/crystal-lang/crystal/pull/14143), thanks @HertzDevil) +- *(interpreter)* Support absolute paths in `CRYSTAL_INTERPRETER_LOADER_INFO` ([#14147](https://github.com/crystal-lang/crystal/pull/14147), thanks @HertzDevil) +- *(interpreter)* Add `Crystal::Repl#parse_and_interpret` ([#14138](https://github.com/crystal-lang/crystal/pull/14138), thanks @bcardiff) +- *(semantic)* Change short_reference for top-level methods to `::foo` ([#14071](https://github.com/crystal-lang/crystal/pull/14071), thanks @keshavbiswa) + +#### tools + +- *(docs-generator)* Expose inherited macros in generated API docs ([#13810](https://github.com/crystal-lang/crystal/pull/13810), thanks @Blacksmoke16) +- *(docs-generator)* Order macros below class methods in generated docs ([#14024](https://github.com/crystal-lang/crystal/pull/14024), thanks @Blacksmoke16) +- *(formatter)* Do not remove trailing comma from multi-line macro/def parameters (not yet enabled) ([#14075](https://github.com/crystal-lang/crystal/pull/14075), thanks @Blacksmoke16) +- *(unreachable)* Add `--check` flag to `crystal tool unreachable` ([#13930](https://github.com/crystal-lang/crystal/pull/13930), thanks @straight-shoota) +- *(unreachable)* Add annotations to output of `crystal tool unreachable` ([#13927](https://github.com/crystal-lang/crystal/pull/13927), thanks @straight-shoota) +- *(unreachable)* Print relative paths in `crystal tool unreachable` ([#13929](https://github.com/crystal-lang/crystal/pull/13929), thanks @straight-shoota) +- *(unreachable)* Add CSV output format to `crystal tool unreachable` ([#13926](https://github.com/crystal-lang/crystal/pull/13926), thanks @straight-shoota) +- *(unreachable)* Add `--tallies` option to `crystal tool unreachable` ([#13969](https://github.com/crystal-lang/crystal/pull/13969), thanks @straight-shoota) + +### Bugfixes + +#### stdlib + +- Fix `Box(T?)` crashing on `nil` ([#13893](https://github.com/crystal-lang/crystal/pull/13893), thanks @HertzDevil) +- Fix typos in src ([#14053](https://github.com/crystal-lang/crystal/pull/14053), thanks @kojix2) +- *(collection)* Fix `Indexable#each_repeated_combination(n)` when `n > size` ([#14092](https://github.com/crystal-lang/crystal/pull/14092), thanks @HertzDevil) +- *(concurrency)* Make `Process#wait` asynchronous on Windows ([#13908](https://github.com/crystal-lang/crystal/pull/13908), thanks @HertzDevil) +- *(concurrency)* Fix math overflow after spawning `Int32::MAX + 1` fibers ([#14096](https://github.com/crystal-lang/crystal/pull/14096), thanks @ysbaddaden) +- *(concurrency)* Fix `can't resume a running fiber` ([#14128](https://github.com/crystal-lang/crystal/pull/14128), thanks @ysbaddaden) +- *(crypto)* Fix OpenSSL error handling for EOF (support for OpenSSL 3.2) ([#14169](https://github.com/crystal-lang/crystal/pull/14169), thanks @straight-shoota) +- *(files)* Fix `Globber.constant_entry?` matching patterns ([#13955](https://github.com/crystal-lang/crystal/pull/13955), thanks @GeopJr) +- *(files)* Fix `String::Buffer` and `IO::Memory` capacity to grow beyond 1GB ([#13989](https://github.com/crystal-lang/crystal/pull/13989), thanks @straight-shoota) +- *(llvm)* Fix a typo ([#13914](https://github.com/crystal-lang/crystal/pull/13914), thanks @kojix2) +- *(numeric)* Make `String#to_f(whitespace: false)` work with infinity and NaN ([#13875](https://github.com/crystal-lang/crystal/pull/13875), thanks @HertzDevil) +- *(numeric)* Use `LibGMP::SI` and `UI` for size checks, not `Long` and `ULong` ([#13874](https://github.com/crystal-lang/crystal/pull/13874), thanks @HertzDevil) +- *(numeric)* Fix integral part extraction in `Number#format` ([#14061](https://github.com/crystal-lang/crystal/pull/14061), thanks @HertzDevil) +- *(numeric)* Fix out-of-bounds access in `Int128::MIN.to_s(base: 2)` ([#14119](https://github.com/crystal-lang/crystal/pull/14119), thanks @HertzDevil) +- *(numeric)* Avoid double rounding in `Float#format` for nonnegative `decimal_place` ([#14129](https://github.com/crystal-lang/crystal/pull/14129), thanks @HertzDevil) +- *(runtime)* Avoid `@[ThreadLocal]` on Android ([#14025](https://github.com/crystal-lang/crystal/pull/14025), thanks @HertzDevil) +- *(runtime)* Never use string interpolation in `Crystal::System.print_error` ([#14114](https://github.com/crystal-lang/crystal/pull/14114), thanks @HertzDevil) +- *(runtime)* Fix segfault with next boehm gc (after v8.2.4) ([#14130](https://github.com/crystal-lang/crystal/pull/14130), thanks @ysbaddaden) +- *(specs)* Skip spec execution on error exit ([#13986](https://github.com/crystal-lang/crystal/pull/13986), thanks @straight-shoota) +- *(system)* Fix `FileUtils.ln_sf` to override special file types ([#13896](https://github.com/crystal-lang/crystal/pull/13896), thanks @straight-shoota) +- *(system)* Fix `Process.exists?` throwing errors on EPERM ([#13911](https://github.com/crystal-lang/crystal/pull/13911), thanks @refi64) +- *(system)* Fix portable shell command arguments in `Process#prepare_args` ([#13942](https://github.com/crystal-lang/crystal/pull/13942), thanks @GeopJr) +- *(system)* Windows: Do not close process handle in `Process#close` ([#13997](https://github.com/crystal-lang/crystal/pull/13997), thanks @HertzDevil) +- *(system)* Windows: clear `Crystal::System::Process#@completion_key` after use ([#14068](https://github.com/crystal-lang/crystal/pull/14068), thanks @HertzDevil) +- *(system)* Fix UTF-8 console input on Windows ([#13758](https://github.com/crystal-lang/crystal/pull/13758), thanks @erdian718) +- *(text)* Fix invalid UTF-8 handling in `Char::Reader#previous_char` ([#14013](https://github.com/crystal-lang/crystal/pull/14013), thanks @HertzDevil) +- *(text)* Fix `options` parameter for `String#split`, `#scan` ([#14183](https://github.com/crystal-lang/crystal/pull/14183), thanks @straight-shoota) +- *(time)* Fix time span overflow on `Int#milliseconds` and `Int#microseconds` ([#14105](https://github.com/crystal-lang/crystal/pull/14105), thanks @bcardiff) + +#### compiler + +- *(cli)* Remove unnecessary file check for CLI arguments ([#13853](https://github.com/crystal-lang/crystal/pull/13853), thanks @straight-shoota) +- *(cli)* Check for invalid integers in compiler's CLI ([#13959](https://github.com/crystal-lang/crystal/pull/13959), thanks @HertzDevil) +- *(cli)* Fix compiler error message for invalid source file ([#14157](https://github.com/crystal-lang/crystal/pull/14157), thanks @straight-shoota) +- *(codegen)* Fix a typo in compiler source ([#14054](https://github.com/crystal-lang/crystal/pull/14054), thanks @kojix2) +- *(codegen)* Fix codegen error when discarding `is_a?` or `responds_to?`'s result ([#14148](https://github.com/crystal-lang/crystal/pull/14148), thanks @HertzDevil) +- *(interpreter)* Fix element alignment of `Tuple` and `NamedTuple` casts ([#14040](https://github.com/crystal-lang/crystal/pull/14040), thanks @HertzDevil) +- *(interpreter)* `Crystal::Loader`: Skip second linker member on Windows if absent ([#14111](https://github.com/crystal-lang/crystal/pull/14111), thanks @HertzDevil) +- *(parser)* Support `%r` and `%x` when not followed by delimiter start ([#13933](https://github.com/crystal-lang/crystal/pull/13933), thanks @HertzDevil) +- *(parser)* Fix location of global `Path` nodes in certain constructs ([#13932](https://github.com/crystal-lang/crystal/pull/13932), thanks @HertzDevil) +- *(parser)* Fix `ToSVisitor` for expanded string interpolation in backticks ([#13943](https://github.com/crystal-lang/crystal/pull/13943), thanks @straight-shoota) +- *(parser)* Fix location for "invalid trailing comma in call" errors ([#13964](https://github.com/crystal-lang/crystal/pull/13964), thanks @HertzDevil) +- *(semantic)* Fix check for file type ([#13760](https://github.com/crystal-lang/crystal/pull/13760), thanks @straight-shoota) +- *(semantic)* Fix private type definitions with namespaced `Path`s ([#13931](https://github.com/crystal-lang/crystal/pull/13931), thanks @HertzDevil) +- *(semantic)* Fix missing param count in compilation error message ([#13985](https://github.com/crystal-lang/crystal/pull/13985), thanks @koffeinfrei) +- *(semantic)* Fix `ReadInstanceVar` on typedefs ([#14044](https://github.com/crystal-lang/crystal/pull/14044), thanks @HertzDevil) +- *(semantic)* Fix global `Path` lookup inside macro when def has free variables ([#14073](https://github.com/crystal-lang/crystal/pull/14073), thanks @HertzDevil) +- *(semantic)* Add location information to implicit flag enum members ([#14127](https://github.com/crystal-lang/crystal/pull/14127), thanks @Blacksmoke16) + +#### tools + +- *(docs-generator)* Fix `crystal docs` check `File.exists?` for `shard.yml` ([#13937](https://github.com/crystal-lang/crystal/pull/13937), thanks @straight-shoota) +- *(docs-generator)* Fix version sorting in API docs ([#13994](https://github.com/crystal-lang/crystal/pull/13994), thanks @m-o-e) +- *(docs-generator)* Strip whitespace in doc comment before determining summary line ([#14049](https://github.com/crystal-lang/crystal/pull/14049), thanks @Blacksmoke16) +- *(docs-generator)* Skip `Crystal::Macros` unless generating docs ([#13970](https://github.com/crystal-lang/crystal/pull/13970), thanks @straight-shoota) +- *(init)* Fix tool init error message when target exists but not a dir ([#13869](https://github.com/crystal-lang/crystal/pull/13869), thanks @straight-shoota) +- *(unreachable)* Fix infinite recursion of expanded nodes in `UnreachableVisitor` ([#13922](https://github.com/crystal-lang/crystal/pull/13922), thanks @straight-shoota) + +### Chores + +#### lang + +- *(macros)* **[deprecation]** Deprecate the splat operators in macro expressions ([#13939](https://github.com/crystal-lang/crystal/pull/13939), thanks @HertzDevil) + +#### stdlib + +- *(llvm)* **[deprecation]** Deprecate `LLVM.start_multithreaded` and `.stop_multithreaded` ([#13949](https://github.com/crystal-lang/crystal/pull/13949), thanks @HertzDevil) + +### Performance + +#### stdlib + +- *(concurrency)* Skip indirections in `Crystal::Scheduler` ([#14098](https://github.com/crystal-lang/crystal/pull/14098), thanks @ysbaddaden) +- *(numeric)* Optimize `BigInt#&`, `#|`, `#^` with `Int::Primitive` arguments ([#14006](https://github.com/crystal-lang/crystal/pull/14006), thanks @HertzDevil) +- *(numeric)* Optimize `BigInt#bit` ([#13980](https://github.com/crystal-lang/crystal/pull/13980), thanks @HertzDevil) +- *(numeric)* Use `#trailing_zeros_count` in `Int#gcd` ([#14069](https://github.com/crystal-lang/crystal/pull/14069), thanks @HertzDevil) +- *(serialization)* Optimize `JSON::Builder#string` with byte-based algorithm ([#13915](https://github.com/crystal-lang/crystal/pull/13915), thanks @straight-shoota) +- *(serialization)* Improve performance of `JSON::Builder#string` with direct stringification ([#13950](https://github.com/crystal-lang/crystal/pull/13950), thanks @straight-shoota) +- *(text)* Refactor `HTML.unescape` in native Crystal ([#13844](https://github.com/crystal-lang/crystal/pull/13844), thanks @straight-shoota) +- *(text)* Refactor some uses of the blockless `String#split` ([#14001](https://github.com/crystal-lang/crystal/pull/14001), thanks @HertzDevil) + +### Refactor + +#### stdlib + +- *(concurrency)* Add `Crystal::System::Thread` ([#13814](https://github.com/crystal-lang/crystal/pull/13814), thanks @HertzDevil) +- *(concurrency)* Move `Thread#set_current_thread` to `Fiber` ([#14099](https://github.com/crystal-lang/crystal/pull/14099), thanks @ysbaddaden) +- *(files)* Use `IO.copy` in `IO#gets_to_end` ([#13990](https://github.com/crystal-lang/crystal/pull/13990), thanks @straight-shoota) +- *(files)* Do not use `pointerof(Path)` in the standard library ([#14144](https://github.com/crystal-lang/crystal/pull/14144), thanks @HertzDevil) +- *(llvm)* **[deprecation]** Remove `LLVMExtSetCurrentDebugLocation` from `llvm_ext.cc` for LLVM 9+ ([#13965](https://github.com/crystal-lang/crystal/pull/13965), thanks @HertzDevil) +- *(llvm)* Replace some deprecated LLVM bindings ([#13953](https://github.com/crystal-lang/crystal/pull/13953), thanks @HertzDevil) +- *(llvm)* Split `LibLLVM` by C headers ([#13948](https://github.com/crystal-lang/crystal/pull/13948), thanks @HertzDevil) +- *(llvm)* Support `LLVMSetTargetMachineGlobalISel` from LLVM 18 ([#14079](https://github.com/crystal-lang/crystal/pull/14079), thanks @HertzDevil) +- *(llvm)* Support the operand bundle API from LLVM 18 ([#14082](https://github.com/crystal-lang/crystal/pull/14082), thanks @HertzDevil) +- *(numeric)* Simplify `String::Formatter` when Ryu Printf is available ([#14132](https://github.com/crystal-lang/crystal/pull/14132), thanks @HertzDevil) +- *(runtime)* Implement most of `Crystal::System.print_error` in native Crystal ([#14116](https://github.com/crystal-lang/crystal/pull/14116), thanks @HertzDevil) +- *(text)* Drop `Char::Reader#@end` ([#13920](https://github.com/crystal-lang/crystal/pull/13920), thanks @straight-shoota) +- *(text)* Generate `src/html/entities.cr` automatically ([#13998](https://github.com/crystal-lang/crystal/pull/13998), thanks @HertzDevil) +- *(time)* Refactor leap year to use `divisible_by?` ([#13982](https://github.com/crystal-lang/crystal/pull/13982), thanks @meatball133) + +#### compiler + +- Remove relative path to vendored shards `markd` and `reply` ([#13992](https://github.com/crystal-lang/crystal/pull/13992), thanks @nobodywasishere) +- *(cli)* Generalize allowed values for compiler CLI `--format` option ([#13940](https://github.com/crystal-lang/crystal/pull/13940), thanks @straight-shoota) +- *(parser)* Use `Char#to_i?` in lexer ([#13841](https://github.com/crystal-lang/crystal/pull/13841), thanks @straight-shoota) + +#### tools + +- *(unreachable)* Refactor `UnreachablePresenter` ([#13941](https://github.com/crystal-lang/crystal/pull/13941), thanks @straight-shoota) + +### Documentation + +#### lang + +- *(macros)* Add reference to book how merging macro expansion and call docs ([#14139](https://github.com/crystal-lang/crystal/pull/14139), thanks @Blacksmoke16) + +#### stdlib + +- *(collection)* Fix documentation of `Hash#put_if_absent` ([#13898](https://github.com/crystal-lang/crystal/pull/13898), thanks @ilmanzo) +- *(collection)* Improve docs on initial/default values passed to `Array.new` and `Hash.new` ([#13962](https://github.com/crystal-lang/crystal/pull/13962), thanks @straight-shoota) +- *(collection)* Improve docs for `Iterator` step-by-step iteration ([#13967](https://github.com/crystal-lang/crystal/pull/13967), thanks @straight-shoota) +- *(macros)* Document `Crystal::Macros::MagicConstant` ([#14070](https://github.com/crystal-lang/crystal/pull/14070), thanks @HertzDevil) +- *(serialization)* Add docs and explicit type restriction for indent parameter of `JSON.build` ([#14140](https://github.com/crystal-lang/crystal/pull/14140), thanks @syeopite) +- *(text)* Add note about `Char::Reader`'s value semantics ([#14008](https://github.com/crystal-lang/crystal/pull/14008), thanks @HertzDevil) +- *(text)* Fix documentation for `String#index!` ([#14038](https://github.com/crystal-lang/crystal/pull/14038), thanks @gettalong) + +#### compiler + +- *(cli)* Add optimization levels to manpage ([#14162](https://github.com/crystal-lang/crystal/pull/14162), thanks @straight-shoota) +- *(cli)* Add `unreachable` options to manpage ([#14164](https://github.com/crystal-lang/crystal/pull/14164), thanks @straight-shoota) +- *(cli)* Fix formatting in manpage ([#14163](https://github.com/crystal-lang/crystal/pull/14163), thanks @straight-shoota) + +### Specs + +#### stdlib + +- Add `pending_wasm32` ([#14086](https://github.com/crystal-lang/crystal/pull/14086), thanks @HertzDevil) +- *(concurrency)* Workaround regular timeouts in `HTTP::Server` specs with MT ([#14097](https://github.com/crystal-lang/crystal/pull/14097), thanks @ysbaddaden) +- *(files)* Fix `File::AccessDeniedError` expectations in `File` specs ([#14029](https://github.com/crystal-lang/crystal/pull/14029), thanks @HertzDevil) +- *(text)* Refactor specs for `HTML.unescape` ([#13842](https://github.com/crystal-lang/crystal/pull/13842), thanks @straight-shoota) +- *(text)* Fix spec for `String#encode` and `String.new` on DragonFlyBSD ([#13944](https://github.com/crystal-lang/crystal/pull/13944), thanks @GeopJr) + +#### compiler + +- *(codegen)* Remove `LLVMExtCreateMCJITCompilerForModule` from `llvm_ext.cc` ([#13966](https://github.com/crystal-lang/crystal/pull/13966), thanks @HertzDevil) +- *(interpreter)* Disable `mkfifo` spec for interpreter ([#14051](https://github.com/crystal-lang/crystal/pull/14051), thanks @HertzDevil) +- *(interpreter)* Fix interpreter specs on Windows ([#14145](https://github.com/crystal-lang/crystal/pull/14145), thanks @HertzDevil) + +#### tools + +- *(docs-generator)* Use `top_level_semantic` in doc spec instead of `semantic` ([#9352](https://github.com/crystal-lang/crystal/pull/9352), thanks @makenowjust) + +### Infrastructure + +- Changelog for 1.11.0 ([#14158](https://github.com/crystal-lang/crystal/pull/14158), thanks @straight-shoota) +- Update previous Crystal release - 1.10.0 ([#13878](https://github.com/crystal-lang/crystal/pull/13878), thanks @straight-shoota) +- Allow to specify git fork of distribution-scripts in CI ([#13976](https://github.com/crystal-lang/crystal/pull/13976), thanks @miry) +- Extract `generate_data` to separate Makefile ([#14015](https://github.com/crystal-lang/crystal/pull/14015), thanks @straight-shoota) +- Windows: Run specs in random order by default ([#14041](https://github.com/crystal-lang/crystal/pull/14041), thanks @HertzDevil) +- Update shards 0.17.4 ([#14133](https://github.com/crystal-lang/crystal/pull/14133), thanks @straight-shoota) +- Update distribution-scripts ([#14136](https://github.com/crystal-lang/crystal/pull/14136), thanks @straight-shoota) +- Update GH Actions to v4 ([#14120](https://github.com/crystal-lang/crystal/pull/14120), thanks @renovate) +- Embed logo image into repository and upgrade to SVG ([#14137](https://github.com/crystal-lang/crystal/pull/14137), thanks @straight-shoota) +- Improvements for `github-changelog` script ([#14160](https://github.com/crystal-lang/crystal/pull/14160), thanks @straight-shoota) +- Add `scripts/generate_llvm_version_info.cr` ([#14112](https://github.com/crystal-lang/crystal/pull/14112), thanks @HertzDevil) +- Fix `make clean` to remove zipped manpages ([#14135](https://github.com/crystal-lang/crystal/pull/14135), thanks @straight-shoota) +- Make `scripts/*.cr` all executable ([#13999](https://github.com/crystal-lang/crystal/pull/13999), thanks @HertzDevil) +- Reformat changelog release headings ([#13663](https://github.com/crystal-lang/crystal/pull/13663), thanks @straight-shoota) +- Merge `samples/.gitignore` into `.gitignore` ([#14134](https://github.com/crystal-lang/crystal/pull/14134), thanks @straight-shoota) +- *(ci)* Update GH Actions ([#13801](https://github.com/crystal-lang/crystal/pull/13801), thanks @renovate) +- *(ci)* Update LLVM patch version to LLVM 17.0.6 ([#14080](https://github.com/crystal-lang/crystal/pull/14080), thanks @straight-shoota) +- *(ci)* Configure Renovate Bot to add label `topic:infrastructure/ci` on PRs ([#14166](https://github.com/crystal-lang/crystal/pull/14166), thanks @straight-shoota) +- *(ci)* Update GH Actions ([#14165](https://github.com/crystal-lang/crystal/pull/14165), thanks @renovate) +- *(ci)* Distribute LLVM DLLs on Windows CI ([#14110](https://github.com/crystal-lang/crystal/pull/14110), thanks @HertzDevil) +- *(ci)* Use `CMAKE_MSVC_RUNTIME_LIBRARY` flag in win.yml ([#13900](https://github.com/crystal-lang/crystal/pull/13900), thanks @HertzDevil) + ## [1.10.1] (2023-10-13) [1.10.1]: https://github.com/crystal-lang/crystal/releases/1.10.1 diff --git a/src/VERSION b/src/VERSION index 1f724bf455d7..1cac385c6cb8 100644 --- a/src/VERSION +++ b/src/VERSION @@ -1 +1 @@ -1.11.0-dev +1.11.0 From 0ee5483c04c95c9b055bc9d9a8c3b434b715db5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Tue, 9 Jan 2024 17:36:30 +0100 Subject: [PATCH 039/105] Update previous Crystal release 1.11.0 (#14189) --- .circleci/config.yml | 2 +- .github/workflows/interpreter.yml | 6 +++--- .github/workflows/linux.yml | 2 +- .github/workflows/llvm.yml | 2 +- .github/workflows/openssl.yml | 6 +++--- .github/workflows/regex-engine.yml | 4 ++-- .github/workflows/wasm32.yml | 2 +- .github/workflows/win_build_portable.yml | 2 +- bin/ci | 6 +++--- shell.nix | 12 ++++++------ src/VERSION | 2 +- 11 files changed, 23 insertions(+), 23 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 39ae49d81ee3..9804bf22894c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,7 +12,7 @@ parameters: previous_crystal_base_url: description: "Prefix for URLs to Crystal bootstrap compiler" type: string - default: "https://github.com/crystal-lang/crystal/releases/download/1.10.1/crystal-1.10.1-1" + default: "https://github.com/crystal-lang/crystal/releases/download/1.11.0/crystal-1.11.0-1" defaults: environment: &env diff --git a/.github/workflows/interpreter.yml b/.github/workflows/interpreter.yml index 2cd37d4b6579..64ef777fa9d3 100644 --- a/.github/workflows/interpreter.yml +++ b/.github/workflows/interpreter.yml @@ -13,7 +13,7 @@ jobs: test-interpreter_spec: runs-on: ubuntu-22.04 container: - image: crystallang/crystal:1.10.1-build + image: crystallang/crystal:1.11.0-build name: "Test Interpreter" steps: - uses: actions/checkout@v4 @@ -24,7 +24,7 @@ jobs: build-interpreter: runs-on: ubuntu-22.04 container: - image: crystallang/crystal:1.10.1-build + image: crystallang/crystal:1.11.0-build name: Build interpreter steps: - uses: actions/checkout@v4 @@ -43,7 +43,7 @@ jobs: needs: build-interpreter runs-on: ubuntu-22.04 container: - image: crystallang/crystal:1.10.1-build + image: crystallang/crystal:1.11.0-build strategy: matrix: part: [0, 1, 2, 3] diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 9ef73a9fe23c..c501d1b0061c 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - crystal_bootstrap_version: [1.7.3, 1.8.2, 1.9.2, 1.10.1] + crystal_bootstrap_version: [1.7.3, 1.8.2, 1.9.2, 1.10.1, 1.11.0] flags: [""] include: # libffi is only available starting from the 1.2.2 build images diff --git a/.github/workflows/llvm.yml b/.github/workflows/llvm.yml index f361896768d8..e8e891cab665 100644 --- a/.github/workflows/llvm.yml +++ b/.github/workflows/llvm.yml @@ -56,7 +56,7 @@ jobs: - name: Install Crystal uses: crystal-lang/install-crystal@v1 with: - crystal: "1.10.1" + crystal: "1.11.0" - name: Build libllvm_ext run: make -B deps diff --git a/.github/workflows/openssl.yml b/.github/workflows/openssl.yml index 07e2d7e94558..16dfe3b42e32 100644 --- a/.github/workflows/openssl.yml +++ b/.github/workflows/openssl.yml @@ -10,7 +10,7 @@ jobs: openssl3: runs-on: ubuntu-latest name: "OpenSSL 3.0" - container: crystallang/crystal:1.10.1-alpine + container: crystallang/crystal:1.11.0-alpine steps: - name: Download Crystal source uses: actions/checkout@v4 @@ -27,7 +27,7 @@ jobs: openssl111: runs-on: ubuntu-latest name: "OpenSSL 1.1.1" - container: crystallang/crystal:1.10.1-alpine + container: crystallang/crystal:1.11.0-alpine steps: - name: Download Crystal source uses: actions/checkout@v4 @@ -42,7 +42,7 @@ jobs: libressl34: runs-on: ubuntu-latest name: "LibreSSL 3.4" - container: crystallang/crystal:1.10.1-alpine + container: crystallang/crystal:1.11.0-alpine steps: - name: Download Crystal source uses: actions/checkout@v4 diff --git a/.github/workflows/regex-engine.yml b/.github/workflows/regex-engine.yml index a7ad3afbbb65..ad6de969c5f5 100644 --- a/.github/workflows/regex-engine.yml +++ b/.github/workflows/regex-engine.yml @@ -10,7 +10,7 @@ jobs: pcre: runs-on: ubuntu-latest name: "PCRE" - container: crystallang/crystal:1.10.1-alpine + container: crystallang/crystal:1.11.0-alpine steps: - name: Download Crystal source uses: actions/checkout@v4 @@ -25,7 +25,7 @@ jobs: pcre2: runs-on: ubuntu-latest name: "PCRE2" - container: crystallang/crystal:1.10.1-alpine + container: crystallang/crystal:1.11.0-alpine steps: - name: Download Crystal source uses: actions/checkout@v4 diff --git a/.github/workflows/wasm32.yml b/.github/workflows/wasm32.yml index 0d4f32f4c044..eec64cc0bb39 100644 --- a/.github/workflows/wasm32.yml +++ b/.github/workflows/wasm32.yml @@ -12,7 +12,7 @@ env: jobs: wasm32-test: runs-on: ubuntu-latest - container: crystallang/crystal:1.10.1-build + container: crystallang/crystal:1.11.0-build steps: - name: Download Crystal source uses: actions/checkout@v4 diff --git a/.github/workflows/win_build_portable.yml b/.github/workflows/win_build_portable.yml index 960606628a9e..6ea5568305b6 100644 --- a/.github/workflows/win_build_portable.yml +++ b/.github/workflows/win_build_portable.yml @@ -24,7 +24,7 @@ jobs: - name: Install Crystal uses: crystal-lang/install-crystal@v1 with: - crystal: "1.10.1" + crystal: "1.11.0" - name: Download Crystal source uses: actions/checkout@v4 diff --git a/bin/ci b/bin/ci index 8e9f7a5ddadf..d67c2d7f6c4e 100755 --- a/bin/ci +++ b/bin/ci @@ -135,8 +135,8 @@ format() { prepare_build() { on_linux verify_linux_environment - on_osx curl -L https://github.com/crystal-lang/crystal/releases/download/1.10.1/crystal-1.10.1-1-darwin-universal.tar.gz -o ~/crystal.tar.gz - on_osx 'pushd ~;gunzip -c ~/crystal.tar.gz | tar xopf -;mv crystal-1.10.1-1 crystal;popd' + on_osx curl -L https://github.com/crystal-lang/crystal/releases/download/1.11.0/crystal-1.11.0-1-darwin-universal.tar.gz -o ~/crystal.tar.gz + on_osx 'pushd ~;gunzip -c ~/crystal.tar.gz | tar xopf -;mv crystal-1.11.0-1 crystal;popd' # These commands may take a few minutes to run due to the large size of the repositories. # This restriction has been made on GitHub's request because updating shallow @@ -189,7 +189,7 @@ with_build_env() { on_linux verify_linux_environment - export DOCKER_TEST_PREFIX="${DOCKER_TEST_PREFIX:=crystallang/crystal:1.10.1}" + export DOCKER_TEST_PREFIX="${DOCKER_TEST_PREFIX:=crystallang/crystal:1.11.0}" case $ARCH in x86_64) diff --git a/shell.nix b/shell.nix index ab90080aca13..02db8fb637f7 100644 --- a/shell.nix +++ b/shell.nix @@ -52,18 +52,18 @@ let # Hashes obtained using `nix-prefetch-url --unpack <url>` latestCrystalBinary = genericBinary ({ x86_64-darwin = { - url = "https://github.com/crystal-lang/crystal/releases/download/1.10.1/crystal-1.10.1-1-darwin-universal.tar.gz"; - sha256 = "sha256:08k8sixhnk9ld99nyrya11rkpp34zamsg3lk9h50ppbmzfixjyyc"; + url = "https://github.com/crystal-lang/crystal/releases/download/1.11.0/crystal-1.11.0-1-darwin-universal.tar.gz"; + sha256 = "sha256:0x3adik0rpfkgw8nszf6l52vr4m7fs7rwqf1r0m17x4kgq67daiz"; }; aarch64-darwin = { - url = "https://github.com/crystal-lang/crystal/releases/download/1.10.1/crystal-1.10.1-1-darwin-universal.tar.gz"; - sha256 = "sha256:08k8sixhnk9ld99nyrya11rkpp34zamsg3lk9h50ppbmzfixjyyc"; + url = "https://github.com/crystal-lang/crystal/releases/download/1.11.0/crystal-1.11.0-1-darwin-universal.tar.gz"; + sha256 = "sha256:0x3adik0rpfkgw8nszf6l52vr4m7fs7rwqf1r0m17x4kgq67daiz"; }; x86_64-linux = { - url = "https://github.com/crystal-lang/crystal/releases/download/1.10.1/crystal-1.10.1-1-linux-x86_64.tar.gz"; - sha256 = "sha256:02hzslzgv0xxsal3fkbcdrnrrnzf9lraamy36p36sjf8n14v45a2"; + url = "https://github.com/crystal-lang/crystal/releases/download/1.11.0/crystal-1.11.0-1-linux-x86_64.tar.gz"; + sha256 = "sha256:1npbn61mw6fchdlg64s7zd3k33711ifhs8n75skw8w30i4ryilhk"; }; }.${pkgs.stdenv.system}); diff --git a/src/VERSION b/src/VERSION index 1cac385c6cb8..381cf02417c4 100644 --- a/src/VERSION +++ b/src/VERSION @@ -1 +1 @@ -1.11.0 +1.12.0-dev From 0b57b6cc8e4f5003267549892d23d2af5ad6309b Mon Sep 17 00:00:00 2001 From: Stephen von Takach <steve@vontaka.ch> Date: Wed, 10 Jan 2024 02:37:47 +1000 Subject: [PATCH 040/105] Add `Signal::trap_handler?` (#14126) Co-authored-by: Quinton Miller <nicetas.c@gmail.com> --- spec/std/signal_spec.cr | 22 ++++++++++++++++++++++ src/crystal/system/signal.cr | 3 +++ src/crystal/system/unix/signal.cr | 6 +++++- src/crystal/system/wasi/signal.cr | 4 ++++ src/crystal/system/win32/signal.cr | 4 ++++ src/signal.cr | 18 ++++++++++++++++++ 6 files changed, 56 insertions(+), 1 deletion(-) diff --git a/spec/std/signal_spec.cr b/spec/std/signal_spec.cr index e92b74a6370c..d1d3aa3f1643 100644 --- a/spec/std/signal_spec.cr +++ b/spec/std/signal_spec.cr @@ -29,6 +29,8 @@ describe "Signal" do sleep 0.1 end ran.should be_true + ensure + Signal::USR1.reset end it "ignores a signal" do @@ -36,6 +38,26 @@ describe "Signal" do Process.signal Signal::USR2, Process.pid end + it "allows chaining of signals" do + ran_first = false + ran_second = false + + Signal::USR1.trap { ran_first = true } + existing = Signal::USR1.trap_handler? + + Signal::USR1.trap do |signal| + existing.try &.call(signal) + ran_second = true + end + + Process.signal Signal::USR1, Process.pid + sleep 0.1 + ran_first.should be_true + ran_second.should be_true + ensure + Signal::USR1.reset + end + it "CHLD.reset sets default Crystal child handler" do Signal::CHLD.reset child = Process.new("true", shell: true) diff --git a/src/crystal/system/signal.cr b/src/crystal/system/signal.cr index b5ba591b2ec5..a5e3eca885da 100644 --- a/src/crystal/system/signal.cr +++ b/src/crystal/system/signal.cr @@ -2,6 +2,9 @@ module Crystal::System::Signal # Sets the handler for this signal to the passed function. # def self.trap(signal, handler) : Nil + # Returns any existing handler set on the signal + # def self.trap_handler?(signal) + # Resets the handler for this signal to the OS default. # def self.reset(signal) : Nil diff --git a/src/crystal/system/unix/signal.cr b/src/crystal/system/unix/signal.cr index c30a2b985af2..58b1180f56ef 100644 --- a/src/crystal/system/unix/signal.cr +++ b/src/crystal/system/unix/signal.cr @@ -15,7 +15,7 @@ module Crystal::System::Signal @@pipe = IO.pipe(read_blocking: false, write_blocking: true) @@handlers = {} of ::Signal => Handler @@sigset = Sigset.new - class_setter child_handler : Handler? + class_property child_handler : Handler? @@mutex = Mutex.new(:unchecked) def self.trap(signal, handler) : Nil @@ -30,6 +30,10 @@ module Crystal::System::Signal end end + def self.trap_handler?(signal) + @@mutex.synchronize { @@handlers[signal]? } + end + def self.reset(signal) : Nil set(signal, LibC::SIG_DFL) end diff --git a/src/crystal/system/wasi/signal.cr b/src/crystal/system/wasi/signal.cr index d66b9c22c5cd..35675ce14f34 100644 --- a/src/crystal/system/wasi/signal.cr +++ b/src/crystal/system/wasi/signal.cr @@ -3,6 +3,10 @@ module Crystal::System::Signal raise NotImplementedError.new("Crystal::System::Signal.trap") end + def self.trap_handler?(signal) + raise NotImplementedError.new("Crystal::System::Signal.trap_handler?") + end + def self.reset(signal) : Nil raise NotImplementedError.new("Crystal::System::Signal.reset") end diff --git a/src/crystal/system/win32/signal.cr b/src/crystal/system/win32/signal.cr index 8f5541c7599b..d805ea4fd1ab 100644 --- a/src/crystal/system/win32/signal.cr +++ b/src/crystal/system/win32/signal.cr @@ -5,6 +5,10 @@ module Crystal::System::Signal raise NotImplementedError.new("Crystal::System::Signal.trap") end + def self.trap_handler?(signal) + raise NotImplementedError.new("Crystal::System::Signal.trap_handler?") + end + def self.reset(signal) : Nil raise NotImplementedError.new("Crystal::System::Signal.reset") end diff --git a/src/signal.cr b/src/signal.cr index 60eba5b8e7f3..2e085b92311e 100644 --- a/src/signal.cr +++ b/src/signal.cr @@ -117,6 +117,24 @@ enum Signal : Int32 Crystal::System::Signal.trap(self, handler) end + # Returns any existing handler for this signal + # + # ``` + # Signal::USR1.trap { } + # prev_handler = Signal::USR1.trap_handler? + # + # Signal::USR1.trap do |signal| + # prev_handler.try &.call(signal) + # # ... + # end + # ``` + def trap_handler? + {% if @type.has_constant?("CHLD") %} + return Crystal::System::Signal.child_handler if self == CHLD + {% end %} + Crystal::System::Signal.trap_handler?(self) + end + # Resets the handler for this signal to the OS default. # # Note that trying to reset `CHLD` will actually set the default crystal From dd5d2dd8b509ec514ad3c134aec1a4994a8415d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Wed, 10 Jan 2024 12:26:05 +0100 Subject: [PATCH 041/105] Bump VERSION to 1.11.1-dev (#14197) --- src/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/VERSION b/src/VERSION index 1cac385c6cb8..095b66727677 100644 --- a/src/VERSION +++ b/src/VERSION @@ -1 +1 @@ -1.11.0 +1.11.1-dev From bd43c5f6a806ead05b3a00afbc539fd38a01ccba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Wed, 10 Jan 2024 14:29:21 +0100 Subject: [PATCH 042/105] Remove pkg-config name for libgc as workaround for interpreter loader (#14198) --- src/gc/boehm.cr | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/gc/boehm.cr b/src/gc/boehm.cr index 8278f33b8e94..609f71189795 100644 --- a/src/gc/boehm.cr +++ b/src/gc/boehm.cr @@ -21,6 +21,12 @@ {% if flag?(:freebsd) || flag?(:dragonfly) %} @[Link("gc-threaded")] +{% elsif flag?(:interpreted) %} + # FIXME: We're not using the pkg-config name here because that would resolve the + # lib flags for libgc including `-lpthread` which the interpreter is not able + # to load on systems with modern libc where libpthread is only available as an + # (empty) static library. + @[Link("gc")] {% else %} @[Link("gc", pkg_config: "bdw-gc")] {% end %} From 9d52e30d4cda5c77b8ad59c20859a02c3db3d2f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Wed, 10 Jan 2024 16:25:45 +0100 Subject: [PATCH 043/105] Revert "Add `ReferenceStorage` for manual allocation of references (#14106)" (#14207) --- .../semantic/reference_storage_spec.cr | 40 -------------- spec/primitives/reference_spec.cr | 4 +- src/compiler/crystal/codegen/llvm_typer.cr | 4 -- src/compiler/crystal/program.cr | 6 +-- src/compiler/crystal/types.cr | 28 +--------- src/prelude.cr | 1 - src/reference_storage.cr | 54 ------------------- 7 files changed, 5 insertions(+), 132 deletions(-) delete mode 100644 spec/compiler/semantic/reference_storage_spec.cr delete mode 100644 src/reference_storage.cr diff --git a/spec/compiler/semantic/reference_storage_spec.cr b/spec/compiler/semantic/reference_storage_spec.cr deleted file mode 100644 index 791fed054275..000000000000 --- a/spec/compiler/semantic/reference_storage_spec.cr +++ /dev/null @@ -1,40 +0,0 @@ -require "../../spec_helper" - -describe "Semantic: ReferenceStorage" do - it "errors if T is a struct type" do - assert_error <<-CRYSTAL, "Can't instantiate ReferenceStorage(T) with T = Foo (T must be a reference type)" - struct Foo - @x = 1 - end - - ReferenceStorage(Foo) - CRYSTAL - end - - it "errors if T is a value type" do - assert_error <<-CRYSTAL, "Can't instantiate ReferenceStorage(T) with T = Int32 (T must be a reference type)" - ReferenceStorage(Int32) - CRYSTAL - end - - it "errors if T is a union type" do - assert_error <<-CRYSTAL, "Can't instantiate ReferenceStorage(T) with T = (Bar | Foo) (T must be a reference type)" - class Foo - end - - class Bar - end - - ReferenceStorage(Foo | Bar) - CRYSTAL - end - - it "errors if T is a nilable type" do - assert_error <<-CRYSTAL, "Can't instantiate ReferenceStorage(T) with T = (Foo | Nil) (T must be a reference type)" - class Foo - end - - ReferenceStorage(Foo?) - CRYSTAL - end -end diff --git a/spec/primitives/reference_spec.cr b/spec/primitives/reference_spec.cr index 52f179296ee8..b73553748b65 100644 --- a/spec/primitives/reference_spec.cr +++ b/spec/primitives/reference_spec.cr @@ -43,7 +43,9 @@ describe "Primitives: reference" do end it "works when address is on the stack" do - foo_buffer = uninitialized ReferenceStorage(Foo) + # suitably aligned, sufficient storage for type ID + i64 + ptr + # TODO: use `ReferenceStorage` instead + foo_buffer = uninitialized UInt64[3] foo = Foo.pre_initialize(pointerof(foo_buffer)) pointerof(foo_buffer).as(typeof(Foo.crystal_instance_type_id)*).value.should eq(Foo.crystal_instance_type_id) foo.str.should eq("abc") diff --git a/src/compiler/crystal/codegen/llvm_typer.cr b/src/compiler/crystal/codegen/llvm_typer.cr index d72a25ecd3cb..d20fbd59fa9a 100644 --- a/src/compiler/crystal/codegen/llvm_typer.cr +++ b/src/compiler/crystal/codegen/llvm_typer.cr @@ -245,10 +245,6 @@ module Crystal llvm_type(type.remove_alias, wants_size) end - private def create_llvm_type(type : ReferenceStorageType, wants_size) - llvm_struct_type(type.reference_type, wants_size) - end - private def create_llvm_type(type : NonGenericModuleType | GenericClassType, wants_size) # This can only be reached if the module or generic class don't have implementors @llvm_context.int1 diff --git a/src/compiler/crystal/program.cr b/src/compiler/crystal/program.cr index 6d3d185774af..936fc6a0a270 100644 --- a/src/compiler/crystal/program.cr +++ b/src/compiler/crystal/program.cr @@ -197,10 +197,6 @@ module Crystal types["Struct"] = struct_t = @struct_t = NonGenericClassType.new self, self, "Struct", value abstract_value_type(struct_t) - types["ReferenceStorage"] = @reference_storage = reference_storage = GenericReferenceStorageType.new self, self, "ReferenceStorage", value, ["T"] - reference_storage.declare_instance_var("@type_id", int32) - reference_storage.can_be_stored = false - types["Enumerable"] = @enumerable = GenericModuleType.new self, self, "Enumerable", ["T"] types["Indexable"] = @indexable = GenericModuleType.new self, self, "Indexable", ["T"] @@ -497,7 +493,7 @@ module Crystal {% for name in %w(object no_return value number reference void nil bool char int int8 int16 int32 int64 int128 uint8 uint16 uint32 uint64 uint128 float float32 float64 string symbol pointer enumerable indexable - array static_array reference_storage exception tuple named_tuple proc union enum range regex crystal + array static_array exception tuple named_tuple proc union enum range regex crystal packed_annotation thread_local_annotation no_inline_annotation always_inline_annotation naked_annotation returns_twice_annotation raises_annotation primitive_annotation call_convention_annotation diff --git a/src/compiler/crystal/types.cr b/src/compiler/crystal/types.cr index 64bcdda9a3d9..ad9f3d391fa6 100644 --- a/src/compiler/crystal/types.cr +++ b/src/compiler/crystal/types.cr @@ -550,7 +550,7 @@ module Crystal def allows_instance_vars? case self when program.object, program.value, program.struct, - program.reference, program.class_type, program.reference_storage, + program.reference, program.class_type, program.number, program.int, program.float, program.tuple, program.named_tuple, program.pointer, program.static_array, @@ -2642,32 +2642,6 @@ module Crystal end end - # The non-instantiated ReferenceStorage(T) type. - class GenericReferenceStorageType < GenericClassType - @struct = true - - def new_generic_instance(program, generic_type, type_vars) - t = type_vars["T"].type - - unless t.is_a?(TypeParameter) || (t.class? && !t.struct?) - raise TypeException.new "Can't instantiate ReferenceStorage(T) with T = #{t} (T must be a reference type)" - end - - ReferenceStorageType.new program, t - end - end - - class ReferenceStorageType < GenericClassInstanceType - getter reference_type : Type - - def initialize(program, @reference_type) - t_var = Var.new("T", @reference_type) - t_var.bind_to t_var - - super(program, program.reference_storage, program.struct, {"T" => t_var} of String => ASTNode) - end - end - # A lib type, like `lib LibC`. class LibType < ModuleType getter link_annotations : Array(LinkAnnotation)? diff --git a/src/prelude.cr b/src/prelude.cr index f84bb86cb3c1..f06f5bc87015 100644 --- a/src/prelude.cr +++ b/src/prelude.cr @@ -65,7 +65,6 @@ require "raise" require "random" require "range" require "reference" -require "reference_storage" require "regex" require "set" {% unless flag?(:wasm32) %} diff --git a/src/reference_storage.cr b/src/reference_storage.cr deleted file mode 100644 index 4f6e39a8cca0..000000000000 --- a/src/reference_storage.cr +++ /dev/null @@ -1,54 +0,0 @@ -# a `ReferenceStorage(T)` provides the minimum storage for the instance data of -# an object of type `T`. The compiler guarantees that -# `sizeof(ReferenceStorage(T)) == instance_sizeof(T)` and -# `alignof(ReferenceStorage(T)) == instance_alignof(T)` always hold, which means -# `Pointer(ReferenceStorage(T))` and `T` are binary-compatible. -# -# `T` must be a non-union reference type. -# -# WARNING: `ReferenceStorage` is only necessary for manual memory management, -# such as creating instances of `T` with a non-default allocator. Therefore, -# this type is unsafe and no public constructors are defined. -# -# WARNING: `ReferenceStorage` is unsuitable when instances of `T` require more -# than `instance_sizeof(T)` bytes, such as `String` and `Log::Metadata`. -@[Experimental("This type's API is still under development. Join the discussion about custom reference allocation at [#13481](https://github.com/crystal-lang/crystal/issues/13481).")] -struct ReferenceStorage(T) - private def initialize - end - - # Returns whether `self` and *other* are bytewise equal. - # - # NOTE: This does not call `T#==`, so it works even if `self` or *other* does - # not represent a valid instance of `T`. If validity is guaranteed, call - # `to_reference == other.to_reference` instead to use `T#==`. - def ==(other : ReferenceStorage(T)) : Bool - to_bytes == other.to_bytes - end - - def ==(other) : Bool - false - end - - def hash(hasher) - to_bytes.hash(hasher) - end - - def to_s(io : IO) : Nil - io << "ReferenceStorage(#<" << T << ":0x" - pointerof(@type_id).address.to_s(io, 16) - io << ">)" - end - - # Returns a `T` whose instance data refers to `self`. - # - # WARNING: The caller is responsible for ensuring that the instance data is - # correctly initialized and outlives the returned `T`. - def to_reference : T - pointerof(@type_id).as(T) - end - - protected def to_bytes - Slice.new(pointerof(@type_id).as(UInt8*), instance_sizeof(T)) - end -end From c3eb0eb62fe7a047516962497f6afabae3fd68a3 Mon Sep 17 00:00:00 2001 From: Julien Portalier <julien@portalier.com> Date: Wed, 10 Jan 2024 23:25:37 +0100 Subject: [PATCH 044/105] Use per-scheduler stack pools (let's recycle) (#14100) --- src/crystal/scheduler.cr | 46 +++++++++++++++++++--------------------- src/fiber.cr | 18 ++++------------ src/fiber/stack_pool.cr | 16 +++++++++----- src/kernel.cr | 12 +---------- 4 files changed, 38 insertions(+), 54 deletions(-) diff --git a/src/crystal/scheduler.cr b/src/crystal/scheduler.cr index ce06e3c60275..fa963595bf6d 100644 --- a/src/crystal/scheduler.cr +++ b/src/crystal/scheduler.cr @@ -2,6 +2,7 @@ require "crystal/system/event_loop" require "crystal/system/print_error" require "./fiber_channel" require "fiber" +require "fiber/stack_pool" require "crystal/system/thread" # :nodoc: @@ -13,6 +14,11 @@ require "crystal/system/thread" # protected and must never be called directly. class Crystal::Scheduler @event_loop = Crystal::EventLoop.create + @stack_pool = Fiber::StackPool.new + + def self.stack_pool : Fiber::StackPool + Thread.current.scheduler.@stack_pool + end def self.event_loop Thread.current.scheduler.@event_loop @@ -83,15 +89,8 @@ class Crystal::Scheduler {% end %} end - {% if flag?(:preview_mt) %} - def self.enqueue_free_stack(stack : Void*) : Nil - Thread.current.scheduler.enqueue_free_stack(stack) - end - {% end %} - {% if flag?(:preview_mt) %} private getter(fiber_channel : Crystal::FiberChannel) { Crystal::FiberChannel.new } - @free_stacks = Deque(Void*).new {% end %} @main : Fiber @@ -157,18 +156,6 @@ class Crystal::Scheduler exit 1 end - {% if flag?(:preview_mt) %} - protected def enqueue_free_stack(stack) - @free_stacks.push stack - end - - private def release_free_stacks - while stack = @free_stacks.shift? - Fiber.stack_pool.release stack - end - end - {% end %} - protected def reschedule : Nil loop do if runnable = @lock.sync { @runnables.shift? } @@ -178,10 +165,6 @@ class Crystal::Scheduler @event_loop.run_once end end - - {% if flag?(:preview_mt) %} - release_free_stacks - {% end %} end protected def sleep(time : Time::Span) : Nil @@ -207,6 +190,8 @@ class Crystal::Scheduler end def run_loop + spawn_stack_pool_collector + fiber_channel = self.fiber_channel loop do @lock.lock @@ -239,7 +224,7 @@ class Crystal::Scheduler @lock.unlock end - def self.init_workers + def self.init : Nil count = worker_count pending = Atomic(Int32).new(count - 1) @@workers = Array(Thread).new(count) do |i| @@ -281,5 +266,18 @@ class Crystal::Scheduler 4 end end + {% else %} + def self.init : Nil + {% unless flag?(:interpreted) %} + Thread.current.scheduler.spawn_stack_pool_collector + {% end %} + end {% end %} + + # Background loop to cleanup unused fiber stacks. + def spawn_stack_pool_collector + fiber = Fiber.new(name: "Stack pool collector", &->@stack_pool.collect_loop) + {% if flag?(:preview_mt) %} fiber.set_current_thread {% end %} + enqueue(fiber) + end end diff --git a/src/fiber.cr b/src/fiber.cr index aa2af7bf2229..c96184f3cf1f 100644 --- a/src/fiber.cr +++ b/src/fiber.cr @@ -1,6 +1,5 @@ require "crystal/system/thread_linked_list" require "./fiber/context" -require "./fiber/stack_pool" # :nodoc: @[NoInline] @@ -47,9 +46,6 @@ class Fiber # :nodoc: protected class_getter(fibers) { Thread::LinkedList(Fiber).new } - # :nodoc: - class_getter stack_pool = StackPool.new - @context : Context @stack : Void* @resume_event : Crystal::EventLoop::Event? @@ -89,10 +85,9 @@ class Fiber @context = Context.new @stack, @stack_bottom = {% if flag?(:interpreted) %} - # For interpreted mode we don't need a new stack, the stack is held by the interpreter {Pointer(Void).null, Pointer(Void).null} {% else %} - Fiber.stack_pool.checkout + Crystal::Scheduler.stack_pool.checkout {% end %} fiber_main = ->(f : Fiber) { f.run } @@ -153,14 +148,6 @@ class Fiber ex.inspect_with_backtrace(STDERR) STDERR.flush ensure - {% if flag?(:preview_mt) %} - Crystal::Scheduler.enqueue_free_stack @stack - {% elsif flag?(:interpreted) %} - # For interpreted mode we don't need a new stack, the stack is held by the interpreter - {% else %} - Fiber.stack_pool.release(@stack) - {% end %} - # Remove the current fiber from the linked list Fiber.inactive(self) @@ -170,6 +157,9 @@ class Fiber @timeout_select_action = nil @alive = false + {% unless flag?(:interpreted) %} + Crystal::Scheduler.stack_pool.release(@stack) + {% end %} Crystal::Scheduler.reschedule end diff --git a/src/fiber/stack_pool.cr b/src/fiber/stack_pool.cr index 54d03e4ffa5f..aebd82a0870f 100644 --- a/src/fiber/stack_pool.cr +++ b/src/fiber/stack_pool.cr @@ -7,14 +7,13 @@ class Fiber def initialize @deque = Deque(Void*).new - @mutex = Thread::Mutex.new end # Removes and frees at most *count* stacks from the top of the pool, # returning memory to the operating system. def collect(count = lazy_size // 2) : Nil count.times do - if stack = @mutex.synchronize { @deque.shift? } + if stack = @deque.shift? Crystal::System::Fiber.free_stack(stack, STACK_SIZE) else return @@ -22,21 +21,28 @@ class Fiber end end + def collect_loop(every = 5.seconds) : Nil + loop do + sleep every + collect + end + end + # Removes a stack from the bottom of the pool, or allocates a new one. def checkout : {Void*, Void*} - stack = @mutex.synchronize { @deque.pop? } || Crystal::System::Fiber.allocate_stack(STACK_SIZE) + stack = @deque.pop? || Crystal::System::Fiber.allocate_stack(STACK_SIZE) {stack, stack + STACK_SIZE} end # Appends a stack to the bottom of the pool. def release(stack) : Nil - @mutex.synchronize { @deque.push(stack) } + @deque.push(stack) end # Returns the approximated size of the pool. It may be equal or slightly # bigger or smaller than the actual size. def lazy_size : Int32 - @mutex.synchronize { @deque.size } + @deque.size end end end diff --git a/src/kernel.cr b/src/kernel.cr index c3b3106ccae3..d3817ee11661 100644 --- a/src/kernel.cr +++ b/src/kernel.cr @@ -563,14 +563,6 @@ end {% end %} {% unless flag?(:interpreted) || flag?(:wasm32) %} - # Background loop to cleanup unused fiber stacks. - spawn(name: "Fiber Clean Loop") do - loop do - sleep 5 - Fiber.stack_pool.collect - end - end - {% if flag?(:win32) %} Crystal::System::Process.start_interrupt_loop {% else %} @@ -586,7 +578,5 @@ end Exception::CallStack.load_debug_info if ENV["CRYSTAL_LOAD_DEBUG_INFO"]? == "1" Exception::CallStack.setup_crash_handler - {% if flag?(:preview_mt) %} - Crystal::Scheduler.init_workers - {% end %} + Crystal::Scheduler.init {% end %} From b56c7d9db282e054401211e38b832cb3e2f79963 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Thu, 11 Jan 2024 06:25:48 +0800 Subject: [PATCH 045/105] Allow multiple parameters and blocks for operators ending in `=` (#14159) --- spec/compiler/parser/parser_spec.cr | 8 +++++++- src/compiler/crystal/syntax/parser.cr | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/spec/compiler/parser/parser_spec.cr b/spec/compiler/parser/parser_spec.cr index 41fad5cc3a89..2fa1a5b4c4a7 100644 --- a/spec/compiler/parser/parser_spec.cr +++ b/spec/compiler/parser/parser_spec.cr @@ -290,10 +290,16 @@ module Crystal assert_syntax_error "def foo=(*args); end", "setter method 'foo=' cannot have more than one parameter" assert_syntax_error "def foo=(**kwargs); end", "setter method 'foo=' cannot have more than one parameter" assert_syntax_error "def foo=(&block); end", "setter method 'foo=' cannot have a block" - assert_syntax_error "def []=(&block); end", "setter method '[]=' cannot have a block" assert_syntax_error "f.[]= do |a| end", "setter method '[]=' cannot be called with a block" assert_syntax_error "f.[]= { |bar| }", "setter method '[]=' cannot be called with a block" + # #10397 + %w(<= >= == != []= ===).each do |operator| + it_parses "def #{operator}(other, file = 1); end", Def.new(operator, ["other".arg, Arg.new("file", 1.int32)]) + it_parses "def #{operator}(*args, **opts); end", Def.new(operator, ["args".arg], splat_index: 0, double_splat: "opts".arg) + it_parses "def #{operator}(*args, **opts, &); end", Def.new(operator, ["args".arg], splat_index: 0, double_splat: "opts".arg, block_arg: Arg.new(""), block_arity: 0) + end + # #5895, #6042, #5997 %w( begin nil true false yield with abstract diff --git a/src/compiler/crystal/syntax/parser.cr b/src/compiler/crystal/syntax/parser.cr index 751608468cd5..f14399212e65 100644 --- a/src/compiler/crystal/syntax/parser.cr +++ b/src/compiler/crystal/syntax/parser.cr @@ -3658,8 +3658,8 @@ module Crystal end_location = token_end_location - if name.ends_with?('=') - if name != "[]=" && (params.size > 1 || found_splat || found_double_splat) + if Lexer.setter?(name) + if params.size > 1 || found_splat || found_double_splat raise "setter method '#{name}' cannot have more than one parameter" elsif found_block raise "setter method '#{name}' cannot have a block" From 79b6e730135762420fcf12ca066202a93e9ecca6 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Thu, 11 Jan 2024 06:26:03 +0800 Subject: [PATCH 046/105] Always use `%p` for pointers in `Crystal::System.print_error` (#14186) --- src/crystal/system/unix/signal.cr | 2 +- src/exception/call_stack/libunwind.cr | 2 +- src/exception/call_stack/stackwalk.cr | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/crystal/system/unix/signal.cr b/src/crystal/system/unix/signal.cr index 58b1180f56ef..d0fdbf298391 100644 --- a/src/crystal/system/unix/signal.cr +++ b/src/crystal/system/unix/signal.cr @@ -153,7 +153,7 @@ module Crystal::System::Signal if is_stack_overflow Crystal::System.print_error "Stack overflow (e.g., infinite or very deep recursion)\n" else - Crystal::System.print_error "Invalid memory access (signal %d) at address 0x%lx\n", sig, addr + Crystal::System.print_error "Invalid memory access (signal %d) at address %p\n", sig, addr end Exception::CallStack.print_backtrace diff --git a/src/exception/call_stack/libunwind.cr b/src/exception/call_stack/libunwind.cr index 220db21b71f0..81943d99f376 100644 --- a/src/exception/call_stack/libunwind.cr +++ b/src/exception/call_stack/libunwind.cr @@ -102,7 +102,7 @@ struct Exception::CallStack end private def self.print_frame(repeated_frame) - Crystal::System.print_error "[0x%llx] ", repeated_frame.ip.address.to_u64 + Crystal::System.print_error "[%p] ", repeated_frame.ip.address print_frame_location(repeated_frame) Crystal::System.print_error " (%d times)", repeated_frame.count + 1 unless repeated_frame.count == 0 Crystal::System.print_error "\n" diff --git a/src/exception/call_stack/stackwalk.cr b/src/exception/call_stack/stackwalk.cr index f49c87fae623..4879ed8bb95d 100644 --- a/src/exception/call_stack/stackwalk.cr +++ b/src/exception/call_stack/stackwalk.cr @@ -37,7 +37,7 @@ struct Exception::CallStack case exception_info.value.exceptionRecord.value.exceptionCode when LibC::EXCEPTION_ACCESS_VIOLATION addr = exception_info.value.exceptionRecord.value.exceptionInformation[1] - Crystal::System.print_error "Invalid memory access (C0000005) at address 0x%llx\n", addr + Crystal::System.print_error "Invalid memory access (C0000005) at address %p\n", Pointer(Void).new(addr) print_backtrace(exception_info) LibC._exit(1) when LibC::EXCEPTION_STACK_OVERFLOW @@ -150,7 +150,7 @@ struct Exception::CallStack end private def self.print_frame(repeated_frame) - Crystal::System.print_error "[0x%llx] ", repeated_frame.ip.address.to_u64 + Crystal::System.print_error "[%p] ", repeated_frame.ip.address print_frame_location(repeated_frame) Crystal::System.print_error " (%d times)", repeated_frame.count + 1 unless repeated_frame.count == 0 Crystal::System.print_error "\n" From 83ce2bc9223c1add3a72ecdd85c693e673e87d81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Thu, 11 Jan 2024 16:46:26 +0100 Subject: [PATCH 047/105] Revert "Fix OpenSSL error handling for EOF (support for OpenSSL 3.2) (#14169)" (#14217) Fix OpenSSL error handling for EOF (support for OpenSSL 3.2) (#14169)" --- src/openssl.cr | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/openssl.cr b/src/openssl.cr index f34ee169b4cc..802c9a05e7d3 100644 --- a/src/openssl.cr +++ b/src/openssl.cr @@ -89,14 +89,15 @@ module OpenSSL when .syscall? @code, message = fetch_error_details if @code == 0 - errno = {% if flag?(:win32) %} WinError.wsa_value {% else %} Errno.value {% end %} - success = {% if flag?(:win32) %} errno.error_success? {% else %} errno.none? {% end %} - if success + case return_code + when 0 message = "Unexpected EOF" @underlying_eof = true - else - cause = RuntimeError.from_os_error(func || "OpenSSL", os_error: errno) + when -1 + cause = RuntimeError.from_errno(func || "OpenSSL") message = "I/O error" + else + message = "Unknown error" end end when .ssl? From 0aa30372c4aebfb681fe20483fcdd463cdb5cd57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Thu, 11 Jan 2024 21:15:37 +0100 Subject: [PATCH 048/105] Changelog for 1.11.1 (#14208) --- CHANGELOG.md | 20 ++++++++++++++++++++ src/VERSION | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bedb4a96a97..658d9f42f822 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,25 @@ # Changelog +## [1.11.1] (2024-01-11) + +[1.11.1]: https://github.com/crystal-lang/crystal/releases/1.11.1 + +### Bugfixes + +#### stdlib + +- *(crypto)* Revert "Fix OpenSSL error handling for EOF (support for OpenSSL 3.2) (#14169)" ([#14217](https://github.com/crystal-lang/crystal/pull/14217), thanks @straight-shoota) + +#### compiler + +- *(interpreter)* Remove pkg-config name for libgc as workaround for interpreter loader ([#14198](https://github.com/crystal-lang/crystal/pull/14198), thanks @straight-shoota) +- *(semantic)* Revert "Add `ReferenceStorage` for manual allocation of references (#14106)" ([#14207](https://github.com/crystal-lang/crystal/pull/14207), thanks @straight-shoota) + +### Infrastructure + +- Changelog for 1.11.1 ([#14208](https://github.com/crystal-lang/crystal/pull/14208), thanks @straight-shoota) +- Bump VERSION to 1.11.1-dev ([#14197](https://github.com/crystal-lang/crystal/pull/14197), thanks @straight-shoota) + ## [1.11.0] (2024-01-08) [1.11.0]: https://github.com/crystal-lang/crystal/releases/1.11.0 diff --git a/src/VERSION b/src/VERSION index 095b66727677..720c7384c619 100644 --- a/src/VERSION +++ b/src/VERSION @@ -1 +1 @@ -1.11.1-dev +1.11.1 From 7867cd8071a3816ecc3c0fdd4a7f4c02fbd6e8aa Mon Sep 17 00:00:00 2001 From: Jack <jack@kilmer.co> Date: Fri, 12 Jan 2024 06:19:34 -0600 Subject: [PATCH 049/105] Enhance docs for `Int#downto` (#14176) Co-authored-by: George Dietrich <george@dietrich.app> --- src/int.cr | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/int.cr b/src/int.cr index 005d2c625c7b..b36ddba14e9e 100644 --- a/src/int.cr +++ b/src/int.cr @@ -567,6 +567,20 @@ struct Int end # Calls the given block with each integer value from self down to `to`. + # + # ``` + # 3.downto(1) do |i| + # puts i + # end + # ``` + # + # Prints: + # + # ```text + # 3 + # 2 + # 1 + # ``` def downto(to, &block : self ->) : Nil return unless self >= to x = self From 6bfcfe8e9910a10c383cc51b4c34bc049d1d661f Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Fri, 12 Jan 2024 20:19:48 +0800 Subject: [PATCH 050/105] Move most of spec runner's state into `Spec::CLI` (#14170) --- spec/compiler/interpreter/spec_helper.cr | 24 ++- spec/std/log/env_config_spec.cr | 2 +- src/compiler/crystal/command/spec.cr | 2 +- src/spec.cr | 74 +++---- src/spec/cli.cr | 223 ++++++++++---------- src/spec/context.cr | 38 ++-- src/spec/dsl.cr | 249 ++++++++++++----------- src/spec/example.cr | 10 +- src/spec/formatter.cr | 28 ++- src/spec/methods.cr | 30 +-- 10 files changed, 353 insertions(+), 327 deletions(-) diff --git a/spec/compiler/interpreter/spec_helper.cr b/spec/compiler/interpreter/spec_helper.cr index e6aeb240674c..3c6f88ab1679 100644 --- a/spec/compiler/interpreter/spec_helper.cr +++ b/spec/compiler/interpreter/spec_helper.cr @@ -24,18 +24,20 @@ end # In a nutshell, `interpret_in_separate_process` below calls this same process with an extra option that causes # the interpretation of the code from stdin, reading the output from stdout. That string is used as the result of # the program being tested. -def Spec.option_parser - option_parser = previous_def - option_parser.on("", "--interpret-code PRELUDE", "Execute interpreted code") do |prelude| - code = STDIN.gets_to_end - - repl = Crystal::Repl.new - repl.prelude = prelude - - print repl.run_code(code) - exit +class Spec::CLI + def option_parser + option_parser = previous_def + option_parser.on("", "--interpret-code PRELUDE", "Execute interpreted code") do |prelude| + code = STDIN.gets_to_end + + repl = Crystal::Repl.new + repl.prelude = prelude + + print repl.run_code(code) + exit + end + option_parser end - option_parser end def interpret_in_separate_process(code, prelude, file = __FILE__, line = __LINE__) diff --git a/spec/std/log/env_config_spec.cr b/spec/std/log/env_config_spec.cr index 7bfdfb0f239a..5ddc2941b82a 100644 --- a/spec/std/log/env_config_spec.cr +++ b/spec/std/log/env_config_spec.cr @@ -10,7 +10,7 @@ end describe "Log.setup_from_env" do after_all do # Setup logging in specs (again) since these specs perform Log.setup - Spec.log_setup + Spec.cli.log_setup end describe "backend" do diff --git a/src/compiler/crystal/command/spec.cr b/src/compiler/crystal/command/spec.cr index ff8f47b11859..ce34b2ac4155 100644 --- a/src/compiler/crystal/command/spec.cr +++ b/src/compiler/crystal/command/spec.cr @@ -24,7 +24,7 @@ class Crystal::Command puts opts puts - runtime_options = Spec.option_parser + runtime_options = Spec::CLI.new.option_parser runtime_options.banner = "Runtime options (passed to spec runner):" puts runtime_options exit diff --git a/src/spec.cr b/src/spec.cr index e9cf5d448efd..c51ee8831de4 100644 --- a/src/spec.cr +++ b/src/spec.cr @@ -91,45 +91,51 @@ require "./spec/cli" # value can be used to rerun the specs in that same order by passing the seed # value to `--order`. module Spec -end + # :nodoc: + class CLI + # :nodoc: + # + # Implement formatter configuration. + def configure_formatter(formatter, output_path = nil) + case formatter + when "junit" + junit_formatter = Spec::JUnitFormatter.file(Path.new(output_path.not_nil!)) + add_formatter(junit_formatter) + when "verbose" + override_default_formatter(Spec::VerboseFormatter.new) + when "tap" + override_default_formatter(Spec::TAPFormatter.new) + end + end -Colorize.on_tty_only! + def main(args) + Colorize.on_tty_only! -# :nodoc: -# -# Implement formatter configuration. -def Spec.configure_formatter(formatter, output_path = nil) - case formatter - when "junit" - junit_formatter = Spec::JUnitFormatter.file(Path.new(output_path.not_nil!)) - Spec.add_formatter(junit_formatter) - when "verbose" - Spec.override_default_formatter(Spec::VerboseFormatter.new) - when "tap" - Spec.override_default_formatter(Spec::TAPFormatter.new) - end -end + begin + option_parser.parse(args) + rescue e : OptionParser::InvalidOption + abort("Error: #{e.message}") + end -begin - Spec.option_parser.parse(ARGV) -rescue e : OptionParser::InvalidOption - abort("Error: #{e.message}") -end + unless args.empty? + STDERR.puts "Error: unknown argument '#{args.first}'" + exit 1 + end -unless ARGV.empty? - STDERR.puts "Error: unknown argument '#{ARGV.first}'" - exit 1 -end + if ENV["SPEC_VERBOSE"]? == "1" + override_default_formatter(Spec::VerboseFormatter.new) + end -if ENV["SPEC_VERBOSE"]? == "1" - Spec.override_default_formatter(Spec::VerboseFormatter.new) -end + add_split_filter ENV["SPEC_SPLIT"]? -Spec.add_split_filter ENV["SPEC_SPLIT"]? + {% unless flag?(:wasm32) %} + # TODO(wasm): Enable this once `Process.on_interrupt` is implemented + Process.on_interrupt { abort! } + {% end %} -{% unless flag?(:wasm32) %} - # TODO(wasm): Enable this once `Process.on_interrupt` is implemented - Process.on_interrupt { Spec.abort! } -{% end %} + run + end + end +end -Spec.run +Spec.cli.main(ARGV) diff --git a/src/spec/cli.cr b/src/spec/cli.cr index e17f59206123..4f57c3d4adbb 100644 --- a/src/spec/cli.cr +++ b/src/spec/cli.cr @@ -1,139 +1,130 @@ require "option_parser" +require "colorize" # This file is included in the compiler to add usage instructions for the # spec runner on `crystal spec --help`. module Spec # :nodoc: - class_property pattern : Regex? - - # :nodoc: - class_property line : Int32? - - # :nodoc: - class_property slowest : Int32? - - # :nodoc: - class_property? fail_fast = false - - # :nodoc: - class_property? focus = false - - # :nodoc: - class_property? dry_run = false - - # :nodoc: - class_property? list_tags = false - - # :nodoc: - def self.add_location(file, line) - locations = @@locations ||= {} of String => Array(Int32) - locations.put_if_absent(File.expand_path(file)) { [] of Int32 } << line - end + # + # Configuration for a spec runner. More global state is defined in `./dsl.cr`. + class CLI + getter pattern : Regex? + getter line : Int32? + getter slowest : Int32? + getter? fail_fast = false + property? focus = false + getter? dry_run = false + getter? list_tags = false - # :nodoc: - def self.add_tag(tag) - if anti_tag = tag.lchop?('~') - (@@anti_tags ||= Set(String).new) << anti_tag - else - (@@tags ||= Set(String).new) << tag + def add_location(file, line) + locations = @locations ||= {} of String => Array(Int32) + locations.put_if_absent(File.expand_path(file)) { [] of Int32 } << line end - end - - # :nodoc: - class_getter randomizer_seed : UInt64? - class_getter randomizer : Random::PCG32? - # :nodoc: - def self.order=(mode) - seed = - case mode - when "default" - nil - when "random" - Random::Secure.rand(1..99999).to_u64 # 5 digits or less for simplicity - when UInt64 - mode + def add_tag(tag) + if anti_tag = tag.lchop?('~') + (@anti_tags ||= Set(String).new) << anti_tag else - raise ArgumentError.new("Order must be either 'default', 'random', or a numeric seed value") + (@tags ||= Set(String).new) << tag end + end - @@randomizer_seed = seed - @@randomizer = seed ? Random::PCG32.new(seed) : nil - end + getter randomizer_seed : UInt64? + getter randomizer : Random::PCG32? - # :nodoc: - class_property option_parser : OptionParser = begin - OptionParser.new do |opts| - opts.banner = "crystal spec runner" - opts.on("-e", "--example STRING", "run examples whose full nested names include STRING") do |pattern| - Spec.pattern = Regex.new(Regex.escape(pattern)) - end - opts.on("-l", "--line LINE", "run examples whose line matches LINE") do |line| - Spec.line = line.to_i - end - opts.on("-p", "--profile", "Print the 10 slowest specs") do - Spec.slowest = 10 - end - opts.on("--fail-fast", "abort the run on first failure") do - Spec.fail_fast = true - end - opts.on("--location file:line", "run example at line 'line' in file 'file', multiple allowed") do |location| - if location =~ /\A(.+?)\:(\d+)\Z/ - Spec.add_location $1, $2.to_i + def order=(mode) + seed = + case mode + when "default" + nil + when "random" + Random::Secure.rand(1..99999).to_u64 # 5 digits or less for simplicity + when UInt64 + mode else - STDERR.puts "location #{location} must be file:line" - exit 1 + raise ArgumentError.new("Order must be either 'default', 'random', or a numeric seed value") end - end - opts.on("--tag TAG", "run examples with the specified TAG, or exclude examples by adding ~ before the TAG.") do |tag| - Spec.add_tag tag - end - opts.on("--list-tags", "lists all the tags used.") do - Spec.list_tags = true - end - opts.on("--order MODE", "run examples in random order by passing MODE as 'random' or to a specific seed by passing MODE as the seed value") do |mode| - if mode.in?("default", "random") - Spec.order = mode - elsif seed = mode.to_u64? - Spec.order = seed - else - abort("order must be either 'default', 'random', or a numeric seed value") + + @randomizer_seed = seed + @randomizer = seed ? Random::PCG32.new(seed) : nil + end + + def option_parser : OptionParser + @option_parser ||= OptionParser.new do |opts| + opts.banner = "crystal spec runner" + opts.on("-e", "--example STRING", "run examples whose full nested names include STRING") do |pattern| + @pattern = Regex.new(Regex.escape(pattern)) + end + opts.on("-l", "--line LINE", "run examples whose line matches LINE") do |line| + @line = line.to_i + end + opts.on("-p", "--profile", "Print the 10 slowest specs") do + @slowest = 10 + end + opts.on("--fail-fast", "abort the run on first failure") do + @fail_fast = true + end + opts.on("--location file:line", "run example at line 'line' in file 'file', multiple allowed") do |location| + if location =~ /\A(.+?)\:(\d+)\Z/ + add_location $1, $2.to_i + else + STDERR.puts "location #{location} must be file:line" + exit 1 + end + end + opts.on("--tag TAG", "run examples with the specified TAG, or exclude examples by adding ~ before the TAG.") do |tag| + add_tag tag + end + opts.on("--list-tags", "lists all the tags used.") do + @list_tags = true + end + opts.on("--order MODE", "run examples in random order by passing MODE as 'random' or to a specific seed by passing MODE as the seed value") do |mode| + if mode.in?("default", "random") + self.order = mode + elsif seed = mode.to_u64? + self.order = seed + else + abort("order must be either 'default', 'random', or a numeric seed value") + end + end + opts.on("--junit_output OUTPUT_PATH", "generate JUnit XML output within the given OUTPUT_PATH") do |output_path| + configure_formatter("junit", output_path) + end + opts.on("-h", "--help", "show this help") do |pattern| + puts opts + exit + end + opts.on("-v", "--verbose", "verbose output") do + configure_formatter("verbose") + end + opts.on("--tap", "Generate TAP output (Test Anything Protocol)") do + configure_formatter("tap") + end + opts.on("--color", "Enabled ANSI colored output") do + Colorize.enabled = true + end + opts.on("--no-color", "Disable ANSI colored output") do + Colorize.enabled = false + end + opts.on("--dry-run", "Pass all tests without execution") do + @dry_run = true + end + opts.unknown_args do |args| end - end - opts.on("--junit_output OUTPUT_PATH", "generate JUnit XML output within the given OUTPUT_PATH") do |output_path| - configure_formatter("junit", output_path) - end - opts.on("-h", "--help", "show this help") do |pattern| - puts opts - exit - end - opts.on("-v", "--verbose", "verbose output") do - configure_formatter("verbose") - end - opts.on("--tap", "Generate TAP output (Test Anything Protocol)") do - configure_formatter("tap") - end - opts.on("--color", "Enabled ANSI colored output") do - Colorize.enabled = true - end - opts.on("--no-color", "Disable ANSI colored output") do - Colorize.enabled = false - end - opts.on("--dry-run", "Pass all tests without execution") do - Spec.dry_run = true - end - opts.unknown_args do |args| end end + + # Blank implementation to reduce the interface of spec's option parser for + # inclusion in the compiler. This avoids depending on more of `Spec` + # module. + # The real implementation in `../spec.cr` overrides this for actual use. + def configure_formatter(formatter, output_path = nil) + end end - # :nodoc: - # - # Blank implementation to reduce the interface of spec's option parser for - # inclusion in the compiler. This avoids depending on more of `Spec` - # module. - # The real implementation in `../spec.cr` overrides this for actual use. - def self.configure_formatter(formatter, output_path = nil) + @[Deprecated("This is an internal API.")] + def self.randomizer : Random::PCG32? + @@cli.randomizer end end diff --git a/src/spec/context.cr b/src/spec/context.cr index 0a1109c12b92..c18836fe0455 100644 --- a/src/spec/context.cr +++ b/src/spec/context.cr @@ -126,13 +126,15 @@ module Spec exception : Exception? # :nodoc: - def self.root_context - RootContext.instance - end + class CLI + def root_context + RootContext.instance + end - # :nodoc: - def self.current_context : Context - RootContext.current_context + # :nodoc: + def current_context : Context + RootContext.current_context + end end # :nodoc: @@ -167,7 +169,7 @@ module Spec end def report_formatters(result) - Spec.formatters.each(&.report(result)) + Spec.cli.formatters.each(&.report(result)) end def succeeded @@ -175,8 +177,8 @@ module Spec end def finish(elapsed_time, aborted = false) - Spec.formatters.each(&.finish(elapsed_time, aborted)) - Spec.formatters.each(&.print_results(elapsed_time, aborted)) + Spec.cli.formatters.each(&.finish(elapsed_time, aborted)) + Spec.cli.formatters.each(&.print_results(elapsed_time, aborted)) end def print_results(elapsed_time, aborted = false) @@ -223,13 +225,13 @@ module Spec end end - if Spec.slowest + if Spec.cli.slowest puts results = results_for(:success) + results_for(:fail) - top_n = results.sort_by { |res| -res.elapsed.not_nil!.to_f }[0..Spec.slowest.not_nil!] + top_n = results.sort_by { |res| -res.elapsed.not_nil!.to_f }[0..Spec.cli.slowest.not_nil!] top_n_time = top_n.sum &.elapsed.not_nil!.total_seconds percent = (top_n_time * 100) / elapsed_time.total_seconds - puts "Top #{Spec.slowest} slowest examples (#{top_n_time.humanize} seconds, #{percent.round(2)}% of total time):" + puts "Top #{Spec.cli.slowest} slowest examples (#{top_n_time.humanize} seconds, #{percent.round(2)}% of total time):" top_n.each do |res| puts " #{res.description}" res_elapsed = res.elapsed.not_nil!.total_seconds.humanize @@ -252,7 +254,7 @@ module Spec puts "Aborted!".colorize.red if aborted puts "Finished in #{Spec.to_human(elapsed_time)}" puts Spec.color("#{total} examples, #{failures.size} failures, #{errors.size} errors, #{pendings.size} pending", final_status) - puts Spec.color("Only running `focus: true`", :focus) if Spec.focus? + puts Spec.color("Only running `focus: true`", :focus) if Spec.cli.focus? unless failures_and_errors.empty? puts @@ -268,13 +270,13 @@ module Spec end def print_order_message - if randomizer_seed = Spec.randomizer_seed + if randomizer_seed = Spec.cli.randomizer_seed puts Spec.color("Randomized with seed: #{randomizer_seed}", :order) end end def describe(description, file, line, end_line, focus, tags, &block) - Spec.focus = true if focus + Spec.cli.focus = true if focus context = Spec::ExampleGroup.new(@@current_context, description, file, line, end_line, focus, tags) @@current_context.children << context @@ -298,7 +300,7 @@ module Spec private def add_example(description, file, line, end_line, focus, tags, block) check_nesting_spec(file, line) do - Spec.focus = true if focus + Spec.cli.focus = true if focus @@current_context.children << Example.new(@@current_context, description, file, line, end_line, focus, tags, block) end @@ -334,12 +336,12 @@ module Spec # :nodoc: def run - Spec.formatters.each(&.push(self)) + Spec.cli.formatters.each(&.push(self)) ran = run_around_all_hooks(ExampleGroup::Procsy.new(self) { internal_run }) ran || internal_run - Spec.formatters.each(&.pop) + Spec.cli.formatters.each(&.pop) end protected def report(status : Status, description, file, line, elapsed = nil, ex = nil) diff --git a/src/spec/dsl.cr b/src/spec/dsl.cr index 065b31e7aff4..578076b86d69 100644 --- a/src/spec/dsl.cr +++ b/src/spec/dsl.cr @@ -2,6 +2,10 @@ require "colorize" require "option_parser" module Spec + # :nodoc: + # The default spec runner. + class_getter cli = CLI.new + # :nodoc: enum InfoKind Comment @@ -61,14 +65,6 @@ module Spec class NestingSpecError < SpecError end - @@aborted = false - - # :nodoc: - def self.abort! - @@aborted = true - finish_run - end - # :nodoc: def self.to_human(span : Time::Span) total_milliseconds = span.total_milliseconds @@ -92,17 +88,6 @@ module Spec record SplitFilter, remainder : Int32, quotient : Int32 - @@split_filter : SplitFilter? = nil - - def self.add_split_filter(filter) - if filter - r, _, m = filter.partition('%') - @@split_filter = SplitFilter.new(remainder: r.to_i, quotient: m.to_i) - else - @@split_filter = nil - end - end - # Instructs the spec runner to execute the given block # before each spec in the spec suite. # @@ -118,7 +103,7 @@ module Spec # # will print, just before each spec, 1 and then 2. def self.before_each(&block) - root_context.before_each(&block) + @@cli.root_context.before_each(&block) end # Instructs the spec runner to execute the given block @@ -136,7 +121,7 @@ module Spec # # will print, just after each spec, 2 and then 1. def self.after_each(&block) - root_context.after_each(&block) + @@cli.root_context.after_each(&block) end # Instructs the spec runner to execute the given block @@ -154,7 +139,7 @@ module Spec # # will print, just before the spec suite starts, 1 and then 2. def self.before_suite(&block) - root_context.before_all(&block) + @@cli.root_context.before_all(&block) end # Instructs the spec runner to execute the given block @@ -172,7 +157,7 @@ module Spec # # will print, just after the spec suite ends, 2 and then 1. def self.after_suite(&block) - root_context.after_all(&block) + @@cli.root_context.after_all(&block) end # Instructs the spec runner to execute the given block when each spec in the @@ -196,129 +181,157 @@ module Spec # it { } # ``` def self.around_each(&block : Example::Procsy ->) - root_context.around_each(&block) + @@cli.root_context.around_each(&block) end - @@start_time : Time::Span? = nil - # :nodoc: - def self.run - @@start_time = Time.monotonic - - at_exit do |status| - # Do not run specs if the process is exiting on an error - next unless status == 0 - - begin - if Spec.list_tags? - execute_list_tags - else - execute_examples + class CLI + @aborted = false + + def abort! + @aborted = true + finish_run + end + + @split_filter : SplitFilter? = nil + + def add_split_filter(filter) + if filter + r, _, m = filter.partition('%') + @split_filter = SplitFilter.new(remainder: r.to_i, quotient: m.to_i) + else + @split_filter = nil + end + end + + @start_time : Time::Span? = nil + + def run + @start_time = Time.monotonic + + at_exit do |status| + # Do not run specs if the process is exiting on an error + next unless status == 0 + + begin + if list_tags? + execute_list_tags + else + execute_examples + end + rescue ex + STDERR.print "Unhandled exception: " + ex.inspect_with_backtrace(STDERR) + STDERR.flush + @aborted = true + ensure + finish_run unless list_tags? end - rescue ex - STDERR.print "Unhandled exception: " - ex.inspect_with_backtrace(STDERR) - STDERR.flush - @@aborted = true - ensure - finish_run unless Spec.list_tags? end end - end - # :nodoc: - def self.execute_examples - log_setup - maybe_randomize - run_filters - root_context.run - end + def execute_examples + log_setup + maybe_randomize + run_filters + root_context.run + end - # :nodoc: - def self.execute_list_tags - run_filters - tag_counts = collect_tags(root_context) - print_list_tags(tag_counts) - end + def execute_list_tags + run_filters + tag_counts = collect_tags(root_context) + print_list_tags(tag_counts) + end - private def self.collect_tags(context) : Hash(String, Int32) - tag_counts = Hash(String, Int32).new(0) - collect_tags(tag_counts, context, Set(String).new) - tag_counts - end + private def collect_tags(context) : Hash(String, Int32) + tag_counts = Hash(String, Int32).new(0) + collect_tags(tag_counts, context, Set(String).new) + tag_counts + end - private def self.collect_tags(tag_counts, context : Context, tags) - if context.responds_to?(:tags) && (context_tags = context.tags) - tags += context_tags + private def collect_tags(tag_counts, context : Context, tags) + if context.responds_to?(:tags) && (context_tags = context.tags) + tags += context_tags + end + context.children.each do |child| + collect_tags(tag_counts, child, tags) + end end - context.children.each do |child| - collect_tags(tag_counts, child, tags) + + private def collect_tags(tag_counts, example : Example, tags) + if example_tags = example.tags + tags += example_tags + end + if tags.empty? + tag_counts.update("untagged") { |count| count + 1 } + else + tags.tally(tag_counts) + end end - end - private def self.collect_tags(tag_counts, example : Example, tags) - if example_tags = example.tags - tags += example_tags + private def print_list_tags(tag_counts : Hash(String, Int32)) : Nil + return if tag_counts.empty? + longest_name_size = tag_counts.keys.max_of(&.size) + tag_counts.to_a.sort_by! { |k, v| {-v, k} }.each do |tag_name, count| + puts "#{tag_name.rjust(longest_name_size)}: #{count}" + end end - if tags.empty? - tag_counts.update("untagged") { |count| count + 1 } - else - tags.tally(tag_counts) + + # :nodoc: + # + # Workaround for #8914 + private macro defined?(t) + {% if t.resolve? %} + {{ yield }} + {% end %} end - end - private def self.print_list_tags(tag_counts : Hash(String, Int32)) : Nil - return if tag_counts.empty? - longest_name_size = tag_counts.keys.max_of(&.size) - tag_counts.to_a.sort_by! { |k, v| {-v, k} }.each do |tag_name, count| - puts "#{tag_name.rjust(longest_name_size)}: #{count}" + # :nodoc: + def log_setup end - end - # :nodoc: - # - # Workaround for #8914 - private macro defined?(t) - {% if t.resolve? %} - {{ yield }} - {% end %} - end + # :nodoc: + macro finished + # :nodoc: + # + # Initialized the log module for the specs. + # If the "log" module is required it is configured to emit no entries by default. + def log_setup + defined?(::Log) do + if Log.responds_to?(:setup) + Log.setup_from_env(default_level: :none) + end + end + end + end - # :nodoc: - def self.log_setup - end + def finish_run + elapsed_time = Time.monotonic - @start_time.not_nil! + root_context.finish(elapsed_time, @aborted) + exit 1 if !root_context.succeeded || @aborted || (focus? && ENV["SPEC_FOCUS_NO_FAIL"]? != "1") + end - # :nodoc: - macro finished # :nodoc: - # - # Initialized the log module for the specs. - # If the "log" module is required it is configured to emit no entries by default. - def self.log_setup - defined?(::Log) do - if Log.responds_to?(:setup) - Log.setup_from_env(default_level: :none) - end + def maybe_randomize + if randomizer = @randomizer + root_context.randomize(randomizer) end end - end - def self.finish_run - elapsed_time = Time.monotonic - @@start_time.not_nil! - root_context.finish(elapsed_time, @@aborted) - exit 1 if !root_context.succeeded || @@aborted || (focus? && ENV["SPEC_FOCUS_NO_FAIL"]? != "1") + # :nodoc: + def run_filters + root_context.run_filters(@pattern, @line, @locations, @split_filter, @focus, @tags, @anti_tags) + end end - # :nodoc: - def self.maybe_randomize - if randomizer = @@randomizer - root_context.randomize(randomizer) - end + @[Deprecated("This is an internal API.")] + def self.finish_run + @@cli.finish_run end - # :nodoc: - def self.run_filters - root_context.run_filters(@@pattern, @@line, @@locations, @@split_filter, @@focus, @@tags, @@anti_tags) + @[Deprecated("This is an internal API.")] + def self.add_split_filter(filter) + @@cli.add_split_filter(filter) end end diff --git a/src/spec/example.cr b/src/spec/example.cr index e6ae51942a38..72bffd6c0e07 100644 --- a/src/spec/example.cr +++ b/src/spec/example.cr @@ -18,10 +18,10 @@ module Spec # :nodoc: def run - Spec.root_context.check_nesting_spec(file, line) do - Spec.formatters.each(&.before_example(description)) + Spec.cli.root_context.check_nesting_spec(file, line) do + Spec.cli.formatters.each(&.before_example(description)) - if Spec.dry_run? + if Spec.cli.dry_run? @parent.report(:success, description, file, line) return end @@ -51,12 +51,12 @@ module Spec @parent.report(:success, description, file, line, Time.monotonic - start) rescue ex : Spec::AssertionFailed @parent.report(:fail, description, file, line, Time.monotonic - start, ex) - Spec.abort! if Spec.fail_fast? + Spec.cli.abort! if Spec.cli.fail_fast? rescue ex : Spec::ExamplePending @parent.report(:pending, description, file, line, Time.monotonic - start) rescue ex @parent.report(:error, description, file, line, Time.monotonic - start, ex) - Spec.abort! if Spec.fail_fast? + Spec.cli.abort! if Spec.cli.fail_fast? ensure @parent.run_after_each_hooks end diff --git a/src/spec/formatter.cr b/src/spec/formatter.cr index 51b355ec075f..cfd88f2b5a6a 100644 --- a/src/spec/formatter.cr +++ b/src/spec/formatter.cr @@ -55,7 +55,7 @@ module Spec end def print_results(elapsed_time : Time::Span, aborted : Bool) - Spec.root_context.print_results(elapsed_time, aborted) + Spec.cli.root_context.print_results(elapsed_time, aborted) end end @@ -111,22 +111,34 @@ module Spec end def print_results(elapsed_time : Time::Span, aborted : Bool) - Spec.root_context.print_results(elapsed_time, aborted) + Spec.cli.root_context.print_results(elapsed_time, aborted) end end - @@formatters = [Spec::DotFormatter.new] of Spec::Formatter - # :nodoc: - def self.formatters - @@formatters + class CLI + @formatters = [Spec::DotFormatter.new] of Spec::Formatter + + def formatters + @formatters + end + + def override_default_formatter(formatter) + @formatters[0] = formatter + end + + def add_formatter(formatter) + @formatters << formatter + end end + @[Deprecated("This is an internal API.")] def self.override_default_formatter(formatter) - @@formatters[0] = formatter + @@cli.override_default_formatter(formatter) end + @[Deprecated("This is an internal API.")] def self.add_formatter(formatter) - @@formatters << formatter + @@cli.add_formatter(formatter) end end diff --git a/src/spec/methods.cr b/src/spec/methods.cr index f98326be0ed3..54b8de34b9bb 100644 --- a/src/spec/methods.cr +++ b/src/spec/methods.cr @@ -17,7 +17,7 @@ module Spec::Methods # # If `focus` is `true`, only this `describe`, and others marked with `focus: true`, will run. def describe(description = nil, file = __FILE__, line = __LINE__, end_line = __END_LINE__, focus : Bool = false, tags : String | Enumerable(String) | Nil = nil, &block) - Spec.root_context.describe(description.to_s, file, line, end_line, focus, tags, &block) + Spec.cli.root_context.describe(description.to_s, file, line, end_line, focus, tags, &block) end # Defines an example group that establishes a specific context, @@ -46,7 +46,7 @@ module Spec::Methods # # If `focus` is `true`, only this test, and others marked with `focus: true`, will run. def it(description = "assert", file = __FILE__, line = __LINE__, end_line = __END_LINE__, focus : Bool = false, tags : String | Enumerable(String) | Nil = nil, &block) - Spec.root_context.it(description.to_s, file, line, end_line, focus, tags, &block) + Spec.cli.root_context.it(description.to_s, file, line, end_line, focus, tags, &block) end # Defines a pending test case. @@ -72,7 +72,7 @@ module Spec::Methods # # If `focus` is `true`, only this test, and others marked with `focus: true`, will run. def pending(description = "assert", file = __FILE__, line = __LINE__, end_line = __END_LINE__, focus : Bool = false, tags : String | Enumerable(String) | Nil = nil) - Spec.root_context.pending(description.to_s, file, line, end_line, focus, tags) + Spec.cli.root_context.pending(description.to_s, file, line, end_line, focus, tags) end # Fails an example. @@ -124,10 +124,10 @@ module Spec::Methods # end # ``` def before_each(&block) - if Spec.current_context.is_a?(RootContext) + if Spec.cli.current_context.is_a?(RootContext) raise "Can't call `before_each` outside of a describe/context" end - Spec.current_context.before_each(&block) + Spec.cli.current_context.before_each(&block) end # Executes the given block after each spec in the current context runs. @@ -154,10 +154,10 @@ module Spec::Methods # end # ``` def after_each(&block) - if Spec.current_context.is_a?(RootContext) + if Spec.cli.current_context.is_a?(RootContext) raise "Can't call `after_each` outside of a describe/context" end - Spec.current_context.after_each(&block) + Spec.cli.current_context.after_each(&block) end # Executes the given block before the first spec in the current context runs. @@ -184,10 +184,10 @@ module Spec::Methods # end # ``` def before_all(&block) - if Spec.current_context.is_a?(RootContext) + if Spec.cli.current_context.is_a?(RootContext) raise "Can't call `before_all` outside of a describe/context" end - Spec.current_context.before_all(&block) + Spec.cli.current_context.before_all(&block) end # Executes the given block after the last spec in the current context runs. @@ -214,10 +214,10 @@ module Spec::Methods # end # ``` def after_all(&block) - if Spec.current_context.is_a?(RootContext) + if Spec.cli.current_context.is_a?(RootContext) raise "Can't call `after_all` outside of a describe/context" end - Spec.current_context.after_all(&block) + Spec.cli.current_context.after_all(&block) end # Executes the given block when each spec in the current context runs. @@ -252,10 +252,10 @@ module Spec::Methods # end # ``` def around_each(&block : Example::Procsy ->) - if Spec.current_context.is_a?(RootContext) + if Spec.cli.current_context.is_a?(RootContext) raise "Can't call `around_each` outside of a describe/context" end - Spec.current_context.around_each(&block) + Spec.cli.current_context.around_each(&block) end # Executes the given block when the current context runs. @@ -297,10 +297,10 @@ module Spec::Methods # end # ``` def around_all(&block : ExampleGroup::Procsy ->) - if Spec.current_context.is_a?(RootContext) + if Spec.cli.current_context.is_a?(RootContext) raise "Can't call `around_all` outside of a describe/context" end - Spec.current_context.around_all(&block) + Spec.cli.current_context.around_all(&block) end end From 11b107ba1ae5a0978b28e1381e62e88870a52f2f Mon Sep 17 00:00:00 2001 From: femto <femtowin@gmail.com> Date: Fri, 12 Jan 2024 20:19:58 +0800 Subject: [PATCH 051/105] Add support for `Etc/UTC` time zone identifier without tzdb (#14185) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Johannes Müller <straightshoota@gmail.com> Co-authored-by: George Dietrich <george@dietrich.app> --- spec/std/time/location_spec.cr | 4 +--- src/time/location.cr | 12 ++++++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/spec/std/time/location_spec.cr b/spec/std/time/location_spec.cr index bcf7595cffd8..78e27a230fde 100644 --- a/spec/std/time/location_spec.cr +++ b/spec/std/time/location_spec.cr @@ -67,9 +67,7 @@ class Time::Location with_zoneinfo do Location.load("UTC").should eq Location::UTC Location.load("").should eq Location::UTC - - # Etc/UTC could be pointing to anything - Location.load("Etc/UTC").should_not eq Location::UTC + Location.load("Etc/UTC").should eq Location::UTC end end diff --git a/src/time/location.cr b/src/time/location.cr index d84c1ab14218..7e0e8f160cb9 100644 --- a/src/time/location.cr +++ b/src/time/location.cr @@ -236,7 +236,7 @@ class Time::Location # # *name* is understood to be a location name in the IANA Time # Zone database, such as `"America/New_York"`. As special cases, - # `"UTC"` and empty string (`""`) return `Location::UTC`, and + # `"UTC"`, `"Etc/UTC"` and empty string (`""`) return `Location::UTC`, and # `"Local"` returns `Location.local`. # # The implementation uses a list of system-specific paths to look for a time @@ -277,7 +277,11 @@ class Time::Location # `Location`, unless the time zone database has been updated in between. def self.load(name : String) : Location case name - when "", "UTC" + when "", "UTC", "Etc/UTC" + # `UTC` is a special identifier, empty string represents a fallback mechanism. + # `Etc/UTC` is technically a tzdb identifier which could potentially point to anything. + # But we map it to `Location::UTC` directly for convenience which allows it to work + # without a copy of the database. UTC when "Local" local @@ -339,7 +343,7 @@ class Time::Location # The environment variable `ENV["TZ"]` is consulted for finding the time zone # to use. # - # * `"UTC"` and empty string (`""`) return `Location::UTC` + # * `"UTC"`, `"Etc/UTC"` and empty string (`""`) return `Location::UTC` # * Any other value (such as `"Europe/Berlin"`) is tried to be resolved using # `Location.load`. # * If `ENV["TZ"]` is not set, the system's local time zone data will be used @@ -348,7 +352,7 @@ class Time::Location # `Location::UTC` is returned. def self.load_local : Location case tz = ENV["TZ"]? - when "", "UTC" + when "", "UTC", "Etc/UTC" return UTC when Nil if localtime = Crystal::System::Time.load_localtime From 7ed7a74255c736ecf2045a54de0fd34dfa028dfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Fri, 12 Jan 2024 15:02:54 +0100 Subject: [PATCH 052/105] Update previous Crystal release 1.11.1 (#14224) --- .circleci/config.yml | 2 +- .github/workflows/interpreter.yml | 6 +++--- .github/workflows/linux.yml | 2 +- .github/workflows/llvm.yml | 2 +- .github/workflows/openssl.yml | 6 +++--- .github/workflows/regex-engine.yml | 4 ++-- .github/workflows/wasm32.yml | 2 +- .github/workflows/win_build_portable.yml | 2 +- bin/ci | 6 +++--- shell.nix | 12 ++++++------ 10 files changed, 22 insertions(+), 22 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9804bf22894c..548716adb511 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,7 +12,7 @@ parameters: previous_crystal_base_url: description: "Prefix for URLs to Crystal bootstrap compiler" type: string - default: "https://github.com/crystal-lang/crystal/releases/download/1.11.0/crystal-1.11.0-1" + default: "https://github.com/crystal-lang/crystal/releases/download/1.11.1/crystal-1.11.1-1" defaults: environment: &env diff --git a/.github/workflows/interpreter.yml b/.github/workflows/interpreter.yml index 64ef777fa9d3..96403e595e17 100644 --- a/.github/workflows/interpreter.yml +++ b/.github/workflows/interpreter.yml @@ -13,7 +13,7 @@ jobs: test-interpreter_spec: runs-on: ubuntu-22.04 container: - image: crystallang/crystal:1.11.0-build + image: crystallang/crystal:1.11.1-build name: "Test Interpreter" steps: - uses: actions/checkout@v4 @@ -24,7 +24,7 @@ jobs: build-interpreter: runs-on: ubuntu-22.04 container: - image: crystallang/crystal:1.11.0-build + image: crystallang/crystal:1.11.1-build name: Build interpreter steps: - uses: actions/checkout@v4 @@ -43,7 +43,7 @@ jobs: needs: build-interpreter runs-on: ubuntu-22.04 container: - image: crystallang/crystal:1.11.0-build + image: crystallang/crystal:1.11.1-build strategy: matrix: part: [0, 1, 2, 3] diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index c501d1b0061c..f4b284f9ce74 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - crystal_bootstrap_version: [1.7.3, 1.8.2, 1.9.2, 1.10.1, 1.11.0] + crystal_bootstrap_version: [1.7.3, 1.8.2, 1.9.2, 1.10.1, 1.11.1] flags: [""] include: # libffi is only available starting from the 1.2.2 build images diff --git a/.github/workflows/llvm.yml b/.github/workflows/llvm.yml index e8e891cab665..15fa6df8712c 100644 --- a/.github/workflows/llvm.yml +++ b/.github/workflows/llvm.yml @@ -56,7 +56,7 @@ jobs: - name: Install Crystal uses: crystal-lang/install-crystal@v1 with: - crystal: "1.11.0" + crystal: "1.11.1" - name: Build libllvm_ext run: make -B deps diff --git a/.github/workflows/openssl.yml b/.github/workflows/openssl.yml index 16dfe3b42e32..30b148448416 100644 --- a/.github/workflows/openssl.yml +++ b/.github/workflows/openssl.yml @@ -10,7 +10,7 @@ jobs: openssl3: runs-on: ubuntu-latest name: "OpenSSL 3.0" - container: crystallang/crystal:1.11.0-alpine + container: crystallang/crystal:1.11.1-alpine steps: - name: Download Crystal source uses: actions/checkout@v4 @@ -27,7 +27,7 @@ jobs: openssl111: runs-on: ubuntu-latest name: "OpenSSL 1.1.1" - container: crystallang/crystal:1.11.0-alpine + container: crystallang/crystal:1.11.1-alpine steps: - name: Download Crystal source uses: actions/checkout@v4 @@ -42,7 +42,7 @@ jobs: libressl34: runs-on: ubuntu-latest name: "LibreSSL 3.4" - container: crystallang/crystal:1.11.0-alpine + container: crystallang/crystal:1.11.1-alpine steps: - name: Download Crystal source uses: actions/checkout@v4 diff --git a/.github/workflows/regex-engine.yml b/.github/workflows/regex-engine.yml index ad6de969c5f5..523a645085bf 100644 --- a/.github/workflows/regex-engine.yml +++ b/.github/workflows/regex-engine.yml @@ -10,7 +10,7 @@ jobs: pcre: runs-on: ubuntu-latest name: "PCRE" - container: crystallang/crystal:1.11.0-alpine + container: crystallang/crystal:1.11.1-alpine steps: - name: Download Crystal source uses: actions/checkout@v4 @@ -25,7 +25,7 @@ jobs: pcre2: runs-on: ubuntu-latest name: "PCRE2" - container: crystallang/crystal:1.11.0-alpine + container: crystallang/crystal:1.11.1-alpine steps: - name: Download Crystal source uses: actions/checkout@v4 diff --git a/.github/workflows/wasm32.yml b/.github/workflows/wasm32.yml index eec64cc0bb39..ca3431808c01 100644 --- a/.github/workflows/wasm32.yml +++ b/.github/workflows/wasm32.yml @@ -12,7 +12,7 @@ env: jobs: wasm32-test: runs-on: ubuntu-latest - container: crystallang/crystal:1.11.0-build + container: crystallang/crystal:1.11.1-build steps: - name: Download Crystal source uses: actions/checkout@v4 diff --git a/.github/workflows/win_build_portable.yml b/.github/workflows/win_build_portable.yml index 6ea5568305b6..77e823384ef2 100644 --- a/.github/workflows/win_build_portable.yml +++ b/.github/workflows/win_build_portable.yml @@ -24,7 +24,7 @@ jobs: - name: Install Crystal uses: crystal-lang/install-crystal@v1 with: - crystal: "1.11.0" + crystal: "1.11.1" - name: Download Crystal source uses: actions/checkout@v4 diff --git a/bin/ci b/bin/ci index d67c2d7f6c4e..9a3776a3b7d3 100755 --- a/bin/ci +++ b/bin/ci @@ -135,8 +135,8 @@ format() { prepare_build() { on_linux verify_linux_environment - on_osx curl -L https://github.com/crystal-lang/crystal/releases/download/1.11.0/crystal-1.11.0-1-darwin-universal.tar.gz -o ~/crystal.tar.gz - on_osx 'pushd ~;gunzip -c ~/crystal.tar.gz | tar xopf -;mv crystal-1.11.0-1 crystal;popd' + on_osx curl -L https://github.com/crystal-lang/crystal/releases/download/1.11.1/crystal-1.11.1-1-darwin-universal.tar.gz -o ~/crystal.tar.gz + on_osx 'pushd ~;gunzip -c ~/crystal.tar.gz | tar xopf -;mv crystal-1.11.1-1 crystal;popd' # These commands may take a few minutes to run due to the large size of the repositories. # This restriction has been made on GitHub's request because updating shallow @@ -189,7 +189,7 @@ with_build_env() { on_linux verify_linux_environment - export DOCKER_TEST_PREFIX="${DOCKER_TEST_PREFIX:=crystallang/crystal:1.11.0}" + export DOCKER_TEST_PREFIX="${DOCKER_TEST_PREFIX:=crystallang/crystal:1.11.1}" case $ARCH in x86_64) diff --git a/shell.nix b/shell.nix index 02db8fb637f7..647315af5e70 100644 --- a/shell.nix +++ b/shell.nix @@ -52,18 +52,18 @@ let # Hashes obtained using `nix-prefetch-url --unpack <url>` latestCrystalBinary = genericBinary ({ x86_64-darwin = { - url = "https://github.com/crystal-lang/crystal/releases/download/1.11.0/crystal-1.11.0-1-darwin-universal.tar.gz"; - sha256 = "sha256:0x3adik0rpfkgw8nszf6l52vr4m7fs7rwqf1r0m17x4kgq67daiz"; + url = "https://github.com/crystal-lang/crystal/releases/download/1.11.1/crystal-1.11.1-1-darwin-universal.tar.gz"; + sha256 = "sha256:1yfb8xzhb3hnf9dn5y0mk25va1hbmk03x0hm9da6805xllr7bq8l"; }; aarch64-darwin = { - url = "https://github.com/crystal-lang/crystal/releases/download/1.11.0/crystal-1.11.0-1-darwin-universal.tar.gz"; - sha256 = "sha256:0x3adik0rpfkgw8nszf6l52vr4m7fs7rwqf1r0m17x4kgq67daiz"; + url = "https://github.com/crystal-lang/crystal/releases/download/1.11.1/crystal-1.11.1-1-darwin-universal.tar.gz"; + sha256 = "sha256:1yfb8xzhb3hnf9dn5y0mk25va1hbmk03x0hm9da6805xllr7bq8l"; }; x86_64-linux = { - url = "https://github.com/crystal-lang/crystal/releases/download/1.11.0/crystal-1.11.0-1-linux-x86_64.tar.gz"; - sha256 = "sha256:1npbn61mw6fchdlg64s7zd3k33711ifhs8n75skw8w30i4ryilhk"; + url = "https://github.com/crystal-lang/crystal/releases/download/1.11.1/crystal-1.11.1-1-linux-x86_64.tar.gz"; + sha256 = "sha256:18mqp2sy5df6bkyvndg4xwgjf6lmaipz5mcr6lg9a47is2vr1i7v"; }; }.${pkgs.stdenv.system}); From 5bd7cb538e47e2639b118c7ade2e68362d85a434 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Sat, 13 Jan 2024 00:46:00 +0800 Subject: [PATCH 053/105] `XML::Reader`: Disallow attributes containing null bytes (#14193) --- spec/std/xml/reader_spec.cr | 15 +++++++++++++++ src/xml/reader.cr | 8 ++++++++ 2 files changed, 23 insertions(+) diff --git a/spec/std/xml/reader_spec.cr b/spec/std/xml/reader_spec.cr index 54183dd8742d..d89593620970 100644 --- a/spec/std/xml/reader_spec.cr +++ b/spec/std/xml/reader_spec.cr @@ -359,6 +359,11 @@ module XML reader.value.should eq("2") reader.read.should be_false end + + it "raises if attribute contains null byte" do + reader = Reader.new("<root/>") + expect_raises(Exception) { reader.move_to_attribute("\0") } + end end describe "#[]" do @@ -378,6 +383,11 @@ module XML reader.read # </root> reader["id"].should eq("1") end + + it "raises if attribute contains null byte" do + reader = Reader.new("<root/>") + expect_raises(Exception) { reader["\0"] } + end end describe "#[]?" do @@ -397,6 +407,11 @@ module XML reader.read # </root> reader["id"]?.should eq("1") end + + it "raises if attribute contains null byte" do + reader = Reader.new("<root/>") + expect_raises(Exception) { reader["\0"]? } + end end describe "#move_to_element" do diff --git a/src/xml/reader.cr b/src/xml/reader.cr index 9d1de3ed4c9e..decdd8468185 100644 --- a/src/xml/reader.cr +++ b/src/xml/reader.cr @@ -119,6 +119,7 @@ class XML::Reader # Moves to the `XML::Reader::Type::ATTRIBUTE` with the specified name. def move_to_attribute(name : String) : Bool + check_no_null_byte(name) LibXML.xmlTextReaderMoveToAttribute(@reader, name) == 1 end @@ -131,6 +132,7 @@ class XML::Reader # Gets the attribute content for the *attribute* given by name. # Returns `nil` if attribute is not found. def []?(attribute : String) : String? + check_no_null_byte(attribute) value = LibXML.xmlTextReaderGetAttribute(@reader, attribute) String.new(value) if value end @@ -200,4 +202,10 @@ class XML::Reader Error.add_errors(@errors) end end + + private def check_no_null_byte(attribute) + if attribute.byte_index(0) + raise XML::Error.new("Invalid attribute name: #{attribute.inspect} (contains null character)", 0) + end + end end From 06f2f82b156cec23d5f1dee06e9041457281c0f6 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Sat, 13 Jan 2024 00:46:15 +0800 Subject: [PATCH 054/105] Always call `LibXML.xmlInitParser` when requiring XML libraries (#14191) --- src/xml/libxml2.cr | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/xml/libxml2.cr b/src/xml/libxml2.cr index 3dff7fb6cb40..feea8a1ba6d7 100644 --- a/src/xml/libxml2.cr +++ b/src/xml/libxml2.cr @@ -11,9 +11,10 @@ require "./save_options" lib LibXML alias Int = LibC::Int + fun xmlInitParser + # TODO: check if other platforms also support per-thread globals {% if flag?(:win32) %} - fun xmlInitParser fun __xmlIndentTreeOutput : Int* fun __xmlTreeIndentString : UInt8** {% else %} @@ -324,9 +325,7 @@ lib LibXML fun xmlValidateNameValue(value : UInt8*) : Int end -{% if flag?(:win32) %} - LibXML.xmlInitParser -{% end %} +LibXML.xmlInitParser LibXML.xmlGcMemSetup( ->GC.free, From f5844b0fc1ad9eec10cb823f732b9e6e72ee7422 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Sat, 13 Jan 2024 00:48:20 +0800 Subject: [PATCH 055/105] Reserve stack space on non-main threads for crash recovery on Windows (#14187) --- src/crystal/system/win32/thread.cr | 13 ++++++++++++- src/exception/call_stack/stackwalk.cr | 3 ++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/crystal/system/win32/thread.cr b/src/crystal/system/win32/thread.cr index 9a13bfb4dc03..5dbcbabbfad9 100644 --- a/src/crystal/system/win32/thread.cr +++ b/src/crystal/system/win32/thread.cr @@ -12,13 +12,24 @@ module Crystal::System::Thread @system_handle = GC.beginthreadex( security: Pointer(Void).null, stack_size: LibC::UInt.zero, - start_address: ->(data : Void*) { data.as(::Thread).start; LibC::UInt.zero }, + start_address: ->Thread.thread_proc(Void*), arglist: self.as(Void*), initflag: LibC::UInt.zero, thrdaddr: Pointer(LibC::UInt).null, ) end + def self.thread_proc(data : Void*) : LibC::UInt + # ensure that even in the case of stack overflow there is enough reserved + # stack space for recovery (for the main thread this is done in + # `Exception::CallStack.setup_crash_handler`) + stack_size = Crystal::System::Fiber::RESERVED_STACK_SIZE + LibC.SetThreadStackGuarantee(pointerof(stack_size)) + + data.as(::Thread).start + LibC::UInt.zero + end + def self.current_handle : Handle # `GetCurrentThread` returns a _constant_ and is only meaningful as an # argument to Win32 APIs; to uniquely identify it we must duplicate the handle diff --git a/src/exception/call_stack/stackwalk.cr b/src/exception/call_stack/stackwalk.cr index 4879ed8bb95d..4d60e02305d0 100644 --- a/src/exception/call_stack/stackwalk.cr +++ b/src/exception/call_stack/stackwalk.cr @@ -51,7 +51,8 @@ struct Exception::CallStack end) # ensure that even in the case of stack overflow there is enough reserved - # stack space for recovery + # stack space for recovery (for other threads this is done in + # `Crystal::System::Thread.thread_proc`) stack_size = Crystal::System::Fiber::RESERVED_STACK_SIZE LibC.SetThreadStackGuarantee(pointerof(stack_size)) end From 3bf68ddfcc8cf253ec84a7aa27dd103180a51618 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Sat, 13 Jan 2024 06:17:35 +0800 Subject: [PATCH 056/105] Remove extra newline in top-level `FunDef`'s string representation (#14212) --- spec/compiler/parser/to_s_spec.cr | 3 ++- src/compiler/crystal/syntax/to_s.cr | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/compiler/parser/to_s_spec.cr b/spec/compiler/parser/to_s_spec.cr index 752bece45374..75c0bac3ebee 100644 --- a/spec/compiler/parser/to_s_spec.cr +++ b/spec/compiler/parser/to_s_spec.cr @@ -143,7 +143,8 @@ describe "ASTNode#to_s" do expect_to_s %(@[Foo(1, 2, a: 1, b: 2)]) expect_to_s %(lib Foo\nend) expect_to_s %(lib LibC\n fun getchar(Int, Float)\nend) - expect_to_s %(fun foo(a : Void, b : Void, ...) : Void\n\nend) + expect_to_s %(fun foo(a : Void, b : Void, ...) : Void\nend) + expect_to_s %(fun foo\nend) expect_to_s %(lib Foo\n struct Foo\n a : Void\n b : Void\n end\nend) expect_to_s %(lib Foo\n union Foo\n a : Int\n b : Int32\n end\nend) expect_to_s %(lib Foo\n FOO = 0\nend) diff --git a/src/compiler/crystal/syntax/to_s.cr b/src/compiler/crystal/syntax/to_s.cr index 8ea364d3f991..bf8eff6aef2d 100644 --- a/src/compiler/crystal/syntax/to_s.cr +++ b/src/compiler/crystal/syntax/to_s.cr @@ -1170,7 +1170,6 @@ module Crystal if body = node.body newline accept_with_indent body - newline append_indent @str << "end" end From e814029e3f27d2a7f6fe3a9d8d0222902fec6756 Mon Sep 17 00:00:00 2001 From: femto <femtowin@gmail.com> Date: Sat, 13 Jan 2024 06:18:00 +0800 Subject: [PATCH 057/105] Change short reference for top-level macros to `::foo` (#14203) --- spec/compiler/macro/macro_methods_spec.cr | 2 +- src/compiler/crystal/macros/methods.cr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/compiler/macro/macro_methods_spec.cr b/spec/compiler/macro/macro_methods_spec.cr index 9d6304e81f01..6e3af42e4d3f 100644 --- a/spec/compiler/macro/macro_methods_spec.cr +++ b/spec/compiler/macro/macro_methods_spec.cr @@ -3565,7 +3565,7 @@ module Crystal # there are no macro methods with required named parameters it "uses correct name for top-level macro methods" do - assert_macro_error %({{flag?}}), "wrong number of arguments for top-level macro 'flag?' (given 0, expected 1)" + assert_macro_error %({{flag?}}), "wrong number of arguments for macro '::flag?' (given 0, expected 1)" end end diff --git a/src/compiler/crystal/macros/methods.cr b/src/compiler/crystal/macros/methods.cr index 24d3d8bbd14d..abef63c402d3 100644 --- a/src/compiler/crystal/macros/methods.cr +++ b/src/compiler/crystal/macros/methods.cr @@ -300,7 +300,7 @@ module Crystal def interpret_run(node) if node.args.size == 0 - node.wrong_number_of_arguments "top-level macro 'run'", 0, "1+" + node.wrong_number_of_arguments "macro '::run'", 0, "1+" end node.args.first.accept self @@ -2841,7 +2841,7 @@ end private def full_macro_name(node, method, top_level) if top_level - "top-level macro '#{method}'" + "macro '::#{method}'" else "macro '#{node.class_desc}##{method}'" end From db8ecefc6d77df61b35a69c587c3dc1324f0222d Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Sat, 13 Jan 2024 06:18:13 +0800 Subject: [PATCH 058/105] Formatter: Add more whitespace around `ProcLiteral`s (#14209) --- spec/compiler/formatter/formatter_spec.cr | 8 ++++++++ src/compiler/crystal/tools/formatter.cr | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/spec/compiler/formatter/formatter_spec.cr b/spec/compiler/formatter/formatter_spec.cr index 4567638f0fd8..ce2c7e72364c 100644 --- a/spec/compiler/formatter/formatter_spec.cr +++ b/spec/compiler/formatter/formatter_spec.cr @@ -1629,6 +1629,14 @@ describe Crystal::Formatter do assert_format "->( x : Int32 , y ) { x }", "->(x : Int32, y) { x }" assert_format "->{}" + # #13232 + assert_format "->{}", "-> { }", flags: %w[proc_literal_whitespace] + assert_format "->(){}", "-> { }", flags: %w[proc_literal_whitespace] + assert_format "->{1}", "-> { 1 }", flags: %w[proc_literal_whitespace] + assert_format "->(x : Int32) {}", "->(x : Int32) { }", flags: %w[proc_literal_whitespace] + assert_format "-> : Int32 {}", "-> : Int32 { }", flags: %w[proc_literal_whitespace] + assert_format "->do\nend", "-> do\nend", flags: %w[proc_literal_whitespace] + assert_format "-> : Int32 {}" assert_format "-> : Int32 | String { 1 }" assert_format "-> : Array(Int32) {}" diff --git a/src/compiler/crystal/tools/formatter.cr b/src/compiler/crystal/tools/formatter.cr index fc3be7a4cf66..a18634fe8232 100644 --- a/src/compiler/crystal/tools/formatter.cr +++ b/src/compiler/crystal/tools/formatter.cr @@ -4256,7 +4256,7 @@ module Crystal skip_space_or_newline end - write " " unless a_def.args.empty? && !return_type + write " " if a_def.args.present? || return_type || flag?("proc_literal_whitespace") is_do = false if @token.keyword?(:do) @@ -4264,6 +4264,7 @@ module Crystal is_do = true else write_token :OP_LCURLY + write " " if a_def.body.is_a?(Nop) && flag?("proc_literal_whitespace") end skip_space From dba80384366cc0c2620682dfc4e2982430ee990a Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Sat, 13 Jan 2024 19:38:41 +0800 Subject: [PATCH 059/105] Fix: Always use `%p` for pointers in `Crystal::System.print_error` (#14221) --- src/exception/call_stack/libunwind.cr | 2 +- src/exception/call_stack/stackwalk.cr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/exception/call_stack/libunwind.cr b/src/exception/call_stack/libunwind.cr index 81943d99f376..9f17512491fe 100644 --- a/src/exception/call_stack/libunwind.cr +++ b/src/exception/call_stack/libunwind.cr @@ -102,7 +102,7 @@ struct Exception::CallStack end private def self.print_frame(repeated_frame) - Crystal::System.print_error "[%p] ", repeated_frame.ip.address + Crystal::System.print_error "[%p] ", repeated_frame.ip print_frame_location(repeated_frame) Crystal::System.print_error " (%d times)", repeated_frame.count + 1 unless repeated_frame.count == 0 Crystal::System.print_error "\n" diff --git a/src/exception/call_stack/stackwalk.cr b/src/exception/call_stack/stackwalk.cr index 4d60e02305d0..47b78e0ee0df 100644 --- a/src/exception/call_stack/stackwalk.cr +++ b/src/exception/call_stack/stackwalk.cr @@ -151,7 +151,7 @@ struct Exception::CallStack end private def self.print_frame(repeated_frame) - Crystal::System.print_error "[%p] ", repeated_frame.ip.address + Crystal::System.print_error "[%p] ", repeated_frame.ip print_frame_location(repeated_frame) Crystal::System.print_error " (%d times)", repeated_frame.count + 1 unless repeated_frame.count == 0 Crystal::System.print_error "\n" From c35b5e8b6fd0ee69f1c8ce8990bb2ea10e267f2f Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Sat, 13 Jan 2024 19:38:52 +0800 Subject: [PATCH 060/105] Always preserve the environment for specs that modify `ENV` (#14211) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Johannes Müller <straightshoota@gmail.com> --- spec/compiler/macro/macro_methods_spec.cr | 12 ++-- spec/std/dir_spec.cr | 20 +------ spec/std/env_spec.cr | 46 ++++++--------- spec/std/process_spec.cr | 71 +++++++++++------------ 4 files changed, 59 insertions(+), 90 deletions(-) diff --git a/spec/compiler/macro/macro_methods_spec.cr b/spec/compiler/macro/macro_methods_spec.cr index 6e3af42e4d3f..13b063355c33 100644 --- a/spec/compiler/macro/macro_methods_spec.cr +++ b/spec/compiler/macro/macro_methods_spec.cr @@ -1,4 +1,5 @@ require "../../spec_helper" +require "../../support/env" private def declare_class_var(container : ClassVarContainer, name, var_type : Type, annotations = nil) var = MetaTypeVar.new(name) @@ -3281,14 +3282,15 @@ module Crystal describe "env" do it "has key" do - ENV["FOO"] = "foo" - assert_macro %({{env("FOO")}}), %("foo") - ENV.delete "FOO" + with_env("FOO": "foo") do + assert_macro %({{env("FOO")}}), %("foo") + end end it "doesn't have key" do - ENV.delete "FOO" - assert_macro %({{env("FOO")}}), %(nil) + with_env("FOO": nil) do + assert_macro %({{env("FOO")}}), %(nil) + end end end diff --git a/spec/std/dir_spec.cr b/spec/std/dir_spec.cr index f0721ef66abb..f0c01d613570 100644 --- a/spec/std/dir_spec.cr +++ b/spec/std/dir_spec.cr @@ -3,25 +3,9 @@ require "../support/env" private def unset_tempdir(&) {% if flag?(:windows) %} - old_tempdirs = {ENV["TMP"]?, ENV["TEMP"]?, ENV["USERPROFILE"]?} - begin - ENV.delete("TMP") - ENV.delete("TEMP") - ENV.delete("USERPROFILE") - - yield - ensure - ENV["TMP"], ENV["TEMP"], ENV["USERPROFILE"] = old_tempdirs - end + with_env("TMP": nil, "TEMP": nil, "USERPROFILE": nil) { yield } {% else %} - begin - old_tempdir = ENV["TMPDIR"]? - ENV.delete("TMPDIR") - - yield - ensure - ENV["TMPDIR"] = old_tempdir - end + with_env("TMPDIR": nil) { yield } {% end %} end diff --git a/spec/std/env_spec.cr b/spec/std/env_spec.cr index 8342494b10f6..038bdc74b9b1 100644 --- a/spec/std/env_spec.cr +++ b/spec/std/env_spec.cr @@ -2,6 +2,23 @@ require "spec" require "./spec_helper" describe "ENV" do + # Preserves the existing environment for each spec. + # To avoid potential circular definitions, this has to use the system methods + # directly, rather than `ENV` or `with_env`. + around_each do |example| + old_env = {} of String => String + Crystal::System::Env.each { |key, value| old_env[key] = value } + + begin + example.run + ensure + keys = [] of String + Crystal::System::Env.each { |key| keys << key } + keys.each { |key| Crystal::System::Env.set(key, nil) } + old_env.each { |key, value| Crystal::System::Env.set(key, value) } + end + end + it "gets non existent key raises" do expect_raises KeyError, "Missing ENV key: \"NON-EXISTENT\"" do ENV["NON-EXISTENT"] @@ -16,8 +33,6 @@ describe "ENV" do (ENV["FOO"] = "1").should eq("1") ENV["FOO"].should eq("1") ENV["FOO"]?.should eq("1") - ensure - ENV.delete("FOO") end {% if flag?(:win32) %} @@ -25,15 +40,11 @@ describe "ENV" do (ENV["FOO"] = "1").should eq("1") ENV["Foo"].should eq("1") ENV["foo"]?.should eq("1") - ensure - ENV.delete("FOO") end {% else %} it "sets and gets case-sensitive" do ENV["FOO"] = "1" ENV["foo"]?.should be_nil - ensure - ENV.delete("FOO") end {% end %} @@ -47,16 +58,12 @@ describe "ENV" do it "sets to empty string" do (ENV["FOO_EMPTY"] = "").should eq "" ENV["FOO_EMPTY"]?.should eq "" - ensure - ENV.delete("FOO_EMPTY") end it "does has_key?" do ENV["FOO"] = "1" ENV.has_key?("NON_EXISTENT").should be_false ENV.has_key?("FOO").should be_true - ensure - ENV.delete("FOO") end it "deletes a key" do @@ -70,9 +77,6 @@ describe "ENV" do %w(FOO BAR).each { |k| ENV.keys.should_not contain(k) } ENV["FOO"] = ENV["BAR"] = "1" %w(FOO BAR).each { |k| ENV.keys.should contain(k) } - ensure - ENV.delete("FOO") - ENV.delete("BAR") end it "does not have an empty key" do @@ -86,9 +90,6 @@ describe "ENV" do ENV["FOO"] = "SOMEVALUE_1" ENV["BAR"] = "SOMEVALUE_2" [1, 2].each { |i| ENV.values.should contain("SOMEVALUE_#{i}") } - ensure - ENV.delete("FOO") - ENV.delete("BAR") end describe "[]=" do @@ -115,16 +116,12 @@ describe "ENV" do it "fetches with one argument" do ENV["1"] = "2" ENV.fetch("1").should eq("2") - ensure - ENV.delete("1") end it "fetches with default value" do ENV["1"] = "2" ENV.fetch("1", "3").should eq("2") ENV.fetch("2", "3").should eq("3") - ensure - ENV.delete("1") end it "fetches with block" do @@ -132,8 +129,6 @@ describe "ENV" do ENV.fetch("1") { |k| k + "block" }.should eq("2") ENV.fetch("2") { |k| k + "block" }.should eq("2block") ENV.fetch("3") { 4 }.should eq(4) - ensure - ENV.delete("1") end it "fetches and raises" do @@ -141,8 +136,6 @@ describe "ENV" do expect_raises KeyError, "Missing ENV key: \"2\"" do ENV.fetch("2") end - ensure - ENV.delete("1") end end @@ -162,16 +155,11 @@ describe "ENV" do "TEST_UNICODE_1" => "bar\u{d7ff}\u{10000}", "TEST_UNICODE_2" => "\u{1234}", }) - ensure - ENV.delete("TEST_UNICODE_1") - ENV.delete("TEST_UNICODE_2") end it "#to_h" do ENV["FOO"] = "foo" ENV.to_h["FOO"].should eq "foo" - ensure - ENV.delete("FOO") end {% if flag?(:win32) %} diff --git a/spec/std/process_spec.cr b/spec/std/process_spec.cr index 94b8ec18a915..9734ec5ea99c 100644 --- a/spec/std/process_spec.cr +++ b/spec/std/process_spec.cr @@ -3,6 +3,7 @@ require "spec" require "process" require "./spec_helper" +require "../support/env" private def exit_code_command(code) {% if flag?(:win32) %} @@ -267,68 +268,62 @@ describe Process do end it "deletes existing environment variable" do - ENV["FOO"] = "bar" - value = Process.run(*print_env_command, env: {"FOO" => nil}) do |proc| - proc.output.gets_to_end + with_env("FOO": "bar") do + value = Process.run(*print_env_command, env: {"FOO" => nil}) do |proc| + proc.output.gets_to_end + end + value.should_not match /(*ANYCRLF)^FOO=/m end - value.should_not match /(*ANYCRLF)^FOO=/m - ensure - ENV.delete("FOO") end {% if flag?(:win32) %} it "deletes existing environment variable case-insensitive" do - ENV["FOO"] = "bar" - value = Process.run(*print_env_command, env: {"foo" => nil}) do |proc| - proc.output.gets_to_end + with_env("FOO": "bar") do + value = Process.run(*print_env_command, env: {"foo" => nil}) do |proc| + proc.output.gets_to_end + end + value.should_not match /(*ANYCRLF)^FOO=/mi end - value.should_not match /(*ANYCRLF)^FOO=/mi - ensure - ENV.delete("FOO") end {% end %} it "preserves existing environment variable" do - ENV["FOO"] = "bar" - value = Process.run(*print_env_command) do |proc| - proc.output.gets_to_end + with_env("FOO": "bar") do + value = Process.run(*print_env_command) do |proc| + proc.output.gets_to_end + end + value.should match /(*ANYCRLF)^FOO=bar$/m end - value.should match /(*ANYCRLF)^FOO=bar$/m - ensure - ENV.delete("FOO") end it "preserves and sets an environment variable" do - ENV["FOO"] = "bar" - value = Process.run(*print_env_command, env: {"FOO2" => "bar2"}) do |proc| - proc.output.gets_to_end + with_env("FOO": "bar") do + value = Process.run(*print_env_command, env: {"FOO2" => "bar2"}) do |proc| + proc.output.gets_to_end + end + value.should match /(*ANYCRLF)^FOO=bar$/m + value.should match /(*ANYCRLF)^FOO2=bar2$/m end - value.should match /(*ANYCRLF)^FOO=bar$/m - value.should match /(*ANYCRLF)^FOO2=bar2$/m - ensure - ENV.delete("FOO") end it "overrides existing environment variable" do - ENV["FOO"] = "bar" - value = Process.run(*print_env_command, env: {"FOO" => "different"}) do |proc| - proc.output.gets_to_end + with_env("FOO": "bar") do + value = Process.run(*print_env_command, env: {"FOO" => "different"}) do |proc| + proc.output.gets_to_end + end + value.should match /(*ANYCRLF)^FOO=different$/m end - value.should match /(*ANYCRLF)^FOO=different$/m - ensure - ENV.delete("FOO") end {% if flag?(:win32) %} it "overrides existing environment variable case-insensitive" do - ENV["FOO"] = "bar" - value = Process.run(*print_env_command, env: {"fOo" => "different"}) do |proc| - proc.output.gets_to_end + with_env("FOO": "bar") do + value = Process.run(*print_env_command, env: {"fOo" => "different"}) do |proc| + proc.output.gets_to_end + end + value.should_not match /(*ANYCRLF)^FOO=/m + value.should match /(*ANYCRLF)^fOo=different$/m end - value.should_not match /(*ANYCRLF)^FOO=/m - value.should match /(*ANYCRLF)^fOo=different$/m - ensure - ENV.delete("FOO") end {% end %} end From e0c5301a5eb22c1e22398e146d44dbc85b3ff998 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Sat, 13 Jan 2024 19:38:59 +0800 Subject: [PATCH 061/105] Remove `T*` and `T[N]` macro interpolation behavior inside libs (#14215) --- spec/compiler/parser/to_s_spec.cr | 19 ++++++++++++++++ .../semantic/restrictions_augmenter_spec.cr | 4 ++-- src/compiler/crystal/syntax/to_s.cr | 22 ------------------- 3 files changed, 21 insertions(+), 24 deletions(-) diff --git a/spec/compiler/parser/to_s_spec.cr b/spec/compiler/parser/to_s_spec.cr index 75c0bac3ebee..63da166aba45 100644 --- a/spec/compiler/parser/to_s_spec.cr +++ b/spec/compiler/parser/to_s_spec.cr @@ -148,6 +148,25 @@ describe "ASTNode#to_s" do expect_to_s %(lib Foo\n struct Foo\n a : Void\n b : Void\n end\nend) expect_to_s %(lib Foo\n union Foo\n a : Int\n b : Int32\n end\nend) expect_to_s %(lib Foo\n FOO = 0\nend) + expect_to_s <<-CRYSTAL, <<-CRYSTAL + lib Foo + A = Pointer(Void).new(0) + struct B + x : Void* + y : Int[1] + end + fun c(Void*) : Char[2]* + end + CRYSTAL + lib Foo + A = Pointer(Void).new(0) + struct B + x : ::Pointer(Void) + y : ::StaticArray(Int, 1) + end + fun c(::Pointer(Void)) : ::Pointer(::StaticArray(Char, 2)) + end + CRYSTAL expect_to_s %(lib LibC\n fun getch = "get.char"\nend) expect_to_s %(lib Foo::Bar\nend) expect_to_s %(enum Foo\n A = 0\n B\nend) diff --git a/spec/compiler/semantic/restrictions_augmenter_spec.cr b/spec/compiler/semantic/restrictions_augmenter_spec.cr index b3798dc257c0..5095f8613943 100644 --- a/spec/compiler/semantic/restrictions_augmenter_spec.cr +++ b/spec/compiler/semantic/restrictions_augmenter_spec.cr @@ -272,7 +272,7 @@ describe "Semantic: restrictions augmenter" do it "augments typedef" do before = <<-CRYSTAL lib LibFoo - type X = Void* + type X = Int32 end class Foo @x : LibFoo::X @@ -284,7 +284,7 @@ describe "Semantic: restrictions augmenter" do after = <<-CRYSTAL lib LibFoo - type X = Void* + type X = Int32 end class Foo @x : LibFoo::X diff --git a/src/compiler/crystal/syntax/to_s.cr b/src/compiler/crystal/syntax/to_s.cr index bf8eff6aef2d..f5086e346277 100644 --- a/src/compiler/crystal/syntax/to_s.cr +++ b/src/compiler/crystal/syntax/to_s.cr @@ -28,7 +28,6 @@ module Crystal def initialize(@str = IO::Memory.new, @macro_expansion_pragmas = nil, @emit_doc = false) @indent = 0 @inside_macro = 0 - @inside_lib = false end def visit_any(node) @@ -847,25 +846,6 @@ module Crystal def visit(node : Generic) name = node.name - if @inside_lib && (name.is_a?(Path) && name.names.size == 1) - case name.names.first - when "Pointer" - node.type_vars.first.accept self - @str << '*' - return false - when "StaticArray" - if node.type_vars.size == 2 - node.type_vars[0].accept self - @str << '[' - node.type_vars[1].accept self - @str << ']' - return false - end - else - # Not a special type - end - end - node.name.accept self printed_arg = false @@ -1131,9 +1111,7 @@ module Crystal @str << "lib " node.name.accept self newline - @inside_lib = true accept_with_indent(node.body) - @inside_lib = false append_indent @str << "end" false From bb96c5398e001f41b31431eea283a1a28198a84b Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Sun, 14 Jan 2024 00:37:42 +0800 Subject: [PATCH 062/105] Support `@[Link]`'s DLL search order in the interpreter on Windows (#14146) --- spec/compiler/ffi/ffi_spec.cr | 32 +++++++--- spec/compiler/loader/msvc_spec.cr | 65 +++++++++++++++++---- src/compiler/crystal/codegen/link.cr | 4 ++ src/compiler/crystal/interpreter/context.cr | 23 +++++++- src/compiler/crystal/loader.cr | 19 +++--- src/compiler/crystal/loader/msvc.cr | 37 ++++++++---- src/compiler/crystal/loader/unix.cr | 14 ++++- 7 files changed, 151 insertions(+), 43 deletions(-) diff --git a/spec/compiler/ffi/ffi_spec.cr b/spec/compiler/ffi/ffi_spec.cr index ac16cfc425f2..ec644e45870d 100644 --- a/spec/compiler/ffi/ffi_spec.cr +++ b/spec/compiler/ffi/ffi_spec.cr @@ -19,6 +19,22 @@ private record TestStruct, d : Float64, p : Pointer(Void) +private def dll_search_paths + {% if flag?(:msvc) %} + [SPEC_CRYSTAL_LOADER_LIB_PATH] + {% else %} + nil + {% end %} +end + +{% if flag?(:unix) %} + class Crystal::Loader + def self.new(search_paths : Array(String), *, dll_search_paths : Nil) + new(search_paths) + end + end +{% end %} + describe Crystal::FFI::CallInterface do before_all do FileUtils.mkdir_p(SPEC_CRYSTAL_LOADER_LIB_PATH) @@ -33,7 +49,7 @@ describe Crystal::FFI::CallInterface do it "simple call" do call_interface = Crystal::FFI::CallInterface.new Crystal::FFI::Type.sint64, [] of Crystal::FFI::Type - loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH]) + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: dll_search_paths) loader.load_library "sum" function_pointer = loader.find_symbol("answer") return_value = 0_i64 @@ -48,7 +64,7 @@ describe Crystal::FFI::CallInterface do Crystal::FFI::Type.sint32, Crystal::FFI::Type.sint32, Crystal::FFI::Type.sint32, ] of Crystal::FFI::Type - loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH]) + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: dll_search_paths) loader.load_library "sum" function_pointer = loader.find_symbol("sum") @@ -71,7 +87,7 @@ describe Crystal::FFI::CallInterface do Crystal::FFI::Type.pointer, ] of Crystal::FFI::Type - loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH]) + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: dll_search_paths) loader.load_library "sum" function_pointer = loader.find_symbol("sum_primitive_types") @@ -109,7 +125,7 @@ describe Crystal::FFI::CallInterface do ] call_interface = Crystal::FFI::CallInterface.new Crystal::FFI::Type.struct(struct_fields), struct_fields - loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH]) + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: dll_search_paths) loader.load_library "sum" function_pointer = loader.find_symbol("make_struct") @@ -145,7 +161,7 @@ describe Crystal::FFI::CallInterface do ]), ] of Crystal::FFI::Type - loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH]) + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: dll_search_paths) loader.load_library "sum" function_pointer = loader.find_symbol("sum_struct") @@ -183,7 +199,7 @@ describe Crystal::FFI::CallInterface do ]), ] of Crystal::FFI::Type - loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH]) + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: dll_search_paths) loader.load_library "sum" function_pointer = loader.find_symbol("sum_array") @@ -208,7 +224,7 @@ describe Crystal::FFI::CallInterface do it "basic" do call_interface = Crystal::FFI::CallInterface.variadic Crystal::FFI::Type.sint64, [Crystal::FFI::Type.sint32, Crystal::FFI::Type.sint32, Crystal::FFI::Type.sint32, Crystal::FFI::Type.sint32] of Crystal::FFI::Type, 1 - loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH]) + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: dll_search_paths) loader.load_library "sum" function_pointer = loader.find_symbol("sum_variadic") @@ -224,7 +240,7 @@ describe Crystal::FFI::CallInterface do it "zero varargs" do call_interface = Crystal::FFI::CallInterface.variadic Crystal::FFI::Type.sint64, [Crystal::FFI::Type.sint32] of Crystal::FFI::Type, 1 - loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH]) + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: dll_search_paths) loader.load_library "sum" function_pointer = loader.find_symbol("sum_variadic") diff --git a/spec/compiler/loader/msvc_spec.cr b/spec/compiler/loader/msvc_spec.cr index 5893d29aee02..e62ba0bd620c 100644 --- a/spec/compiler/loader/msvc_spec.cr +++ b/spec/compiler/loader/msvc_spec.cr @@ -45,7 +45,7 @@ describe Crystal::Loader do describe "#load_file?" do it "finds function symbol" do - loader = Crystal::Loader.new([] of String) + loader = Crystal::Loader.new([] of String, dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) loader.load_file?(File.join(SPEC_CRYSTAL_LOADER_LIB_PATH, Crystal::Loader.library_filename("foo"))).should be_true loader.find_symbol?("foo").should_not be_nil ensure @@ -55,7 +55,7 @@ describe Crystal::Loader do describe "#load_library?" do it "library name" do - loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH] of String) + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) loader.load_library?("foo").should be_true loader.find_symbol?("foo").should_not be_nil ensure @@ -63,7 +63,7 @@ describe Crystal::Loader do end it "full path" do - loader = Crystal::Loader.new([] of String) + loader = Crystal::Loader.new([] of String, dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) loader.load_library?(File.join(SPEC_CRYSTAL_LOADER_LIB_PATH, Crystal::Loader.library_filename("foo"))).should be_true loader.find_symbol?("foo").should_not be_nil ensure @@ -72,7 +72,7 @@ describe Crystal::Loader do it "does not implicitly find dependencies" do build_c_dynlib(compiler_datapath("loader", "bar.c")) - loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH] of String) + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) loader.load_library?("bar").should be_true loader.find_symbol?("bar").should_not be_nil loader.find_symbol?("foo").should be_nil @@ -83,23 +83,23 @@ describe Crystal::Loader do it "lookup in order" do build_c_dynlib(compiler_datapath("loader", "foo2.c")) - help_loader1 = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH] of String) + help_loader1 = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) help_loader1.load_library?("foo").should be_true foo_address = help_loader1.find_symbol?("foo").should_not be_nil - help_loader2 = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH] of String) + help_loader2 = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) help_loader2.load_library?("foo2").should be_true foo2_address = help_loader2.find_symbol?("foo").should_not be_nil foo_address.should_not eq foo2_address - loader1 = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH] of String) + loader1 = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) loader1.load_library("foo") loader1.load_library("foo2") loader1.find_symbol?("foo").should eq foo_address - loader2 = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH] of String) + loader2 = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) loader2.load_library("foo2") loader2.load_library("foo") @@ -114,18 +114,59 @@ describe Crystal::Loader do end it "does not find global symbols" do - loader = Crystal::Loader.new([] of String) + loader = Crystal::Loader.new([] of String, dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) loader.find_symbol?("__crystal_main").should be_nil end it "validate that lib handles are properly closed" do - loader = Crystal::Loader.new([] of String) + loader = Crystal::Loader.new([] of String, dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) expect_raises(Crystal::Loader::LoadError, "undefined reference to `foo'") do loader.find_symbol("foo") end end end + describe "dll_search_paths" do + it "supports an arbitrary path different from lib search path" do + with_tempfile("loader-dll_search_paths") do |path| + FileUtils.mkdir_p(SPEC_CRYSTAL_LOADER_LIB_PATH) + FileUtils.mkdir_p(path) + + build_c_dynlib(compiler_datapath("loader", "foo.c")) + File.rename(File.join(SPEC_CRYSTAL_LOADER_LIB_PATH, "foo.dll"), File.join(path, "foo.dll")) + + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH] of String, dll_search_paths: [path]) + loader.load_library?("foo").should be_true + ensure + loader.try &.close_all + + FileUtils.rm_rf(path) + FileUtils.rm_rf(SPEC_CRYSTAL_LOADER_LIB_PATH) + end + end + + it "doesn't load DLLs outside dll_search_path or Windows' default search paths" do + with_tempfile("loader-dll_search_paths") do |path| + FileUtils.mkdir_p(SPEC_CRYSTAL_LOADER_LIB_PATH) + FileUtils.mkdir_p(path) + + build_c_dynlib(compiler_datapath("loader", "foo.c")) + File.rename(File.join(SPEC_CRYSTAL_LOADER_LIB_PATH, "foo.dll"), File.join(path, "foo.dll")) + + loader1 = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH] of String, dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) + loader1.load_library?("foo").should be_false + loader2 = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH] of String) + loader2.load_library?("foo").should be_false + ensure + loader2.try &.close_all + loader1.try &.close_all + + FileUtils.rm_rf(path) + FileUtils.rm_rf(SPEC_CRYSTAL_LOADER_LIB_PATH) + end + end + end + describe "lib suffix" do before_all do FileUtils.mkdir_p(SPEC_CRYSTAL_LOADER_LIB_PATH) @@ -137,7 +178,7 @@ describe Crystal::Loader do it "respects -dynamic" do build_c_dynlib(compiler_datapath("loader", "foo.c"), lib_name: "foo-dynamic") - loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH] of String) + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) loader.load_library?("foo").should be_true ensure loader.close_all if loader @@ -145,7 +186,7 @@ describe Crystal::Loader do it "ignores -static" do build_c_dynlib(compiler_datapath("loader", "foo.c"), lib_name: "bar-static") - loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH] of String) + loader = Crystal::Loader.new([SPEC_CRYSTAL_LOADER_LIB_PATH], dll_search_paths: [SPEC_CRYSTAL_LOADER_LIB_PATH]) loader.load_library?("bar").should be_false ensure loader.close_all if loader diff --git a/src/compiler/crystal/codegen/link.cr b/src/compiler/crystal/codegen/link.cr index cc703ec81eef..d9910d64c7a8 100644 --- a/src/compiler/crystal/codegen/link.cr +++ b/src/compiler/crystal/codegen/link.cr @@ -232,6 +232,10 @@ module Crystal flags.join(" ") end + # Searches among CRYSTAL_LIBRARY_PATH, the compiler's directory, and PATH + # for every DLL specified in the used `@[Link]` annotations. Yields the + # absolute path and `true` if found, the base name and `false` if not found. + # The directories should match `Crystal::Repl::Context#dll_search_paths` def each_dll_path(& : String, Bool ->) executable_path = nil compiler_origin = nil diff --git a/src/compiler/crystal/interpreter/context.cr b/src/compiler/crystal/interpreter/context.cr index d597810b36de..2d5da06dcf15 100644 --- a/src/compiler/crystal/interpreter/context.cr +++ b/src/compiler/crystal/interpreter/context.cr @@ -409,7 +409,7 @@ class Crystal::Repl::Context # (MSVC doesn't seem to have this issue) args.delete("-lgc") - Crystal::Loader.parse(args).tap do |loader| + Crystal::Loader.parse(args, dll_search_paths: dll_search_paths).tap do |loader| # FIXME: Part 2: This is a workaround for initial integration of the interpreter: # We append a handle to the current executable (i.e. the compiler program) # to the loader's handle list. This gives the loader access to all the symbols in the compiler program, @@ -427,6 +427,27 @@ class Crystal::Repl::Context end } + # Extra DLL search paths to mimic compiled code's DLL-copying behavior + # regarding `@[Link]` annotations. These directories should match the ones + # used in `Crystal::Program#each_dll_path` + private def dll_search_paths + {% if flag?(:msvc) %} + paths = CrystalLibraryPath.paths + + if executable_path = Process.executable_path + paths << File.dirname(executable_path) + end + + ENV["PATH"]?.try &.split(Process::PATH_DELIMITER, remove_empty: true) do |path| + paths << path + end + + paths + {% else %} + nil + {% end %} + end + def c_function(name : String) loader.find_symbol(name) end diff --git a/src/compiler/crystal/loader.cr b/src/compiler/crystal/loader.cr index d7d0133cc993..5a147dad590f 100644 --- a/src/compiler/crystal/loader.cr +++ b/src/compiler/crystal/loader.cr @@ -14,6 +14,7 @@ class Crystal::Loader class LoadError < Exception property args : Array(String)? property search_paths : Array(String)? + property dll_search_paths : Array(String)? def message String.build do |io| @@ -26,28 +27,26 @@ class Crystal::Loader io << "\nSearch path: " search_paths.join(io, Process::PATH_DELIMITER) end + if dll_search_paths = @dll_search_paths + io << "\nDLL search path: " + dll_search_paths.join(io, Process::PATH_DELIMITER) + end end end end - def self.new(search_paths : Array(String), libnames : Array(String), file_paths : Array(String)) : self - loader = new(search_paths) - + def load_all(libnames : Array(String), file_paths : Array(String)) file_paths.each do |path| - loader.load_file(::Path[path].expand) + load_file(::Path[path].expand) end libnames.each do |libname| - loader.load_library(libname) + load_library(libname) end - loader end getter search_paths : Array(String) getter loaded_libraries = [] of String - - def initialize(@search_paths : Array(String)) - @handles = [] of Handle - end + @handles = [] of Handle # def self.library_filename(libname : String) : String # raise NotImplementedError.new("library_filename") diff --git a/src/compiler/crystal/loader/msvc.cr b/src/compiler/crystal/loader/msvc.cr index e9fdc9af5bbd..60aca1aae333 100644 --- a/src/compiler/crystal/loader/msvc.cr +++ b/src/compiler/crystal/loader/msvc.cr @@ -5,9 +5,9 @@ require "crystal/system/win32/library_archive" # `link.exe`, using the Win32 DLL API. # # * Only dynamic libraries can be loaded. Static libraries and object files -# are unsupported. in particular, `LibC.printf` and `LibC.snprintf`are inline -# functions in `legacy-stdio_definitions.lib` since VS2015, so they are never -# found by the loader. +# are unsupported. For example, `LibC.printf` and `LibC.snprintf` are inline +# functions in `legacy_stdio_definitions.lib` since VS2015, so they are never +# found by the loader (this is why stdlib no longer uses those functions). # * Unlike the Unix counterpart, symbols in the current module do not clash with # the ones in DLLs or their corresponding import libraries. @@ -18,16 +18,28 @@ class Crystal::Loader include SystemError end + getter dll_search_paths : Array(String)? + + def initialize(@search_paths : Array(String), @dll_search_paths : Array(String)? = nil) + end + # Parses linker arguments in the style of `link.exe`. - def self.parse(args : Array(String), *, search_paths : Array(String) = default_search_paths) : self + # + # The directories in *dll_search_paths* are tried before Windows' search order + # when looking for DLLs corresponding to an import library. The compiler uses + # this to mimic `@[Link]`'s DLL-copying behavior for compiled code. + def self.parse(args : Array(String), *, search_paths : Array(String) = default_search_paths, dll_search_paths : Array(String)? = nil) : self search_paths, libnames = parse_args(args, search_paths) file_paths = [] of String begin - self.new(search_paths, libnames, file_paths) + loader = new(search_paths, dll_search_paths) + loader.load_all(libnames, file_paths) + loader rescue exc : LoadError exc.args = args exc.search_paths = search_paths + exc.dll_search_paths = dll_search_paths raise exc end end @@ -127,14 +139,19 @@ class Crystal::Loader # files, whose base names may not match the library's. Thus it is necessary # to extract this information from the library archive itself. System::LibraryArchive.imported_dlls(path).each do |dll| - # always consider the `.dll` in the same directory as the `.lib` first, - # regardless of the search order - first_path = File.join(File.dirname(path), dll) - dll = first_path if File.file?(first_path) + dll_full_path = @dll_search_paths.try &.each do |search_path| + full_path = File.join(search_path, dll) + break full_path if File.file?(full_path) + end + dll = dll_full_path || dll # TODO: `dll` is an unqualified name, e.g. `SHELL32.dll`, so the default - # DLL search order is used; consider getting rid of the cwd + # DLL search order is used if *dll_full_path* is nil; consider getting rid + # of the current working directory altogether # (https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order) + # + # Note that the compiler's directory and PATH are effectively searched + # twice when coming from the interpreter handle = open_library(dll) return false unless handle diff --git a/src/compiler/crystal/loader/unix.cr b/src/compiler/crystal/loader/unix.cr index 39fef6e0c318..46bca67341cc 100644 --- a/src/compiler/crystal/loader/unix.cr +++ b/src/compiler/crystal/loader/unix.cr @@ -35,8 +35,16 @@ class Crystal::Loader end end + def initialize(@search_paths : Array(String)) + end + # Parses linker arguments in the style of `ld`. - def self.parse(args : Array(String), *, search_paths : Array(String) = default_search_paths) : self + # + # *dll_search_paths* has no effect. (Technically speaking, `LD_LIBRARY_PATH` + # goes here and `LIBRARY_PATH` goes into *search_paths*, but there is little + # point in doing so since the same library files are used at both compile and + # run time.) + def self.parse(args : Array(String), *, search_paths : Array(String) = default_search_paths, dll_search_paths : Array(String)? = nil) : self libnames = [] of String file_paths = [] of String @@ -73,7 +81,9 @@ class Crystal::Loader search_paths = extra_search_paths + search_paths begin - self.new(search_paths, libnames, file_paths) + loader = new(search_paths) + loader.load_all(libnames, file_paths) + loader rescue exc : LoadError exc.args = args exc.search_paths = search_paths From f8b52134b39d023a29b89e5c75089a322b0c9961 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Tue, 16 Jan 2024 14:11:03 +0100 Subject: [PATCH 063/105] Add macro methods for lib-related nodes (#14218) --- spec/compiler/macro/macro_methods_spec.cr | 121 +++++++++++++ src/compiler/crystal/macros.cr | 200 +++++++++++++++++++--- src/compiler/crystal/macros/methods.cr | 91 ++++++++++ 3 files changed, 391 insertions(+), 21 deletions(-) diff --git a/spec/compiler/macro/macro_methods_spec.cr b/spec/compiler/macro/macro_methods_spec.cr index 13b063355c33..5142ad86c5bd 100644 --- a/spec/compiler/macro/macro_methods_spec.cr +++ b/spec/compiler/macro/macro_methods_spec.cr @@ -3280,6 +3280,127 @@ module Crystal end end + describe LibDef do + lib_def = LibDef.new(Path.new("Foo", "Bar", global: true), FunDef.new("foo")) + + it "executes kind" do + assert_macro %({{x.kind}}), %(lib), {x: lib_def} + end + + it "executes name" do + assert_macro %({{x.name}}), %(::Foo::Bar), {x: lib_def} + assert_macro %({{x.name(generic_args: true)}}), %(::Foo::Bar), {x: lib_def} + assert_macro %({{x.name(generic_args: false)}}), %(::Foo::Bar), {x: lib_def} + assert_macro_error %({{x.name(generic_args: 99)}}), "named argument 'generic_args' to LibDef#name must be a BoolLiteral, not NumberLiteral", {x: lib_def} + end + + it "executes body" do + assert_macro %({{x.body}}), %(fun foo), {x: lib_def} + end + end + + describe CStructOrUnionDef do + c_struct_def = CStructOrUnionDef.new("Foo", TypeDeclaration.new("x".var, "Int".path)) + c_union_def = CStructOrUnionDef.new("Bar", Include.new("Foo".path), union: true) + + it "executes kind" do + assert_macro %({{x.kind}}), %(struct), {x: c_struct_def} + assert_macro %({{x.kind}}), %(union), {x: c_union_def} + end + + it "executes name" do + assert_macro %({{x.name}}), %(Foo), {x: c_struct_def} + assert_macro %({{x.name(generic_args: true)}}), %(Foo), {x: c_struct_def} + assert_macro %({{x.name(generic_args: false)}}), %(Foo), {x: c_struct_def} + assert_macro_error %({{x.name(generic_args: 99)}}), "named argument 'generic_args' to CStructOrUnionDef#name must be a BoolLiteral, not NumberLiteral", {x: c_struct_def} + end + + it "executes body" do + assert_macro %({{x.body}}), %(x : Int), {x: c_struct_def} + assert_macro %({{x.body}}), %(include Foo), {x: c_union_def} + end + + it "executes union?" do + assert_macro %({{x.union?}}), %(false), {x: c_struct_def} + assert_macro %({{x.union?}}), %(true), {x: c_union_def} + end + end + + describe FunDef do + lib_fun = FunDef.new("foo") + top_level_fun = FunDef.new("bar", [Arg.new("x", restriction: "Int32".path), Arg.new("", restriction: "Char".path)], "Void".path, true, 1.int32, "y.z") + top_level_fun2 = FunDef.new("baz", body: Nop.new) + + it "executes name" do + assert_macro %({{x.name}}), %(foo), {x: lib_fun} + assert_macro %({{x.name}}), %(bar), {x: top_level_fun} + end + + it "executes real_name" do + assert_macro %({{x.real_name}}), %(), {x: lib_fun} + assert_macro %({{x.real_name}}), %("y.z"), {x: top_level_fun} + end + + it "executes args" do + assert_macro %({{x.args}}), %([]), {x: lib_fun} + assert_macro %({{x.args}}), %([x : Int32, : Char]), {x: top_level_fun} + end + + it "executes variadic?" do + assert_macro %({{x.variadic?}}), %(false), {x: lib_fun} + assert_macro %({{x.variadic?}}), %(true), {x: top_level_fun} + end + + it "executes return_type" do + assert_macro %({{x.return_type}}), %(), {x: lib_fun} + assert_macro %({{x.return_type}}), %(Void), {x: top_level_fun} + end + + it "executes body" do + assert_macro %({{x.body}}), %(), {x: lib_fun} + assert_macro %({{x.body}}), %(1), {x: top_level_fun} + assert_macro %({{x.body}}), %(), {x: top_level_fun2} + end + + it "executes has_body?" do + assert_macro %({{x.has_body?}}), %(false), {x: lib_fun} + assert_macro %({{x.has_body?}}), %(true), {x: top_level_fun} + assert_macro %({{x.has_body?}}), %(true), {x: top_level_fun2} + end + end + + describe TypeDef do + type_def = TypeDef.new("Foo", Path.new("Bar", "Baz", global: true)) + + it "executes name" do + assert_macro %({{x.name}}), %(Foo), {x: type_def} + end + + it "executes type" do + assert_macro %({{x.type}}), %(::Bar::Baz), {x: type_def} + end + end + + describe ExternalVar do + external_var1 = ExternalVar.new("foo", Path.new("Bar", "Baz")) + external_var2 = ExternalVar.new("X", Generic.new(Path.global("Pointer"), ["Char".path] of ASTNode), real_name: "y.z") + + it "executes name" do + assert_macro %({{x.name}}), %(foo), {x: external_var1} + assert_macro %({{x.name}}), %(X), {x: external_var2} + end + + it "executes real_name" do + assert_macro %({{x.real_name}}), %(), {x: external_var1} + assert_macro %({{x.real_name}}), %("y.z"), {x: external_var2} + end + + it "executes type" do + assert_macro %({{x.type}}), %(Bar::Baz), {x: external_var1} + assert_macro %({{x.type}}), %(::Pointer(Char)), {x: external_var2} + end + end + describe "env" do it "has key" do with_env("FOO": "foo") do diff --git a/src/compiler/crystal/macros.cr b/src/compiler/crystal/macros.cr index 90c802bad25e..c18782dac954 100644 --- a/src/compiler/crystal/macros.cr +++ b/src/compiler/crystal/macros.cr @@ -1806,6 +1806,185 @@ module Crystal::Macros end end + # A lib definition. + # + # Every lib definition `node` is equivalent to: + # + # ``` + # {% begin %} + # {{ node.kind }} {{ node.name }} + # {{ node.body }} + # end + # {% end %} + # ``` + class LibDef < ASTNode + # Returns the keyword used to define this type. + # + # For `LibDef` this is always `lib`. + def kind : MacroId + end + + # Returns the name of this type definition. + # + # *generic_args* has no effect. It exists solely to match the interface of + # other related AST nodes. + def name(*, generic_args : BoolLiteral = true) : Path + end + + # Returns the body of this type definition. + def body : ASTNode + end + end + + # A struct or union definition inside a lib. + # + # Every type definition `node` is equivalent to: + # + # ``` + # {% begin %} + # {{ node.kind }} {{ node.name }} + # {{ node.body }} + # end + # {% end %} + # ``` + class CStructOrUnionDef < ASTNode + # Returns whether this node defines a C union. + def union? : BoolLiteral + end + + # Returns the keyword used to define this type. + # + # For `CStructOrUnionDef` this is either `struct` or `union`. + def kind : MacroId + end + + # Returns the name of this type definition. + # + # *generic_args* has no effect. It exists solely to match the interface of + # other related AST nodes. + def name(*, generic_args : BoolLiteral = true) : Path + end + + # Returns the body of this type definition. + def body : ASTNode + end + end + + # A function declaration inside a lib, or a top-level C function definition. + # + # Every function `node` is equivalent to: + # + # ``` + # fun {{ node.name }} {% if real_name = node.real_name %}= {{ real_name }}{% end %}( + # {% for arg in node.args %} {{ arg }}, {% end %} + # {% if node.variadic? %} ... {% end %} + # ) {% if return_type = node.return_type %}: {{ return_type }}{% end %} + # {% if node.has_body? %} + # {{ body }} + # end + # {% end %} + # ``` + class FunDef < ASTNode + # Returns the name of the function in Crystal. + def name : MacroId + end + + # Returns the real C name of the function, if any. + def real_name : StringLiteral | Nop + end + + # Returns the parameters of the function. + # + # This does not include the variadic parameter. + def args : ArrayLiteral(Arg) + end + + # Returns whether the function is variadic. + def variadic? : BoolLiteral + end + + # Returns the return type of the function, if specified. + def return_type : ASTNode | Nop + end + + # Returns the body of the function, if any. + # + # Both top-level funs and lib funs may return a `Nop`. Instead, `#has_body?` + # can be used to distinguish between the two. + # + # ``` + # macro body_class(x) + # {{ (x.is_a?(LibDef) ? x.body : x).body.class_name }} + # end + # + # body_class(lib MyLib + # fun foo + # end) # => "Nop" + # + # body_class(fun foo + # end) # => "Nop" + # ``` + def body : ASTNode | Nop + end + + # Returns whether this function has a body. + # + # Top-level funs have a body, whereas lib funs do not. + # + # ``` + # macro has_body(x) + # {{ (x.is_a?(LibDef) ? x.body : x).has_body? }} + # end + # + # has_body(lib MyLib + # fun foo + # end) # => false + # + # has_body(fun foo + # end) # => true + # ``` + def has_body? : BoolLiteral + end + end + + # A typedef inside a lib. + # + # Every typedef `node` is equivalent to: + # + # ``` + # type {{ node.name }} = {{ node.type }} + # ``` + class TypeDef < ASTNode + # Returns the name of the typedef. + def name : Path + end + + # Returns the name of the type this typedef is equivalent to. + def type : ASTNode + end + end + + # An external variable declaration inside a lib. + # + # Every variable `node` is equivalent to: + # + # ``` + # ${{ node.name }} {% if real_name = node.real_name %}= {{ real_name }}{% end %} : {{ node.type }} + # ``` + class ExternalVar < ASTNode + # Returns the name of the variable in Crystal, without the preceding `$`. + def name : MacroId + end + + # Returns the real C name of the variable, if any. + def real_name : StringLiteral | Nop + end + + # Returns the name of the variable's type. + def type : ASTNode + end + end + # A `while` expression class While < ASTNode # Returns this while's condition. @@ -2034,27 +2213,6 @@ module Crystal::Macros end end - # class LibDef < ASTNode - # end - - # class FunDef < ASTNode - # end - - # class TypeDef < ASTNode - # end - - # abstract class CStructOrUnionDef < ASTNode - # end - - # class StructDef < CStructOrUnionDef - # end - - # class UnionDef < CStructOrUnionDef - # end - - # class ExternalVar < ASTNode - # end - # class Alias < ASTNode # end diff --git a/src/compiler/crystal/macros/methods.cr b/src/compiler/crystal/macros/methods.cr index abef63c402d3..39ec31828328 100644 --- a/src/compiler/crystal/macros/methods.cr +++ b/src/compiler/crystal/macros/methods.cr @@ -2522,6 +2522,97 @@ module Crystal end end end + + class LibDef + def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) + case method + when "kind" + interpret_check_args { MacroId.new("lib") } + when "name" + interpret_check_args(named_params: ["generic_args"]) do + # parse the argument, but ignore it otherwise + parse_generic_args_argument(self, method, named_args, default: true) + @name + end + when "body" + interpret_check_args { @body } + else + super + end + end + end + + class CStructOrUnionDef + def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) + case method + when "kind" + interpret_check_args { MacroId.new(@union ? "union" : "struct") } + when "name" + interpret_check_args(named_params: ["generic_args"]) do + # parse the argument, but ignore it otherwise + parse_generic_args_argument(self, method, named_args, default: true) + Path.new(@name) + end + when "body" + interpret_check_args { @body } + when "union?" + interpret_check_args { BoolLiteral.new(@union) } + else + super + end + end + end + + class FunDef + def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) + case method + when "name" + interpret_check_args { MacroId.new(@name) } + when "real_name" + interpret_check_args { @real_name != @name ? StringLiteral.new(@real_name) : Nop.new } + when "args" + interpret_check_args { ArrayLiteral.map(@args, &.itself) } + when "variadic?" + interpret_check_args { BoolLiteral.new(@varargs) } + when "return_type" + interpret_check_args { @return_type || Nop.new } + when "body" + interpret_check_args { @body || Nop.new } + when "has_body?" + interpret_check_args { BoolLiteral.new(!@body.nil?) } + else + super + end + end + end + + class TypeDef + def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) + case method + when "name" + interpret_check_args { Path.new(@name).at(@name_location) } + when "type" + interpret_check_args { @type_spec } + else + super + end + end + end + + class ExternalVar + def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) + case method + when "name" + interpret_check_args { MacroId.new(@name) } + when "real_name" + interpret_check_args { (real_name = @real_name) ? StringLiteral.new(real_name) : Nop.new } + when "type" + interpret_check_args { @type_spec } + else + super + end + end + end end private def get_named_annotation_args(object) From 261f46f540d398e826fdf44b31ec591fb01cf031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Tue, 16 Jan 2024 19:39:51 +0100 Subject: [PATCH 064/105] Fix missing `cause` parameter from `IO::Error#initialize` (#14242) --- spec/std/io/io_spec.cr | 10 ++++++++++ src/io/error.cr | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/spec/std/io/io_spec.cr b/spec/std/io/io_spec.cr index e2c065ecebf0..2c53df75205e 100644 --- a/spec/std/io/io_spec.cr +++ b/spec/std/io/io_spec.cr @@ -1013,4 +1013,14 @@ describe IO do typeof(STDIN.cooked!) typeof(STDIN.raw { }) typeof(STDIN.raw!) + + describe IO::Error do + describe ".new" do + it "accepts `cause` argument (#14241)" do + cause = Exception.new("cause") + error = IO::Error.new("foo", cause: cause) + error.cause.should be cause + end + end + end end diff --git a/src/io/error.cr b/src/io/error.cr index 4c6d30952f13..ec0374040699 100644 --- a/src/io/error.cr +++ b/src/io/error.cr @@ -16,10 +16,10 @@ class IO "#{message} (#{target})" end - def initialize(message : String? = nil, *, target = nil) + def initialize(message : String? = nil, cause : Exception? = nil, *, target = nil) @target = target.try(&.to_s) - super message + super message, cause end end From 045547a1715868d8b8bca272c64fc82a2677fd98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Wed, 17 Jan 2024 12:17:03 +0100 Subject: [PATCH 065/105] Drop flag `openbsd6.2` (#14233) --- src/crystal/system/unix/fiber.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crystal/system/unix/fiber.cr b/src/crystal/system/unix/fiber.cr index 17cbe5c07fdb..2a06b3d3d1a1 100644 --- a/src/crystal/system/unix/fiber.cr +++ b/src/crystal/system/unix/fiber.cr @@ -3,7 +3,7 @@ require "c/sys/mman" module Crystal::System::Fiber def self.allocate_stack(stack_size) : Void* flags = LibC::MAP_PRIVATE | LibC::MAP_ANON - {% if flag?(:openbsd) && !flag?(:"openbsd6.2") %} + {% if flag?(:openbsd) %} flags |= LibC::MAP_STACK {% end %} From 97ca775f2f03d18000972ad16d8f96fa15f29f10 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Thu, 11 Jan 2024 06:26:03 +0800 Subject: [PATCH 066/105] Always use `%p` for pointers in `Crystal::System.print_error` (#14186) --- src/crystal/system/unix/signal.cr | 2 +- src/exception/call_stack/libunwind.cr | 2 +- src/exception/call_stack/stackwalk.cr | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/crystal/system/unix/signal.cr b/src/crystal/system/unix/signal.cr index c30a2b985af2..f7c0ad31e326 100644 --- a/src/crystal/system/unix/signal.cr +++ b/src/crystal/system/unix/signal.cr @@ -149,7 +149,7 @@ module Crystal::System::Signal if is_stack_overflow Crystal::System.print_error "Stack overflow (e.g., infinite or very deep recursion)\n" else - Crystal::System.print_error "Invalid memory access (signal %d) at address 0x%lx\n", sig, addr + Crystal::System.print_error "Invalid memory access (signal %d) at address %p\n", sig, addr end Exception::CallStack.print_backtrace diff --git a/src/exception/call_stack/libunwind.cr b/src/exception/call_stack/libunwind.cr index 220db21b71f0..81943d99f376 100644 --- a/src/exception/call_stack/libunwind.cr +++ b/src/exception/call_stack/libunwind.cr @@ -102,7 +102,7 @@ struct Exception::CallStack end private def self.print_frame(repeated_frame) - Crystal::System.print_error "[0x%llx] ", repeated_frame.ip.address.to_u64 + Crystal::System.print_error "[%p] ", repeated_frame.ip.address print_frame_location(repeated_frame) Crystal::System.print_error " (%d times)", repeated_frame.count + 1 unless repeated_frame.count == 0 Crystal::System.print_error "\n" diff --git a/src/exception/call_stack/stackwalk.cr b/src/exception/call_stack/stackwalk.cr index f49c87fae623..4879ed8bb95d 100644 --- a/src/exception/call_stack/stackwalk.cr +++ b/src/exception/call_stack/stackwalk.cr @@ -37,7 +37,7 @@ struct Exception::CallStack case exception_info.value.exceptionRecord.value.exceptionCode when LibC::EXCEPTION_ACCESS_VIOLATION addr = exception_info.value.exceptionRecord.value.exceptionInformation[1] - Crystal::System.print_error "Invalid memory access (C0000005) at address 0x%llx\n", addr + Crystal::System.print_error "Invalid memory access (C0000005) at address %p\n", Pointer(Void).new(addr) print_backtrace(exception_info) LibC._exit(1) when LibC::EXCEPTION_STACK_OVERFLOW @@ -150,7 +150,7 @@ struct Exception::CallStack end private def self.print_frame(repeated_frame) - Crystal::System.print_error "[0x%llx] ", repeated_frame.ip.address.to_u64 + Crystal::System.print_error "[%p] ", repeated_frame.ip.address print_frame_location(repeated_frame) Crystal::System.print_error " (%d times)", repeated_frame.count + 1 unless repeated_frame.count == 0 Crystal::System.print_error "\n" From 4e6531aaf6cfcb8aed6c783137387337481cb3c1 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Sat, 13 Jan 2024 19:38:41 +0800 Subject: [PATCH 067/105] Fix: Always use `%p` for pointers in `Crystal::System.print_error` (#14221) --- src/exception/call_stack/libunwind.cr | 2 +- src/exception/call_stack/stackwalk.cr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/exception/call_stack/libunwind.cr b/src/exception/call_stack/libunwind.cr index 81943d99f376..9f17512491fe 100644 --- a/src/exception/call_stack/libunwind.cr +++ b/src/exception/call_stack/libunwind.cr @@ -102,7 +102,7 @@ struct Exception::CallStack end private def self.print_frame(repeated_frame) - Crystal::System.print_error "[%p] ", repeated_frame.ip.address + Crystal::System.print_error "[%p] ", repeated_frame.ip print_frame_location(repeated_frame) Crystal::System.print_error " (%d times)", repeated_frame.count + 1 unless repeated_frame.count == 0 Crystal::System.print_error "\n" diff --git a/src/exception/call_stack/stackwalk.cr b/src/exception/call_stack/stackwalk.cr index 4879ed8bb95d..a6a400b1befd 100644 --- a/src/exception/call_stack/stackwalk.cr +++ b/src/exception/call_stack/stackwalk.cr @@ -150,7 +150,7 @@ struct Exception::CallStack end private def self.print_frame(repeated_frame) - Crystal::System.print_error "[%p] ", repeated_frame.ip.address + Crystal::System.print_error "[%p] ", repeated_frame.ip print_frame_location(repeated_frame) Crystal::System.print_error " (%d times)", repeated_frame.count + 1 unless repeated_frame.count == 0 Crystal::System.print_error "\n" From fda656c7134138e013e89281e74a4f3761b53fd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Thu, 18 Jan 2024 14:36:11 +0100 Subject: [PATCH 068/105] Changelog for 1.11.2 (#14249) --- CHANGELOG.md | 16 ++++++++++++++++ src/VERSION | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 658d9f42f822..4e152e9ad2d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## [1.11.2] (2024-01-18) + +[1.11.2]: https://github.com/crystal-lang/crystal/releases/1.11.2 + +### Bugfixes + +#### stdlib + +- *(files)* Fix missing `cause` parameter from `IO::Error#initialize` ([#14242](https://github.com/crystal-lang/crystal/pull/14242), thanks @straight-shoota) +- *(runtime)* Always use `%p` for pointers in `Crystal::System.print_error` ([#14186](https://github.com/crystal-lang/crystal/pull/14186), thanks @HertzDevil) +- *(runtime)* Fixup for always use `%p` for pointers in `Crystal::System.print_error` ([#14221](https://github.com/crystal-lang/crystal/pull/14221), thanks @HertzDevil) + +### Infrastructure + +- Changelog for 1.11.2 ([#14249](https://github.com/crystal-lang/crystal/pull/14249), thanks @straight-shoota) + ## [1.11.1] (2024-01-11) [1.11.1]: https://github.com/crystal-lang/crystal/releases/1.11.1 diff --git a/src/VERSION b/src/VERSION index 720c7384c619..ca7176690dd6 100644 --- a/src/VERSION +++ b/src/VERSION @@ -1 +1 @@ -1.11.1 +1.11.2 From f01de65e852dfb1c21aef609525ff447e96ec66c Mon Sep 17 00:00:00 2001 From: Julien Portalier <julien@portalier.com> Date: Wed, 24 Jan 2024 11:18:50 +0100 Subject: [PATCH 069/105] MT: reduce interleaved backtraces in spawn unhandled exceptions (#14220) --- src/fiber.cr | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/fiber.cr b/src/fiber.cr index c96184f3cf1f..049b7e9bb0c0 100644 --- a/src/fiber.cr +++ b/src/fiber.cr @@ -140,12 +140,20 @@ class Fiber GC.unlock_read @proc.call rescue ex + io = {% if flag?(:preview_mt) %} + IO::Memory.new(4096) # PIPE_BUF + {% else %} + STDERR + {% end %} if name = @name - STDERR.print "Unhandled exception in spawn(name: #{name}): " + io << "Unhandled exception in spawn(name: " << name << "): " else - STDERR.print "Unhandled exception in spawn: " + io << "Unhandled exception in spawn: " end - ex.inspect_with_backtrace(STDERR) + ex.inspect_with_backtrace(io) + {% if flag?(:preview_mt) %} + STDERR.write(io.to_slice) + {% end %} STDERR.flush ensure # Remove the current fiber from the linked list From 724249fb54858a6eff33895b1144f00ac276ad01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Wed, 24 Jan 2024 11:19:18 +0100 Subject: [PATCH 070/105] Remove filtering of already mentioned PRs (#14229) --- scripts/github-changelog.cr | 3 --- 1 file changed, 3 deletions(-) diff --git a/scripts/github-changelog.cr b/scripts/github-changelog.cr index c660a01cd8ca..7397440c3676 100755 --- a/scripts/github-changelog.cr +++ b/scripts/github-changelog.cr @@ -262,9 +262,6 @@ array = parser.on_key! "data" do end end -changelog = File.read("CHANGELOG.md") -array.select! { |pr| pr.merged_at && !changelog.index(pr.permalink) } - sections = array.group_by(&.section) SECTION_TITLES = { From d42b67382b6a97b74ebcb96e6e30531aa1c3a26e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Sat, 27 Jan 2024 15:03:59 +0100 Subject: [PATCH 071/105] Update previous Crystal release - 1.11.2 (#14251) --- .circleci/config.yml | 2 +- .github/workflows/interpreter.yml | 6 +++--- .github/workflows/linux.yml | 2 +- .github/workflows/llvm.yml | 2 +- .github/workflows/openssl.yml | 6 +++--- .github/workflows/regex-engine.yml | 4 ++-- .github/workflows/wasm32.yml | 2 +- .github/workflows/win_build_portable.yml | 2 +- bin/ci | 6 +++--- shell.nix | 12 ++++++------ 10 files changed, 22 insertions(+), 22 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 548716adb511..2eef408ee4ad 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,7 +12,7 @@ parameters: previous_crystal_base_url: description: "Prefix for URLs to Crystal bootstrap compiler" type: string - default: "https://github.com/crystal-lang/crystal/releases/download/1.11.1/crystal-1.11.1-1" + default: "https://github.com/crystal-lang/crystal/releases/download/1.11.2/crystal-1.11.2-1" defaults: environment: &env diff --git a/.github/workflows/interpreter.yml b/.github/workflows/interpreter.yml index 96403e595e17..35cf1f916770 100644 --- a/.github/workflows/interpreter.yml +++ b/.github/workflows/interpreter.yml @@ -13,7 +13,7 @@ jobs: test-interpreter_spec: runs-on: ubuntu-22.04 container: - image: crystallang/crystal:1.11.1-build + image: crystallang/crystal:1.11.2-build name: "Test Interpreter" steps: - uses: actions/checkout@v4 @@ -24,7 +24,7 @@ jobs: build-interpreter: runs-on: ubuntu-22.04 container: - image: crystallang/crystal:1.11.1-build + image: crystallang/crystal:1.11.2-build name: Build interpreter steps: - uses: actions/checkout@v4 @@ -43,7 +43,7 @@ jobs: needs: build-interpreter runs-on: ubuntu-22.04 container: - image: crystallang/crystal:1.11.1-build + image: crystallang/crystal:1.11.2-build strategy: matrix: part: [0, 1, 2, 3] diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index f4b284f9ce74..3d85af22e5a3 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - crystal_bootstrap_version: [1.7.3, 1.8.2, 1.9.2, 1.10.1, 1.11.1] + crystal_bootstrap_version: [1.7.3, 1.8.2, 1.9.2, 1.10.1, 1.11.2] flags: [""] include: # libffi is only available starting from the 1.2.2 build images diff --git a/.github/workflows/llvm.yml b/.github/workflows/llvm.yml index 15fa6df8712c..fe8ad578163a 100644 --- a/.github/workflows/llvm.yml +++ b/.github/workflows/llvm.yml @@ -56,7 +56,7 @@ jobs: - name: Install Crystal uses: crystal-lang/install-crystal@v1 with: - crystal: "1.11.1" + crystal: "1.11.2" - name: Build libllvm_ext run: make -B deps diff --git a/.github/workflows/openssl.yml b/.github/workflows/openssl.yml index 30b148448416..65766c6325c2 100644 --- a/.github/workflows/openssl.yml +++ b/.github/workflows/openssl.yml @@ -10,7 +10,7 @@ jobs: openssl3: runs-on: ubuntu-latest name: "OpenSSL 3.0" - container: crystallang/crystal:1.11.1-alpine + container: crystallang/crystal:1.11.2-alpine steps: - name: Download Crystal source uses: actions/checkout@v4 @@ -27,7 +27,7 @@ jobs: openssl111: runs-on: ubuntu-latest name: "OpenSSL 1.1.1" - container: crystallang/crystal:1.11.1-alpine + container: crystallang/crystal:1.11.2-alpine steps: - name: Download Crystal source uses: actions/checkout@v4 @@ -42,7 +42,7 @@ jobs: libressl34: runs-on: ubuntu-latest name: "LibreSSL 3.4" - container: crystallang/crystal:1.11.1-alpine + container: crystallang/crystal:1.11.2-alpine steps: - name: Download Crystal source uses: actions/checkout@v4 diff --git a/.github/workflows/regex-engine.yml b/.github/workflows/regex-engine.yml index 523a645085bf..d7d9c2655584 100644 --- a/.github/workflows/regex-engine.yml +++ b/.github/workflows/regex-engine.yml @@ -10,7 +10,7 @@ jobs: pcre: runs-on: ubuntu-latest name: "PCRE" - container: crystallang/crystal:1.11.1-alpine + container: crystallang/crystal:1.11.2-alpine steps: - name: Download Crystal source uses: actions/checkout@v4 @@ -25,7 +25,7 @@ jobs: pcre2: runs-on: ubuntu-latest name: "PCRE2" - container: crystallang/crystal:1.11.1-alpine + container: crystallang/crystal:1.11.2-alpine steps: - name: Download Crystal source uses: actions/checkout@v4 diff --git a/.github/workflows/wasm32.yml b/.github/workflows/wasm32.yml index ca3431808c01..c8f2058ebea0 100644 --- a/.github/workflows/wasm32.yml +++ b/.github/workflows/wasm32.yml @@ -12,7 +12,7 @@ env: jobs: wasm32-test: runs-on: ubuntu-latest - container: crystallang/crystal:1.11.1-build + container: crystallang/crystal:1.11.2-build steps: - name: Download Crystal source uses: actions/checkout@v4 diff --git a/.github/workflows/win_build_portable.yml b/.github/workflows/win_build_portable.yml index 77e823384ef2..d1aa2793d4ff 100644 --- a/.github/workflows/win_build_portable.yml +++ b/.github/workflows/win_build_portable.yml @@ -24,7 +24,7 @@ jobs: - name: Install Crystal uses: crystal-lang/install-crystal@v1 with: - crystal: "1.11.1" + crystal: "1.11.2" - name: Download Crystal source uses: actions/checkout@v4 diff --git a/bin/ci b/bin/ci index 9a3776a3b7d3..9d0b73507f24 100755 --- a/bin/ci +++ b/bin/ci @@ -135,8 +135,8 @@ format() { prepare_build() { on_linux verify_linux_environment - on_osx curl -L https://github.com/crystal-lang/crystal/releases/download/1.11.1/crystal-1.11.1-1-darwin-universal.tar.gz -o ~/crystal.tar.gz - on_osx 'pushd ~;gunzip -c ~/crystal.tar.gz | tar xopf -;mv crystal-1.11.1-1 crystal;popd' + on_osx curl -L https://github.com/crystal-lang/crystal/releases/download/1.11.2/crystal-1.11.2-1-darwin-universal.tar.gz -o ~/crystal.tar.gz + on_osx 'pushd ~;gunzip -c ~/crystal.tar.gz | tar xopf -;mv crystal-1.11.2-1 crystal;popd' # These commands may take a few minutes to run due to the large size of the repositories. # This restriction has been made on GitHub's request because updating shallow @@ -189,7 +189,7 @@ with_build_env() { on_linux verify_linux_environment - export DOCKER_TEST_PREFIX="${DOCKER_TEST_PREFIX:=crystallang/crystal:1.11.1}" + export DOCKER_TEST_PREFIX="${DOCKER_TEST_PREFIX:=crystallang/crystal:1.11.2}" case $ARCH in x86_64) diff --git a/shell.nix b/shell.nix index 647315af5e70..aef4211f280a 100644 --- a/shell.nix +++ b/shell.nix @@ -52,18 +52,18 @@ let # Hashes obtained using `nix-prefetch-url --unpack <url>` latestCrystalBinary = genericBinary ({ x86_64-darwin = { - url = "https://github.com/crystal-lang/crystal/releases/download/1.11.1/crystal-1.11.1-1-darwin-universal.tar.gz"; - sha256 = "sha256:1yfb8xzhb3hnf9dn5y0mk25va1hbmk03x0hm9da6805xllr7bq8l"; + url = "https://github.com/crystal-lang/crystal/releases/download/1.11.2/crystal-1.11.2-1-darwin-universal.tar.gz"; + sha256 = "sha256:0qcdr8yl6k7il0x63z2gyqbkjp89m77nq7x1h3m80y1imfg0z1q9"; }; aarch64-darwin = { - url = "https://github.com/crystal-lang/crystal/releases/download/1.11.1/crystal-1.11.1-1-darwin-universal.tar.gz"; - sha256 = "sha256:1yfb8xzhb3hnf9dn5y0mk25va1hbmk03x0hm9da6805xllr7bq8l"; + url = "https://github.com/crystal-lang/crystal/releases/download/1.11.2/crystal-1.11.2-1-darwin-universal.tar.gz"; + sha256 = "sha256:0qcdr8yl6k7il0x63z2gyqbkjp89m77nq7x1h3m80y1imfg0z1q9"; }; x86_64-linux = { - url = "https://github.com/crystal-lang/crystal/releases/download/1.11.1/crystal-1.11.1-1-linux-x86_64.tar.gz"; - sha256 = "sha256:18mqp2sy5df6bkyvndg4xwgjf6lmaipz5mcr6lg9a47is2vr1i7v"; + url = "https://github.com/crystal-lang/crystal/releases/download/1.11.2/crystal-1.11.2-1-linux-x86_64.tar.gz"; + sha256 = "sha256:01l9cq8d3p7p3ijkrg0xpchj0l21z3sjvd5f6zw1pnms647a6hdr"; }; }.${pkgs.stdenv.system}); From ac895ff483789b34079388210f1d4fc37b220227 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 27 Jan 2024 15:04:10 +0100 Subject: [PATCH 072/105] Update GH Actions (#14246) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/llvm.yml | 2 +- .github/workflows/macos.yml | 4 ++-- .github/workflows/win.yml | 16 ++++++++-------- .github/workflows/win_build_portable.yml | 12 ++++++------ 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/llvm.yml b/.github/workflows/llvm.yml index fe8ad578163a..887ede290fe3 100644 --- a/.github/workflows/llvm.yml +++ b/.github/workflows/llvm.yml @@ -33,7 +33,7 @@ jobs: - name: Cache LLVM id: cache-llvm - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ./llvm key: llvm-${{ matrix.llvm_version }} diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index dbab5f5bc93c..765595ce2d09 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -17,12 +17,12 @@ jobs: - name: Download Crystal source uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v24 + - uses: cachix/install-nix-action@v25 with: install_url: https://releases.nixos.org/nix/nix-2.9.2/install extra_nix_config: | experimental-features = nix-command - - uses: cachix/cachix-action@v13 + - uses: cachix/cachix-action@v14 with: name: crystal-ci signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}' diff --git a/.github/workflows/win.yml b/.github/workflows/win.yml index c80dcfce8fb6..9fce9f93aa44 100644 --- a/.github/workflows/win.yml +++ b/.github/workflows/win.yml @@ -25,7 +25,7 @@ jobs: - name: Cache libraries id: cache-libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | # openssl and llvm take much longer to build so they are cached separately libs/pcre.lib @@ -68,7 +68,7 @@ jobs: - name: Cache OpenSSL id: cache-openssl - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | libs/crypto.lib @@ -97,7 +97,7 @@ jobs: - name: Cache libraries id: cache-dlls - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | # openssl and llvm take much longer to build so they are cached separately libs/pcre-dynamic.lib @@ -149,7 +149,7 @@ jobs: - name: Cache OpenSSL id: cache-openssl-dlls - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | libs/crypto-dynamic.lib @@ -172,7 +172,7 @@ jobs: - name: Cache LLVM id: cache-llvm-libs - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: llvm key: llvm-libs-${{ env.CI_LLVM_VERSION }}-msvc @@ -219,7 +219,7 @@ jobs: - name: Cache LLVM id: cache-llvm-dlls - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | libs/llvm_VERSION @@ -258,7 +258,7 @@ jobs: path: build - name: Restore LLVM - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: llvm key: llvm-libs-${{ env.CI_LLVM_VERSION }}-msvc @@ -309,7 +309,7 @@ jobs: path: etc/win-ci/portable - name: Restore LLVM - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: llvm key: llvm-libs-${{ env.CI_LLVM_VERSION }}-msvc diff --git a/.github/workflows/win_build_portable.yml b/.github/workflows/win_build_portable.yml index d1aa2793d4ff..bab89e04685e 100644 --- a/.github/workflows/win_build_portable.yml +++ b/.github/workflows/win_build_portable.yml @@ -30,7 +30,7 @@ jobs: uses: actions/checkout@v4 - name: Restore libraries - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: | libs/pcre.lib @@ -45,7 +45,7 @@ jobs: key: win-libs-${{ hashFiles('.github/workflows/win.yml', 'etc/win-ci/*.ps1') }}-msvc fail-on-cache-miss: true - name: Restore OpenSSL - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: | libs/crypto.lib @@ -54,7 +54,7 @@ jobs: key: win-openssl-libs-3.1.0-${{ hashFiles('etc/win-ci/build-openssl.ps1') }}-msvc fail-on-cache-miss: true - name: Restore DLLs - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: | libs/pcre-dynamic.lib @@ -78,7 +78,7 @@ jobs: key: win-dlls-${{ hashFiles('.github/workflows/win.yml', 'etc/win-ci/*.ps1') }}-msvc fail-on-cache-miss: true - name: Restore OpenSSL DLLs - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: | libs/crypto-dynamic.lib @@ -88,13 +88,13 @@ jobs: key: win-openssl-dlls-3.1.0-${{ hashFiles('etc/win-ci/build-openssl.ps1') }}-msvc fail-on-cache-miss: true - name: Restore LLVM - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: llvm key: llvm-libs-${{ inputs.llvm_version }}-msvc fail-on-cache-miss: true - name: Restore LLVM DLLs - uses: actions/cache/restore@v3 + uses: actions/cache/restore@v4 with: path: | libs/llvm_VERSION From 7628de67ea55801ad575623d2a9045b750d5cefa Mon Sep 17 00:00:00 2001 From: Ryan Gonzalez <git@refi64.dev> Date: Sat, 27 Jan 2024 08:48:32 -0600 Subject: [PATCH 073/105] Add `--frame-pointers` to control preservation of frame pointers (#13860) Co-authored-by: Sijawusz Pur Rahnama <sija@sija.pl> Co-authored-by: Quinton Miller <nicetas.c@gmail.com> --- man/crystal.1 | 2 ++ src/compiler/crystal/codegen/codegen.cr | 11 ++++++++--- src/compiler/crystal/codegen/fun.cr | 6 +++++- src/compiler/crystal/command.cr | 8 ++++++++ src/compiler/crystal/compiler.cr | 12 +++++++++++- src/llvm/function.cr | 7 +++++++ src/llvm/lib_llvm/core.cr | 1 + 7 files changed, 42 insertions(+), 5 deletions(-) diff --git a/man/crystal.1 b/man/crystal.1 index 3a2a3d4a1b2a..ef23beac77c3 100644 --- a/man/crystal.1 +++ b/man/crystal.1 @@ -117,6 +117,8 @@ Generate the output without any symbolic debug symbols. Define a compile-time flag. This is useful to conditionally define types, methods, or commands based on flags available at compile time. The default flags are from the target triple given with --target-triple or the hosts default, if none is given. .It Fl -emit Op asm|llvm-bc|llvm-ir|obj Comma separated list of types of output for the compiler to emit. You can use this to see the generated LLVM IR, LLVM bitcode, assembly, and object files. +.It Fl -frame-pointers Op auto|always|non-leaf +Control the preservation of frame pointers. The default value, --frame-pointers=auto, will preserve frame pointers on debug builds and try to omit them on release builds (certain platforms require them to stay enabled). --frame-pointers=always will always preserve them, and non-leaf will only force their preservation on non-leaf functions. .It Fl f Ar text|json, Fl -format Ar text|json Format of output. Defaults to text. The json format can be used to get a more parser-friendly output. .It Fl -error-trace diff --git a/src/compiler/crystal/codegen/codegen.cr b/src/compiler/crystal/codegen/codegen.cr index 651afa44ca27..a6015012eb7c 100644 --- a/src/compiler/crystal/codegen/codegen.cr +++ b/src/compiler/crystal/codegen/codegen.cr @@ -69,8 +69,10 @@ module Crystal end end - def codegen(node, single_module = false, debug = Debug::Default) - visitor = CodeGenVisitor.new self, node, single_module: single_module, debug: debug + def codegen(node, single_module = false, debug = Debug::Default, + frame_pointers = FramePointers::Auto) + visitor = CodeGenVisitor.new self, node, single_module: single_module, + debug: debug, frame_pointers: frame_pointers visitor.accept node visitor.process_finished_hooks visitor.finish @@ -190,7 +192,10 @@ module Crystal @c_malloc_fun : LLVMTypedFunction? @c_realloc_fun : LLVMTypedFunction? - def initialize(@program : Program, @node : ASTNode, @single_module : Bool = false, @debug = Debug::Default) + def initialize(@program : Program, @node : ASTNode, + @single_module : Bool = false, + @debug = Debug::Default, + @frame_pointers : FramePointers = :auto) @abi = @program.target_machine.abi @llvm_context = LLVM::Context.new # LLVM::Context.register(@llvm_context, "main") diff --git a/src/compiler/crystal/codegen/fun.cr b/src/compiler/crystal/codegen/fun.cr index 9a8e51df3175..784eba83b9b9 100644 --- a/src/compiler/crystal/codegen/fun.cr +++ b/src/compiler/crystal/codegen/fun.cr @@ -101,9 +101,13 @@ class Crystal::CodeGenVisitor context.fun.add_attribute LLVM::Attribute::UWTable, value: @program.has_flag?("aarch64") ? LLVM::UWTableKind::Sync : LLVM::UWTableKind::Async {% end %} - if @program.has_flag?("darwin") + if @frame_pointers.always? + context.fun.add_attribute "frame-pointer", value: "all" + elsif @program.has_flag?("darwin") # Disable frame pointer elimination in Darwin, as it causes issues during stack unwind context.fun.add_target_dependent_attribute "frame-pointer", "all" + elsif @frame_pointers.non_leaf? + context.fun.add_attribute "frame-pointer", value: "non-leaf" end new_entry_block diff --git a/src/compiler/crystal/command.cr b/src/compiler/crystal/command.cr index 97bf46feb663..6549c2768aea 100644 --- a/src/compiler/crystal/command.cr +++ b/src/compiler/crystal/command.cr @@ -399,6 +399,14 @@ class Crystal::Command opts.on("--no-debug", "Skip any symbolic debug info") do compiler.debug = Crystal::Debug::None end + + opts.on("--frame-pointers auto|always|non-leaf", "Control the preservation of frame pointers") do |value| + if frame_pointers = FramePointers.parse?(value) + compiler.frame_pointers = frame_pointers + else + error "Invalid value `#{value}` for frame-pointers" + end + end end opts.on("-D FLAG", "--define FLAG", "Define a compile-time flag") do |flag| diff --git a/src/compiler/crystal/compiler.cr b/src/compiler/crystal/compiler.cr index 283f44289468..899ef242f318 100644 --- a/src/compiler/crystal/compiler.cr +++ b/src/compiler/crystal/compiler.cr @@ -16,6 +16,12 @@ module Crystal Default = LineNumbers end + enum FramePointers + Auto + Always + NonLeaf + end + # Main interface to the compiler. # # A Compiler parses source code, type checks it and @@ -45,6 +51,9 @@ module Crystal # code by the `flag?(...)` macro method. property flags = [] of String + # Controls generation of frame pointers. + property frame_pointers = FramePointers::Auto + # If `true`, the executable will be generated with debug code # that can be understood by `gdb` and `lldb`. property debug = Debug::Default @@ -297,7 +306,8 @@ module Crystal private def codegen(program, node : ASTNode, sources, output_filename) llvm_modules = @progress_tracker.stage("Codegen (crystal)") do - program.codegen node, debug: debug, single_module: @single_module || @cross_compile || !@emit_targets.none? + program.codegen node, debug: debug, frame_pointers: frame_pointers, + single_module: @single_module || @cross_compile || !@emit_targets.none? end output_dir = CacheDir.instance.directory_for(sources) diff --git a/src/llvm/function.cr b/src/llvm/function.cr index a586cd6fdde5..d643e74d758b 100644 --- a/src/llvm/function.cr +++ b/src/llvm/function.cr @@ -28,6 +28,13 @@ struct LLVM::Function end end + def add_attribute(attribute : String, index = AttributeIndex::FunctionIndex, *, value : String) + context = LibLLVM.get_module_context(LibLLVM.get_global_parent(self)) + attribute_ref = LibLLVM.create_string_attribute(context, attribute, attribute.bytesize, + value, value.bytesize) + LibLLVM.add_attribute_at_index(self, index, attribute_ref) + end + def add_attribute(attribute : Attribute, index = AttributeIndex::FunctionIndex, *, value) return if attribute.value == 0 diff --git a/src/llvm/lib_llvm/core.cr b/src/llvm/lib_llvm/core.cr index 0645441f8a70..20f10c7e6e62 100644 --- a/src/llvm/lib_llvm/core.cr +++ b/src/llvm/lib_llvm/core.cr @@ -25,6 +25,7 @@ lib LibLLVM fun get_enum_attribute_kind_for_name = LLVMGetEnumAttributeKindForName(name : Char*, s_len : SizeT) : UInt fun get_last_enum_attribute_kind = LLVMGetLastEnumAttributeKind : UInt fun create_enum_attribute = LLVMCreateEnumAttribute(c : ContextRef, kind_id : UInt, val : UInt64) : AttributeRef + fun create_string_attribute = LLVMCreateStringAttribute(c : ContextRef, k : Char*, k_length : UInt, v : Char*, v_length : UInt) : AttributeRef {% unless LibLLVM::IS_LT_120 %} fun create_type_attribute = LLVMCreateTypeAttribute(c : ContextRef, kind_id : UInt, type_ref : TypeRef) : AttributeRef {% end %} From 0ff99d97deafc47cf6ef80da8c1f0ece1f9c1343 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Mon, 29 Jan 2024 19:15:46 +0800 Subject: [PATCH 074/105] Add macro methods for `Primitive` (#14263) --- spec/compiler/macro/macro_methods_spec.cr | 7 +++++++ src/compiler/crystal/macros.cr | 21 +++++++++++++++++++++ src/compiler/crystal/macros/methods.cr | 11 +++++++++++ 3 files changed, 39 insertions(+) diff --git a/spec/compiler/macro/macro_methods_spec.cr b/spec/compiler/macro/macro_methods_spec.cr index 5142ad86c5bd..516c3e408280 100644 --- a/spec/compiler/macro/macro_methods_spec.cr +++ b/spec/compiler/macro/macro_methods_spec.cr @@ -2505,6 +2505,13 @@ module Crystal end end + describe Primitive do + it "executes name" do + assert_macro %({{x.name}}), %(:abc), {x: Primitive.new("abc")} + assert_macro %({{x.name}}), %(:"x.y.z"), {x: Primitive.new("x.y.z")} + end + end + describe "macro methods" do it "executes name" do assert_macro %({{x.name}}), "some_macro", {x: Macro.new("some_macro")} diff --git a/src/compiler/crystal/macros.cr b/src/compiler/crystal/macros.cr index c18782dac954..f18c3c7246ab 100644 --- a/src/compiler/crystal/macros.cr +++ b/src/compiler/crystal/macros.cr @@ -1407,6 +1407,27 @@ module Crystal::Macros end end + # A fictitious node representing the body of a `Def` marked with + # `@[Primitive]`. + class Primitive < ASTNode + # Returns the name of the primitive. + # + # This is identical to the argument to the associated `@[Primitive]` + # annotation. + # + # ``` + # module Foo + # @[Primitive(:abc)] + # def foo + # end + # end + # + # {{ Foo.methods.first.body.name }} # => :abc + # ``` + def name : SymbolLiteral + end + end + # A macro definition. class Macro < ASTNode # Returns the name of this macro. diff --git a/src/compiler/crystal/macros/methods.cr b/src/compiler/crystal/macros/methods.cr index 39ec31828328..60ecdb528509 100644 --- a/src/compiler/crystal/macros/methods.cr +++ b/src/compiler/crystal/macros/methods.cr @@ -1459,6 +1459,17 @@ module Crystal end end + class Primitive + def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) + case method + when "name" + interpret_check_args { SymbolLiteral.new(@name) } + else + super + end + end + end + class Macro def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) case method From ab96337f02315171a05d55645baaea3670aa7122 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Mon, 29 Jan 2024 19:15:56 +0800 Subject: [PATCH 075/105] Respect `NO_COLOR` in the compiler (#14260) --- src/compiler/crystal/command.cr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/crystal/command.cr b/src/compiler/crystal/command.cr index 6549c2768aea..18def74ebbd0 100644 --- a/src/compiler/crystal/command.cr +++ b/src/compiler/crystal/command.cr @@ -58,7 +58,7 @@ class Crystal::Command @compiler : Compiler? def initialize(@options : Array(String)) - @color = ENV["TERM"]? != "dumb" + @color = ENV["TERM"]? != "dumb" && !ENV.has_key?("NO_COLOR") @error_trace = false @progress_tracker = ProgressTracker.new end @@ -743,7 +743,7 @@ class Crystal::Command private def error(msg, exit_code = 1) # This is for the case where the main command is wrong - @color = false if ARGV.includes?("--no-color") || ENV["TERM"]? == "dumb" + @color = false if ARGV.includes?("--no-color") || ENV["TERM"]? == "dumb" || ENV.has_key?("NO_COLOR") Crystal.error msg, @color, exit_code: exit_code end From f6b81842e10bc9bb1951ef70fa896591aad3d672 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Mon, 29 Jan 2024 19:16:06 +0800 Subject: [PATCH 076/105] Add macro methods for `TypeOf` (#14262) --- spec/compiler/macro/macro_methods_spec.cr | 6 ++++++ src/compiler/crystal/macros.cr | 14 ++++++++++++-- src/compiler/crystal/macros/methods.cr | 11 +++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/spec/compiler/macro/macro_methods_spec.cr b/spec/compiler/macro/macro_methods_spec.cr index 516c3e408280..a970aff3e876 100644 --- a/spec/compiler/macro/macro_methods_spec.cr +++ b/spec/compiler/macro/macro_methods_spec.cr @@ -2770,6 +2770,12 @@ module Crystal end end + describe TypeOf do + it "executes args" do + assert_macro %({{x.args}}), "[1, 'a', Foo]", {x: TypeOf.new([1.int32, CharLiteral.new('a'), "Foo".path])} + end + end + describe "case methods" do describe "when" do case_node = Case.new(1.int32, [When.new([2.int32, 3.int32] of ASTNode, 4.int32)], 5.int32, exhaustive: false) diff --git a/src/compiler/crystal/macros.cr b/src/compiler/crystal/macros.cr index f18c3c7246ab..3b9ce399c7ef 100644 --- a/src/compiler/crystal/macros.cr +++ b/src/compiler/crystal/macros.cr @@ -2276,8 +2276,18 @@ module Crystal::Macros end end - # class TypeOf < ASTNode - # end + # A `typeof` expression. + # + # Every expression *node* is equivalent to: + # + # ``` + # typeof({{ node.args.splat }}) + # ``` + class TypeOf < ASTNode + # Returns the arguments to this `typeof`. + def args : ArrayLiteral(ASTNode) + end + end # A macro expression, # surrounded by {{ ... }} (output = true) diff --git a/src/compiler/crystal/macros/methods.cr b/src/compiler/crystal/macros/methods.cr index 60ecdb528509..b98306db3fc8 100644 --- a/src/compiler/crystal/macros/methods.cr +++ b/src/compiler/crystal/macros/methods.cr @@ -2362,6 +2362,17 @@ module Crystal end end + class TypeOf + def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) + case method + when "args" + interpret_check_args { ArrayLiteral.map(@expressions, &.itself) } + else + super + end + end + end + class Generic def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) case method From bc0c8725cf007c7e88728ef75100fe7fad1e505b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Mon, 29 Jan 2024 20:14:49 +0100 Subject: [PATCH 077/105] Optimize hash lookup in `Enumerable#group_by` (#14235) Co-authored-by: Quinton Miller <nicetas.c@gmail.com> --- src/enumerable.cr | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/enumerable.cr b/src/enumerable.cr index 6b24c833f44f..9a1aad3debd0 100644 --- a/src/enumerable.cr +++ b/src/enumerable.cr @@ -636,11 +636,7 @@ module Enumerable(T) h = Hash(U, Array(T)).new each do |e| v = yield e - if h.has_key?(v) - h[v].push(e) - else - h[v] = [e] - end + h.put_if_absent(v) { Array(T).new } << e end h end From 57d67c2229d58f2737d00482a2f01e9179499ee3 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Tue, 30 Jan 2024 03:14:57 +0800 Subject: [PATCH 078/105] Fix `Colorize.enabled?`'s documentation (#14258) --- src/colorize.cr | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/colorize.cr b/src/colorize.cr index 48975c8a451f..83fd82c3935e 100644 --- a/src/colorize.cr +++ b/src/colorize.cr @@ -129,8 +129,7 @@ module Colorize # "hello".colorize.red.to_s # => "hello" # ``` # - # NOTE: This is by default disabled on non-TTY devices because they likely don't support ANSI escape codes. - # This will also be disabled if the environment variable `TERM` is "dumb" or `NO_COLOR` contains any value. + # NOTE: This is by default disabled if the environment variable `NO_COLOR` contains any value. class_property? enabled : Bool { !ENV.has_key?("NO_COLOR") } # Makes `Colorize.enabled` `true` if and only if both of `STDOUT.tty?` From 0f7c4e0c1d4864fb905037dd9c9db684acc0122f Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Tue, 30 Jan 2024 03:15:05 +0800 Subject: [PATCH 079/105] Add macro methods for `Alias` (#14261) --- spec/compiler/macro/macro_methods_spec.cr | 12 ++++++++++++ src/compiler/crystal/macros.cr | 18 ++++++++++++++++-- src/compiler/crystal/macros/methods.cr | 13 +++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/spec/compiler/macro/macro_methods_spec.cr b/spec/compiler/macro/macro_methods_spec.cr index a970aff3e876..806040a55faf 100644 --- a/spec/compiler/macro/macro_methods_spec.cr +++ b/spec/compiler/macro/macro_methods_spec.cr @@ -2618,6 +2618,18 @@ module Crystal end end + describe Alias do + node = Alias.new("Foo".path, Generic.new(Path.new(["Bar", "Baz"], global: true), ["T".path] of ASTNode)) + + it "executes name" do + assert_macro %({{x.name}}), %(Foo), {x: node} + end + + it "executes type" do + assert_macro %({{x.type}}), %(::Bar::Baz(T)), {x: node} + end + end + describe "visibility modifier methods" do node = VisibilityModifier.new(Visibility::Protected, Def.new("some_def")) diff --git a/src/compiler/crystal/macros.cr b/src/compiler/crystal/macros.cr index 3b9ce399c7ef..2ab9f051530e 100644 --- a/src/compiler/crystal/macros.cr +++ b/src/compiler/crystal/macros.cr @@ -2234,8 +2234,22 @@ module Crystal::Macros end end - # class Alias < ASTNode - # end + # An `alias` statement. + # + # Every statement `node` is equivalent to: + # + # ``` + # alias {{ node.name }} = {{ node.type }} + # ``` + class Alias < ASTNode + # Returns the name of the alias. + def name : Path + end + + # Returns the name of the type this alias is equivalent to. + def type : ASTNode + end + end # A metaclass in a type expression: `T.class` class Metaclass < ASTNode diff --git a/src/compiler/crystal/macros/methods.cr b/src/compiler/crystal/macros/methods.cr index b98306db3fc8..caa94c23035d 100644 --- a/src/compiler/crystal/macros/methods.cr +++ b/src/compiler/crystal/macros/methods.cr @@ -1560,6 +1560,19 @@ module Crystal end end + class Alias + def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) + case method + when "name" + interpret_check_args { @name } + when "type" + interpret_check_args { @value } + else + super + end + end + end + class OffsetOf def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) case method From 4b8f5c59ae23a79b281a75fadef30b04e973d005 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Tue, 30 Jan 2024 06:28:16 +0800 Subject: [PATCH 080/105] Do not handle inline assembly with `"intel"` flag as AT&T syntax (#14264) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Johannes Müller <straightshoota@gmail.com> --- spec/compiler/codegen/asm_spec.cr | 8 ++++++++ src/compiler/crystal/codegen/asm.cr | 2 +- src/compiler/crystal/codegen/ast.cr | 6 ++++++ src/llvm/enums.cr | 5 +++++ src/llvm/lib_llvm/core.cr | 9 ++------- src/llvm/type.cr | 6 +++--- 6 files changed, 25 insertions(+), 11 deletions(-) diff --git a/spec/compiler/codegen/asm_spec.cr b/spec/compiler/codegen/asm_spec.cr index 2c6b0707699e..289c1455741e 100644 --- a/spec/compiler/codegen/asm_spec.cr +++ b/spec/compiler/codegen/asm_spec.cr @@ -44,5 +44,13 @@ describe "Code gen: asm" do c )).to_i.should eq(42) end + + it "codegens with intel dialect" do + run(<<-CRYSTAL).to_i.should eq(1234) + dst = uninitialized Int32 + asm("mov dword ptr [$0], 1234" :: "r"(pointerof(dst)) :: "intel") + dst + CRYSTAL + end {% end %} end diff --git a/src/compiler/crystal/codegen/asm.cr b/src/compiler/crystal/codegen/asm.cr index f0b3e2f088ab..107d63f19ecf 100644 --- a/src/compiler/crystal/codegen/asm.cr +++ b/src/compiler/crystal/codegen/asm.cr @@ -53,7 +53,7 @@ class Crystal::CodeGenVisitor fun_type = LLVM::Type.function(input_types, output_type) constraints = constraints.to_s - value = fun_type.inline_asm(node.text, constraints, node.volatile?, node.alignstack?, node.can_throw?) + value = fun_type.inline_asm(node.text, constraints, node.volatile?, node.alignstack?, node.can_throw?, node.dialect) value = LLVM::Function.from_value(value) asm_value = call LLVMTypedFunction.new(fun_type, value), input_values diff --git a/src/compiler/crystal/codegen/ast.cr b/src/compiler/crystal/codegen/ast.cr index 816958844dd9..ab4fa76d4e16 100644 --- a/src/compiler/crystal/codegen/ast.cr +++ b/src/compiler/crystal/codegen/ast.cr @@ -138,4 +138,10 @@ module Crystal found_extern end end + + class Asm + def dialect : LLVM::InlineAsmDialect + intel? ? LLVM::InlineAsmDialect::Intel : LLVM::InlineAsmDialect::ATT + end + end end diff --git a/src/llvm/enums.cr b/src/llvm/enums.cr index b8e06fb46f89..ac23fa711560 100644 --- a/src/llvm/enums.cr +++ b/src/llvm/enums.cr @@ -440,6 +440,11 @@ module LLVM LittleEndian = 1 << 28 end + enum InlineAsmDialect + ATT + Intel + end + struct Value enum Kind Argument diff --git a/src/llvm/lib_llvm/core.cr b/src/llvm/lib_llvm/core.cr index 20f10c7e6e62..c865baaa55a5 100644 --- a/src/llvm/lib_llvm/core.cr +++ b/src/llvm/lib_llvm/core.cr @@ -4,11 +4,6 @@ lib LibLLVM # NOTE: the following C enums usually have different values from their C++ # counterparts (e.g. `LLVMModuleFlagBehavior` v.s. `LLVM::Module::ModFlagBehavior`) - enum InlineAsmDialect - ATT - Intel - end - enum ModuleFlagBehavior Warning = 1 end @@ -39,9 +34,9 @@ lib LibLLVM fun print_module_to_file = LLVMPrintModuleToFile(m : ModuleRef, filename : Char*, error_message : Char**) : Bool fun print_module_to_string = LLVMPrintModuleToString(m : ModuleRef) : Char* {% if !LibLLVM::IS_LT_130 %} - fun get_inline_asm = LLVMGetInlineAsm(ty : TypeRef, asm_string : Char*, asm_string_size : SizeT, constraints : Char*, constraints_size : SizeT, has_side_effects : Bool, is_align_stack : Bool, dialect : InlineAsmDialect, can_throw : Bool) : ValueRef + fun get_inline_asm = LLVMGetInlineAsm(ty : TypeRef, asm_string : Char*, asm_string_size : SizeT, constraints : Char*, constraints_size : SizeT, has_side_effects : Bool, is_align_stack : Bool, dialect : LLVM::InlineAsmDialect, can_throw : Bool) : ValueRef {% else %} - fun get_inline_asm = LLVMGetInlineAsm(t : TypeRef, asm_string : Char*, asm_string_size : SizeT, constraints : Char*, constraints_size : SizeT, has_side_effects : Bool, is_align_stack : Bool, dialect : InlineAsmDialect) : ValueRef + fun get_inline_asm = LLVMGetInlineAsm(t : TypeRef, asm_string : Char*, asm_string_size : SizeT, constraints : Char*, constraints_size : SizeT, has_side_effects : Bool, is_align_stack : Bool, dialect : LLVM::InlineAsmDialect) : ValueRef {% end %} fun get_module_context = LLVMGetModuleContext(m : ModuleRef) : ContextRef diff --git a/src/llvm/type.cr b/src/llvm/type.cr index 06c36ff5796d..c391019aef83 100644 --- a/src/llvm/type.cr +++ b/src/llvm/type.cr @@ -173,7 +173,7 @@ struct LLVM::Type Value.new LibLLVM.const_array(self, (values.to_unsafe.as(LibLLVM::ValueRef*)), values.size) end - def inline_asm(asm_string, constraints, has_side_effects = false, is_align_stack = false, can_throw = false) + def inline_asm(asm_string, constraints, has_side_effects = false, is_align_stack = false, can_throw = false, dialect : InlineAsmDialect = InlineAsmDialect::ATT) value = {% if LibLLVM::IS_LT_130 %} LibLLVM.get_inline_asm( @@ -184,7 +184,7 @@ struct LLVM::Type constraints.size, (has_side_effects ? 1 : 0), (is_align_stack ? 1 : 0), - LibLLVM::InlineAsmDialect::ATT + dialect, ) {% else %} LibLLVM.get_inline_asm( @@ -195,7 +195,7 @@ struct LLVM::Type constraints.size, (has_side_effects ? 1 : 0), (is_align_stack ? 1 : 0), - LibLLVM::InlineAsmDialect::ATT, + dialect, (can_throw ? 1 : 0) ) {% end %} From de7a0786e5e1635f6cda6176ac9ec395086f8dcf Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Tue, 30 Jan 2024 06:28:27 +0800 Subject: [PATCH 081/105] Use correct string size for `LLVM::Type#inline_asm` (#14265) --- spec/compiler/codegen/asm_spec.cr | 8 ++++++++ src/llvm/type.cr | 8 ++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/spec/compiler/codegen/asm_spec.cr b/spec/compiler/codegen/asm_spec.cr index 289c1455741e..05eb3b895032 100644 --- a/spec/compiler/codegen/asm_spec.cr +++ b/spec/compiler/codegen/asm_spec.cr @@ -3,6 +3,14 @@ require "../../spec_helper" describe "Code gen: asm" do # TODO: arm asm tests {% if flag?(:i386) || flag?(:x86_64) %} + it "passes correct string length to LLVM" do + run <<-CRYSTAL + asm("// 😂😂 + nop + nop") + CRYSTAL + end + it "codegens without inputs" do run(%( dst = uninitialized Int32 diff --git a/src/llvm/type.cr b/src/llvm/type.cr index c391019aef83..42d1a314c118 100644 --- a/src/llvm/type.cr +++ b/src/llvm/type.cr @@ -179,9 +179,9 @@ struct LLVM::Type LibLLVM.get_inline_asm( self, asm_string, - asm_string.size, + asm_string.bytesize, constraints, - constraints.size, + constraints.bytesize, (has_side_effects ? 1 : 0), (is_align_stack ? 1 : 0), dialect, @@ -190,9 +190,9 @@ struct LLVM::Type LibLLVM.get_inline_asm( self, asm_string, - asm_string.size, + asm_string.bytesize, constraints, - constraints.size, + constraints.bytesize, (has_side_effects ? 1 : 0), (is_align_stack ? 1 : 0), dialect, From 8a2a1a83f1f454f2a424242eef2c6a55158a536c Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Tue, 30 Jan 2024 20:47:10 +0800 Subject: [PATCH 082/105] Fix name locations of `FunDef` and `External` nodes (#14267) --- spec/compiler/parser/parser_spec.cr | 18 ++++++++++++++++++ .../crystal/semantic/top_level_visitor.cr | 1 + src/compiler/crystal/syntax/ast.cr | 9 ++++++++- src/compiler/crystal/syntax/parser.cr | 2 ++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/spec/compiler/parser/parser_spec.cr b/spec/compiler/parser/parser_spec.cr index 2fa1a5b4c4a7..9f4ec5faccf7 100644 --- a/spec/compiler/parser/parser_spec.cr +++ b/spec/compiler/parser/parser_spec.cr @@ -2505,6 +2505,24 @@ module Crystal name_location.column_number.should eq(12) end + it "sets location of top-level fun name" do + parser = Parser.new("fun foo; end") + node = parser.parse.as(FunDef) + + name_location = node.name_location.should_not be_nil + name_location.line_number.should eq(1) + name_location.column_number.should eq(5) + end + + it "sets location of lib fun name" do + parser = Parser.new("lib Foo; fun foo; end") + node = parser.parse.as(LibDef).body.as(FunDef) + + name_location = node.name_location.should_not be_nil + name_location.line_number.should eq(1) + name_location.column_number.should eq(14) + end + it "sets correct location of proc literal" do parser = Parser.new("->(\n x : Int32,\n y : String\n) { }") node = parser.parse.as(ProcLiteral) diff --git a/src/compiler/crystal/semantic/top_level_visitor.cr b/src/compiler/crystal/semantic/top_level_visitor.cr index 05d8918f8383..11c5707b19fa 100644 --- a/src/compiler/crystal/semantic/top_level_visitor.cr +++ b/src/compiler/crystal/semantic/top_level_visitor.cr @@ -918,6 +918,7 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor end external = External.new(node.name, external_args, node.body, node.real_name).at(node) + external.name_location = node.name_location call_convention = nil process_def_annotations(external, annotations) do |annotation_type, ann| diff --git a/src/compiler/crystal/syntax/ast.cr b/src/compiler/crystal/syntax/ast.cr index d0be18606714..9c0ffcf0d7e5 100644 --- a/src/compiler/crystal/syntax/ast.cr +++ b/src/compiler/crystal/syntax/ast.cr @@ -1954,6 +1954,7 @@ module Crystal property real_name : String property doc : String? property? varargs : Bool + property name_location : Location? def initialize(@name, @args = [] of Arg, @return_type = nil, @varargs = false, @body = nil, @real_name = name) end @@ -1965,7 +1966,13 @@ module Crystal end def clone_without_location - FunDef.new(@name, @args.clone, @return_type.clone, @varargs, @body.clone, @real_name) + clone = FunDef.new(@name, @args.clone, @return_type.clone, @varargs, @body.clone, @real_name) + clone.name_location = name_location + clone + end + + def name_size + @name.size end def_equals_and_hash @name, @args, @return_type, @varargs, @body, @real_name diff --git a/src/compiler/crystal/syntax/parser.cr b/src/compiler/crystal/syntax/parser.cr index f14399212e65..e3f4c2605ed6 100644 --- a/src/compiler/crystal/syntax/parser.cr +++ b/src/compiler/crystal/syntax/parser.cr @@ -5732,6 +5732,7 @@ module Crystal with_isolated_var_scope(require_body) do next_token_skip_space_or_newline + name_location = @token.location name = if top_level check_ident else @@ -5835,6 +5836,7 @@ module Crystal end fun_def = FunDef.new name, params, return_type, varargs, body, real_name + fun_def.name_location = name_location fun_def.doc = doc fun_def.at(location).at_end(end_location) end From d88c013588e4c92d2510af21b88fd14542c5a902 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Tue, 30 Jan 2024 20:47:21 +0800 Subject: [PATCH 083/105] Ensure `Crystal::Visitor#visit` returns `Bool` (#14266) --- samples/compiler/visitor_example.cr | 1 + src/compiler/crystal/codegen/codegen.cr | 17 +++++++++++--- src/compiler/crystal/codegen/primitives.cr | 2 ++ src/compiler/crystal/interpreter/compiler.cr | 5 +++-- src/compiler/crystal/macros/interpreter.cr | 8 +++++-- .../crystal/semantic/cleanup_transformer.cr | 2 ++ src/compiler/crystal/semantic/main_visitor.cr | 22 ++++++++++++++++--- .../semantic/restrictions_augmenter.cr | 3 ++- src/compiler/crystal/semantic/to_s.cr | 3 +++ .../crystal/semantic/top_level_visitor.cr | 1 + .../crystal/semantic/type_guess_visitor.cr | 3 +++ src/compiler/crystal/syntax/to_s.cr | 15 +++++++++++++ src/compiler/crystal/tools/expand.cr | 4 ++++ src/compiler/crystal/tools/implementations.cr | 2 ++ .../crystal/tools/print_types_visitor.cr | 4 ++++ 15 files changed, 81 insertions(+), 11 deletions(-) diff --git a/samples/compiler/visitor_example.cr b/samples/compiler/visitor_example.cr index ec063a832efa..d9be4da91baf 100644 --- a/samples/compiler/visitor_example.cr +++ b/samples/compiler/visitor_example.cr @@ -15,6 +15,7 @@ class Counter < Crystal::Visitor def visit(node : Crystal::NumberLiteral) @count += 1 + false end def visit(node : Crystal::ASTNode) diff --git a/src/compiler/crystal/codegen/codegen.cr b/src/compiler/crystal/codegen/codegen.cr index a6015012eb7c..e7128302a66e 100644 --- a/src/compiler/crystal/codegen/codegen.cr +++ b/src/compiler/crystal/codegen/codegen.cr @@ -501,18 +501,22 @@ module Crystal def visit(node : Nop) @last = llvm_nil + false end def visit(node : NilLiteral) @last = llvm_nil + false end def visit(node : BoolLiteral) @last = int1(node.value ? 1 : 0) + false end def visit(node : CharLiteral) @last = int32(node.value.ord) + false end def visit(node : NumberLiteral) @@ -542,14 +546,17 @@ module Crystal in .f64? @last = float64(node.value) end + false end def visit(node : StringLiteral) @last = build_string_constant(node.value, node.value) + false end def visit(node : SymbolLiteral) @last = int(@symbols[node.value]) + false end def visit(node : TupleLiteral) @@ -1092,7 +1099,7 @@ module Crystal request_value(value) - return if value.no_returns? + return false if value.no_returns? last = @last @@ -1106,7 +1113,7 @@ module Crystal read_class_var_ptr(target) when Var # Can't assign void - return if target.type.void? + return false if target.type.void? # If assigning to a special variable in a method that yields, # assign to that variable too. @@ -1284,6 +1291,7 @@ module Crystal else node.raise "BUG: missing context var: #{node.name}" end + false end def visit(node : Global) @@ -1292,6 +1300,7 @@ module Crystal def visit(node : ClassVar) @last = read_class_var(node) + false end def visit(node : InstanceVar) @@ -1403,7 +1412,7 @@ module Crystal unless filtered_type @last = upcast llvm_nil, resulting_type, @program.nil - return + return false end non_nilable_type = node.non_nilable_type @@ -1664,6 +1673,7 @@ module Crystal def visit(node : Unreachable) builder.unreachable + false end def check_proc_is_not_closure(value, type) @@ -2049,6 +2059,7 @@ module Crystal def unreachable(file = __FILE__, line = __LINE__) debug_codegen_log(file, line) { "Reached the unreachable!" } builder.unreachable + false end def allocate_aggregate(type) diff --git a/src/compiler/crystal/codegen/primitives.cr b/src/compiler/crystal/codegen/primitives.cr index 9ed05c0009f2..80ba7d832a41 100644 --- a/src/compiler/crystal/codegen/primitives.cr +++ b/src/compiler/crystal/codegen/primitives.cr @@ -11,6 +11,8 @@ class Crystal::CodeGenVisitor else raise "BUG: unhandled primitive in codegen visit: #{node.name}" end + + false end def codegen_primitive(call, node, target_def, call_args) diff --git a/src/compiler/crystal/interpreter/compiler.cr b/src/compiler/crystal/interpreter/compiler.cr index bfd1514b419f..04fc885fce7e 100644 --- a/src/compiler/crystal/interpreter/compiler.cr +++ b/src/compiler/crystal/interpreter/compiler.cr @@ -762,7 +762,7 @@ class Crystal::Repl::Compiler < Crystal::Visitor # particularly when outside of a method. if is_self && !scope.is_a?(Program) && !scope.passed_as_self? put_type scope, node: node - return + return false end local_var = lookup_local_var_or_closured_var(node.name) @@ -1687,7 +1687,7 @@ class Crystal::Repl::Compiler < Crystal::Visitor if node.upcast? upcast node.obj, obj_type, node.non_nilable_type upcast node.obj, node.non_nilable_type, node.type - return + return false end # Check if obj is a `to_type` @@ -3158,6 +3158,7 @@ class Crystal::Repl::Compiler < Crystal::Visitor {% end %} call compiled_def, node: node + false end def visit(node : ASTNode) diff --git a/src/compiler/crystal/macros/interpreter.cr b/src/compiler/crystal/macros/interpreter.cr index 5bc7cd0117ca..1e18e92b7545 100644 --- a/src/compiler/crystal/macros/interpreter.cr +++ b/src/compiler/crystal/macros/interpreter.cr @@ -118,6 +118,7 @@ module Crystal def visit(node : MacroLiteral) @str << node.value + false end def visit(node : MacroVerbatim) @@ -135,7 +136,8 @@ module Crystal def visit(node : Var) var = @vars[node.name]? if var - return @last = var + @last = var + return false end # Try to consider the var as a top-level macro call. @@ -150,7 +152,8 @@ module Crystal # and in this case the parser has no idea about this, so the only # solution is to do it now. if value = interpret_top_level_call?(Call.new(nil, node.name)) - return @last = value + @last = value + return false end node.raise "undefined macro variable '#{node.name}'" @@ -549,6 +552,7 @@ module Crystal else node.raise "unknown macro instance var: '#{node.name}'" end + false end def visit(node : TupleLiteral) diff --git a/src/compiler/crystal/semantic/cleanup_transformer.cr b/src/compiler/crystal/semantic/cleanup_transformer.cr index bc3084429ed3..541e0f51d662 100644 --- a/src/compiler/crystal/semantic/cleanup_transformer.cr +++ b/src/compiler/crystal/semantic/cleanup_transformer.cr @@ -635,10 +635,12 @@ module Crystal if @a_def.vars.try &.[node.name]?.try &.closured? @vars << node end + false end def visit(node : InstanceVar) @vars << node + false end def visit(node : ASTNode) diff --git a/src/compiler/crystal/semantic/main_visitor.cr b/src/compiler/crystal/semantic/main_visitor.cr index 37218e7a34dc..61d1aa508a46 100644 --- a/src/compiler/crystal/semantic/main_visitor.cr +++ b/src/compiler/crystal/semantic/main_visitor.cr @@ -226,6 +226,8 @@ module Crystal node.syntax_replacement = type node.bind_to type end + + false end def visit(node : Generic) @@ -353,6 +355,7 @@ module Crystal def visit(node : Self) node.type = the_self(node).instance_type + false end def visit(node : Var) @@ -394,6 +397,7 @@ module Crystal else node.raise "read before assignment to local variable '#{node.name}'" end + false end def visit(node : TypeDeclaration) @@ -628,6 +632,8 @@ module Crystal ivar.nil_reason ||= NilReason.new(node.name, :used_before_initialized, [node] of ASTNode) ivar.bind_to program.nil_var end + + false end def visit(node : ReadInstanceVar) @@ -1007,7 +1013,7 @@ module Crystal end def visit(node : Block) - return if node.visited? + return false if node.visited? node.visited = true node.context = current_non_block_context @@ -1630,6 +1636,7 @@ module Crystal ivars[node.name] = node_in_callstack(node) end end + false end def visit(node : Var) @@ -1761,7 +1768,7 @@ module Crystal comp.accept self node.syntax_replacement = comp node.bind_to comp - return + return false end if needs_type_filters? && (var = get_expression_var(node.obj)) @@ -2060,7 +2067,7 @@ module Crystal unless node.has_breaks? if endless_while node.type = program.no_return - return + return false end filter_vars TypeFilters.not(cond_type_filters) @@ -2325,6 +2332,8 @@ module Crystal else node.raise "BUG: unhandled primitive in MainVisitor: #{node.name}" end + + false end def visit_va_arg(node) @@ -3042,31 +3051,38 @@ module Crystal def visit(node : Nop) node.type = @program.nil + false end def visit(node : NilLiteral) node.type = @program.nil + false end def visit(node : BoolLiteral) node.type = program.bool + false end def visit(node : NumberLiteral) node.type = program.type_from_literal_kind node.kind + false end def visit(node : CharLiteral) node.type = program.char + false end def visit(node : SymbolLiteral) node.type = program.symbol program.symbols.add node.value + false end def visit(node : StringLiteral) node.type = program.string + false end def visit(node : RegexLiteral) diff --git a/src/compiler/crystal/semantic/restrictions_augmenter.cr b/src/compiler/crystal/semantic/restrictions_augmenter.cr index a627f27f5fe0..5b3e31056110 100644 --- a/src/compiler/crystal/semantic/restrictions_augmenter.cr +++ b/src/compiler/crystal/semantic/restrictions_augmenter.cr @@ -59,7 +59,8 @@ module Crystal def visit(node : Call) if expanded = node.expanded - return expanded.accept self + expanded.accept self + return false end node.obj.try &.accept self diff --git a/src/compiler/crystal/semantic/to_s.cr b/src/compiler/crystal/semantic/to_s.cr index 8c91426bc379..13e8203efe1d 100644 --- a/src/compiler/crystal/semantic/to_s.cr +++ b/src/compiler/crystal/semantic/to_s.cr @@ -44,14 +44,17 @@ module Crystal def visit(node : Primitive) @str << "# primitive: " @str << node.name + false end def visit(node : MetaVar) @str << node.name + false end def visit(node : MetaMacroVar) @str << node.name + false end def visit(node : TypeFilteredNode) diff --git a/src/compiler/crystal/semantic/top_level_visitor.cr b/src/compiler/crystal/semantic/top_level_visitor.cr index 11c5707b19fa..9b7eedb2a876 100644 --- a/src/compiler/crystal/semantic/top_level_visitor.cr +++ b/src/compiler/crystal/semantic/top_level_visitor.cr @@ -598,6 +598,7 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor typed_def_type = lookup_type(node.type_spec) typed_def_type = check_allowed_in_lib node.type_spec, typed_def_type current_type.types[node.name] = TypeDefType.new @program, current_type, node.name, typed_def_type + false end end diff --git a/src/compiler/crystal/semantic/type_guess_visitor.cr b/src/compiler/crystal/semantic/type_guess_visitor.cr index 693cade2906b..612390db8e21 100644 --- a/src/compiler/crystal/semantic/type_guess_visitor.cr +++ b/src/compiler/crystal/semantic/type_guess_visitor.cr @@ -86,6 +86,7 @@ module Crystal end check_var_is_self(node) + false end def visit(node : UninitializedVar) @@ -114,6 +115,7 @@ module Crystal # TODO: can this be reached? end end + false end def visit(node : Assign) @@ -1353,6 +1355,7 @@ module Crystal if node.name == "self" @has_self = true end + false end def visit(node : ASTNode) diff --git a/src/compiler/crystal/syntax/to_s.cr b/src/compiler/crystal/syntax/to_s.cr index f5086e346277..3ea146d15c3e 100644 --- a/src/compiler/crystal/syntax/to_s.cr +++ b/src/compiler/crystal/syntax/to_s.cr @@ -49,10 +49,12 @@ module Crystal end def visit(node : Nop) + false end def visit(node : BoolLiteral) @str << (node.value ? "true" : "false") + false end def visit(node : NumberLiteral) @@ -62,6 +64,8 @@ module Crystal @str << '_' @str << node.kind.to_s end + + false end def needs_suffix?(node : NumberLiteral) @@ -83,10 +87,12 @@ module Crystal def visit(node : CharLiteral) node.value.inspect(@str) + false end def visit(node : SymbolLiteral) visit_symbol_literal_value node.value + false end def visit_symbol_literal_value(value : String) @@ -100,6 +106,7 @@ module Crystal def visit(node : StringLiteral) node.value.inspect(@str) + false end def visit(node : StringInterpolation) @@ -189,6 +196,7 @@ module Crystal def visit(node : NilLiteral) @str << "nil" + false end def visit(node : Expressions) @@ -573,6 +581,7 @@ module Crystal def visit(node : Var) @str << node.name + false end def visit(node : ProcLiteral) @@ -836,11 +845,13 @@ module Crystal def visit(node : Self) @str << "self" + false end def visit(node : Path) @str << "::" if node.global? node.names.join(@str, "::") + false end def visit(node : Generic) @@ -907,6 +918,7 @@ module Crystal def visit(node : InstanceVar) @str << node.name + false end def visit(node : ReadInstanceVar) @@ -918,6 +930,7 @@ module Crystal def visit(node : ClassVar) @str << node.name + false end def visit(node : Yield) @@ -1105,6 +1118,7 @@ module Crystal def visit(node : Global) @str << node.name + false end def visit(node : LibDef) @@ -1449,6 +1463,7 @@ module Crystal def visit(node : MagicConstant) @str << node.name + false end def visit(node : Asm) diff --git a/src/compiler/crystal/tools/expand.cr b/src/compiler/crystal/tools/expand.cr index 365fc2b3f865..792d60869bd3 100644 --- a/src/compiler/crystal/tools/expand.cr +++ b/src/compiler/crystal/tools/expand.cr @@ -144,6 +144,8 @@ module Crystal else contains_target(node) end + else + false end end @@ -156,6 +158,8 @@ module Crystal else contains_target(node) end + else + false end end diff --git a/src/compiler/crystal/tools/implementations.cr b/src/compiler/crystal/tools/implementations.cr index f4f3a390f0eb..e2dbee001346 100644 --- a/src/compiler/crystal/tools/implementations.cr +++ b/src/compiler/crystal/tools/implementations.cr @@ -114,6 +114,7 @@ module Crystal @locations << target_def.location.not_nil! end end + false end def visit(node : Path) @@ -123,6 +124,7 @@ module Crystal target.try &.locations.try &.each do |loc| @locations << loc end + false end def visit(node) diff --git a/src/compiler/crystal/tools/print_types_visitor.cr b/src/compiler/crystal/tools/print_types_visitor.cr index 6ffc533a4b0f..0744dc17febd 100644 --- a/src/compiler/crystal/tools/print_types_visitor.cr +++ b/src/compiler/crystal/tools/print_types_visitor.cr @@ -39,10 +39,12 @@ module Crystal def visit(node : Var) output_name node + false end def visit(node : Global) output_name node + false end def visit(node : TypeDeclaration) @@ -50,6 +52,7 @@ module Crystal if var.is_a?(Var) output_name var end + false end def visit(node : UninitializedVar) @@ -57,6 +60,7 @@ module Crystal if var.is_a?(Var) output_name var end + false end def output_name(node) From f66312174d0b7dfa30b8795e356c30b9c23e0649 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Tue, 30 Jan 2024 20:47:29 +0800 Subject: [PATCH 084/105] Add macro methods for `Asm` and `AsmOperand` (#14268) --- spec/compiler/macro/macro_methods_spec.cr | 69 +++++++++++++++++++++++ src/compiler/crystal/macros.cr | 69 +++++++++++++++++++++++ src/compiler/crystal/macros/methods.cr | 56 ++++++++++++++++++ 3 files changed, 194 insertions(+) diff --git a/spec/compiler/macro/macro_methods_spec.cr b/spec/compiler/macro/macro_methods_spec.cr index 806040a55faf..76d5f795903c 100644 --- a/spec/compiler/macro/macro_methods_spec.cr +++ b/spec/compiler/macro/macro_methods_spec.cr @@ -3426,6 +3426,75 @@ module Crystal end end + describe Asm do + asm1 = Asm.new("nop") + asm2 = Asm.new( + text: "foo", + outputs: [AsmOperand.new("=r", "x".var), AsmOperand.new("=r", "y".var)], + inputs: [AsmOperand.new("i", 1.int32), AsmOperand.new("r", 2.int32)], + clobbers: %w(rax memory), + volatile: true, + alignstack: true, + intel: true, + can_throw: true, + ) + + it "executes text" do + assert_macro %({{x.text}}), %("nop"), {x: asm1} + assert_macro %({{x.text}}), %("foo"), {x: asm2} + end + + it "executes outputs" do + assert_macro %({{x.outputs}}), %([] of ::NoReturn), {x: asm1} + assert_macro %({{x.outputs}}), %(["=r"(x), "=r"(y)]), {x: asm2} + end + + it "executes inputs" do + assert_macro %({{x.inputs}}), %([] of ::NoReturn), {x: asm1} + assert_macro %({{x.inputs}}), %(["i"(1), "r"(2)]), {x: asm2} + end + + it "executes clobbers" do + assert_macro %({{x.clobbers}}), %([] of ::NoReturn), {x: asm1} + assert_macro %({{x.clobbers}}), %(["rax", "memory"]), {x: asm2} + end + + it "executes volatile?" do + assert_macro %({{x.volatile?}}), %(false), {x: asm1} + assert_macro %({{x.volatile?}}), %(true), {x: asm2} + end + + it "executes alignstack?" do + assert_macro %({{x.alignstack?}}), %(false), {x: asm1} + assert_macro %({{x.alignstack?}}), %(true), {x: asm2} + end + + it "executes intel?" do + assert_macro %({{x.intel?}}), %(false), {x: asm1} + assert_macro %({{x.intel?}}), %(true), {x: asm2} + end + + it "executes can_throw?" do + assert_macro %({{x.can_throw?}}), %(false), {x: asm1} + assert_macro %({{x.can_throw?}}), %(true), {x: asm2} + end + end + + describe AsmOperand do + asm_operand1 = AsmOperand.new("=r", "x".var) + asm_operand2 = AsmOperand.new("i", 1.int32) + + it "executes constraint" do + assert_macro %({{x.constraint}}), %("=r"), {x: asm_operand1} + assert_macro %({{x.constraint}}), %("i"), {x: asm_operand2} + end + + it "executes exp" do + assert_macro %({{x.exp}}), %(x), {x: asm_operand1} + assert_macro %({{x.exp}}), %(1), {x: asm_operand2} + end + end + describe "env" do it "has key" do with_env("FOO": "foo") do diff --git a/src/compiler/crystal/macros.cr b/src/compiler/crystal/macros.cr index 2ab9f051530e..3ec6243ffd62 100644 --- a/src/compiler/crystal/macros.cr +++ b/src/compiler/crystal/macros.cr @@ -2377,6 +2377,75 @@ module Crystal::Macros class MagicConstant < ASTNode end + # An inline assembly expression. + # + # Every assembly `node` is equivalent to: + # + # ``` + # asm( + # {{ node.text }} : + # {{ node.outputs.splat }} : + # {{ node.inputs.splat }} : + # {{ node.clobbers.splat }} : + # {% if node.volatile? %} "volatile", {% end %} + # {% if node.alignstack? %} "alignstack", {% end %} + # {% if node.intel? %} "intel", {% end %} + # {% if node.can_throw? %} "unwind", {% end %} + # ) + # ``` + class Asm < ASTNode + # Returns the template string for this assembly expression. + def text : StringLiteral + end + + # Returns an array of output operands for this assembly expression. + def outputs : ArrayLiteral(AsmOperand) + end + + # Returns an array of input operands for this assembly expression. + def inputs : ArrayLiteral(AsmOperand) + end + + # Returns an array of clobbered register names for this assembly expression. + def clobbers : ArrayLiteral(StringLiteral) + end + + # Returns whether the assembly expression contains side effects that are + # not listed in `#outputs`, `#inputs`, and `#clobbers`. + def volatile? : BoolLiteral + end + + # Returns whether the assembly expression requires stack alignment code. + def alignstack? : BoolLiteral + end + + # Returns `true` if the template string uses the Intel syntax, `false` if it + # uses the AT&T syntax. + def intel? : BoolLiteral + end + + # Returns whether the assembly expression might unwind the stack. + def can_throw? : BoolLiteral + end + end + + # An output or input operand for an `Asm` node. + # + # Every operand `node` is equivalent to: + # + # ``` + # {{ node.constraint }}({{ node.exp }}) + # ``` + class AsmOperand < ASTNode + # Returns the constraint string of this operand. + def constraint : StringLiteral + end + + # Returns the associated output or input argument of this operand. + def exp : ASTNode + end + end + # A fictitious node representing an identifier like, `foo`, `Bar` or `something_else`. # # The parser doesn't create these nodes. Instead, you create them by invoking `id` diff --git a/src/compiler/crystal/macros/methods.cr b/src/compiler/crystal/macros/methods.cr index caa94c23035d..9891c4cc2b2a 100644 --- a/src/compiler/crystal/macros/methods.cr +++ b/src/compiler/crystal/macros/methods.cr @@ -1653,6 +1653,62 @@ module Crystal end end + class Asm + def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) + case method + when "text" + interpret_check_args { StringLiteral.new(@text) } + when "outputs" + interpret_check_args do + if outputs = @outputs + ArrayLiteral.map(outputs, &.itself) + else + empty_no_return_array + end + end + when "inputs" + interpret_check_args do + if inputs = @inputs + ArrayLiteral.map(inputs, &.itself) + else + empty_no_return_array + end + end + when "clobbers" + interpret_check_args do + if clobbers = @clobbers + ArrayLiteral.map(clobbers) { |clobber| StringLiteral.new(clobber) } + else + empty_no_return_array + end + end + when "volatile?" + interpret_check_args { BoolLiteral.new(@volatile) } + when "alignstack?" + interpret_check_args { BoolLiteral.new(@alignstack) } + when "intel?" + interpret_check_args { BoolLiteral.new(@intel) } + when "can_throw?" + interpret_check_args { BoolLiteral.new(@can_throw) } + else + super + end + end + end + + class AsmOperand + def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) + case method + when "constraint" + interpret_check_args { StringLiteral.new(@constraint) } + when "exp" + interpret_check_args { @exp } + else + super + end + end + end + class MacroId def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) case method From 8d1c0806d2e959825a65727fdc0cc5b36a5648a5 Mon Sep 17 00:00:00 2001 From: Julien Portalier <julien@portalier.com> Date: Tue, 30 Jan 2024 20:13:06 +0100 Subject: [PATCH 085/105] Thread: set name (#14257) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Johannes Müller <straightshoota@gmail.com> --- spec/std/thread_spec.cr | 13 ++++++++++++ src/crystal/scheduler.cr | 2 +- src/crystal/system/thread.cr | 20 ++++++++++++++++++- src/crystal/system/unix/pthread.cr | 17 ++++++++++++++++ src/crystal/system/win32/thread.cr | 7 +++++++ src/lib_c/aarch64-android/c/pthread.cr | 1 + src/lib_c/aarch64-darwin/c/pthread.cr | 1 + src/lib_c/aarch64-linux-gnu/c/pthread.cr | 1 + src/lib_c/aarch64-linux-musl/c/pthread.cr | 1 + src/lib_c/arm-linux-gnueabihf/c/pthread.cr | 1 + src/lib_c/i386-linux-gnu/c/pthread.cr | 1 + src/lib_c/i386-linux-musl/c/pthread.cr | 1 + src/lib_c/x86_64-darwin/c/pthread.cr | 1 + src/lib_c/x86_64-dragonfly/c/pthread.cr | 1 + src/lib_c/x86_64-freebsd/c/pthread.cr | 1 + src/lib_c/x86_64-linux-gnu/c/pthread.cr | 1 + src/lib_c/x86_64-linux-musl/c/pthread.cr | 1 + src/lib_c/x86_64-netbsd/c/pthread.cr | 1 + src/lib_c/x86_64-openbsd/c/pthread.cr | 1 + .../c/processthreadsapi.cr | 3 +++ 20 files changed, 74 insertions(+), 2 deletions(-) diff --git a/spec/std/thread_spec.cr b/spec/std/thread_spec.cr index 599a1968f52f..136026667137 100644 --- a/spec/std/thread_spec.cr +++ b/spec/std/thread_spec.cr @@ -49,4 +49,17 @@ describe Thread do thread.join end + + it "names the thread" do + Thread.current.name.should be_nil + name = nil + + thread = Thread.new(name: "some-name") do + name = Thread.current.name + end + thread.name.should eq("some-name") + + thread.join + name.should eq("some-name") + end end diff --git a/src/crystal/scheduler.cr b/src/crystal/scheduler.cr index fa963595bf6d..101a287d23bb 100644 --- a/src/crystal/scheduler.cr +++ b/src/crystal/scheduler.cr @@ -234,7 +234,7 @@ class Crystal::Scheduler Thread.current.scheduler.enqueue worker_loop Thread.current else - Thread.new do + Thread.new(name: "CRYSTAL-MT-#{i}") do scheduler = Thread.current.scheduler pending.sub(1) scheduler.run_loop diff --git a/src/crystal/system/thread.cr b/src/crystal/system/thread.cr index 88784ed68330..b40a7dceb32b 100644 --- a/src/crystal/system/thread.cr +++ b/src/crystal/system/thread.cr @@ -17,6 +17,8 @@ module Crystal::System::Thread # private def system_close # private def stack_address : Void* + + # private def system_name=(String) : String end {% if flag?(:wasi) %} @@ -49,12 +51,14 @@ class Thread # :nodoc: property previous : Thread? + getter name : String? + def self.unsafe_each(&) threads.unsafe_each { |thread| yield thread } end # Creates and starts a new system thread. - def initialize(&@func : ->) + def initialize(@name : String? = nil, &@func : ->) @system_handle = uninitialized Crystal::System::Thread::Handle init_handle end @@ -104,6 +108,12 @@ class Thread Crystal::System::Thread.yield_current end + # Changes the name of the current thread. + def self.name=(name : String) : String + thread = Thread.current + thread.name = name + end + # :nodoc: getter scheduler : Crystal::Scheduler { Crystal::Scheduler.new(self) } @@ -112,6 +122,10 @@ class Thread Thread.current = self @main_fiber = fiber = Fiber.new(stack_address, self) + if name = @name + self.system_name = name + end + begin @func.call rescue ex @@ -123,6 +137,10 @@ class Thread end end + protected def name=(@name : String) + self.system_name = name + end + # Holds the GC thread handler property gc_thread_handler : Void* = Pointer(Void).null end diff --git a/src/crystal/system/unix/pthread.cr b/src/crystal/system/unix/pthread.cr index ca16080621e3..5d6e2a332adc 100644 --- a/src/crystal/system/unix/pthread.cr +++ b/src/crystal/system/unix/pthread.cr @@ -112,6 +112,23 @@ module Crystal::System::Thread address end + + # Warning: must be called from the current thread itself, because Darwin + # doesn't allow to set the name of any thread but the current one! + private def system_name=(name : String) : String + {% if flag?(:darwin) %} + LibC.pthread_setname_np(name) + {% elsif flag?(:netbsd) %} + LibC.pthread_setname_np(@system_handle, name, nil) + {% elsif LibC.has_method?(:pthread_setname_np) %} + LibC.pthread_setname_np(@system_handle, name) + {% elsif LibC.has_method?(:pthread_set_name_np) %} + LibC.pthread_set_name_np(@system_handle, name) + {% else %} + {% raise "No `Crystal::System::Thread#system_name` implementation available" %} + {% end %} + name + end end # In musl (alpine) the calls to unwind API segfaults diff --git a/src/crystal/system/win32/thread.cr b/src/crystal/system/win32/thread.cr index 5dbcbabbfad9..2b44f66c28ce 100644 --- a/src/crystal/system/win32/thread.cr +++ b/src/crystal/system/win32/thread.cr @@ -72,4 +72,11 @@ module Crystal::System::Thread low_limit {% end %} end + + private def system_name=(name : String) : String + {% if LibC.has_method?(:SetThreadDescription) %} + LibC.SetThreadDescription(@system_handle, System.to_wstr(name)) + {% end %} + name + end end diff --git a/src/lib_c/aarch64-android/c/pthread.cr b/src/lib_c/aarch64-android/c/pthread.cr index d761bcb3ceb2..fbab59bd07d7 100644 --- a/src/lib_c/aarch64-android/c/pthread.cr +++ b/src/lib_c/aarch64-android/c/pthread.cr @@ -38,6 +38,7 @@ lib LibC fun pthread_mutex_unlock(__mutex : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(__key : PthreadT, __name : Char*) : Int fun pthread_setspecific(__key : PthreadKeyT, __value : Void*) : Int end diff --git a/src/lib_c/aarch64-darwin/c/pthread.cr b/src/lib_c/aarch64-darwin/c/pthread.cr index dd262f7d9c12..d146e227197f 100644 --- a/src/lib_c/aarch64-darwin/c/pthread.cr +++ b/src/lib_c/aarch64-darwin/c/pthread.cr @@ -25,4 +25,5 @@ lib LibC fun pthread_mutex_trylock(x0 : PthreadMutexT*) : Int fun pthread_mutex_unlock(x0 : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(Char*) : Int end diff --git a/src/lib_c/aarch64-linux-gnu/c/pthread.cr b/src/lib_c/aarch64-linux-gnu/c/pthread.cr index 643fca7c015a..5d9f7b94e225 100644 --- a/src/lib_c/aarch64-linux-gnu/c/pthread.cr +++ b/src/lib_c/aarch64-linux-gnu/c/pthread.cr @@ -36,4 +36,5 @@ lib LibC fun pthread_mutex_trylock(mutex : PthreadMutexT*) : Int fun pthread_mutex_unlock(mutex : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(PthreadT, Char*) : Int end diff --git a/src/lib_c/aarch64-linux-musl/c/pthread.cr b/src/lib_c/aarch64-linux-musl/c/pthread.cr index c318bb5f4357..6ee1a20d90a6 100644 --- a/src/lib_c/aarch64-linux-musl/c/pthread.cr +++ b/src/lib_c/aarch64-linux-musl/c/pthread.cr @@ -27,4 +27,5 @@ lib LibC fun pthread_mutex_trylock(x0 : PthreadMutexT*) : Int fun pthread_mutex_unlock(x0 : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(PthreadT, Char*) : Int end diff --git a/src/lib_c/arm-linux-gnueabihf/c/pthread.cr b/src/lib_c/arm-linux-gnueabihf/c/pthread.cr index 643fca7c015a..5d9f7b94e225 100644 --- a/src/lib_c/arm-linux-gnueabihf/c/pthread.cr +++ b/src/lib_c/arm-linux-gnueabihf/c/pthread.cr @@ -36,4 +36,5 @@ lib LibC fun pthread_mutex_trylock(mutex : PthreadMutexT*) : Int fun pthread_mutex_unlock(mutex : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(PthreadT, Char*) : Int end diff --git a/src/lib_c/i386-linux-gnu/c/pthread.cr b/src/lib_c/i386-linux-gnu/c/pthread.cr index ab943b23587d..33274a6cf51d 100644 --- a/src/lib_c/i386-linux-gnu/c/pthread.cr +++ b/src/lib_c/i386-linux-gnu/c/pthread.cr @@ -35,4 +35,5 @@ lib LibC fun pthread_mutex_trylock(mutex : PthreadMutexT*) : Int fun pthread_mutex_unlock(mutex : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(PthreadT, Char*) : Int end diff --git a/src/lib_c/i386-linux-musl/c/pthread.cr b/src/lib_c/i386-linux-musl/c/pthread.cr index c318bb5f4357..6ee1a20d90a6 100644 --- a/src/lib_c/i386-linux-musl/c/pthread.cr +++ b/src/lib_c/i386-linux-musl/c/pthread.cr @@ -27,4 +27,5 @@ lib LibC fun pthread_mutex_trylock(x0 : PthreadMutexT*) : Int fun pthread_mutex_unlock(x0 : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(PthreadT, Char*) : Int end diff --git a/src/lib_c/x86_64-darwin/c/pthread.cr b/src/lib_c/x86_64-darwin/c/pthread.cr index dd262f7d9c12..d146e227197f 100644 --- a/src/lib_c/x86_64-darwin/c/pthread.cr +++ b/src/lib_c/x86_64-darwin/c/pthread.cr @@ -25,4 +25,5 @@ lib LibC fun pthread_mutex_trylock(x0 : PthreadMutexT*) : Int fun pthread_mutex_unlock(x0 : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(Char*) : Int end diff --git a/src/lib_c/x86_64-dragonfly/c/pthread.cr b/src/lib_c/x86_64-dragonfly/c/pthread.cr index 87ae8c05c358..90bf0c6285a0 100644 --- a/src/lib_c/x86_64-dragonfly/c/pthread.cr +++ b/src/lib_c/x86_64-dragonfly/c/pthread.cr @@ -29,4 +29,5 @@ lib LibC fun pthread_mutex_trylock(x0 : PthreadMutexT*) : Int fun pthread_mutex_unlock(x0 : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(PthreadT, Char*) : Int end diff --git a/src/lib_c/x86_64-freebsd/c/pthread.cr b/src/lib_c/x86_64-freebsd/c/pthread.cr index 87ae8c05c358..9cc78c2f2850 100644 --- a/src/lib_c/x86_64-freebsd/c/pthread.cr +++ b/src/lib_c/x86_64-freebsd/c/pthread.cr @@ -29,4 +29,5 @@ lib LibC fun pthread_mutex_trylock(x0 : PthreadMutexT*) : Int fun pthread_mutex_unlock(x0 : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_set_name_np(PthreadT, Char*) end diff --git a/src/lib_c/x86_64-linux-gnu/c/pthread.cr b/src/lib_c/x86_64-linux-gnu/c/pthread.cr index ab943b23587d..33274a6cf51d 100644 --- a/src/lib_c/x86_64-linux-gnu/c/pthread.cr +++ b/src/lib_c/x86_64-linux-gnu/c/pthread.cr @@ -35,4 +35,5 @@ lib LibC fun pthread_mutex_trylock(mutex : PthreadMutexT*) : Int fun pthread_mutex_unlock(mutex : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(PthreadT, Char*) : Int end diff --git a/src/lib_c/x86_64-linux-musl/c/pthread.cr b/src/lib_c/x86_64-linux-musl/c/pthread.cr index c318bb5f4357..6ee1a20d90a6 100644 --- a/src/lib_c/x86_64-linux-musl/c/pthread.cr +++ b/src/lib_c/x86_64-linux-musl/c/pthread.cr @@ -27,4 +27,5 @@ lib LibC fun pthread_mutex_trylock(x0 : PthreadMutexT*) : Int fun pthread_mutex_unlock(x0 : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(PthreadT, Char*) : Int end diff --git a/src/lib_c/x86_64-netbsd/c/pthread.cr b/src/lib_c/x86_64-netbsd/c/pthread.cr index 133d4922c57f..e0f477018777 100644 --- a/src/lib_c/x86_64-netbsd/c/pthread.cr +++ b/src/lib_c/x86_64-netbsd/c/pthread.cr @@ -35,5 +35,6 @@ lib LibC fun pthread_mutex_trylock(x0 : PthreadMutexT*) : Int fun pthread_mutex_unlock(x0 : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_setname_np(PthreadT, Char*, Void*) : Int fun pthread_setspecific(PthreadKeyT, Void*) : Int end diff --git a/src/lib_c/x86_64-openbsd/c/pthread.cr b/src/lib_c/x86_64-openbsd/c/pthread.cr index 788823c40a31..15773336f239 100644 --- a/src/lib_c/x86_64-openbsd/c/pthread.cr +++ b/src/lib_c/x86_64-openbsd/c/pthread.cr @@ -30,6 +30,7 @@ lib LibC fun pthread_mutex_trylock(x0 : PthreadMutexT*) : Int fun pthread_mutex_unlock(x0 : PthreadMutexT*) : Int fun pthread_self : PthreadT + fun pthread_set_name_np(PthreadT, Char*) fun pthread_setspecific(PthreadKeyT, Void*) : Int fun pthread_stackseg_np(PthreadT, StackT*) : Int end diff --git a/src/lib_c/x86_64-windows-msvc/c/processthreadsapi.cr b/src/lib_c/x86_64-windows-msvc/c/processthreadsapi.cr index 9c22d4530c81..efa684075162 100644 --- a/src/lib_c/x86_64-windows-msvc/c/processthreadsapi.cr +++ b/src/lib_c/x86_64-windows-msvc/c/processthreadsapi.cr @@ -50,6 +50,9 @@ lib LibC bInheritHandles : BOOL, dwCreationFlags : DWORD, lpEnvironment : Void*, lpCurrentDirectory : LPWSTR, lpStartupInfo : STARTUPINFOW*, lpProcessInformation : PROCESS_INFORMATION*) : BOOL + {% if LibC::WIN32_WINNT >= LibC::WIN32_WINNT_WIN10 %} + fun SetThreadDescription(hThread : HANDLE, lpThreadDescription : LPWSTR) : LONG + {% end %} fun SetThreadStackGuarantee(stackSizeInBytes : DWORD*) : BOOL fun GetProcessTimes(hProcess : HANDLE, lpCreationTime : FILETIME*, lpExitTime : FILETIME*, lpKernelTime : FILETIME*, lpUserTime : FILETIME*) : BOOL From e6d4998b5580456e3b9ecbffb40395f2699f3d69 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Wed, 31 Jan 2024 03:13:16 +0800 Subject: [PATCH 086/105] Add `ReferenceStorage` for manual allocation of references (#14270) --- .../semantic/reference_storage_spec.cr | 72 +++++++++++++++++++ spec/primitives/reference_spec.cr | 4 +- src/compiler/crystal/codegen/llvm_typer.cr | 4 ++ .../crystal/semantic/top_level_visitor.cr | 70 +++++++++++++++--- src/compiler/crystal/types.cr | 29 +++++++- src/prelude.cr | 1 + src/reference_storage.cr | 55 ++++++++++++++ 7 files changed, 221 insertions(+), 14 deletions(-) create mode 100644 spec/compiler/semantic/reference_storage_spec.cr create mode 100644 src/reference_storage.cr diff --git a/spec/compiler/semantic/reference_storage_spec.cr b/spec/compiler/semantic/reference_storage_spec.cr new file mode 100644 index 000000000000..a0c0f2343260 --- /dev/null +++ b/spec/compiler/semantic/reference_storage_spec.cr @@ -0,0 +1,72 @@ +require "../../spec_helper" + +describe "Semantic: ReferenceStorage" do + it "errors if T is a struct type" do + assert_error <<-CRYSTAL, "Can't instantiate ReferenceStorage(T) with T = Foo (T must be a reference type)" + @[Primitive(:ReferenceStorageType)] + struct ReferenceStorage(T) < Value + end + + struct Foo + @x = 1 + end + + ReferenceStorage(Foo) + CRYSTAL + end + + it "errors if T is a value type" do + assert_error <<-CRYSTAL, "Can't instantiate ReferenceStorage(T) with T = Int32 (T must be a reference type)" + @[Primitive(:ReferenceStorageType)] + struct ReferenceStorage(T) < Value + end + + ReferenceStorage(Int32) + CRYSTAL + end + + it "errors if T is a union type" do + assert_error <<-CRYSTAL, "Can't instantiate ReferenceStorage(T) with T = (Bar | Foo) (T must be a reference type)" + @[Primitive(:ReferenceStorageType)] + struct ReferenceStorage(T) < Value + end + + class Foo + end + + class Bar + end + + ReferenceStorage(Foo | Bar) + CRYSTAL + end + + it "errors if T is a nilable type" do + assert_error <<-CRYSTAL, "Can't instantiate ReferenceStorage(T) with T = (Foo | Nil) (T must be a reference type)" + @[Primitive(:ReferenceStorageType)] + struct ReferenceStorage(T) < Value + end + + class Foo + end + + ReferenceStorage(Foo?) + CRYSTAL + end + + it "allows a different name" do + assert_type(<<-CRYSTAL) { types["Foo"].metaclass } + @[Primitive(:ReferenceStorageType)] + struct MyRef(U) < Value + def u + U + end + end + + class Foo + end + + MyRef(Foo).new.u + CRYSTAL + end +end diff --git a/spec/primitives/reference_spec.cr b/spec/primitives/reference_spec.cr index b73553748b65..52f179296ee8 100644 --- a/spec/primitives/reference_spec.cr +++ b/spec/primitives/reference_spec.cr @@ -43,9 +43,7 @@ describe "Primitives: reference" do end it "works when address is on the stack" do - # suitably aligned, sufficient storage for type ID + i64 + ptr - # TODO: use `ReferenceStorage` instead - foo_buffer = uninitialized UInt64[3] + foo_buffer = uninitialized ReferenceStorage(Foo) foo = Foo.pre_initialize(pointerof(foo_buffer)) pointerof(foo_buffer).as(typeof(Foo.crystal_instance_type_id)*).value.should eq(Foo.crystal_instance_type_id) foo.str.should eq("abc") diff --git a/src/compiler/crystal/codegen/llvm_typer.cr b/src/compiler/crystal/codegen/llvm_typer.cr index d20fbd59fa9a..d72a25ecd3cb 100644 --- a/src/compiler/crystal/codegen/llvm_typer.cr +++ b/src/compiler/crystal/codegen/llvm_typer.cr @@ -245,6 +245,10 @@ module Crystal llvm_type(type.remove_alias, wants_size) end + private def create_llvm_type(type : ReferenceStorageType, wants_size) + llvm_struct_type(type.reference_type, wants_size) + end + private def create_llvm_type(type : NonGenericModuleType | GenericClassType, wants_size) # This can only be reached if the module or generic class don't have implementors @llvm_context.int1 diff --git a/src/compiler/crystal/semantic/top_level_visitor.cr b/src/compiler/crystal/semantic/top_level_visitor.cr index 9b7eedb2a876..98ceb23df6b3 100644 --- a/src/compiler/crystal/semantic/top_level_visitor.cr +++ b/src/compiler/crystal/semantic/top_level_visitor.cr @@ -41,6 +41,11 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor @last_doc : String? + # special types recognized for `@[Primitive]` + private enum PrimitiveType + ReferenceStorageType + end + def visit(node : ClassDef) check_outside_exp node, "declare class" @@ -48,6 +53,27 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor annotations = read_annotations + special_type = nil + process_annotations(annotations) do |annotation_type, ann| + case annotation_type + when @program.primitive_annotation + if ann.args.size != 1 + ann.raise "expected Primitive annotation to have one argument" + end + + arg = ann.args.first + unless arg.is_a?(SymbolLiteral) + arg.raise "expected Primitive argument to be a symbol literal" + end + + value = arg.value + special_type = PrimitiveType.parse?(value) + unless special_type + arg.raise "BUG: Unknown primitive type #{value.inspect}" + end + end + end + created_new_type = false if type @@ -70,14 +96,34 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor end else created_new_type = true - if type_vars = node.type_vars - type = GenericClassType.new @program, scope, name, nil, type_vars, false - type.splat_index = node.splat_index - else - type = NonGenericClassType.new @program, scope, name, nil, false + case special_type + in Nil + if type_vars = node.type_vars + type = GenericClassType.new @program, scope, name, nil, type_vars, false + type.splat_index = node.splat_index + else + type = NonGenericClassType.new @program, scope, name, nil, false + end + type.abstract = node.abstract? + type.struct = node.struct? + in .reference_storage_type? + type_vars = node.type_vars + case + when !node.struct? + node.raise "BUG: Expected ReferenceStorageType to be a struct type" + when node.abstract? + node.raise "BUG: Expected ReferenceStorageType to be a non-abstract type" + when !type_vars + node.raise "BUG: Expected ReferenceStorageType to be a generic type" + when type_vars.size != 1 + node.raise "BUG: Expected ReferenceStorageType to have a single generic type parameter" + when node.splat_index + node.raise "BUG: Expected ReferenceStorageType to have no splat parameter" + end + type = GenericReferenceStorageType.new @program, scope, name, @program.value, type_vars + type.declare_instance_var("@type_id", @program.int32) + type.can_be_stored = false end - type.abstract = node.abstract? - type.struct = node.struct? end type.private = true if node.visibility.private? @@ -133,6 +179,10 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor if superclass.struct? && !superclass.abstract? node.raise "can't extend non-abstract struct #{superclass}" end + + if type.is_a?(GenericReferenceStorageType) && superclass != @program.value + node.raise "BUG: Expected reference_storage_type to inherit from Value" + end end if created_new_type @@ -375,7 +425,7 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor process_def_annotations(node, annotations) do |annotation_type, ann| if annotation_type == @program.primitive_annotation - process_primitive_annotation(node, ann) + process_def_primitive_annotation(node, ann) end node.add_annotation(annotation_type, ann) @@ -460,7 +510,7 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor false end - private def process_primitive_annotation(node, ann) + private def process_def_primitive_annotation(node, ann) if ann.args.size != 1 ann.raise "expected Primitive annotation to have one argument" end @@ -926,7 +976,7 @@ class Crystal::TopLevelVisitor < Crystal::SemanticVisitor if annotation_type == @program.call_convention_annotation call_convention = parse_call_convention(ann, call_convention) elsif annotation_type == @program.primitive_annotation - process_primitive_annotation(external, ann) + process_def_primitive_annotation(external, ann) else ann.raise "funs can only be annotated with: NoInline, AlwaysInline, Naked, ReturnsTwice, Raises, CallConvention" end diff --git a/src/compiler/crystal/types.cr b/src/compiler/crystal/types.cr index ad9f3d391fa6..5d903b763050 100644 --- a/src/compiler/crystal/types.cr +++ b/src/compiler/crystal/types.cr @@ -555,7 +555,7 @@ module Crystal program.tuple, program.named_tuple, program.pointer, program.static_array, program.union, program.enum, program.proc, - PrimitiveType + PrimitiveType, GenericReferenceStorageType false else true @@ -2642,6 +2642,33 @@ module Crystal end end + # The non-instantiated ReferenceStorage(T) type. + class GenericReferenceStorageType < GenericClassType + @struct = true + + def new_generic_instance(program, generic_type, type_vars) + type_param = self.type_vars.first + t = type_vars[type_param].type + + unless t.is_a?(TypeParameter) || (t.class? && !t.struct?) + raise TypeException.new "Can't instantiate ReferenceStorage(#{type_param}) with #{type_param} = #{t} (#{type_param} must be a reference type)" + end + + ReferenceStorageType.new program, t, self, type_param + end + end + + class ReferenceStorageType < GenericClassInstanceType + getter reference_type : Type + + def initialize(program, @reference_type, generic_type, type_param) + t_var = Var.new("T", @reference_type) + t_var.bind_to t_var + + super(program, generic_type, program.value, {type_param => t_var} of String => ASTNode) + end + end + # A lib type, like `lib LibC`. class LibType < ModuleType getter link_annotations : Array(LinkAnnotation)? diff --git a/src/prelude.cr b/src/prelude.cr index f06f5bc87015..f84bb86cb3c1 100644 --- a/src/prelude.cr +++ b/src/prelude.cr @@ -65,6 +65,7 @@ require "raise" require "random" require "range" require "reference" +require "reference_storage" require "regex" require "set" {% unless flag?(:wasm32) %} diff --git a/src/reference_storage.cr b/src/reference_storage.cr new file mode 100644 index 000000000000..2ca3edc171aa --- /dev/null +++ b/src/reference_storage.cr @@ -0,0 +1,55 @@ +# `ReferenceStorage(T)` provides the minimum storage for the instance data of +# an object of type `T`. The compiler guarantees that +# `sizeof(ReferenceStorage(T)) == instance_sizeof(T)` and +# `alignof(ReferenceStorage(T)) == instance_alignof(T)` always hold, which means +# `Pointer(ReferenceStorage(T))` and `T` are binary-compatible. +# +# `T` must be a non-union reference type. +# +# WARNING: `ReferenceStorage` is only necessary for manual memory management, +# such as creating instances of `T` with a non-default allocator. Therefore, +# this type is unsafe and no public constructors are defined. +# +# WARNING: `ReferenceStorage` is unsuitable when instances of `T` require more +# than `instance_sizeof(T)` bytes, such as `String` and `Log::Metadata`. +@[Experimental("This type's API is still under development. Join the discussion about custom reference allocation at [#13481](https://github.com/crystal-lang/crystal/issues/13481).")] +@[Primitive(:ReferenceStorageType)] +struct ReferenceStorage(T) < Value + private def initialize + end + + # Returns whether `self` and *other* are bytewise equal. + # + # NOTE: This does not call `T#==`, so it works even if `self` or *other* does + # not represent a valid instance of `T`. If validity is guaranteed, call + # `to_reference == other.to_reference` instead to use `T#==`. + def ==(other : ReferenceStorage(T)) : Bool + to_bytes == other.to_bytes + end + + def ==(other) : Bool + false + end + + def hash(hasher) + to_bytes.hash(hasher) + end + + def to_s(io : IO) : Nil + io << "ReferenceStorage(#<" << T << ":0x" + pointerof(@type_id).address.to_s(io, 16) + io << ">)" + end + + # Returns a `T` whose instance data refers to `self`. + # + # WARNING: The caller is responsible for ensuring that the instance data is + # correctly initialized and outlives the returned `T`. + def to_reference : T + pointerof(@type_id).as(T) + end + + protected def to_bytes + Slice.new(pointerof(@type_id).as(UInt8*), instance_sizeof(T)) + end +end From 9890b17d97a46522c825edb8651607f6f53fd108 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Wed, 31 Jan 2024 03:13:31 +0800 Subject: [PATCH 087/105] Fix end locations of `Alias` nodes (#14271) --- spec/compiler/parser/parser_spec.cr | 1 + src/compiler/crystal/syntax/parser.cr | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/spec/compiler/parser/parser_spec.cr b/spec/compiler/parser/parser_spec.cr index 9f4ec5faccf7..c9a28d87c33f 100644 --- a/spec/compiler/parser/parser_spec.cr +++ b/spec/compiler/parser/parser_spec.cr @@ -2252,6 +2252,7 @@ module Crystal assert_end_location "class Foo; end" assert_end_location "struct Foo; end" assert_end_location "module Foo; end" + assert_end_location "alias Foo = Bar" assert_end_location "->{ }" assert_end_location "macro foo;end" assert_end_location "macro foo; 123; end" diff --git a/src/compiler/crystal/syntax/parser.cr b/src/compiler/crystal/syntax/parser.cr index e3f4c2605ed6..16a45eaf5e22 100644 --- a/src/compiler/crystal/syntax/parser.cr +++ b/src/compiler/crystal/syntax/parser.cr @@ -5854,9 +5854,10 @@ module Crystal next_token_skip_space_or_newline value = parse_bare_proc_type + end_location = value.end_location skip_space - alias_node = Alias.new(name, value) + alias_node = Alias.new(name, value).at_end(end_location) alias_node.doc = doc alias_node end From 14f69e38cadf06ff5594b562d22d3b38689c3d4d Mon Sep 17 00:00:00 2001 From: Julien Portalier <julien@portalier.com> Date: Wed, 31 Jan 2024 12:42:24 +0100 Subject: [PATCH 088/105] Interpreter: fix fiber's resumable property (#14252) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sijawusz Pur Rahnama <sija@sija.pl> Co-authored-by: Johannes Müller <straightshoota@gmail.com> --- spec/interpreter_std_spec.cr | 1 + spec/std/fiber_spec.cr | 21 +++++++++++++++++++ .../crystal/interpreter/instructions.cr | 5 +++++ .../crystal/interpreter/interpreter.cr | 11 ++++++++-- .../crystal/interpreter/primitives.cr | 3 +++ src/crystal/interpreter.cr | 5 +++++ src/crystal/scheduler.cr | 8 ------- src/fiber/context.cr | 20 ++++++++++++++++-- src/fiber/context/interpreted.cr | 4 ++-- 9 files changed, 64 insertions(+), 14 deletions(-) create mode 100644 spec/std/fiber_spec.cr diff --git a/spec/interpreter_std_spec.cr b/spec/interpreter_std_spec.cr index 3cdcc55cbd61..8638b0a83f7f 100644 --- a/spec/interpreter_std_spec.cr +++ b/spec/interpreter_std_spec.cr @@ -72,6 +72,7 @@ require "./std/env_spec.cr" require "./std/errno_spec.cr" # require "./std/exception/call_stack_spec.cr" (failed to run) # require "./std/exception_spec.cr" (failed to run) +require "./std/fiber_spec.cr" require "./std/file_spec.cr" require "./std/file/tempfile_spec.cr" require "./std/file_utils_spec.cr" diff --git a/spec/std/fiber_spec.cr b/spec/std/fiber_spec.cr new file mode 100644 index 000000000000..5c85d1a7475d --- /dev/null +++ b/spec/std/fiber_spec.cr @@ -0,0 +1,21 @@ +require "spec" + +describe Fiber do + it "#resumable?" do + done = false + resumable = nil + + fiber = spawn do + resumable = Fiber.current.resumable? + done = true + end + + fiber.resumable?.should be_true + + until done + Fiber.yield + end + + resumable.should be_false + end +end diff --git a/src/compiler/crystal/interpreter/instructions.cr b/src/compiler/crystal/interpreter/instructions.cr index 67966277bf15..f2b8abcb9a51 100644 --- a/src/compiler/crystal/interpreter/instructions.cr +++ b/src/compiler/crystal/interpreter/instructions.cr @@ -1649,6 +1649,11 @@ require "./repl" pop_values: [current_context : Void*, new_context : Void*], code: swapcontext(current_context, new_context), }, + interpreter_fiber_resumable: { + pop_values: [context : Void*], + push: true, + code: fiber_resumable(context), + }, {% if flag?(:bits64) %} interpreter_intrinsics_memcpy: { diff --git a/src/compiler/crystal/interpreter/interpreter.cr b/src/compiler/crystal/interpreter/interpreter.cr index 608fb6d85d1a..eca73ecae6bc 100644 --- a/src/compiler/crystal/interpreter/interpreter.cr +++ b/src/compiler/crystal/interpreter/interpreter.cr @@ -1154,6 +1154,7 @@ class Crystal::Repl::Interpreter nil end end + spawned_fiber.@context.resumable = 1 spawned_fiber.as(Void*) end @@ -1161,11 +1162,17 @@ class Crystal::Repl::Interpreter # current_fiber = current_context.as(Fiber*).value new_fiber = new_context.as(Fiber*).value - # We directly resume the next fiber. - # TODO: is this okay? We totally ignore the scheduler here! + # delegates the context switch to the interpreter's scheduler, so we update + # the current fiber reference, set the GC stack bottom, and so on (aka + # there's more to switching context than `Fiber.swapcontext`): new_fiber.resume end + private def fiber_resumable(context : Void*) : LibC::Long + fiber = context.as(Fiber*).value + fiber.@context.resumable + end + private def pry(ip, instructions, stack_bottom, stack) offset = (ip - instructions.instructions.to_unsafe).to_i32 node = instructions.nodes[offset]? diff --git a/src/compiler/crystal/interpreter/primitives.cr b/src/compiler/crystal/interpreter/primitives.cr index 1d50568c5d62..968361fb6c1d 100644 --- a/src/compiler/crystal/interpreter/primitives.cr +++ b/src/compiler/crystal/interpreter/primitives.cr @@ -402,6 +402,9 @@ class Crystal::Repl::Compiler when "interpreter_fiber_swapcontext" accept_call_args(node) interpreter_fiber_swapcontext(node: node) + when "interpreter_fiber_resumable" + accept_call_args(node) + interpreter_fiber_resumable(node: node) when "interpreter_intrinsics_memcpy" accept_call_args(node) interpreter_intrinsics_memcpy(node: node) diff --git a/src/crystal/interpreter.cr b/src/crystal/interpreter.cr index 2a9a6b23c5f8..d3b3589d50cb 100644 --- a/src/crystal/interpreter.cr +++ b/src/crystal/interpreter.cr @@ -19,5 +19,10 @@ module Crystal @[Primitive(:interpreter_spawn)] def self.spawn(fiber : Fiber, fiber_main : Void*) : Void* end + + # Returns the resumable value from the interpreter's fiber. + @[Primitive(:interpreter_fiber_resumable)] + def self.fiber_resumable(context) : LibC::Long + end end end diff --git a/src/crystal/scheduler.cr b/src/crystal/scheduler.cr index 101a287d23bb..1728a9b7f335 100644 --- a/src/crystal/scheduler.cr +++ b/src/crystal/scheduler.cr @@ -125,14 +125,6 @@ class Crystal::Scheduler {% end %} current, @current = @current, fiber - - {% if flag?(:interpreted) %} - # TODO: ideally we could set this in the interpreter if the - # @context had a pointer back to the fiber. - # I also wonder why this isn't done always like that instead of in asm. - current.@context.resumable = 1 - {% end %} - Fiber.swapcontext(pointerof(current.@context), pointerof(fiber.@context)) {% if flag?(:preview_mt) %} diff --git a/src/fiber/context.cr b/src/fiber/context.cr index 28b54458fe66..eab06d886de6 100644 --- a/src/fiber/context.cr +++ b/src/fiber/context.cr @@ -7,10 +7,26 @@ class Fiber @[Extern] struct Context property stack_top : Void* - property resumable : LibC::Long + + {% if flag?(:interpreted) %} + # In interpreted mode, the interpreted fibers will be backed by a real + # fiber run by the interpreter. The fiber context is thus fake. + # + # The `stack_top` property is actually a pointer to the real Fiber + # running in the interpreter. + # + # The `resumable` property is also delegated to the real fiber. Only the + # getter is defined (so we know the real state of the fiber); we don't + # declare a setter because only the interpreter can manipulate it (in the + # `makecontext` and `swapcontext` primitives). + def resumable : LibC::Long + Crystal::Interpreter.fiber_resumable(pointerof(@stack_top)) + end + {% else %} + property resumable : LibC::Long = 0 + {% end %} def initialize(@stack_top = Pointer(Void).null) - @resumable = 0 end end diff --git a/src/fiber/context/interpreted.cr b/src/fiber/context/interpreted.cr index 55b9354a1a57..900ad6f3111c 100644 --- a/src/fiber/context/interpreted.cr +++ b/src/fiber/context/interpreted.cr @@ -5,9 +5,9 @@ require "crystal/interpreter" class Fiber # :nodoc: def makecontext(stack_ptr, fiber_main) : Nil - # In interpreted mode the stack_top variable actually points to a fiber + # In interpreted mode the stack_top variable actually points to the actual + # fiber running on the interpreter @context.stack_top = Crystal::Interpreter.spawn(self, fiber_main.pointer) - @context.resumable = 1 end # :nodoc: From 202c655008e9b191aca30701ef678e54503ef1b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Wed, 31 Jan 2024 13:20:49 +0100 Subject: [PATCH 089/105] Add `crystal tool flags` (#14234) --- etc/completion.bash | 2 +- etc/completion.fish | 4 +- etc/completion.zsh | 7 ++ man/crystal.1 | 4 +- spec/compiler/crystal/tools/flags_spec.cr | 44 +++++++++ src/compiler/crystal/command.cr | 4 + src/compiler/crystal/tools/flags.cr | 104 ++++++++++++++++++++++ 7 files changed, 166 insertions(+), 3 deletions(-) create mode 100644 spec/compiler/crystal/tools/flags_spec.cr create mode 100644 src/compiler/crystal/tools/flags.cr diff --git a/etc/completion.bash b/etc/completion.bash index d8731c65bff7..9263289b5b4e 100644 --- a/etc/completion.bash +++ b/etc/completion.bash @@ -66,7 +66,7 @@ _crystal() _crystal_compgen_options "${opts}" "${cur}" else if [[ "${prev}" == "tool" ]] ; then - local subcommands="context dependencies format hierarchy implementations types" + local subcommands="context dependencies flags format hierarchy implementations types" _crystal_compgen_options "${subcommands}" "${cur}" else _crystal_compgen_sources "${cur}" diff --git a/etc/completion.fish b/etc/completion.fish index 150dd37108d8..64fc6a97b45a 100644 --- a/etc/completion.fish +++ b/etc/completion.fish @@ -1,5 +1,5 @@ set -l crystal_commands init build clear_cache docs env eval i interactive play run spec tool help version -set -l tool_subcommands context expand format hierarchy implementations types +set -l tool_subcommands context expand flags format hierarchy implementations types complete -c crystal -s h -l help -d "Show help" -x @@ -173,6 +173,8 @@ complete -c crystal -n "__fish_seen_subcommand_from expand" -s p -l progress -d complete -c crystal -n "__fish_seen_subcommand_from expand" -s t -l time -d "Enable execution time output" complete -c crystal -n "__fish_seen_subcommand_from expand" -l stdin-filename -d "Source file name to be read from STDIN" +complete -c crystal -n "__fish_seen_subcommand_from tool; and not __fish_seen_subcommand_from $tool_subcommands" -a "flags" -d "print all macro 'flag?' values" -x + complete -c crystal -n "__fish_seen_subcommand_from tool; and not __fish_seen_subcommand_from $tool_subcommands" -a "format" -d "format project, directories and/or files" -x complete -c crystal -n "__fish_seen_subcommand_from format" -l check -d "Checks that formatting code produces no changes" complete -c crystal -n "__fish_seen_subcommand_from format" -s i -l include -d "Include path" diff --git a/etc/completion.zsh b/etc/completion.zsh index bf57d80208df..ffa12798ca18 100644 --- a/etc/completion.zsh +++ b/etc/completion.zsh @@ -165,6 +165,7 @@ _crystal-tool() { "context:show context for given location" "dependencies:show tree of required source files" "expand:show macro expansion for given location" + "flags:print all macro 'flag?' values" "format:format project, directories and/or files" "hierarchy:show type hierarchy" "implementations:show implementations for given call in location" @@ -211,6 +212,12 @@ _crystal-tool() { $cursor_args ;; + (flags) + _arguments \ + $programfile \ + $help_args + ;; + (format) _arguments \ $programfile \ diff --git a/man/crystal.1 b/man/crystal.1 index ef23beac77c3..15fed461c26c 100644 --- a/man/crystal.1 +++ b/man/crystal.1 @@ -369,7 +369,7 @@ Disable colored output. .Op -- .Op arguments .Pp -Run a tool. The available tools are: context, dependencies, format, hierarchy, implementations, and types. +Run a tool. The available tools are: context, dependencies, flags, format, hierarchy, implementations, and types. .Pp Tools: .Bl -tag -offset indent @@ -398,6 +398,8 @@ Show skipped and heads of filtered paths .El .It Cm expand Show macro expansion for given location. +.It Cm flags +Print all macro 'flag?' values .It Cm format Format project, directories and/or files with the coding style used in the standard library. You can use the .Fl -check diff --git a/spec/compiler/crystal/tools/flags_spec.cr b/spec/compiler/crystal/tools/flags_spec.cr new file mode 100644 index 000000000000..c295439e0547 --- /dev/null +++ b/spec/compiler/crystal/tools/flags_spec.cr @@ -0,0 +1,44 @@ +require "../../../spec_helper" +include Crystal + +private def parse_flags(source) + Crystal::Command::FlagsVisitor.new.tap do |visitor| + Parser.parse(source).accept(visitor) + end +end + +describe Crystal::Command::FlagsVisitor do + it "different flags" do + visitor = parse_flags <<-CRYSTAL + {% + flag?(:foo) + flag?("bar") + flag?(1) + flag?(true) + %} + CRYSTAL + visitor.flag_names.should eq %w[1 bar foo true] + end + + it "unique flags" do + visitor = parse_flags <<-CRYSTAL + {% + flag?(:foo) + flag?("foo") + flag?(:foo) + %} + CRYSTAL + visitor.flag_names.should eq %w[foo] + end + + it "only macro" do + visitor = parse_flags <<-CRYSTAL + flag?(:flag) + f.flag?(:foo) + F.flag?(:bar) + {% f.flag?(:baz) %} + {% f.flag?(:qux, other: true) %} + CRYSTAL + visitor.flag_names.should eq %w[] + end +end diff --git a/src/compiler/crystal/command.cr b/src/compiler/crystal/command.cr index 18def74ebbd0..178a307a54b8 100644 --- a/src/compiler/crystal/command.cr +++ b/src/compiler/crystal/command.cr @@ -41,6 +41,7 @@ class Crystal::Command Tool: context show context for given location expand show macro expansion for given location + flags print all macro `flag?` values format format project, directories and/or files hierarchy show type hierarchy dependencies show file dependency tree @@ -177,6 +178,9 @@ class Crystal::Command when "format".starts_with?(tool) options.shift format + when "flags" == tool + options.shift + flags when "expand".starts_with?(tool) options.shift expand diff --git a/src/compiler/crystal/tools/flags.cr b/src/compiler/crystal/tools/flags.cr new file mode 100644 index 000000000000..17bb15007021 --- /dev/null +++ b/src/compiler/crystal/tools/flags.cr @@ -0,0 +1,104 @@ +require "colorize" +require "../syntax/ast" + +class Crystal::Command + private def flags + OptionParser.parse(@options) do |opts| + opts.banner = "Usage: crystal tool flags [path...]\n\nOptions:" + + opts.on("-h", "--help", "Show this message") do + puts opts + exit + end + + opts.on("--no-color", "Disable colored output") do + @color = false + end + end + + visitor = FlagsVisitor.new + find_sources(options) do |source| + Parser.parse(source.code).accept(visitor) + end + visitor.flag_names.each do |flag| + puts flag + end + end + + def find_sources( + paths : Array(String), + stdin : IO = STDIN, + & : Compiler::Source -> + ) : Nil + stdin_content = nil + paths.each do |path| + if path == "-" + stdin_content ||= stdin.gets_to_end + yield Compiler::Source.new(path, stdin_content) + elsif File.file?(path) + yield Compiler::Source.new(path, File.read(path)) + elsif Dir.exists?(path) + Dir.glob(::Path[path].to_posix.join("**/*.cr")) do |dir_path| + if File.file?(dir_path) + yield Compiler::Source.new(path, File.read(dir_path)) + end + end + else + Crystal.error "file or directory does not exist: #{path}", @color, leading_error: false + end + end + end + + class FlagsVisitor < Visitor + @in_macro_expression = false + + getter all_flags = [] of ASTNode + + def initialize(@flag_name : String = "flag?") + end + + def flag_names + all_flags.map { |flag| string_flag(flag) }.uniq!.sort! + end + + private def string_flag(node) + case node + when StringLiteral, SymbolLiteral + node.value + else + node.to_s + end + end + + def visit(node) + true + end + + def visit(node : Crystal::MacroExpression | Crystal::MacroIf | Crystal::MacroFor) + @in_macro_expression = true + + true + end + + def end_visit(node : Crystal::MacroExpression | Crystal::MacroIf | Crystal::MacroFor) + @in_macro_expression = false + end + + def visit(node : Crystal::Call) + check_call(node) + true + end + + private def check_call(node) + return unless @in_macro_expression + return unless node.name == @flag_name + return unless node.obj.nil? && node.block.nil? && node.named_args.nil? + + args = node.args + return unless args.size == 1 + arg = args[0] + + all_flags << arg + end + end +end From 2f48d297feb527b1a29a3108d05da98f33a5a434 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Wed, 31 Jan 2024 21:04:09 +0100 Subject: [PATCH 090/105] Document builtin constants (#14276) --- src/compiler/crystal/program.cr | 91 ++++++++++++++++++++++++--------- 1 file changed, 66 insertions(+), 25 deletions(-) diff --git a/src/compiler/crystal/program.cr b/src/compiler/crystal/program.cr index 936fc6a0a270..675202ee0144 100644 --- a/src/compiler/crystal/program.cr +++ b/src/compiler/crystal/program.cr @@ -275,36 +275,77 @@ module Crystal # Defines a predefined constant in the Crystal module, such as BUILD_DATE and VERSION. private def define_crystal_constants if build_commit = Crystal::Config.build_commit - define_crystal_string_constant "BUILD_COMMIT", build_commit + build_commit_const = define_crystal_string_constant "BUILD_COMMIT", build_commit else - define_crystal_nil_constant "BUILD_COMMIT" + build_commit_const = define_crystal_nil_constant "BUILD_COMMIT" end - - define_crystal_string_constant "BUILD_DATE", Crystal::Config.date - define_crystal_string_constant "CACHE_DIR", CacheDir.instance.dir - define_crystal_string_constant "DEFAULT_PATH", Crystal::Config.path - define_crystal_string_constant "DESCRIPTION", Crystal::Config.description - define_crystal_string_constant "PATH", Crystal::CrystalPath.default_path - define_crystal_string_constant "LIBRARY_PATH", Crystal::CrystalLibraryPath.default_path - define_crystal_string_constant "LIBRARY_RPATH", Crystal::CrystalLibraryPath.default_rpath - define_crystal_string_constant "VERSION", Crystal::Config.version - define_crystal_string_constant "LLVM_VERSION", Crystal::Config.llvm_version - define_crystal_string_constant "HOST_TRIPLE", Crystal::Config.host_target.to_s - define_crystal_string_constant "TARGET_TRIPLE", Crystal::Config.host_target.to_s - end - - private def define_crystal_string_constant(name, value) - define_crystal_constant name, StringLiteral.new(value).tap(&.set_type(string)) - end - - private def define_crystal_nil_constant(name) - define_crystal_constant name, NilLiteral.new.tap(&.set_type(self.nil)) - end - - private def define_crystal_constant(name, value) + build_commit_const.doc = <<-MD if wants_doc? + The build commit identifier of the Crystal compiler. + MD + + define_crystal_string_constant "BUILD_DATE", Crystal::Config.date, <<-MD + The build date of the Crystal compiler. + MD + define_crystal_string_constant "CACHE_DIR", CacheDir.instance.dir, <<-MD + The cache directory configured for the Crystal compiler. + + The value is defined by the environment variable `CRYSTAL_CACHE_DIR` and + defaults to the user's configured cache directory. + MD + define_crystal_string_constant "DEFAULT_PATH", Crystal::Config.path, <<-MD + The default Crystal path configured in the compiler. This value is baked + into the compiler and usually points to the accompanying version of the + standard library. + MD + define_crystal_string_constant "DESCRIPTION", Crystal::Config.description, <<-MD + Full version information of the Crystal compiler. Equivalent to `crystal --version`. + MD + define_crystal_string_constant "PATH", Crystal::CrystalPath.default_path, <<-MD + Colon-separated paths where the compiler searches for required source files. + + The value is defined by the environment variable `CRYSTAL_PATH` + and defaults to `DEFAULT_PATH`. + MD + define_crystal_string_constant "LIBRARY_PATH", Crystal::CrystalLibraryPath.default_path, <<-MD + Colon-separated paths where the compiler searches for (binary) libraries. + + The value is defined by the environment variables `CRYSTAL_LIBRARY_PATH`. + MD + define_crystal_string_constant "LIBRARY_RPATH", Crystal::CrystalLibraryPath.default_rpath, <<-MD + Colon-separated paths where the loader searches for dynamic libraries at runtime. + + The value is defined by the environment variables `CRYSTAL_LIBRARY_RPATH`. + MD + define_crystal_string_constant "VERSION", Crystal::Config.version, <<-MD + The version of the Crystal compiler. + MD + define_crystal_string_constant "LLVM_VERSION", Crystal::Config.llvm_version, <<-MD + The version of LLVM used by the Crystal compiler. + MD + define_crystal_string_constant "HOST_TRIPLE", Crystal::Config.host_target.to_s, <<-MD + The LLVM target triple of the host system (the machine that the compiler runs on). + MD + define_crystal_string_constant "TARGET_TRIPLE", Crystal::Config.host_target.to_s, <<-MD + The LLVM target triple of the target system (the machine that the compiler builds for). + MD + end + + private def define_crystal_string_constant(name, value, doc = nil) + define_crystal_constant name, StringLiteral.new(value).tap(&.set_type(string)), doc + end + + private def define_crystal_nil_constant(name, doc = nil) + define_crystal_constant name, NilLiteral.new.tap(&.set_type(self.nil)), doc + end + + private def define_crystal_constant(name, value, doc = nil) : Const crystal.types[name] = const = Const.new self, crystal, name, value const.no_init_flag = true + if doc && wants_doc? + const.doc = doc + end predefined_constants << const + const end property(target_machine : LLVM::TargetMachine) { codegen_target.to_target_machine } From b655c0f43d57e889ff3767635733396bd67455be Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Fri, 2 Feb 2024 21:22:39 +0800 Subject: [PATCH 091/105] Respect alignments above `alignof(Void*)` inside union values (#14279) --- spec/compiler/codegen/cast_spec.cr | 27 +++++++++ spec/compiler/codegen/sizeof_spec.cr | 10 ++++ src/compiler/crystal/codegen/codegen.cr | 4 +- src/compiler/crystal/codegen/unions.cr | 78 ++++++++++++++++++------- 4 files changed, 96 insertions(+), 23 deletions(-) diff --git a/spec/compiler/codegen/cast_spec.cr b/spec/compiler/codegen/cast_spec.cr index 32b265ea0415..fbe6cd78ac87 100644 --- a/spec/compiler/codegen/cast_spec.cr +++ b/spec/compiler/codegen/cast_spec.cr @@ -77,6 +77,33 @@ describe "Code gen: cast" do )).to_b.should be_true end + it "upcasts from union to union with different alignment" do + run(<<-CRYSTAL).to_i.should eq(1) + require "prelude" + + a = 1 || 2_i64 + a.as(Int32 | Int64 | Int128) + CRYSTAL + end + + it "downcasts from union to union with different alignment" do + run(<<-CRYSTAL).to_i.should eq(1) + require "prelude" + + a = 1 || 2_i64 || 3_i128 + a.as(Int32 | Int64) + CRYSTAL + end + + it "sidecasts from union to union with different alignment" do + run(<<-CRYSTAL).to_i.should eq(1) + require "prelude" + + a = 1 || 2_i64 + a.as(Int32 | Int128) + CRYSTAL + end + it "casts from virtual to single type" do run(%( require "prelude" diff --git a/spec/compiler/codegen/sizeof_spec.cr b/spec/compiler/codegen/sizeof_spec.cr index 8139db8bc426..e90553d0b3c1 100644 --- a/spec/compiler/codegen/sizeof_spec.cr +++ b/spec/compiler/codegen/sizeof_spec.cr @@ -279,6 +279,16 @@ describe "Code gen: sizeof" do alignof(Foo) CRYSTAL end + + it "gets alignof union" do + run("alignof(Int32 | Int8)").to_i.should eq(8) + run("alignof(Int32 | Int64)").to_i.should eq(8) + end + + it "alignof mixed union is not less than alignof its variant types" do + # NOTE: `alignof(Int128) == 16` is not guaranteed + run("alignof(Int32 | Int128) >= alignof(Int128)").to_b.should be_true + end end describe "instance_alignof" do diff --git a/src/compiler/crystal/codegen/codegen.cr b/src/compiler/crystal/codegen/codegen.cr index e7128302a66e..441f3cfa09ae 100644 --- a/src/compiler/crystal/codegen/codegen.cr +++ b/src/compiler/crystal/codegen/codegen.cr @@ -2253,11 +2253,11 @@ module Crystal res end - def memcpy(dest, src, len, align, volatile) + def memcpy(dest, src, len, align, volatile, *, src_align = align) res = call c_memcpy_fun, [dest, src, len, volatile] LibLLVM.set_instr_param_alignment(res, 1, align) - LibLLVM.set_instr_param_alignment(res, 2, align) + LibLLVM.set_instr_param_alignment(res, 2, src_align) res end diff --git a/src/compiler/crystal/codegen/unions.cr b/src/compiler/crystal/codegen/unions.cr index 1f29763d504a..7ac58ff84887 100644 --- a/src/compiler/crystal/codegen/unions.cr +++ b/src/compiler/crystal/codegen/unions.cr @@ -28,20 +28,19 @@ module Crystal @structs[llvm_name] = a_struct end - max_size = 0 + max_size = 0_u64 + max_alignment = pointer_size.to_u32! + type.expand_union_types.each do |subtype| unless subtype.void? - size = size_of(llvm_type(subtype, wants_size: true)) - max_size = size if size > max_size + llvm_type = llvm_type(subtype, wants_size: true) + max_size = {size_of(llvm_type), max_size}.max + max_alignment = {align_of(llvm_type), max_alignment}.max end end - max_size /= pointer_size.to_f - max_size = max_size.ceil.to_i - - max_size = 1 if max_size == 0 - - llvm_value_type = size_t.array(max_size) + value_size = {(max_size + (max_alignment - 1)) // max_alignment, 1_u64}.max + llvm_value_type = @llvm_context.int(max_alignment * 8).array(value_size) [@llvm_context.int32, llvm_value_type] end @@ -109,23 +108,60 @@ module Crystal store type_id(@program.void), union_type_id(struct_type, union_pointer) end - def assign_distinct_union_types(target_pointer, target_type, value_type, value) + # this is needed if `union_type` and `value_type` have different alignments, + # i.e. their `#union_value`s do not have the same offsets + def store_union_in_union(union_type, union_pointer, value_type, value) + to_llvm_type = llvm_type(union_type) + from_llvm_type = llvm_type(value_type) + union_value_type = from_llvm_type.struct_element_types[1] + + store type_id(value, value_type), union_type_id(to_llvm_type, union_pointer) + + size = @llvm_typer.size_of(union_value_type) + size = @program.bits64? ? int64(size) : int32(size) + memcpy( + cast_to_void_pointer(union_value(to_llvm_type, union_pointer)), + cast_to_void_pointer(union_value(from_llvm_type, value)), + size, + align: @llvm_typer.align_of(to_llvm_type.struct_element_types[1]), + src_align: @llvm_typer.align_of(union_value_type), + volatile: int1(0), + ) + end + + def assign_distinct_union_types(to_pointer, to_type, from_type, from_pointer) # If we have: - # - target_pointer: Pointer(A | B | C) - # - target_type: A | B | C - # - value_type: A | B - # - value: Pointer(A | B) + # - to_pointer: Pointer(A | B | C) + # - to_type: A | B | C + # - from_type: A | B + # - from_pointer: Pointer(A | B) # - # Then we: - # - load the value, we get A | B - # - cast the target pointer to Pointer(A | B) - # - store the A | B from the first pointer into the casted target pointer - casted_target_pointer = cast_to_pointer target_pointer, value_type - store load(llvm_type(value_type), value), casted_target_pointer + # Then it might happen that from_type and to_type have the same alignment. + # In this case, the two pointers are interchangeable, so we can simply: + if align_of(to_type) == align_of(from_type) + # - load the value, we get A | B + # - cast the target pointer to Pointer(A | B) + # - store the A | B from the value pointer into the casted target pointer + casted_target_pointer = cast_to_pointer to_pointer, from_type + store load(llvm_type(from_type), from_pointer), casted_target_pointer + else + # Otherwise, the type ID and the value must be stored separately + store_union_in_union to_type, to_pointer, from_type, from_pointer + end end def downcast_distinct_union_types(value, to_type : MixedUnionType, from_type : MixedUnionType) - cast_to_pointer value, to_type + # If from_type and to_type have the same alignment, we don't need a + # separate value; just cast the larger value pointer to the smaller one + if align_of(to_type) == align_of(from_type) + cast_to_pointer value, to_type + else + # This is the same as upcasting and we need that separate, newly aligned + # union value + target_pointer = alloca llvm_type(to_type) + store_union_in_union to_type, target_pointer, from_type, value + target_pointer + end end def upcast_distinct_union_types(value, to_type : MixedUnionType, from_type : MixedUnionType) From 3ba4291b0a0b8b7ae1b85cc0959d44d9c0a4d95b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Fri, 2 Feb 2024 14:22:54 +0100 Subject: [PATCH 092/105] Fix format for `asm` with comments (#14278) Co-authored-by: Sijawusz Pur Rahnama <sija@sija.pl> --- spec/compiler/formatter/formatter_spec.cr | 38 +++++++++++++++++++++++ src/compiler/crystal/tools/formatter.cr | 19 +++++++++--- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/spec/compiler/formatter/formatter_spec.cr b/spec/compiler/formatter/formatter_spec.cr index ce2c7e72364c..df25062a0931 100644 --- a/spec/compiler/formatter/formatter_spec.cr +++ b/spec/compiler/formatter/formatter_spec.cr @@ -1695,6 +1695,44 @@ describe Crystal::Formatter do assert_format %(asm("a" : "b"(c) : "d"(e)\n : "f",\n "g")) assert_format %(asm("a" ::: "a"\n : "volatile",\n "intel")) + assert_format <<-CRYSTAL, <<-CRYSTAL + asm( + # foo + "nop" + # bar + ) + CRYSTAL + asm( + # foo + "nop" + # bar + ) + CRYSTAL + + assert_format <<-CRYSTAL, <<-CRYSTAL + asm( + # the assembly template string, following the + # syntax for LLVM's integrated assembler + "nop" : # output operands + "=r"(foo), "=r"(bar) : # input operands + "r"(1), "r"(baz) : # names of clobbered registers + "eax", "memory" : # optional flags, corresponding to the LLVM IR + # sideeffect / alignstack / inteldialect / unwind attributes + "volatile", "alignstack", "intel", "unwind" + ) + CRYSTAL + asm( + # the assembly template string, following the + # syntax for LLVM's integrated assembler + "nop" : # output operands + "=r"(foo), "=r"(bar) : # input operands + "r"(1), "r"(baz) : # names of clobbered registers + "eax", "memory" : # optional flags, corresponding to the LLVM IR + # sideeffect / alignstack / inteldialect / unwind attributes + "volatile", "alignstack", "intel", "unwind" + ) + CRYSTAL + assert_format "1 # foo\n1234 # bar", "1 # foo\n1234 # bar" assert_format "1234 # foo\n1 # bar", "1234 # foo\n1 # bar" assert_format "1#foo", "1 # foo" diff --git a/src/compiler/crystal/tools/formatter.cr b/src/compiler/crystal/tools/formatter.cr index a18634fe8232..f7ebf63be7d2 100644 --- a/src/compiler/crystal/tools/formatter.cr +++ b/src/compiler/crystal/tools/formatter.cr @@ -4370,6 +4370,7 @@ module Crystal skip_space if @token.type.newline? + @indent += 2 consume_newlines has_newlines = true end @@ -4378,7 +4379,7 @@ module Crystal string = StringLiteral.new(node.text) if has_newlines - write_indent(@indent + 2, string) + write_indent(@indent, string) else indent(@column, string) end @@ -4386,8 +4387,8 @@ module Crystal skip_space if @token.type.newline? + consume_newlines if node.outputs || node.inputs - consume_newlines column += 4 write_indent(column) end @@ -4419,7 +4420,8 @@ module Crystal write_token :OP_COLON part_index += 1 end - skip_space_or_newline + skip_space + consume_newlines case part_index when 1 @@ -4457,7 +4459,9 @@ module Crystal skip_space_or_newline if has_newlines - write_line + @indent -= 2 + + write_line unless @wrote_newline write_indent end @@ -4480,7 +4484,12 @@ module Crystal end def visit_asm_parts(parts, colon_column, &) : Nil - write " " + if @wrote_newline + write_indent + else + write " " + end + column = @column parts.each_with_index do |part, i| From 3def4de48f34a95ccf02afede1372b0c2277a5a4 Mon Sep 17 00:00:00 2001 From: Kevin <apainintheneck@gmail.com> Date: Fri, 2 Feb 2024 05:23:06 -0800 Subject: [PATCH 093/105] fix: `build --no-codegen` output file name error (#14239) --- src/compiler/crystal/command.cr | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/compiler/crystal/command.cr b/src/compiler/crystal/command.cr index 178a307a54b8..b51f9405c4e6 100644 --- a/src/compiler/crystal/command.cr +++ b/src/compiler/crystal/command.cr @@ -372,6 +372,7 @@ class Crystal::Command allowed_formats = ["text", "json"]) compiler = new_compiler compiler.progress_tracker = @progress_tracker + compiler.no_codegen = no_codegen link_flags = [] of String filenames = [] of String has_stdin_filename = false @@ -608,7 +609,7 @@ class Crystal::Command output_filename = "#{::Path[first_filename].stem}#{output_extension}" # Check if we'll overwrite the main source file - if !no_codegen && !run && first_filename == File.expand_path(output_filename) + if !compiler.no_codegen? && !run && first_filename == File.expand_path(output_filename) error "compilation will overwrite source file '#{Crystal.relative_filename(first_filename)}', either change its extension to '.cr' or specify an output file with '-o'" end end @@ -620,7 +621,7 @@ class Crystal::Command error "maximum number of threads cannot be lower than 1" if compiler.n_threads < 1 - if !no_codegen && !run && Dir.exists?(output_filename) + if !compiler.no_codegen? && !run && Dir.exists?(output_filename) error "can't use `#{output_filename}` as output filename because it's a directory" end @@ -628,7 +629,7 @@ class Crystal::Command emit_base_filename = ::Path[sources.first.filename].stem end - combine_rpath = run && !no_codegen + combine_rpath = run && !compiler.no_codegen? @config = CompilerConfig.new compiler, sources, output_filename, emit_base_filename, arguments, specified_output, hierarchy_exp, cursor_location, output_format.not_nil!, combine_rpath, includes, excludes, verbose, check, tallies From 54f185d0dffa48535f9975641261d5126b578964 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Sat, 3 Feb 2024 06:09:16 +0800 Subject: [PATCH 094/105] Allow calling `#[]=` with a block using method syntax (#14161) --- spec/compiler/formatter/formatter_spec.cr | 7 +++++++ spec/compiler/parser/parser_spec.cr | 6 +++--- src/compiler/crystal/syntax/parser.cr | 6 ------ 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/spec/compiler/formatter/formatter_spec.cr b/spec/compiler/formatter/formatter_spec.cr index df25062a0931..bd992b78fa4a 100644 --- a/spec/compiler/formatter/formatter_spec.cr +++ b/spec/compiler/formatter/formatter_spec.cr @@ -1999,6 +1999,13 @@ describe Crystal::Formatter do assert_format "foo.[] = 1" assert_format "foo.[1, 2] = 3" + %w(<= == >= != []= ===).each do |operator| + assert_format "1.#{operator} { 3 }" + assert_format "1.#{operator}() { 3 }" + assert_format "1.#{operator}(2) { 3 }" + assert_format "1.#{operator} do\nend" + end + assert_format "@foo : Int32 # comment\n\ndef foo\nend" assert_format "getter foo # comment\n\ndef foo\nend" assert_format "getter foo : Int32 # comment\n\ndef foo\nend" diff --git a/spec/compiler/parser/parser_spec.cr b/spec/compiler/parser/parser_spec.cr index c9a28d87c33f..ea230d4e36ac 100644 --- a/spec/compiler/parser/parser_spec.cr +++ b/spec/compiler/parser/parser_spec.cr @@ -290,8 +290,6 @@ module Crystal assert_syntax_error "def foo=(*args); end", "setter method 'foo=' cannot have more than one parameter" assert_syntax_error "def foo=(**kwargs); end", "setter method 'foo=' cannot have more than one parameter" assert_syntax_error "def foo=(&block); end", "setter method 'foo=' cannot have a block" - assert_syntax_error "f.[]= do |a| end", "setter method '[]=' cannot be called with a block" - assert_syntax_error "f.[]= { |bar| }", "setter method '[]=' cannot be called with a block" # #10397 %w(<= >= == != []= ===).each do |operator| @@ -630,10 +628,12 @@ module Crystal it_parses "->Foo.#{op}(Int32)", ProcPointer.new("Foo".path, op, ["Int32".path] of ASTNode) end - ["bar", "+", "-", "*", "/", "<", "<=", "==", ">", ">=", "%", "|", "&", "^", "**", "===", "=~", "!~"].each do |name| + ["bar", "+", "-", "*", "/", "<", "<=", "==", ">", ">=", "%", "|", "&", "^", "**", "===", "=~", "!=", "[]=", "!~"].each do |name| it_parses "foo.#{name}", Call.new("foo".call, name) it_parses "foo.#{name} 1, 2", Call.new("foo".call, name, 1.int32, 2.int32) it_parses "foo.#{name}(1, 2)", Call.new("foo".call, name, 1.int32, 2.int32) + it_parses "foo.#{name}(1, 2) { 3 }", Call.new("foo".call, name, args: [1.int32, 2.int32] of ASTNode, block: Block.new(body: 3.int32)) + it_parses "foo.#{name} do end", Call.new("foo".call, name, block: Block.new) end ["+", "-", "*", "/", "//", "%", "|", "&", "^", "**", "<<", ">>", "&+", "&-", "&*"].each do |op| diff --git a/src/compiler/crystal/syntax/parser.cr b/src/compiler/crystal/syntax/parser.cr index 16a45eaf5e22..5d80b28ed20b 100644 --- a/src/compiler/crystal/syntax/parser.cr +++ b/src/compiler/crystal/syntax/parser.cr @@ -788,12 +788,6 @@ module Crystal end block = parse_block(block, stop_on_do: @stop_on_do) - if block || block_arg - if name == "[]=" - raise "setter method '[]=' cannot be called with a block" - end - end - atomic = Call.new atomic, name, (args || [] of ASTNode), block, block_arg, named_args atomic.has_parentheses = has_parentheses atomic.name_location = name_location From 2bce8843d8e3d82549e675519b580ab95ae1c8f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Fri, 2 Feb 2024 23:09:35 +0100 Subject: [PATCH 095/105] Drop pinning Dwarf version 2 for android (#14243) --- src/compiler/crystal/codegen/debug.cr | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/compiler/crystal/codegen/debug.cr b/src/compiler/crystal/codegen/debug.cr index 58d139ef2b3c..72555d074bb0 100644 --- a/src/compiler/crystal/codegen/debug.cr +++ b/src/compiler/crystal/codegen/debug.cr @@ -47,14 +47,6 @@ module Crystal "CodeView", mod.context.int32.const_int(1) ) - elsif @program.has_flag?("osx") || @program.has_flag?("android") - # DebugInfo generation in LLVM by default uses a higher version of dwarf - # than OS X currently understands. Android has the same problem. - mod.add_flag( - LibLLVM::ModuleFlagBehavior::Warning, - "Dwarf Version", - mod.context.int32.const_int(2) - ) end mod.add_flag( From 592051e89ff95211f584c9619dc7104ad77e6ffb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Fri, 2 Feb 2024 23:09:47 +0100 Subject: [PATCH 096/105] [CI] Upgrade `resource_class` for `test_preview_mt` (#14274) --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2eef408ee4ad..8c07a1005b70 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -116,6 +116,7 @@ jobs: test_preview_mt: machine: image: ubuntu-2004:202201-02 + resource_class: large environment: <<: *env TRAVIS_OS_NAME: linux From c67883c060dbb44b8b7365a2d028a0eb21636429 Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Mon, 5 Feb 2024 05:16:12 +0800 Subject: [PATCH 097/105] Support LLVM 18.1 (#14277) --- .github/workflows/win.yml | 27 +++++---------------------- etc/win-ci/build-llvm.ps1 | 2 +- src/llvm/ext/llvm-versions.txt | 2 +- src/llvm/lib_llvm.cr | 2 +- 4 files changed, 8 insertions(+), 25 deletions(-) diff --git a/.github/workflows/win.yml b/.github/workflows/win.yml index 9fce9f93aa44..3ef4cccb8739 100644 --- a/.github/workflows/win.yml +++ b/.github/workflows/win.yml @@ -7,7 +7,7 @@ concurrency: cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: - CI_LLVM_VERSION: "17.0.2" + CI_LLVM_VERSION: "18.1.0-rc1" jobs: x86_64-windows-libs: @@ -177,30 +177,13 @@ jobs: path: llvm key: llvm-libs-${{ env.CI_LLVM_VERSION }}-msvc - - name: Download LLVM - if: steps.cache-llvm-libs.outputs.cache-hit != 'true' - run: | - iwr https://github.com/llvm/llvm-project/releases/download/llvmorg-${{ env.CI_LLVM_VERSION }}/llvm-${{ env.CI_LLVM_VERSION }}.src.tar.xz -OutFile llvm.tar.xz - (Get-FileHash -Algorithm SHA256 .\llvm.tar.xz).hash -eq "D820E63BC3A6F4F833EC69A1EF49A2E81992E90BC23989F98946914B061AB6C7" - 7z x llvm.tar.xz - 7z x llvm.tar - mv llvm-* llvm-src - - - name: Download LLVM's CMake files - if: steps.cache-llvm-libs.outputs.cache-hit != 'true' - run: | - iwr https://github.com/llvm/llvm-project/releases/download/llvmorg-${{ env.CI_LLVM_VERSION }}/cmake-${{ env.CI_LLVM_VERSION }}.src.tar.xz -OutFile cmake.tar.xz - (Get-FileHash -Algorithm SHA256 .\cmake.tar.xz).hash -eq "B6D83C91F12757030D8361DEDC5DD84357B3EDB8DA406B5D0850DF8B6F7798B1" - 7z x cmake.tar.xz - 7z x cmake.tar - mv cmake-* cmake - - name: Build LLVM if: steps.cache-llvm-libs.outputs.cache-hit != 'true' run: | + git clone --config core.autocrlf=false -b llvmorg-${{ env.CI_LLVM_VERSION }} --depth 1 https://github.com/llvm/llvm-project.git mkdir llvm-build cd llvm-build - cmake ..\llvm-src -Thost=x64 -DLLVM_TARGETS_TO_BUILD="X86;AArch64" -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded -DBUILD_SHARED_LIBS=OFF -DCMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH=OFF -DLLVM_INCLUDE_BENCHMARKS=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_ENABLE_ZSTD=OFF + cmake ..\llvm-project\llvm -Thost=x64 -DLLVM_TARGETS_TO_BUILD="X86;AArch64" -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded -DBUILD_SHARED_LIBS=OFF -DCMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH=OFF -DLLVM_INCLUDE_BENCHMARKS=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_ENABLE_ZSTD=OFF cmake --build . --config Release cmake "-DCMAKE_INSTALL_PREFIX=$(pwd)\..\llvm" -P cmake_install.cmake @@ -235,7 +218,7 @@ jobs: uses: ./.github/workflows/win_build_portable.yml with: release: false - llvm_version: "17.0.2" + llvm_version: "18.1.0-rc1" x86_64-windows-test: runs-on: windows-2022 @@ -288,7 +271,7 @@ jobs: uses: ./.github/workflows/win_build_portable.yml with: release: true - llvm_version: "17.0.2" + llvm_version: "18.1.0-rc1" x86_64-windows-installer: if: github.repository_owner == 'crystal-lang' && (startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/heads/ci/')) diff --git a/etc/win-ci/build-llvm.ps1 b/etc/win-ci/build-llvm.ps1 index b544e9eba784..9335cfe9abe4 100644 --- a/etc/win-ci/build-llvm.ps1 +++ b/etc/win-ci/build-llvm.ps1 @@ -16,7 +16,7 @@ if (-not $Dynamic) { Setup-Git -Path $BuildTree -Url https://github.com/llvm/llvm-project.git -Ref llvmorg-$Version Run-InDirectory $BuildTree\build { - $args = "-Thost=x64 -DLLVM_TARGETS_TO_BUILD=""$($TargetsToBuild -join ';')"" -DCMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH=OFF -DLLVM_INCLUDE_BENCHMARKS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_ENABLE_ZSTD=OFF" + $args = "-Thost=x64 -DLLVM_TARGETS_TO_BUILD=$($TargetsToBuild -join ';') -DCMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH=OFF -DLLVM_INCLUDE_BENCHMARKS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_ENABLE_ZSTD=OFF" if ($Dynamic) { $args = "-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL $args" } else { diff --git a/src/llvm/ext/llvm-versions.txt b/src/llvm/ext/llvm-versions.txt index 7c8773c02212..92ae5ecbaa5a 100644 --- a/src/llvm/ext/llvm-versions.txt +++ b/src/llvm/ext/llvm-versions.txt @@ -1 +1 @@ -17.0 16.0 15.0 14.0 13.0 12.0 11.1 11.0 10.0 9.0 8.0 +18.1 17.0 16.0 15.0 14.0 13.0 12.0 11.1 11.0 10.0 9.0 8.0 diff --git a/src/llvm/lib_llvm.cr b/src/llvm/lib_llvm.cr index d5e7c2488002..b68e212d2052 100644 --- a/src/llvm/lib_llvm.cr +++ b/src/llvm/lib_llvm.cr @@ -35,7 +35,7 @@ @[Link(ldflags: {{ llvm_ldflags }})] lib LibLLVM - VERSION = {{ llvm_version.strip.gsub(/git/, "") }} + VERSION = {{ llvm_version.strip.gsub(/git/, "").gsub(/rc.*/, "") }} BUILT_TARGETS = {{ llvm_targets.strip.downcase.split(' ').map(&.id.symbolize) }} end {% end %} From 9b7850b4582fe51693c4bd77bcbd33d291534d94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Tue, 6 Feb 2024 10:19:12 +0100 Subject: [PATCH 098/105] [CI] Upgrade from old machine images approaching EOL (#14275) --- .circleci/config.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8c07a1005b70..fe4e6dabaffd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -39,7 +39,7 @@ defaults: jobs: test_linux: machine: - image: ubuntu-2004:202201-02 + image: default environment: <<: *env TRAVIS_OS_NAME: linux @@ -70,7 +70,7 @@ jobs: test_alpine: machine: - image: ubuntu-2004:202201-02 + image: default environment: <<: *env TRAVIS_OS_NAME: linux @@ -115,7 +115,7 @@ jobs: test_preview_mt: machine: - image: ubuntu-2004:202201-02 + image: default resource_class: large environment: <<: *env @@ -264,7 +264,7 @@ jobs: dist_linux: machine: - image: ubuntu-2004:202201-02 + image: default steps: - attach_workspace: at: /tmp/workspace @@ -347,7 +347,7 @@ jobs: dist_docker: machine: - image: ubuntu-2004:202201-02 + image: default steps: - attach_workspace: at: /tmp/workspace @@ -363,7 +363,7 @@ jobs: publish_docker: machine: - image: ubuntu-2004:202201-02 + image: default steps: - attach_workspace: at: /tmp/workspace @@ -418,7 +418,7 @@ jobs: dist_docs: machine: - image: ubuntu-2004:202201-02 + image: default steps: - attach_workspace: at: /tmp/workspace @@ -464,7 +464,7 @@ jobs: test_dist_linux_on_docker: machine: - image: ubuntu-2004:202201-02 + image: default environment: <<: *env TRAVIS_OS_NAME: linux From b6fc5d5d5f7d9aca34ab459ce9aa71cfc2f8796a Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Thu, 8 Feb 2024 08:01:19 +0800 Subject: [PATCH 099/105] Relax `delegate`'s setter detection (#14282) --- spec/std/object_spec.cr | 36 +++++++++++++++++++++++++++++++++++- src/object.cr | 41 +++++++++++++++++++++++++++++++---------- 2 files changed, 66 insertions(+), 11 deletions(-) diff --git a/spec/std/object_spec.cr b/spec/std/object_spec.cr index 3df134513ae2..43d1c009a19e 100644 --- a/spec/std/object_spec.cr +++ b/spec/std/object_spec.cr @@ -11,6 +11,8 @@ private class StringWrapper end end +private EQ_OPERATORS = %w(<= >= == != []= ===) + private class TestObject getter getter1 getter getter2 : Int32 @@ -113,6 +115,19 @@ private class TestObject {key, value} end + # NOTE: these methods are a syntax error in older versions + {% if compare_versions(Crystal::VERSION, "1.12.0-dev") >= 0 %} + {% for op in EQ_OPERATORS %} + def {{ op.id }}(*args, **opts) + [args, opts] + end + + def {{ op.id }}(*args, **opts, &) + [args, opts, yield] + end + {% end %} + {% end %} + annotation TestAnnotation end @@ -130,7 +145,10 @@ end private class DelegatedTestObject delegate :property1=, to: @test_object - delegate :[]=, to: @test_object + + {% for op in EQ_OPERATORS %} + delegate {{ op.id.symbolize }}, to: @test_object + {% end %} def initialize(@test_object : TestObject) end @@ -206,6 +224,22 @@ describe Object do delegated = DelegatedTestObject.new(test_object) (delegated["foo"] = "bar").should eq({"foo", "bar"}) end + + {% if compare_versions(Crystal::VERSION, "1.12.0-dev") >= 0 %} + {% for op in EQ_OPERATORS %} + it "forwards \#{{ op.id }} with multiple parameters" do + test_object = TestObject.new + delegated = DelegatedTestObject.new(test_object) + delegated.{{ op.id }}(1, 2, a: 3, b: 4).should eq [{1, 2}, {a: 3, b: 4}] + end + + it "forwards \#{{ op.id }} with multiple parameters and block parameter" do + test_object = TestObject.new + delegated = DelegatedTestObject.new(test_object) + delegated.{{ op.id }}(1, 2, a: 3, b: 4) { 5 }.should eq [{1, 2}, {a: 3, b: 4}, 5] + end + {% end %} + {% end %} end describe "getter" do diff --git a/src/object.cr b/src/object.cr index 6687e19f424a..ba818ac2979e 100644 --- a/src/object.cr +++ b/src/object.cr @@ -1293,17 +1293,18 @@ class Object # wrapper.capitalize # => "Hello" # ``` macro delegate(*methods, to object) - {% for method in methods %} - {% if method.id.ends_with?('=') && method.id != "[]=" %} - def {{method.id}}(arg) - {{object.id}}.{{method.id}} arg - end - {% else %} - def {{method.id}}(*args, **options) - {{object.id}}.{{method.id}}(*args, **options) - end + {% if compare_versions(Crystal::VERSION, "1.12.0-dev") >= 0 %} + {% eq_operators = %w(<= >= == != []= ===) %} + {% for method in methods %} + {% if method.id.ends_with?('=') && !eq_operators.includes?(method.id.stringify) %} + def {{method.id}}(arg) + {{object.id}}.{{method.id}} arg + end + {% else %} + def {{method.id}}(*args, **options) + {{object.id}}.{{method.id}}(*args, **options) + end - {% if method.id != "[]=" %} def {{method.id}}(*args, **options) {{object.id}}.{{method.id}}(*args, **options) do |*yield_args| yield *yield_args @@ -1311,6 +1312,26 @@ class Object end {% end %} {% end %} + {% else %} + {% for method in methods %} + {% if method.id.ends_with?('=') && method.id != "[]=" %} + def {{method.id}}(arg) + {{object.id}}.{{method.id}} arg + end + {% else %} + def {{method.id}}(*args, **options) + {{object.id}}.{{method.id}}(*args, **options) + end + + {% if method.id != "[]=" %} + def {{method.id}}(*args, **options) + {{object.id}}.{{method.id}}(*args, **options) do |*yield_args| + yield *yield_args + end + end + {% end %} + {% end %} + {% end %} {% end %} end From 1d9042b6853eed540bd89f60254a16c689e5375c Mon Sep 17 00:00:00 2001 From: Quinton Miller <nicetas.c@gmail.com> Date: Sat, 10 Feb 2024 01:11:40 +0800 Subject: [PATCH 100/105] Fix stack corruption in union-to-union casts (#14289) --- spec/compiler/codegen/cast_spec.cr | 35 ++++++++++++++++++++++++++ src/compiler/crystal/codegen/unions.cr | 12 ++++++--- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/spec/compiler/codegen/cast_spec.cr b/spec/compiler/codegen/cast_spec.cr index fbe6cd78ac87..dd6653f036c9 100644 --- a/spec/compiler/codegen/cast_spec.cr +++ b/spec/compiler/codegen/cast_spec.cr @@ -104,6 +104,41 @@ describe "Code gen: cast" do CRYSTAL end + it "doesn't corrupt stack when downcasting union to union with different alignment (#14285)" do + run(<<-CRYSTAL).to_b.should be_true + struct Time2 + def initialize(@seconds : Int64) + @nanoseconds = uninitialized UInt32[3] + end + + def <(other : Time2) : Bool + @seconds < other.@seconds + end + end + + class Constraints::Range + def initialize(@min : Int128 | Time2 | Nil) + end + end + + def validate(value : Time2, constraint) : Bool + min = constraint.@min + if min.is_a?(Time2?) + if min + if value < min + return false + end + end + end + true + end + + value = Time2.new(123) + constraint = Constraints::Range.new(Time2.new(45)) + validate(value, constraint) + CRYSTAL + end + it "casts from virtual to single type" do run(%( require "prelude" diff --git a/src/compiler/crystal/codegen/unions.cr b/src/compiler/crystal/codegen/unions.cr index 7ac58ff84887..bcef273a8010 100644 --- a/src/compiler/crystal/codegen/unions.cr +++ b/src/compiler/crystal/codegen/unions.cr @@ -113,18 +113,22 @@ module Crystal def store_union_in_union(union_type, union_pointer, value_type, value) to_llvm_type = llvm_type(union_type) from_llvm_type = llvm_type(value_type) - union_value_type = from_llvm_type.struct_element_types[1] + to_value_type = to_llvm_type.struct_element_types[1] + from_value_type = from_llvm_type.struct_element_types[1] store type_id(value, value_type), union_type_id(to_llvm_type, union_pointer) - size = @llvm_typer.size_of(union_value_type) + size = { + @llvm_typer.size_of(from_value_type), + @llvm_typer.size_of(to_value_type), + }.min size = @program.bits64? ? int64(size) : int32(size) memcpy( cast_to_void_pointer(union_value(to_llvm_type, union_pointer)), cast_to_void_pointer(union_value(from_llvm_type, value)), size, - align: @llvm_typer.align_of(to_llvm_type.struct_element_types[1]), - src_align: @llvm_typer.align_of(union_value_type), + align: @llvm_typer.align_of(to_value_type), + src_align: @llvm_typer.align_of(from_value_type), volatile: int1(0), ) end From 01bf92147a08073343981316493cb097d034eb78 Mon Sep 17 00:00:00 2001 From: Julien Portalier <julien@portalier.com> Date: Fri, 9 Feb 2024 18:11:49 +0100 Subject: [PATCH 101/105] Fix: don't run thread specs with the interpreter (#14287) --- spec/interpreter_std_spec.cr | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/interpreter_std_spec.cr b/spec/interpreter_std_spec.cr index 8638b0a83f7f..79b8bab3edbc 100644 --- a/spec/interpreter_std_spec.cr +++ b/spec/interpreter_std_spec.cr @@ -235,9 +235,9 @@ require "./std/system_error_spec.cr" require "./std/system/group_spec.cr" # require "./std/system_spec.cr" (failed to run) require "./std/system/user_spec.cr" -require "./std/thread/condition_variable_spec.cr" -require "./std/thread/mutex_spec.cr" -# require "./std/thread_spec.cr" (failed to run) +# require "./std/thread/condition_variable_spec.cr" (interpreter must support threads) +# require "./std/thread/mutex_spec.cr" (interpreter must support threads) +# require "./std/thread_spec.cr" (interpreter must support threads) require "./std/time/custom_formats_spec.cr" require "./std/time/format_spec.cr" require "./std/time/location_spec.cr" From 8d3722ca98ab86f7740be24da3639fa5beefc03a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Fri, 9 Feb 2024 18:12:02 +0100 Subject: [PATCH 102/105] Mention RFC process in contribution instructions (#14291) --- .github/ISSUE_TEMPLATE/feature-request.md | 4 ++++ CONTRIBUTING.md | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md index 756c4cfd2816..e6665a621eaa 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.md +++ b/.github/ISSUE_TEMPLATE/feature-request.md @@ -10,3 +10,7 @@ labels: kind:feature - Describe the feature you would like, optionally illustrated by examples, and how it will solve the above problem. - Describe considered alternative solutions, and the reasons why you have not proposed them as a solution here. - Does it break backward compatibility, if yes then what's the migration path? + +In case this proposal includes a substantial change to the language, we ask you to go through an [RFC process](https://github.com/crystal-lang/rfcs). + +The best place to start an open discussion about potential changes is the [Crystal forum](https://forum.crystal-lang.org/c/crystal-contrib/6). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 77ad67860f4b..640c980909ee 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,6 +15,10 @@ there's no more room for discussion. We'll anyway close the issue after some day If something is missing from the language it might be that it's not yet implemented or that it was purposely left out. If in doubt, just ask. +Substantial changes go through an [RFC process](https://github.com/crystal-lang/rfcs). + +The best place to start an open discussion about potential changes is the [Crystal forum](https://forum.crystal-lang.org/c/crystal-contrib/6). + ### What's needed right now You can find a list of tasks that we consider suitable for a first time contribution at From a3e8d12f5af17ddbf45aeb0a59c818541fe4dd78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Fri, 9 Feb 2024 18:14:15 +0100 Subject: [PATCH 103/105] Drop Nikola sponsor mention from Readme (#14290) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 70577b822fdc..19d8e09ee853 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Project Status Within a major version, language features won't be removed or changed in any way that could prevent a Crystal program written with that version from compiling and working. The built-in standard library might be enriched, but it will always be done with backwards compatibility in mind. -Development of the Crystal language is possible thanks to the community's effort and the continued support of [84codes](https://www.84codes.com/), [Nikola Motor Company](https://nikolamotor.com/) and every other [sponsor](https://crystal-lang.org/sponsors). +Development of the Crystal language is possible thanks to the community's effort and the continued support of [84codes](https://www.84codes.com/) and every other [sponsor](https://crystal-lang.org/sponsors). Installing ---------- From db67d71341f54d11933a33b667e141819c2af33a Mon Sep 17 00:00:00 2001 From: Jamie Gaskins <jgaskins@hey.com> Date: Sat, 10 Feb 2024 06:22:35 -0600 Subject: [PATCH 104/105] Add memory barrier to `Mutex#unlock` on aarch64 (#14272) --- src/mutex.cr | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mutex.cr b/src/mutex.cr index 6bdd9a98fd25..83dd4bb53429 100644 --- a/src/mutex.cr +++ b/src/mutex.cr @@ -107,6 +107,9 @@ class Mutex @mutex_fiber = nil end + {% if flag?(:aarch64) %} + Atomic::Ops.fence :sequentially_consistent, false + {% end %} @state.lazy_set(0) if @queue_count.get == 0 From c0270c60a685760af2b756dd65921346e172be81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= <straightshoota@gmail.com> Date: Sat, 10 Feb 2024 13:22:49 +0100 Subject: [PATCH 105/105] Enhance changelog script to pull milestone info from GitHub (#14230) --- scripts/github-changelog.cr | 47 +++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/scripts/github-changelog.cr b/scripts/github-changelog.cr index 7397440c3676..f2d277f258e7 100755 --- a/scripts/github-changelog.cr +++ b/scripts/github-changelog.cr @@ -31,6 +31,10 @@ def query_prs(api_token, repository, milestone) repository(owner: $owner, name: $repository) { milestones(query: $milestone, first: 1) { nodes { + closedAt + description + dueOn + title pullRequests(first: 300) { nodes { number @@ -81,6 +85,28 @@ module LabelNameConverter end end +record Milestone, + closed_at : Time?, + description : String, + due_on : Time?, + title : String, + pull_requests : Array(PullRequest) do + include JSON::Serializable + + @[JSON::Field(key: "dueOn")] + @due_on : Time? + + @[JSON::Field(key: "closedAt")] + @closed_at : Time? + + @[JSON::Field(key: "pullRequests", root: "nodes")] + @pull_requests : Array(PullRequest) + + def release_date + closed_at || due_on + end +end + record PullRequest, number : Int32, title : String, @@ -245,24 +271,20 @@ end response = query_prs(api_token, repository, milestone) parser = JSON::PullParser.new(response.body) -array = parser.on_key! "data" do +milestone = parser.on_key! "data" do parser.on_key! "repository" do parser.on_key! "milestones" do parser.on_key! "nodes" do parser.read_begin_array - a = parser.on_key! "pullRequests" do - parser.on_key! "nodes" do - Array(PullRequest).new(parser) - end - end + milestone = Milestone.new(parser) parser.read_end_array - a + milestone end end end end -sections = array.group_by(&.section) +sections = milestone.pull_requests.group_by(&.section) SECTION_TITLES = { "breaking" => "Breaking changes", @@ -279,9 +301,14 @@ SECTION_TITLES = { TOPIC_ORDER = %w[lang stdlib compiler tools other] -puts "## [#{milestone}] (#{Time.local.to_s("%F")})" +puts "## [#{milestone.title}] (#{milestone.release_date.try(&.to_s("%F")) || "unreleased"})" +if description = milestone.description.presence + puts + print "_", description + puts "_" +end puts -puts "[#{milestone}]: https://github.com/crystal-lang/crystal/releases/#{milestone}" +puts "[#{milestone.title}]: https://github.com/crystal-lang/crystal/releases/#{milestone.title}" puts SECTION_TITLES.each do |id, title|