*** empty log message ***
[chuck-blob.git] / v2 / chuck_type.cpp
blobb099ddd7af94ea9c4f2eb3be72b1b6a295cce322
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_type.cpp
27 // desc: chuck type-system / type-checker
29 // author: Ge Wang (gewang@cs.princeton.edu)
30 // Perry R. Cook (prc@cs.princeton.edu)
31 // date: Autumn 2002 - original
32 // Autumn 2004 - rewrite
33 //-----------------------------------------------------------------------------
34 #include "chuck_type.h"
35 #include "chuck_parse.h"
36 #include "chuck_scan.h"
37 #include "chuck_vm.h"
38 #include "chuck_errmsg.h"
39 #include "chuck_lang.h"
40 #include "util_string.h"
41 #include "ugen_xxx.h"
43 using namespace std;
48 //-----------------------------------------------------------------------------
49 // default types
50 //-----------------------------------------------------------------------------
51 Chuck_Type t_void( te_void, "void", NULL, 0 );
52 Chuck_Type t_int( te_int, "int", NULL, sizeof(t_CKINT) );
53 Chuck_Type t_float( te_float, "float", NULL, sizeof(t_CKFLOAT) );
54 Chuck_Type t_time( te_time, "time", NULL, sizeof(t_CKTIME) );
55 Chuck_Type t_dur( te_dur, "dur", NULL, sizeof(t_CKTIME) );
56 Chuck_Type t_complex( te_complex, "complex", NULL, sizeof(t_CKCOMPLEX) );
57 Chuck_Type t_polar( te_polar, "polar", NULL, sizeof(t_CKPOLAR) );
58 Chuck_Type t_null( te_null, "@null", NULL, sizeof(void *) );
59 Chuck_Type t_function( te_function, "@function", &t_object, sizeof(void *) );
60 Chuck_Type t_object( te_object, "Object", NULL, sizeof(void *) );
61 Chuck_Type t_array( te_array, "@array", &t_object, sizeof(void *) );
62 Chuck_Type t_string( te_string, "string", &t_object, sizeof(void *) );
63 Chuck_Type t_event( te_event, "Event", &t_object, sizeof(void *) );
64 Chuck_Type t_ugen( te_ugen, "UGen", &t_object, sizeof(void *) );
65 Chuck_Type t_uana( te_uana, "UAna", &t_ugen, sizeof(void *) );
66 Chuck_Type t_uanablob( te_uanablob, "UAnaBlob", &t_object, sizeof(void *) );
67 Chuck_Type t_shred( te_shred, "Shred", &t_object, sizeof(void *) );
68 Chuck_Type t_io( te_io, "IO", &t_object, sizeof(void *) );
69 Chuck_Type t_fileio( te_fileio, "FileIO", &t_io, sizeof(void *) );
70 Chuck_Type t_thread( te_thread, "Thread", &t_object, sizeof(void *) );
71 Chuck_Type t_class( te_class, "Class", &t_object, sizeof(void *) );
73 /* exile
74 struct Chuck_Type t_adc = { te_adc, "adc", &t_ugen, t_ugen.size };
75 struct Chuck_Type t_dac = { te_dac, "dac", &t_ugen, t_ugen.size };
76 struct Chuck_Type t_bunghole = { te_bunghole, "bunghole", &t_ugen, t_ugen.size };
77 struct Chuck_Type t_midiout = { te_midiout, "midiout", &t_object, sizeof(void *) };
78 struct Chuck_Type t_midiin = { te_midiin, "midiin", &t_object, sizeof(void *) };
79 struct Chuck_Type t_stdout = { te_stdout, "@stdout", &t_object, sizeof(void *) };
80 struct Chuck_Type t_stderr ={ te_stdout, "@stderr", &t_object, sizeof(void *) };
82 struct Chuck_Type t_uint = { te_uint, "uint", NULL, sizeof(t_CKUINT) };
83 struct Chuck_Type t_single = { te_single, "single", NULL, sizeof(float) };
84 struct Chuck_Type t_double = { te_double, "double", NULL, sizeof(double) };
85 struct Chuck_Type t_code = { te_code, "code", NULL, sizeof(void *) };
86 struct Chuck_Type t_tuple = { te_tuple, "tuple", NULL, sizeof(void *) };
87 struct Chuck_Type t_pattern = { te_pattern, "pattern", &t_object, sizeof(void *) };
88 struct Chuck_Type t_transport = { te_transport, "transport", &t_object, sizeof(void *) };
89 struct Chuck_Type t_host = { te_host, "host", &t_object, sizeof(void *) }; */
94 //-----------------------------------------------------------------------------
95 // function prototypes
96 //-----------------------------------------------------------------------------
97 t_CKBOOL type_engine_check_stmt_list( Chuck_Env * env, a_Stmt_List list );
98 t_CKBOOL type_engine_check_stmt( Chuck_Env * env, a_Stmt stmt );
99 t_CKBOOL type_engine_check_if( Chuck_Env * env, a_Stmt_If stmt );
100 t_CKBOOL type_engine_check_for( Chuck_Env * env, a_Stmt_For stmt );
101 t_CKBOOL type_engine_check_while( Chuck_Env * env, a_Stmt_While stmt );
102 t_CKBOOL type_engine_check_until( Chuck_Env * env, a_Stmt_Until stmt );
103 t_CKBOOL type_engine_check_loop( Chuck_Env * env, a_Stmt_Loop stmt );
104 t_CKBOOL type_engine_check_break( Chuck_Env * env, a_Stmt_Break br );
105 t_CKBOOL type_engine_check_continue( Chuck_Env * env, a_Stmt_Continue cont );
106 t_CKBOOL type_engine_check_return( Chuck_Env * env, a_Stmt_Return stmt );
107 t_CKBOOL type_engine_check_switch( Chuck_Env * env, a_Stmt_Switch stmt );
108 t_CKTYPE type_engine_check_exp( Chuck_Env * env, a_Exp exp );
109 t_CKTYPE type_engine_check_exp_binary( Chuck_Env * env, a_Exp_Binary binary );
110 t_CKTYPE type_engine_check_op( Chuck_Env * env, ae_Operator op, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary );
111 t_CKTYPE type_engine_check_op_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary );
112 t_CKTYPE type_engine_check_op_unchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs );
113 t_CKTYPE type_engine_check_op_upchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs );
114 t_CKTYPE type_engine_check_op_at_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs );
115 t_CKTYPE type_engine_check_exp_unary( Chuck_Env * env, a_Exp_Unary unary );
116 t_CKTYPE type_engine_check_exp_primary( Chuck_Env * env, a_Exp_Primary exp );
117 t_CKTYPE type_engine_check_exp_array_lit( Chuck_Env * env, a_Exp_Primary exp );
118 t_CKTYPE type_engine_check_exp_complex_lit( Chuck_Env * env, a_Exp_Primary exp );
119 t_CKTYPE type_engine_check_exp_polar_lit( Chuck_Env * env, a_Exp_Primary exp );
120 t_CKTYPE type_engine_check_exp_cast( Chuck_Env * env, a_Exp_Cast cast );
121 t_CKTYPE type_engine_check_exp_postfix( Chuck_Env * env, a_Exp_Postfix postfix );
122 t_CKTYPE type_engine_check_exp_dur( Chuck_Env * env, a_Exp_Dur dur );
123 t_CKTYPE type_engine_check_exp_array( Chuck_Env * env, a_Exp_Array array );
124 t_CKTYPE type_engine_check_exp_func_call( Chuck_Env * env, a_Exp_Func_Call func_call );
125 t_CKTYPE type_engine_check_exp_func_call( Chuck_Env * env, a_Exp exp_func, a_Exp args,
126 t_CKFUNC & ck_func, int linepos );
127 t_CKTYPE type_engine_check_exp_dot_member( Chuck_Env * env, a_Exp_Dot_Member member );
128 t_CKTYPE type_engine_check_exp_if( Chuck_Env * env, a_Exp_If exp_if );
129 t_CKTYPE type_engine_check_exp_decl( Chuck_Env * env, a_Exp_Decl decl );
130 t_CKBOOL type_engine_check_array_subscripts( Chuck_Env * env, a_Exp exp_list );
131 t_CKBOOL type_engine_check_cast_valid( Chuck_Env * env, t_CKTYPE to, t_CKTYPE from );
132 t_CKBOOL type_engine_check_code_segment( Chuck_Env * env, a_Stmt_Code stmt, t_CKBOOL push = TRUE );
133 t_CKBOOL type_engine_check_func_def( Chuck_Env * env, a_Func_Def func_def );
134 t_CKBOOL type_engine_check_class_def( Chuck_Env * env, a_Class_Def class_def );
136 // helper
137 a_Func_Def make_dll_as_fun( Chuck_DL_Func * dl_fun, t_CKBOOL is_static );
139 // static
140 Chuck_Env * Chuck_Env::our_instance = NULL;
143 //-----------------------------------------------------------------------------
144 // name: startup()
145 // desc:
146 //-----------------------------------------------------------------------------
147 t_CKBOOL Chuck_Env::startup()
149 assert( our_instance == NULL );
150 our_instance = new Chuck_Env;
151 assert( our_instance != NULL );
153 return TRUE;
159 //-----------------------------------------------------------------------------
160 // name: instance()
161 // desc: ...
162 //-----------------------------------------------------------------------------
163 Chuck_Env * Chuck_Env::instance()
165 return our_instance;
171 //-----------------------------------------------------------------------------
172 // name: shutdown()
173 // desc: ...
174 //-----------------------------------------------------------------------------
175 t_CKBOOL Chuck_Env::shutdown()
177 assert( our_instance != NULL );
178 SAFE_DELETE( our_instance );
179 assert( our_instance == NULL );
181 return TRUE;
187 //-----------------------------------------------------------------------------
188 // name: type_engine_init()
189 // desc: initialize a type engine
190 //-----------------------------------------------------------------------------
191 Chuck_Env * type_engine_init( Chuck_VM * vm )
193 // log
194 EM_log( CK_LOG_SEVERE, "initializing type checker..." );
195 // push indent level
196 EM_pushlog();
198 // allocate a new env
199 if( !Chuck_Env::startup() ) return NULL;
200 // get the instance
201 Chuck_Env * env = Chuck_Env::instance();
202 // set the name of global namespace
203 env->global()->name = "global";
204 // set the current namespace to global
205 env->curr = env->global();
207 // enter the default global type mapping : lock VM objects to catch deletion
208 env->global()->type.add( t_void.name, &t_void ); t_void.lock();
209 env->global()->type.add( t_int.name, &t_int ); t_int.lock();
210 env->global()->type.add( t_float.name, &t_float ); t_float.lock();
211 env->global()->type.add( t_time.name, &t_time ); t_time.lock();
212 env->global()->type.add( t_dur.name, &t_dur ); t_dur.lock();
213 env->global()->type.add( t_complex.name, &t_complex ); t_complex.lock();
214 env->global()->type.add( t_polar.name, &t_polar ); t_polar.lock();
215 env->global()->type.add( t_object.name, &t_object ); t_object.lock();
216 env->global()->type.add( t_string.name, &t_string ); t_string.lock();
217 env->global()->type.add( t_ugen.name, &t_ugen ); t_ugen.lock();
218 env->global()->type.add( t_uana.name, &t_uana ); t_uana.lock();
219 env->global()->type.add( t_uanablob.name, &t_uanablob ); t_uanablob.lock();
220 env->global()->type.add( t_shred.name, &t_shred ); t_shred.lock();
221 env->global()->type.add( t_thread.name, &t_thread ); t_thread.lock();
222 env->global()->type.add( t_function.name, &t_function ); t_function.lock();
223 env->global()->type.add( t_class.name, &t_class ); t_class.lock();
224 env->global()->type.add( t_array.name, &t_array ); t_array.lock();
225 env->global()->type.add( t_event.name, &t_event ); t_event.lock();
226 env->global()->type.add( t_io.name, &t_io ); t_io.lock();
227 env->global()->type.add( t_fileio.name, &t_fileio ); t_fileio.lock();
229 // dur value
230 t_CKDUR samp = 1.0;
231 // TODO:
232 t_CKDUR second = vm->srate() * samp;
233 // t_CKDUR second = 44100 * samp;
234 t_CKDUR ms = second / 1000.0;
235 t_CKDUR minute = second * 60.0;
236 t_CKDUR hour = minute * 60.0;
237 t_CKDUR day = hour * 24.0;
238 t_CKDUR week = day * 7.0;
240 // add internal classes
241 EM_log( CK_LOG_SEVERE, "adding base classes..." );
242 EM_pushlog();
243 init_class_object( env, &t_object );
244 init_class_array( env, &t_array );
245 init_class_string( env, &t_string );
246 init_class_ugen( env, &t_ugen );
247 init_class_blob( env, &t_uanablob );
248 init_class_uana( env, &t_uana );
249 init_class_shred( env, &t_shred );
250 init_class_event( env, &t_event );
251 init_class_io( env, &t_io );
253 EM_log( CK_LOG_SEVERE, "class 'class'" );
254 t_class.info = new Chuck_Namespace;
255 t_class.info->add_ref();
256 t_thread.info = new Chuck_Namespace;
257 t_thread.info->add_ref();
259 // pop indent
260 EM_poplog();
262 // default global values
263 env->global()->value.add( "null", new Chuck_Value( &t_null, "null", new void *(NULL), TRUE ) );
264 env->global()->value.add( "NULL", new Chuck_Value( &t_null, "NULL", new void *(NULL), TRUE ) );
265 env->global()->value.add( "t_zero", new Chuck_Value( &t_time, "time_zero", new t_CKDUR(0.0), TRUE ) );
266 env->global()->value.add( "d_zero", new Chuck_Value( &t_dur, "dur_zero", new t_CKDUR(0.0), TRUE ) );
267 env->global()->value.add( "samp", new Chuck_Value( &t_dur, "samp", new t_CKDUR(samp), TRUE ) );
268 env->global()->value.add( "ms", new Chuck_Value( &t_dur, "ms", new t_CKDUR(ms), TRUE ) );
269 env->global()->value.add( "second", new Chuck_Value( &t_dur, "second", new t_CKDUR(second), TRUE ) );
270 env->global()->value.add( "minute", new Chuck_Value( &t_dur, "minute", new t_CKDUR(minute), TRUE ) );
271 env->global()->value.add( "hour", new Chuck_Value( &t_dur, "hour", new t_CKDUR(hour), TRUE ) );
272 env->global()->value.add( "day", new Chuck_Value( &t_dur, "day", new t_CKDUR(day), TRUE ) );
273 env->global()->value.add( "week", new Chuck_Value( &t_dur, "week", new t_CKDUR(week), TRUE ) );
274 env->global()->value.add( "true", new Chuck_Value( &t_int, "true", new t_CKINT(1), TRUE ) );
275 env->global()->value.add( "false", new Chuck_Value( &t_int, "false", new t_CKINT(0), TRUE ) );
276 env->global()->value.add( "maybe", new Chuck_Value( &t_int, "maybe", new t_CKFLOAT(.5), FALSE ) );
277 env->global()->value.add( "pi", new Chuck_Value( &t_float, "pi", new t_CKFLOAT(ONE_PI), TRUE ) );
278 env->global()->value.add( "global", new Chuck_Value( &t_class, "global", env->global(), TRUE ) );
280 // TODO: can't use the following now is local to shred
281 // env->global()->value.add( "now", new Chuck_Value( &t_time, "now", &(vm->shreduler()->now_system), TRUE ) );
284 S_enter( e->value, insert_symbol( "machine" ), &t_null );
285 S_enter( e->value, insert_symbol( "language" ), &t_null );
286 S_enter( e->value, insert_symbol( "compiler" ), &t_null );
287 S_enter( e->value, insert_symbol( "chout" ), &t_system_out );
288 S_enter( e->value, insert_symbol( "cherr" ), &t_system_err );
289 S_enter( e->value, insert_symbol( "stdout" ), &t_system_out );
290 S_enter( e->value, insert_symbol( "stderr" ), &t_system_err );
291 S_enter( e->value, insert_symbol( "midiout" ), &t_midiout );
292 S_enter( e->value, insert_symbol( "midiin" ), &t_midiin );
293 S_enter( e->value, insert_symbol( "adc" ), &t_adc );
294 S_enter( e->value, insert_symbol( "dac" ), &t_dac );
295 S_enter( e->value, insert_symbol( "bunghole" ), &t_bunghole );
296 S_enter( e->value, insert_symbol( "blackhole" ), &t_bunghole );
297 S_enter( e->value, insert_symbol( "endl" ), &t_string );
300 // add reserve words
301 env->key_words["for"] = TRUE;
302 env->key_words["while"] = TRUE;
303 env->key_words["until"] = TRUE;
304 env->key_words["if"] = TRUE;
305 env->key_words["else"] = TRUE;
306 env->key_words["spork"] = TRUE;
307 env->key_words["return"] = TRUE;
308 env->key_words["class"] = TRUE;
309 env->key_words["extends"] = TRUE;
310 env->key_words["implements"] = TRUE;
311 env->key_words["function"] = TRUE;
312 env->key_words["fun"] = TRUE;
313 env->key_words["public"] = TRUE;
314 env->key_words["protected"] = TRUE;
315 env->key_words["private"] = TRUE;
316 env->key_words["static"] = TRUE;
317 env->key_words["pure"] = TRUE;
318 env->key_words["function"] = TRUE;
319 env->key_words["fun"] = TRUE;
320 env->key_words["break"] = TRUE;
321 env->key_words["continue"] = TRUE;
323 env->key_values["now"] = TRUE;
324 env->key_values["true"] = TRUE;
325 env->key_values["false"] = TRUE;
326 env->key_values["maybe"] = TRUE;
327 env->key_values["pi"] = TRUE;
328 env->key_values["this"] = TRUE;
329 env->key_values["super"] = TRUE;
330 env->key_values["me"] = TRUE;
331 env->key_values["samp"] = TRUE;
332 env->key_values["ms"] = TRUE;
333 env->key_values["second"] = TRUE;
334 env->key_values["minute"] = TRUE;
335 env->key_values["hour"] = TRUE;
336 env->key_values["day"] = TRUE;
337 env->key_values["week"] = TRUE;
338 env->key_values["adc"] = TRUE;
339 env->key_values["dac"] = TRUE;
340 env->key_values["blackhole"] = TRUE;
341 env->key_values["global"] = TRUE;
342 env->key_values["null"] = TRUE;
343 env->key_values["NULL"] = TRUE;
345 env->key_types["void"] = TRUE;
346 env->key_types["same"] = TRUE;
347 env->key_types["int"] = TRUE;
348 env->key_types["float"] = TRUE;
349 // env->key_types["dur"] = TRUE;
350 // env->key_types["time"] = TRUE;
351 // env->key_types["Object"] = TRUE;
352 // env->key_types["string"] = TRUE;
353 // env->key_types["Shred"] = TRUE;
354 // env->key_types["Event"] = TRUE;
355 // env->key_types["UGen"] = TRUE;
356 // env->key_types["machine"] = TRUE;
357 // env->key_types["language"] = TRUE;
358 // env->key_types["compiler"] = TRUE;
360 // commit the global namespace
361 env->global()->commit();
363 // pop indent level
364 EM_poplog();
366 return env;
371 //-----------------------------------------------------------------------------
372 // name: type_engine_shutdown()
373 // desc: ...
374 //-----------------------------------------------------------------------------
375 void type_engine_shutdown( Chuck_Env * env )
377 // log
378 EM_log( CK_LOG_SEVERE, "shutting down type checker..." );
380 // shut it down
381 Chuck_Env::shutdown();
383 // TODO: free these properly
384 SAFE_RELEASE( t_object.info );
385 SAFE_RELEASE( t_array.info );
386 SAFE_RELEASE( t_string.info );
387 SAFE_RELEASE( t_ugen.info );
388 SAFE_RELEASE( t_uanablob.info );
389 SAFE_RELEASE( t_uana.info );
390 SAFE_RELEASE( t_shred.info );
391 SAFE_RELEASE( t_event.info );
392 SAFE_RELEASE( t_class.info );
393 SAFE_RELEASE( t_thread.info );
394 SAFE_RELEASE( t_io.info );
400 //-----------------------------------------------------------------------------
401 // name: type_engine_check_prog()
402 // desc: ...
403 //-----------------------------------------------------------------------------
404 t_CKBOOL type_engine_check_prog( Chuck_Env * env, a_Program prog,
405 const string & filename )
407 t_CKBOOL ret = FALSE;
409 // log
410 EM_log( CK_LOG_FINE, "type-checking program '%s' - passes 0, 1, 2, 3...",
411 filename.c_str() );
412 // push indent
413 EM_pushlog();
415 // make the context
416 Chuck_Context * context = type_engine_make_context( prog, filename );
417 if( !context ) goto done;
419 // reset the env
420 env->reset();
422 // load the context
423 if( !type_engine_load_context( env, context ) )
424 { ret = FALSE; goto done; }
426 // 0th-scan (pass 0)
427 if( !type_engine_scan0_prog( env, g_program, te_do_all ) )
428 { ret = FALSE; goto cleanup; }
430 // 1st-scan (pass 1)
431 if( !type_engine_scan1_prog( env, g_program, te_do_all ) )
432 { ret = FALSE; goto cleanup; }
434 // 2nd-scan (pass 2)
435 if( !type_engine_scan2_prog( env, prog, te_do_all ) )
436 { ret = FALSE; goto cleanup; }
438 // check the context (pass 3)
439 if( !type_engine_check_context( env, context ) )
440 { ret = FALSE; goto cleanup; }
442 cleanup:
444 // commit
445 if( ret ) env->global()->commit();
446 // or rollback
447 else env->global()->rollback();
449 // unload the context from the type-checker
450 if( !type_engine_unload_context( env ) )
452 EM_error2( 0, "internal error unloading context...\n" );
453 ret = FALSE;
456 done:
458 // pop indent
459 EM_poplog();
461 return ret;
467 //-----------------------------------------------------------------------------
468 // name: type_engine_make_context()
469 // desc: ...
470 //-----------------------------------------------------------------------------
471 Chuck_Context * type_engine_make_context( a_Program prog, const string & filename )
473 // log
474 EM_log( CK_LOG_FINER, "creating context '%s'...", filename.c_str() );
475 // push indent
476 EM_pushlog();
478 // each parse tree corresponds to a chuck context
479 Chuck_Context * context = new Chuck_Context;
480 // save a reference to the parse tree
481 context->parse_tree = prog;
482 // set name
483 context->filename = filename;
485 // pop indent
486 EM_poplog();
488 return context;
494 //-----------------------------------------------------------------------------
495 // name: type_engine_check_context()
496 // desc: ...
497 //-----------------------------------------------------------------------------
498 t_CKBOOL type_engine_check_context( Chuck_Env * env,
499 Chuck_Context * context,
500 te_HowMuch how_much )
502 t_CKBOOL ret = TRUE;
503 a_Program prog = NULL;
505 // log
506 EM_log( CK_LOG_FINER, "(pass 3) type-checking context '%s'...",
507 context->filename.c_str() );
508 // push indent
509 EM_pushlog();
510 // how much
511 EM_log( CK_LOG_FINER, "target: %s", howmuch2str( how_much ) );
513 // make sure there is a context
514 if( !env->context )
516 // error
517 EM_error2( 0, "internal error: env->context NULL!" );
518 ret = FALSE; goto done;
521 // parse tree
522 prog = context->parse_tree;
523 if( !prog )
525 // error
526 EM_error2( 0, "internal error: context->parse_tree NULL!" );
527 ret = FALSE; goto done;
530 // go through each of the program sections
531 while( prog && ret )
533 switch( prog->section->s_type )
535 case ae_section_stmt:
536 // if only classes, then skip
537 if( how_much == te_do_classes_only ) break;
538 // check the statements
539 ret = type_engine_check_stmt_list( env, prog->section->stmt_list );
540 break;
542 case ae_section_func:
543 // if only classes, then skip
544 if( how_much == te_do_classes_only ) break;
545 // check the function definition
546 ret = type_engine_check_func_def( env, prog->section->func_def );
547 break;
549 case ae_section_class:
550 // if no classes, then skip
551 if( how_much == te_do_no_classes ) break;
552 // check the class definition
553 ret = type_engine_check_class_def( env, prog->section->class_def );
554 break;
556 default:
557 EM_error2( prog->linepos,
558 "internal error: unrecognized program section in type checker..." );
559 ret = FALSE;
560 break;
563 prog = prog->next;
566 // make sure we still have the same context
567 assert( env->contexts.size() != 0 );
568 // assert( env->contexts.back() == context );
570 // check to see if everything passed
571 if( !ret )
573 // TODO: remove the effects of the context in the env
574 // ---> insert code here <----
576 // flag the context with error, so more stuff gets deleted
577 env->context->has_error = TRUE;
580 done:
582 // pop indent
583 EM_poplog();
585 return ret;
591 //-----------------------------------------------------------------------------
592 // name: type_engine_load_context()
593 // desc: call this before context is type-checked
594 //-----------------------------------------------------------------------------
595 t_CKBOOL type_engine_load_context( Chuck_Env * env, Chuck_Context * context )
597 // log
598 EM_log( CK_LOG_FINER, "loading context '%s'...", context->filename.c_str() );
599 // push indent
600 EM_pushlog();
601 if( env->context ) EM_log( CK_LOG_FINER, "pushing existing context '%s'...",
602 env->context->filename.c_str() );
603 // append the context to the env
604 env->contexts.push_back( env->context );
605 // make the context current
606 env->context = context;
607 // add reference
608 env->context->add_ref();
609 // push the context scope
610 env->context->nspc->value.push();
611 // push the current namespaces
612 env->nspc_stack.push_back( env->curr );
613 // set the parent
614 context->nspc->parent = env->curr;
615 // set the context's namespace as current
616 env->curr = context->nspc;
618 // pop indent
619 EM_poplog();
621 return TRUE;
627 //-----------------------------------------------------------------------------
628 // name: type_engine_unload_context()
629 // desc: call this after context is emitted
630 //-----------------------------------------------------------------------------
631 t_CKBOOL type_engine_unload_context( Chuck_Env * env )
633 // make sure
634 assert( env->context != NULL );
635 assert( env->contexts.size() != 0 );
636 // log
637 EM_log( CK_LOG_FINER, "unloading context '%s'...",
638 env->context->filename.c_str() );
639 // push indent
640 EM_pushlog();
641 EM_log( CK_LOG_FINER, "restoring context '%s'...",
642 env->contexts.back()->filename.c_str() );
643 // assert( env->context->has_error == FALSE );
644 // pop the context scope
645 env->context->nspc->value.pop();
646 // restore the current namespace
647 env->curr = env->nspc_stack.back();
648 // pop the namespace stack
649 env->nspc_stack.pop_back();
650 // release the context
651 env->context->release();
652 // restore context
653 env->context = env->contexts.back();
654 // pop the context
655 env->contexts.pop_back();
657 // make sure the nspc is ok
658 assert( env->nspc_stack.size() != 0 );
659 // assert( env->stack.back() == &(context->nspc) );
661 // pop indent
662 EM_poplog();
664 return TRUE;
670 //-----------------------------------------------------------------------------
671 // name: type_engine_check_stmt_list()
672 // desc: ...
673 //-----------------------------------------------------------------------------
674 t_CKBOOL type_engine_check_stmt_list( Chuck_Env * env, a_Stmt_List list )
676 // type check the stmt_list
677 while( list )
679 // the current statement
680 if( !type_engine_check_stmt( env, list->stmt ) )
681 return FALSE;
683 // advance to the next statement
684 list = list->next;
687 return TRUE;
693 //-----------------------------------------------------------------------------
694 // name: type_engine_check_stmt(()
695 // desc: ...
696 //-----------------------------------------------------------------------------
697 t_CKBOOL type_engine_check_stmt( Chuck_Env * env, a_Stmt stmt )
699 t_CKBOOL ret = FALSE;
701 if( !stmt )
702 return TRUE;
704 // the type of stmt
705 switch( stmt->s_type )
707 case ae_stmt_if:
708 // count scope to help determine class member
709 env->class_scope++;
710 env->curr->value.push();
711 ret = type_engine_check_if( env, &stmt->stmt_if );
712 env->curr->value.pop();
713 env->class_scope--;
714 break;
716 case ae_stmt_for:
717 env->class_scope++;
718 env->curr->value.push();
719 ret = type_engine_check_for( env, &stmt->stmt_for );
720 env->curr->value.pop();
721 env->class_scope--;
722 break;
724 case ae_stmt_while:
725 env->class_scope++;
726 env->curr->value.push();
727 ret = type_engine_check_while( env, &stmt->stmt_while );
728 env->curr->value.pop();
729 env->class_scope--;
730 break;
732 case ae_stmt_until:
733 env->class_scope++;
734 env->curr->value.push();
735 ret = type_engine_check_until( env, &stmt->stmt_until );
736 env->curr->value.pop();
737 env->class_scope--;
738 break;
740 case ae_stmt_loop:
741 env->class_scope++;
742 env->curr->value.push();
743 ret = type_engine_check_loop( env, &stmt->stmt_loop );
744 env->curr->value.pop();
745 env->class_scope--;
746 break;
748 case ae_stmt_exp:
749 ret = ( type_engine_check_exp( env, stmt->stmt_exp ) != NULL );
750 break;
752 case ae_stmt_return:
753 ret = type_engine_check_return( env, &stmt->stmt_return );
754 break;
756 case ae_stmt_code:
757 env->class_scope++;
758 ret = type_engine_check_code_segment( env, &stmt->stmt_code );
759 env->class_scope--;
760 break;
762 case ae_stmt_break:
763 ret = type_engine_check_break( env, &stmt->stmt_break );
764 break;
766 case ae_stmt_continue:
767 ret = type_engine_check_continue( env, &stmt->stmt_continue );
768 break;
770 case ae_stmt_switch:
771 env->class_scope++;
772 ret = type_engine_check_switch( env, &stmt->stmt_switch );
773 env->class_scope--;
774 break;
776 case ae_stmt_case:
777 // ret = type_engine_check_case( env, &stmt->stmt_case );
778 break;
780 case ae_stmt_gotolabel:
781 // ret = type_engine_check_gotolabel( env, &stmt->goto_label );
782 break;
784 default:
785 EM_error2( stmt->linepos,
786 "internal compiler error - no stmt type '%i'!", stmt->s_type );
787 ret = FALSE;
788 break;
791 return ret;
797 //-----------------------------------------------------------------------------
798 // name: type_engine_check_if()
799 // desc: ...
800 //-----------------------------------------------------------------------------
801 t_CKBOOL type_engine_check_if( Chuck_Env * env, a_Stmt_If stmt )
803 // check the conditional
804 if( !type_engine_check_exp( env, stmt->cond ) )
805 return FALSE;
807 // TODO: ensure that conditional has valid type
809 // check if
810 if( !type_engine_check_stmt( env, stmt->if_body ) )
811 return FALSE;
813 // check else, if there is one
814 if( stmt->else_body )
815 if( !type_engine_check_stmt( env, stmt->else_body ) )
816 return FALSE;
818 return TRUE;
824 //-----------------------------------------------------------------------------
825 // name: type_engine_check_for()
826 // desc: ...
827 //-----------------------------------------------------------------------------
828 t_CKBOOL type_engine_check_for( Chuck_Env * env, a_Stmt_For stmt )
830 // check the initial
831 if( !type_engine_check_stmt( env, stmt->c1 ) )
832 return FALSE;
834 // check the conditional
835 if( !type_engine_check_stmt( env, stmt->c2 ) )
836 return FALSE;
838 // TODO: same as if - check conditional type valid
840 // check the post
841 if( stmt->c3 && !type_engine_check_exp( env, stmt->c3 ) )
842 return FALSE;
844 // for break and continue statement
845 env->breaks.push_back( stmt->self );
847 // check body
848 // TODO: restore break stack? (same for other loops)
849 if( !type_engine_check_stmt( env, stmt->body ) )
850 return FALSE;
852 // remove the loop from the stack
853 assert( env->breaks.size() && env->breaks.back() == stmt->self );
854 env->breaks.pop_back();
856 return TRUE;
862 //-----------------------------------------------------------------------------
863 // name: type_engine_check_while()
864 // desc: ...
865 //-----------------------------------------------------------------------------
866 t_CKBOOL type_engine_check_while( Chuck_Env * env, a_Stmt_While stmt )
868 // check the conditional
869 if( !type_engine_check_exp( env, stmt->cond ) )
870 return FALSE;
872 // TODO: same as if - ensure the type in conditional is valid
874 // for break and continue statement
875 env->breaks.push_back( stmt->self );
877 // check the body
878 if( !type_engine_check_stmt( env, stmt->body ) )
879 return FALSE;
881 // remove the loop from the stack
882 assert( env->breaks.size() && env->breaks.back() == stmt->self );
883 env->breaks.pop_back();
885 return TRUE;
891 //-----------------------------------------------------------------------------
892 // name: type_engine_check_until()
893 // desc: ...
894 //-----------------------------------------------------------------------------
895 t_CKBOOL type_engine_check_until( Chuck_Env * env, a_Stmt_Until stmt )
897 // check the conditional
898 if( !type_engine_check_exp( env, stmt->cond ) )
899 return FALSE;
901 // TODO: same as if - ensure the type in conditional is valid
903 // for break and continue statement
904 env->breaks.push_back( stmt->self );
906 // check the body
907 if( !type_engine_check_stmt( env, stmt->body ) )
908 return FALSE;
910 // remove the loop from the stack
911 assert( env->breaks.size() && env->breaks.back() == stmt->self );
912 env->breaks.pop_back();
914 return TRUE;
920 //-----------------------------------------------------------------------------
921 // name: type_engine_check_loop()
922 // desc: ...
923 //-----------------------------------------------------------------------------
924 t_CKBOOL type_engine_check_loop( Chuck_Env * env, a_Stmt_Loop stmt )
926 Chuck_Type * type = NULL;
928 // check the conditional
929 if( !(type = type_engine_check_exp( env, stmt->cond )) )
930 return FALSE;
932 // ensure the type in conditional is int (different from other loops)
933 if( isa( type, &t_float ) )
935 // cast
936 stmt->cond->cast_to = &t_int;
938 else if( !isa( type, &t_int ) ) // must be int
940 EM_error2( stmt->linepos,
941 "loop * conditional must be of type 'int'..." );
942 return FALSE;
945 // for break and continue statement
946 env->breaks.push_back( stmt->self );
948 // check the body
949 if( !type_engine_check_stmt( env, stmt->body ) )
950 return FALSE;
952 // remove the loop from the stack
953 assert( env->breaks.size() && env->breaks.back() == stmt->self );
954 env->breaks.pop_back();
956 return TRUE;
962 //-----------------------------------------------------------------------------
963 // name: type_engine_check_switch()
964 // desc: ...
965 //-----------------------------------------------------------------------------
966 t_CKBOOL type_engine_check_switch( Chuck_Env * env, a_Stmt_Switch stmt )
968 // TODO: implement this
969 EM_error2( stmt->linepos, "switch not implemented..." );
971 return FALSE;
977 //-----------------------------------------------------------------------------
978 // name: type_engine_check_break()
979 // desc: ...
980 //-----------------------------------------------------------------------------
981 t_CKBOOL type_engine_check_break( Chuck_Env * env, a_Stmt_Break br )
983 // check to see if inside valid stmt
984 if( env->breaks.size() <= 0 )
986 EM_error2( br->linepos,
987 "'break' found outside of for/while/until/switch..." );
988 return FALSE;
991 return TRUE;
997 //-----------------------------------------------------------------------------
998 // name: type_engine_check_continue()
999 // desc: ...
1000 //-----------------------------------------------------------------------------
1001 t_CKBOOL type_engine_check_continue( Chuck_Env * env, a_Stmt_Continue cont )
1003 // check to see if inside valid loop
1004 if( env->breaks.size() <= 0 )
1006 EM_error2( cont->linepos,
1007 "'continue' found outside of for/while/until..." );
1008 return FALSE;
1011 return TRUE;
1017 //-----------------------------------------------------------------------------
1018 // name: type_engine_check_return()
1019 // desc: ...
1020 //-----------------------------------------------------------------------------
1021 t_CKBOOL type_engine_check_return( Chuck_Env * env, a_Stmt_Return stmt )
1023 Chuck_Type * ret_type = NULL;
1025 // check to see if within function definition
1026 if( !env->func )
1028 EM_error2( stmt->linepos,
1029 "'return' statement found outside function definition" );
1030 return FALSE;
1033 // check the type of the return
1034 if( stmt->val )
1035 ret_type = type_engine_check_exp( env, stmt->val );
1036 else
1037 ret_type = &t_void;
1039 // check to see that return type matches the prototype
1040 if( ret_type && !isa( ret_type, env->func->def->ret_type ) )
1042 EM_error2( stmt->linepos,
1043 "function '%s' was defined with return type '%s' -- but returning type '%s'",
1044 env->func->name.c_str(), env->func->def->ret_type->c_name(),
1045 ret_type->c_name() );
1046 return FALSE;
1049 return ret_type != NULL;
1055 //-----------------------------------------------------------------------------
1056 // name: type_engine_check_code_segment()
1057 // desc: ...
1058 //-----------------------------------------------------------------------------
1059 t_CKBOOL type_engine_check_code_segment( Chuck_Env * env, a_Stmt_Code stmt,
1060 t_CKBOOL push )
1062 // TODO: make sure this is in a function or is outside class
1064 // class
1065 env->class_scope++;
1066 // push
1067 if( push ) env->curr->value.push(); // env->context->nspc.value.push();
1068 // do it
1069 t_CKBOOL t = type_engine_check_stmt_list( env, stmt->stmt_list );
1070 // pop
1071 if( push ) env->curr->value.pop(); // env->context->nspc.value.pop();
1072 // class
1073 env->class_scope--;
1075 return t;
1081 //-----------------------------------------------------------------------------
1082 // name: type_engine_check_exp()
1083 // desc: ...
1084 //-----------------------------------------------------------------------------
1085 t_CKTYPE type_engine_check_exp( Chuck_Env * env, a_Exp exp )
1087 a_Exp curr = exp;
1089 // reset the group size
1090 exp->group_size = 0;
1092 // loop through parallel expressions
1093 while( curr )
1095 // reset the type
1096 curr->type = NULL;
1097 // increment first exp's group size
1098 exp->group_size++;
1100 // examine the syntax
1101 switch( curr->s_type )
1103 case ae_exp_binary:
1104 curr->type = type_engine_check_exp_binary( env, &curr->binary );
1105 break;
1107 case ae_exp_unary:
1108 curr->type = type_engine_check_exp_unary( env, &curr->unary );
1109 break;
1111 case ae_exp_cast:
1112 curr->type = type_engine_check_exp_cast( env, &curr->cast );
1113 break;
1115 case ae_exp_postfix:
1116 curr->type = type_engine_check_exp_postfix( env, &curr->postfix );
1117 break;
1119 case ae_exp_dur:
1120 curr->type = type_engine_check_exp_dur( env, &curr->dur );
1121 break;
1123 case ae_exp_primary:
1124 curr->type = type_engine_check_exp_primary( env, &curr->primary );
1125 break;
1127 case ae_exp_array:
1128 curr->type = type_engine_check_exp_array( env, &curr->array );
1129 break;
1131 case ae_exp_func_call:
1132 curr->type = type_engine_check_exp_func_call( env, &curr->func_call );
1133 // set the return type
1134 curr->func_call.ret_type = curr->type;
1135 break;
1137 case ae_exp_dot_member:
1138 curr->type = type_engine_check_exp_dot_member( env, &curr->dot_member );
1139 break;
1141 case ae_exp_if:
1142 curr->type = type_engine_check_exp_if( env, &curr->exp_if );
1143 break;
1145 case ae_exp_decl:
1146 curr->type = type_engine_check_exp_decl( env, &curr->decl );
1147 break;
1149 default:
1150 EM_error2( curr->linepos,
1151 "internal compiler error - no expression type '%i'...",
1152 curr->s_type );
1153 return NULL;
1156 // error
1157 if( !curr->type )
1158 return NULL;
1160 // advance to next expression
1161 curr = curr->next;
1164 // return type
1165 return exp->type;
1171 //-----------------------------------------------------------------------------
1172 // name: type_engine_check_exp_binary()
1173 // desc: ...
1174 //-----------------------------------------------------------------------------
1175 t_CKTYPE type_engine_check_exp_binary( Chuck_Env * env, a_Exp_Binary binary )
1177 a_Exp cl = binary->lhs, cr = binary->rhs;
1178 t_CKTYPE ret = NULL;
1180 // type check the lhs and rhs
1181 t_CKTYPE left = type_engine_check_exp( env, cl );
1182 t_CKTYPE right = type_engine_check_exp( env, cr );
1184 // if either fails, then return NULL
1185 if( !left || !right )
1186 return NULL;
1188 // cross chuck
1189 while( cr )
1191 // type check the pair
1192 if( !(ret = type_engine_check_op( env, binary->op, cl, cr, binary )) )
1193 return NULL;
1195 cr = cr->next;
1198 return ret;
1204 //-----------------------------------------------------------------------------
1205 // name: type_engine_ensure_no_multi_decl()
1206 // desc: ...
1207 //-----------------------------------------------------------------------------
1208 t_CKBOOL type_engine_ensure_no_multi_decl( a_Exp exp, const char * op_str )
1210 // go
1211 if( exp->s_type == ae_exp_decl && exp->decl.num_var_decls > 1 )
1213 // multiple declarations on left side
1214 EM_error2( exp->linepos,
1215 "cannot '%s' from/to a multi-variable declaration", op_str );
1216 return FALSE;
1219 return TRUE;
1223 // helper macros
1224 #define LR( L, R ) if( (left->xid == L) && (right->xid == R) )
1225 #define COMMUTE( L, R ) if( ( (left->xid == L) && (right->xid == R) ) || \
1226 ( (left->xid == R) && (right->xid == L) ) )
1229 //-----------------------------------------------------------------------------
1230 // name: type_engine_check_op()
1231 // desc: ...
1232 //-----------------------------------------------------------------------------
1233 t_CKTYPE type_engine_check_op( Chuck_Env * env, ae_Operator op, a_Exp lhs, a_Exp rhs,
1234 a_Exp_Binary binary )
1236 t_CKTYPE left = lhs->type, right = rhs->type;
1237 assert( left && right );
1239 // make sure not involve multiple declarations (for now)
1240 if( !type_engine_ensure_no_multi_decl( lhs, op2str(op) ) ||
1241 !type_engine_ensure_no_multi_decl( rhs, op2str(op) ) )
1242 return FALSE;
1244 // if lhs is multi-value, then check separately
1245 if( (lhs->next && op != ae_op_chuck /*&& !isa( right, &t_function)*/ ) || rhs->next )
1247 // TODO: implement this
1248 EM_error2( lhs->linepos,
1249 "multi-value (%s) operation not supported/implemented...",
1250 op2str(op));
1251 return NULL;
1254 // file I/O
1255 if( op == ae_op_arrow_left || op == ae_op_arrow_right )
1257 // check left
1258 if( isa( left, &t_io ) )
1260 // check for assignment
1261 if( op == ae_op_arrow_right && lhs->s_meta != ae_meta_var )
1263 // error
1264 EM_error2( rhs->linepos,
1265 "cannot perform I/O assignment via '->' to non-mutable value" );
1266 return NULL;
1269 // check right
1270 if( isa( right, &t_int ) || isa( right, &t_float ) ||
1271 isa( right, &t_string ) )
1272 return left;
1276 // implicit cast
1277 if( *left != *right )
1279 // for some - int/float
1280 switch( op )
1282 case ae_op_plus:
1283 // Object.toString
1284 if( isa( left, &t_string ) && isa( right, &t_object ) && !isa( right, &t_string) )
1285 right = rhs->cast_to = &t_string;
1286 else if( isa( left, &t_object ) && isa( right, &t_string ) && !isa( left, &t_string) )
1287 left = lhs->cast_to = &t_string;
1288 case ae_op_minus:
1289 case ae_op_times:
1290 case ae_op_divide:
1291 case ae_op_lt:
1292 case ae_op_le:
1293 case ae_op_gt:
1294 case ae_op_ge:
1295 case ae_op_eq:
1296 case ae_op_neq:
1297 // complex
1298 LR( te_int, te_complex ) left = lhs->cast_to = &t_complex;
1299 else LR( te_complex, te_int ) right = rhs->cast_to = &t_complex;
1300 LR( te_float, te_complex ) left = lhs->cast_to = &t_complex;
1301 else LR( te_complex, te_float ) right = rhs->cast_to = &t_complex;
1303 // polar
1304 LR( te_int, te_polar ) left = lhs->cast_to = &t_polar;
1305 else LR( te_complex, te_int ) right = rhs->cast_to = &t_polar;
1306 LR( te_float, te_complex ) left = lhs->cast_to = &t_polar;
1307 else LR( te_complex, te_float ) right = rhs->cast_to = &t_polar;
1308 case ae_op_percent:
1309 // mark for cast
1310 LR( te_int, te_float ) left = lhs->cast_to = &t_float;
1311 else LR( te_float, te_int ) right = rhs->cast_to = &t_float;
1312 break;
1314 default: break;
1317 // no commute - int/float
1318 switch( op )
1320 case ae_op_plus_chuck:
1321 // Object.toString
1322 if( isa( left, &t_object ) && isa( right, &t_string ) && !isa( left, &t_string ) )
1323 left = lhs->cast_to = &t_string;
1324 case ae_op_minus_chuck:
1325 case ae_op_times_chuck:
1326 case ae_op_divide_chuck:
1327 case ae_op_percent_chuck:
1328 // mark for cast
1329 LR( te_int, te_float ) left = lhs->cast_to = &t_float;
1330 LR( te_float, te_complex ) left = lhs->cast_to = &t_complex;
1331 LR( te_float, te_polar ) left = lhs->cast_to = &t_polar;
1332 LR( te_int, te_complex ) left = lhs->cast_to = &t_complex;
1333 LR( te_int, te_polar ) left = lhs->cast_to = &t_polar;
1334 break;
1336 default: break;
1339 // int/dur
1340 if( op == ae_op_times )
1342 LR( te_int, te_dur ) left = lhs->cast_to = &t_float;
1343 else LR( te_dur, te_int ) right = rhs->cast_to = &t_float;
1345 else if( op == ae_op_divide )
1347 LR( te_dur, te_int ) right = rhs->cast_to = &t_float;
1350 // array
1351 if( op == ae_op_shift_left && isa( left, &t_array ) )
1353 // type of array
1354 Chuck_Type * atype = left->array_type;
1355 // check type
1356 if( isa( atype, &t_float ) )
1358 if( right->xid == te_int ) right = rhs->cast_to = &t_float;
1360 else if( isa( atype, &t_complex ) )
1362 if( right->xid == te_int || right->xid == te_float
1363 || right->xid == te_polar ) right = rhs->cast_to = &t_complex;
1365 else if( isa( atype, &t_polar ) )
1367 if( right->xid == te_int || right->xid == te_float
1368 || right->xid == te_complex ) right = rhs->cast_to = &t_complex;
1373 // objects
1374 switch( op )
1376 case ae_op_plus:
1377 case ae_op_plus_chuck:
1378 // take care of string
1379 if( isa( left, &t_string ) )
1381 // right is string or int/float
1382 if( isa( right, &t_string ) || isa( right, &t_int )
1383 || isa( right, &t_float ) )
1384 break;
1386 else if( isa( left, &t_string ) || isa( left, &t_int )
1387 || isa( left, &t_float ) )
1389 // right is string
1390 if( isa( right, &t_string ) )
1391 break;
1393 case ae_op_minus:
1394 case ae_op_times:
1395 case ae_op_divide:
1396 //case ae_op_lt:
1397 //case ae_op_le:
1398 //case ae_op_gt:
1399 //case ae_op_ge:
1400 case ae_op_percent:
1401 case ae_op_minus_chuck:
1402 case ae_op_times_chuck:
1403 case ae_op_divide_chuck:
1404 case ae_op_percent_chuck:
1405 if( isa( left, &t_object ) ) {
1406 EM_error2( lhs->linepos, "cannot perform '%s' on object references...",
1407 op2str(op) );
1408 return NULL;
1410 if( isa( right, &t_object ) ) {
1411 EM_error2( lhs->linepos, "cannot perform '%s' on object references...",
1412 op2str(op) );
1413 return NULL;
1415 break;
1417 default: break;
1420 // make sure
1421 switch( op )
1423 case ae_op_plus_chuck:
1424 case ae_op_minus_chuck:
1425 case ae_op_times_chuck:
1426 case ae_op_divide_chuck:
1427 case ae_op_percent_chuck:
1428 case ae_op_s_and_chuck:
1429 case ae_op_s_or_chuck:
1430 case ae_op_s_xor_chuck:
1431 case ae_op_shift_left_chuck:
1432 case ae_op_shift_right_chuck:
1433 // make sure mutable
1434 if( rhs->s_meta != ae_meta_var )
1436 EM_error2( lhs->linepos,
1437 "cannot assign '%s' on types '%s' %s '%s'...",
1438 op2str( op ), left->c_name(), op2str( op ), right->c_name() );
1439 EM_error2( lhs->linepos,
1440 "...(reason: --- right-side operand is not mutable)" );
1441 return NULL;
1444 // mark to emit var instead of value
1445 rhs->emit_var = 1;
1447 break;
1449 default: break;
1452 // based on the op
1453 switch( op )
1455 case ae_op_chuck:
1456 return type_engine_check_op_chuck( env, lhs, rhs, binary );
1458 case ae_op_unchuck:
1459 return type_engine_check_op_unchuck( env, lhs, rhs );
1461 case ae_op_upchuck:
1462 return type_engine_check_op_upchuck( env, lhs, rhs );
1464 case ae_op_at_chuck:
1465 return type_engine_check_op_at_chuck( env, lhs, rhs );
1467 case ae_op_plus_chuck:
1468 if( isa( left, &t_string ) && isa( right, &t_string ) ) return &t_string;
1469 if( isa( left, &t_int ) && isa( right, &t_string ) ) return &t_string;
1470 if( isa( left, &t_float ) && isa( right, &t_string ) ) return &t_string;
1471 case ae_op_plus:
1472 LR( te_int, te_int ) return &t_int;
1473 LR( te_float, te_float ) return &t_float;
1474 LR( te_dur, te_dur ) return &t_dur;
1475 LR( te_complex, te_complex ) return &t_complex;
1476 LR( te_polar, te_polar ) return &t_polar;
1477 // COMMUTE( te_float, te_complex ) return &t_complex;
1478 // COMMUTE( te_float, te_polar ) return &t_polar;
1479 COMMUTE( te_dur, te_time ) return &t_time;
1480 if( isa( left, &t_string ) && isa( right, &t_string ) ) return &t_string;
1481 if( isa( left, &t_string ) && isa( right, &t_int ) ) return &t_string;
1482 if( isa( left, &t_string ) && isa( right, &t_float ) ) return &t_string;
1483 if( isa( left, &t_int ) && isa( right, &t_string ) ) return &t_string;
1484 if( isa( left, &t_float ) && isa( right, &t_string ) ) return &t_string;
1485 break;
1487 case ae_op_minus:
1488 LR( te_time, te_time ) return &t_dur;
1489 LR( te_time, te_dur ) return &t_time;
1490 LR( te_int, te_int ) return &t_int;
1491 LR( te_float, te_float ) return &t_float;
1492 LR( te_dur, te_dur ) return &t_dur;
1493 LR( te_complex, te_complex ) return &t_complex;
1494 LR( te_polar, te_polar ) return &t_polar;
1495 // COMMUTE( te_float, te_complex ) return &t_complex;
1496 // COMMUTE( te_float, te_polar ) return &t_polar;
1497 break;
1499 // take care of non-commutative
1500 case ae_op_minus_chuck:
1501 LR( te_int, te_int ) return &t_int;
1502 LR( te_float, te_float ) return &t_float;
1503 LR( te_dur, te_dur ) return &t_dur;
1504 LR( te_dur, te_time ) return &t_time;
1505 LR( te_complex, te_complex ) return &t_complex;
1506 LR( te_polar, te_polar ) return &t_polar;
1507 // COMMUTE( te_float, te_complex ) return &t_complex;
1508 // COMMUTE( te_float, te_polar ) return &t_polar;
1509 break;
1511 case ae_op_times_chuck:
1512 case ae_op_times:
1513 LR( te_int, te_int ) return &t_int;
1514 LR( te_float, te_float ) return &t_float;
1515 LR( te_complex, te_complex ) return &t_complex;
1516 LR( te_polar, te_polar ) return &t_polar;
1517 // COMMUTE( te_float, te_complex ) return &t_complex;
1518 // COMMUTE( te_float, te_polar ) return &t_polar;
1519 COMMUTE( te_float, te_dur ) return &t_dur;
1520 break;
1522 case ae_op_divide:
1523 LR( te_dur, te_dur ) return &t_float;
1524 LR( te_time, te_dur ) return &t_float;
1525 LR( te_dur, te_float ) return &t_dur;
1526 LR( te_int, te_int ) return &t_int;
1527 LR( te_float, te_float ) return &t_float;
1528 LR( te_complex, te_complex ) return &t_complex;
1529 LR( te_polar, te_polar ) return &t_polar;
1530 // COMMUTE( te_float, te_complex ) return &t_complex;
1531 // COMMUTE( te_float, te_polar ) return &t_polar;
1532 break;
1534 // take care of non-commutative
1535 case ae_op_divide_chuck:
1536 LR( te_int, te_int ) return &t_int;
1537 LR( te_float, te_float ) return &t_float;
1538 LR( te_float, te_dur ) return &t_dur;
1539 LR( te_complex, te_complex ) return &t_complex;
1540 LR( te_polar, te_polar ) return &t_polar;
1541 // COMMUTE( te_float, te_complex ) return &t_complex;
1542 // COMMUTE( te_float, te_polar ) return &t_polar;
1543 break;
1545 case ae_op_eq:
1546 // null
1547 // if( isa( left, &t_object ) && isa( right, &t_null ) ) return &t_int;
1548 // if( isa( left, &t_null ) && isa( right, &t_object ) ) return &t_int;
1549 case ae_op_lt:
1550 case ae_op_gt:
1551 case ae_op_le:
1552 case ae_op_ge:
1553 case ae_op_neq:
1554 LR( te_int, te_int ) return &t_int;
1555 LR( te_float, te_float ) return &t_int;
1556 LR( te_dur, te_dur ) return &t_int;
1557 LR( te_time, te_time ) return &t_int;
1558 LR( te_complex, te_complex ) return &t_int;
1559 LR( te_polar, te_polar ) return &t_int;
1560 // COMMUTE( te_float, te_complex ) return &t_int;
1561 // COMMUTE( te_float, te_polar ) return &t_int;
1562 if( isa( left, &t_object ) && isa( right, &t_object ) ) return &t_int;
1563 break;
1565 case ae_op_s_and_chuck:
1566 case ae_op_s_or_chuck:
1567 case ae_op_s_xor_chuck:
1568 case ae_op_shift_right_chuck:
1569 case ae_op_shift_left_chuck:
1570 // the above are non-commutative
1571 case ae_op_and:
1572 case ae_op_or:
1573 case ae_op_s_xor:
1574 case ae_op_s_and:
1575 case ae_op_s_or:
1576 case ae_op_shift_left:
1577 // prepend || append
1578 if( isa( left, &t_array ) )
1580 // sanity check
1581 assert( left->array_type != NULL );
1582 // check type
1583 if( isa( right, left->array_type ) ) return left;
1584 // both arrays
1585 if( right->array_depth > 0 && left->array_depth > 0 )
1586 if( right->array_type == left->array_type &&
1587 right->array_depth + 1 == left->array_depth ) return left;
1589 case ae_op_shift_right:
1590 // shift
1591 LR( te_int, te_int ) return &t_int;
1592 break;
1594 case ae_op_percent:
1595 LR( te_time, te_dur ) return &t_dur;
1596 LR( te_dur, te_dur ) return &t_dur;
1597 LR( te_int, te_int ) return &t_int;
1598 LR( te_float, te_float ) return &t_float;
1599 break;
1601 // take of non-commutative
1602 case ae_op_percent_chuck:
1603 LR( te_int, te_int ) return &t_int;
1604 LR( te_float, te_float ) return &t_float;
1605 LR( te_dur, te_dur ) return &t_dur;
1606 break;
1608 default: break;
1611 // no match
1612 EM_error2( lhs->linepos,
1613 "cannot resolve operator '%s' on types '%s' and '%s'",
1614 op2str( op ), left->c_name(), right->c_name() );
1615 return NULL;
1621 //-----------------------------------------------------------------------------
1622 // name: type_engine_check_op_chuck()
1623 // desc: ...
1624 //-----------------------------------------------------------------------------
1625 t_CKTYPE type_engine_check_op_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs,
1626 a_Exp_Binary binary )
1628 t_CKTYPE left = lhs->type, right = rhs->type;
1630 // chuck to function
1631 if( isa( right, &t_function ) )
1633 // treat this function call
1634 return type_engine_check_exp_func_call( env, rhs, lhs, binary->ck_func, binary->linepos );
1637 // multi-value not supported beyond this for now
1638 if( lhs->next || rhs->next )
1640 EM_error2( lhs->linepos,
1641 "multi-value (=>) operation not supported/implemented..." );
1642 return NULL;
1645 // ugen => ugen
1646 if( isa( left, &t_ugen ) && isa( right, &t_ugen ) )
1648 // make sure non-zero
1649 if( left->ugen_info->num_outs == 0 )
1651 // error
1652 EM_error2( lhs->linepos,
1653 "ugen's of type '%s' have no output - cannot => to another ugen...",
1654 left->c_name() );
1655 return NULL;
1657 else if( right->ugen_info->num_ins == 0 )
1659 // error
1660 EM_error2( rhs->linepos,
1661 "ugen's of type '%s' have no input - cannot => from another ugen...",
1662 right->c_name() );
1663 return NULL;
1666 return right;
1669 // time advance ( dur => now )
1670 if( isa( left, &t_dur ) && isa( right, &t_time ) && rhs->s_meta == ae_meta_var
1671 && rhs->s_type == ae_exp_primary && !strcmp( "now", S_name(rhs->primary.var) ) )
1673 return right;
1676 // event wait ( Event => now )
1677 if( isa( left, &t_event ) && isa( right, &t_time ) && rhs->s_meta == ae_meta_var
1678 && rhs->s_type == ae_exp_primary && !strcmp( "now", S_name(rhs->primary.var) ) )
1680 return right;
1683 // object.toString
1685 // implicit cast
1686 LR( te_int, te_float ) left = lhs->cast_to = &t_float;
1687 LR( te_int, te_complex ) left = lhs->cast_to = &t_complex;
1688 LR( te_int, te_polar ) left = lhs->cast_to = &t_polar;
1690 // assignment or something else
1691 if( isa( left, right ) )
1693 // basic types?
1694 if( type_engine_check_primitive( left ) || isa( left, &t_string ) )
1696 // if the right is a decl, then make sure ref
1697 if( isa( left, &t_string ) && rhs->s_type == ae_exp_decl )
1699 rhs->decl.type->ref = TRUE;
1701 // TODO: const
1702 // assigment?
1703 if( rhs->s_meta == ae_meta_var )
1705 // emit ref - remember for emitter
1706 rhs->emit_var = TRUE;
1707 // right side
1708 return right;
1711 // error
1712 EM_error2( lhs->linepos,
1713 "cannot chuck/assign '=>' on types '%s' => '%s'...",
1714 left->c_name(), right->c_name() );
1715 EM_error2( lhs->linepos,
1716 "...(reason: right-side operand is not mutable)" );
1717 return NULL;
1719 // aggregate types
1720 else
1722 // TODO: check overloading of =>
1724 // no match
1725 EM_error2( lhs->linepos,
1726 "cannot resolve operator '=>' on types '%s' and '%s'...",
1727 left->c_name(), right->c_name() );
1728 EM_error2( lhs->linepos,
1729 "...(note: use '@=>' for object reference assignment)" );
1730 return NULL;
1734 // TODO: check overloading of =>
1736 // no match
1737 EM_error2( lhs->linepos,
1738 "cannot resolve operator '=>' on types '%s' and '%s'...",
1739 left->c_name(), right->c_name() );
1741 return NULL;
1747 //-----------------------------------------------------------------------------
1748 // name: type_engine_check_op_unchuck()
1749 // desc: ...
1750 //-----------------------------------------------------------------------------
1751 t_CKTYPE type_engine_check_op_unchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs )
1753 t_CKTYPE left = lhs->type, right = rhs->type;
1755 // ugen =< ugen
1756 if( isa( left, &t_ugen ) && isa( right, &t_ugen ) ) return right;
1758 // TODO: check overloading of =<
1760 // no match
1761 EM_error2( lhs->linepos,
1762 "no suitable resolution for binary operator '=<'..." );
1763 EM_error2( lhs->linepos,
1764 "...on types '%s' and '%s'",
1765 left->c_name(), right->c_name() );
1767 return NULL;
1773 //-----------------------------------------------------------------------------
1774 // name: type_engine_check_op_upchuck()
1775 // desc: ...
1776 //-----------------------------------------------------------------------------
1777 t_CKTYPE type_engine_check_op_upchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs )
1779 t_CKTYPE left = lhs->type, right = rhs->type;
1781 // uana =^ uana
1782 if( isa( left, &t_uana ) && isa( right, &t_uana ) ) return right;
1784 // TODO: check overloading of =^
1786 // no match
1787 EM_error2( lhs->linepos,
1788 "no suitable resolution for binary operator '=^'..." );
1789 EM_error2( lhs->linepos,
1790 "...on types '%s' and '%s'",
1791 left->c_name(), right->c_name() );
1793 return NULL;
1799 //-----------------------------------------------------------------------------
1800 // name: type_engine_check_op_at_chuck()
1801 // desc: ...
1802 //-----------------------------------------------------------------------------
1803 t_CKTYPE type_engine_check_op_at_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs )
1805 t_CKTYPE left = lhs->type, right = rhs->type;
1807 // static
1808 //if( isa( left, &t_class ) )
1810 // EM_error2( lhs->linepos,
1811 // "cannot assign '@=>' using static class as left operand..." );
1812 // return NULL;
1814 //else if( isa( right, &t_class ) )
1816 // EM_error2( rhs->linepos,
1817 // "cannot assign '@=>' using static class as right operand..." );
1818 // return NULL;
1821 // make sure mutable
1822 if( rhs->s_meta != ae_meta_var )
1824 EM_error2( lhs->linepos,
1825 "cannot assign '@=>' on types '%s' @=> '%s'...",
1826 left->c_name(), right->c_name() );
1827 EM_error2( lhs->linepos,
1828 "...(reason: --- right-side operand is not mutable)" );
1829 return NULL;
1832 // if the right is a decl, then make sure ref
1833 if( rhs->s_type == ae_exp_decl )
1835 rhs->decl.type->ref = TRUE;
1838 // implicit cast
1839 LR( te_int, te_float ) left = lhs->cast_to = &t_float;
1841 // primitive
1842 if( !isa( left, right ) )
1844 EM_error2( lhs->linepos,
1845 "cannot assign '@=>' on types '%s' @=> '%s'...",
1846 left->c_name(), right->c_name() );
1847 EM_error2( lhs->linepos,
1848 "...(reason: --- incompatible types for assignment)" );
1849 return NULL;
1852 // assign
1853 rhs->emit_var = TRUE;
1855 return right;
1861 //-----------------------------------------------------------------------------
1862 // name: type_engine_check_exp_unary()
1863 // desc: ...
1864 //-----------------------------------------------------------------------------
1865 t_CKTYPE type_engine_check_exp_unary( Chuck_Env * env, a_Exp_Unary unary )
1867 Chuck_Type * t = NULL;
1869 // make sure
1870 if( unary->exp )
1872 // assert( unary->op == ae_op_new );
1873 t = type_engine_check_exp( env, unary->exp );
1874 if( !t ) return NULL;
1877 // check the op
1878 switch( unary->op )
1880 case ae_op_plusplus:
1881 case ae_op_minusminus:
1882 // assignable?
1883 if( unary->exp->s_meta != ae_meta_var )
1885 EM_error2( unary->linepos,
1886 "prefix unary operator '%s' cannot "
1887 "be used on non-mutable data-types...", op2str( unary->op ) );
1888 return NULL;
1891 // assign
1892 unary->exp->emit_var = TRUE;
1894 // check type
1895 if( isa( t, &t_int ) || isa( t, &t_float ) )
1896 return t;
1898 // TODO: check overloading
1899 break;
1901 case ae_op_minus:
1902 // float
1903 if( isa( t, &t_float ) ) return t;
1904 case ae_op_tilda:
1905 case ae_op_exclamation:
1906 // int
1907 if( isa( t, &t_int ) ) return t;
1908 break;
1910 case ae_op_spork:
1911 // spork shred (by function call)
1912 if( unary->exp && unary->exp->s_type == ae_exp_func_call ) return &t_shred;
1913 // spork shred (by code segment)
1914 // else if( unary->code ) return &t_shred;
1915 // got a problem
1916 else
1918 EM_error2( unary->linepos,
1919 "only function calls can be sporked..." );
1920 return NULL;
1922 break;
1924 case ae_op_new:
1925 // look up the type
1926 // t = env->curr->lookup_type( unary->type->xid->xid, TRUE );
1927 t = type_engine_find_type( env, unary->type->xid );
1928 if( !t )
1930 EM_error2( unary->linepos,
1931 "... in 'new' expression ..." );
1932 return NULL;
1935 // []
1936 if( unary->array )
1938 // verify there are no errors from the parser...
1939 if( !verify_array( unary->array ) )
1940 return NULL;
1942 // if empty
1943 if( !unary->array->exp_list )
1945 EM_error2( unary->linepos, "cannot use empty [] with 'new'..." );
1946 return NULL;
1949 // type check the exp
1950 if( !type_engine_check_exp( env, unary->array->exp_list ) )
1951 return NULL;
1952 // make sure types are of int
1953 if( !type_engine_check_array_subscripts( env, unary->array->exp_list ) )
1954 return NULL;
1956 // create the new array type, replace t
1957 t = new_array_type(
1958 env, // the env
1959 &t_array, // the array base class, usually &t_array
1960 unary->array->depth, // the depth of the new type
1961 t, // the 'array_type'
1962 env->curr // the owner namespace
1965 // TODO: ref?
1968 // make sure the type is not a primitive
1969 if( isa( t, &t_int ) || isa( t, &t_float ) || isa( t, &t_dur )
1970 || isa( t, &t_time ) )
1972 EM_error2( unary->linepos,
1973 "cannot instantiate/(new) primitive type '%s'...",
1974 t->c_name() );
1975 EM_error2( unary->linepos,
1976 "...(primitive types: 'int', 'float', 'time', 'dur')" );
1977 return NULL;
1980 // make sure the type is not a reference
1981 if( unary->type->ref && !unary->array )
1983 EM_error2( unary->linepos,
1984 "cannot instantiate/(new) single object references (@)..." );
1985 return NULL;
1988 // return the type
1989 return t;
1990 break;
1992 default: break;
1995 // no match
1996 EM_error2( unary->linepos,
1997 "no suitable resolution for prefix unary operator '%s' on type '%s...",
1998 op2str( unary->op ), t->c_name() );
1999 return NULL;
2005 //-----------------------------------------------------------------------------
2006 // name: type_engine_check_exp_primary()
2007 // desc: ...
2008 //-----------------------------------------------------------------------------
2009 t_CKTYPE type_engine_check_exp_primary( Chuck_Env * env, a_Exp_Primary exp )
2011 t_CKTYPE t = NULL;
2012 Chuck_Value * v = NULL;
2013 string str;
2015 // check syntax
2016 switch( exp->s_type )
2018 // variable
2019 case ae_primary_var:
2020 str = S_name(exp->var);
2022 // check it
2023 if( str == "this" ) // this
2025 // in class def
2026 if( !env->class_def )
2028 EM_error2( exp->linepos,
2029 "keyword 'this' can be used only inside class definition..." );
2030 return NULL;
2033 // in member func
2034 if( env->func && !env->func->is_member )
2036 EM_error2( exp->linepos,
2037 "keyword 'this' cannot be used inside static functions..." );
2038 return NULL;
2041 // not assignable
2042 exp->self->s_meta = ae_meta_value;
2043 // whatever the class is
2044 t = env->class_def;
2046 else if( str == "me" ) // me
2048 // not assignable
2049 exp->self->s_meta = ae_meta_value;
2050 // refers to shred
2051 t = &t_shred;
2053 else if( str == "now" ) // now
2055 // assignable in a strongly timed way
2056 exp->self->s_meta = ae_meta_var;
2057 // time
2058 t = &t_time;
2060 else if( str == "dac" ) // dac
2062 // not assignable
2063 exp->self->s_meta = ae_meta_value;
2064 // ugen
2065 t = g_t_dac;
2067 else if( str == "adc" ) // adc
2069 // not assignable
2070 exp->self->s_meta = ae_meta_value;
2071 // ugen
2072 t = g_t_adc;
2074 else if( str == "blackhole" ) // blackhole
2076 // non assignable
2077 exp->self->s_meta = ae_meta_value;
2078 // ugen
2079 t = &t_ugen;
2081 else if( str == "null" || str == "NULL" ) // null / NULL
2083 // not assignable
2084 exp->self->s_meta = ae_meta_value;
2085 // refers to null
2086 t = &t_null;
2088 else // look up
2090 // look in local scope first
2091 // v = env->curr->lookup_value( exp->var, FALSE );
2092 v = type_engine_find_value( env, S_name(exp->var), FALSE );
2093 if( !v )
2095 // if in class
2096 if( env->class_def )
2098 // see if in parent
2099 v = type_engine_find_value( env->class_def->parent, exp->var );
2102 // still not found
2103 if( !v )
2105 // look globally
2106 // v = env->curr->lookup_value( exp->var, TRUE );
2107 v = type_engine_find_value( env, S_name(exp->var), TRUE, exp->linepos );
2110 // check
2111 if( v )
2113 // inside a class
2114 if( env->class_def )
2116 // inside a function definition
2117 if( env->func )
2119 // if func static, v not
2120 if( env->func->def->static_decl == ae_key_static &&
2121 v->is_member && !v->is_static )
2123 EM_error2( exp->linepos,
2124 "non-static member '%s' used from static function...", S_name(exp->var) );
2125 return NULL;
2130 // error
2131 else
2133 // checking for class scope incorrect (thanks Robin Davies)
2134 if( !env->class_def /* || env->class_scope > 0 */ )
2136 EM_error2( exp->linepos,
2137 "undefined variable '%s'...", S_name(exp->var) );
2138 return NULL;
2140 else
2142 EM_error2( exp->linepos,
2143 "undefined variable/member '%s' in class/namespace '%s'...",
2144 S_name(exp->var), env->class_def->name.c_str() );
2145 return NULL;
2150 // make sure v is legit as this point
2151 if( !v->is_decl_checked )
2153 EM_error2( exp->linepos,
2154 "variable/member '%s' is used before declaration...",
2155 S_name(exp->var) );
2156 return NULL;
2159 // the type
2160 t = v->type;
2161 // remember
2162 exp->value = v;
2164 break;
2166 // int
2167 case ae_primary_num:
2168 t = &t_int;
2169 break;
2171 // float
2172 case ae_primary_float:
2173 t = &t_float;
2174 break;
2176 // string
2177 case ae_primary_str:
2178 // escape the thing
2179 if( !escape_str( exp->str, exp->linepos ) )
2180 return NULL;
2182 // a string
2183 t = &t_string;
2184 break;
2186 // array literal
2187 case ae_primary_array:
2188 t = type_engine_check_exp_array_lit( env, exp );
2189 break;
2191 // complex literal
2192 case ae_primary_complex:
2193 t = type_engine_check_exp_complex_lit( env, exp );
2194 break;
2196 // polar literal
2197 case ae_primary_polar:
2198 t = type_engine_check_exp_polar_lit( env, exp );
2199 break;
2201 // expression
2202 case ae_primary_exp:
2203 t = type_engine_check_exp( env, exp->exp );
2204 break;
2206 // hack
2207 case ae_primary_hack:
2208 // make sure not l-value
2209 if( exp->exp->s_type == ae_exp_decl )
2211 EM_error2( exp->linepos,
2212 "cannot use <<< >>> on variable declarations..." );
2213 return NULL;
2216 t = type_engine_check_exp( env, exp->exp );
2217 break;
2219 // nil
2220 case ae_primary_nil:
2221 t = &t_void;
2222 break;
2224 // no match
2225 default:
2226 EM_error2( exp->linepos,
2227 "internal error - unrecognized primary type '%i'...", exp->s_type );
2228 return NULL;
2231 return t;
2237 //-----------------------------------------------------------------------------
2238 // name: type_engine_check_exp_array_lit()
2239 // desc: ...
2240 //-----------------------------------------------------------------------------
2241 t_CKTYPE type_engine_check_exp_array_lit( Chuck_Env * env, a_Exp_Primary exp )
2243 // make sure
2244 assert( exp->s_type == ae_primary_array );
2246 // type
2247 Chuck_Type * t = NULL, * type = NULL, * common = NULL;
2249 // verify there are no errors from the parser...
2250 if( !verify_array( exp->array ) )
2251 return NULL;
2253 // verify they are of same type - do this later?
2254 a_Exp e = exp->array->exp_list;
2256 // can't be []
2257 if( !e )
2259 EM_error2( exp->linepos,
2260 "must provide values/expressions for array [...]" );
2261 return NULL;
2264 // go through the array and type check each
2265 if( !type_engine_check_exp( env, e ) )
2266 return NULL;
2268 // loop
2269 while( e )
2271 // get the type
2272 t = e->type;
2274 // compare
2275 if( !type )
2277 // first
2278 type = t;
2280 else
2282 // find common ancestor
2283 common = type_engine_find_common_anc( t, type );
2284 // update type
2285 if( common ) type = common;
2286 // no common
2287 else
2289 // maybe one is int and other is float
2290 if( isa( t, &t_int ) && isa( type, &t_float ) )
2292 // cast from int to float
2293 e->cast_to = type;
2295 else
2297 // incompatible
2298 EM_error2( e->linepos, "array init [...] contains incompatible types..." );
2299 return NULL;
2304 // next exp
2305 e = e->next;
2308 // make sure
2309 assert( type != NULL );
2311 // treat static and dynamic separately
2312 // exp->array->is_dynamic = !is_static_array_lit( env, exp->array->exp_list );
2314 // create the new array type
2315 t = new_array_type(
2316 env, // the env
2317 &t_array, // the array base class, usually &t_array
2318 type->array_depth + 1, // the depth of the new type
2319 type->array_depth ? type->array_type : type, // the 'array_type'
2320 env->curr // the owner namespace
2324 // create the new type
2325 t = env->context->new_Chuck_Type();
2326 // set the xid
2327 t->xid = te_array;
2328 // set the name
2329 t->name = type->name;
2330 // set the parent
2331 t->parent = &t_array;
2332 // is a ref
2333 t->size = t_array.size;
2334 // set the array depth
2335 t->array_depth = type->array_depth + 1;
2336 // set the base type
2337 t->array_type = type->array_depth ? type->array_type : type;
2338 // TODO: verify the following is correct
2339 // set namespace
2340 t->info = t_array.info;
2341 // add reference
2342 t->info->add_ref();
2343 // set owner
2344 t->owner = env->curr;
2347 return t;
2353 //-----------------------------------------------------------------------------
2354 // name: type_engine_check_exp_complex_lit()
2355 // desc: ...
2356 //-----------------------------------------------------------------------------
2357 t_CKTYPE type_engine_check_exp_complex_lit( Chuck_Env * env, a_Exp_Primary exp )
2359 // make sure
2360 assert( exp->s_type == ae_primary_complex );
2362 // type
2363 Chuck_Type * type_re = NULL, * type_im = NULL;
2365 // get the complex
2366 a_Complex val = exp->complex;
2368 // check if we have enough
2369 if( val->im == NULL )
2371 EM_error2( exp->linepos,
2372 "missing imaginary component in complex value...\n"
2373 " --> format: #(re,im)" );
2374 return NULL;
2376 // check if we have too much
2377 if( val->im->next != NULL )
2379 EM_error2( exp->linepos,
2380 "extraneous arguments in complex value...\n"
2381 " --> format #(re,im)" );
2382 return NULL;
2385 // find types (only need real, since imag is linked after real)
2386 if( !(type_re = type_engine_check_exp( env, val->re )) )
2387 // || !(type_im = type_engine_check_exp( env, val->im )) )
2388 return NULL;
2390 // imaginary
2391 type_im = val->im->type;
2393 // check types
2394 if( !isa( type_re, &t_float ) && !isa( type_re, &t_int ) )
2396 EM_error2( exp->linepos,
2397 "invalid type '%s' in real component of complex value...\n"
2398 " (must be of type 'int' or 'float')", type_re->c_name() );
2399 return NULL;
2401 if( !isa( type_im, &t_float ) && !isa( type_im, &t_int ) )
2403 EM_error2( exp->linepos,
2404 "invalid type '%s' in imaginary component of complex value...\n"
2405 " (must be of type 'int' or 'float')", type_im->c_name() );
2406 return NULL;
2409 // implcit cast
2410 if( isa( type_re, &t_int ) ) val->re->cast_to = &t_float;
2411 if( isa( type_im, &t_int ) ) val->im->cast_to = &t_float;
2413 return &t_complex;
2419 //-----------------------------------------------------------------------------
2420 // name: type_engine_check_exp_polar_lit()
2421 // desc: ...
2422 //-----------------------------------------------------------------------------
2423 t_CKTYPE type_engine_check_exp_polar_lit( Chuck_Env * env, a_Exp_Primary exp )
2425 // make sure
2426 assert( exp->s_type == ae_primary_polar );
2428 // type
2429 Chuck_Type * type_mod = NULL, * type_phase = NULL;
2431 // get the polar
2432 a_Polar val = exp->polar;
2434 // check if we have enough
2435 if( val->phase == NULL )
2437 EM_error2( exp->linepos,
2438 "missing phase component in polar value...\n"
2439 " --> format: %%(mag,phase)" );
2440 return NULL;
2442 // check if we have extra
2443 if( val->phase->next != NULL )
2445 EM_error2( exp->linepos,
2446 "extraneous arguments in polar value...\n"
2447 " --> format: %%(mag,phase)" );
2448 return NULL;
2451 // find types
2452 if( !(type_mod = type_engine_check_exp( env, val->mod )) ||
2453 !(type_phase = type_engine_check_exp( env, val->phase )) )
2454 return NULL;
2456 // check types
2457 if( !isa( type_mod, &t_float ) && !isa( type_mod, &t_int ) )
2459 EM_error2( exp->linepos,
2460 "invalid type '%s' in magnitude component of polar value...\n"
2461 " (must be of type 'int' or 'float')", type_mod->c_name() );
2462 return NULL;
2464 if( !isa( type_phase, &t_float ) && !isa( type_phase, &t_int ) )
2466 EM_error2( exp->linepos,
2467 "invalid type '%s' in phase component of polar value...\n"
2468 " (must be of type 'int' or 'float')", type_phase->c_name() );
2469 return NULL;
2472 // implcit cast
2473 if( isa( type_mod, &t_int ) ) val->mod->cast_to = &t_float;
2474 if( isa( type_phase, &t_int ) ) val->phase->cast_to = &t_float;
2476 return &t_polar;
2482 //-----------------------------------------------------------------------------
2483 // name: type_engine_check_exp_cast()
2484 // desc: ...
2485 //-----------------------------------------------------------------------------
2486 t_CKTYPE type_engine_check_exp_cast( Chuck_Env * env, a_Exp_Cast cast )
2488 // check the exp
2489 t_CKTYPE t = type_engine_check_exp( env, cast->exp );
2490 if( !t ) return NULL;
2492 // the type to cast to
2493 // t_CKTYPE t2 = env->curr->lookup_type( cast->type->xid->xid, TRUE );
2494 t_CKTYPE t2 = type_engine_find_type( env, cast->type->xid );
2495 if( !t2 )
2497 EM_error2( cast->linepos, "... in cast expression ..." );
2498 return NULL;
2501 // check if cast valid
2502 if( !type_engine_check_cast_valid( env, t2, t ) )
2504 EM_error2( cast->linepos,
2505 "invalid cast to '%s' from '%s'...",
2506 S_name( cast->type->xid->xid ), t->c_name() );
2507 return NULL;
2510 return t2;
2516 //-----------------------------------------------------------------------------
2517 // name: type_engine_check_cast_valid()
2518 // desc: ...
2519 //-----------------------------------------------------------------------------
2520 t_CKBOOL type_engine_check_cast_valid( Chuck_Env * env, t_CKTYPE to, t_CKTYPE from )
2522 // down cast
2523 if( isa( from, to ) ) return TRUE;
2525 // up cast
2526 if( isa( to, from ) ) return TRUE;
2528 // TODO: dynamic type checking
2530 // int to float, float to int
2531 if( isa( to, &t_float ) && isa( from, &t_int ) ) return TRUE;
2532 if( isa( to, &t_int ) && isa( from, &t_float ) ) return TRUE;
2533 if( isa( to, &t_complex ) && isa( from, &t_int ) ) return TRUE;
2534 if( isa( to, &t_polar ) && isa( from, &t_int ) ) return TRUE;
2535 if( isa( to, &t_complex ) && isa( from, &t_float ) ) return TRUE;
2536 if( isa( to, &t_polar ) && isa( from, &t_float ) ) return TRUE;
2537 if( isa( to, &t_complex ) && isa( from, &t_polar ) ) return TRUE;
2538 if( isa( to, &t_polar ) && isa( from, &t_complex ) ) return TRUE;
2540 return FALSE;
2546 //-----------------------------------------------------------------------------
2547 // name: type_engine_check_exp_dur()
2548 // desc: ...
2549 //-----------------------------------------------------------------------------
2550 t_CKTYPE type_engine_check_exp_dur( Chuck_Env * env, a_Exp_Dur dur )
2552 // type check the two components
2553 t_CKTYPE base = type_engine_check_exp( env, dur->base );
2554 t_CKTYPE unit = type_engine_check_exp( env, dur->unit );
2556 // make sure both type check
2557 if( !base || !unit ) return NULL;
2559 // check base type
2560 if( !isa( base, &t_int ) && !isa( base, &t_float ) )
2562 EM_error2( dur->base->linepos,
2563 "invalid type '%s' in prefix of dur expression...\n"
2564 " (must be of type 'int' or 'float')", base->c_name() );
2565 return NULL;
2568 // check unit type
2569 if( !isa( unit, &t_dur ) )
2571 EM_error2( dur->unit->linepos,
2572 "invalid type '%s' in postfix of dur expression...\n"
2573 " (must be of type 'dur')", unit->c_name() );
2574 return NULL;
2577 return unit;
2583 //-----------------------------------------------------------------------------
2584 // name: type_engine_check_exp_postfix()
2585 // desc: ...
2586 //-----------------------------------------------------------------------------
2587 t_CKTYPE type_engine_check_exp_postfix( Chuck_Env * env, a_Exp_Postfix postfix )
2589 // check the exp
2590 t_CKTYPE t = type_engine_check_exp( env, postfix->exp );
2591 if( !t ) return NULL;
2593 // syntax
2594 switch( postfix->op )
2596 case ae_op_plusplus:
2597 case ae_op_minusminus:
2598 // assignable?
2599 if( postfix->exp->s_meta != ae_meta_var )
2601 EM_error2( postfix->exp->linepos,
2602 "postfix operator '%s' cannot be used on non-mutable data-type...",
2603 op2str( postfix->op ) );
2604 return NULL;
2607 postfix->exp->emit_var = TRUE;
2608 // TODO: mark somewhere we need to post increment
2610 // check type
2611 if( isa( t, &t_int ) || isa( t, &t_float ) )
2612 return t;
2613 break;
2615 default:
2616 // no match
2617 EM_error2( postfix->linepos,
2618 "internal compiler error: unrecognized postfix '%i'", postfix->op );
2619 return NULL;
2622 // no match
2623 EM_error2( postfix->linepos,
2624 "no suitable resolutation for postfix operator '%s' on type '%s'...",
2625 op2str( postfix->op ), t->c_name() );
2626 return NULL;
2632 //-----------------------------------------------------------------------------
2633 // name: type_engine_check_exp_if()
2634 // desc: ...
2635 //-----------------------------------------------------------------------------
2636 t_CKTYPE type_engine_check_exp_if( Chuck_Env * env, a_Exp_If exp_if )
2638 // check the components
2639 t_CKTYPE cond = type_engine_check_exp( env, exp_if->cond );
2640 t_CKTYPE if_exp = type_engine_check_exp( env, exp_if->if_exp );
2641 t_CKTYPE else_exp = type_engine_check_exp( env, exp_if->else_exp );
2643 // make sure everything good
2644 if( !cond || !if_exp || !else_exp ) return NULL;
2646 // check the type
2647 if( !isa( cond, &t_int ) ) return NULL;
2649 // make sure the if and else have compatible types
2650 // TODO: the lesser of two types
2651 if( !( *if_exp == *else_exp ) )
2653 EM_error2( exp_if->linepos,
2654 "incompatible types '%s' and '%s' in if expression...",
2655 if_exp->c_name(), else_exp->c_name() );
2656 return NULL;
2659 return if_exp;
2665 //-----------------------------------------------------------------------------
2666 // name: type_engine_check_array_subscripts( )
2667 // desc: ...
2668 //-----------------------------------------------------------------------------
2669 t_CKBOOL type_engine_check_array_subscripts( Chuck_Env * env, a_Exp exp_list )
2671 a_Exp exp = exp_list;
2673 // loop through
2674 while( exp )
2676 // if not int
2677 if( !isa( exp->type, &t_int ) )
2679 EM_error2( exp->linepos,
2680 "incompatible array subscript type '%s'...",
2681 exp->type->name.c_str() );
2682 return FALSE;
2685 exp = exp->next;
2688 return TRUE;
2694 //-----------------------------------------------------------------------------
2695 // name: type_engine_check_exp_decl( )
2696 // desc: ...
2697 //-----------------------------------------------------------------------------
2698 t_CKTYPE type_engine_check_exp_decl( Chuck_Env * env, a_Exp_Decl decl )
2700 a_Var_Decl_List list = decl->var_decl_list;
2701 a_Var_Decl var_decl = NULL;
2702 Chuck_Type * type = NULL;
2703 Chuck_Value * value = NULL;
2704 t_CKBOOL is_obj = FALSE;
2705 t_CKBOOL is_ref = FALSE;
2707 // loop through the variables
2708 while( list != NULL )
2710 // get the decl
2711 var_decl = list->var_decl;
2713 // (if at class_scope) check if in parent
2714 // TODO: sort
2715 if( env->class_def && env->class_scope == 0 && ( value =
2716 type_engine_find_value( env->class_def->parent, var_decl->xid ) ) )
2718 EM_error2( var_decl->linepos,
2719 "'%s' has already been defined in super class '%s'...",
2720 S_name(var_decl->xid), value->owner_class->c_name() );
2721 return NULL;
2724 // get the value
2725 value = var_decl->value;
2726 // make sure
2727 assert( value != NULL );
2728 // get the type
2729 type = value->type;
2730 // make sure
2731 assert( type != NULL );
2732 // is object
2733 is_obj = isobj( type );
2734 // is ref
2735 is_ref = decl->type->ref;
2737 // if array, then check to see if empty []
2738 if( var_decl->array && var_decl->array->exp_list != NULL )
2740 // instantiate object, including array
2741 if( !type_engine_check_exp( env, var_decl->array->exp_list ) )
2742 return FALSE;
2744 // check the subscripts
2745 if( !type_engine_check_array_subscripts( env, var_decl->array->exp_list ) )
2746 return FALSE;
2749 // member?
2750 if( value->is_member )
2752 // offset
2753 value->offset = env->curr->offset;
2754 // move the offset (TODO: check the size)
2755 env->curr->offset += type->size;
2757 else if( decl->is_static ) // static
2759 // base scope
2760 if( env->class_def == NULL || env->class_scope > 0 )
2762 EM_error2( decl->linepos,
2763 "static variables must be declared at class scope..." );
2764 return FALSE;
2767 // flag
2768 value->is_static = TRUE;
2769 // offset
2770 value->offset = env->class_def->info->class_data_size;
2771 // move the size
2772 env->class_def->info->class_data_size += type->size;
2774 // if this is an object
2775 if( is_obj && !is_ref )
2777 // for now - no good for static, since we need separate
2778 // initialization which we don't have
2779 EM_error2( var_decl->linepos,
2780 "cannot declare static non-primitive objects (yet)..." );
2781 EM_error2( var_decl->linepos,
2782 "...(hint: declare as ref (@) & initialize outside for now)" );
2783 return FALSE;
2786 else // local variable
2788 // do nothing?
2791 // mark the decl checked (see scan pass 2)
2792 value->is_decl_checked = TRUE;
2794 // add the value, if we are not at class scope
2795 // (otherwise they should already have been added)
2796 if( !env->class_def || env->class_scope > 0 )
2798 // add as value
2799 env->curr->value.add( var_decl->xid, value );
2802 // the next var decl
2803 list = list->next;
2806 return decl->ck_type;
2812 //-----------------------------------------------------------------------------
2813 // name: type_engine_print_exp_dot_member()
2814 // desc: ...
2815 //-----------------------------------------------------------------------------
2816 string type_engine_print_exp_dot_member( Chuck_Env * env, a_Exp_Dot_Member member )
2818 // UNUSED: Chuck_Value * value = NULL;
2819 Chuck_Type * the_base = NULL;
2820 t_CKBOOL base_static = FALSE;
2821 string str;
2823 // type check the base
2824 member->t_base = type_engine_check_exp( env, member->base );
2825 if( !member->t_base ) return "[error]";
2827 // is the base a class/namespace or a variable
2828 base_static = isa( member->t_base, &t_class );
2829 // actual type
2830 the_base = base_static ? member->t_base->actual_type : member->t_base;
2832 // this
2833 str = S_name(member->xid);
2835 return string(the_base->c_name()) + std::string(".") + str;
2841 //-----------------------------------------------------------------------------
2842 // name: find_func_match()
2843 // desc: ...
2844 //-----------------------------------------------------------------------------
2845 Chuck_Func * find_func_match( Chuck_Func * up, a_Exp args, t_CKBOOL implicit )
2847 a_Exp e;
2848 a_Arg_List e1;
2849 t_CKUINT count;
2850 Chuck_Func * func;
2852 // see if args is nil
2853 if( args && args->type == &t_void )
2854 args = NULL;
2856 // up is the list of functions in single class / namespace
2857 while( up )
2859 func = up;
2860 // loop
2861 while( func )
2863 e = args;
2864 e1 = func->def->arg_list;
2865 count = 1;
2867 // check arguments against the definition
2868 while( e )
2870 // check for extra arguments
2871 if( e1 == NULL ) goto moveon;
2873 // no match
2874 if( !isa( e->type, e1->type ) )
2876 // TODO: fix this for overload implicit cast (multiple matches)
2877 if( implicit && *e->type == t_int && *e1->type == t_float )
2879 // int to float
2880 e->cast_to = &t_float;
2882 else goto moveon; // type mismatch
2885 e = e->next;
2886 e1 = e1->next;
2887 count++;
2890 // check for extra arguments
2891 if( e1 == NULL ) return func;
2893 moveon:
2894 // next func
2895 func = func->next;
2898 // go up
2899 if( up->up ) up = up->up->func_ref;
2900 else up = NULL;
2903 // not found
2904 return NULL;
2910 //-----------------------------------------------------------------------------
2911 // name: type_engine_check_exp_func_call()
2912 // desc: ...
2913 //-----------------------------------------------------------------------------
2914 t_CKTYPE type_engine_check_exp_func_call( Chuck_Env * env, a_Exp exp_func, a_Exp args,
2915 t_CKFUNC & ck_func, int linepos )
2917 Chuck_Func * func = NULL;
2918 Chuck_Func * up = NULL;
2920 // type check the func
2921 t_CKTYPE f = exp_func->type = type_engine_check_exp( env, exp_func );
2922 if( !f ) return NULL;
2924 // void type for args
2925 t_CKTYPE a = &t_void;
2927 // make sure we have a function
2928 if( !isa( f, &t_function ) )
2930 EM_error2( exp_func->linepos,
2931 "function call using a non-function value" );
2932 return NULL;
2935 // copy the func
2936 up = f->func;
2938 // check the arguments
2939 if( args )
2941 a = type_engine_check_exp( env, args );
2942 if( !a ) return NULL;
2945 // look for a match
2946 func = find_func_match( up, args, FALSE );
2947 // look for a match (with implicit cast)
2948 if( !func ) func = find_func_match( up, args, TRUE );
2950 // no func
2951 if( !func )
2953 // if primary
2954 if( exp_func->s_type == ae_exp_primary && exp_func->primary.s_type == ae_primary_var )
2956 EM_error2( exp_func->linepos,
2957 "argument type(s) do not match:" );
2958 EM_error2( exp_func->linepos,
2959 "... for function '%s(...)' ...",
2960 S_name(exp_func->primary.var) );
2962 else if( exp_func->s_type == ae_exp_dot_member )
2964 EM_error2( exp_func->linepos,
2965 "arguments type(s) do not match:" );
2966 EM_error2( exp_func->linepos,
2967 "... for function '%s(...)' ...",
2968 type_engine_print_exp_dot_member( env, &exp_func->dot_member ).c_str() );
2970 else
2972 EM_error2( exp_func->linepos,
2973 "argument type(s) do not match for function ..." );
2976 EM_error2( exp_func->linepos,
2977 "...(please check the argument types)" );
2979 return NULL;
2982 // recheck the type with new name
2983 if( exp_func->s_type == ae_exp_primary && exp_func->primary.s_type == ae_primary_var )
2985 // set the new name
2986 // TODO: clear old
2987 exp_func->primary.var = insert_symbol(func->name.c_str());
2988 // make sure the type is still the name
2989 if( *exp_func->type != *type_engine_check_exp( env, exp_func ) )
2991 // error
2992 EM_error2( exp_func->linepos,
2993 "internal error: function type different on second check..." );
2994 return NULL;
2997 else if( exp_func->s_type == ae_exp_dot_member )
2999 // set the new name
3000 // TODO: clear old
3001 exp_func->dot_member.xid = insert_symbol(func->name.c_str());
3003 // TODO: figure if this is necessary - it type checks things twice!
3004 // make sure the type is still the name
3005 if( *exp_func->type != *type_engine_check_exp( env, exp_func ) )
3007 // error
3008 EM_error2( exp_func->linepos,
3009 "internal error: function type different on second check..." );
3010 return NULL;
3014 else assert( FALSE );
3016 ck_func = func;
3018 return func->def->ret_type;
3024 //-----------------------------------------------------------------------------
3025 // name: type_engine_check_exp_func_call()
3026 // desc: ...
3027 //-----------------------------------------------------------------------------
3028 t_CKTYPE type_engine_check_exp_func_call( Chuck_Env * env, a_Exp_Func_Call func_call )
3030 // type check it
3031 return type_engine_check_exp_func_call( env, func_call->func, func_call->args,
3032 func_call->ck_func, func_call->linepos );
3038 //-----------------------------------------------------------------------------
3039 // name: type_engine_check_exp_dot_member()
3040 // desc: ...
3041 //-----------------------------------------------------------------------------
3042 t_CKTYPE type_engine_check_exp_dot_member( Chuck_Env * env, a_Exp_Dot_Member member )
3044 Chuck_Value * value = NULL;
3045 Chuck_Type * the_base = NULL;
3046 t_CKBOOL base_static = FALSE;
3047 string str;
3049 // type check the base
3050 member->t_base = type_engine_check_exp( env, member->base );
3051 if( !member->t_base ) return NULL;
3053 // if complex or polar
3054 if( member->t_base->xid == te_complex ) // TODO: constants!!!
3056 // get as string
3057 string str = S_name(member->xid);
3058 // verify member is either re or im
3059 if( str == "re" || str == "im" )
3061 // check addressing consistency (ISSUE: emit_var set after!)
3062 if( member->self->emit_var && member->base->s_meta == ae_meta_var )
3064 // error
3065 EM_error2( member->base->linepos,
3066 "cannot assign value to literal complex value..." );
3067 return NULL;
3070 return &t_float;
3072 else
3074 // not valid
3075 EM_error2( member->linepos,
3076 "type '%s' has no member named '%s'...", member->t_base->c_name(), str.c_str() );
3077 return NULL;
3080 else if( member->t_base->xid == te_polar )
3082 // get as string
3083 string str = S_name(member->xid);
3084 // verify member is either re or im
3085 if( str == "mag" || str == "phase" )
3087 // check addressing consistency (ISSUE: emit_var set after!)
3088 if( member->self->emit_var && member->base->s_meta == ae_meta_var )
3090 // error
3091 EM_error2( member->base->linepos,
3092 "cannot assign value to literal polar value..." );
3093 return NULL;
3096 return &t_float;
3098 else
3100 // not valid
3101 EM_error2( member->linepos,
3102 "type '%s' has no member named '%s'...", member->t_base->c_name(), str.c_str() );
3103 return NULL;
3107 // is the base a class/namespace or a variable
3108 base_static = isa( member->t_base, &t_class );
3109 // actual type
3110 the_base = base_static ? member->t_base->actual_type : member->t_base;
3112 // have members?
3113 if( !the_base->info )
3115 // base type does not have members
3116 EM_error2( member->base->linepos,
3117 "type '%s' does not have members - invalid use in dot expression",
3118 the_base->c_name() );
3119 return NULL;
3122 // this
3123 str = S_name(member->xid);
3124 if( str == "this" )
3126 // uh
3127 if( base_static )
3129 EM_error2( member->linepos,
3130 "keyword 'this' must be associated with object instance..." );
3131 return NULL;
3133 // in member func
3134 if( env->func && !env->func->is_member )
3136 EM_error2( member->linepos,
3137 "keyword 'this' cannot be used inside static functions..." );
3138 return NULL;
3141 return env->class_def;
3144 // find the value
3145 value = type_engine_find_value( the_base, member->xid );
3146 if( !value )
3148 // can't find member
3149 EM_error2( member->base->linepos,
3150 "class '%s' has no member '%s'",
3151 the_base->c_name(), S_name(member->xid) );
3152 return NULL;
3155 // make sure
3156 if( base_static && value->is_member )
3158 // this won't work
3159 EM_error2( member->linepos,
3160 "cannot access member '%s.%s' without object instance...",
3161 the_base->c_name(), S_name(member->xid) );
3162 return NULL;
3165 return value->type;
3171 //-----------------------------------------------------------------------------
3172 // name: type_engine_check_exp_array()
3173 // desc: ...
3174 //-----------------------------------------------------------------------------
3175 t_CKTYPE type_engine_check_exp_array( Chuck_Env * env, a_Exp_Array array )
3177 // verify there are no errors from the parser...
3178 if( !verify_array( array->indices ) )
3179 return NULL;
3181 // type check the base
3182 t_CKTYPE t_base = type_engine_check_exp( env, array->base );
3183 if( !t_base ) return NULL;
3185 // dimension
3186 if( array->indices->depth > t_base->array_depth )
3188 EM_error2( array->linepos,
3189 "array subscripts (%i) exceeds defined dimension (%i)",
3190 array->indices->depth, t_base->array_depth );
3191 return NULL;
3194 // type check the index
3195 t_CKTYPE t_index = type_engine_check_exp( env, array->indices->exp_list );
3196 if( !t_index ) return NULL;
3198 // cycle through each exp
3199 a_Exp e = array->indices->exp_list;
3200 // count the dimension
3201 t_CKUINT depth = 0;
3203 while( e )
3205 // increment
3206 depth++;
3207 // check if index is of valid type
3208 if( !isa( e->type, &t_int ) && !isa( e->type, &t_string ) )
3210 // not int or string
3211 EM_error2( e->linepos,
3212 "array index %i must be of type 'int' or 'string', not '%s'",
3213 depth, e->type->c_name() );
3214 return NULL;
3217 // advance the list
3218 e = e->next;
3221 // sanity
3222 assert( array->indices->depth == depth );
3224 t_CKTYPE t = NULL;
3225 // make sure depth <= max
3226 if( depth == t_base->array_depth )
3228 // the original type
3229 t = array->base->type->array_type;
3231 else
3233 // partial
3234 t = array->base->type->copy( env );
3235 // remainder
3236 t->array_depth -= depth;
3239 return t;
3245 //-----------------------------------------------------------------------------
3246 // name: type_engine_check_class_def()
3247 // desc: ...
3248 //-----------------------------------------------------------------------------
3249 t_CKBOOL type_engine_check_class_def( Chuck_Env * env, a_Class_Def class_def )
3251 // make new type for class def
3252 t_CKTYPE the_class = NULL;
3253 // the parent class
3254 t_CKTYPE t_parent = NULL;
3255 // the return type
3256 t_CKBOOL ret = TRUE;
3257 // the class body
3258 a_Class_Body body = class_def->body;
3260 // make sure inheritance
3261 // TODO: sort!
3262 if( class_def->ext )
3264 // if extend
3265 if( class_def->ext->extend_id )
3267 // find the type
3268 t_parent = type_engine_find_type( env, class_def->ext->extend_id );
3269 if( !t_parent )
3271 EM_error2( class_def->ext->linepos,
3272 "undefined super class '%s' in definition of class '%s'",
3273 type_path(class_def->ext->extend_id), S_name(class_def->name->xid) );
3274 return FALSE;
3277 // must not be primitive
3278 if( isprim( t_parent ) )
3280 EM_error2( class_def->ext->linepos,
3281 "cannot extend primitive type '%s'",
3282 t_parent->c_name() );
3283 EM_error2( class_def->ext->linepos,
3284 "...(note: primitives types are 'int', 'float', 'time', and 'dur')" );
3285 return FALSE;
3288 // if not complete
3289 if( t_parent->is_complete == FALSE )
3291 EM_error2( class_def->ext->linepos,
3292 "cannot extend incomplete type '%s'",
3293 t_parent->c_name() );
3294 EM_error2( class_def->ext->linepos,
3295 "...(note: the parent's declaration must preceed child's)" );
3296 return FALSE;
3300 // TODO: interface
3303 // by default object
3304 if( !t_parent ) t_parent = &t_object;
3306 // check for fun
3307 assert( env->context != NULL );
3308 assert( class_def->type != NULL );
3309 assert( class_def->type->info != NULL );
3311 // retrieve the new type (created in scan_class_def)
3312 the_class = class_def->type;
3314 // set fields not set in scan
3315 the_class->parent = t_parent;
3316 // inherit ugen_info data from parent PLD
3317 the_class->ugen_info = t_parent->ugen_info;
3318 // set the beginning of data segment to after the parent
3319 the_class->info->offset = t_parent->obj_size;
3320 // duplicate the parent's virtual table
3321 the_class->info->obj_v_table = t_parent->info->obj_v_table;
3323 // set the new type as current
3324 env->nspc_stack.push_back( env->curr );
3325 env->curr = the_class->info;
3326 // push the class def
3327 env->class_stack.push_back( env->class_def );
3328 env->class_def = the_class;
3329 // reset the nest list
3330 env->class_scope = 0;
3332 // type check the body
3333 while( body && ret )
3335 // check the section
3336 switch( body->section->s_type )
3338 case ae_section_stmt:
3339 // flag as having a constructor
3340 env->class_def->has_constructor |= (body->section->stmt_list->stmt != NULL);
3341 ret = type_engine_check_stmt_list( env, body->section->stmt_list );
3342 break;
3344 case ae_section_func:
3345 // set to complete
3346 env->class_def->is_complete = TRUE;
3347 ret = type_engine_check_func_def( env, body->section->func_def );
3348 // back
3349 env->class_def->is_complete = FALSE;
3350 break;
3352 case ae_section_class:
3353 // check it
3354 ret = type_engine_check_class_def( env, body->section->class_def );
3355 break;
3358 // move to the next section
3359 body = body->next;
3362 // pop the class
3363 env->class_def = env->class_stack.back();
3364 env->class_stack.pop_back();
3365 // pop the namesapce
3366 env->curr = env->nspc_stack.back();
3367 env->nspc_stack.pop_back();
3369 // if ok
3370 if( ret )
3372 // set the object size
3373 the_class->obj_size = the_class->info->offset;
3374 // set complete
3375 the_class->is_complete = TRUE;
3377 if( !ret )
3379 // delete the class definition
3380 SAFE_RELEASE( class_def->type );
3381 // set the thing to NULL
3382 the_class = NULL;
3385 return ret;
3391 //-----------------------------------------------------------------------------
3392 // name: type_engine_check_func_def()
3393 // desc: ...
3394 //-----------------------------------------------------------------------------
3395 t_CKBOOL type_engine_check_func_def( Chuck_Env * env, a_Func_Def f )
3397 Chuck_Value * value = NULL;
3398 Chuck_Func * func = NULL;
3400 Chuck_Type * parent = NULL;
3401 Chuck_Value * override = NULL;
3402 Chuck_Value * v = NULL;
3403 Chuck_Func * parent_func = NULL;
3404 a_Arg_List arg_list = NULL;
3405 t_CKBOOL parent_match = FALSE;
3406 string func_name = S_name(f->name);
3407 t_CKUINT count = 0;
3408 t_CKBOOL has_code = FALSE; // use this for both user and imported
3410 // see if we are already in a function definition
3411 if( env->func != NULL )
3413 EM_error2( f->linepos,
3414 "nested function definitions are not (yet) allowed" );
3415 return FALSE;
3418 // get the func
3419 func = f->ck_func;
3420 // get the value
3421 value = func->value_ref;
3422 // make sure
3423 assert( func != NULL && value != NULL );
3425 // look up the value in the parent class
3426 if( env->class_def &&
3427 ( override = type_engine_find_value( env->class_def->parent, f->name ) ) )
3429 // see if the target is a function
3430 if( !isa( override->type, &t_function ) )
3432 EM_error2( f->linepos, "function name '%s' conflicts with previously defined value...",
3433 S_name(f->name) );
3434 EM_error2( f->linepos, "from super class '%s'...", override->owner_class->c_name() );
3435 return FALSE;
3439 // make sure a code segment is in stmt - else we should push scope
3440 assert( !f->code || f->code->s_type == ae_stmt_code );
3442 // if override
3443 if( override )
3445 // make reference to parent
3446 // TODO: ref count
3447 func->up = override;
3450 // make sure return type is not NULL
3451 assert( f->ret_type != NULL );
3453 // only class functions can be pure
3454 if( !env->class_def && f->static_decl == ae_key_abstract )
3456 EM_error2( f->linepos, "non-class function cannot be declared as 'pure'..." );
3457 EM_error2( f->linepos, "...at function '%s'", S_name(f->name) );
3458 goto error;
3461 // figure out if the function has code associated with it
3462 if( f->s_type == ae_func_user ) has_code = ( f->code != NULL );
3463 else has_code = (f->dl_func_ptr != NULL); // imported
3465 // if interface, then cannot have code
3466 if( env->class_def && env->class_def->def && env->class_def->def->iface && has_code )
3468 EM_error2( f->linepos, "interface function signatures cannot contain code..." );
3469 EM_error2( f->linepos, "...at function '%s'", S_name(f->name) );
3470 goto error;
3473 // if pure, then cannot have code
3474 if( f->static_decl == ae_key_abstract && has_code )
3476 EM_error2( f->linepos, "'pure' function signatures cannot contain code..." );
3477 EM_error2( f->linepos, "...at function '%s'", S_name(f->name) );
3478 goto error;
3481 // yeah
3482 if( f->static_decl != ae_key_abstract && !has_code )
3484 EM_error2( f->linepos, "function declaration must contain code..." );
3485 EM_error2( f->linepos, "(unless in interface, or is declared 'pure')" );
3486 EM_error2( f->linepos, "...at function '%s'", S_name(f->name) );
3487 goto error;
3490 // if overriding super class function, then check signatures
3491 if( env->class_def )
3493 // get parent
3494 parent = env->class_def->parent;
3495 while( parent && !parent_match )
3497 if(( v = type_engine_find_value( env->class_def->parent, f->name ) ))
3499 // see if the target is a function
3500 if( !isa( v->type, &t_function ) )
3502 EM_error2( f->linepos, "function name '%s' conflicts with previously defined value...",
3503 S_name(f->name) );
3504 EM_error2( f->linepos, "from super class '%s'...", v->owner_class->c_name() );
3505 goto error;
3508 // parent func
3509 parent_func = v->func_ref;
3511 // go through all overloading
3512 while( parent_func && !parent_match )
3514 // match the prototypes
3515 string err;
3516 if( !type_engine_compat_func( f, parent_func->def, f->linepos, err, FALSE ) )
3518 // next
3519 parent_func = parent_func->next;
3520 // move on
3521 continue;
3524 EM_error2( f->linepos,
3525 "function '%s.%s' resembles '%s.%s' but cannot override...",
3526 env->class_def->c_name(), S_name(f->name),
3527 value->owner_class->c_name(), S_name(f->name) );
3528 if( err != "" ) EM_error2( f->linepos, "...(reason: %s)", err.c_str() );
3529 goto error;
3532 // see if parent function is static
3533 if( parent_func->def->static_decl == ae_key_static )
3535 EM_error2( f->linepos,
3536 "function '%s.%s' resembles '%s.%s' but cannot override...",
3537 env->class_def->c_name(), S_name(f->name),
3538 v->owner_class->c_name(), S_name(f->name) );
3539 EM_error2( f->linepos,
3540 "...(reason: '%s.%s' is declared as 'static')",
3541 v->owner_class->c_name(), S_name(f->name) );
3542 goto error;
3545 // see if function is static
3546 if( f->static_decl == ae_key_static )
3548 EM_error2( f->linepos,
3549 "function '%s.%s' resembles '%s.%s' but cannot override...",
3550 env->class_def->c_name(), S_name(f->name),
3551 v->owner_class->c_name(), S_name(f->name) );
3552 EM_error2( f->linepos,
3553 "...(reason: '%s.%s' is declared as 'static')",
3554 env->class_def->c_name(), S_name(f->name) );
3555 goto error;
3558 // see if function is pure
3559 if( f->static_decl == ae_key_abstract )
3561 EM_error2( f->linepos,
3562 "function '%s.%s' resembles '%s.%s' but cannot override...",
3563 env->class_def->c_name(), S_name(f->name),
3564 v->owner_class->c_name(), S_name(f->name) );
3565 EM_error2( f->linepos,
3566 "...(reason: '%s.%s' is declared as 'pure')",
3567 env->class_def->c_name(), S_name(f->name) );
3568 goto error;
3571 // make sure returns are equal
3572 if( *(f->ret_type) != *(parent_func->def->ret_type) )
3574 EM_error2( f->linepos, "function signatures differ in return type..." );
3575 EM_error2( f->linepos,
3576 "function '%s.%s' matches '%s.%s' but cannot override...",
3577 env->class_def->c_name(), S_name(f->name),
3578 v->owner_class->c_name(), S_name(f->name) );
3579 goto error;
3582 // match
3583 parent_match = TRUE;
3585 // update virtual table
3586 func->vt_index = parent_func->vt_index;
3587 assert( func->vt_index < env->curr->obj_v_table.funcs.size() );
3588 env->curr->obj_v_table.funcs[func->vt_index] = func;
3589 // update name
3590 func_name = parent_func->name;
3591 func->name = func_name;
3592 value->name = func_name;
3596 // move to next parent
3597 parent = parent->parent;
3601 // if not override, make entry in virtual table
3602 if( func->is_member && !parent_match )
3604 // remember virtual table index
3605 func->vt_index = env->curr->obj_v_table.funcs.size();
3606 // append to virtual table
3607 env->curr->obj_v_table.funcs.push_back( func );
3610 // set the current function to this
3611 env->func = func;
3612 // push the value stack
3613 env->curr->value.push();
3615 // look up types for the function arguments
3616 arg_list = f->arg_list;
3617 // count
3618 count = 1;
3619 // loop over arguments
3620 while( arg_list )
3622 // make sure type != NULL
3623 assert( arg_list->type != NULL );
3624 // get the value
3625 v = arg_list->var_decl->value;
3626 // make sure value != NULL
3627 assert( v != NULL );
3629 // look up in scope: later
3630 if( env->curr->lookup_value( arg_list->var_decl->xid, FALSE ) )
3632 EM_error2( arg_list->linepos, "in function '%s':", S_name(f->name) );
3633 EM_error2( arg_list->linepos, "argument %i '%s' is already defined in this scope",
3634 count, S_name(arg_list->var_decl->xid) );
3635 goto error;
3638 // add as value
3639 env->curr->value.add( arg_list->var_decl->xid, v );
3641 // increment count
3642 count++;
3643 // next arg
3644 arg_list = arg_list->next;
3647 // type check the code
3648 assert( f->code == NULL || f->code->s_type == ae_stmt_code );
3649 if( f->code && !type_engine_check_code_segment( env, &f->code->stmt_code, FALSE ) )
3651 EM_error2( 0, "...in function '%s'", S_name(f->name) );
3652 goto error;
3655 // if imported, add the stack depth
3656 if( f->s_type == ae_func_builtin )
3658 // set the stack depth?
3659 func->code->stack_depth = f->stack_depth;
3660 // if member add room for this
3661 // done: if( func->is_member ) func->code->stack_depth += sizeof(t_CKUINT);
3664 // pop the value stack
3665 env->curr->value.pop();
3667 // clear the env's function definition
3668 env->func = NULL;
3670 return TRUE;
3672 error:
3674 // clean up
3675 env->func = NULL;
3676 // func->release();
3678 return FALSE;
3684 //-----------------------------------------------------------------------------
3685 // name: lookup_type()
3686 // desc: lookup type in the env
3687 //-----------------------------------------------------------------------------
3688 Chuck_Type * Chuck_Namespace::lookup_type( const string & name, t_CKINT climb )
3690 Chuck_Type * t = type.lookup( name, climb );
3691 if( climb > 0 && !t && parent )
3692 return parent->lookup_type( name, climb );
3693 return t;
3699 //-----------------------------------------------------------------------------
3700 // name: lookup_type()
3701 // desc: lookup type in the env
3702 //-----------------------------------------------------------------------------
3703 Chuck_Type * Chuck_Namespace::lookup_type( S_Symbol name, t_CKINT climb )
3705 Chuck_Type * t = type.lookup( name, climb );
3706 if( climb > 0 && !t && parent )
3707 return parent->lookup_type( name, climb );
3708 return t;
3714 //-----------------------------------------------------------------------------
3715 // name: lookup_value()
3716 // desc: lookup value in the env
3717 //-----------------------------------------------------------------------------
3718 Chuck_Value * Chuck_Namespace::lookup_value( const string & name, t_CKINT climb )
3720 Chuck_Value * v = value.lookup( name, climb );
3721 if( climb > 0 && !v && parent )
3722 return parent->lookup_value( name, climb );
3723 return v;
3729 //-----------------------------------------------------------------------------
3730 // name: lookup_value()
3731 // desc: lookup value in the env
3732 //-----------------------------------------------------------------------------
3733 Chuck_Value * Chuck_Namespace::lookup_value( S_Symbol name, t_CKINT climb )
3735 Chuck_Value * v = value.lookup( name, climb );
3736 if( climb > 0 && !v && parent )
3737 return parent->lookup_value( name, climb );
3738 return v;
3744 //-----------------------------------------------------------------------------
3745 // name: lookup_func()
3746 // desc: lookup func in the env
3747 //-----------------------------------------------------------------------------
3748 Chuck_Func * Chuck_Namespace::lookup_func( const string & name, t_CKINT climb )
3750 Chuck_Func * f = func.lookup( name, climb );
3751 if( climb > 0 && !f && parent )
3752 return parent->lookup_func( name, climb );
3753 return f;
3759 //-----------------------------------------------------------------------------
3760 // name: lookup_func()
3761 // desc: lookup func in the env
3762 //-----------------------------------------------------------------------------
3763 Chuck_Func * Chuck_Namespace::lookup_func( S_Symbol name, t_CKINT climb )
3765 Chuck_Func * f = func.lookup( name, climb );
3766 if( climb > 0 && !f && parent )
3767 return parent->lookup_func( name, climb );
3768 return f;
3774 //-----------------------------------------------------------------------------
3775 // name: get_types()
3776 // desc: get top level types
3777 //-----------------------------------------------------------------------------
3778 void Chuck_Namespace::get_types( vector<Chuck_Type *> & out )
3780 // temporary vector
3781 vector<Chuck_VM_Object *> list;
3782 // get it from the scope
3783 this->type.get_toplevel( list );
3784 // clear
3785 out.clear();
3787 // copy the list - cast
3788 for( t_CKUINT i = 0; i < list.size(); i++ )
3789 out.push_back( (Chuck_Type *)list[i] );
3795 //-----------------------------------------------------------------------------
3796 // name: get_values()
3797 // desc: get top level values
3798 //-----------------------------------------------------------------------------
3799 void Chuck_Namespace::get_values( vector<Chuck_Value *> & out )
3801 // temporary vector
3802 vector<Chuck_VM_Object *> list;
3803 // get it from the scope
3804 this->value.get_toplevel( list );
3805 // clear
3806 out.clear();
3808 // copy the list - cast
3809 for( t_CKUINT i = 0; i < list.size(); i++ )
3810 out.push_back( (Chuck_Value *)list[i] );
3816 //-----------------------------------------------------------------------------
3817 // name: get_funcs()
3818 // desc: get top level functions
3819 //-----------------------------------------------------------------------------
3820 void Chuck_Namespace::get_funcs( vector<Chuck_Func *> & out )
3822 // temporary vector
3823 vector<Chuck_VM_Object *> list;
3824 // get it from the scope
3825 this->type.get_toplevel( list );
3826 // clear
3827 out.clear();
3829 // copy the list - cast
3830 for( t_CKUINT i = 0; i < list.size(); i++ )
3831 out.push_back( (Chuck_Func *)list[i] );
3837 //-----------------------------------------------------------------------------
3838 // name: operator ==
3839 // desc: ...
3840 //-----------------------------------------------------------------------------
3841 t_CKBOOL operator ==( const Chuck_Type & lhs, const Chuck_Type & rhs )
3843 // check id
3844 if( lhs.xid != rhs.xid ) return FALSE;
3845 // check array depth
3846 if( lhs.array_depth != rhs.array_depth ) return FALSE;
3847 // check array type
3848 if( lhs.array_depth && (*lhs.actual_type != *rhs.actual_type) ) return FALSE;
3850 // if user-defined type
3851 if( lhs.xid == te_user )
3853 // check name
3854 if( lhs.name != rhs.name ) return FALSE;
3855 // check owner
3856 if( lhs.owner != rhs.owner ) return FALSE;
3859 return TRUE;
3865 //-----------------------------------------------------------------------------
3866 // name: operator !=
3867 // desc: ...
3868 //-----------------------------------------------------------------------------
3869 t_CKBOOL operator !=( const Chuck_Type & lhs, const Chuck_Type & rhs )
3870 { return !( lhs == rhs ); }
3875 //-----------------------------------------------------------------------------
3876 // name: equals()
3877 // desc: ...
3878 //-----------------------------------------------------------------------------
3879 t_CKBOOL equals( Chuck_Type * lhs, Chuck_Type * rhs ) { return (*lhs) == (*rhs); }
3884 //-----------------------------------------------------------------------------
3885 // name: operator <=
3886 // desc: ...
3887 //-----------------------------------------------------------------------------
3888 t_CKBOOL operator <=( const Chuck_Type & lhs, const Chuck_Type & rhs )
3890 // check to see if type L == type R
3891 if( lhs == rhs ) return TRUE;
3893 // if lhs is a child of rhs
3894 const Chuck_Type * curr = lhs.parent;
3895 while( curr )
3897 if( *curr == rhs ) return TRUE;
3898 curr = curr->parent;
3901 // if lhs is null and rhs is a object
3902 if( lhs == t_null && (rhs <= t_object) ) return TRUE;
3904 return FALSE;
3910 //-----------------------------------------------------------------------------
3911 // name: isa()
3912 // desc: ...
3913 //-----------------------------------------------------------------------------
3914 t_CKBOOL isa( Chuck_Type * lhs, Chuck_Type * rhs ) { return (*lhs) <= (*rhs); }
3919 //-----------------------------------------------------------------------------
3920 // name: ~Chuck_Context()
3921 // desc: ...
3922 //-----------------------------------------------------------------------------
3923 Chuck_Context::~Chuck_Context()
3925 // if has error, then delete nspc. otherwise, the nspc stays as part of
3926 // the type system, since many things have been added to it
3927 if( has_error )
3929 SAFE_DELETE( nspc );
3931 // delete the types - can't do this since the type system and vm still use
3932 // for( t_CKINT i = 0; i < new_types.size(); i++ )
3933 // new_types[i]->release();
3935 // clear it
3936 new_types.clear();
3939 // TODO: delete abstract syntax tree *
3945 //-----------------------------------------------------------------------------
3946 // name: add_commit_candidate()
3947 // desc: ...
3948 //-----------------------------------------------------------------------------
3949 void Chuck_Context::add_commit_candidate( Chuck_Namespace * nspc )
3951 // add for commit
3952 commit_map[nspc] = nspc;
3958 //-----------------------------------------------------------------------------
3959 // name: commit()
3960 // desc: ...
3961 //-----------------------------------------------------------------------------
3962 void Chuck_Context::commit()
3964 std::map<Chuck_Namespace *, Chuck_Namespace *>::iterator iter;
3966 // loop through
3967 for( iter = commit_map.begin(); iter != commit_map.end(); iter++ )
3969 // commit
3970 (*iter).second->commit();
3973 // clear
3974 commit_map.clear();
3980 //-----------------------------------------------------------------------------
3981 // name: rollback()
3982 // desc: ...
3983 //-----------------------------------------------------------------------------
3984 void Chuck_Context::rollback()
3986 std::map<Chuck_Namespace *, Chuck_Namespace *>::iterator iter;
3988 // loop through
3989 for( iter = commit_map.begin(); iter != commit_map.end(); iter++ )
3991 // rollback
3992 (*iter).second->rollback();
3995 // clear
3996 commit_map.clear();
4002 //-----------------------------------------------------------------------------
4003 // name: type_engine_check_reserved()
4004 // desc: ...
4005 //--------------------------------------------------------------------------
4006 t_CKBOOL type_engine_check_reserved( Chuck_Env * env, const string & xid, int pos )
4008 // key word?
4009 if( env->key_words[xid] )
4011 EM_error2( pos, "illegal use of keyword '%s'.", xid.c_str() );
4012 return TRUE;
4015 // key value?
4016 if( env->key_values[xid] )
4018 EM_error2( pos, "illegal re-declaration of reserved value '%s'.", xid.c_str() );
4019 return TRUE;
4022 // key type?
4023 if( env->key_types[xid] )
4025 EM_error2( pos, "illegal use of reserved type id '%s'.", xid.c_str() );
4026 return TRUE;
4029 return FALSE;
4035 //-----------------------------------------------------------------------------
4036 // name: type_engine_check_reserved()
4037 // desc: ...
4038 //-----------------------------------------------------------------------------
4039 t_CKBOOL type_engine_check_reserved( Chuck_Env * env, S_Symbol xid, int pos )
4041 return type_engine_check_reserved( env, string(S_name(xid)), pos );
4047 //-----------------------------------------------------------------------------
4048 // name: type_engine_check_primitive()
4049 // desc: ...
4050 //-----------------------------------------------------------------------------
4051 t_CKBOOL type_engine_check_primitive( Chuck_Type * type )
4053 return ( isa(type, &t_int) || isa(type, &t_float) || isa(type, &t_dur) ||
4054 isa(type, &t_time) ) || isa(type, &t_complex) || isa(type, &t_polar)
4055 && ( type->array_depth == 0 );
4057 t_CKBOOL isprim( Chuck_Type * type )
4058 { return type_engine_check_primitive( type ); }
4059 t_CKBOOL isobj( Chuck_Type * type )
4060 { return !type_engine_check_primitive( type ); }
4061 t_CKBOOL isfunc( Chuck_Type * type )
4062 { return isa( type, &t_function ); }
4067 //-----------------------------------------------------------------------------
4068 // name: type_engine_find_common_anc()
4069 // desc: ...
4070 //-----------------------------------------------------------------------------
4071 Chuck_Type * type_engine_find_common_anc( Chuck_Type * lhs, Chuck_Type * rhs )
4073 // check to see if either is child of other
4074 if( isa( lhs, rhs ) ) return rhs;
4075 if( isa( rhs, lhs ) ) return lhs;
4077 // move up
4078 Chuck_Type * t = lhs->parent;
4080 // not at root
4081 while( t )
4083 // check and see again
4084 if( isa( rhs, t ) ) return t;
4085 // move up
4086 t = t->parent;
4089 // didn't find
4090 return NULL;
4096 //-----------------------------------------------------------------------------
4097 // name: type_path()
4098 // desc: ...
4099 //-----------------------------------------------------------------------------
4100 const char * type_path( a_Id_List path )
4102 static string str;
4104 // clear it
4105 str = "";
4106 // loop over path
4107 while( path )
4109 // concatenate
4110 str += S_name(path->xid);
4111 // add .
4112 if( path->next ) str += ".";
4113 // advance
4114 path = path->next;
4117 return str.c_str();
4123 //-----------------------------------------------------------------------------
4124 // name: type_engine_find_type()
4125 // desc: ...
4126 //-----------------------------------------------------------------------------
4127 Chuck_Type * type_engine_find_type( Chuck_Namespace * nspc, S_Symbol xid )
4129 Chuck_Type * type = NULL;
4130 if( !nspc) return NULL;
4131 // -1 for base
4132 if(( type = nspc->lookup_type( xid, -1 ) )) return type;
4133 return NULL;
4139 //-----------------------------------------------------------------------------
4140 // name: type_engine_get_deprecate()
4141 // desc: ...
4142 //-----------------------------------------------------------------------------
4143 t_CKBOOL type_engine_get_deprecate( Chuck_Env * env,
4144 const string & from, string & to )
4146 // find mapping
4147 if( env->deprecated.find( from ) == env->deprecated.end() )
4148 return FALSE;
4150 // return
4151 to = env->deprecated[from];
4153 return TRUE;
4159 //-----------------------------------------------------------------------------
4160 // name: type_engine_find_deprecated_type()
4161 // desc: ...
4162 //-----------------------------------------------------------------------------
4163 Chuck_Type * type_engine_find_deprecated_type( Chuck_Env * env, a_Id_List path )
4165 S_Symbol xid = NULL;
4166 Chuck_Type * t = NULL;
4167 std::string actual;
4169 // find mapping
4170 if( !type_engine_get_deprecate( env, S_name(path->xid), actual ) )
4171 return NULL;
4173 // get base type
4174 Chuck_Type * type = env->curr->lookup_type( actual, TRUE );
4175 if( !type ) return NULL;
4176 else
4178 // check level
4179 if( env->deprecate_level < 2 )
4181 EM_error2( path->linepos, "deprecated: '%s' --> use: '%s'...",
4182 type_path( path ), actual.c_str() );
4186 return type;
4192 //-----------------------------------------------------------------------------
4193 // name: type_engine_find_type()
4194 // desc: ...
4195 //-----------------------------------------------------------------------------
4196 Chuck_Type * type_engine_find_type( Chuck_Env * env, a_Id_List path )
4198 S_Symbol xid = NULL;
4199 Chuck_Type * t = NULL;
4200 // get base type
4201 Chuck_Type * type = env->curr->lookup_type( path->xid, TRUE );
4202 if( !type )
4204 // check level
4205 if( env->deprecate_level > 0 )
4206 type = type_engine_find_deprecated_type( env, path );
4208 // error
4209 if( !type )
4211 EM_error2( path->linepos, "undefined type '%s'...",
4212 type_path( path ) );
4213 return NULL;
4216 // start the namespace
4217 Chuck_Namespace * nspc = type->info;
4218 path = path->next;
4220 // loop
4221 while( path != NULL )
4223 // get the id
4224 xid = path->xid;
4225 // look for the type in the namespace
4226 t = type_engine_find_type( nspc, xid );
4227 // look in parent
4228 while( !t && type && type->parent )
4230 t = type_engine_find_type( type->parent->info, xid );
4231 type = type->parent;
4233 // can't find
4234 if( !t )
4236 // error
4237 EM_error2( path->linepos, "undefined type '%s'...",
4238 type_path( path ) );
4239 EM_error2( path->linepos,
4240 "...(cannot find class '%s' in namespace '%s')",
4241 S_name(xid), nspc->name.c_str() );
4242 return NULL;
4245 // set the type
4246 type = t;
4247 // update nspc
4248 if( type ) nspc = type->info;
4249 // advance
4250 path = path->next;
4253 return type;
4259 //-----------------------------------------------------------------------------
4260 // name: type_engine_find_value()
4261 // desc: ...
4262 //-----------------------------------------------------------------------------
4263 Chuck_Value * type_engine_find_value( Chuck_Type * type, S_Symbol xid )
4265 return type_engine_find_value( type, string(S_name(xid)) );
4271 //-----------------------------------------------------------------------------
4272 // name: type_engine_find_value()
4273 // desc: ...
4274 //-----------------------------------------------------------------------------
4275 Chuck_Value * type_engine_find_value( Chuck_Type * type, const string & xid )
4277 Chuck_Value * value = NULL;
4278 if( !type ) return NULL;
4279 if( !type->info ) return NULL;
4280 // -1 for base
4281 if(( value = type->info->lookup_value( xid, -1 ) )) return value;
4282 if( type->parent ) return type_engine_find_value( type->parent, xid );
4283 return NULL;
4289 //-----------------------------------------------------------------------------
4290 // name: type_engine_find_value()
4291 // desc: from env...
4292 //-----------------------------------------------------------------------------
4293 Chuck_Value * type_engine_find_value( Chuck_Env * env, const string & xid,
4294 t_CKBOOL climb, int linepos )
4296 Chuck_Value * value = NULL;
4297 string actual;
4299 // look up
4300 if(( value = env->curr->lookup_value( xid, climb ) )) return value;
4302 // see if deprecated if climb
4303 if( climb )
4305 if( !type_engine_get_deprecate( env, xid, actual ) )
4306 return NULL;
4308 // get base type
4309 value = env->curr->lookup_value( actual, TRUE );
4310 if( !value ) return NULL;
4311 else
4313 // check level
4314 if( env->deprecate_level < 2 )
4316 EM_error2( linepos, "deprecated: '%s' --> use: '%s'...",
4317 xid.c_str(), actual.c_str() );
4322 return value;
4328 //-----------------------------------------------------------------------------
4329 // name: type_engine_find_nspc()
4330 // desc: ...
4331 //-----------------------------------------------------------------------------
4332 Chuck_Namespace * type_engine_find_nspc( Chuck_Env * env, a_Id_List path )
4334 Chuck_Namespace * nspc = NULL;
4335 // if the first if global, move to the next
4336 if( path && !strcmp( S_name(path->xid), "global" ) ) path = path->next;
4337 // global namespace
4338 if( path == NULL ) return env->global();
4339 // find the type
4340 Chuck_Type * type = type_engine_find_type( env, path );
4341 if( type == NULL ) return NULL;
4342 // copy the nspc
4343 nspc = type->info;
4344 if( nspc == NULL )
4346 // primitive
4347 if( isprim( type ) )
4349 // error
4350 EM_error2( 0, "primitive type '%s' has no namespace and cannot be extended...",
4351 type->c_name() );
4352 return NULL;
4354 else
4356 // internal error
4357 EM_error2( 0, "internal error: type '%s' without namespace...",
4358 type->c_name() );
4359 return NULL;
4363 return nspc;
4369 //-----------------------------------------------------------------------------
4370 // name: type_engine_compat_func()
4371 // desc: see if two function signatures are compatible
4372 //-----------------------------------------------------------------------------
4373 t_CKBOOL type_engine_compat_func( a_Func_Def lhs, a_Func_Def rhs, int pos, string & err, t_CKBOOL print )
4375 // make sure public/private/protected/function match
4376 if( lhs->func_decl != rhs->func_decl )
4378 if( print )
4380 EM_error2( pos, "function signatures differ in access modifiers..." );
4381 EM_error2( pos, "(both must be one of public/private/protected/function)..." );
4383 return FALSE;
4386 a_Arg_List e1 = lhs->arg_list;
4387 a_Arg_List e2 = rhs->arg_list;
4388 t_CKUINT count = 1;
4390 // check arguments against the definition
4391 while( e1 && e2 )
4393 // make sure
4394 assert( e1->type && e2->type );
4396 // match types
4397 if( *e1->type != *e2->type )
4399 if( print ) EM_error2( pos, "function signatures differ in argument %i's type...", count );
4400 return FALSE;
4403 e1 = e1->next;
4404 e2 = e2->next;
4405 count++;
4408 // anything left
4409 if( e1 != NULL || e2 != NULL )
4411 if( print ) EM_error2( pos,
4412 "function signatures differ in number of arguments..." );
4413 return FALSE;
4416 return TRUE;
4422 //-----------------------------------------------------------------------------
4423 // name: type_engine_import_class_begin()
4424 // desc: import existing base class, such as Object or Event
4425 // must be completed by type_engine_import_class_end()
4426 //-----------------------------------------------------------------------------
4427 Chuck_Type * type_engine_import_class_begin( Chuck_Env * env, Chuck_Type * type,
4428 Chuck_Namespace * where,
4429 f_ctor pre_ctor, f_dtor dtor )
4431 Chuck_Value * value = NULL;
4432 Chuck_Type * type_type = NULL;
4434 // make sure there is not namesapce
4435 if( type->info != NULL )
4437 // error
4438 EM_error2( 0, "during import: class '%s' already imported...", type->c_name() );
4439 return NULL;
4442 // allocate namespace for type
4443 type->info = new Chuck_Namespace;
4444 // add reference
4445 SAFE_ADD_REF(type->info);
4446 // name it
4447 type->info->name = type->name;
4448 // set the parent namespace
4449 type->info->parent = where;
4450 // add reference
4451 SAFE_ADD_REF(type->info->parent);
4453 // if pre constructor
4454 if( pre_ctor != 0 )
4456 // flag it
4457 type->has_constructor = TRUE;
4458 // allocate vm code for pre_ctor
4459 type->info->pre_ctor = new Chuck_VM_Code;
4460 // add pre_ctor
4461 type->info->pre_ctor->native_func = (t_CKUINT)pre_ctor;
4462 // mark type as ctor
4463 type->info->pre_ctor->native_func_type = Chuck_VM_Code::NATIVE_CTOR;
4464 // specify that we need this
4465 type->info->pre_ctor->need_this = TRUE;
4466 // no arguments to preconstructor other than self
4467 type->info->pre_ctor->stack_depth = sizeof(t_CKUINT);
4470 // if destructor
4471 if( dtor != 0 )
4473 // flag it
4474 type->has_destructor = TRUE;
4475 // allocate vm code for dtor
4476 type->info->dtor = new Chuck_VM_Code;
4477 // add dtor
4478 type->info->dtor->native_func = (t_CKUINT)dtor;
4479 // mark type as dtor
4480 type->info->dtor->native_func_type = Chuck_VM_Code::NATIVE_DTOR;
4481 // specify that we need this
4482 type->info->dtor->need_this = TRUE;
4483 // no arguments to destructor other than self
4484 type->info->dtor->stack_depth = sizeof(t_CKUINT);
4487 // set the beginning of the data segment after parent
4488 if( type->parent )
4490 type->info->offset = type->parent->obj_size;
4491 // duplicate parent's virtual table
4492 assert( type->parent->info != NULL );
4493 type->info->obj_v_table = type->parent->info->obj_v_table;
4496 // set the owner namespace
4497 type->owner = where;
4498 // add reference
4499 SAFE_ADD_REF(type->owner);
4500 // set the size, which is always the width of a pointer
4501 type->size = sizeof(t_CKUINT);
4502 // set the object size
4503 type->obj_size = 0; // TODO
4505 // flag as complete
4506 type->is_complete = TRUE;
4507 // make type
4508 type_type = t_class.copy( env );
4509 type_type->actual_type = type;
4510 // SAFE_REF_ASSIGN( type_type->actual_type, type );
4512 // make value
4513 value = new Chuck_Value( type_type, type->name );
4514 value->owner = where;
4515 // SAFE_REF_ASSIGN( value->owner, where );
4516 value->is_const = TRUE;
4517 value->is_member = FALSE;
4519 // add to env
4520 where->value.add( value->name, value );
4522 // make the type current
4523 env->nspc_stack.push_back( env->curr );
4524 env->curr = type->info;
4525 // push the class def
4526 env->class_stack.push_back( env->class_def );
4527 env->class_def = type;
4529 // ref count
4530 type->add_ref();
4532 return type;
4538 //-----------------------------------------------------------------------------
4539 // name: type_engine_import_class_begin()
4540 // desc: ...
4541 //-----------------------------------------------------------------------------
4542 Chuck_Type * type_engine_import_class_begin( Chuck_Env * env, const char * name,
4543 const char * parent_str,
4544 Chuck_Namespace * where,
4545 f_ctor pre_ctor, f_dtor dtor )
4547 // which namespace
4548 Chuck_Type * parent = NULL;
4549 Chuck_Type * type = NULL;
4550 a_Id_List parent_list = NULL;
4552 // if parent is specified
4553 if( strcmp( parent_str, "") )
4555 // get parent
4556 parent_list = str2list( parent_str );
4557 parent = type_engine_find_type( env, parent_list );
4558 if( !parent ) goto error;
4560 else // if no parent specified, then extend Object
4562 parent = &t_object;
4565 // allocate type
4566 type = new Chuck_Type( te_user, name, parent, sizeof(void *) );
4568 // add to namespace - TODO: handle failure, remove from where
4569 where->type.add( name, type );
4571 // do the rest
4572 if( !type_engine_import_class_begin( env, type, where, pre_ctor, dtor ) )
4573 goto error;
4575 // done
4576 goto cleanup;
4578 error:
4579 // error
4580 EM_error2( 0, "... during import of class '%s'", name );
4581 // free
4582 SAFE_DELETE( type );
4584 cleanup:
4585 // cleanup
4586 delete_id_list( parent_list );
4588 return type;
4594 //-----------------------------------------------------------------------------
4595 // name: type_engine_import_ugen_begin()
4596 // desc: ...
4597 //-----------------------------------------------------------------------------
4598 Chuck_Type * type_engine_import_ugen_begin( Chuck_Env * env, const char * name,
4599 const char * parent, Chuck_Namespace * where,
4600 f_ctor pre_ctor, f_dtor dtor,
4601 f_tick tick, f_pmsg pmsg,
4602 t_CKUINT num_ins, t_CKUINT num_outs )
4604 Chuck_Type * type = NULL;
4605 Chuck_UGen_Info * info = NULL;
4607 // construct class
4608 if( !(type = type_engine_import_class_begin( env, name, parent, where, pre_ctor, dtor ) ) )
4609 return FALSE;
4611 // make sure parent is ugen
4612 assert( type->parent != NULL );
4613 if( !isa( type->parent, &t_ugen ) )
4615 // error
4616 EM_error2( 0,
4617 "imported class '%s' does not have a ugen as parent",
4618 type->c_name() );
4619 return FALSE;
4622 // do the ugen part
4623 info = new Chuck_UGen_Info;
4624 info->add_ref();
4625 info->tick = type->parent->ugen_info->tick;
4626 info->pmsg = type->parent->ugen_info->pmsg;
4627 info->num_ins = type->parent->ugen_info->num_ins;
4628 info->num_outs = type->parent->ugen_info->num_outs;
4629 if( tick ) info->tick = tick;
4630 if( pmsg ) info->pmsg = pmsg;
4631 if( num_ins != 0xffffffff ) info->num_ins = num_ins;
4632 if( num_outs != 0xffffffff ) info->num_outs = num_outs;
4633 // set in type
4634 type->ugen_info = info;
4636 return type;
4642 //-----------------------------------------------------------------------------
4643 // name: type_engine_import_uana_begin()
4644 // desc: ...
4645 //-----------------------------------------------------------------------------
4646 Chuck_Type * type_engine_import_uana_begin( Chuck_Env * env, const char * name,
4647 const char * parent, Chuck_Namespace * where,
4648 f_ctor pre_ctor, f_dtor dtor,
4649 f_tick tick, f_tock tock, f_pmsg pmsg,
4650 t_CKUINT num_ins, t_CKUINT num_outs,
4651 t_CKUINT num_ins_ana, t_CKUINT num_outs_ana )
4653 Chuck_Type * type = NULL;
4654 Chuck_UGen_Info * info = NULL;
4656 // construct class
4657 if( !(type = type_engine_import_ugen_begin( env, name, parent, where, pre_ctor, dtor,
4658 tick, pmsg, num_ins, num_outs ) ) )
4659 return FALSE;
4661 // make sure parent is ugen
4662 assert( type->parent != NULL );
4663 if( !isa( type->parent, &t_uana ) )
4665 // error
4666 EM_error2( 0,
4667 "imported class '%s' does not have a uana as parent",
4668 type->c_name() );
4669 return FALSE;
4672 // do the info
4673 info = type->ugen_info;
4674 // sanity
4675 assert( info != NULL );
4676 // set
4677 if( tock ) info->tock = tock;
4678 if( num_ins_ana != 0xffffffff ) info->num_ins_ana = num_ins_ana;
4679 if( num_outs_ana != 0xffffffff ) info->num_outs_ana = num_outs_ana;
4681 return type;
4687 //-----------------------------------------------------------------------------
4688 // name: type_engine_import_class_end()
4689 // desc: finish import of a class
4690 //-----------------------------------------------------------------------------
4691 t_CKBOOL type_engine_import_class_end( Chuck_Env * env )
4693 if( !env->class_def )
4695 // error
4696 EM_error2( 0, "import: too many class_end called..." );
4697 return FALSE;
4700 // set the object size
4701 env->class_def->obj_size = env->class_def->info->offset;
4703 // pop the class
4704 env->class_def = env->class_stack.back();
4705 env->class_stack.pop_back();
4706 // pop the namesapce
4707 env->curr = env->nspc_stack.back();
4708 env->nspc_stack.pop_back();
4710 return TRUE;
4716 //-----------------------------------------------------------------------------
4717 // name: type_engine_import_mfun()
4718 // desc: import member function (must be between class_begin/end)
4719 //-----------------------------------------------------------------------------
4720 t_CKBOOL type_engine_import_mfun( Chuck_Env * env, Chuck_DL_Func * mfun )
4722 a_Func_Def func_def = NULL;
4724 // make sure we are in class
4725 if( !env->class_def )
4727 // error
4728 EM_error2( 0,
4729 "import error: import_mfun '%s' invoked between begin/end",
4730 mfun->name.c_str() );
4731 return FALSE;
4734 // make into func_def
4735 func_def = make_dll_as_fun( mfun, FALSE );
4736 if( !func_def )
4737 return FALSE;
4739 // add the function to class
4740 if( !type_engine_scan1_func_def( env, func_def ) )
4741 return FALSE;
4742 if( !type_engine_scan2_func_def( env, func_def ) )
4743 return FALSE;
4744 if( !type_engine_check_func_def( env, func_def ) )
4745 return FALSE;
4747 return TRUE;
4753 //-----------------------------------------------------------------------------
4754 // name: type_engine_import_sfun()
4755 // desc: import static function (must be between class_begin/end)
4756 //-----------------------------------------------------------------------------
4757 t_CKBOOL type_engine_import_sfun( Chuck_Env * env, Chuck_DL_Func * sfun )
4759 a_Func_Def func_def = NULL;
4761 // make sure we are in class
4762 if( !env->class_def )
4764 // error
4765 EM_error2( 0,
4766 "import error: import_sfun '%s' invoked between begin/end",
4767 sfun->name.c_str() );
4768 return FALSE;
4771 // make into func_def
4772 func_def = make_dll_as_fun( sfun, TRUE );
4774 // add the function to class
4775 if( !type_engine_scan1_func_def( env, func_def ) )
4776 return FALSE;
4777 if( !type_engine_scan2_func_def( env, func_def ) )
4778 return FALSE;
4779 if( !type_engine_check_func_def( env, func_def ) )
4780 return FALSE;
4782 return TRUE;
4788 //-----------------------------------------------------------------------------
4789 // name: type_engine_import_mvar()
4790 // desc: import member variable (must be between class_begin/end)
4791 //-----------------------------------------------------------------------------
4792 t_CKUINT type_engine_import_mvar( Chuck_Env * env, const char * type,
4793 const char * name, t_CKUINT is_const )
4795 // make sure we are in class
4796 if( !env->class_def )
4798 // error
4799 EM_error2( 0,
4800 "import error: import_mvar '%s' invoked between begin/end",
4801 name );
4802 return CK_INVALID_OFFSET;
4805 // make path
4806 t_CKUINT array_depth = 0;
4807 a_Id_List path = str2list( type, array_depth );
4808 if( !path )
4810 // error
4811 EM_error2( 0, "... during mvar import '%s.%s'...",
4812 env->class_def->c_name(), name );
4813 return CK_INVALID_OFFSET;
4815 // make type decl
4816 a_Type_Decl type_decl = new_type_decl( path, FALSE, 0 );
4817 // check for array
4818 if( array_depth )
4820 // add the array
4821 type_decl->array = new_array_sub( NULL, 0 );
4822 // set the depth
4823 type_decl->array->depth = array_depth;
4825 // make var decl
4826 a_Var_Decl var_decl = new_var_decl( (char *)name, NULL, 0 );
4827 // make var decl list
4828 a_Var_Decl_List var_decl_list = new_var_decl_list( var_decl, 0 );
4829 // make exp decl
4830 a_Exp exp_decl = new_exp_decl( type_decl, var_decl_list, FALSE, 0 );
4831 // add it
4832 if( !type_engine_scan1_exp_decl( env, &exp_decl->decl ) ||
4833 !type_engine_scan2_exp_decl( env, &exp_decl->decl ) ||
4834 !type_engine_check_exp_decl( env, &exp_decl->decl ) )
4836 delete_id_list( path );
4837 return CK_INVALID_OFFSET;
4840 // cleanup
4841 delete_id_list( path );
4843 // return the offset
4844 return var_decl->value->offset;
4850 //-----------------------------------------------------------------------------
4851 // name: type_engine_import_svar()
4852 // desc: import static variable (must be between class_begin/end)
4853 //-----------------------------------------------------------------------------
4854 t_CKBOOL type_engine_import_svar( Chuck_Env * env, const char * type,
4855 const char * name, t_CKUINT is_const,
4856 t_CKUINT addr )
4858 // make sure we are in class
4859 if( !env->class_def )
4861 // error
4862 EM_error2( 0,
4863 "import error: import_svar '%s' invoked between begin/end",
4864 name );
4865 return FALSE;
4868 // make path
4869 a_Id_List path = str2list( type );
4870 if( !path )
4872 // error
4873 EM_error2( 0, "... during svar import '%s.%s'...",
4874 env->class_def->c_name(), name );
4875 return FALSE;
4878 // make type decl
4879 a_Type_Decl type_decl = new_type_decl( path, FALSE, 0 );
4880 // make var decl
4881 a_Var_Decl var_decl = new_var_decl( (char *)name, NULL, 0 );
4882 // make var decl list
4883 a_Var_Decl_List var_decl_list = new_var_decl_list( var_decl, 0 );
4884 // make exp decl
4885 a_Exp exp_decl = new_exp_decl( type_decl, var_decl_list, TRUE, 0 );
4886 // add addr
4887 var_decl->addr = (void *)addr;
4888 // add it
4889 if( !type_engine_scan1_exp_decl( env, &exp_decl->decl ) ||
4890 !type_engine_scan2_exp_decl( env, &exp_decl->decl ) ||
4891 !type_engine_check_exp_decl( env, &exp_decl->decl ) )
4893 delete_id_list( path );
4894 return FALSE;
4897 // cleanup
4898 delete_id_list( path );
4900 return TRUE;
4906 //-----------------------------------------------------------------------------
4907 // name: type_engine_register_deprecate()
4908 // desc: ...
4909 //-----------------------------------------------------------------------------
4910 t_CKBOOL type_engine_register_deprecate( Chuck_Env * env,
4911 const string & former,
4912 const string & latter )
4914 env->deprecated[former] = latter;
4915 return TRUE;
4921 //-----------------------------------------------------------------------------
4922 // name: init_special()
4923 // desc: ...
4924 //-----------------------------------------------------------------------------
4925 void init_special( Chuck_VM_Object * obj )
4927 // reference - this is done when the reference is assigned
4928 // obj->add_ref();
4930 // add to vector
4931 if( obj->m_v_ref ) obj->m_v_ref->push_back( obj );
4937 //-----------------------------------------------------------------------------
4938 // name: new_Chuck_Type()
4939 // desc: instantiate new chuck type
4940 //-----------------------------------------------------------------------------
4941 Chuck_Type * Chuck_Context::new_Chuck_Type()
4943 // allocate
4944 Chuck_Type * type = new Chuck_Type;
4945 if( !type ) return NULL;
4946 // set v ref
4947 type->m_v_ref = &new_types;
4948 // initialize it
4949 init_special( type );
4951 return type;
4957 //-----------------------------------------------------------------------------
4958 // name: new_Chuck_Value()
4959 // desc: instantiate new chuck value
4960 //-----------------------------------------------------------------------------
4961 Chuck_Value * Chuck_Context::new_Chuck_Value( Chuck_Type * t,
4962 const string & name )
4964 // allocate
4965 Chuck_Value * value = new Chuck_Value( t, name );
4966 if( !value ) return NULL;
4967 // set v ref
4968 value->m_v_ref = &new_values;
4969 // initialize it
4970 init_special( value );
4972 return value;
4978 //-----------------------------------------------------------------------------
4979 // name: new_Chuck_Func()
4980 // desc: instantiate new chuck func
4981 //-----------------------------------------------------------------------------
4982 Chuck_Func * Chuck_Context::new_Chuck_Func()
4984 // allocate
4985 Chuck_Func * func = new Chuck_Func;
4986 if( !func ) return NULL;
4987 // set v ref
4988 func->m_v_ref = &new_funcs;
4989 // initialize it
4990 init_special( func );
4992 return func;
4998 //-----------------------------------------------------------------------------
4999 // name: new_Chuck_Namespace()
5000 // desc: instantiate new chuck namespace
5001 //-----------------------------------------------------------------------------
5002 Chuck_Namespace * Chuck_Context::new_Chuck_Namespace()
5004 // allocate
5005 Chuck_Namespace * nspc = new Chuck_Namespace;
5006 if( !nspc ) return NULL;
5007 // set v ref
5008 nspc->m_v_ref = &new_nspc;
5009 // initialize it
5010 init_special( nspc );
5012 return nspc;
5018 //-----------------------------------------------------------------------------
5019 // name: new_array_type()
5020 // desc: instantiate new chuck type for some kind of array
5021 //-----------------------------------------------------------------------------
5022 Chuck_Type * new_array_type( Chuck_Env * env, Chuck_Type * array_parent,
5023 t_CKUINT depth, Chuck_Type * base_type,
5024 Chuck_Namespace * owner_nspc )
5026 // make new type
5027 Chuck_Type * t = env->context->new_Chuck_Type();
5028 // set the id
5029 t->xid = te_array;
5030 // set the name
5031 t->name = base_type->name;
5032 // set the parent
5033 t->parent = array_parent;
5034 // add reference
5035 SAFE_ADD_REF(t->parent);
5036 // is a ref
5037 t->size = array_parent->size;
5038 // set the array depth
5039 t->array_depth = depth;
5040 // set the base type
5041 t->array_type = base_type;
5042 // add reference
5043 SAFE_ADD_REF(t->array_type);
5044 // set the namesapce
5045 t->info = array_parent->info;
5046 // add reference
5047 SAFE_ADD_REF(t->info);
5048 // set owner
5049 t->owner = owner_nspc;
5050 // add reference
5051 SAFE_ADD_REF(t->owner);
5053 // return the type
5054 return t;
5060 //-----------------------------------------------------------------------------
5061 // name: new_Chuck_Namespace()
5062 // desc: instantiate new chuck namespace
5063 //-----------------------------------------------------------------------------
5064 t_CKBOOL verify_array( a_Array_Sub array )
5066 // verify there were no errors from the parser...
5067 if( array->err_num )
5069 if( array->err_num == 1 )
5071 EM_error2( array->linepos,
5072 "invalid format for array init [...][...]..." );
5073 return FALSE;
5075 else if( array->err_num == 2 )
5077 EM_error2( array->linepos,
5078 "partially empty array init [...][]..." );
5079 return FALSE;
5081 else
5083 EM_error2( array->linepos,
5084 "internal error: unrecognized array error..." );
5085 return FALSE;
5089 return TRUE;
5095 //-----------------------------------------------------------------------------
5096 // name: str2list()
5097 // desc: convert str to list
5098 //-----------------------------------------------------------------------------
5099 a_Id_List str2list( const string & path )
5101 t_CKUINT dummy;
5102 return str2list( path, dummy );
5108 //-----------------------------------------------------------------------------
5109 // name: str2list()
5110 // desc: convert str to list
5111 //-----------------------------------------------------------------------------
5112 a_Id_List str2list( const string & path, t_CKUINT & array_depth )
5114 t_CKINT len = path.length();
5115 t_CKINT i, j;
5116 string curr;
5117 a_Id_List list = NULL;
5118 char last = '\0';
5120 // look for []
5121 array_depth = 0;
5122 while( len > 2 && path[len-1] == ']' && path[len-2] == '[' )
5124 // flag it
5125 array_depth++;
5126 // shorten len
5127 len -= 2;
5130 // loop backwards
5131 for( i = len - 1; i >= 0; i-- )
5133 char c = path[i];
5134 // if not .
5135 if( c != '.' )
5137 // check to make sure valid
5138 if( ( c >= 'A' && c <= 'Z' ) || ( c >= 'a' && c <= 'z' )
5139 || ( c == '_' ) || ( c >= '0' && c <= '9' ) )
5141 // add
5142 curr += c;
5144 else
5146 // error
5147 EM_error2( 0, "illegal character '%c' in path '%s'...",
5148 c, path.c_str() );
5149 // delete
5150 delete_id_list( list );
5151 return NULL;
5155 // add
5156 if( c == '.' || i == 0 )
5158 // make sure valid
5159 if( (i != 0 && last != '.' && last != '\0') ||
5160 (i == 0 && c != '.') )
5162 char s;
5163 t_CKINT size = curr.length();
5164 // reverse
5165 for( j = 0; j < size/2; j++ )
5167 // swap
5168 s = curr[j];
5169 curr[j] = curr[size-j-1];
5170 curr[size-j-1] = s;
5172 // make a new id and put in list
5173 list = prepend_id_list( (char *)curr.c_str(), list, 0 );
5174 // clear
5175 curr = "";
5177 else
5179 // error
5180 EM_error2( 0, "path '%s' must not begin or end with '.'",
5181 path.c_str() );
5182 // delete
5183 delete_id_list( list );
5184 return NULL;
5188 // remember last
5189 last = c;
5192 return list;
5198 //-----------------------------------------------------------------------------
5199 // name: make_dll_arg_list()
5200 // desc: make an chuck dll function into arg list
5201 //-----------------------------------------------------------------------------
5202 a_Arg_List make_dll_arg_list( Chuck_DL_Func * dl_fun )
5204 a_Arg_List arg_list = NULL;
5205 a_Type_Decl type_decl = NULL;
5206 a_Var_Decl var_decl = NULL;
5207 a_Id_List type_path = NULL;
5208 a_Id_List name_path = NULL;
5209 a_Array_Sub array_sub = NULL;
5210 Chuck_DL_Value * arg = NULL;
5211 t_CKUINT array_depth = 0;
5212 t_CKUINT array_depth2 = 0;
5213 t_CKINT i = 0;
5215 // loop backwards
5216 for( i = dl_fun->args.size() - 1; i >= 0; i-- )
5218 // copy into variable
5219 arg = dl_fun->args[i];
5221 // path
5222 type_path = str2list( arg->type, array_depth );
5223 if( !type_path )
5225 // error
5226 EM_error2( 0, "...at argument '%i'...", i+1 );
5227 // delete the arg list
5228 // delete_arg_list( arg_list );
5229 return NULL;
5232 // type
5233 type_decl = new_type_decl( type_path, FALSE, 0 );
5234 // TODO: fix this
5235 assert( type_decl );
5237 // var
5238 name_path = str2list( arg->name, array_depth2 );
5241 // sanity
5242 if( array_depth && array_depth2 )
5244 // error
5245 EM_error2( 0, "array subscript specified incorrectly for built-in module" );
5246 // TODO: cleanup
5247 return NULL;
5250 // TODO: arrays?
5251 if( array_depth2 ) array_depth = array_depth2;
5252 if( array_depth )
5254 array_sub = new_array_sub( NULL, 0 );
5256 for( int i = 1; i < array_depth; i++ )
5257 array_sub = prepend_array_sub( array_sub, NULL, 0 );
5260 var_decl = new_var_decl( (char *)arg->name.c_str(), array_sub, 0 );
5262 // make new arg
5263 arg_list = prepend_arg_list( type_decl, var_decl, arg_list, 0 );
5266 return arg_list;
5272 //-----------------------------------------------------------------------------
5273 // name: make_dll_as_fun()
5274 // desc: make an chuck dll function into absyn function
5275 //-----------------------------------------------------------------------------
5276 a_Func_Def make_dll_as_fun( Chuck_DL_Func * dl_fun, t_CKBOOL is_static )
5278 a_Func_Def func_def = NULL;
5279 ae_Keyword func_decl = ae_key_func;
5280 ae_Keyword static_decl = ae_key_instance;
5281 a_Id_List type_path = NULL;
5282 a_Type_Decl type_decl = NULL;
5283 const char * name = NULL;
5284 a_Arg_List arg_list = NULL;
5285 t_CKUINT array_depth = 0;
5287 // fun decl TODO: fix this
5288 func_decl = ae_key_func;
5289 // static decl TODO: allow abstract
5290 static_decl = is_static ? ae_key_static : ae_key_instance;
5291 // path
5292 type_path = str2list( dl_fun->type, array_depth );
5293 if( !type_path )
5295 // error
5296 EM_error2( 0, "...during function import '%s' (type)...",
5297 dl_fun->name.c_str() );
5298 goto error;
5301 // type decl
5302 // old: type_decl = new_type_decl( type_path, 1, 0 );
5303 type_decl = new_type_decl( type_path, 0, 0 );
5304 assert( type_decl );
5305 if( !type_decl )
5307 // error
5308 EM_error2( 0, "...during function import '%s' (type2)...",
5309 dl_fun->name.c_str() );
5310 // delete list
5311 delete_id_list( type_path );
5312 type_path = NULL;
5313 goto error;
5316 // array types
5317 // this allows us to define built-in functions that return array types
5318 // however doing this without garbage collection is probably a bad idea
5319 // -spencer
5320 if( array_depth )
5322 a_Array_Sub array_sub = new_array_sub( NULL, 0 );
5324 for( int i = 1; i < array_depth; i++ )
5325 array_sub = prepend_array_sub( array_sub, NULL, 0 );
5327 type_decl = add_type_decl_array( type_decl, array_sub, 0 );
5330 // name of the function
5331 name = dl_fun->name.c_str();
5332 // arg list
5333 arg_list = make_dll_arg_list( dl_fun );
5334 if( dl_fun->args.size() > 0 && !arg_list )
5336 // error
5337 EM_error2( 0, "...during function import '%s' (arg_list)...",
5338 dl_fun->name.c_str() );
5339 // delete type_decl
5340 // delete_type_decl( type_decl );
5341 type_decl = NULL;
5342 goto error;
5345 // make a func_def
5346 func_def = new_func_def( func_decl, static_decl, type_decl, (char *)name,
5347 arg_list, NULL, 0 );
5348 // mark the function as imported (instead of defined in ChucK)
5349 func_def->s_type = ae_func_builtin;
5350 // copy the function pointer - the type doesn't matter here
5351 // ... since we copying into a void * - so mfun is used
5352 func_def->dl_func_ptr = (void *)dl_fun->mfun;
5354 return func_def;
5356 error:
5358 // clean up
5359 // if( !func_def ) delete_type_decl( type_decl );
5360 // else delete_func_def( func_def );
5362 return NULL;
5368 //-----------------------------------------------------------------------------
5369 // name: type_engine_add_dll()
5370 // desc: add an chuck dll into the env
5371 //-----------------------------------------------------------------------------
5372 t_CKBOOL type_engine_add_dll( Chuck_Env * env, Chuck_DLL * dll, const string & dest )
5374 // which namespace
5375 string where = ( dest == "" ? "global" : dest );
5376 Chuck_Namespace * nspc = NULL;
5377 const Chuck_DL_Query * query = NULL;
5378 t_CKUINT i, j;
5379 vector<a_Func_Def> the_funs;
5381 // convert to id list
5382 a_Id_List path = str2list( dest );
5383 if( !path ) goto error;
5385 // find the namespace to put the import
5386 nspc = type_engine_find_nspc( env, path );
5387 if( !nspc ) goto error;
5389 // get the query
5390 query = dll->query();
5392 // loop
5393 for( i = 0; i < query->classes.size(); i++ )
5395 a_Class_Def def = NULL;
5396 a_Class_Ext ext = NULL;
5397 a_Class_Body body = NULL;
5398 // UNUSED: a_Section sec = NULL;
5399 a_Func_Def fun = NULL;
5400 a_Id_List name;
5401 a_Id_List parent;
5402 // UNUSED: Chuck_DL_Func * dl_fun = NULL;
5403 // UNUSED: Chuck_DL_Value * dl_val = NULL;
5404 // UNUSED: Chuck_DL_Ctrl * dl_ctrl = NULL;
5405 Chuck_DL_Class * cl = query->classes[i];
5406 assert( cl != NULL );
5408 // get name
5409 name = str2list( cl->name );
5410 if( !name ) goto error;
5411 // if parent is specified
5412 if( cl->parent != "" )
5414 // get parent
5415 parent = str2list( cl->parent );
5416 if( !parent ) goto error;
5418 else // if no parent specified, then extend Object
5420 parent = str2list( "Object" );
5421 assert( parent != NULL );
5424 // clear the funs vector
5425 the_funs.clear();
5427 // loop over member functions
5428 for( j = 0; j < cl->mfuns.size(); j++ )
5430 // get the function from the dll
5431 fun = make_dll_as_fun( cl->mfuns[j], FALSE );
5432 if( !fun ) goto error;
5433 // add to vector
5434 the_funs.push_back( fun );
5437 // loop over static functions
5438 for( j = 0; j < cl->sfuns.size(); j++ )
5440 // get the function from the dll
5441 fun = make_dll_as_fun( cl->sfuns[j], TRUE );
5442 if( !fun ) goto error;
5443 // add to vector
5444 the_funs.push_back( fun );
5447 // loop over member data
5448 // ignored for now... -spencer
5449 for( j = 0; j < cl->mvars.size(); j++ )
5453 // the next few lines take static member variables defined by the DLL
5454 // and creates a list of corresponding declarations to add to the
5455 // class definition
5456 // -spencer
5458 // static member variable declarations
5459 a_Stmt_List svar_decls = NULL;
5461 // loop over static data
5462 for( j = 0; j < cl->svars.size(); j++ )
5464 // get type
5465 a_Id_List path = str2list( cl->svars[j]->type.c_str() );
5466 // make type decl
5467 a_Type_Decl type_decl = new_type_decl( path, FALSE, 0 );
5468 // make var decl
5469 a_Var_Decl var_decl = new_var_decl( cl->svars[j]->name.c_str(), NULL, 0 );
5470 // make var decl list
5471 a_Var_Decl_List var_decl_list = new_var_decl_list( var_decl, 0 );
5472 // make exp decl
5473 a_Exp exp_decl = new_exp_decl( type_decl, var_decl_list, TRUE, 0 );
5474 // add addr
5475 var_decl->addr = (void *)cl->svars[j]->static_addr;
5476 // prepend exp stmt to stmt list
5477 svar_decls = prepend_stmt_list( new_stmt_from_expression( exp_decl, 0 ), svar_decls, 0 );
5480 // if there are any declarations, prepend them to body
5481 if( svar_decls )
5482 body = prepend_class_body( new_section_stmt( svar_decls, 0 ), body, 0 );
5484 // go through funs backwards, and prepend
5485 for( t_CKINT k = (t_CKINT)the_funs.size() - 1; k >= 0; k-- )
5487 // add to body
5488 body = prepend_class_body( new_section_func_def( the_funs[k], 0 ), body, 0 );
5491 // construct class
5492 def = new_class_def( ae_key_public, name, ext, body, 0 );
5493 // set where to add
5494 def->home = nspc;
5495 // TODO: mark the class as dll import?
5497 // scan type check it
5498 if( !type_engine_scan0_class_def( env, def ) ) goto error;
5499 if( !type_engine_scan1_class_def( env, def ) ) goto error;
5500 if( !type_engine_scan2_class_def( env, def ) ) goto error;
5501 if( !type_engine_check_class_def( env, def ) ) goto error;
5503 // TODO: clean up?
5506 // free the path
5507 delete_id_list( path );
5509 return TRUE;
5511 error:
5512 // error
5513 EM_error2( 0, "...(in object import '%s' in DLL '%s')",
5514 query ? ( query->dll_name.c_str() == "" ? query->dll_name.c_str() : "[empty]" ) : "[null]", dll->name() );
5516 // free the path
5517 delete_id_list( path );
5519 // TODO: free the absyn stuff?
5521 return FALSE;
5527 static const char * g_howmuch[] = { "ALL", "CLASSES_ONLY", "ALL_EXCEPT_CLASSES" };
5528 //-----------------------------------------------------------------------------
5529 // name: howmuch2str()
5530 // desc: ...
5531 //-----------------------------------------------------------------------------
5532 const char * howmuch2str( te_HowMuch how_much )
5534 if( how_much < 0 || how_much > te_do_no_classes ) return "[INVALID]";
5535 else return g_howmuch[how_much];
5541 // table of escape characters
5542 static char g_escape[256];
5543 static t_CKBOOL g_escape_ready = FALSE;
5545 //-----------------------------------------------------------------------------
5546 // name: escape_table()
5547 // desc: ...
5548 //-----------------------------------------------------------------------------
5549 void escape_table( )
5551 // escape
5552 g_escape['\''] = '\'';
5553 g_escape['"'] = '"';
5554 g_escape['\\'] = '\\';
5555 g_escape['a'] = (char)7; // audible bell
5556 g_escape['b'] = (char)8; // back space
5557 g_escape['f'] = (char)12; // form feed
5558 g_escape['n'] = (char)10; // new line
5559 g_escape['r'] = (char)13; // carriage return
5560 g_escape['t'] = (char)9; // horizontal tab
5561 g_escape['v'] = (char)11; // vertical tab
5563 // done
5564 g_escape_ready = TRUE;
5568 //-----------------------------------------------------------------------------
5569 // name: escape_str()
5570 // desc: ...
5571 //-----------------------------------------------------------------------------
5572 t_CKBOOL escape_str( char * str_lit, int linepos )
5574 // create if not yet
5575 if( !g_escape_ready )
5576 escape_table( );
5578 // write pointer
5579 char * str = str_lit;
5580 // unsigned because we index array of 256
5581 unsigned char c, c2, c3;
5583 // iterate
5584 while( *str_lit )
5586 // if \ encountered
5587 if( *str_lit == '\\' )
5589 // advance pointer
5590 str_lit++;
5592 // make sure next char
5593 if( *str_lit == '\0' )
5595 EM_error2( linepos, "invalid: string ends with escape charactor '\\'" );
5596 return FALSE;
5599 // next characters
5600 c = *(str_lit);
5601 c2 = *(str_lit+1);
5603 // is octal?
5604 if( c >= '0' && c <= '7' )
5606 // look at next
5607 if( c == '0' && ( c2 < '0' || c2 > '7' ) )
5608 *str++ = '\0';
5609 else
5611 // get next
5612 c3 = *(str_lit+2);
5614 // all three should be within range
5615 if( c2 >= '0' && c2 <= '7' && c3 >= '0' && c3 <= '7' )
5617 // ascii value
5618 *str++ = (c-'0') * 64 + (c2-'0') * 8 + (c3-'0');
5619 // advance pointer
5620 str_lit += 2;
5622 else
5624 EM_error2( linepos, "malformed octal escape sequence '\\%c%c%c'", c, c2, c3 );
5625 return FALSE;
5629 else if( c == 'x' ) // is hex?
5631 EM_error2( linepos, "hex escape sequence not (yet) supported (use octal!)");
5632 return FALSE;
5634 else // is other?
5636 // lookup
5637 if( g_escape[(int)c] )
5638 *str++ = g_escape[c];
5639 else // error
5641 EM_error2( linepos, "unrecognized escape sequence '\\%c'", c );
5642 return FALSE;
5646 else
5648 // char
5649 *str++ = *str_lit;
5652 // advance pointer
5653 str_lit++;
5656 // make sure
5657 assert( str <= str_lit );
5659 // terminate
5660 *str = '\0';
5662 return TRUE;