Skip to content

Commit

Permalink
Merge pull request #412 from ccrma/2023-ctors
Browse files Browse the repository at this point in the history
support for constructors and destructors
  • Loading branch information
gewang authored Nov 16, 2023
2 parents 5b3076f + 448394a commit 7dfee32
Show file tree
Hide file tree
Showing 46 changed files with 3,012 additions and 1,534 deletions.
39 changes: 38 additions & 1 deletion VERSIONS
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,45 @@
ChucK VERSIONS log
------------------

1.5.1.9 (November 2023)
1.5.1.9 (November 2023) "Better Late Than Never...constructors"
=======
- (added) language-level, overloadable class constructors
- (added) language-level class destructor
```
class Foo
{
// a member variable
1 => int num;

// constructor "default"
fun @construct() { 2 => num; }

// another constructor
fun @construct( int x ) { x => num; }

// yet another constructor
fun @construct( int x, int y ) { x*y => num; }

// alternate way of define a constructor
fun void Foo( int x, int y, int z ) { x*y*z => num; }

// destructor
fun @destruct() { <<< "bye:", this >>>; }
}

// constructor "default"
Foo f1();
// another constructor
Foo f2(15);
// yet another constructor
new Foo(8,9) @=> Foo @ f3;
// yet another constructor
new Foo(10,11,12) @=> Foo @ f4;
// print
<<< f1.num, f2.num, f3.num, f4.num >>>;
```
- (added) examples/class/constructors.ck
- (added) examples/class/destructor.ck
- (added) Shred.parent() and Shred.ancestor()
- (added) chugins runtime API support for creating arrays from chugins
- (fixed) Type.of("int[][]").isArray() now correctly returns true
Expand Down
53 changes: 53 additions & 0 deletions examples/class/constructors.ck
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// specifying and overloading class constructors
// requires chuck-1.5.2.0 or higher

// a class
class Foo
{
// a member variable (this will be initialized before
// any actual constructors, as Foo's "pre-constructor")
1 => int num;

// constructor 1 "default"
fun @construct()
{
13 => num; // set num to something
<<< "constructor 1:", num >>>;
}

// constructor 2
fun @construct( int x )
{
x => num;
<<< "constructor 2:", x >>>;
}

// constructor 3 (alternate method to define)
fun void Foo( int x, int y )
{
x*y => num;
<<< "constructor 3:", x, y >>>;
}
}

// declare a Foo, invoke constructor 1
Foo f0;
// declare a Foo, invoke constructor 1
Foo f1();
// declare a Foo, invoke constructor 2
Foo f2(15);
// instantiate a Foo, invoke constructor 3
new Foo(8,9) @=> Foo @ f3;

// print
<<< f0.num, f1.num, f2.num, f3.num >>>;

// can also invoke constructor for each element in array
Foo array1(2)[3];
// print each element's num
for( auto f : array1 ) <<< f.num, "" >>>;

// instantiate an array of Foo, invoking constructor for each
new Foo(6,5)[4] @=> Foo array2[];
// print each element's num
for( auto f : array2 ) <<< f.num, "" >>>;
36 changes: 36 additions & 0 deletions examples/class/ctors-dtor.ck
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// example: defining basic class constructors + destructor

// a class
class Foo
{
// a member variable
1 => int num;

// constructor "default"
fun @construct() { 2 => num; }

// another constructor
fun @construct( int x ) { x => num; }

// yet another constructor
fun @construct( int x, int y ) { x*y => num; }

// alternate way of define a constructor
fun void Foo( int x, int y, int z ) { x*y*z => num; }

// destructor
fun @destruct() { <<< "destructor:", this.num >>>; }
}

// constructor "default"
Foo f0;
// constructor "default"
Foo f1();
// another constructor
Foo f2(15);
// yet another constructor
new Foo(8,9) @=> Foo @ f3;
// yet another constructor
new Foo(10,11,12) @=> Foo @ f4;
// print
<<< f0.num, f1.num, f2.num, f3.num, f4.num >>>;
14 changes: 14 additions & 0 deletions examples/class/destructor.ck
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// example of class destructor

// a class
class Foo
{
// class destructor
fun @destruct()
{
<<< "destructor called...", "" >>>;
}
}

Foo foo;
// when `foo` goes out of scope, the destructor should be called...
11 changes: 6 additions & 5 deletions examples/oper/oper_post_inc.ck
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// i++ - doesn't fully work yet (1.2.0.1)
// post increment operator

// starting value
4 => int i;
// assign, then increment i
i++ => int j;

<<<"printing i, then j">>>;
<<<i>>>;
<<<j>>>;
if ( i == 5 && j == 4) <<<"success">>>;
// print (i should be 1 higher than j)
<<< i >>>;
<<< j >>>;
4 changes: 2 additions & 2 deletions src/core/chuck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -764,8 +764,8 @@ t_CKBOOL ChucK::initChugins()
compiler()->env()->op_registry.preserve();
// get the code
code = compiler()->output();
// name it - TODO?
// code->name = string(argv[i]);
// name it | 1.5.1.9 (ge)
code->name = string("pre-load ck file: ") + filename;

// spork it
shred = vm()->spork( code, NULL, TRUE );
Expand Down
2 changes: 2 additions & 0 deletions src/core/chuck.lex
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,8 @@ global { adjust(); return GLOBAL; }
"@" { adjust(); return AT_SYM; }
"@@" { adjust(); return ATAT_SYM; }
"@operator" { adjust(); return AT_OP; }
"@construct" { adjust(); return AT_CTOR; }
"@destruct" { adjust(); return AT_DTOR; }
"->" { adjust(); return ARROW_RIGHT; }
"<-" { adjust(); return ARROW_LEFT; }
"-->" { adjust(); return GRUCK_RIGHT; }
Expand Down
41 changes: 33 additions & 8 deletions src/core/chuck.y
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ a_Program g_program = NULL;
UNCHUCK UPCHUCK CLASS INTERFACE EXTENDS IMPLEMENTS
PUBLIC PROTECTED PRIVATE STATIC ABSTRACT CONST
SPORK ARROW_RIGHT ARROW_LEFT L_HACK R_HACK
GRUCK_RIGHT GRUCK_LEFT UNGRUCK_RIGHT UNGRUCK_LEFT AT_OP
GRUCK_RIGHT GRUCK_LEFT UNGRUCK_RIGHT UNGRUCK_LEFT
AT_OP AT_CTOR AT_DTOR


%type <program> program
Expand Down Expand Up @@ -266,6 +267,18 @@ function_definition
{ $$ = new_func_def( $1, $2, $3, $4, $6, $8, TRUE, @1.first_line, @1.first_column ); }
| function_decl static_decl type_decl2 ID LPAREN RPAREN code_segment
{ $$ = new_func_def( $1, $2, $3, $4, NULL, $7, TRUE, @1.first_line, @1.first_column ); }
| function_decl static_decl ID LPAREN arg_list RPAREN code_segment
{ $$ = new_func_def( $1, $2, NULL, $3, $5, $7, TRUE, @1.first_line, @1.first_column ); }
| function_decl static_decl ID LPAREN RPAREN code_segment
{ $$ = new_func_def( $1, $2, NULL, $3, NULL, $6, TRUE, @1.first_line, @1.first_column ); }
| function_decl AT_CTOR LPAREN arg_list RPAREN code_segment // 1.5.1.9 (ge) added for constructors
{ $$ = new_func_def( $1, ae_key_instance, NULL, "@construct", $4, $6, TRUE, @1.first_line, @1.first_column ); }
| function_decl AT_CTOR LPAREN RPAREN code_segment // 1.5.1.9 (ge) added for constructors
{ $$ = new_func_def( $1, ae_key_instance, NULL, "@construct", NULL, $5, TRUE, @1.first_line, @1.first_column ); }
| function_decl AT_DTOR LPAREN RPAREN code_segment // 1.5.1.9 (ge) added for destructor
{ $$ = new_func_def( $1, ae_key_instance, NULL, "@destruct", NULL, $5, TRUE, @1.first_line, @1.first_column ); }
| function_decl AT_DTOR LPAREN arg_list RPAREN code_segment // 1.5.1.9 (ge) added for constructors
{ $$ = new_func_def( $1, ae_key_instance, NULL, "@destruct", $4, $6, TRUE, @1.first_line, @1.first_column ); }
| function_decl static_decl type_decl2 ID LPAREN arg_list RPAREN SEMICOLON
{ $$ = new_func_def( $1, $2, $3, $4, $6, NULL, TRUE, @1.first_line, @1.first_column ); }
| function_decl static_decl type_decl2 ID LPAREN RPAREN SEMICOLON
Expand Down Expand Up @@ -434,9 +447,13 @@ var_decl_list
;

var_decl
: ID { $$ = new_var_decl( $1, NULL, @1.first_line, @1.first_column ); }
| ID array_exp { $$ = new_var_decl( $1, $2, @1.first_line, @1.first_column ); }
| ID array_empty { $$ = new_var_decl( $1, $2, @1.first_line, @1.first_column ); }
: ID { $$ = new_var_decl( $1, FALSE, NULL, NULL, @1.first_line, @1.first_column ); }
| ID array_exp { $$ = new_var_decl( $1, FALSE, NULL, $2, @1.first_line, @1.first_column ); }
| ID array_empty { $$ = new_var_decl( $1, FALSE, NULL, $2, @1.first_line, @1.first_column ); }
| ID LPAREN RPAREN { $$ = new_var_decl( $1, TRUE, NULL, NULL, @1.first_line, @1.first_column ); } // 1.5.1.9 (ge) added for constructors
| ID LPAREN expression RPAREN { $$ = new_var_decl( $1, TRUE, $3, NULL, @1.first_line, @1.first_column ); } // 1.5.1.9 (ge) added for constructors
| ID LPAREN RPAREN array_exp { $$ = new_var_decl( $1, TRUE, NULL, $4, @1.first_line, @1.first_column ); } // 1.5.1.9 (ge) added for constructors
| ID LPAREN expression RPAREN array_exp { $$ = new_var_decl( $1, TRUE, $3, $5, @1.first_line, @1.first_column ); } // 1.5.1.9 (ge) added for constructors
;

complex_exp
Expand Down Expand Up @@ -586,10 +603,18 @@ unary_expression
{ $$ = new_exp_from_unary( ae_op_typeof, $2, @1.first_line, @1.first_column ); }
| SIZEOF unary_expression
{ $$ = new_exp_from_unary( ae_op_sizeof, $2, @1.first_line, @1.first_column ); }
| NEW type_decl
{ $$ = new_exp_from_unary2( ae_op_new, $2, NULL, @1.first_line, @1.first_column ); }
| NEW type_decl array_exp
{ $$ = new_exp_from_unary2( ae_op_new, $2, $3, @1.first_line, @1.first_column ); }
| NEW type_decl // e.g., new Foo;
{ $$ = new_exp_from_unary2( ae_op_new, $2, FALSE, NULL, NULL, @1.first_line, @1.first_column ); }
| NEW type_decl array_exp // e.g., new Foo[10];
{ $$ = new_exp_from_unary2( ae_op_new, $2, FALSE, NULL, $3, @1.first_line, @1.first_column ); }
| NEW type_decl LPAREN RPAREN // 1.5.1.9 (ge) added for constructors | e.g., new Foo();
{ $$ = new_exp_from_unary2( ae_op_new, $2, TRUE, NULL, NULL, @1.first_line, @1.first_column ); }
| NEW type_decl LPAREN expression RPAREN // 1.5.1.9 (ge) added for constructors | e.g., new Foo(1,2,3);
{ $$ = new_exp_from_unary2( ae_op_new, $2, TRUE, $4, NULL, @1.first_line, @1.first_column ); }
| NEW type_decl LPAREN RPAREN array_exp // 1.5.1.9 (ge) added for constructors | e.g., new Foo()[10];
{ $$ = new_exp_from_unary2( ae_op_new, $2, TRUE, NULL, $5, @1.first_line, @1.first_column ); }
| NEW type_decl LPAREN expression RPAREN array_exp // 1.5.1.9 (ge) added for constructors | e.g., new Foo(1,2,3)[10];
{ $$ = new_exp_from_unary2( ae_op_new, $2, TRUE, $4, $6, @1.first_line, @1.first_column ); }
// | SPORK TILDA code_segment
// { $$ = new_exp_from_unary3( ae_op_spork, $3, @1.first_line, @1.first_column ); }
;
Expand Down
16 changes: 11 additions & 5 deletions src/core/chuck_absyn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,13 +394,16 @@ a_Exp new_exp_from_unary( ae_Operator oper, a_Exp exp, uint32_t lineNum, uint32_
}

a_Exp new_exp_from_unary2( ae_Operator oper, a_Type_Decl type,
a_Array_Sub array, uint32_t lineNum, uint32_t posNum )
int ctor_invoked, a_Exp ctor_args, a_Array_Sub array,
uint32_t lineNum, uint32_t posNum )
{
a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
a->s_type = ae_exp_unary;
a->s_meta = ae_meta_value;
a->unary.op = oper;
a->unary.type = type;
a->unary.ctor.invoked = ctor_invoked;
a->unary.ctor.args = ctor_args;
a->unary.array = array;
a->line = lineNum; a->where = posNum;
a->unary.line = lineNum; a->unary.where = posNum;
Expand Down Expand Up @@ -521,7 +524,7 @@ a_Exp new_exp_from_id( c_str xid, uint32_t lineNum, uint32_t posNum )
return a;
}

a_Exp new_exp_from_int( long num, uint32_t lineNum, uint32_t posNum )
a_Exp new_exp_from_int( t_CKINT num, uint32_t lineNum, uint32_t posNum )
{
a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
a->s_type = ae_exp_primary;
Expand All @@ -535,7 +538,7 @@ a_Exp new_exp_from_int( long num, uint32_t lineNum, uint32_t posNum )
return a;
}

a_Exp new_exp_from_float( double num, uint32_t lineNum, uint32_t posNum )
a_Exp new_exp_from_float( t_CKFLOAT num, uint32_t lineNum, uint32_t posNum )
{
a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
a->s_type = ae_exp_primary;
Expand Down Expand Up @@ -712,10 +715,12 @@ a_Exp new_exp_from_nil( uint32_t lineNum, uint32_t posNum )
return a;
}

a_Var_Decl new_var_decl( c_constr xid, a_Array_Sub array, uint32_t lineNum, uint32_t posNum )
a_Var_Decl new_var_decl( c_constr xid, int ctor_invoked, a_Exp ctor_args, a_Array_Sub array, uint32_t lineNum, uint32_t posNum )
{
a_Var_Decl a = (a_Var_Decl)checked_malloc( sizeof( struct a_Var_Decl_ ) );
a->xid = insert_symbol(xid);
a->ctor.invoked = ctor_invoked;
a->ctor.args = ctor_args;
a->array = array;
a->line = lineNum; a->where = posNum;

Expand Down Expand Up @@ -790,7 +795,8 @@ a_Func_Def new_func_def( ae_Keyword func_decl, ae_Keyword static_decl,
sizeof( struct a_Func_Def_ ) );
a->func_decl = func_decl;
a->static_decl = static_decl;
a->type_decl = type_decl;
// substitute if NULL | 1.5.1.9 (ge) for constructors
a->type_decl = type_decl ? type_decl : new_type_decl(new_id_list("void",0,0),0,0,0);
a->name = insert_symbol( name );
a->arg_list = arg_list;
a->s_type = ae_func_user;
Expand Down
22 changes: 15 additions & 7 deletions src/core/chuck_absyn.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ typedef enum {
ae_key_private, ae_key_static, ae_key_instance, ae_key_abstract
} ae_Keyword;

// key



Expand Down Expand Up @@ -130,6 +131,7 @@ typedef struct a_Id_List_ * a_Id_List;
typedef struct a_Class_Ext_ * a_Class_Ext;
typedef struct a_Class_Body_ * a_Class_Body;
typedef struct a_Array_Sub_ * a_Array_Sub;
typedef struct a_Ctor_Call_ * a_Ctor_Call; // 1.5.1.9 (ge) added
typedef struct a_Complex_ * a_Complex;
typedef struct a_Polar_ * a_Polar;
typedef struct a_Vec_ * a_Vec; // ge: added 1.3.5.3
Expand Down Expand Up @@ -173,7 +175,7 @@ a_Stmt new_stmt_from_case( a_Exp exp, uint32_t line, uint32_t where );
a_Exp append_expression( a_Exp list, a_Exp exp, uint32_t line, uint32_t where );
a_Exp new_exp_from_binary( a_Exp lhs, ae_Operator oper, a_Exp rhs, uint32_t line, uint32_t where );
a_Exp new_exp_from_unary( ae_Operator oper, a_Exp exp, uint32_t line, uint32_t where );
a_Exp new_exp_from_unary2( ae_Operator oper, a_Type_Decl type, a_Array_Sub array, uint32_t line, uint32_t where );
a_Exp new_exp_from_unary2( ae_Operator oper, a_Type_Decl type, int ctor_invoked, a_Exp ctor_args, a_Array_Sub array, uint32_t line, uint32_t where );
a_Exp new_exp_from_unary3( ae_Operator oper, a_Stmt code, uint32_t line, uint32_t where );
a_Exp new_exp_from_cast( a_Type_Decl type, a_Exp exp, uint32_t line, uint32_t where, uint32_t castPos );
a_Exp new_exp_from_array( a_Exp base, a_Array_Sub indices, uint32_t line, uint32_t where );
Expand All @@ -183,8 +185,8 @@ a_Exp new_exp_from_member_dot( a_Exp base, c_str member, uint32_t line, uint32_t
a_Exp new_exp_from_postfix( a_Exp base, ae_Operator op, uint32_t line, uint32_t where );
a_Exp new_exp_from_dur( a_Exp base, a_Exp unit, uint32_t line, uint32_t where );
a_Exp new_exp_from_id( c_str xid, uint32_t line, uint32_t where );
a_Exp new_exp_from_int( long num, uint32_t line, uint32_t where );
a_Exp new_exp_from_float( double num, uint32_t line, uint32_t where );
a_Exp new_exp_from_int( t_CKINT num, uint32_t line, uint32_t where );
a_Exp new_exp_from_float( t_CKFLOAT num, uint32_t line, uint32_t where );
a_Exp new_exp_from_str( c_str str, uint32_t line, uint32_t where );
a_Exp new_exp_from_char( c_str chr, uint32_t line, uint32_t where );
a_Exp new_exp_from_if( a_Exp cond, a_Exp lhs, a_Exp rhs, uint32_t line, uint32_t where );
Expand All @@ -198,7 +200,7 @@ a_Exp new_exp_from_hack( a_Exp exp, uint32_t line, uint32_t where );
a_Exp new_exp_from_nil( uint32_t line, uint32_t where );
a_Var_Decl_List new_var_decl_list( a_Var_Decl var_decl, uint32_t line, uint32_t where );
a_Var_Decl_List prepend_var_decl_list( a_Var_Decl var_decl, a_Var_Decl_List list, uint32_t line, uint32_t where );
a_Var_Decl new_var_decl( c_constr xid, a_Array_Sub array, uint32_t line, uint32_t where );
a_Var_Decl new_var_decl( c_constr xid, int ctor_invoked, a_Exp ctor_args, a_Array_Sub array, uint32_t line, uint32_t where );
a_Type_Decl new_type_decl( a_Id_List xid, int ref, uint32_t line, uint32_t where );
a_Type_Decl add_type_decl_array( a_Type_Decl type_decl, a_Array_Sub array, uint32_t line, uint32_t where );
a_Arg_List new_arg_list( a_Type_Decl type_decl, a_Var_Decl var_decl, uint32_t line, uint32_t where );
Expand Down Expand Up @@ -294,12 +296,17 @@ void delete_vec( a_Vec v );



//------------------------------------------------------------------------------
// helper structs
//------------------------------------------------------------------------------
// 1.5.1.9 (ge) added constructor support
struct a_Ctor_Call_ { int invoked; a_Exp args; t_CKFUNC func; int primitive; };
//------------------------------------------------------------------------------
// abstract syntax tree | structs
//------------------------------------------------------------------------------
struct a_Exp_Binary_ { a_Exp lhs; ae_Operator op; a_Exp rhs; t_CKFUNC ck_func; t_CKFUNC ck_overload_func; uint32_t line; uint32_t where; a_Exp self; };
struct a_Exp_Cast_ { a_Type_Decl type; a_Exp exp; uint32_t line; uint32_t where; a_Exp self; };
struct a_Exp_Unary_ { ae_Operator op; a_Exp exp; a_Type_Decl type; a_Array_Sub array;
struct a_Exp_Unary_ { ae_Operator op; a_Exp exp; a_Type_Decl type; struct a_Ctor_Call_ ctor; a_Array_Sub array;
a_Stmt code; t_CKFUNC ck_overload_func; uint32_t line; uint32_t where; a_Exp self; };
struct a_Exp_Postfix_ { a_Exp exp; ae_Operator op; t_CKFUNC ck_overload_func; uint32_t line; uint32_t where; a_Exp self; };
struct a_Exp_Dur_ { a_Exp base; a_Exp unit; uint32_t line; uint32_t where; a_Exp self; };
Expand All @@ -313,8 +320,9 @@ struct a_Exp_Decl_ { a_Type_Decl type; a_Var_Decl_List var_decl_list; int num_va
struct a_Exp_Hack_ { a_Exp exp; uint32_t line; uint32_t where; a_Exp self; };
struct a_Var_Decl_List_ { a_Var_Decl var_decl; a_Var_Decl_List next; uint32_t line; uint32_t where; a_Exp self; };
// 1.4.2.0 (ge) added ck_type and ref, to handle multiple array decl (e.g., int x, y[], z[1];)
struct a_Var_Decl_ { S_Symbol xid; a_Array_Sub array; t_CKVALUE value; void * addr;
t_CKTYPE ck_type; /* int is_auto; */ int ref; int force_ref;
struct a_Var_Decl_ { S_Symbol xid; struct a_Ctor_Call_ ctor;
a_Array_Sub array; t_CKVALUE value; void * addr; t_CKTYPE ck_type;
/* int is_auto; */ int ref; int force_ref;
uint32_t line; uint32_t where; a_Exp self; };
struct a_Type_Decl_ { a_Id_List xid; a_Array_Sub array; int ref; uint32_t line; uint32_t where; /*a_Exp self;*/ };
struct a_Array_Sub_ { t_CKUINT depth; a_Exp exp_list; uint32_t line; uint32_t where; a_Exp self;
Expand Down
Loading

0 comments on commit 7dfee32

Please sign in to comment.