Pile aims to build an elegant library and scripting language for small devices.
It has several components including pile class, pile library, pile runtime and pile intepreter.
Pile uses C macro and struct to implement classes.
Here's an example:
// test_class.h
#include "pile_class.h"
#include "pile_types.h"
#define PILE_CLASS_SHORTCUTS true
class(test_class)
{
pile_int_t a;
pile_int_t def_fn(test_class, get_a);
def_destruct(test_class);
};
// test_class.c
pile_int_t impl_fn(test_class, get_a)
{
return self->a;
}
impl_construct(test_class, pile_int_t a)
{
self->a = a;
_assgin(test_class, get_a);
}
impl_default_destruct(test_class);
// main.c
#include <stdio.h>
#include "test_class.h"
int main() {
new(test_class, ins, 10);
printf("%d\r\n", ins->get_a(ins));
ins->a = 1000;
printf("%d\r\n", call(ins, get_a));
del(ins);
renew(test_class, ins, 200);
printf("%d\r\n", ins->get_a(ins));
del(ins);
return 0;
}
The macros have shortcuts when PILE_CLASS_SHORTCUTS
is defined.
You can disable that if the shortcuts cause name conflicts.
Shortcut | Origin |
---|---|
class |
PILE_CLASS |
new |
PILE_NEW |
del |
PILE_DEL |
impl_fn |
PILE_CLASS_METHOD |
impl_construct |
PILE_CLASS_CONSTRUCTOR |
impl_destruct |
PILE_CLASS_DESTRUCTOR |
impl_default_destruct |
PILE_CLASS_DESTRUCTOR_DEFAULT |
_assign |
PILE_ASSIGN_METHOD |
def_fn |
PILE_DEFINE_METHOD |
def_destruct |
PILE_DEFINE_DESTRUCT |
call |
PILE_CALL |
In the document, we will use shortcuts to tell.
class(test_class)
{
pile_int_t a;
void def_fn(test_class, set_a, pile_int_t a);
def_destruct(test_class);
};
In the code above, we define a class named test_class
.
To define a class, we need to use macro class
or PILE_CLASS
. It receives an argument as the class name. Then a struct body need to be followed.
Note: after the brackets the semicolon(
;
) cannot be missed.
Because of the limits of C language, pile doesn't support private atrributes. The properties can be defined in normal struct way, like: pile_str_t str;
.
When defining class methods, we use def_fn
or PILE_DEFINE_METHOD
macros. The macro receives its first parameter as the class name, and the second as method name. The return type should be defined before calling the macro, and the parameter list should start at the third macro parameter, separated by commas.
Note the constructor should not be defined in the class definition. But the destructor must be defined using def_destruct
or PILE_DEFINE_DESTRUCT
macro. The macro receives its first parameter as the class name and no other parameters should be followed.
The following types will be defined as in the example:
- struct test_class: The original struct type
- test_class_t: Orignal type defined using typedef
- test_class_ptr_t: Pointer to the original type (instance type)
Note: constructors and destructors should be defined using another macro, which will be described in the next section.
When implementing a method, macro impl_fn
or PILE_CLASS_METHOD
should be used.
void impl_fn(test_class, set_a, pile_int_t a)
{
self->a = a;
}
The return type should be defined before calling the macro.
The first parameter is the class name while the second is the method name.
The following parameters are argument list of the method.
Inside the function body we can use self
to access the instance.
In a destructor, a class can free the resources it uses.
Use impl_destruct
or PILE_CLASS_DESTRUCTOR
to implement one.
Example:
impl_destruct(test_class)
{
PILE_FREE(self->data);
}
When a class does nothing in a destructor, you can use impl_default_destruct
.
Example:
impl_default_destruct(test_class);
A constructor need to do two things:
- Init the properties
- Assign methods
You can use impl_construct
or PILE_CLASS_CONSTRUCT
macros to implement.
The first parameter is class name, and it can receive a parameter list.
impl_construct(test_class, pile_int_t a)
{
_assign(test_class, set_a);
self->set_a(a);
}
The _assign
or PILE_ASSIGN
macro can automatically assign a method to a class.
All the methods need to be assigned in the constructor,
The macro receives two parameters, where the first one is the class name and the second one is the method name.
You can use new
or PILE_NEW
macros to create a new instance.
Example:
new(test_class, ins, 123);
The first parameter is the class name, while the second is the variable name. The following parameters will be passed to the constructor. Then you can use ins
to access the instance.
The above code will create a new variable with type test_class_ptr_t
.
If you have a variable typed that already available, you can use renew
or PILE_RENEW
macro to re-initialize it.
Example:
test_class_ptr_t ins;
renew(test_class, ins, 123);
Use del
or PILE_DEL
macros.
Example:
del(ins);
The parameter is the variable name of the instance.
You can use ins->method_name(ins, 123);
to call a method.
Note the first parameter should pass the variable again.
If you use call
or PILE_CALL
macro, then you don't need to pass itself again. It looks like:
call(test_cass, set_a, 100);
The first parameter is the class name, while the second one is the method name.
pcert = pile_container_t
pvcoer = PILE_VALUE_CONTAINER