Browse files

Copy docs from NewCompiler to master

  • Loading branch information...
LadyCailin committed Aug 18, 2017
1 parent f867330 commit 17ef0af6035af0d398827b925fcd5737fecf9f55

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -0,0 +1,94 @@
Annotations allow for meta data to be added to elements, and are used by the system
in various places, and can also be defined and used by your code as well.
== Usage ==
The basic syntax for an annotation uses the <code>@{}</code> syntax. If the annotation
were named Annotation, and you were tagging a variable declaration, it might look like this:
string @s = 'The string';
Annotations may also have annotation parameters. The parameters must be immutable,
and fully defined at compile time, which means that you can either hardcode the values
in, or use an immutable variable. If the parameter takes an array, and you only
have one value in the array, you may simply provide the single element. Additionally,
if the annotation is defined with only one parameter, and that parameter's name is
'value', you may leave off the parameter name and it will be assigned to value,
otherwise you must label the parameters the same as you would when creating an array.
Here are some valid examples:
# Assuming no parameters
# Also valid, for no parameters
# Assuming the one parameter is to be assigned to 'value'
@{Annotation('the value')}
# The same thing, only explicit
@{Annotation(value: 'the value')}
# With multiple parameters
@{Annotation(value: 'the value', number: 3)}
# Assuming 'numbers' is an array
@{Annotation(numbers: 3)}
# Now with an actual array
@{Annotation(numbers: array(1, 2, 3))}
# With external, but constant variables
immutable int @a = 4;
@{Annotation(numbers: array(1, 2, 3, @a)}
The key principal to take away here, is that annotations require immutable data, and
are ways to add meta information to your code. They do not "execute" ever, that is,
they are to be fully resolved at compile time, because in many cases, the compiler
itself uses the annotations itself to do certain things.
== Defining custom annotations ==
To define your own annotation, define the public values in an <code>annotations</code>
block in a class-like structure, and
include default values if you like. Methods may also be defined in the annotation,
but constructors are not allowed, therefore preventing direct instantiations of
an annotation.
annotation Annotation {
annotations {
string @value = 'default',
int @number = 5,
array<number> @numbers = array(1, 2, 3),
To use the annotation on an element, you must use the reflection methods. Since multiple
annotations may be present on an element, you must select the annotations specifically
(or you can iterate through all of them dynamically). Annotation parameters are immutable,
though they do not work exactly the same as immutable class types, because the default value
is not used if the value is provided by the user.
@{Annotation(number: 10)}
string @var = 'the string';
Annotation @a = reflect_annotation(Annotation, @var);
msg(@a->number) # msg's 10
foreach(reflect_annotations(@var), @annotation){
msg(typeof(@annotation)) # In this case, "Annotation"
== Meta annotations ==
Annotation declarations (not the annotation usages) can be themselves annotated
with various annotations. All annotations are available at runtime, so unlike Java,
there is no Retention annotation. There is however the ability to restrict ''where''
an annotation is placed, based on the type of code structure being annotated. The
Target annotation, which takes a ElementType enum, can be used to restrict what elements
this annotation is added to.
@@ -0,0 +1,64 @@
MethodScript has several "built in" types. They work just like user definable types, but it is worth mentioning them specifically,
since they form the basis of all objects.
== Inheritance Tree ==
TODO: Add inheritance tree image
== mixed ==
Mixed is the root of all possible types. It is an interface, which defines a very few methods, which are common
to all objects, built in and user defined types.
=== primitive ===
The primitive class defines all data types that can be "typed in" directly into code, so 'string', 5, 3.1415.
==== string ====
A string is created in code with quotes, either single quotes or double quotes. 'string', for example.
==== number ====
The number class is the super class for all data types that support numeric operations.
===== double =====
A double is a floating point number.
===== int =====
An int is a integral number.
==== boolean ====
A boolean is a true/false value.
=== array ===
An array is a "collection" of other data types.
==== map ====
A map is a "dictionary" of string to mixed mappings.
==== Object ====
An Object is the superclass of all user defined types, and is the first
type in the hierarchy that requires instantiation with the "new" keyword.
== byte_array ==
A byte array wraps a native byte array object, to allow for more efficient
byte array manipulations, and to allow for translation to external processes
that communicate at the lowest level.
== auto ==
The auto type isn't a type per se, it works as a bridge between scripting language
and compiled language. If a type is marked as auto, casting is not required, and
it will attempt to cast to the correct data type at runtime, and only throw
an exception then. This is discouraged from normal use, except in the case
of receiving user input, or very small one time scripts. Additionally, string
constants and numeric constants work as if they are declared as auto. Variables
declared as auto are eligible to use the cross-casting system.
@@ -0,0 +1,162 @@
Cross casting is a feature of MethodScript that allows for rapid scripting, while
maintaining strong type safety elsewhere. Cross casting is less stringent than a
fully strongly typed system though, so it should be used sparingly, and only if
there is a strong case for automatic casting. Generally it should only be used to
cross cast from primitives, instead of other objects. The cross casting system goes hand
in hand with multiple inheritance, but is not to be confused with it. Cross casting
may be taken advantage of by using the auto keyword.
== Cross Casting ==
As a simple example, we can consider the conversion of string to enum. Assume
we have the following declared:
enum Compass {
enums {
If the procedure _func accepts a single Compass argument, it is acceptable to
do <code>_func('NORTH')</code>, but it is not acceptable to first define a string,
then attempt to cross cast:
string @val = 'NORTH';
_func(@val); # Compile error, expecting Compass type, but found string
auto @val2 = 'NORTH';
_func(@val2); # Not a compile error, because cross casting occurs
Compass @val3 = 'NORTH';
_func(@val3); # Also not a compile error, because cross casting occurs during
# the declaration of @val3
This is because while string constants are declared as auto, variables declared
as string are not. This is because when hardcoding the string in, it is quite
obvious what the intention is; you are intending for the string to take on the
enum constant value. However, when you declare it in a variable first, it is assumed
that the input is programmer specified, and therefore is not intended to be cross
cast. If cross casting were generally allowed, then obvious bugs like this:
string @val = 'NOT A REAL ENUM';
_func(@val); # Should be a compile error
would necessarily have to be runtime errors. In this case, since the type is programmer
specified, it is reasonable to assume that it is meant to be used as a generic string,
not the enum type. Additionally, when hard coding strings or numbers, the compiler
can check to ensure that the type is a valid cross cast type, at compile time.
== Cross Casting User Classes ==
You can also take advantage of the cross compiling system, should it suit your classes
needs. You declare your class to be cross compilable from various types, by annotating
it with the @{CrossCast} annotation. If this annotation is declared, you must override
the cast() method, (which should be protected) and return a new instance of the
object, given the type to convert. Say you have a class, Label, which you want to
be cross castable from a string.
@{CrossCast(string | number)}
public class Label {
* The type of @value must be the type of the disjoint of the values, or a superclass of that,
* and the function must return the type of the class it is defined in.
protected static Label cast(primitive @value){
if(@value instanceof number){
# You might do something different here
return(new Label(@value->toString());
} else if(@value instanceof string){
return new Label(@value->toString());
} else {
# This is a programmer error, because it is guaranteed that if the type is
# determined not to be one of the types string or number, this method will
# not have been called, and we don't normally have to consider those cases.
die('Programmer error! You forgot to handle the case of '.typeof(@value))
The compiler will attempt to check the validity of the cross casting at compile
time, if the cast method is determined to be a constant expression, so you
should keep the logic to a minimum to allow for the compile time error checking
to work. Once this occurs, the following code is now valid:
# Valid
Label @l = 'This is a label';
# Valid
auto @s = 'This is a label';
Label @l = @s;
# Not valid
string @s = 'This is a label';
Label @l = @s; # Compile error, expected Label, but found string
There is a caveat to this process. An object cannot cross cast an object of the
same type, or a supertype or subtype. Otherwise, this would make reference vs copy
ambiguous. Consider the following:
@{CrossCast(array(Label, string))} # Actually a compile error
class Label {
protected Label cast(mixed @l){
if(@l instanceof Label){
return(new Label(@l->getLabel()))
} else {
return(new Label(@l))
public Label(string @l){
# ...
If this were allowed, this would make the following code ambiguous:
Label @l = new Label('The label');
Label @l2 = @l; # Are we meaning to create a new Label, or just point to the same reference?
# We simply declare that this is a pointer to the same object, since that is
# clearer.
Because this code is at a glance unclear on whether or not we are actually trying to allocate space
for a new Label object, or simply point to the existing object, this is not allowed.
Supertypes are also restricted, because then both of these would be allowed:
# Assume AbstractLabel is the superclass of Label, and
# AbstractLabelFactory::instance returns a new AbstractLabel of unknown type
AbstractLabel @al = AbstractLabelFactory::instance('Label');
Label @l1 = @al; # If you meant the second one, but did this instead, you get totally
# different results. Therefore, this is not allowed
Label @l2 = (Label)@al; # This is allowed though, because we are obviously just
# trying to cast to the Label type, from AbstractLabel
== Cross Casting vs. Multiple Inheritance ==
In multiple inheritance, an object actually IS multiple other objects, there is no
conversion required. For instance, assume Label extended both class One and class Two.
Then the following code is not a cast of any sort, it's just a simple assignment.
Label @l = new Label('');
One @one = @l;
Two @two = @l;
This further demonstrates why cross casting to a super type isn't allowed.
Oops, something went wrong.

0 comments on commit 17ef0af

Please sign in to comment.