1 /*----------------------------------------------------------------------------
2 ChucK Concurrent, On-the-fly Audio Programming Language
3 Compiler and Virtual Machine
5 Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6 http://chuck.cs.princeton.edu/
7 http://soundlab.cs.princeton.edu/
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 -----------------------------------------------------------------------------*/
25 //-----------------------------------------------------------------------------
26 // file: chuck_compile.cpp
27 // desc: chuck compile system unifying parser, type checker, and emitter
29 // author: Ge Wang (gewang@cs.princeton.edu)
30 // Perry R. Cook (prc@cs.princeton.edu)
31 // date: Autumn 2005 - original
32 //-----------------------------------------------------------------------------
33 #include "chuck_compile.h"
34 #include "chuck_lang.h"
35 #include "chuck_errmsg.h"
36 #include "chuck_otf.h"
40 #include "ugen_filter.h"
42 #include "uana_xform.h"
43 #include "uana_extract.h"
44 #include "ulib_machine.h"
45 #include "ulib_math.h"
47 #include "ulib_opsc.h"
54 // function prototypes
55 t_CKBOOL
load_internal_modules( Chuck_Compiler
* compiler
);
56 t_CKBOOL
load_module( Chuck_Env
* env
, f_ck_query query
, const char * name
, const char * nspc
);
61 //-----------------------------------------------------------------------------
62 // name: Chuck_Compiler()
64 //-----------------------------------------------------------------------------
65 Chuck_Compiler::Chuck_Compiler()
75 //-----------------------------------------------------------------------------
76 // name: ~Chuck_Compiler()
78 //-----------------------------------------------------------------------------
79 Chuck_Compiler::~Chuck_Compiler()
88 //-----------------------------------------------------------------------------
90 // desc: initialize the compiler
91 //-----------------------------------------------------------------------------
92 t_CKBOOL
Chuck_Compiler::initialize( Chuck_VM
* vm
)
95 EM_log( CK_LOG_SYSTEM
, "initializing compiler..." );
99 // allocate the type checker
100 env
= type_engine_init( vm
);
104 // allocate the emitter
105 emitter
= emit_engine_init( env
);
108 // set auto depend to 0
109 m_auto_depend
= FALSE
;
111 // load internal libs
112 if( !load_internal_modules( this ) )
133 //-----------------------------------------------------------------------------
135 // desc: shutdown the compiler
136 //-----------------------------------------------------------------------------
137 void Chuck_Compiler::shutdown()
140 EM_log( CK_LOG_SYSTEM
, "shutting down compiler..." ) ;
145 type_engine_shutdown( env
);
146 // emit_engine_shutdown( emitter );
150 m_auto_depend
= FALSE
;
160 //-----------------------------------------------------------------------------
161 // name: set_auto_depend()
162 // desc: auto dependency resolve for types
163 //-----------------------------------------------------------------------------
164 void Chuck_Compiler::set_auto_depend( t_CKBOOL v
)
167 EM_log( CK_LOG_SYSTEM
, "type dependency resolution: %s",
168 v
? "AUTO" : "MANUAL" );
175 //-----------------------------------------------------------------------------
177 // desc: parse, type-check, and emit a program
178 //-----------------------------------------------------------------------------
179 t_CKBOOL
Chuck_Compiler::go( const string
& filename
, FILE * fd
, const char * str_src
)
182 Chuck_Context
* context
= NULL
;
184 // check to see if resolve dependencies automatically
188 ret
= this->do_normal( filename
, fd
, str_src
);
194 if( !chuck_parse( filename
.c_str(), fd
, str_src
) )
198 context
= type_engine_make_context( g_program
, filename
);
199 if( !context
) return FALSE
;
205 if( !type_engine_load_context( env
, context
) )
209 if( !do_entire_file( context
) )
210 { ret
= FALSE
; goto cleanup
; }
213 if( !(code
= context
->code()) )
216 EM_error2( 0, "internal error: context->code() NULL!" );
223 if( ret
) env
->global()->commit();
225 else env
->global()->rollback();
227 // unload the context from the type-checker
228 if( !type_engine_unload_context( env
) )
230 EM_error2( 0, "internal error unloading context...\n" );
241 //-----------------------------------------------------------------------------
243 // desc: resolve type automatically - if auto_depend is off, return FALSE
244 //-----------------------------------------------------------------------------
245 t_CKBOOL
Chuck_Compiler::resolve( const string
& type
)
253 // look up if name is already parsed
263 //-----------------------------------------------------------------------------
264 // name: do_entire_file()
265 // desc: parse, type-check, and emit a program
266 //-----------------------------------------------------------------------------
267 t_CKBOOL
Chuck_Compiler::do_entire_file( Chuck_Context
* context
)
270 if( !type_engine_scan0_prog( env
, g_program
, te_do_all
) )
274 if( !type_engine_scan1_prog( env
, g_program
, te_do_all
) )
278 if( !type_engine_scan2_prog( env
, g_program
, te_do_all
) )
281 // check the program (pass 3)
282 if( !type_engine_check_context( env
, context
, te_do_all
) )
286 if( !emit_engine_emit_prog( emitter
, g_program
) )
289 // set the state of the context to done
290 context
->progress
= Chuck_Context::P_ALL
;
298 //-----------------------------------------------------------------------------
299 // name: do_only_classes()
300 // desc: compile only classes definitions
301 //-----------------------------------------------------------------------------
302 t_CKBOOL
Chuck_Compiler::do_only_classes( Chuck_Context
* context
)
305 if( !type_engine_scan0_prog( env
, g_program
, te_do_classes_only
) )
309 if( !type_engine_scan1_prog( env
, g_program
, te_do_classes_only
) )
313 if( !type_engine_scan2_prog( env
, g_program
, te_do_classes_only
) )
316 // check the program (pass 3)
317 if( !type_engine_check_context( env
, context
, te_do_classes_only
) )
321 if( !(code
= emit_engine_emit_prog( emitter
, g_program
, te_do_classes_only
)) )
324 // set the state of the context to done
325 context
->progress
= Chuck_Context::P_ALL
;
333 //-----------------------------------------------------------------------------
334 // name: do_all_except_classes()
335 // desc: compile everything except classes
336 //-----------------------------------------------------------------------------
337 t_CKBOOL
Chuck_Compiler::do_all_except_classes( Chuck_Context
* context
)
339 // 0th scan only deals with classes, so is not needed
342 if( !type_engine_scan1_prog( env
, g_program
, te_do_no_classes
) )
346 if( !type_engine_scan2_prog( env
, g_program
, te_do_no_classes
) )
349 // check the program (pass 3)
350 if( !type_engine_check_context( env
, context
, te_do_no_classes
) )
354 if( !(code
= emit_engine_emit_prog( emitter
, g_program
, te_do_no_classes
)) )
357 // set the state of the context to done
358 context
->progress
= Chuck_Context::P_ALL
;
366 //-----------------------------------------------------------------------------
368 // desc: compile normally without auto-depend
369 //-----------------------------------------------------------------------------
370 t_CKBOOL
Chuck_Compiler::do_normal( const string
& filename
, FILE * fd
, const char * str_src
)
373 Chuck_Context
* context
= NULL
;
376 if( !chuck_parse( filename
.c_str(), fd
, str_src
) )
380 context
= type_engine_make_context( g_program
, filename
);
381 if( !context
) return FALSE
;
387 if( !type_engine_load_context( env
, context
) )
391 if( !type_engine_scan0_prog( env
, g_program
, te_do_all
) )
392 { ret
= FALSE
; goto cleanup
; }
395 if( !type_engine_scan1_prog( env
, g_program
, te_do_all
) )
396 { ret
= FALSE
; goto cleanup
; }
399 if( !type_engine_scan2_prog( env
, g_program
, te_do_all
) )
400 { ret
= FALSE
; goto cleanup
; }
402 // check the program (pass 3)
403 if( !type_engine_check_context( env
, context
, te_do_all
) )
404 { ret
= FALSE
; goto cleanup
; }
407 if( !(code
= emit_engine_emit_prog( emitter
, g_program
, te_do_all
)) )
408 { ret
= FALSE
; goto cleanup
; }
413 if( ret
) env
->global()->commit();
415 else env
->global()->rollback();
417 // unload the context from the type-checker
418 if( !type_engine_unload_context( env
) )
420 EM_error2( 0, "internal error unloading context...\n" );
430 //-----------------------------------------------------------------------------
431 // name: find_recent_path()
432 // desc: find recent context by path
433 //-----------------------------------------------------------------------------
434 Chuck_Context
* Chuck_Compiler::find_recent_path( const string
& path
)
442 //-----------------------------------------------------------------------------
443 // name: find_recent_type()
444 // desc: find recent context by type name
445 //-----------------------------------------------------------------------------
446 Chuck_Context
* Chuck_Compiler::find_recent_type( const string
& type
)
454 //-----------------------------------------------------------------------------
455 // name: add_recent_path()
456 // desc: add recent context by path
457 //-----------------------------------------------------------------------------
458 t_CKBOOL
Chuck_Compiler::add_recent_path( const string
& path
,
459 Chuck_Context
* context
)
467 //-----------------------------------------------------------------------------
469 // desc: get the code generated by the last do()
470 //-----------------------------------------------------------------------------
471 Chuck_VM_Code
* Chuck_Compiler::output()
479 //-----------------------------------------------------------------------------
480 // name: load_module()
481 // desc: load a dll and add it
482 //-----------------------------------------------------------------------------
483 t_CKBOOL
load_module( Chuck_Env
* env
, f_ck_query query
,
484 const char * name
, const char * nspc
)
486 Chuck_DLL
* dll
= NULL
;
487 t_CKBOOL query_failed
= FALSE
;
490 dll
= new Chuck_DLL( name
);
491 if( !dll
->load( query
) || (query_failed
= !dll
->query()) ||
492 !type_engine_add_dll( env
, dll
, nspc
) )
495 "[chuck]: internal error loading module '%s.%s'...\n",
498 fprintf( stderr
, " %s\n", dll
->last_error() );
509 //-----------------------------------------------------------------------------
510 // name: load_internal_modules()
512 //-----------------------------------------------------------------------------
513 t_CKBOOL
load_internal_modules( Chuck_Compiler
* compiler
)
516 EM_log( CK_LOG_SEVERE
, "loading built-in modules..." );
521 Chuck_Env
* env
= compiler
->env
;
523 Chuck_Context
* context
= type_engine_make_context( NULL
, "@[internal]" );
524 // reset env - not needed since we just created the env
527 type_engine_load_context( env
, context
);
530 EM_log( CK_LOG_SEVERE
, "module osc..." );
531 load_module( env
, osc_query
, "osc", "global" );
532 EM_log( CK_LOG_SEVERE
, "module xxx..." );
533 load_module( env
, xxx_query
, "xxx", "global" );
534 EM_log( CK_LOG_SEVERE
, "module filter..." );
535 load_module( env
, filter_query
, "filter", "global" );
536 EM_log( CK_LOG_SEVERE
, "module STK..." );
537 load_module( env
, stk_query
, "stk", "global" );
538 EM_log( CK_LOG_SEVERE
, "module xform..." );
539 load_module( env
, xform_query
, "xform", "global" );
540 EM_log( CK_LOG_SEVERE
, "module extract..." );
541 load_module( env
, extract_query
, "extract", "global" );
544 EM_log( CK_LOG_SEVERE
, "class 'machine'..." );
545 if( !load_module( env
, machine_query
, "Machine", "global" ) ) goto error
;
546 machine_init( compiler
, otf_process_msg
);
547 EM_log( CK_LOG_SEVERE
, "class 'std'..." );
548 if( !load_module( env
, libstd_query
, "Std", "global" ) ) goto error
;
549 EM_log( CK_LOG_SEVERE
, "class 'math'..." );
550 if( !load_module( env
, libmath_query
, "Math", "global" ) ) goto error
;
551 EM_log( CK_LOG_SEVERE
, "class 'opsc'..." );
552 if( !load_module( env
, opensoundcontrol_query
, "opsc", "global" ) ) goto error
;
553 // if( !load_module( env, net_query, "net", "global" ) ) goto error;
555 #ifndef __DISABLE_MIDI__
556 if( !init_class_Midi( env
) ) goto error
;
557 if( !init_class_MidiRW( env
) ) goto error
;
558 #endif // __DISABLE_MIDI__
559 if( !init_class_HID( env
) ) goto error
;
562 type_engine_unload_context( env
);
564 // commit what is in the type checker at this point
565 env
->global()->commit();
574 // probably dangerous: rollback
575 env
->global()->rollback();
578 type_engine_unload_context( env
);