Keywords and Operand types
🚧 Under Construction
This page is actively being written. Content may be incomplete or change.Runestaff’s type system closely follows the Java class file format. Every token in a .rns source file is parsed as one of the types described below. The parser determines a token’s type mostly by inspecting its first character.
Keywords
Section titled “Keywords”Keywords are reserved words that carry special meaning in the language syntax. In Runestaff, keywords are positionally reserved — they are only treated as keywords in certain positions, and can be used as plain identifiers everywhere else. Think of them as “soft” reserved words.
For example, .super is a directive keyword, but it can also appear as an identifier in the operand position:
.super com/example/MySuperClass; ".super" is the directive keyword; "com/example/MySuperClass" is an identifier
.super .super; or.super public; here ".super" and "public" are in operand position — treated as identifiers, not keywordsThis applies to any keyword: its meaning is determined entirely by where it appears, not by what it is.
Directives
Section titled “Directives”Directives always start with a dot (.) and declare structural elements: classes, methods, fields, and so on. They consume operands of the types described in the Operands section below.
See the Directives page for the full list.
Access flags
Section titled “Access flags”Access flags control the visibility and behaviour of classes, methods, and fields. Common examples: public, private, protected, static, final, abstract. Access flag is optionally present and should be placed right after the directive keyword (TODO: examples on methods and fields).:
.class public final MyClassOrder of access flags
Section titled “Order of access flags”I don’t enforce a specific order for access flags:
.class final public MyClassTODO: Interfaces, annotations, enums blabla TODO: Say about some rules and JVMS warnings
Operands
Section titled “Operands”Operands are the values that directives and instructions operate on. They are mostly based on constant pool entries, because almost all operands are encoded as constant pool references in the resulting bytecode.
Runestaff supports implicit type inference for operands — the parser determines the operand type from its syntax. A token starting with a digit is parsed as an integer literal, one starting with " is a string, and so on.
Identifiers
Section titled “Identifiers”Identifiers are the most general operand type. An identifier can refer to almost any constant pool entry without requiring explicit type syntax. The assembler resolves it to the appropriate constant pool type based on context.
For example, a superclass reference is stored as a CONSTANT_Class entry in the constant pool, but you just write it as a plain identifier:
.super java/lang/Object; "java/lang/Object" resolves to a CONSTANT_Class entryA method name or descriptor resolves to CONSTANT_Utf8:
.method public static main ([Ljava/lang/String;)V; "main" and "([Ljava/lang/String;)V" resolve to CONSTANT_Utf8 entriesForced identifier syntax
Section titled “Forced identifier syntax”Sometimes you need an identifier that starts with a digit, contains spaces, or includes characters that would break normal parsing. Use the raw identifier syntax for this:
#"..." — raw identifier
.super #"42"; An identifier literally named "42", not the integer 42
.super #"my class name"; An identifier with spacesThe following escape sequences are supported inside #"...":
| Sequence | Meaning |
|---|---|
\" | Double quote |
\\ | Backslash |
\n | Newline |
\t | Tab |
\r | Carriage return |
\0 | Null |
\b | Backspace |
\f | Form feed |
Integers
Section titled “Integers”Integers are supported only in decimal form for now. Hexadecimal and binary literals are not yet supported.
As JVM supports only 32-bit integers, the valid range is from -2147483648 to 2147483647. Values outside this range will cause an error.
Strings
Section titled “Strings”String literals are enclosed in double quotes and support the same escape sequences as raw identifiers:
ldc "Hello, World!"ldc "line one\nline two"ldc "she said \"hi\""String literals are encoded as CONSTANT_String entries in the constant pool.
Note: Multi-line string literals are not currently supported. A string must be written on a single line.
Floats, Doubles, and Longs
Section titled “Floats, Doubles, and Longs”Not yet supported.
Type hints
Section titled “Type hints”By default, Runestaff infers the constant pool type from context. However, since Runestaff is a sister project to Lagertha VM and is designed to produce any bytecode — including intentionally invalid bytecode — you may need to force a specific constant pool type regardless of context.
Type hints let you do exactly that. The syntax is:
@type components...Where type is the constant pool type name followed by the space-separated components of that constant pool entry.
For example, to force a superclass reference to point to a CONSTANT_Methodref instead of a CONSTANT_Class:
.super @methodref java/lang/Object toString ()Ljava/lang/String;; Forces the operand to a method reference, regardless of what .super normally expectsSupported type hints:
| Type hint | Constant pool entry | Components | Example |
|---|---|---|---|
@utf8 | CONSTANT_Utf8 | Identifier | @utf8 MyClass.class |
@int | CONSTANT_Integer | Decimal or hex integer | @int 42 |
@string | CONSTANT_String | String literal | @string "Hello, World!" |
@class | CONSTANT_Class | Class name identifier | @class java/lang/Object |
@methodref | CONSTANT_Methodref | ClassName MethodName Descriptor | @methodref java/lang/Object toString ()Ljava/lang/String; |
| todo | … | … | … |