{"id":16375008,"url":"https://github.com/moderocky/krow","last_synced_at":"2026-03-31T16:30:17.688Z","repository":{"id":103957265,"uuid":"380790765","full_name":"Moderocky/Krow","owner":"Moderocky","description":"The bare-bones JVM language.","archived":false,"fork":false,"pushed_at":"2021-12-06T14:20:45.000Z","size":370,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-01T04:15:09.954Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Moderocky.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-06-27T16:42:48.000Z","updated_at":"2023-10-11T15:39:32.000Z","dependencies_parsed_at":null,"dependency_job_id":"b2738fbf-ecce-47f5-b865-78de2d9544e2","html_url":"https://github.com/Moderocky/Krow","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Moderocky%2FKrow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Moderocky%2FKrow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Moderocky%2FKrow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Moderocky%2FKrow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Moderocky","download_url":"https://codeload.github.com/Moderocky/Krow/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239954699,"owners_count":19724287,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T03:19:06.638Z","updated_at":"2026-03-31T16:30:17.625Z","avatar_url":"https://github.com/Moderocky.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"Krow\n=====\n\n### Opus #8\n\n// Unfinished.\n\nThe bare-bones JVM language.\n\n## Introduction\n\nKrow is a very basic compiled JVM language.\nThe language's core goal is to tackle some of Java's deficits, while also targeting a slightly different niche.\n\nJava's long-standing and established nature is both a strength and a flaw: Java is feature-rich and well-known, but outdated and badly-designed concepts cannot be replaced or improved. Java is safe and reliable, but limited in execution. Java is simple and efficient, but direct control is locked behind the compiler.\n\nClearly, there are many situations where these benefits outweigh their drawbacks. Many programmers benefit from Java's simplicity, newer programmers benefit from Java's safety and everybody benefits from Java's reliability. However, some users may find themselves longing for source-level access to JVM internals or to patch the many gaps and inconsistencies in Java.\n\nThe Krow language spec and the original ReKrow compiler were designed and written within six days. I rested on the seventh. ;) More than anything, they were created for proof of concept: a JVM language entirely interoperable with Java, yet able to do things far outside the Java language spec. A JVM language that provides more than sugar.\n\n\u003e *Nomenclature:*\n\u003e \n\u003e Krow spells 'work' backwards, but this is coincidental. The name comes from it being in row 'K' of my project table. \n\u003e However, the back-to-front name has been embraced for other elements: rekrow (worker) .ark (Krow ARchive)\n\u003e \n\u003e The pronunciation doesn't matter, I'm partial to 'kay-row', but 'crow' is equally fine. The tag-line is a reference to crows being carrion birds.\n\u003e \n\u003e Coincidentally, K comes after J in the alphabet.\n\n## The ReKrow Compiler\n\nThe basic Krow compiler is called 'ReKrow'. \n\nReKrow is very rudimentary. It is designed to be as close to 'what-you-see-is-what-you-get' as possible, with no re-ordering or rearranging of entries.\n\nIt also has very little verification, allowing a lot of instructions to be compiled that Java's compiler would consider illegal. Some of these will still be caught by the runtime verifier when the class is loaded, if they would actually prevent the code from running.\n\nIn practice, this means you can:\n- Create default classes with abstract methods.\n- Extend an abstract class without implementing all of its methods.\n- Write unreachable code after the return statement or between jumps.\n- Much, much more.\n\nReKrow is a 'flyover' compiler. This means it reads the input source in one line: the compiler does not know about something until it reaches it. While this does make forward referencing more problematic, it also makes the compiler less complex and more efficient: elements are dealt with as they are reached, then discarded. The compiler requires no recursion or sub-parsing.\n\nReKrow uses [ASM](https://asm.ow2.io/) for assembling its output bytecode. ASM is a very old and established tool, so much so that the Java JDK uses it internally.\n\n## Krow Compiler Libraries\n\nThe ReKrow compiler uses modular 'Libraries' which define all the keywords and compile-time behaviour.\nAdditional libraries can be used to add new source-level language features on a per-file basis.\n\nThis gives Krow the potential to have DSL modifications added, to tailor the language for a particular use case.\nAs libraries may also export (compiled) classes to the Krow runtime, this means that modifiers have much more freedom as to what they can and cannot add.\n\nLibraries are registered at the top of the file (in the root level) by name, for example:\n```java \nlibrary krow.binder;\nlibrary my.custom.library;\nclass org/example/MyClass {\n    \n}\n```\n\nLibraries can:\n- Register new keywords.\n- Register new language concepts.\n- Register new operators.\n- Register new in-statement behaviour.\n- Register new class-level or block-level structures.\n- Export utility classes to the Krow runtime.\n\nLibraries cannot:\n- Overload base language structures.\n- Remove existing language structures.\n- Add new compile-states.\n\n### Built-in Libraries\n\nKrow maintains a few built-in libraries: `krow.binder` (for API creation and internal language modification) and `krow.memory` for direct memory management.\n\nThese features were moved to separate libraries in order to preserve the language integrity and, also, to avoid bloating the runtime with unused features.\n\n#### Binder\n\nBinder adds a `clone` method metadata keyword. This allows the programmer to target an existing Java method (available at compile-time) and directly copy its bytecode into a synthetic result method.\nThis allows a combination of Java and Krow source code to be used in a single class.\n\n## The Krow Runtime\n\nKrow has a runtime environment. This is very small (limited to a couple of classes) and designed to be as unobtrusive as possible. Basic Krow can be used without the runtime, but some of the more advanced features (structs, dynamic invocation, targets) require it.\n\nFortunately, Krow's runtime is tiny - with only a few stubs - and very unobtrusive (looking at you, Kotlin!) so it should never be a size problem.\n\nThe runtime contains the four bootstraps needed for dynamic methods and the `Structure` stub class that all structs extend under the hood. It also contains the endpoints for the built-in targets.\n\n\u003e *Fun fact:* the first version of the Krow runtime was written before number literals were added to the language spec. This meant I had to use booleans and bit-shift them to obtain number values.\n\n## File Structure\n\nWhile it may look unusual at first, the Krow source file structure is very similar to that of Java.\n\nThere are four major differences:\n1. Krow uses `/` as the class path separator.\n2. There is no explicit package declaration. \n3. There are no explicit modifiers.\n4. Special methods are visible.\n\n### Class Path Separators\n\nJVM bytecode uses `/` as the class path separator internally. Rather than find-and-replacing a Java-style `org.example.Type` path, Krow opts to cut out the middle man and use the 'internal' `org/example/Type` style instead.\n\nThis may take some getting used to, but should be a trivial change.\n\nThe name of a class (and its superclass, where applicable) must **always** use their fully-qualified names. This is because the `class` and `extends` keywords are given special treatment internally and do not get access to imported types.\n\nExample:\n```java \nclass org/example/Type extends box/path/Thing {\n    \n}\n```\n\n### Packages\n\nKrow does not place the same sanctity on packages as Java does: there is no explicit `package x.y.z;` declaration in a Krow source file.\n\nInstead, the package is taken from the name in the `class` declaration.\n\nFurthermore, Krow classes do not need to be put in a file structure matching the package or class names, though this is recommended for better organisation.\n\n### Modifiers\n\nKrow does not have Java's 'public/private/protected' modifiers. See [here](#targeted-exporting) for more information on the reasons behind this and alternatives.\n\nFor simplicity, adding an empty `export \u003c\u003e` metadata tag will make the subsequent element public.\n\nExample:\n```java \nexport \u003c\u003e // public class\nclass org/example/Type extends box/path/Thing {\n    \n    export \u003c\u003e // public method\n    static void foo() {\n    }\n    \n    // non-public method\n    static void bar() {\n    }\n    \n}\n```\n\n### Special Methods\n\nJava hides key methods behind special syntax, and sometimes completely.\n\nKrow makes all of these 'special' methods accessible, since there is no good reason not to.\n\n#### Class Initialiser\n\nJava's `static {...}` block is the class initialiser.\nKrow uses an explicit declaration: `static void \u003cclinit\u003e() {...}`\nThis is to keep parity with the method's real name.\n\nExample:\n```java \nclass org/example/Obj {\n    \n    static void \u003cclinit\u003e () {\n    \n    }\n    \n}\n```\n\nThe class initialiser will be run by the classloader and should not be invoked manually.\n\n#### Object Initialiser\n\nKrow also exposes the real constructor method: `void \u003cinit\u003e() {...}`.\nThis is equivalent to Java's `Type()` constructor or `{...}` initialiser block.\nThis is to keep parity with the method's real name.\n\nUsage of this is the same as a regular constructor:\n```java \nclass org/example/Obj {\n    String name;\n    \n    export \u003c\u003e // public constructor\n    void \u003cinit\u003e(String name) {\n        this.name = name;\n    }\n    \n}\n```\n\nNote: this method is a void method, and it should never be called explicitly.\nWhen creating a new object, the constructor will be run by the `invokespecial` instruction `obj(...)`.\nThis means you can use `new Obj(...)` as you would in java.\n\n#### Bridge Methods\n\nKrow does not offer generic classes or methods - these are unnecessary as the `bridge` method is exposed at a source level.\n\nBridge methods are synthetic members added by the Java compiler to link up a generic superclass method with its actual implementation.\nIn Krow, bridges are used in order to bind one method to another, effectively giving a single method two endpoints.\n\n```\nclass org/example/Obj {\n    \n    String myMethod(String var) {\n    }\n    \n    export \u003c\u003e\n    bridge \u003cObj::myMethod(String)String\u003e\n    Object myMethod(Object var); // Invoking this method will invoke the real version\n    \n}\n```\n\nBridge methods are very useful for properly extending a Java library class with generic parameters - the real implementation can be written with the actual types required, and then a bridge version with `Object`s replacing the type parameters will make sure it overrides the correct superclass version.\n\nThe full method signature is required for the bridge metadata - the compiler cannot infer which method it targets, since multiple methods could be valid targets.\n\n\n## Keywords\n\n### Metadata Keywords\n\nMetadata keywords provide information to the compiler for the upcoming element.\nWhile they exist only at source level, they can have side effects in the compiled result.\nSee the [metadata particle](#the-metadata-particle-) for more information.\n\n|Word|Value|Target|Description|\n|----|-----------|------|-----------|\n|`import`|Reference `\u003c\u003e` metadata.|Class declaration, field declaration, method declaration.|Asserts the given references exist in the target area, allows use of their shortened names.|\n|`export`|Reference `\u003c\u003e` metadata.|Class declaration, field declaration, method declaration.|Exports the given element for use outside the class. Exports any included elements to users of this element.|\n|`bridge`|Reference `\u003c\u003e` metadata for a method.|Method declaration.|Sets the bridge target of the upcoming method.|\n|`implement`|Type `\u003c\u003e` metadata for a class.|Class declaration.|Adds interfaces to the upcoming class.|\n|`const`|Identifier and literal value.|Class body, method body.|Stores a compile-time constant.|\n\n### Modifier Keywords\n\nModifier keywords modify the upcoming element. They are effective in the compiled result.\nNote: Krow does not directly offer visibility modifiers.\n\n|Word|Target|Description|\n|----|-----------|------|\n|`static`|Field declaration, method declaration.|Marks the upcoming class member as static.|\n|`abstract`|Class declaration, method declaration.|Marks the upcoming method as implemented elsewhere.|\n|`final`|Field declaration, class declaration, method declaration.|Marks the upcoming element as final.|\n|`native`|Method declaration.|Marks the upcoming element as implemented elsewhere.|\n\n### Instruction Keywords\n\nInstruction keywords are used in code bodies. They perform a function, and may only be used at the start of a statement. \n\n|Word|Accepts|Description|\n|----|-----------|------|\n|`label`|`identifier`|Marks a point which can be jumped to.|\n|`goto`|`identifier`|Jumps to the given label.|\n|`if`|`(boolean)`|Runs the subsequent statement if the condition is true. Note: the statement is from root-level.|\n|`return`|`value?`|Returns the given value from the method, or returns empty.|\n|`assert`|`boolean`|Asserts that the given value is true.|\n\n### Type Keywords\n\nType keywords are used to designate primitive (or built-in constants) in fields, methods, variables and returns.\n\n|Word|Length|Machine Words|Descriptor|\n|----|------|-------------|----------|\n|`void`|1|1|V|\n|`boolean`|1|1|Z|\n|`char`|2|1|C|\n|`short`|2|1|S|\n|`int`|4|1|I|\n|`long`|8|2|J|\n|`float`|4|1|F|\n|`double`|8|2|D|\n|`struct`|8 (16+ in real memory)|2|S(...) // See [struct](#Structs) section.|\n\n## Core Features\n\n### Literals\n\nKrow introduces source-level literals for methods, fields, classes and structs.\n\n|Type|Java Example|Krow Literal|Description|\n|----|-------|---------|-----------|\n|Class|`com.example.Thing`|`com/example/Thing`|A type literal.|\n|Field|`static Type name`|`Owner.name:Type`|A field reference. Used for importing, exporting and reflective access.|\n|Method|`public void myMethod(Type param, int i)`|`Owner::myMethod(Type,I)V`|A method reference. Used for importing, exporting and reflective access.|\n|Struct|Java doesn't have structs :(|`S(name:Type,name:Type)`|A structure reference, used for automatic type inference.|\n\n### Jump Instructions\n\nKrow allows for routine jumps in methods by use of the `goto` and `label` keywords.\n\nThese are very raw and potentially dangerous instructions - it is very easy to create infinite loops or inaccessible code that the JVM simply cannot process because the jump instructions cannot be processed. As such, non-trivial use of `goto` is not recommended.\n\nWarnings aside, the instruction is very simple.\nLabels are denoted by a `label name;` statement.\nThat label can be jumped to by a `goto name;` statement.\n\nFor beginners, it is recommended to keep these instructions in pairs (rather than having multiple jumps to a single point) as it lowers the risk of jump asymmetry.\n\n\u003e N.B: Jump asymmetry occurs when the stack/variable map could have two different states at a label.\n\u003e The Krow compiler is able to prevent this in most situations.\n\nJump instructions can be used to create more complex conditional sections:\n```java \nint a = 6;\nint b = 5;\nif (a == b) goto end;\nSystem.out.println(a);\nSystem.out.println(b);\nlabel end;\nSystem.out.println(\"end\");\n```\n\nIt is very easy to create inaccessible areas of code.\nThis is not an issue in itself - unlike Java, Krow is perfectly able to handle unreachable statements - but programmers should be careful with doing this accidentally.\n\nUnreachable code: (Valid but pointless.)\n```java \nint a = 10;\nint b = 5;\ngoto box;\nint c = 6;\nSystem.out.println(a);\nSystem.out.println(c);\nlabel box;\nSystem.out.println(b);\n```\n\nThis can be used to manually assemble Java's `while` and `for` loops.\nExample:\n```java \nint a = 0;\nlabel top;\nif (a == 12) goto exit;\na = a + 1;\ngoto top;\nlabel exit;\nSystem.out.println(a);\n```\n\nManual jump instructions can be used to create much more efficient and direct loops - a skilled programmer can always create a more effective version than a machine compiler.\nHowever, the reverse is also true: misuse of jump instructions will likely be less efficient than a simple loop. Use them wisely.\n\n### Constants\n\nLike other languages, Krow offers constants using the `const` keyword.\nHowever, this is a compile-time keyword. The constant is *not* available at runtime as a field or variable. It is simply a programming tool to make use of the `LDC` instruction instead of assigning unnecessary variables for constant values.\n\nConstants must either be primitive or of a compile-time constant type, such as a string, class or handle.\n\nThis feature is a better replacement for Java's final assigned variables and fields.\nThe variable `final String name = \"Bob\";` would have its value copied to all uses within the method using `LDC`, but the variable will still occupy a slot in memory which it doesn't need to - the variable itself is never accessed. Krow avoids this waste with `const` by using the value as-is and never assigning a variable for it.\nThe same principle applies to final primitive variables which are assigned at declaration.\n\n\nConstants can be declared at the class or the method level, and are available within their scope like regular variables.\n```java \nclass Example {\n    const name = \"Henry\";\n    \n    void myMethod() {\n        const surname = \"Carter\";\n        // name is available here\n        // surname is available here\n    }\n}\n```\n\nConstants may also be used in the implicit struct constructor.\n\n### Structs\n\nStructs are compile-time anonymous classes that hold only field data and have no declared methods.\n\nThey are referenced and assigned through the `struct` keyword, and can be used in any place an object can.\n\nStructs can be assigned through one of two ways:\n1. The implied `struct(var0, var1, ...)` constructor.\n2. The literal `{ Type name = val; Type name = val; }` block.\n\nThe implicit constructor is quicker and easier to use, but only accepts fields/variables as arguments. This is because the compiler uses the variable names/types as the struct fields.\nThis implicit constructor is only provided for ease-of-use.\n\nThe literal block is the safer and clearer way to create a struct.\n\nStructs do not need to be declared in order to be used publicly. The compiler calculates the runtime class coordinates so that any struct with the same field types/names will use the same class.\n\n*Example:* Simple data structure using the implicit constructor.\n```java \nimport \u003cjava/util/UUID\u003e\nexport \u003c\u003e\nstruct myMethod(String name, int age, UUID id) {\n    return struct(name, age);\n    // implicit struct { String name; int age; }\n}\n```\n\n*Example:* Using structs for multiple return.\n```java \nimport \u003corg/bukkit/Player, Player::getHealth()D, Player::getName()String\u003e\nstruct getData(Player player) {\n    return {\n        double health = player.getHealth();\n        String name = player.getName();\n    }\n}\n\nimport \u003corg/bukkit/Player\u003e\nvoid use(Player player) {\n    struct data = this.getData(player);\n    if (data.health \u003e 20) //...\n    if (data.name.equals(\"henry\")) // ...\n}\n```\n\n### Deferred Initialisation\n\nUnlike Java, Krow is very lenient when it comes to object initialisation rules.\n\nWhile this can be a lot more dangerous (it is possible to write code that passes compilation but would error at runtime) it also gives advanced users a lot more freedom to be creative in unusual situations.\n\nCreating an object is broken up into two stages: allocation and initialisation.\n\nAllocation is done via the `new` keyword and the provided type. Initialisation is done using `()` parentheses to call a constructor.\nIn most cases, users will want to do both together as you would in Java:\n```MyType var = new MyType(1, 2);```\n\nHowever, there may be cases when it is more convenient (or even necessary) to do these separately.\n```\nMyType var = new MyType; // allocate\nvar(1, 2); // initialise\n```\nIn this special situation, the constructor `()` may be called on the variable directly because it is still an `uninitialised_n` on the stack.\n\nThese two parts do not need to be done together - you may have other code or logic between, as long as the object is not directly used before it is initialised.\n\n### Targeted Exporting\n\nKrow does not include visibility modifiers at the language level.\nThis is a deliberate choice - partly because it is very simple to ignore access modifiers in Krow using the built-in [dynamic particle](#the-dynamic-particle-). This would make a `private` modifier a little pointless.\nInstead, Krow opts for an `export` metadata system.\n\nThis is currently unfinished.\n\n## Particles\n\nKrow uses particles to indicate new functionality without making the language more verbose or confusing than it needs to be.\nParticles reduce the need for new keywords that would clutter the language, are easier to spot and highlight and make parsing more efficient.\n\n|Symbol|Name|Description|\n|------|----|-----------|\n|`\u003c\u003e`|[Meta Section](#the-metadata-particle-)|Reference metadata section (for imports, exports, bridges).|\n|`#`|[Dynamic](#the-dynamic-particle-)|Invoking inaccessible methods.|\n|`?`|[Optional](#the-optional-particle-)|Null inference and control.|\n|`@`|[Target](#the-target-particle-)|Reserved.|\n\n### The Metadata Particle `\u003c\u003e`\n\nThe metadata particle is used to store signatures, which are source-level representations of the basic language elements.\nThis particle is used during the compiler import phase to register locally-available constructs that can be referenced by their simple name within code (e.g. `System.out` rather than `java/lang/System.out`.)\nSignature metadata is also used during the export phase to show where elements should be made available to (via targeted visibility.)\n\nIn method body code, the metadata particle can be used for type assurance and to tell the compiler to add an explicit `CHECKCAST` instruction in. This can be used after any value-giving code element (such as a non-void method, field, variable or literal.)\n\nSignatures may also be used in code for obtaining member references. \n\n#### Type\n\nTypes may always be referenced by their fully-qualified names, but once imported can always be referred to by simple name.\nSo-called 'nested' classes from java are referred by their full `Root$Nested` name, since this is the actual name of the class in memory.\n\nExample: `import \u003cjava/io/PrintStream\u003e`\nExample: `String var1 = var2\u003cString\u003e;` (String type assurance.)\n```\norg/example/Type\n    |         |\n    |       Type name\n    |\n  Package path\n```\n\n#### Method\n\nThe method signature can be recognised by the `::` and `()` elements.\n\nExample: `import \u003cArrays::toString(Object[])String`\n```\nOwner::methodName(Param[],Z,J)Return\n  |         |       |           |\n  |        Name     |          Return type\n  |               Parameter types\n Declaring class\n```\n\nConstructors use `Type::new(...)V` in their signature, rather than their true `\u003cinit\u003e` name.\n\n#### Field\n\nThe field signature can be recognised by the `.` and `:` combination.\n\nExample: `import \u003cSystem.out:PrintStream\u003e`\n```\nSystem.out:PrintStream\n  |     |       | \n  |    Name    Type\n  |   \n Declaring class\n```\n\n### The Dynamic Particle `#`\n\nThe dynamic particle is a powerful feature of the Krow source schema that permits use of the `INVOKEDYNAMIC` instruction, allowing access to otherwise-inaccessible members.\n\nThe particle is used in place of the `.` during regular access.\n\nA compile-time constant of the member handle is generated, which is then passed to the bootstrapper in the Krow runtime on first use. After this first access, the bootstrap is no longer necessary.\n\nKrow's dynamic particle is an alternative to Java reflection in a lot of cases.\n\nAdvantages:\n- Much simpler to use.\n- Much shorter to write in code.\n- No need to cache method/field objects.\n- Significantly faster than reflective access.\n\nDisadvantages:\n- Method signature must be known at compile time.\n- The same bootstrap is not reused in multiple places.\n\nKrow's dynamic particle is inappropriate in some cases, such as using reflection to blindly/dynamically access classes and methods whose names are not known at runtime.\n\nFor methods:\nRegular: `String c = object.myPrivateMethod(a, b);` (Throws error at verification - `myPrivateMethod` is private and inaccessible.)\nDynamic: `String c = object#myPrivateMethod(a, b);` (No error - invocation is permitted.)\n\nFor fields:\nRegular: `PrintStream stream = System.out;`\nDynamic: `PrintStream stream = System#out;` \n\nNote: regular access should always be preferred as it is more efficient and easier for the JIT compiler to speed up. However, this is still significantly better for performance than Java's typical reflection, or even using Java's MethodHandles API manually. It is of comparable speed to calling a lambda function.\n\n### The Optional Particle `?`\n\nThe optional particle is designed to introduce basic null safety to Krow at both the source and execution level, without needing to resort to third-party meta like Java's `@Nullable` annotations (and similar.)\n\nThe optional has four main uses:\n1. On variables, fields and method return types, as an indicator of potential null-values. (Semantic.)\n2. In field and method calls, to prevent `NullPointerException`s. (Functional.)\n3. As an alternative to ternaries, to prevent double evaluation of the input. (Functional.)\n\n#### Semantic Null Marker\nExample: Potential null return value.\n```java \nString? getName() {\n    return this.name;\n}\n```\n\nThe `String?` tells the compiler (and any verifier tools) that the result of the method can be `null` during regular operation of the program. This should, of course, be used sparingly - if a value would only be `null` during an error or some extreme state, using the operator here should be avoided.\n\nSimilarly, this can also be used with fields and variables: `final Object? obj;`\nThe same caveat applies - overuse and abuse of the optional particle will do nothing more than produce annoying warnings.\n\n#### Null Check\n\nKrow's compiler uses `?value` for the `ISNULL` instruction. \nSimilarly, `!?value` is effectively the `NOTNULL` instruction, since `!` negates the boolean.\n\nExample:\n```java \nObject a = null;\nObject b = \"hello\";\n\nif (?a) // never reached\nif (!?a) // always reached\n\nif (?b) // always reached\nif (!?b) // never reached\n```\n\n#### Default Value\n\nThe typical Java ternary `(str != null ? str : \"default\")` requires the evaluation of the checked element twice. While this is not a problem for small variables, you could not do this with a method without calling the method result twice.\nThis is also mirrored in Java's compile result, which will load the `str` variable twice.\n\nKrow adds an alternative for this case: the default value `var1 ? var2`.\nThis `?` default operator is an implicit null check, and functions very similarly to the above ternary, but without loading the variable twice.\n\nThis is not just syntax sugar - there is a minor performance improvement over a ternary, but the difference is minimal.\n\nExample:\n```java \nString name = player.getName();\nreturn name ? \"Unknown\";\n```\n\n#### Early Exit\nExample: The target on which this method is called is potentially null.\n```java \nString string = null;\nString sub = string?.substring(3);\nassert !?sub;\n\n```\n\nKrow's optional particle will make the compiler verify the target is set before calling the method. If the target is null, the instruction will be skipped.\nNote: this should be used CAUTIOUSLY as it can have some unintended side-effects, which cannot always be verified by the Krow compiler!\n\n```java \n// x and y are objects\nObject value = \nobj? // obj is not null\n    .method()? // this is null\n    .method(); // so this is skipped\n    // value = null\n```\n\nThe Krow compiler handles this by keeping the stack map constant so that linear jump instructions can be used at each `?` particle so the null value left on the stack will be stored.\n\nIn cases where the method is void or the value is not used, the null-value is popped when the dead end `;` is reached.\n\n### The Target Particle `@`\n\nReserved.\nPotentially for easier invocation of utilities from the Krow runtime.\n\n\n## Language Efficiency\n\nWhether or not Krow is 'faster' or 'better' than another JVM language is difficult to answer.\n\nThe result code that ReKrow produces is minimalist: a class written in Krow will be much smaller than a class written in Java. This is because ReKrow includes no source metadata (line numbers, variable names) which take up a large amount of space in `javac`'s class result.\n\nCode compiled by Krow could be more efficient than Java code. Some results are natively more efficient than what `javac` produces, particularly when it comes to logic instructions.\n\u003e *Note:* I don't know why this is the case. Krow is about 30% faster at inverting booleans, for example.\n\nOn the other hand, `javac` will spot and remove loops and variable assignments it deems pointless, whereas ReKrow will not. This is very minor - JIT will catch it all in the end.\n\nOutside these small edge cases, the efficiency of Krow code will depend entirely on the programmer: ReKrow does exactly what you tell it to, mistakes and all. :)\n\n\u003e *Note:* I would imagine a very proficient programmer could write much more efficient code in Krow but, equally, a mere mortal like myself would probably benefit from `javac`'s hand-holding a lot of the time. :)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoderocky%2Fkrow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmoderocky%2Fkrow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoderocky%2Fkrow/lists"}