/*---------------------------------------------------------------------------- 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_compile.cpp// desc: chuck compile system unifying parser, type checker, and emitter//// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)// date: Autumn 2005 - original//-----------------------------------------------------------------------------#include "chuck_compile.h"#include "chuck_lang.h"#include "chuck_errmsg.h"#include "chuck_io.h"#ifndef __DISABLE_OTF_SERVER__#include "chuck_otf.h"#endif #include "ugen_osc.h"#include "ugen_xxx.h"#include "ugen_filter.h"#include "ugen_stk.h"#include "uana_xform.h"#include "uana_extract.h" #include "ulib_ai.h"#include "ulib_doc.h"#include "ulib_machine.h"#include "ulib_math.h"#include "ulib_std.h"#include "util_string.h" #ifndef __DISABLE_NETWORK__#include "ulib_opsc.h"#endif #if defined(__PLATFORM_WIN32__) #include "dirent_win32.h"#endif //#if defined(__WINDOWS_PTHREAD__)#include <sys/stat.h>//#endif #include <string>#include <vector>#include <algorithm>using namespace std; // function prototypest_CKBOOL load_internal_modules( Chuck_Compiler * compiler );t_CKBOOL load_external_modules( Chuck_Compiler * compiler, const char * extension, std::list<std::string> & chugin_search_paths, std::list<std::string> & named_dls);t_CKBOOL load_module( Chuck_Compiler * compiler, Chuck_Env * env, f_ck_query query, const char * name, const char * nspc ); //-----------------------------------------------------------------------------// name: Chuck_Compiler()// desc: constructor//-----------------------------------------------------------------------------Chuck_Compiler::Chuck_Compiler(){ emitter = NULL; code = NULL; // REFACTOR-2017: add carrier m_carrier = NULL; // initialize m_auto_depend = FALSE; // origin hint | 1.5.0.0 (ge) added m_originHint = te_originUnknown;} //-----------------------------------------------------------------------------// name: ~Chuck_Compiler()// desc: destructor//-----------------------------------------------------------------------------Chuck_Compiler::~Chuck_Compiler(){ // call shutdown this->shutdown();} //-----------------------------------------------------------------------------// name: initialize()// desc: initialize the compiler//-----------------------------------------------------------------------------t_CKBOOL Chuck_Compiler::initialize(){ // set origin hint m_originHint = te_originBuiltin; // allocate the type checker Chuck_Env * env = type_engine_init( m_carrier ); // add reference env->add_ref(); // allocate the emitter emitter = emit_engine_init( env ); // add reference emitter->add_ref(); // set auto depend to 0 m_auto_depend = FALSE; // load internal libs if( !load_internal_modules( this ) ) goto error; // unset origin hint m_originHint = te_originUnknown; return TRUE; error: // clean up | 1.4.1.0 (ge) removed -- should be cleaned up outside // this->shutdown(); // pop indent EM_poplog(); return FALSE;} //-----------------------------------------------------------------------------// name: shutdown()// desc: shutdown the compiler//-----------------------------------------------------------------------------void Chuck_Compiler::shutdown(){ // log EM_log( CK_LOG_SYSTEM, "shutting down compiler..." ) ; // push indent EM_pushlog(); // TODO: free type_engine_shutdown( env() ); // TODO: check if emitter gets cleaned up // emit_engine_shutdown( emitter ); emitter = NULL; code = NULL; m_auto_depend = FALSE; m_recent.clear(); for(std::list<Chuck_DLL *>::iterator i = m_dlls.begin(); i != m_dlls.end(); i++) { delete (*i); } m_dlls.clear(); // pop indent EM_poplog();} //-----------------------------------------------------------------------------// name: bind()// desc: bind a new type system module, via query function//-----------------------------------------------------------------------------t_CKBOOL Chuck_Compiler::bind( f_ck_query query_func, const std::string & name, const std::string & nspc ){ // log EM_log( CK_LOG_SYSTEM, "on-demand binding compiler module '%s'...", name.c_str() ); // push indent level EM_pushlog(); // get env Chuck_Env * env = this->env(); // make context Chuck_Context * context = type_engine_make_context( NULL, string("@[bind:") + name + string("]") ); // reset env - not needed since we just created the env env->reset(); // load it type_engine_load_context( env, context ); // do it if( !load_module( this, env, query_func, name.c_str(), nspc.c_str() ) ) goto error; // clear context type_engine_unload_context( env ); // commit what is in the type checker at this point env->global()->commit(); // pop indent level EM_poplog(); return TRUE; error: // probably dangerous: rollback env->global()->rollback(); // clear context type_engine_unload_context( env ); // pop indent level EM_poplog(); return FALSE;} //-----------------------------------------------------------------------------// name: set_auto_depend()// desc: auto dependency resolve for types//-----------------------------------------------------------------------------void Chuck_Compiler::set_auto_depend( t_CKBOOL v ){ // log EM_log( CK_LOG_SYSTEM, "type dependency resolution: %s", v ? "AUTO" : "MANUAL" ); m_auto_depend = v;} //-----------------------------------------------------------------------------// name: go()// desc: parse, type-check, and emit a program//-----------------------------------------------------------------------------t_CKBOOL Chuck_Compiler::go( const string & filename, const string & full_path, const string & codeLiteral ){ t_CKBOOL ret = TRUE; // Chuck_Context * context = NULL; EM_reset_msg(); // check to see if resolve dependencies automatically if( !m_auto_depend ) { // normal (note: full_path added 1.3.0.0) ret = this->do_normal_depend( filename, codeLiteral, full_path ); } else // auto depend { // call auto-depend compile (1.4.1.0) ret = this->do_auto_depend( filename, codeLiteral, full_path ); } // 1.4.1.0 (ge) | added to unset the fileName reference, which determines // how messages print to console (e.g., [file.ck]: or [chuck]:) EM_change_file( NULL ); return ret;} //-----------------------------------------------------------------------------// name: set_file2parse()// desc: set a FILE * for one-time use on next go(); see header for details//-----------------------------------------------------------------------------void Chuck_Compiler::set_file2parse( FILE * fd, t_CKBOOL autoClose ){ // call down to parser ::fd2parse_set( fd, autoClose );} //-----------------------------------------------------------------------------// name: resolve()// desc: resolve type automatically - if auto_depend is off, return FALSE//-----------------------------------------------------------------------------t_CKBOOL Chuck_Compiler::resolve( const string & type ){ t_CKBOOL ret = TRUE; // check auto_depend if( !m_auto_depend ) return FALSE; // look up if name is already parsed return ret;} //-----------------------------------------------------------------------------// name: setReplaceDac()// desc: tell the compiler whether dac should be replaced in scripts// with the name of an external UGen, and if so which one//-----------------------------------------------------------------------------void Chuck_Compiler::setReplaceDac( t_CKBOOL shouldReplaceDac, const std::string & replacement ){ emitter->should_replace_dac = shouldReplaceDac; emitter->dac_replacement = replacement;} //-----------------------------------------------------------------------------// name: do_entire_file()// desc: parse, type-check, and emit a program//-----------------------------------------------------------------------------t_CKBOOL Chuck_Compiler::do_entire_file( Chuck_Context * context ){ // 0th-scan (pass 0) if( !type_engine_scan0_prog( env(), g_program, te_do_all ) ) return FALSE; // 1st-scan (pass 1) if( !type_engine_scan1_prog( env(), g_program, te_do_all ) ) return FALSE; // 2nd-scan (pass 2) if( !type_engine_scan2_prog( env(), g_program, te_do_all ) ) return FALSE; // check the program (pass 3) if( !type_engine_check_context( env(), context, te_do_all ) ) return FALSE; // emit (pass 4) if( !emit_engine_emit_prog( emitter, g_program ) ) return FALSE; // set the state of the context to done context->progress = Chuck_Context::P_ALL_DONE; return TRUE;} //-----------------------------------------------------------------------------// name: do_only_classes()// desc: compile only classes definitions//-----------------------------------------------------------------------------t_CKBOOL Chuck_Compiler::do_only_classes( Chuck_Context * context ){ // 0th-scan (pass 0) if( !type_engine_scan0_prog( env(), g_program, te_do_classes_only ) ) return FALSE; // 1st-scan (pass 1) if( !type_engine_scan1_prog( env(), g_program, te_do_classes_only ) ) return FALSE; // 2nd-scan (pass 2) if( !type_engine_scan2_prog( env(), g_program, te_do_classes_only ) ) return FALSE; // check the program (pass 3) if( !type_engine_check_context( env(), context, te_do_classes_only ) ) return FALSE; // emit (pass 4) code = emit_engine_emit_prog( emitter, g_program , te_do_classes_only ); if( !code ) return FALSE; // set the state of the context to done context->progress = Chuck_Context::P_ALL_DONE; return TRUE;} //-----------------------------------------------------------------------------// name: do_all_except_classes()// desc: compile everything except classes//-----------------------------------------------------------------------------t_CKBOOL Chuck_Compiler::do_all_except_classes( Chuck_Context * context ){ // 0th scan only deals with classes, so is not needed // 1st-scan (pass 1) if( !type_engine_scan1_prog( env(), g_program, te_do_no_classes ) ) return FALSE; // 2nd-scan (pass 2) if( !type_engine_scan2_prog( env(), g_program, te_do_no_classes ) ) return FALSE; // check the program (pass 3) if( !type_engine_check_context( env(), context, te_do_no_classes ) ) return FALSE; // emit (pass 4) code = emit_engine_emit_prog( emitter, g_program, te_do_no_classes ); if( !code ) return FALSE; // set the state of the context to done context->progress = Chuck_Context::P_ALL_DONE; return TRUE;} //-----------------------------------------------------------------------------// name: do_normal_depend()// desc: compile normally without auto-depend//-----------------------------------------------------------------------------t_CKBOOL Chuck_Compiler::do_normal_depend( const string & filename, const string & codeLiteral, const string & full_path ){ t_CKBOOL ret = TRUE; Chuck_Context * context = NULL; // expand string theFilename = expand_filepath(filename); string theFullpath = expand_filepath(full_path); // parse the code if( !chuck_parse( theFilename, codeLiteral ) ) return FALSE; // make the context context = type_engine_make_context( g_program, theFilename ); if( !context ) return FALSE; // remember full path (added 1.3.0.0) context->full_path = theFullpath; // reset the env env()->reset(); // load the context if( !type_engine_load_context( env(), context ) ) return FALSE; // 0th-scan (pass 0) if( !type_engine_scan0_prog( env(), g_program, te_do_all ) ) { ret = FALSE; goto cleanup; } // 1st-scan (pass 1) if( !type_engine_scan1_prog( env(), g_program, te_do_all ) ) { ret = FALSE; goto cleanup; } // 2nd-scan (pass 2) if( !type_engine_scan2_prog( env(), g_program, te_do_all ) ) { ret = FALSE; goto cleanup; } Lines 1–500 of 1292. 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_compile.cpp // desc: chuck compile system unifying parser, type checker, and emitter // // author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) // date: Autumn 2005 - original //----------------------------------------------------------------------------- #include "chuck_compile.h" #include "chuck_lang.h" #include "chuck_errmsg.h" #include "chuck_io.h" #ifndef __DISABLE_OTF_SERVER__ #include "chuck_otf.h" #endif #include "ugen_osc.h" #include "ugen_xxx.h" #include "ugen_filter.h" #include "ugen_stk.h" #include "uana_xform.h" #include "uana_extract.h" #include "ulib_ai.h" #include "ulib_doc.h" #include "ulib_machine.h" #include "ulib_math.h" #include "ulib_std.h" #include "util_string.h" #ifndef __DISABLE_NETWORK__ #include "ulib_opsc.h" #endif #if defined(__PLATFORM_WIN32__) #include "dirent_win32.h" #endif //#if defined(__WINDOWS_PTHREAD__) #include <sys/stat.h> //#endif #include <string> #include <vector> #include <algorithm> using namespace std; // function prototypes t_CKBOOL load_internal_modules( Chuck_Compiler * compiler ); t_CKBOOL load_external_modules( Chuck_Compiler * compiler, const char * extension, std::list<std::string> & chugin_search_paths, std::list<std::string> & named_dls); t_CKBOOL load_module( Chuck_Compiler * compiler, Chuck_Env * env, f_ck_query query, const char * name, const char * nspc ); //----------------------------------------------------------------------------- // name: Chuck_Compiler() // desc: constructor //----------------------------------------------------------------------------- Chuck_Compiler::Chuck_Compiler() { emitter = NULL; code = NULL; // REFACTOR-2017: add carrier m_carrier = NULL; // initialize m_auto_depend = FALSE; // origin hint | 1.5.0.0 (ge) added m_originHint = te_originUnknown; } //----------------------------------------------------------------------------- // name: ~Chuck_Compiler() // desc: destructor //----------------------------------------------------------------------------- Chuck_Compiler::~Chuck_Compiler() { // call shutdown this->shutdown(); } //----------------------------------------------------------------------------- // name: initialize() // desc: initialize the compiler //----------------------------------------------------------------------------- t_CKBOOL Chuck_Compiler::initialize() { // set origin hint m_originHint = te_originBuiltin; // allocate the type checker Chuck_Env * env = type_engine_init( m_carrier ); // add reference env->add_ref(); // allocate the emitter emitter = emit_engine_init( env ); // add reference emitter->add_ref(); // set auto depend to 0 m_auto_depend = FALSE; // load internal libs if( !load_internal_modules( this ) ) goto error; // unset origin hint m_originHint = te_originUnknown; return TRUE; error: // clean up | 1.4.1.0 (ge) removed -- should be cleaned up outside // this->shutdown(); // pop indent EM_poplog(); return FALSE; } //----------------------------------------------------------------------------- // name: shutdown() // desc: shutdown the compiler //----------------------------------------------------------------------------- void Chuck_Compiler::shutdown() { // log EM_log( CK_LOG_SYSTEM, "shutting down compiler..." ) ; // push indent EM_pushlog(); // TODO: free type_engine_shutdown( env() ); // TODO: check if emitter gets cleaned up // emit_engine_shutdown( emitter ); emitter = NULL; code = NULL; m_auto_depend = FALSE; m_recent.clear(); for(std::list<Chuck_DLL *>::iterator i = m_dlls.begin(); i != m_dlls.end(); i++) { delete (*i); } m_dlls.clear(); // pop indent EM_poplog(); } //----------------------------------------------------------------------------- // name: bind() // desc: bind a new type system module, via query function //----------------------------------------------------------------------------- t_CKBOOL Chuck_Compiler::bind( f_ck_query query_func, const std::string & name, const std::string & nspc ) { // log EM_log( CK_LOG_SYSTEM, "on-demand binding compiler module '%s'...", name.c_str() ); // push indent level EM_pushlog(); // get env Chuck_Env * env = this->env(); // make context Chuck_Context * context = type_engine_make_context( NULL, string("@[bind:") + name + string("]") ); // reset env - not needed since we just created the env env->reset(); // load it type_engine_load_context( env, context ); // do it if( !load_module( this, env, query_func, name.c_str(), nspc.c_str() ) ) goto error; // clear context type_engine_unload_context( env ); // commit what is in the type checker at this point env->global()->commit(); // pop indent level EM_poplog(); return TRUE; error: // probably dangerous: rollback env->global()->rollback(); // clear context type_engine_unload_context( env ); // pop indent level EM_poplog(); return FALSE; } //----------------------------------------------------------------------------- // name: set_auto_depend() // desc: auto dependency resolve for types //----------------------------------------------------------------------------- void Chuck_Compiler::set_auto_depend( t_CKBOOL v ) { // log EM_log( CK_LOG_SYSTEM, "type dependency resolution: %s", v ? "AUTO" : "MANUAL" ); m_auto_depend = v; } //----------------------------------------------------------------------------- // name: go() // desc: parse, type-check, and emit a program //----------------------------------------------------------------------------- t_CKBOOL Chuck_Compiler::go( const string & filename, const string & full_path, const string & codeLiteral ) { t_CKBOOL ret = TRUE; // Chuck_Context * context = NULL; EM_reset_msg(); // check to see if resolve dependencies automatically if( !m_auto_depend ) { // normal (note: full_path added 1.3.0.0) ret = this->do_normal_depend( filename, codeLiteral, full_path ); } else // auto depend { // call auto-depend compile (1.4.1.0) ret = this->do_auto_depend( filename, codeLiteral, full_path ); } // 1.4.1.0 (ge) | added to unset the fileName reference, which determines // how messages print to console (e.g., [file.ck]: or [chuck]:) EM_change_file( NULL ); return ret; } //----------------------------------------------------------------------------- // name: set_file2parse() // desc: set a FILE * for one-time use on next go(); see header for details //----------------------------------------------------------------------------- void Chuck_Compiler::set_file2parse( FILE * fd, t_CKBOOL autoClose ) { // call down to parser ::fd2parse_set( fd, autoClose ); } //----------------------------------------------------------------------------- // name: resolve() // desc: resolve type automatically - if auto_depend is off, return FALSE //----------------------------------------------------------------------------- t_CKBOOL Chuck_Compiler::resolve( const string & type ) { t_CKBOOL ret = TRUE; // check auto_depend if( !m_auto_depend ) return FALSE; // look up if name is already parsed return ret; } //----------------------------------------------------------------------------- // name: setReplaceDac() // desc: tell the compiler whether dac should be replaced in scripts // with the name of an external UGen, and if so which one //----------------------------------------------------------------------------- void Chuck_Compiler::setReplaceDac( t_CKBOOL shouldReplaceDac, const std::string & replacement ) { emitter->should_replace_dac = shouldReplaceDac; emitter->dac_replacement = replacement; } //----------------------------------------------------------------------------- // name: do_entire_file() // desc: parse, type-check, and emit a program //----------------------------------------------------------------------------- t_CKBOOL Chuck_Compiler::do_entire_file( Chuck_Context * context ) { // 0th-scan (pass 0) if( !type_engine_scan0_prog( env(), g_program, te_do_all ) ) return FALSE; // 1st-scan (pass 1) if( !type_engine_scan1_prog( env(), g_program, te_do_all ) ) return FALSE; // 2nd-scan (pass 2) if( !type_engine_scan2_prog( env(), g_program, te_do_all ) ) return FALSE; // check the program (pass 3) if( !type_engine_check_context( env(), context, te_do_all ) ) return FALSE; // emit (pass 4) if( !emit_engine_emit_prog( emitter, g_program ) ) return FALSE; // set the state of the context to done context->progress = Chuck_Context::P_ALL_DONE; return TRUE; } //----------------------------------------------------------------------------- // name: do_only_classes() // desc: compile only classes definitions //----------------------------------------------------------------------------- t_CKBOOL Chuck_Compiler::do_only_classes( Chuck_Context * context ) { // 0th-scan (pass 0) if( !type_engine_scan0_prog( env(), g_program, te_do_classes_only ) ) return FALSE; // 1st-scan (pass 1) if( !type_engine_scan1_prog( env(), g_program, te_do_classes_only ) ) return FALSE; // 2nd-scan (pass 2) if( !type_engine_scan2_prog( env(), g_program, te_do_classes_only ) ) return FALSE; // check the program (pass 3) if( !type_engine_check_context( env(), context, te_do_classes_only ) ) return FALSE; // emit (pass 4) code = emit_engine_emit_prog( emitter, g_program , te_do_classes_only ); if( !code ) return FALSE; // set the state of the context to done context->progress = Chuck_Context::P_ALL_DONE; return TRUE; } //----------------------------------------------------------------------------- // name: do_all_except_classes() // desc: compile everything except classes //----------------------------------------------------------------------------- t_CKBOOL Chuck_Compiler::do_all_except_classes( Chuck_Context * context ) { // 0th scan only deals with classes, so is not needed // 1st-scan (pass 1) if( !type_engine_scan1_prog( env(), g_program, te_do_no_classes ) ) return FALSE; // 2nd-scan (pass 2) if( !type_engine_scan2_prog( env(), g_program, te_do_no_classes ) ) return FALSE; // check the program (pass 3) if( !type_engine_check_context( env(), context, te_do_no_classes ) ) return FALSE; // emit (pass 4) code = emit_engine_emit_prog( emitter, g_program, te_do_no_classes ); if( !code ) return FALSE; // set the state of the context to done context->progress = Chuck_Context::P_ALL_DONE; return TRUE; } //----------------------------------------------------------------------------- // name: do_normal_depend() // desc: compile normally without auto-depend //----------------------------------------------------------------------------- t_CKBOOL Chuck_Compiler::do_normal_depend( const string & filename, const string & codeLiteral, const string & full_path ) { t_CKBOOL ret = TRUE; Chuck_Context * context = NULL; // expand string theFilename = expand_filepath(filename); string theFullpath = expand_filepath(full_path); // parse the code if( !chuck_parse( theFilename, codeLiteral ) ) return FALSE; // make the context context = type_engine_make_context( g_program, theFilename ); if( !context ) return FALSE; // remember full path (added 1.3.0.0) context->full_path = theFullpath; // reset the env env()->reset(); // load the context if( !type_engine_load_context( env(), context ) ) return FALSE; // 0th-scan (pass 0) if( !type_engine_scan0_prog( env(), g_program, te_do_all ) ) { ret = FALSE; goto cleanup; } // 1st-scan (pass 1) if( !type_engine_scan1_prog( env(), g_program, te_do_all ) ) { ret = FALSE; goto cleanup; } // 2nd-scan (pass 2) if( !type_engine_scan2_prog( env(), g_program, te_do_all ) ) { ret = FALSE; goto cleanup; }