<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Getting-Started on TrustLang</title>
		<link>https://trust-lang.net/ru/tags/getting-started/</link>
		<description>Recent content in Getting-Started on TrustLang</description>
		<generator>Hugo</generator>
		<language>ru</language>
		
		
		
		
			<atom:link href="https://trust-lang.net/ru/tags/getting-started/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>Playground and example code</title>
				<link>https://trust-lang.net/ru/playground/</link>
				<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
				<guid>https://trust-lang.net/ru/playground/</guid>
				<description>&lt;p&gt;Двухоконный playground (godbolt-стиль): слева - редактор Trust (подсветка и живая&#xA;пере-транспиляция), справа - генерируемый C++. Клик по строке в одном окне&#xA;подсвечивает соответствующие строки в противоположной. Примеры выбираются в&#xA;комбобоксе над Trust-редактором.&lt;/p&gt;&#xA;&lt;style&gt;&#xA;/* Playground CSS (godbolt-стиль). Встраивается в html_emit.cpp через #embed.&#xA;   Светлые дефолты; сайт может переопределить --tpl-* в своём CSS (общая тема). */&#xA;.tpl-pg{--tpl-bg:var(--site-bg,#ffffff);--tpl-text:var(--site-text,#24292f);--tpl-gutter:var(--site-muted,#6b7280);--tpl-border:var(--site-border,#d1d5db);--tpl-toolbar:var(--site-toolbar,#f6f8fa);--tpl-linked:var(--site-linked,#fff3bf);--tpl-error:var(--site-error,#dc2626);display:flex;flex-direction:column;gap:6px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;background:var(--tpl-bg);color:var(--tpl-text);padding:8px;border:1px solid var(--tpl-border);border-radius:6px;box-sizing:border-box;height:calc(100vh - 11rem);height:calc(100dvh - 11rem);min-height:540px;}&#xA;.tpl-row{display:flex;gap:0;flex:1 1 auto;min-height:0;}&#xA;.tpl-pane{flex:1 1 0;display:flex;flex-direction:column;min-width:0;position:relative;border:1px solid var(--tpl-border);border-radius:4px;overflow:hidden;}&#xA;/* Изменяемый размер: вертикальный сплиттер между Trust и Generated C++,&#xA;   горизонтальный - над окном лога. */&#xA;.tpl-splitter-v{width:6px;cursor:col-resize;flex:none;background:var(--tpl-toolbar);user-select:none;}&#xA;.tpl-splitter-v:hover{background:var(--tpl-border);}&#xA;.tpl-splitter-h{height:6px;cursor:row-resize;flex:none;background:var(--tpl-toolbar);user-select:none;}&#xA;.tpl-splitter-h:hover{background:var(--tpl-border);}&#xA;.tpl-toolbar{padding:4px 8px;background:var(--tpl-toolbar);font-size:12px;font-weight:600;user-select:none;display:flex;align-items:center;gap:8px;}&#xA;.tpl-examples{font-size:12px;font-weight:400;max-width:260px;background:var(--tpl-bg);color:var(--tpl-text);border:1px solid var(--tpl-border);border-radius:3px;}&#xA;.tpl-editor{flex:1;min-height:0;}&#xA;.tpl-status{min-height:1.2em;font-size:12px;color:var(--tpl-gutter);white-space:pre-wrap;}&#xA;.tpl-status.tpl-error{color:var(--tpl-error);}&#xA;.tpl-status a.tpl-copy{color:var(--tpl-gutter);cursor:pointer;text-decoration:underline;white-space:nowrap;}&#xA;.tpl-status a.tpl-copy:hover{color:var(--tpl-text);}&#xA;/* Индикатор связи песочницы с балансировщиком (публичный пинг /health): онлайн/деградация/нет связи. */&#xA;.tpl-health{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;color:var(--tpl-text);white-space:nowrap;}&#xA;.tpl-health .dot{width:9px;height:9px;border-radius:50%;background:var(--tpl-gutter);flex:none;}&#xA;.tpl-health.ok .dot{background:#2e7d32;}&#xA;.tpl-health.degraded .dot{background:#ef6c00;}&#xA;.tpl-health.down .dot{background:var(--tpl-error);}&#xA;.tpl-linked{background:var(--tpl-linked);}&#xA;.tpl-gutter{box-shadow:inset 3px 0 0 var(--tpl-text);opacity:.55;}&#xA;.tpl-follow{font-size:12px;font-weight:400;display:flex;align-items:center;gap:4px;margin-left:auto;cursor:pointer;user-select:none;}&#xA;.tpl-follow input{accent-color:var(--tpl-text);cursor:pointer;}&#xA;.tpl-btn{font-size:12px;padding:3px 10px;background:var(--tpl-toolbar);color:var(--tpl-text);border:1px solid var(--tpl-border);border-radius:4px;cursor:pointer;text-decoration:none;font-weight:600;}&#xA;.tpl-btn-disabled{opacity:.6;pointer-events:none;}&#xA;.tpl-log{height:120px;min-height:40px;flex:none;overflow:auto;font-size:12px;color:var(--tpl-text);background:var(--tpl-bg);border:1px solid var(--tpl-border);border-radius:4px;padding:6px;white-space:pre-wrap;}&#xA;/* Строки лога: кликабельные заголовки диагностик (переход на строку в исходнике). */&#xA;.tpl-logline{min-height:1.1em;}&#xA;.tpl-log-link{cursor:pointer;text-decoration:underline;text-decoration-style:dotted;}&#xA;.tpl-log-error{color:var(--tpl-error);}&#xA;.tpl-log-warn{color:var(--tpl-text);}&#xA;/* Оверлей правой панели: центрированное сообщение об ошибке/нет связи с сервером&#xA;   песочницы. По умолчанию скрыт (display:none), включается из glue-JS. */&#xA;.tpl-overlay{position:absolute;top:0;left:0;right:0;bottom:0;display:none;align-items:center;justify-content:center;padding:16px;text-align:center;background:var(--tpl-bg);color:var(--tpl-error);font-size:14px;line-height:1.5;z-index:10;}&#xA;&lt;/style&gt;&#xA;&lt;!-- Playground HTML-каркас (godbolt-стиль). Встраивается в html_emit.cpp через #embed.&#xA;     Статичен: динамические части (конфиг/Monarch/glue-JS) вставляются в C++ отдельным &lt;script&gt;. --&gt;&#xA;&lt;div class=&#34;tpl-pg&#34; id=&#34;trust-playground&#34;&gt;&#xA;&lt;div class=&#34;tpl-row&#34;&gt;&#xA;  &lt;div class=&#34;tpl-pane&#34;&gt;&lt;div class=&#34;tpl-toolbar&#34;&gt;Trust&lt;select id=&#34;tpl-examples&#34; class=&#34;tpl-examples&#34; title=&#34;Load example&#34;&gt;&lt;/select&gt;&lt;/div&gt;&lt;div id=&#34;tpl-trust-editor&#34; class=&#34;tpl-editor&#34;&gt;&lt;/div&gt;&lt;/div&gt;&#xA;  &lt;div class=&#34;tpl-splitter-v&#34; id=&#34;tpl-split-v&#34;&gt;&lt;/div&gt;&#xA;  &lt;div class=&#34;tpl-pane&#34;&gt;&lt;div class=&#34;tpl-toolbar&#34;&gt;Generated C++&lt;a id=&#34;tpl-download&#34; class=&#34;tpl-btn tpl-btn-disabled&#34; href=&#34;#&#34; title=&#34;Download build archive&#34;&gt;&amp;#11015; Download archive&lt;/a&gt;&lt;label id=&#34;tpl-follow&#34; class=&#34;tpl-follow&#34; title=&#34;Follow the selected line (scroll the other pane to it)&#34;&gt;&lt;input type=&#34;checkbox&#34; id=&#34;tpl-follow-cb&#34; checked&gt;follow&lt;/label&gt;&lt;/div&gt;&lt;div id=&#34;tpl-cpp-editor&#34; class=&#34;tpl-editor&#34;&gt;&lt;/div&gt;&lt;div id=&#34;tpl-cpp-overlay&#34; class=&#34;tpl-overlay&#34;&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;div class=&#34;tpl-splitter-h&#34; id=&#34;tpl-split-h&#34;&gt;&lt;/div&gt;&#xA;&lt;div id=&#34;tpl-log&#34; class=&#34;tpl-log&#34;&gt;&lt;/div&gt;&#xA;&lt;div class=&#34;tpl-toolbar&#34; style=&#34;border-top:1px solid var(--tpl-border);&#34;&gt;&lt;span id=&#34;tpl-health&#34; class=&#34;tpl-health&#34;&gt;&lt;span class=&#34;dot&#34;&gt;&lt;/span&gt;&lt;span id=&#34;tpl-health-text&#34;&gt;…&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&#xA;&lt;div id=&#34;tpl-status&#34; class=&#34;tpl-status&#34;&gt;&lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;script&gt;&#xA;window.__TPG = window.__TPG || {};&#xA;window.__TPG.config = {&#34;monacoUrl&#34;:&#34;/monaco/vs&#34;,&#34;serverUrl&#34;:&#34;https://playground.trust-lang.net/run&#34;,&#34;source&#34;:&#34;#!../_build/trust --run\n#\n# Launching the program as a bash script that automatically compiles the C++ code \n# on the first run and subsequently executes the binary file. \n# Automatic recompilation occurs whenever the source code changes.\n#\n# Importing and calling native functions from the C++ standard library.\n# \&#34;Hello, world!\&#34; and checking argument types against the printf format string.\n\n@[ format(\&#34;printf\&#34;, 1, 2) @]\n%printf(fmt:@[ reftype(ptr) @] StrChar^, ...):Int32 := ...;\n\nпривет := &#39;Привет&#39;;\nмир := &#39;мир&#39;;\nмир_size := мир.size();\n\n%printf(&#39;%s %s!\\n&#39;, привет.c_str(), мир.%c_str());\n%printf(&#39;Длина строки: %zu + %zu + 1 = %d\\n&#39;, привет.size(), {% $мир_size %}, :Int32(привет.%size() + мир_size + 1));\n\n%printf(&#39;Строка: \&#34;%s\&#34;\\n&#39;, &#39;это строковый аргумент&#39;);\n\n# Invalid calls – compile-time errors (format attribute):\n# %printf(&#39;Ошибка: %s\\n&#39;, 42);\n# %printf(&#39;Ошибка: %d\\n&#39;, &#39;строка&#39;);\n# %printf(&#39;Ошибка: %s\\n&#39;, строка);\n\n\nforward %labs(x:Int64):Int64;\nextern abs(x:Int32):Int32;\n\n@print(&#39;abs(-42)={}\\n&#39;, abs(-42));\n@print(&#39;labs(-9000000000)={}\\n&#39;, %labs(-9000000000));\n\nsum:Int32 := 0;\ni:Int32 := -3;\nwhile (i \u003c= 3) {\n    sum += abs(i);\n    i += 1;\n};\n@print(&#39;sum of abs(-3..3)={}\\n&#39;, sum);\n&#34;,&#34;examples&#34;:[{&#34;name&#34;:&#34;dict&#34;,&#34;source&#34;:&#34;#!../_build/trust --run -Wembed=ignore -Wsigil=ignore \n#\n# Example of using the Dict: literal `(1, two=2, name=&#39;3&#39;,)`\n# Ways to access elements:\n#   d.name - by name; \n#   d.1 - static index;\n#   d[0]   - dynamic index (runtime check).\n# Adding elements - `[]=` operator (append/push_back).\n#\n# Command-line arguments\n@main(argv^: Dict, args^: Dict) := {\n\n    @print(&#39;argv.size()={}\\n&#39;, $argv.size());\n    @print(&#39;args.size()={}\\n&#39;, $args.size());\n    @print(&#39;argv={}\\n&#39;, argv);\n    @print(&#39;args={}\\n&#39;, args);\n\n    d := (1, two=2, name=&#39;3&#39;,);\n\n    @print(&#39;size={}\\n&#39;, :Int32( {% $d.size() %} ));\n    @print(&#39;first={}\\n&#39;, :Int32( d[0] ));\n    @print(&#39;one={}\\n&#39;,   :Int32( d.1 ));\n    @print(&#39;two={}\\n&#39;,   :Int32( d.two ));\n    @print(&#39;name={}\\n&#39;,  d.name);\n\n    # Static index d.4 is missing (compilation error):\n    # print(&#39;one={}\\n&#39;,    d.4);\n\n    # Adding elements using the `[]=` operator\n    d []= 999;\n    d []= &#39;строка&#39;;\n\n    # Dictionary size increased by 2. (static check)\n    @print(&#39;size_after_append={}\\n&#39;, $d.size());\n    \n    @print(&#39;appended_int={}\\n&#39;, d[3]);\n    # Static index d.4 is now allowed (size increased to 5).\n    @print(&#39;appended_str={}\\n&#39;, d.4);\n\n    # Dictionary merging via `...` unpacking: `d[] = ...dict` adds ALL elements of the operand\n    extra := (e=6, 7,);\n    d []= ... extra;          # add full dictionary\n    d []= ... (последний=8,); # add a single named element to the dictionary\n\n    @print(&#39;size_final={}\\n&#39;, $d.size());  # 5 + 2 + 1 = 8\n    @print(&#39;e={}, {}\\n&#39;, d.e, d.6);    # access to the merged dictionary by name and index\n\n    # The same element at static index d.7 (8th element)\n    @print(&#39;последний={}\\n&#39;, d.7);\n\n    # Print the entire dictionary\n    @print(&#39;{}\\n&#39;, d);\n\n    @return 0;\n}\n\n&#34;},{&#34;name&#34;:&#34;fibonacci&#34;,&#34;source&#34;:&#34;#!../_build/trust --run --stack-check=explicit -Wsigil=ignore\n#\n# Arbitrary-precision Fibonacci numbers\n#\n# The recursive fib() uses stack overflow protection (the @[stack_check@] attribute and --stack-check=explicit mode).\n# Before a stack overflow occurs, a software interrupt is generated instead of a segfault;\n# this interrupt is caught using the try ... catch.\n\n@func parse_bigint(s:StrChar):BigInteger {\n    try {\n        {% return trust::BigInteger(c_s); %};\n    } catch(:StdException) {\n        return :BigInteger(-1);\n    };\n    return :BigInteger(-1);\n};\n\n@[ stack_check @]\n%fib(n:BigInteger):Tuple(sum:BigInteger, fib:BigInteger) := {\n    if (n \u003c 3) {\n        $one:BigInteger := 1;\n        return :Tuple($one, $one);\n    };\n    p := fib(n - 1);\n    return (p.0 + p.1, p.sum,):Tuple;\n};\n\n%calc(n:BigInteger):Void := {\n    result := fib(n);\n    $value := &#39;{0}&#39;(result.fib);\n    @print(&#39;{}: {}\\n{}\\n&#39;, n, $value.size(), $value);\n};\n\n@main(argv^:Dict, args^:Dict) := {\n\n    if (:Int32({% $argv.size() %}) \u003c 1) {\n        @print(&#39;Usage: fibonacci \u003cn&gt;\\n&#39;);\n        @print(&#39;  \u003cn&gt; - compute the n-th Fibonacci number (&gt; 0)\\n&#39;);\n        return 1;\n    };\n    $n := parse_bigint(:StrChar(argv[0]));\n    if ($n \u003c 1) {\n        @print(&#39;Error: invalid \u003cn&gt;: \&#34;{}\&#34; (expected integer &gt; 0)\\n&#39;, argv[0]);\n        return 1;\n    };\n\n    try_error {\n        calc($n);\n    } catch(_) {\n        @print(&#39;STACK OVERFLOW caught computing fibonacci({})\\n&#39;, $n);\n    };\n    return 0;\n};\n&#34;},{&#34;name&#34;:&#34;hello&#34;,&#34;source&#34;:&#34;#!../_build/trust --run\n#\n# Launching the program as a bash script that automatically compiles the C++ code \n# on the first run and subsequently executes the binary file. \n# Automatic recompilation occurs whenever the source code changes.\n#\n# Importing and calling native functions from the C++ standard library.\n# \&#34;Hello, world!\&#34; and checking argument types against the printf format string.\n\n@[ format(\&#34;printf\&#34;, 1, 2) @]\n%printf(fmt:@[ reftype(ptr) @] StrChar^, ...):Int32 := ...;\n\nпривет := &#39;Привет&#39;;\nмир := &#39;мир&#39;;\nмир_size := мир.size();\n\n%printf(&#39;%s %s!\\n&#39;, привет.c_str(), мир.%c_str());\n%printf(&#39;Длина строки: %zu + %zu + 1 = %d\\n&#39;, привет.size(), {% $мир_size %}, :Int32(привет.%size() + мир_size + 1));\n\n%printf(&#39;Строка: \&#34;%s\&#34;\\n&#39;, &#39;это строковый аргумент&#39;);\n\n# Invalid calls – compile-time errors (format attribute):\n# %printf(&#39;Ошибка: %s\\n&#39;, 42);\n# %printf(&#39;Ошибка: %d\\n&#39;, &#39;строка&#39;);\n# %printf(&#39;Ошибка: %s\\n&#39;, строка);\n\n\nforward %labs(x:Int64):Int64;\nextern abs(x:Int32):Int32;\n\n@print(&#39;abs(-42)={}\\n&#39;, abs(-42));\n@print(&#39;labs(-9000000000)={}\\n&#39;, %labs(-9000000000));\n\nsum:Int32 := 0;\ni:Int32 := -3;\nwhile (i \u003c= 3) {\n    sum += abs(i);\n    i += 1;\n};\n@print(&#39;sum of abs(-3..3)={}\\n&#39;, sum);\n&#34;},{&#34;name&#34;:&#34;prime&#34;,&#34;source&#34;:&#34;#!../_build/trust --run -Wsigil=ignore -Wembed=ignore --stack-check=explicit\n#\n# Recursive primality test with stack overflow protection and\n# a performance comparison between standard and protected implementations.\n#\n# Works with arbitrary-precision integers (BigInteger); the initial number\n# can far exceed the limits of an Int64.\n#\n# If free space runs low (i.e., *before* an actual stack overflow and crash occurs),\n# a standard software exception is thrown and caught via a try { ... } catch(_){ ... } block.\n\n# Native function for measuring execution speed\n@forward %clock():Int64;\n\n# Helper functions\n@func parse_i64(s:StrChar):Int64 {\n    try {\n        {% return (int64_t)std::stoll(c_s); %};\n    } catch(:StdException) {\n        return -1;\n    };\n    return -1;\n};\n\n@func parse_bigint(s:StrChar):BigInteger {\n    try {\n        {% return trust::BigInteger(c_s); %};\n    } catch(:StdException) {\n        return :BigInteger(-1);\n    };\n    return :BigInteger(-1);\n};\n\n# Recursion depth and call count counters\ncurrentDepth:Int64 := 0;\nmaxDepth:Int64 := 0;\ncallCount:Int64 := 0;\n\n# Macro to define a function for the recursive primality test\n@@ primeFn $fname @@\n@func @$fname(n:BigInteger, divisor:BigInteger):Bool {\n    callCount = callCount + 1;\n    currentDepth = currentDepth + 1;\n    if (currentDepth &gt; maxDepth) {\n        maxDepth = currentDepth;\n    };\n    if (n \u003c 2) {\n        currentDepth = currentDepth - 1;\n        @return false;\n    };\n    if (divisor &gt; n / divisor) {\n        currentDepth = currentDepth - 1;\n        @return true;\n    };\n    if ((n / divisor) * divisor == n) {\n        currentDepth = currentDepth - 1;\n        @return false;\n    };\n    $r := @$fname(n, divisor + 1);\n    currentDepth = currentDepth - 1;\n    return $r;\n};\n@@@@;\n\n# Function without stack overflow checking\n@primeFn isPrime;\n\n# Function with stack overflow protection\n@[ stack_check @]\n@primeFn isPrimeSafe;\n\n\n@main(argv^:Dict, args^:Dict) := {\n    if (:Int32({% $argv.size() %}) \u003c 2) {\n        @print(&#39;Usage: prime \u003cstart_number&gt; \u003ccount&gt;\\n&#39;);\n        @print(&#39;  \u003cstart_number&gt; - start number (&gt;= 2), BigInteger\\n&#39;);\n        @print(&#39;  \u003ccount&gt;        - how many primes to find (&gt; 0)\\n&#39;);\n        @return 1;\n    };\n    $start := parse_bigint(:StrChar(argv[0]));\n    $count := parse_i64(:StrChar(argv[1]));\n    if ($start \u003c 2) {\n        @print(&#39;Error: invalid \u003cstart_number&gt;: \&#34;{}\&#34; (expected integer &gt;= 2)\\n&#39;, argv[0]);\n        return 1;\n    };\n    if ($count \u003c 1) {\n        @print(&#39;Error: invalid \u003ccount&gt;: \&#34;{}\&#34; (expected integer &gt; 0)\\n&#39;, argv[1]);\n        return 1;\n    };\n\n    @print(&#39;Searching for {} primes starting from {}:\\n&#39;, $count, $start);\n\n    # The first call to the protected function checks whether the stack size is sufficient for the entire call depth.\n    callCount = 0;\n    maxDepth = 0;\n    currentDepth = 0;\n    $t0 := %clock();\n    try_error {\n        \n        $n := $start;\n        $found := 0;\n        while ($found \u003c $count) {\n            if (isPrimeSafe($n, 2)) {\n                @print(&#39;  prime: {}\\n&#39;, $n);\n                $found += 1;\n            };\n            $n += 1;\n        };\n\n        # Copy the statistics of the protected version into local variables.\n        $t1 := %clock();\n        $safeMax := maxDepth;\n        $safeCalls := callCount;\n    } catch(_) {\n\n        # Handling any exception (in this case, a stack overflow)\n        @print(&#39;safe: STACK OVERFLOW caught at max depth={}, calls={}\\n&#39;, maxDepth, callCount);\n        @print(&#39;safe: time until overflow = {} ticks\\n&#39;, %clock() - $t0);\n        @return 0;\n\n    } else {\n\n        @print(&#39;safe: completed, max depth={}, calls={}, time={} ticks\\n&#39;, $safeMax, $safeCalls, $t1 - $t0);\n\n        # The UNPROTECTED version executes only if the function with stack overflow protection has completed successfully.\n        callCount = 0;\n        maxDepth = 0;\n        currentDepth = 0;\n        $t2 := %clock();\n        $n2 := $start;\n        $found2 := 0;\n        while ($found2 \u003c $count) {\n            if (isPrime($n2, 2)) {\n                @print(&#39;  prime: {}\\n&#39;, $n2);\n                $found2 += 1;\n            };\n            $n2 += 1;\n        };\n        $t3 := %clock();\n        $unprotMax := maxDepth;\n        $unprotCalls := callCount;\n        @print(&#39;unprotected: completed, max depth={}, calls={}, time={} ticks\\n&#39;, $unprotMax, $unprotCalls, $t3 - $t2);\n\n        $du := $t3 - $t2;\n        if ($du &gt; 0) {\n            @print(&#39;difference: protected is {:.2f}% slower\\n&#39;,1000.0*($t1 - $t0 - $du) / (10 * $du));\n        };\n        return 0;\n    };\n}\n&#34;},{&#34;name&#34;:&#34;rational&#34;,&#34;source&#34;:&#34;#!../_build/trust --run -Wsigil=ignore -Wembed=ignore\n\n$fact := 1\\1;\t# Autotyping \n$mult:Int32 := 1; # Fixed type\n\nwhile( mult \u003c= 1000 ) {\n    fact *= mult;\n    {% $mult++; %};  \t# Increment as C++ embedded\n};\n\n# factorial 1000!\ntest := 402387260077093773543702433923003985719374864210714632\\\n54379991042993851239862902059204420848696940480047998861019719605863166\\\n68729948085589013238296699445909974245040870737599188236277271887325197\\\n79505950995276120874975462497043601418278094646496291056393887437886487\\\n33711918104582578364784997701247663288983595573543251318532395846307555\\\n74091142624174743493475534286465766116677973966688202912073791438537195\\\n88249808126867838374559731746136085379534524221586593201928090878297308\\\n43139284440328123155861103697680135730421616874760967587134831202547858\\\n93207671691324484262361314125087802080002616831510273418279777047846358\\\n68170164365024153691398281264810213092761244896359928705114964975419909\\\n34222156683257208082133318611681155361583654698404670897560290095053761\\\n64758477284218896796462449451607653534081989013854424879849599533191017\\\n23355556602139450399736280750137837615307127761926849034352625200015888\\\n53514733161170210396817592151090778801939317811419454525722386554146106\\\n28921879602238389714760885062768629671466746975629112340824392081601537\\\n80889893964518263243671616762179168909779911903754031274622289988005195\\\n44441428201218736174599264295658174662830295557029902432415318161721046\\\n58320367869061172601587835207515162842255402651704833042261439742869330\\\n61690897968482590125458327168226458066526769958652682272807075781391858\\\n17888965220816434834482599326604336766017699961283186078838615027946595\\\n51311565520360939881806121385586003014356945272242063446317974605946825\\\n73103790084024432438465657245014402821885252470935190620929023136493273\\\n49756551395872055965422874977401141334696271542284586237738753823048386\\\n56889764619273838149001407673104466402598994902222217659043399018860185\\\n66526485061799702356193897017860040811889729918311021171229845901641921\\\n06888438712185564612496079872290851929681937238864261483965738229112312\\\n50241866493531439701374285319266498753372189406942814341185201580141233\\\n44828015051399694290153483077644569099073152433278288269864602789864321\\\n13908350621709500259738986355427719674282224875758676575234422020757363\\\n05694988250879689281627538488633969099598262809561214509948717012445164\\\n61260379029309120889086942028510640182154399457156805941872748998094254\\\n74217358240106367740459574178516082923013535808184009699637252423056085\\\n59037006242712434169090041536901059339838357779394109700277534720000000\\\n00000000000000000000000000000000000000000000000000000000000000000000000\\\n00000000000000000000000000000000000000000000000000000000000000000000000\\\n00000000000000000000000000000000000000000000000000000000000000000000000\\\n00000000000000000000000000000;\n\n\n# Check factorial 1000!\nassert( fact == test, &#39;{} != {}&#39;, fact.display(8), test.display(8));\n\n# Print result\n@print(&#39;{}\\n&#39;, fact);\n\n&#34;},{&#34;name&#34;:&#34;refs&#34;,&#34;source&#34;:&#34;#!../_build/trust --run -Wsigil=ignore\n#\n# Concept syntax case for working with reference variables\n# The reference type can appear before the variable name (and/or before the type):\n#   `&amp;*` - shared (shared ownership),\n#   `&amp;&amp;` - unique (exclusive ownership; inline, zero-cost),\n#   `&amp;?` - weak   (weak reference; created from shared via `&amp; var`).\n#\n# Accessing data via a reference (dereferencing) `*var`\n# Swap operator `:=:`:\n#   `a :=: b`   - swap references of the same type (std::swap);\n#   `*a :=: *b` - swap VALUES (pointees) referenced by the pointers, including references of DIFFERENT types.\n# `with(l1 = *r1, l2 = *r2) { ... }` - simultaneous acquisition (locking) of multiple\n# references for the duration of the block.\n\n@main():Int32 := {\n    &amp;* s := 5:Int32;              # shared\n    &amp;? w := &amp; s;                  # weak (из shared через address-of `&amp; s`)\n    &amp;&amp; u := 10:Int32;             # unique\n\n    @print(&#39;s={} w={} u={}\\n&#39;, *s, *w, *u);\n\n    *s = 7;\n    @print(&#39;s=7 -&gt; w={} (weak видит тот же объект)\\n&#39;, *w);\n\n    *u = 11;\n    @print(&#39;unique={}\\n&#39;, *u);\n\n    &amp;* a := 1:Int32;\n    &amp;* b := 2:Int32;\n    a :=: b;\n    @print(&#39;swap refs (a\u003c-&gt;b): a={} b={}\\n&#39;, *a, *b);\n\n    &amp;? c := &amp; a;\n    @print(&#39;weak c={}\\n&#39;, *c);\n\n    &amp;* p := 100:Int32;            # shared\n    &amp;&amp; q := 200:Int32;            # unique\n    @print(&#39;value-swap before: *p={} *q={}\\n&#39;, *p, *q);\n    *p :=: *q;                    # std::swap data (not reference)\n    @print(&#39;value-swap after : *p={} *q={}\\n&#39;, *p, *q);\n\n    # with: simultaneous acquisition (locking) of multiple references\n    &amp;* m := 1:Int32;\n    &amp;* n := 2:Int32;\n    with(lm = *m, ln = *n) {\n        lm = lm + 10;\n        ln = ln + 20;\n    } else {\n        @print(&#39;capture failed\\n&#39;);\n    };\n    @print(&#39;after with: m={} n={}\\n&#39;, *m, *n);\n\n    return 0;\n}\n&#34;}]};&#xA;window.__TPG.monarch = function () { return (    {&#xA;      defaultToken: &#39;&#39;,&#xA;        tokenizer: {&#xA;          root: [&#xA;            [/\/\*/, &#39;comment.block&#39;, &#39;@comment&#39;],&#xA;            [/#.*$/, &#39;comment.line&#39;],&#xA;            [/@\w[\w_]*/, &#39;keyword.macro&#39;],&#xA;            [/@[{}[\]&lt;&gt;:|]/, &#39;keyword.control&#39;],&#xA;            [/\$\$|\$\*|\$\.\.\.|\$\^/, &#39;variable.language&#39;],&#xA;            [/\$\d+/, &#39;variable.language&#39;],&#xA;            [/\$[A-Za-z_]\w*/, &#39;variable&#39;],&#xA;            [/:[A-Za-z_]\w*/, &#39;type&#39;],&#xA;            [/%[A-Za-z_]\w*/, &#39;keyword.function&#39;],&#xA;            [/R&#34;[\s\S]*?&#34;/, &#39;string.raw&#39;],&#xA;            [/R&#39;[\s\S]*?&#39;/, &#39;string.raw&#39;],&#xA;            [/`[^`]*`/, &#39;string&#39;],&#xA;            [/&#34;/, &#39;string.double&#39;, &#39;@str_d&#39;],&#xA;            [/&#39;/, &#39;string.single&#39;, &#39;@str_s&#39;],&#xA;            [/-?\d[\d_]*\.\d+([eE][-+]?\d+)?|-?\d[\d_]*([eE][-+]?\d+)?/, &#39;number&#39;],&#xA;            [/[a-zA-Z_]\w*/, &#39;identifier&#39;],&#xA;            [/[{}()\[\]]/, &#39;@brackets&#39;],&#xA;            [/[=:;,.+\-*\/%&amp;|^~!&lt;&gt;]+/, &#39;operator&#39;],&#xA;            [/\s+/, &#39;white&#39;]&#xA;          ],&#xA;          comment: [&#xA;            [/[^/*]+/, &#39;comment.block&#39;],&#xA;            [/\/\*/, &#39;comment.block&#39;, &#39;@push&#39;],&#xA;            [/\*\//, &#39;comment.block&#39;, &#39;@pop&#39;],&#xA;            [/[/*]/, &#39;comment.block&#39;]&#xA;          ],&#xA;          str_d: [&#xA;            [/[^&#34;\\]+/, &#39;string.double&#39;],&#xA;            [/\\./, &#39;string.escape&#39;],&#xA;            [/&#34;/, &#39;string.double&#39;, &#39;@pop&#39;]&#xA;          ],&#xA;          str_s: [&#xA;            [/[^&#39;\\]+/, &#39;string.single&#39;],&#xA;            [/\\./, &#39;string.escape&#39;],&#xA;            [/&#39;/, &#39;string.single&#39;, &#39;@pop&#39;]&#xA;          ]&#xA;        }&#xA;    }&#xA;); };&#xA;window.__TPG.glue = function (m) { var __MONARCH__ = m;   (function () {&#xA;    var cfg = window.__TPG &amp;&amp; window.__TPG.config;&#xA;    if (!cfg) { return; }&#xA;    // Origin бэкенда (для абсолютных URL: /download живёт на балансировщике, а страница - на статике).&#xA;    var serverOrigin = &#39;&#39;;&#xA;    try { serverOrigin = new URL(cfg.serverUrl, location.href).origin; } catch (e) { serverOrigin = &#39;&#39;; }&#xA;    var trustHost = document.getElementById(&#39;tpl-trust-editor&#39;);&#xA;    var cppHost = document.getElementById(&#39;tpl-cpp-editor&#39;);&#xA;    var status = document.getElementById(&#39;tpl-status&#39;);&#xA;    var healthEl = document.getElementById(&#39;tpl-health&#39;);&#xA;    var healthText = document.getElementById(&#39;tpl-health-text&#39;);&#xA;    var examplesSel = document.getElementById(&#39;tpl-examples&#39;);&#xA;    var log = document.getElementById(&#39;tpl-log&#39;);&#xA;    var downloadBtn = document.getElementById(&#39;tpl-download&#39;);&#xA;    var followCb = document.getElementById(&#39;tpl-follow-cb&#39;);&#xA;    var cppOverlay = document.getElementById(&#39;tpl-cpp-overlay&#39;);&#xA;    if (!trustHost || !cppHost) { return; }&#xA;&#xA;    // Редакторы создаются в Monaco-колбэке; вынесены в область видимости glue,&#xA;    // чтобы к ним был доступ и из обработчиков комбобокса.&#xA;    var trustEditor = null, cppEditor = null;&#xA;&#xA;    // Исходник последнего загруженного примера (для детекции изменений текста).&#xA;    var loadedSource = cfg.source;&#xA;    // Индекс текущего выбранного примера в комбобоксе (для отката при отмене).&#xA;    var curExIndex = -1;&#xA;    // Имя текущего выбранного примера (для кеша на балансировщике: X-Example-Name).&#xA;    var curExampleName = &#39;&#39;;&#xA;&#xA;    // --- Опциональные URL-параметры песочницы ---&#xA;    // Позволяют открыть страницу в конкретном состоянии:&#xA;    //   file=&lt;имя примера&gt;    - выбрать предопределённый файл из cfg.examples&#xA;    //   win=src|cppt          - активное окно (Trust | Generated C++); default src&#xA;    //   line=&lt;n&gt;, col=&lt;m&gt;     - позиция курсора (1-based; col default 1)&#xA;    //   toLine=&lt;n&gt;, toCol=&lt;m&gt; - конец диапазона выделения (если заданы -&gt; выделение)&#xA;    // Все параметры опциональны; если line отсутствует - позицию не трогаем.&#xA;    function parseUrlParams() {&#xA;      var q = {};&#xA;      var s = (location.search || &#39;&#39;).replace(/^[?]/, &#39;&#39;);&#xA;      if (!s) { return q; }&#xA;      var parts = s.split(&#39;&amp;&#39;);&#xA;      for (var i = 0; i &lt; parts.length; i++) {&#xA;        var kv = parts[i].split(&#39;=&#39;);&#xA;        if (!kv[0]) { continue; }&#xA;        var k, v = &#39;&#39;;&#xA;        try { k = decodeURIComponent(kv[0].replace(/\+/g, &#39; &#39;)); } catch (e) { continue; }&#xA;        if (kv.length &gt; 1) { try { v = decodeURIComponent(kv.slice(1).join(&#39;=&#39;).replace(/\+/g, &#39; &#39;)); } catch (e) {} }&#xA;        q[k] = v;&#xA;      }&#xA;      return q;&#xA;    }&#xA;    var urlParams = parseUrlParams();&#xA;    // Инициализируемый по URL пример (заполняется в populateExamples, читается в initEditors).&#xA;    var initialExample = null;&#xA;    function urlPos(v) { var n = parseInt(v, 10); return (isFinite(n) &amp;&amp; n &gt; 0) ? n : 0; }&#xA;    var initLine = urlPos(urlParams.line);&#xA;    var initCol = urlPos(urlParams.col) || 1;&#xA;    var initToLine = urlPos(urlParams.toLine);&#xA;    var initToCol = urlPos(urlParams.toCol) || 1;&#xA;    // Окно, в которое ставим начальный курсор/выделение.&#xA;    var initWindow = (urlParams.win === &#39;cppt&#39; || urlParams.win === &#39;cpp&#39;) ? &#39;cppt&#39; : &#39;src&#39;;&#xA;    // Окно, в котором находится курсор (для построения share-URL). default src.&#xA;    var activeWindow = &#39;src&#39;;&#xA;    // Применено ли начальное состояние (cppt применяется после первой пере-транспиляции).&#xA;    var initApplied = false;&#xA;&#xA;    // Применяет начальную позицию/выделение к указанному редактору, если окно совпало.&#xA;    function applyInitialPosition(editor, which) {&#xA;      if (which !== initWindow || initApplied) { return; }&#xA;      if (!initLine || !editor || !editor.setPosition) { return; }&#xA;      if (initLine &gt; editor.getModel().getLineCount()) { return; }&#xA;      activeWindow = which;&#xA;      if (initToLine) {&#xA;        editor.setSelection(new monaco.Range(initLine, initCol, initToLine, initToCol));&#xA;      } else {&#xA;        editor.setPosition({ lineNumber: initLine, column: initCol });&#xA;      }&#xA;      editor.revealLineInCenter(initLine);&#xA;      editor.focus();&#xA;      initApplied = true;&#xA;    }&#xA;&#xA;    // Строит URL текущего состояния песочницы для копирования в буфер обмена.&#xA;    // file включается только если текст не изменён относительно загруженного примера&#xA;    // (иначе комбобокс показал бы «Custom», и file-параметр был бы некорректен).&#xA;    function buildShareUrl() {&#xA;      var ed = (activeWindow === &#39;cppt&#39;) ? cppEditor : trustEditor;&#xA;      var base = location.href.split(&#39;#&#39;)[0].split(&#39;?&#39;)[0];&#xA;      var parts = [];&#xA;      function add(k, v) { if (v !== &#39;&#39; &amp;&amp; v != null) { parts.push(encodeURIComponent(k) + &#39;=&#39; + encodeURIComponent(v)); } }&#xA;      var fname = &#39;&#39;;&#xA;      if (curExampleName) {&#xA;        var txt = (trustEditor &amp;&amp; trustEditor.getValue) ? trustEditor.getValue() : &#39;&#39;;&#xA;        if (txt === loadedSource) { fname = curExampleName; }&#xA;      }&#xA;      add(&#39;file&#39;, fname);&#xA;      add(&#39;win&#39;, activeWindow);&#xA;      if (ed &amp;&amp; ed.getSelection) {&#xA;        var sel = ed.getSelection();&#xA;        if (sel) {&#xA;          add(&#39;line&#39;, sel.startLineNumber);&#xA;          add(&#39;col&#39;, sel.startColumn);&#xA;          if (sel.startLineNumber !== sel.endLineNumber || sel.startColumn !== sel.endColumn) {&#xA;            add(&#39;toLine&#39;, sel.endLineNumber);&#xA;            add(&#39;toCol&#39;, sel.endColumn);&#xA;          }&#xA;        }&#xA;      }&#xA;      return parts.length ? base + &#39;?&#39; + parts.join(&#39;&amp;&#39;) : base;&#xA;    }&#xA;&#xA;    // Копирование текста в буфер обмена: navigator.clipboard + фолбэк (textarea/execCommand).&#xA;    function copyText(text) {&#xA;      if (navigator.clipboard &amp;&amp; navigator.clipboard.writeText) {&#xA;        return navigator.clipboard.writeText(text);&#xA;      }&#xA;      return new Promise(function (resolve, reject) {&#xA;        try {&#xA;          var ta = document.createElement(&#39;textarea&#39;);&#xA;          ta.value = text;&#xA;          ta.style.position = &#39;fixed&#39;;&#xA;          ta.style.opacity = &#39;0&#39;;&#xA;          document.body.appendChild(ta);&#xA;          ta.focus(); ta.select();&#xA;          var ok = document.execCommand(&#39;copy&#39;);&#xA;          document.body.removeChild(ta);&#xA;          if (ok) { resolve(); } else { reject(new Error(&#39;copy failed&#39;)); }&#xA;        } catch (e) { reject(e); }&#xA;      });&#xA;    }&#xA;&#xA;    // Показывает в статус-баре текст диапазона + ссылку-копирование актуального URL.&#xA;    function appendShareLink() {&#xA;      if (!status) { return; }&#xA;      var a = document.createElement(&#39;a&#39;);&#xA;      a.className = &#39;tpl-copy&#39;;&#xA;      a.href = &#39;#&#39;;&#xA;      a.title = &#39;Copy link to the current playground state&#39;;&#xA;      a.textContent = &#39;🔗 copy link&#39;;&#xA;      a.addEventListener(&#39;click&#39;, function (ev) {&#xA;        ev.preventDefault();&#xA;        var url = buildShareUrl();&#xA;        copyText(url).then(function () {&#xA;          var old = a.textContent;&#xA;          a.textContent = &#39;✓ copied&#39;;&#xA;          setTimeout(function () { a.textContent = old; }, 1500);&#xA;        }).catch(function () {&#xA;          a.textContent = &#39;copy failed&#39;;&#xA;          setTimeout(function () { a.textContent = &#39;🔗 copy link&#39;; }, 2000);&#xA;        });&#xA;      });&#xA;      status.appendChild(a);&#xA;    }&#xA;    function showRange(text) {&#xA;      if (!status) { return; }&#xA;      status.textContent = &#39;&#39;;&#xA;      if (text) { status.appendChild(document.createTextNode(text + &#39;  &#39;)); }&#xA;      appendShareLink();&#xA;    }&#xA;&#xA;    // Диагностики trust-lsp в логе приходят из stderr в формате&#xA;    // &#34;файл:строка:колонка: severity: сообщение&#34; (см. src/diag/diag.cpp). Такие строки&#xA;    // делаем кликабельными: клик переводит курсор редактора Trust на строку в исходнике.&#xA;    var logDiagRe = /^(.+):(\d+):(\d+):\s*(fatal|error|warning|remark|note):(.*)$/;&#xA;    var logFirstErrLine = 0; // 1-based строка исходника первой ошибки (для авто-перехода)&#xA;&#xA;    function gotoTrustLine(line, col) {&#xA;      if (!trustEditor || !line || line &lt; 1) { return; }&#xA;      var column = (col &amp;&amp; col &gt; 0) ? col : 1;&#xA;      trustEditor.setPosition({ lineNumber: line, column: column });&#xA;      trustEditor.revealLineInCenter(line);&#xA;      trustEditor.focus();&#xA;    }&#xA;&#xA;    // При наличии в логе ошибки - перевести курсор на её строку. Не вырываем курсор,&#xA;    // если пользователь активно редактирует (редактор Trust в фокусе): иначе debounce&#xA;    // пере-транспиляции при каждом нажатии сбрасывал бы позицию на первую ошибку.&#xA;    function autoFocusFirstError() {&#xA;      if (logFirstErrLine &amp;&amp; trustEditor &amp;&amp; !trustEditor.hasTextFocus()) {&#xA;        gotoTrustLine(logFirstErrLine, 1);&#xA;      }&#xA;    }&#xA;&#xA;    function appendLog(msg) {&#xA;      if (!log) { return; }&#xA;      var lines = String(msg).split(&#39;\n&#39;);&#xA;      for (var i = 0; i &lt; lines.length; i++) {&#xA;        var row = document.createElement(&#39;div&#39;);&#xA;        row.className = &#39;tpl-logline&#39;;&#xA;        var text = lines[i];&#xA;        var m = logDiagRe.exec(text);&#xA;        if (m) {&#xA;          var ln = parseInt(m[2], 10);&#xA;          var col = parseInt(m[3], 10);&#xA;          var sev = (m[4] || &#39;&#39;).toLowerCase();&#xA;          var isErr = (sev === &#39;error&#39; || sev === &#39;fatal&#39;);&#xA;          if (isErr &amp;&amp; !logFirstErrLine) { logFirstErrLine = ln; }&#xA;          var link = document.createElement(&#39;span&#39;);&#xA;          link.className = &#39;tpl-log-link &#39; + (isErr ? &#39;tpl-log-error&#39; : &#39;tpl-log-warn&#39;);&#xA;          link.textContent = text;&#xA;          link.title = &#39;Go to line &#39; + ln;&#xA;          link.addEventListener(&#39;click&#39;, (function (ll, lc) {&#xA;            return function () { gotoTrustLine(ll, lc); };&#xA;          })(ln, col));&#xA;          row.appendChild(link);&#xA;        } else {&#xA;          row.textContent = text;&#xA;        }&#xA;        log.appendChild(row);&#xA;      }&#xA;      log.scrollTop = log.scrollHeight;&#xA;    }&#xA;    function clearLog() {&#xA;      if (log) { log.textContent = &#39;&#39;; }&#xA;      logFirstErrLine = 0;&#xA;    }&#xA;&#xA;    // Ссылка документации о песочнице должна вести в ту же языковую версию, что и&#xA;    // страница. Сайт мультиязычный: ru -&gt; /ru/docs/sandbox/, en -&gt; /en/docs/sandbox/&#xA;    // (или без префикса, если en - язык по умолчанию). Если на странице нет&#xA;    // языкового префикса - возвращаем URL как есть.&#xA;    function localizeLink(url) {&#xA;      var m = /^\/(ru|en)\//.exec(location.pathname);&#xA;      if (!m) { return url; }&#xA;      var lang = m[1];&#xA;      return url.replace(/^([a-z][a-z0-9+.-]*:\/\/[^\/]+)(\/)/i, &#39;$1/&#39; + lang + &#39;$2&#39;);&#xA;    }&#xA;&#xA;    // Показ/скрытие центрированного сообщения поверх правой панели (ошибки,&#xA;    // нет связи с сервером песочницы). По умолчанию оверлей скрыт (display:none).&#xA;    // Контент собирается через createElement/textContent (НЕ innerHTML): строки&#xA;    // (data.error, instructionsUrl) приходят от сервера и не должны исполняться как HTML.&#xA;    function setCppOverlay(text, linkHref, linkText) {&#xA;      if (!cppOverlay) { return; }&#xA;      cppOverlay.textContent = &#39;&#39;;&#xA;      if (text) { cppOverlay.appendChild(document.createTextNode(text)); }&#xA;      if (linkHref) {&#xA;        var a = document.createElement(&#39;a&#39;);&#xA;        a.href = linkHref;&#xA;        a.target = &#39;_blank&#39;;&#xA;        a.rel = &#39;noopener&#39;;&#xA;        a.textContent = linkText || linkHref;&#xA;        cppOverlay.appendChild(a);&#xA;      }&#xA;      cppOverlay.style.display = &#39;flex&#39;;&#xA;    }&#xA;    function clearCppOverlay() {&#xA;      if (!cppOverlay) { return; }&#xA;      cppOverlay.style.display = &#39;none&#39;;&#xA;      cppOverlay.textContent = &#39;&#39;;&#xA;    }&#xA;&#xA;    function setDownloadDisabled(on) {&#xA;      if (!downloadBtn) { return; }&#xA;      if (on) { downloadBtn.classList.add(&#39;tpl-btn-disabled&#39;); downloadBtn.href = &#39;#&#39;; }&#xA;      else { downloadBtn.classList.remove(&#39;tpl-btn-disabled&#39;); }&#xA;    }&#xA;&#xA;    // Ленивое скачивание build-архива: POST /download - отдельный запрос, заново&#xA;    // обрабатывает текущий код и сразу возвращает tar.gz. НЕ зависит от /run.&#xA;    function downloadArchive() {&#xA;      if (!downloadBtn || !cfg.serverUrl) { return; }&#xA;      var body = (trustEditor &amp;&amp; trustEditor.getValue) ? trustEditor.getValue() : (loadedSource || &#39;&#39;);&#xA;      setStatus(&#39;building archive…&#39;);&#xA;      appendLog(&#39;building archive…&#39;);&#xA;      fetchWithTimeout(serverOrigin + &#39;/download&#39;, {&#xA;        method: &#39;POST&#39;,&#xA;        headers: requestHeaders(),&#xA;        body: body&#xA;      }, kRunTimeoutMs).then(function (res) {&#xA;        if (!res.ok) {&#xA;          return res.json().catch(function () { return {}; }).then(function (d) {&#xA;            throw new Error((d &amp;&amp; d.error) || (&#39;archive build failed (&#39; + res.status + &#39;)&#39;));&#xA;          });&#xA;        }&#xA;        var name = &#39;trust-build.tar.gz&#39;;&#xA;        var cd = res.headers.get(&#39;Content-Disposition&#39;);&#xA;        if (cd) { var m = /filename=&#34;?([^&#34;;]+)/.exec(cd); if (m &amp;&amp; m[1]) { name = m[1]; } }&#xA;        return res.blob().then(function (blob) {&#xA;          var a = document.createElement(&#39;a&#39;);&#xA;          a.href = URL.createObjectURL(blob);&#xA;          a.download = name;&#xA;          document.body.appendChild(a);&#xA;          a.click();&#xA;          document.body.removeChild(a);&#xA;          URL.revokeObjectURL(a.href);&#xA;          setStatus(&#39;ok&#39;);&#xA;          appendLog(&#39;archive: &#39; + name);&#xA;        });&#xA;      }).catch(function (err) {&#xA;        var m = &#39;archive build failed: &#39; + err;&#xA;        setStatus(m);&#xA;        appendLog(m);&#xA;      });&#xA;    }&#xA;    if (downloadBtn) {&#xA;      downloadBtn.addEventListener(&#39;click&#39;, function (ev) { ev.preventDefault(); downloadArchive(); });&#xA;    }&#xA;&#xA;    // Заполняем комбобокс примеров СРАЗУ (до загрузки Monaco) - он не может быть пустым.&#xA;    function populateExamples() {&#xA;      if (!examplesSel || !cfg.examples || cfg.examples.length === 0) { return; }&#xA;      var matched = -1;&#xA;      var wantName = urlParams.file || &#39;&#39;;&#xA;      for (var i = 0; i &lt; cfg.examples.length; i++) {&#xA;        var opt = document.createElement(&#39;option&#39;);&#xA;        opt.value = i;&#xA;        opt.textContent = cfg.examples[i].name;&#xA;        examplesSel.appendChild(opt);&#xA;        // Приоритет: явный URL-параметр file; иначе - пример, совпадающий с cfg.source.&#xA;        if (wantName &amp;&amp; cfg.examples[i].name === wantName) { matched = i; }&#xA;        else if (!wantName &amp;&amp; cfg.examples[i].source === cfg.source) { matched = i; }&#xA;      }&#xA;      if (matched &gt;= 0) {&#xA;        curExIndex = matched;&#xA;        curExampleName = cfg.examples[matched].name;&#xA;        examplesSel.selectedIndex = matched;&#xA;        // Инициализируемый по URL (или дефолтный) пример: исходник подставим в initEditors,&#xA;        // чтобы редактор Trust стартовал именно с него (и кеш-заголовок X-Example-Name был верным).&#xA;        initialExample = cfg.examples[matched];&#xA;      } else {&#xA;        // Текущий текст не совпадает ни с одним примером → отключённая опция «Custom».&#xA;        var custom = document.createElement(&#39;option&#39;);&#xA;        custom.value = -1;&#xA;        custom.textContent = &#39;Custom&#39;;&#xA;        custom.disabled = true;&#xA;        examplesSel.insertBefore(custom, examplesSel.firstChild);&#xA;        examplesSel.selectedIndex = 0;&#xA;        curExIndex = -1;&#xA;        curExampleName = &#39;&#39;;&#xA;      }&#xA;      examplesSel.onchange = function () {&#xA;        var idx = parseInt(examplesSel.value, 10);&#xA;        if (!cfg.examples[idx]) { return; }&#xA;        var ex = cfg.examples[idx];&#xA;        if (trustEditor &amp;&amp; trustEditor.getValue() !== loadedSource) {&#xA;          if (!confirm(&#39;The current text will be replaced with example &#34;&#39; + ex.name + &#39;&#34;. Continue?&#39;)) {&#xA;            if (curExIndex &gt;= 0) { examplesSel.selectedIndex = curExIndex; }&#xA;            else { examplesSel.selectedIndex = 0; }&#xA;            return;&#xA;          }&#xA;        }&#xA;        if (trustEditor) { trustEditor.setValue(ex.source); }&#xA;        loadedSource = ex.source;&#xA;        curExIndex = idx;&#xA;        curExampleName = ex.name;&#xA;        setStatus(&#39;loaded example &#39; + ex.name);&#xA;      };&#xA;    }&#xA;    populateExamples();&#xA;&#xA;    function setStatus(msg) { if (status) { status.textContent = msg; } }&#xA;&#xA;    // Таймауты сетевых вызовов балансировщика (мс). Без клиентского таймаута при&#xA;    // неустановимом соединении (хост недоступен/прокси висит) статус-строка держала&#xA;    // бы «transpiling…» до OS/браузерного connect-timeout (30-60 с). /health у живого&#xA;    // балансировщика всегда мгновенен - короткий таймаут; /run может быть медленным&#xA;    // (серверный максимум ~30 с), поэтому его таймаут - только последний рубеж.&#xA;    var kHealthTimeoutMs = 4000;&#xA;    var kRunTimeoutMs = 35000;&#xA;&#xA;    // Достижимость балансировщика по последнему /health: null - неизвестно, true/false -&#xA;    // результат проверки. Используется, чтобы не слать /run впустую и показывать ошибку сразу.&#xA;    var balancerReady = null;&#xA;    // Активный запрос /run: при недоступности балансировщика обрываем его - ошибка покажется сразу.&#xA;    var runAbort = null;&#xA;    // Номер текущего recompile: устаревшие ответы (в т.ч. оборванные) не трогают UI.&#xA;    var runSeq = 0;&#xA;&#xA;    // fetch с клиентским таймаутом: по истечении (или внешнему abort) промис реджектится&#xA;    // с явной ошибкой - вызывающий код показывает ошибку связи (без «тихого» fallback).&#xA;    function fetchWithTimeout(url, opts, timeoutMs, externalCtrl) {&#xA;      var ctrl = externalCtrl || ((&#39;AbortController&#39; in window) ? new AbortController() : null);&#xA;      var o = opts || {};&#xA;      if (ctrl) { o.signal = ctrl.signal; }&#xA;      var timer = ctrl ? setTimeout(function () { ctrl.abort(); }, timeoutMs) : null;&#xA;      function clear() { if (timer !== null) { clearTimeout(timer); } }&#xA;      return fetch(url, o).then(function (res) {&#xA;        clear();&#xA;        return res;&#xA;      }, function (err) {&#xA;        clear();&#xA;        if (err &amp;&amp; err.name === &#39;AbortError&#39;) { throw new Error(&#39;request aborted (timeout &#39; + timeoutMs + &#39; ms)&#39;); }&#xA;        throw err;&#xA;      });&#xA;    }&#xA;&#xA;    // Помечает балансировщик недоступным и обрывает висящий /run (см. recompile).&#xA;    function markBalancerDown() {&#xA;      balancerReady = false;&#xA;      if (runAbort &amp;&amp; runAbort.abort) { runAbort.abort(); }&#xA;    }&#xA;    function markBalancerUp() { balancerReady = true; }&#xA;&#xA;    // Заголовки к балансировщику: имя примера (для кеша - только пока текст НЕ изменён).&#xA;    function requestHeaders() {&#xA;      var h = { &#39;Content-Type&#39;: &#39;text/plain; charset=utf-8&#39; };&#xA;      var name = &#39;&#39;;&#xA;      if (curExampleName) {&#xA;        var txt = (trustEditor &amp;&amp; trustEditor.getValue) ? trustEditor.getValue() : &#39;&#39;;&#xA;        if (txt === loadedSource) { name = curExampleName; }&#xA;      }&#xA;      if (name) { h[&#39;X-Example-Name&#39;] = name; }&#xA;      return h;&#xA;    }&#xA;&#xA;    function setHealth(state, txt) {&#xA;      if (!healthEl) { return; }&#xA;      healthEl.className = &#39;tpl-health &#39; + state;&#xA;      if (healthText) { healthText.textContent = txt; }&#xA;    }&#xA;&#xA;    // Публичный пинг балансировщика: онлайн ли он и сколько воркеров активно.&#xA;    // Постоянный статус готовности, отличает «нет связи с балансировщиком» от «нет воркеров».&#xA;    // Терпим к старым балансировщикам: если в ответе нет workers_connected - всё равно «онлайн»,&#xA;    // просто без счётчика (поле появилось в новой версии /health).&#xA;    // Возвращает промис с bool (доступен ли балансировщик) - используется как гейт в recompile.&#xA;    function probeHealth() {&#xA;      if (!healthEl) { return Promise.resolve(true); }&#xA;      if (!cfg.serverUrl) {&#xA;        setHealth(&#39;down&#39;, &#39;no connection to the balancer&#39;);&#xA;        markBalancerDown();&#xA;        return Promise.resolve(false);&#xA;      }&#xA;      function down(res, txt) { setHealth(&#39;down&#39;, txt); markBalancerDown(); return res; }&#xA;      return fetchWithTimeout(serverOrigin + &#39;/health&#39;, { method: &#39;GET&#39; }, kHealthTimeoutMs).then(function (res) {&#xA;        if (!res.ok) {&#xA;          console.warn(&#39;[trust-playground] /health HTTP &#39; + res.status + &#39; at &#39; + serverOrigin);&#xA;          return down(false, &#39;no connection to the balancer (HTTP &#39; + res.status + &#39;)&#39;);&#xA;        }&#xA;        return res.json().then(function (d) {&#xA;          if (!d || d.status !== &#39;ok&#39;) {&#xA;            console.warn(&#39;[trust-playground] /health response without status=ok:&#39;, d);&#xA;            return down(false, &#39;no connection to the balancer&#39;);&#xA;          }&#xA;          var n = (typeof d.workers_connected === &#39;number&#39;) ? d.workers_connected : null;&#xA;          if (n === null) { setHealth(&#39;ok&#39;, &#39;balancer online&#39;); }&#xA;          else if (n &gt; 0) { setHealth(&#39;ok&#39;, &#39;balancer online · workers: &#39; + n); }&#xA;          else { setHealth(&#39;degraded&#39;, &#39;balancer online · no workers&#39;); }&#xA;          markBalancerUp();&#xA;          return true;&#xA;        }, function () {&#xA;          console.warn(&#39;[trust-playground] /health returned non-JSON (probably a static page instead of the balancer): &#39; + serverOrigin);&#xA;          return down(false, &#39;no connection to the balancer&#39;);&#xA;        });&#xA;      }, function (e) {&#xA;        console.warn(&#39;[trust-playground] /health fetch failed at &#39; + serverOrigin + &#39;:&#39;, e);&#xA;        return down(false, &#39;no connection to the balancer&#39;);&#xA;      });&#xA;    }&#xA;&#xA;    // Поллинг статуса балансировщика (setInterval); результат - в индикаторе и balancerReady.&#xA;    function updateHealth() { probeHealth(); }&#xA;&#xA;    function loadScript(src, onload) {&#xA;      var s = document.createElement(&#39;script&#39;);&#xA;      s.src = src;&#xA;      s.onload = onload;&#xA;      s.onerror = function () { setStatus(&#39;Failed to load Monaco from &#39; + src); };&#xA;      document.head.appendChild(s);&#xA;    }&#xA;&#xA;    function mkDeco(lines, cls) {&#xA;      var arr = [];&#xA;      for (var i = 0; i &lt; lines.length; i++) {&#xA;        arr.push({ range: new monaco.Range(lines[i], 1, lines[i], 1),&#xA;                   options: { isWholeLine: true, className: cls } });&#xA;      }&#xA;      return arr;&#xA;    }&#xA;&#xA;    function initEditors() {&#xA;      if (typeof require === &#39;undefined&#39;) { setStatus(&#39;Monaco loader unavailable&#39;); return; }&#xA;      require.config({ paths: { vs: cfg.monacoUrl } });&#xA;      require([&#39;vs/editor/editor.main&#39;], function () {&#xA;        try {&#xA;          /* trust Monarch tokenizer */&#xA;          monaco.languages.register({ id: &#39;trust&#39; });&#xA;          monaco.languages.setMonarchTokensProvider(&#39;trust&#39;, __MONARCH__);&#xA;&#xA;          trustEditor = monaco.editor.create(trustHost, {&#xA;            // Стартовый текст: пример, выбранный URL-параметром file (или дефолтный cfg.source).&#xA;            value: (initialExample ? initialExample.source : cfg.source), language: &#39;trust&#39;, theme: &#39;vs&#39;,&#xA;            readOnly: false, automaticLayout: true, scrollBeyondLastLine: false,&#xA;            minimap: { enabled: true }&#xA;          });&#xA;          if (initialExample) {&#xA;            // Синхронизируем состояние «загруженного примера» с фактическим исходником редактора,&#xA;            // чтобы кеш-заголовок X-Example-Name и share-URL (file=) были корректны.&#xA;            loadedSource = initialExample.source;&#xA;            curExampleName = initialExample.name;&#xA;          }&#xA;          // Применяем начальную позицию/выделение для окна src сразу (контент уже в редакторе).&#xA;          applyInitialPosition(trustEditor, &#39;src&#39;);&#xA;          cppEditor = monaco.editor.create(cppHost, {&#xA;            // Трансляция НЕ хранится в шаблоне страницы - правый редактор&#xA;            // стартует пустым и заполняется только из ответа балансировщика.&#xA;            value: &#39;&#39;, language: &#39;cpp&#39;, theme: &#39;vs&#39;,&#xA;            readOnly: true, automaticLayout: true, scrollBeyondLastLine: false,&#xA;            minimap: { enabled: true }&#xA;          });&#xA;&#xA;          var t2c = {}, c2t = {};&#xA;          var trustDec = [], cppDec = [];&#xA;          var trustGutterDec = [], cppGutterDec = [];&#xA;&#xA;          function followEnabled() { return !followCb || followCb.checked; }&#xA;&#xA;          // Gutter-маркеры: пометить в колонке номеров ВСЕ строки, у которых есть маппинг&#xA;          // (постоянные декор-метки; не путать с breadcrumb текущей строки).&#xA;          function mkGutter(lines) {&#xA;            var arr = [];&#xA;            for (var i = 0; i &lt; lines.length; i++) {&#xA;              arr.push({ range: new monaco.Range(lines[i], 1, lines[i], 1),&#xA;                         options: { isWholeLine: true, linesDecorationsClassName: &#39;tpl-gutter&#39; } });&#xA;            }&#xA;            return arr;&#xA;          }&#xA;          function buildGutterMarks() {&#xA;            var tl = [], cl = [];&#xA;            for (var k in t2c) { if (t2c[k] &amp;&amp; t2c[k].length) { tl.push(Number(k)); } }&#xA;            for (var k in c2t) { if (c2t[k] &amp;&amp; c2t[k].length) { cl.push(Number(k)); } }&#xA;            trustGutterDec = trustEditor.deltaDecorations(trustGutterDec, mkGutter(tl));&#xA;            cppGutterDec = cppEditor.deltaDecorations(cppGutterDec, mkGutter(cl));&#xA;          }&#xA;          buildGutterMarks();&#xA;&#xA;          // Троттлинг reveal: не «дёргать» прокрутку при быстрых перемещениях курсора.&#xA;          var revealTimers = { trust: 0, cpp: 0 };&#xA;          function revealThrottled(editor, line, which) {&#xA;            if (!followEnabled()) { return; }&#xA;            clearTimeout(revealTimers[which]);&#xA;            revealTimers[which] = setTimeout(function () { editor.revealLine(line); }, 80);&#xA;          }&#xA;&#xA;          // Навигация + breadcrumb: подсветить соответствующие строки, прокрутить (если follow),&#xA;          // показать маппинг ТЕКУЩЕЙ строки в статус-баре («→ cpp: N») и ссылку-копирование URL.&#xA;          // activeWindow фиксирует окно с курсором для построения share-URL.&#xA;          trustEditor.onDidChangeCursorPosition(function (e) {&#xA;            activeWindow = &#39;src&#39;;&#xA;            var l = e.position.lineNumber;&#xA;            var lines = (t2c[l] || []);&#xA;            cppDec = cppEditor.deltaDecorations(cppDec, mkDeco(lines, &#39;tpl-linked&#39;));&#xA;            if (lines.length) {&#xA;              revealThrottled(cppEditor, lines[0], &#39;cpp&#39;);&#xA;              showRange(&#39;→ cpp: &#39; + lines.join(&#39;, &#39;));&#xA;            }&#xA;          });&#xA;          cppEditor.onDidChangeCursorPosition(function (e) {&#xA;            activeWindow = &#39;cppt&#39;;&#xA;            var l = e.position.lineNumber;&#xA;            var lines = (c2t[l] || []);&#xA;            trustDec = trustEditor.deltaDecorations(trustDec, mkDeco(lines, &#39;tpl-linked&#39;));&#xA;            if (lines.length) {&#xA;              revealThrottled(trustEditor, lines[0], &#39;trust&#39;);&#xA;              showRange(&#39;→ trust: &#39; + lines.join(&#39;, &#39;));&#xA;            }&#xA;          });&#xA;&#xA;          // Двойной клик: перейти к первой соответствующей строке в противоположной панели.&#xA;          trustEditor.onMouseDown(function (e) {&#xA;            var dl = t2c[e.target.position.lineNumber];&#xA;            if (e.event &amp;&amp; e.event.detail &gt;= 2 &amp;&amp; dl &amp;&amp; dl.length) {&#xA;              cppEditor.setPosition({ lineNumber: dl[0], column: 1 });&#xA;              cppEditor.revealLineInCenter(dl[0]);&#xA;            }&#xA;          });&#xA;          cppEditor.onMouseDown(function (e) {&#xA;            var dl = c2t[e.target.position.lineNumber];&#xA;            if (e.event &amp;&amp; e.event.detail &gt;= 2 &amp;&amp; dl &amp;&amp; dl.length) {&#xA;              trustEditor.setPosition({ lineNumber: dl[0], column: 1 });&#xA;              trustEditor.revealLineInCenter(dl[0]);&#xA;            }&#xA;          });&#xA;&#xA;          function resetCppPane(text, linkHref, linkText) {&#xA;            // Очищаем правую панель и показываем по центру сообщение об ошибке/нет связи.&#xA;            if (cppEditor &amp;&amp; cppEditor.setValue) { cppEditor.setValue(&#39;&#39;); }&#xA;            t2c = {}; c2t = {};&#xA;            cppDec = cppEditor.deltaDecorations(cppDec, []);&#xA;            cppGutterDec = cppEditor.deltaDecorations(cppGutterDec, []);&#xA;            trustGutterDec = trustEditor.deltaDecorations(trustGutterDec, []);&#xA;            setCppOverlay(text, linkHref, linkText);&#xA;            setDownloadDisabled(true);&#xA;          }&#xA;&#xA;          function recompile() {&#xA;            var body = trustEditor.getValue();&#xA;            var seq = ++runSeq;&#xA;            clearLog();&#xA;            // Не шлём /run впустую: если балансировщик ещё не подтверждён доступным,&#xA;            // сначала короткая проверка /health. Недоступен - сразу показываем ошибку&#xA;            // связи (status + overlay), не удерживая «transpiling…» до 30-60 с.&#xA;            var gate = (balancerReady === true) ? Promise.resolve(true) : probeHealth();&#xA;            gate.then(function (ready) {&#xA;              if (seq !== runSeq) { return; }&#xA;              if (!ready) {&#xA;                var downMsg = &#39;No connection to the balancer&#39;;&#xA;                setStatus(downMsg);&#xA;                appendLog(downMsg);&#xA;                resetCppPane(downMsg);&#xA;                return;&#xA;              }&#xA;              setStatus(&#39;transpiling…&#39;);&#xA;              appendLog(&#39;transpiling…&#39;);&#xA;              if (runAbort &amp;&amp; runAbort.abort) { runAbort.abort(); }&#xA;              runAbort = (&#39;AbortController&#39; in window) ? new AbortController() : null;&#xA;              fetchWithTimeout(cfg.serverUrl, {&#xA;                method: &#39;POST&#39;,&#xA;                headers: requestHeaders(),&#xA;                body: body&#xA;              }, kRunTimeoutMs, runAbort).then(function (res) {&#xA;                // Читаем тело как текст и пытаемся распарсить JSON: балансировщик&#xA;                // может вернуть HTML/прокси-ошибку (не JSON) - в этом случае трактуем&#xA;                // как отсутствие связи/ошибку и не роняем цепочку.&#xA;                return res.text().then(function (txt) {&#xA;                  var data = null;&#xA;                  try { data = JSON.parse(txt); } catch (e) { data = null; }&#xA;                  return { ok: res.ok, status: res.status, data: data };&#xA;                });&#xA;              }).then(function (rr) {&#xA;                if (seq !== runSeq) { return; }&#xA;                var data = rr.data;&#xA;                if (data &amp;&amp; data.unavailable) {&#xA;                  // Нет доступных воркеров (балансировщик онлайн, но ни один воркер не&#xA;                  // подключён/не свободен). Отличаем от «Нет связи с балансировщиком».&#xA;                  var umsg = &#39;No workers available&#39;;&#xA;                  var uLink = null;&#xA;                  if (data.instructionsUrl) { uLink = localizeLink(data.instructionsUrl); }&#xA;                  appendLog((data &amp;&amp; data.error) ? data.error : umsg);&#xA;                  setStatus(umsg);&#xA;                  resetCppPane(umsg, uLink, &#39;run your own node&#39;);&#xA;                  return;&#xA;                }&#xA;                if (!rr.ok) {&#xA;                  // Балансировщик/прокси вернул HTTP-ошибку без валидного JSON-контракта.&#xA;                  var herr = (data &amp;&amp; data.error) ? data.error : (&#39;No connection to the balancer (HTTP &#39; + rr.status + &#39;)&#39;);&#xA;                  setStatus(herr);&#xA;                  appendLog(herr);&#xA;                  resetCppPane(herr);&#xA;                  return;&#xA;                }&#xA;                if (!data || !data.ok) {&#xA;                  var err = (data &amp;&amp; data.error) ? data.error : &#39;Transpilation error&#39;;&#xA;                  setStatus(err);&#xA;                  appendLog(err);&#xA;                  if (data &amp;&amp; data.log) { appendLog(data.log); }&#xA;                  resetCppPane(err);&#xA;                  autoFocusFirstError();&#xA;                  return;&#xA;                }&#xA;                cppEditor.setValue(data.cpp);&#xA;                t2c = data.trustToCpp || {}; c2t = data.cppToTrust || {};&#xA;                // Для окна cppt начальную позицию/выделение применяем только после того,&#xA;                // как правый редактор заполнен ответом балансировщика (guard initApplied).&#xA;                applyInitialPosition(cppEditor, &#39;cppt&#39;);&#xA;                cppDec = cppEditor.deltaDecorations(cppDec, []);&#xA;                clearCppOverlay();&#xA;                setDownloadDisabled(false);&#xA;                setStatus(&#39;ok&#39;);&#xA;                appendLog(&#39;ok&#39;);&#xA;                if (data.log) { appendLog(data.log); }&#xA;                autoFocusFirstError();&#xA;              }).catch(function (err) {&#xA;                if (seq !== runSeq) { return; }&#xA;                // Сетевой сбой/таймаут (нет связи с балансировщиком) - НЕ путать с «нет воркеров».&#xA;                appendLog(&#39;request failed: &#39; + err);&#xA;                resetCppPane(&#39;No connection to the balancer&#39;);&#xA;                setStatus(&#39;No connection to the balancer&#39;);&#xA;              });&#xA;            });&#xA;          }&#xA;&#xA;          setStatus(&#39;ready&#39;);&#xA;          if (cfg.serverUrl) {&#xA;            var timer = null;&#xA;            trustEditor.onDidChangeModelContent(function () {&#xA;              clearTimeout(timer);&#xA;              timer = setTimeout(recompile, 400);&#xA;            });&#xA;            // Первичная транспиляция на загрузке (заполняет лог). Кнопка «⬇ Скачать»&#xA;            // активна только после первого успешного ответа балансировщика.&#xA;            recompile();&#xA;          }&#xA;        } catch (err) {&#xA;          setStatus(&#39;init error: &#39; + err);&#xA;        }&#xA;      });&#xA;    }&#xA;&#xA;    updateHealth();&#xA;    setInterval(updateHealth, 5000);&#xA;&#xA;    // --- Изменяемый размер окон: вертикальный сплиттер Trust|C++ и горизонтальный (высота лога) ---&#xA;    var playground = document.getElementById(&#39;trust-playground&#39;);&#xA;    var splitV = document.getElementById(&#39;tpl-split-v&#39;);&#xA;    var splitH = document.getElementById(&#39;tpl-split-h&#39;);&#xA;&#xA;    // Универсальный drag для сплиттера (мышь). После вертикального перетаскивания&#xA;    // редакторы Monaco требуют явного layout() - см. onDrag.&#xA;    function makeSplitter(handle, axis, onDrag) {&#xA;      if (!handle) { return; }&#xA;      var dragging = false;&#xA;      var cursor = (axis === &#39;v&#39;) ? &#39;col-resize&#39; : &#39;row-resize&#39;;&#xA;      handle.addEventListener(&#39;mousedown&#39;, function (e) {&#xA;        if (e.button !== 0) { return; }&#xA;        dragging = true;&#xA;        document.body.style.cursor = cursor;&#xA;        document.body.style.userSelect = &#39;none&#39;;&#xA;        e.preventDefault();&#xA;      });&#xA;      document.addEventListener(&#39;mousemove&#39;, function (e) {&#xA;        if (!dragging) { return; }&#xA;        onDrag(e.clientX, e.clientY);&#xA;      });&#xA;      document.addEventListener(&#39;mouseup&#39;, function () {&#xA;        if (!dragging) { return; }&#xA;        dragging = false;&#xA;        document.body.style.cursor = &#39;&#39;;&#xA;        document.body.style.userSelect = &#39;&#39;;&#xA;      });&#xA;    }&#xA;&#xA;    // Вертикальный сплиттер: ширина левой (Trust) панели в процентах от .tpl-row.&#xA;    if (splitV &amp;&amp; trustHost) {&#xA;      var rowEl = splitV.parentElement;&#xA;      makeSplitter(splitV, &#39;v&#39;, function (cx) {&#xA;        var rect = rowEl.getBoundingClientRect();&#xA;        if (rect.width &lt;= 0) { return; }&#xA;        var pct = ((cx - rect.left) / rect.width) * 100;&#xA;        pct = Math.max(15, Math.min(85, pct));&#xA;        trustHost.parentElement.style.flex = &#39;0 0 &#39; + pct + &#39;%&#39;;&#xA;        if (trustEditor) { trustEditor.layout(); }&#xA;        if (cppEditor) { cppEditor.layout(); }&#xA;      });&#xA;    }&#xA;&#xA;    // Горизонтальный сплиттер: высота окна лога (от курсора до низа контейнера).&#xA;    if (splitH &amp;&amp; log &amp;&amp; playground) {&#xA;      makeSplitter(splitH, &#39;h&#39;, function (cx, cy) {&#xA;        var bottom = playground.getBoundingClientRect().bottom;&#xA;        var h = Math.max(40, Math.min(500, bottom - cy - 6));&#xA;        log.style.height = h + &#39;px&#39;;&#xA;      });&#xA;    }&#xA;&#xA;&#xA;    loadScript(cfg.monacoUrl + &#39;/loader.js&#39;, initEditors);&#xA;  })();&#xA; };&#xA;if (window.__TPG.monarch &amp;&amp; window.__TPG.glue) { window.__TPG.glue(window.__TPG.monarch()); }&#xA;&lt;/script&gt;</description>
			</item>
			<item>
				<title>Песочница (playground)</title>
				<link>https://trust-lang.net/ru/docs/sandbox/</link>
				<pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
				<guid>https://trust-lang.net/ru/docs/sandbox/</guid>
				<description>&lt;h2 id=&#34;что-такое-песочница&#34;&gt;Что такое песочница&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%87%d1%82%d0%be-%d1%82%d0%b0%d0%ba%d0%be%d0%b5-%d0%bf%d0%b5%d1%81%d0%be%d1%87%d0%bd%d0%b8%d1%86%d0%b0&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Песочница (playground)&lt;/strong&gt; — это интерактивная веб-страница, где можно писать код на&#xA;TrustLang прямо в браузере и сразу видеть сгенерированный результат транспиляции в C++.&#xA;Это «живой» пример языка с встроенным редактором и подсветкой кода, выбором примеров из списка,&#xA;выводом диагностических сообщений, кросс-навигация между кодом и C++ и кнопкой для скачивания итогового build-архива.&lt;/p&gt;&#xA;&lt;h2 id=&#34;ссылки-на-состояние-песочницы-url-параметры&#34;&gt;Ссылки на состояние песочницы (URL-параметры)&lt;a class=&#34;td-heading-self-link&#34; href=&#34;#%d1%81%d1%81%d1%8b%d0%bb%d0%ba%d0%b8-%d0%bd%d0%b0-%d1%81%d0%be%d1%81%d1%82%d0%be%d1%8f%d0%bd%d0%b8%d0%b5-%d0%bf%d0%b5%d1%81%d0%be%d1%87%d0%bd%d0%b8%d1%86%d1%8b-url-%d0%bf%d0%b0%d1%80%d0%b0%d0%bc%d0%b5%d1%82%d1%80%d1%8b&#34; aria-label=&#34;Heading self-link&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Страницу песочницы можно открыть сразу в нужном состоянии, передав опциональные параметры&#xA;в URL (query-string). Все параметры необязательны и без &lt;code&gt;line&lt;/code&gt; позиция курсора не меняется:&lt;/p&gt;</description>
			</item>
	</channel>
</rss>
