Attributes
Attributes can be placed on a node to add extra information. There are two types of attributes.
:
is used to attach a type attribute to a node. We’ve used these in sym
instructions and function arguments.
sym x:i32;
::
is used to attach non-type attributes to a node. For example, we’ve seen ::noDrop
on function arguments and ::preprocess
on macro arguments.
There can be multiple non-type attributes attached to a single node. Each has a name and a value. If the value is not specified, it will implicitly be set to true
.
# single attribute with no value provided
a::attr0
# single attribute with a value provided
a::((attr0 val0))
# multiple attributes with no values provided
a::(attr0 attr1)
# multiple attributes, some have values provided
a::(attr0 (attr1 val1) (attr2 val2))
The attr??
and attrOf
special forms are used for attribute inspection. attr??
checks whether a node has an attribute with a given name. attrOf
fetches the value of that attribute from the node.
The name of type attribute is type
. Note that a node’s type attribute is a different concept from the type of that node.
fnc main () () {
eval (sym (x 0::((myAttr 10))));
attr?? x myAttr; # true
attrOf x myAttr; # 10
attr?? x fakeAttr; # false
attr?? 0:i32 type; # true
attrOf 0:i32 type; # i32
};
Data types can have attributes attached to their type. This is useful for additional type inspection.
import "std/io.orb";
data Foo {
x:i32
}::((xTy i32));
fnc main () () {
eval (sym foo:Foo);
eval (if (attr?? (typeOf foo) xTy) {
message (attrOf (typeOf foo) xTy); # prints i32
});
};
Attributes are useful in conjunction with macro arguments, as they preserve their attributes during the invocation.
import "base.orb";
mac myFoo (a) {
if (&& (attr?? a selection) (== (attrOf a selection) diffBehaviour)) {
# ...
};
# ...
};