diff --git a/src/core/chuck.lex b/src/core/chuck.lex index d4c0bd7ba..707be0ad5 100644 --- a/src/core/chuck.lex +++ b/src/core/chuck.lex @@ -380,6 +380,7 @@ global { adjust(); return GLOBAL; } "@construct" { adjust(); return AT_CTOR; } "@destruct" { adjust(); return AT_DTOR; } "@import" { adjust(); return AT_IMPORT; } +"@doc" { adjust(); return AT_DOC; } "->" { adjust(); return ARROW_RIGHT; } "<-" { adjust(); return ARROW_LEFT; } "-->" { adjust(); return GRUCK_RIGHT; } diff --git a/src/core/chuck.y b/src/core/chuck.y index 51e8b61a9..3a72e4b46 100644 --- a/src/core/chuck.y +++ b/src/core/chuck.y @@ -98,7 +98,8 @@ a_Program g_program = NULL; a_Complex complex_exp; a_Polar polar_exp; a_Vec vec_exp; // ge: added 1.3.5.3 - a_Import import; // 1.5.2.5 (ge) added + a_Import import; // 1.5.4.0 (ge) added + a_Doc doc; // 1.5.4.4 (ge) added }; // expect shift/reduce conflicts @@ -108,8 +109,9 @@ a_Program g_program = NULL; // 1.4.0.0: changed to 41 for global keyword // 1.4.0.1: changed to 79 for left recursion // 1.5.1.1: changed to 80 for trailing comma in array literals -// 1.5.2.5: changed to 84 for @import statements -%expect 84 +// 1.5.4.0: changed to 84 for @import statements +// 1.5.4.4: changed to 86 for @doc statements +%expect 86 %token ID STRING_LIT CHAR_LIT %token INT_VAL @@ -137,7 +139,7 @@ a_Program g_program = NULL; 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 AT_CTOR AT_DTOR AT_IMPORT + AT_OP AT_CTOR AT_DTOR AT_IMPORT AT_DOC %type program @@ -159,6 +161,7 @@ a_Program g_program = NULL; %type jump_statement %type expression_statement %type import_statement +%type doc_statement %type expression %type chuck_expression %type arrow_expression @@ -200,8 +203,10 @@ a_Program g_program = NULL; %type complex_exp %type polar_exp %type vec_exp // ge: added 1.3.5.3 -%type import_target // 1.5.2.5 (ge) added -%type import_list // 1.5.2.5 (ge) added +%type import_target // 1.5.4.0 (ge) added +%type import_list // 1.5.4.0 (ge) added +%type doc_target // 1.5.4.4 (ge) added +%type doc_list // 1.5.4.4 (ge) added %start program @@ -361,6 +366,7 @@ statement // | label_statement { } | code_segment { $$ = $1; } | import_statement { $$ = $1; } + | doc_statement { $$ = $1; } ; jump_statement @@ -402,17 +408,36 @@ code_segment ; import_statement - : AT_IMPORT import_target { $$ = new_stmt_from_import( $2, @1.first_line, @1.first_column );} - | AT_IMPORT LBRACE import_list RBRACE { $$ = new_stmt_from_import( $3, @1.first_line, @1.first_column );} + : AT_IMPORT import_target { $$ = new_stmt_from_import( $2, @1.first_line, @1.first_column ); } + | AT_IMPORT LBRACK RBRACK { $$ = new_stmt_from_import( NULL, @1.first_line, @1.first_column ); } + | AT_IMPORT LBRACE RBRACE { $$ = new_stmt_from_import( NULL, @1.first_line, @1.first_column ); } + | AT_IMPORT LBRACK import_list LBRACK { $$ = new_stmt_from_import( $3, @1.first_line, @1.first_column ); } + | AT_IMPORT LBRACE import_list RBRACE { $$ = new_stmt_from_import( $3, @1.first_line, @1.first_column ); } ; import_list : import_target { $$ = $1; } | import_target COMMA import_list { $$ = prepend_import( $1, $3, @1.first_line, @1.first_column ); } + ; import_target : STRING_LIT { $$ = new_import( $1, NULL, @1.first_line, @1.first_column ); } - // | id_dot { $$ = new_import( NULL, $1, @1.first_line, @1.first_column ); } + // | id_dot { $$ = new_import( NULL, $1, @1.first_line, @1.first_column ); } + ; + +doc_statement + : AT_DOC doc_target { $$ = new_stmt_from_doc( $2, @1.first_line, @1.first_column ); } + | AT_DOC LBRACK doc_list RBRACK { $$ = new_stmt_from_doc( $3, @1.first_line, @1.first_column ); } + | AT_DOC LBRACE doc_list RBRACE { $$ = new_stmt_from_doc( $3, @1.first_line, @1.first_column ); } + ; + +doc_list + : doc_target { $$ = $1; } + | doc_target COMMA doc_list { $$ = prepend_doc( $1, $3, @1.first_line, @1.first_column ); } + ; + +doc_target + : STRING_LIT { $$ = new_doc( $1, @1.first_line, @1.first_column ); } ; expression_statement diff --git a/src/core/chuck_absyn.cpp b/src/core/chuck_absyn.cpp index b59490bbd..a6a2ba4cc 100644 --- a/src/core/chuck_absyn.cpp +++ b/src/core/chuck_absyn.cpp @@ -344,7 +344,7 @@ a_Stmt new_stmt_from_case( a_Exp exp, uint32_t lineNum, uint32_t posNum ) return a; } -a_Stmt new_stmt_from_import( a_Import list, uint32_t line, uint32_t where ) // 1.5.2.5 (ge) added +a_Stmt new_stmt_from_import( a_Import list, uint32_t line, uint32_t where ) // 1.5.4.0 (ge) added { a_Stmt a = (a_Stmt)checked_malloc( sizeof(struct a_Stmt_) ); a->s_type = ae_stmt_import; @@ -356,7 +356,19 @@ a_Stmt new_stmt_from_import( a_Import list, uint32_t line, uint32_t where ) // 1 return a; } -a_Import new_import( c_str str, a_Id_List list, uint32_t line, uint32_t where ) // 1.5.2.5 (ge) added +a_Stmt new_stmt_from_doc( a_Doc list, uint32_t line, uint32_t where ) // 1.5.4.4 (ge) added +{ + a_Stmt a = (a_Stmt)checked_malloc( sizeof(struct a_Stmt_) ); + a->s_type = ae_stmt_doc; + a->stmt_doc.list = list; + a->line = line; a->where = where; + a->stmt_doc.line = line; a->stmt_doc.where = where; + a->stmt_doc.self = a; + + return a; +} + +a_Import new_import( c_str str, a_Id_List list, uint32_t line, uint32_t where ) // 1.5.4.0 (ge) added { a_Import a = (a_Import)checked_malloc( sizeof(struct a_Import_) ); @@ -404,6 +416,25 @@ a_Import prepend_import( a_Import target, a_Import list, uint32_t lineNum, uint3 return target; } +a_Doc new_doc( c_str str, uint32_t line, uint32_t where ) // 1.5.4.4 (ge) added +{ + a_Doc a = (a_Doc)checked_malloc( sizeof(struct a_Doc_) ); + + // copy allocated string pointer + a->desc = str; // no strdup( str ); <-- str should have been allocated in alloc_str() + + // set line info + a->line = line; a->where = where; + + return a; +} + +a_Doc prepend_doc( a_Doc target, a_Doc list, uint32_t lineNum, uint32_t posNum ) +{ + target->next = list; + return target; +} + a_Exp append_expression( a_Exp list, a_Exp exp, uint32_t lineNum, uint32_t posNum ) { a_Exp current; @@ -1373,6 +1404,9 @@ void delete_stmt( a_Stmt stmt ) case ae_stmt_import: delete_stmt_from_import( stmt ); break; + case ae_stmt_doc: // 1.5.4.4 (ge) added + delete_stmt_from_doc( stmt ); + break; } CK_SAFE_FREE( stmt ); @@ -1476,6 +1510,27 @@ void delete_stmt_from_import( a_Stmt stmt ) } } +void delete_stmt_from_doc( a_Stmt stmt ) +{ + EM_log( CK_LOG_FINEST, "deleting stmt %p (doc)...", (void *)stmt ); + + // pointer + a_Doc next = NULL, i = stmt->stmt_doc.list; + + // iterate instead of recurse to avoid stack overflow + while( i ) + { + // delete the content + CK_SAFE_FREE( i->desc ); + // get next before we delete this one + next = i->next; + // delete the import target + CK_SAFE_FREE( i ); + // move to the next one + i = next; + } +} + void delete_exp_from_primary( a_Exp_Primary_ & p ) { EM_log( CK_LOG_FINEST, "deleting exp (primary)..." ); diff --git a/src/core/chuck_absyn.h b/src/core/chuck_absyn.h index df181f0b3..e627e6559 100644 --- a/src/core/chuck_absyn.h +++ b/src/core/chuck_absyn.h @@ -140,6 +140,7 @@ typedef struct a_Stmt_Return_ * a_Stmt_Return; typedef struct a_Stmt_Case_ * a_Stmt_Case; typedef struct a_Stmt_GotoLabel_ * a_Stmt_GotoLabel; typedef struct a_Stmt_Import_ * a_Stmt_Import; +typedef struct a_Stmt_Doc_ * a_Stmt_Doc; typedef struct a_Decl_ * a_Decl; typedef struct a_Var_Decl_ * a_Var_Decl; typedef struct a_Var_Decl_List_ * a_Var_Decl_List; @@ -153,7 +154,9 @@ typedef struct a_Ctor_Call_ * a_Ctor_Call; // 1.5.2.0 (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 -typedef struct a_Import_ * a_Import; // 1.5.2.5 (ge) added +typedef struct a_Import_ * a_Import; // 1.5.4.0 (ge) added +typedef struct a_Doc_ * a_Doc; // 1.5.4.4 (ge) added + // forward reference for type typedef struct Chuck_Type * t_CKTYPE; @@ -192,6 +195,7 @@ a_Stmt new_stmt_from_return( a_Exp exp, uint32_t line, uint32_t where ); a_Stmt new_stmt_from_label( c_str xid, uint32_t line, uint32_t where ); a_Stmt new_stmt_from_case( a_Exp exp, uint32_t line, uint32_t where ); a_Stmt new_stmt_from_import( a_Import target, uint32_t line, uint32_t where ); +a_Stmt new_stmt_from_doc( a_Doc target, 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 ); @@ -230,8 +234,10 @@ a_Array_Sub prepend_array_sub( a_Array_Sub array, a_Exp exp, uint32_t line, uint a_Complex new_complex( a_Exp re, uint32_t line, uint32_t where ); a_Polar new_polar( a_Exp mod, uint32_t line, uint32_t where ); // ge: added 1.3.5.3 a_Vec new_vec( a_Exp e, uint32_t line, uint32_t where ); -a_Import new_import( c_str str, a_Id_List id_list, uint32_t line, uint32_t where ); -a_Import prepend_import( a_Import target, a_Import list, uint32_t line, uint32_t where ); +a_Import new_import( c_str str, a_Id_List id_list, uint32_t line, uint32_t where ); // 1.5.4.0 (ge) added +a_Import prepend_import( a_Import target, a_Import list, uint32_t line, uint32_t where ); // 1.5.4.0 (ge) added +a_Doc new_doc( c_str str, uint32_t line, uint32_t where ); // 1.5.4.4 (ge) added +a_Doc prepend_doc( a_Doc target, a_Doc list, uint32_t line, uint32_t where ); // 1.5.4.4 (ge) added a_Class_Def new_class_def( ae_Keyword class_decl, a_Id_List xid, a_Class_Ext ext, a_Class_Body body, uint32_t line, uint32_t where ); a_Class_Body new_class_body( a_Section section, uint32_t line, uint32_t where ); @@ -285,6 +291,7 @@ void delete_stmt_from_continue( a_Stmt stmt ); void delete_stmt_from_return( a_Stmt stmt ); void delete_stmt_from_label( a_Stmt stmt ); void delete_stmt_from_import( a_Stmt stmt ); +void delete_stmt_from_doc( a_Stmt stmt ); // delete an exp void delete_exp( a_Exp exp ); @@ -355,7 +362,8 @@ struct a_Arg_List_ { a_Type_Decl type_decl; a_Var_Decl var_decl; t_CKTYPE type; struct a_Complex_ { a_Exp re; a_Exp im; uint32_t line; uint32_t where; a_Exp self; }; struct a_Polar_ { a_Exp mod; a_Exp phase; uint32_t line; uint32_t where; a_Exp self; }; struct a_Vec_ { a_Exp args; int numdims; uint32_t line; uint32_t where; a_Exp self; }; // ge: added 1.3.5.3 -struct a_Import_ { c_str what; a_Import next; uint32_t line; uint32_t where; }; // 1.5.2.5 (ge) added +struct a_Import_ { c_str what; a_Import next; uint32_t line; uint32_t where; }; // 1.5.4.0 (ge) added +struct a_Doc_ { c_str desc; a_Doc next; uint32_t line; uint32_t where; }; // 1.5.4.4(ge) added // enum primary exp type typedef enum { ae_primary_var, ae_primary_num, ae_primary_float, @@ -445,6 +453,7 @@ struct a_Stmt_Return_ { a_Exp val; uint32_t line; uint32_t where; a_Stmt self; } struct a_Stmt_Case_ { a_Exp exp; uint32_t line; uint32_t where; a_Stmt self; }; struct a_Stmt_GotoLabel_ { S_Symbol name; uint32_t line; uint32_t where; a_Stmt self; }; struct a_Stmt_Import_ { a_Import list; uint32_t line; uint32_t where; a_Stmt self; }; +struct a_Stmt_Doc_ { a_Doc list; uint32_t line; uint32_t where; a_Stmt self; }; struct a_Stmt_Code_ { // statement list @@ -459,7 +468,7 @@ struct a_Stmt_Code_ typedef enum { ae_stmt_exp, ae_stmt_while, ae_stmt_until, ae_stmt_for, ae_stmt_foreach, ae_stmt_loop, ae_stmt_if, ae_stmt_code, ae_stmt_switch, ae_stmt_break, ae_stmt_continue, ae_stmt_return, ae_stmt_case, ae_stmt_gotolabel, - ae_stmt_import + ae_stmt_import, ae_stmt_doc } ae_Stmt_Type; // a statement @@ -493,6 +502,7 @@ struct a_Stmt_ struct a_Stmt_Case_ stmt_case; struct a_Stmt_GotoLabel_ stmt_gotolabel; struct a_Stmt_Import_ stmt_import; + struct a_Stmt_Doc_ stmt_doc; }; // code position diff --git a/src/core/chuck_compile.cpp b/src/core/chuck_compile.cpp index b2951209d..a0e740ce7 100644 --- a/src/core/chuck_compile.cpp +++ b/src/core/chuck_compile.cpp @@ -746,7 +746,7 @@ t_CKBOOL Chuck_Compiler::compile_entire_file( Chuck_Context * context ) //----------------------------------------------------------------------------- -// name: compile_import_only() // 1.5.2.5 (ge) added +// name: compile_import_only() | 1.5.4.0 (ge) added // desc: import only public definitions (classes and operator overloads) //----------------------------------------------------------------------------- t_CKBOOL Chuck_Compiler::compile_import_only( Chuck_Context * context ) @@ -831,17 +831,17 @@ t_CKBOOL type_engine_scan_import( Chuck_Env * env, a_Stmt_List stmt_list, if( stmt_list->stmt && stmt_list->stmt->s_type == ae_stmt_import ) { // get the import list - a_Import import = stmt_list->stmt->stmt_import.list; + a_Import importList = stmt_list->stmt->stmt_import.list; // loop over import list - while( import ) + while( importList ) { // resolve, using importer's absolute path, expandSearch == TRUE - string abs = compiler->resolveFilename( import->what, target->absolutePath, TRUE ); + string abs = compiler->resolveFilename( importList->what, target->absolutePath, TRUE ); // if cannot resolve filename if( abs == "" ) { // print error - EM_error2( import->where, "no such file: '%s'", import->what ); + EM_error2( importList->where, "no such file: '%s'", importList->what ); // done return FALSE; } @@ -863,7 +863,7 @@ t_CKBOOL type_engine_scan_import( Chuck_Env * env, a_Stmt_List stmt_list, if( !compiler->importChugin( abs, TRUE, theFile, errorStr ) ) { // print error (chugin loading only prints to log) - EM_error2( import->where, "cannot load chugin: '%s'...", theFile.c_str() ); + EM_error2( importList->where, "cannot load chugin: '%s'...", theFile.c_str() ); EM_error2( 0, "...(reason) %s", errorStr.length() ? errorStr.c_str() : "[none provided, unhelpfully (try running with more verbose log-level)]" ); EM_error2( 0, "...in file '%s'", abs.c_str() ); // error encountered in chugin load, bailing out @@ -887,7 +887,7 @@ t_CKBOOL type_engine_scan_import( Chuck_Env * env, a_Stmt_List stmt_list, // make new target with import only t = new Chuck_CompileTarget( te_do_import_only ); // set filename, with transplant path, expand search if necessary - if( !compiler->openFile( t, import->what, target, TRUE, import->where ) ) + if( !compiler->openFile( t, importList->what, target, TRUE, importList->where ) ) { // clean up CK_SAFE_DELETE( t ); @@ -899,9 +899,9 @@ t_CKBOOL type_engine_scan_import( Chuck_Env * env, a_Stmt_List stmt_list, } } // add to target - target->dependencies.push_back( ImportTargetNode( t, import->where, import->line ) ); + target->dependencies.push_back( ImportTargetNode( t, importList->where, importList->line ) ); // next in list - import = import->next; + importList = importList->next; } } diff --git a/src/core/chuck_compile.h b/src/core/chuck_compile.h index 18d44152b..41906dd20 100644 --- a/src/core/chuck_compile.h +++ b/src/core/chuck_compile.h @@ -392,7 +392,7 @@ struct Chuck_Compiler // compile entire file t_CKBOOL compile_entire_file( Chuck_Context * context ); // import only: public definitions (e.g., classes and operator overloads) - t_CKBOOL compile_import_only( Chuck_Context * context ); // 1.5.2.5 (ge) added + t_CKBOOL compile_import_only( Chuck_Context * context ); // 1.5.4.0 (ge) added // all except import t_CKBOOL compile_all_except_import( Chuck_Context * context ); diff --git a/src/core/chuck_emit.cpp b/src/core/chuck_emit.cpp index 48968aab2..bdb2f9c90 100644 --- a/src/core/chuck_emit.cpp +++ b/src/core/chuck_emit.cpp @@ -614,7 +614,12 @@ t_CKBOOL emit_engine_emit_stmt( Chuck_Emitter * emit, a_Stmt stmt, t_CKBOOL pop break; } - case ae_stmt_import: // 1.5.2.5 (ge) added + case ae_stmt_import: // 1.5.4.0 (ge) added + // do nothing here (return true to bypass) + ret = TRUE; + break; + + case ae_stmt_doc: // 1.5.4.4 (ge) added // do nothing here (return true to bypass) ret = TRUE; break; diff --git a/src/core/chuck_parse.cpp b/src/core/chuck_parse.cpp index 54a933f95..6c821c305 100644 --- a/src/core/chuck_parse.cpp +++ b/src/core/chuck_parse.cpp @@ -233,6 +233,7 @@ string absyn_loop2str( a_Stmt_Loop stmt_loop ); string absyn_break2str( a_Stmt_Break stmt_break ); string absyn_continue2str( a_Stmt_Continue stmt_continue ); string absyn_return2str( a_Stmt_Return stmt_return ); +string absyn_doc2str( a_Stmt_Doc stmt_doc ); string absyn_code2str( a_Stmt_Code stmt_code ); @@ -305,6 +306,14 @@ string absyn_stmt2str( a_Stmt stmt ) str = absyn_return2str( &stmt->stmt_return ); break; + case ae_stmt_import: // import statement + // (compile-time evaluated) + break; + + case ae_stmt_doc: // doc statement | 1.5.4.4 (ge) added + str = absyn_doc2str( &stmt->stmt_doc ); + break; + case ae_stmt_code: // code segment str = absyn_code2str( &stmt->stmt_code ); break; @@ -313,7 +322,6 @@ string absyn_stmt2str( a_Stmt stmt ) case ae_stmt_switch: // switch statement case ae_stmt_case: // case statement case ae_stmt_gotolabel: // goto label statement - default: // bad break; } @@ -856,6 +864,45 @@ string absyn_return2str( a_Stmt_Return stmt_return ) +//----------------------------------------------------------------------------- +// name: absyn_doc2str() | 1.5.4.4 (ge) added +// desc: convert abstract syntax doc stmt to string +//----------------------------------------------------------------------------- +string absyn_doc2str( a_Stmt_Doc stmt_doc ) +{ + // check + if( !stmt_doc || !stmt_doc->list ) return "@doc [empty]"; + + // more than one target in list? + if( stmt_doc->list->next == NULL ) + { + // return one item format + return "@doc \"" + string(stmt_doc->list->desc) + "\";"; + } + + // the string to be constructed + string str = "@doc [ "; + // the current target + a_Doc i = stmt_doc->list; + // iterate + while( i ) + { + // append + str += "\"" + string( i->desc ) + "\""; + // next + i = i->next; + // check + str += ( i ? ", " : " "); + } + // end string + str += "];"; + // return it + return str; +} + + + + //----------------------------------------------------------------------------- // name: absyn_stmt2str() // desc: convert abstract syntax decl to string diff --git a/src/core/chuck_scan.cpp b/src/core/chuck_scan.cpp index d55f81c3d..0f88a1552 100644 --- a/src/core/chuck_scan.cpp +++ b/src/core/chuck_scan.cpp @@ -530,7 +530,12 @@ t_CKBOOL type_engine_scan1_stmt( Chuck_Env * env, a_Stmt stmt ) // the type of stmt switch( stmt->s_type ) { - case ae_stmt_import: // 1.5.2.5 (ge) added + case ae_stmt_import: // 1.5.4.0 (ge) added + // do nothing here (return true to bypass) + ret = TRUE; + break; + + case ae_stmt_doc: // 1.5.4.4 (ge) added // do nothing here (return true to bypass) ret = TRUE; break; @@ -1783,7 +1788,12 @@ t_CKBOOL type_engine_scan2_stmt( Chuck_Env * env, a_Stmt stmt ) // the type of stmt switch( stmt->s_type ) { - case ae_stmt_import: // 1.5.2.5 (ge) added + case ae_stmt_import: // 1.5.4.0 (ge) added + // do nothing here (return true to bypass) + ret = TRUE; + break; + + case ae_stmt_doc: // 1.5.4.4 (ge) added // do nothing here (return true to bypass) ret = TRUE; break; diff --git a/src/core/chuck_type.cpp b/src/core/chuck_type.cpp index 679f19b24..0664556a6 100644 --- a/src/core/chuck_type.cpp +++ b/src/core/chuck_type.cpp @@ -68,6 +68,7 @@ t_CKBOOL type_engine_check_break( Chuck_Env * env, a_Stmt_Break br ); t_CKBOOL type_engine_check_continue( Chuck_Env * env, a_Stmt_Continue cont ); t_CKBOOL type_engine_check_return( Chuck_Env * env, a_Stmt_Return stmt ); t_CKBOOL type_engine_check_switch( Chuck_Env * env, a_Stmt_Switch stmt ); +t_CKBOOL type_engine_enact_doc( Chuck_Env * env, a_Stmt_Doc doc ); t_CKTYPE type_engine_check_exp( Chuck_Env * env, a_Exp exp ); t_CKTYPE type_engine_check_exp_binary( Chuck_Env * env, a_Exp_Binary binary ); t_CKTYPE type_engine_check_op( Chuck_Env * env, ae_Operator op, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ); @@ -1201,6 +1202,7 @@ t_CKBOOL type_engine_verify_stmt_static( Chuck_Env * env, a_Stmt stmt ) case ae_stmt_case: case ae_stmt_return: case ae_stmt_code: + case ae_stmt_doc: // 1.5.4.4 (ge) added default: // shouldn't get here EM_error2( stmt->where, @@ -1236,11 +1238,15 @@ t_CKBOOL type_engine_check_stmt( Chuck_Env * env, a_Stmt stmt ) // the type of stmt switch( stmt->s_type ) { - case ae_stmt_import: // 1.5.2.5 (ge) added + case ae_stmt_import: // 1.5.4.0 (ge) added // do nothing here (return true to bypass) ret = TRUE; break; + case ae_stmt_doc: // 1.5.4.4 (ge) added + ret = type_engine_enact_doc( env, &stmt->stmt_doc ); + break; + case ae_stmt_if: // count scope to help determine class member env->class_scope++; @@ -1831,6 +1837,36 @@ t_CKBOOL type_engine_check_return( Chuck_Env * env, a_Stmt_Return stmt ) +//----------------------------------------------------------------------------- +// name: type_engine_enact_doc() +// desc: take action for @doc statement +//----------------------------------------------------------------------------- +t_CKBOOL type_engine_enact_doc( Chuck_Env * env, a_Stmt_Doc doc ) +{ + // check if we are in a function + if( env->func ) + { + // set the documentation string from first + env->func->doc = doc->list ? doc->list->desc : ""; + } + else if( env->class_def ) + { + // set the documentation string from first + env->class_def->doc = doc->list ? doc->list->desc : ""; + } + else + { + // error + EM_error2( doc->where, "@doc statements used outside class and function definitions"); + return FALSE; + } + + return TRUE; +} + + + + //----------------------------------------------------------------------------- // name: type_engine_infer_auto() | 1.5.0.8 (ge) added // desc: process auto type from base_type/array_depth @@ -6030,9 +6066,51 @@ void Chuck_Namespace::get_funcs( vector & out, t_CKBOOL includeMan +//----------------------------------------------------------------------------- +// name: contains() +// desc: check if a particular type is in this namespace | 1.5.4.4 (ge) added +//----------------------------------------------------------------------------- +t_CKBOOL Chuck_Namespace::contains( Chuck_Type * target ) const +{ + vector results; + type.get_toplevel( results, FALSE ); + return std::find( results.begin(), results.end(), target ) != results.end(); +} + + + + +//----------------------------------------------------------------------------- +// name: contains() +// desc: check if a particular value is in this namespace | 1.5.4.4 (ge) added +//----------------------------------------------------------------------------- +t_CKBOOL Chuck_Namespace::contains( Chuck_Value * target ) const +{ + vector results; + value.get_toplevel( results, FALSE ); + return std::find( results.begin(), results.end(), target ) != results.end(); +} + + + + +//----------------------------------------------------------------------------- +// name: contains() +// desc; check if a particular function is in this namespace | 1.5.4.4 (ge) added +//----------------------------------------------------------------------------- +t_CKBOOL Chuck_Namespace::contains( Chuck_Func * target ) const +{ + vector results; + func.get_toplevel( results, TRUE ); + return std::find( results.begin(), results.end(), target ) != results.end(); +} + + + + //----------------------------------------------------------------------------- // name: operator == -// desc: ... +// desc: type equivalence //----------------------------------------------------------------------------- t_CKBOOL operator ==( const Chuck_Type & lhs, const Chuck_Type & rhs ) { @@ -10850,8 +10928,8 @@ void Chuck_Type::apropos_vars( std::string & output, const std::string & PREFIX, if( value->name.length() == 0 ) continue; // see if name is internally reserved if( value->name[0] == '@' ) continue; - // see if name is a function - if( value->type->base_name == "[function]" ) continue; + // see if value is a function + if( value->func_ref ) continue; // check for static declaration if( value->is_static ) { diff --git a/src/core/chuck_type.h b/src/core/chuck_type.h index b5a78391a..20739227f 100644 --- a/src/core/chuck_type.h +++ b/src/core/chuck_type.h @@ -226,23 +226,23 @@ struct Chuck_Scope } // get list of top level - void get_toplevel( std::vector & out, t_CKBOOL includeMangled = TRUE ) + void get_toplevel( std::vector & out, t_CKBOOL includeMangled = TRUE ) const { // pass on get_level( 0, out, includeMangled ); } // get list of top level - void get_level( int level, std::vector & out, t_CKBOOL includeMangled = TRUE ) + void get_level( int level, std::vector & out, t_CKBOOL includeMangled = TRUE ) const { assert( scope.size() > level ); // clear the out out.clear(); // our iterator - std::map::iterator iter; + std::map::const_iterator iter; // get func map - std::map * m = NULL; + std::map const * m = NULL; // 1.5.0.5 (ge) modified: actually use level m = scope[level]; @@ -373,6 +373,13 @@ struct Chuck_Namespace : public Chuck_VM_Object void get_values( std::vector & out ); // get top level functions void get_funcs( std::vector & out, t_CKBOOL includeManged = TRUE ); + + // check if this namespace contains a particular type at top scope level | 1.5.4.4 (ge) added + t_CKBOOL contains( Chuck_Type * target ) const; + // check if this namespace contains a particular value at top scope level | 1.5.4.4 (ge) added + t_CKBOOL contains( Chuck_Value * target ) const; + // check if this namespace contains a particular function at top scope level | 1.5.4.4 (ge) added + t_CKBOOL contains( Chuck_Func * target ) const; }; diff --git a/src/core/ulib_doc.cpp b/src/core/ulib_doc.cpp index 56efcd62b..5b1cd1aeb 100644 --- a/src/core/ulib_doc.cpp +++ b/src/core/ulib_doc.cpp @@ -65,6 +65,8 @@ CK_DLL_MFUN( CKDoc_genGroups ); CK_DLL_MFUN( CKDoc_genType_type ); CK_DLL_MFUN( CKDoc_genType_str ); CK_DLL_MFUN( CKDoc_outputToDir ); +CK_DLL_SFUN( CKDoc_set_describe ); +CK_DLL_SFUN( CKDoc_get_describe ); // offset static t_CKUINT CKDoc_offset_data = 0; @@ -222,6 +224,19 @@ DLL_QUERY ckdoc_query( Chuck_DL_Query * QUERY ) func->doc = "Generate everything as files into the output directory."; if( !type_engine_import_mfun( env, func ) ) goto error; + // // describe + // func = make_new_sfun( "int", "describe", CKDoc_set_describe ); + // func->add_arg( "Object", "target" ); + // func->add_arg( "string", "description" ); + // func->doc = "Associate a description with `target`, which must be either a Type (i.e., a class) or a function. Returns true on sucess; returns false if target is neither a class nor function, or if describe() was called on a target without sufficient permission to update its description."; + // if( !type_engine_import_sfun( env, func ) ) goto error; + + // // describe + // func = make_new_sfun( "string", "describe", CKDoc_get_describe ); + // func->add_arg( "Object", "target" ); + // func->doc = "Returns the description associated with `target`, which must be either a Type (i.e., a class) or a function."; + // if( !type_engine_import_sfun( env, func ) ) goto error; + // end the class import type_engine_import_class_end( env ); @@ -2259,6 +2274,129 @@ CK_DLL_MFUN( CKDoc_outputToDir ) ckdoc->outputToDir( thePath, theTitle ); } +CK_DLL_SFUN( CKDoc_set_describe ) +{ + Chuck_Object * target = GET_NEXT_OBJECT(ARGS); + Chuck_String * desc = GET_NEXT_STRING(ARGS); + string str = desc ? desc->str() : ""; + RETURN->v_int = FALSE; + + // check it + if( !target ) + { + CK_FPRINTF_STDERR( "CKDoc.describe(): null target argument; no action taken.\n" ); + return; + } + + // check target type + Chuck_Type * type = target->type_ref; + if( !isa(type,VM->env()->ckt_class) && !isa(type,VM->env()->ckt_function) ) + { + CK_FPRINTF_STDERR( "CKDoc.describe(): target type must be either Type (i.e., a class) or a function; no action taken.\n" ); + return; + } + + // if a class + if( isa(type,VM->env()->ckt_class) ) + { + Chuck_Type * targetType = (Chuck_Type *)target; + // check this isn't a system type + if( targetType->m_locked || VM->env()->global()->contains( targetType ) ) + { + CK_FPRINTF_STDERR( "CKDoc.describe(): cannot modify description for system-defined type '%s'\n", targetType->name().c_str() ); + return; + } + // check this isn't a system type + if( targetType->doc != "" ) + { + CK_FPRINTF_STDERR( "CKDoc.describe(): cannot overwrite a description after it has already been set (type: '%s')", targetType->name().c_str() ); + return; + } + // update the doc string + targetType->doc = trim(str); + } + // if a func + else if( isa(type,VM->env()->ckt_function) ) + { + Chuck_Func * targetFunc = (Chuck_Func *)target; + // get containing type, if there is one + Chuck_Type * funcOwner = targetFunc->ownerType(); + // check this isn't a system type + if( VM->env()->global()->contains( funcOwner ) ) + { + CK_FPRINTF_STDERR( "CKDoc.describe(): cannot modify description for system-defined function '%s'\n", targetFunc->signature(FALSE,FALSE).c_str() ); + return; + } + // check this isn't a system type + if( targetFunc->doc != "" ) + { + CK_FPRINTF_STDERR( "CKDoc.describe(): cannot overwrite a description after it has already been set (function: '%s'", targetFunc->signature(FALSE,FALSE).c_str() ); + return; + } + // update the doc string + targetFunc->doc = trim(str); + } + else + { + // should not get here + CK_FPRINTF_STDERR( "CKDoc.describe(): internal error -- unaccounted Object type '%s", target->type_ref->name().c_str() ); + return; + } + + // return affirmative + RETURN->v_int = TRUE; +} + +CK_DLL_SFUN( CKDoc_get_describe ) +{ + Chuck_Object * target = GET_NEXT_OBJECT(ARGS); + // type of object + Chuck_Type * type = target ? target->type_ref : NULL; + string doc = ""; + + // check it + if( !target ) + { + CK_FPRINTF_STDERR( "CKDoc.describe(): null target argument; no action taken.\n" ); + goto done; + } + + // check target type + if( !isa(type,VM->env()->ckt_class) && !isa(type,VM->env()->ckt_function) ) + { + CK_FPRINTF_STDERR( "CKDoc.describe(): target type must be either Type (i.e., a class) or a function; no action taken.\n" ); + goto done; + } + + // if a class + if( isa(type,VM->env()->ckt_class) ) + { + // target is a type + Chuck_Type * targetType = (Chuck_Type *)target; + // copy the document string + doc = targetType->doc; + } + // if a func + else if( isa(type,VM->env()->ckt_function) ) + { + // target is a function + Chuck_Func * targetFunc = (Chuck_Func *)target; + // copy the document string + doc = targetFunc->doc; + } + else + { + // should not get here + CK_FPRINTF_STDERR( "CKDoc.describe(): internal error -- unaccounted Object type '%s", target->type_ref->name().c_str() ); + goto done; + } + +done: + // return a new chuck string + RETURN->v_string = (Chuck_String *)instantiate_and_initialize_object( VM->env()->ckt_string, VM ); + // set the contents + RETURN->v_string->set( doc ); +}