*** empty log message ***
[chuck-blob.git] / v1 / chuck_emit.cpp
blob0ae11feb7111a019897b49df8adc3b386602d998
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
22 U.S.A.
23 -----------------------------------------------------------------------------*/
25 //-----------------------------------------------------------------------------
26 // file: chuck_emit.cpp
27 // desc: ...
29 // author: Ge Wang (gewang@cs.princeton.edu)
30 // Perry R. Cook (prc@cs.princeton.edu)
31 // date: Autumn 2002
32 // Autumn 2003 updated
33 //-----------------------------------------------------------------------------
34 #include <vector>
35 #include <string>
36 using namespace std;
38 #include "chuck_emit.h"
39 #include "chuck_frame.h"
40 #include "chuck_instr.h"
41 #include "chuck_bbq.h"
42 #include "chuck_vm.h"
43 #include "chuck_errmsg.h"
48 //-----------------------------------------------------------------------------
49 // name: class Chuck_Code
50 // desc: ...
51 //-----------------------------------------------------------------------------
52 class Chuck_Code
54 public:
55 vector<Chuck_Instr *> code;
56 string name;
57 F_Frame frame;
58 unsigned int stack_depth;
60 Chuck_Code( c_str scope_name )
62 name = scope_name;
63 frame = F_new_frame( Temp_named_label( scope_name ) );
64 stack_depth = 0;
67 ~Chuck_Code()
69 // TODO: free the frame
76 //-----------------------------------------------------------------------------
77 // name: struct Dur_Node
78 // desc: ...
79 //-----------------------------------------------------------------------------
80 struct Dur_Node
82 t_CKDUR dur;
84 Dur_Node( t_CKDUR d )
85 { dur = d; }
91 //-----------------------------------------------------------------------------
92 // name: struct Func_Link
93 // desc: ...
94 //-----------------------------------------------------------------------------
95 struct Func_Link
97 S_Symbol name;
98 Chuck_Instr_Reg_Push_Imm * op;
101 // global func table
102 S_table g_func2code = NULL;
103 vector<Func_Link *> g_func_links;
108 //-----------------------------------------------------------------------------
109 // name: struct Chuck_Emmission
110 // desc: ...
111 //-----------------------------------------------------------------------------
112 struct Chuck_Emmission
114 Chuck_Code * global;
115 Chuck_Code * local;
116 vector<Chuck_Code *> functions;
117 S_table var2offset;
118 S_table dur2num_samps;
119 S_table globals;
120 t_Env env;
121 unsigned int is_global;
122 unsigned int count;
123 unsigned int chuck_count;
124 vector<Chuck_Instr_Branch_Op *> returns;
125 vector<Chuck_Instr_Unary_Op *> addr_map;
127 // namespace
128 t_Env nspc;
129 a_Func_Def nspc_func;
130 vector<Chuck_Instr_Unary_Op *> ops;
132 Chuck_Emmission( t_Env e )
134 global = NULL;
135 local = NULL;
136 var2offset = S_empty();
137 dur2num_samps = S_empty();
138 globals = S_empty();
139 is_global = TRUE;
140 count = 0;
141 chuck_count = 0;
142 returns.clear();
143 env = e;
144 nspc = e;
145 nspc_func = NULL;
148 void push_op( Chuck_Instr_Unary_Op * a )
150 ops.push_back( a );
153 Chuck_Instr_Unary_Op * get_op()
155 if( ops.size() ) return ops[ops.size()-1];
156 else return NULL;
159 void pop_op( )
161 if( ops.size() ) ops.pop_back();
164 void append_ops()
166 while( get_op() )
168 append( get_op() );
169 pop_op();
173 void pop_the_ops()
175 ops.clear();
176 // while( get_op() ) pop_op();
179 uint append( Chuck_Instr * instr )
181 if( is_global )
183 global->code.push_back( instr );
184 return (uint)global->code.size() - 1;
186 else
188 local->code.push_back( instr );
189 return (uint)local->code.size() - 1;
193 Chuck_Instr * remove_last( )
195 if( is_global )
197 if( global->code.size() == 0 ) return NULL;
198 Chuck_Instr * instr = *global->code.end();
199 global->code.pop_back();
200 return instr;
202 else
204 if( local->code.size() == 0 ) return NULL;
205 Chuck_Instr * instr = *local->code.end();
206 local->code.pop_back();
207 return instr;
211 uint next_index()
213 if( is_global )
214 return (uint)global->code.size();
215 else
216 return (uint)local->code.size();
219 void alloc_dur( S_Symbol var, t_CKDUR samp )
221 S_enter( dur2num_samps, var, new Dur_Node( samp ) );
224 uint find_dur( S_Symbol var, t_CKDUR * dur )
226 Dur_Node * n = (Dur_Node *)S_look( dur2num_samps, var );
227 if( !n )
228 return FALSE;
230 *dur = n->dur;
231 return TRUE;
234 unsigned int alloc_local( S_Symbol var, t_Type type )
236 // allocate offset in the frame
237 F_Access a;
238 if( is_global )
239 a = F_alloc_local( global->frame, type->size, is_global );
240 else
241 a = F_alloc_local( local->frame, type->size, is_global );
243 unsigned int offset = F_offset( a );
245 // push in the table
246 S_enter( var2offset, var, a );
248 return offset;
251 int find_offset( S_Symbol var, t_CKBOOL * isglobal = NULL, t_CKUINT * size = NULL )
253 F_Access a = (F_Access)S_look( var2offset, var );
254 if( !a )
255 return -1;
256 if( isglobal )
257 *isglobal = a->global;
258 if( size )
259 *size = a->size;
261 return a->offset;
264 unsigned int stack_depth()
266 if( is_global )
267 return F_stack_depth( global->frame );
268 else
269 return F_stack_depth( local->frame );
272 void push( c_str scope_name = NULL )
274 S_beginScope( var2offset );
275 if( this->is_global )
276 F_begin_scope( global->frame );
277 else
278 F_begin_scope( local->frame );
279 count++;
282 void pop( )
284 if( !count )
286 EM_error2( 0, "(emit): internal error - too many pop()!" );
287 return;
290 S_endScope( var2offset );
291 if( is_global )
292 F_end_scope( global->frame );
293 else
294 F_end_scope( local->frame );
295 count--;
302 //-----------------------------------------------------------------------------
303 // name: emit_to_code()
304 // desc: emit to vm code
305 //-----------------------------------------------------------------------------
306 Chuck_VM_Code * emit_to_code( Chuck_Emmission * emit, t_CKBOOL dump )
308 Chuck_VM_Code * code = new Chuck_VM_Code;
309 code->num_instr = emit->global->code.size();
310 code->instr = new Chuck_Instr *[code->num_instr];
312 // copy
313 for( unsigned int i = 0; i < code->num_instr; i++ )
314 code->instr[i] = emit->global->code[i];
316 // functions
317 for( unsigned int j = 0; j < emit->functions.size(); j++ )
319 Chuck_VM_Code * code2 = new Chuck_VM_Code;
320 Chuck_Code * c = emit->functions[j];
321 code2->num_instr = c->code.size();
322 code2->instr = new Chuck_Instr *[code2->num_instr];
324 // copy
325 for( unsigned int i = 0; i < code2->num_instr; i++ )
326 code2->instr[i] = c->code[i];
328 // set the parent
329 code2->stack_depth = c->stack_depth;
331 if( dump )
333 fprintf( stderr, "[chuck]: dumping function %s( ... )\n\n", c->name.c_str() );
335 for( unsigned int i = 0; i < code2->num_instr; i++ )
336 fprintf( stdout, "'%i' %s( %s )\n", i,
337 code2->instr[i]->name(), code2->instr[i]->params() );
339 fprintf( stdout, "...\n\n" );
342 // put in table
343 S_enter( g_func2code, insert_symbol((char *)c->name.c_str()), code2 );
346 return code;
352 //------------------------------------------------------------------------------
353 // name: emit_engine_addr_map()
354 // desc: ...
355 //------------------------------------------------------------------------------
356 t_CKBOOL emit_engine_addr_map( Chuck_Emmission * emit, Chuck_VM_Shred * shred )
358 // memory stack
359 uint sp = (uint)shred->mem->sp;
361 // offset the initial region
362 sp += sizeof(t_CKINT);
364 // map the offset to pointers
365 for( unsigned int i = 0; i < emit->addr_map.size(); i++ )
366 emit->addr_map[i]->set( sp + emit->addr_map[i]->get() );
368 return TRUE;
373 //-----------------------------------------------------------------------------
374 // name: emit_engine_resolve()
375 // desc: ...
376 //-----------------------------------------------------------------------------
377 t_CKBOOL emit_engine_resolve()
379 Func_Link * f = NULL;
380 Chuck_VM_Code * code = NULL;
382 for( unsigned int i = 0; i < g_func_links.size(); i++ )
384 f = g_func_links[i];
385 code = (Chuck_VM_Code *)S_look( g_func2code, f->name );
386 if( code == NULL )
388 EM_error2( 0, "error: cannot resolve function '%s'",
389 S_name(f->name) );
390 return FALSE;
393 f->op->set( (uint)code );
396 g_func_links.clear();
398 return TRUE;
404 //-----------------------------------------------------------------------------
405 // prototypes
406 //-----------------------------------------------------------------------------
407 t_CKBOOL emit_engine_emit_prog( Chuck_Emmission * emit, a_Program prog );
408 t_CKBOOL emit_engine_emit_stmt_list( Chuck_Emmission * emit, a_Stmt_List list );
409 t_CKBOOL emit_engine_emit_stmt( Chuck_Emmission * emit, a_Stmt stmt, t_CKBOOL pop = TRUE );
410 t_CKBOOL emit_engine_emit_code_segment( Chuck_Emmission * emit, a_Stmt_Code stmt );
411 t_CKBOOL emit_engine_emit_switch( Chuck_Emmission * emit, a_Stmt_Switch stmt );
412 t_CKBOOL emit_engine_emit_while( Chuck_Emmission * emit, a_Stmt_While stmt );
413 t_CKBOOL emit_engine_emit_do_while( Chuck_Emmission * emit, a_Stmt_While stmt );
414 t_CKBOOL emit_engine_emit_until( Chuck_Emmission * emit, a_Stmt_Until stmt );
415 t_CKBOOL emit_engine_emit_do_until( Chuck_Emmission * emit, a_Stmt_Until stmt );
416 t_CKBOOL emit_engine_emit_for( Chuck_Emmission * emit, a_Stmt_For stmt );
417 t_CKBOOL emit_engine_emit_if( Chuck_Emmission * emit, a_Stmt_If stmt );
418 t_CKBOOL emit_engine_emit_return( Chuck_Emmission * emit, a_Stmt_Return stmt );
419 t_CKBOOL emit_engine_emit_exp( Chuck_Emmission * emit, a_Exp exp );
420 t_CKBOOL emit_engine_emit_exp_binary( Chuck_Emmission * emit, a_Exp_Binary exp );
421 t_CKBOOL emit_engine_emit_exp_unary( Chuck_Emmission * emit, a_Exp_Unary exp );
422 t_CKBOOL emit_engine_emit_exp_cast( Chuck_Emmission * emit, a_Exp_Cast exp );
423 t_CKBOOL emit_engine_emit_exp_postfix( Chuck_Emmission * emit, a_Exp_Postfix exp );
424 t_CKBOOL emit_engine_emit_exp_dur( Chuck_Emmission * emit, a_Exp_Dur exp );
425 t_CKBOOL emit_engine_emit_exp_primary( Chuck_Emmission * emit, a_Exp_Primary exp );
426 t_CKBOOL emit_engine_emit_exp_array( Chuck_Emmission * emit, a_Exp_Array exp );
427 t_CKBOOL emit_engine_emit_exp_func_call( Chuck_Emmission * emit, a_Exp_Func_Call exp, t_CKBOOL spork = FALSE );
428 t_CKBOOL emit_engine_emit_exp_dot_member( Chuck_Emmission * emit, a_Exp_Dot_Member exp, t_Type t );
429 t_CKBOOL emit_engine_emit_exp_if( Chuck_Emmission * emit, a_Exp_If exp );
430 t_CKBOOL emit_engine_emit_exp_decl( Chuck_Emmission * emit, a_Exp_Decl exp );
431 t_CKBOOL emit_engine_emit_exp_namespace( Chuck_Emmission * emit, a_Exp_Namespace nspc );
432 t_CKBOOL emit_engine_emit_op( Chuck_Emmission * emit, ae_Operator op, a_Exp lhs, a_Exp rhs );
433 t_CKBOOL emit_engine_emit_chuck( Chuck_Emmission * emit, a_Exp lhs, a_Exp rhs );
434 t_CKBOOL emit_engine_emit_unchuck( Chuck_Emmission * emit, a_Exp lhs, a_Exp rhs );
435 t_CKBOOL emit_engine_emit_func_def( Chuck_Emmission * emit, a_Func_Def func_def );
436 t_CKBOOL emit_engine_emit_spork( Chuck_Emmission * emit, a_Exp_Func_Call exp );
438 t_CKBOOL emit_engine_emit_exp_mem( Chuck_Emmission * emit, a_Exp exp );
439 t_CKBOOL emit_engine_emit_exp_primary_mem( Chuck_Emmission * emit, a_Exp_Primary exp );
440 t_CKBOOL emit_engine_emit_exp_dot_member_mem( Chuck_Emmission * emit, a_Exp_Dot_Member exp );
441 t_CKBOOL emit_engine_emit_exp_array_mem( Chuck_Emmission * emit, a_Exp_Array exp );
442 t_CKBOOL emit_engine_emit_exp_func_call_mem( Chuck_Emmission * emit, a_Exp_Func_Call exp );
444 t_CKBOOL emit_engine_emit_symbol( Chuck_Emmission * emit, S_Symbol symbol,
445 t_CKBOOL offset, int linepos );
450 //-----------------------------------------------------------------------------
451 // name: emit_engine_init()
452 // desc: ...
453 //-----------------------------------------------------------------------------
454 Chuck_Emmission * emit_engine_init( t_Env env )
456 // allocate the emit
457 Chuck_Emmission * emit = new Chuck_Emmission( env );
458 if( !emit )
460 EM_error2( 0, "(emit): out of memory!" );
461 return NULL;
464 if( g_func2code == NULL )
465 g_func2code = S_empty();
467 // set the env
468 emit->global = new Chuck_Code( "__system_scope__" );
469 emit->push( "__system_scope__" );
471 // push special
472 //emit->alloc_local( insert_symbol("now"), lookup_value(env, insert_symbol("now") ) );
473 //emit->alloc_local( insert_symbol("samp"), lookup_value(env, insert_symbol("samp") ) );
474 //emit->alloc_local( insert_symbol("ms"), lookup_value(env, insert_symbol("ms") ) );
475 //emit->alloc_local( insert_symbol("second"), lookup_value(env, insert_symbol("second") ) );
476 //emit->alloc_local( insert_symbol("minute"), lookup_value(env, insert_symbol("minute") ) );
477 //emit->alloc_local( insert_symbol("hour"), lookup_value(env, insert_symbol("hour") ) );
478 //emit->alloc_local( insert_symbol("day"), lookup_value(env, insert_symbol("day") ) );
479 //emit->alloc_local( insert_symbol("week"), lookup_value(env, insert_symbol("week") ) );
480 emit->alloc_local( insert_symbol("stdout"), lookup_value(env, insert_symbol("stdout") ) );
481 emit->alloc_local( insert_symbol("stderr"), lookup_value(env, insert_symbol("stderr") ) );
482 emit->alloc_local( insert_symbol("chout"), lookup_value(env, insert_symbol("chout") ) );
483 emit->alloc_local( insert_symbol("cherr"), lookup_value(env, insert_symbol("cherr") ) );
484 emit->alloc_local( insert_symbol("midiin"), lookup_value(env, insert_symbol("midiin") ) );
485 emit->alloc_local( insert_symbol("midiout"), lookup_value(env, insert_symbol("midiout") ) );
486 //emit->alloc_local( insert_symbol("adc"), lookup_value(env, insert_symbol("adc") ) );
487 //emit->alloc_local( insert_symbol("dac"), lookup_value(env, insert_symbol("dac") ) );
489 t_CKDUR samp = 1.0;
490 t_CKDUR second = Digitalio::sampling_rate() * samp;
491 t_CKDUR ms = second / 1000.0;
492 t_CKDUR minute = second * 60.0;
493 t_CKDUR hour = minute * 60.0;
494 t_CKDUR day = hour * 24.0;
495 t_CKDUR week = day * 7.0;
497 // push dur
498 emit->alloc_dur( insert_symbol("samp"), samp );
499 emit->alloc_dur( insert_symbol("ms"), ms );
500 emit->alloc_dur( insert_symbol("second"), second );
501 emit->alloc_dur( insert_symbol("minute"), minute );
502 emit->alloc_dur( insert_symbol("hour"), hour );
503 emit->alloc_dur( insert_symbol("day"), day );
504 emit->alloc_dur( insert_symbol("week"), week );
506 emit->push( "__base_scope__" );
508 return emit;
514 //-----------------------------------------------------------------------------
515 // name: emit_engine_shutdown()
516 // desc: ...
517 //-----------------------------------------------------------------------------
518 t_CKBOOL emit_engine_shutdown( Chuck_Emmission *& emit )
520 // delete and set pointer to NULL
521 delete emit;
522 emit = NULL;
524 return TRUE;
530 //-----------------------------------------------------------------------------
531 // name: emit_engine_emit_prog()
532 // desc: emit a program
533 //-----------------------------------------------------------------------------
534 t_CKBOOL emit_engine_emit_prog( Chuck_Emmission * emit, a_Program prog )
536 t_CKBOOL ret = TRUE;
537 Chuck_Instr_Mem_Push_Imm * op = new Chuck_Instr_Mem_Push_Imm( 0 );
539 if( !prog )
540 return FALSE;
542 // emit the stack depth - we don't know this yet
543 emit->append( op );
545 while( prog && ret )
547 switch( prog->section->s_type )
549 case ae_section_stmt:
550 ret = emit_engine_emit_stmt_list( emit, prog->section->stmt_list );
551 break;
553 case ae_section_func:
554 ret = emit_engine_emit_func_def( emit, prog->section->func_def );
555 break;
557 case ae_section_class:
558 ret = FALSE;
559 break;
562 prog = prog->next;
565 // done
566 emit->append( new Chuck_Instr_EOC );
567 // set the stack depth now that we know
568 op->set( emit->stack_depth() );
570 return ret;
576 //-----------------------------------------------------------------------------
577 // name: emit_engine_emit_stmt_list()
578 // desc: emit stmt list
579 //-----------------------------------------------------------------------------
580 t_CKBOOL emit_engine_emit_stmt_list( Chuck_Emmission * emit, a_Stmt_List list )
582 t_CKBOOL ret = TRUE;
584 // emit->push();
585 while( list && ret )
587 ret = emit_engine_emit_stmt( emit, list->stmt );
588 list = list->next;
590 // emit->pop();
592 return ret;
598 //-----------------------------------------------------------------------------
599 // name: emit_engine_emit_stmt()
600 // desc: emit a stmt
601 //-----------------------------------------------------------------------------
602 t_CKBOOL emit_engine_emit_stmt( Chuck_Emmission * emit, a_Stmt stmt, t_CKBOOL pop )
604 t_CKBOOL ret = TRUE;
606 if( !stmt )
607 return TRUE;
609 switch( stmt->s_type )
611 case ae_stmt_exp:
612 // env->print( "stmt_exp" );
613 ret = emit_engine_emit_exp( emit, stmt->stmt_exp );
614 if( pop && stmt->stmt_exp->type->size > 0 )
616 if( stmt->stmt_exp->type->size == 4 || stmt->stmt_exp->s_type == ae_exp_decl )
617 emit->append( new Chuck_Instr_Reg_Pop_Word );
618 else if( stmt->stmt_exp->type->size == 8 )
619 emit->append( new Chuck_Instr_Reg_Pop_Word2 );
620 else
622 EM_error2( stmt->stmt_exp->linepos,
623 "(emit): internal error: %i byte stack item not unhandled",
624 stmt->stmt_exp->type->size );
625 return FALSE;
628 break;
630 case ae_stmt_if:
631 // env->print( "stmt_if" );
632 emit->push();
633 ret = emit_engine_emit_if( emit, &stmt->stmt_if );
634 emit->pop();
635 break;
637 case ae_stmt_for:
638 // env->print( "stmt_for" );
639 emit->push();
640 ret = emit_engine_emit_for( emit, &stmt->stmt_for );
641 emit->pop();
642 break;
644 case ae_stmt_while:
645 // env->print( "stmt_while" );
646 emit->push();
647 if( stmt->stmt_while.is_do )
648 ret = emit_engine_emit_do_while( emit, &stmt->stmt_while );
649 else
650 ret = emit_engine_emit_while( emit, &stmt->stmt_while );
651 emit->pop();
652 break;
654 case ae_stmt_until:
655 // env->print( "stmt_until" );
656 emit->push();
657 if( stmt->stmt_until.is_do )
658 ret = emit_engine_emit_do_until( emit, &stmt->stmt_until );
659 else
660 ret = emit_engine_emit_until( emit, &stmt->stmt_until );
661 emit->pop();
662 break;
664 case ae_stmt_switch:
665 // env->print( "stmt_switch" );
666 // not implemented
667 ret = FALSE;
668 break;
670 case ae_stmt_break:
671 // env->print( "break? not implemented" );
672 // ok here
673 break;
675 case ae_stmt_code:
676 // env->print( "code segment" );
677 emit->push();
678 ret = emit_engine_emit_code_segment( emit, &stmt->stmt_code );
679 emit->pop();
680 break;
682 case ae_stmt_continue:
683 // env->print( "continue" );
684 // ret = emit_engine_emit_continue( emit, &stmt->stmt_continue );
685 break;
687 case ae_stmt_return:
688 // env->print( "return" );
689 ret = emit_engine_emit_return( emit, &stmt->stmt_return );
690 break;
692 case ae_stmt_case:
693 // env->print( "case" );
694 // ret = emit_engine_emit_case( emit, &stmt->stmt_case );
695 break;
697 case ae_stmt_gotolabel:
698 // env->print( "gotolabel" );
699 // ret = emit_engine_emit_gotolabel( emit, &stmt->stmt_case );
700 break;
702 default:
703 EM_error2( stmt->linepos,
704 "(emit): internal error: unhandled statement '%i' during emission",
705 stmt->s_type );
706 break;
709 return ret;
715 //-----------------------------------------------------------------------------
716 // name: emit_engine_emit_exp()
717 // desc: emit an exp
718 //-----------------------------------------------------------------------------
719 t_CKBOOL emit_engine_emit_exp( Chuck_Emmission * emit, a_Exp exp )
721 while( exp )
723 switch( exp->s_type )
725 case ae_exp_binary:
726 if( !emit_engine_emit_exp_binary( emit, &exp->binary ) )
727 return FALSE;
728 break;
730 case ae_exp_unary:
731 if( !emit_engine_emit_exp_unary( emit, &exp->unary ) )
732 return FALSE;
733 break;
735 case ae_exp_cast:
736 if( !emit_engine_emit_exp_cast( emit, &exp->cast ) )
737 return FALSE;
738 break;
740 case ae_exp_postfix:
741 if( !emit_engine_emit_exp_postfix( emit, &exp->postfix ) )
742 return FALSE;
743 break;
745 case ae_exp_dur:
746 if( !emit_engine_emit_exp_dur( emit, &exp->dur ) )
747 return FALSE;
748 break;
750 case ae_exp_primary:
751 if( !emit_engine_emit_exp_primary( emit, &exp->primary ) )
752 return FALSE;
753 break;
755 case ae_exp_array:
756 if( !emit_engine_emit_exp_array( emit, &exp->array ) )
757 return FALSE;
758 break;
760 case ae_exp_func_call:
761 if( !emit_engine_emit_exp_func_call( emit, &exp->func_call ) )
762 return FALSE;
763 break;
765 case ae_exp_dot_member:
766 if( !emit_engine_emit_exp_dot_member( emit, &exp->dot_member, exp->type ) )
767 return FALSE;
768 break;
770 case ae_exp_if:
771 if( !emit_engine_emit_exp_if( emit, &exp->exp_if ) )
772 return FALSE;
773 break;
775 case ae_exp_decl:
776 if( !emit_engine_emit_exp_decl( emit, &exp->decl ) )
777 return FALSE;
778 break;
780 case ae_exp_namespace:
781 if( !emit_engine_emit_exp_namespace( emit, &exp->name_space ) )
782 return FALSE;
783 break;
785 default:
786 EM_error2( exp->linepos,
787 "(emit): internal error: unhandled expression '%i' in emission!",
788 exp->s_type );
789 return FALSE;
792 exp = exp->next;
795 return TRUE;
801 //-----------------------------------------------------------------------------
802 // name: emit_engine_emit_exp_binary
803 // desc: ...
804 //-----------------------------------------------------------------------------
805 t_CKBOOL emit_engine_emit_exp_binary( Chuck_Emmission * emit, a_Exp_Binary exp )
807 t_CKBOOL left = FALSE;
808 t_CKBOOL right = FALSE;
810 // hack for determining if a dot member comes first in chuck chain
811 if( exp->op == ae_op_chuck && ( exp->rhs->s_type == ae_exp_dot_member ) )
813 // set the flag
814 exp->rhs->dot_member.flag = TRUE;
817 // ^ op should be reversed for midi
818 if( exp->op == ae_op_s_xor && ( exp->lhs->type->type == te_midiin || exp->lhs->type->type == te_midiout ) )
820 right = emit_engine_emit_exp( emit, exp->rhs );
821 left = emit_engine_emit_exp( emit, exp->lhs );
823 else
825 left = emit_engine_emit_exp( emit, exp->lhs );
826 right = emit_engine_emit_exp( emit, exp->rhs );
830 // check
831 if( !left || !right )
832 return FALSE;
834 // emit the op
835 if( !emit_engine_emit_op( emit, exp->op, exp->lhs, exp->rhs ) )
836 return FALSE;
838 return TRUE;
844 //-----------------------------------------------------------------------------
845 // name: emit_engine_emit_exp_unary
846 // desc: ...
847 //-----------------------------------------------------------------------------
848 t_CKBOOL emit_engine_emit_exp_unary( Chuck_Emmission * emit, a_Exp_Unary exp )
850 if( exp->op != ae_op_spork && !emit_engine_emit_exp( emit, exp->exp ) )
851 return FALSE;
853 switch( exp->op )
855 case ae_op_plusplus:
856 if( !emit_engine_emit_exp_mem( emit, exp->exp ) )
857 return FALSE;
859 if( exp->exp->type->type == te_int )
860 emit->append( new Chuck_Instr_Inc_int );
861 else if( exp->exp->type->type == te_uint )
862 emit->append( new Chuck_Instr_Inc_uint );
863 else
865 EM_error2( exp->linepos,
866 "(emit): internal error: unhandled type '%s' for pre '++'' operator",
867 exp->exp->type->name );
868 return FALSE;
870 break;
872 case ae_op_minusminus:
873 if( !emit_engine_emit_exp_mem( emit, exp->exp ) )
874 return FALSE;
876 if( exp->exp->type->type == te_int )
877 emit->append( new Chuck_Instr_Dec_int );
878 else if( exp->exp->type->type == te_uint )
879 emit->append( new Chuck_Instr_Dec_uint );
880 else
882 EM_error2( exp->linepos,
883 "(emit): internal error: unhandled type '%s' for pre '--' operator",
884 exp->exp->type->name );
885 return FALSE;
887 break;
889 case ae_op_tilda:
890 if( exp->exp->type->type == te_int )
891 emit->append( new Chuck_Instr_Complement_int );
892 else if( exp->exp->type->type == te_uint )
893 emit->append( new Chuck_Instr_Complement_uint );
894 else
896 EM_error2( exp->linepos,
897 "(emit): internal error: unhandled type '%s' for '~' operator",
898 exp->exp->type->name );
899 return FALSE;
901 break;
903 case ae_op_exclamation:
904 if( exp->exp->type->type == te_int || exp->exp->type->type == te_uint)
905 emit->append( new Chuck_Instr_Not_int );
906 else
908 EM_error2( exp->linepos,
909 "(emit): internal error: unhandled type '%s' for '!' operator",
910 exp->exp->type->name );
911 return FALSE;
913 break;
915 case ae_op_minus:
916 if( exp->exp->type->type == te_int || exp->exp->type->type == te_uint )
917 emit->append( new Chuck_Instr_Negate_int );
918 else if( exp->exp->type->type == te_float )
919 emit->append( new Chuck_Instr_Negate_double );
920 else
922 EM_error2( exp->linepos,
923 "(emit): internal error: unhandled type '%s' for unary '-' operator",
924 exp->exp->type->name );
925 return FALSE;
927 break;
929 case ae_op_spork:
930 if( exp->exp->s_type == ae_exp_func_call )
932 if( !emit_engine_emit_spork( emit, &exp->exp->func_call ) )
933 return FALSE;
935 else
937 EM_error2( exp->linepos,
938 "(emit): internal error: sporking non-function call..." );
939 return FALSE;
941 break;
942 default:
943 EM_error2( exp->linepos,
944 "(emit): internal error: unhandled unary op '%i",
945 exp->op );
946 return FALSE;
949 return TRUE;
955 //-----------------------------------------------------------------------------
956 // name: emit_engine_emit_spork
957 // desc: ...
958 //-----------------------------------------------------------------------------
959 t_CKBOOL emit_engine_emit_spork( Chuck_Emmission * emit, a_Exp_Func_Call exp )
961 // emit the function call
962 if( !emit_engine_emit_exp_func_call( emit, exp, true ) )
963 return FALSE;
965 return TRUE;
971 //-----------------------------------------------------------------------------
972 // name: emit_engine_emit_spork
973 // desc: ...
974 //-----------------------------------------------------------------------------
975 t_CKBOOL emit_engine_emit_spork( Chuck_Emmission * emit, a_Exp exp )
977 Chuck_Emmission * emit2 = emit_engine_init( emit->env );
979 Chuck_Instr_Mem_Push_Imm * op = new Chuck_Instr_Mem_Push_Imm( 0 );
981 // emit the stack depth - we don't know this yet
982 emit2->append( op );
984 // emit the function call
985 if( !emit_engine_emit_exp( emit2, exp ) )
986 return FALSE;
988 // done
989 emit2->append( new Chuck_Instr_EOC );
990 // set the stack depth now that we know
991 op->set( emit2->stack_depth() );
993 // emit it
994 Chuck_VM_Code * code = emit_to_code( emit2 );
995 code->name = string("spork ~ exp");
996 emit->append( new Chuck_Instr_Reg_Push_Imm( (uint)code ) );
997 emit->append( new Chuck_Instr_Spork );
999 return TRUE;
1005 //-----------------------------------------------------------------------------
1006 // name: emit_get_cast_instr()
1007 // desc: ...
1008 //-----------------------------------------------------------------------------
1009 t_CKBOOL emit_get_cast_instr( Chuck_Emmission * emit, t_Type to, t_Type from )
1011 if( to->type == from->type ) return TRUE;
1013 if( to->type == te_int && from->type == te_float )
1014 emit->append( new Chuck_Instr_Cast_double2int );
1015 else if( to->type == te_float && from->type == te_int )
1016 emit->append( new Chuck_Instr_Cast_int2double );
1017 else
1019 EM_error2( 0, "(emit): internal error: no instruction for casting type '%s' to '%s'",
1020 from->name, to->name );
1021 return FALSE;
1024 return TRUE;
1030 //-----------------------------------------------------------------------------
1031 // name: emit_engine_emit_exp_cast
1032 // desc: ...
1033 //-----------------------------------------------------------------------------
1034 t_CKBOOL emit_engine_emit_exp_cast( Chuck_Emmission * emit, a_Exp_Cast exp )
1036 if( !emit_engine_emit_exp( emit, exp->exp ) )
1037 return FALSE;
1038 if( !emit_get_cast_instr( emit, lookup_type( emit->env, exp->type, TRUE ),
1039 exp->exp->type ) )
1040 return FALSE;
1042 return TRUE;
1048 //-----------------------------------------------------------------------------
1049 // name: emit_engine_emit_exp_postfix
1050 // desc: ...
1051 //-----------------------------------------------------------------------------
1052 t_CKBOOL emit_engine_emit_exp_postfix( Chuck_Emmission * emit, a_Exp_Postfix exp )
1054 // emit the exp inside
1055 if( !emit_engine_emit_exp( emit, exp->exp ) )
1056 return FALSE;
1058 switch( exp->op )
1060 case ae_op_plusplus:
1061 if( !emit_engine_emit_exp_mem( emit, exp->exp ) )
1063 EM_error2( exp->linepos,
1064 "(emit): internal error: emitting [mem] exp from postfix..." );
1065 return FALSE;
1068 if( exp->exp->type->type == te_int )
1069 emit->append( new Chuck_Instr_Inc_int );
1070 else if( exp->exp->type->type == te_uint )
1071 emit->append( new Chuck_Instr_Inc_uint );
1072 else
1074 EM_error2( exp->linepos,
1075 "(emit): internal error: unhandled type '%s' for post '++' operator",
1076 exp->exp->type->name );
1077 return FALSE;
1079 break;
1081 case ae_op_minusminus:
1082 if( !emit_engine_emit_exp_mem( emit, exp->exp ) )
1084 EM_error2( exp->linepos,
1085 "(emit): internal error: emitting [mem] exp from postfix..." );
1086 return FALSE;
1089 if( exp->exp->type->type == te_int )
1090 emit->append( new Chuck_Instr_Dec_int );
1091 else if( exp->exp->type->type == te_uint )
1092 emit->append( new Chuck_Instr_Dec_uint );
1093 else
1095 EM_error2( exp->linepos,
1096 "(emit): internal error: unhandled type '%s' for post '--' operator",
1097 exp->exp->type->name );
1098 return FALSE;
1100 break;
1102 default:
1103 EM_error2( exp->linepos,
1104 "(emit): internal error: unhandled postfix operator '%i'",
1105 exp->op );
1106 return FALSE;
1109 return TRUE;
1115 //-----------------------------------------------------------------------------
1116 // name: emit_engine_emit_exp_dur
1117 // desc: ...
1118 //-----------------------------------------------------------------------------
1119 t_CKBOOL emit_engine_emit_exp_dur( Chuck_Emmission * emit, a_Exp_Dur exp )
1121 if( !emit_engine_emit_exp( emit, exp->base ) )
1122 return FALSE;
1124 // cast
1125 if( exp->base->type->type == te_int )
1126 emit->append( new Chuck_Instr_Cast_int2double );
1128 if( !emit_engine_emit_exp( emit, exp->unit ) )
1129 return FALSE;
1131 // multiply
1132 emit->append( new Chuck_Instr_Times_double );
1134 return TRUE;
1140 //-----------------------------------------------------------------------------
1141 // name: emit_engine_emit_symbol
1142 // desc: ...
1143 //-----------------------------------------------------------------------------
1144 t_CKBOOL emit_engine_emit_symbol( Chuck_Emmission * emit, S_Symbol id,
1145 t_CKBOOL off, int linepos )
1147 t_CKUINT is_global = FALSE;
1148 t_CKUINT size = 0;
1149 int offset = off ? emit->find_offset( id, &is_global, &size ) : -1;
1150 if( offset < 0 )
1152 // could be a function
1153 t_Type t = lookup_value( emit->nspc, id );
1154 if( t && t->type == te_function )
1156 a_Func_Def func = lookup_func( emit->nspc, id, FALSE );
1157 if( !func || ( func && func->s_type == ae_func_user ) )
1159 Func_Link * f = (Func_Link *)checked_malloc( sizeof( Func_Link ) );
1160 f->name = id;
1161 emit->append( f->op = new Chuck_Instr_Reg_Push_Imm( 0 ) );
1162 g_func_links.push_back( f );
1164 else // func && func->s_type == ae_func_builtin
1166 emit->nspc_func = func;
1167 emit->append( new Chuck_Instr_Reg_Push_Imm( func->stack_depth ) );
1168 emit->append( new Chuck_Instr_Reg_Push_Imm(
1169 (uint)func->builtin ) );
1172 else if( t && t->type == __te_system_namespace__ )
1174 // find the namespace
1175 emit->nspc = lookup_namespace( emit->env, id, FALSE );
1176 if( !emit->nspc )
1178 EM_error2( linepos,
1179 "(emit): internal error: cannot find namespace '%s'",
1180 S_name(id) );
1181 return FALSE;
1184 else if( t && t->type == __te_system_class__ )
1186 // error
1187 EM_error2( linepos,
1188 "(emit): internal error: class/lookup not impl" );
1189 return FALSE;
1191 else if( emit->nspc && ( t = lookup_value( emit->nspc, id, FALSE ) ) )
1193 void * addr = lookup_addr( emit->nspc, id, FALSE );
1194 if( !addr )
1196 EM_error2( linepos,
1197 "(emit): internal error looking up addr for '%s.%s'",
1198 "[namespace]", S_name(id) );
1199 return FALSE;
1202 // push the addr
1203 if( t->size == 4 || t->size == 8 )
1204 emit->append( new Chuck_Instr_Reg_Push_Deref( (uint)addr, t->size ) );
1205 else
1207 EM_error2( linepos,
1208 "(emit): internal error resolving '%s.%s'",
1209 "[namespace]", S_name(id) );
1210 return FALSE;
1213 else
1215 // error
1216 EM_error2( linepos,
1217 "(emit): internal error resolving var '%s'",
1218 S_name(id) );
1219 return FALSE;
1222 else
1224 if( emit->is_global || !is_global )
1226 if( size == 4 )
1227 emit->append( new Chuck_Instr_Reg_Push_Mem( offset ) );
1228 else if( size == 8 )
1229 emit->append( new Chuck_Instr_Reg_Push_Mem2( offset ) );
1230 else
1232 EM_error2( linepos,
1233 "(emit): internal error with reg push %i",
1234 size );
1235 return FALSE;
1238 else // local and global
1240 Chuck_Instr_Unary_Op * op = NULL;
1241 // the offset is not set yet
1242 emit->append( op = new Chuck_Instr_Reg_Push_Deref( offset, size ) );
1243 // queue for addr translation later
1244 emit->addr_map.push_back( op );
1248 return TRUE;
1254 //-----------------------------------------------------------------------------
1255 // name: emit_engine_emit_exp_primary
1256 // desc: ...
1257 //-----------------------------------------------------------------------------
1258 t_CKBOOL emit_engine_emit_exp_primary( Chuck_Emmission * emit, a_Exp_Primary exp )
1260 uint temp;
1261 t_CKDUR dur;
1262 Chuck_Instr_Unary_Op * op = NULL, * op2 = NULL;
1264 switch( exp->s_type )
1266 case ae_primary_var:
1267 if( exp->var == insert_symbol( "now" ) )
1269 emit->append( new Chuck_Instr_Reg_Push_Now );
1271 else if( exp->var == insert_symbol( "start" ) )
1273 emit->append( new Chuck_Instr_Reg_Push_Start );
1275 else if( exp->var == insert_symbol( "midiin" ) )
1277 if( emit->get_op() )
1279 EM_error2( exp->linepos,
1280 "MIDI in should be drained by using => before invoking again" );
1281 return FALSE;
1284 emit->append( op = new Chuck_Instr_Midi_In(0) );
1285 emit->append( op2 = new Chuck_Instr_Midi_In_Go(0) );
1286 emit->push_op( op2 );
1287 emit->push_op( op );
1289 else if( exp->var == insert_symbol( "midiout" ) )
1291 if( emit->get_op() )
1293 EM_error2( exp->linepos,
1294 "MIDI out should be drained by using => before invoking again" );
1295 return FALSE;
1298 emit->append( op = new Chuck_Instr_Midi_Out(0) );
1299 emit->append( op2 = new Chuck_Instr_Midi_Out_Go(0) );
1300 emit->push_op( op2 );
1301 emit->push_op( op );
1303 else if( exp->var == insert_symbol( "dac" ) )
1305 emit->append( new Chuck_Instr_DAC );
1307 else if( exp->var == insert_symbol( "adc" ) )
1309 emit->append( new Chuck_Instr_ADC );
1311 else if( exp->var == insert_symbol( "bunghole" ) )
1313 emit->append( new Chuck_Instr_Bunghole );
1315 else if( exp->var == insert_symbol( "blackhole" ) )
1317 emit->append( new Chuck_Instr_Bunghole );
1319 else if( exp->var == insert_symbol( "true" ) )
1321 emit->append( new Chuck_Instr_Reg_Push_Imm( 1 ) );
1323 else if( exp->var == insert_symbol( "false" ) )
1325 emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
1327 else if( exp->var == insert_symbol("maybe") )
1329 emit->append( new Chuck_Instr_Reg_Push_Maybe() );
1331 else if( exp->var == insert_symbol( "pi" ) )
1333 double pi = 3.14159265358979323846;
1334 emit->append( new Chuck_Instr_Reg_Push_Imm2( pi ) );
1336 else if( exp->var == insert_symbol( "endl" ) )
1338 emit->append( new Chuck_Instr_Reg_Push_Imm( (uint)"\n" ) );
1340 else if( exp->var == insert_symbol( "stdout" ) ||
1341 exp->var == insert_symbol( "chout" ) )
1343 emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
1345 else if( emit->find_dur( exp->var, &dur ) )
1347 emit->append( new Chuck_Instr_Reg_Push_Imm2( dur ) );
1349 else
1351 // emit the symbol
1352 return emit_engine_emit_symbol( emit, exp->var, TRUE, exp->linepos );
1354 break;
1356 case ae_primary_num:
1357 memcpy( &temp, &exp->num, sizeof(temp) );
1358 emit->append( new Chuck_Instr_Reg_Push_Imm( temp ) );
1359 break;
1361 case ae_primary_uint:
1362 emit->append( new Chuck_Instr_Reg_Push_Imm( exp->num2 ) );
1363 break;
1365 case ae_primary_float:
1366 emit->append( new Chuck_Instr_Reg_Push_Imm2( exp->fnum ) );
1367 break;
1369 case ae_primary_str:
1370 temp = (uint)exp->str;
1371 emit->append( new Chuck_Instr_Reg_Push_Imm( temp ) );
1372 break;
1374 case ae_primary_exp:
1375 emit_engine_emit_exp( emit, exp->exp );
1376 break;
1379 return TRUE;
1385 //-----------------------------------------------------------------------------
1386 // name: emit_engine_emit_exp_array
1387 // desc: ...
1388 //-----------------------------------------------------------------------------
1389 t_CKBOOL emit_engine_emit_exp_array( Chuck_Emmission * emit, a_Exp_Array exp )
1391 return TRUE;
1397 //-----------------------------------------------------------------------------
1398 // name: emit_engine_emit_exp_func_call
1399 // desc: ...
1400 //-----------------------------------------------------------------------------
1401 t_CKBOOL emit_engine_emit_exp_func_call( Chuck_Emmission * emit, a_Exp_Func_Call exp,
1402 t_CKBOOL spork )
1404 if( exp->args )
1406 // emit the args
1407 if( !emit_engine_emit_exp( emit, exp->args ) )
1409 EM_error2( exp->linepos,
1410 "(emit): internal error in emitting function call arguments..." );
1411 return FALSE;
1415 // spork
1416 Chuck_Emmission * emit_save = emit;
1417 Chuck_Instr_Mem_Push_Imm * op = NULL;
1418 if( spork )
1420 emit = emit_engine_init( emit->env );
1421 op = new Chuck_Instr_Mem_Push_Imm( 0 );
1422 // emit the stack depth - we don't know this yet
1423 emit->append( op );
1426 // emit func
1427 if( !emit_engine_emit_exp( emit, exp->func ) )
1429 EM_error2( exp->linepos,
1430 "(emit): internal error in evaluating function call..." );
1431 return FALSE;
1434 // push the local stack depth
1435 emit->append( new Chuck_Instr_Reg_Push_Imm( emit->stack_depth() ) );
1437 // call the function
1438 if( emit->nspc_func && emit->nspc_func->s_type == ae_func_builtin )
1440 if( exp->ret_type->size == 0 )
1441 emit->append( new Chuck_Instr_Func_Call0 );
1442 else if( exp->ret_type->size == 4 )
1443 emit->append( new Chuck_Instr_Func_Call2 );
1444 else if( exp->ret_type->size == 8 )
1445 emit->append( new Chuck_Instr_Func_Call3 );
1446 else
1448 EM_error2( exp->linepos,
1449 "(emit): internal error: %i func call not handled",
1450 exp->ret_type->size );
1451 return FALSE;
1454 else
1456 Chuck_Instr * op = new Chuck_Instr_Func_Call;
1457 emit->append( op );
1460 // spork
1461 if( spork )
1463 // done
1464 emit->append( new Chuck_Instr_EOC );
1465 // set the stack depth now that we know
1466 op->set( emit->stack_depth() );
1468 // emit it
1469 Chuck_VM_Code * code = emit_to_code( emit );
1470 code->name = string("spork ~ exp");
1471 emit = emit_save;
1473 a_Exp e = exp->args;
1474 t_CKUINT size = 0;
1475 while( e ) { size += e->type->size; e=e->next; }
1476 emit->append( new Chuck_Instr_Reg_Push_Imm( (uint)code ) );
1477 emit->append( new Chuck_Instr_Spork( size ) );
1480 // reset the emit
1481 emit->nspc = emit->env;
1482 emit->nspc_func = NULL;
1484 return TRUE;
1490 //-----------------------------------------------------------------------------
1491 // name: emit_engine_emit_exp_dot_member
1492 // desc: ...
1493 //-----------------------------------------------------------------------------
1494 t_CKBOOL emit_engine_emit_exp_dot_member( Chuck_Emmission * emit, a_Exp_Dot_Member exp, t_Type t )
1496 t_Type t_base = exp->base->type;
1497 t_Env e = NULL;
1499 // namespace or class
1500 if( t_base->type == __te_system_namespace__ )
1502 // emit the base
1503 emit_engine_emit_exp( emit, exp->base );
1504 // emit the member
1505 emit_engine_emit_symbol( emit, exp->id, FALSE, exp->linepos );
1507 else if( isa( t_base, lookup_type( emit->env, insert_symbol( "ugen" ) ) ) )
1509 // emit the base
1510 emit_engine_emit_exp( emit, exp->base );
1511 // emit the member
1512 //if( !exp->data )
1514 // EM_error2( exp->linepos,
1515 // "(emit): internal error: no ctrl for '%s.%s'",
1516 // t_base->name, S_name(exp->id) );
1517 // return FALSE;
1519 // push the addr
1520 //emit->append( new Chuck_Instr_Reg_Push_Imm( exp->data ) );
1522 // cget
1523 if( exp->flag == 0 )
1525 if( exp->data2 == 0 )
1527 EM_error2( exp->linepos,
1528 "(emit): internal error: cannot read from ugen parameter '%s.%s', it is write-only",
1529 t_base->name, S_name(exp->id) );
1530 return FALSE;
1533 // the cget function addr
1534 emit->append( new Chuck_Instr_Reg_Push_Imm( exp->data2 ) );
1536 // the ugen
1537 if( !strcmp( S_name(exp->id), "op" ) )
1538 emit->append( new Chuck_Instr_UGen_CGet_Op );
1539 else if( !strcmp( S_name(exp->id), "gain" ) )
1540 emit->append( new Chuck_Instr_UGen_CGet_Gain );
1541 else if( !strcmp( S_name(exp->id), "last" ) )
1542 emit->append( new Chuck_Instr_UGen_CGet_Last );
1543 else
1545 // cget passing to ugen
1546 if( t->size == 4 )
1547 emit->append( new Chuck_Instr_UGen_CGet );
1548 else if( t->size == 8 )
1549 emit->append( new Chuck_Instr_UGen_CGet2 );
1550 else
1552 EM_error2( exp->linepos,
1553 "(emit): internal error: %i ugen cget not handled",
1554 t->size );
1555 return FALSE;
1560 else
1562 EM_error2( exp->linepos,
1563 "(emit): internal error: class.member not impl" );
1564 return FALSE;
1567 return TRUE;
1573 //-----------------------------------------------------------------------------
1574 // name: emit_engine_emit_exp_if
1575 // desc: ...
1576 //-----------------------------------------------------------------------------
1577 t_CKBOOL emit_engine_emit_exp_if( Chuck_Emmission * emit, a_Exp_If exp )
1579 return TRUE;
1585 //-----------------------------------------------------------------------------
1586 // name: emit_engine_emit_exp_decl
1587 // desc: ...
1588 //-----------------------------------------------------------------------------
1589 t_CKBOOL emit_engine_emit_exp_decl( Chuck_Emmission * emit, a_Exp_Decl exp )
1591 a_Var_Decl_List list = exp->var_decl_list;
1592 a_Var_Decl var_decl = NULL;
1594 while( list )
1596 var_decl = list->var_decl;
1597 t_Type type = lookup_type( emit->env, exp->type );
1599 if( var_decl->isarray )
1601 EM_error2( exp->linepos,
1602 "(emit): internal error: array not impl" );
1603 return FALSE;
1605 else
1607 // offset
1608 emit->append( new Chuck_Instr_Reg_Push_Imm(
1609 emit->alloc_local( var_decl->id, type ) ) );
1611 // ugen
1612 if( isa( type, lookup_type(emit->env, insert_symbol("ugen")) ) )
1614 Chuck_UGen_Info * info = lookup_ugen( emit->nspc, exp->type );
1615 if( !info )
1617 EM_error2( exp->linepos,
1618 "(emit): internal error: undefined ugen type '%s'",
1619 S_name(var_decl->id) );
1620 return FALSE;
1622 emit->append( new Chuck_Instr_Reg_Push_Imm( (uint)info ) );
1623 emit->append( new Chuck_Instr_UGen_Alloc() );
1624 emit->append( new Chuck_Instr_Chuck_Assign_Object2 );
1628 list = list->next;
1631 return TRUE;
1637 //-----------------------------------------------------------------------------
1638 // name: emit_engine_emit_exp_namespace()
1639 // desc: ...
1640 //-----------------------------------------------------------------------------
1641 t_CKBOOL emit_engine_emit_exp_namespace( Chuck_Emmission * emit, a_Exp_Namespace exp )
1643 // push the name
1644 emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)S_name(exp->name) ) );
1645 return TRUE;
1651 //-----------------------------------------------------------------------------
1652 // name: emit_engine_emit_op()
1653 // desc: emit op
1654 //-----------------------------------------------------------------------------
1655 t_CKBOOL emit_engine_emit_op( Chuck_Emmission * emit,
1656 ae_Operator op, a_Exp lhs, a_Exp rhs )
1658 te_Type left = lhs->type->type;
1659 te_Type right = rhs->type->type;
1661 switch( op )
1664 // ----------------------------- num --------------------------------------
1666 case ae_op_plus:
1667 if( ( left == te_dur && right == te_time ) ||
1668 ( left == te_time && right == te_dur ) )
1669 emit->append( new Chuck_Instr_Add_double );
1670 else
1672 switch( left )
1674 case te_int:
1675 emit->append( new Chuck_Instr_Add_int );
1676 break;
1677 case te_uint:
1678 emit->append( new Chuck_Instr_Add_uint );
1679 break;
1680 case te_float:
1681 emit->append( new Chuck_Instr_Add_double );
1682 break;
1683 case te_dur:
1684 emit->append( new Chuck_Instr_Add_double );
1685 break;
1687 default:
1688 EM_error2( lhs->linepos,
1689 "(emit): internal error: unhandled type '%i' in binary op '+'",
1690 left );
1691 return FALSE;
1694 break;
1696 case ae_op_minus:
1697 if( ( left == te_time && right == te_dur ) )
1698 emit->append( new Chuck_Instr_Minus_double );
1699 else if( ( left == te_time && right == te_time ) ) // XXX time - time = dur
1700 emit->append( new Chuck_Instr_Minus_double );
1701 else
1703 switch( left )
1705 case te_int:
1706 emit->append( new Chuck_Instr_Minus_int );
1707 break;
1708 case te_uint:
1709 emit->append( new Chuck_Instr_Minus_uint );
1710 break;
1711 case te_float:
1712 emit->append( new Chuck_Instr_Minus_double );
1713 break;
1714 case te_dur:
1715 emit->append( new Chuck_Instr_Minus_double );
1716 break;
1718 default:
1719 EM_error2( lhs->linepos,
1720 "(emit): internal error: unhandled '%i' in binary op '-'",
1721 left );
1722 return FALSE;
1725 break;
1727 case ae_op_times:
1728 switch( left )
1730 case te_int:
1731 emit->append( new Chuck_Instr_Times_int );
1732 break;
1733 case te_uint:
1734 emit->append( new Chuck_Instr_Times_uint );
1735 break;
1736 case te_float:
1737 emit->append( new Chuck_Instr_Times_double );
1738 break;
1739 case te_dur:
1740 emit->append( new Chuck_Instr_Times_double );
1741 break;
1743 default:
1744 EM_error2( lhs->linepos,
1745 "(emit): internal error: unhandled type '%i' in binary op '*'",
1746 left );
1747 return FALSE;
1749 break;
1751 case ae_op_divide:
1752 switch( left )
1754 case te_int:
1755 emit->append( new Chuck_Instr_Divide_int );
1756 break;
1757 case te_uint:
1758 emit->append( new Chuck_Instr_Divide_uint );
1759 break;
1760 case te_float:
1761 emit->append( new Chuck_Instr_Divide_double );
1762 break;
1763 case te_dur:
1764 emit->append( new Chuck_Instr_Divide_double );
1765 break;
1767 default:
1768 EM_error2( lhs->linepos,
1769 "(emit): internal error: unhandled type '%i' in binary op '/'",
1770 left );
1771 return FALSE;
1773 break;
1775 case ae_op_s_or:
1776 switch( left )
1778 case te_int:
1779 case te_uint:
1780 emit->append( new Chuck_Instr_Binary_Or );
1781 break;
1783 default:
1784 EM_error2( lhs->linepos,
1785 "(emit): internal error: unhandled type '%i' in binary op '|'",
1786 left );
1787 return FALSE;
1789 break;
1791 case ae_op_s_and:
1792 switch( left )
1794 case te_int:
1795 case te_uint:
1796 emit->append( new Chuck_Instr_Binary_And );
1797 break;
1799 default:
1800 EM_error2( lhs->linepos,
1801 "(emit): internal error: unhandled type '%i' in binary op '&'",
1802 left );
1803 return FALSE;
1805 break;
1807 case ae_op_shift_left:
1808 switch( left )
1810 case te_int:
1811 case te_uint:
1812 emit->append( new Chuck_Instr_Binary_Shift_Left );
1813 break;
1815 default:
1816 EM_error2( lhs->linepos,
1817 "(emit): internal error: unhandled type '%i' in binary op '<<'",
1818 left );
1819 return FALSE;
1821 break;
1823 case ae_op_shift_right:
1824 switch( left )
1826 case te_int:
1827 case te_uint:
1828 emit->append( new Chuck_Instr_Binary_Shift_Right );
1829 break;
1831 default:
1832 EM_error2( lhs->linepos,
1833 "(emit): internal error: unhandled type '%i' in binary op '>>'",
1834 left );
1835 return FALSE;
1837 break;
1839 case ae_op_percent:
1840 switch( left )
1842 case te_int:
1843 emit->append( new Chuck_Instr_Mod_int );
1844 break;
1845 case te_uint:
1846 emit->append( new Chuck_Instr_Mod_uint );
1847 break;
1848 case te_float:
1849 case te_time:
1850 case te_dur:
1851 emit->append( new Chuck_Instr_Mod_double );
1852 break;
1854 default:
1855 EM_error2( lhs->linepos,
1856 "(emit): internal error: unhandled type '%i' in binary op '%%'",
1857 left );
1858 return FALSE;
1860 break;
1862 case ae_op_s_xor:
1863 switch( left )
1865 case te_int:
1866 case te_uint:
1867 emit->append( new Chuck_Instr_Binary_Xor );
1868 break;
1869 case te_midiin:
1871 Chuck_Instr_Unary_Op * op = emit->get_op();
1872 if( !op )
1874 EM_error2( lhs->linepos,
1875 "(emit): internal error: in binary op '%i'", left );
1876 return FALSE;
1878 op->set( op->get() | 1 );
1879 // emit->append_ops();
1881 break;
1882 case te_midiout:
1884 Chuck_Instr_Unary_Op * op = emit->get_op();
1885 if( !op )
1887 EM_error2( lhs->linepos,
1888 "(emit): internal error: in binary op '%i'", left );
1889 return FALSE;
1891 op->set( op->get() | 1 );
1892 // emit->append_ops();
1894 break;
1895 default:
1896 EM_error2( lhs->linepos,
1897 "(emit): internal error: unhandled type '%i' in binary op '^'",
1898 left );
1899 return FALSE;
1901 break;
1903 // ----------------------------- chuck -------------------------------------
1905 case ae_op_chuck:
1907 a_Exp cl = lhs, cr = rhs;
1909 while( cr )
1911 cl = lhs;
1912 while( cl )
1914 if( !emit_engine_emit_chuck( emit, cl, cr ) )
1915 return FALSE;
1916 cl = cl->next;
1919 cr = cr->next;
1921 break;
1924 case ae_op_unchuck:
1926 a_Exp cl = lhs, cr = rhs;
1928 while( cr )
1930 cl = lhs;
1931 while( cl )
1933 if( !emit_engine_emit_unchuck( emit, cl, cr ) )
1934 return FALSE;
1935 cl = cl->next;
1938 cr = cr->next;
1940 break;
1943 case ae_op_at_chuck:
1944 break;
1946 case ae_op_s_chuck:
1947 break;
1949 case ae_op_plus_chuck:
1950 break;
1952 case ae_op_minus_chuck:
1953 break;
1955 case ae_op_times_chuck:
1956 break;
1958 case ae_op_divide_chuck:
1959 break;
1961 case ae_op_s_and_chuck:
1962 break;
1964 case ae_op_s_or_chuck:
1965 break;
1967 case ae_op_s_xor_chuck:
1968 break;
1970 case ae_op_shift_right_chuck:
1971 break;
1973 case ae_op_shift_left_chuck:
1974 break;
1976 case ae_op_percent_chuck:
1977 break;
1979 // -------------------------------- bool -----------------------------------
1981 case ae_op_eq:
1982 switch( left )
1984 case te_int:
1985 emit->append( new Chuck_Instr_Eq_int );
1986 break;
1987 case te_uint:
1988 emit->append( new Chuck_Instr_Eq_uint );
1989 break;
1990 case te_float:
1991 emit->append( new Chuck_Instr_Eq_double );
1992 break;
1993 case te_dur:
1994 emit->append( new Chuck_Instr_Eq_double );
1995 break;
1996 case te_time:
1997 emit->append( new Chuck_Instr_Eq_double );
1998 break;
2000 default:
2001 EM_error2( lhs->linepos,
2002 "(emit): internal error: unhandled type '%i' in binary op '=='",
2003 left );
2004 return FALSE;
2006 break;
2008 case ae_op_neq:
2009 switch( left )
2011 case te_int:
2012 emit->append( new Chuck_Instr_Neq_int );
2013 break;
2014 case te_uint:
2015 emit->append( new Chuck_Instr_Neq_uint );
2016 break;
2017 case te_float:
2018 emit->append( new Chuck_Instr_Neq_double );
2019 break;
2020 case te_dur:
2021 emit->append( new Chuck_Instr_Neq_double );
2022 break;
2023 case te_time:
2024 emit->append( new Chuck_Instr_Neq_double );
2025 break;
2027 default:
2028 EM_error2( lhs->linepos,
2029 "(emit): internal error: unhandled type '%i' in binary op '!='",
2030 left );
2031 return FALSE;
2033 break;
2035 case ae_op_lt:
2036 switch( left )
2038 case te_int:
2039 emit->append( new Chuck_Instr_Lt_int );
2040 break;
2041 case te_uint:
2042 emit->append( new Chuck_Instr_Lt_uint );
2043 break;
2044 case te_float:
2045 emit->append( new Chuck_Instr_Lt_double );
2046 break;
2047 case te_dur:
2048 emit->append( new Chuck_Instr_Lt_double );
2049 break;
2050 case te_time:
2051 emit->append( new Chuck_Instr_Lt_double );
2052 break;
2054 default:
2055 EM_error2( lhs->linepos,
2056 "(emit): internal error: unhandled type '%i' in binary op '<'",
2057 left );
2058 return FALSE;
2060 break;
2062 case ae_op_le:
2063 switch( left )
2065 case te_int:
2066 emit->append( new Chuck_Instr_Le_int );
2067 break;
2068 case te_uint:
2069 emit->append( new Chuck_Instr_Le_uint );
2070 break;
2071 case te_float:
2072 emit->append( new Chuck_Instr_Le_double );
2073 break;
2074 case te_dur:
2075 emit->append( new Chuck_Instr_Le_double );
2076 break;
2077 case te_time:
2078 emit->append( new Chuck_Instr_Le_double );
2079 break;
2081 default:
2082 EM_error2( lhs->linepos,
2083 "(emit): internal error: unhandled type '%i' in binary op '<='",
2084 left );
2085 return FALSE;
2087 break;
2089 case ae_op_gt:
2090 switch( left )
2092 case te_int:
2093 emit->append( new Chuck_Instr_Gt_int );
2094 break;
2095 case te_uint:
2096 emit->append( new Chuck_Instr_Gt_uint );
2097 break;
2098 case te_float:
2099 emit->append( new Chuck_Instr_Gt_double );
2100 break;
2101 case te_dur:
2102 emit->append( new Chuck_Instr_Gt_double );
2103 break;
2104 case te_time:
2105 emit->append( new Chuck_Instr_Gt_double );
2106 break;
2108 default:
2109 EM_error2( lhs->linepos,
2110 "(emit): internal error: unhandled type '%i' in binary op '>='",
2111 left );
2112 return FALSE;
2114 break;
2116 case ae_op_ge:
2117 switch( left )
2119 case te_int:
2120 emit->append( new Chuck_Instr_Ge_int );
2121 break;
2122 case te_uint:
2123 emit->append( new Chuck_Instr_Ge_uint );
2124 break;
2125 case te_float:
2126 emit->append( new Chuck_Instr_Ge_double );
2127 break;
2128 case te_dur:
2129 emit->append( new Chuck_Instr_Ge_double );
2130 break;
2131 case te_time:
2132 emit->append( new Chuck_Instr_Ge_double );
2133 break;
2135 default:
2136 EM_error2( lhs->linepos,
2137 "(emit): internal error: unhandled type '%i' in binary op '>='",
2138 left );
2139 return FALSE;
2141 break;
2143 case ae_op_and:
2144 switch( left )
2146 case te_int:
2147 case te_uint:
2148 //case te_float:
2149 //case te_dur:
2150 //case te_time:
2151 emit->append( new Chuck_Instr_And );
2152 break;
2154 default:
2155 EM_error2( lhs->linepos,
2156 "(emit): internal error: unhandled type '%i' in binary op '&&'",
2157 left );
2158 return FALSE;
2160 break;
2162 case ae_op_or:
2163 switch( left )
2165 case te_int:
2166 case te_uint:
2167 //case te_float:
2168 //case te_dur:
2169 //case te_time:
2170 emit->append( new Chuck_Instr_Or );
2171 break;
2173 default:
2174 EM_error2( lhs->linepos,
2175 "(emit): internal error: unhandled type '%i' in binary op '||'",
2176 left );
2177 return FALSE;
2179 break;
2181 default:
2182 EM_error2( lhs->linepos,
2183 "(emit): internal error: op '%i' not handled",
2184 op );
2185 return FALSE;
2188 return TRUE;
2194 //------------------------------------------------------------------------------
2195 // name: emit_engine_emit_while()
2196 // desc: ...
2197 //------------------------------------------------------------------------------
2198 t_CKBOOL emit_engine_emit_while( Chuck_Emmission * emit, a_Stmt_While stmt )
2200 t_CKBOOL ret = TRUE;
2201 Chuck_Instr_Branch_Op * op = NULL;
2202 uint start_index = emit->next_index();
2204 // emit the cond
2205 emit_engine_emit_exp( emit, stmt->cond );
2207 switch( stmt->cond->type->type )
2209 case te_int:
2210 case te_uint:
2211 // push 0
2212 emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
2213 op = new Chuck_Instr_Branch_Eq_uint( 0 );
2214 break;
2215 case te_float:
2216 case te_dur:
2217 case te_time:
2218 // push 0
2219 emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) );
2220 op = new Chuck_Instr_Branch_Eq_double( 0 );
2221 break;
2223 default:
2224 EM_error2( stmt->cond->linepos,
2225 "(emit): internal error: unhandled type '%s' in while conditional",
2226 stmt->cond->type->name );
2227 return FALSE;
2230 // append the op
2231 emit->append( op );
2233 // emit the body
2234 emit_engine_emit_stmt( emit, stmt->body );
2236 // go back to do check the condition
2237 emit->append( new Chuck_Instr_Goto( start_index ) );
2239 // set the op's target
2240 op->set( emit->next_index() );
2242 return ret;
2248 //------------------------------------------------------------------------------
2249 // name: emit_engine_emit_do_while()
2250 // desc: ...
2251 //------------------------------------------------------------------------------
2252 t_CKBOOL emit_engine_emit_do_while( Chuck_Emmission * emit, a_Stmt_While stmt )
2254 t_CKBOOL ret = TRUE;
2255 Chuck_Instr_Branch_Op * op = NULL;
2256 uint start_index = emit->next_index();
2258 // emit the body
2259 emit_engine_emit_stmt( emit, stmt->body );
2261 // emit the cond
2262 emit_engine_emit_exp( emit, stmt->cond );
2264 switch( stmt->cond->type->type )
2266 case te_int:
2267 case te_uint:
2268 // push 0
2269 emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
2270 op = new Chuck_Instr_Branch_Neq_uint( 0 );
2271 break;
2272 case te_float:
2273 case te_dur:
2274 case te_time:
2275 // push 0
2276 emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) );
2277 op = new Chuck_Instr_Branch_Neq_double( 0 );
2278 break;
2280 default:
2281 EM_error2( stmt->cond->linepos,
2282 "(emit): internal error: unhandled type '%s' in do/while conditional",
2283 stmt->cond->type->name );
2284 return FALSE;
2287 // append the op
2288 emit->append( op );
2290 // set the op's target
2291 op->set( start_index );
2293 return ret;
2299 //------------------------------------------------------------------------------
2300 // name: emit_engine_emit_until()
2301 // desc: ...
2302 //------------------------------------------------------------------------------
2303 t_CKBOOL emit_engine_emit_until( Chuck_Emmission * emit, a_Stmt_Until stmt )
2305 t_CKBOOL ret = TRUE;
2306 Chuck_Instr_Branch_Op * op = NULL;
2307 uint start_index = emit->next_index();
2309 // emit the cond
2310 emit_engine_emit_exp( emit, stmt->cond );
2312 switch( stmt->cond->type->type )
2314 case te_int:
2315 case te_uint:
2316 // push 0
2317 emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
2318 op = new Chuck_Instr_Branch_Neq_uint( 0 );
2319 break;
2320 case te_float:
2321 case te_dur:
2322 case te_time:
2323 // push 0
2324 emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) );
2325 op = new Chuck_Instr_Branch_Neq_double( 0 );
2326 break;
2328 default:
2329 EM_error2( stmt->cond->linepos,
2330 "(emit): internal error: unhandled type '%s' in until conditional",
2331 stmt->cond->type->name );
2332 return FALSE;
2335 // append the op
2336 emit->append( op );
2338 // emit the body
2339 emit_engine_emit_stmt( emit, stmt->body );
2341 // go back to do check the condition
2342 emit->append( new Chuck_Instr_Goto( start_index ) );
2344 // set the op's target
2345 op->set( emit->next_index() );
2347 return ret;
2353 //------------------------------------------------------------------------------
2354 // name: emit_engine_emit_do_until()
2355 // desc: ...
2356 //------------------------------------------------------------------------------
2357 t_CKBOOL emit_engine_emit_do_until( Chuck_Emmission * emit, a_Stmt_Until stmt )
2359 t_CKBOOL ret = TRUE;
2360 Chuck_Instr_Branch_Op * op = NULL;
2361 uint start_index = emit->next_index();
2363 // emit the body
2364 emit_engine_emit_stmt( emit, stmt->body );
2366 // emit the cond
2367 emit_engine_emit_exp( emit, stmt->cond );
2369 switch( stmt->cond->type->type )
2371 case te_int:
2372 case te_uint:
2373 // push 0
2374 emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
2375 op = new Chuck_Instr_Branch_Eq_uint( 0 );
2376 break;
2377 case te_float:
2378 case te_dur:
2379 case te_time:
2380 // push 0
2381 emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) );
2382 op = new Chuck_Instr_Branch_Eq_double( 0 );
2383 break;
2385 default:
2386 EM_error2( stmt->cond->linepos,
2387 "(emit): internal error: unhandled type '%s' in do/until conditional",
2388 stmt->cond->type->name );
2389 return FALSE;
2392 // append the op
2393 emit->append( op );
2395 // set the op's target
2396 op->set( start_index );
2398 return ret;
2404 //------------------------------------------------------------------------------
2405 // name: emit_engine_emit_for()
2406 // desc: ...
2407 //------------------------------------------------------------------------------
2408 t_CKBOOL emit_engine_emit_for( Chuck_Emmission * emit, a_Stmt_For stmt )
2410 t_CKBOOL ret = TRUE;
2411 Chuck_Instr_Branch_Op * op = NULL;
2413 // emit the cond
2414 emit_engine_emit_stmt( emit, stmt->c1 );
2416 uint start_index = emit->next_index();
2418 // emit the cond
2419 emit_engine_emit_stmt( emit, stmt->c2, FALSE );
2421 // could be NULL
2422 if( stmt->c2 )
2424 switch( stmt->c2->stmt_exp->type->type )
2426 case te_int:
2427 case te_uint:
2428 // push 0
2429 emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
2430 op = new Chuck_Instr_Branch_Eq_uint( 0 );
2431 break;
2432 case te_float:
2433 case te_dur:
2434 case te_time:
2435 // push 0
2436 emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) );
2437 op = new Chuck_Instr_Branch_Eq_double( 0 );
2438 break;
2440 default:
2441 EM_error2( stmt->c2->stmt_exp->linepos,
2442 "(emit): internal error: unhandled type '%s' in for conditional",
2443 stmt->c2->stmt_exp->type->name );
2444 return FALSE;
2446 // append the op
2447 emit->append( op );
2450 // emit the body
2451 emit_engine_emit_stmt( emit, stmt->body );
2453 // emit the action
2454 emit_engine_emit_exp( emit, stmt->c3 );
2455 if( stmt->c3 )
2456 if( stmt->c3->type->size == 8 )
2457 emit->append( new Chuck_Instr_Reg_Pop_Word2 );
2458 else if( stmt->c3->type->size == 4 )
2459 emit->append( new Chuck_Instr_Reg_Pop_Word );
2460 else if( stmt->c3->type->size != 0 )
2462 EM_error2( stmt->c3->linepos,
2463 "(emit): internal error: non-void type size %i not handled",
2464 stmt->c3->type->size );
2465 return FALSE;
2468 // go back to do check the condition
2469 emit->append( new Chuck_Instr_Goto( start_index ) );
2471 // could be NULL
2472 if( stmt->c2 )
2473 // set the op's target
2474 op->set( emit->next_index() );
2476 return ret;
2482 //------------------------------------------------------------------------------
2483 // name: emit_engine_emit_if()
2484 // desc: ...
2485 //------------------------------------------------------------------------------
2486 t_CKBOOL emit_engine_emit_if( Chuck_Emmission * emit, a_Stmt_If stmt )
2488 t_CKBOOL ret = TRUE;
2489 Chuck_Instr_Branch_Op * op = NULL, * op2 = NULL;
2490 uint start_index = emit->next_index();
2492 // emit the cond
2493 emit_engine_emit_exp( emit, stmt->cond );
2495 switch( stmt->cond->type->type )
2497 case te_int:
2498 case te_uint:
2499 // push 0
2500 emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
2501 op = new Chuck_Instr_Branch_Eq_uint( 0 );
2502 break;
2503 case te_float:
2504 case te_dur:
2505 case te_time:
2506 // push 0
2507 emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) );
2508 op = new Chuck_Instr_Branch_Eq_double( 0 );
2509 break;
2511 default:
2512 EM_error2( stmt->cond->linepos,
2513 "(emit): internal erorr: unhandled type '%s' in if conditional",
2514 stmt->cond->type->name );
2515 break;
2518 // append the op
2519 emit->append( op );
2521 // emit the body
2522 emit_engine_emit_stmt( emit, stmt->if_body );
2524 // emit the skip to the end
2525 emit->append( op2 = new Chuck_Instr_Goto(0) );
2527 // set the op's target
2528 op->set( emit->next_index() );
2530 // emit the body
2531 emit_engine_emit_stmt( emit, stmt->else_body );
2533 // set the op2's target
2534 op2->set( emit->next_index() );
2536 return ret;
2542 //------------------------------------------------------------------------------
2543 // name: emit_engine_emit_return()
2544 // desc: ...
2545 //------------------------------------------------------------------------------
2546 t_CKBOOL emit_engine_emit_return( Chuck_Emmission * emit, a_Stmt_Return ret )
2548 if( !emit_engine_emit_exp( emit, ret->val ) )
2549 return FALSE;
2551 // determine where later
2552 Chuck_Instr_Goto * instr = new Chuck_Instr_Goto( 0 );
2553 emit->append( instr );
2554 emit->returns.push_back( instr );
2556 return TRUE;
2562 //------------------------------------------------------------------------------
2563 // name: emit_engine_emit_code_segment()
2564 // desc: ...
2565 //------------------------------------------------------------------------------
2566 t_CKBOOL emit_engine_emit_code_segment( Chuck_Emmission * emit, a_Stmt_Code stmt )
2568 a_Stmt_List list = stmt->stmt_list;
2570 while( list )
2572 if( !emit_engine_emit_stmt( emit, list->stmt ) )
2573 return FALSE;
2575 list = list->next;
2578 return TRUE;
2584 //-----------------------------------------------------------------------------
2585 // name: emit_engine_emit_chuck()
2586 // desc: emit chuck operator
2587 //-----------------------------------------------------------------------------
2588 t_CKBOOL emit_engine_emit_chuck( Chuck_Emmission * emit, a_Exp lhs, a_Exp rhs )
2590 if( rhs->type->type == te_midiout || lhs->type->type == te_midiin )
2591 emit->pop_the_ops();
2593 if( lhs->type->parent && rhs->type->parent &&
2594 lhs->type->parent->type == te_ugen &&
2595 rhs->type->parent->type == te_ugen )
2597 emit->append( new Chuck_Instr_UGen_Link );
2599 return TRUE;
2601 else if( lhs->type->type == __te_system_out__ )
2603 switch( rhs->type->type )
2605 case te_int:
2606 emit->append( new Chuck_Instr_Reg_Push_Imm( cip_int ) );
2607 break;
2608 case te_uint:
2609 emit->append( new Chuck_Instr_Reg_Push_Imm( cip_uint ) );
2610 break;
2611 case te_float:
2612 emit->append( new Chuck_Instr_Reg_Push_Imm( cip_float ) );
2613 break;
2614 case te_double:
2615 emit->append( new Chuck_Instr_Reg_Push_Imm( cip_double ) );
2616 break;
2617 case te_time:
2618 emit->append( new Chuck_Instr_Reg_Push_Imm( cip_time ) );
2619 break;
2620 case te_dur:
2621 emit->append( new Chuck_Instr_Reg_Push_Imm( cip_dur ) );
2622 break;
2623 case te_string:
2624 emit->append( new Chuck_Instr_Reg_Push_Imm( cip_string ) );
2625 break;
2626 default:
2627 EM_error2( rhs->linepos,
2628 "(emit): internal error: unsupported type '%s' to print to console",
2629 rhs->type->name );
2630 return FALSE;
2633 emit->append( new Chuck_Instr_Print_Console2 );
2635 else if( rhs->s_type != ae_exp_decl )
2637 if( rhs->s_type == ae_exp_primary &&
2638 rhs->primary.s_type == ae_primary_var )
2640 a_Exp_Primary primary = &(rhs->primary);
2641 if( !strcmp( S_name(primary->var), "now" ) )
2643 // special case: time advance
2644 if( lhs->type->type == te_dur )
2645 emit->append( new Chuck_Instr_Add_dur_time );
2646 else if( lhs->type->type == te_time )
2647 // pop the now - no need it anymore
2648 emit->append( new Chuck_Instr_Reg_Pop_Word2() );
2649 else
2651 EM_error2( lhs->linepos,
2652 "(emit): internal error: bad type '%s' chucked to now",
2653 lhs->type->name );
2654 return FALSE;
2657 // advance
2658 emit->append( new Chuck_Instr_Time_Advance );
2660 return TRUE;
2662 else if( !strcmp( S_name(primary->var), "midiin" ) )
2664 EM_error2( lhs->linepos,
2665 "(emit): internal error: value chucked to midiin" );
2666 return FALSE;
2668 else if( !strcmp( S_name(primary->var), "midiout" ) )
2670 emit->append_ops();
2671 // emit->append( new Chuck_Instr_Midi_Out_Go(0) );
2672 return TRUE;
2674 else if( !strcmp( S_name(primary->var), "true" ) )
2676 EM_error2( primary->linepos,
2677 "cannot assign value to 'true'" );
2678 return FALSE;
2680 else if( !strcmp( S_name(primary->var), "false" ) )
2682 EM_error2( primary->linepos,
2683 "cannot assign value to 'false'" );
2684 return FALSE;
2686 else if( !strcmp( S_name(primary->var), "maybe" ) )
2688 EM_error2( primary->linepos,
2689 "cannot assign value to 'maybe'" );
2690 return FALSE;
2692 else if( !strcmp( S_name(primary->var), "pi" ) )
2694 EM_error2( primary->linepos,
2695 "cannot assign value to 'pi'" );
2696 return FALSE;
2698 else if( !strcmp( S_name(primary->var), "stdout" ) ||
2699 !strcmp( S_name(primary->var), "chout" ) )
2701 switch( lhs->type->type )
2703 case te_int:
2704 emit->append( new Chuck_Instr_Reg_Push_Imm( cip_int ) );
2705 break;
2706 case te_uint:
2707 emit->append( new Chuck_Instr_Reg_Push_Imm( cip_uint ) );
2708 break;
2709 case te_float:
2710 emit->append( new Chuck_Instr_Reg_Push_Imm( cip_double ) );
2711 break;
2712 case te_double:
2713 emit->append( new Chuck_Instr_Reg_Push_Imm( cip_double ) );
2714 break;
2715 case te_time:
2716 emit->append( new Chuck_Instr_Reg_Push_Imm( cip_time ) );
2717 break;
2718 case te_dur:
2719 emit->append( new Chuck_Instr_Reg_Push_Imm( cip_dur ) );
2720 break;
2721 case te_string:
2722 emit->append( new Chuck_Instr_Reg_Push_Imm( cip_string ) );
2723 break;
2724 default:
2725 EM_error2( lhs->linepos,
2726 "(emit): internal error: unsupported type '%s' to print to console",
2727 lhs->type->name );
2728 return FALSE;
2731 emit->append( new Chuck_Instr_Print_Console );
2733 else
2735 t_CKUINT is_global = FALSE;
2736 t_CKUINT size = 0;
2737 int offset = emit->find_offset( primary->var, &is_global, &size );
2738 Chuck_Instr_Unary_Op * op = NULL;
2740 if( offset < 0 )
2742 // should be a function
2743 EM_error2( rhs->linepos,
2744 "(emit): internal error: chuck to function not impl" );
2745 return FALSE;
2747 else
2749 // TODO: fix this hack
2750 if( size == 4 )
2751 emit->append( new Chuck_Instr_Reg_Pop_Word );
2752 else if( size == 8 )
2753 emit->append( new Chuck_Instr_Reg_Pop_Word2 );
2754 else
2756 EM_error2( rhs->linepos,
2757 "(emit): %i byte not handled in chuck operator : decl",
2758 size );
2759 return FALSE;
2762 emit->append( op = new Chuck_Instr_Reg_Push_Imm( offset ) );
2763 if( emit->is_global || !is_global )
2765 // special case: assignment
2766 if( rhs->type->parent == NULL )
2768 if( rhs->type->size == 4 )
2769 emit->append( new Chuck_Instr_Chuck_Assign );
2770 else if( rhs->type->size == 8 )
2771 emit->append( new Chuck_Instr_Chuck_Assign2 );
2772 else
2774 EM_error2( rhs->linepos,
2775 "(emit): %i byte not handled in chuck operator assign",
2776 rhs->type->size );
2777 return FALSE;
2780 else
2781 emit->append( new Chuck_Instr_Chuck_Assign_Object );
2783 else
2785 emit->addr_map.push_back( op );
2786 // special case: deref assignment
2787 if( rhs->type->parent == NULL )
2789 if( rhs->type->size == 4 )
2790 emit->append( new Chuck_Instr_Chuck_Assign_Deref );
2791 else
2792 emit->append( new Chuck_Instr_Chuck_Assign_Deref2 );
2794 else
2795 emit->append( new Chuck_Instr_Chuck_Assign_Object_Deref );
2800 else if( rhs->s_type == ae_exp_namespace )
2802 if( lhs->type->type == te_string )
2804 // emit instruction to load the DLL
2805 emit->append( new Chuck_Instr_DLL_Load );
2807 else
2809 EM_error2( lhs->linepos,
2810 "(emit): internal error: unhandled type '%s' in namespace expression",
2811 lhs->type->name );
2812 return FALSE;
2815 else if( rhs->s_type == ae_exp_dot_member && rhs->dot_member.data )
2817 // the function addr
2818 emit->append( new Chuck_Instr_Reg_Push_Imm( rhs->dot_member.data ) );
2819 emit->append( new Chuck_Instr_Reg_Push_Imm( rhs->dot_member.data2 ) );
2821 // the ugen
2822 if( !strcmp( S_name(rhs->dot_member.id), "op" ) )
2823 emit->append( new Chuck_Instr_UGen_Ctrl_Op );
2824 else if( !strcmp( S_name(rhs->dot_member.id), "gain" ) )
2825 emit->append( new Chuck_Instr_UGen_Ctrl_Gain );
2826 else if( !strcmp( S_name(rhs->dot_member.id), "last" ) )
2828 EM_error2( rhs->linepos,
2829 "(emit): internal error: cannot chuck to 'ugen.last'" );
2830 return FALSE;
2832 else
2834 // ctrl passing to ugen
2835 if( rhs->type->size == 4 )
2836 emit->append( new Chuck_Instr_UGen_Ctrl );
2837 else if( rhs->type->size == 8 )
2838 emit->append( new Chuck_Instr_UGen_Ctrl2 );
2839 else
2841 EM_error2( rhs->linepos,
2842 "(emit): internal error: %i ugen ctrl not handled",
2843 rhs->type->size );
2844 return FALSE;
2848 else if( rhs->s_type == ae_exp_dot_member )
2850 EM_error2( rhs->linepos,
2851 "(emit): cannot assign values to namespace constants" );
2852 return FALSE;
2854 else
2856 EM_error2( rhs->linepos,
2857 "(emit): internal error: illegal expression" );
2858 return FALSE;
2861 else // if( rhs->s_type == ae_exp_decl )
2863 // special case: assignment
2864 if( rhs->type->parent == NULL )
2866 if( rhs->type->size == 4 )
2867 emit->append( new Chuck_Instr_Chuck_Assign );
2868 else if( rhs->type->size == 8 )
2869 emit->append( new Chuck_Instr_Chuck_Assign2 );
2870 else
2872 EM_error2( rhs->linepos,
2873 "(emit): %i size not handled in chuck assigg",
2874 rhs->type->size );
2875 return FALSE;
2878 else
2879 emit->append( new Chuck_Instr_Chuck_Assign_Object );
2882 return TRUE;
2888 //-----------------------------------------------------------------------------
2889 // name: emit_engine_emit_unchuck()
2890 // desc: ...
2891 //-----------------------------------------------------------------------------
2892 t_CKBOOL emit_engine_emit_unchuck( Chuck_Emmission * emit, a_Exp lhs, a_Exp rhs )
2894 if( lhs->type->parent && rhs->type->parent &&
2895 lhs->type->parent->type == te_ugen && rhs->type->parent->type == te_ugen )
2897 emit->append( new Chuck_Instr_UGen_UnLink );
2899 else
2901 EM_error2( lhs->linepos,
2902 "(emit): internal error: no suitable un-chuck resolution on types '%s' and '%s'",
2903 lhs->type->name, rhs->type->name );
2904 return FALSE;
2907 return TRUE;
2913 //-----------------------------------------------------------------------------
2914 // name: emit_engine_emit_func_def()
2915 // desc: ...
2916 //-----------------------------------------------------------------------------
2917 t_CKBOOL emit_engine_emit_func_def( Chuck_Emmission * emit, a_Func_Def func_def )
2919 if( func_def->s_type == ae_func_user )
2921 emit->is_global = FALSE;
2922 emit->local = new Chuck_Code( S_name(func_def->name) );
2923 emit->push( "__func_def_scope__" );
2924 emit->functions.push_back( emit->local );
2925 emit->local->stack_depth = func_def->stack_depth;
2926 emit->returns.clear();
2928 // args
2929 a_Arg_List args = func_def->arg_list;
2931 while( args )
2933 emit->alloc_local( args->id, args->type );
2934 args = args->next;
2937 // emit the function body
2938 emit_engine_emit_stmt( emit, func_def->code );
2940 // return index to the end of the function
2941 for( unsigned int i = 0; i < emit->returns.size(); i++ )
2942 emit->returns[i]->set( emit->next_index() );
2944 // emit the return
2945 emit->append( new Chuck_Instr_Func_Return );
2947 emit->pop();
2948 emit->is_global = TRUE;
2949 emit->local = NULL;
2951 else
2953 EM_error2( func_def->linepos,
2954 "(emit): internal error: builtin functions not impl" );
2955 return FALSE;
2958 return TRUE;
2963 //-----------------------------------------------------------------------------
2964 // name: emit_engine_emit_exp_mem()
2965 // desc: emit an exp as memory address only
2966 //-----------------------------------------------------------------------------
2967 t_CKBOOL emit_engine_emit_exp_mem( Chuck_Emmission * emit, a_Exp exp )
2969 while( exp )
2971 switch( exp->s_type )
2973 case ae_exp_primary:
2974 if( !emit_engine_emit_exp_primary_mem( emit, &exp->primary ) )
2975 return FALSE;
2976 break;
2978 case ae_exp_dot_member:
2979 if( !emit_engine_emit_exp_dot_member_mem( emit, &exp->dot_member ) )
2980 return FALSE;
2981 break;
2983 case ae_exp_array:
2984 if( !emit_engine_emit_exp_array_mem( emit, &exp->array ) )
2985 return FALSE;
2986 break;
2988 case ae_exp_func_call:
2989 if( !emit_engine_emit_exp_func_call_mem( emit, &exp->func_call ) )
2990 return FALSE;
2991 break;
2993 default:
2994 EM_error2( exp->linepos,
2995 "(emit): internal error: unhandled expression in [mem] emission" );
2996 return FALSE;
2999 exp = exp->next;
3002 return TRUE;
3008 //-----------------------------------------------------------------------------
3009 // name: emit_engine_emit_exp_primary_mem()
3010 // desc: emit a primary exp as memory address only
3011 //-----------------------------------------------------------------------------
3012 t_CKBOOL emit_engine_emit_exp_primary_mem( Chuck_Emmission * emit, a_Exp_Primary exp )
3014 switch( exp->s_type )
3016 case ae_primary_var:
3017 /*if( exp->var == insert_symbol( "now" ) )
3019 emit->append( new Chuck_Instr_Reg_Push_Now );
3021 else */
3023 int offset = emit->find_offset( exp->var );
3024 if( offset < 0 )
3026 // could be a function
3027 EM_error2( exp->linepos,
3028 "(emit): internal error: cannot resolve [mem] var '%s'",
3029 S_name(exp->var) );
3030 return FALSE;
3033 emit->append( new Chuck_Instr_Reg_Push_Imm( offset ) );
3035 break;
3037 case ae_primary_exp:
3038 return emit_engine_emit_exp_mem( emit, exp->exp );
3039 break;
3041 default:
3042 EM_error2( exp->linepos,
3043 "(emit): internal error: cannot emit [mem] primary exp" );
3044 return FALSE;
3047 return TRUE;
3053 //-----------------------------------------------------------------------------
3054 // name: emit_engine_emit_exp_dot_member_mem()
3055 // desc: emit a dot exp as memory address only
3056 //-----------------------------------------------------------------------------
3057 t_CKBOOL emit_engine_emit_exp_dot_member_mem( Chuck_Emmission * emit, a_Exp_Dot_Member exp )
3059 EM_error2( exp->linepos,
3060 "(emit): internal erorr: . address not impl" );
3061 return FALSE;
3067 //-----------------------------------------------------------------------------
3068 // name: emit_engine_emit_exp_array_mem()
3069 // desc: emit array exp as memory address only
3070 //-----------------------------------------------------------------------------
3071 t_CKBOOL emit_engine_emit_exp_array_mem( Chuck_Emmission * emit, a_Exp_Array exp )
3073 EM_error2( exp->linepos,
3074 "(emit): internal error: array address not impl" );
3075 return FALSE;
3081 //-----------------------------------------------------------------------------
3082 // name: emit_engine_emit_exp_func_call_mem()
3083 // desc: emit a func call exp as memory address only
3084 //-----------------------------------------------------------------------------
3085 t_CKBOOL emit_engine_emit_exp_func_call_mem( Chuck_Emmission * emit, a_Exp_Func_Call exp )
3087 EM_error2( exp->linepos,
3088 "(emit): internal error: func call address no impl" );
3089 return FALSE;