/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.stanford.edu/ http://chuck.cs.princeton.edu/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A.-----------------------------------------------------------------------------*/ //-----------------------------------------------------------------------------// file: chuck_scan.cpp// desc: chuck type-system / type-checker pre-scan//// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)// date: Summer 2005 - original//-----------------------------------------------------------------------------#include "chuck_scan.h"#include "chuck_errmsg.h"#include "chuck_instr.h"#include "chuck_type.h"#include "chuck_vm.h"#include "util_string.h" #include <string>using namespace std; //-----------------------------------------------------------------------------// function prototypes//-----------------------------------------------------------------------------t_CKBOOL type_engine_scan0_class_def( Chuck_Env * env, a_Class_Def class_def ); t_CKBOOL type_engine_scan1_stmt_list( Chuck_Env * env, a_Stmt_List list );t_CKBOOL type_engine_scan1_stmt( Chuck_Env * env, a_Stmt stmt );t_CKBOOL type_engine_scan1_if( Chuck_Env * env, a_Stmt_If stmt );t_CKBOOL type_engine_scan1_for( Chuck_Env * env, a_Stmt_For stmt );t_CKBOOL type_engine_scan1_while( Chuck_Env * env, a_Stmt_While stmt );t_CKBOOL type_engine_scan1_until( Chuck_Env * env, a_Stmt_Until stmt );t_CKBOOL type_engine_scan1_loop( Chuck_Env * env, a_Stmt_Loop stmt );t_CKBOOL type_engine_scan1_break( Chuck_Env * env, a_Stmt_Break br );t_CKBOOL type_engine_scan1_continue( Chuck_Env * env, a_Stmt_Continue cont );t_CKBOOL type_engine_scan1_return( Chuck_Env * env, a_Stmt_Return stmt );t_CKBOOL type_engine_scan1_switch( Chuck_Env * env, a_Stmt_Switch stmt );t_CKBOOL type_engine_scan1_exp( Chuck_Env * env, a_Exp exp );t_CKBOOL type_engine_scan1_exp_binary( Chuck_Env * env, a_Exp_Binary binary );t_CKBOOL type_engine_scan1_op( Chuck_Env * env, ae_Operator op, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary );t_CKBOOL type_engine_scan1_op_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary );t_CKBOOL type_engine_scan1_op_unchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs );t_CKBOOL type_engine_scan1_op_upchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs );t_CKBOOL type_engine_scan1_op_at_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs );t_CKBOOL type_engine_scan1_exp_unary( Chuck_Env * env, a_Exp_Unary unary );t_CKBOOL type_engine_scan1_exp_primary( Chuck_Env * env, a_Exp_Primary exp );t_CKBOOL type_engine_scan1_exp_array_lit( Chuck_Env * env, a_Exp_Primary exp );t_CKBOOL type_engine_scan1_exp_cast( Chuck_Env * env, a_Exp_Cast cast );t_CKBOOL type_engine_scan1_exp_postfix( Chuck_Env * env, a_Exp_Postfix postfix );t_CKBOOL type_engine_scan1_exp_dur( Chuck_Env * env, a_Exp_Dur dur );t_CKBOOL type_engine_scan1_exp_array( Chuck_Env * env, a_Exp_Array array );t_CKBOOL type_engine_scan1_exp_func_call( Chuck_Env * env, a_Exp_Func_Call func_call );t_CKBOOL type_engine_scan1_exp_func_call( Chuck_Env * env, a_Exp exp_func, a_Exp args, t_CKFUNC & ck_func, int linepos );t_CKBOOL type_engine_scan1_exp_dot_member( Chuck_Env * env, a_Exp_Dot_Member member );t_CKBOOL type_engine_scan1_exp_if( Chuck_Env * env, a_Exp_If exp_if );t_CKBOOL type_engine_scan1_exp_decl( Chuck_Env * env, a_Exp_Decl decl );t_CKBOOL type_engine_scan1_array_subscripts( Chuck_Env * env, a_Exp exp_list );t_CKBOOL type_engine_scan1_cast_valid( Chuck_Env * env, t_CKTYPE to, t_CKTYPE from );t_CKBOOL type_engine_scan1_code_segment( Chuck_Env * env, a_Stmt_Code stmt, t_CKBOOL push = TRUE );t_CKBOOL type_engine_scan1_func_def( Chuck_Env * env, a_Func_Def func_def );t_CKBOOL type_engine_scan1_class_def( Chuck_Env * env, a_Class_Def class_def ); t_CKBOOL type_engine_scan2_stmt_list( Chuck_Env * env, a_Stmt_List list );t_CKBOOL type_engine_scan2_stmt( Chuck_Env * env, a_Stmt stmt );t_CKBOOL type_engine_scan2_if( Chuck_Env * env, a_Stmt_If stmt );t_CKBOOL type_engine_scan2_for( Chuck_Env * env, a_Stmt_For stmt );t_CKBOOL type_engine_scan2_while( Chuck_Env * env, a_Stmt_While stmt );t_CKBOOL type_engine_scan2_loop( Chuck_Env * env, a_Stmt_Loop stmt );t_CKBOOL type_engine_scan2_until( Chuck_Env * env, a_Stmt_Until stmt );t_CKBOOL type_engine_scan2_break( Chuck_Env * env, a_Stmt_Break br );t_CKBOOL type_engine_scan2_continue( Chuck_Env * env, a_Stmt_Continue cont );t_CKBOOL type_engine_scan2_return( Chuck_Env * env, a_Stmt_Return stmt );t_CKBOOL type_engine_scan2_switch( Chuck_Env * env, a_Stmt_Switch stmt );t_CKBOOL type_engine_scan2_exp( Chuck_Env * env, a_Exp exp );t_CKBOOL type_engine_scan2_exp_binary( Chuck_Env * env, a_Exp_Binary binary );t_CKBOOL type_engine_scan2_op( Chuck_Env * env, ae_Operator op, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary );t_CKBOOL type_engine_scan2_op_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary );t_CKBOOL type_engine_scan2_op_unchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs );t_CKBOOL type_engine_scan2_op_upchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs );t_CKBOOL type_engine_scan2_op_at_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs );t_CKBOOL type_engine_scan2_exp_unary( Chuck_Env * env, a_Exp_Unary unary );t_CKBOOL type_engine_scan2_exp_primary( Chuck_Env * env, a_Exp_Primary exp );t_CKBOOL type_engine_scan2_exp_array_lit( Chuck_Env * env, a_Exp_Primary exp );t_CKBOOL type_engine_scan2_exp_cast( Chuck_Env * env, a_Exp_Cast cast );t_CKBOOL type_engine_scan2_exp_postfix( Chuck_Env * env, a_Exp_Postfix postfix );t_CKBOOL type_engine_scan2_exp_dur( Chuck_Env * env, a_Exp_Dur dur );t_CKBOOL type_engine_scan2_exp_array( Chuck_Env * env, a_Exp_Array array );t_CKBOOL type_engine_scan2_exp_func_call( Chuck_Env * env, a_Exp_Func_Call func_call );t_CKBOOL type_engine_scan2_exp_func_call( Chuck_Env * env, a_Exp exp_func, a_Exp args, t_CKFUNC & ck_func, int linepos );t_CKBOOL type_engine_scan2_exp_dot_member( Chuck_Env * env, a_Exp_Dot_Member member );t_CKBOOL type_engine_scan2_exp_if( Chuck_Env * env, a_Exp_If exp_if );t_CKBOOL type_engine_scan2_exp_decl( Chuck_Env * env, a_Exp_Decl decl );t_CKBOOL type_engine_scan2_array_subscripts( Chuck_Env * env, a_Exp exp_list );t_CKBOOL type_engine_scan2_cast_valid( Chuck_Env * env, t_CKTYPE to, t_CKTYPE from );t_CKBOOL type_engine_scan2_code_segment( Chuck_Env * env, a_Stmt_Code stmt, t_CKBOOL push = TRUE );t_CKBOOL type_engine_scan2_func_def( Chuck_Env * env, a_Func_Def func_def );t_CKBOOL type_engine_scan2_class_def( Chuck_Env * env, a_Class_Def class_def );t_CKBOOL type_engine_scan2_func_def( Chuck_Env * env, a_Func_Def func_def );t_CKBOOL type_engine_scan2_class_def( Chuck_Env * env, a_Class_Def class_def ); //-----------------------------------------------------------------------------// name: type_engine_scan0_prog()// desc: data in env should be ready : type discovery//-----------------------------------------------------------------------------t_CKBOOL type_engine_scan0_prog( Chuck_Env * env, a_Program prog, te_HowMuch how_much ){ t_CKBOOL ret = TRUE; if( !prog ) return FALSE; // log EM_log( CK_LOG_FINER, "(pass 0) type discovery scan..." ); // env->context->filename.c_str() ); // push indent EM_pushlog(); // log how much EM_log( CK_LOG_FINEST, "target: %s", howmuch2str( how_much ) ); // go through each of the program sections while( prog && ret ) { switch( prog->section->s_type ) { case ae_section_stmt: // do nothing break; case ae_section_func: // do nothing break; case ae_section_class: // if no classes, then skip if( how_much == te_do_no_classes ) break; // make global, if marked public if( prog->section->class_def->decl == ae_key_public ) { // make sure the context has no public class if( env->context->public_class_def != NULL ) { EM_error2( prog->section->class_def->linepos, "more than one 'public' class defined..." ); ret = FALSE; continue; } // make global prog->section->class_def->home = env->user(); // remember env->context->public_class_def = prog->section->class_def; } // scan the class definition ret = type_engine_scan0_class_def( env, prog->section->class_def ); break; default: EM_error2( prog->linepos, "internal error: unrecognized program section in type checker pre-scan..." ); ret = FALSE; break; } prog = prog->next; } // pop indent EM_poplog(); return ret;} //-----------------------------------------------------------------------------// name: type_engine_scan0_class_def()// desc: add defined class to env - this is the main goal of scan0//-----------------------------------------------------------------------------t_CKBOOL type_engine_scan0_class_def( Chuck_Env * env, a_Class_Def class_def ){ // make new type for class def t_CKTYPE the_class = NULL; // the return type t_CKBOOL ret = TRUE; // the class body a_Class_Body body = class_def->body; // log EM_log( CK_LOG_FINER, "scanning class definition '%s'...", S_name(class_def->name->xid) ); // push indent EM_pushlog(); // if nspc is attached to class_def, that means the class_def is to be // put in that namespace. this is usually the case when doing import if( class_def->home != NULL ) { // log EM_log( CK_LOG_FINER, "target namespace: '%s'", class_def->home->name.c_str() ); // set the new type as current env->nspc_stack.push_back( env->curr ); env->curr = class_def->home; } // make sure class not already in namespace if( env->curr->lookup_type( class_def->name->xid, FALSE ) ) { EM_error2( class_def->name->linepos, "class/type '%s' is already defined in namespace '%s'", S_name(class_def->name->xid), env->curr->name.c_str() ); ret = FALSE; goto done; } // check if reserved if( type_engine_check_reserved( env, class_def->name->xid, class_def->name->linepos ) ) { EM_error2( class_def->name->linepos, "...in class definition '%s'", S_name(class_def->name->xid) ); ret = FALSE; goto done; } // allocate new type assert( env->context != NULL ); the_class = env->context->new_Chuck_Type( env ); // add reference SAFE_ADD_REF( the_class ); // set the fields the_class->xid = te_user; the_class->name = S_name(class_def->name->xid); the_class->owner = env->curr; the_class->array_depth = 0; the_class->size = sizeof(void *); the_class->obj_size = 0; // TODO: the_class->info = env->context->new_Chuck_Namespace(); SAFE_ADD_REF( the_class->info ); the_class->info->name = the_class->name; // if public class, then set parent to context // ... allowing the class to address current context if( env->context->public_class_def == class_def ) { the_class->info->parent = env->context->nspc; } else { the_class->info->parent = env->curr; } // TODO: add ref to the parent? the_class->func = NULL; the_class->def = class_def; // add code the_class->info->pre_ctor = new Chuck_VM_Code; SAFE_ADD_REF( the_class->info->pre_ctor ); // add to env env->curr->type.add( the_class->name, the_class ); // URGENT: make this global // incomplete the_class->is_complete = FALSE; // set the new type as current env->nspc_stack.push_back( env->curr ); env->curr = the_class->info; // push the class def env->class_stack.push_back( env->class_def ); env->class_def = the_class; // reset the nest list env->class_scope = 0; // type check the body while( body && ret ) { // check the section switch( body->section->s_type ) { case ae_section_stmt: break; case ae_section_func: break; case ae_section_class: // do the class ret = type_engine_scan0_class_def( env, body->section->class_def ); break; } // move to the next section body = body->next; } // pop the class env->class_def = env->class_stack.back(); env->class_stack.pop_back(); // pop the namesapce env->curr = env->nspc_stack.back(); env->nspc_stack.pop_back(); // if things checked out if( ret ) { Chuck_Value * value = NULL; Chuck_Type * type = NULL; // allocate value type = env->t_class->copy( env ); type->actual_type = the_class; value = env->context->new_Chuck_Value( type, the_class->name ); value->owner = env->curr; value->is_const = TRUE; value->is_member = FALSE; // add to env env->curr->value.add( the_class->name, value ); // remember class_def->type = the_class; } // if nspc is attached to class_def, that means the class_def is to be // put in that namespace. this is usually the case when doing import // we undo that extra namespace layer here... if( class_def->home != NULL ) { // pop the namesapce env->curr = env->nspc_stack.back(); env->nspc_stack.pop_back(); } else // set the current namespace as home { // set curr as home class_def->home = env->curr; } // initialize the Type info object | 1.5.0.0 (ge) added initialize_object( the_class, env->t_class ); done: // pop indent EM_poplog(); return ret;} //-----------------------------------------------------------------------------// name: type_engine_scan1_prog()// desc: data in env should be ready//-----------------------------------------------------------------------------t_CKBOOL type_engine_scan1_prog( Chuck_Env * env, a_Program prog, te_HowMuch how_much ){ t_CKBOOL ret = TRUE; if( !prog ) return FALSE; // log EM_log( CK_LOG_FINER, "(pass 1) type resolution scan..." ); // env->context->filename.c_str() ); // push indent EM_pushlog(); // log how much EM_log( CK_LOG_FINEST, "target: %s", howmuch2str( how_much ) ); // go through each of the program sections while( prog && ret ) { switch( prog->section->s_type ) { case ae_section_stmt: // if only classes, then skip if( how_much == te_do_classes_only ) break; // scan the statements ret = type_engine_scan1_stmt_list( env, prog->section->stmt_list ); break; case ae_section_func: // if only classes, then skip if( how_much == te_do_classes_only ) break; // scan the function definition ret = type_engine_scan1_func_def( env, prog->section->func_def ); break; case ae_section_class: // if no classes, then skip if( how_much == te_do_no_classes ) break; // scan the class definition ret = type_engine_scan1_class_def( env, prog->section->class_def ); break; default: EM_error2( prog->linepos, "internal error: unrecognized program section in type checker pre-scan..." ); ret = FALSE; break; } prog = prog->next; } // pop indent EM_poplog(); return ret;} //-----------------------------------------------------------------------------// name: type_engine_scan1_stmt_list()// desc: ...//-----------------------------------------------------------------------------t_CKBOOL type_engine_scan1_stmt_list( Chuck_Env * env, a_Stmt_List list ){ // type check the stmt_list while( list ) { // the current statement if( !type_engine_scan1_stmt( env, list->stmt ) ) return FALSE; // advance to the next statement list = list->next; } return TRUE;} //-----------------------------------------------------------------------------// name: type_engine_scan1_stmt(()// desc: ...//-----------------------------------------------------------------------------t_CKBOOL type_engine_scan1_stmt( Chuck_Env * env, a_Stmt stmt ){ t_CKBOOL ret = FALSE; if( !stmt ) return TRUE; // the type of stmt switch( stmt->s_type ) { case ae_stmt_if: // count scope to help determine class member env->class_scope++; env->curr->value.push(); ret = type_engine_scan1_if( env, &stmt->stmt_if ); env->curr->value.pop(); env->class_scope--; break; case ae_stmt_for: env->class_scope++; env->curr->value.push(); ret = type_engine_scan1_for( env, &stmt->stmt_for ); env->curr->value.pop(); env->class_scope--; break; case ae_stmt_while: env->class_scope++; env->curr->value.push(); ret = type_engine_scan1_while( env, &stmt->stmt_while ); env->curr->value.pop(); env->class_scope--; break; case ae_stmt_until: env->class_scope++; env->curr->value.push();Lines 1–500 of 2831. Load more
/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.stanford.edu/ http://chuck.cs.princeton.edu/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_scan.cpp // desc: chuck type-system / type-checker pre-scan // // author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) // date: Summer 2005 - original //----------------------------------------------------------------------------- #include "chuck_scan.h" #include "chuck_errmsg.h" #include "chuck_instr.h" #include "chuck_type.h" #include "chuck_vm.h" #include "util_string.h" #include <string> using namespace std; //----------------------------------------------------------------------------- // function prototypes //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan0_class_def( Chuck_Env * env, a_Class_Def class_def ); t_CKBOOL type_engine_scan1_stmt_list( Chuck_Env * env, a_Stmt_List list ); t_CKBOOL type_engine_scan1_stmt( Chuck_Env * env, a_Stmt stmt ); t_CKBOOL type_engine_scan1_if( Chuck_Env * env, a_Stmt_If stmt ); t_CKBOOL type_engine_scan1_for( Chuck_Env * env, a_Stmt_For stmt ); t_CKBOOL type_engine_scan1_while( Chuck_Env * env, a_Stmt_While stmt ); t_CKBOOL type_engine_scan1_until( Chuck_Env * env, a_Stmt_Until stmt ); t_CKBOOL type_engine_scan1_loop( Chuck_Env * env, a_Stmt_Loop stmt ); t_CKBOOL type_engine_scan1_break( Chuck_Env * env, a_Stmt_Break br ); t_CKBOOL type_engine_scan1_continue( Chuck_Env * env, a_Stmt_Continue cont ); t_CKBOOL type_engine_scan1_return( Chuck_Env * env, a_Stmt_Return stmt ); t_CKBOOL type_engine_scan1_switch( Chuck_Env * env, a_Stmt_Switch stmt ); t_CKBOOL type_engine_scan1_exp( Chuck_Env * env, a_Exp exp ); t_CKBOOL type_engine_scan1_exp_binary( Chuck_Env * env, a_Exp_Binary binary ); t_CKBOOL type_engine_scan1_op( Chuck_Env * env, ae_Operator op, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ); t_CKBOOL type_engine_scan1_op_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ); t_CKBOOL type_engine_scan1_op_unchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs ); t_CKBOOL type_engine_scan1_op_upchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs ); t_CKBOOL type_engine_scan1_op_at_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs ); t_CKBOOL type_engine_scan1_exp_unary( Chuck_Env * env, a_Exp_Unary unary ); t_CKBOOL type_engine_scan1_exp_primary( Chuck_Env * env, a_Exp_Primary exp ); t_CKBOOL type_engine_scan1_exp_array_lit( Chuck_Env * env, a_Exp_Primary exp ); t_CKBOOL type_engine_scan1_exp_cast( Chuck_Env * env, a_Exp_Cast cast ); t_CKBOOL type_engine_scan1_exp_postfix( Chuck_Env * env, a_Exp_Postfix postfix ); t_CKBOOL type_engine_scan1_exp_dur( Chuck_Env * env, a_Exp_Dur dur ); t_CKBOOL type_engine_scan1_exp_array( Chuck_Env * env, a_Exp_Array array ); t_CKBOOL type_engine_scan1_exp_func_call( Chuck_Env * env, a_Exp_Func_Call func_call ); t_CKBOOL type_engine_scan1_exp_func_call( Chuck_Env * env, a_Exp exp_func, a_Exp args, t_CKFUNC & ck_func, int linepos ); t_CKBOOL type_engine_scan1_exp_dot_member( Chuck_Env * env, a_Exp_Dot_Member member ); t_CKBOOL type_engine_scan1_exp_if( Chuck_Env * env, a_Exp_If exp_if ); t_CKBOOL type_engine_scan1_exp_decl( Chuck_Env * env, a_Exp_Decl decl ); t_CKBOOL type_engine_scan1_array_subscripts( Chuck_Env * env, a_Exp exp_list ); t_CKBOOL type_engine_scan1_cast_valid( Chuck_Env * env, t_CKTYPE to, t_CKTYPE from ); t_CKBOOL type_engine_scan1_code_segment( Chuck_Env * env, a_Stmt_Code stmt, t_CKBOOL push = TRUE ); t_CKBOOL type_engine_scan1_func_def( Chuck_Env * env, a_Func_Def func_def ); t_CKBOOL type_engine_scan1_class_def( Chuck_Env * env, a_Class_Def class_def ); t_CKBOOL type_engine_scan2_stmt_list( Chuck_Env * env, a_Stmt_List list ); t_CKBOOL type_engine_scan2_stmt( Chuck_Env * env, a_Stmt stmt ); t_CKBOOL type_engine_scan2_if( Chuck_Env * env, a_Stmt_If stmt ); t_CKBOOL type_engine_scan2_for( Chuck_Env * env, a_Stmt_For stmt ); t_CKBOOL type_engine_scan2_while( Chuck_Env * env, a_Stmt_While stmt ); t_CKBOOL type_engine_scan2_loop( Chuck_Env * env, a_Stmt_Loop stmt ); t_CKBOOL type_engine_scan2_until( Chuck_Env * env, a_Stmt_Until stmt ); t_CKBOOL type_engine_scan2_break( Chuck_Env * env, a_Stmt_Break br ); t_CKBOOL type_engine_scan2_continue( Chuck_Env * env, a_Stmt_Continue cont ); t_CKBOOL type_engine_scan2_return( Chuck_Env * env, a_Stmt_Return stmt ); t_CKBOOL type_engine_scan2_switch( Chuck_Env * env, a_Stmt_Switch stmt ); t_CKBOOL type_engine_scan2_exp( Chuck_Env * env, a_Exp exp ); t_CKBOOL type_engine_scan2_exp_binary( Chuck_Env * env, a_Exp_Binary binary ); t_CKBOOL type_engine_scan2_op( Chuck_Env * env, ae_Operator op, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ); t_CKBOOL type_engine_scan2_op_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ); t_CKBOOL type_engine_scan2_op_unchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs ); t_CKBOOL type_engine_scan2_op_upchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs ); t_CKBOOL type_engine_scan2_op_at_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs ); t_CKBOOL type_engine_scan2_exp_unary( Chuck_Env * env, a_Exp_Unary unary ); t_CKBOOL type_engine_scan2_exp_primary( Chuck_Env * env, a_Exp_Primary exp ); t_CKBOOL type_engine_scan2_exp_array_lit( Chuck_Env * env, a_Exp_Primary exp ); t_CKBOOL type_engine_scan2_exp_cast( Chuck_Env * env, a_Exp_Cast cast ); t_CKBOOL type_engine_scan2_exp_postfix( Chuck_Env * env, a_Exp_Postfix postfix ); t_CKBOOL type_engine_scan2_exp_dur( Chuck_Env * env, a_Exp_Dur dur ); t_CKBOOL type_engine_scan2_exp_array( Chuck_Env * env, a_Exp_Array array ); t_CKBOOL type_engine_scan2_exp_func_call( Chuck_Env * env, a_Exp_Func_Call func_call ); t_CKBOOL type_engine_scan2_exp_func_call( Chuck_Env * env, a_Exp exp_func, a_Exp args, t_CKFUNC & ck_func, int linepos ); t_CKBOOL type_engine_scan2_exp_dot_member( Chuck_Env * env, a_Exp_Dot_Member member ); t_CKBOOL type_engine_scan2_exp_if( Chuck_Env * env, a_Exp_If exp_if ); t_CKBOOL type_engine_scan2_exp_decl( Chuck_Env * env, a_Exp_Decl decl ); t_CKBOOL type_engine_scan2_array_subscripts( Chuck_Env * env, a_Exp exp_list ); t_CKBOOL type_engine_scan2_cast_valid( Chuck_Env * env, t_CKTYPE to, t_CKTYPE from ); t_CKBOOL type_engine_scan2_code_segment( Chuck_Env * env, a_Stmt_Code stmt, t_CKBOOL push = TRUE ); t_CKBOOL type_engine_scan2_func_def( Chuck_Env * env, a_Func_Def func_def ); t_CKBOOL type_engine_scan2_class_def( Chuck_Env * env, a_Class_Def class_def ); t_CKBOOL type_engine_scan2_func_def( Chuck_Env * env, a_Func_Def func_def ); t_CKBOOL type_engine_scan2_class_def( Chuck_Env * env, a_Class_Def class_def ); //----------------------------------------------------------------------------- // name: type_engine_scan0_prog() // desc: data in env should be ready : type discovery //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan0_prog( Chuck_Env * env, a_Program prog, te_HowMuch how_much ) { t_CKBOOL ret = TRUE; if( !prog ) return FALSE; // log EM_log( CK_LOG_FINER, "(pass 0) type discovery scan..." ); // env->context->filename.c_str() ); // push indent EM_pushlog(); // log how much EM_log( CK_LOG_FINEST, "target: %s", howmuch2str( how_much ) ); // go through each of the program sections while( prog && ret ) { switch( prog->section->s_type ) { case ae_section_stmt: // do nothing break; case ae_section_func: // do nothing break; case ae_section_class: // if no classes, then skip if( how_much == te_do_no_classes ) break; // make global, if marked public if( prog->section->class_def->decl == ae_key_public ) { // make sure the context has no public class if( env->context->public_class_def != NULL ) { EM_error2( prog->section->class_def->linepos, "more than one 'public' class defined..." ); ret = FALSE; continue; } // make global prog->section->class_def->home = env->user(); // remember env->context->public_class_def = prog->section->class_def; } // scan the class definition ret = type_engine_scan0_class_def( env, prog->section->class_def ); break; default: EM_error2( prog->linepos, "internal error: unrecognized program section in type checker pre-scan..." ); ret = FALSE; break; } prog = prog->next; } // pop indent EM_poplog(); return ret; } //----------------------------------------------------------------------------- // name: type_engine_scan0_class_def() // desc: add defined class to env - this is the main goal of scan0 //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan0_class_def( Chuck_Env * env, a_Class_Def class_def ) { // make new type for class def t_CKTYPE the_class = NULL; // the return type t_CKBOOL ret = TRUE; // the class body a_Class_Body body = class_def->body; // log EM_log( CK_LOG_FINER, "scanning class definition '%s'...", S_name(class_def->name->xid) ); // push indent EM_pushlog(); // if nspc is attached to class_def, that means the class_def is to be // put in that namespace. this is usually the case when doing import if( class_def->home != NULL ) { // log EM_log( CK_LOG_FINER, "target namespace: '%s'", class_def->home->name.c_str() ); // set the new type as current env->nspc_stack.push_back( env->curr ); env->curr = class_def->home; } // make sure class not already in namespace if( env->curr->lookup_type( class_def->name->xid, FALSE ) ) { EM_error2( class_def->name->linepos, "class/type '%s' is already defined in namespace '%s'", S_name(class_def->name->xid), env->curr->name.c_str() ); ret = FALSE; goto done; } // check if reserved if( type_engine_check_reserved( env, class_def->name->xid, class_def->name->linepos ) ) { EM_error2( class_def->name->linepos, "...in class definition '%s'", S_name(class_def->name->xid) ); ret = FALSE; goto done; } // allocate new type assert( env->context != NULL ); the_class = env->context->new_Chuck_Type( env ); // add reference SAFE_ADD_REF( the_class ); // set the fields the_class->xid = te_user; the_class->name = S_name(class_def->name->xid); the_class->owner = env->curr; the_class->array_depth = 0; the_class->size = sizeof(void *); the_class->obj_size = 0; // TODO: the_class->info = env->context->new_Chuck_Namespace(); SAFE_ADD_REF( the_class->info ); the_class->info->name = the_class->name; // if public class, then set parent to context // ... allowing the class to address current context if( env->context->public_class_def == class_def ) { the_class->info->parent = env->context->nspc; } else { the_class->info->parent = env->curr; } // TODO: add ref to the parent? the_class->func = NULL; the_class->def = class_def; // add code the_class->info->pre_ctor = new Chuck_VM_Code; SAFE_ADD_REF( the_class->info->pre_ctor ); // add to env env->curr->type.add( the_class->name, the_class ); // URGENT: make this global // incomplete the_class->is_complete = FALSE; // set the new type as current env->nspc_stack.push_back( env->curr ); env->curr = the_class->info; // push the class def env->class_stack.push_back( env->class_def ); env->class_def = the_class; // reset the nest list env->class_scope = 0; // type check the body while( body && ret ) { // check the section switch( body->section->s_type ) { case ae_section_stmt: break; case ae_section_func: break; case ae_section_class: // do the class ret = type_engine_scan0_class_def( env, body->section->class_def ); break; } // move to the next section body = body->next; } // pop the class env->class_def = env->class_stack.back(); env->class_stack.pop_back(); // pop the namesapce env->curr = env->nspc_stack.back(); env->nspc_stack.pop_back(); // if things checked out if( ret ) { Chuck_Value * value = NULL; Chuck_Type * type = NULL; // allocate value type = env->t_class->copy( env ); type->actual_type = the_class; value = env->context->new_Chuck_Value( type, the_class->name ); value->owner = env->curr; value->is_const = TRUE; value->is_member = FALSE; // add to env env->curr->value.add( the_class->name, value ); // remember class_def->type = the_class; } // if nspc is attached to class_def, that means the class_def is to be // put in that namespace. this is usually the case when doing import // we undo that extra namespace layer here... if( class_def->home != NULL ) { // pop the namesapce env->curr = env->nspc_stack.back(); env->nspc_stack.pop_back(); } else // set the current namespace as home { // set curr as home class_def->home = env->curr; } // initialize the Type info object | 1.5.0.0 (ge) added initialize_object( the_class, env->t_class ); done: // pop indent EM_poplog(); return ret; } //----------------------------------------------------------------------------- // name: type_engine_scan1_prog() // desc: data in env should be ready //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_prog( Chuck_Env * env, a_Program prog, te_HowMuch how_much ) { t_CKBOOL ret = TRUE; if( !prog ) return FALSE; // log EM_log( CK_LOG_FINER, "(pass 1) type resolution scan..." ); // env->context->filename.c_str() ); // push indent EM_pushlog(); // log how much EM_log( CK_LOG_FINEST, "target: %s", howmuch2str( how_much ) ); // go through each of the program sections while( prog && ret ) { switch( prog->section->s_type ) { case ae_section_stmt: // if only classes, then skip if( how_much == te_do_classes_only ) break; // scan the statements ret = type_engine_scan1_stmt_list( env, prog->section->stmt_list ); break; case ae_section_func: // if only classes, then skip if( how_much == te_do_classes_only ) break; // scan the function definition ret = type_engine_scan1_func_def( env, prog->section->func_def ); break; case ae_section_class: // if no classes, then skip if( how_much == te_do_no_classes ) break; // scan the class definition ret = type_engine_scan1_class_def( env, prog->section->class_def ); break; default: EM_error2( prog->linepos, "internal error: unrecognized program section in type checker pre-scan..." ); ret = FALSE; break; } prog = prog->next; } // pop indent EM_poplog(); return ret; } //----------------------------------------------------------------------------- // name: type_engine_scan1_stmt_list() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_stmt_list( Chuck_Env * env, a_Stmt_List list ) { // type check the stmt_list while( list ) { // the current statement if( !type_engine_scan1_stmt( env, list->stmt ) ) return FALSE; // advance to the next statement list = list->next; } return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_stmt(() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_stmt( Chuck_Env * env, a_Stmt stmt ) { t_CKBOOL ret = FALSE; if( !stmt ) return TRUE; // the type of stmt switch( stmt->s_type ) { case ae_stmt_if: // count scope to help determine class member env->class_scope++; env->curr->value.push(); ret = type_engine_scan1_if( env, &stmt->stmt_if ); env->curr->value.pop(); env->class_scope--; break; case ae_stmt_for: env->class_scope++; env->curr->value.push(); ret = type_engine_scan1_for( env, &stmt->stmt_for ); env->curr->value.pop(); env->class_scope--; break; case ae_stmt_while: env->class_scope++; env->curr->value.push(); ret = type_engine_scan1_while( env, &stmt->stmt_while ); env->curr->value.pop(); env->class_scope--; break; case ae_stmt_until: env->class_scope++; env->curr->value.push();