#include <fstream.hfa>
#include <stdlib.hfa>

int main() {
    // initialize basic structure
    struct S {
	int i, j, k;
    };
    void ?{}( S & s ) { s.i = 1, s.k = 2; }		// default constructor
    void ?{}( S & s, int i, int k ) { s.i = i, s.k = k; } // 2 parameter constructor
    void ?{}( S & s, S c ) { /* s @= c */ s.[i,j,k] = c.[i,j,k]; } // copy constructor
    void ^?{}( S & s ) { s.i = 0, s.k = 0; }		// default destructor
    void ^?{}( S & s, int i ) { s.i = i, s.k = i; }	// 1 parameter destructor
    {
	S s1;						// default constructor
	S s2 = { 3, 7 };				// 2 parameter constructor
	S s3 @= { .k:3, .i:7 };				// 2 parameter C initialization
	?{}( s3, 2, 5 );				// explicit 2 parameter constructor
	^?{}( s1 );					// explicit call to default destructor
    } // implicit call to default destructor for s2, explicit call s1, no call for s3
    S s4 @= {};						// no default construction
    (s4){ 2, 5 };					// explicit 2 parameter constructor
    ^s4{ 3 };						// explicit call to 1 parameter destructor

    // initialize pointer to a basic structure

    void ?{}( S *& s ) { s = malloc(); s->i = 1, (*s).k = 2; } // default constructor
    void ?{}( S *& s, int i, int k ) { s = malloc(); (*s).i = i, (*s).k = k; } // 2 parameter constructor
    void ^?{}( S *& s ) { (*s).i = 0, (*s).k = 0; free( s ); &s = 0p; } // default destructor
    {
	S * ps1;					// default constructor
	S * ps2 = { 3, 7 };				// 2 parameter constructor
	sout | ps1 | ps2;

	S * ps3 @= 0p;					// C initialization
	S * ps4 @= { 3 };				// no default construction
	sout | ps3 | ps4;

	?{}( ps3, 2, 5 );				// explicit 2 parameter constructor
	(ps4){ 2, 5 };					// explicit 2 parameter constructor
	sout | ps3 | ps4;

	^?{}( ps3 );					// explicit call to default destructor
	^ps4{};						// explicit call to default destructor
	sout | ps3 | ps4;
    } // implicit call to default destructor for ps2 and ps1, checks ordering of explicit destructor calls

    // initialize complex structure

    struct T {
	struct S s;
    };

    void ?{}( T & t ) {}	// default constructor => implicitly call constructor for field s
    void ?{}( T & t, int i, int k ) { (t.s){ i, k }; } // 2 parameter constructor => explicitly call constructor for field s
    void ?{}( T & t, S c ) { (t.s){ c }; }// 1 parameter constructor => explicitly call copy constructor for field s
    void ^?{}( T & s ) {}	// destructor => implicitly call destructor for field s
    void ^?{}( T & s, int i ) {}// destructor => implicitly call destructor for field s
    {
	S s;						// default constructor
	T t1;						// default constructor
	T t2 = { s };					// 1 parameter constructor
	^?{}( t1, 3 );					// explicit call to default destructor => implicit call to t1.s's destructor
	T t3;						// default constructor
	T t4 @= { { 1, 3 } };				// C initialization
	(t4){ 2, 5 };					// explicit 2 parameter constructor
    } // implicit call to default destructor for t2 and implicit call for s;

    T *pt = malloc(){ 3, 4 };	// common usage
} // implicit call to default destructor for t3
