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
3D [0-9]
4L [a-zA-Z_]
5H [a-fA-F0-9]
6E [Ee][+-]?{D}+
7FS (f|F|l|L)
8IS (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
62extern YYSTYPE yylval;
63int 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)
69extern "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()
85int yywrap( void )
86{
87 char_pos = 1;
88 return 1;
89}
90
91// adjust()
92void adjust()
93{
94 EM_tokPos = char_pos;
95 char_pos += yyleng;
96}
97
98// strip
99c_str strip_lit( c_str str )
100{
101 str[strlen(str)-1] = '\0';
102 return str+1;
103}
104
105// alloc_str()
106c_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
115long 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; }
224for { adjust(); return FOR; }
225while { adjust(); return WHILE; }
226until { adjust(); return UNTIL; }
227repeat { adjust(); return LOOP; }
228continue { adjust(); return CONTINUE; }
229break { adjust(); return BREAK; }
230if { adjust(); return IF; }
231else { adjust(); return ELSE; }
232do { adjust(); return DO; }
233"<<<" { adjust(); return L_HACK; }
234">>>" { adjust(); return R_HACK; }
235
236return { adjust(); return RETURN; }
237
238function { adjust(); return FUNCTION; }
239fun { adjust(); return FUNCTION; }
240new { adjust(); return NEW; }
241class { adjust(); return CLASS; }
242interface { adjust(); return INTERFACE; }
243extends { adjust(); return EXTENDS; }
244implements { adjust(); return IMPLEMENTS; }
245public { adjust(); return PUBLIC; }
246protected { adjust(); return PROTECTED; }
247private { adjust(); return PRIVATE; }
248static { adjust(); return STATIC; }
249pure { adjust(); return ABSTRACT; }
250const { adjust(); return CONST; }
251spork { adjust(); return SPORK; }
252typeof { 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
2740[xX][0-9a-fA-F]+{IS}? { adjust(); yylval.ival=htol(yytext); return NUM; }
2750[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
289int 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
304int block_comment()
305{
306 char c, c1;
307
308loop:
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
46int yylex( void );
47
48void yyerror( char *s )
49{
50 EM_error( EM_tokPos, "%s", s );
51}
52
53a_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
180program
181 : program_section { $$ = g_program = new_program( $1, EM_lineNum ); }
182 | program_section program { $$ = g_program = prepend_program( $1, $2, EM_lineNum ); }
183 ;
184
185program_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
191class_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
202class_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
209class_body
210 : class_body2 { $$ = $1; }
211 | { $$ = NULL; }
212 ;
213
214class_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
220class_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
226iface_ext
227 : EXTENDS id_list { $$ = new_class_ext( NULL, $2, EM_lineNum ); }
228 ;
229
230id_list
231 : ID { $$ = new_id_list( $1, EM_lineNum ); }
232 | ID COMMA id_list { $$ = prepend_id_list( $1, $3, EM_lineNum ); }
233 ;
234
235id_dot
236 : ID { $$ = new_id_list( $1, EM_lineNum ); }
237 | ID DOT id_dot { $$ = prepend_id_list( $1, $3, EM_lineNum ); }
238 ;
239
240function_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
251class_decl
252 : PUBLIC { $$ = ae_key_public; }
253 | PRIVATE { $$ = ae_key_private; }
254 | { $$ = ae_key_private; }
255 ;
256
257function_decl
258 : FUNCTION { $$ = ae_key_func; }
259 | PUBLIC { $$ = ae_key_public; }
260 | PROTECTED { $$ = ae_key_protected; }
261 | PRIVATE { $$ = ae_key_private; }
262 ;
263
264static_decl
265 : STATIC { $$ = ae_key_static; }
266 | ABSTRACT { $$ = ae_key_abstract; }
267 | { $$ = ae_key_instance; }
268 ;
269
270type_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
275type_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
285type_decl
286 : type_decl_a { $$ = $1; }
287 | type_decl_b { $$ = $1; }
288 // | type_decl_c { $$ = $1; }
289 ;
290
291type_decl2
292 : type_decl { $$ = $1; }
293 | type_decl array_empty { $$ = add_type_decl_array( $1, $2, EM_lineNum ); }
294 ;
295
296arg_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
301statement_list
302 : statement { $$ = new_stmt_list( $1, EM_lineNum ); }
303 | statement statement_list { $$ = prepend_stmt_list( $1, $2, EM_lineNum ); }
304 ;
305
306statement
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
315jump_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
322selection_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
329loop_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
346code_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
351expression_statement
352 : SEMICOLON { $$ = NULL; }
353 | expression SEMICOLON { $$ = new_stmt_from_expression( $1, EM_lineNum ); }
354 ;
355
356expression
357 : chuck_expression { $$ = $1; }
358 | chuck_expression COMMA expression { $$ = prepend_expression( $1, $3, EM_lineNum ); }
359 ;
360
361chuck_expression
362 : arrow_expression { $$ = $1; }
363 | chuck_expression chuck_operator arrow_expression
364 { $$ = new_exp_from_binary( $1, $2, $3, EM_lineNum ); }
365 ;
366
367arrow_expression
368 : decl_expression { $$ = $1; }
369 | arrow_expression arrow_operator decl_expression
370 { $$ = new_exp_from_binary( $1, $2, $3, EM_lineNum ); }
371 ;
372
373array_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
379array_empty
380 : LBRACK RBRACK { $$ = new_array_sub( NULL, EM_lineNum ); }
381 | array_empty LBRACK RBRACK { $$ = prepend_array_sub( $1, NULL, EM_lineNum ); }
382 ;
383
384decl_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
392var_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
397var_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
403complex_exp
404 : POUNDPAREN expression RPAREN
405 { $$ = new_complex( $2, EM_lineNum ); }
406 ;
407
408polar_exp
409 : PERCENTPAREN expression RPAREN
410 { $$ = new_polar( $2, EM_lineNum ); }
411 ;
412
413vec_exp // ge: added 1.3.5.3
414 : ATPAREN expression RPAREN
415 { $$ = new_vec( $2, EM_lineNum ); }
416 ;
417
418chuck_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
435arrow_operator
436 : ARROW_LEFT { $$ = ae_op_arrow_left; }
437 | ARROW_RIGHT { $$ = ae_op_arrow_right; }
438 ;
439
440conditional_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
446logical_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
452logical_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
458inclusive_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
464exclusive_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
470and_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
476equality_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
484relational_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
496shift_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
504additive_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
512multiplicative_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
522tilda_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
528cast_expression
529 : unary_expression { $$ = $1; }
530 | cast_expression DOLLAR type_decl
531 { $$ = new_exp_from_cast( $3, $1, EM_lineNum ); }
532 ;
533
534unary_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
554unary_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
564dur_expression
565 : postfix_expression
566 | dur_expression COLONCOLON postfix_expression
567 { $$ = new_exp_from_dur( $1, $3, EM_lineNum ); }
568 ;
569
570postfix_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
587primary_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
38a_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
47a_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
56a_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
66a_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
76a_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
86a_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
96a_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
105a_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
115a_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
127a_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
141a_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
155a_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
169a_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
183a_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
197a_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
212a_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
225a_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
237a_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
248a_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
259a_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
271a_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
283a_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
295a_Exp prepend_expression( a_Exp exp, a_Exp list, int pos )
296{
297 exp->next = list;
298 return exp;
299}
300
301a_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
316a_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
330a_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
346a_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
360a_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
374a_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
388a_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
402a_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
416a_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
430a_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
444a_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
458a_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
472a_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
486a_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
500a_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
514a_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
528a_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
544a_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
552a_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
567a_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
581a_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
596a_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
611a_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
626a_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
639a_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
649a_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
659a_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
667a_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
678a_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
686a_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
698a_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
708a_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
726a_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
739a_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
748a_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
757a_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
766a_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
776a_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
786a_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
795void clean_exp( a_Exp exp )
796{
797 if( !exp ) return;
798 clean_exp( exp->next );
799 free( exp );
800}
801
802a_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
834a_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
866error:
867 clean_exp( exp );
868 return a;
869}
870
871a_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
881a_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
891a_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
905void 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
921static 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
965const 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)
38extern "C" {
39#endif
40
41// pos
42typedef int a_Pos;
43
44// enum oper
45typedef 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
59const char * op2str( ae_Operator op );
60
61// enum key words
62typedef 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//-----------------------------------------------------------------------------
73typedef struct a_Program_ * a_Program;
74typedef struct a_Section_ * a_Section;
75typedef struct a_Stmt_List_ * a_Stmt_List;
76typedef struct a_Class_Def_ * a_Class_Def;
77typedef struct a_Func_Def_ * a_Func_Def;
78typedef struct a_Code_Segment_ * a_Code_Segment;
79typedef struct a_Stmt_ * a_Stmt;
80typedef struct a_Exp_ * a_Exp;
81typedef struct a_Exp_Chuck_ * a_Exp_Chuck;
82typedef struct a_Exp_Binary_ * a_Exp_Binary;
83typedef struct a_Exp_Cast_ * a_Exp_Cast;
84typedef struct a_Exp_Unary_ * a_Exp_Unary;
85typedef struct a_Exp_Postfix_ * a_Exp_Postfix;
86typedef struct a_Exp_Primary_ * a_Exp_Primary;
87typedef struct a_Exp_Dur_ * a_Exp_Dur;
88typedef struct a_Exp_Array_ * a_Exp_Array;
89typedef struct a_Exp_Func_Call_ * a_Exp_Func_Call;
90typedef struct a_Exp_Dot_Member_ * a_Exp_Dot_Member;
91typedef struct a_Exp_If_ * a_Exp_If;
92typedef struct a_Exp_Decl_ * a_Exp_Decl;
93typedef struct a_Exp_Hack_ * a_Exp_Hack;
94typedef struct a_Stmt_Code_ * a_Stmt_Code;
95typedef struct a_Stmt_If_ * a_Stmt_If;
96typedef struct a_Stmt_While_ * a_Stmt_While;
97typedef struct a_Stmt_Until_ * a_Stmt_Until;
98typedef struct a_Stmt_For_ * a_Stmt_For;
99typedef struct a_Stmt_Loop_ * a_Stmt_Loop;
100typedef struct a_Stmt_Switch_ * a_Stmt_Switch;
101typedef struct a_Stmt_Break_ * a_Stmt_Break;
102typedef struct a_Stmt_Continue_ * a_Stmt_Continue;
103typedef struct a_Stmt_Return_ * a_Stmt_Return;
104typedef struct a_Stmt_Case_ * a_Stmt_Case;
105typedef struct a_Stmt_GotoLabel_ * a_Stmt_GotoLabel;
106typedef struct a_Decl_ * a_Decl;
107typedef struct a_Var_Decl_ * a_Var_Decl;
108typedef struct a_Var_Decl_List_ * a_Var_Decl_List;
109typedef struct a_Type_Decl_ * a_Type_Decl;
110typedef struct a_Arg_List_ * a_Arg_List;
111typedef struct a_Id_List_ * a_Id_List;
112typedef struct a_Class_Ext_ * a_Class_Ext;
113typedef struct a_Class_Body_ * a_Class_Body;
114typedef struct a_Array_Sub_ * a_Array_Sub;
115typedef struct a_Complex_ * a_Complex;
116typedef struct a_Polar_ * a_Polar;
117typedef struct a_Vec_ * a_Vec; // ge: added 1.3.5.3
118
119// forward reference for type
120typedef struct Chuck_Type * t_CKTYPE;
121typedef struct Chuck_Value * t_CKVALUE;
122typedef struct Chuck_Func * t_CKFUNC;
123typedef struct Chuck_Namespace * t_CKNSPC;
124typedef struct Chuck_VM_Code * t_CKVMCODE;
125
126
127
128
129//------------------------------------------------------------------------------
130// functions
131//------------------------------------------------------------------------------
132a_Program new_program( a_Section section, int pos );
133a_Program prepend_program( a_Section section, a_Program program, int pos );
134a_Section new_section_stmt( a_Stmt_List stmt_list, int pos );
135a_Section new_section_func_def( a_Func_Def func_def, int pos );
136a_Section new_section_class_def( a_Class_Def class_def, int pos );
137a_Stmt_List new_stmt_list( a_Stmt stmt, int pos );
138a_Stmt_List prepend_stmt_list( a_Stmt stmt, a_Stmt_List stmt_list, int pos );
139a_Stmt new_stmt_from_expression( a_Exp exp, int pos );
140a_Stmt new_stmt_from_code( a_Stmt_List code, int pos );
141a_Stmt new_stmt_from_while( a_Exp cond, a_Stmt body, int pos );
142a_Stmt new_stmt_from_do_while( a_Exp cond, a_Stmt body, int pos );
143a_Stmt new_stmt_from_until( a_Exp cond, a_Stmt body, int pos );
144a_Stmt new_stmt_from_do_until( a_Exp cond, a_Stmt body, int pos );
145a_Stmt new_stmt_from_for( a_Stmt c1, a_Stmt c2, a_Exp c3, a_Stmt body, int pos );
146a_Stmt new_stmt_from_loop( a_Exp cond, a_Stmt body, int pos );
147a_Stmt new_stmt_from_if( a_Exp cond, a_Stmt if_body, a_Stmt else_body, int pos );
148a_Stmt new_stmt_from_switch( a_Exp exp, int pos );
149a_Stmt new_stmt_from_break( int pos );
150a_Stmt new_stmt_from_continue( int pos );
151a_Stmt new_stmt_from_return( a_Exp exp, int pos );
152a_Stmt new_stmt_from_label( c_str xid, int pos );
153a_Stmt new_stmt_from_case( a_Exp exp, int pos );
154a_Exp prepend_expression( a_Exp exp, a_Exp list, int pos );
155a_Exp new_exp_from_binary( a_Exp lhs, ae_Operator oper, a_Exp rhs, int pos );
156a_Exp new_exp_from_unary( ae_Operator oper, a_Exp exp, int pos );
157a_Exp new_exp_from_unary2( ae_Operator oper, a_Type_Decl type, a_Array_Sub array, int pos );
158a_Exp new_exp_from_unary3( ae_Operator oper, a_Stmt code, int pos );
159a_Exp new_exp_from_cast( a_Type_Decl type, a_Exp exp, int pos );
160a_Exp new_exp_from_array( a_Exp base, a_Array_Sub indices, int pos );
161a_Exp new_exp_from_array_lit( a_Array_Sub exp_list, int pos );
162a_Exp new_exp_from_func_call( a_Exp base, a_Exp args, int pos );
163a_Exp new_exp_from_member_dot( a_Exp base, c_str member, int pos );
164a_Exp new_exp_from_postfix( a_Exp base, ae_Operator op, int pos );
165a_Exp new_exp_from_dur( a_Exp base, a_Exp unit, int pos );
166a_Exp new_exp_from_id( c_str xid, int pos );
167a_Exp new_exp_from_int( long num, int pos );
168a_Exp new_exp_from_uint( unsigned long num, int pos );
169a_Exp new_exp_from_float( double num, int pos );
170a_Exp new_exp_from_str( c_str str, int pos );
171a_Exp new_exp_from_char( c_str chr, int pos );
172a_Exp new_exp_from_if( a_Exp cond, a_Exp lhs, a_Exp rhs, int pos );
173a_Exp new_exp_from_complex( a_Complex, int pos );
174a_Exp new_exp_from_polar( a_Polar, int pos );
175a_Exp new_exp_from_vec( a_Vec, int pos ); // ge: added 1.3.5.3
176a_Exp new_exp_decl_external( a_Type_Decl type_decl, a_Var_Decl_List var_decl_list, int is_static, int pos );
177a_Exp new_exp_decl( a_Type_Decl type_decl, a_Var_Decl_List var_decl_list, int is_static, int pos );
178a_Exp new_exp_from_hack( a_Exp exp, int pos );
179a_Exp new_exp_from_nil( int pos );
180a_Var_Decl_List new_var_decl_list( a_Var_Decl var_decl, int pos );
181a_Var_Decl_List prepend_var_decl_list( a_Var_Decl var_decl, a_Var_Decl_List list, int pos );
182a_Var_Decl new_var_decl( c_constr xid, a_Array_Sub array, int pos );
183a_Type_Decl new_type_decl( a_Id_List xid, int ref, int pos );
184a_Type_Decl add_type_decl_array( a_Type_Decl type_decl, a_Array_Sub array, int pos );
185a_Arg_List new_arg_list( a_Type_Decl type_decl, a_Var_Decl var_decl, int pos );
186a_Arg_List prepend_arg_list( a_Type_Decl type_decl, a_Var_Decl var_decl, a_Arg_List arg_list, int pos );
187a_Array_Sub new_array_sub( a_Exp exp, int pos );
188a_Array_Sub prepend_array_sub( a_Array_Sub array, a_Exp exp, int pos );
189a_Complex new_complex( a_Exp re, int pos );
190a_Polar new_polar( a_Exp mod, int pos ); // ge: added 1.3.5.3
191a_Vec new_vec( a_Exp e, int pos );
192
193a_Class_Def new_class_def( ae_Keyword class_decl, a_Id_List xid, a_Class_Ext ext, a_Class_Body body, int pos );
194a_Class_Body new_class_body( a_Section section, int pos );
195a_Class_Body prepend_class_body( a_Section section, a_Class_Body body, int pos );
196a_Class_Ext new_class_ext( a_Id_List extend_id, a_Id_List impl_list, int pos );
197a_Class_Def new_iface_def( ae_Keyword class_decl, a_Id_List xid, a_Class_Ext ext, a_Class_Body body, int pos );
198a_Id_List new_id_list( c_constr xid, int pos );
199a_Id_List prepend_id_list( c_constr xid, a_Id_List list, int pos );
200void clean_exp( a_Exp exp );
201a_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
205void delete_id_list( a_Id_List x );
206
207
208
209
210//------------------------------------------------------------------------------
211// structs
212//------------------------------------------------------------------------------
213struct a_Exp_Binary_ { a_Exp lhs; ae_Operator op; a_Exp rhs; t_CKFUNC ck_func; int linepos; a_Exp self; };
214struct a_Exp_Cast_ { a_Type_Decl type; a_Exp exp; int linepos; a_Exp self; };
215struct 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; };
217struct a_Exp_Postfix_ { a_Exp exp; ae_Operator op; int linepos; a_Exp self; };
218struct a_Exp_Dur_ { a_Exp base; a_Exp unit; int linepos; a_Exp self; };
219struct a_Exp_Array_ { a_Exp base; a_Array_Sub indices; int linepos; a_Exp self; };
220struct 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; };
222struct a_Exp_Dot_Member_ { a_Exp base; t_CKTYPE t_base; S_Symbol xid; int linepos; a_Exp self; };
223struct a_Exp_If_ { a_Exp cond; a_Exp if_exp; a_Exp else_exp; int linepos; a_Exp self; };
224struct 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; };
226struct a_Exp_Hack_ { a_Exp exp; int linepos; a_Exp self; };
227struct a_Var_Decl_List_ { a_Var_Decl var_decl; a_Var_Decl_List next; int linepos; a_Exp self; };
228struct 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; };
230struct a_Type_Decl_ { a_Id_List xid; a_Array_Sub array; int ref; int linepos; /*a_Exp self;*/ };
231struct a_Array_Sub_ { t_CKUINT depth; a_Exp exp_list; int linepos; a_Exp self;
232 int err_num; int err_pos; };
233struct 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; };
235struct a_Complex_ { a_Exp re; a_Exp im; int linepos; a_Exp self; };
236struct a_Polar_ { a_Exp mod; a_Exp phase; int linepos; a_Exp self; };
237struct a_Vec_ { a_Exp args; int numdims; int linepos; a_Exp self; }; // ge: added 1.3.5.3
238
239// enum primary exp type
240typedef 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
246struct 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
270typedef 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
275typedef enum { ae_meta_value = 0, ae_meta_var } ae_Exp_Meta;
276
277struct 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
307struct a_Stmt_While_ { int is_do; a_Exp cond; a_Stmt body; int linepos; a_Stmt self; };
308struct a_Stmt_Until_ { int is_do; a_Exp cond; a_Stmt body; int linepos; a_Stmt self; };
309struct a_Stmt_For_ { a_Stmt c1; a_Stmt c2; a_Exp c3; a_Stmt body; int linepos; a_Stmt self; };
310struct a_Stmt_Loop_ { a_Exp cond; a_Stmt body; int linepos; a_Stmt self; };
311struct a_Stmt_Code_ { a_Stmt_List stmt_list; int linepos; a_Stmt self; };
312struct a_Stmt_If_ { a_Exp cond; a_Stmt if_body; a_Stmt else_body; int linepos; a_Stmt self; };
313struct a_Stmt_Switch_ { a_Exp val; int linepos; a_Stmt self; };
314struct a_Stmt_Break_ { int linepos; a_Stmt self; };
315struct a_Stmt_Continue_ { int linepos; a_Stmt self; };
316struct a_Stmt_Return_ { a_Exp val; int linepos; a_Stmt self; };
317struct a_Stmt_Case_ { a_Exp exp; int linepos; a_Stmt self; };
318struct a_Stmt_GotoLabel_ { S_Symbol name; int linepos; a_Stmt self; };
319
320// enum values for stmt type
321typedef 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
326struct 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
351struct a_Stmt_List_ { a_Stmt stmt; a_Stmt_List next; int linepos; };
352struct 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; };
355struct a_Class_Ext_ { a_Id_List extend_id; a_Id_List impl_list; int linepos; };
356struct a_Class_Body_ { a_Section section; a_Class_Body next; int linepos; };
357struct a_Id_List_ { S_Symbol xid; a_Id_List next; int linepos; };
358
359typedef 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; };
363struct 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
380typedef enum { ae_section_stmt, ae_section_func, ae_section_class
381 } ae_Section_Type;
382
383struct 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
397struct 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
37#ifndef __CHUCK_CARRIER_H__37#ifndef __CHUCK_CARRIER_H__
38#define __CHUCK_CARRIER_H__38#define __CHUCK_CARRIER_H__
39 39
40#include "chuck_def.h"
40 41
41 42
42 43
43// forward references44
45// forward references (C++)
44class Chuck_Compiler;46class Chuck_Compiler;
45class Chuck_VM;47class Chuck_VM;
46class Chuck_Env;48class Chuck_Env;
47class Chuck_IO_Chout;49class Chuck_IO_Chout;
48class Chuck_IO_Cherr;50class Chuck_IO_Cherr;
49 51
52// forward references ("C")
53struct ck_socket;
54
50 55
51 56
52 57
@@ -62,14 +67,20 @@ struct Chuck_Carrier · 9 unmodified lines
62 Chuck_IO_Chout * chout;67 Chuck_IO_Chout * chout;
63 Chuck_IO_Cherr * cherr;68 Chuck_IO_Cherr * cherr;
64 69
70 // OTF programming things
71 ck_socket otf_socket;
72 t_CKINT otf_port;
73
65 // constructor74 // constructor
66 Chuck_Carrier() :75 Chuck_Carrier() :
67 compiler( NULL ),76 compiler( NULL ),
68 env( NULL ),77 env( NULL ),
69 vm( NULL ),78 vm( NULL ),
70 chout( NULL ),79 chout( NULL ),
71 cherr( NULL )80 cherr( NULL ),
72 { }81 otf_socket( NULL ),
82 otf_port( 0 )
83 { }
73};84};
74 85
75 86
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
57using namespace std;
58
59
60
61
62// function prototypes
63t_CKBOOL load_internal_modules( Chuck_Compiler * compiler );
64t_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);
68t_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//-----------------------------------------------------------------------------
77Chuck_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//-----------------------------------------------------------------------------
93Chuck_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//-----------------------------------------------------------------------------
106t_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
139error:
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//-----------------------------------------------------------------------------
156void 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//-----------------------------------------------------------------------------
192t_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
225error:
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//-----------------------------------------------------------------------------
246void 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//-----------------------------------------------------------------------------
261t_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
304cleanup:
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//-----------------------------------------------------------------------------
329t_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//-----------------------------------------------------------------------------
351t_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//-----------------------------------------------------------------------------
386t_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//-----------------------------------------------------------------------------
421t_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//-----------------------------------------------------------------------------
454t_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
497cleanup:
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//-----------------------------------------------------------------------------
521Chuck_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//-----------------------------------------------------------------------------
533Chuck_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//-----------------------------------------------------------------------------
545t_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//-----------------------------------------------------------------------------
558Chuck_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//-----------------------------------------------------------------------------
570t_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//-----------------------------------------------------------------------------
601t_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
668error:
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//-----------------------------------------------------------------------------
688t_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//-----------------------------------------------------------------------------
723static 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//-----------------------------------------------------------------------------
739t_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//-----------------------------------------------------------------------------
835t_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 /*
886error:
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
45struct Chuck_DLL;
46
47
48
49
50//-----------------------------------------------------------------------------
51// name: struct Chuck_Compiler
52// desc: the sum of the components in compilation
53//-----------------------------------------------------------------------------
54struct Chuck_Compiler
55{
56protected: // data
57 // carrier
58 Chuck_Carrier * m_carrier;
59
60public: // 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
71public: // 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
85public: // 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
97public: // 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
102public: // 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
113protected: // 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
133extern "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
59typedef struct { t_CKFLOAT re ; t_CKFLOAT im ; } t_CKCOMPLEX;
60// polar type
61typedef struct { t_CKFLOAT modulus ; t_CKFLOAT phase ; } t_CKPOLAR;
62
63// vector types
64typedef struct { t_CKFLOAT x ; t_CKFLOAT y ; t_CKFLOAT z ; } t_CKVEC3;
65typedef struct { t_CKFLOAT x ; t_CKFLOAT y ; t_CKFLOAT z ; t_CKFLOAT w ; } t_CKVEC4;
66typedef 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
96typedef char * c_str;
97typedef 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
117typedef 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>
46using namespace std;
47
48
49
50
51#if defined(__MACOSX_CORE__)
52char g_default_chugin_path[] = "/usr/local/lib/chuck:/Library/Application Support/ChucK/ChuGins:~/Library/Application Support/ChucK/ChuGins";
53#elif defined(__PLATFORM_WIN32__)
54char g_default_chugin_path[] = "C:\\WINDOWS\\system32\\ChucK;C:\\Program Files\\ChucK\\chugins;C:\\Program Files (x86)\\ChucK\\chugins";
55#else // Linux/Cygwin
56char g_default_chugin_path[] = "/usr/local/lib/chuck";
57#endif
58
59char g_chugin_path_envvar[] = "CHUCK_CHUGIN_PATH";
60
61
62
63
64//-----------------------------------------------------------------------------
65// internal implementation of query functions
66//-----------------------------------------------------------------------------
67
68
69
70t_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//-----------------------------------------------------------------------------
78void 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//-----------------------------------------------------------------------------
91void 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//-----------------------------------------------------------------------------
151void 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//-----------------------------------------------------------------------------
179void 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//-----------------------------------------------------------------------------
216void 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//-----------------------------------------------------------------------------
245void 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//-----------------------------------------------------------------------------
274t_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//-----------------------------------------------------------------------------
331void 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//-----------------------------------------------------------------------------
363void 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//-----------------------------------------------------------------------------
397void 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//-----------------------------------------------------------------------------
438void 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//-----------------------------------------------------------------------------
479void 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//-----------------------------------------------------------------------------
495void 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//-----------------------------------------------------------------------------
524t_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//-----------------------------------------------------------------------------
566Chuck_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//-----------------------------------------------------------------------------
581t_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//-----------------------------------------------------------------------------
597t_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
610t_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
623t_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//------------------------------------------------------------------------------
640Chuck_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 ); }
642Chuck_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 ); }
644Chuck_DL_Value * make_new_arg( const char * t, const char * n )
645{ return new Chuck_DL_Value( t, n ); }
646Chuck_DL_Value * make_new_mvar( const char * t, const char * n, t_CKBOOL c )
647{ return new Chuck_DL_Value( t, n, c ); }
648Chuck_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//-----------------------------------------------------------------------------
658t_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//-----------------------------------------------------------------------------
689t_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//-----------------------------------------------------------------------------
710t_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//-----------------------------------------------------------------------------
722const 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//-----------------------------------------------------------------------------
867t_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//-----------------------------------------------------------------------------
895void * 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//-----------------------------------------------------------------------------
913const 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//-----------------------------------------------------------------------------
925const 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//-----------------------------------------------------------------------------
937Chuck_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//-----------------------------------------------------------------------------
983void 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//-----------------------------------------------------------------------------
1002Chuck_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//-----------------------------------------------------------------------------
1025Chuck_DL_Func::~Chuck_DL_Func()
1026{
1027 for( t_CKUINT i = 0; i < args.size(); i++ )
1028 delete args[i];
1029}
1030
1031
1032
1033t_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
1045t_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//-----------------------------------------------------------------------------
1059Chuck_DL_MainThreadHook::Chuck_DL_MainThreadHook(f_mainthreadhook hook, f_mainthreadquit quit,
1060 void * bindle, Chuck_VM * vm) :
1061m_hook(hook),
1062m_quit(quit),
1063m_vm(vm),
1064m_bindle(bindle),
1065activate(ck_mthook_activate),
1066deactivate(ck_mthook_deactivate),
1067m_active(FALSE)
1068{ }
1069
1070
1071
1072/*******************************************************************************
1073
1074 Chuck_DL_Api stuff
1075
1076*******************************************************************************/
1077
1078namespace Chuck_DL_Api
1079{
1080 Api Api::g_api;
1081}
1082
1083
1084static t_CKUINT ck_get_srate(CK_DL_API api, Chuck_VM_Shred * shred)
1085{
1086 return shred->vm_ref->srate();
1087}
1088
1089static 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
1101static 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
1111static 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
1120static t_CKBOOL ck_get_mvar_int( CK_DL_API api, Chuck_DL_Api::Object, std::string &, t_CKINT & )
1121{
1122 return TRUE;
1123}
1124
1125static t_CKBOOL ck_get_mvar_float( CK_DL_API api, Chuck_DL_Api::Object, std::string &, t_CKFLOAT & )
1126{
1127 return TRUE;
1128}
1129
1130static t_CKBOOL ck_get_mvar_dur( CK_DL_API api, Chuck_DL_Api::Object, std::string &, t_CKDUR & )
1131{
1132 return TRUE;
1133}
1134
1135static t_CKBOOL ck_get_mvar_time( CK_DL_API api, Chuck_DL_Api::Object, std::string &, t_CKTIME & )
1136{
1137 return TRUE;
1138}
1139
1140static 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
1145static 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
1150static 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
1161Chuck_DL_Api::Api::VMApi::VMApi() :
1162get_srate(ck_get_srate)
1163{ }
1164
1165
1166Chuck_DL_Api::Api::ObjectApi::ObjectApi() :
1167get_type(ck_get_type),
1168create(ck_create),
1169create_string(ck_create_string),
1170get_mvar_int(ck_get_mvar_int),
1171get_mvar_float(ck_get_mvar_float),
1172get_mvar_dur(ck_get_mvar_dur),
1173get_mvar_time(ck_get_mvar_time),
1174get_mvar_string(ck_get_mvar_string),
1175get_mvar_object(ck_get_mvar_object),
1176set_string(ck_set_string)
1177{ }
1178
1179
1180// windows
1181#if defined(__WINDOWS_DS__)
1182extern "C"
1183{
1184#include <windows.h>
1185
1186void *dlopen( const char *path, int mode )
1187{
1188 return (void *)LoadLibrary(path);
1189}
1190
1191int dlclose( void *handle )
1192{
1193 FreeLibrary((HMODULE)handle);
1194 return 1;
1195}
1196
1197void *dlsym( void * handle, const char *symbol )
1198{
1199 return (void *)GetProcAddress((HMODULE)handle, symbol);
1200}
1201
1202const 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
60extern char g_default_chugin_path[];
61extern char g_chugin_path_envvar[];
62
63
64
65// forward references
66struct Chuck_DL_Query;
67struct Chuck_DL_Class;
68struct Chuck_DL_Func;
69struct Chuck_DL_Value;
70struct Chuck_DL_Ctrl;
71union Chuck_DL_Return;
72struct Chuck_DLL;
73struct Chuck_UGen;
74struct Chuck_UAna;
75struct Chuck_UAnaBlobProxy;
76struct Chuck_DL_MainThreadHook;
77namespace 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
168typedef 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//-----------------------------------------------------------------------------
240extern "C" {
241// query
242typedef t_CKUINT (CK_DLL_CALL * f_ck_declversion)();
243typedef t_CKBOOL (CK_DLL_CALL * f_ck_query)( Chuck_DL_Query * QUERY );
244// object
245typedef Chuck_Object * (CK_DLL_CALL * f_alloc)( Chuck_VM_Shred * SHRED, CK_DL_API API );
246typedef t_CKVOID (CK_DLL_CALL * f_ctor)( Chuck_Object * SELF, void * ARGS, Chuck_VM_Shred * SHRED, CK_DL_API API );
247typedef t_CKVOID (CK_DLL_CALL * f_dtor)( Chuck_Object * SELF, Chuck_VM_Shred * SHRED, CK_DL_API API );
248typedef t_CKVOID (CK_DLL_CALL * f_mfun)( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED, CK_DL_API API );
249typedef t_CKVOID (CK_DLL_CALL * f_sfun)( void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED, CK_DL_API API );
250// ugen specific
251typedef t_CKBOOL (CK_DLL_CALL * f_tick)( Chuck_Object * SELF, SAMPLE in, SAMPLE * out, Chuck_VM_Shred * SHRED, CK_DL_API API );
252typedef 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 );
253typedef t_CKVOID (CK_DLL_CALL * f_ctrl)( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED, CK_DL_API API );
254typedef t_CKVOID (CK_DLL_CALL * f_cget)( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED, CK_DL_API API );
255typedef 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
257typedef 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
259typedef t_CKBOOL (CK_DLL_CALL * f_mainthreadhook)( void * bindle );
260// "main thread" quit (stop running hook)
261typedef 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//-----------------------------------------------------------------------------
276extern "C" {
277// set name of ckx
278typedef void ( CK_DLL_CALL * f_setname)( Chuck_DL_Query * query, const char * name );
279
280// begin class/namespace, can be nested
281typedef 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
283typedef void (CK_DLL_CALL * f_add_ctor)( Chuck_DL_Query * query, f_ctor ctor );
284// add destructor - cannot have args
285typedef void (CK_DLL_CALL * f_add_dtor)( Chuck_DL_Query * query, f_dtor dtor );
286// add member function - args to follow
287typedef 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
289typedef void (CK_DLL_CALL * f_add_sfun)( Chuck_DL_Query * query, f_sfun sfun, const char * type, const char * name );
290// add member variable
291typedef 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
294typedef 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
298typedef 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
300typedef 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 );
301typedef 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 );
302typedef 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
304typedef 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
307typedef t_CKBOOL (CK_DLL_CALL * f_end_class)( Chuck_DL_Query * query );
308// register
309typedef 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
313typedef t_CKBOOL (CK_DLL_CALL * f_doc_class)( Chuck_DL_Query * query, const char * doc );
314// add example of current class
315typedef t_CKBOOL (CK_DLL_CALL * f_add_example)( Chuck_DL_Query * query, const char * ex );
316// set current function documentation
317typedef t_CKBOOL (CK_DLL_CALL * f_doc_func)( Chuck_DL_Query * query, const char * doc );
318// set last mvar documentation
319typedef 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//-----------------------------------------------------------------------------
327struct Chuck_DL_Query
328{
329protected:
330 // REFACTOR-2017: carrier ref
331 Chuck_Carrier * m_carrier;
332
333public:
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
339public:
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//-----------------------------------------------------------------------------
427struct 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//-----------------------------------------------------------------------------
478struct 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//-----------------------------------------------------------------------------
504struct 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//-----------------------------------------------------------------------------
535struct 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//------------------------------------------------------------------------------
555Chuck_DL_Func * make_new_mfun( const char * t, const char * n, f_mfun mfun );
556Chuck_DL_Func * make_new_sfun( const char * t, const char * n, f_sfun sfun );
557Chuck_DL_Value * make_new_arg( const char * t, const char * n );
558Chuck_DL_Value * make_new_mvar( const char * t, const char * n, t_CKBOOL c = FALSE );
559Chuck_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//------------------------------------------------------------------------------
568union 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//-----------------------------------------------------------------------------
592struct Chuck_DLL : public Chuck_VM_Object
593{
594public:
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
613public:
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
623protected:
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
637struct Chuck_DL_MainThreadHook
638{
639public:
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 */
656namespace Chuck_DL_Api
657{
658typedef void * Object;
659typedef void * Type;
660typedef void * String;
661
662struct Api
663{
664public:
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
701private:
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
40using namespace std;
41
42
43
44
45//-----------------------------------------------------------------------------
46// function prototypes
47//-----------------------------------------------------------------------------
48t_CKBOOL emit_engine_emit_stmt_list( Chuck_Emitter * emit, a_Stmt_List list );
49t_CKBOOL emit_engine_emit_stmt( Chuck_Emitter * emit, a_Stmt stmt, t_CKBOOL pop = TRUE );
50t_CKBOOL emit_engine_emit_if( Chuck_Emitter * emit, a_Stmt_If stmt );
51t_CKBOOL emit_engine_emit_for( Chuck_Emitter * emit, a_Stmt_For stmt );
52t_CKBOOL emit_engine_emit_while( Chuck_Emitter * emit, a_Stmt_While stmt );
53t_CKBOOL emit_engine_emit_do_while( Chuck_Emitter * emit, a_Stmt_While stmt );
54t_CKBOOL emit_engine_emit_until( Chuck_Emitter * emit, a_Stmt_Until stmt );
55t_CKBOOL emit_engine_emit_do_until( Chuck_Emitter * emit, a_Stmt_Until stmt );
56t_CKBOOL emit_engine_emit_loop( Chuck_Emitter * emit, a_Stmt_Loop stmt );
57t_CKBOOL emit_engine_emit_break( Chuck_Emitter * emit, a_Stmt_Break br );
58t_CKBOOL emit_engine_emit_continue( Chuck_Emitter * emit, a_Stmt_Continue cont );
59t_CKBOOL emit_engine_emit_return( Chuck_Emitter * emit, a_Stmt_Return stmt );
60t_CKBOOL emit_engine_emit_switch( Chuck_Emitter * emit, a_Stmt_Switch stmt );
61t_CKBOOL emit_engine_emit_exp( Chuck_Emitter * emit, a_Exp exp, t_CKBOOL doAddRef = FALSE );
62t_CKBOOL emit_engine_emit_exp_binary( Chuck_Emitter * emit, a_Exp_Binary binary );
63t_CKBOOL emit_engine_emit_op( Chuck_Emitter * emit, ae_Operator op, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary );
64t_CKBOOL emit_engine_emit_op_chuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary );
65t_CKBOOL emit_engine_emit_op_unchuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs );
66t_CKBOOL emit_engine_emit_op_upchuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs );
67t_CKBOOL emit_engine_emit_op_at_chuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs );
68t_CKBOOL emit_engine_emit_exp_unary( Chuck_Emitter * emit, a_Exp_Unary unary );
69t_CKBOOL emit_engine_emit_exp_primary( Chuck_Emitter * emit, a_Exp_Primary exp );
70t_CKBOOL emit_engine_emit_exp_cast( Chuck_Emitter * emit, a_Exp_Cast cast );
71t_CKBOOL emit_engine_emit_exp_postfix( Chuck_Emitter * emit, a_Exp_Postfix postfix );
72t_CKBOOL emit_engine_emit_exp_dur( Chuck_Emitter * emit, a_Exp_Dur dur );
73t_CKBOOL emit_engine_emit_exp_array( Chuck_Emitter * emit, a_Exp_Array array );
74t_CKBOOL emit_engine_emit_exp_func_call( Chuck_Emitter * emit, Chuck_Func * func,
75 Chuck_Type * type, int linepos, t_CKBOOL spork = FALSE );
76t_CKBOOL emit_engine_emit_exp_func_call( Chuck_Emitter * emit, a_Exp_Func_Call func_call,
77 t_CKBOOL spork = FALSE );
78t_CKBOOL emit_engine_emit_func_args( Chuck_Emitter * emit, a_Exp_Func_Call func_call );
79t_CKBOOL emit_engine_emit_exp_dot_member( Chuck_Emitter * emit, a_Exp_Dot_Member member );
80t_CKBOOL emit_engine_emit_exp_if( Chuck_Emitter * emit, a_Exp_If exp_if );
81t_CKBOOL emit_engine_emit_exp_decl( Chuck_Emitter * emit, a_Exp_Decl decl, t_CKBOOL first_exp );
82t_CKBOOL emit_engine_emit_array_lit( Chuck_Emitter * emit, a_Array_Sub array );
83t_CKBOOL emit_engine_emit_complex_lit( Chuck_Emitter * emit, a_Complex val );
84t_CKBOOL emit_engine_emit_polar_lit( Chuck_Emitter * emit, a_Polar val );
85t_CKBOOL emit_engine_emit_vec_lit( Chuck_Emitter * emit, a_Vec val );
86t_CKBOOL emit_engine_emit_code_segment( Chuck_Emitter * emit, a_Stmt_Code stmt,
87 t_CKBOOL push = TRUE );
88t_CKBOOL emit_engine_emit_func_def( Chuck_Emitter * emit, a_Func_Def func_def );
89t_CKBOOL emit_engine_emit_class_def( Chuck_Emitter * emit, a_Class_Def class_def );
90t_CKBOOL emit_engine_pre_constructor( Chuck_Emitter * emit, Chuck_Type * type );
91t_CKBOOL emit_engine_instantiate_object( Chuck_Emitter * emit, Chuck_Type * type,
92 a_Array_Sub array, t_CKBOOL is_ref );
93t_CKBOOL emit_engine_emit_spork( Chuck_Emitter * emit, a_Exp_Func_Call exp );
94t_CKBOOL emit_engine_emit_cast( Chuck_Emitter * emit, Chuck_Type * to, Chuck_Type * from );
95t_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//-----------------------------------------------------------------------------
107Chuck_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//-----------------------------------------------------------------------------
130t_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//-----------------------------------------------------------------------------
151Chuck_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//-----------------------------------------------------------------------------
261Chuck_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//-----------------------------------------------------------------------------
331t_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//-----------------------------------------------------------------------------
353t_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//-----------------------------------------------------------------------------
491t_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//-----------------------------------------------------------------------------
587t_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//-----------------------------------------------------------------------------
736t_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//-----------------------------------------------------------------------------
839t_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//-----------------------------------------------------------------------------
938t_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//-----------------------------------------------------------------------------
1039t_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//-----------------------------------------------------------------------------
1130t_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//-----------------------------------------------------------------------------
1237t_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//-----------------------------------------------------------------------------
1255t_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//-----------------------------------------------------------------------------
1273t_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//-----------------------------------------------------------------------------
1296t_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//-----------------------------------------------------------------------------
1308t_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//-----------------------------------------------------------------------------
1411t_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//-----------------------------------------------------------------------------
1514t_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//-----------------------------------------------------------------------------
2430t_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//-----------------------------------------------------------------------------
2553t_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//-----------------------------------------------------------------------------
2583t_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//-----------------------------------------------------------------------------
2615t_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//-----------------------------------------------------------------------------
2701t_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//-----------------------------------------------------------------------------
2845t_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//-----------------------------------------------------------------------------
3018t_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//-----------------------------------------------------------------------------
3049t_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//-----------------------------------------------------------------------------
3069t_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//-----------------------------------------------------------------------------
3089t_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//-----------------------------------------------------------------------------
3116t_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//-----------------------------------------------------------------------------
3136t_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//-----------------------------------------------------------------------------
3185t_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//-----------------------------------------------------------------------------
3235t_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//-----------------------------------------------------------------------------
3262t_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//-----------------------------------------------------------------------------
3367t_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//-----------------------------------------------------------------------------
3432t_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//-----------------------------------------------------------------------------
3453t_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//-----------------------------------------------------------------------------
3487t_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//-----------------------------------------------------------------------------
3593check_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//-----------------------------------------------------------------------------
3660t_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//-----------------------------------------------------------------------------
3831t_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//-----------------------------------------------------------------------------
3904t_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//-----------------------------------------------------------------------------
3930t_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//-----------------------------------------------------------------------------
3959t_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//-----------------------------------------------------------------------------
4000t_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//-----------------------------------------------------------------------------
4236t_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//-----------------------------------------------------------------------------
4264t_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//-----------------------------------------------------------------------------
4441t_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//-----------------------------------------------------------------------------
4575t_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//-----------------------------------------------------------------------------
4721t_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//-----------------------------------------------------------------------------
4810void 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//-----------------------------------------------------------------------------
4840void 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//-----------------------------------------------------------------------------
4878t_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//-----------------------------------------------------------------------------
4903t_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
43struct Chuck_Instr;
44struct Chuck_Instr_Goto;
45struct Chuck_VM_Code;
46struct Chuck_VM_Shred;
47
48
49
50
51//-----------------------------------------------------------------------------
52// name: struct Chuck_Code
53// desc: ...
54//-----------------------------------------------------------------------------
55struct Chuck_Code
56{
57public:
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//-----------------------------------------------------------------------------
98struct 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
157Chuck_Emitter * emit_engine_init( Chuck_Env * env );
158// shutdown and free the emitter
159t_CKBOOL emit_engine_shutdown( Chuck_Emitter *& emit );
160// emit a program into vm code
161Chuck_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
165Chuck_VM_Code * emit_to_code( Chuck_Code * in,
166 Chuck_VM_Code * out = NULL,
167 t_CKBOOL dump = FALSE );
168
169// NOT USED: ...
170t_CKBOOL emit_engine_addr_map( Chuck_Emitter * emit, Chuck_VM_Shred * shred );
171t_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
45int EM_tokPos = 0;
46int EM_lineNum = 1;
47int EM_extLineNum = 1;
48t_CKBOOL anyErrors= FALSE;
49
50// local global
51static const char * fileName = "";
52static int lineNum = 1;
53static char g_buffer[1024] = "";
54static const size_t LASTERROR_SIZE = 1024;
55static char g_lasterror[LASTERROR_SIZE] = "[chuck]: (no error)";
56static size_t g_lasterrorIndex = strlen(g_lasterror);
57// log globals
58int g_loglevel = CK_LOG_CORE;
59int g_logstack = 0;
60XMutex g_logmutex;
61
62// more local globals
63static const size_t g_buffer2_size = 1024;
64static char g_buffer2[g_buffer2_size] = "";
65std::stringstream g_stdout_stream;
66std::stringstream g_stderr_stream;
67
68// local global callbacks
69void (*g_stdout_callback)(const char *) = NULL;
70void (*g_stderr_callback)(const char *) = NULL;
71
72void 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
88void 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
104void 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
126void 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
149void 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
162void 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
176void 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
185void 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
194extern "C++" {
195
196ChuckOutStream::ChuckOutStream( bool isErr )
197{
198 m_callback = NULL;
199 m_isErr = isErr;
200}
201
202
203ChuckOutStream::~ChuckOutStream()
204{
205}
206
207
208ChuckOutStream& 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
219ChuckOutStream& ChuckOutStream::operator<<( const char * val )
220{
221 m_stream << val;
222 return *this;
223}
224
225
226ChuckOutStream& ChuckOutStream::operator<<( const double val )
227{
228 m_stream << val;
229 return *this;
230}
231
232
233ChuckOutStream& ChuckOutStream::operator<<( const float val )
234{
235 m_stream << val;
236 return *this;
237}
238
239
240ChuckOutStream& ChuckOutStream::operator<<( const unsigned long long val )
241{
242 m_stream << val;
243 return *this;
244}
245
246
247ChuckOutStream& ChuckOutStream::operator<<( const long long val )
248{
249 m_stream << val;
250 return *this;
251}
252
253
254ChuckOutStream& ChuckOutStream::operator<<( const unsigned long val )
255{
256 m_stream << val;
257 return *this;
258}
259
260
261ChuckOutStream& ChuckOutStream::operator<<( const long val )
262{
263 m_stream << val;
264 return *this;
265}
266
267
268ChuckOutStream& ChuckOutStream::operator<<( const unsigned int val )
269{
270 m_stream << val;
271 return *this;
272}
273
274
275ChuckOutStream& ChuckOutStream::operator<<( const int val )
276{
277 m_stream << val;
278 return *this;
279}
280
281
282ChuckOutStream& ChuckOutStream::operator<<( const bool val )
283{
284 m_stream << val;
285 return *this;
286}
287
288
289
290
291
292void ChuckOutStream::set_callback( void (*callback)( const char * ) )
293{
294 m_callback = callback;
295}
296
297
298void 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
326ChuckOutStream g_ck_stdoutstream( FALSE );
327ChuckOutStream g_ck_stderrstream( TRUE );
328
329}
330#endif
331
332
333
334
335// name
336static 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
352typedef struct intList {int i; struct intList *rest;} *IntList;
353static IntList linePos=NULL;
354
355
356static 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
372static 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
381void 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 '/'
391const 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'
401const 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
409void EM_reset_msg()
410{
411 g_lasterror[0] = '\0';
412 g_lasterrorIndex = 0;
413}
414
415// [%s]:line(%d).char(%d):
416void 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):
459void 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):
495void 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//
531void 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
556void 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
585void 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
596void EM_pushlog()
597{
598 g_logstack++;
599}
600
601// pop log
602void EM_poplog()
603{
604 g_logstack--;
605 if( g_logstack < 0 ) g_logstack = 0;
606}
607
608// prepare new file
609t_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
635void 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
647const 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)
42extern "C" {
43#endif
44
45
46extern t_CKBOOL EM_anyErrors;
47extern int EM_tokPos;
48extern 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)
52extern int EM_extLineNum;
53
54void 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
74void ck_fprintf_stdout( const char * format, ... );
75void ck_fprintf_stderr( const char * format, ... );
76void ck_fflush_stdout();
77void ck_fflush_stderr();
78void ck_vfprintf_stdout( const char * format, va_list args );
79void ck_vfprintf_stderr( const char * format, va_list args );
80
81// callbacks
82void ck_set_stdout_callback( void (*callback)(const char *) );
83void 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
94extern "C++" {
95#include <sstream>
96
97class ChuckOutStream
98{
99public:
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
119private:
120 void flush();
121 std::stringstream m_stream;
122 void (*m_callback)(const char *);
123 bool m_isErr;
124};
125
126
127extern ChuckOutStream g_ck_stdoutstream;
128extern 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
149void EM_log( int, c_constr, ... );
150void EM_setlog( int );
151void EM_pushlog();
152void EM_poplog();
153
154// actual level
155extern int g_loglevel;
156// macro to compare
157#define DO_LOG(x) ( x <= g_loglevel )
158
159void EM_error( int, c_constr, ... );
160void EM_error2( int, c_constr, ... );
161void EM_error2b( int, c_constr, ... );
162void EM_error3( c_constr, ... );
163void EM_impossible( c_constr, ... );
164t_CKBOOL EM_reset( c_constr filename, FILE * fd );
165void EM_change_file( c_constr filename );
166const char * EM_lasterror();
167void EM_reset_msg();
168
169const char * mini( const char * str );
170const 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"
33using namespace std;
34
35
36
37
38//-----------------------------------------------------------------------------
39// name: Chuck_Frame()
40// desc: ...
41//-----------------------------------------------------------------------------
42Chuck_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//-----------------------------------------------------------------------------
59Chuck_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//-----------------------------------------------------------------------------
89void 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//-----------------------------------------------------------------------------
101void 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//-----------------------------------------------------------------------------
134void 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//-----------------------------------------------------------------------------
45struct 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//-----------------------------------------------------------------------------
71struct 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
82public:
83 Chuck_Frame();
84 ~Chuck_Frame() { }
85
86public:
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>
53using namespace std;
54
55
56#ifdef __WINDOWS_DS__
57typedef BYTE uint8_t;
58typedef WORD uint16_t;
59// ge: this needed in earlier/some versions of windows
60#ifndef __WINDOWS_MODERN__
61typedef DWORD uint32_t;
62#endif
63#endif
64
65
66// available baud rates
67const t_CKUINT Chuck_IO_Serial::CK_BAUD_2400 = 2400;
68const t_CKUINT Chuck_IO_Serial::CK_BAUD_4800 = 4800;
69const t_CKUINT Chuck_IO_Serial::CK_BAUD_9600 = 9600;
70const t_CKUINT Chuck_IO_Serial::CK_BAUD_19200 = 19200;
71const t_CKUINT Chuck_IO_Serial::CK_BAUD_38400 = 38400;
72const t_CKUINT Chuck_IO_Serial::CK_BAUD_7200 = 7200;
73const t_CKUINT Chuck_IO_Serial::CK_BAUD_14400 = 14400;
74const t_CKUINT Chuck_IO_Serial::CK_BAUD_28800 = 28800;
75const t_CKUINT Chuck_IO_Serial::CK_BAUD_57600 = 57600;
76const t_CKUINT Chuck_IO_Serial::CK_BAUD_76800 = 76800;
77const t_CKUINT Chuck_IO_Serial::CK_BAUD_115200 = 115200;
78const t_CKUINT Chuck_IO_Serial::CK_BAUD_230400 = 230400;
79
80const t_CKUINT Chuck_IO_Serial::TYPE_NONE = 0;
81const t_CKUINT Chuck_IO_Serial::TYPE_BYTE = 1;
82const t_CKUINT Chuck_IO_Serial::TYPE_WORD = 2;
83const t_CKUINT Chuck_IO_Serial::TYPE_INT = 3;
84const t_CKUINT Chuck_IO_Serial::TYPE_FLOAT = 4;
85const t_CKUINT Chuck_IO_Serial::TYPE_STRING = 5;
86const t_CKUINT Chuck_IO_Serial::TYPE_LINE = 6;
87const t_CKUINT Chuck_IO_Serial::TYPE_WRITE = 100;
88
89std::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
100const t_CKUINT CHUCK_IO_DEFAULT_BUFSIZE = 1024;
101const char * CHUCK_IO_SCANF_STRING = "%1024s";
102
103CK_DLL_MFUN(serialio_canWait);
104
105void * 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
114void * 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
123void 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
134Chuck_IO_Serial::Chuck_IO_Serial( Chuck_VM * vm ) :
135m_asyncRequests(CircularBuffer<Request>(32)),
136m_asyncResponses(CircularBuffer<Request>(32)),
137m_asyncWriteRequests(CircularBuffer<Request>(32)),
138m_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
163Chuck_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
183t_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
200t_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
220t_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
260t_CKBOOL Chuck_IO_Serial::good()
261{
262 return m_fd >= 0 && m_cfd != NULL;
263}
264
265void 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
283void 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
298void 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
309t_CKBOOL Chuck_IO_Serial::can_wait()
310{
311 return m_asyncResponses.numElements() == 0;
312}
313
314t_CKINT Chuck_IO_Serial::mode()
315{
316 return m_iomode;
317}
318
319void 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
328t_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
380t_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
410t_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
442Chuck_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
478t_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
494void 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
526void Chuck_IO_Serial::write( t_CKINT val )
527{
528 write( val, 4 );
529}
530
531
532void 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
604void 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
671void 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
713void 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
729t_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
758Chuck_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
781t_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
804Chuck_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
828Chuck_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
851Chuck_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
874Chuck_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
897t_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
953t_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
972t_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
990t_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
1005t_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
1052error:
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
1067t_CKBOOL Chuck_IO_Serial::handle_string(Chuck_IO_Serial::Request & r)
1068{
1069 return FALSE;
1070}
1071
1072t_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
1116error:
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
1124t_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
1166error:
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
1174t_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
1214error:
1215 r.m_val = 0;
1216 r.m_status = Chuck_IO_Serial::Request::RQ_STATUS_FAILURE;
1217
1218 return TRUE;
1219}
1220
1221t_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
1256t_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
1291void 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
1384void 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
1426t_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
1513error:
1514
1515 DWORD error = GetLastError();
1516
1517 return FALSE;
1518
1519#endif
1520}
1521
1522
1523t_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
1548error:
1549 return 0;
1550
1551#endif
1552}
1553
1554
1555//-----------------------------------------------------------------------------
1556// serialio API
1557//-----------------------------------------------------------------------------
1558CK_DLL_SFUN( serialio_list );
1559CK_DLL_ALLOC( serialio_alloc );
1560CK_DLL_CTOR( serialio_ctor );
1561CK_DLL_DTOR( serialio_dtor );
1562CK_DLL_MFUN( serialio_open );
1563CK_DLL_MFUN( serialio_close );
1564CK_DLL_MFUN( serialio_ready );
1565CK_DLL_MFUN( serialio_readLine );
1566CK_DLL_MFUN( serialio_onLine );
1567CK_DLL_MFUN( serialio_onByte );
1568CK_DLL_MFUN( serialio_onBytes );
1569CK_DLL_MFUN( serialio_onInts );
1570CK_DLL_MFUN( serialio_onFloats );
1571CK_DLL_MFUN( serialio_getLine );
1572CK_DLL_MFUN( serialio_getByte );
1573CK_DLL_MFUN( serialio_getBytes );
1574CK_DLL_MFUN( serialio_getInts );
1575CK_DLL_MFUN( serialio_setBaudRate );
1576CK_DLL_MFUN( serialio_getBaudRate );
1577CK_DLL_MFUN( serialio_writeByte );
1578CK_DLL_MFUN( serialio_writeBytes );
1579
1580CK_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//-----------------------------------------------------------------------------
1592t_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
1747error:
1748
1749 // end the class import
1750 type_engine_import_class_end( env );
1751
1752 return FALSE;
1753}
1754
1755
1756
1757CK_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
1776CK_DLL_ALLOC( serialio_alloc )
1777{
1778 return new Chuck_IO_Serial( SHRED->vm_ref );
1779}
1780
1781CK_DLL_CTOR( serialio_ctor )
1782{
1783 Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1784 SHRED->add_serialio(cereal);
1785}
1786
1787CK_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
1797CK_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
1807CK_DLL_MFUN( serialio_close )
1808{
1809 Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1810
1811 cereal->close();
1812}
1813
1814CK_DLL_MFUN( serialio_ready )
1815{
1816 Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1817
1818 RETURN->v_int = cereal->ready();
1819}
1820
1821CK_DLL_MFUN( serialio_readLine )
1822{
1823 Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1824
1825 RETURN->v_string = cereal->readLine();
1826}
1827
1828
1829CK_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
1839CK_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
1849CK_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
1861CK_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
1873CK_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
1885CK_DLL_MFUN( serialio_getLine )
1886{
1887 Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1888 RETURN->v_string = cereal->getLine();
1889}
1890
1891
1892CK_DLL_MFUN( serialio_getByte )
1893{
1894 Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1895 RETURN->v_int = cereal->getByte();
1896}
1897
1898
1899CK_DLL_MFUN( serialio_getBytes )
1900{
1901 Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1902 RETURN->v_object = cereal->getBytes();
1903}
1904
1905
1906CK_DLL_MFUN( serialio_getInts )
1907{
1908 Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1909 RETURN->v_object = cereal->getInts();
1910}
1911
1912
1913CK_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
1921CK_DLL_MFUN( serialio_getBaudRate )
1922{
1923 Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF;
1924 RETURN->v_int = cereal->getBaudRate();
1925}
1926
1927
1928CK_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
1936CK_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
1943CK_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//-----------------------------------------------------------------------------
47struct Chuck_IO_Serial : public Chuck_IO
48{
49public:
50 Chuck_IO_Serial( Chuck_VM * vm );
51 virtual ~Chuck_IO_Serial();
52
53 static void shutdown();
54
55public:
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
137protected:
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
199t_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>
54using namespace std;
55
56// dac tick
57CK_DLL_TICK(__ugen_tick) { *out = in; return TRUE; }
58// object string offset
59static t_CKUINT Object_offset_string = 0;
60
61// global
62static Chuck_String * g_newline = new Chuck_String();
63
64
65
66
67
68
69
70//-----------------------------------------------------------------------------
71// name: init_class_object()
72// desc: ...
73//-----------------------------------------------------------------------------
74t_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
101error:
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//-----------------------------------------------------------------------------
116t_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
192error:
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
204static t_CKINT uana_offset_blob = 0;
205//-----------------------------------------------------------------------------
206// name: init_class_uana()
207// desc: ...
208//-----------------------------------------------------------------------------
209t_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
279error:
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
291static t_CKINT uanablob_offset_when = 0;
292static t_CKINT uanablob_offset_fvals = 0;
293static t_CKINT uanablob_offset_cvals = 0;
294//-----------------------------------------------------------------------------
295// name: init_class_blob()
296// desc: ...
297//-----------------------------------------------------------------------------
298t_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
354error:
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//-----------------------------------------------------------------------------
371t_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
419error:
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//-----------------------------------------------------------------------------
435t_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
539error:
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//-----------------------------------------------------------------------------
554t_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
630error:
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//-----------------------------------------------------------------------------
644t_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
685error:
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//-----------------------------------------------------------------------------
699t_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
823error:
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//-----------------------------------------------------------------------------
838t_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
985error:
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//-----------------------------------------------------------------------------
1000t_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
1078error:
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//-----------------------------------------------------------------------------
1093t_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
1171error:
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//-----------------------------------------------------------------------------
1184t_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
1377error:
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//-----------------------------------------------------------------------------
1392t_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
1469error:
1470
1471 // end the class import
1472 type_engine_import_class_end( env );
1473
1474 return FALSE;
1475}
1476
1477
1478
1479// static
1480static t_CKUINT MidiIn_offset_data = 0;
1481t_CKUINT MidiMsg_offset_data1 = 0;
1482t_CKUINT MidiMsg_offset_data2 = 0;
1483t_CKUINT MidiMsg_offset_data3 = 0;
1484t_CKUINT MidiMsg_offset_when = 0;
1485static t_CKUINT MidiOut_offset_data = 0;
1486
1487//-----------------------------------------------------------------------------
1488// name: init_class_Midi()
1489// desc: ...
1490//-----------------------------------------------------------------------------
1491t_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
1617error:
1618
1619 // end the class import
1620 type_engine_import_class_end( env );
1621
1622 return FALSE;
1623}
1624
1625
1626
1627
1628// static
1629static t_CKUINT HidIn_offset_data = 0;
1630
1631static t_CKUINT HidMsg_offset_device_type = 0;
1632static t_CKUINT HidMsg_offset_device_num = 0;
1633static t_CKUINT HidMsg_offset_type = 0;
1634static t_CKUINT HidMsg_offset_which = 0;
1635static t_CKUINT HidMsg_offset_idata = 0;
1636static t_CKUINT HidMsg_offset_fdata = 0;
1637static t_CKUINT HidMsg_offset_when = 0;
1638static t_CKUINT HidMsg_offset_deltax = 0;
1639static t_CKUINT HidMsg_offset_deltay = 0;
1640static t_CKUINT HidMsg_offset_axis_position = 0; // deprecated
1641static t_CKUINT HidMsg_offset_axis_position2 = 0;
1642static t_CKUINT HidMsg_offset_scaled_axis_position = 0; // deprecated
1643static t_CKUINT HidMsg_offset_hat_position = 0;
1644static t_CKUINT HidMsg_offset_cursorx = 0;
1645static t_CKUINT HidMsg_offset_cursory = 0;
1646static t_CKUINT HidMsg_offset_scaledcursorx = 0;
1647static t_CKUINT HidMsg_offset_scaledcursory = 0;
1648static t_CKUINT HidMsg_offset_x = 0;
1649static t_CKUINT HidMsg_offset_y = 0;
1650static t_CKUINT HidMsg_offset_z = 0;
1651static t_CKUINT HidMsg_offset_touchx = 0; // added 1.3.0.0
1652static t_CKUINT HidMsg_offset_touchy = 0; // added 1.3.0.0
1653static t_CKUINT HidMsg_offset_touchsize = 0; // added 1.3.0.0
1654static t_CKUINT HidMsg_offset_ascii = 0;
1655static t_CKUINT HidMsg_offset_key = 0;
1656
1657static t_CKUINT HidOut_offset_data = 0;
1658
1659//-----------------------------------------------------------------------------
1660// name: init_class_HID()
1661// desc: ...
1662//-----------------------------------------------------------------------------
1663t_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
2056error:
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
2069static t_CKUINT MidiRW_offset_data = 0;
2070static t_CKUINT MidiMsgOut_offset_data = 0;
2071static t_CKUINT MidiMsgIn_offset_data = 0;
2072//-----------------------------------------------------------------------------
2073// name: init_class_MidiRW()
2074// desc: ...
2075//-----------------------------------------------------------------------------
2076t_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
2176error:
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
2190CK_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
2201CK_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
2214CK_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
2250CK_DLL_CTOR( ugen_ctor )
2251{
2252}
2253
2254CK_DLL_DTOR( ugen_dtor )
2255{
2256 // get as ugen
2257 // Chuck_UGen * ugen = (Chuck_UGen *)SELF;
2258}
2259
2260CK_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
2283CK_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
2291CK_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
2303CK_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
2328CK_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
2336CK_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
2357CK_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
2365CK_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
2373CK_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
2381CK_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
2395CK_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
2417CK_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
2431CK_DLL_DTOR( uana_dtor )
2432{
2433 // TODO: GC should release the blob!
2434}
2435
2436CK_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
2484CK_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
2491CK_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
2498CK_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
2516CK_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
2534CK_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
2556Chuck_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
2564Chuck_UAnaBlobProxy::~Chuck_UAnaBlobProxy()
2565{
2566 // release
2567 SAFE_RELEASE( m_blob );
2568}
2569
2570t_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
2576Chuck_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
2584Chuck_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
2593Chuck_UAnaBlobProxy * getBlobProxy( const Chuck_UAna * uana )
2594{
2595 return (Chuck_UAnaBlobProxy *)OBJ_MEMBER_INT(uana, uana_offset_blob);
2596}
2597
2598// ctor
2599CK_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
2618CK_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
2635CK_DLL_MFUN( uanablob_when )
2636{
2637 // set return
2638 RETURN->v_time = OBJ_MEMBER_TIME(SELF, uanablob_offset_when);
2639}
2640
2641CK_DLL_MFUN( uanablob_fvals )
2642{
2643 // set return
2644 RETURN->v_object = (Chuck_Array8 *)OBJ_MEMBER_INT(SELF, uanablob_offset_fvals);
2645}
2646
2647CK_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
2664CK_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
2681CK_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
2688CK_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
2695CK_DLL_DTOR( event_dtor )
2696{
2697// delete (Data_Event *)OBJ_MEMBER_INT(SELF, event_offset_data);
2698}
2699
2700CK_DLL_MFUN( event_signal )
2701{
2702 Chuck_Event * d = (Chuck_Event *)SELF;
2703 d->signal();
2704}
2705
2706CK_DLL_MFUN( event_broadcast )
2707{
2708 Chuck_Event * d = (Chuck_Event *)SELF;
2709 d->broadcast();
2710}
2711
2712CK_DLL_MFUN( event_wait )
2713{
2714 // Chuck_Event * d = (Chuck_Event *)SELF;
2715 assert( FALSE );
2716}
2717
2718CK_DLL_MFUN( event_can_wait )
2719{
2720 RETURN->v_int = TRUE;
2721}
2722
2723
2724//-----------------------------------------------------------------------------
2725// vec3 API
2726//-----------------------------------------------------------------------------
2727CK_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
2738CK_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
2746CK_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
2756CK_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
2771CK_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
2781CK_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
2793CK_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
2807CK_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
2817CK_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
2831CK_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
2841CK_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//-----------------------------------------------------------------------------
2859CK_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
2871CK_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
2879CK_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
2890CK_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//-----------------------------------------------------------------------------
2911CK_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
2919CK_DLL_SFUN( io_newline )
2920{
2921 RETURN->v_string = g_newline;
2922}
2923
2924
2925//-----------------------------------------------------------------------------
2926// FileIO API
2927//-----------------------------------------------------------------------------
2928CK_DLL_CTOR( fileio_ctor )
2929{ }
2930
2931CK_DLL_DTOR( fileio_dtor )
2932{ }
2933
2934CK_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
2944CK_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
2953CK_DLL_MFUN( fileio_close )
2954{
2955 Chuck_IO_File * f = (Chuck_IO_File *)SELF;
2956 f->close();
2957}
2958
2959CK_DLL_MFUN( fileio_good )
2960{
2961 Chuck_IO_File * f = (Chuck_IO_File *)SELF;
2962 RETURN->v_int = f->good();
2963}
2964
2965CK_DLL_MFUN( fileio_flush )
2966{
2967 Chuck_IO_File * f = (Chuck_IO_File *)SELF;
2968 f->flush();
2969}
2970
2971CK_DLL_MFUN( fileio_getmode )
2972{
2973 Chuck_IO_File * f = (Chuck_IO_File *)SELF;
2974 RETURN->v_int = f->mode();
2975}
2976
2977CK_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
2986CK_DLL_MFUN( fileio_size )
2987{
2988 Chuck_IO_File * f = (Chuck_IO_File *)SELF;
2989 RETURN->v_int = f->size();
2990}
2991
2992CK_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
3000CK_DLL_MFUN( fileio_tell )
3001{
3002 Chuck_IO_File * f = (Chuck_IO_File *)SELF;
3003 RETURN->v_int = f->tell();
3004}
3005
3006CK_DLL_MFUN( fileio_isdir )
3007{
3008 Chuck_IO_File * f = (Chuck_IO_File *)SELF;
3009 RETURN->v_int = f->isDir();
3010}
3011
3012CK_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/*
3020CK_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
3030CK_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
3037CK_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
3072CK_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
3082CK_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
3089CK_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
3096CK_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
3103CK_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
3135CK_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
3167CK_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
3201CK_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//-----------------------------------------------------------------------------
3237CK_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
3245CK_DLL_MFUN( chout_good )
3246{
3247 Chuck_IO_Chout * c = SHRED->vm_ref->chout();
3248 RETURN->v_int = c->good();
3249}
3250
3251CK_DLL_MFUN( chout_flush )
3252{
3253 Chuck_IO_Chout * c = SHRED->vm_ref->chout();
3254 c->flush();
3255}
3256
3257CK_DLL_MFUN( chout_getmode )
3258{
3259 // problem
3260 Chuck_IO_Chout * c = SHRED->vm_ref->chout();
3261 RETURN->v_int = c->mode();
3262}
3263
3264CK_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
3282CK_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
3289CK_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
3295CK_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
3305CK_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
3312CK_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
3319CK_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
3326CK_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
3334CK_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
3342CK_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//-----------------------------------------------------------------------------
3356CK_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
3364CK_DLL_MFUN( cherr_good )
3365{
3366 Chuck_IO_Cherr * c = SHRED->vm_ref->cherr();
3367 RETURN->v_int = c->good();
3368}
3369
3370CK_DLL_MFUN( cherr_flush )
3371{
3372 Chuck_IO_Cherr * c = SHRED->vm_ref->cherr();
3373 c->flush();
3374}
3375
3376CK_DLL_MFUN( cherr_getmode )
3377{
3378 // problem
3379 Chuck_IO_Cherr * c = SHRED->vm_ref->cherr();
3380 RETURN->v_int = c->mode();
3381}
3382
3383CK_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
3401CK_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
3408CK_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
3414CK_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
3424CK_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
3431CK_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
3438CK_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
3445CK_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
3453CK_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
3461CK_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
3479CK_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
3487CK_DLL_MFUN( shred_running )
3488{
3489 Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF;
3490 RETURN->v_int = derhs->is_running;
3491}
3492
3493CK_DLL_MFUN( shred_done )
3494{
3495 Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF;
3496 RETURN->v_int = derhs->is_done;
3497}
3498
3499CK_DLL_MFUN( shred_clone )
3500{
3501}
3502
3503CK_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
3510CK_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
3521CK_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
3529CK_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
3543CK_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
3552CK_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
3563CK_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
3582CK_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
3592CK_DLL_MFUN( string_length )
3593{
3594 Chuck_String * s = (Chuck_String *)SELF;
3595 RETURN->v_int = s->str().length();
3596}
3597
3598CK_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
3606CK_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
3614CK_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
3622CK_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
3630CK_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
3638CK_DLL_MFUN( string_toString )
3639{
3640 Chuck_String * s = (Chuck_String *)SELF;
3641 RETURN->v_string = s;
3642}
3643
3644CK_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
3659CK_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
3679CK_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
3697CK_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
3723CK_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
3746CK_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
3775CK_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
3806CK_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
3819CK_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
3840CK_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
3853CK_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
3874CK_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
3887CK_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
3908CK_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
3921CK_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
3942CK_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
3966CK_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
3974CK_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
3982CK_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/*
4007CK_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
4014CK_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()
4023CK_DLL_MFUN( array_get_size )
4024{
4025 Chuck_Array * array = (Chuck_Array *)SELF;
4026 RETURN->v_int = array->size();
4027}
4028
4029// array.size()
4030CK_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()
4049CK_DLL_MFUN( array_clear )
4050{
4051 Chuck_Array * array = (Chuck_Array *)SELF;
4052 array->clear();
4053}
4054
4055// array.reset()
4056CK_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()
4065CK_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()
4083CK_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()
4090CK_DLL_MFUN( array_get_capacity )
4091{
4092 Chuck_Array * array = (Chuck_Array *)SELF;
4093 RETURN->v_int = array->capacity();
4094}
4095
4096// array.find()
4097CK_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()
4105CK_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()
4113CK_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()
4128CK_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//-----------------------------------------------------------------------------
4148CK_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
4155CK_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
4161CK_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
4168CK_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
4175CK_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
4181CK_DLL_MFUN( MidiIn_num )
4182{
4183 MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data);
4184 RETURN->v_int = min->num();
4185}
4186
4187CK_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
4194CK_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
4205CK_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
4220CK_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//-----------------------------------------------------------------------------
4230CK_DLL_CTOR( MidiOut_ctor )
4231{
4232 OBJ_MEMBER_INT(SELF, MidiOut_offset_data) = (t_CKUINT)new MidiOut;
4233}
4234
4235CK_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
4241CK_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
4248CK_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
4255CK_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
4261CK_DLL_MFUN( MidiOut_num )
4262{
4263 MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data);
4264 RETURN->v_int = mout->num();
4265}
4266
4267CK_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
4278CK_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
4285CK_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//-----------------------------------------------------------------------------
4302CK_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
4308CK_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
4314CK_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
4320CK_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
4326CK_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
4332CK_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//-----------------------------------------------------------------------------
4341CK_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
4348CK_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
4354CK_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
4363CK_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
4371CK_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
4378CK_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
4385CK_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
4392CK_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
4398CK_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
4404CK_DLL_MFUN( HidIn_num )
4405{
4406 HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data);
4407 RETURN->v_int = min->num();
4408}
4409
4410CK_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
4417CK_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
4430CK_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
4477CK_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
4525CK_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
4540CK_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
4546CK_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
4585CK_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
4610CK_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
4625CK_DLL_SFUN( HidIn_start_cursor_track )
4626{
4627 RETURN->v_int = !Mouse_start_cursor_track();
4628}
4629
4630CK_DLL_SFUN( HidIn_stop_cursor_track )
4631{
4632 RETURN->v_int = !Mouse_stop_cursor_track();
4633}
4634
4635//-----------------------------------------------------------------------------
4636// HidOut API
4637//-----------------------------------------------------------------------------
4638CK_DLL_CTOR( HidOut_ctor )
4639{
4640 OBJ_MEMBER_INT(SELF, HidOut_offset_data) = (t_CKUINT)new HidOut;
4641}
4642
4643CK_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
4649CK_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
4656CK_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
4662CK_DLL_MFUN( HidOut_num )
4663{
4664 HidOut * mout = (HidOut *)OBJ_MEMBER_INT(SELF, HidOut_offset_data);
4665 RETURN->v_int = mout->num();
4666}
4667
4668CK_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
4679CK_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
4686CK_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//-----------------------------------------------------------------------------
4701CK_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
4708CK_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
4716CK_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
4725CK_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
4733CK_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
4748CK_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//-----------------------------------------------------------------------------
4766CK_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
4773CK_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
4781CK_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
4790CK_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
4798CK_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//-----------------------------------------------------------------------------
4816CK_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
4823CK_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
4831CK_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
4840CK_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
4848CK_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
45struct Chuck_UAna;
46
47// query
48DLL_QUERY lang_query( Chuck_DL_Query * QUERY );
49
50// base class initialization
51t_CKBOOL init_class_object( Chuck_Env * env, Chuck_Type * type );
52t_CKBOOL init_class_ugen( Chuck_Env * env, Chuck_Type * type );
53t_CKBOOL init_class_uana( Chuck_Env * env, Chuck_Type * type );
54t_CKBOOL init_class_blob( Chuck_Env * env, Chuck_Type * type );
55t_CKBOOL init_class_event( Chuck_Env * env, Chuck_Type * type );
56t_CKBOOL init_class_shred( Chuck_Env * env, Chuck_Type * type );
57t_CKBOOL init_class_string( Chuck_Env * env, Chuck_Type * type );
58t_CKBOOL init_class_array( Chuck_Env * env, Chuck_Type * type );
59t_CKBOOL init_class_vec3( Chuck_Env * env, Chuck_Type * type ); // 1.3.5.3
60t_CKBOOL init_class_vec4( Chuck_Env * env, Chuck_Type * type ); // 1.3.5.3
61
62t_CKBOOL init_class_Midi( Chuck_Env * env );
63t_CKBOOL init_class_MidiRW( Chuck_Env * env );
64t_CKBOOL init_class_HID( Chuck_Env * env );
65t_CKBOOL init_class_io( Chuck_Env * env, Chuck_Type * type );
66t_CKBOOL init_class_fileio( Chuck_Env * env, Chuck_Type * type );
67// added 1.3.0.0 -- moved to be full-fledged class
68t_CKBOOL init_class_chout( Chuck_Env * env, Chuck_Type * type );
69// added 1.3.0.0 -- moved to be full-fledged class
70t_CKBOOL init_class_cherr( Chuck_Env * env, Chuck_Type * type );
71
72
73
74
75//-----------------------------------------------------------------------------
76// object API
77//-----------------------------------------------------------------------------
78CK_DLL_CTOR( object_ctor );
79CK_DLL_DTOR( object_dtor );
80CK_DLL_MFUN( object_equals );
81CK_DLL_MFUN( object_getType );
82CK_DLL_MFUN( object_hashCode );
83CK_DLL_MFUN( object_toString );
84
85
86//-----------------------------------------------------------------------------
87// ugen API
88//-----------------------------------------------------------------------------
89CK_DLL_CTOR( ugen_ctor );
90CK_DLL_DTOR( ugen_dtor );
91CK_DLL_MFUN( ugen_op );
92CK_DLL_MFUN( ugen_cget_op );
93CK_DLL_MFUN( ugen_last );
94CK_DLL_MFUN( ugen_cget_last );
95CK_DLL_MFUN( ugen_next );
96CK_DLL_MFUN( ugen_cget_next );
97CK_DLL_MFUN( ugen_gain );
98CK_DLL_MFUN( ugen_cget_gain );
99CK_DLL_MFUN( ugen_numChannels );
100CK_DLL_MFUN( ugen_cget_numChannels );
101CK_DLL_MFUN( ugen_chan );
102CK_DLL_MFUN( ugen_connected );
103
104
105//-----------------------------------------------------------------------------
106// uana API
107//-----------------------------------------------------------------------------
108CK_DLL_CTOR( uana_ctor );
109CK_DLL_DTOR( uana_dtor );
110CK_DLL_MFUN( uana_upchuck );
111CK_DLL_MFUN( uana_blob );
112CK_DLL_MFUN( uana_fvals );
113CK_DLL_MFUN( uana_cvals );
114CK_DLL_MFUN( uana_fval );
115CK_DLL_MFUN( uana_cval );
116CK_DLL_MFUN( uana_connected );
117
118
119//-----------------------------------------------------------------------------
120// uanablob API
121//-----------------------------------------------------------------------------
122CK_DLL_CTOR( uanablob_ctor );
123CK_DLL_DTOR( uanablob_dtor );
124CK_DLL_MFUN( uanablob_fvals );
125CK_DLL_MFUN( uanablob_cvals );
126CK_DLL_MFUN( uanablob_fval );
127CK_DLL_MFUN( uanablob_cval );
128CK_DLL_MFUN( uanablob_when );
129
130
131//-----------------------------------------------------------------------------
132// name: Chuck_UAnaBlobProxy
133// desc: proxy for interfacing with UAnaBlob, which is a Chuck class
134//-----------------------------------------------------------------------------
135struct Chuck_UAnaBlobProxy
136{
137public:
138 Chuck_UAnaBlobProxy( Chuck_Object * blob );
139 virtual ~Chuck_UAnaBlobProxy();
140
141public:
142 t_CKTIME & when();
143 Chuck_Array8 & fvals();
144 Chuck_Array16 & cvals();
145
146public:
147 Chuck_Object * realblob() { return m_blob; }
148
149protected:
150 Chuck_Object * m_blob;
151};
152
153// get proxy
154Chuck_UAnaBlobProxy * getBlobProxy( const Chuck_UAna * uana );
155
156
157//-----------------------------------------------------------------------------
158// shred API
159//-----------------------------------------------------------------------------
160CK_DLL_CTOR( shred_ctor );
161CK_DLL_DTOR( shred_dtor );
162CK_DLL_MFUN( shred_exit );
163CK_DLL_MFUN( shred_clone );
164CK_DLL_MFUN( shred_id );
165CK_DLL_MFUN( shred_yield );
166CK_DLL_MFUN( shred_running );
167CK_DLL_MFUN( shred_done );
168CK_DLL_MFUN( shred_numArgs );
169CK_DLL_MFUN( shred_getArg );
170CK_DLL_MFUN( shred_sourcePath ); // added 1.3.0.0
171CK_DLL_MFUN( shred_sourceDir ); // added 1.3.0.0
172CK_DLL_MFUN( shred_sourceDir2 ); // added 1.3.2.0
173CK_DLL_SFUN( shred_fromId ); // added 1.3.2.0
174
175
176//-----------------------------------------------------------------------------
177// array API
178//-----------------------------------------------------------------------------
179CK_DLL_CTOR( array_ctor );
180CK_DLL_DTOR( array_dtor );
181CK_DLL_MFUN( array_set_capacity );
182CK_DLL_MFUN( array_get_capacity );
183CK_DLL_MFUN( array_get_capacity_hack );
184CK_DLL_MFUN( array_set_size );
185CK_DLL_MFUN( array_get_size );
186CK_DLL_MFUN( array_push_back );
187CK_DLL_MFUN( array_pop_back );
188CK_DLL_MFUN( array_push_front );
189CK_DLL_MFUN( array_pop_front );
190CK_DLL_MFUN( array_find );
191CK_DLL_MFUN( array_erase );
192CK_DLL_MFUN( array_clear );
193CK_DLL_MFUN( array_reset );
194
195
196//-----------------------------------------------------------------------------
197// event API
198//-----------------------------------------------------------------------------
199CK_DLL_CTOR( event_ctor );
200CK_DLL_DTOR( event_dtor );
201CK_DLL_MFUN( event_signal );
202CK_DLL_MFUN( event_broadcast );
203CK_DLL_MFUN( event_wait );
204CK_DLL_MFUN( event_can_wait );
205
206
207//-----------------------------------------------------------------------------
208// io API
209//-----------------------------------------------------------------------------
210CK_DLL_MFUN( io_dummy );
211CK_DLL_SFUN( io_newline );
212CK_DLL_SFUN( io_openfile );
213
214
215//-----------------------------------------------------------------------------
216// fileio API
217//-----------------------------------------------------------------------------
218CK_DLL_CTOR( fileio_ctor );
219CK_DLL_DTOR( fileio_dtor );
220CK_DLL_MFUN( fileio_open );
221CK_DLL_MFUN( fileio_openflags );
222CK_DLL_MFUN( fileio_good );
223CK_DLL_MFUN( fileio_close );
224CK_DLL_MFUN( fileio_flush );
225CK_DLL_MFUN( fileio_getmode );
226CK_DLL_MFUN( fileio_setmode );
227CK_DLL_MFUN( fileio_size );
228CK_DLL_MFUN( fileio_seek );
229CK_DLL_MFUN( fileio_tell );
230CK_DLL_MFUN( fileio_isdir );
231CK_DLL_MFUN( fileio_dirlist );
232CK_DLL_MFUN( fileio_read );
233CK_DLL_MFUN( fileio_readline );
234CK_DLL_MFUN( fileio_readint );
235CK_DLL_MFUN( fileio_readintflags );
236CK_DLL_MFUN( fileio_readfloat );
237CK_DLL_MFUN( fileio_eof );
238CK_DLL_MFUN( fileio_more );
239CK_DLL_MFUN( fileio_writestring );
240CK_DLL_MFUN( fileio_writeint );
241CK_DLL_MFUN( fileio_writeintflags );
242CK_DLL_MFUN( fileio_writefloat );
243
244
245//-----------------------------------------------------------------------------
246// chout API -- added 1.3.0.0 as full class
247//-----------------------------------------------------------------------------
248CK_DLL_MFUN( chout_good );
249CK_DLL_MFUN( chout_close );
250CK_DLL_MFUN( chout_flush );
251CK_DLL_MFUN( chout_getmode );
252CK_DLL_MFUN( chout_setmode );
253CK_DLL_MFUN( chout_read );
254CK_DLL_MFUN( chout_readline );
255CK_DLL_MFUN( chout_readint );
256CK_DLL_MFUN( chout_readintflags );
257CK_DLL_MFUN( chout_readfloat );
258CK_DLL_MFUN( chout_eof );
259CK_DLL_MFUN( chout_more );
260CK_DLL_MFUN( chout_writestring );
261CK_DLL_MFUN( chout_writeint );
262CK_DLL_MFUN( chout_writefloat );
263
264
265//-----------------------------------------------------------------------------
266// cherr API -- added 1.3.0.0 as full class
267//-----------------------------------------------------------------------------
268CK_DLL_MFUN( cherr_good );
269CK_DLL_MFUN( cherr_close );
270CK_DLL_MFUN( cherr_flush );
271CK_DLL_MFUN( cherr_getmode );
272CK_DLL_MFUN( cherr_setmode );
273CK_DLL_MFUN( cherr_read );
274CK_DLL_MFUN( cherr_readline );
275CK_DLL_MFUN( cherr_readint );
276CK_DLL_MFUN( cherr_readintflags );
277CK_DLL_MFUN( cherr_readfloat );
278CK_DLL_MFUN( cherr_eof );
279CK_DLL_MFUN( cherr_more );
280CK_DLL_MFUN( cherr_writestring );
281CK_DLL_MFUN( cherr_writeint );
282CK_DLL_MFUN( cherr_writefloat );
283
284
285//-----------------------------------------------------------------------------
286// string API
287//-----------------------------------------------------------------------------
288CK_DLL_CTOR( string_ctor );
289CK_DLL_DTOR( string_dtor );
290CK_DLL_MFUN( string_length );
291CK_DLL_MFUN( string_upper );
292CK_DLL_MFUN( string_lower );
293CK_DLL_MFUN( string_ltrim );
294CK_DLL_MFUN( string_rtrim );
295CK_DLL_MFUN( string_trim );
296CK_DLL_MFUN( string_toString );
297CK_DLL_MFUN( string_set_at );
298CK_DLL_MFUN( string_get_at );
299CK_DLL_MFUN( string_charAt);
300CK_DLL_MFUN( string_setCharAt);
301CK_DLL_MFUN( string_substring);
302CK_DLL_MFUN( string_substringN);
303CK_DLL_MFUN( string_insert);
304CK_DLL_MFUN( string_replace);
305CK_DLL_MFUN( string_replaceN);
306CK_DLL_MFUN( string_find);
307CK_DLL_MFUN( string_findStart);
308CK_DLL_MFUN( string_findStr);
309CK_DLL_MFUN( string_findStrStart);
310CK_DLL_MFUN( string_rfind);
311CK_DLL_MFUN( string_rfindStart);
312CK_DLL_MFUN( string_rfindStr);
313CK_DLL_MFUN( string_rfindStrStart);
314CK_DLL_MFUN( string_erase);
315CK_DLL_MFUN( string_toInt);
316CK_DLL_MFUN( string_toFloat);
317CK_DLL_MFUN( string_parent);
318
319
320//-----------------------------------------------------------------------------
321// vector API (vec3, vec4, eventually vector) ge: 1.3.5.3
322//-----------------------------------------------------------------------------
323CK_DLL_MFUN( vec3_set );
324CK_DLL_MFUN( vec3_setAll );
325CK_DLL_MFUN( vec3_magnitude );
326CK_DLL_MFUN( vec3_normalize );
327CK_DLL_MFUN( vec3_interp );
328CK_DLL_MFUN( vec3_interp_delta_float );
329CK_DLL_MFUN( vec3_interp_delta_dur );
330CK_DLL_MFUN( vec3_update_goal );
331CK_DLL_MFUN( vec3_update_goal_slew );
332CK_DLL_MFUN( vec3_updateSet_goalAndValue );
333CK_DLL_MFUN( vec3_updateSet_goalAndValue_slew );
334CK_DLL_MFUN( vec4_set );
335CK_DLL_MFUN( vec4_setAll );
336CK_DLL_MFUN( vec4_magnitude );
337CK_DLL_MFUN( vec4_normalize );
338
339
340//-----------------------------------------------------------------------------
341// name: Data_Exception
342// desc: data for base Chuck Exception class
343//-----------------------------------------------------------------------------
344struct Data_Exception
345{
346public:
347 Data_Exception();
348 ~Data_Exception();
349
350public:
351};
352//-----------------------------------------------------------------------------
353// exception API
354//-----------------------------------------------------------------------------
355
356
357//-----------------------------------------------------------------------------
358// MidiMsg API
359//-----------------------------------------------------------------------------
360CK_DLL_CTOR( MidiMsg_ctor );
361
362extern t_CKUINT MidiMsg_offset_data1;
363extern t_CKUINT MidiMsg_offset_data2;
364extern t_CKUINT MidiMsg_offset_data3;
365extern t_CKUINT MidiMsg_offset_when;
366
367//-----------------------------------------------------------------------------
368// MidiRW API
369//-----------------------------------------------------------------------------
370CK_DLL_CTOR( MidiRW_ctor );
371CK_DLL_DTOR( MidiRW_dtor );
372CK_DLL_MFUN( MidiRW_open );
373CK_DLL_MFUN( MidiRW_close );
374CK_DLL_MFUN( MidiRW_read );
375CK_DLL_MFUN( MidiRW_write );
376
377
378//-----------------------------------------------------------------------------
379// MidiMsgOut API
380//-----------------------------------------------------------------------------
381CK_DLL_CTOR( MidiMsgOut_ctor );
382CK_DLL_DTOR( MidiMsgOut_dtor );
383CK_DLL_MFUN( MidiMsgOut_open );
384CK_DLL_MFUN( MidiMsgOut_close );
385CK_DLL_MFUN( MidiMsgOut_write );
386
387
388//-----------------------------------------------------------------------------
389// MidiMsgIn API
390//-----------------------------------------------------------------------------
391CK_DLL_CTOR( MidiMsgIn_ctor );
392CK_DLL_DTOR( MidiMsgIn_dtor );
393CK_DLL_MFUN( MidiMsgIn_open );
394CK_DLL_MFUN( MidiMsgIn_close );
395CK_DLL_MFUN( MidiMsgIn_read );
396
397
398//-----------------------------------------------------------------------------
399// MidiIn API
400//-----------------------------------------------------------------------------
401CK_DLL_CTOR( MidiIn_ctor );
402CK_DLL_DTOR( MidiIn_dtor );
403CK_DLL_MFUN( MidiIn_open );
404CK_DLL_MFUN( MidiIn_open_named ); // added 1.3.0.0
405CK_DLL_MFUN( MidiIn_open_named_i ); // added 1.3.0.0
406CK_DLL_MFUN( MidiIn_good );
407CK_DLL_MFUN( MidiIn_num );
408CK_DLL_MFUN( MidiIn_name );
409CK_DLL_MFUN( MidiIn_printerr );
410CK_DLL_MFUN( MidiIn_recv );
411CK_DLL_MFUN( MidiIn_can_wait );
412
413
414//-----------------------------------------------------------------------------
415// MidiOut API
416//-----------------------------------------------------------------------------
417CK_DLL_CTOR( MidiOut_ctor );
418CK_DLL_DTOR( MidiOut_dtor );
419CK_DLL_MFUN( MidiOut_open );
420CK_DLL_MFUN( MidiOut_open_named ); // added 1.3.0.0
421CK_DLL_MFUN( MidiOut_open_named_i); // added 1.3.0.0
422CK_DLL_MFUN( MidiOut_good );
423CK_DLL_MFUN( MidiOut_num );
424CK_DLL_MFUN( MidiOut_name );
425CK_DLL_MFUN( MidiOut_printerr );
426CK_DLL_MFUN( MidiOut_send );
427
428
429//-----------------------------------------------------------------------------
430// HidMsg API
431//-----------------------------------------------------------------------------
432CK_DLL_MFUN( HidMsg_is_axis_motion );
433CK_DLL_MFUN( HidMsg_is_button_down );
434CK_DLL_MFUN( HidMsg_is_button_up );
435CK_DLL_MFUN( HidMsg_is_mouse_motion );
436CK_DLL_MFUN( HidMsg_is_hat_motion );
437CK_DLL_MFUN( HidMsg_is_wheel_motion );
438
439//-----------------------------------------------------------------------------
440// HidIn API
441//-----------------------------------------------------------------------------
442CK_DLL_CTOR( HidIn_ctor );
443CK_DLL_DTOR( HidIn_dtor );
444CK_DLL_MFUN( HidIn_open );
445CK_DLL_MFUN( HidIn_open_named );
446CK_DLL_MFUN( HidIn_open_named_i ); // added 1.3.0.0
447CK_DLL_MFUN( HidIn_open_joystick );
448CK_DLL_MFUN( HidIn_open_mouse );
449CK_DLL_MFUN( HidIn_open_keyboard );
450CK_DLL_MFUN( HidIn_open_tiltsensor );
451CK_DLL_MFUN( HidIn_good );
452CK_DLL_MFUN( HidIn_num );
453CK_DLL_MFUN( HidIn_name );
454CK_DLL_MFUN( HidIn_printerr );
455CK_DLL_MFUN( HidIn_recv );
456CK_DLL_MFUN( HidIn_read );
457CK_DLL_MFUN( HidIn_send );
458CK_DLL_MFUN( HidIn_can_wait );
459CK_DLL_SFUN( HidIn_read_tilt_sensor );
460CK_DLL_SFUN( HidIn_ctrl_tiltPollRate );
461CK_DLL_SFUN( HidIn_cget_tiltPollRate );
462CK_DLL_SFUN( HidIn_start_cursor_track );
463CK_DLL_SFUN( HidIn_stop_cursor_track );
464
465
466//-----------------------------------------------------------------------------
467// HidOut API
468//-----------------------------------------------------------------------------
469CK_DLL_CTOR( HidOut_ctor );
470CK_DLL_DTOR( HidOut_dtor );
471CK_DLL_MFUN( HidOut_open );
472CK_DLL_MFUN( HidOut_good );
473CK_DLL_MFUN( HidOut_num );
474CK_DLL_MFUN( HidOut_name );
475CK_DLL_MFUN( HidOut_printerr );
476CK_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>
45using namespace std;
46
47#if defined(__PLATFORM_WIN32__)
48 #include "dirent_win32.h"
49#endif
50
51
52// initialize
53t_CKBOOL Chuck_VM_Object::our_locks_in_effect = TRUE;
54const t_CKINT Chuck_IO::INT32 = 0x1;
55const t_CKINT Chuck_IO::INT16 = 0x2;
56const t_CKINT Chuck_IO::INT8 = 0x4;
57const t_CKINT Chuck_IO::MODE_SYNC = 0;
58const t_CKINT Chuck_IO::MODE_ASYNC = 1;
59const t_CKINT Chuck_IO_File::FLAG_READ_WRITE = 0x8;
60const t_CKINT Chuck_IO_File::FLAG_READONLY = 0x10;
61const t_CKINT Chuck_IO_File::FLAG_WRITEONLY = 0x20;
62const t_CKINT Chuck_IO_File::FLAG_APPEND = 0x40;
63const t_CKINT Chuck_IO_File::TYPE_ASCII = 0x80;
64const t_CKINT Chuck_IO_File::TYPE_BINARY = 0x100;
65void (* Chuck_IO_Chout::m_callback)(const char *) = NULL;
66void (* Chuck_IO_Cherr::m_callback)(const char *) = NULL;
67std::stringstream Chuck_IO_Chout::m_buffer;
68std::stringstream Chuck_IO_Cherr::m_buffer;
69
70
71
72
73//-----------------------------------------------------------------------------
74// name: init_ref()
75// desc: initialize vm object
76//-----------------------------------------------------------------------------
77void 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//-----------------------------------------------------------------------------
98void 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//-----------------------------------------------------------------------------
123void 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//-----------------------------------------------------------------------------
160void 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//-----------------------------------------------------------------------------
172void 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//-----------------------------------------------------------------------------
187void 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
199Chuck_VM_Alloc * Chuck_VM_Alloc::our_instance = NULL;
200
201
202//-----------------------------------------------------------------------------
203// name: instance()
204// desc: return static instance
205//-----------------------------------------------------------------------------
206Chuck_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//-----------------------------------------------------------------------------
224void 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//-----------------------------------------------------------------------------
244void 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//-----------------------------------------------------------------------------
270Chuck_VM_Alloc::Chuck_VM_Alloc()
271{ }
272
273
274
275
276//-----------------------------------------------------------------------------
277// name: ~Chuck_VM_Alloc()
278// desc: destructor
279//-----------------------------------------------------------------------------
280Chuck_VM_Alloc::~Chuck_VM_Alloc()
281{ }
282
283
284
285
286//-----------------------------------------------------------------------------
287// name: Chuck_Object()
288// desc: constructor
289//-----------------------------------------------------------------------------
290Chuck_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//-----------------------------------------------------------------------------
312Chuck_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//-----------------------------------------------------------------------------
344Chuck_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//-----------------------------------------------------------------------------
364Chuck_Array4::~Chuck_Array4()
365{
366 // do nothing
367}
368
369
370
371
372//-----------------------------------------------------------------------------
373// name: addr()
374// desc: ...
375//-----------------------------------------------------------------------------
376t_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//-----------------------------------------------------------------------------
393t_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//-----------------------------------------------------------------------------
406t_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//-----------------------------------------------------------------------------
426t_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//-----------------------------------------------------------------------------
446t_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//-----------------------------------------------------------------------------
475t_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//-----------------------------------------------------------------------------
500t_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//-----------------------------------------------------------------------------
512t_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//-----------------------------------------------------------------------------
534t_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//-----------------------------------------------------------------------------
554t_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//-----------------------------------------------------------------------------
584t_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//-----------------------------------------------------------------------------
603void 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//-----------------------------------------------------------------------------
619t_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//-----------------------------------------------------------------------------
637t_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//-----------------------------------------------------------------------------
671void 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