*** empty log message ***
[chuck-blob.git] / v2 / chuck_scan.cpp
blob916b579c6fac884a343df4fc7b7f1186d25c66a6
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_scan.cpp
27 // desc: chuck type-system / type-checker pre-scan
29 // author: Ge Wang (gewang@cs.princeton.edu)
30 // Perry R. Cook (prc@cs.princeton.edu)
31 // date: Summer 2005 - original
32 //-----------------------------------------------------------------------------
33 #include "chuck_type.h"
34 #include "chuck_scan.h"
35 #include "chuck_errmsg.h"
36 #include "chuck_vm.h"
37 #include "util_string.h"
39 using namespace std;
44 //-----------------------------------------------------------------------------
45 // function prototypes
46 //-----------------------------------------------------------------------------
47 t_CKBOOL type_engine_scan0_class_def( Chuck_Env * env, a_Class_Def class_def );
49 t_CKBOOL type_engine_scan1_stmt_list( Chuck_Env * env, a_Stmt_List list );
50 t_CKBOOL type_engine_scan1_stmt( Chuck_Env * env, a_Stmt stmt );
51 t_CKBOOL type_engine_scan1_if( Chuck_Env * env, a_Stmt_If stmt );
52 t_CKBOOL type_engine_scan1_for( Chuck_Env * env, a_Stmt_For stmt );
53 t_CKBOOL type_engine_scan1_while( Chuck_Env * env, a_Stmt_While stmt );
54 t_CKBOOL type_engine_scan1_until( Chuck_Env * env, a_Stmt_Until stmt );
55 t_CKBOOL type_engine_scan1_loop( Chuck_Env * env, a_Stmt_Loop stmt );
56 t_CKBOOL type_engine_scan1_break( Chuck_Env * env, a_Stmt_Break br );
57 t_CKBOOL type_engine_scan1_continue( Chuck_Env * env, a_Stmt_Continue cont );
58 t_CKBOOL type_engine_scan1_return( Chuck_Env * env, a_Stmt_Return stmt );
59 t_CKBOOL type_engine_scan1_switch( Chuck_Env * env, a_Stmt_Switch stmt );
60 t_CKBOOL type_engine_scan1_exp( Chuck_Env * env, a_Exp exp );
61 t_CKBOOL type_engine_scan1_exp_binary( Chuck_Env * env, a_Exp_Binary binary );
62 t_CKBOOL type_engine_scan1_op( Chuck_Env * env, ae_Operator op, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary );
63 t_CKBOOL type_engine_scan1_op_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary );
64 t_CKBOOL type_engine_scan1_op_unchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs );
65 t_CKBOOL type_engine_scan1_op_upchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs );
66 t_CKBOOL type_engine_scan1_op_at_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs );
67 t_CKBOOL type_engine_scan1_exp_unary( Chuck_Env * env, a_Exp_Unary unary );
68 t_CKBOOL type_engine_scan1_exp_primary( Chuck_Env * env, a_Exp_Primary exp );
69 t_CKBOOL type_engine_scan1_exp_array_lit( Chuck_Env * env, a_Exp_Primary exp );
70 t_CKBOOL type_engine_scan1_exp_cast( Chuck_Env * env, a_Exp_Cast cast );
71 t_CKBOOL type_engine_scan1_exp_postfix( Chuck_Env * env, a_Exp_Postfix postfix );
72 t_CKBOOL type_engine_scan1_exp_dur( Chuck_Env * env, a_Exp_Dur dur );
73 t_CKBOOL type_engine_scan1_exp_array( Chuck_Env * env, a_Exp_Array array );
74 t_CKBOOL type_engine_scan1_exp_func_call( Chuck_Env * env, a_Exp_Func_Call func_call );
75 t_CKBOOL type_engine_scan1_exp_func_call( Chuck_Env * env, a_Exp exp_func, a_Exp args,
76 t_CKFUNC & ck_func, int linepos );
77 t_CKBOOL type_engine_scan1_exp_dot_member( Chuck_Env * env, a_Exp_Dot_Member member );
78 t_CKBOOL type_engine_scan1_exp_if( Chuck_Env * env, a_Exp_If exp_if );
79 t_CKBOOL type_engine_scan1_exp_decl( Chuck_Env * env, a_Exp_Decl decl );
80 t_CKBOOL type_engine_scan1_array_subscripts( Chuck_Env * env, a_Exp exp_list );
81 t_CKBOOL type_engine_scan1_cast_valid( Chuck_Env * env, t_CKTYPE to, t_CKTYPE from );
82 t_CKBOOL type_engine_scan1_code_segment( Chuck_Env * env, a_Stmt_Code stmt, t_CKBOOL push = TRUE );
83 t_CKBOOL type_engine_scan1_func_def( Chuck_Env * env, a_Func_Def func_def );
84 t_CKBOOL type_engine_scan1_class_def( Chuck_Env * env, a_Class_Def class_def );
86 t_CKBOOL type_engine_scan2_stmt_list( Chuck_Env * env, a_Stmt_List list );
87 t_CKBOOL type_engine_scan2_stmt( Chuck_Env * env, a_Stmt stmt );
88 t_CKBOOL type_engine_scan2_if( Chuck_Env * env, a_Stmt_If stmt );
89 t_CKBOOL type_engine_scan2_for( Chuck_Env * env, a_Stmt_For stmt );
90 t_CKBOOL type_engine_scan2_while( Chuck_Env * env, a_Stmt_While stmt );
91 t_CKBOOL type_engine_scan2_loop( Chuck_Env * env, a_Stmt_Loop stmt );
92 t_CKBOOL type_engine_scan2_until( Chuck_Env * env, a_Stmt_Until stmt );
93 t_CKBOOL type_engine_scan2_break( Chuck_Env * env, a_Stmt_Break br );
94 t_CKBOOL type_engine_scan2_continue( Chuck_Env * env, a_Stmt_Continue cont );
95 t_CKBOOL type_engine_scan2_return( Chuck_Env * env, a_Stmt_Return stmt );
96 t_CKBOOL type_engine_scan2_switch( Chuck_Env * env, a_Stmt_Switch stmt );
97 t_CKBOOL type_engine_scan2_exp( Chuck_Env * env, a_Exp exp );
98 t_CKBOOL type_engine_scan2_exp_binary( Chuck_Env * env, a_Exp_Binary binary );
99 t_CKBOOL type_engine_scan2_op( Chuck_Env * env, ae_Operator op, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary );
100 t_CKBOOL type_engine_scan2_op_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary );
101 t_CKBOOL type_engine_scan2_op_unchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs );
102 t_CKBOOL type_engine_scan2_op_upchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs );
103 t_CKBOOL type_engine_scan2_op_at_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs );
104 t_CKBOOL type_engine_scan2_exp_unary( Chuck_Env * env, a_Exp_Unary unary );
105 t_CKBOOL type_engine_scan2_exp_primary( Chuck_Env * env, a_Exp_Primary exp );
106 t_CKBOOL type_engine_scan2_exp_array_lit( Chuck_Env * env, a_Exp_Primary exp );
107 t_CKBOOL type_engine_scan2_exp_cast( Chuck_Env * env, a_Exp_Cast cast );
108 t_CKBOOL type_engine_scan2_exp_postfix( Chuck_Env * env, a_Exp_Postfix postfix );
109 t_CKBOOL type_engine_scan2_exp_dur( Chuck_Env * env, a_Exp_Dur dur );
110 t_CKBOOL type_engine_scan2_exp_array( Chuck_Env * env, a_Exp_Array array );
111 t_CKBOOL type_engine_scan2_exp_func_call( Chuck_Env * env, a_Exp_Func_Call func_call );
112 t_CKBOOL type_engine_scan2_exp_func_call( Chuck_Env * env, a_Exp exp_func, a_Exp args,
113 t_CKFUNC & ck_func, int linepos );
114 t_CKBOOL type_engine_scan2_exp_dot_member( Chuck_Env * env, a_Exp_Dot_Member member );
115 t_CKBOOL type_engine_scan2_exp_if( Chuck_Env * env, a_Exp_If exp_if );
116 t_CKBOOL type_engine_scan2_exp_decl( Chuck_Env * env, a_Exp_Decl decl );
117 t_CKBOOL type_engine_scan2_array_subscripts( Chuck_Env * env, a_Exp exp_list );
118 t_CKBOOL type_engine_scan2_cast_valid( Chuck_Env * env, t_CKTYPE to, t_CKTYPE from );
119 t_CKBOOL type_engine_scan2_code_segment( Chuck_Env * env, a_Stmt_Code stmt, t_CKBOOL push = TRUE );
120 t_CKBOOL type_engine_scan2_func_def( Chuck_Env * env, a_Func_Def func_def );
121 t_CKBOOL type_engine_scan2_class_def( Chuck_Env * env, a_Class_Def class_def );
122 t_CKBOOL type_engine_scan2_func_def( Chuck_Env * env, a_Func_Def func_def );
123 t_CKBOOL type_engine_scan2_class_def( Chuck_Env * env, a_Class_Def class_def );
128 //-----------------------------------------------------------------------------
129 // name: type_engine_scan0_prog()
130 // desc: data in env should be ready : type discovery
131 //-----------------------------------------------------------------------------
132 t_CKBOOL type_engine_scan0_prog( Chuck_Env * env, a_Program prog,
133 te_HowMuch how_much )
135 t_CKBOOL ret = TRUE;
137 if( !prog )
138 return FALSE;
140 // log
141 EM_log( CK_LOG_FINER, "(pass 0) type discovery scan '%s'...",
142 env->context->filename.c_str() );
143 // push indent
144 EM_pushlog();
145 // log how much
146 EM_log( CK_LOG_FINER, "target: %s", howmuch2str( how_much ) );
148 // go through each of the program sections
149 while( prog && ret )
151 switch( prog->section->s_type )
153 case ae_section_stmt:
154 // do nothing
155 break;
157 case ae_section_func:
158 // do nothing
159 break;
161 case ae_section_class:
162 // if no classes, then skip
163 if( how_much == te_do_no_classes ) break;
164 // make global, if marked public
165 if( prog->section->class_def->decl == ae_key_public )
167 // make sure the context has no public class
168 if( env->context->public_class_def != NULL )
170 EM_error2( prog->section->class_def->linepos,
171 "more than one 'public' class defined..." );
172 ret = FALSE;
173 continue;
176 // make global
177 prog->section->class_def->home = env->global();
178 // remember
179 env->context->public_class_def = prog->section->class_def;
181 // scan the class definition
182 ret = type_engine_scan0_class_def( env, prog->section->class_def );
183 break;
185 default:
186 EM_error2( prog->linepos,
187 "internal error: unrecognized program section in type checker pre-scan..." );
188 ret = FALSE;
189 break;
192 prog = prog->next;
195 // pop indent
196 EM_poplog();
198 return ret;
204 //-----------------------------------------------------------------------------
205 // name: type_engine_scan0_class_def()
206 // desc: add defined class to env - this is the main goal of scan0
207 //-----------------------------------------------------------------------------
208 t_CKBOOL type_engine_scan0_class_def( Chuck_Env * env, a_Class_Def class_def )
210 // make new type for class def
211 t_CKTYPE the_class = NULL;
212 // the return type
213 t_CKBOOL ret = TRUE;
214 // the class body
215 a_Class_Body body = class_def->body;
217 // log
218 EM_log( CK_LOG_FINER, "scanning class definition '%s'...",
219 S_name(class_def->name->xid) );
220 // push indent
221 EM_pushlog();
223 // if nspc is attached to class_def, that means the class_def is to be
224 // put in that namespace. this is usually the case when doing import
225 if( class_def->home != NULL )
227 // log
228 EM_log( CK_LOG_FINER, "target namespace: '%s'",
229 class_def->home->name.c_str() );
230 // set the new type as current
231 env->nspc_stack.push_back( env->curr );
232 env->curr = class_def->home;
235 // make sure class not already in namespace
236 if( env->curr->lookup_type( class_def->name->xid, FALSE ) )
238 EM_error2( class_def->name->linepos,
239 "class/type '%s' is already defined in namespace '%s'",
240 S_name(class_def->name->xid), env->curr->name.c_str() );
241 ret = FALSE; goto done;
244 // check if reserved
245 if( type_engine_check_reserved( env, class_def->name->xid, class_def->name->linepos ) )
247 EM_error2( class_def->name->linepos, "...in class definition '%s'",
248 S_name(class_def->name->xid) );
249 ret = FALSE; goto done;
252 // allocate new type
253 assert( env->context != NULL );
254 the_class = env->context->new_Chuck_Type();
255 // add reference
256 SAFE_ADD_REF( the_class );
257 // set the fields
258 the_class->xid = te_user;
259 the_class->name = S_name(class_def->name->xid);
260 the_class->owner = env->curr;
261 the_class->array_depth = 0;
262 the_class->size = sizeof(void *);
263 the_class->obj_size = 0; // TODO:
264 the_class->info = env->context->new_Chuck_Namespace();
265 SAFE_ADD_REF( the_class->info );
266 the_class->info->name = the_class->name;
267 // if public class, then set parent to context
268 // ... allowing the class to address current context
269 if( env->context->public_class_def == class_def )
270 { the_class->info->parent = env->context->nspc; }
271 else { the_class->info->parent = env->curr; }
272 // TODO: add ref to the parent?
273 the_class->func = NULL;
274 the_class->def = class_def;
275 // add code
276 the_class->info->pre_ctor = new Chuck_VM_Code;
277 SAFE_ADD_REF( the_class->info->pre_ctor );
278 // add to env
279 env->curr->type.add( the_class->name, the_class ); // URGENT: make this global
280 // incomplete
281 the_class->is_complete = FALSE;
283 // set the new type as current
284 env->nspc_stack.push_back( env->curr );
285 env->curr = the_class->info;
286 // push the class def
287 env->class_stack.push_back( env->class_def );
288 env->class_def = the_class;
289 // reset the nest list
290 env->class_scope = 0;
292 // type check the body
293 while( body && ret )
295 // check the section
296 switch( body->section->s_type )
298 case ae_section_stmt:
299 break;
301 case ae_section_func:
302 break;
304 case ae_section_class:
305 // do the class
306 ret = type_engine_scan0_class_def( env, body->section->class_def );
307 break;
310 // move to the next section
311 body = body->next;
315 // pop the class
316 env->class_def = env->class_stack.back();
317 env->class_stack.pop_back();
318 // pop the namesapce
319 env->curr = env->nspc_stack.back();
320 env->nspc_stack.pop_back();
322 // if things checked out
323 if( ret )
325 Chuck_Value * value = NULL;
326 Chuck_Type * type = NULL;
328 // allocate value
329 type = t_class.copy( env );
330 type->actual_type = the_class;
331 value = env->context->new_Chuck_Value( type, the_class->name );
332 value->owner = env->curr;
333 value->is_const = TRUE;
334 value->is_member = FALSE;
335 // add to env
336 env->curr->value.add( the_class->name, value );
338 // remember
339 class_def->type = the_class;
342 // if nspc is attached to class_def, that means the class_def is to be
343 // put in that namespace. this is usually the case when doing import
344 // we undo that extra namespace layer here...
345 if( class_def->home != NULL )
347 // pop the namesapce
348 env->curr = env->nspc_stack.back();
349 env->nspc_stack.pop_back();
351 else // set the current namespace as home
353 // set curr as home
354 class_def->home = env->curr;
357 done:
359 // pop indent
360 EM_poplog();
362 return ret;
368 //-----------------------------------------------------------------------------
369 // name: type_engine_scan1_prog()
370 // desc: data in env should be ready
371 //-----------------------------------------------------------------------------
372 t_CKBOOL type_engine_scan1_prog( Chuck_Env * env, a_Program prog,
373 te_HowMuch how_much )
375 t_CKBOOL ret = TRUE;
377 if( !prog )
378 return FALSE;
380 // log
381 EM_log( CK_LOG_FINER, "(pass 1) type resolution scan '%s'...",
382 env->context->filename.c_str() );
383 // push indent
384 EM_pushlog();
385 // log how much
386 EM_log( CK_LOG_FINER, "target: %s", howmuch2str( how_much ) );
388 // go through each of the program sections
389 while( prog && ret )
391 switch( prog->section->s_type )
393 case ae_section_stmt:
394 // if only classes, then skip
395 if( how_much == te_do_classes_only ) break;
396 // scan the statements
397 ret = type_engine_scan1_stmt_list( env, prog->section->stmt_list );
398 break;
400 case ae_section_func:
401 // if only classes, then skip
402 if( how_much == te_do_classes_only ) break;
403 // scan the function definition
404 ret = type_engine_scan1_func_def( env, prog->section->func_def );
405 break;
407 case ae_section_class:
408 // if no classes, then skip
409 if( how_much == te_do_no_classes ) break;
410 // scan the class definition
411 ret = type_engine_scan1_class_def( env, prog->section->class_def );
412 break;
414 default:
415 EM_error2( prog->linepos,
416 "internal error: unrecognized program section in type checker pre-scan..." );
417 ret = FALSE;
418 break;
421 prog = prog->next;
424 // pop indent
425 EM_poplog();
427 return ret;
433 //-----------------------------------------------------------------------------
434 // name: type_engine_scan1_stmt_list()
435 // desc: ...
436 //-----------------------------------------------------------------------------
437 t_CKBOOL type_engine_scan1_stmt_list( Chuck_Env * env, a_Stmt_List list )
439 // type check the stmt_list
440 while( list )
442 // the current statement
443 if( !type_engine_scan1_stmt( env, list->stmt ) )
444 return FALSE;
446 // advance to the next statement
447 list = list->next;
450 return TRUE;
456 //-----------------------------------------------------------------------------
457 // name: type_engine_scan1_stmt(()
458 // desc: ...
459 //-----------------------------------------------------------------------------
460 t_CKBOOL type_engine_scan1_stmt( Chuck_Env * env, a_Stmt stmt )
462 t_CKBOOL ret = FALSE;
464 if( !stmt )
465 return TRUE;
467 // the type of stmt
468 switch( stmt->s_type )
470 case ae_stmt_if:
471 // count scope to help determine class member
472 env->class_scope++;
473 env->curr->value.push();
474 ret = type_engine_scan1_if( env, &stmt->stmt_if );
475 env->curr->value.pop();
476 env->class_scope--;
477 break;
479 case ae_stmt_for:
480 env->class_scope++;
481 env->curr->value.push();
482 ret = type_engine_scan1_for( env, &stmt->stmt_for );
483 env->curr->value.pop();
484 env->class_scope--;
485 break;
487 case ae_stmt_while:
488 env->class_scope++;
489 env->curr->value.push();
490 ret = type_engine_scan1_while( env, &stmt->stmt_while );
491 env->curr->value.pop();
492 env->class_scope--;
493 break;
495 case ae_stmt_until:
496 env->class_scope++;
497 env->curr->value.push();
498 ret = type_engine_scan1_until( env, &stmt->stmt_until );
499 env->curr->value.pop();
500 env->class_scope--;
501 break;
503 case ae_stmt_loop:
504 env->class_scope++;
505 env->curr->value.push();
506 ret = type_engine_scan1_loop( env, &stmt->stmt_loop );
507 env->curr->value.pop();
508 env->class_scope--;
509 break;
511 case ae_stmt_exp:
512 ret = type_engine_scan1_exp( env, stmt->stmt_exp );
513 break;
515 case ae_stmt_return:
516 ret = type_engine_scan1_return( env, &stmt->stmt_return );
517 break;
519 case ae_stmt_code:
520 env->class_scope++;
521 ret = type_engine_scan1_code_segment( env, &stmt->stmt_code );
522 env->class_scope--;
523 break;
525 case ae_stmt_break:
526 ret = type_engine_scan1_break( env, &stmt->stmt_break );
527 break;
529 case ae_stmt_continue:
530 ret = type_engine_scan1_continue( env, &stmt->stmt_continue );
531 break;
533 case ae_stmt_switch:
534 env->class_scope++;
535 ret = type_engine_scan1_switch( env, &stmt->stmt_switch );
536 env->class_scope--;
537 break;
539 case ae_stmt_case:
540 // ret = type_engine_scan1_case( env, &stmt->stmt_case );
541 break;
543 case ae_stmt_gotolabel:
544 // ret = type_engine_scan1_gotolabel( env, &stmt->goto_label );
545 break;
547 default:
548 EM_error2( stmt->linepos,
549 "internal compiler error (pre-scan) - no stmt type '%i'!", stmt->s_type );
550 ret = FALSE;
551 break;
554 return ret;
560 //-----------------------------------------------------------------------------
561 // name: type_engine_scan1_if()
562 // desc: ...
563 //-----------------------------------------------------------------------------
564 t_CKBOOL type_engine_scan1_if( Chuck_Env * env, a_Stmt_If stmt )
566 // check the conditional
567 if( !type_engine_scan1_exp( env, stmt->cond ) )
568 return FALSE;
570 // TODO: ensure that conditional has valid type
572 // check if
573 if( !type_engine_scan1_stmt( env, stmt->if_body ) )
574 return FALSE;
576 // check else, if there is one
577 if( stmt->else_body )
578 if( !type_engine_scan1_stmt( env, stmt->else_body ) )
579 return FALSE;
581 return TRUE;
587 //-----------------------------------------------------------------------------
588 // name: type_engine_scan1_for()
589 // desc: ...
590 //-----------------------------------------------------------------------------
591 t_CKBOOL type_engine_scan1_for( Chuck_Env * env, a_Stmt_For stmt )
593 // check the initial
594 if( !type_engine_scan1_stmt( env, stmt->c1 ) )
595 return FALSE;
597 // check the conditional
598 if( !type_engine_scan1_stmt( env, stmt->c2 ) )
599 return FALSE;
601 // TODO: same as if - check conditional type valid
603 // check the post
604 if( stmt->c3 && !type_engine_scan1_exp( env, stmt->c3 ) )
605 return FALSE;
607 // check body
608 if( !type_engine_scan1_stmt( env, stmt->body ) )
609 return FALSE;
611 return TRUE;
617 //-----------------------------------------------------------------------------
618 // name: type_engine_scan1_while()
619 // desc: ...
620 //-----------------------------------------------------------------------------
621 t_CKBOOL type_engine_scan1_while( Chuck_Env * env, a_Stmt_While stmt )
623 // check the conditional
624 if( !type_engine_scan1_exp( env, stmt->cond ) )
625 return FALSE;
627 // TODO: same as if - ensure the type in conditional is valid
629 // check the body
630 if( !type_engine_scan1_stmt( env, stmt->body ) )
631 return FALSE;
633 return TRUE;
639 //-----------------------------------------------------------------------------
640 // name: type_engine_scan1_until()
641 // desc: ...
642 //-----------------------------------------------------------------------------
643 t_CKBOOL type_engine_scan1_until( Chuck_Env * env, a_Stmt_Until stmt )
645 // check the conditional
646 if( !type_engine_scan1_exp( env, stmt->cond ) )
647 return FALSE;
649 // TODO: same as if - ensure the type in conditional is valid
651 // check the body
652 if( !type_engine_scan1_stmt( env, stmt->body ) )
653 return FALSE;
655 return TRUE;
661 //-----------------------------------------------------------------------------
662 // name: type_engine_scan1_loop()
663 // desc: ...
664 //-----------------------------------------------------------------------------
665 t_CKBOOL type_engine_scan1_loop( Chuck_Env * env, a_Stmt_Loop stmt )
667 // check the conditional
668 if( !type_engine_scan1_exp( env, stmt->cond ) )
669 return FALSE;
671 // TODO: same as if - ensure the type in conditional is valid
673 // check the body
674 if( !type_engine_scan1_stmt( env, stmt->body ) )
675 return FALSE;
677 return TRUE;
683 //-----------------------------------------------------------------------------
684 // name: type_engine_scan1_switch()
685 // desc: ...
686 //-----------------------------------------------------------------------------
687 t_CKBOOL type_engine_scan1_switch( Chuck_Env * env, a_Stmt_Switch stmt )
689 // TODO: implement this
690 EM_error2( stmt->linepos, "switch not implemented..." );
692 return FALSE;
698 //-----------------------------------------------------------------------------
699 // name: type_engine_scan1_break()
700 // desc: ...
701 //-----------------------------------------------------------------------------
702 t_CKBOOL type_engine_scan1_break( Chuck_Env * env, a_Stmt_Break br )
704 return TRUE;
710 //-----------------------------------------------------------------------------
711 // name: type_engine_scan1_continue()
712 // desc: ...
713 //-----------------------------------------------------------------------------
714 t_CKBOOL type_engine_scan1_continue( Chuck_Env * env, a_Stmt_Continue cont )
716 return TRUE;
722 //-----------------------------------------------------------------------------
723 // name: type_engine_scan1_return()
724 // desc: ...
725 //-----------------------------------------------------------------------------
726 t_CKBOOL type_engine_scan1_return( Chuck_Env * env, a_Stmt_Return stmt )
728 t_CKBOOL ret = FALSE;
730 // check the type of the return
731 if( stmt->val )
732 ret = type_engine_scan1_exp( env, stmt->val );
733 else
734 ret = TRUE;
736 return ret;
742 //-----------------------------------------------------------------------------
743 // name: type_engine_scan1_code_segment()
744 // desc: ...
745 //-----------------------------------------------------------------------------
746 t_CKBOOL type_engine_scan1_code_segment( Chuck_Env * env, a_Stmt_Code stmt,
747 t_CKBOOL push )
749 // class
750 env->class_scope++;
751 // push
752 if( push ) env->curr->value.push(); // env->context->nspc.value.push();
753 // do it
754 t_CKBOOL t = type_engine_scan1_stmt_list( env, stmt->stmt_list );
755 // pop
756 if( push ) env->curr->value.pop(); // env->context->nspc.value.pop();
757 // class
758 env->class_scope--;
760 return t;
766 //-----------------------------------------------------------------------------
767 // name: type_engine_scan1_exp()
768 // desc: ...
769 //-----------------------------------------------------------------------------
770 t_CKBOOL type_engine_scan1_exp( Chuck_Env * env, a_Exp exp )
772 a_Exp curr = exp;
773 t_CKBOOL ret = TRUE;
775 // loop through parallel expressions
776 while( curr )
778 // examine the syntax
779 switch( curr->s_type )
781 case ae_exp_binary:
782 ret = type_engine_scan1_exp_binary( env, &curr->binary );
783 break;
785 case ae_exp_unary:
786 ret = type_engine_scan1_exp_unary( env, &curr->unary );
787 break;
789 case ae_exp_cast:
790 ret = type_engine_scan1_exp_cast( env, &curr->cast );
791 break;
793 case ae_exp_postfix:
794 ret = type_engine_scan1_exp_postfix( env, &curr->postfix );
795 break;
797 case ae_exp_dur:
798 ret = type_engine_scan1_exp_dur( env, &curr->dur );
799 break;
801 case ae_exp_primary:
802 ret = type_engine_scan1_exp_primary( env, &curr->primary );
803 break;
805 case ae_exp_array:
806 ret = type_engine_scan1_exp_array( env, &curr->array );
807 break;
809 case ae_exp_func_call:
810 ret = type_engine_scan1_exp_func_call( env, &curr->func_call );
811 break;
813 case ae_exp_dot_member:
814 ret = type_engine_scan1_exp_dot_member( env, &curr->dot_member );
815 break;
817 case ae_exp_if:
818 ret = type_engine_scan1_exp_if( env, &curr->exp_if );
819 break;
821 case ae_exp_decl:
822 ret = type_engine_scan1_exp_decl( env, &curr->decl );
823 break;
825 default:
826 EM_error2( curr->linepos,
827 "internal compiler error - no expression type '%i'...",
828 curr->s_type );
829 return FALSE;
832 // error
833 if( !ret )
834 return FALSE;
836 // advance to next expression
837 curr = curr->next;
840 // return type
841 return ret;
847 //-----------------------------------------------------------------------------
848 // name: type_engine_scan1_exp_binary()
849 // desc: ...
850 //-----------------------------------------------------------------------------
851 t_CKBOOL type_engine_scan1_exp_binary( Chuck_Env * env, a_Exp_Binary binary )
853 a_Exp cl = binary->lhs, cr = binary->rhs;
855 // type check the lhs and rhs
856 t_CKBOOL left = type_engine_scan1_exp( env, cl );
857 t_CKBOOL right = type_engine_scan1_exp( env, cr);
859 // if either fails, then return FALSE
860 if( !left || !right )
861 return FALSE;
863 // cross chuck
864 while( cr )
866 // type check the pair
867 if( !type_engine_scan1_op( env, binary->op, cl, cr, binary ) )
868 return FALSE;
870 cr = cr->next;
873 return TRUE;
879 //-----------------------------------------------------------------------------
880 // name: type_engine_scan1_op()
881 // desc: ...
882 //-----------------------------------------------------------------------------
883 t_CKBOOL type_engine_scan1_op( Chuck_Env * env, ae_Operator op, a_Exp lhs, a_Exp rhs,
884 a_Exp_Binary binary )
886 // TODO: check for static here
888 return TRUE;
894 //-----------------------------------------------------------------------------
895 // name: type_engine_scan1_op_chuck()
896 // desc: ...
897 //-----------------------------------------------------------------------------
898 t_CKBOOL type_engine_scan1_op_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs,
899 a_Exp_Binary binary )
901 return TRUE;
907 //-----------------------------------------------------------------------------
908 // name: type_engine_scan1_op_unchuck()
909 // desc: ...
910 //-----------------------------------------------------------------------------
911 t_CKBOOL type_engine_scan1_op_unchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs )
913 return TRUE;
919 //-----------------------------------------------------------------------------
920 // name: type_engine_scan1_op_upchuck()
921 // desc: ...
922 //-----------------------------------------------------------------------------
923 t_CKBOOL type_engine_scan1_op_upchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs )
925 return TRUE;
931 //-----------------------------------------------------------------------------
932 // name: type_engine_scan1_op_at_chuck()
933 // desc: ...
934 //-----------------------------------------------------------------------------
935 t_CKBOOL type_engine_scan1_op_at_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs )
937 return TRUE;
943 //-----------------------------------------------------------------------------
944 // name: type_engine_scan1_exp_unary()
945 // desc: ...
946 //-----------------------------------------------------------------------------
947 t_CKBOOL type_engine_scan1_exp_unary( Chuck_Env * env, a_Exp_Unary unary )
949 return TRUE;
955 //-----------------------------------------------------------------------------
956 // name: type_engine_scan1_exp_primary()
957 // desc: ...
958 //-----------------------------------------------------------------------------
959 t_CKBOOL type_engine_scan1_exp_primary( Chuck_Env * env, a_Exp_Primary exp )
961 return TRUE;
967 //-----------------------------------------------------------------------------
968 // name: type_engine_scan1_exp_array_lit()
969 // desc: ...
970 //-----------------------------------------------------------------------------
971 t_CKBOOL type_engine_scan1_exp_array_lit( Chuck_Env * env, a_Exp_Primary exp )
973 // verify there are no errors from the parser...
974 if( !verify_array( exp->array ) )
975 return FALSE;
977 return TRUE;
983 //-----------------------------------------------------------------------------
984 // name: type_engine_scan1_exp_cast()
985 // desc: ...
986 //-----------------------------------------------------------------------------
987 t_CKBOOL type_engine_scan1_exp_cast( Chuck_Env * env, a_Exp_Cast cast )
989 // check the exp
990 t_CKBOOL t = type_engine_scan1_exp( env, cast->exp );
991 if( !t ) return FALSE;
993 return TRUE;
999 //-----------------------------------------------------------------------------
1000 // name: type_engine_scan1_exp_dur()
1001 // desc: ...
1002 //-----------------------------------------------------------------------------
1003 t_CKBOOL type_engine_scan1_exp_dur( Chuck_Env * env, a_Exp_Dur dur )
1005 // type check the two components
1006 t_CKBOOL base = type_engine_scan1_exp( env, dur->base );
1007 t_CKBOOL unit = type_engine_scan1_exp( env, dur->unit );
1009 // make sure both type check
1010 if( !base || !unit ) return FALSE;
1012 return TRUE;
1018 //-----------------------------------------------------------------------------
1019 // name: type_engine_scan1_exp_postfix()
1020 // desc: ...
1021 //-----------------------------------------------------------------------------
1022 t_CKBOOL type_engine_scan1_exp_postfix( Chuck_Env * env, a_Exp_Postfix postfix )
1024 // check the exp
1025 t_CKBOOL t = type_engine_scan1_exp( env, postfix->exp );
1026 if( !t ) return FALSE;
1028 // syntax
1029 // TODO: figure out ++/--
1030 switch( postfix->op )
1032 case ae_op_plusplus:
1033 case ae_op_minusminus:
1034 // assignable?
1035 if( postfix->exp->s_meta != ae_meta_var )
1037 EM_error2( postfix->exp->linepos,
1038 "postfix operator '%s' cannot be used on non-mutable data-type...",
1039 op2str( postfix->op ) );
1040 return FALSE;
1043 // TODO: mark somewhere we need to post increment
1045 return TRUE;
1046 break;
1048 default:
1049 // no match
1050 EM_error2( postfix->linepos,
1051 "internal compiler error (pre-scan): unrecognized postfix '%i'", postfix->op );
1052 return FALSE;
1055 return TRUE;
1061 //-----------------------------------------------------------------------------
1062 // name: type_engine_scan1_exp_if()
1063 // desc: ...
1064 //-----------------------------------------------------------------------------
1065 t_CKBOOL type_engine_scan1_exp_if( Chuck_Env * env, a_Exp_If exp_if )
1067 // check the components
1068 t_CKBOOL cond = type_engine_scan1_exp( env, exp_if->cond );
1069 t_CKBOOL if_exp = type_engine_scan1_exp( env, exp_if->if_exp );
1070 t_CKBOOL else_exp = type_engine_scan1_exp( env, exp_if->else_exp );
1072 // make sure everything good
1073 if( !cond || !if_exp || !else_exp ) return FALSE;
1075 return TRUE;
1081 //-----------------------------------------------------------------------------
1082 // name: type_engine_scan1_array_subscripts( )
1083 // desc: ...
1084 //-----------------------------------------------------------------------------
1085 t_CKBOOL type_engine_scan1_array_subscripts( Chuck_Env * env, a_Exp exp_list )
1087 return TRUE;
1093 //-----------------------------------------------------------------------------
1094 // name: type_engine_scan1_exp_decl( )
1095 // desc: ...
1096 //-----------------------------------------------------------------------------
1097 t_CKBOOL type_engine_scan1_exp_decl( Chuck_Env * env, a_Exp_Decl decl )
1099 a_Var_Decl_List list = decl->var_decl_list;
1100 a_Var_Decl var_decl = NULL;
1102 // look up the type
1103 // TODO: handle T a, b, c...
1104 // TODO: do we climb?
1105 t_CKTYPE t = type_engine_find_type( env, decl->type->xid );
1106 // if not found, try to resolve
1107 if( !t )
1109 // resolve
1110 EM_error2( decl->linepos, "... in declaration ..." );
1111 return FALSE;
1114 // loop through the variables
1115 while( list != NULL )
1117 // get the decl
1118 var_decl = list->var_decl;
1119 // count
1120 decl->num_var_decls++;
1122 // scan if array
1123 if( var_decl->array != NULL )
1125 // verify there are no errors from the parser...
1126 if( !verify_array( var_decl->array ) )
1127 return FALSE;
1129 // may be partial and empty []
1130 if( var_decl->array->exp_list )
1132 // type check the exp
1133 if( !type_engine_scan1_exp( env, var_decl->array->exp_list ) )
1134 return FALSE;
1135 // make sure types are of int
1136 if( !type_engine_scan1_array_subscripts( env, var_decl->array->exp_list ) )
1137 return FALSE;
1141 // the next var decl
1142 list = list->next;
1145 // remember : decl->ck_type = t;
1146 SAFE_REF_ASSIGN( decl->ck_type, t );
1148 return TRUE;
1154 //-----------------------------------------------------------------------------
1155 // name: type_engine_scan1_exp_func_call()
1156 // desc: ...
1157 //-----------------------------------------------------------------------------
1158 t_CKBOOL type_engine_scan1_exp_func_call( Chuck_Env * env, a_Exp exp_func, a_Exp args,
1159 t_CKFUNC & ck_func, int linepos )
1161 // Chuck_Func * func = NULL;
1162 // Chuck_Func * up = NULL;
1164 // type check the func
1165 t_CKBOOL f = type_engine_scan1_exp( env, exp_func );
1166 if( !f ) return FALSE;
1168 // check the arguments
1169 if( args )
1171 t_CKBOOL a = type_engine_scan1_exp( env, args );
1172 if( !a ) return FALSE;
1175 return TRUE;
1181 //-----------------------------------------------------------------------------
1182 // name: type_engine_scan1_exp_func_call()
1183 // desc: ...
1184 //-----------------------------------------------------------------------------
1185 t_CKBOOL type_engine_scan1_exp_func_call( Chuck_Env * env, a_Exp_Func_Call func_call )
1187 // type check it
1188 return type_engine_scan1_exp_func_call( env, func_call->func, func_call->args,
1189 func_call->ck_func, func_call->linepos );
1195 //-----------------------------------------------------------------------------
1196 // name: type_engine_scan1_exp_dot_member()
1197 // desc: ...
1198 //-----------------------------------------------------------------------------
1199 t_CKBOOL type_engine_scan1_exp_dot_member( Chuck_Env * env, a_Exp_Dot_Member member )
1201 // type check the base
1202 t_CKBOOL base = type_engine_scan1_exp( env, member->base );
1203 if( !base ) return FALSE;
1205 return TRUE;
1211 //-----------------------------------------------------------------------------
1212 // name: type_engine_scan1_exp_array()
1213 // desc: ...
1214 //-----------------------------------------------------------------------------
1215 t_CKBOOL type_engine_scan1_exp_array( Chuck_Env * env, a_Exp_Array array )
1217 // verify there are no errors from the parser...
1218 if( !verify_array( array->indices ) )
1219 return FALSE;
1221 // type check the base
1222 t_CKBOOL base = type_engine_scan1_exp( env, array->base );
1223 if( !base ) return FALSE;
1225 // type check the index
1226 t_CKBOOL index = type_engine_scan1_exp( env, array->indices->exp_list );
1227 if( !index ) return FALSE;
1229 // cycle through each exp
1230 // a_Exp e = array->indices->exp_list;
1231 // count the dimension
1232 // t_CKUINT depth = 0;
1234 return TRUE;
1240 //-----------------------------------------------------------------------------
1241 // name: type_engine_scan1_class_def()
1242 // desc: ...
1243 //-----------------------------------------------------------------------------
1244 t_CKBOOL type_engine_scan1_class_def( Chuck_Env * env, a_Class_Def class_def )
1246 // the return type
1247 t_CKBOOL ret = TRUE;
1248 // the class body
1249 a_Class_Body body = class_def->body;
1250 // the class
1251 Chuck_Type * the_class = class_def->type;
1253 // set the new type as current
1254 env->nspc_stack.push_back( env->curr );
1255 env->curr = the_class->info;
1256 // push the class def
1257 env->class_stack.push_back( env->class_def );
1258 env->class_def = the_class;
1259 // reset the nest list
1260 env->class_scope = 0;
1262 // type check the body
1263 while( body && ret )
1265 // check the section
1266 switch( body->section->s_type )
1268 case ae_section_stmt:
1269 // do the statements
1270 ret = type_engine_scan1_stmt_list( env, body->section->stmt_list );
1271 break;
1273 case ae_section_func:
1274 // do the function
1275 ret = type_engine_scan1_func_def( env, body->section->func_def );
1276 break;
1278 case ae_section_class:
1279 // do the class
1280 ret = type_engine_scan1_class_def( env, body->section->class_def );
1281 break;
1284 // move to the next section
1285 body = body->next;
1288 // pop the class
1289 env->class_def = env->class_stack.back();
1290 env->class_stack.pop_back();
1291 // pop the namesapce
1292 env->curr = env->nspc_stack.back();
1293 env->nspc_stack.pop_back();
1295 return ret;
1301 //-----------------------------------------------------------------------------
1302 // name: type_engine_scan1_func_def()
1303 // desc: ...
1304 //-----------------------------------------------------------------------------
1305 t_CKBOOL type_engine_scan1_func_def( Chuck_Env * env, a_Func_Def f )
1307 a_Arg_List arg_list = NULL;
1308 t_CKUINT count = 0;
1309 // t_CKBOOL has_code = FALSE;
1310 // Chuck_Value * v = NULL;
1312 // if not imported, then check to make sure no reserved word conflict
1313 // if( f->s_type != ae_func_builtin ) // TODO: fix this
1315 // check if reserved
1316 if( type_engine_check_reserved( env, f->name, f->linepos ) )
1318 EM_error2( f->linepos, "...in function definition '%s'",
1319 S_name(f->name) );
1320 return FALSE;
1323 // look up the return type
1324 f->ret_type = type_engine_find_type( env, f->type_decl->xid );
1325 // no return type
1326 if( !f->ret_type )
1328 // TODO: try to resolve
1329 EM_error2( f->linepos, "... in return type of function '%s' ...", S_name(f->name) );
1330 goto error;
1332 // check if array
1333 if( f->type_decl->array != NULL )
1335 // verify there are no errors from the parser...
1336 if( !verify_array( f->type_decl->array ) )
1337 return FALSE;
1339 Chuck_Type * t = NULL;
1340 Chuck_Type * t2 = f->ret_type;
1341 // should be partial and empty []
1342 if( f->type_decl->array->exp_list )
1344 EM_error2( f->type_decl->array->linepos, "function '%s':", S_name(f->name) );
1345 EM_error2( f->type_decl->array->linepos, "return array type must be defined with empty []'s" );
1346 return FALSE;
1349 // create the new array type
1350 t = new_array_type(
1351 env, // the env
1352 &t_array, // the array base class, usually &t_array
1353 f->type_decl->array->depth, // the depth of the new type
1354 t2, // the 'array_type'
1355 env->curr // the owner namespace
1358 // TODO: verify
1359 // set ref
1360 f->type_decl->ref = TRUE;
1361 // replace type : f->ret_type = t
1362 SAFE_REF_ASSIGN( f->ret_type, t );
1365 // look up types for the function arguments
1366 arg_list = f->arg_list;
1367 // count
1368 count = 1;
1369 // loop over arguments
1370 while( arg_list )
1372 // look up in type table
1373 arg_list->type = type_engine_find_type( env, arg_list->type_decl->xid );
1374 // if not there, try to resolve
1375 if( !arg_list->type )
1377 // TODO: try to resolve
1378 // EM_error2( arg_list->linepos, "in function '%s':", S_name(f->name) );
1379 EM_error2( arg_list->linepos,
1380 "... in argument %i '%s' of function '%s(.)' ...",
1381 count, S_name(arg_list->var_decl->xid), S_name(f->name) );
1382 goto error;
1385 // count
1386 count++;
1387 // next arg
1388 arg_list = arg_list->next;
1391 // scan the code for types that need resolution
1392 assert( f->code == NULL || f->code->s_type == ae_stmt_code );
1393 if( f->code && !type_engine_scan1_code_segment( env, &f->code->stmt_code, FALSE ) )
1395 EM_error2( 0, "...in function '%s'", S_name(f->name) );
1396 goto error;
1399 return TRUE;
1401 error:
1403 return FALSE;
1409 //-----------------------------------------------------------------------------
1410 // name: type_engine_scan2_prog()
1411 // desc: data in env should be ready
1412 //-----------------------------------------------------------------------------
1413 t_CKBOOL type_engine_scan2_prog( Chuck_Env * env, a_Program prog,
1414 te_HowMuch how_much )
1416 t_CKBOOL ret = TRUE;
1418 if( !prog )
1419 return FALSE;
1421 // log
1422 EM_log( CK_LOG_FINER, "(pass 2) type verification scan '%s'...",
1423 env->context->filename.c_str() );
1424 // push indent
1425 EM_pushlog();
1426 // log how much
1427 EM_log( CK_LOG_FINER, "target: %s", howmuch2str( how_much ) );
1429 // go through each of the program sections
1430 while( prog && ret )
1432 switch( prog->section->s_type )
1434 case ae_section_stmt:
1435 // if classes only, then skip
1436 if( how_much == te_do_classes_only ) break;
1437 // scan the statements
1438 ret = type_engine_scan2_stmt_list( env, prog->section->stmt_list );
1439 break;
1441 case ae_section_func:
1442 // if classes only, then skip
1443 if( how_much == te_do_classes_only ) break;
1444 // scan the function definition
1445 ret = type_engine_scan2_func_def( env, prog->section->func_def );
1446 break;
1448 case ae_section_class:
1449 // if no classes, then skip
1450 if( how_much == te_do_no_classes ) break;
1451 // scan the class definition
1452 ret = type_engine_scan2_class_def( env, prog->section->class_def );
1453 break;
1455 default:
1456 EM_error2( prog->linepos,
1457 "internal error: unrecognized program section in type checker pre-scan..." );
1458 ret = FALSE;
1459 break;
1462 prog = prog->next;
1465 // pop indent
1466 EM_poplog();
1468 return ret;
1474 //-----------------------------------------------------------------------------
1475 // name: type_engine_scan2_stmt_list()
1476 // desc: ...
1477 //-----------------------------------------------------------------------------
1478 t_CKBOOL type_engine_scan2_stmt_list( Chuck_Env * env, a_Stmt_List list )
1480 // type check the stmt_list
1481 while( list )
1483 // the current statement
1484 if( !type_engine_scan2_stmt( env, list->stmt ) )
1485 return FALSE;
1487 // advance to the next statement
1488 list = list->next;
1491 return TRUE;
1497 //-----------------------------------------------------------------------------
1498 // name: type_engine_scan2_stmt(()
1499 // desc: ...
1500 //-----------------------------------------------------------------------------
1501 t_CKBOOL type_engine_scan2_stmt( Chuck_Env * env, a_Stmt stmt )
1503 t_CKBOOL ret = FALSE;
1505 if( !stmt )
1506 return TRUE;
1508 // the type of stmt
1509 switch( stmt->s_type )
1511 case ae_stmt_if:
1512 // count scope to help determine class member
1513 env->class_scope++;
1514 env->curr->value.push();
1515 ret = type_engine_scan2_if( env, &stmt->stmt_if );
1516 env->curr->value.pop();
1517 env->class_scope--;
1518 break;
1520 case ae_stmt_for:
1521 env->class_scope++;
1522 env->curr->value.push();
1523 ret = type_engine_scan2_for( env, &stmt->stmt_for );
1524 env->curr->value.pop();
1525 env->class_scope--;
1526 break;
1528 case ae_stmt_while:
1529 env->class_scope++;
1530 env->curr->value.push();
1531 ret = type_engine_scan2_while( env, &stmt->stmt_while );
1532 env->curr->value.pop();
1533 env->class_scope--;
1534 break;
1536 case ae_stmt_until:
1537 env->class_scope++;
1538 env->curr->value.push();
1539 ret = type_engine_scan2_until( env, &stmt->stmt_until );
1540 env->curr->value.pop();
1541 env->class_scope--;
1542 break;
1544 case ae_stmt_loop:
1545 env->class_scope++;
1546 env->curr->value.push();
1547 ret = type_engine_scan2_loop( env, &stmt->stmt_loop );
1548 env->curr->value.pop();
1549 env->class_scope--;
1550 break;
1552 case ae_stmt_exp:
1553 ret = type_engine_scan2_exp( env, stmt->stmt_exp );
1554 break;
1556 case ae_stmt_return:
1557 ret = type_engine_scan2_return( env, &stmt->stmt_return );
1558 break;
1560 case ae_stmt_code:
1561 env->class_scope++;
1562 ret = type_engine_scan2_code_segment( env, &stmt->stmt_code );
1563 env->class_scope--;
1564 break;
1566 case ae_stmt_break:
1567 ret = type_engine_scan2_break( env, &stmt->stmt_break );
1568 break;
1570 case ae_stmt_continue:
1571 ret = type_engine_scan2_continue( env, &stmt->stmt_continue );
1572 break;
1574 case ae_stmt_switch:
1575 env->class_scope++;
1576 ret = type_engine_scan2_switch( env, &stmt->stmt_switch );
1577 env->class_scope--;
1578 break;
1580 case ae_stmt_case:
1581 // ret = type_engine_scan2_case( env, &stmt->stmt_case );
1582 break;
1584 case ae_stmt_gotolabel:
1585 // ret = type_engine_scan2_gotolabel( env, &stmt->goto_label );
1586 break;
1588 default:
1589 EM_error2( stmt->linepos,
1590 "internal compiler error (pre-scan) - no stmt type '%i'!", stmt->s_type );
1591 ret = FALSE;
1592 break;
1595 return ret;
1601 //-----------------------------------------------------------------------------
1602 // name: type_engine_scan2_if()
1603 // desc: ...
1604 //-----------------------------------------------------------------------------
1605 t_CKBOOL type_engine_scan2_if( Chuck_Env * env, a_Stmt_If stmt )
1607 // check the conditional
1608 if( !type_engine_scan2_exp( env, stmt->cond ) )
1609 return FALSE;
1611 // TODO: ensure that conditional has valid type
1613 // check if
1614 if( !type_engine_scan2_stmt( env, stmt->if_body ) )
1615 return FALSE;
1617 // check else, if there is one
1618 if( stmt->else_body )
1619 if( !type_engine_scan2_stmt( env, stmt->else_body ) )
1620 return FALSE;
1622 return TRUE;
1628 //-----------------------------------------------------------------------------
1629 // name: type_engine_scan2_for()
1630 // desc: ...
1631 //-----------------------------------------------------------------------------
1632 t_CKBOOL type_engine_scan2_for( Chuck_Env * env, a_Stmt_For stmt )
1634 // check the initial
1635 if( !type_engine_scan2_stmt( env, stmt->c1 ) )
1636 return FALSE;
1638 // check the conditional
1639 if( !type_engine_scan2_stmt( env, stmt->c2 ) )
1640 return FALSE;
1642 // TODO: same as if - check conditional type valid
1644 // check the post
1645 if( stmt->c3 && !type_engine_scan2_exp( env, stmt->c3 ) )
1646 return FALSE;
1648 // check body
1649 if( !type_engine_scan2_stmt( env, stmt->body ) )
1650 return FALSE;
1652 return TRUE;
1658 //-----------------------------------------------------------------------------
1659 // name: type_engine_scan2_while()
1660 // desc: ...
1661 //-----------------------------------------------------------------------------
1662 t_CKBOOL type_engine_scan2_while( Chuck_Env * env, a_Stmt_While stmt )
1664 // check the conditional
1665 if( !type_engine_scan2_exp( env, stmt->cond ) )
1666 return FALSE;
1668 // TODO: same as if - ensure the type in conditional is valid
1670 // check the body
1671 if( !type_engine_scan2_stmt( env, stmt->body ) )
1672 return FALSE;
1674 return TRUE;
1680 //-----------------------------------------------------------------------------
1681 // name: type_engine_scan2_until()
1682 // desc: ...
1683 //-----------------------------------------------------------------------------
1684 t_CKBOOL type_engine_scan2_until( Chuck_Env * env, a_Stmt_Until stmt )
1686 // check the conditional
1687 if( !type_engine_scan2_exp( env, stmt->cond ) )
1688 return FALSE;
1690 // TODO: same as if - ensure the type in conditional is valid
1692 // check the body
1693 if( !type_engine_scan2_stmt( env, stmt->body ) )
1694 return FALSE;
1696 return TRUE;
1702 //-----------------------------------------------------------------------------
1703 // name: type_engine_scan2_loop()
1704 // desc: ...
1705 //-----------------------------------------------------------------------------
1706 t_CKBOOL type_engine_scan2_loop( Chuck_Env * env, a_Stmt_Loop stmt )
1708 // check the conditional
1709 if( !type_engine_scan2_exp( env, stmt->cond ) )
1710 return FALSE;
1712 // TODO: same as if - ensure the type in conditional is valid
1714 // check the body
1715 if( !type_engine_scan2_stmt( env, stmt->body ) )
1716 return FALSE;
1718 return TRUE;
1724 //-----------------------------------------------------------------------------
1725 // name: type_engine_scan2_switch()
1726 // desc: ...
1727 //-----------------------------------------------------------------------------
1728 t_CKBOOL type_engine_scan2_switch( Chuck_Env * env, a_Stmt_Switch stmt )
1730 // TODO: implement this
1731 EM_error2( stmt->linepos, "switch not implemented..." );
1733 return FALSE;
1739 //-----------------------------------------------------------------------------
1740 // name: type_engine_scan2_break()
1741 // desc: ...
1742 //-----------------------------------------------------------------------------
1743 t_CKBOOL type_engine_scan2_break( Chuck_Env * env, a_Stmt_Break br )
1745 return TRUE;
1751 //-----------------------------------------------------------------------------
1752 // name: type_engine_scan2_continue()
1753 // desc: ...
1754 //-----------------------------------------------------------------------------
1755 t_CKBOOL type_engine_scan2_continue( Chuck_Env * env, a_Stmt_Continue cont )
1757 return TRUE;
1763 //-----------------------------------------------------------------------------
1764 // name: type_engine_scan2_return()
1765 // desc: ...
1766 //-----------------------------------------------------------------------------
1767 t_CKBOOL type_engine_scan2_return( Chuck_Env * env, a_Stmt_Return stmt )
1769 t_CKBOOL ret = FALSE;
1771 // check the type of the return
1772 if( stmt->val )
1773 ret = type_engine_scan2_exp( env, stmt->val );
1774 else
1775 ret = TRUE;
1777 return ret;
1783 //-----------------------------------------------------------------------------
1784 // name: type_engine_scan2_code_segment()
1785 // desc: ...
1786 //-----------------------------------------------------------------------------
1787 t_CKBOOL type_engine_scan2_code_segment( Chuck_Env * env, a_Stmt_Code stmt,
1788 t_CKBOOL push )
1790 // class
1791 env->class_scope++;
1792 // push
1793 if( push ) env->curr->value.push(); // env->context->nspc.value.push();
1794 // do it
1795 t_CKBOOL t = type_engine_scan2_stmt_list( env, stmt->stmt_list );
1796 // pop
1797 if( push ) env->curr->value.pop(); // env->context->nspc.value.pop();
1798 // class
1799 env->class_scope--;
1801 return t;
1807 //-----------------------------------------------------------------------------
1808 // name: type_engine_scan2_exp()
1809 // desc: ...
1810 //-----------------------------------------------------------------------------
1811 t_CKBOOL type_engine_scan2_exp( Chuck_Env * env, a_Exp exp )
1813 a_Exp curr = exp;
1814 t_CKBOOL ret = TRUE;
1816 // loop through parallel expressions
1817 while( curr )
1819 // examine the syntax
1820 switch( curr->s_type )
1822 case ae_exp_binary:
1823 ret = type_engine_scan2_exp_binary( env, &curr->binary );
1824 break;
1826 case ae_exp_unary:
1827 ret = type_engine_scan2_exp_unary( env, &curr->unary );
1828 break;
1830 case ae_exp_cast:
1831 ret = type_engine_scan2_exp_cast( env, &curr->cast );
1832 break;
1834 case ae_exp_postfix:
1835 ret = type_engine_scan2_exp_postfix( env, &curr->postfix );
1836 break;
1838 case ae_exp_dur:
1839 ret = type_engine_scan2_exp_dur( env, &curr->dur );
1840 break;
1842 case ae_exp_primary:
1843 ret = type_engine_scan2_exp_primary( env, &curr->primary );
1844 break;
1846 case ae_exp_array:
1847 ret = type_engine_scan2_exp_array( env, &curr->array );
1848 break;
1850 case ae_exp_func_call:
1851 ret = type_engine_scan2_exp_func_call( env, &curr->func_call );
1852 break;
1854 case ae_exp_dot_member:
1855 ret = type_engine_scan2_exp_dot_member( env, &curr->dot_member );
1856 break;
1858 case ae_exp_if:
1859 ret = type_engine_scan2_exp_if( env, &curr->exp_if );
1860 break;
1862 case ae_exp_decl:
1863 ret = type_engine_scan2_exp_decl( env, &curr->decl );
1864 break;
1866 default:
1867 EM_error2( curr->linepos,
1868 "internal compiler error - no expression type '%i'...",
1869 curr->s_type );
1870 return FALSE;
1873 // error
1874 if( !ret )
1875 return FALSE;
1877 // advance to next expression
1878 curr = curr->next;
1881 // return type
1882 return ret;
1888 //-----------------------------------------------------------------------------
1889 // name: type_engine_scan2_exp_binary()
1890 // desc: ...
1891 //-----------------------------------------------------------------------------
1892 t_CKBOOL type_engine_scan2_exp_binary( Chuck_Env * env, a_Exp_Binary binary )
1894 a_Exp cl = binary->lhs, cr = binary->rhs;
1896 // type check the lhs and rhs
1897 t_CKBOOL left = type_engine_scan2_exp( env, cl );
1898 t_CKBOOL right = type_engine_scan2_exp( env, cr);
1900 // if either fails, then return FALSE
1901 if( !left || !right )
1902 return FALSE;
1904 // cross chuck
1905 while( cr )
1907 // type check the pair
1908 if( !type_engine_scan2_op( env, binary->op, cl, cr, binary ) )
1909 return FALSE;
1911 cr = cr->next;
1914 return TRUE;
1920 //-----------------------------------------------------------------------------
1921 // name: type_engine_scan2_op()
1922 // desc: ...
1923 //-----------------------------------------------------------------------------
1924 t_CKBOOL type_engine_scan2_op( Chuck_Env * env, ae_Operator op, a_Exp lhs, a_Exp rhs,
1925 a_Exp_Binary binary )
1927 // TODO: check for static here
1929 return TRUE;
1935 //-----------------------------------------------------------------------------
1936 // name: type_engine_scan2_op_chuck()
1937 // desc: ...
1938 //-----------------------------------------------------------------------------
1939 t_CKBOOL type_engine_scan2_op_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs,
1940 a_Exp_Binary binary )
1942 return TRUE;
1948 //-----------------------------------------------------------------------------
1949 // name: type_engine_scan2_op_unchuck()
1950 // desc: ...
1951 //-----------------------------------------------------------------------------
1952 t_CKBOOL type_engine_scan2_op_unchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs )
1954 return TRUE;
1960 //-----------------------------------------------------------------------------
1961 // name: type_engine_scan2_op_upchuck()
1962 // desc: ...
1963 //-----------------------------------------------------------------------------
1964 t_CKBOOL type_engine_scan2_op_upchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs )
1966 return TRUE;
1972 //-----------------------------------------------------------------------------
1973 // name: type_engine_scan2_op_at_chuck()
1974 // desc: ...
1975 //-----------------------------------------------------------------------------
1976 t_CKBOOL type_engine_scan2_op_at_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs )
1978 return TRUE;
1984 //-----------------------------------------------------------------------------
1985 // name: type_engine_scan2_exp_unary()
1986 // desc: ...
1987 //-----------------------------------------------------------------------------
1988 t_CKBOOL type_engine_scan2_exp_unary( Chuck_Env * env, a_Exp_Unary unary )
1990 return TRUE;
1996 //-----------------------------------------------------------------------------
1997 // name: type_engine_scan2_exp_primary()
1998 // desc: ...
1999 //-----------------------------------------------------------------------------
2000 t_CKBOOL type_engine_scan2_exp_primary( Chuck_Env * env, a_Exp_Primary exp )
2002 return TRUE;
2008 //-----------------------------------------------------------------------------
2009 // name: type_engine_scan2_exp_array_lit()
2010 // desc: ...
2011 //-----------------------------------------------------------------------------
2012 t_CKBOOL type_engine_scan2_exp_array_lit( Chuck_Env * env, a_Exp_Primary exp )
2014 // verify there are no errors from the parser...
2015 if( !verify_array( exp->array ) )
2016 return FALSE;
2018 return TRUE;
2024 //-----------------------------------------------------------------------------
2025 // name: type_engine_scan2_exp_cast()
2026 // desc: ...
2027 //-----------------------------------------------------------------------------
2028 t_CKBOOL type_engine_scan2_exp_cast( Chuck_Env * env, a_Exp_Cast cast )
2030 // check the exp
2031 t_CKBOOL t = type_engine_scan2_exp( env, cast->exp );
2032 if( !t ) return FALSE;
2034 return TRUE;
2040 //-----------------------------------------------------------------------------
2041 // name: type_engine_scan2_exp_dur()
2042 // desc: ...
2043 //-----------------------------------------------------------------------------
2044 t_CKBOOL type_engine_scan2_exp_dur( Chuck_Env * env, a_Exp_Dur dur )
2046 // type check the two components
2047 t_CKBOOL base = type_engine_scan2_exp( env, dur->base );
2048 t_CKBOOL unit = type_engine_scan2_exp( env, dur->unit );
2050 // make sure both type check
2051 if( !base || !unit ) return FALSE;
2053 return TRUE;
2059 //-----------------------------------------------------------------------------
2060 // name: type_engine_scan2_exp_postfix()
2061 // desc: ...
2062 //-----------------------------------------------------------------------------
2063 t_CKBOOL type_engine_scan2_exp_postfix( Chuck_Env * env, a_Exp_Postfix postfix )
2065 // check the exp
2066 t_CKBOOL t = type_engine_scan2_exp( env, postfix->exp );
2067 if( !t ) return FALSE;
2069 // syntax
2070 // TODO: figure out ++/--
2071 switch( postfix->op )
2073 case ae_op_plusplus:
2074 case ae_op_minusminus:
2075 // assignable?
2076 if( postfix->exp->s_meta != ae_meta_var )
2078 EM_error2( postfix->exp->linepos,
2079 "postfix operator '%s' cannot be used on non-mutable data-type...",
2080 op2str( postfix->op ) );
2081 return FALSE;
2084 // TODO: mark somewhere we need to post increment
2086 return TRUE;
2087 break;
2089 default:
2090 // no match
2091 EM_error2( postfix->linepos,
2092 "internal compiler error (pre-scan): unrecognized postfix '%i'", postfix->op );
2093 return FALSE;
2096 return TRUE;
2102 //-----------------------------------------------------------------------------
2103 // name: type_engine_scan2_exp_if()
2104 // desc: ...
2105 //-----------------------------------------------------------------------------
2106 t_CKBOOL type_engine_scan2_exp_if( Chuck_Env * env, a_Exp_If exp_if )
2108 // check the components
2109 t_CKBOOL cond = type_engine_scan2_exp( env, exp_if->cond );
2110 t_CKBOOL if_exp = type_engine_scan2_exp( env, exp_if->if_exp );
2111 t_CKBOOL else_exp = type_engine_scan2_exp( env, exp_if->else_exp );
2113 // make sure everything good
2114 if( !cond || !if_exp || !else_exp ) return FALSE;
2116 return TRUE;
2122 //-----------------------------------------------------------------------------
2123 // name: type_engine_scan2_array_subscripts( )
2124 // desc: ...
2125 //-----------------------------------------------------------------------------
2126 t_CKBOOL type_engine_scan2_array_subscripts( Chuck_Env * env, a_Exp exp_list )
2128 return TRUE;
2134 //-----------------------------------------------------------------------------
2135 // name: type_engine_scan2_exp_decl( )
2136 // desc: ...
2137 //-----------------------------------------------------------------------------
2138 t_CKBOOL type_engine_scan2_exp_decl( Chuck_Env * env, a_Exp_Decl decl )
2140 a_Var_Decl_List list = decl->var_decl_list;
2141 a_Var_Decl var_decl = NULL;
2142 Chuck_Type * type = NULL;
2143 Chuck_Value * value = NULL;
2144 t_CKBOOL do_alloc = TRUE;
2146 // retrieve the type
2147 type = decl->ck_type;
2148 // make sure it's not NULL
2149 assert( type != NULL );
2151 // check to see type is not void
2152 if( type->size == 0 )
2154 EM_error( decl->linepos,
2155 "cannot declare variables of size '0' (i.e. 'void')..." );
2156 return FALSE;
2159 // T @ foo?
2160 do_alloc = !decl->type->ref;
2162 // make sure complete
2163 if( /*!t->is_complete &&*/ do_alloc )
2165 // check to see if class inside itself
2166 if( env->class_def && equals( type, env->class_def ) && env->class_scope == 0 )
2168 EM_error2( decl->linepos,
2169 "...(note: object of type '%s' declared inside itself)",
2170 type->c_name() );
2171 return FALSE;
2175 // primitive
2176 if( (isprim( type ) || isa( type, &t_string )) && decl->type->ref ) // TODO: string
2178 EM_error2( decl->linepos,
2179 "cannot declare references (@) of primitive type '%s'...",
2180 type->c_name() );
2181 EM_error2( decl->linepos,
2182 "...(primitive types: 'int', 'float', 'time', 'dur')" );
2183 return FALSE;
2186 // loop through the variables
2187 while( list != NULL )
2189 // get the decl
2190 var_decl = list->var_decl;
2192 // check if reserved
2193 if( type_engine_check_reserved( env, var_decl->xid, var_decl->linepos ) )
2195 EM_error2( var_decl->linepos,
2196 "...in variable declaration", S_name(var_decl->xid) );
2197 return FALSE;
2200 // check if locally defined
2201 if( env->curr->lookup_value( var_decl->xid, FALSE ) )
2203 EM_error2( var_decl->linepos,
2204 "'%s' has already been defined in the same scope...",
2205 S_name(var_decl->xid) );
2206 return FALSE;
2209 // check if array
2210 if( var_decl->array != NULL )
2212 // verify there are no errors from the parser...
2213 if( !verify_array( var_decl->array ) )
2214 return FALSE;
2216 Chuck_Type * t2 = type;
2217 // may be partial and empty []
2218 if( var_decl->array->exp_list )
2220 // scan2 the exp
2221 if( !type_engine_scan2_exp( env, var_decl->array->exp_list ) )
2222 return FALSE;
2223 // make sure types are of int
2224 if( !type_engine_scan2_array_subscripts( env, var_decl->array->exp_list ) )
2225 return FALSE;
2228 // create the new array type
2229 type = new_array_type(
2230 env, // the env
2231 &t_array, // the array base class, usually &t_array
2232 var_decl->array->depth, // the depth of the new type
2233 t2, // the 'array_type'
2234 env->curr // the owner namespace
2237 // set ref
2238 if( !var_decl->array->exp_list )
2239 decl->type->ref = TRUE;
2241 // set reference : decl->ck_type = type;
2242 SAFE_REF_ASSIGN( decl->ck_type, type );
2245 // enter into value binding
2246 env->curr->value.add( var_decl->xid,
2247 value = env->context->new_Chuck_Value( type, S_name(var_decl->xid) ) );
2249 // remember the owner
2250 value->owner = env->curr;
2251 value->owner_class = env->func ? NULL : env->class_def;
2252 value->is_member = ( env->class_def != NULL &&
2253 env->class_scope == 0 &&
2254 env->func == NULL && !decl->is_static );
2255 value->is_context_global = ( env->class_def == NULL && env->func == NULL );
2256 value->addr = var_decl->addr;
2257 // flag it until the decl is checked
2258 value->is_decl_checked = FALSE;
2260 // remember the value
2261 var_decl->value = value;
2263 // the next var decl
2264 list = list->next;
2267 return TRUE;
2273 //-----------------------------------------------------------------------------
2274 // name: type_engine_scan2_exp_func_call()
2275 // desc: ...
2276 //-----------------------------------------------------------------------------
2277 t_CKBOOL type_engine_scan2_exp_func_call( Chuck_Env * env, a_Exp exp_func, a_Exp args,
2278 t_CKFUNC & ck_func, int linepos )
2280 // Chuck_Func * func = NULL;
2281 // Chuck_Func * up = NULL;
2283 // type check the func
2284 t_CKBOOL f = type_engine_scan2_exp( env, exp_func );
2285 if( !f ) return FALSE;
2287 // check the arguments
2288 if( args )
2290 t_CKBOOL a = type_engine_scan2_exp( env, args );
2291 if( !a ) return FALSE;
2294 return TRUE;
2300 //-----------------------------------------------------------------------------
2301 // name: type_engine_scan2_exp_func_call()
2302 // desc: ...
2303 //-----------------------------------------------------------------------------
2304 t_CKBOOL type_engine_scan2_exp_func_call( Chuck_Env * env, a_Exp_Func_Call func_call )
2306 // type check it
2307 return type_engine_scan2_exp_func_call( env, func_call->func, func_call->args,
2308 func_call->ck_func, func_call->linepos );
2314 //-----------------------------------------------------------------------------
2315 // name: type_engine_scan2_exp_dot_member()
2316 // desc: ...
2317 //-----------------------------------------------------------------------------
2318 t_CKBOOL type_engine_scan2_exp_dot_member( Chuck_Env * env, a_Exp_Dot_Member member )
2320 // type check the base
2321 t_CKBOOL base = type_engine_scan2_exp( env, member->base );
2322 if( !base ) return FALSE;
2324 return TRUE;
2330 //-----------------------------------------------------------------------------
2331 // name: type_engine_scan2_exp_array()
2332 // desc: ...
2333 //-----------------------------------------------------------------------------
2334 t_CKBOOL type_engine_scan2_exp_array( Chuck_Env * env, a_Exp_Array array )
2336 // verify there are no errors from the parser...
2337 if( !verify_array( array->indices ) )
2338 return FALSE;
2340 // type check the base
2341 t_CKBOOL base = type_engine_scan2_exp( env, array->base );
2342 if( !base ) return FALSE;
2344 // type check the index
2345 t_CKBOOL index = type_engine_scan2_exp( env, array->indices->exp_list );
2346 if( !index ) return FALSE;
2348 // cycle through each exp
2349 // a_Exp e = array->indices->exp_list;
2350 // count the dimension
2351 // t_CKUINT depth = 0;
2353 return TRUE;
2359 //-----------------------------------------------------------------------------
2360 // name: type_engine_scan2_class_def()
2361 // desc: ...
2362 //-----------------------------------------------------------------------------
2363 t_CKBOOL type_engine_scan2_class_def( Chuck_Env * env, a_Class_Def class_def )
2365 // the return type
2366 t_CKBOOL ret = TRUE;
2367 // the class body
2368 a_Class_Body body = class_def->body;
2369 // the class
2370 Chuck_Type * the_class = class_def->type;
2371 // make sure
2372 assert( the_class != NULL );
2374 // set the new type as current
2375 env->nspc_stack.push_back( env->curr );
2376 env->curr = the_class->info;
2377 // push the class def
2378 env->class_stack.push_back( env->class_def );
2379 env->class_def = the_class;
2380 // reset the nest list
2381 env->class_scope = 0;
2383 // type check the body
2384 while( body && ret )
2386 // check the section
2387 switch( body->section->s_type )
2389 case ae_section_stmt:
2390 // already flagged as having a constructor or not
2391 ret = type_engine_scan2_stmt_list( env, body->section->stmt_list );
2392 break;
2394 case ae_section_func:
2395 // do function
2396 ret = type_engine_scan2_func_def( env, body->section->func_def );
2397 break;
2399 case ae_section_class:
2400 // do the class
2401 ret = type_engine_scan2_class_def( env, body->section->class_def );
2402 break;
2405 // move to the next section
2406 body = body->next;
2409 // pop the class
2410 env->class_def = env->class_stack.back();
2411 env->class_stack.pop_back();
2412 // pop the namesapce
2413 env->curr = env->nspc_stack.back();
2414 env->nspc_stack.pop_back();
2416 return ret;
2422 //-----------------------------------------------------------------------------
2423 // name: type_engine_scan2_func_def()
2424 // desc: ...
2425 //-----------------------------------------------------------------------------
2426 t_CKBOOL type_engine_scan2_func_def( Chuck_Env * env, a_Func_Def f )
2428 Chuck_Type * type = NULL;
2429 Chuck_Value * value = NULL;
2430 Chuck_Func * func = NULL;
2432 // Chuck_Type * parent = NULL;
2433 Chuck_Value * overload = NULL;
2434 // Chuck_Value * override = NULL;
2435 Chuck_Value * v = NULL;
2436 // Chuck_Func * parent_func = NULL;
2437 a_Arg_List arg_list = NULL;
2438 // t_CKBOOL parent_match = FALSE;
2439 string func_name = S_name(f->name);
2440 string orig_name = func_name;
2441 vector<Chuck_Value *> values;
2442 vector<a_Arg_List> symbols;
2443 t_CKUINT count = 0;
2444 // t_CKBOOL has_code = FALSE; // use this for both user and imported
2446 // see if we are already in a function definition
2447 if( env->func != NULL )
2449 EM_error2( f->linepos,
2450 "nested function definitions are not (yet) allowed" );
2451 return FALSE;
2454 // make sure a code segment is in stmt - else we should push scope
2455 assert( !f->code || f->code->s_type == ae_stmt_code );
2457 // look up the value in the current class (can shadow?)
2458 if(( overload = env->curr->lookup_value( f->name, FALSE ) ))
2460 // if value
2461 if( !isa( overload->type, &t_function ) )
2463 EM_error2( f->linepos,
2464 "function name '%s' is already used by another value", S_name(f->name) );
2465 return FALSE;
2467 else
2469 // overload
2470 if( !overload->func_ref )
2472 // error
2473 EM_error2( f->linepos,
2474 "internal error: missing function '%s'",
2475 overload->name.c_str() );
2476 return FALSE;
2481 // if overload
2482 if( overload )
2484 // make the new name
2485 func_name += "@" + itoa( ++overload->func_num_overloads ) + "@" + env->curr->name;
2487 else
2489 // make name using 0
2490 func_name += "@0@" + env->curr->name;
2493 // make sure a code segment is in stmt - else we should push scope
2494 assert( !f->code || f->code->s_type == ae_stmt_code );
2496 // make a new func object
2497 func = env->context->new_Chuck_Func();
2498 // set the name
2499 func->name = func_name;
2500 // reference the function definition
2501 func->def = f;
2502 // note whether the function is marked as member
2503 func->is_member = (f->static_decl != ae_key_static) &&
2504 (env->class_def != NULL);
2505 // copy the native code, for imported functions
2506 if( f->s_type == ae_func_builtin )
2508 // we can emit code now
2509 func->code = new Chuck_VM_Code;
2510 // whether the function needs 'this'
2511 func->code->need_this = func->is_member;
2512 // set the function pointer
2513 func->code->native_func = (t_CKUINT)func->def->dl_func_ptr;
2516 // make a new type for the function
2517 type = env->context->new_Chuck_Type();
2518 type->xid = te_function;
2519 type->name = "[function]";
2520 type->parent = &t_function;
2521 type->size = sizeof(void *);
2522 type->func = func;
2524 // make new value, with potential overloaded name
2525 value = env->context->new_Chuck_Value( type, func_name );
2526 // it is const
2527 value->is_const = TRUE;
2528 // remember the owner
2529 value->owner = env->curr;
2530 value->owner_class = env->class_def;
2531 value->is_member = func->is_member;
2532 // is global context
2533 value->is_context_global = env->class_def == NULL;
2534 // remember the func
2535 value->func_ref = func; func->add_ref(); // add reference TODO: break cycle?
2536 // remember the value
2537 func->value_ref = value; value->add_ref(); // add reference TODO: break cycle?
2539 // set the func
2540 f->ck_func = func; func->add_ref(); // add reference
2542 // if overload
2543 if( overload )
2545 // add
2546 func->next = overload->func_ref->next;
2547 overload->func_ref->next = func;
2550 // make sure
2551 assert( f->ret_type != NULL );
2553 // primitive
2554 if( (isprim( f->ret_type ) /*|| isa( f->ret_type, &t_string )*/)
2555 && f->type_decl->ref ) // TODO: string
2557 EM_error2( f->type_decl->linepos,
2558 "cannot declare references (@) of primitive type '%s'...",
2559 f->ret_type->c_name() );
2560 EM_error2( f->type_decl->linepos,
2561 "...(primitive types: 'int', 'float', 'time', 'dur')" );
2562 goto error;
2565 // look up types for the function arguments
2566 arg_list = f->arg_list;
2567 // count
2568 count = 1;
2569 // make room for 'this'
2570 f->stack_depth = func->is_member ? sizeof(void *) : 0;
2571 // loop over arguments
2572 while( arg_list )
2574 // make sure the type is not NULL - it should have been
2575 // set in scan1_func_def()...
2576 assert( arg_list->type != NULL );
2578 // make sure it's not void
2579 if( arg_list->type->size == 0 )
2581 EM_error2( arg_list->linepos,
2582 "cannot declare variables of size '0' (i.e. 'void')..." );
2583 goto error;
2586 // check if reserved
2587 if( type_engine_check_reserved( env, arg_list->var_decl->xid, arg_list->linepos ) )
2589 EM_error2( arg_list->linepos, "in function '%s'", S_name(f->name) );
2590 goto error;
2593 // look up in scope: later
2594 //if( env->curr->lookup_value( arg_list->var_decl->xid, FALSE ) )
2596 // EM_error2( arg_list->linepos, "in function '%s':", S_name(f->name) );
2597 // EM_error2( arg_list->linepos, "argument %i '%s' is already defined in this scope",
2598 // count, S_name(arg_list->var_decl->xid) );
2599 // goto error;
2602 // primitive
2603 if( (isprim( arg_list->type ) /*|| isa( arg_list->type, &t_string )*/)
2604 && arg_list->type_decl->ref ) // TODO: string
2606 EM_error2( arg_list->type_decl->linepos,
2607 "cannot declare references (@) of primitive type '%s'...",
2608 arg_list->type->c_name() );
2609 EM_error2( arg_list->type_decl->linepos,
2610 "...(primitive types: 'int', 'float', 'time', 'dur')" );
2611 goto error;
2614 // check if array
2615 if( arg_list->var_decl->array != NULL )
2617 // verify there are no errors from the parser...
2618 if( !verify_array( arg_list->var_decl->array ) )
2619 return FALSE;
2621 Chuck_Type * t = arg_list->type;
2622 Chuck_Type * t2 = t;
2623 // should be partial and empty []
2624 if( arg_list->var_decl->array->exp_list )
2626 EM_error2( arg_list->linepos, "in function '%s':", S_name(f->name) );
2627 EM_error2( arg_list->linepos, "argument %i '%s' must be defined with empty []'s",
2628 count, S_name(arg_list->var_decl->xid) );
2629 return FALSE;
2632 // create the new array type
2633 t = new_array_type(
2634 env, // the env
2635 &t_array, // the array base class, usually &t_array
2636 arg_list->var_decl->array->depth, // the depth of the new type
2637 t2, // the 'array_type'
2638 env->curr // the owner namespace
2641 // set ref
2642 arg_list->type_decl->ref = TRUE;
2643 // set type : arg_list->type = t;
2644 SAFE_REF_ASSIGN( arg_list->type, t );
2647 // make new value
2648 v = env->context->new_Chuck_Value(
2649 arg_list->type, S_name(arg_list->var_decl->xid) );
2650 // remember the owner
2651 v->owner = env->curr;
2652 // function args not owned
2653 v->owner_class = NULL;
2654 v->is_member = FALSE;
2655 // later: add as value
2656 // symbols.push_back( arg_list );
2657 // values.push_back( v );
2658 // later: env->curr->value.add( arg_list->var_decl->xid, v );
2660 // stack
2661 v->offset = f->stack_depth;
2662 f->stack_depth += arg_list->type->size;
2664 // remember
2665 arg_list->var_decl->value = v;
2667 // count
2668 count++;
2669 // next arg
2670 arg_list = arg_list->next;
2673 // add as value
2674 env->curr->value.add( value->name, value );
2675 // enter the name into the function table
2676 env->curr->func.add( func->name, func );
2678 // add for orig name
2679 if( !overload )
2681 env->curr->value.add( orig_name, value );
2682 env->curr->func.add( orig_name, func );
2685 // if overload
2686 if( overload )
2688 // make sure returns are equal
2689 if( *(f->ret_type) != *(overload->func_ref->def->ret_type) )
2691 EM_error2( f->linepos, "function signatures differ in return type..." );
2692 EM_error2( f->linepos,
2693 "function '%s.%s' matches '%s.%s' but cannot overload...",
2694 env->class_def->c_name(), S_name(f->name),
2695 value->owner_class->c_name(), S_name(f->name) );
2696 goto error;
2700 // set the current function to this
2701 env->func = func;
2702 // push the value stack
2703 env->curr->value.push();
2705 // scan the code
2706 assert( f->code == NULL || f->code->s_type == ae_stmt_code );
2707 if( f->code && !type_engine_scan2_code_segment( env, &f->code->stmt_code, FALSE ) )
2709 EM_error2( 0, "...in function '%s'", S_name(f->name) );
2710 goto error;
2713 // pop the value stack
2714 env->curr->value.pop();
2715 // clear the env's function definition
2716 env->func = NULL;
2718 return TRUE;
2720 error:
2722 // clean up
2723 if( func )
2725 env->func = NULL;
2726 func->release();
2729 return FALSE;