# def
def name [= expr]
Declare a dynamically-typed local variable, or a script binding at top level. An unassigned `def` reads as `null`.
def x = 5
println(x) // => 5
groovyrs v0.1.9 · Groovy on fusevm · lex/parse → AST → bytecode → Cranelift JIT · no bespoke VM, no JVM · MIT · in active development
Every name the current groovyrs build recognizes — reserved words, literal forms, contextual keywords, operators, the script print commands, every dispatched GDK method, every readable property, the class-member hooks the runtime calls by name, the modeled throwable hierarchy, and the built-in type names instanceof answers for — each with a signature, a description, and a runnable example. This page is generated from the language-server corpus (src/lsp.rs) by the gen-docs binary, so it stays in sync with what the runtime and editor tooling actually know about. Reserved words and literal forms mirror lexer.rs, contextual keywords and operators mirror parser.rs and compiler.rs, and every method, property, hook, throwable, and type name mirrors a real dispatch arm in src/host.rs or a real table in src/throwable.rs / src/compiler.rs. Where groovyrs diverges from Apache Groovy the entry says so.
defdef name [= expr]
Declare a dynamically-typed local variable, or a script binding at top level. An unassigned `def` reads as `null`.
def x = 5
println(x) // => 5
ifif (cond) stmt
Conditional branch. The condition goes through Groovy truth (`host::groovy_truthy`), so an empty string, an empty list, `0`, and `null` are all false.
if (1 < 2) println("yes") // => yes
elseif (cond) stmt else stmt
The fallback branch of an `if`. Binds to the nearest unmatched `if`.
if (false) println("a") else println("b") // => b
whilewhile (cond) stmt
Loop while the condition is Groovy-truthy; the test runs before the first iteration.
def i = 0
while (i < 3) i++
println(i) // => 3
dodo stmt while (cond)
Post-tested loop: the body runs once before the condition is evaluated.
def i = 0
do { i++ } while (i < 3)
println(i) // => 3
forfor (init; cond; update) stmt | for (name in iterable) stmt
C-style three-clause loop, or the `in` form over a range, list, map, or String. The `in` form materialises its subject through `host::GITER` first.
for (i in 0..2) print(i) // => 012
infor (name in iterable)
The iteration separator of a `for` loop. Walks a range's integers, a list's elements, a map's entries, or a String's characters.
for (n in [1, 2, 3]) print(n) // => 123
switchswitch (subject) { case label: … default: … }
Multi-way branch, in statement or value position. Each label is tested with Groovy's `isCase` (`host::GIS_CASE`), so a constant, a range, a list, a type name, a `~/…/` pattern, or a closure all work as labels. As an expression it answers the matching arm, and `null` when none matched — no exhaustiveness is required.
switch (5) { case 4..6: println("in"); break; default: println("out") } // => in
casecase label[, label…]: | case label[, label…] -> value
One `switch` label, or several sharing an arm. A colon section falls through to the next until a `break`; an arrow arm runs alone and is valued by its trailing expression, so a braced body is a block (`case 2 -> { 5 }` is 5). The two forms may not be mixed in one `switch`. A COMMA list is switch-expression grammar: writing `case 3, 4:` makes the whole switch an expression, so every arm must yield or throw and `break` is no longer one of its statements.
println(switch (1) { case 1, 2 -> "low"; default -> "hi" }) // => low
yieldyield expr
The value of the enclosing `switch` expression, which it also leaves — running any `finally` it jumps over. Contextual: only inside a `switch` arm is `yield` this statement, so a program may still use the name elsewhere.
println(switch (1) { case 1: yield "one"; default: yield "d" }) // => one
defaultdefault: | default ReturnType method(params) { … }
The `switch` section entered when no `case` label matched; a duplicate `default` is a parse error. Inside an `interface` body it instead marks a method that carries an implementation.
switch (9) { case 1: break; default: println("d") } // => d
assertassert cond [ : message ]
Raise `PowerAssertionError` when the condition is falsy, printing the source text with each recorded sub-expression's value under the column it occupied. The `: message` form instead raises a plain `AssertionError` whose text is `<message>. Expression: <condition>`, with a `Values:` clause naming the condition's bare-variable operands.
assert 1 + 1 == 2 // passes silently
returnreturn [expr]
Return from the enclosing method, closure, or constructor; at script level it ends the script. A method with no `return` yields its last expression.
def f() { return 7 }
println(f()) // => 7
breakbreak [label]
Exit the nearest enclosing loop or `switch`. `break label` exits the loop carrying that label; an unknown label is a compile error.
for (i in 0..9) { if (i == 3) break; print(i) } // => 012
continuecontinue [label]
Skip to the next iteration of the nearest enclosing loop, or of the labeled one.
for (i in 0..3) { if (i == 1) continue; print(i) } // => 023
newnew Type([args])
Construct an instance. Fields across the whole superclass chain are materialised to `null`, initialisers run superclass-first, then the most-derived constructor of matching arity runs (`host::GNEW`).
class P { def x; P(v) { x = v } }
println(new P(7).x) // => 7
truetrue
The boolean true value, lexed as a reserved word.
println(true) // => true
falsefalse
The boolean false value.
println(1 > 2) // => false
nullnull
The null reference. A method call on `null` answers only `toString`, `equals`, and `getClass`; anything else raises `NullPointerException`.
def x
println(x) // => null
42<digits>
An integer literal. It is an `Integer` when it fits in 32 bits and a `Long` when it does not, which is the width its arithmetic wraps at: `1000000 * 1000000` is `-727379968`. A literal past `Long` range is a lex error, not a silent wrap.
println(42 + 1) // => 43
42L<digits>L | <digits>l
A long-suffixed integer literal. The suffix makes the literal a `Long` whatever its magnitude, so its arithmetic wraps at 64 bits rather than 32: `2000000000L + 2000000000L` is `4000000000` where the unsuffixed form is `-294967296`.
println(2000000000L + 2000000000L) // => 4000000000
0xFF0x<hex> | 0b<binary> | 0<octal>
A radix-prefixed integer literal. The digits are read as a magnitude and the literal takes the smallest type holding it, so `0xff` is an `Integer` and `0xFFFFFFFF` is the `Long` `4294967295`.
println(0xFF) // => 255
1_000_000<digits>_<digits>
An integer or decimal literal with `_` group separators. The separators are not part of the value.
println(1_000_000) // => 1000000
1.50<digits>.<digits> [g|G]
An unsuffixed decimal literal — a `java.math.BigDecimal`, kept as its exact source text so the literal's own scale survives. `1.50` prints with both fraction digits, which no `f64` could preserve.
println(1.50) // => 1.50
1.5d<digits>.<digits> d|D|f|F
A `d`/`f`-suffixed literal — an IEEE double (`Value::Float`). This is the only literal form that is *not* a `BigDecimal`. The `instanceof` table classifies by value shape rather than by literal form, so groovyrs answers `1.5d instanceof BigDecimal` true and `1.5 instanceof BigDecimal` false — Apache Groovy answers the opposite for both.
println(1.5d / 0.0d) // => Infinity
2.5e7<digits>[.<digits>]e[+|-]<digits>
An exponent literal. The exponent makes the literal a decimal with or without a fractional part, and the result is a `BigDecimal` unless a `d`/`f` suffix follows.
println(2.5e7) // => 2.5E+7
'text''…'
A single-quoted String — inert text. Backslash escapes are decoded, but `$` never interpolates.
println('a$b') // => a$b
"text""… $name … ${ expr } …"
A double-quoted String. With no placeholder it lexes as a plain String; with one it becomes a GString whose parts render through `toString()` at runtime (`host::GSTRING`). `$name` takes a dotted *property* path only, so `"$n.toString()"` reads the property `n.toString` and leaves `()` as text.
def n = 5
println("n=$n and ${n + 1}") // => n=5 and 6
~/pattern/~/…/
A regex literal — a pattern handle built by `host::GREGEX`. Only `\/` is special inside the delimiters; every other backslash escape passes through to the pattern. Modeled far enough to drive a `switch` label, whose `isCase` is a *full* match.
switch ("abc") { case ~/a.c/: println("m"); break } // => m
[a, b][expr, …]
A list literal. Lists are `Value::Array` and print with Groovy's `[1, 2, 3]` rendering.
println([1, 2, 3]) // => [1, 2, 3]
[][]
The empty list. Falsy under Groovy truth, so `if ([])` does not run.
if (![]) println("empty") // => empty
[k: v][key: expr, …] | [(expr): expr, …]
A map literal, built by `host::GMAKE_MAP` into an insertion-ordered map. A bare identifier key is the string of its own name; parenthesise the key to compute it.
println([a: 1, b: 2]) // => [a:1, b:2]
[:][:]
The empty map — the form that distinguishes an empty map from the empty list `[]`.
println([:].isEmpty()) // => true
{ a, b -> … }{ param, … -> body }
A closure literal with an explicit parameter list, including the zero-parameter form `{ -> … }`. It lowers to a subroutine region plus a runtime closure handle and captures the enclosing script bindings.
def add = { a, b -> a + b }
println(add(2, 3)) // => 5
{ it }{ body }
A closure literal with no parameter list: Groovy supplies the single implicit parameter `it`.
println([1, 2, 3].collect { it * 2 }) // => [2, 4, 6]
trytry { … } catch (T e) { … } [finally { … }]
Run a block with `catch` handlers and/or a `finally` cleanup. Recognised at statement start when followed by `{`; a `try` with neither a `catch` nor a `finally` is a parse error.
try { throw new Exception("x") } catch (Exception e) { println(e.message) } // => x
catchcatch (Type [| Type…] name) { … }
Handle a thrown value whose class chain reaches the named type. The multi-catch form `catch (A | B e)` tests each alternative in turn.
try { 1 / 0 } catch (ArithmeticException e) { println(e.message) } // => Division by zero
finallyfinally { … }
Cleanup block. Runs on every exit path out of the `try` — normal completion, a caught throwable, an uncaught one, and a `return`.
try { println("body") } finally { println("cleanup") } // => body then cleanup
throwthrow expr
Raise a throwable (`host::GTHROW`), unwinding to the innermost `catch` whose type matches. groovyrs has no unwind opcode: the throw parks the value and the compiler-emitted guards cut the stack back.
try { throw new IllegalStateException("bad") } catch (Exception e) { println(e) } // => java.lang.IllegalStateException: bad
class[modifiers] class Name [extends S] [implements I, …] { … }
Declare a class. Registration is a `host::GCLASS` call carrying the superclass, interfaces, field names, initialisers, methods, and constructors.
class P { def x = 1 }
println(new P().x) // => 1
interface[modifiers] interface Name [extends I, …] { … }
Declare an interface. `new` on one faults; its `default` methods are reachable from an implementing class through the interface closure.
interface Greet { default def hi() { "hi" } }
class A implements Greet {}
println(new A().hi()) // => hi
extendsclass Name extends Superclass
Name the direct superclass in a class header (or the supertype list in an interface header). Method lookup walks this chain most-derived first.
class A { def f() { 1 } }
class B extends A {}
println(new B().f()) // => 1
implementsclass Name implements Iface, …
Name the interfaces a class implements. They participate in `instanceof` and in `catch` matching through the interface closure.
interface I {}
class A implements I {}
println(new A() instanceof I) // => true
instanceofvalue instanceof Type
Runtime type test (`host::GINSTANCEOF`) at relational precedence. Answers for declared classes, the 25 modeled throwables, and the 22 built-in type names. `null instanceof X` is always false.
println("x" instanceof String) // => true
packagepackage name.path
A leading package declaration. Parsed and skipped — groovyrs has no package namespace, so the line has no runtime effect.
package demo
println(1) // => 1
importimport name.path[.*]
A leading import. Parsed and skipped: the built-in type and throwable names resolve without one, and there is no classpath to import from.
import java.util.List
println([1].size()) // => 1
publicpublic …
Access modifier on a type declaration or class member. Accepted and skipped — groovyrs enforces no access control.
class A { public def f() { 1 } }
println(new A().f()) // => 1
privateprivate …
Access modifier. Accepted and skipped: a `private` member is reachable from anywhere, which is a deliberate divergence from Groovy.
class A { private def x = 1 }
println(new A().x) // => 1
protectedprotected …
Access modifier. Accepted and skipped, like `private`.
class A { protected def x = 2 }
println(new A().x) // => 2
staticstatic …
Member modifier. Accepted and skipped — groovyrs has no static storage, so a `static` field is an ordinary per-instance field.
class A { static def f() { 3 } }
println(new A().f()) // => 3
finalfinal …
Immutability modifier. Accepted and skipped; groovyrs does not reject a later write.
class A { final def x = 4 }
println(new A().x) // => 4
abstractabstract …
Abstractness modifier. Accepted and skipped: groovyrs does not refuse `new` on an `abstract` class the way it refuses it on an `interface`.
abstract class A { def f() { 5 } }
println(new A().f()) // => 5
synchronizedsynchronized …
Member modifier. Accepted and skipped — a groovyrs script runs on one thread, so there is nothing to synchronise.
class A { synchronized def f() { 6 } }
println(new A().f()) // => 6
transienttransient …
Serialization modifier. Accepted and skipped; groovyrs has no serialization.
class A { transient def x = 7 }
println(new A().x) // => 7
volatilevolatile …
Memory-visibility modifier. Accepted and skipped, like `synchronized`.
class A { volatile def x = 8 }
println(new A().x) // => 8
thisthis[.member]
The receiver inside a class member. A bare field or method name inside a class body already resolves through `this`, so the explicit form is rarely needed.
class A { def x = 1; def f() { this.x } }
println(new A().f()) // => 1
supersuper(args) | super.method(args)
Invoke the superclass constructor (`host::GSUPER_CTOR`, valid as the first statement of a constructor) or a superclass method non-virtually (`host::GSUPER_METHOD`).
class A { def f() { "A" } }
class B extends A { def f() { super.f() + "B" } }
println(new B().f()) // => AB
itit
The implicit single parameter of a closure written without a parameter list. It is an ordinary binding, so a closure with explicit parameters has no `it`.
println([1, 2].collect { it + 1 }) // => [2, 3]
+a + b
Addition. Two integers stay integral, a decimal operand keeps `BigDecimal` scale, a `double` operand promotes to a double, a String operand concatenates (rendering the other side through `toString()`), a list operand appends, and a map operand merges. On a class instance it dispatches `plus`.
println(1 + 2)
println("a" + 1) // => 3 then a1
-a - b
Subtraction over the same numeric tower as `+`. On a class instance it dispatches `minus`.
println(5 - 2) // => 3
*a * b
Multiplication. On a class instance it dispatches `multiply`.
println(3 * 4) // => 12
/a / b
Division, lowered to the `GDIV` builtin rather than a VM opcode. Two integers that divide exactly yield an integer; anything else yields a `BigDecimal` — never a double, unless an operand already is one. A zero divisor raises `ArithmeticException`. On a class instance it dispatches `div`.
println(7 / 2)
println(4 / 2) // => 3.5 then 2
%a % b
Remainder. The compiler emits a bare opcode when it can prove the divisor non-zero and a guarded builtin call otherwise. On a class instance it dispatches `remainder`, which is Groovy's mapping — not `mod`.
println(5 % 3) // => 2
- (unary)-a
Arithmetic negation. On a class instance it dispatches `negative`.
println(-(-3)) // => 3
!!a
Logical negation of the operand's Groovy truth, so `![]`, `!""`, `!0`, and `!null` are all true.
println(!false) // => true
==a == b
Equality. Groovy's `==` is value equality, not identity, and it is null-safe. On a class instance it uses `compareTo(…) == 0` when the class defines `compareTo`, a user `equals` otherwise, and heap identity with neither.
println([1, 2] == [1, 2]) // => true
!=a != b
The negation of `==`, resolved through the same instance rules.
println(1 != 2) // => true
<a < b
Less-than. On a class instance it dispatches `compareTo`; a class without one falls back to comparing the rendered strings.
println(1 < 2) // => true
>a > b
Greater-than, resolved like `<`.
println(3 > 2) // => true
<=a <= b
Less-than-or-equal, resolved like `<`.
println(2 <= 2) // => true
>=a >= b
Greater-than-or-equal, resolved like `<`.
println(2 >= 3) // => false
<=>a <=> b
The spaceship operator — `compareTo`, lowered to the `GCMP` builtin. Yields a negative number, zero, or a positive number.
println(5 <=> 3) // => 1
&&a && b
Short-circuiting logical and. Both operands go through Groovy truth; the result is a `Boolean`, not the operand.
println(1 && "x") // => true
||a || b
Short-circuiting logical or, with the same truth rules as `&&`.
println(0 || 3) // => true
?:a ?: b
The Elvis operator. Evaluates the left side once and yields it when Groovy-truthy, otherwise the right side. Unlike `||` it yields the *operand*, not a `Boolean`.
println(null ?: "d")
println("" ?: "d") // => d then d
? :cond ? a : b
The ternary conditional. The condition goes through Groovy truth.
println(true ? 1 : 2) // => 1
?.recv?.member | recv?.method(args)
Safe navigation. Yields `null` without dispatching when the receiver is `null`, so a chain of `?.` never raises `NullPointerException`.
def x
println(x?.size()) // => null
*.recv*.member | recv*.method(args)
The spread-dot operator. Desugars to `recv.collect { it?.member }` — including the safe navigation, which is why a `null` element spreads to `null` rather than raising.
println([1, 2, 3]*.toString()) // => [1, 2, 3]
[ ]recv[index]
Subscript, lowered to the `GINDEX` builtin. A list index past the end yields `null` and a negative index counts from the end; a String subscript yields a one-character String and raises past the end; a map subscript is a key read. On a class instance it dispatches `getAt`.
println([1, 2, 3][-1])
println("hello"[1]) // => 3 then e
..a..b
An inclusive range — a `groovy.lang.Range` object, so `(0..3).class.simpleName` is `IntRange` and printing one shows `0..3`. Being a `java.util.List` in Groovy, every list method and operator applies to it as well.
println(0..3) // => [0, 1, 2, 3]
..<a..<b
A half-open range: the endpoint is excluded, so `(0..<3)` enumerates `0, 1, 2` and prints `0..<3`.
println(0..<3) // => [0, 1, 2]
++x++ | ++x
Increment. Postfix yields the value before the update, prefix the value after. On a class instance it dispatches `plus` — not Groovy's `next`, which is a deliberate divergence.
def i = 0
println(i++)
println(i) // => 0 then 1
--x-- | --x
Decrement, mirroring `++`; on a class instance it dispatches `minus` rather than Groovy's `previous`.
def i = 2
println(--i) // => 1
=target = expr
Assignment to a local, a script binding, a field, a property (`GSETPROP`), or a subscript. A property write to a name the class chain never declared raises `MissingPropertyException` rather than growing the object.
def x = 1
x = 2
println(x) // => 2
+=target += expr
Compound addition — the `+` lowering with a load before and a store after. Inside a class body a bare field target routes through the property builtins.
def x = 1
x += 2
println(x) // => 3
-=target -= expr
Compound subtraction.
def x = 5
x -= 2
println(x) // => 3
*=target *= expr
Compound multiplication.
def x = 3
x *= 4
println(x) // => 12
/=target /= expr
Compound division. Reuses the `GDIV` builtin, so `7 /= 2` yields a `BigDecimal`.
def x = 7
x /= 2
println(x) // => 3.5
%=target %= expr
Compound remainder, reusing the guarded `%` lowering.
def x = 7
x %= 3
println(x) // => 1
.recv.member | recv.method(args)
Member access. A call routes through the `GMETHOD` builtin and a read through `GPROP`; on a class instance a read prefers a user `getX()` getter over the raw field.
println("abc".size()) // => 3
->{ params -> body }
The closure parameter separator. Its presence — even with an empty list — is what makes the parameter list explicit and suppresses the implicit `it`.
println([1, 2].collect { n -> n * 10 }) // => [10, 20]
|catch (A | B name)
The multi-catch alternative separator. This is its only meaning: groovyrs has no bitwise-or operator.
try { 1 / 0 } catch (IOException | ArithmeticException e) { println("caught") } // => caught
@@Name
The annotation marker. Annotations are lexed and skipped before a class or member declaration; groovyrs attaches no meaning to any of them.
class A { @Override def toString() { "A" } }
println(new A()) // => A
label:name: loop
A statement label. Only a loop is a useful target, and only `break label` / `continue label` read it; naming a label no enclosing loop carries is a compile error.
outer: for (i in 0..3) { if (i == 1) break outer; print(i) } // => 0
printlnprintln([value])
Print a Groovy-formatted value and a trailing newline, then yield `null`. Parentheses are optional. A class instance renders through its `toString()`; a list renders as `[1, 2, 3]` and a map as `[a:1]`.
println("hi")
println([a: 1]) // => hi then [a:1]
printprint([value])
Print a Groovy-formatted value with no trailing newline, then yield `null`.
print("a"); print("b") // => ab
sizevalue.size() -> Integer
The element count: characters for a String, elements for a list, entries for a map. groovyrs answers `size()` on *every* receiver and yields `0` for a scalar, where Groovy raises `MissingMethodException` on, say, an `Integer`.
println("ab".size())
println([1, 2, 3].size()) // => 2 then 3
getClassvalue.getClass() -> Class
The `java.lang.Class` handle for the receiver, answered before the per-type table so it works on everything. `null.getClass()` answers `NullObject`'s class rather than raising, as in Groovy.
println(1.5.getClass().getName()) // => java.math.BigDecimal
toStringvalue.toString() -> String
The receiver rendered the way `println` renders it. A class instance uses its own `toString()` when it declares one; a throwable renders as `qualified.Name: message`.
println([1, 2].toString()) // => [1, 2]
equalsvalue.equals(other) -> Boolean
Value equality. Modeled explicitly only on a `null` receiver (`null.equals(null)` is true); on a class instance a user `equals` is dispatched, and on other receivers it is the `==` comparison.
def x
println(x.equals(null)) // => true
callclosure.call([args]) -> Object
Invoke a closure explicitly. `clo(args)` and `clo.call(args)` reach the same code path; calling `call` on a non-closure falls through to ordinary GDK dispatch.
def f = { a -> a * 2 }
println(f.call(4)) // => 8
lengthstring.length() -> Integer
The character count of a String — Unicode characters, not bytes.
println("héllo".length()) // => 5
toUpperCasestring.toUpperCase() -> String
The receiver uppercased. Uses Rust's Unicode-aware case mapping rather than a JDK locale.
println("abc".toUpperCase()) // => ABC
toLowerCasestring.toLowerCase() -> String
The receiver lowercased.
println("ABC".toLowerCase()) // => abc
trimstring.trim() -> String
The receiver with leading and trailing whitespace removed.
println(" x ".trim() + "!") // => x!
reversestring.reverse() -> String
The receiver's characters in reverse order.
println("abc".reverse()) // => cba
isEmptystring.isEmpty() -> Boolean
True when the String has no characters. This is a length test, not a whitespace test.
println("".isEmpty()) // => true
containsstring.contains(needle) -> Boolean
True when the rendered argument occurs as a substring. The argument is rendered first, so a non-String argument is compared by its printed form — where Apache Groovy raises `MissingMethodException` for one.
println("abc".contains("bc")) // => true
toIntegerstring.toInteger() -> Integer
Parse the *trimmed* text as an integer, range-checked to 32 bits. A failed parse — including one that overflows `Integer` — raises `NumberFormatException` naming the text.
println("42".toInteger() + 1) // => 43
toLongstring.toLong() -> Long
Parse the trimmed text as a 64-bit integer. Unlike `toInteger` it accepts values outside the 32-bit range.
println("2147483648".toLong()) // => 2147483648
toDoublestring.toDouble() -> Double
Parse the text the way `Double.parseDouble` does: surrounding whitespace and a trailing `d`/`f` are allowed, as are `Infinity` and `NaN` — but not Rust's extra `inf`/`nan` spellings or a hex literal.
println("1.5".toDouble() * 2) // => 3.0
toFloatstring.toFloat() -> Float
Identical to `toDouble` — groovyrs has one IEEE type, so there is no narrowing to 32-bit precision.
println("0.25".toFloat()) // => 0.25
toBigDecimalstring.toBigDecimal() -> BigDecimal
`new BigDecimal(text.trim())`. The failure carries `BigDecimal`'s own character-level diagnostics, including the message-less `NumberFormatException` an empty string produces.
println("1.50".toBigDecimal()) // => 1.50
isEmptylist.isEmpty() -> Boolean
True when the list has no elements.
println([].isEmpty()) // => true
containslist.contains(value) -> Boolean
True when some element matches. groovyrs compares the *rendered* forms, so `[1, 2].contains("1")` is true where Groovy's `equals`-based test is false.
println([1, 2, 3].contains(2)) // => true
getlist.get(index) -> Object
The element at `index`. Unlike the `[i]` subscript this is the raw JDK call: any out-of-range index raises `IndexOutOfBoundsException` instead of yielding `null`, and a negative index does not wrap.
println([10, 20].get(1)) // => 20
reverselist.reverse() -> List
A new list with the elements in reverse order. The receiver is not mutated.
println([1, 2, 3].reverse()) // => [3, 2, 1]
joinlist.join([separator]) -> String
Render each element the way `println` does and join them with the separator, which defaults to the empty string.
println([1, 2, 3].join("-")) // => 1-2-3
subListlist.subList(from, to) -> List
A live `java.util.ArrayList$SubList` window over `[from, to)` — a second reference to part of the backing list, not a copy. Writes travel both ways, and a structural write through the window splices the backing list and resizes the window. A structural change made to the backing list through any *other* reference invalidates the window: every later use raises `ConcurrentModificationException`. Bounds are the JDK's, checked in the JDK's order. On a `Range` the answer is another `Range`.
def a = [1, 2, 3, 4]; def s = a.subList(1, 3); s.set(0, 99); println(a) // => [1, 99, 3, 4]
addAlllist.addAll(collection) | list.addAll(index, collection) -> Boolean
Append the collection's elements, or insert them at `index`. Answers whether the list changed, so an empty argument is `false`.
def a = [1, 2]; a.addAll(1, [8, 9]); println([a, a.addAll([])]) // => [[1, 8, 9, 2], false]
eachlist.each { it -> … } -> List
Run the closure once per element for its side effects and yield the receiver. A `throw` inside the closure stops the iteration so the exception reaches the caller's handler.
[1, 2].each { print(it) } // => 12
eachWithIndexlist.eachWithIndex { it, i -> … } -> List
Like `each`, but the closure also receives the element's 0-based index.
[9, 8].eachWithIndex { v, i -> println("$i:$v") } // => 0:9 then 1:8
collectlist.collect { it -> … } -> List
Map each element through the closure into a new list of the same length.
println([1, 2, 3].collect { it * 2 }) // => [2, 4, 6]
findAlllist.findAll { it -> … } -> List
Keep the elements for which the closure's result is Groovy-truthy.
println([1, 2, 3].findAll { it > 1 }) // => [2, 3]
findlist.find { it -> … } -> Object
The first element the closure accepts, or `null` when none does.
println([1, 2, 3].find { it > 1 }) // => 2
injectlist.inject([seed]) { acc, val -> … } -> Object
Fold left. With a seed the fold starts there; without one it seeds with the first element and starts at the second. An empty list with no seed yields `null`.
println([1, 2, 3].inject(0) { a, b -> a + b }) // => 6
sumlist.sum([seed]) | list.sum { it -> … } -> Object
Add the elements, or the closure's results, using the `+` numeric tower — so a String element concatenates and a list element appends. An empty list with no seed yields `null`.
println([1, 2, 3].sum())
println([1, 2, 3].sum { it * 2 }) // => 6 then 12
sortlist.sort([true]) | list.sort { it -> key } | list.sort { a, b -> … } -> List
Order the elements naturally, by a one-parameter key closure, or by a two-parameter comparator. The sort is in place and answers the receiver, so every other name for that list sees it — whether the receiver is a variable, a map value, or an element of another list. `sort(false)` asks for a copy and leaves the receiver alone.
println([3, 1, 2].sort()) // => [1, 2, 3]
uniquelist.unique([true]) | list.unique { it -> key } -> List
Drop later duplicates, keeping source order. Comparison is the same natural-or-closure ordering `sort` uses, and it mutates the receiver in place the same way. `unique(false)` asks for a copy.
println([1, 1, 2].unique()) // => [1, 2]
maxlist.max([{ it -> key }]) -> Object
The greatest element, by natural order or by the closure's key.
println([3, 1, 2].max()) // => 3
minlist.min([{ it -> key }]) -> Object
The least element, by natural order or by the closure's key.
println([3, 1, 2].min()) // => 1
groupBylist.groupBy { it -> key } -> Map
A map from each closure result to the sublist of elements that produced it, with keys in first-seen order. The key is the rendered form of the closure's result.
println([1, 2, 3].groupBy { it % 2 }) // => [1:[1, 3], 0:[2]]
countBylist.countBy { it -> key } -> Map
A map from each closure result to how many elements produced it, keys in first-seen order.
println([1, 2, 3, 4].countBy { it % 2 }) // => [1:2, 0:2]
findIndexValueslist.findIndexValues([from]) { it -> … } -> List
Every index whose element the closure accepts, where `findIndexOf` answers only the first. An optional leading argument is the index to start from.
println([1, 2, 3].findIndexValues { it > 1 }) // => [1, 2]
curryclosure.curry(args…) -> Closure
A closure with `args` bound to the *leading* parameters; the rest are supplied at call time.
def add = { a, b -> a + b }
println add.curry(1)(2) // => 3
rcurryclosure.rcurry(args…) -> Closure
As `curry`, but the bound values go at the *end* of the supplied arguments.
def sub = { a, b -> a - b }
println sub.rcurry(1)(5) // => 4
ncurryclosure.ncurry(n, args…) -> Closure
As `curry`, but the bound values are spliced in at index `n` of the argument list.
def three = { a, b, c -> "$a$b$c" }
println three.ncurry(1, "X")("a", "c") // => aXc
memoizeclosure.memoize() -> Closure
A closure that runs the body once per distinct argument list and answers the recorded result thereafter. The cache is keyed by the rendered arguments and shared by every holder of the handle.
def n = 0
def f = { n++; it * 2 }.memoize()
f(3); f(3)
println n // => 1
andThenclosure.andThen(other) -> Closure
Composition running the receiver first and feeding its result to `other` — the same as Groovy's `>>`.
def inc = { it + 1 }
println inc.andThen { it * 2 }(3) // => 8
composeclosure.compose(other) -> Closure
Composition running `other` first — the same as Groovy's `<<`.
def inc = { it + 1 }
println inc.compose { it * 2 }(3) // => 7
isEmptymap.isEmpty() -> Boolean
True when the map has no entries.
println([:].isEmpty()) // => true
containsKeymap.containsKey(key) -> Boolean
True when the map holds the rendered key.
println([a: 1].containsKey("a")) // => true
getmap.get(key) -> Object
The value stored under the rendered key, or `null` when absent. Unlike `List.get` this never raises.
println([a: 1].get("a")) // => 1
keySetmap.keySet() -> List
The keys in insertion order. groovyrs yields a plain list rather than a `Set` view, so it is ordered and allows subscripting.
println([a: 1, b: 2].keySet()) // => [a, b]
keysmap.keys() -> List
A groovyrs synonym for `keySet`. Apache Groovy has no `Map.keys()` — this is an extension, not a port.
println([a: 1, b: 2].keys()) // => [a, b]
valuesmap.values() -> List
The values in insertion order, as a plain list.
println([a: 1, b: 2].values()) // => [1, 2]
subMapmap.subMap(keys) | map.subMap(k1, k2, …) -> Map
The entries for the listed keys, in the *receiver's* order. A key the map does not hold is dropped rather than read as `null`.
println([a: 1, b: 2].subMap(["a"])) // => [a:1]
spreadmap.spread() -> Map
A shallow copy of the map.
println([a: 1].spread()) // => [a:1]
intersectmap.intersect(other) -> Map
The entries `other` holds identically — same key *and* same value. `map.minus(other)` (`map - other`) is the complement.
println([a: 1, b: 2].intersect([a: 1])) // => [a:1]
iteratormap.iterator() -> Iterator
A live cursor over the map's entries. Also defined on a list, a range and a `String`; `next()` advances the shared handle and raises `NoSuchElementException` past the end.
println([a: 1].iterator().next()) // => a=1
eachmap.each { k, v -> … } | map.each { entry -> … } -> Map
Run the closure once per entry and yield the receiver. A two-parameter closure receives `(key, value)`; a one-parameter closure receives one `Map.Entry` — the closure's declared parameter count decides, as in Groovy.
[a: 1, b: 2].each { k, v -> println("$k$v") } // => a1 then b2
eachWithIndexmap.eachWithIndex { k, v, i -> … } -> Map
Like `each`, with the entry's 0-based index appended to the closure's arguments.
[a: 1].eachWithIndex { k, v, i -> print("$i:$k") } // => 0:a
collectmap.collect { k, v -> … } -> List
Map each entry through the closure. The result is a *list* of the closure's results, not a map — matching Groovy.
println([a: 1, b: 2].collect { k, v -> k + v }) // => [a1, b2]
findAllmap.findAll { k, v -> … } -> Map
Keep the entries the closure accepts, as a new map in source order.
println([a: 1, b: 2].findAll { k, v -> v > 1 }) // => [b:2]
findmap.find { k, v -> … } -> Map.Entry
The first accepted entry as a `Map.Entry` (which prints as `key=value`), or `null` when none matches.
println([a: 1, b: 2].find { k, v -> v > 1 }) // => b=2
anymap.any { k, v -> … } -> Boolean
True when the closure accepts at least one entry; stops at the first acceptance.
println([a: 1, b: 2].any { k, v -> v > 1 }) // => true
everymap.every { k, v -> … } -> Boolean
True when the closure accepts every entry; stops at the first rejection.
println([a: 1, b: 2].every { k, v -> v > 0 }) // => true
countmap.count { k, v -> … } -> Integer
How many entries the closure accepts.
println([a: 1, b: 2].count { k, v -> v > 1 }) // => 1
countBymap.countBy { k, v -> key } -> Map
A map from each closure result to how many entries produced it, keys in first-seen order.
println([a: 1, b: 2].countBy { k, v -> v % 2 }) // => [1:1, 0:1]
withDefaultmap.withDefault { key -> … } -> Map
A copy whose missing-key read runs the closure with that key, *stores* the result under it, and answers it — Groovy's `MapWithDefault`, which grows as it is read.
def m = [:].withDefault { 0 }
println m["z"]
println m // => 0 then [z:0]
groupBymap.groupBy { k, v -> key } -> Map
A map from each closure result to the *sub-map* of entries that produced it, keys in first-seen order.
println([a: 1, b: 2].groupBy { k, v -> v % 2 }) // => [1:[a:1], 0:[b:2]]
injectmap.inject(seed) { acc, entry -> … } -> Object
Fold over the entries, passing the accumulator and one `Map.Entry`. Unlike the list form the seed is required here.
println([a: 1, b: 2].inject(0) { a, e -> a + e.value }) // => 3
sortmap.sort([{ entry -> key }]) -> Map
A new map ordered by key, or by the closure's key over each entry. Unlike `List.sort` this never mutates or writes back to the receiver, which is also Groovy's behaviour.
println([b: 1, a: 2].sort()) // => [a:2, b:1]
maxmap.max { entry -> key } -> Map.Entry
The entry whose closure key is greatest, as a `Map.Entry`. The closure is required.
println([a: 2, b: 1].max { it.value }) // => a=2
minmap.min { entry -> key } -> Map.Entry
The entry whose closure key is least, as a `Map.Entry`.
println([a: 2, b: 1].min { it.value }) // => b=1
toStringdecimal.toString() -> String
The decimal rendered with its own scale preserved, so `1.50` keeps both fraction digits and `2.5e7` prints as `2.5E+7`.
println(1.50.toString()) // => 1.50
absdecimal.abs() -> BigDecimal
The magnitude, keeping the receiver's scale.
println((-1.5).abs()) // => 1.5
negatedecimal.negate() -> BigDecimal
The receiver with its sign flipped.
println(1.5.negate()) // => -1.5
toBigDecimaldecimal.toBigDecimal() -> BigDecimal
The receiver itself — the identity conversion, provided so a script can call it uniformly on a String or a decimal.
println(1.50.toBigDecimal()) // => 1.50
intValuedecimal.intValue() -> Integer
Truncate toward zero to an integer. This discards the fraction rather than rounding it.
println(1.99.intValue()) // => 1
longValuedecimal.longValue() -> Long
Truncate toward zero to a 64-bit integer — the same value `intValue` yields, since groovyrs holds one integer width.
println(1.99.longValue()) // => 1
toIntegerdecimal.toInteger() -> Integer
A truncating conversion, identical to `intValue`.
println(2.9.toInteger()) // => 2
toLongdecimal.toLong() -> Long
A truncating conversion, identical to `longValue`.
println(2.9.toLong()) // => 2
rounddecimal.round() -> Integer
Round to the nearest integer — the one conversion here that does not truncate.
println(1.50.round()) // => 2
doubleValuedecimal.doubleValue() -> Double
Convert to an IEEE double, giving up the exact decimal scale.
println(1.50.doubleValue()) // => 1.5
toDoubledecimal.toDouble() -> Double
Identical to `doubleValue`.
println(0.25.toDouble()) // => 0.25
floatValuedecimal.floatValue() -> Float
Identical to `doubleValue` — groovyrs has one IEEE width, so there is no narrowing to 32-bit precision.
println(1.25.floatValue()) // => 1.25
toFloatdecimal.toFloat() -> Float
Identical to `floatValue`.
println(1.25.toFloat()) // => 1.25
getNameclazz.getName() -> String
The fully-qualified class name. A script-declared class answers its bare name, as in Groovy's default package.
println("x".getClass().getName()) // => java.lang.String
getTypeNameclazz.getTypeName() -> String
The qualified name — the same string `getName` yields.
println([1].getClass().getTypeName()) // => java.util.ArrayList
getCanonicalNameclazz.getCanonicalName() -> String
The qualified name again. groovyrs models no nested or array classes, the two cases where the JDK's canonical name differs from `getName`.
println(1.getClass().getCanonicalName()) // => java.lang.Integer
getSimpleNameclazz.getSimpleName() -> String
The last dot-separated segment of the qualified name.
println("x".getClass().getSimpleName()) // => String
getKeyentry.getKey() -> String
The entry's key. Map keys are held as strings, so this always yields a String.
println([a: 1].find { k, v -> true }.getKey()) // => a
getValueentry.getValue() -> Object
The entry's value, of whatever type the map holds.
println([a: 1].find { k, v -> true }.getValue()) // => 1
sizevalue.size -> Integer
The count property on a String, list, or map. On a map this rule is *not* reached: a map's property access is only a key read, so `[a: 1].size` is `null` while `[size: 9].size` is `9`.
println([1, 2].size)
println([a: 1].size) // => 2 then null
lengthvalue.length -> Integer
A synonym of the `size` property, with the same map exception.
println("abc".length) // => 3
classvalue.class -> Class
The `getClass()` property, available on every value but a map — where it is a key read like any other name. On a class instance a declared field named `class` still wins.
println("a".class.simpleName) // => String
nameclazz.name -> String
The qualified name of a `java.lang.Class` handle, through Groovy's getter-to-property rule.
println(1.5.class.name) // => java.math.BigDecimal
typeNameclazz.typeName -> String
The qualified name of a class handle — the property form of `getTypeName()`.
println("x".class.typeName) // => java.lang.String
canonicalNameclazz.canonicalName -> String
The qualified name of a class handle — the property form of `getCanonicalName()`.
println([1].class.canonicalName) // => java.util.ArrayList
simpleNameclazz.simpleName -> String
The last segment of a class handle's qualified name.
println([1].class.simpleName) // => ArrayList
keyentry.key -> String
The key of a `Map.Entry`, the property form of `getKey()`.
println([a: 1].find { k, v -> true }.key) // => a
valueentry.value -> Object
The value of a `Map.Entry`, the property form of `getValue()`.
println([a: 1].max { it.value }.value) // => 1
toStringdef toString() { … }
Declare it and `println`, string concatenation, GString interpolation, and `list.join` all render the instance through it.
class P { def x = 1; String toString() { "P($x)" } }
println(new P()) // => P(1)
equalsdef equals(other) { … }
Decides `==` and `!=` for instances of the class — but only when the class does not also define `compareTo`, which takes precedence.
class P { def equals(o) { true } }
println(new P() == new P()) // => true
compareTodef compareTo(other) { … }
Models `Comparable`. It drives `<`, `>`, `<=`, `>=`, `<=>`, `sort`, `unique`, `max`, `min` — and equality too, where `==` becomes `compareTo(…) == 0`.
class P { def n = 1; def compareTo(o) { 0 } }
println(new P() == new P()) // => true
asBooleandef asBoolean() { … }
Defines the instance's Groovy truth for `if`, `while`, `&&`, `||`, `?:`, and `findAll`. An instance whose class does not declare it is always truthy.
class P { def asBoolean() { false } }
if (new P()) println("t") else println("f") // => f
getAtdef getAt(index) { … }
Defines the `[…]` subscript on the instance. The subscript is reported as a missing `getAt` when the class does not declare one.
class P { def getAt(i) { i * 2 } }
println(new P()[4]) // => 8
plusdef plus(other) { … }
The `+` operator on the instance. `++` also dispatches here — groovyrs does not model Groovy's `next`.
class P { def plus(o) { 42 } }
println(new P() + 1) // => 42
minusdef minus(other) { … }
The `-` operator on the instance, and the operator `--` dispatches to.
class P { def minus(o) { 7 } }
println(new P() - 1) // => 7
multiplydef multiply(other) { … }
The `*` operator on the instance.
class P { def multiply(o) { 6 } }
println(new P() * 2) // => 6
divdef div(other) { … }
The `/` operator on the instance. It is resolved inside the `GDIV` builtin rather than through the numeric hook the other operators use.
class P { def div(o) { 9 } }
println(new P() / 1) // => 9
remainderdef remainder(other) { … }
The `%` operator on the instance. Groovy maps `%` to `remainder`, not to `mod` — verified against Apache Groovy 5.0.7.
class P { def remainder(o) { 3 } }
println(new P() % 2) // => 3
negativedef negative() { … }
Unary `-` on the instance.
class P { def negative() { -5 } }
println(-new P()) // => -5
powerdef power(other) { … }
Groovy's `**` operator method. The mapping exists in the runtime, but groovyrs's lexer has no `**` token, so nothing can reach this hook today.
class P { def power(o) { 8 } }
println(new P().power(3)) // => 8
get<Name>def getName() { … }
A getter. Reading the property `obj.name` prefers this method over the raw field, and calling `obj.getName()` falls back to the field when no such method exists. Note that a getter which reads its own backing field re-enters itself in the current build, so the body must not name the field it fronts.
class P { def x = 1; def getX() { 99 } }
println(new P().x) // => 99
set<Name>def setName(value) { … }
A setter. Writing `obj.name = v` prefers this method over the raw field write. As with the getter, assigning to the backing field of the same name re-enters the setter in the current build, so write through a differently-named field.
class P { def y = 0; def setX(v) { y = v * 2 } }
def p = new P()
p.x = 5
println(p.y) // => 10
Throwablenew Throwable([String message]) — java.lang
The root of the modeled hierarchy and the only type that declares the `message` field; every descendant inherits it. `catch (Throwable e)` matches everything a script can throw.
try { throw new Throwable("t") } catch (Throwable e) { println(e) } // => java.lang.Throwable: t
Exceptionnew Exception([String message]) — java.lang
The checked-exception root, directly under `Throwable`. It does not match an `Error`, so `catch (Exception e)` will not catch an `AssertionError`.
try { throw new Exception("x") } catch (Exception e) { println(e.message) } // => x
Errornew Error([String message]) — java.lang
The unrecoverable-condition root, the sibling of `Exception` under `Throwable`. `AssertionError` lives beneath it.
try { throw new Error("e") } catch (Throwable t) { println(t) } // => java.lang.Error: e
RuntimeExceptionnew RuntimeException([String message]) — java.lang
The unchecked-exception root under `Exception`; most of the throwables the runtime raises itself descend from it.
try { throw new RuntimeException("r") } catch (Exception e) { println(e) } // => java.lang.RuntimeException: r
IllegalArgumentExceptionnew IllegalArgumentException([String message]) — java.lang
An argument outside a method's contract. Its one modeled subtype is `NumberFormatException`.
try { throw new IllegalArgumentException("bad") } catch (RuntimeException e) { println(e.message) } // => bad
NumberFormatExceptionnew NumberFormatException([String message]) — java.lang
Raised by `String.toInteger`, `toLong`, `toDouble`, `toFloat`, and `toBigDecimal` when the text does not parse. The `toBigDecimal` path can raise the message-less form, which prints with no `: message` suffix.
try { "x".toInteger() } catch (NumberFormatException e) { println(e.message) } // => For input string: "x"
IllegalStateExceptionnew IllegalStateException([String message]) — java.lang
An operation attempted in the wrong state. groovyrs never raises it itself; it is here for scripts to throw.
try { throw new IllegalStateException("bad") } catch (Exception e) { println(e) } // => java.lang.IllegalStateException: bad
ArithmeticExceptionnew ArithmeticException([String message]) — java.lang
Raised by division and remainder with a zero divisor. The message is `Division by zero` for a decimal divisor, `/ by zero` for an integer one, and `Division undefined` for `0/0`.
try { 1 / 0 } catch (ArithmeticException e) { println(e.message) } // => Division by zero
NullPointerExceptionnew NullPointerException([String message]) — java.lang
Raised by a method call, property read, or property write on `null` — except `toString`, `equals`, and `getClass`, which `null` answers.
try { null.foo() } catch (NullPointerException e) { println(e.message) } // => Cannot invoke method foo() on null object
IndexOutOfBoundsExceptionnew IndexOutOfBoundsException([String message]) — java.lang
Raised by `List.get` for any index outside the list. The `[i]` subscript does not raise it — a list subscript past the end yields `null`.
try { [1].get(5) } catch (IndexOutOfBoundsException e) { println(e.message) } // => Index 5 out of bounds for length 1
ArrayIndexOutOfBoundsExceptionnew ArrayIndexOutOfBoundsException([String message]) — java.lang
Raised by a negative subscript whose magnitude exceeds the receiver's length, on a list or a String.
try { [1][-5] } catch (ArrayIndexOutOfBoundsException e) { println(e.message) } // => Negative array index [-5] too large for array size 1
StringIndexOutOfBoundsExceptionnew StringIndexOutOfBoundsException([String message]) — java.lang
Raised by a String subscript past the end, naming the half-open range it tried to read.
try { "ab"[9] } catch (StringIndexOutOfBoundsException e) { println(e.message) } // => Range [9, 10) out of bounds for length 2
UnsupportedOperationExceptionnew UnsupportedOperationException([String message]) — java.lang
An operation a type does not support. Registered for scripts to throw; the runtime does not raise it.
try { throw new UnsupportedOperationException("no") } catch (RuntimeException e) { println(e.message) } // => no
ClassCastExceptionnew ClassCastException([String message]) — java.lang
A bad cast. groovyrs has no cast operator, so only a script raises this.
try { throw new ClassCastException("c") } catch (Exception e) { println(e) } // => java.lang.ClassCastException: c
InterruptedExceptionnew InterruptedException([String message]) — java.lang
Thread interruption, directly under `Exception`. A groovyrs script runs on one thread, so this exists for hierarchy fidelity.
try { throw new InterruptedException("i") } catch (Exception e) { println(e) } // => java.lang.InterruptedException: i
CloneNotSupportedExceptionnew CloneNotSupportedException([String message]) — java.lang
Registered so the checked-exception branch under `Exception` matches the JDK's shape; groovyrs models no `clone`.
try { throw new CloneNotSupportedException("c") } catch (Exception e) { println(e) } // => java.lang.CloneNotSupportedException: c
AssertionErrornew AssertionError([String message]) — java.lang
Raised by the `assert cond : message` form. It sits under `Error`, so `catch (Exception e)` does not catch it.
try { assert false : "nope" } catch (AssertionError e) { println(e.message) } // => nope. Expression: false
IOExceptionnew IOException([String message]) — java.io
The I/O root. groovyrs performs no file I/O, so only a script raises it.
try { throw new IOException("x") } catch (Exception e) { println(e) } // => java.io.IOException: x
FileNotFoundExceptionnew FileNotFoundException([String message]) — java.io
A missing file, under `IOException`.
try { throw new FileNotFoundException("f") } catch (IOException e) { println(e) } // => java.io.FileNotFoundException: f
NoSuchElementExceptionnew NoSuchElementException([String message]) — java.util
An exhausted iterator or an absent element, under `RuntimeException`.
try { throw new NoSuchElementException("n") } catch (RuntimeException e) { println(e) } // => java.util.NoSuchElementException: n
ConcurrentModificationExceptionnew ConcurrentModificationException([String message]) — java.util
A collection mutated during iteration. groovyrs iterates over a materialised copy and so never raises it itself.
try { throw new ConcurrentModificationException("c") } catch (RuntimeException e) { println(e) } // => java.util.ConcurrentModificationException: c
GroovyRuntimeExceptionnew GroovyRuntimeException([String message]) — groovy.lang
The root of Groovy's own runtime failures, under `RuntimeException`. Both dispatch failures below descend from it.
try { throw new GroovyRuntimeException("g") } catch (RuntimeException e) { println(e) } // => groovy.lang.GroovyRuntimeException: g
MissingMethodExceptionnew MissingMethodException([String message]) — groovy.lang
Raised whenever a `recv.method(args)` combination falls outside the modeled GDK, rather than mis-running. The message names the method, the receiver's class, and the argument types.
try { "".bar() } catch (MissingMethodException e) { println(e.message) }
MissingPropertyExceptionnew MissingPropertyException([String message]) — groovy.lang
Raised by a read of an unmodeled property, and by a write to a field the class chain never declared — groovyrs does not grow an object on assignment.
try { 5.zz } catch (MissingPropertyException e) { println(e.message) } // => No such property: zz for class: java.lang.Integer
PowerAssertionErrornew PowerAssertionError([String message]) — org.codehaus.groovy.runtime.powerassert
What a bare `assert` raises. It overrides `toString` to print `Assertion failed:` followed by the source text with each recorded sub-expression's value laid out under the column it occupied.
try { assert 1 == 2 } catch (AssertionError e) { println(e.getClass().simpleName) } // => PowerAssertionError
Objectvalue instanceof Object
True for every non-null value. A qualified name is matched on its last segment, so `java.lang.Object` behaves identically.
println(1 instanceof Object) // => true
GroovyObjectvalue instanceof GroovyObject
True for every non-null value — groovyrs treats it as a synonym of `Object`. Apache Groovy restricts it to objects that implement the interface, and answers false for a `String`.
println("x" instanceof GroovyObject) // => true
Stringvalue instanceof String
True for a String value.
println("x" instanceof String) // => true
CharSequencevalue instanceof CharSequence
True for a String value — the same test `String` performs.
println("x" instanceof CharSequence) // => true
GStringvalue instanceof GString
True for a String value. An interpolated literal collapses to an ordinary String at runtime, so groovyrs cannot distinguish a GString from a plain one here.
def n = 1
println("$n" instanceof GString) // => true
Integervalue instanceof Integer
True for an integer value. groovyrs holds one 64-bit integer type, so this does not range-check to 32 bits.
println(1 instanceof Integer) // => true
Longvalue instanceof Long
True for an integer value — indistinguishable from `Integer` in groovyrs, where Apache Groovy answers false because an integer literal is an `Integer`.
println(1 instanceof Long) // => true
Shortvalue instanceof Short
True for an integer value, with no width check; Apache Groovy answers false because an integer literal is an `Integer`.
println(1 instanceof Short) // => true
Bytevalue instanceof Byte
True for an integer value, with no width check; Apache Groovy answers false because an integer literal is an `Integer`.
println(1 instanceof Byte) // => true
BigDecimalvalue instanceof BigDecimal
True for an IEEE double value. This is coarser than the value model: a decimal literal such as `1.5` lives on the host heap and is *not* matched here, while the `d`-suffixed `1.5d` is — the exact inverse of what Apache Groovy answers for the same two literals.
println(1.5d instanceof BigDecimal)
println(1.5 instanceof BigDecimal) // => true then false
Doublevalue instanceof Double
True for an IEEE double value.
println(1.5d instanceof Double) // => true
Floatvalue instanceof Float
True for an IEEE double value — groovyrs has one IEEE width.
println(1.5d instanceof Float) // => true
BigIntegervalue instanceof BigInteger
True for an IEEE double value. groovyrs models no arbitrary-precision integer, so this name resolves with the other floating types rather than with `Integer` — Apache Groovy answers false for a double.
println(1.5d instanceof BigInteger) // => true
Numbervalue instanceof Number
True for an integer or an IEEE double value.
println(1 instanceof Number) // => true
Booleanvalue instanceof Boolean
True for a boolean value.
println(true instanceof Boolean) // => true
Listvalue instanceof List
True for a list value — including a range, since a Groovy `Range` is a `java.util.List`.
println([1] instanceof List) // => true
ArrayListvalue instanceof ArrayList
True for a list value. `ArrayList` is also the class name a list reports from `getClass()`.
println((0..2) instanceof ArrayList) // => true
Collectionvalue instanceof Collection
True for a list value. groovyrs models no `Set`, so `Collection` and `List` answer identically.
println([1] instanceof Collection) // => true
Iterablevalue instanceof Iterable
True for a list value. Note that a String and a map are both iterable in a `for (x in …)` loop yet do not answer true here.
println([1] instanceof Iterable) // => true
Mapvalue instanceof Map
True for a map value, whether it is a fusevm hash or an insertion-ordered host map.
println([a: 1] instanceof Map) // => true
LinkedHashMapvalue instanceof LinkedHashMap
True for a map value — and the accurate one, since every groovyrs map preserves insertion order.
println([a: 1] instanceof LinkedHashMap) // => true
HashMapvalue instanceof HashMap
True for a map value, even though groovyrs never produces an unordered map.
println([a: 1] instanceof HashMap) // => true
rustrust { … }
An inline Rust block. The parser rewrites it to a `__rust_compile("<base64>", line)` call, which hands the body to fusevm's FFI at run time: it is compiled to a cdylib once and cached on disk under `FUSEVM_FFI_DIR`, so a second run of the same block is a cache hit.
rust {
#[no_mangle]
pub extern "C" fn add(a: i64, b: i64) -> i64 { a + b }
}
println(add(2, 3)) // => 5
__rust_compile__rust_compile(base64Body, line)
The desugar target a `rust { … }` block lowers to — the `GFFI_COMPILE` builtin. It is not meant to be written by hand; a script that does so is calling the FFI compiler directly.
// emitted by the parser for every `rust { … }` block