Brainmap Specification
Brainmaps are the means by which brainfrick code can access methods, classes,
fields, constructors, and other such object oriented aspects of the JVM. The
brainmap contains a series of entries (generally one per line, though the parser
ignores all whitespace), indexed from 0 onwards. By using the :
operator in a
number with an integer-like value, the corresponding member of the brainmaps the
code is compiled against is called, with the top values of the buffer. For
instance, if the buffer consisted of 1, 2, 4, 7, 3
, with 3
being the most
recently added value, and the :
operator was called invoking a brainmap member
that expects two inputs, it would be given the inputs 7
and 3
, in that order.
Brainmaps define both what the code can call and what classes, methods, and fields
it can define using the ;
and ;{ ... }
syntax. Each top-level
;{
in a .frick
file corresponds with a class from the brainmap or brainmaps
provided to the compiler; each inner ;
or ;{
corresponds to a method or constructor
in the class. If you wish to make a method abstract, it must be given the
abstract
keyword in the brainmap and must not have a body defined in code; this
can be done by using a ;
without brackets. To skip the definition of a method
or class, use a -
. Fields are defined by default if their class is defined, and
cannot be skipped.
Entries
The entries of a brainmap can take the following forms:
Class
public class fully.qualified.Name
Classes can be given the public
, abstract
, or final
modifiers. They are
considered to be package-private unless otherwise specified. Classes you are not
defining but only calling or accessing do not need access modifiers specified.
Invoking a class from the brainmap places the corresponding Class
object at the
pointer.
Classes can be made to extend or implement other classes or interfaces much as in
java, using the extends
and implements
keywords with the fully qualified names
of the super classes or interfaces:
public class fully.qualified.Name implements java.util.function.Function, java.util.function.Consumer
extends java.util.AbstractList
Classes extend java.lang.Object
unless otherwise specified.
Interface
public interface fully.qualified.Name
Interfaces can be given the public
modifier. They are
considered to be package-private unless otherwise specified. Interfaces you are not
defining but only calling or accessing do not need access modifiers specified.
Invoking an interface from the brainmap places the corresponding Class
object at the
pointer.
Similar to classes, interfaces can be made to extend other interfaces using the
extends
keyword:
public interface fully.qualified.Name extends java.util.List
Method
public class fully.qualified.Name extends fully.qualified.NameSuper
protected final void methodName(java.lang.String, int, char)
public void callMethod() -> fully.qualified.NameSuper callMethod()
class fully.qualified.NameSuper
Methods can be given the public
, protected
, private
, final
, static
, or
abstract
modifiers. They are package-private unless otherwise specified. Methods
you are not defining but only calling do not need access modifiers specified.
Methods will be defined in the last class listed in the brainmap prior to the
method declaration. They are defined with comma-separated arguments taking the
form of either a fully qualified class name or one of int
, short
, byte
,
char
, long
, float
, double
, or boolean
. The return type can be anything
the argument typs can be, with the addition of void
.
Invoking a method from the brainmap consumes the same number of values as
the method has arguments, plus one if the method is non-static. These arguments
are consumed in order, with the instance for non-static methods being first. The
return value is placed at the pointer; if the method returns void
, then null
is placed at the pointer.
The ->
syntax can be used to define a super method of the method; this does not
change what method the declared method overrides (as that is determined by the signature),
but it does allow the use of the ;
operator to call the super method using values
from the buffer. The instance that the method is being called on must be included
on the buffer in such a super call. The class the super method is taken from
must be present elsewhere in the brainmap.
Field Getters and Setters
public class fully.qualified.Name
get static final java.util.List LIST
put int i
Field getters and setters can be given the public
, protected
, private
,
or static
modifiers. They are package-private unless otherwise specified.
Currently, fields being declared cannot be final, as there is no way to
ensure that the fields are properly initialized. Accessing final fields, however,
should work fine.
Fields you are not defining but only using do not need access modifiers specified.
Fields will be defined if either a getter or setter (or both) is present in the
last class listed in the brainmap prior to the field declaration, and if that
class is being defined. Their return type can be a fully qualified class name or
a primitive type, the same as method arguments.
Invoking a static field getter places the value of the static field at the pointer.
Invoking a non-static field getter consumes an instance and places the value of the field at the pointer.
Invoking a static field setter consumes a value and sets the field to that value,
placing null
at the pointer.
Invoking a non-static field setter consumes an instance and a value and sets the
field on that instance to the provided value, placing null
at the pointer.
Constructors
public class fully.qualified.Name
protected new(float) -> java.lang.Object new()
class java.lang.Object
Constructors can be given the public
, protected
, or private
modifiers.
They are package-private unless otherwise specified. Constructors you are not
defining but only calling do not need access modifiers specified. Constructors
will be defined in the last class listed in the brainmap prior to the constructor
declaration. They are defined with comma-separated arguments taking the same
possible types as method arguments.
Invoking a constructor from the brainmap consumes the same number of values as the constructor has arguments. These arguments are consumed in order, and the constructed object is placed at the pointer.
The ->
syntax can be used to define a super constructor of the constructor;
this allows the use of the ;
operator to call the super constructor using values
from the buffer. The instance that the method is being called on cannot be included
on the buffer in such a super call. Unlike for methods, this syntax is not optional;
every constructor must call some super constructor. The class the super constructor
is taken from must be present elsewhere in the brainmap.
Annotations
@?fully.qualified.AnnotationName(string="String", enumVal=fully.qualified.EnumName#VALUE)
public class fully.qualified.Name extends fully.qualified.SuperName
@java.lang.Deprecated(since="1.0", forRemoval=true)
protected new(float) -> java.lang.Object new()
@?org.jetbrains.annotations.ApiStatus$Experimental
get int intField
@javax.annotation.Nullable
public void someMethod(@javax.annotation.Nonnull java.lang.String)
class java.lang.Object
All brainmap entries, as well as method or constructor parameters, can be annotated.
These annotations should use @
for annotations which ought to be runtime-visible,
and @?
for annotations which should be in the class file but invisible at runtime.
Annotations may optionally take a comma-separated list of name-value pairs, with
values of the following forms:
Type | Example |
---|---|
int | 1 or 1i |
short | 3s |
byte | 4b |
char | 'a' |
long | -2l |
float | 3.5f |
double | 2.0 or 2.0d |
String | "Hello, world!" |
Class | java.lang.Object |
Enum Value | fully.qualified.EnumName#ENUM_VALUE |
Annotation | @fully.qualified.AnnotationName... (same as the outer notation) |
Array | {1,2,3} (Can be of any of the types above, though not a nested array) |