History

refactor 2017 core merge pre-compile

Ge Wang committed 9 years ago

Commit 702edde1 parent f57fe96129 files · +161698 −3Browse files

Unified · Split

129 files
  1. core/chuck.lex +328 −0
  2. core/chuck.y +600 −0
  3. core/chuck_absyn.cpp +972 −0
  4. core/chuck_absyn.h +406 −0
  5. core/chuck_carrier.h +14 −3
  6. core/chuck_compile.cpp +900 −0
  7. core/chuck_compile.h +138 −0
  8. core/chuck_def.h +203 −0
  9. core/chuck_dl.cpp +1210 −0
  10. core/chuck_dl.h +755 −0
  11. core/chuck_emit.cpp +4972 −0
  12. core/chuck_emit.h +176 −0
  13. core/chuck_errmsg.cpp +650 −0
  14. core/chuck_errmsg.h +177 −0
  15. core/chuck_frame.cpp +163 −0
  16. core/chuck_frame.h +101 −0
  17. core/chuck_io.cpp +1950 −0
  18. core/chuck_io.h +204 −0
  19. core/chuck_lang.cpp +4861 −0
  20. core/chuck_lang.h +481 −0
  21. core/chuck_oo.cpp +3285 −0
  22. core/chuck_otf.cpp +728 −0
  23. core/chuck_otf.h +98 −0
  24. core/chuck_parse.cpp +230 −0
  25. core/chuck_parse.h +153 −0
  26. core/chuck_scan.cpp +2750 −0
  27. core/chuck_scan.h +71 −0
  28. core/chuck_symbol.cpp +143 −0
  29. core/chuck_symbol.h +88 −0
  30. core/chuck_table.cpp +221 −0
  31. core/chuck_table.h +76 −0
  32. core/chuck_type.cpp +6483 −0
  33. core/chuck_type.h +947 −0
  34. core/chuck_utils.cpp +77 −0
  35. core/chuck_utils.h +62 −0
  36. core/dirent_win32.h +234 −0
  37. core/lo/address.c +346 −0
  38. core/lo/blob.c +64 −0
  39. core/lo/bundle.c +181 −0
  40. core/lo/config.h +200 −0
  41. core/lo/lo.h +353 −0
  42. core/lo/lo_endian.h +256 −0
  43. core/lo/lo_errors.h +45 −0
  44. core/lo/lo_internal.h +63 −0
  45. core/lo/lo_lowlevel.h +860 −0
  46. core/lo/lo_macros.h +80 −0
  47. core/lo/lo_osc_types.h +145 −0
  48. core/lo/lo_throw.h +30 −0
  49. core/lo/lo_types.h +143 −0
  50. core/lo/lo_types_internal.h +145 −0
  51. core/lo/message.c +1081 −0
  52. core/lo/method.c +35 −0
  53. core/lo/pattern_match.c +248 −0
  54. core/lo/send.c +491 −0
  55. core/lo/server.c +1400 −0
  56. core/lo/server_thread.c +188 −0
  57. core/lo/timetag.c +58 −0
  58. core/regex/LICENSE.txt +29 −0
  59. core/regex/README.txt +235 −0
  60. core/regex/config.h +184 −0
  61. core/regex/regcomp.c +129 −0
  62. core/regex/regerror.c +83 −0
  63. core/regex/regex.h +38 −0
  64. core/regex/regexec.c +348 −0
  65. core/regex/tre-ast.c +226 −0
  66. core/regex/tre-ast.h +128 −0
  67. core/regex/tre-compile.c +2296 −0
  68. core/regex/tre-compile.h +27 −0
  69. core/regex/tre-config.h +52 −0
  70. core/regex/tre-filter.c +73 −0
  71. core/regex/tre-filter.h +19 −0
  72. core/regex/tre-internal.h +287 −0
  73. core/regex/tre-match-approx.c +812 −0
  74. core/regex/tre-match-backtrack.c +666 −0
  75. core/regex/tre-match-parallel.c +501 −0
  76. core/regex/tre-match-utils.h +215 −0
  77. core/regex/tre-mem.c +155 −0
  78. core/regex/tre-mem.h +66 −0
  79. core/regex/tre-parse.c +1739 −0
  80. core/regex/tre-parse.h +50 −0
  81. core/regex/tre-stack.c +125 −0
  82. core/regex/tre-stack.h +76 −0
  83. core/regex/tre.h +276 −0
  84. core/regex/xmalloc.c +351 −0
  85. core/regex/xmalloc.h +77 −0
  86. core/uana_extract.cpp +1526 −0
  87. core/uana_extract.h +45 −0
  88. core/uana_xform.cpp +3762 −0
  89. core/uana_xform.h +45 −0
  90. core/ugen_filter.cpp +2694 −0
  91. core/ugen_filter.h +238 −0
  92. core/ugen_osc.cpp +1759 −0
  93. core/ugen_osc.h +112 −0
  94. core/ugen_stk.cpp +27016 −0
  95. core/ugen_stk.h +6622 −0
  96. core/ugen_xxx.cpp +4965 −0
  97. core/ugen_xxx.h +256 −0
  98. core/ulib_machine.cpp +221 −0
  99. core/ulib_machine.h +62 −0
  100. core/ulib_math.cpp +777 −0
  101. core/ulib_math.h +100 −0
  102. core/ulib_opsc.cpp +1662 −0
  103. core/ulib_opsc.h +79 −0
  104. core/ulib_regex.cpp +404 −0
  105. core/ulib_regex.h +40 −0
  106. core/ulib_std.cpp +1971 −0
  107. core/ulib_std.h +143 −0
  108. core/util_console.cpp +210 −0
  109. core/util_console.h +51 −0
  110. core/util_hid.cpp +8068 −0
  111. core/util_hid.h +221 −0
  112. core/util_math.c +200 −0
  113. core/util_math.h +75 −0
  114. core/util_network.c +442 −0
  115. core/util_network.h +105 −0
  116. core/util_opsc.cpp +2541 −0
  117. core/util_opsc.h +630 −0
  118. core/util_raw.c +4784 −0
  119. core/util_raw.h +100 −0
  120. core/util_serial.cpp +248 −0
  121. core/util_serial.h +58 −0
  122. core/util_sndfile.c +34323 −0
  123. core/util_sndfile.h +2706 −0
  124. core/util_string.cpp +569 −0
  125. core/util_string.h +87 −0
  126. core/util_thread.cpp +443 −0
  127. core/util_thread.h +213 −0
  128. core/util_xforms.c +454 −0
  129. core/util_xforms.h +89 −0
core/chuck.lex+328−0
@@ -0,0 +1,328 @@
1+
2+
3+D [0-9]
4+L [a-zA-Z_]
5+H [a-fA-F0-9]
6+E [Ee][+-]?{D}+
7+FS (f|F|l|L)
8+IS (u|U|l|L)*
9+
10+%{
11+/*----------------------------------------------------------------------------
12+ ChucK Concurrent, On-the-fly Audio Programming Language
13+ Compiler and Virtual Machine
14+
15+ Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
16+ http://chuck.cs.princeton.edu/
17+ http://soundlab.cs.princeton.edu/
18+
19+ This program is free software; you can redistribute it and/or modify
20+ it under the terms of the GNU General Public License as published by
21+ the Free Software Foundation; either version 2 of the License, or
22+ (at your option) any later version.
23+
24+ This program is distributed in the hope that it will be useful,
25+ but WITHOUT ANY WARRANTY; without even the implied warranty of
26+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27+ GNU General Public License for more details.
28+
29+ You should have received a copy of the GNU General Public License
30+ along with this program; if not, write to the Free Software
31+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
32+ U.S.A.
33+-----------------------------------------------------------------------------*/
34+
35+//-----------------------------------------------------------------------------
36+// file: chuck.yy.c
37+// desc: chuck lexer
38+//
39+// author: Ge Wang (gewang.cs.princeton.edu) - generated by lex
40+// Perry R. Cook (prc@cs.princeton.edu)
41+//
42+// based on the ansi C grammar by Jeff Lee, maintained by Jutta Degener
43+//
44+// date: Summer 2002
45+//-----------------------------------------------------------------------------
46+
47+#include <stdlib.h>
48+#include <string.h>
49+#include "chuck_utils.h"
50+#include "chuck_absyn.h"
51+#include "chuck_errmsg.h"
52+
53+#ifndef __PLATFORM_WIN32__
54+ #include "chuck.tab.h"
55+#else
56+ #include "chuck_win32.h"
57+#endif
58+
59+
60+
61+// globals
62+extern YYSTYPE yylval;
63+int char_pos = 1;
64+
65+// define error handling
66+#define YY_FATAL_ERROR(msg) EM_error2( 0, msg )
67+
68+#if defined(_cplusplus) || defined(__cplusplus)
69+extern "C" {
70+#endif
71+
72+ int yywrap(void);
73+ void adjust();
74+ c_str strip_lit( c_str str );
75+ c_str alloc_str( c_str str );
76+ long htol( c_str str );
77+ int comment();
78+ int block_comment();
79+
80+#if defined(_cplusplus) || defined(__cplusplus)
81+}
82+#endif
83+
84+// yywrap()
85+int yywrap( void )
86+{
87+ char_pos = 1;
88+ return 1;
89+}
90+
91+// adjust()
92+void adjust()
93+{
94+ EM_tokPos = char_pos;
95+ char_pos += yyleng;
96+}
97+
98+// strip
99+c_str strip_lit( c_str str )
100+{
101+ str[strlen(str)-1] = '\0';
102+ return str+1;
103+}
104+
105+// alloc_str()
106+c_str alloc_str( c_str str )
107+{
108+ c_str s = (c_str)malloc( strlen(str) + 1 );
109+ strcpy( s, str );
110+
111+ return s;
112+}
113+
114+// to long
115+long htol( c_str str )
116+{
117+ char * c = str;
118+ unsigned long n = 0;
119+
120+ // skip over 0x
121+ c += 2;
122+ while( *c )
123+ {
124+ n <<= 4;
125+ switch( *c )
126+ {
127+ case '1': case '2': case '3': case '4': case '5':
128+ case '6': case '7': case '8': case '9': case '0':
129+ n += *c - '0';
130+ break;
131+
132+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
133+ n += *c - 'a' + 10;
134+ break;
135+
136+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
137+ n += *c - 'A' + 10;
138+ break;
139+ }
140+ c++;
141+ }
142+
143+ return n;
144+}
145+
146+
147+
148+// block comment hack (thanks to unput/yytext_ptr inconsistency)
149+#define block_comment_hack loop: \
150+ while ((c = input()) != '*' && c != 0 && c != EOF ) \
151+ if( c == '\n' ) EM_newline(); \
152+ if( c == EOF ) adjust(); \
153+ else if( (c1 = input()) != '/' && c != 0 ) \
154+ { \
155+ unput(c1); \
156+ goto loop; \
157+ } \
158+ if( c != 0 ) adjust();
159+
160+// comment hack
161+#define comment_hack \
162+ while ((c = input()) != '\n' && c != '\r' && c != 0 && c != EOF ); \
163+ if (c != 0) { \
164+ adjust(); \
165+ if (c == '\n') EM_newline(); \
166+ }
167+
168+// .*\-\-> { adjust(); continue; }
169+
170+%}
171+
172+%%
173+
174+"//" { char c; adjust(); comment_hack; continue; }
175+"<--" { char c; adjust(); comment_hack; continue; }
176+"/*" { char c, c1; adjust(); block_comment_hack; continue; }
177+" " { adjust(); continue; }
178+"\t" { adjust(); continue; }
179+"\r\n" { adjust(); EM_newline(); continue; }
180+"\n" { adjust(); EM_newline(); continue; }
181+
182+"++" { adjust(); return PLUSPLUS; }
183+"--" { adjust(); return MINUSMINUS; }
184+"#(" { adjust(); return POUNDPAREN; }
185+"%(" { adjust(); return PERCENTPAREN; }
186+"@(" { adjust(); return ATPAREN; }
187+
188+"," { adjust(); return COMMA; }
189+":" { adjust(); return COLON; }
190+"." { adjust(); return DOT; }
191+"+" { adjust(); return PLUS; }
192+"-" { adjust(); return MINUS; }
193+"*" { adjust(); return TIMES; }
194+"/" { adjust(); return DIVIDE; }
195+"%" { adjust(); return PERCENT; }
196+"#" { adjust(); return POUND; }
197+"$" { adjust(); return DOLLAR; }
198+
199+"::" { adjust(); return COLONCOLON; }
200+"==" { adjust(); return EQ; }
201+"!=" { adjust(); return NEQ; }
202+"<" { adjust(); return LT; }
203+">" { adjust(); return GT; }
204+"<=" { adjust(); return LE; }
205+">=" { adjust(); return GE; }
206+"&&" { adjust(); return AND; }
207+"||" { adjust(); return OR; }
208+"&" { adjust(); return S_AND; }
209+"|" { adjust(); return S_OR; }
210+"^" { adjust(); return S_XOR; }
211+">>" { adjust(); return SHIFT_RIGHT; }
212+"<<" { adjust(); return SHIFT_LEFT; }
213+"=" { adjust(); return ASSIGN; }
214+"(" { adjust(); return LPAREN; }
215+")" { adjust(); return RPAREN; }
216+"[" { adjust(); return LBRACK; }
217+"]" { adjust(); return RBRACK; }
218+"{" { adjust(); return LBRACE; }
219+"}" { adjust(); return RBRACE; }
220+";" { adjust(); return SEMICOLON; }
221+"?" { adjust(); return QUESTION; }
222+"!" { adjust(); return EXCLAMATION; }
223+"~" { adjust(); return TILDA; }
224+for { adjust(); return FOR; }
225+while { adjust(); return WHILE; }
226+until { adjust(); return UNTIL; }
227+repeat { adjust(); return LOOP; }
228+continue { adjust(); return CONTINUE; }
229+break { adjust(); return BREAK; }
230+if { adjust(); return IF; }
231+else { adjust(); return ELSE; }
232+do { adjust(); return DO; }
233+"<<<" { adjust(); return L_HACK; }
234+">>>" { adjust(); return R_HACK; }
235+
236+return { adjust(); return RETURN; }
237+
238+function { adjust(); return FUNCTION; }
239+fun { adjust(); return FUNCTION; }
240+new { adjust(); return NEW; }
241+class { adjust(); return CLASS; }
242+interface { adjust(); return INTERFACE; }
243+extends { adjust(); return EXTENDS; }
244+implements { adjust(); return IMPLEMENTS; }
245+public { adjust(); return PUBLIC; }
246+protected { adjust(); return PROTECTED; }
247+private { adjust(); return PRIVATE; }
248+static { adjust(); return STATIC; }
249+pure { adjust(); return ABSTRACT; }
250+const { adjust(); return CONST; }
251+spork { adjust(); return SPORK; }
252+typeof { adjust(); return TYPEOF; }
253+
254+"=>" { adjust(); return CHUCK; }
255+"=<" { adjust(); return UNCHUCK; }
256+"!=>" { adjust(); return UNCHUCK; }
257+"=^" { adjust(); return UPCHUCK; }
258+"@=>" { adjust(); return AT_CHUCK; }
259+"+=>" { adjust(); return PLUS_CHUCK; }
260+"-=>" { adjust(); return MINUS_CHUCK; }
261+"*=>" { adjust(); return TIMES_CHUCK; }
262+"/=>" { adjust(); return DIVIDE_CHUCK; }
263+"&=>" { adjust(); return S_AND_CHUCK; }
264+"|=>" { adjust(); return S_OR_CHUCK; }
265+"^=>" { adjust(); return S_XOR_CHUCK; }
266+">>=>" { adjust(); return SHIFT_RIGHT_CHUCK; }
267+"<<=>" { adjust(); return SHIFT_LEFT_CHUCK; }
268+"%=>" { adjust(); return PERCENT_CHUCK; }
269+"@" { adjust(); return AT_SYM; }
270+"@@" { adjust(); return ATAT_SYM; }
271+"->" { adjust(); return ARROW_RIGHT; }
272+"<-" { adjust(); return ARROW_LEFT; }
273+
274+0[xX][0-9a-fA-F]+{IS}? { adjust(); yylval.ival=htol(yytext); return NUM; }
275+0[cC][0-7]+{IS}? { adjust(); yylval.ival=atoi(yytext); return NUM; }
276+[0-9]+{IS}? { adjust(); yylval.ival=atoi(yytext); return NUM; }
277+([0-9]+"."[0-9]*)|([0-9]*"."[0-9]+) { adjust(); yylval.fval=atof(yytext); return FLOAT; }
278+[A-Za-z_][A-Za-z0-9_]* { adjust(); yylval.sval=alloc_str(yytext); return ID; }
279+\"(\\.|[^\\"])*\" { adjust(); yylval.sval=alloc_str(strip_lit(yytext)); return STRING_LIT; }
280+`(\\.|[^\\`])*` { adjust(); yylval.sval=alloc_str(strip_lit(yytext)); return STRING_LIT; }
281+'(\\.|[^\\'])' { adjust(); yylval.sval=alloc_str(strip_lit(yytext)); return CHAR_LIT; }
282+
283+. { adjust(); EM_error( EM_tokPos, "illegal token" ); }
284+
285+%%
286+
287+/*
288+// comment
289+int comment()
290+{
291+ char c;
292+
293+ while ((c = yyinput()) != '\n' && c != '\r' && c != 0 && c != EOF );
294+
295+ if (c != 0) {
296+ adjust();
297+ if (c == '\n') EM_newline();
298+ }
299+
300+ return 0;
301+}
302+
303+// block comment
304+int block_comment()
305+{
306+ char c, c1;
307+
308+loop:
309+ while ((c = yyinput()) != '*' && c != 0 && c != EOF )
310+ if( c == '\n' ) EM_newline();
311+
312+ if( c == EOF )
313+ {
314+ adjust();
315+ return 1;
316+ }
317+
318+ if( (c1 = yyinput()) != '/' && c != 0 )
319+ {
320+ unput(c1);
321+ goto loop;
322+ }
323+
324+ if( c != 0 ) adjust();
325+
326+ return 0;
327+}
328+*/
core/chuck.y+600−0
@@ -0,0 +1,600 @@
1+%{
2+
3+/*----------------------------------------------------------------------------
4+ ChucK Concurrent, On-the-fly Audio Programming Language
5+ Compiler and Virtual Machine
6+
7+ Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
8+ http://chuck.cs.princeton.edu/
9+ http://soundlab.cs.princeton.edu/
10+
11+ This program is free software; you can redistribute it and/or modify
12+ it under the terms of the GNU General Public License as published by
13+ the Free Software Foundation; either version 2 of the License, or
14+ (at your option) any later version.
15+
16+ This program is distributed in the hope that it will be useful,
17+ but WITHOUT ANY WARRANTY; without even the implied warranty of
18+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19+ GNU General Public License for more details.
20+
21+ You should have received a copy of the GNU General Public License
22+ along with this program; if not, write to the Free Software
23+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
24+ U.S.A.
25+-----------------------------------------------------------------------------*/
26+
27+//-----------------------------------------------------------------------------
28+// file: chuck.tab.c
29+// desc: chuck parser
30+//
31+// author: Ge Wang (gewang@cs.princeton.edu) - generated by yacc
32+// Perry R. Cook (prc@cs.princeton.edu)
33+//
34+// based in part on the ansi C grammar by Jeff Lee, maintained by Jutta Degener
35+//
36+// date: Summer 2002
37+//-----------------------------------------------------------------------------
38+#include <stdio.h>
39+#include <string.h>
40+#include <stdlib.h>
41+#include "chuck_utils.h"
42+#include "chuck_errmsg.h"
43+#include "chuck_absyn.h"
44+
45+// function
46+int yylex( void );
47+
48+void yyerror( char *s )
49+{
50+ EM_error( EM_tokPos, "%s", s );
51+}
52+
53+a_Program g_program = NULL;
54+
55+%}
56+
57+
58+%union
59+{
60+ int pos;
61+ int ival;
62+ double fval;
63+ c_str sval;
64+
65+ a_Program program;
66+ a_Section program_section;
67+ a_Stmt_List stmt_list;
68+ a_Class_Def class_def;
69+ a_Class_Ext class_ext;
70+ a_Class_Body class_body;
71+ a_Stmt stmt;
72+ a_Exp exp;
73+ a_Func_Def func_def;
74+ a_Var_Decl_List var_decl_list;
75+ a_Var_Decl var_decl;
76+ a_Type_Decl type_decl;
77+ a_Arg_List arg_list;
78+ a_Id_List id_list;
79+ a_Array_Sub array_sub;
80+ a_Complex complex_exp;
81+ a_Polar polar_exp;
82+ a_Vec vec_exp; // ge: added 1.3.5.3
83+};
84+
85+// expect shift/reduce conflicts
86+// 1.3.3.0: changed to 38 for char literal - spencer
87+// 1.3.5.3: changed to 39 for vec literal
88+%expect 39
89+
90+%token <sval> ID STRING_LIT CHAR_LIT
91+%token <ival> NUM
92+%token <fval> FLOAT
93+
94+%token
95+ POUND COMMA COLON SEMICOLON LPAREN RPAREN
96+ LBRACK RBRACK LBRACE RBRACE DOT
97+ PLUS MINUS TIMES DIVIDE PERCENT
98+ EQ NEQ LT LE GT GE AND OR ASSIGN
99+ IF THEN ELSE WHILE FOR DO LOOP
100+ BREAK CONTINUE NULL_TOK FUNCTION RETURN
101+ QUESTION EXCLAMATION S_OR S_AND S_XOR
102+ PLUSPLUS MINUSMINUS DOLLAR POUNDPAREN PERCENTPAREN ATPAREN
103+ SIMULT PATTERN CODE TRANSPORT HOST
104+ TIME WHENEVER NEXT UNTIL EVERY BEFORE
105+ AFTER AT AT_SYM ATAT_SYM NEW SIZEOF TYPEOF
106+ SAME PLUS_CHUCK MINUS_CHUCK TIMES_CHUCK
107+ DIVIDE_CHUCK S_AND_CHUCK S_OR_CHUCK
108+ S_XOR_CHUCK SHIFT_RIGHT_CHUCK
109+ SHIFT_LEFT_CHUCK PERCENT_CHUCK
110+ SHIFT_RIGHT SHIFT_LEFT TILDA CHUCK
111+ COLONCOLON S_CHUCK AT_CHUCK LEFT_S_CHUCK
112+ UNCHUCK UPCHUCK CLASS INTERFACE EXTENDS IMPLEMENTS
113+ PUBLIC PROTECTED PRIVATE STATIC ABSTRACT CONST
114+ SPORK ARROW_RIGHT ARROW_LEFT L_HACK R_HACK
115+
116+
117+%type <program> program
118+%type <program_section> program_section
119+%type <stmt> code_segment
120+%type <func_def> function_definition
121+%type <class_def> class_definition
122+%type <class_body> class_body
123+%type <class_body> class_body2
124+%type <class_ext> class_ext
125+%type <ival> class_decl
126+%type <class_ext> iface_ext
127+%type <program_section> class_section
128+%type <stmt_list> statement_list
129+%type <stmt> statement
130+//%type <stmt_label> label_statement
131+%type <stmt> loop_statement
132+%type <stmt> selection_statement
133+%type <stmt> jump_statement
134+%type <stmt> expression_statement
135+%type <exp> expression
136+%type <exp> chuck_expression
137+%type <exp> arrow_expression
138+%type <exp> conditional_expression
139+%type <exp> logical_or_expression
140+%type <exp> logical_and_expression
141+%type <exp> inclusive_or_expression
142+%type <exp> exclusive_or_expression
143+%type <exp> and_expression
144+%type <exp> equality_expression
145+%type <exp> relational_expression
146+%type <exp> shift_expression
147+%type <exp> additive_expression
148+%type <exp> multiplicative_expression
149+%type <exp> tilda_expression
150+%type <exp> cast_expression
151+%type <exp> unary_expression
152+%type <exp> dur_expression
153+%type <exp> postfix_expression
154+%type <exp> primary_expression
155+%type <exp> decl_expression
156+%type <ival> unary_operator
157+%type <ival> chuck_operator
158+%type <ival> arrow_operator
159+%type <var_decl_list> var_decl_list
160+%type <var_decl> var_decl
161+%type <type_decl> type_decl_a
162+%type <type_decl> type_decl_b
163+%type <type_decl> type_decl
164+%type <type_decl> type_decl2
165+%type <ival> function_decl
166+%type <ival> static_decl
167+%type <arg_list> arg_list
168+%type <id_list> id_list
169+%type <id_list> id_dot
170+%type <array_sub> array_exp
171+%type <array_sub> array_empty
172+%type <complex_exp> complex_exp
173+%type <polar_exp> polar_exp
174+%type <vec_exp> vec_exp // ge: added 1.3.5.3
175+
176+%start program
177+
178+%%
179+
180+program
181+ : program_section { $$ = g_program = new_program( $1, EM_lineNum ); }
182+ | program_section program { $$ = g_program = prepend_program( $1, $2, EM_lineNum ); }
183+ ;
184+
185+program_section
186+ : statement_list { $$ = new_section_stmt( $1, EM_lineNum ); }
187+ | function_definition { $$ = new_section_func_def( $1, EM_lineNum ); }
188+ | class_definition { $$ = new_section_class_def( $1, EM_lineNum ); }
189+ ;
190+
191+class_definition
192+ : class_decl CLASS id_list LBRACE class_body RBRACE
193+ { $$ = new_class_def( $1, $3, NULL, $5, EM_lineNum ); }
194+ | class_decl CLASS id_list class_ext LBRACE class_body RBRACE
195+ { $$ = new_class_def( $1, $3, $4, $6, EM_lineNum ); }
196+ | class_decl INTERFACE id_list LBRACE class_body RBRACE
197+ { $$ = new_iface_def( $1, $3, NULL, $5, EM_lineNum ); }
198+ | class_decl INTERFACE id_list iface_ext LBRACE class_body RBRACE
199+ { $$ = new_iface_def( $1, $3, $4, $6, EM_lineNum ); }
200+ ;
201+
202+class_ext
203+ : IMPLEMENTS id_list { $$ = new_class_ext( NULL, $2, EM_lineNum ); }
204+ | IMPLEMENTS id_list EXTENDS id_dot { $$ = new_class_ext( $4, $2, EM_lineNum ); }
205+ | EXTENDS id_dot { $$ = new_class_ext( $2, NULL, EM_lineNum ); }
206+ | EXTENDS id_dot IMPLEMENTS id_list { $$ = new_class_ext( $2, $4, EM_lineNum ); }
207+ ;
208+
209+class_body
210+ : class_body2 { $$ = $1; }
211+ | { $$ = NULL; }
212+ ;
213+
214+class_body2
215+ : class_section { $$ = new_class_body( $1, EM_lineNum ); }
216+ | class_section class_body2 { $$ = prepend_class_body( $1, $2, EM_lineNum ); }
217+ ;
218+
219+
220+class_section
221+ : statement_list { $$ = new_section_stmt( $1, EM_lineNum ); }
222+ | function_definition { $$ = new_section_func_def( $1, EM_lineNum ); }
223+ | class_definition { $$ = new_section_class_def( $1, EM_lineNum ); }
224+ ;
225+
226+iface_ext
227+ : EXTENDS id_list { $$ = new_class_ext( NULL, $2, EM_lineNum ); }
228+ ;
229+
230+id_list
231+ : ID { $$ = new_id_list( $1, EM_lineNum ); }
232+ | ID COMMA id_list { $$ = prepend_id_list( $1, $3, EM_lineNum ); }
233+ ;
234+
235+id_dot
236+ : ID { $$ = new_id_list( $1, EM_lineNum ); }
237+ | ID DOT id_dot { $$ = prepend_id_list( $1, $3, EM_lineNum ); }
238+ ;
239+
240+function_definition
241+ : function_decl static_decl type_decl2 ID LPAREN arg_list RPAREN code_segment
242+ { $$ = new_func_def( $1, $2, $3, $4, $6, $8, EM_lineNum ); }
243+ | function_decl static_decl type_decl2 ID LPAREN RPAREN code_segment
244+ { $$ = new_func_def( $1, $2, $3, $4, NULL, $7, EM_lineNum ); }
245+ | function_decl static_decl type_decl2 ID LPAREN arg_list RPAREN SEMICOLON
246+ { $$ = new_func_def( $1, $2, $3, $4, $6, NULL, EM_lineNum ); }
247+ | function_decl static_decl type_decl2 ID LPAREN RPAREN SEMICOLON
248+ { $$ = new_func_def( $1, $2, $3, $4, NULL, NULL, EM_lineNum ); }
249+ ;
250+
251+class_decl
252+ : PUBLIC { $$ = ae_key_public; }
253+ | PRIVATE { $$ = ae_key_private; }
254+ | { $$ = ae_key_private; }
255+ ;
256+
257+function_decl
258+ : FUNCTION { $$ = ae_key_func; }
259+ | PUBLIC { $$ = ae_key_public; }
260+ | PROTECTED { $$ = ae_key_protected; }
261+ | PRIVATE { $$ = ae_key_private; }
262+ ;
263+
264+static_decl
265+ : STATIC { $$ = ae_key_static; }
266+ | ABSTRACT { $$ = ae_key_abstract; }
267+ | { $$ = ae_key_instance; }
268+ ;
269+
270+type_decl_a
271+ : ID { $$ = new_type_decl( new_id_list( $1, EM_lineNum ), 0, EM_lineNum ); }
272+ | ID AT_SYM { $$ = new_type_decl( new_id_list( $1, EM_lineNum ), 1, EM_lineNum ); }
273+ ;
274+
275+type_decl_b
276+ : LT id_dot GT { $$ = new_type_decl( $2, 0, EM_lineNum ); }
277+ | LT id_dot GT AT_SYM { $$ = new_type_decl( $2, 1, EM_lineNum ); }
278+ ;
279+
280+//type_decl_c
281+// : LPAREN id_dot RPAREN { $$ = new_type_decl( $3, 0, EM_lineNum ); }
282+// // | LPAREN id_dot RPAREN AT_SYM { $$ = new_type_decl( $1, 1, EM_lineNum ); }
283+// ;
284+
285+type_decl
286+ : type_decl_a { $$ = $1; }
287+ | type_decl_b { $$ = $1; }
288+ // | type_decl_c { $$ = $1; }
289+ ;
290+
291+type_decl2
292+ : type_decl { $$ = $1; }
293+ | type_decl array_empty { $$ = add_type_decl_array( $1, $2, EM_lineNum ); }
294+ ;
295+
296+arg_list
297+ : type_decl var_decl { $$ = new_arg_list( $1, $2, EM_lineNum ); }
298+ | type_decl var_decl COMMA arg_list { $$ = prepend_arg_list( $1, $2, $4, EM_lineNum ); }
299+ ;
300+
301+statement_list
302+ : statement { $$ = new_stmt_list( $1, EM_lineNum ); }
303+ | statement statement_list { $$ = prepend_stmt_list( $1, $2, EM_lineNum ); }
304+ ;
305+
306+statement
307+ : expression_statement { $$ = $1; }
308+ | loop_statement { $$ = $1; }
309+ | selection_statement { $$ = $1; }
310+ | jump_statement { $$ = $1; }
311+ // | label_statement { }
312+ | code_segment { $$ = $1; }
313+ ;
314+
315+jump_statement
316+ : RETURN SEMICOLON { $$ = new_stmt_from_return( NULL, EM_lineNum ); }
317+ | RETURN expression SEMICOLON { $$ = new_stmt_from_return( $2, EM_lineNum ); }
318+ | BREAK SEMICOLON { $$ = new_stmt_from_break( EM_lineNum ); }
319+ | CONTINUE SEMICOLON { $$ = new_stmt_from_continue( EM_lineNum ); }
320+ ;
321+
322+selection_statement
323+ : IF LPAREN expression RPAREN statement
324+ { $$ = new_stmt_from_if( $3, $5, NULL, EM_lineNum ); }
325+ | IF LPAREN expression RPAREN statement ELSE statement
326+ { $$ = new_stmt_from_if( $3, $5, $7, EM_lineNum ); }
327+ ;
328+
329+loop_statement
330+ : WHILE LPAREN expression RPAREN statement
331+ { $$ = new_stmt_from_while( $3, $5, EM_lineNum ); }
332+ | DO statement WHILE LPAREN expression RPAREN SEMICOLON
333+ { $$ = new_stmt_from_do_while( $5, $2, EM_lineNum ); }
334+ | FOR LPAREN expression_statement expression_statement RPAREN statement
335+ { $$ = new_stmt_from_for( $3, $4, NULL, $6, EM_lineNum ); }
336+ | FOR LPAREN expression_statement expression_statement expression RPAREN statement
337+ { $$ = new_stmt_from_for( $3, $4, $5, $7, EM_lineNum ); }
338+ | UNTIL LPAREN expression RPAREN statement
339+ { $$ = new_stmt_from_until( $3, $5, EM_lineNum ); }
340+ | DO statement UNTIL LPAREN expression RPAREN SEMICOLON
341+ { $$ = new_stmt_from_do_until( $5, $2, EM_lineNum ); }
342+ | LOOP LPAREN expression RPAREN statement
343+ { $$ = new_stmt_from_loop( $3, $5, EM_lineNum ); }
344+ ;
345+
346+code_segment
347+ : LBRACE RBRACE { $$ = new_stmt_from_code( NULL, EM_lineNum ); }
348+ | LBRACE statement_list RBRACE { $$ = new_stmt_from_code( $2, EM_lineNum ); }
349+ ;
350+
351+expression_statement
352+ : SEMICOLON { $$ = NULL; }
353+ | expression SEMICOLON { $$ = new_stmt_from_expression( $1, EM_lineNum ); }
354+ ;
355+
356+expression
357+ : chuck_expression { $$ = $1; }
358+ | chuck_expression COMMA expression { $$ = prepend_expression( $1, $3, EM_lineNum ); }
359+ ;
360+
361+chuck_expression
362+ : arrow_expression { $$ = $1; }
363+ | chuck_expression chuck_operator arrow_expression
364+ { $$ = new_exp_from_binary( $1, $2, $3, EM_lineNum ); }
365+ ;
366+
367+arrow_expression
368+ : decl_expression { $$ = $1; }
369+ | arrow_expression arrow_operator decl_expression
370+ { $$ = new_exp_from_binary( $1, $2, $3, EM_lineNum ); }
371+ ;
372+
373+array_exp
374+ : LBRACK expression RBRACK { $$ = new_array_sub( $2, EM_lineNum ); }
375+ | LBRACK expression RBRACK array_exp
376+ { $$ = prepend_array_sub( $4, $2, EM_lineNum ); }
377+ ;
378+
379+array_empty
380+ : LBRACK RBRACK { $$ = new_array_sub( NULL, EM_lineNum ); }
381+ | array_empty LBRACK RBRACK { $$ = prepend_array_sub( $1, NULL, EM_lineNum ); }
382+ ;
383+
384+decl_expression
385+ : conditional_expression { $$ = $1; }
386+ | type_decl var_decl_list { $$ = new_exp_decl( $1, $2, 0, EM_lineNum ); }
387+ | STATIC type_decl var_decl_list { $$ = new_exp_decl( $2, $3, 1, EM_lineNum ); }
388+ | SAME var_decl_list { $$ = new_exp_decl( NULL, $2, 0, EM_lineNum ); }
389+ | STATIC SAME var_decl_list { $$ = new_exp_decl( NULL, $3, 1, EM_lineNum ); }
390+ ;
391+
392+var_decl_list
393+ : var_decl { $$ = new_var_decl_list( $1, EM_lineNum ); }
394+ | var_decl COMMA var_decl_list { $$ = prepend_var_decl_list( $1, $3, EM_lineNum ); }
395+ ;
396+
397+var_decl
398+ : ID { $$ = new_var_decl( $1, NULL, EM_lineNum ); }
399+ | ID array_exp { $$ = new_var_decl( $1, $2, EM_lineNum ); }
400+ | ID array_empty { $$ = new_var_decl( $1, $2, EM_lineNum ); }
401+ ;
402+
403+complex_exp
404+ : POUNDPAREN expression RPAREN
405+ { $$ = new_complex( $2, EM_lineNum ); }
406+ ;
407+
408+polar_exp
409+ : PERCENTPAREN expression RPAREN
410+ { $$ = new_polar( $2, EM_lineNum ); }
411+ ;
412+
413+vec_exp // ge: added 1.3.5.3
414+ : ATPAREN expression RPAREN
415+ { $$ = new_vec( $2, EM_lineNum ); }
416+ ;
417+
418+chuck_operator
419+ : CHUCK { $$ = ae_op_chuck; }
420+ | AT_CHUCK { $$ = ae_op_at_chuck; }
421+ | PLUS_CHUCK { $$ = ae_op_plus_chuck; }
422+ | MINUS_CHUCK { $$ = ae_op_minus_chuck; }
423+ | TIMES_CHUCK { $$ = ae_op_times_chuck; }
424+ | DIVIDE_CHUCK { $$ = ae_op_divide_chuck; }
425+ | SHIFT_RIGHT_CHUCK { $$ = ae_op_shift_right_chuck; }
426+ | SHIFT_LEFT_CHUCK { $$ = ae_op_shift_left_chuck; }
427+ | PERCENT_CHUCK { $$ = ae_op_percent_chuck; }
428+ | UNCHUCK { $$ = ae_op_unchuck; }
429+ | UPCHUCK { $$ = ae_op_upchuck; }
430+ | S_AND_CHUCK { $$ = ae_op_s_and_chuck; }
431+ | S_OR_CHUCK { $$ = ae_op_s_or_chuck; }
432+ | S_XOR_CHUCK { $$ = ae_op_s_xor_chuck; }
433+ ;
434+
435+arrow_operator
436+ : ARROW_LEFT { $$ = ae_op_arrow_left; }
437+ | ARROW_RIGHT { $$ = ae_op_arrow_right; }
438+ ;
439+
440+conditional_expression
441+ : logical_or_expression { $$ = $1; }
442+ | logical_or_expression QUESTION expression COLON conditional_expression
443+ { $$ = new_exp_from_if( $1, $3, $5, EM_lineNum ); }
444+ ;
445+
446+logical_or_expression
447+ : logical_and_expression { $$ = $1; }
448+ | logical_or_expression OR logical_and_expression
449+ { $$ = new_exp_from_binary( $1, ae_op_or, $3, EM_lineNum ); }
450+ ;
451+
452+logical_and_expression
453+ : inclusive_or_expression { $$ = $1; }
454+ | logical_and_expression AND inclusive_or_expression
455+ { $$ = new_exp_from_binary( $1, ae_op_and, $3, EM_lineNum ); }
456+ ;
457+
458+inclusive_or_expression
459+ : exclusive_or_expression { $$ = $1; }
460+ | inclusive_or_expression S_OR exclusive_or_expression
461+ { $$ = new_exp_from_binary( $1, ae_op_s_or, $3, EM_lineNum ); }
462+ ;
463+
464+exclusive_or_expression
465+ : and_expression { $$ = $1; }
466+ | exclusive_or_expression S_XOR and_expression
467+ { $$ = new_exp_from_binary( $1, ae_op_s_xor, $3, EM_lineNum ); }
468+ ;
469+
470+and_expression
471+ : equality_expression { $$ = $1; }
472+ | and_expression S_AND equality_expression
473+ { $$ = new_exp_from_binary( $1, ae_op_s_and, $3, EM_lineNum ); }
474+ ;
475+
476+equality_expression
477+ : relational_expression { $$ = $1; }
478+ | equality_expression EQ relational_expression
479+ { $$ = new_exp_from_binary( $1, ae_op_eq, $3, EM_lineNum ); }
480+ | equality_expression NEQ relational_expression
481+ { $$ = new_exp_from_binary( $1, ae_op_neq, $3, EM_lineNum ); }
482+ ;
483+
484+relational_expression
485+ : shift_expression { $$ = $1; }
486+ | relational_expression LT shift_expression
487+ { $$ = new_exp_from_binary( $1, ae_op_lt, $3, EM_lineNum ); }
488+ | relational_expression GT shift_expression
489+ { $$ = new_exp_from_binary( $1, ae_op_gt, $3, EM_lineNum ); }
490+ | relational_expression LE shift_expression
491+ { $$ = new_exp_from_binary( $1, ae_op_le, $3, EM_lineNum ); }
492+ | relational_expression GE shift_expression
493+ { $$ = new_exp_from_binary( $1, ae_op_ge, $3, EM_lineNum ); }
494+ ;
495+
496+shift_expression
497+ : additive_expression { $$ = $1; }
498+ | shift_expression SHIFT_LEFT additive_expression
499+ { $$ = new_exp_from_binary( $1, ae_op_shift_left, $3, EM_lineNum ); }
500+ | shift_expression SHIFT_RIGHT additive_expression
501+ { $$ = new_exp_from_binary( $1, ae_op_shift_right, $3, EM_lineNum ); }
502+ ;
503+
504+additive_expression
505+ : multiplicative_expression { $$ = $1; }
506+ | additive_expression PLUS multiplicative_expression
507+ { $$ = new_exp_from_binary( $1, ae_op_plus, $3, EM_lineNum ); }
508+ | additive_expression MINUS multiplicative_expression
509+ { $$ = new_exp_from_binary( $1, ae_op_minus, $3, EM_lineNum ); }
510+ ;
511+
512+multiplicative_expression
513+ : tilda_expression { $$ = $1; }
514+ | multiplicative_expression TIMES tilda_expression
515+ { $$ = new_exp_from_binary( $1, ae_op_times, $3, EM_lineNum ); }
516+ | multiplicative_expression DIVIDE tilda_expression
517+ { $$ = new_exp_from_binary( $1, ae_op_divide, $3, EM_lineNum ); }
518+ | multiplicative_expression PERCENT tilda_expression
519+ { $$ = new_exp_from_binary( $1, ae_op_percent, $3, EM_lineNum ); }
520+ ;
521+
522+tilda_expression
523+ : cast_expression { $$ = $1; }
524+ | tilda_expression TILDA cast_expression
525+ { $$ = new_exp_from_binary( $1, ae_op_tilda, $3, EM_lineNum ); }
526+ ;
527+
528+cast_expression
529+ : unary_expression { $$ = $1; }
530+ | cast_expression DOLLAR type_decl
531+ { $$ = new_exp_from_cast( $3, $1, EM_lineNum ); }
532+ ;
533+
534+unary_expression
535+ : dur_expression { $$ = $1; }
536+ | PLUSPLUS unary_expression
537+ { $$ = new_exp_from_unary( ae_op_plusplus, $2, EM_lineNum ); }
538+ | MINUSMINUS unary_expression
539+ { $$ = new_exp_from_unary( ae_op_minusminus, $2, EM_lineNum ); }
540+ | unary_operator unary_expression
541+ { $$ = new_exp_from_unary( $1, $2, EM_lineNum ); }
542+ | TYPEOF unary_expression
543+ { $$ = new_exp_from_unary( ae_op_typeof, $2, EM_lineNum ); }
544+ | SIZEOF unary_expression
545+ { $$ = new_exp_from_unary( ae_op_sizeof, $2, EM_lineNum ); }
546+ | NEW type_decl
547+ { $$ = new_exp_from_unary2( ae_op_new, $2, NULL, EM_lineNum ); }
548+ | NEW type_decl array_exp
549+ { $$ = new_exp_from_unary2( ae_op_new, $2, $3, EM_lineNum ); }
550+// | SPORK TILDA code_segment
551+// { $$ = new_exp_from_unary3( ae_op_spork, $3, EM_lineNum ); }
552+ ;
553+
554+unary_operator
555+ : PLUS { $$ = ae_op_plus; }
556+ | MINUS { $$ = ae_op_minus; }
557+ | TILDA { $$ = ae_op_tilda; }
558+ | EXCLAMATION { $$ = ae_op_exclamation; }
559+ | TIMES { $$ = ae_op_times; }
560+ | SPORK TILDA { $$ = ae_op_spork; }
561+ // | S_AND { $$ = ae_op_s_and; }
562+ ;
563+
564+dur_expression
565+ : postfix_expression
566+ | dur_expression COLONCOLON postfix_expression
567+ { $$ = new_exp_from_dur( $1, $3, EM_lineNum ); }
568+ ;
569+
570+postfix_expression
571+ : primary_expression { $$ = $1; }
572+ | postfix_expression array_exp
573+ { $$ = new_exp_from_array( $1, $2, EM_lineNum ); }
574+ | postfix_expression LPAREN RPAREN
575+ { $$ = new_exp_from_func_call( $1, NULL, EM_lineNum ); }
576+ | postfix_expression LPAREN expression RPAREN
577+ { $$ = new_exp_from_func_call( $1, $3, EM_lineNum ); }
578+ | postfix_expression DOT ID
579+ { $$ = new_exp_from_member_dot( $1, $3, EM_lineNum ); }
580+ | postfix_expression PLUSPLUS
581+ { $$ = new_exp_from_postfix( $1, ae_op_plusplus, EM_lineNum ); }
582+ | postfix_expression MINUSMINUS
583+ { $$ = new_exp_from_postfix( $1, ae_op_minusminus, EM_lineNum ); }
584+ ;
585+
586+// 1.3.3.0: added CHAR_LIT - spencer
587+primary_expression
588+ : ID { $$ = new_exp_from_id( $1, EM_lineNum ); }
589+ | NUM { $$ = new_exp_from_int( $1, EM_lineNum ); }
590+ | FLOAT { $$ = new_exp_from_float( $1, EM_lineNum ); }
591+ | STRING_LIT { $$ = new_exp_from_str( $1, EM_lineNum ); }
592+ | CHAR_LIT { $$ = new_exp_from_char( $1, EM_lineNum ); }
593+ | array_exp { $$ = new_exp_from_array_lit( $1, EM_lineNum ); }
594+ | complex_exp { $$ = new_exp_from_complex( $1, EM_lineNum ); }
595+ | polar_exp { $$ = new_exp_from_polar( $1, EM_lineNum ); }
596+ | vec_exp { $$ = new_exp_from_vec( $1, EM_lineNum ); }
597+ | L_HACK expression R_HACK { $$ = new_exp_from_hack( $2, EM_lineNum ); }
598+ | LPAREN expression RPAREN { $$ = $2; }
599+ | LPAREN RPAREN { $$ = new_exp_from_nil( EM_lineNum ); }
600+ ;
core/chuck_absyn.cpp+972−0
@@ -0,0 +1,972 @@
1+/*----------------------------------------------------------------------------
2+ ChucK Concurrent, On-the-fly Audio Programming Language
3+ Compiler and Virtual Machine
4+
5+ Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6+ http://chuck.stanford.edu/
7+ http://chuck.cs.princeton.edu/
8+
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.
13+
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.
18+
19+ You should have received a copy of the GNU General Public License
20+ along with this program; if not, write to the Free Software
21+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22+ U.S.A.
23+-----------------------------------------------------------------------------*/
24+
25+//-----------------------------------------------------------------------------
26+// file: chuck_absyn.cpp
27+// desc: chuck abstract syntax
28+//
29+// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
30+// date: Autumn 2002
31+//-----------------------------------------------------------------------------
32+#include <stdlib.h>
33+#include <stdio.h>
34+#include "chuck_absyn.h"
35+#include "chuck_utils.h"
36+
37+
38+a_Program new_program( a_Section section, int pos )
39+{
40+ a_Program a = (a_Program)checked_malloc( sizeof( struct a_Program_ ) );
41+ a->section = section;
42+ a->linepos = pos;
43+
44+ return a;
45+}
46+
47+a_Program prepend_program( a_Section section, a_Program program, int pos )
48+{
49+ a_Program a = new_program( section, pos );
50+ a->next = program;
51+ a->linepos = pos;
52+
53+ return a;
54+}
55+
56+a_Section new_section_stmt( a_Stmt_List list, int pos )
57+{
58+ a_Section a = (a_Section)checked_malloc( sizeof( struct a_Section_ ) );
59+ a->s_type = ae_section_stmt;
60+ a->stmt_list = list;
61+ a->linepos = pos;
62+
63+ return a;
64+}
65+
66+a_Section new_section_func_def( a_Func_Def func_def, int pos )
67+{
68+ a_Section a = (a_Section)checked_malloc( sizeof( struct a_Section_) );
69+ a->s_type = ae_section_func;
70+ a->func_def = func_def;
71+ a->linepos = pos;
72+
73+ return a;
74+}
75+
76+a_Section new_section_class_def( a_Class_Def class_def, int pos )
77+{
78+ a_Section a = (a_Section)checked_malloc( sizeof( struct a_Section_) );
79+ a->s_type = ae_section_class;
80+ a->class_def = class_def;
81+ a->linepos = pos;
82+
83+ return a;
84+}
85+
86+a_Stmt_List new_stmt_list( a_Stmt stmt, int pos )
87+{
88+ a_Stmt_List a = (a_Stmt_List)checked_malloc( sizeof( struct a_Stmt_List_ ) );
89+ a->stmt = stmt;
90+ a->next = NULL;
91+ a->linepos = pos;
92+
93+ return a;
94+}
95+
96+a_Stmt_List prepend_stmt_list( a_Stmt stmt, a_Stmt_List stmt_list, int pos )
97+{
98+ a_Stmt_List a = new_stmt_list( stmt, pos );
99+ a->next = stmt_list;
100+ a->linepos = pos;
101+
102+ return a;
103+}
104+
105+a_Stmt new_stmt_from_expression( a_Exp exp, int pos )
106+{
107+ a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) );
108+ a->s_type = ae_stmt_exp;
109+ a->stmt_exp = exp;
110+ a->linepos = pos;
111+
112+ return a;
113+}
114+
115+a_Stmt new_stmt_from_code( a_Stmt_List stmt_list, int pos )
116+{
117+ a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) );
118+ a->s_type = ae_stmt_code;
119+ a->stmt_code.stmt_list = stmt_list;
120+ a->linepos = pos;
121+ a->stmt_code.linepos = pos;
122+ a->stmt_code.self = a;
123+
124+ return a;
125+}
126+
127+a_Stmt new_stmt_from_if( a_Exp cond, a_Stmt if_body, a_Stmt else_body, int pos )
128+{
129+ a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) );
130+ a->s_type = ae_stmt_if;
131+ a->stmt_if.cond = cond;
132+ a->stmt_if.if_body = if_body;
133+ a->stmt_if.else_body = else_body;
134+ a->linepos = pos;
135+ a->stmt_if.linepos = pos;
136+ a->stmt_if.self = a;
137+
138+ return a;
139+}
140+
141+a_Stmt new_stmt_from_while( a_Exp cond, a_Stmt body, int pos )
142+{
143+ a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) );
144+ a->s_type = ae_stmt_while;
145+ a->stmt_while.is_do = 0;
146+ a->stmt_while.cond = cond;
147+ a->stmt_while.body = body;
148+ a->linepos = pos;
149+ a->stmt_while.linepos = pos;
150+ a->stmt_while.self = a;
151+
152+ return a;
153+}
154+
155+a_Stmt new_stmt_from_do_while( a_Exp cond, a_Stmt body, int pos )
156+{
157+ a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) );
158+ a->s_type = ae_stmt_while;
159+ a->stmt_while.is_do = 1;
160+ a->stmt_while.cond = cond;
161+ a->stmt_while.body = body;
162+ a->linepos = pos;
163+ a->stmt_while.linepos = pos;
164+ a->stmt_while.self = a;
165+
166+ return a;
167+}
168+
169+a_Stmt new_stmt_from_until( a_Exp cond, a_Stmt body, int pos )
170+{
171+ a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) );
172+ a->s_type = ae_stmt_until;
173+ a->stmt_until.is_do = 0;
174+ a->stmt_until.cond = cond;
175+ a->stmt_until.body = body;
176+ a->linepos = pos;
177+ a->stmt_until.linepos = pos;
178+ a->stmt_until.self = a;
179+
180+ return a;
181+}
182+
183+a_Stmt new_stmt_from_do_until( a_Exp cond, a_Stmt body, int pos )
184+{
185+ a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) );
186+ a->s_type = ae_stmt_until;
187+ a->stmt_until.is_do = 1;
188+ a->stmt_until.cond = cond;
189+ a->stmt_until.body = body;
190+ a->linepos = pos;
191+ a->stmt_until.linepos = pos;
192+ a->stmt_until.self = a;
193+
194+ return a;
195+}
196+
197+a_Stmt new_stmt_from_for( a_Stmt c1, a_Stmt c2, a_Exp c3, a_Stmt body, int pos )
198+{
199+ a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) );
200+ a->s_type = ae_stmt_for;
201+ a->stmt_for.c1 = c1;
202+ a->stmt_for.c2 = c2;
203+ a->stmt_for.c3 = c3;
204+ a->stmt_for.body = body;
205+ a->linepos = pos;
206+ a->stmt_for.linepos = pos;
207+ a->stmt_for.self = a;
208+
209+ return a;
210+}
211+
212+a_Stmt new_stmt_from_loop( a_Exp cond, a_Stmt body, int pos )
213+{
214+ a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) );
215+ a->s_type = ae_stmt_loop;
216+ a->stmt_loop.cond = cond;
217+ a->stmt_loop.body = body;
218+ a->linepos = pos;
219+ a->stmt_loop.linepos = pos;
220+ a->stmt_loop.self = a;
221+
222+ return a;
223+}
224+
225+a_Stmt new_stmt_from_switch( a_Exp val, int pos )
226+{
227+ a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) );
228+ a->s_type = ae_stmt_switch;
229+ a->stmt_switch.val = val;
230+ a->linepos = pos;
231+ a->stmt_switch.linepos = pos;
232+ a->stmt_switch.self = a;
233+
234+ return a;
235+}
236+
237+a_Stmt new_stmt_from_break( int pos )
238+{
239+ a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) );
240+ a->s_type = ae_stmt_break;
241+ a->linepos = pos;
242+ a->stmt_break.linepos = pos;
243+ a->stmt_break.self = a;
244+
245+ return a;
246+}
247+
248+a_Stmt new_stmt_from_continue( int pos )
249+{
250+ a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) );
251+ a->s_type = ae_stmt_continue;
252+ a->linepos = pos;
253+ a->stmt_continue.linepos = pos;
254+ a->stmt_continue.self = a;
255+
256+ return a;
257+}
258+
259+a_Stmt new_stmt_from_return( a_Exp exp, int pos )
260+{
261+ a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) );
262+ a->s_type = ae_stmt_return;
263+ a->stmt_return.val = exp;
264+ a->linepos = pos;
265+ a->stmt_return.linepos = pos;
266+ a->stmt_return.self = a;
267+
268+ return a;
269+}
270+
271+a_Stmt new_stmt_from_label( c_str xid, int pos )
272+{
273+ a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) );
274+ a->s_type = ae_stmt_gotolabel;
275+ a->stmt_gotolabel.name = insert_symbol( xid );
276+ a->linepos = pos;
277+ a->stmt_gotolabel.linepos = pos;
278+ a->stmt_gotolabel.self = a;
279+
280+ return a;
281+}
282+
283+a_Stmt new_stmt_from_case( a_Exp exp, int pos )
284+{
285+ a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) );
286+ a->s_type = ae_stmt_case;
287+ a->stmt_case.exp = exp;
288+ a->linepos = pos;
289+ a->stmt_case.linepos = pos;
290+ a->stmt_case.self = a;
291+
292+ return a;
293+}
294+
295+a_Exp prepend_expression( a_Exp exp, a_Exp list, int pos )
296+{
297+ exp->next = list;
298+ return exp;
299+}
300+
301+a_Exp new_exp_from_binary( a_Exp lhs, ae_Operator oper, a_Exp rhs, int pos )
302+{
303+ a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
304+ a->s_type = ae_exp_binary;
305+ a->s_meta = ae_meta_value;
306+ a->binary.lhs = lhs;
307+ a->binary.op = oper;
308+ a->binary.rhs = rhs;
309+ a->linepos = pos;
310+ a->binary.linepos = pos;
311+ a->binary.self = a;
312+
313+ return a;
314+}
315+
316+a_Exp new_exp_from_unary( ae_Operator oper, a_Exp exp, int pos )
317+{
318+ a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
319+ a->s_type = ae_exp_unary;
320+ a->s_meta = exp->s_meta;
321+ a->unary.op = oper;
322+ a->unary.exp = exp;
323+ a->linepos = pos;
324+ a->unary.linepos = pos;
325+ a->unary.self = a;
326+
327+ return a;
328+}
329+
330+a_Exp new_exp_from_unary2( ae_Operator oper, a_Type_Decl type,
331+ a_Array_Sub array, int pos )
332+{
333+ a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
334+ a->s_type = ae_exp_unary;
335+ a->s_meta = ae_meta_value;
336+ a->unary.op = oper;
337+ a->unary.type = type;
338+ a->unary.array = array;
339+ a->linepos = pos;
340+ a->unary.linepos = pos;
341+ a->unary.self = a;
342+
343+ return a;
344+}
345+
346+a_Exp new_exp_from_unary3( ae_Operator oper, a_Stmt code, int pos )
347+{
348+ a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
349+ a->s_type = ae_exp_unary;
350+ a->s_meta = ae_meta_value;
351+ a->unary.op = oper;
352+ a->unary.code = code;
353+ a->linepos = pos;
354+ a->unary.linepos = pos;
355+ a->unary.self = a;
356+
357+ return a;
358+}
359+
360+a_Exp new_exp_from_cast( a_Type_Decl type, a_Exp exp, int pos )
361+{
362+ a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
363+ a->s_type = ae_exp_cast;
364+ a->s_meta = ae_meta_value;
365+ a->cast.type = type;
366+ a->cast.exp = exp;
367+ a->linepos = pos;
368+ a->cast.linepos = pos;
369+ a->cast.self = a;
370+
371+ return a;
372+}
373+
374+a_Exp new_exp_from_array( a_Exp base, a_Array_Sub indices, int pos )
375+{
376+ a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
377+ a->s_type = ae_exp_array;
378+ a->s_meta = ae_meta_var;
379+ a->array.base = base;
380+ a->array.indices = indices;
381+ a->linepos = pos;
382+ a->array.linepos = pos;
383+ a->array.self = a;
384+
385+ return a;
386+}
387+
388+a_Exp new_exp_from_func_call( a_Exp base, a_Exp args, int pos )
389+{
390+ a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
391+ a->s_type = ae_exp_func_call;
392+ a->s_meta = ae_meta_value;
393+ a->func_call.func = base;
394+ a->func_call.args = args;
395+ a->linepos = pos;
396+ a->func_call.linepos = pos;
397+ a->func_call.self = a;
398+
399+ return a;
400+}
401+
402+a_Exp new_exp_from_member_dot( a_Exp base, c_str xid, int pos )
403+{
404+ a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
405+ a->s_type = ae_exp_dot_member;
406+ a->s_meta = ae_meta_var;
407+ a->dot_member.base = base;
408+ a->dot_member.xid = insert_symbol( xid );
409+ a->linepos = pos;
410+ a->dot_member.linepos = pos;
411+ a->dot_member.self = a;
412+
413+ return a;
414+}
415+
416+a_Exp new_exp_from_postfix( a_Exp base, ae_Operator op, int pos )
417+{
418+ a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
419+ a->s_type = ae_exp_postfix;
420+ a->s_meta = ae_meta_var;
421+ a->postfix.exp = base;
422+ a->postfix.op = op;
423+ a->linepos = pos;
424+ a->postfix.linepos = pos;
425+ a->postfix.self = a;
426+
427+ return a;
428+}
429+
430+a_Exp new_exp_from_dur( a_Exp base, a_Exp unit, int pos )
431+{
432+ a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
433+ a->s_type = ae_exp_dur;
434+ a->s_meta = ae_meta_value;
435+ a->dur.base = base;
436+ a->dur.unit = unit;
437+ a->linepos = pos;
438+ a->dur.linepos = pos;
439+ a->dur.self = a;
440+
441+ return a;
442+}
443+
444+a_Exp new_exp_from_id( c_str xid, int pos )
445+{
446+ a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
447+ a->s_type = ae_exp_primary;
448+ a->s_meta = ae_meta_var;
449+ a->primary.s_type = ae_primary_var;
450+ a->primary.var = insert_symbol( xid );
451+ a->linepos = pos;
452+ a->primary.linepos = pos;
453+ a->primary.self = a;
454+
455+ return a;
456+}
457+
458+a_Exp new_exp_from_int( long num, int pos )
459+{
460+ a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
461+ a->s_type = ae_exp_primary;
462+ a->s_meta = ae_meta_value;
463+ a->primary.s_type = ae_primary_num;
464+ a->primary.num = num;
465+ a->linepos = pos;
466+ a->primary.linepos = pos;
467+ a->primary.self = a;
468+
469+ return a;
470+}
471+
472+a_Exp new_exp_from_float( double num, int pos )
473+{
474+ a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
475+ a->s_type = ae_exp_primary;
476+ a->s_meta = ae_meta_value;
477+ a->primary.s_type = ae_primary_float;
478+ a->primary.fnum = num;
479+ a->linepos = pos;
480+ a->primary.linepos = pos;
481+ a->primary.self = a;
482+
483+ return a;
484+}
485+
486+a_Exp new_exp_from_str( c_str str, int pos )
487+{
488+ a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
489+ a->s_type = ae_exp_primary;
490+ a->s_meta = ae_meta_value;
491+ a->primary.s_type = ae_primary_str;
492+ a->primary.str = str;
493+ a->linepos = pos;
494+ a->primary.linepos = pos;
495+ a->primary.self = a;
496+
497+ return a;
498+}
499+
500+a_Exp new_exp_from_char( c_str chr, int pos )
501+{
502+ a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
503+ a->s_type = ae_exp_primary;
504+ a->s_meta = ae_meta_value;
505+ a->primary.s_type = ae_primary_char;
506+ a->primary.chr = chr;
507+ a->linepos = pos;
508+ a->primary.linepos = pos;
509+ a->primary.self = a;
510+
511+ return a;
512+}
513+
514+a_Exp new_exp_from_array_lit( a_Array_Sub exp_list, int pos )
515+{
516+ a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
517+ a->s_type = ae_exp_primary;
518+ a->s_meta = ae_meta_value;
519+ a->primary.s_type = ae_primary_array;
520+ a->primary.array = exp_list;
521+ a->linepos = pos;
522+ a->primary.linepos = pos;
523+ a->primary.self = a;
524+
525+ return a;
526+}
527+
528+a_Exp new_exp_from_if( a_Exp cond, a_Exp if_exp, a_Exp else_exp, int pos )
529+{
530+ a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
531+ a->s_type = ae_exp_if;
532+ a->s_meta = ( ( if_exp->s_meta == ae_meta_var &&
533+ else_exp->s_meta == ae_meta_var ) ? ae_meta_var : ae_meta_value );
534+ a->exp_if.cond = cond;
535+ a->exp_if.if_exp = if_exp;
536+ a->exp_if.else_exp = else_exp;
537+ a->linepos = pos;
538+ a->exp_if.linepos = pos;
539+ a->exp_if.self = a;
540+
541+ return a;
542+}
543+
544+a_Exp new_exp_decl_external( a_Type_Decl type, a_Var_Decl_List var_decl_list, int is_static, int pos )
545+{
546+ a_Exp a = new_exp_decl( type, var_decl_list, is_static, pos );
547+ a->decl.is_external = 1;
548+
549+ return a;
550+}
551+
552+a_Exp new_exp_decl( a_Type_Decl type, a_Var_Decl_List var_decl_list, int is_static, int pos )
553+{
554+ a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
555+ a->s_type = ae_exp_decl;
556+ a->s_meta = ae_meta_var;
557+ a->decl.type = type;
558+ a->decl.var_decl_list = var_decl_list;
559+ a->linepos = pos;
560+ a->decl.is_static = is_static;
561+ a->decl.linepos = pos;
562+ a->decl.self = a;
563+
564+ return a;
565+}
566+
567+a_Exp new_exp_from_hack( a_Exp exp, int pos )
568+{
569+ a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
570+ a->s_type = ae_exp_primary;
571+ a->s_meta = ae_meta_value;
572+ a->primary.s_type = ae_primary_hack;
573+ a->primary.exp = exp;
574+ a->primary.linepos = pos;
575+ a->linepos = pos;
576+ a->primary.self = a;
577+
578+ return a;
579+}
580+
581+a_Exp new_exp_from_complex( a_Complex exp, int pos )
582+{
583+ a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
584+ a->s_type = ae_exp_primary;
585+ a->s_meta = ae_meta_value;
586+ a->primary.s_type = ae_primary_complex;
587+ a->primary.complex = exp;
588+ a->primary.linepos = pos;
589+ a->linepos = pos;
590+ a->primary.complex->self = a;
591+ a->primary.self = a;
592+
593+ return a;
594+}
595+
596+a_Exp new_exp_from_polar( a_Polar exp, int pos )
597+{
598+ a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
599+ a->s_type = ae_exp_primary;
600+ a->s_meta = ae_meta_value;
601+ a->primary.s_type = ae_primary_polar;
602+ a->primary.polar = exp;
603+ a->primary.linepos = pos;
604+ a->linepos = pos;
605+ a->primary.polar->self = a;
606+ a->primary.self = a;
607+
608+ return a;
609+}
610+
611+a_Exp new_exp_from_vec( a_Vec exp, int pos ) // ge: added 1.3.5.3
612+{
613+ a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
614+ a->s_type = ae_exp_primary;
615+ a->s_meta = ae_meta_value;
616+ a->primary.s_type = ae_primary_vec;
617+ a->primary.vec = exp;
618+ a->primary.linepos = pos;
619+ a->linepos = pos;
620+ a->primary.vec->self = a;
621+ a->primary.self = a;
622+
623+ return a;
624+}
625+
626+a_Exp new_exp_from_nil( int pos )
627+{
628+ a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) );
629+ a->s_type = ae_exp_primary;
630+ a->s_meta = ae_meta_value;
631+ a->primary.s_type = ae_primary_nil;
632+ a->primary.linepos = pos;
633+ a->linepos = pos;
634+ a->primary.self = a;
635+
636+ return a;
637+}
638+
639+a_Var_Decl new_var_decl( c_constr xid, a_Array_Sub array, int pos )
640+{
641+ a_Var_Decl a = (a_Var_Decl)checked_malloc( sizeof( struct a_Var_Decl_ ) );
642+ a->xid = insert_symbol(xid);
643+ a->array = array;
644+ a->linepos = pos;
645+
646+ return a;
647+}
648+
649+a_Var_Decl_List new_var_decl_list( a_Var_Decl var_decl, int pos )
650+{
651+ a_Var_Decl_List a = (a_Var_Decl_List)checked_malloc(
652+ sizeof( struct a_Var_Decl_List_ ) );
653+ a->var_decl = var_decl;
654+ a->linepos = pos;
655+
656+ return a;
657+}
658+
659+a_Var_Decl_List prepend_var_decl_list( a_Var_Decl var_decl, a_Var_Decl_List list, int pos )
660+{
661+ a_Var_Decl_List a = new_var_decl_list( var_decl, pos );
662+ a->next = list;
663+
664+ return a;
665+}
666+
667+a_Type_Decl new_type_decl( a_Id_List type, int ref, int pos )
668+{
669+ a_Type_Decl a = (a_Type_Decl)checked_malloc(
670+ sizeof( struct a_Type_Decl_ ) );
671+ a->xid = type;
672+ a->ref = ref;
673+ a->linepos = pos;
674+
675+ return a;
676+}
677+
678+a_Type_Decl add_type_decl_array( a_Type_Decl a, a_Array_Sub array, int pos )
679+{
680+ assert( a->array == NULL );
681+ a->array = array;
682+
683+ return a;
684+}
685+
686+a_Arg_List new_arg_list( a_Type_Decl type_decl, a_Var_Decl var_decl, int pos )
687+{
688+ a_Arg_List a = (a_Arg_List)checked_malloc(
689+ sizeof( struct a_Arg_List_ ) );
690+ a->type_decl = type_decl;
691+ a->var_decl = var_decl;
692+ a->next = NULL;
693+ a->linepos = pos;
694+
695+ return a;
696+}
697+
698+a_Arg_List prepend_arg_list( a_Type_Decl type_decl, a_Var_Decl var_decl,
699+ a_Arg_List arg_list, int pos )
700+{
701+ a_Arg_List a = new_arg_list( type_decl, var_decl, pos );
702+ a->next = arg_list;
703+ a->linepos = pos;
704+
705+ return a;
706+}
707+
708+a_Func_Def new_func_def( ae_Keyword func_decl, ae_Keyword static_decl,
709+ a_Type_Decl type_decl, c_str name,
710+ a_Arg_List arg_list, a_Stmt code, int pos )
711+{
712+ a_Func_Def a = (a_Func_Def)checked_malloc(
713+ sizeof( struct a_Func_Def_ ) );
714+ a->func_decl = func_decl;
715+ a->static_decl = static_decl;
716+ a->type_decl = type_decl;
717+ a->name = insert_symbol( name );
718+ a->arg_list = arg_list;
719+ a->s_type = ae_func_user;
720+ a->code = code;
721+ a->linepos = pos;
722+
723+ return a;
724+}
725+
726+a_Class_Def new_class_def( ae_Keyword class_decl, a_Id_List name,
727+ a_Class_Ext ext, a_Class_Body body, int pos )
728+{
729+ a_Class_Def a = (a_Class_Def)checked_malloc( sizeof( struct a_Class_Def_ ) );
730+ a->decl = class_decl;
731+ a->name = name;
732+ a->ext = ext;
733+ a->body = body;
734+ a->linepos = pos;
735+
736+ return a;
737+}
738+
739+a_Class_Def new_iface_def( ae_Keyword class_decl, a_Id_List name,
740+ a_Class_Ext ext, a_Class_Body body, int pos )
741+{
742+ a_Class_Def a = new_class_def( class_decl, name, ext, body, pos );
743+ a->iface = 1;
744+
745+ return a;
746+}
747+
748+a_Class_Body new_class_body( a_Section section, int pos )
749+{
750+ a_Class_Body a = (a_Class_Body)checked_malloc( sizeof( struct a_Class_Body_ ) );
751+ a->section = section;
752+ a->linepos = pos;
753+
754+ return a;
755+}
756+
757+a_Class_Body prepend_class_body( a_Section section, a_Class_Body body, int pos )
758+{
759+ a_Class_Body a = new_class_body( section, pos );
760+ a->next = body;
761+ a->linepos = pos;
762+
763+ return a;
764+}
765+
766+a_Class_Ext new_class_ext( a_Id_List extend_id, a_Id_List impl_list, int pos )
767+{
768+ a_Class_Ext a = (a_Class_Ext)checked_malloc( sizeof( struct a_Class_Ext_ ) );
769+ a->extend_id = extend_id;
770+ a->impl_list = impl_list;
771+ a->linepos = pos;
772+
773+ return a;
774+}
775+
776+a_Id_List new_id_list( c_constr xid, int pos )
777+{
778+ a_Id_List a = (a_Id_List)checked_malloc( sizeof( struct a_Id_List_ ) );
779+ a->xid = insert_symbol( xid );
780+ a->next = NULL;
781+ a->linepos = pos;
782+
783+ return a;
784+}
785+
786+a_Id_List prepend_id_list( c_constr xid, a_Id_List list, int pos )
787+{
788+ a_Id_List a = new_id_list( xid, pos );
789+ a->next = list;
790+ a->linepos = pos;
791+
792+ return a;
793+}
794+
795+void clean_exp( a_Exp exp )
796+{
797+ if( !exp ) return;
798+ clean_exp( exp->next );
799+ free( exp );
800+}
801+
802+a_Array_Sub new_array_sub( a_Exp exp, int pos )
803+{
804+ a_Array_Sub a = (a_Array_Sub)checked_malloc( sizeof( struct a_Array_Sub_ ) );
805+ a->exp_list = exp;
806+ a->depth = 1;
807+ a->linepos = pos;
808+
809+ // make sure no multi
810+ /* if( exp && exp->next )
811+ {
812+ // primary exp?
813+ if( is_primary )
814+ {
815+ a->exp_list = NULL;
816+ a->exp_multi = exp;
817+ }
818+ else
819+ {
820+ a->err_num = 1; // multi
821+ a->err_pos = exp->linepos; // set error for type-checker
822+ goto error;
823+ }
824+ } */
825+
826+ return a;
827+
828+/* error:
829+ clean_exp( exp );
830+ a->exp_list = NULL;
831+ return a; */
832+}
833+
834+a_Array_Sub prepend_array_sub( a_Array_Sub a, a_Exp exp, int pos )
835+{
836+ // if already error
837+ if( a->err_num ) goto error;
838+
839+ // make sure no multi
840+ if( exp && exp->next )
841+ {
842+ a->err_num = 1; // multi
843+ a->err_pos = exp->linepos; // set error for type-checker
844+ goto error;
845+ }
846+
847+ // empty or not
848+ if( (exp && !a->exp_list) || (!exp && a->exp_list) )
849+ {
850+ a->err_num = 2; // partial
851+ a->err_pos = pos; // set error for type-checker
852+ goto error;
853+ }
854+
855+ // prepend
856+ if( exp )
857+ {
858+ exp->next = a->exp_list;
859+ a->exp_list = exp;
860+ }
861+
862+ // count
863+ a->depth++;
864+ return a;
865+
866+error:
867+ clean_exp( exp );
868+ return a;
869+}
870+
871+a_Complex new_complex( a_Exp re, int pos )
872+{
873+ a_Complex a = (a_Complex)checked_malloc( sizeof( struct a_Complex_ ) );
874+ a->re = re;
875+ if( re ) a->im = re->next;
876+ a->linepos = pos;
877+
878+ return a;
879+}
880+
881+a_Polar new_polar( a_Exp mod, int pos )
882+{
883+ a_Polar a = (a_Polar)checked_malloc( sizeof( struct a_Polar_ ) );
884+ a->mod = mod;
885+ if( mod ) a->phase = mod->next;
886+ a->linepos = pos;
887+
888+ return a;
889+}
890+
891+a_Vec new_vec( a_Exp e, int pos ) // ge: added 1.3.5.3
892+{
893+ a_Vec a = (a_Vec)checked_malloc( sizeof( struct a_Vec_ ) );
894+ a->args = e;
895+ while( e ) // count number of dims
896+ {
897+ a->numdims++;
898+ e = e->next;
899+ }
900+ a->linepos = pos;
901+
902+ return a;
903+}
904+
905+void delete_id_list( a_Id_List x )
906+{
907+ if( !x ) return;
908+
909+ a_Id_List curr = x, next = x->next, temp;
910+
911+ while( curr )
912+ {
913+ temp = curr;
914+ curr = next;
915+ next = temp->next;
916+ free( temp );
917+ }
918+}
919+
920+
921+static const char * op_str[] = {
922+ "+",
923+ "-",
924+ "*",
925+ "/",
926+ "==",
927+ "!=",
928+ "<",
929+ "<=",
930+ ">",
931+ ">=",
932+ "&&",
933+ "||",
934+ "|",
935+ "&",
936+ "<<",
937+ ">>",
938+ "%",
939+ "^",
940+ "=>",
941+ "+=>",
942+ "-=>",
943+ "*=>",
944+ "/=>",
945+ "&=>",
946+ "|=>",
947+ "^=>",
948+ ">>=>",
949+ "<<=>",
950+ "%=>",
951+ "->",
952+ "++",
953+ "--",
954+ "~",
955+ "!",
956+ "@=>",
957+ "=<",
958+ "spork ~",
959+ "typeof",
960+ "sizeof",
961+ "new"
962+};
963+
964+
965+const char * op2str( ae_Operator op )
966+{
967+ t_CKINT index = (t_CKINT)op;
968+ if( index < 0 || index >= (t_CKINT)(sizeof(op_str)/sizeof(char *)) )
969+ return "[non-existent operator]";
970+
971+ return op_str[index];
972+}
core/chuck_absyn.h+406−0
@@ -0,0 +1,406 @@
1+/*----------------------------------------------------------------------------
2+ ChucK Concurrent, On-the-fly Audio Programming Language
3+ Compiler and Virtual Machine
4+
5+ Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6+ http://chuck.stanford.edu/
7+ http://chuck.cs.princeton.edu/
8+
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.
13+
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.
18+
19+ You should have received a copy of the GNU General Public License
20+ along with this program; if not, write to the Free Software
21+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22+ U.S.A.
23+-----------------------------------------------------------------------------*/
24+
25+//-----------------------------------------------------------------------------
26+// file: chuck_absyn.h
27+// desc: chuck abstract syntax
28+//
29+// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
30+// date: Autumn 2002
31+//-----------------------------------------------------------------------------
32+#ifndef __CHUCK_ABSYN_H__
33+#define __CHUCK_ABSYN_H__
34+
35+#include "chuck_symbol.h"
36+
37+#if defined(_cplusplus) || defined(__cplusplus)
38+extern "C" {
39+#endif
40+
41+// pos
42+typedef int a_Pos;
43+
44+// enum oper
45+typedef enum {
46+ ae_op_plus, ae_op_minus, ae_op_times, ae_op_divide,
47+ ae_op_eq, ae_op_neq, ae_op_lt, ae_op_le, ae_op_gt,
48+ ae_op_ge, ae_op_and, ae_op_or, ae_op_s_or, ae_op_s_and,
49+ ae_op_shift_left, ae_op_shift_right, ae_op_percent,
50+ ae_op_s_xor, ae_op_chuck, ae_op_plus_chuck, ae_op_minus_chuck,
51+ ae_op_times_chuck, ae_op_divide_chuck, ae_op_s_and_chuck,
52+ ae_op_s_or_chuck, ae_op_s_xor_chuck, ae_op_shift_right_chuck,
53+ ae_op_shift_left_chuck, ae_op_percent_chuck, ae_op_s_chuck,
54+ ae_op_plusplus, ae_op_minusminus, ae_op_tilda, ae_op_exclamation,
55+ ae_op_at_chuck, ae_op_unchuck, ae_op_upchuck, ae_op_spork,
56+ ae_op_typeof, ae_op_sizeof, ae_op_new, ae_op_arrow_left, ae_op_arrow_right
57+} ae_Operator;
58+
59+const char * op2str( ae_Operator op );
60+
61+// enum key words
62+typedef enum {
63+ ae_key_this, ae_key_me, ae_key_func, ae_key_public, ae_key_protected,
64+ ae_key_private, ae_key_static, ae_key_instance, ae_key_abstract
65+} ae_Keyword;
66+
67+
68+
69+
70+//-----------------------------------------------------------------------------
71+// pointer types
72+//-----------------------------------------------------------------------------
73+typedef struct a_Program_ * a_Program;
74+typedef struct a_Section_ * a_Section;
75+typedef struct a_Stmt_List_ * a_Stmt_List;
76+typedef struct a_Class_Def_ * a_Class_Def;
77+typedef struct a_Func_Def_ * a_Func_Def;
78+typedef struct a_Code_Segment_ * a_Code_Segment;
79+typedef struct a_Stmt_ * a_Stmt;
80+typedef struct a_Exp_ * a_Exp;
81+typedef struct a_Exp_Chuck_ * a_Exp_Chuck;
82+typedef struct a_Exp_Binary_ * a_Exp_Binary;
83+typedef struct a_Exp_Cast_ * a_Exp_Cast;
84+typedef struct a_Exp_Unary_ * a_Exp_Unary;
85+typedef struct a_Exp_Postfix_ * a_Exp_Postfix;
86+typedef struct a_Exp_Primary_ * a_Exp_Primary;
87+typedef struct a_Exp_Dur_ * a_Exp_Dur;
88+typedef struct a_Exp_Array_ * a_Exp_Array;
89+typedef struct a_Exp_Func_Call_ * a_Exp_Func_Call;
90+typedef struct a_Exp_Dot_Member_ * a_Exp_Dot_Member;
91+typedef struct a_Exp_If_ * a_Exp_If;
92+typedef struct a_Exp_Decl_ * a_Exp_Decl;
93+typedef struct a_Exp_Hack_ * a_Exp_Hack;
94+typedef struct a_Stmt_Code_ * a_Stmt_Code;
95+typedef struct a_Stmt_If_ * a_Stmt_If;
96+typedef struct a_Stmt_While_ * a_Stmt_While;
97+typedef struct a_Stmt_Until_ * a_Stmt_Until;
98+typedef struct a_Stmt_For_ * a_Stmt_For;
99+typedef struct a_Stmt_Loop_ * a_Stmt_Loop;
100+typedef struct a_Stmt_Switch_ * a_Stmt_Switch;
101+typedef struct a_Stmt_Break_ * a_Stmt_Break;
102+typedef struct a_Stmt_Continue_ * a_Stmt_Continue;
103+typedef struct a_Stmt_Return_ * a_Stmt_Return;
104+typedef struct a_Stmt_Case_ * a_Stmt_Case;
105+typedef struct a_Stmt_GotoLabel_ * a_Stmt_GotoLabel;
106+typedef struct a_Decl_ * a_Decl;
107+typedef struct a_Var_Decl_ * a_Var_Decl;
108+typedef struct a_Var_Decl_List_ * a_Var_Decl_List;
109+typedef struct a_Type_Decl_ * a_Type_Decl;
110+typedef struct a_Arg_List_ * a_Arg_List;
111+typedef struct a_Id_List_ * a_Id_List;
112+typedef struct a_Class_Ext_ * a_Class_Ext;
113+typedef struct a_Class_Body_ * a_Class_Body;
114+typedef struct a_Array_Sub_ * a_Array_Sub;
115+typedef struct a_Complex_ * a_Complex;
116+typedef struct a_Polar_ * a_Polar;
117+typedef struct a_Vec_ * a_Vec; // ge: added 1.3.5.3
118+
119+// forward reference for type
120+typedef struct Chuck_Type * t_CKTYPE;
121+typedef struct Chuck_Value * t_CKVALUE;
122+typedef struct Chuck_Func * t_CKFUNC;
123+typedef struct Chuck_Namespace * t_CKNSPC;
124+typedef struct Chuck_VM_Code * t_CKVMCODE;
125+
126+
127+
128+
129+//------------------------------------------------------------------------------
130+// functions
131+//------------------------------------------------------------------------------
132+a_Program new_program( a_Section section, int pos );
133+a_Program prepend_program( a_Section section, a_Program program, int pos );
134+a_Section new_section_stmt( a_Stmt_List stmt_list, int pos );
135+a_Section new_section_func_def( a_Func_Def func_def, int pos );
136+a_Section new_section_class_def( a_Class_Def class_def, int pos );
137+a_Stmt_List new_stmt_list( a_Stmt stmt, int pos );
138+a_Stmt_List prepend_stmt_list( a_Stmt stmt, a_Stmt_List stmt_list, int pos );
139+a_Stmt new_stmt_from_expression( a_Exp exp, int pos );
140+a_Stmt new_stmt_from_code( a_Stmt_List code, int pos );
141+a_Stmt new_stmt_from_while( a_Exp cond, a_Stmt body, int pos );
142+a_Stmt new_stmt_from_do_while( a_Exp cond, a_Stmt body, int pos );
143+a_Stmt new_stmt_from_until( a_Exp cond, a_Stmt body, int pos );
144+a_Stmt new_stmt_from_do_until( a_Exp cond, a_Stmt body, int pos );
145+a_Stmt new_stmt_from_for( a_Stmt c1, a_Stmt c2, a_Exp c3, a_Stmt body, int pos );
146+a_Stmt new_stmt_from_loop( a_Exp cond, a_Stmt body, int pos );
147+a_Stmt new_stmt_from_if( a_Exp cond, a_Stmt if_body, a_Stmt else_body, int pos );
148+a_Stmt new_stmt_from_switch( a_Exp exp, int pos );
149+a_Stmt new_stmt_from_break( int pos );
150+a_Stmt new_stmt_from_continue( int pos );
151+a_Stmt new_stmt_from_return( a_Exp exp, int pos );
152+a_Stmt new_stmt_from_label( c_str xid, int pos );
153+a_Stmt new_stmt_from_case( a_Exp exp, int pos );
154+a_Exp prepend_expression( a_Exp exp, a_Exp list, int pos );
155+a_Exp new_exp_from_binary( a_Exp lhs, ae_Operator oper, a_Exp rhs, int pos );
156+a_Exp new_exp_from_unary( ae_Operator oper, a_Exp exp, int pos );
157+a_Exp new_exp_from_unary2( ae_Operator oper, a_Type_Decl type, a_Array_Sub array, int pos );
158+a_Exp new_exp_from_unary3( ae_Operator oper, a_Stmt code, int pos );
159+a_Exp new_exp_from_cast( a_Type_Decl type, a_Exp exp, int pos );
160+a_Exp new_exp_from_array( a_Exp base, a_Array_Sub indices, int pos );
161+a_Exp new_exp_from_array_lit( a_Array_Sub exp_list, int pos );
162+a_Exp new_exp_from_func_call( a_Exp base, a_Exp args, int pos );
163+a_Exp new_exp_from_member_dot( a_Exp base, c_str member, int pos );
164+a_Exp new_exp_from_postfix( a_Exp base, ae_Operator op, int pos );
165+a_Exp new_exp_from_dur( a_Exp base, a_Exp unit, int pos );
166+a_Exp new_exp_from_id( c_str xid, int pos );
167+a_Exp new_exp_from_int( long num, int pos );
168+a_Exp new_exp_from_uint( unsigned long num, int pos );
169+a_Exp new_exp_from_float( double num, int pos );
170+a_Exp new_exp_from_str( c_str str, int pos );
171+a_Exp new_exp_from_char( c_str chr, int pos );
172+a_Exp new_exp_from_if( a_Exp cond, a_Exp lhs, a_Exp rhs, int pos );
173+a_Exp new_exp_from_complex( a_Complex, int pos );
174+a_Exp new_exp_from_polar( a_Polar, int pos );
175+a_Exp new_exp_from_vec( a_Vec, int pos ); // ge: added 1.3.5.3
176+a_Exp new_exp_decl_external( a_Type_Decl type_decl, a_Var_Decl_List var_decl_list, int is_static, int pos );
177+a_Exp new_exp_decl( a_Type_Decl type_decl, a_Var_Decl_List var_decl_list, int is_static, int pos );
178+a_Exp new_exp_from_hack( a_Exp exp, int pos );
179+a_Exp new_exp_from_nil( int pos );
180+a_Var_Decl_List new_var_decl_list( a_Var_Decl var_decl, int pos );
181+a_Var_Decl_List prepend_var_decl_list( a_Var_Decl var_decl, a_Var_Decl_List list, int pos );
182+a_Var_Decl new_var_decl( c_constr xid, a_Array_Sub array, int pos );
183+a_Type_Decl new_type_decl( a_Id_List xid, int ref, int pos );
184+a_Type_Decl add_type_decl_array( a_Type_Decl type_decl, a_Array_Sub array, int pos );
185+a_Arg_List new_arg_list( a_Type_Decl type_decl, a_Var_Decl var_decl, int pos );
186+a_Arg_List prepend_arg_list( a_Type_Decl type_decl, a_Var_Decl var_decl, a_Arg_List arg_list, int pos );
187+a_Array_Sub new_array_sub( a_Exp exp, int pos );
188+a_Array_Sub prepend_array_sub( a_Array_Sub array, a_Exp exp, int pos );
189+a_Complex new_complex( a_Exp re, int pos );
190+a_Polar new_polar( a_Exp mod, int pos ); // ge: added 1.3.5.3
191+a_Vec new_vec( a_Exp e, int pos );
192+
193+a_Class_Def new_class_def( ae_Keyword class_decl, a_Id_List xid, a_Class_Ext ext, a_Class_Body body, int pos );
194+a_Class_Body new_class_body( a_Section section, int pos );
195+a_Class_Body prepend_class_body( a_Section section, a_Class_Body body, int pos );
196+a_Class_Ext new_class_ext( a_Id_List extend_id, a_Id_List impl_list, int pos );
197+a_Class_Def new_iface_def( ae_Keyword class_decl, a_Id_List xid, a_Class_Ext ext, a_Class_Body body, int pos );
198+a_Id_List new_id_list( c_constr xid, int pos );
199+a_Id_List prepend_id_list( c_constr xid, a_Id_List list, int pos );
200+void clean_exp( a_Exp exp );
201+a_Func_Def new_func_def( ae_Keyword func_decl, ae_Keyword static_decl,
202+ a_Type_Decl type_decl, c_str name,
203+ a_Arg_List arg_list, a_Stmt code, int pos );
204+
205+void delete_id_list( a_Id_List x );
206+
207+
208+
209+
210+//------------------------------------------------------------------------------
211+// structs
212+//------------------------------------------------------------------------------
213+struct a_Exp_Binary_ { a_Exp lhs; ae_Operator op; a_Exp rhs; t_CKFUNC ck_func; int linepos; a_Exp self; };
214+struct a_Exp_Cast_ { a_Type_Decl type; a_Exp exp; int linepos; a_Exp self; };
215+struct a_Exp_Unary_ { ae_Operator op; a_Exp exp; a_Type_Decl type; a_Array_Sub array;
216+ a_Stmt code; int linepos; a_Exp self; };
217+struct a_Exp_Postfix_ { a_Exp exp; ae_Operator op; int linepos; a_Exp self; };
218+struct a_Exp_Dur_ { a_Exp base; a_Exp unit; int linepos; a_Exp self; };
219+struct a_Exp_Array_ { a_Exp base; a_Array_Sub indices; int linepos; a_Exp self; };
220+struct a_Exp_Func_Call_ { a_Exp func; a_Exp args; t_CKTYPE ret_type;
221+ t_CKFUNC ck_func; t_CKVMCODE ck_vm_code; int linepos; a_Exp self; };
222+struct a_Exp_Dot_Member_ { a_Exp base; t_CKTYPE t_base; S_Symbol xid; int linepos; a_Exp self; };
223+struct a_Exp_If_ { a_Exp cond; a_Exp if_exp; a_Exp else_exp; int linepos; a_Exp self; };
224+struct a_Exp_Decl_ { a_Type_Decl type; a_Var_Decl_List var_decl_list; int num_var_decls; int is_static; int is_external;
225+ t_CKTYPE ck_type; int linepos; a_Exp self; };
226+struct a_Exp_Hack_ { a_Exp exp; int linepos; a_Exp self; };
227+struct a_Var_Decl_List_ { a_Var_Decl var_decl; a_Var_Decl_List next; int linepos; a_Exp self; };
228+struct a_Var_Decl_ { S_Symbol xid; a_Var_Decl var_decl; a_Array_Sub array; t_CKVALUE value;
229+ void * addr; int linepos; a_Exp self; };
230+struct a_Type_Decl_ { a_Id_List xid; a_Array_Sub array; int ref; int linepos; /*a_Exp self;*/ };
231+struct a_Array_Sub_ { t_CKUINT depth; a_Exp exp_list; int linepos; a_Exp self;
232+ int err_num; int err_pos; };
233+struct a_Arg_List_ { a_Type_Decl type_decl; a_Var_Decl var_decl; t_CKTYPE type;
234+ a_Arg_List next; int linepos; a_Exp self; };
235+struct a_Complex_ { a_Exp re; a_Exp im; int linepos; a_Exp self; };
236+struct a_Polar_ { a_Exp mod; a_Exp phase; int linepos; a_Exp self; };
237+struct a_Vec_ { a_Exp args; int numdims; int linepos; a_Exp self; }; // ge: added 1.3.5.3
238+
239+// enum primary exp type
240+typedef enum { ae_primary_var, ae_primary_num, ae_primary_float,
241+ ae_primary_str, ae_primary_array, ae_primary_exp,
242+ ae_primary_hack, ae_primary_complex, ae_primary_polar,
243+ ae_primary_vec, ae_primary_char, ae_primary_nil
244+ } ae_Exp_Primary_Type;
245+
246+struct a_Exp_Primary_
247+{
248+ ae_Exp_Primary_Type s_type;
249+ t_CKVALUE value;
250+
251+ union
252+ {
253+ S_Symbol var;
254+ t_CKINT num;
255+ t_CKFLOAT fnum;
256+ c_str str;
257+ c_str chr;
258+ a_Array_Sub array;
259+ a_Exp exp;
260+ a_Complex complex;
261+ a_Polar polar;
262+ a_Vec vec; // ge: added 1.3.5.3
263+ };
264+
265+ int linepos;
266+ a_Exp self;
267+};
268+
269+// enum exp type
270+typedef enum { ae_exp_binary = 0, ae_exp_unary, ae_exp_cast, ae_exp_postfix,
271+ ae_exp_dur, ae_exp_primary, ae_exp_array, ae_exp_func_call,
272+ ae_exp_dot_member, ae_exp_if, ae_exp_decl
273+ } ae_Exp_Type;
274+// type meta data
275+typedef enum { ae_meta_value = 0, ae_meta_var } ae_Exp_Meta;
276+
277+struct a_Exp_
278+{
279+ ae_Exp_Type s_type;
280+ ae_Exp_Meta s_meta;
281+ t_CKTYPE type;
282+ t_CKNSPC owner;
283+ a_Exp next;
284+
285+ t_CKUINT group_size;
286+ t_CKTYPE cast_to;
287+ t_CKUINT emit_var; // 1 = emit var, 2 = emit var and value
288+
289+ union
290+ {
291+ struct a_Exp_Binary_ binary;
292+ struct a_Exp_Unary_ unary;
293+ struct a_Exp_Cast_ cast;
294+ struct a_Exp_Postfix_ postfix;
295+ struct a_Exp_Dur_ dur;
296+ struct a_Exp_Primary_ primary;
297+ struct a_Exp_Array_ array;
298+ struct a_Exp_Func_Call_ func_call;
299+ struct a_Exp_Dot_Member_ dot_member;
300+ struct a_Exp_If_ exp_if;
301+ struct a_Exp_Decl_ decl;
302+ };
303+
304+ int linepos;
305+};
306+
307+struct a_Stmt_While_ { int is_do; a_Exp cond; a_Stmt body; int linepos; a_Stmt self; };
308+struct a_Stmt_Until_ { int is_do; a_Exp cond; a_Stmt body; int linepos; a_Stmt self; };
309+struct a_Stmt_For_ { a_Stmt c1; a_Stmt c2; a_Exp c3; a_Stmt body; int linepos; a_Stmt self; };
310+struct a_Stmt_Loop_ { a_Exp cond; a_Stmt body; int linepos; a_Stmt self; };
311+struct a_Stmt_Code_ { a_Stmt_List stmt_list; int linepos; a_Stmt self; };
312+struct a_Stmt_If_ { a_Exp cond; a_Stmt if_body; a_Stmt else_body; int linepos; a_Stmt self; };
313+struct a_Stmt_Switch_ { a_Exp val; int linepos; a_Stmt self; };
314+struct a_Stmt_Break_ { int linepos; a_Stmt self; };
315+struct a_Stmt_Continue_ { int linepos; a_Stmt self; };
316+struct a_Stmt_Return_ { a_Exp val; int linepos; a_Stmt self; };
317+struct a_Stmt_Case_ { a_Exp exp; int linepos; a_Stmt self; };
318+struct a_Stmt_GotoLabel_ { S_Symbol name; int linepos; a_Stmt self; };
319+
320+// enum values for stmt type
321+typedef enum { ae_stmt_exp, ae_stmt_while, ae_stmt_until, ae_stmt_for, ae_stmt_loop,
322+ ae_stmt_if, ae_stmt_code, ae_stmt_switch, ae_stmt_break,
323+ ae_stmt_continue, ae_stmt_return, ae_stmt_case, ae_stmt_gotolabel
324+ } ae_Stmt_Type;
325+
326+struct a_Stmt_
327+{
328+ ae_Stmt_Type s_type;
329+ int skip;
330+
331+ union
332+ {
333+ a_Exp stmt_exp;
334+ struct a_Stmt_Code_ stmt_code;
335+ struct a_Stmt_While_ stmt_while;
336+ struct a_Stmt_Until_ stmt_until;
337+ struct a_Stmt_Loop_ stmt_loop;
338+ struct a_Stmt_For_ stmt_for;
339+ struct a_Stmt_If_ stmt_if;
340+ struct a_Stmt_Switch_ stmt_switch;
341+ struct a_Stmt_Break_ stmt_break;
342+ struct a_Stmt_Continue_ stmt_continue;
343+ struct a_Stmt_Return_ stmt_return;
344+ struct a_Stmt_Case_ stmt_case;
345+ struct a_Stmt_GotoLabel_ stmt_gotolabel;
346+ };
347+
348+ int linepos;
349+};
350+
351+struct a_Stmt_List_ { a_Stmt stmt; a_Stmt_List next; int linepos; };
352+struct a_Class_Def_ { ae_Keyword decl; a_Id_List name; a_Class_Ext ext;
353+ a_Class_Body body; t_CKTYPE type; int iface; t_CKNSPC home;
354+ int linepos; };
355+struct a_Class_Ext_ { a_Id_List extend_id; a_Id_List impl_list; int linepos; };
356+struct a_Class_Body_ { a_Section section; a_Class_Body next; int linepos; };
357+struct a_Id_List_ { S_Symbol xid; a_Id_List next; int linepos; };
358+
359+typedef enum { ae_func_user, ae_func_builtin } ae_Func_Type;
360+// struct t_Func_User_ { int linepos; };
361+// typedef unsigned int (* builtin_func_ptr)( unsigned int arg );
362+// struct t_Func_BuiltIn_ { builtin_func_ptr func_ptr; int linepos; };
363+struct a_Func_Def_ {
364+ ae_Keyword func_decl;
365+ ae_Keyword static_decl;
366+ a_Type_Decl type_decl;
367+ t_CKTYPE ret_type;
368+ S_Symbol name;
369+ a_Arg_List arg_list;
370+ a_Stmt code;
371+ t_CKFUNC ck_func;
372+ unsigned int global;
373+ unsigned int s_type;
374+ unsigned int stack_depth;
375+ void * dl_func_ptr; // should be not NULL iff s_type == ae_func_builtin
376+ int linepos;
377+};
378+
379+// enum values for section types
380+typedef enum { ae_section_stmt, ae_section_func, ae_section_class
381+ } ae_Section_Type;
382+
383+struct a_Section_
384+{
385+ ae_Section_Type s_type;
386+
387+ union
388+ {
389+ a_Stmt_List stmt_list;
390+ a_Class_Def class_def;
391+ a_Func_Def func_def;
392+ };
393+
394+ int linepos;
395+};
396+
397+struct a_Program_ { a_Section section; a_Program next; int linepos; };
398+
399+
400+#if defined(_cplusplus) || defined(__cplusplus)
401+}
402+#endif
403+
404+
405+
406+#endif
core/chuck_carrier.h+14−3
@@ -37,16 +37,21 @@ · 36 unmodified lines
3737 #ifndef __CHUCK_CARRIER_H__
3838 #define __CHUCK_CARRIER_H__
3939
40+#include "chuck_def.h"
4041
4142
4243
43−// forward references
44+
45+// forward references (C++)
4446 class Chuck_Compiler;
4547 class Chuck_VM;
4648 class Chuck_Env;
4749 class Chuck_IO_Chout;
4850 class Chuck_IO_Cherr;
4951
52+// forward references ("C")
53+struct ck_socket;
54+
5055
5156
5257
@@ -62,14 +67,20 @@ struct Chuck_Carrier · 9 unmodified lines
6267 Chuck_IO_Chout * chout;
6368 Chuck_IO_Cherr * cherr;
6469
70+ // OTF programming things
71+ ck_socket otf_socket;
72+ t_CKINT otf_port;
73+
6574 // constructor
6675 Chuck_Carrier() :
6776 compiler( NULL ),
6877 env( NULL ),
6978 vm( NULL ),
7079 chout( NULL ),
71− cherr( NULL )
72− { }
80+ cherr( NULL ),
81+ otf_socket( NULL ),
82+ otf_port( 0 )
83+ { }
7384 };
7485
7586
core/chuck_compile.cpp+900−0
@@ -0,0 +1,900 @@
1+/*----------------------------------------------------------------------------
2+ ChucK Concurrent, On-the-fly Audio Programming Language
3+ Compiler and Virtual Machine
4+
5+ Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6+ http://chuck.stanford.edu/
7+ http://chuck.cs.princeton.edu/
8+
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.
13+
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.
18+
19+ You should have received a copy of the GNU General Public License
20+ along with this program; if not, write to the Free Software
21+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22+ U.S.A.
23+-----------------------------------------------------------------------------*/
24+
25+//-----------------------------------------------------------------------------
26+// file: chuck_compile.cpp
27+// desc: chuck compile system unifying parser, type checker, and emitter
28+//
29+// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
30+// date: Autumn 2005 - original
31+//-----------------------------------------------------------------------------
32+#include "chuck_compile.h"
33+#include "chuck_lang.h"
34+#include "chuck_errmsg.h"
35+#include "chuck_otf.h"
36+
37+#include "ugen_osc.h"
38+#include "ugen_xxx.h"
39+#include "ugen_filter.h"
40+#include "ugen_stk.h"
41+#include "uana_xform.h"
42+#include "uana_extract.h"
43+#include "ulib_machine.h"
44+#include "ulib_math.h"
45+#include "ulib_std.h"
46+#include "ulib_opsc.h"
47+#include "ulib_regex.h"
48+#include "chuck_io.h"
49+
50+#if defined(__PLATFORM_WIN32__)
51+#include "dirent_win32.h"
52+#endif
53+//#if defined(__WINDOWS_PTHREAD__)
54+#include <sys/stat.h>
55+//#endif
56+
57+using namespace std;
58+
59+
60+
61+
62+// function prototypes
63+t_CKBOOL load_internal_modules( Chuck_Compiler * compiler );
64+t_CKBOOL load_external_modules( Chuck_Compiler * compiler,
65+ const char * extension,
66+ std::list<std::string> & chugin_search_paths,
67+ std::list<std::string> & named_dls);
68+t_CKBOOL load_module( Chuck_Compiler * compiler, Chuck_Env * env, f_ck_query query, const char * name, const char * nspc );
69+
70+
71+
72+
73+//-----------------------------------------------------------------------------
74+// name: Chuck_Compiler()
75+// desc: constructor
76+//-----------------------------------------------------------------------------
77+Chuck_Compiler::Chuck_Compiler()
78+{
79+ emitter = NULL;
80+ code = NULL;
81+
82+ // REFACTOR-2017: add carrier
83+ m_carrier = NULL;
84+}
85+
86+
87+
88+
89+//-----------------------------------------------------------------------------
90+// name: ~Chuck_Compiler()
91+// desc: destructor
92+//-----------------------------------------------------------------------------
93+Chuck_Compiler::~Chuck_Compiler()
94+{
95+ // call shutdown
96+ this->shutdown();
97+}
98+
99+
100+
101+
102+//-----------------------------------------------------------------------------
103+// name: initialize()
104+// desc: initialize the compiler
105+//-----------------------------------------------------------------------------
106+t_CKBOOL Chuck_Compiler::initialize( std::list<std::string> & chugin_search_paths,
107+ std::list<std::string> & named_dls )
108+{
109+ // log
110+ EM_log( CK_LOG_SYSTEM, "initializing compiler..." );
111+ // push indent level
112+ EM_pushlog();
113+
114+ // allocate the type checker
115+ Chuck_Env * env = type_engine_init( m_carrier );
116+ // add reference
117+ env->add_ref();
118+
119+ // allocate the emitter
120+ emitter = emit_engine_init( env );
121+ // add reference
122+ emitter->add_ref();
123+ // set auto depend to 0
124+ m_auto_depend = FALSE;
125+
126+ // load internal libs
127+ if( !load_internal_modules( this ) )
128+ goto error;
129+
130+ // load external libs
131+ if( !load_external_modules( this, ".chug", chugin_search_paths, named_dls ) )
132+ goto error;
133+
134+ // pop indent
135+ EM_poplog();
136+
137+ return TRUE;
138+
139+error:
140+ // clean up
141+ this->shutdown();
142+
143+ // pop indent
144+ EM_poplog();
145+
146+ return FALSE;
147+}
148+
149+
150+
151+
152+//-----------------------------------------------------------------------------
153+// name: shutdown()
154+// desc: shutdown the compiler
155+//-----------------------------------------------------------------------------
156+void Chuck_Compiler::shutdown()
157+{
158+ // log
159+ EM_log( CK_LOG_SYSTEM, "shutting down compiler..." ) ;
160+ // push indent
161+ EM_pushlog();
162+
163+ // TODO: free
164+ type_engine_shutdown( env() );
165+ // TODO: check if emitter gets cleaned up
166+ // emit_engine_shutdown( emitter );
167+ emitter = NULL;
168+ code = NULL;
169+ m_auto_depend = FALSE;
170+ m_recent.clear();
171+
172+ for(std::list<Chuck_DLL *>::iterator i = m_dlls.begin();
173+ i != m_dlls.end(); i++)
174+ {
175+ delete (*i);
176+ }
177+
178+ m_dlls.clear();
179+
180+ // pop indent
181+ EM_poplog();
182+}
183+
184+
185+
186+
187+
188+//-----------------------------------------------------------------------------
189+// name: bind()
190+// desc: bind a new type system module, via query function
191+//-----------------------------------------------------------------------------
192+t_CKBOOL Chuck_Compiler::bind( f_ck_query query_func, const std::string & name,
193+ const std::string & nspc )
194+{
195+ // log
196+ EM_log( CK_LOG_SYSTEM, "on-demand binding compiler module '%s'...",
197+ name.c_str() );
198+ // push indent level
199+ EM_pushlog();
200+
201+ // get env
202+ Chuck_Env * env = this->env();
203+ // make context
204+ Chuck_Context * context = type_engine_make_context(
205+ NULL, string("@[bind:") + name + string("]") );
206+ // reset env - not needed since we just created the env
207+ env->reset();
208+ // load it
209+ type_engine_load_context( env, context );
210+
211+ // do it
212+ if( !load_module( this, env, query_func, name.c_str(), nspc.c_str() ) ) goto error;
213+
214+ // clear context
215+ type_engine_unload_context( env );
216+
217+ // commit what is in the type checker at this point
218+ env->global()->commit();
219+
220+ // pop indent level
221+ EM_poplog();
222+
223+ return TRUE;
224+
225+error:
226+
227+ // probably dangerous: rollback
228+ env->global()->rollback();
229+
230+ // clear context
231+ type_engine_unload_context( env );
232+
233+ // pop indent level
234+ EM_poplog();
235+
236+ return FALSE;
237+}
238+
239+
240+
241+
242+//-----------------------------------------------------------------------------
243+// name: set_auto_depend()
244+// desc: auto dependency resolve for types
245+//-----------------------------------------------------------------------------
246+void Chuck_Compiler::set_auto_depend( t_CKBOOL v )
247+{
248+ // log
249+ EM_log( CK_LOG_SYSTEM, "type dependency resolution: %s",
250+ v ? "AUTO" : "MANUAL" );
251+ m_auto_depend = v;
252+}
253+
254+
255+
256+
257+//-----------------------------------------------------------------------------
258+// name: go()
259+// desc: parse, type-check, and emit a program
260+//-----------------------------------------------------------------------------
261+t_CKBOOL Chuck_Compiler::go( const string & filename, FILE * fd, const char * str_src, const string & full_path )
262+{
263+ t_CKBOOL ret = TRUE;
264+ Chuck_Context * context = NULL;
265+
266+ EM_reset_msg();
267+
268+ // check to see if resolve dependencies automatically
269+ if( !m_auto_depend )
270+ {
271+ // normal (note: full_path added 1.3.0.0)
272+ ret = this->do_normal( filename, fd, str_src, full_path );
273+ return ret;
274+ }
275+ else // auto
276+ {
277+ // parse the code
278+ if( !chuck_parse( filename.c_str(), fd, str_src ) )
279+ return FALSE;
280+
281+ // make the context
282+ context = type_engine_make_context( g_program, filename );
283+ if( !context ) return FALSE;
284+
285+ // reset the env
286+ env()->reset();
287+
288+ // load the context
289+ if( !type_engine_load_context( env(), context ) )
290+ return FALSE;
291+
292+ // do entire file
293+ if( !do_entire_file( context ) )
294+ { ret = FALSE; goto cleanup; }
295+
296+ // get the code
297+ if( !(code = context->code()) )
298+ {
299+ ret = FALSE;
300+ EM_error2( 0, "internal error: context->code() NULL!" );
301+ goto cleanup;
302+ }
303+
304+cleanup:
305+
306+ // commit
307+ if( ret ) env()->global()->commit();
308+ // or rollback
309+ else env()->global()->rollback();
310+
311+ // unload the context from the type-checker
312+ if( !type_engine_unload_context( env() ) )
313+ {
314+ EM_error2( 0, "internal error unloading context...\n" );
315+ return FALSE;
316+ }
317+
318+ return ret;
319+ }
320+}
321+
322+
323+
324+
325+//-----------------------------------------------------------------------------
326+// name: resolve()
327+// desc: resolve type automatically - if auto_depend is off, return FALSE
328+//-----------------------------------------------------------------------------
329+t_CKBOOL Chuck_Compiler::resolve( const string & type )
330+{
331+ t_CKBOOL ret = TRUE;
332+
333+ // check auto_depend
334+ if( !m_auto_depend )
335+ return FALSE;
336+
337+ // look up if name is already parsed
338+
339+
340+
341+ return ret;
342+}
343+
344+
345+
346+
347+//-----------------------------------------------------------------------------
348+// name: do_entire_file()
349+// desc: parse, type-check, and emit a program
350+//-----------------------------------------------------------------------------
351+t_CKBOOL Chuck_Compiler::do_entire_file( Chuck_Context * context )
352+{
353+ // 0th-scan (pass 0)
354+ if( !type_engine_scan0_prog( env(), g_program, te_do_all ) )
355+ return FALSE;
356+
357+ // 1st-scan (pass 1)
358+ if( !type_engine_scan1_prog( env(), g_program, te_do_all ) )
359+ return FALSE;
360+
361+ // 2nd-scan (pass 2)
362+ if( !type_engine_scan2_prog( env(), g_program, te_do_all ) )
363+ return FALSE;
364+
365+ // check the program (pass 3)
366+ if( !type_engine_check_context( env(), context, te_do_all ) )
367+ return FALSE;
368+
369+ // emit (pass 4)
370+ if( !emit_engine_emit_prog( emitter, g_program ) )
371+ return FALSE;
372+
373+ // set the state of the context to done
374+ context->progress = Chuck_Context::P_ALL;
375+
376+ return TRUE;
377+}
378+
379+
380+
381+
382+//-----------------------------------------------------------------------------
383+// name: do_only_classes()
384+// desc: compile only classes definitions
385+//-----------------------------------------------------------------------------
386+t_CKBOOL Chuck_Compiler::do_only_classes( Chuck_Context * context )
387+{
388+ // 0th-scan (pass 0)
389+ if( !type_engine_scan0_prog( env(), g_program, te_do_classes_only ) )
390+ return FALSE;
391+
392+ // 1st-scan (pass 1)
393+ if( !type_engine_scan1_prog( env(), g_program, te_do_classes_only ) )
394+ return FALSE;
395+
396+ // 2nd-scan (pass 2)
397+ if( !type_engine_scan2_prog( env(), g_program, te_do_classes_only ) )
398+ return FALSE;
399+
400+ // check the program (pass 3)
401+ if( !type_engine_check_context( env(), context, te_do_classes_only ) )
402+ return FALSE;
403+
404+ // emit (pass 4)
405+ if( !(code = emit_engine_emit_prog( emitter, g_program , te_do_classes_only )) )
406+ return FALSE;
407+
408+ // set the state of the context to done
409+ context->progress = Chuck_Context::P_ALL;
410+
411+ return TRUE;
412+}
413+
414+
415+
416+
417+//-----------------------------------------------------------------------------
418+// name: do_all_except_classes()
419+// desc: compile everything except classes
420+//-----------------------------------------------------------------------------
421+t_CKBOOL Chuck_Compiler::do_all_except_classes( Chuck_Context * context )
422+{
423+ // 0th scan only deals with classes, so is not needed
424+
425+ // 1st-scan (pass 1)
426+ if( !type_engine_scan1_prog( env(), g_program, te_do_no_classes ) )
427+ return FALSE;
428+
429+ // 2nd-scan (pass 2)
430+ if( !type_engine_scan2_prog( env(), g_program, te_do_no_classes ) )
431+ return FALSE;
432+
433+ // check the program (pass 3)
434+ if( !type_engine_check_context( env(), context, te_do_no_classes ) )
435+ return FALSE;
436+
437+ // emit (pass 4)
438+ if( !(code = emit_engine_emit_prog( emitter, g_program, te_do_no_classes )) )
439+ return FALSE;
440+
441+ // set the state of the context to done
442+ context->progress = Chuck_Context::P_ALL;
443+
444+ return TRUE;
445+}
446+
447+
448+
449+
450+//-----------------------------------------------------------------------------
451+// name: do_normal()
452+// desc: compile normally without auto-depend
453+//-----------------------------------------------------------------------------
454+t_CKBOOL Chuck_Compiler::do_normal( const string & filename, FILE * fd, const char * str_src, const string & full_path )
455+{
456+ t_CKBOOL ret = TRUE;
457+ Chuck_Context * context = NULL;
458+
459+ // parse the code
460+ if( !chuck_parse( filename.c_str(), fd, str_src ) )
461+ return FALSE;
462+
463+ // make the context
464+ context = type_engine_make_context( g_program, filename );
465+ if( !context ) return FALSE;
466+
467+ // remember full path (added 1.3.0.0)
468+ context->full_path = full_path;
469+
470+ // reset the env
471+ env()->reset();
472+
473+ // load the context
474+ if( !type_engine_load_context( env(), context ) )
475+ return FALSE;
476+
477+ // 0th-scan (pass 0)
478+ if( !type_engine_scan0_prog( env(), g_program, te_do_all ) )
479+ { ret = FALSE; goto cleanup; }
480+
481+ // 1st-scan (pass 1)
482+ if( !type_engine_scan1_prog( env(), g_program, te_do_all ) )
483+ { ret = FALSE; goto cleanup; }
484+
485+ // 2nd-scan (pass 2)
486+ if( !type_engine_scan2_prog( env(), g_program, te_do_all ) )
487+ { ret = FALSE; goto cleanup; }
488+
489+ // check the program (pass 3)
490+ if( !type_engine_check_context( env(), context, te_do_all ) )
491+ { ret = FALSE; goto cleanup; }
492+
493+ // emit (pass 4)
494+ if( !(code = emit_engine_emit_prog( emitter, g_program, te_do_all )) )
495+ { ret = FALSE; goto cleanup; }
496+
497+cleanup:
498+
499+ // commit
500+ if( ret ) env()->global()->commit();
501+ // or rollback
502+ else env()->global()->rollback();
503+
504+ // unload the context from the type-checker
505+ if( !type_engine_unload_context( env() ) )
506+ {
507+ EM_error2( 0, "internal error unloading context...\n" );
508+ return FALSE;
509+ }
510+
511+ return ret;
512+}
513+
514+
515+
516+
517+//-----------------------------------------------------------------------------
518+// name: find_recent_path()
519+// desc: find recent context by path
520+//-----------------------------------------------------------------------------
521+Chuck_Context * Chuck_Compiler::find_recent_path( const string & path )
522+{
523+ return NULL;
524+}
525+
526+
527+
528+
529+//-----------------------------------------------------------------------------
530+// name: find_recent_type()
531+// desc: find recent context by type name
532+//-----------------------------------------------------------------------------
533+Chuck_Context * Chuck_Compiler::find_recent_type( const string & type )
534+{
535+ return NULL;
536+}
537+
538+
539+
540+
541+//-----------------------------------------------------------------------------
542+// name: add_recent_path()
543+// desc: add recent context by path
544+//-----------------------------------------------------------------------------
545+t_CKBOOL Chuck_Compiler::add_recent_path( const string & path,
546+ Chuck_Context * context )
547+{
548+ return TRUE;
549+}
550+
551+
552+
553+
554+//-----------------------------------------------------------------------------
555+// name: output()
556+// desc: get the code generated by the last do()
557+//-----------------------------------------------------------------------------
558+Chuck_VM_Code * Chuck_Compiler::output()
559+{
560+ return this->code;
561+}
562+
563+
564+
565+
566+//-----------------------------------------------------------------------------
567+// name: load_module()
568+// desc: load a dll and add it
569+//-----------------------------------------------------------------------------
570+t_CKBOOL load_module( Chuck_Compiler * compiler, Chuck_Env * env, f_ck_query query,
571+ const char * name, const char * nspc )
572+{
573+ Chuck_DLL * dll = NULL;
574+ t_CKBOOL query_failed = FALSE;
575+
576+ // load osc
577+ dll = new Chuck_DLL( compiler->carrier(), name );
578+ // (fixed: 1.3.0.0) query_failed now catches either failure of load or query
579+ if( (query_failed = !(dll->load( query ) && dll->query())) ||
580+ !type_engine_add_dll( env, dll, nspc ) )
581+ {
582+ CK_FPRINTF_STDERR(
583+ "[chuck]: internal error loading module '%s.%s'...\n",
584+ nspc, name );
585+ if( query_failed )
586+ CK_FPRINTF_STDERR( " %s", dll->last_error() );
587+
588+ return FALSE;
589+ }
590+
591+ return TRUE;
592+}
593+
594+
595+
596+
597+//-----------------------------------------------------------------------------
598+// name: load_internal_modules()
599+// desc: ...
600+//-----------------------------------------------------------------------------
601+t_CKBOOL load_internal_modules( Chuck_Compiler * compiler )
602+{
603+ // log
604+ EM_log( CK_LOG_SEVERE, "loading built-in modules..." );
605+ // push indent level
606+ EM_pushlog();
607+
608+ // get env
609+ Chuck_Env * env = compiler->env();
610+ // make context
611+ Chuck_Context * context = type_engine_make_context( NULL, "@[internal]" );
612+ // reset env - not needed since we just created the env
613+ env->reset();
614+ // load it
615+ type_engine_load_context( env, context );
616+
617+//#ifndef __DISABLE_MIDI__
618+ if( !init_class_Midi( env ) ) goto error;
619+ if( !init_class_MidiRW( env ) ) goto error;
620+//#endif // __DISABLE_MIDI__
621+
622+ // load
623+ EM_log( CK_LOG_SEVERE, "module osc..." );
624+ load_module( compiler, env, osc_query, "osc", "global" );
625+ EM_log( CK_LOG_SEVERE, "module xxx..." );
626+ load_module( compiler, env, xxx_query, "xxx", "global" );
627+ EM_log( CK_LOG_SEVERE, "module filter..." );
628+ load_module( compiler, env, filter_query, "filter", "global" );
629+ EM_log( CK_LOG_SEVERE, "module STK..." );
630+ load_module( compiler, env, stk_query, "stk", "global" );
631+ EM_log( CK_LOG_SEVERE, "module xform..." );
632+ load_module( compiler, env, xform_query, "xform", "global" );
633+ EM_log( CK_LOG_SEVERE, "module extract..." );
634+ load_module( compiler, env, extract_query, "extract", "global" );
635+
636+ // load
637+ EM_log( CK_LOG_SEVERE, "class 'machine'..." );
638+ if( !load_module( compiler, env, machine_query, "Machine", "global" ) ) goto error;
639+ machine_init( compiler, otf_process_msg );
640+ EM_log( CK_LOG_SEVERE, "class 'std'..." );
641+ if( !load_module( compiler, env, libstd_query, "Std", "global" ) ) goto error;
642+ EM_log( CK_LOG_SEVERE, "class 'math'..." );
643+ if( !load_module( compiler, env, libmath_query, "Math", "global" ) ) goto error;
644+
645+// ge: these currently don't compile on "modern" windows versions (1.3.5.3)
646+#ifndef __WINDOWS_MODERN__
647+ EM_log( CK_LOG_SEVERE, "class 'opsc'..." );
648+ if( !load_module( compiler, env, opensoundcontrol_query, "opsc", "global" ) ) goto error;
649+#endif
650+ EM_log( CK_LOG_SEVERE, "class 'RegEx'..." );
651+ if( !load_module( compiler, env, regex_query, "RegEx", "global" ) ) goto error;
652+ // if( !load_module( compiler, env, net_query, "net", "global" ) ) goto error;
653+
654+ if( !init_class_HID( env ) ) goto error;
655+ if( !init_class_serialio( env ) ) goto error;
656+
657+ // clear context
658+ type_engine_unload_context( env );
659+
660+ // commit what is in the type checker at this point
661+ env->global()->commit();
662+
663+ // pop indent level
664+ EM_poplog();
665+
666+ return TRUE;
667+
668+error:
669+
670+ // probably dangerous: rollback
671+ env->global()->rollback();
672+
673+ // clear context
674+ type_engine_unload_context( env );
675+
676+ // pop indent level
677+ EM_poplog();
678+
679+ return FALSE;
680+}
681+
682+
683+
684+//-----------------------------------------------------------------------------
685+// name: load_external_module_at_path()
686+// desc: ...
687+//-----------------------------------------------------------------------------
688+t_CKBOOL load_external_module_at_path( Chuck_Compiler * compiler,
689+ const char * name,
690+ const char * dl_path )
691+{
692+ Chuck_Env * env = compiler->env();
693+
694+ EM_log(CK_LOG_SEVERE, "loading chugin '%s'", name);
695+
696+ Chuck_DLL * dll = new Chuck_DLL( compiler->carrier(), name );
697+ t_CKBOOL query_failed = FALSE;
698+
699+ if((query_failed = !(dll->load(dl_path) && dll->query())) ||
700+ !type_engine_add_dll2(env, dll, "global"))
701+ {
702+ EM_log(CK_LOG_SEVERE, "error loading chugin '%s', skipping", name);
703+ if(query_failed)
704+ EM_log(CK_LOG_SEVERE, "error from chuck_dl: '%s'", dll->last_error());
705+ delete dll;
706+
707+ return FALSE;
708+ }
709+ else
710+ {
711+ compiler->m_dlls.push_back(dll);
712+ return TRUE;
713+ }
714+}
715+
716+
717+
718+
719+//-----------------------------------------------------------------------------
720+// name: extension_matches()
721+// desc: ...
722+//-----------------------------------------------------------------------------
723+static t_CKBOOL extension_matches( const char * filename, const char * extension )
724+{
725+ t_CKUINT extension_length = strlen(extension);
726+ t_CKUINT filename_length = strlen(filename);
727+
728+ return strncmp( extension, filename+(filename_length-extension_length),
729+ extension_length) == 0;
730+}
731+
732+
733+
734+
735+//-----------------------------------------------------------------------------
736+// name: load_external_modules_in_directory()
737+// desc: ...
738+//-----------------------------------------------------------------------------
739+t_CKBOOL load_external_modules_in_directory( Chuck_Compiler * compiler,
740+ const char * directory,
741+ const char * extension )
742+{
743+ static const t_CKBOOL RECURSIVE_SEARCH = false;
744+
745+ DIR * dir = opendir(directory);
746+
747+ if( dir )
748+ {
749+ // log
750+ EM_log( CK_LOG_INFO, "examining directory '%s' for chugins", directory );
751+
752+ struct dirent *de = NULL;
753+
754+ while( (de = readdir(dir)) )
755+ {
756+ t_CKBOOL is_regular = false;
757+ t_CKBOOL is_directory = false;
758+
759+#if defined(__PLATFORM_WIN32__)
760+ is_directory = de->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
761+ is_regular = ((de->data.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) ||
762+ (de->data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ||
763+ (de->data.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE));
764+#elif defined(__WINDOWS_PTHREAD__) // Cygwin -- doesn't have dirent d_type
765+ std::string absolute_path = std::string(directory) + "/" + de->d_name;
766+ struct stat st;
767+ if( stat(absolute_path.c_str(), &st) == 0 )
768+ {
769+ is_directory = st.st_mode & S_IFDIR;
770+ is_regular = st.st_mode & S_IFREG;
771+ }
772+ else
773+ {
774+ // uhh ...
775+ EM_log( CK_LOG_INFO,
776+ "unable to stat file '%s', ignoring for chugins",
777+ absolute_path.c_str() );
778+ continue;
779+ }
780+#else
781+ is_directory = de->d_type == DT_DIR;
782+ is_regular = de->d_type == DT_REG;
783+#endif
784+
785+ if( is_regular ) // TODO: follow links?
786+ {
787+ if( extension_matches(de->d_name, extension) )
788+ {
789+ std::string absolute_path = std::string(directory) + "/" + de->d_name;
790+
791+ load_external_module_at_path(compiler, de->d_name,
792+ absolute_path.c_str());
793+ }
794+ else if( extension_matches(de->d_name, ".ck") )
795+ {
796+ std::string absolute_path = std::string(directory) + "/" + de->d_name;
797+ compiler->m_cklibs_to_preload.push_back(absolute_path);
798+ }
799+ }
800+ else if( RECURSIVE_SEARCH && is_directory )
801+ {
802+ // recurse
803+ // TODO: max depth?
804+ if( strncmp(de->d_name, ".", sizeof(".")) != 0 &&
805+ strncmp(de->d_name, "..", sizeof("..")) != 0 )
806+ {
807+ std::string absolute_path = std::string(directory) + "/" + de->d_name;
808+ load_external_modules_in_directory(compiler,
809+ absolute_path.c_str(),
810+ extension);
811+ }
812+ }
813+ }
814+
815+ // close
816+ closedir( dir );
817+ }
818+ else
819+ {
820+ // log (1.3.1.2: changed to 2 lines to stay within 80 chars)
821+ EM_log( CK_LOG_INFO, "unable to open directory '%s'...", directory );
822+ EM_log( CK_LOG_INFO, "(ignoring for chugins...)" );
823+ }
824+
825+ return TRUE;
826+}
827+
828+
829+
830+
831+//-----------------------------------------------------------------------------
832+// name: load_external_modules()
833+// desc: ...
834+//-----------------------------------------------------------------------------
835+t_CKBOOL load_external_modules( Chuck_Compiler * compiler,
836+ const char * extension,
837+ std::list<std::string> & chugin_search_paths,
838+ std::list<std::string> & named_dls )
839+{
840+ // log
841+ EM_log( CK_LOG_SEVERE, "loading chugins" );
842+ // push indent level
843+ EM_pushlog();
844+
845+ // get env
846+ Chuck_Env * env = compiler->env();
847+ // make context
848+ Chuck_Context * context = type_engine_make_context( NULL, "@[external]" );
849+ // reset env - not needed since we just created the env
850+ env->reset();
851+ // load it
852+ type_engine_load_context( env, context );
853+
854+ /* first load dynamic libraries explicitly named on the command line */
855+
856+ for(std::list<std::string>::iterator i_dl = named_dls.begin();
857+ i_dl != named_dls.end(); i_dl++)
858+ {
859+ std::string & dl_path = *i_dl;
860+ if(!extension_matches(dl_path.c_str(), extension))
861+ dl_path += extension;
862+
863+ load_external_module_at_path(compiler, dl_path.c_str(),
864+ dl_path.c_str());
865+ }
866+
867+ /* now recurse through search paths and load any DLs or .ck files found */
868+
869+ for(std::list<std::string>::iterator i_sp = chugin_search_paths.begin();
870+ i_sp != chugin_search_paths.end(); i_sp++)
871+ {
872+ load_external_modules_in_directory(compiler, (*i_sp).c_str(), extension);
873+ }
874+
875+ // clear context
876+ type_engine_unload_context( env );
877+
878+ // commit what is in the type checker at this point
879+ env->global()->commit();
880+
881+ // pop indent level
882+ EM_poplog();
883+
884+ return TRUE;
885+ /*
886+error:
887+
888+ // probably dangerous: rollback
889+ env->global()->rollback();
890+
891+ // clear context
892+ type_engine_unload_context( env );
893+
894+ // pop indent level
895+ EM_poplog();
896+
897+ return FALSE;
898+ */
899+}
900+
core/chuck_compile.h+138−0
@@ -0,0 +1,138 @@
1+/*----------------------------------------------------------------------------
2+ ChucK Concurrent, On-the-fly Audio Programming Language
3+ Compiler and Virtual Machine
4+
5+ Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6+ http://chuck.stanford.edu/
7+ http://chuck.cs.princeton.edu/
8+
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.
13+
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.
18+
19+ You should have received a copy of the GNU General Public License
20+ along with this program; if not, write to the Free Software
21+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22+ U.S.A.
23+-----------------------------------------------------------------------------*/
24+
25+//-----------------------------------------------------------------------------
26+// file: chuck_compile.h
27+// desc: chuck compile system unifying parser, type checker, and emitter
28+//
29+// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
30+// date: Autumn 2005 - original
31+//-----------------------------------------------------------------------------
32+#ifndef __CHUCK_COMPILE_H__
33+#define __CHUCK_COMPILE_H__
34+
35+#include "chuck_def.h"
36+#include "chuck_parse.h"
37+#include "chuck_scan.h"
38+#include "chuck_type.h"
39+#include "chuck_emit.h"
40+#include "chuck_vm.h"
41+#include <list>
42+
43+
44+// forward reference
45+struct Chuck_DLL;
46+
47+
48+
49+
50+//-----------------------------------------------------------------------------
51+// name: struct Chuck_Compiler
52+// desc: the sum of the components in compilation
53+//-----------------------------------------------------------------------------
54+struct Chuck_Compiler
55+{
56+protected: // data
57+ // carrier
58+ Chuck_Carrier * m_carrier;
59+
60+public: // get protected data
61+ // REFACTOR-2017: get associated, per-compiler environment
62+ Chuck_Env * env() const { return m_carrier->env; }
63+ // REFACTOR-2017: get associated, per-compiler VM
64+ Chuck_VM * vm() const { return m_carrier->vm; }
65+ // REFACTOR-2017: get associated, per-compiler carrier
66+ Chuck_Carrier * carrier() const { return m_carrier; }
67+ // set carrier
68+ t_CKBOOL setCarrier( Chuck_Carrier * c ) { m_carrier = c; return TRUE; }
69+
70+
71+public: // data
72+ // emitter
73+ Chuck_Emitter * emitter;
74+ // generated code
75+ Chuck_VM_Code * code;
76+
77+ // auto-depend flag
78+ t_CKBOOL m_auto_depend;
79+ // recent map
80+ std::map<std::string, Chuck_Context *> m_recent;
81+
82+ std::list<Chuck_DLL *> m_dlls;
83+ std::list<std::string> m_cklibs_to_preload;
84+
85+public: // to all
86+ // contructor
87+ Chuck_Compiler();
88+ // destructor
89+ virtual ~Chuck_Compiler();
90+
91+ // initialize
92+ t_CKBOOL initialize( std::list<std::string> & chugin_search_paths,
93+ std::list<std::string> & named_dls );
94+ // shutdown
95+ void shutdown();
96+
97+public: // additional binding
98+ // bind a new type system module, via query function
99+ t_CKBOOL bind( f_ck_query query_func, const std::string & name,
100+ const std::string & nspc = "global" );
101+
102+public: // compile
103+ // set auto depend
104+ void set_auto_depend( t_CKBOOL v );
105+ // parse, type-check, and emit a program
106+ t_CKBOOL go( const std::string & filename, FILE * fd = NULL,
107+ const char * str_src = NULL, const std::string & full_path = "" );
108+ // resolve a type automatically, if auto_depend is on
109+ t_CKBOOL resolve( const std::string & type );
110+ // get the code generated from the last go()
111+ Chuck_VM_Code * output( );
112+
113+protected: // internal
114+ // do entire file
115+ t_CKBOOL do_entire_file( Chuck_Context * context );
116+ // do just class definitions
117+ t_CKBOOL do_only_classes( Chuck_Context * context );
118+ // do all excect classes
119+ t_CKBOOL do_all_except_classes( Chuck_Context * context );
120+ // do normal compile
121+ t_CKBOOL do_normal( const std::string & path, FILE * fd = NULL,
122+ const char * str_src = NULL, const std::string & full_path = "" );
123+ // look up in recent
124+ Chuck_Context * find_recent_path( const std::string & path );
125+ // look up in recent
126+ Chuck_Context * find_recent_type( const std::string & type );
127+ // add to recent
128+ t_CKBOOL add_recent_path( const std::string & path, Chuck_Context * context );
129+};
130+
131+
132+// call this to detach all open files
133+extern "C" void all_detach();
134+
135+
136+
137+
138+#endif
core/chuck_def.h+203−0
@@ -0,0 +1,203 @@
1+/*----------------------------------------------------------------------------
2+ ChucK Concurrent, On-the-fly Audio Programming Language
3+ Compiler and Virtual Machine
4+
5+ Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6+ http://chuck.stanford.edu/
7+ http://chuck.cs.princeton.edu/
8+
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.
13+
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.
18+
19+ You should have received a copy of the GNU General Public License
20+ along with this program; if not, write to the Free Software
21+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22+ U.S.A.
23+-----------------------------------------------------------------------------*/
24+
25+//-----------------------------------------------------------------------------
26+// file: chuck_def.h
27+// desc: ChucK defines for the system
28+//
29+// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
30+// Perry R. Cook (prc@cs.princeton.edu)
31+// date: Autumn 2002
32+//-----------------------------------------------------------------------------
33+#ifndef __CHUCK_DEF_H__
34+#define __CHUCK_DEF_H__
35+
36+#include <stdlib.h>
37+#include <memory.h>
38+#include <assert.h>
39+
40+
41+// types
42+#define t_CKTIME double
43+#define t_CKDUR double
44+#define t_CKFLOAT double
45+#define t_CKDOUBLE double
46+#define t_CKSINGLE float
47+#ifdef _WIN64 // REFACTOR-2017
48+#define t_CKINT long long // REFACTOR-2017
49+#else
50+#define t_CKINT long
51+#endif
52+#define t_CKUINT unsigned t_CKINT
53+#define t_CKBOOL unsigned t_CKINT
54+#define t_CKBYTE unsigned char
55+#define t_CKVOID void
56+#define t_CKVOIDPTR void *
57+
58+// complex type
59+typedef struct { t_CKFLOAT re ; t_CKFLOAT im ; } t_CKCOMPLEX;
60+// polar type
61+typedef struct { t_CKFLOAT modulus ; t_CKFLOAT phase ; } t_CKPOLAR;
62+
63+// vector types
64+typedef struct { t_CKFLOAT x ; t_CKFLOAT y ; t_CKFLOAT z ; } t_CKVEC3;
65+typedef struct { t_CKFLOAT x ; t_CKFLOAT y ; t_CKFLOAT z ; t_CKFLOAT w ; } t_CKVEC4;
66+typedef struct { t_CKUINT N ; t_CKFLOAT * values ; } t_CKVECTOR;
67+
68+// size
69+#define sz_TIME sizeof(t_CKTIME)
70+#define sz_DUR sizeof(t_CKDUR)
71+#define sz_FLOAT sizeof(t_CKFLOAT)
72+#define sz_DOUBLE sizeof(t_CKDOUBLE)
73+#define sz_SINGLE sizeof(t_CKSINGLE)
74+#define sz_INT sizeof(t_CKINT)
75+#define sz_UINT sizeof(t_CKUINT)
76+#define sz_BOOL sizeof(t_CKBOOL)
77+#define sz_BYTE sizeof(t_CKBYTE)
78+#define sz_VOIDPTR sizeof(t_CKVOIDPTR)
79+#define sz_COMPLEX sizeof(t_CKCOMPLEX)
80+#define sz_POLAR sizeof(t_CKPOLAR)
81+#define sz_VEC3 sizeof(t_CKVEC3)
82+#define sz_VEC4 sizeof(t_CKVEC4)
83+#define sz_VECTOR sizeof(t_CKVECTOR)
84+#define sz_VOID 0
85+#define sz_WORD 4
86+
87+// kinds (added 1.3.1.0 to faciliate 64-bit support)
88+// to differentiate in case int and float have same size
89+#define kindof_VOID 0
90+#define kindof_INT 1
91+#define kindof_FLOAT 2
92+#define kindof_COMPLEX 3
93+#define kindof_VEC3 4
94+#define kindof_VEC4 5
95+
96+typedef char * c_str;
97+typedef const char * c_constr;
98+
99+// use 64-bit samples in the audio engine
100+// #define __CHUCK_USE_64_BIT_SAMPLE__
101+
102+// sample
103+#ifdef __CHUCK_USE_64_BIT_SAMPLE__
104+#define SAMPLE double
105+#define SILENCE 0.0
106+#define CK_DDN CK_DDN_DOUBLE
107+#else
108+#define SAMPLE float
109+#define SILENCE 0.0f
110+#define CK_DDN CK_DDN_SINGLE
111+#endif
112+
113+// for external use
114+#define t_CKSAMPLE SAMPLE
115+
116+// sample complex
117+typedef struct { SAMPLE re ; SAMPLE im ; } t_CKCOMPLEX_SAMPLE;
118+
119+// bool
120+#ifndef TRUE
121+#define TRUE 1
122+#define FALSE 0
123+#endif
124+
125+// 3.1415926535897932384626433832795028841971693993751058209749445...
126+#define ONE_PI (3.14159265358979323846)
127+#define TWO_PI (2.0 * ONE_PI)
128+#define SQRT2 (1.41421356237309504880)
129+
130+#ifndef SAFE_DELETE
131+#define SAFE_DELETE(x) do { if(x){ delete x; x = NULL; } } while(0)
132+#define SAFE_DELETE_ARRAY(x) do { if(x){ delete [] x; x = NULL; } } while(0)
133+#define SAFE_RELEASE(x) do { if(x){ x->release(); x = NULL; } } while(0)
134+#define SAFE_ADD_REF(x) do { if(x){ x->add_ref(); } } while(0)
135+#define SAFE_REF_ASSIGN(lhs,rhs) do { SAFE_RELEASE(lhs); (lhs) = (rhs); SAFE_ADD_REF(lhs); } while(0)
136+#endif
137+
138+// max + min
139+#define ck_max(x,y) ( (x) >= (y) ? (x) : (y) )
140+#define ck_min(x,y) ( (x) <= (y) ? (x) : (y) )
141+
142+#ifndef __arm__
143+// dedenormal
144+#define CK_DDN_SINGLE(f) f = ( f >= 0 ? \
145+ ( ( f > (t_CKSINGLE)1e-15 && f < (t_CKSINGLE)1e15 ) ? f : (t_CKSINGLE)0.0 ) : \
146+ ( ( f < (t_CKSINGLE)-1e-15 && f > (t_CKSINGLE)-1e15 ) ? f : (t_CKSINGLE)0.0 ) )
147+#define CK_DDN_DOUBLE(f) f = ( f >= 0 ? \
148+ ( ( f > (t_CKDOUBLE)1e-15 && f < (t_CKDOUBLE)1e15 ) ? f : 0.0 ) : \
149+ ( ( f < (t_CKDOUBLE)-1e-15 && f > (t_CKDOUBLE)-1e15 ) ? f : 0.0 ) )
150+#else
151+#define CK_DDN_SINGLE(f) (f)
152+#define CK_DDN_DOUBLE(f) (f)
153+#endif // __arm__
154+
155+// tracking
156+#if defined(__CHUCK_STAT_TRACK__)
157+#define CK_TRACK( stmt ) stmt
158+#else
159+#define CK_TRACK( stmt )
160+#endif
161+
162+#ifdef __MACOSX_CORE__
163+#define __PLATFORM_MACOSX__
164+#endif
165+
166+#if defined(__LINUX_ALSA__) || defined(__LINUX_JACK__) || defined(__LINUX_OSS__) || defined(__LINUX_PULSE__) || defined(__UNIX_JACK__)
167+// defined by default in Linux makefiles
168+//#define __PLATFORM_LINUX__
169+#endif
170+
171+#ifdef __PLATFORM_WIN32__
172+#ifndef usleep
173+#define usleep(x) Sleep( (x / 1000 <= 0 ? 1 : x / 1000) )
174+#endif
175+#pragma warning (disable : 4996) // stdio deprecation
176+#pragma warning (disable : 4786) // stl debug info
177+#pragma warning (disable : 4312) // type casts from void*
178+#pragma warning (disable : 4311) // type casts to void*
179+#pragma warning (disable : 4244) // truncation
180+#pragma warning (disable : 4068) // unknown pragma
181+#pragma warning (disable : 4018) // signed/unsigned mismatch
182+#endif
183+
184+#ifdef __CHIP_MODE__
185+#define __DISABLE_MIDI__
186+//#define __DISABLE_SNDBUF__
187+#define __DISABLE_WATCHDOG__
188+#define __DISABLE_RAW__
189+#define __DISABLE_KBHIT__
190+#define __DISABLE_PROMPTER__
191+#define __DISABLE_RTAUDIO__
192+#define __DISABLE_OTF_SERVER__
193+#define __ALTER_HID__
194+#define __ALTER_ENTRY_POINT__
195+#define __STK_USE_SINGLE_PRECISION__
196+#endif
197+
198+#ifdef __arm__
199+// enable additional optimization
200+#define __STK_USE_SINGLE_PRECISION__
201+#endif // __arm__
202+
203+#endif
core/chuck_dl.cpp+1210−0
@@ -0,0 +1,1210 @@
1+/*----------------------------------------------------------------------------
2+ ChucK Concurrent, On-the-fly Audio Programming Language
3+ Compiler and Virtual Machine
4+
5+ Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6+ http://chuck.stanford.edu/
7+ http://chuck.cs.princeton.edu/
8+
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.
13+
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.
18+
19+ You should have received a copy of the GNU General Public License
20+ along with this program; if not, write to the Free Software
21+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22+ U.S.A.
23+-----------------------------------------------------------------------------*/
24+
25+//-----------------------------------------------------------------------------
26+// name: chuck_dl.cpp
27+// desc: chuck dynamic linking header
28+//
29+// authors: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
30+// Ari Lazier (alazier@cs.princeton.edu)
31+// Spencer Salazar (spencer@ccrma.stanford.edu)
32+// mac os code based on apple's open source
33+//
34+// date: spring 2004 - 1.1
35+// spring 2005 - 1.2
36+//-----------------------------------------------------------------------------
37+#include "chuck_dl.h"
38+#include "chuck_errmsg.h"
39+#include "chuck_bbq.h"
40+#include "chuck_type.h"
41+#include "chuck_instr.h"
42+#include "chuck_globals.h"
43+#include "chuck_compile.h"
44+#include "chuck_vm.h"
45+#include <sstream>
46+using namespace std;
47+
48+
49+
50+
51+#if defined(__MACOSX_CORE__)
52+char g_default_chugin_path[] = "/usr/local/lib/chuck:/Library/Application Support/ChucK/ChuGins:~/Library/Application Support/ChucK/ChuGins";
53+#elif defined(__PLATFORM_WIN32__)
54+char g_default_chugin_path[] = "C:\\WINDOWS\\system32\\ChucK;C:\\Program Files\\ChucK\\chugins;C:\\Program Files (x86)\\ChucK\\chugins";
55+#else // Linux/Cygwin
56+char g_default_chugin_path[] = "/usr/local/lib/chuck";
57+#endif
58+
59+char g_chugin_path_envvar[] = "CHUCK_CHUGIN_PATH";
60+
61+
62+
63+
64+//-----------------------------------------------------------------------------
65+// internal implementation of query functions
66+//-----------------------------------------------------------------------------
67+
68+
69+
70+t_CKUINT ck_builtin_declversion() { return CK_DLL_VERSION; }
71+
72+
73+
74+//-----------------------------------------------------------------------------
75+// name: ck_setname()
76+// desc: set the name of the module
77+//-----------------------------------------------------------------------------
78+void CK_DLL_CALL ck_setname( Chuck_DL_Query * query, const char * name )
79+{
80+ // set the name
81+ query->dll_name = name;
82+}
83+
84+
85+
86+
87+//-----------------------------------------------------------------------------
88+// name: ck_begin_class()
89+// desc: begin class/namespace, can be nexted
90+//-----------------------------------------------------------------------------
91+void CK_DLL_CALL ck_begin_class( Chuck_DL_Query * query, const char * name, const char * parent )
92+{
93+ // find parent mvar offset
94+ t_CKINT parent_offset = 0;
95+ if(parent && parent[0] != '\0')
96+ {
97+ a_Id_List parent_path = str2list( parent );
98+ if( !parent_path )
99+ {
100+ // error
101+ EM_error2( 0, "class import: ck_begin_class: unknown parent type '%s'",
102+ query->curr_class->name.c_str(), name, parent );
103+ return;
104+ }
105+
106+ Chuck_Type * ck_parent_type = type_engine_find_type( query->env(), parent_path );
107+
108+ delete_id_list( parent_path );
109+
110+ if( !ck_parent_type )
111+ {
112+ // error
113+ EM_error2( 0, "class import: ck_begin_class: unable to find parent type '%s'", ck_parent_type );
114+ return;
115+ }
116+
117+ parent_offset = ck_parent_type->obj_size;
118+ }
119+
120+ // push
121+ query->stack.push_back( query->curr_class );
122+ // allocate
123+ Chuck_DL_Class * c = new Chuck_DL_Class;
124+
125+ // add class
126+ if( query->curr_class )
127+ // recursive
128+ query->curr_class->classes.push_back( c );
129+ // 1.3.2.0: do not save class for later import (will import it on class close)
130+// else
131+// // first level
132+// query->classes.push_back( c );
133+
134+ // remember info
135+ c->name = name;
136+ c->parent = parent;
137+ c->current_mvar_offset = parent_offset;
138+
139+ // curr
140+ query->curr_class = c;
141+ query->curr_func = NULL;
142+}
143+
144+
145+
146+
147+//-----------------------------------------------------------------------------
148+// name: ck_add_ctor()
149+// desc: add constructor, can be followed by add_arg
150+//-----------------------------------------------------------------------------
151+void CK_DLL_CALL ck_add_ctor( Chuck_DL_Query * query, f_ctor ctor )
152+{
153+ // make sure there is class
154+ if( !query->curr_class )
155+ {
156+ // error
157+ EM_error2( 0, "class import: add_ctor invoked without begin_class..." );
158+ return;
159+ }
160+
161+ // allocate
162+ Chuck_DL_Func * f = new Chuck_DL_Func;
163+ f->name = "[ctor]";
164+ f->type = "void";
165+ f->ctor = ctor;
166+
167+ // add
168+ query->curr_class->ctors.push_back( f );
169+ query->curr_func = f;
170+}
171+
172+
173+
174+
175+//-----------------------------------------------------------------------------
176+// name: ck_add_dtor()
177+// add destructor, no args allowed
178+//-----------------------------------------------------------------------------
179+void CK_DLL_CALL ck_add_dtor( Chuck_DL_Query * query, f_dtor dtor )
180+{
181+ // make sure there is class
182+ if( !query->curr_class )
183+ {
184+ // error
185+ EM_error2( 0, "class import: add_dtor invoked without begin_class..." );
186+ return;
187+ }
188+
189+ // make sure there are no duplicates
190+ if( query->curr_class->dtor )
191+ {
192+ // error
193+ EM_error2( 0, "class import: multiple dtor added ..." );
194+ return;
195+ }
196+
197+ // allocate
198+ Chuck_DL_Func * f = new Chuck_DL_Func;
199+ f->name = "[dtor]";
200+ f->type = "void";
201+ f->dtor = dtor;
202+
203+ // add
204+ query->curr_class->dtor = f;
205+ // set
206+ query->curr_func = NULL;
207+}
208+
209+
210+
211+
212+//-----------------------------------------------------------------------------
213+// name: ck_add_mfun()
214+// desc: add member function, can be followed by add_arg
215+//-----------------------------------------------------------------------------
216+void CK_DLL_CALL ck_add_mfun( Chuck_DL_Query * query, f_mfun addr,
217+ const char * type, const char * name )
218+{
219+ // make sure there is class
220+ if( !query->curr_class )
221+ {
222+ // error
223+ EM_error2( 0, "class import: add_mfun invoked without begin_class..." );
224+ return;
225+ }
226+
227+ // allocate
228+ Chuck_DL_Func * f = new Chuck_DL_Func;
229+ f->name = name;
230+ f->type = type;
231+ f->mfun = addr;
232+
233+ // add
234+ query->curr_class->mfuns.push_back( f );
235+ query->curr_func = f;
236+}
237+
238+
239+
240+
241+//-----------------------------------------------------------------------------
242+// name: ck_add_sfun()
243+// desc: add static function, can be followed by add_arg
244+//-----------------------------------------------------------------------------
245+void CK_DLL_CALL ck_add_sfun( Chuck_DL_Query * query, f_sfun addr,
246+ const char * type, const char * name )
247+{
248+ // make sure there is class
249+ if( !query->curr_class )
250+ {
251+ // error
252+ EM_error2( 0, "class import: add_sfun invoked without begin_class..." );
253+ return;
254+ }
255+
256+ // allocate
257+ Chuck_DL_Func * f = new Chuck_DL_Func;
258+ f->name = name;
259+ f->type = type;
260+ f->sfun = addr;
261+
262+ // add
263+ query->curr_class->sfuns.push_back( f );
264+ query->curr_func = f;
265+}
266+
267+
268+
269+
270+//-----------------------------------------------------------------------------
271+// name: ck_add_mvar()
272+// desc: add member var
273+//-----------------------------------------------------------------------------
274+t_CKUINT CK_DLL_CALL ck_add_mvar( Chuck_DL_Query * query,
275+ const char * type, const char * name,
276+ t_CKBOOL is_const )
277+{
278+ // make sure there is class
279+ if( !query->curr_class )
280+ {
281+ // error
282+ EM_error2( 0, "class import: add_mvar invoked without begin_class..." );
283+ return CK_INVALID_OFFSET;
284+ }
285+
286+ a_Id_List path = str2list( type );
287+ if( !path )
288+ {
289+ // error
290+ EM_error2( 0, "class import: add_mvar: mvar %s.%s has unknown type '%s'",
291+ query->curr_class->name.c_str(), name, type );
292+ return CK_INVALID_OFFSET;
293+ }
294+
295+ Chuck_Type * ck_type = type_engine_find_type( query->env(), path );
296+
297+ delete_id_list( path );
298+
299+ if( !ck_type )
300+ {
301+ // error
302+ EM_error2( 0, "class import: add_mvar: unable to find type '%s'", type );
303+ return CK_INVALID_OFFSET;
304+ }
305+
306+ // allocate
307+ Chuck_DL_Value * v = new Chuck_DL_Value;
308+ v->name = name;
309+ v->type = type;
310+ v->is_const = is_const;
311+
312+ // add
313+ query->curr_class->mvars.push_back( v );
314+ query->curr_func = NULL;
315+ query->last_var = v;
316+
317+ t_CKUINT offset = query->curr_class->current_mvar_offset;
318+ query->curr_class->current_mvar_offset = type_engine_next_offset( query->curr_class->current_mvar_offset,
319+ ck_type );
320+
321+ return offset;
322+}
323+
324+
325+
326+
327+//-----------------------------------------------------------------------------
328+// name: ck_add_svar()
329+// desc: add static var
330+//-----------------------------------------------------------------------------
331+void CK_DLL_CALL ck_add_svar( Chuck_DL_Query * query, const char * type, const char * name,
332+ t_CKBOOL is_const, void * addr )
333+{
334+ // make sure there is class
335+ if( !query->curr_class )
336+ {
337+ // error
338+ EM_error2( 0, "class import: add_svar invoked without begin_class..." );
339+ return;
340+ }
341+
342+ // allocate
343+ Chuck_DL_Value * v = new Chuck_DL_Value;
344+ v->name = name;
345+ v->type = type;
346+ v->is_const = is_const;
347+ v->static_addr = addr;
348+
349+ // add
350+ query->curr_class->svars.push_back( v );
351+ query->curr_func = NULL;
352+
353+ query->last_var = v;
354+}
355+
356+
357+
358+
359+//-----------------------------------------------------------------------------
360+// name: ck_add_arg()
361+// desc: add argument to function
362+//-----------------------------------------------------------------------------
363+void CK_DLL_CALL ck_add_arg( Chuck_DL_Query * query, const char * type, const char * name )
364+{
365+ // make sure there is class
366+ if( !query->curr_class )
367+ {
368+ // error
369+ EM_error2( 0, "class import: add_arg invoked without begin_class..." );
370+ return;
371+ }
372+
373+ // make sure there is function
374+ if( !query->curr_func )
375+ {
376+ // error
377+ EM_error2( 0, "class import: add_arg can only follow 'ctor', 'mfun', 'sfun', 'arg'..." );
378+ return;
379+ }
380+
381+ // allocate
382+ Chuck_DL_Value * v = new Chuck_DL_Value;
383+ v->name = name;
384+ v->type = type;
385+
386+ // add
387+ query->curr_func->args.push_back( v );
388+}
389+
390+
391+
392+
393+//-----------------------------------------------------------------------------
394+// name: ck_add_ugen_func()
395+// desc: (ugen only) add tick and pmsg functions
396+//-----------------------------------------------------------------------------
397+void CK_DLL_CALL ck_add_ugen_func( Chuck_DL_Query * query, f_tick ugen_tick, f_pmsg ugen_pmsg, t_CKUINT num_in, t_CKUINT num_out )
398+{
399+ // make sure there is class
400+ if( !query->curr_class )
401+ {
402+ // error
403+ EM_error2( 0, "class import: add_ugen_func invoked without begin_class..." );
404+ return;
405+ }
406+
407+ // make sure tick not defined already
408+ if( query->curr_class->ugen_tick && ugen_tick )
409+ {
410+ // error
411+ EM_error2( 0, "class import: ugen_tick already defined..." );
412+ return;
413+ }
414+
415+ // make sure pmsg not defined already
416+ if( query->curr_class->ugen_pmsg && ugen_pmsg )
417+ {
418+ // error
419+ EM_error2( 0, "class import: ugen_pmsg already defined..." );
420+ return;
421+ }
422+
423+ // set
424+ if( ugen_tick ) query->curr_class->ugen_tick = ugen_tick;
425+ if( ugen_pmsg ) query->curr_class->ugen_pmsg = ugen_pmsg;
426+ query->curr_class->ugen_num_in = num_in;
427+ query->curr_class->ugen_num_out = num_out;
428+ query->curr_func = NULL;
429+}
430+
431+
432+
433+
434+//-----------------------------------------------------------------------------
435+// name: ck_add_ugen_funcf()
436+// desc: (ugen only) add tick and pmsg functions
437+//-----------------------------------------------------------------------------
438+void CK_DLL_CALL ck_add_ugen_funcf( Chuck_DL_Query * query, f_tickf ugen_tickf, f_pmsg ugen_pmsg, t_CKUINT num_in, t_CKUINT num_out )
439+{
440+ // make sure there is class
441+ if( !query->curr_class )
442+ {
443+ // error
444+ EM_error2( 0, "class import: add_ugen_func invoked without begin_class..." );
445+ return;
446+ }
447+
448+ // make sure tick not defined already
449+ if( query->curr_class->ugen_tickf && ugen_tickf )
450+ {
451+ // error
452+ EM_error2( 0, "class import: ugen_tick already defined..." );
453+ return;
454+ }
455+
456+ // make sure pmsg not defined already
457+ if( query->curr_class->ugen_pmsg && ugen_pmsg )
458+ {
459+ // error
460+ EM_error2( 0, "class import: ugen_pmsg already defined..." );
461+ return;
462+ }
463+
464+ // set
465+ if( ugen_tickf ) query->curr_class->ugen_tickf = ugen_tickf;
466+ if( ugen_pmsg ) query->curr_class->ugen_pmsg = ugen_pmsg;
467+ query->curr_class->ugen_num_in = num_in;
468+ query->curr_class->ugen_num_out = num_out;
469+ query->curr_func = NULL;
470+}
471+
472+
473+
474+
475+//-----------------------------------------------------------------------------
476+// name: ck_add_ugen_funcf_auto_num_channels()
477+// desc: (ugen only) add tick and pmsg functions. specify num channels by vm.
478+//-----------------------------------------------------------------------------
479+void CK_DLL_CALL ck_add_ugen_funcf_auto_num_channels( Chuck_DL_Query * query,
480+ f_tickf ugen_tickf, f_pmsg ugen_pmsg )
481+{
482+ ck_add_ugen_funcf( query, ugen_tickf, ugen_pmsg,
483+ query->vm()->m_num_adc_channels,
484+ query->vm()->m_num_dac_channels
485+ );
486+}
487+
488+
489+
490+
491+//-----------------------------------------------------------------------------
492+// name: ck_add_ugen_ctrl()
493+// desc: (ugen only) add ctrl parameters
494+//-----------------------------------------------------------------------------
495+void CK_DLL_CALL ck_add_ugen_ctrl( Chuck_DL_Query * query, f_ctrl ugen_ctrl, f_cget ugen_cget,
496+ const char * type, const char * name )
497+{
498+ // make sure there is class
499+ if( !query->curr_class )
500+ {
501+ // error
502+ EM_error2( 0, "class import: add_ugen_func invoked without begin_class..." );
503+ return;
504+ }
505+
506+ // allocate
507+ Chuck_DL_Ctrl * c = new Chuck_DL_Ctrl;
508+ c->name = name;
509+ c->type = type;
510+ c->ctrl = ugen_ctrl;
511+ c->cget = ugen_cget;
512+
513+ // set
514+ query->curr_func = NULL;
515+}
516+
517+
518+
519+
520+//-----------------------------------------------------------------------------
521+// name: ck_end_class()
522+// desc: end class/namespace, compile it
523+//-----------------------------------------------------------------------------
524+t_CKBOOL CK_DLL_CALL ck_end_class( Chuck_DL_Query * query )
525+{
526+ // make sure there is class
527+ if( !query->curr_class )
528+ {
529+ // error
530+ EM_error2( 0, "class import: end_class invoked without begin_class..." );
531+ return FALSE;
532+ }
533+
534+ // type check the class?
535+ // 1.3.2.0: import class into type engine if at top level
536+ if( query->stack.size() == 1 ) // top level class
537+ {
538+ if( !type_engine_add_class_from_dl( query->env(), query->curr_class ) )
539+ {
540+ EM_log(CK_LOG_SEVERE, "[chuck](DL): error importing class '%s' into type engine",
541+ query->curr_class->name.c_str());
542+
543+ // pop
544+ assert( query->stack.size() );
545+ query->curr_class = query->stack.back();
546+ query->stack.pop_back();
547+
548+ return FALSE;
549+ }
550+ }
551+
552+ // pop
553+ assert( query->stack.size() );
554+ query->curr_class = query->stack.back();
555+ query->stack.pop_back();
556+
557+ return TRUE;
558+}
559+
560+
561+
562+//-----------------------------------------------------------------------------
563+// name: ck_create_main_thread_hook()
564+// desc: ...
565+//-----------------------------------------------------------------------------
566+Chuck_DL_MainThreadHook * CK_DLL_CALL ck_create_main_thread_hook( Chuck_DL_Query * query,
567+ f_mainthreadhook hook,
568+ f_mainthreadquit quit,
569+ void * bindle )
570+{
571+ assert( query->compiler() );
572+ assert( query->vm() );
573+
574+ return new Chuck_DL_MainThreadHook( hook, quit, bindle, query->vm() );
575+}
576+
577+//-----------------------------------------------------------------------------
578+// name: ck_doc_class()
579+// desc: set current class documentation
580+//-----------------------------------------------------------------------------
581+t_CKBOOL CK_DLL_CALL ck_doc_class( Chuck_DL_Query * query, const char * doc )
582+{
583+#ifdef CK_DOC // disable unless CK_DOC
584+ if(query->curr_class)
585+ query->curr_class->doc = doc;
586+ else
587+ return FALSE;
588+#endif // CK_DOC
589+
590+ return TRUE;
591+}
592+
593+//-----------------------------------------------------------------------------
594+// name: ck_add_example()
595+// desc: set current class documentation
596+//-----------------------------------------------------------------------------
597+t_CKBOOL CK_DLL_CALL ck_add_example( Chuck_DL_Query * query, const char * ex )
598+{
599+#ifdef CK_DOC // disable unless CK_DOC
600+ if(query->curr_class)
601+ query->curr_class->examples.push_back(ex);
602+ else
603+ return FALSE;
604+#endif // CK_DOC
605+
606+ return TRUE;
607+}
608+
609+// set current function documentation
610+t_CKBOOL CK_DLL_CALL ck_doc_func( Chuck_DL_Query * query, const char * doc )
611+{
612+#ifdef CK_DOC // disable unless CK_DOC
613+ if(query->curr_func)
614+ query->curr_func->doc = doc;
615+ else
616+ return FALSE;
617+#endif // CK_DOC
618+
619+ return TRUE;
620+}
621+
622+// set last mvar documentation
623+t_CKBOOL CK_DLL_CALL ck_doc_var( Chuck_DL_Query * query, const char * doc )
624+{
625+#ifdef CK_DOC // disable unless CK_DOC
626+ if(query->last_var)
627+ query->last_var->doc = doc;
628+ else
629+ return FALSE;
630+#endif // CK_DOC
631+
632+ return TRUE;
633+}
634+
635+
636+
637+//------------------------------------------------------------------------------
638+// alternative functions to make stuff
639+//------------------------------------------------------------------------------
640+Chuck_DL_Func * make_new_mfun( const char * t, const char * n, f_mfun mfun )
641+{ return new Chuck_DL_Func( t, n, (t_CKUINT)mfun ); }
642+Chuck_DL_Func * make_new_sfun( const char * t, const char * n, f_sfun sfun )
643+{ return new Chuck_DL_Func( t, n, (t_CKUINT)sfun ); }
644+Chuck_DL_Value * make_new_arg( const char * t, const char * n )
645+{ return new Chuck_DL_Value( t, n ); }
646+Chuck_DL_Value * make_new_mvar( const char * t, const char * n, t_CKBOOL c )
647+{ return new Chuck_DL_Value( t, n, c ); }
648+Chuck_DL_Value * make_new_svar( const char * t, const char * n, t_CKBOOL c, void * a )
649+{ return new Chuck_DL_Value( t, n, c, a ); }
650+
651+
652+
653+
654+//-----------------------------------------------------------------------------
655+// name: load()
656+// desc: load dynamic link library
657+//-----------------------------------------------------------------------------
658+t_CKBOOL Chuck_DLL::load( const char * filename, const char * func, t_CKBOOL lazy )
659+{
660+ // open
661+ m_handle = dlopen( filename, lazy ? RTLD_LAZY : RTLD_NOW );
662+
663+ // still not there
664+ if( !m_handle )
665+ {
666+ m_last_error = dlerror();
667+ return FALSE;
668+ }
669+
670+ // save the filename
671+ m_filename = filename;
672+ m_done_query = FALSE;
673+ m_func = func;
674+
675+ // if not lazy, do it
676+ if( !lazy && !this->query() )
677+ return FALSE;
678+
679+ return TRUE;
680+}
681+
682+
683+
684+
685+//-----------------------------------------------------------------------------
686+// name: load()
687+// desc: load dynamic link library
688+//-----------------------------------------------------------------------------
689+t_CKBOOL Chuck_DLL::load( f_ck_query query_func, t_CKBOOL lazy )
690+{
691+ m_query_func = query_func;
692+ m_version_func = ck_builtin_declversion;
693+ m_done_query = FALSE;
694+ m_func = "ck_query";
695+
696+ // if not lazy, do it
697+ if( !lazy && !this->query() )
698+ return FALSE;
699+
700+ return TRUE;
701+}
702+
703+
704+
705+
706+//-----------------------------------------------------------------------------
707+// name: good()
708+// desc: ...
709+//-----------------------------------------------------------------------------
710+t_CKBOOL Chuck_DLL::good() const
711+{
712+ return ( m_handle != NULL || m_query_func != NULL );
713+}
714+
715+
716+
717+
718+//-----------------------------------------------------------------------------
719+// name: query()
720+// desc: ...
721+//-----------------------------------------------------------------------------
722+const Chuck_DL_Query * Chuck_DLL::query( )
723+{
724+ if( !m_handle && !m_query_func )
725+ {
726+ m_last_error = "dynamic link library not loaded for query...";
727+ return NULL;
728+ }
729+
730+ // return if there already
731+ if( m_done_query )
732+ return &m_query;
733+
734+ // get the address of the DL version function from the DLL
735+ if( !m_version_func )
736+ m_version_func = (f_ck_declversion)this->get_addr( CK_DECLVERSION_FUNC );
737+ if( !m_version_func )
738+ m_version_func = (f_ck_declversion)this->get_addr( (string("_")+CK_DECLVERSION_FUNC).c_str() );
739+ if( !m_version_func )
740+ {
741+ m_last_error = string("no version function found in dll '")
742+ + m_filename + string("'");
743+ return NULL;
744+ }
745+
746+ // check version
747+ t_CKUINT dll_version = m_version_func();
748+ t_CKBOOL version_ok = FALSE;
749+ // oops lets have version 4 be ok actually
750+ if(CK_DLL_VERSION_GETMAJOR(dll_version) == 4)
751+ version_ok = TRUE;
752+ // major version must be same
753+ // minor version must less than or equal
754+ if(CK_DLL_VERSION_GETMAJOR(dll_version) == CK_DLL_VERSION_MAJOR &&
755+ CK_DLL_VERSION_GETMINOR(dll_version) <= CK_DLL_VERSION_MINOR)
756+ version_ok = TRUE;
757+
758+ if(!version_ok)
759+ // SPENCERTODO: do they need to be equal, or can dll_version be < ?
760+ {
761+ ostringstream oss;
762+ oss << "DL version not supported: "
763+ << CK_DLL_VERSION_GETMAJOR(dll_version)
764+ << "."
765+ << CK_DLL_VERSION_GETMINOR(dll_version)
766+ << " in '"
767+ << m_filename
768+ << "'";
769+
770+ m_last_error = oss.str();
771+
772+ return NULL;
773+ }
774+
775+ // get the address of the query function from the DLL
776+ if( !m_query_func )
777+ m_query_func = (f_ck_query)this->get_addr( m_func.c_str() );
778+ if( !m_query_func )
779+ m_query_func = (f_ck_query)this->get_addr( (string("_")+m_func).c_str() );
780+ if( !m_query_func )
781+ {
782+ m_last_error = string("no query function found in dll '")
783+ + m_filename + string("'");
784+ return NULL;
785+ }
786+
787+ // get the address of the attach function from the DLL
788+ /* if( !m_attach_func )
789+ m_attach_func = (f_ck_attach)this->get_addr( "ck_attach" );
790+ if( !m_attach_func )
791+ m_attach_func = (f_ck_attach)this->get_addr( "_ck_attach" );
792+
793+ // get the address of the detach function from the DLL
794+ if( !m_detach_func )
795+ m_detach_func = (f_ck_detach)this->get_addr( "ck_detach" );
796+ if( !m_detach_func )
797+ m_detach_func = (f_ck_detach)this->get_addr( "_ck_detach" ); */
798+
799+ // do the query
800+ m_query.clear();
801+ if( !m_query_func( &m_query ) )
802+ {
803+ m_last_error = string("unsuccessful query in dll '") + m_filename
804+ + string("'");
805+ return NULL;
806+ }
807+
808+ // load the proto table
809+ /* Chuck_DL_Proto * proto;
810+ m_name2proto.clear();
811+ for( t_CKUINT i = 0; i < m_query.dll_exports.size(); i++ )
812+ {
813+ proto = &m_query.dll_exports[i];
814+ if( m_name2proto[proto->name] )
815+ {
816+ m_last_error = string("duplicate export name '") + proto->name
817+ + string("'");
818+ return NULL;
819+ }
820+
821+ // get the addr
822+ if( !proto->addr )
823+ proto->addr = (f_ck_func)this->get_addr( (char *)proto->name.c_str() );
824+ if( !proto->addr )
825+ {
826+ m_last_error = string("no addr associated with export '") +
827+ proto->name + string("'");
828+ return NULL;
829+ }
830+
831+ // put in the lookup table
832+ m_name2proto[proto->name] = proto;
833+ }
834+
835+ // load the proto table
836+ Chuck_UGen_Info * info;
837+ m_name2ugen.clear();
838+ for( t_CKUINT j = 0; j < m_query.ugen_exports.size(); j++ )
839+ {
840+ info = &m_query.ugen_exports[j];
841+ if( m_name2ugen[info->name] )
842+ {
843+ m_last_error = string("duplicate export ugen name '") + info->name
844+ + string("'");
845+ return NULL;
846+ }
847+
848+ // put in the lookup table
849+ m_name2ugen[info->name] = info;
850+ }*/
851+
852+ m_done_query = TRUE;
853+
854+ // call attach
855+ // if( m_attach_func ) m_attach_func( 0, NULL );
856+
857+ return &m_query;
858+}
859+
860+
861+
862+
863+//-----------------------------------------------------------------------------
864+// name: unload()
865+// desc: ...
866+//-----------------------------------------------------------------------------
867+t_CKBOOL Chuck_DLL::unload()
868+{
869+ if( !m_handle && !m_query_func )
870+ {
871+ m_last_error = "cannot unload dynamic library - nothing open...";
872+ return FALSE;
873+ }
874+
875+ // if( m_detach_func ) m_detach_func( 0, NULL );
876+
877+ if( m_handle )
878+ {
879+ dlclose( m_handle );
880+ m_handle = NULL;
881+ }
882+ else
883+ m_query_func = NULL;
884+
885+ return TRUE;
886+}
887+
888+
889+
890+
891+//-----------------------------------------------------------------------------
892+// name: get_addr()
893+// desc: ...
894+//-----------------------------------------------------------------------------
895+void * Chuck_DLL::get_addr( const char * symbol )
896+{
897+ if( !m_handle )
898+ {
899+ m_last_error = "cannot find addr from dynamic library - nothing open...";
900+ return FALSE;
901+ }
902+
903+ return dlsym( m_handle, symbol );
904+}
905+
906+
907+
908+
909+//-----------------------------------------------------------------------------
910+// name: last_error()
911+// desc: ...
912+//-----------------------------------------------------------------------------
913+const char * Chuck_DLL::last_error() const
914+{
915+ return m_last_error.c_str();
916+}
917+
918+
919+
920+
921+//-----------------------------------------------------------------------------
922+// name: name()
923+// desc: ...
924+//-----------------------------------------------------------------------------
925+const char * Chuck_DLL::name() const
926+{
927+ return m_id.c_str();
928+}
929+
930+
931+//const t_CKUINT Chuck_DL_Query::RESERVED_SIZE;
932+
933+//-----------------------------------------------------------------------------
934+// name: Chuck_DL_Query
935+// desc: ...
936+//-----------------------------------------------------------------------------
937+Chuck_DL_Query::Chuck_DL_Query( Chuck_Carrier * carrier )
938+{
939+ // set the pointers to functions so the module can call
940+ setname = ck_setname;
941+ begin_class = ck_begin_class;
942+ add_ctor = ck_add_ctor;
943+ add_dtor = ck_add_dtor;
944+ add_mfun = ck_add_mfun;
945+ add_sfun = ck_add_sfun;
946+ add_mvar = ck_add_mvar;
947+ add_svar = ck_add_svar;
948+ add_arg = ck_add_arg;
949+ add_ugen_func = ck_add_ugen_func;
950+ add_ugen_funcf = ck_add_ugen_funcf;
951+ add_ugen_funcf_auto_num_channels = ck_add_ugen_funcf_auto_num_channels;
952+ add_ugen_ctrl = ck_add_ugen_ctrl;
953+ end_class = ck_end_class;
954+ create_main_thread_hook = ck_create_main_thread_hook;
955+ doc_class = ck_doc_class;
956+ doc_func = ck_doc_func;
957+ doc_var = ck_doc_var;
958+ m_carrier = carrier;
959+
960+// memset(reserved2, NULL, sizeof(void*)*RESERVED_SIZE);
961+
962+ dll_name = "[noname]";
963+ reserved = NULL;
964+ curr_class = NULL;
965+ curr_func = NULL;
966+
967+#ifndef __CKDL_NO_BBQ__
968+ srate = Digitalio::sampling_rate() ; bufsize = Digitalio::buffer_size();
969+#else
970+ srate = 0; bufsize = 0;
971+#endif
972+
973+ linepos = 0;
974+}
975+
976+
977+
978+
979+//-----------------------------------------------------------------------------
980+// name: clear()
981+// desc: ...
982+//-----------------------------------------------------------------------------
983+void Chuck_DL_Query::clear()
984+{
985+ // set to 0
986+ dll_name = "[noname]";
987+ // line pos
988+ linepos = 0;
989+ // delete classes
990+ for( t_CKUINT i = 0; i < classes.size(); i++ ) delete classes[i];
991+ // clear
992+ classes.clear();
993+}
994+
995+
996+
997+
998+//-----------------------------------------------------------------------------
999+// name: ~Chuck_DL_Class()
1000+// desc: ...
1001+//-----------------------------------------------------------------------------
1002+Chuck_DL_Class::~Chuck_DL_Class()
1003+{
1004+ t_CKUINT i;
1005+
1006+ // delete mfuns
1007+ for( i = 0; i < mfuns.size(); i++ ) delete mfuns[i];
1008+ // delete sfuns
1009+ for( i = 0; i < sfuns.size(); i++ ) delete sfuns[i];
1010+ // delete mvars
1011+ for( i = 0; i < mvars.size(); i++ ) delete mvars[i];
1012+ // delete svars
1013+ for( i = 0; i < svars.size(); i++ ) delete svars[i];
1014+ // delete classes
1015+ for( i = 0; i < classes.size(); i++ ) delete classes[i];
1016+}
1017+
1018+
1019+
1020+
1021+//-----------------------------------------------------------------------------
1022+// name: ~Chuck_DL_Func()
1023+// desc: ...
1024+//-----------------------------------------------------------------------------
1025+Chuck_DL_Func::~Chuck_DL_Func()
1026+{
1027+ for( t_CKUINT i = 0; i < args.size(); i++ )
1028+ delete args[i];
1029+}
1030+
1031+
1032+
1033+t_CKBOOL ck_mthook_activate(Chuck_DL_MainThreadHook *hook)
1034+{
1035+ // ge: changed in 1.3.5.3
1036+ hook->m_active = set_main_thread_hook(hook->m_hook,
1037+ hook->m_quit,
1038+ hook->m_bindle);
1039+// hook->m_active = hook->m_vm->set_main_thread_hook(hook->m_hook,
1040+// hook->m_quit,
1041+// hook->m_bindle);
1042+ return hook->m_active;
1043+}
1044+
1045+t_CKBOOL ck_mthook_deactivate(Chuck_DL_MainThreadHook *hook)
1046+{
1047+ if(hook->m_active)
1048+ // ge: changed in 1.3.5.3
1049+ return clear_main_thread_hook();
1050+ // return hook->m_vm->clear_main_thread_hook();
1051+ else
1052+ return FALSE;
1053+}
1054+
1055+//-----------------------------------------------------------------------------
1056+// name: Chuck_DL_MainThreadHook()
1057+// desc: ...
1058+//-----------------------------------------------------------------------------
1059+Chuck_DL_MainThreadHook::Chuck_DL_MainThreadHook(f_mainthreadhook hook, f_mainthreadquit quit,
1060+ void * bindle, Chuck_VM * vm) :
1061+m_hook(hook),
1062+m_quit(quit),
1063+m_vm(vm),
1064+m_bindle(bindle),
1065+activate(ck_mthook_activate),
1066+deactivate(ck_mthook_deactivate),
1067+m_active(FALSE)
1068+{ }
1069+
1070+
1071+
1072+/*******************************************************************************
1073+
1074+ Chuck_DL_Api stuff
1075+
1076+*******************************************************************************/
1077+
1078+namespace Chuck_DL_Api
1079+{
1080+ Api Api::g_api;
1081+}
1082+
1083+
1084+static t_CKUINT ck_get_srate(CK_DL_API api, Chuck_VM_Shred * shred)
1085+{
1086+ return shred->vm_ref->srate();
1087+}
1088+
1089+static Chuck_DL_Api::Type ck_get_type( CK_DL_API api, Chuck_VM_Shred * shred, std::string & name )
1090+{
1091+ Chuck_Env * env = shred->vm_ref->env();
1092+ a_Id_List list = new_id_list( name.c_str(), 0 ); // TODO: nested types
1093+
1094+ Chuck_Type * t = type_engine_find_type( env, list );
1095+
1096+ delete_id_list( list );
1097+
1098+ return ( Chuck_DL_Api::Type ) t;
1099+}
1100+
1101+static Chuck_DL_Api::Object ck_create( CK_DL_API api, Chuck_VM_Shred * shred, Chuck_DL_Api::Type t )
1102+{
1103+ assert( t != NULL );
1104+
1105+ Chuck_Type * type = ( Chuck_Type * ) t;
1106+ Chuck_Object * o = instantiate_and_initialize_object( type, shred->vm_ref );
1107+
1108+ return ( Chuck_DL_Api::Object ) o;
1109+}
1110+
1111+static Chuck_DL_Api::String ck_create_string( CK_DL_API api, Chuck_VM_Shred * shred, std::string & str )
1112+{
1113+ Chuck_String * string = ( Chuck_String * ) instantiate_and_initialize_object( shred->vm_ref->env()->t_string, shred->vm_ref );
1114+
1115+ string->set( str );
1116+
1117+ return ( Chuck_DL_Api::String ) string;
1118+}
1119+
1120+static t_CKBOOL ck_get_mvar_int( CK_DL_API api, Chuck_DL_Api::Object, std::string &, t_CKINT & )
1121+{
1122+ return TRUE;
1123+}
1124+
1125+static t_CKBOOL ck_get_mvar_float( CK_DL_API api, Chuck_DL_Api::Object, std::string &, t_CKFLOAT & )
1126+{
1127+ return TRUE;
1128+}
1129+
1130+static t_CKBOOL ck_get_mvar_dur( CK_DL_API api, Chuck_DL_Api::Object, std::string &, t_CKDUR & )
1131+{
1132+ return TRUE;
1133+}
1134+
1135+static t_CKBOOL ck_get_mvar_time( CK_DL_API api, Chuck_DL_Api::Object, std::string &, t_CKTIME & )
1136+{
1137+ return TRUE;
1138+}
1139+
1140+static t_CKBOOL ck_get_mvar_string( CK_DL_API api, Chuck_DL_Api::Object, std::string &, Chuck_DL_Api::String & )
1141+{
1142+ return TRUE;
1143+}
1144+
1145+static t_CKBOOL ck_get_mvar_object( CK_DL_API api, Chuck_DL_Api::Object, std::string &, Chuck_DL_Api::Object & )
1146+{
1147+ return TRUE;
1148+}
1149+
1150+static t_CKBOOL ck_set_string( CK_DL_API api, Chuck_DL_Api::String s, std::string & str )
1151+{
1152+ assert( s != NULL );
1153+
1154+ Chuck_String * string = ( Chuck_String * ) s;
1155+ string->set( str );
1156+
1157+ return TRUE;
1158+}
1159+
1160+
1161+Chuck_DL_Api::Api::VMApi::VMApi() :
1162+get_srate(ck_get_srate)
1163+{ }
1164+
1165+
1166+Chuck_DL_Api::Api::ObjectApi::ObjectApi() :
1167+get_type(ck_get_type),
1168+create(ck_create),
1169+create_string(ck_create_string),
1170+get_mvar_int(ck_get_mvar_int),
1171+get_mvar_float(ck_get_mvar_float),
1172+get_mvar_dur(ck_get_mvar_dur),
1173+get_mvar_time(ck_get_mvar_time),
1174+get_mvar_string(ck_get_mvar_string),
1175+get_mvar_object(ck_get_mvar_object),
1176+set_string(ck_set_string)
1177+{ }
1178+
1179+
1180+// windows
1181+#if defined(__WINDOWS_DS__)
1182+extern "C"
1183+{
1184+#include <windows.h>
1185+
1186+void *dlopen( const char *path, int mode )
1187+{
1188+ return (void *)LoadLibrary(path);
1189+}
1190+
1191+int dlclose( void *handle )
1192+{
1193+ FreeLibrary((HMODULE)handle);
1194+ return 1;
1195+}
1196+
1197+void *dlsym( void * handle, const char *symbol )
1198+{
1199+ return (void *)GetProcAddress((HMODULE)handle, symbol);
1200+}
1201+
1202+const char * dlerror( void )
1203+{
1204+ int error = GetLastError();
1205+ if( error == 0 ) return NULL;
1206+ sprintf( dlerror_buffer, "%i", error );
1207+ return dlerror_buffer;
1208+}
1209+}
1210+#endif
core/chuck_dl.h+755−0
@@ -0,0 +1,755 @@
1+/*----------------------------------------------------------------------------
2+ ChucK Concurrent, On-the-fly Audio Programming Language
3+ Compiler and Virtual Machine
4+
5+ Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6+ http://chuck.stanford.edu/
7+ http://chuck.cs.princeton.edu/
8+
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.
13+
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.
18+
19+ You should have received a copy of the GNU General Public License
20+ along with this program; if not, write to the Free Software
21+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22+ U.S.A.
23+-----------------------------------------------------------------------------*/
24+
25+//-----------------------------------------------------------------------------
26+// name: chuck_dl.h
27+// desc: chuck dynamic linking header
28+//
29+// authors: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
30+// Ari Lazier (alazier@cs.princeton.edu)
31+// Spencer Salazar (spencer@ccrma.stanford.edu)
32+// mac os code based on apple's open source
33+//
34+// date: spring 2004 - 1.1
35+// spring 2005 - 1.2
36+//-----------------------------------------------------------------------------
37+#ifndef __CHUCK_DL_H__
38+#define __CHUCK_DL_H__
39+
40+#include "chuck_def.h"
41+#include "chuck_oo.h"
42+#include "chuck_carrier.h"
43+#include <string>
44+#include <vector>
45+#include <map>
46+
47+
48+// major version must be the same between chuck:chugin
49+#define CK_DLL_VERSION_MAJOR (0x0006)
50+// minor version of chugin must be less than or equal to chuck's
51+#define CK_DLL_VERSION_MINOR (0x0000)
52+#define CK_DLL_VERSION_MAKE(maj,min) ((t_CKUINT)(((maj) << 16) | (min)))
53+#define CK_DLL_VERSION_GETMAJOR(v) (((v) >> 16) & 0xFFFF)
54+#define CK_DLL_VERSION_GETMINOR(v) ((v) & 0xFFFF)
55+#define CK_DLL_VERSION (CK_DLL_VERSION_MAKE(CK_DLL_VERSION_MAJOR, CK_DLL_VERSION_MINOR))
56+
57+
58+
59+
60+extern char g_default_chugin_path[];
61+extern char g_chugin_path_envvar[];
62+
63+
64+
65+// forward references
66+struct Chuck_DL_Query;
67+struct Chuck_DL_Class;
68+struct Chuck_DL_Func;
69+struct Chuck_DL_Value;
70+struct Chuck_DL_Ctrl;
71+union Chuck_DL_Return;
72+struct Chuck_DLL;
73+struct Chuck_UGen;
74+struct Chuck_UAna;
75+struct Chuck_UAnaBlobProxy;
76+struct Chuck_DL_MainThreadHook;
77+namespace Chuck_DL_Api { struct Api; }
78+
79+
80+// param conversion - to extract values from ARGS to functions
81+#define GET_CK_FLOAT(ptr) (*(t_CKFLOAT *)ptr)
82+#define GET_CK_SINGLE(ptr) (*(float *)ptr)
83+#define GET_CK_DOUBLE(ptr) (*(double *)ptr)
84+#define GET_CK_INT(ptr) (*(t_CKINT *)ptr)
85+#define GET_CK_UINT(ptr) (*(t_CKUINT *)ptr)
86+#define GET_CK_TIME(ptr) (*(t_CKTIME *)ptr)
87+#define GET_CK_DUR(ptr) (*(t_CKDUR *)ptr)
88+#define GET_CK_COMPLEX(ptr) (*(t_CKCOMPLEX *)ptr)
89+#define GET_CK_POLAR(ptr) (*(t_CKPOLAR *)ptr)
90+#define GET_CK_VEC3(ptr) (*(t_CKVEC3 *)ptr)
91+#define GET_CK_VEC4(ptr) (*(t_CKVEC4 *)ptr)
92+#define GET_CK_VECTOR(ptr) (*(t_CKVECTOR *)ptr)
93+#define GET_CK_OBJECT(ptr) (*(Chuck_Object **)ptr)
94+#define GET_CK_STRING(ptr) (*(Chuck_String **)ptr)
95+
96+// param conversion with pointer advance
97+#define GET_NEXT_FLOAT(ptr) (*((t_CKFLOAT *&)ptr)++)
98+#define GET_NEXT_SINGLE(ptr) (*((float *&)ptr)++)
99+#define GET_NEXT_DOUBLE(ptr) (*((double *&)ptr)++)
100+#define GET_NEXT_INT(ptr) (*((t_CKINT *&)ptr)++)
101+#define GET_NEXT_UINT(ptr) (*((t_CKUINT *&)ptr)++)
102+#define GET_NEXT_TIME(ptr) (*((t_CKTIME *&)ptr)++)
103+#define GET_NEXT_DUR(ptr) (*((t_CKDUR *&)ptr)++)
104+#define GET_NEXT_COMPLEX(ptr) (*((t_CKCOMPLEX *&)ptr)++)
105+#define GET_NEXT_POLAR(ptr) (*((t_CKPOLAR *&)ptr)++)
106+#define GET_NEXT_VEC3(ptr) (*((t_CKVEC3 *&)ptr)++)
107+#define GET_NEXT_VEC4(ptr) (*((t_CKVEC4 *&)ptr)++)
108+#define GET_NEXT_VECTOR(ptr) (*((t_CKVECTOR *&)ptr)++)
109+#define GET_NEXT_OBJECT(ptr) (*((Chuck_Object **&)ptr)++)
110+#define GET_NEXT_STRING(ptr) (*((Chuck_String **&)ptr)++)
111+
112+// param conversion
113+#define SET_CK_FLOAT(ptr,v) (*(t_CKFLOAT *&)ptr=v)
114+#define SET_CK_SINGLE(ptr,v) (*(float *&)ptr=v)
115+#define SET_CK_DOUBLE(ptr,v) (*(double *&)ptr=v)
116+#define SET_CK_INT(ptr,v) (*(t_CKINT *&)ptr=v)
117+#define SET_CK_UINT(ptr,v) (*(t_CKUINT *&)ptr=v)
118+#define SET_CK_TIME(ptr,v) (*(t_CKTIME *&)ptr=v)
119+#define SET_CK_DUR(ptr,v) (*(t_CKDUR *&)ptr=v)
120+#define SET_CK_VEC3(ptr,v) (*(t_CKVEC3 *&)ptr=v)
121+#define SET_CK_VEC4(ptr,v) (*(t_CKVEC4 *&)ptr=v)
122+#define SET_CK_VECTOR(ptr,v) (*(t_CKVECTOR *&)ptr=v)
123+#define SET_CK_STRING(ptr,v) (*(Chuck_String **&)ptr=v)
124+
125+// param conversion with pointer advance
126+#define SET_NEXT_FLOAT(ptr,v) (*((t_CKFLOAT *&)ptr)++=v)
127+#define SET_NEXT_SINGLE(ptr,v) (*((float *&)ptr)++=v)
128+#define SET_NEXT_DOUBLE(ptr,v) (*((double *&)ptr)++=v)
129+#define SET_NEXT_INT(ptr,v) (*((t_CKINT *&)ptr)++=v)
130+#define SET_NEXT_UINT(ptr,v) (*((t_CKUINT *&)ptr)++=v)
131+#define SET_NEXT_TIME(ptr,v) (*((t_CKTIME *&)ptr)++=v)
132+#define SET_NEXT_DUR(ptr,v) (*((t_CKDUR *&)ptr)++=v)
133+#define SET_NEXT_VEC3(ptr,v) (*((t_CKVEC3 *&)ptr)++=v)
134+#define SET_NEXT_VEC4(ptr,v) (*((t_CKVEC4 *&)ptr)++=v)
135+#define SET_NEXT_VECTOR(ptr,v) (*((t_CKVECTOR *&)ptr)++=v)
136+#define SET_NEXT_STRING(ptr,v) (*((Chuck_String **&)ptr)++=v)
137+
138+// param conversion - to extract values from object's data segment
139+#define OBJ_MEMBER_DATA(obj,offset) (obj->data + offset)
140+#define OBJ_MEMBER_FLOAT(obj,offset) (*(t_CKFLOAT *)OBJ_MEMBER_DATA(obj,offset))
141+#define OBJ_MEMBER_SINGLE(obj,offset) (*(float *)OBJ_MEMBER_DATA(obj,offset))
142+#define OBJ_MEMBER_DOUBLE(obj,offset) (*(double *)OBJ_MEMBER_DATA(obj,offset))
143+#define OBJ_MEMBER_INT(obj,offset) (*(t_CKINT *)OBJ_MEMBER_DATA(obj,offset))
144+#define OBJ_MEMBER_UINT(obj,offset) (*(t_CKUINT *)OBJ_MEMBER_DATA(obj,offset))
145+#define OBJ_MEMBER_TIME(obj,offset) (*(t_CKTIME *)OBJ_MEMBER_DATA(obj,offset))
146+#define OBJ_MEMBER_DUR(obj,offset) (*(t_CKDUR *)OBJ_MEMBER_DATA(obj,offset))
147+#define OBJ_MEMBER_VEC3(obj,offset) (*(t_CKVEC3 *)OBJ_MEMBER_DATA(obj,offset))
148+#define OBJ_MEMBER_VEC4(obj,offset) (*(t_CKVEC4 *)OBJ_MEMBER_DATA(obj,offset))
149+#define OBJ_MEMBER_VECTOR(obj,offset) (*(t_CKVECTOR *)OBJ_MEMBER_DATA(obj,offset))
150+#define OBJ_MEMBER_OBJECT(obj,offset) (*(Chuck_Object **)OBJ_MEMBER_DATA(obj,offset))
151+#define OBJ_MEMBER_STRING(obj,offset) (*(Chuck_String **)OBJ_MEMBER_DATA(obj,offset))
152+
153+
154+// chuck dll export linkage and calling convention
155+#if defined (__PLATFORM_WIN32__)
156+ #define CK_DLL_LINKAGE extern "C" __declspec( dllexport )
157+#else
158+ #define CK_DLL_LINKAGE extern "C"
159+#endif
160+
161+// calling convention of functions provided by chuck to the dll
162+#if defined(__WINDOWS_DS__)
163+ #define CK_DLL_CALL _cdecl
164+#else
165+ #define CK_DLL_CALL
166+#endif
167+
168+typedef const Chuck_DL_Api::Api *CK_DL_API;
169+
170+// macro for defining ChucK DLL export functions
171+// example: CK_DLL_EXPORT(int) foo() { return 1; }
172+#define CK_DLL_EXPORT(type) CK_DLL_LINKAGE type CK_DLL_CALL
173+// macro for declaring version of ChucK DL a given DLL links to
174+// example: CK_DLL_DECLVERSION
175+#define CK_DLL_DECLVERSION CK_DLL_EXPORT(t_CKUINT) ck_version() { return CK_DLL_VERSION; }
176+// naming convention for static query functions
177+#define CK_DLL_QUERY_STATIC_NAME(name) ck_##name##_query
178+// macro for defining ChucK DLL export query-functions (static version)
179+#define CK_DLL_QUERY_STATIC(name) CK_DLL_EXPORT(t_CKBOOL) CK_DLL_QUERY_STATIC_NAME(name)( Chuck_DL_Query * QUERY )
180+// macro for defining ChucK DLL export query-functions
181+// example: CK_DLL_QUERY
182+#ifndef __CK_DLL_STATIC__
183+#define CK_DLL_QUERY(name) CK_DLL_DECLVERSION CK_DLL_EXPORT(t_CKBOOL) ck_query( Chuck_DL_Query * QUERY )
184+#else
185+#define CK_DLL_QUERY(name) CK_DLL_QUERY_STATIC(name)
186+#endif // __CK_DLL_STATIC__
187+// macro for defining ChucK DLL export allocator
188+// example: CK_DLL_ALLOC(foo)
189+#define CK_DLL_ALLOC(name) CK_DLL_EXPORT(Chuck_Object *) name( Chuck_VM_Shred * SHRED, CK_DL_API API )
190+// macro for defining ChucK DLL export constructors
191+// example: CK_DLL_CTOR(foo)
192+#define CK_DLL_CTOR(name) CK_DLL_EXPORT(void) name( Chuck_Object * SELF, void * ARGS, Chuck_VM_Shred * SHRED, CK_DL_API API )
193+// macro for defining ChucK DLL export destructors
194+// example: CK_DLL_DTOR(foo)
195+#define CK_DLL_DTOR(name) CK_DLL_EXPORT(void) name( Chuck_Object * SELF, Chuck_VM_Shred * SHRED, CK_DL_API API )
196+// macro for defining ChucK DLL export member functions
197+// example: CK_DLL_MFUN(foo)
198+#define CK_DLL_MFUN(name) CK_DLL_EXPORT(void) name( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED, CK_DL_API API )
199+// macro for defining ChucK DLL export static functions
200+// example: CK_DLL_SFUN(foo)
201+#define CK_DLL_SFUN(name) CK_DLL_EXPORT(void) name( void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED, CK_DL_API API )
202+// macro for defining ChucK DLL export ugen tick functions
203+// example: CK_DLL_TICK(foo)
204+#define CK_DLL_TICK(name) CK_DLL_EXPORT(t_CKBOOL) name( Chuck_Object * SELF, SAMPLE in, SAMPLE * out, Chuck_VM_Shred * SHRED, CK_DL_API API )
205+// macro for defining ChucK DLL export ugen multi-channel tick functions
206+// example: CK_DLL_TICKF(foo)
207+#define CK_DLL_TICKF(name) CK_DLL_EXPORT(t_CKBOOL) name( Chuck_Object * SELF, SAMPLE * in, SAMPLE * out, t_CKUINT nframes, Chuck_VM_Shred * SHRED, CK_DL_API API )
208+// macro for defining ChucK DLL export ugen ctrl functions
209+// example: CK_DLL_CTRL(foo)
210+#define CK_DLL_CTRL(name) CK_DLL_EXPORT(void) name( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED, CK_DL_API API )
211+// macro for defining ChucK DLL export ugen cget functions
212+// example: CK_DLL_CGET(foo)
213+#define CK_DLL_CGET(name) CK_DLL_EXPORT(void) name( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED, CK_DL_API API )
214+// macro for defining ChucK DLL export ugen pmsg functions
215+// example: CK_DLL_PMSG(foo)
216+#define CK_DLL_PMSG(name) CK_DLL_EXPORT(t_CKBOOL) name( Chuck_Object * SELF, const char * MSG, void * ARGS, Chuck_VM_Shred * SHRED, CK_DL_API API )
217+// macro for defining ChucK DLL export uana tock functions
218+// example: CK_DLL_TOCK(foo)
219+#define CK_DLL_TOCK(name) CK_DLL_EXPORT(t_CKBOOL) name( Chuck_Object * SELF, Chuck_UAna * UANA, Chuck_UAnaBlobProxy * BLOB, Chuck_VM_Shred * SHRED, CK_DL_API API )
220+
221+
222+// macros for DLL exports
223+// example: DLL_QUERY query( Chuck_DL_Query * QUERY )
224+// example: DLL_FUNC foo( void * ARGS, Chuck_DL_Return * RETURN )
225+// example: DLL_UGEN_F foo_tick( Chuck_UGen * SELF, SAMPLE, SAMPLE * out );
226+#define DLL_QUERY CK_DLL_EXPORT(t_CKBOOL)
227+#define DLL_FUNC CK_DLL_EXPORT(void)
228+#define UGEN_CTOR CK_DLL_EXPORT(void *)
229+#define UGEN_DTOR CK_DLL_EXPORT(void)
230+#define UGEN_TICK CK_DLL_EXPORT(t_CKBOOL)
231+#define UGEN_PMSG CK_DLL_EXPORT(t_CKBOOL)
232+#define UGEN_CTRL CK_DLL_EXPORT(t_CKVOID)
233+#define UGEN_CGET CK_DLL_EXPORT(t_CKVOID)
234+#define UANA_TOCK CK_DLL_EXPORT(t_CKBOOL)
235+
236+
237+//-----------------------------------------------------------------------------
238+// dynamic linking class interface prototypes
239+//-----------------------------------------------------------------------------
240+extern "C" {
241+// query
242+typedef t_CKUINT (CK_DLL_CALL * f_ck_declversion)();
243+typedef t_CKBOOL (CK_DLL_CALL * f_ck_query)( Chuck_DL_Query * QUERY );
244+// object
245+typedef Chuck_Object * (CK_DLL_CALL * f_alloc)( Chuck_VM_Shred * SHRED, CK_DL_API API );
246+typedef t_CKVOID (CK_DLL_CALL * f_ctor)( Chuck_Object * SELF, void * ARGS, Chuck_VM_Shred * SHRED, CK_DL_API API );
247+typedef t_CKVOID (CK_DLL_CALL * f_dtor)( Chuck_Object * SELF, Chuck_VM_Shred * SHRED, CK_DL_API API );
248+typedef t_CKVOID (CK_DLL_CALL * f_mfun)( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED, CK_DL_API API );
249+typedef t_CKVOID (CK_DLL_CALL * f_sfun)( void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED, CK_DL_API API );
250+// ugen specific
251+typedef t_CKBOOL (CK_DLL_CALL * f_tick)( Chuck_Object * SELF, SAMPLE in, SAMPLE * out, Chuck_VM_Shred * SHRED, CK_DL_API API );
252+typedef t_CKBOOL (CK_DLL_CALL * f_tickf)( Chuck_Object * SELF, SAMPLE * in, SAMPLE * out, t_CKUINT nframes, Chuck_VM_Shred * SHRED, CK_DL_API API );
253+typedef t_CKVOID (CK_DLL_CALL * f_ctrl)( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED, CK_DL_API API );
254+typedef t_CKVOID (CK_DLL_CALL * f_cget)( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED, CK_DL_API API );
255+typedef t_CKBOOL (CK_DLL_CALL * f_pmsg)( Chuck_Object * SELF, const char * MSG, void * ARGS, Chuck_VM_Shred * SHRED, CK_DL_API API );
256+// uana specific
257+typedef t_CKBOOL (CK_DLL_CALL * f_tock)( Chuck_Object * SELF, Chuck_UAna * UANA, Chuck_UAnaBlobProxy * BLOB, Chuck_VM_Shred * SHRED, CK_DL_API API );
258+// "main thread" hook
259+typedef t_CKBOOL (CK_DLL_CALL * f_mainthreadhook)( void * bindle );
260+// "main thread" quit (stop running hook)
261+typedef t_CKBOOL (CK_DLL_CALL * f_mainthreadquit)( void * bindle );
262+}
263+
264+
265+// default name in DLL/ckx to look for
266+#define CK_QUERY_FUNC "ck_query"
267+// default name in DLL/ckx to look for
268+#define CK_DECLVERSION_FUNC "ck_version"
269+// bad object data offset
270+#define CK_INVALID_OFFSET 0xffffffff
271+
272+
273+//-----------------------------------------------------------------------------
274+// chuck DLL query functions, implemented on chuck side for portability
275+//-----------------------------------------------------------------------------
276+extern "C" {
277+// set name of ckx
278+typedef void ( CK_DLL_CALL * f_setname)( Chuck_DL_Query * query, const char * name );
279+
280+// begin class/namespace, can be nested
281+typedef void (CK_DLL_CALL * f_begin_class)( Chuck_DL_Query * query, const char * name, const char * parent );
282+// add constructor, must be betwen begin/end_class : use f_add_arg to add arguments immediately after
283+typedef void (CK_DLL_CALL * f_add_ctor)( Chuck_DL_Query * query, f_ctor ctor );
284+// add destructor - cannot have args
285+typedef void (CK_DLL_CALL * f_add_dtor)( Chuck_DL_Query * query, f_dtor dtor );
286+// add member function - args to follow
287+typedef void (CK_DLL_CALL * f_add_mfun)( Chuck_DL_Query * query, f_mfun mfun, const char * type, const char * name );
288+// add static function - args to follow
289+typedef void (CK_DLL_CALL * f_add_sfun)( Chuck_DL_Query * query, f_sfun sfun, const char * type, const char * name );
290+// add member variable
291+typedef t_CKUINT (CK_DLL_CALL * f_add_mvar)( Chuck_DL_Query * query,
292+ const char * type, const char * name, t_CKBOOL is_const ); // TODO: public/protected/private
293+// add static variable
294+typedef void (CK_DLL_CALL * f_add_svar)( Chuck_DL_Query * query,
295+ const char * type, const char * name,
296+ t_CKBOOL is_const, void * static_addr ); // TODO: public/protected/private
297+// add arg - follows ctor mfun sfun
298+typedef void (CK_DLL_CALL * f_add_arg)( Chuck_DL_Query * query, const char * type, const char * name );
299+// ** functions for adding unit generators, must extend ugen
300+typedef void (CK_DLL_CALL * f_add_ugen_func)( Chuck_DL_Query * query, f_tick tick, f_pmsg pmsg, t_CKUINT num_in, t_CKUINT num_out );
301+typedef void (CK_DLL_CALL * f_add_ugen_funcf)( Chuck_DL_Query * query, f_tickf tickf, f_pmsg pmsg, t_CKUINT num_in, t_CKUINT num_out );
302+typedef void (CK_DLL_CALL * f_add_ugen_funcf_auto_num_channels)( Chuck_DL_Query * query, f_tickf tickf, f_pmsg psmg );
303+// ** add a ugen control
304+typedef void (CK_DLL_CALL * f_add_ugen_ctrl)( Chuck_DL_Query * query, f_ctrl ctrl, f_cget cget,
305+ const char * type, const char * name );
306+// end class/namespace - must correspondent with begin_class. returns false on error
307+typedef t_CKBOOL (CK_DLL_CALL * f_end_class)( Chuck_DL_Query * query );
308+// register
309+typedef Chuck_DL_MainThreadHook * (CK_DLL_CALL * f_create_main_thread_hook)( Chuck_DL_Query * query, f_mainthreadhook hook, f_mainthreadquit quit, void * bindle );
310+
311+// documentation
312+// set current class documentation
313+typedef t_CKBOOL (CK_DLL_CALL * f_doc_class)( Chuck_DL_Query * query, const char * doc );
314+// add example of current class
315+typedef t_CKBOOL (CK_DLL_CALL * f_add_example)( Chuck_DL_Query * query, const char * ex );
316+// set current function documentation
317+typedef t_CKBOOL (CK_DLL_CALL * f_doc_func)( Chuck_DL_Query * query, const char * doc );
318+// set last mvar documentation
319+typedef t_CKBOOL (CK_DLL_CALL * f_doc_var)( Chuck_DL_Query * query, const char * doc );
320+}
321+
322+
323+//-----------------------------------------------------------------------------
324+// name: struct Chuck_DL_Query
325+// desc: passed to module
326+//-----------------------------------------------------------------------------
327+struct Chuck_DL_Query
328+{
329+protected:
330+ // REFACTOR-2017: carrier ref
331+ Chuck_Carrier * m_carrier;
332+
333+public:
334+ // REFACTOR-2017: get associated compiler, vm, env
335+ Chuck_Compiler * compiler() const { return m_carrier->compiler; }
336+ Chuck_VM * vm() const { return m_carrier->vm; }
337+ Chuck_Env * env() const { return m_carrier->env; }
338+
339+public:
340+ // function pointers - to be called from client module
341+ // QUERY->setname( QUERY, ... );
342+ //
343+ // set the name of the module
344+ f_setname setname;
345+ // begin class/namespace, can be nexted
346+ f_begin_class begin_class;
347+ // add constructor, can be followed by add_arg
348+ f_add_ctor add_ctor;
349+ // add destructor, no args allowed
350+ f_add_dtor add_dtor;
351+ // add member function, can be followed by add_arg
352+ f_add_mfun add_mfun;
353+ // add static function, can be followed by add_arg
354+ f_add_sfun add_sfun;
355+ // add member variable
356+ f_add_mvar add_mvar;
357+ // add static variable
358+ f_add_svar add_svar;
359+ // add argument to function
360+ f_add_arg add_arg;
361+ // (ugen only) add tick and pmsg functions
362+ f_add_ugen_func add_ugen_func;
363+ // (ugen only) add tick and pmsg functions
364+ f_add_ugen_funcf add_ugen_funcf;
365+ // (ugen only) add tick and pmsg functions, specify channels by vm
366+ f_add_ugen_funcf_auto_num_channels add_ugen_funcf_auto_num_channels;
367+ // (ugen only) add ctrl parameters
368+ f_add_ugen_ctrl add_ugen_ctrl;
369+ // end class/namespace, compile it
370+ f_end_class end_class;
371+
372+ // added 1.3.2.0
373+ f_create_main_thread_hook create_main_thread_hook;
374+
375+ // added 1.3.5
376+ Chuck_DL_Value * last_var;
377+ f_doc_class doc_class;
378+ f_doc_func doc_func;
379+ f_doc_var doc_var;
380+ f_add_example add_ex;
381+
382+ // NOTE: everything below std::anything cannot be reliably accessed
383+ // by offset between dynamic modules, since std::anything could be variable
384+ // size -- put everything need to be accessed across modules above here!
385+ // discovered by the vigilant and forever traumatized Jack Atherton,
386+ // fixed during REFACTOR-2017; warning by the guilt-ridden Ge Wang
387+
388+ // dll
389+ Chuck_DLL * dll_ref;
390+ // reserved
391+ void * reserved;
392+ // sample rate
393+ t_CKUINT srate;
394+ // bsize
395+ t_CKUINT bufsize;
396+ // line pos
397+ int linepos;
398+ // name of dll
399+ std::string dll_name;
400+
401+ // current class
402+ Chuck_DL_Class * curr_class;
403+ // current function
404+ Chuck_DL_Func * curr_func;
405+ // name
406+ std::string name;
407+ // collection of class
408+ std::vector<Chuck_DL_Class *> classes;
409+ // stack
410+ std::vector<Chuck_DL_Class * >stack;
411+
412+ // constructor
413+ Chuck_DL_Query( Chuck_Carrier * carrier );
414+ // desctructor
415+ ~Chuck_DL_Query() { this->clear(); }
416+ // clear
417+ void clear();
418+};
419+
420+
421+
422+
423+//-----------------------------------------------------------------------------
424+// name: struct Chuck_DL_Class
425+// desc: class built from module
426+//-----------------------------------------------------------------------------
427+struct Chuck_DL_Class
428+{
429+ // the name of the class
430+ std::string name;
431+ // the name of the parent
432+ std::string parent;
433+ // ctor
434+ std::vector<Chuck_DL_Func *> ctors;
435+ // dtor
436+ Chuck_DL_Func * dtor;
437+ // mfun
438+ std::vector<Chuck_DL_Func *> mfuns;
439+ // sfun
440+ std::vector<Chuck_DL_Func *> sfuns;
441+ // mdata
442+ std::vector<Chuck_DL_Value *> mvars;
443+ // sdata
444+ std::vector<Chuck_DL_Value *> svars;
445+ // ugen_tick
446+ f_tick ugen_tick;
447+ // ugen_tickf
448+ f_tickf ugen_tickf;
449+ // ugen_pmsg
450+ f_pmsg ugen_pmsg;
451+ // ugen_ctrl/cget
452+ std::vector<Chuck_DL_Ctrl *> ugen_ctrl;
453+ // uana_tock
454+ f_tock uana_tock;
455+ // collection of recursive classes
456+ std::vector<Chuck_DL_Class *> classes;
457+ // current mvar offset
458+ t_CKUINT current_mvar_offset;
459+
460+ t_CKUINT ugen_num_in, ugen_num_out;
461+
462+ std::string doc;
463+ std::vector<std::string> examples;
464+
465+ // constructor
466+ Chuck_DL_Class() { dtor = NULL; ugen_tick = NULL; ugen_tickf = NULL; ugen_pmsg = NULL; uana_tock = NULL; ugen_pmsg = NULL; current_mvar_offset = 0; ugen_num_in = ugen_num_out = 0; }
467+ // destructor
468+ ~Chuck_DL_Class();
469+};
470+
471+
472+
473+
474+//-----------------------------------------------------------------------------
475+// name: struct Chuck_DL_Value
476+// desc: value from module
477+//-----------------------------------------------------------------------------
478+struct Chuck_DL_Value
479+{
480+ // the name of the value
481+ std::string name;
482+ // the type of the value
483+ std::string type;
484+ // is const
485+ t_CKBOOL is_const;
486+ // addr static
487+ void * static_addr;
488+ // description
489+ std::string doc;
490+
491+ // constructor
492+ Chuck_DL_Value() { is_const = FALSE; static_addr = NULL; }
493+ Chuck_DL_Value( const char * t, const char * n, t_CKBOOL c = FALSE, void * a = NULL )
494+ { name = n; type = t; is_const = c; static_addr = a; }
495+};
496+
497+
498+
499+
500+//-----------------------------------------------------------------------------
501+// name: struct Chuck_DL_Func
502+// desc: function from module
503+//-----------------------------------------------------------------------------
504+struct Chuck_DL_Func
505+{
506+ // the name of the function
507+ std::string name;
508+ // the return type
509+ std::string type;
510+ // the pointer
511+ union { f_ctor ctor; f_dtor dtor; f_mfun mfun; f_sfun sfun; t_CKUINT addr; };
512+ // arguments
513+ std::vector<Chuck_DL_Value *> args;
514+ // description
515+ std::string doc;
516+
517+ // constructor
518+ Chuck_DL_Func() { ctor = NULL; }
519+ Chuck_DL_Func( const char * t, const char * n, t_CKUINT a )
520+ { name = n; type = t; addr = a; }
521+ // destructor
522+ ~Chuck_DL_Func();
523+ // add arg
524+ void add_arg( const char * t, const char * n )
525+ { args.push_back( new Chuck_DL_Value( t, n ) ); }
526+};
527+
528+
529+
530+
531+//-----------------------------------------------------------------------------
532+// name: struct Chuck_DL_Ctrl
533+// desc: ctrl for ugen
534+//-----------------------------------------------------------------------------
535+struct Chuck_DL_Ctrl
536+{
537+ // the name of the ctrl
538+ std::string name;
539+ // the first type
540+ std::string type;
541+ // the types of the value
542+ std::vector<std::string> types;
543+ // ctrl
544+ f_ctrl ctrl;
545+ // cget
546+ f_cget cget;
547+};
548+
549+
550+
551+
552+//------------------------------------------------------------------------------
553+// alternative functions to make stuff
554+//------------------------------------------------------------------------------
555+Chuck_DL_Func * make_new_mfun( const char * t, const char * n, f_mfun mfun );
556+Chuck_DL_Func * make_new_sfun( const char * t, const char * n, f_sfun sfun );
557+Chuck_DL_Value * make_new_arg( const char * t, const char * n );
558+Chuck_DL_Value * make_new_mvar( const char * t, const char * n, t_CKBOOL c = FALSE );
559+Chuck_DL_Value * make_new_svar( const char * t, const char * n, t_CKBOOL c, void * a );
560+
561+
562+
563+
564+//------------------------------------------------------------------------------
565+// name: union Chuck_DL_Return
566+// desc: dynamic link return function return struct
567+//------------------------------------------------------------------------------
568+union Chuck_DL_Return
569+{
570+ t_CKINT v_int;
571+ t_CKUINT v_uint;
572+ t_CKFLOAT v_float;
573+ t_CKDUR v_dur;
574+ t_CKTIME v_time;
575+ t_CKCOMPLEX v_complex;
576+ t_CKPOLAR v_polar;
577+ t_CKVEC3 v_vec3; // ge: added 1.3.5.3
578+ t_CKVEC4 v_vec4; // ge: added 1.3.5.3
579+ Chuck_Object * v_object;
580+ Chuck_String * v_string;
581+
582+ Chuck_DL_Return() { v_vec4.x = v_vec4.y = v_vec4.z = v_vec4.w = 0; }
583+};
584+
585+
586+
587+
588+//-----------------------------------------------------------------------------
589+// name: struct Chuck_DLL
590+// desc: dynamic link library
591+//-----------------------------------------------------------------------------
592+struct Chuck_DLL : public Chuck_VM_Object
593+{
594+public:
595+ // load dynamic ckx/dll from filename
596+ t_CKBOOL load( const char * filename,
597+ const char * func = CK_QUERY_FUNC,
598+ t_CKBOOL lazy = FALSE );
599+ t_CKBOOL load( f_ck_query query_func, t_CKBOOL lazy = FALSE );
600+ // get address in loaded ckx
601+ void * get_addr( const char * symbol );
602+ // get last error
603+ const char * last_error() const;
604+ // unload the ckx
605+ t_CKBOOL unload( );
606+ // query the content of the dll
607+ const Chuck_DL_Query * query( );
608+ // is good
609+ t_CKBOOL good() const;
610+ // name
611+ const char * name() const;
612+
613+public:
614+ // constructor
615+ Chuck_DLL( Chuck_Carrier * carrier, const char * xid = NULL )
616+ : m_handle(NULL), m_id(xid ? xid : ""),
617+ m_query( carrier ),
618+ m_done_query(FALSE), m_query_func(NULL), m_version_func(NULL)
619+ { }
620+ // destructor
621+ ~Chuck_DLL() { this->unload(); }
622+
623+protected:
624+ // data
625+ void * m_handle;
626+ std::string m_last_error;
627+ std::string m_filename;
628+ std::string m_id;
629+ std::string m_func;
630+ t_CKBOOL m_done_query;
631+
632+ f_ck_declversion m_version_func;
633+ f_ck_query m_query_func;
634+ Chuck_DL_Query m_query;
635+};
636+
637+struct Chuck_DL_MainThreadHook
638+{
639+public:
640+ Chuck_DL_MainThreadHook(f_mainthreadhook hook, f_mainthreadquit quit,
641+ void * bindle, Chuck_VM * vm);
642+ t_CKBOOL (* const activate)(Chuck_DL_MainThreadHook *);
643+ t_CKBOOL (* const deactivate)(Chuck_DL_MainThreadHook *);
644+
645+ Chuck_VM * const m_vm;
646+ f_mainthreadhook const m_hook;
647+ f_mainthreadquit const m_quit;
648+ void * const m_bindle;
649+ t_CKBOOL m_active;
650+};
651+
652+
653+
654+
655+/* API to ChucK's innards */
656+namespace Chuck_DL_Api
657+{
658+typedef void * Object;
659+typedef void * Type;
660+typedef void * String;
661+
662+struct Api
663+{
664+public:
665+ static Api g_api;
666+ static inline const Api * instance() { return &g_api; }
667+
668+ struct VMApi
669+ {
670+ VMApi();
671+ t_CKUINT (* const get_srate)( CK_DL_API, Chuck_VM_Shred * );
672+ } * const vm;
673+
674+ struct ObjectApi
675+ {
676+ ObjectApi();
677+
678+ private:
679+ Type (* const get_type)( CK_DL_API, Chuck_VM_Shred *, std::string &name );
680+
681+ Object (* const create)( CK_DL_API, Chuck_VM_Shred *, Type type );
682+
683+ String (* const create_string)( CK_DL_API, Chuck_VM_Shred *, std::string &value );
684+
685+ t_CKBOOL (* const get_mvar_int)( CK_DL_API, Object object, std::string &name, t_CKINT &value );
686+ t_CKBOOL (* const get_mvar_float)( CK_DL_API, Object object, std::string &name, t_CKFLOAT &value );
687+ t_CKBOOL (* const get_mvar_dur)( CK_DL_API, Object object, std::string &name, t_CKDUR &value );
688+ t_CKBOOL (* const get_mvar_time)( CK_DL_API, Object object, std::string &name, t_CKTIME &value );
689+ t_CKBOOL (* const get_mvar_string)( CK_DL_API, Object object, std::string &name, String &value );
690+ t_CKBOOL (* const get_mvar_object)( CK_DL_API, Object object, std::string &name, Object &value );
691+
692+ t_CKBOOL (* const set_string)( CK_DL_API, String string, std::string &value );
693+
694+ } * const object;
695+
696+ Api() :
697+ vm(new VMApi),
698+ object(new ObjectApi)
699+ {}
700+
701+private:
702+ Api(Api &a) :
703+ vm(a.vm),
704+ object(a.object)
705+ { assert(0); };
706+
707+ Api &operator=(Api &a) { assert(0); return a; }
708+};
709+}
710+
711+
712+
713+// dlfcn interface
714+#if defined(__MACOSX_CORE__)
715+#include <AvailabilityMacros.h>
716+#endif
717+
718+// dlfcn interface, panther or below
719+#if defined(__MACOSX_CORE__) && MAC_OS_X_VERSION_MAX_ALLOWED <= 1030
720+
721+#error ChucK not support on Mac OS X 10.3 or lower
722+
723+#elif defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__)
724+
725+ #ifdef __cplusplus
726+ extern "C" {
727+ #endif
728+
729+ #define RTLD_LAZY 0x1
730+ #define RTLD_NOW 0x2
731+ #define RTLD_LOCAL 0x4
732+ #define RTLD_GLOBAL 0x8
733+ #define RTLD_NOLOAD 0x10
734+ #define RTLD_SHARED 0x20 /* not used, the default */
735+ #define RTLD_UNSHARED 0x40
736+ #define RTLD_NODELETE 0x80
737+ #define RTLD_LAZY_UNDEF 0x100
738+
739+ void * dlopen( const char * path, int mode );
740+ void * dlsym( void * handle, const char * symbol );
741+ const char * dlerror( void );
742+ int dlclose( void * handle );
743+ static char dlerror_buffer[128];
744+
745+ #ifdef __cplusplus
746+ }
747+ #endif
748+
749+#else
750+ #include "dlfcn.h"
751+#endif
752+
753+
754+
755+#endif
core/chuck_emit.cpp+4972−0
@@ -0,0 +1,4972 @@
1+/*----------------------------------------------------------------------------
2+ ChucK Concurrent, On-the-fly Audio Programming Language
3+ Compiler and Virtual Machine
4+
5+ Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6+ http://chuck.stanford.edu/
7+ http://chuck.cs.princeton.edu/
8+
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.
13+
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.
18+
19+ You should have received a copy of the GNU General Public License
20+ along with this program; if not, write to the Free Software
21+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22+ U.S.A.
23+-----------------------------------------------------------------------------*/
24+
25+//-----------------------------------------------------------------------------
26+// file: chuck_emit.cpp
27+// desc: chuck instruction emitter
28+//
29+// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
30+// date: Autumn 2002 - first version
31+// Autumn 2004 - redesign
32+//-----------------------------------------------------------------------------
33+#include "chuck_emit.h"
34+#include "chuck_vm.h"
35+#include "chuck_errmsg.h"
36+#include "chuck_instr.h"
37+#include <sstream>
38+#include <iostream>
39+
40+using namespace std;
41+
42+
43+
44+
45+//-----------------------------------------------------------------------------
46+// function prototypes
47+//-----------------------------------------------------------------------------
48+t_CKBOOL emit_engine_emit_stmt_list( Chuck_Emitter * emit, a_Stmt_List list );
49+t_CKBOOL emit_engine_emit_stmt( Chuck_Emitter * emit, a_Stmt stmt, t_CKBOOL pop = TRUE );
50+t_CKBOOL emit_engine_emit_if( Chuck_Emitter * emit, a_Stmt_If stmt );
51+t_CKBOOL emit_engine_emit_for( Chuck_Emitter * emit, a_Stmt_For stmt );
52+t_CKBOOL emit_engine_emit_while( Chuck_Emitter * emit, a_Stmt_While stmt );
53+t_CKBOOL emit_engine_emit_do_while( Chuck_Emitter * emit, a_Stmt_While stmt );
54+t_CKBOOL emit_engine_emit_until( Chuck_Emitter * emit, a_Stmt_Until stmt );
55+t_CKBOOL emit_engine_emit_do_until( Chuck_Emitter * emit, a_Stmt_Until stmt );
56+t_CKBOOL emit_engine_emit_loop( Chuck_Emitter * emit, a_Stmt_Loop stmt );
57+t_CKBOOL emit_engine_emit_break( Chuck_Emitter * emit, a_Stmt_Break br );
58+t_CKBOOL emit_engine_emit_continue( Chuck_Emitter * emit, a_Stmt_Continue cont );
59+t_CKBOOL emit_engine_emit_return( Chuck_Emitter * emit, a_Stmt_Return stmt );
60+t_CKBOOL emit_engine_emit_switch( Chuck_Emitter * emit, a_Stmt_Switch stmt );
61+t_CKBOOL emit_engine_emit_exp( Chuck_Emitter * emit, a_Exp exp, t_CKBOOL doAddRef = FALSE );
62+t_CKBOOL emit_engine_emit_exp_binary( Chuck_Emitter * emit, a_Exp_Binary binary );
63+t_CKBOOL emit_engine_emit_op( Chuck_Emitter * emit, ae_Operator op, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary );
64+t_CKBOOL emit_engine_emit_op_chuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary );
65+t_CKBOOL emit_engine_emit_op_unchuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs );
66+t_CKBOOL emit_engine_emit_op_upchuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs );
67+t_CKBOOL emit_engine_emit_op_at_chuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs );
68+t_CKBOOL emit_engine_emit_exp_unary( Chuck_Emitter * emit, a_Exp_Unary unary );
69+t_CKBOOL emit_engine_emit_exp_primary( Chuck_Emitter * emit, a_Exp_Primary exp );
70+t_CKBOOL emit_engine_emit_exp_cast( Chuck_Emitter * emit, a_Exp_Cast cast );
71+t_CKBOOL emit_engine_emit_exp_postfix( Chuck_Emitter * emit, a_Exp_Postfix postfix );
72+t_CKBOOL emit_engine_emit_exp_dur( Chuck_Emitter * emit, a_Exp_Dur dur );
73+t_CKBOOL emit_engine_emit_exp_array( Chuck_Emitter * emit, a_Exp_Array array );
74+t_CKBOOL emit_engine_emit_exp_func_call( Chuck_Emitter * emit, Chuck_Func * func,
75+ Chuck_Type * type, int linepos, t_CKBOOL spork = FALSE );
76+t_CKBOOL emit_engine_emit_exp_func_call( Chuck_Emitter * emit, a_Exp_Func_Call func_call,
77+ t_CKBOOL spork = FALSE );
78+t_CKBOOL emit_engine_emit_func_args( Chuck_Emitter * emit, a_Exp_Func_Call func_call );
79+t_CKBOOL emit_engine_emit_exp_dot_member( Chuck_Emitter * emit, a_Exp_Dot_Member member );
80+t_CKBOOL emit_engine_emit_exp_if( Chuck_Emitter * emit, a_Exp_If exp_if );
81+t_CKBOOL emit_engine_emit_exp_decl( Chuck_Emitter * emit, a_Exp_Decl decl, t_CKBOOL first_exp );
82+t_CKBOOL emit_engine_emit_array_lit( Chuck_Emitter * emit, a_Array_Sub array );
83+t_CKBOOL emit_engine_emit_complex_lit( Chuck_Emitter * emit, a_Complex val );
84+t_CKBOOL emit_engine_emit_polar_lit( Chuck_Emitter * emit, a_Polar val );
85+t_CKBOOL emit_engine_emit_vec_lit( Chuck_Emitter * emit, a_Vec val );
86+t_CKBOOL emit_engine_emit_code_segment( Chuck_Emitter * emit, a_Stmt_Code stmt,
87+ t_CKBOOL push = TRUE );
88+t_CKBOOL emit_engine_emit_func_def( Chuck_Emitter * emit, a_Func_Def func_def );
89+t_CKBOOL emit_engine_emit_class_def( Chuck_Emitter * emit, a_Class_Def class_def );
90+t_CKBOOL emit_engine_pre_constructor( Chuck_Emitter * emit, Chuck_Type * type );
91+t_CKBOOL emit_engine_instantiate_object( Chuck_Emitter * emit, Chuck_Type * type,
92+ a_Array_Sub array, t_CKBOOL is_ref );
93+t_CKBOOL emit_engine_emit_spork( Chuck_Emitter * emit, a_Exp_Func_Call exp );
94+t_CKBOOL emit_engine_emit_cast( Chuck_Emitter * emit, Chuck_Type * to, Chuck_Type * from );
95+t_CKBOOL emit_engine_emit_symbol( Chuck_Emitter * emit, S_Symbol symbol,
96+ Chuck_Value * v, t_CKBOOL emit_var, int linepos );
97+// disabled until further notice (added 1.3.0.0)
98+// t_CKBOOL emit_engine_emit_spork( Chuck_Emitter * emit, a_Stmt stmt );
99+
100+
101+
102+
103+//-----------------------------------------------------------------------------
104+// name: emit_engine_init()
105+// desc: ...
106+//-----------------------------------------------------------------------------
107+Chuck_Emitter * emit_engine_init( Chuck_Env * env )
108+{
109+ // log
110+ EM_log( CK_LOG_SEVERE, "initializing emitter..." );
111+
112+ // TODO: ensure this in a better way
113+ assert( sizeof(t_CKUINT) == sizeof(void *) );
114+
115+ // allocate new emit
116+ Chuck_Emitter * emit = new Chuck_Emitter;
117+ // set the reference
118+ emit->env = env;
119+
120+ return emit;
121+}
122+
123+
124+
125+
126+//-----------------------------------------------------------------------------
127+// name: emit_engine_shutdown()
128+// desc: ...
129+//-----------------------------------------------------------------------------
130+t_CKBOOL emit_engine_shutdown( Chuck_Emitter *& emit )
131+{
132+ if( !emit ) return FALSE;
133+
134+ // log
135+ EM_log( CK_LOG_SYSTEM, "shutting down emitter..." );
136+
137+ // delete
138+ delete emit;
139+ emit = NULL;
140+
141+ return TRUE;
142+}
143+
144+
145+
146+
147+//-----------------------------------------------------------------------------
148+// name: emit_engine_emit_prog()
149+// desc: ...
150+//-----------------------------------------------------------------------------
151+Chuck_VM_Code * emit_engine_emit_prog( Chuck_Emitter * emit, a_Program prog,
152+ te_HowMuch how_much )
153+{
154+ // make sure the code is NULL
155+ assert( emit->code == NULL );
156+ // make sure the stack is empty
157+ assert( emit->stack.size() == 0 );
158+ // make sure there is a context to emit
159+ assert( emit->env->context != NULL );
160+ // make sure no code
161+ assert( emit->env->context->nspc->pre_ctor == NULL );
162+
163+ // log
164+ EM_log( CK_LOG_FINER, "(pass 4) emitting VM code '%s'...",
165+ emit->env->context->filename.c_str() );
166+ // push indent
167+ EM_pushlog();
168+ // log how much
169+ EM_log( CK_LOG_FINER, "target: %s", howmuch2str( how_much ) );
170+
171+ // return
172+ t_CKBOOL ret = TRUE;
173+ // allocate the code
174+ emit->code = new Chuck_Code;
175+ // set the current context
176+ emit->context = emit->env->context;
177+ // set the namespace
178+ emit->nspc = emit->context->nspc;
179+ // reset the func
180+ emit->func = NULL;
181+ // clear the code stack
182+ emit->stack.clear();
183+ // name the code
184+ // emit->code->name = "(main)";
185+ // whether code need this
186+ emit->code->need_this = TRUE;
187+ // keep track of full path (added 1.3.0.0)
188+ emit->code->filename = emit->context->full_path;
189+ // push global scope (added 1.3.0.0)
190+ emit->push_scope();
191+
192+ // loop over the program sections
193+ while( prog && ret )
194+ {
195+ switch( prog->section->s_type )
196+ {
197+ case ae_section_stmt: // code section
198+ // if only classes, then skip
199+ if( how_much == te_do_classes_only ) break;
200+ // emit statement list
201+ ret = emit_engine_emit_stmt_list( emit, prog->section->stmt_list );
202+ break;
203+
204+ case ae_section_func: // function definition
205+ // if only classes, then skip
206+ if( how_much == te_do_classes_only ) break;
207+ // check function definition
208+ ret = emit_engine_emit_func_def( emit, prog->section->func_def );
209+ break;
210+
211+ case ae_section_class: // class definition
212+ // if no classes, then skip
213+ if( how_much == te_do_no_classes ) break;
214+ // check class definition
215+ ret = emit_engine_emit_class_def( emit, prog->section->class_def );
216+ break;
217+
218+ default: // bad
219+ EM_error2( 0,
220+ "internal compiler error: unrecognized program section..." );
221+ ret = FALSE;
222+ break;
223+ }
224+
225+ // the next
226+ prog = prog->next;
227+ }
228+
229+ if( ret )
230+ {
231+ // pop global scope (added 1.3.0.0)
232+ emit->pop_scope();
233+ // append end of code
234+ emit->append( new Chuck_Instr_EOC );
235+ // make sure
236+ assert( emit->context->nspc->pre_ctor == NULL );
237+ // converted to virtual machine code
238+ emit->context->nspc->pre_ctor = emit_to_code( emit->code, NULL, emit->dump );
239+ // add reference
240+ emit->context->nspc->pre_ctor->add_ref();
241+ }
242+
243+ // clear the code
244+ delete emit->code;
245+ emit->code = NULL;
246+
247+ // pop indent
248+ EM_poplog();
249+
250+ // return the code
251+ return emit->context->nspc->pre_ctor;
252+}
253+
254+
255+
256+
257+//-----------------------------------------------------------------------------
258+// name: emit_to_code()
259+// desc: ...
260+//-----------------------------------------------------------------------------
261+Chuck_VM_Code * emit_to_code( Chuck_Code * in,
262+ Chuck_VM_Code * out,
263+ t_CKBOOL dump )
264+{
265+ // log
266+ EM_log( CK_LOG_FINER, "emitting code: %d VM instructions...",
267+ in->code.size() );
268+ // allocate the vm code
269+ Chuck_VM_Code * code = out ? out : new Chuck_VM_Code;
270+ // make sure
271+ assert( code->num_instr == 0 );
272+ // size
273+ code->num_instr = in->code.size();
274+ // allocate instruction pointers+
275+ code->instr = new Chuck_Instr *[code->num_instr];
276+ // set the stack depth
277+ code->stack_depth = in->stack_depth;
278+ // set whether code need this base pointer
279+ code->need_this = in->need_this;
280+ // set name
281+ code->name = in->name;
282+ // set filename for me.sourceDir() (added 1.3.0.0)
283+ code->filename = in->filename;
284+
285+ // copy
286+ for( t_CKUINT i = 0; i < code->num_instr; i++ )
287+ code->instr[i] = in->code[i];
288+
289+ // dump
290+ if( dump )
291+ {
292+ // name of what we are dumping
293+ EM_error2( 0, "dumping %s:", in->name.c_str() );
294+
295+ // uh
296+ EM_error2( 0, "-------" );
297+ for( t_CKUINT i = 0; i < code->num_instr; i++ )
298+ EM_error2( 0, "[%i] %s( %s )", i,
299+ code->instr[i]->name(), code->instr[i]->params() );
300+ EM_error2( 0, "-------\n" );
301+ }
302+
303+ return code;
304+}
305+
306+
307+
308+
309+//-----------------------------------------------------------------------------
310+// name:
311+// desc: ...
312+//-----------------------------------------------------------------------------
313+// t_CKBOOL emit_engine_addr_map( Chuck_Emitter * emit, Chuck_VM_Shred * shred );
314+
315+
316+
317+
318+//-----------------------------------------------------------------------------
319+// name:
320+// desc: ...
321+//-----------------------------------------------------------------------------
322+// t_CKBOOL emit_engine_resolve( );
323+
324+
325+
326+
327+//-----------------------------------------------------------------------------
328+// name: emit_engine_emit_stmt_list()
329+// desc: ...
330+//-----------------------------------------------------------------------------
331+t_CKBOOL emit_engine_emit_stmt_list( Chuck_Emitter * emit, a_Stmt_List list )
332+{
333+ t_CKBOOL ret = TRUE;
334+
335+ // emit->push();
336+ while( list && ret )
337+ {
338+ ret = emit_engine_emit_stmt( emit, list->stmt );
339+ list = list->next;
340+ }
341+ // emit->pop();
342+
343+ return ret;
344+}
345+
346+
347+
348+
349+//-----------------------------------------------------------------------------
350+// name: emit_engine_emit_stmt()
351+// desc: ...
352+//-----------------------------------------------------------------------------
353+t_CKBOOL emit_engine_emit_stmt( Chuck_Emitter * emit, a_Stmt stmt, t_CKBOOL pop )
354+{
355+ // empty stmt list
356+ if( !stmt )
357+ return TRUE;
358+
359+ // return
360+ t_CKBOOL ret = TRUE;
361+
362+ // loop over statements
363+ switch( stmt->s_type )
364+ {
365+ case ae_stmt_exp: // expression statement
366+ // emit it
367+ ret = emit_engine_emit_exp( emit, stmt->stmt_exp );
368+ if( !ret )
369+ return FALSE;
370+ // need to pop the final value from stack
371+ if( ret && pop && stmt->stmt_exp->type->size > 0 )
372+ {
373+ // sanity
374+ assert( stmt->stmt_exp->cast_to == NULL );
375+
376+ // exp
377+ a_Exp exp = stmt->stmt_exp;
378+ // hack
379+ if( exp->s_type == ae_exp_primary && exp->primary.s_type == ae_primary_hack )
380+ exp = exp->primary.exp;
381+
382+ // HACK!
383+ while( exp )
384+ {
385+ // if decl, then expect only one word per var
386+ // added 1.3.1.0: iskindofint -- since on some 64-bit systems sz_INT == sz_FLOAT
387+ if( exp->s_type == ae_exp_decl )
388+ // (added 1.3.1.0 -- multiply by type size; #64-bit)
389+ // (fixed 1.3.1.2 -- uh... decl should also be int-sized, so changed to INT/WORD)
390+ emit->append( new Chuck_Instr_Reg_Pop_Word4( exp->decl.num_var_decls * sz_INT / sz_WORD ) );
391+ else if( exp->type->size == sz_INT && iskindofint(emit->env, exp->type) ) // ISSUE: 64-bit (fixed 1.3.1.0)
392+ emit->append( new Chuck_Instr_Reg_Pop_Word );
393+ else if( exp->type->size == sz_FLOAT ) // ISSUE: 64-bit (fixed 1.3.1.0)
394+ emit->append( new Chuck_Instr_Reg_Pop_Word2 );
395+ else if( exp->type->size == sz_COMPLEX ) // ISSUE: 64-bit (fixed 1.3.1.0)
396+ emit->append( new Chuck_Instr_Reg_Pop_Word3 );
397+ else if( exp->type->size == sz_VEC3 ) // ge: added 1.3.5.3
398+ emit->append( new Chuck_Instr_Reg_Pop_Word4(sz_VEC3/sz_WORD) );
399+ else if( exp->type->size == sz_VEC4 ) // ge: added 1.3.5.3
400+ emit->append( new Chuck_Instr_Reg_Pop_Word4(sz_VEC4/sz_WORD) );
401+ else
402+ {
403+ EM_error2( exp->linepos,
404+ "(emit): internal error: %i byte stack item unhandled...",
405+ exp->type->size );
406+ return FALSE;
407+ }
408+
409+ // go
410+ exp = exp->next;
411+ }
412+ }
413+ break;
414+
415+ case ae_stmt_if: // if statement
416+ ret = emit_engine_emit_if( emit, &stmt->stmt_if );
417+ break;
418+
419+ case ae_stmt_for: // for statement
420+ ret = emit_engine_emit_for( emit, &stmt->stmt_for );
421+ break;
422+
423+ case ae_stmt_while: // while statement
424+ if( stmt->stmt_while.is_do )
425+ ret = emit_engine_emit_do_while( emit, &stmt->stmt_while );
426+ else
427+ ret = emit_engine_emit_while( emit, &stmt->stmt_while );
428+ break;
429+
430+ case ae_stmt_until: // until statement
431+ if( stmt->stmt_until.is_do )
432+ ret = emit_engine_emit_do_until( emit, &stmt->stmt_until );
433+ else
434+ ret = emit_engine_emit_until( emit, &stmt->stmt_until );
435+ break;
436+
437+ case ae_stmt_loop: // loop statement
438+ ret = emit_engine_emit_loop( emit, &stmt->stmt_loop );
439+ break;
440+
441+ case ae_stmt_switch: // switch statement
442+ // not implemented
443+ ret = FALSE;
444+ break;
445+
446+ case ae_stmt_break: // break statement
447+ ret = emit_engine_emit_break( emit, &stmt->stmt_break );
448+ break;
449+
450+ case ae_stmt_code: // code segment
451+ ret = emit_engine_emit_code_segment( emit, &stmt->stmt_code );
452+ break;
453+
454+ case ae_stmt_continue: // continue statement
455+ ret = emit_engine_emit_continue( emit, &stmt->stmt_continue );
456+ break;
457+
458+ case ae_stmt_return: // return statement
459+ ret = emit_engine_emit_return( emit, &stmt->stmt_return );
460+ break;
461+
462+ case ae_stmt_case: // case statement
463+ // not implemented
464+ ret = FALSE;
465+ // ret = emit_engine_emit_case( emit, &stmt->stmt_case );
466+ break;
467+
468+ case ae_stmt_gotolabel: // goto label statement
469+ // not implemented
470+ ret = FALSE;
471+ // ret = emit_engine_emit_gotolabel( emit, &stmt->stmt_case );
472+ break;
473+
474+ default: // bad
475+ EM_error2( stmt->linepos,
476+ "(emit): internal error: unhandled statement type '%i'...",
477+ stmt->s_type );
478+ break;
479+ }
480+
481+ return ret;
482+}
483+
484+
485+
486+
487+//-----------------------------------------------------------------------------
488+// name: emit_engine_emit_if()
489+// desc: ...
490+//-----------------------------------------------------------------------------
491+t_CKBOOL emit_engine_emit_if( Chuck_Emitter * emit, a_Stmt_If stmt )
492+{
493+ t_CKBOOL ret = TRUE;
494+ Chuck_Instr_Branch_Op * op = NULL, * op2 = NULL;
495+
496+ // push the stack, allowing for new local variables
497+ emit->push_scope();
498+
499+ // emit the condition
500+ ret = emit_engine_emit_exp( emit, stmt->cond );
501+ if( !ret )
502+ return FALSE;
503+
504+ // type of the condition
505+ switch( stmt->cond->type->xid )
506+ {
507+ case te_int:
508+ // push 0
509+ emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
510+ op = new Chuck_Instr_Branch_Eq_int( 0 );
511+ break;
512+ case te_float:
513+ case te_dur:
514+ case te_time:
515+ // push 0
516+ emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) );
517+ op = new Chuck_Instr_Branch_Eq_double( 0 );
518+ break;
519+
520+ default:
521+ // check for IO
522+ if( isa( stmt->cond->type, emit->env->t_io ) )
523+ {
524+ // push 0
525+ emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
526+ op = new Chuck_Instr_Branch_Eq_int_IO_good( 0 );
527+ break;
528+ }
529+
530+ EM_error2( stmt->cond->linepos,
531+ "(emit): internal error: unhandled type '%s' in if condition",
532+ stmt->cond->type->name.c_str() );
533+ return FALSE;
534+ }
535+
536+ if( !ret ) return FALSE;
537+
538+ // append the op
539+ emit->append( op );
540+
541+ // ge: 2012 april: scope for if body (added 1.3.0.0)
542+ {
543+ // push the stack, allowing for new local variables
544+ emit->push_scope();
545+ // emit the body
546+ ret = emit_engine_emit_stmt( emit, stmt->if_body );
547+ if( !ret )
548+ return FALSE;
549+ // pop stack
550+ emit->pop_scope();
551+ }
552+
553+ // emit the skip to the end
554+ emit->append( op2 = new Chuck_Instr_Goto(0) );
555+
556+ // set the op's target
557+ op->set( emit->next_index() );
558+
559+ // ge: 2012 april: scope for else body (added 1.3.0.0)
560+ {
561+ // push the stack, allowing for new local variables
562+ emit->push_scope();
563+ // emit the body
564+ ret = emit_engine_emit_stmt( emit, stmt->else_body );
565+ if( !ret )
566+ return FALSE;
567+ // pop stack
568+ emit->pop_scope();
569+ }
570+
571+ // set the op2's target
572+ op2->set( emit->next_index() );
573+
574+ // pop stack
575+ emit->pop_scope();
576+
577+ return ret;
578+}
579+
580+
581+
582+
583+//-----------------------------------------------------------------------------
584+// name: emit_engine_emit_for()
585+// desc: ...
586+//-----------------------------------------------------------------------------
587+t_CKBOOL emit_engine_emit_for( Chuck_Emitter * emit, a_Stmt_For stmt )
588+{
589+ t_CKBOOL ret = TRUE;
590+ Chuck_Instr_Branch_Op * op = NULL;
591+
592+ // push the stack
593+ emit->push_scope();
594+
595+ // emit the cond
596+ ret = emit_engine_emit_stmt( emit, stmt->c1 );
597+ if( !ret )
598+ return FALSE;
599+
600+ // the start index
601+ t_CKUINT start_index = emit->next_index();
602+ t_CKUINT cont_index = 0;
603+ // mark the stack of continue
604+ emit->code->stack_cont.push_back( NULL );
605+ // mark the stack of break
606+ emit->code->stack_break.push_back( NULL );
607+
608+ // emit the cond - keep the result on the stack
609+ emit_engine_emit_stmt( emit, stmt->c2, FALSE );
610+
611+ // could be NULL
612+ if( stmt->c2 )
613+ {
614+ switch( stmt->c2->stmt_exp->type->xid )
615+ {
616+ case te_int:
617+ // push 0
618+ emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
619+ op = new Chuck_Instr_Branch_Eq_int( 0 );
620+ break;
621+ case te_float:
622+ case te_dur:
623+ case te_time:
624+ // push 0
625+ emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) );
626+ op = new Chuck_Instr_Branch_Eq_double( 0 );
627+ break;
628+
629+ default:
630+ // check for IO
631+ if( isa( stmt->c2->stmt_exp->type, emit->env->t_io ) )
632+ {
633+ // push 0
634+ emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
635+ op = new Chuck_Instr_Branch_Eq_int_IO_good( 0 );
636+ break;
637+ }
638+
639+ EM_error2( stmt->c2->stmt_exp->linepos,
640+ "(emit): internal error: unhandled type '%s' in for conditional",
641+ stmt->c2->stmt_exp->type->name.c_str() );
642+ return FALSE;
643+ }
644+ // append the op
645+ emit->append( op );
646+ }
647+
648+ // added 1.3.1.1: new scope just for loop body
649+ emit->push_scope();
650+
651+ // emit the body
652+ ret = emit_engine_emit_stmt( emit, stmt->body );
653+ if( !ret )
654+ return FALSE;
655+
656+ // added 1.3.1.1: pop scope for loop body
657+ emit->pop_scope();
658+
659+ // continue here
660+ cont_index = emit->next_index();
661+
662+ // emit the action
663+ if( stmt->c3 )
664+ {
665+ ret = emit_engine_emit_exp( emit, stmt->c3 );
666+ if( !ret )
667+ return FALSE;
668+
669+ // HACK!
670+ // count the number of words to pop
671+ a_Exp e = stmt->c3;
672+ t_CKUINT num_words = 0;
673+ while( e )
674+ {
675+ if( e->type->size == sz_FLOAT ) // ISSUE: 64-bit (fixed 1.3.1.0)
676+ num_words += sz_FLOAT / sz_WORD; // changed to compute number of words; 1.3.1.0
677+ else if( e->type->size == sz_INT ) // ISSUE: 64-bit (fixed 1.3.1.0)
678+ num_words += sz_INT / sz_WORD; // changed to compute number of words; 1.3.1.0
679+ else if( e->type->size == sz_COMPLEX ) // ISSUE: 64-bit (fixed 1.3.1.0)
680+ num_words += sz_COMPLEX / sz_WORD; // changed to compute number of words; 1.3.1.0
681+ else if( e->type->size != 0 )
682+ {
683+ EM_error2( e->linepos,
684+ "(emit): internal error: non-void type size %i unhandled...",
685+ e->type->size );
686+ return FALSE;
687+ }
688+
689+ // advance
690+ e = e->next;
691+ }
692+
693+ // pop (changed to Chuck_Instr_Reg_Pop_Word4 in 1.3.1.0)
694+ if( num_words > 0 ) emit->append( new Chuck_Instr_Reg_Pop_Word4( num_words ) );
695+ }
696+
697+ // go back to do check the condition
698+ emit->append( new Chuck_Instr_Goto( start_index ) );
699+
700+ // could be NULL
701+ if( stmt->c2 )
702+ // set the op's target
703+ op->set( emit->next_index() );
704+
705+ // stack of continue
706+ while( emit->code->stack_cont.size() && emit->code->stack_cont.back() )
707+ {
708+ emit->code->stack_cont.back()->set( cont_index );
709+ emit->code->stack_cont.pop_back();
710+ }
711+
712+ // stack of break
713+ while( emit->code->stack_break.size() && emit->code->stack_break.back() )
714+ {
715+ emit->code->stack_break.back()->set( emit->next_index() );
716+ emit->code->stack_break.pop_back();
717+ }
718+
719+ // pop stack
720+ emit->pop_scope();
721+ // pop continue stack
722+ emit->code->stack_cont.pop_back();
723+ // pop break stack
724+ emit->code->stack_break.pop_back();
725+
726+ return ret;
727+}
728+
729+
730+
731+
732+//-----------------------------------------------------------------------------
733+// name: emit_engine_emit_while()
734+// desc: ...
735+//-----------------------------------------------------------------------------
736+t_CKBOOL emit_engine_emit_while( Chuck_Emitter * emit, a_Stmt_While stmt )
737+{
738+ t_CKBOOL ret = TRUE;
739+ Chuck_Instr_Branch_Op * op = NULL;
740+
741+ // push stack
742+ emit->push_scope();
743+
744+ // get the index
745+ t_CKUINT start_index = emit->next_index();
746+ // mark the stack of continue
747+ emit->code->stack_cont.push_back( NULL );
748+ // mark the stack of break
749+ emit->code->stack_break.push_back( NULL );
750+
751+ // emit the cond
752+ ret = emit_engine_emit_exp( emit, stmt->cond );
753+ if( !ret )
754+ return FALSE;
755+
756+ // the condition
757+ switch( stmt->cond->type->xid )
758+ {
759+ case te_int:
760+ // push 0
761+ emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
762+ op = new Chuck_Instr_Branch_Eq_int( 0 );
763+ break;
764+ case te_float:
765+ case te_dur:
766+ case te_time:
767+ // push 0
768+ emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) );
769+ op = new Chuck_Instr_Branch_Eq_double( 0 );
770+ break;
771+
772+ default:
773+ // check for IO
774+ if( isa( stmt->cond->type, emit->env->t_io ) )
775+ {
776+ // push 0
777+ emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
778+ op = new Chuck_Instr_Branch_Eq_int_IO_good( 0 );
779+ break;
780+ }
781+
782+ EM_error2( stmt->cond->linepos,
783+ "(emit): internal error: unhandled type '%s' in while conditional",
784+ stmt->cond->type->name.c_str() );
785+ return FALSE;
786+ }
787+
788+ // append the op
789+ emit->append( op );
790+
791+ // added 1.3.1.1: new scope just for loop body
792+ emit->push_scope();
793+
794+ // emit the body
795+ ret = emit_engine_emit_stmt( emit, stmt->body );
796+ if( !ret )
797+ return FALSE;
798+
799+ // added 1.3.1.1: pop scope for loop body
800+ emit->pop_scope();
801+
802+ // go back to do check the condition
803+ emit->append( new Chuck_Instr_Goto( start_index ) );
804+
805+ // set the op's target
806+ op->set( emit->next_index() );
807+
808+ // stack of continue
809+ while( emit->code->stack_cont.size() && emit->code->stack_cont.back() )
810+ {
811+ emit->code->stack_cont.back()->set( start_index );
812+ emit->code->stack_cont.pop_back();
813+ }
814+
815+ // stack of break
816+ while( emit->code->stack_break.size() && emit->code->stack_break.back() )
817+ {
818+ emit->code->stack_break.back()->set( emit->next_index() );
819+ emit->code->stack_break.pop_back();
820+ }
821+
822+ // pop stack
823+ emit->pop_scope();
824+ // pop continue stack
825+ emit->code->stack_cont.pop_back();
826+ // pop break stack
827+ emit->code->stack_break.pop_back();
828+
829+ return ret;
830+}
831+
832+
833+
834+
835+//-----------------------------------------------------------------------------
836+// name: emit_engine_emit_do_while()
837+// desc: ...
838+//-----------------------------------------------------------------------------
839+t_CKBOOL emit_engine_emit_do_while( Chuck_Emitter * emit, a_Stmt_While stmt )
840+{
841+ t_CKBOOL ret = TRUE;
842+ Chuck_Instr_Branch_Op * op = NULL;
843+ t_CKUINT start_index = emit->next_index();
844+
845+ // push stack
846+ emit->push_scope();
847+
848+ // mark the stack of continue
849+ emit->code->stack_cont.push_back( NULL );
850+ // mark the stack of break
851+ emit->code->stack_break.push_back( NULL );
852+
853+ // added 1.3.1.1: new scope just for loop body
854+ emit->push_scope();
855+
856+ // emit the body
857+ ret = emit_engine_emit_stmt( emit, stmt->body );
858+ if( !ret )
859+ return FALSE;
860+
861+ // added 1.3.1.1: pop scope for loop body
862+ emit->pop_scope();
863+
864+ // emit the cond
865+ ret = emit_engine_emit_exp( emit, stmt->cond );
866+ if( !ret )
867+ return FALSE;
868+
869+ // the condition
870+ switch( stmt->cond->type->xid )
871+ {
872+ case te_int:
873+ // push 0
874+ emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
875+ op = new Chuck_Instr_Branch_Neq_int( 0 );
876+ break;
877+ case te_float:
878+ case te_dur:
879+ case te_time:
880+ // push 0
881+ emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) );
882+ op = new Chuck_Instr_Branch_Neq_double( 0 );
883+ break;
884+
885+ default:
886+ // check for IO
887+ if( isa( stmt->cond->type, emit->env->t_io ) )
888+ {
889+ // push 0
890+ emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
891+ op = new Chuck_Instr_Branch_Eq_int_IO_good( 0 );
892+ break;
893+ }
894+
895+ EM_error2( stmt->cond->linepos,
896+ "(emit): internal error: unhandled type '%s' in do/while conditional",
897+ stmt->cond->type->c_name() );
898+ return FALSE;
899+ }
900+
901+ // append the op
902+ emit->append( op );
903+
904+ // set the op's target
905+ op->set( start_index );
906+
907+ // stack of continue
908+ while( emit->code->stack_cont.size() && emit->code->stack_cont.back() )
909+ {
910+ emit->code->stack_cont.back()->set( start_index );
911+ emit->code->stack_cont.pop_back();
912+ }
913+
914+ // stack of break
915+ while( emit->code->stack_break.size() && emit->code->stack_break.back() )
916+ {
917+ emit->code->stack_break.back()->set( emit->next_index() );
918+ emit->code->stack_break.pop_back();
919+ }
920+
921+ // pop stack
922+ emit->pop_scope();
923+ // pop continue stack
924+ emit->code->stack_cont.pop_back();
925+ // pop break stack
926+ emit->code->stack_break.pop_back();
927+
928+ return ret;
929+}
930+
931+
932+
933+
934+//-----------------------------------------------------------------------------
935+// name: emit_engine_emit_until()
936+// desc: ...
937+//-----------------------------------------------------------------------------
938+t_CKBOOL emit_engine_emit_until( Chuck_Emitter * emit, a_Stmt_Until stmt )
939+{
940+ t_CKBOOL ret = TRUE;
941+ Chuck_Instr_Branch_Op * op = NULL;
942+
943+ // push stack
944+ emit->push_scope();
945+
946+ // get index
947+ t_CKUINT start_index = emit->next_index();
948+ // mark the stack of continue
949+ emit->code->stack_cont.push_back( NULL );
950+ // mark the stack of break
951+ emit->code->stack_break.push_back( NULL );
952+
953+ // emit the cond
954+ ret = emit_engine_emit_exp( emit, stmt->cond );
955+ if( !ret )
956+ return FALSE;
957+
958+ // condition
959+ switch( stmt->cond->type->xid )
960+ {
961+ case te_int:
962+ // push 0
963+ emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
964+ op = new Chuck_Instr_Branch_Neq_int( 0 );
965+ break;
966+ case te_float:
967+ case te_dur:
968+ case te_time:
969+ // push 0
970+ emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) );
971+ op = new Chuck_Instr_Branch_Neq_double( 0 );
972+ break;
973+
974+ default:
975+ // check for IO
976+ if( isa( stmt->cond->type, emit->env->t_io ) )
977+ {
978+ // push 0
979+ emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
980+ op = new Chuck_Instr_Branch_Neq_int_IO_good( 0 );
981+ break;
982+ }
983+
984+ EM_error2( stmt->cond->linepos,
985+ "(emit): internal error: unhandled type '%s' in until conditional",
986+ stmt->cond->type->name.c_str() );
987+ return FALSE;
988+ }
989+
990+ // append the op
991+ emit->append( op );
992+
993+ // added 1.3.1.1: new scope just for loop body
994+ emit->push_scope();
995+
996+ // emit the body
997+ emit_engine_emit_stmt( emit, stmt->body );
998+
999+ // added 1.3.1.1: pop scope for loop body
1000+ emit->pop_scope();
1001+
1002+ // go back to do check the condition
1003+ emit->append( new Chuck_Instr_Goto( start_index ) );
1004+
1005+ // set the op's target
1006+ op->set( emit->next_index() );
1007+
1008+ // stack of continue
1009+ while( emit->code->stack_cont.size() && emit->code->stack_cont.back() )
1010+ {
1011+ emit->code->stack_cont.back()->set( start_index );
1012+ emit->code->stack_cont.pop_back();
1013+ }
1014+
1015+ // stack of break
1016+ while( emit->code->stack_break.size() && emit->code->stack_break.back() )
1017+ {
1018+ emit->code->stack_break.back()->set( emit->next_index() );
1019+ emit->code->stack_break.pop_back();
1020+ }
1021+
1022+ // pop stack
1023+ emit->pop_scope();
1024+ // pop continue stack
1025+ emit->code->stack_cont.pop_back();
1026+ // pop break stack
1027+ emit->code->stack_break.pop_back();
1028+
1029+ return ret;
1030+}
1031+
1032+
1033+
1034+
1035+//-----------------------------------------------------------------------------
1036+// name: emit_engine_emit_do_until()
1037+// desc: ...
1038+//-----------------------------------------------------------------------------
1039+t_CKBOOL emit_engine_emit_do_until( Chuck_Emitter * emit, a_Stmt_Until stmt )
1040+{
1041+ t_CKBOOL ret = TRUE;
1042+ Chuck_Instr_Branch_Op * op = NULL;
1043+
1044+ // push stack
1045+ emit->push_scope();
1046+
1047+ // the index
1048+ t_CKUINT start_index = emit->next_index();
1049+ // mark the stack of continue
1050+ emit->code->stack_cont.push_back( NULL );
1051+ // mark the stack of break
1052+ emit->code->stack_break.push_back( NULL );
1053+
1054+ // added 1.3.1.1: new scope just for loop body
1055+ emit->push_scope();
1056+
1057+ // emit the body
1058+ ret = emit_engine_emit_stmt( emit, stmt->body );
1059+ if( !ret )
1060+ return FALSE;
1061+
1062+ // added 1.3.1.1: pop scope for loop body
1063+ emit->pop_scope();
1064+
1065+ // emit the cond
1066+ ret = emit_engine_emit_exp( emit, stmt->cond );
1067+ if( !ret )
1068+ return FALSE;
1069+
1070+ // condition
1071+ switch( stmt->cond->type->xid )
1072+ {
1073+ case te_int:
1074+ // push 0
1075+ emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
1076+ op = new Chuck_Instr_Branch_Eq_int( 0 );
1077+ break;
1078+ case te_float:
1079+ case te_dur:
1080+ case te_time:
1081+ // push 0
1082+ emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) );
1083+ op = new Chuck_Instr_Branch_Eq_double( 0 );
1084+ break;
1085+
1086+ default:
1087+ EM_error2( stmt->cond->linepos,
1088+ "(emit): internal error: unhandled type '%s' in do/until conditional",
1089+ stmt->cond->type->name.c_str() );
1090+ return FALSE;
1091+ }
1092+
1093+ // append the op
1094+ emit->append( op );
1095+
1096+ // set the op's target
1097+ op->set( start_index );
1098+
1099+ // stack of continue
1100+ while( emit->code->stack_cont.size() && emit->code->stack_cont.back() )
1101+ {
1102+ emit->code->stack_cont.back()->set( start_index );
1103+ emit->code->stack_cont.pop_back();
1104+ }
1105+
1106+ // stack of break
1107+ while( emit->code->stack_break.size() && emit->code->stack_break.back() )
1108+ {
1109+ emit->code->stack_break.back()->set( emit->next_index() );
1110+ emit->code->stack_break.pop_back();
1111+ }
1112+
1113+ // pop stack
1114+ emit->pop_scope();
1115+ // pop continue stack
1116+ emit->code->stack_cont.pop_back();
1117+ // pop break stack
1118+ emit->code->stack_break.pop_back();
1119+
1120+ return ret;
1121+}
1122+
1123+
1124+
1125+
1126+//-----------------------------------------------------------------------------
1127+// name: emit_engine_emit_loop()
1128+// desc: ...
1129+//-----------------------------------------------------------------------------
1130+t_CKBOOL emit_engine_emit_loop( Chuck_Emitter * emit, a_Stmt_Loop stmt )
1131+{
1132+ t_CKBOOL ret = TRUE;
1133+ Chuck_Instr_Branch_Op * op = NULL;
1134+
1135+ Chuck_Instr * instr = NULL;
1136+
1137+ // push stack
1138+ emit->push_scope();
1139+
1140+ // emit the cond
1141+ ret = emit_engine_emit_exp( emit, stmt->cond );
1142+ if( !ret )
1143+ return FALSE;
1144+
1145+ // initialize our loop counter (1.3.5.3)
1146+ emit->append( new Chuck_Instr_Init_Loop_Counter() );
1147+
1148+ // get the index
1149+ t_CKUINT start_index = emit->next_index();
1150+ // mark the stack of continue
1151+ emit->code->stack_cont.push_back( NULL );
1152+ // mark the stack of break
1153+ emit->code->stack_break.push_back( NULL );
1154+
1155+ // push the value of the loop counter
1156+ emit->append( instr = new Chuck_Instr_Reg_Push_Loop_Counter_Deref() );
1157+ instr->set_linepos( stmt->linepos );
1158+
1159+ // get the type, taking cast into account
1160+ Chuck_Type * type = stmt->cond->cast_to ? stmt->cond->cast_to : stmt->cond->type;
1161+
1162+ // the condition
1163+ switch( type->xid )
1164+ {
1165+ case te_int:
1166+ // push 0
1167+ emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
1168+ op = new Chuck_Instr_Branch_Eq_int( 0 );
1169+ break;
1170+
1171+ default:
1172+ EM_error2( stmt->cond->linepos,
1173+ "(emit): internal error: unhandled type '%s' in while conditional",
1174+ type->name.c_str() );
1175+
1176+ return FALSE;
1177+ }
1178+
1179+ // append the op
1180+ emit->append( op );
1181+
1182+ // decrement the counter
1183+ emit->append( instr = new Chuck_Instr_Dec_Loop_Counter() );
1184+ instr->set_linepos( stmt->linepos );
1185+
1186+ // added 1.3.1.1: new scope just for loop body
1187+ emit->push_scope();
1188+
1189+ // emit the body
1190+ ret = emit_engine_emit_stmt( emit, stmt->body );
1191+ if( !ret )
1192+ return FALSE;
1193+
1194+ // added 1.3.1.1: pop scope for loop body
1195+ emit->pop_scope();
1196+
1197+ // go back to do check the condition
1198+ emit->append( new Chuck_Instr_Goto( start_index ) );
1199+
1200+ // set the op's target
1201+ op->set( emit->next_index() );
1202+
1203+ // pop the loop counter
1204+ emit->append( new Chuck_Instr_Pop_Loop_Counter );
1205+
1206+ // stack of continue
1207+ while( emit->code->stack_cont.size() && emit->code->stack_cont.back() )
1208+ {
1209+ emit->code->stack_cont.back()->set( start_index );
1210+ emit->code->stack_cont.pop_back();
1211+ }
1212+
1213+ // stack of break
1214+ while( emit->code->stack_break.size() && emit->code->stack_break.back() )
1215+ {
1216+ emit->code->stack_break.back()->set( emit->next_index() );
1217+ emit->code->stack_break.pop_back();
1218+ }
1219+
1220+ // pop stack
1221+ emit->pop_scope();
1222+ // pop continue stack
1223+ emit->code->stack_cont.pop_back();
1224+ // pop break stack
1225+ emit->code->stack_break.pop_back();
1226+
1227+ return ret;
1228+}
1229+
1230+
1231+
1232+
1233+//-----------------------------------------------------------------------------
1234+// name: emit_engine_emit_break()
1235+// desc: ...
1236+//-----------------------------------------------------------------------------
1237+t_CKBOOL emit_engine_emit_break( Chuck_Emitter * emit, a_Stmt_Break br )
1238+{
1239+ // append
1240+ Chuck_Instr_Goto * op = new Chuck_Instr_Goto( 0 );
1241+ emit->append( op );
1242+ // remember
1243+ emit->code->stack_break.push_back( op );
1244+
1245+ return TRUE;
1246+}
1247+
1248+
1249+
1250+
1251+//-----------------------------------------------------------------------------
1252+// name: emit_engine_emit_continue()
1253+// desc: ...
1254+//-----------------------------------------------------------------------------
1255+t_CKBOOL emit_engine_emit_continue( Chuck_Emitter * emit, a_Stmt_Continue cont )
1256+{
1257+ // append
1258+ Chuck_Instr_Goto * op = new Chuck_Instr_Goto( 0 );
1259+ emit->append( op );
1260+ // remember
1261+ emit->code->stack_cont.push_back( op );
1262+
1263+ return TRUE;
1264+}
1265+
1266+
1267+
1268+
1269+//-----------------------------------------------------------------------------
1270+// name: emit_engine_emit_return()
1271+// desc: ...
1272+//-----------------------------------------------------------------------------
1273+t_CKBOOL emit_engine_emit_return( Chuck_Emitter * emit, a_Stmt_Return stmt )
1274+{
1275+ if( !emit_engine_emit_exp( emit, stmt->val ) )
1276+ return FALSE;
1277+
1278+ // emit return
1279+ // emit->append( new Chuck_Instr_Func_Return );
1280+
1281+ // determine where later
1282+ Chuck_Instr_Goto * instr = new Chuck_Instr_Goto( 0 );
1283+ emit->append( instr );
1284+ emit->code->stack_return.push_back( instr );
1285+
1286+ return TRUE;
1287+}
1288+
1289+
1290+
1291+
1292+//-----------------------------------------------------------------------------
1293+// name:
1294+// desc: ...
1295+//-----------------------------------------------------------------------------
1296+t_CKBOOL emit_engine_emit_switch( Chuck_Emitter * emit, a_Stmt_Switch stmt );
1297+
1298+
1299+
1300+
1301+//-----------------------------------------------------------------------------
1302+// name: emit_engine_emit_exp()
1303+// desc: (doAddRef added 1.3.0.0 -- typically this is set to TRUE for function
1304+// calls so that pointers on the reg is accounted for; this is important
1305+// in case the object is released/reclaimed before the value is used;
1306+// on particular case is when sporking with a local object as argument)
1307+//-----------------------------------------------------------------------------
1308+t_CKBOOL emit_engine_emit_exp( Chuck_Emitter * emit, a_Exp exp, t_CKBOOL doAddRef )
1309+{
1310+ // for now...
1311+ // assert( exp->next == NULL );
1312+
1313+ // loop over
1314+ while( exp )
1315+ {
1316+ switch( exp->s_type )
1317+ {
1318+ case ae_exp_binary:
1319+ if( !emit_engine_emit_exp_binary( emit, &exp->binary ) )
1320+ return FALSE;
1321+ break;
1322+
1323+ case ae_exp_unary:
1324+ if( !emit_engine_emit_exp_unary( emit, &exp->unary ) )
1325+ return FALSE;
1326+ break;
1327+
1328+ case ae_exp_cast:
1329+ if( !emit_engine_emit_exp_cast( emit, &exp->cast ) )
1330+ return FALSE;
1331+ break;
1332+
1333+ case ae_exp_postfix:
1334+ if( !emit_engine_emit_exp_postfix( emit, &exp->postfix ) )
1335+ return FALSE;
1336+ break;
1337+
1338+ case ae_exp_dur:
1339+ if( !emit_engine_emit_exp_dur( emit, &exp->dur ) )
1340+ return FALSE;
1341+ break;
1342+
1343+ case ae_exp_primary:
1344+ if( !emit_engine_emit_exp_primary( emit, &exp->primary ) )
1345+ return FALSE;
1346+ break;
1347+
1348+ case ae_exp_array:
1349+ if( !emit_engine_emit_exp_array( emit, &exp->array ) )
1350+ return FALSE;
1351+ break;
1352+
1353+ case ae_exp_func_call:
1354+ if( !emit_engine_emit_exp_func_call( emit, &exp->func_call ) )
1355+ return FALSE;
1356+ break;
1357+
1358+ case ae_exp_dot_member:
1359+ if( !emit_engine_emit_exp_dot_member( emit, &exp->dot_member ) )
1360+ return FALSE;
1361+ break;
1362+
1363+ case ae_exp_if:
1364+ if( !emit_engine_emit_exp_if( emit, &exp->exp_if ) )
1365+ return FALSE;
1366+ break;
1367+
1368+ case ae_exp_decl:
1369+ if( !emit_engine_emit_exp_decl( emit, &exp->decl, FALSE ) )
1370+ return FALSE;
1371+ break;
1372+
1373+ //case ae_exp_namespace:
1374+ // if( !emit_engine_emit_exp_namespace( emit, &exp->name_space ) )
1375+ // return FALSE;
1376+ // break;
1377+
1378+ default:
1379+ EM_error2( exp->linepos,
1380+ "(emit): internal error: unhandled expression type '%i'...",
1381+ exp->s_type );
1382+ return FALSE;
1383+ }
1384+
1385+ // implicit cast
1386+ if( exp->cast_to != NULL )
1387+ if( !emit_engine_emit_cast( emit, exp->cast_to, exp->type ) )
1388+ return FALSE;
1389+
1390+ // check if we need to handle ref (added 1.3.0.0)
1391+ // (NOTE: cast shouldn't matter since pointer width should remain constant)
1392+ if( doAddRef && isobj( emit->env, exp->type ) )
1393+ {
1394+ // add ref in place on the stack
1395+ emit->append( new Chuck_Instr_Reg_AddRef_Object3() );
1396+ }
1397+
1398+ exp = exp->next;
1399+ }
1400+
1401+ return TRUE;
1402+}
1403+
1404+
1405+
1406+
1407+//-----------------------------------------------------------------------------
1408+// name: emit_engine_emit_exp_binary()
1409+// desc: ...
1410+//-----------------------------------------------------------------------------
1411+t_CKBOOL emit_engine_emit_exp_binary( Chuck_Emitter * emit, a_Exp_Binary binary )
1412+{
1413+ // sanity
1414+ assert( binary->self->emit_var == FALSE );
1415+
1416+ t_CKBOOL left = FALSE;
1417+ t_CKBOOL right = FALSE;
1418+
1419+ // hack to allow && to terminate as soon as possible - spencer
1420+ // i.e. in ( 0 && f() ) the function f() will not be called
1421+ // (obviates need for boolean AND instruction)
1422+ if( binary->op == ae_op_and )
1423+ {
1424+ Chuck_Instr_Branch_Op * op;
1425+
1426+ // push default result
1427+ emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
1428+
1429+ left = emit_engine_emit_exp( emit, binary->lhs );
1430+ if( !left )
1431+ return FALSE;
1432+
1433+ // compare to 0; use default result if zero
1434+ emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
1435+ emit->append( op = new Chuck_Instr_Branch_Eq_int( 0 ) );
1436+
1437+ // pop default result
1438+ emit->append( new Chuck_Instr_Reg_Pop_Word );
1439+
1440+ // result of whole expression is now result of rhs
1441+ right = emit_engine_emit_exp( emit, binary->rhs );
1442+ if( !right )
1443+ return FALSE;
1444+
1445+ // set branch location
1446+ op->set( emit->next_index() );
1447+
1448+ return TRUE;
1449+ }
1450+
1451+ // hack to allow || to terminate as soon as possible - spencer
1452+ // i.e. in ( 1 || f() ) the function f() will not be called
1453+ // (obviates need for boolean OR instruction)
1454+ else if( binary->op == ae_op_or )
1455+ {
1456+ Chuck_Instr_Branch_Op * op;
1457+
1458+ // push default result
1459+ emit->append( new Chuck_Instr_Reg_Push_Imm( 1 ) );
1460+
1461+ left = emit_engine_emit_exp( emit, binary->lhs );
1462+ if( !left )
1463+ return FALSE;
1464+
1465+ // compare to 0; use default result if non-zero
1466+ emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
1467+ emit->append( op = new Chuck_Instr_Branch_Neq_int( 0 ) );
1468+
1469+ // pop default result
1470+ emit->append( new Chuck_Instr_Reg_Pop_Word );
1471+
1472+ // result of whole expression is now result of rhs
1473+ right = emit_engine_emit_exp( emit, binary->rhs );
1474+ if( !right )
1475+ return FALSE;
1476+
1477+ // set branch location
1478+ op->set( emit->next_index() );
1479+
1480+ return TRUE;
1481+ }
1482+
1483+ // whether to track object references on stack (added 1.3.0.2)
1484+ t_CKBOOL doRef = FALSE;
1485+ // check to see if this is a function call (added 1.3.0.2)
1486+ if( isa( binary->rhs->type, emit->env->t_function ) )
1487+ {
1488+ // take care of objects in terms of reference counting
1489+ doRef = TRUE;
1490+ }
1491+
1492+ // emit (doRef added 1.3.0.2)
1493+ left = emit_engine_emit_exp( emit, binary->lhs, doRef );
1494+ right = emit_engine_emit_exp( emit, binary->rhs );
1495+
1496+ // check
1497+ if( !left || !right )
1498+ return FALSE;
1499+
1500+ // emit the op
1501+ if( !emit_engine_emit_op( emit, binary->op, binary->lhs, binary->rhs, binary ) )
1502+ return FALSE;
1503+
1504+ return TRUE;
1505+}
1506+
1507+
1508+
1509+
1510+//-----------------------------------------------------------------------------
1511+// name: emit_engine_emit_op()
1512+// desc: emit binary operator
1513+//-----------------------------------------------------------------------------
1514+t_CKBOOL emit_engine_emit_op( Chuck_Emitter * emit, ae_Operator op, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary )
1515+{
1516+ // any implicit cast happens before this
1517+ Chuck_Type * t_left = lhs->cast_to ? lhs->cast_to : lhs->type;
1518+ Chuck_Type * t_right = rhs->cast_to ? rhs->cast_to : rhs->type;
1519+ // get the types of the left and right
1520+ te_Type left = t_left->xid;
1521+ te_Type right = t_right->xid;
1522+ // op
1523+ Chuck_Instr * instr = NULL;
1524+
1525+ // emit op
1526+ switch( op )
1527+ {
1528+ // ----------------------------- num --------------------------------------
1529+ case ae_op_plus:
1530+ // time + dur
1531+ if( ( left == te_dur && right == te_time ) ||
1532+ ( left == te_time && right == te_dur ) )
1533+ {
1534+ emit->append( instr = new Chuck_Instr_Add_double );
1535+ }
1536+ // string + string
1537+ else if( isa( t_left, emit->env->t_string ) && isa( t_right, emit->env->t_string ) )
1538+ {
1539+ // concatenate
1540+ emit->append( instr = new Chuck_Instr_Add_string );
1541+ instr->set_linepos( lhs->linepos );
1542+ }
1543+ // left: string
1544+ else if( isa( t_left, emit->env->t_string ) )
1545+ {
1546+ // + int
1547+ if( isa( t_right, emit->env->t_int ) )
1548+ {
1549+ emit->append( instr = new Chuck_Instr_Add_string_int );
1550+ instr->set_linepos( lhs->linepos );
1551+ }
1552+ else if( isa( t_right, emit->env->t_float ) )
1553+ {
1554+ emit->append( instr = new Chuck_Instr_Add_string_float );
1555+ instr->set_linepos( lhs->linepos );
1556+ }
1557+ else
1558+ {
1559+ EM_error2( lhs->linepos,
1560+ "(emit): internal error: unhandled op '%s' %s '%s'",
1561+ t_left->c_name(), op2str( op ), t_right->c_name() );
1562+ return FALSE;
1563+ }
1564+ }
1565+ // right: string
1566+ else if( isa( t_right, emit->env->t_string ) )
1567+ {
1568+ // + int
1569+ if( isa( t_left, emit->env->t_int ) )
1570+ {
1571+ emit->append( instr = new Chuck_Instr_Add_int_string );
1572+ instr->set_linepos( rhs->linepos );
1573+ }
1574+ else if( isa( t_left, emit->env->t_float ) )
1575+ {
1576+ emit->append( instr = new Chuck_Instr_Add_float_string );
1577+ instr->set_linepos( rhs->linepos );
1578+ }
1579+ else
1580+ {
1581+ EM_error2( lhs->linepos,
1582+ "(emit): internal error: unhandled op '%s' %s '%s'",
1583+ t_left->c_name(), op2str( op ), t_right->c_name() );
1584+ return FALSE;
1585+ }
1586+ }
1587+ else // other types
1588+ {
1589+ switch( left )
1590+ {
1591+ case te_int:
1592+ emit->append( instr = new Chuck_Instr_Add_int );
1593+ break;
1594+ case te_float:
1595+ case te_dur:
1596+ emit->append( instr = new Chuck_Instr_Add_double );
1597+ break;
1598+ case te_complex:
1599+ emit->append( instr = new Chuck_Instr_Add_complex );
1600+ break;
1601+ case te_polar:
1602+ emit->append( instr = new Chuck_Instr_Add_polar );
1603+ break;
1604+ case te_vec3:
1605+ emit->append( instr = new Chuck_Instr_Add_vec3 );
1606+ break;
1607+ case te_vec4:
1608+ emit->append( instr = new Chuck_Instr_Add_vec4 );
1609+ break;
1610+
1611+ default: break;
1612+ }
1613+ }
1614+ break;
1615+
1616+ case ae_op_plus_chuck:
1617+ // time advance
1618+ if( left == te_dur && right == te_time && rhs->s_meta == ae_meta_var &&
1619+ rhs->s_type == ae_exp_primary && !strcmp( "now", S_name(rhs->primary.var) ) )
1620+ {
1621+ // add the two
1622+ emit->append( new Chuck_Instr_Add_double );
1623+ // advance time (TODO: verify having two instr is OK)
1624+ emit->append( instr = new Chuck_Instr_Time_Advance );
1625+ instr->set_linepos( lhs->linepos );
1626+ }
1627+ // time + dur
1628+ else if( ( left == te_dur && right == te_time ) ||
1629+ ( left == te_time && right == te_dur ) )
1630+ {
1631+ emit->append( instr = new Chuck_Instr_Add_double_Assign );
1632+ }
1633+ // string + string
1634+ else if( isa( t_left, emit->env->t_string ) && isa( t_right, emit->env->t_string ) )
1635+ {
1636+ // concatenate
1637+ emit->append( instr = new Chuck_Instr_Add_string_Assign );
1638+ instr->set_linepos( lhs->linepos );
1639+ }
1640+ // right: string
1641+ else if( isa( t_right, emit->env->t_string ) )
1642+ {
1643+ // + int
1644+ if( isa( t_left, emit->env->t_int ) )
1645+ {
1646+ emit->append( instr = new Chuck_Instr_Add_int_string_Assign );
1647+ // null exceptions will occur from string: use rhs, not lhs
1648+ instr->set_linepos( rhs->linepos );
1649+ }
1650+ else if( isa( t_left, emit->env->t_float ) )
1651+ {
1652+ emit->append( instr = new Chuck_Instr_Add_float_string_Assign );
1653+ instr->set_linepos( rhs->linepos );
1654+ }
1655+ else
1656+ {
1657+ EM_error2( lhs->linepos,
1658+ "(emit): internal error: unhandled op '%s' %s '%s'",
1659+ t_left->c_name(), op2str( op ), t_right->c_name() );
1660+ return FALSE;
1661+ }
1662+ }
1663+ else // other types
1664+ {
1665+ switch( left )
1666+ {
1667+ case te_int:
1668+ emit->append( instr = new Chuck_Instr_Add_int_Assign );
1669+ break;
1670+ case te_float:
1671+ case te_dur:
1672+ emit->append( instr = new Chuck_Instr_Add_double_Assign );
1673+ break;
1674+ case te_complex:
1675+ emit->append( instr = new Chuck_Instr_Add_complex_Assign );
1676+ break;
1677+ case te_polar:
1678+ emit->append( instr = new Chuck_Instr_Add_polar_Assign );
1679+ break;
1680+ case te_vec3:
1681+ emit->append( instr = new Chuck_Instr_Add_vec3_Assign );
1682+ break;
1683+ case te_vec4:
1684+ emit->append( instr = new Chuck_Instr_Add_vec4_Assign );
1685+ break;
1686+
1687+ default: break;
1688+ }
1689+ }
1690+ break;
1691+
1692+ case ae_op_minus:
1693+ if( ( left == te_time && right == te_dur ) ) // time - dur = time
1694+ emit->append( instr = new Chuck_Instr_Minus_double );
1695+ else if( ( left == te_time && right == te_time ) ) // time - time = dur
1696+ emit->append( instr = new Chuck_Instr_Minus_double );
1697+ else // other types
1698+ {
1699+ switch( left )
1700+ {
1701+ case te_int:
1702+ emit->append( instr = new Chuck_Instr_Minus_int );
1703+ break;
1704+ case te_float:
1705+ case te_dur:
1706+ emit->append( instr = new Chuck_Instr_Minus_double );
1707+ break;
1708+ case te_complex:
1709+ emit->append( instr = new Chuck_Instr_Minus_complex );
1710+ break;
1711+ case te_polar:
1712+ emit->append( instr = new Chuck_Instr_Minus_polar );
1713+ break;
1714+ case te_vec3:
1715+ emit->append( instr = new Chuck_Instr_Minus_vec3 );
1716+ break;
1717+ case te_vec4:
1718+ emit->append( instr = new Chuck_Instr_Minus_vec4 );
1719+ break;
1720+
1721+ default: break;
1722+ }
1723+ }
1724+ break;
1725+
1726+ case ae_op_minus_chuck:
1727+ if( ( left == te_dur && right == te_time ) ) // time - dur = time
1728+ emit->append( instr = new Chuck_Instr_Minus_double_Assign );
1729+ else if( ( left == te_time && right == te_time ) ) // time - time = dur
1730+ emit->append( instr = new Chuck_Instr_Minus_double_Assign );
1731+ else // other types
1732+ {
1733+ switch( left )
1734+ {
1735+ case te_int:
1736+ emit->append( instr = new Chuck_Instr_Minus_int_Assign );
1737+ break;
1738+ case te_float:
1739+ case te_dur:
1740+ emit->append( instr = new Chuck_Instr_Minus_double_Assign );
1741+ break;
1742+ case te_complex:
1743+ emit->append( instr = new Chuck_Instr_Minus_complex_Assign );
1744+ break;
1745+ case te_polar:
1746+ emit->append( instr = new Chuck_Instr_Minus_polar_Assign );
1747+ break;
1748+ case te_vec3:
1749+ emit->append( instr = new Chuck_Instr_Minus_vec3_Assign );
1750+ break;
1751+ case te_vec4:
1752+ emit->append( instr = new Chuck_Instr_Minus_vec4_Assign );
1753+ break;
1754+
1755+ default: break;
1756+ }
1757+ }
1758+ break;
1759+
1760+ case ae_op_times:
1761+ // check
1762+ if( left == te_float && right == te_vec3 )
1763+ {
1764+ emit->append( instr = new Chuck_Instr_float_Times_vec3 );
1765+ }
1766+ else if( left == te_vec3 && right == te_float )
1767+ {
1768+ emit->append( instr = new Chuck_Instr_vec3_Times_float );
1769+ }
1770+ else if( left == te_float && right == te_vec4 )
1771+ {
1772+ emit->append( instr = new Chuck_Instr_float_Times_vec4 );
1773+ }
1774+ else if( left == te_vec4 && right == te_float )
1775+ {
1776+ emit->append( instr = new Chuck_Instr_vec4_Times_float );
1777+ }
1778+ else // other cases
1779+ {
1780+ switch( left )
1781+ {
1782+ case te_int:
1783+ emit->append( instr = new Chuck_Instr_Times_int );
1784+ break;
1785+ case te_float:
1786+ case te_dur:
1787+ emit->append( instr = new Chuck_Instr_Times_double );
1788+ break;
1789+ case te_complex:
1790+ emit->append( instr = new Chuck_Instr_Times_complex );
1791+ break;
1792+ case te_polar:
1793+ emit->append( instr = new Chuck_Instr_Times_polar );
1794+ break;
1795+ case te_vec3:
1796+ emit->append( instr = new Chuck_Instr_XProduct_vec3 );
1797+ break;
1798+ case te_vec4:
1799+ emit->append( instr = new Chuck_Instr_XProduct_vec4 );
1800+ break;
1801+
1802+ default: break;
1803+ }
1804+ }
1805+ break;
1806+
1807+ case ae_op_times_chuck:
1808+ // check
1809+ if( left == te_float && right == te_vec3 )
1810+ {
1811+ emit->append( instr = new Chuck_Instr_float_Times_vec3_Assign );
1812+ }
1813+ else if( left == te_float && right == te_vec4 )
1814+ {
1815+ emit->append( instr = new Chuck_Instr_float_Times_vec4_Assign );
1816+ }
1817+ else
1818+ {
1819+ switch( left )
1820+ {
1821+ case te_int:
1822+ emit->append( instr = new Chuck_Instr_Times_int_Assign );
1823+ break;
1824+ case te_float:
1825+ emit->append( instr = new Chuck_Instr_Times_double_Assign );
1826+ break;
1827+ case te_complex:
1828+ emit->append( instr = new Chuck_Instr_Times_complex_Assign );
1829+ break;
1830+ case te_polar:
1831+ emit->append( instr = new Chuck_Instr_Times_polar_Assign );
1832+ break;
1833+
1834+ default: break;
1835+ }
1836+ }
1837+ break;
1838+
1839+ case ae_op_divide:
1840+ if( ( left == te_time && right == te_dur ) ) // time / dur = float
1841+ emit->append( instr = new Chuck_Instr_Divide_double );
1842+ else if( left == te_vec3 && right == te_float )
1843+ {
1844+ emit->append( instr = new Chuck_Instr_vec3_Divide_float );
1845+ }
1846+ else if( left == te_vec4 && right == te_float )
1847+ {
1848+ emit->append( instr = new Chuck_Instr_vec4_Divide_float );
1849+ }
1850+ else // other types
1851+ {
1852+ switch( left )
1853+ {
1854+ case te_int:
1855+ emit->append( instr = new Chuck_Instr_Divide_int );
1856+ instr->set_linepos( rhs->linepos );
1857+ break;
1858+ case te_float:
1859+ case te_dur:
1860+ emit->append( instr = new Chuck_Instr_Divide_double );
1861+ break;
1862+ case te_complex:
1863+ emit->append( instr = new Chuck_Instr_Divide_complex );
1864+ break;
1865+ case te_polar:
1866+ emit->append( instr = new Chuck_Instr_Divide_polar );
1867+ break;
1868+
1869+ default: break;
1870+ }
1871+ }
1872+ break;
1873+
1874+ case ae_op_divide_chuck:
1875+ // reverse
1876+ if( ( left == te_dur && right == te_time ) ) // time / dur = float
1877+ emit->append( instr = new Chuck_Instr_Divide_double_Assign );
1878+ else
1879+ if( left == te_float && right == te_vec3 )
1880+ {
1881+ emit->append( instr = new Chuck_Instr_vec3_Divide_float_Assign );
1882+ }
1883+ else if( left == te_float && right == te_vec4 )
1884+ {
1885+ emit->append( instr = new Chuck_Instr_vec4_Divide_float_Assign );
1886+ }
1887+ else // other types
1888+ {
1889+ switch( left )
1890+ {
1891+ case te_int:
1892+ emit->append( instr = new Chuck_Instr_Divide_int_Assign );
1893+ instr->set_linepos( lhs->linepos );
1894+ break;
1895+ case te_float:
1896+ emit->append( instr = new Chuck_Instr_Divide_double_Assign );
1897+ break;
1898+ case te_complex:
1899+ emit->append( instr = new Chuck_Instr_Divide_complex_Assign );
1900+ break;
1901+ case te_polar:
1902+ emit->append( instr = new Chuck_Instr_Divide_polar_Assign );
1903+ break;
1904+
1905+ default: break;
1906+ }
1907+ }
1908+ break;
1909+
1910+ case ae_op_s_or:
1911+ switch( left )
1912+ {
1913+ case te_int:
1914+ emit->append( instr = new Chuck_Instr_Binary_Or );
1915+ break;
1916+
1917+ default: break;
1918+ }
1919+ break;
1920+
1921+ case ae_op_s_or_chuck:
1922+ switch( left )
1923+ {
1924+ case te_int:
1925+ emit->append( instr = new Chuck_Instr_Binary_Or_Assign );
1926+ break;
1927+
1928+ default: break;
1929+ }
1930+ break;
1931+
1932+ case ae_op_s_and:
1933+ switch( left )
1934+ {
1935+ case te_int:
1936+ emit->append( instr = new Chuck_Instr_Binary_And );
1937+ break;
1938+
1939+ default: break;
1940+ }
1941+ break;
1942+
1943+ case ae_op_s_and_chuck:
1944+ switch( left )
1945+ {
1946+ case te_int:
1947+ emit->append( instr = new Chuck_Instr_Binary_And_Assign );
1948+ break;
1949+
1950+ default: break;
1951+ }
1952+ break;
1953+
1954+ case ae_op_shift_left:
1955+ switch( left )
1956+ {
1957+ case te_int:
1958+ emit->append( instr = new Chuck_Instr_Binary_Shift_Left );
1959+ break;
1960+
1961+ case te_array:
1962+ // check size (1.3.1.0: changed to getkindof)
1963+ emit->append( instr = new Chuck_Instr_Array_Append( getkindof( emit->env, t_left->array_type ) ) );
1964+ instr->set_linepos( lhs->linepos );
1965+ break;
1966+
1967+ default: break;
1968+ }
1969+ break;
1970+
1971+ case ae_op_shift_left_chuck:
1972+ // reverse
1973+ switch( left )
1974+ {
1975+ case te_int:
1976+ emit->append( instr = new Chuck_Instr_Binary_Shift_Left_Assign );
1977+ break;
1978+
1979+ default: break;
1980+ }
1981+ break;
1982+
1983+ case ae_op_shift_right:
1984+ switch( left )
1985+ {
1986+ case te_int:
1987+ emit->append( instr = new Chuck_Instr_Binary_Shift_Right );
1988+ break;
1989+
1990+ // case te_array:
1991+ // emit->append( instr = new Chuck_Instr_Array_Prepend( t_left->array_type->size ) );
1992+ // break;
1993+
1994+ default: break;
1995+ }
1996+ break;
1997+
1998+ case ae_op_shift_right_chuck:
1999+ // reverse
2000+ switch( left )
2001+ {
2002+ case te_int:
2003+ emit->append( instr = new Chuck_Instr_Binary_Shift_Right_Assign );
2004+ break;
2005+
2006+ default: break;
2007+ }
2008+ break;
2009+
2010+ case ae_op_percent:
2011+ if( ( left == te_time && right == te_dur ) ) // time % dur = dur
2012+ {
2013+ emit->append( instr = new Chuck_Instr_Mod_double );
2014+ }
2015+ else // other types
2016+ {
2017+ switch( left )
2018+ {
2019+ case te_int:
2020+ emit->append( instr = new Chuck_Instr_Mod_int );
2021+ break;
2022+ case te_float:
2023+ case te_dur:
2024+ emit->append( instr = new Chuck_Instr_Mod_double );
2025+ break;
2026+
2027+ default: break;
2028+ }
2029+ }
2030+ break;
2031+
2032+ case ae_op_percent_chuck:
2033+ // reverse
2034+ if( ( left == te_dur && right == te_time ) ) // time % dur = dur
2035+ {
2036+ emit->append( instr = new Chuck_Instr_Mod_double_Assign );
2037+ }
2038+ else // other types
2039+ {
2040+ switch( left )
2041+ {
2042+ case te_int:
2043+ emit->append( instr = new Chuck_Instr_Mod_int_Assign );
2044+ break;
2045+ case te_float:
2046+ case te_dur:
2047+ emit->append( instr = new Chuck_Instr_Mod_double_Assign );
2048+ break;
2049+
2050+ default: break;
2051+ }
2052+ }
2053+ break;
2054+
2055+ case ae_op_s_xor:
2056+ switch( left )
2057+ {
2058+ case te_int:
2059+ emit->append( instr = new Chuck_Instr_Binary_Xor );
2060+ break;
2061+ default: break;
2062+ }
2063+ break;
2064+
2065+ case ae_op_s_xor_chuck:
2066+ switch( left )
2067+ {
2068+ case te_int:
2069+ emit->append( instr = new Chuck_Instr_Binary_Xor_Assign );
2070+ break;
2071+ default: break;
2072+ }
2073+ break;
2074+
2075+ // ----------------------------- chuck -------------------------------------
2076+ case ae_op_chuck:
2077+ {
2078+ a_Exp cl = lhs, cr = rhs;
2079+
2080+ if( !emit_engine_emit_op_chuck( emit, cl, cr, binary ) )
2081+ return FALSE;
2082+
2083+ return TRUE;
2084+ }
2085+
2086+ case ae_op_unchuck:
2087+ {
2088+ a_Exp cl = lhs, cr = rhs;
2089+
2090+ // TODO: cross chuck
2091+ assert( cl->next == NULL && cr->next == NULL );
2092+ while( cr )
2093+ {
2094+ cl = lhs;
2095+ while( cl )
2096+ {
2097+ if( !emit_engine_emit_op_unchuck( emit, cl, cr ) )
2098+ return FALSE;
2099+ cl = cl->next;
2100+ }
2101+
2102+ cr = cr->next;
2103+ }
2104+
2105+ return TRUE;
2106+ }
2107+
2108+ case ae_op_upchuck:
2109+ {
2110+ a_Exp cl = lhs, cr = rhs;
2111+
2112+ // TODO: cross chuck
2113+ assert( cl->next == NULL && cr->next == NULL );
2114+ while( cr )
2115+ {
2116+ cl = lhs;
2117+ while( cl )
2118+ {
2119+ if( !emit_engine_emit_op_upchuck( emit, cl, cr ) )
2120+ return FALSE;
2121+ cl = cl->next;
2122+ }
2123+
2124+ cr = cr->next;
2125+ }
2126+
2127+ return TRUE;
2128+ }
2129+
2130+ case ae_op_at_chuck:
2131+ {
2132+ a_Exp cl = lhs, cr = rhs;
2133+
2134+ // TODO: cross chuck
2135+ assert( cl->next == NULL && cr->next == NULL );
2136+ while( cr )
2137+ {
2138+ cl = lhs;
2139+ while( cl )
2140+ {
2141+ if( !emit_engine_emit_op_at_chuck( emit, cl, cr ) )
2142+ return FALSE;
2143+ cl = cl->next;
2144+ }
2145+
2146+ cr = cr->next;
2147+ }
2148+
2149+ return TRUE;
2150+ }
2151+
2152+ case ae_op_s_chuck:
2153+ break;
2154+
2155+ // -------------------------------- bool -----------------------------------
2156+ case ae_op_eq:
2157+ if( isa( t_left, emit->env->t_string ) && isa( t_right, emit->env->t_string )
2158+ && !isa( t_left, emit->env->t_null ) && !isa( t_right, emit->env->t_null ) ) // !null
2159+ {
2160+ emit->append( instr = new Chuck_Instr_Op_string( op ) );
2161+ instr->set_linepos( lhs->linepos );
2162+ }
2163+ else if( isa( t_left, emit->env->t_object ) && isa( t_right, emit->env->t_object ) )
2164+ emit->append( instr = new Chuck_Instr_Eq_int );
2165+ else
2166+ {
2167+ switch( left )
2168+ {
2169+ case te_int:
2170+ emit->append( instr = new Chuck_Instr_Eq_int );
2171+ break;
2172+ case te_float:
2173+ case te_dur:
2174+ case te_time:
2175+ emit->append( instr = new Chuck_Instr_Eq_double );
2176+ break;
2177+ case te_complex:
2178+ case te_polar:
2179+ emit->append( instr = new Chuck_Instr_Eq_complex );
2180+ break;
2181+ case te_vec3:
2182+ emit->append( instr = new Chuck_Instr_Eq_vec3 );
2183+ break;
2184+ case te_vec4:
2185+ emit->append( instr = new Chuck_Instr_Eq_vec4 );
2186+ break;
2187+
2188+ default: break;
2189+ }
2190+ }
2191+ break;
2192+
2193+ case ae_op_neq:
2194+ if( isa( t_left, emit->env->t_string ) && isa( t_right, emit->env->t_string )
2195+ && !isa( t_left, emit->env->t_null ) && !isa( t_right, emit->env->t_null ) ) // !null
2196+ // added 1.3.2.0 (spencer)
2197+ {
2198+ emit->append( instr = new Chuck_Instr_Op_string( op ) );
2199+ instr->set_linepos( lhs->linepos );
2200+ }
2201+ else if( isa( t_left, emit->env->t_object ) && isa( t_right, emit->env->t_object ) )
2202+ emit->append( instr = new Chuck_Instr_Neq_int );
2203+ else
2204+ {
2205+ switch( left )
2206+ {
2207+ case te_int:
2208+ emit->append( instr = new Chuck_Instr_Neq_int );
2209+ break;
2210+ case te_float:
2211+ case te_dur:
2212+ case te_time:
2213+ emit->append( instr = new Chuck_Instr_Neq_double );
2214+ break;
2215+ case te_complex:
2216+ case te_polar:
2217+ emit->append( instr = new Chuck_Instr_Neq_complex );
2218+ break;
2219+ case te_vec3:
2220+ emit->append( instr = new Chuck_Instr_Neq_vec3 );
2221+ break;
2222+ case te_vec4:
2223+ emit->append( instr = new Chuck_Instr_Neq_vec4 );
2224+ break;
2225+
2226+ default: break;
2227+ }
2228+ }
2229+ break;
2230+
2231+ case ae_op_lt:
2232+ switch( left )
2233+ {
2234+ case te_int:
2235+ emit->append( instr = new Chuck_Instr_Lt_int );
2236+ break;
2237+ case te_float:
2238+ case te_dur:
2239+ case te_time:
2240+ emit->append( instr = new Chuck_Instr_Lt_double );
2241+ break;
2242+
2243+ default:
2244+ if( isa( t_left, emit->env->t_string ) && isa( t_right, emit->env->t_string ) )
2245+ {
2246+ emit->append( instr = new Chuck_Instr_Op_string( op ) );
2247+ instr->set_linepos( lhs->linepos );
2248+ }
2249+ break;
2250+ }
2251+ break;
2252+
2253+ case ae_op_le:
2254+ switch( left )
2255+ {
2256+ case te_int:
2257+ emit->append( instr = new Chuck_Instr_Le_int );
2258+ break;
2259+ case te_float:
2260+ case te_dur:
2261+ case te_time:
2262+ emit->append( instr = new Chuck_Instr_Le_double );
2263+ break;
2264+
2265+ default:
2266+ if( isa( t_left, emit->env->t_string ) && isa( t_right, emit->env->t_string ) )
2267+ {
2268+ emit->append( instr = new Chuck_Instr_Op_string( op ) );
2269+ instr->set_linepos( lhs->linepos );
2270+ }
2271+ else if( isa( t_left, emit->env->t_io ) )
2272+ {
2273+ // output
2274+ if( isa( t_right, emit->env->t_int ) )
2275+ {
2276+ emit->append( instr = new Chuck_Instr_IO_out_int );
2277+ instr->set_linepos( rhs->linepos );
2278+ }
2279+ else if( isa( t_right, emit->env->t_float ) )
2280+ {
2281+ emit->append( instr = new Chuck_Instr_IO_out_float );
2282+ instr->set_linepos( rhs->linepos );
2283+ }
2284+ else if( isa( t_right, emit->env->t_string ) )
2285+ {
2286+ emit->append( instr = new Chuck_Instr_IO_out_string );
2287+ instr->set_linepos( rhs->linepos );
2288+ }
2289+ }
2290+ break;
2291+ }
2292+ break;
2293+
2294+ case ae_op_gt:
2295+ switch( left )
2296+ {
2297+ case te_int:
2298+ emit->append( instr = new Chuck_Instr_Gt_int );
2299+ break;
2300+ case te_float:
2301+ case te_dur:
2302+ case te_time:
2303+ emit->append( instr = new Chuck_Instr_Gt_double );
2304+ break;
2305+
2306+ default:
2307+ if( isa( t_left, emit->env->t_string ) && isa( t_right, emit->env->t_string ) )
2308+ {
2309+ emit->append( instr = new Chuck_Instr_Op_string( op ) );
2310+ instr->set_linepos( lhs->linepos );
2311+ }
2312+ break;
2313+ }
2314+ break;
2315+
2316+ case ae_op_ge:
2317+ switch( left )
2318+ {
2319+ case te_int:
2320+ emit->append( instr = new Chuck_Instr_Ge_int );
2321+ break;
2322+ case te_float:
2323+ case te_dur:
2324+ case te_time:
2325+ emit->append( instr = new Chuck_Instr_Ge_double );
2326+ break;
2327+
2328+ default:
2329+ if( isa( t_left, emit->env->t_string ) && isa( t_right, emit->env->t_string ) )
2330+ {
2331+ emit->append( instr = new Chuck_Instr_Op_string( op ) );
2332+ instr->set_linepos( lhs->linepos );
2333+ }
2334+ break;
2335+ }
2336+ break;
2337+
2338+ case ae_op_and:
2339+ switch( left )
2340+ {
2341+ case te_int:
2342+ emit->append( instr = new Chuck_Instr_And );
2343+ break;
2344+
2345+ default: break;
2346+ }
2347+ break;
2348+
2349+ case ae_op_or:
2350+ switch( left )
2351+ {
2352+ case te_int:
2353+ emit->append( instr = new Chuck_Instr_Or );
2354+ break;
2355+
2356+ default: break;
2357+ }
2358+ break;
2359+
2360+ //------------------------------- IO ----------------------------------
2361+ case ae_op_arrow_left:
2362+ switch( right )
2363+ {
2364+ case te_int:
2365+ emit->append( instr = new Chuck_Instr_IO_out_int );
2366+ instr->set_linepos( rhs->linepos );
2367+ break;
2368+ case te_float:
2369+ emit->append( instr = new Chuck_Instr_IO_out_float );
2370+ instr->set_linepos( rhs->linepos );
2371+ break;
2372+ default:
2373+ if( isa( t_right, emit->env->t_string ) )
2374+ {
2375+ emit->append( instr = new Chuck_Instr_IO_out_string );
2376+ instr->set_linepos( rhs->linepos );
2377+ }
2378+ break;
2379+ }
2380+ break;
2381+
2382+ case ae_op_arrow_right:
2383+ switch( right )
2384+ {
2385+ case te_int:
2386+ emit->append( instr = new Chuck_Instr_IO_in_int );
2387+ instr->set_linepos( rhs->linepos );
2388+ break;
2389+ case te_float:
2390+ emit->append( instr = new Chuck_Instr_IO_in_float );
2391+ instr->set_linepos( rhs->linepos );
2392+ break;
2393+ default:
2394+ if( isa( t_right, emit->env->t_string ) )
2395+ {
2396+ emit->append( instr = new Chuck_Instr_IO_in_string );
2397+ instr->set_linepos( rhs->linepos );
2398+ }
2399+ break;
2400+ }
2401+ break;
2402+
2403+ //---------------------------- (error) --------------------------------
2404+ default:
2405+ EM_error2( lhs->linepos,
2406+ "(emit): internal error: unhandled op '%s' %s '%s'",
2407+ t_left->c_name(), op2str( op ), t_right->c_name() );
2408+ return FALSE;
2409+ }
2410+
2411+ // make sure emit
2412+ if( !instr )
2413+ {
2414+ EM_error2( lhs->linepos,
2415+ "(emit): internal error: unhandled op '%s' %s '%s'",
2416+ t_left->c_name(), op2str( op ), t_right->c_name() );
2417+ return FALSE;
2418+ }
2419+
2420+ return TRUE;
2421+}
2422+
2423+
2424+
2425+
2426+//-----------------------------------------------------------------------------
2427+// name: emit_engine_emit_op_chuck()
2428+// desc: ...
2429+//-----------------------------------------------------------------------------
2430+t_CKBOOL emit_engine_emit_op_chuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary )
2431+{
2432+ // any implicit cast happens before this
2433+ Chuck_Type * left = lhs->cast_to ? lhs->cast_to : lhs->type;
2434+ Chuck_Type * right = rhs->cast_to ? rhs->cast_to : rhs->type;
2435+
2436+ // the pointer
2437+ Chuck_Instr * instr = NULL;
2438+
2439+ // ugen => ugen
2440+ if( isa( left, emit->env->t_ugen ) && isa( right, emit->env->t_ugen ) )
2441+ {
2442+ // link, flag as NOT unchuck
2443+ emit->append( instr = new Chuck_Instr_UGen_Link( FALSE ) );
2444+ instr->set_linepos( lhs->linepos );
2445+ // done
2446+ return TRUE;
2447+ }
2448+
2449+ // ugen[] => ugen[] (or permutation)
2450+ if( ( isa( left, emit->env->t_ugen ) || ( isa( left, emit->env->t_array ) && isa( left->array_type, emit->env->t_ugen ) ) ) &&
2451+ ( isa( right, emit->env->t_ugen ) || ( isa( right, emit->env->t_array ) && isa( right->array_type, emit->env->t_ugen ) ) ) )
2452+ {
2453+ // link, flag as NOT unchuck
2454+ emit->append( instr = new Chuck_Instr_UGen_Array_Link( isa( left, emit->env->t_array ), isa( right, emit->env->t_array ) ) );
2455+ instr->set_linepos( lhs->linepos );
2456+ // done
2457+ return TRUE;
2458+ }
2459+
2460+ // time advance
2461+ if( isa( left, emit->env->t_dur ) && isa( right, emit->env->t_time ) && rhs->s_meta == ae_meta_var )
2462+ {
2463+ // add the two
2464+ emit->append( new Chuck_Instr_Add_double );
2465+
2466+ // see if rhs is 'now'
2467+ if( rhs->s_type == ae_exp_primary && !strcmp( "now", S_name(rhs->primary.var) ) )
2468+ {
2469+ // advance time
2470+ emit->append( instr = new Chuck_Instr_Time_Advance );
2471+ instr->set_linepos( lhs->linepos );
2472+ }
2473+
2474+ return TRUE;
2475+ }
2476+
2477+ // time advance
2478+ if( isa( left, emit->env->t_event ) && isa( right, emit->env->t_time ) && rhs->s_meta == ae_meta_var &&
2479+ rhs->s_type == ae_exp_primary && !strcmp( "now", S_name(rhs->primary.var) ) )
2480+ {
2481+ // pop now
2482+ emit->append( new Chuck_Instr_Reg_Pop_Word2 );
2483+ emit->append( instr = new Chuck_Instr_Event_Wait );
2484+ instr->set_linepos( lhs->linepos );
2485+
2486+ return TRUE;
2487+ }
2488+
2489+ // input
2490+ if( isa( left, emit->env->t_io ) )
2491+ {
2492+ if( isa( right, emit->env->t_int ) )
2493+ {
2494+ assert( rhs->s_meta == ae_meta_var );
2495+ emit->append( instr = new Chuck_Instr_IO_in_int );
2496+ instr->set_linepos( rhs->linepos );
2497+ return TRUE;
2498+ }
2499+ else if( isa( right, emit->env->t_float ) )
2500+ {
2501+ assert( rhs->s_meta == ae_meta_var );
2502+ emit->append( instr = new Chuck_Instr_IO_in_float );
2503+ instr->set_linepos( rhs->linepos );
2504+ return TRUE;
2505+ }
2506+ else if( isa( right, emit->env->t_string ) )
2507+ {
2508+ assert( rhs->s_meta == ae_meta_var );
2509+ emit->append( instr = new Chuck_Instr_IO_in_string );
2510+ instr->set_linepos( rhs->linepos );
2511+ return TRUE;
2512+ }
2513+ }
2514+
2515+ // func call
2516+ if( isa( right, emit->env->t_function ) )
2517+ {
2518+ assert( binary->ck_func != NULL );
2519+
2520+ // emit
2521+ return emit_engine_emit_exp_func_call( emit, binary->ck_func, binary->self->type, binary->linepos );
2522+ }
2523+
2524+ // assignment or something else
2525+ if( isa( left, right ) )
2526+ {
2527+ // basic types?
2528+ if( type_engine_check_primitive( emit->env, left ) || isa( left, emit->env->t_string ) )
2529+ {
2530+ // use at assign
2531+ return emit_engine_emit_op_at_chuck( emit, lhs, rhs );
2532+ }
2533+ }
2534+
2535+ // TODO: check overloading of =>
2536+ // TODO: deal with const
2537+
2538+ // no match
2539+ EM_error2( lhs->linepos,
2540+ "(emit): internal error: unhandled '=>' on types '%s' and '%s'...",
2541+ left->c_name(), right->c_name() );
2542+
2543+ return FALSE;
2544+}
2545+
2546+
2547+
2548+
2549+//-----------------------------------------------------------------------------
2550+// name: emit_engine_emit_op_unchuck()
2551+// desc: ...
2552+//-----------------------------------------------------------------------------
2553+t_CKBOOL emit_engine_emit_op_unchuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs )
2554+{
2555+ // any implicit cast happens before this
2556+ Chuck_Type * left = lhs->cast_to ? lhs->cast_to : lhs->type;
2557+ Chuck_Type * right = rhs->cast_to ? rhs->cast_to : rhs->type;
2558+
2559+ // if ugen
2560+ if( isa( left, emit->env->t_ugen ) && isa( right, emit->env->t_ugen ) )
2561+ {
2562+ // no connect
2563+ emit->append( new Chuck_Instr_UGen_UnLink );
2564+ }
2565+ else
2566+ {
2567+ EM_error2( lhs->linepos,
2568+ "(emit): internal error: unhandled '=<' on types '%s' and '%s'",
2569+ left->c_name(), right->c_name() );
2570+ return FALSE;
2571+ }
2572+
2573+ return TRUE;
2574+}
2575+
2576+
2577+
2578+
2579+//-----------------------------------------------------------------------------
2580+// name: emit_engine_emit_op_upchuck()
2581+// desc: ...
2582+//-----------------------------------------------------------------------------
2583+t_CKBOOL emit_engine_emit_op_upchuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs )
2584+{
2585+ // any implicit cast happens before this
2586+ Chuck_Type * left = lhs->cast_to ? lhs->cast_to : lhs->type;
2587+ Chuck_Type * right = rhs->cast_to ? rhs->cast_to : rhs->type;
2588+
2589+ // if ugen
2590+ if( isa( left, emit->env->t_uana ) && isa( right, emit->env->t_uana ) )
2591+ {
2592+ // connect; flag it as unchuck
2593+ Chuck_Instr * instr = NULL;
2594+ emit->append( instr = new Chuck_Instr_UGen_Link( TRUE ) );
2595+ instr->set_linepos( lhs->linepos );
2596+ }
2597+ else
2598+ {
2599+ EM_error2( lhs->linepos,
2600+ "(emit): internal error: unhandled '=^' on types '%s' and '%s'",
2601+ left->c_name(), right->c_name() );
2602+ return FALSE;
2603+ }
2604+
2605+ return TRUE;
2606+}
2607+
2608+
2609+
2610+
2611+//-----------------------------------------------------------------------------
2612+// name: emit_engine_emit_op_at_chuck()
2613+// desc: ...
2614+//-----------------------------------------------------------------------------
2615+t_CKBOOL emit_engine_emit_op_at_chuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs )
2616+{
2617+ // any implicit cast happens before this
2618+ Chuck_Type * left = lhs->cast_to ? lhs->cast_to : lhs->type;
2619+ Chuck_Type * right = rhs->cast_to ? rhs->cast_to : rhs->type;
2620+
2621+ // assignment or something else
2622+ if( isa( left, right ) )
2623+ {
2624+ // basic types?
2625+ if( type_engine_check_primitive( emit->env, left ) || isa( left, emit->env->t_string ) )
2626+ {
2627+ // assigment?
2628+ if( rhs->s_meta != ae_meta_var )
2629+ {
2630+ EM_error2( lhs->linepos,
2631+ "(emit): internal error: assignment to non-variable..." );
2632+ return FALSE;
2633+ }
2634+
2635+ // see if rhs is 'now' - time => now
2636+ if( rhs->s_type == ae_exp_primary && !strcmp( "now", S_name(rhs->primary.var) ) )
2637+ {
2638+ // pop the now addr
2639+ emit->append( new Chuck_Instr_Reg_Pop_Word2 );
2640+ // advance time
2641+ Chuck_Instr * instr = NULL;
2642+ emit->append( instr = new Chuck_Instr_Time_Advance );
2643+ instr->set_linepos( lhs->linepos );
2644+ }
2645+ else if( isa( left, emit->env->t_string ) ) // string
2646+ {
2647+ // assign string
2648+ emit->append( new Chuck_Instr_Assign_String );
2649+ }
2650+ else
2651+ {
2652+ // assign primitive
2653+ // added 1.3.1.0: iskindofint -- since on some 64-bit systems, sz_INT == sz_FLOAT
2654+ if( right->size == sz_INT && iskindofint(emit->env, right) ) // ISSUE: 64-bit (fixed 1.3.1.0)
2655+ emit->append( new Chuck_Instr_Assign_Primitive );
2656+ else if( right->size == sz_FLOAT ) // ISSUE: 64-bit (fixed 1.3.1.0)
2657+ emit->append( new Chuck_Instr_Assign_Primitive2 );
2658+ else if( right->size == sz_COMPLEX ) // ISSUE: 64-bit (fixed 1.3.1.0)
2659+ emit->append( new Chuck_Instr_Assign_Primitive4 );
2660+ else if( right->size == sz_VEC3 ) // ge: added 1.3.5.3
2661+ emit->append( new Chuck_Instr_Assign_PrimitiveVec3 );
2662+ else if( right->size == sz_VEC4 ) // ge: added 1.3.5.3
2663+ emit->append( new Chuck_Instr_Assign_PrimitiveVec4 );
2664+ else
2665+ {
2666+ EM_error2( rhs->linepos,
2667+ "(emit): internal error: assignment to type of size %i...",
2668+ right->size );
2669+ }
2670+ }
2671+
2672+ return TRUE;
2673+ }
2674+ else // objects
2675+ {
2676+ // assign object
2677+ emit->append( new Chuck_Instr_Assign_Object );
2678+
2679+ return TRUE;
2680+ }
2681+ }
2682+
2683+ // TODO: check overloading of =>
2684+ // TODO: deal with const
2685+
2686+ // no match
2687+ EM_error2( lhs->linepos,
2688+ "(emit): internal error: unhandled '@=>' on types '%s' and '%s'...",
2689+ left->c_name(), right->c_name() );
2690+
2691+ return FALSE;
2692+}
2693+
2694+
2695+
2696+
2697+//-----------------------------------------------------------------------------
2698+// name: emit_engine_emit_exp_unary()
2699+// desc: ...
2700+//-----------------------------------------------------------------------------
2701+t_CKBOOL emit_engine_emit_exp_unary( Chuck_Emitter * emit, a_Exp_Unary unary )
2702+{
2703+ if( unary->op != ae_op_spork && !emit_engine_emit_exp( emit, unary->exp ) )
2704+ return FALSE;
2705+
2706+ // get type
2707+ Chuck_Type * t = unary->self->type;
2708+ assert( t != NULL );
2709+
2710+ // emit the operator
2711+ switch( unary->op )
2712+ {
2713+ case ae_op_plusplus:
2714+ // make sure assignment is legal
2715+ if( unary->self->s_meta != ae_meta_var ) // TODO: const
2716+ {
2717+ EM_error2( unary->self->linepos,
2718+ "(emit): target for '++' not mutable..." );
2719+ return FALSE;
2720+ }
2721+
2722+ // increment
2723+ if( equals( unary->exp->type, emit->env->t_int ) )
2724+ emit->append( new Chuck_Instr_PreInc_int );
2725+ else
2726+ {
2727+ EM_error2( unary->linepos,
2728+ "(emit): internal error: unhandled type '%s' for pre '++'' operator",
2729+ unary->exp->type->c_name() );
2730+ return FALSE;
2731+ }
2732+ break;
2733+
2734+ case ae_op_minusminus:
2735+ // make sure assignment is legal
2736+ if( unary->self->s_meta != ae_meta_var ) // TODO: const
2737+ {
2738+ EM_error2( unary->self->linepos,
2739+ "(emit): target for '--' not mutable..." );
2740+ return FALSE;
2741+ }
2742+
2743+ // decrement
2744+ if( equals( unary->exp->type, emit->env->t_int ) )
2745+ emit->append( new Chuck_Instr_PreDec_int );
2746+ else
2747+ {
2748+ EM_error2( unary->linepos,
2749+ "(emit): internal error: unhandled type '%s' for pre '--' operator",
2750+ unary->exp->type->c_name() );
2751+ return FALSE;
2752+ }
2753+ break;
2754+
2755+ case ae_op_tilda:
2756+ // complement
2757+ if( equals( unary->exp->type, emit->env->t_int ) )
2758+ emit->append( new Chuck_Instr_Complement_int );
2759+ else
2760+ {
2761+ EM_error2( unary->linepos,
2762+ "(emit): internal error: unhandled type '%s' for '~' operator",
2763+ unary->exp->type->c_name() );
2764+ return FALSE;
2765+ }
2766+ break;
2767+
2768+ case ae_op_exclamation:
2769+ // !
2770+ if( equals( unary->exp->type, emit->env->t_int ) )
2771+ emit->append( new Chuck_Instr_Not_int );
2772+ else
2773+ {
2774+ EM_error2( unary->linepos,
2775+ "(emit): internal error: unhandled type '%s' for '!' operator",
2776+ unary->exp->type->c_name() );
2777+ return FALSE;
2778+ }
2779+ break;
2780+
2781+ case ae_op_minus:
2782+ // negate
2783+ if( equals( unary->exp->type, emit->env->t_int ) )
2784+ emit->append( new Chuck_Instr_Negate_int );
2785+ else if( equals( unary->exp->type, emit->env->t_float ) )
2786+ emit->append( new Chuck_Instr_Negate_double );
2787+ else
2788+ {
2789+ EM_error2( unary->linepos,
2790+ "(emit): internal error: unhandled type '%s' for unary '-' operator",
2791+ unary->exp->type->c_name() );
2792+ return FALSE;
2793+ }
2794+ break;
2795+
2796+ case ae_op_spork:
2797+ // spork ~ func()
2798+ if( unary->exp && unary->exp->s_type == ae_exp_func_call )
2799+ {
2800+ if( !emit_engine_emit_spork( emit, &unary->exp->func_call ) )
2801+ return FALSE;
2802+ }
2803+ // spork ~ { ... }
2804+ // else if( unary->code )
2805+ // {
2806+ // if( !emit_engine_emit_spork( emit, unary->code ) )
2807+ // return FALSE;
2808+ // }
2809+ else
2810+ {
2811+ EM_error2( unary->linepos,
2812+ "(emit): internal error: sporking non-function call..." );
2813+ return FALSE;
2814+ }
2815+ break;
2816+
2817+ case ae_op_new:
2818+
2819+ // if this is an object
2820+ if( isobj( emit->env, t ) )
2821+ {
2822+ // instantiate object, including array
2823+ if( !emit_engine_instantiate_object( emit, t, unary->array, unary->type->ref ) )
2824+ return FALSE;
2825+ }
2826+ break;
2827+
2828+ default:
2829+ EM_error2( unary->linepos,
2830+ "(emit): internal error: unhandled unary op '%s",
2831+ op2str( unary->op ) );
2832+ return FALSE;
2833+ }
2834+
2835+ return TRUE;
2836+}
2837+
2838+
2839+
2840+
2841+//-----------------------------------------------------------------------------
2842+// name: emit_engine_emit_exp_primary()
2843+// desc: ...
2844+//-----------------------------------------------------------------------------
2845+t_CKBOOL emit_engine_emit_exp_primary( Chuck_Emitter * emit, a_Exp_Primary exp )
2846+{
2847+ t_CKUINT temp;
2848+ t_CKDUR dur;
2849+ Chuck_String * str = NULL;
2850+
2851+ // find out exp
2852+ switch( exp->s_type )
2853+ {
2854+ case ae_primary_var:
2855+ if( exp->var == insert_symbol( "now" ) )
2856+ {
2857+ emit->append( new Chuck_Instr_Reg_Push_Now );
2858+ }
2859+ else if( exp->var == insert_symbol( "this" ) )
2860+ {
2861+ // TODO: verify this is in the right scope
2862+ emit->append( new Chuck_Instr_Reg_Push_This );
2863+ }
2864+ else if( exp->var == insert_symbol( "me" ) )
2865+ {
2866+ emit->append( new Chuck_Instr_Reg_Push_Me );
2867+ }
2868+ else if( exp->var == insert_symbol( "true" ) )
2869+ {
2870+ emit->append( new Chuck_Instr_Reg_Push_Imm( 1 ) );
2871+ }
2872+ else if( exp->var == insert_symbol( "false" ) )
2873+ {
2874+ emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
2875+ }
2876+ else if( exp->var == insert_symbol("maybe") )
2877+ {
2878+ emit->append( new Chuck_Instr_Reg_Push_Maybe() );
2879+ }
2880+ else if( exp->var == insert_symbol("null") ||
2881+ exp->var == insert_symbol("NULL") )
2882+ {
2883+ emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
2884+ }
2885+ else if( exp->var == insert_symbol( "pi" ) )
2886+ {
2887+ double pi = 3.14159265358979323846;
2888+ emit->append( new Chuck_Instr_Reg_Push_Imm2( pi ) );
2889+ }
2890+ else if( exp->var == insert_symbol( "dac" ) )
2891+ {
2892+ emit->append( new Chuck_Instr_DAC );
2893+ }
2894+ else if( exp->var == insert_symbol( "adc" ) )
2895+ {
2896+ emit->append( new Chuck_Instr_ADC );
2897+ }
2898+ else if( exp->var == insert_symbol( "bunghole" ) )
2899+ {
2900+ emit->append( new Chuck_Instr_Bunghole );
2901+ }
2902+ else if( exp->var == insert_symbol( "blackhole" ) )
2903+ {
2904+ emit->append( new Chuck_Instr_Bunghole );
2905+ }
2906+ else if( exp->var == insert_symbol( "chout" ) )
2907+ {
2908+ emit->append( new Chuck_Instr_Chout );
2909+ }
2910+ else if( exp->var == insert_symbol( "cherr" ) )
2911+ {
2912+ emit->append( new Chuck_Instr_Cherr );
2913+ }
2914+ else if( emit->find_dur( S_name(exp->var), &dur ) )
2915+ {
2916+ emit->append( new Chuck_Instr_Reg_Push_Imm2( dur ) );
2917+ }
2918+ else
2919+ {
2920+ // emit the symbol
2921+ return emit_engine_emit_symbol(
2922+ emit, exp->var, exp->value, exp->self->emit_var, exp->linepos );
2923+ }
2924+ break;
2925+
2926+ case ae_primary_num:
2927+ memcpy( &temp, &exp->num, sizeof(temp) );
2928+ emit->append( new Chuck_Instr_Reg_Push_Imm( temp ) );
2929+ break;
2930+
2931+ case ae_primary_float:
2932+ emit->append( new Chuck_Instr_Reg_Push_Imm2( exp->fnum ) );
2933+ break;
2934+
2935+ case ae_primary_str:
2936+ // TODO: fix this
2937+ str = new Chuck_String();
2938+ if( !str || !initialize_object( str, emit->env->t_string ) )
2939+ {
2940+ // error (TODO: why is this a SAFE_RELEASE and not SAFE_DELETE?)
2941+ SAFE_RELEASE( str );
2942+ // error out
2943+ CK_FPRINTF_STDERR(
2944+ "[chuck](emitter): OutOfMemory: while allocating string literal '%s'\n", exp->str );
2945+ return FALSE;
2946+ }
2947+ str->set( exp->str );
2948+ temp = (t_CKUINT)str;
2949+ emit->append( new Chuck_Instr_Reg_Push_Imm( temp ) );
2950+ // add reference for string literal (added 1.3.0.2)
2951+ str->add_ref();
2952+ break;
2953+
2954+ case ae_primary_char:
2955+ emit->append( new Chuck_Instr_Reg_Push_Imm( str2char(exp->chr, exp->linepos ) ) );
2956+ break;
2957+
2958+ case ae_primary_array:
2959+ if( !emit_engine_emit_array_lit( emit, exp->array ) )
2960+ return FALSE;
2961+ break;
2962+
2963+ case ae_primary_complex:
2964+ if( !emit_engine_emit_complex_lit( emit, exp->complex ) )
2965+ return FALSE;
2966+ break;
2967+
2968+ case ae_primary_polar:
2969+ if( !emit_engine_emit_polar_lit( emit, exp->polar ) )
2970+ return FALSE;
2971+ break;
2972+
2973+ case ae_primary_vec:
2974+ if( !emit_engine_emit_vec_lit( emit, exp->vec ) )
2975+ return FALSE;
2976+ break;
2977+
2978+ case ae_primary_exp:
2979+ if( !emit_engine_emit_exp( emit, exp->exp ) )
2980+ return FALSE;
2981+ break;
2982+
2983+ case ae_primary_hack:
2984+ {
2985+ a_Exp e = exp->exp;
2986+ // emit the expression
2987+ if( !emit_engine_emit_exp( emit, e ) )
2988+ return FALSE;
2989+ std::vector<Chuck_Type *> types;
2990+
2991+ while( e != NULL )
2992+ {
2993+ types.push_back( e->type );
2994+ e = e->next;
2995+ }
2996+
2997+ // emit hack
2998+ emit->append( new Chuck_Instr_Gack( types ) );
2999+
3000+ break;
3001+ }
3002+
3003+ // ge (april 2012): nil is void, so nothing to emit; TODO: check it (added 1.3.0.0)
3004+ case ae_primary_nil:
3005+ break;
3006+ }
3007+
3008+ return TRUE;
3009+}
3010+
3011+
3012+
3013+
3014+//-----------------------------------------------------------------------------
3015+// name: emit_engine_emit_array_lit()
3016+// desc: ...
3017+//-----------------------------------------------------------------------------
3018+t_CKBOOL emit_engine_emit_array_lit( Chuck_Emitter * emit, a_Array_Sub array )
3019+{
3020+ // go through and emit the expressions
3021+ if( !emit_engine_emit_exp( emit, array->exp_list ) )
3022+ return FALSE;
3023+
3024+ // count the number
3025+ a_Exp e = array->exp_list;
3026+ t_CKUINT count = 0;
3027+ // loop over
3028+ while( e ) { count++; e = e->next; }
3029+
3030+ // the type
3031+ e = array->exp_list;
3032+ Chuck_Type * type = e->cast_to ? e->cast_to : e->type;
3033+
3034+ // construct array dynamically
3035+ Chuck_Instr * instr = NULL;
3036+ emit->append( instr = new Chuck_Instr_Array_Init( emit->env, type, count ) );
3037+ instr->set_linepos( array->linepos );
3038+
3039+ return TRUE;
3040+}
3041+
3042+
3043+
3044+
3045+//-----------------------------------------------------------------------------
3046+// name: emit_engine_emit_complex_lit()
3047+// desc: ...
3048+//-----------------------------------------------------------------------------
3049+t_CKBOOL emit_engine_emit_complex_lit( Chuck_Emitter * emit, a_Complex val )
3050+{
3051+ // go through and emit the real and imaginary
3052+ if( !emit_engine_emit_exp( emit, val->re ) )
3053+ return FALSE;
3054+
3055+ // imaginary (not needed since linked after real
3056+ // if( !emit_engine_emit_exp( emit, val->im ) )
3057+ // return FALSE;
3058+
3059+ return TRUE;
3060+}
3061+
3062+
3063+
3064+
3065+//-----------------------------------------------------------------------------
3066+// name: emit_engine_emit_polar_lit()
3067+// desc: ...
3068+//-----------------------------------------------------------------------------
3069+t_CKBOOL emit_engine_emit_polar_lit( Chuck_Emitter * emit, a_Polar val )
3070+{
3071+ // go through and emit the mod and phase
3072+ if( !emit_engine_emit_exp( emit, val->mod ) )
3073+ return FALSE;
3074+
3075+ // phase (not needed since linked after mod)
3076+ // if( !emit_engine_emit_exp( emit, val->phase ) )
3077+ // return FALSE;
3078+
3079+ return TRUE;
3080+}
3081+
3082+
3083+
3084+
3085+//-----------------------------------------------------------------------------
3086+// name: emit_engine_emit_vec_lit()
3087+// desc: ...
3088+//-----------------------------------------------------------------------------
3089+t_CKBOOL emit_engine_emit_vec_lit( Chuck_Emitter * emit, a_Vec val )
3090+{
3091+ // go through and emit the mod and phase
3092+ if( !emit_engine_emit_exp( emit, val->args ) )
3093+ return FALSE;
3094+
3095+ // zero pad if needed
3096+ t_CKINT n = 3 - val->numdims;
3097+ // any remaining
3098+ while( n > 0 )
3099+ {
3100+ // emit a zero float
3101+ emit->append( new Chuck_Instr_Reg_Push_Imm2( 0 ) );
3102+ // decrement
3103+ n--;
3104+ }
3105+
3106+ return TRUE;
3107+}
3108+
3109+
3110+
3111+
3112+//-----------------------------------------------------------------------------
3113+// name: emit_engine_emit_exp_cast()
3114+// desc: ...
3115+//-----------------------------------------------------------------------------
3116+t_CKBOOL emit_engine_emit_exp_cast( Chuck_Emitter * emit, a_Exp_Cast cast )
3117+{
3118+ Chuck_Type * to = cast->self->type;
3119+ Chuck_Type * from = cast->exp->type;
3120+
3121+ // emit the exp
3122+ if( !emit_engine_emit_exp( emit, cast->exp ) )
3123+ return FALSE;
3124+
3125+ // the actual work to be done
3126+ return emit_engine_emit_cast( emit, to, from );
3127+}
3128+
3129+
3130+
3131+
3132+//-----------------------------------------------------------------------------
3133+// name: emit_engine_emit_cast()
3134+// desc: ...
3135+//-----------------------------------------------------------------------------
3136+t_CKBOOL emit_engine_emit_cast( Chuck_Emitter * emit,
3137+ Chuck_Type * to, Chuck_Type * from )
3138+{
3139+ // if type is already the same
3140+ if( equals( to, from ) )
3141+ return TRUE;
3142+
3143+ // int to float
3144+ if( equals( to, emit->env->t_int ) && equals( from, emit->env->t_float ) )
3145+ emit->append( new Chuck_Instr_Cast_double2int );
3146+ // float to int
3147+ else if( equals( to, emit->env->t_float ) && equals( from, emit->env->t_int ) )
3148+ emit->append( new Chuck_Instr_Cast_int2double );
3149+ else if( equals( to, emit->env->t_complex ) && equals( from, emit->env->t_int ) )
3150+ emit->append( new Chuck_Instr_Cast_int2complex );
3151+ else if( equals( to, emit->env->t_polar ) && equals( from, emit->env->t_int ) )
3152+ emit->append( new Chuck_Instr_Cast_int2polar );
3153+ else if( equals( to, emit->env->t_complex ) && equals( from, emit->env->t_float ) )
3154+ emit->append( new Chuck_Instr_Cast_double2complex );
3155+ else if( equals( to, emit->env->t_polar ) && equals( from, emit->env->t_float ) )
3156+ emit->append( new Chuck_Instr_Cast_double2polar );
3157+ else if( equals( to, emit->env->t_polar ) && equals( from, emit->env->t_complex ) )
3158+ emit->append( new Chuck_Instr_Cast_complex2polar );
3159+ else if( equals( to, emit->env->t_complex ) && equals( from, emit->env->t_polar ) )
3160+ emit->append( new Chuck_Instr_Cast_polar2complex );
3161+ else if( equals( to, emit->env->t_vec3 ) && equals( from, emit->env->t_vec4 ) )
3162+ emit->append( new Chuck_Instr_Cast_vec4tovec3 );
3163+ else if( equals( to, emit->env->t_vec4 ) && equals( from, emit->env->t_vec3 ) )
3164+ emit->append( new Chuck_Instr_Cast_vec3tovec4 );
3165+ else if( equals( to, emit->env->t_string ) && isa( from, emit->env->t_object ) && !isa( from, emit->env->t_string ) )
3166+ emit->append( new Chuck_Instr_Cast_object2string );
3167+ // up cast - do nothing
3168+ else if( !isa( to, from ) && !isa( from, to ) )
3169+ {
3170+ EM_error2( 0, "(emit): internal error: cannot cast type '%s' to '%s'",
3171+ from->c_name(), to->c_name() );
3172+ return FALSE;
3173+ }
3174+
3175+ return TRUE;
3176+}
3177+
3178+
3179+
3180+
3181+//-----------------------------------------------------------------------------
3182+// name: emit_engine_emit_exp_postfix()
3183+// desc: ...
3184+//-----------------------------------------------------------------------------
3185+t_CKBOOL emit_engine_emit_exp_postfix( Chuck_Emitter * emit, a_Exp_Postfix postfix )
3186+{
3187+ // emit the exp
3188+ if( !emit_engine_emit_exp( emit, postfix->exp ) )
3189+ return FALSE;
3190+
3191+ // emit
3192+ switch( postfix->op )
3193+ {
3194+ case ae_op_plusplus:
3195+ if( equals( postfix->exp->type, emit->env->t_int ) )
3196+ emit->append( new Chuck_Instr_PostInc_int );
3197+ else
3198+ {
3199+ EM_error2( postfix->linepos,
3200+ "(emit): internal error: unhandled type '%s' for post '++' operator",
3201+ postfix->exp->type->c_name() );
3202+ return FALSE;
3203+ }
3204+ break;
3205+
3206+ case ae_op_minusminus:
3207+ if( equals( postfix->exp->type, emit->env->t_int ) )
3208+ emit->append( new Chuck_Instr_PostDec_int );
3209+ else
3210+ {
3211+ EM_error2( postfix->linepos,
3212+ "(emit): internal error: unhandled type '%s' for post '--' operator",
3213+ postfix->exp->type->c_name() );
3214+ return FALSE;
3215+ }
3216+ break;
3217+
3218+ default:
3219+ EM_error2( postfix->linepos,
3220+ "(emit): internal error: unhandled postfix operator '%s'",
3221+ op2str( postfix->op ) );
3222+ return FALSE;
3223+ }
3224+
3225+ return TRUE;
3226+}
3227+
3228+
3229+
3230+
3231+//-----------------------------------------------------------------------------
3232+// name: emit_engine_emit_exp_dur()
3233+// desc: ...
3234+//-----------------------------------------------------------------------------
3235+t_CKBOOL emit_engine_emit_exp_dur( Chuck_Emitter * emit, a_Exp_Dur dur )
3236+{
3237+ // emit base
3238+ if( !emit_engine_emit_exp( emit, dur->base ) )
3239+ return FALSE;
3240+
3241+ // cast
3242+ if( equals( dur->base->type, emit->env->t_int ) )
3243+ emit->append( new Chuck_Instr_Cast_int2double );
3244+
3245+ // emit unit
3246+ if( !emit_engine_emit_exp( emit, dur->unit ) )
3247+ return FALSE;
3248+
3249+ // multiply
3250+ emit->append( new Chuck_Instr_Times_double );
3251+
3252+ return TRUE;
3253+}
3254+
3255+
3256+
3257+
3258+//-----------------------------------------------------------------------------
3259+// name: emit_engine_emit_exp_array()
3260+// desc: ...
3261+//-----------------------------------------------------------------------------
3262+t_CKBOOL emit_engine_emit_exp_array( Chuck_Emitter * emit, a_Exp_Array array )
3263+{
3264+ Chuck_Type * type = NULL, * base_type = NULL;
3265+ t_CKUINT depth = 0;
3266+ a_Array_Sub sub = NULL;
3267+ a_Exp exp = NULL;
3268+ t_CKBOOL is_var = FALSE;
3269+ t_CKBOOL is_str = FALSE;
3270+
3271+ // get the type
3272+ type = array->self->type;
3273+ // get the base type
3274+ base_type = array->base->type;
3275+ // emit as addr?
3276+ is_var = array->self->emit_var;
3277+ // get the dimension
3278+ depth = base_type->array_depth - type->array_depth;
3279+ // make sure
3280+ if( depth == 0 )
3281+ {
3282+ EM_error2( array->linepos,
3283+ "(emit): internal error: array with 0 depth..." );
3284+ return FALSE;
3285+ }
3286+ // get the sub
3287+ sub = array->indices;
3288+ if( !sub )
3289+ {
3290+ EM_error2( array->linepos,
3291+ "(emit): internal error: NULL array sub..." );
3292+ return FALSE;
3293+ }
3294+ // get the exp list
3295+ exp = sub->exp_list;
3296+ if( !exp )
3297+ {
3298+ EM_error2( array->linepos,
3299+ "(emit): internal error: NULL array exp..." );
3300+ return FALSE;
3301+ }
3302+
3303+ // emit the base (it should be a pointer to array)
3304+ if( !emit_engine_emit_exp( emit, array->base ) )
3305+ return FALSE;
3306+
3307+ // emit the exp list
3308+ if( !emit_engine_emit_exp( emit, exp ) )
3309+ return FALSE;
3310+
3311+ // find out first element
3312+ if( isa( exp->type, emit->env->t_string ) )
3313+ is_str = TRUE;
3314+
3315+ // make sure
3316+ // ISSUE: 64-bit (fixed 1.3.1.0)
3317+ if( type->size != sz_INT && type->size != sz_FLOAT && type->size != sz_COMPLEX &&
3318+ type->size != sz_VEC3 && type->size != sz_VEC4 )
3319+ {
3320+ EM_error2( array->linepos,
3321+ "(emit): internal error: array with datasize of %i...", type->size );
3322+ return FALSE;
3323+ }
3324+
3325+ // check the depth
3326+ if( depth == 1 )
3327+ {
3328+ // the pointer
3329+ Chuck_Instr * instr = NULL;
3330+ // emit the array access (1.3.1.0: use getkindof instead of type->size)
3331+ if( is_str )
3332+ emit->append( instr = new Chuck_Instr_Array_Map_Access( getkindof(emit->env, type), is_var ) );
3333+ else
3334+ emit->append( instr = new Chuck_Instr_Array_Access( getkindof(emit->env, type), is_var ) );
3335+ instr->set_linepos( array->linepos );
3336+ }
3337+ else
3338+ {
3339+ // the pointer
3340+ Chuck_Instr_Array_Access_Multi * aam = NULL;
3341+ // emit the multi array access (1.3.1.0: use getkindof instead of type->size)
3342+ emit->append( aam = new Chuck_Instr_Array_Access_Multi( depth, getkindof(emit->env, type), is_var ) );
3343+ aam->set_linepos( array->linepos );
3344+ // add type info (1.3.1.0) -- to support mixed string & int indexing (thanks Robin Haberkorn)
3345+ a_Exp e = exp;
3346+ while( e )
3347+ {
3348+ // check if string
3349+ aam->indexIsAssociative().push_back( isa( exp->type, emit->env->t_string ) );
3350+ // next
3351+ e = e->next;
3352+ }
3353+ }
3354+
3355+ // TODO: variable?
3356+
3357+ return TRUE;
3358+}
3359+
3360+
3361+
3362+
3363+//-----------------------------------------------------------------------------
3364+// name: emit_engine_emit_exp_func_call()
3365+// desc: ...
3366+//-----------------------------------------------------------------------------
3367+t_CKBOOL emit_engine_emit_exp_func_call( Chuck_Emitter * emit,
3368+ Chuck_Func * func,
3369+ Chuck_Type * type,
3370+ int linepos,
3371+ t_CKBOOL spork )
3372+{
3373+ // is a member?
3374+ t_CKBOOL is_member = func->is_member;
3375+
3376+ // if member
3377+ //if( is_member )
3378+ //{
3379+ // // this
3380+ // emit->append( new Chuck_Instr_Reg_Push_This );
3381+ //}
3382+
3383+ // translate to code
3384+ emit->append( new Chuck_Instr_Func_To_Code );
3385+ // emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)func->code ) );
3386+ // push the local stack depth - local variables
3387+ emit->append( new Chuck_Instr_Reg_Push_Imm( emit->code->frame->curr_offset ) );
3388+
3389+ // TODO: member functions and static functions
3390+ // call the function
3391+ t_CKUINT size = type->size;
3392+ t_CKUINT kind = getkindof( emit->env, type ); // added 1.3.1.0
3393+
3394+ // the pointer
3395+ Chuck_Instr * instr = NULL;
3396+ if( func->def->s_type == ae_func_builtin )
3397+ {
3398+ // ISSUE: 64-bit (fixed 1.3.1.0)
3399+ if( size == 0 || size == sz_INT || size == sz_FLOAT || size == sz_COMPLEX ||
3400+ size == sz_VEC3 || sz_VEC4 )
3401+ {
3402+ // is member (1.3.1.0: changed to use kind instead of size)
3403+ if( is_member )
3404+ emit->append( instr = new Chuck_Instr_Func_Call_Member( kind ) );
3405+ else
3406+ emit->append( instr = new Chuck_Instr_Func_Call_Static( kind ) );
3407+ }
3408+ else
3409+ {
3410+ EM_error2( linepos,
3411+ "(emit): internal error: %i func call not handled",
3412+ size );
3413+ return FALSE;
3414+ }
3415+ }
3416+ else
3417+ {
3418+ emit->append( instr = new Chuck_Instr_Func_Call );
3419+ }
3420+ instr->set_linepos(linepos);
3421+
3422+ return TRUE;
3423+}
3424+
3425+
3426+
3427+
3428+//-----------------------------------------------------------------------------
3429+// name: emit_engine_emit_func_args()
3430+// desc: ...
3431+//-----------------------------------------------------------------------------
3432+t_CKBOOL emit_engine_emit_func_args( Chuck_Emitter * emit,
3433+ a_Exp_Func_Call func_call )
3434+{
3435+ // emit the args (TRUE for doAddRef added 1.3.0.0)
3436+ if( !emit_engine_emit_exp( emit, func_call->args, TRUE ) )
3437+ {
3438+ EM_error2( func_call->linepos,
3439+ "(emit): internal error in emitting function call arguments..." );
3440+ return FALSE;
3441+ }
3442+
3443+ return TRUE;
3444+}
3445+
3446+
3447+
3448+
3449+//-----------------------------------------------------------------------------
3450+// name: emit_engine_emit_exp_func_call()
3451+// desc: ...
3452+//-----------------------------------------------------------------------------
3453+t_CKBOOL emit_engine_emit_exp_func_call( Chuck_Emitter * emit,
3454+ a_Exp_Func_Call func_call,
3455+ t_CKBOOL spork )
3456+{
3457+ // note: spork situations are now taken care in exp_spork...
3458+ // please look at that one before modifying this one!
3459+
3460+ // make sure there are args, and not sporking
3461+ if( func_call->args && !spork )
3462+ {
3463+ if( !emit_engine_emit_func_args( emit, func_call ) )
3464+ return FALSE;
3465+ }
3466+
3467+ // emit func
3468+ if( !emit_engine_emit_exp( emit, func_call->func ) )
3469+ {
3470+ EM_error2( func_call->linepos,
3471+ "(emit): internal error in evaluating function call..." );
3472+ return FALSE;
3473+ }
3474+
3475+ // the rest
3476+ return emit_engine_emit_exp_func_call( emit, func_call->ck_func, func_call->ret_type,
3477+ func_call->linepos, spork );
3478+}
3479+
3480+
3481+
3482+
3483+//-----------------------------------------------------------------------------
3484+// name: emit_engine_emit_dot_member_special()
3485+// desc: emit special dot member: complex, polar, vec3, vec4
3486+//-----------------------------------------------------------------------------
3487+t_CKBOOL emit_engine_emit_exp_dot_member_special( Chuck_Emitter * emit,
3488+ a_Exp_Dot_Member member )
3489+{
3490+ // whether to emit addr or value
3491+ t_CKBOOL emit_addr = member->self->emit_var;
3492+
3493+ // special case: complex and polar
3494+ if( member->t_base->xid == te_complex )
3495+ {
3496+ // mark to emit addr
3497+ if( member->base->s_meta == ae_meta_var )
3498+ member->base->emit_var = TRUE;
3499+ else if( emit_addr )
3500+ {
3501+ EM_error2( member->base->linepos,
3502+ "(emit): cannot assign value to literal 'complex' value..." );
3503+ return FALSE;
3504+ }
3505+
3506+ // emit the base
3507+ if( !emit_engine_emit_exp( emit, member->base ) )
3508+ return FALSE;
3509+
3510+ string str = S_name(member->xid);
3511+ // check
3512+ if( str == "re" )
3513+ emit->append( new Chuck_Instr_Dot_Cmp_First( member->base->s_meta == ae_meta_var, emit_addr ) );
3514+ else if( str == "im" )
3515+ emit->append( new Chuck_Instr_Dot_Cmp_Second( member->base->s_meta == ae_meta_var, emit_addr ) );
3516+ else
3517+ goto check_func;
3518+
3519+ // done
3520+ return TRUE;
3521+ }
3522+ else if( member->t_base->xid == te_polar )
3523+ {
3524+ // mark to emit addr
3525+ if( member->base->s_meta == ae_meta_var )
3526+ member->base->emit_var = TRUE;
3527+ else if( emit_addr )
3528+ {
3529+ EM_error2( member->base->linepos,
3530+ "(emit): cannot assign value to literal 'polar' value..." );
3531+ return FALSE;
3532+ }
3533+
3534+ // emit the base
3535+ if( !emit_engine_emit_exp( emit, member->base ) )
3536+ return FALSE;
3537+
3538+ string str = S_name(member->xid);
3539+ // check
3540+ if( str == "mag" )
3541+ emit->append( new Chuck_Instr_Dot_Cmp_First( member->base->s_meta == ae_meta_var, emit_addr ) );
3542+ else if( str == "phase" )
3543+ emit->append( new Chuck_Instr_Dot_Cmp_Second( member->base->s_meta == ae_meta_var, emit_addr ) );
3544+ else
3545+ goto check_func;
3546+
3547+ // done
3548+ return TRUE;
3549+ }
3550+ else if( member->t_base->xid == te_vec3 || member->t_base->xid == te_vec4 )
3551+ {
3552+ // mark to emit addr
3553+ if( member->base->s_meta == ae_meta_var )
3554+ member->base->emit_var = TRUE;
3555+ else if( emit_addr )
3556+ {
3557+ EM_error2( member->base->linepos,
3558+ "(emit): cannot assign value to literal '%s' value...",
3559+ member->t_base->c_name() );
3560+ return FALSE;
3561+ }
3562+
3563+ // emit the base
3564+ if( !emit_engine_emit_exp( emit, member->base ) )
3565+ return FALSE;
3566+
3567+ string str = S_name(member->xid);
3568+ // check for .xyz[w] .rgb[a] .value/goal/slew
3569+ if( str == "x" || str == "r" || str == "value" )
3570+ emit->append( new Chuck_Instr_Dot_Cmp_First( member->base->s_meta == ae_meta_var, emit_addr ) );
3571+ else if( str == "y" || str == "g" || str == "goal" )
3572+ emit->append( new Chuck_Instr_Dot_Cmp_Second( member->base->s_meta == ae_meta_var, emit_addr ) );
3573+ else if( str == "z" || str == "b" || str == "slew" )
3574+ emit->append( new Chuck_Instr_Dot_Cmp_Third( member->base->s_meta == ae_meta_var, emit_addr ) );
3575+ else if( member->t_base->xid == te_vec4 && ( str == "w" || str == "a" ) )
3576+ emit->append( new Chuck_Instr_Dot_Cmp_Fourth( member->base->s_meta == ae_meta_var, emit_addr ) );
3577+ else
3578+ goto check_func;
3579+
3580+ // done
3581+ return TRUE;
3582+ }
3583+
3584+ // should not get here
3585+ EM_error2( member->base->linepos,
3586+ "(emit): internal error in lit_special()..." );
3587+
3588+ return FALSE;
3589+
3590+//-----------------------------------------------------------------------------
3591+// goto: check for special member functions, 1.3.5.3
3592+//-----------------------------------------------------------------------------
3593+check_func:
3594+
3595+ // the type of the base
3596+ Chuck_Type * t_base = member->t_base;
3597+ // is the base a class/namespace or a variable
3598+ t_CKBOOL base_static = isa( member->t_base, emit->env->t_class );
3599+ // a function
3600+ Chuck_Func * func = NULL;
3601+ // a non-function value
3602+ Chuck_Value * value = NULL;
3603+ // the offset
3604+ t_CKUINT offset = 0;
3605+
3606+ // check error
3607+ if( base_static )
3608+ {
3609+ // should not get here
3610+ EM_error2( member->base->linepos,
3611+ "(emit): internal error in lit_special(): base static" );
3612+ // done
3613+ return FALSE;
3614+ }
3615+
3616+ if( !isfunc( emit->env, member->self->type ) )
3617+ {
3618+ // should not get here
3619+ EM_error2( member->base->linepos,
3620+ "(emit): internal error in lit_special(): not member func" );
3621+ // done
3622+ return FALSE;
3623+ }
3624+
3625+ // get the func
3626+ value = type_engine_find_value( t_base, member->xid );
3627+ func = value->func_ref;
3628+ // make sure it's there
3629+ assert( func != NULL );
3630+
3631+ // NOTE: base already emitted earier in this function (and as var)
3632+
3633+ // check base; 1.3.5.3
3634+ if( member->base->s_meta == ae_meta_value ) // is literal
3635+ {
3636+ // dup the value as pointer (as faux-'this' pointer)
3637+ emit->append( new Chuck_Instr_Reg_Dup_Last_As_Pointer( t_base->size / sz_WORD ) );
3638+ }
3639+ else // normal object
3640+ {
3641+ // dup the base pointer (as 'this' argument -- special case primitive)
3642+ emit->append( new Chuck_Instr_Reg_Dup_Last );
3643+ }
3644+
3645+ // find the offset for virtual table
3646+ offset = func->vt_index;
3647+ // emit the function
3648+ emit->append( new Chuck_Instr_Dot_Primitive_Func( (t_CKUINT)func ) );
3649+
3650+ return TRUE;
3651+}
3652+
3653+
3654+
3655+
3656+//-----------------------------------------------------------------------------
3657+// name: emit_engine_emit_dot_member()
3658+// desc: ...
3659+//-----------------------------------------------------------------------------
3660+t_CKBOOL emit_engine_emit_exp_dot_member( Chuck_Emitter * emit,
3661+ a_Exp_Dot_Member member )
3662+{
3663+ // the type of the base
3664+ Chuck_Type * t_base = NULL;
3665+ // whether to emit addr or value
3666+ t_CKBOOL emit_addr = member->self->emit_var;
3667+ // is the base a class/namespace or a variable
3668+ t_CKBOOL base_static = isa( member->t_base, emit->env->t_class );
3669+ // a function
3670+ Chuck_Func * func = NULL;
3671+ // a non-function value
3672+ Chuck_Value * value = NULL;
3673+ // the offset
3674+ t_CKUINT offset = 0;
3675+
3676+ // the pointer
3677+ Chuck_Instr * instr = NULL;
3678+
3679+ // type of the base
3680+ t_CKUINT tbase_xid = member->t_base->xid;
3681+ // switch on it
3682+ switch( tbase_xid )
3683+ {
3684+ case te_complex:
3685+ case te_polar:
3686+ case te_vec3:
3687+ case te_vec4:
3688+ // emit special
3689+ return emit_engine_emit_exp_dot_member_special( emit, member );
3690+ // done
3691+ break;
3692+ }
3693+
3694+ // actual type - if base is class name its type is actually 'class'
3695+ // to get the actual type use actual_type
3696+ t_base = base_static ? member->t_base->actual_type : member->t_base;
3697+
3698+ // make sure that the base type is object
3699+ assert( t_base->info != NULL );
3700+
3701+ // if base is static
3702+ if( !base_static )
3703+ {
3704+ // if is a func
3705+ if( isfunc( emit->env, member->self->type ) )
3706+ {
3707+ // get the func
3708+ value = type_engine_find_value( t_base, member->xid );
3709+ func = value->func_ref;
3710+ // make sure it's there
3711+ assert( func != NULL );
3712+
3713+ // is the func static?
3714+ if( func->is_member )
3715+ {
3716+ // emit the base (TODO: return on error?)
3717+ emit_engine_emit_exp( emit, member->base );
3718+ // dup the base pointer (as 'this' argument)
3719+ emit->append( new Chuck_Instr_Reg_Dup_Last );
3720+ // find the offset for virtual table
3721+ offset = func->vt_index;
3722+ // emit the function
3723+ emit->append( instr = new Chuck_Instr_Dot_Member_Func( offset ) );
3724+ instr->set_linepos( member->linepos );
3725+ }
3726+ else
3727+ {
3728+ // emit the type
3729+ emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)t_base ) );
3730+ // emit the static function
3731+ emit->append( new Chuck_Instr_Dot_Static_Func( func ) );
3732+ }
3733+ }
3734+ else
3735+ {
3736+ // get the value
3737+ // value = t_base->info->lookup_value( member->xid, FALSE );
3738+ value = type_engine_find_value( t_base, member->xid );
3739+ // make sure it's there
3740+ assert( value != NULL );
3741+
3742+ // find the offset for data
3743+ offset = value->offset;
3744+
3745+ // is the value static?
3746+ if( value->is_member )
3747+ {
3748+ // emit the base (TODO: return on error?)
3749+ emit_engine_emit_exp( emit, member->base );
3750+ // lookup the member (1.3.1.0: changed to use getkindof instead of type size)
3751+ emit->append( instr = new Chuck_Instr_Dot_Member_Data(
3752+ offset, getkindof(emit->env, member->self->type), emit_addr ) );
3753+ instr->set_linepos( member->linepos );
3754+ }
3755+ else
3756+ {
3757+ // if builtin or not
3758+ if( value->addr )
3759+ {
3760+ // emit builtin (1.3.1.0: changed to use getkindof instead of type size)
3761+ emit->append( new Chuck_Instr_Dot_Static_Import_Data(
3762+ value->addr, getkindof(emit->env, member->self->type), emit_addr ) );
3763+ }
3764+ else
3765+ {
3766+ // emit the type
3767+ emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)t_base ) );
3768+ // emit the static value (1.3.1.0: changed to use getkindof in addition to size)
3769+ emit->append( new Chuck_Instr_Dot_Static_Data(
3770+ offset, member->self->type->size, getkindof(emit->env, member->self->type), emit_addr ) );
3771+ }
3772+ }
3773+ }
3774+ }
3775+ else // static
3776+ {
3777+ // emit the type
3778+ // commented out so built-in static member variables don't have an
3779+ // extra thing on the stack - spencer
3780+ //emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)t_base ) );
3781+
3782+ // if is a func
3783+ if( isfunc( emit->env, member->self->type ) )
3784+ {
3785+ // emit the type - spencer
3786+ emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)t_base ) );
3787+ // get the func
3788+ func = t_base->info->lookup_func( member->xid, FALSE );
3789+ // make sure it's there
3790+ assert( func != NULL );
3791+ // emit the function
3792+ emit->append( new Chuck_Instr_Dot_Static_Func( func ) );
3793+ }
3794+ else
3795+ {
3796+ // get the value
3797+ value = t_base->info->lookup_value( member->xid, FALSE );
3798+ // make sure it's there
3799+ assert( value != NULL );
3800+
3801+ // if builtin
3802+ if( value->addr )
3803+ {
3804+ // emit (1.3.1.0: changed to use getkindof instead of type size)
3805+ emit->append( new Chuck_Instr_Dot_Static_Import_Data(
3806+ value->addr, getkindof(emit->env, member->self->type), emit_addr ) );
3807+ }
3808+ else
3809+ {
3810+ // emit the type - spencer
3811+ emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)t_base ) );
3812+ // find the offset for data
3813+ offset = value->offset;
3814+ // emit the member (1.3.1.0: changed to use getkindof in addition to size)
3815+ emit->append( new Chuck_Instr_Dot_Static_Data(
3816+ offset, member->self->type->size, getkindof(emit->env, member->self->type), emit_addr ) );
3817+ }
3818+ }
3819+ }
3820+
3821+ return TRUE;
3822+}
3823+
3824+
3825+
3826+
3827+//-----------------------------------------------------------------------------
3828+// name: emit_engine_emit_exp_if()
3829+// desc: ...
3830+//-----------------------------------------------------------------------------
3831+t_CKBOOL emit_engine_emit_exp_if( Chuck_Emitter * emit, a_Exp_If exp_if )
3832+{
3833+ t_CKBOOL ret = TRUE;
3834+ Chuck_Instr_Branch_Op * op = NULL, * op2 = NULL;
3835+
3836+ // push the stack, allowing for new local variables
3837+ emit->push_scope();
3838+
3839+ // emit the condition
3840+ ret = emit_engine_emit_exp( emit, exp_if->cond );
3841+ if( !ret )
3842+ return FALSE;
3843+
3844+ // type of the condition
3845+ switch( exp_if->cond->type->xid )
3846+ {
3847+ case te_int:
3848+ // push 0
3849+ emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
3850+ op = new Chuck_Instr_Branch_Eq_int( 0 );
3851+ break;
3852+ case te_float:
3853+ case te_dur:
3854+ case te_time:
3855+ // push 0
3856+ emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) );
3857+ op = new Chuck_Instr_Branch_Eq_double( 0 );
3858+ break;
3859+
3860+ default:
3861+ EM_error2( exp_if->cond->linepos,
3862+ "(emit): internal error: unhandled type '%s' in if condition",
3863+ exp_if->cond->type->name.c_str() );
3864+ return FALSE;
3865+ }
3866+
3867+ if( !ret ) return FALSE;
3868+
3869+ // append the op
3870+ emit->append( op );
3871+
3872+ // emit the body
3873+ ret = emit_engine_emit_exp( emit, exp_if->if_exp );
3874+ if( !ret )
3875+ return FALSE;
3876+
3877+ // emit the skip to the end
3878+ emit->append( op2 = new Chuck_Instr_Goto(0) );
3879+
3880+ // set the op's target
3881+ op->set( emit->next_index() );
3882+
3883+ // emit the body
3884+ ret = emit_engine_emit_exp( emit, exp_if->else_exp );
3885+ if( !ret )
3886+ return FALSE;
3887+
3888+ // pop stack
3889+ emit->pop_scope();
3890+
3891+ // set the op2's target
3892+ op2->set( emit->next_index() );
3893+
3894+ return ret;
3895+}
3896+
3897+
3898+
3899+
3900+//-----------------------------------------------------------------------------
3901+// name: emit_engine_pre_constructor()
3902+// desc: ...
3903+//-----------------------------------------------------------------------------
3904+t_CKBOOL emit_engine_pre_constructor( Chuck_Emitter * emit, Chuck_Type * type )
3905+{
3906+ // parent first pre constructor
3907+ if( type->parent != NULL )
3908+ emit_engine_pre_constructor( emit, type->parent );
3909+
3910+ // pre constructor
3911+ if( type->has_constructor )
3912+ {
3913+ // make sure
3914+ assert( type->info->pre_ctor != NULL );
3915+ // append instruction
3916+ emit->append( new Chuck_Instr_Pre_Constructor( type->info->pre_ctor,
3917+ emit->code->frame->curr_offset ) );
3918+ }
3919+
3920+ return TRUE;
3921+}
3922+
3923+
3924+
3925+
3926+//-----------------------------------------------------------------------------
3927+// name: emit_engine_pre_constructor_array()
3928+// desc: ...
3929+//-----------------------------------------------------------------------------
3930+t_CKBOOL emit_engine_pre_constructor_array( Chuck_Emitter * emit, Chuck_Type * type )
3931+{
3932+ // alloc should have put all objects to made in linear list, on stack
3933+ Chuck_Instr_Pre_Ctor_Array_Top * top = NULL;
3934+ Chuck_Instr_Pre_Ctor_Array_Bottom * bottom = NULL;
3935+ // get start index
3936+ t_CKUINT start_index = emit->next_index();
3937+ // append first part of pre ctor
3938+ emit->append( top = new Chuck_Instr_Pre_Ctor_Array_Top( type ) );
3939+ // call pre constructor
3940+ emit_engine_pre_constructor( emit, type );
3941+ // append second part of the pre ctor
3942+ emit->append( bottom = new Chuck_Instr_Pre_Ctor_Array_Bottom );
3943+ // set the goto of the first one
3944+ top->set( emit->next_index() );
3945+ // set the goto for the second one
3946+ bottom->set( start_index );
3947+ // clean up code
3948+ emit->append( new Chuck_Instr_Pre_Ctor_Array_Post );
3949+
3950+ return TRUE;
3951+}
3952+
3953+
3954+
3955+//-----------------------------------------------------------------------------
3956+// name: emit_engine_instantiate_object()
3957+// desc: ...
3958+//-----------------------------------------------------------------------------
3959+t_CKBOOL emit_engine_instantiate_object( Chuck_Emitter * emit, Chuck_Type * type,
3960+ a_Array_Sub array, t_CKBOOL is_ref )
3961+{
3962+ // if array
3963+ if( type->array_depth )
3964+ {
3965+ // emit indices
3966+ emit_engine_emit_exp( emit, array->exp_list );
3967+ // emit array allocation
3968+ Chuck_Instr * instr = NULL;
3969+ emit->append( instr = new Chuck_Instr_Array_Alloc( emit->env,
3970+ type->array_depth, type->array_type, emit->code->frame->curr_offset,
3971+ is_ref ) );
3972+ instr->set_linepos( array->linepos );
3973+
3974+ // handle constructor
3975+ if( isobj( emit->env, type->array_type ) && !is_ref )
3976+ {
3977+ // call pre constructor for array
3978+ emit_engine_pre_constructor_array( emit, type->array_type );
3979+ }
3980+ }
3981+ else if( !is_ref ) // not array
3982+ {
3983+ // emit object instantiation code, include pre constructor
3984+ emit->append( new Chuck_Instr_Instantiate_Object( type ) );
3985+
3986+ // call pre constructor
3987+ emit_engine_pre_constructor( emit, type );
3988+ }
3989+
3990+ return TRUE;
3991+}
3992+
3993+
3994+
3995+
3996+//-----------------------------------------------------------------------------
3997+// name: emit_engine_emit_exp_decl()
3998+// desc: ...
3999+//-----------------------------------------------------------------------------
4000+t_CKBOOL emit_engine_emit_exp_decl( Chuck_Emitter * emit, a_Exp_Decl decl,
4001+ t_CKBOOL first_exp )
4002+{
4003+ a_Var_Decl_List list = decl->var_decl_list;
4004+ a_Var_Decl var_decl = NULL;
4005+ Chuck_Value * value = NULL;
4006+ Chuck_Type * type = NULL;
4007+ Chuck_Local * local = NULL;
4008+ t_CKBOOL is_obj = FALSE;
4009+ t_CKBOOL is_ref = FALSE;
4010+ t_CKBOOL is_init = FALSE;
4011+
4012+ // loop through vars
4013+ while( list )
4014+ {
4015+ // the var
4016+ var_decl = list->var_decl;
4017+ // get the value determined in type checker
4018+ value = var_decl->value;
4019+ // get the type of the value
4020+ type = value->type;
4021+ // is the variable a reference
4022+ is_obj = isobj( emit->env, type );
4023+ // do alloc or not
4024+ is_ref = decl->type->ref;
4025+ // not init
4026+ is_init = FALSE;
4027+
4028+ // if this is an object
4029+ if( is_obj )
4030+ {
4031+ // if array, then check to see if empty []
4032+ if( list->var_decl->array )
4033+ {
4034+ if( list->var_decl->array->exp_list )
4035+ {
4036+ // set
4037+ is_init = TRUE;
4038+ // instantiate object, including array
4039+ if( !emit_engine_instantiate_object( emit, type, list->var_decl->array, is_ref ) )
4040+ return FALSE;
4041+ }
4042+ }
4043+ else if( !is_ref )
4044+ {
4045+ // set
4046+ is_init = TRUE;
4047+ // instantiate object (not array)
4048+ if( !emit_engine_instantiate_object( emit, type, list->var_decl->array, is_ref ) )
4049+ return FALSE;
4050+ }
4051+ }
4052+
4053+ // if not init and first exp
4054+ /* if( !is_init && first_exp )
4055+ {
4056+ // push 0
4057+ if( type->size == sz_INT ) // ISSUE: 64-bit
4058+ emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) );
4059+ else if( type->size == sz_FLOAT ) // ISSUE: 64-bit
4060+ emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) );
4061+ else if( type->size == sz_COMPLEX ) // ISSUE: 64-bit
4062+ emit->append( new Chuck_Instr_Reg_Push_Imm4( 0.0, 0.0 ) );
4063+ else
4064+ {
4065+ EM_error2( decl->linepos,
4066+ "(emit): unhandle decl size of '%i'...",
4067+ type->size );
4068+ return FALSE;
4069+ }
4070+ }*/
4071+
4072+ // put in the value
4073+
4074+ // member
4075+ if( value->is_member )
4076+ {
4077+ // zero out location in object, and leave addr on operand stack
4078+ // added 1.3.1.0: iskindofint -- on some 64-bit systems, sz_int == sz_FLOAT
4079+ if( type->size == sz_INT && iskindofint(emit->env, type) ) // ISSUE: 64-bit (fixed 1.3.1.0)
4080+ emit->append( new Chuck_Instr_Alloc_Member_Word( value->offset ) );
4081+ else if( type->size == sz_FLOAT ) // ISSUE: 64-bit (fixed 1.3.1.0)
4082+ emit->append( new Chuck_Instr_Alloc_Member_Word2( value->offset ) );
4083+ else if( type->size == sz_COMPLEX ) // ISSUE: 64-bit (fixed 1.3.1.0)
4084+ emit->append( new Chuck_Instr_Alloc_Member_Word4( value->offset ) );
4085+ else if( type->size == sz_VEC3 ) // ge: added 1.3.5.3
4086+ emit->append( new Chuck_Instr_Alloc_Member_Vec3( value->offset ) );
4087+ else if( type->size == sz_VEC4 ) // ge: added 1.3.5.3
4088+ emit->append( new Chuck_Instr_Alloc_Member_Vec4( value->offset) );
4089+ else
4090+ {
4091+ EM_error2( decl->linepos,
4092+ "(emit): internal error: unhandled decl size of '%i'...",
4093+ type->size );
4094+ return FALSE;
4095+ }
4096+ }
4097+ else // not member
4098+ {
4099+ // not in class
4100+ if( !emit->env->class_def || !decl->is_static )
4101+ {
4102+ // allocate a place on the local stack
4103+ // (added 1.3.0.0 -- is_obj for tracking objects ref count on stack)
4104+ local = emit->alloc_local( type->size, value->name, is_ref, is_obj );
4105+ if( !local )
4106+ {
4107+ EM_error2( decl->linepos,
4108+ "(emit): internal error: cannot allocate local '%s'...",
4109+ value->name.c_str() );
4110+ return FALSE;
4111+ }
4112+
4113+ // put in the value
4114+ value->offset = local->offset;
4115+
4116+ // zero out location in memory, and leave addr on operand stack
4117+ // TODO: this is wrong for static
4118+ // BAD:
4119+ // FIX:
4120+ // added 1.3.1.0: iskindofint -- since on some 64-bit systems, sz_INT == sz_FLOAT
4121+ if( type->size == sz_INT && iskindofint(emit->env, type) ) // ISSUE: 64-bit (fixed 1.3.1.0)
4122+ {
4123+ // (added 1.3.0.0 -- is_obj)
4124+ Chuck_Instr_Alloc_Word * instr = new Chuck_Instr_Alloc_Word( local->offset, is_obj );
4125+ if( decl->is_external ) // REFACTOR-2017: added external keyword
4126+ {
4127+ instr->m_is_external = TRUE;
4128+ instr->m_name = value->name;
4129+ instr->m_type = type->xid;
4130+ }
4131+ instr->set_linepos( decl->linepos );
4132+ emit->append( instr );
4133+ }
4134+ else if( type->size == sz_FLOAT ) // ISSUE: 64-bit (fixed 1.3.1.0)
4135+ {
4136+ Chuck_Instr_Alloc_Word2 * instr = new Chuck_Instr_Alloc_Word2( local->offset );
4137+ if( decl->is_external ) // REFACTOR-2017: added external keyword
4138+ {
4139+ instr->m_is_external = TRUE;
4140+ instr->m_name = value->name;
4141+ instr->m_type = type->xid;
4142+ }
4143+ instr->set_linepos( decl->linepos );
4144+ emit->append( instr );
4145+ }
4146+ else if( type->size == sz_COMPLEX ) // ISSUE: 64-bit (fixed 1.3.1.0)
4147+ {
4148+ emit->append( new Chuck_Instr_Alloc_Word4( local->offset ) );
4149+ }
4150+ else if( type->size == sz_VEC3 ) // ge: added 1.3.5.3
4151+ {
4152+ emit->append( new Chuck_Instr_Alloc_Vec3(local->offset) );
4153+ }
4154+ else if( type->size == sz_VEC4 ) // ge: added 1.3.5.3
4155+ {
4156+ emit->append( new Chuck_Instr_Alloc_Vec4(local->offset) );
4157+ }
4158+ else
4159+ {
4160+ EM_error2( decl->linepos,
4161+ "(emit): internal error: unhandled decl size of '%i'...",
4162+ type->size );
4163+ return FALSE;
4164+ }
4165+ }
4166+ else // static
4167+ {
4168+ // emit the type
4169+ emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)emit->env->class_def ) );
4170+ // emit the static value (1.3.1.0: changed to use getkindof in addition to size)
4171+ emit->append( new Chuck_Instr_Dot_Static_Data(
4172+ value->offset, value->type->size, getkindof(emit->env, value->type), TRUE ) );
4173+ }
4174+ }
4175+
4176+ // set is_init
4177+ is_init = FALSE;
4178+
4179+ // if object, assign
4180+ if( is_obj )
4181+ {
4182+ // if array
4183+ if( var_decl->array )
4184+ {
4185+ // if not []
4186+ if( var_decl->array->exp_list )
4187+ {
4188+ // set
4189+ is_init = TRUE;
4190+ // assign
4191+ emit->append( new Chuck_Instr_Assign_Object );
4192+ }
4193+ }
4194+ else if( !is_ref )
4195+ {
4196+ // set
4197+ is_init = TRUE;
4198+ // assign the object
4199+ emit->append( new Chuck_Instr_Assign_Object );
4200+ }
4201+ }
4202+
4203+ // if not init and first exp
4204+ /* if( !is_init && first_exp )
4205+ {
4206+ // if obj
4207+ if( is_obj )
4208+ emit->append( new Chuck_Instr_Assign_Object );
4209+ // size 4 primitive
4210+ // added 1.3.1.0: iskindofint -- since on some 64-bit systems, sz_INT == sz_FLOAT
4211+ else if( type->size == sz_INT && iskindofint(type) ) // ISSUE: 64-bit (fixed 1.3.1.0)
4212+ emit->append( new Chuck_Instr_Assign_Primitive );
4213+ // size 8 primitive
4214+ else if( type->size == sz_FLOAT ) // ISSUE: 64-bit (fixed 1.3.1.0)
4215+ emit->append( new Chuck_Instr_Assign_Primitive2 );
4216+ // size 16 primitive
4217+ else if( type->size == sz_COMPLEX ) // ISSUE: 64-bit (fixed 1.3.1.0)
4218+ emit->append( new Chuck_Instr_Assign_Primitive4 );
4219+ else
4220+ assert( FALSE );
4221+ }*/
4222+
4223+ list = list->next;
4224+ }
4225+
4226+ return TRUE;
4227+}
4228+
4229+
4230+
4231+
4232+//-----------------------------------------------------------------------------
4233+// name: emit_engine_emit_code_segment()
4234+// desc: ...
4235+//-----------------------------------------------------------------------------
4236+t_CKBOOL emit_engine_emit_code_segment( Chuck_Emitter * emit,
4237+ a_Stmt_Code stmt, t_CKBOOL push )
4238+{
4239+ a_Stmt_List list = stmt->stmt_list;
4240+
4241+ // loop through
4242+ while( list )
4243+ {
4244+ // emit the statement
4245+ if( !emit_engine_emit_stmt( emit, list->stmt ) )
4246+ return FALSE;
4247+
4248+ // next
4249+ list = list->next;
4250+ }
4251+
4252+ // TODO: push
4253+
4254+ return TRUE;
4255+}
4256+
4257+
4258+
4259+
4260+//-----------------------------------------------------------------------------
4261+// name: emit_engine_emit_func_def()
4262+// desc: ...
4263+//-----------------------------------------------------------------------------
4264+t_CKBOOL emit_engine_emit_func_def( Chuck_Emitter * emit, a_Func_Def func_def )
4265+{
4266+ // get the func
4267+ Chuck_Func * func = func_def->ck_func;
4268+ // get the value
4269+ Chuck_Value * value = func->value_ref;
4270+ // get the type
4271+ Chuck_Type * type = value->type;
4272+ // local
4273+ Chuck_Local * local = NULL;
4274+
4275+ // make sure it's the same one
4276+ //Chuck_Func * func2 = emit->env->context->nspc.lookup_func( func_def->name, FALSE );
4277+ //if( func != func2 )
4278+ //{
4279+ // EM_error2( func_def->linepos,
4280+ // "(emit): ambiguous function resolution for %s...",
4281+ // S_name(func_def->name) );
4282+ // return FALSE;
4283+ //}
4284+
4285+ // make sure the code is empty
4286+ if( func->code != NULL )
4287+ {
4288+ EM_error2( func_def->linepos,
4289+ "(emit): function '%s' already emitted...",
4290+ S_name(func_def->name) );
4291+ return FALSE;
4292+ }
4293+
4294+ // make sure we are not in a function already
4295+ if( emit->env->func != NULL )
4296+ {
4297+ EM_error2( func_def->linepos,
4298+ "(emit): internal error: nested function definition..." );
4299+ return FALSE;
4300+ }
4301+
4302+ // if not part of a class
4303+ if( !emit->env->class_def )
4304+ {
4305+ // put function on stack
4306+ // ge: added FALSE to the 'is_obj' argument, 2012 april (added 1.3.0.0)
4307+ local = emit->alloc_local( value->type->size, value->name, TRUE, FALSE );
4308+ // remember the offset
4309+ value->offset = local->offset;
4310+ // write to mem stack
4311+ emit->append( new Chuck_Instr_Mem_Set_Imm( value->offset, (t_CKUINT)func ) );
4312+ }
4313+
4314+ // set the func
4315+ emit->env->func = func;
4316+ // push the current code
4317+ emit->stack.push_back( emit->code );
4318+ // make a new one
4319+ emit->code = new Chuck_Code;
4320+ // name the code
4321+ emit->code->name = emit->env->class_def ? emit->env->class_def->name + "." : "";
4322+ emit->code->name += func->name + "( ... )";
4323+ // set whether need this
4324+ emit->code->need_this = func->is_member;
4325+ // keep track of full path (added 1.3.0.0)
4326+ emit->code->filename = emit->context->full_path;
4327+
4328+ // go through the args
4329+ a_Arg_List a = func_def->arg_list;
4330+ t_CKBOOL is_obj = FALSE; // (added 1.3.0.0)
4331+ t_CKBOOL is_ref = FALSE;
4332+
4333+ // if member (non-static) function
4334+ if( func->is_member )
4335+ {
4336+ // get the size
4337+ emit->code->stack_depth += sizeof(t_CKUINT);
4338+ // add this
4339+ // ge: added FALSE to the 'is_obj' argument, 2012 april (added 1.3.0.0)
4340+ if( !emit->alloc_local( sizeof(t_CKUINT), "this", TRUE, FALSE ) )
4341+ {
4342+ EM_error2( a->linepos,
4343+ "(emit): internal error: cannot allocate local 'this'..." );
4344+ return FALSE;
4345+ }
4346+ }
4347+
4348+ // ge: 2012 april: added push scope (added 1.3.0.0)
4349+ emit->push_scope();
4350+
4351+ // loop through args
4352+ while( a )
4353+ {
4354+ // get the value
4355+ value = a->var_decl->value;
4356+ // get the type
4357+ type = value->type;
4358+ // is object? (added ge: 2012 april | added 1.3.0.0)
4359+ is_obj = isobj( emit->env, type );
4360+ // get ref
4361+ is_ref = a->type_decl->ref;
4362+ // get the size
4363+ emit->code->stack_depth += type->size;
4364+ // allocate a place on the local stack
4365+ // ge: added 'is_obj' 2012 april
4366+ local = emit->alloc_local( type->size, value->name, is_ref, is_obj );
4367+ if( !local )
4368+ {
4369+ EM_error2( a->linepos,
4370+ "(emit): internal error: cannot allocate local '%s'...",
4371+ value->name.c_str() );
4372+ return FALSE;
4373+ }
4374+ // remember the offset
4375+ value->offset = local->offset;
4376+
4377+ // advance
4378+ a = a->next;
4379+ }
4380+
4381+ // TODO: make sure the calculated stack depth is the same as func_def->stack depth
4382+ // taking into account member function
4383+
4384+ // add references for objects in the arguments (added 1.3.0.0)
4385+ // NOTE: this isn't in use since currently the caller is reference counting
4386+ // the arguments -- this is to better support sporking, which is more
4387+ // asynchronous. the code below is left in as reference for callee ref counting
4388+ // emit->addref_on_scope();
4389+
4390+ // emit the code
4391+ if( !emit_engine_emit_stmt( emit, func_def->code, FALSE ) )
4392+ return FALSE;
4393+
4394+ // added by spencer June 2014 (1.3.5.0)
4395+ // ensure return
4396+ if( func_def->ret_type && func_def->ret_type != emit->env->t_void )
4397+ {
4398+ emit->append( new Chuck_Instr_Reg_Push_Imm(0) );
4399+
4400+ Chuck_Instr_Goto * instr = new Chuck_Instr_Goto( 0 );
4401+ emit->append( instr );
4402+ emit->code->stack_return.push_back( instr );
4403+ }
4404+
4405+ // ge: pop scope (2012 april | added 1.3.0.0)
4406+ // TODO: ge 2012 april: pop scope? clean up function arguments? are argument properly ref counted?
4407+ emit->pop_scope();
4408+
4409+ // set the index for next instruction for return statements
4410+ for( t_CKUINT i = 0; i < emit->code->stack_return.size(); i++ )
4411+ emit->code->stack_return[i]->set( emit->next_index() );
4412+ // clear the return stack
4413+ emit->code->stack_return.clear();
4414+ // emit return statement
4415+ emit->append( new Chuck_Instr_Func_Return );
4416+
4417+ // vm code
4418+ func->code = emit_to_code( emit->code, NULL, emit->dump );
4419+ // add reference
4420+ func->code->add_ref();
4421+
4422+ // unset the func
4423+ emit->env->func = NULL;
4424+ // delete the code
4425+ SAFE_DELETE( emit->code );
4426+ // pop the code
4427+ assert( emit->stack.size() );
4428+ emit->code = emit->stack.back();
4429+ emit->stack.pop_back();
4430+
4431+ return TRUE;
4432+}
4433+
4434+
4435+
4436+
4437+//-----------------------------------------------------------------------------
4438+// name: emit_engine_emit_class_def()
4439+// desc: ...
4440+//-----------------------------------------------------------------------------
4441+t_CKBOOL emit_engine_emit_class_def( Chuck_Emitter * emit, a_Class_Def class_def )
4442+{
4443+ // get the type
4444+ Chuck_Type * type = class_def->type;
4445+ // the return type
4446+ t_CKBOOL ret = TRUE;
4447+ // the class body
4448+ a_Class_Body body = class_def->body;
4449+
4450+ // make sure the code is empty
4451+ if( type->info->pre_ctor != NULL && type->info->pre_ctor->instr != NULL )
4452+ {
4453+ EM_error2( class_def->linepos,
4454+ "(emit): class '%s' already emitted...",
4455+ type->name.c_str() );
4456+ return FALSE;
4457+ }
4458+
4459+ // make sure we are not in a class already
4460+ //if( emit->env->class_def != NULL )
4461+ //{
4462+ // EM_error2( class_def->linepos,
4463+ // "(emit): internal error: nested class definition..." );
4464+ // return FALSE;
4465+ //}
4466+
4467+ // set the class
4468+ emit->env->class_stack.push_back( emit->env->class_def );
4469+ emit->env->class_def = type;
4470+ // push the current code
4471+ emit->stack.push_back( emit->code );
4472+ // make a new one
4473+ emit->code = new Chuck_Code;
4474+ // name the code
4475+ emit->code->name = string("class ") + type->name;
4476+ // whether code needs this
4477+ emit->code->need_this = TRUE;
4478+ // if has constructor
4479+ // if( type->has_constructor ) type->info->pre_ctor = new Chuck_VM_Code;
4480+ // keep track of full path (added 1.3.0.0)
4481+ emit->code->filename = emit->context->full_path;
4482+
4483+ // get the size
4484+ emit->code->stack_depth += sizeof(t_CKUINT);
4485+ // add this
4486+ // ge: added TRUE to the 'is_obj' argument, 2012 april (added 1.3.0.0)
4487+ // TODO: verify this is right, and not over-ref counted / cleaned up?
4488+ if( !emit->alloc_local( sizeof(t_CKUINT), "this", TRUE, TRUE ) )
4489+ {
4490+ EM_error2( class_def->linepos,
4491+ "(emit): internal error: cannot allocate local 'this'..." );
4492+ return FALSE;
4493+ }
4494+
4495+ // emit the body
4496+ while( body && ret )
4497+ {
4498+ // check the section
4499+ switch( body->section->s_type )
4500+ {
4501+ case ae_section_stmt:
4502+ ret = emit_engine_emit_stmt_list( emit, body->section->stmt_list );
4503+ break;
4504+
4505+ case ae_section_func:
4506+ ret = emit_engine_emit_func_def( emit, body->section->func_def );
4507+ break;
4508+
4509+ case ae_section_class:
4510+ ret = emit_engine_emit_class_def( emit, body->section->class_def );
4511+ //EM_error2( body->section->class_def->linepos,
4512+ // "nested class definitions are not yet supported..." );
4513+ //ret = FALSE;
4514+ break;
4515+ }
4516+
4517+ // move to the next section
4518+ body = body->next;
4519+ }
4520+
4521+ // if ok
4522+ if( ret )
4523+ {
4524+ // emit return statement
4525+ emit->append( new Chuck_Instr_Func_Return );
4526+ // vm code
4527+ type->info->pre_ctor = emit_to_code( emit->code, type->info->pre_ctor, emit->dump );
4528+ // add reference
4529+ type->info->pre_ctor->add_ref();
4530+ // allocate static
4531+ type->info->class_data = new t_CKBYTE[type->info->class_data_size];
4532+ // verify
4533+ if( !type->info->class_data )
4534+ {
4535+ // we have a problem
4536+ CK_FPRINTF_STDERR(
4537+ "[chuck](emitter): OutOfMemory: while allocating static data '%s'\n", type->c_name() );
4538+ // flag
4539+ ret = FALSE;
4540+ }
4541+ else
4542+ {
4543+ // zero it out
4544+ memset( type->info->class_data, 0, type->info->class_data_size );
4545+ }
4546+ }
4547+
4548+ // check again
4549+ if( !ret )
4550+ {
4551+ // clean
4552+ SAFE_DELETE( type->info->pre_ctor );
4553+ }
4554+
4555+ // unset the class
4556+ emit->env->class_def = emit->env->class_stack.back();
4557+ emit->env->class_stack.pop_back();
4558+ // delete the code
4559+ SAFE_DELETE( emit->code );
4560+ // pop the code
4561+ assert( emit->stack.size() );
4562+ emit->code = emit->stack.back();
4563+ emit->stack.pop_back();
4564+
4565+ return ret;
4566+}
4567+
4568+
4569+
4570+
4571+//-----------------------------------------------------------------------------
4572+// name: emit_engine_emit_spork()
4573+// desc: ...
4574+//-----------------------------------------------------------------------------
4575+t_CKBOOL emit_engine_emit_spork( Chuck_Emitter * emit, a_Exp_Func_Call exp )
4576+{
4577+ // spork
4578+ Chuck_Instr_Mem_Push_Imm * op = NULL;
4579+
4580+ // if member function, push this
4581+ // TODO: this is a hack - what if exp is not func_call?
4582+ // if( exp->ck_func->is_member )
4583+ // emit->append( new Chuck_Instr_Reg_Push_This );
4584+
4585+ // evaluate args on sporker shred
4586+ if( !emit_engine_emit_func_args( emit, exp ) )
4587+ return FALSE;
4588+
4589+ // emit func pointer on sporker shred
4590+ if( !emit_engine_emit_exp( emit, exp->func ) )
4591+ {
4592+ EM_error2( exp->linepos,
4593+ "(emit): internal error in evaluating function call..." );
4594+ return FALSE;
4595+ }
4596+
4597+ // push the current code
4598+ emit->stack.push_back( emit->code );
4599+ // make a new one (spork~exp shred)
4600+ emit->code = new Chuck_Code;
4601+ // handle need this
4602+ emit->code->need_this = exp->ck_func->is_member;
4603+ // name it: e.g. spork~foo [line 5]
4604+ std::ostringstream name;
4605+ name << "spork~"
4606+ << exp->ck_func->name.substr( 0, exp->ck_func->name.find( "@" ))
4607+ << " [line " << exp->linepos << "]";
4608+ emit->code->name = name.str();
4609+ // keep track of full path (added 1.3.0.0)
4610+ emit->code->filename = emit->context->full_path;
4611+ // push op
4612+ op = new Chuck_Instr_Mem_Push_Imm( 0 );
4613+ // emit the stack depth - we don't know this yet
4614+ emit->append( op );
4615+
4616+ // call the func on sporkee shred
4617+ if( !emit_engine_emit_exp_func_call(
4618+ emit,
4619+ exp->ck_func,
4620+ exp->ret_type,
4621+ exp->linepos,
4622+ TRUE ) )
4623+ return FALSE;
4624+
4625+ // emit the function call, with special flag
4626+ // if( !emit_engine_emit_exp_func_call( emit, exp, TRUE ) )
4627+ // return FALSE;
4628+
4629+ // done
4630+ emit->append( new Chuck_Instr_EOC );
4631+ // set the stack depth now that we know
4632+ op->set( emit->code->stack_depth );
4633+
4634+ // emit it
4635+ Chuck_VM_Code * code = emit_to_code( emit->code, NULL, emit->dump );
4636+ // remember it
4637+ exp->ck_vm_code = code;
4638+ // add reference
4639+ exp->ck_vm_code->add_ref();
4640+ // code->name = string("spork~exp");
4641+
4642+ // restore the code to sporker shred
4643+ assert( emit->stack.size() > 0 );
4644+ emit->code = emit->stack.back();
4645+ // pop
4646+ emit->stack.pop_back();
4647+
4648+ a_Exp e = exp->args;
4649+ t_CKUINT size = 0;
4650+ while( e ) { size += e->cast_to ? e->cast_to->size : e->type->size; e = e->next; }
4651+
4652+ // handle member function
4653+ // TODO: this is a hack - what if exp is not func_call?
4654+ // if( emit->code->need_this )
4655+ // size += sz_INT; // (changed 1.3.1.0: 4 to sz_INT)
4656+
4657+ // emit instruction that will put the code on the stack
4658+ emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)code ) );
4659+ // emit spork instruction - this will copy, func, args, this
4660+ emit->append( new Chuck_Instr_Spork( size ) );
4661+
4662+ return TRUE;
4663+}
4664+
4665+
4666+
4667+
4668+//-----------------------------------------------------------------------------
4669+// name: emit_engine_emit_spork()
4670+// desc: ...
4671+//-----------------------------------------------------------------------------
4672+//t_CKBOOL emit_engine_emit_spork( Chuck_Emitter * emit, a_Stmt stmt )
4673+//{
4674+// // push the current code
4675+// emit->stack.push_back( emit->code );
4676+// // make a new one (spork~exp shred)
4677+// emit->code = new Chuck_Code;
4678+// // handle need this
4679+// emit->code->need_this = emit->env->class_def ? TRUE : FALSE;
4680+// // name it
4681+// emit->code->name = "spork~exp";
4682+// // keep track of full path (added 1.3.0.0)
4683+// emit->code->filename = emit->context->full_path;
4684+//
4685+// // call the code on sporkee shred
4686+// if( !emit_engine_emit_stmt( emit, stmt, TRUE ) )
4687+// return FALSE;
4688+//
4689+// // done
4690+// emit->append( new Chuck_Instr_EOC );
4691+//
4692+// // emit it
4693+// Chuck_VM_Code * code = emit_to_code( emit->code, NULL, emit->dump );
4694+//
4695+// // restore the code to sporker shred
4696+// assert( emit->stack.size() > 0 );
4697+// emit->code = emit->stack.back();
4698+// // pop
4699+// emit->stack.pop_back();
4700+//
4701+// if( code->need_this )
4702+// {
4703+// // push this if needed
4704+// emit->append( new Chuck_Instr_Reg_Push_This );
4705+// }
4706+// // emit instruction that will put the code on the stack
4707+// emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)code ) );
4708+// // emit spork instruction - this will copy, func, args, this
4709+// emit->append( new Chuck_Instr_Spork_Stmt( 0 ) );
4710+//
4711+// return TRUE;
4712+//}
4713+
4714+
4715+
4716+
4717+//-----------------------------------------------------------------------------
4718+// name: emit_engine_emit_symbol()
4719+// desc: ...
4720+//-----------------------------------------------------------------------------
4721+t_CKBOOL emit_engine_emit_symbol( Chuck_Emitter * emit, S_Symbol symbol,
4722+ Chuck_Value * v, t_CKBOOL emit_var,
4723+ int linepos )
4724+{
4725+ // look up the value
4726+ // Chuck_Value * v = emit->env->curr->lookup_value( symbol, TRUE );
4727+ // it should be there
4728+ if( !v )
4729+ {
4730+ // internal error
4731+ EM_error2( linepos,
4732+ "(emit): internal error: undefined symbol '%s'...",
4733+ S_name(symbol) );
4734+ return FALSE;
4735+ }
4736+
4737+ // if part of class - this only works because x.y is handled separately
4738+ if( v->owner_class && (v->is_member || v->is_static) )
4739+ {
4740+ // make sure talking about the same class
4741+ // this doesn't work since the owner class could be a super class
4742+ // assert( v->owner_class == emit->env->class_def );
4743+ //
4744+ // try this (thanks Robin Davies)
4745+ assert( isa( emit->env->class_def, v->owner_class ) /* || is_global( v->owner_class ) */ );
4746+
4747+ // emit as this.v
4748+ // BUG: passing "this" below might be bad if the exp is freed and string with it
4749+ a_Exp base = new_exp_from_id( (char *)"this", linepos );
4750+ a_Exp dot = new_exp_from_member_dot( base, (char *)v->name.c_str(), linepos );
4751+ base->type = v->owner_class;
4752+ dot->type = v->type;
4753+ dot->dot_member.t_base = v->owner_class;
4754+ dot->emit_var = emit_var;
4755+ // emit it
4756+ if( !emit_engine_emit_exp_dot_member( emit, &dot->dot_member ) )
4757+ {
4758+ // internal error
4759+ EM_error2( linepos,
4760+ "(emit): internal error: symbol transformation failed..." );
4761+ return FALSE;
4762+ }
4763+
4764+ return TRUE;
4765+ }
4766+
4767+ // var or value
4768+ if( emit_var )
4769+ {
4770+ // emit as addr
4771+ emit->append( new Chuck_Instr_Reg_Push_Mem_Addr( v->offset, v->is_context_global ) );
4772+ }
4773+ else
4774+ {
4775+ // special case
4776+ if( v->func_ref )
4777+ emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)v->func_ref ) );
4778+ // check size
4779+ // (added 1.3.1.0: iskindofint -- since in some 64-bit systems, sz_INT == sz_FLOAT)
4780+ else if( v->type->size == sz_INT && iskindofint(emit->env, v->type) ) // ISSUE: 64-bit (fixed 1.3.1.0)
4781+ emit->append( new Chuck_Instr_Reg_Push_Mem( v->offset, v->is_context_global ) );
4782+ else if( v->type->size == sz_FLOAT ) // ISSUE: 64-bit (fixed 1.3.1.0)
4783+ emit->append( new Chuck_Instr_Reg_Push_Mem2( v->offset, v->is_context_global ) );
4784+ else if( v->type->size == sz_COMPLEX ) // ISSUE: 64-bit (fixed 1.3.1.0)
4785+ emit->append( new Chuck_Instr_Reg_Push_Mem4( v->offset, v->is_context_global ) );
4786+ else if( v->type->size == sz_VEC3 ) // ge: added 1.3.5.3
4787+ emit->append( new Chuck_Instr_Reg_Push_Mem_Vec3( v->offset, v->is_context_global ) );
4788+ else if( v->type->size == sz_VEC4 ) // ge: added 1.3.5.3
4789+ emit->append( new Chuck_Instr_Reg_Push_Mem_Vec4( v->offset, v->is_context_global ) );
4790+ else
4791+ {
4792+ // internal error
4793+ EM_error2( linepos,
4794+ "(emit): internal error: symbol '%s' has size '%i'...",
4795+ S_name(symbol), v->type->size );
4796+ return FALSE;
4797+ }
4798+ }
4799+
4800+ return TRUE;
4801+}
4802+
4803+
4804+
4805+
4806+//-----------------------------------------------------------------------------
4807+// name: addref_on_scope()
4808+// desc: add references to locals on current scope (added 1.3.0.0)
4809+//-----------------------------------------------------------------------------
4810+void Chuck_Emitter::addref_on_scope()
4811+{
4812+ // sanity
4813+ assert( code != NULL );
4814+ // clear locals
4815+ locals.clear();
4816+ // get the current scope
4817+ code->frame->get_scope( locals );
4818+
4819+ // iterate over locals
4820+ for( int i = 0; i < locals.size(); i++ )
4821+ {
4822+ // get it
4823+ Chuck_Local * local = locals[i];
4824+ // check to see if it's an object
4825+ if( local->is_obj )
4826+ {
4827+ // emit instruction to add reference
4828+ this->append( new Chuck_Instr_AddRef_Object2( local->offset ) );
4829+ }
4830+ }
4831+}
4832+
4833+
4834+
4835+
4836+//-----------------------------------------------------------------------------
4837+// name: pop_scope()
4838+// desc: ...
4839+//-----------------------------------------------------------------------------
4840+void Chuck_Emitter::pop_scope( )
4841+{
4842+ // sanity
4843+ assert( code != NULL );
4844+ // clear locals
4845+ locals.clear();
4846+ // get locals
4847+ code->frame->pop_scope( locals );
4848+
4849+ // ge (2012 april): attempt to free locals (added 1.3.0.0)
4850+ // was -- TODO: free locals -- chievo!
4851+ for( int i = 0; i < locals.size(); i++ )
4852+ {
4853+ // get local
4854+ Chuck_Local * local = locals[i];
4855+ // CK_STDCERR << "local: " << local->offset << " " << local->is_obj << CK_STDENDL;
4856+ // check to see if it's an object
4857+ if( local->is_obj )
4858+ {
4859+ // emit instruction to release the object
4860+ this->append( new Chuck_Instr_Release_Object2( local->offset ) );
4861+ }
4862+
4863+ // reclaim local; null out to be safe
4864+ SAFE_DELETE( local ); locals[i] = NULL;
4865+ }
4866+
4867+ // clear it
4868+ locals.clear();
4869+}
4870+
4871+
4872+
4873+
4874+//-----------------------------------------------------------------------------
4875+// name: find_dur()
4876+// desc: ...
4877+//-----------------------------------------------------------------------------
4878+t_CKBOOL Chuck_Emitter::find_dur( const string & name, t_CKDUR * out )
4879+{
4880+ // sanity
4881+ assert( env != NULL );
4882+ assert( out != NULL );
4883+
4884+ // zero
4885+ *out = 0.0;
4886+ // get value from env
4887+ Chuck_Value * value = env->global()->lookup_value( name, FALSE );
4888+ if( !value || !equals( value->type, env->t_dur ) ) return FALSE;
4889+ // copy
4890+ *out = *( (t_CKDUR *)value->addr );
4891+
4892+ return TRUE;
4893+}
4894+
4895+
4896+
4897+
4898+/*
4899+//-----------------------------------------------------------------------------
4900+// name: emit_engine_instantiate_object()
4901+// desc: ...
4902+//-----------------------------------------------------------------------------
4903+t_CKBOOL emit_engine_instantiate_object( Chuck_Emitter * emit, Chuck_Type * type,
4904+ a_Array_Sub array, t_CKBOOL is_ref )
4905+{
4906+ // if array
4907+ if( type->array_depth )
4908+ {
4909+ // emit indices
4910+ emit_engine_emit_exp( emit, array->exp_list );
4911+ // emit array allocation
4912+ emit->append( new Chuck_Instr_Array_Alloc(
4913+ type->array_depth, type->array_type, emit->code->frame->curr_offset,
4914+ is_ref ) );
4915+
4916+ // handle constructor
4917+ //if( isobj( emit->env, type->array_type ) && !is_ref )
4918+ //{
4919+ // // TODO:
4920+ // EM_error2( array->linepos, "internal error: object array constructor not impl..." );
4921+ // return FALSE;
4922+ //}
4923+ }
4924+ else if( !is_ref ) // not array
4925+ {
4926+ // if ugen
4927+ //if( isa( type, emit->env->t_ugen ) )
4928+ //{
4929+ // // get the ugen info
4930+ // Chuck_UGen_Info * info = decl->self->type->ugen;
4931+ // if( !info )
4932+ // {
4933+ // EM_error2( decl->linepos,
4934+ // "(emit): internal error: undefined ugen type '%s'",
4935+ // type->name.c_str() );
4936+ // return FALSE;
4937+ // }
4938+ // emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)info ) );
4939+ // emit->append( new Chuck_Instr_UGen_Alloc() );
4940+ //}
4941+ //else
4942+ //{
4943+
4944+ // emit object instantiation code, include pre constructor
4945+ emit->append( new Chuck_Instr_Instantiate_Object( type ) );
4946+
4947+ //}
4948+
4949+ // call pre constructor
4950+ emit_engine_pre_constructor( emit, type );
4951+
4952+ // constructor
4953+ //if( type->has_constructor )
4954+ //{
4955+ // // make sure
4956+ // assert( type->info->pre_ctor != NULL );
4957+ // // push this
4958+ // emit->append( new Chuck_Instr_Reg_Dup_Last );
4959+ // // push pre-constructor
4960+ // emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)type->info->pre_ctor ) );
4961+ // // push frame offset
4962+ // emit->append( new Chuck_Instr_Reg_Push_Imm( emit->code->frame->curr_offset ) );
4963+ // // call the function
4964+ // if( type->info->pre_ctor->native_func != NULL )
4965+ // emit->append( new Chuck_Instr_Func_Call_Member( 0 ) );
4966+ // else
4967+ // emit->append( new Chuck_Instr_Func_Call );
4968+ //}
4969+ }
4970+
4971+ return TRUE;
4972+}*/
core/chuck_emit.h+176−0
@@ -0,0 +1,176 @@
1+/*----------------------------------------------------------------------------
2+ ChucK Concurrent, On-the-fly Audio Programming Language
3+ Compiler and Virtual Machine
4+
5+ Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6+ http://chuck.stanford.edu/
7+ http://chuck.cs.princeton.edu/
8+
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.
13+
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.
18+
19+ You should have received a copy of the GNU General Public License
20+ along with this program; if not, write to the Free Software
21+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22+ U.S.A.
23+-----------------------------------------------------------------------------*/
24+
25+//-----------------------------------------------------------------------------
26+// file: chuck_emit.h
27+// desc: chuck instruction emitter
28+//
29+// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
30+// date: Autumn 2002 - first version
31+// Autumn 2004 - redesign
32+//-----------------------------------------------------------------------------
33+#ifndef __CHUCK_EMIT_H__
34+#define __CHUCK_EMIT_H__
35+
36+#include "chuck_def.h"
37+#include "chuck_oo.h"
38+#include "chuck_type.h"
39+#include "chuck_frame.h"
40+
41+
42+// forward references
43+struct Chuck_Instr;
44+struct Chuck_Instr_Goto;
45+struct Chuck_VM_Code;
46+struct Chuck_VM_Shred;
47+
48+
49+
50+
51+//-----------------------------------------------------------------------------
52+// name: struct Chuck_Code
53+// desc: ...
54+//-----------------------------------------------------------------------------
55+struct Chuck_Code
56+{
57+public:
58+ // name
59+ std::string name;
60+ // stack depth
61+ t_CKUINT stack_depth;
62+ // need this
63+ t_CKBOOL need_this;
64+ // frame
65+ Chuck_Frame * frame;
66+ // code
67+ std::vector<Chuck_Instr *> code;
68+
69+ // continue stack
70+ std::vector<Chuck_Instr_Goto *> stack_cont;
71+ // break stack
72+ std::vector<Chuck_Instr_Goto *> stack_break;
73+ // return stack
74+ std::vector<Chuck_Instr_Goto *> stack_return;
75+
76+ // filename this code came from (added 1.3.0.0)
77+ std::string filename;
78+
79+ // constructor
80+ Chuck_Code( )
81+ {
82+ stack_depth = 0;
83+ need_this = FALSE;
84+ frame = new Chuck_Frame;
85+ }
86+
87+ // destructor
88+ ~Chuck_Code() { delete frame; frame = NULL; }
89+};
90+
91+
92+
93+
94+//-----------------------------------------------------------------------------
95+// name: struct Chuck_Emitter
96+// desc: ...
97+//-----------------------------------------------------------------------------
98+struct Chuck_Emitter : public Chuck_VM_Object
99+{
100+ // reference to the type checker environment
101+ Chuck_Env * env;
102+ // reference to VM
103+ Chuck_VM * vm;
104+
105+ // current code
106+ Chuck_Code * code;
107+ // current context
108+ Chuck_Context * context;
109+ // expression namespace
110+ Chuck_Namespace * nspc;
111+ // current function definition
112+ Chuck_Func * func;
113+
114+ // code stack
115+ std::vector<Chuck_Code *> stack;
116+ // locals
117+ std::vector<Chuck_Local *> locals;
118+
119+ // dump
120+ t_CKBOOL dump;
121+
122+ // constructor
123+ Chuck_Emitter()
124+ { env = NULL; vm = NULL; code = NULL; context = NULL;
125+ nspc = NULL; func = NULL; dump = FALSE; }
126+
127+ // destructor
128+ ~Chuck_Emitter()
129+ { }
130+
131+ // append instruction
132+ void append( Chuck_Instr * instr )
133+ { assert( code != NULL ); code->code.push_back( instr ); }
134+ // index
135+ t_CKUINT next_index()
136+ { assert( code != NULL ); return code->code.size(); }
137+
138+ // push scope
139+ void push_scope( )
140+ { assert( code != NULL ); code->frame->push_scope(); }
141+ // alloc local (ge: added is_obj 2012 april | added 1.3.0.0)
142+ Chuck_Local * alloc_local( t_CKUINT size, const std::string & name, t_CKBOOL is_ref, t_CKBOOL is_obj )
143+ { assert( code != NULL ); return code->frame->alloc_local( size, name, is_ref, is_obj ); }
144+ // add references to locals on current scope (added 1.3.0.0)
145+ void addref_on_scope();
146+ // pop scope
147+ void pop_scope( );
148+
149+ // default durations
150+ t_CKBOOL find_dur( const std::string & name, t_CKDUR * out );
151+};
152+
153+
154+
155+
156+// allocate the emitter
157+Chuck_Emitter * emit_engine_init( Chuck_Env * env );
158+// shutdown and free the emitter
159+t_CKBOOL emit_engine_shutdown( Chuck_Emitter *& emit );
160+// emit a program into vm code
161+Chuck_VM_Code * emit_engine_emit_prog( Chuck_Emitter * emit,
162+ a_Program prog,
163+ te_HowMuch how_much = te_do_all );
164+// helper function to emit code
165+Chuck_VM_Code * emit_to_code( Chuck_Code * in,
166+ Chuck_VM_Code * out = NULL,
167+ t_CKBOOL dump = FALSE );
168+
169+// NOT USED: ...
170+t_CKBOOL emit_engine_addr_map( Chuck_Emitter * emit, Chuck_VM_Shred * shred );
171+t_CKBOOL emit_engine_resolve( );
172+
173+
174+
175+
176+#endif
core/chuck_errmsg.cpp+650−0
@@ -0,0 +1,650 @@
1+/*----------------------------------------------------------------------------
2+ ChucK Concurrent, On-the-fly Audio Programming Language
3+ Compiler and Virtual Machine
4+
5+ Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6+ http://chuck.stanford.edu/
7+ http://chuck.cs.princeton.edu/
8+
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.
13+
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.
18+
19+ You should have received a copy of the GNU General Public License
20+ along with this program; if not, write to the Free Software
21+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22+ U.S.A.
23+-----------------------------------------------------------------------------*/
24+
25+//-----------------------------------------------------------------------------
26+// file: errmsg.cpp
27+// desc: functions used in all phases of the compiler to give error messages
28+// based on Andrew Appel's Tiger code
29+//
30+// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
31+// based on code by: Andrew Appel (appel@cs.princeton.edu)
32+// date: Summer 2002
33+//-----------------------------------------------------------------------------
34+#include <stdlib.h>
35+#include <stdarg.h>
36+#include <string.h>
37+#include <sstream>
38+#include <iostream>
39+#include "chuck_utils.h"
40+#include "chuck_errmsg.h"
41+#include "util_thread.h"
42+
43+
44+// global
45+int EM_tokPos = 0;
46+int EM_lineNum = 1;
47+int EM_extLineNum = 1;
48+t_CKBOOL anyErrors= FALSE;
49+
50+// local global
51+static const char * fileName = "";
52+static int lineNum = 1;
53+static char g_buffer[1024] = "";
54+static const size_t LASTERROR_SIZE = 1024;
55+static char g_lasterror[LASTERROR_SIZE] = "[chuck]: (no error)";
56+static size_t g_lasterrorIndex = strlen(g_lasterror);
57+// log globals
58+int g_loglevel = CK_LOG_CORE;
59+int g_logstack = 0;
60+XMutex g_logmutex;
61+
62+// more local globals
63+static const size_t g_buffer2_size = 1024;
64+static char g_buffer2[g_buffer2_size] = "";
65+std::stringstream g_stdout_stream;
66+std::stringstream g_stderr_stream;
67+
68+// local global callbacks
69+void (*g_stdout_callback)(const char *) = NULL;
70+void (*g_stderr_callback)(const char *) = NULL;
71+
72+void ck_fprintf_stdout( const char * format, ... )
73+{
74+ // evaluate the format string
75+ va_list args;
76+ va_start( args, format );
77+ vsnprintf( g_buffer2, g_buffer2_size, format, args );
78+ va_end( args );
79+
80+ // send the formatted string to the buffer
81+ g_stdout_stream << g_buffer2;
82+
83+ // try flushing
84+ ck_fflush_stdout();
85+}
86+
87+
88+void ck_fprintf_stderr( const char * format, ... )
89+{
90+ // evaluate the format string
91+ va_list args;
92+ va_start( args, format );
93+ vsnprintf( g_buffer2, g_buffer2_size, format, args );
94+ va_end( args );
95+
96+ // send the formatted string to the buffer
97+ g_stderr_stream << g_buffer2;
98+
99+ // try flushing
100+ ck_fflush_stderr();
101+}
102+
103+
104+void ck_fflush_stdout()
105+{
106+ // check if stream contains a newline
107+ if( g_stdout_stream.str().find( '\n' ) != std::string::npos )
108+ {
109+ // if so, print it
110+ if( g_stdout_callback == NULL ) {
111+ // send to stdout
112+ fprintf( stdout, "%s", g_stdout_stream.str().c_str() );
113+ }
114+ else
115+ {
116+ // emit to callback
117+ g_stdout_callback( g_stdout_stream.str().c_str() );
118+ }
119+ // and clear buffer
120+ g_stdout_stream.str( std::string() );
121+
122+ }
123+}
124+
125+
126+void ck_fflush_stderr()
127+{
128+ // check if stream contains a newline
129+ if( g_stderr_stream.str().find( '\n' ) != std::string::npos )
130+ {
131+ // if so, print it
132+ if( g_stderr_callback == NULL )
133+ {
134+ // send to stderr
135+ fprintf( stderr, "%s", g_stderr_stream.str().c_str() );
136+ }
137+ else
138+ {
139+ // emit to callback
140+ g_stderr_callback( g_stderr_stream.str().c_str() );
141+ }
142+
143+ // and clear buffer
144+ g_stderr_stream.str( std::string() );
145+ }
146+}
147+
148+
149+void ck_vfprintf_stdout( const char * format, va_list args )
150+{
151+ // evaluate the format string
152+ vsnprintf( g_buffer2, g_buffer2_size, format, args );
153+
154+ // send the formatted string to the buffer
155+ g_stdout_stream << g_buffer2;
156+
157+ // try flushing
158+ ck_fflush_stdout();
159+}
160+
161+
162+void ck_vfprintf_stderr( const char * format, va_list args )
163+{
164+ // evaluate the format string
165+ vsnprintf( g_buffer2, g_buffer2_size, format, args );
166+
167+ // send the formatted string to the buffer
168+ g_stderr_stream << g_buffer2;
169+
170+ // try flushing
171+ ck_fflush_stderr();
172+}
173+
174+
175+
176+void ck_set_stdout_callback( void (*callback)(const char *) )
177+{
178+ g_stdout_callback = callback;
179+#ifdef __cplusplus
180+ g_ck_stdoutstream.set_callback( callback );
181+#endif
182+}
183+
184+
185+void ck_set_stderr_callback( void (*callback)(const char *) )
186+{
187+ g_stderr_callback = callback;
188+#ifdef __cplusplus
189+ g_ck_stderrstream.set_callback( callback );
190+#endif
191+}
192+
193+#ifdef __cplusplus
194+extern "C++" {
195+
196+ChuckOutStream::ChuckOutStream( bool isErr )
197+{
198+ m_callback = NULL;
199+ m_isErr = isErr;
200+}
201+
202+
203+ChuckOutStream::~ChuckOutStream()
204+{
205+}
206+
207+
208+ChuckOutStream& ChuckOutStream::operator<<( const std::string val )
209+{
210+ m_stream << val;
211+ if( val == CK_STDENDL )
212+ {
213+ this->flush();
214+ }
215+ return *this;
216+}
217+
218+
219+ChuckOutStream& ChuckOutStream::operator<<( const char * val )
220+{
221+ m_stream << val;
222+ return *this;
223+}
224+
225+
226+ChuckOutStream& ChuckOutStream::operator<<( const double val )
227+{
228+ m_stream << val;
229+ return *this;
230+}
231+
232+
233+ChuckOutStream& ChuckOutStream::operator<<( const float val )
234+{
235+ m_stream << val;
236+ return *this;
237+}
238+
239+
240+ChuckOutStream& ChuckOutStream::operator<<( const unsigned long long val )
241+{
242+ m_stream << val;
243+ return *this;
244+}
245+
246+
247+ChuckOutStream& ChuckOutStream::operator<<( const long long val )
248+{
249+ m_stream << val;
250+ return *this;
251+}
252+
253+
254+ChuckOutStream& ChuckOutStream::operator<<( const unsigned long val )
255+{
256+ m_stream << val;
257+ return *this;
258+}
259+
260+
261+ChuckOutStream& ChuckOutStream::operator<<( const long val )
262+{
263+ m_stream << val;
264+ return *this;
265+}
266+
267+
268+ChuckOutStream& ChuckOutStream::operator<<( const unsigned int val )
269+{
270+ m_stream << val;
271+ return *this;
272+}
273+
274+
275+ChuckOutStream& ChuckOutStream::operator<<( const int val )
276+{
277+ m_stream << val;
278+ return *this;
279+}
280+
281+
282+ChuckOutStream& ChuckOutStream::operator<<( const bool val )
283+{
284+ m_stream << val;
285+ return *this;
286+}
287+
288+
289+
290+
291+
292+void ChuckOutStream::set_callback( void (*callback)( const char * ) )
293+{
294+ m_callback = callback;
295+}
296+
297+
298+void ChuckOutStream::flush()
299+{
300+ if( m_callback != NULL )
301+ {
302+ // send to callback
303+ m_callback( m_stream.str().c_str() );
304+ }
305+ else
306+ {
307+ // print it
308+ if( m_isErr )
309+ {
310+ // to cerr
311+ std::cerr << m_stream.str().c_str();
312+ std::cerr.flush();
313+ }
314+ else
315+ {
316+ // to cout
317+ std::cout << m_stream.str().c_str();
318+ std::cout.flush();
319+ }
320+ }
321+ // clear buffer
322+ m_stream.str( std::string() );
323+}
324+
325+
326+ChuckOutStream g_ck_stdoutstream( FALSE );
327+ChuckOutStream g_ck_stderrstream( TRUE );
328+
329+}
330+#endif
331+
332+
333+
334+
335+// name
336+static const char * g_str[] = {
337+ "NONE", // 0
338+ "CKCORE", // 1
339+ "SYSTEM", // 2
340+ "SEVERE", // 3
341+ "WARN!!", // 4
342+ "INFORM", // 5
343+ "CONFIG", // 6
344+ "FINE!!", // 7
345+ "FINER!", // 8
346+ "FINEST", // 9
347+ "ALL!!" // 10
348+};
349+
350+
351+// intList
352+typedef struct intList {int i; struct intList *rest;} *IntList;
353+static IntList linePos=NULL;
354+
355+
356+static int lastErrorCat(const char * str)
357+{
358+ assert(g_lasterrorIndex <= LASTERROR_SIZE-1);
359+
360+ size_t len = strlen(str);
361+
362+ strncat(g_lasterror, str, LASTERROR_SIZE-g_lasterrorIndex-1);
363+
364+ size_t appendCount = ck_min(LASTERROR_SIZE-g_lasterrorIndex-1, len);
365+ g_lasterrorIndex += appendCount;
366+
367+ return appendCount > 0;
368+}
369+
370+
371+// constructor
372+static IntList intList( int i, IntList rest )
373+{
374+ IntList l = (IntList)checked_malloc(sizeof *l);
375+ l->i=i; l->rest=rest;
376+ return l;
377+}
378+
379+
380+// new line in lexer
381+void EM_newline(void)
382+{
383+ lineNum++;
384+ EM_lineNum++;
385+ EM_extLineNum++;
386+ linePos = intList(EM_tokPos, linePos);
387+}
388+
389+
390+// content after rightmost '/'
391+const char * mini( const char * str )
392+{
393+ int len = strlen( str );
394+ const char * p = str + len;
395+ while( p != str && *p != '/' && *p != '\\' ) p--;
396+ return ( p == str || strlen(p+1) == 0 ? p : p+1 );
397+}
398+
399+
400+// content after 'struct'
401+const char * mini_type( const char * str )
402+{
403+ if( !strncmp( str, "struct ", 7 ) ) str += 7;
404+ const char * p = str;
405+ while( *p && *p >= '0' && *p <= '9' ) p++;
406+ return p;
407+}
408+
409+void EM_reset_msg()
410+{
411+ g_lasterror[0] = '\0';
412+ g_lasterrorIndex = 0;
413+}
414+
415+// [%s]:line(%d).char(%d):
416+void EM_error( int pos, const char * message, ... )
417+{
418+ va_list ap;
419+ IntList lines = linePos;
420+ int num = lineNum;
421+
422+ anyErrors = TRUE;
423+ while( lines && lines->i >= pos )
424+ {
425+ lines = lines->rest;
426+ num--;
427+ }
428+
429+ // separate errmsgs with newlines
430+ if( g_lasterror[0] != '\0' ) lastErrorCat( "\n" );
431+
432+ CK_FPRINTF_STDERR( "[%s]:", *fileName ? mini(fileName) : "chuck" );
433+ sprintf( g_buffer, "[%s]:", *fileName ? mini(fileName) : "chuck" );
434+ lastErrorCat( g_buffer );
435+ if(lines)
436+ {
437+ CK_FPRINTF_STDERR( "line(%d).char(%d):", num, pos-lines->i );
438+ sprintf( g_buffer, "line(%d).char(%d):", num, pos-lines->i );
439+ lastErrorCat( g_buffer );
440+ }
441+ CK_FPRINTF_STDERR( " " );
442+ lastErrorCat( " " );
443+
444+ va_start(ap, message);
445+ CK_VFPRINTF_STDERR( message, ap);
446+ va_end(ap);
447+
448+ va_start(ap, message);
449+ vsprintf( g_buffer, message, ap );
450+ va_end(ap);
451+
452+ CK_FPRINTF_STDERR( "\n");
453+ CK_FFLUSH_STDERR();
454+ lastErrorCat( g_buffer );
455+}
456+
457+
458+// [%s]:line(%d):
459+void EM_error2( int line, const char * message, ... )
460+{
461+ va_list ap;
462+
463+ EM_extLineNum = line;
464+
465+ // separate errmsgs with newlines
466+ if( g_lasterror[0] != '\0' ) lastErrorCat( "\n" );
467+
468+ CK_FPRINTF_STDERR( "[%s]:", *fileName ? mini(fileName) : "chuck" );
469+ sprintf( g_buffer, "[%s]:", *fileName ? mini(fileName) : "chuck" );
470+ lastErrorCat( g_buffer );
471+ if(line)
472+ {
473+ CK_FPRINTF_STDERR( "line(%d):", line );
474+ sprintf( g_buffer, "line(%d):", line );
475+ lastErrorCat( g_buffer );
476+ }
477+ CK_FPRINTF_STDERR( " " );
478+ lastErrorCat( " " );
479+
480+ va_start( ap, message );
481+ CK_VFPRINTF_STDERR( message, ap );
482+ va_end( ap );
483+
484+ va_start( ap, message );
485+ vsprintf( g_buffer, message, ap );
486+ va_end( ap );
487+
488+ lastErrorCat( g_buffer );
489+ CK_FPRINTF_STDERR( "\n" );
490+ CK_FFLUSH_STDERR();
491+}
492+
493+
494+// [%s]:line(%d):
495+void EM_error2b( int line, const char * message, ... )
496+{
497+ va_list ap;
498+
499+ EM_extLineNum = line;
500+
501+ // separate errmsgs with newlines
502+ if( g_lasterror[0] != '\0' ) lastErrorCat( "\n" );
503+
504+ CK_FPRINTF_STDERR( "[%s]:", *fileName ? mini(fileName) : "chuck" );
505+ sprintf( g_buffer, "[%s]:", *fileName ? mini(fileName) : "chuck" );
506+ lastErrorCat( g_buffer );
507+ if(line)
508+ {
509+ CK_FPRINTF_STDERR( "line(%d):", line );
510+ sprintf( g_buffer, "line(%d):", line );
511+ lastErrorCat( g_buffer );
512+ }
513+ CK_FPRINTF_STDERR( " " );
514+ lastErrorCat( " " );
515+
516+ va_start( ap, message );
517+ CK_VFPRINTF_STDERR( message, ap );
518+ va_end( ap );
519+
520+ va_start( ap, message );
521+ vsprintf( g_buffer, message, ap );
522+ va_end( ap );
523+
524+ lastErrorCat( g_buffer );
525+ CK_FPRINTF_STDOUT( "\n" );
526+ CK_FFLUSH_STDOUT();
527+}
528+
529+
530+//
531+void EM_error3( const char * message, ... )
532+{
533+ va_list ap;
534+
535+ // separate errmsgs with newlines
536+ if( g_lasterror[0] != '\0' ) lastErrorCat( "\n" );
537+
538+// g_lasterror[0] = '\0';
539+ g_buffer[0] = '\0';
540+
541+ va_start( ap, message );
542+ CK_VFPRINTF_STDERR( message, ap );
543+ va_end( ap );
544+
545+ va_start( ap, message );
546+ vsprintf( g_buffer, message, ap );
547+ va_end( ap );
548+
549+ lastErrorCat( g_buffer );
550+ CK_FPRINTF_STDERR( "\n" );
551+ CK_FFLUSH_STDERR();
552+}
553+
554+
555+// log
556+void EM_log( int level, const char * message, ... )
557+{
558+ va_list ap;
559+
560+ if( level > CK_LOG_CRAZY ) level = CK_LOG_CRAZY;
561+ else if( level <= CK_LOG_NONE ) level = CK_LOG_NONE + 1;
562+
563+ // check level
564+ if( level > g_loglevel ) return;
565+
566+ g_logmutex.acquire();
567+ CK_FPRINTF_STDERR( "[chuck]:" );
568+ CK_FPRINTF_STDERR( "(%i:%s): ", level, g_str[level] );
569+
570+ // if( g_logstack ) CK_FPRINTF_STDERR( " " );
571+ for( int i = 0; i < g_logstack; i++ )
572+ CK_FPRINTF_STDERR( " | " );
573+
574+ va_start( ap, message );
575+ CK_VFPRINTF_STDERR( message, ap );
576+ va_end( ap );
577+
578+ CK_FPRINTF_STDERR( "\n" );
579+ CK_FFLUSH_STDERR();
580+ g_logmutex.release();
581+}
582+
583+
584+// set log level
585+void EM_setlog( int level )
586+{
587+ if( level > CK_LOG_CRAZY ) level = CK_LOG_CRAZY;
588+ else if( level < CK_LOG_NONE ) level = CK_LOG_NONE;
589+ g_loglevel = level;
590+
591+ // log this
592+ EM_log( CK_LOG_SYSTEM, "setting log level to: %i (%s)...", level, g_str[level] );
593+}
594+
595+// push log
596+void EM_pushlog()
597+{
598+ g_logstack++;
599+}
600+
601+// pop log
602+void EM_poplog()
603+{
604+ g_logstack--;
605+ if( g_logstack < 0 ) g_logstack = 0;
606+}
607+
608+// prepare new file
609+t_CKBOOL EM_reset( const char * fname, FILE * fd )
610+{
611+ anyErrors = FALSE;
612+ fileName = fname ? fname : (c_str)"";
613+ lineNum = 1;
614+ EM_lineNum = 1;
615+ EM_extLineNum = 1;
616+
617+ // free the intList
618+ IntList curr = NULL;
619+ while( linePos )
620+ {
621+ curr = linePos;
622+ linePos = linePos->rest;
623+ // free
624+ free( curr );
625+ }
626+
627+ // make new intList
628+ linePos = intList( 0, NULL );
629+
630+ return TRUE;
631+}
632+
633+
634+// change file
635+void EM_change_file( const char * fname )
636+{
637+ // set
638+ fileName = fname ? fname : (c_str)"";
639+ // more set
640+ lineNum = 0;
641+ EM_lineNum = 0;
642+ EM_extLineNum = 0;
643+}
644+
645+
646+// return last error
647+const char * EM_lasterror()
648+{
649+ return g_lasterror;
650+}
core/chuck_errmsg.h+177−0
@@ -0,0 +1,177 @@
1+/*----------------------------------------------------------------------------
2+ ChucK Concurrent, On-the-fly Audio Programming Language
3+ Compiler and Virtual Machine
4+
5+ Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6+ http://chuck.stanford.edu/
7+ http://chuck.cs.princeton.edu/
8+
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.
13+
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.
18+
19+ You should have received a copy of the GNU General Public License
20+ along with this program; if not, write to the Free Software
21+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22+ U.S.A.
23+-----------------------------------------------------------------------------*/
24+
25+//-----------------------------------------------------------------------------
26+// file: errmsg.h
27+// desc: functions used in all phases of the compiler to give error messages
28+// based on Andrew Appel's Tiger code
29+//
30+// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
31+// based on code by: Andrew Appel (appel@cs.princeton.edu)
32+// date: Summer 2002
33+//-----------------------------------------------------------------------------
34+#ifndef __CHUCK_ERRORMSG_H__
35+#define __CHUCK_ERRORMSG_H__
36+
37+#include "chuck_def.h"
38+#include <stdio.h>
39+
40+
41+#if defined(_cplusplus) || defined(__cplusplus)
42+extern "C" {
43+#endif
44+
45+
46+extern t_CKBOOL EM_anyErrors;
47+extern int EM_tokPos;
48+extern int EM_lineNum;
49+
50+// EM_extLineNum is synced with EM_lineNum in lexer/parser phase, then synced
51+// with scanner/typechecker (EM_lineNum is not synced with scanner/typechecker)
52+extern int EM_extLineNum;
53+
54+void EM_newline( );
55+
56+// levels
57+#define CK_LOG_CRAZY 10 // set this to log everything
58+#define CK_LOG_FINEST 9
59+#define CK_LOG_FINER 8
60+#define CK_LOG_FINE 7
61+#define CK_LOG_CONFIG 6
62+#define CK_LOG_INFO 5
63+#define CK_LOG_WARNING 4
64+#define CK_LOG_SEVERE 3
65+#define CK_LOG_SYSTEM 2
66+#define CK_LOG_CORE 1
67+#define CK_LOG_NONE 0 // set this to log nothing
68+
69+
70+//-----------------------------------------------------------------------------
71+// REFACTOR-2017: (jack) -- callback printing
72+//-----------------------------------------------------------------------------
73+// printing
74+void ck_fprintf_stdout( const char * format, ... );
75+void ck_fprintf_stderr( const char * format, ... );
76+void ck_fflush_stdout();
77+void ck_fflush_stderr();
78+void ck_vfprintf_stdout( const char * format, va_list args );
79+void ck_vfprintf_stderr( const char * format, va_list args );
80+
81+// callbacks
82+void ck_set_stdout_callback( void (*callback)(const char *) );
83+void ck_set_stderr_callback( void (*callback)(const char *) );
84+
85+#define CK_FPRINTF_STDOUT(...) ck_fprintf_stdout(__VA_ARGS__)
86+#define CK_FPRINTF_STDERR(...) ck_fprintf_stderr(__VA_ARGS__)
87+#define CK_FFLUSH_STDOUT() ck_fflush_stdout()
88+#define CK_FFLUSH_STDERR() ck_fflush_stderr()
89+#define CK_VFPRINTF_STDOUT(message, ap) ck_vfprintf_stdout(message, ap)
90+#define CK_VFPRINTF_STDERR(message, ap) ck_vfprintf_stderr(message, ap)
91+
92+#ifdef __cplusplus
93+// c++: custom stream-like thing
94+extern "C++" {
95+#include <sstream>
96+
97+class ChuckOutStream
98+{
99+public:
100+ ChuckOutStream( bool isErr );
101+ ~ChuckOutStream();
102+
103+ // there's probably a way to do this with templates or something
104+ // this is not that way
105+ ChuckOutStream& operator<<( const std::string val );
106+ ChuckOutStream& operator<<( const char * val );
107+ ChuckOutStream& operator<<( const double val );
108+ ChuckOutStream& operator<<( const float val );
109+ ChuckOutStream& operator<<( const unsigned long long val );
110+ ChuckOutStream& operator<<( const long long val );
111+ ChuckOutStream& operator<<( const unsigned long val );
112+ ChuckOutStream& operator<<( const long val );
113+ ChuckOutStream& operator<<( const unsigned int val );
114+ ChuckOutStream& operator<<( const int val );
115+ ChuckOutStream& operator<<( const bool val );
116+
117+ void set_callback( void (*callback)(const char *) );
118+
119+private:
120+ void flush();
121+ std::stringstream m_stream;
122+ void (*m_callback)(const char *);
123+ bool m_isErr;
124+};
125+
126+
127+extern ChuckOutStream g_ck_stdoutstream;
128+extern ChuckOutStream g_ck_stderrstream;
129+
130+#define CK_STDCOUT g_ck_stdoutstream
131+#define CK_STDCERR g_ck_stderrstream
132+#define CK_STDENDL std::string("\n")
133+
134+}
135+#else
136+// c: oh well
137+#define CK_STDCOUT std::cout
138+#define CK_STDCERR std::cerr
139+#define CK_STDENDL std::endl
140+
141+#endif
142+//-----------------------------------------------------------------------------
143+// here endeth the callback printing
144+//-----------------------------------------------------------------------------
145+
146+
147+
148+
149+void EM_log( int, c_constr, ... );
150+void EM_setlog( int );
151+void EM_pushlog();
152+void EM_poplog();
153+
154+// actual level
155+extern int g_loglevel;
156+// macro to compare
157+#define DO_LOG(x) ( x <= g_loglevel )
158+
159+void EM_error( int, c_constr, ... );
160+void EM_error2( int, c_constr, ... );
161+void EM_error2b( int, c_constr, ... );
162+void EM_error3( c_constr, ... );
163+void EM_impossible( c_constr, ... );
164+t_CKBOOL EM_reset( c_constr filename, FILE * fd );
165+void EM_change_file( c_constr filename );
166+const char * EM_lasterror();
167+void EM_reset_msg();
168+
169+const char * mini( const char * str );
170+const char * mini_type( const char * str );
171+
172+#if defined(_cplusplus) || defined(__cplusplus)
173+}
174+#endif
175+
176+
177+#endif
core/chuck_frame.cpp+163−0
@@ -0,0 +1,163 @@
1+/*----------------------------------------------------------------------------
2+ ChucK Concurrent, On-the-fly Audio Programming Language
3+ Compiler and Virtual Machine
4+
5+ Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6+ http://chuck.stanford.edu/
7+ http://chuck.cs.princeton.edu/
8+
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.
13+
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.
18+
19+ You should have received a copy of the GNU General Public License
20+ along with this program; if not, write to the Free Software
21+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22+ U.S.A.
23+-----------------------------------------------------------------------------*/
24+
25+//-----------------------------------------------------------------------------
26+// file: chuck_frame.cpp
27+// desc: chuck scope frame
28+//
29+// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
30+// date: Autumn 2002
31+//-----------------------------------------------------------------------------
32+#include "chuck_frame.h"
33+using namespace std;
34+
35+
36+
37+
38+//-----------------------------------------------------------------------------
39+// name: Chuck_Frame()
40+// desc: ...
41+//-----------------------------------------------------------------------------
42+Chuck_Frame::Chuck_Frame()
43+{
44+ // name
45+ name = "";
46+ // ofset
47+ curr_offset = 0;
48+ // don't know
49+ num_access = 0;
50+}
51+
52+
53+
54+
55+//-----------------------------------------------------------------------------
56+// name: alloc_local()
57+// desc: ...
58+//-----------------------------------------------------------------------------
59+Chuck_Local * Chuck_Frame::alloc_local( t_CKUINT size, const string & name,
60+ t_CKBOOL is_ref, t_CKBOOL is_obj )
61+{
62+ // alloc
63+ Chuck_Local * local = new Chuck_Local;
64+ // size
65+ local->size = size;
66+ // the offset
67+ local->offset = this->curr_offset;
68+ // ref
69+ local->is_ref = is_ref;
70+ // is object type? (added ge: 2012 april | added 1.3.0.0)
71+ local->is_obj = is_obj;
72+ // the next offset
73+ this->curr_offset += local->size;
74+ // name
75+ local->name = name;
76+ // push the local
77+ this->stack.push_back( local );
78+
79+ return local;
80+}
81+
82+
83+
84+
85+//-----------------------------------------------------------------------------
86+// name: push_scope()
87+// desc: ...
88+//-----------------------------------------------------------------------------
89+void Chuck_Frame::push_scope( )
90+{
91+ stack.push_back( NULL );
92+}
93+
94+
95+
96+
97+//-----------------------------------------------------------------------------
98+// name: get_scope()
99+// desc: get current scope (added 1.3.0.0)
100+//-----------------------------------------------------------------------------
101+void Chuck_Frame::get_scope( vector<Chuck_Local *> & out ) const
102+{
103+ // sanity
104+ assert( this->stack.size() > 0 );
105+
106+ // the local
107+ Chuck_Local * local = NULL;
108+ // the index
109+ long index = this->stack.size() - 1;
110+
111+ // loop
112+ while( index >= 0 && this->stack[index] != NULL )
113+ {
114+ // last thing
115+ local = stack[index];
116+ // move
117+ index--;
118+ // check if not null
119+ if( local )
120+ {
121+ // copy out
122+ out.push_back( local );
123+ }
124+ }
125+}
126+
127+
128+
129+
130+//-----------------------------------------------------------------------------
131+// name: pop_scope()
132+// desc: ....
133+//-----------------------------------------------------------------------------
134+void Chuck_Frame::pop_scope( vector<Chuck_Local *> & out )
135+{
136+ // sanity
137+ assert( this->stack.size() > 0 );
138+
139+ // the local
140+ Chuck_Local * local = NULL;
141+
142+ // loop
143+ while( this->stack.size() && this->stack.back() )
144+ {
145+ // last thing
146+ local = stack.back();
147+ // pop
148+ stack.pop_back();
149+ // check if not null
150+ if( local )
151+ {
152+ // offset
153+ curr_offset -= local->size;
154+ // copy out (NOTE: these locals should be memory managed outside)
155+ out.push_back( local );
156+ }
157+ }
158+
159+ // sanity (should be at least one left)
160+ assert( this->stack.size() > 0 );
161+ // get ride of null boundary character (added 1.3.0.0)
162+ this->stack.pop_back();
163+}
core/chuck_frame.h+101−0
@@ -0,0 +1,101 @@
1+/*----------------------------------------------------------------------------
2+ ChucK Concurrent, On-the-fly Audio Programming Language
3+ Compiler and Virtual Machine
4+
5+ Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6+ http://chuck.stanford.edu/
7+ http://chuck.cs.princeton.edu/
8+
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.
13+
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.
18+
19+ You should have received a copy of the GNU General Public License
20+ along with this program; if not, write to the Free Software
21+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22+ U.S.A.
23+-----------------------------------------------------------------------------*/
24+
25+//-----------------------------------------------------------------------------
26+// file: chuck_frame.h
27+// desc: chuck scope frame
28+//
29+// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
30+// date: Autumn 2002
31+//-----------------------------------------------------------------------------
32+#ifndef __CHUCK_FRAME_H__
33+#define __CHUCK_FRAME_H__
34+
35+#include "chuck_def.h"
36+
37+#include <string>
38+#include <vector>
39+
40+
41+//-----------------------------------------------------------------------------
42+// name: struct Chuck_Local
43+// desc: ...
44+//-----------------------------------------------------------------------------
45+struct Chuck_Local
46+{
47+ // name
48+ std::string name;
49+ // the size of the local
50+ t_CKUINT size;
51+ // is ref
52+ t_CKBOOL is_ref;
53+ // is an object type (added ge: 2012 april | added 1.3.0.0)
54+ t_CKBOOL is_obj;
55+ // the offset
56+ t_CKUINT offset;
57+
58+ // constructor
59+ Chuck_Local()
60+ // (added 1.3.0.0 -- is_obj)
61+ { size = 0; is_ref = FALSE; is_obj = FALSE; offset = 0; }
62+};
63+
64+
65+
66+
67+//-----------------------------------------------------------------------------
68+// name: struct Chuck_Frame
69+// desc: ...
70+//-----------------------------------------------------------------------------
71+struct Chuck_Frame
72+{
73+ // yes
74+ std::string name;
75+ // the offset
76+ t_CKUINT curr_offset;
77+ // not sure
78+ t_CKUINT num_access;
79+ // offset stack
80+ std::vector<Chuck_Local *> stack;
81+
82+public:
83+ Chuck_Frame();
84+ ~Chuck_Frame() { }
85+
86+public:
87+ // push scope
88+ void push_scope();
89+ // add local (added 1.3.0.0 -- is_obj)
90+ Chuck_Local * alloc_local( t_CKUINT size, const std::string & name,
91+ t_CKBOOL is_ref, t_CKBOOL is_obj );
92+ // get the current scope (added 1.3.0.0)
93+ void get_scope( std::vector<Chuck_Local *> & out ) const;
94+ // pop scope
95+ void pop_scope( std::vector<Chuck_Local *> & out );
96+};
97+
98+
99+
100+
101+#endif
core/chuck_io.cpp+1950−0
@@ -0,0 +1,1950 @@
1+/*----------------------------------------------------------------------------
2+ ChucK Concurrent, On-the-fly Audio Programming Language
3+ Compiler and Virtual Machine
4+
5+ Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6+ http://chuck.stanford.edu/
7+ http://chuck.cs.princeton.edu/
8+
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.
13+
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.
18+
19+ You should have received a copy of the GNU General Public License
20+ along with this program; if not, write to the Free Software
21+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22+ U.S.A.
23+-----------------------------------------------------------------------------*/
24+
25+//-----------------------------------------------------------------------------
26+// name: chuck_io.cpp
27+// desc: chuck i/o
28+//
29+// authors: Spencer Salazar (spencer@ccrma.stanford.edu)
30+// date: Summer 2012
31+//-----------------------------------------------------------------------------
32+#include "chuck_io.h"
33+#include "chuck_errmsg.h"
34+#include "util_serial.h"
35+#include "chuck_instr.h"
36+#include "chuck_type.h"
37+#include "chuck_globals.h"
38+#include "chuck_vm.h"
39+
40+#ifndef __WINDOWS_DS__
41+#include <sys/select.h>
42+#include <poll.h>
43+#include <termios.h>
44+#include <unistd.h>
45+#else
46+#include <io.h>
47+#endif // __WINDOWS_DS__
48+#include <fcntl.h>
49+#include <math.h>
50+
51+#include <iostream>
52+#include <fstream>
53+using namespace std;
54+
55+
56+#ifdef __WINDOWS_DS__
57+typedef BYTE uint8_t;
58+typedef WORD uint16_t;
59+// ge: this needed in earlier/some versions of windows
60+#ifndef __WINDOWS_MODERN__
61+typedef DWORD uint32_t;
62+#endif
63+#endif
64+
65+
66+// available baud rates
67+const t_CKUINT Chuck_IO_Serial::CK_BAUD_2400 = 2400;
68+const t_CKUINT Chuck_IO_Serial::CK_BAUD_4800 = 4800;
69+const t_CKUINT Chuck_IO_Serial::CK_BAUD_9600 = 9600;
70+const t_CKUINT Chuck_IO_Serial::CK_BAUD_19200 = 19200;
71+const t_CKUINT Chuck_IO_Serial::CK_BAUD_38400 = 38400;
72+const t_CKUINT Chuck_IO_Serial::CK_BAUD_7200 = 7200;
73+const t_CKUINT Chuck_IO_Serial::CK_BAUD_14400 = 14400;
74+const t_CKUINT Chuck_IO_Serial::CK_BAUD_28800 = 28800;
75+const t_CKUINT Chuck_IO_Serial::CK_BAUD_57600 = 57600;
76+const t_CKUINT Chuck_IO_Serial::CK_BAUD_76800 = 76800;
77+const t_CKUINT Chuck_IO_Serial::CK_BAUD_115200 = 115200;
78+const t_CKUINT Chuck_IO_Serial::CK_BAUD_230400 = 230400;
79+
80+const t_CKUINT Chuck_IO_Serial::TYPE_NONE = 0;
81+const t_CKUINT Chuck_IO_Serial::TYPE_BYTE = 1;
82+const t_CKUINT Chuck_IO_Serial::TYPE_WORD = 2;
83+const t_CKUINT Chuck_IO_Serial::TYPE_INT = 3;
84+const t_CKUINT Chuck_IO_Serial::TYPE_FLOAT = 4;
85+const t_CKUINT Chuck_IO_Serial::TYPE_STRING = 5;
86+const t_CKUINT Chuck_IO_Serial::TYPE_LINE = 6;
87+const t_CKUINT Chuck_IO_Serial::TYPE_WRITE = 100;
88+
89+std::list<Chuck_IO_Serial *> Chuck_IO_Serial::s_serials;
90+
91+// static const t_CKUINT TYPE_NONE = 0;
92+// static const t_CKUINT TYPE_BYTE = 1;
93+// static const t_CKUINT TYPE_WORD = 2;
94+// static const t_CKUINT TYPE_INT = 3;
95+// static const t_CKUINT TYPE_FLOAT = 4;
96+// static const t_CKUINT TYPE_STRING = 5;
97+// static const t_CKUINT TYPE_LINE = 6;
98+// static const t_CKUINT TYPE_WRITE = 100;
99+
100+const t_CKUINT CHUCK_IO_DEFAULT_BUFSIZE = 1024;
101+const char * CHUCK_IO_SCANF_STRING = "%1024s";
102+
103+CK_DLL_MFUN(serialio_canWait);
104+
105+void * Chuck_IO_Serial::shell_read_cb( void *_this )
106+{
107+ Chuck_IO_Serial *cereal = (Chuck_IO_Serial *) _this;
108+
109+ cereal->read_cb();
110+
111+ return NULL;
112+}
113+
114+void * Chuck_IO_Serial::shell_write_cb( void *_this )
115+{
116+ Chuck_IO_Serial *cereal = (Chuck_IO_Serial *) _this;
117+
118+ cereal->write_cb();
119+
120+ return NULL;
121+}
122+
123+void Chuck_IO_Serial::shutdown()
124+{
125+ EM_log(CK_LOG_INFO, "shutting down serial devices");
126+
127+ for(std::list<Chuck_IO_Serial *>::iterator i = s_serials.begin(); i != s_serials.end(); i++)
128+ {
129+ (*i)->close();
130+ }
131+}
132+
133+
134+Chuck_IO_Serial::Chuck_IO_Serial( Chuck_VM * vm ) :
135+m_asyncRequests(CircularBuffer<Request>(32)),
136+m_asyncResponses(CircularBuffer<Request>(32)),
137+m_asyncWriteRequests(CircularBuffer<Request>(32)),
138+m_writeBuffer(1024)
139+{
140+ m_fd = -1;
141+ m_cfd = NULL;
142+
143+ m_io_buf_max = CHUCK_IO_DEFAULT_BUFSIZE;
144+ m_io_buf = new unsigned char[m_io_buf_max];
145+ m_io_buf_pos = m_io_buf_available = 0;
146+
147+ m_tmp_buf_max = CHUCK_IO_DEFAULT_BUFSIZE;
148+ m_tmp_buf = new unsigned char[m_tmp_buf_max];
149+
150+ m_read_thread = NULL;
151+ m_event_buffer = NULL;
152+
153+ m_write_thread = NULL;
154+ m_do_write_thread = TRUE;
155+
156+ m_do_exit = FALSE;
157+
158+ s_serials.push_back(this);
159+
160+ m_vmRef = vm;
161+}
162+
163+Chuck_IO_Serial::~Chuck_IO_Serial()
164+{
165+ m_do_read_thread = FALSE;
166+ m_do_write_thread = FALSE;
167+ SAFE_DELETE(m_read_thread);
168+ if( m_event_buffer )
169+ m_vmRef->destroy_event_buffer( m_event_buffer );
170+
171+ close();
172+
173+ SAFE_DELETE(m_io_buf);
174+ m_io_buf_max = 0;
175+ m_io_buf_pos = m_io_buf_available = 0;
176+
177+ SAFE_DELETE(m_tmp_buf);
178+ m_tmp_buf_max = 0;
179+
180+ s_serials.remove(this);
181+}
182+
183+t_CKBOOL Chuck_IO_Serial::ready()
184+{
185+#ifndef __WINDOWS_DS__
186+ struct pollfd pollfds;
187+ pollfds.fd = m_fd;
188+ pollfds.events = POLLIN;
189+ pollfds.revents = 0;
190+
191+ int result = poll(&pollfds, 1, 0);
192+
193+ if( result > 0 && (pollfds.revents & POLLIN) ) return TRUE;
194+ else return FALSE; // TODO: error handling
195+#else
196+ return FALSE;
197+#endif
198+}
199+
200+t_CKBOOL Chuck_IO_Serial::open( const t_CKUINT i, t_CKINT flags, t_CKUINT baud )
201+{
202+ vector<string> ports = SerialIOManager::availableSerialDevices();
203+
204+ if( i < ports.size() )
205+ {
206+ const string &path = ports[i];
207+
208+ open(path, flags, baud);
209+ }
210+ else
211+ {
212+ EM_log(CK_LOG_WARNING, "(Serial.open): error: invalid port number");
213+ return FALSE;
214+ }
215+
216+ return TRUE;
217+}
218+
219+
220+t_CKBOOL Chuck_IO_Serial::open( const std::string & path, t_CKINT flags, t_CKUINT baud )
221+{
222+ if( flags & Chuck_IO_File::TYPE_BINARY )
223+ {
224+ m_flags = Chuck_IO_File::TYPE_BINARY;
225+ }
226+ else if( flags & Chuck_IO_File::TYPE_ASCII )
227+ {
228+ m_flags = Chuck_IO_File::TYPE_ASCII;
229+ }
230+ else
231+ {
232+ EM_log(CK_LOG_WARNING, "(Serial.open): warning: invalid binary/ASCII flag requested, defaulting to ASCII");
233+ m_flags = Chuck_IO_File::TYPE_ASCII;
234+ }
235+
236+ int fd = ::open( path.c_str(), O_RDWR );
237+ if( fd < 0 )
238+ {
239+ EM_log(CK_LOG_WARNING, "(Serial.open): error: unable to open file at '%s'", path.c_str());
240+ return FALSE;
241+ }
242+
243+ m_fd = fd;
244+ m_path = path;
245+
246+ // set default baud rate
247+ setBaudRate(baud);
248+
249+ m_cfd = fdopen(fd, "a+");
250+ m_iomode = MODE_ASYNC;
251+#ifndef WIN32
252+ fcntl(m_fd, F_SETFL, O_NONBLOCK);
253+#endif
254+ m_eof = FALSE;
255+
256+ return TRUE;
257+}
258+
259+
260+t_CKBOOL Chuck_IO_Serial::good()
261+{
262+ return m_fd >= 0 && m_cfd != NULL;
263+}
264+
265+void Chuck_IO_Serial::close()
266+{
267+ if(m_iomode == MODE_SYNC)
268+ {
269+ close_int();
270+ }
271+ else
272+ {
273+ m_do_exit = TRUE;
274+#ifdef WIN32
275+ m_read_thread->wait(-1, TRUE);
276+ close_int();
277+#else
278+ m_read_thread->wait(-1, FALSE);
279+#endif
280+ }
281+}
282+
283+void Chuck_IO_Serial::close_int()
284+{
285+ EM_log(CK_LOG_INFO, "(Serial.close): closing serial device '%s'", m_path.c_str());
286+
287+ if(good())
288+ {
289+ if(m_cfd)
290+ fclose(m_cfd);
291+ else
292+ ::close(m_fd);
293+ m_fd = -1;
294+ m_cfd = NULL;
295+ }
296+}
297+
298+void Chuck_IO_Serial::flush()
299+{
300+ if(good())
301+ {
302+ if(m_iomode == MODE_SYNC)
303+ fflush(m_cfd);
304+ else
305+ ; // TODO
306+ }
307+}
308+
309+t_CKBOOL Chuck_IO_Serial::can_wait()
310+{
311+ return m_asyncResponses.numElements() == 0;
312+}
313+
314+t_CKINT Chuck_IO_Serial::mode()
315+{
316+ return m_iomode;
317+}
318+
319+void Chuck_IO_Serial::mode( t_CKINT flag )
320+{
321+ if( flag == MODE_SYNC )
322+ m_iomode = MODE_SYNC;
323+ else if( flag == MODE_ASYNC )
324+ m_iomode = MODE_ASYNC;
325+}
326+
327+// reading
328+t_CKINT Chuck_IO_Serial::readInt( t_CKINT flags )
329+{
330+ if( !good() )
331+ {
332+ EM_log(CK_LOG_WARNING, "(Serial.readInt): warning: file not open");
333+ return 0;
334+ }
335+
336+ if( m_iomode == MODE_ASYNC )
337+ {
338+ EM_log(CK_LOG_WARNING, "(Serial.readInt): warning: calling synchronous read function on asynchronous file");
339+ return 0;
340+ }
341+
342+ t_CKINT i = 0;
343+
344+ if( m_flags & Chuck_IO_File::TYPE_BINARY )
345+ {
346+ if( flags & INT8 )
347+ {
348+ uint8_t byte = 0;
349+ if(!fread(&byte, 1, 1, m_cfd))
350+ EM_log(CK_LOG_WARNING, "(Serial.readInt): error: read failed");
351+
352+ i = byte;
353+ }
354+ else if( flags & INT16 )
355+ {
356+ uint16_t word = 0;
357+ if(!fread(&word, 2, 1, m_cfd))
358+ EM_log(CK_LOG_WARNING, "(Serial.readInt): error: read failed");
359+
360+ i = word;
361+ }
362+ else if( flags & INT32 )
363+ {
364+ uint32_t dword = 0;
365+ if(!fread(&dword, 4, 1, m_cfd))
366+ EM_log(CK_LOG_WARNING, "(Serial.readInt): error: read failed");
367+
368+ i = dword;
369+ }
370+ }
371+ else
372+ {
373+ if(!fscanf(m_cfd, "%li", &i))
374+ EM_log(CK_LOG_WARNING, "(Serial.readInt): error: read failed");
375+ }
376+
377+ return i;
378+}
379+
380+t_CKFLOAT Chuck_IO_Serial::readFloat()
381+{
382+ if( !good() )
383+ {
384+ EM_log(CK_LOG_WARNING, "(Serial.readFloat): warning: file not open");
385+ return 0;
386+ }
387+
388+ if( m_iomode == MODE_ASYNC )
389+ {
390+ EM_log(CK_LOG_WARNING, "(Serial.readFloat): warning: calling synchronous read function on asynchronous file");
391+ return 0;
392+ }
393+
394+ t_CKFLOAT f = 0;
395+
396+ if( m_flags & Chuck_IO_File::TYPE_BINARY )
397+ {
398+ if(!fread(&f, 4, 1, m_cfd))
399+ EM_log(CK_LOG_WARNING, "(Serial.readFloat): error: read failed");
400+ }
401+ else
402+ {
403+ if(!fscanf(m_cfd, "%lf", &f))
404+ EM_log(CK_LOG_WARNING, "(Serial.readFloat): error: read failed");
405+ }
406+
407+ return f;
408+}
409+
410+t_CKBOOL Chuck_IO_Serial::readString( std::string & str )
411+{
412+ if( !good() )
413+ {
414+ EM_log(CK_LOG_WARNING, "(Serial.readString): warning: file not open");
415+ return FALSE;
416+ }
417+
418+ if( m_iomode == MODE_ASYNC )
419+ {
420+ EM_log(CK_LOG_WARNING, "(Serial.readString): warning: calling synchronous read function on asynchronous file");
421+ return FALSE;
422+ }
423+
424+ if( m_flags & Chuck_IO_File::TYPE_BINARY )
425+ {
426+ EM_log(CK_LOG_WARNING, "(Serial.readString): warning: cannot read string from binary file");
427+ return FALSE;
428+ }
429+
430+ if(!fscanf(m_cfd, CHUCK_IO_SCANF_STRING, &m_tmp_buf))
431+ {
432+ EM_log(CK_LOG_WARNING, "(Serial.readFloat): error: read failed");
433+ return FALSE;
434+ }
435+
436+ str = (char *) m_tmp_buf;
437+
438+ return TRUE;
439+}
440+
441+
442+Chuck_String * Chuck_IO_Serial::readLine()
443+{
444+ if( !good() )
445+ {
446+ EM_log(CK_LOG_WARNING, "(Serial.readLine): warning: file not open");
447+ return NULL;
448+ }
449+
450+ if( m_iomode == MODE_ASYNC )
451+ {
452+ EM_log(CK_LOG_WARNING, "(Serial.readLine): warning: calling synchronous read function on asynchronous file");
453+ return NULL;
454+ }
455+
456+ if( m_flags & Chuck_IO_File::TYPE_BINARY )
457+ {
458+ EM_log(CK_LOG_WARNING, "(Serial.readLine): warning: cannot read line from binary file");
459+ return NULL;
460+ }
461+
462+
463+ if(!fgets((char *)m_tmp_buf, m_tmp_buf_max, m_cfd))
464+ {
465+ EM_log(CK_LOG_WARNING, "(Serial.readLine): error: from fgets");
466+ return NULL;
467+ }
468+
469+ Chuck_String * str = new Chuck_String;
470+ initialize_object(str, m_vmRef->env()->t_string);
471+
472+ str->set( string((char *)m_tmp_buf) );
473+
474+ return str;
475+}
476+
477+
478+t_CKBOOL Chuck_IO_Serial::eof()
479+{
480+ if( !good() )
481+ {
482+ EM_log(CK_LOG_WARNING, "(Serial.eof): warning: file not open");
483+ return FALSE;
484+ }
485+
486+ if( MODE_SYNC )
487+ return (m_eof = feof( m_cfd ));
488+ else
489+ return m_eof;
490+}
491+
492+
493+// writing
494+void Chuck_IO_Serial::write( const std::string & val )
495+{
496+ if( !good() )
497+ {
498+ EM_log(CK_LOG_WARNING, "(Serial.write): warning: file not open");
499+ return;
500+ }
501+
502+ if( m_iomode == MODE_ASYNC )
503+ {
504+ start_read_thread();
505+
506+ int len = val.length();
507+ for(int i = 0; i < len; i++)
508+ // TODO: efficiency
509+ m_writeBuffer.put(val[i]);
510+
511+ Request r;
512+ r.m_type = TYPE_WRITE;
513+ r.m_val = 0;
514+ r.m_num = 0;
515+ r.m_status = Request::RQ_STATUS_PENDING;
516+
517+ m_asyncWriteRequests.put(r);
518+ }
519+ else if( m_iomode == MODE_SYNC )
520+ {
521+ fprintf( m_cfd, "%s", val.c_str() );
522+ }
523+}
524+
525+
526+void Chuck_IO_Serial::write( t_CKINT val )
527+{
528+ write( val, 4 );
529+}
530+
531+
532+void Chuck_IO_Serial::write( t_CKINT val, t_CKINT size )
533+{
534+ if( !good() )
535+ {
536+ EM_log(CK_LOG_WARNING, "(Serial.write): warning: file not open");
537+ return;
538+ }
539+
540+ if(!(size == 1 || size == 2 || size == 4 || size == 8))
541+ {
542+ EM_log(CK_LOG_WARNING, "(Serial.write): warning: invalid int size %li, ignoring write request", size);
543+ return;
544+ }
545+
546+ if( m_iomode == MODE_ASYNC )
547+ {
548+ start_read_thread();
549+
550+ if( m_flags & Chuck_IO_File::TYPE_ASCII )
551+ {
552+ // TODO: don't use m_tmp_buf (thread safety?)
553+#ifdef WIN32
554+ _snprintf((char *)m_tmp_buf, m_tmp_buf_max, "%li", val);
555+ m_tmp_buf[m_tmp_buf_max - 1] = '\0'; // force NULL terminator -- see http://www.di-mgt.com.au/cprog.html#snprintf
556+#else
557+ snprintf((char *)m_tmp_buf, m_tmp_buf_max, "%li", val);
558+#endif
559+ int len = strlen((char *)m_tmp_buf);
560+ for(int i = 0; i < len; i++)
561+ // TODO: efficiency
562+ m_writeBuffer.put(m_tmp_buf[i]);
563+
564+ Request r;
565+ r.m_type = TYPE_WRITE;
566+ r.m_val = 0;
567+ r.m_num = 0;
568+ r.m_status = Request::RQ_STATUS_PENDING;
569+
570+ m_asyncWriteRequests.put(r);
571+ }
572+ else
573+ {
574+ char * buf = (char *) &val;
575+
576+ // assume 4-byte int
577+ for(int i = 0; i < size; i++)
578+ m_writeBuffer.put(buf[i]);
579+
580+ Request r;
581+ r.m_type = TYPE_WRITE;
582+ r.m_val = 0;
583+ r.m_num = 0;
584+ r.m_status = Request::RQ_STATUS_PENDING;
585+
586+ m_asyncWriteRequests.put(r);
587+ }
588+ }
589+ else if( m_iomode == MODE_SYNC )
590+ {
591+ if( m_flags & Chuck_IO_File::TYPE_ASCII )
592+ {
593+ fprintf( m_cfd, "%li", val );
594+ }
595+ else
596+ {
597+ // assume 4-byte int
598+ char * buf = (char *) &val;
599+ fwrite(buf, 1, size, m_cfd);
600+ }
601+ }
602+}
603+
604+void Chuck_IO_Serial::write( t_CKFLOAT val )
605+{
606+ if( !good() )
607+ {
608+ EM_log(CK_LOG_WARNING, "(Serial.write): warning: file not open");
609+ return;
610+ }
611+
612+ if( m_iomode == MODE_ASYNC )
613+ {
614+ start_read_thread();
615+
616+ if( m_flags & Chuck_IO_File::TYPE_ASCII )
617+ {
618+#ifdef WIN32
619+ _snprintf((char *)m_tmp_buf, m_tmp_buf_max, "%f", val);
620+ m_tmp_buf[m_tmp_buf_max - 1] = '\0'; // force NULL terminator -- see http://www.di-mgt.com.au/cprog.html#snprintf
621+#else
622+ snprintf((char *)m_tmp_buf, m_tmp_buf_max, "%f", val);
623+#endif
624+
625+ int len = strlen((char *)m_tmp_buf);
626+ for(int i = 0; i < len; i++)
627+ // TODO: efficiency
628+ m_writeBuffer.put(m_tmp_buf[i]);
629+
630+ Request r;
631+ r.m_type = TYPE_WRITE;
632+ r.m_val = 0;
633+ r.m_num = 0;
634+ r.m_status = Request::RQ_STATUS_PENDING;
635+
636+ m_asyncWriteRequests.put(r);
637+ }
638+ else
639+ {
640+ char * buf = (char *) &val;
641+
642+ // assume 4-byte float
643+ for(int i = 0; i < 4; i++)
644+ m_writeBuffer.put(buf[i]);
645+
646+ Request r;
647+ r.m_type = TYPE_WRITE;
648+ r.m_val = 0;
649+ r.m_num = 0;
650+ r.m_status = Request::RQ_STATUS_PENDING;
651+
652+ m_asyncWriteRequests.put(r);
653+ }
654+ }
655+ else if( m_iomode == MODE_SYNC )
656+ {
657+ if( m_flags & Chuck_IO_File::TYPE_ASCII )
658+ {
659+ fprintf( m_cfd, "%f", val );
660+ }
661+ else
662+ {
663+ // assume 4-byte int
664+ char * buf = (char *) &val;
665+ fwrite(buf, 1, size, m_cfd);
666+ }
667+ }
668+}
669+
670+
671+void Chuck_IO_Serial::writeBytes( Chuck_Array4 * arr )
672+{
673+ if( !good() )
674+ {
675+ EM_log(CK_LOG_WARNING, "(Serial.writeBytes): warning: file not open");
676+ return;
677+ }
678+
679+ if( m_iomode == MODE_ASYNC )
680+ {
681+ start_read_thread();
682+
683+ int len = arr->size();
684+ for(int i = 0; i < len; i++)
685+ {
686+ // TODO: efficiency
687+ t_CKUINT byte;
688+ arr->get(i, &byte);
689+ m_writeBuffer.put((char) byte);
690+ }
691+
692+ Request r;
693+ r.m_type = TYPE_WRITE;
694+ r.m_val = 0;
695+ r.m_num = 0;
696+ r.m_status = Request::RQ_STATUS_PENDING;
697+
698+ m_asyncWriteRequests.put(r);
699+ }
700+ else if( m_iomode == MODE_SYNC )
701+ {
702+ int len = arr->size();
703+ for(int i = 0; i < len; i++)
704+ {
705+ // TODO: efficiency
706+ t_CKUINT byte;
707+ arr->get(i, &byte);
708+ fwrite(&byte, 1, 1, m_cfd);
709+ }
710+ }
711+}
712+
713+void Chuck_IO_Serial::start_read_thread()
714+{
715+ if(m_read_thread == NULL)
716+ {
717+ m_read_thread = new XThread();
718+#ifdef WIN32
719+ m_read_thread->start((unsigned int (__stdcall *)(void*))shell_read_cb, this);
720+#else
721+ m_read_thread->start(shell_read_cb, this);
722+#endif
723+ assert(m_event_buffer == NULL);
724+ m_event_buffer = m_vmRef->create_event_buffer();
725+ }
726+}
727+
728+
729+t_CKBOOL Chuck_IO_Serial::readAsync( t_CKUINT type, t_CKUINT num )
730+{
731+ if( !good() )
732+ {
733+ EM_log(CK_LOG_WARNING, "(Serial.readAsync): warning: file not open");
734+ return FALSE;
735+ }
736+
737+ start_read_thread();
738+
739+ Request read;
740+ read.m_type = type;
741+ read.m_num = num;
742+ read.m_val = 0;
743+ read.m_status = Request::RQ_STATUS_PENDING;
744+
745+ if(!m_asyncRequests.atMaximum() )
746+ {
747+ m_asyncRequests.put(read);
748+ }
749+ else
750+ {
751+ EM_log(CK_LOG_SEVERE, "(SerialIO.readAsync): warning: request buffer overflow, dropping read");
752+ return FALSE;
753+ }
754+
755+ return TRUE;
756+}
757+
758+Chuck_String * Chuck_IO_Serial::getLine()
759+{
760+ if( !good() )
761+ {
762+ EM_log(CK_LOG_WARNING, "(Serial.getLine): warning: file not open");
763+ return NULL;
764+ }
765+
766+ Request r;
767+
768+ Chuck_String * str = NULL;
769+
770+ if(m_asyncResponses.peek(r, 1) &&
771+ r.m_type == TYPE_LINE && r.m_status == Request::RQ_STATUS_SUCCESS)
772+ {
773+ str = (Chuck_String *) r.m_val;
774+ m_asyncResponses.get(r);
775+ }
776+
777+ return str;
778+}
779+
780+
781+t_CKINT Chuck_IO_Serial::getByte()
782+{
783+ if( !good() )
784+ {
785+ EM_log(CK_LOG_WARNING, "(Serial.getByte): warning: file not open");
786+ return 0;
787+ }
788+
789+ Request r;
790+
791+ t_CKINT i = 0;
792+
793+ if(m_asyncResponses.peek(r, 1) &&
794+ r.m_type == TYPE_BYTE && r.m_num == 1 &&
795+ r.m_status == Request::RQ_STATUS_SUCCESS)
796+ {
797+ i = (t_CKINT) r.m_val;
798+ m_asyncResponses.get(r);
799+ }
800+
801+ return i;
802+}
803+
804+Chuck_Array * Chuck_IO_Serial::getBytes()
805+{
806+ if( !good() )
807+ {
808+ EM_log(CK_LOG_WARNING, "(Serial.getBytes): warning: file not open");
809+ return NULL;
810+ }
811+
812+ Request r;
813+
814+ Chuck_Array * arr = NULL;
815+
816+ if(m_asyncResponses.peek(r, 1) &&
817+ r.m_type == TYPE_BYTE && r.m_num > 1 &&
818+ r.m_status == Request::RQ_STATUS_SUCCESS)
819+ {
820+ arr = (Chuck_Array *) r.m_val;
821+ initialize_object(arr, m_vmRef->env()->t_array);
822+ m_asyncResponses.get(r);
823+ }
824+
825+ return arr;
826+}
827+
828+Chuck_Array * Chuck_IO_Serial::getInts()
829+{
830+ if( !good() )
831+ {
832+ EM_log(CK_LOG_WARNING, "(Serial.getInts): warning: file not open");
833+ return NULL;
834+ }
835+
836+ Request r;
837+
838+ Chuck_Array * arr = NULL;
839+
840+ if(m_asyncResponses.peek(r, 1) &&
841+ r.m_type == TYPE_INT && r.m_status == Request::RQ_STATUS_SUCCESS)
842+ {
843+ arr = (Chuck_Array *) r.m_val;
844+ initialize_object(arr, m_vmRef->env()->t_array);
845+ m_asyncResponses.get(r);
846+ }
847+
848+ return arr;
849+}
850+
851+Chuck_Array * Chuck_IO_Serial::getFloats()
852+{
853+ if( !good() )
854+ {
855+ EM_log(CK_LOG_WARNING, "(Serial.getFloats): warning: file not open");
856+ return NULL;
857+ }
858+
859+ Request r;
860+
861+ Chuck_Array * arr = NULL;
862+
863+ if(m_asyncResponses.peek(r, 1) &&
864+ r.m_type == TYPE_FLOAT && r.m_status == Request::RQ_STATUS_SUCCESS)
865+ {
866+ arr = (Chuck_Array *) r.m_val;
867+ initialize_object(arr, m_vmRef->env()->t_array);
868+ m_asyncResponses.get(r);
869+ }
870+
871+ return arr;
872+}
873+
874+Chuck_String * Chuck_IO_Serial::getString()
875+{
876+ if( !good() )
877+ {
878+ EM_log(CK_LOG_WARNING, "(Serial.getString): warning: file not open");
879+ return NULL;
880+ }
881+
882+ Request r;
883+
884+ Chuck_String * str = NULL;
885+
886+ if(m_asyncResponses.peek(r, 1) &&
887+ r.m_type == TYPE_STRING && r.m_status == Request::RQ_STATUS_SUCCESS)
888+ {
889+ str = (Chuck_String *) r.m_val;
890+ m_asyncResponses.get(r);
891+ }
892+
893+ return str;
894+}
895+
896+
897+t_CKBOOL Chuck_IO_Serial::get_buffer(t_CKINT timeout_ms)
898+{
899+#ifndef WIN32
900+ fd_set fds;
901+ FD_ZERO(&fds);
902+ FD_SET(m_fd, &fds);
903+
904+ timeval tv;
905+ tv.tv_sec = timeout_ms/1000;
906+ tv.tv_usec = 1000 * (timeout_ms%1000);
907+
908+ int result = select(m_fd+1, &fds, NULL, NULL, &tv);
909+
910+ if(result > 0 && FD_ISSET(m_fd, &fds))
911+ {
912+ result = ::read(m_fd, m_io_buf, m_io_buf_max);
913+ if(result > 0)
914+ {
915+ m_io_buf_available = result;
916+ m_io_buf_pos = 0;
917+
918+ EM_log(CK_LOG_FINE, "(SerialIO::get_buffer): read() returned %i bytes", result);
919+
920+ return TRUE;
921+ }
922+ else
923+ {
924+ EM_log(CK_LOG_SEVERE, "(SerialIO::get_buffer): read() returned 0 bytes");
925+ }
926+ }
927+ else
928+ {
929+ EM_log(CK_LOG_FINE, "(SerialIO::get_buffer): select() timeout");
930+ }
931+
932+ return FALSE;
933+
934+#else
935+
936+ int result = ::read(m_fd, m_io_buf, m_io_buf_max);
937+ if(result > 0)
938+ {
939+ m_io_buf_available = result;
940+ m_io_buf_pos = 0;
941+
942+ return TRUE;
943+ }
944+
945+ Sleep(timeout_ms);
946+
947+ return FALSE;
948+
949+#endif
950+}
951+
952+// peek next byte
953+t_CKINT Chuck_IO_Serial::peek_buffer()
954+{
955+ // CK_FPRINTF_STDERR( "Chuck_IO_Serial::peek_buffer %i/%i\n", m_io_buf_pos, m_io_buf_available);
956+
957+ if(m_io_buf_pos >= m_io_buf_available)
958+ {
959+ // refresh data
960+ while(!m_do_exit && !m_eof && !get_buffer(5))
961+ ;
962+
963+ if(m_do_exit || m_eof)
964+ return -1;
965+ }
966+
967+ return m_io_buf[m_io_buf_pos];
968+}
969+
970+// consume next byte
971+// return -1 on error/exit condition
972+t_CKINT Chuck_IO_Serial::pull_buffer()
973+{
974+ // CK_FPRINTF_STDERR( "Chuck_IO_Serial::pull_buffer %i/%i\n", m_io_buf_pos, m_io_buf_available);
975+
976+ if(m_io_buf_pos >= m_io_buf_available)
977+ {
978+ // refresh data
979+ while(!m_do_exit && !m_eof && !get_buffer(5))
980+ ;
981+
982+ if(m_do_exit || m_eof)
983+ return -1;
984+ }
985+
986+ return m_io_buf[m_io_buf_pos++];
987+}
988+
989+
990+t_CKINT Chuck_IO_Serial::buffer_bytes_to_tmp(t_CKINT num_bytes)
991+{
992+ t_CKUINT len = 0;
993+ while(len < num_bytes && !m_do_exit)
994+ {
995+ if(peek_buffer() == -1)
996+ break;
997+
998+ m_tmp_buf[len++] = pull_buffer();
999+ }
1000+
1001+ return len;
1002+}
1003+
1004+
1005+t_CKBOOL Chuck_IO_Serial::handle_line(Chuck_IO_Serial::Request &r)
1006+{
1007+ t_CKUINT len = 0;
1008+ Chuck_String * str;
1009+
1010+ while(!m_do_exit)
1011+ {
1012+ if(peek_buffer() == -1)
1013+ break;
1014+
1015+ if(peek_buffer() == '\r')
1016+ {
1017+ // consume newline character
1018+ pull_buffer();
1019+ if(peek_buffer() == '\n') pull_buffer(); // handle \r\n
1020+ break;
1021+ }
1022+
1023+ if(peek_buffer() == '\n')
1024+ {
1025+ // consume newline character
1026+ pull_buffer();
1027+ if(peek_buffer() == '\r') pull_buffer(); // handle \n\r (unlikely)
1028+ break;
1029+ }
1030+
1031+ m_tmp_buf[len++] = pull_buffer();
1032+
1033+ if(len >= m_tmp_buf_max)
1034+ {
1035+ EM_log(CK_LOG_WARNING, "(Serial.handle_line): warning: line exceeds buffer length, truncating to %i characters", m_tmp_buf_max);
1036+ break;
1037+ }
1038+ }
1039+
1040+ if(m_do_exit)
1041+ goto error;
1042+ // TODO: eof
1043+
1044+ str = new Chuck_String;
1045+ str->set( std::string((char *)m_tmp_buf, len) );
1046+
1047+ r.m_val = (t_CKUINT) str;
1048+ r.m_status = Chuck_IO_Serial::Request::RQ_STATUS_SUCCESS;
1049+
1050+ return TRUE;
1051+
1052+error:
1053+ r.m_val = 0;
1054+ r.m_status = Chuck_IO_Serial::Request::RQ_STATUS_FAILURE;
1055+
1056+#ifdef WIN32
1057+ HANDLE hFile = (HANDLE) _get_osfhandle(m_fd);
1058+ DWORD error;
1059+ ClearCommError(hFile, &error, NULL);
1060+
1061+ PurgeComm(hFile, PURGE_RXCLEAR);
1062+#endif
1063+
1064+ return TRUE;
1065+}
1066+
1067+t_CKBOOL Chuck_IO_Serial::handle_string(Chuck_IO_Serial::Request & r)
1068+{
1069+ return FALSE;
1070+}
1071+
1072+t_CKBOOL Chuck_IO_Serial::handle_float_ascii(Chuck_IO_Serial::Request & r)
1073+{
1074+ t_CKFLOAT val = 0;
1075+ int numRead = 0;
1076+ Chuck_Array8 * array = new Chuck_Array8(0);
1077+
1078+ for(int i = 0; i < r.m_num && !m_do_exit; i++)
1079+ {
1080+ t_CKUINT len = 0;
1081+
1082+ while(!m_do_exit)
1083+ {
1084+ if(peek_buffer() == -1)
1085+ break;
1086+
1087+ // TODO: '\r'?
1088+ int c = peek_buffer();
1089+
1090+ if(isdigit(c) || c=='.' || (len==0 && (c=='-' || c=='+')))
1091+ {
1092+ m_tmp_buf[len++] = pull_buffer();
1093+ }
1094+ else if(len > 0)
1095+ {
1096+ m_tmp_buf[len++] = '\0';
1097+ val = strtod((char *)m_tmp_buf, NULL);
1098+
1099+ numRead++;
1100+ array->push_back(val);
1101+
1102+ break;
1103+ }
1104+ }
1105+ }
1106+
1107+ if(m_do_exit || m_eof)
1108+ goto error;
1109+
1110+ r.m_num = numRead;
1111+ r.m_val = (t_CKUINT) array;
1112+ r.m_status = Request::RQ_STATUS_SUCCESS;
1113+
1114+ return TRUE;
1115+
1116+error:
1117+ SAFE_DELETE(array);
1118+ r.m_val = 0;
1119+ r.m_status = Chuck_IO_Serial::Request::RQ_STATUS_FAILURE;
1120+
1121+ return TRUE;
1122+}
1123+
1124+t_CKBOOL Chuck_IO_Serial::handle_int_ascii(Chuck_IO_Serial::Request & r)
1125+{
1126+ t_CKINT val = 0;
1127+ int numRead = 0;
1128+ Chuck_Array4 * array = new Chuck_Array4(FALSE, 0);
1129+ for(int i = 0; i < r.m_num; i++)
1130+ {
1131+ t_CKUINT len = 0;
1132+
1133+ while(!m_do_exit)
1134+ {
1135+ if(peek_buffer() == -1)
1136+ break;
1137+
1138+ int c = pull_buffer();
1139+
1140+ if(isdigit(c) || (len==0 && (c=='-' || c=='+')))
1141+ {
1142+ m_tmp_buf[len++] = c;
1143+ }
1144+ else if(len > 0)
1145+ {
1146+ m_tmp_buf[len++] = '\0';
1147+ val = strtol((char *)m_tmp_buf, NULL, 10);
1148+
1149+ numRead++;
1150+ array->push_back(val);
1151+
1152+ break;
1153+ }
1154+ }
1155+ }
1156+
1157+ if(m_do_exit || m_eof)
1158+ goto error;
1159+
1160+ r.m_num = numRead;
1161+ r.m_val = (t_CKUINT) array;
1162+ r.m_status = Request::RQ_STATUS_SUCCESS;
1163+
1164+ return TRUE;
1165+
1166+error:
1167+ SAFE_DELETE(array);
1168+ r.m_val = 0;
1169+ r.m_status = Chuck_IO_Serial::Request::RQ_STATUS_FAILURE;
1170+
1171+ return TRUE;
1172+}
1173+
1174+t_CKBOOL Chuck_IO_Serial::handle_byte(Chuck_IO_Serial::Request & r)
1175+{
1176+ // binary
1177+ int size = 1;
1178+ int num = r.m_num;
1179+ t_CKUINT val = 0;
1180+
1181+ if(size*num > m_tmp_buf_max)
1182+ {
1183+ int new_num = (int) floorf(((float)m_tmp_buf_max)/size);
1184+ EM_log(CK_LOG_WARNING, "SerialIO.read_cb: error: request size %i too large (%i bytes), truncating to %i",
1185+ num, size*num, new_num);
1186+ num = new_num;
1187+ }
1188+
1189+ t_CKINT len = buffer_bytes_to_tmp(num);
1190+
1191+ if(m_do_exit || m_eof)
1192+ goto error;
1193+
1194+ r.m_num = len;
1195+
1196+ if(r.m_num == 1)
1197+ val = m_tmp_buf[0];
1198+ else
1199+ {
1200+ Chuck_Array4 * array = new Chuck_Array4(FALSE, r.m_num);
1201+ for(int i = 0; i < r.m_num; i++)
1202+ {
1203+ array->set(i, m_tmp_buf[i]);
1204+ }
1205+
1206+ val = (t_CKUINT) array;
1207+ }
1208+
1209+ r.m_val = val;
1210+ r.m_status = Request::RQ_STATUS_SUCCESS;
1211+
1212+ return TRUE;
1213+
1214+error:
1215+ r.m_val = 0;
1216+ r.m_status = Chuck_IO_Serial::Request::RQ_STATUS_FAILURE;
1217+
1218+ return TRUE;
1219+}
1220+
1221+t_CKBOOL Chuck_IO_Serial::handle_float_binary(Chuck_IO_Serial::Request & r)
1222+{
1223+ // binary
1224+ int size = 4; // SPENCERTODO: should these be based on arch (64 bit)?
1225+ assert(sizeof(t_CKSINGLE) == 4);
1226+
1227+ int num = r.m_num;
1228+
1229+ if(size*num > m_tmp_buf_max)
1230+ {
1231+ int new_num = (int) floorf(((float)m_tmp_buf_max)/size);
1232+ EM_log(CK_LOG_WARNING, "(SerialIO.read_cb): error: request size %i too large (%i bytes), truncating to %i",
1233+ num, size*num, new_num);
1234+ num = new_num;
1235+ }
1236+
1237+ r.m_num = buffer_bytes_to_tmp(size*num)/size;
1238+
1239+ t_CKUINT val = 0;
1240+ t_CKSINGLE * m_floats = (t_CKSINGLE *) m_tmp_buf;
1241+
1242+ Chuck_Array8 * array = new Chuck_Array8(r.m_num);
1243+ for(int i = 0; i < r.m_num; i++)
1244+ {
1245+ array->set(i, m_floats[i]);
1246+ }
1247+
1248+ val = (t_CKUINT) array;
1249+
1250+ r.m_val = val;
1251+ r.m_status = Request::RQ_STATUS_SUCCESS;
1252+
1253+ return TRUE;
1254+}
1255+
1256+t_CKBOOL Chuck_IO_Serial::handle_int_binary(Chuck_IO_Serial::Request & r)
1257+{
1258+ // binary
1259+ int size = 4; // SPENCERTODO: should these be based on arch (64 bit)?
1260+
1261+ int num = r.m_num;
1262+
1263+ if(size*num > m_tmp_buf_max)
1264+ {
1265+ int new_num = (int) floorf(((float)m_tmp_buf_max)/size);
1266+ EM_log(CK_LOG_WARNING, "SerialIO.read_cb: error: request size %i too large (%i bytes), truncating to %i",
1267+ num, size*num, new_num);
1268+ num = new_num;
1269+ }
1270+
1271+ r.m_num = buffer_bytes_to_tmp(size*num)/size;
1272+
1273+ t_CKUINT val = 0;
1274+ uint32_t * m_ints = (uint32_t *) m_tmp_buf;
1275+
1276+ Chuck_Array4 * array = new Chuck_Array4(FALSE, r.m_num);
1277+ for(int i = 0; i < r.m_num; i++)
1278+ {
1279+ array->set(i, m_ints[i]);
1280+ }
1281+
1282+ val = (t_CKUINT) array;
1283+
1284+ r.m_val = val;
1285+ r.m_status = Request::RQ_STATUS_SUCCESS;
1286+
1287+ return TRUE;
1288+}
1289+
1290+
1291+void Chuck_IO_Serial::read_cb()
1292+{
1293+ m_do_read_thread = TRUE;
1294+
1295+ m_write_thread = new XThread;
1296+#ifdef WIN32
1297+ m_read_thread->start((unsigned int (__stdcall *)(void*))shell_write_cb, this);
1298+#else
1299+ m_write_thread->start(shell_write_cb, this);
1300+#endif
1301+
1302+ while(m_do_read_thread && !m_do_exit)
1303+ {
1304+ Request r;
1305+ int num_responses = 0;
1306+
1307+ while(m_asyncRequests.get(r) && m_do_read_thread && !m_do_exit)
1308+ {
1309+ if( m_asyncResponses.atMaximum() )
1310+ {
1311+ EM_log(CK_LOG_SEVERE, "SerialIO.read_cb: error: response buffer overflow, dropping read");
1312+ continue;
1313+ }
1314+
1315+ if(m_flags & Chuck_IO_File::TYPE_ASCII)
1316+ {
1317+ switch(r.m_type)
1318+ {
1319+ case TYPE_LINE:
1320+ handle_line(r);
1321+ break;
1322+
1323+ case TYPE_STRING:
1324+ handle_string(r);
1325+ break;
1326+
1327+ case TYPE_INT:
1328+ handle_int_ascii(r);
1329+ break;
1330+
1331+ case TYPE_FLOAT:
1332+ handle_float_ascii(r);
1333+ break;
1334+
1335+ default:
1336+ // this shouldnt happen
1337+ r.m_type = TYPE_NONE;
1338+ r.m_num = 0;
1339+ r.m_status = Request::RQ_STATUS_INVALID;
1340+ r.m_val = 0;
1341+ EM_log(CK_LOG_WARNING, "SerialIO.read_cb: error: invalid request");
1342+ }
1343+ }
1344+ else
1345+ {
1346+ // binary
1347+ switch(r.m_type)
1348+ {
1349+ case TYPE_BYTE:
1350+ handle_byte(r);
1351+ break;
1352+ case TYPE_INT:
1353+ handle_int_binary(r);
1354+ break;
1355+ case TYPE_FLOAT:
1356+ handle_float_binary(r);
1357+ break;
1358+
1359+ default:
1360+ // this shouldnt happen
1361+ r.m_type = TYPE_NONE;
1362+ r.m_num = 0;
1363+ r.m_status = Request::RQ_STATUS_INVALID;
1364+ r.m_val = 0;
1365+ EM_log(CK_LOG_WARNING, "SerialIO.read_cb: error: invalid request");
1366+ }
1367+ }
1368+
1369+ m_asyncResponses.put(r);
1370+ num_responses++;
1371+ }
1372+
1373+ if(m_asyncResponses.numElements() > 0)
1374+ queue_broadcast(m_event_buffer);
1375+
1376+ usleep(100);
1377+ }
1378+
1379+ m_write_thread->wait(-1);
1380+
1381+ close_int();
1382+}
1383+
1384+void Chuck_IO_Serial::write_cb()
1385+{
1386+ m_do_write_thread = TRUE;
1387+
1388+ char *tmp_writethread_buf = new char[CHUCK_IO_DEFAULT_BUFSIZE];
1389+ t_CKINT tmp_writethread_buf_max = CHUCK_IO_DEFAULT_BUFSIZE;
1390+
1391+ while(m_do_write_thread && !m_do_exit)
1392+ {
1393+ Request r;
1394+
1395+ while(m_asyncWriteRequests.get(r) && m_do_write_thread && !m_do_exit)
1396+ {
1397+ if(r.m_type == TYPE_WRITE)
1398+ {
1399+ int numBytes = 0;
1400+ char c;
1401+ while(m_writeBuffer.get(c))
1402+ {
1403+ tmp_writethread_buf[numBytes] = c;
1404+ numBytes++;
1405+ }
1406+
1407+ assert(numBytes < tmp_writethread_buf_max);
1408+
1409+ if(numBytes)
1410+ {
1411+ fwrite(tmp_writethread_buf, 1, numBytes, m_cfd);
1412+ fflush(m_cfd);
1413+ }
1414+ }
1415+ }
1416+
1417+ // todo: replace with semaphore?
1418+ usleep(100);
1419+ }
1420+
1421+ delete[] tmp_writethread_buf;
1422+ tmp_writethread_buf = NULL;
1423+}
1424+
1425+
1426+t_CKBOOL Chuck_IO_Serial::setBaudRate( t_CKUINT rate )
1427+{
1428+#ifndef WIN32
1429+ // set serial IO baud rate
1430+ struct termios tios;
1431+ tcgetattr(m_fd, &tios);
1432+ cfsetispeed(&tios, rate);
1433+ cfsetospeed(&tios, rate);
1434+ tcsetattr(m_fd, TCSAFLUSH, &tios);
1435+
1436+ return TRUE;
1437+#else
1438+ DCB dcb;
1439+ COMMTIMEOUTS timeouts;
1440+ HANDLE hFile = (HANDLE) _get_osfhandle(m_fd);
1441+
1442+ bool was_error = false;
1443+ DWORD error_flag = 0;
1444+
1445+ if(!hFile)
1446+ {
1447+ goto error;
1448+ }
1449+
1450+ if(!GetCommTimeouts(hFile, &timeouts))
1451+ {
1452+ goto error;
1453+ }
1454+
1455+ timeouts.ReadIntervalTimeout = 10;
1456+ timeouts.WriteTotalTimeoutConstant = 5000;
1457+
1458+ if(!SetCommTimeouts(hFile, &timeouts))
1459+ {
1460+ goto error;
1461+ }
1462+
1463+ if(!GetCommState(hFile, &dcb))
1464+ {
1465+ goto error;
1466+ }
1467+
1468+ // set baud rate
1469+ dcb.BaudRate = rate;
1470+
1471+ // set important stuff
1472+ dcb.ByteSize = 8;
1473+ dcb.StopBits = ONESTOPBIT;
1474+
1475+ if(!SetCommState(hFile, &dcb))
1476+ {
1477+ //goto error;
1478+ was_error = true;
1479+ ClearCommError(hFile, &error_flag, NULL);
1480+ }
1481+
1482+ // set everything else
1483+ if(!GetCommState(hFile, &dcb))
1484+ {
1485+ goto error;
1486+ }
1487+
1488+ dcb.fBinary = TRUE;
1489+ dcb.fParity = FALSE;
1490+ dcb.fOutxCtsFlow = FALSE;
1491+ dcb.fOutxDsrFlow = FALSE;
1492+ dcb.fDtrControl = DTR_CONTROL_ENABLE;
1493+ dcb.fDsrSensitivity = FALSE;
1494+ dcb.fTXContinueOnXoff = TRUE;
1495+ dcb.fOutX = FALSE;
1496+ dcb.fInX = FALSE;
1497+ dcb.fErrorChar = FALSE;
1498+ dcb.fNull = FALSE;
1499+ dcb.fRtsControl = RTS_CONTROL_ENABLE;
1500+ dcb.fAbortOnError = TRUE;
1501+ dcb.Parity = NOPARITY;
1502+
1503+ if(!SetCommState(hFile, &dcb))
1504+ {
1505+ //goto error;
1506+ was_error = true;
1507+ ClearCommError(hFile, &error_flag, NULL);
1508+ }
1509+
1510+ if(!was_error)
1511+ return TRUE;
1512+
1513+error:
1514+
1515+ DWORD error = GetLastError();
1516+
1517+ return FALSE;
1518+
1519+#endif
1520+}
1521+
1522+
1523+t_CKUINT Chuck_IO_Serial::getBaudRate()
1524+{
1525+#ifndef WIN32
1526+ // set serial IO baud rate
1527+ struct termios tios;
1528+ tcgetattr(m_fd, &tios);
1529+ speed_t rate = cfgetispeed(&tios);
1530+ return rate;
1531+#else
1532+
1533+ DCB dcb;
1534+ HANDLE hFile = (HANDLE) _get_osfhandle(m_fd);
1535+
1536+ if(!hFile)
1537+ {
1538+ goto error;
1539+ }
1540+
1541+ if(!GetCommState(hFile, &dcb))
1542+ {
1543+ goto error;
1544+ }
1545+
1546+ return dcb.BaudRate;
1547+
1548+error:
1549+ return 0;
1550+
1551+#endif
1552+}
1553+
1554+
1555+//-----------------------------------------------------------------------------
1556+// serialio API
1557+//-----------------------------------------------------------------------------
1558+CK_DLL_SFUN( serialio_list );
1559+CK_DLL_ALLOC( serialio_alloc );
1560+CK_DLL_CTOR( serialio_ctor );
1561+CK_DLL_DTOR( serialio_dtor );
1562+CK_DLL_MFUN( serialio_open );
1563+CK_DLL_MFUN( serialio_close );
1564+CK_DLL_MFUN( serialio_ready );
1565+CK_DLL_MFUN( serialio_readLine );
1566+CK_DLL_MFUN( serialio_onLine );
1567+CK_DLL_MFUN( serialio_onByte );
1568+CK_DLL_MFUN( serialio_onBytes );
1569+CK_DLL_MFUN( serialio_onInts );
1570+CK_DLL_MFUN( serialio_onFloats );
1571+CK_DLL_MFUN( serialio_getLine );
1572+CK_DLL_MFUN( serialio_getByte );
1573+CK_DLL_MFUN( serialio_getBytes );
1574+CK_DLL_MFUN( serialio_getInts );
1575+CK_DLL_MFUN( serialio_setBaudRate );
1576+CK_DLL_MFUN( serialio_getBaudRate );
1577+CK_DLL_MFUN( serialio_writeByte );
1578+CK_DLL_MFUN( serialio_writeBytes );
1579+
1580+CK_DLL_MFUN( serialio_flush )
1581+{
1582+ Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1583+
1584+ cereal->flush();
1585+}
1586+
1587+
1588+//-----------------------------------------------------------------------------
1589+// name: init_class_serialio()
1590+// desc: ...
1591+//-----------------------------------------------------------------------------
1592+t_CKBOOL init_class_serialio( Chuck_Env * env )
1593+{
1594+ // init as base class
1595+ Chuck_DL_Func * func = NULL;
1596+
1597+ // log
1598+ EM_log( CK_LOG_SEVERE, "class 'SerialIO'" );
1599+
1600+ std::string doc = "Handles reading and writing for serial input/output devices, such as Arduino.";
1601+
1602+ Chuck_Type * type = type_engine_import_class_begin( env, "SerialIO", "IO",
1603+ env->global(), serialio_ctor, serialio_dtor, doc.c_str() );
1604+ // TODO: ctor/dtor?
1605+ if( !type )
1606+ return FALSE;
1607+
1608+ // HACK; SPENCERTODO: better way to set this
1609+ type->allocator = serialio_alloc;
1610+
1611+ // add list()
1612+ func = make_new_sfun( "string[]", "list", serialio_list );
1613+ func->doc = "Return list of available serial devices.";
1614+ if( !type_engine_import_sfun( env, func ) ) goto error;
1615+
1616+ func = make_new_mfun("int", "open", serialio_open);
1617+ func->add_arg("int", "i");
1618+ func->add_arg("int", "baud");
1619+ func->add_arg("int", "mode");
1620+ func->doc = "Open serial device i with specified baud rate and mode (binary or ASCII).";
1621+ if( !type_engine_import_mfun( env, func ) ) goto error;
1622+
1623+ func = make_new_mfun("void", "close", serialio_close);
1624+ if( !type_engine_import_mfun( env, func ) ) goto error;
1625+
1626+ // add ready (data available)
1627+ func = make_new_mfun("int", "dataAvailable", serialio_ready);
1628+ if( !type_engine_import_mfun( env, func ) ) goto error;
1629+
1630+ // add readLine
1631+ func = make_new_mfun("string", "readLine", serialio_readLine);
1632+ if( !type_engine_import_mfun( env, func ) ) goto error;
1633+
1634+ // add onLine
1635+ func = make_new_mfun("SerialIO", "onLine", serialio_onLine);
1636+ func->doc = "Wait for one line (ASCII mode only).";
1637+ if( !type_engine_import_mfun( env, func ) ) goto error;
1638+
1639+ // add onByte
1640+ func = make_new_mfun("SerialIO", "onByte", serialio_onByte);
1641+ func->doc = "Wait for one byte (binary mode only).";
1642+ if( !type_engine_import_mfun( env, func ) ) goto error;
1643+
1644+ // add onBytes
1645+ func = make_new_mfun("SerialIO", "onBytes", serialio_onBytes);
1646+ func->add_arg("int", "num");
1647+ func->doc = "Wait for requested number of bytes (binary mode only).";
1648+ if( !type_engine_import_mfun( env, func ) ) goto error;
1649+
1650+ // add onInts
1651+ func = make_new_mfun("SerialIO", "onInts", serialio_onInts);
1652+ func->add_arg("int", "num");
1653+ func->doc = "Wait for requested number of ints (ASCII or binary mode).";
1654+ if( !type_engine_import_mfun( env, func ) ) goto error;
1655+
1656+ // add onInts
1657+ func = make_new_mfun("SerialIO", "onFloats", serialio_onFloats);
1658+ func->add_arg("int", "num");
1659+ func->doc = "Wait for requested number of floats (ASCII or binary mode).";
1660+ if( !type_engine_import_mfun( env, func ) ) goto error;
1661+
1662+ // add getLine
1663+ func = make_new_mfun("string", "getLine", serialio_getLine);
1664+ func->doc = "Get next requested line.";
1665+ if( !type_engine_import_mfun( env, func ) ) goto error;
1666+
1667+ // add getByte
1668+ func = make_new_mfun("int", "getByte", serialio_getByte);
1669+ func->doc = "Get next requested byte. ";
1670+ if( !type_engine_import_mfun( env, func ) ) goto error;
1671+
1672+ // add getBytes
1673+ func = make_new_mfun("int[]", "getBytes", serialio_getBytes);
1674+ func->doc = "Get next requested number of bytes. ";
1675+ if( !type_engine_import_mfun( env, func ) ) goto error;
1676+
1677+ // add getInts
1678+ func = make_new_mfun("int[]", "getInts", serialio_getInts);
1679+ func->doc = "Get next requested number of integers. ";
1680+ if( !type_engine_import_mfun( env, func ) ) goto error;
1681+
1682+ // add writeByte
1683+ func = make_new_mfun("void", "writeByte", serialio_writeByte);
1684+ func->add_arg("int", "b");
1685+ func->doc = "Write a single byte.";
1686+ if( !type_engine_import_mfun( env, func ) ) goto error;
1687+
1688+ // add writeBytes
1689+ func = make_new_mfun("void", "writeBytes", serialio_writeBytes);
1690+ func->add_arg("int[]", "b");
1691+ func->doc = "Write array of bytes.";
1692+ if( !type_engine_import_mfun( env, func ) ) goto error;
1693+
1694+ // add setBaudRate
1695+ func = make_new_mfun("int", "baudRate", serialio_setBaudRate);
1696+ func->add_arg("int", "r");
1697+ func->doc = "Set baud rate.";
1698+ if( !type_engine_import_mfun( env, func ) ) goto error;
1699+
1700+ // add getBaudRate
1701+ func = make_new_mfun("int", "baudRate", serialio_getBaudRate);
1702+ func->doc = "Get current baud rate.";
1703+ if( !type_engine_import_mfun( env, func ) ) goto error;
1704+
1705+ // add getBaudRate
1706+ func = make_new_mfun("void", "flush", serialio_flush);
1707+ func->doc = "Flush the IO buffer.";
1708+ if( !type_engine_import_mfun( env, func ) ) goto error;
1709+
1710+ // add can_wait
1711+ // func = make_new_mfun("int", "can_wait", serialio_canWait);
1712+ // func->doc = "";
1713+ // if( !type_engine_import_mfun( env, func ) ) goto error;
1714+
1715+ // add baud rate constants
1716+ type_engine_import_svar(env, "int", "B2400", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_2400, "2400 baud");
1717+ type_engine_import_svar(env, "int", "B4800", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_4800, "4800 baud");
1718+ type_engine_import_svar(env, "int", "B9600", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_9600, "9600 baud");
1719+ type_engine_import_svar(env, "int", "B19200", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_19200, "19200 baud");
1720+ type_engine_import_svar(env, "int", "B38400", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_38400, "38400 baud");
1721+ type_engine_import_svar(env, "int", "B7200", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_7200, "7200 baud");
1722+ type_engine_import_svar(env, "int", "B14400", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_14400, "14400 baud");
1723+ type_engine_import_svar(env, "int", "B28800", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_28800, "28800 baud");
1724+ type_engine_import_svar(env, "int", "B57600", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_57600, "57600 baud");
1725+ type_engine_import_svar(env, "int", "B76800", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_76800, "76800 baud");
1726+ type_engine_import_svar(env, "int", "B115200", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_115200, "115200 baud");
1727+ type_engine_import_svar(env, "int", "B230400", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_230400, "230400 baud");
1728+
1729+ type_engine_import_svar(env, "int", "BINARY", TRUE, (t_CKUINT) &Chuck_IO_File::TYPE_BINARY, "Binary mode");
1730+ type_engine_import_svar(env, "int", "ASCII", TRUE, (t_CKUINT) &Chuck_IO_File::TYPE_ASCII, "ASCII mode");
1731+
1732+ // add examples
1733+ if( !type_engine_import_add_ex( env, "serial/byte.ck" ) ) goto error;
1734+ if( !type_engine_import_add_ex( env, "serial/bytes.ck" ) ) goto error;
1735+ if( !type_engine_import_add_ex( env, "serial/ints-bin.ck" ) ) goto error;
1736+ if( !type_engine_import_add_ex( env, "serial/ints.ck" ) ) goto error;
1737+ if( !type_engine_import_add_ex( env, "serial/lines.ck" ) ) goto error;
1738+ if( !type_engine_import_add_ex( env, "serial/list.ck" ) ) goto error;
1739+ if( !type_engine_import_add_ex( env, "serial/write-bytes.ck" ) ) goto error;
1740+ if( !type_engine_import_add_ex( env, "serial/write.ck" ) ) goto error;
1741+
1742+ // end the class import
1743+ type_engine_import_class_end( env );
1744+
1745+ return TRUE;
1746+
1747+error:
1748+
1749+ // end the class import
1750+ type_engine_import_class_end( env );
1751+
1752+ return FALSE;
1753+}
1754+
1755+
1756+
1757+CK_DLL_SFUN( serialio_list )
1758+{
1759+ vector<string> devices = SerialIOManager::availableSerialDevices();
1760+
1761+ // ISSUE: 64-bit
1762+ Chuck_Array4 * array = new Chuck_Array4(TRUE, 0);
1763+ initialize_object( array, SHRED->vm_ref->env()->t_array );
1764+
1765+ for(vector<string>::iterator i = devices.begin(); i != devices.end(); i++)
1766+ {
1767+ Chuck_String * name = new Chuck_String(*i);
1768+ initialize_object(name, SHRED->vm_ref->env()->t_string);
1769+ array->push_back((t_CKUINT) name);
1770+ }
1771+
1772+ RETURN->v_object = array;
1773+}
1774+
1775+
1776+CK_DLL_ALLOC( serialio_alloc )
1777+{
1778+ return new Chuck_IO_Serial( SHRED->vm_ref );
1779+}
1780+
1781+CK_DLL_CTOR( serialio_ctor )
1782+{
1783+ Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1784+ SHRED->add_serialio(cereal);
1785+}
1786+
1787+CK_DLL_DTOR( serialio_dtor )
1788+{
1789+ Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1790+ if(cereal)
1791+ {
1792+ SHRED->remove_serialio(cereal);
1793+ cereal->close();
1794+ }
1795+}
1796+
1797+CK_DLL_MFUN( serialio_open )
1798+{
1799+ Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1800+ t_CKINT num = GET_NEXT_INT(ARGS);
1801+ t_CKINT baud = GET_NEXT_INT(ARGS);
1802+ t_CKINT mode = GET_NEXT_INT(ARGS);
1803+
1804+ RETURN->v_int = cereal->open(num, mode, baud);
1805+}
1806+
1807+CK_DLL_MFUN( serialio_close )
1808+{
1809+ Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1810+
1811+ cereal->close();
1812+}
1813+
1814+CK_DLL_MFUN( serialio_ready )
1815+{
1816+ Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1817+
1818+ RETURN->v_int = cereal->ready();
1819+}
1820+
1821+CK_DLL_MFUN( serialio_readLine )
1822+{
1823+ Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1824+
1825+ RETURN->v_string = cereal->readLine();
1826+}
1827+
1828+
1829+CK_DLL_MFUN( serialio_onLine )
1830+{
1831+ Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1832+
1833+ cereal->readAsync(Chuck_IO_Serial::TYPE_LINE, 1);
1834+
1835+ RETURN->v_object = cereal;
1836+}
1837+
1838+
1839+CK_DLL_MFUN( serialio_onByte )
1840+{
1841+ Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1842+
1843+ cereal->readAsync(Chuck_IO_Serial::TYPE_BYTE, 1);
1844+
1845+ RETURN->v_object = cereal;
1846+}
1847+
1848+
1849+CK_DLL_MFUN( serialio_onBytes )
1850+{
1851+ Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1852+
1853+ t_CKINT num = GET_NEXT_INT(ARGS);
1854+
1855+ cereal->readAsync(Chuck_IO_Serial::TYPE_BYTE, num);
1856+
1857+ RETURN->v_object = cereal;
1858+}
1859+
1860+
1861+CK_DLL_MFUN( serialio_onInts )
1862+{
1863+ Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1864+
1865+ t_CKINT num = GET_NEXT_INT(ARGS);
1866+
1867+ cereal->readAsync(Chuck_IO_Serial::TYPE_INT, num);
1868+
1869+ RETURN->v_object = cereal;
1870+}
1871+
1872+
1873+CK_DLL_MFUN( serialio_onFloats )
1874+{
1875+ Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1876+
1877+ t_CKINT num = GET_NEXT_INT(ARGS);
1878+
1879+ cereal->readAsync(Chuck_IO_Serial::TYPE_FLOAT, num);
1880+
1881+ RETURN->v_object = cereal;
1882+}
1883+
1884+
1885+CK_DLL_MFUN( serialio_getLine )
1886+{
1887+ Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1888+ RETURN->v_string = cereal->getLine();
1889+}
1890+
1891+
1892+CK_DLL_MFUN( serialio_getByte )
1893+{
1894+ Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1895+ RETURN->v_int = cereal->getByte();
1896+}
1897+
1898+
1899+CK_DLL_MFUN( serialio_getBytes )
1900+{
1901+ Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1902+ RETURN->v_object = cereal->getBytes();
1903+}
1904+
1905+
1906+CK_DLL_MFUN( serialio_getInts )
1907+{
1908+ Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1909+ RETURN->v_object = cereal->getInts();
1910+}
1911+
1912+
1913+CK_DLL_MFUN( serialio_setBaudRate )
1914+{
1915+ Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1916+ cereal->setBaudRate(GET_NEXT_INT(ARGS));
1917+ RETURN->v_int = cereal->getBaudRate();
1918+}
1919+
1920+
1921+CK_DLL_MFUN( serialio_getBaudRate )
1922+{
1923+ Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1924+ RETURN->v_int = cereal->getBaudRate();
1925+}
1926+
1927+
1928+CK_DLL_MFUN( serialio_writeByte )
1929+{
1930+ Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1931+ t_CKINT byte = GET_NEXT_INT(ARGS);
1932+ cereal->write(byte, 1);
1933+}
1934+
1935+
1936+CK_DLL_MFUN( serialio_writeBytes )
1937+{
1938+ Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1939+ Chuck_Array4 * arr = (Chuck_Array4 *) GET_NEXT_OBJECT(ARGS);
1940+ cereal->writeBytes(arr);
1941+}
1942+
1943+CK_DLL_MFUN(serialio_canWait)
1944+{
1945+ Chuck_IO_Serial *cereal = (Chuck_IO_Serial *) SELF;
1946+ RETURN->v_int = cereal->can_wait();
1947+}
1948+
1949+
1950+
core/chuck_io.h+204−0
@@ -0,0 +1,204 @@
1+/*----------------------------------------------------------------------------
2+ ChucK Concurrent, On-the-fly Audio Programming Language
3+ Compiler and Virtual Machine
4+
5+ Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6+ http://chuck.stanford.edu/
7+ http://chuck.cs.princeton.edu/
8+
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.
13+
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.
18+
19+ You should have received a copy of the GNU General Public License
20+ along with this program; if not, write to the Free Software
21+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22+ U.S.A.
23+-----------------------------------------------------------------------------*/
24+
25+//-----------------------------------------------------------------------------
26+// name: chuck_io.h
27+// desc: chuck i/o
28+//
29+// authors: Spencer Salazar (spencer@ccrma.stanford.edu)
30+// date: Summer 2012
31+//-----------------------------------------------------------------------------
32+#ifndef __CHUCK_IO_H__
33+#define __CHUCK_IO_H__
34+
35+#include "chuck_oo.h"
36+#include "util_thread.h"
37+#include "util_buffers.h"
38+#include <list>
39+
40+
41+
42+
43+//-----------------------------------------------------------------------------
44+// name: struct Chuck_IO_Serial
45+// desc: chuck serial I/O
46+//-----------------------------------------------------------------------------
47+struct Chuck_IO_Serial : public Chuck_IO
48+{
49+public:
50+ Chuck_IO_Serial( Chuck_VM * vm );
51+ virtual ~Chuck_IO_Serial();
52+
53+ static void shutdown();
54+
55+public:
56+ // meta
57+ virtual t_CKBOOL open( const t_CKUINT i, t_CKINT flags, t_CKUINT baud = CK_BAUD_9600 );
58+ virtual t_CKBOOL open( const std::string & path, t_CKINT flags, t_CKUINT baud = CK_BAUD_9600 );
59+
60+ virtual t_CKBOOL can_wait();
61+
62+ virtual t_CKBOOL good();
63+ virtual void close();
64+ virtual void flush();
65+ virtual t_CKINT mode();
66+ virtual void mode( t_CKINT flag );
67+
68+ // reading
69+ virtual Chuck_String * readLine();
70+ virtual t_CKINT readInt( t_CKINT flags );
71+ virtual t_CKFLOAT readFloat();
72+ virtual t_CKBOOL readString( std::string & str );
73+ virtual t_CKBOOL eof();
74+
75+ // writing
76+ virtual void write( const std::string & val );
77+ virtual void write( t_CKINT val );
78+ virtual void write( t_CKINT val, t_CKINT size );
79+ virtual void writeBytes( Chuck_Array4 * arr );
80+ virtual void write( t_CKFLOAT val );
81+
82+ // serial stuff
83+ virtual t_CKBOOL setBaudRate( t_CKUINT rate );
84+ virtual t_CKUINT getBaudRate();
85+
86+ // async reading
87+ virtual t_CKBOOL readAsync( t_CKUINT type, t_CKUINT num );
88+ virtual Chuck_String * getLine();
89+ virtual t_CKINT getByte();
90+ virtual Chuck_Array * getBytes();
91+ virtual Chuck_Array * getInts();
92+ virtual Chuck_Array * getFloats();
93+ virtual Chuck_String * getString();
94+
95+ static const t_CKUINT TYPE_NONE;
96+ static const t_CKUINT TYPE_BYTE;
97+ static const t_CKUINT TYPE_WORD;
98+ static const t_CKUINT TYPE_INT;
99+ static const t_CKUINT TYPE_FLOAT;
100+ static const t_CKUINT TYPE_STRING;
101+ static const t_CKUINT TYPE_LINE;
102+ static const t_CKUINT TYPE_WRITE;
103+
104+ struct Request
105+ {
106+ t_CKUINT m_type; // type
107+ t_CKUINT m_num; // how many
108+ t_CKUINT m_status;
109+ t_CKUINT m_val; // ISSUE: 64-bit
110+
111+ enum Status
112+ {
113+ RQ_STATUS_PENDING,
114+ RQ_STATUS_SUCCESS,
115+ RQ_STATUS_FAILURE,
116+ RQ_STATUS_INVALID,
117+ RQ_STATUS_EOF,
118+ };
119+ };
120+
121+ virtual t_CKBOOL ready();
122+
123+ // available baud rates
124+ static const t_CKUINT CK_BAUD_2400;
125+ static const t_CKUINT CK_BAUD_4800;
126+ static const t_CKUINT CK_BAUD_9600;
127+ static const t_CKUINT CK_BAUD_19200;
128+ static const t_CKUINT CK_BAUD_38400;
129+ static const t_CKUINT CK_BAUD_7200;
130+ static const t_CKUINT CK_BAUD_14400;
131+ static const t_CKUINT CK_BAUD_28800;
132+ static const t_CKUINT CK_BAUD_57600;
133+ static const t_CKUINT CK_BAUD_76800;
134+ static const t_CKUINT CK_BAUD_115200;
135+ static const t_CKUINT CK_BAUD_230400;
136+
137+protected:
138+
139+ void start_read_thread();
140+ XThread * m_read_thread;
141+ static void *shell_read_cb(void *);
142+ void read_cb();
143+
144+ XThread * m_write_thread;
145+ static void *shell_write_cb(void *);
146+ void write_cb();
147+
148+ void close_int();
149+
150+ t_CKBOOL get_buffer(t_CKINT timeout_ms = 1);
151+ t_CKINT peek_buffer();
152+ t_CKINT pull_buffer();
153+ t_CKINT buffer_bytes_to_tmp(t_CKINT num_bytes);
154+
155+ t_CKBOOL handle_line(Request &);
156+ t_CKBOOL handle_string(Request &);
157+ t_CKBOOL handle_float_ascii(Request &);
158+ t_CKBOOL handle_int_ascii(Request &);
159+ t_CKBOOL handle_byte(Request &);
160+ t_CKBOOL handle_float_binary(Request &);
161+ t_CKBOOL handle_int_binary(Request &);
162+
163+ bool m_do_read_thread;
164+ bool m_do_write_thread;
165+
166+ CircularBuffer<Request> m_asyncRequests;
167+ CircularBuffer<Request> m_asyncResponses;
168+ CBufferSimple * m_event_buffer;
169+
170+ int m_fd;
171+ FILE * m_cfd;
172+
173+ std::string m_path;
174+
175+ unsigned char * m_io_buf;
176+ t_CKUINT m_io_buf_max;
177+ t_CKUINT m_io_buf_available;
178+ t_CKUINT m_io_buf_pos;
179+
180+ unsigned char * m_tmp_buf;
181+ t_CKUINT m_tmp_buf_max;
182+
183+ CircularBuffer<Request> m_asyncWriteRequests;
184+ CircularBuffer<char> m_writeBuffer;
185+
186+ t_CKINT m_flags;
187+ t_CKINT m_iomode; // SYNC or ASYNC
188+ t_CKBOOL m_eof;
189+
190+ t_CKBOOL m_do_exit;
191+
192+ static std::list<Chuck_IO_Serial *> s_serials;
193+
194+ Chuck_VM * m_vmRef;
195+};
196+
197+
198+// initialize
199+t_CKBOOL init_class_serialio( Chuck_Env * env ); // added 1.3.1
200+
201+
202+
203+
204+#endif // __CHUCK_IO_H__
core/chuck_lang.cpp+4861−0
@@ -0,0 +1,4861 @@
1+/*----------------------------------------------------------------------------
2+ ChucK Concurrent, On-the-fly Audio Programming Language
3+ Compiler and Virtual Machine
4+
5+ Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6+ http://chuck.stanford.edu/
7+ http://chuck.cs.princeton.edu/
8+
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.
13+
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.
18+
19+ You should have received a copy of the GNU General Public License
20+ along with this program; if not, write to the Free Software
21+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22+ U.S.A.
23+-----------------------------------------------------------------------------*/
24+
25+//-----------------------------------------------------------------------------
26+// name: chuck_lang.cpp
27+// desc: chuck class library base
28+//
29+// authors: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
30+// Spencer Salazar (spencer@ccrma.stanford.edu)
31+// Ananya Misra (amisra@cs.princeton.edu)
32+// Andrew Schran (aschran@princeton.edu)
33+// date: spring 2005
34+//-----------------------------------------------------------------------------
35+#include "chuck_lang.h"
36+#include "chuck_type.h"
37+#include "chuck_instr.h"
38+#include "chuck_vm.h"
39+#include "chuck_errmsg.h"
40+#include "chuck_ugen.h"
41+#include "chuck_globals.h"
42+#include "hidio_sdl.h"
43+#include "util_string.h"
44+#include "util_serial.h"
45+
46+#ifndef __DISABLE_MIDI__
47+#include "midiio_rtmidi.h"
48+#endif
49+
50+#include <math.h>
51+#include <iostream>
52+#include <iomanip>
53+#include <sstream>
54+using namespace std;
55+
56+// dac tick
57+CK_DLL_TICK(__ugen_tick) { *out = in; return TRUE; }
58+// object string offset
59+static t_CKUINT Object_offset_string = 0;
60+
61+// global
62+static Chuck_String * g_newline = new Chuck_String();
63+
64+
65+
66+
67+
68+
69+
70+//-----------------------------------------------------------------------------
71+// name: init_class_object()
72+// desc: ...
73+//-----------------------------------------------------------------------------
74+t_CKBOOL init_class_object( Chuck_Env * env, Chuck_Type * type )
75+{
76+ Chuck_DL_Func * func = NULL;
77+
78+ // log
79+ EM_log( CK_LOG_SEVERE, "class 'object'" );
80+
81+ const char * doc = "Base class for all class types in ChucK.";
82+
83+ // init as base class
84+ if( !type_engine_import_class_begin( env, type, env->global(), object_ctor, object_dtor, doc ) )
85+ return FALSE;
86+
87+ // add member to hold string
88+ Object_offset_string = type_engine_import_mvar( env, "string", "@string", FALSE );
89+ if( Object_offset_string == CK_INVALID_OFFSET ) goto error;
90+
91+ // add toString()
92+ func = make_new_mfun( "string", "toString", object_toString );
93+ func->doc = "Return a textual description of this object.";
94+ if( !type_engine_import_mfun( env, func ) ) goto error;
95+
96+ // end the class import
97+ type_engine_import_class_end( env );
98+
99+ return TRUE;
100+
101+error:
102+
103+ // end the class import
104+ type_engine_import_class_end( env );
105+
106+ return FALSE;
107+}
108+
109+
110+
111+
112+//-----------------------------------------------------------------------------
113+// name: init_class_ugen()
114+// desc: ...
115+//-----------------------------------------------------------------------------
116+t_CKBOOL init_class_ugen( Chuck_Env * env, Chuck_Type * type )
117+{
118+ Chuck_DL_Func * func = NULL;
119+
120+ EM_log( CK_LOG_SEVERE, "class 'ugen'" );
121+
122+ // add ugen info
123+ type->ugen_info = new Chuck_UGen_Info;
124+ type->ugen_info->add_ref();
125+ type->ugen_info->tick = __ugen_tick;
126+ type->ugen_info->num_ins = 1;
127+ type->ugen_info->num_outs = 1;
128+
129+ const char * doc = "Base class for all UGen types in ChucK.";
130+
131+ // init as base class
132+ // TODO: ctor/dtor, ugen's sometimes created internally?
133+ if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL, doc ) )
134+ return FALSE;
135+
136+ // gain
137+ func = make_new_mfun( "float", "gain", ugen_gain );
138+ func->add_arg( "float", "val" );
139+ func->doc = "Set the gain of the ugen.";
140+ if( !type_engine_import_mfun( env, func ) ) goto error;
141+ func = make_new_mfun( "float", "gain", ugen_cget_gain );
142+ func->doc = "Return the gain of the ugen.";
143+ if( !type_engine_import_mfun( env, func ) ) goto error;
144+
145+/* // next
146+ func = make_new_mfun( "float", "next", ugen_next );
147+ func->add_arg( "float", "val" );
148+ if( !type_engine_import_mfun( env, func ) ) goto error;
149+ func = make_new_mfun( "float", "next", ugen_cget_next );
150+ if( !type_engine_import_mfun( env, func ) ) goto error;
151+*/
152+ // last
153+ func = make_new_mfun( "float", "last", ugen_last );
154+ func->doc = "Return the last sample value of the unit generator.";
155+ if( !type_engine_import_mfun( env, func ) ) goto error;
156+
157+ // op
158+ func = make_new_mfun( "int", "op", ugen_op );
159+ func->add_arg( "int", "val" );
160+ func->doc = "Set the ugen's operation mode. Accepted values are: 1 (sum inputs), 2 (take difference between first input and subsequent inputs), 3 (multiply inputs), 4 (divide first input by subsequent inputs), 0 (do not synthesize audio, output 0) or -1 (passthrough inputs to output).";
161+ if( !type_engine_import_mfun( env, func ) ) goto error;
162+ func = make_new_mfun( "int", "op", ugen_cget_op );
163+ func->doc = "Return the ugen's operation mode.";
164+ if( !type_engine_import_mfun( env, func ) ) goto error;
165+
166+ // add numChannels
167+ func = make_new_mfun( "int", "channels", ugen_numChannels );
168+ func->add_arg( "int", "num" );
169+ func->doc = "Set number of channels. (Not currently supported.)";
170+ if( !type_engine_import_mfun( env, func ) ) goto error;
171+ func = make_new_mfun( "int", "channels", ugen_cget_numChannels );
172+ func->doc = "Return number of channels.";
173+ if( !type_engine_import_mfun( env, func ) ) goto error;
174+
175+ // add chan
176+ func = make_new_mfun( "UGen", "chan", ugen_chan );
177+ func->add_arg( "int", "num" );
178+ func->doc = "Return channel at specified index.";
179+ if( !type_engine_import_mfun( env, func ) ) goto error;
180+
181+ // add isConnectedTo
182+ func = make_new_mfun( "int", "isConnectedTo", ugen_connected );
183+ func->add_arg( "UGen", "right" );
184+ func->doc = "Return true if this ugen's output is connected to the input of the argument. Return false otherwise. ";
185+ if( !type_engine_import_mfun( env, func ) ) goto error;
186+
187+ // end
188+ type_engine_import_class_end( env );
189+
190+ return TRUE;
191+
192+error:
193+
194+ // end the class import
195+ type_engine_import_class_end( env );
196+
197+ return FALSE;
198+}
199+
200+
201+
202+
203+// virtual table offset
204+static t_CKINT uana_offset_blob = 0;
205+//-----------------------------------------------------------------------------
206+// name: init_class_uana()
207+// desc: ...
208+//-----------------------------------------------------------------------------
209+t_CKBOOL init_class_uana( Chuck_Env * env, Chuck_Type * type )
210+{
211+ Chuck_DL_Func * func = NULL;
212+
213+ EM_log( CK_LOG_SEVERE, "class 'uana'" );
214+
215+ // add uana info
216+ type->ugen_info = new Chuck_UGen_Info;
217+ type->ugen_info->add_ref();
218+ type->ugen_info->tick = __ugen_tick;
219+ type->ugen_info->num_ins = 1;
220+ type->ugen_info->num_outs = 1;
221+
222+ const char * doc = "Base class from which all unit analyzers (UAnae) inherit; UAnae (note plural form) can be interconnected via => (standard chuck operator) or via =^ (upchuck operator), specify the the types of and when data is passed between UAnae and UGens. When .upchuck() is invoked on a given UAna, the UAna-chain (UAnae connected via =^) is traversed backwards from the upchucked UAna, and analysis is performed at each UAna along the chain; the updated analysis results are stored in UAnaBlobs.";
223+
224+ // init as base class, type should already know the parent type
225+ // TODO: ctor/dtor, ugen's sometimes created internally?
226+ if( !type_engine_import_class_begin( env, type, env->global(), uana_ctor, uana_dtor, doc ) )
227+ return FALSE;
228+
229+ // add variables
230+ uana_offset_blob = type_engine_import_mvar( env, "UAnaBlob", "m_blob", FALSE );
231+ if( uana_offset_blob == CK_INVALID_OFFSET ) goto error;
232+
233+ // add upchuck
234+ func = make_new_mfun( "UAnaBlob", "upchuck", uana_upchuck );
235+ func->doc = "Initiate analysis at the UAna; returns result.";
236+ if( !type_engine_import_mfun( env, func ) ) goto error;
237+
238+ // add fvals
239+ func = make_new_mfun( "float[]", "fvals", uana_fvals );
240+ func->doc = "Get blob's float array.";
241+ if( !type_engine_import_mfun( env, func ) ) goto error;
242+
243+ // add cvals
244+ func = make_new_mfun( "complex[]", "cvals", uana_cvals );
245+ func->doc = "Get blob's complex array.";
246+ if( !type_engine_import_mfun( env, func ) ) goto error;
247+
248+ // add fval
249+ func = make_new_mfun( "float", "fval", uana_fval );
250+ func->add_arg( "int", "index" );
251+ func->doc = "Get blob's float value at index.";
252+ if( !type_engine_import_mfun( env, func ) ) goto error;
253+
254+ // add cval
255+ func = make_new_mfun( "complex", "cval", uana_cval );
256+ func->add_arg( "int", "index" );
257+ func->doc = "Get blob's complex value at index.";
258+ if( !type_engine_import_mfun( env, func ) ) goto error;
259+
260+ // add isUpConnectedTo
261+ func = make_new_mfun( "int", "isUpConnectedTo", uana_connected );
262+ func->add_arg( "UAna", "right" );
263+ func->doc = "Is connected to another uana via =^?";
264+ if( !type_engine_import_mfun( env, func ) ) goto error;
265+
266+ // TODO: add nonchuck
267+ // func = make_new_mfun( "void", "nonchuck", uana_nonchuck );
268+ // if( !type_engine_import_mfun( env, func ) ) goto error;
269+
270+ // TODO: add event
271+ // func = make_new_mfun( "Event", "event", uana_event );
272+ // if( !type_engine_import_mfun( env, func ) ) goto error;
273+
274+ // end
275+ type_engine_import_class_end( env );
276+
277+ return TRUE;
278+
279+error:
280+
281+ // end the class import
282+ type_engine_import_class_end( env );
283+
284+ return FALSE;
285+}
286+
287+
288+
289+
290+// virtual table offset
291+static t_CKINT uanablob_offset_when = 0;
292+static t_CKINT uanablob_offset_fvals = 0;
293+static t_CKINT uanablob_offset_cvals = 0;
294+//-----------------------------------------------------------------------------
295+// name: init_class_blob()
296+// desc: ...
297+//-----------------------------------------------------------------------------
298+t_CKBOOL init_class_blob( Chuck_Env * env, Chuck_Type * type )
299+{
300+ Chuck_DL_Func * func = NULL;
301+ // Chuck_Value * value = NULL;
302+
303+ // log
304+ EM_log( CK_LOG_SEVERE, "class 'uanablob'" );
305+
306+ const char * doc = "This object contains results associated with UAna analysis. There is a UAnaBlob associated with every UAna. As a UAna is upchucked, the result is stored in the UAnaBlob's floating point vector and/or complex vector. The intended interpretation of the results depends on the specific UAna.";
307+
308+ // init class
309+ // TODO: ctor/dtor
310+ if( !type_engine_import_class_begin( env, type, env->global(), uanablob_ctor, uanablob_dtor, doc ) )
311+ return FALSE;
312+
313+ // add variables
314+ uanablob_offset_when = type_engine_import_mvar( env, "time", "m_when", FALSE );
315+ if( uanablob_offset_when == CK_INVALID_OFFSET ) goto error;
316+ uanablob_offset_fvals = type_engine_import_mvar( env, "float[]", "m_fvals", FALSE );
317+ if( uanablob_offset_fvals == CK_INVALID_OFFSET ) goto error;
318+ uanablob_offset_cvals = type_engine_import_mvar( env, "complex[]", "m_cvals", FALSE );
319+ if( uanablob_offset_cvals == CK_INVALID_OFFSET ) goto error;
320+
321+ // add when
322+ func = make_new_mfun( "time", "when", uanablob_when );
323+ func->doc = "Get the time when blob was last upchucked.";
324+ if( !type_engine_import_mfun( env, func ) ) goto error;
325+
326+ // add fvals
327+ func = make_new_mfun( "float[]", "fvals", uanablob_fvals );
328+ func->doc = "Get blob's float array.";
329+ if( !type_engine_import_mfun( env, func ) ) goto error;
330+
331+ // add cvals
332+ func = make_new_mfun( "complex[]", "cvals", uanablob_cvals );
333+ func->doc = "Get blob's complex array.";
334+ if( !type_engine_import_mfun( env, func ) ) goto error;
335+
336+ // add fval
337+ func = make_new_mfun( "float", "fval", uanablob_fval );
338+ func->add_arg( "int", "index" );
339+ func->doc = "Get blob's float value at index.";
340+ if( !type_engine_import_mfun( env, func ) ) goto error;
341+
342+ // add cval
343+ func = make_new_mfun( "complex", "cval", uanablob_cval );
344+ func->add_arg( "int", "index" );
345+ func->doc = "Get blob's complex value at index.";
346+ if( !type_engine_import_mfun( env, func ) ) goto error;
347+
348+ // end class import
349+ type_engine_import_class_end( env );
350+
351+ // done
352+ return TRUE;
353+
354+error:
355+
356+ // end class import
357+ type_engine_import_class_end( env );
358+
359+ // error
360+ return FALSE;
361+}
362+
363+
364+
365+
366+// static t_CKUINT event_offset_data = 0;
367+//-----------------------------------------------------------------------------
368+// name: init_class_event()
369+// desc: ...
370+//-----------------------------------------------------------------------------
371+t_CKBOOL init_class_event( Chuck_Env * env, Chuck_Type * type )
372+{
373+ Chuck_DL_Func * func = NULL;
374+ Chuck_Value * value = NULL;
375+
376+ // log
377+ EM_log( CK_LOG_SEVERE, "class 'event'" );
378+
379+ const char *doc = "The Event class allows exact synchronization across an arbitrary number of shreds.";
380+
381+ // init as base class
382+ // TODO: ctor/dtor?
383+ if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL, doc ) )
384+ return FALSE;
385+
386+ // add signal()
387+ func = make_new_mfun( "void", "signal", event_signal );
388+ func->doc = "Signal one shred that is waiting on this event. ";
389+ if( !type_engine_import_mfun( env, func ) ) goto error;
390+
391+ // add broadcast()
392+ func = make_new_mfun( "void", "broadcast", event_broadcast );
393+ func->doc = "Signal all shreds that are waiting on this event.";
394+ if( !type_engine_import_mfun( env, func ) ) goto error;
395+
396+ // add wait()
397+ func = make_new_mfun( "void", "wait", event_wait );
398+ func->add_arg( "Shred", "me" );
399+ func->doc = "(Currently unsupported.)";
400+ if( !type_engine_import_mfun( env, func ) ) goto error;
401+
402+ // add can_wait()
403+ func = make_new_mfun( "int", "can_wait", event_can_wait );
404+ func->doc = "Whether or not the event can be waited on. Currently always returns true.";
405+ if( !type_engine_import_mfun( env, func ) ) goto error;
406+
407+ // end the class import
408+ type_engine_import_class_end( env );
409+
410+ // find the offset for can_wait
411+ value = type_engine_find_value( type, "can_wait" );
412+ assert( value != NULL );
413+ assert( value->func_ref != NULL );
414+ // remember it
415+ Chuck_Event::our_can_wait = value->func_ref->vt_index;
416+
417+ return TRUE;
418+
419+error:
420+
421+ // end the class import
422+ type_engine_import_class_end( env );
423+
424+ return FALSE;
425+}
426+
427+
428+
429+
430+// static t_CKUINT shred_offset_args = 0;
431+//-----------------------------------------------------------------------------
432+// name: init_class_shred()
433+// desc: ...
434+//-----------------------------------------------------------------------------
435+t_CKBOOL init_class_shred( Chuck_Env * env, Chuck_Type * type )
436+{
437+ // init as base class
438+ Chuck_DL_Func * func = NULL;
439+
440+ // log
441+ EM_log( CK_LOG_SEVERE, "class 'shred'" );
442+
443+ const char *doc = "Shred facilitates various operations and interactions with shreds running in the ChucK virtual machine.";
444+
445+ // init as base class
446+ // TODO: ctor/dtor?
447+ if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL, doc ) )
448+ return FALSE;
449+
450+ // add dtor
451+ // not
452+
453+ // add fromId()
454+ func = make_new_sfun( "Shred", "fromId", shred_fromId );
455+ func->add_arg( "int", "id" );
456+ func->doc = "Return a Shred object corresponding to the provided shred ID.";
457+ if( !type_engine_import_sfun( env, func ) ) goto error;
458+
459+ // add clone()
460+ func = make_new_mfun( "void", "clone", shred_clone );
461+ if( !type_engine_import_mfun( env, func ) ) goto error;
462+
463+ // add exit()
464+ func = make_new_mfun( "void", "exit", shred_exit );
465+ func->doc = "Immediately halt the shred's operation and remove it from the virtual machine.";
466+ if( !type_engine_import_mfun( env, func ) ) goto error;
467+
468+ // add id()
469+ func = make_new_mfun( "int", "id", shred_id );
470+ func->doc = "Return the unique numeric id of the shred.";
471+ if( !type_engine_import_mfun( env, func ) ) goto error;
472+
473+ // add yield()
474+ func = make_new_mfun( "void", "yield", shred_yield );
475+ func->doc = "Cause the shred to temporarily stop processing, allowing other scheduled shreds to run as needed.";
476+ if( !type_engine_import_mfun( env, func ) ) goto error;
477+
478+ // add running()
479+ func = make_new_mfun( "int", "running", shred_running );
480+ func->doc = "Return true if the shred is currently running; false otherwise.";
481+ if( !type_engine_import_mfun( env, func ) ) goto error;
482+
483+ // add done()
484+ func = make_new_mfun( "int", "done", shred_done );
485+ func->doc = "Return true if the shred is done processing; false otherwise.";
486+ if( !type_engine_import_mfun( env, func ) ) goto error;
487+
488+ // add nargs()
489+ // func = make_new_mfun( "int", "numArgs", shred_numArgs );
490+ // if( !type_engine_import_mfun( env, func ) ) goto error;
491+
492+ // add nargs()
493+ func = make_new_mfun( "int", "args", shred_numArgs );
494+ func->doc = "Return the number of arguments provided to the shred.";
495+ if( !type_engine_import_mfun( env, func ) ) goto error;
496+
497+ // add arg()
498+ // func = make_new_mfun( "string", "getArg", shred_getArg );
499+ // func->add_arg( "int", "index" );
500+ // if( !type_engine_import_mfun( env, func ) ) goto error;
501+
502+ // add arg()
503+ func = make_new_mfun( "string", "arg", shred_getArg );
504+ func->add_arg( "int", "index" );
505+ func->doc = "Return the argument at the specified index.";
506+ if( !type_engine_import_mfun( env, func ) ) goto error;
507+
508+ // add sourcePath() (added 1.3.0.0)
509+ func = make_new_mfun( "string", "sourcePath", shred_sourcePath );
510+ func->doc = "Return the path of the source code file from which this shred's code is derived.";
511+ if( !type_engine_import_mfun( env, func ) ) goto error;
512+
513+ // add path() (added 1.3.2.0)
514+ func = make_new_mfun( "string", "path", shred_sourcePath );
515+ func->doc = "Return the file path of the source code file from which this shred's code is derived (same as .sourcePath()).";
516+ if( !type_engine_import_mfun( env, func ) ) goto error;
517+
518+ // add sourceDir() (added 1.3.0.0)
519+ func = make_new_mfun( "string", "sourceDir", shred_sourceDir );
520+ func->doc = "Return the enclosing directory of the source code file from which this shred's code is derived.";
521+ if( !type_engine_import_mfun( env, func ) ) goto error;
522+
523+ // add dir() (added 1.3.2.0)
524+ func = make_new_mfun( "string", "dir", shred_sourceDir );
525+ func->doc = "Return the enclosing directory of the source code file from which this shred's code is derived (same as .sourceDir()).";
526+ if( !type_engine_import_mfun( env, func ) ) goto error;
527+
528+ // add dir() (added 1.3.2.0, ge)
529+ func = make_new_mfun( "string", "dir", shred_sourceDir2 );
530+ func->add_arg( "int", "levelsUp" );
531+ func->doc = "Return the enclosing directory, the specified number of parent directories up.";
532+ if( !type_engine_import_mfun( env, func ) ) goto error;
533+
534+ // end the class import
535+ type_engine_import_class_end( env );
536+
537+ return TRUE;
538+
539+error:
540+
541+ // end the class import
542+ type_engine_import_class_end( env );
543+
544+ return FALSE;
545+}
546+
547+
548+
549+
550+//-----------------------------------------------------------------------------
551+// name: init_class_vec3()
552+// desc: initialize primitive type vec3
553+//-----------------------------------------------------------------------------
554+t_CKBOOL init_class_vec3( Chuck_Env * env, Chuck_Type * type )
555+{
556+ // init as base class
557+ Chuck_DL_Func * func = NULL;
558+
559+ // log
560+ EM_log( CK_LOG_SEVERE, "class 'vec3' (primitive)" );
561+
562+ // document
563+ const char *doc = "vec3 is a primitive type for a 3-dimensional vector; potentially useful for 3D coordinates, RGB color, or as a value/goal/slew interpolator.";
564+
565+ // init as base class
566+ if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL, doc ) )
567+ return FALSE;
568+
569+ // add set(float,float,float)
570+ func = make_new_mfun( "void", "set", vec3_set );
571+ func->add_arg( "float", "x" );
572+ func->add_arg( "float", "y" );
573+ func->add_arg( "float", "z" );
574+ if( !type_engine_import_mfun( env, func ) ) goto error;
575+
576+ // add setAll(float)
577+ func = make_new_mfun( "void", "setAll", vec3_setAll );
578+ func->add_arg( "float", "value" );
579+ if( !type_engine_import_mfun( env, func ) ) goto error;
580+
581+ // add magnitude()
582+ func = make_new_mfun( "float", "magnitude", vec3_magnitude );
583+ if( !type_engine_import_mfun( env, func ) ) goto error;
584+
585+ // add normalize()
586+ func = make_new_mfun( "void", "normalize", vec3_normalize );
587+ if( !type_engine_import_mfun( env, func ) ) goto error;
588+
589+ // add interp()
590+ func = make_new_mfun( "float", "interp", vec3_interp );
591+ if( !type_engine_import_mfun( env, func ) ) goto error;
592+
593+ // add interp( float )
594+ func = make_new_mfun( "float", "interp", vec3_interp_delta_float );
595+ func->add_arg( "float", "delta" );
596+ if( !type_engine_import_mfun( env, func ) ) goto error;
597+
598+ // add interp( dur )
599+ func = make_new_mfun( "float", "interp", vec3_interp_delta_dur );
600+ func->add_arg( "dur", "delta" );
601+ if( !type_engine_import_mfun( env, func ) ) goto error;
602+
603+ // add update( float )
604+ func = make_new_mfun( "void", "update", vec3_update_goal );
605+ func->add_arg( "float", "goal" );
606+ if( !type_engine_import_mfun( env, func ) ) goto error;
607+
608+ // add update( float, float )
609+ func = make_new_mfun( "void", "update", vec3_update_goal_slew );
610+ func->add_arg( "float", "goal" );
611+ func->add_arg( "float", "slew" );
612+ if( !type_engine_import_mfun( env, func ) ) goto error;
613+
614+ // add update( float )
615+ func = make_new_mfun( "void", "updateSet", vec3_updateSet_goalAndValue );
616+ func->add_arg( "float", "goalAndValue" );
617+ if( !type_engine_import_mfun( env, func ) ) goto error;
618+
619+ // add update( float, float )
620+ func = make_new_mfun( "void", "updateSet", vec3_updateSet_goalAndValue_slew );
621+ func->add_arg( "float", "goal" );
622+ func->add_arg( "float", "slew" );
623+ if( !type_engine_import_mfun( env, func ) ) goto error;
624+
625+ // end the class import
626+ type_engine_import_class_end( env );
627+
628+ return TRUE;
629+
630+error:
631+ // end the class import
632+ type_engine_import_class_end( env );
633+
634+ return FALSE;
635+}
636+
637+
638+
639+
640+//-----------------------------------------------------------------------------
641+// name: init_class_vec4()
642+// desc: initialize primitive type vec4
643+//-----------------------------------------------------------------------------
644+t_CKBOOL init_class_vec4( Chuck_Env * env, Chuck_Type * type )
645+{
646+ // init as base class
647+ Chuck_DL_Func * func = NULL;
648+
649+ // log
650+ EM_log( CK_LOG_SEVERE, "class 'vec4' (primitive)" );
651+
652+ // document
653+ const char *doc = "vec4 is a primitive type for a 4-dimensional vector; potentially useful for 4D coordinatesm and RGBA color.";
654+
655+ // init as base class
656+ if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL, doc ) )
657+ return FALSE;
658+
659+ // add set(float,float,float)
660+ func = make_new_mfun( "void", "set", vec4_set );
661+ func->add_arg( "float", "x" );
662+ func->add_arg( "float", "y" );
663+ func->add_arg( "float", "z" );
664+ func->add_arg( "float", "w" );
665+ if( !type_engine_import_mfun( env, func ) ) goto error;
666+
667+ // add setAll(float)
668+ func = make_new_mfun( "void", "setAll", vec4_setAll );
669+ func->add_arg( "float", "value" );
670+ if( !type_engine_import_mfun( env, func ) ) goto error;
671+
672+ // add magnitude()
673+ func = make_new_mfun( "float", "magnitude", vec4_magnitude );
674+ if( !type_engine_import_mfun( env, func ) ) goto error;
675+
676+ // add normalize()
677+ func = make_new_mfun( "void", "normalize", vec4_normalize );
678+ if( !type_engine_import_mfun( env, func ) ) goto error;
679+
680+ // end the class import
681+ type_engine_import_class_end( env );
682+
683+ return TRUE;
684+
685+error:
686+ // end the class import
687+ type_engine_import_class_end( env );
688+
689+ return FALSE;
690+}
691+
692+
693+
694+
695+//-----------------------------------------------------------------------------
696+// name: init_class_io()
697+// desc: ...
698+//-----------------------------------------------------------------------------
699+t_CKBOOL init_class_io( Chuck_Env * env, Chuck_Type * type )
700+{
701+ // init as base class
702+ Chuck_DL_Func * func = NULL;
703+
704+ // log
705+ EM_log( CK_LOG_SEVERE, "class 'io'" );
706+
707+ // init as base class
708+ // TODO: ctor/dtor?
709+ // TODO: replace dummy with pure function
710+ if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL ) )
711+ return FALSE;
712+
713+ // add good()
714+ func = make_new_mfun( "int", "good", io_dummy );
715+ if( !type_engine_import_mfun( env, func ) ) goto error;
716+
717+ // add close()
718+ func = make_new_mfun( "void", "close", io_dummy );
719+ if( !type_engine_import_mfun( env, func ) ) goto error;
720+
721+ // add flush()
722+ func = make_new_mfun( "void", "flush", io_dummy );
723+ if( !type_engine_import_mfun( env, func ) ) goto error;
724+
725+ // add mode(int)
726+ func = make_new_mfun( "int", "mode", io_dummy );
727+ func->add_arg( "int", "flag" );
728+ if( !type_engine_import_mfun( env, func ) ) goto error;
729+
730+ // add mode()
731+ func = make_new_mfun( "int", "mode", io_dummy );
732+ if( !type_engine_import_mfun( env, func ) ) goto error;
733+
734+ // TODO: add this later?
735+ // add read()
736+ // func = make_new_mfun( "string", "read", io_dummy );
737+ // func->add_arg( "int", "length" );
738+ // if( !type_engine_import_mfun( env, func ) ) goto error;
739+
740+ // add readLine()
741+ func = make_new_mfun( "string", "readLine", io_dummy );
742+ if( !type_engine_import_mfun( env, func ) ) goto error;
743+
744+ // add readInt()
745+ func = make_new_mfun( "int", "readInt", io_dummy );
746+ func->add_arg( "int", "flags" );
747+ if( !type_engine_import_mfun( env, func ) ) goto error;
748+
749+ // add readFloat()
750+ // func = make_new_mfun( "float", "readFloat", io_dummy );
751+ // if( !type_engine_import_mfun( env, func ) ) goto error;
752+
753+ // add eof()
754+ func = make_new_mfun( "int", "eof", io_dummy );
755+ if( !type_engine_import_mfun( env, func ) ) goto error;
756+
757+ // add more()
758+ func = make_new_mfun( "int", "more", io_dummy );
759+ if( !type_engine_import_mfun( env, func ) ) goto error;
760+
761+ // add write(string)
762+ func = make_new_mfun( "void", "write", io_dummy );
763+ func->add_arg( "string", "val" );
764+ if( !type_engine_import_mfun( env, func ) ) goto error;
765+
766+ // add write(int)
767+ func = make_new_mfun( "void", "write", io_dummy );
768+ func->add_arg( "int", "val" );
769+ if( !type_engine_import_mfun( env, func ) ) goto error;
770+
771+ // add write(float)
772+ func = make_new_mfun( "void", "write", io_dummy );
773+ func->add_arg( "float", "val" );
774+ if( !type_engine_import_mfun( env, func ) ) goto error;
775+
776+ // add newline
777+ func = make_new_sfun( "string", "newline", io_newline );
778+ if( !type_engine_import_sfun( env, func ) ) goto error;
779+ func = make_new_sfun( "string", "nl", io_newline );
780+ if( !type_engine_import_sfun( env, func ) ) goto error;
781+ func = make_new_sfun( "string", "newlineEx2VistaHWNDVisualFoxProA", io_newline );
782+ if( !type_engine_import_sfun( env, func ) ) goto error;
783+ initialize_object( g_newline, env->t_string );
784+ g_newline->set( "\n" );
785+
786+ // add READ_INT32
787+ if( !type_engine_import_svar( env, "int", "READ_INT32",
788+ TRUE, (t_CKUINT)&Chuck_IO::INT32 ) ) goto error;
789+
790+ // add READ_INT16
791+ if( !type_engine_import_svar( env, "int", "READ_INT16",
792+ TRUE, (t_CKUINT)&Chuck_IO::INT16 ) ) goto error;
793+
794+ // add READ_INT8
795+ if( !type_engine_import_svar( env, "int", "READ_INT8",
796+ TRUE, (t_CKUINT)&Chuck_IO::INT8 ) ) goto error;
797+
798+ // add INT32
799+ if( !type_engine_import_svar( env, "int", "INT32",
800+ TRUE, (t_CKUINT)&Chuck_IO::INT32 ) ) goto error;
801+
802+ // add INT16
803+ if( !type_engine_import_svar( env, "int", "INT16",
804+ TRUE, (t_CKUINT)&Chuck_IO::INT16 ) ) goto error;
805+
806+ // add INT8
807+ if( !type_engine_import_svar( env, "int", "INT8",
808+ TRUE, (t_CKUINT)&Chuck_IO::INT8 ) ) goto error;
809+
810+ // add MODE_SYNC
811+ if( !type_engine_import_svar( env, "int", "MODE_SYNC",
812+ TRUE, (t_CKUINT)&Chuck_IO::MODE_SYNC ) ) goto error;
813+
814+ // add MODE_ASYNC
815+ if( !type_engine_import_svar( env, "int", "MODE_ASYNC",
816+ TRUE, (t_CKUINT)&Chuck_IO::MODE_ASYNC ) ) goto error;
817+
818+ // end the class import
819+ type_engine_import_class_end( env );
820+
821+ return TRUE;
822+
823+error:
824+
825+ // end the class import
826+ type_engine_import_class_end( env );
827+
828+ return FALSE;
829+}
830+
831+
832+
833+
834+//-----------------------------------------------------------------------------
835+// name: init_class_fileio()
836+// desc: ...
837+//-----------------------------------------------------------------------------
838+t_CKBOOL init_class_fileio( Chuck_Env * env, Chuck_Type * type )
839+{
840+ // init as base class
841+ Chuck_DL_Func * func = NULL;
842+
843+ // log
844+ EM_log( CK_LOG_SEVERE, "class 'fileio'" );
845+
846+ // init as base class
847+ // TODO: ctor/dtor?
848+ // TODO: replace dummy with pure function
849+ if( !type_engine_import_class_begin( env, type, env->global(), fileio_ctor, fileio_dtor ) )
850+ return FALSE;
851+
852+ // add open(string)
853+ func = make_new_mfun( "int", "open", fileio_open );
854+ func->add_arg( "string", "path" );
855+ if( !type_engine_import_mfun( env, func ) ) goto error;
856+
857+ // add open(string, flags)
858+ func = make_new_mfun( "int", "open", fileio_openflags );
859+ func->add_arg( "string", "path" );
860+ func->add_arg( "int", "flags" );
861+ if( !type_engine_import_mfun( env, func ) ) goto error;
862+
863+ // add good()
864+ func = make_new_mfun( "int", "good", fileio_good );
865+ if( !type_engine_import_mfun( env, func ) ) goto error;
866+
867+ // add close()
868+ func = make_new_mfun( "void", "close", fileio_close );
869+ if( !type_engine_import_mfun( env, func ) ) goto error;
870+
871+ // add flush()
872+ func = make_new_mfun( "void", "flush", fileio_flush );
873+ if( !type_engine_import_mfun( env, func ) ) goto error;
874+
875+ // add mode()
876+ func = make_new_mfun( "int", "mode", fileio_getmode );
877+ if( !type_engine_import_mfun( env, func ) ) goto error;
878+
879+ // add mode(int)
880+ func = make_new_mfun( "int", "mode", fileio_setmode );
881+ func->add_arg( "int", "flag" );
882+ if( !type_engine_import_mfun( env, func ) ) goto error;
883+
884+ // add size()
885+ func = make_new_mfun( "int", "size", fileio_size );
886+ if( !type_engine_import_mfun( env, func ) ) goto error;
887+
888+ // add seek(int)
889+ func = make_new_mfun( "void", "seek", fileio_seek );
890+ func->add_arg( "int", "pos" );
891+ if( !type_engine_import_mfun( env, func ) ) goto error;
892+
893+ // add tell()
894+ func = make_new_mfun( "int", "tell", fileio_tell );
895+ if( !type_engine_import_mfun( env, func ) ) goto error;
896+
897+ // add isDir()
898+ func = make_new_mfun( "int", "isDir", fileio_isdir );
899+ if( !type_engine_import_mfun( env, func ) ) goto error;
900+
901+ // add dirList()
902+ func = make_new_mfun( "string[]", "dirList", fileio_dirlist );
903+ if( !type_engine_import_mfun( env, func ) ) goto error;
904+
905+ // add read()
906+ // func = make_new_mfun( "string", "read", fileio_read );
907+ // func->add_arg( "int", "length" );
908+ // if( !type_engine_import_mfun( env, func ) ) goto error;
909+
910+ // add readLine()
911+ func = make_new_mfun( "string", "readLine", fileio_readline );
912+ if( !type_engine_import_mfun( env, func ) ) goto error;
913+
914+ // add readInt()
915+ // func = make_new_mfun( "int", "readInt", fileio_readint );
916+ // if( !type_engine_import_mfun( env, func ) ) goto error;
917+
918+ // add readInt(int)
919+ func = make_new_mfun( "int", "readInt", fileio_readintflags );
920+ func->add_arg( "int", "flags" );
921+ if( !type_engine_import_mfun( env, func ) ) goto error;
922+
923+ // add readFloat()
924+ // func = make_new_mfun( "float", "readFloat", fileio_readfloat );
925+ // if( !type_engine_import_mfun( env, func ) ) goto error;
926+
927+ // add eof()
928+ func = make_new_mfun( "int", "eof", fileio_eof );
929+ if( !type_engine_import_mfun( env, func ) ) goto error;
930+
931+ // add more()
932+ func = make_new_mfun( "int", "more", fileio_more );
933+ if( !type_engine_import_mfun( env, func ) ) goto error;
934+
935+ // add write(string)
936+ func = make_new_mfun( "void", "write", fileio_writestring );
937+ func->add_arg( "string", "val" );
938+ if( !type_engine_import_mfun( env, func ) ) goto error;
939+
940+ // add write(int)
941+ func = make_new_mfun( "void", "write", fileio_writeint );
942+ func->add_arg( "int", "val" );
943+ if( !type_engine_import_mfun( env, func ) ) goto error;
944+
945+ // add write(int,flags)
946+ func = make_new_mfun( "void", "write", fileio_writeintflags );
947+ func->add_arg( "int", "val" );
948+ func->add_arg( "int", "flags" );
949+ if( !type_engine_import_mfun( env, func ) ) goto error;
950+
951+ // add write(float)
952+ func = make_new_mfun( "void", "write", fileio_writefloat );
953+ func->add_arg( "float", "val" );
954+ if( !type_engine_import_mfun( env, func ) ) goto error;
955+
956+ // add FLAG_READ_WRITE
957+ if( !type_engine_import_svar( env, "int", "READ_WRITE",
958+ TRUE, (t_CKUINT)&Chuck_IO_File::FLAG_READ_WRITE ) ) goto error;
959+
960+ // add FLAG_READONLY
961+ if( !type_engine_import_svar( env, "int", "READ",
962+ TRUE, (t_CKUINT)&Chuck_IO_File::FLAG_READONLY ) ) goto error;
963+
964+ // add FLAG_WRITEONLY
965+ if( !type_engine_import_svar( env, "int", "WRITE",
966+ TRUE, (t_CKUINT)&Chuck_IO_File::FLAG_WRITEONLY ) ) goto error;
967+
968+ // add FLAG_APPEND
969+ if( !type_engine_import_svar( env, "int", "APPEND",
970+ TRUE, (t_CKUINT)&Chuck_IO_File::FLAG_APPEND ) ) goto error;
971+
972+ // add TYPE_ASCII
973+ if( !type_engine_import_svar( env, "int", "ASCII",
974+ TRUE, (t_CKUINT)&Chuck_IO_File::TYPE_ASCII ) ) goto error;
975+
976+ // add TYPE_BINARY
977+ if( !type_engine_import_svar( env, "int", "BINARY",
978+ TRUE, (t_CKUINT)&Chuck_IO_File::TYPE_BINARY ) ) goto error;
979+
980+ // end the class import
981+ type_engine_import_class_end( env );
982+
983+ return TRUE;
984+
985+error:
986+
987+ // end the class import
988+ type_engine_import_class_end( env );
989+
990+ return FALSE;
991+}
992+
993+
994+
995+
996+//-----------------------------------------------------------------------------
997+// name: init_class_chout()
998+// desc: added 1.3.0.0 as full class
999+//-----------------------------------------------------------------------------
1000+t_CKBOOL init_class_chout( Chuck_Env * env, Chuck_Type * type )
1001+{
1002+ // init as base class
1003+ Chuck_DL_Func * func = NULL;
1004+
1005+ // log
1006+ EM_log( CK_LOG_SEVERE, "class 'chout'" );
1007+
1008+ // TODO: ctor/dtor?
1009+ if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL ) )
1010+ return FALSE;
1011+
1012+ // add good()
1013+ func = make_new_mfun( "int", "good", chout_good );
1014+ if( !type_engine_import_mfun( env, func ) ) goto error;
1015+
1016+ // add close()
1017+ func = make_new_mfun( "void", "close", chout_close );
1018+ if( !type_engine_import_mfun( env, func ) ) goto error;
1019+
1020+ // add flush()
1021+ func = make_new_mfun( "void", "flush", chout_flush );
1022+ if( !type_engine_import_mfun( env, func ) ) goto error;
1023+
1024+ // add mode()
1025+ func = make_new_mfun( "int", "mode", chout_getmode );
1026+ if( !type_engine_import_mfun( env, func ) ) goto error;
1027+
1028+ // add mode(int)
1029+ func = make_new_mfun( "int", "mode", chout_setmode );
1030+ func->add_arg( "int", "flag" );
1031+ if( !type_engine_import_mfun( env, func ) ) goto error;
1032+
1033+ // add readLine()
1034+ func = make_new_mfun( "string", "readLine", chout_readline );
1035+ if( !type_engine_import_mfun( env, func ) ) goto error;
1036+
1037+ // add readInt()
1038+ // func = make_new_mfun( "int", "readInt", chout_readint );
1039+ // if( !type_engine_import_mfun( env, func ) ) goto error;
1040+
1041+ // add readInt(int)
1042+ func = make_new_mfun( "int", "readInt", chout_readintflags );
1043+ func->add_arg( "int", "flags" );
1044+ if( !type_engine_import_mfun( env, func ) ) goto error;
1045+
1046+ // add readFloat()
1047+ // func = make_new_mfun( "float", "readFloat", chout_readfloat );
1048+ // if( !type_engine_import_mfun( env, func ) ) goto error;
1049+
1050+ // add eof()
1051+ func = make_new_mfun( "int", "eof", chout_eof );
1052+ if( !type_engine_import_mfun( env, func ) ) goto error;
1053+
1054+ // add more()
1055+ func = make_new_mfun( "int", "more", chout_more );
1056+ if( !type_engine_import_mfun( env, func ) ) goto error;
1057+
1058+ // add write(string)
1059+ func = make_new_mfun( "void", "write", chout_writestring );
1060+ func->add_arg( "string", "val" );
1061+ if( !type_engine_import_mfun( env, func ) ) goto error;
1062+
1063+ // add write(int)
1064+ func = make_new_mfun( "void", "write", chout_writeint );
1065+ func->add_arg( "int", "val" );
1066+ if( !type_engine_import_mfun( env, func ) ) goto error;
1067+
1068+ // add write(float)
1069+ func = make_new_mfun( "void", "write", chout_writefloat );
1070+ func->add_arg( "float", "val" );
1071+ if( !type_engine_import_mfun( env, func ) ) goto error;
1072+
1073+ // end the class import
1074+ type_engine_import_class_end( env );
1075+
1076+ return TRUE;
1077+
1078+error:
1079+
1080+ // end the class import
1081+ type_engine_import_class_end( env );
1082+
1083+ return FALSE;
1084+}
1085+
1086+
1087+
1088+
1089+//-----------------------------------------------------------------------------
1090+// name: init_class_cherr()
1091+// desc: added 1.3.0.0 -- as full class
1092+//-----------------------------------------------------------------------------
1093+t_CKBOOL init_class_cherr( Chuck_Env * env, Chuck_Type * type )
1094+{
1095+ // init as base class
1096+ Chuck_DL_Func * func = NULL;
1097+
1098+ // log
1099+ EM_log( CK_LOG_SEVERE, "class 'cherr'" );
1100+
1101+ // TODO: ctor/dtor?
1102+ if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL ) )
1103+ return FALSE;
1104+
1105+ // add good()
1106+ func = make_new_mfun( "int", "good", cherr_good );
1107+ if( !type_engine_import_mfun( env, func ) ) goto error;
1108+
1109+ // add close()
1110+ func = make_new_mfun( "void", "close", cherr_close );
1111+ if( !type_engine_import_mfun( env, func ) ) goto error;
1112+
1113+ // add flush()
1114+ func = make_new_mfun( "void", "flush", cherr_flush );
1115+ if( !type_engine_import_mfun( env, func ) ) goto error;
1116+
1117+ // add mode()
1118+ func = make_new_mfun( "int", "mode", cherr_getmode );
1119+ if( !type_engine_import_mfun( env, func ) ) goto error;
1120+
1121+ // add mode(int)
1122+ func = make_new_mfun( "int", "mode", cherr_setmode );
1123+ func->add_arg( "int", "flag" );
1124+ if( !type_engine_import_mfun( env, func ) ) goto error;
1125+
1126+ // add readLine()
1127+ func = make_new_mfun( "string", "readLine", cherr_readline );
1128+ if( !type_engine_import_mfun( env, func ) ) goto error;
1129+
1130+ // add readInt()
1131+ // func = make_new_mfun( "int", "readInt", cherr_readint );
1132+ // if( !type_engine_import_mfun( env, func ) ) goto error;
1133+
1134+ // add readInt(int)
1135+ func = make_new_mfun( "int", "readInt", cherr_readintflags );
1136+ func->add_arg( "int", "flags" );
1137+ if( !type_engine_import_mfun( env, func ) ) goto error;
1138+
1139+ // add readFloat()
1140+ // func = make_new_mfun( "float", "readFloat", cherr_readfloat );
1141+ // if( !type_engine_import_mfun( env, func ) ) goto error;
1142+
1143+ // add eof()
1144+ func = make_new_mfun( "int", "eof", cherr_eof );
1145+ if( !type_engine_import_mfun( env, func ) ) goto error;
1146+
1147+ // add more()
1148+ func = make_new_mfun( "int", "more", cherr_more );
1149+ if( !type_engine_import_mfun( env, func ) ) goto error;
1150+
1151+ // add write(string)
1152+ func = make_new_mfun( "void", "write", cherr_writestring );
1153+ func->add_arg( "string", "val" );
1154+ if( !type_engine_import_mfun( env, func ) ) goto error;
1155+
1156+ // add write(int)
1157+ func = make_new_mfun( "void", "write", cherr_writeint );
1158+ func->add_arg( "int", "val" );
1159+ if( !type_engine_import_mfun( env, func ) ) goto error;
1160+
1161+ // add write(float)
1162+ func = make_new_mfun( "void", "write", cherr_writefloat );
1163+ func->add_arg( "float", "val" );
1164+ if( !type_engine_import_mfun( env, func ) ) goto error;
1165+
1166+ // end the class import
1167+ type_engine_import_class_end( env );
1168+
1169+ return TRUE;
1170+
1171+error:
1172+
1173+ // end the class import
1174+ type_engine_import_class_end( env );
1175+
1176+ return FALSE;
1177+}
1178+
1179+
1180+//-----------------------------------------------------------------------------
1181+// name: init_class_string()
1182+// desc: ...
1183+//-----------------------------------------------------------------------------
1184+t_CKBOOL init_class_string( Chuck_Env * env, Chuck_Type * type )
1185+{
1186+ // init as base class
1187+ Chuck_DL_Func * func = NULL;
1188+
1189+ // log
1190+ EM_log( CK_LOG_SEVERE, "class 'string'" );
1191+
1192+ const char * doc = "The string class holds textual data as a sequence of characters, and provides a number of functions for manipulating text.";
1193+
1194+ // init as base class
1195+ // TODO: ctor/dtor
1196+ if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL, doc ) )
1197+ return FALSE;
1198+
1199+ // add length()
1200+ func = make_new_mfun( "int", "length", string_length );
1201+ func->doc = "Return the number of characters of the string.";
1202+ if( !type_engine_import_mfun( env, func ) ) goto error;
1203+
1204+ // add upper()
1205+ func = make_new_mfun( "string", "upper", string_upper );
1206+ func->doc = "Return a new string in which the lowercase characters of the original string have been converted to uppercase.";
1207+ if( !type_engine_import_mfun( env, func ) ) goto error;
1208+
1209+ // add lower()
1210+ func = make_new_mfun( "string", "lower", string_lower );
1211+ func->doc = "Return a new string in which the uppercase characters of the original string have been converted to lowercase.";
1212+ if( !type_engine_import_mfun( env, func ) ) goto error;
1213+
1214+ // add ltrim()
1215+ func = make_new_mfun( "string", "ltrim", string_ltrim );
1216+ func->doc = "Return a new string in which leading whitespace has been removed.";
1217+ if( !type_engine_import_mfun( env, func ) ) goto error;
1218+
1219+ // add rtrim()
1220+ func = make_new_mfun( "string", "rtrim", string_rtrim );
1221+ func->doc = "Return a new string in which trailing whitespace has been removed.";
1222+ if( !type_engine_import_mfun( env, func ) ) goto error;
1223+
1224+ // add trim()
1225+ func = make_new_mfun( "string", "trim", string_trim );
1226+ func->doc = "Return a new string in which leading and trailing whitespace has been removed.";
1227+ if( !type_engine_import_mfun( env, func ) ) goto error;
1228+
1229+ // add toString()
1230+ func = make_new_mfun( "string", "toString", string_toString );
1231+ if( !type_engine_import_mfun( env, func ) ) goto error;
1232+
1233+ // add charAt()
1234+ func = make_new_mfun( "int", "charAt", string_charAt );
1235+ func->add_arg("int", "index");
1236+ func->doc = "Return a character at the specified index.";
1237+ if( !type_engine_import_mfun( env, func ) ) goto error;
1238+
1239+ // add setCharAt()
1240+ func = make_new_mfun( "int", "setCharAt", string_setCharAt );
1241+ func->add_arg("int", "index");
1242+ func->add_arg("int", "theChar");
1243+ func->doc = "Set the character at the specified index.";
1244+ if( !type_engine_import_mfun( env, func ) ) goto error;
1245+
1246+ // add substring()
1247+ func = make_new_mfun( "string", "substring", string_substring );
1248+ func->add_arg("int", "start");
1249+ func->doc = "Return a new string containing the substring from the start index to the end of the string.";
1250+ if( !type_engine_import_mfun( env, func ) ) goto error;
1251+
1252+ // add substring()
1253+ func = make_new_mfun( "string", "substring", string_substringN );
1254+ func->add_arg("int", "start");
1255+ func->add_arg("int", "length");
1256+ func->doc = "Return a new string containing the substring from the start index of the specified length.";
1257+ if( !type_engine_import_mfun( env, func ) ) goto error;
1258+
1259+ // add insert()
1260+ func = make_new_mfun( "void", "insert", string_insert );
1261+ func->add_arg("int", "position");
1262+ func->add_arg("string", "str");
1263+ func->doc = "Insert str at the specified position.";
1264+ if( !type_engine_import_mfun( env, func ) ) goto error;
1265+
1266+ // add replace()
1267+ func = make_new_mfun( "void", "replace", string_replace );
1268+ func->add_arg( "int", "position" );
1269+ func->add_arg( "string", "str" );
1270+ func->doc = "Replace characters from the start position to the end of the string with str.";
1271+ if( !type_engine_import_mfun( env, func ) ) goto error;
1272+
1273+ // add replace()
1274+ func = make_new_mfun( "void", "replace", string_replaceN );
1275+ func->add_arg( "int", "position" );
1276+ func->add_arg( "int", "length" );
1277+ func->add_arg( "string", "str" );
1278+ func->doc = "Replace length characters from the start position with str.";
1279+ if( !type_engine_import_mfun( env, func ) ) goto error;
1280+
1281+ // add find()
1282+ func = make_new_mfun( "int", "find", string_find );
1283+ func->add_arg( "int", "theChar" );
1284+ func->doc = "Return the index of the first occurence of theChar, or -1 if theChar is not found.";
1285+ if( !type_engine_import_mfun( env, func ) ) goto error;
1286+
1287+ // add find()
1288+ func = make_new_mfun( "int", "find", string_findStart );
1289+ func->add_arg( "int", "theChar" );
1290+ func->add_arg( "int", "start" );
1291+ func->doc = "Return the index of the first occurence of theChar at or after the start position, or -1 if theChar is not found.";
1292+ if( !type_engine_import_mfun( env, func ) ) goto error;
1293+
1294+ // add find()
1295+ func = make_new_mfun( "int", "find", string_findStr );
1296+ func->add_arg( "string", "str" );
1297+ func->doc = "Return the index of the first occurence of str, or -1 if str is not found.";
1298+ if( !type_engine_import_mfun( env, func ) ) goto error;
1299+
1300+ // add find()
1301+ func = make_new_mfun( "int", "find", string_findStrStart );
1302+ func->add_arg( "string", "str" );
1303+ func->add_arg( "int", "start" );
1304+ func->doc = "Return the index of the first occurence of str at or after the start position, or -1 if str is not found.";
1305+ if( !type_engine_import_mfun( env, func ) ) goto error;
1306+
1307+ // add rfind()
1308+ func = make_new_mfun( "int", "rfind", string_rfind );
1309+ func->add_arg( "int", "theChar" );
1310+ func->doc = "Return the index of the last occurence of theChar, or -1 if theChar is not found.";
1311+ if( !type_engine_import_mfun( env, func ) ) goto error;
1312+
1313+ // add rfind()
1314+ func = make_new_mfun( "int", "rfind", string_rfindStart );
1315+ func->add_arg( "int", "theChar" );
1316+ func->add_arg( "int", "start" );
1317+ func->doc = "Return the index of the last occurence of theChar at or before the start position, or -1 if theChar is not found.";
1318+ if( !type_engine_import_mfun( env, func ) ) goto error;
1319+
1320+ // add rfind()
1321+ func = make_new_mfun( "int", "rfind", string_rfindStr );
1322+ func->add_arg( "string", "str" );
1323+ func->doc = "Return the index of the last occurence of str, or -1 if str is not found.";
1324+ if( !type_engine_import_mfun( env, func ) ) goto error;
1325+
1326+ // add rfind()
1327+ func = make_new_mfun( "int", "rfind", string_rfindStrStart );
1328+ func->add_arg( "string", "str" );
1329+ func->add_arg( "int", "start" );
1330+ func->doc = "Return the index of the last occurence of str at or before the start position, or -1 if str is not found.";
1331+ if( !type_engine_import_mfun( env, func ) ) goto error;
1332+
1333+ // add erase()
1334+ func = make_new_mfun( "void", "erase", string_erase );
1335+ func->add_arg( "int", "start" );
1336+ func->add_arg( "int", "length" );
1337+ func->doc = "Erase length characters of the string from start position.";
1338+ if( !type_engine_import_mfun( env, func ) ) goto error;
1339+
1340+ // add toInt()
1341+ func = make_new_mfun( "int", "toInt", string_toInt );
1342+ func->doc = "Attempt to convert the contents of the string to an integer and return the result, or 0 if conversion failed.";
1343+ if( !type_engine_import_mfun( env, func ) ) goto error;
1344+
1345+ // add toFloat()
1346+ func = make_new_mfun( "float", "toFloat", string_toFloat );
1347+ func->doc = "Attempt to convert the contents of the string to an float and return the result, or 0 if conversion failed.";
1348+ if( !type_engine_import_mfun( env, func ) ) goto error;
1349+
1350+ // add parent()
1351+ // disable for now
1352+// func = make_new_mfun( "string", "parent", string_parent );
1353+// if( !type_engine_import_mfun( env, func ) ) goto error;
1354+
1355+// // add toTime()
1356+// func = make_new_mfun( "float", "toTime", string_toFloat );
1357+// if( !type_engine_import_mfun( env, func ) ) goto error;
1358+//
1359+// // add toDur()
1360+// func = make_new_mfun( "float", "toDur", string_toFloat );
1361+// if( !type_engine_import_mfun( env, func ) ) goto error;
1362+
1363+/* // add at()
1364+ func = make_new_mfun( "int", "ch", string_set_at );
1365+ func->add_arg( "int", "index" );
1366+ func->add_arg( "int", "val" );
1367+ if( !type_engine_import_mfun( env, func ) ) goto error;
1368+ func = make_new_mfun( "int", "ch", string_get_at );
1369+ func->add_arg( "int", "index" );
1370+ if( !type_engine_import_mfun( env, func ) ) goto error;
1371+*/
1372+ // end the class import
1373+ type_engine_import_class_end( env );
1374+
1375+ return TRUE;
1376+
1377+error:
1378+
1379+ // end the class import
1380+ type_engine_import_class_end( env );
1381+
1382+ return FALSE;
1383+}
1384+
1385+
1386+
1387+
1388+//-----------------------------------------------------------------------------
1389+// name: init_class_array()
1390+// desc: ...
1391+//-----------------------------------------------------------------------------
1392+t_CKBOOL init_class_array( Chuck_Env * env, Chuck_Type * type )
1393+{
1394+ // init as base class
1395+ Chuck_DL_Func * func = NULL;
1396+
1397+ // log
1398+ EM_log( CK_LOG_SEVERE, "class 'array'" );
1399+
1400+ // init as base class
1401+ // TODO: ctor/dtor?
1402+ const char *doc = "The array class is used to store linear sequences of data, also providing capabilities for stack and map data structures.";
1403+ if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL, doc ) )
1404+ return FALSE;
1405+
1406+ // add clear()
1407+ func = make_new_mfun( "void", "clear", array_clear );
1408+ func->doc = "Clear the contents of the array.";
1409+ if( !type_engine_import_mfun( env, func ) ) goto error;
1410+
1411+ // add reset()
1412+ func = make_new_mfun( "void", "reset", array_reset );
1413+ func->doc = "Reset array to original state; clears the array and sets capacity to 8.";
1414+ if( !type_engine_import_mfun( env, func ) ) goto error;
1415+
1416+ // add popBack()
1417+ func = make_new_mfun( "void", "popBack", array_pop_back );
1418+ func->doc = "Remove the last item of the array";
1419+ if( !type_engine_import_mfun( env, func ) ) goto error;
1420+
1421+ // add size()
1422+ func = make_new_mfun( "int", "size", array_get_size );
1423+ func->doc = "Return the number of elements in the array.";
1424+ if( !type_engine_import_mfun( env, func ) ) goto error;
1425+ // add size()
1426+ func = make_new_mfun( "int", "size", array_set_size );
1427+ func->add_arg( "int", "newSize" );
1428+ func->doc = "Set the size of the array. If the new size is less than the current size, elements will be deleted from the end; if the new size is larger than the current size, 0 or null elements will be added to the end.";
1429+ if( !type_engine_import_mfun( env, func ) ) goto error;
1430+
1431+ // add cap()
1432+ func = make_new_mfun( "int", "cap", array_get_capacity_hack );
1433+ func->doc = "Return current capacity of the array (number of elements that can be held without reallocating internal buffer). ";
1434+ if( !type_engine_import_mfun( env, func ) ) goto error;
1435+
1436+ // add capacity()
1437+ // func = make_new_mfun( "int", "capacity", array_get_capacity );
1438+ // if( !type_engine_import_mfun( env, func ) ) goto error;
1439+ // func = make_new_mfun( "int", "capacity", array_set_capacity );
1440+ // func->add_arg( "int", "val" );
1441+ // if( !type_engine_import_mfun( env, func ) ) goto error;
1442+
1443+ // add find()
1444+ func = make_new_mfun( "int", "find", array_find );
1445+ func->add_arg( "string", "key" );
1446+ func->doc = "Return number of elements with the specified key. ";
1447+ if( !type_engine_import_mfun( env, func ) ) goto error;
1448+
1449+ // add erase()
1450+ func = make_new_mfun( "int", "erase", array_erase );
1451+ func->add_arg( "string", "key" );
1452+ func->doc = "Erase all elements with the specified key. ";
1453+ if( !type_engine_import_mfun( env, func ) ) goto error;
1454+
1455+ // add examples
1456+ if( !type_engine_import_add_ex( env, "array/array_argument.ck" ) ) goto error;
1457+ if( !type_engine_import_add_ex( env, "array/array_assign.ck" ) ) goto error;
1458+ if( !type_engine_import_add_ex( env, "array/array_dynamic.ck" ) ) goto error;
1459+ if( !type_engine_import_add_ex( env, "array/array_mdim.ck" ) ) goto error;
1460+ if( !type_engine_import_add_ex( env, "array/array_mmixed.ck" ) ) goto error;
1461+ if( !type_engine_import_add_ex( env, "array/array_resize.ck" ) ) goto error;
1462+ if( !type_engine_import_add_ex( env, "array/array_storage.ck" ) ) goto error;
1463+ if( !type_engine_import_add_ex( env, "array/array_sub_assign.ck" ) ) goto error;
1464+
1465+ type_engine_import_class_end( env );
1466+
1467+ return TRUE;
1468+
1469+error:
1470+
1471+ // end the class import
1472+ type_engine_import_class_end( env );
1473+
1474+ return FALSE;
1475+}
1476+
1477+
1478+
1479+// static
1480+static t_CKUINT MidiIn_offset_data = 0;
1481+t_CKUINT MidiMsg_offset_data1 = 0;
1482+t_CKUINT MidiMsg_offset_data2 = 0;
1483+t_CKUINT MidiMsg_offset_data3 = 0;
1484+t_CKUINT MidiMsg_offset_when = 0;
1485+static t_CKUINT MidiOut_offset_data = 0;
1486+
1487+//-----------------------------------------------------------------------------
1488+// name: init_class_Midi()
1489+// desc: ...
1490+//-----------------------------------------------------------------------------
1491+t_CKBOOL init_class_Midi( Chuck_Env * env )
1492+{
1493+ Chuck_DL_Func * func = NULL;
1494+
1495+ // init base class
1496+ // TODO: ctor/dtor?
1497+ if( !type_engine_import_class_begin( env, "MidiMsg", "Object",
1498+ env->global(), NULL, NULL ) )
1499+ return FALSE;
1500+
1501+ // add member variable
1502+ MidiMsg_offset_data1 = type_engine_import_mvar( env, "int", "data1", FALSE );
1503+ if( MidiMsg_offset_data1 == CK_INVALID_OFFSET ) goto error;
1504+
1505+ // add member variable
1506+ MidiMsg_offset_data2 = type_engine_import_mvar( env, "int", "data2", FALSE );
1507+ if( MidiMsg_offset_data2 == CK_INVALID_OFFSET ) goto error;
1508+
1509+ // add member variable
1510+ MidiMsg_offset_data3 = type_engine_import_mvar( env, "int", "data3", FALSE );
1511+ if( MidiMsg_offset_data3 == CK_INVALID_OFFSET ) goto error;
1512+
1513+ // add member variable
1514+ MidiMsg_offset_when = type_engine_import_mvar( env, "dur", "when", FALSE );
1515+ if( MidiMsg_offset_when == CK_INVALID_OFFSET ) goto error;
1516+
1517+ // end the class import
1518+ type_engine_import_class_end( env );
1519+
1520+#ifndef __DISABLE_MIDI__
1521+ // init base class
1522+ if( !type_engine_import_class_begin( env, "MidiIn", "Event",
1523+ env->global(), MidiIn_ctor, MidiIn_dtor ) )
1524+ return FALSE;
1525+
1526+ // add open()
1527+ func = make_new_mfun( "int", "open", MidiIn_open );
1528+ func->add_arg( "int", "port" );
1529+ if( !type_engine_import_mfun( env, func ) ) goto error;
1530+
1531+ // add open() (added 1.3.0.0)
1532+ func = make_new_mfun( "int", "open", MidiIn_open_named );
1533+ func->add_arg( "string", "name" );
1534+ if( !type_engine_import_mfun( env, func ) ) goto error;
1535+
1536+ // add good()
1537+ func = make_new_mfun( "int", "good", MidiIn_good );
1538+ if( !type_engine_import_mfun( env, func ) ) goto error;
1539+
1540+ // add num()
1541+ func = make_new_mfun( "int", "num", MidiIn_num );
1542+ if( !type_engine_import_mfun( env, func ) ) goto error;
1543+
1544+ // add name()
1545+ func = make_new_mfun( "string", "name", MidiIn_name );
1546+ if( !type_engine_import_mfun( env, func ) ) goto error;
1547+
1548+ // add printerr()
1549+ func = make_new_mfun( "void", "printerr", MidiIn_printerr );
1550+ func->add_arg( "int", "print_or_not" );
1551+ if( !type_engine_import_mfun( env, func ) ) goto error;
1552+
1553+ // add recv()
1554+ func = make_new_mfun( "int", "recv", MidiIn_recv );
1555+ func->add_arg( "MidiMsg", "msg" );
1556+ if( !type_engine_import_mfun( env, func ) ) goto error;
1557+
1558+ // add can_wait()
1559+ func = make_new_mfun( "int", "can_wait", MidiIn_can_wait );
1560+ if( !type_engine_import_mfun( env, func ) ) goto error;
1561+
1562+ // add member variable
1563+ MidiIn_offset_data = type_engine_import_mvar( env, "int", "@MidiIn_data", FALSE );
1564+ if( MidiIn_offset_data == CK_INVALID_OFFSET ) goto error;
1565+
1566+ // end the class import
1567+ type_engine_import_class_end( env );
1568+
1569+ // init base class
1570+ if( !type_engine_import_class_begin( env, "MidiOut", "Object",
1571+ env->global(), MidiOut_ctor, MidiOut_dtor ) )
1572+ return FALSE;
1573+
1574+ // add open()
1575+ func = make_new_mfun( "int", "open", MidiOut_open );
1576+ func->add_arg( "int", "port" );
1577+ if( !type_engine_import_mfun( env, func ) ) goto error;
1578+
1579+ // add open() (added 1.3.0.0)
1580+ func = make_new_mfun( "int", "open", MidiOut_open_named );
1581+ func->add_arg( "string", "name" );
1582+ if( !type_engine_import_mfun( env, func ) ) goto error;
1583+
1584+ // add good()
1585+ func = make_new_mfun( "int", "good", MidiOut_good );
1586+ if( !type_engine_import_mfun( env, func ) ) goto error;
1587+
1588+ // add num()
1589+ func = make_new_mfun( "int", "num", MidiOut_num );
1590+ if( !type_engine_import_mfun( env, func ) ) goto error;
1591+
1592+ // add name()
1593+ func = make_new_mfun( "string", "name", MidiOut_name );
1594+ if( !type_engine_import_mfun( env, func ) ) goto error;
1595+
1596+ // add printerr()
1597+ func = make_new_mfun( "void", "printerr", MidiOut_printerr );
1598+ func->add_arg( "int", "print_or_not" );
1599+ if( !type_engine_import_mfun( env, func ) ) goto error;
1600+
1601+ // add send()
1602+ func = make_new_mfun( "int", "send", MidiOut_send );
1603+ func->add_arg( "MidiMsg", "msg" );
1604+ if( !type_engine_import_mfun( env, func ) ) goto error;
1605+
1606+ // add member variable
1607+ MidiOut_offset_data = type_engine_import_mvar( env, "int", "@MidiOut_data", FALSE );
1608+ if( MidiOut_offset_data == CK_INVALID_OFFSET ) goto error;
1609+
1610+ // end the class import
1611+ type_engine_import_class_end( env );
1612+
1613+#endif // __DISABLE_MIDI__
1614+
1615+ return TRUE;
1616+
1617+error:
1618+
1619+ // end the class import
1620+ type_engine_import_class_end( env );
1621+
1622+ return FALSE;
1623+}
1624+
1625+
1626+
1627+
1628+// static
1629+static t_CKUINT HidIn_offset_data = 0;
1630+
1631+static t_CKUINT HidMsg_offset_device_type = 0;
1632+static t_CKUINT HidMsg_offset_device_num = 0;
1633+static t_CKUINT HidMsg_offset_type = 0;
1634+static t_CKUINT HidMsg_offset_which = 0;
1635+static t_CKUINT HidMsg_offset_idata = 0;
1636+static t_CKUINT HidMsg_offset_fdata = 0;
1637+static t_CKUINT HidMsg_offset_when = 0;
1638+static t_CKUINT HidMsg_offset_deltax = 0;
1639+static t_CKUINT HidMsg_offset_deltay = 0;
1640+static t_CKUINT HidMsg_offset_axis_position = 0; // deprecated
1641+static t_CKUINT HidMsg_offset_axis_position2 = 0;
1642+static t_CKUINT HidMsg_offset_scaled_axis_position = 0; // deprecated
1643+static t_CKUINT HidMsg_offset_hat_position = 0;
1644+static t_CKUINT HidMsg_offset_cursorx = 0;
1645+static t_CKUINT HidMsg_offset_cursory = 0;
1646+static t_CKUINT HidMsg_offset_scaledcursorx = 0;
1647+static t_CKUINT HidMsg_offset_scaledcursory = 0;
1648+static t_CKUINT HidMsg_offset_x = 0;
1649+static t_CKUINT HidMsg_offset_y = 0;
1650+static t_CKUINT HidMsg_offset_z = 0;
1651+static t_CKUINT HidMsg_offset_touchx = 0; // added 1.3.0.0
1652+static t_CKUINT HidMsg_offset_touchy = 0; // added 1.3.0.0
1653+static t_CKUINT HidMsg_offset_touchsize = 0; // added 1.3.0.0
1654+static t_CKUINT HidMsg_offset_ascii = 0;
1655+static t_CKUINT HidMsg_offset_key = 0;
1656+
1657+static t_CKUINT HidOut_offset_data = 0;
1658+
1659+//-----------------------------------------------------------------------------
1660+// name: init_class_HID()
1661+// desc: ...
1662+//-----------------------------------------------------------------------------
1663+t_CKBOOL init_class_HID( Chuck_Env * env )
1664+{
1665+ Chuck_DL_Func * func = NULL;
1666+
1667+ // init base class
1668+ if( !type_engine_import_class_begin( env, "HidMsg", "Object",
1669+ env->global(), NULL, NULL ) )
1670+ return FALSE;
1671+
1672+ // add member variable
1673+ HidMsg_offset_device_type = type_engine_import_mvar( env, "int", "deviceType", FALSE );
1674+ if( HidMsg_offset_device_type == CK_INVALID_OFFSET ) goto error;
1675+
1676+ // add member variable
1677+ HidMsg_offset_device_num = type_engine_import_mvar( env, "int", "deviceNum", FALSE );
1678+ if( HidMsg_offset_device_num == CK_INVALID_OFFSET ) goto error;
1679+
1680+ // add member variable
1681+ HidMsg_offset_type = type_engine_import_mvar( env, "int", "type", FALSE );
1682+ if( HidMsg_offset_type == CK_INVALID_OFFSET ) goto error;
1683+
1684+ // add member variable
1685+ HidMsg_offset_which = type_engine_import_mvar( env, "int", "which", FALSE );
1686+ if( HidMsg_offset_which == CK_INVALID_OFFSET ) goto error;
1687+
1688+ // add member variable
1689+ HidMsg_offset_idata = type_engine_import_mvar( env, "int", "idata", FALSE );
1690+ if( HidMsg_offset_idata == CK_INVALID_OFFSET ) goto error;
1691+
1692+ // add member variable
1693+ HidMsg_offset_fdata = type_engine_import_mvar( env, "float", "fdata", FALSE );
1694+ if( HidMsg_offset_fdata == CK_INVALID_OFFSET ) goto error;
1695+
1696+ // add member variable
1697+ HidMsg_offset_when = type_engine_import_mvar( env, "time", "when", FALSE );
1698+ if( HidMsg_offset_when == CK_INVALID_OFFSET ) goto error;
1699+
1700+ // add member variable
1701+ HidMsg_offset_deltax = type_engine_import_mvar( env, "int", "deltaX", FALSE );
1702+ if( HidMsg_offset_deltax == CK_INVALID_OFFSET ) goto error;
1703+
1704+ // add member variable
1705+ HidMsg_offset_deltay = type_engine_import_mvar( env, "int", "deltaY", FALSE );
1706+ if( HidMsg_offset_deltay == CK_INVALID_OFFSET ) goto error;
1707+
1708+ // add member variable
1709+ HidMsg_offset_cursorx = type_engine_import_mvar( env, "int", "cursorX", FALSE );
1710+ if( HidMsg_offset_cursorx == CK_INVALID_OFFSET ) goto error;
1711+
1712+ // add member variable
1713+ HidMsg_offset_cursory = type_engine_import_mvar( env, "int", "cursorY", FALSE );
1714+ if( HidMsg_offset_cursory == CK_INVALID_OFFSET ) goto error;
1715+
1716+ // add member variable
1717+ HidMsg_offset_scaledcursorx = type_engine_import_mvar( env, "float", "scaledCursorX", FALSE );
1718+ if( HidMsg_offset_scaledcursorx == CK_INVALID_OFFSET ) goto error;
1719+
1720+ // add member variable
1721+ HidMsg_offset_scaledcursory = type_engine_import_mvar( env, "float", "scaledCursorY", FALSE );
1722+ if( HidMsg_offset_scaledcursory == CK_INVALID_OFFSET ) goto error;
1723+
1724+ // add member variable
1725+ HidMsg_offset_x = type_engine_import_mvar( env, "int", "x", FALSE );
1726+ if( HidMsg_offset_x == CK_INVALID_OFFSET ) goto error;
1727+
1728+ // add member variable
1729+ HidMsg_offset_y = type_engine_import_mvar( env, "int", "y", FALSE );
1730+ if( HidMsg_offset_y == CK_INVALID_OFFSET ) goto error;
1731+
1732+ // add member variable
1733+ HidMsg_offset_z = type_engine_import_mvar( env, "int", "z", FALSE );
1734+ if( HidMsg_offset_z == CK_INVALID_OFFSET ) goto error;
1735+
1736+ // add member variable (added 1.3.0.0)
1737+ HidMsg_offset_touchx = type_engine_import_mvar( env, "float", "touchX", FALSE );
1738+ if( HidMsg_offset_touchx == CK_INVALID_OFFSET ) goto error;
1739+
1740+ // add member variable (added 1.3.0.0)
1741+ HidMsg_offset_touchy = type_engine_import_mvar( env, "float", "touchY", FALSE );
1742+ if( HidMsg_offset_touchy == CK_INVALID_OFFSET ) goto error;
1743+
1744+ // add member variable (added 1.3.0.0)
1745+ HidMsg_offset_touchsize = type_engine_import_mvar( env, "float", "touchSize", FALSE );
1746+ if( HidMsg_offset_touchsize == CK_INVALID_OFFSET ) goto error;
1747+
1748+ // add member variable
1749+ HidMsg_offset_axis_position = type_engine_import_mvar( env, "int", "axis_position", FALSE );
1750+ if( HidMsg_offset_axis_position == CK_INVALID_OFFSET ) goto error;
1751+
1752+ // add member variable
1753+ HidMsg_offset_axis_position2 = type_engine_import_mvar( env, "float", "axisPosition", FALSE );
1754+ if( HidMsg_offset_axis_position2 == CK_INVALID_OFFSET ) goto error;
1755+
1756+ // add member variable
1757+ HidMsg_offset_hat_position = type_engine_import_mvar( env, "int", "hatPosition", FALSE );
1758+ if( HidMsg_offset_hat_position == CK_INVALID_OFFSET ) goto error;
1759+
1760+ // add member variable
1761+ HidMsg_offset_ascii = type_engine_import_mvar( env, "int", "ascii", FALSE );
1762+ if( HidMsg_offset_ascii == CK_INVALID_OFFSET ) goto error;
1763+
1764+ // add member variable
1765+ HidMsg_offset_key = type_engine_import_mvar( env, "int", "key", FALSE );
1766+ if( HidMsg_offset_key == CK_INVALID_OFFSET ) goto error;
1767+
1768+ // add member variable
1769+ HidMsg_offset_scaled_axis_position = type_engine_import_mvar( env, "float", "scaled_axis_position", FALSE );
1770+ if( HidMsg_offset_scaled_axis_position == CK_INVALID_OFFSET ) goto error;
1771+
1772+ // add is_axis_motion()
1773+ func = make_new_mfun( "int", "is_axis_motion", HidMsg_is_axis_motion ); // deprecated
1774+ if( !type_engine_import_mfun( env, func ) ) goto error;
1775+
1776+ // add isAxisMotion()
1777+ func = make_new_mfun( "int", "isAxisMotion", HidMsg_is_axis_motion );
1778+ if( !type_engine_import_mfun( env, func ) ) goto error;
1779+
1780+ // add is_button_down()
1781+ func = make_new_mfun( "int", "is_button_down", HidMsg_is_button_down ); // deprecated
1782+ if( !type_engine_import_mfun( env, func ) ) goto error;
1783+
1784+ // add isButtonDown()
1785+ func = make_new_mfun( "int", "isButtonDown", HidMsg_is_button_down );
1786+ if( !type_engine_import_mfun( env, func ) ) goto error;
1787+
1788+ // add is_button_up()
1789+ func = make_new_mfun( "int", "is_button_up", HidMsg_is_button_up ); // deprecated
1790+ if( !type_engine_import_mfun( env, func ) ) goto error;
1791+
1792+ // add isButtonUp()
1793+ func = make_new_mfun( "int", "isButtonUp", HidMsg_is_button_up );
1794+ if( !type_engine_import_mfun( env, func ) ) goto error;
1795+
1796+ // add is_mouse_motion()
1797+ func = make_new_mfun( "int", "is_mouse_motion", HidMsg_is_mouse_motion ); // deprecated
1798+ if( !type_engine_import_mfun( env, func ) ) goto error;
1799+
1800+ // add isMouseMotion()
1801+ func = make_new_mfun( "int", "isMouseMotion", HidMsg_is_mouse_motion );
1802+ if( !type_engine_import_mfun( env, func ) ) goto error;
1803+
1804+ // add is_hat_motion()
1805+ func = make_new_mfun( "int", "is_hat_motion", HidMsg_is_hat_motion ); // deprecated
1806+ if( !type_engine_import_mfun( env, func ) ) goto error;
1807+
1808+ // add isHatMotion()
1809+ func = make_new_mfun( "int", "isHatMotion", HidMsg_is_hat_motion );
1810+ if( !type_engine_import_mfun( env, func ) ) goto error;
1811+
1812+ // add isWheelMotion()
1813+ func = make_new_mfun( "int", "isWheelMotion", HidMsg_is_wheel_motion );
1814+ if( !type_engine_import_mfun( env, func ) ) goto error;
1815+
1816+ // end the class import
1817+ type_engine_import_class_end( env );
1818+
1819+
1820+ // register deprecate
1821+ type_engine_register_deprecate( env, "HidIn", "Hid" );
1822+
1823+ // init base class Hid (copy of HidIn + constants)
1824+ if( !type_engine_import_class_begin( env, "Hid", "Event",
1825+ env->global(), HidIn_ctor, HidIn_dtor ) )
1826+ return FALSE;
1827+
1828+ // add open()
1829+ func = make_new_mfun( "int", "open", HidIn_open );
1830+ func->add_arg( "int", "type" );
1831+ func->add_arg( "int", "num" );
1832+ if( !type_engine_import_mfun( env, func ) ) goto error;
1833+
1834+ // add open()
1835+ func = make_new_mfun( "int", "open", HidIn_open_named );
1836+ func->add_arg( "string", "name" );
1837+ if( !type_engine_import_mfun( env, func ) ) goto error;
1838+
1839+ // add openJoystick()
1840+ func = make_new_mfun( "int", "openJoystick", HidIn_open_joystick );
1841+ func->add_arg( "int", "num" );
1842+ if( !type_engine_import_mfun( env, func ) ) goto error;
1843+
1844+ // add openMouse()
1845+ func = make_new_mfun( "int", "openMouse", HidIn_open_mouse );
1846+ func->add_arg( "int", "num" );
1847+ if( !type_engine_import_mfun( env, func ) ) goto error;
1848+
1849+ // add openKeyboard()
1850+ func = make_new_mfun( "int", "openKeyboard", HidIn_open_keyboard );
1851+ func->add_arg( "int", "num" );
1852+ if( !type_engine_import_mfun( env, func ) ) goto error;
1853+
1854+ // add openTiltSensor()
1855+ func = make_new_mfun( "int", "openTiltSensor", HidIn_open_tiltsensor );
1856+ if( !type_engine_import_mfun( env, func ) ) goto error;
1857+
1858+ // add good()
1859+ func = make_new_mfun( "int", "good", HidIn_good );
1860+ if( !type_engine_import_mfun( env, func ) ) goto error;
1861+
1862+ // add num()
1863+ func = make_new_mfun( "int", "num", HidIn_num );
1864+ if( !type_engine_import_mfun( env, func ) ) goto error;
1865+
1866+ // add name()
1867+ func = make_new_mfun( "string", "name", HidIn_name );
1868+ if( !type_engine_import_mfun( env, func ) ) goto error;
1869+
1870+ // add printerr()
1871+ func = make_new_mfun( "void", "printerr", HidIn_printerr );
1872+ func->add_arg( "int", "print_or_not" );
1873+ if( !type_engine_import_mfun( env, func ) ) goto error;
1874+
1875+ // add recv()
1876+ func = make_new_mfun( "int", "recv", HidIn_recv );
1877+ func->add_arg( "HidMsg", "msg" );
1878+ if( !type_engine_import_mfun( env, func ) ) goto error;
1879+
1880+ // add read()
1881+ func = make_new_mfun( "int", "read", HidIn_read );
1882+ func->add_arg( "int", "type" );
1883+ func->add_arg( "int", "which" );
1884+ func->add_arg( "HidMsg", "msg" );
1885+ if( !type_engine_import_mfun( env, func ) ) goto error;
1886+
1887+ // add send()
1888+ func = make_new_mfun( "int", "send", HidIn_send );
1889+ func->add_arg( "HidMsg", "msg" );
1890+ if( !type_engine_import_mfun( env, func ) ) goto error;
1891+
1892+ // add can_wait()
1893+ func = make_new_mfun( "int", "can_wait", HidIn_can_wait );
1894+ if( !type_engine_import_mfun( env, func ) ) goto error;
1895+
1896+ // add readTiltSensor()
1897+ func = make_new_sfun( "int[]", "readTiltSensor", HidIn_read_tilt_sensor );
1898+ if( !type_engine_import_sfun( env, func ) ) goto error;
1899+
1900+ // add globalTiltPollRate()
1901+ func = make_new_sfun( "dur", "globalTiltPollRate", HidIn_ctrl_tiltPollRate );
1902+ func->add_arg( "dur", "d" );
1903+ if( !type_engine_import_sfun( env, func ) ) goto error;
1904+
1905+ // add globalTiltPollRate()
1906+ func = make_new_sfun( "dur", "globalTiltPollRate", HidIn_cget_tiltPollRate );
1907+ if( !type_engine_import_sfun( env, func ) ) goto error;
1908+
1909+ // add startCursorTrack()
1910+ func = make_new_sfun( "int", "startCursorTrack", HidIn_start_cursor_track );
1911+ if( !type_engine_import_sfun( env, func ) ) goto error;
1912+
1913+ // add stopCursorTrack()
1914+ func = make_new_sfun( "int", "stopCursorTrack", HidIn_stop_cursor_track );
1915+ if( !type_engine_import_sfun( env, func ) ) goto error;
1916+
1917+ // add member variable
1918+ HidIn_offset_data = type_engine_import_mvar( env, "int", "@Hid_data", FALSE );
1919+ if( HidIn_offset_data == CK_INVALID_OFFSET ) goto error;
1920+
1921+ // add static member variable joystick
1922+ if( type_engine_import_svar( env, "int", "JOYSTICK", TRUE,
1923+ ( t_CKUINT ) &CK_HID_DEV_JOYSTICK ) == FALSE )
1924+ goto error;
1925+
1926+ // add static member variable keyboard
1927+ if( type_engine_import_svar( env, "int", "KEYBOARD", TRUE,
1928+ ( t_CKUINT ) &CK_HID_DEV_KEYBOARD ) == FALSE )
1929+ goto error;
1930+
1931+ // add static member variable mouse
1932+ if( type_engine_import_svar( env, "int", "MOUSE", TRUE,
1933+ ( t_CKUINT ) &CK_HID_DEV_MOUSE ) == FALSE )
1934+ goto error;
1935+
1936+ // add static member variable wii_remote
1937+ if( type_engine_import_svar( env, "int", "WII_REMOTE", TRUE,
1938+ ( t_CKUINT ) &CK_HID_DEV_WIIREMOTE ) == FALSE )
1939+ goto error;
1940+
1941+ // add static member variable wii_remote
1942+ if( type_engine_import_svar( env, "int", "TILT_SENSOR", TRUE,
1943+ ( t_CKUINT ) &CK_HID_DEV_TILTSENSOR ) == FALSE )
1944+ goto error;
1945+
1946+ // add static member variable tablet
1947+ if( type_engine_import_svar( env, "int", "TABLET", TRUE,
1948+ ( t_CKUINT ) &CK_HID_DEV_TABLET ) == FALSE )
1949+ goto error;
1950+
1951+ // add static member variable axisMotion
1952+ if( type_engine_import_svar( env, "int", "AXIS_MOTION", TRUE,
1953+ ( t_CKUINT ) &CK_HID_JOYSTICK_AXIS ) == FALSE )
1954+ goto error;
1955+
1956+ // add static member variable buttonDown
1957+ if( type_engine_import_svar( env, "int", "BUTTON_DOWN", TRUE,
1958+ ( t_CKUINT ) &CK_HID_BUTTON_DOWN ) == FALSE )
1959+ goto error;
1960+
1961+ // add static member variable buttonUp
1962+ if( type_engine_import_svar( env, "int", "BUTTON_UP", TRUE,
1963+ ( t_CKUINT ) &CK_HID_BUTTON_UP ) == FALSE )
1964+ goto error;
1965+
1966+ // add static member variable joystickHat
1967+ if( type_engine_import_svar( env, "int", "JOYSTICK_HAT", TRUE,
1968+ ( t_CKUINT ) &CK_HID_JOYSTICK_HAT ) == FALSE )
1969+ goto error;
1970+
1971+ // add static member variable JOYSTICK_BALL
1972+ if( type_engine_import_svar( env, "int", "JOYSTICK_BALL", TRUE,
1973+ ( t_CKUINT ) &CK_HID_JOYSTICK_BALL ) == FALSE )
1974+ goto error;
1975+
1976+ // add static member variable mouseMotion
1977+ if( type_engine_import_svar( env, "int", "MOUSE_MOTION", TRUE,
1978+ ( t_CKUINT ) &CK_HID_MOUSE_MOTION ) == FALSE )
1979+ goto error;
1980+
1981+ // add static member variable mouseWheel
1982+ if( type_engine_import_svar( env, "int", "MOUSE_WHEEL", TRUE,
1983+ ( t_CKUINT ) &CK_HID_MOUSE_WHEEL ) == FALSE )
1984+ goto error;
1985+
1986+ // add static member variable DEVICE_CONNECTED
1987+ if( type_engine_import_svar( env, "int", "DEVICE_CONNECTED", TRUE,
1988+ ( t_CKUINT ) &CK_HID_DEVICE_CONNECTED ) == FALSE )
1989+ goto error;
1990+
1991+ // add static member variable DEVICE_DISCONNECTED
1992+ if( type_engine_import_svar( env, "int", "DEVICE_DISCONNECTED", TRUE,
1993+ ( t_CKUINT ) &CK_HID_DEVICE_DISCONNECTED ) == FALSE )
1994+ goto error;
1995+
1996+ // add static member variable ACCELEROMETER
1997+ if( type_engine_import_svar( env, "int", "ACCELEROMETER", TRUE,
1998+ ( t_CKUINT ) &CK_HID_ACCELEROMETER ) == FALSE )
1999+ goto error;
2000+
2001+ // add static member variable LED
2002+ if( type_engine_import_svar( env, "int", "LED", TRUE,
2003+ ( t_CKUINT ) &CK_HID_LED ) == FALSE )
2004+ goto error;
2005+
2006+ // add static member variable LED
2007+ if( type_engine_import_svar( env, "int", "FORCE_FEEDBACK", TRUE,
2008+ ( t_CKUINT ) &CK_HID_FORCE_FEEDBACK ) == FALSE )
2009+ goto error;
2010+
2011+ // end the class import
2012+ type_engine_import_class_end( env );
2013+
2014+ /*
2015+ // init base class
2016+ if( !type_engine_import_class_begin( env, "HidOut", "Object",
2017+ env->global(), HidOut_ctor ) )
2018+ return FALSE;
2019+
2020+ // add open()
2021+ func = make_new_mfun( "int", "open", HidOut_open );
2022+ func->add_arg( "int", "port" );
2023+ if( !type_engine_import_mfun( env, func ) ) goto error;
2024+
2025+ // add good()
2026+ func = make_new_mfun( "int", "good", HidOut_good );
2027+ if( !type_engine_import_mfun( env, func ) ) goto error;
2028+
2029+ // add num()
2030+ func = make_new_mfun( "int", "num", HidOut_num );
2031+ if( !type_engine_import_mfun( env, func ) ) goto error;
2032+
2033+ // add name()
2034+ func = make_new_mfun( "string", "name", HidOut_name );
2035+ if( !type_engine_import_mfun( env, func ) ) goto error;
2036+
2037+ // add printerr()
2038+ func = make_new_mfun( "void", "printerr", HidOut_printerr );
2039+ func->add_arg( "int", "print_or_not" );
2040+ if( !type_engine_import_mfun( env, func ) ) goto error;
2041+
2042+ // add send()
2043+ func = make_new_mfun( "int", "send", HidOut_send );
2044+ func->add_arg( "HidMsg", "msg" );
2045+ if( !type_engine_import_mfun( env, func ) ) goto error;
2046+
2047+ // add member variable
2048+ HidOut_offset_data = type_engine_import_mvar( env, "int", "@HidOut_data", FALSE );
2049+ if( HidOut_offset_data == CK_INVALID_OFFSET ) goto error;
2050+
2051+ // end the class import
2052+ type_engine_import_class_end( env );
2053+ */
2054+ return TRUE;
2055+
2056+error:
2057+
2058+ // end the class import
2059+ type_engine_import_class_end( env );
2060+
2061+ return FALSE;
2062+}
2063+
2064+
2065+
2066+
2067+
2068+// static
2069+static t_CKUINT MidiRW_offset_data = 0;
2070+static t_CKUINT MidiMsgOut_offset_data = 0;
2071+static t_CKUINT MidiMsgIn_offset_data = 0;
2072+//-----------------------------------------------------------------------------
2073+// name: init_class_MidiRW()
2074+// desc: ...
2075+//-----------------------------------------------------------------------------
2076+t_CKBOOL init_class_MidiRW( Chuck_Env * env )
2077+{
2078+ Chuck_DL_Func * func = NULL;
2079+
2080+#ifndef __DISABLE_MIDI__
2081+
2082+ // init base class
2083+ if( !type_engine_import_class_begin( env, "MidiRW", "Object",
2084+ env->global(), MidiRW_ctor, MidiRW_dtor ) )
2085+ return FALSE;
2086+
2087+ // add open()
2088+ func = make_new_mfun( "int", "open", MidiRW_open );
2089+ func->add_arg( "string", "filename" );
2090+ if( !type_engine_import_mfun( env, func ) ) goto error;
2091+
2092+ // add close()
2093+ func = make_new_mfun( "int", "close", MidiRW_close );
2094+ if( !type_engine_import_mfun( env, func ) ) goto error;
2095+
2096+ // add write()
2097+ func = make_new_mfun( "int", "write", MidiRW_write );
2098+ func->add_arg( "MidiMsg", "msg" );
2099+ func->add_arg( "time", "t" );
2100+ if( !type_engine_import_mfun( env, func ) ) goto error;
2101+
2102+ // add read()
2103+ func = make_new_mfun( "int", "read", MidiRW_read );
2104+ func->add_arg( "MidiMsg", "msg" );
2105+ //func->add_arg( "time", "t" );
2106+ if( !type_engine_import_mfun( env, func ) ) goto error;
2107+
2108+ // add member variable
2109+ MidiRW_offset_data = type_engine_import_mvar( env, "int", "@MidiRW_data", FALSE );
2110+ if( MidiRW_offset_data == CK_INVALID_OFFSET ) goto error;
2111+
2112+ // end the class import
2113+ type_engine_import_class_end( env );
2114+
2115+ // init base class
2116+ if( !type_engine_import_class_begin( env, "MidiMsgOut", "Object",
2117+ env->global(), MidiMsgOut_ctor, MidiMsgOut_dtor ) )
2118+ return FALSE;
2119+
2120+ // add open()
2121+ func = make_new_mfun( "int", "open", MidiMsgOut_open );
2122+ func->add_arg( "string", "filename" );
2123+ if( !type_engine_import_mfun( env, func ) ) goto error;
2124+
2125+ // add close()
2126+ func = make_new_mfun( "int", "close", MidiMsgOut_close );
2127+ if( !type_engine_import_mfun( env, func ) ) goto error;
2128+
2129+ // add write()
2130+ func = make_new_mfun( "int", "write", MidiMsgOut_write );
2131+ func->add_arg( "MidiMsg", "msg" );
2132+ func->add_arg( "time", "t" );
2133+ if( !type_engine_import_mfun( env, func ) ) goto error;
2134+
2135+ // add member variable
2136+ MidiMsgOut_offset_data = type_engine_import_mvar( env, "int", "@MidiMsgOut_data", FALSE );
2137+ if( MidiMsgOut_offset_data == CK_INVALID_OFFSET ) goto error;
2138+
2139+ // end the class import
2140+ type_engine_import_class_end( env );
2141+
2142+ // init base class
2143+ if( !type_engine_import_class_begin( env, "MidiMsgIn", "Object",
2144+ env->global(), MidiMsgIn_ctor, MidiMsgIn_dtor ) )
2145+ return FALSE;
2146+
2147+ // add open()
2148+ func = make_new_mfun( "int", "open", MidiMsgIn_open );
2149+ func->add_arg( "string", "filename" );
2150+ if( !type_engine_import_mfun( env, func ) ) goto error;
2151+
2152+ // add close()
2153+ func = make_new_mfun( "int", "close", MidiMsgIn_close );
2154+ if( !type_engine_import_mfun( env, func ) ) goto error;
2155+
2156+ // add read()
2157+ func = make_new_mfun( "int", "read", MidiMsgIn_read );
2158+ func->add_arg( "MidiMsg", "msg" );
2159+ //func->add_arg( "time", "t" );
2160+ if( !type_engine_import_mfun( env, func ) ) goto error;
2161+
2162+ // add member variable
2163+ MidiMsgIn_offset_data = type_engine_import_mvar( env, "int", "@MidiMsgIn_data", FALSE );
2164+ if( MidiMsgIn_offset_data == CK_INVALID_OFFSET ) goto error;
2165+
2166+ // end the class import
2167+ type_engine_import_class_end( env );
2168+
2169+#endif // __DISABLE_MIDI__
2170+
2171+ // initialize
2172+ // HidInManager::init();
2173+
2174+ return TRUE;
2175+
2176+error:
2177+
2178+ // end the class import
2179+ type_engine_import_class_end( env );
2180+
2181+ return FALSE;
2182+}
2183+
2184+
2185+
2186+
2187+
2188+
2189+// Object ctor
2190+CK_DLL_CTOR( object_ctor )
2191+{
2192+ // log
2193+ // EM_log( CK_LOG_FINEST, "Object constructor..." );
2194+
2195+ // initialize
2196+ OBJ_MEMBER_UINT(SELF, Object_offset_string) = 0;
2197+}
2198+
2199+
2200+// Object dtor
2201+CK_DLL_DTOR( object_dtor )
2202+{
2203+ // log
2204+ // EM_log( CK_LOG_FINEST, "Object destructor..." );
2205+
2206+ // get the string
2207+ Chuck_String * str = (Chuck_String *)OBJ_MEMBER_UINT(SELF, Object_offset_string);
2208+ // release
2209+ SAFE_RELEASE( str );
2210+}
2211+
2212+
2213+// toString
2214+CK_DLL_MFUN( object_toString )
2215+{
2216+ // get the string
2217+ Chuck_String * str = (Chuck_String *)OBJ_MEMBER_UINT(SELF, Object_offset_string);
2218+ // allocate
2219+ if( !str )
2220+ {
2221+ // new it
2222+ str = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED );
2223+ // check it
2224+ if( !str )
2225+ {
2226+ // TODO: make this exception
2227+ CK_FPRINTF_STDERR( "[chuck]: Object.toString() out of memory!\n" );
2228+ RETURN->v_object = NULL;
2229+ return;
2230+ }
2231+ // set it
2232+ ostringstream strout( ostringstream::out );
2233+ // get the type
2234+ Chuck_Type * type = SELF->type_ref;
2235+ // write
2236+ strout.setf( ios::hex, ios::basefield );
2237+ strout << ((type != NULL) ? type->c_name() : "[VOID]") << ":" << (t_CKUINT)SELF;
2238+ strout.flush();
2239+
2240+ // done
2241+ str->set( strout.str() );
2242+ }
2243+
2244+ // set return
2245+ RETURN->v_object = str;
2246+}
2247+
2248+
2249+// ctor
2250+CK_DLL_CTOR( ugen_ctor )
2251+{
2252+}
2253+
2254+CK_DLL_DTOR( ugen_dtor )
2255+{
2256+ // get as ugen
2257+ // Chuck_UGen * ugen = (Chuck_UGen *)SELF;
2258+}
2259+
2260+CK_DLL_MFUN( ugen_op )
2261+{
2262+ // get as ugen
2263+ Chuck_UGen * ugen = (Chuck_UGen *)SELF;
2264+ // get arg
2265+ t_CKINT op = GET_CK_INT( ARGS );
2266+ // set op
2267+ ugen->m_op = op;
2268+ // set return
2269+ RETURN->v_int = ugen->m_op;
2270+
2271+ // for multiple channels
2272+ Chuck_DL_Return ret;
2273+ // added 1.3.0.0 -- Chuck_DL_Api::Api::instance()
2274+ for( t_CKUINT i = 0; i < ugen->m_multi_chan_size; i++ )
2275+ ugen_op( ugen->m_multi_chan[i], ARGS, &ret, SHRED, API );
2276+ // added 1.3.0.2 -- apply op to subgraph outlet
2277+ if( ugen->inlet() )
2278+ ugen->inlet()->m_op = op;
2279+ if( ugen->outlet() )
2280+ ugen->outlet()->m_op = op;
2281+}
2282+
2283+CK_DLL_MFUN( ugen_cget_op )
2284+{
2285+ // get as ugen
2286+ Chuck_UGen * ugen = (Chuck_UGen *)SELF;
2287+ // set return
2288+ RETURN->v_int = ugen->m_op;
2289+}
2290+
2291+CK_DLL_MFUN( ugen_last )
2292+{
2293+ // get as ugen
2294+ Chuck_UGen * ugen = (Chuck_UGen *)SELF;
2295+ // set return
2296+ // added 1.3.0.2 -- ugen outlet() last if subgraph
2297+ if( ugen->outlet() )
2298+ RETURN->v_float = (t_CKFLOAT) ugen->outlet()->m_last;
2299+ else
2300+ RETURN->v_float = (t_CKFLOAT)ugen->m_last;
2301+}
2302+
2303+CK_DLL_MFUN( ugen_next )
2304+{
2305+ // get as ugen
2306+ Chuck_UGen * ugen = (Chuck_UGen *)SELF;
2307+ // get arg
2308+ t_CKFLOAT next = GET_CK_FLOAT( ARGS );
2309+ // set op
2310+ ugen->m_next = (SAMPLE)next;
2311+ ugen->m_use_next = TRUE;
2312+ // set return
2313+ RETURN->v_float = (t_CKFLOAT)ugen->m_next;
2314+
2315+ // for multiple channels
2316+ Chuck_DL_Return ret;
2317+ // added 1.3.0.0 -- Chuck_DL_Api::Api::instance()
2318+ for( t_CKUINT i = 0; i < ugen->m_multi_chan_size; i++ )
2319+ ugen_next( ugen->m_multi_chan[i], ARGS, &ret, SHRED, API );
2320+ // added 1.3.0.2 -- apply op to subgraph outlet
2321+ if( ugen->outlet() )
2322+ {
2323+ ugen->outlet()->m_next = (SAMPLE) next;
2324+ ugen->outlet()->m_use_next = TRUE;
2325+ }
2326+}
2327+
2328+CK_DLL_MFUN( ugen_cget_next )
2329+{
2330+ // get as ugen
2331+ Chuck_UGen * ugen = (Chuck_UGen *)SELF;
2332+ // set return
2333+ RETURN->v_float = ugen->m_use_next ? (t_CKFLOAT)ugen->m_next : 0.0f;
2334+}
2335+
2336+CK_DLL_MFUN( ugen_gain )
2337+{
2338+ // get as ugen
2339+ Chuck_UGen * ugen = (Chuck_UGen *)SELF;
2340+ // get arg
2341+ t_CKFLOAT gain = GET_CK_FLOAT( ARGS );
2342+ // set op
2343+ ugen->m_gain = (SAMPLE)gain;
2344+ // set return
2345+ RETURN->v_float = (t_CKFLOAT)ugen->m_gain;
2346+
2347+ // for multiple channels
2348+ Chuck_DL_Return ret;
2349+ // added 1.3.0.0 -- Chuck_DL_Api::Api::instance()
2350+ for( t_CKUINT i = 0; i < ugen->m_multi_chan_size; i++ )
2351+ ugen_gain( ugen->m_multi_chan[i], ARGS, &ret, SHRED, API );
2352+ // added 1.3.0.2 -- apply gain to subgraph outlet
2353+ if( ugen->outlet() )
2354+ ugen->outlet()->m_gain = (SAMPLE) gain;
2355+}
2356+
2357+CK_DLL_MFUN( ugen_cget_gain )
2358+{
2359+ // get as ugen
2360+ Chuck_UGen * ugen = (Chuck_UGen *)SELF;
2361+ // set return
2362+ RETURN->v_float = (t_CKFLOAT)ugen->m_gain;
2363+}
2364+
2365+CK_DLL_CTRL( ugen_numChannels )
2366+{
2367+ // get ugen
2368+ //Chuck_UGen * ugen = (Chuck_UGen *)SELF;
2369+ // error
2370+ EM_error3( "setting .numChannels is not yet supported (use the command line)..." );
2371+}
2372+
2373+CK_DLL_CGET( ugen_cget_numChannels )
2374+{
2375+ // get ugen
2376+ Chuck_UGen * ugen = (Chuck_UGen *)SELF;
2377+ // return
2378+ RETURN->v_int = ugen->m_multi_chan_size == 0 ? 1 : ugen->m_multi_chan_size;
2379+}
2380+
2381+CK_DLL_CTRL( ugen_chan )
2382+{
2383+ // get ugen
2384+ Chuck_UGen * ugen = (Chuck_UGen *)SELF;
2385+ t_CKINT num = GET_NEXT_INT(ARGS);
2386+ // check
2387+ if( !ugen->m_multi_chan_size && num == 0 )
2388+ RETURN->v_object = ugen;
2389+ else if( num >= 0 && num < ugen->m_multi_chan_size )
2390+ RETURN->v_object = ugen->m_multi_chan[num];
2391+ else
2392+ RETURN->v_object = NULL;
2393+}
2394+
2395+CK_DLL_CTRL( ugen_connected )
2396+{
2397+ // get ugen
2398+ Chuck_UGen * ugen = (Chuck_UGen *)SELF;
2399+ Chuck_UGen * right = (Chuck_UGen *)GET_NEXT_OBJECT(ARGS);
2400+
2401+ // sanity
2402+ t_CKINT ret = FALSE;
2403+ if( !right )
2404+ {
2405+ ret = FALSE;
2406+ }
2407+ else
2408+ {
2409+ ret = right->is_connected_from( ugen );
2410+ }
2411+
2412+ RETURN->v_int = ret;
2413+}
2414+
2415+
2416+// ctor
2417+CK_DLL_CTOR( uana_ctor )
2418+{
2419+ // make an actual blob
2420+ Chuck_Object * blob = instantiate_and_initialize_object( SHRED->vm_ref->env()->t_uanablob, SHRED );
2421+ // TODO: check out of memory
2422+ assert( blob != NULL );
2423+ // make a blob proxy
2424+ Chuck_UAnaBlobProxy * proxy = new Chuck_UAnaBlobProxy( blob );
2425+ // remember it
2426+ OBJ_MEMBER_INT(SELF, uana_offset_blob) = (t_CKINT)proxy;
2427+ // HACK: DANGER: manually call blob's ctor (added 1.3.0.0 -- Chuck_DL_Api::Api::instance())
2428+ uanablob_ctor( blob, NULL, SHRED, API );
2429+}
2430+
2431+CK_DLL_DTOR( uana_dtor )
2432+{
2433+ // TODO: GC should release the blob!
2434+}
2435+
2436+CK_DLL_MFUN( uana_upchuck )
2437+{
2438+ // get as uana
2439+ Chuck_UAna * uana = (Chuck_UAna *)SELF;
2440+ // get shred
2441+ Chuck_VM_Shred * derhs = SHRED;
2442+ // make sure it's not NULL
2443+ if( !derhs )
2444+ {
2445+ EM_error3( "UAna.upchuck() encountered NULL shred; operation aborting!" );
2446+ return;
2447+ }
2448+
2449+ // get VM
2450+ Chuck_VM * vm = derhs->vm_ref;
2451+ // ensure
2452+ if( !vm )
2453+ {
2454+ EM_error3( "UAna.upchuck() encountered NULL VM ref; operation aborting!" );
2455+ return;
2456+ }
2457+
2458+ // check if time
2459+ if( uana->m_uana_time < vm->shreduler()->now_system )
2460+ {
2461+ // for multiple channels
2462+ Chuck_DL_Return ret;
2463+ // added 1.3.0.0 -- Chuck_DL_Api::Api::instance()
2464+ for( t_CKUINT i = 0; i < uana->m_multi_chan_size; i++ )
2465+ uana_upchuck( uana->m_multi_chan[i], ARGS, &ret, SHRED, API );
2466+
2467+ // tock it (TODO: order relative to multiple channels?)
2468+ uana->system_tock( vm->shreduler()->now_system );
2469+ }
2470+
2471+ // return
2472+ RETURN->v_object = uana->blobProxy()->realblob();
2473+}
2474+
2475+/* CK_DLL_MFUN( uana_blob )
2476+{
2477+ // get as uana
2478+ Chuck_UAna * uana = (Chuck_UAna *)SELF;
2479+
2480+ // TODO: return
2481+ RETURN->v_object = NULL;
2482+} */
2483+
2484+CK_DLL_MFUN( uana_fvals )
2485+{
2486+ // get the fvals array
2487+ Chuck_UAnaBlobProxy * blob = (Chuck_UAnaBlobProxy *)OBJ_MEMBER_INT(SELF, uana_offset_blob);
2488+ RETURN->v_object = &blob->fvals();
2489+}
2490+
2491+CK_DLL_MFUN( uana_cvals )
2492+{
2493+ // get the fvals array
2494+ Chuck_UAnaBlobProxy * blob = (Chuck_UAnaBlobProxy *)OBJ_MEMBER_INT(SELF, uana_offset_blob);
2495+ RETURN->v_object = &blob->cvals();
2496+}
2497+
2498+CK_DLL_MFUN( uana_fval )
2499+{
2500+ // get index
2501+ t_CKINT i = GET_NEXT_INT(ARGS);
2502+ // get the fvals array
2503+ Chuck_UAnaBlobProxy * blob = (Chuck_UAnaBlobProxy *)OBJ_MEMBER_INT(SELF, uana_offset_blob);
2504+ Chuck_Array8 & fvals = blob->fvals();
2505+ // check caps
2506+ if( i < 0 || fvals.size() <= i ) RETURN->v_float = 0;
2507+ else
2508+ {
2509+ // get
2510+ t_CKFLOAT val;
2511+ fvals.get( i, &val );
2512+ RETURN->v_float = val;
2513+ }
2514+}
2515+
2516+CK_DLL_MFUN( uana_cval )
2517+{
2518+ // get index
2519+ t_CKINT i = GET_NEXT_INT(ARGS);
2520+ // get the fvals array
2521+ Chuck_UAnaBlobProxy * blob = (Chuck_UAnaBlobProxy *)OBJ_MEMBER_INT(SELF, uana_offset_blob);
2522+ Chuck_Array16 & cvals = blob->cvals();
2523+ // check caps
2524+ if( i < 0 || cvals.size() <= i ) RETURN->v_complex.re = RETURN->v_complex.im = 0;
2525+ else
2526+ {
2527+ // get
2528+ t_CKCOMPLEX val;
2529+ cvals.get( i, &val );
2530+ RETURN->v_complex = val;
2531+ }
2532+}
2533+
2534+CK_DLL_MFUN( uana_connected )
2535+{
2536+ // get ugen
2537+ Chuck_UAna * uana = (Chuck_UAna *)SELF;
2538+ Chuck_UAna * right = (Chuck_UAna *)GET_NEXT_OBJECT(ARGS);
2539+
2540+ // sanity
2541+ t_CKINT ret = FALSE;
2542+ if( !right )
2543+ {
2544+ ret = FALSE;
2545+ }
2546+ else
2547+ {
2548+ ret = right->is_up_connected_from( uana );
2549+ }
2550+
2551+ RETURN->v_int = ret;
2552+}
2553+
2554+
2555+// blob proxy implementation
2556+Chuck_UAnaBlobProxy::Chuck_UAnaBlobProxy( Chuck_Object * blob )
2557+{
2558+ m_blob = blob;
2559+ assert( m_blob != NULL );
2560+ // add reference
2561+ m_blob->add_ref();
2562+}
2563+
2564+Chuck_UAnaBlobProxy::~Chuck_UAnaBlobProxy()
2565+{
2566+ // release
2567+ SAFE_RELEASE( m_blob );
2568+}
2569+
2570+t_CKTIME & Chuck_UAnaBlobProxy::when()
2571+{
2572+ // TODO: DANGER: is this actually returning correct reference?!
2573+ return OBJ_MEMBER_TIME(m_blob, uanablob_offset_when);
2574+}
2575+
2576+Chuck_Array8 & Chuck_UAnaBlobProxy::fvals()
2577+{
2578+ // TODO: DANGER: is this actually returning correct reference?!
2579+ Chuck_Array8 * arr8 = (Chuck_Array8 *)OBJ_MEMBER_INT(m_blob, uanablob_offset_fvals);
2580+ assert( arr8 != NULL );
2581+ return *arr8;
2582+}
2583+
2584+Chuck_Array16 & Chuck_UAnaBlobProxy::cvals()
2585+{
2586+ // TODO: DANGER: is this actually returning correct reference?!
2587+ Chuck_Array16 * arr16 = (Chuck_Array16 *)OBJ_MEMBER_INT(m_blob, uanablob_offset_cvals);
2588+ assert( arr16 != NULL );
2589+ return *arr16;
2590+}
2591+
2592+// get proxy
2593+Chuck_UAnaBlobProxy * getBlobProxy( const Chuck_UAna * uana )
2594+{
2595+ return (Chuck_UAnaBlobProxy *)OBJ_MEMBER_INT(uana, uana_offset_blob);
2596+}
2597+
2598+// ctor
2599+CK_DLL_CTOR( uanablob_ctor )
2600+{
2601+ // when
2602+ OBJ_MEMBER_TIME(SELF, uanablob_offset_when) = 0;
2603+ // fvals
2604+ Chuck_Array8 * arr8 = new Chuck_Array8( 8 );
2605+ initialize_object( arr8, SHRED->vm_ref->env()->t_array );
2606+ // TODO: check out of memory
2607+ arr8->add_ref();
2608+ OBJ_MEMBER_INT(SELF, uanablob_offset_fvals) = (t_CKINT)arr8;
2609+ // cvals
2610+ Chuck_Array16 * arr16 = new Chuck_Array16( 8 );
2611+ initialize_object( arr16, SHRED->vm_ref->env()->t_array );
2612+ // TODO: check out of memory
2613+ arr16->add_ref();
2614+ OBJ_MEMBER_INT(SELF, uanablob_offset_cvals) = (t_CKINT)arr16;
2615+}
2616+
2617+// dtor
2618+CK_DLL_DTOR( uanablob_dtor )
2619+{
2620+ // get array
2621+ Chuck_Array8 * arr8 = (Chuck_Array8 *)OBJ_MEMBER_INT(SELF, uanablob_offset_fvals);
2622+ // release it
2623+ arr8->release();
2624+ OBJ_MEMBER_INT(SELF, uanablob_offset_fvals) = 0;
2625+
2626+ // get array
2627+ Chuck_Array16 * arr16 = (Chuck_Array16 *)OBJ_MEMBER_INT(SELF, uanablob_offset_cvals);
2628+ // release it
2629+ arr16->release();
2630+ OBJ_MEMBER_INT(SELF, uanablob_offset_cvals) = 0;
2631+
2632+ OBJ_MEMBER_TIME(SELF, uanablob_offset_when) = 0;
2633+}
2634+
2635+CK_DLL_MFUN( uanablob_when )
2636+{
2637+ // set return
2638+ RETURN->v_time = OBJ_MEMBER_TIME(SELF, uanablob_offset_when);
2639+}
2640+
2641+CK_DLL_MFUN( uanablob_fvals )
2642+{
2643+ // set return
2644+ RETURN->v_object = (Chuck_Array8 *)OBJ_MEMBER_INT(SELF, uanablob_offset_fvals);
2645+}
2646+
2647+CK_DLL_MFUN( uanablob_fval )
2648+{
2649+ // get index
2650+ t_CKINT i = GET_NEXT_INT(ARGS);
2651+ // get the fvals array
2652+ Chuck_Array8 * fvals = (Chuck_Array8 *)OBJ_MEMBER_INT(SELF, uanablob_offset_fvals);
2653+ // check caps
2654+ if( i < 0 || fvals->size() <= i ) RETURN->v_float = 0;
2655+ else
2656+ {
2657+ // get
2658+ t_CKFLOAT val;
2659+ fvals->get( i, &val );
2660+ RETURN->v_float = val;
2661+ }
2662+}
2663+
2664+CK_DLL_MFUN( uanablob_cval )
2665+{
2666+ // get index
2667+ t_CKINT i = GET_NEXT_INT(ARGS);
2668+ // get the fvals array
2669+ Chuck_Array16 * cvals = (Chuck_Array16 *)OBJ_MEMBER_INT(SELF, uanablob_offset_cvals);
2670+ // check caps
2671+ if( i < 0 || cvals->size() <= i ) RETURN->v_complex.re = RETURN->v_complex.im = 0;
2672+ else
2673+ {
2674+ // get
2675+ t_CKCOMPLEX val;
2676+ cvals->get( i, &val );
2677+ RETURN->v_complex = val;
2678+ }
2679+}
2680+
2681+CK_DLL_MFUN( uanablob_cvals )
2682+{
2683+ // set return
2684+ RETURN->v_object = (Chuck_Array16 *)OBJ_MEMBER_INT(SELF, uanablob_offset_cvals);
2685+}
2686+
2687+// ctor
2688+CK_DLL_CTOR( event_ctor )
2689+{
2690+// OBJ_MEMBER_INT(SELF, event_offset_data) = (t_CKUINT)new Data_Event;
2691+// Chuck_Event * event = (Chuck_Event *)SELF;
2692+}
2693+
2694+
2695+CK_DLL_DTOR( event_dtor )
2696+{
2697+// delete (Data_Event *)OBJ_MEMBER_INT(SELF, event_offset_data);
2698+}
2699+
2700+CK_DLL_MFUN( event_signal )
2701+{
2702+ Chuck_Event * d = (Chuck_Event *)SELF;
2703+ d->signal();
2704+}
2705+
2706+CK_DLL_MFUN( event_broadcast )
2707+{
2708+ Chuck_Event * d = (Chuck_Event *)SELF;
2709+ d->broadcast();
2710+}
2711+
2712+CK_DLL_MFUN( event_wait )
2713+{
2714+ // Chuck_Event * d = (Chuck_Event *)SELF;
2715+ assert( FALSE );
2716+}
2717+
2718+CK_DLL_MFUN( event_can_wait )
2719+{
2720+ RETURN->v_int = TRUE;
2721+}
2722+
2723+
2724+//-----------------------------------------------------------------------------
2725+// vec3 API
2726+//-----------------------------------------------------------------------------
2727+CK_DLL_MFUN( vec3_set )
2728+{
2729+ // HACK: this is a particularly horrid cast from (Chuck_Object *)
2730+ // t_CKVEC3 is neither a super- or sub-class of Chuck_Object...
2731+ t_CKVEC3 * vec3 = (t_CKVEC3 *)SELF;
2732+ // get index
2733+ vec3->x = GET_NEXT_FLOAT(ARGS);
2734+ vec3->y = GET_NEXT_FLOAT(ARGS);
2735+ vec3->z = GET_NEXT_FLOAT(ARGS);
2736+}
2737+
2738+CK_DLL_MFUN( vec3_setAll )
2739+{
2740+ // get data pointer
2741+ t_CKVEC3 * vec3 = (t_CKVEC3 *)SELF;
2742+ // get index
2743+ vec3->x = vec3->y = vec3->z = GET_NEXT_FLOAT(ARGS);
2744+}
2745+
2746+CK_DLL_MFUN( vec3_magnitude )
2747+{
2748+ // get data pointer
2749+ t_CKVEC3 * vec3 = (t_CKVEC3 *)SELF;
2750+ // compute magnitude
2751+ t_CKFLOAT mag = ::sqrt( vec3->x*vec3->x + vec3->y*vec3->y + vec3->z*vec3->z );
2752+ // return
2753+ RETURN->v_float = mag;
2754+}
2755+
2756+CK_DLL_MFUN( vec3_normalize )
2757+{
2758+ // get data pointer
2759+ t_CKVEC3 * vec3 = (t_CKVEC3 *)SELF;
2760+ // compute magnitude
2761+ t_CKFLOAT mag = ::sqrt( vec3->x*vec3->x + vec3->y*vec3->y + vec3->z*vec3->z );
2762+ // check for zero
2763+ if( mag > 0 )
2764+ {
2765+ vec3->x /= mag;
2766+ vec3->y /= mag;
2767+ vec3->z /= mag;
2768+ }
2769+}
2770+
2771+CK_DLL_MFUN( vec3_interp )
2772+{
2773+ // get data pointer
2774+ t_CKVEC3 * vec3 = (t_CKVEC3 *)SELF;
2775+ // update value based on goal and slew
2776+ vec3->x = (vec3->y - vec3->x) * vec3->z + vec3->x;
2777+ // set return to value so it can used right after if desired
2778+ RETURN->v_float = vec3->x;
2779+}
2780+
2781+CK_DLL_MFUN( vec3_interp_delta_float )
2782+{
2783+ // get data pointer
2784+ t_CKVEC3 * vec3 = (t_CKVEC3 *)SELF;
2785+ // get index
2786+ t_CKFLOAT delta = GET_NEXT_FLOAT(ARGS);
2787+ // update value based on goal and slew
2788+ vec3->x = (vec3->y - vec3->x) * vec3->z * delta + vec3->x;
2789+ // set return to value so it can used right after if desired
2790+ RETURN->v_float = vec3->x;
2791+}
2792+
2793+CK_DLL_MFUN( vec3_interp_delta_dur )
2794+{
2795+ // get data pointer
2796+ t_CKVEC3 * vec3 = (t_CKVEC3 *)SELF;
2797+ // get index
2798+ t_CKDUR delta = GET_NEXT_DUR(ARGS);
2799+ // get srate
2800+ t_CKFLOAT srate = SHRED->vm_ref->srate();
2801+ // update value based on goal and slew
2802+ vec3->x = (vec3->y - vec3->x) * vec3->z * (delta / srate) + vec3->x;
2803+ // set return to value so it can used right after if desired
2804+ RETURN->v_float = vec3->x;
2805+}
2806+
2807+CK_DLL_MFUN( vec3_update_goal )
2808+{
2809+ // get data pointer
2810+ t_CKVEC3 * vec3 = (t_CKVEC3 *)SELF;
2811+ // get index
2812+ t_CKDUR goal = GET_NEXT_DUR(ARGS);
2813+ // set goal
2814+ vec3->y = goal;
2815+}
2816+
2817+CK_DLL_MFUN( vec3_update_goal_slew )
2818+{
2819+ // get data pointer
2820+ t_CKVEC3 * vec3 = (t_CKVEC3 *)SELF;
2821+ // get goal
2822+ t_CKDUR goal = GET_NEXT_DUR(ARGS);
2823+ // get slew
2824+ t_CKDUR slew = GET_NEXT_DUR(ARGS);
2825+ // set goal
2826+ vec3->y = goal;
2827+ // set slew
2828+ vec3->z = slew;
2829+}
2830+
2831+CK_DLL_MFUN( vec3_updateSet_goalAndValue )
2832+{
2833+ // get data pointer
2834+ t_CKVEC3 * vec3 = (t_CKVEC3 *)SELF;
2835+ // get goal
2836+ t_CKDUR goalAndValue = GET_NEXT_DUR(ARGS);
2837+ // set goal and value
2838+ vec3->y = vec3->x = goalAndValue;
2839+}
2840+
2841+CK_DLL_MFUN( vec3_updateSet_goalAndValue_slew )
2842+{
2843+ // get data pointer
2844+ t_CKVEC3 * vec3 = (t_CKVEC3 *)SELF;
2845+ // get goal
2846+ t_CKDUR goalAndValue = GET_NEXT_DUR(ARGS);
2847+ // get slew
2848+ t_CKDUR slew = GET_NEXT_DUR(ARGS);
2849+ // set goal and value
2850+ vec3->y = vec3->x = goalAndValue;
2851+ // set slew
2852+ vec3->z = slew;
2853+}
2854+
2855+
2856+//-----------------------------------------------------------------------------
2857+// vec4 API
2858+//-----------------------------------------------------------------------------
2859+CK_DLL_MFUN( vec4_set )
2860+{
2861+ // HACK: this is a particularly horrid cast from (Chuck_Object *)
2862+ // t_CKVEC3 is neither a super- or sub-class of Chuck_Object...
2863+ t_CKVEC4 * vec3 = (t_CKVEC4 *)SELF;
2864+ // get index
2865+ vec3->x = GET_NEXT_FLOAT(ARGS);
2866+ vec3->y = GET_NEXT_FLOAT(ARGS);
2867+ vec3->z = GET_NEXT_FLOAT(ARGS);
2868+ vec3->w = GET_NEXT_FLOAT(ARGS);
2869+}
2870+
2871+CK_DLL_MFUN( vec4_setAll )
2872+{
2873+ // get data pointer
2874+ t_CKVEC4 * vec4 = (t_CKVEC4 *)SELF;
2875+ // get index
2876+ vec4->x = vec4->y = vec4->z = vec4->w = GET_NEXT_FLOAT(ARGS);
2877+}
2878+
2879+CK_DLL_MFUN( vec4_magnitude )
2880+{
2881+ // get data pointer
2882+ t_CKVEC4 * vec4 = (t_CKVEC4 *)SELF;
2883+ // compute magnitude
2884+ t_CKFLOAT mag = ::sqrt( vec4->x*vec4->x + vec4->y*vec4->y
2885+ + vec4->z*vec4->z + vec4->w*vec4->w );
2886+ // return
2887+ RETURN->v_float = mag;
2888+}
2889+
2890+CK_DLL_MFUN( vec4_normalize )
2891+{
2892+ // get data pointer
2893+ t_CKVEC4 * vec4 = (t_CKVEC4 *)SELF;
2894+ // compute magnitude
2895+ t_CKFLOAT mag = ::sqrt( vec4->x*vec4->x + vec4->y*vec4->y
2896+ + vec4->z*vec4->z + vec4->w*vec4->w );
2897+ // check for zero
2898+ if( mag > 0 )
2899+ {
2900+ vec4->x /= mag;
2901+ vec4->y /= mag;
2902+ vec4->z /= mag;
2903+ vec4->w /= mag;
2904+ }
2905+}
2906+
2907+
2908+//-----------------------------------------------------------------------------
2909+// IO API
2910+//-----------------------------------------------------------------------------
2911+CK_DLL_MFUN( io_dummy )
2912+{
2913+ EM_error3( "(IO): internal error! inside an abstract function! help!" );
2914+ EM_error3( " note: please hunt down someone (e.g., Ge) to fix this..." );
2915+ assert( FALSE );
2916+ RETURN->v_int = 0;
2917+}
2918+
2919+CK_DLL_SFUN( io_newline )
2920+{
2921+ RETURN->v_string = g_newline;
2922+}
2923+
2924+
2925+//-----------------------------------------------------------------------------
2926+// FileIO API
2927+//-----------------------------------------------------------------------------
2928+CK_DLL_CTOR( fileio_ctor )
2929+{ }
2930+
2931+CK_DLL_DTOR( fileio_dtor )
2932+{ }
2933+
2934+CK_DLL_MFUN( fileio_open )
2935+{
2936+ std::string filename = GET_NEXT_STRING(ARGS)->str();
2937+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
2938+ t_CKINT default_flags =
2939+ Chuck_IO_File::FLAG_READ_WRITE | Chuck_IO_File::TYPE_ASCII;
2940+
2941+ RETURN->v_int = f->open(filename, default_flags);
2942+}
2943+
2944+CK_DLL_MFUN( fileio_openflags )
2945+{
2946+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
2947+ std::string filename = GET_NEXT_STRING(ARGS)->str();
2948+ t_CKINT flags = GET_NEXT_INT(ARGS);
2949+
2950+ RETURN->v_int = f->open(filename, flags);
2951+}
2952+
2953+CK_DLL_MFUN( fileio_close )
2954+{
2955+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
2956+ f->close();
2957+}
2958+
2959+CK_DLL_MFUN( fileio_good )
2960+{
2961+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
2962+ RETURN->v_int = f->good();
2963+}
2964+
2965+CK_DLL_MFUN( fileio_flush )
2966+{
2967+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
2968+ f->flush();
2969+}
2970+
2971+CK_DLL_MFUN( fileio_getmode )
2972+{
2973+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
2974+ RETURN->v_int = f->mode();
2975+}
2976+
2977+CK_DLL_MFUN( fileio_setmode )
2978+{
2979+ t_CKINT flag = GET_NEXT_INT(ARGS);
2980+
2981+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
2982+ f->mode( flag );
2983+ RETURN->v_int = 0;
2984+}
2985+
2986+CK_DLL_MFUN( fileio_size )
2987+{
2988+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
2989+ RETURN->v_int = f->size();
2990+}
2991+
2992+CK_DLL_MFUN( fileio_seek )
2993+{
2994+ t_CKINT pos = GET_NEXT_INT(ARGS);
2995+
2996+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
2997+ f->seek(pos);
2998+}
2999+
3000+CK_DLL_MFUN( fileio_tell )
3001+{
3002+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
3003+ RETURN->v_int = f->tell();
3004+}
3005+
3006+CK_DLL_MFUN( fileio_isdir )
3007+{
3008+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
3009+ RETURN->v_int = f->isDir();
3010+}
3011+
3012+CK_DLL_MFUN( fileio_dirlist )
3013+{
3014+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
3015+ Chuck_Array4 * a = f->dirList();
3016+ RETURN->v_object = a;
3017+}
3018+
3019+/*
3020+CK_DLL_MFUN( fileio_read )
3021+{
3022+ t_CKINT len = GET_NEXT_INT(ARGS);
3023+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
3024+
3025+ Chuck_String * s = f->read( len );
3026+ RETURN->v_object = s;
3027+}
3028+*/
3029+
3030+CK_DLL_MFUN( fileio_readline )
3031+{
3032+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
3033+ Chuck_String * ret = f->readLine();
3034+ RETURN->v_object = ret;
3035+}
3036+
3037+CK_DLL_MFUN( fileio_readint )
3038+{
3039+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
3040+ t_CKINT defaultflags = Chuck_IO::INT32;
3041+
3042+ /* (ATODO: doesn't look like asynchronous reading will work)
3043+ if (f->mode() == Chuck_IO::MODE_ASYNC)
3044+ {
3045+ // set up arguments
3046+ Chuck_IO::async_args *args = new Chuck_IO::async_args;
3047+ args->RETURN = (void *)RETURN;
3048+ args->fileio_obj = f;
3049+ args->intArg = defaultflags;
3050+ // set shred to wait for I/O completion
3051+ f->m_asyncEvent->wait( SHRED, SHRED->vm_ref );
3052+ // start thread
3053+ bool ret = f->m_thread->start( f->readInt_thread, (void *)args );
3054+ if (!ret) {
3055+ cerr << "m_thread->start failed; recreating m_thread" << endl;
3056+ delete f->m_thread;
3057+ f->m_thread = new XThread;
3058+ ret = f->m_thread->start( f->readInt_thread, (void *)args );
3059+ if (!ret) {
3060+ EM_error3( "(FileIO): failed to start thread for asynchronous mode I/O" );
3061+ }
3062+ }
3063+ } else {*/
3064+ t_CKINT ret = f->readInt( defaultflags );
3065+ RETURN->v_int = ret;
3066+ //}
3067+ // ATODO: Debug
3068+ //sleep(1);
3069+ //cerr << "fileio_readint exiting" << endl;
3070+}
3071+
3072+CK_DLL_MFUN( fileio_readintflags )
3073+{
3074+ t_CKINT flags = GET_NEXT_INT(ARGS);
3075+
3076+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
3077+ t_CKINT ret = f->readInt( flags );
3078+
3079+ RETURN->v_int = ret;
3080+}
3081+
3082+CK_DLL_MFUN( fileio_readfloat )
3083+{
3084+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
3085+ t_CKFLOAT ret = f->readFloat();
3086+ RETURN->v_float = ret;
3087+}
3088+
3089+CK_DLL_MFUN( fileio_eof )
3090+{
3091+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
3092+ t_CKBOOL ret = f->eof();
3093+ RETURN->v_int = ret;
3094+}
3095+
3096+CK_DLL_MFUN( fileio_more )
3097+{
3098+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
3099+ t_CKBOOL ret = !f->eof();
3100+ RETURN->v_int = ret;
3101+}
3102+
3103+CK_DLL_MFUN( fileio_writestring )
3104+{
3105+ std::string val = GET_NEXT_STRING(ARGS)->str();
3106+
3107+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
3108+ if (f->mode() == Chuck_IO::MODE_ASYNC)
3109+ {
3110+ // set up arguments
3111+ Chuck_IO::async_args *args = new Chuck_IO::async_args;
3112+ args->RETURN = (void *)RETURN;
3113+ args->fileio_obj = f;
3114+ args->stringArg = std::string(val);
3115+ // set shred to wait for I/O completion
3116+ assert( SHRED != NULL );
3117+ f->m_asyncEvent->wait( SHRED, SHRED->vm_ref );
3118+ // start thread
3119+ bool ret = f->m_thread->start( f->writeStr_thread, (void *)args );
3120+ if (!ret) {
3121+ // for some reason, the XThread object needs to be
3122+ // deleted and reconstructed every time after call #375
3123+ delete f->m_thread;
3124+ f->m_thread = new XThread;
3125+ ret = f->m_thread->start( f->writeStr_thread, (void *)args );
3126+ if (!ret) {
3127+ EM_error3( "(FileIO): failed to start thread for asynchronous mode I/O" );
3128+ }
3129+ }
3130+ } else {
3131+ f->write(val);
3132+ }
3133+}
3134+
3135+CK_DLL_MFUN( fileio_writeint )
3136+{
3137+ t_CKINT val = GET_NEXT_INT(ARGS);
3138+
3139+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
3140+ if (f->mode() == Chuck_IO::MODE_ASYNC)
3141+ {
3142+ // set up arguments
3143+ Chuck_IO::async_args *args = new Chuck_IO::async_args;
3144+ args->RETURN = (void *)RETURN;
3145+ args->fileio_obj = f;
3146+ args->intArg = val;
3147+ // set shred to wait for I/O completion
3148+ assert( SHRED != NULL );
3149+ f->m_asyncEvent->wait( SHRED, SHRED->vm_ref );
3150+ // start thread
3151+ bool ret = f->m_thread->start( f->writeInt_thread, (void *)args );
3152+ if (!ret) {
3153+ // for some reason, the XThread object needs to be
3154+ // deleted and reconstructed every time after call #375
3155+ delete f->m_thread;
3156+ f->m_thread = new XThread;
3157+ ret = f->m_thread->start( f->writeInt_thread, (void *)args );
3158+ if (!ret) {
3159+ EM_error3( "(FileIO): failed to start thread for asynchronous mode I/O" );
3160+ }
3161+ }
3162+ } else {
3163+ f->write(val);
3164+ }
3165+}
3166+
3167+CK_DLL_MFUN( fileio_writeintflags )
3168+{
3169+ t_CKINT val = GET_NEXT_INT(ARGS);
3170+ t_CKINT flags = GET_NEXT_INT(ARGS);
3171+
3172+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
3173+ if (f->mode() == Chuck_IO::MODE_ASYNC)
3174+ {
3175+ // TODO: pass flags in args
3176+ // set up arguments
3177+ Chuck_IO::async_args *args = new Chuck_IO::async_args;
3178+ args->RETURN = (void *)RETURN;
3179+ args->fileio_obj = f;
3180+ args->intArg = val;
3181+ // set shred to wait for I/O completion
3182+ assert( SHRED != NULL );
3183+ f->m_asyncEvent->wait( SHRED, SHRED->vm_ref );
3184+ // start thread
3185+ bool ret = f->m_thread->start( f->writeInt_thread, (void *)args );
3186+ if (!ret) {
3187+ // for some reason, the XThread object needs to be
3188+ // deleted and reconstructed every time after call #375
3189+ delete f->m_thread;
3190+ f->m_thread = new XThread;
3191+ ret = f->m_thread->start( f->writeInt_thread, (void *)args );
3192+ if (!ret) {
3193+ EM_error3( "(FileIO): failed to start thread for asynchronous mode I/O" );
3194+ }
3195+ }
3196+ } else {
3197+ f->write(val, flags);
3198+ }
3199+}
3200+
3201+CK_DLL_MFUN( fileio_writefloat )
3202+{
3203+ t_CKFLOAT val = GET_NEXT_FLOAT(ARGS);
3204+
3205+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
3206+ if (f->mode() == Chuck_IO::MODE_ASYNC)
3207+ {
3208+ // set up arguments
3209+ Chuck_IO::async_args *args = new Chuck_IO::async_args;
3210+ args->RETURN = (void *)RETURN;
3211+ args->fileio_obj = f;
3212+ args->floatArg = val;
3213+ // set shred to wait for I/O completion
3214+ assert( SHRED != NULL );
3215+ f->m_asyncEvent->wait( SHRED, SHRED->vm_ref );
3216+ // start thread
3217+ bool ret = f->m_thread->start( f->writeFloat_thread, (void *)args );
3218+ if (!ret) {
3219+ // for some reason, the XThread object needs to be
3220+ // deleted and reconstructed every time after call #375
3221+ delete f->m_thread;
3222+ f->m_thread = new XThread;
3223+ ret = f->m_thread->start( f->writeFloat_thread, (void *)args );
3224+ if (!ret) {
3225+ EM_error3( "(FileIO): failed to start thread for asynchronous mode I/O" );
3226+ }
3227+ }
3228+ } else {
3229+ f->write(val);
3230+ }
3231+}
3232+
3233+
3234+//-----------------------------------------------------------------------------
3235+// Chout API
3236+//-----------------------------------------------------------------------------
3237+CK_DLL_MFUN( chout_close )
3238+{
3239+ // problem
3240+ CK_FPRINTF_STDERR( "[chuck]: cannot close 'chout'...\n" );
3241+ Chuck_IO_Chout * c = SHRED->vm_ref->chout();
3242+ c->close();
3243+}
3244+
3245+CK_DLL_MFUN( chout_good )
3246+{
3247+ Chuck_IO_Chout * c = SHRED->vm_ref->chout();
3248+ RETURN->v_int = c->good();
3249+}
3250+
3251+CK_DLL_MFUN( chout_flush )
3252+{
3253+ Chuck_IO_Chout * c = SHRED->vm_ref->chout();
3254+ c->flush();
3255+}
3256+
3257+CK_DLL_MFUN( chout_getmode )
3258+{
3259+ // problem
3260+ Chuck_IO_Chout * c = SHRED->vm_ref->chout();
3261+ RETURN->v_int = c->mode();
3262+}
3263+
3264+CK_DLL_MFUN( chout_setmode )
3265+{
3266+ Chuck_IO_Chout * c = SHRED->vm_ref->chout();
3267+ c->mode( GET_NEXT_INT(ARGS) );
3268+ RETURN->v_int = c->mode();
3269+}
3270+
3271+/*
3272+ CK_DLL_MFUN( chout_read )
3273+ {
3274+ t_CKINT len = GET_NEXT_INT(ARGS);
3275+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
3276+
3277+ Chuck_String * s = f->read( len );
3278+ RETURN->v_object = s;
3279+ }
3280+ */
3281+
3282+CK_DLL_MFUN( chout_readline )
3283+{
3284+ Chuck_IO_Chout * c = SHRED->vm_ref->chout();
3285+ Chuck_String * ret = c->readLine();
3286+ RETURN->v_object = ret;
3287+}
3288+
3289+CK_DLL_MFUN( chout_readint )
3290+{
3291+ Chuck_IO_Chout * c = SHRED->vm_ref->chout();
3292+ RETURN->v_int = c->readInt( Chuck_IO::INT32 );
3293+}
3294+
3295+CK_DLL_MFUN( chout_readintflags )
3296+{
3297+ t_CKINT flags = GET_NEXT_INT(ARGS);
3298+
3299+ Chuck_IO_Chout * c = SHRED->vm_ref->chout();
3300+ t_CKINT ret = c->readInt( flags );
3301+
3302+ RETURN->v_int = ret;
3303+}
3304+
3305+CK_DLL_MFUN( chout_readfloat )
3306+{
3307+ Chuck_IO_Chout * c = SHRED->vm_ref->chout();
3308+ t_CKFLOAT ret = c->readFloat();
3309+ RETURN->v_float = ret;
3310+}
3311+
3312+CK_DLL_MFUN( chout_eof )
3313+{
3314+ Chuck_IO_Chout * c = SHRED->vm_ref->chout();
3315+ t_CKBOOL ret = c->eof();
3316+ RETURN->v_int = ret;
3317+}
3318+
3319+CK_DLL_MFUN( chout_more )
3320+{
3321+ Chuck_IO_Chout * c = SHRED->vm_ref->chout();
3322+ t_CKBOOL ret = !c->eof();
3323+ RETURN->v_int = ret;
3324+}
3325+
3326+CK_DLL_MFUN( chout_writestring )
3327+{
3328+ std::string val = GET_NEXT_STRING(ARGS)->str();
3329+
3330+ Chuck_IO_Chout * c = SHRED->vm_ref->chout();
3331+ c->write( val );
3332+}
3333+
3334+CK_DLL_MFUN( chout_writeint )
3335+{
3336+ t_CKINT val = GET_NEXT_INT(ARGS);
3337+
3338+ Chuck_IO_Chout * c = SHRED->vm_ref->chout();
3339+ c->write(val);
3340+}
3341+
3342+CK_DLL_MFUN( chout_writefloat )
3343+{
3344+ t_CKFLOAT val = GET_NEXT_FLOAT(ARGS);
3345+
3346+ Chuck_IO_Chout * c = SHRED->vm_ref->chout();
3347+ c->write(val);
3348+}
3349+
3350+
3351+
3352+
3353+//-----------------------------------------------------------------------------
3354+// Cherr API
3355+//-----------------------------------------------------------------------------
3356+CK_DLL_MFUN( cherr_close )
3357+{
3358+ // problem
3359+ CK_FPRINTF_STDERR( "[chuck]: cannot close 'cherr'...\n" );
3360+ Chuck_IO_Cherr * c = SHRED->vm_ref->cherr();
3361+ c->close();
3362+}
3363+
3364+CK_DLL_MFUN( cherr_good )
3365+{
3366+ Chuck_IO_Cherr * c = SHRED->vm_ref->cherr();
3367+ RETURN->v_int = c->good();
3368+}
3369+
3370+CK_DLL_MFUN( cherr_flush )
3371+{
3372+ Chuck_IO_Cherr * c = SHRED->vm_ref->cherr();
3373+ c->flush();
3374+}
3375+
3376+CK_DLL_MFUN( cherr_getmode )
3377+{
3378+ // problem
3379+ Chuck_IO_Cherr * c = SHRED->vm_ref->cherr();
3380+ RETURN->v_int = c->mode();
3381+}
3382+
3383+CK_DLL_MFUN( cherr_setmode )
3384+{
3385+ Chuck_IO_Cherr * c = SHRED->vm_ref->cherr();
3386+ c->mode( GET_NEXT_INT(ARGS) );
3387+ RETURN->v_int = c->mode();
3388+}
3389+
3390+/*
3391+ CK_DLL_MFUN( cherr_read )
3392+ {
3393+ t_CKINT len = GET_NEXT_INT(ARGS);
3394+ Chuck_IO_File * f = (Chuck_IO_File *)SELF;
3395+
3396+ Chuck_String * s = f->read( len );
3397+ RETURN->v_object = s;
3398+ }
3399+ */
3400+
3401+CK_DLL_MFUN( cherr_readline )
3402+{
3403+ Chuck_IO_Cherr * c = SHRED->vm_ref->cherr();
3404+ Chuck_String * ret = c->readLine();
3405+ RETURN->v_object = ret;
3406+}
3407+
3408+CK_DLL_MFUN( cherr_readint )
3409+{
3410+ Chuck_IO_Cherr * c = SHRED->vm_ref->cherr();
3411+ RETURN->v_int = c->readInt( Chuck_IO::INT32 );
3412+}
3413+
3414+CK_DLL_MFUN( cherr_readintflags )
3415+{
3416+ t_CKINT flags = GET_NEXT_INT(ARGS);
3417+
3418+ Chuck_IO_Cherr * c = SHRED->vm_ref->cherr();
3419+ t_CKINT ret = c->readInt( flags );
3420+
3421+ RETURN->v_int = ret;
3422+}
3423+
3424+CK_DLL_MFUN( cherr_readfloat )
3425+{
3426+ Chuck_IO_Cherr * c = SHRED->vm_ref->cherr();
3427+ t_CKFLOAT ret = c->readFloat();
3428+ RETURN->v_float = ret;
3429+}
3430+
3431+CK_DLL_MFUN( cherr_eof )
3432+{
3433+ Chuck_IO_Cherr * c = SHRED->vm_ref->cherr();
3434+ t_CKBOOL ret = c->eof();
3435+ RETURN->v_int = ret;
3436+}
3437+
3438+CK_DLL_MFUN( cherr_more )
3439+{
3440+ Chuck_IO_Cherr * c = SHRED->vm_ref->cherr();
3441+ t_CKBOOL ret = !c->eof();
3442+ RETURN->v_int = ret;
3443+}
3444+
3445+CK_DLL_MFUN( cherr_writestring )
3446+{
3447+ std::string val = GET_NEXT_STRING(ARGS)->str();
3448+
3449+ Chuck_IO_Cherr * c = SHRED->vm_ref->cherr();
3450+ c->write( val );
3451+}
3452+
3453+CK_DLL_MFUN( cherr_writeint )
3454+{
3455+ t_CKINT val = GET_NEXT_INT(ARGS);
3456+
3457+ Chuck_IO_Chout * c = SHRED->vm_ref->chout();
3458+ c->write(val);
3459+}
3460+
3461+CK_DLL_MFUN( cherr_writefloat )
3462+{
3463+ t_CKFLOAT val = GET_NEXT_FLOAT(ARGS);
3464+
3465+ Chuck_IO_Cherr * c = SHRED->vm_ref->cherr();
3466+ c->write(val);
3467+}
3468+
3469+
3470+
3471+
3472+//-----------------------------------------------------------------------------
3473+// Shred API
3474+//-----------------------------------------------------------------------------
3475+
3476+//CK_DLL_CTOR( shred_ctor );
3477+//CK_DLL_DTOR( shred_dtor ); //
3478+
3479+CK_DLL_MFUN( shred_exit )
3480+{
3481+ Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF;
3482+ // end the shred
3483+ derhs->is_done = TRUE;
3484+ derhs->is_running = FALSE;
3485+}
3486+
3487+CK_DLL_MFUN( shred_running )
3488+{
3489+ Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF;
3490+ RETURN->v_int = derhs->is_running;
3491+}
3492+
3493+CK_DLL_MFUN( shred_done )
3494+{
3495+ Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF;
3496+ RETURN->v_int = derhs->is_done;
3497+}
3498+
3499+CK_DLL_MFUN( shred_clone )
3500+{
3501+}
3502+
3503+CK_DLL_MFUN( shred_id )
3504+{
3505+ Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF;
3506+ // return the id
3507+ RETURN->v_int = derhs->xid;
3508+}
3509+
3510+CK_DLL_MFUN( shred_yield )
3511+{
3512+ Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF;
3513+ Chuck_VM * vm = derhs->vm_ref;
3514+
3515+ // suspend
3516+ derhs->is_running = FALSE;
3517+ // reshredule
3518+ vm->shreduler()->shredule( derhs, derhs->now );
3519+}
3520+
3521+CK_DLL_MFUN( shred_numArgs )
3522+{
3523+ Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF;
3524+
3525+ // get the number of arguments
3526+ RETURN->v_int = derhs->args.size();
3527+}
3528+
3529+CK_DLL_MFUN( shred_getArg )
3530+{
3531+ Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF;
3532+
3533+ // get index
3534+ t_CKINT i = GET_NEXT_INT(ARGS);
3535+ // total
3536+ t_CKINT num = derhs->args.size();
3537+
3538+ Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED );
3539+ str->set( ( i < num ? derhs->args[i] : "" ) );
3540+ RETURN->v_string = str;
3541+}
3542+
3543+CK_DLL_MFUN( shred_sourcePath ) // added 1.3.0.0
3544+{
3545+ Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF;
3546+
3547+ Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED );
3548+ str->set( derhs->code->filename );
3549+ RETURN->v_string = str;
3550+}
3551+
3552+CK_DLL_MFUN( shred_sourceDir ) // added 1.3.0.0
3553+{
3554+ Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF;
3555+
3556+ Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED );
3557+
3558+ str->set( extract_filepath_dir(derhs->code->filename) );
3559+
3560+ RETURN->v_string = str;
3561+}
3562+
3563+CK_DLL_MFUN( shred_sourceDir2 ) // added 1.3.2.0
3564+{
3565+ Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF;
3566+ // get num up
3567+ t_CKINT i = GET_NEXT_INT(ARGS);
3568+ // abs
3569+ if( i < 0 ) i = -i;
3570+
3571+ // new chuck string
3572+ Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED );
3573+ // set the content
3574+ str->set( extract_filepath_dir(derhs->code->filename) );
3575+ // up
3576+ str->set( dir_go_up( str->str(), i ) );
3577+
3578+ RETURN->v_string = str;
3579+}
3580+
3581+
3582+CK_DLL_SFUN( shred_fromId ) // added 1.3.2.0
3583+{
3584+ t_CKINT shred_id = GET_NEXT_INT(ARGS);
3585+
3586+ Chuck_VM_Shred * derhs = SHRED->vm_ref->shreduler()->lookup(shred_id);
3587+
3588+ RETURN->v_object = derhs;
3589+}
3590+
3591+
3592+CK_DLL_MFUN( string_length )
3593+{
3594+ Chuck_String * s = (Chuck_String *)SELF;
3595+ RETURN->v_int = s->str().length();
3596+}
3597+
3598+CK_DLL_MFUN( string_upper )
3599+{
3600+ Chuck_String * s = (Chuck_String *)SELF;
3601+ Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED );
3602+ str->set( toupper( s->str() ) );
3603+ RETURN->v_string = str;
3604+}
3605+
3606+CK_DLL_MFUN( string_lower )
3607+{
3608+ Chuck_String * s = (Chuck_String *)SELF;
3609+ Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED );
3610+ str->set( tolower( s->str() ) );
3611+ RETURN->v_string = str;
3612+}
3613+
3614+CK_DLL_MFUN( string_ltrim )
3615+{
3616+ Chuck_String * s = (Chuck_String *)SELF;
3617+ Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED );
3618+ str->set( ltrim( s->str() ) );
3619+ RETURN->v_string = str;
3620+}
3621+
3622+CK_DLL_MFUN( string_rtrim )
3623+{
3624+ Chuck_String * s = (Chuck_String *)SELF;
3625+ Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED );
3626+ str->set( rtrim( s->str() ) );
3627+ RETURN->v_string = str;
3628+}
3629+
3630+CK_DLL_MFUN( string_trim )
3631+{
3632+ Chuck_String * s = (Chuck_String *)SELF;
3633+ Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED );
3634+ str->set( trim( s->str() ) );
3635+ RETURN->v_string = str;
3636+}
3637+
3638+CK_DLL_MFUN( string_toString )
3639+{
3640+ Chuck_String * s = (Chuck_String *)SELF;
3641+ RETURN->v_string = s;
3642+}
3643+
3644+CK_DLL_MFUN(string_charAt)
3645+{
3646+ Chuck_String * str = (Chuck_String *) SELF;
3647+ t_CKINT index = GET_NEXT_INT(ARGS);
3648+
3649+ if(index < 0 || index >= str->str().length())
3650+ {
3651+ throw_exception(SHRED, "IndexOutOfBoundsException", index);
3652+ RETURN->v_int = -1;
3653+ return;
3654+ }
3655+
3656+ RETURN->v_int = str->str().at(index);
3657+}
3658+
3659+CK_DLL_MFUN(string_setCharAt)
3660+{
3661+ Chuck_String * str = (Chuck_String *) SELF;
3662+ t_CKINT index = GET_NEXT_INT(ARGS);
3663+ t_CKINT the_char = GET_NEXT_INT(ARGS);
3664+
3665+ if(index < 0 || index >= str->str().length())
3666+ {
3667+ throw_exception(SHRED, "IndexOutOfBoundsException", index);
3668+ RETURN->v_int = -1;
3669+ return;
3670+ }
3671+
3672+ // str->str.at(index) = the_char;
3673+ std::string s = str->str();
3674+ s.at(index) = the_char;
3675+ str->set( s );
3676+ RETURN->v_int = str->str().at(index);
3677+}
3678+
3679+CK_DLL_MFUN(string_substring)
3680+{
3681+ Chuck_String * str = (Chuck_String *) SELF;
3682+ t_CKINT start = GET_NEXT_INT(ARGS);
3683+
3684+ if(start < 0 || start >= str->str().length())
3685+ {
3686+ throw_exception(SHRED, "IndexOutOfBoundsException", start);
3687+ RETURN->v_string = NULL;
3688+ return;
3689+ }
3690+
3691+ Chuck_String * ss = (Chuck_String *) instantiate_and_initialize_object(SHRED->vm_ref->env()->t_string, SHRED);
3692+ ss->set( str->str().substr(start) );
3693+
3694+ RETURN->v_string = ss;
3695+}
3696+
3697+CK_DLL_MFUN(string_substringN)
3698+{
3699+ Chuck_String * str = (Chuck_String *) SELF;
3700+ t_CKINT start = GET_NEXT_INT(ARGS);
3701+ t_CKINT length = GET_NEXT_INT(ARGS);
3702+
3703+ if(start < 0 || start >= str->str().length())
3704+ {
3705+ throw_exception(SHRED, "IndexOutOfBoundsException", start);
3706+ RETURN->v_string = NULL;
3707+ return;
3708+ }
3709+
3710+ if(length < 0 || start+length > str->str().length())
3711+ {
3712+ throw_exception(SHRED, "IndexOutOfBoundsException", length);
3713+ RETURN->v_string = NULL;
3714+ return;
3715+ }
3716+
3717+ Chuck_String * ss = (Chuck_String *) instantiate_and_initialize_object(SHRED->vm_ref->env()->t_string, SHRED);
3718+ ss->set( str->str().substr(start, length) );
3719+
3720+ RETURN->v_string = ss;
3721+}
3722+
3723+CK_DLL_MFUN(string_insert)
3724+{
3725+ Chuck_String * str = (Chuck_String *) SELF;
3726+ t_CKINT position = GET_NEXT_INT(ARGS);
3727+ Chuck_String * str2 = GET_NEXT_STRING(ARGS);
3728+
3729+ if(position < 0 || position >= str->str().length())
3730+ {
3731+ throw_exception(SHRED, "IndexOutOfBoundsException", position);
3732+ return;
3733+ }
3734+ if(str2 == NULL)
3735+ {
3736+ throw_exception(SHRED, "NullPointerException");
3737+ return;
3738+ }
3739+
3740+ // str->str.insert(position, str2->str);
3741+ std::string s = str->str();
3742+ s.insert( position, str2->str() );
3743+ str->set( s );
3744+}
3745+
3746+CK_DLL_MFUN(string_replace)
3747+{
3748+ Chuck_String * str = (Chuck_String *) SELF;
3749+ t_CKINT position = GET_NEXT_INT(ARGS);
3750+ Chuck_String * str2 = GET_NEXT_STRING(ARGS);
3751+
3752+ if(position < 0 || position >= str->str().length())
3753+ {
3754+ throw_exception(SHRED, "IndexOutOfBoundsException", position);
3755+ return;
3756+ }
3757+ if(str2 == NULL)
3758+ {
3759+ throw_exception(SHRED, "NullPointerException");
3760+ return;
3761+ }
3762+
3763+ string::size_type length;
3764+ if(position + str2->str().length() > str->str().length())
3765+ length = str->str().length() - position;
3766+ else
3767+ length = str2->str().length();
3768+
3769+ // str->str.replace(position, length, str2->str);
3770+ std::string s = str->str();
3771+ s.replace( position, length, str2->str() );
3772+ str->set( s );
3773+}
3774+
3775+CK_DLL_MFUN(string_replaceN)
3776+{
3777+ Chuck_String * str = (Chuck_String *) SELF;
3778+ t_CKINT position = GET_NEXT_INT(ARGS);
3779+ t_CKINT length = GET_NEXT_INT(ARGS);
3780+ Chuck_String * str2 = GET_NEXT_STRING(ARGS);
3781+
3782+ if(position < 0 || position >= str->str().length())
3783+ {
3784+ throw_exception(SHRED, "IndexOutOfBoundsException", position);
3785+ return;
3786+ }
3787+
3788+ if(length < 0 || position+length > str->str().length())
3789+ {
3790+ throw_exception(SHRED, "IndexOutOfBoundsException", length);
3791+ return;
3792+ }
3793+
3794+ if(str2 == NULL)
3795+ {
3796+ throw_exception(SHRED, "NullPointerException");
3797+ return;
3798+ }
3799+
3800+ // str->str.replace(position, length, str2->str);
3801+ std::string s = str->str();
3802+ s.replace( position, length, str2->str() );
3803+ str->set( s );
3804+}
3805+
3806+CK_DLL_MFUN(string_find)
3807+{
3808+ Chuck_String * str = (Chuck_String *) SELF;
3809+ t_CKINT the_char = GET_NEXT_INT(ARGS);
3810+
3811+ string::size_type index = str->str().find(the_char);
3812+
3813+ if(index == string::npos)
3814+ RETURN->v_int = -1;
3815+ else
3816+ RETURN->v_int = index;
3817+}
3818+
3819+CK_DLL_MFUN(string_findStart)
3820+{
3821+ Chuck_String * str = (Chuck_String *) SELF;
3822+ t_CKINT the_char = GET_NEXT_INT(ARGS);
3823+ t_CKINT start = GET_NEXT_INT(ARGS);
3824+
3825+ if(start < 0 || start >= str->str().length())
3826+ {
3827+ throw_exception(SHRED, "IndexOutOfBoundsException", start);
3828+ RETURN->v_int = -1;
3829+ return;
3830+ }
3831+
3832+ string::size_type index = str->str().find(the_char, start);
3833+
3834+ if(index == string::npos)
3835+ RETURN->v_int = -1;
3836+ else
3837+ RETURN->v_int = index;
3838+}
3839+
3840+CK_DLL_MFUN(string_findStr)
3841+{
3842+ Chuck_String * str = (Chuck_String *) SELF;
3843+ Chuck_String * the_str = GET_NEXT_STRING(ARGS);
3844+
3845+ string::size_type index = str->str().find(the_str->str());
3846+
3847+ if(index == string::npos)
3848+ RETURN->v_int = -1;
3849+ else
3850+ RETURN->v_int = index;
3851+}
3852+
3853+CK_DLL_MFUN(string_findStrStart)
3854+{
3855+ Chuck_String * str = (Chuck_String *) SELF;
3856+ Chuck_String * the_str = GET_NEXT_STRING(ARGS);
3857+ t_CKINT start = GET_NEXT_INT(ARGS);
3858+
3859+ if(start < 0 || start >= str->str().length())
3860+ {
3861+ throw_exception(SHRED, "IndexOutOfBoundsException", start);
3862+ RETURN->v_int = -1;
3863+ return;
3864+ }
3865+
3866+ string::size_type index = str->str().find(the_str->str(), start);
3867+
3868+ if(index == string::npos)
3869+ RETURN->v_int = -1;
3870+ else
3871+ RETURN->v_int = index;
3872+}
3873+
3874+CK_DLL_MFUN(string_rfind)
3875+{
3876+ Chuck_String * str = (Chuck_String *) SELF;
3877+ t_CKINT the_char = GET_NEXT_INT(ARGS);
3878+
3879+ string::size_type index = str->str().rfind(the_char);
3880+
3881+ if(index == string::npos)
3882+ RETURN->v_int = -1;
3883+ else
3884+ RETURN->v_int = index;
3885+}
3886+
3887+CK_DLL_MFUN(string_rfindStart)
3888+{
3889+ Chuck_String * str = (Chuck_String *) SELF;
3890+ t_CKINT the_char = GET_NEXT_INT(ARGS);
3891+ t_CKINT start = GET_NEXT_INT(ARGS);
3892+
3893+ if(start < 0 || start >= str->str().length())
3894+ {
3895+ throw_exception(SHRED, "IndexOutOfBoundsException", start);
3896+ RETURN->v_int = -1;
3897+ return;
3898+ }
3899+
3900+ string::size_type index = str->str().rfind(the_char, start);
3901+
3902+ if(index == string::npos)
3903+ RETURN->v_int = -1;
3904+ else
3905+ RETURN->v_int = index;
3906+}
3907+
3908+CK_DLL_MFUN(string_rfindStr)
3909+{
3910+ Chuck_String * str = (Chuck_String *) SELF;
3911+ Chuck_String * the_str = GET_NEXT_STRING(ARGS);
3912+
3913+ string::size_type index = str->str().rfind(the_str->str());
3914+
3915+ if(index == string::npos)
3916+ RETURN->v_int = -1;
3917+ else
3918+ RETURN->v_int = index;
3919+}
3920+
3921+CK_DLL_MFUN(string_rfindStrStart)
3922+{
3923+ Chuck_String * str = (Chuck_String *) SELF;
3924+ Chuck_String * the_str = GET_NEXT_STRING(ARGS);
3925+ t_CKINT start = GET_NEXT_INT(ARGS);
3926+
3927+ if(start < 0 || start >= str->str().length())
3928+ {
3929+ throw_exception(SHRED, "IndexOutOfBoundsException", start);
3930+ RETURN->v_int = -1;
3931+ return;
3932+ }
3933+
3934+ string::size_type index = str->str().rfind(the_str->str(), start);
3935+
3936+ if(index == string::npos)
3937+ RETURN->v_int = -1;
3938+ else
3939+ RETURN->v_int = index;
3940+}
3941+
3942+CK_DLL_MFUN(string_erase)
3943+{
3944+ Chuck_String * str = (Chuck_String *) SELF;
3945+ t_CKINT start = GET_NEXT_INT(ARGS);
3946+ t_CKINT length = GET_NEXT_INT(ARGS);
3947+
3948+ if(start < 0 || start >= str->str().length())
3949+ {
3950+ throw_exception(SHRED, "IndexOutOfBoundsException", start);
3951+ return;
3952+ }
3953+
3954+ if(length < 0 || start+length > str->str().length())
3955+ {
3956+ throw_exception(SHRED, "IndexOutOfBoundsException", length);
3957+ return;
3958+ }
3959+
3960+ // str->str.erase(start, length);
3961+ std::string s = str->str();
3962+ s.erase( start, length );
3963+ str->set( s );
3964+}
3965+
3966+CK_DLL_MFUN( string_toInt )
3967+{
3968+ // get pointer to self
3969+ Chuck_String * str = (Chuck_String *)SELF;
3970+ // convert to int
3971+ RETURN->v_int = ::atoi( str->str().c_str() );
3972+}
3973+
3974+CK_DLL_MFUN( string_toFloat )
3975+{
3976+ // get pointer to self
3977+ Chuck_String * str = (Chuck_String *)SELF;
3978+ // convert to int
3979+ RETURN->v_float = (t_CKFLOAT)::atof( str->str().c_str() );
3980+}
3981+
3982+CK_DLL_MFUN( string_parent )
3983+{
3984+ Chuck_String * str = (Chuck_String *) SELF;
3985+
3986+ string::size_type i = str->str().rfind('/', str->str().length()-2);
3987+#ifdef WIN32
3988+ // SPENCERTODO: make this legit on windows
3989+ if(i == string::npos)
3990+ i = str->str().rfind('\\', str->str().length()-2);
3991+#endif // WIN32
3992+
3993+ Chuck_String * parent = (Chuck_String *) instantiate_and_initialize_object(SHRED->vm_ref->env()->t_string, SHRED);
3994+
3995+ if(i != string::npos)
3996+ {
3997+ if(i == 0)
3998+ parent->set( "/" );
3999+ else
4000+ parent->set( str->str().substr(0, i) );
4001+ }
4002+
4003+ RETURN->v_string = parent;
4004+}
4005+
4006+/*
4007+CK_DLL_MFUN( string_set_at )
4008+{
4009+ Chuck_String * s = (Chuck_String *)SELF;
4010+ t_CKINT c = GET_CK_INT(
4011+ RETURN->v_int = s->str.length();
4012+}
4013+
4014+CK_DLL_MFUN( string_get_at )
4015+{
4016+ Chuck_String * s = (Chuck_String *)SELF;
4017+ RETURN->v_int = s->str.length();
4018+}
4019+*/
4020+
4021+
4022+// array.size()
4023+CK_DLL_MFUN( array_get_size )
4024+{
4025+ Chuck_Array * array = (Chuck_Array *)SELF;
4026+ RETURN->v_int = array->size();
4027+}
4028+
4029+// array.size()
4030+CK_DLL_MFUN( array_set_size )
4031+{
4032+ Chuck_Array * array = (Chuck_Array *)SELF;
4033+ t_CKINT size = GET_NEXT_INT(ARGS);
4034+ if( size < 0 )
4035+ {
4036+ // TODO: make this exception
4037+ CK_FPRINTF_STDERR( "[chuck](via array): attempt to set negative array size!\n" );
4038+ RETURN->v_int = 0;
4039+ }
4040+ else
4041+ {
4042+ array->set_size( size );
4043+ RETURN->v_int = array->size();
4044+ }
4045+ RETURN->v_int = array->size();
4046+}
4047+
4048+// array.clear()
4049+CK_DLL_MFUN( array_clear )
4050+{
4051+ Chuck_Array * array = (Chuck_Array *)SELF;
4052+ array->clear();
4053+}
4054+
4055+// array.reset()
4056+CK_DLL_MFUN( array_reset )
4057+{
4058+ Chuck_Array * array = (Chuck_Array *)SELF;
4059+ array->clear();
4060+ // default capacity
4061+ array->set_capacity( 8 );
4062+}
4063+
4064+// array.cap()
4065+CK_DLL_MFUN( array_set_capacity )
4066+{
4067+ Chuck_Array * array = (Chuck_Array *)SELF;
4068+ t_CKINT capacity = GET_NEXT_INT(ARGS);
4069+ if( capacity < 0 )
4070+ {
4071+ // TODO: make this exception
4072+ CK_FPRINTF_STDERR( "[chuck](via array): attempt to set negative array capacity!\n" );
4073+ RETURN->v_int = 0;
4074+ }
4075+ else
4076+ {
4077+ array->set_capacity( capacity );
4078+ RETURN->v_int = array->capacity();
4079+ }
4080+}
4081+
4082+// array.cap()
4083+CK_DLL_MFUN( array_get_capacity_hack )
4084+{
4085+ Chuck_Array * array = (Chuck_Array *)SELF;
4086+ RETURN->v_int = array->size();
4087+}
4088+
4089+// array.capacity()
4090+CK_DLL_MFUN( array_get_capacity )
4091+{
4092+ Chuck_Array * array = (Chuck_Array *)SELF;
4093+ RETURN->v_int = array->capacity();
4094+}
4095+
4096+// array.find()
4097+CK_DLL_MFUN( array_find )
4098+{
4099+ Chuck_Array * array = (Chuck_Array *)SELF;
4100+ Chuck_String * name = GET_NEXT_STRING( ARGS );
4101+ RETURN->v_int = array->find( name->str() );
4102+}
4103+
4104+// array.erase()
4105+CK_DLL_MFUN( array_erase )
4106+{
4107+ Chuck_Array * array = (Chuck_Array *)SELF;
4108+ Chuck_String * name = GET_NEXT_STRING( ARGS );
4109+ RETURN->v_int = array->erase( name->str() );
4110+}
4111+
4112+// array.push_back()
4113+CK_DLL_MFUN( array_push_back )
4114+{
4115+ Chuck_Array * array = (Chuck_Array *)SELF;
4116+ // ISSUE: 64-bit (fixed 1.3.1.0 using data kind)
4117+ if( array->data_type_kind() == CHUCK_ARRAY4_DATAKIND )
4118+ RETURN->v_int = ((Chuck_Array4 *)array)->push_back( GET_NEXT_UINT( ARGS ) );
4119+ else if( array->data_type_kind() == CHUCK_ARRAY8_DATAKIND )
4120+ RETURN->v_int = ((Chuck_Array8 *)array)->push_back( GET_NEXT_FLOAT( ARGS ) );
4121+ else if( array->data_type_kind() == CHUCK_ARRAY16_DATAKIND )
4122+ RETURN->v_int = ((Chuck_Array16 *)array)->push_back( GET_NEXT_COMPLEX( ARGS ) );
4123+ else
4124+ assert( FALSE );
4125+}
4126+
4127+// array.pop_back()
4128+CK_DLL_MFUN( array_pop_back )
4129+{
4130+ Chuck_Array * array = (Chuck_Array *)SELF;
4131+ // ISSUE: 64-bit (fixed 1.3.1.0 using data kind)
4132+ if( array->data_type_kind() == CHUCK_ARRAY4_DATAKIND )
4133+ RETURN->v_int = ((Chuck_Array4 *)array)->pop_back( );
4134+ else if( array->data_type_kind() == CHUCK_ARRAY8_DATAKIND )
4135+ RETURN->v_int = ((Chuck_Array8 *)array)->pop_back( );
4136+ else if( array->data_type_kind() == CHUCK_ARRAY16_DATAKIND )
4137+ RETURN->v_int = ((Chuck_Array16 *)array)->pop_back( );
4138+ else
4139+ assert( FALSE );
4140+}
4141+
4142+
4143+#ifndef __DISABLE_MIDI__
4144+
4145+//-----------------------------------------------------------------------------
4146+// MidiIn API
4147+//-----------------------------------------------------------------------------
4148+CK_DLL_CTOR( MidiIn_ctor )
4149+{
4150+ MidiIn * min = new MidiIn;
4151+ min->SELF = SELF;
4152+ OBJ_MEMBER_INT(SELF, MidiIn_offset_data) = (t_CKINT)min;
4153+}
4154+
4155+CK_DLL_DTOR( MidiIn_dtor )
4156+{
4157+ delete (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data);
4158+ OBJ_MEMBER_INT(SELF, MidiIn_offset_data) = 0;
4159+}
4160+
4161+CK_DLL_MFUN( MidiIn_open )
4162+{
4163+ MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data);
4164+ t_CKINT port = GET_CK_INT(ARGS);
4165+ RETURN->v_int = min->open( SHRED->vm_ref, port );
4166+}
4167+
4168+CK_DLL_MFUN( MidiIn_open_named ) // added 1.3.0.0
4169+{
4170+ MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data);
4171+ Chuck_String * name = GET_CK_STRING(ARGS);
4172+ RETURN->v_int = min->open( SHRED->vm_ref, name->str() );
4173+}
4174+
4175+CK_DLL_MFUN( MidiIn_good )
4176+{
4177+ MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data);
4178+ RETURN->v_int = (t_CKINT)min->good();
4179+}
4180+
4181+CK_DLL_MFUN( MidiIn_num )
4182+{
4183+ MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data);
4184+ RETURN->v_int = min->num();
4185+}
4186+
4187+CK_DLL_MFUN( MidiIn_printerr )
4188+{
4189+ MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data);
4190+ t_CKINT print_or_not = GET_CK_INT(ARGS);
4191+ min->set_suppress( !print_or_not );
4192+}
4193+
4194+CK_DLL_MFUN( MidiIn_name )
4195+{
4196+ MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data);
4197+ // TODO: memory leak, please fix, Thanks.
4198+ Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED );
4199+ // only if valid
4200+ if( min->good() )
4201+ a->set( min->min->getPortName( min->num() ) );
4202+ RETURN->v_string = a;
4203+}
4204+
4205+CK_DLL_MFUN( MidiIn_recv )
4206+{
4207+ MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data);
4208+ Chuck_Object * fake_msg = GET_CK_OBJECT(ARGS);
4209+ MidiMsg the_msg;
4210+ RETURN->v_int = min->recv( &the_msg );
4211+ if( RETURN->v_int )
4212+ {
4213+ OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data1) = the_msg.data[0];
4214+ OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data2) = the_msg.data[1];
4215+ OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data3) = the_msg.data[2];
4216+ }
4217+}
4218+
4219+
4220+CK_DLL_MFUN( MidiIn_can_wait )
4221+{
4222+ MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data);
4223+ RETURN->v_int = min->empty();
4224+}
4225+
4226+
4227+//-----------------------------------------------------------------------------
4228+// MidiOut API
4229+//-----------------------------------------------------------------------------
4230+CK_DLL_CTOR( MidiOut_ctor )
4231+{
4232+ OBJ_MEMBER_INT(SELF, MidiOut_offset_data) = (t_CKUINT)new MidiOut;
4233+}
4234+
4235+CK_DLL_DTOR( MidiOut_dtor )
4236+{
4237+ delete (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data);
4238+ OBJ_MEMBER_INT(SELF, MidiOut_offset_data) = 0;
4239+}
4240+
4241+CK_DLL_MFUN( MidiOut_open )
4242+{
4243+ MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data);
4244+ t_CKINT port = GET_CK_INT(ARGS);
4245+ RETURN->v_int = mout->open( port );
4246+}
4247+
4248+CK_DLL_MFUN( MidiOut_open_named ) // added 1.3.0.0
4249+{
4250+ MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data);
4251+ Chuck_String * name = GET_CK_STRING(ARGS);
4252+ RETURN->v_int = mout->open( name->str() );
4253+}
4254+
4255+CK_DLL_MFUN( MidiOut_good )
4256+{
4257+ MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data);
4258+ RETURN->v_int = (t_CKINT)mout->good();
4259+}
4260+
4261+CK_DLL_MFUN( MidiOut_num )
4262+{
4263+ MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data);
4264+ RETURN->v_int = mout->num();
4265+}
4266+
4267+CK_DLL_MFUN( MidiOut_name )
4268+{
4269+ MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data);
4270+ // TODO: memory leak, please fix, Thanks.
4271+ Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED );
4272+ // only if valid
4273+ if( mout->good() )
4274+ a->set( mout->mout->getPortName( mout->num() ) );
4275+ RETURN->v_string = a;
4276+}
4277+
4278+CK_DLL_MFUN( MidiOut_printerr )
4279+{
4280+ MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data);
4281+ t_CKINT print_or_not = GET_CK_INT(ARGS);
4282+ mout->set_suppress( !print_or_not );
4283+}
4284+
4285+CK_DLL_MFUN( MidiOut_send )
4286+{
4287+ MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data);
4288+ Chuck_Object * fake_msg = GET_CK_OBJECT(ARGS);
4289+ MidiMsg the_msg;
4290+ the_msg.data[0] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data1);
4291+ the_msg.data[1] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data2);
4292+ the_msg.data[2] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data3);
4293+ RETURN->v_int = mout->send( &the_msg );
4294+}
4295+
4296+#endif // __DISABLE_MIDI__
4297+
4298+
4299+//-----------------------------------------------------------------------------
4300+// HidMsg API
4301+//-----------------------------------------------------------------------------
4302+CK_DLL_MFUN( HidMsg_is_axis_motion )
4303+{
4304+ RETURN->v_int = ( ( t_CKINT ) OBJ_MEMBER_INT( SELF, HidMsg_offset_type ) ==
4305+ CK_HID_JOYSTICK_AXIS ? 1 : 0 );
4306+}
4307+
4308+CK_DLL_MFUN( HidMsg_is_button_down )
4309+{
4310+ RETURN->v_int = ( ( t_CKINT ) OBJ_MEMBER_INT( SELF, HidMsg_offset_type ) ==
4311+ CK_HID_BUTTON_DOWN ? 1 : 0 );
4312+}
4313+
4314+CK_DLL_MFUN( HidMsg_is_button_up )
4315+{
4316+ RETURN->v_int = ( ( t_CKINT ) OBJ_MEMBER_INT( SELF, HidMsg_offset_type ) ==
4317+ CK_HID_BUTTON_UP ? 1 : 0 );
4318+}
4319+
4320+CK_DLL_MFUN( HidMsg_is_mouse_motion )
4321+{
4322+ RETURN->v_int = ( ( t_CKINT ) OBJ_MEMBER_INT( SELF, HidMsg_offset_type ) ==
4323+ CK_HID_MOUSE_MOTION ? 1 : 0 );
4324+}
4325+
4326+CK_DLL_MFUN( HidMsg_is_hat_motion )
4327+{
4328+ RETURN->v_int = ( ( t_CKINT ) OBJ_MEMBER_INT( SELF, HidMsg_offset_type ) ==
4329+ CK_HID_JOYSTICK_HAT ? 1 : 0 );
4330+}
4331+
4332+CK_DLL_MFUN( HidMsg_is_wheel_motion )
4333+{
4334+ RETURN->v_int = ( ( t_CKINT ) OBJ_MEMBER_INT( SELF, HidMsg_offset_type ) ==
4335+ CK_HID_MOUSE_WHEEL ? 1 : 0 );
4336+}
4337+
4338+//-----------------------------------------------------------------------------
4339+// HidIn API
4340+//-----------------------------------------------------------------------------
4341+CK_DLL_CTOR( HidIn_ctor )
4342+{
4343+ HidIn * min = new HidIn;
4344+ min->SELF = SELF;
4345+ OBJ_MEMBER_INT(SELF, HidIn_offset_data) = (t_CKINT)min;
4346+}
4347+
4348+CK_DLL_DTOR( HidIn_dtor )
4349+{
4350+ delete (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data);
4351+ OBJ_MEMBER_INT(SELF, HidIn_offset_data) = 0;
4352+}
4353+
4354+CK_DLL_MFUN( HidIn_open )
4355+{
4356+ HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data);
4357+ t_CKINT type = GET_NEXT_INT(ARGS);
4358+ t_CKINT num = GET_NEXT_INT(ARGS);
4359+ // CK_FPRINTF_STDERR( "HidIn_open %li %li\n", type, num );
4360+ RETURN->v_int = min->open( SHRED->vm_ref, type, num );
4361+}
4362+
4363+CK_DLL_MFUN( HidIn_open_named )
4364+{
4365+ HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data);
4366+ Chuck_String * name = GET_NEXT_STRING(ARGS);
4367+ std::string s = name->str();
4368+ RETURN->v_int = min->open( SHRED->vm_ref, s );
4369+}
4370+
4371+CK_DLL_MFUN( HidIn_open_joystick )
4372+{
4373+ HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data);
4374+ t_CKINT num = GET_NEXT_INT(ARGS);
4375+ RETURN->v_int = min->open( SHRED->vm_ref, CK_HID_DEV_JOYSTICK, num );
4376+}
4377+
4378+CK_DLL_MFUN( HidIn_open_mouse )
4379+{
4380+ HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data);
4381+ t_CKINT num = GET_NEXT_INT(ARGS);
4382+ RETURN->v_int = min->open( SHRED->vm_ref, CK_HID_DEV_MOUSE, num );
4383+}
4384+
4385+CK_DLL_MFUN( HidIn_open_keyboard )
4386+{
4387+ HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data);
4388+ t_CKINT num = GET_NEXT_INT(ARGS);
4389+ RETURN->v_int = min->open( SHRED->vm_ref, CK_HID_DEV_KEYBOARD, num );
4390+}
4391+
4392+CK_DLL_MFUN( HidIn_open_tiltsensor )
4393+{
4394+ HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data);
4395+ RETURN->v_int = min->open( SHRED->vm_ref, CK_HID_DEV_TILTSENSOR, 0 );
4396+}
4397+
4398+CK_DLL_MFUN( HidIn_good )
4399+{
4400+ HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data);
4401+ RETURN->v_int = (t_CKINT)min->good();
4402+}
4403+
4404+CK_DLL_MFUN( HidIn_num )
4405+{
4406+ HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data);
4407+ RETURN->v_int = min->num();
4408+}
4409+
4410+CK_DLL_MFUN( HidIn_printerr )
4411+{
4412+ HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data);
4413+ t_CKINT print_or_not = GET_CK_INT(ARGS);
4414+ min->set_suppress( !print_or_not );
4415+}
4416+
4417+CK_DLL_MFUN( HidIn_name )
4418+{
4419+ HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data);
4420+ // TODO: memory leak, please fix, Thanks.
4421+ // Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED );
4422+ // only if valid
4423+ // if( min->good() )
4424+ // a->str = min->phin->getPortName( min->num() );
4425+ // TODO: is null problem?
4426+ RETURN->v_string = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED );
4427+ RETURN->v_string->set( min->name() );
4428+}
4429+
4430+CK_DLL_MFUN( HidIn_recv )
4431+{
4432+ HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data);
4433+ Chuck_Object * fake_msg = GET_CK_OBJECT(ARGS);
4434+ HidMsg the_msg;
4435+ RETURN->v_int = min->recv( &the_msg );
4436+ if( RETURN->v_int )
4437+ {
4438+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_device_type) = the_msg.device_type;
4439+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_device_num) = the_msg.device_num;
4440+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_type) = the_msg.type;
4441+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_which) = the_msg.eid;
4442+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_idata) = the_msg.idata[0];
4443+ OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_fdata) = the_msg.fdata[0];
4444+
4445+ // mouse motion specific member variables
4446+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_deltax) = the_msg.idata[0];
4447+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_deltay) = the_msg.idata[1];
4448+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_cursorx) = the_msg.idata[2];
4449+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_cursory) = the_msg.idata[3];
4450+ OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_scaledcursorx) = the_msg.fdata[0];
4451+ OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_scaledcursory) = the_msg.fdata[1];
4452+
4453+ // axis motion specific member variables
4454+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_axis_position) = the_msg.idata[0];
4455+ OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_scaled_axis_position) = the_msg.fdata[0];
4456+ OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_axis_position2) = the_msg.fdata[0];
4457+
4458+ // hat motion specific variables
4459+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_hat_position) = the_msg.idata[0];
4460+
4461+ // keyboard specific variables
4462+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_key) = the_msg.idata[1];
4463+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_ascii) = the_msg.idata[2];
4464+
4465+ // accelerometer (tilt sensor, wii remote) specific members
4466+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_x) = the_msg.idata[0];
4467+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_y) = the_msg.idata[1];
4468+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_z) = the_msg.idata[2];
4469+
4470+ // multitouch stuff - added 1.3.0.0
4471+ OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_touchx) = the_msg.fdata[0];
4472+ OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_touchy) = the_msg.fdata[1];
4473+ OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_touchsize) = the_msg.fdata[2];
4474+ }
4475+}
4476+
4477+CK_DLL_MFUN( HidIn_read )
4478+{
4479+ HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data);
4480+ t_CKINT type = GET_NEXT_INT(ARGS);
4481+ t_CKINT num = GET_NEXT_INT(ARGS);
4482+ Chuck_Object * fake_msg = GET_NEXT_OBJECT(ARGS);
4483+
4484+ HidMsg the_msg;
4485+
4486+ RETURN->v_int = min->read( type, num, &the_msg );
4487+
4488+ if( RETURN->v_int )
4489+ {
4490+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_device_type) = the_msg.device_type;
4491+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_device_num) = the_msg.device_num;
4492+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_type) = the_msg.type;
4493+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_which) = the_msg.eid;
4494+
4495+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_idata) = the_msg.idata[0];
4496+ OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_fdata) = the_msg.fdata[0];
4497+
4498+ // mouse motion specific member members
4499+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_deltax) = the_msg.idata[0];
4500+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_deltay) = the_msg.idata[1];
4501+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_cursorx) = the_msg.idata[2];
4502+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_cursory) = the_msg.idata[3];
4503+ OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_scaledcursorx) = the_msg.fdata[0];
4504+ OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_scaledcursory) = the_msg.fdata[1];
4505+
4506+ // joystick axis specific member members
4507+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_axis_position) = the_msg.idata[0];
4508+ OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_scaled_axis_position) = the_msg.fdata[0];
4509+ OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_axis_position2) = the_msg.fdata[0];
4510+
4511+ // joystick hat specific member members
4512+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_hat_position) = the_msg.idata[0];
4513+
4514+ // keyboard specific members
4515+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_key) = the_msg.idata[1];
4516+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_ascii) = the_msg.idata[2];
4517+
4518+ // accelerometer (tilt sensor, wii remote) specific members
4519+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_x) = the_msg.idata[0];
4520+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_y) = the_msg.idata[1];
4521+ OBJ_MEMBER_INT(fake_msg, HidMsg_offset_z) = the_msg.idata[2];
4522+ }
4523+}
4524+
4525+CK_DLL_MFUN( HidIn_send )
4526+{
4527+ HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data);
4528+ Chuck_Object * fake_msg = GET_NEXT_OBJECT(ARGS);
4529+
4530+ HidMsg the_msg;
4531+ the_msg.device_type = OBJ_MEMBER_INT( fake_msg, HidMsg_offset_device_type );
4532+ the_msg.device_num = OBJ_MEMBER_INT( fake_msg, HidMsg_offset_device_num );
4533+ the_msg.type = OBJ_MEMBER_INT( fake_msg, HidMsg_offset_type );
4534+ the_msg.eid = OBJ_MEMBER_INT( fake_msg, HidMsg_offset_which );
4535+ the_msg.idata[0] = OBJ_MEMBER_INT( fake_msg, HidMsg_offset_idata );
4536+
4537+ RETURN->v_int = min->send( &the_msg );
4538+}
4539+
4540+CK_DLL_MFUN( HidIn_can_wait )
4541+{
4542+ HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data);
4543+ RETURN->v_int = min->empty();
4544+}
4545+
4546+CK_DLL_SFUN( HidIn_read_tilt_sensor )
4547+{
4548+ static HidIn * hi;
4549+ static t_CKBOOL hi_good = TRUE;
4550+
4551+ Chuck_Array4 * array = new Chuck_Array4( FALSE, 3 );
4552+ array->set( 0, 0 );
4553+ array->set( 1, 0 );
4554+ array->set( 2, 0 );
4555+
4556+ // TODO: reference count?
4557+ array->add_ref();
4558+ RETURN->v_object = array;
4559+
4560+ if( hi_good == FALSE )
4561+ return;
4562+
4563+ if( !hi )
4564+ {
4565+ hi = new HidIn;
4566+ if( !hi->open( SHRED->vm_ref, CK_HID_DEV_TILTSENSOR, 0 ) )
4567+ {
4568+ hi_good = FALSE;
4569+ return;
4570+ }
4571+ }
4572+
4573+ HidMsg msg;
4574+
4575+ if( !hi->read( CK_HID_ACCELEROMETER, 0, &msg ) )
4576+ {
4577+ return;
4578+ }
4579+
4580+ array->set( 0, msg.idata[0] );
4581+ array->set( 1, msg.idata[1] );
4582+ array->set( 2, msg.idata[2] );
4583+}
4584+
4585+CK_DLL_SFUN( HidIn_ctrl_tiltPollRate )
4586+{
4587+ // get srate
4588+ if( !SHRED || !SHRED->vm_ref )
4589+ {
4590+ // problem
4591+ CK_FPRINTF_STDERR( "[chuck](via HID): can't set tiltPollRate on NULL shred/VM...\n" );
4592+ RETURN->v_dur = 0;
4593+ return;
4594+ }
4595+ t_CKFLOAT srate = SHRED->vm_ref->srate();
4596+
4597+ // get arg
4598+ t_CKDUR v = GET_NEXT_DUR( ARGS );
4599+
4600+ // get in microseconds
4601+ t_CKINT usec = (t_CKINT)( v / srate * 1000000 );
4602+
4603+ // make sure it's nonnegative
4604+ if( usec < 0 ) usec = 0;
4605+
4606+ // go
4607+ RETURN->v_dur = TiltSensor_setPollRate( usec ) * srate / 1000000;
4608+}
4609+
4610+CK_DLL_SFUN( HidIn_cget_tiltPollRate )
4611+{
4612+ // get srate
4613+ if( !SHRED || !SHRED->vm_ref )
4614+ {
4615+ // problem
4616+ CK_FPRINTF_STDERR( "[chuck](via HID): can't get tiltPollRate on NULL shred/VM...\n" );
4617+ RETURN->v_dur = 0;
4618+ return;
4619+ }
4620+ t_CKFLOAT srate = SHRED->vm_ref->srate();
4621+
4622+ RETURN->v_dur = TiltSensor_getPollRate() * srate / 1000000;
4623+}
4624+
4625+CK_DLL_SFUN( HidIn_start_cursor_track )
4626+{
4627+ RETURN->v_int = !Mouse_start_cursor_track();
4628+}
4629+
4630+CK_DLL_SFUN( HidIn_stop_cursor_track )
4631+{
4632+ RETURN->v_int = !Mouse_stop_cursor_track();
4633+}
4634+
4635+//-----------------------------------------------------------------------------
4636+// HidOut API
4637+//-----------------------------------------------------------------------------
4638+CK_DLL_CTOR( HidOut_ctor )
4639+{
4640+ OBJ_MEMBER_INT(SELF, HidOut_offset_data) = (t_CKUINT)new HidOut;
4641+}
4642+
4643+CK_DLL_DTOR( HidOut_dtor )
4644+{
4645+ delete (HidOut *)OBJ_MEMBER_INT(SELF, HidOut_offset_data);
4646+ OBJ_MEMBER_INT(SELF, HidOut_offset_data) = 0;
4647+}
4648+
4649+CK_DLL_MFUN( HidOut_open )
4650+{
4651+ HidOut * mout = (HidOut *)OBJ_MEMBER_INT(SELF, HidOut_offset_data);
4652+ t_CKINT num = GET_CK_INT(ARGS);
4653+ RETURN->v_int = mout->open( num );
4654+}
4655+
4656+CK_DLL_MFUN( HidOut_good )
4657+{
4658+ HidOut * mout = (HidOut *)OBJ_MEMBER_INT(SELF, HidOut_offset_data);
4659+ RETURN->v_int = (t_CKINT)mout->good();
4660+}
4661+
4662+CK_DLL_MFUN( HidOut_num )
4663+{
4664+ HidOut * mout = (HidOut *)OBJ_MEMBER_INT(SELF, HidOut_offset_data);
4665+ RETURN->v_int = mout->num();
4666+}
4667+
4668+CK_DLL_MFUN( HidOut_name )
4669+{
4670+ // HidOut * mout = (HidOut *)OBJ_MEMBER_INT(SELF, HidOut_offset_data);
4671+ // TODO: memory leak, please fix, Thanks.
4672+ Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED );
4673+ // only if valid
4674+ // if( mout->good() )
4675+ // a->str = mout->mout->getPortName( mout->num() );
4676+ RETURN->v_string = a;
4677+}
4678+
4679+CK_DLL_MFUN( HidOut_printerr )
4680+{
4681+ HidOut * mout = (HidOut *)OBJ_MEMBER_INT(SELF, HidOut_offset_data);
4682+ t_CKINT print_or_not = GET_CK_INT(ARGS);
4683+ mout->set_suppress( !print_or_not );
4684+}
4685+
4686+CK_DLL_MFUN( HidOut_send )
4687+{
4688+ HidOut * mout = (HidOut *)OBJ_MEMBER_INT(SELF, HidOut_offset_data);
4689+ // Chuck_Object * fake_msg = GET_CK_OBJECT(ARGS);
4690+ HidMsg the_msg;
4691+ // the_msg.data[0] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, HidMsg_offset_data1);
4692+ // the_msg.data[1] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, HidMsg_offset_data2);
4693+ // the_msg.data[2] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, HidMsg_offset_data3);
4694+ RETURN->v_int = mout->send( &the_msg );
4695+}
4696+
4697+
4698+//-----------------------------------------------------------------------------
4699+// MidiRW API
4700+//-----------------------------------------------------------------------------
4701+CK_DLL_CTOR( MidiRW_ctor )
4702+{
4703+#ifndef __DISABLE_MIDI__
4704+ OBJ_MEMBER_INT(SELF, MidiRW_offset_data) = (t_CKUINT)new MidiRW;
4705+#endif // __DISABLE_MIDI__
4706+}
4707+
4708+CK_DLL_DTOR( MidiRW_dtor )
4709+{
4710+#ifndef __DISABLE_MIDI__
4711+ delete (MidiRW *)OBJ_MEMBER_INT(SELF, MidiRW_offset_data);
4712+ OBJ_MEMBER_INT(SELF, MidiRW_offset_data) = 0;
4713+#endif // __DISABLE_MIDI__
4714+}
4715+
4716+CK_DLL_MFUN( MidiRW_open )
4717+{
4718+#ifndef __DISABLE_MIDI__
4719+ MidiRW * mrw = (MidiRW *)OBJ_MEMBER_INT(SELF, MidiRW_offset_data);
4720+ const char * filename = GET_CK_STRING(ARGS)->str().c_str();
4721+ RETURN->v_int = mrw->open( filename );
4722+#endif // __DISABLE_MIDI__
4723+}
4724+
4725+CK_DLL_MFUN( MidiRW_close )
4726+{
4727+#ifndef __DISABLE_MIDI__
4728+ MidiRW * mrw = (MidiRW *)OBJ_MEMBER_INT(SELF, MidiRW_offset_data);
4729+ RETURN->v_int = mrw->close();
4730+#endif // __DISABLE_MIDI__
4731+}
4732+
4733+CK_DLL_MFUN( MidiRW_read )
4734+{
4735+#ifndef __DISABLE_MIDI__
4736+ MidiRW * mrw = (MidiRW *)OBJ_MEMBER_INT(SELF, MidiRW_offset_data);
4737+ Chuck_Object * fake_msg = GET_NEXT_OBJECT(ARGS);
4738+ MidiMsg the_msg;
4739+ t_CKTIME time = 0.0;
4740+ RETURN->v_int = mrw->read( &the_msg, &time );
4741+ OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data1) = the_msg.data[0];
4742+ OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data2) = the_msg.data[1];
4743+ OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data3) = the_msg.data[2];
4744+ OBJ_MEMBER_TIME(fake_msg, MidiMsg_offset_when) = time;
4745+#endif // __DISABLE_MIDI__
4746+}
4747+
4748+CK_DLL_MFUN( MidiRW_write )
4749+{
4750+#ifndef __DISABLE_MIDI__
4751+ MidiRW * mrw = (MidiRW *)OBJ_MEMBER_INT(SELF, MidiRW_offset_data);
4752+ Chuck_Object * fake_msg = GET_NEXT_OBJECT(ARGS);
4753+ t_CKTIME time = GET_NEXT_TIME(ARGS);
4754+ MidiMsg the_msg;
4755+ the_msg.data[0] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data1);
4756+ the_msg.data[1] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data2);
4757+ the_msg.data[2] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data3);
4758+ RETURN->v_int = mrw->write( &the_msg, &time );
4759+#endif // __DISABLE_MIDI__
4760+}
4761+
4762+
4763+//-----------------------------------------------------------------------------
4764+// MidiMsgOut API
4765+//-----------------------------------------------------------------------------
4766+CK_DLL_CTOR( MidiMsgOut_ctor )
4767+{
4768+#ifndef __DISABLE_MIDI__
4769+ OBJ_MEMBER_INT(SELF, MidiMsgOut_offset_data) = (t_CKUINT)new MidiMsgOut;
4770+#endif // __DISABLE_MIDI__
4771+}
4772+
4773+CK_DLL_DTOR( MidiMsgOut_dtor )
4774+{
4775+#ifndef __DISABLE_MIDI__
4776+ delete (MidiMsgOut *)OBJ_MEMBER_INT(SELF, MidiMsgOut_offset_data);
4777+ OBJ_MEMBER_INT(SELF, MidiMsgOut_offset_data) = 0;
4778+#endif // __DISABLE_MIDI__
4779+}
4780+
4781+CK_DLL_MFUN( MidiMsgOut_open )
4782+{
4783+#ifndef __DISABLE_MIDI__
4784+ MidiMsgOut * mrw = (MidiMsgOut *)OBJ_MEMBER_INT(SELF, MidiMsgOut_offset_data);
4785+ const char * filename = GET_CK_STRING(ARGS)->str().c_str();
4786+ RETURN->v_int = mrw->open( filename );
4787+#endif // __DISABLE_MIDI__
4788+}
4789+
4790+CK_DLL_MFUN( MidiMsgOut_close )
4791+{
4792+#ifndef __DISABLE_MIDI__
4793+ MidiMsgOut * mrw = (MidiMsgOut *)OBJ_MEMBER_INT(SELF, MidiMsgOut_offset_data);
4794+ RETURN->v_int = mrw->close();
4795+#endif // __DISABLE_MIDI__
4796+}
4797+
4798+CK_DLL_MFUN( MidiMsgOut_write )
4799+{
4800+#ifndef __DISABLE_MIDI__
4801+ MidiMsgOut * mrw = (MidiMsgOut *)OBJ_MEMBER_INT(SELF, MidiMsgOut_offset_data);
4802+ Chuck_Object * fake_msg = GET_NEXT_OBJECT(ARGS);
4803+ t_CKTIME time = GET_NEXT_TIME(ARGS);
4804+ MidiMsg the_msg;
4805+ the_msg.data[0] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data1);
4806+ the_msg.data[1] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data2);
4807+ the_msg.data[2] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data3);
4808+ RETURN->v_int = mrw->write( &the_msg, &time );
4809+#endif // __DISABLE_MIDI__
4810+}
4811+
4812+
4813+//-----------------------------------------------------------------------------
4814+// MidiMsgIn API
4815+//-----------------------------------------------------------------------------
4816+CK_DLL_CTOR( MidiMsgIn_ctor )
4817+{
4818+#ifndef __DISABLE_MIDI__
4819+ OBJ_MEMBER_INT(SELF, MidiMsgIn_offset_data) = (t_CKUINT)new MidiMsgIn;
4820+#endif // __DISABLE_MIDI__
4821+}
4822+
4823+CK_DLL_DTOR( MidiMsgIn_dtor )
4824+{
4825+#ifndef __DISABLE_MIDI__
4826+ delete (MidiMsgIn *)OBJ_MEMBER_INT(SELF, MidiMsgIn_offset_data);
4827+ OBJ_MEMBER_INT(SELF, MidiMsgIn_offset_data) = 0;
4828+#endif // __DISABLE_MIDI__
4829+}
4830+
4831+CK_DLL_MFUN( MidiMsgIn_open )
4832+{
4833+#ifndef __DISABLE_MIDI__
4834+ MidiMsgIn * mrw = (MidiMsgIn *)OBJ_MEMBER_INT(SELF, MidiMsgIn_offset_data);
4835+ const char * filename = GET_CK_STRING(ARGS)->str().c_str();
4836+ RETURN->v_int = mrw->open( filename );
4837+#endif // __DISABLE_MIDI__
4838+}
4839+
4840+CK_DLL_MFUN( MidiMsgIn_close )
4841+{
4842+#ifndef __DISABLE_MIDI__
4843+ MidiMsgIn * mrw = (MidiMsgIn *)OBJ_MEMBER_INT(SELF, MidiMsgIn_offset_data);
4844+ RETURN->v_int = mrw->close();
4845+#endif // __DISABLE_MIDI__
4846+}
4847+
4848+CK_DLL_MFUN( MidiMsgIn_read )
4849+{
4850+#ifndef __DISABLE_MIDI__
4851+ MidiMsgIn * mrw = (MidiMsgIn *)OBJ_MEMBER_INT(SELF, MidiMsgIn_offset_data);
4852+ Chuck_Object * fake_msg = GET_NEXT_OBJECT(ARGS);
4853+ MidiMsg the_msg;
4854+ t_CKTIME time = 0.0;
4855+ RETURN->v_int = mrw->read( &the_msg, &time );
4856+ OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data1) = the_msg.data[0];
4857+ OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data2) = the_msg.data[1];
4858+ OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data3) = the_msg.data[2];
4859+ OBJ_MEMBER_TIME(fake_msg, MidiMsg_offset_when) = time;
4860+#endif // __DISABLE_MIDI__
4861+}
core/chuck_lang.h+481−0
@@ -0,0 +1,481 @@
1+/*----------------------------------------------------------------------------
2+ ChucK Concurrent, On-the-fly Audio Programming Language
3+ Compiler and Virtual Machine
4+
5+ Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6+ http://chuck.stanford.edu/
7+ http://chuck.cs.princeton.edu/
8+
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.
13+
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.
18+
19+ You should have received a copy of the GNU General Public License
20+ along with this program; if not, write to the Free Software
21+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22+ U.S.A.
23+-----------------------------------------------------------------------------*/
24+
25+//-----------------------------------------------------------------------------
26+// name: chuck_lang.h
27+// desc: chuck class library base
28+//
29+// authors: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
30+// Spencer Salazar (spencer@ccrma.stanford.edu)
31+// Ananya Misra (amisra@cs.princeton.edu)
32+// Andrew Schran (aschran@princeton.edu)
33+// date: spring 2005
34+//-----------------------------------------------------------------------------
35+#ifndef __CHUCK_LANG_H__
36+#define __CHUCK_LANG_H__
37+
38+#include "chuck_def.h"
39+#include "chuck_oo.h"
40+#include "chuck_dl.h"
41+#include <queue>
42+
43+
44+// forward reference
45+struct Chuck_UAna;
46+
47+// query
48+DLL_QUERY lang_query( Chuck_DL_Query * QUERY );
49+
50+// base class initialization
51+t_CKBOOL init_class_object( Chuck_Env * env, Chuck_Type * type );
52+t_CKBOOL init_class_ugen( Chuck_Env * env, Chuck_Type * type );
53+t_CKBOOL init_class_uana( Chuck_Env * env, Chuck_Type * type );
54+t_CKBOOL init_class_blob( Chuck_Env * env, Chuck_Type * type );
55+t_CKBOOL init_class_event( Chuck_Env * env, Chuck_Type * type );
56+t_CKBOOL init_class_shred( Chuck_Env * env, Chuck_Type * type );
57+t_CKBOOL init_class_string( Chuck_Env * env, Chuck_Type * type );
58+t_CKBOOL init_class_array( Chuck_Env * env, Chuck_Type * type );
59+t_CKBOOL init_class_vec3( Chuck_Env * env, Chuck_Type * type ); // 1.3.5.3
60+t_CKBOOL init_class_vec4( Chuck_Env * env, Chuck_Type * type ); // 1.3.5.3
61+
62+t_CKBOOL init_class_Midi( Chuck_Env * env );
63+t_CKBOOL init_class_MidiRW( Chuck_Env * env );
64+t_CKBOOL init_class_HID( Chuck_Env * env );
65+t_CKBOOL init_class_io( Chuck_Env * env, Chuck_Type * type );
66+t_CKBOOL init_class_fileio( Chuck_Env * env, Chuck_Type * type );
67+// added 1.3.0.0 -- moved to be full-fledged class
68+t_CKBOOL init_class_chout( Chuck_Env * env, Chuck_Type * type );
69+// added 1.3.0.0 -- moved to be full-fledged class
70+t_CKBOOL init_class_cherr( Chuck_Env * env, Chuck_Type * type );
71+
72+
73+
74+
75+//-----------------------------------------------------------------------------
76+// object API
77+//-----------------------------------------------------------------------------
78+CK_DLL_CTOR( object_ctor );
79+CK_DLL_DTOR( object_dtor );
80+CK_DLL_MFUN( object_equals );
81+CK_DLL_MFUN( object_getType );
82+CK_DLL_MFUN( object_hashCode );
83+CK_DLL_MFUN( object_toString );
84+
85+
86+//-----------------------------------------------------------------------------
87+// ugen API
88+//-----------------------------------------------------------------------------
89+CK_DLL_CTOR( ugen_ctor );
90+CK_DLL_DTOR( ugen_dtor );
91+CK_DLL_MFUN( ugen_op );
92+CK_DLL_MFUN( ugen_cget_op );
93+CK_DLL_MFUN( ugen_last );
94+CK_DLL_MFUN( ugen_cget_last );
95+CK_DLL_MFUN( ugen_next );
96+CK_DLL_MFUN( ugen_cget_next );
97+CK_DLL_MFUN( ugen_gain );
98+CK_DLL_MFUN( ugen_cget_gain );
99+CK_DLL_MFUN( ugen_numChannels );
100+CK_DLL_MFUN( ugen_cget_numChannels );
101+CK_DLL_MFUN( ugen_chan );
102+CK_DLL_MFUN( ugen_connected );
103+
104+
105+//-----------------------------------------------------------------------------
106+// uana API
107+//-----------------------------------------------------------------------------
108+CK_DLL_CTOR( uana_ctor );
109+CK_DLL_DTOR( uana_dtor );
110+CK_DLL_MFUN( uana_upchuck );
111+CK_DLL_MFUN( uana_blob );
112+CK_DLL_MFUN( uana_fvals );
113+CK_DLL_MFUN( uana_cvals );
114+CK_DLL_MFUN( uana_fval );
115+CK_DLL_MFUN( uana_cval );
116+CK_DLL_MFUN( uana_connected );
117+
118+
119+//-----------------------------------------------------------------------------
120+// uanablob API
121+//-----------------------------------------------------------------------------
122+CK_DLL_CTOR( uanablob_ctor );
123+CK_DLL_DTOR( uanablob_dtor );
124+CK_DLL_MFUN( uanablob_fvals );
125+CK_DLL_MFUN( uanablob_cvals );
126+CK_DLL_MFUN( uanablob_fval );
127+CK_DLL_MFUN( uanablob_cval );
128+CK_DLL_MFUN( uanablob_when );
129+
130+
131+//-----------------------------------------------------------------------------
132+// name: Chuck_UAnaBlobProxy
133+// desc: proxy for interfacing with UAnaBlob, which is a Chuck class
134+//-----------------------------------------------------------------------------
135+struct Chuck_UAnaBlobProxy
136+{
137+public:
138+ Chuck_UAnaBlobProxy( Chuck_Object * blob );
139+ virtual ~Chuck_UAnaBlobProxy();
140+
141+public:
142+ t_CKTIME & when();
143+ Chuck_Array8 & fvals();
144+ Chuck_Array16 & cvals();
145+
146+public:
147+ Chuck_Object * realblob() { return m_blob; }
148+
149+protected:
150+ Chuck_Object * m_blob;
151+};
152+
153+// get proxy
154+Chuck_UAnaBlobProxy * getBlobProxy( const Chuck_UAna * uana );
155+
156+
157+//-----------------------------------------------------------------------------
158+// shred API
159+//-----------------------------------------------------------------------------
160+CK_DLL_CTOR( shred_ctor );
161+CK_DLL_DTOR( shred_dtor );
162+CK_DLL_MFUN( shred_exit );
163+CK_DLL_MFUN( shred_clone );
164+CK_DLL_MFUN( shred_id );
165+CK_DLL_MFUN( shred_yield );
166+CK_DLL_MFUN( shred_running );
167+CK_DLL_MFUN( shred_done );
168+CK_DLL_MFUN( shred_numArgs );
169+CK_DLL_MFUN( shred_getArg );
170+CK_DLL_MFUN( shred_sourcePath ); // added 1.3.0.0
171+CK_DLL_MFUN( shred_sourceDir ); // added 1.3.0.0
172+CK_DLL_MFUN( shred_sourceDir2 ); // added 1.3.2.0
173+CK_DLL_SFUN( shred_fromId ); // added 1.3.2.0
174+
175+
176+//-----------------------------------------------------------------------------
177+// array API
178+//-----------------------------------------------------------------------------
179+CK_DLL_CTOR( array_ctor );
180+CK_DLL_DTOR( array_dtor );
181+CK_DLL_MFUN( array_set_capacity );
182+CK_DLL_MFUN( array_get_capacity );
183+CK_DLL_MFUN( array_get_capacity_hack );
184+CK_DLL_MFUN( array_set_size );
185+CK_DLL_MFUN( array_get_size );
186+CK_DLL_MFUN( array_push_back );
187+CK_DLL_MFUN( array_pop_back );
188+CK_DLL_MFUN( array_push_front );
189+CK_DLL_MFUN( array_pop_front );
190+CK_DLL_MFUN( array_find );
191+CK_DLL_MFUN( array_erase );
192+CK_DLL_MFUN( array_clear );
193+CK_DLL_MFUN( array_reset );
194+
195+
196+//-----------------------------------------------------------------------------
197+// event API
198+//-----------------------------------------------------------------------------
199+CK_DLL_CTOR( event_ctor );
200+CK_DLL_DTOR( event_dtor );
201+CK_DLL_MFUN( event_signal );
202+CK_DLL_MFUN( event_broadcast );
203+CK_DLL_MFUN( event_wait );
204+CK_DLL_MFUN( event_can_wait );
205+
206+
207+//-----------------------------------------------------------------------------
208+// io API
209+//-----------------------------------------------------------------------------
210+CK_DLL_MFUN( io_dummy );
211+CK_DLL_SFUN( io_newline );
212+CK_DLL_SFUN( io_openfile );
213+
214+
215+//-----------------------------------------------------------------------------
216+// fileio API
217+//-----------------------------------------------------------------------------
218+CK_DLL_CTOR( fileio_ctor );
219+CK_DLL_DTOR( fileio_dtor );
220+CK_DLL_MFUN( fileio_open );
221+CK_DLL_MFUN( fileio_openflags );
222+CK_DLL_MFUN( fileio_good );
223+CK_DLL_MFUN( fileio_close );
224+CK_DLL_MFUN( fileio_flush );
225+CK_DLL_MFUN( fileio_getmode );
226+CK_DLL_MFUN( fileio_setmode );
227+CK_DLL_MFUN( fileio_size );
228+CK_DLL_MFUN( fileio_seek );
229+CK_DLL_MFUN( fileio_tell );
230+CK_DLL_MFUN( fileio_isdir );
231+CK_DLL_MFUN( fileio_dirlist );
232+CK_DLL_MFUN( fileio_read );
233+CK_DLL_MFUN( fileio_readline );
234+CK_DLL_MFUN( fileio_readint );
235+CK_DLL_MFUN( fileio_readintflags );
236+CK_DLL_MFUN( fileio_readfloat );
237+CK_DLL_MFUN( fileio_eof );
238+CK_DLL_MFUN( fileio_more );
239+CK_DLL_MFUN( fileio_writestring );
240+CK_DLL_MFUN( fileio_writeint );
241+CK_DLL_MFUN( fileio_writeintflags );
242+CK_DLL_MFUN( fileio_writefloat );
243+
244+
245+//-----------------------------------------------------------------------------
246+// chout API -- added 1.3.0.0 as full class
247+//-----------------------------------------------------------------------------
248+CK_DLL_MFUN( chout_good );
249+CK_DLL_MFUN( chout_close );
250+CK_DLL_MFUN( chout_flush );
251+CK_DLL_MFUN( chout_getmode );
252+CK_DLL_MFUN( chout_setmode );
253+CK_DLL_MFUN( chout_read );
254+CK_DLL_MFUN( chout_readline );
255+CK_DLL_MFUN( chout_readint );
256+CK_DLL_MFUN( chout_readintflags );
257+CK_DLL_MFUN( chout_readfloat );
258+CK_DLL_MFUN( chout_eof );
259+CK_DLL_MFUN( chout_more );
260+CK_DLL_MFUN( chout_writestring );
261+CK_DLL_MFUN( chout_writeint );
262+CK_DLL_MFUN( chout_writefloat );
263+
264+
265+//-----------------------------------------------------------------------------
266+// cherr API -- added 1.3.0.0 as full class
267+//-----------------------------------------------------------------------------
268+CK_DLL_MFUN( cherr_good );
269+CK_DLL_MFUN( cherr_close );
270+CK_DLL_MFUN( cherr_flush );
271+CK_DLL_MFUN( cherr_getmode );
272+CK_DLL_MFUN( cherr_setmode );
273+CK_DLL_MFUN( cherr_read );
274+CK_DLL_MFUN( cherr_readline );
275+CK_DLL_MFUN( cherr_readint );
276+CK_DLL_MFUN( cherr_readintflags );
277+CK_DLL_MFUN( cherr_readfloat );
278+CK_DLL_MFUN( cherr_eof );
279+CK_DLL_MFUN( cherr_more );
280+CK_DLL_MFUN( cherr_writestring );
281+CK_DLL_MFUN( cherr_writeint );
282+CK_DLL_MFUN( cherr_writefloat );
283+
284+
285+//-----------------------------------------------------------------------------
286+// string API
287+//-----------------------------------------------------------------------------
288+CK_DLL_CTOR( string_ctor );
289+CK_DLL_DTOR( string_dtor );
290+CK_DLL_MFUN( string_length );
291+CK_DLL_MFUN( string_upper );
292+CK_DLL_MFUN( string_lower );
293+CK_DLL_MFUN( string_ltrim );
294+CK_DLL_MFUN( string_rtrim );
295+CK_DLL_MFUN( string_trim );
296+CK_DLL_MFUN( string_toString );
297+CK_DLL_MFUN( string_set_at );
298+CK_DLL_MFUN( string_get_at );
299+CK_DLL_MFUN( string_charAt);
300+CK_DLL_MFUN( string_setCharAt);
301+CK_DLL_MFUN( string_substring);
302+CK_DLL_MFUN( string_substringN);
303+CK_DLL_MFUN( string_insert);
304+CK_DLL_MFUN( string_replace);
305+CK_DLL_MFUN( string_replaceN);
306+CK_DLL_MFUN( string_find);
307+CK_DLL_MFUN( string_findStart);
308+CK_DLL_MFUN( string_findStr);
309+CK_DLL_MFUN( string_findStrStart);
310+CK_DLL_MFUN( string_rfind);
311+CK_DLL_MFUN( string_rfindStart);
312+CK_DLL_MFUN( string_rfindStr);
313+CK_DLL_MFUN( string_rfindStrStart);
314+CK_DLL_MFUN( string_erase);
315+CK_DLL_MFUN( string_toInt);
316+CK_DLL_MFUN( string_toFloat);
317+CK_DLL_MFUN( string_parent);
318+
319+
320+//-----------------------------------------------------------------------------
321+// vector API (vec3, vec4, eventually vector) ge: 1.3.5.3
322+//-----------------------------------------------------------------------------
323+CK_DLL_MFUN( vec3_set );
324+CK_DLL_MFUN( vec3_setAll );
325+CK_DLL_MFUN( vec3_magnitude );
326+CK_DLL_MFUN( vec3_normalize );
327+CK_DLL_MFUN( vec3_interp );
328+CK_DLL_MFUN( vec3_interp_delta_float );
329+CK_DLL_MFUN( vec3_interp_delta_dur );
330+CK_DLL_MFUN( vec3_update_goal );
331+CK_DLL_MFUN( vec3_update_goal_slew );
332+CK_DLL_MFUN( vec3_updateSet_goalAndValue );
333+CK_DLL_MFUN( vec3_updateSet_goalAndValue_slew );
334+CK_DLL_MFUN( vec4_set );
335+CK_DLL_MFUN( vec4_setAll );
336+CK_DLL_MFUN( vec4_magnitude );
337+CK_DLL_MFUN( vec4_normalize );
338+
339+
340+//-----------------------------------------------------------------------------
341+// name: Data_Exception
342+// desc: data for base Chuck Exception class
343+//-----------------------------------------------------------------------------
344+struct Data_Exception
345+{
346+public:
347+ Data_Exception();
348+ ~Data_Exception();
349+
350+public:
351+};
352+//-----------------------------------------------------------------------------
353+// exception API
354+//-----------------------------------------------------------------------------
355+
356+
357+//-----------------------------------------------------------------------------
358+// MidiMsg API
359+//-----------------------------------------------------------------------------
360+CK_DLL_CTOR( MidiMsg_ctor );
361+
362+extern t_CKUINT MidiMsg_offset_data1;
363+extern t_CKUINT MidiMsg_offset_data2;
364+extern t_CKUINT MidiMsg_offset_data3;
365+extern t_CKUINT MidiMsg_offset_when;
366+
367+//-----------------------------------------------------------------------------
368+// MidiRW API
369+//-----------------------------------------------------------------------------
370+CK_DLL_CTOR( MidiRW_ctor );
371+CK_DLL_DTOR( MidiRW_dtor );
372+CK_DLL_MFUN( MidiRW_open );
373+CK_DLL_MFUN( MidiRW_close );
374+CK_DLL_MFUN( MidiRW_read );
375+CK_DLL_MFUN( MidiRW_write );
376+
377+
378+//-----------------------------------------------------------------------------
379+// MidiMsgOut API
380+//-----------------------------------------------------------------------------
381+CK_DLL_CTOR( MidiMsgOut_ctor );
382+CK_DLL_DTOR( MidiMsgOut_dtor );
383+CK_DLL_MFUN( MidiMsgOut_open );
384+CK_DLL_MFUN( MidiMsgOut_close );
385+CK_DLL_MFUN( MidiMsgOut_write );
386+
387+
388+//-----------------------------------------------------------------------------
389+// MidiMsgIn API
390+//-----------------------------------------------------------------------------
391+CK_DLL_CTOR( MidiMsgIn_ctor );
392+CK_DLL_DTOR( MidiMsgIn_dtor );
393+CK_DLL_MFUN( MidiMsgIn_open );
394+CK_DLL_MFUN( MidiMsgIn_close );
395+CK_DLL_MFUN( MidiMsgIn_read );
396+
397+
398+//-----------------------------------------------------------------------------
399+// MidiIn API
400+//-----------------------------------------------------------------------------
401+CK_DLL_CTOR( MidiIn_ctor );
402+CK_DLL_DTOR( MidiIn_dtor );
403+CK_DLL_MFUN( MidiIn_open );
404+CK_DLL_MFUN( MidiIn_open_named ); // added 1.3.0.0
405+CK_DLL_MFUN( MidiIn_open_named_i ); // added 1.3.0.0
406+CK_DLL_MFUN( MidiIn_good );
407+CK_DLL_MFUN( MidiIn_num );
408+CK_DLL_MFUN( MidiIn_name );
409+CK_DLL_MFUN( MidiIn_printerr );
410+CK_DLL_MFUN( MidiIn_recv );
411+CK_DLL_MFUN( MidiIn_can_wait );
412+
413+
414+//-----------------------------------------------------------------------------
415+// MidiOut API
416+//-----------------------------------------------------------------------------
417+CK_DLL_CTOR( MidiOut_ctor );
418+CK_DLL_DTOR( MidiOut_dtor );
419+CK_DLL_MFUN( MidiOut_open );
420+CK_DLL_MFUN( MidiOut_open_named ); // added 1.3.0.0
421+CK_DLL_MFUN( MidiOut_open_named_i); // added 1.3.0.0
422+CK_DLL_MFUN( MidiOut_good );
423+CK_DLL_MFUN( MidiOut_num );
424+CK_DLL_MFUN( MidiOut_name );
425+CK_DLL_MFUN( MidiOut_printerr );
426+CK_DLL_MFUN( MidiOut_send );
427+
428+
429+//-----------------------------------------------------------------------------
430+// HidMsg API
431+//-----------------------------------------------------------------------------
432+CK_DLL_MFUN( HidMsg_is_axis_motion );
433+CK_DLL_MFUN( HidMsg_is_button_down );
434+CK_DLL_MFUN( HidMsg_is_button_up );
435+CK_DLL_MFUN( HidMsg_is_mouse_motion );
436+CK_DLL_MFUN( HidMsg_is_hat_motion );
437+CK_DLL_MFUN( HidMsg_is_wheel_motion );
438+
439+//-----------------------------------------------------------------------------
440+// HidIn API
441+//-----------------------------------------------------------------------------
442+CK_DLL_CTOR( HidIn_ctor );
443+CK_DLL_DTOR( HidIn_dtor );
444+CK_DLL_MFUN( HidIn_open );
445+CK_DLL_MFUN( HidIn_open_named );
446+CK_DLL_MFUN( HidIn_open_named_i ); // added 1.3.0.0
447+CK_DLL_MFUN( HidIn_open_joystick );
448+CK_DLL_MFUN( HidIn_open_mouse );
449+CK_DLL_MFUN( HidIn_open_keyboard );
450+CK_DLL_MFUN( HidIn_open_tiltsensor );
451+CK_DLL_MFUN( HidIn_good );
452+CK_DLL_MFUN( HidIn_num );
453+CK_DLL_MFUN( HidIn_name );
454+CK_DLL_MFUN( HidIn_printerr );
455+CK_DLL_MFUN( HidIn_recv );
456+CK_DLL_MFUN( HidIn_read );
457+CK_DLL_MFUN( HidIn_send );
458+CK_DLL_MFUN( HidIn_can_wait );
459+CK_DLL_SFUN( HidIn_read_tilt_sensor );
460+CK_DLL_SFUN( HidIn_ctrl_tiltPollRate );
461+CK_DLL_SFUN( HidIn_cget_tiltPollRate );
462+CK_DLL_SFUN( HidIn_start_cursor_track );
463+CK_DLL_SFUN( HidIn_stop_cursor_track );
464+
465+
466+//-----------------------------------------------------------------------------
467+// HidOut API
468+//-----------------------------------------------------------------------------
469+CK_DLL_CTOR( HidOut_ctor );
470+CK_DLL_DTOR( HidOut_dtor );
471+CK_DLL_MFUN( HidOut_open );
472+CK_DLL_MFUN( HidOut_good );
473+CK_DLL_MFUN( HidOut_num );
474+CK_DLL_MFUN( HidOut_name );
475+CK_DLL_MFUN( HidOut_printerr );
476+CK_DLL_MFUN( HidOut_send );
477+
478+
479+
480+
481+#endif
core/chuck_oo.cpp+3285−0
@@ -0,0 +1,3285 @@
1+/*----------------------------------------------------------------------------
2+ ChucK Concurrent, On-the-fly Audio Programming Language
3+ Compiler and Virtual Machine
4+
5+ Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
6+ http://chuck.stanford.edu/
7+ http://chuck.cs.princeton.edu/
8+
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.
13+
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.
18+
19+ You should have received a copy of the GNU General Public License
20+ along with this program; if not, write to the Free Software
21+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22+ U.S.A.
23+-----------------------------------------------------------------------------*/
24+
25+//-----------------------------------------------------------------------------
26+// file: chuck_oo.cpp
27+// desc: chuck baes objects
28+//
29+// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
30+// Ananya Misra (amisra@cs.princeton.edu)
31+// Andrew Schran (aschran@princeton.edu) - fileIO implementation
32+// date: Autumn 2004
33+//-----------------------------------------------------------------------------
34+#include "chuck_oo.h"
35+#include "chuck_type.h"
36+#include "chuck_vm.h"
37+#include "chuck_instr.h"
38+#include "chuck_errmsg.h"
39+#include "chuck_dl.h"
40+
41+#include <iostream>
42+#include <sstream>
43+#include <iomanip>
44+#include <typeinfo>
45+using namespace std;
46+
47+#if defined(__PLATFORM_WIN32__)
48+ #include "dirent_win32.h"
49+#endif
50+
51+
52+// initialize
53+t_CKBOOL Chuck_VM_Object::our_locks_in_effect = TRUE;
54+const t_CKINT Chuck_IO::INT32 = 0x1;
55+const t_CKINT Chuck_IO::INT16 = 0x2;
56+const t_CKINT Chuck_IO::INT8 = 0x4;
57+const t_CKINT Chuck_IO::MODE_SYNC = 0;
58+const t_CKINT Chuck_IO::MODE_ASYNC = 1;
59+const t_CKINT Chuck_IO_File::FLAG_READ_WRITE = 0x8;
60+const t_CKINT Chuck_IO_File::FLAG_READONLY = 0x10;
61+const t_CKINT Chuck_IO_File::FLAG_WRITEONLY = 0x20;
62+const t_CKINT Chuck_IO_File::FLAG_APPEND = 0x40;
63+const t_CKINT Chuck_IO_File::TYPE_ASCII = 0x80;
64+const t_CKINT Chuck_IO_File::TYPE_BINARY = 0x100;
65+void (* Chuck_IO_Chout::m_callback)(const char *) = NULL;
66+void (* Chuck_IO_Cherr::m_callback)(const char *) = NULL;
67+std::stringstream Chuck_IO_Chout::m_buffer;
68+std::stringstream Chuck_IO_Cherr::m_buffer;
69+
70+
71+
72+
73+//-----------------------------------------------------------------------------
74+// name: init_ref()
75+// desc: initialize vm object
76+//-----------------------------------------------------------------------------
77+void Chuck_VM_Object::init_ref()
78+{
79+ // set reference count
80+ m_ref_count = 0;
81+ // set flag
82+ m_pooled = FALSE;
83+ // set to not locked
84+ m_locked = FALSE;
85+ // set v ref
86+ m_v_ref = NULL;
87+ // add to vm allocator
88+ // Chuck_VM_Alloc::instance()->add_object( this );
89+}
90+
91+
92+
93+
94+//-----------------------------------------------------------------------------
95+// name: add_ref()
96+// desc: add reference
97+//-----------------------------------------------------------------------------
98+void Chuck_VM_Object::add_ref()
99+{
100+ // increment reference count
101+ m_ref_count++;
102+
103+ // if going from 0 to 1
104+ if( m_ref_count == 1 )
105+ {
106+ // add to vm allocator
107+ Chuck_VM_Alloc::instance()->add_object( this );
108+ }
109+
110+ // added 1.3.0.0
111+ CK_MEMMGMT_TRACK(CK_FPRINTF_STDERR( "Chuck_VM_Object::add_ref() : 0x%08x, %s, %lu\n", this, typeid(*this).name(), m_ref_count));
112+ // string n = typeid(*this).name();
113+ // cerr << "ADDREF: " << dec << n << " " << m_ref_count << " 0x" << hex << (int)this << endl;
114+}
115+
116+
117+
118+
119+//-----------------------------------------------------------------------------
120+// name: release()
121+// desc: remove reference
122+//-----------------------------------------------------------------------------
123+void Chuck_VM_Object::release()
124+{
125+ // make sure there is at least one reference
126+ assert( m_ref_count > 0 );
127+ // decrement
128+ m_ref_count--;
129+
130+ // added 1.3.0.0
131+ CK_MEMMGMT_TRACK(CK_FPRINTF_STDERR( "Chuck_VM_Object::release() : 0x%08x, %s, %ulu\n", this, typeid(*this).name(), m_ref_count));
132+ // string n = typeid(*this).name();
133+ // cerr << "RELEASE: " << dec << n << " " << m_ref_count << " 0x" << hex << (int)this << endl;
134+
135+ // if no more references
136+ if( m_ref_count == 0 )
137+ {
138+ // this is not good
139+ if( our_locks_in_effect && m_locked )
140+ {
141+ EM_error2( 0, "internal error: releasing locked VM object!" );
142+ // fail
143+ assert( FALSE );
144+ // in case assert is disabled
145+ *(int *)0 = 1;
146+ }
147+
148+ // tell the object manager to set this free
149+ Chuck_VM_Alloc::instance()->free_object( this );
150+ }
151+}
152+
153+
154+
155+
156+//-----------------------------------------------------------------------------
157+// name: lock()
158+// desc: lock to keep from deleted
159+//-----------------------------------------------------------------------------
160+void Chuck_VM_Object::lock()
161+{
162+ m_locked = TRUE;
163+}
164+
165+
166+
167+
168+//-----------------------------------------------------------------------------
169+// name: lock_all()
170+// desc: disallow deletion of locked objects
171+//-----------------------------------------------------------------------------
172+void Chuck_VM_Object::lock_all()
173+{
174+ // log
175+ EM_log( CK_LOG_SYSTEM, "locking down special objects..." );
176+ // set flag
177+ our_locks_in_effect = TRUE;
178+}
179+
180+
181+
182+
183+//-----------------------------------------------------------------------------
184+// name: unlock_all()
185+// desc: allow deletion of locked objects (USE WITH CAUTION!)
186+//-----------------------------------------------------------------------------
187+void Chuck_VM_Object::unlock_all()
188+{
189+ // log
190+ EM_log( CK_LOG_SYSTEM, "unprotecting special objects..." );
191+ // set flag
192+ our_locks_in_effect = FALSE;
193+}
194+
195+
196+
197+
198+// static member
199+Chuck_VM_Alloc * Chuck_VM_Alloc::our_instance = NULL;
200+
201+
202+//-----------------------------------------------------------------------------
203+// name: instance()
204+// desc: return static instance
205+//-----------------------------------------------------------------------------
206+Chuck_VM_Alloc * Chuck_VM_Alloc::instance()
207+{
208+ if( !our_instance )
209+ {
210+ our_instance = new Chuck_VM_Alloc;
211+ assert( our_instance != NULL );
212+ }
213+
214+ return our_instance;
215+}
216+
217+
218+
219+
220+//-----------------------------------------------------------------------------
221+// name: add_object()
222+// desc: add newly allocated vm object
223+//-----------------------------------------------------------------------------
224+void Chuck_VM_Alloc::add_object( Chuck_VM_Object * obj )
225+{
226+ // do log
227+ if( DO_LOG( CK_LOG_CRAZY ) )
228+ {
229+ // log it
230+ EM_log( CK_LOG_CRAZY, "adding '%s' (0x%lx)...",
231+ mini_type( typeid(*obj).name() ), obj );
232+ }
233+
234+ // add it to map
235+}
236+
237+
238+
239+
240+//-----------------------------------------------------------------------------
241+// name: free_object()
242+// desc: free vm object - reference count should be 0
243+//-----------------------------------------------------------------------------
244+void Chuck_VM_Alloc::free_object( Chuck_VM_Object * obj )
245+{
246+ // make sure the ref count is 0
247+ assert( obj && obj->m_ref_count == 0 );
248+
249+ // do log
250+ if( DO_LOG( CK_LOG_FINEST ) )
251+ {
252+ // log it
253+ EM_log( CK_LOG_FINEST, "freeing '%s' (0x%lx)...",
254+ mini_type( typeid(*obj).name() ), obj );
255+ }
256+
257+ // remove it from map
258+
259+ // delete it
260+ delete obj;
261+}
262+
263+
264+
265+
266+//-----------------------------------------------------------------------------
267+// name: Chuck_VM_Alloc()
268+// desc: constructor
269+//-----------------------------------------------------------------------------
270+Chuck_VM_Alloc::Chuck_VM_Alloc()
271+{ }
272+
273+
274+
275+
276+//-----------------------------------------------------------------------------
277+// name: ~Chuck_VM_Alloc()
278+// desc: destructor
279+//-----------------------------------------------------------------------------
280+Chuck_VM_Alloc::~Chuck_VM_Alloc()
281+{ }
282+
283+
284+
285+
286+//-----------------------------------------------------------------------------
287+// name: Chuck_Object()
288+// desc: constructor
289+//-----------------------------------------------------------------------------
290+Chuck_Object::Chuck_Object()
291+{
292+ // zero virtual table
293+ vtable = NULL;
294+ // zero type
295+ type_ref = NULL;
296+ // zero size
297+ size = 0;
298+ // zero data
299+ data = NULL;
300+
301+ // add to vm allocator
302+ Chuck_VM_Alloc::instance()->add_object( this );
303+}
304+
305+
306+
307+
308+//-----------------------------------------------------------------------------
309+// name: Chuck_Object()
310+// desc: ...
311+//-----------------------------------------------------------------------------
312+Chuck_Object::~Chuck_Object()
313+{
314+ // added 1.3.0.0:
315+ // call destructors, from latest descended child to oldest parent
316+ Chuck_Type * type = this->type_ref;
317+ while( type != NULL )
318+ {
319+ // SPENCERTODO: HACK! is there a better way to call the dtor?
320+ if( type->has_destructor )
321+ {
322+ // sanity check
323+ assert( type->info->dtor && type->info->dtor->native_func );
324+ ((f_dtor)(type->info->dtor->native_func))( this, NULL, Chuck_DL_Api::Api::instance() );
325+ }
326+
327+ // go up the inheritance
328+ type = type->parent;
329+ }
330+
331+ // free
332+ if( vtable ) { delete vtable; vtable = NULL; }
333+ if( type_ref ) { type_ref->release(); type_ref = NULL; }
334+ if( data ) { delete [] data; size = 0; data = NULL; }
335+}
336+
337+
338+
339+
340+//-----------------------------------------------------------------------------
341+// name: Chuck_Array4()
342+// desc: constructor
343+//-----------------------------------------------------------------------------
344+Chuck_Array4::Chuck_Array4( t_CKBOOL is_obj, t_CKINT capacity )
345+{
346+ // sanity check
347+ assert( capacity >= 0 );
348+ // set size
349+ m_vector.resize( capacity );
350+ // clear (as non-object, so no releases)
351+ m_is_obj = FALSE;
352+ this->zero( 0, m_vector.capacity() );
353+ // is object (set after clear)
354+ m_is_obj = is_obj;
355+}
356+
357+
358+
359+
360+//-----------------------------------------------------------------------------
361+// name: ~Chuck_Array4()
362+// desc: destructor
363+//-----------------------------------------------------------------------------
364+Chuck_Array4::~Chuck_Array4()
365+{
366+ // do nothing
367+}
368+
369+
370+
371+
372+//-----------------------------------------------------------------------------
373+// name: addr()
374+// desc: ...
375+//-----------------------------------------------------------------------------
376+t_CKUINT Chuck_Array4::addr( t_CKINT i )
377+{
378+ // bound check
379+ if( i < 0 || i >= m_vector.capacity() )
380+ return 0;
381+
382+ // get the addr
383+ return (t_CKUINT)(&m_vector[i]);
384+}
385+
386+
387+
388+
389+//-----------------------------------------------------------------------------
390+// name: addr()
391+// desc: ...
392+//-----------------------------------------------------------------------------
393+t_CKUINT Chuck_Array4::addr( const string & key )
394+{
395+ // get the addr
396+ return (t_CKUINT)(&m_map[key]);
397+}
398+
399+
400+
401+
402+//-----------------------------------------------------------------------------
403+// name: get()
404+// desc: ...
405+//-----------------------------------------------------------------------------
406+t_CKINT Chuck_Array4::get( t_CKINT i, t_CKUINT * val )
407+{
408+ // bound check
409+ if( i < 0 || i >= m_vector.capacity() )
410+ return 0;
411+
412+ // get the value
413+ *val = m_vector[i];
414+
415+ // return good
416+ return 1;
417+}
418+
419+
420+
421+
422+//-----------------------------------------------------------------------------
423+// name: get()
424+// desc: ...
425+//-----------------------------------------------------------------------------
426+t_CKINT Chuck_Array4::get( const string & key, t_CKUINT * val )
427+{
428+ // set to zero
429+ *val = 0;
430+ // find
431+ map<string, t_CKUINT>::iterator iter = m_map.find( key );
432+ // check
433+ if( iter != m_map.end() ) *val = (*iter).second;
434+
435+ // return good
436+ return 1;
437+}
438+
439+
440+
441+
442+//-----------------------------------------------------------------------------
443+// name: set()
444+// desc: include ref counting
445+//-----------------------------------------------------------------------------
446+t_CKINT Chuck_Array4::set( t_CKINT i, t_CKUINT val )
447+{
448+ // bound check
449+ if( i < 0 || i >= m_vector.capacity() )
450+ return 0;
451+
452+ t_CKUINT v = m_vector[i];
453+
454+ // if obj
455+ if( m_is_obj && v ) ((Chuck_Object *)v)->release();
456+
457+ // set the value
458+ m_vector[i] = val;
459+
460+ // if obj
461+ if( m_is_obj && val ) ((Chuck_Object *)val)->add_ref();
462+
463+ // return good
464+ return 1;
465+}
466+
467+
468+
469+
470+
471+//-----------------------------------------------------------------------------
472+// name: set()
473+// desc: include ref counting
474+//-----------------------------------------------------------------------------
475+t_CKINT Chuck_Array4::set( const string & key, t_CKUINT val )
476+{
477+ map<string, t_CKUINT>::iterator iter = m_map.find( key );
478+
479+ // if obj
480+ if( m_is_obj && iter != m_map.end() )
481+ ((Chuck_Object *)(*iter).second)->release();
482+
483+ if( !val ) m_map.erase( key );
484+ else m_map[key] = val;
485+
486+ // if obj
487+ if( m_is_obj && val ) ((Chuck_Object *)val)->add_ref();
488+
489+ // return good
490+ return 1;
491+}
492+
493+
494+
495+
496+//-----------------------------------------------------------------------------
497+// name: find()
498+// desc: ...
499+//-----------------------------------------------------------------------------
500+t_CKINT Chuck_Array4::find( const string & key )
501+{
502+ return m_map.find( key ) != m_map.end();
503+}
504+
505+
506+
507+
508+//-----------------------------------------------------------------------------
509+// name: erase()
510+// desc: ...
511+//-----------------------------------------------------------------------------
512+t_CKINT Chuck_Array4::erase( const string & key )
513+{
514+ map<string, t_CKUINT>::iterator iter = m_map.find( key );
515+ t_CKINT v = iter != m_map.end();
516+
517+ // if obj
518+ if( m_is_obj && iter != m_map.end() )
519+ ((Chuck_Object *)(*iter).second)->release();
520+
521+ // erase
522+ if( v ) m_map.erase( key );
523+
524+ return v;
525+}
526+
527+
528+
529+
530+//-----------------------------------------------------------------------------
531+// name: push_back()
532+// desc: ...
533+//-----------------------------------------------------------------------------
534+t_CKINT Chuck_Array4::push_back( t_CKUINT val )
535+{
536+ // TODO: is this right?
537+
538+ // if obj, reference count it (added 1.3.0.0)
539+ if( m_is_obj && val ) ((Chuck_Object *)val)->add_ref();
540+
541+ // add to vector
542+ m_vector.push_back( val );
543+
544+ return 1;
545+}
546+
547+
548+
549+
550+//-----------------------------------------------------------------------------
551+// name: pop_back()
552+// desc: ...
553+//-----------------------------------------------------------------------------
554+t_CKINT Chuck_Array4::pop_back( )
555+{
556+ // check
557+ if( m_vector.size() == 0 )
558+ return 0;
559+
560+ // if obj
561+ if( m_is_obj )
562+ {
563+ // get pointer
564+ Chuck_Object * v = (Chuck_Object *)m_vector[m_vector.size()-1];
565+ // if not null, release
566+ if( v ) v->release();
567+ }
568+
569+ // zero
570+ m_vector[m_vector.size()-1] = 0;
571+ // add to vector
572+ m_vector.pop_back();
573+
574+ return 1;
575+}
576+
577+
578+
579+
580+//-----------------------------------------------------------------------------
581+// name: back()
582+// desc: ...
583+//-----------------------------------------------------------------------------
584+t_CKINT Chuck_Array4::back( t_CKUINT * val ) const
585+{
586+ // check
587+ if( m_vector.size() == 0 )
588+ return 0;
589+
590+ // get
591+ *val = m_vector.back();
592+
593+ return 1;
594+}
595+
596+
597+
598+
599+//-----------------------------------------------------------------------------
600+// name: clear()
601+// desc: ...
602+//-----------------------------------------------------------------------------
603+void Chuck_Array4::clear( )
604+{
605+ // zero
606+ zero( 0, m_vector.size() );
607+
608+ // clear vector
609+ m_vector.clear();
610+}
611+
612+
613+
614+
615+//-----------------------------------------------------------------------------
616+// name: set_capacity()
617+// desc: ...
618+//-----------------------------------------------------------------------------
619+t_CKINT Chuck_Array4::set_capacity( t_CKINT capacity )
620+{
621+ // sanity check
622+ assert( capacity >= 0 );
623+
624+ // ensure size
625+ set_size( capacity );
626+
627+ return m_vector.capacity();
628+}
629+
630+
631+
632+
633+//-----------------------------------------------------------------------------
634+// name: set_size()
635+// desc: ...
636+//-----------------------------------------------------------------------------
637+t_CKINT Chuck_Array4::set_size( t_CKINT size )
638+{
639+ // sanity check
640+ assert( size >= 0 );
641+
642+ // if clearing size
643+ if( size < m_vector.size() )
644+ {
645+ // zero out section
646+ zero( size, m_vector.size() );
647+ }
648+
649+ // what the size was
650+ t_CKINT size2 = m_vector.size();
651+ // resize vector
652+ m_vector.resize( size );
653+
654+ // if clearing size
655+ if( m_vector.size() > size2 )
656+ {
657+ // zero out section
658+ zero( size2, m_vector.size() );
659+ }
660+
661+ return m_vector.size();
662+}
663+
664+
665+
666+
667+//-----------------------------------------------------------------------------
668+// name: zero()
669+// desc: ...
670+//-----------------------------------------------------------------------------
671+void Chuck_Array4::zero( t_CKUINT start, t_CKUINT end )
672+{
673+ // sanity check
674+ assert( start <= m_vector.capacity() && end <= m_vector.capacity() );
675+
676+ // if contains objects
677+ if( m_is_obj )
678+ {
679+ Chuck_Object * v = NULL;
680+ for( t_CKUINT i = start; i < end; i++ )
681+ {
682+ // get it
683+ v = (Chuck_Object *)m_vector[i];
684+ // release
685+ if( v )
686+ {
687+ v->release();

2598 more lines aren’t shown here.

core/chuck_otf.cpp+728−0

This diff is large: its 729 lines aren’t shown here.

core/chuck_otf.h+98−0

This diff is large: its 99 lines aren’t shown here.

core/chuck_parse.cpp+230−0

This diff is large: its 231 lines aren’t shown here.

core/chuck_parse.h+153−0

This diff is large: its 154 lines aren’t shown here.

core/chuck_scan.cpp+2750−0

This diff is large: its 2751 lines aren’t shown here.

core/chuck_scan.h+71−0

This diff is large: its 72 lines aren’t shown here.

core/chuck_symbol.cpp+143−0

This diff is large: its 144 lines aren’t shown here.

core/chuck_symbol.h+88−0

This diff is large: its 89 lines aren’t shown here.

core/chuck_table.cpp+221−0

This diff is large: its 222 lines aren’t shown here.

core/chuck_table.h+76−0

This diff is large: its 77 lines aren’t shown here.

core/chuck_type.cpp+6483−0

This diff is large: its 6484 lines aren’t shown here.

core/chuck_type.h+947−0

This diff is large: its 948 lines aren’t shown here.

core/chuck_utils.cpp+77−0

This diff is large: its 78 lines aren’t shown here.

core/chuck_utils.h+62−0

This diff is large: its 63 lines aren’t shown here.

core/dirent_win32.h+234−0

This diff is large: its 235 lines aren’t shown here.

core/lo/address.c+346−0

This diff is large: its 347 lines aren’t shown here.

core/lo/blob.c+64−0

This diff is large: its 65 lines aren’t shown here.

core/lo/bundle.c+181−0

This diff is large: its 182 lines aren’t shown here.

core/lo/config.h+200−0

This diff is large: its 201 lines aren’t shown here.

core/lo/lo.h+353−0

This diff is large: its 354 lines aren’t shown here.

core/lo/lo_endian.h+256−0

This diff is large: its 257 lines aren’t shown here.

core/lo/lo_errors.h+45−0

This diff is large: its 46 lines aren’t shown here.

core/lo/lo_internal.h+63−0

This diff is large: its 64 lines aren’t shown here.

core/lo/lo_lowlevel.h+860−0

This diff is large: its 861 lines aren’t shown here.

core/lo/lo_macros.h+80−0

This diff is large: its 81 lines aren’t shown here.

core/lo/lo_osc_types.h+145−0

This diff is large: its 146 lines aren’t shown here.

core/lo/lo_throw.h+30−0

This diff is large: its 31 lines aren’t shown here.

core/lo/lo_types.h+143−0

This diff is large: its 144 lines aren’t shown here.

core/lo/lo_types_internal.h+145−0

This diff is large: its 146 lines aren’t shown here.

core/lo/message.c+1081−0

This diff is large: its 1082 lines aren’t shown here.

core/lo/method.c+35−0

This diff is large: its 36 lines aren’t shown here.

core/lo/pattern_match.c+248−0

This diff is large: its 249 lines aren’t shown here.

core/lo/send.c+491−0

This diff is large: its 492 lines aren’t shown here.

core/lo/server.c+1400−0

This diff is large: its 1401 lines aren’t shown here.

core/lo/server_thread.c+188−0

This diff is large: its 189 lines aren’t shown here.

core/lo/timetag.c+58−0

This diff is large: its 59 lines aren’t shown here.

core/regex/LICENSE.txt+29−0

This diff is large: its 30 lines aren’t shown here.

core/regex/README.txt+235−0

This diff is large: its 236 lines aren’t shown here.

core/regex/config.h+184−0

This diff is large: its 185 lines aren’t shown here.

core/regex/regcomp.c+129−0

This diff is large: its 130 lines aren’t shown here.

core/regex/regerror.c+83−0

This diff is large: its 84 lines aren’t shown here.

core/regex/regex.h+38−0

This diff is large: its 39 lines aren’t shown here.

core/regex/regexec.c+348−0

This diff is large: its 349 lines aren’t shown here.

core/regex/tre-ast.c+226−0

This diff is large: its 227 lines aren’t shown here.

core/regex/tre-ast.h+128−0

This diff is large: its 129 lines aren’t shown here.

core/regex/tre-compile.c+2296−0

This diff is large: its 2297 lines aren’t shown here.

core/regex/tre-compile.h+27−0

This diff is large: its 28 lines aren’t shown here.

core/regex/tre-config.h+52−0

This diff is large: its 53 lines aren’t shown here.

core/regex/tre-filter.c+73−0

This diff is large: its 74 lines aren’t shown here.

core/regex/tre-filter.h+19−0

This diff is large: its 20 lines aren’t shown here.

core/regex/tre-internal.h+287−0

This diff is large: its 288 lines aren’t shown here.

core/regex/tre-match-approx.c+812−0

This diff is large: its 813 lines aren’t shown here.

core/regex/tre-match-backtrack.c+666−0

This diff is large: its 667 lines aren’t shown here.

core/regex/tre-match-parallel.c+501−0

This diff is large: its 502 lines aren’t shown here.

core/regex/tre-match-utils.h+215−0

This diff is large: its 216 lines aren’t shown here.

core/regex/tre-mem.c+155−0

This diff is large: its 156 lines aren’t shown here.

core/regex/tre-mem.h+66−0

This diff is large: its 67 lines aren’t shown here.

core/regex/tre-parse.c+1739−0

This diff is large: its 1740 lines aren’t shown here.

core/regex/tre-parse.h+50−0

This diff is large: its 51 lines aren’t shown here.

core/regex/tre-stack.c+125−0

This diff is large: its 126 lines aren’t shown here.

core/regex/tre-stack.h+76−0

This diff is large: its 77 lines aren’t shown here.

core/regex/tre.h+276−0

This diff is large: its 277 lines aren’t shown here.

core/regex/xmalloc.c+351−0

This diff is large: its 352 lines aren’t shown here.

core/regex/xmalloc.h+77−0

This diff is large: its 78 lines aren’t shown here.

core/uana_extract.cpp+1526−0

This diff is large: its 1527 lines aren’t shown here.

core/uana_extract.h+45−0

This diff is large: its 46 lines aren’t shown here.

core/uana_xform.cpp+3762−0

This diff is large: its 3763 lines aren’t shown here.

core/uana_xform.h+45−0

This diff is large: its 46 lines aren’t shown here.

core/ugen_filter.cpp+2694−0

This diff is large: its 2695 lines aren’t shown here.

core/ugen_filter.h+238−0

This diff is large: its 239 lines aren’t shown here.

core/ugen_osc.cpp+1759−0

This diff is large: its 1760 lines aren’t shown here.

core/ugen_osc.h+112−0

This diff is large: its 113 lines aren’t shown here.

core/ugen_stk.cpp+27016−0

This diff is large: its 27017 lines aren’t shown here.

core/ugen_stk.h+6622−0

This diff is large: its 6623 lines aren’t shown here.

core/ugen_xxx.cpp+4965−0

This diff is large: its 4966 lines aren’t shown here.

core/ugen_xxx.h+256−0

This diff is large: its 257 lines aren’t shown here.

core/ulib_machine.cpp+221−0

This diff is large: its 222 lines aren’t shown here.

core/ulib_machine.h+62−0

This diff is large: its 63 lines aren’t shown here.

core/ulib_math.cpp+777−0

This diff is large: its 778 lines aren’t shown here.

core/ulib_math.h+100−0

This diff is large: its 101 lines aren’t shown here.

core/ulib_opsc.cpp+1662−0

This diff is large: its 1663 lines aren’t shown here.

core/ulib_opsc.h+79−0

This diff is large: its 80 lines aren’t shown here.

core/ulib_regex.cpp+404−0

This diff is large: its 405 lines aren’t shown here.

core/ulib_regex.h+40−0

This diff is large: its 41 lines aren’t shown here.

core/ulib_std.cpp+1971−0

This diff is large: its 1972 lines aren’t shown here.

core/ulib_std.h+143−0

This diff is large: its 144 lines aren’t shown here.

core/util_console.cpp+210−0

This diff is large: its 211 lines aren’t shown here.

core/util_console.h+51−0

This diff is large: its 52 lines aren’t shown here.

core/util_hid.cpp+8068−0

This diff is large: its 8069 lines aren’t shown here.

core/util_hid.h+221−0

This diff is large: its 222 lines aren’t shown here.

core/util_math.c+200−0

This diff is large: its 201 lines aren’t shown here.

core/util_math.h+75−0

This diff is large: its 76 lines aren’t shown here.

core/util_network.c+442−0

This diff is large: its 443 lines aren’t shown here.

core/util_network.h+105−0

This diff is large: its 106 lines aren’t shown here.

core/util_opsc.cpp+2541−0

This diff is large: its 2542 lines aren’t shown here.

core/util_opsc.h+630−0

This diff is large: its 631 lines aren’t shown here.

core/util_raw.c+4784−0

This diff is large: its 4785 lines aren’t shown here.

core/util_raw.h+100−0

This diff is large: its 101 lines aren’t shown here.

core/util_serial.cpp+248−0

This diff is large: its 249 lines aren’t shown here.

core/util_serial.h+58−0

This diff is large: its 59 lines aren’t shown here.

core/util_sndfile.c+34323−0

This diff is large: its 34324 lines aren’t shown here.

core/util_sndfile.h+2706−0

This diff is large: its 2707 lines aren’t shown here.

core/util_string.cpp+569−0

This diff is large: its 570 lines aren’t shown here.

core/util_string.h+87−0

This diff is large: its 88 lines aren’t shown here.

core/util_thread.cpp+443−0

This diff is large: its 444 lines aren’t shown here.

core/util_thread.h+213−0

This diff is large: its 214 lines aren’t shown here.

core/util_xforms.c+454−0

This diff is large: its 455 lines aren’t shown here.

core/util_xforms.h+89−0

This diff is large: its 90 lines aren’t shown here.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t