2831 lines · 84.2 KB · C++
RawDownload
/*----------------------------------------------------------------------------  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 '%s'...",            env->context->filename.c_str() );    // push indent    EM_pushlog();    // log how much    EM_log( CK_LOG_FINER, "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 '%s'...",        env->context->filename.c_str() );    // push indent    EM_pushlog();    // log how much    EM_log( CK_LOG_FINER, "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.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t