ranger-compiler 3.5.0 → 3.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1160 -19
- package/LICENSE +3 -1
- package/README.md +124 -29
- package/dist/Lang.rgr +1188 -290
- package/dist/api.d.ts +2343 -879
- package/dist/api.js +79924 -56922
- package/dist/lib/JSON.rgr +102 -91
- package/dist/lib/Shell.rgr +4 -4
- package/dist/lib/apple/AppleToolchain.rgr +4 -4
- package/dist/lib/apple/README.md +5 -4
- package/dist/lib/apple/apple_test.rgr +1 -1
- package/dist/lib/core/README.md +1 -1
- package/dist/lib/evg/EVG.rgr +12 -0
- package/dist/lib/evg/EVGA11yFromTree.rgr +302 -0
- package/dist/lib/evg/EVGA11yTree.rgr +894 -0
- package/dist/lib/evg/EVGBox.rgr +267 -0
- package/dist/lib/evg/EVGBoxShorthandTest.rgr +220 -0
- package/dist/lib/evg/EVGCodepoint.rgr +316 -0
- package/dist/lib/evg/EVGColor.rgr +700 -0
- package/dist/lib/evg/EVGCommands.rgr +177 -0
- package/dist/lib/evg/EVGComponent.rgr +331 -0
- package/dist/lib/evg/EVGComponentTest.rgr +387 -0
- package/dist/lib/evg/EVGConnector.rgr +541 -0
- package/dist/lib/evg/EVGConnectorTest.rgr +306 -0
- package/dist/lib/evg/EVGDisplayList.rgr +4186 -0
- package/dist/lib/evg/EVGEasing.rgr +370 -0
- package/dist/lib/evg/EVGEffectTest.rgr +253 -0
- package/dist/lib/evg/EVGElement.rgr +4914 -0
- package/dist/lib/evg/EVGFixedTest.rgr +289 -0
- package/dist/lib/evg/EVGFlexRulesTest.rgr +317 -0
- package/dist/lib/evg/EVGFlexWrapTest.rgr +246 -0
- package/dist/lib/evg/EVGFling.rgr +244 -0
- package/dist/lib/evg/EVGFocus.rgr +400 -0
- package/dist/lib/evg/EVGFocusTest.rgr +399 -0
- package/dist/lib/evg/EVGGradient.rgr +322 -0
- package/dist/lib/evg/EVGGrapheme.rgr +190 -0
- package/dist/lib/evg/EVGGrid.rgr +975 -0
- package/dist/lib/evg/EVGHitTest.rgr +208 -0
- package/dist/lib/evg/EVGHoles.rgr +294 -0
- package/dist/lib/evg/EVGHostMeasurerTest.rgr +281 -0
- package/dist/lib/evg/EVGHostTextMeasurer.rgr +331 -0
- package/dist/lib/evg/EVGHostTree.rgr +834 -0
- package/dist/lib/evg/EVGHostTreeTest.rgr +447 -0
- package/dist/lib/evg/EVGImageDecode.rgr +117 -0
- package/dist/lib/evg/EVGImageMeasurer.rgr +86 -0
- package/dist/lib/evg/EVGInspect.rgr +883 -0
- package/dist/lib/evg/EVGInvalidateTest.rgr +432 -0
- package/dist/lib/evg/EVGJsonTest.rgr +535 -0
- package/dist/lib/evg/EVGLayout.rgr +4220 -0
- package/dist/lib/evg/EVGMeasure.rgr +1267 -0
- package/dist/lib/evg/EVGOverlayTest.rgr +626 -0
- package/dist/lib/evg/EVGPatch.rgr +1721 -0
- package/dist/lib/evg/EVGPatchTest.rgr +692 -0
- package/dist/lib/evg/EVGPopoverTest.rgr +395 -0
- package/dist/lib/evg/EVGReconcile.rgr +226 -0
- package/dist/lib/evg/EVGReconcileTest.rgr +421 -0
- package/dist/lib/evg/EVGReject.rgr +126 -0
- package/dist/lib/evg/EVGRelayoutTest.rgr +375 -0
- package/dist/lib/evg/EVGRtlLayoutTest.rgr +319 -0
- package/dist/lib/evg/EVGRuler.rgr +232 -0
- package/dist/lib/evg/EVGRulerTest.rgr +172 -0
- package/dist/lib/evg/EVGSelectChrome.rgr +178 -0
- package/dist/lib/evg/EVGStyleCacheTest.rgr +419 -0
- package/dist/lib/evg/EVGStyleSheet.rgr +2148 -0
- package/dist/lib/evg/EVGStyleStateTest.rgr +407 -0
- package/dist/lib/evg/EVGStyleVarTest.rgr +471 -0
- package/dist/lib/evg/EVGText.rgr +105 -0
- package/dist/lib/evg/EVGTextEngine.rgr +536 -0
- package/dist/lib/evg/EVGTextMeasurer.rgr +720 -0
- package/dist/lib/evg/EVGTimingTest.rgr +1417 -0
- package/dist/lib/evg/EVGToolbar.rgr +1369 -0
- package/dist/lib/evg/EVGTransition.rgr +728 -0
- package/dist/lib/evg/EVGTreeJson.rgr +721 -0
- package/dist/lib/evg/EVGUnit.rgr +554 -0
- package/dist/lib/evg/EVGViewportUnitTest.rgr +236 -0
- package/dist/lib/evg/EvgApp.rgr +189 -0
- package/dist/lib/evg/EvgBitmapTracer.rgr +4277 -0
- package/dist/lib/evg/EvgBitmapTracerTest.rgr +2119 -0
- package/dist/lib/evg/EvgHost.rgr +451 -0
- package/dist/lib/evg/EvgTest.rgr +91 -0
- package/dist/lib/evg/EvgTraceColor.rgr +236 -0
- package/dist/lib/evg/EvgTraceCurve.rgr +648 -0
- package/dist/lib/evg/EvgTraceFit.rgr +767 -0
- package/dist/lib/evg/EvgTracePath.rgr +435 -0
- package/dist/lib/evg/EvgTraceTypes.rgr +559 -0
- package/dist/lib/evg/EvgViewport.rgr +313 -0
- package/dist/lib/evg/FxDemoDoc.rgr +185 -0
- package/dist/lib/evg/HOSTS.md +227 -0
- package/dist/lib/evg/ISSUES.md +835 -0
- package/dist/lib/evg/PLAN_ACCESSIBILITY.md +650 -0
- package/dist/lib/evg/PLAN_CSS_LAYOUT_AND_FONTS.md +1124 -0
- package/dist/lib/evg/PLAN_EFFECTS.md +431 -0
- package/dist/lib/evg/PLAN_EVG.md +518 -0
- package/dist/lib/evg/PLAN_EVG_RENDERER.md +1674 -0
- package/dist/lib/evg/PLAN_INSPECTOR.md +788 -0
- package/dist/lib/evg/PLAN_LINKS_AND_FORMS.md +157 -0
- package/dist/lib/evg/PLAN_NATIVE_HOSTS.md +671 -0
- package/dist/lib/evg/PLAN_VECTOR_IR.md +664 -0
- package/dist/lib/evg/PLAN_VIEW_TRANSFORM.md +322 -0
- package/dist/lib/evg/PathBuilder.rgr +333 -0
- package/dist/lib/evg/README.md +1236 -0
- package/dist/lib/evg/SPEC.md +1252 -0
- package/dist/lib/evg/SVGPathParser.rgr +1199 -0
- package/dist/lib/evg/SvgParser.rgr +1736 -0
- package/dist/lib/evg/TODO_EVG_RENDERER.md +595 -0
- package/dist/lib/evg/VectorShapes.rgr +331 -0
- package/dist/lib/evg/VectorStroke.rgr +107 -0
- package/dist/lib/evg/VectorViewBox.rgr +380 -0
- package/dist/lib/evg/agent/README.md +290 -0
- package/dist/lib/evg/agent/evg_agent.rgr +899 -0
- package/dist/lib/evg/agent/fixtures/broken.evg.json +7 -0
- package/dist/lib/evg/agent/fixtures/card.evg.json +9 -0
- package/dist/lib/evg/agent/fixtures/connector.css +63 -0
- package/dist/lib/evg/agent/fixtures/connector.evg.json +14 -0
- package/dist/lib/evg/agent/fixtures/drawn.evg.json +129 -0
- package/dist/lib/evg/agent/fixtures/gradient.evg.json +4 -0
- package/dist/lib/evg/agent/fixtures/popover.css +99 -0
- package/dist/lib/evg/agent/fixtures/popover.evg.json +30 -0
- package/dist/lib/evg/agent/roundtrip.sh +74 -0
- package/dist/lib/evg/agent/smoke.sh +230 -0
- package/dist/lib/evg/android/README.md +97 -0
- package/dist/lib/evg/android/androidstubs/AndroidStubs.kt +175 -0
- package/dist/lib/evg/android/androidstubs/Annotation.kt +10 -0
- package/dist/lib/evg/android/androidstubs/App.kt +30 -0
- package/dist/lib/evg/android/androidstubs/Content.kt +41 -0
- package/dist/lib/evg/android/androidstubs/ContentRes.kt +12 -0
- package/dist/lib/evg/android/androidstubs/InputMethod.kt +46 -0
- package/dist/lib/evg/android/androidstubs/Net.kt +6 -0
- package/dist/lib/evg/android/androidstubs/Os.kt +30 -0
- package/dist/lib/evg/android/androidstubs/Util.kt +15 -0
- package/dist/lib/evg/android/androidstubs/View.kt +113 -0
- package/dist/lib/evg/android/androidstubs/Widget.kt +16 -0
- package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/AndroidEvgSurface.kt +323 -0
- package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/AndroidTextMeasurer.kt +56 -0
- package/dist/lib/evg/android/src/android/kotlin/fi/ranger/evg/RippleEffect.kt +262 -0
- package/dist/lib/evg/android/src/awt/kotlin/fi/ranger/evg/AwtEvgSurface.kt +238 -0
- package/dist/lib/evg/android/src/awt/kotlin/fi/ranger/evg/AwtTextMeasurer.kt +85 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgEngineThread.kt +115 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgPainter.kt +231 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/EvgSurface.kt +117 -0
- package/dist/lib/evg/android/src/main/kotlin/fi/ranger/evg/RecordingSurface.kt +94 -0
- package/dist/lib/evg/apple/README.md +128 -0
- package/dist/lib/evg/apple/Sources/CoreGraphicsEvgSurface.swift +329 -0
- package/dist/lib/evg/apple/Sources/CoreTextMeasurer.swift +70 -0
- package/dist/lib/evg/apple/Sources/EvgEngineQueue.swift +105 -0
- package/dist/lib/evg/apple/Sources/EvgPainter.swift +225 -0
- package/dist/lib/evg/apple/Sources/EvgSurface.swift +163 -0
- package/dist/lib/evg/apple/Sources/RecordingSurface.swift +110 -0
- package/dist/lib/evg/bench/EvgLayoutBench.rgr +34 -0
- package/dist/lib/evg/bench/README.md +64 -0
- package/dist/lib/evg/bench/layout-bench.mjs +316 -0
- package/dist/lib/evg/bench/layout-cases.mjs +510 -0
- package/dist/lib/evg/bench/layout-conformance.mjs +254 -0
- package/dist/lib/evg/bin/.gitignore +17 -0
- package/dist/lib/evg/evg_test.rgr +313 -0
- package/dist/lib/evg/gl/README.md +198 -0
- package/dist/lib/evg/gl/a11y-paint-check.mjs +73 -0
- package/dist/lib/evg/gl/blur-check.mjs +399 -0
- package/dist/lib/evg/gl/boxmodel.json +1 -0
- package/dist/lib/evg/gl/demo.html +46 -0
- package/dist/lib/evg/gl/effect-presets.css +285 -0
- package/dist/lib/evg/gl/effect-presets.js +63 -0
- package/dist/lib/evg/gl/effect-shots.mjs +135 -0
- package/dist/lib/evg/gl/evg-a11y.js +566 -0
- package/dist/lib/evg/gl/evg-binary.js +160 -0
- package/dist/lib/evg/gl/evg-engine.js +296 -0
- package/dist/lib/evg/gl/evg-fx.js +237 -0
- package/dist/lib/evg/gl/evg-gestures.js +209 -0
- package/dist/lib/evg/gl/evg-list.js +167 -0
- package/dist/lib/evg/gl/evg-measure.js +186 -0
- package/dist/lib/evg/gl/evg-textinput.js +303 -0
- package/dist/lib/evg/gl/evg-view.js +144 -0
- package/dist/lib/evg/gl/evg-webgl.js +3942 -0
- package/dist/lib/evg/gl/fx-check.mjs +998 -0
- package/dist/lib/evg/gl/fx-demo.html +166 -0
- package/dist/lib/evg/gl/fx-demo.js +2 -0
- package/dist/lib/evg/gl/fx-serve.mjs +47 -0
- package/dist/lib/evg/gl/gestures-check.mjs +189 -0
- package/dist/lib/evg/gl/list-binary-check.mjs +152 -0
- package/dist/lib/evg/gl/measure-check.mjs +135 -0
- package/dist/lib/evg/gl/rotation-check.mjs +207 -0
- package/dist/lib/evg/gl/shift-check.mjs +113 -0
- package/dist/lib/evg/gl/stroke-check.mjs +168 -0
- package/dist/lib/evg/gl/text-snap-check.mjs +139 -0
- package/dist/lib/evg/gl/view-check.mjs +343 -0
- package/dist/lib/evg/gl/view-policy-check.mjs +184 -0
- package/dist/lib/evg/html/evg-dom.js +318 -0
- package/dist/lib/evg/html/evg-html.js +600 -0
- package/dist/lib/evg/inspect/README.md +415 -0
- package/dist/lib/evg/inspect/browser-smoke.mjs +115 -0
- package/dist/lib/evg/inspect/evg-inspect.js +947 -0
- package/dist/lib/evg/inspect/shots/css.png +0 -0
- package/dist/lib/evg/inspect/shots/dashboard.png +0 -0
- package/dist/lib/evg/inspect/shots/pptx-slide.png +0 -0
- package/dist/lib/evg/inspect/shots/state.png +0 -0
- package/dist/lib/evg/inspect/shots.mjs +226 -0
- package/dist/lib/evg/oracle/css-blur.json +576 -0
- package/dist/lib/evg/oracle/css-box.json +157 -0
- package/dist/lib/evg/oracle/css-timing.json +709 -0
- package/dist/lib/evg/oracle/css_blur_oracle.mjs +529 -0
- package/dist/lib/evg/oracle/css_box_oracle.mjs +106 -0
- package/dist/lib/evg/oracle/css_timing_oracle.mjs +389 -0
- package/dist/lib/evg/original/EVGColor.clj +310 -0
- package/dist/lib/evg/original/EVGColorContext.rgr +178 -0
- package/dist/lib/evg/original/SVGPath.rgr +627 -0
- package/dist/lib/evg/original/Vec2.crgr +103 -0
- package/dist/lib/evg/ranger.json +9 -0
- package/dist/lib/evg/showcase/README.md +246 -0
- package/dist/lib/evg/showcase/assets/emblem.svg +30 -0
- package/dist/lib/evg/showcase/assets/rosette.svg +22 -0
- package/dist/lib/evg/showcase/build.mjs +651 -0
- package/dist/lib/evg/showcase/pages/album.tsx +30 -0
- package/dist/lib/evg/showcase/pages/boxmodel.tsx +37 -0
- package/dist/lib/evg/showcase/pages/cards.tsx +41 -0
- package/dist/lib/evg/showcase/pages/chart_api.tsx +170 -0
- package/dist/lib/evg/showcase/pages/charts.tsx +219 -0
- package/dist/lib/evg/showcase/pages/drawing.tsx +160 -0
- package/dist/lib/evg/showcase/pages/emoji.tsx +91 -0
- package/dist/lib/evg/showcase/pages/flex.tsx +46 -0
- package/dist/lib/evg/showcase/pages/more.tsx +332 -0
- package/dist/lib/evg/showcase/pages/plots.tsx +262 -0
- package/dist/lib/evg/showcase/pages/svg.tsx +63 -0
- package/dist/lib/evg/showcase/pages/tables.tsx +209 -0
- package/dist/lib/evg/showcase/pages/typography.tsx +43 -0
- package/dist/lib/evg/showcase/pages/units.tsx +35 -0
- package/dist/lib/evg/showcase/pages/variants.tsx +233 -0
- package/dist/lib/evg/showcase/pages/vector.tsx +75 -0
- package/dist/lib/evg/showcase/pages/views.tsx +223 -0
- package/dist/lib/evg/showcase/tests/chart_api_smoke.mjs +339 -0
- package/dist/lib/evg/showcase/tests/gl_smoke.mjs +125 -0
- package/dist/lib/evg/showcase/themes/chart_api-default.css +15 -0
- package/dist/lib/evg/showcase/themes/charts-default.css +29 -0
- package/dist/lib/evg/showcase/themes/drawing-default.css +35 -0
- package/dist/lib/evg/showcase/themes/more-default.css +128 -0
- package/dist/lib/evg/showcase/themes/plots-default.css +18 -0
- package/dist/lib/evg/showcase/themes/showcase.css +508 -0
- package/dist/lib/evg/showcase/themes/tables-default.css +123 -0
- package/dist/lib/evg/showcase/themes/variants-default.css +15 -0
- package/dist/lib/evg/showcase/themes/views-default.css +15 -0
- package/dist/lib/evg/tools/bench_vs_potrace.mjs +290 -0
- package/dist/lib/evg/tools/evg_image_tool.rgr +488 -0
- package/dist/lib/evg/tools/evg_trace_bench.rgr +114 -0
- package/dist/lib/evg/tools/evg_trace_cli.rgr +662 -0
- package/dist/lib/evg/tools/evg_trace_cpp_bench.rgr +83 -0
- package/dist/lib/evg/tools/run_trace_bench.sh +74 -0
- package/dist/lib/evg/tools/run_trace_cli_smoke.sh +128 -0
- package/dist/lib/evg/web/responsive/EvgResponsiveCheck.rgr +271 -0
- package/dist/lib/evg/web/responsive/EvgResponsiveDemo.rgr +531 -0
- package/dist/lib/evg/web/responsive/README.md +97 -0
- package/dist/lib/evg/web/responsive/build.mjs +90 -0
- package/dist/lib/evg/web/responsive/dom-check.mjs +169 -0
- package/dist/lib/evg/web/responsive/index.html +177 -0
- package/dist/lib/evg/web/responsive/smoke.mjs +221 -0
- package/dist/lib/evg/web/tools/assets-client.mjs +95 -0
- package/dist/lib/evg/web/tools/boot-bench.mjs +189 -0
- package/dist/lib/evg/web/tools/inline-assets.mjs +119 -0
- package/dist/lib/evg/web/tools/minify.mjs +60 -0
- package/dist/lib/evg/web/tracer/build.mjs +87 -0
- package/dist/lib/evg/web/tracer/index.html +2805 -0
- package/dist/lib/evg/web/tracer/sample.png +0 -0
- package/dist/lib/evg/web/tracer/smoke.mjs +1162 -0
- package/dist/lib/evgr/Cargo.lock +21 -0
- package/dist/lib/evgr/Cargo.toml +19 -0
- package/dist/lib/evgr/README.md +140 -0
- package/dist/lib/evgr/bench/NativeBench.rgr +246 -0
- package/dist/lib/evgr/bench/compare.mjs +252 -0
- package/dist/lib/evgr/bench/speed.mjs +277 -0
- package/dist/lib/evgr/bin/.gitignore +3 -0
- package/dist/lib/evgr/src/bin/bench.rs +106 -0
- package/dist/lib/evgr/src/bin/smoke.rs +13 -0
- package/dist/lib/evgr/src/grid.rs +730 -0
- package/dist/lib/evgr/src/lib.rs +1003 -0
- package/dist/lib/evgr/src/style.rs +468 -0
- package/dist/lib/evgr/src/text.rs +83 -0
- package/dist/lib/image/BitReader.rgr +171 -0
- package/dist/lib/image/Buffer.rgr +173 -0
- package/dist/lib/image/DCT.rgr +283 -0
- package/dist/lib/image/Deflate.rgr +339 -0
- package/dist/lib/image/HuffmanDecoder.rgr +181 -0
- package/dist/lib/image/ImageBuffer.rgr +706 -0
- package/dist/lib/image/JPEGDecoder.rgr +808 -0
- package/dist/lib/image/PNGDecoder.rgr +544 -0
- package/dist/lib/image/PNGEncoder.rgr +388 -0
- package/dist/lib/image/PPMImage.rgr +224 -0
- package/dist/lib/image/ProgressiveJPEGDecoder.rgr +1154 -0
- package/dist/lib/image/README.md +33 -0
- package/dist/lib/image/RasterBuffer.rgr +294 -0
- package/dist/lib/image/VP8BoolDecoder.rgr +163 -0
- package/dist/lib/image/WebPDecoder.rgr +433 -0
- package/dist/lib/image/WebPLossless.rgr +1035 -0
- package/dist/lib/image/WebPLossy.rgr +1929 -0
- package/dist/lib/image/ranger.json +9 -0
- package/dist/lib/image/testdata/webp/anim_2f_24x16.webp +0 -0
- package/dist/lib/image/testdata/webp/fixtures.txt +33 -0
- package/dist/lib/image/testdata/webp/gen_fixtures.py +261 -0
- package/dist/lib/image/testdata/webp/ll_1x1.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_alpha_29x21.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_gradient_64x64.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_meta_32x32.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_noise_17x9.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal11_23x11.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal2_19x7.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal40_16x16.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_pal4_13x5.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_photo_40x30.webp +0 -0
- package/dist/lib/image/testdata/webp/ll_predictors_64x32.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_1x1.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f0_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f1_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f2_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_raw_f3_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f0_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f1_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f2_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alph_vp8l_f3_21x13.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_alpha_33x17.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_exif_15x11.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_i16_96x80.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_nofilter_24x20.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_odd_17x9.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_photo_48x40.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_q100_20x18.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_sharp_40x36.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_simple_filter_33x31.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_vpx_parts8_37x45.webp +0 -0
- package/dist/lib/image/testdata/webp/ly_vpx_skip_96x80.webp +0 -0
- package/dist/lib/image/tests/WebPDecodeTool.rgr +81 -0
- package/dist/lib/image/tests/WebPDecoderTest.rgr +1162 -0
- package/dist/lib/image/tests/run_webp_tests.sh +39 -0
- package/dist/lib/rust/RsJson.rgr +468 -0
- package/dist/lib/rust/RsPrelude.rgr +1663 -0
- package/dist/lib/shell_test.rgr +7 -7
- package/dist/lib/stdlib.rgr +21 -5
- package/dist/lib/zip/ranger.json +6 -0
- package/dist/rgrc.js +87318 -67610
- package/package.json +1010 -1040
- package/dist/README.md +0 -117
- package/dist/package.json +0 -47
|
@@ -0,0 +1,1663 @@
|
|
|
1
|
+
; SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
; Runtime support for Rust-syntax modules (PLAN_RUST_SYNTAX.md).
|
|
4
|
+
;
|
|
5
|
+
; A `.rs` module is translated to Ranger (compiler/frontend/rust/lower) and
|
|
6
|
+
; imports this file. Rust fixes semantics that Ranger's own operators leave to
|
|
7
|
+
; the target -- integer division and remainder truncate toward zero, `as`
|
|
8
|
+
; truncates a float, `{}` prints a float in its shortest round-trip form and
|
|
9
|
+
; never in exponent notation -- and every target must print what the native
|
|
10
|
+
; Rust build prints. The operators here give each of those one meaning.
|
|
11
|
+
;
|
|
12
|
+
; Most are type-overloaded (`rs_div` on two ints, on two doubles), so the
|
|
13
|
+
; translator can emit one name and leave the choice to Ranger's type checker.
|
|
14
|
+
|
|
15
|
+
operators {
|
|
16
|
+
|
|
17
|
+
; ------------------------------------------------------------ arithmetic
|
|
18
|
+
|
|
19
|
+
; Integer division truncates toward zero (Python's `//` floors). Every
|
|
20
|
+
; target is spelled out: an operator with a `* @macro` template ignores its
|
|
21
|
+
; per-target ones.
|
|
22
|
+
rs_div _:int (a:int b:int) {
|
|
23
|
+
templates {
|
|
24
|
+
ranger ( "(rs_div " (e 1) " " (e 2) ")" )
|
|
25
|
+
es6 ( "Math.trunc(" (e 1) " / " (e 2) ")" )
|
|
26
|
+
python ( "rs_idiv(" (e 1) ", " (e 2) ")"
|
|
27
|
+
(create_polyfill "
|
|
28
|
+
def rs_idiv(a, b):
|
|
29
|
+
q = abs(a) // abs(b)
|
|
30
|
+
return q if (a >= 0) == (b >= 0) else -q
|
|
31
|
+
"))
|
|
32
|
+
dart ( "(" (e 1) " ~/ " (e 2) ")" )
|
|
33
|
+
php ( "intdiv(" (e 1) ", " (e 2) ")" )
|
|
34
|
+
* ( "(" (e 1) " / " (e 2) ")" )
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
rs_div _:double (a:double b:double) {
|
|
38
|
+
templates {
|
|
39
|
+
* @macro(true) ( "(" "(" (e 1) ")" " / " "(" (e 2) ")" ")" )
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
; The remainder has the sign of the dividend (Python's `%` has the sign of
|
|
44
|
+
; the divisor).
|
|
45
|
+
rs_rem _:int (a:int b:int) {
|
|
46
|
+
templates {
|
|
47
|
+
ranger ( "(rs_rem " (e 1) " " (e 2) ")" )
|
|
48
|
+
python ( "rs_irem(" (e 1) ", " (e 2) ")"
|
|
49
|
+
(create_polyfill "
|
|
50
|
+
def rs_irem(a, b):
|
|
51
|
+
r = abs(a) % abs(b)
|
|
52
|
+
return r if a >= 0 else -r
|
|
53
|
+
"))
|
|
54
|
+
dart ( "(" (e 1) ").remainder(" (e 2) ")" )
|
|
55
|
+
* ( "(" (e 1) " % " (e 2) ")" )
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
rs_rem _:double (a:double b:double) {
|
|
59
|
+
templates {
|
|
60
|
+
ranger ( "(rs_rem" " " (e 1) " " (e 2) ")" )
|
|
61
|
+
python ( "math.fmod(" (e 1) ", " (e 2) ")" (imp "math") )
|
|
62
|
+
go ( "math.Mod(" (e 1) ", " (e 2) ")" (imp "math") )
|
|
63
|
+
cpp ( "std::fmod(" (e 1) ", " (e 2) ")" (imp "<cmath>") )
|
|
64
|
+
php ( "fmod(" (e 1) ", " (e 2) ")" )
|
|
65
|
+
* ( "(" (e 1) " % " (e 2) ")" )
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
rs_neg _:int (a:int) {
|
|
70
|
+
templates {
|
|
71
|
+
* @macro(true) ( "(0 - " "(" (e 1) ")" ")" )
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
rs_neg _:double (a:double) {
|
|
75
|
+
templates {
|
|
76
|
+
* @macro(true) ( "(0.0 - " "(" (e 1) ")" ")" )
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
rs_abs _:int (a:int) {
|
|
81
|
+
templates {
|
|
82
|
+
* @macro(true) ( "(? (" "(" (e 1) ")" " < 0) (0 - " "(" (e 1) ")" ") " "(" (e 1) ")" ")" )
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
rs_abs _:double (a:double) {
|
|
86
|
+
templates {
|
|
87
|
+
* @macro(true) ( "(? (" "(" (e 1) ")" " < 0.0) (0.0 - " "(" (e 1) ")" ") " "(" (e 1) ")" ")" )
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
rs_min _:int (a:int b:int) {
|
|
92
|
+
templates {
|
|
93
|
+
* @macro(true) ( "(? (" "(" (e 1) ")" " < " "(" (e 2) ")" ") " "(" (e 1) ")" " " "(" (e 2) ")" ")" )
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
rs_min _:double (a:double b:double) {
|
|
97
|
+
templates {
|
|
98
|
+
* @macro(true) ( "(? (" "(" (e 1) ")" " < " "(" (e 2) ")" ") " "(" (e 1) ")" " " "(" (e 2) ")" ")" )
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
rs_max _:int (a:int b:int) {
|
|
102
|
+
templates {
|
|
103
|
+
* @macro(true) ( "(? (" "(" (e 1) ")" " > " "(" (e 2) ")" ") " "(" (e 1) ")" " " "(" (e 2) ")" ")" )
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
rs_max _:double (a:double b:double) {
|
|
107
|
+
templates {
|
|
108
|
+
* @macro(true) ( "(? (" "(" (e 1) ")" " > " "(" (e 2) ")" ") " "(" (e 1) ")" " " "(" (e 2) ")" ")" )
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
rs_sqrt _:double (a:double) {
|
|
113
|
+
templates {
|
|
114
|
+
* @macro(true) ( "(sqrt " "(" (e 1) ")" ")" )
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
; `f64::floor` / `ceil` answer a double (Ranger's `floor` / `ceil` an
|
|
118
|
+
; int)
|
|
119
|
+
rs_floor _:double (a:double) {
|
|
120
|
+
templates {
|
|
121
|
+
ranger ( "(rs_floor " (e 1) ")" )
|
|
122
|
+
es6 ( "Math.floor(" (e 1) ")" )
|
|
123
|
+
python ( "float(math.floor(" (e 1) "))" (imp "math") )
|
|
124
|
+
go ( "math.Floor(" (e 1) ")" (imp "math") )
|
|
125
|
+
cpp ( "std::floor(" (e 1) ")" (imp "<cmath>") )
|
|
126
|
+
rust ( "(" (e 1) ").floor()" )
|
|
127
|
+
java7 ( "Math.floor(" (e 1) ")" )
|
|
128
|
+
kotlin ( "Math.floor(" (e 1) ")" )
|
|
129
|
+
csharp ( "System.Math.Floor(" (e 1) ")" )
|
|
130
|
+
dart ( "(" (e 1) ").floorToDouble()" )
|
|
131
|
+
scala ( "math.floor(" (e 1) ")" )
|
|
132
|
+
php ( "floor(" (e 1) ")" )
|
|
133
|
+
swift6 ( "(" (e 1) ").rounded(.down)" )
|
|
134
|
+
* ( "Math.floor(" (e 1) ")" )
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
rs_ceil _:double (a:double) {
|
|
138
|
+
templates {
|
|
139
|
+
ranger ( "(rs_ceil " (e 1) ")" )
|
|
140
|
+
es6 ( "Math.ceil(" (e 1) ")" )
|
|
141
|
+
python ( "float(math.ceil(" (e 1) "))" (imp "math") )
|
|
142
|
+
go ( "math.Ceil(" (e 1) ")" (imp "math") )
|
|
143
|
+
cpp ( "std::ceil(" (e 1) ")" (imp "<cmath>") )
|
|
144
|
+
rust ( "(" (e 1) ").ceil()" )
|
|
145
|
+
java7 ( "Math.ceil(" (e 1) ")" )
|
|
146
|
+
kotlin ( "Math.ceil(" (e 1) ")" )
|
|
147
|
+
csharp ( "System.Math.Ceiling(" (e 1) ")" )
|
|
148
|
+
dart ( "(" (e 1) ").ceilToDouble()" )
|
|
149
|
+
scala ( "math.ceil(" (e 1) ")" )
|
|
150
|
+
php ( "ceil(" (e 1) ")" )
|
|
151
|
+
swift6 ( "(" (e 1) ").rounded(.up)" )
|
|
152
|
+
* ( "Math.ceil(" (e 1) ")" )
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
rs_powi _:double (a:double n:int) {
|
|
156
|
+
templates {
|
|
157
|
+
ranger ( "(rs_powi" " " (e 1) " " (e 2) ")" )
|
|
158
|
+
es6 ( "Math.pow(" (e 1) ", " (e 2) ")" )
|
|
159
|
+
python ( "float(" (e 1) " ** " (e 2) ")" )
|
|
160
|
+
go ( "math.Pow(" (e 1) ", float64(" (e 2) "))" (imp "math") )
|
|
161
|
+
cpp ( "std::pow(" (e 1) ", (double)" (e 2) ")" (imp "<cmath>") )
|
|
162
|
+
kotlin ( "Math.pow(" (e 1) ", (" (e 2) ").toDouble())" )
|
|
163
|
+
csharp ( "System.Math.Pow(" (e 1) ", " (e 2) ")" )
|
|
164
|
+
dart ( "pow(" (e 1) ", " (e 2) ").toDouble()" (imp "dart:math") )
|
|
165
|
+
scala ( "math.pow(" (e 1) ", (" (e 2) ").toDouble)" )
|
|
166
|
+
php ( "((float)pow(" (e 1) ", " (e 2) "))" )
|
|
167
|
+
* ( "Math.pow(" (e 1) ", " (e 2) ")" )
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
rs_pow _:int (a:int n:int) {
|
|
171
|
+
templates {
|
|
172
|
+
ranger ( "(rs_pow" " " (e 1) " " (e 2) ")" )
|
|
173
|
+
es6 ( "Math.pow(" (e 1) ", " (e 2) ")" )
|
|
174
|
+
python ( "(" (e 1) " ** " (e 2) ")" )
|
|
175
|
+
go ( "rs_ipow(" (e 1) ", " (e 2) ")"
|
|
176
|
+
(create_polyfill "
|
|
177
|
+
func rs_ipow(a int64, n int64) int64 {
|
|
178
|
+
r := int64(1)
|
|
179
|
+
for i := int64(0); i < n; i++ {
|
|
180
|
+
r *= a
|
|
181
|
+
}
|
|
182
|
+
return r
|
|
183
|
+
}
|
|
184
|
+
"))
|
|
185
|
+
cpp ( "rs_ipow(" (e 1) ", " (e 2) ")"
|
|
186
|
+
(create_polyfill "
|
|
187
|
+
inline long long rs_ipow(long long a, long long n) {
|
|
188
|
+
long long r = 1;
|
|
189
|
+
for (long long i = 0; i < n; i++) { r *= a; }
|
|
190
|
+
return r;
|
|
191
|
+
}
|
|
192
|
+
"))
|
|
193
|
+
java7 ( "rs_ipow(" (e 1) ", " (e 2) ")"
|
|
194
|
+
(create_polyfill "
|
|
195
|
+
static int rs_ipow(int a, int n) {
|
|
196
|
+
int r = 1;
|
|
197
|
+
for (int i = 0; i < n; i++) { r *= a; }
|
|
198
|
+
return r;
|
|
199
|
+
}
|
|
200
|
+
"))
|
|
201
|
+
kotlin ( "rs_ipow(" (e 1) ", " (e 2) ")"
|
|
202
|
+
(create_polyfill "
|
|
203
|
+
fun rs_ipow(a: Int, n: Int): Int {
|
|
204
|
+
var r = 1
|
|
205
|
+
for (i in 0 until n) { r *= a }
|
|
206
|
+
return r
|
|
207
|
+
}
|
|
208
|
+
"))
|
|
209
|
+
csharp ( "rs_ipow(" (e 1) ", " (e 2) ")"
|
|
210
|
+
(create_polyfill "
|
|
211
|
+
static int rs_ipow(int a, int n) {
|
|
212
|
+
int r = 1;
|
|
213
|
+
for (int i = 0; i < n; i++) { r *= a; }
|
|
214
|
+
return r;
|
|
215
|
+
}
|
|
216
|
+
"))
|
|
217
|
+
dart ( "rs_ipow(" (e 1) ", " (e 2) ")"
|
|
218
|
+
(create_polyfill "
|
|
219
|
+
int rs_ipow(int a, int n) {
|
|
220
|
+
var r = 1;
|
|
221
|
+
for (var i = 0; i < n; i++) { r *= a; }
|
|
222
|
+
return r;
|
|
223
|
+
}
|
|
224
|
+
"))
|
|
225
|
+
scala ( "rs_ipow(" (e 1) ", " (e 2) ")"
|
|
226
|
+
(create_polyfill "
|
|
227
|
+
def rs_ipow(a: Int, n: Int): Int = {
|
|
228
|
+
var r = 1
|
|
229
|
+
var i = 0
|
|
230
|
+
while (i < n) { r *= a; i += 1 }
|
|
231
|
+
r
|
|
232
|
+
}
|
|
233
|
+
"))
|
|
234
|
+
php ( "rs_ipow(" (e 1) ", " (e 2) ")"
|
|
235
|
+
(create_polyfill "
|
|
236
|
+
function rs_ipow($a, $n) {
|
|
237
|
+
$r = 1;
|
|
238
|
+
for ($i = 0; $i < $n; $i++) { $r *= $a; }
|
|
239
|
+
return $r;
|
|
240
|
+
}
|
|
241
|
+
"))
|
|
242
|
+
* ( "Math.pow(" (e 1) ", " (e 2) ")" )
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
; ----------------------------------------------------------------- casts
|
|
247
|
+
|
|
248
|
+
; `x as i64` on a float truncates toward zero (`to_int` floors).
|
|
249
|
+
rs_f2i _:int (a:double) {
|
|
250
|
+
templates {
|
|
251
|
+
ranger ( "(rs_f2i" " " (e 1) ")" )
|
|
252
|
+
es6 ( "Math.trunc(" (e 1) ")" )
|
|
253
|
+
python ( "int(" (e 1) ")" )
|
|
254
|
+
go ( "rs_f2i(" (e 1) ")"
|
|
255
|
+
(create_polyfill "
|
|
256
|
+
func rs_f2i(x float64) int64 {
|
|
257
|
+
return int64(x)
|
|
258
|
+
}
|
|
259
|
+
"))
|
|
260
|
+
cpp ( "(long long)(" (e 1) ")" )
|
|
261
|
+
java7 ( "((int)(double)(" (e 1) "))" )
|
|
262
|
+
kotlin ( "(" (e 1) ").toInt()" )
|
|
263
|
+
csharp ( "((int)(" (e 1) "))" )
|
|
264
|
+
dart ( "(" (e 1) ").toInt()" )
|
|
265
|
+
scala ( "(" (e 1) ").toInt" )
|
|
266
|
+
php ( "((int)(" (e 1) "))" )
|
|
267
|
+
* ( "Math.trunc(" (e 1) ")" )
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
rs_i2f _:double (a:int) {
|
|
271
|
+
templates {
|
|
272
|
+
* @macro(true) ( "(to_double " "(" (e 1) ")" ")" )
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
rs_wrap_u8 _:int (a:int) {
|
|
276
|
+
templates {
|
|
277
|
+
* @macro(true) ( "(bit_and " "(" (e 1) ")" " 255)" )
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
rs_wrap_u16 _:int (a:int) {
|
|
281
|
+
templates {
|
|
282
|
+
* @macro(true) ( "(bit_and " "(" (e 1) ")" " 65535)" )
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
; A Rust `char` is a one-character string here; these cross to and from
|
|
287
|
+
; its code point.
|
|
288
|
+
rs_char_code _:int (c:string) {
|
|
289
|
+
templates {
|
|
290
|
+
* @macro(true) ( "(itemAt (to_chars " "(" (e 1) ")" ") 0)" )
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
rs_char_from _:string (code:int) {
|
|
294
|
+
templates {
|
|
295
|
+
es6 ( "String.fromCodePoint(" (e 1) ")" )
|
|
296
|
+
python ( "chr(" (e 1) ")" )
|
|
297
|
+
go ( "string(rune(" (e 1) "))" )
|
|
298
|
+
java7 ( "(new String(Character.toChars(" (e 1) ")))" )
|
|
299
|
+
kotlin ( "String(Character.toChars(" (e 1) "))" )
|
|
300
|
+
csharp ( "char.ConvertFromUtf32(" (e 1) ")" )
|
|
301
|
+
dart ( "String.fromCharCode(" (e 1) ")" )
|
|
302
|
+
scala ( "new String(Character.toChars(" (e 1) "))" )
|
|
303
|
+
php ( "mb_chr(" (e 1) ", 'UTF-8')" )
|
|
304
|
+
* @macro(true) ( "(strfromcode " "(" (e 1) ")" ")" )
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
; ------------------------------------------------------------ formatting
|
|
309
|
+
|
|
310
|
+
; `{}` of a float: shortest round-trip digits, never an exponent, no
|
|
311
|
+
; trailing `.0` -- what Rust's Display writes.
|
|
312
|
+
rs_fmt _:string (a:double) {
|
|
313
|
+
templates {
|
|
314
|
+
ranger ( "(rs_fmt" " " (e 1) ")" )
|
|
315
|
+
es6 ( "rs_f64(" (e 1) ")"
|
|
316
|
+
(create_polyfill "
|
|
317
|
+
function rs_expand_exp(s) {
|
|
318
|
+
var neg = s.charAt(0) === '-';
|
|
319
|
+
if (neg) { s = s.slice(1); }
|
|
320
|
+
var parts = s.toLowerCase().split('e');
|
|
321
|
+
var mant = parts[0];
|
|
322
|
+
var exp = parseInt(parts[1], 10);
|
|
323
|
+
var dot = mant.indexOf('.');
|
|
324
|
+
var digits = mant.replace('.', '');
|
|
325
|
+
var intLen = (dot < 0 ? mant.length : dot) + exp;
|
|
326
|
+
var out;
|
|
327
|
+
if (intLen <= 0) { out = '0.' + '0'.repeat(-intLen) + digits; }
|
|
328
|
+
else if (intLen >= digits.length) { out = digits + '0'.repeat(intLen - digits.length); }
|
|
329
|
+
else { out = digits.slice(0, intLen) + '.' + digits.slice(intLen); }
|
|
330
|
+
return (neg ? '-' : '') + out;
|
|
331
|
+
}
|
|
332
|
+
function rs_f64(x) {
|
|
333
|
+
if (Number.isNaN(x)) { return 'NaN'; }
|
|
334
|
+
if (x === Infinity) { return 'inf'; }
|
|
335
|
+
if (x === -Infinity) { return '-inf'; }
|
|
336
|
+
if (x === 0 && 1 / x < 0) { return '-0'; }
|
|
337
|
+
var s = String(x);
|
|
338
|
+
return s.indexOf('e') < 0 ? s : rs_expand_exp(s);
|
|
339
|
+
}
|
|
340
|
+
"))
|
|
341
|
+
python ( "rs_f64(" (e 1) ")"
|
|
342
|
+
(create_polyfill "
|
|
343
|
+
def rs_f64(x):
|
|
344
|
+
import math
|
|
345
|
+
if math.isnan(x):
|
|
346
|
+
return 'NaN'
|
|
347
|
+
if math.isinf(x):
|
|
348
|
+
return 'inf' if x > 0 else '-inf'
|
|
349
|
+
s = repr(float(x))
|
|
350
|
+
if 'e' in s:
|
|
351
|
+
neg = s.startswith('-')
|
|
352
|
+
if neg:
|
|
353
|
+
s = s[1:]
|
|
354
|
+
mant, exp = s.split('e')
|
|
355
|
+
exp = int(exp)
|
|
356
|
+
dot = mant.find('.')
|
|
357
|
+
digits = mant.replace('.', '')
|
|
358
|
+
int_len = (len(mant) if dot < 0 else dot) + exp
|
|
359
|
+
if int_len <= 0:
|
|
360
|
+
s = '0.' + '0' * (-int_len) + digits
|
|
361
|
+
elif int_len >= len(digits):
|
|
362
|
+
s = digits + '0' * (int_len - len(digits))
|
|
363
|
+
else:
|
|
364
|
+
s = digits[:int_len] + '.' + digits[int_len:]
|
|
365
|
+
if neg:
|
|
366
|
+
s = '-' + s
|
|
367
|
+
if s.endswith('.0'):
|
|
368
|
+
s = s[:-2]
|
|
369
|
+
return s
|
|
370
|
+
"))
|
|
371
|
+
go ( "rs_f64(" (e 1) ")" (imp "strconv") (imp "math")
|
|
372
|
+
(create_polyfill "
|
|
373
|
+
func rs_f64(x float64) string {
|
|
374
|
+
if math.IsNaN(x) {
|
|
375
|
+
return \"NaN\"
|
|
376
|
+
}
|
|
377
|
+
if math.IsInf(x, 1) {
|
|
378
|
+
return \"inf\"
|
|
379
|
+
}
|
|
380
|
+
if math.IsInf(x, -1) {
|
|
381
|
+
return \"-inf\"
|
|
382
|
+
}
|
|
383
|
+
return strconv.FormatFloat(x, 'f', -1, 64)
|
|
384
|
+
}
|
|
385
|
+
"))
|
|
386
|
+
cpp ( "rs_f64(" (e 1) ")" (imp "<charconv>") (imp "<cmath>") (imp "<string>")
|
|
387
|
+
(create_polyfill "
|
|
388
|
+
inline std::string rs_f64(double x) {
|
|
389
|
+
if (std::isnan(x)) { return \"NaN\"; }
|
|
390
|
+
if (std::isinf(x)) { return x > 0 ? \"inf\" : \"-inf\"; }
|
|
391
|
+
char buf[400];
|
|
392
|
+
auto r = std::to_chars(buf, buf + sizeof(buf), x, std::chars_format::fixed);
|
|
393
|
+
return std::string(buf, r.ptr);
|
|
394
|
+
}
|
|
395
|
+
"))
|
|
396
|
+
rust ( "format!(\"{}\", " (e 1) ")" )
|
|
397
|
+
java7 ( "rs_f64(" (e 1) ")"
|
|
398
|
+
(create_polyfill "
|
|
399
|
+
static String rs_f64(double x) {
|
|
400
|
+
if (Double.isNaN(x)) { return \"NaN\"; }
|
|
401
|
+
if (Double.isInfinite(x)) { return x > 0 ? \"inf\" : \"-inf\"; }
|
|
402
|
+
if (x == 0.0) { return (1.0 / x < 0) ? \"-0\" : \"0\"; }
|
|
403
|
+
return new java.math.BigDecimal(Double.toString(x)).stripTrailingZeros().toPlainString();
|
|
404
|
+
}
|
|
405
|
+
"))
|
|
406
|
+
kotlin ( "rs_f64(" (e 1) ")"
|
|
407
|
+
(create_polyfill "
|
|
408
|
+
fun rs_f64(x: Double): String {
|
|
409
|
+
if (x.isNaN()) { return \"NaN\" }
|
|
410
|
+
if (x.isInfinite()) { return if (x > 0) \"inf\" else \"-inf\" }
|
|
411
|
+
if (x == 0.0) { return if (1.0 / x < 0) \"-0\" else \"0\" }
|
|
412
|
+
return java.math.BigDecimal(x.toString()).stripTrailingZeros().toPlainString()
|
|
413
|
+
}
|
|
414
|
+
"))
|
|
415
|
+
csharp ( "rs_f64(" (e 1) ")"
|
|
416
|
+
(create_polyfill "
|
|
417
|
+
// The decimal digits of mant * 2^e * 10^k, k = max(0, -e): exact, so no
|
|
418
|
+
// digit depends on the runtime's number formatting.
|
|
419
|
+
static string rs_exact(long mant, int e) {
|
|
420
|
+
var limbs = new System.Collections.Generic.List<ulong>();
|
|
421
|
+
while (mant > 0) { limbs.Add((ulong)(mant % 1000000000L)); mant /= 1000000000L; }
|
|
422
|
+
if (limbs.Count == 0) { limbs.Add(0); }
|
|
423
|
+
ulong f = e < 0 ? 5UL : 2UL;
|
|
424
|
+
for (int n = (e < 0 ? -e : e); n > 0; n--) {
|
|
425
|
+
ulong carry = 0;
|
|
426
|
+
for (int i = 0; i < limbs.Count; i++) {
|
|
427
|
+
ulong t = limbs[i] * f + carry;
|
|
428
|
+
limbs[i] = t % 1000000000UL;
|
|
429
|
+
carry = t / 1000000000UL;
|
|
430
|
+
}
|
|
431
|
+
if (carry > 0) { limbs.Add(carry); }
|
|
432
|
+
}
|
|
433
|
+
var sb = new System.Text.StringBuilder();
|
|
434
|
+
sb.Append(limbs[limbs.Count - 1]);
|
|
435
|
+
for (int i = limbs.Count - 2; i >= 0; i--) { sb.Append(limbs[i].ToString(\"D9\")); }
|
|
436
|
+
return sb.ToString();
|
|
437
|
+
}
|
|
438
|
+
// Adds one to a digit string; the result may be one digit longer.
|
|
439
|
+
static string rs_digits_inc(string s) {
|
|
440
|
+
char[] c = s.ToCharArray();
|
|
441
|
+
int i = c.Length - 1;
|
|
442
|
+
while (i >= 0 && c[i] == '9') { c[i] = '0'; i--; }
|
|
443
|
+
if (i < 0) { return \"1\" + new string(c); }
|
|
444
|
+
c[i]++;
|
|
445
|
+
return new string(c);
|
|
446
|
+
}
|
|
447
|
+
// Compares two digit strings as numbers.
|
|
448
|
+
static int rs_digits_cmp(string a, string b) {
|
|
449
|
+
a = a.TrimStart('0');
|
|
450
|
+
b = b.TrimStart('0');
|
|
451
|
+
if (a.Length != b.Length) { return a.Length < b.Length ? -1 : 1; }
|
|
452
|
+
return System.Math.Sign(string.CompareOrdinal(a, b));
|
|
453
|
+
}
|
|
454
|
+
// digits * 10^-k written without an exponent.
|
|
455
|
+
static string rs_place(string digits, int k) {
|
|
456
|
+
if (digits.Length <= k) { digits = new string('0', k - digits.Length + 1) + digits; }
|
|
457
|
+
string ip = digits.Substring(0, digits.Length - k).TrimStart('0');
|
|
458
|
+
if (ip.Length == 0) { ip = \"0\"; }
|
|
459
|
+
return k > 0 ? ip + \".\" + digits.Substring(digits.Length - k) : ip;
|
|
460
|
+
}
|
|
461
|
+
")
|
|
462
|
+
(create_polyfill "
|
|
463
|
+
// Rust's Display: the shortest digits that read back as x (the one nearest
|
|
464
|
+
// x when there are two), never an exponent.
|
|
465
|
+
static string rs_f64(double x) {
|
|
466
|
+
if (double.IsNaN(x)) { return \"NaN\"; }
|
|
467
|
+
if (double.IsPositiveInfinity(x)) { return \"inf\"; }
|
|
468
|
+
if (double.IsNegativeInfinity(x)) { return \"-inf\"; }
|
|
469
|
+
if (x == 0.0) { return (1.0 / x < 0) ? \"-0\" : \"0\"; }
|
|
470
|
+
long bits = System.BitConverter.DoubleToInt64Bits(x);
|
|
471
|
+
int be = (int)((bits >> 52) & 0x7FF);
|
|
472
|
+
long m = bits & 0xFFFFFFFFFFFFFL;
|
|
473
|
+
if (be == 0) { be = 1; } else { m |= 1L << 52; }
|
|
474
|
+
int e = be - 1077;
|
|
475
|
+
// x and the halfway points to its neighbours, all times 2^e
|
|
476
|
+
string xs = rs_exact(4 * m, e);
|
|
477
|
+
string hi = rs_exact(4 * m + 2, e);
|
|
478
|
+
string lo = rs_exact((m == (1L << 52) && be > 1) ? 4 * m - 1 : 4 * m - 2, e);
|
|
479
|
+
bool incl = (m % 2) == 0;
|
|
480
|
+
int k = e < 0 ? -e : 0;
|
|
481
|
+
string res = xs;
|
|
482
|
+
for (int n = 1; n <= xs.Length; n++) {
|
|
483
|
+
string head = xs.Substring(0, n);
|
|
484
|
+
string tail = xs.Substring(n);
|
|
485
|
+
string zeros = new string('0', tail.Length);
|
|
486
|
+
string down = head + zeros;
|
|
487
|
+
string up = rs_digits_inc(head) + zeros;
|
|
488
|
+
string half = \"5\" + new string('0', tail.Length > 0 ? tail.Length - 1 : 0);
|
|
489
|
+
int c = tail.Length > 0 ? rs_digits_cmp(tail, half) : -1;
|
|
490
|
+
bool nearUp = c > 0 || (c == 0 && ((head[n - 1] - '0') % 2) == 1);
|
|
491
|
+
string first = nearUp ? up : down;
|
|
492
|
+
string second = nearUp ? down : up;
|
|
493
|
+
string pick = null;
|
|
494
|
+
foreach (string cand in new string[] { first, second }) {
|
|
495
|
+
int cl = rs_digits_cmp(cand, lo);
|
|
496
|
+
int ch = rs_digits_cmp(cand, hi);
|
|
497
|
+
if ((cl > 0 || (incl && cl == 0)) && (ch < 0 || (incl && ch == 0))) { pick = cand; break; }
|
|
498
|
+
}
|
|
499
|
+
if (pick != null) { res = pick; break; }
|
|
500
|
+
}
|
|
501
|
+
string o = rs_place(res, k);
|
|
502
|
+
if (o.IndexOf('.') >= 0) { o = o.TrimEnd('0').TrimEnd('.'); }
|
|
503
|
+
return bits < 0 ? \"-\" + o : o;
|
|
504
|
+
}
|
|
505
|
+
"))
|
|
506
|
+
dart ( "rs_f64(" (e 1) ")"
|
|
507
|
+
(create_polyfill "
|
|
508
|
+
String rs_f64(double x) {
|
|
509
|
+
if (x.isNaN) { return 'NaN'; }
|
|
510
|
+
if (x.isInfinite) { return x > 0 ? 'inf' : '-inf'; }
|
|
511
|
+
if (x == 0.0) { return x.isNegative ? '-0' : '0'; }
|
|
512
|
+
var s = x.toString();
|
|
513
|
+
if (s.contains('e')) {
|
|
514
|
+
var neg = s.startsWith('-');
|
|
515
|
+
if (neg) { s = s.substring(1); }
|
|
516
|
+
var parts = s.split('e');
|
|
517
|
+
var mant = parts[0];
|
|
518
|
+
var exp = int.parse(parts[1]);
|
|
519
|
+
var dot = mant.indexOf('.');
|
|
520
|
+
var digits = mant.replaceAll('.', '');
|
|
521
|
+
var intLen = (dot < 0 ? mant.length : dot) + exp;
|
|
522
|
+
if (intLen <= 0) { s = '0.' + ('0' * -intLen) + digits; }
|
|
523
|
+
else if (intLen >= digits.length) { s = digits + ('0' * (intLen - digits.length)); }
|
|
524
|
+
else { s = digits.substring(0, intLen) + '.' + digits.substring(intLen); }
|
|
525
|
+
if (neg) { s = '-' + s; }
|
|
526
|
+
}
|
|
527
|
+
if (s.endsWith('.0')) { s = s.substring(0, s.length - 2); }
|
|
528
|
+
return s;
|
|
529
|
+
}
|
|
530
|
+
"))
|
|
531
|
+
scala ( "rs_f64(" (e 1) ")"
|
|
532
|
+
(create_polyfill "
|
|
533
|
+
def rs_f64(x: Double): String = {
|
|
534
|
+
if (x.isNaN) \"NaN\"
|
|
535
|
+
else if (x.isInfinite) (if (x > 0) \"inf\" else \"-inf\")
|
|
536
|
+
else if (x == 0.0) (if (1.0 / x < 0) \"-0\" else \"0\")
|
|
537
|
+
else new java.math.BigDecimal(java.lang.Double.toString(x)).stripTrailingZeros().toPlainString()
|
|
538
|
+
}
|
|
539
|
+
"))
|
|
540
|
+
php ( "rs_f64(" (e 1) ")"
|
|
541
|
+
(create_polyfill "
|
|
542
|
+
function rs_f64($x) {
|
|
543
|
+
if (is_nan($x)) { return 'NaN'; }
|
|
544
|
+
if (is_infinite($x)) { return $x > 0 ? 'inf' : '-inf'; }
|
|
545
|
+
$s = var_export((float)$x, true);
|
|
546
|
+
$neg = $s[0] == '-';
|
|
547
|
+
if ($neg) { $s = substr($s, 1); }
|
|
548
|
+
$ep = strpos($s, 'E');
|
|
549
|
+
if ($ep !== false) {
|
|
550
|
+
$mant = substr($s, 0, $ep);
|
|
551
|
+
$exp = (int)substr($s, $ep + 1);
|
|
552
|
+
$dot = strpos($mant, '.');
|
|
553
|
+
$digits = rtrim(str_replace('.', '', $mant), '0');
|
|
554
|
+
if ($digits === '') { $digits = '0'; }
|
|
555
|
+
$intLen = ($dot === false ? strlen($mant) : $dot) + $exp;
|
|
556
|
+
if ($intLen <= 0) { $s = '0.' . str_repeat('0', -$intLen) . $digits; }
|
|
557
|
+
elseif ($intLen >= strlen($digits)) { $s = $digits . str_repeat('0', $intLen - strlen($digits)); }
|
|
558
|
+
else { $s = substr($digits, 0, $intLen) . '.' . substr($digits, $intLen); }
|
|
559
|
+
}
|
|
560
|
+
if (substr($s, -2) === '.0') { $s = substr($s, 0, -2); }
|
|
561
|
+
return $neg ? '-' . $s : $s;
|
|
562
|
+
}
|
|
563
|
+
"))
|
|
564
|
+
* ( "rs_f64(" (e 1) ")" )
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
rs_fmt _:string (a:int) {
|
|
568
|
+
templates {
|
|
569
|
+
ranger ( "(rs_fmt " (e 1) ")" )
|
|
570
|
+
python ( "str(" (e 1) ")" )
|
|
571
|
+
go ( "strconv.FormatInt(int64(" (e 1) "), 10)" (imp "strconv") )
|
|
572
|
+
cpp ( "std::to_string(" (e 1) ")" (imp "<string>") )
|
|
573
|
+
rust ( (e 1) ".to_string()" )
|
|
574
|
+
java7 ( "String.valueOf(" (e 1) ")" )
|
|
575
|
+
kotlin ( (e 1) ".toString()" )
|
|
576
|
+
scala ( (e 1) ".toString" )
|
|
577
|
+
dart ( (e 1) ".toString()" )
|
|
578
|
+
csharp ( (e 1) ".ToString()" )
|
|
579
|
+
swift3 ( "String(" (e 1) ")" )
|
|
580
|
+
swift6 ( "String(" (e 1) ")" )
|
|
581
|
+
php ( "strval(" (e 1) ")" )
|
|
582
|
+
* ( "String(" (e 1) ")" )
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
rs_fmt _:string (a:boolean) {
|
|
586
|
+
templates {
|
|
587
|
+
ranger ( "(rs_fmt " (e 1) ")" )
|
|
588
|
+
python ( "('true' if " (e 1) " else 'false')" )
|
|
589
|
+
go ( "strconv.FormatBool(" (e 1) ")" (imp "strconv") )
|
|
590
|
+
cpp ( "std::string(" (e 1) " ? \"true\" : \"false\")" (imp "<string>") )
|
|
591
|
+
rust ( (e 1) ".to_string()" )
|
|
592
|
+
php ( "(" (e 1) " ? 'true' : 'false')" )
|
|
593
|
+
* ( "(" (e 1) " ? \"true\" : \"false\")" )
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
rs_fmt _:string (a:string) {
|
|
597
|
+
templates {
|
|
598
|
+
ranger ( "(rs_fmt " (e 1) ")" )
|
|
599
|
+
* ( (e 1) )
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
; `{:.N}` of a float: N decimals, a tie rounded to even as Rust does
|
|
604
|
+
; (JavaScript's toFixed rounds a tie up).
|
|
605
|
+
rs_fmt_prec _:string (a:double p:int) {
|
|
606
|
+
templates {
|
|
607
|
+
ranger ( "(rs_fmt_prec" " " (e 1) " " (e 2) ")" )
|
|
608
|
+
es6 ( "rs_f64_prec(" (e 1) ", " (e 2) ")"
|
|
609
|
+
(create_polyfill "
|
|
610
|
+
function rs_f64_prec(x, p) {
|
|
611
|
+
var m = Math.pow(10, p);
|
|
612
|
+
var y = x * m;
|
|
613
|
+
var t = Math.trunc(y);
|
|
614
|
+
if (Math.abs(y - t) === 0.5 && Number.isSafeInteger(t)) {
|
|
615
|
+
var n = (Math.abs(t) % 2 === 0) ? t : t + Math.sign(y);
|
|
616
|
+
return (n / m).toFixed(p);
|
|
617
|
+
}
|
|
618
|
+
return x.toFixed(p);
|
|
619
|
+
}
|
|
620
|
+
"))
|
|
621
|
+
python ( "format(" (e 1) ", '.' + str(" (e 2) ") + 'f')" )
|
|
622
|
+
go ( "strconv.FormatFloat(" (e 1) ", 'f', int(" (e 2) "), 64)" (imp "strconv") )
|
|
623
|
+
cpp ( "rs_f64_prec(" (e 1) ", " (e 2) ")" (imp "<cstdio>") (imp "<string>")
|
|
624
|
+
(create_polyfill "
|
|
625
|
+
inline std::string rs_f64_prec(double x, long long p) {
|
|
626
|
+
char buf[400];
|
|
627
|
+
std::snprintf(buf, sizeof(buf), \"%.*f\", (int)p, x);
|
|
628
|
+
return std::string(buf);
|
|
629
|
+
}
|
|
630
|
+
"))
|
|
631
|
+
rust ( "format!(\"{:.*}\", " (e 2) " as usize, " (e 1) ")" )
|
|
632
|
+
java7 ( "rs_f64_prec(" (e 1) ", " (e 2) ")"
|
|
633
|
+
(create_polyfill "
|
|
634
|
+
static String rs_f64_prec(double x, int p) {
|
|
635
|
+
if (Double.isNaN(x)) { return \"NaN\"; }
|
|
636
|
+
if (Double.isInfinite(x)) { return x > 0 ? \"inf\" : \"-inf\"; }
|
|
637
|
+
java.math.BigDecimal r = new java.math.BigDecimal(x).setScale(p, java.math.RoundingMode.HALF_EVEN);
|
|
638
|
+
String s = r.toPlainString();
|
|
639
|
+
if ((x < 0 || (x == 0.0 && 1.0 / x < 0)) && r.signum() == 0) { s = \"-\" + s; }
|
|
640
|
+
return s;
|
|
641
|
+
}
|
|
642
|
+
"))
|
|
643
|
+
kotlin ( "rs_f64_prec(" (e 1) ", " (e 2) ")"
|
|
644
|
+
(create_polyfill "
|
|
645
|
+
fun rs_f64_prec(x: Double, p: Int): String {
|
|
646
|
+
if (x.isNaN()) { return \"NaN\" }
|
|
647
|
+
if (x.isInfinite()) { return if (x > 0) \"inf\" else \"-inf\" }
|
|
648
|
+
val r = java.math.BigDecimal(x).setScale(p, java.math.RoundingMode.HALF_EVEN)
|
|
649
|
+
var s = r.toPlainString()
|
|
650
|
+
if ((x < 0 || (x == 0.0 && 1.0 / x < 0)) && r.signum() == 0) { s = \"-\" + s }
|
|
651
|
+
return s
|
|
652
|
+
}
|
|
653
|
+
"))
|
|
654
|
+
csharp ( "rs_f64_prec(" (e 1) ", " (e 2) ")"
|
|
655
|
+
(create_polyfill "
|
|
656
|
+
// The decimal digits of mant * 2^e * 10^k, k = max(0, -e): exact, so no
|
|
657
|
+
// digit depends on the runtime's number formatting.
|
|
658
|
+
static string rs_exact(long mant, int e) {
|
|
659
|
+
var limbs = new System.Collections.Generic.List<ulong>();
|
|
660
|
+
while (mant > 0) { limbs.Add((ulong)(mant % 1000000000L)); mant /= 1000000000L; }
|
|
661
|
+
if (limbs.Count == 0) { limbs.Add(0); }
|
|
662
|
+
ulong f = e < 0 ? 5UL : 2UL;
|
|
663
|
+
for (int n = (e < 0 ? -e : e); n > 0; n--) {
|
|
664
|
+
ulong carry = 0;
|
|
665
|
+
for (int i = 0; i < limbs.Count; i++) {
|
|
666
|
+
ulong t = limbs[i] * f + carry;
|
|
667
|
+
limbs[i] = t % 1000000000UL;
|
|
668
|
+
carry = t / 1000000000UL;
|
|
669
|
+
}
|
|
670
|
+
if (carry > 0) { limbs.Add(carry); }
|
|
671
|
+
}
|
|
672
|
+
var sb = new System.Text.StringBuilder();
|
|
673
|
+
sb.Append(limbs[limbs.Count - 1]);
|
|
674
|
+
for (int i = limbs.Count - 2; i >= 0; i--) { sb.Append(limbs[i].ToString(\"D9\")); }
|
|
675
|
+
return sb.ToString();
|
|
676
|
+
}
|
|
677
|
+
// Adds one to a digit string; the result may be one digit longer.
|
|
678
|
+
static string rs_digits_inc(string s) {
|
|
679
|
+
char[] c = s.ToCharArray();
|
|
680
|
+
int i = c.Length - 1;
|
|
681
|
+
while (i >= 0 && c[i] == '9') { c[i] = '0'; i--; }
|
|
682
|
+
if (i < 0) { return \"1\" + new string(c); }
|
|
683
|
+
c[i]++;
|
|
684
|
+
return new string(c);
|
|
685
|
+
}
|
|
686
|
+
// Compares two digit strings as numbers.
|
|
687
|
+
static int rs_digits_cmp(string a, string b) {
|
|
688
|
+
a = a.TrimStart('0');
|
|
689
|
+
b = b.TrimStart('0');
|
|
690
|
+
if (a.Length != b.Length) { return a.Length < b.Length ? -1 : 1; }
|
|
691
|
+
return System.Math.Sign(string.CompareOrdinal(a, b));
|
|
692
|
+
}
|
|
693
|
+
// digits * 10^-k written without an exponent.
|
|
694
|
+
static string rs_place(string digits, int k) {
|
|
695
|
+
if (digits.Length <= k) { digits = new string('0', k - digits.Length + 1) + digits; }
|
|
696
|
+
string ip = digits.Substring(0, digits.Length - k).TrimStart('0');
|
|
697
|
+
if (ip.Length == 0) { ip = \"0\"; }
|
|
698
|
+
return k > 0 ? ip + \".\" + digits.Substring(digits.Length - k) : ip;
|
|
699
|
+
}
|
|
700
|
+
")
|
|
701
|
+
(create_polyfill "
|
|
702
|
+
// `{:.N}`: the exact value rounded to N decimals, a tie to even.
|
|
703
|
+
static string rs_f64_prec(double x, int p) {
|
|
704
|
+
if (double.IsNaN(x)) { return \"NaN\"; }
|
|
705
|
+
if (double.IsPositiveInfinity(x)) { return \"inf\"; }
|
|
706
|
+
if (double.IsNegativeInfinity(x)) { return \"-inf\"; }
|
|
707
|
+
long bits = System.BitConverter.DoubleToInt64Bits(x);
|
|
708
|
+
int be = (int)((bits >> 52) & 0x7FF);
|
|
709
|
+
long m = bits & 0xFFFFFFFFFFFFFL;
|
|
710
|
+
if (be == 0) { be = 1; } else { m |= 1L << 52; }
|
|
711
|
+
int e = be - 1075;
|
|
712
|
+
int k = e < 0 ? -e : 0;
|
|
713
|
+
string digits = rs_exact(m, e);
|
|
714
|
+
if (k > p) {
|
|
715
|
+
string head = digits.Length > k - p ? digits.Substring(0, digits.Length - (k - p)) : \"0\";
|
|
716
|
+
string tail = digits.Length > k - p ? digits.Substring(digits.Length - (k - p)) : digits.PadLeft(k - p, '0');
|
|
717
|
+
int c = rs_digits_cmp(tail, \"5\" + new string('0', tail.Length - 1));
|
|
718
|
+
if (c > 0 || (c == 0 && ((head[head.Length - 1] - '0') % 2) == 1)) { head = rs_digits_inc(head); }
|
|
719
|
+
digits = head;
|
|
720
|
+
} else {
|
|
721
|
+
digits = digits + new string('0', p - k);
|
|
722
|
+
}
|
|
723
|
+
string res = rs_place(digits, p);
|
|
724
|
+
return bits < 0 ? \"-\" + res : res;
|
|
725
|
+
}
|
|
726
|
+
"))
|
|
727
|
+
dart ( "rs_f64_prec(" (e 1) ", " (e 2) ")" (imp "dart:typed_data")
|
|
728
|
+
(create_polyfill "
|
|
729
|
+
String rs_f64_prec(double x, int p) {
|
|
730
|
+
if (x.isNaN) { return 'NaN'; }
|
|
731
|
+
if (x.isInfinite) { return x > 0 ? 'inf' : '-inf'; }
|
|
732
|
+
var bd = ByteData(8)..setFloat64(0, x);
|
|
733
|
+
var hi = bd.getUint32(0);
|
|
734
|
+
var lo = bd.getUint32(4);
|
|
735
|
+
var neg = (hi >> 31) == 1;
|
|
736
|
+
var be = (hi >> 20) & 0x7FF;
|
|
737
|
+
var m = (BigInt.from(hi & 0xFFFFF) << 32) | BigInt.from(lo);
|
|
738
|
+
if (be == 0) { be = 1; } else { m = m | (BigInt.one << 52); }
|
|
739
|
+
var e = be - 1075;
|
|
740
|
+
// the exact value times 10^p, rounded half to even
|
|
741
|
+
var n = m * BigInt.from(10).pow(p);
|
|
742
|
+
if (e >= 0) {
|
|
743
|
+
n = n << e;
|
|
744
|
+
} else {
|
|
745
|
+
var q = n >> -e;
|
|
746
|
+
var r = n - (q << -e);
|
|
747
|
+
var half = BigInt.one << (-e - 1);
|
|
748
|
+
if (r > half || (r == half && q.isOdd)) { q = q + BigInt.one; }
|
|
749
|
+
n = q;
|
|
750
|
+
}
|
|
751
|
+
var s = n.toString();
|
|
752
|
+
if (p > 0) {
|
|
753
|
+
s = s.padLeft(p + 1, '0');
|
|
754
|
+
s = s.substring(0, s.length - p) + '.' + s.substring(s.length - p);
|
|
755
|
+
}
|
|
756
|
+
return neg ? '-' + s : s;
|
|
757
|
+
}
|
|
758
|
+
"))
|
|
759
|
+
scala ( "rs_f64_prec(" (e 1) ", " (e 2) ")"
|
|
760
|
+
(create_polyfill "
|
|
761
|
+
def rs_f64_prec(x: Double, p: Int): String = {
|
|
762
|
+
if (x.isNaN) { return \"NaN\" }
|
|
763
|
+
if (x.isInfinite) { return if (x > 0) \"inf\" else \"-inf\" }
|
|
764
|
+
val r = new java.math.BigDecimal(x).setScale(p, java.math.RoundingMode.HALF_EVEN)
|
|
765
|
+
val s = r.toPlainString()
|
|
766
|
+
if ((x < 0 || (x == 0.0 && 1.0 / x < 0)) && r.signum() == 0) \"-\" + s else s
|
|
767
|
+
}
|
|
768
|
+
"))
|
|
769
|
+
php ( "rs_f64_prec(" (e 1) ", " (e 2) ")"
|
|
770
|
+
(create_polyfill "
|
|
771
|
+
// The decimal digits of $m * 2^$e * 10^k, k = max(0, -$e), exact.
|
|
772
|
+
function rs_exact($m, $e) {
|
|
773
|
+
$limbs = [];
|
|
774
|
+
while ($m > 0) { $limbs[] = $m % 1000000000; $m = intdiv($m, 1000000000); }
|
|
775
|
+
if (count($limbs) == 0) { $limbs[] = 0; }
|
|
776
|
+
$f = $e < 0 ? 5 : 2;
|
|
777
|
+
for ($n = abs($e); $n > 0; $n--) {
|
|
778
|
+
$carry = 0;
|
|
779
|
+
$len = count($limbs);
|
|
780
|
+
for ($i = 0; $i < $len; $i++) {
|
|
781
|
+
$t = $limbs[$i] * $f + $carry;
|
|
782
|
+
$limbs[$i] = $t % 1000000000;
|
|
783
|
+
$carry = intdiv($t, 1000000000);
|
|
784
|
+
}
|
|
785
|
+
if ($carry > 0) { $limbs[] = $carry; }
|
|
786
|
+
}
|
|
787
|
+
$s = (string)$limbs[count($limbs) - 1];
|
|
788
|
+
for ($i = count($limbs) - 2; $i >= 0; $i--) { $s .= str_pad((string)$limbs[$i], 9, '0', STR_PAD_LEFT); }
|
|
789
|
+
return $s;
|
|
790
|
+
}
|
|
791
|
+
// Adds one to a digit string.
|
|
792
|
+
function rs_digits_inc($s) {
|
|
793
|
+
$i = strlen($s) - 1;
|
|
794
|
+
while ($i >= 0 && $s[$i] == '9') { $s[$i] = '0'; $i--; }
|
|
795
|
+
if ($i < 0) { return '1' . $s; }
|
|
796
|
+
$s[$i] = chr(ord($s[$i]) + 1);
|
|
797
|
+
return $s;
|
|
798
|
+
}
|
|
799
|
+
")
|
|
800
|
+
(create_polyfill "
|
|
801
|
+
// `{:.N}`: the exact value rounded to N decimals, a tie to even.
|
|
802
|
+
function rs_f64_prec($x, $p) {
|
|
803
|
+
if (is_nan($x)) { return 'NaN'; }
|
|
804
|
+
if (is_infinite($x)) { return $x > 0 ? 'inf' : '-inf'; }
|
|
805
|
+
$w = unpack('N2', pack('E', (float)$x));
|
|
806
|
+
$hi = $w[1];
|
|
807
|
+
$lo = $w[2];
|
|
808
|
+
$neg = ($hi >> 31) == 1;
|
|
809
|
+
$be = ($hi >> 20) & 0x7FF;
|
|
810
|
+
$m = (($hi & 0xFFFFF) << 32) | $lo;
|
|
811
|
+
if ($be == 0) { $be = 1; } else { $m = $m | (1 << 52); }
|
|
812
|
+
$e = $be - 1075;
|
|
813
|
+
$k = $e < 0 ? -$e : 0;
|
|
814
|
+
$digits = rs_exact($m, $e);
|
|
815
|
+
if ($k > $p) {
|
|
816
|
+
$cut = $k - $p;
|
|
817
|
+
if (strlen($digits) <= $cut) { $digits = str_repeat('0', $cut - strlen($digits) + 1) . $digits; }
|
|
818
|
+
$head = substr($digits, 0, strlen($digits) - $cut);
|
|
819
|
+
$tail = substr($digits, strlen($digits) - $cut);
|
|
820
|
+
$half = '5' . str_repeat('0', $cut - 1);
|
|
821
|
+
$c = strcmp($tail, $half);
|
|
822
|
+
if ($c > 0 || ($c == 0 && ((int)$head[strlen($head) - 1]) % 2 == 1)) { $head = rs_digits_inc($head); }
|
|
823
|
+
$digits = $head;
|
|
824
|
+
} else {
|
|
825
|
+
$digits = $digits . str_repeat('0', $p - $k);
|
|
826
|
+
}
|
|
827
|
+
if (strlen($digits) <= $p) { $digits = str_repeat('0', $p - strlen($digits) + 1) . $digits; }
|
|
828
|
+
$ip = ltrim(substr($digits, 0, strlen($digits) - $p), '0');
|
|
829
|
+
if ($ip === '') { $ip = '0'; }
|
|
830
|
+
$res = $p > 0 ? $ip . '.' . substr($digits, strlen($digits) - $p) : $ip;
|
|
831
|
+
return $neg ? '-' . $res : $res;
|
|
832
|
+
}
|
|
833
|
+
"))
|
|
834
|
+
* ( "rs_f64_prec(" (e 1) ", " (e 2) ")" )
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
; `{:?}` of a string: quoted, with Rust's escapes.
|
|
839
|
+
rs_dbg _:string (a:string) {
|
|
840
|
+
templates {
|
|
841
|
+
* @macro(true) ( "(\"\\\"\" + ((replace (replace (replace (replace " "(" (e 1) ")" " \"\\\\\" \"\\\\\\\\\") \"\\\"\" \"\\\\\\\"\") \"\\n\" \"\\\\n\") \"\\t\" \"\\\\t\") + \"\\\"\"))" )
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
rs_dbg _:string (a:double) {
|
|
845
|
+
templates {
|
|
846
|
+
* @macro(true) ( "(rs_fmt_dbg_f64 " "(" (e 1) ")" ")" )
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
rs_dbg _:string (a:int) {
|
|
850
|
+
templates {
|
|
851
|
+
* @macro(true) ( "(to_string " "(" (e 1) ")" ")" )
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
rs_dbg _:string (a:boolean) {
|
|
855
|
+
templates {
|
|
856
|
+
* @macro(true) ( "(? " "(" (e 1) ")" " \"true\" \"false\")" )
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
; `{:?}` of a float keeps the `.0` Display drops.
|
|
861
|
+
rs_fmt_dbg_f64 _:string (a:double) {
|
|
862
|
+
templates {
|
|
863
|
+
* @macro(true) ( "(RsFmt.dbgF64(" "(" (e 1) ")" "))" )
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
; `panic!`: the message on stderr and exit status 101, as Rust does. Not
|
|
868
|
+
; a Ranger `throw`, which callers would have to catch.
|
|
869
|
+
rs_panic _:void (msg:string) {
|
|
870
|
+
templates {
|
|
871
|
+
ranger ( "rs_panic " (e 1) )
|
|
872
|
+
es6 ( "process.stderr.write(" (e 1) " + \"\\n\"); process.exit(101);" )
|
|
873
|
+
python ( "sys.stderr.write(" (e 1) " + \"\\n\"); sys.exit(101)" (imp "sys") )
|
|
874
|
+
go ( "fmt.Fprintln(os.Stderr, " (e 1) "); os.Exit(101)" (imp "fmt") (imp "os") )
|
|
875
|
+
cpp ( "std::cerr << " (e 1) " << std::endl; std::exit(101);" (imp "<iostream>") (imp "<cstdlib>") )
|
|
876
|
+
rust ( "panic!(\"{}\", " (e 1) ");" )
|
|
877
|
+
java7 ( "System.err.println(" (e 1) "); System.exit(101);" )
|
|
878
|
+
kotlin ( "System.err.println(" (e 1) "); kotlin.system.exitProcess(101)" )
|
|
879
|
+
csharp ( "System.Console.Error.WriteLine(" (e 1) "); System.Environment.Exit(101);" )
|
|
880
|
+
dart ( "stderr.writeln(" (e 1) "); exit(101);" (imp "dart:io") )
|
|
881
|
+
scala ( "System.err.println(" (e 1) "); sys.exit(101)" )
|
|
882
|
+
php ( "fwrite(STDERR, " (e 1) " . \"\\n\"); exit(101);" )
|
|
883
|
+
* ( "process.stderr.write(" (e 1) " + \"\\n\"); process.exit(101);" )
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
; Ordering of strings: Ranger's `<` / `>` take numbers only.
|
|
888
|
+
rs_str_cmp _:int (a:string b:string) {
|
|
889
|
+
templates {
|
|
890
|
+
ranger ( "(rs_str_cmp " (e 1) " " (e 2) ")" )
|
|
891
|
+
es6 ( "(" (e 1) " < " (e 2) " ? -1 : (" (e 1) " > " (e 2) " ? 1 : 0))" )
|
|
892
|
+
python ( "(-1 if " (e 1) " < " (e 2) " else (1 if " (e 1) " > " (e 2) " else 0))" )
|
|
893
|
+
go ( "int64(strings.Compare(" (e 1) ", " (e 2) "))" (imp "strings") )
|
|
894
|
+
cpp ( "(long long)((" (e 1) ").compare(" (e 2) ") < 0 ? -1 : ((" (e 1) ").compare(" (e 2) ") > 0 ? 1 : 0))" )
|
|
895
|
+
rust ( "(match " (e 1) ".cmp(&" (e 2) ") { std::cmp::Ordering::Less => -1, std::cmp::Ordering::Equal => 0, _ => 1 })" )
|
|
896
|
+
java7 ( "Integer.signum(" (e 1) ".compareTo(" (e 2) "))" )
|
|
897
|
+
kotlin ( "Integer.signum(" (e 1) ".compareTo(" (e 2) "))" )
|
|
898
|
+
csharp ( "System.Math.Sign(string.CompareOrdinal(" (e 1) ", " (e 2) "))" )
|
|
899
|
+
dart ( "(" (e 1) ").compareTo(" (e 2) ").sign" )
|
|
900
|
+
scala ( "Integer.signum(" (e 1) ".compareTo(" (e 2) "))" )
|
|
901
|
+
php ( "max(-1, min(1, strcmp(" (e 1) ", " (e 2) ")))" )
|
|
902
|
+
* ( "(" (e 1) " < " (e 2) " ? -1 : (" (e 1) " > " (e 2) " ? 1 : 0))" )
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
rs_map_len _:int (m:[K:T]) {
|
|
907
|
+
templates {
|
|
908
|
+
ranger ( "(rs_map_len " (e 1) ")" )
|
|
909
|
+
es6 ( "Object.keys(" (e 1) ").length" )
|
|
910
|
+
python ( "len(" (e 1) ")" )
|
|
911
|
+
go ( "int64(len(" (e 1) "))" )
|
|
912
|
+
cpp ( "(long long)(" (e 1) ").size()" )
|
|
913
|
+
rust ( "(" (e 1) ".len() as i64)" )
|
|
914
|
+
java7 ( (e 1) ".size()" )
|
|
915
|
+
kotlin ( (e 1) ".size" )
|
|
916
|
+
csharp ( (e 1) ".Count" )
|
|
917
|
+
dart ( (e 1) ".length" )
|
|
918
|
+
php ( "count(" (e 1) ")" )
|
|
919
|
+
swift6 ( (e 1) ".count" )
|
|
920
|
+
scala ( (e 1) ".size" )
|
|
921
|
+
* ( "Object.keys(" (e 1) ").length" )
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
; Removing a key: Ranger has no operator for it.
|
|
926
|
+
rs_map_remove _:void (m:[K:T] k:K) {
|
|
927
|
+
templates {
|
|
928
|
+
ranger ( "rs_map_remove " (e 1) " " (e 2) )
|
|
929
|
+
es6 ( "delete " (e 1) "[" (e 2) "];" )
|
|
930
|
+
python ( (e 1) ".pop(" (e 2) ", None)" )
|
|
931
|
+
go ( "delete(" (e 1) ", " (e 2) ")" )
|
|
932
|
+
cpp ( "rs_map_erase(" (e 1) ", " (e 2) ");"
|
|
933
|
+
(create_polyfill "
|
|
934
|
+
template <class M, class K>
|
|
935
|
+
inline void rs_map_erase(M& m, const K& k) {
|
|
936
|
+
for (auto it = m.entries.begin(); it != m.entries.end(); ++it) {
|
|
937
|
+
if (it->first == k) {
|
|
938
|
+
m.entries.erase(it);
|
|
939
|
+
m.rehash_();
|
|
940
|
+
return;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
"))
|
|
945
|
+
rust ( (e 1) ".remove(&" (e 2) ");" )
|
|
946
|
+
java7 ( (e 1) ".remove(" (e 2) ");" )
|
|
947
|
+
kotlin ( (e 1) ".remove(" (e 2) ")" )
|
|
948
|
+
csharp ( (e 1) ".Remove(" (e 2) ");" )
|
|
949
|
+
dart ( (e 1) ".remove(" (e 2) ");" )
|
|
950
|
+
php ( "unset(" (e 1) "[" (e 2) "]);" )
|
|
951
|
+
swift6 ( (e 1) ".removeValue(forKey: " (e 2) ")" )
|
|
952
|
+
scala ( (e 1) ".remove(" (e 2) ")" )
|
|
953
|
+
* ( "delete " (e 1) "[" (e 2) "];" )
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
; ---------------------------------------------------------------- strings
|
|
958
|
+
|
|
959
|
+
; Rust's `find` answers a BYTE offset; `indexOf` answers the target's own
|
|
960
|
+
; unit, so the prefix before the hit is measured in UTF-8.
|
|
961
|
+
rs_find_bytes _:int (s:string p:string) {
|
|
962
|
+
templates {
|
|
963
|
+
* @macro(true) ( "(RsStr.findBytes(" "(" (e 1) ")" " " "(" (e 2) ")" "))" )
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
rs_byte_slice _:string (s:string a:int b:int) {
|
|
967
|
+
templates {
|
|
968
|
+
* @macro(true) ( "(substring (to_charbuffer " "(" (e 1) ")" ") " "(" (e 2) ")" " " "(" (e 3) ")" ")" )
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
rs_byte_len _:int (s:string) {
|
|
972
|
+
templates {
|
|
973
|
+
* @macro(true) ( "(length (to_charbuffer " "(" (e 1) ")" "))" )
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
; Unicode case mapping. The C++ target's to_uppercase maps ASCII only; the
|
|
977
|
+
; polyfill covers Latin-1, Latin Extended-A, Greek and Cyrillic.
|
|
978
|
+
rs_upper _:string (s:string) {
|
|
979
|
+
templates {
|
|
980
|
+
ranger ( "(rs_upper " (e 1) ")" )
|
|
981
|
+
cpp ( "rs_case(" (e 1) ", true)" (imp "<string>")
|
|
982
|
+
(create_polyfill "
|
|
983
|
+
inline long rs_case_map(long c, bool up) {
|
|
984
|
+
if (up) {
|
|
985
|
+
if (c >= 'a' && c <= 'z') { return c - 32; }
|
|
986
|
+
if ((c >= 0xE0 && c <= 0xFE && c != 0xF7)) { return c - 32; }
|
|
987
|
+
if (c == 0xFF) { return 0x178; }
|
|
988
|
+
if (c >= 0x100 && c <= 0x17F && c != 0x130 && c != 0x131 && c != 0x138 && c != 0x149 && c != 0x17F) {
|
|
989
|
+
bool oddLow = (c >= 0x139 && c <= 0x148) || (c >= 0x179 && c <= 0x17E);
|
|
990
|
+
if (oddLow) { return (c % 2 == 0) ? c - 1 : c; }
|
|
991
|
+
return (c % 2 == 1) ? c - 1 : c;
|
|
992
|
+
}
|
|
993
|
+
if (c >= 0x3B1 && c <= 0x3C9 && c != 0x3C2) { return c - 32; }
|
|
994
|
+
if (c >= 0x430 && c <= 0x44F) { return c - 32; }
|
|
995
|
+
if (c >= 0x450 && c <= 0x45F) { return c - 80; }
|
|
996
|
+
return c;
|
|
997
|
+
}
|
|
998
|
+
if (c >= 'A' && c <= 'Z') { return c + 32; }
|
|
999
|
+
if ((c >= 0xC0 && c <= 0xDE && c != 0xD7)) { return c + 32; }
|
|
1000
|
+
if (c == 0x178) { return 0xFF; }
|
|
1001
|
+
if (c >= 0x100 && c <= 0x17F && c != 0x130 && c != 0x131 && c != 0x138 && c != 0x149 && c != 0x17F) {
|
|
1002
|
+
bool oddLow = (c >= 0x139 && c <= 0x148) || (c >= 0x179 && c <= 0x17E);
|
|
1003
|
+
if (oddLow) { return (c % 2 == 1) ? c + 1 : c; }
|
|
1004
|
+
return (c % 2 == 0) ? c + 1 : c;
|
|
1005
|
+
}
|
|
1006
|
+
if (c >= 0x391 && c <= 0x3A9 && c != 0x3A2) { return c + 32; }
|
|
1007
|
+
if (c >= 0x410 && c <= 0x42F) { return c + 32; }
|
|
1008
|
+
if (c >= 0x400 && c <= 0x40F) { return c + 80; }
|
|
1009
|
+
return c;
|
|
1010
|
+
}
|
|
1011
|
+
inline std::string rs_case(const std::string& s, bool up) {
|
|
1012
|
+
std::string out;
|
|
1013
|
+
size_t i = 0;
|
|
1014
|
+
while (i < s.size()) {
|
|
1015
|
+
unsigned char b = (unsigned char)s[i];
|
|
1016
|
+
long c = b;
|
|
1017
|
+
size_t n = 1;
|
|
1018
|
+
if (b >= 0xF0) { c = b & 0x07; n = 4; }
|
|
1019
|
+
else if (b >= 0xE0) { c = b & 0x0F; n = 3; }
|
|
1020
|
+
else if (b >= 0xC0) { c = b & 0x1F; n = 2; }
|
|
1021
|
+
for (size_t k = 1; k < n && i + k < s.size(); k++) { c = (c << 6) | ((unsigned char)s[i + k] & 0x3F); }
|
|
1022
|
+
i += n;
|
|
1023
|
+
if (up && c == 0xDF) { out += \"SS\"; continue; }
|
|
1024
|
+
long m = rs_case_map(c, up);
|
|
1025
|
+
if (m < 0x80) { out += (char)m; }
|
|
1026
|
+
else if (m < 0x800) { out += (char)(0xC0 | (m >> 6)); out += (char)(0x80 | (m & 0x3F)); }
|
|
1027
|
+
else if (m < 0x10000) { out += (char)(0xE0 | (m >> 12)); out += (char)(0x80 | ((m >> 6) & 0x3F)); out += (char)(0x80 | (m & 0x3F)); }
|
|
1028
|
+
else { out += (char)(0xF0 | (m >> 18)); out += (char)(0x80 | ((m >> 12) & 0x3F)); out += (char)(0x80 | ((m >> 6) & 0x3F)); out += (char)(0x80 | (m & 0x3F)); }
|
|
1029
|
+
}
|
|
1030
|
+
return out;
|
|
1031
|
+
}
|
|
1032
|
+
"))
|
|
1033
|
+
; strings.ToUpper maps one rune to one rune; Rust special casing writes
|
|
1034
|
+
; ß as SS
|
|
1035
|
+
go ( "strings.ReplaceAll(strings.ToUpper(" (e 1) "), \"ß\", \"SS\")" (imp "strings") )
|
|
1036
|
+
csharp ( "(" (e 1) ").ToUpperInvariant().Replace(\"ß\", \"SS\")" )
|
|
1037
|
+
dart ( "(" (e 1) ").toUpperCase().replaceAll(\"ß\", \"SS\")" )
|
|
1038
|
+
php ( "mb_strtoupper(" (e 1) ", 'UTF-8')" )
|
|
1039
|
+
* @macro(true) ( "(to_uppercase " "(" (e 1) ")" ")" )
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
rs_lower _:string (s:string) {
|
|
1043
|
+
templates {
|
|
1044
|
+
ranger ( "(rs_lower " (e 1) ")" )
|
|
1045
|
+
cpp ( "rs_case(" (e 1) ", false)" (imp "<string>") )
|
|
1046
|
+
php ( "mb_strtolower(" (e 1) ", 'UTF-8')" )
|
|
1047
|
+
* @macro(true) ( "(to_lowercase " "(" (e 1) ")" ")" )
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
rs_char_count _:int (s:string) {
|
|
1052
|
+
templates {
|
|
1053
|
+
* @macro(true) ( "(array_length (to_chars " "(" (e 1) ")" "))" )
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
; ------------------------------------------------------- float methods
|
|
1057
|
+
; `x.round()` rounds half away from zero; `x.trunc()`, `x.ln()`,
|
|
1058
|
+
; `x.exp()`, `x.log10()`, `x.powf(y)` and `x.signum()` are the libm ones.
|
|
1059
|
+
|
|
1060
|
+
rs_round _:double (a:double) {
|
|
1061
|
+
templates {
|
|
1062
|
+
ranger ( "(rs_round " (e 1) ")" )
|
|
1063
|
+
es6 ( "rs_round(" (e 1) ")"
|
|
1064
|
+
(create_polyfill "
|
|
1065
|
+
function rs_round(x) {
|
|
1066
|
+
const a = Math.abs(x);
|
|
1067
|
+
let r = Math.floor(a);
|
|
1068
|
+
if (a - r >= 0.5) { r += 1; }
|
|
1069
|
+
return x < 0 ? -r : r;
|
|
1070
|
+
}
|
|
1071
|
+
"))
|
|
1072
|
+
python ( "rs_round(" (e 1) ")" (imp "math")
|
|
1073
|
+
(create_polyfill "
|
|
1074
|
+
def rs_round(x):
|
|
1075
|
+
if not math.isfinite(x):
|
|
1076
|
+
return x
|
|
1077
|
+
a = abs(x)
|
|
1078
|
+
r = math.floor(a)
|
|
1079
|
+
if a - r >= 0.5:
|
|
1080
|
+
r += 1
|
|
1081
|
+
return math.copysign(float(r), x)
|
|
1082
|
+
"))
|
|
1083
|
+
go ( "math.Round(" (e 1) ")" (imp "math") )
|
|
1084
|
+
cpp ( "std::round(" (e 1) ")" (imp "<cmath>") )
|
|
1085
|
+
java7 ( "rs_round(" (e 1) ")"
|
|
1086
|
+
(create_polyfill "
|
|
1087
|
+
static double rs_round(double x) {
|
|
1088
|
+
if (Double.isNaN(x) || Double.isInfinite(x)) { return x; }
|
|
1089
|
+
double a = Math.abs(x);
|
|
1090
|
+
double r = Math.floor(a);
|
|
1091
|
+
if (a - r >= 0.5) { r += 1; }
|
|
1092
|
+
return Math.copySign(r, x);
|
|
1093
|
+
}
|
|
1094
|
+
"))
|
|
1095
|
+
kotlin ( "rs_round(" (e 1) ")"
|
|
1096
|
+
(create_polyfill "
|
|
1097
|
+
fun rs_round(x: Double): Double {
|
|
1098
|
+
if (x.isNaN() || x.isInfinite()) { return x }
|
|
1099
|
+
val a = Math.abs(x)
|
|
1100
|
+
var r = Math.floor(a)
|
|
1101
|
+
if (a - r >= 0.5) { r += 1.0 }
|
|
1102
|
+
return Math.copySign(r, x)
|
|
1103
|
+
}
|
|
1104
|
+
"))
|
|
1105
|
+
csharp ( "System.Math.Round(" (e 1) ", System.MidpointRounding.AwayFromZero)" )
|
|
1106
|
+
dart ( "(" (e 1) ").roundToDouble()" )
|
|
1107
|
+
scala ( "rs_round(" (e 1) ")"
|
|
1108
|
+
(create_polyfill "
|
|
1109
|
+
def rs_round(x: Double): Double = {
|
|
1110
|
+
if (x.isNaN || x.isInfinite) { return x }
|
|
1111
|
+
val a = math.abs(x)
|
|
1112
|
+
var r = math.floor(a)
|
|
1113
|
+
if (a - r >= 0.5) { r += 1.0 }
|
|
1114
|
+
java.lang.Math.copySign(r, x)
|
|
1115
|
+
}
|
|
1116
|
+
"))
|
|
1117
|
+
php ( "round(" (e 1) ")" )
|
|
1118
|
+
* ( "Math.round(" (e 1) ")" )
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
rs_trunc _:double (a:double) {
|
|
1122
|
+
templates {
|
|
1123
|
+
ranger ( "(rs_trunc " (e 1) ")" )
|
|
1124
|
+
es6 ( "Math.trunc(" (e 1) ")" )
|
|
1125
|
+
python ( "rs_trunc(" (e 1) ")" (imp "math")
|
|
1126
|
+
(create_polyfill "
|
|
1127
|
+
def rs_trunc(x):
|
|
1128
|
+
if not math.isfinite(x):
|
|
1129
|
+
return x
|
|
1130
|
+
return math.copysign(float(math.trunc(x)), x)
|
|
1131
|
+
"))
|
|
1132
|
+
go ( "math.Trunc(" (e 1) ")" (imp "math") )
|
|
1133
|
+
cpp ( "std::trunc(" (e 1) ")" (imp "<cmath>") )
|
|
1134
|
+
java7 ( "(" (e 1) " < 0 ? Math.ceil(" (e 1) ") : Math.floor(" (e 1) "))" )
|
|
1135
|
+
kotlin ( "(if (" (e 1) " < 0) Math.ceil(" (e 1) ") else Math.floor(" (e 1) "))" )
|
|
1136
|
+
csharp ( "System.Math.Truncate(" (e 1) ")" )
|
|
1137
|
+
dart ( "(" (e 1) ").truncateToDouble()" )
|
|
1138
|
+
scala ( "(if (" (e 1) " < 0) math.ceil(" (e 1) ") else math.floor(" (e 1) "))" )
|
|
1139
|
+
php ( "rs_trunc(" (e 1) ")"
|
|
1140
|
+
(create_polyfill "
|
|
1141
|
+
function rs_trunc($x) {
|
|
1142
|
+
return $x < 0 ? ceil($x) : floor($x);
|
|
1143
|
+
}
|
|
1144
|
+
"))
|
|
1145
|
+
* ( "Math.floor(" (e 1) ")" )
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
rs_ln _:double (a:double) {
|
|
1149
|
+
templates {
|
|
1150
|
+
ranger ( "(rs_ln " (e 1) ")" )
|
|
1151
|
+
es6 ( "Math.log(" (e 1) ")" )
|
|
1152
|
+
python ( "math.log(" (e 1) ")" (imp "math") )
|
|
1153
|
+
go ( "math.Log(" (e 1) ")" (imp "math") )
|
|
1154
|
+
cpp ( "std::log(" (e 1) ")" (imp "<cmath>") )
|
|
1155
|
+
csharp ( "System.Math.Log(" (e 1) ")" )
|
|
1156
|
+
dart ( "log(" (e 1) ")" (imp "dart:math") )
|
|
1157
|
+
scala ( "math.log(" (e 1) ")" )
|
|
1158
|
+
php ( "log(" (e 1) ")" )
|
|
1159
|
+
* ( "Math.log(" (e 1) ")" )
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
rs_exp _:double (a:double) {
|
|
1163
|
+
templates {
|
|
1164
|
+
ranger ( "(rs_exp " (e 1) ")" )
|
|
1165
|
+
es6 ( "Math.exp(" (e 1) ")" )
|
|
1166
|
+
python ( "math.exp(" (e 1) ")" (imp "math") )
|
|
1167
|
+
go ( "math.Exp(" (e 1) ")" (imp "math") )
|
|
1168
|
+
cpp ( "std::exp(" (e 1) ")" (imp "<cmath>") )
|
|
1169
|
+
csharp ( "System.Math.Exp(" (e 1) ")" )
|
|
1170
|
+
dart ( "exp(" (e 1) ")" (imp "dart:math") )
|
|
1171
|
+
scala ( "math.exp(" (e 1) ")" )
|
|
1172
|
+
php ( "exp(" (e 1) ")" )
|
|
1173
|
+
* ( "Math.exp(" (e 1) ")" )
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
rs_log10 _:double (a:double) {
|
|
1177
|
+
templates {
|
|
1178
|
+
ranger ( "(rs_log10 " (e 1) ")" )
|
|
1179
|
+
es6 ( "Math.log10(" (e 1) ")" )
|
|
1180
|
+
python ( "math.log10(" (e 1) ")" (imp "math") )
|
|
1181
|
+
go ( "math.Log10(" (e 1) ")" (imp "math") )
|
|
1182
|
+
cpp ( "std::log10(" (e 1) ")" (imp "<cmath>") )
|
|
1183
|
+
csharp ( "System.Math.Log10(" (e 1) ")" )
|
|
1184
|
+
dart ( "rs_log10(" (e 1) ")" (imp "dart:math")
|
|
1185
|
+
(create_polyfill "
|
|
1186
|
+
double rs_log10(double x) {
|
|
1187
|
+
var r = log(x) / ln10;
|
|
1188
|
+
// exact powers of ten come out exact, as libm's log10 gives them
|
|
1189
|
+
var k = r.roundToDouble();
|
|
1190
|
+
if (k.abs() < 300 && pow(10.0, k) == x) { return k; }
|
|
1191
|
+
return r;
|
|
1192
|
+
}
|
|
1193
|
+
"))
|
|
1194
|
+
scala ( "math.log10(" (e 1) ")" )
|
|
1195
|
+
php ( "log10(" (e 1) ")" )
|
|
1196
|
+
* ( "Math.log10(" (e 1) ")" )
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
rs_powf _:double (a:double b:double) {
|
|
1200
|
+
templates {
|
|
1201
|
+
ranger ( "(rs_powf " (e 1) " " (e 2) ")" )
|
|
1202
|
+
es6 ( "Math.pow(" (e 1) ", " (e 2) ")" )
|
|
1203
|
+
python ( "math.pow(" (e 1) ", " (e 2) ")" (imp "math") )
|
|
1204
|
+
go ( "math.Pow(" (e 1) ", " (e 2) ")" (imp "math") )
|
|
1205
|
+
cpp ( "std::pow(" (e 1) ", " (e 2) ")" (imp "<cmath>") )
|
|
1206
|
+
csharp ( "System.Math.Pow(" (e 1) ", " (e 2) ")" )
|
|
1207
|
+
dart ( "pow(" (e 1) ", " (e 2) ").toDouble()" (imp "dart:math") )
|
|
1208
|
+
scala ( "math.pow(" (e 1) ", " (e 2) ")" )
|
|
1209
|
+
php ( "((float)pow(" (e 1) ", " (e 2) "))" )
|
|
1210
|
+
* ( "Math.pow(" (e 1) ", " (e 2) ")" )
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
; 1.0 for +0.0 and positive numbers, -1.0 for -0.0 and negative ones, NaN
|
|
1214
|
+
; for NaN
|
|
1215
|
+
rs_signum _:double (a:double) {
|
|
1216
|
+
templates {
|
|
1217
|
+
ranger ( "(rs_signum " (e 1) ")" )
|
|
1218
|
+
es6 ( "rs_signum(" (e 1) ")"
|
|
1219
|
+
(create_polyfill "
|
|
1220
|
+
function rs_signum(x) {
|
|
1221
|
+
if (x !== x) { return x; }
|
|
1222
|
+
return (x < 0 || Object.is(x, -0)) ? -1 : 1;
|
|
1223
|
+
}
|
|
1224
|
+
"))
|
|
1225
|
+
python ( "(" (e 1) " if math.isnan(" (e 1) ") else math.copysign(1.0, " (e 1) "))" (imp "math") )
|
|
1226
|
+
go ( "rs_signum(" (e 1) ")" (imp "math")
|
|
1227
|
+
(create_polyfill "
|
|
1228
|
+
func rs_signum(x float64) float64 {
|
|
1229
|
+
if math.IsNaN(x) {
|
|
1230
|
+
return x
|
|
1231
|
+
}
|
|
1232
|
+
return math.Copysign(1, x)
|
|
1233
|
+
}
|
|
1234
|
+
"))
|
|
1235
|
+
cpp ( "(std::isnan(" (e 1) ") ? " (e 1) " : std::copysign(1.0, " (e 1) "))" (imp "<cmath>") )
|
|
1236
|
+
java7 ( "(Double.isNaN(" (e 1) ") ? " (e 1) " : Math.copySign(1.0, " (e 1) "))" )
|
|
1237
|
+
kotlin ( "(if ((" (e 1) ").isNaN()) " (e 1) " else Math.copySign(1.0, " (e 1) "))" )
|
|
1238
|
+
csharp ( "(double.IsNaN(" (e 1) ") ? " (e 1) " : ((" (e 1) " < 0 || (" (e 1) " == 0 && 1.0 / " (e 1) " < 0)) ? -1.0 : 1.0))" )
|
|
1239
|
+
dart ( "((" (e 1) ").isNaN ? " (e 1) " : ((" (e 1) ").isNegative ? -1.0 : 1.0))" )
|
|
1240
|
+
scala ( "(if ((" (e 1) ").isNaN) " (e 1) " else java.lang.Math.copySign(1.0, " (e 1) "))" )
|
|
1241
|
+
php ( "rs_signum(" (e 1) ")"
|
|
1242
|
+
(create_polyfill "
|
|
1243
|
+
function rs_signum($x) {
|
|
1244
|
+
if (is_nan($x)) { return $x; }
|
|
1245
|
+
return ($x < 0 || ($x == 0 && fdiv(1, $x) < 0)) ? -1.0 : 1.0;
|
|
1246
|
+
}
|
|
1247
|
+
"))
|
|
1248
|
+
* ( "Math.signum(" (e 1) ")" )
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
; ------------------------------------------------------------ map keys
|
|
1253
|
+
|
|
1254
|
+
; The keys of an int-keyed map (Ranger's `keys` takes string keys). On
|
|
1255
|
+
; JavaScript the map is an object, whose keys come back as strings.
|
|
1256
|
+
rs_int_keys _:[int] (m:[int:T]) {
|
|
1257
|
+
templates {
|
|
1258
|
+
ranger ( "(rs_int_keys " (e 1) ")" )
|
|
1259
|
+
es6 ( "Object.keys(" (e 1) ").map(Number)" )
|
|
1260
|
+
python ( "list(" (e 1) ".keys())" )
|
|
1261
|
+
go ( "rs_int_keys(" (e 1) ")"
|
|
1262
|
+
(create_polyfill "
|
|
1263
|
+
func rs_int_keys[V any](m map[int64]V) []int64 {
|
|
1264
|
+
res := make([]int64, 0, len(m))
|
|
1265
|
+
for k := range m {
|
|
1266
|
+
res = append(res, k)
|
|
1267
|
+
}
|
|
1268
|
+
return res
|
|
1269
|
+
}
|
|
1270
|
+
"))
|
|
1271
|
+
cpp ( "rs_int_keys(" (e 1) ")" (imp "<vector>")
|
|
1272
|
+
(create_polyfill "
|
|
1273
|
+
template< typename M >
|
|
1274
|
+
std::vector<int> rs_int_keys( const M & m ) {
|
|
1275
|
+
std::vector<int> res;
|
|
1276
|
+
for (auto it = m.begin(); it != m.end(); ++it) {
|
|
1277
|
+
res.push_back(it->first);
|
|
1278
|
+
}
|
|
1279
|
+
return res;
|
|
1280
|
+
}
|
|
1281
|
+
"))
|
|
1282
|
+
rust ( (e 1) ".keys().cloned().collect::<Vec<i64>>()" )
|
|
1283
|
+
kotlin ( "ArrayList(" (e 1) ".keys)" )
|
|
1284
|
+
csharp ( "new System.Collections.Generic.List<int>(" (e 1) ".Keys)" )
|
|
1285
|
+
dart ( "(" (e 1) ").keys.toList()" )
|
|
1286
|
+
scala ( "(" (e 1) ").keys.to[collection.mutable.ArrayBuffer]" )
|
|
1287
|
+
php ( "array_keys(" (e 1) ")" )
|
|
1288
|
+
* ( "new ArrayList<>(" (e 1) ".keySet())" )
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
; ---------------------------------------------------------------- stderr
|
|
1293
|
+
|
|
1294
|
+
; `eprintln!`: a line on standard error.
|
|
1295
|
+
rs_eprint _:void (s:string) {
|
|
1296
|
+
templates {
|
|
1297
|
+
ranger ( "rs_eprint " (e 1) nl )
|
|
1298
|
+
es6 ( "console.error(" (e 1) ");" nl )
|
|
1299
|
+
python ( "print(" (e 1) ", file=sys.stderr)" nl (imp "sys") )
|
|
1300
|
+
go ( "fmt.Fprintln(os.Stderr, " (e 1) ")" nl (imp "fmt") (imp "os") )
|
|
1301
|
+
cpp ( "std::cerr << " (e 1) " << std::endl;" nl (imp "<iostream>") )
|
|
1302
|
+
kotlin ( "System.err.println(" (e 1) ")" nl )
|
|
1303
|
+
csharp ( "System.Console.Error.WriteLine(" (e 1) ");" nl )
|
|
1304
|
+
dart ( "stderr.writeln(" (e 1) ");" nl (imp "dart:io") )
|
|
1305
|
+
scala ( "System.err.println(" (e 1) ")" nl )
|
|
1306
|
+
php ( "fwrite(STDERR, " (e 1) " . \"\\n\");" nl )
|
|
1307
|
+
* ( "System.err.println(" (e 1) ");" nl )
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
|
|
1313
|
+
class RsFmt {
|
|
1314
|
+
; `{:?}` of a char: quoted with ', escapes as Rust writes them.
|
|
1315
|
+
sfn dbgChar:string (c:string) {
|
|
1316
|
+
if (c == "\\") {
|
|
1317
|
+
return "'\\\\'"
|
|
1318
|
+
}
|
|
1319
|
+
if (c == "'") {
|
|
1320
|
+
return "'\\''"
|
|
1321
|
+
}
|
|
1322
|
+
if (c == "\n") {
|
|
1323
|
+
return "'\\n'"
|
|
1324
|
+
}
|
|
1325
|
+
if (c == "\t") {
|
|
1326
|
+
return "'\\t'"
|
|
1327
|
+
}
|
|
1328
|
+
if (c == "\r") {
|
|
1329
|
+
return "'\\r'"
|
|
1330
|
+
}
|
|
1331
|
+
return (("'" + c) + "'")
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
; `{:>8}`, `{:<8}`, `{:^8}` with a fill character; the width counts code
|
|
1335
|
+
; points, as Rust's does.
|
|
1336
|
+
sfn pad:string (s:string width:int align:string fill:string) {
|
|
1337
|
+
def n:int (rs_char_count s)
|
|
1338
|
+
if (n >= width) {
|
|
1339
|
+
return s
|
|
1340
|
+
}
|
|
1341
|
+
def total:int (width - n)
|
|
1342
|
+
def left:int 0
|
|
1343
|
+
if (align == ">") {
|
|
1344
|
+
left = total
|
|
1345
|
+
}
|
|
1346
|
+
if (align == "^") {
|
|
1347
|
+
left = (rs_div total 2)
|
|
1348
|
+
}
|
|
1349
|
+
def right:int (total - left)
|
|
1350
|
+
return (((RsStr.repeat(fill left)) + s) + (RsStr.repeat(fill right)))
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
; `{:08}`: zeros after the sign.
|
|
1354
|
+
sfn padZero:string (s:string width:int) {
|
|
1355
|
+
def n:int (rs_char_count s)
|
|
1356
|
+
if (n >= width) {
|
|
1357
|
+
return s
|
|
1358
|
+
}
|
|
1359
|
+
def zeros:string (RsStr.repeat("0" (width - n)))
|
|
1360
|
+
if ((strlen s) > 0) {
|
|
1361
|
+
def first:string (substring s 0 1)
|
|
1362
|
+
if ((first == "-") || (first == "+")) {
|
|
1363
|
+
return ((first + zeros) + (substring s 1 (strlen s)))
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
return (zeros + s)
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
sfn dbgF64:string (x:double) {
|
|
1370
|
+
def s:string (rs_fmt x)
|
|
1371
|
+
if ((indexOf s ".") >= 0) {
|
|
1372
|
+
return s
|
|
1373
|
+
}
|
|
1374
|
+
if ((s == "NaN") || (s == "inf") || (s == "-inf")) {
|
|
1375
|
+
return s
|
|
1376
|
+
}
|
|
1377
|
+
return (s + ".0")
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
class RsStr {
|
|
1382
|
+
; `s.parse::<i64>()`: an optional sign and decimal digits, nothing else
|
|
1383
|
+
; (no spaces, no trailing text), within i64.
|
|
1384
|
+
sfn parseI64@(optional):int (s:string) {
|
|
1385
|
+
def none@(optional):int
|
|
1386
|
+
def cs:[int] (to_chars s)
|
|
1387
|
+
def n:int (array_length cs)
|
|
1388
|
+
if (n == 0) {
|
|
1389
|
+
return none
|
|
1390
|
+
}
|
|
1391
|
+
def i:int 0
|
|
1392
|
+
def first:int (itemAt cs 0)
|
|
1393
|
+
if ((first == 43) || (first == 45)) {
|
|
1394
|
+
i = 1
|
|
1395
|
+
}
|
|
1396
|
+
if (i >= n) {
|
|
1397
|
+
return none
|
|
1398
|
+
}
|
|
1399
|
+
if ((n - i) > 19) {
|
|
1400
|
+
return none
|
|
1401
|
+
}
|
|
1402
|
+
while (i < n) {
|
|
1403
|
+
def c:int (itemAt cs i)
|
|
1404
|
+
if ((c < 48) || (c > 57)) {
|
|
1405
|
+
return none
|
|
1406
|
+
}
|
|
1407
|
+
i = i + 1
|
|
1408
|
+
}
|
|
1409
|
+
def r@(optional):int (to_int s)
|
|
1410
|
+
return r
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
; Rust's ParseIntError text for `s`.
|
|
1414
|
+
sfn parseIntErr:string (s:string) {
|
|
1415
|
+
if ((strlen s) == 0) {
|
|
1416
|
+
return "cannot parse integer from empty string"
|
|
1417
|
+
}
|
|
1418
|
+
if ((s == "-") || (s == "+")) {
|
|
1419
|
+
return "invalid digit found in string"
|
|
1420
|
+
}
|
|
1421
|
+
def cs:[int] (to_chars s)
|
|
1422
|
+
def i:int 0
|
|
1423
|
+
def n:int (array_length cs)
|
|
1424
|
+
def first:int (itemAt cs 0)
|
|
1425
|
+
if ((first == 43) || (first == 45)) {
|
|
1426
|
+
i = 1
|
|
1427
|
+
}
|
|
1428
|
+
while (i < n) {
|
|
1429
|
+
def c:int (itemAt cs i)
|
|
1430
|
+
if ((c < 48) || (c > 57)) {
|
|
1431
|
+
return "invalid digit found in string"
|
|
1432
|
+
}
|
|
1433
|
+
i = i + 1
|
|
1434
|
+
}
|
|
1435
|
+
if (first == 45) {
|
|
1436
|
+
return "number too small to fit in target type"
|
|
1437
|
+
}
|
|
1438
|
+
return "number too large to fit in target type"
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
; `s.parse::<f64>()`: sign, digits with at most one dot, an optional
|
|
1442
|
+
; exponent; "inf", "infinity" and "NaN" as Rust spells them.
|
|
1443
|
+
sfn parseF64@(optional):double (s:string) {
|
|
1444
|
+
def none@(optional):double
|
|
1445
|
+
def low:string (to_lowercase s)
|
|
1446
|
+
def body:string low
|
|
1447
|
+
if (((strlen low) > 0) && (((substring low 0 1) == "+") || ((substring low 0 1) == "-"))) {
|
|
1448
|
+
body = (substring low 1 (strlen low))
|
|
1449
|
+
}
|
|
1450
|
+
if ((body == "inf") || (body == "infinity") || (body == "nan")) {
|
|
1451
|
+
def sp@(optional):double (to_double s)
|
|
1452
|
+
if (null? sp) {
|
|
1453
|
+
def neg:boolean ((substring low 0 1) == "-")
|
|
1454
|
+
if (body == "nan") {
|
|
1455
|
+
return none
|
|
1456
|
+
}
|
|
1457
|
+
def big:double 1.0
|
|
1458
|
+
def k:int 0
|
|
1459
|
+
while (k < 400) {
|
|
1460
|
+
big = (big * 10.0)
|
|
1461
|
+
k = k + 1
|
|
1462
|
+
}
|
|
1463
|
+
if neg {
|
|
1464
|
+
big = (0.0 - big)
|
|
1465
|
+
}
|
|
1466
|
+
def bo@(optional):double big
|
|
1467
|
+
return bo
|
|
1468
|
+
}
|
|
1469
|
+
return sp
|
|
1470
|
+
}
|
|
1471
|
+
def cs:[int] (to_chars body)
|
|
1472
|
+
def n:int (array_length cs)
|
|
1473
|
+
def digits:int 0
|
|
1474
|
+
def dots:int 0
|
|
1475
|
+
def i:int 0
|
|
1476
|
+
while ((i < n) && ((itemAt cs i) != 101)) {
|
|
1477
|
+
def c:int (itemAt cs i)
|
|
1478
|
+
if (c == 46) {
|
|
1479
|
+
dots = dots + 1
|
|
1480
|
+
} {
|
|
1481
|
+
if ((c < 48) || (c > 57)) {
|
|
1482
|
+
return none
|
|
1483
|
+
}
|
|
1484
|
+
digits = digits + 1
|
|
1485
|
+
}
|
|
1486
|
+
i = i + 1
|
|
1487
|
+
}
|
|
1488
|
+
if ((digits == 0) || (dots > 1)) {
|
|
1489
|
+
return none
|
|
1490
|
+
}
|
|
1491
|
+
if (i < n) {
|
|
1492
|
+
i = i + 1
|
|
1493
|
+
if ((i < n) && (((itemAt cs i) == 43) || ((itemAt cs i) == 45))) {
|
|
1494
|
+
i = i + 1
|
|
1495
|
+
}
|
|
1496
|
+
if (i >= n) {
|
|
1497
|
+
return none
|
|
1498
|
+
}
|
|
1499
|
+
while (i < n) {
|
|
1500
|
+
def e:int (itemAt cs i)
|
|
1501
|
+
if ((e < 48) || (e > 57)) {
|
|
1502
|
+
return none
|
|
1503
|
+
}
|
|
1504
|
+
i = i + 1
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
def r@(optional):double (to_double s)
|
|
1508
|
+
return r
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
sfn parseFloatErr:string (s:string) {
|
|
1512
|
+
if ((strlen s) == 0) {
|
|
1513
|
+
return "cannot parse float from empty string"
|
|
1514
|
+
}
|
|
1515
|
+
return "invalid float literal"
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
; `s.repeat(n)`
|
|
1519
|
+
sfn repeat:string (s:string n:int) {
|
|
1520
|
+
def r:string ""
|
|
1521
|
+
def i:int 0
|
|
1522
|
+
while (i < n) {
|
|
1523
|
+
r = r + s
|
|
1524
|
+
i = i + 1
|
|
1525
|
+
}
|
|
1526
|
+
return r
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
; Code points `a` up to `b` of `s`.
|
|
1530
|
+
sfn codeSlice:string (s:string a:int b:int) {
|
|
1531
|
+
return (utf8_substring s a b)
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
; `s.split_whitespace()`: the runs between White_Space characters.
|
|
1535
|
+
sfn splitWhitespace:[string] (s:string) {
|
|
1536
|
+
def res:[string]
|
|
1537
|
+
def cs:[int] (to_chars s)
|
|
1538
|
+
def n:int (array_length cs)
|
|
1539
|
+
def start:int -1
|
|
1540
|
+
def i:int 0
|
|
1541
|
+
while (i < n) {
|
|
1542
|
+
def ch:string (rs_char_from (itemAt cs i))
|
|
1543
|
+
if (RsChar.isWhitespace(ch)) {
|
|
1544
|
+
if (start >= 0) {
|
|
1545
|
+
push res (utf8_substring s start i)
|
|
1546
|
+
start = -1
|
|
1547
|
+
}
|
|
1548
|
+
} {
|
|
1549
|
+
if (start < 0) {
|
|
1550
|
+
start = i
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
i = i + 1
|
|
1554
|
+
}
|
|
1555
|
+
if (start >= 0) {
|
|
1556
|
+
push res (utf8_substring s start n)
|
|
1557
|
+
}
|
|
1558
|
+
return res
|
|
1559
|
+
}
|
|
1560
|
+
|
|
1561
|
+
; The UTF-8 byte offset of the first `p` in `s`, or -1.
|
|
1562
|
+
sfn findBytes:int (s:string p:string) {
|
|
1563
|
+
def idx:int (indexOf s p)
|
|
1564
|
+
if (idx < 0) {
|
|
1565
|
+
return -1
|
|
1566
|
+
}
|
|
1567
|
+
def head:string (substring s 0 idx)
|
|
1568
|
+
return (length (to_charbuffer head))
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
class RsChar {
|
|
1573
|
+
; `c.is_ascii_digit()`, `c.is_numeric()` (for the digits Rust's is_numeric
|
|
1574
|
+
; and ASCII agree on)
|
|
1575
|
+
sfn isAsciiDigit:boolean (c:string) {
|
|
1576
|
+
def k:int (rs_char_code c)
|
|
1577
|
+
return ((k >= 48) && (k <= 57))
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
sfn isAsciiAlpha:boolean (c:string) {
|
|
1581
|
+
def k:int (rs_char_code c)
|
|
1582
|
+
return (((k >= 65) && (k <= 90)) || ((k >= 97) && (k <= 122)))
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
sfn isAsciiUpper:boolean (c:string) {
|
|
1586
|
+
def k:int (rs_char_code c)
|
|
1587
|
+
return ((k >= 65) && (k <= 90))
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
sfn isAsciiLower:boolean (c:string) {
|
|
1591
|
+
def k:int (rs_char_code c)
|
|
1592
|
+
return ((k >= 97) && (k <= 122))
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
sfn isAsciiAlnum:boolean (c:string) {
|
|
1596
|
+
return ((RsChar.isAsciiAlpha(c)) || (RsChar.isAsciiDigit(c)))
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
sfn asciiUpper:string (c:string) {
|
|
1600
|
+
if (RsChar.isAsciiLower(c)) {
|
|
1601
|
+
return (rs_char_from ((rs_char_code c) - 32))
|
|
1602
|
+
}
|
|
1603
|
+
return c
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
sfn asciiLower:string (c:string) {
|
|
1607
|
+
if (RsChar.isAsciiUpper(c)) {
|
|
1608
|
+
return (rs_char_from ((rs_char_code c) + 32))
|
|
1609
|
+
}
|
|
1610
|
+
return c
|
|
1611
|
+
}
|
|
1612
|
+
|
|
1613
|
+
sfn isAsciiSpace:boolean (c:string) {
|
|
1614
|
+
def k:int (rs_char_code c)
|
|
1615
|
+
return ((k == 32) || (k == 9) || (k == 10) || (k == 12) || (k == 13))
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
; Rust's White_Space property.
|
|
1619
|
+
sfn isWhitespace:boolean (c:string) {
|
|
1620
|
+
def k:int (rs_char_code c)
|
|
1621
|
+
if (((k >= 9) && (k <= 13)) || (k == 32) || (k == 133) || (k == 160) || (k == 5760)) {
|
|
1622
|
+
return true
|
|
1623
|
+
}
|
|
1624
|
+
if (((k >= 8192) && (k <= 8202)) || (k == 8232) || (k == 8233) || (k == 8239) || (k == 8287) || (k == 12288)) {
|
|
1625
|
+
return true
|
|
1626
|
+
}
|
|
1627
|
+
return false
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1630
|
+
; A cased letter changes under one of the case maps; letters without case
|
|
1631
|
+
; are taken from the large scripts that have none (kana, CJK, Hangul).
|
|
1632
|
+
; Rust's `is_alphabetic` covers every script: this is the subset the
|
|
1633
|
+
; targets can test without a Unicode table.
|
|
1634
|
+
sfn isAlphabetic:boolean (c:string) {
|
|
1635
|
+
def k:int (rs_char_code c)
|
|
1636
|
+
if (k < 128) {
|
|
1637
|
+
return (RsChar.isAsciiAlpha(c))
|
|
1638
|
+
}
|
|
1639
|
+
if ((rs_upper c) != (rs_lower c)) {
|
|
1640
|
+
return true
|
|
1641
|
+
}
|
|
1642
|
+
if ((k == 170) || (k == 186) || (k == 223)) {
|
|
1643
|
+
return true
|
|
1644
|
+
}
|
|
1645
|
+
return (((k >= 12353) && (k <= 12543)) || ((k >= 13312) && (k <= 40959)) || ((k >= 44032) && (k <= 55215)))
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1648
|
+
sfn isAlphanumeric:boolean (c:string) {
|
|
1649
|
+
return ((RsChar.isAlphabetic(c)) || (RsChar.isAsciiDigit(c)))
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
sfn isUppercase:boolean (c:string) {
|
|
1653
|
+
return ((rs_lower c) != c)
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
sfn isLowercase:boolean (c:string) {
|
|
1657
|
+
def k:int (rs_char_code c)
|
|
1658
|
+
if (k == 223) {
|
|
1659
|
+
return true
|
|
1660
|
+
}
|
|
1661
|
+
return ((rs_upper c) != c)
|
|
1662
|
+
}
|
|
1663
|
+
}
|