1 /*----------------------------------------------------------------------------
2 ChucK Concurrent, On-the-fly Audio Programming Language
3 Compiler and Virtual Machine
5 Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6 http://chuck.cs.princeton.edu/
7 http://soundlab.cs.princeton.edu/
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 -----------------------------------------------------------------------------*/
25 //-----------------------------------------------------------------------------
26 // file: chuck_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"
38 #include "chuck_errmsg.h"
39 #include "chuck_lang.h"
40 #include "util_string.h"
48 //-----------------------------------------------------------------------------
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 *) );
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
);
137 a_Func_Def
make_dll_as_fun( Chuck_DL_Func
* dl_fun
, t_CKBOOL is_static
);
140 Chuck_Env
* Chuck_Env::our_instance
= NULL
;
143 //-----------------------------------------------------------------------------
146 //-----------------------------------------------------------------------------
147 t_CKBOOL
Chuck_Env::startup()
149 assert( our_instance
== NULL
);
150 our_instance
= new Chuck_Env
;
151 assert( our_instance
!= NULL
);
159 //-----------------------------------------------------------------------------
162 //-----------------------------------------------------------------------------
163 Chuck_Env
* Chuck_Env::instance()
171 //-----------------------------------------------------------------------------
174 //-----------------------------------------------------------------------------
175 t_CKBOOL
Chuck_Env::shutdown()
177 assert( our_instance
!= NULL
);
178 SAFE_DELETE( our_instance
);
179 assert( our_instance
== NULL
);
187 //-----------------------------------------------------------------------------
188 // name: type_engine_init()
189 // desc: initialize a type engine
190 //-----------------------------------------------------------------------------
191 Chuck_Env
* type_engine_init( Chuck_VM
* vm
)
194 EM_log( CK_LOG_SEVERE
, "initializing type checker..." );
198 // allocate a new env
199 if( !Chuck_Env::startup() ) return NULL
;
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();
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..." );
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();
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 );
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();
371 //-----------------------------------------------------------------------------
372 // name: type_engine_shutdown()
374 //-----------------------------------------------------------------------------
375 void type_engine_shutdown( Chuck_Env
* env
)
378 EM_log( CK_LOG_SEVERE
, "shutting down type checker..." );
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()
403 //-----------------------------------------------------------------------------
404 t_CKBOOL
type_engine_check_prog( Chuck_Env
* env
, a_Program prog
,
405 const string
& filename
)
407 t_CKBOOL ret
= FALSE
;
410 EM_log( CK_LOG_FINE
, "type-checking program '%s' - passes 0, 1, 2, 3...",
416 Chuck_Context
* context
= type_engine_make_context( prog
, filename
);
417 if( !context
) goto done
;
423 if( !type_engine_load_context( env
, context
) )
424 { ret
= FALSE
; goto done
; }
427 if( !type_engine_scan0_prog( env
, g_program
, te_do_all
) )
428 { ret
= FALSE
; goto cleanup
; }
431 if( !type_engine_scan1_prog( env
, g_program
, te_do_all
) )
432 { ret
= FALSE
; goto cleanup
; }
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
; }
445 if( ret
) env
->global()->commit();
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" );
467 //-----------------------------------------------------------------------------
468 // name: type_engine_make_context()
470 //-----------------------------------------------------------------------------
471 Chuck_Context
* type_engine_make_context( a_Program prog
, const string
& filename
)
474 EM_log( CK_LOG_FINER
, "creating context '%s'...", filename
.c_str() );
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
;
483 context
->filename
= filename
;
494 //-----------------------------------------------------------------------------
495 // name: type_engine_check_context()
497 //-----------------------------------------------------------------------------
498 t_CKBOOL
type_engine_check_context( Chuck_Env
* env
,
499 Chuck_Context
* context
,
500 te_HowMuch how_much
)
503 a_Program prog
= NULL
;
506 EM_log( CK_LOG_FINER
, "(pass 3) type-checking context '%s'...",
507 context
->filename
.c_str() );
511 EM_log( CK_LOG_FINER
, "target: %s", howmuch2str( how_much
) );
513 // make sure there is a context
517 EM_error2( 0, "internal error: env->context NULL!" );
518 ret
= FALSE
; goto done
;
522 prog
= context
->parse_tree
;
526 EM_error2( 0, "internal error: context->parse_tree NULL!" );
527 ret
= FALSE
; goto done
;
530 // go through each of the program sections
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
);
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
);
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
);
557 EM_error2( prog
->linepos
,
558 "internal error: unrecognized program section in type checker..." );
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
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
;
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
)
598 EM_log( CK_LOG_FINER
, "loading context '%s'...", context
->filename
.c_str() );
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
;
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
);
614 context
->nspc
->parent
= env
->curr
;
615 // set the context's namespace as current
616 env
->curr
= context
->nspc
;
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
)
634 assert( env
->context
!= NULL
);
635 assert( env
->contexts
.size() != 0 );
637 EM_log( CK_LOG_FINER
, "unloading context '%s'...",
638 env
->context
->filename
.c_str() );
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();
653 env
->context
= env
->contexts
.back();
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) );
670 //-----------------------------------------------------------------------------
671 // name: type_engine_check_stmt_list()
673 //-----------------------------------------------------------------------------
674 t_CKBOOL
type_engine_check_stmt_list( Chuck_Env
* env
, a_Stmt_List list
)
676 // type check the stmt_list
679 // the current statement
680 if( !type_engine_check_stmt( env
, list
->stmt
) )
683 // advance to the next statement
693 //-----------------------------------------------------------------------------
694 // name: type_engine_check_stmt(()
696 //-----------------------------------------------------------------------------
697 t_CKBOOL
type_engine_check_stmt( Chuck_Env
* env
, a_Stmt stmt
)
699 t_CKBOOL ret
= FALSE
;
705 switch( stmt
->s_type
)
708 // count scope to help determine class member
710 env
->curr
->value
.push();
711 ret
= type_engine_check_if( env
, &stmt
->stmt_if
);
712 env
->curr
->value
.pop();
718 env
->curr
->value
.push();
719 ret
= type_engine_check_for( env
, &stmt
->stmt_for
);
720 env
->curr
->value
.pop();
726 env
->curr
->value
.push();
727 ret
= type_engine_check_while( env
, &stmt
->stmt_while
);
728 env
->curr
->value
.pop();
734 env
->curr
->value
.push();
735 ret
= type_engine_check_until( env
, &stmt
->stmt_until
);
736 env
->curr
->value
.pop();
742 env
->curr
->value
.push();
743 ret
= type_engine_check_loop( env
, &stmt
->stmt_loop
);
744 env
->curr
->value
.pop();
749 ret
= ( type_engine_check_exp( env
, stmt
->stmt_exp
) != NULL
);
753 ret
= type_engine_check_return( env
, &stmt
->stmt_return
);
758 ret
= type_engine_check_code_segment( env
, &stmt
->stmt_code
);
763 ret
= type_engine_check_break( env
, &stmt
->stmt_break
);
766 case ae_stmt_continue
:
767 ret
= type_engine_check_continue( env
, &stmt
->stmt_continue
);
772 ret
= type_engine_check_switch( env
, &stmt
->stmt_switch
);
777 // ret = type_engine_check_case( env, &stmt->stmt_case );
780 case ae_stmt_gotolabel
:
781 // ret = type_engine_check_gotolabel( env, &stmt->goto_label );
785 EM_error2( stmt
->linepos
,
786 "internal compiler error - no stmt type '%i'!", stmt
->s_type
);
797 //-----------------------------------------------------------------------------
798 // name: type_engine_check_if()
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
) )
807 // TODO: ensure that conditional has valid type
810 if( !type_engine_check_stmt( env
, stmt
->if_body
) )
813 // check else, if there is one
814 if( stmt
->else_body
)
815 if( !type_engine_check_stmt( env
, stmt
->else_body
) )
824 //-----------------------------------------------------------------------------
825 // name: type_engine_check_for()
827 //-----------------------------------------------------------------------------
828 t_CKBOOL
type_engine_check_for( Chuck_Env
* env
, a_Stmt_For stmt
)
831 if( !type_engine_check_stmt( env
, stmt
->c1
) )
834 // check the conditional
835 if( !type_engine_check_stmt( env
, stmt
->c2
) )
838 // TODO: same as if - check conditional type valid
841 if( stmt
->c3
&& !type_engine_check_exp( env
, stmt
->c3
) )
844 // for break and continue statement
845 env
->breaks
.push_back( stmt
->self
);
848 // TODO: restore break stack? (same for other loops)
849 if( !type_engine_check_stmt( env
, stmt
->body
) )
852 // remove the loop from the stack
853 assert( env
->breaks
.size() && env
->breaks
.back() == stmt
->self
);
854 env
->breaks
.pop_back();
862 //-----------------------------------------------------------------------------
863 // name: type_engine_check_while()
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
) )
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
);
878 if( !type_engine_check_stmt( env
, stmt
->body
) )
881 // remove the loop from the stack
882 assert( env
->breaks
.size() && env
->breaks
.back() == stmt
->self
);
883 env
->breaks
.pop_back();
891 //-----------------------------------------------------------------------------
892 // name: type_engine_check_until()
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
) )
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
);
907 if( !type_engine_check_stmt( env
, stmt
->body
) )
910 // remove the loop from the stack
911 assert( env
->breaks
.size() && env
->breaks
.back() == stmt
->self
);
912 env
->breaks
.pop_back();
920 //-----------------------------------------------------------------------------
921 // name: type_engine_check_loop()
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
)) )
932 // ensure the type in conditional is int (different from other loops)
933 if( isa( type
, &t_float
) )
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'..." );
945 // for break and continue statement
946 env
->breaks
.push_back( stmt
->self
);
949 if( !type_engine_check_stmt( env
, stmt
->body
) )
952 // remove the loop from the stack
953 assert( env
->breaks
.size() && env
->breaks
.back() == stmt
->self
);
954 env
->breaks
.pop_back();
962 //-----------------------------------------------------------------------------
963 // name: type_engine_check_switch()
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..." );
977 //-----------------------------------------------------------------------------
978 // name: type_engine_check_break()
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..." );
997 //-----------------------------------------------------------------------------
998 // name: type_engine_check_continue()
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..." );
1017 //-----------------------------------------------------------------------------
1018 // name: type_engine_check_return()
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
1028 EM_error2( stmt
->linepos
,
1029 "'return' statement found outside function definition" );
1033 // check the type of the return
1035 ret_type
= type_engine_check_exp( env
, stmt
->val
);
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() );
1049 return ret_type
!= NULL
;
1055 //-----------------------------------------------------------------------------
1056 // name: type_engine_check_code_segment()
1058 //-----------------------------------------------------------------------------
1059 t_CKBOOL
type_engine_check_code_segment( Chuck_Env
* env
, a_Stmt_Code stmt
,
1062 // TODO: make sure this is in a function or is outside class
1067 if( push
) env
->curr
->value
.push(); // env->context->nspc.value.push();
1069 t_CKBOOL t
= type_engine_check_stmt_list( env
, stmt
->stmt_list
);
1071 if( push
) env
->curr
->value
.pop(); // env->context->nspc.value.pop();
1081 //-----------------------------------------------------------------------------
1082 // name: type_engine_check_exp()
1084 //-----------------------------------------------------------------------------
1085 t_CKTYPE
type_engine_check_exp( Chuck_Env
* env
, a_Exp exp
)
1089 // reset the group size
1090 exp
->group_size
= 0;
1092 // loop through parallel expressions
1097 // increment first exp's group size
1100 // examine the syntax
1101 switch( curr
->s_type
)
1104 curr
->type
= type_engine_check_exp_binary( env
, &curr
->binary
);
1108 curr
->type
= type_engine_check_exp_unary( env
, &curr
->unary
);
1112 curr
->type
= type_engine_check_exp_cast( env
, &curr
->cast
);
1115 case ae_exp_postfix
:
1116 curr
->type
= type_engine_check_exp_postfix( env
, &curr
->postfix
);
1120 curr
->type
= type_engine_check_exp_dur( env
, &curr
->dur
);
1123 case ae_exp_primary
:
1124 curr
->type
= type_engine_check_exp_primary( env
, &curr
->primary
);
1128 curr
->type
= type_engine_check_exp_array( env
, &curr
->array
);
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
;
1137 case ae_exp_dot_member
:
1138 curr
->type
= type_engine_check_exp_dot_member( env
, &curr
->dot_member
);
1142 curr
->type
= type_engine_check_exp_if( env
, &curr
->exp_if
);
1146 curr
->type
= type_engine_check_exp_decl( env
, &curr
->decl
);
1150 EM_error2( curr
->linepos
,
1151 "internal compiler error - no expression type '%i'...",
1160 // advance to next expression
1171 //-----------------------------------------------------------------------------
1172 // name: type_engine_check_exp_binary()
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
)
1191 // type check the pair
1192 if( !(ret
= type_engine_check_op( env
, binary
->op
, cl
, cr
, binary
)) )
1204 //-----------------------------------------------------------------------------
1205 // name: type_engine_ensure_no_multi_decl()
1207 //-----------------------------------------------------------------------------
1208 t_CKBOOL
type_engine_ensure_no_multi_decl( a_Exp exp
, const char * op_str
)
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
);
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()
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
) ) )
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...",
1255 if( op
== ae_op_arrow_left
|| op
== ae_op_arrow_right
)
1258 if( isa( left
, &t_io
) )
1260 // check for assignment
1261 if( op
== ae_op_arrow_right
&& lhs
->s_meta
!= ae_meta_var
)
1264 EM_error2( rhs
->linepos
,
1265 "cannot perform I/O assignment via '->' to non-mutable value" );
1270 if( isa( right
, &t_int
) || isa( right
, &t_float
) ||
1271 isa( right
, &t_string
) )
1277 if( *left
!= *right
)
1279 // for some - int/float
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
;
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
;
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
;
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
;
1317 // no commute - int/float
1320 case ae_op_plus_chuck
:
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
:
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
;
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
;
1351 if( op
== ae_op_shift_left
&& isa( left
, &t_array
) )
1354 Chuck_Type
* atype
= left
->array_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
;
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
) )
1386 else if( isa( left
, &t_string
) || isa( left
, &t_int
)
1387 || isa( left
, &t_float
) )
1390 if( isa( right
, &t_string
) )
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...",
1410 if( isa( right
, &t_object
) ) {
1411 EM_error2( lhs
->linepos
, "cannot perform '%s' on object references...",
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)" );
1444 // mark to emit var instead of value
1456 return type_engine_check_op_chuck( env
, lhs
, rhs
, binary
);
1459 return type_engine_check_op_unchuck( env
, lhs
, rhs
);
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
;
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
;
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;
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;
1511 case ae_op_times_chuck
:
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
;
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;
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;
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;
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
;
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
1576 case ae_op_shift_left
:
1577 // prepend || append
1578 if( isa( left
, &t_array
) )
1581 assert( left
->array_type
!= NULL
);
1583 if( isa( right
, left
->array_type
) ) return left
;
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
:
1591 LR( te_int
, te_int
) return &t_int
;
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
;
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
;
1612 EM_error2( lhs
->linepos
,
1613 "cannot resolve operator '%s' on types '%s' and '%s'",
1614 op2str( op
), left
->c_name(), right
->c_name() );
1621 //-----------------------------------------------------------------------------
1622 // name: type_engine_check_op_chuck()
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..." );
1646 if( isa( left
, &t_ugen
) && isa( right
, &t_ugen
) )
1648 // make sure non-zero
1649 if( left
->ugen_info
->num_outs
== 0 )
1652 EM_error2( lhs
->linepos
,
1653 "ugen's of type '%s' have no output - cannot => to another ugen...",
1657 else if( right
->ugen_info
->num_ins
== 0 )
1660 EM_error2( rhs
->linepos
,
1661 "ugen's of type '%s' have no input - cannot => from another ugen...",
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
) ) )
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
) ) )
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
) )
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
;
1703 if( rhs
->s_meta
== ae_meta_var
)
1705 // emit ref - remember for emitter
1706 rhs
->emit_var
= TRUE
;
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)" );
1722 // TODO: check overloading of =>
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)" );
1734 // TODO: check overloading of =>
1737 EM_error2( lhs
->linepos
,
1738 "cannot resolve operator '=>' on types '%s' and '%s'...",
1739 left
->c_name(), right
->c_name() );
1747 //-----------------------------------------------------------------------------
1748 // name: type_engine_check_op_unchuck()
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
;
1756 if( isa( left
, &t_ugen
) && isa( right
, &t_ugen
) ) return right
;
1758 // TODO: check overloading of =<
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() );
1773 //-----------------------------------------------------------------------------
1774 // name: type_engine_check_op_upchuck()
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
;
1782 if( isa( left
, &t_uana
) && isa( right
, &t_uana
) ) return right
;
1784 // TODO: check overloading of =^
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() );
1799 //-----------------------------------------------------------------------------
1800 // name: type_engine_check_op_at_chuck()
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
;
1808 //if( isa( left, &t_class ) )
1810 // EM_error2( lhs->linepos,
1811 // "cannot assign '@=>' using static class as left operand..." );
1814 //else if( isa( right, &t_class ) )
1816 // EM_error2( rhs->linepos,
1817 // "cannot assign '@=>' using static class as right operand..." );
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)" );
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
;
1839 LR( te_int
, te_float
) left
= lhs
->cast_to
= &t_float
;
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)" );
1853 rhs
->emit_var
= TRUE
;
1861 //-----------------------------------------------------------------------------
1862 // name: type_engine_check_exp_unary()
1864 //-----------------------------------------------------------------------------
1865 t_CKTYPE
type_engine_check_exp_unary( Chuck_Env
* env
, a_Exp_Unary unary
)
1867 Chuck_Type
* t
= NULL
;
1872 // assert( unary->op == ae_op_new );
1873 t
= type_engine_check_exp( env
, unary
->exp
);
1874 if( !t
) return NULL
;
1880 case ae_op_plusplus
:
1881 case ae_op_minusminus
:
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
) );
1892 unary
->exp
->emit_var
= TRUE
;
1895 if( isa( t
, &t_int
) || isa( t
, &t_float
) )
1898 // TODO: check overloading
1903 if( isa( t
, &t_float
) ) return t
;
1905 case ae_op_exclamation
:
1907 if( isa( t
, &t_int
) ) return t
;
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;
1918 EM_error2( unary
->linepos
,
1919 "only function calls can be sporked..." );
1926 // t = env->curr->lookup_type( unary->type->xid->xid, TRUE );
1927 t
= type_engine_find_type( env
, unary
->type
->xid
);
1930 EM_error2( unary
->linepos
,
1931 "... in 'new' expression ..." );
1938 // verify there are no errors from the parser...
1939 if( !verify_array( unary
->array
) )
1943 if( !unary
->array
->exp_list
)
1945 EM_error2( unary
->linepos
, "cannot use empty [] with 'new'..." );
1949 // type check the exp
1950 if( !type_engine_check_exp( env
, unary
->array
->exp_list
) )
1952 // make sure types are of int
1953 if( !type_engine_check_array_subscripts( env
, unary
->array
->exp_list
) )
1956 // create the new array type, replace t
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
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'...",
1975 EM_error2( unary
->linepos
,
1976 "...(primitive types: 'int', 'float', 'time', 'dur')" );
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 (@)..." );
1996 EM_error2( unary
->linepos
,
1997 "no suitable resolution for prefix unary operator '%s' on type '%s...",
1998 op2str( unary
->op
), t
->c_name() );
2005 //-----------------------------------------------------------------------------
2006 // name: type_engine_check_exp_primary()
2008 //-----------------------------------------------------------------------------
2009 t_CKTYPE
type_engine_check_exp_primary( Chuck_Env
* env
, a_Exp_Primary exp
)
2012 Chuck_Value
* v
= NULL
;
2016 switch( exp
->s_type
)
2019 case ae_primary_var
:
2020 str
= S_name(exp
->var
);
2023 if( str
== "this" ) // this
2026 if( !env
->class_def
)
2028 EM_error2( exp
->linepos
,
2029 "keyword 'this' can be used only inside class definition..." );
2034 if( env
->func
&& !env
->func
->is_member
)
2036 EM_error2( exp
->linepos
,
2037 "keyword 'this' cannot be used inside static functions..." );
2042 exp
->self
->s_meta
= ae_meta_value
;
2043 // whatever the class is
2046 else if( str
== "me" ) // me
2049 exp
->self
->s_meta
= ae_meta_value
;
2053 else if( str
== "now" ) // now
2055 // assignable in a strongly timed way
2056 exp
->self
->s_meta
= ae_meta_var
;
2060 else if( str
== "dac" ) // dac
2063 exp
->self
->s_meta
= ae_meta_value
;
2067 else if( str
== "adc" ) // adc
2070 exp
->self
->s_meta
= ae_meta_value
;
2074 else if( str
== "blackhole" ) // blackhole
2077 exp
->self
->s_meta
= ae_meta_value
;
2081 else if( str
== "null" || str
== "NULL" ) // null / NULL
2084 exp
->self
->s_meta
= ae_meta_value
;
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
);
2096 if( env
->class_def
)
2099 v
= type_engine_find_value( env
->class_def
->parent
, exp
->var
);
2106 // v = env->curr->lookup_value( exp->var, TRUE );
2107 v
= type_engine_find_value( env
, S_name(exp
->var
), TRUE
, exp
->linepos
);
2114 if( env
->class_def
)
2116 // inside a function definition
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
) );
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
) );
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() );
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...",
2167 case ae_primary_num
:
2172 case ae_primary_float
:
2177 case ae_primary_str
:
2179 if( !escape_str( exp
->str
, exp
->linepos
) )
2187 case ae_primary_array
:
2188 t
= type_engine_check_exp_array_lit( env
, exp
);
2192 case ae_primary_complex
:
2193 t
= type_engine_check_exp_complex_lit( env
, exp
);
2197 case ae_primary_polar
:
2198 t
= type_engine_check_exp_polar_lit( env
, exp
);
2202 case ae_primary_exp
:
2203 t
= type_engine_check_exp( env
, exp
->exp
);
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..." );
2216 t
= type_engine_check_exp( env
, exp
->exp
);
2220 case ae_primary_nil
:
2226 EM_error2( exp
->linepos
,
2227 "internal error - unrecognized primary type '%i'...", exp
->s_type
);
2237 //-----------------------------------------------------------------------------
2238 // name: type_engine_check_exp_array_lit()
2240 //-----------------------------------------------------------------------------
2241 t_CKTYPE
type_engine_check_exp_array_lit( Chuck_Env
* env
, a_Exp_Primary exp
)
2244 assert( exp
->s_type
== ae_primary_array
);
2247 Chuck_Type
* t
= NULL
, * type
= NULL
, * common
= NULL
;
2249 // verify there are no errors from the parser...
2250 if( !verify_array( exp
->array
) )
2253 // verify they are of same type - do this later?
2254 a_Exp e
= exp
->array
->exp_list
;
2259 EM_error2( exp
->linepos
,
2260 "must provide values/expressions for array [...]" );
2264 // go through the array and type check each
2265 if( !type_engine_check_exp( env
, e
) )
2282 // find common ancestor
2283 common
= type_engine_find_common_anc( t
, type
);
2285 if( common
) type
= common
;
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
2298 EM_error2( e
->linepos
, "array init [...] contains incompatible types..." );
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
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();
2329 t->name = type->name;
2331 t->parent = &t_array;
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
2340 t->info = t_array.info;
2344 t->owner = env->curr;
2353 //-----------------------------------------------------------------------------
2354 // name: type_engine_check_exp_complex_lit()
2356 //-----------------------------------------------------------------------------
2357 t_CKTYPE
type_engine_check_exp_complex_lit( Chuck_Env
* env
, a_Exp_Primary exp
)
2360 assert( exp
->s_type
== ae_primary_complex
);
2363 Chuck_Type
* type_re
= NULL
, * type_im
= NULL
;
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)" );
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)" );
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 )) )
2391 type_im
= val
->im
->type
;
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() );
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() );
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
;
2419 //-----------------------------------------------------------------------------
2420 // name: type_engine_check_exp_polar_lit()
2422 //-----------------------------------------------------------------------------
2423 t_CKTYPE
type_engine_check_exp_polar_lit( Chuck_Env
* env
, a_Exp_Primary exp
)
2426 assert( exp
->s_type
== ae_primary_polar
);
2429 Chuck_Type
* type_mod
= NULL
, * type_phase
= NULL
;
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)" );
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)" );
2452 if( !(type_mod
= type_engine_check_exp( env
, val
->mod
)) ||
2453 !(type_phase
= type_engine_check_exp( env
, val
->phase
)) )
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() );
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() );
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
;
2482 //-----------------------------------------------------------------------------
2483 // name: type_engine_check_exp_cast()
2485 //-----------------------------------------------------------------------------
2486 t_CKTYPE
type_engine_check_exp_cast( Chuck_Env
* env
, a_Exp_Cast cast
)
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
);
2497 EM_error2( cast
->linepos
, "... in cast expression ..." );
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() );
2516 //-----------------------------------------------------------------------------
2517 // name: type_engine_check_cast_valid()
2519 //-----------------------------------------------------------------------------
2520 t_CKBOOL
type_engine_check_cast_valid( Chuck_Env
* env
, t_CKTYPE to
, t_CKTYPE from
)
2523 if( isa( from
, to
) ) return TRUE
;
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
;
2546 //-----------------------------------------------------------------------------
2547 // name: type_engine_check_exp_dur()
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
;
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() );
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() );
2583 //-----------------------------------------------------------------------------
2584 // name: type_engine_check_exp_postfix()
2586 //-----------------------------------------------------------------------------
2587 t_CKTYPE
type_engine_check_exp_postfix( Chuck_Env
* env
, a_Exp_Postfix postfix
)
2590 t_CKTYPE t
= type_engine_check_exp( env
, postfix
->exp
);
2591 if( !t
) return NULL
;
2594 switch( postfix
->op
)
2596 case ae_op_plusplus
:
2597 case ae_op_minusminus
:
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
) );
2607 postfix
->exp
->emit_var
= TRUE
;
2608 // TODO: mark somewhere we need to post increment
2611 if( isa( t
, &t_int
) || isa( t
, &t_float
) )
2617 EM_error2( postfix
->linepos
,
2618 "internal compiler error: unrecognized postfix '%i'", postfix
->op
);
2623 EM_error2( postfix
->linepos
,
2624 "no suitable resolutation for postfix operator '%s' on type '%s'...",
2625 op2str( postfix
->op
), t
->c_name() );
2632 //-----------------------------------------------------------------------------
2633 // name: type_engine_check_exp_if()
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
;
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() );
2665 //-----------------------------------------------------------------------------
2666 // name: type_engine_check_array_subscripts( )
2668 //-----------------------------------------------------------------------------
2669 t_CKBOOL
type_engine_check_array_subscripts( Chuck_Env
* env
, a_Exp exp_list
)
2671 a_Exp exp
= exp_list
;
2677 if( !isa( exp
->type
, &t_int
) )
2679 EM_error2( exp
->linepos
,
2680 "incompatible array subscript type '%s'...",
2681 exp
->type
->name
.c_str() );
2694 //-----------------------------------------------------------------------------
2695 // name: type_engine_check_exp_decl( )
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
)
2711 var_decl
= list
->var_decl
;
2713 // (if at class_scope) check if in parent
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() );
2725 value
= var_decl
->value
;
2727 assert( value
!= NULL
);
2731 assert( type
!= NULL
);
2733 is_obj
= isobj( type
);
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
) )
2744 // check the subscripts
2745 if( !type_engine_check_array_subscripts( env
, var_decl
->array
->exp_list
) )
2750 if( value
->is_member
)
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
2760 if( env
->class_def
== NULL
|| env
->class_scope
> 0 )
2762 EM_error2( decl
->linepos
,
2763 "static variables must be declared at class scope..." );
2768 value
->is_static
= TRUE
;
2770 value
->offset
= env
->class_def
->info
->class_data_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)" );
2786 else // local variable
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 )
2799 env
->curr
->value
.add( var_decl
->xid
, value
);
2802 // the next var decl
2806 return decl
->ck_type
;
2812 //-----------------------------------------------------------------------------
2813 // name: type_engine_print_exp_dot_member()
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
;
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
);
2830 the_base
= base_static
? member
->t_base
->actual_type
: member
->t_base
;
2833 str
= S_name(member
->xid
);
2835 return string(the_base
->c_name()) + std::string(".") + str
;
2841 //-----------------------------------------------------------------------------
2842 // name: find_func_match()
2844 //-----------------------------------------------------------------------------
2845 Chuck_Func
* find_func_match( Chuck_Func
* up
, a_Exp args
, t_CKBOOL implicit
)
2852 // see if args is nil
2853 if( args
&& args
->type
== &t_void
)
2856 // up is the list of functions in single class / namespace
2864 e1
= func
->def
->arg_list
;
2867 // check arguments against the definition
2870 // check for extra arguments
2871 if( e1
== NULL
) goto moveon
;
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
)
2880 e
->cast_to
= &t_float
;
2882 else goto moveon
; // type mismatch
2890 // check for extra arguments
2891 if( e1
== NULL
) return func
;
2899 if( up
->up
) up
= up
->up
->func_ref
;
2910 //-----------------------------------------------------------------------------
2911 // name: type_engine_check_exp_func_call()
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" );
2938 // check the arguments
2941 a
= type_engine_check_exp( env
, args
);
2942 if( !a
) return NULL
;
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
);
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() );
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)" );
2982 // recheck the type with new name
2983 if( exp_func
->s_type
== ae_exp_primary
&& exp_func
->primary
.s_type
== ae_primary_var
)
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
) )
2992 EM_error2( exp_func
->linepos
,
2993 "internal error: function type different on second check..." );
2997 else if( exp_func
->s_type
== ae_exp_dot_member
)
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 ) )
3008 EM_error2( exp_func->linepos,
3009 "internal error: function type different on second check..." );
3014 else assert( FALSE
);
3018 return func
->def
->ret_type
;
3024 //-----------------------------------------------------------------------------
3025 // name: type_engine_check_exp_func_call()
3027 //-----------------------------------------------------------------------------
3028 t_CKTYPE
type_engine_check_exp_func_call( Chuck_Env
* env
, a_Exp_Func_Call func_call
)
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()
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
;
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!!!
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
)
3065 EM_error2( member
->base
->linepos
,
3066 "cannot assign value to literal complex value..." );
3075 EM_error2( member
->linepos
,
3076 "type '%s' has no member named '%s'...", member
->t_base
->c_name(), str
.c_str() );
3080 else if( member
->t_base
->xid
== te_polar
)
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
)
3091 EM_error2( member
->base
->linepos
,
3092 "cannot assign value to literal polar value..." );
3101 EM_error2( member
->linepos
,
3102 "type '%s' has no member named '%s'...", member
->t_base
->c_name(), str
.c_str() );
3107 // is the base a class/namespace or a variable
3108 base_static
= isa( member
->t_base
, &t_class
);
3110 the_base
= base_static
? member
->t_base
->actual_type
: member
->t_base
;
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() );
3123 str
= S_name(member
->xid
);
3129 EM_error2( member
->linepos
,
3130 "keyword 'this' must be associated with object instance..." );
3134 if( env
->func
&& !env
->func
->is_member
)
3136 EM_error2( member
->linepos
,
3137 "keyword 'this' cannot be used inside static functions..." );
3141 return env
->class_def
;
3145 value
= type_engine_find_value( the_base
, member
->xid
);
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
) );
3156 if( base_static
&& value
->is_member
)
3159 EM_error2( member
->linepos
,
3160 "cannot access member '%s.%s' without object instance...",
3161 the_base
->c_name(), S_name(member
->xid
) );
3171 //-----------------------------------------------------------------------------
3172 // name: type_engine_check_exp_array()
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
) )
3181 // type check the base
3182 t_CKTYPE t_base
= type_engine_check_exp( env
, array
->base
);
3183 if( !t_base
) return NULL
;
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
);
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
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() );
3222 assert( array
->indices
->depth
== depth
);
3225 // make sure depth <= max
3226 if( depth
== t_base
->array_depth
)
3228 // the original type
3229 t
= array
->base
->type
->array_type
;
3234 t
= array
->base
->type
->copy( env
);
3236 t
->array_depth
-= depth
;
3245 //-----------------------------------------------------------------------------
3246 // name: type_engine_check_class_def()
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
;
3254 t_CKTYPE t_parent
= NULL
;
3256 t_CKBOOL ret
= TRUE
;
3258 a_Class_Body body
= class_def
->body
;
3260 // make sure inheritance
3262 if( class_def
->ext
)
3265 if( class_def
->ext
->extend_id
)
3268 t_parent
= type_engine_find_type( env
, class_def
->ext
->extend_id
);
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
) );
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')" );
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)" );
3303 // by default object
3304 if( !t_parent
) t_parent
= &t_object
;
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
);
3344 case ae_section_func
:
3346 env
->class_def
->is_complete
= TRUE
;
3347 ret
= type_engine_check_func_def( env
, body
->section
->func_def
);
3349 env
->class_def
->is_complete
= FALSE
;
3352 case ae_section_class
:
3354 ret
= type_engine_check_class_def( env
, body
->section
->class_def
);
3358 // move to the next section
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();
3372 // set the object size
3373 the_class
->obj_size
= the_class
->info
->offset
;
3375 the_class
->is_complete
= TRUE
;
3379 // delete the class definition
3380 SAFE_RELEASE( class_def
->type
);
3381 // set the thing to NULL
3391 //-----------------------------------------------------------------------------
3392 // name: type_engine_check_func_def()
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
);
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" );
3421 value
= func
->value_ref
;
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...",
3434 EM_error2( f
->linepos
, "from super class '%s'...", override
->owner_class
->c_name() );
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
);
3445 // make reference to parent
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
) );
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
) );
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
) );
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
) );
3490 // if overriding super class function, then check signatures
3491 if( env
->class_def
)
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...",
3504 EM_error2( f
->linepos
, "from super class '%s'...", v
->owner_class
->c_name() );
3509 parent_func
= v
->func_ref
;
3511 // go through all overloading
3512 while( parent_func
&& !parent_match
)
3514 // match the prototypes
3516 if( !type_engine_compat_func( f
, parent_func
->def
, f
->linepos
, err
, FALSE
) )
3519 parent_func
= parent_func
->next
;
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() );
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
) );
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
) );
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
) );
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
) );
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
;
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
3612 // push the value stack
3613 env
->curr
->value
.push();
3615 // look up types for the function arguments
3616 arg_list
= f
->arg_list
;
3619 // loop over arguments
3622 // make sure type != NULL
3623 assert( arg_list
->type
!= NULL
);
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
) );
3639 env
->curr
->value
.add( arg_list
->var_decl
->xid
, v
);
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
) );
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
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
);
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
);
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
);
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
);
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
);
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
);
3774 //-----------------------------------------------------------------------------
3775 // name: get_types()
3776 // desc: get top level types
3777 //-----------------------------------------------------------------------------
3778 void Chuck_Namespace::get_types( vector
<Chuck_Type
*> & out
)
3781 vector
<Chuck_VM_Object
*> list
;
3782 // get it from the scope
3783 this->type
.get_toplevel( list
);
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
)
3802 vector
<Chuck_VM_Object
*> list
;
3803 // get it from the scope
3804 this->value
.get_toplevel( list
);
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
)
3823 vector
<Chuck_VM_Object
*> list
;
3824 // get it from the scope
3825 this->type
.get_toplevel( list
);
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 ==
3840 //-----------------------------------------------------------------------------
3841 t_CKBOOL
operator ==( const Chuck_Type
& lhs
, const Chuck_Type
& rhs
)
3844 if( lhs
.xid
!= rhs
.xid
) return FALSE
;
3845 // check array depth
3846 if( lhs
.array_depth
!= rhs
.array_depth
) return FALSE
;
3848 if( lhs
.array_depth
&& (*lhs
.actual_type
!= *rhs
.actual_type
) ) return FALSE
;
3850 // if user-defined type
3851 if( lhs
.xid
== te_user
)
3854 if( lhs
.name
!= rhs
.name
) return FALSE
;
3856 if( lhs
.owner
!= rhs
.owner
) return FALSE
;
3865 //-----------------------------------------------------------------------------
3866 // name: operator !=
3868 //-----------------------------------------------------------------------------
3869 t_CKBOOL
operator !=( const Chuck_Type
& lhs
, const Chuck_Type
& rhs
)
3870 { return !( lhs
== rhs
); }
3875 //-----------------------------------------------------------------------------
3878 //-----------------------------------------------------------------------------
3879 t_CKBOOL
equals( Chuck_Type
* lhs
, Chuck_Type
* rhs
) { return (*lhs
) == (*rhs
); }
3884 //-----------------------------------------------------------------------------
3885 // name: operator <=
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
;
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
;
3910 //-----------------------------------------------------------------------------
3913 //-----------------------------------------------------------------------------
3914 t_CKBOOL
isa( Chuck_Type
* lhs
, Chuck_Type
* rhs
) { return (*lhs
) <= (*rhs
); }
3919 //-----------------------------------------------------------------------------
3920 // name: ~Chuck_Context()
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
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();
3939 // TODO: delete abstract syntax tree *
3945 //-----------------------------------------------------------------------------
3946 // name: add_commit_candidate()
3948 //-----------------------------------------------------------------------------
3949 void Chuck_Context::add_commit_candidate( Chuck_Namespace
* nspc
)
3952 commit_map
[nspc
] = nspc
;
3958 //-----------------------------------------------------------------------------
3961 //-----------------------------------------------------------------------------
3962 void Chuck_Context::commit()
3964 std::map
<Chuck_Namespace
*, Chuck_Namespace
*>::iterator iter
;
3967 for( iter
= commit_map
.begin(); iter
!= commit_map
.end(); iter
++ )
3970 (*iter
).second
->commit();
3980 //-----------------------------------------------------------------------------
3983 //-----------------------------------------------------------------------------
3984 void Chuck_Context::rollback()
3986 std::map
<Chuck_Namespace
*, Chuck_Namespace
*>::iterator iter
;
3989 for( iter
= commit_map
.begin(); iter
!= commit_map
.end(); iter
++ )
3992 (*iter
).second
->rollback();
4002 //-----------------------------------------------------------------------------
4003 // name: type_engine_check_reserved()
4005 //--------------------------------------------------------------------------
4006 t_CKBOOL
type_engine_check_reserved( Chuck_Env
* env
, const string
& xid
, int pos
)
4009 if( env
->key_words
[xid
] )
4011 EM_error2( pos
, "illegal use of keyword '%s'.", xid
.c_str() );
4016 if( env
->key_values
[xid
] )
4018 EM_error2( pos
, "illegal re-declaration of reserved value '%s'.", xid
.c_str() );
4023 if( env
->key_types
[xid
] )
4025 EM_error2( pos
, "illegal use of reserved type id '%s'.", xid
.c_str() );
4035 //-----------------------------------------------------------------------------
4036 // name: type_engine_check_reserved()
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()
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()
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
;
4078 Chuck_Type
* t
= lhs
->parent
;
4083 // check and see again
4084 if( isa( rhs
, t
) ) return t
;
4096 //-----------------------------------------------------------------------------
4097 // name: type_path()
4099 //-----------------------------------------------------------------------------
4100 const char * type_path( a_Id_List path
)
4110 str
+= S_name(path
->xid
);
4112 if( path
->next
) str
+= ".";
4123 //-----------------------------------------------------------------------------
4124 // name: type_engine_find_type()
4126 //-----------------------------------------------------------------------------
4127 Chuck_Type
* type_engine_find_type( Chuck_Namespace
* nspc
, S_Symbol xid
)
4129 Chuck_Type
* type
= NULL
;
4130 if( !nspc
) return NULL
;
4132 if(( type
= nspc
->lookup_type( xid
, -1 ) )) return type
;
4139 //-----------------------------------------------------------------------------
4140 // name: type_engine_get_deprecate()
4142 //-----------------------------------------------------------------------------
4143 t_CKBOOL
type_engine_get_deprecate( Chuck_Env
* env
,
4144 const string
& from
, string
& to
)
4147 if( env
->deprecated
.find( from
) == env
->deprecated
.end() )
4151 to
= env
->deprecated
[from
];
4159 //-----------------------------------------------------------------------------
4160 // name: type_engine_find_deprecated_type()
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
;
4170 if( !type_engine_get_deprecate( env
, S_name(path
->xid
), actual
) )
4174 Chuck_Type
* type
= env
->curr
->lookup_type( actual
, TRUE
);
4175 if( !type
) return NULL
;
4179 if( env
->deprecate_level
< 2 )
4181 EM_error2( path
->linepos
, "deprecated: '%s' --> use: '%s'...",
4182 type_path( path
), actual
.c_str() );
4192 //-----------------------------------------------------------------------------
4193 // name: type_engine_find_type()
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
;
4201 Chuck_Type
* type
= env
->curr
->lookup_type( path
->xid
, TRUE
);
4205 if( env
->deprecate_level
> 0 )
4206 type
= type_engine_find_deprecated_type( env
, path
);
4211 EM_error2( path
->linepos
, "undefined type '%s'...",
4212 type_path( path
) );
4216 // start the namespace
4217 Chuck_Namespace
* nspc
= type
->info
;
4221 while( path
!= NULL
)
4225 // look for the type in the namespace
4226 t
= type_engine_find_type( nspc
, xid
);
4228 while( !t
&& type
&& type
->parent
)
4230 t
= type_engine_find_type( type
->parent
->info
, xid
);
4231 type
= type
->parent
;
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() );
4248 if( type
) nspc
= type
->info
;
4259 //-----------------------------------------------------------------------------
4260 // name: type_engine_find_value()
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()
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
;
4281 if(( value
= type
->info
->lookup_value( xid
, -1 ) )) return value
;
4282 if( type
->parent
) return type_engine_find_value( type
->parent
, xid
);
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
;
4300 if(( value
= env
->curr
->lookup_value( xid
, climb
) )) return value
;
4302 // see if deprecated if climb
4305 if( !type_engine_get_deprecate( env
, xid
, actual
) )
4309 value
= env
->curr
->lookup_value( actual
, TRUE
);
4310 if( !value
) return NULL
;
4314 if( env
->deprecate_level
< 2 )
4316 EM_error2( linepos
, "deprecated: '%s' --> use: '%s'...",
4317 xid
.c_str(), actual
.c_str() );
4328 //-----------------------------------------------------------------------------
4329 // name: type_engine_find_nspc()
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
;
4338 if( path
== NULL
) return env
->global();
4340 Chuck_Type
* type
= type_engine_find_type( env
, path
);
4341 if( type
== NULL
) return NULL
;
4347 if( isprim( type
) )
4350 EM_error2( 0, "primitive type '%s' has no namespace and cannot be extended...",
4357 EM_error2( 0, "internal error: type '%s' without namespace...",
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
)
4380 EM_error2( pos
, "function signatures differ in access modifiers..." );
4381 EM_error2( pos
, "(both must be one of public/private/protected/function)..." );
4386 a_Arg_List e1
= lhs
->arg_list
;
4387 a_Arg_List e2
= rhs
->arg_list
;
4390 // check arguments against the definition
4394 assert( e1
->type
&& e2
->type
);
4397 if( *e1
->type
!= *e2
->type
)
4399 if( print
) EM_error2( pos
, "function signatures differ in argument %i's type...", count
);
4409 if( e1
!= NULL
|| e2
!= NULL
)
4411 if( print
) EM_error2( pos
,
4412 "function signatures differ in number of arguments..." );
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
)
4438 EM_error2( 0, "during import: class '%s' already imported...", type
->c_name() );
4442 // allocate namespace for type
4443 type
->info
= new Chuck_Namespace
;
4445 SAFE_ADD_REF(type
->info
);
4447 type
->info
->name
= type
->name
;
4448 // set the parent namespace
4449 type
->info
->parent
= where
;
4451 SAFE_ADD_REF(type
->info
->parent
);
4453 // if pre constructor
4457 type
->has_constructor
= TRUE
;
4458 // allocate vm code for pre_ctor
4459 type
->info
->pre_ctor
= new Chuck_VM_Code
;
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
);
4474 type
->has_destructor
= TRUE
;
4475 // allocate vm code for dtor
4476 type
->info
->dtor
= new Chuck_VM_Code
;
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
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
;
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
4506 type
->is_complete
= TRUE
;
4508 type_type
= t_class
.copy( env
);
4509 type_type
->actual_type
= type
;
4510 // SAFE_REF_ASSIGN( type_type->actual_type, type );
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
;
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
;
4538 //-----------------------------------------------------------------------------
4539 // name: type_engine_import_class_begin()
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
)
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
, "") )
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
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
);
4572 if( !type_engine_import_class_begin( env
, type
, where
, pre_ctor
, dtor
) )
4580 EM_error2( 0, "... during import of class '%s'", name
);
4582 SAFE_DELETE( type
);
4586 delete_id_list( parent_list
);
4594 //-----------------------------------------------------------------------------
4595 // name: type_engine_import_ugen_begin()
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
;
4608 if( !(type
= type_engine_import_class_begin( env
, name
, parent
, where
, pre_ctor
, dtor
) ) )
4611 // make sure parent is ugen
4612 assert( type
->parent
!= NULL
);
4613 if( !isa( type
->parent
, &t_ugen
) )
4617 "imported class '%s' does not have a ugen as parent",
4623 info
= new Chuck_UGen_Info
;
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
;
4634 type
->ugen_info
= info
;
4642 //-----------------------------------------------------------------------------
4643 // name: type_engine_import_uana_begin()
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
;
4657 if( !(type
= type_engine_import_ugen_begin( env
, name
, parent
, where
, pre_ctor
, dtor
,
4658 tick
, pmsg
, num_ins
, num_outs
) ) )
4661 // make sure parent is ugen
4662 assert( type
->parent
!= NULL
);
4663 if( !isa( type
->parent
, &t_uana
) )
4667 "imported class '%s' does not have a uana as parent",
4673 info
= type
->ugen_info
;
4675 assert( info
!= NULL
);
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
;
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
)
4696 EM_error2( 0, "import: too many class_end called..." );
4700 // set the object size
4701 env
->class_def
->obj_size
= env
->class_def
->info
->offset
;
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();
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
)
4729 "import error: import_mfun '%s' invoked between begin/end",
4730 mfun
->name
.c_str() );
4734 // make into func_def
4735 func_def
= make_dll_as_fun( mfun
, FALSE
);
4739 // add the function to class
4740 if( !type_engine_scan1_func_def( env
, func_def
) )
4742 if( !type_engine_scan2_func_def( env
, func_def
) )
4744 if( !type_engine_check_func_def( env
, func_def
) )
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
)
4766 "import error: import_sfun '%s' invoked between begin/end",
4767 sfun
->name
.c_str() );
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
) )
4777 if( !type_engine_scan2_func_def( env
, func_def
) )
4779 if( !type_engine_check_func_def( env
, func_def
) )
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
)
4800 "import error: import_mvar '%s' invoked between begin/end",
4802 return CK_INVALID_OFFSET
;
4806 t_CKUINT array_depth
= 0;
4807 a_Id_List path
= str2list( type
, array_depth
);
4811 EM_error2( 0, "... during mvar import '%s.%s'...",
4812 env
->class_def
->c_name(), name
);
4813 return CK_INVALID_OFFSET
;
4816 a_Type_Decl type_decl
= new_type_decl( path
, FALSE
, 0 );
4821 type_decl
->array
= new_array_sub( NULL
, 0 );
4823 type_decl
->array
->depth
= array_depth
;
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 );
4830 a_Exp exp_decl
= new_exp_decl( type_decl
, var_decl_list
, FALSE
, 0 );
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
;
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
,
4858 // make sure we are in class
4859 if( !env
->class_def
)
4863 "import error: import_svar '%s' invoked between begin/end",
4869 a_Id_List path
= str2list( type
);
4873 EM_error2( 0, "... during svar import '%s.%s'...",
4874 env
->class_def
->c_name(), name
);
4879 a_Type_Decl type_decl
= new_type_decl( path
, FALSE
, 0 );
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 );
4885 a_Exp exp_decl
= new_exp_decl( type_decl
, var_decl_list
, TRUE
, 0 );
4887 var_decl
->addr
= (void *)addr
;
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
);
4898 delete_id_list( path
);
4906 //-----------------------------------------------------------------------------
4907 // name: type_engine_register_deprecate()
4909 //-----------------------------------------------------------------------------
4910 t_CKBOOL
type_engine_register_deprecate( Chuck_Env
* env
,
4911 const string
& former
,
4912 const string
& latter
)
4914 env
->deprecated
[former
] = latter
;
4921 //-----------------------------------------------------------------------------
4922 // name: init_special()
4924 //-----------------------------------------------------------------------------
4925 void init_special( Chuck_VM_Object
* obj
)
4927 // reference - this is done when the reference is assigned
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()
4944 Chuck_Type
* type
= new Chuck_Type
;
4945 if( !type
) return NULL
;
4947 type
->m_v_ref
= &new_types
;
4949 init_special( 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
)
4965 Chuck_Value
* value
= new Chuck_Value( t
, name
);
4966 if( !value
) return NULL
;
4968 value
->m_v_ref
= &new_values
;
4970 init_special( value
);
4978 //-----------------------------------------------------------------------------
4979 // name: new_Chuck_Func()
4980 // desc: instantiate new chuck func
4981 //-----------------------------------------------------------------------------
4982 Chuck_Func
* Chuck_Context::new_Chuck_Func()
4985 Chuck_Func
* func
= new Chuck_Func
;
4986 if( !func
) return NULL
;
4988 func
->m_v_ref
= &new_funcs
;
4990 init_special( func
);
4998 //-----------------------------------------------------------------------------
4999 // name: new_Chuck_Namespace()
5000 // desc: instantiate new chuck namespace
5001 //-----------------------------------------------------------------------------
5002 Chuck_Namespace
* Chuck_Context::new_Chuck_Namespace()
5005 Chuck_Namespace
* nspc
= new Chuck_Namespace
;
5006 if( !nspc
) return NULL
;
5008 nspc
->m_v_ref
= &new_nspc
;
5010 init_special( 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
)
5027 Chuck_Type
* t
= env
->context
->new_Chuck_Type();
5031 t
->name
= base_type
->name
;
5033 t
->parent
= array_parent
;
5035 SAFE_ADD_REF(t
->parent
);
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
;
5043 SAFE_ADD_REF(t
->array_type
);
5044 // set the namesapce
5045 t
->info
= array_parent
->info
;
5047 SAFE_ADD_REF(t
->info
);
5049 t
->owner
= owner_nspc
;
5051 SAFE_ADD_REF(t
->owner
);
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 [...][...]..." );
5075 else if( array
->err_num
== 2 )
5077 EM_error2( array
->linepos
,
5078 "partially empty array init [...][]..." );
5083 EM_error2( array
->linepos
,
5084 "internal error: unrecognized array error..." );
5095 //-----------------------------------------------------------------------------
5097 // desc: convert str to list
5098 //-----------------------------------------------------------------------------
5099 a_Id_List
str2list( const string
& path
)
5102 return str2list( path
, dummy
);
5108 //-----------------------------------------------------------------------------
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();
5117 a_Id_List list
= NULL
;
5122 while( len
> 2 && path
[len
-1] == ']' && path
[len
-2] == '[' )
5131 for( i
= len
- 1; i
>= 0; i
-- )
5137 // check to make sure valid
5138 if( ( c
>= 'A' && c
<= 'Z' ) || ( c
>= 'a' && c
<= 'z' )
5139 || ( c
== '_' ) || ( c
>= '0' && c
<= '9' ) )
5147 EM_error2( 0, "illegal character '%c' in path '%s'...",
5150 delete_id_list( list
);
5156 if( c
== '.' || i
== 0 )
5159 if( (i
!= 0 && last
!= '.' && last
!= '\0') ||
5160 (i
== 0 && c
!= '.') )
5163 t_CKINT size
= curr
.length();
5165 for( j
= 0; j
< size
/2; j
++ )
5169 curr
[j
] = curr
[size
-j
-1];
5172 // make a new id and put in list
5173 list
= prepend_id_list( (char *)curr
.c_str(), list
, 0 );
5180 EM_error2( 0, "path '%s' must not begin or end with '.'",
5183 delete_id_list( 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;
5216 for( i
= dl_fun
->args
.size() - 1; i
>= 0; i
-- )
5218 // copy into variable
5219 arg
= dl_fun
->args
[i
];
5222 type_path
= str2list( arg
->type
, array_depth
);
5226 EM_error2( 0, "...at argument '%i'...", i
+1 );
5227 // delete the arg list
5228 // delete_arg_list( arg_list );
5233 type_decl
= new_type_decl( type_path
, FALSE
, 0 );
5235 assert( type_decl
);
5238 name_path
= str2list( arg
->name
, array_depth2
);
5242 if( array_depth
&& array_depth2
)
5245 EM_error2( 0, "array subscript specified incorrectly for built-in module" );
5251 if( array_depth2
) array_depth
= array_depth2
;
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 );
5263 arg_list
= prepend_arg_list( type_decl
, var_decl
, arg_list
, 0 );
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
;
5292 type_path
= str2list( dl_fun
->type
, array_depth
);
5296 EM_error2( 0, "...during function import '%s' (type)...",
5297 dl_fun
->name
.c_str() );
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
);
5308 EM_error2( 0, "...during function import '%s' (type2)...",
5309 dl_fun
->name
.c_str() );
5311 delete_id_list( type_path
);
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
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();
5333 arg_list
= make_dll_arg_list( dl_fun
);
5334 if( dl_fun
->args
.size() > 0 && !arg_list
)
5337 EM_error2( 0, "...during function import '%s' (arg_list)...",
5338 dl_fun
->name
.c_str() );
5340 // delete_type_decl( type_decl );
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
;
5359 // if( !func_def ) delete_type_decl( type_decl );
5360 // else delete_func_def( func_def );
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
)
5375 string where
= ( dest
== "" ? "global" : dest
);
5376 Chuck_Namespace
* nspc
= NULL
;
5377 const Chuck_DL_Query
* query
= NULL
;
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
;
5390 query
= dll
->query();
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
;
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
);
5409 name
= str2list( cl
->name
);
5410 if( !name
) goto error
;
5411 // if parent is specified
5412 if( cl
->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
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
;
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
;
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
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
++ )
5465 a_Id_List path
= str2list( cl
->svars
[j
]->type
.c_str() );
5467 a_Type_Decl type_decl
= new_type_decl( path
, FALSE
, 0 );
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 );
5473 a_Exp exp_decl
= new_exp_decl( type_decl
, var_decl_list
, TRUE
, 0 );
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
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
-- )
5488 body
= prepend_class_body( new_section_func_def( the_funs
[k
], 0 ), body
, 0 );
5492 def
= new_class_def( ae_key_public
, name
, ext
, body
, 0 );
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
;
5507 delete_id_list( path
);
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() );
5517 delete_id_list( path
);
5519 // TODO: free the absyn stuff?
5527 static const char * g_howmuch
[] = { "ALL", "CLASSES_ONLY", "ALL_EXCEPT_CLASSES" };
5528 //-----------------------------------------------------------------------------
5529 // name: howmuch2str()
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()
5548 //-----------------------------------------------------------------------------
5549 void escape_table( )
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
5564 g_escape_ready
= TRUE
;
5568 //-----------------------------------------------------------------------------
5569 // name: escape_str()
5571 //-----------------------------------------------------------------------------
5572 t_CKBOOL
escape_str( char * str_lit
, int linepos
)
5574 // create if not yet
5575 if( !g_escape_ready
)
5579 char * str
= str_lit
;
5580 // unsigned because we index array of 256
5581 unsigned char c
, c2
, c3
;
5587 if( *str_lit
== '\\' )
5592 // make sure next char
5593 if( *str_lit
== '\0' )
5595 EM_error2( linepos
, "invalid: string ends with escape charactor '\\'" );
5604 if( c
>= '0' && c
<= '7' )
5607 if( c
== '0' && ( c2
< '0' || c2
> '7' ) )
5614 // all three should be within range
5615 if( c2
>= '0' && c2
<= '7' && c3
>= '0' && c3
<= '7' )
5618 *str
++ = (c
-'0') * 64 + (c2
-'0') * 8 + (c3
-'0');
5624 EM_error2( linepos
, "malformed octal escape sequence '\\%c%c%c'", c
, c2
, c3
);
5629 else if( c
== 'x' ) // is hex?
5631 EM_error2( linepos
, "hex escape sequence not (yet) supported (use octal!)");
5637 if( g_escape
[(int)c
] )
5638 *str
++ = g_escape
[c
];
5641 EM_error2( linepos
, "unrecognized escape sequence '\\%c'", c
);
5657 assert( str
<= str_lit
);