Repository navigation
Releases: ordnary-com/brim
Releases · ordnary-com/brim
Release list
Brim v1.0.0-rc.2
Changed
- The project file is
.brimprojand the lock file.brimlock, instead ofbrim.tomlandbrim.lock. Projects with the old names keep working:brim.tomlgives a warning to rename it, andbrim.lockis replaced by.brimlockthe next time the lock file is written. The registry accepts archives with either name, and editors find a project's root by either.
Brim v1.0.0-rc.1
The first release candidate for 1.0. From 1.0, what docs/releasing.md
calls stable does not break within 1.x.
Added
- The specification describes the whole language, and its open design questions are decided (
docs/language-spec.md, sections 11 and 12).docs/releasing.mddefines what is stable from 1.0 and the edition policy. - A security review of the runtime, the package client and the registry, with its findings and their fixes in
docs/design/security-review.md. M0015: a locked registry version whose checksum on the registry differs frombrim.lockis refused;brim updaterecords a new one.- The registry revokes tokens (
DELETE /api/v1/me/token, andDELETE /api/v1/admin/tokensfor all of a user's tokens).
Changed
set_timeouton a connection bounds a whole read, not each wait for data, so a client sending a byte now and then cannot hold a server.- The language server resolves dependencies offline, from
brim.lockand the cache: opening a file never clones, downloads or writes. brim publishrefuses symbolic links in a package. Tokens are only sent over https (or http tolocalhost), andcredentials.tomlis created readable by its owner only.- Git dependencies: URLs that git would read as options or helper programs are refused, and git may only use the
https,http,ssh,gitandfiletransports. - The registry limits package metadata, compares the archive's
brim.tomlwith the metadata, reserves names such asstd, refuses paths that unpack differently on Windows, and needs"existing": trueto give an existing user another token. - Text from outside a program (arguments, file names, HTTPS headers) that is not UTF-8 has its invalid bytes replaced by U+FFFD in native code, as in the interpreter.
Fixed
- Native code: HTTPS requests from tasks at the same time could mix up their headers; a connection closed by one task while another used it could crash the program; child processes inherited the program's sockets; on Windows, batch files could run commands hidden in arguments and programs were looked up in the current directory; a string with a NUL character could name a different file;
remove_allcould follow a link out of the directory it removed. crypto.equaltakes the same time wherever two values differ.
Brim v0.5.0
Added
- Tasks:
std.taskruns functions at the same time, each on a thread of its own, in the interpreter and in native code.task.spawn(f)gives aTask[T]tojoin,task.detach(f)starts a task that is never joined, and channels (task.channel(),task.bounded(n)) carry values between tasks withsend,receiveandclose. Tasks share no changeable memory, so there are no data races: values are shared until one side changes them, as before. A run-time error in a task stops the program with that task's call stack; joining a task twice isR0012. The design is indocs/design/concurrency.md. - HTTP servers handle requests at the same time with a task per request;
Server.next()andRequest.respondwork from different tasks, keep-alive included. - Version requirements and a package registry:
router = "1.2"in[dependencies]picks the newest version that meets every requirement on the package in the project (^,~,=, comparisons and*, as indocs/registry.md), records it with its checksum inbrim.lockand works offline from there. Conflicts say who requires what (M0014).brim updatepicks the newest versions again. brim publish(with--dry-run),brim loginandbrim yank NAME@VERSION [--undo]. A path dependency can carry aversionfor publishing:shared = { path = "../shared", version = "0.1" }.[package]takesdescription,licenseandrepository.- The registry service itself, in
registry/: index, downloads, publishing with API tokens, yanking, search and package pages. - Calling C:
extern fn cos(x: f64) -> f64declares a C function, withi64,i32,u8,u64,f64,boolandstring(const char *) parameters and results.[build] c-sourcescompiles C files into native builds and[build] linklinks libraries.brim runbuilds and runs programs that call C; the interpreter stops at such a call withR0011. - Workspaces:
[workspace] members = ["apps/*", "shared"]in a rootbrim.toml, with onebrim.lockfor all members. At the root,check,test,buildanddocwork on every member;-p NAME(--package) picks one. - Native builds on Windows: the C runtime has a Windows version (Winsock, Win32 files, processes, clocks and random numbers, UTF-8 console output and arguments),
brim buildlinks withclang, and releases have awindows-x86_64-nativearchive, whichinstall.ps1prefers. HTTPS requests in native Windows programs go through WinHTTP, the system's own HTTP client, with the same results and error messages as libcurl elsewhere. - The interpreter compiled to WebAssembly (
crates/brim-playground,wasm32-wasip1) runs programs in a browser or in Node, with standard input and a step limit. brim buildskips programs whose sources, options, C compiler andbrimdid not change since they were last built ((up to date)), with the cache in$BRIM_HOME/cache;BRIM_NO_CACHE=1turns all build caches off.- Debug information: native builds without
--releasecarry DWARF line tables, a subprogram per Brim function and the variables of typei64,f64andbool, so lldb and gdb can stop at a Brim line, step, show the call stack with Brim names and print those variables (on macOS in a.dSYMnext to the executable). The oneunsafecall this needs lives in the small cratebrim-llvm-extra. brim doc: HTML documentation from doc comments (the//lines abovepubitems, and the comment at the top of each module), with linked types and a search box.brim doc --stddocuments the standard library; the site publishes that reference under/docs/std/.- The language server completes names, a module's items after
module.and the fields and methods of a value's type aftervalue.; finds references; renames across files; shows signature help in calls; offers quick fixes for diagnostics whose help says what to write (a similar name,let mut, a missing import,2.0); and shows inferred types on hover. It uses a new index from the checker (brim_semantic::index_modules) of what every name refers to, which is there also for programs with errors.
Changed
brim checkon a library withoutmainchecks its library root instead of asking formain.- Native code releases values right after their last use instead of at the end of the block, so a list or map changed by several
mut selfmethods in a row is changed in place instead of copied (aStringBuilderwith twoadds per loop went from 6 s to a few ms for 100,000 parts). brim buildkeeps the compiled runtime in~/.brim/cache($BRIM_HOME/cache): builds after the first are about ten times faster.sorted()on lists of integers and strings is done by the runtime: about 25 times faster in the interpreter.- The interpreter frees numbers and shared values without extra work: loops run about 15% faster.
- The default registry is
https://registry.brimlang.com, and the install scripts live athttps://brimlang.com/install.shandinstall.ps1.
Fixed
brim fmtkeeps the space in0 .5(a field of an integer), which it used to join into the float0.5.
Brim v0.4.0
Added
std.postgres: a PostgreSQL client written in Brim.connect(url),queryandexecutewith$1parameters,query_asinto structs (throughData),transaction, and logins with SCRAM-SHA-256, MD5 or a plain password. A CI job runs it against a real server.std.crypto(SHA-256, HMAC-SHA-256, PBKDF2, MD5, secure random bytes, hex, a constant-time comparison) andstd.base64, the same in the interpreter and native code.Conn.read_bytes(count)andConn.write_bytes(bytes)instd.net, for binary protocols.- HTTP keep-alive: the server keeps connections open for the next request (HTTP/1.1 unless
connection: close) and waits for new and kept connections at once, so a quiet client keeps no one else out; quiet connections close after five seconds.Listener.next_ready(idle_millis)andListener.keep(conn)instd.netdo this for other servers. - API functions: the built-in
serve_api(module, request)serves thepub fns of a module atPOST /api/<name>, with parameters and results as JSON (200, 422 forErr, 400, 404, 405).brim gen ts --angularwrites an Angular service per served module, with a typed method per function.examples/http/apishows both. http.new_request(method, path, body)for testing handlers, andnet.closed().- Typed JSON:
json.encode(value)andjson.decode(text)(andto_json,from_json) for every type that implements the new built-in traitData, which is every type without functions in it. The shapes matchbrim gen ts, and decoding errors give the path:at $.tags[1]: expected a string, found a number. ?passes the expected type on to its operand, solet note: Note = json.decode(text)?needs no other annotation.xs.sum()for lists of numbers.std.process:run(cmd, args)gives the exit code and the standard output and error as strings;output(cmd, args)gives the output of a program that succeeds. Both read the two streams at once, so large output does not block.std.fs:exists,is_dir,is_file,list,create_dir,remove,remove_all,rename,size,modified,read,writeandappend, with the same messages in the interpreter and native code.- Methods on
Option(is_some,is_none,unwrap_or,map) andResult(is_ok,is_err,unwrap_or,ok,map), from the prelude. std.random:int(low, high),float(),bool(),choice,shuffleandseed(n). The generator (xoshiro256**) is the same in the interpreter and the C runtime, so seeded programs print the same numbers in both.- Strings:
StringBuilder(in the prelude:new,add,add_line,is_empty,build),s.code_points(),s.char_count()andfrom_code_point(n). The prelude's public types are known in every module. Set[T]:Set(),Set(list),add,remove,contains,len,to_list,union,intersection,difference,is_subset,for x in set,==andprint({1, 2}). The built-in traitKeylets generic code use maps and sets; map keys can now be any integer type.- Math:
abs,sqrt,floor,ceil,roundandpow(overflow andabs(i64::MIN)areR0001), and in the preludemin,max,clamp,PIandE. Native programs now link with libm. - List methods
map,filter,any,all,fold,find,each,minandmax, also in the prelude. A line that starts with.continues the expression above it, for method chains. - List methods
sorted(),sorted_by(less),reversed(),slice(start, end)andindex_of(x). They are written in Brim, in the new modulestd.preludethat every program has. The built-in traitOrdallows<in generic code.
Brim v0.3.0
Added
- Floating-point numbers: the
f64type, literals (1.5,6.02e23), arithmetic and comparisons following IEEE 754,to_float,to_int(run-time errorR0010for NaN and out-of-range numbers),to_string,printandparse_float. Numbers are written with the fewest digits that read back exactly, the same in the interpreter and native code (checked on 200,000 values).std.jsongetsas_floatandfrom_float;brim gen tsmapsf64tonumber; every editor grammar knowsf64.i64andf64never mix implicitly, and the diagnostics say how to convert.E0007now means a floating-point literal too large forf64. - Visibility per field:
pub name: type; other fields are private to the struct's module (E0241when read, assigned or given elsewhere).pub import module.{X}re-exports items, and import lists can name constants. - Tuples:
(i64, string)types,(a, b)values, fieldst.0,(p, q)patterns inmatch, andlet (q, r) = divmod(17, 5)(E0251when the pattern can fail).==andprintwork on them, andbrim gen tswrites TypeScript tuples. - f-strings:
f"Hello, {name}! You are {age + 1}."shows each value asprintdoes;{{and}}are literal braces. Plain strings are unchanged. The formatter, tree-sitter grammar and VS Code grammar know them. ifandmatchas values:let sign = if n < 0 { -1 } else { 1 },return match shape { Circle(r) => r * r, ... }. A block's value is its last line; branches that return or break need none.E0250for anifwithoutelseand for blocks without a value.const NAME: T = valueat the top level (pub constusable asmodule.NAME), computed from literals, operators and other constants (E0249otherwise), andloop { ... }.constandloopare keywords now.letwithout a type:let total = 0,let name = user.nametake the type of the value.[],[:]andNonestill need an annotation.- Traits:
trait Shape { fn area(self) -> f64 },impl Shape for Circle { ... }(checked against the trait, withSelfin signatures), and bounds on type parameters (fn total[T: Shape + Show](...)) checked at every call. Calls through a bound compile to direct calls of the concrete method. The built-inEqandShowallow==andprintin generic code. New errorsE0246,E0247andE0248;traitis now a keyword. The tree-sitter grammar and the Helix, Zed and Neovim queries know the syntax. - Functions as values: function types
fn(A, B) -> R,fnexpressions (fn(x: i64) -> i64 { return x + n }) that copy the variables they use, named functions used as values, and calls of function values (f(3),button.on_click(3),make_adder(1)(2)). A closure is a function and a reference-counted environment, the same in the interpreter and in native code. Changing a captured variable isE0218. The tree-sitter grammar and the Helix, Zed and Neovim queries know the new syntax. - More integer types:
i32,u8andu64. Literals take the type the context needs, arithmetic and comparisons work on two integers of the same type, and results that do not fit stop the program withR0001in the interpreter and in native code.to_i32,to_u8,to_u64andto_intconvert between them with the same check;print,to_string,to_float,==andmatchwork on all of them. Bytes are aList[u8]:s.bytes()andstring_from_bytes(b). Every editor grammar knows the new names. Box[T]: one immutable value on the heap, so a struct or enum can contain itself (enum Expr { Num(i64), Add(Box[Expr], Box[Expr]) }).Box(value)creates one,b.value()reads it.E0221now suggests aBox. Every editor grammar knowsBox;brim gen tsmapsBox[T]toT.==,!=,printandto_stringwork on structs, enums, lists and maps (includingOptionandResult) whose values support them. Equality is structural (maps compare in any order); the text form looks like the code that builds the value, with strings quoted:Point { x: 1, y: 2 },Some("ada"),[1, 2],["ada": 36]. The compiler generates one function per type, in the interpreter and in native code alike.o == Noneno longer needs an annotation.?converts errors: when the function's error type is an enum with exactly one variant holding the operand's error type, the error is wrapped in that variant (ParseErrorbecomesConfigError.Parse(...)). Without such a variant, or with two,E0233says what to add or that the choice is ambiguous.- Richer
matchpatterns: patterns nest (Some(Shape.Circle(r)),Ok(0)),|joins alternatives (1 | 2 | 3,Some(Empty) | None), a lowercase name binds the whole value, andpattern if conditionadds a guard. Exhaustiveness is checked at every depth, and the error lists example values that no arm matches (not covered: Some(Rect(_, _))). Unreachable arms and alternatives warn withW0004; alternatives that bind different names areE0245. The tree-sitter grammar and the Helix, Zed and Neovim queries know the new syntax. - A Dockerfile for the notes example (
examples/http), which CI builds, runs and calls. The example readsHOSTas well asPORT.
Changed
- Struct fields are private to their module unless declared
pub. The standard library marks the fields programs use (http.Request,http.Response,time.Time,time.DateTime) aspub; code that reads fields of its own structs from other modules needspubon them. Boxis a built-in type now, so a struct or enum namedBoxmust be renamed (E0219).
Fixed
- Freeing deeply nested values (lists of lists, or chains of boxes) no longer overflows the stack, in the interpreter and in native code.
Brim v0.2.0
Added
- Standard library modules written in Brim and built into the compiler, imported with
import std.x. std.net: TCP listeners and connections (listen,connect,accept,read_line,read_until,read_exact,read_all,write,set_timeout), in the interpreter and native executables alike.std.http: an HTTP/1.1 server (serve,Server.next,Request.respond, text, JSON and HTML responses, query parameters, chunked request bodies, 400 for malformed requests) and client (get,post,request,content-length, chunked and until-close bodies), plus URLencodeanddecode.std.time: the current time, dates in UTC (iso,date,http_date,parts), a monotonic clock for durations, andsleep.std.log:info,warnanderrorlines with a timestamp on standard error. The notes example logs every request with its duration.- Limits in the
std.httpserver: request heads over 64 KiB get 431 and bodies over 10 MiB (Server.with_max_body) get 413, also for chunked bodies.net.Conn.read_until_maxreads up to a delimiter with a size limit. https://requests instd.http, through libcurl: the interpreter uses thecurlcrate, and native programs that use the HTTP client link with libcurl (servers and other programs do not). Certificates are checked; errors arecertificate not trusted,TLS handshake failedand the network reasons.std.json: aJsonvalue type,parse(RFC 8259, with positions in errors),stringify,pretty, and functions to build and read values. Numbers keep their text, so no precision is lost.examples/http/notes.brim, a JSON API for notes built withstd.httpandstd.json.- Structs and enums can contain themselves through
ListandMap, for trees and JSON-like values (enum Json { Array(List[Json]), ... }). The checker already allowed it; lowering looped forever.
Changed
- Only functions reachable from
mainand the tests are compiled, so unused functions of imported modules cost nothing.
Fixed
- An assignment to a map entry whose value uses
?(m[key] = parse(x)?) produced invalid IR when the key was not an integer.
Brim v0.1.1
Added
install.sh(macOS, Linux) andinstall.ps1(Windows) install the latest release, after checking its checksum.- A standard library reference on the documentation site, with an example for every part.
- Releases include the VS Code extension as a
.vsixfile, and can publish it to the Visual Studio Marketplace and Open VSX and update a Homebrew formula (scripts/homebrew-formula.sh). - Helix indent and text object queries.
- The editor packages are tested in Neovim, Helix, Kakoune, nano, micro and Kate in CI (
editors/test/run.sh).
Fixed
?in a method withmut selfproduced invalid IR (an internal compiler error): its early return now also gives backself.
Brim v0.1.0
Added
- Enums:
enum Shape { Circle(i64), Rect(i64, i64), Empty }, constructed withShape.Circle(1), andmatchstatements with variant, literal and_patterns, exhaustiveness checking and unreachable-arm warnings (W0004). - Generics: type parameters on functions, structs and enums (
fn swap[A, B](p: Pair[A, B]) -> Pair[B, A]), with type arguments inferred from arguments and annotations, compiled by monomorphization. - Built-in
Option[T](Some,None) andResult[T, E](Ok,Err). - The
?operator:parse(s)?continues with theOk/Somevalue, or returns theErr/Nonefrom the function (E0232,E0233). - New diagnostics
E0225toE0231andW0004;enumandmatchare now keywords, and[,]and=>are tokens. examples/shapes.brim.List[T]: literals ([1, 2, 3]), indexing (xs[i], run-time errorR0005outside the list), element assignment (xs[i] = v), and the methodslen,is_empty,get,first,last,contains,join,push,pop,insert,removeandclear. Lists are values with copy-on-write; changing a list that is not shared happens in place, also inside structs and nested lists.for x in list { ... }andfor i in a..b { ... };forandinare keywords and..is a token.- IR: list types and instructions,
take, and consumed operands (checked by the validator). - New diagnostics
E0234andE0235;examples/lists.brim. Map[K, V]withi64,boolorstringkeys: literals (["a": 1],[:]), indexing (m[k], run-time errorR0006for a missing key), assignment through keys, and the methodslen,is_empty,get,contains_key,keys,values,insert,removeandclear. Entries keep insertion order. Maps are values with copy-on-write.E0236for map keys of other types;examples/maps.brim.- Modules: every file is a module;
import a.b,import a.b as candimport a.b.{X, y}, withpubfor items and methods. Diagnostics show labels in other files with:::. New diagnosticsE0241toE0243;import,pubandasare keywords.tests/modulesholds multi-module test programs. - Standard library: string methods (
len,is_empty,contains,starts_with,ends_with,find,slice,trim,trim_start,trim_end,to_upper,to_lower,replace,repeat,split,lines,chars,parse_int), string comparison with<and friends, and the builtinseprint,read_line,read_file,write_file,args,envandexit. Run-time errorR0007for invalid string slices. brim test [PATH] [FILTER]runs the program's tests, the functions namedtest_..., and reports each one;mainis optional for it. The builtinsassertandassert_eq(oni64,boolandstring) stop the program with run-time errorR0008, which shows both values. New diagnosticE0244.- A documentation site in
site/(mdBook): introduction, getting started, a tour of the language, projects and tools, and the reference documents fromdocs/. A test runs every example on it and compares the output; a workflow builds it and can publish it to GitHub Pages. - A release process (
docs/releasing.md) with stability rules per edition, and a release workflow that buildsbrimfor Linux (x86_64, aarch64), macOS (aarch64) and Windows (x86_64), plus Linux and macOS builds with the LLVM backend linked in statically (new featurellvm-static).brim --versionsays whether the native backend is included. - Fuzzing:
crates/brim-cli/tests/fuzz_smoke.rsruns mutants of all example and test programs through the frontend, the formatter and the interpreter with every test run;fuzz/has cargo-fuzz targets (frontend,fmt,run,manifest), run weekly in CI. brim_interp::Limits::max_steps, an optional limit on executed instructions for embedders, with run-time errorR0009.brim lsp, a language server over standard input and output (new cratebrim-lsp): diagnostics for every file of the program as you type, formatting, document symbols, go to definition and hover for variables, parameters, functions, types, fields, variants, methods and modules. Program loading moved to the new cratebrim-driver, shared with the command line.- Support for every common editor in
editors/: a tree-sitter grammar (tree-sitter-brim, parsing every example and test program) with packages for Neovim, Helix and Zed, and highlighting plus language server setup for Emacs (brim-mode), Sublime Text (also bat), JetBrains IDEs, Kate, Kakoune, Vim, nano, micro and Notepad++. CI checks the grammars and that every one knows all keywords and builtins. - Editor support in
editors/: a VS Code extension (TextMate grammar, file icon for.brim, language configuration, language client) and a Vim syntax file. A test keeps the grammars in step with the keywords and builtins. brim gen ts [PATH] [-o FILE]writes TypeScript declarations for the program'spubstructs and enums and the types they use, describing them as JSON (see the language specification, section 9.4). New cratebrim-tsgen, errorG0001,examples/api.brimwithexamples/api.ts.- Dependencies:
[dependencies]inbrim.tomlwith{ path = "..." }or{ git = "...", tag/branch/rev = "..." }.import depuses the dependency's library root (src/lib.brim, or[build] lib),import dep.a.bits other modules. Git dependencies are cached in$BRIM_HOME/gitand their commits recorded inbrim.lock;brim updatemoves them to the newest commits. New cratebrim-package; manifest errorsM0006toM0010. brim fmt [--check] [PATH...]formats source files in place (or standard input with-): indentation, spaces between tokens and blank lines, keeping comments and line breaks. It refuses files with syntax errors and verifies that formatting does not change the tokens. New cratebrim-fmt.brim new PATHcreates a project with a manifest,src/main.brimwith a test, and a.gitignore.brim run PROGRAM ARGS...passes arguments to the program, and the program's exit code becomesbrim run's.examples/wc.brim, a smallwc.- Methods:
impl Type { fn name(self, ...) }, withself(a copy),mut self(changes the caller's value, which is moved into the method so lists in it change in place) and methods withoutselfcalled on the type (Stack.new()). Generic types get genericimplblocks. New diagnosticsE0237toE0240;implandselfare keywords. - Structs:
structdeclarations, struct literals (Point { x: 1, y: 2 }), field access (p.x) and field assignment (p.x = 3,p.from.y += 1), with value semantics. Supported by the interpreter and the native backend, including reference counting of strings inside structs. New diagnosticsE0219toE0224;structis now a keyword. E0007for floating-point literals such as9.99.examples/structs.brim.- Native code generation:
brim buildcompiles a program with LLVM 22 and links it with a small C runtime into a native executable. Opt-in at compile time with thellvmCargo feature (cargo build --features brim-cli/llvm); without it,brim buildstill reports the backend as unavailable. brim build -o <path>andbrim build --release. Projects build totarget/<package name>.- Native executables report run-time errors exactly like
brim run, including the call stack and the 10,000-call depth limit. - Differential tests that build every integration program and example natively (debug and release) and compare stdout, stderr and exit code with the interpreter; a CI job with LLVM 22 on Linux and macOS.
- Integration programs for
i64::MIN / -1and negation overflow. - Reference counting for strings in native executables: strings are freed when their last reference goes away (a loop building 5 million strings now peaks at under 2 MB instead of over 300 MB).
BRIM_RT_CHECK=1runtime check mode for native executables: use after free aborts and leaks are reported. The differential tests run every program with it.- Control flow:
if/else/else if,whileloops,breakandcontinue. - Mutable variables with
let mut, assignment and compound assignment (+=,-=,*=,/=,%=). to_stringbuiltin fori64andbool.- Divergence-based return checking:
if/elsewhere both branches return, andwhile truewithoutbreak, count as never reaching the end. - New diagnostics:
E0217(break/continueoutside a loop),E0218(assignment to an immutable variable),W0003(unneededmut). examples/control_flow.brim.- Initial Rust workspace for the Brim toolchain.
- Language specification draft for Brim 0.1 (edition 2026), with an EBNF grammar.
- Lexer with UTF-8 spans, string escapes, integer literals, reserved keywords and error recovery.
- Recursive-descent parser with precedence climbing, newline-terminated statements, error recovery and a nesting limit.
- Semantic analysis: scopes, function table, type checking for
i64,bool,stringandvoid, entry-point validation, typo suggestions and warnings. - Diagnostics system with error codes, labels, notes, help and colored rendering.
- Brim IR with a text form and validator, and lowering from the checked program.
- Reference interpreter with checked integer arithmetic and located run-time errors.
- Native backend interface (
brim-codegen). The LLVM backend is not implemented, andbrim buildreports it as unavailable. - Runtime ABI definition and builtin catalogue (
print). brim.tomlmanifest parsing and validation.brimCLI:check(with--emit tokens|ast|ir),run,build,help,version.- Examples, fixture-based test suites, and CI for formatting, linting and tests on Linux, macOS and Windows.
Fixed
- Internal compiler error (invalid IR) when
&&or||appeared in an operand or argument after another value, as into_string(1) + to_string(a && b)orf(x, a || b).
Changed
brim-codegennow depends on `brim-diag...