Unified · Split
| @@ -0,0 +1,328 @@ | |||
| 1 | |||
| 2 | |||
| 3 | D [0-9] | ||
| 4 | L [a-zA-Z_] | ||
| 5 | H [a-fA-F0-9] | ||
| 6 | E [Ee][+-]?{D}+ | ||
| 7 | FS (f|F|l|L) | ||
| 8 | IS (u|U|l|L)* | ||
| 9 | |||
| 10 | %{ | ||
| 11 | /*---------------------------------------------------------------------------- | ||
| 12 | ChucK Concurrent, On-the-fly Audio Programming Language | ||
| 13 | Compiler and Virtual Machine | ||
| 14 | |||
| 15 | Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. | ||
| 16 | http://chuck.cs.princeton.edu/ | ||
| 17 | http://soundlab.cs.princeton.edu/ | ||
| 18 | |||
| 19 | This program is free software; you can redistribute it and/or modify | ||
| 20 | it under the terms of the GNU General Public License as published by | ||
| 21 | the Free Software Foundation; either version 2 of the License, or | ||
| 22 | (at your option) any later version. | ||
| 23 | |||
| 24 | This program is distributed in the hope that it will be useful, | ||
| 25 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 26 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 27 | GNU General Public License for more details. | ||
| 28 | |||
| 29 | You should have received a copy of the GNU General Public License | ||
| 30 | along with this program; if not, write to the Free Software | ||
| 31 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
| 32 | U.S.A. | ||
| 33 | -----------------------------------------------------------------------------*/ | ||
| 34 | |||
| 35 | //----------------------------------------------------------------------------- | ||
| 36 | // file: chuck.yy.c | ||
| 37 | // desc: chuck lexer | ||
| 38 | // | ||
| 39 | // author: Ge Wang (gewang.cs.princeton.edu) - generated by lex | ||
| 40 | // Perry R. Cook (prc@cs.princeton.edu) | ||
| 41 | // | ||
| 42 | // based on the ansi C grammar by Jeff Lee, maintained by Jutta Degener | ||
| 43 | // | ||
| 44 | // date: Summer 2002 | ||
| 45 | //----------------------------------------------------------------------------- | ||
| 46 | |||
| 47 | #include <stdlib.h> | ||
| 48 | #include <string.h> | ||
| 49 | #include "chuck_utils.h" | ||
| 50 | #include "chuck_absyn.h" | ||
| 51 | #include "chuck_errmsg.h" | ||
| 52 | |||
| 53 | #ifndef __PLATFORM_WIN32__ | ||
| 54 | #include "chuck.tab.h" | ||
| 55 | #else | ||
| 56 | #include "chuck_win32.h" | ||
| 57 | #endif | ||
| 58 | |||
| 59 | |||
| 60 | |||
| 61 | // globals | ||
| 62 | extern YYSTYPE yylval; | ||
| 63 | int char_pos = 1; | ||
| 64 | |||
| 65 | // define error handling | ||
| 66 | #define YY_FATAL_ERROR(msg) EM_error2( 0, msg ) | ||
| 67 | |||
| 68 | #if defined(_cplusplus) || defined(__cplusplus) | ||
| 69 | extern "C" { | ||
| 70 | #endif | ||
| 71 | |||
| 72 | int yywrap(void); | ||
| 73 | void adjust(); | ||
| 74 | c_str strip_lit( c_str str ); | ||
| 75 | c_str alloc_str( c_str str ); | ||
| 76 | long htol( c_str str ); | ||
| 77 | int comment(); | ||
| 78 | int block_comment(); | ||
| 79 | |||
| 80 | #if defined(_cplusplus) || defined(__cplusplus) | ||
| 81 | } | ||
| 82 | #endif | ||
| 83 | |||
| 84 | // yywrap() | ||
| 85 | int yywrap( void ) | ||
| 86 | { | ||
| 87 | char_pos = 1; | ||
| 88 | return 1; | ||
| 89 | } | ||
| 90 | |||
| 91 | // adjust() | ||
| 92 | void adjust() | ||
| 93 | { | ||
| 94 | EM_tokPos = char_pos; | ||
| 95 | char_pos += yyleng; | ||
| 96 | } | ||
| 97 | |||
| 98 | // strip | ||
| 99 | c_str strip_lit( c_str str ) | ||
| 100 | { | ||
| 101 | str[strlen(str)-1] = '\0'; | ||
| 102 | return str+1; | ||
| 103 | } | ||
| 104 | |||
| 105 | // alloc_str() | ||
| 106 | c_str alloc_str( c_str str ) | ||
| 107 | { | ||
| 108 | c_str s = (c_str)malloc( strlen(str) + 1 ); | ||
| 109 | strcpy( s, str ); | ||
| 110 | |||
| 111 | return s; | ||
| 112 | } | ||
| 113 | |||
| 114 | // to long | ||
| 115 | long htol( c_str str ) | ||
| 116 | { | ||
| 117 | char * c = str; | ||
| 118 | unsigned long n = 0; | ||
| 119 | |||
| 120 | // skip over 0x | ||
| 121 | c += 2; | ||
| 122 | while( *c ) | ||
| 123 | { | ||
| 124 | n <<= 4; | ||
| 125 | switch( *c ) | ||
| 126 | { | ||
| 127 | case '1': case '2': case '3': case '4': case '5': | ||
| 128 | case '6': case '7': case '8': case '9': case '0': | ||
| 129 | n += *c - '0'; | ||
| 130 | break; | ||
| 131 | |||
| 132 | case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': | ||
| 133 | n += *c - 'a' + 10; | ||
| 134 | break; | ||
| 135 | |||
| 136 | case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': | ||
| 137 | n += *c - 'A' + 10; | ||
| 138 | break; | ||
| 139 | } | ||
| 140 | c++; | ||
| 141 | } | ||
| 142 | |||
| 143 | return n; | ||
| 144 | } | ||
| 145 | |||
| 146 | |||
| 147 | |||
| 148 | // block comment hack (thanks to unput/yytext_ptr inconsistency) | ||
| 149 | #define block_comment_hack loop: \ | ||
| 150 | while ((c = input()) != '*' && c != 0 && c != EOF ) \ | ||
| 151 | if( c == '\n' ) EM_newline(); \ | ||
| 152 | if( c == EOF ) adjust(); \ | ||
| 153 | else if( (c1 = input()) != '/' && c != 0 ) \ | ||
| 154 | { \ | ||
| 155 | unput(c1); \ | ||
| 156 | goto loop; \ | ||
| 157 | } \ | ||
| 158 | if( c != 0 ) adjust(); | ||
| 159 | |||
| 160 | // comment hack | ||
| 161 | #define comment_hack \ | ||
| 162 | while ((c = input()) != '\n' && c != '\r' && c != 0 && c != EOF ); \ | ||
| 163 | if (c != 0) { \ | ||
| 164 | adjust(); \ | ||
| 165 | if (c == '\n') EM_newline(); \ | ||
| 166 | } | ||
| 167 | |||
| 168 | // .*\-\-> { adjust(); continue; } | ||
| 169 | |||
| 170 | %} | ||
| 171 | |||
| 172 | %% | ||
| 173 | |||
| 174 | "//" { char c; adjust(); comment_hack; continue; } | ||
| 175 | "<--" { char c; adjust(); comment_hack; continue; } | ||
| 176 | "/*" { char c, c1; adjust(); block_comment_hack; continue; } | ||
| 177 | " " { adjust(); continue; } | ||
| 178 | "\t" { adjust(); continue; } | ||
| 179 | "\r\n" { adjust(); EM_newline(); continue; } | ||
| 180 | "\n" { adjust(); EM_newline(); continue; } | ||
| 181 | |||
| 182 | "++" { adjust(); return PLUSPLUS; } | ||
| 183 | "--" { adjust(); return MINUSMINUS; } | ||
| 184 | "#(" { adjust(); return POUNDPAREN; } | ||
| 185 | "%(" { adjust(); return PERCENTPAREN; } | ||
| 186 | "@(" { adjust(); return ATPAREN; } | ||
| 187 | |||
| 188 | "," { adjust(); return COMMA; } | ||
| 189 | ":" { adjust(); return COLON; } | ||
| 190 | "." { adjust(); return DOT; } | ||
| 191 | "+" { adjust(); return PLUS; } | ||
| 192 | "-" { adjust(); return MINUS; } | ||
| 193 | "*" { adjust(); return TIMES; } | ||
| 194 | "/" { adjust(); return DIVIDE; } | ||
| 195 | "%" { adjust(); return PERCENT; } | ||
| 196 | "#" { adjust(); return POUND; } | ||
| 197 | "$" { adjust(); return DOLLAR; } | ||
| 198 | |||
| 199 | "::" { adjust(); return COLONCOLON; } | ||
| 200 | "==" { adjust(); return EQ; } | ||
| 201 | "!=" { adjust(); return NEQ; } | ||
| 202 | "<" { adjust(); return LT; } | ||
| 203 | ">" { adjust(); return GT; } | ||
| 204 | "<=" { adjust(); return LE; } | ||
| 205 | ">=" { adjust(); return GE; } | ||
| 206 | "&&" { adjust(); return AND; } | ||
| 207 | "||" { adjust(); return OR; } | ||
| 208 | "&" { adjust(); return S_AND; } | ||
| 209 | "|" { adjust(); return S_OR; } | ||
| 210 | "^" { adjust(); return S_XOR; } | ||
| 211 | ">>" { adjust(); return SHIFT_RIGHT; } | ||
| 212 | "<<" { adjust(); return SHIFT_LEFT; } | ||
| 213 | "=" { adjust(); return ASSIGN; } | ||
| 214 | "(" { adjust(); return LPAREN; } | ||
| 215 | ")" { adjust(); return RPAREN; } | ||
| 216 | "[" { adjust(); return LBRACK; } | ||
| 217 | "]" { adjust(); return RBRACK; } | ||
| 218 | "{" { adjust(); return LBRACE; } | ||
| 219 | "}" { adjust(); return RBRACE; } | ||
| 220 | ";" { adjust(); return SEMICOLON; } | ||
| 221 | "?" { adjust(); return QUESTION; } | ||
| 222 | "!" { adjust(); return EXCLAMATION; } | ||
| 223 | "~" { adjust(); return TILDA; } | ||
| 224 | for { adjust(); return FOR; } | ||
| 225 | while { adjust(); return WHILE; } | ||
| 226 | until { adjust(); return UNTIL; } | ||
| 227 | repeat { adjust(); return LOOP; } | ||
| 228 | continue { adjust(); return CONTINUE; } | ||
| 229 | break { adjust(); return BREAK; } | ||
| 230 | if { adjust(); return IF; } | ||
| 231 | else { adjust(); return ELSE; } | ||
| 232 | do { adjust(); return DO; } | ||
| 233 | "<<<" { adjust(); return L_HACK; } | ||
| 234 | ">>>" { adjust(); return R_HACK; } | ||
| 235 | |||
| 236 | return { adjust(); return RETURN; } | ||
| 237 | |||
| 238 | function { adjust(); return FUNCTION; } | ||
| 239 | fun { adjust(); return FUNCTION; } | ||
| 240 | new { adjust(); return NEW; } | ||
| 241 | class { adjust(); return CLASS; } | ||
| 242 | interface { adjust(); return INTERFACE; } | ||
| 243 | extends { adjust(); return EXTENDS; } | ||
| 244 | implements { adjust(); return IMPLEMENTS; } | ||
| 245 | public { adjust(); return PUBLIC; } | ||
| 246 | protected { adjust(); return PROTECTED; } | ||
| 247 | private { adjust(); return PRIVATE; } | ||
| 248 | static { adjust(); return STATIC; } | ||
| 249 | pure { adjust(); return ABSTRACT; } | ||
| 250 | const { adjust(); return CONST; } | ||
| 251 | spork { adjust(); return SPORK; } | ||
| 252 | typeof { adjust(); return TYPEOF; } | ||
| 253 | |||
| 254 | "=>" { adjust(); return CHUCK; } | ||
| 255 | "=<" { adjust(); return UNCHUCK; } | ||
| 256 | "!=>" { adjust(); return UNCHUCK; } | ||
| 257 | "=^" { adjust(); return UPCHUCK; } | ||
| 258 | "@=>" { adjust(); return AT_CHUCK; } | ||
| 259 | "+=>" { adjust(); return PLUS_CHUCK; } | ||
| 260 | "-=>" { adjust(); return MINUS_CHUCK; } | ||
| 261 | "*=>" { adjust(); return TIMES_CHUCK; } | ||
| 262 | "/=>" { adjust(); return DIVIDE_CHUCK; } | ||
| 263 | "&=>" { adjust(); return S_AND_CHUCK; } | ||
| 264 | "|=>" { adjust(); return S_OR_CHUCK; } | ||
| 265 | "^=>" { adjust(); return S_XOR_CHUCK; } | ||
| 266 | ">>=>" { adjust(); return SHIFT_RIGHT_CHUCK; } | ||
| 267 | "<<=>" { adjust(); return SHIFT_LEFT_CHUCK; } | ||
| 268 | "%=>" { adjust(); return PERCENT_CHUCK; } | ||
| 269 | "@" { adjust(); return AT_SYM; } | ||
| 270 | "@@" { adjust(); return ATAT_SYM; } | ||
| 271 | "->" { adjust(); return ARROW_RIGHT; } | ||
| 272 | "<-" { adjust(); return ARROW_LEFT; } | ||
| 273 | |||
| 274 | 0[xX][0-9a-fA-F]+{IS}? { adjust(); yylval.ival=htol(yytext); return NUM; } | ||
| 275 | 0[cC][0-7]+{IS}? { adjust(); yylval.ival=atoi(yytext); return NUM; } | ||
| 276 | [0-9]+{IS}? { adjust(); yylval.ival=atoi(yytext); return NUM; } | ||
| 277 | ([0-9]+"."[0-9]*)|([0-9]*"."[0-9]+) { adjust(); yylval.fval=atof(yytext); return FLOAT; } | ||
| 278 | [A-Za-z_][A-Za-z0-9_]* { adjust(); yylval.sval=alloc_str(yytext); return ID; } | ||
| 279 | \"(\\.|[^\\"])*\" { adjust(); yylval.sval=alloc_str(strip_lit(yytext)); return STRING_LIT; } | ||
| 280 | `(\\.|[^\\`])*` { adjust(); yylval.sval=alloc_str(strip_lit(yytext)); return STRING_LIT; } | ||
| 281 | '(\\.|[^\\'])' { adjust(); yylval.sval=alloc_str(strip_lit(yytext)); return CHAR_LIT; } | ||
| 282 | |||
| 283 | . { adjust(); EM_error( EM_tokPos, "illegal token" ); } | ||
| 284 | |||
| 285 | %% | ||
| 286 | |||
| 287 | /* | ||
| 288 | // comment | ||
| 289 | int comment() | ||
| 290 | { | ||
| 291 | char c; | ||
| 292 | |||
| 293 | while ((c = yyinput()) != '\n' && c != '\r' && c != 0 && c != EOF ); | ||
| 294 | |||
| 295 | if (c != 0) { | ||
| 296 | adjust(); | ||
| 297 | if (c == '\n') EM_newline(); | ||
| 298 | } | ||
| 299 | |||
| 300 | return 0; | ||
| 301 | } | ||
| 302 | |||
| 303 | // block comment | ||
| 304 | int block_comment() | ||
| 305 | { | ||
| 306 | char c, c1; | ||
| 307 | |||
| 308 | loop: | ||
| 309 | while ((c = yyinput()) != '*' && c != 0 && c != EOF ) | ||
| 310 | if( c == '\n' ) EM_newline(); | ||
| 311 | |||
| 312 | if( c == EOF ) | ||
| 313 | { | ||
| 314 | adjust(); | ||
| 315 | return 1; | ||
| 316 | } | ||
| 317 | |||
| 318 | if( (c1 = yyinput()) != '/' && c != 0 ) | ||
| 319 | { | ||
| 320 | unput(c1); | ||
| 321 | goto loop; | ||
| 322 | } | ||
| 323 | |||
| 324 | if( c != 0 ) adjust(); | ||
| 325 | |||
| 326 | return 0; | ||
| 327 | } | ||
| 328 | */ | ||
| @@ -0,0 +1,600 @@ | |||
| 1 | %{ | ||
| 2 | |||
| 3 | /*---------------------------------------------------------------------------- | ||
| 4 | ChucK Concurrent, On-the-fly Audio Programming Language | ||
| 5 | Compiler and Virtual Machine | ||
| 6 | |||
| 7 | Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. | ||
| 8 | http://chuck.cs.princeton.edu/ | ||
| 9 | http://soundlab.cs.princeton.edu/ | ||
| 10 | |||
| 11 | This program is free software; you can redistribute it and/or modify | ||
| 12 | it under the terms of the GNU General Public License as published by | ||
| 13 | the Free Software Foundation; either version 2 of the License, or | ||
| 14 | (at your option) any later version. | ||
| 15 | |||
| 16 | This program is distributed in the hope that it will be useful, | ||
| 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | GNU General Public License for more details. | ||
| 20 | |||
| 21 | You should have received a copy of the GNU General Public License | ||
| 22 | along with this program; if not, write to the Free Software | ||
| 23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
| 24 | U.S.A. | ||
| 25 | -----------------------------------------------------------------------------*/ | ||
| 26 | |||
| 27 | //----------------------------------------------------------------------------- | ||
| 28 | // file: chuck.tab.c | ||
| 29 | // desc: chuck parser | ||
| 30 | // | ||
| 31 | // author: Ge Wang (gewang@cs.princeton.edu) - generated by yacc | ||
| 32 | // Perry R. Cook (prc@cs.princeton.edu) | ||
| 33 | // | ||
| 34 | // based in part on the ansi C grammar by Jeff Lee, maintained by Jutta Degener | ||
| 35 | // | ||
| 36 | // date: Summer 2002 | ||
| 37 | //----------------------------------------------------------------------------- | ||
| 38 | #include <stdio.h> | ||
| 39 | #include <string.h> | ||
| 40 | #include <stdlib.h> | ||
| 41 | #include "chuck_utils.h" | ||
| 42 | #include "chuck_errmsg.h" | ||
| 43 | #include "chuck_absyn.h" | ||
| 44 | |||
| 45 | // function | ||
| 46 | int yylex( void ); | ||
| 47 | |||
| 48 | void yyerror( char *s ) | ||
| 49 | { | ||
| 50 | EM_error( EM_tokPos, "%s", s ); | ||
| 51 | } | ||
| 52 | |||
| 53 | a_Program g_program = NULL; | ||
| 54 | |||
| 55 | %} | ||
| 56 | |||
| 57 | |||
| 58 | %union | ||
| 59 | { | ||
| 60 | int pos; | ||
| 61 | int ival; | ||
| 62 | double fval; | ||
| 63 | c_str sval; | ||
| 64 | |||
| 65 | a_Program program; | ||
| 66 | a_Section program_section; | ||
| 67 | a_Stmt_List stmt_list; | ||
| 68 | a_Class_Def class_def; | ||
| 69 | a_Class_Ext class_ext; | ||
| 70 | a_Class_Body class_body; | ||
| 71 | a_Stmt stmt; | ||
| 72 | a_Exp exp; | ||
| 73 | a_Func_Def func_def; | ||
| 74 | a_Var_Decl_List var_decl_list; | ||
| 75 | a_Var_Decl var_decl; | ||
| 76 | a_Type_Decl type_decl; | ||
| 77 | a_Arg_List arg_list; | ||
| 78 | a_Id_List id_list; | ||
| 79 | a_Array_Sub array_sub; | ||
| 80 | a_Complex complex_exp; | ||
| 81 | a_Polar polar_exp; | ||
| 82 | a_Vec vec_exp; // ge: added 1.3.5.3 | ||
| 83 | }; | ||
| 84 | |||
| 85 | // expect shift/reduce conflicts | ||
| 86 | // 1.3.3.0: changed to 38 for char literal - spencer | ||
| 87 | // 1.3.5.3: changed to 39 for vec literal | ||
| 88 | %expect 39 | ||
| 89 | |||
| 90 | %token <sval> ID STRING_LIT CHAR_LIT | ||
| 91 | %token <ival> NUM | ||
| 92 | %token <fval> FLOAT | ||
| 93 | |||
| 94 | %token | ||
| 95 | POUND COMMA COLON SEMICOLON LPAREN RPAREN | ||
| 96 | LBRACK RBRACK LBRACE RBRACE DOT | ||
| 97 | PLUS MINUS TIMES DIVIDE PERCENT | ||
| 98 | EQ NEQ LT LE GT GE AND OR ASSIGN | ||
| 99 | IF THEN ELSE WHILE FOR DO LOOP | ||
| 100 | BREAK CONTINUE NULL_TOK FUNCTION RETURN | ||
| 101 | QUESTION EXCLAMATION S_OR S_AND S_XOR | ||
| 102 | PLUSPLUS MINUSMINUS DOLLAR POUNDPAREN PERCENTPAREN ATPAREN | ||
| 103 | SIMULT PATTERN CODE TRANSPORT HOST | ||
| 104 | TIME WHENEVER NEXT UNTIL EVERY BEFORE | ||
| 105 | AFTER AT AT_SYM ATAT_SYM NEW SIZEOF TYPEOF | ||
| 106 | SAME PLUS_CHUCK MINUS_CHUCK TIMES_CHUCK | ||
| 107 | DIVIDE_CHUCK S_AND_CHUCK S_OR_CHUCK | ||
| 108 | S_XOR_CHUCK SHIFT_RIGHT_CHUCK | ||
| 109 | SHIFT_LEFT_CHUCK PERCENT_CHUCK | ||
| 110 | SHIFT_RIGHT SHIFT_LEFT TILDA CHUCK | ||
| 111 | COLONCOLON S_CHUCK AT_CHUCK LEFT_S_CHUCK | ||
| 112 | UNCHUCK UPCHUCK CLASS INTERFACE EXTENDS IMPLEMENTS | ||
| 113 | PUBLIC PROTECTED PRIVATE STATIC ABSTRACT CONST | ||
| 114 | SPORK ARROW_RIGHT ARROW_LEFT L_HACK R_HACK | ||
| 115 | |||
| 116 | |||
| 117 | %type <program> program | ||
| 118 | %type <program_section> program_section | ||
| 119 | %type <stmt> code_segment | ||
| 120 | %type <func_def> function_definition | ||
| 121 | %type <class_def> class_definition | ||
| 122 | %type <class_body> class_body | ||
| 123 | %type <class_body> class_body2 | ||
| 124 | %type <class_ext> class_ext | ||
| 125 | %type <ival> class_decl | ||
| 126 | %type <class_ext> iface_ext | ||
| 127 | %type <program_section> class_section | ||
| 128 | %type <stmt_list> statement_list | ||
| 129 | %type <stmt> statement | ||
| 130 | //%type <stmt_label> label_statement | ||
| 131 | %type <stmt> loop_statement | ||
| 132 | %type <stmt> selection_statement | ||
| 133 | %type <stmt> jump_statement | ||
| 134 | %type <stmt> expression_statement | ||
| 135 | %type <exp> expression | ||
| 136 | %type <exp> chuck_expression | ||
| 137 | %type <exp> arrow_expression | ||
| 138 | %type <exp> conditional_expression | ||
| 139 | %type <exp> logical_or_expression | ||
| 140 | %type <exp> logical_and_expression | ||
| 141 | %type <exp> inclusive_or_expression | ||
| 142 | %type <exp> exclusive_or_expression | ||
| 143 | %type <exp> and_expression | ||
| 144 | %type <exp> equality_expression | ||
| 145 | %type <exp> relational_expression | ||
| 146 | %type <exp> shift_expression | ||
| 147 | %type <exp> additive_expression | ||
| 148 | %type <exp> multiplicative_expression | ||
| 149 | %type <exp> tilda_expression | ||
| 150 | %type <exp> cast_expression | ||
| 151 | %type <exp> unary_expression | ||
| 152 | %type <exp> dur_expression | ||
| 153 | %type <exp> postfix_expression | ||
| 154 | %type <exp> primary_expression | ||
| 155 | %type <exp> decl_expression | ||
| 156 | %type <ival> unary_operator | ||
| 157 | %type <ival> chuck_operator | ||
| 158 | %type <ival> arrow_operator | ||
| 159 | %type <var_decl_list> var_decl_list | ||
| 160 | %type <var_decl> var_decl | ||
| 161 | %type <type_decl> type_decl_a | ||
| 162 | %type <type_decl> type_decl_b | ||
| 163 | %type <type_decl> type_decl | ||
| 164 | %type <type_decl> type_decl2 | ||
| 165 | %type <ival> function_decl | ||
| 166 | %type <ival> static_decl | ||
| 167 | %type <arg_list> arg_list | ||
| 168 | %type <id_list> id_list | ||
| 169 | %type <id_list> id_dot | ||
| 170 | %type <array_sub> array_exp | ||
| 171 | %type <array_sub> array_empty | ||
| 172 | %type <complex_exp> complex_exp | ||
| 173 | %type <polar_exp> polar_exp | ||
| 174 | %type <vec_exp> vec_exp // ge: added 1.3.5.3 | ||
| 175 | |||
| 176 | %start program | ||
| 177 | |||
| 178 | %% | ||
| 179 | |||
| 180 | program | ||
| 181 | : program_section { $$ = g_program = new_program( $1, EM_lineNum ); } | ||
| 182 | | program_section program { $$ = g_program = prepend_program( $1, $2, EM_lineNum ); } | ||
| 183 | ; | ||
| 184 | |||
| 185 | program_section | ||
| 186 | : statement_list { $$ = new_section_stmt( $1, EM_lineNum ); } | ||
| 187 | | function_definition { $$ = new_section_func_def( $1, EM_lineNum ); } | ||
| 188 | | class_definition { $$ = new_section_class_def( $1, EM_lineNum ); } | ||
| 189 | ; | ||
| 190 | |||
| 191 | class_definition | ||
| 192 | : class_decl CLASS id_list LBRACE class_body RBRACE | ||
| 193 | { $$ = new_class_def( $1, $3, NULL, $5, EM_lineNum ); } | ||
| 194 | | class_decl CLASS id_list class_ext LBRACE class_body RBRACE | ||
| 195 | { $$ = new_class_def( $1, $3, $4, $6, EM_lineNum ); } | ||
| 196 | | class_decl INTERFACE id_list LBRACE class_body RBRACE | ||
| 197 | { $$ = new_iface_def( $1, $3, NULL, $5, EM_lineNum ); } | ||
| 198 | | class_decl INTERFACE id_list iface_ext LBRACE class_body RBRACE | ||
| 199 | { $$ = new_iface_def( $1, $3, $4, $6, EM_lineNum ); } | ||
| 200 | ; | ||
| 201 | |||
| 202 | class_ext | ||
| 203 | : IMPLEMENTS id_list { $$ = new_class_ext( NULL, $2, EM_lineNum ); } | ||
| 204 | | IMPLEMENTS id_list EXTENDS id_dot { $$ = new_class_ext( $4, $2, EM_lineNum ); } | ||
| 205 | | EXTENDS id_dot { $$ = new_class_ext( $2, NULL, EM_lineNum ); } | ||
| 206 | | EXTENDS id_dot IMPLEMENTS id_list { $$ = new_class_ext( $2, $4, EM_lineNum ); } | ||
| 207 | ; | ||
| 208 | |||
| 209 | class_body | ||
| 210 | : class_body2 { $$ = $1; } | ||
| 211 | | { $$ = NULL; } | ||
| 212 | ; | ||
| 213 | |||
| 214 | class_body2 | ||
| 215 | : class_section { $$ = new_class_body( $1, EM_lineNum ); } | ||
| 216 | | class_section class_body2 { $$ = prepend_class_body( $1, $2, EM_lineNum ); } | ||
| 217 | ; | ||
| 218 | |||
| 219 | |||
| 220 | class_section | ||
| 221 | : statement_list { $$ = new_section_stmt( $1, EM_lineNum ); } | ||
| 222 | | function_definition { $$ = new_section_func_def( $1, EM_lineNum ); } | ||
| 223 | | class_definition { $$ = new_section_class_def( $1, EM_lineNum ); } | ||
| 224 | ; | ||
| 225 | |||
| 226 | iface_ext | ||
| 227 | : EXTENDS id_list { $$ = new_class_ext( NULL, $2, EM_lineNum ); } | ||
| 228 | ; | ||
| 229 | |||
| 230 | id_list | ||
| 231 | : ID { $$ = new_id_list( $1, EM_lineNum ); } | ||
| 232 | | ID COMMA id_list { $$ = prepend_id_list( $1, $3, EM_lineNum ); } | ||
| 233 | ; | ||
| 234 | |||
| 235 | id_dot | ||
| 236 | : ID { $$ = new_id_list( $1, EM_lineNum ); } | ||
| 237 | | ID DOT id_dot { $$ = prepend_id_list( $1, $3, EM_lineNum ); } | ||
| 238 | ; | ||
| 239 | |||
| 240 | function_definition | ||
| 241 | : function_decl static_decl type_decl2 ID LPAREN arg_list RPAREN code_segment | ||
| 242 | { $$ = new_func_def( $1, $2, $3, $4, $6, $8, EM_lineNum ); } | ||
| 243 | | function_decl static_decl type_decl2 ID LPAREN RPAREN code_segment | ||
| 244 | { $$ = new_func_def( $1, $2, $3, $4, NULL, $7, EM_lineNum ); } | ||
| 245 | | function_decl static_decl type_decl2 ID LPAREN arg_list RPAREN SEMICOLON | ||
| 246 | { $$ = new_func_def( $1, $2, $3, $4, $6, NULL, EM_lineNum ); } | ||
| 247 | | function_decl static_decl type_decl2 ID LPAREN RPAREN SEMICOLON | ||
| 248 | { $$ = new_func_def( $1, $2, $3, $4, NULL, NULL, EM_lineNum ); } | ||
| 249 | ; | ||
| 250 | |||
| 251 | class_decl | ||
| 252 | : PUBLIC { $$ = ae_key_public; } | ||
| 253 | | PRIVATE { $$ = ae_key_private; } | ||
| 254 | | { $$ = ae_key_private; } | ||
| 255 | ; | ||
| 256 | |||
| 257 | function_decl | ||
| 258 | : FUNCTION { $$ = ae_key_func; } | ||
| 259 | | PUBLIC { $$ = ae_key_public; } | ||
| 260 | | PROTECTED { $$ = ae_key_protected; } | ||
| 261 | | PRIVATE { $$ = ae_key_private; } | ||
| 262 | ; | ||
| 263 | |||
| 264 | static_decl | ||
| 265 | : STATIC { $$ = ae_key_static; } | ||
| 266 | | ABSTRACT { $$ = ae_key_abstract; } | ||
| 267 | | { $$ = ae_key_instance; } | ||
| 268 | ; | ||
| 269 | |||
| 270 | type_decl_a | ||
| 271 | : ID { $$ = new_type_decl( new_id_list( $1, EM_lineNum ), 0, EM_lineNum ); } | ||
| 272 | | ID AT_SYM { $$ = new_type_decl( new_id_list( $1, EM_lineNum ), 1, EM_lineNum ); } | ||
| 273 | ; | ||
| 274 | |||
| 275 | type_decl_b | ||
| 276 | : LT id_dot GT { $$ = new_type_decl( $2, 0, EM_lineNum ); } | ||
| 277 | | LT id_dot GT AT_SYM { $$ = new_type_decl( $2, 1, EM_lineNum ); } | ||
| 278 | ; | ||
| 279 | |||
| 280 | //type_decl_c | ||
| 281 | // : LPAREN id_dot RPAREN { $$ = new_type_decl( $3, 0, EM_lineNum ); } | ||
| 282 | // // | LPAREN id_dot RPAREN AT_SYM { $$ = new_type_decl( $1, 1, EM_lineNum ); } | ||
| 283 | // ; | ||
| 284 | |||
| 285 | type_decl | ||
| 286 | : type_decl_a { $$ = $1; } | ||
| 287 | | type_decl_b { $$ = $1; } | ||
| 288 | // | type_decl_c { $$ = $1; } | ||
| 289 | ; | ||
| 290 | |||
| 291 | type_decl2 | ||
| 292 | : type_decl { $$ = $1; } | ||
| 293 | | type_decl array_empty { $$ = add_type_decl_array( $1, $2, EM_lineNum ); } | ||
| 294 | ; | ||
| 295 | |||
| 296 | arg_list | ||
| 297 | : type_decl var_decl { $$ = new_arg_list( $1, $2, EM_lineNum ); } | ||
| 298 | | type_decl var_decl COMMA arg_list { $$ = prepend_arg_list( $1, $2, $4, EM_lineNum ); } | ||
| 299 | ; | ||
| 300 | |||
| 301 | statement_list | ||
| 302 | : statement { $$ = new_stmt_list( $1, EM_lineNum ); } | ||
| 303 | | statement statement_list { $$ = prepend_stmt_list( $1, $2, EM_lineNum ); } | ||
| 304 | ; | ||
| 305 | |||
| 306 | statement | ||
| 307 | : expression_statement { $$ = $1; } | ||
| 308 | | loop_statement { $$ = $1; } | ||
| 309 | | selection_statement { $$ = $1; } | ||
| 310 | | jump_statement { $$ = $1; } | ||
| 311 | // | label_statement { } | ||
| 312 | | code_segment { $$ = $1; } | ||
| 313 | ; | ||
| 314 | |||
| 315 | jump_statement | ||
| 316 | : RETURN SEMICOLON { $$ = new_stmt_from_return( NULL, EM_lineNum ); } | ||
| 317 | | RETURN expression SEMICOLON { $$ = new_stmt_from_return( $2, EM_lineNum ); } | ||
| 318 | | BREAK SEMICOLON { $$ = new_stmt_from_break( EM_lineNum ); } | ||
| 319 | | CONTINUE SEMICOLON { $$ = new_stmt_from_continue( EM_lineNum ); } | ||
| 320 | ; | ||
| 321 | |||
| 322 | selection_statement | ||
| 323 | : IF LPAREN expression RPAREN statement | ||
| 324 | { $$ = new_stmt_from_if( $3, $5, NULL, EM_lineNum ); } | ||
| 325 | | IF LPAREN expression RPAREN statement ELSE statement | ||
| 326 | { $$ = new_stmt_from_if( $3, $5, $7, EM_lineNum ); } | ||
| 327 | ; | ||
| 328 | |||
| 329 | loop_statement | ||
| 330 | : WHILE LPAREN expression RPAREN statement | ||
| 331 | { $$ = new_stmt_from_while( $3, $5, EM_lineNum ); } | ||
| 332 | | DO statement WHILE LPAREN expression RPAREN SEMICOLON | ||
| 333 | { $$ = new_stmt_from_do_while( $5, $2, EM_lineNum ); } | ||
| 334 | | FOR LPAREN expression_statement expression_statement RPAREN statement | ||
| 335 | { $$ = new_stmt_from_for( $3, $4, NULL, $6, EM_lineNum ); } | ||
| 336 | | FOR LPAREN expression_statement expression_statement expression RPAREN statement | ||
| 337 | { $$ = new_stmt_from_for( $3, $4, $5, $7, EM_lineNum ); } | ||
| 338 | | UNTIL LPAREN expression RPAREN statement | ||
| 339 | { $$ = new_stmt_from_until( $3, $5, EM_lineNum ); } | ||
| 340 | | DO statement UNTIL LPAREN expression RPAREN SEMICOLON | ||
| 341 | { $$ = new_stmt_from_do_until( $5, $2, EM_lineNum ); } | ||
| 342 | | LOOP LPAREN expression RPAREN statement | ||
| 343 | { $$ = new_stmt_from_loop( $3, $5, EM_lineNum ); } | ||
| 344 | ; | ||
| 345 | |||
| 346 | code_segment | ||
| 347 | : LBRACE RBRACE { $$ = new_stmt_from_code( NULL, EM_lineNum ); } | ||
| 348 | | LBRACE statement_list RBRACE { $$ = new_stmt_from_code( $2, EM_lineNum ); } | ||
| 349 | ; | ||
| 350 | |||
| 351 | expression_statement | ||
| 352 | : SEMICOLON { $$ = NULL; } | ||
| 353 | | expression SEMICOLON { $$ = new_stmt_from_expression( $1, EM_lineNum ); } | ||
| 354 | ; | ||
| 355 | |||
| 356 | expression | ||
| 357 | : chuck_expression { $$ = $1; } | ||
| 358 | | chuck_expression COMMA expression { $$ = prepend_expression( $1, $3, EM_lineNum ); } | ||
| 359 | ; | ||
| 360 | |||
| 361 | chuck_expression | ||
| 362 | : arrow_expression { $$ = $1; } | ||
| 363 | | chuck_expression chuck_operator arrow_expression | ||
| 364 | { $$ = new_exp_from_binary( $1, $2, $3, EM_lineNum ); } | ||
| 365 | ; | ||
| 366 | |||
| 367 | arrow_expression | ||
| 368 | : decl_expression { $$ = $1; } | ||
| 369 | | arrow_expression arrow_operator decl_expression | ||
| 370 | { $$ = new_exp_from_binary( $1, $2, $3, EM_lineNum ); } | ||
| 371 | ; | ||
| 372 | |||
| 373 | array_exp | ||
| 374 | : LBRACK expression RBRACK { $$ = new_array_sub( $2, EM_lineNum ); } | ||
| 375 | | LBRACK expression RBRACK array_exp | ||
| 376 | { $$ = prepend_array_sub( $4, $2, EM_lineNum ); } | ||
| 377 | ; | ||
| 378 | |||
| 379 | array_empty | ||
| 380 | : LBRACK RBRACK { $$ = new_array_sub( NULL, EM_lineNum ); } | ||
| 381 | | array_empty LBRACK RBRACK { $$ = prepend_array_sub( $1, NULL, EM_lineNum ); } | ||
| 382 | ; | ||
| 383 | |||
| 384 | decl_expression | ||
| 385 | : conditional_expression { $$ = $1; } | ||
| 386 | | type_decl var_decl_list { $$ = new_exp_decl( $1, $2, 0, EM_lineNum ); } | ||
| 387 | | STATIC type_decl var_decl_list { $$ = new_exp_decl( $2, $3, 1, EM_lineNum ); } | ||
| 388 | | SAME var_decl_list { $$ = new_exp_decl( NULL, $2, 0, EM_lineNum ); } | ||
| 389 | | STATIC SAME var_decl_list { $$ = new_exp_decl( NULL, $3, 1, EM_lineNum ); } | ||
| 390 | ; | ||
| 391 | |||
| 392 | var_decl_list | ||
| 393 | : var_decl { $$ = new_var_decl_list( $1, EM_lineNum ); } | ||
| 394 | | var_decl COMMA var_decl_list { $$ = prepend_var_decl_list( $1, $3, EM_lineNum ); } | ||
| 395 | ; | ||
| 396 | |||
| 397 | var_decl | ||
| 398 | : ID { $$ = new_var_decl( $1, NULL, EM_lineNum ); } | ||
| 399 | | ID array_exp { $$ = new_var_decl( $1, $2, EM_lineNum ); } | ||
| 400 | | ID array_empty { $$ = new_var_decl( $1, $2, EM_lineNum ); } | ||
| 401 | ; | ||
| 402 | |||
| 403 | complex_exp | ||
| 404 | : POUNDPAREN expression RPAREN | ||
| 405 | { $$ = new_complex( $2, EM_lineNum ); } | ||
| 406 | ; | ||
| 407 | |||
| 408 | polar_exp | ||
| 409 | : PERCENTPAREN expression RPAREN | ||
| 410 | { $$ = new_polar( $2, EM_lineNum ); } | ||
| 411 | ; | ||
| 412 | |||
| 413 | vec_exp // ge: added 1.3.5.3 | ||
| 414 | : ATPAREN expression RPAREN | ||
| 415 | { $$ = new_vec( $2, EM_lineNum ); } | ||
| 416 | ; | ||
| 417 | |||
| 418 | chuck_operator | ||
| 419 | : CHUCK { $$ = ae_op_chuck; } | ||
| 420 | | AT_CHUCK { $$ = ae_op_at_chuck; } | ||
| 421 | | PLUS_CHUCK { $$ = ae_op_plus_chuck; } | ||
| 422 | | MINUS_CHUCK { $$ = ae_op_minus_chuck; } | ||
| 423 | | TIMES_CHUCK { $$ = ae_op_times_chuck; } | ||
| 424 | | DIVIDE_CHUCK { $$ = ae_op_divide_chuck; } | ||
| 425 | | SHIFT_RIGHT_CHUCK { $$ = ae_op_shift_right_chuck; } | ||
| 426 | | SHIFT_LEFT_CHUCK { $$ = ae_op_shift_left_chuck; } | ||
| 427 | | PERCENT_CHUCK { $$ = ae_op_percent_chuck; } | ||
| 428 | | UNCHUCK { $$ = ae_op_unchuck; } | ||
| 429 | | UPCHUCK { $$ = ae_op_upchuck; } | ||
| 430 | | S_AND_CHUCK { $$ = ae_op_s_and_chuck; } | ||
| 431 | | S_OR_CHUCK { $$ = ae_op_s_or_chuck; } | ||
| 432 | | S_XOR_CHUCK { $$ = ae_op_s_xor_chuck; } | ||
| 433 | ; | ||
| 434 | |||
| 435 | arrow_operator | ||
| 436 | : ARROW_LEFT { $$ = ae_op_arrow_left; } | ||
| 437 | | ARROW_RIGHT { $$ = ae_op_arrow_right; } | ||
| 438 | ; | ||
| 439 | |||
| 440 | conditional_expression | ||
| 441 | : logical_or_expression { $$ = $1; } | ||
| 442 | | logical_or_expression QUESTION expression COLON conditional_expression | ||
| 443 | { $$ = new_exp_from_if( $1, $3, $5, EM_lineNum ); } | ||
| 444 | ; | ||
| 445 | |||
| 446 | logical_or_expression | ||
| 447 | : logical_and_expression { $$ = $1; } | ||
| 448 | | logical_or_expression OR logical_and_expression | ||
| 449 | { $$ = new_exp_from_binary( $1, ae_op_or, $3, EM_lineNum ); } | ||
| 450 | ; | ||
| 451 | |||
| 452 | logical_and_expression | ||
| 453 | : inclusive_or_expression { $$ = $1; } | ||
| 454 | | logical_and_expression AND inclusive_or_expression | ||
| 455 | { $$ = new_exp_from_binary( $1, ae_op_and, $3, EM_lineNum ); } | ||
| 456 | ; | ||
| 457 | |||
| 458 | inclusive_or_expression | ||
| 459 | : exclusive_or_expression { $$ = $1; } | ||
| 460 | | inclusive_or_expression S_OR exclusive_or_expression | ||
| 461 | { $$ = new_exp_from_binary( $1, ae_op_s_or, $3, EM_lineNum ); } | ||
| 462 | ; | ||
| 463 | |||
| 464 | exclusive_or_expression | ||
| 465 | : and_expression { $$ = $1; } | ||
| 466 | | exclusive_or_expression S_XOR and_expression | ||
| 467 | { $$ = new_exp_from_binary( $1, ae_op_s_xor, $3, EM_lineNum ); } | ||
| 468 | ; | ||
| 469 | |||
| 470 | and_expression | ||
| 471 | : equality_expression { $$ = $1; } | ||
| 472 | | and_expression S_AND equality_expression | ||
| 473 | { $$ = new_exp_from_binary( $1, ae_op_s_and, $3, EM_lineNum ); } | ||
| 474 | ; | ||
| 475 | |||
| 476 | equality_expression | ||
| 477 | : relational_expression { $$ = $1; } | ||
| 478 | | equality_expression EQ relational_expression | ||
| 479 | { $$ = new_exp_from_binary( $1, ae_op_eq, $3, EM_lineNum ); } | ||
| 480 | | equality_expression NEQ relational_expression | ||
| 481 | { $$ = new_exp_from_binary( $1, ae_op_neq, $3, EM_lineNum ); } | ||
| 482 | ; | ||
| 483 | |||
| 484 | relational_expression | ||
| 485 | : shift_expression { $$ = $1; } | ||
| 486 | | relational_expression LT shift_expression | ||
| 487 | { $$ = new_exp_from_binary( $1, ae_op_lt, $3, EM_lineNum ); } | ||
| 488 | | relational_expression GT shift_expression | ||
| 489 | { $$ = new_exp_from_binary( $1, ae_op_gt, $3, EM_lineNum ); } | ||
| 490 | | relational_expression LE shift_expression | ||
| 491 | { $$ = new_exp_from_binary( $1, ae_op_le, $3, EM_lineNum ); } | ||
| 492 | | relational_expression GE shift_expression | ||
| 493 | { $$ = new_exp_from_binary( $1, ae_op_ge, $3, EM_lineNum ); } | ||
| 494 | ; | ||
| 495 | |||
| 496 | shift_expression | ||
| 497 | : additive_expression { $$ = $1; } | ||
| 498 | | shift_expression SHIFT_LEFT additive_expression | ||
| 499 | { $$ = new_exp_from_binary( $1, ae_op_shift_left, $3, EM_lineNum ); } | ||
| 500 | | shift_expression SHIFT_RIGHT additive_expression | ||
| 501 | { $$ = new_exp_from_binary( $1, ae_op_shift_right, $3, EM_lineNum ); } | ||
| 502 | ; | ||
| 503 | |||
| 504 | additive_expression | ||
| 505 | : multiplicative_expression { $$ = $1; } | ||
| 506 | | additive_expression PLUS multiplicative_expression | ||
| 507 | { $$ = new_exp_from_binary( $1, ae_op_plus, $3, EM_lineNum ); } | ||
| 508 | | additive_expression MINUS multiplicative_expression | ||
| 509 | { $$ = new_exp_from_binary( $1, ae_op_minus, $3, EM_lineNum ); } | ||
| 510 | ; | ||
| 511 | |||
| 512 | multiplicative_expression | ||
| 513 | : tilda_expression { $$ = $1; } | ||
| 514 | | multiplicative_expression TIMES tilda_expression | ||
| 515 | { $$ = new_exp_from_binary( $1, ae_op_times, $3, EM_lineNum ); } | ||
| 516 | | multiplicative_expression DIVIDE tilda_expression | ||
| 517 | { $$ = new_exp_from_binary( $1, ae_op_divide, $3, EM_lineNum ); } | ||
| 518 | | multiplicative_expression PERCENT tilda_expression | ||
| 519 | { $$ = new_exp_from_binary( $1, ae_op_percent, $3, EM_lineNum ); } | ||
| 520 | ; | ||
| 521 | |||
| 522 | tilda_expression | ||
| 523 | : cast_expression { $$ = $1; } | ||
| 524 | | tilda_expression TILDA cast_expression | ||
| 525 | { $$ = new_exp_from_binary( $1, ae_op_tilda, $3, EM_lineNum ); } | ||
| 526 | ; | ||
| 527 | |||
| 528 | cast_expression | ||
| 529 | : unary_expression { $$ = $1; } | ||
| 530 | | cast_expression DOLLAR type_decl | ||
| 531 | { $$ = new_exp_from_cast( $3, $1, EM_lineNum ); } | ||
| 532 | ; | ||
| 533 | |||
| 534 | unary_expression | ||
| 535 | : dur_expression { $$ = $1; } | ||
| 536 | | PLUSPLUS unary_expression | ||
| 537 | { $$ = new_exp_from_unary( ae_op_plusplus, $2, EM_lineNum ); } | ||
| 538 | | MINUSMINUS unary_expression | ||
| 539 | { $$ = new_exp_from_unary( ae_op_minusminus, $2, EM_lineNum ); } | ||
| 540 | | unary_operator unary_expression | ||
| 541 | { $$ = new_exp_from_unary( $1, $2, EM_lineNum ); } | ||
| 542 | | TYPEOF unary_expression | ||
| 543 | { $$ = new_exp_from_unary( ae_op_typeof, $2, EM_lineNum ); } | ||
| 544 | | SIZEOF unary_expression | ||
| 545 | { $$ = new_exp_from_unary( ae_op_sizeof, $2, EM_lineNum ); } | ||
| 546 | | NEW type_decl | ||
| 547 | { $$ = new_exp_from_unary2( ae_op_new, $2, NULL, EM_lineNum ); } | ||
| 548 | | NEW type_decl array_exp | ||
| 549 | { $$ = new_exp_from_unary2( ae_op_new, $2, $3, EM_lineNum ); } | ||
| 550 | // | SPORK TILDA code_segment | ||
| 551 | // { $$ = new_exp_from_unary3( ae_op_spork, $3, EM_lineNum ); } | ||
| 552 | ; | ||
| 553 | |||
| 554 | unary_operator | ||
| 555 | : PLUS { $$ = ae_op_plus; } | ||
| 556 | | MINUS { $$ = ae_op_minus; } | ||
| 557 | | TILDA { $$ = ae_op_tilda; } | ||
| 558 | | EXCLAMATION { $$ = ae_op_exclamation; } | ||
| 559 | | TIMES { $$ = ae_op_times; } | ||
| 560 | | SPORK TILDA { $$ = ae_op_spork; } | ||
| 561 | // | S_AND { $$ = ae_op_s_and; } | ||
| 562 | ; | ||
| 563 | |||
| 564 | dur_expression | ||
| 565 | : postfix_expression | ||
| 566 | | dur_expression COLONCOLON postfix_expression | ||
| 567 | { $$ = new_exp_from_dur( $1, $3, EM_lineNum ); } | ||
| 568 | ; | ||
| 569 | |||
| 570 | postfix_expression | ||
| 571 | : primary_expression { $$ = $1; } | ||
| 572 | | postfix_expression array_exp | ||
| 573 | { $$ = new_exp_from_array( $1, $2, EM_lineNum ); } | ||
| 574 | | postfix_expression LPAREN RPAREN | ||
| 575 | { $$ = new_exp_from_func_call( $1, NULL, EM_lineNum ); } | ||
| 576 | | postfix_expression LPAREN expression RPAREN | ||
| 577 | { $$ = new_exp_from_func_call( $1, $3, EM_lineNum ); } | ||
| 578 | | postfix_expression DOT ID | ||
| 579 | { $$ = new_exp_from_member_dot( $1, $3, EM_lineNum ); } | ||
| 580 | | postfix_expression PLUSPLUS | ||
| 581 | { $$ = new_exp_from_postfix( $1, ae_op_plusplus, EM_lineNum ); } | ||
| 582 | | postfix_expression MINUSMINUS | ||
| 583 | { $$ = new_exp_from_postfix( $1, ae_op_minusminus, EM_lineNum ); } | ||
| 584 | ; | ||
| 585 | |||
| 586 | // 1.3.3.0: added CHAR_LIT - spencer | ||
| 587 | primary_expression | ||
| 588 | : ID { $$ = new_exp_from_id( $1, EM_lineNum ); } | ||
| 589 | | NUM { $$ = new_exp_from_int( $1, EM_lineNum ); } | ||
| 590 | | FLOAT { $$ = new_exp_from_float( $1, EM_lineNum ); } | ||
| 591 | | STRING_LIT { $$ = new_exp_from_str( $1, EM_lineNum ); } | ||
| 592 | | CHAR_LIT { $$ = new_exp_from_char( $1, EM_lineNum ); } | ||
| 593 | | array_exp { $$ = new_exp_from_array_lit( $1, EM_lineNum ); } | ||
| 594 | | complex_exp { $$ = new_exp_from_complex( $1, EM_lineNum ); } | ||
| 595 | | polar_exp { $$ = new_exp_from_polar( $1, EM_lineNum ); } | ||
| 596 | | vec_exp { $$ = new_exp_from_vec( $1, EM_lineNum ); } | ||
| 597 | | L_HACK expression R_HACK { $$ = new_exp_from_hack( $2, EM_lineNum ); } | ||
| 598 | | LPAREN expression RPAREN { $$ = $2; } | ||
| 599 | | LPAREN RPAREN { $$ = new_exp_from_nil( EM_lineNum ); } | ||
| 600 | ; | ||
| @@ -0,0 +1,972 @@ | |||
| 1 | /*---------------------------------------------------------------------------- | ||
| 2 | ChucK Concurrent, On-the-fly Audio Programming Language | ||
| 3 | Compiler and Virtual Machine | ||
| 4 | |||
| 5 | Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. | ||
| 6 | http://chuck.stanford.edu/ | ||
| 7 | http://chuck.cs.princeton.edu/ | ||
| 8 | |||
| 9 | This program is free software; you can redistribute it and/or modify | ||
| 10 | it under the terms of the GNU General Public License as published by | ||
| 11 | the Free Software Foundation; either version 2 of the License, or | ||
| 12 | (at your option) any later version. | ||
| 13 | |||
| 14 | This program is distributed in the hope that it will be useful, | ||
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | GNU General Public License for more details. | ||
| 18 | |||
| 19 | You should have received a copy of the GNU General Public License | ||
| 20 | along with this program; if not, write to the Free Software | ||
| 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
| 22 | U.S.A. | ||
| 23 | -----------------------------------------------------------------------------*/ | ||
| 24 | |||
| 25 | //----------------------------------------------------------------------------- | ||
| 26 | // file: chuck_absyn.cpp | ||
| 27 | // desc: chuck abstract syntax | ||
| 28 | // | ||
| 29 | // author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) | ||
| 30 | // date: Autumn 2002 | ||
| 31 | //----------------------------------------------------------------------------- | ||
| 32 | #include <stdlib.h> | ||
| 33 | #include <stdio.h> | ||
| 34 | #include "chuck_absyn.h" | ||
| 35 | #include "chuck_utils.h" | ||
| 36 | |||
| 37 | |||
| 38 | a_Program new_program( a_Section section, int pos ) | ||
| 39 | { | ||
| 40 | a_Program a = (a_Program)checked_malloc( sizeof( struct a_Program_ ) ); | ||
| 41 | a->section = section; | ||
| 42 | a->linepos = pos; | ||
| 43 | |||
| 44 | return a; | ||
| 45 | } | ||
| 46 | |||
| 47 | a_Program prepend_program( a_Section section, a_Program program, int pos ) | ||
| 48 | { | ||
| 49 | a_Program a = new_program( section, pos ); | ||
| 50 | a->next = program; | ||
| 51 | a->linepos = pos; | ||
| 52 | |||
| 53 | return a; | ||
| 54 | } | ||
| 55 | |||
| 56 | a_Section new_section_stmt( a_Stmt_List list, int pos ) | ||
| 57 | { | ||
| 58 | a_Section a = (a_Section)checked_malloc( sizeof( struct a_Section_ ) ); | ||
| 59 | a->s_type = ae_section_stmt; | ||
| 60 | a->stmt_list = list; | ||
| 61 | a->linepos = pos; | ||
| 62 | |||
| 63 | return a; | ||
| 64 | } | ||
| 65 | |||
| 66 | a_Section new_section_func_def( a_Func_Def func_def, int pos ) | ||
| 67 | { | ||
| 68 | a_Section a = (a_Section)checked_malloc( sizeof( struct a_Section_) ); | ||
| 69 | a->s_type = ae_section_func; | ||
| 70 | a->func_def = func_def; | ||
| 71 | a->linepos = pos; | ||
| 72 | |||
| 73 | return a; | ||
| 74 | } | ||
| 75 | |||
| 76 | a_Section new_section_class_def( a_Class_Def class_def, int pos ) | ||
| 77 | { | ||
| 78 | a_Section a = (a_Section)checked_malloc( sizeof( struct a_Section_) ); | ||
| 79 | a->s_type = ae_section_class; | ||
| 80 | a->class_def = class_def; | ||
| 81 | a->linepos = pos; | ||
| 82 | |||
| 83 | return a; | ||
| 84 | } | ||
| 85 | |||
| 86 | a_Stmt_List new_stmt_list( a_Stmt stmt, int pos ) | ||
| 87 | { | ||
| 88 | a_Stmt_List a = (a_Stmt_List)checked_malloc( sizeof( struct a_Stmt_List_ ) ); | ||
| 89 | a->stmt = stmt; | ||
| 90 | a->next = NULL; | ||
| 91 | a->linepos = pos; | ||
| 92 | |||
| 93 | return a; | ||
| 94 | } | ||
| 95 | |||
| 96 | a_Stmt_List prepend_stmt_list( a_Stmt stmt, a_Stmt_List stmt_list, int pos ) | ||
| 97 | { | ||
| 98 | a_Stmt_List a = new_stmt_list( stmt, pos ); | ||
| 99 | a->next = stmt_list; | ||
| 100 | a->linepos = pos; | ||
| 101 | |||
| 102 | return a; | ||
| 103 | } | ||
| 104 | |||
| 105 | a_Stmt new_stmt_from_expression( a_Exp exp, int pos ) | ||
| 106 | { | ||
| 107 | a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); | ||
| 108 | a->s_type = ae_stmt_exp; | ||
| 109 | a->stmt_exp = exp; | ||
| 110 | a->linepos = pos; | ||
| 111 | |||
| 112 | return a; | ||
| 113 | } | ||
| 114 | |||
| 115 | a_Stmt new_stmt_from_code( a_Stmt_List stmt_list, int pos ) | ||
| 116 | { | ||
| 117 | a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); | ||
| 118 | a->s_type = ae_stmt_code; | ||
| 119 | a->stmt_code.stmt_list = stmt_list; | ||
| 120 | a->linepos = pos; | ||
| 121 | a->stmt_code.linepos = pos; | ||
| 122 | a->stmt_code.self = a; | ||
| 123 | |||
| 124 | return a; | ||
| 125 | } | ||
| 126 | |||
| 127 | a_Stmt new_stmt_from_if( a_Exp cond, a_Stmt if_body, a_Stmt else_body, int pos ) | ||
| 128 | { | ||
| 129 | a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); | ||
| 130 | a->s_type = ae_stmt_if; | ||
| 131 | a->stmt_if.cond = cond; | ||
| 132 | a->stmt_if.if_body = if_body; | ||
| 133 | a->stmt_if.else_body = else_body; | ||
| 134 | a->linepos = pos; | ||
| 135 | a->stmt_if.linepos = pos; | ||
| 136 | a->stmt_if.self = a; | ||
| 137 | |||
| 138 | return a; | ||
| 139 | } | ||
| 140 | |||
| 141 | a_Stmt new_stmt_from_while( a_Exp cond, a_Stmt body, int pos ) | ||
| 142 | { | ||
| 143 | a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); | ||
| 144 | a->s_type = ae_stmt_while; | ||
| 145 | a->stmt_while.is_do = 0; | ||
| 146 | a->stmt_while.cond = cond; | ||
| 147 | a->stmt_while.body = body; | ||
| 148 | a->linepos = pos; | ||
| 149 | a->stmt_while.linepos = pos; | ||
| 150 | a->stmt_while.self = a; | ||
| 151 | |||
| 152 | return a; | ||
| 153 | } | ||
| 154 | |||
| 155 | a_Stmt new_stmt_from_do_while( a_Exp cond, a_Stmt body, int pos ) | ||
| 156 | { | ||
| 157 | a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); | ||
| 158 | a->s_type = ae_stmt_while; | ||
| 159 | a->stmt_while.is_do = 1; | ||
| 160 | a->stmt_while.cond = cond; | ||
| 161 | a->stmt_while.body = body; | ||
| 162 | a->linepos = pos; | ||
| 163 | a->stmt_while.linepos = pos; | ||
| 164 | a->stmt_while.self = a; | ||
| 165 | |||
| 166 | return a; | ||
| 167 | } | ||
| 168 | |||
| 169 | a_Stmt new_stmt_from_until( a_Exp cond, a_Stmt body, int pos ) | ||
| 170 | { | ||
| 171 | a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); | ||
| 172 | a->s_type = ae_stmt_until; | ||
| 173 | a->stmt_until.is_do = 0; | ||
| 174 | a->stmt_until.cond = cond; | ||
| 175 | a->stmt_until.body = body; | ||
| 176 | a->linepos = pos; | ||
| 177 | a->stmt_until.linepos = pos; | ||
| 178 | a->stmt_until.self = a; | ||
| 179 | |||
| 180 | return a; | ||
| 181 | } | ||
| 182 | |||
| 183 | a_Stmt new_stmt_from_do_until( a_Exp cond, a_Stmt body, int pos ) | ||
| 184 | { | ||
| 185 | a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); | ||
| 186 | a->s_type = ae_stmt_until; | ||
| 187 | a->stmt_until.is_do = 1; | ||
| 188 | a->stmt_until.cond = cond; | ||
| 189 | a->stmt_until.body = body; | ||
| 190 | a->linepos = pos; | ||
| 191 | a->stmt_until.linepos = pos; | ||
| 192 | a->stmt_until.self = a; | ||
| 193 | |||
| 194 | return a; | ||
| 195 | } | ||
| 196 | |||
| 197 | a_Stmt new_stmt_from_for( a_Stmt c1, a_Stmt c2, a_Exp c3, a_Stmt body, int pos ) | ||
| 198 | { | ||
| 199 | a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); | ||
| 200 | a->s_type = ae_stmt_for; | ||
| 201 | a->stmt_for.c1 = c1; | ||
| 202 | a->stmt_for.c2 = c2; | ||
| 203 | a->stmt_for.c3 = c3; | ||
| 204 | a->stmt_for.body = body; | ||
| 205 | a->linepos = pos; | ||
| 206 | a->stmt_for.linepos = pos; | ||
| 207 | a->stmt_for.self = a; | ||
| 208 | |||
| 209 | return a; | ||
| 210 | } | ||
| 211 | |||
| 212 | a_Stmt new_stmt_from_loop( a_Exp cond, a_Stmt body, int pos ) | ||
| 213 | { | ||
| 214 | a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); | ||
| 215 | a->s_type = ae_stmt_loop; | ||
| 216 | a->stmt_loop.cond = cond; | ||
| 217 | a->stmt_loop.body = body; | ||
| 218 | a->linepos = pos; | ||
| 219 | a->stmt_loop.linepos = pos; | ||
| 220 | a->stmt_loop.self = a; | ||
| 221 | |||
| 222 | return a; | ||
| 223 | } | ||
| 224 | |||
| 225 | a_Stmt new_stmt_from_switch( a_Exp val, int pos ) | ||
| 226 | { | ||
| 227 | a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); | ||
| 228 | a->s_type = ae_stmt_switch; | ||
| 229 | a->stmt_switch.val = val; | ||
| 230 | a->linepos = pos; | ||
| 231 | a->stmt_switch.linepos = pos; | ||
| 232 | a->stmt_switch.self = a; | ||
| 233 | |||
| 234 | return a; | ||
| 235 | } | ||
| 236 | |||
| 237 | a_Stmt new_stmt_from_break( int pos ) | ||
| 238 | { | ||
| 239 | a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); | ||
| 240 | a->s_type = ae_stmt_break; | ||
| 241 | a->linepos = pos; | ||
| 242 | a->stmt_break.linepos = pos; | ||
| 243 | a->stmt_break.self = a; | ||
| 244 | |||
| 245 | return a; | ||
| 246 | } | ||
| 247 | |||
| 248 | a_Stmt new_stmt_from_continue( int pos ) | ||
| 249 | { | ||
| 250 | a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); | ||
| 251 | a->s_type = ae_stmt_continue; | ||
| 252 | a->linepos = pos; | ||
| 253 | a->stmt_continue.linepos = pos; | ||
| 254 | a->stmt_continue.self = a; | ||
| 255 | |||
| 256 | return a; | ||
| 257 | } | ||
| 258 | |||
| 259 | a_Stmt new_stmt_from_return( a_Exp exp, int pos ) | ||
| 260 | { | ||
| 261 | a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); | ||
| 262 | a->s_type = ae_stmt_return; | ||
| 263 | a->stmt_return.val = exp; | ||
| 264 | a->linepos = pos; | ||
| 265 | a->stmt_return.linepos = pos; | ||
| 266 | a->stmt_return.self = a; | ||
| 267 | |||
| 268 | return a; | ||
| 269 | } | ||
| 270 | |||
| 271 | a_Stmt new_stmt_from_label( c_str xid, int pos ) | ||
| 272 | { | ||
| 273 | a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); | ||
| 274 | a->s_type = ae_stmt_gotolabel; | ||
| 275 | a->stmt_gotolabel.name = insert_symbol( xid ); | ||
| 276 | a->linepos = pos; | ||
| 277 | a->stmt_gotolabel.linepos = pos; | ||
| 278 | a->stmt_gotolabel.self = a; | ||
| 279 | |||
| 280 | return a; | ||
| 281 | } | ||
| 282 | |||
| 283 | a_Stmt new_stmt_from_case( a_Exp exp, int pos ) | ||
| 284 | { | ||
| 285 | a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); | ||
| 286 | a->s_type = ae_stmt_case; | ||
| 287 | a->stmt_case.exp = exp; | ||
| 288 | a->linepos = pos; | ||
| 289 | a->stmt_case.linepos = pos; | ||
| 290 | a->stmt_case.self = a; | ||
| 291 | |||
| 292 | return a; | ||
| 293 | } | ||
| 294 | |||
| 295 | a_Exp prepend_expression( a_Exp exp, a_Exp list, int pos ) | ||
| 296 | { | ||
| 297 | exp->next = list; | ||
| 298 | return exp; | ||
| 299 | } | ||
| 300 | |||
| 301 | a_Exp new_exp_from_binary( a_Exp lhs, ae_Operator oper, a_Exp rhs, int pos ) | ||
| 302 | { | ||
| 303 | a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); | ||
| 304 | a->s_type = ae_exp_binary; | ||
| 305 | a->s_meta = ae_meta_value; | ||
| 306 | a->binary.lhs = lhs; | ||
| 307 | a->binary.op = oper; | ||
| 308 | a->binary.rhs = rhs; | ||
| 309 | a->linepos = pos; | ||
| 310 | a->binary.linepos = pos; | ||
| 311 | a->binary.self = a; | ||
| 312 | |||
| 313 | return a; | ||
| 314 | } | ||
| 315 | |||
| 316 | a_Exp new_exp_from_unary( ae_Operator oper, a_Exp exp, int pos ) | ||
| 317 | { | ||
| 318 | a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); | ||
| 319 | a->s_type = ae_exp_unary; | ||
| 320 | a->s_meta = exp->s_meta; | ||
| 321 | a->unary.op = oper; | ||
| 322 | a->unary.exp = exp; | ||
| 323 | a->linepos = pos; | ||
| 324 | a->unary.linepos = pos; | ||
| 325 | a->unary.self = a; | ||
| 326 | |||
| 327 | return a; | ||
| 328 | } | ||
| 329 | |||
| 330 | a_Exp new_exp_from_unary2( ae_Operator oper, a_Type_Decl type, | ||
| 331 | a_Array_Sub array, int pos ) | ||
| 332 | { | ||
| 333 | a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); | ||
| 334 | a->s_type = ae_exp_unary; | ||
| 335 | a->s_meta = ae_meta_value; | ||
| 336 | a->unary.op = oper; | ||
| 337 | a->unary.type = type; | ||
| 338 | a->unary.array = array; | ||
| 339 | a->linepos = pos; | ||
| 340 | a->unary.linepos = pos; | ||
| 341 | a->unary.self = a; | ||
| 342 | |||
| 343 | return a; | ||
| 344 | } | ||
| 345 | |||
| 346 | a_Exp new_exp_from_unary3( ae_Operator oper, a_Stmt code, int pos ) | ||
| 347 | { | ||
| 348 | a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); | ||
| 349 | a->s_type = ae_exp_unary; | ||
| 350 | a->s_meta = ae_meta_value; | ||
| 351 | a->unary.op = oper; | ||
| 352 | a->unary.code = code; | ||
| 353 | a->linepos = pos; | ||
| 354 | a->unary.linepos = pos; | ||
| 355 | a->unary.self = a; | ||
| 356 | |||
| 357 | return a; | ||
| 358 | } | ||
| 359 | |||
| 360 | a_Exp new_exp_from_cast( a_Type_Decl type, a_Exp exp, int pos ) | ||
| 361 | { | ||
| 362 | a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); | ||
| 363 | a->s_type = ae_exp_cast; | ||
| 364 | a->s_meta = ae_meta_value; | ||
| 365 | a->cast.type = type; | ||
| 366 | a->cast.exp = exp; | ||
| 367 | a->linepos = pos; | ||
| 368 | a->cast.linepos = pos; | ||
| 369 | a->cast.self = a; | ||
| 370 | |||
| 371 | return a; | ||
| 372 | } | ||
| 373 | |||
| 374 | a_Exp new_exp_from_array( a_Exp base, a_Array_Sub indices, int pos ) | ||
| 375 | { | ||
| 376 | a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); | ||
| 377 | a->s_type = ae_exp_array; | ||
| 378 | a->s_meta = ae_meta_var; | ||
| 379 | a->array.base = base; | ||
| 380 | a->array.indices = indices; | ||
| 381 | a->linepos = pos; | ||
| 382 | a->array.linepos = pos; | ||
| 383 | a->array.self = a; | ||
| 384 | |||
| 385 | return a; | ||
| 386 | } | ||
| 387 | |||
| 388 | a_Exp new_exp_from_func_call( a_Exp base, a_Exp args, int pos ) | ||
| 389 | { | ||
| 390 | a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); | ||
| 391 | a->s_type = ae_exp_func_call; | ||
| 392 | a->s_meta = ae_meta_value; | ||
| 393 | a->func_call.func = base; | ||
| 394 | a->func_call.args = args; | ||
| 395 | a->linepos = pos; | ||
| 396 | a->func_call.linepos = pos; | ||
| 397 | a->func_call.self = a; | ||
| 398 | |||
| 399 | return a; | ||
| 400 | } | ||
| 401 | |||
| 402 | a_Exp new_exp_from_member_dot( a_Exp base, c_str xid, int pos ) | ||
| 403 | { | ||
| 404 | a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); | ||
| 405 | a->s_type = ae_exp_dot_member; | ||
| 406 | a->s_meta = ae_meta_var; | ||
| 407 | a->dot_member.base = base; | ||
| 408 | a->dot_member.xid = insert_symbol( xid ); | ||
| 409 | a->linepos = pos; | ||
| 410 | a->dot_member.linepos = pos; | ||
| 411 | a->dot_member.self = a; | ||
| 412 | |||
| 413 | return a; | ||
| 414 | } | ||
| 415 | |||
| 416 | a_Exp new_exp_from_postfix( a_Exp base, ae_Operator op, int pos ) | ||
| 417 | { | ||
| 418 | a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); | ||
| 419 | a->s_type = ae_exp_postfix; | ||
| 420 | a->s_meta = ae_meta_var; | ||
| 421 | a->postfix.exp = base; | ||
| 422 | a->postfix.op = op; | ||
| 423 | a->linepos = pos; | ||
| 424 | a->postfix.linepos = pos; | ||
| 425 | a->postfix.self = a; | ||
| 426 | |||
| 427 | return a; | ||
| 428 | } | ||
| 429 | |||
| 430 | a_Exp new_exp_from_dur( a_Exp base, a_Exp unit, int pos ) | ||
| 431 | { | ||
| 432 | a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); | ||
| 433 | a->s_type = ae_exp_dur; | ||
| 434 | a->s_meta = ae_meta_value; | ||
| 435 | a->dur.base = base; | ||
| 436 | a->dur.unit = unit; | ||
| 437 | a->linepos = pos; | ||
| 438 | a->dur.linepos = pos; | ||
| 439 | a->dur.self = a; | ||
| 440 | |||
| 441 | return a; | ||
| 442 | } | ||
| 443 | |||
| 444 | a_Exp new_exp_from_id( c_str xid, int pos ) | ||
| 445 | { | ||
| 446 | a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); | ||
| 447 | a->s_type = ae_exp_primary; | ||
| 448 | a->s_meta = ae_meta_var; | ||
| 449 | a->primary.s_type = ae_primary_var; | ||
| 450 | a->primary.var = insert_symbol( xid ); | ||
| 451 | a->linepos = pos; | ||
| 452 | a->primary.linepos = pos; | ||
| 453 | a->primary.self = a; | ||
| 454 | |||
| 455 | return a; | ||
| 456 | } | ||
| 457 | |||
| 458 | a_Exp new_exp_from_int( long num, int pos ) | ||
| 459 | { | ||
| 460 | a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); | ||
| 461 | a->s_type = ae_exp_primary; | ||
| 462 | a->s_meta = ae_meta_value; | ||
| 463 | a->primary.s_type = ae_primary_num; | ||
| 464 | a->primary.num = num; | ||
| 465 | a->linepos = pos; | ||
| 466 | a->primary.linepos = pos; | ||
| 467 | a->primary.self = a; | ||
| 468 | |||
| 469 | return a; | ||
| 470 | } | ||
| 471 | |||
| 472 | a_Exp new_exp_from_float( double num, int pos ) | ||
| 473 | { | ||
| 474 | a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); | ||
| 475 | a->s_type = ae_exp_primary; | ||
| 476 | a->s_meta = ae_meta_value; | ||
| 477 | a->primary.s_type = ae_primary_float; | ||
| 478 | a->primary.fnum = num; | ||
| 479 | a->linepos = pos; | ||
| 480 | a->primary.linepos = pos; | ||
| 481 | a->primary.self = a; | ||
| 482 | |||
| 483 | return a; | ||
| 484 | } | ||
| 485 | |||
| 486 | a_Exp new_exp_from_str( c_str str, int pos ) | ||
| 487 | { | ||
| 488 | a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); | ||
| 489 | a->s_type = ae_exp_primary; | ||
| 490 | a->s_meta = ae_meta_value; | ||
| 491 | a->primary.s_type = ae_primary_str; | ||
| 492 | a->primary.str = str; | ||
| 493 | a->linepos = pos; | ||
| 494 | a->primary.linepos = pos; | ||
| 495 | a->primary.self = a; | ||
| 496 | |||
| 497 | return a; | ||
| 498 | } | ||
| 499 | |||
| 500 | a_Exp new_exp_from_char( c_str chr, int pos ) | ||
| 501 | { | ||
| 502 | a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); | ||
| 503 | a->s_type = ae_exp_primary; | ||
| 504 | a->s_meta = ae_meta_value; | ||
| 505 | a->primary.s_type = ae_primary_char; | ||
| 506 | a->primary.chr = chr; | ||
| 507 | a->linepos = pos; | ||
| 508 | a->primary.linepos = pos; | ||
| 509 | a->primary.self = a; | ||
| 510 | |||
| 511 | return a; | ||
| 512 | } | ||
| 513 | |||
| 514 | a_Exp new_exp_from_array_lit( a_Array_Sub exp_list, int pos ) | ||
| 515 | { | ||
| 516 | a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); | ||
| 517 | a->s_type = ae_exp_primary; | ||
| 518 | a->s_meta = ae_meta_value; | ||
| 519 | a->primary.s_type = ae_primary_array; | ||
| 520 | a->primary.array = exp_list; | ||
| 521 | a->linepos = pos; | ||
| 522 | a->primary.linepos = pos; | ||
| 523 | a->primary.self = a; | ||
| 524 | |||
| 525 | return a; | ||
| 526 | } | ||
| 527 | |||
| 528 | a_Exp new_exp_from_if( a_Exp cond, a_Exp if_exp, a_Exp else_exp, int pos ) | ||
| 529 | { | ||
| 530 | a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); | ||
| 531 | a->s_type = ae_exp_if; | ||
| 532 | a->s_meta = ( ( if_exp->s_meta == ae_meta_var && | ||
| 533 | else_exp->s_meta == ae_meta_var ) ? ae_meta_var : ae_meta_value ); | ||
| 534 | a->exp_if.cond = cond; | ||
| 535 | a->exp_if.if_exp = if_exp; | ||
| 536 | a->exp_if.else_exp = else_exp; | ||
| 537 | a->linepos = pos; | ||
| 538 | a->exp_if.linepos = pos; | ||
| 539 | a->exp_if.self = a; | ||
| 540 | |||
| 541 | return a; | ||
| 542 | } | ||
| 543 | |||
| 544 | a_Exp new_exp_decl_external( a_Type_Decl type, a_Var_Decl_List var_decl_list, int is_static, int pos ) | ||
| 545 | { | ||
| 546 | a_Exp a = new_exp_decl( type, var_decl_list, is_static, pos ); | ||
| 547 | a->decl.is_external = 1; | ||
| 548 | |||
| 549 | return a; | ||
| 550 | } | ||
| 551 | |||
| 552 | a_Exp new_exp_decl( a_Type_Decl type, a_Var_Decl_List var_decl_list, int is_static, int pos ) | ||
| 553 | { | ||
| 554 | a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); | ||
| 555 | a->s_type = ae_exp_decl; | ||
| 556 | a->s_meta = ae_meta_var; | ||
| 557 | a->decl.type = type; | ||
| 558 | a->decl.var_decl_list = var_decl_list; | ||
| 559 | a->linepos = pos; | ||
| 560 | a->decl.is_static = is_static; | ||
| 561 | a->decl.linepos = pos; | ||
| 562 | a->decl.self = a; | ||
| 563 | |||
| 564 | return a; | ||
| 565 | } | ||
| 566 | |||
| 567 | a_Exp new_exp_from_hack( a_Exp exp, int pos ) | ||
| 568 | { | ||
| 569 | a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); | ||
| 570 | a->s_type = ae_exp_primary; | ||
| 571 | a->s_meta = ae_meta_value; | ||
| 572 | a->primary.s_type = ae_primary_hack; | ||
| 573 | a->primary.exp = exp; | ||
| 574 | a->primary.linepos = pos; | ||
| 575 | a->linepos = pos; | ||
| 576 | a->primary.self = a; | ||
| 577 | |||
| 578 | return a; | ||
| 579 | } | ||
| 580 | |||
| 581 | a_Exp new_exp_from_complex( a_Complex exp, int pos ) | ||
| 582 | { | ||
| 583 | a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); | ||
| 584 | a->s_type = ae_exp_primary; | ||
| 585 | a->s_meta = ae_meta_value; | ||
| 586 | a->primary.s_type = ae_primary_complex; | ||
| 587 | a->primary.complex = exp; | ||
| 588 | a->primary.linepos = pos; | ||
| 589 | a->linepos = pos; | ||
| 590 | a->primary.complex->self = a; | ||
| 591 | a->primary.self = a; | ||
| 592 | |||
| 593 | return a; | ||
| 594 | } | ||
| 595 | |||
| 596 | a_Exp new_exp_from_polar( a_Polar exp, int pos ) | ||
| 597 | { | ||
| 598 | a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); | ||
| 599 | a->s_type = ae_exp_primary; | ||
| 600 | a->s_meta = ae_meta_value; | ||
| 601 | a->primary.s_type = ae_primary_polar; | ||
| 602 | a->primary.polar = exp; | ||
| 603 | a->primary.linepos = pos; | ||
| 604 | a->linepos = pos; | ||
| 605 | a->primary.polar->self = a; | ||
| 606 | a->primary.self = a; | ||
| 607 | |||
| 608 | return a; | ||
| 609 | } | ||
| 610 | |||
| 611 | a_Exp new_exp_from_vec( a_Vec exp, int pos ) // ge: added 1.3.5.3 | ||
| 612 | { | ||
| 613 | a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); | ||
| 614 | a->s_type = ae_exp_primary; | ||
| 615 | a->s_meta = ae_meta_value; | ||
| 616 | a->primary.s_type = ae_primary_vec; | ||
| 617 | a->primary.vec = exp; | ||
| 618 | a->primary.linepos = pos; | ||
| 619 | a->linepos = pos; | ||
| 620 | a->primary.vec->self = a; | ||
| 621 | a->primary.self = a; | ||
| 622 | |||
| 623 | return a; | ||
| 624 | } | ||
| 625 | |||
| 626 | a_Exp new_exp_from_nil( int pos ) | ||
| 627 | { | ||
| 628 | a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); | ||
| 629 | a->s_type = ae_exp_primary; | ||
| 630 | a->s_meta = ae_meta_value; | ||
| 631 | a->primary.s_type = ae_primary_nil; | ||
| 632 | a->primary.linepos = pos; | ||
| 633 | a->linepos = pos; | ||
| 634 | a->primary.self = a; | ||
| 635 | |||
| 636 | return a; | ||
| 637 | } | ||
| 638 | |||
| 639 | a_Var_Decl new_var_decl( c_constr xid, a_Array_Sub array, int pos ) | ||
| 640 | { | ||
| 641 | a_Var_Decl a = (a_Var_Decl)checked_malloc( sizeof( struct a_Var_Decl_ ) ); | ||
| 642 | a->xid = insert_symbol(xid); | ||
| 643 | a->array = array; | ||
| 644 | a->linepos = pos; | ||
| 645 | |||
| 646 | return a; | ||
| 647 | } | ||
| 648 | |||
| 649 | a_Var_Decl_List new_var_decl_list( a_Var_Decl var_decl, int pos ) | ||
| 650 | { | ||
| 651 | a_Var_Decl_List a = (a_Var_Decl_List)checked_malloc( | ||
| 652 | sizeof( struct a_Var_Decl_List_ ) ); | ||
| 653 | a->var_decl = var_decl; | ||
| 654 | a->linepos = pos; | ||
| 655 | |||
| 656 | return a; | ||
| 657 | } | ||
| 658 | |||
| 659 | a_Var_Decl_List prepend_var_decl_list( a_Var_Decl var_decl, a_Var_Decl_List list, int pos ) | ||
| 660 | { | ||
| 661 | a_Var_Decl_List a = new_var_decl_list( var_decl, pos ); | ||
| 662 | a->next = list; | ||
| 663 | |||
| 664 | return a; | ||
| 665 | } | ||
| 666 | |||
| 667 | a_Type_Decl new_type_decl( a_Id_List type, int ref, int pos ) | ||
| 668 | { | ||
| 669 | a_Type_Decl a = (a_Type_Decl)checked_malloc( | ||
| 670 | sizeof( struct a_Type_Decl_ ) ); | ||
| 671 | a->xid = type; | ||
| 672 | a->ref = ref; | ||
| 673 | a->linepos = pos; | ||
| 674 | |||
| 675 | return a; | ||
| 676 | } | ||
| 677 | |||
| 678 | a_Type_Decl add_type_decl_array( a_Type_Decl a, a_Array_Sub array, int pos ) | ||
| 679 | { | ||
| 680 | assert( a->array == NULL ); | ||
| 681 | a->array = array; | ||
| 682 | |||
| 683 | return a; | ||
| 684 | } | ||
| 685 | |||
| 686 | a_Arg_List new_arg_list( a_Type_Decl type_decl, a_Var_Decl var_decl, int pos ) | ||
| 687 | { | ||
| 688 | a_Arg_List a = (a_Arg_List)checked_malloc( | ||
| 689 | sizeof( struct a_Arg_List_ ) ); | ||
| 690 | a->type_decl = type_decl; | ||
| 691 | a->var_decl = var_decl; | ||
| 692 | a->next = NULL; | ||
| 693 | a->linepos = pos; | ||
| 694 | |||
| 695 | return a; | ||
| 696 | } | ||
| 697 | |||
| 698 | a_Arg_List prepend_arg_list( a_Type_Decl type_decl, a_Var_Decl var_decl, | ||
| 699 | a_Arg_List arg_list, int pos ) | ||
| 700 | { | ||
| 701 | a_Arg_List a = new_arg_list( type_decl, var_decl, pos ); | ||
| 702 | a->next = arg_list; | ||
| 703 | a->linepos = pos; | ||
| 704 | |||
| 705 | return a; | ||
| 706 | } | ||
| 707 | |||
| 708 | a_Func_Def new_func_def( ae_Keyword func_decl, ae_Keyword static_decl, | ||
| 709 | a_Type_Decl type_decl, c_str name, | ||
| 710 | a_Arg_List arg_list, a_Stmt code, int pos ) | ||
| 711 | { | ||
| 712 | a_Func_Def a = (a_Func_Def)checked_malloc( | ||
| 713 | sizeof( struct a_Func_Def_ ) ); | ||
| 714 | a->func_decl = func_decl; | ||
| 715 | a->static_decl = static_decl; | ||
| 716 | a->type_decl = type_decl; | ||
| 717 | a->name = insert_symbol( name ); | ||
| 718 | a->arg_list = arg_list; | ||
| 719 | a->s_type = ae_func_user; | ||
| 720 | a->code = code; | ||
| 721 | a->linepos = pos; | ||
| 722 | |||
| 723 | return a; | ||
| 724 | } | ||
| 725 | |||
| 726 | a_Class_Def new_class_def( ae_Keyword class_decl, a_Id_List name, | ||
| 727 | a_Class_Ext ext, a_Class_Body body, int pos ) | ||
| 728 | { | ||
| 729 | a_Class_Def a = (a_Class_Def)checked_malloc( sizeof( struct a_Class_Def_ ) ); | ||
| 730 | a->decl = class_decl; | ||
| 731 | a->name = name; | ||
| 732 | a->ext = ext; | ||
| 733 | a->body = body; | ||
| 734 | a->linepos = pos; | ||
| 735 | |||
| 736 | return a; | ||
| 737 | } | ||
| 738 | |||
| 739 | a_Class_Def new_iface_def( ae_Keyword class_decl, a_Id_List name, | ||
| 740 | a_Class_Ext ext, a_Class_Body body, int pos ) | ||
| 741 | { | ||
| 742 | a_Class_Def a = new_class_def( class_decl, name, ext, body, pos ); | ||
| 743 | a->iface = 1; | ||
| 744 | |||
| 745 | return a; | ||
| 746 | } | ||
| 747 | |||
| 748 | a_Class_Body new_class_body( a_Section section, int pos ) | ||
| 749 | { | ||
| 750 | a_Class_Body a = (a_Class_Body)checked_malloc( sizeof( struct a_Class_Body_ ) ); | ||
| 751 | a->section = section; | ||
| 752 | a->linepos = pos; | ||
| 753 | |||
| 754 | return a; | ||
| 755 | } | ||
| 756 | |||
| 757 | a_Class_Body prepend_class_body( a_Section section, a_Class_Body body, int pos ) | ||
| 758 | { | ||
| 759 | a_Class_Body a = new_class_body( section, pos ); | ||
| 760 | a->next = body; | ||
| 761 | a->linepos = pos; | ||
| 762 | |||
| 763 | return a; | ||
| 764 | } | ||
| 765 | |||
| 766 | a_Class_Ext new_class_ext( a_Id_List extend_id, a_Id_List impl_list, int pos ) | ||
| 767 | { | ||
| 768 | a_Class_Ext a = (a_Class_Ext)checked_malloc( sizeof( struct a_Class_Ext_ ) ); | ||
| 769 | a->extend_id = extend_id; | ||
| 770 | a->impl_list = impl_list; | ||
| 771 | a->linepos = pos; | ||
| 772 | |||
| 773 | return a; | ||
| 774 | } | ||
| 775 | |||
| 776 | a_Id_List new_id_list( c_constr xid, int pos ) | ||
| 777 | { | ||
| 778 | a_Id_List a = (a_Id_List)checked_malloc( sizeof( struct a_Id_List_ ) ); | ||
| 779 | a->xid = insert_symbol( xid ); | ||
| 780 | a->next = NULL; | ||
| 781 | a->linepos = pos; | ||
| 782 | |||
| 783 | return a; | ||
| 784 | } | ||
| 785 | |||
| 786 | a_Id_List prepend_id_list( c_constr xid, a_Id_List list, int pos ) | ||
| 787 | { | ||
| 788 | a_Id_List a = new_id_list( xid, pos ); | ||
| 789 | a->next = list; | ||
| 790 | a->linepos = pos; | ||
| 791 | |||
| 792 | return a; | ||
| 793 | } | ||
| 794 | |||
| 795 | void clean_exp( a_Exp exp ) | ||
| 796 | { | ||
| 797 | if( !exp ) return; | ||
| 798 | clean_exp( exp->next ); | ||
| 799 | free( exp ); | ||
| 800 | } | ||
| 801 | |||
| 802 | a_Array_Sub new_array_sub( a_Exp exp, int pos ) | ||
| 803 | { | ||
| 804 | a_Array_Sub a = (a_Array_Sub)checked_malloc( sizeof( struct a_Array_Sub_ ) ); | ||
| 805 | a->exp_list = exp; | ||
| 806 | a->depth = 1; | ||
| 807 | a->linepos = pos; | ||
| 808 | |||
| 809 | // make sure no multi | ||
| 810 | /* if( exp && exp->next ) | ||
| 811 | { | ||
| 812 | // primary exp? | ||
| 813 | if( is_primary ) | ||
| 814 | { | ||
| 815 | a->exp_list = NULL; | ||
| 816 | a->exp_multi = exp; | ||
| 817 | } | ||
| 818 | else | ||
| 819 | { | ||
| 820 | a->err_num = 1; // multi | ||
| 821 | a->err_pos = exp->linepos; // set error for type-checker | ||
| 822 | goto error; | ||
| 823 | } | ||
| 824 | } */ | ||
| 825 | |||
| 826 | return a; | ||
| 827 | |||
| 828 | /* error: | ||
| 829 | clean_exp( exp ); | ||
| 830 | a->exp_list = NULL; | ||
| 831 | return a; */ | ||
| 832 | } | ||
| 833 | |||
| 834 | a_Array_Sub prepend_array_sub( a_Array_Sub a, a_Exp exp, int pos ) | ||
| 835 | { | ||
| 836 | // if already error | ||
| 837 | if( a->err_num ) goto error; | ||
| 838 | |||
| 839 | // make sure no multi | ||
| 840 | if( exp && exp->next ) | ||
| 841 | { | ||
| 842 | a->err_num = 1; // multi | ||
| 843 | a->err_pos = exp->linepos; // set error for type-checker | ||
| 844 | goto error; | ||
| 845 | } | ||
| 846 | |||
| 847 | // empty or not | ||
| 848 | if( (exp && !a->exp_list) || (!exp && a->exp_list) ) | ||
| 849 | { | ||
| 850 | a->err_num = 2; // partial | ||
| 851 | a->err_pos = pos; // set error for type-checker | ||
| 852 | goto error; | ||
| 853 | } | ||
| 854 | |||
| 855 | // prepend | ||
| 856 | if( exp ) | ||
| 857 | { | ||
| 858 | exp->next = a->exp_list; | ||
| 859 | a->exp_list = exp; | ||
| 860 | } | ||
| 861 | |||
| 862 | // count | ||
| 863 | a->depth++; | ||
| 864 | return a; | ||
| 865 | |||
| 866 | error: | ||
| 867 | clean_exp( exp ); | ||
| 868 | return a; | ||
| 869 | } | ||
| 870 | |||
| 871 | a_Complex new_complex( a_Exp re, int pos ) | ||
| 872 | { | ||
| 873 | a_Complex a = (a_Complex)checked_malloc( sizeof( struct a_Complex_ ) ); | ||
| 874 | a->re = re; | ||
| 875 | if( re ) a->im = re->next; | ||
| 876 | a->linepos = pos; | ||
| 877 | |||
| 878 | return a; | ||
| 879 | } | ||
| 880 | |||
| 881 | a_Polar new_polar( a_Exp mod, int pos ) | ||
| 882 | { | ||
| 883 | a_Polar a = (a_Polar)checked_malloc( sizeof( struct a_Polar_ ) ); | ||
| 884 | a->mod = mod; | ||
| 885 | if( mod ) a->phase = mod->next; | ||
| 886 | a->linepos = pos; | ||
| 887 | |||
| 888 | return a; | ||
| 889 | } | ||
| 890 | |||
| 891 | a_Vec new_vec( a_Exp e, int pos ) // ge: added 1.3.5.3 | ||
| 892 | { | ||
| 893 | a_Vec a = (a_Vec)checked_malloc( sizeof( struct a_Vec_ ) ); | ||
| 894 | a->args = e; | ||
| 895 | while( e ) // count number of dims | ||
| 896 | { | ||
| 897 | a->numdims++; | ||
| 898 | e = e->next; | ||
| 899 | } | ||
| 900 | a->linepos = pos; | ||
| 901 | |||
| 902 | return a; | ||
| 903 | } | ||
| 904 | |||
| 905 | void delete_id_list( a_Id_List x ) | ||
| 906 | { | ||
| 907 | if( !x ) return; | ||
| 908 | |||
| 909 | a_Id_List curr = x, next = x->next, temp; | ||
| 910 | |||
| 911 | while( curr ) | ||
| 912 | { | ||
| 913 | temp = curr; | ||
| 914 | curr = next; | ||
| 915 | next = temp->next; | ||
| 916 | free( temp ); | ||
| 917 | } | ||
| 918 | } | ||
| 919 | |||
| 920 | |||
| 921 | static const char * op_str[] = { | ||
| 922 | "+", | ||
| 923 | "-", | ||
| 924 | "*", | ||
| 925 | "/", | ||
| 926 | "==", | ||
| 927 | "!=", | ||
| 928 | "<", | ||
| 929 | "<=", | ||
| 930 | ">", | ||
| 931 | ">=", | ||
| 932 | "&&", | ||
| 933 | "||", | ||
| 934 | "|", | ||
| 935 | "&", | ||
| 936 | "<<", | ||
| 937 | ">>", | ||
| 938 | "%", | ||
| 939 | "^", | ||
| 940 | "=>", | ||
| 941 | "+=>", | ||
| 942 | "-=>", | ||
| 943 | "*=>", | ||
| 944 | "/=>", | ||
| 945 | "&=>", | ||
| 946 | "|=>", | ||
| 947 | "^=>", | ||
| 948 | ">>=>", | ||
| 949 | "<<=>", | ||
| 950 | "%=>", | ||
| 951 | "->", | ||
| 952 | "++", | ||
| 953 | "--", | ||
| 954 | "~", | ||
| 955 | "!", | ||
| 956 | "@=>", | ||
| 957 | "=<", | ||
| 958 | "spork ~", | ||
| 959 | "typeof", | ||
| 960 | "sizeof", | ||
| 961 | "new" | ||
| 962 | }; | ||
| 963 | |||
| 964 | |||
| 965 | const char * op2str( ae_Operator op ) | ||
| 966 | { | ||
| 967 | t_CKINT index = (t_CKINT)op; | ||
| 968 | if( index < 0 || index >= (t_CKINT)(sizeof(op_str)/sizeof(char *)) ) | ||
| 969 | return "[non-existent operator]"; | ||
| 970 | |||
| 971 | return op_str[index]; | ||
| 972 | } | ||
| @@ -0,0 +1,406 @@ | |||
| 1 | /*---------------------------------------------------------------------------- | ||
| 2 | ChucK Concurrent, On-the-fly Audio Programming Language | ||
| 3 | Compiler and Virtual Machine | ||
| 4 | |||
| 5 | Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. | ||
| 6 | http://chuck.stanford.edu/ | ||
| 7 | http://chuck.cs.princeton.edu/ | ||
| 8 | |||
| 9 | This program is free software; you can redistribute it and/or modify | ||
| 10 | it under the terms of the GNU General Public License as published by | ||
| 11 | the Free Software Foundation; either version 2 of the License, or | ||
| 12 | (at your option) any later version. | ||
| 13 | |||
| 14 | This program is distributed in the hope that it will be useful, | ||
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | GNU General Public License for more details. | ||
| 18 | |||
| 19 | You should have received a copy of the GNU General Public License | ||
| 20 | along with this program; if not, write to the Free Software | ||
| 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
| 22 | U.S.A. | ||
| 23 | -----------------------------------------------------------------------------*/ | ||
| 24 | |||
| 25 | //----------------------------------------------------------------------------- | ||
| 26 | // file: chuck_absyn.h | ||
| 27 | // desc: chuck abstract syntax | ||
| 28 | // | ||
| 29 | // author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) | ||
| 30 | // date: Autumn 2002 | ||
| 31 | //----------------------------------------------------------------------------- | ||
| 32 | #ifndef __CHUCK_ABSYN_H__ | ||
| 33 | #define __CHUCK_ABSYN_H__ | ||
| 34 | |||
| 35 | #include "chuck_symbol.h" | ||
| 36 | |||
| 37 | #if defined(_cplusplus) || defined(__cplusplus) | ||
| 38 | extern "C" { | ||
| 39 | #endif | ||
| 40 | |||
| 41 | // pos | ||
| 42 | typedef int a_Pos; | ||
| 43 | |||
| 44 | // enum oper | ||
| 45 | typedef enum { | ||
| 46 | ae_op_plus, ae_op_minus, ae_op_times, ae_op_divide, | ||
| 47 | ae_op_eq, ae_op_neq, ae_op_lt, ae_op_le, ae_op_gt, | ||
| 48 | ae_op_ge, ae_op_and, ae_op_or, ae_op_s_or, ae_op_s_and, | ||
| 49 | ae_op_shift_left, ae_op_shift_right, ae_op_percent, | ||
| 50 | ae_op_s_xor, ae_op_chuck, ae_op_plus_chuck, ae_op_minus_chuck, | ||
| 51 | ae_op_times_chuck, ae_op_divide_chuck, ae_op_s_and_chuck, | ||
| 52 | ae_op_s_or_chuck, ae_op_s_xor_chuck, ae_op_shift_right_chuck, | ||
| 53 | ae_op_shift_left_chuck, ae_op_percent_chuck, ae_op_s_chuck, | ||
| 54 | ae_op_plusplus, ae_op_minusminus, ae_op_tilda, ae_op_exclamation, | ||
| 55 | ae_op_at_chuck, ae_op_unchuck, ae_op_upchuck, ae_op_spork, | ||
| 56 | ae_op_typeof, ae_op_sizeof, ae_op_new, ae_op_arrow_left, ae_op_arrow_right | ||
| 57 | } ae_Operator; | ||
| 58 | |||
| 59 | const char * op2str( ae_Operator op ); | ||
| 60 | |||
| 61 | // enum key words | ||
| 62 | typedef enum { | ||
| 63 | ae_key_this, ae_key_me, ae_key_func, ae_key_public, ae_key_protected, | ||
| 64 | ae_key_private, ae_key_static, ae_key_instance, ae_key_abstract | ||
| 65 | } ae_Keyword; | ||
| 66 | |||
| 67 | |||
| 68 | |||
| 69 | |||
| 70 | //----------------------------------------------------------------------------- | ||
| 71 | // pointer types | ||
| 72 | //----------------------------------------------------------------------------- | ||
| 73 | typedef struct a_Program_ * a_Program; | ||
| 74 | typedef struct a_Section_ * a_Section; | ||
| 75 | typedef struct a_Stmt_List_ * a_Stmt_List; | ||
| 76 | typedef struct a_Class_Def_ * a_Class_Def; | ||
| 77 | typedef struct a_Func_Def_ * a_Func_Def; | ||
| 78 | typedef struct a_Code_Segment_ * a_Code_Segment; | ||
| 79 | typedef struct a_Stmt_ * a_Stmt; | ||
| 80 | typedef struct a_Exp_ * a_Exp; | ||
| 81 | typedef struct a_Exp_Chuck_ * a_Exp_Chuck; | ||
| 82 | typedef struct a_Exp_Binary_ * a_Exp_Binary; | ||
| 83 | typedef struct a_Exp_Cast_ * a_Exp_Cast; | ||
| 84 | typedef struct a_Exp_Unary_ * a_Exp_Unary; | ||
| 85 | typedef struct a_Exp_Postfix_ * a_Exp_Postfix; | ||
| 86 | typedef struct a_Exp_Primary_ * a_Exp_Primary; | ||
| 87 | typedef struct a_Exp_Dur_ * a_Exp_Dur; | ||
| 88 | typedef struct a_Exp_Array_ * a_Exp_Array; | ||
| 89 | typedef struct a_Exp_Func_Call_ * a_Exp_Func_Call; | ||
| 90 | typedef struct a_Exp_Dot_Member_ * a_Exp_Dot_Member; | ||
| 91 | typedef struct a_Exp_If_ * a_Exp_If; | ||
| 92 | typedef struct a_Exp_Decl_ * a_Exp_Decl; | ||
| 93 | typedef struct a_Exp_Hack_ * a_Exp_Hack; | ||
| 94 | typedef struct a_Stmt_Code_ * a_Stmt_Code; | ||
| 95 | typedef struct a_Stmt_If_ * a_Stmt_If; | ||
| 96 | typedef struct a_Stmt_While_ * a_Stmt_While; | ||
| 97 | typedef struct a_Stmt_Until_ * a_Stmt_Until; | ||
| 98 | typedef struct a_Stmt_For_ * a_Stmt_For; | ||
| 99 | typedef struct a_Stmt_Loop_ * a_Stmt_Loop; | ||
| 100 | typedef struct a_Stmt_Switch_ * a_Stmt_Switch; | ||
| 101 | typedef struct a_Stmt_Break_ * a_Stmt_Break; | ||
| 102 | typedef struct a_Stmt_Continue_ * a_Stmt_Continue; | ||
| 103 | typedef struct a_Stmt_Return_ * a_Stmt_Return; | ||
| 104 | typedef struct a_Stmt_Case_ * a_Stmt_Case; | ||
| 105 | typedef struct a_Stmt_GotoLabel_ * a_Stmt_GotoLabel; | ||
| 106 | typedef struct a_Decl_ * a_Decl; | ||
| 107 | typedef struct a_Var_Decl_ * a_Var_Decl; | ||
| 108 | typedef struct a_Var_Decl_List_ * a_Var_Decl_List; | ||
| 109 | typedef struct a_Type_Decl_ * a_Type_Decl; | ||
| 110 | typedef struct a_Arg_List_ * a_Arg_List; | ||
| 111 | typedef struct a_Id_List_ * a_Id_List; | ||
| 112 | typedef struct a_Class_Ext_ * a_Class_Ext; | ||
| 113 | typedef struct a_Class_Body_ * a_Class_Body; | ||
| 114 | typedef struct a_Array_Sub_ * a_Array_Sub; | ||
| 115 | typedef struct a_Complex_ * a_Complex; | ||
| 116 | typedef struct a_Polar_ * a_Polar; | ||
| 117 | typedef struct a_Vec_ * a_Vec; // ge: added 1.3.5.3 | ||
| 118 | |||
| 119 | // forward reference for type | ||
| 120 | typedef struct Chuck_Type * t_CKTYPE; | ||
| 121 | typedef struct Chuck_Value * t_CKVALUE; | ||
| 122 | typedef struct Chuck_Func * t_CKFUNC; | ||
| 123 | typedef struct Chuck_Namespace * t_CKNSPC; | ||
| 124 | typedef struct Chuck_VM_Code * t_CKVMCODE; | ||
| 125 | |||
| 126 | |||
| 127 | |||
| 128 | |||
| 129 | //------------------------------------------------------------------------------ | ||
| 130 | // functions | ||
| 131 | //------------------------------------------------------------------------------ | ||
| 132 | a_Program new_program( a_Section section, int pos ); | ||
| 133 | a_Program prepend_program( a_Section section, a_Program program, int pos ); | ||
| 134 | a_Section new_section_stmt( a_Stmt_List stmt_list, int pos ); | ||
| 135 | a_Section new_section_func_def( a_Func_Def func_def, int pos ); | ||
| 136 | a_Section new_section_class_def( a_Class_Def class_def, int pos ); | ||
| 137 | a_Stmt_List new_stmt_list( a_Stmt stmt, int pos ); | ||
| 138 | a_Stmt_List prepend_stmt_list( a_Stmt stmt, a_Stmt_List stmt_list, int pos ); | ||
| 139 | a_Stmt new_stmt_from_expression( a_Exp exp, int pos ); | ||
| 140 | a_Stmt new_stmt_from_code( a_Stmt_List code, int pos ); | ||
| 141 | a_Stmt new_stmt_from_while( a_Exp cond, a_Stmt body, int pos ); | ||
| 142 | a_Stmt new_stmt_from_do_while( a_Exp cond, a_Stmt body, int pos ); | ||
| 143 | a_Stmt new_stmt_from_until( a_Exp cond, a_Stmt body, int pos ); | ||
| 144 | a_Stmt new_stmt_from_do_until( a_Exp cond, a_Stmt body, int pos ); | ||
| 145 | a_Stmt new_stmt_from_for( a_Stmt c1, a_Stmt c2, a_Exp c3, a_Stmt body, int pos ); | ||
| 146 | a_Stmt new_stmt_from_loop( a_Exp cond, a_Stmt body, int pos ); | ||
| 147 | a_Stmt new_stmt_from_if( a_Exp cond, a_Stmt if_body, a_Stmt else_body, int pos ); | ||
| 148 | a_Stmt new_stmt_from_switch( a_Exp exp, int pos ); | ||
| 149 | a_Stmt new_stmt_from_break( int pos ); | ||
| 150 | a_Stmt new_stmt_from_continue( int pos ); | ||
| 151 | a_Stmt new_stmt_from_return( a_Exp exp, int pos ); | ||
| 152 | a_Stmt new_stmt_from_label( c_str xid, int pos ); | ||
| 153 | a_Stmt new_stmt_from_case( a_Exp exp, int pos ); | ||
| 154 | a_Exp prepend_expression( a_Exp exp, a_Exp list, int pos ); | ||
| 155 | a_Exp new_exp_from_binary( a_Exp lhs, ae_Operator oper, a_Exp rhs, int pos ); | ||
| 156 | a_Exp new_exp_from_unary( ae_Operator oper, a_Exp exp, int pos ); | ||
| 157 | a_Exp new_exp_from_unary2( ae_Operator oper, a_Type_Decl type, a_Array_Sub array, int pos ); | ||
| 158 | a_Exp new_exp_from_unary3( ae_Operator oper, a_Stmt code, int pos ); | ||
| 159 | a_Exp new_exp_from_cast( a_Type_Decl type, a_Exp exp, int pos ); | ||
| 160 | a_Exp new_exp_from_array( a_Exp base, a_Array_Sub indices, int pos ); | ||
| 161 | a_Exp new_exp_from_array_lit( a_Array_Sub exp_list, int pos ); | ||
| 162 | a_Exp new_exp_from_func_call( a_Exp base, a_Exp args, int pos ); | ||
| 163 | a_Exp new_exp_from_member_dot( a_Exp base, c_str member, int pos ); | ||
| 164 | a_Exp new_exp_from_postfix( a_Exp base, ae_Operator op, int pos ); | ||
| 165 | a_Exp new_exp_from_dur( a_Exp base, a_Exp unit, int pos ); | ||
| 166 | a_Exp new_exp_from_id( c_str xid, int pos ); | ||
| 167 | a_Exp new_exp_from_int( long num, int pos ); | ||
| 168 | a_Exp new_exp_from_uint( unsigned long num, int pos ); | ||
| 169 | a_Exp new_exp_from_float( double num, int pos ); | ||
| 170 | a_Exp new_exp_from_str( c_str str, int pos ); | ||
| 171 | a_Exp new_exp_from_char( c_str chr, int pos ); | ||
| 172 | a_Exp new_exp_from_if( a_Exp cond, a_Exp lhs, a_Exp rhs, int pos ); | ||
| 173 | a_Exp new_exp_from_complex( a_Complex, int pos ); | ||
| 174 | a_Exp new_exp_from_polar( a_Polar, int pos ); | ||
| 175 | a_Exp new_exp_from_vec( a_Vec, int pos ); // ge: added 1.3.5.3 | ||
| 176 | a_Exp new_exp_decl_external( a_Type_Decl type_decl, a_Var_Decl_List var_decl_list, int is_static, int pos ); | ||
| 177 | a_Exp new_exp_decl( a_Type_Decl type_decl, a_Var_Decl_List var_decl_list, int is_static, int pos ); | ||
| 178 | a_Exp new_exp_from_hack( a_Exp exp, int pos ); | ||
| 179 | a_Exp new_exp_from_nil( int pos ); | ||
| 180 | a_Var_Decl_List new_var_decl_list( a_Var_Decl var_decl, int pos ); | ||
| 181 | a_Var_Decl_List prepend_var_decl_list( a_Var_Decl var_decl, a_Var_Decl_List list, int pos ); | ||
| 182 | a_Var_Decl new_var_decl( c_constr xid, a_Array_Sub array, int pos ); | ||
| 183 | a_Type_Decl new_type_decl( a_Id_List xid, int ref, int pos ); | ||
| 184 | a_Type_Decl add_type_decl_array( a_Type_Decl type_decl, a_Array_Sub array, int pos ); | ||
| 185 | a_Arg_List new_arg_list( a_Type_Decl type_decl, a_Var_Decl var_decl, int pos ); | ||
| 186 | a_Arg_List prepend_arg_list( a_Type_Decl type_decl, a_Var_Decl var_decl, a_Arg_List arg_list, int pos ); | ||
| 187 | a_Array_Sub new_array_sub( a_Exp exp, int pos ); | ||
| 188 | a_Array_Sub prepend_array_sub( a_Array_Sub array, a_Exp exp, int pos ); | ||
| 189 | a_Complex new_complex( a_Exp re, int pos ); | ||
| 190 | a_Polar new_polar( a_Exp mod, int pos ); // ge: added 1.3.5.3 | ||
| 191 | a_Vec new_vec( a_Exp e, int pos ); | ||
| 192 | |||
| 193 | a_Class_Def new_class_def( ae_Keyword class_decl, a_Id_List xid, a_Class_Ext ext, a_Class_Body body, int pos ); | ||
| 194 | a_Class_Body new_class_body( a_Section section, int pos ); | ||
| 195 | a_Class_Body prepend_class_body( a_Section section, a_Class_Body body, int pos ); | ||
| 196 | a_Class_Ext new_class_ext( a_Id_List extend_id, a_Id_List impl_list, int pos ); | ||
| 197 | a_Class_Def new_iface_def( ae_Keyword class_decl, a_Id_List xid, a_Class_Ext ext, a_Class_Body body, int pos ); | ||
| 198 | a_Id_List new_id_list( c_constr xid, int pos ); | ||
| 199 | a_Id_List prepend_id_list( c_constr xid, a_Id_List list, int pos ); | ||
| 200 | void clean_exp( a_Exp exp ); | ||
| 201 | a_Func_Def new_func_def( ae_Keyword func_decl, ae_Keyword static_decl, | ||
| 202 | a_Type_Decl type_decl, c_str name, | ||
| 203 | a_Arg_List arg_list, a_Stmt code, int pos ); | ||
| 204 | |||
| 205 | void delete_id_list( a_Id_List x ); | ||
| 206 | |||
| 207 | |||
| 208 | |||
| 209 | |||
| 210 | //------------------------------------------------------------------------------ | ||
| 211 | // structs | ||
| 212 | //------------------------------------------------------------------------------ | ||
| 213 | struct a_Exp_Binary_ { a_Exp lhs; ae_Operator op; a_Exp rhs; t_CKFUNC ck_func; int linepos; a_Exp self; }; | ||
| 214 | struct a_Exp_Cast_ { a_Type_Decl type; a_Exp exp; int linepos; a_Exp self; }; | ||
| 215 | struct a_Exp_Unary_ { ae_Operator op; a_Exp exp; a_Type_Decl type; a_Array_Sub array; | ||
| 216 | a_Stmt code; int linepos; a_Exp self; }; | ||
| 217 | struct a_Exp_Postfix_ { a_Exp exp; ae_Operator op; int linepos; a_Exp self; }; | ||
| 218 | struct a_Exp_Dur_ { a_Exp base; a_Exp unit; int linepos; a_Exp self; }; | ||
| 219 | struct a_Exp_Array_ { a_Exp base; a_Array_Sub indices; int linepos; a_Exp self; }; | ||
| 220 | struct a_Exp_Func_Call_ { a_Exp func; a_Exp args; t_CKTYPE ret_type; | ||
| 221 | t_CKFUNC ck_func; t_CKVMCODE ck_vm_code; int linepos; a_Exp self; }; | ||
| 222 | struct a_Exp_Dot_Member_ { a_Exp base; t_CKTYPE t_base; S_Symbol xid; int linepos; a_Exp self; }; | ||
| 223 | struct a_Exp_If_ { a_Exp cond; a_Exp if_exp; a_Exp else_exp; int linepos; a_Exp self; }; | ||
| 224 | struct a_Exp_Decl_ { a_Type_Decl type; a_Var_Decl_List var_decl_list; int num_var_decls; int is_static; int is_external; | ||
| 225 | t_CKTYPE ck_type; int linepos; a_Exp self; }; | ||
| 226 | struct a_Exp_Hack_ { a_Exp exp; int linepos; a_Exp self; }; | ||
| 227 | struct a_Var_Decl_List_ { a_Var_Decl var_decl; a_Var_Decl_List next; int linepos; a_Exp self; }; | ||
| 228 | struct a_Var_Decl_ { S_Symbol xid; a_Var_Decl var_decl; a_Array_Sub array; t_CKVALUE value; | ||
| 229 | void * addr; int linepos; a_Exp self; }; | ||
| 230 | struct a_Type_Decl_ { a_Id_List xid; a_Array_Sub array; int ref; int linepos; /*a_Exp self;*/ }; | ||
| 231 | struct a_Array_Sub_ { t_CKUINT depth; a_Exp exp_list; int linepos; a_Exp self; | ||
| 232 | int err_num; int err_pos; }; | ||
| 233 | struct a_Arg_List_ { a_Type_Decl type_decl; a_Var_Decl var_decl; t_CKTYPE type; | ||
| 234 | a_Arg_List next; int linepos; a_Exp self; }; | ||
| 235 | struct a_Complex_ { a_Exp re; a_Exp im; int linepos; a_Exp self; }; | ||
| 236 | struct a_Polar_ { a_Exp mod; a_Exp phase; int linepos; a_Exp self; }; | ||
| 237 | struct a_Vec_ { a_Exp args; int numdims; int linepos; a_Exp self; }; // ge: added 1.3.5.3 | ||
| 238 | |||
| 239 | // enum primary exp type | ||
| 240 | typedef enum { ae_primary_var, ae_primary_num, ae_primary_float, | ||
| 241 | ae_primary_str, ae_primary_array, ae_primary_exp, | ||
| 242 | ae_primary_hack, ae_primary_complex, ae_primary_polar, | ||
| 243 | ae_primary_vec, ae_primary_char, ae_primary_nil | ||
| 244 | } ae_Exp_Primary_Type; | ||
| 245 | |||
| 246 | struct a_Exp_Primary_ | ||
| 247 | { | ||
| 248 | ae_Exp_Primary_Type s_type; | ||
| 249 | t_CKVALUE value; | ||
| 250 | |||
| 251 | union | ||
| 252 | { | ||
| 253 | S_Symbol var; | ||
| 254 | t_CKINT num; | ||
| 255 | t_CKFLOAT fnum; | ||
| 256 | c_str str; | ||
| 257 | c_str chr; | ||
| 258 | a_Array_Sub array; | ||
| 259 | a_Exp exp; | ||
| 260 | a_Complex complex; | ||
| 261 | a_Polar polar; | ||
| 262 | a_Vec vec; // ge: added 1.3.5.3 | ||
| 263 | }; | ||
| 264 | |||
| 265 | int linepos; | ||
| 266 | a_Exp self; | ||
| 267 | }; | ||
| 268 | |||
| 269 | // enum exp type | ||
| 270 | typedef enum { ae_exp_binary = 0, ae_exp_unary, ae_exp_cast, ae_exp_postfix, | ||
| 271 | ae_exp_dur, ae_exp_primary, ae_exp_array, ae_exp_func_call, | ||
| 272 | ae_exp_dot_member, ae_exp_if, ae_exp_decl | ||
| 273 | } ae_Exp_Type; | ||
| 274 | // type meta data | ||
| 275 | typedef enum { ae_meta_value = 0, ae_meta_var } ae_Exp_Meta; | ||
| 276 | |||
| 277 | struct a_Exp_ | ||
| 278 | { | ||
| 279 | ae_Exp_Type s_type; | ||
| 280 | ae_Exp_Meta s_meta; | ||
| 281 | t_CKTYPE type; | ||
| 282 | t_CKNSPC owner; | ||
| 283 | a_Exp next; | ||
| 284 | |||
| 285 | t_CKUINT group_size; | ||
| 286 | t_CKTYPE cast_to; | ||
| 287 | t_CKUINT emit_var; // 1 = emit var, 2 = emit var and value | ||
| 288 | |||
| 289 | union | ||
| 290 | { | ||
| 291 | struct a_Exp_Binary_ binary; | ||
| 292 | struct a_Exp_Unary_ unary; | ||
| 293 | struct a_Exp_Cast_ cast; | ||
| 294 | struct a_Exp_Postfix_ postfix; | ||
| 295 | struct a_Exp_Dur_ dur; | ||
| 296 | struct a_Exp_Primary_ primary; | ||
| 297 | struct a_Exp_Array_ array; | ||
| 298 | struct a_Exp_Func_Call_ func_call; | ||
| 299 | struct a_Exp_Dot_Member_ dot_member; | ||
| 300 | struct a_Exp_If_ exp_if; | ||
| 301 | struct a_Exp_Decl_ decl; | ||
| 302 | }; | ||
| 303 | |||
| 304 | int linepos; | ||
| 305 | }; | ||
| 306 | |||
| 307 | struct a_Stmt_While_ { int is_do; a_Exp cond; a_Stmt body; int linepos; a_Stmt self; }; | ||
| 308 | struct a_Stmt_Until_ { int is_do; a_Exp cond; a_Stmt body; int linepos; a_Stmt self; }; | ||
| 309 | struct a_Stmt_For_ { a_Stmt c1; a_Stmt c2; a_Exp c3; a_Stmt body; int linepos; a_Stmt self; }; | ||
| 310 | struct a_Stmt_Loop_ { a_Exp cond; a_Stmt body; int linepos; a_Stmt self; }; | ||
| 311 | struct a_Stmt_Code_ { a_Stmt_List stmt_list; int linepos; a_Stmt self; }; | ||
| 312 | struct a_Stmt_If_ { a_Exp cond; a_Stmt if_body; a_Stmt else_body; int linepos; a_Stmt self; }; | ||
| 313 | struct a_Stmt_Switch_ { a_Exp val; int linepos; a_Stmt self; }; | ||
| 314 | struct a_Stmt_Break_ { int linepos; a_Stmt self; }; | ||
| 315 | struct a_Stmt_Continue_ { int linepos; a_Stmt self; }; | ||
| 316 | struct a_Stmt_Return_ { a_Exp val; int linepos; a_Stmt self; }; | ||
| 317 | struct a_Stmt_Case_ { a_Exp exp; int linepos; a_Stmt self; }; | ||
| 318 | struct a_Stmt_GotoLabel_ { S_Symbol name; int linepos; a_Stmt self; }; | ||
| 319 | |||
| 320 | // enum values for stmt type | ||
| 321 | typedef enum { ae_stmt_exp, ae_stmt_while, ae_stmt_until, ae_stmt_for, ae_stmt_loop, | ||
| 322 | ae_stmt_if, ae_stmt_code, ae_stmt_switch, ae_stmt_break, | ||
| 323 | ae_stmt_continue, ae_stmt_return, ae_stmt_case, ae_stmt_gotolabel | ||
| 324 | } ae_Stmt_Type; | ||
| 325 | |||
| 326 | struct a_Stmt_ | ||
| 327 | { | ||
| 328 | ae_Stmt_Type s_type; | ||
| 329 | int skip; | ||
| 330 | |||
| 331 | union | ||
| 332 | { | ||
| 333 | a_Exp stmt_exp; | ||
| 334 | struct a_Stmt_Code_ stmt_code; | ||
| 335 | struct a_Stmt_While_ stmt_while; | ||
| 336 | struct a_Stmt_Until_ stmt_until; | ||
| 337 | struct a_Stmt_Loop_ stmt_loop; | ||
| 338 | struct a_Stmt_For_ stmt_for; | ||
| 339 | struct a_Stmt_If_ stmt_if; | ||
| 340 | struct a_Stmt_Switch_ stmt_switch; | ||
| 341 | struct a_Stmt_Break_ stmt_break; | ||
| 342 | struct a_Stmt_Continue_ stmt_continue; | ||
| 343 | struct a_Stmt_Return_ stmt_return; | ||
| 344 | struct a_Stmt_Case_ stmt_case; | ||
| 345 | struct a_Stmt_GotoLabel_ stmt_gotolabel; | ||
| 346 | }; | ||
| 347 | |||
| 348 | int linepos; | ||
| 349 | }; | ||
| 350 | |||
| 351 | struct a_Stmt_List_ { a_Stmt stmt; a_Stmt_List next; int linepos; }; | ||
| 352 | struct a_Class_Def_ { ae_Keyword decl; a_Id_List name; a_Class_Ext ext; | ||
| 353 | a_Class_Body body; t_CKTYPE type; int iface; t_CKNSPC home; | ||
| 354 | int linepos; }; | ||
| 355 | struct a_Class_Ext_ { a_Id_List extend_id; a_Id_List impl_list; int linepos; }; | ||
| 356 | struct a_Class_Body_ { a_Section section; a_Class_Body next; int linepos; }; | ||
| 357 | struct a_Id_List_ { S_Symbol xid; a_Id_List next; int linepos; }; | ||
| 358 | |||
| 359 | typedef enum { ae_func_user, ae_func_builtin } ae_Func_Type; | ||
| 360 | // struct t_Func_User_ { int linepos; }; | ||
| 361 | // typedef unsigned int (* builtin_func_ptr)( unsigned int arg ); | ||
| 362 | // struct t_Func_BuiltIn_ { builtin_func_ptr func_ptr; int linepos; }; | ||
| 363 | struct a_Func_Def_ { | ||
| 364 | ae_Keyword func_decl; | ||
| 365 | ae_Keyword static_decl; | ||
| 366 | a_Type_Decl type_decl; | ||
| 367 | t_CKTYPE ret_type; | ||
| 368 | S_Symbol name; | ||
| 369 | a_Arg_List arg_list; | ||
| 370 | a_Stmt code; | ||
| 371 | t_CKFUNC ck_func; | ||
| 372 | unsigned int global; | ||
| 373 | unsigned int s_type; | ||
| 374 | unsigned int stack_depth; | ||
| 375 | void * dl_func_ptr; // should be not NULL iff s_type == ae_func_builtin | ||
| 376 | int linepos; | ||
| 377 | }; | ||
| 378 | |||
| 379 | // enum values for section types | ||
| 380 | typedef enum { ae_section_stmt, ae_section_func, ae_section_class | ||
| 381 | } ae_Section_Type; | ||
| 382 | |||
| 383 | struct a_Section_ | ||
| 384 | { | ||
| 385 | ae_Section_Type s_type; | ||
| 386 | |||
| 387 | union | ||
| 388 | { | ||
| 389 | a_Stmt_List stmt_list; | ||
| 390 | a_Class_Def class_def; | ||
| 391 | a_Func_Def func_def; | ||
| 392 | }; | ||
| 393 | |||
| 394 | int linepos; | ||
| 395 | }; | ||
| 396 | |||
| 397 | struct a_Program_ { a_Section section; a_Program next; int linepos; }; | ||
| 398 | |||
| 399 | |||
| 400 | #if defined(_cplusplus) || defined(__cplusplus) | ||
| 401 | } | ||
| 402 | #endif | ||
| 403 | |||
| 404 | |||
| 405 | |||
| 406 | #endif | ||
| @@ -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 references | 44 | |
| 45 | // forward references (C++) | ||
| 44 | class Chuck_Compiler; | 46 | class Chuck_Compiler; |
| 45 | class Chuck_VM; | 47 | class Chuck_VM; |
| 46 | class Chuck_Env; | 48 | class Chuck_Env; |
| 47 | class Chuck_IO_Chout; | 49 | class Chuck_IO_Chout; |
| 48 | class Chuck_IO_Cherr; | 50 | class Chuck_IO_Cherr; |
| 49 | 51 | ||
| 52 | // forward references ("C") | ||
| 53 | struct 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 | // constructor | 74 | // 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 | ||
| @@ -0,0 +1,900 @@ | |||
| 1 | /*---------------------------------------------------------------------------- | ||
| 2 | ChucK Concurrent, On-the-fly Audio Programming Language | ||
| 3 | Compiler and Virtual Machine | ||
| 4 | |||
| 5 | Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. | ||
| 6 | http://chuck.stanford.edu/ | ||
| 7 | http://chuck.cs.princeton.edu/ | ||
| 8 | |||
| 9 | This program is free software; you can redistribute it and/or modify | ||
| 10 | it under the terms of the GNU General Public License as published by | ||
| 11 | the Free Software Foundation; either version 2 of the License, or | ||
| 12 | (at your option) any later version. | ||
| 13 | |||
| 14 | This program is distributed in the hope that it will be useful, | ||
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | GNU General Public License for more details. | ||
| 18 | |||
| 19 | You should have received a copy of the GNU General Public License | ||
| 20 | along with this program; if not, write to the Free Software | ||
| 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
| 22 | U.S.A. | ||
| 23 | -----------------------------------------------------------------------------*/ | ||
| 24 | |||
| 25 | //----------------------------------------------------------------------------- | ||
| 26 | // file: chuck_compile.cpp | ||
| 27 | // desc: chuck compile system unifying parser, type checker, and emitter | ||
| 28 | // | ||
| 29 | // author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) | ||
| 30 | // date: Autumn 2005 - original | ||
| 31 | //----------------------------------------------------------------------------- | ||
| 32 | #include "chuck_compile.h" | ||
| 33 | #include "chuck_lang.h" | ||
| 34 | #include "chuck_errmsg.h" | ||
| 35 | #include "chuck_otf.h" | ||
| 36 | |||
| 37 | #include "ugen_osc.h" | ||
| 38 | #include "ugen_xxx.h" | ||
| 39 | #include "ugen_filter.h" | ||
| 40 | #include "ugen_stk.h" | ||
| 41 | #include "uana_xform.h" | ||
| 42 | #include "uana_extract.h" | ||
| 43 | #include "ulib_machine.h" | ||
| 44 | #include "ulib_math.h" | ||
| 45 | #include "ulib_std.h" | ||
| 46 | #include "ulib_opsc.h" | ||
| 47 | #include "ulib_regex.h" | ||
| 48 | #include "chuck_io.h" | ||
| 49 | |||
| 50 | #if defined(__PLATFORM_WIN32__) | ||
| 51 | #include "dirent_win32.h" | ||
| 52 | #endif | ||
| 53 | //#if defined(__WINDOWS_PTHREAD__) | ||
| 54 | #include <sys/stat.h> | ||
| 55 | //#endif | ||
| 56 | |||
| 57 | using namespace std; | ||
| 58 | |||
| 59 | |||
| 60 | |||
| 61 | |||
| 62 | // function prototypes | ||
| 63 | t_CKBOOL load_internal_modules( Chuck_Compiler * compiler ); | ||
| 64 | t_CKBOOL load_external_modules( Chuck_Compiler * compiler, | ||
| 65 | const char * extension, | ||
| 66 | std::list<std::string> & chugin_search_paths, | ||
| 67 | std::list<std::string> & named_dls); | ||
| 68 | t_CKBOOL load_module( Chuck_Compiler * compiler, Chuck_Env * env, f_ck_query query, const char * name, const char * nspc ); | ||
| 69 | |||
| 70 | |||
| 71 | |||
| 72 | |||
| 73 | //----------------------------------------------------------------------------- | ||
| 74 | // name: Chuck_Compiler() | ||
| 75 | // desc: constructor | ||
| 76 | //----------------------------------------------------------------------------- | ||
| 77 | Chuck_Compiler::Chuck_Compiler() | ||
| 78 | { | ||
| 79 | emitter = NULL; | ||
| 80 | code = NULL; | ||
| 81 | |||
| 82 | // REFACTOR-2017: add carrier | ||
| 83 | m_carrier = NULL; | ||
| 84 | } | ||
| 85 | |||
| 86 | |||
| 87 | |||
| 88 | |||
| 89 | //----------------------------------------------------------------------------- | ||
| 90 | // name: ~Chuck_Compiler() | ||
| 91 | // desc: destructor | ||
| 92 | //----------------------------------------------------------------------------- | ||
| 93 | Chuck_Compiler::~Chuck_Compiler() | ||
| 94 | { | ||
| 95 | // call shutdown | ||
| 96 | this->shutdown(); | ||
| 97 | } | ||
| 98 | |||
| 99 | |||
| 100 | |||
| 101 | |||
| 102 | //----------------------------------------------------------------------------- | ||
| 103 | // name: initialize() | ||
| 104 | // desc: initialize the compiler | ||
| 105 | //----------------------------------------------------------------------------- | ||
| 106 | t_CKBOOL Chuck_Compiler::initialize( std::list<std::string> & chugin_search_paths, | ||
| 107 | std::list<std::string> & named_dls ) | ||
| 108 | { | ||
| 109 | // log | ||
| 110 | EM_log( CK_LOG_SYSTEM, "initializing compiler..." ); | ||
| 111 | // push indent level | ||
| 112 | EM_pushlog(); | ||
| 113 | |||
| 114 | // allocate the type checker | ||
| 115 | Chuck_Env * env = type_engine_init( m_carrier ); | ||
| 116 | // add reference | ||
| 117 | env->add_ref(); | ||
| 118 | |||
| 119 | // allocate the emitter | ||
| 120 | emitter = emit_engine_init( env ); | ||
| 121 | // add reference | ||
| 122 | emitter->add_ref(); | ||
| 123 | // set auto depend to 0 | ||
| 124 | m_auto_depend = FALSE; | ||
| 125 | |||
| 126 | // load internal libs | ||
| 127 | if( !load_internal_modules( this ) ) | ||
| 128 | goto error; | ||
| 129 | |||
| 130 | // load external libs | ||
| 131 | if( !load_external_modules( this, ".chug", chugin_search_paths, named_dls ) ) | ||
| 132 | goto error; | ||
| 133 | |||
| 134 | // pop indent | ||
| 135 | EM_poplog(); | ||
| 136 | |||
| 137 | return TRUE; | ||
| 138 | |||
| 139 | error: | ||
| 140 | // clean up | ||
| 141 | this->shutdown(); | ||
| 142 | |||
| 143 | // pop indent | ||
| 144 | EM_poplog(); | ||
| 145 | |||
| 146 | return FALSE; | ||
| 147 | } | ||
| 148 | |||
| 149 | |||
| 150 | |||
| 151 | |||
| 152 | //----------------------------------------------------------------------------- | ||
| 153 | // name: shutdown() | ||
| 154 | // desc: shutdown the compiler | ||
| 155 | //----------------------------------------------------------------------------- | ||
| 156 | void Chuck_Compiler::shutdown() | ||
| 157 | { | ||
| 158 | // log | ||
| 159 | EM_log( CK_LOG_SYSTEM, "shutting down compiler..." ) ; | ||
| 160 | // push indent | ||
| 161 | EM_pushlog(); | ||
| 162 | |||
| 163 | // TODO: free | ||
| 164 | type_engine_shutdown( env() ); | ||
| 165 | // TODO: check if emitter gets cleaned up | ||
| 166 | // emit_engine_shutdown( emitter ); | ||
| 167 | emitter = NULL; | ||
| 168 | code = NULL; | ||
| 169 | m_auto_depend = FALSE; | ||
| 170 | m_recent.clear(); | ||
| 171 | |||
| 172 | for(std::list<Chuck_DLL *>::iterator i = m_dlls.begin(); | ||
| 173 | i != m_dlls.end(); i++) | ||
| 174 | { | ||
| 175 | delete (*i); | ||
| 176 | } | ||
| 177 | |||
| 178 | m_dlls.clear(); | ||
| 179 | |||
| 180 | // pop indent | ||
| 181 | EM_poplog(); | ||
| 182 | } | ||
| 183 | |||
| 184 | |||
| 185 | |||
| 186 | |||
| 187 | |||
| 188 | //----------------------------------------------------------------------------- | ||
| 189 | // name: bind() | ||
| 190 | // desc: bind a new type system module, via query function | ||
| 191 | //----------------------------------------------------------------------------- | ||
| 192 | t_CKBOOL Chuck_Compiler::bind( f_ck_query query_func, const std::string & name, | ||
| 193 | const std::string & nspc ) | ||
| 194 | { | ||
| 195 | // log | ||
| 196 | EM_log( CK_LOG_SYSTEM, "on-demand binding compiler module '%s'...", | ||
| 197 | name.c_str() ); | ||
| 198 | // push indent level | ||
| 199 | EM_pushlog(); | ||
| 200 | |||
| 201 | // get env | ||
| 202 | Chuck_Env * env = this->env(); | ||
| 203 | // make context | ||
| 204 | Chuck_Context * context = type_engine_make_context( | ||
| 205 | NULL, string("@[bind:") + name + string("]") ); | ||
| 206 | // reset env - not needed since we just created the env | ||
| 207 | env->reset(); | ||
| 208 | // load it | ||
| 209 | type_engine_load_context( env, context ); | ||
| 210 | |||
| 211 | // do it | ||
| 212 | if( !load_module( this, env, query_func, name.c_str(), nspc.c_str() ) ) goto error; | ||
| 213 | |||
| 214 | // clear context | ||
| 215 | type_engine_unload_context( env ); | ||
| 216 | |||
| 217 | // commit what is in the type checker at this point | ||
| 218 | env->global()->commit(); | ||
| 219 | |||
| 220 | // pop indent level | ||
| 221 | EM_poplog(); | ||
| 222 | |||
| 223 | return TRUE; | ||
| 224 | |||
| 225 | error: | ||
| 226 | |||
| 227 | // probably dangerous: rollback | ||
| 228 | env->global()->rollback(); | ||
| 229 | |||
| 230 | // clear context | ||
| 231 | type_engine_unload_context( env ); | ||
| 232 | |||
| 233 | // pop indent level | ||
| 234 | EM_poplog(); | ||
| 235 | |||
| 236 | return FALSE; | ||
| 237 | } | ||
| 238 | |||
| 239 | |||
| 240 | |||
| 241 | |||
| 242 | //----------------------------------------------------------------------------- | ||
| 243 | // name: set_auto_depend() | ||
| 244 | // desc: auto dependency resolve for types | ||
| 245 | //----------------------------------------------------------------------------- | ||
| 246 | void Chuck_Compiler::set_auto_depend( t_CKBOOL v ) | ||
| 247 | { | ||
| 248 | // log | ||
| 249 | EM_log( CK_LOG_SYSTEM, "type dependency resolution: %s", | ||
| 250 | v ? "AUTO" : "MANUAL" ); | ||
| 251 | m_auto_depend = v; | ||
| 252 | } | ||
| 253 | |||
| 254 | |||
| 255 | |||
| 256 | |||
| 257 | //----------------------------------------------------------------------------- | ||
| 258 | // name: go() | ||
| 259 | // desc: parse, type-check, and emit a program | ||
| 260 | //----------------------------------------------------------------------------- | ||
| 261 | t_CKBOOL Chuck_Compiler::go( const string & filename, FILE * fd, const char * str_src, const string & full_path ) | ||
| 262 | { | ||
| 263 | t_CKBOOL ret = TRUE; | ||
| 264 | Chuck_Context * context = NULL; | ||
| 265 | |||
| 266 | EM_reset_msg(); | ||
| 267 | |||
| 268 | // check to see if resolve dependencies automatically | ||
| 269 | if( !m_auto_depend ) | ||
| 270 | { | ||
| 271 | // normal (note: full_path added 1.3.0.0) | ||
| 272 | ret = this->do_normal( filename, fd, str_src, full_path ); | ||
| 273 | return ret; | ||
| 274 | } | ||
| 275 | else // auto | ||
| 276 | { | ||
| 277 | // parse the code | ||
| 278 | if( !chuck_parse( filename.c_str(), fd, str_src ) ) | ||
| 279 | return FALSE; | ||
| 280 | |||
| 281 | // make the context | ||
| 282 | context = type_engine_make_context( g_program, filename ); | ||
| 283 | if( !context ) return FALSE; | ||
| 284 | |||
| 285 | // reset the env | ||
| 286 | env()->reset(); | ||
| 287 | |||
| 288 | // load the context | ||
| 289 | if( !type_engine_load_context( env(), context ) ) | ||
| 290 | return FALSE; | ||
| 291 | |||
| 292 | // do entire file | ||
| 293 | if( !do_entire_file( context ) ) | ||
| 294 | { ret = FALSE; goto cleanup; } | ||
| 295 | |||
| 296 | // get the code | ||
| 297 | if( !(code = context->code()) ) | ||
| 298 | { | ||
| 299 | ret = FALSE; | ||
| 300 | EM_error2( 0, "internal error: context->code() NULL!" ); | ||
| 301 | goto cleanup; | ||
| 302 | } | ||
| 303 | |||
| 304 | cleanup: | ||
| 305 | |||
| 306 | // commit | ||
| 307 | if( ret ) env()->global()->commit(); | ||
| 308 | // or rollback | ||
| 309 | else env()->global()->rollback(); | ||
| 310 | |||
| 311 | // unload the context from the type-checker | ||
| 312 | if( !type_engine_unload_context( env() ) ) | ||
| 313 | { | ||
| 314 | EM_error2( 0, "internal error unloading context...\n" ); | ||
| 315 | return FALSE; | ||
| 316 | } | ||
| 317 | |||
| 318 | return ret; | ||
| 319 | } | ||
| 320 | } | ||
| 321 | |||
| 322 | |||
| 323 | |||
| 324 | |||
| 325 | //----------------------------------------------------------------------------- | ||
| 326 | // name: resolve() | ||
| 327 | // desc: resolve type automatically - if auto_depend is off, return FALSE | ||
| 328 | //----------------------------------------------------------------------------- | ||
| 329 | t_CKBOOL Chuck_Compiler::resolve( const string & type ) | ||
| 330 | { | ||
| 331 | t_CKBOOL ret = TRUE; | ||
| 332 | |||
| 333 | // check auto_depend | ||
| 334 | if( !m_auto_depend ) | ||
| 335 | return FALSE; | ||
| 336 | |||
| 337 | // look up if name is already parsed | ||
| 338 | |||
| 339 | |||
| 340 | |||
| 341 | return ret; | ||
| 342 | } | ||
| 343 | |||
| 344 | |||
| 345 | |||
| 346 | |||
| 347 | //----------------------------------------------------------------------------- | ||
| 348 | // name: do_entire_file() | ||
| 349 | // desc: parse, type-check, and emit a program | ||
| 350 | //----------------------------------------------------------------------------- | ||
| 351 | t_CKBOOL Chuck_Compiler::do_entire_file( Chuck_Context * context ) | ||
| 352 | { | ||
| 353 | // 0th-scan (pass 0) | ||
| 354 | if( !type_engine_scan0_prog( env(), g_program, te_do_all ) ) | ||
| 355 | return FALSE; | ||
| 356 | |||
| 357 | // 1st-scan (pass 1) | ||
| 358 | if( !type_engine_scan1_prog( env(), g_program, te_do_all ) ) | ||
| 359 | return FALSE; | ||
| 360 | |||
| 361 | // 2nd-scan (pass 2) | ||
| 362 | if( !type_engine_scan2_prog( env(), g_program, te_do_all ) ) | ||
| 363 | return FALSE; | ||
| 364 | |||
| 365 | // check the program (pass 3) | ||
| 366 | if( !type_engine_check_context( env(), context, te_do_all ) ) | ||
| 367 | return FALSE; | ||
| 368 | |||
| 369 | // emit (pass 4) | ||
| 370 | if( !emit_engine_emit_prog( emitter, g_program ) ) | ||
| 371 | return FALSE; | ||
| 372 | |||
| 373 | // set the state of the context to done | ||
| 374 | context->progress = Chuck_Context::P_ALL; | ||
| 375 | |||
| 376 | return TRUE; | ||
| 377 | } | ||
| 378 | |||
| 379 | |||
| 380 | |||
| 381 | |||
| 382 | //----------------------------------------------------------------------------- | ||
| 383 | // name: do_only_classes() | ||
| 384 | // desc: compile only classes definitions | ||
| 385 | //----------------------------------------------------------------------------- | ||
| 386 | t_CKBOOL Chuck_Compiler::do_only_classes( Chuck_Context * context ) | ||
| 387 | { | ||
| 388 | // 0th-scan (pass 0) | ||
| 389 | if( !type_engine_scan0_prog( env(), g_program, te_do_classes_only ) ) | ||
| 390 | return FALSE; | ||
| 391 | |||
| 392 | // 1st-scan (pass 1) | ||
| 393 | if( !type_engine_scan1_prog( env(), g_program, te_do_classes_only ) ) | ||
| 394 | return FALSE; | ||
| 395 | |||
| 396 | // 2nd-scan (pass 2) | ||
| 397 | if( !type_engine_scan2_prog( env(), g_program, te_do_classes_only ) ) | ||
| 398 | return FALSE; | ||
| 399 | |||
| 400 | // check the program (pass 3) | ||
| 401 | if( !type_engine_check_context( env(), context, te_do_classes_only ) ) | ||
| 402 | return FALSE; | ||
| 403 | |||
| 404 | // emit (pass 4) | ||
| 405 | if( !(code = emit_engine_emit_prog( emitter, g_program , te_do_classes_only )) ) | ||
| 406 | return FALSE; | ||
| 407 | |||
| 408 | // set the state of the context to done | ||
| 409 | context->progress = Chuck_Context::P_ALL; | ||
| 410 | |||
| 411 | return TRUE; | ||
| 412 | } | ||
| 413 | |||
| 414 | |||
| 415 | |||
| 416 | |||
| 417 | //----------------------------------------------------------------------------- | ||
| 418 | // name: do_all_except_classes() | ||
| 419 | // desc: compile everything except classes | ||
| 420 | //----------------------------------------------------------------------------- | ||
| 421 | t_CKBOOL Chuck_Compiler::do_all_except_classes( Chuck_Context * context ) | ||
| 422 | { | ||
| 423 | // 0th scan only deals with classes, so is not needed | ||
| 424 | |||
| 425 | // 1st-scan (pass 1) | ||
| 426 | if( !type_engine_scan1_prog( env(), g_program, te_do_no_classes ) ) | ||
| 427 | return FALSE; | ||
| 428 | |||
| 429 | // 2nd-scan (pass 2) | ||
| 430 | if( !type_engine_scan2_prog( env(), g_program, te_do_no_classes ) ) | ||
| 431 | return FALSE; | ||
| 432 | |||
| 433 | // check the program (pass 3) | ||
| 434 | if( !type_engine_check_context( env(), context, te_do_no_classes ) ) | ||
| 435 | return FALSE; | ||
| 436 | |||
| 437 | // emit (pass 4) | ||
| 438 | if( !(code = emit_engine_emit_prog( emitter, g_program, te_do_no_classes )) ) | ||
| 439 | return FALSE; | ||
| 440 | |||
| 441 | // set the state of the context to done | ||
| 442 | context->progress = Chuck_Context::P_ALL; | ||
| 443 | |||
| 444 | return TRUE; | ||
| 445 | } | ||
| 446 | |||
| 447 | |||
| 448 | |||
| 449 | |||
| 450 | //----------------------------------------------------------------------------- | ||
| 451 | // name: do_normal() | ||
| 452 | // desc: compile normally without auto-depend | ||
| 453 | //----------------------------------------------------------------------------- | ||
| 454 | t_CKBOOL Chuck_Compiler::do_normal( const string & filename, FILE * fd, const char * str_src, const string & full_path ) | ||
| 455 | { | ||
| 456 | t_CKBOOL ret = TRUE; | ||
| 457 | Chuck_Context * context = NULL; | ||
| 458 | |||
| 459 | // parse the code | ||
| 460 | if( !chuck_parse( filename.c_str(), fd, str_src ) ) | ||
| 461 | return FALSE; | ||
| 462 | |||
| 463 | // make the context | ||
| 464 | context = type_engine_make_context( g_program, filename ); | ||
| 465 | if( !context ) return FALSE; | ||
| 466 | |||
| 467 | // remember full path (added 1.3.0.0) | ||
| 468 | context->full_path = full_path; | ||
| 469 | |||
| 470 | // reset the env | ||
| 471 | env()->reset(); | ||
| 472 | |||
| 473 | // load the context | ||
| 474 | if( !type_engine_load_context( env(), context ) ) | ||
| 475 | return FALSE; | ||
| 476 | |||
| 477 | // 0th-scan (pass 0) | ||
| 478 | if( !type_engine_scan0_prog( env(), g_program, te_do_all ) ) | ||
| 479 | { ret = FALSE; goto cleanup; } | ||
| 480 | |||
| 481 | // 1st-scan (pass 1) | ||
| 482 | if( !type_engine_scan1_prog( env(), g_program, te_do_all ) ) | ||
| 483 | { ret = FALSE; goto cleanup; } | ||
| 484 | |||
| 485 | // 2nd-scan (pass 2) | ||
| 486 | if( !type_engine_scan2_prog( env(), g_program, te_do_all ) ) | ||
| 487 | { ret = FALSE; goto cleanup; } | ||
| 488 | |||
| 489 | // check the program (pass 3) | ||
| 490 | if( !type_engine_check_context( env(), context, te_do_all ) ) | ||
| 491 | { ret = FALSE; goto cleanup; } | ||
| 492 | |||
| 493 | // emit (pass 4) | ||
| 494 | if( !(code = emit_engine_emit_prog( emitter, g_program, te_do_all )) ) | ||
| 495 | { ret = FALSE; goto cleanup; } | ||
| 496 | |||
| 497 | cleanup: | ||
| 498 | |||
| 499 | // commit | ||
| 500 | if( ret ) env()->global()->commit(); | ||
| 501 | // or rollback | ||
| 502 | else env()->global()->rollback(); | ||
| 503 | |||
| 504 | // unload the context from the type-checker | ||
| 505 | if( !type_engine_unload_context( env() ) ) | ||
| 506 | { | ||
| 507 | EM_error2( 0, "internal error unloading context...\n" ); | ||
| 508 | return FALSE; | ||
| 509 | } | ||
| 510 | |||
| 511 | return ret; | ||
| 512 | } | ||
| 513 | |||
| 514 | |||
| 515 | |||
| 516 | |||
| 517 | //----------------------------------------------------------------------------- | ||
| 518 | // name: find_recent_path() | ||
| 519 | // desc: find recent context by path | ||
| 520 | //----------------------------------------------------------------------------- | ||
| 521 | Chuck_Context * Chuck_Compiler::find_recent_path( const string & path ) | ||
| 522 | { | ||
| 523 | return NULL; | ||
| 524 | } | ||
| 525 | |||
| 526 | |||
| 527 | |||
| 528 | |||
| 529 | //----------------------------------------------------------------------------- | ||
| 530 | // name: find_recent_type() | ||
| 531 | // desc: find recent context by type name | ||
| 532 | //----------------------------------------------------------------------------- | ||
| 533 | Chuck_Context * Chuck_Compiler::find_recent_type( const string & type ) | ||
| 534 | { | ||
| 535 | return NULL; | ||
| 536 | } | ||
| 537 | |||
| 538 | |||
| 539 | |||
| 540 | |||
| 541 | //----------------------------------------------------------------------------- | ||
| 542 | // name: add_recent_path() | ||
| 543 | // desc: add recent context by path | ||
| 544 | //----------------------------------------------------------------------------- | ||
| 545 | t_CKBOOL Chuck_Compiler::add_recent_path( const string & path, | ||
| 546 | Chuck_Context * context ) | ||
| 547 | { | ||
| 548 | return TRUE; | ||
| 549 | } | ||
| 550 | |||
| 551 | |||
| 552 | |||
| 553 | |||
| 554 | //----------------------------------------------------------------------------- | ||
| 555 | // name: output() | ||
| 556 | // desc: get the code generated by the last do() | ||
| 557 | //----------------------------------------------------------------------------- | ||
| 558 | Chuck_VM_Code * Chuck_Compiler::output() | ||
| 559 | { | ||
| 560 | return this->code; | ||
| 561 | } | ||
| 562 | |||
| 563 | |||
| 564 | |||
| 565 | |||
| 566 | //----------------------------------------------------------------------------- | ||
| 567 | // name: load_module() | ||
| 568 | // desc: load a dll and add it | ||
| 569 | //----------------------------------------------------------------------------- | ||
| 570 | t_CKBOOL load_module( Chuck_Compiler * compiler, Chuck_Env * env, f_ck_query query, | ||
| 571 | const char * name, const char * nspc ) | ||
| 572 | { | ||
| 573 | Chuck_DLL * dll = NULL; | ||
| 574 | t_CKBOOL query_failed = FALSE; | ||
| 575 | |||
| 576 | // load osc | ||
| 577 | dll = new Chuck_DLL( compiler->carrier(), name ); | ||
| 578 | // (fixed: 1.3.0.0) query_failed now catches either failure of load or query | ||
| 579 | if( (query_failed = !(dll->load( query ) && dll->query())) || | ||
| 580 | !type_engine_add_dll( env, dll, nspc ) ) | ||
| 581 | { | ||
| 582 | CK_FPRINTF_STDERR( | ||
| 583 | "[chuck]: internal error loading module '%s.%s'...\n", | ||
| 584 | nspc, name ); | ||
| 585 | if( query_failed ) | ||
| 586 | CK_FPRINTF_STDERR( " %s", dll->last_error() ); | ||
| 587 | |||
| 588 | return FALSE; | ||
| 589 | } | ||
| 590 | |||
| 591 | return TRUE; | ||
| 592 | } | ||
| 593 | |||
| 594 | |||
| 595 | |||
| 596 | |||
| 597 | //----------------------------------------------------------------------------- | ||
| 598 | // name: load_internal_modules() | ||
| 599 | // desc: ... | ||
| 600 | //----------------------------------------------------------------------------- | ||
| 601 | t_CKBOOL load_internal_modules( Chuck_Compiler * compiler ) | ||
| 602 | { | ||
| 603 | // log | ||
| 604 | EM_log( CK_LOG_SEVERE, "loading built-in modules..." ); | ||
| 605 | // push indent level | ||
| 606 | EM_pushlog(); | ||
| 607 | |||
| 608 | // get env | ||
| 609 | Chuck_Env * env = compiler->env(); | ||
| 610 | // make context | ||
| 611 | Chuck_Context * context = type_engine_make_context( NULL, "@[internal]" ); | ||
| 612 | // reset env - not needed since we just created the env | ||
| 613 | env->reset(); | ||
| 614 | // load it | ||
| 615 | type_engine_load_context( env, context ); | ||
| 616 | |||
| 617 | //#ifndef __DISABLE_MIDI__ | ||
| 618 | if( !init_class_Midi( env ) ) goto error; | ||
| 619 | if( !init_class_MidiRW( env ) ) goto error; | ||
| 620 | //#endif // __DISABLE_MIDI__ | ||
| 621 | |||
| 622 | // load | ||
| 623 | EM_log( CK_LOG_SEVERE, "module osc..." ); | ||
| 624 | load_module( compiler, env, osc_query, "osc", "global" ); | ||
| 625 | EM_log( CK_LOG_SEVERE, "module xxx..." ); | ||
| 626 | load_module( compiler, env, xxx_query, "xxx", "global" ); | ||
| 627 | EM_log( CK_LOG_SEVERE, "module filter..." ); | ||
| 628 | load_module( compiler, env, filter_query, "filter", "global" ); | ||
| 629 | EM_log( CK_LOG_SEVERE, "module STK..." ); | ||
| 630 | load_module( compiler, env, stk_query, "stk", "global" ); | ||
| 631 | EM_log( CK_LOG_SEVERE, "module xform..." ); | ||
| 632 | load_module( compiler, env, xform_query, "xform", "global" ); | ||
| 633 | EM_log( CK_LOG_SEVERE, "module extract..." ); | ||
| 634 | load_module( compiler, env, extract_query, "extract", "global" ); | ||
| 635 | |||
| 636 | // load | ||
| 637 | EM_log( CK_LOG_SEVERE, "class 'machine'..." ); | ||
| 638 | if( !load_module( compiler, env, machine_query, "Machine", "global" ) ) goto error; | ||
| 639 | machine_init( compiler, otf_process_msg ); | ||
| 640 | EM_log( CK_LOG_SEVERE, "class 'std'..." ); | ||
| 641 | if( !load_module( compiler, env, libstd_query, "Std", "global" ) ) goto error; | ||
| 642 | EM_log( CK_LOG_SEVERE, "class 'math'..." ); | ||
| 643 | if( !load_module( compiler, env, libmath_query, "Math", "global" ) ) goto error; | ||
| 644 | |||
| 645 | // ge: these currently don't compile on "modern" windows versions (1.3.5.3) | ||
| 646 | #ifndef __WINDOWS_MODERN__ | ||
| 647 | EM_log( CK_LOG_SEVERE, "class 'opsc'..." ); | ||
| 648 | if( !load_module( compiler, env, opensoundcontrol_query, "opsc", "global" ) ) goto error; | ||
| 649 | #endif | ||
| 650 | EM_log( CK_LOG_SEVERE, "class 'RegEx'..." ); | ||
| 651 | if( !load_module( compiler, env, regex_query, "RegEx", "global" ) ) goto error; | ||
| 652 | // if( !load_module( compiler, env, net_query, "net", "global" ) ) goto error; | ||
| 653 | |||
| 654 | if( !init_class_HID( env ) ) goto error; | ||
| 655 | if( !init_class_serialio( env ) ) goto error; | ||
| 656 | |||
| 657 | // clear context | ||
| 658 | type_engine_unload_context( env ); | ||
| 659 | |||
| 660 | // commit what is in the type checker at this point | ||
| 661 | env->global()->commit(); | ||
| 662 | |||
| 663 | // pop indent level | ||
| 664 | EM_poplog(); | ||
| 665 | |||
| 666 | return TRUE; | ||
| 667 | |||
| 668 | error: | ||
| 669 | |||
| 670 | // probably dangerous: rollback | ||
| 671 | env->global()->rollback(); | ||
| 672 | |||
| 673 | // clear context | ||
| 674 | type_engine_unload_context( env ); | ||
| 675 | |||
| 676 | // pop indent level | ||
| 677 | EM_poplog(); | ||
| 678 | |||
| 679 | return FALSE; | ||
| 680 | } | ||
| 681 | |||
| 682 | |||
| 683 | |||
| 684 | //----------------------------------------------------------------------------- | ||
| 685 | // name: load_external_module_at_path() | ||
| 686 | // desc: ... | ||
| 687 | //----------------------------------------------------------------------------- | ||
| 688 | t_CKBOOL load_external_module_at_path( Chuck_Compiler * compiler, | ||
| 689 | const char * name, | ||
| 690 | const char * dl_path ) | ||
| 691 | { | ||
| 692 | Chuck_Env * env = compiler->env(); | ||
| 693 | |||
| 694 | EM_log(CK_LOG_SEVERE, "loading chugin '%s'", name); | ||
| 695 | |||
| 696 | Chuck_DLL * dll = new Chuck_DLL( compiler->carrier(), name ); | ||
| 697 | t_CKBOOL query_failed = FALSE; | ||
| 698 | |||
| 699 | if((query_failed = !(dll->load(dl_path) && dll->query())) || | ||
| 700 | !type_engine_add_dll2(env, dll, "global")) | ||
| 701 | { | ||
| 702 | EM_log(CK_LOG_SEVERE, "error loading chugin '%s', skipping", name); | ||
| 703 | if(query_failed) | ||
| 704 | EM_log(CK_LOG_SEVERE, "error from chuck_dl: '%s'", dll->last_error()); | ||
| 705 | delete dll; | ||
| 706 | |||
| 707 | return FALSE; | ||
| 708 | } | ||
| 709 | else | ||
| 710 | { | ||
| 711 | compiler->m_dlls.push_back(dll); | ||
| 712 | return TRUE; | ||
| 713 | } | ||
| 714 | } | ||
| 715 | |||
| 716 | |||
| 717 | |||
| 718 | |||
| 719 | //----------------------------------------------------------------------------- | ||
| 720 | // name: extension_matches() | ||
| 721 | // desc: ... | ||
| 722 | //----------------------------------------------------------------------------- | ||
| 723 | static t_CKBOOL extension_matches( const char * filename, const char * extension ) | ||
| 724 | { | ||
| 725 | t_CKUINT extension_length = strlen(extension); | ||
| 726 | t_CKUINT filename_length = strlen(filename); | ||
| 727 | |||
| 728 | return strncmp( extension, filename+(filename_length-extension_length), | ||
| 729 | extension_length) == 0; | ||
| 730 | } | ||
| 731 | |||
| 732 | |||
| 733 | |||
| 734 | |||
| 735 | //----------------------------------------------------------------------------- | ||
| 736 | // name: load_external_modules_in_directory() | ||
| 737 | // desc: ... | ||
| 738 | //----------------------------------------------------------------------------- | ||
| 739 | t_CKBOOL load_external_modules_in_directory( Chuck_Compiler * compiler, | ||
| 740 | const char * directory, | ||
| 741 | const char * extension ) | ||
| 742 | { | ||
| 743 | static const t_CKBOOL RECURSIVE_SEARCH = false; | ||
| 744 | |||
| 745 | DIR * dir = opendir(directory); | ||
| 746 | |||
| 747 | if( dir ) | ||
| 748 | { | ||
| 749 | // log | ||
| 750 | EM_log( CK_LOG_INFO, "examining directory '%s' for chugins", directory ); | ||
| 751 | |||
| 752 | struct dirent *de = NULL; | ||
| 753 | |||
| 754 | while( (de = readdir(dir)) ) | ||
| 755 | { | ||
| 756 | t_CKBOOL is_regular = false; | ||
| 757 | t_CKBOOL is_directory = false; | ||
| 758 | |||
| 759 | #if defined(__PLATFORM_WIN32__) | ||
| 760 | is_directory = de->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; | ||
| 761 | is_regular = ((de->data.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) || | ||
| 762 | (de->data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) || | ||
| 763 | (de->data.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)); | ||
| 764 | #elif defined(__WINDOWS_PTHREAD__) // Cygwin -- doesn't have dirent d_type | ||
| 765 | std::string absolute_path = std::string(directory) + "/" + de->d_name; | ||
| 766 | struct stat st; | ||
| 767 | if( stat(absolute_path.c_str(), &st) == 0 ) | ||
| 768 | { | ||
| 769 | is_directory = st.st_mode & S_IFDIR; | ||
| 770 | is_regular = st.st_mode & S_IFREG; | ||
| 771 | } | ||
| 772 | else | ||
| 773 | { | ||
| 774 | // uhh ... | ||
| 775 | EM_log( CK_LOG_INFO, | ||
| 776 | "unable to stat file '%s', ignoring for chugins", | ||
| 777 | absolute_path.c_str() ); | ||
| 778 | continue; | ||
| 779 | } | ||
| 780 | #else | ||
| 781 | is_directory = de->d_type == DT_DIR; | ||
| 782 | is_regular = de->d_type == DT_REG; | ||
| 783 | #endif | ||
| 784 | |||
| 785 | if( is_regular ) // TODO: follow links? | ||
| 786 | { | ||
| 787 | if( extension_matches(de->d_name, extension) ) | ||
| 788 | { | ||
| 789 | std::string absolute_path = std::string(directory) + "/" + de->d_name; | ||
| 790 | |||
| 791 | load_external_module_at_path(compiler, de->d_name, | ||
| 792 | absolute_path.c_str()); | ||
| 793 | } | ||
| 794 | else if( extension_matches(de->d_name, ".ck") ) | ||
| 795 | { | ||
| 796 | std::string absolute_path = std::string(directory) + "/" + de->d_name; | ||
| 797 | compiler->m_cklibs_to_preload.push_back(absolute_path); | ||
| 798 | } | ||
| 799 | } | ||
| 800 | else if( RECURSIVE_SEARCH && is_directory ) | ||
| 801 | { | ||
| 802 | // recurse | ||
| 803 | // TODO: max depth? | ||
| 804 | if( strncmp(de->d_name, ".", sizeof(".")) != 0 && | ||
| 805 | strncmp(de->d_name, "..", sizeof("..")) != 0 ) | ||
| 806 | { | ||
| 807 | std::string absolute_path = std::string(directory) + "/" + de->d_name; | ||
| 808 | load_external_modules_in_directory(compiler, | ||
| 809 | absolute_path.c_str(), | ||
| 810 | extension); | ||
| 811 | } | ||
| 812 | } | ||
| 813 | } | ||
| 814 | |||
| 815 | // close | ||
| 816 | closedir( dir ); | ||
| 817 | } | ||
| 818 | else | ||
| 819 | { | ||
| 820 | // log (1.3.1.2: changed to 2 lines to stay within 80 chars) | ||
| 821 | EM_log( CK_LOG_INFO, "unable to open directory '%s'...", directory ); | ||
| 822 | EM_log( CK_LOG_INFO, "(ignoring for chugins...)" ); | ||
| 823 | } | ||
| 824 | |||
| 825 | return TRUE; | ||
| 826 | } | ||
| 827 | |||
| 828 | |||
| 829 | |||
| 830 | |||
| 831 | //----------------------------------------------------------------------------- | ||
| 832 | // name: load_external_modules() | ||
| 833 | // desc: ... | ||
| 834 | //----------------------------------------------------------------------------- | ||
| 835 | t_CKBOOL load_external_modules( Chuck_Compiler * compiler, | ||
| 836 | const char * extension, | ||
| 837 | std::list<std::string> & chugin_search_paths, | ||
| 838 | std::list<std::string> & named_dls ) | ||
| 839 | { | ||
| 840 | // log | ||
| 841 | EM_log( CK_LOG_SEVERE, "loading chugins" ); | ||
| 842 | // push indent level | ||
| 843 | EM_pushlog(); | ||
| 844 | |||
| 845 | // get env | ||
| 846 | Chuck_Env * env = compiler->env(); | ||
| 847 | // make context | ||
| 848 | Chuck_Context * context = type_engine_make_context( NULL, "@[external]" ); | ||
| 849 | // reset env - not needed since we just created the env | ||
| 850 | env->reset(); | ||
| 851 | // load it | ||
| 852 | type_engine_load_context( env, context ); | ||
| 853 | |||
| 854 | /* first load dynamic libraries explicitly named on the command line */ | ||
| 855 | |||
| 856 | for(std::list<std::string>::iterator i_dl = named_dls.begin(); | ||
| 857 | i_dl != named_dls.end(); i_dl++) | ||
| 858 | { | ||
| 859 | std::string & dl_path = *i_dl; | ||
| 860 | if(!extension_matches(dl_path.c_str(), extension)) | ||
| 861 | dl_path += extension; | ||
| 862 | |||
| 863 | load_external_module_at_path(compiler, dl_path.c_str(), | ||
| 864 | dl_path.c_str()); | ||
| 865 | } | ||
| 866 | |||
| 867 | /* now recurse through search paths and load any DLs or .ck files found */ | ||
| 868 | |||
| 869 | for(std::list<std::string>::iterator i_sp = chugin_search_paths.begin(); | ||
| 870 | i_sp != chugin_search_paths.end(); i_sp++) | ||
| 871 | { | ||
| 872 | load_external_modules_in_directory(compiler, (*i_sp).c_str(), extension); | ||
| 873 | } | ||
| 874 | |||
| 875 | // clear context | ||
| 876 | type_engine_unload_context( env ); | ||
| 877 | |||
| 878 | // commit what is in the type checker at this point | ||
| 879 | env->global()->commit(); | ||
| 880 | |||
| 881 | // pop indent level | ||
| 882 | EM_poplog(); | ||
| 883 | |||
| 884 | return TRUE; | ||
| 885 | /* | ||
| 886 | error: | ||
| 887 | |||
| 888 | // probably dangerous: rollback | ||
| 889 | env->global()->rollback(); | ||
| 890 | |||
| 891 | // clear context | ||
| 892 | type_engine_unload_context( env ); | ||
| 893 | |||
| 894 | // pop indent level | ||
| 895 | EM_poplog(); | ||
| 896 | |||
| 897 | return FALSE; | ||
| 898 | */ | ||
| 899 | } | ||
| 900 | |||
| @@ -0,0 +1,138 @@ | |||
| 1 | /*---------------------------------------------------------------------------- | ||
| 2 | ChucK Concurrent, On-the-fly Audio Programming Language | ||
| 3 | Compiler and Virtual Machine | ||
| 4 | |||
| 5 | Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. | ||
| 6 | http://chuck.stanford.edu/ | ||
| 7 | http://chuck.cs.princeton.edu/ | ||
| 8 | |||
| 9 | This program is free software; you can redistribute it and/or modify | ||
| 10 | it under the terms of the GNU General Public License as published by | ||
| 11 | the Free Software Foundation; either version 2 of the License, or | ||
| 12 | (at your option) any later version. | ||
| 13 | |||
| 14 | This program is distributed in the hope that it will be useful, | ||
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | GNU General Public License for more details. | ||
| 18 | |||
| 19 | You should have received a copy of the GNU General Public License | ||
| 20 | along with this program; if not, write to the Free Software | ||
| 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
| 22 | U.S.A. | ||
| 23 | -----------------------------------------------------------------------------*/ | ||
| 24 | |||
| 25 | //----------------------------------------------------------------------------- | ||
| 26 | // file: chuck_compile.h | ||
| 27 | // desc: chuck compile system unifying parser, type checker, and emitter | ||
| 28 | // | ||
| 29 | // author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) | ||
| 30 | // date: Autumn 2005 - original | ||
| 31 | //----------------------------------------------------------------------------- | ||
| 32 | #ifndef __CHUCK_COMPILE_H__ | ||
| 33 | #define __CHUCK_COMPILE_H__ | ||
| 34 | |||
| 35 | #include "chuck_def.h" | ||
| 36 | #include "chuck_parse.h" | ||
| 37 | #include "chuck_scan.h" | ||
| 38 | #include "chuck_type.h" | ||
| 39 | #include "chuck_emit.h" | ||
| 40 | #include "chuck_vm.h" | ||
| 41 | #include <list> | ||
| 42 | |||
| 43 | |||
| 44 | // forward reference | ||
| 45 | struct Chuck_DLL; | ||
| 46 | |||
| 47 | |||
| 48 | |||
| 49 | |||
| 50 | //----------------------------------------------------------------------------- | ||
| 51 | // name: struct Chuck_Compiler | ||
| 52 | // desc: the sum of the components in compilation | ||
| 53 | //----------------------------------------------------------------------------- | ||
| 54 | struct Chuck_Compiler | ||
| 55 | { | ||
| 56 | protected: // data | ||
| 57 | // carrier | ||
| 58 | Chuck_Carrier * m_carrier; | ||
| 59 | |||
| 60 | public: // get protected data | ||
| 61 | // REFACTOR-2017: get associated, per-compiler environment | ||
| 62 | Chuck_Env * env() const { return m_carrier->env; } | ||
| 63 | // REFACTOR-2017: get associated, per-compiler VM | ||
| 64 | Chuck_VM * vm() const { return m_carrier->vm; } | ||
| 65 | // REFACTOR-2017: get associated, per-compiler carrier | ||
| 66 | Chuck_Carrier * carrier() const { return m_carrier; } | ||
| 67 | // set carrier | ||
| 68 | t_CKBOOL setCarrier( Chuck_Carrier * c ) { m_carrier = c; return TRUE; } | ||
| 69 | |||
| 70 | |||
| 71 | public: // data | ||
| 72 | // emitter | ||
| 73 | Chuck_Emitter * emitter; | ||
| 74 | // generated code | ||
| 75 | Chuck_VM_Code * code; | ||
| 76 | |||
| 77 | // auto-depend flag | ||
| 78 | t_CKBOOL m_auto_depend; | ||
| 79 | // recent map | ||
| 80 | std::map<std::string, Chuck_Context *> m_recent; | ||
| 81 | |||
| 82 | std::list<Chuck_DLL *> m_dlls; | ||
| 83 | std::list<std::string> m_cklibs_to_preload; | ||
| 84 | |||
| 85 | public: // to all | ||
| 86 | // contructor | ||
| 87 | Chuck_Compiler(); | ||
| 88 | // destructor | ||
| 89 | virtual ~Chuck_Compiler(); | ||
| 90 | |||
| 91 | // initialize | ||
| 92 | t_CKBOOL initialize( std::list<std::string> & chugin_search_paths, | ||
| 93 | std::list<std::string> & named_dls ); | ||
| 94 | // shutdown | ||
| 95 | void shutdown(); | ||
| 96 | |||
| 97 | public: // additional binding | ||
| 98 | // bind a new type system module, via query function | ||
| 99 | t_CKBOOL bind( f_ck_query query_func, const std::string & name, | ||
| 100 | const std::string & nspc = "global" ); | ||
| 101 | |||
| 102 | public: // compile | ||
| 103 | // set auto depend | ||
| 104 | void set_auto_depend( t_CKBOOL v ); | ||
| 105 | // parse, type-check, and emit a program | ||
| 106 | t_CKBOOL go( const std::string & filename, FILE * fd = NULL, | ||
| 107 | const char * str_src = NULL, const std::string & full_path = "" ); | ||
| 108 | // resolve a type automatically, if auto_depend is on | ||
| 109 | t_CKBOOL resolve( const std::string & type ); | ||
| 110 | // get the code generated from the last go() | ||
| 111 | Chuck_VM_Code * output( ); | ||
| 112 | |||
| 113 | protected: // internal | ||
| 114 | // do entire file | ||
| 115 | t_CKBOOL do_entire_file( Chuck_Context * context ); | ||
| 116 | // do just class definitions | ||
| 117 | t_CKBOOL do_only_classes( Chuck_Context * context ); | ||
| 118 | // do all excect classes | ||
| 119 | t_CKBOOL do_all_except_classes( Chuck_Context * context ); | ||
| 120 | // do normal compile | ||
| 121 | t_CKBOOL do_normal( const std::string & path, FILE * fd = NULL, | ||
| 122 | const char * str_src = NULL, const std::string & full_path = "" ); | ||
| 123 | // look up in recent | ||
| 124 | Chuck_Context * find_recent_path( const std::string & path ); | ||
| 125 | // look up in recent | ||
| 126 | Chuck_Context * find_recent_type( const std::string & type ); | ||
| 127 | // add to recent | ||
| 128 | t_CKBOOL add_recent_path( const std::string & path, Chuck_Context * context ); | ||
| 129 | }; | ||
| 130 | |||
| 131 | |||
| 132 | // call this to detach all open files | ||
| 133 | extern "C" void all_detach(); | ||
| 134 | |||
| 135 | |||
| 136 | |||
| 137 | |||
| 138 | #endif | ||
| @@ -0,0 +1,203 @@ | |||
| 1 | /*---------------------------------------------------------------------------- | ||
| 2 | ChucK Concurrent, On-the-fly Audio Programming Language | ||
| 3 | Compiler and Virtual Machine | ||
| 4 | |||
| 5 | Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. | ||
| 6 | http://chuck.stanford.edu/ | ||
| 7 | http://chuck.cs.princeton.edu/ | ||
| 8 | |||
| 9 | This program is free software; you can redistribute it and/or modify | ||
| 10 | it under the terms of the GNU General Public License as published by | ||
| 11 | the Free Software Foundation; either version 2 of the License, or | ||
| 12 | (at your option) any later version. | ||
| 13 | |||
| 14 | This program is distributed in the hope that it will be useful, | ||
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | GNU General Public License for more details. | ||
| 18 | |||
| 19 | You should have received a copy of the GNU General Public License | ||
| 20 | along with this program; if not, write to the Free Software | ||
| 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
| 22 | U.S.A. | ||
| 23 | -----------------------------------------------------------------------------*/ | ||
| 24 | |||
| 25 | //----------------------------------------------------------------------------- | ||
| 26 | // file: chuck_def.h | ||
| 27 | // desc: ChucK defines for the system | ||
| 28 | // | ||
| 29 | // author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) | ||
| 30 | // Perry R. Cook (prc@cs.princeton.edu) | ||
| 31 | // date: Autumn 2002 | ||
| 32 | //----------------------------------------------------------------------------- | ||
| 33 | #ifndef __CHUCK_DEF_H__ | ||
| 34 | #define __CHUCK_DEF_H__ | ||
| 35 | |||
| 36 | #include <stdlib.h> | ||
| 37 | #include <memory.h> | ||
| 38 | #include <assert.h> | ||
| 39 | |||
| 40 | |||
| 41 | // types | ||
| 42 | #define t_CKTIME double | ||
| 43 | #define t_CKDUR double | ||
| 44 | #define t_CKFLOAT double | ||
| 45 | #define t_CKDOUBLE double | ||
| 46 | #define t_CKSINGLE float | ||
| 47 | #ifdef _WIN64 // REFACTOR-2017 | ||
| 48 | #define t_CKINT long long // REFACTOR-2017 | ||
| 49 | #else | ||
| 50 | #define t_CKINT long | ||
| 51 | #endif | ||
| 52 | #define t_CKUINT unsigned t_CKINT | ||
| 53 | #define t_CKBOOL unsigned t_CKINT | ||
| 54 | #define t_CKBYTE unsigned char | ||
| 55 | #define t_CKVOID void | ||
| 56 | #define t_CKVOIDPTR void * | ||
| 57 | |||
| 58 | // complex type | ||
| 59 | typedef struct { t_CKFLOAT re ; t_CKFLOAT im ; } t_CKCOMPLEX; | ||
| 60 | // polar type | ||
| 61 | typedef struct { t_CKFLOAT modulus ; t_CKFLOAT phase ; } t_CKPOLAR; | ||
| 62 | |||
| 63 | // vector types | ||
| 64 | typedef struct { t_CKFLOAT x ; t_CKFLOAT y ; t_CKFLOAT z ; } t_CKVEC3; | ||
| 65 | typedef struct { t_CKFLOAT x ; t_CKFLOAT y ; t_CKFLOAT z ; t_CKFLOAT w ; } t_CKVEC4; | ||
| 66 | typedef struct { t_CKUINT N ; t_CKFLOAT * values ; } t_CKVECTOR; | ||
| 67 | |||
| 68 | // size | ||
| 69 | #define sz_TIME sizeof(t_CKTIME) | ||
| 70 | #define sz_DUR sizeof(t_CKDUR) | ||
| 71 | #define sz_FLOAT sizeof(t_CKFLOAT) | ||
| 72 | #define sz_DOUBLE sizeof(t_CKDOUBLE) | ||
| 73 | #define sz_SINGLE sizeof(t_CKSINGLE) | ||
| 74 | #define sz_INT sizeof(t_CKINT) | ||
| 75 | #define sz_UINT sizeof(t_CKUINT) | ||
| 76 | #define sz_BOOL sizeof(t_CKBOOL) | ||
| 77 | #define sz_BYTE sizeof(t_CKBYTE) | ||
| 78 | #define sz_VOIDPTR sizeof(t_CKVOIDPTR) | ||
| 79 | #define sz_COMPLEX sizeof(t_CKCOMPLEX) | ||
| 80 | #define sz_POLAR sizeof(t_CKPOLAR) | ||
| 81 | #define sz_VEC3 sizeof(t_CKVEC3) | ||
| 82 | #define sz_VEC4 sizeof(t_CKVEC4) | ||
| 83 | #define sz_VECTOR sizeof(t_CKVECTOR) | ||
| 84 | #define sz_VOID 0 | ||
| 85 | #define sz_WORD 4 | ||
| 86 | |||
| 87 | // kinds (added 1.3.1.0 to faciliate 64-bit support) | ||
| 88 | // to differentiate in case int and float have same size | ||
| 89 | #define kindof_VOID 0 | ||
| 90 | #define kindof_INT 1 | ||
| 91 | #define kindof_FLOAT 2 | ||
| 92 | #define kindof_COMPLEX 3 | ||
| 93 | #define kindof_VEC3 4 | ||
| 94 | #define kindof_VEC4 5 | ||
| 95 | |||
| 96 | typedef char * c_str; | ||
| 97 | typedef const char * c_constr; | ||
| 98 | |||
| 99 | // use 64-bit samples in the audio engine | ||
| 100 | // #define __CHUCK_USE_64_BIT_SAMPLE__ | ||
| 101 | |||
| 102 | // sample | ||
| 103 | #ifdef __CHUCK_USE_64_BIT_SAMPLE__ | ||
| 104 | #define SAMPLE double | ||
| 105 | #define SILENCE 0.0 | ||
| 106 | #define CK_DDN CK_DDN_DOUBLE | ||
| 107 | #else | ||
| 108 | #define SAMPLE float | ||
| 109 | #define SILENCE 0.0f | ||
| 110 | #define CK_DDN CK_DDN_SINGLE | ||
| 111 | #endif | ||
| 112 | |||
| 113 | // for external use | ||
| 114 | #define t_CKSAMPLE SAMPLE | ||
| 115 | |||
| 116 | // sample complex | ||
| 117 | typedef struct { SAMPLE re ; SAMPLE im ; } t_CKCOMPLEX_SAMPLE; | ||
| 118 | |||
| 119 | // bool | ||
| 120 | #ifndef TRUE | ||
| 121 | #define TRUE 1 | ||
| 122 | #define FALSE 0 | ||
| 123 | #endif | ||
| 124 | |||
| 125 | // 3.1415926535897932384626433832795028841971693993751058209749445... | ||
| 126 | #define ONE_PI (3.14159265358979323846) | ||
| 127 | #define TWO_PI (2.0 * ONE_PI) | ||
| 128 | #define SQRT2 (1.41421356237309504880) | ||
| 129 | |||
| 130 | #ifndef SAFE_DELETE | ||
| 131 | #define SAFE_DELETE(x) do { if(x){ delete x; x = NULL; } } while(0) | ||
| 132 | #define SAFE_DELETE_ARRAY(x) do { if(x){ delete [] x; x = NULL; } } while(0) | ||
| 133 | #define SAFE_RELEASE(x) do { if(x){ x->release(); x = NULL; } } while(0) | ||
| 134 | #define SAFE_ADD_REF(x) do { if(x){ x->add_ref(); } } while(0) | ||
| 135 | #define SAFE_REF_ASSIGN(lhs,rhs) do { SAFE_RELEASE(lhs); (lhs) = (rhs); SAFE_ADD_REF(lhs); } while(0) | ||
| 136 | #endif | ||
| 137 | |||
| 138 | // max + min | ||
| 139 | #define ck_max(x,y) ( (x) >= (y) ? (x) : (y) ) | ||
| 140 | #define ck_min(x,y) ( (x) <= (y) ? (x) : (y) ) | ||
| 141 | |||
| 142 | #ifndef __arm__ | ||
| 143 | // dedenormal | ||
| 144 | #define CK_DDN_SINGLE(f) f = ( f >= 0 ? \ | ||
| 145 | ( ( f > (t_CKSINGLE)1e-15 && f < (t_CKSINGLE)1e15 ) ? f : (t_CKSINGLE)0.0 ) : \ | ||
| 146 | ( ( f < (t_CKSINGLE)-1e-15 && f > (t_CKSINGLE)-1e15 ) ? f : (t_CKSINGLE)0.0 ) ) | ||
| 147 | #define CK_DDN_DOUBLE(f) f = ( f >= 0 ? \ | ||
| 148 | ( ( f > (t_CKDOUBLE)1e-15 && f < (t_CKDOUBLE)1e15 ) ? f : 0.0 ) : \ | ||
| 149 | ( ( f < (t_CKDOUBLE)-1e-15 && f > (t_CKDOUBLE)-1e15 ) ? f : 0.0 ) ) | ||
| 150 | #else | ||
| 151 | #define CK_DDN_SINGLE(f) (f) | ||
| 152 | #define CK_DDN_DOUBLE(f) (f) | ||
| 153 | #endif // __arm__ | ||
| 154 | |||
| 155 | // tracking | ||
| 156 | #if defined(__CHUCK_STAT_TRACK__) | ||
| 157 | #define CK_TRACK( stmt ) stmt | ||
| 158 | #else | ||
| 159 | #define CK_TRACK( stmt ) | ||
| 160 | #endif | ||
| 161 | |||
| 162 | #ifdef __MACOSX_CORE__ | ||
| 163 | #define __PLATFORM_MACOSX__ | ||
| 164 | #endif | ||
| 165 | |||
| 166 | #if defined(__LINUX_ALSA__) || defined(__LINUX_JACK__) || defined(__LINUX_OSS__) || defined(__LINUX_PULSE__) || defined(__UNIX_JACK__) | ||
| 167 | // defined by default in Linux makefiles | ||
| 168 | //#define __PLATFORM_LINUX__ | ||
| 169 | #endif | ||
| 170 | |||
| 171 | #ifdef __PLATFORM_WIN32__ | ||
| 172 | #ifndef usleep | ||
| 173 | #define usleep(x) Sleep( (x / 1000 <= 0 ? 1 : x / 1000) ) | ||
| 174 | #endif | ||
| 175 | #pragma warning (disable : 4996) // stdio deprecation | ||
| 176 | #pragma warning (disable : 4786) // stl debug info | ||
| 177 | #pragma warning (disable : 4312) // type casts from void* | ||
| 178 | #pragma warning (disable : 4311) // type casts to void* | ||
| 179 | #pragma warning (disable : 4244) // truncation | ||
| 180 | #pragma warning (disable : 4068) // unknown pragma | ||
| 181 | #pragma warning (disable : 4018) // signed/unsigned mismatch | ||
| 182 | #endif | ||
| 183 | |||
| 184 | #ifdef __CHIP_MODE__ | ||
| 185 | #define __DISABLE_MIDI__ | ||
| 186 | //#define __DISABLE_SNDBUF__ | ||
| 187 | #define __DISABLE_WATCHDOG__ | ||
| 188 | #define __DISABLE_RAW__ | ||
| 189 | #define __DISABLE_KBHIT__ | ||
| 190 | #define __DISABLE_PROMPTER__ | ||
| 191 | #define __DISABLE_RTAUDIO__ | ||
| 192 | #define __DISABLE_OTF_SERVER__ | ||
| 193 | #define __ALTER_HID__ | ||
| 194 | #define __ALTER_ENTRY_POINT__ | ||
| 195 | #define __STK_USE_SINGLE_PRECISION__ | ||
| 196 | #endif | ||
| 197 | |||
| 198 | #ifdef __arm__ | ||
| 199 | // enable additional optimization | ||
| 200 | #define __STK_USE_SINGLE_PRECISION__ | ||
| 201 | #endif // __arm__ | ||
| 202 | |||
| 203 | #endif | ||
| @@ -0,0 +1,1210 @@ | |||
| 1 | /*---------------------------------------------------------------------------- | ||
| 2 | ChucK Concurrent, On-the-fly Audio Programming Language | ||
| 3 | Compiler and Virtual Machine | ||
| 4 | |||
| 5 | Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. | ||
| 6 | http://chuck.stanford.edu/ | ||
| 7 | http://chuck.cs.princeton.edu/ | ||
| 8 | |||
| 9 | This program is free software; you can redistribute it and/or modify | ||
| 10 | it under the terms of the GNU General Public License as published by | ||
| 11 | the Free Software Foundation; either version 2 of the License, or | ||
| 12 | (at your option) any later version. | ||
| 13 | |||
| 14 | This program is distributed in the hope that it will be useful, | ||
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | GNU General Public License for more details. | ||
| 18 | |||
| 19 | You should have received a copy of the GNU General Public License | ||
| 20 | along with this program; if not, write to the Free Software | ||
| 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
| 22 | U.S.A. | ||
| 23 | -----------------------------------------------------------------------------*/ | ||
| 24 | |||
| 25 | //----------------------------------------------------------------------------- | ||
| 26 | // name: chuck_dl.cpp | ||
| 27 | // desc: chuck dynamic linking header | ||
| 28 | // | ||
| 29 | // authors: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) | ||
| 30 | // Ari Lazier (alazier@cs.princeton.edu) | ||
| 31 | // Spencer Salazar (spencer@ccrma.stanford.edu) | ||
| 32 | // mac os code based on apple's open source | ||
| 33 | // | ||
| 34 | // date: spring 2004 - 1.1 | ||
| 35 | // spring 2005 - 1.2 | ||
| 36 | //----------------------------------------------------------------------------- | ||
| 37 | #include "chuck_dl.h" | ||
| 38 | #include "chuck_errmsg.h" | ||
| 39 | #include "chuck_bbq.h" | ||
| 40 | #include "chuck_type.h" | ||
| 41 | #include "chuck_instr.h" | ||
| 42 | #include "chuck_globals.h" | ||
| 43 | #include "chuck_compile.h" | ||
| 44 | #include "chuck_vm.h" | ||
| 45 | #include <sstream> | ||
| 46 | using namespace std; | ||
| 47 | |||
| 48 | |||
| 49 | |||
| 50 | |||
| 51 | #if defined(__MACOSX_CORE__) | ||
| 52 | char g_default_chugin_path[] = "/usr/local/lib/chuck:/Library/Application Support/ChucK/ChuGins:~/Library/Application Support/ChucK/ChuGins"; | ||
| 53 | #elif defined(__PLATFORM_WIN32__) | ||
| 54 | char g_default_chugin_path[] = "C:\\WINDOWS\\system32\\ChucK;C:\\Program Files\\ChucK\\chugins;C:\\Program Files (x86)\\ChucK\\chugins"; | ||
| 55 | #else // Linux/Cygwin | ||
| 56 | char g_default_chugin_path[] = "/usr/local/lib/chuck"; | ||
| 57 | #endif | ||
| 58 | |||
| 59 | char g_chugin_path_envvar[] = "CHUCK_CHUGIN_PATH"; | ||
| 60 | |||
| 61 | |||
| 62 | |||
| 63 | |||
| 64 | //----------------------------------------------------------------------------- | ||
| 65 | // internal implementation of query functions | ||
| 66 | //----------------------------------------------------------------------------- | ||
| 67 | |||
| 68 | |||
| 69 | |||
| 70 | t_CKUINT ck_builtin_declversion() { return CK_DLL_VERSION; } | ||
| 71 | |||
| 72 | |||
| 73 | |||
| 74 | //----------------------------------------------------------------------------- | ||
| 75 | // name: ck_setname() | ||
| 76 | // desc: set the name of the module | ||
| 77 | //----------------------------------------------------------------------------- | ||
| 78 | void CK_DLL_CALL ck_setname( Chuck_DL_Query * query, const char * name ) | ||
| 79 | { | ||
| 80 | // set the name | ||
| 81 | query->dll_name = name; | ||
| 82 | } | ||
| 83 | |||
| 84 | |||
| 85 | |||
| 86 | |||
| 87 | //----------------------------------------------------------------------------- | ||
| 88 | // name: ck_begin_class() | ||
| 89 | // desc: begin class/namespace, can be nexted | ||
| 90 | //----------------------------------------------------------------------------- | ||
| 91 | void CK_DLL_CALL ck_begin_class( Chuck_DL_Query * query, const char * name, const char * parent ) | ||
| 92 | { | ||
| 93 | // find parent mvar offset | ||
| 94 | t_CKINT parent_offset = 0; | ||
| 95 | if(parent && parent[0] != '\0') | ||
| 96 | { | ||
| 97 | a_Id_List parent_path = str2list( parent ); | ||
| 98 | if( !parent_path ) | ||
| 99 | { | ||
| 100 | // error | ||
| 101 | EM_error2( 0, "class import: ck_begin_class: unknown parent type '%s'", | ||
| 102 | query->curr_class->name.c_str(), name, parent ); | ||
| 103 | return; | ||
| 104 | } | ||
| 105 | |||
| 106 | Chuck_Type * ck_parent_type = type_engine_find_type( query->env(), parent_path ); | ||
| 107 | |||
| 108 | delete_id_list( parent_path ); | ||
| 109 | |||
| 110 | if( !ck_parent_type ) | ||
| 111 | { | ||
| 112 | // error | ||
| 113 | EM_error2( 0, "class import: ck_begin_class: unable to find parent type '%s'", ck_parent_type ); | ||
| 114 | return; | ||
| 115 | } | ||
| 116 | |||
| 117 | parent_offset = ck_parent_type->obj_size; | ||
| 118 | } | ||
| 119 | |||
| 120 | // push | ||
| 121 | query->stack.push_back( query->curr_class ); | ||
| 122 | // allocate | ||
| 123 | Chuck_DL_Class * c = new Chuck_DL_Class; | ||
| 124 | |||
| 125 | // add class | ||
| 126 | if( query->curr_class ) | ||
| 127 | // recursive | ||
| 128 | query->curr_class->classes.push_back( c ); | ||
| 129 | // 1.3.2.0: do not save class for later import (will import it on class close) | ||
| 130 | // else | ||
| 131 | // // first level | ||
| 132 | // query->classes.push_back( c ); | ||
| 133 | |||
| 134 | // remember info | ||
| 135 | c->name = name; | ||
| 136 | c->parent = parent; | ||
| 137 | c->current_mvar_offset = parent_offset; | ||
| 138 | |||
| 139 | // curr | ||
| 140 | query->curr_class = c; | ||
| 141 | query->curr_func = NULL; | ||
| 142 | } | ||
| 143 | |||
| 144 | |||
| 145 | |||
| 146 | |||
| 147 | //----------------------------------------------------------------------------- | ||
| 148 | // name: ck_add_ctor() | ||
| 149 | // desc: add constructor, can be followed by add_arg | ||
| 150 | //----------------------------------------------------------------------------- | ||
| 151 | void CK_DLL_CALL ck_add_ctor( Chuck_DL_Query * query, f_ctor ctor ) | ||
| 152 | { | ||
| 153 | // make sure there is class | ||
| 154 | if( !query->curr_class ) | ||
| 155 | { | ||
| 156 | // error | ||
| 157 | EM_error2( 0, "class import: add_ctor invoked without begin_class..." ); | ||
| 158 | return; | ||
| 159 | } | ||
| 160 | |||
| 161 | // allocate | ||
| 162 | Chuck_DL_Func * f = new Chuck_DL_Func; | ||
| 163 | f->name = "[ctor]"; | ||
| 164 | f->type = "void"; | ||
| 165 | f->ctor = ctor; | ||
| 166 | |||
| 167 | // add | ||
| 168 | query->curr_class->ctors.push_back( f ); | ||
| 169 | query->curr_func = f; | ||
| 170 | } | ||
| 171 | |||
| 172 | |||
| 173 | |||
| 174 | |||
| 175 | //----------------------------------------------------------------------------- | ||
| 176 | // name: ck_add_dtor() | ||
| 177 | // add destructor, no args allowed | ||
| 178 | //----------------------------------------------------------------------------- | ||
| 179 | void CK_DLL_CALL ck_add_dtor( Chuck_DL_Query * query, f_dtor dtor ) | ||
| 180 | { | ||
| 181 | // make sure there is class | ||
| 182 | if( !query->curr_class ) | ||
| 183 | { | ||
| 184 | // error | ||
| 185 | EM_error2( 0, "class import: add_dtor invoked without begin_class..." ); | ||
| 186 | return; | ||
| 187 | } | ||
| 188 | |||
| 189 | // make sure there are no duplicates | ||
| 190 | if( query->curr_class->dtor ) | ||
| 191 | { | ||
| 192 | // error | ||
| 193 | EM_error2( 0, "class import: multiple dtor added ..." ); | ||
| 194 | return; | ||
| 195 | } | ||
| 196 | |||
| 197 | // allocate | ||
| 198 | Chuck_DL_Func * f = new Chuck_DL_Func; | ||
| 199 | f->name = "[dtor]"; | ||
| 200 | f->type = "void"; | ||
| 201 | f->dtor = dtor; | ||
| 202 | |||
| 203 | // add | ||
| 204 | query->curr_class->dtor = f; | ||
| 205 | // set | ||
| 206 | query->curr_func = NULL; | ||
| 207 | } | ||
| 208 | |||
| 209 | |||
| 210 | |||
| 211 | |||
| 212 | //----------------------------------------------------------------------------- | ||
| 213 | // name: ck_add_mfun() | ||
| 214 | // desc: add member function, can be followed by add_arg | ||
| 215 | //----------------------------------------------------------------------------- | ||
| 216 | void CK_DLL_CALL ck_add_mfun( Chuck_DL_Query * query, f_mfun addr, | ||
| 217 | const char * type, const char * name ) | ||
| 218 | { | ||
| 219 | // make sure there is class | ||
| 220 | if( !query->curr_class ) | ||
| 221 | { | ||
| 222 | // error | ||
| 223 | EM_error2( 0, "class import: add_mfun invoked without begin_class..." ); | ||
| 224 | return; | ||
| 225 | } | ||
| 226 | |||
| 227 | // allocate | ||
| 228 | Chuck_DL_Func * f = new Chuck_DL_Func; | ||
| 229 | f->name = name; | ||
| 230 | f->type = type; | ||
| 231 | f->mfun = addr; | ||
| 232 | |||
| 233 | // add | ||
| 234 | query->curr_class->mfuns.push_back( f ); | ||
| 235 | query->curr_func = f; | ||
| 236 | } | ||
| 237 | |||
| 238 | |||
| 239 | |||
| 240 | |||
| 241 | //----------------------------------------------------------------------------- | ||
| 242 | // name: ck_add_sfun() | ||
| 243 | // desc: add static function, can be followed by add_arg | ||
| 244 | //----------------------------------------------------------------------------- | ||
| 245 | void CK_DLL_CALL ck_add_sfun( Chuck_DL_Query * query, f_sfun addr, | ||
| 246 | const char * type, const char * name ) | ||
| 247 | { | ||
| 248 | // make sure there is class | ||
| 249 | if( !query->curr_class ) | ||
| 250 | { | ||
| 251 | // error | ||
| 252 | EM_error2( 0, "class import: add_sfun invoked without begin_class..." ); | ||
| 253 | return; | ||
| 254 | } | ||
| 255 | |||
| 256 | // allocate | ||
| 257 | Chuck_DL_Func * f = new Chuck_DL_Func; | ||
| 258 | f->name = name; | ||
| 259 | f->type = type; | ||
| 260 | f->sfun = addr; | ||
| 261 | |||
| 262 | // add | ||
| 263 | query->curr_class->sfuns.push_back( f ); | ||
| 264 | query->curr_func = f; | ||
| 265 | } | ||
| 266 | |||
| 267 | |||
| 268 | |||
| 269 | |||
| 270 | //----------------------------------------------------------------------------- | ||
| 271 | // name: ck_add_mvar() | ||
| 272 | // desc: add member var | ||
| 273 | //----------------------------------------------------------------------------- | ||
| 274 | t_CKUINT CK_DLL_CALL ck_add_mvar( Chuck_DL_Query * query, | ||
| 275 | const char * type, const char * name, | ||
| 276 | t_CKBOOL is_const ) | ||
| 277 | { | ||
| 278 | // make sure there is class | ||
| 279 | if( !query->curr_class ) | ||
| 280 | { | ||
| 281 | // error | ||
| 282 | EM_error2( 0, "class import: add_mvar invoked without begin_class..." ); | ||
| 283 | return CK_INVALID_OFFSET; | ||
| 284 | } | ||
| 285 | |||
| 286 | a_Id_List path = str2list( type ); | ||
| 287 | if( !path ) | ||
| 288 | { | ||
| 289 | // error | ||
| 290 | EM_error2( 0, "class import: add_mvar: mvar %s.%s has unknown type '%s'", | ||
| 291 | query->curr_class->name.c_str(), name, type ); | ||
| 292 | return CK_INVALID_OFFSET; | ||
| 293 | } | ||
| 294 | |||
| 295 | Chuck_Type * ck_type = type_engine_find_type( query->env(), path ); | ||
| 296 | |||
| 297 | delete_id_list( path ); | ||
| 298 | |||
| 299 | if( !ck_type ) | ||
| 300 | { | ||
| 301 | // error | ||
| 302 | EM_error2( 0, "class import: add_mvar: unable to find type '%s'", type ); | ||
| 303 | return CK_INVALID_OFFSET; | ||
| 304 | } | ||
| 305 | |||
| 306 | // allocate | ||
| 307 | Chuck_DL_Value * v = new Chuck_DL_Value; | ||
| 308 | v->name = name; | ||
| 309 | v->type = type; | ||
| 310 | v->is_const = is_const; | ||
| 311 | |||
| 312 | // add | ||
| 313 | query->curr_class->mvars.push_back( v ); | ||
| 314 | query->curr_func = NULL; | ||
| 315 | query->last_var = v; | ||
| 316 | |||
| 317 | t_CKUINT offset = query->curr_class->current_mvar_offset; | ||
| 318 | query->curr_class->current_mvar_offset = type_engine_next_offset( query->curr_class->current_mvar_offset, | ||
| 319 | ck_type ); | ||
| 320 | |||
| 321 | return offset; | ||
| 322 | } | ||
| 323 | |||
| 324 | |||
| 325 | |||
| 326 | |||
| 327 | //----------------------------------------------------------------------------- | ||
| 328 | // name: ck_add_svar() | ||
| 329 | // desc: add static var | ||
| 330 | //----------------------------------------------------------------------------- | ||
| 331 | void CK_DLL_CALL ck_add_svar( Chuck_DL_Query * query, const char * type, const char * name, | ||
| 332 | t_CKBOOL is_const, void * addr ) | ||
| 333 | { | ||
| 334 | // make sure there is class | ||
| 335 | if( !query->curr_class ) | ||
| 336 | { | ||
| 337 | // error | ||
| 338 | EM_error2( 0, "class import: add_svar invoked without begin_class..." ); | ||
| 339 | return; | ||
| 340 | } | ||
| 341 | |||
| 342 | // allocate | ||
| 343 | Chuck_DL_Value * v = new Chuck_DL_Value; | ||
| 344 | v->name = name; | ||
| 345 | v->type = type; | ||
| 346 | v->is_const = is_const; | ||
| 347 | v->static_addr = addr; | ||
| 348 | |||
| 349 | // add | ||
| 350 | query->curr_class->svars.push_back( v ); | ||
| 351 | query->curr_func = NULL; | ||
| 352 | |||
| 353 | query->last_var = v; | ||
| 354 | } | ||
| 355 | |||
| 356 | |||
| 357 | |||
| 358 | |||
| 359 | //----------------------------------------------------------------------------- | ||
| 360 | // name: ck_add_arg() | ||
| 361 | // desc: add argument to function | ||
| 362 | //----------------------------------------------------------------------------- | ||
| 363 | void CK_DLL_CALL ck_add_arg( Chuck_DL_Query * query, const char * type, const char * name ) | ||
| 364 | { | ||
| 365 | // make sure there is class | ||
| 366 | if( !query->curr_class ) | ||
| 367 | { | ||
| 368 | // error | ||
| 369 | EM_error2( 0, "class import: add_arg invoked without begin_class..." ); | ||
| 370 | return; | ||
| 371 | } | ||
| 372 | |||
| 373 | // make sure there is function | ||
| 374 | if( !query->curr_func ) | ||
| 375 | { | ||
| 376 | // error | ||
| 377 | EM_error2( 0, "class import: add_arg can only follow 'ctor', 'mfun', 'sfun', 'arg'..." ); | ||
| 378 | return; | ||
| 379 | } | ||
| 380 | |||
| 381 | // allocate | ||
| 382 | Chuck_DL_Value * v = new Chuck_DL_Value; | ||
| 383 | v->name = name; | ||
| 384 | v->type = type; | ||
| 385 | |||
| 386 | // add | ||
| 387 | query->curr_func->args.push_back( v ); | ||
| 388 | } | ||
| 389 | |||
| 390 | |||
| 391 | |||
| 392 | |||
| 393 | //----------------------------------------------------------------------------- | ||
| 394 | // name: ck_add_ugen_func() | ||
| 395 | // desc: (ugen only) add tick and pmsg functions | ||
| 396 | //----------------------------------------------------------------------------- | ||
| 397 | void CK_DLL_CALL ck_add_ugen_func( Chuck_DL_Query * query, f_tick ugen_tick, f_pmsg ugen_pmsg, t_CKUINT num_in, t_CKUINT num_out ) | ||
| 398 | { | ||
| 399 | // make sure there is class | ||
| 400 | if( !query->curr_class ) | ||
| 401 | { | ||
| 402 | // error | ||
| 403 | EM_error2( 0, "class import: add_ugen_func invoked without begin_class..." ); | ||
| 404 | return; | ||
| 405 | } | ||
| 406 | |||
| 407 | // make sure tick not defined already | ||
| 408 | if( query->curr_class->ugen_tick && ugen_tick ) | ||
| 409 | { | ||
| 410 | // error | ||
| 411 | EM_error2( 0, "class import: ugen_tick already defined..." ); | ||
| 412 | return; | ||
| 413 | } | ||
| 414 | |||
| 415 | // make sure pmsg not defined already | ||
| 416 | if( query->curr_class->ugen_pmsg && ugen_pmsg ) | ||
| 417 | { | ||
| 418 | // error | ||
| 419 | EM_error2( 0, "class import: ugen_pmsg already defined..." ); | ||
| 420 | return; | ||
| 421 | } | ||
| 422 | |||
| 423 | // set | ||
| 424 | if( ugen_tick ) query->curr_class->ugen_tick = ugen_tick; | ||
| 425 | if( ugen_pmsg ) query->curr_class->ugen_pmsg = ugen_pmsg; | ||
| 426 | query->curr_class->ugen_num_in = num_in; | ||
| 427 | query->curr_class->ugen_num_out = num_out; | ||
| 428 | query->curr_func = NULL; | ||
| 429 | } | ||
| 430 | |||
| 431 | |||
| 432 | |||
| 433 | |||
| 434 | //----------------------------------------------------------------------------- | ||
| 435 | // name: ck_add_ugen_funcf() | ||
| 436 | // desc: (ugen only) add tick and pmsg functions | ||
| 437 | //----------------------------------------------------------------------------- | ||
| 438 | void CK_DLL_CALL ck_add_ugen_funcf( Chuck_DL_Query * query, f_tickf ugen_tickf, f_pmsg ugen_pmsg, t_CKUINT num_in, t_CKUINT num_out ) | ||
| 439 | { | ||
| 440 | // make sure there is class | ||
| 441 | if( !query->curr_class ) | ||
| 442 | { | ||
| 443 | // error | ||
| 444 | EM_error2( 0, "class import: add_ugen_func invoked without begin_class..." ); | ||
| 445 | return; | ||
| 446 | } | ||
| 447 | |||
| 448 | // make sure tick not defined already | ||
| 449 | if( query->curr_class->ugen_tickf && ugen_tickf ) | ||
| 450 | { | ||
| 451 | // error | ||
| 452 | EM_error2( 0, "class import: ugen_tick already defined..." ); | ||
| 453 | return; | ||
| 454 | } | ||
| 455 | |||
| 456 | // make sure pmsg not defined already | ||
| 457 | if( query->curr_class->ugen_pmsg && ugen_pmsg ) | ||
| 458 | { | ||
| 459 | // error | ||
| 460 | EM_error2( 0, "class import: ugen_pmsg already defined..." ); | ||
| 461 | return; | ||
| 462 | } | ||
| 463 | |||
| 464 | // set | ||
| 465 | if( ugen_tickf ) query->curr_class->ugen_tickf = ugen_tickf; | ||
| 466 | if( ugen_pmsg ) query->curr_class->ugen_pmsg = ugen_pmsg; | ||
| 467 | query->curr_class->ugen_num_in = num_in; | ||
| 468 | query->curr_class->ugen_num_out = num_out; | ||
| 469 | query->curr_func = NULL; | ||
| 470 | } | ||
| 471 | |||
| 472 | |||
| 473 | |||
| 474 | |||
| 475 | //----------------------------------------------------------------------------- | ||
| 476 | // name: ck_add_ugen_funcf_auto_num_channels() | ||
| 477 | // desc: (ugen only) add tick and pmsg functions. specify num channels by vm. | ||
| 478 | //----------------------------------------------------------------------------- | ||
| 479 | void CK_DLL_CALL ck_add_ugen_funcf_auto_num_channels( Chuck_DL_Query * query, | ||
| 480 | f_tickf ugen_tickf, f_pmsg ugen_pmsg ) | ||
| 481 | { | ||
| 482 | ck_add_ugen_funcf( query, ugen_tickf, ugen_pmsg, | ||
| 483 | query->vm()->m_num_adc_channels, | ||
| 484 | query->vm()->m_num_dac_channels | ||
| 485 | ); | ||
| 486 | } | ||
| 487 | |||
| 488 | |||
| 489 | |||
| 490 | |||
| 491 | //----------------------------------------------------------------------------- | ||
| 492 | // name: ck_add_ugen_ctrl() | ||
| 493 | // desc: (ugen only) add ctrl parameters | ||
| 494 | //----------------------------------------------------------------------------- | ||
| 495 | void CK_DLL_CALL ck_add_ugen_ctrl( Chuck_DL_Query * query, f_ctrl ugen_ctrl, f_cget ugen_cget, | ||
| 496 | const char * type, const char * name ) | ||
| 497 | { | ||
| 498 | // make sure there is class | ||
| 499 | if( !query->curr_class ) | ||
| 500 | { | ||
| 501 | // error | ||
| 502 | EM_error2( 0, "class import: add_ugen_func invoked without begin_class..." ); | ||
| 503 | return; | ||
| 504 | } | ||
| 505 | |||
| 506 | // allocate | ||
| 507 | Chuck_DL_Ctrl * c = new Chuck_DL_Ctrl; | ||
| 508 | c->name = name; | ||
| 509 | c->type = type; | ||
| 510 | c->ctrl = ugen_ctrl; | ||
| 511 | c->cget = ugen_cget; | ||
| 512 | |||
| 513 | // set | ||
| 514 | query->curr_func = NULL; | ||
| 515 | } | ||
| 516 | |||
| 517 | |||
| 518 | |||
| 519 | |||
| 520 | //----------------------------------------------------------------------------- | ||
| 521 | // name: ck_end_class() | ||
| 522 | // desc: end class/namespace, compile it | ||
| 523 | //----------------------------------------------------------------------------- | ||
| 524 | t_CKBOOL CK_DLL_CALL ck_end_class( Chuck_DL_Query * query ) | ||
| 525 | { | ||
| 526 | // make sure there is class | ||
| 527 | if( !query->curr_class ) | ||
| 528 | { | ||
| 529 | // error | ||
| 530 | EM_error2( 0, "class import: end_class invoked without begin_class..." ); | ||
| 531 | return FALSE; | ||
| 532 | } | ||
| 533 | |||
| 534 | // type check the class? | ||
| 535 | // 1.3.2.0: import class into type engine if at top level | ||
| 536 | if( query->stack.size() == 1 ) // top level class | ||
| 537 | { | ||
| 538 | if( !type_engine_add_class_from_dl( query->env(), query->curr_class ) ) | ||
| 539 | { | ||
| 540 | EM_log(CK_LOG_SEVERE, "[chuck](DL): error importing class '%s' into type engine", | ||
| 541 | query->curr_class->name.c_str()); | ||
| 542 | |||
| 543 | // pop | ||
| 544 | assert( query->stack.size() ); | ||
| 545 | query->curr_class = query->stack.back(); | ||
| 546 | query->stack.pop_back(); | ||
| 547 | |||
| 548 | return FALSE; | ||
| 549 | } | ||
| 550 | } | ||
| 551 | |||
| 552 | // pop | ||
| 553 | assert( query->stack.size() ); | ||
| 554 | query->curr_class = query->stack.back(); | ||
| 555 | query->stack.pop_back(); | ||
| 556 | |||
| 557 | return TRUE; | ||
| 558 | } | ||
| 559 | |||
| 560 | |||
| 561 | |||
| 562 | //----------------------------------------------------------------------------- | ||
| 563 | // name: ck_create_main_thread_hook() | ||
| 564 | // desc: ... | ||
| 565 | //----------------------------------------------------------------------------- | ||
| 566 | Chuck_DL_MainThreadHook * CK_DLL_CALL ck_create_main_thread_hook( Chuck_DL_Query * query, | ||
| 567 | f_mainthreadhook hook, | ||
| 568 | f_mainthreadquit quit, | ||
| 569 | void * bindle ) | ||
| 570 | { | ||
| 571 | assert( query->compiler() ); | ||
| 572 | assert( query->vm() ); | ||
| 573 | |||
| 574 | return new Chuck_DL_MainThreadHook( hook, quit, bindle, query->vm() ); | ||
| 575 | } | ||
| 576 | |||
| 577 | //----------------------------------------------------------------------------- | ||
| 578 | // name: ck_doc_class() | ||
| 579 | // desc: set current class documentation | ||
| 580 | //----------------------------------------------------------------------------- | ||
| 581 | t_CKBOOL CK_DLL_CALL ck_doc_class( Chuck_DL_Query * query, const char * doc ) | ||
| 582 | { | ||
| 583 | #ifdef CK_DOC // disable unless CK_DOC | ||
| 584 | if(query->curr_class) | ||
| 585 | query->curr_class->doc = doc; | ||
| 586 | else | ||
| 587 | return FALSE; | ||
| 588 | #endif // CK_DOC | ||
| 589 | |||
| 590 | return TRUE; | ||
| 591 | } | ||
| 592 | |||
| 593 | //----------------------------------------------------------------------------- | ||
| 594 | // name: ck_add_example() | ||
| 595 | // desc: set current class documentation | ||
| 596 | //----------------------------------------------------------------------------- | ||
| 597 | t_CKBOOL CK_DLL_CALL ck_add_example( Chuck_DL_Query * query, const char * ex ) | ||
| 598 | { | ||
| 599 | #ifdef CK_DOC // disable unless CK_DOC | ||
| 600 | if(query->curr_class) | ||
| 601 | query->curr_class->examples.push_back(ex); | ||
| 602 | else | ||
| 603 | return FALSE; | ||
| 604 | #endif // CK_DOC | ||
| 605 | |||
| 606 | return TRUE; | ||
| 607 | } | ||
| 608 | |||
| 609 | // set current function documentation | ||
| 610 | t_CKBOOL CK_DLL_CALL ck_doc_func( Chuck_DL_Query * query, const char * doc ) | ||
| 611 | { | ||
| 612 | #ifdef CK_DOC // disable unless CK_DOC | ||
| 613 | if(query->curr_func) | ||
| 614 | query->curr_func->doc = doc; | ||
| 615 | else | ||
| 616 | return FALSE; | ||
| 617 | #endif // CK_DOC | ||
| 618 | |||
| 619 | return TRUE; | ||
| 620 | } | ||
| 621 | |||
| 622 | // set last mvar documentation | ||
| 623 | t_CKBOOL CK_DLL_CALL ck_doc_var( Chuck_DL_Query * query, const char * doc ) | ||
| 624 | { | ||
| 625 | #ifdef CK_DOC // disable unless CK_DOC | ||
| 626 | if(query->last_var) | ||
| 627 | query->last_var->doc = doc; | ||
| 628 | else | ||
| 629 | return FALSE; | ||
| 630 | #endif // CK_DOC | ||
| 631 | |||
| 632 | return TRUE; | ||
| 633 | } | ||
| 634 | |||
| 635 | |||
| 636 | |||
| 637 | //------------------------------------------------------------------------------ | ||
| 638 | // alternative functions to make stuff | ||
| 639 | //------------------------------------------------------------------------------ | ||
| 640 | Chuck_DL_Func * make_new_mfun( const char * t, const char * n, f_mfun mfun ) | ||
| 641 | { return new Chuck_DL_Func( t, n, (t_CKUINT)mfun ); } | ||
| 642 | Chuck_DL_Func * make_new_sfun( const char * t, const char * n, f_sfun sfun ) | ||
| 643 | { return new Chuck_DL_Func( t, n, (t_CKUINT)sfun ); } | ||
| 644 | Chuck_DL_Value * make_new_arg( const char * t, const char * n ) | ||
| 645 | { return new Chuck_DL_Value( t, n ); } | ||
| 646 | Chuck_DL_Value * make_new_mvar( const char * t, const char * n, t_CKBOOL c ) | ||
| 647 | { return new Chuck_DL_Value( t, n, c ); } | ||
| 648 | Chuck_DL_Value * make_new_svar( const char * t, const char * n, t_CKBOOL c, void * a ) | ||
| 649 | { return new Chuck_DL_Value( t, n, c, a ); } | ||
| 650 | |||
| 651 | |||
| 652 | |||
| 653 | |||
| 654 | //----------------------------------------------------------------------------- | ||
| 655 | // name: load() | ||
| 656 | // desc: load dynamic link library | ||
| 657 | //----------------------------------------------------------------------------- | ||
| 658 | t_CKBOOL Chuck_DLL::load( const char * filename, const char * func, t_CKBOOL lazy ) | ||
| 659 | { | ||
| 660 | // open | ||
| 661 | m_handle = dlopen( filename, lazy ? RTLD_LAZY : RTLD_NOW ); | ||
| 662 | |||
| 663 | // still not there | ||
| 664 | if( !m_handle ) | ||
| 665 | { | ||
| 666 | m_last_error = dlerror(); | ||
| 667 | return FALSE; | ||
| 668 | } | ||
| 669 | |||
| 670 | // save the filename | ||
| 671 | m_filename = filename; | ||
| 672 | m_done_query = FALSE; | ||
| 673 | m_func = func; | ||
| 674 | |||
| 675 | // if not lazy, do it | ||
| 676 | if( !lazy && !this->query() ) | ||
| 677 | return FALSE; | ||
| 678 | |||
| 679 | return TRUE; | ||
| 680 | } | ||
| 681 | |||
| 682 | |||
| 683 | |||
| 684 | |||
| 685 | //----------------------------------------------------------------------------- | ||
| 686 | // name: load() | ||
| 687 | // desc: load dynamic link library | ||
| 688 | //----------------------------------------------------------------------------- | ||
| 689 | t_CKBOOL Chuck_DLL::load( f_ck_query query_func, t_CKBOOL lazy ) | ||
| 690 | { | ||
| 691 | m_query_func = query_func; | ||
| 692 | m_version_func = ck_builtin_declversion; | ||
| 693 | m_done_query = FALSE; | ||
| 694 | m_func = "ck_query"; | ||
| 695 | |||
| 696 | // if not lazy, do it | ||
| 697 | if( !lazy && !this->query() ) | ||
| 698 | return FALSE; | ||
| 699 | |||
| 700 | return TRUE; | ||
| 701 | } | ||
| 702 | |||
| 703 | |||
| 704 | |||
| 705 | |||
| 706 | //----------------------------------------------------------------------------- | ||
| 707 | // name: good() | ||
| 708 | // desc: ... | ||
| 709 | //----------------------------------------------------------------------------- | ||
| 710 | t_CKBOOL Chuck_DLL::good() const | ||
| 711 | { | ||
| 712 | return ( m_handle != NULL || m_query_func != NULL ); | ||
| 713 | } | ||
| 714 | |||
| 715 | |||
| 716 | |||
| 717 | |||
| 718 | //----------------------------------------------------------------------------- | ||
| 719 | // name: query() | ||
| 720 | // desc: ... | ||
| 721 | //----------------------------------------------------------------------------- | ||
| 722 | const Chuck_DL_Query * Chuck_DLL::query( ) | ||
| 723 | { | ||
| 724 | if( !m_handle && !m_query_func ) | ||
| 725 | { | ||
| 726 | m_last_error = "dynamic link library not loaded for query..."; | ||
| 727 | return NULL; | ||
| 728 | } | ||
| 729 | |||
| 730 | // return if there already | ||
| 731 | if( m_done_query ) | ||
| 732 | return &m_query; | ||
| 733 | |||
| 734 | // get the address of the DL version function from the DLL | ||
| 735 | if( !m_version_func ) | ||
| 736 | m_version_func = (f_ck_declversion)this->get_addr( CK_DECLVERSION_FUNC ); | ||
| 737 | if( !m_version_func ) | ||
| 738 | m_version_func = (f_ck_declversion)this->get_addr( (string("_")+CK_DECLVERSION_FUNC).c_str() ); | ||
| 739 | if( !m_version_func ) | ||
| 740 | { | ||
| 741 | m_last_error = string("no version function found in dll '") | ||
| 742 | + m_filename + string("'"); | ||
| 743 | return NULL; | ||
| 744 | } | ||
| 745 | |||
| 746 | // check version | ||
| 747 | t_CKUINT dll_version = m_version_func(); | ||
| 748 | t_CKBOOL version_ok = FALSE; | ||
| 749 | // oops lets have version 4 be ok actually | ||
| 750 | if(CK_DLL_VERSION_GETMAJOR(dll_version) == 4) | ||
| 751 | version_ok = TRUE; | ||
| 752 | // major version must be same | ||
| 753 | // minor version must less than or equal | ||
| 754 | if(CK_DLL_VERSION_GETMAJOR(dll_version) == CK_DLL_VERSION_MAJOR && | ||
| 755 | CK_DLL_VERSION_GETMINOR(dll_version) <= CK_DLL_VERSION_MINOR) | ||
| 756 | version_ok = TRUE; | ||
| 757 | |||
| 758 | if(!version_ok) | ||
| 759 | // SPENCERTODO: do they need to be equal, or can dll_version be < ? | ||
| 760 | { | ||
| 761 | ostringstream oss; | ||
| 762 | oss << "DL version not supported: " | ||
| 763 | << CK_DLL_VERSION_GETMAJOR(dll_version) | ||
| 764 | << "." | ||
| 765 | << CK_DLL_VERSION_GETMINOR(dll_version) | ||
| 766 | << " in '" | ||
| 767 | << m_filename | ||
| 768 | << "'"; | ||
| 769 | |||
| 770 | m_last_error = oss.str(); | ||
| 771 | |||
| 772 | return NULL; | ||
| 773 | } | ||
| 774 | |||
| 775 | // get the address of the query function from the DLL | ||
| 776 | if( !m_query_func ) | ||
| 777 | m_query_func = (f_ck_query)this->get_addr( m_func.c_str() ); | ||
| 778 | if( !m_query_func ) | ||
| 779 | m_query_func = (f_ck_query)this->get_addr( (string("_")+m_func).c_str() ); | ||
| 780 | if( !m_query_func ) | ||
| 781 | { | ||
| 782 | m_last_error = string("no query function found in dll '") | ||
| 783 | + m_filename + string("'"); | ||
| 784 | return NULL; | ||
| 785 | } | ||
| 786 | |||
| 787 | // get the address of the attach function from the DLL | ||
| 788 | /* if( !m_attach_func ) | ||
| 789 | m_attach_func = (f_ck_attach)this->get_addr( "ck_attach" ); | ||
| 790 | if( !m_attach_func ) | ||
| 791 | m_attach_func = (f_ck_attach)this->get_addr( "_ck_attach" ); | ||
| 792 | |||
| 793 | // get the address of the detach function from the DLL | ||
| 794 | if( !m_detach_func ) | ||
| 795 | m_detach_func = (f_ck_detach)this->get_addr( "ck_detach" ); | ||
| 796 | if( !m_detach_func ) | ||
| 797 | m_detach_func = (f_ck_detach)this->get_addr( "_ck_detach" ); */ | ||
| 798 | |||
| 799 | // do the query | ||
| 800 | m_query.clear(); | ||
| 801 | if( !m_query_func( &m_query ) ) | ||
| 802 | { | ||
| 803 | m_last_error = string("unsuccessful query in dll '") + m_filename | ||
| 804 | + string("'"); | ||
| 805 | return NULL; | ||
| 806 | } | ||
| 807 | |||
| 808 | // load the proto table | ||
| 809 | /* Chuck_DL_Proto * proto; | ||
| 810 | m_name2proto.clear(); | ||
| 811 | for( t_CKUINT i = 0; i < m_query.dll_exports.size(); i++ ) | ||
| 812 | { | ||
| 813 | proto = &m_query.dll_exports[i]; | ||
| 814 | if( m_name2proto[proto->name] ) | ||
| 815 | { | ||
| 816 | m_last_error = string("duplicate export name '") + proto->name | ||
| 817 | + string("'"); | ||
| 818 | return NULL; | ||
| 819 | } | ||
| 820 | |||
| 821 | // get the addr | ||
| 822 | if( !proto->addr ) | ||
| 823 | proto->addr = (f_ck_func)this->get_addr( (char *)proto->name.c_str() ); | ||
| 824 | if( !proto->addr ) | ||
| 825 | { | ||
| 826 | m_last_error = string("no addr associated with export '") + | ||
| 827 | proto->name + string("'"); | ||
| 828 | return NULL; | ||
| 829 | } | ||
| 830 | |||
| 831 | // put in the lookup table | ||
| 832 | m_name2proto[proto->name] = proto; | ||
| 833 | } | ||
| 834 | |||
| 835 | // load the proto table | ||
| 836 | Chuck_UGen_Info * info; | ||
| 837 | m_name2ugen.clear(); | ||
| 838 | for( t_CKUINT j = 0; j < m_query.ugen_exports.size(); j++ ) | ||
| 839 | { | ||
| 840 | info = &m_query.ugen_exports[j]; | ||
| 841 | if( m_name2ugen[info->name] ) | ||
| 842 | { | ||
| 843 | m_last_error = string("duplicate export ugen name '") + info->name | ||
| 844 | + string("'"); | ||
| 845 | return NULL; | ||
| 846 | } | ||
| 847 | |||
| 848 | // put in the lookup table | ||
| 849 | m_name2ugen[info->name] = info; | ||
| 850 | }*/ | ||
| 851 | |||
| 852 | m_done_query = TRUE; | ||
| 853 | |||
| 854 | // call attach | ||
| 855 | // if( m_attach_func ) m_attach_func( 0, NULL ); | ||
| 856 | |||
| 857 | return &m_query; | ||
| 858 | } | ||
| 859 | |||
| 860 | |||
| 861 | |||
| 862 | |||
| 863 | //----------------------------------------------------------------------------- | ||
| 864 | // name: unload() | ||
| 865 | // desc: ... | ||
| 866 | //----------------------------------------------------------------------------- | ||
| 867 | t_CKBOOL Chuck_DLL::unload() | ||
| 868 | { | ||
| 869 | if( !m_handle && !m_query_func ) | ||
| 870 | { | ||
| 871 | m_last_error = "cannot unload dynamic library - nothing open..."; | ||
| 872 | return FALSE; | ||
| 873 | } | ||
| 874 | |||
| 875 | // if( m_detach_func ) m_detach_func( 0, NULL ); | ||
| 876 | |||
| 877 | if( m_handle ) | ||
| 878 | { | ||
| 879 | dlclose( m_handle ); | ||
| 880 | m_handle = NULL; | ||
| 881 | } | ||
| 882 | else | ||
| 883 | m_query_func = NULL; | ||
| 884 | |||
| 885 | return TRUE; | ||
| 886 | } | ||
| 887 | |||
| 888 | |||
| 889 | |||
| 890 | |||
| 891 | //----------------------------------------------------------------------------- | ||
| 892 | // name: get_addr() | ||
| 893 | // desc: ... | ||
| 894 | //----------------------------------------------------------------------------- | ||
| 895 | void * Chuck_DLL::get_addr( const char * symbol ) | ||
| 896 | { | ||
| 897 | if( !m_handle ) | ||
| 898 | { | ||
| 899 | m_last_error = "cannot find addr from dynamic library - nothing open..."; | ||
| 900 | return FALSE; | ||
| 901 | } | ||
| 902 | |||
| 903 | return dlsym( m_handle, symbol ); | ||
| 904 | } | ||
| 905 | |||
| 906 | |||
| 907 | |||
| 908 | |||
| 909 | //----------------------------------------------------------------------------- | ||
| 910 | // name: last_error() | ||
| 911 | // desc: ... | ||
| 912 | //----------------------------------------------------------------------------- | ||
| 913 | const char * Chuck_DLL::last_error() const | ||
| 914 | { | ||
| 915 | return m_last_error.c_str(); | ||
| 916 | } | ||
| 917 | |||
| 918 | |||
| 919 | |||
| 920 | |||
| 921 | //----------------------------------------------------------------------------- | ||
| 922 | // name: name() | ||
| 923 | // desc: ... | ||
| 924 | //----------------------------------------------------------------------------- | ||
| 925 | const char * Chuck_DLL::name() const | ||
| 926 | { | ||
| 927 | return m_id.c_str(); | ||
| 928 | } | ||
| 929 | |||
| 930 | |||
| 931 | //const t_CKUINT Chuck_DL_Query::RESERVED_SIZE; | ||
| 932 | |||
| 933 | //----------------------------------------------------------------------------- | ||
| 934 | // name: Chuck_DL_Query | ||
| 935 | // desc: ... | ||
| 936 | //----------------------------------------------------------------------------- | ||
| 937 | Chuck_DL_Query::Chuck_DL_Query( Chuck_Carrier * carrier ) | ||
| 938 | { | ||
| 939 | // set the pointers to functions so the module can call | ||
| 940 | setname = ck_setname; | ||
| 941 | begin_class = ck_begin_class; | ||
| 942 | add_ctor = ck_add_ctor; | ||
| 943 | add_dtor = ck_add_dtor; | ||
| 944 | add_mfun = ck_add_mfun; | ||
| 945 | add_sfun = ck_add_sfun; | ||
| 946 | add_mvar = ck_add_mvar; | ||
| 947 | add_svar = ck_add_svar; | ||
| 948 | add_arg = ck_add_arg; | ||
| 949 | add_ugen_func = ck_add_ugen_func; | ||
| 950 | add_ugen_funcf = ck_add_ugen_funcf; | ||
| 951 | add_ugen_funcf_auto_num_channels = ck_add_ugen_funcf_auto_num_channels; | ||
| 952 | add_ugen_ctrl = ck_add_ugen_ctrl; | ||
| 953 | end_class = ck_end_class; | ||
| 954 | create_main_thread_hook = ck_create_main_thread_hook; | ||
| 955 | doc_class = ck_doc_class; | ||
| 956 | doc_func = ck_doc_func; | ||
| 957 | doc_var = ck_doc_var; | ||
| 958 | m_carrier = carrier; | ||
| 959 | |||
| 960 | // memset(reserved2, NULL, sizeof(void*)*RESERVED_SIZE); | ||
| 961 | |||
| 962 | dll_name = "[noname]"; | ||
| 963 | reserved = NULL; | ||
| 964 | curr_class = NULL; | ||
| 965 | curr_func = NULL; | ||
| 966 | |||
| 967 | #ifndef __CKDL_NO_BBQ__ | ||
| 968 | srate = Digitalio::sampling_rate() ; bufsize = Digitalio::buffer_size(); | ||
| 969 | #else | ||
| 970 | srate = 0; bufsize = 0; | ||
| 971 | #endif | ||
| 972 | |||
| 973 | linepos = 0; | ||
| 974 | } | ||
| 975 | |||
| 976 | |||
| 977 | |||
| 978 | |||
| 979 | //----------------------------------------------------------------------------- | ||
| 980 | // name: clear() | ||
| 981 | // desc: ... | ||
| 982 | //----------------------------------------------------------------------------- | ||
| 983 | void Chuck_DL_Query::clear() | ||
| 984 | { | ||
| 985 | // set to 0 | ||
| 986 | dll_name = "[noname]"; | ||
| 987 | // line pos | ||
| 988 | linepos = 0; | ||
| 989 | // delete classes | ||
| 990 | for( t_CKUINT i = 0; i < classes.size(); i++ ) delete classes[i]; | ||
| 991 | // clear | ||
| 992 | classes.clear(); | ||
| 993 | } | ||
| 994 | |||
| 995 | |||
| 996 | |||
| 997 | |||
| 998 | //----------------------------------------------------------------------------- | ||
| 999 | // name: ~Chuck_DL_Class() | ||
| 1000 | // desc: ... | ||
| 1001 | //----------------------------------------------------------------------------- | ||
| 1002 | Chuck_DL_Class::~Chuck_DL_Class() | ||
| 1003 | { | ||
| 1004 | t_CKUINT i; | ||
| 1005 | |||
| 1006 | // delete mfuns | ||
| 1007 | for( i = 0; i < mfuns.size(); i++ ) delete mfuns[i]; | ||
| 1008 | // delete sfuns | ||
| 1009 | for( i = 0; i < sfuns.size(); i++ ) delete sfuns[i]; | ||
| 1010 | // delete mvars | ||
| 1011 | for( i = 0; i < mvars.size(); i++ ) delete mvars[i]; | ||
| 1012 | // delete svars | ||
| 1013 | for( i = 0; i < svars.size(); i++ ) delete svars[i]; | ||
| 1014 | // delete classes | ||
| 1015 | for( i = 0; i < classes.size(); i++ ) delete classes[i]; | ||
| 1016 | } | ||
| 1017 | |||
| 1018 | |||
| 1019 | |||
| 1020 | |||
| 1021 | //----------------------------------------------------------------------------- | ||
| 1022 | // name: ~Chuck_DL_Func() | ||
| 1023 | // desc: ... | ||
| 1024 | //----------------------------------------------------------------------------- | ||
| 1025 | Chuck_DL_Func::~Chuck_DL_Func() | ||
| 1026 | { | ||
| 1027 | for( t_CKUINT i = 0; i < args.size(); i++ ) | ||
| 1028 | delete args[i]; | ||
| 1029 | } | ||
| 1030 | |||
| 1031 | |||
| 1032 | |||
| 1033 | t_CKBOOL ck_mthook_activate(Chuck_DL_MainThreadHook *hook) | ||
| 1034 | { | ||
| 1035 | // ge: changed in 1.3.5.3 | ||
| 1036 | hook->m_active = set_main_thread_hook(hook->m_hook, | ||
| 1037 | hook->m_quit, | ||
| 1038 | hook->m_bindle); | ||
| 1039 | // hook->m_active = hook->m_vm->set_main_thread_hook(hook->m_hook, | ||
| 1040 | // hook->m_quit, | ||
| 1041 | // hook->m_bindle); | ||
| 1042 | return hook->m_active; | ||
| 1043 | } | ||
| 1044 | |||
| 1045 | t_CKBOOL ck_mthook_deactivate(Chuck_DL_MainThreadHook *hook) | ||
| 1046 | { | ||
| 1047 | if(hook->m_active) | ||
| 1048 | // ge: changed in 1.3.5.3 | ||
| 1049 | return clear_main_thread_hook(); | ||
| 1050 | // return hook->m_vm->clear_main_thread_hook(); | ||
| 1051 | else | ||
| 1052 | return FALSE; | ||
| 1053 | } | ||
| 1054 | |||
| 1055 | //----------------------------------------------------------------------------- | ||
| 1056 | // name: Chuck_DL_MainThreadHook() | ||
| 1057 | // desc: ... | ||
| 1058 | //----------------------------------------------------------------------------- | ||
| 1059 | Chuck_DL_MainThreadHook::Chuck_DL_MainThreadHook(f_mainthreadhook hook, f_mainthreadquit quit, | ||
| 1060 | void * bindle, Chuck_VM * vm) : | ||
| 1061 | m_hook(hook), | ||
| 1062 | m_quit(quit), | ||
| 1063 | m_vm(vm), | ||
| 1064 | m_bindle(bindle), | ||
| 1065 | activate(ck_mthook_activate), | ||
| 1066 | deactivate(ck_mthook_deactivate), | ||
| 1067 | m_active(FALSE) | ||
| 1068 | { } | ||
| 1069 | |||
| 1070 | |||
| 1071 | |||
| 1072 | /******************************************************************************* | ||
| 1073 | |||
| 1074 | Chuck_DL_Api stuff | ||
| 1075 | |||
| 1076 | *******************************************************************************/ | ||
| 1077 | |||
| 1078 | namespace Chuck_DL_Api | ||
| 1079 | { | ||
| 1080 | Api Api::g_api; | ||
| 1081 | } | ||
| 1082 | |||
| 1083 | |||
| 1084 | static t_CKUINT ck_get_srate(CK_DL_API api, Chuck_VM_Shred * shred) | ||
| 1085 | { | ||
| 1086 | return shred->vm_ref->srate(); | ||
| 1087 | } | ||
| 1088 | |||
| 1089 | static Chuck_DL_Api::Type ck_get_type( CK_DL_API api, Chuck_VM_Shred * shred, std::string & name ) | ||
| 1090 | { | ||
| 1091 | Chuck_Env * env = shred->vm_ref->env(); | ||
| 1092 | a_Id_List list = new_id_list( name.c_str(), 0 ); // TODO: nested types | ||
| 1093 | |||
| 1094 | Chuck_Type * t = type_engine_find_type( env, list ); | ||
| 1095 | |||
| 1096 | delete_id_list( list ); | ||
| 1097 | |||
| 1098 | return ( Chuck_DL_Api::Type ) t; | ||
| 1099 | } | ||
| 1100 | |||
| 1101 | static Chuck_DL_Api::Object ck_create( CK_DL_API api, Chuck_VM_Shred * shred, Chuck_DL_Api::Type t ) | ||
| 1102 | { | ||
| 1103 | assert( t != NULL ); | ||
| 1104 | |||
| 1105 | Chuck_Type * type = ( Chuck_Type * ) t; | ||
| 1106 | Chuck_Object * o = instantiate_and_initialize_object( type, shred->vm_ref ); | ||
| 1107 | |||
| 1108 | return ( Chuck_DL_Api::Object ) o; | ||
| 1109 | } | ||
| 1110 | |||
| 1111 | static Chuck_DL_Api::String ck_create_string( CK_DL_API api, Chuck_VM_Shred * shred, std::string & str ) | ||
| 1112 | { | ||
| 1113 | Chuck_String * string = ( Chuck_String * ) instantiate_and_initialize_object( shred->vm_ref->env()->t_string, shred->vm_ref ); | ||
| 1114 | |||
| 1115 | string->set( str ); | ||
| 1116 | |||
| 1117 | return ( Chuck_DL_Api::String ) string; | ||
| 1118 | } | ||
| 1119 | |||
| 1120 | static t_CKBOOL ck_get_mvar_int( CK_DL_API api, Chuck_DL_Api::Object, std::string &, t_CKINT & ) | ||
| 1121 | { | ||
| 1122 | return TRUE; | ||
| 1123 | } | ||
| 1124 | |||
| 1125 | static t_CKBOOL ck_get_mvar_float( CK_DL_API api, Chuck_DL_Api::Object, std::string &, t_CKFLOAT & ) | ||
| 1126 | { | ||
| 1127 | return TRUE; | ||
| 1128 | } | ||
| 1129 | |||
| 1130 | static t_CKBOOL ck_get_mvar_dur( CK_DL_API api, Chuck_DL_Api::Object, std::string &, t_CKDUR & ) | ||
| 1131 | { | ||
| 1132 | return TRUE; | ||
| 1133 | } | ||
| 1134 | |||
| 1135 | static t_CKBOOL ck_get_mvar_time( CK_DL_API api, Chuck_DL_Api::Object, std::string &, t_CKTIME & ) | ||
| 1136 | { | ||
| 1137 | return TRUE; | ||
| 1138 | } | ||
| 1139 | |||
| 1140 | static t_CKBOOL ck_get_mvar_string( CK_DL_API api, Chuck_DL_Api::Object, std::string &, Chuck_DL_Api::String & ) | ||
| 1141 | { | ||
| 1142 | return TRUE; | ||
| 1143 | } | ||
| 1144 | |||
| 1145 | static t_CKBOOL ck_get_mvar_object( CK_DL_API api, Chuck_DL_Api::Object, std::string &, Chuck_DL_Api::Object & ) | ||
| 1146 | { | ||
| 1147 | return TRUE; | ||
| 1148 | } | ||
| 1149 | |||
| 1150 | static t_CKBOOL ck_set_string( CK_DL_API api, Chuck_DL_Api::String s, std::string & str ) | ||
| 1151 | { | ||
| 1152 | assert( s != NULL ); | ||
| 1153 | |||
| 1154 | Chuck_String * string = ( Chuck_String * ) s; | ||
| 1155 | string->set( str ); | ||
| 1156 | |||
| 1157 | return TRUE; | ||
| 1158 | } | ||
| 1159 | |||
| 1160 | |||
| 1161 | Chuck_DL_Api::Api::VMApi::VMApi() : | ||
| 1162 | get_srate(ck_get_srate) | ||
| 1163 | { } | ||
| 1164 | |||
| 1165 | |||
| 1166 | Chuck_DL_Api::Api::ObjectApi::ObjectApi() : | ||
| 1167 | get_type(ck_get_type), | ||
| 1168 | create(ck_create), | ||
| 1169 | create_string(ck_create_string), | ||
| 1170 | get_mvar_int(ck_get_mvar_int), | ||
| 1171 | get_mvar_float(ck_get_mvar_float), | ||
| 1172 | get_mvar_dur(ck_get_mvar_dur), | ||
| 1173 | get_mvar_time(ck_get_mvar_time), | ||
| 1174 | get_mvar_string(ck_get_mvar_string), | ||
| 1175 | get_mvar_object(ck_get_mvar_object), | ||
| 1176 | set_string(ck_set_string) | ||
| 1177 | { } | ||
| 1178 | |||
| 1179 | |||
| 1180 | // windows | ||
| 1181 | #if defined(__WINDOWS_DS__) | ||
| 1182 | extern "C" | ||
| 1183 | { | ||
| 1184 | #include <windows.h> | ||
| 1185 | |||
| 1186 | void *dlopen( const char *path, int mode ) | ||
| 1187 | { | ||
| 1188 | return (void *)LoadLibrary(path); | ||
| 1189 | } | ||
| 1190 | |||
| 1191 | int dlclose( void *handle ) | ||
| 1192 | { | ||
| 1193 | FreeLibrary((HMODULE)handle); | ||
| 1194 | return 1; | ||
| 1195 | } | ||
| 1196 | |||
| 1197 | void *dlsym( void * handle, const char *symbol ) | ||
| 1198 | { | ||
| 1199 | return (void *)GetProcAddress((HMODULE)handle, symbol); | ||
| 1200 | } | ||
| 1201 | |||
| 1202 | const char * dlerror( void ) | ||
| 1203 | { | ||
| 1204 | int error = GetLastError(); | ||
| 1205 | if( error == 0 ) return NULL; | ||
| 1206 | sprintf( dlerror_buffer, "%i", error ); | ||
| 1207 | return dlerror_buffer; | ||
| 1208 | } | ||
| 1209 | } | ||
| 1210 | #endif | ||
| @@ -0,0 +1,755 @@ | |||
| 1 | /*---------------------------------------------------------------------------- | ||
| 2 | ChucK Concurrent, On-the-fly Audio Programming Language | ||
| 3 | Compiler and Virtual Machine | ||
| 4 | |||
| 5 | Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. | ||
| 6 | http://chuck.stanford.edu/ | ||
| 7 | http://chuck.cs.princeton.edu/ | ||
| 8 | |||
| 9 | This program is free software; you can redistribute it and/or modify | ||
| 10 | it under the terms of the GNU General Public License as published by | ||
| 11 | the Free Software Foundation; either version 2 of the License, or | ||
| 12 | (at your option) any later version. | ||
| 13 | |||
| 14 | This program is distributed in the hope that it will be useful, | ||
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | GNU General Public License for more details. | ||
| 18 | |||
| 19 | You should have received a copy of the GNU General Public License | ||
| 20 | along with this program; if not, write to the Free Software | ||
| 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
| 22 | U.S.A. | ||
| 23 | -----------------------------------------------------------------------------*/ | ||
| 24 | |||
| 25 | //----------------------------------------------------------------------------- | ||
| 26 | // name: chuck_dl.h | ||
| 27 | // desc: chuck dynamic linking header | ||
| 28 | // | ||
| 29 | // authors: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) | ||
| 30 | // Ari Lazier (alazier@cs.princeton.edu) | ||
| 31 | // Spencer Salazar (spencer@ccrma.stanford.edu) | ||
| 32 | // mac os code based on apple's open source | ||
| 33 | // | ||
| 34 | // date: spring 2004 - 1.1 | ||
| 35 | // spring 2005 - 1.2 | ||
| 36 | //----------------------------------------------------------------------------- | ||
| 37 | #ifndef __CHUCK_DL_H__ | ||
| 38 | #define __CHUCK_DL_H__ | ||
| 39 | |||
| 40 | #include "chuck_def.h" | ||
| 41 | #include "chuck_oo.h" | ||
| 42 | #include "chuck_carrier.h" | ||
| 43 | #include <string> | ||
| 44 | #include <vector> | ||
| 45 | #include <map> | ||
| 46 | |||
| 47 | |||
| 48 | // major version must be the same between chuck:chugin | ||
| 49 | #define CK_DLL_VERSION_MAJOR (0x0006) | ||
| 50 | // minor version of chugin must be less than or equal to chuck's | ||
| 51 | #define CK_DLL_VERSION_MINOR (0x0000) | ||
| 52 | #define CK_DLL_VERSION_MAKE(maj,min) ((t_CKUINT)(((maj) << 16) | (min))) | ||
| 53 | #define CK_DLL_VERSION_GETMAJOR(v) (((v) >> 16) & 0xFFFF) | ||
| 54 | #define CK_DLL_VERSION_GETMINOR(v) ((v) & 0xFFFF) | ||
| 55 | #define CK_DLL_VERSION (CK_DLL_VERSION_MAKE(CK_DLL_VERSION_MAJOR, CK_DLL_VERSION_MINOR)) | ||
| 56 | |||
| 57 | |||
| 58 | |||
| 59 | |||
| 60 | extern char g_default_chugin_path[]; | ||
| 61 | extern char g_chugin_path_envvar[]; | ||
| 62 | |||
| 63 | |||
| 64 | |||
| 65 | // forward references | ||
| 66 | struct Chuck_DL_Query; | ||
| 67 | struct Chuck_DL_Class; | ||
| 68 | struct Chuck_DL_Func; | ||
| 69 | struct Chuck_DL_Value; | ||
| 70 | struct Chuck_DL_Ctrl; | ||
| 71 | union Chuck_DL_Return; | ||
| 72 | struct Chuck_DLL; | ||
| 73 | struct Chuck_UGen; | ||
| 74 | struct Chuck_UAna; | ||
| 75 | struct Chuck_UAnaBlobProxy; | ||
| 76 | struct Chuck_DL_MainThreadHook; | ||
| 77 | namespace Chuck_DL_Api { struct Api; } | ||
| 78 | |||
| 79 | |||
| 80 | // param conversion - to extract values from ARGS to functions | ||
| 81 | #define GET_CK_FLOAT(ptr) (*(t_CKFLOAT *)ptr) | ||
| 82 | #define GET_CK_SINGLE(ptr) (*(float *)ptr) | ||
| 83 | #define GET_CK_DOUBLE(ptr) (*(double *)ptr) | ||
| 84 | #define GET_CK_INT(ptr) (*(t_CKINT *)ptr) | ||
| 85 | #define GET_CK_UINT(ptr) (*(t_CKUINT *)ptr) | ||
| 86 | #define GET_CK_TIME(ptr) (*(t_CKTIME *)ptr) | ||
| 87 | #define GET_CK_DUR(ptr) (*(t_CKDUR *)ptr) | ||
| 88 | #define GET_CK_COMPLEX(ptr) (*(t_CKCOMPLEX *)ptr) | ||
| 89 | #define GET_CK_POLAR(ptr) (*(t_CKPOLAR *)ptr) | ||
| 90 | #define GET_CK_VEC3(ptr) (*(t_CKVEC3 *)ptr) | ||
| 91 | #define GET_CK_VEC4(ptr) (*(t_CKVEC4 *)ptr) | ||
| 92 | #define GET_CK_VECTOR(ptr) (*(t_CKVECTOR *)ptr) | ||
| 93 | #define GET_CK_OBJECT(ptr) (*(Chuck_Object **)ptr) | ||
| 94 | #define GET_CK_STRING(ptr) (*(Chuck_String **)ptr) | ||
| 95 | |||
| 96 | // param conversion with pointer advance | ||
| 97 | #define GET_NEXT_FLOAT(ptr) (*((t_CKFLOAT *&)ptr)++) | ||
| 98 | #define GET_NEXT_SINGLE(ptr) (*((float *&)ptr)++) | ||
| 99 | #define GET_NEXT_DOUBLE(ptr) (*((double *&)ptr)++) | ||
| 100 | #define GET_NEXT_INT(ptr) (*((t_CKINT *&)ptr)++) | ||
| 101 | #define GET_NEXT_UINT(ptr) (*((t_CKUINT *&)ptr)++) | ||
| 102 | #define GET_NEXT_TIME(ptr) (*((t_CKTIME *&)ptr)++) | ||
| 103 | #define GET_NEXT_DUR(ptr) (*((t_CKDUR *&)ptr)++) | ||
| 104 | #define GET_NEXT_COMPLEX(ptr) (*((t_CKCOMPLEX *&)ptr)++) | ||
| 105 | #define GET_NEXT_POLAR(ptr) (*((t_CKPOLAR *&)ptr)++) | ||
| 106 | #define GET_NEXT_VEC3(ptr) (*((t_CKVEC3 *&)ptr)++) | ||
| 107 | #define GET_NEXT_VEC4(ptr) (*((t_CKVEC4 *&)ptr)++) | ||
| 108 | #define GET_NEXT_VECTOR(ptr) (*((t_CKVECTOR *&)ptr)++) | ||
| 109 | #define GET_NEXT_OBJECT(ptr) (*((Chuck_Object **&)ptr)++) | ||
| 110 | #define GET_NEXT_STRING(ptr) (*((Chuck_String **&)ptr)++) | ||
| 111 | |||
| 112 | // param conversion | ||
| 113 | #define SET_CK_FLOAT(ptr,v) (*(t_CKFLOAT *&)ptr=v) | ||
| 114 | #define SET_CK_SINGLE(ptr,v) (*(float *&)ptr=v) | ||
| 115 | #define SET_CK_DOUBLE(ptr,v) (*(double *&)ptr=v) | ||
| 116 | #define SET_CK_INT(ptr,v) (*(t_CKINT *&)ptr=v) | ||
| 117 | #define SET_CK_UINT(ptr,v) (*(t_CKUINT *&)ptr=v) | ||
| 118 | #define SET_CK_TIME(ptr,v) (*(t_CKTIME *&)ptr=v) | ||
| 119 | #define SET_CK_DUR(ptr,v) (*(t_CKDUR *&)ptr=v) | ||
| 120 | #define SET_CK_VEC3(ptr,v) (*(t_CKVEC3 *&)ptr=v) | ||
| 121 | #define SET_CK_VEC4(ptr,v) (*(t_CKVEC4 *&)ptr=v) | ||
| 122 | #define SET_CK_VECTOR(ptr,v) (*(t_CKVECTOR *&)ptr=v) | ||
| 123 | #define SET_CK_STRING(ptr,v) (*(Chuck_String **&)ptr=v) | ||
| 124 | |||
| 125 | // param conversion with pointer advance | ||
| 126 | #define SET_NEXT_FLOAT(ptr,v) (*((t_CKFLOAT *&)ptr)++=v) | ||
| 127 | #define SET_NEXT_SINGLE(ptr,v) (*((float *&)ptr)++=v) | ||
| 128 | #define SET_NEXT_DOUBLE(ptr,v) (*((double *&)ptr)++=v) | ||
| 129 | #define SET_NEXT_INT(ptr,v) (*((t_CKINT *&)ptr)++=v) | ||
| 130 | #define SET_NEXT_UINT(ptr,v) (*((t_CKUINT *&)ptr)++=v) | ||
| 131 | #define SET_NEXT_TIME(ptr,v) (*((t_CKTIME *&)ptr)++=v) | ||
| 132 | #define SET_NEXT_DUR(ptr,v) (*((t_CKDUR *&)ptr)++=v) | ||
| 133 | #define SET_NEXT_VEC3(ptr,v) (*((t_CKVEC3 *&)ptr)++=v) | ||
| 134 | #define SET_NEXT_VEC4(ptr,v) (*((t_CKVEC4 *&)ptr)++=v) | ||
| 135 | #define SET_NEXT_VECTOR(ptr,v) (*((t_CKVECTOR *&)ptr)++=v) | ||
| 136 | #define SET_NEXT_STRING(ptr,v) (*((Chuck_String **&)ptr)++=v) | ||
| 137 | |||
| 138 | // param conversion - to extract values from object's data segment | ||
| 139 | #define OBJ_MEMBER_DATA(obj,offset) (obj->data + offset) | ||
| 140 | #define OBJ_MEMBER_FLOAT(obj,offset) (*(t_CKFLOAT *)OBJ_MEMBER_DATA(obj,offset)) | ||
| 141 | #define OBJ_MEMBER_SINGLE(obj,offset) (*(float *)OBJ_MEMBER_DATA(obj,offset)) | ||
| 142 | #define OBJ_MEMBER_DOUBLE(obj,offset) (*(double *)OBJ_MEMBER_DATA(obj,offset)) | ||
| 143 | #define OBJ_MEMBER_INT(obj,offset) (*(t_CKINT *)OBJ_MEMBER_DATA(obj,offset)) | ||
| 144 | #define OBJ_MEMBER_UINT(obj,offset) (*(t_CKUINT *)OBJ_MEMBER_DATA(obj,offset)) | ||
| 145 | #define OBJ_MEMBER_TIME(obj,offset) (*(t_CKTIME *)OBJ_MEMBER_DATA(obj,offset)) | ||
| 146 | #define OBJ_MEMBER_DUR(obj,offset) (*(t_CKDUR *)OBJ_MEMBER_DATA(obj,offset)) | ||
| 147 | #define OBJ_MEMBER_VEC3(obj,offset) (*(t_CKVEC3 *)OBJ_MEMBER_DATA(obj,offset)) | ||
| 148 | #define OBJ_MEMBER_VEC4(obj,offset) (*(t_CKVEC4 *)OBJ_MEMBER_DATA(obj,offset)) | ||
| 149 | #define OBJ_MEMBER_VECTOR(obj,offset) (*(t_CKVECTOR *)OBJ_MEMBER_DATA(obj,offset)) | ||
| 150 | #define OBJ_MEMBER_OBJECT(obj,offset) (*(Chuck_Object **)OBJ_MEMBER_DATA(obj,offset)) | ||
| 151 | #define OBJ_MEMBER_STRING(obj,offset) (*(Chuck_String **)OBJ_MEMBER_DATA(obj,offset)) | ||
| 152 | |||
| 153 | |||
| 154 | // chuck dll export linkage and calling convention | ||
| 155 | #if defined (__PLATFORM_WIN32__) | ||
| 156 | #define CK_DLL_LINKAGE extern "C" __declspec( dllexport ) | ||
| 157 | #else | ||
| 158 | #define CK_DLL_LINKAGE extern "C" | ||
| 159 | #endif | ||
| 160 | |||
| 161 | // calling convention of functions provided by chuck to the dll | ||
| 162 | #if defined(__WINDOWS_DS__) | ||
| 163 | #define CK_DLL_CALL _cdecl | ||
| 164 | #else | ||
| 165 | #define CK_DLL_CALL | ||
| 166 | #endif | ||
| 167 | |||
| 168 | typedef const Chuck_DL_Api::Api *CK_DL_API; | ||
| 169 | |||
| 170 | // macro for defining ChucK DLL export functions | ||
| 171 | // example: CK_DLL_EXPORT(int) foo() { return 1; } | ||
| 172 | #define CK_DLL_EXPORT(type) CK_DLL_LINKAGE type CK_DLL_CALL | ||
| 173 | // macro for declaring version of ChucK DL a given DLL links to | ||
| 174 | // example: CK_DLL_DECLVERSION | ||
| 175 | #define CK_DLL_DECLVERSION CK_DLL_EXPORT(t_CKUINT) ck_version() { return CK_DLL_VERSION; } | ||
| 176 | // naming convention for static query functions | ||
| 177 | #define CK_DLL_QUERY_STATIC_NAME(name) ck_##name##_query | ||
| 178 | // macro for defining ChucK DLL export query-functions (static version) | ||
| 179 | #define CK_DLL_QUERY_STATIC(name) CK_DLL_EXPORT(t_CKBOOL) CK_DLL_QUERY_STATIC_NAME(name)( Chuck_DL_Query * QUERY ) | ||
| 180 | // macro for defining ChucK DLL export query-functions | ||
| 181 | // example: CK_DLL_QUERY | ||
| 182 | #ifndef __CK_DLL_STATIC__ | ||
| 183 | #define CK_DLL_QUERY(name) CK_DLL_DECLVERSION CK_DLL_EXPORT(t_CKBOOL) ck_query( Chuck_DL_Query * QUERY ) | ||
| 184 | #else | ||
| 185 | #define CK_DLL_QUERY(name) CK_DLL_QUERY_STATIC(name) | ||
| 186 | #endif // __CK_DLL_STATIC__ | ||
| 187 | // macro for defining ChucK DLL export allocator | ||
| 188 | // example: CK_DLL_ALLOC(foo) | ||
| 189 | #define CK_DLL_ALLOC(name) CK_DLL_EXPORT(Chuck_Object *) name( Chuck_VM_Shred * SHRED, CK_DL_API API ) | ||
| 190 | // macro for defining ChucK DLL export constructors | ||
| 191 | // example: CK_DLL_CTOR(foo) | ||
| 192 | #define CK_DLL_CTOR(name) CK_DLL_EXPORT(void) name( Chuck_Object * SELF, void * ARGS, Chuck_VM_Shred * SHRED, CK_DL_API API ) | ||
| 193 | // macro for defining ChucK DLL export destructors | ||
| 194 | // example: CK_DLL_DTOR(foo) | ||
| 195 | #define CK_DLL_DTOR(name) CK_DLL_EXPORT(void) name( Chuck_Object * SELF, Chuck_VM_Shred * SHRED, CK_DL_API API ) | ||
| 196 | // macro for defining ChucK DLL export member functions | ||
| 197 | // example: CK_DLL_MFUN(foo) | ||
| 198 | #define CK_DLL_MFUN(name) CK_DLL_EXPORT(void) name( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED, CK_DL_API API ) | ||
| 199 | // macro for defining ChucK DLL export static functions | ||
| 200 | // example: CK_DLL_SFUN(foo) | ||
| 201 | #define CK_DLL_SFUN(name) CK_DLL_EXPORT(void) name( void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED, CK_DL_API API ) | ||
| 202 | // macro for defining ChucK DLL export ugen tick functions | ||
| 203 | // example: CK_DLL_TICK(foo) | ||
| 204 | #define CK_DLL_TICK(name) CK_DLL_EXPORT(t_CKBOOL) name( Chuck_Object * SELF, SAMPLE in, SAMPLE * out, Chuck_VM_Shred * SHRED, CK_DL_API API ) | ||
| 205 | // macro for defining ChucK DLL export ugen multi-channel tick functions | ||
| 206 | // example: CK_DLL_TICKF(foo) | ||
| 207 | #define CK_DLL_TICKF(name) CK_DLL_EXPORT(t_CKBOOL) name( Chuck_Object * SELF, SAMPLE * in, SAMPLE * out, t_CKUINT nframes, Chuck_VM_Shred * SHRED, CK_DL_API API ) | ||
| 208 | // macro for defining ChucK DLL export ugen ctrl functions | ||
| 209 | // example: CK_DLL_CTRL(foo) | ||
| 210 | #define CK_DLL_CTRL(name) CK_DLL_EXPORT(void) name( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED, CK_DL_API API ) | ||
| 211 | // macro for defining ChucK DLL export ugen cget functions | ||
| 212 | // example: CK_DLL_CGET(foo) | ||
| 213 | #define CK_DLL_CGET(name) CK_DLL_EXPORT(void) name( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED, CK_DL_API API ) | ||
| 214 | // macro for defining ChucK DLL export ugen pmsg functions | ||
| 215 | // example: CK_DLL_PMSG(foo) | ||
| 216 | #define CK_DLL_PMSG(name) CK_DLL_EXPORT(t_CKBOOL) name( Chuck_Object * SELF, const char * MSG, void * ARGS, Chuck_VM_Shred * SHRED, CK_DL_API API ) | ||
| 217 | // macro for defining ChucK DLL export uana tock functions | ||
| 218 | // example: CK_DLL_TOCK(foo) | ||
| 219 | #define CK_DLL_TOCK(name) CK_DLL_EXPORT(t_CKBOOL) name( Chuck_Object * SELF, Chuck_UAna * UANA, Chuck_UAnaBlobProxy * BLOB, Chuck_VM_Shred * SHRED, CK_DL_API API ) | ||
| 220 | |||
| 221 | |||
| 222 | // macros for DLL exports | ||
| 223 | // example: DLL_QUERY query( Chuck_DL_Query * QUERY ) | ||
| 224 | // example: DLL_FUNC foo( void * ARGS, Chuck_DL_Return * RETURN ) | ||
| 225 | // example: DLL_UGEN_F foo_tick( Chuck_UGen * SELF, SAMPLE, SAMPLE * out ); | ||
| 226 | #define DLL_QUERY CK_DLL_EXPORT(t_CKBOOL) | ||
| 227 | #define DLL_FUNC CK_DLL_EXPORT(void) | ||
| 228 | #define UGEN_CTOR CK_DLL_EXPORT(void *) | ||
| 229 | #define UGEN_DTOR CK_DLL_EXPORT(void) | ||
| 230 | #define UGEN_TICK CK_DLL_EXPORT(t_CKBOOL) | ||
| 231 | #define UGEN_PMSG CK_DLL_EXPORT(t_CKBOOL) | ||
| 232 | #define UGEN_CTRL CK_DLL_EXPORT(t_CKVOID) | ||
| 233 | #define UGEN_CGET CK_DLL_EXPORT(t_CKVOID) | ||
| 234 | #define UANA_TOCK CK_DLL_EXPORT(t_CKBOOL) | ||
| 235 | |||
| 236 | |||
| 237 | //----------------------------------------------------------------------------- | ||
| 238 | // dynamic linking class interface prototypes | ||
| 239 | //----------------------------------------------------------------------------- | ||
| 240 | extern "C" { | ||
| 241 | // query | ||
| 242 | typedef t_CKUINT (CK_DLL_CALL * f_ck_declversion)(); | ||
| 243 | typedef t_CKBOOL (CK_DLL_CALL * f_ck_query)( Chuck_DL_Query * QUERY ); | ||
| 244 | // object | ||
| 245 | typedef Chuck_Object * (CK_DLL_CALL * f_alloc)( Chuck_VM_Shred * SHRED, CK_DL_API API ); | ||
| 246 | typedef t_CKVOID (CK_DLL_CALL * f_ctor)( Chuck_Object * SELF, void * ARGS, Chuck_VM_Shred * SHRED, CK_DL_API API ); | ||
| 247 | typedef t_CKVOID (CK_DLL_CALL * f_dtor)( Chuck_Object * SELF, Chuck_VM_Shred * SHRED, CK_DL_API API ); | ||
| 248 | typedef t_CKVOID (CK_DLL_CALL * f_mfun)( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED, CK_DL_API API ); | ||
| 249 | typedef t_CKVOID (CK_DLL_CALL * f_sfun)( void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED, CK_DL_API API ); | ||
| 250 | // ugen specific | ||
| 251 | typedef t_CKBOOL (CK_DLL_CALL * f_tick)( Chuck_Object * SELF, SAMPLE in, SAMPLE * out, Chuck_VM_Shred * SHRED, CK_DL_API API ); | ||
| 252 | typedef t_CKBOOL (CK_DLL_CALL * f_tickf)( Chuck_Object * SELF, SAMPLE * in, SAMPLE * out, t_CKUINT nframes, Chuck_VM_Shred * SHRED, CK_DL_API API ); | ||
| 253 | typedef t_CKVOID (CK_DLL_CALL * f_ctrl)( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED, CK_DL_API API ); | ||
| 254 | typedef t_CKVOID (CK_DLL_CALL * f_cget)( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED, CK_DL_API API ); | ||
| 255 | typedef t_CKBOOL (CK_DLL_CALL * f_pmsg)( Chuck_Object * SELF, const char * MSG, void * ARGS, Chuck_VM_Shred * SHRED, CK_DL_API API ); | ||
| 256 | // uana specific | ||
| 257 | typedef t_CKBOOL (CK_DLL_CALL * f_tock)( Chuck_Object * SELF, Chuck_UAna * UANA, Chuck_UAnaBlobProxy * BLOB, Chuck_VM_Shred * SHRED, CK_DL_API API ); | ||
| 258 | // "main thread" hook | ||
| 259 | typedef t_CKBOOL (CK_DLL_CALL * f_mainthreadhook)( void * bindle ); | ||
| 260 | // "main thread" quit (stop running hook) | ||
| 261 | typedef t_CKBOOL (CK_DLL_CALL * f_mainthreadquit)( void * bindle ); | ||
| 262 | } | ||
| 263 | |||
| 264 | |||
| 265 | // default name in DLL/ckx to look for | ||
| 266 | #define CK_QUERY_FUNC "ck_query" | ||
| 267 | // default name in DLL/ckx to look for | ||
| 268 | #define CK_DECLVERSION_FUNC "ck_version" | ||
| 269 | // bad object data offset | ||
| 270 | #define CK_INVALID_OFFSET 0xffffffff | ||
| 271 | |||
| 272 | |||
| 273 | //----------------------------------------------------------------------------- | ||
| 274 | // chuck DLL query functions, implemented on chuck side for portability | ||
| 275 | //----------------------------------------------------------------------------- | ||
| 276 | extern "C" { | ||
| 277 | // set name of ckx | ||
| 278 | typedef void ( CK_DLL_CALL * f_setname)( Chuck_DL_Query * query, const char * name ); | ||
| 279 | |||
| 280 | // begin class/namespace, can be nested | ||
| 281 | typedef void (CK_DLL_CALL * f_begin_class)( Chuck_DL_Query * query, const char * name, const char * parent ); | ||
| 282 | // add constructor, must be betwen begin/end_class : use f_add_arg to add arguments immediately after | ||
| 283 | typedef void (CK_DLL_CALL * f_add_ctor)( Chuck_DL_Query * query, f_ctor ctor ); | ||
| 284 | // add destructor - cannot have args | ||
| 285 | typedef void (CK_DLL_CALL * f_add_dtor)( Chuck_DL_Query * query, f_dtor dtor ); | ||
| 286 | // add member function - args to follow | ||
| 287 | typedef void (CK_DLL_CALL * f_add_mfun)( Chuck_DL_Query * query, f_mfun mfun, const char * type, const char * name ); | ||
| 288 | // add static function - args to follow | ||
| 289 | typedef void (CK_DLL_CALL * f_add_sfun)( Chuck_DL_Query * query, f_sfun sfun, const char * type, const char * name ); | ||
| 290 | // add member variable | ||
| 291 | typedef t_CKUINT (CK_DLL_CALL * f_add_mvar)( Chuck_DL_Query * query, | ||
| 292 | const char * type, const char * name, t_CKBOOL is_const ); // TODO: public/protected/private | ||
| 293 | // add static variable | ||
| 294 | typedef void (CK_DLL_CALL * f_add_svar)( Chuck_DL_Query * query, | ||
| 295 | const char * type, const char * name, | ||
| 296 | t_CKBOOL is_const, void * static_addr ); // TODO: public/protected/private | ||
| 297 | // add arg - follows ctor mfun sfun | ||
| 298 | typedef void (CK_DLL_CALL * f_add_arg)( Chuck_DL_Query * query, const char * type, const char * name ); | ||
| 299 | // ** functions for adding unit generators, must extend ugen | ||
| 300 | typedef void (CK_DLL_CALL * f_add_ugen_func)( Chuck_DL_Query * query, f_tick tick, f_pmsg pmsg, t_CKUINT num_in, t_CKUINT num_out ); | ||
| 301 | typedef void (CK_DLL_CALL * f_add_ugen_funcf)( Chuck_DL_Query * query, f_tickf tickf, f_pmsg pmsg, t_CKUINT num_in, t_CKUINT num_out ); | ||
| 302 | typedef void (CK_DLL_CALL * f_add_ugen_funcf_auto_num_channels)( Chuck_DL_Query * query, f_tickf tickf, f_pmsg psmg ); | ||
| 303 | // ** add a ugen control | ||
| 304 | typedef void (CK_DLL_CALL * f_add_ugen_ctrl)( Chuck_DL_Query * query, f_ctrl ctrl, f_cget cget, | ||
| 305 | const char * type, const char * name ); | ||
| 306 | // end class/namespace - must correspondent with begin_class. returns false on error | ||
| 307 | typedef t_CKBOOL (CK_DLL_CALL * f_end_class)( Chuck_DL_Query * query ); | ||
| 308 | // register | ||
| 309 | typedef Chuck_DL_MainThreadHook * (CK_DLL_CALL * f_create_main_thread_hook)( Chuck_DL_Query * query, f_mainthreadhook hook, f_mainthreadquit quit, void * bindle ); | ||
| 310 | |||
| 311 | // documentation | ||
| 312 | // set current class documentation | ||
| 313 | typedef t_CKBOOL (CK_DLL_CALL * f_doc_class)( Chuck_DL_Query * query, const char * doc ); | ||
| 314 | // add example of current class | ||
| 315 | typedef t_CKBOOL (CK_DLL_CALL * f_add_example)( Chuck_DL_Query * query, const char * ex ); | ||
| 316 | // set current function documentation | ||
| 317 | typedef t_CKBOOL (CK_DLL_CALL * f_doc_func)( Chuck_DL_Query * query, const char * doc ); | ||
| 318 | // set last mvar documentation | ||
| 319 | typedef t_CKBOOL (CK_DLL_CALL * f_doc_var)( Chuck_DL_Query * query, const char * doc ); | ||
| 320 | } | ||
| 321 | |||
| 322 | |||
| 323 | //----------------------------------------------------------------------------- | ||
| 324 | // name: struct Chuck_DL_Query | ||
| 325 | // desc: passed to module | ||
| 326 | //----------------------------------------------------------------------------- | ||
| 327 | struct Chuck_DL_Query | ||
| 328 | { | ||
| 329 | protected: | ||
| 330 | // REFACTOR-2017: carrier ref | ||
| 331 | Chuck_Carrier * m_carrier; | ||
| 332 | |||
| 333 | public: | ||
| 334 | // REFACTOR-2017: get associated compiler, vm, env | ||
| 335 | Chuck_Compiler * compiler() const { return m_carrier->compiler; } | ||
| 336 | Chuck_VM * vm() const { return m_carrier->vm; } | ||
| 337 | Chuck_Env * env() const { return m_carrier->env; } | ||
| 338 | |||
| 339 | public: | ||
| 340 | // function pointers - to be called from client module | ||
| 341 | // QUERY->setname( QUERY, ... ); | ||
| 342 | // | ||
| 343 | // set the name of the module | ||
| 344 | f_setname setname; | ||
| 345 | // begin class/namespace, can be nexted | ||
| 346 | f_begin_class begin_class; | ||
| 347 | // add constructor, can be followed by add_arg | ||
| 348 | f_add_ctor add_ctor; | ||
| 349 | // add destructor, no args allowed | ||
| 350 | f_add_dtor add_dtor; | ||
| 351 | // add member function, can be followed by add_arg | ||
| 352 | f_add_mfun add_mfun; | ||
| 353 | // add static function, can be followed by add_arg | ||
| 354 | f_add_sfun add_sfun; | ||
| 355 | // add member variable | ||
| 356 | f_add_mvar add_mvar; | ||
| 357 | // add static variable | ||
| 358 | f_add_svar add_svar; | ||
| 359 | // add argument to function | ||
| 360 | f_add_arg add_arg; | ||
| 361 | // (ugen only) add tick and pmsg functions | ||
| 362 | f_add_ugen_func add_ugen_func; | ||
| 363 | // (ugen only) add tick and pmsg functions | ||
| 364 | f_add_ugen_funcf add_ugen_funcf; | ||
| 365 | // (ugen only) add tick and pmsg functions, specify channels by vm | ||
| 366 | f_add_ugen_funcf_auto_num_channels add_ugen_funcf_auto_num_channels; | ||
| 367 | // (ugen only) add ctrl parameters | ||
| 368 | f_add_ugen_ctrl add_ugen_ctrl; | ||
| 369 | // end class/namespace, compile it | ||
| 370 | f_end_class end_class; | ||
| 371 | |||
| 372 | // added 1.3.2.0 | ||
| 373 | f_create_main_thread_hook create_main_thread_hook; | ||
| 374 | |||
| 375 | // added 1.3.5 | ||
| 376 | Chuck_DL_Value * last_var; | ||
| 377 | f_doc_class doc_class; | ||
| 378 | f_doc_func doc_func; | ||
| 379 | f_doc_var doc_var; | ||
| 380 | f_add_example add_ex; | ||
| 381 | |||
| 382 | // NOTE: everything below std::anything cannot be reliably accessed | ||
| 383 | // by offset between dynamic modules, since std::anything could be variable | ||
| 384 | // size -- put everything need to be accessed across modules above here! | ||
| 385 | // discovered by the vigilant and forever traumatized Jack Atherton, | ||
| 386 | // fixed during REFACTOR-2017; warning by the guilt-ridden Ge Wang | ||
| 387 | |||
| 388 | // dll | ||
| 389 | Chuck_DLL * dll_ref; | ||
| 390 | // reserved | ||
| 391 | void * reserved; | ||
| 392 | // sample rate | ||
| 393 | t_CKUINT srate; | ||
| 394 | // bsize | ||
| 395 | t_CKUINT bufsize; | ||
| 396 | // line pos | ||
| 397 | int linepos; | ||
| 398 | // name of dll | ||
| 399 | std::string dll_name; | ||
| 400 | |||
| 401 | // current class | ||
| 402 | Chuck_DL_Class * curr_class; | ||
| 403 | // current function | ||
| 404 | Chuck_DL_Func * curr_func; | ||
| 405 | // name | ||
| 406 | std::string name; | ||
| 407 | // collection of class | ||
| 408 | std::vector<Chuck_DL_Class *> classes; | ||
| 409 | // stack | ||
| 410 | std::vector<Chuck_DL_Class * >stack; | ||
| 411 | |||
| 412 | // constructor | ||
| 413 | Chuck_DL_Query( Chuck_Carrier * carrier ); | ||
| 414 | // desctructor | ||
| 415 | ~Chuck_DL_Query() { this->clear(); } | ||
| 416 | // clear | ||
| 417 | void clear(); | ||
| 418 | }; | ||
| 419 | |||
| 420 | |||
| 421 | |||
| 422 | |||
| 423 | //----------------------------------------------------------------------------- | ||
| 424 | // name: struct Chuck_DL_Class | ||
| 425 | // desc: class built from module | ||
| 426 | //----------------------------------------------------------------------------- | ||
| 427 | struct Chuck_DL_Class | ||
| 428 | { | ||
| 429 | // the name of the class | ||
| 430 | std::string name; | ||
| 431 | // the name of the parent | ||
| 432 | std::string parent; | ||
| 433 | // ctor | ||
| 434 | std::vector<Chuck_DL_Func *> ctors; | ||
| 435 | // dtor | ||
| 436 | Chuck_DL_Func * dtor; | ||
| 437 | // mfun | ||
| 438 | std::vector<Chuck_DL_Func *> mfuns; | ||
| 439 | // sfun | ||
| 440 | std::vector<Chuck_DL_Func *> sfuns; | ||
| 441 | // mdata | ||
| 442 | std::vector<Chuck_DL_Value *> mvars; | ||
| 443 | // sdata | ||
| 444 | std::vector<Chuck_DL_Value *> svars; | ||
| 445 | // ugen_tick | ||
| 446 | f_tick ugen_tick; | ||
| 447 | // ugen_tickf | ||
| 448 | f_tickf ugen_tickf; | ||
| 449 | // ugen_pmsg | ||
| 450 | f_pmsg ugen_pmsg; | ||
| 451 | // ugen_ctrl/cget | ||
| 452 | std::vector<Chuck_DL_Ctrl *> ugen_ctrl; | ||
| 453 | // uana_tock | ||
| 454 | f_tock uana_tock; | ||
| 455 | // collection of recursive classes | ||
| 456 | std::vector<Chuck_DL_Class *> classes; | ||
| 457 | // current mvar offset | ||
| 458 | t_CKUINT current_mvar_offset; | ||
| 459 | |||
| 460 | t_CKUINT ugen_num_in, ugen_num_out; | ||
| 461 | |||
| 462 | std::string doc; | ||
| 463 | std::vector<std::string> examples; | ||
| 464 | |||
| 465 | // constructor | ||
| 466 | Chuck_DL_Class() { dtor = NULL; ugen_tick = NULL; ugen_tickf = NULL; ugen_pmsg = NULL; uana_tock = NULL; ugen_pmsg = NULL; current_mvar_offset = 0; ugen_num_in = ugen_num_out = 0; } | ||
| 467 | // destructor | ||
| 468 | ~Chuck_DL_Class(); | ||
| 469 | }; | ||
| 470 | |||
| 471 | |||
| 472 | |||
| 473 | |||
| 474 | //----------------------------------------------------------------------------- | ||
| 475 | // name: struct Chuck_DL_Value | ||
| 476 | // desc: value from module | ||
| 477 | //----------------------------------------------------------------------------- | ||
| 478 | struct Chuck_DL_Value | ||
| 479 | { | ||
| 480 | // the name of the value | ||
| 481 | std::string name; | ||
| 482 | // the type of the value | ||
| 483 | std::string type; | ||
| 484 | // is const | ||
| 485 | t_CKBOOL is_const; | ||
| 486 | // addr static | ||
| 487 | void * static_addr; | ||
| 488 | // description | ||
| 489 | std::string doc; | ||
| 490 | |||
| 491 | // constructor | ||
| 492 | Chuck_DL_Value() { is_const = FALSE; static_addr = NULL; } | ||
| 493 | Chuck_DL_Value( const char * t, const char * n, t_CKBOOL c = FALSE, void * a = NULL ) | ||
| 494 | { name = n; type = t; is_const = c; static_addr = a; } | ||
| 495 | }; | ||
| 496 | |||
| 497 | |||
| 498 | |||
| 499 | |||
| 500 | //----------------------------------------------------------------------------- | ||
| 501 | // name: struct Chuck_DL_Func | ||
| 502 | // desc: function from module | ||
| 503 | //----------------------------------------------------------------------------- | ||
| 504 | struct Chuck_DL_Func | ||
| 505 | { | ||
| 506 | // the name of the function | ||
| 507 | std::string name; | ||
| 508 | // the return type | ||
| 509 | std::string type; | ||
| 510 | // the pointer | ||
| 511 | union { f_ctor ctor; f_dtor dtor; f_mfun mfun; f_sfun sfun; t_CKUINT addr; }; | ||
| 512 | // arguments | ||
| 513 | std::vector<Chuck_DL_Value *> args; | ||
| 514 | // description | ||
| 515 | std::string doc; | ||
| 516 | |||
| 517 | // constructor | ||
| 518 | Chuck_DL_Func() { ctor = NULL; } | ||
| 519 | Chuck_DL_Func( const char * t, const char * n, t_CKUINT a ) | ||
| 520 | { name = n; type = t; addr = a; } | ||
| 521 | // destructor | ||
| 522 | ~Chuck_DL_Func(); | ||
| 523 | // add arg | ||
| 524 | void add_arg( const char * t, const char * n ) | ||
| 525 | { args.push_back( new Chuck_DL_Value( t, n ) ); } | ||
| 526 | }; | ||
| 527 | |||
| 528 | |||
| 529 | |||
| 530 | |||
| 531 | //----------------------------------------------------------------------------- | ||
| 532 | // name: struct Chuck_DL_Ctrl | ||
| 533 | // desc: ctrl for ugen | ||
| 534 | //----------------------------------------------------------------------------- | ||
| 535 | struct Chuck_DL_Ctrl | ||
| 536 | { | ||
| 537 | // the name of the ctrl | ||
| 538 | std::string name; | ||
| 539 | // the first type | ||
| 540 | std::string type; | ||
| 541 | // the types of the value | ||
| 542 | std::vector<std::string> types; | ||
| 543 | // ctrl | ||
| 544 | f_ctrl ctrl; | ||
| 545 | // cget | ||
| 546 | f_cget cget; | ||
| 547 | }; | ||
| 548 | |||
| 549 | |||
| 550 | |||
| 551 | |||
| 552 | //------------------------------------------------------------------------------ | ||
| 553 | // alternative functions to make stuff | ||
| 554 | //------------------------------------------------------------------------------ | ||
| 555 | Chuck_DL_Func * make_new_mfun( const char * t, const char * n, f_mfun mfun ); | ||
| 556 | Chuck_DL_Func * make_new_sfun( const char * t, const char * n, f_sfun sfun ); | ||
| 557 | Chuck_DL_Value * make_new_arg( const char * t, const char * n ); | ||
| 558 | Chuck_DL_Value * make_new_mvar( const char * t, const char * n, t_CKBOOL c = FALSE ); | ||
| 559 | Chuck_DL_Value * make_new_svar( const char * t, const char * n, t_CKBOOL c, void * a ); | ||
| 560 | |||
| 561 | |||
| 562 | |||
| 563 | |||
| 564 | //------------------------------------------------------------------------------ | ||
| 565 | // name: union Chuck_DL_Return | ||
| 566 | // desc: dynamic link return function return struct | ||
| 567 | //------------------------------------------------------------------------------ | ||
| 568 | union Chuck_DL_Return | ||
| 569 | { | ||
| 570 | t_CKINT v_int; | ||
| 571 | t_CKUINT v_uint; | ||
| 572 | t_CKFLOAT v_float; | ||
| 573 | t_CKDUR v_dur; | ||
| 574 | t_CKTIME v_time; | ||
| 575 | t_CKCOMPLEX v_complex; | ||
| 576 | t_CKPOLAR v_polar; | ||
| 577 | t_CKVEC3 v_vec3; // ge: added 1.3.5.3 | ||
| 578 | t_CKVEC4 v_vec4; // ge: added 1.3.5.3 | ||
| 579 | Chuck_Object * v_object; | ||
| 580 | Chuck_String * v_string; | ||
| 581 | |||
| 582 | Chuck_DL_Return() { v_vec4.x = v_vec4.y = v_vec4.z = v_vec4.w = 0; } | ||
| 583 | }; | ||
| 584 | |||
| 585 | |||
| 586 | |||
| 587 | |||
| 588 | //----------------------------------------------------------------------------- | ||
| 589 | // name: struct Chuck_DLL | ||
| 590 | // desc: dynamic link library | ||
| 591 | //----------------------------------------------------------------------------- | ||
| 592 | struct Chuck_DLL : public Chuck_VM_Object | ||
| 593 | { | ||
| 594 | public: | ||
| 595 | // load dynamic ckx/dll from filename | ||
| 596 | t_CKBOOL load( const char * filename, | ||
| 597 | const char * func = CK_QUERY_FUNC, | ||
| 598 | t_CKBOOL lazy = FALSE ); | ||
| 599 | t_CKBOOL load( f_ck_query query_func, t_CKBOOL lazy = FALSE ); | ||
| 600 | // get address in loaded ckx | ||
| 601 | void * get_addr( const char * symbol ); | ||
| 602 | // get last error | ||
| 603 | const char * last_error() const; | ||
| 604 | // unload the ckx | ||
| 605 | t_CKBOOL unload( ); | ||
| 606 | // query the content of the dll | ||
| 607 | const Chuck_DL_Query * query( ); | ||
| 608 | // is good | ||
| 609 | t_CKBOOL good() const; | ||
| 610 | // name | ||
| 611 | const char * name() const; | ||
| 612 | |||
| 613 | public: | ||
| 614 | // constructor | ||
| 615 | Chuck_DLL( Chuck_Carrier * carrier, const char * xid = NULL ) | ||
| 616 | : m_handle(NULL), m_id(xid ? xid : ""), | ||
| 617 | m_query( carrier ), | ||
| 618 | m_done_query(FALSE), m_query_func(NULL), m_version_func(NULL) | ||
| 619 | { } | ||
| 620 | // destructor | ||
| 621 | ~Chuck_DLL() { this->unload(); } | ||
| 622 | |||
| 623 | protected: | ||
| 624 | // data | ||
| 625 | void * m_handle; | ||
| 626 | std::string m_last_error; | ||
| 627 | std::string m_filename; | ||
| 628 | std::string m_id; | ||
| 629 | std::string m_func; | ||
| 630 | t_CKBOOL m_done_query; | ||
| 631 | |||
| 632 | f_ck_declversion m_version_func; | ||
| 633 | f_ck_query m_query_func; | ||
| 634 | Chuck_DL_Query m_query; | ||
| 635 | }; | ||
| 636 | |||
| 637 | struct Chuck_DL_MainThreadHook | ||
| 638 | { | ||
| 639 | public: | ||
| 640 | Chuck_DL_MainThreadHook(f_mainthreadhook hook, f_mainthreadquit quit, | ||
| 641 | void * bindle, Chuck_VM * vm); | ||
| 642 | t_CKBOOL (* const activate)(Chuck_DL_MainThreadHook *); | ||
| 643 | t_CKBOOL (* const deactivate)(Chuck_DL_MainThreadHook *); | ||
| 644 | |||
| 645 | Chuck_VM * const m_vm; | ||
| 646 | f_mainthreadhook const m_hook; | ||
| 647 | f_mainthreadquit const m_quit; | ||
| 648 | void * const m_bindle; | ||
| 649 | t_CKBOOL m_active; | ||
| 650 | }; | ||
| 651 | |||
| 652 | |||
| 653 | |||
| 654 | |||
| 655 | /* API to ChucK's innards */ | ||
| 656 | namespace Chuck_DL_Api | ||
| 657 | { | ||
| 658 | typedef void * Object; | ||
| 659 | typedef void * Type; | ||
| 660 | typedef void * String; | ||
| 661 | |||
| 662 | struct Api | ||
| 663 | { | ||
| 664 | public: | ||
| 665 | static Api g_api; | ||
| 666 | static inline const Api * instance() { return &g_api; } | ||
| 667 | |||
| 668 | struct VMApi | ||
| 669 | { | ||
| 670 | VMApi(); | ||
| 671 | t_CKUINT (* const get_srate)( CK_DL_API, Chuck_VM_Shred * ); | ||
| 672 | } * const vm; | ||
| 673 | |||
| 674 | struct ObjectApi | ||
| 675 | { | ||
| 676 | ObjectApi(); | ||
| 677 | |||
| 678 | private: | ||
| 679 | Type (* const get_type)( CK_DL_API, Chuck_VM_Shred *, std::string &name ); | ||
| 680 | |||
| 681 | Object (* const create)( CK_DL_API, Chuck_VM_Shred *, Type type ); | ||
| 682 | |||
| 683 | String (* const create_string)( CK_DL_API, Chuck_VM_Shred *, std::string &value ); | ||
| 684 | |||
| 685 | t_CKBOOL (* const get_mvar_int)( CK_DL_API, Object object, std::string &name, t_CKINT &value ); | ||
| 686 | t_CKBOOL (* const get_mvar_float)( CK_DL_API, Object object, std::string &name, t_CKFLOAT &value ); | ||
| 687 | t_CKBOOL (* const get_mvar_dur)( CK_DL_API, Object object, std::string &name, t_CKDUR &value ); | ||
| 688 | t_CKBOOL (* const get_mvar_time)( CK_DL_API, Object object, std::string &name, t_CKTIME &value ); | ||
| 689 | t_CKBOOL (* const get_mvar_string)( CK_DL_API, Object object, std::string &name, String &value ); | ||
| 690 | t_CKBOOL (* const get_mvar_object)( CK_DL_API, Object object, std::string &name, Object &value ); | ||
| 691 | |||
| 692 | t_CKBOOL (* const set_string)( CK_DL_API, String string, std::string &value ); | ||
| 693 | |||
| 694 | } * const object; | ||
| 695 | |||
| 696 | Api() : | ||
| 697 | vm(new VMApi), | ||
| 698 | object(new ObjectApi) | ||
| 699 | {} | ||
| 700 | |||
| 701 | private: | ||
| 702 | Api(Api &a) : | ||
| 703 | vm(a.vm), | ||
| 704 | object(a.object) | ||
| 705 | { assert(0); }; | ||
| 706 | |||
| 707 | Api &operator=(Api &a) { assert(0); return a; } | ||
| 708 | }; | ||
| 709 | } | ||
| 710 | |||
| 711 | |||
| 712 | |||
| 713 | // dlfcn interface | ||
| 714 | #if defined(__MACOSX_CORE__) | ||
| 715 | #include <AvailabilityMacros.h> | ||
| 716 | #endif | ||
| 717 | |||
| 718 | // dlfcn interface, panther or below | ||
| 719 | #if defined(__MACOSX_CORE__) && MAC_OS_X_VERSION_MAX_ALLOWED <= 1030 | ||
| 720 | |||
| 721 | #error ChucK not support on Mac OS X 10.3 or lower | ||
| 722 | |||
| 723 | #elif defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) | ||
| 724 | |||
| 725 | #ifdef __cplusplus | ||
| 726 | extern "C" { | ||
| 727 | #endif | ||
| 728 | |||
| 729 | #define RTLD_LAZY 0x1 | ||
| 730 | #define RTLD_NOW 0x2 | ||
| 731 | #define RTLD_LOCAL 0x4 | ||
| 732 | #define RTLD_GLOBAL 0x8 | ||
| 733 | #define RTLD_NOLOAD 0x10 | ||
| 734 | #define RTLD_SHARED 0x20 /* not used, the default */ | ||
| 735 | #define RTLD_UNSHARED 0x40 | ||
| 736 | #define RTLD_NODELETE 0x80 | ||
| 737 | #define RTLD_LAZY_UNDEF 0x100 | ||
| 738 | |||
| 739 | void * dlopen( const char * path, int mode ); | ||
| 740 | void * dlsym( void * handle, const char * symbol ); | ||
| 741 | const char * dlerror( void ); | ||
| 742 | int dlclose( void * handle ); | ||
| 743 | static char dlerror_buffer[128]; | ||
| 744 | |||
| 745 | #ifdef __cplusplus | ||
| 746 | } | ||
| 747 | #endif | ||
| 748 | |||
| 749 | #else | ||
| 750 | #include "dlfcn.h" | ||
| 751 | #endif | ||
| 752 | |||
| 753 | |||
| 754 | |||
| 755 | #endif | ||
| @@ -0,0 +1,4972 @@ | |||
| 1 | /*---------------------------------------------------------------------------- | ||
| 2 | ChucK Concurrent, On-the-fly Audio Programming Language | ||
| 3 | Compiler and Virtual Machine | ||
| 4 | |||
| 5 | Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. | ||
| 6 | http://chuck.stanford.edu/ | ||
| 7 | http://chuck.cs.princeton.edu/ | ||
| 8 | |||
| 9 | This program is free software; you can redistribute it and/or modify | ||
| 10 | it under the terms of the GNU General Public License as published by | ||
| 11 | the Free Software Foundation; either version 2 of the License, or | ||
| 12 | (at your option) any later version. | ||
| 13 | |||
| 14 | This program is distributed in the hope that it will be useful, | ||
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | GNU General Public License for more details. | ||
| 18 | |||
| 19 | You should have received a copy of the GNU General Public License | ||
| 20 | along with this program; if not, write to the Free Software | ||
| 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
| 22 | U.S.A. | ||
| 23 | -----------------------------------------------------------------------------*/ | ||
| 24 | |||
| 25 | //----------------------------------------------------------------------------- | ||
| 26 | // file: chuck_emit.cpp | ||
| 27 | // desc: chuck instruction emitter | ||
| 28 | // | ||
| 29 | // author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) | ||
| 30 | // date: Autumn 2002 - first version | ||
| 31 | // Autumn 2004 - redesign | ||
| 32 | //----------------------------------------------------------------------------- | ||
| 33 | #include "chuck_emit.h" | ||
| 34 | #include "chuck_vm.h" | ||
| 35 | #include "chuck_errmsg.h" | ||
| 36 | #include "chuck_instr.h" | ||
| 37 | #include <sstream> | ||
| 38 | #include <iostream> | ||
| 39 | |||
| 40 | using namespace std; | ||
| 41 | |||
| 42 | |||
| 43 | |||
| 44 | |||
| 45 | //----------------------------------------------------------------------------- | ||
| 46 | // function prototypes | ||
| 47 | //----------------------------------------------------------------------------- | ||
| 48 | t_CKBOOL emit_engine_emit_stmt_list( Chuck_Emitter * emit, a_Stmt_List list ); | ||
| 49 | t_CKBOOL emit_engine_emit_stmt( Chuck_Emitter * emit, a_Stmt stmt, t_CKBOOL pop = TRUE ); | ||
| 50 | t_CKBOOL emit_engine_emit_if( Chuck_Emitter * emit, a_Stmt_If stmt ); | ||
| 51 | t_CKBOOL emit_engine_emit_for( Chuck_Emitter * emit, a_Stmt_For stmt ); | ||
| 52 | t_CKBOOL emit_engine_emit_while( Chuck_Emitter * emit, a_Stmt_While stmt ); | ||
| 53 | t_CKBOOL emit_engine_emit_do_while( Chuck_Emitter * emit, a_Stmt_While stmt ); | ||
| 54 | t_CKBOOL emit_engine_emit_until( Chuck_Emitter * emit, a_Stmt_Until stmt ); | ||
| 55 | t_CKBOOL emit_engine_emit_do_until( Chuck_Emitter * emit, a_Stmt_Until stmt ); | ||
| 56 | t_CKBOOL emit_engine_emit_loop( Chuck_Emitter * emit, a_Stmt_Loop stmt ); | ||
| 57 | t_CKBOOL emit_engine_emit_break( Chuck_Emitter * emit, a_Stmt_Break br ); | ||
| 58 | t_CKBOOL emit_engine_emit_continue( Chuck_Emitter * emit, a_Stmt_Continue cont ); | ||
| 59 | t_CKBOOL emit_engine_emit_return( Chuck_Emitter * emit, a_Stmt_Return stmt ); | ||
| 60 | t_CKBOOL emit_engine_emit_switch( Chuck_Emitter * emit, a_Stmt_Switch stmt ); | ||
| 61 | t_CKBOOL emit_engine_emit_exp( Chuck_Emitter * emit, a_Exp exp, t_CKBOOL doAddRef = FALSE ); | ||
| 62 | t_CKBOOL emit_engine_emit_exp_binary( Chuck_Emitter * emit, a_Exp_Binary binary ); | ||
| 63 | t_CKBOOL emit_engine_emit_op( Chuck_Emitter * emit, ae_Operator op, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ); | ||
| 64 | t_CKBOOL emit_engine_emit_op_chuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ); | ||
| 65 | t_CKBOOL emit_engine_emit_op_unchuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs ); | ||
| 66 | t_CKBOOL emit_engine_emit_op_upchuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs ); | ||
| 67 | t_CKBOOL emit_engine_emit_op_at_chuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs ); | ||
| 68 | t_CKBOOL emit_engine_emit_exp_unary( Chuck_Emitter * emit, a_Exp_Unary unary ); | ||
| 69 | t_CKBOOL emit_engine_emit_exp_primary( Chuck_Emitter * emit, a_Exp_Primary exp ); | ||
| 70 | t_CKBOOL emit_engine_emit_exp_cast( Chuck_Emitter * emit, a_Exp_Cast cast ); | ||
| 71 | t_CKBOOL emit_engine_emit_exp_postfix( Chuck_Emitter * emit, a_Exp_Postfix postfix ); | ||
| 72 | t_CKBOOL emit_engine_emit_exp_dur( Chuck_Emitter * emit, a_Exp_Dur dur ); | ||
| 73 | t_CKBOOL emit_engine_emit_exp_array( Chuck_Emitter * emit, a_Exp_Array array ); | ||
| 74 | t_CKBOOL emit_engine_emit_exp_func_call( Chuck_Emitter * emit, Chuck_Func * func, | ||
| 75 | Chuck_Type * type, int linepos, t_CKBOOL spork = FALSE ); | ||
| 76 | t_CKBOOL emit_engine_emit_exp_func_call( Chuck_Emitter * emit, a_Exp_Func_Call func_call, | ||
| 77 | t_CKBOOL spork = FALSE ); | ||
| 78 | t_CKBOOL emit_engine_emit_func_args( Chuck_Emitter * emit, a_Exp_Func_Call func_call ); | ||
| 79 | t_CKBOOL emit_engine_emit_exp_dot_member( Chuck_Emitter * emit, a_Exp_Dot_Member member ); | ||
| 80 | t_CKBOOL emit_engine_emit_exp_if( Chuck_Emitter * emit, a_Exp_If exp_if ); | ||
| 81 | t_CKBOOL emit_engine_emit_exp_decl( Chuck_Emitter * emit, a_Exp_Decl decl, t_CKBOOL first_exp ); | ||
| 82 | t_CKBOOL emit_engine_emit_array_lit( Chuck_Emitter * emit, a_Array_Sub array ); | ||
| 83 | t_CKBOOL emit_engine_emit_complex_lit( Chuck_Emitter * emit, a_Complex val ); | ||
| 84 | t_CKBOOL emit_engine_emit_polar_lit( Chuck_Emitter * emit, a_Polar val ); | ||
| 85 | t_CKBOOL emit_engine_emit_vec_lit( Chuck_Emitter * emit, a_Vec val ); | ||
| 86 | t_CKBOOL emit_engine_emit_code_segment( Chuck_Emitter * emit, a_Stmt_Code stmt, | ||
| 87 | t_CKBOOL push = TRUE ); | ||
| 88 | t_CKBOOL emit_engine_emit_func_def( Chuck_Emitter * emit, a_Func_Def func_def ); | ||
| 89 | t_CKBOOL emit_engine_emit_class_def( Chuck_Emitter * emit, a_Class_Def class_def ); | ||
| 90 | t_CKBOOL emit_engine_pre_constructor( Chuck_Emitter * emit, Chuck_Type * type ); | ||
| 91 | t_CKBOOL emit_engine_instantiate_object( Chuck_Emitter * emit, Chuck_Type * type, | ||
| 92 | a_Array_Sub array, t_CKBOOL is_ref ); | ||
| 93 | t_CKBOOL emit_engine_emit_spork( Chuck_Emitter * emit, a_Exp_Func_Call exp ); | ||
| 94 | t_CKBOOL emit_engine_emit_cast( Chuck_Emitter * emit, Chuck_Type * to, Chuck_Type * from ); | ||
| 95 | t_CKBOOL emit_engine_emit_symbol( Chuck_Emitter * emit, S_Symbol symbol, | ||
| 96 | Chuck_Value * v, t_CKBOOL emit_var, int linepos ); | ||
| 97 | // disabled until further notice (added 1.3.0.0) | ||
| 98 | // t_CKBOOL emit_engine_emit_spork( Chuck_Emitter * emit, a_Stmt stmt ); | ||
| 99 | |||
| 100 | |||
| 101 | |||
| 102 | |||
| 103 | //----------------------------------------------------------------------------- | ||
| 104 | // name: emit_engine_init() | ||
| 105 | // desc: ... | ||
| 106 | //----------------------------------------------------------------------------- | ||
| 107 | Chuck_Emitter * emit_engine_init( Chuck_Env * env ) | ||
| 108 | { | ||
| 109 | // log | ||
| 110 | EM_log( CK_LOG_SEVERE, "initializing emitter..." ); | ||
| 111 | |||
| 112 | // TODO: ensure this in a better way | ||
| 113 | assert( sizeof(t_CKUINT) == sizeof(void *) ); | ||
| 114 | |||
| 115 | // allocate new emit | ||
| 116 | Chuck_Emitter * emit = new Chuck_Emitter; | ||
| 117 | // set the reference | ||
| 118 | emit->env = env; | ||
| 119 | |||
| 120 | return emit; | ||
| 121 | } | ||
| 122 | |||
| 123 | |||
| 124 | |||
| 125 | |||
| 126 | //----------------------------------------------------------------------------- | ||
| 127 | // name: emit_engine_shutdown() | ||
| 128 | // desc: ... | ||
| 129 | //----------------------------------------------------------------------------- | ||
| 130 | t_CKBOOL emit_engine_shutdown( Chuck_Emitter *& emit ) | ||
| 131 | { | ||
| 132 | if( !emit ) return FALSE; | ||
| 133 | |||
| 134 | // log | ||
| 135 | EM_log( CK_LOG_SYSTEM, "shutting down emitter..." ); | ||
| 136 | |||
| 137 | // delete | ||
| 138 | delete emit; | ||
| 139 | emit = NULL; | ||
| 140 | |||
| 141 | return TRUE; | ||
| 142 | } | ||
| 143 | |||
| 144 | |||
| 145 | |||
| 146 | |||
| 147 | //----------------------------------------------------------------------------- | ||
| 148 | // name: emit_engine_emit_prog() | ||
| 149 | // desc: ... | ||
| 150 | //----------------------------------------------------------------------------- | ||
| 151 | Chuck_VM_Code * emit_engine_emit_prog( Chuck_Emitter * emit, a_Program prog, | ||
| 152 | te_HowMuch how_much ) | ||
| 153 | { | ||
| 154 | // make sure the code is NULL | ||
| 155 | assert( emit->code == NULL ); | ||
| 156 | // make sure the stack is empty | ||
| 157 | assert( emit->stack.size() == 0 ); | ||
| 158 | // make sure there is a context to emit | ||
| 159 | assert( emit->env->context != NULL ); | ||
| 160 | // make sure no code | ||
| 161 | assert( emit->env->context->nspc->pre_ctor == NULL ); | ||
| 162 | |||
| 163 | // log | ||
| 164 | EM_log( CK_LOG_FINER, "(pass 4) emitting VM code '%s'...", | ||
| 165 | emit->env->context->filename.c_str() ); | ||
| 166 | // push indent | ||
| 167 | EM_pushlog(); | ||
| 168 | // log how much | ||
| 169 | EM_log( CK_LOG_FINER, "target: %s", howmuch2str( how_much ) ); | ||
| 170 | |||
| 171 | // return | ||
| 172 | t_CKBOOL ret = TRUE; | ||
| 173 | // allocate the code | ||
| 174 | emit->code = new Chuck_Code; | ||
| 175 | // set the current context | ||
| 176 | emit->context = emit->env->context; | ||
| 177 | // set the namespace | ||
| 178 | emit->nspc = emit->context->nspc; | ||
| 179 | // reset the func | ||
| 180 | emit->func = NULL; | ||
| 181 | // clear the code stack | ||
| 182 | emit->stack.clear(); | ||
| 183 | // name the code | ||
| 184 | // emit->code->name = "(main)"; | ||
| 185 | // whether code need this | ||
| 186 | emit->code->need_this = TRUE; | ||
| 187 | // keep track of full path (added 1.3.0.0) | ||
| 188 | emit->code->filename = emit->context->full_path; | ||
| 189 | // push global scope (added 1.3.0.0) | ||
| 190 | emit->push_scope(); | ||
| 191 | |||
| 192 | // loop over the program sections | ||
| 193 | while( prog && ret ) | ||
| 194 | { | ||
| 195 | switch( prog->section->s_type ) | ||
| 196 | { | ||
| 197 | case ae_section_stmt: // code section | ||
| 198 | // if only classes, then skip | ||
| 199 | if( how_much == te_do_classes_only ) break; | ||
| 200 | // emit statement list | ||
| 201 | ret = emit_engine_emit_stmt_list( emit, prog->section->stmt_list ); | ||
| 202 | break; | ||
| 203 | |||
| 204 | case ae_section_func: // function definition | ||
| 205 | // if only classes, then skip | ||
| 206 | if( how_much == te_do_classes_only ) break; | ||
| 207 | // check function definition | ||
| 208 | ret = emit_engine_emit_func_def( emit, prog->section->func_def ); | ||
| 209 | break; | ||
| 210 | |||
| 211 | case ae_section_class: // class definition | ||
| 212 | // if no classes, then skip | ||
| 213 | if( how_much == te_do_no_classes ) break; | ||
| 214 | // check class definition | ||
| 215 | ret = emit_engine_emit_class_def( emit, prog->section->class_def ); | ||
| 216 | break; | ||
| 217 | |||
| 218 | default: // bad | ||
| 219 | EM_error2( 0, | ||
| 220 | "internal compiler error: unrecognized program section..." ); | ||
| 221 | ret = FALSE; | ||
| 222 | break; | ||
| 223 | } | ||
| 224 | |||
| 225 | // the next | ||
| 226 | prog = prog->next; | ||
| 227 | } | ||
| 228 | |||
| 229 | if( ret ) | ||
| 230 | { | ||
| 231 | // pop global scope (added 1.3.0.0) | ||
| 232 | emit->pop_scope(); | ||
| 233 | // append end of code | ||
| 234 | emit->append( new Chuck_Instr_EOC ); | ||
| 235 | // make sure | ||
| 236 | assert( emit->context->nspc->pre_ctor == NULL ); | ||
| 237 | // converted to virtual machine code | ||
| 238 | emit->context->nspc->pre_ctor = emit_to_code( emit->code, NULL, emit->dump ); | ||
| 239 | // add reference | ||
| 240 | emit->context->nspc->pre_ctor->add_ref(); | ||
| 241 | } | ||
| 242 | |||
| 243 | // clear the code | ||
| 244 | delete emit->code; | ||
| 245 | emit->code = NULL; | ||
| 246 | |||
| 247 | // pop indent | ||
| 248 | EM_poplog(); | ||
| 249 | |||
| 250 | // return the code | ||
| 251 | return emit->context->nspc->pre_ctor; | ||
| 252 | } | ||
| 253 | |||
| 254 | |||
| 255 | |||
| 256 | |||
| 257 | //----------------------------------------------------------------------------- | ||
| 258 | // name: emit_to_code() | ||
| 259 | // desc: ... | ||
| 260 | //----------------------------------------------------------------------------- | ||
| 261 | Chuck_VM_Code * emit_to_code( Chuck_Code * in, | ||
| 262 | Chuck_VM_Code * out, | ||
| 263 | t_CKBOOL dump ) | ||
| 264 | { | ||
| 265 | // log | ||
| 266 | EM_log( CK_LOG_FINER, "emitting code: %d VM instructions...", | ||
| 267 | in->code.size() ); | ||
| 268 | // allocate the vm code | ||
| 269 | Chuck_VM_Code * code = out ? out : new Chuck_VM_Code; | ||
| 270 | // make sure | ||
| 271 | assert( code->num_instr == 0 ); | ||
| 272 | // size | ||
| 273 | code->num_instr = in->code.size(); | ||
| 274 | // allocate instruction pointers+ | ||
| 275 | code->instr = new Chuck_Instr *[code->num_instr]; | ||
| 276 | // set the stack depth | ||
| 277 | code->stack_depth = in->stack_depth; | ||
| 278 | // set whether code need this base pointer | ||
| 279 | code->need_this = in->need_this; | ||
| 280 | // set name | ||
| 281 | code->name = in->name; | ||
| 282 | // set filename for me.sourceDir() (added 1.3.0.0) | ||
| 283 | code->filename = in->filename; | ||
| 284 | |||
| 285 | // copy | ||
| 286 | for( t_CKUINT i = 0; i < code->num_instr; i++ ) | ||
| 287 | code->instr[i] = in->code[i]; | ||
| 288 | |||
| 289 | // dump | ||
| 290 | if( dump ) | ||
| 291 | { | ||
| 292 | // name of what we are dumping | ||
| 293 | EM_error2( 0, "dumping %s:", in->name.c_str() ); | ||
| 294 | |||
| 295 | // uh | ||
| 296 | EM_error2( 0, "-------" ); | ||
| 297 | for( t_CKUINT i = 0; i < code->num_instr; i++ ) | ||
| 298 | EM_error2( 0, "[%i] %s( %s )", i, | ||
| 299 | code->instr[i]->name(), code->instr[i]->params() ); | ||
| 300 | EM_error2( 0, "-------\n" ); | ||
| 301 | } | ||
| 302 | |||
| 303 | return code; | ||
| 304 | } | ||
| 305 | |||
| 306 | |||
| 307 | |||
| 308 | |||
| 309 | //----------------------------------------------------------------------------- | ||
| 310 | // name: | ||
| 311 | // desc: ... | ||
| 312 | //----------------------------------------------------------------------------- | ||
| 313 | // t_CKBOOL emit_engine_addr_map( Chuck_Emitter * emit, Chuck_VM_Shred * shred ); | ||
| 314 | |||
| 315 | |||
| 316 | |||
| 317 | |||
| 318 | //----------------------------------------------------------------------------- | ||
| 319 | // name: | ||
| 320 | // desc: ... | ||
| 321 | //----------------------------------------------------------------------------- | ||
| 322 | // t_CKBOOL emit_engine_resolve( ); | ||
| 323 | |||
| 324 | |||
| 325 | |||
| 326 | |||
| 327 | //----------------------------------------------------------------------------- | ||
| 328 | // name: emit_engine_emit_stmt_list() | ||
| 329 | // desc: ... | ||
| 330 | //----------------------------------------------------------------------------- | ||
| 331 | t_CKBOOL emit_engine_emit_stmt_list( Chuck_Emitter * emit, a_Stmt_List list ) | ||
| 332 | { | ||
| 333 | t_CKBOOL ret = TRUE; | ||
| 334 | |||
| 335 | // emit->push(); | ||
| 336 | while( list && ret ) | ||
| 337 | { | ||
| 338 | ret = emit_engine_emit_stmt( emit, list->stmt ); | ||
| 339 | list = list->next; | ||
| 340 | } | ||
| 341 | // emit->pop(); | ||
| 342 | |||
| 343 | return ret; | ||
| 344 | } | ||
| 345 | |||
| 346 | |||
| 347 | |||
| 348 | |||
| 349 | //----------------------------------------------------------------------------- | ||
| 350 | // name: emit_engine_emit_stmt() | ||
| 351 | // desc: ... | ||
| 352 | //----------------------------------------------------------------------------- | ||
| 353 | t_CKBOOL emit_engine_emit_stmt( Chuck_Emitter * emit, a_Stmt stmt, t_CKBOOL pop ) | ||
| 354 | { | ||
| 355 | // empty stmt list | ||
| 356 | if( !stmt ) | ||
| 357 | return TRUE; | ||
| 358 | |||
| 359 | // return | ||
| 360 | t_CKBOOL ret = TRUE; | ||
| 361 | |||
| 362 | // loop over statements | ||
| 363 | switch( stmt->s_type ) | ||
| 364 | { | ||
| 365 | case ae_stmt_exp: // expression statement | ||
| 366 | // emit it | ||
| 367 | ret = emit_engine_emit_exp( emit, stmt->stmt_exp ); | ||
| 368 | if( !ret ) | ||
| 369 | return FALSE; | ||
| 370 | // need to pop the final value from stack | ||
| 371 | if( ret && pop && stmt->stmt_exp->type->size > 0 ) | ||
| 372 | { | ||
| 373 | // sanity | ||
| 374 | assert( stmt->stmt_exp->cast_to == NULL ); | ||
| 375 | |||
| 376 | // exp | ||
| 377 | a_Exp exp = stmt->stmt_exp; | ||
| 378 | // hack | ||
| 379 | if( exp->s_type == ae_exp_primary && exp->primary.s_type == ae_primary_hack ) | ||
| 380 | exp = exp->primary.exp; | ||
| 381 | |||
| 382 | // HACK! | ||
| 383 | while( exp ) | ||
| 384 | { | ||
| 385 | // if decl, then expect only one word per var | ||
| 386 | // added 1.3.1.0: iskindofint -- since on some 64-bit systems sz_INT == sz_FLOAT | ||
| 387 | if( exp->s_type == ae_exp_decl ) | ||
| 388 | // (added 1.3.1.0 -- multiply by type size; #64-bit) | ||
| 389 | // (fixed 1.3.1.2 -- uh... decl should also be int-sized, so changed to INT/WORD) | ||
| 390 | emit->append( new Chuck_Instr_Reg_Pop_Word4( exp->decl.num_var_decls * sz_INT / sz_WORD ) ); | ||
| 391 | else if( exp->type->size == sz_INT && iskindofint(emit->env, exp->type) ) // ISSUE: 64-bit (fixed 1.3.1.0) | ||
| 392 | emit->append( new Chuck_Instr_Reg_Pop_Word ); | ||
| 393 | else if( exp->type->size == sz_FLOAT ) // ISSUE: 64-bit (fixed 1.3.1.0) | ||
| 394 | emit->append( new Chuck_Instr_Reg_Pop_Word2 ); | ||
| 395 | else if( exp->type->size == sz_COMPLEX ) // ISSUE: 64-bit (fixed 1.3.1.0) | ||
| 396 | emit->append( new Chuck_Instr_Reg_Pop_Word3 ); | ||
| 397 | else if( exp->type->size == sz_VEC3 ) // ge: added 1.3.5.3 | ||
| 398 | emit->append( new Chuck_Instr_Reg_Pop_Word4(sz_VEC3/sz_WORD) ); | ||
| 399 | else if( exp->type->size == sz_VEC4 ) // ge: added 1.3.5.3 | ||
| 400 | emit->append( new Chuck_Instr_Reg_Pop_Word4(sz_VEC4/sz_WORD) ); | ||
| 401 | else | ||
| 402 | { | ||
| 403 | EM_error2( exp->linepos, | ||
| 404 | "(emit): internal error: %i byte stack item unhandled...", | ||
| 405 | exp->type->size ); | ||
| 406 | return FALSE; | ||
| 407 | } | ||
| 408 | |||
| 409 | // go | ||
| 410 | exp = exp->next; | ||
| 411 | } | ||
| 412 | } | ||
| 413 | break; | ||
| 414 | |||
| 415 | case ae_stmt_if: // if statement | ||
| 416 | ret = emit_engine_emit_if( emit, &stmt->stmt_if ); | ||
| 417 | break; | ||
| 418 | |||
| 419 | case ae_stmt_for: // for statement | ||
| 420 | ret = emit_engine_emit_for( emit, &stmt->stmt_for ); | ||
| 421 | break; | ||
| 422 | |||
| 423 | case ae_stmt_while: // while statement | ||
| 424 | if( stmt->stmt_while.is_do ) | ||
| 425 | ret = emit_engine_emit_do_while( emit, &stmt->stmt_while ); | ||
| 426 | else | ||
| 427 | ret = emit_engine_emit_while( emit, &stmt->stmt_while ); | ||
| 428 | break; | ||
| 429 | |||
| 430 | case ae_stmt_until: // until statement | ||
| 431 | if( stmt->stmt_until.is_do ) | ||
| 432 | ret = emit_engine_emit_do_until( emit, &stmt->stmt_until ); | ||
| 433 | else | ||
| 434 | ret = emit_engine_emit_until( emit, &stmt->stmt_until ); | ||
| 435 | break; | ||
| 436 | |||
| 437 | case ae_stmt_loop: // loop statement | ||
| 438 | ret = emit_engine_emit_loop( emit, &stmt->stmt_loop ); | ||
| 439 | break; | ||
| 440 | |||
| 441 | case ae_stmt_switch: // switch statement | ||
| 442 | // not implemented | ||
| 443 | ret = FALSE; | ||
| 444 | break; | ||
| 445 | |||
| 446 | case ae_stmt_break: // break statement | ||
| 447 | ret = emit_engine_emit_break( emit, &stmt->stmt_break ); | ||
| 448 | break; | ||
| 449 | |||
| 450 | case ae_stmt_code: // code segment | ||
| 451 | ret = emit_engine_emit_code_segment( emit, &stmt->stmt_code ); | ||
| 452 | break; | ||
| 453 | |||
| 454 | case ae_stmt_continue: // continue statement | ||
| 455 | ret = emit_engine_emit_continue( emit, &stmt->stmt_continue ); | ||
| 456 | break; | ||
| 457 | |||
| 458 | case ae_stmt_return: // return statement | ||
| 459 | ret = emit_engine_emit_return( emit, &stmt->stmt_return ); | ||
| 460 | break; | ||
| 461 | |||
| 462 | case ae_stmt_case: // case statement | ||
| 463 | // not implemented | ||
| 464 | ret = FALSE; | ||
| 465 | // ret = emit_engine_emit_case( emit, &stmt->stmt_case ); | ||
| 466 | break; | ||
| 467 | |||
| 468 | case ae_stmt_gotolabel: // goto label statement | ||
| 469 | // not implemented | ||
| 470 | ret = FALSE; | ||
| 471 | // ret = emit_engine_emit_gotolabel( emit, &stmt->stmt_case ); | ||
| 472 | break; | ||
| 473 | |||
| 474 | default: // bad | ||
| 475 | EM_error2( stmt->linepos, | ||
| 476 | "(emit): internal error: unhandled statement type '%i'...", | ||
| 477 | stmt->s_type ); | ||
| 478 | break; | ||
| 479 | } | ||
| 480 | |||
| 481 | return ret; | ||
| 482 | } | ||
| 483 | |||
| 484 | |||
| 485 | |||
| 486 | |||
| 487 | //----------------------------------------------------------------------------- | ||
| 488 | // name: emit_engine_emit_if() | ||
| 489 | // desc: ... | ||
| 490 | //----------------------------------------------------------------------------- | ||
| 491 | t_CKBOOL emit_engine_emit_if( Chuck_Emitter * emit, a_Stmt_If stmt ) | ||
| 492 | { | ||
| 493 | t_CKBOOL ret = TRUE; | ||
| 494 | Chuck_Instr_Branch_Op * op = NULL, * op2 = NULL; | ||
| 495 | |||
| 496 | // push the stack, allowing for new local variables | ||
| 497 | emit->push_scope(); | ||
| 498 | |||
| 499 | // emit the condition | ||
| 500 | ret = emit_engine_emit_exp( emit, stmt->cond ); | ||
| 501 | if( !ret ) | ||
| 502 | return FALSE; | ||
| 503 | |||
| 504 | // type of the condition | ||
| 505 | switch( stmt->cond->type->xid ) | ||
| 506 | { | ||
| 507 | case te_int: | ||
| 508 | // push 0 | ||
| 509 | emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); | ||
| 510 | op = new Chuck_Instr_Branch_Eq_int( 0 ); | ||
| 511 | break; | ||
| 512 | case te_float: | ||
| 513 | case te_dur: | ||
| 514 | case te_time: | ||
| 515 | // push 0 | ||
| 516 | emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) ); | ||
| 517 | op = new Chuck_Instr_Branch_Eq_double( 0 ); | ||
| 518 | break; | ||
| 519 | |||
| 520 | default: | ||
| 521 | // check for IO | ||
| 522 | if( isa( stmt->cond->type, emit->env->t_io ) ) | ||
| 523 | { | ||
| 524 | // push 0 | ||
| 525 | emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); | ||
| 526 | op = new Chuck_Instr_Branch_Eq_int_IO_good( 0 ); | ||
| 527 | break; | ||
| 528 | } | ||
| 529 | |||
| 530 | EM_error2( stmt->cond->linepos, | ||
| 531 | "(emit): internal error: unhandled type '%s' in if condition", | ||
| 532 | stmt->cond->type->name.c_str() ); | ||
| 533 | return FALSE; | ||
| 534 | } | ||
| 535 | |||
| 536 | if( !ret ) return FALSE; | ||
| 537 | |||
| 538 | // append the op | ||
| 539 | emit->append( op ); | ||
| 540 | |||
| 541 | // ge: 2012 april: scope for if body (added 1.3.0.0) | ||
| 542 | { | ||
| 543 | // push the stack, allowing for new local variables | ||
| 544 | emit->push_scope(); | ||
| 545 | // emit the body | ||
| 546 | ret = emit_engine_emit_stmt( emit, stmt->if_body ); | ||
| 547 | if( !ret ) | ||
| 548 | return FALSE; | ||
| 549 | // pop stack | ||
| 550 | emit->pop_scope(); | ||
| 551 | } | ||
| 552 | |||
| 553 | // emit the skip to the end | ||
| 554 | emit->append( op2 = new Chuck_Instr_Goto(0) ); | ||
| 555 | |||
| 556 | // set the op's target | ||
| 557 | op->set( emit->next_index() ); | ||
| 558 | |||
| 559 | // ge: 2012 april: scope for else body (added 1.3.0.0) | ||
| 560 | { | ||
| 561 | // push the stack, allowing for new local variables | ||
| 562 | emit->push_scope(); | ||
| 563 | // emit the body | ||
| 564 | ret = emit_engine_emit_stmt( emit, stmt->else_body ); | ||
| 565 | if( !ret ) | ||
| 566 | return FALSE; | ||
| 567 | // pop stack | ||
| 568 | emit->pop_scope(); | ||
| 569 | } | ||
| 570 | |||
| 571 | // set the op2's target | ||
| 572 | op2->set( emit->next_index() ); | ||
| 573 | |||
| 574 | // pop stack | ||
| 575 | emit->pop_scope(); | ||
| 576 | |||
| 577 | return ret; | ||
| 578 | } | ||
| 579 | |||
| 580 | |||
| 581 | |||
| 582 | |||
| 583 | //----------------------------------------------------------------------------- | ||
| 584 | // name: emit_engine_emit_for() | ||
| 585 | // desc: ... | ||
| 586 | //----------------------------------------------------------------------------- | ||
| 587 | t_CKBOOL emit_engine_emit_for( Chuck_Emitter * emit, a_Stmt_For stmt ) | ||
| 588 | { | ||
| 589 | t_CKBOOL ret = TRUE; | ||
| 590 | Chuck_Instr_Branch_Op * op = NULL; | ||
| 591 | |||
| 592 | // push the stack | ||
| 593 | emit->push_scope(); | ||
| 594 | |||
| 595 | // emit the cond | ||
| 596 | ret = emit_engine_emit_stmt( emit, stmt->c1 ); | ||
| 597 | if( !ret ) | ||
| 598 | return FALSE; | ||
| 599 | |||
| 600 | // the start index | ||
| 601 | t_CKUINT start_index = emit->next_index(); | ||
| 602 | t_CKUINT cont_index = 0; | ||
| 603 | // mark the stack of continue | ||
| 604 | emit->code->stack_cont.push_back( NULL ); | ||
| 605 | // mark the stack of break | ||
| 606 | emit->code->stack_break.push_back( NULL ); | ||
| 607 | |||
| 608 | // emit the cond - keep the result on the stack | ||
| 609 | emit_engine_emit_stmt( emit, stmt->c2, FALSE ); | ||
| 610 | |||
| 611 | // could be NULL | ||
| 612 | if( stmt->c2 ) | ||
| 613 | { | ||
| 614 | switch( stmt->c2->stmt_exp->type->xid ) | ||
| 615 | { | ||
| 616 | case te_int: | ||
| 617 | // push 0 | ||
| 618 | emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); | ||
| 619 | op = new Chuck_Instr_Branch_Eq_int( 0 ); | ||
| 620 | break; | ||
| 621 | case te_float: | ||
| 622 | case te_dur: | ||
| 623 | case te_time: | ||
| 624 | // push 0 | ||
| 625 | emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) ); | ||
| 626 | op = new Chuck_Instr_Branch_Eq_double( 0 ); | ||
| 627 | break; | ||
| 628 | |||
| 629 | default: | ||
| 630 | // check for IO | ||
| 631 | if( isa( stmt->c2->stmt_exp->type, emit->env->t_io ) ) | ||
| 632 | { | ||
| 633 | // push 0 | ||
| 634 | emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); | ||
| 635 | op = new Chuck_Instr_Branch_Eq_int_IO_good( 0 ); | ||
| 636 | break; | ||
| 637 | } | ||
| 638 | |||
| 639 | EM_error2( stmt->c2->stmt_exp->linepos, | ||
| 640 | "(emit): internal error: unhandled type '%s' in for conditional", | ||
| 641 | stmt->c2->stmt_exp->type->name.c_str() ); | ||
| 642 | return FALSE; | ||
| 643 | } | ||
| 644 | // append the op | ||
| 645 | emit->append( op ); | ||
| 646 | } | ||
| 647 | |||
| 648 | // added 1.3.1.1: new scope just for loop body | ||
| 649 | emit->push_scope(); | ||
| 650 | |||
| 651 | // emit the body | ||
| 652 | ret = emit_engine_emit_stmt( emit, stmt->body ); | ||
| 653 | if( !ret ) | ||
| 654 | return FALSE; | ||
| 655 | |||
| 656 | // added 1.3.1.1: pop scope for loop body | ||
| 657 | emit->pop_scope(); | ||
| 658 | |||
| 659 | // continue here | ||
| 660 | cont_index = emit->next_index(); | ||
| 661 | |||
| 662 | // emit the action | ||
| 663 | if( stmt->c3 ) | ||
| 664 | { | ||
| 665 | ret = emit_engine_emit_exp( emit, stmt->c3 ); | ||
| 666 | if( !ret ) | ||
| 667 | return FALSE; | ||
| 668 | |||
| 669 | // HACK! | ||
| 670 | // count the number of words to pop | ||
| 671 | a_Exp e = stmt->c3; | ||
| 672 | t_CKUINT num_words = 0; | ||
| 673 | while( e ) | ||
| 674 | { | ||
| 675 | if( e->type->size == sz_FLOAT ) // ISSUE: 64-bit (fixed 1.3.1.0) | ||
| 676 | num_words += sz_FLOAT / sz_WORD; // changed to compute number of words; 1.3.1.0 | ||
| 677 | else if( e->type->size == sz_INT ) // ISSUE: 64-bit (fixed 1.3.1.0) | ||
| 678 | num_words += sz_INT / sz_WORD; // changed to compute number of words; 1.3.1.0 | ||
| 679 | else if( e->type->size == sz_COMPLEX ) // ISSUE: 64-bit (fixed 1.3.1.0) | ||
| 680 | num_words += sz_COMPLEX / sz_WORD; // changed to compute number of words; 1.3.1.0 | ||
| 681 | else if( e->type->size != 0 ) | ||
| 682 | { | ||
| 683 | EM_error2( e->linepos, | ||
| 684 | "(emit): internal error: non-void type size %i unhandled...", | ||
| 685 | e->type->size ); | ||
| 686 | return FALSE; | ||
| 687 | } | ||
| 688 | |||
| 689 | // advance | ||
| 690 | e = e->next; | ||
| 691 | } | ||
| 692 | |||
| 693 | // pop (changed to Chuck_Instr_Reg_Pop_Word4 in 1.3.1.0) | ||
| 694 | if( num_words > 0 ) emit->append( new Chuck_Instr_Reg_Pop_Word4( num_words ) ); | ||
| 695 | } | ||
| 696 | |||
| 697 | // go back to do check the condition | ||
| 698 | emit->append( new Chuck_Instr_Goto( start_index ) ); | ||
| 699 | |||
| 700 | // could be NULL | ||
| 701 | if( stmt->c2 ) | ||
| 702 | // set the op's target | ||
| 703 | op->set( emit->next_index() ); | ||
| 704 | |||
| 705 | // stack of continue | ||
| 706 | while( emit->code->stack_cont.size() && emit->code->stack_cont.back() ) | ||
| 707 | { | ||
| 708 | emit->code->stack_cont.back()->set( cont_index ); | ||
| 709 | emit->code->stack_cont.pop_back(); | ||
| 710 | } | ||
| 711 | |||
| 712 | // stack of break | ||
| 713 | while( emit->code->stack_break.size() && emit->code->stack_break.back() ) | ||
| 714 | { | ||
| 715 | emit->code->stack_break.back()->set( emit->next_index() ); | ||
| 716 | emit->code->stack_break.pop_back(); | ||
| 717 | } | ||
| 718 | |||
| 719 | // pop stack | ||
| 720 | emit->pop_scope(); | ||
| 721 | // pop continue stack | ||
| 722 | emit->code->stack_cont.pop_back(); | ||
| 723 | // pop break stack | ||
| 724 | emit->code->stack_break.pop_back(); | ||
| 725 | |||
| 726 | return ret; | ||
| 727 | } | ||
| 728 | |||
| 729 | |||
| 730 | |||
| 731 | |||
| 732 | //----------------------------------------------------------------------------- | ||
| 733 | // name: emit_engine_emit_while() | ||
| 734 | // desc: ... | ||
| 735 | //----------------------------------------------------------------------------- | ||
| 736 | t_CKBOOL emit_engine_emit_while( Chuck_Emitter * emit, a_Stmt_While stmt ) | ||
| 737 | { | ||
| 738 | t_CKBOOL ret = TRUE; | ||
| 739 | Chuck_Instr_Branch_Op * op = NULL; | ||
| 740 | |||
| 741 | // push stack | ||
| 742 | emit->push_scope(); | ||
| 743 | |||
| 744 | // get the index | ||
| 745 | t_CKUINT start_index = emit->next_index(); | ||
| 746 | // mark the stack of continue | ||
| 747 | emit->code->stack_cont.push_back( NULL ); | ||
| 748 | // mark the stack of break | ||
| 749 | emit->code->stack_break.push_back( NULL ); | ||
| 750 | |||
| 751 | // emit the cond | ||
| 752 | ret = emit_engine_emit_exp( emit, stmt->cond ); | ||
| 753 | if( !ret ) | ||
| 754 | return FALSE; | ||
| 755 | |||
| 756 | // the condition | ||
| 757 | switch( stmt->cond->type->xid ) | ||
| 758 | { | ||
| 759 | case te_int: | ||
| 760 | // push 0 | ||
| 761 | emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); | ||
| 762 | op = new Chuck_Instr_Branch_Eq_int( 0 ); | ||
| 763 | break; | ||
| 764 | case te_float: | ||
| 765 | case te_dur: | ||
| 766 | case te_time: | ||
| 767 | // push 0 | ||
| 768 | emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) ); | ||
| 769 | op = new Chuck_Instr_Branch_Eq_double( 0 ); | ||
| 770 | break; | ||
| 771 | |||
| 772 | default: | ||
| 773 | // check for IO | ||
| 774 | if( isa( stmt->cond->type, emit->env->t_io ) ) | ||
| 775 | { | ||
| 776 | // push 0 | ||
| 777 | emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); | ||
| 778 | op = new Chuck_Instr_Branch_Eq_int_IO_good( 0 ); | ||
| 779 | break; | ||
| 780 | } | ||
| 781 | |||
| 782 | EM_error2( stmt->cond->linepos, | ||
| 783 | "(emit): internal error: unhandled type '%s' in while conditional", | ||
| 784 | stmt->cond->type->name.c_str() ); | ||
| 785 | return FALSE; | ||
| 786 | } | ||
| 787 | |||
| 788 | // append the op | ||
| 789 | emit->append( op ); | ||
| 790 | |||
| 791 | // added 1.3.1.1: new scope just for loop body | ||
| 792 | emit->push_scope(); | ||
| 793 | |||
| 794 | // emit the body | ||
| 795 | ret = emit_engine_emit_stmt( emit, stmt->body ); | ||
| 796 | if( !ret ) | ||
| 797 | return FALSE; | ||
| 798 | |||
| 799 | // added 1.3.1.1: pop scope for loop body | ||
| 800 | emit->pop_scope(); | ||
| 801 | |||
| 802 | // go back to do check the condition | ||
| 803 | emit->append( new Chuck_Instr_Goto( start_index ) ); | ||
| 804 | |||
| 805 | // set the op's target | ||
| 806 | op->set( emit->next_index() ); | ||
| 807 | |||
| 808 | // stack of continue | ||
| 809 | while( emit->code->stack_cont.size() && emit->code->stack_cont.back() ) | ||
| 810 | { | ||
| 811 | emit->code->stack_cont.back()->set( start_index ); | ||
| 812 | emit->code->stack_cont.pop_back(); | ||
| 813 | } | ||
| 814 | |||
| 815 | // stack of break | ||
| 816 | while( emit->code->stack_break.size() && emit->code->stack_break.back() ) | ||
| 817 | { | ||
| 818 | emit->code->stack_break.back()->set( emit->next_index() ); | ||
| 819 | emit->code->stack_break.pop_back(); | ||
| 820 | } | ||
| 821 | |||
| 822 | // pop stack | ||
| 823 | emit->pop_scope(); | ||
| 824 | // pop continue stack | ||
| 825 | emit->code->stack_cont.pop_back(); | ||
| 826 | // pop break stack | ||
| 827 | emit->code->stack_break.pop_back(); | ||
| 828 | |||
| 829 | return ret; | ||
| 830 | } | ||
| 831 | |||
| 832 | |||
| 833 | |||
| 834 | |||
| 835 | //----------------------------------------------------------------------------- | ||
| 836 | // name: emit_engine_emit_do_while() | ||
| 837 | // desc: ... | ||
| 838 | //----------------------------------------------------------------------------- | ||
| 839 | t_CKBOOL emit_engine_emit_do_while( Chuck_Emitter * emit, a_Stmt_While stmt ) | ||
| 840 | { | ||
| 841 | t_CKBOOL ret = TRUE; | ||
| 842 | Chuck_Instr_Branch_Op * op = NULL; | ||
| 843 | t_CKUINT start_index = emit->next_index(); | ||
| 844 | |||
| 845 | // push stack | ||
| 846 | emit->push_scope(); | ||
| 847 | |||
| 848 | // mark the stack of continue | ||
| 849 | emit->code->stack_cont.push_back( NULL ); | ||
| 850 | // mark the stack of break | ||
| 851 | emit->code->stack_break.push_back( NULL ); | ||
| 852 | |||
| 853 | // added 1.3.1.1: new scope just for loop body | ||
| 854 | emit->push_scope(); | ||
| 855 | |||
| 856 | // emit the body | ||
| 857 | ret = emit_engine_emit_stmt( emit, stmt->body ); | ||
| 858 | if( !ret ) | ||
| 859 | return FALSE; | ||
| 860 | |||
| 861 | // added 1.3.1.1: pop scope for loop body | ||
| 862 | emit->pop_scope(); | ||
| 863 | |||
| 864 | // emit the cond | ||
| 865 | ret = emit_engine_emit_exp( emit, stmt->cond ); | ||
| 866 | if( !ret ) | ||
| 867 | return FALSE; | ||
| 868 | |||
| 869 | // the condition | ||
| 870 | switch( stmt->cond->type->xid ) | ||
| 871 | { | ||
| 872 | case te_int: | ||
| 873 | // push 0 | ||
| 874 | emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); | ||
| 875 | op = new Chuck_Instr_Branch_Neq_int( 0 ); | ||
| 876 | break; | ||
| 877 | case te_float: | ||
| 878 | case te_dur: | ||
| 879 | case te_time: | ||
| 880 | // push 0 | ||
| 881 | emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) ); | ||
| 882 | op = new Chuck_Instr_Branch_Neq_double( 0 ); | ||
| 883 | break; | ||
| 884 | |||
| 885 | default: | ||
| 886 | // check for IO | ||
| 887 | if( isa( stmt->cond->type, emit->env->t_io ) ) | ||
| 888 | { | ||
| 889 | // push 0 | ||
| 890 | emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); | ||
| 891 | op = new Chuck_Instr_Branch_Eq_int_IO_good( 0 ); | ||
| 892 | break; | ||
| 893 | } | ||
| 894 | |||
| 895 | EM_error2( stmt->cond->linepos, | ||
| 896 | "(emit): internal error: unhandled type '%s' in do/while conditional", | ||
| 897 | stmt->cond->type->c_name() ); | ||
| 898 | return FALSE; | ||
| 899 | } | ||
| 900 | |||
| 901 | // append the op | ||
| 902 | emit->append( op ); | ||
| 903 | |||
| 904 | // set the op's target | ||
| 905 | op->set( start_index ); | ||
| 906 | |||
| 907 | // stack of continue | ||
| 908 | while( emit->code->stack_cont.size() && emit->code->stack_cont.back() ) | ||
| 909 | { | ||
| 910 | emit->code->stack_cont.back()->set( start_index ); | ||
| 911 | emit->code->stack_cont.pop_back(); | ||
| 912 | } | ||
| 913 | |||
| 914 | // stack of break | ||
| 915 | while( emit->code->stack_break.size() && emit->code->stack_break.back() ) | ||
| 916 | { | ||
| 917 | emit->code->stack_break.back()->set( emit->next_index() ); | ||
| 918 | emit->code->stack_break.pop_back(); | ||
| 919 | } | ||
| 920 | |||
| 921 | // pop stack | ||
| 922 | emit->pop_scope(); | ||
| 923 | // pop continue stack | ||
| 924 | emit->code->stack_cont.pop_back(); | ||
| 925 | // pop break stack | ||
| 926 | emit->code->stack_break.pop_back(); | ||
| 927 | |||
| 928 | return ret; | ||
| 929 | } | ||
| 930 | |||
| 931 | |||
| 932 | |||
| 933 | |||
| 934 | //----------------------------------------------------------------------------- | ||
| 935 | // name: emit_engine_emit_until() | ||
| 936 | // desc: ... | ||
| 937 | //----------------------------------------------------------------------------- | ||
| 938 | t_CKBOOL emit_engine_emit_until( Chuck_Emitter * emit, a_Stmt_Until stmt ) | ||
| 939 | { | ||
| 940 | t_CKBOOL ret = TRUE; | ||
| 941 | Chuck_Instr_Branch_Op * op = NULL; | ||
| 942 | |||
| 943 | // push stack | ||
| 944 | emit->push_scope(); | ||
| 945 | |||
| 946 | // get index | ||
| 947 | t_CKUINT start_index = emit->next_index(); | ||
| 948 | // mark the stack of continue | ||
| 949 | emit->code->stack_cont.push_back( NULL ); | ||
| 950 | // mark the stack of break | ||
| 951 | emit->code->stack_break.push_back( NULL ); | ||
| 952 | |||
| 953 | // emit the cond | ||
| 954 | ret = emit_engine_emit_exp( emit, stmt->cond ); | ||
| 955 | if( !ret ) | ||
| 956 | return FALSE; | ||
| 957 | |||
| 958 | // condition | ||
| 959 | switch( stmt->cond->type->xid ) | ||
| 960 | { | ||
| 961 | case te_int: | ||
| 962 | // push 0 | ||
| 963 | emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); | ||
| 964 | op = new Chuck_Instr_Branch_Neq_int( 0 ); | ||
| 965 | break; | ||
| 966 | case te_float: | ||
| 967 | case te_dur: | ||
| 968 | case te_time: | ||
| 969 | // push 0 | ||
| 970 | emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) ); | ||
| 971 | op = new Chuck_Instr_Branch_Neq_double( 0 ); | ||
| 972 | break; | ||
| 973 | |||
| 974 | default: | ||
| 975 | // check for IO | ||
| 976 | if( isa( stmt->cond->type, emit->env->t_io ) ) | ||
| 977 | { | ||
| 978 | // push 0 | ||
| 979 | emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); | ||
| 980 | op = new Chuck_Instr_Branch_Neq_int_IO_good( 0 ); | ||
| 981 | break; | ||
| 982 | } | ||
| 983 | |||
| 984 | EM_error2( stmt->cond->linepos, | ||
| 985 | "(emit): internal error: unhandled type '%s' in until conditional", | ||
| 986 | stmt->cond->type->name.c_str() ); | ||
| 987 | return FALSE; | ||
| 988 | } | ||
| 989 | |||
| 990 | // append the op | ||
| 991 | emit->append( op ); | ||
| 992 | |||
| 993 | // added 1.3.1.1: new scope just for loop body | ||
| 994 | emit->push_scope(); | ||
| 995 | |||
| 996 | // emit the body | ||
| 997 | emit_engine_emit_stmt( emit, stmt->body ); | ||
| 998 | |||
| 999 | // added 1.3.1.1: pop scope for loop body | ||
| 1000 | emit->pop_scope(); | ||
| 1001 | |||
| 1002 | // go back to do check the condition | ||
| 1003 | emit->append( new Chuck_Instr_Goto( start_index ) ); | ||
| 1004 | |||
| 1005 | // set the op's target | ||
| 1006 | op->set( emit->next_index() ); | ||
| 1007 | |||
| 1008 | // stack of continue | ||
| 1009 | while( emit->code->stack_cont.size() && emit->code->stack_cont.back() ) | ||
| 1010 | { | ||
| 1011 | emit->code->stack_cont.back()->set( start_index ); | ||
| 1012 | emit->code->stack_cont.pop_back(); | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | // stack of break | ||
| 1016 | while( emit->code->stack_break.size() && emit->code->stack_break.back() ) | ||
| 1017 | { | ||
| 1018 | emit->code->stack_break.back()->set( emit->next_index() ); | ||
| 1019 | emit->code->stack_break.pop_back(); | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | // pop stack | ||
| 1023 | emit->pop_scope(); | ||
| 1024 | // pop continue stack | ||
| 1025 | emit->code->stack_cont.pop_back(); | ||
| 1026 | // pop break stack | ||
| 1027 | emit->code->stack_break.pop_back(); | ||
| 1028 | |||
| 1029 | return ret; | ||
| 1030 | } | ||
| 1031 | |||
| 1032 | |||
| 1033 | |||
| 1034 | |||
| 1035 | //----------------------------------------------------------------------------- | ||
| 1036 | // name: emit_engine_emit_do_until() | ||
| 1037 | // desc: ... | ||
| 1038 | //----------------------------------------------------------------------------- | ||
| 1039 | t_CKBOOL emit_engine_emit_do_until( Chuck_Emitter * emit, a_Stmt_Until stmt ) | ||
| 1040 | { | ||
| 1041 | t_CKBOOL ret = TRUE; | ||
| 1042 | Chuck_Instr_Branch_Op * op = NULL; | ||
| 1043 | |||
| 1044 | // push stack | ||
| 1045 | emit->push_scope(); | ||
| 1046 | |||
| 1047 | // the index | ||
| 1048 | t_CKUINT start_index = emit->next_index(); | ||
| 1049 | // mark the stack of continue | ||
| 1050 | emit->code->stack_cont.push_back( NULL ); | ||
| 1051 | // mark the stack of break | ||
| 1052 | emit->code->stack_break.push_back( NULL ); | ||
| 1053 | |||
| 1054 | // added 1.3.1.1: new scope just for loop body | ||
| 1055 | emit->push_scope(); | ||
| 1056 | |||
| 1057 | // emit the body | ||
| 1058 | ret = emit_engine_emit_stmt( emit, stmt->body ); | ||
| 1059 | if( !ret ) | ||
| 1060 | return FALSE; | ||
| 1061 | |||
| 1062 | // added 1.3.1.1: pop scope for loop body | ||
| 1063 | emit->pop_scope(); | ||
| 1064 | |||
| 1065 | // emit the cond | ||
| 1066 | ret = emit_engine_emit_exp( emit, stmt->cond ); | ||
| 1067 | if( !ret ) | ||
| 1068 | return FALSE; | ||
| 1069 | |||
| 1070 | // condition | ||
| 1071 | switch( stmt->cond->type->xid ) | ||
| 1072 | { | ||
| 1073 | case te_int: | ||
| 1074 | // push 0 | ||
| 1075 | emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); | ||
| 1076 | op = new Chuck_Instr_Branch_Eq_int( 0 ); | ||
| 1077 | break; | ||
| 1078 | case te_float: | ||
| 1079 | case te_dur: | ||
| 1080 | case te_time: | ||
| 1081 | // push 0 | ||
| 1082 | emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) ); | ||
| 1083 | op = new Chuck_Instr_Branch_Eq_double( 0 ); | ||
| 1084 | break; | ||
| 1085 | |||
| 1086 | default: | ||
| 1087 | EM_error2( stmt->cond->linepos, | ||
| 1088 | "(emit): internal error: unhandled type '%s' in do/until conditional", | ||
| 1089 | stmt->cond->type->name.c_str() ); | ||
| 1090 | return FALSE; | ||
| 1091 | } | ||
| 1092 | |||
| 1093 | // append the op | ||
| 1094 | emit->append( op ); | ||
| 1095 | |||
| 1096 | // set the op's target | ||
| 1097 | op->set( start_index ); | ||
| 1098 | |||
| 1099 | // stack of continue | ||
| 1100 | while( emit->code->stack_cont.size() && emit->code->stack_cont.back() ) | ||
| 1101 | { | ||
| 1102 | emit->code->stack_cont.back()->set( start_index ); | ||
| 1103 | emit->code->stack_cont.pop_back(); | ||
| 1104 | } | ||
| 1105 | |||
| 1106 | // stack of break | ||
| 1107 | while( emit->code->stack_break.size() && emit->code->stack_break.back() ) | ||
| 1108 | { | ||
| 1109 | emit->code->stack_break.back()->set( emit->next_index() ); | ||
| 1110 | emit->code->stack_break.pop_back(); | ||
| 1111 | } | ||
| 1112 | |||
| 1113 | // pop stack | ||
| 1114 | emit->pop_scope(); | ||
| 1115 | // pop continue stack | ||
| 1116 | emit->code->stack_cont.pop_back(); | ||
| 1117 | // pop break stack | ||
| 1118 | emit->code->stack_break.pop_back(); | ||
| 1119 | |||
| 1120 | return ret; | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | |||
| 1124 | |||
| 1125 | |||
| 1126 | //----------------------------------------------------------------------------- | ||
| 1127 | // name: emit_engine_emit_loop() | ||
| 1128 | // desc: ... | ||
| 1129 | //----------------------------------------------------------------------------- | ||
| 1130 | t_CKBOOL emit_engine_emit_loop( Chuck_Emitter * emit, a_Stmt_Loop stmt ) | ||
| 1131 | { | ||
| 1132 | t_CKBOOL ret = TRUE; | ||
| 1133 | Chuck_Instr_Branch_Op * op = NULL; | ||
| 1134 | |||
| 1135 | Chuck_Instr * instr = NULL; | ||
| 1136 | |||
| 1137 | // push stack | ||
| 1138 | emit->push_scope(); | ||
| 1139 | |||
| 1140 | // emit the cond | ||
| 1141 | ret = emit_engine_emit_exp( emit, stmt->cond ); | ||
| 1142 | if( !ret ) | ||
| 1143 | return FALSE; | ||
| 1144 | |||
| 1145 | // initialize our loop counter (1.3.5.3) | ||
| 1146 | emit->append( new Chuck_Instr_Init_Loop_Counter() ); | ||
| 1147 | |||
| 1148 | // get the index | ||
| 1149 | t_CKUINT start_index = emit->next_index(); | ||
| 1150 | // mark the stack of continue | ||
| 1151 | emit->code->stack_cont.push_back( NULL ); | ||
| 1152 | // mark the stack of break | ||
| 1153 | emit->code->stack_break.push_back( NULL ); | ||
| 1154 | |||
| 1155 | // push the value of the loop counter | ||
| 1156 | emit->append( instr = new Chuck_Instr_Reg_Push_Loop_Counter_Deref() ); | ||
| 1157 | instr->set_linepos( stmt->linepos ); | ||
| 1158 | |||
| 1159 | // get the type, taking cast into account | ||
| 1160 | Chuck_Type * type = stmt->cond->cast_to ? stmt->cond->cast_to : stmt->cond->type; | ||
| 1161 | |||
| 1162 | // the condition | ||
| 1163 | switch( type->xid ) | ||
| 1164 | { | ||
| 1165 | case te_int: | ||
| 1166 | // push 0 | ||
| 1167 | emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); | ||
| 1168 | op = new Chuck_Instr_Branch_Eq_int( 0 ); | ||
| 1169 | break; | ||
| 1170 | |||
| 1171 | default: | ||
| 1172 | EM_error2( stmt->cond->linepos, | ||
| 1173 | "(emit): internal error: unhandled type '%s' in while conditional", | ||
| 1174 | type->name.c_str() ); | ||
| 1175 | |||
| 1176 | return FALSE; | ||
| 1177 | } | ||
| 1178 | |||
| 1179 | // append the op | ||
| 1180 | emit->append( op ); | ||
| 1181 | |||
| 1182 | // decrement the counter | ||
| 1183 | emit->append( instr = new Chuck_Instr_Dec_Loop_Counter() ); | ||
| 1184 | instr->set_linepos( stmt->linepos ); | ||
| 1185 | |||
| 1186 | // added 1.3.1.1: new scope just for loop body | ||
| 1187 | emit->push_scope(); | ||
| 1188 | |||
| 1189 | // emit the body | ||
| 1190 | ret = emit_engine_emit_stmt( emit, stmt->body ); | ||
| 1191 | if( !ret ) | ||
| 1192 | return FALSE; | ||
| 1193 | |||
| 1194 | // added 1.3.1.1: pop scope for loop body | ||
| 1195 | emit->pop_scope(); | ||
| 1196 | |||
| 1197 | // go back to do check the condition | ||
| 1198 | emit->append( new Chuck_Instr_Goto( start_index ) ); | ||
| 1199 | |||
| 1200 | // set the op's target | ||
| 1201 | op->set( emit->next_index() ); | ||
| 1202 | |||
| 1203 | // pop the loop counter | ||
| 1204 | emit->append( new Chuck_Instr_Pop_Loop_Counter ); | ||
| 1205 | |||
| 1206 | // stack of continue | ||
| 1207 | while( emit->code->stack_cont.size() && emit->code->stack_cont.back() ) | ||
| 1208 | { | ||
| 1209 | emit->code->stack_cont.back()->set( start_index ); | ||
| 1210 | emit->code->stack_cont.pop_back(); | ||
| 1211 | } | ||
| 1212 | |||
| 1213 | // stack of break | ||
| 1214 | while( emit->code->stack_break.size() && emit->code->stack_break.back() ) | ||
| 1215 | { | ||
| 1216 | emit->code->stack_break.back()->set( emit->next_index() ); | ||
| 1217 | emit->code->stack_break.pop_back(); | ||
| 1218 | } | ||
| 1219 | |||
| 1220 | // pop stack | ||
| 1221 | emit->pop_scope(); | ||
| 1222 | // pop continue stack | ||
| 1223 | emit->code->stack_cont.pop_back(); | ||
| 1224 | // pop break stack | ||
| 1225 | emit->code->stack_break.pop_back(); | ||
| 1226 | |||
| 1227 | return ret; | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | |||
| 1231 | |||
| 1232 | |||
| 1233 | //----------------------------------------------------------------------------- | ||
| 1234 | // name: emit_engine_emit_break() | ||
| 1235 | // desc: ... | ||
| 1236 | //----------------------------------------------------------------------------- | ||
| 1237 | t_CKBOOL emit_engine_emit_break( Chuck_Emitter * emit, a_Stmt_Break br ) | ||
| 1238 | { | ||
| 1239 | // append | ||
| 1240 | Chuck_Instr_Goto * op = new Chuck_Instr_Goto( 0 ); | ||
| 1241 | emit->append( op ); | ||
| 1242 | // remember | ||
| 1243 | emit->code->stack_break.push_back( op ); | ||
| 1244 | |||
| 1245 | return TRUE; | ||
| 1246 | } | ||
| 1247 | |||
| 1248 | |||
| 1249 | |||
| 1250 | |||
| 1251 | //----------------------------------------------------------------------------- | ||
| 1252 | // name: emit_engine_emit_continue() | ||
| 1253 | // desc: ... | ||
| 1254 | //----------------------------------------------------------------------------- | ||
| 1255 | t_CKBOOL emit_engine_emit_continue( Chuck_Emitter * emit, a_Stmt_Continue cont ) | ||
| 1256 | { | ||
| 1257 | // append | ||
| 1258 | Chuck_Instr_Goto * op = new Chuck_Instr_Goto( 0 ); | ||
| 1259 | emit->append( op ); | ||
| 1260 | // remember | ||
| 1261 | emit->code->stack_cont.push_back( op ); | ||
| 1262 | |||
| 1263 | return TRUE; | ||
| 1264 | } | ||
| 1265 | |||
| 1266 | |||
| 1267 | |||
| 1268 | |||
| 1269 | //----------------------------------------------------------------------------- | ||
| 1270 | // name: emit_engine_emit_return() | ||
| 1271 | // desc: ... | ||
| 1272 | //----------------------------------------------------------------------------- | ||
| 1273 | t_CKBOOL emit_engine_emit_return( Chuck_Emitter * emit, a_Stmt_Return stmt ) | ||
| 1274 | { | ||
| 1275 | if( !emit_engine_emit_exp( emit, stmt->val ) ) | ||
| 1276 | return FALSE; | ||
| 1277 | |||
| 1278 | // emit return | ||
| 1279 | // emit->append( new Chuck_Instr_Func_Return ); | ||
| 1280 | |||
| 1281 | // determine where later | ||
| 1282 | Chuck_Instr_Goto * instr = new Chuck_Instr_Goto( 0 ); | ||
| 1283 | emit->append( instr ); | ||
| 1284 | emit->code->stack_return.push_back( instr ); | ||
| 1285 | |||
| 1286 | return TRUE; | ||
| 1287 | } | ||
| 1288 | |||
| 1289 | |||
| 1290 | |||
| 1291 | |||
| 1292 | //----------------------------------------------------------------------------- | ||
| 1293 | // name: | ||
| 1294 | // desc: ... | ||
| 1295 | //----------------------------------------------------------------------------- | ||
| 1296 | t_CKBOOL emit_engine_emit_switch( Chuck_Emitter * emit, a_Stmt_Switch stmt ); | ||
| 1297 | |||
| 1298 | |||
| 1299 | |||
| 1300 | |||
| 1301 | //----------------------------------------------------------------------------- | ||
| 1302 | // name: emit_engine_emit_exp() | ||
| 1303 | // desc: (doAddRef added 1.3.0.0 -- typically this is set to TRUE for function | ||
| 1304 | // calls so that pointers on the reg is accounted for; this is important | ||
| 1305 | // in case the object is released/reclaimed before the value is used; | ||
| 1306 | // on particular case is when sporking with a local object as argument) | ||
| 1307 | //----------------------------------------------------------------------------- | ||
| 1308 | t_CKBOOL emit_engine_emit_exp( Chuck_Emitter * emit, a_Exp exp, t_CKBOOL doAddRef ) | ||
| 1309 | { | ||
| 1310 | // for now... | ||
| 1311 | // assert( exp->next == NULL ); | ||
| 1312 | |||
| 1313 | // loop over | ||
| 1314 | while( exp ) | ||
| 1315 | { | ||
| 1316 | switch( exp->s_type ) | ||
| 1317 | { | ||
| 1318 | case ae_exp_binary: | ||
| 1319 | if( !emit_engine_emit_exp_binary( emit, &exp->binary ) ) | ||
| 1320 | return FALSE; | ||
| 1321 | break; | ||
| 1322 | |||
| 1323 | case ae_exp_unary: | ||
| 1324 | if( !emit_engine_emit_exp_unary( emit, &exp->unary ) ) | ||
| 1325 | return FALSE; | ||
| 1326 | break; | ||
| 1327 | |||
| 1328 | case ae_exp_cast: | ||
| 1329 | if( !emit_engine_emit_exp_cast( emit, &exp->cast ) ) | ||
| 1330 | return FALSE; | ||
| 1331 | break; | ||
| 1332 | |||
| 1333 | case ae_exp_postfix: | ||
| 1334 | if( !emit_engine_emit_exp_postfix( emit, &exp->postfix ) ) | ||
| 1335 | return FALSE; | ||
| 1336 | break; | ||
| 1337 | |||
| 1338 | case ae_exp_dur: | ||
| 1339 | if( !emit_engine_emit_exp_dur( emit, &exp->dur ) ) | ||
| 1340 | return FALSE; | ||
| 1341 | break; | ||
| 1342 | |||
| 1343 | case ae_exp_primary: | ||
| 1344 | if( !emit_engine_emit_exp_primary( emit, &exp->primary ) ) | ||
| 1345 | return FALSE; | ||
| 1346 | break; | ||
| 1347 | |||
| 1348 | case ae_exp_array: | ||
| 1349 | if( !emit_engine_emit_exp_array( emit, &exp->array ) ) | ||
| 1350 | return FALSE; | ||
| 1351 | break; | ||
| 1352 | |||
| 1353 | case ae_exp_func_call: | ||
| 1354 | if( !emit_engine_emit_exp_func_call( emit, &exp->func_call ) ) | ||
| 1355 | return FALSE; | ||
| 1356 | break; | ||
| 1357 | |||
| 1358 | case ae_exp_dot_member: | ||
| 1359 | if( !emit_engine_emit_exp_dot_member( emit, &exp->dot_member ) ) | ||
| 1360 | return FALSE; | ||
| 1361 | break; | ||
| 1362 | |||
| 1363 | case ae_exp_if: | ||
| 1364 | if( !emit_engine_emit_exp_if( emit, &exp->exp_if ) ) | ||
| 1365 | return FALSE; | ||
| 1366 | break; | ||
| 1367 | |||
| 1368 | case ae_exp_decl: | ||
| 1369 | if( !emit_engine_emit_exp_decl( emit, &exp->decl, FALSE ) ) | ||
| 1370 | return FALSE; | ||
| 1371 | break; | ||
| 1372 | |||
| 1373 | //case ae_exp_namespace: | ||
| 1374 | // if( !emit_engine_emit_exp_namespace( emit, &exp->name_space ) ) | ||
| 1375 | // return FALSE; | ||
| 1376 | // break; | ||
| 1377 | |||
| 1378 | default: | ||
| 1379 | EM_error2( exp->linepos, | ||
| 1380 | "(emit): internal error: unhandled expression type '%i'...", | ||
| 1381 | exp->s_type ); | ||
| 1382 | return FALSE; | ||
| 1383 | } | ||
| 1384 | |||
| 1385 | // implicit cast | ||
| 1386 | if( exp->cast_to != NULL ) | ||
| 1387 | if( !emit_engine_emit_cast( emit, exp->cast_to, exp->type ) ) | ||
| 1388 | return FALSE; | ||
| 1389 | |||
| 1390 | // check if we need to handle ref (added 1.3.0.0) | ||
| 1391 | // (NOTE: cast shouldn't matter since pointer width should remain constant) | ||
| 1392 | if( doAddRef && isobj( emit->env, exp->type ) ) | ||
| 1393 | { | ||
| 1394 | // add ref in place on the stack | ||
| 1395 | emit->append( new Chuck_Instr_Reg_AddRef_Object3() ); | ||
| 1396 | } | ||
| 1397 | |||
| 1398 | exp = exp->next; | ||
| 1399 | } | ||
| 1400 | |||
| 1401 | return TRUE; | ||
| 1402 | } | ||
| 1403 | |||
| 1404 | |||
| 1405 | |||
| 1406 | |||
| 1407 | //----------------------------------------------------------------------------- | ||
| 1408 | // name: emit_engine_emit_exp_binary() | ||
| 1409 | // desc: ... | ||
| 1410 | //----------------------------------------------------------------------------- | ||
| 1411 | t_CKBOOL emit_engine_emit_exp_binary( Chuck_Emitter * emit, a_Exp_Binary binary ) | ||
| 1412 | { | ||
| 1413 | // sanity | ||
| 1414 | assert( binary->self->emit_var == FALSE ); | ||
| 1415 | |||
| 1416 | t_CKBOOL left = FALSE; | ||
| 1417 | t_CKBOOL right = FALSE; | ||
| 1418 | |||
| 1419 | // hack to allow && to terminate as soon as possible - spencer | ||
| 1420 | // i.e. in ( 0 && f() ) the function f() will not be called | ||
| 1421 | // (obviates need for boolean AND instruction) | ||
| 1422 | if( binary->op == ae_op_and ) | ||
| 1423 | { | ||
| 1424 | Chuck_Instr_Branch_Op * op; | ||
| 1425 | |||
| 1426 | // push default result | ||
| 1427 | emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); | ||
| 1428 | |||
| 1429 | left = emit_engine_emit_exp( emit, binary->lhs ); | ||
| 1430 | if( !left ) | ||
| 1431 | return FALSE; | ||
| 1432 | |||
| 1433 | // compare to 0; use default result if zero | ||
| 1434 | emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); | ||
| 1435 | emit->append( op = new Chuck_Instr_Branch_Eq_int( 0 ) ); | ||
| 1436 | |||
| 1437 | // pop default result | ||
| 1438 | emit->append( new Chuck_Instr_Reg_Pop_Word ); | ||
| 1439 | |||
| 1440 | // result of whole expression is now result of rhs | ||
| 1441 | right = emit_engine_emit_exp( emit, binary->rhs ); | ||
| 1442 | if( !right ) | ||
| 1443 | return FALSE; | ||
| 1444 | |||
| 1445 | // set branch location | ||
| 1446 | op->set( emit->next_index() ); | ||
| 1447 | |||
| 1448 | return TRUE; | ||
| 1449 | } | ||
| 1450 | |||
| 1451 | // hack to allow || to terminate as soon as possible - spencer | ||
| 1452 | // i.e. in ( 1 || f() ) the function f() will not be called | ||
| 1453 | // (obviates need for boolean OR instruction) | ||
| 1454 | else if( binary->op == ae_op_or ) | ||
| 1455 | { | ||
| 1456 | Chuck_Instr_Branch_Op * op; | ||
| 1457 | |||
| 1458 | // push default result | ||
| 1459 | emit->append( new Chuck_Instr_Reg_Push_Imm( 1 ) ); | ||
| 1460 | |||
| 1461 | left = emit_engine_emit_exp( emit, binary->lhs ); | ||
| 1462 | if( !left ) | ||
| 1463 | return FALSE; | ||
| 1464 | |||
| 1465 | // compare to 0; use default result if non-zero | ||
| 1466 | emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); | ||
| 1467 | emit->append( op = new Chuck_Instr_Branch_Neq_int( 0 ) ); | ||
| 1468 | |||
| 1469 | // pop default result | ||
| 1470 | emit->append( new Chuck_Instr_Reg_Pop_Word ); | ||
| 1471 | |||
| 1472 | // result of whole expression is now result of rhs | ||
| 1473 | right = emit_engine_emit_exp( emit, binary->rhs ); | ||
| 1474 | if( !right ) | ||
| 1475 | return FALSE; | ||
| 1476 | |||
| 1477 | // set branch location | ||
| 1478 | op->set( emit->next_index() ); | ||
| 1479 | |||
| 1480 | return TRUE; | ||
| 1481 | } | ||
| 1482 | |||
| 1483 | // whether to track object references on stack (added 1.3.0.2) | ||
| 1484 | t_CKBOOL doRef = FALSE; | ||
| 1485 | // check to see if this is a function call (added 1.3.0.2) | ||
| 1486 | if( isa( binary->rhs->type, emit->env->t_function ) ) | ||
| 1487 | { | ||
| 1488 | // take care of objects in terms of reference counting | ||
| 1489 | doRef = TRUE; | ||
| 1490 | } | ||
| 1491 | |||
| 1492 | // emit (doRef added 1.3.0.2) | ||
| 1493 | left = emit_engine_emit_exp( emit, binary->lhs, doRef ); | ||
| 1494 | right = emit_engine_emit_exp( emit, binary->rhs ); | ||
| 1495 | |||
| 1496 | // check | ||
| 1497 | if( !left || !right ) | ||
| 1498 | return FALSE; | ||
| 1499 | |||
| 1500 | // emit the op | ||
| 1501 | if( !emit_engine_emit_op( emit, binary->op, binary->lhs, binary->rhs, binary ) ) | ||
| 1502 | return FALSE; | ||
| 1503 | |||
| 1504 | return TRUE; | ||
| 1505 | } | ||
| 1506 | |||
| 1507 | |||
| 1508 | |||
| 1509 | |||
| 1510 | //----------------------------------------------------------------------------- | ||
| 1511 | // name: emit_engine_emit_op() | ||
| 1512 | // desc: emit binary operator | ||
| 1513 | //----------------------------------------------------------------------------- | ||
| 1514 | t_CKBOOL emit_engine_emit_op( Chuck_Emitter * emit, ae_Operator op, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ) | ||
| 1515 | { | ||
| 1516 | // any implicit cast happens before this | ||
| 1517 | Chuck_Type * t_left = lhs->cast_to ? lhs->cast_to : lhs->type; | ||
| 1518 | Chuck_Type * t_right = rhs->cast_to ? rhs->cast_to : rhs->type; | ||
| 1519 | // get the types of the left and right | ||
| 1520 | te_Type left = t_left->xid; | ||
| 1521 | te_Type right = t_right->xid; | ||
| 1522 | // op | ||
| 1523 | Chuck_Instr * instr = NULL; | ||
| 1524 | |||
| 1525 | // emit op | ||
| 1526 | switch( op ) | ||
| 1527 | { | ||
| 1528 | // ----------------------------- num -------------------------------------- | ||
| 1529 | case ae_op_plus: | ||
| 1530 | // time + dur | ||
| 1531 | if( ( left == te_dur && right == te_time ) || | ||
| 1532 | ( left == te_time && right == te_dur ) ) | ||
| 1533 | { | ||
| 1534 | emit->append( instr = new Chuck_Instr_Add_double ); | ||
| 1535 | } | ||
| 1536 | // string + string | ||
| 1537 | else if( isa( t_left, emit->env->t_string ) && isa( t_right, emit->env->t_string ) ) | ||
| 1538 | { | ||
| 1539 | // concatenate | ||
| 1540 | emit->append( instr = new Chuck_Instr_Add_string ); | ||
| 1541 | instr->set_linepos( lhs->linepos ); | ||
| 1542 | } | ||
| 1543 | // left: string | ||
| 1544 | else if( isa( t_left, emit->env->t_string ) ) | ||
| 1545 | { | ||
| 1546 | // + int | ||
| 1547 | if( isa( t_right, emit->env->t_int ) ) | ||
| 1548 | { | ||
| 1549 | emit->append( instr = new Chuck_Instr_Add_string_int ); | ||
| 1550 | instr->set_linepos( lhs->linepos ); | ||
| 1551 | } | ||
| 1552 | else if( isa( t_right, emit->env->t_float ) ) | ||
| 1553 | { | ||
| 1554 | emit->append( instr = new Chuck_Instr_Add_string_float ); | ||
| 1555 | instr->set_linepos( lhs->linepos ); | ||
| 1556 | } | ||
| 1557 | else | ||
| 1558 | { | ||
| 1559 | EM_error2( lhs->linepos, | ||
| 1560 | "(emit): internal error: unhandled op '%s' %s '%s'", | ||
| 1561 | t_left->c_name(), op2str( op ), t_right->c_name() ); | ||
| 1562 | return FALSE; | ||
| 1563 | } | ||
| 1564 | } | ||
| 1565 | // right: string | ||
| 1566 | else if( isa( t_right, emit->env->t_string ) ) | ||
| 1567 | { | ||
| 1568 | // + int | ||
| 1569 | if( isa( t_left, emit->env->t_int ) ) | ||
| 1570 | { | ||
| 1571 | emit->append( instr = new Chuck_Instr_Add_int_string ); | ||
| 1572 | instr->set_linepos( rhs->linepos ); | ||
| 1573 | } | ||
| 1574 | else if( isa( t_left, emit->env->t_float ) ) | ||
| 1575 | { | ||
| 1576 | emit->append( instr = new Chuck_Instr_Add_float_string ); | ||
| 1577 | instr->set_linepos( rhs->linepos ); | ||
| 1578 | } | ||
| 1579 | else | ||
| 1580 | { | ||
| 1581 | EM_error2( lhs->linepos, | ||
| 1582 | "(emit): internal error: unhandled op '%s' %s '%s'", | ||
| 1583 | t_left->c_name(), op2str( op ), t_right->c_name() ); | ||
| 1584 | return FALSE; | ||
| 1585 | } | ||
| 1586 | } | ||
| 1587 | else // other types | ||
| 1588 | { | ||
| 1589 | switch( left ) | ||
| 1590 | { | ||
| 1591 | case te_int: | ||
| 1592 | emit->append( instr = new Chuck_Instr_Add_int ); | ||
| 1593 | break; | ||
| 1594 | case te_float: | ||
| 1595 | case te_dur: | ||
| 1596 | emit->append( instr = new Chuck_Instr_Add_double ); | ||
| 1597 | break; | ||
| 1598 | case te_complex: | ||
| 1599 | emit->append( instr = new Chuck_Instr_Add_complex ); | ||
| 1600 | break; | ||
| 1601 | case te_polar: | ||
| 1602 | emit->append( instr = new Chuck_Instr_Add_polar ); | ||
| 1603 | break; | ||
| 1604 | case te_vec3: | ||
| 1605 | emit->append( instr = new Chuck_Instr_Add_vec3 ); | ||
| 1606 | break; | ||
| 1607 | case te_vec4: | ||
| 1608 | emit->append( instr = new Chuck_Instr_Add_vec4 ); | ||
| 1609 | break; | ||
| 1610 | |||
| 1611 | default: break; | ||
| 1612 | } | ||
| 1613 | } | ||
| 1614 | break; | ||
| 1615 | |||
| 1616 | case ae_op_plus_chuck: | ||
| 1617 | // time advance | ||
| 1618 | if( left == te_dur && right == te_time && rhs->s_meta == ae_meta_var && | ||
| 1619 | rhs->s_type == ae_exp_primary && !strcmp( "now", S_name(rhs->primary.var) ) ) | ||
| 1620 | { | ||
| 1621 | // add the two | ||
| 1622 | emit->append( new Chuck_Instr_Add_double ); | ||
| 1623 | // advance time (TODO: verify having two instr is OK) | ||
| 1624 | emit->append( instr = new Chuck_Instr_Time_Advance ); | ||
| 1625 | instr->set_linepos( lhs->linepos ); | ||
| 1626 | } | ||
| 1627 | // time + dur | ||
| 1628 | else if( ( left == te_dur && right == te_time ) || | ||
| 1629 | ( left == te_time && right == te_dur ) ) | ||
| 1630 | { | ||
| 1631 | emit->append( instr = new Chuck_Instr_Add_double_Assign ); | ||
| 1632 | } | ||
| 1633 | // string + string | ||
| 1634 | else if( isa( t_left, emit->env->t_string ) && isa( t_right, emit->env->t_string ) ) | ||
| 1635 | { | ||
| 1636 | // concatenate | ||
| 1637 | emit->append( instr = new Chuck_Instr_Add_string_Assign ); | ||
| 1638 | instr->set_linepos( lhs->linepos ); | ||
| 1639 | } | ||
| 1640 | // right: string | ||
| 1641 | else if( isa( t_right, emit->env->t_string ) ) | ||
| 1642 | { | ||
| 1643 | // + int | ||
| 1644 | if( isa( t_left, emit->env->t_int ) ) | ||
| 1645 | { | ||
| 1646 | emit->append( instr = new Chuck_Instr_Add_int_string_Assign ); | ||
| 1647 | // null exceptions will occur from string: use rhs, not lhs | ||
| 1648 | instr->set_linepos( rhs->linepos ); | ||
| 1649 | } | ||
| 1650 | else if( isa( t_left, emit->env->t_float ) ) | ||
| 1651 | { | ||
| 1652 | emit->append( instr = new Chuck_Instr_Add_float_string_Assign ); | ||
| 1653 | instr->set_linepos( rhs->linepos ); | ||
| 1654 | } | ||
| 1655 | else | ||
| 1656 | { | ||
| 1657 | EM_error2( lhs->linepos, | ||
| 1658 | "(emit): internal error: unhandled op '%s' %s '%s'", | ||
| 1659 | t_left->c_name(), op2str( op ), t_right->c_name() ); | ||
| 1660 | return FALSE; | ||
| 1661 | } | ||
| 1662 | } | ||
| 1663 | else // other types | ||
| 1664 | { | ||
| 1665 | switch( left ) | ||
| 1666 | { | ||
| 1667 | case te_int: | ||
| 1668 | emit->append( instr = new Chuck_Instr_Add_int_Assign ); | ||
| 1669 | break; | ||
| 1670 | case te_float: | ||
| 1671 | case te_dur: | ||
| 1672 | emit->append( instr = new Chuck_Instr_Add_double_Assign ); | ||
| 1673 | break; | ||
| 1674 | case te_complex: | ||
| 1675 | emit->append( instr = new Chuck_Instr_Add_complex_Assign ); | ||
| 1676 | break; | ||
| 1677 | case te_polar: | ||
| 1678 | emit->append( instr = new Chuck_Instr_Add_polar_Assign ); | ||
| 1679 | break; | ||
| 1680 | case te_vec3: | ||
| 1681 | emit->append( instr = new Chuck_Instr_Add_vec3_Assign ); | ||
| 1682 | break; | ||
| 1683 | case te_vec4: | ||
| 1684 | emit->append( instr = new Chuck_Instr_Add_vec4_Assign ); | ||
| 1685 | break; | ||
| 1686 | |||
| 1687 | default: break; | ||
| 1688 | } | ||
| 1689 | } | ||
| 1690 | break; | ||
| 1691 | |||
| 1692 | case ae_op_minus: | ||
| 1693 | if( ( left == te_time && right == te_dur ) ) // time - dur = time | ||
| 1694 | emit->append( instr = new Chuck_Instr_Minus_double ); | ||
| 1695 | else if( ( left == te_time && right == te_time ) ) // time - time = dur | ||
| 1696 | emit->append( instr = new Chuck_Instr_Minus_double ); | ||
| 1697 | else // other types | ||
| 1698 | { | ||
| 1699 | switch( left ) | ||
| 1700 | { | ||
| 1701 | case te_int: | ||
| 1702 | emit->append( instr = new Chuck_Instr_Minus_int ); | ||
| 1703 | break; | ||
| 1704 | case te_float: | ||
| 1705 | case te_dur: | ||
| 1706 | emit->append( instr = new Chuck_Instr_Minus_double ); | ||
| 1707 | break; | ||
| 1708 | case te_complex: | ||
| 1709 | emit->append( instr = new Chuck_Instr_Minus_complex ); | ||
| 1710 | break; | ||
| 1711 | case te_polar: | ||
| 1712 | emit->append( instr = new Chuck_Instr_Minus_polar ); | ||
| 1713 | break; | ||
| 1714 | case te_vec3: | ||
| 1715 | emit->append( instr = new Chuck_Instr_Minus_vec3 ); | ||
| 1716 | break; | ||
| 1717 | case te_vec4: | ||
| 1718 | emit->append( instr = new Chuck_Instr_Minus_vec4 ); | ||
| 1719 | break; | ||
| 1720 | |||
| 1721 | default: break; | ||
| 1722 | } | ||
| 1723 | } | ||
| 1724 | break; | ||
| 1725 | |||
| 1726 | case ae_op_minus_chuck: | ||
| 1727 | if( ( left == te_dur && right == te_time ) ) // time - dur = time | ||
| 1728 | emit->append( instr = new Chuck_Instr_Minus_double_Assign ); | ||
| 1729 | else if( ( left == te_time && right == te_time ) ) // time - time = dur | ||
| 1730 | emit->append( instr = new Chuck_Instr_Minus_double_Assign ); | ||
| 1731 | else // other types | ||
| 1732 | { | ||
| 1733 | switch( left ) | ||
| 1734 | { | ||
| 1735 | case te_int: | ||
| 1736 | emit->append( instr = new Chuck_Instr_Minus_int_Assign ); | ||
| 1737 | break; | ||
| 1738 | case te_float: | ||
| 1739 | case te_dur: | ||
| 1740 | emit->append( instr = new Chuck_Instr_Minus_double_Assign ); | ||
| 1741 | break; | ||
| 1742 | case te_complex: | ||
| 1743 | emit->append( instr = new Chuck_Instr_Minus_complex_Assign ); | ||
| 1744 | break; | ||
| 1745 | case te_polar: | ||
| 1746 | emit->append( instr = new Chuck_Instr_Minus_polar_Assign ); | ||
| 1747 | break; | ||
| 1748 | case te_vec3: | ||
| 1749 | emit->append( instr = new Chuck_Instr_Minus_vec3_Assign ); | ||
| 1750 | break; | ||
| 1751 | case te_vec4: | ||
| 1752 | emit->append( instr = new Chuck_Instr_Minus_vec4_Assign ); | ||
| 1753 | break; | ||
| 1754 | |||
| 1755 | default: break; | ||
| 1756 | } | ||
| 1757 | } | ||
| 1758 | break; | ||
| 1759 | |||
| 1760 | case ae_op_times: | ||
| 1761 | // check | ||
| 1762 | if( left == te_float && right == te_vec3 ) | ||
| 1763 | { | ||
| 1764 | emit->append( instr = new Chuck_Instr_float_Times_vec3 ); | ||
| 1765 | } | ||
| 1766 | else if( left == te_vec3 && right == te_float ) | ||
| 1767 | { | ||
| 1768 | emit->append( instr = new Chuck_Instr_vec3_Times_float ); | ||
| 1769 | } | ||
| 1770 | else if( left == te_float && right == te_vec4 ) | ||
| 1771 | { | ||
| 1772 | emit->append( instr = new Chuck_Instr_float_Times_vec4 ); | ||
| 1773 | } | ||
| 1774 | else if( left == te_vec4 && right == te_float ) | ||
| 1775 | { | ||
| 1776 | emit->append( instr = new Chuck_Instr_vec4_Times_float ); | ||
| 1777 | } | ||
| 1778 | else // other cases | ||
| 1779 | { | ||
| 1780 | switch( left ) | ||
| 1781 | { | ||
| 1782 | case te_int: | ||
| 1783 | emit->append( instr = new Chuck_Instr_Times_int ); | ||
| 1784 | break; | ||
| 1785 | case te_float: | ||
| 1786 | case te_dur: | ||
| 1787 | emit->append( instr = new Chuck_Instr_Times_double ); | ||
| 1788 | break; | ||
| 1789 | case te_complex: | ||
| 1790 | emit->append( instr = new Chuck_Instr_Times_complex ); | ||
| 1791 | break; | ||
| 1792 | case te_polar: | ||
| 1793 | emit->append( instr = new Chuck_Instr_Times_polar ); | ||
| 1794 | break; | ||
| 1795 | case te_vec3: | ||
| 1796 | emit->append( instr = new Chuck_Instr_XProduct_vec3 ); | ||
| 1797 | break; | ||
| 1798 | case te_vec4: | ||
| 1799 | emit->append( instr = new Chuck_Instr_XProduct_vec4 ); | ||
| 1800 | break; | ||
| 1801 | |||
| 1802 | default: break; | ||
| 1803 | } | ||
| 1804 | } | ||
| 1805 | break; | ||
| 1806 | |||
| 1807 | case ae_op_times_chuck: | ||
| 1808 | // check | ||
| 1809 | if( left == te_float && right == te_vec3 ) | ||
| 1810 | { | ||
| 1811 | emit->append( instr = new Chuck_Instr_float_Times_vec3_Assign ); | ||
| 1812 | } | ||
| 1813 | else if( left == te_float && right == te_vec4 ) | ||
| 1814 | { | ||
| 1815 | emit->append( instr = new Chuck_Instr_float_Times_vec4_Assign ); | ||
| 1816 | } | ||
| 1817 | else | ||
| 1818 | { | ||
| 1819 | switch( left ) | ||
| 1820 | { | ||
| 1821 | case te_int: | ||
| 1822 | emit->append( instr = new Chuck_Instr_Times_int_Assign ); | ||
| 1823 | break; | ||
| 1824 | case te_float: | ||
| 1825 | emit->append( instr = new Chuck_Instr_Times_double_Assign ); | ||
| 1826 | break; | ||
| 1827 | case te_complex: | ||
| 1828 | emit->append( instr = new Chuck_Instr_Times_complex_Assign ); | ||
| 1829 | break; | ||
| 1830 | case te_polar: | ||
| 1831 | emit->append( instr = new Chuck_Instr_Times_polar_Assign ); | ||
| 1832 | break; | ||
| 1833 | |||
| 1834 | default: break; | ||
| 1835 | } | ||
| 1836 | } | ||
| 1837 | break; | ||
| 1838 | |||
| 1839 | case ae_op_divide: | ||
| 1840 | if( ( left == te_time && right == te_dur ) ) // time / dur = float | ||
| 1841 | emit->append( instr = new Chuck_Instr_Divide_double ); | ||
| 1842 | else if( left == te_vec3 && right == te_float ) | ||
| 1843 | { | ||
| 1844 | emit->append( instr = new Chuck_Instr_vec3_Divide_float ); | ||
| 1845 | } | ||
| 1846 | else if( left == te_vec4 && right == te_float ) | ||
| 1847 | { | ||
| 1848 | emit->append( instr = new Chuck_Instr_vec4_Divide_float ); | ||
| 1849 | } | ||
| 1850 | else // other types | ||
| 1851 | { | ||
| 1852 | switch( left ) | ||
| 1853 | { | ||
| 1854 | case te_int: | ||
| 1855 | emit->append( instr = new Chuck_Instr_Divide_int ); | ||
| 1856 | instr->set_linepos( rhs->linepos ); | ||
| 1857 | break; | ||
| 1858 | case te_float: | ||
| 1859 | case te_dur: | ||
| 1860 | emit->append( instr = new Chuck_Instr_Divide_double ); | ||
| 1861 | break; | ||
| 1862 | case te_complex: | ||
| 1863 | emit->append( instr = new Chuck_Instr_Divide_complex ); | ||
| 1864 | break; | ||
| 1865 | case te_polar: | ||
| 1866 | emit->append( instr = new Chuck_Instr_Divide_polar ); | ||
| 1867 | break; | ||
| 1868 | |||
| 1869 | default: break; | ||
| 1870 | } | ||
| 1871 | } | ||
| 1872 | break; | ||
| 1873 | |||
| 1874 | case ae_op_divide_chuck: | ||
| 1875 | // reverse | ||
| 1876 | if( ( left == te_dur && right == te_time ) ) // time / dur = float | ||
| 1877 | emit->append( instr = new Chuck_Instr_Divide_double_Assign ); | ||
| 1878 | else | ||
| 1879 | if( left == te_float && right == te_vec3 ) | ||
| 1880 | { | ||
| 1881 | emit->append( instr = new Chuck_Instr_vec3_Divide_float_Assign ); | ||
| 1882 | } | ||
| 1883 | else if( left == te_float && right == te_vec4 ) | ||
| 1884 | { | ||
| 1885 | emit->append( instr = new Chuck_Instr_vec4_Divide_float_Assign ); | ||
| 1886 | } | ||
| 1887 | else // other types | ||
| 1888 | { | ||
| 1889 | switch( left ) | ||
| 1890 | { | ||
| 1891 | case te_int: | ||
| 1892 | emit->append( instr = new Chuck_Instr_Divide_int_Assign ); | ||
| 1893 | instr->set_linepos( lhs->linepos ); | ||
| 1894 | break; | ||
| 1895 | case te_float: | ||
| 1896 | emit->append( instr = new Chuck_Instr_Divide_double_Assign ); | ||
| 1897 | break; | ||
| 1898 | case te_complex: | ||
| 1899 | emit->append( instr = new Chuck_Instr_Divide_complex_Assign ); | ||
| 1900 | break; | ||
| 1901 | case te_polar: | ||
| 1902 | emit->append( instr = new Chuck_Instr_Divide_polar_Assign ); | ||
| 1903 | break; | ||
| 1904 | |||
| 1905 | default: break; | ||
| 1906 | } | ||
| 1907 | } | ||
| 1908 | break; | ||
| 1909 | |||
| 1910 | case ae_op_s_or: | ||
| 1911 | switch( left ) | ||
| 1912 | { | ||
| 1913 | case te_int: | ||
| 1914 | emit->append( instr = new Chuck_Instr_Binary_Or ); | ||
| 1915 | break; | ||
| 1916 | |||
| 1917 | default: break; | ||
| 1918 | } | ||
| 1919 | break; | ||
| 1920 | |||
| 1921 | case ae_op_s_or_chuck: | ||
| 1922 | switch( left ) | ||
| 1923 | { | ||
| 1924 | case te_int: | ||
| 1925 | emit->append( instr = new Chuck_Instr_Binary_Or_Assign ); | ||
| 1926 | break; | ||
| 1927 | |||
| 1928 | default: break; | ||
| 1929 | } | ||
| 1930 | break; | ||
| 1931 | |||
| 1932 | case ae_op_s_and: | ||
| 1933 | switch( left ) | ||
| 1934 | { | ||
| 1935 | case te_int: | ||
| 1936 | emit->append( instr = new Chuck_Instr_Binary_And ); | ||
| 1937 | break; | ||
| 1938 | |||
| 1939 | default: break; | ||
| 1940 | } | ||
| 1941 | break; | ||
| 1942 | |||
| 1943 | case ae_op_s_and_chuck: | ||
| 1944 | switch( left ) | ||
| 1945 | { | ||
| 1946 | case te_int: | ||
| 1947 | emit->append( instr = new Chuck_Instr_Binary_And_Assign ); | ||
| 1948 | break; | ||
| 1949 | |||
| 1950 | default: break; | ||
| 1951 | } | ||
| 1952 | break; | ||
| 1953 | |||
| 1954 | case ae_op_shift_left: | ||
| 1955 | switch( left ) | ||
| 1956 | { | ||
| 1957 | case te_int: | ||
| 1958 | emit->append( instr = new Chuck_Instr_Binary_Shift_Left ); | ||
| 1959 | break; | ||
| 1960 | |||
| 1961 | case te_array: | ||
| 1962 | // check size (1.3.1.0: changed to getkindof) | ||
| 1963 | emit->append( instr = new Chuck_Instr_Array_Append( getkindof( emit->env, t_left->array_type ) ) ); | ||
| 1964 | instr->set_linepos( lhs->linepos ); | ||
| 1965 | break; | ||
| 1966 | |||
| 1967 | default: break; | ||
| 1968 | } | ||
| 1969 | break; | ||
| 1970 | |||
| 1971 | case ae_op_shift_left_chuck: | ||
| 1972 | // reverse | ||
| 1973 | switch( left ) | ||
| 1974 | { | ||
| 1975 | case te_int: | ||
| 1976 | emit->append( instr = new Chuck_Instr_Binary_Shift_Left_Assign ); | ||
| 1977 | break; | ||
| 1978 | |||
| 1979 | default: break; | ||
| 1980 | } | ||
| 1981 | break; | ||
| 1982 | |||
| 1983 | case ae_op_shift_right: | ||
| 1984 | switch( left ) | ||
| 1985 | { | ||
| 1986 | case te_int: | ||
| 1987 | emit->append( instr = new Chuck_Instr_Binary_Shift_Right ); | ||
| 1988 | break; | ||
| 1989 | |||
| 1990 | // case te_array: | ||
| 1991 | // emit->append( instr = new Chuck_Instr_Array_Prepend( t_left->array_type->size ) ); | ||
| 1992 | // break; | ||
| 1993 | |||
| 1994 | default: break; | ||
| 1995 | } | ||
| 1996 | break; | ||
| 1997 | |||
| 1998 | case ae_op_shift_right_chuck: | ||
| 1999 | // reverse | ||
| 2000 | switch( left ) | ||
| 2001 | { | ||
| 2002 | case te_int: | ||
| 2003 | emit->append( instr = new Chuck_Instr_Binary_Shift_Right_Assign ); | ||
| 2004 | break; | ||
| 2005 | |||
| 2006 | default: break; | ||
| 2007 | } | ||
| 2008 | break; | ||
| 2009 | |||
| 2010 | case ae_op_percent: | ||
| 2011 | if( ( left == te_time && right == te_dur ) ) // time % dur = dur | ||
| 2012 | { | ||
| 2013 | emit->append( instr = new Chuck_Instr_Mod_double ); | ||
| 2014 | } | ||
| 2015 | else // other types | ||
| 2016 | { | ||
| 2017 | switch( left ) | ||
| 2018 | { | ||
| 2019 | case te_int: | ||
| 2020 | emit->append( instr = new Chuck_Instr_Mod_int ); | ||
| 2021 | break; | ||
| 2022 | case te_float: | ||
| 2023 | case te_dur: | ||
| 2024 | emit->append( instr = new Chuck_Instr_Mod_double ); | ||
| 2025 | break; | ||
| 2026 | |||
| 2027 | default: break; | ||
| 2028 | } | ||
| 2029 | } | ||
| 2030 | break; | ||
| 2031 | |||
| 2032 | case ae_op_percent_chuck: | ||
| 2033 | // reverse | ||
| 2034 | if( ( left == te_dur && right == te_time ) ) // time % dur = dur | ||
| 2035 | { | ||
| 2036 | emit->append( instr = new Chuck_Instr_Mod_double_Assign ); | ||
| 2037 | } | ||
| 2038 | else // other types | ||
| 2039 | { | ||
| 2040 | switch( left ) | ||
| 2041 | { | ||
| 2042 | case te_int: | ||
| 2043 | emit->append( instr = new Chuck_Instr_Mod_int_Assign ); | ||
| 2044 | break; | ||
| 2045 | case te_float: | ||
| 2046 | case te_dur: | ||
| 2047 | emit->append( instr = new Chuck_Instr_Mod_double_Assign ); | ||
| 2048 | break; | ||
| 2049 | |||
| 2050 | default: break; | ||
| 2051 | } | ||
| 2052 | } | ||
| 2053 | break; | ||
| 2054 | |||
| 2055 | case ae_op_s_xor: | ||
| 2056 | switch( left ) | ||
| 2057 | { | ||
| 2058 | case te_int: | ||
| 2059 | emit->append( instr = new Chuck_Instr_Binary_Xor ); | ||
| 2060 | break; | ||
| 2061 | default: break; | ||
| 2062 | } | ||
| 2063 | break; | ||
| 2064 | |||
| 2065 | case ae_op_s_xor_chuck: | ||
| 2066 | switch( left ) | ||
| 2067 | { | ||
| 2068 | case te_int: | ||
| 2069 | emit->append( instr = new Chuck_Instr_Binary_Xor_Assign ); | ||
| 2070 | break; | ||
| 2071 | default: break; | ||
| 2072 | } | ||
| 2073 | break; | ||
| 2074 | |||
| 2075 | // ----------------------------- chuck ------------------------------------- | ||
| 2076 | case ae_op_chuck: | ||
| 2077 | { | ||
| 2078 | a_Exp cl = lhs, cr = rhs; | ||
| 2079 | |||
| 2080 | if( !emit_engine_emit_op_chuck( emit, cl, cr, binary ) ) | ||
| 2081 | return FALSE; | ||
| 2082 | |||
| 2083 | return TRUE; | ||
| 2084 | } | ||
| 2085 | |||
| 2086 | case ae_op_unchuck: | ||
| 2087 | { | ||
| 2088 | a_Exp cl = lhs, cr = rhs; | ||
| 2089 | |||
| 2090 | // TODO: cross chuck | ||
| 2091 | assert( cl->next == NULL && cr->next == NULL ); | ||
| 2092 | while( cr ) | ||
| 2093 | { | ||
| 2094 | cl = lhs; | ||
| 2095 | while( cl ) | ||
| 2096 | { | ||
| 2097 | if( !emit_engine_emit_op_unchuck( emit, cl, cr ) ) | ||
| 2098 | return FALSE; | ||
| 2099 | cl = cl->next; | ||
| 2100 | } | ||
| 2101 | |||
| 2102 | cr = cr->next; | ||
| 2103 | } | ||
| 2104 | |||
| 2105 | return TRUE; | ||
| 2106 | } | ||
| 2107 | |||
| 2108 | case ae_op_upchuck: | ||
| 2109 | { | ||
| 2110 | a_Exp cl = lhs, cr = rhs; | ||
| 2111 | |||
| 2112 | // TODO: cross chuck | ||
| 2113 | assert( cl->next == NULL && cr->next == NULL ); | ||
| 2114 | while( cr ) | ||
| 2115 | { | ||
| 2116 | cl = lhs; | ||
| 2117 | while( cl ) | ||
| 2118 | { | ||
| 2119 | if( !emit_engine_emit_op_upchuck( emit, cl, cr ) ) | ||
| 2120 | return FALSE; | ||
| 2121 | cl = cl->next; | ||
| 2122 | } | ||
| 2123 | |||
| 2124 | cr = cr->next; | ||
| 2125 | } | ||
| 2126 | |||
| 2127 | return TRUE; | ||
| 2128 | } | ||
| 2129 | |||
| 2130 | case ae_op_at_chuck: | ||
| 2131 | { | ||
| 2132 | a_Exp cl = lhs, cr = rhs; | ||
| 2133 | |||
| 2134 | // TODO: cross chuck | ||
| 2135 | assert( cl->next == NULL && cr->next == NULL ); | ||
| 2136 | while( cr ) | ||
| 2137 | { | ||
| 2138 | cl = lhs; | ||
| 2139 | while( cl ) | ||
| 2140 | { | ||
| 2141 | if( !emit_engine_emit_op_at_chuck( emit, cl, cr ) ) | ||
| 2142 | return FALSE; | ||
| 2143 | cl = cl->next; | ||
| 2144 | } | ||
| 2145 | |||
| 2146 | cr = cr->next; | ||
| 2147 | } | ||
| 2148 | |||
| 2149 | return TRUE; | ||
| 2150 | } | ||
| 2151 | |||
| 2152 | case ae_op_s_chuck: | ||
| 2153 | break; | ||
| 2154 | |||
| 2155 | // -------------------------------- bool ----------------------------------- | ||
| 2156 | case ae_op_eq: | ||
| 2157 | if( isa( t_left, emit->env->t_string ) && isa( t_right, emit->env->t_string ) | ||
| 2158 | && !isa( t_left, emit->env->t_null ) && !isa( t_right, emit->env->t_null ) ) // !null | ||
| 2159 | { | ||
| 2160 | emit->append( instr = new Chuck_Instr_Op_string( op ) ); | ||
| 2161 | instr->set_linepos( lhs->linepos ); | ||
| 2162 | } | ||
| 2163 | else if( isa( t_left, emit->env->t_object ) && isa( t_right, emit->env->t_object ) ) | ||
| 2164 | emit->append( instr = new Chuck_Instr_Eq_int ); | ||
| 2165 | else | ||
| 2166 | { | ||
| 2167 | switch( left ) | ||
| 2168 | { | ||
| 2169 | case te_int: | ||
| 2170 | emit->append( instr = new Chuck_Instr_Eq_int ); | ||
| 2171 | break; | ||
| 2172 | case te_float: | ||
| 2173 | case te_dur: | ||
| 2174 | case te_time: | ||
| 2175 | emit->append( instr = new Chuck_Instr_Eq_double ); | ||
| 2176 | break; | ||
| 2177 | case te_complex: | ||
| 2178 | case te_polar: | ||
| 2179 | emit->append( instr = new Chuck_Instr_Eq_complex ); | ||
| 2180 | break; | ||
| 2181 | case te_vec3: | ||
| 2182 | emit->append( instr = new Chuck_Instr_Eq_vec3 ); | ||
| 2183 | break; | ||
| 2184 | case te_vec4: | ||
| 2185 | emit->append( instr = new Chuck_Instr_Eq_vec4 ); | ||
| 2186 | break; | ||
| 2187 | |||
| 2188 | default: break; | ||
| 2189 | } | ||
| 2190 | } | ||
| 2191 | break; | ||
| 2192 | |||
| 2193 | case ae_op_neq: | ||
| 2194 | if( isa( t_left, emit->env->t_string ) && isa( t_right, emit->env->t_string ) | ||
| 2195 | && !isa( t_left, emit->env->t_null ) && !isa( t_right, emit->env->t_null ) ) // !null | ||
| 2196 | // added 1.3.2.0 (spencer) | ||
| 2197 | { | ||
| 2198 | emit->append( instr = new Chuck_Instr_Op_string( op ) ); | ||
| 2199 | instr->set_linepos( lhs->linepos ); | ||
| 2200 | } | ||
| 2201 | else if( isa( t_left, emit->env->t_object ) && isa( t_right, emit->env->t_object ) ) | ||
| 2202 | emit->append( instr = new Chuck_Instr_Neq_int ); | ||
| 2203 | else | ||
| 2204 | { | ||
| 2205 | switch( left ) | ||
| 2206 | { | ||
| 2207 | case te_int: | ||
| 2208 | emit->append( instr = new Chuck_Instr_Neq_int ); | ||
| 2209 | break; | ||
| 2210 | case te_float: | ||
| 2211 | case te_dur: | ||
| 2212 | case te_time: | ||
| 2213 | emit->append( instr = new Chuck_Instr_Neq_double ); | ||
| 2214 | break; | ||
| 2215 | case te_complex: | ||
| 2216 | case te_polar: | ||
| 2217 | emit->append( instr = new Chuck_Instr_Neq_complex ); | ||
| 2218 | break; | ||
| 2219 | case te_vec3: | ||
| 2220 | emit->append( instr = new Chuck_Instr_Neq_vec3 ); | ||
| 2221 | break; | ||
| 2222 | case te_vec4: | ||
| 2223 | emit->append( instr = new Chuck_Instr_Neq_vec4 ); | ||
| 2224 | break; | ||
| 2225 | |||
| 2226 | default: break; | ||
| 2227 | } | ||
| 2228 | } | ||
| 2229 | break; | ||
| 2230 | |||
| 2231 | case ae_op_lt: | ||
| 2232 | switch( left ) | ||
| 2233 | { | ||
| 2234 | case te_int: | ||
| 2235 | emit->append( instr = new Chuck_Instr_Lt_int ); | ||
| 2236 | break; | ||
| 2237 | case te_float: | ||
| 2238 | case te_dur: | ||
| 2239 | case te_time: | ||
| 2240 | emit->append( instr = new Chuck_Instr_Lt_double ); | ||
| 2241 | break; | ||
| 2242 | |||
| 2243 | default: | ||
| 2244 | if( isa( t_left, emit->env->t_string ) && isa( t_right, emit->env->t_string ) ) | ||
| 2245 | { | ||
| 2246 | emit->append( instr = new Chuck_Instr_Op_string( op ) ); | ||
| 2247 | instr->set_linepos( lhs->linepos ); | ||
| 2248 | } | ||
| 2249 | break; | ||
| 2250 | } | ||
| 2251 | break; | ||
| 2252 | |||
| 2253 | case ae_op_le: | ||
| 2254 | switch( left ) | ||
| 2255 | { | ||
| 2256 | case te_int: | ||
| 2257 | emit->append( instr = new Chuck_Instr_Le_int ); | ||
| 2258 | break; | ||
| 2259 | case te_float: | ||
| 2260 | case te_dur: | ||
| 2261 | case te_time: | ||
| 2262 | emit->append( instr = new Chuck_Instr_Le_double ); | ||
| 2263 | break; | ||
| 2264 | |||
| 2265 | default: | ||
| 2266 | if( isa( t_left, emit->env->t_string ) && isa( t_right, emit->env->t_string ) ) | ||
| 2267 | { | ||
| 2268 | emit->append( instr = new Chuck_Instr_Op_string( op ) ); | ||
| 2269 | instr->set_linepos( lhs->linepos ); | ||
| 2270 | } | ||
| 2271 | else if( isa( t_left, emit->env->t_io ) ) | ||
| 2272 | { | ||
| 2273 | // output | ||
| 2274 | if( isa( t_right, emit->env->t_int ) ) | ||
| 2275 | { | ||
| 2276 | emit->append( instr = new Chuck_Instr_IO_out_int ); | ||
| 2277 | instr->set_linepos( rhs->linepos ); | ||
| 2278 | } | ||
| 2279 | else if( isa( t_right, emit->env->t_float ) ) | ||
| 2280 | { | ||
| 2281 | emit->append( instr = new Chuck_Instr_IO_out_float ); | ||
| 2282 | instr->set_linepos( rhs->linepos ); | ||
| 2283 | } | ||
| 2284 | else if( isa( t_right, emit->env->t_string ) ) | ||
| 2285 | { | ||
| 2286 | emit->append( instr = new Chuck_Instr_IO_out_string ); | ||
| 2287 | instr->set_linepos( rhs->linepos ); | ||
| 2288 | } | ||
| 2289 | } | ||
| 2290 | break; | ||
| 2291 | } | ||
| 2292 | break; | ||
| 2293 | |||
| 2294 | case ae_op_gt: | ||
| 2295 | switch( left ) | ||
| 2296 | { | ||
| 2297 | case te_int: | ||
| 2298 | emit->append( instr = new Chuck_Instr_Gt_int ); | ||
| 2299 | break; | ||
| 2300 | case te_float: | ||
| 2301 | case te_dur: | ||
| 2302 | case te_time: | ||
| 2303 | emit->append( instr = new Chuck_Instr_Gt_double ); | ||
| 2304 | break; | ||
| 2305 | |||
| 2306 | default: | ||
| 2307 | if( isa( t_left, emit->env->t_string ) && isa( t_right, emit->env->t_string ) ) | ||
| 2308 | { | ||
| 2309 | emit->append( instr = new Chuck_Instr_Op_string( op ) ); | ||
| 2310 | instr->set_linepos( lhs->linepos ); | ||
| 2311 | } | ||
| 2312 | break; | ||
| 2313 | } | ||
| 2314 | break; | ||
| 2315 | |||
| 2316 | case ae_op_ge: | ||
| 2317 | switch( left ) | ||
| 2318 | { | ||
| 2319 | case te_int: | ||
| 2320 | emit->append( instr = new Chuck_Instr_Ge_int ); | ||
| 2321 | break; | ||
| 2322 | case te_float: | ||
| 2323 | case te_dur: | ||
| 2324 | case te_time: | ||
| 2325 | emit->append( instr = new Chuck_Instr_Ge_double ); | ||
| 2326 | break; | ||
| 2327 | |||
| 2328 | default: | ||
| 2329 | if( isa( t_left, emit->env->t_string ) && isa( t_right, emit->env->t_string ) ) | ||
| 2330 | { | ||
| 2331 | emit->append( instr = new Chuck_Instr_Op_string( op ) ); | ||
| 2332 | instr->set_linepos( lhs->linepos ); | ||
| 2333 | } | ||
| 2334 | break; | ||
| 2335 | } | ||
| 2336 | break; | ||
| 2337 | |||
| 2338 | case ae_op_and: | ||
| 2339 | switch( left ) | ||
| 2340 | { | ||
| 2341 | case te_int: | ||
| 2342 | emit->append( instr = new Chuck_Instr_And ); | ||
| 2343 | break; | ||
| 2344 | |||
| 2345 | default: break; | ||
| 2346 | } | ||
| 2347 | break; | ||
| 2348 | |||
| 2349 | case ae_op_or: | ||
| 2350 | switch( left ) | ||
| 2351 | { | ||
| 2352 | case te_int: | ||
| 2353 | emit->append( instr = new Chuck_Instr_Or ); | ||
| 2354 | break; | ||
| 2355 | |||
| 2356 | default: break; | ||
| 2357 | } | ||
| 2358 | break; | ||
| 2359 | |||
| 2360 | //------------------------------- IO ---------------------------------- | ||
| 2361 | case ae_op_arrow_left: | ||
| 2362 | switch( right ) | ||
| 2363 | { | ||
| 2364 | case te_int: | ||
| 2365 | emit->append( instr = new Chuck_Instr_IO_out_int ); | ||
| 2366 | instr->set_linepos( rhs->linepos ); | ||
| 2367 | break; | ||
| 2368 | case te_float: | ||
| 2369 | emit->append( instr = new Chuck_Instr_IO_out_float ); | ||
| 2370 | instr->set_linepos( rhs->linepos ); | ||
| 2371 | break; | ||
| 2372 | default: | ||
| 2373 | if( isa( t_right, emit->env->t_string ) ) | ||
| 2374 | { | ||
| 2375 | emit->append( instr = new Chuck_Instr_IO_out_string ); | ||
| 2376 | instr->set_linepos( rhs->linepos ); | ||
| 2377 | } | ||
| 2378 | break; | ||
| 2379 | } | ||
| 2380 | break; | ||
| 2381 | |||
| 2382 | case ae_op_arrow_right: | ||
| 2383 | switch( right ) | ||
| 2384 | { | ||
| 2385 | case te_int: | ||
| 2386 | emit->append( instr = new Chuck_Instr_IO_in_int ); | ||
| 2387 | instr->set_linepos( rhs->linepos ); | ||
| 2388 | break; | ||
| 2389 | case te_float: | ||
| 2390 | emit->append( instr = new Chuck_Instr_IO_in_float ); | ||
| 2391 | instr->set_linepos( rhs->linepos ); | ||
| 2392 | break; | ||
| 2393 | default: | ||
| 2394 | if( isa( t_right, emit->env->t_string ) ) | ||
| 2395 | { | ||
| 2396 | emit->append( instr = new Chuck_Instr_IO_in_string ); | ||
| 2397 | instr->set_linepos( rhs->linepos ); | ||
| 2398 | } | ||
| 2399 | break; | ||
| 2400 | } | ||
| 2401 | break; | ||
| 2402 | |||
| 2403 | //---------------------------- (error) -------------------------------- | ||
| 2404 | default: | ||
| 2405 | EM_error2( lhs->linepos, | ||
| 2406 | "(emit): internal error: unhandled op '%s' %s '%s'", | ||
| 2407 | t_left->c_name(), op2str( op ), t_right->c_name() ); | ||
| 2408 | return FALSE; | ||
| 2409 | } | ||
| 2410 | |||
| 2411 | // make sure emit | ||
| 2412 | if( !instr ) | ||
| 2413 | { | ||
| 2414 | EM_error2( lhs->linepos, | ||
| 2415 | "(emit): internal error: unhandled op '%s' %s '%s'", | ||
| 2416 | t_left->c_name(), op2str( op ), t_right->c_name() ); | ||
| 2417 | return FALSE; | ||
| 2418 | } | ||
| 2419 | |||
| 2420 | return TRUE; | ||
| 2421 | } | ||
| 2422 | |||
| 2423 | |||
| 2424 | |||
| 2425 | |||
| 2426 | //----------------------------------------------------------------------------- | ||
| 2427 | // name: emit_engine_emit_op_chuck() | ||
| 2428 | // desc: ... | ||
| 2429 | //----------------------------------------------------------------------------- | ||
| 2430 | t_CKBOOL emit_engine_emit_op_chuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ) | ||
| 2431 | { | ||
| 2432 | // any implicit cast happens before this | ||
| 2433 | Chuck_Type * left = lhs->cast_to ? lhs->cast_to : lhs->type; | ||
| 2434 | Chuck_Type * right = rhs->cast_to ? rhs->cast_to : rhs->type; | ||
| 2435 | |||
| 2436 | // the pointer | ||
| 2437 | Chuck_Instr * instr = NULL; | ||
| 2438 | |||
| 2439 | // ugen => ugen | ||
| 2440 | if( isa( left, emit->env->t_ugen ) && isa( right, emit->env->t_ugen ) ) | ||
| 2441 | { | ||
| 2442 | // link, flag as NOT unchuck | ||
| 2443 | emit->append( instr = new Chuck_Instr_UGen_Link( FALSE ) ); | ||
| 2444 | instr->set_linepos( lhs->linepos ); | ||
| 2445 | // done | ||
| 2446 | return TRUE; | ||
| 2447 | } | ||
| 2448 | |||
| 2449 | // ugen[] => ugen[] (or permutation) | ||
| 2450 | if( ( isa( left, emit->env->t_ugen ) || ( isa( left, emit->env->t_array ) && isa( left->array_type, emit->env->t_ugen ) ) ) && | ||
| 2451 | ( isa( right, emit->env->t_ugen ) || ( isa( right, emit->env->t_array ) && isa( right->array_type, emit->env->t_ugen ) ) ) ) | ||
| 2452 | { | ||
| 2453 | // link, flag as NOT unchuck | ||
| 2454 | emit->append( instr = new Chuck_Instr_UGen_Array_Link( isa( left, emit->env->t_array ), isa( right, emit->env->t_array ) ) ); | ||
| 2455 | instr->set_linepos( lhs->linepos ); | ||
| 2456 | // done | ||
| 2457 | return TRUE; | ||
| 2458 | } | ||
| 2459 | |||
| 2460 | // time advance | ||
| 2461 | if( isa( left, emit->env->t_dur ) && isa( right, emit->env->t_time ) && rhs->s_meta == ae_meta_var ) | ||
| 2462 | { | ||
| 2463 | // add the two | ||
| 2464 | emit->append( new Chuck_Instr_Add_double ); | ||
| 2465 | |||
| 2466 | // see if rhs is 'now' | ||
| 2467 | if( rhs->s_type == ae_exp_primary && !strcmp( "now", S_name(rhs->primary.var) ) ) | ||
| 2468 | { | ||
| 2469 | // advance time | ||
| 2470 | emit->append( instr = new Chuck_Instr_Time_Advance ); | ||
| 2471 | instr->set_linepos( lhs->linepos ); | ||
| 2472 | } | ||
| 2473 | |||
| 2474 | return TRUE; | ||
| 2475 | } | ||
| 2476 | |||
| 2477 | // time advance | ||
| 2478 | if( isa( left, emit->env->t_event ) && isa( right, emit->env->t_time ) && rhs->s_meta == ae_meta_var && | ||
| 2479 | rhs->s_type == ae_exp_primary && !strcmp( "now", S_name(rhs->primary.var) ) ) | ||
| 2480 | { | ||
| 2481 | // pop now | ||
| 2482 | emit->append( new Chuck_Instr_Reg_Pop_Word2 ); | ||
| 2483 | emit->append( instr = new Chuck_Instr_Event_Wait ); | ||
| 2484 | instr->set_linepos( lhs->linepos ); | ||
| 2485 | |||
| 2486 | return TRUE; | ||
| 2487 | } | ||
| 2488 | |||
| 2489 | // input | ||
| 2490 | if( isa( left, emit->env->t_io ) ) | ||
| 2491 | { | ||
| 2492 | if( isa( right, emit->env->t_int ) ) | ||
| 2493 | { | ||
| 2494 | assert( rhs->s_meta == ae_meta_var ); | ||
| 2495 | emit->append( instr = new Chuck_Instr_IO_in_int ); | ||
| 2496 | instr->set_linepos( rhs->linepos ); | ||
| 2497 | return TRUE; | ||
| 2498 | } | ||
| 2499 | else if( isa( right, emit->env->t_float ) ) | ||
| 2500 | { | ||
| 2501 | assert( rhs->s_meta == ae_meta_var ); | ||
| 2502 | emit->append( instr = new Chuck_Instr_IO_in_float ); | ||
| 2503 | instr->set_linepos( rhs->linepos ); | ||
| 2504 | return TRUE; | ||
| 2505 | } | ||
| 2506 | else if( isa( right, emit->env->t_string ) ) | ||
| 2507 | { | ||
| 2508 | assert( rhs->s_meta == ae_meta_var ); | ||
| 2509 | emit->append( instr = new Chuck_Instr_IO_in_string ); | ||
| 2510 | instr->set_linepos( rhs->linepos ); | ||
| 2511 | return TRUE; | ||
| 2512 | } | ||
| 2513 | } | ||
| 2514 | |||
| 2515 | // func call | ||
| 2516 | if( isa( right, emit->env->t_function ) ) | ||
| 2517 | { | ||
| 2518 | assert( binary->ck_func != NULL ); | ||
| 2519 | |||
| 2520 | // emit | ||
| 2521 | return emit_engine_emit_exp_func_call( emit, binary->ck_func, binary->self->type, binary->linepos ); | ||
| 2522 | } | ||
| 2523 | |||
| 2524 | // assignment or something else | ||
| 2525 | if( isa( left, right ) ) | ||
| 2526 | { | ||
| 2527 | // basic types? | ||
| 2528 | if( type_engine_check_primitive( emit->env, left ) || isa( left, emit->env->t_string ) ) | ||
| 2529 | { | ||
| 2530 | // use at assign | ||
| 2531 | return emit_engine_emit_op_at_chuck( emit, lhs, rhs ); | ||
| 2532 | } | ||
| 2533 | } | ||
| 2534 | |||
| 2535 | // TODO: check overloading of => | ||
| 2536 | // TODO: deal with const | ||
| 2537 | |||
| 2538 | // no match | ||
| 2539 | EM_error2( lhs->linepos, | ||
| 2540 | "(emit): internal error: unhandled '=>' on types '%s' and '%s'...", | ||
| 2541 | left->c_name(), right->c_name() ); | ||
| 2542 | |||
| 2543 | return FALSE; | ||
| 2544 | } | ||
| 2545 | |||
| 2546 | |||
| 2547 | |||
| 2548 | |||
| 2549 | //----------------------------------------------------------------------------- | ||
| 2550 | // name: emit_engine_emit_op_unchuck() | ||
| 2551 | // desc: ... | ||
| 2552 | //----------------------------------------------------------------------------- | ||
| 2553 | t_CKBOOL emit_engine_emit_op_unchuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs ) | ||
| 2554 | { | ||
| 2555 | // any implicit cast happens before this | ||
| 2556 | Chuck_Type * left = lhs->cast_to ? lhs->cast_to : lhs->type; | ||
| 2557 | Chuck_Type * right = rhs->cast_to ? rhs->cast_to : rhs->type; | ||
| 2558 | |||
| 2559 | // if ugen | ||
| 2560 | if( isa( left, emit->env->t_ugen ) && isa( right, emit->env->t_ugen ) ) | ||
| 2561 | { | ||
| 2562 | // no connect | ||
| 2563 | emit->append( new Chuck_Instr_UGen_UnLink ); | ||
| 2564 | } | ||
| 2565 | else | ||
| 2566 | { | ||
| 2567 | EM_error2( lhs->linepos, | ||
| 2568 | "(emit): internal error: unhandled '=<' on types '%s' and '%s'", | ||
| 2569 | left->c_name(), right->c_name() ); | ||
| 2570 | return FALSE; | ||
| 2571 | } | ||
| 2572 | |||
| 2573 | return TRUE; | ||
| 2574 | } | ||
| 2575 | |||
| 2576 | |||
| 2577 | |||
| 2578 | |||
| 2579 | //----------------------------------------------------------------------------- | ||
| 2580 | // name: emit_engine_emit_op_upchuck() | ||
| 2581 | // desc: ... | ||
| 2582 | //----------------------------------------------------------------------------- | ||
| 2583 | t_CKBOOL emit_engine_emit_op_upchuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs ) | ||
| 2584 | { | ||
| 2585 | // any implicit cast happens before this | ||
| 2586 | Chuck_Type * left = lhs->cast_to ? lhs->cast_to : lhs->type; | ||
| 2587 | Chuck_Type * right = rhs->cast_to ? rhs->cast_to : rhs->type; | ||
| 2588 | |||
| 2589 | // if ugen | ||
| 2590 | if( isa( left, emit->env->t_uana ) && isa( right, emit->env->t_uana ) ) | ||
| 2591 | { | ||
| 2592 | // connect; flag it as unchuck | ||
| 2593 | Chuck_Instr * instr = NULL; | ||
| 2594 | emit->append( instr = new Chuck_Instr_UGen_Link( TRUE ) ); | ||
| 2595 | instr->set_linepos( lhs->linepos ); | ||
| 2596 | } | ||
| 2597 | else | ||
| 2598 | { | ||
| 2599 | EM_error2( lhs->linepos, | ||
| 2600 | "(emit): internal error: unhandled '=^' on types '%s' and '%s'", | ||
| 2601 | left->c_name(), right->c_name() ); | ||
| 2602 | return FALSE; | ||
| 2603 | } | ||
| 2604 | |||
| 2605 | return TRUE; | ||
| 2606 | } | ||
| 2607 | |||
| 2608 | |||
| 2609 | |||
| 2610 | |||
| 2611 | //----------------------------------------------------------------------------- | ||
| 2612 | // name: emit_engine_emit_op_at_chuck() | ||
| 2613 | // desc: ... | ||
| 2614 | //----------------------------------------------------------------------------- | ||
| 2615 | t_CKBOOL emit_engine_emit_op_at_chuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs ) | ||
| 2616 | { | ||
| 2617 | // any implicit cast happens before this | ||
| 2618 | Chuck_Type * left = lhs->cast_to ? lhs->cast_to : lhs->type; | ||
| 2619 | Chuck_Type * right = rhs->cast_to ? rhs->cast_to : rhs->type; | ||
| 2620 | |||
| 2621 | // assignment or something else | ||
| 2622 | if( isa( left, right ) ) | ||
| 2623 | { | ||
| 2624 | // basic types? | ||
| 2625 | if( type_engine_check_primitive( emit->env, left ) || isa( left, emit->env->t_string ) ) | ||
| 2626 | { | ||
| 2627 | // assigment? | ||
| 2628 | if( rhs->s_meta != ae_meta_var ) | ||
| 2629 | { | ||
| 2630 | EM_error2( lhs->linepos, | ||
| 2631 | "(emit): internal error: assignment to non-variable..." ); | ||
| 2632 | return FALSE; | ||
| 2633 | } | ||
| 2634 | |||
| 2635 | // see if rhs is 'now' - time => now | ||
| 2636 | if( rhs->s_type == ae_exp_primary && !strcmp( "now", S_name(rhs->primary.var) ) ) | ||
| 2637 | { | ||
| 2638 | // pop the now addr | ||
| 2639 | emit->append( new Chuck_Instr_Reg_Pop_Word2 ); | ||
| 2640 | // advance time | ||
| 2641 | Chuck_Instr * instr = NULL; | ||
| 2642 | emit->append( instr = new Chuck_Instr_Time_Advance ); | ||
| 2643 | instr->set_linepos( lhs->linepos ); | ||
| 2644 | } | ||
| 2645 | else if( isa( left, emit->env->t_string ) ) // string | ||
| 2646 | { | ||
| 2647 | // assign string | ||
| 2648 | emit->append( new Chuck_Instr_Assign_String ); | ||
| 2649 | } | ||
| 2650 | else | ||
| 2651 | { | ||
| 2652 | // assign primitive | ||
| 2653 | // added 1.3.1.0: iskindofint -- since on some 64-bit systems, sz_INT == sz_FLOAT | ||
| 2654 | if( right->size == sz_INT && iskindofint(emit->env, right) ) // ISSUE: 64-bit (fixed 1.3.1.0) | ||
| 2655 | emit->append( new Chuck_Instr_Assign_Primitive ); | ||
| 2656 | else if( right->size == sz_FLOAT ) // ISSUE: 64-bit (fixed 1.3.1.0) | ||
| 2657 | emit->append( new Chuck_Instr_Assign_Primitive2 ); | ||
| 2658 | else if( right->size == sz_COMPLEX ) // ISSUE: 64-bit (fixed 1.3.1.0) | ||
| 2659 | emit->append( new Chuck_Instr_Assign_Primitive4 ); | ||
| 2660 | else if( right->size == sz_VEC3 ) // ge: added 1.3.5.3 | ||
| 2661 | emit->append( new Chuck_Instr_Assign_PrimitiveVec3 ); | ||
| 2662 | else if( right->size == sz_VEC4 ) // ge: added 1.3.5.3 | ||
| 2663 | emit->append( new Chuck_Instr_Assign_PrimitiveVec4 ); | ||
| 2664 | else | ||
| 2665 | { | ||
| 2666 | EM_error2( rhs->linepos, | ||
| 2667 | "(emit): internal error: assignment to type of size %i...", | ||
| 2668 | right->size ); | ||
| 2669 | } | ||
| 2670 | } | ||
| 2671 | |||
| 2672 | return TRUE; | ||
| 2673 | } | ||
| 2674 | else // objects | ||
| 2675 | { | ||
| 2676 | // assign object | ||
| 2677 | emit->append( new Chuck_Instr_Assign_Object ); | ||
| 2678 | |||
| 2679 | return TRUE; | ||
| 2680 | } | ||
| 2681 | } | ||
| 2682 | |||
| 2683 | // TODO: check overloading of => | ||
| 2684 | // TODO: deal with const | ||
| 2685 | |||
| 2686 | // no match | ||
| 2687 | EM_error2( lhs->linepos, | ||
| 2688 | "(emit): internal error: unhandled '@=>' on types '%s' and '%s'...", | ||
| 2689 | left->c_name(), right->c_name() ); | ||
| 2690 | |||
| 2691 | return FALSE; | ||
| 2692 | } | ||
| 2693 | |||
| 2694 | |||
| 2695 | |||
| 2696 | |||
| 2697 | //----------------------------------------------------------------------------- | ||
| 2698 | // name: emit_engine_emit_exp_unary() | ||
| 2699 | // desc: ... | ||
| 2700 | //----------------------------------------------------------------------------- | ||
| 2701 | t_CKBOOL emit_engine_emit_exp_unary( Chuck_Emitter * emit, a_Exp_Unary unary ) | ||
| 2702 | { | ||
| 2703 | if( unary->op != ae_op_spork && !emit_engine_emit_exp( emit, unary->exp ) ) | ||
| 2704 | return FALSE; | ||
| 2705 | |||
| 2706 | // get type | ||
| 2707 | Chuck_Type * t = unary->self->type; | ||
| 2708 | assert( t != NULL ); | ||
| 2709 | |||
| 2710 | // emit the operator | ||
| 2711 | switch( unary->op ) | ||
| 2712 | { | ||
| 2713 | case ae_op_plusplus: | ||
| 2714 | // make sure assignment is legal | ||
| 2715 | if( unary->self->s_meta != ae_meta_var ) // TODO: const | ||
| 2716 | { | ||
| 2717 | EM_error2( unary->self->linepos, | ||
| 2718 | "(emit): target for '++' not mutable..." ); | ||
| 2719 | return FALSE; | ||
| 2720 | } | ||
| 2721 | |||
| 2722 | // increment | ||
| 2723 | if( equals( unary->exp->type, emit->env->t_int ) ) | ||
| 2724 | emit->append( new Chuck_Instr_PreInc_int ); | ||
| 2725 | else | ||
| 2726 | { | ||
| 2727 | EM_error2( unary->linepos, | ||
| 2728 | "(emit): internal error: unhandled type '%s' for pre '++'' operator", | ||
| 2729 | unary->exp->type->c_name() ); | ||
| 2730 | return FALSE; | ||
| 2731 | } | ||
| 2732 | break; | ||
| 2733 | |||
| 2734 | case ae_op_minusminus: | ||
| 2735 | // make sure assignment is legal | ||
| 2736 | if( unary->self->s_meta != ae_meta_var ) // TODO: const | ||
| 2737 | { | ||
| 2738 | EM_error2( unary->self->linepos, | ||
| 2739 | "(emit): target for '--' not mutable..." ); | ||
| 2740 | return FALSE; | ||
| 2741 | } | ||
| 2742 | |||
| 2743 | // decrement | ||
| 2744 | if( equals( unary->exp->type, emit->env->t_int ) ) | ||
| 2745 | emit->append( new Chuck_Instr_PreDec_int ); | ||
| 2746 | else | ||
| 2747 | { | ||
| 2748 | EM_error2( unary->linepos, | ||
| 2749 | "(emit): internal error: unhandled type '%s' for pre '--' operator", | ||
| 2750 | unary->exp->type->c_name() ); | ||
| 2751 | return FALSE; | ||
| 2752 | } | ||
| 2753 | break; | ||
| 2754 | |||
| 2755 | case ae_op_tilda: | ||
| 2756 | // complement | ||
| 2757 | if( equals( unary->exp->type, emit->env->t_int ) ) | ||
| 2758 | emit->append( new Chuck_Instr_Complement_int ); | ||
| 2759 | else | ||
| 2760 | { | ||
| 2761 | EM_error2( unary->linepos, | ||
| 2762 | "(emit): internal error: unhandled type '%s' for '~' operator", | ||
| 2763 | unary->exp->type->c_name() ); | ||
| 2764 | return FALSE; | ||
| 2765 | } | ||
| 2766 | break; | ||
| 2767 | |||
| 2768 | case ae_op_exclamation: | ||
| 2769 | // ! | ||
| 2770 | if( equals( unary->exp->type, emit->env->t_int ) ) | ||
| 2771 | emit->append( new Chuck_Instr_Not_int ); | ||
| 2772 | else | ||
| 2773 | { | ||
| 2774 | EM_error2( unary->linepos, | ||
| 2775 | "(emit): internal error: unhandled type '%s' for '!' operator", | ||
| 2776 | unary->exp->type->c_name() ); | ||
| 2777 | return FALSE; | ||
| 2778 | } | ||
| 2779 | break; | ||
| 2780 | |||
| 2781 | case ae_op_minus: | ||
| 2782 | // negate | ||
| 2783 | if( equals( unary->exp->type, emit->env->t_int ) ) | ||
| 2784 | emit->append( new Chuck_Instr_Negate_int ); | ||
| 2785 | else if( equals( unary->exp->type, emit->env->t_float ) ) | ||
| 2786 | emit->append( new Chuck_Instr_Negate_double ); | ||
| 2787 | else | ||
| 2788 | { | ||
| 2789 | EM_error2( unary->linepos, | ||
| 2790 | "(emit): internal error: unhandled type '%s' for unary '-' operator", | ||
| 2791 | unary->exp->type->c_name() ); | ||
| 2792 | return FALSE; | ||
| 2793 | } | ||
| 2794 | break; | ||
| 2795 | |||
| 2796 | case ae_op_spork: | ||
| 2797 | // spork ~ func() | ||
| 2798 | if( unary->exp && unary->exp->s_type == ae_exp_func_call ) | ||
| 2799 | { | ||
| 2800 | if( !emit_engine_emit_spork( emit, &unary->exp->func_call ) ) | ||
| 2801 | return FALSE; | ||
| 2802 | } | ||
| 2803 | // spork ~ { ... } | ||
| 2804 | // else if( unary->code ) | ||
| 2805 | // { | ||
| 2806 | // if( !emit_engine_emit_spork( emit, unary->code ) ) | ||
| 2807 | // return FALSE; | ||
| 2808 | // } | ||
| 2809 | else | ||
| 2810 | { | ||
| 2811 | EM_error2( unary->linepos, | ||
| 2812 | "(emit): internal error: sporking non-function call..." ); | ||
| 2813 | return FALSE; | ||
| 2814 | } | ||
| 2815 | break; | ||
| 2816 | |||
| 2817 | case ae_op_new: | ||
| 2818 | |||
| 2819 | // if this is an object | ||
| 2820 | if( isobj( emit->env, t ) ) | ||
| 2821 | { | ||
| 2822 | // instantiate object, including array | ||
| 2823 | if( !emit_engine_instantiate_object( emit, t, unary->array, unary->type->ref ) ) | ||
| 2824 | return FALSE; | ||
| 2825 | } | ||
| 2826 | break; | ||
| 2827 | |||
| 2828 | default: | ||
| 2829 | EM_error2( unary->linepos, | ||
| 2830 | "(emit): internal error: unhandled unary op '%s", | ||
| 2831 | op2str( unary->op ) ); | ||
| 2832 | return FALSE; | ||
| 2833 | } | ||
| 2834 | |||
| 2835 | return TRUE; | ||
| 2836 | } | ||
| 2837 | |||
| 2838 | |||
| 2839 | |||
| 2840 | |||
| 2841 | //----------------------------------------------------------------------------- | ||
| 2842 | // name: emit_engine_emit_exp_primary() | ||
| 2843 | // desc: ... | ||
| 2844 | //----------------------------------------------------------------------------- | ||
| 2845 | t_CKBOOL emit_engine_emit_exp_primary( Chuck_Emitter * emit, a_Exp_Primary exp ) | ||
| 2846 | { | ||
| 2847 | t_CKUINT temp; | ||
| 2848 | t_CKDUR dur; | ||
| 2849 | Chuck_String * str = NULL; | ||
| 2850 | |||
| 2851 | // find out exp | ||
| 2852 | switch( exp->s_type ) | ||
| 2853 | { | ||
| 2854 | case ae_primary_var: | ||
| 2855 | if( exp->var == insert_symbol( "now" ) ) | ||
| 2856 | { | ||
| 2857 | emit->append( new Chuck_Instr_Reg_Push_Now ); | ||
| 2858 | } | ||
| 2859 | else if( exp->var == insert_symbol( "this" ) ) | ||
| 2860 | { | ||
| 2861 | // TODO: verify this is in the right scope | ||
| 2862 | emit->append( new Chuck_Instr_Reg_Push_This ); | ||
| 2863 | } | ||
| 2864 | else if( exp->var == insert_symbol( "me" ) ) | ||
| 2865 | { | ||
| 2866 | emit->append( new Chuck_Instr_Reg_Push_Me ); | ||
| 2867 | } | ||
| 2868 | else if( exp->var == insert_symbol( "true" ) ) | ||
| 2869 | { | ||
| 2870 | emit->append( new Chuck_Instr_Reg_Push_Imm( 1 ) ); | ||
| 2871 | } | ||
| 2872 | else if( exp->var == insert_symbol( "false" ) ) | ||
| 2873 | { | ||
| 2874 | emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); | ||
| 2875 | } | ||
| 2876 | else if( exp->var == insert_symbol("maybe") ) | ||
| 2877 | { | ||
| 2878 | emit->append( new Chuck_Instr_Reg_Push_Maybe() ); | ||
| 2879 | } | ||
| 2880 | else if( exp->var == insert_symbol("null") || | ||
| 2881 | exp->var == insert_symbol("NULL") ) | ||
| 2882 | { | ||
| 2883 | emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); | ||
| 2884 | } | ||
| 2885 | else if( exp->var == insert_symbol( "pi" ) ) | ||
| 2886 | { | ||
| 2887 | double pi = 3.14159265358979323846; | ||
| 2888 | emit->append( new Chuck_Instr_Reg_Push_Imm2( pi ) ); | ||
| 2889 | } | ||
| 2890 | else if( exp->var == insert_symbol( "dac" ) ) | ||
| 2891 | { | ||
| 2892 | emit->append( new Chuck_Instr_DAC ); | ||
| 2893 | } | ||
| 2894 | else if( exp->var == insert_symbol( "adc" ) ) | ||
| 2895 | { | ||
| 2896 | emit->append( new Chuck_Instr_ADC ); | ||
| 2897 | } | ||
| 2898 | else if( exp->var == insert_symbol( "bunghole" ) ) | ||
| 2899 | { | ||
| 2900 | emit->append( new Chuck_Instr_Bunghole ); | ||
| 2901 | } | ||
| 2902 | else if( exp->var == insert_symbol( "blackhole" ) ) | ||
| 2903 | { | ||
| 2904 | emit->append( new Chuck_Instr_Bunghole ); | ||
| 2905 | } | ||
| 2906 | else if( exp->var == insert_symbol( "chout" ) ) | ||
| 2907 | { | ||
| 2908 | emit->append( new Chuck_Instr_Chout ); | ||
| 2909 | } | ||
| 2910 | else if( exp->var == insert_symbol( "cherr" ) ) | ||
| 2911 | { | ||
| 2912 | emit->append( new Chuck_Instr_Cherr ); | ||
| 2913 | } | ||
| 2914 | else if( emit->find_dur( S_name(exp->var), &dur ) ) | ||
| 2915 | { | ||
| 2916 | emit->append( new Chuck_Instr_Reg_Push_Imm2( dur ) ); | ||
| 2917 | } | ||
| 2918 | else | ||
| 2919 | { | ||
| 2920 | // emit the symbol | ||
| 2921 | return emit_engine_emit_symbol( | ||
| 2922 | emit, exp->var, exp->value, exp->self->emit_var, exp->linepos ); | ||
| 2923 | } | ||
| 2924 | break; | ||
| 2925 | |||
| 2926 | case ae_primary_num: | ||
| 2927 | memcpy( &temp, &exp->num, sizeof(temp) ); | ||
| 2928 | emit->append( new Chuck_Instr_Reg_Push_Imm( temp ) ); | ||
| 2929 | break; | ||
| 2930 | |||
| 2931 | case ae_primary_float: | ||
| 2932 | emit->append( new Chuck_Instr_Reg_Push_Imm2( exp->fnum ) ); | ||
| 2933 | break; | ||
| 2934 | |||
| 2935 | case ae_primary_str: | ||
| 2936 | // TODO: fix this | ||
| 2937 | str = new Chuck_String(); | ||
| 2938 | if( !str || !initialize_object( str, emit->env->t_string ) ) | ||
| 2939 | { | ||
| 2940 | // error (TODO: why is this a SAFE_RELEASE and not SAFE_DELETE?) | ||
| 2941 | SAFE_RELEASE( str ); | ||
| 2942 | // error out | ||
| 2943 | CK_FPRINTF_STDERR( | ||
| 2944 | "[chuck](emitter): OutOfMemory: while allocating string literal '%s'\n", exp->str ); | ||
| 2945 | return FALSE; | ||
| 2946 | } | ||
| 2947 | str->set( exp->str ); | ||
| 2948 | temp = (t_CKUINT)str; | ||
| 2949 | emit->append( new Chuck_Instr_Reg_Push_Imm( temp ) ); | ||
| 2950 | // add reference for string literal (added 1.3.0.2) | ||
| 2951 | str->add_ref(); | ||
| 2952 | break; | ||
| 2953 | |||
| 2954 | case ae_primary_char: | ||
| 2955 | emit->append( new Chuck_Instr_Reg_Push_Imm( str2char(exp->chr, exp->linepos ) ) ); | ||
| 2956 | break; | ||
| 2957 | |||
| 2958 | case ae_primary_array: | ||
| 2959 | if( !emit_engine_emit_array_lit( emit, exp->array ) ) | ||
| 2960 | return FALSE; | ||
| 2961 | break; | ||
| 2962 | |||
| 2963 | case ae_primary_complex: | ||
| 2964 | if( !emit_engine_emit_complex_lit( emit, exp->complex ) ) | ||
| 2965 | return FALSE; | ||
| 2966 | break; | ||
| 2967 | |||
| 2968 | case ae_primary_polar: | ||
| 2969 | if( !emit_engine_emit_polar_lit( emit, exp->polar ) ) | ||
| 2970 | return FALSE; | ||
| 2971 | break; | ||
| 2972 | |||
| 2973 | case ae_primary_vec: | ||
| 2974 | if( !emit_engine_emit_vec_lit( emit, exp->vec ) ) | ||
| 2975 | return FALSE; | ||
| 2976 | break; | ||
| 2977 | |||
| 2978 | case ae_primary_exp: | ||
| 2979 | if( !emit_engine_emit_exp( emit, exp->exp ) ) | ||
| 2980 | return FALSE; | ||
| 2981 | break; | ||
| 2982 | |||
| 2983 | case ae_primary_hack: | ||
| 2984 | { | ||
| 2985 | a_Exp e = exp->exp; | ||
| 2986 | // emit the expression | ||
| 2987 | if( !emit_engine_emit_exp( emit, e ) ) | ||
| 2988 | return FALSE; | ||
| 2989 | std::vector<Chuck_Type *> types; | ||
| 2990 | |||
| 2991 | while( e != NULL ) | ||
| 2992 | { | ||
| 2993 | types.push_back( e->type ); | ||
| 2994 | e = e->next; | ||
| 2995 | } | ||
| 2996 | |||
| 2997 | // emit hack | ||
| 2998 | emit->append( new Chuck_Instr_Gack( types ) ); | ||
| 2999 | |||
| 3000 | break; | ||
| 3001 | } | ||
| 3002 | |||
| 3003 | // ge (april 2012): nil is void, so nothing to emit; TODO: check it (added 1.3.0.0) | ||
| 3004 | case ae_primary_nil: | ||
| 3005 | break; | ||
| 3006 | } | ||
| 3007 | |||
| 3008 | return TRUE; | ||
| 3009 | } | ||
| 3010 | |||
| 3011 | |||
| 3012 | |||
| 3013 | |||
| 3014 | //----------------------------------------------------------------------------- | ||
| 3015 | // name: emit_engine_emit_array_lit() | ||
| 3016 | // desc: ... | ||
| 3017 | //----------------------------------------------------------------------------- | ||
| 3018 | t_CKBOOL emit_engine_emit_array_lit( Chuck_Emitter * emit, a_Array_Sub array ) | ||
| 3019 | { | ||
| 3020 | // go through and emit the expressions | ||
| 3021 | if( !emit_engine_emit_exp( emit, array->exp_list ) ) | ||
| 3022 | return FALSE; | ||
| 3023 | |||
| 3024 | // count the number | ||
| 3025 | a_Exp e = array->exp_list; | ||
| 3026 | t_CKUINT count = 0; | ||
| 3027 | // loop over | ||
| 3028 | while( e ) { count++; e = e->next; } | ||
| 3029 | |||
| 3030 | // the type | ||
| 3031 | e = array->exp_list; | ||
| 3032 | Chuck_Type * type = e->cast_to ? e->cast_to : e->type; | ||
| 3033 | |||
| 3034 | // construct array dynamically | ||
| 3035 | Chuck_Instr * instr = NULL; | ||
| 3036 | emit->append( instr = new Chuck_Instr_Array_Init( emit->env, type, count ) ); | ||
| 3037 | instr->set_linepos( array->linepos ); | ||
| 3038 | |||
| 3039 | return TRUE; | ||
| 3040 | } | ||
| 3041 | |||
| 3042 | |||
| 3043 | |||
| 3044 | |||
| 3045 | //----------------------------------------------------------------------------- | ||
| 3046 | // name: emit_engine_emit_complex_lit() | ||
| 3047 | // desc: ... | ||
| 3048 | //----------------------------------------------------------------------------- | ||
| 3049 | t_CKBOOL emit_engine_emit_complex_lit( Chuck_Emitter * emit, a_Complex val ) | ||
| 3050 | { | ||
| 3051 | // go through and emit the real and imaginary | ||
| 3052 | if( !emit_engine_emit_exp( emit, val->re ) ) | ||
| 3053 | return FALSE; | ||
| 3054 | |||
| 3055 | // imaginary (not needed since linked after real | ||
| 3056 | // if( !emit_engine_emit_exp( emit, val->im ) ) | ||
| 3057 | // return FALSE; | ||
| 3058 | |||
| 3059 | return TRUE; | ||
| 3060 | } | ||
| 3061 | |||
| 3062 | |||
| 3063 | |||
| 3064 | |||
| 3065 | //----------------------------------------------------------------------------- | ||
| 3066 | // name: emit_engine_emit_polar_lit() | ||
| 3067 | // desc: ... | ||
| 3068 | //----------------------------------------------------------------------------- | ||
| 3069 | t_CKBOOL emit_engine_emit_polar_lit( Chuck_Emitter * emit, a_Polar val ) | ||
| 3070 | { | ||
| 3071 | // go through and emit the mod and phase | ||
| 3072 | if( !emit_engine_emit_exp( emit, val->mod ) ) | ||
| 3073 | return FALSE; | ||
| 3074 | |||
| 3075 | // phase (not needed since linked after mod) | ||
| 3076 | // if( !emit_engine_emit_exp( emit, val->phase ) ) | ||
| 3077 | // return FALSE; | ||
| 3078 | |||
| 3079 | return TRUE; | ||
| 3080 | } | ||
| 3081 | |||
| 3082 | |||
| 3083 | |||
| 3084 | |||
| 3085 | //----------------------------------------------------------------------------- | ||
| 3086 | // name: emit_engine_emit_vec_lit() | ||
| 3087 | // desc: ... | ||
| 3088 | //----------------------------------------------------------------------------- | ||
| 3089 | t_CKBOOL emit_engine_emit_vec_lit( Chuck_Emitter * emit, a_Vec val ) | ||
| 3090 | { | ||
| 3091 | // go through and emit the mod and phase | ||
| 3092 | if( !emit_engine_emit_exp( emit, val->args ) ) | ||
| 3093 | return FALSE; | ||
| 3094 | |||
| 3095 | // zero pad if needed | ||
| 3096 | t_CKINT n = 3 - val->numdims; | ||
| 3097 | // any remaining | ||
| 3098 | while( n > 0 ) | ||
| 3099 | { | ||
| 3100 | // emit a zero float | ||
| 3101 | emit->append( new Chuck_Instr_Reg_Push_Imm2( 0 ) ); | ||
| 3102 | // decrement | ||
| 3103 | n--; | ||
| 3104 | } | ||
| 3105 | |||
| 3106 | return TRUE; | ||
| 3107 | } | ||
| 3108 | |||
| 3109 | |||
| 3110 | |||
| 3111 | |||
| 3112 | //----------------------------------------------------------------------------- | ||
| 3113 | // name: emit_engine_emit_exp_cast() | ||
| 3114 | // desc: ... | ||
| 3115 | //----------------------------------------------------------------------------- | ||
| 3116 | t_CKBOOL emit_engine_emit_exp_cast( Chuck_Emitter * emit, a_Exp_Cast cast ) | ||
| 3117 | { | ||
| 3118 | Chuck_Type * to = cast->self->type; | ||
| 3119 | Chuck_Type * from = cast->exp->type; | ||
| 3120 | |||
| 3121 | // emit the exp | ||
| 3122 | if( !emit_engine_emit_exp( emit, cast->exp ) ) | ||
| 3123 | return FALSE; | ||
| 3124 | |||
| 3125 | // the actual work to be done | ||
| 3126 | return emit_engine_emit_cast( emit, to, from ); | ||
| 3127 | } | ||
| 3128 | |||
| 3129 | |||
| 3130 | |||
| 3131 | |||
| 3132 | //----------------------------------------------------------------------------- | ||
| 3133 | // name: emit_engine_emit_cast() | ||
| 3134 | // desc: ... | ||
| 3135 | //----------------------------------------------------------------------------- | ||
| 3136 | t_CKBOOL emit_engine_emit_cast( Chuck_Emitter * emit, | ||
| 3137 | Chuck_Type * to, Chuck_Type * from ) | ||
| 3138 | { | ||
| 3139 | // if type is already the same | ||
| 3140 | if( equals( to, from ) ) | ||
| 3141 | return TRUE; | ||
| 3142 | |||
| 3143 | // int to float | ||
| 3144 | if( equals( to, emit->env->t_int ) && equals( from, emit->env->t_float ) ) | ||
| 3145 | emit->append( new Chuck_Instr_Cast_double2int ); | ||
| 3146 | // float to int | ||
| 3147 | else if( equals( to, emit->env->t_float ) && equals( from, emit->env->t_int ) ) | ||
| 3148 | emit->append( new Chuck_Instr_Cast_int2double ); | ||
| 3149 | else if( equals( to, emit->env->t_complex ) && equals( from, emit->env->t_int ) ) | ||
| 3150 | emit->append( new Chuck_Instr_Cast_int2complex ); | ||
| 3151 | else if( equals( to, emit->env->t_polar ) && equals( from, emit->env->t_int ) ) | ||
| 3152 | emit->append( new Chuck_Instr_Cast_int2polar ); | ||
| 3153 | else if( equals( to, emit->env->t_complex ) && equals( from, emit->env->t_float ) ) | ||
| 3154 | emit->append( new Chuck_Instr_Cast_double2complex ); | ||
| 3155 | else if( equals( to, emit->env->t_polar ) && equals( from, emit->env->t_float ) ) | ||
| 3156 | emit->append( new Chuck_Instr_Cast_double2polar ); | ||
| 3157 | else if( equals( to, emit->env->t_polar ) && equals( from, emit->env->t_complex ) ) | ||
| 3158 | emit->append( new Chuck_Instr_Cast_complex2polar ); | ||
| 3159 | else if( equals( to, emit->env->t_complex ) && equals( from, emit->env->t_polar ) ) | ||
| 3160 | emit->append( new Chuck_Instr_Cast_polar2complex ); | ||
| 3161 | else if( equals( to, emit->env->t_vec3 ) && equals( from, emit->env->t_vec4 ) ) | ||
| 3162 | emit->append( new Chuck_Instr_Cast_vec4tovec3 ); | ||
| 3163 | else if( equals( to, emit->env->t_vec4 ) && equals( from, emit->env->t_vec3 ) ) | ||
| 3164 | emit->append( new Chuck_Instr_Cast_vec3tovec4 ); | ||
| 3165 | else if( equals( to, emit->env->t_string ) && isa( from, emit->env->t_object ) && !isa( from, emit->env->t_string ) ) | ||
| 3166 | emit->append( new Chuck_Instr_Cast_object2string ); | ||
| 3167 | // up cast - do nothing | ||
| 3168 | else if( !isa( to, from ) && !isa( from, to ) ) | ||
| 3169 | { | ||
| 3170 | EM_error2( 0, "(emit): internal error: cannot cast type '%s' to '%s'", | ||
| 3171 | from->c_name(), to->c_name() ); | ||
| 3172 | return FALSE; | ||
| 3173 | } | ||
| 3174 | |||
| 3175 | return TRUE; | ||
| 3176 | } | ||
| 3177 | |||
| 3178 | |||
| 3179 | |||
| 3180 | |||
| 3181 | //----------------------------------------------------------------------------- | ||
| 3182 | // name: emit_engine_emit_exp_postfix() | ||
| 3183 | // desc: ... | ||
| 3184 | //----------------------------------------------------------------------------- | ||
| 3185 | t_CKBOOL emit_engine_emit_exp_postfix( Chuck_Emitter * emit, a_Exp_Postfix postfix ) | ||
| 3186 | { | ||
| 3187 | // emit the exp | ||
| 3188 | if( !emit_engine_emit_exp( emit, postfix->exp ) ) | ||
| 3189 | return FALSE; | ||
| 3190 | |||
| 3191 | // emit | ||
| 3192 | switch( postfix->op ) | ||
| 3193 | { | ||
| 3194 | case ae_op_plusplus: | ||
| 3195 | if( equals( postfix->exp->type, emit->env->t_int ) ) | ||
| 3196 | emit->append( new Chuck_Instr_PostInc_int ); | ||
| 3197 | else | ||
| 3198 | { | ||
| 3199 | EM_error2( postfix->linepos, | ||
| 3200 | "(emit): internal error: unhandled type '%s' for post '++' operator", | ||
| 3201 | postfix->exp->type->c_name() ); | ||
| 3202 | return FALSE; | ||
| 3203 | } | ||
| 3204 | break; | ||
| 3205 | |||
| 3206 | case ae_op_minusminus: | ||
| 3207 | if( equals( postfix->exp->type, emit->env->t_int ) ) | ||
| 3208 | emit->append( new Chuck_Instr_PostDec_int ); | ||
| 3209 | else | ||
| 3210 | { | ||
| 3211 | EM_error2( postfix->linepos, | ||
| 3212 | "(emit): internal error: unhandled type '%s' for post '--' operator", | ||
| 3213 | postfix->exp->type->c_name() ); | ||
| 3214 | return FALSE; | ||
| 3215 | } | ||
| 3216 | break; | ||
| 3217 | |||
| 3218 | default: | ||
| 3219 | EM_error2( postfix->linepos, | ||
| 3220 | "(emit): internal error: unhandled postfix operator '%s'", | ||
| 3221 | op2str( postfix->op ) ); | ||
| 3222 | return FALSE; | ||
| 3223 | } | ||
| 3224 | |||
| 3225 | return TRUE; | ||
| 3226 | } | ||
| 3227 | |||
| 3228 | |||
| 3229 | |||
| 3230 | |||
| 3231 | //----------------------------------------------------------------------------- | ||
| 3232 | // name: emit_engine_emit_exp_dur() | ||
| 3233 | // desc: ... | ||
| 3234 | //----------------------------------------------------------------------------- | ||
| 3235 | t_CKBOOL emit_engine_emit_exp_dur( Chuck_Emitter * emit, a_Exp_Dur dur ) | ||
| 3236 | { | ||
| 3237 | // emit base | ||
| 3238 | if( !emit_engine_emit_exp( emit, dur->base ) ) | ||
| 3239 | return FALSE; | ||
| 3240 | |||
| 3241 | // cast | ||
| 3242 | if( equals( dur->base->type, emit->env->t_int ) ) | ||
| 3243 | emit->append( new Chuck_Instr_Cast_int2double ); | ||
| 3244 | |||
| 3245 | // emit unit | ||
| 3246 | if( !emit_engine_emit_exp( emit, dur->unit ) ) | ||
| 3247 | return FALSE; | ||
| 3248 | |||
| 3249 | // multiply | ||
| 3250 | emit->append( new Chuck_Instr_Times_double ); | ||
| 3251 | |||
| 3252 | return TRUE; | ||
| 3253 | } | ||
| 3254 | |||
| 3255 | |||
| 3256 | |||
| 3257 | |||
| 3258 | //----------------------------------------------------------------------------- | ||
| 3259 | // name: emit_engine_emit_exp_array() | ||
| 3260 | // desc: ... | ||
| 3261 | //----------------------------------------------------------------------------- | ||
| 3262 | t_CKBOOL emit_engine_emit_exp_array( Chuck_Emitter * emit, a_Exp_Array array ) | ||
| 3263 | { | ||
| 3264 | Chuck_Type * type = NULL, * base_type = NULL; | ||
| 3265 | t_CKUINT depth = 0; | ||
| 3266 | a_Array_Sub sub = NULL; | ||
| 3267 | a_Exp exp = NULL; | ||
| 3268 | t_CKBOOL is_var = FALSE; | ||
| 3269 | t_CKBOOL is_str = FALSE; | ||
| 3270 | |||
| 3271 | // get the type | ||
| 3272 | type = array->self->type; | ||
| 3273 | // get the base type | ||
| 3274 | base_type = array->base->type; | ||
| 3275 | // emit as addr? | ||
| 3276 | is_var = array->self->emit_var; | ||
| 3277 | // get the dimension | ||
| 3278 | depth = base_type->array_depth - type->array_depth; | ||
| 3279 | // make sure | ||
| 3280 | if( depth == 0 ) | ||
| 3281 | { | ||
| 3282 | EM_error2( array->linepos, | ||
| 3283 | "(emit): internal error: array with 0 depth..." ); | ||
| 3284 | return FALSE; | ||
| 3285 | } | ||
| 3286 | // get the sub | ||
| 3287 | sub = array->indices; | ||
| 3288 | if( !sub ) | ||
| 3289 | { | ||
| 3290 | EM_error2( array->linepos, | ||
| 3291 | "(emit): internal error: NULL array sub..." ); | ||
| 3292 | return FALSE; | ||
| 3293 | } | ||
| 3294 | // get the exp list | ||
| 3295 | exp = sub->exp_list; | ||
| 3296 | if( !exp ) | ||
| 3297 | { | ||
| 3298 | EM_error2( array->linepos, | ||
| 3299 | "(emit): internal error: NULL array exp..." ); | ||
| 3300 | return FALSE; | ||
| 3301 | } | ||
| 3302 | |||
| 3303 | // emit the base (it should be a pointer to array) | ||
| 3304 | if( !emit_engine_emit_exp( emit, array->base ) ) | ||
| 3305 | return FALSE; | ||
| 3306 | |||
| 3307 | // emit the exp list | ||
| 3308 | if( !emit_engine_emit_exp( emit, exp ) ) | ||
| 3309 | return FALSE; | ||
| 3310 | |||
| 3311 | // find out first element | ||
| 3312 | if( isa( exp->type, emit->env->t_string ) ) | ||
| 3313 | is_str = TRUE; | ||
| 3314 | |||
| 3315 | // make sure | ||
| 3316 | // ISSUE: 64-bit (fixed 1.3.1.0) | ||
| 3317 | if( type->size != sz_INT && type->size != sz_FLOAT && type->size != sz_COMPLEX && | ||
| 3318 | type->size != sz_VEC3 && type->size != sz_VEC4 ) | ||
| 3319 | { | ||
| 3320 | EM_error2( array->linepos, | ||
| 3321 | "(emit): internal error: array with datasize of %i...", type->size ); | ||
| 3322 | return FALSE; | ||
| 3323 | } | ||
| 3324 | |||
| 3325 | // check the depth | ||
| 3326 | if( depth == 1 ) | ||
| 3327 | { | ||
| 3328 | // the pointer | ||
| 3329 | Chuck_Instr * instr = NULL; | ||
| 3330 | // emit the array access (1.3.1.0: use getkindof instead of type->size) | ||
| 3331 | if( is_str ) | ||
| 3332 | emit->append( instr = new Chuck_Instr_Array_Map_Access( getkindof(emit->env, type), is_var ) ); | ||
| 3333 | else | ||
| 3334 | emit->append( instr = new Chuck_Instr_Array_Access( getkindof(emit->env, type), is_var ) ); | ||
| 3335 | instr->set_linepos( array->linepos ); | ||
| 3336 | } | ||
| 3337 | else | ||
| 3338 | { | ||
| 3339 | // the pointer | ||
| 3340 | Chuck_Instr_Array_Access_Multi * aam = NULL; | ||
| 3341 | // emit the multi array access (1.3.1.0: use getkindof instead of type->size) | ||
| 3342 | emit->append( aam = new Chuck_Instr_Array_Access_Multi( depth, getkindof(emit->env, type), is_var ) ); | ||
| 3343 | aam->set_linepos( array->linepos ); | ||
| 3344 | // add type info (1.3.1.0) -- to support mixed string & int indexing (thanks Robin Haberkorn) | ||
| 3345 | a_Exp e = exp; | ||
| 3346 | while( e ) | ||
| 3347 | { | ||
| 3348 | // check if string | ||
| 3349 | aam->indexIsAssociative().push_back( isa( exp->type, emit->env->t_string ) ); | ||
| 3350 | // next | ||
| 3351 | e = e->next; | ||
| 3352 | } | ||
| 3353 | } | ||
| 3354 | |||
| 3355 | // TODO: variable? | ||
| 3356 | |||
| 3357 | return TRUE; | ||
| 3358 | } | ||
| 3359 | |||
| 3360 | |||
| 3361 | |||
| 3362 | |||
| 3363 | //----------------------------------------------------------------------------- | ||
| 3364 | // name: emit_engine_emit_exp_func_call() | ||
| 3365 | // desc: ... | ||
| 3366 | //----------------------------------------------------------------------------- | ||
| 3367 | t_CKBOOL emit_engine_emit_exp_func_call( Chuck_Emitter * emit, | ||
| 3368 | Chuck_Func * func, | ||
| 3369 | Chuck_Type * type, | ||
| 3370 | int linepos, | ||
| 3371 | t_CKBOOL spork ) | ||
| 3372 | { | ||
| 3373 | // is a member? | ||
| 3374 | t_CKBOOL is_member = func->is_member; | ||
| 3375 | |||
| 3376 | // if member | ||
| 3377 | //if( is_member ) | ||
| 3378 | //{ | ||
| 3379 | // // this | ||
| 3380 | // emit->append( new Chuck_Instr_Reg_Push_This ); | ||
| 3381 | //} | ||
| 3382 | |||
| 3383 | // translate to code | ||
| 3384 | emit->append( new Chuck_Instr_Func_To_Code ); | ||
| 3385 | // emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)func->code ) ); | ||
| 3386 | // push the local stack depth - local variables | ||
| 3387 | emit->append( new Chuck_Instr_Reg_Push_Imm( emit->code->frame->curr_offset ) ); | ||
| 3388 | |||
| 3389 | // TODO: member functions and static functions | ||
| 3390 | // call the function | ||
| 3391 | t_CKUINT size = type->size; | ||
| 3392 | t_CKUINT kind = getkindof( emit->env, type ); // added 1.3.1.0 | ||
| 3393 | |||
| 3394 | // the pointer | ||
| 3395 | Chuck_Instr * instr = NULL; | ||
| 3396 | if( func->def->s_type == ae_func_builtin ) | ||
| 3397 | { | ||
| 3398 | // ISSUE: 64-bit (fixed 1.3.1.0) | ||
| 3399 | if( size == 0 || size == sz_INT || size == sz_FLOAT || size == sz_COMPLEX || | ||
| 3400 | size == sz_VEC3 || sz_VEC4 ) | ||
| 3401 | { | ||
| 3402 | // is member (1.3.1.0: changed to use kind instead of size) | ||
| 3403 | if( is_member ) | ||
| 3404 | emit->append( instr = new Chuck_Instr_Func_Call_Member( kind ) ); | ||
| 3405 | else | ||
| 3406 | emit->append( instr = new Chuck_Instr_Func_Call_Static( kind ) ); | ||
| 3407 | } | ||
| 3408 | else | ||
| 3409 | { | ||
| 3410 | EM_error2( linepos, | ||
| 3411 | "(emit): internal error: %i func call not handled", | ||
| 3412 | size ); | ||
| 3413 | return FALSE; | ||
| 3414 | } | ||
| 3415 | } | ||
| 3416 | else | ||
| 3417 | { | ||
| 3418 | emit->append( instr = new Chuck_Instr_Func_Call ); | ||
| 3419 | } | ||
| 3420 | instr->set_linepos(linepos); | ||
| 3421 | |||
| 3422 | return TRUE; | ||
| 3423 | } | ||
| 3424 | |||
| 3425 | |||
| 3426 | |||
| 3427 | |||
| 3428 | //----------------------------------------------------------------------------- | ||
| 3429 | // name: emit_engine_emit_func_args() | ||
| 3430 | // desc: ... | ||
| 3431 | //----------------------------------------------------------------------------- | ||
| 3432 | t_CKBOOL emit_engine_emit_func_args( Chuck_Emitter * emit, | ||
| 3433 | a_Exp_Func_Call func_call ) | ||
| 3434 | { | ||
| 3435 | // emit the args (TRUE for doAddRef added 1.3.0.0) | ||
| 3436 | if( !emit_engine_emit_exp( emit, func_call->args, TRUE ) ) | ||
| 3437 | { | ||
| 3438 | EM_error2( func_call->linepos, | ||
| 3439 | "(emit): internal error in emitting function call arguments..." ); | ||
| 3440 | return FALSE; | ||
| 3441 | } | ||
| 3442 | |||
| 3443 | return TRUE; | ||
| 3444 | } | ||
| 3445 | |||
| 3446 | |||
| 3447 | |||
| 3448 | |||
| 3449 | //----------------------------------------------------------------------------- | ||
| 3450 | // name: emit_engine_emit_exp_func_call() | ||
| 3451 | // desc: ... | ||
| 3452 | //----------------------------------------------------------------------------- | ||
| 3453 | t_CKBOOL emit_engine_emit_exp_func_call( Chuck_Emitter * emit, | ||
| 3454 | a_Exp_Func_Call func_call, | ||
| 3455 | t_CKBOOL spork ) | ||
| 3456 | { | ||
| 3457 | // note: spork situations are now taken care in exp_spork... | ||
| 3458 | // please look at that one before modifying this one! | ||
| 3459 | |||
| 3460 | // make sure there are args, and not sporking | ||
| 3461 | if( func_call->args && !spork ) | ||
| 3462 | { | ||
| 3463 | if( !emit_engine_emit_func_args( emit, func_call ) ) | ||
| 3464 | return FALSE; | ||
| 3465 | } | ||
| 3466 | |||
| 3467 | // emit func | ||
| 3468 | if( !emit_engine_emit_exp( emit, func_call->func ) ) | ||
| 3469 | { | ||
| 3470 | EM_error2( func_call->linepos, | ||
| 3471 | "(emit): internal error in evaluating function call..." ); | ||
| 3472 | return FALSE; | ||
| 3473 | } | ||
| 3474 | |||
| 3475 | // the rest | ||
| 3476 | return emit_engine_emit_exp_func_call( emit, func_call->ck_func, func_call->ret_type, | ||
| 3477 | func_call->linepos, spork ); | ||
| 3478 | } | ||
| 3479 | |||
| 3480 | |||
| 3481 | |||
| 3482 | |||
| 3483 | //----------------------------------------------------------------------------- | ||
| 3484 | // name: emit_engine_emit_dot_member_special() | ||
| 3485 | // desc: emit special dot member: complex, polar, vec3, vec4 | ||
| 3486 | //----------------------------------------------------------------------------- | ||
| 3487 | t_CKBOOL emit_engine_emit_exp_dot_member_special( Chuck_Emitter * emit, | ||
| 3488 | a_Exp_Dot_Member member ) | ||
| 3489 | { | ||
| 3490 | // whether to emit addr or value | ||
| 3491 | t_CKBOOL emit_addr = member->self->emit_var; | ||
| 3492 | |||
| 3493 | // special case: complex and polar | ||
| 3494 | if( member->t_base->xid == te_complex ) | ||
| 3495 | { | ||
| 3496 | // mark to emit addr | ||
| 3497 | if( member->base->s_meta == ae_meta_var ) | ||
| 3498 | member->base->emit_var = TRUE; | ||
| 3499 | else if( emit_addr ) | ||
| 3500 | { | ||
| 3501 | EM_error2( member->base->linepos, | ||
| 3502 | "(emit): cannot assign value to literal 'complex' value..." ); | ||
| 3503 | return FALSE; | ||
| 3504 | } | ||
| 3505 | |||
| 3506 | // emit the base | ||
| 3507 | if( !emit_engine_emit_exp( emit, member->base ) ) | ||
| 3508 | return FALSE; | ||
| 3509 | |||
| 3510 | string str = S_name(member->xid); | ||
| 3511 | // check | ||
| 3512 | if( str == "re" ) | ||
| 3513 | emit->append( new Chuck_Instr_Dot_Cmp_First( member->base->s_meta == ae_meta_var, emit_addr ) ); | ||
| 3514 | else if( str == "im" ) | ||
| 3515 | emit->append( new Chuck_Instr_Dot_Cmp_Second( member->base->s_meta == ae_meta_var, emit_addr ) ); | ||
| 3516 | else | ||
| 3517 | goto check_func; | ||
| 3518 | |||
| 3519 | // done | ||
| 3520 | return TRUE; | ||
| 3521 | } | ||
| 3522 | else if( member->t_base->xid == te_polar ) | ||
| 3523 | { | ||
| 3524 | // mark to emit addr | ||
| 3525 | if( member->base->s_meta == ae_meta_var ) | ||
| 3526 | member->base->emit_var = TRUE; | ||
| 3527 | else if( emit_addr ) | ||
| 3528 | { | ||
| 3529 | EM_error2( member->base->linepos, | ||
| 3530 | "(emit): cannot assign value to literal 'polar' value..." ); | ||
| 3531 | return FALSE; | ||
| 3532 | } | ||
| 3533 | |||
| 3534 | // emit the base | ||
| 3535 | if( !emit_engine_emit_exp( emit, member->base ) ) | ||
| 3536 | return FALSE; | ||
| 3537 | |||
| 3538 | string str = S_name(member->xid); | ||
| 3539 | // check | ||
| 3540 | if( str == "mag" ) | ||
| 3541 | emit->append( new Chuck_Instr_Dot_Cmp_First( member->base->s_meta == ae_meta_var, emit_addr ) ); | ||
| 3542 | else if( str == "phase" ) | ||
| 3543 | emit->append( new Chuck_Instr_Dot_Cmp_Second( member->base->s_meta == ae_meta_var, emit_addr ) ); | ||
| 3544 | else | ||
| 3545 | goto check_func; | ||
| 3546 | |||
| 3547 | // done | ||
| 3548 | return TRUE; | ||
| 3549 | } | ||
| 3550 | else if( member->t_base->xid == te_vec3 || member->t_base->xid == te_vec4 ) | ||
| 3551 | { | ||
| 3552 | // mark to emit addr | ||
| 3553 | if( member->base->s_meta == ae_meta_var ) | ||
| 3554 | member->base->emit_var = TRUE; | ||
| 3555 | else if( emit_addr ) | ||
| 3556 | { | ||
| 3557 | EM_error2( member->base->linepos, | ||
| 3558 | "(emit): cannot assign value to literal '%s' value...", | ||
| 3559 | member->t_base->c_name() ); | ||
| 3560 | return FALSE; | ||
| 3561 | } | ||
| 3562 | |||
| 3563 | // emit the base | ||
| 3564 | if( !emit_engine_emit_exp( emit, member->base ) ) | ||
| 3565 | return FALSE; | ||
| 3566 | |||
| 3567 | string str = S_name(member->xid); | ||
| 3568 | // check for .xyz[w] .rgb[a] .value/goal/slew | ||
| 3569 | if( str == "x" || str == "r" || str == "value" ) | ||
| 3570 | emit->append( new Chuck_Instr_Dot_Cmp_First( member->base->s_meta == ae_meta_var, emit_addr ) ); | ||
| 3571 | else if( str == "y" || str == "g" || str == "goal" ) | ||
| 3572 | emit->append( new Chuck_Instr_Dot_Cmp_Second( member->base->s_meta == ae_meta_var, emit_addr ) ); | ||
| 3573 | else if( str == "z" || str == "b" || str == "slew" ) | ||
| 3574 | emit->append( new Chuck_Instr_Dot_Cmp_Third( member->base->s_meta == ae_meta_var, emit_addr ) ); | ||
| 3575 | else if( member->t_base->xid == te_vec4 && ( str == "w" || str == "a" ) ) | ||
| 3576 | emit->append( new Chuck_Instr_Dot_Cmp_Fourth( member->base->s_meta == ae_meta_var, emit_addr ) ); | ||
| 3577 | else | ||
| 3578 | goto check_func; | ||
| 3579 | |||
| 3580 | // done | ||
| 3581 | return TRUE; | ||
| 3582 | } | ||
| 3583 | |||
| 3584 | // should not get here | ||
| 3585 | EM_error2( member->base->linepos, | ||
| 3586 | "(emit): internal error in lit_special()..." ); | ||
| 3587 | |||
| 3588 | return FALSE; | ||
| 3589 | |||
| 3590 | //----------------------------------------------------------------------------- | ||
| 3591 | // goto: check for special member functions, 1.3.5.3 | ||
| 3592 | //----------------------------------------------------------------------------- | ||
| 3593 | check_func: | ||
| 3594 | |||
| 3595 | // the type of the base | ||
| 3596 | Chuck_Type * t_base = member->t_base; | ||
| 3597 | // is the base a class/namespace or a variable | ||
| 3598 | t_CKBOOL base_static = isa( member->t_base, emit->env->t_class ); | ||
| 3599 | // a function | ||
| 3600 | Chuck_Func * func = NULL; | ||
| 3601 | // a non-function value | ||
| 3602 | Chuck_Value * value = NULL; | ||
| 3603 | // the offset | ||
| 3604 | t_CKUINT offset = 0; | ||
| 3605 | |||
| 3606 | // check error | ||
| 3607 | if( base_static ) | ||
| 3608 | { | ||
| 3609 | // should not get here | ||
| 3610 | EM_error2( member->base->linepos, | ||
| 3611 | "(emit): internal error in lit_special(): base static" ); | ||
| 3612 | // done | ||
| 3613 | return FALSE; | ||
| 3614 | } | ||
| 3615 | |||
| 3616 | if( !isfunc( emit->env, member->self->type ) ) | ||
| 3617 | { | ||
| 3618 | // should not get here | ||
| 3619 | EM_error2( member->base->linepos, | ||
| 3620 | "(emit): internal error in lit_special(): not member func" ); | ||
| 3621 | // done | ||
| 3622 | return FALSE; | ||
| 3623 | } | ||
| 3624 | |||
| 3625 | // get the func | ||
| 3626 | value = type_engine_find_value( t_base, member->xid ); | ||
| 3627 | func = value->func_ref; | ||
| 3628 | // make sure it's there | ||
| 3629 | assert( func != NULL ); | ||
| 3630 | |||
| 3631 | // NOTE: base already emitted earier in this function (and as var) | ||
| 3632 | |||
| 3633 | // check base; 1.3.5.3 | ||
| 3634 | if( member->base->s_meta == ae_meta_value ) // is literal | ||
| 3635 | { | ||
| 3636 | // dup the value as pointer (as faux-'this' pointer) | ||
| 3637 | emit->append( new Chuck_Instr_Reg_Dup_Last_As_Pointer( t_base->size / sz_WORD ) ); | ||
| 3638 | } | ||
| 3639 | else // normal object | ||
| 3640 | { | ||
| 3641 | // dup the base pointer (as 'this' argument -- special case primitive) | ||
| 3642 | emit->append( new Chuck_Instr_Reg_Dup_Last ); | ||
| 3643 | } | ||
| 3644 | |||
| 3645 | // find the offset for virtual table | ||
| 3646 | offset = func->vt_index; | ||
| 3647 | // emit the function | ||
| 3648 | emit->append( new Chuck_Instr_Dot_Primitive_Func( (t_CKUINT)func ) ); | ||
| 3649 | |||
| 3650 | return TRUE; | ||
| 3651 | } | ||
| 3652 | |||
| 3653 | |||
| 3654 | |||
| 3655 | |||
| 3656 | //----------------------------------------------------------------------------- | ||
| 3657 | // name: emit_engine_emit_dot_member() | ||
| 3658 | // desc: ... | ||
| 3659 | //----------------------------------------------------------------------------- | ||
| 3660 | t_CKBOOL emit_engine_emit_exp_dot_member( Chuck_Emitter * emit, | ||
| 3661 | a_Exp_Dot_Member member ) | ||
| 3662 | { | ||
| 3663 | // the type of the base | ||
| 3664 | Chuck_Type * t_base = NULL; | ||
| 3665 | // whether to emit addr or value | ||
| 3666 | t_CKBOOL emit_addr = member->self->emit_var; | ||
| 3667 | // is the base a class/namespace or a variable | ||
| 3668 | t_CKBOOL base_static = isa( member->t_base, emit->env->t_class ); | ||
| 3669 | // a function | ||
| 3670 | Chuck_Func * func = NULL; | ||
| 3671 | // a non-function value | ||
| 3672 | Chuck_Value * value = NULL; | ||
| 3673 | // the offset | ||
| 3674 | t_CKUINT offset = 0; | ||
| 3675 | |||
| 3676 | // the pointer | ||
| 3677 | Chuck_Instr * instr = NULL; | ||
| 3678 | |||
| 3679 | // type of the base | ||
| 3680 | t_CKUINT tbase_xid = member->t_base->xid; | ||
| 3681 | // switch on it | ||
| 3682 | switch( tbase_xid ) | ||
| 3683 | { | ||
| 3684 | case te_complex: | ||
| 3685 | case te_polar: | ||
| 3686 | case te_vec3: | ||
| 3687 | case te_vec4: | ||
| 3688 | // emit special | ||
| 3689 | return emit_engine_emit_exp_dot_member_special( emit, member ); | ||
| 3690 | // done | ||
| 3691 | break; | ||
| 3692 | } | ||
| 3693 | |||
| 3694 | // actual type - if base is class name its type is actually 'class' | ||
| 3695 | // to get the actual type use actual_type | ||
| 3696 | t_base = base_static ? member->t_base->actual_type : member->t_base; | ||
| 3697 | |||
| 3698 | // make sure that the base type is object | ||
| 3699 | assert( t_base->info != NULL ); | ||
| 3700 | |||
| 3701 | // if base is static | ||
| 3702 | if( !base_static ) | ||
| 3703 | { | ||
| 3704 | // if is a func | ||
| 3705 | if( isfunc( emit->env, member->self->type ) ) | ||
| 3706 | { | ||
| 3707 | // get the func | ||
| 3708 | value = type_engine_find_value( t_base, member->xid ); | ||
| 3709 | func = value->func_ref; | ||
| 3710 | // make sure it's there | ||
| 3711 | assert( func != NULL ); | ||
| 3712 | |||
| 3713 | // is the func static? | ||
| 3714 | if( func->is_member ) | ||
| 3715 | { | ||
| 3716 | // emit the base (TODO: return on error?) | ||
| 3717 | emit_engine_emit_exp( emit, member->base ); | ||
| 3718 | // dup the base pointer (as 'this' argument) | ||
| 3719 | emit->append( new Chuck_Instr_Reg_Dup_Last ); | ||
| 3720 | // find the offset for virtual table | ||
| 3721 | offset = func->vt_index; | ||
| 3722 | // emit the function | ||
| 3723 | emit->append( instr = new Chuck_Instr_Dot_Member_Func( offset ) ); | ||
| 3724 | instr->set_linepos( member->linepos ); | ||
| 3725 | } | ||
| 3726 | else | ||
| 3727 | { | ||
| 3728 | // emit the type | ||
| 3729 | emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)t_base ) ); | ||
| 3730 | // emit the static function | ||
| 3731 | emit->append( new Chuck_Instr_Dot_Static_Func( func ) ); | ||
| 3732 | } | ||
| 3733 | } | ||
| 3734 | else | ||
| 3735 | { | ||
| 3736 | // get the value | ||
| 3737 | // value = t_base->info->lookup_value( member->xid, FALSE ); | ||
| 3738 | value = type_engine_find_value( t_base, member->xid ); | ||
| 3739 | // make sure it's there | ||
| 3740 | assert( value != NULL ); | ||
| 3741 | |||
| 3742 | // find the offset for data | ||
| 3743 | offset = value->offset; | ||
| 3744 | |||
| 3745 | // is the value static? | ||
| 3746 | if( value->is_member ) | ||
| 3747 | { | ||
| 3748 | // emit the base (TODO: return on error?) | ||
| 3749 | emit_engine_emit_exp( emit, member->base ); | ||
| 3750 | // lookup the member (1.3.1.0: changed to use getkindof instead of type size) | ||
| 3751 | emit->append( instr = new Chuck_Instr_Dot_Member_Data( | ||
| 3752 | offset, getkindof(emit->env, member->self->type), emit_addr ) ); | ||
| 3753 | instr->set_linepos( member->linepos ); | ||
| 3754 | } | ||
| 3755 | else | ||
| 3756 | { | ||
| 3757 | // if builtin or not | ||
| 3758 | if( value->addr ) | ||
| 3759 | { | ||
| 3760 | // emit builtin (1.3.1.0: changed to use getkindof instead of type size) | ||
| 3761 | emit->append( new Chuck_Instr_Dot_Static_Import_Data( | ||
| 3762 | value->addr, getkindof(emit->env, member->self->type), emit_addr ) ); | ||
| 3763 | } | ||
| 3764 | else | ||
| 3765 | { | ||
| 3766 | // emit the type | ||
| 3767 | emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)t_base ) ); | ||
| 3768 | // emit the static value (1.3.1.0: changed to use getkindof in addition to size) | ||
| 3769 | emit->append( new Chuck_Instr_Dot_Static_Data( | ||
| 3770 | offset, member->self->type->size, getkindof(emit->env, member->self->type), emit_addr ) ); | ||
| 3771 | } | ||
| 3772 | } | ||
| 3773 | } | ||
| 3774 | } | ||
| 3775 | else // static | ||
| 3776 | { | ||
| 3777 | // emit the type | ||
| 3778 | // commented out so built-in static member variables don't have an | ||
| 3779 | // extra thing on the stack - spencer | ||
| 3780 | //emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)t_base ) ); | ||
| 3781 | |||
| 3782 | // if is a func | ||
| 3783 | if( isfunc( emit->env, member->self->type ) ) | ||
| 3784 | { | ||
| 3785 | // emit the type - spencer | ||
| 3786 | emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)t_base ) ); | ||
| 3787 | // get the func | ||
| 3788 | func = t_base->info->lookup_func( member->xid, FALSE ); | ||
| 3789 | // make sure it's there | ||
| 3790 | assert( func != NULL ); | ||
| 3791 | // emit the function | ||
| 3792 | emit->append( new Chuck_Instr_Dot_Static_Func( func ) ); | ||
| 3793 | } | ||
| 3794 | else | ||
| 3795 | { | ||
| 3796 | // get the value | ||
| 3797 | value = t_base->info->lookup_value( member->xid, FALSE ); | ||
| 3798 | // make sure it's there | ||
| 3799 | assert( value != NULL ); | ||
| 3800 | |||
| 3801 | // if builtin | ||
| 3802 | if( value->addr ) | ||
| 3803 | { | ||
| 3804 | // emit (1.3.1.0: changed to use getkindof instead of type size) | ||
| 3805 | emit->append( new Chuck_Instr_Dot_Static_Import_Data( | ||
| 3806 | value->addr, getkindof(emit->env, member->self->type), emit_addr ) ); | ||
| 3807 | } | ||
| 3808 | else | ||
| 3809 | { | ||
| 3810 | // emit the type - spencer | ||
| 3811 | emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)t_base ) ); | ||
| 3812 | // find the offset for data | ||
| 3813 | offset = value->offset; | ||
| 3814 | // emit the member (1.3.1.0: changed to use getkindof in addition to size) | ||
| 3815 | emit->append( new Chuck_Instr_Dot_Static_Data( | ||
| 3816 | offset, member->self->type->size, getkindof(emit->env, member->self->type), emit_addr ) ); | ||
| 3817 | } | ||
| 3818 | } | ||
| 3819 | } | ||
| 3820 | |||
| 3821 | return TRUE; | ||
| 3822 | } | ||
| 3823 | |||
| 3824 | |||
| 3825 | |||
| 3826 | |||
| 3827 | //----------------------------------------------------------------------------- | ||
| 3828 | // name: emit_engine_emit_exp_if() | ||
| 3829 | // desc: ... | ||
| 3830 | //----------------------------------------------------------------------------- | ||
| 3831 | t_CKBOOL emit_engine_emit_exp_if( Chuck_Emitter * emit, a_Exp_If exp_if ) | ||
| 3832 | { | ||
| 3833 | t_CKBOOL ret = TRUE; | ||
| 3834 | Chuck_Instr_Branch_Op * op = NULL, * op2 = NULL; | ||
| 3835 | |||
| 3836 | // push the stack, allowing for new local variables | ||
| 3837 | emit->push_scope(); | ||
| 3838 | |||
| 3839 | // emit the condition | ||
| 3840 | ret = emit_engine_emit_exp( emit, exp_if->cond ); | ||
| 3841 | if( !ret ) | ||
| 3842 | return FALSE; | ||
| 3843 | |||
| 3844 | // type of the condition | ||
| 3845 | switch( exp_if->cond->type->xid ) | ||
| 3846 | { | ||
| 3847 | case te_int: | ||
| 3848 | // push 0 | ||
| 3849 | emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); | ||
| 3850 | op = new Chuck_Instr_Branch_Eq_int( 0 ); | ||
| 3851 | break; | ||
| 3852 | case te_float: | ||
| 3853 | case te_dur: | ||
| 3854 | case te_time: | ||
| 3855 | // push 0 | ||
| 3856 | emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) ); | ||
| 3857 | op = new Chuck_Instr_Branch_Eq_double( 0 ); | ||
| 3858 | break; | ||
| 3859 | |||
| 3860 | default: | ||
| 3861 | EM_error2( exp_if->cond->linepos, | ||
| 3862 | "(emit): internal error: unhandled type '%s' in if condition", | ||
| 3863 | exp_if->cond->type->name.c_str() ); | ||
| 3864 | return FALSE; | ||
| 3865 | } | ||
| 3866 | |||
| 3867 | if( !ret ) return FALSE; | ||
| 3868 | |||
| 3869 | // append the op | ||
| 3870 | emit->append( op ); | ||
| 3871 | |||
| 3872 | // emit the body | ||
| 3873 | ret = emit_engine_emit_exp( emit, exp_if->if_exp ); | ||
| 3874 | if( !ret ) | ||
| 3875 | return FALSE; | ||
| 3876 | |||
| 3877 | // emit the skip to the end | ||
| 3878 | emit->append( op2 = new Chuck_Instr_Goto(0) ); | ||
| 3879 | |||
| 3880 | // set the op's target | ||
| 3881 | op->set( emit->next_index() ); | ||
| 3882 | |||
| 3883 | // emit the body | ||
| 3884 | ret = emit_engine_emit_exp( emit, exp_if->else_exp ); | ||
| 3885 | if( !ret ) | ||
| 3886 | return FALSE; | ||
| 3887 | |||
| 3888 | // pop stack | ||
| 3889 | emit->pop_scope(); | ||
| 3890 | |||
| 3891 | // set the op2's target | ||
| 3892 | op2->set( emit->next_index() ); | ||
| 3893 | |||
| 3894 | return ret; | ||
| 3895 | } | ||
| 3896 | |||
| 3897 | |||
| 3898 | |||
| 3899 | |||
| 3900 | //----------------------------------------------------------------------------- | ||
| 3901 | // name: emit_engine_pre_constructor() | ||
| 3902 | // desc: ... | ||
| 3903 | //----------------------------------------------------------------------------- | ||
| 3904 | t_CKBOOL emit_engine_pre_constructor( Chuck_Emitter * emit, Chuck_Type * type ) | ||
| 3905 | { | ||
| 3906 | // parent first pre constructor | ||
| 3907 | if( type->parent != NULL ) | ||
| 3908 | emit_engine_pre_constructor( emit, type->parent ); | ||
| 3909 | |||
| 3910 | // pre constructor | ||
| 3911 | if( type->has_constructor ) | ||
| 3912 | { | ||
| 3913 | // make sure | ||
| 3914 | assert( type->info->pre_ctor != NULL ); | ||
| 3915 | // append instruction | ||
| 3916 | emit->append( new Chuck_Instr_Pre_Constructor( type->info->pre_ctor, | ||
| 3917 | emit->code->frame->curr_offset ) ); | ||
| 3918 | } | ||
| 3919 | |||
| 3920 | return TRUE; | ||
| 3921 | } | ||
| 3922 | |||
| 3923 | |||
| 3924 | |||
| 3925 | |||
| 3926 | //----------------------------------------------------------------------------- | ||
| 3927 | // name: emit_engine_pre_constructor_array() | ||
| 3928 | // desc: ... | ||
| 3929 | //----------------------------------------------------------------------------- | ||
| 3930 | t_CKBOOL emit_engine_pre_constructor_array( Chuck_Emitter * emit, Chuck_Type * type ) | ||
| 3931 | { | ||
| 3932 | // alloc should have put all objects to made in linear list, on stack | ||
| 3933 | Chuck_Instr_Pre_Ctor_Array_Top * top = NULL; | ||
| 3934 | Chuck_Instr_Pre_Ctor_Array_Bottom * bottom = NULL; | ||
| 3935 | // get start index | ||
| 3936 | t_CKUINT start_index = emit->next_index(); | ||
| 3937 | // append first part of pre ctor | ||
| 3938 | emit->append( top = new Chuck_Instr_Pre_Ctor_Array_Top( type ) ); | ||
| 3939 | // call pre constructor | ||
| 3940 | emit_engine_pre_constructor( emit, type ); | ||
| 3941 | // append second part of the pre ctor | ||
| 3942 | emit->append( bottom = new Chuck_Instr_Pre_Ctor_Array_Bottom ); | ||
| 3943 | // set the goto of the first one | ||
| 3944 | top->set( emit->next_index() ); | ||
| 3945 | // set the goto for the second one | ||
| 3946 | bottom->set( start_index ); | ||
| 3947 | // clean up code | ||
| 3948 | emit->append( new Chuck_Instr_Pre_Ctor_Array_Post ); | ||
| 3949 | |||
| 3950 | return TRUE; | ||
| 3951 | } | ||
| 3952 | |||
| 3953 | |||
| 3954 | |||
| 3955 | //----------------------------------------------------------------------------- | ||
| 3956 | // name: emit_engine_instantiate_object() | ||
| 3957 | // desc: ... | ||
| 3958 | //----------------------------------------------------------------------------- | ||
| 3959 | t_CKBOOL emit_engine_instantiate_object( Chuck_Emitter * emit, Chuck_Type * type, | ||
| 3960 | a_Array_Sub array, t_CKBOOL is_ref ) | ||
| 3961 | { | ||
| 3962 | // if array | ||
| 3963 | if( type->array_depth ) | ||
| 3964 | { | ||
| 3965 | // emit indices | ||
| 3966 | emit_engine_emit_exp( emit, array->exp_list ); | ||
| 3967 | // emit array allocation | ||
| 3968 | Chuck_Instr * instr = NULL; | ||
| 3969 | emit->append( instr = new Chuck_Instr_Array_Alloc( emit->env, | ||
| 3970 | type->array_depth, type->array_type, emit->code->frame->curr_offset, | ||
| 3971 | is_ref ) ); | ||
| 3972 | instr->set_linepos( array->linepos ); | ||
| 3973 | |||
| 3974 | // handle constructor | ||
| 3975 | if( isobj( emit->env, type->array_type ) && !is_ref ) | ||
| 3976 | { | ||
| 3977 | // call pre constructor for array | ||
| 3978 | emit_engine_pre_constructor_array( emit, type->array_type ); | ||
| 3979 | } | ||
| 3980 | } | ||
| 3981 | else if( !is_ref ) // not array | ||
| 3982 | { | ||
| 3983 | // emit object instantiation code, include pre constructor | ||
| 3984 | emit->append( new Chuck_Instr_Instantiate_Object( type ) ); | ||
| 3985 | |||
| 3986 | // call pre constructor | ||
| 3987 | emit_engine_pre_constructor( emit, type ); | ||
| 3988 | } | ||
| 3989 | |||
| 3990 | return TRUE; | ||
| 3991 | } | ||
| 3992 | |||
| 3993 | |||
| 3994 | |||
| 3995 | |||
| 3996 | //----------------------------------------------------------------------------- | ||
| 3997 | // name: emit_engine_emit_exp_decl() | ||
| 3998 | // desc: ... | ||
| 3999 | //----------------------------------------------------------------------------- | ||
| 4000 | t_CKBOOL emit_engine_emit_exp_decl( Chuck_Emitter * emit, a_Exp_Decl decl, | ||
| 4001 | t_CKBOOL first_exp ) | ||
| 4002 | { | ||
| 4003 | a_Var_Decl_List list = decl->var_decl_list; | ||
| 4004 | a_Var_Decl var_decl = NULL; | ||
| 4005 | Chuck_Value * value = NULL; | ||
| 4006 | Chuck_Type * type = NULL; | ||
| 4007 | Chuck_Local * local = NULL; | ||
| 4008 | t_CKBOOL is_obj = FALSE; | ||
| 4009 | t_CKBOOL is_ref = FALSE; | ||
| 4010 | t_CKBOOL is_init = FALSE; | ||
| 4011 | |||
| 4012 | // loop through vars | ||
| 4013 | while( list ) | ||
| 4014 | { | ||
| 4015 | // the var | ||
| 4016 | var_decl = list->var_decl; | ||
| 4017 | // get the value determined in type checker | ||
| 4018 | value = var_decl->value; | ||
| 4019 | // get the type of the value | ||
| 4020 | type = value->type; | ||
| 4021 | // is the variable a reference | ||
| 4022 | is_obj = isobj( emit->env, type ); | ||
| 4023 | // do alloc or not | ||
| 4024 | is_ref = decl->type->ref; | ||
| 4025 | // not init | ||
| 4026 | is_init = FALSE; | ||
| 4027 | |||
| 4028 | // if this is an object | ||
| 4029 | if( is_obj ) | ||
| 4030 | { | ||
| 4031 | // if array, then check to see if empty [] | ||
| 4032 | if( list->var_decl->array ) | ||
| 4033 | { | ||
| 4034 | if( list->var_decl->array->exp_list ) | ||
| 4035 | { | ||
| 4036 | // set | ||
| 4037 | is_init = TRUE; | ||
| 4038 | // instantiate object, including array | ||
| 4039 | if( !emit_engine_instantiate_object( emit, type, list->var_decl->array, is_ref ) ) | ||
| 4040 | return FALSE; | ||
| 4041 | } | ||
| 4042 | } | ||
| 4043 | else if( !is_ref ) | ||
| 4044 | { | ||
| 4045 | // set | ||
| 4046 | is_init = TRUE; | ||
| 4047 | // instantiate object (not array) | ||
| 4048 | if( !emit_engine_instantiate_object( emit, type, list->var_decl->array, is_ref ) ) | ||
| 4049 | return FALSE; | ||
| 4050 | } | ||
| 4051 | } | ||
| 4052 | |||
| 4053 | // if not init and first exp | ||
| 4054 | /* if( !is_init && first_exp ) | ||
| 4055 | { | ||
| 4056 | // push 0 | ||
| 4057 | if( type->size == sz_INT ) // ISSUE: 64-bit | ||
| 4058 | emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); | ||
| 4059 | else if( type->size == sz_FLOAT ) // ISSUE: 64-bit | ||
| 4060 | emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) ); | ||
| 4061 | else if( type->size == sz_COMPLEX ) // ISSUE: 64-bit | ||
| 4062 | emit->append( new Chuck_Instr_Reg_Push_Imm4( 0.0, 0.0 ) ); | ||
| 4063 | else | ||
| 4064 | { | ||
| 4065 | EM_error2( decl->linepos, | ||
| 4066 | "(emit): unhandle decl size of '%i'...", | ||
| 4067 | type->size ); | ||
| 4068 | return FALSE; | ||
| 4069 | } | ||
| 4070 | }*/ | ||
| 4071 | |||
| 4072 | // put in the value | ||
| 4073 | |||
| 4074 | // member | ||
| 4075 | if( value->is_member ) | ||
| 4076 | { | ||
| 4077 | // zero out location in object, and leave addr on operand stack | ||
| 4078 | // added 1.3.1.0: iskindofint -- on some 64-bit systems, sz_int == sz_FLOAT | ||
| 4079 | if( type->size == sz_INT && iskindofint(emit->env, type) ) // ISSUE: 64-bit (fixed 1.3.1.0) | ||
| 4080 | emit->append( new Chuck_Instr_Alloc_Member_Word( value->offset ) ); | ||
| 4081 | else if( type->size == sz_FLOAT ) // ISSUE: 64-bit (fixed 1.3.1.0) | ||
| 4082 | emit->append( new Chuck_Instr_Alloc_Member_Word2( value->offset ) ); | ||
| 4083 | else if( type->size == sz_COMPLEX ) // ISSUE: 64-bit (fixed 1.3.1.0) | ||
| 4084 | emit->append( new Chuck_Instr_Alloc_Member_Word4( value->offset ) ); | ||
| 4085 | else if( type->size == sz_VEC3 ) // ge: added 1.3.5.3 | ||
| 4086 | emit->append( new Chuck_Instr_Alloc_Member_Vec3( value->offset ) ); | ||
| 4087 | else if( type->size == sz_VEC4 ) // ge: added 1.3.5.3 | ||
| 4088 | emit->append( new Chuck_Instr_Alloc_Member_Vec4( value->offset) ); | ||
| 4089 | else | ||
| 4090 | { | ||
| 4091 | EM_error2( decl->linepos, | ||
| 4092 | "(emit): internal error: unhandled decl size of '%i'...", | ||
| 4093 | type->size ); | ||
| 4094 | return FALSE; | ||
| 4095 | } | ||
| 4096 | } | ||
| 4097 | else // not member | ||
| 4098 | { | ||
| 4099 | // not in class | ||
| 4100 | if( !emit->env->class_def || !decl->is_static ) | ||
| 4101 | { | ||
| 4102 | // allocate a place on the local stack | ||
| 4103 | // (added 1.3.0.0 -- is_obj for tracking objects ref count on stack) | ||
| 4104 | local = emit->alloc_local( type->size, value->name, is_ref, is_obj ); | ||
| 4105 | if( !local ) | ||
| 4106 | { | ||
| 4107 | EM_error2( decl->linepos, | ||
| 4108 | "(emit): internal error: cannot allocate local '%s'...", | ||
| 4109 | value->name.c_str() ); | ||
| 4110 | return FALSE; | ||
| 4111 | } | ||
| 4112 | |||
| 4113 | // put in the value | ||
| 4114 | value->offset = local->offset; | ||
| 4115 | |||
| 4116 | // zero out location in memory, and leave addr on operand stack | ||
| 4117 | // TODO: this is wrong for static | ||
| 4118 | // BAD: | ||
| 4119 | // FIX: | ||
| 4120 | // added 1.3.1.0: iskindofint -- since on some 64-bit systems, sz_INT == sz_FLOAT | ||
| 4121 | if( type->size == sz_INT && iskindofint(emit->env, type) ) // ISSUE: 64-bit (fixed 1.3.1.0) | ||
| 4122 | { | ||
| 4123 | // (added 1.3.0.0 -- is_obj) | ||
| 4124 | Chuck_Instr_Alloc_Word * instr = new Chuck_Instr_Alloc_Word( local->offset, is_obj ); | ||
| 4125 | if( decl->is_external ) // REFACTOR-2017: added external keyword | ||
| 4126 | { | ||
| 4127 | instr->m_is_external = TRUE; | ||
| 4128 | instr->m_name = value->name; | ||
| 4129 | instr->m_type = type->xid; | ||
| 4130 | } | ||
| 4131 | instr->set_linepos( decl->linepos ); | ||
| 4132 | emit->append( instr ); | ||
| 4133 | } | ||
| 4134 | else if( type->size == sz_FLOAT ) // ISSUE: 64-bit (fixed 1.3.1.0) | ||
| 4135 | { | ||
| 4136 | Chuck_Instr_Alloc_Word2 * instr = new Chuck_Instr_Alloc_Word2( local->offset ); | ||
| 4137 | if( decl->is_external ) // REFACTOR-2017: added external keyword | ||
| 4138 | { | ||
| 4139 | instr->m_is_external = TRUE; | ||
| 4140 | instr->m_name = value->name; | ||
| 4141 | instr->m_type = type->xid; | ||
| 4142 | } | ||
| 4143 | instr->set_linepos( decl->linepos ); | ||
| 4144 | emit->append( instr ); | ||
| 4145 | } | ||
| 4146 | else if( type->size == sz_COMPLEX ) // ISSUE: 64-bit (fixed 1.3.1.0) | ||
| 4147 | { | ||
| 4148 | emit->append( new Chuck_Instr_Alloc_Word4( local->offset ) ); | ||
| 4149 | } | ||
| 4150 | else if( type->size == sz_VEC3 ) // ge: added 1.3.5.3 | ||
| 4151 | { | ||
| 4152 | emit->append( new Chuck_Instr_Alloc_Vec3(local->offset) ); | ||
| 4153 | } | ||
| 4154 | else if( type->size == sz_VEC4 ) // ge: added 1.3.5.3 | ||
| 4155 | { | ||
| 4156 | emit->append( new Chuck_Instr_Alloc_Vec4(local->offset) ); | ||
| 4157 | } | ||
| 4158 | else | ||
| 4159 | { | ||
| 4160 | EM_error2( decl->linepos, | ||
| 4161 | "(emit): internal error: unhandled decl size of '%i'...", | ||
| 4162 | type->size ); | ||
| 4163 | return FALSE; | ||
| 4164 | } | ||
| 4165 | } | ||
| 4166 | else // static | ||
| 4167 | { | ||
| 4168 | // emit the type | ||
| 4169 | emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)emit->env->class_def ) ); | ||
| 4170 | // emit the static value (1.3.1.0: changed to use getkindof in addition to size) | ||
| 4171 | emit->append( new Chuck_Instr_Dot_Static_Data( | ||
| 4172 | value->offset, value->type->size, getkindof(emit->env, value->type), TRUE ) ); | ||
| 4173 | } | ||
| 4174 | } | ||
| 4175 | |||
| 4176 | // set is_init | ||
| 4177 | is_init = FALSE; | ||
| 4178 | |||
| 4179 | // if object, assign | ||
| 4180 | if( is_obj ) | ||
| 4181 | { | ||
| 4182 | // if array | ||
| 4183 | if( var_decl->array ) | ||
| 4184 | { | ||
| 4185 | // if not [] | ||
| 4186 | if( var_decl->array->exp_list ) | ||
| 4187 | { | ||
| 4188 | // set | ||
| 4189 | is_init = TRUE; | ||
| 4190 | // assign | ||
| 4191 | emit->append( new Chuck_Instr_Assign_Object ); | ||
| 4192 | } | ||
| 4193 | } | ||
| 4194 | else if( !is_ref ) | ||
| 4195 | { | ||
| 4196 | // set | ||
| 4197 | is_init = TRUE; | ||
| 4198 | // assign the object | ||
| 4199 | emit->append( new Chuck_Instr_Assign_Object ); | ||
| 4200 | } | ||
| 4201 | } | ||
| 4202 | |||
| 4203 | // if not init and first exp | ||
| 4204 | /* if( !is_init && first_exp ) | ||
| 4205 | { | ||
| 4206 | // if obj | ||
| 4207 | if( is_obj ) | ||
| 4208 | emit->append( new Chuck_Instr_Assign_Object ); | ||
| 4209 | // size 4 primitive | ||
| 4210 | // added 1.3.1.0: iskindofint -- since on some 64-bit systems, sz_INT == sz_FLOAT | ||
| 4211 | else if( type->size == sz_INT && iskindofint(type) ) // ISSUE: 64-bit (fixed 1.3.1.0) | ||
| 4212 | emit->append( new Chuck_Instr_Assign_Primitive ); | ||
| 4213 | // size 8 primitive | ||
| 4214 | else if( type->size == sz_FLOAT ) // ISSUE: 64-bit (fixed 1.3.1.0) | ||
| 4215 | emit->append( new Chuck_Instr_Assign_Primitive2 ); | ||
| 4216 | // size 16 primitive | ||
| 4217 | else if( type->size == sz_COMPLEX ) // ISSUE: 64-bit (fixed 1.3.1.0) | ||
| 4218 | emit->append( new Chuck_Instr_Assign_Primitive4 ); | ||
| 4219 | else | ||
| 4220 | assert( FALSE ); | ||
| 4221 | }*/ | ||
| 4222 | |||
| 4223 | list = list->next; | ||
| 4224 | } | ||
| 4225 | |||
| 4226 | return TRUE; | ||
| 4227 | } | ||
| 4228 | |||
| 4229 | |||
| 4230 | |||
| 4231 | |||
| 4232 | //----------------------------------------------------------------------------- | ||
| 4233 | // name: emit_engine_emit_code_segment() | ||
| 4234 | // desc: ... | ||
| 4235 | //----------------------------------------------------------------------------- | ||
| 4236 | t_CKBOOL emit_engine_emit_code_segment( Chuck_Emitter * emit, | ||
| 4237 | a_Stmt_Code stmt, t_CKBOOL push ) | ||
| 4238 | { | ||
| 4239 | a_Stmt_List list = stmt->stmt_list; | ||
| 4240 | |||
| 4241 | // loop through | ||
| 4242 | while( list ) | ||
| 4243 | { | ||
| 4244 | // emit the statement | ||
| 4245 | if( !emit_engine_emit_stmt( emit, list->stmt ) ) | ||
| 4246 | return FALSE; | ||
| 4247 | |||
| 4248 | // next | ||
| 4249 | list = list->next; | ||
| 4250 | } | ||
| 4251 | |||
| 4252 | // TODO: push | ||
| 4253 | |||
| 4254 | return TRUE; | ||
| 4255 | } | ||
| 4256 | |||
| 4257 | |||
| 4258 | |||
| 4259 | |||
| 4260 | //----------------------------------------------------------------------------- | ||
| 4261 | // name: emit_engine_emit_func_def() | ||
| 4262 | // desc: ... | ||
| 4263 | //----------------------------------------------------------------------------- | ||
| 4264 | t_CKBOOL emit_engine_emit_func_def( Chuck_Emitter * emit, a_Func_Def func_def ) | ||
| 4265 | { | ||
| 4266 | // get the func | ||
| 4267 | Chuck_Func * func = func_def->ck_func; | ||
| 4268 | // get the value | ||
| 4269 | Chuck_Value * value = func->value_ref; | ||
| 4270 | // get the type | ||
| 4271 | Chuck_Type * type = value->type; | ||
| 4272 | // local | ||
| 4273 | Chuck_Local * local = NULL; | ||
| 4274 | |||
| 4275 | // make sure it's the same one | ||
| 4276 | //Chuck_Func * func2 = emit->env->context->nspc.lookup_func( func_def->name, FALSE ); | ||
| 4277 | //if( func != func2 ) | ||
| 4278 | //{ | ||
| 4279 | // EM_error2( func_def->linepos, | ||
| 4280 | // "(emit): ambiguous function resolution for %s...", | ||
| 4281 | // S_name(func_def->name) ); | ||
| 4282 | // return FALSE; | ||
| 4283 | //} | ||
| 4284 | |||
| 4285 | // make sure the code is empty | ||
| 4286 | if( func->code != NULL ) | ||
| 4287 | { | ||
| 4288 | EM_error2( func_def->linepos, | ||
| 4289 | "(emit): function '%s' already emitted...", | ||
| 4290 | S_name(func_def->name) ); | ||
| 4291 | return FALSE; | ||
| 4292 | } | ||
| 4293 | |||
| 4294 | // make sure we are not in a function already | ||
| 4295 | if( emit->env->func != NULL ) | ||
| 4296 | { | ||
| 4297 | EM_error2( func_def->linepos, | ||
| 4298 | "(emit): internal error: nested function definition..." ); | ||
| 4299 | return FALSE; | ||
| 4300 | } | ||
| 4301 | |||
| 4302 | // if not part of a class | ||
| 4303 | if( !emit->env->class_def ) | ||
| 4304 | { | ||
| 4305 | // put function on stack | ||
| 4306 | // ge: added FALSE to the 'is_obj' argument, 2012 april (added 1.3.0.0) | ||
| 4307 | local = emit->alloc_local( value->type->size, value->name, TRUE, FALSE ); | ||
| 4308 | // remember the offset | ||
| 4309 | value->offset = local->offset; | ||
| 4310 | // write to mem stack | ||
| 4311 | emit->append( new Chuck_Instr_Mem_Set_Imm( value->offset, (t_CKUINT)func ) ); | ||
| 4312 | } | ||
| 4313 | |||
| 4314 | // set the func | ||
| 4315 | emit->env->func = func; | ||
| 4316 | // push the current code | ||
| 4317 | emit->stack.push_back( emit->code ); | ||
| 4318 | // make a new one | ||
| 4319 | emit->code = new Chuck_Code; | ||
| 4320 | // name the code | ||
| 4321 | emit->code->name = emit->env->class_def ? emit->env->class_def->name + "." : ""; | ||
| 4322 | emit->code->name += func->name + "( ... )"; | ||
| 4323 | // set whether need this | ||
| 4324 | emit->code->need_this = func->is_member; | ||
| 4325 | // keep track of full path (added 1.3.0.0) | ||
| 4326 | emit->code->filename = emit->context->full_path; | ||
| 4327 | |||
| 4328 | // go through the args | ||
| 4329 | a_Arg_List a = func_def->arg_list; | ||
| 4330 | t_CKBOOL is_obj = FALSE; // (added 1.3.0.0) | ||
| 4331 | t_CKBOOL is_ref = FALSE; | ||
| 4332 | |||
| 4333 | // if member (non-static) function | ||
| 4334 | if( func->is_member ) | ||
| 4335 | { | ||
| 4336 | // get the size | ||
| 4337 | emit->code->stack_depth += sizeof(t_CKUINT); | ||
| 4338 | // add this | ||
| 4339 | // ge: added FALSE to the 'is_obj' argument, 2012 april (added 1.3.0.0) | ||
| 4340 | if( !emit->alloc_local( sizeof(t_CKUINT), "this", TRUE, FALSE ) ) | ||
| 4341 | { | ||
| 4342 | EM_error2( a->linepos, | ||
| 4343 | "(emit): internal error: cannot allocate local 'this'..." ); | ||
| 4344 | return FALSE; | ||
| 4345 | } | ||
| 4346 | } | ||
| 4347 | |||
| 4348 | // ge: 2012 april: added push scope (added 1.3.0.0) | ||
| 4349 | emit->push_scope(); | ||
| 4350 | |||
| 4351 | // loop through args | ||
| 4352 | while( a ) | ||
| 4353 | { | ||
| 4354 | // get the value | ||
| 4355 | value = a->var_decl->value; | ||
| 4356 | // get the type | ||
| 4357 | type = value->type; | ||
| 4358 | // is object? (added ge: 2012 april | added 1.3.0.0) | ||
| 4359 | is_obj = isobj( emit->env, type ); | ||
| 4360 | // get ref | ||
| 4361 | is_ref = a->type_decl->ref; | ||
| 4362 | // get the size | ||
| 4363 | emit->code->stack_depth += type->size; | ||
| 4364 | // allocate a place on the local stack | ||
| 4365 | // ge: added 'is_obj' 2012 april | ||
| 4366 | local = emit->alloc_local( type->size, value->name, is_ref, is_obj ); | ||
| 4367 | if( !local ) | ||
| 4368 | { | ||
| 4369 | EM_error2( a->linepos, | ||
| 4370 | "(emit): internal error: cannot allocate local '%s'...", | ||
| 4371 | value->name.c_str() ); | ||
| 4372 | return FALSE; | ||
| 4373 | } | ||
| 4374 | // remember the offset | ||
| 4375 | value->offset = local->offset; | ||
| 4376 | |||
| 4377 | // advance | ||
| 4378 | a = a->next; | ||
| 4379 | } | ||
| 4380 | |||
| 4381 | // TODO: make sure the calculated stack depth is the same as func_def->stack depth | ||
| 4382 | // taking into account member function | ||
| 4383 | |||
| 4384 | // add references for objects in the arguments (added 1.3.0.0) | ||
| 4385 | // NOTE: this isn't in use since currently the caller is reference counting | ||
| 4386 | // the arguments -- this is to better support sporking, which is more | ||
| 4387 | // asynchronous. the code below is left in as reference for callee ref counting | ||
| 4388 | // emit->addref_on_scope(); | ||
| 4389 | |||
| 4390 | // emit the code | ||
| 4391 | if( !emit_engine_emit_stmt( emit, func_def->code, FALSE ) ) | ||
| 4392 | return FALSE; | ||
| 4393 | |||
| 4394 | // added by spencer June 2014 (1.3.5.0) | ||
| 4395 | // ensure return | ||
| 4396 | if( func_def->ret_type && func_def->ret_type != emit->env->t_void ) | ||
| 4397 | { | ||
| 4398 | emit->append( new Chuck_Instr_Reg_Push_Imm(0) ); | ||
| 4399 | |||
| 4400 | Chuck_Instr_Goto * instr = new Chuck_Instr_Goto( 0 ); | ||
| 4401 | emit->append( instr ); | ||
| 4402 | emit->code->stack_return.push_back( instr ); | ||
| 4403 | } | ||
| 4404 | |||
| 4405 | // ge: pop scope (2012 april | added 1.3.0.0) | ||
| 4406 | // TODO: ge 2012 april: pop scope? clean up function arguments? are argument properly ref counted? | ||
| 4407 | emit->pop_scope(); | ||
| 4408 | |||
| 4409 | // set the index for next instruction for return statements | ||
| 4410 | for( t_CKUINT i = 0; i < emit->code->stack_return.size(); i++ ) | ||
| 4411 | emit->code->stack_return[i]->set( emit->next_index() ); | ||
| 4412 | // clear the return stack | ||
| 4413 | emit->code->stack_return.clear(); | ||
| 4414 | // emit return statement | ||
| 4415 | emit->append( new Chuck_Instr_Func_Return ); | ||
| 4416 | |||
| 4417 | // vm code | ||
| 4418 | func->code = emit_to_code( emit->code, NULL, emit->dump ); | ||
| 4419 | // add reference | ||
| 4420 | func->code->add_ref(); | ||
| 4421 | |||
| 4422 | // unset the func | ||
| 4423 | emit->env->func = NULL; | ||
| 4424 | // delete the code | ||
| 4425 | SAFE_DELETE( emit->code ); | ||
| 4426 | // pop the code | ||
| 4427 | assert( emit->stack.size() ); | ||
| 4428 | emit->code = emit->stack.back(); | ||
| 4429 | emit->stack.pop_back(); | ||
| 4430 | |||
| 4431 | return TRUE; | ||
| 4432 | } | ||
| 4433 | |||
| 4434 | |||
| 4435 | |||
| 4436 | |||
| 4437 | //----------------------------------------------------------------------------- | ||
| 4438 | // name: emit_engine_emit_class_def() | ||
| 4439 | // desc: ... | ||
| 4440 | //----------------------------------------------------------------------------- | ||
| 4441 | t_CKBOOL emit_engine_emit_class_def( Chuck_Emitter * emit, a_Class_Def class_def ) | ||
| 4442 | { | ||
| 4443 | // get the type | ||
| 4444 | Chuck_Type * type = class_def->type; | ||
| 4445 | // the return type | ||
| 4446 | t_CKBOOL ret = TRUE; | ||
| 4447 | // the class body | ||
| 4448 | a_Class_Body body = class_def->body; | ||
| 4449 | |||
| 4450 | // make sure the code is empty | ||
| 4451 | if( type->info->pre_ctor != NULL && type->info->pre_ctor->instr != NULL ) | ||
| 4452 | { | ||
| 4453 | EM_error2( class_def->linepos, | ||
| 4454 | "(emit): class '%s' already emitted...", | ||
| 4455 | type->name.c_str() ); | ||
| 4456 | return FALSE; | ||
| 4457 | } | ||
| 4458 | |||
| 4459 | // make sure we are not in a class already | ||
| 4460 | //if( emit->env->class_def != NULL ) | ||
| 4461 | //{ | ||
| 4462 | // EM_error2( class_def->linepos, | ||
| 4463 | // "(emit): internal error: nested class definition..." ); | ||
| 4464 | // return FALSE; | ||
| 4465 | //} | ||
| 4466 | |||
| 4467 | // set the class | ||
| 4468 | emit->env->class_stack.push_back( emit->env->class_def ); | ||
| 4469 | emit->env->class_def = type; | ||
| 4470 | // push the current code | ||
| 4471 | emit->stack.push_back( emit->code ); | ||
| 4472 | // make a new one | ||
| 4473 | emit->code = new Chuck_Code; | ||
| 4474 | // name the code | ||
| 4475 | emit->code->name = string("class ") + type->name; | ||
| 4476 | // whether code needs this | ||
| 4477 | emit->code->need_this = TRUE; | ||
| 4478 | // if has constructor | ||
| 4479 | // if( type->has_constructor ) type->info->pre_ctor = new Chuck_VM_Code; | ||
| 4480 | // keep track of full path (added 1.3.0.0) | ||
| 4481 | emit->code->filename = emit->context->full_path; | ||
| 4482 | |||
| 4483 | // get the size | ||
| 4484 | emit->code->stack_depth += sizeof(t_CKUINT); | ||
| 4485 | // add this | ||
| 4486 | // ge: added TRUE to the 'is_obj' argument, 2012 april (added 1.3.0.0) | ||
| 4487 | // TODO: verify this is right, and not over-ref counted / cleaned up? | ||
| 4488 | if( !emit->alloc_local( sizeof(t_CKUINT), "this", TRUE, TRUE ) ) | ||
| 4489 | { | ||
| 4490 | EM_error2( class_def->linepos, | ||
| 4491 | "(emit): internal error: cannot allocate local 'this'..." ); | ||
| 4492 | return FALSE; | ||
| 4493 | } | ||
| 4494 | |||
| 4495 | // emit the body | ||
| 4496 | while( body && ret ) | ||
| 4497 | { | ||
| 4498 | // check the section | ||
| 4499 | switch( body->section->s_type ) | ||
| 4500 | { | ||
| 4501 | case ae_section_stmt: | ||
| 4502 | ret = emit_engine_emit_stmt_list( emit, body->section->stmt_list ); | ||
| 4503 | break; | ||
| 4504 | |||
| 4505 | case ae_section_func: | ||
| 4506 | ret = emit_engine_emit_func_def( emit, body->section->func_def ); | ||
| 4507 | break; | ||
| 4508 | |||
| 4509 | case ae_section_class: | ||
| 4510 | ret = emit_engine_emit_class_def( emit, body->section->class_def ); | ||
| 4511 | //EM_error2( body->section->class_def->linepos, | ||
| 4512 | // "nested class definitions are not yet supported..." ); | ||
| 4513 | //ret = FALSE; | ||
| 4514 | break; | ||
| 4515 | } | ||
| 4516 | |||
| 4517 | // move to the next section | ||
| 4518 | body = body->next; | ||
| 4519 | } | ||
| 4520 | |||
| 4521 | // if ok | ||
| 4522 | if( ret ) | ||
| 4523 | { | ||
| 4524 | // emit return statement | ||
| 4525 | emit->append( new Chuck_Instr_Func_Return ); | ||
| 4526 | // vm code | ||
| 4527 | type->info->pre_ctor = emit_to_code( emit->code, type->info->pre_ctor, emit->dump ); | ||
| 4528 | // add reference | ||
| 4529 | type->info->pre_ctor->add_ref(); | ||
| 4530 | // allocate static | ||
| 4531 | type->info->class_data = new t_CKBYTE[type->info->class_data_size]; | ||
| 4532 | // verify | ||
| 4533 | if( !type->info->class_data ) | ||
| 4534 | { | ||
| 4535 | // we have a problem | ||
| 4536 | CK_FPRINTF_STDERR( | ||
| 4537 | "[chuck](emitter): OutOfMemory: while allocating static data '%s'\n", type->c_name() ); | ||
| 4538 | // flag | ||
| 4539 | ret = FALSE; | ||
| 4540 | } | ||
| 4541 | else | ||
| 4542 | { | ||
| 4543 | // zero it out | ||
| 4544 | memset( type->info->class_data, 0, type->info->class_data_size ); | ||
| 4545 | } | ||
| 4546 | } | ||
| 4547 | |||
| 4548 | // check again | ||
| 4549 | if( !ret ) | ||
| 4550 | { | ||
| 4551 | // clean | ||
| 4552 | SAFE_DELETE( type->info->pre_ctor ); | ||
| 4553 | } | ||
| 4554 | |||
| 4555 | // unset the class | ||
| 4556 | emit->env->class_def = emit->env->class_stack.back(); | ||
| 4557 | emit->env->class_stack.pop_back(); | ||
| 4558 | // delete the code | ||
| 4559 | SAFE_DELETE( emit->code ); | ||
| 4560 | // pop the code | ||
| 4561 | assert( emit->stack.size() ); | ||
| 4562 | emit->code = emit->stack.back(); | ||
| 4563 | emit->stack.pop_back(); | ||
| 4564 | |||
| 4565 | return ret; | ||
| 4566 | } | ||
| 4567 | |||
| 4568 | |||
| 4569 | |||
| 4570 | |||
| 4571 | //----------------------------------------------------------------------------- | ||
| 4572 | // name: emit_engine_emit_spork() | ||
| 4573 | // desc: ... | ||
| 4574 | //----------------------------------------------------------------------------- | ||
| 4575 | t_CKBOOL emit_engine_emit_spork( Chuck_Emitter * emit, a_Exp_Func_Call exp ) | ||
| 4576 | { | ||
| 4577 | // spork | ||
| 4578 | Chuck_Instr_Mem_Push_Imm * op = NULL; | ||
| 4579 | |||
| 4580 | // if member function, push this | ||
| 4581 | // TODO: this is a hack - what if exp is not func_call? | ||
| 4582 | // if( exp->ck_func->is_member ) | ||
| 4583 | // emit->append( new Chuck_Instr_Reg_Push_This ); | ||
| 4584 | |||
| 4585 | // evaluate args on sporker shred | ||
| 4586 | if( !emit_engine_emit_func_args( emit, exp ) ) | ||
| 4587 | return FALSE; | ||
| 4588 | |||
| 4589 | // emit func pointer on sporker shred | ||
| 4590 | if( !emit_engine_emit_exp( emit, exp->func ) ) | ||
| 4591 | { | ||
| 4592 | EM_error2( exp->linepos, | ||
| 4593 | "(emit): internal error in evaluating function call..." ); | ||
| 4594 | return FALSE; | ||
| 4595 | } | ||
| 4596 | |||
| 4597 | // push the current code | ||
| 4598 | emit->stack.push_back( emit->code ); | ||
| 4599 | // make a new one (spork~exp shred) | ||
| 4600 | emit->code = new Chuck_Code; | ||
| 4601 | // handle need this | ||
| 4602 | emit->code->need_this = exp->ck_func->is_member; | ||
| 4603 | // name it: e.g. spork~foo [line 5] | ||
| 4604 | std::ostringstream name; | ||
| 4605 | name << "spork~" | ||
| 4606 | << exp->ck_func->name.substr( 0, exp->ck_func->name.find( "@" )) | ||
| 4607 | << " [line " << exp->linepos << "]"; | ||
| 4608 | emit->code->name = name.str(); | ||
| 4609 | // keep track of full path (added 1.3.0.0) | ||
| 4610 | emit->code->filename = emit->context->full_path; | ||
| 4611 | // push op | ||
| 4612 | op = new Chuck_Instr_Mem_Push_Imm( 0 ); | ||
| 4613 | // emit the stack depth - we don't know this yet | ||
| 4614 | emit->append( op ); | ||
| 4615 | |||
| 4616 | // call the func on sporkee shred | ||
| 4617 | if( !emit_engine_emit_exp_func_call( | ||
| 4618 | emit, | ||
| 4619 | exp->ck_func, | ||
| 4620 | exp->ret_type, | ||
| 4621 | exp->linepos, | ||
| 4622 | TRUE ) ) | ||
| 4623 | return FALSE; | ||
| 4624 | |||
| 4625 | // emit the function call, with special flag | ||
| 4626 | // if( !emit_engine_emit_exp_func_call( emit, exp, TRUE ) ) | ||
| 4627 | // return FALSE; | ||
| 4628 | |||
| 4629 | // done | ||
| 4630 | emit->append( new Chuck_Instr_EOC ); | ||
| 4631 | // set the stack depth now that we know | ||
| 4632 | op->set( emit->code->stack_depth ); | ||
| 4633 | |||
| 4634 | // emit it | ||
| 4635 | Chuck_VM_Code * code = emit_to_code( emit->code, NULL, emit->dump ); | ||
| 4636 | // remember it | ||
| 4637 | exp->ck_vm_code = code; | ||
| 4638 | // add reference | ||
| 4639 | exp->ck_vm_code->add_ref(); | ||
| 4640 | // code->name = string("spork~exp"); | ||
| 4641 | |||
| 4642 | // restore the code to sporker shred | ||
| 4643 | assert( emit->stack.size() > 0 ); | ||
| 4644 | emit->code = emit->stack.back(); | ||
| 4645 | // pop | ||
| 4646 | emit->stack.pop_back(); | ||
| 4647 | |||
| 4648 | a_Exp e = exp->args; | ||
| 4649 | t_CKUINT size = 0; | ||
| 4650 | while( e ) { size += e->cast_to ? e->cast_to->size : e->type->size; e = e->next; } | ||
| 4651 | |||
| 4652 | // handle member function | ||
| 4653 | // TODO: this is a hack - what if exp is not func_call? | ||
| 4654 | // if( emit->code->need_this ) | ||
| 4655 | // size += sz_INT; // (changed 1.3.1.0: 4 to sz_INT) | ||
| 4656 | |||
| 4657 | // emit instruction that will put the code on the stack | ||
| 4658 | emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)code ) ); | ||
| 4659 | // emit spork instruction - this will copy, func, args, this | ||
| 4660 | emit->append( new Chuck_Instr_Spork( size ) ); | ||
| 4661 | |||
| 4662 | return TRUE; | ||
| 4663 | } | ||
| 4664 | |||
| 4665 | |||
| 4666 | |||
| 4667 | |||
| 4668 | //----------------------------------------------------------------------------- | ||
| 4669 | // name: emit_engine_emit_spork() | ||
| 4670 | // desc: ... | ||
| 4671 | //----------------------------------------------------------------------------- | ||
| 4672 | //t_CKBOOL emit_engine_emit_spork( Chuck_Emitter * emit, a_Stmt stmt ) | ||
| 4673 | //{ | ||
| 4674 | // // push the current code | ||
| 4675 | // emit->stack.push_back( emit->code ); | ||
| 4676 | // // make a new one (spork~exp shred) | ||
| 4677 | // emit->code = new Chuck_Code; | ||
| 4678 | // // handle need this | ||
| 4679 | // emit->code->need_this = emit->env->class_def ? TRUE : FALSE; | ||
| 4680 | // // name it | ||
| 4681 | // emit->code->name = "spork~exp"; | ||
| 4682 | // // keep track of full path (added 1.3.0.0) | ||
| 4683 | // emit->code->filename = emit->context->full_path; | ||
| 4684 | // | ||
| 4685 | // // call the code on sporkee shred | ||
| 4686 | // if( !emit_engine_emit_stmt( emit, stmt, TRUE ) ) | ||
| 4687 | // return FALSE; | ||
| 4688 | // | ||
| 4689 | // // done | ||
| 4690 | // emit->append( new Chuck_Instr_EOC ); | ||
| 4691 | // | ||
| 4692 | // // emit it | ||
| 4693 | // Chuck_VM_Code * code = emit_to_code( emit->code, NULL, emit->dump ); | ||
| 4694 | // | ||
| 4695 | // // restore the code to sporker shred | ||
| 4696 | // assert( emit->stack.size() > 0 ); | ||
| 4697 | // emit->code = emit->stack.back(); | ||
| 4698 | // // pop | ||
| 4699 | // emit->stack.pop_back(); | ||
| 4700 | // | ||
| 4701 | // if( code->need_this ) | ||
| 4702 | // { | ||
| 4703 | // // push this if needed | ||
| 4704 | // emit->append( new Chuck_Instr_Reg_Push_This ); | ||
| 4705 | // } | ||
| 4706 | // // emit instruction that will put the code on the stack | ||
| 4707 | // emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)code ) ); | ||
| 4708 | // // emit spork instruction - this will copy, func, args, this | ||
| 4709 | // emit->append( new Chuck_Instr_Spork_Stmt( 0 ) ); | ||
| 4710 | // | ||
| 4711 | // return TRUE; | ||
| 4712 | //} | ||
| 4713 | |||
| 4714 | |||
| 4715 | |||
| 4716 | |||
| 4717 | //----------------------------------------------------------------------------- | ||
| 4718 | // name: emit_engine_emit_symbol() | ||
| 4719 | // desc: ... | ||
| 4720 | //----------------------------------------------------------------------------- | ||
| 4721 | t_CKBOOL emit_engine_emit_symbol( Chuck_Emitter * emit, S_Symbol symbol, | ||
| 4722 | Chuck_Value * v, t_CKBOOL emit_var, | ||
| 4723 | int linepos ) | ||
| 4724 | { | ||
| 4725 | // look up the value | ||
| 4726 | // Chuck_Value * v = emit->env->curr->lookup_value( symbol, TRUE ); | ||
| 4727 | // it should be there | ||
| 4728 | if( !v ) | ||
| 4729 | { | ||
| 4730 | // internal error | ||
| 4731 | EM_error2( linepos, | ||
| 4732 | "(emit): internal error: undefined symbol '%s'...", | ||
| 4733 | S_name(symbol) ); | ||
| 4734 | return FALSE; | ||
| 4735 | } | ||
| 4736 | |||
| 4737 | // if part of class - this only works because x.y is handled separately | ||
| 4738 | if( v->owner_class && (v->is_member || v->is_static) ) | ||
| 4739 | { | ||
| 4740 | // make sure talking about the same class | ||
| 4741 | // this doesn't work since the owner class could be a super class | ||
| 4742 | // assert( v->owner_class == emit->env->class_def ); | ||
| 4743 | // | ||
| 4744 | // try this (thanks Robin Davies) | ||
| 4745 | assert( isa( emit->env->class_def, v->owner_class ) /* || is_global( v->owner_class ) */ ); | ||
| 4746 | |||
| 4747 | // emit as this.v | ||
| 4748 | // BUG: passing "this" below might be bad if the exp is freed and string with it | ||
| 4749 | a_Exp base = new_exp_from_id( (char *)"this", linepos ); | ||
| 4750 | a_Exp dot = new_exp_from_member_dot( base, (char *)v->name.c_str(), linepos ); | ||
| 4751 | base->type = v->owner_class; | ||
| 4752 | dot->type = v->type; | ||
| 4753 | dot->dot_member.t_base = v->owner_class; | ||
| 4754 | dot->emit_var = emit_var; | ||
| 4755 | // emit it | ||
| 4756 | if( !emit_engine_emit_exp_dot_member( emit, &dot->dot_member ) ) | ||
| 4757 | { | ||
| 4758 | // internal error | ||
| 4759 | EM_error2( linepos, | ||
| 4760 | "(emit): internal error: symbol transformation failed..." ); | ||
| 4761 | return FALSE; | ||
| 4762 | } | ||
| 4763 | |||
| 4764 | return TRUE; | ||
| 4765 | } | ||
| 4766 | |||
| 4767 | // var or value | ||
| 4768 | if( emit_var ) | ||
| 4769 | { | ||
| 4770 | // emit as addr | ||
| 4771 | emit->append( new Chuck_Instr_Reg_Push_Mem_Addr( v->offset, v->is_context_global ) ); | ||
| 4772 | } | ||
| 4773 | else | ||
| 4774 | { | ||
| 4775 | // special case | ||
| 4776 | if( v->func_ref ) | ||
| 4777 | emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)v->func_ref ) ); | ||
| 4778 | // check size | ||
| 4779 | // (added 1.3.1.0: iskindofint -- since in some 64-bit systems, sz_INT == sz_FLOAT) | ||
| 4780 | else if( v->type->size == sz_INT && iskindofint(emit->env, v->type) ) // ISSUE: 64-bit (fixed 1.3.1.0) | ||
| 4781 | emit->append( new Chuck_Instr_Reg_Push_Mem( v->offset, v->is_context_global ) ); | ||
| 4782 | else if( v->type->size == sz_FLOAT ) // ISSUE: 64-bit (fixed 1.3.1.0) | ||
| 4783 | emit->append( new Chuck_Instr_Reg_Push_Mem2( v->offset, v->is_context_global ) ); | ||
| 4784 | else if( v->type->size == sz_COMPLEX ) // ISSUE: 64-bit (fixed 1.3.1.0) | ||
| 4785 | emit->append( new Chuck_Instr_Reg_Push_Mem4( v->offset, v->is_context_global ) ); | ||
| 4786 | else if( v->type->size == sz_VEC3 ) // ge: added 1.3.5.3 | ||
| 4787 | emit->append( new Chuck_Instr_Reg_Push_Mem_Vec3( v->offset, v->is_context_global ) ); | ||
| 4788 | else if( v->type->size == sz_VEC4 ) // ge: added 1.3.5.3 | ||
| 4789 | emit->append( new Chuck_Instr_Reg_Push_Mem_Vec4( v->offset, v->is_context_global ) ); | ||
| 4790 | else | ||
| 4791 | { | ||
| 4792 | // internal error | ||
| 4793 | EM_error2( linepos, | ||
| 4794 | "(emit): internal error: symbol '%s' has size '%i'...", | ||
| 4795 | S_name(symbol), v->type->size ); | ||
| 4796 | return FALSE; | ||
| 4797 | } | ||
| 4798 | } | ||
| 4799 | |||
| 4800 | return TRUE; | ||
| 4801 | } | ||
| 4802 | |||
| 4803 | |||
| 4804 | |||
| 4805 | |||
| 4806 | //----------------------------------------------------------------------------- | ||
| 4807 | // name: addref_on_scope() | ||
| 4808 | // desc: add references to locals on current scope (added 1.3.0.0) | ||
| 4809 | //----------------------------------------------------------------------------- | ||
| 4810 | void Chuck_Emitter::addref_on_scope() | ||
| 4811 | { | ||
| 4812 | // sanity | ||
| 4813 | assert( code != NULL ); | ||
| 4814 | // clear locals | ||
| 4815 | locals.clear(); | ||
| 4816 | // get the current scope | ||
| 4817 | code->frame->get_scope( locals ); | ||
| 4818 | |||
| 4819 | // iterate over locals | ||
| 4820 | for( int i = 0; i < locals.size(); i++ ) | ||
| 4821 | { | ||
| 4822 | // get it | ||
| 4823 | Chuck_Local * local = locals[i]; | ||
| 4824 | // check to see if it's an object | ||
| 4825 | if( local->is_obj ) | ||
| 4826 | { | ||
| 4827 | // emit instruction to add reference | ||
| 4828 | this->append( new Chuck_Instr_AddRef_Object2( local->offset ) ); | ||
| 4829 | } | ||
| 4830 | } | ||
| 4831 | } | ||
| 4832 | |||
| 4833 | |||
| 4834 | |||
| 4835 | |||
| 4836 | //----------------------------------------------------------------------------- | ||
| 4837 | // name: pop_scope() | ||
| 4838 | // desc: ... | ||
| 4839 | //----------------------------------------------------------------------------- | ||
| 4840 | void Chuck_Emitter::pop_scope( ) | ||
| 4841 | { | ||
| 4842 | // sanity | ||
| 4843 | assert( code != NULL ); | ||
| 4844 | // clear locals | ||
| 4845 | locals.clear(); | ||
| 4846 | // get locals | ||
| 4847 | code->frame->pop_scope( locals ); | ||
| 4848 | |||
| 4849 | // ge (2012 april): attempt to free locals (added 1.3.0.0) | ||
| 4850 | // was -- TODO: free locals -- chievo! | ||
| 4851 | for( int i = 0; i < locals.size(); i++ ) | ||
| 4852 | { | ||
| 4853 | // get local | ||
| 4854 | Chuck_Local * local = locals[i]; | ||
| 4855 | // CK_STDCERR << "local: " << local->offset << " " << local->is_obj << CK_STDENDL; | ||
| 4856 | // check to see if it's an object | ||
| 4857 | if( local->is_obj ) | ||
| 4858 | { | ||
| 4859 | // emit instruction to release the object | ||
| 4860 | this->append( new Chuck_Instr_Release_Object2( local->offset ) ); | ||
| 4861 | } | ||
| 4862 | |||
| 4863 | // reclaim local; null out to be safe | ||
| 4864 | SAFE_DELETE( local ); locals[i] = NULL; | ||
| 4865 | } | ||
| 4866 | |||
| 4867 | // clear it | ||
| 4868 | locals.clear(); | ||
| 4869 | } | ||
| 4870 | |||
| 4871 | |||
| 4872 | |||
| 4873 | |||
| 4874 | //----------------------------------------------------------------------------- | ||
| 4875 | // name: find_dur() | ||
| 4876 | // desc: ... | ||
| 4877 | //----------------------------------------------------------------------------- | ||
| 4878 | t_CKBOOL Chuck_Emitter::find_dur( const string & name, t_CKDUR * out ) | ||
| 4879 | { | ||
| 4880 | // sanity | ||
| 4881 | assert( env != NULL ); | ||
| 4882 | assert( out != NULL ); | ||
| 4883 | |||
| 4884 | // zero | ||
| 4885 | *out = 0.0; | ||
| 4886 | // get value from env | ||
| 4887 | Chuck_Value * value = env->global()->lookup_value( name, FALSE ); | ||
| 4888 | if( !value || !equals( value->type, env->t_dur ) ) return FALSE; | ||
| 4889 | // copy | ||
| 4890 | *out = *( (t_CKDUR *)value->addr ); | ||
| 4891 | |||
| 4892 | return TRUE; | ||
| 4893 | } | ||
| 4894 | |||
| 4895 | |||
| 4896 | |||
| 4897 | |||
| 4898 | /* | ||
| 4899 | //----------------------------------------------------------------------------- | ||
| 4900 | // name: emit_engine_instantiate_object() | ||
| 4901 | // desc: ... | ||
| 4902 | //----------------------------------------------------------------------------- | ||
| 4903 | t_CKBOOL emit_engine_instantiate_object( Chuck_Emitter * emit, Chuck_Type * type, | ||
| 4904 | a_Array_Sub array, t_CKBOOL is_ref ) | ||
| 4905 | { | ||
| 4906 | // if array | ||
| 4907 | if( type->array_depth ) | ||
| 4908 | { | ||
| 4909 | // emit indices | ||
| 4910 | emit_engine_emit_exp( emit, array->exp_list ); | ||
| 4911 | // emit array allocation | ||
| 4912 | emit->append( new Chuck_Instr_Array_Alloc( | ||
| 4913 | type->array_depth, type->array_type, emit->code->frame->curr_offset, | ||
| 4914 | is_ref ) ); | ||
| 4915 | |||
| 4916 | // handle constructor | ||
| 4917 | //if( isobj( emit->env, type->array_type ) && !is_ref ) | ||
| 4918 | //{ | ||
| 4919 | // // TODO: | ||
| 4920 | // EM_error2( array->linepos, "internal error: object array constructor not impl..." ); | ||
| 4921 | // return FALSE; | ||
| 4922 | //} | ||
| 4923 | } | ||
| 4924 | else if( !is_ref ) // not array | ||
| 4925 | { | ||
| 4926 | // if ugen | ||
| 4927 | //if( isa( type, emit->env->t_ugen ) ) | ||
| 4928 | //{ | ||
| 4929 | // // get the ugen info | ||
| 4930 | // Chuck_UGen_Info * info = decl->self->type->ugen; | ||
| 4931 | // if( !info ) | ||
| 4932 | // { | ||
| 4933 | // EM_error2( decl->linepos, | ||
| 4934 | // "(emit): internal error: undefined ugen type '%s'", | ||
| 4935 | // type->name.c_str() ); | ||
| 4936 | // return FALSE; | ||
| 4937 | // } | ||
| 4938 | // emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)info ) ); | ||
| 4939 | // emit->append( new Chuck_Instr_UGen_Alloc() ); | ||
| 4940 | //} | ||
| 4941 | //else | ||
| 4942 | //{ | ||
| 4943 | |||
| 4944 | // emit object instantiation code, include pre constructor | ||
| 4945 | emit->append( new Chuck_Instr_Instantiate_Object( type ) ); | ||
| 4946 | |||
| 4947 | //} | ||
| 4948 | |||
| 4949 | // call pre constructor | ||
| 4950 | emit_engine_pre_constructor( emit, type ); | ||
| 4951 | |||
| 4952 | // constructor | ||
| 4953 | //if( type->has_constructor ) | ||
| 4954 | //{ | ||
| 4955 | // // make sure | ||
| 4956 | // assert( type->info->pre_ctor != NULL ); | ||
| 4957 | // // push this | ||
| 4958 | // emit->append( new Chuck_Instr_Reg_Dup_Last ); | ||
| 4959 | // // push pre-constructor | ||
| 4960 | // emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)type->info->pre_ctor ) ); | ||
| 4961 | // // push frame offset | ||
| 4962 | // emit->append( new Chuck_Instr_Reg_Push_Imm( emit->code->frame->curr_offset ) ); | ||
| 4963 | // // call the function | ||
| 4964 | // if( type->info->pre_ctor->native_func != NULL ) | ||
| 4965 | // emit->append( new Chuck_Instr_Func_Call_Member( 0 ) ); | ||
| 4966 | // else | ||
| 4967 | // emit->append( new Chuck_Instr_Func_Call ); | ||
| 4968 | //} | ||
| 4969 | } | ||
| 4970 | |||
| 4971 | return TRUE; | ||
| 4972 | }*/ | ||
| @@ -0,0 +1,176 @@ | |||
| 1 | /*---------------------------------------------------------------------------- | ||
| 2 | ChucK Concurrent, On-the-fly Audio Programming Language | ||
| 3 | Compiler and Virtual Machine | ||
| 4 | |||
| 5 | Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. | ||
| 6 | http://chuck.stanford.edu/ | ||
| 7 | http://chuck.cs.princeton.edu/ | ||
| 8 | |||
| 9 | This program is free software; you can redistribute it and/or modify | ||
| 10 | it under the terms of the GNU General Public License as published by | ||
| 11 | the Free Software Foundation; either version 2 of the License, or | ||
| 12 | (at your option) any later version. | ||
| 13 | |||
| 14 | This program is distributed in the hope that it will be useful, | ||
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | GNU General Public License for more details. | ||
| 18 | |||
| 19 | You should have received a copy of the GNU General Public License | ||
| 20 | along with this program; if not, write to the Free Software | ||
| 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
| 22 | U.S.A. | ||
| 23 | -----------------------------------------------------------------------------*/ | ||
| 24 | |||
| 25 | //----------------------------------------------------------------------------- | ||
| 26 | // file: chuck_emit.h | ||
| 27 | // desc: chuck instruction emitter | ||
| 28 | // | ||
| 29 | // author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) | ||
| 30 | // date: Autumn 2002 - first version | ||
| 31 | // Autumn 2004 - redesign | ||
| 32 | //----------------------------------------------------------------------------- | ||
| 33 | #ifndef __CHUCK_EMIT_H__ | ||
| 34 | #define __CHUCK_EMIT_H__ | ||
| 35 | |||
| 36 | #include "chuck_def.h" | ||
| 37 | #include "chuck_oo.h" | ||
| 38 | #include "chuck_type.h" | ||
| 39 | #include "chuck_frame.h" | ||
| 40 | |||
| 41 | |||
| 42 | // forward references | ||
| 43 | struct Chuck_Instr; | ||
| 44 | struct Chuck_Instr_Goto; | ||
| 45 | struct Chuck_VM_Code; | ||
| 46 | struct Chuck_VM_Shred; | ||
| 47 | |||
| 48 | |||
| 49 | |||
| 50 | |||
| 51 | //----------------------------------------------------------------------------- | ||
| 52 | // name: struct Chuck_Code | ||
| 53 | // desc: ... | ||
| 54 | //----------------------------------------------------------------------------- | ||
| 55 | struct Chuck_Code | ||
| 56 | { | ||
| 57 | public: | ||
| 58 | // name | ||
| 59 | std::string name; | ||
| 60 | // stack depth | ||
| 61 | t_CKUINT stack_depth; | ||
| 62 | // need this | ||
| 63 | t_CKBOOL need_this; | ||
| 64 | // frame | ||
| 65 | Chuck_Frame * frame; | ||
| 66 | // code | ||
| 67 | std::vector<Chuck_Instr *> code; | ||
| 68 | |||
| 69 | // continue stack | ||
| 70 | std::vector<Chuck_Instr_Goto *> stack_cont; | ||
| 71 | // break stack | ||
| 72 | std::vector<Chuck_Instr_Goto *> stack_break; | ||
| 73 | // return stack | ||
| 74 | std::vector<Chuck_Instr_Goto *> stack_return; | ||
| 75 | |||
| 76 | // filename this code came from (added 1.3.0.0) | ||
| 77 | std::string filename; | ||
| 78 | |||
| 79 | // constructor | ||
| 80 | Chuck_Code( ) | ||
| 81 | { | ||
| 82 | stack_depth = 0; | ||
| 83 | need_this = FALSE; | ||
| 84 | frame = new Chuck_Frame; | ||
| 85 | } | ||
| 86 | |||
| 87 | // destructor | ||
| 88 | ~Chuck_Code() { delete frame; frame = NULL; } | ||
| 89 | }; | ||
| 90 | |||
| 91 | |||
| 92 | |||
| 93 | |||
| 94 | //----------------------------------------------------------------------------- | ||
| 95 | // name: struct Chuck_Emitter | ||
| 96 | // desc: ... | ||
| 97 | //----------------------------------------------------------------------------- | ||
| 98 | struct Chuck_Emitter : public Chuck_VM_Object | ||
| 99 | { | ||
| 100 | // reference to the type checker environment | ||
| 101 | Chuck_Env * env; | ||
| 102 | // reference to VM | ||
| 103 | Chuck_VM * vm; | ||
| 104 | |||
| 105 | // current code | ||
| 106 | Chuck_Code * code; | ||
| 107 | // current context | ||
| 108 | Chuck_Context * context; | ||
| 109 | // expression namespace | ||
| 110 | Chuck_Namespace * nspc; | ||
| 111 | // current function definition | ||
| 112 | Chuck_Func * func; | ||
| 113 | |||
| 114 | // code stack | ||
| 115 | std::vector<Chuck_Code *> stack; | ||
| 116 | // locals | ||
| 117 | std::vector<Chuck_Local *> locals; | ||
| 118 | |||
| 119 | // dump | ||
| 120 | t_CKBOOL dump; | ||
| 121 | |||
| 122 | // constructor | ||
| 123 | Chuck_Emitter() | ||
| 124 | { env = NULL; vm = NULL; code = NULL; context = NULL; | ||
| 125 | nspc = NULL; func = NULL; dump = FALSE; } | ||
| 126 | |||
| 127 | // destructor | ||
| 128 | ~Chuck_Emitter() | ||
| 129 | { } | ||
| 130 | |||
| 131 | // append instruction | ||
| 132 | void append( Chuck_Instr * instr ) | ||
| 133 | { assert( code != NULL ); code->code.push_back( instr ); } | ||
| 134 | // index | ||
| 135 | t_CKUINT next_index() | ||
| 136 | { assert( code != NULL ); return code->code.size(); } | ||
| 137 | |||
| 138 | // push scope | ||
| 139 | void push_scope( ) | ||
| 140 | { assert( code != NULL ); code->frame->push_scope(); } | ||
| 141 | // alloc local (ge: added is_obj 2012 april | added 1.3.0.0) | ||
| 142 | Chuck_Local * alloc_local( t_CKUINT size, const std::string & name, t_CKBOOL is_ref, t_CKBOOL is_obj ) | ||
| 143 | { assert( code != NULL ); return code->frame->alloc_local( size, name, is_ref, is_obj ); } | ||
| 144 | // add references to locals on current scope (added 1.3.0.0) | ||
| 145 | void addref_on_scope(); | ||
| 146 | // pop scope | ||
| 147 | void pop_scope( ); | ||
| 148 | |||
| 149 | // default durations | ||
| 150 | t_CKBOOL find_dur( const std::string & name, t_CKDUR * out ); | ||
| 151 | }; | ||
| 152 | |||
| 153 | |||
| 154 | |||
| 155 | |||
| 156 | // allocate the emitter | ||
| 157 | Chuck_Emitter * emit_engine_init( Chuck_Env * env ); | ||
| 158 | // shutdown and free the emitter | ||
| 159 | t_CKBOOL emit_engine_shutdown( Chuck_Emitter *& emit ); | ||
| 160 | // emit a program into vm code | ||
| 161 | Chuck_VM_Code * emit_engine_emit_prog( Chuck_Emitter * emit, | ||
| 162 | a_Program prog, | ||
| 163 | te_HowMuch how_much = te_do_all ); | ||
| 164 | // helper function to emit code | ||
| 165 | Chuck_VM_Code * emit_to_code( Chuck_Code * in, | ||
| 166 | Chuck_VM_Code * out = NULL, | ||
| 167 | t_CKBOOL dump = FALSE ); | ||
| 168 | |||
| 169 | // NOT USED: ... | ||
| 170 | t_CKBOOL emit_engine_addr_map( Chuck_Emitter * emit, Chuck_VM_Shred * shred ); | ||
| 171 | t_CKBOOL emit_engine_resolve( ); | ||
| 172 | |||
| 173 | |||
| 174 | |||
| 175 | |||
| 176 | #endif | ||
| @@ -0,0 +1,650 @@ | |||
| 1 | /*---------------------------------------------------------------------------- | ||
| 2 | ChucK Concurrent, On-the-fly Audio Programming Language | ||
| 3 | Compiler and Virtual Machine | ||
| 4 | |||
| 5 | Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. | ||
| 6 | http://chuck.stanford.edu/ | ||
| 7 | http://chuck.cs.princeton.edu/ | ||
| 8 | |||
| 9 | This program is free software; you can redistribute it and/or modify | ||
| 10 | it under the terms of the GNU General Public License as published by | ||
| 11 | the Free Software Foundation; either version 2 of the License, or | ||
| 12 | (at your option) any later version. | ||
| 13 | |||
| 14 | This program is distributed in the hope that it will be useful, | ||
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | GNU General Public License for more details. | ||
| 18 | |||
| 19 | You should have received a copy of the GNU General Public License | ||
| 20 | along with this program; if not, write to the Free Software | ||
| 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
| 22 | U.S.A. | ||
| 23 | -----------------------------------------------------------------------------*/ | ||
| 24 | |||
| 25 | //----------------------------------------------------------------------------- | ||
| 26 | // file: errmsg.cpp | ||
| 27 | // desc: functions used in all phases of the compiler to give error messages | ||
| 28 | // based on Andrew Appel's Tiger code | ||
| 29 | // | ||
| 30 | // author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) | ||
| 31 | // based on code by: Andrew Appel (appel@cs.princeton.edu) | ||
| 32 | // date: Summer 2002 | ||
| 33 | //----------------------------------------------------------------------------- | ||
| 34 | #include <stdlib.h> | ||
| 35 | #include <stdarg.h> | ||
| 36 | #include <string.h> | ||
| 37 | #include <sstream> | ||
| 38 | #include <iostream> | ||
| 39 | #include "chuck_utils.h" | ||
| 40 | #include "chuck_errmsg.h" | ||
| 41 | #include "util_thread.h" | ||
| 42 | |||
| 43 | |||
| 44 | // global | ||
| 45 | int EM_tokPos = 0; | ||
| 46 | int EM_lineNum = 1; | ||
| 47 | int EM_extLineNum = 1; | ||
| 48 | t_CKBOOL anyErrors= FALSE; | ||
| 49 | |||
| 50 | // local global | ||
| 51 | static const char * fileName = ""; | ||
| 52 | static int lineNum = 1; | ||
| 53 | static char g_buffer[1024] = ""; | ||
| 54 | static const size_t LASTERROR_SIZE = 1024; | ||
| 55 | static char g_lasterror[LASTERROR_SIZE] = "[chuck]: (no error)"; | ||
| 56 | static size_t g_lasterrorIndex = strlen(g_lasterror); | ||
| 57 | // log globals | ||
| 58 | int g_loglevel = CK_LOG_CORE; | ||
| 59 | int g_logstack = 0; | ||
| 60 | XMutex g_logmutex; | ||
| 61 | |||
| 62 | // more local globals | ||
| 63 | static const size_t g_buffer2_size = 1024; | ||
| 64 | static char g_buffer2[g_buffer2_size] = ""; | ||
| 65 | std::stringstream g_stdout_stream; | ||
| 66 | std::stringstream g_stderr_stream; | ||
| 67 | |||
| 68 | // local global callbacks | ||
| 69 | void (*g_stdout_callback)(const char *) = NULL; | ||
| 70 | void (*g_stderr_callback)(const char *) = NULL; | ||
| 71 | |||
| 72 | void ck_fprintf_stdout( const char * format, ... ) | ||
| 73 | { | ||
| 74 | // evaluate the format string | ||
| 75 | va_list args; | ||
| 76 | va_start( args, format ); | ||
| 77 | vsnprintf( g_buffer2, g_buffer2_size, format, args ); | ||
| 78 | va_end( args ); | ||
| 79 | |||
| 80 | // send the formatted string to the buffer | ||
| 81 | g_stdout_stream << g_buffer2; | ||
| 82 | |||
| 83 | // try flushing | ||
| 84 | ck_fflush_stdout(); | ||
| 85 | } | ||
| 86 | |||
| 87 | |||
| 88 | void ck_fprintf_stderr( const char * format, ... ) | ||
| 89 | { | ||
| 90 | // evaluate the format string | ||
| 91 | va_list args; | ||
| 92 | va_start( args, format ); | ||
| 93 | vsnprintf( g_buffer2, g_buffer2_size, format, args ); | ||
| 94 | va_end( args ); | ||
| 95 | |||
| 96 | // send the formatted string to the buffer | ||
| 97 | g_stderr_stream << g_buffer2; | ||
| 98 | |||
| 99 | // try flushing | ||
| 100 | ck_fflush_stderr(); | ||
| 101 | } | ||
| 102 | |||
| 103 | |||
| 104 | void ck_fflush_stdout() | ||
| 105 | { | ||
| 106 | // check if stream contains a newline | ||
| 107 | if( g_stdout_stream.str().find( '\n' ) != std::string::npos ) | ||
| 108 | { | ||
| 109 | // if so, print it | ||
| 110 | if( g_stdout_callback == NULL ) { | ||
| 111 | // send to stdout | ||
| 112 | fprintf( stdout, "%s", g_stdout_stream.str().c_str() ); | ||
| 113 | } | ||
| 114 | else | ||
| 115 | { | ||
| 116 | // emit to callback | ||
| 117 | g_stdout_callback( g_stdout_stream.str().c_str() ); | ||
| 118 | } | ||
| 119 | // and clear buffer | ||
| 120 | g_stdout_stream.str( std::string() ); | ||
| 121 | |||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | |||
| 126 | void ck_fflush_stderr() | ||
| 127 | { | ||
| 128 | // check if stream contains a newline | ||
| 129 | if( g_stderr_stream.str().find( '\n' ) != std::string::npos ) | ||
| 130 | { | ||
| 131 | // if so, print it | ||
| 132 | if( g_stderr_callback == NULL ) | ||
| 133 | { | ||
| 134 | // send to stderr | ||
| 135 | fprintf( stderr, "%s", g_stderr_stream.str().c_str() ); | ||
| 136 | } | ||
| 137 | else | ||
| 138 | { | ||
| 139 | // emit to callback | ||
| 140 | g_stderr_callback( g_stderr_stream.str().c_str() ); | ||
| 141 | } | ||
| 142 | |||
| 143 | // and clear buffer | ||
| 144 | g_stderr_stream.str( std::string() ); | ||
| 145 | } | ||
| 146 | } | ||
| 147 | |||
| 148 | |||
| 149 | void ck_vfprintf_stdout( const char * format, va_list args ) | ||
| 150 | { | ||
| 151 | // evaluate the format string | ||
| 152 | vsnprintf( g_buffer2, g_buffer2_size, format, args ); | ||
| 153 | |||
| 154 | // send the formatted string to the buffer | ||
| 155 | g_stdout_stream << g_buffer2; | ||
| 156 | |||
| 157 | // try flushing | ||
| 158 | ck_fflush_stdout(); | ||
| 159 | } | ||
| 160 | |||
| 161 | |||
| 162 | void ck_vfprintf_stderr( const char * format, va_list args ) | ||
| 163 | { | ||
| 164 | // evaluate the format string | ||
| 165 | vsnprintf( g_buffer2, g_buffer2_size, format, args ); | ||
| 166 | |||
| 167 | // send the formatted string to the buffer | ||
| 168 | g_stderr_stream << g_buffer2; | ||
| 169 | |||
| 170 | // try flushing | ||
| 171 | ck_fflush_stderr(); | ||
| 172 | } | ||
| 173 | |||
| 174 | |||
| 175 | |||
| 176 | void ck_set_stdout_callback( void (*callback)(const char *) ) | ||
| 177 | { | ||
| 178 | g_stdout_callback = callback; | ||
| 179 | #ifdef __cplusplus | ||
| 180 | g_ck_stdoutstream.set_callback( callback ); | ||
| 181 | #endif | ||
| 182 | } | ||
| 183 | |||
| 184 | |||
| 185 | void ck_set_stderr_callback( void (*callback)(const char *) ) | ||
| 186 | { | ||
| 187 | g_stderr_callback = callback; | ||
| 188 | #ifdef __cplusplus | ||
| 189 | g_ck_stderrstream.set_callback( callback ); | ||
| 190 | #endif | ||
| 191 | } | ||
| 192 | |||
| 193 | #ifdef __cplusplus | ||
| 194 | extern "C++" { | ||
| 195 | |||
| 196 | ChuckOutStream::ChuckOutStream( bool isErr ) | ||
| 197 | { | ||
| 198 | m_callback = NULL; | ||
| 199 | m_isErr = isErr; | ||
| 200 | } | ||
| 201 | |||
| 202 | |||
| 203 | ChuckOutStream::~ChuckOutStream() | ||
| 204 | { | ||
| 205 | } | ||
| 206 | |||
| 207 | |||
| 208 | ChuckOutStream& ChuckOutStream::operator<<( const std::string val ) | ||
| 209 | { | ||
| 210 | m_stream << val; | ||
| 211 | if( val == CK_STDENDL ) | ||
| 212 | { | ||
| 213 | this->flush(); | ||
| 214 | } | ||
| 215 | return *this; | ||
| 216 | } | ||
| 217 | |||
| 218 | |||
| 219 | ChuckOutStream& ChuckOutStream::operator<<( const char * val ) | ||
| 220 | { | ||
| 221 | m_stream << val; | ||
| 222 | return *this; | ||
| 223 | } | ||
| 224 | |||
| 225 | |||
| 226 | ChuckOutStream& ChuckOutStream::operator<<( const double val ) | ||
| 227 | { | ||
| 228 | m_stream << val; | ||
| 229 | return *this; | ||
| 230 | } | ||
| 231 | |||
| 232 | |||
| 233 | ChuckOutStream& ChuckOutStream::operator<<( const float val ) | ||
| 234 | { | ||
| 235 | m_stream << val; | ||
| 236 | return *this; | ||
| 237 | } | ||
| 238 | |||
| 239 | |||
| 240 | ChuckOutStream& ChuckOutStream::operator<<( const unsigned long long val ) | ||
| 241 | { | ||
| 242 | m_stream << val; | ||
| 243 | return *this; | ||
| 244 | } | ||
| 245 | |||
| 246 | |||
| 247 | ChuckOutStream& ChuckOutStream::operator<<( const long long val ) | ||
| 248 | { | ||
| 249 | m_stream << val; | ||
| 250 | return *this; | ||
| 251 | } | ||
| 252 | |||
| 253 | |||
| 254 | ChuckOutStream& ChuckOutStream::operator<<( const unsigned long val ) | ||
| 255 | { | ||
| 256 | m_stream << val; | ||
| 257 | return *this; | ||
| 258 | } | ||
| 259 | |||
| 260 | |||
| 261 | ChuckOutStream& ChuckOutStream::operator<<( const long val ) | ||
| 262 | { | ||
| 263 | m_stream << val; | ||
| 264 | return *this; | ||
| 265 | } | ||
| 266 | |||
| 267 | |||
| 268 | ChuckOutStream& ChuckOutStream::operator<<( const unsigned int val ) | ||
| 269 | { | ||
| 270 | m_stream << val; | ||
| 271 | return *this; | ||
| 272 | } | ||
| 273 | |||
| 274 | |||
| 275 | ChuckOutStream& ChuckOutStream::operator<<( const int val ) | ||
| 276 | { | ||
| 277 | m_stream << val; | ||
| 278 | return *this; | ||
| 279 | } | ||
| 280 | |||
| 281 | |||
| 282 | ChuckOutStream& ChuckOutStream::operator<<( const bool val ) | ||
| 283 | { | ||
| 284 | m_stream << val; | ||
| 285 | return *this; | ||
| 286 | } | ||
| 287 | |||
| 288 | |||
| 289 | |||
| 290 | |||
| 291 | |||
| 292 | void ChuckOutStream::set_callback( void (*callback)( const char * ) ) | ||
| 293 | { | ||
| 294 | m_callback = callback; | ||
| 295 | } | ||
| 296 | |||
| 297 | |||
| 298 | void ChuckOutStream::flush() | ||
| 299 | { | ||
| 300 | if( m_callback != NULL ) | ||
| 301 | { | ||
| 302 | // send to callback | ||
| 303 | m_callback( m_stream.str().c_str() ); | ||
| 304 | } | ||
| 305 | else | ||
| 306 | { | ||
| 307 | // print it | ||
| 308 | if( m_isErr ) | ||
| 309 | { | ||
| 310 | // to cerr | ||
| 311 | std::cerr << m_stream.str().c_str(); | ||
| 312 | std::cerr.flush(); | ||
| 313 | } | ||
| 314 | else | ||
| 315 | { | ||
| 316 | // to cout | ||
| 317 | std::cout << m_stream.str().c_str(); | ||
| 318 | std::cout.flush(); | ||
| 319 | } | ||
| 320 | } | ||
| 321 | // clear buffer | ||
| 322 | m_stream.str( std::string() ); | ||
| 323 | } | ||
| 324 | |||
| 325 | |||
| 326 | ChuckOutStream g_ck_stdoutstream( FALSE ); | ||
| 327 | ChuckOutStream g_ck_stderrstream( TRUE ); | ||
| 328 | |||
| 329 | } | ||
| 330 | #endif | ||
| 331 | |||
| 332 | |||
| 333 | |||
| 334 | |||
| 335 | // name | ||
| 336 | static const char * g_str[] = { | ||
| 337 | "NONE", // 0 | ||
| 338 | "CKCORE", // 1 | ||
| 339 | "SYSTEM", // 2 | ||
| 340 | "SEVERE", // 3 | ||
| 341 | "WARN!!", // 4 | ||
| 342 | "INFORM", // 5 | ||
| 343 | "CONFIG", // 6 | ||
| 344 | "FINE!!", // 7 | ||
| 345 | "FINER!", // 8 | ||
| 346 | "FINEST", // 9 | ||
| 347 | "ALL!!" // 10 | ||
| 348 | }; | ||
| 349 | |||
| 350 | |||
| 351 | // intList | ||
| 352 | typedef struct intList {int i; struct intList *rest;} *IntList; | ||
| 353 | static IntList linePos=NULL; | ||
| 354 | |||
| 355 | |||
| 356 | static int lastErrorCat(const char * str) | ||
| 357 | { | ||
| 358 | assert(g_lasterrorIndex <= LASTERROR_SIZE-1); | ||
| 359 | |||
| 360 | size_t len = strlen(str); | ||
| 361 | |||
| 362 | strncat(g_lasterror, str, LASTERROR_SIZE-g_lasterrorIndex-1); | ||
| 363 | |||
| 364 | size_t appendCount = ck_min(LASTERROR_SIZE-g_lasterrorIndex-1, len); | ||
| 365 | g_lasterrorIndex += appendCount; | ||
| 366 | |||
| 367 | return appendCount > 0; | ||
| 368 | } | ||
| 369 | |||
| 370 | |||
| 371 | // constructor | ||
| 372 | static IntList intList( int i, IntList rest ) | ||
| 373 | { | ||
| 374 | IntList l = (IntList)checked_malloc(sizeof *l); | ||
| 375 | l->i=i; l->rest=rest; | ||
| 376 | return l; | ||
| 377 | } | ||
| 378 | |||
| 379 | |||
| 380 | // new line in lexer | ||
| 381 | void EM_newline(void) | ||
| 382 | { | ||
| 383 | lineNum++; | ||
| 384 | EM_lineNum++; | ||
| 385 | EM_extLineNum++; | ||
| 386 | linePos = intList(EM_tokPos, linePos); | ||
| 387 | } | ||
| 388 | |||
| 389 | |||
| 390 | // content after rightmost '/' | ||
| 391 | const char * mini( const char * str ) | ||
| 392 | { | ||
| 393 | int len = strlen( str ); | ||
| 394 | const char * p = str + len; | ||
| 395 | while( p != str && *p != '/' && *p != '\\' ) p--; | ||
| 396 | return ( p == str || strlen(p+1) == 0 ? p : p+1 ); | ||
| 397 | } | ||
| 398 | |||
| 399 | |||
| 400 | // content after 'struct' | ||
| 401 | const char * mini_type( const char * str ) | ||
| 402 | { | ||
| 403 | if( !strncmp( str, "struct ", 7 ) ) str += 7; | ||
| 404 | const char * p = str; | ||
| 405 | while( *p && *p >= '0' && *p <= '9' ) p++; | ||
| 406 | return p; | ||
| 407 | } | ||
| 408 | |||
| 409 | void EM_reset_msg() | ||
| 410 | { | ||
| 411 | g_lasterror[0] = '\0'; | ||
| 412 | g_lasterrorIndex = 0; | ||
| 413 | } | ||
| 414 | |||
| 415 | // [%s]:line(%d).char(%d): | ||
| 416 | void EM_error( int pos, const char * message, ... ) | ||
| 417 | { | ||
| 418 | va_list ap; | ||
| 419 | IntList lines = linePos; | ||
| 420 | int num = lineNum; | ||
| 421 | |||
| 422 | anyErrors = TRUE; | ||
| 423 | while( lines && lines->i >= pos ) | ||
| 424 | { | ||
| 425 | lines = lines->rest; | ||
| 426 | num--; | ||
| 427 | } | ||
| 428 | |||
| 429 | // separate errmsgs with newlines | ||
| 430 | if( g_lasterror[0] != '\0' ) lastErrorCat( "\n" ); | ||
| 431 | |||
| 432 | CK_FPRINTF_STDERR( "[%s]:", *fileName ? mini(fileName) : "chuck" ); | ||
| 433 | sprintf( g_buffer, "[%s]:", *fileName ? mini(fileName) : "chuck" ); | ||
| 434 | lastErrorCat( g_buffer ); | ||
| 435 | if(lines) | ||
| 436 | { | ||
| 437 | CK_FPRINTF_STDERR( "line(%d).char(%d):", num, pos-lines->i ); | ||
| 438 | sprintf( g_buffer, "line(%d).char(%d):", num, pos-lines->i ); | ||
| 439 | lastErrorCat( g_buffer ); | ||
| 440 | } | ||
| 441 | CK_FPRINTF_STDERR( " " ); | ||
| 442 | lastErrorCat( " " ); | ||
| 443 | |||
| 444 | va_start(ap, message); | ||
| 445 | CK_VFPRINTF_STDERR( message, ap); | ||
| 446 | va_end(ap); | ||
| 447 | |||
| 448 | va_start(ap, message); | ||
| 449 | vsprintf( g_buffer, message, ap ); | ||
| 450 | va_end(ap); | ||
| 451 | |||
| 452 | CK_FPRINTF_STDERR( "\n"); | ||
| 453 | CK_FFLUSH_STDERR(); | ||
| 454 | lastErrorCat( g_buffer ); | ||
| 455 | } | ||
| 456 | |||
| 457 | |||
| 458 | // [%s]:line(%d): | ||
| 459 | void EM_error2( int line, const char * message, ... ) | ||
| 460 | { | ||
| 461 | va_list ap; | ||
| 462 | |||
| 463 | EM_extLineNum = line; | ||
| 464 | |||
| 465 | // separate errmsgs with newlines | ||
| 466 | if( g_lasterror[0] != '\0' ) lastErrorCat( "\n" ); | ||
| 467 | |||
| 468 | CK_FPRINTF_STDERR( "[%s]:", *fileName ? mini(fileName) : "chuck" ); | ||
| 469 | sprintf( g_buffer, "[%s]:", *fileName ? mini(fileName) : "chuck" ); | ||
| 470 | lastErrorCat( g_buffer ); | ||
| 471 | if(line) | ||
| 472 | { | ||
| 473 | CK_FPRINTF_STDERR( "line(%d):", line ); | ||
| 474 | sprintf( g_buffer, "line(%d):", line ); | ||
| 475 | lastErrorCat( g_buffer ); | ||
| 476 | } | ||
| 477 | CK_FPRINTF_STDERR( " " ); | ||
| 478 | lastErrorCat( " " ); | ||
| 479 | |||
| 480 | va_start( ap, message ); | ||
| 481 | CK_VFPRINTF_STDERR( message, ap ); | ||
| 482 | va_end( ap ); | ||
| 483 | |||
| 484 | va_start( ap, message ); | ||
| 485 | vsprintf( g_buffer, message, ap ); | ||
| 486 | va_end( ap ); | ||
| 487 | |||
| 488 | lastErrorCat( g_buffer ); | ||
| 489 | CK_FPRINTF_STDERR( "\n" ); | ||
| 490 | CK_FFLUSH_STDERR(); | ||
| 491 | } | ||
| 492 | |||
| 493 | |||
| 494 | // [%s]:line(%d): | ||
| 495 | void EM_error2b( int line, const char * message, ... ) | ||
| 496 | { | ||
| 497 | va_list ap; | ||
| 498 | |||
| 499 | EM_extLineNum = line; | ||
| 500 | |||
| 501 | // separate errmsgs with newlines | ||
| 502 | if( g_lasterror[0] != '\0' ) lastErrorCat( "\n" ); | ||
| 503 | |||
| 504 | CK_FPRINTF_STDERR( "[%s]:", *fileName ? mini(fileName) : "chuck" ); | ||
| 505 | sprintf( g_buffer, "[%s]:", *fileName ? mini(fileName) : "chuck" ); | ||
| 506 | lastErrorCat( g_buffer ); | ||
| 507 | if(line) | ||
| 508 | { | ||
| 509 | CK_FPRINTF_STDERR( "line(%d):", line ); | ||
| 510 | sprintf( g_buffer, "line(%d):", line ); | ||
| 511 | lastErrorCat( g_buffer ); | ||
| 512 | } | ||
| 513 | CK_FPRINTF_STDERR( " " ); | ||
| 514 | lastErrorCat( " " ); | ||
| 515 | |||
| 516 | va_start( ap, message ); | ||
| 517 | CK_VFPRINTF_STDERR( message, ap ); | ||
| 518 | va_end( ap ); | ||
| 519 | |||
| 520 | va_start( ap, message ); | ||
| 521 | vsprintf( g_buffer, message, ap ); | ||
| 522 | va_end( ap ); | ||
| 523 | |||
| 524 | lastErrorCat( g_buffer ); | ||
| 525 | CK_FPRINTF_STDOUT( "\n" ); | ||
| 526 | CK_FFLUSH_STDOUT(); | ||
| 527 | } | ||
| 528 | |||
| 529 | |||
| 530 | // | ||
| 531 | void EM_error3( const char * message, ... ) | ||
| 532 | { | ||
| 533 | va_list ap; | ||
| 534 | |||
| 535 | // separate errmsgs with newlines | ||
| 536 | if( g_lasterror[0] != '\0' ) lastErrorCat( "\n" ); | ||
| 537 | |||
| 538 | // g_lasterror[0] = '\0'; | ||
| 539 | g_buffer[0] = '\0'; | ||
| 540 | |||
| 541 | va_start( ap, message ); | ||
| 542 | CK_VFPRINTF_STDERR( message, ap ); | ||
| 543 | va_end( ap ); | ||
| 544 | |||
| 545 | va_start( ap, message ); | ||
| 546 | vsprintf( g_buffer, message, ap ); | ||
| 547 | va_end( ap ); | ||
| 548 | |||
| 549 | lastErrorCat( g_buffer ); | ||
| 550 | CK_FPRINTF_STDERR( "\n" ); | ||
| 551 | CK_FFLUSH_STDERR(); | ||
| 552 | } | ||
| 553 | |||
| 554 | |||
| 555 | // log | ||
| 556 | void EM_log( int level, const char * message, ... ) | ||
| 557 | { | ||
| 558 | va_list ap; | ||
| 559 | |||
| 560 | if( level > CK_LOG_CRAZY ) level = CK_LOG_CRAZY; | ||
| 561 | else if( level <= CK_LOG_NONE ) level = CK_LOG_NONE + 1; | ||
| 562 | |||
| 563 | // check level | ||
| 564 | if( level > g_loglevel ) return; | ||
| 565 | |||
| 566 | g_logmutex.acquire(); | ||
| 567 | CK_FPRINTF_STDERR( "[chuck]:" ); | ||
| 568 | CK_FPRINTF_STDERR( "(%i:%s): ", level, g_str[level] ); | ||
| 569 | |||
| 570 | // if( g_logstack ) CK_FPRINTF_STDERR( " " ); | ||
| 571 | for( int i = 0; i < g_logstack; i++ ) | ||
| 572 | CK_FPRINTF_STDERR( " | " ); | ||
| 573 | |||
| 574 | va_start( ap, message ); | ||
| 575 | CK_VFPRINTF_STDERR( message, ap ); | ||
| 576 | va_end( ap ); | ||
| 577 | |||
| 578 | CK_FPRINTF_STDERR( "\n" ); | ||
| 579 | CK_FFLUSH_STDERR(); | ||
| 580 | g_logmutex.release(); | ||
| 581 | } | ||
| 582 | |||
| 583 | |||
| 584 | // set log level | ||
| 585 | void EM_setlog( int level ) | ||
| 586 | { | ||
| 587 | if( level > CK_LOG_CRAZY ) level = CK_LOG_CRAZY; | ||
| 588 | else if( level < CK_LOG_NONE ) level = CK_LOG_NONE; | ||
| 589 | g_loglevel = level; | ||
| 590 | |||
| 591 | // log this | ||
| 592 | EM_log( CK_LOG_SYSTEM, "setting log level to: %i (%s)...", level, g_str[level] ); | ||
| 593 | } | ||
| 594 | |||
| 595 | // push log | ||
| 596 | void EM_pushlog() | ||
| 597 | { | ||
| 598 | g_logstack++; | ||
| 599 | } | ||
| 600 | |||
| 601 | // pop log | ||
| 602 | void EM_poplog() | ||
| 603 | { | ||
| 604 | g_logstack--; | ||
| 605 | if( g_logstack < 0 ) g_logstack = 0; | ||
| 606 | } | ||
| 607 | |||
| 608 | // prepare new file | ||
| 609 | t_CKBOOL EM_reset( const char * fname, FILE * fd ) | ||
| 610 | { | ||
| 611 | anyErrors = FALSE; | ||
| 612 | fileName = fname ? fname : (c_str)""; | ||
| 613 | lineNum = 1; | ||
| 614 | EM_lineNum = 1; | ||
| 615 | EM_extLineNum = 1; | ||
| 616 | |||
| 617 | // free the intList | ||
| 618 | IntList curr = NULL; | ||
| 619 | while( linePos ) | ||
| 620 | { | ||
| 621 | curr = linePos; | ||
| 622 | linePos = linePos->rest; | ||
| 623 | // free | ||
| 624 | free( curr ); | ||
| 625 | } | ||
| 626 | |||
| 627 | // make new intList | ||
| 628 | linePos = intList( 0, NULL ); | ||
| 629 | |||
| 630 | return TRUE; | ||
| 631 | } | ||
| 632 | |||
| 633 | |||
| 634 | // change file | ||
| 635 | void EM_change_file( const char * fname ) | ||
| 636 | { | ||
| 637 | // set | ||
| 638 | fileName = fname ? fname : (c_str)""; | ||
| 639 | // more set | ||
| 640 | lineNum = 0; | ||
| 641 | EM_lineNum = 0; | ||
| 642 | EM_extLineNum = 0; | ||
| 643 | } | ||
| 644 | |||
| 645 | |||
| 646 | // return last error | ||
| 647 | const char * EM_lasterror() | ||
| 648 | { | ||
| 649 | return g_lasterror; | ||
| 650 | } | ||
| @@ -0,0 +1,177 @@ | |||
| 1 | /*---------------------------------------------------------------------------- | ||
| 2 | ChucK Concurrent, On-the-fly Audio Programming Language | ||
| 3 | Compiler and Virtual Machine | ||
| 4 | |||
| 5 | Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. | ||
| 6 | http://chuck.stanford.edu/ | ||
| 7 | http://chuck.cs.princeton.edu/ | ||
| 8 | |||
| 9 | This program is free software; you can redistribute it and/or modify | ||
| 10 | it under the terms of the GNU General Public License as published by | ||
| 11 | the Free Software Foundation; either version 2 of the License, or | ||
| 12 | (at your option) any later version. | ||
| 13 | |||
| 14 | This program is distributed in the hope that it will be useful, | ||
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | GNU General Public License for more details. | ||
| 18 | |||
| 19 | You should have received a copy of the GNU General Public License | ||
| 20 | along with this program; if not, write to the Free Software | ||
| 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
| 22 | U.S.A. | ||
| 23 | -----------------------------------------------------------------------------*/ | ||
| 24 | |||
| 25 | //----------------------------------------------------------------------------- | ||
| 26 | // file: errmsg.h | ||
| 27 | // desc: functions used in all phases of the compiler to give error messages | ||
| 28 | // based on Andrew Appel's Tiger code | ||
| 29 | // | ||
| 30 | // author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) | ||
| 31 | // based on code by: Andrew Appel (appel@cs.princeton.edu) | ||
| 32 | // date: Summer 2002 | ||
| 33 | //----------------------------------------------------------------------------- | ||
| 34 | #ifndef __CHUCK_ERRORMSG_H__ | ||
| 35 | #define __CHUCK_ERRORMSG_H__ | ||
| 36 | |||
| 37 | #include "chuck_def.h" | ||
| 38 | #include <stdio.h> | ||
| 39 | |||
| 40 | |||
| 41 | #if defined(_cplusplus) || defined(__cplusplus) | ||
| 42 | extern "C" { | ||
| 43 | #endif | ||
| 44 | |||
| 45 | |||
| 46 | extern t_CKBOOL EM_anyErrors; | ||
| 47 | extern int EM_tokPos; | ||
| 48 | extern int EM_lineNum; | ||
| 49 | |||
| 50 | // EM_extLineNum is synced with EM_lineNum in lexer/parser phase, then synced | ||
| 51 | // with scanner/typechecker (EM_lineNum is not synced with scanner/typechecker) | ||
| 52 | extern int EM_extLineNum; | ||
| 53 | |||
| 54 | void EM_newline( ); | ||
| 55 | |||
| 56 | // levels | ||
| 57 | #define CK_LOG_CRAZY 10 // set this to log everything | ||
| 58 | #define CK_LOG_FINEST 9 | ||
| 59 | #define CK_LOG_FINER 8 | ||
| 60 | #define CK_LOG_FINE 7 | ||
| 61 | #define CK_LOG_CONFIG 6 | ||
| 62 | #define CK_LOG_INFO 5 | ||
| 63 | #define CK_LOG_WARNING 4 | ||
| 64 | #define CK_LOG_SEVERE 3 | ||
| 65 | #define CK_LOG_SYSTEM 2 | ||
| 66 | #define CK_LOG_CORE 1 | ||
| 67 | #define CK_LOG_NONE 0 // set this to log nothing | ||
| 68 | |||
| 69 | |||
| 70 | //----------------------------------------------------------------------------- | ||
| 71 | // REFACTOR-2017: (jack) -- callback printing | ||
| 72 | //----------------------------------------------------------------------------- | ||
| 73 | // printing | ||
| 74 | void ck_fprintf_stdout( const char * format, ... ); | ||
| 75 | void ck_fprintf_stderr( const char * format, ... ); | ||
| 76 | void ck_fflush_stdout(); | ||
| 77 | void ck_fflush_stderr(); | ||
| 78 | void ck_vfprintf_stdout( const char * format, va_list args ); | ||
| 79 | void ck_vfprintf_stderr( const char * format, va_list args ); | ||
| 80 | |||
| 81 | // callbacks | ||
| 82 | void ck_set_stdout_callback( void (*callback)(const char *) ); | ||
| 83 | void ck_set_stderr_callback( void (*callback)(const char *) ); | ||
| 84 | |||
| 85 | #define CK_FPRINTF_STDOUT(...) ck_fprintf_stdout(__VA_ARGS__) | ||
| 86 | #define CK_FPRINTF_STDERR(...) ck_fprintf_stderr(__VA_ARGS__) | ||
| 87 | #define CK_FFLUSH_STDOUT() ck_fflush_stdout() | ||
| 88 | #define CK_FFLUSH_STDERR() ck_fflush_stderr() | ||
| 89 | #define CK_VFPRINTF_STDOUT(message, ap) ck_vfprintf_stdout(message, ap) | ||
| 90 | #define CK_VFPRINTF_STDERR(message, ap) ck_vfprintf_stderr(message, ap) | ||
| 91 | |||
| 92 | #ifdef __cplusplus | ||
| 93 | // c++: custom stream-like thing | ||
| 94 | extern "C++" { | ||
| 95 | #include <sstream> | ||
| 96 | |||
| 97 | class ChuckOutStream | ||
| 98 | { | ||
| 99 | public: | ||
| 100 | ChuckOutStream( bool isErr ); | ||
| 101 | ~ChuckOutStream(); | ||
| 102 | |||
| 103 | // there's probably a way to do this with templates or something | ||
| 104 | // this is not that way | ||
| 105 | ChuckOutStream& operator<<( const std::string val ); | ||
| 106 | ChuckOutStream& operator<<( const char * val ); | ||
| 107 | ChuckOutStream& operator<<( const double val ); | ||
| 108 | ChuckOutStream& operator<<( const float val ); | ||
| 109 | ChuckOutStream& operator<<( const unsigned long long val ); | ||
| 110 | ChuckOutStream& operator<<( const long long val ); | ||
| 111 | ChuckOutStream& operator<<( const unsigned long val ); | ||
| 112 | ChuckOutStream& operator<<( const long val ); | ||
| 113 | ChuckOutStream& operator<<( const unsigned int val ); | ||
| 114 | ChuckOutStream& operator<<( const int val ); | ||
| 115 | ChuckOutStream& operator<<( const bool val ); | ||
| 116 | |||
| 117 | void set_callback( void (*callback)(const char *) ); | ||
| 118 | |||
| 119 | private: | ||
| 120 | void flush(); | ||
| 121 | std::stringstream m_stream; | ||
| 122 | void (*m_callback)(const char *); | ||
| 123 | bool m_isErr; | ||
| 124 | }; | ||
| 125 | |||
| 126 | |||
| 127 | extern ChuckOutStream g_ck_stdoutstream; | ||
| 128 | extern ChuckOutStream g_ck_stderrstream; | ||
| 129 | |||
| 130 | #define CK_STDCOUT g_ck_stdoutstream | ||
| 131 | #define CK_STDCERR g_ck_stderrstream | ||
| 132 | #define CK_STDENDL std::string("\n") | ||
| 133 | |||
| 134 | } | ||
| 135 | #else | ||
| 136 | // c: oh well | ||
| 137 | #define CK_STDCOUT std::cout | ||
| 138 | #define CK_STDCERR std::cerr | ||
| 139 | #define CK_STDENDL std::endl | ||
| 140 | |||
| 141 | #endif | ||
| 142 | //----------------------------------------------------------------------------- | ||
| 143 | // here endeth the callback printing | ||
| 144 | //----------------------------------------------------------------------------- | ||
| 145 | |||
| 146 | |||
| 147 | |||
| 148 | |||
| 149 | void EM_log( int, c_constr, ... ); | ||
| 150 | void EM_setlog( int ); | ||
| 151 | void EM_pushlog(); | ||
| 152 | void EM_poplog(); | ||
| 153 | |||
| 154 | // actual level | ||
| 155 | extern int g_loglevel; | ||
| 156 | // macro to compare | ||
| 157 | #define DO_LOG(x) ( x <= g_loglevel ) | ||
| 158 | |||
| 159 | void EM_error( int, c_constr, ... ); | ||
| 160 | void EM_error2( int, c_constr, ... ); | ||
| 161 | void EM_error2b( int, c_constr, ... ); | ||
| 162 | void EM_error3( c_constr, ... ); | ||
| 163 | void EM_impossible( c_constr, ... ); | ||
| 164 | t_CKBOOL EM_reset( c_constr filename, FILE * fd ); | ||
| 165 | void EM_change_file( c_constr filename ); | ||
| 166 | const char * EM_lasterror(); | ||
| 167 | void EM_reset_msg(); | ||
| 168 | |||
| 169 | const char * mini( const char * str ); | ||
| 170 | const char * mini_type( const char * str ); | ||
| 171 | |||
| 172 | #if defined(_cplusplus) || defined(__cplusplus) | ||
| 173 | } | ||
| 174 | #endif | ||
| 175 | |||
| 176 | |||
| 177 | #endif | ||
| @@ -0,0 +1,163 @@ | |||
| 1 | /*---------------------------------------------------------------------------- | ||
| 2 | ChucK Concurrent, On-the-fly Audio Programming Language | ||
| 3 | Compiler and Virtual Machine | ||
| 4 | |||
| 5 | Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. | ||
| 6 | http://chuck.stanford.edu/ | ||
| 7 | http://chuck.cs.princeton.edu/ | ||
| 8 | |||
| 9 | This program is free software; you can redistribute it and/or modify | ||
| 10 | it under the terms of the GNU General Public License as published by | ||
| 11 | the Free Software Foundation; either version 2 of the License, or | ||
| 12 | (at your option) any later version. | ||
| 13 | |||
| 14 | This program is distributed in the hope that it will be useful, | ||
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | GNU General Public License for more details. | ||
| 18 | |||
| 19 | You should have received a copy of the GNU General Public License | ||
| 20 | along with this program; if not, write to the Free Software | ||
| 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
| 22 | U.S.A. | ||
| 23 | -----------------------------------------------------------------------------*/ | ||
| 24 | |||
| 25 | //----------------------------------------------------------------------------- | ||
| 26 | // file: chuck_frame.cpp | ||
| 27 | // desc: chuck scope frame | ||
| 28 | // | ||
| 29 | // author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) | ||
| 30 | // date: Autumn 2002 | ||
| 31 | //----------------------------------------------------------------------------- | ||
| 32 | #include "chuck_frame.h" | ||
| 33 | using namespace std; | ||
| 34 | |||
| 35 | |||
| 36 | |||
| 37 | |||
| 38 | //----------------------------------------------------------------------------- | ||
| 39 | // name: Chuck_Frame() | ||
| 40 | // desc: ... | ||
| 41 | //----------------------------------------------------------------------------- | ||
| 42 | Chuck_Frame::Chuck_Frame() | ||
| 43 | { | ||
| 44 | // name | ||
| 45 | name = ""; | ||
| 46 | // ofset | ||
| 47 | curr_offset = 0; | ||
| 48 | // don't know | ||
| 49 | num_access = 0; | ||
| 50 | } | ||
| 51 | |||
| 52 | |||
| 53 | |||
| 54 | |||
| 55 | //----------------------------------------------------------------------------- | ||
| 56 | // name: alloc_local() | ||
| 57 | // desc: ... | ||
| 58 | //----------------------------------------------------------------------------- | ||
| 59 | Chuck_Local * Chuck_Frame::alloc_local( t_CKUINT size, const string & name, | ||
| 60 | t_CKBOOL is_ref, t_CKBOOL is_obj ) | ||
| 61 | { | ||
| 62 | // alloc | ||
| 63 | Chuck_Local * local = new Chuck_Local; | ||
| 64 | // size | ||
| 65 | local->size = size; | ||
| 66 | // the offset | ||
| 67 | local->offset = this->curr_offset; | ||
| 68 | // ref | ||
| 69 | local->is_ref = is_ref; | ||
| 70 | // is object type? (added ge: 2012 april | added 1.3.0.0) | ||
| 71 | local->is_obj = is_obj; | ||
| 72 | // the next offset | ||
| 73 | this->curr_offset += local->size; | ||
| 74 | // name | ||
| 75 | local->name = name; | ||
| 76 | // push the local | ||
| 77 | this->stack.push_back( local ); | ||
| 78 | |||
| 79 | return local; | ||
| 80 | } | ||
| 81 | |||
| 82 | |||
| 83 | |||
| 84 | |||
| 85 | //----------------------------------------------------------------------------- | ||
| 86 | // name: push_scope() | ||
| 87 | // desc: ... | ||
| 88 | //----------------------------------------------------------------------------- | ||
| 89 | void Chuck_Frame::push_scope( ) | ||
| 90 | { | ||
| 91 | stack.push_back( NULL ); | ||
| 92 | } | ||
| 93 | |||
| 94 | |||
| 95 | |||
| 96 | |||
| 97 | //----------------------------------------------------------------------------- | ||
| 98 | // name: get_scope() | ||
| 99 | // desc: get current scope (added 1.3.0.0) | ||
| 100 | //----------------------------------------------------------------------------- | ||
| 101 | void Chuck_Frame::get_scope( vector<Chuck_Local *> & out ) const | ||
| 102 | { | ||
| 103 | // sanity | ||
| 104 | assert( this->stack.size() > 0 ); | ||
| 105 | |||
| 106 | // the local | ||
| 107 | Chuck_Local * local = NULL; | ||
| 108 | // the index | ||
| 109 | long index = this->stack.size() - 1; | ||
| 110 | |||
| 111 | // loop | ||
| 112 | while( index >= 0 && this->stack[index] != NULL ) | ||
| 113 | { | ||
| 114 | // last thing | ||
| 115 | local = stack[index]; | ||
| 116 | // move | ||
| 117 | index--; | ||
| 118 | // check if not null | ||
| 119 | if( local ) | ||
| 120 | { | ||
| 121 | // copy out | ||
| 122 | out.push_back( local ); | ||
| 123 | } | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | |||
| 128 | |||
| 129 | |||
| 130 | //----------------------------------------------------------------------------- | ||
| 131 | // name: pop_scope() | ||
| 132 | // desc: .... | ||
| 133 | //----------------------------------------------------------------------------- | ||
| 134 | void Chuck_Frame::pop_scope( vector<Chuck_Local *> & out ) | ||
| 135 | { | ||
| 136 | // sanity | ||
| 137 | assert( this->stack.size() > 0 ); | ||
| 138 | |||
| 139 | // the local | ||
| 140 | Chuck_Local * local = NULL; | ||
| 141 | |||
| 142 | // loop | ||
| 143 | while( this->stack.size() && this->stack.back() ) | ||
| 144 | { | ||
| 145 | // last thing | ||
| 146 | local = stack.back(); | ||
| 147 | // pop | ||
| 148 | stack.pop_back(); | ||
| 149 | // check if not null | ||
| 150 | if( local ) | ||
| 151 | { | ||
| 152 | // offset | ||
| 153 | curr_offset -= local->size; | ||
| 154 | // copy out (NOTE: these locals should be memory managed outside) | ||
| 155 | out.push_back( local ); | ||
| 156 | } | ||
| 157 | } | ||
| 158 | |||
| 159 | // sanity (should be at least one left) | ||
| 160 | assert( this->stack.size() > 0 ); | ||
| 161 | // get ride of null boundary character (added 1.3.0.0) | ||
| 162 | this->stack.pop_back(); | ||
| 163 | } | ||
| @@ -0,0 +1,101 @@ | |||
| 1 | /*---------------------------------------------------------------------------- | ||
| 2 | ChucK Concurrent, On-the-fly Audio Programming Language | ||
| 3 | Compiler and Virtual Machine | ||
| 4 | |||
| 5 | Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. | ||
| 6 | http://chuck.stanford.edu/ | ||
| 7 | http://chuck.cs.princeton.edu/ | ||
| 8 | |||
| 9 | This program is free software; you can redistribute it and/or modify | ||
| 10 | it under the terms of the GNU General Public License as published by | ||
| 11 | the Free Software Foundation; either version 2 of the License, or | ||
| 12 | (at your option) any later version. | ||
| 13 | |||
| 14 | This program is distributed in the hope that it will be useful, | ||
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | GNU General Public License for more details. | ||
| 18 | |||
| 19 | You should have received a copy of the GNU General Public License | ||
| 20 | along with this program; if not, write to the Free Software | ||
| 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
| 22 | U.S.A. | ||
| 23 | -----------------------------------------------------------------------------*/ | ||
| 24 | |||
| 25 | //----------------------------------------------------------------------------- | ||
| 26 | // file: chuck_frame.h | ||
| 27 | // desc: chuck scope frame | ||
| 28 | // | ||
| 29 | // author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) | ||
| 30 | // date: Autumn 2002 | ||
| 31 | //----------------------------------------------------------------------------- | ||
| 32 | #ifndef __CHUCK_FRAME_H__ | ||
| 33 | #define __CHUCK_FRAME_H__ | ||
| 34 | |||
| 35 | #include "chuck_def.h" | ||
| 36 | |||
| 37 | #include <string> | ||
| 38 | #include <vector> | ||
| 39 | |||
| 40 | |||
| 41 | //----------------------------------------------------------------------------- | ||
| 42 | // name: struct Chuck_Local | ||
| 43 | // desc: ... | ||
| 44 | //----------------------------------------------------------------------------- | ||
| 45 | struct Chuck_Local | ||
| 46 | { | ||
| 47 | // name | ||
| 48 | std::string name; | ||
| 49 | // the size of the local | ||
| 50 | t_CKUINT size; | ||
| 51 | // is ref | ||
| 52 | t_CKBOOL is_ref; | ||
| 53 | // is an object type (added ge: 2012 april | added 1.3.0.0) | ||
| 54 | t_CKBOOL is_obj; | ||
| 55 | // the offset | ||
| 56 | t_CKUINT offset; | ||
| 57 | |||
| 58 | // constructor | ||
| 59 | Chuck_Local() | ||
| 60 | // (added 1.3.0.0 -- is_obj) | ||
| 61 | { size = 0; is_ref = FALSE; is_obj = FALSE; offset = 0; } | ||
| 62 | }; | ||
| 63 | |||
| 64 | |||
| 65 | |||
| 66 | |||
| 67 | //----------------------------------------------------------------------------- | ||
| 68 | // name: struct Chuck_Frame | ||
| 69 | // desc: ... | ||
| 70 | //----------------------------------------------------------------------------- | ||
| 71 | struct Chuck_Frame | ||
| 72 | { | ||
| 73 | // yes | ||
| 74 | std::string name; | ||
| 75 | // the offset | ||
| 76 | t_CKUINT curr_offset; | ||
| 77 | // not sure | ||
| 78 | t_CKUINT num_access; | ||
| 79 | // offset stack | ||
| 80 | std::vector<Chuck_Local *> stack; | ||
| 81 | |||
| 82 | public: | ||
| 83 | Chuck_Frame(); | ||
| 84 | ~Chuck_Frame() { } | ||
| 85 | |||
| 86 | public: | ||
| 87 | // push scope | ||
| 88 | void push_scope(); | ||
| 89 | // add local (added 1.3.0.0 -- is_obj) | ||
| 90 | Chuck_Local * alloc_local( t_CKUINT size, const std::string & name, | ||
| 91 | t_CKBOOL is_ref, t_CKBOOL is_obj ); | ||
| 92 | // get the current scope (added 1.3.0.0) | ||
| 93 | void get_scope( std::vector<Chuck_Local *> & out ) const; | ||
| 94 | // pop scope | ||
| 95 | void pop_scope( std::vector<Chuck_Local *> & out ); | ||
| 96 | }; | ||
| 97 | |||
| 98 | |||
| 99 | |||
| 100 | |||
| 101 | #endif | ||
| @@ -0,0 +1,1950 @@ | |||
| 1 | /*---------------------------------------------------------------------------- | ||
| 2 | ChucK Concurrent, On-the-fly Audio Programming Language | ||
| 3 | Compiler and Virtual Machine | ||
| 4 | |||
| 5 | Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. | ||
| 6 | http://chuck.stanford.edu/ | ||
| 7 | http://chuck.cs.princeton.edu/ | ||
| 8 | |||
| 9 | This program is free software; you can redistribute it and/or modify | ||
| 10 | it under the terms of the GNU General Public License as published by | ||
| 11 | the Free Software Foundation; either version 2 of the License, or | ||
| 12 | (at your option) any later version. | ||
| 13 | |||
| 14 | This program is distributed in the hope that it will be useful, | ||
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | GNU General Public License for more details. | ||
| 18 | |||
| 19 | You should have received a copy of the GNU General Public License | ||
| 20 | along with this program; if not, write to the Free Software | ||
| 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
| 22 | U.S.A. | ||
| 23 | -----------------------------------------------------------------------------*/ | ||
| 24 | |||
| 25 | //----------------------------------------------------------------------------- | ||
| 26 | // name: chuck_io.cpp | ||
| 27 | // desc: chuck i/o | ||
| 28 | // | ||
| 29 | // authors: Spencer Salazar (spencer@ccrma.stanford.edu) | ||
| 30 | // date: Summer 2012 | ||
| 31 | //----------------------------------------------------------------------------- | ||
| 32 | #include "chuck_io.h" | ||
| 33 | #include "chuck_errmsg.h" | ||
| 34 | #include "util_serial.h" | ||
| 35 | #include "chuck_instr.h" | ||
| 36 | #include "chuck_type.h" | ||
| 37 | #include "chuck_globals.h" | ||
| 38 | #include "chuck_vm.h" | ||
| 39 | |||
| 40 | #ifndef __WINDOWS_DS__ | ||
| 41 | #include <sys/select.h> | ||
| 42 | #include <poll.h> | ||
| 43 | #include <termios.h> | ||
| 44 | #include <unistd.h> | ||
| 45 | #else | ||
| 46 | #include <io.h> | ||
| 47 | #endif // __WINDOWS_DS__ | ||
| 48 | #include <fcntl.h> | ||
| 49 | #include <math.h> | ||
| 50 | |||
| 51 | #include <iostream> | ||
| 52 | #include <fstream> | ||
| 53 | using namespace std; | ||
| 54 | |||
| 55 | |||
| 56 | #ifdef __WINDOWS_DS__ | ||
| 57 | typedef BYTE uint8_t; | ||
| 58 | typedef WORD uint16_t; | ||
| 59 | // ge: this needed in earlier/some versions of windows | ||
| 60 | #ifndef __WINDOWS_MODERN__ | ||
| 61 | typedef DWORD uint32_t; | ||
| 62 | #endif | ||
| 63 | #endif | ||
| 64 | |||
| 65 | |||
| 66 | // available baud rates | ||
| 67 | const t_CKUINT Chuck_IO_Serial::CK_BAUD_2400 = 2400; | ||
| 68 | const t_CKUINT Chuck_IO_Serial::CK_BAUD_4800 = 4800; | ||
| 69 | const t_CKUINT Chuck_IO_Serial::CK_BAUD_9600 = 9600; | ||
| 70 | const t_CKUINT Chuck_IO_Serial::CK_BAUD_19200 = 19200; | ||
| 71 | const t_CKUINT Chuck_IO_Serial::CK_BAUD_38400 = 38400; | ||
| 72 | const t_CKUINT Chuck_IO_Serial::CK_BAUD_7200 = 7200; | ||
| 73 | const t_CKUINT Chuck_IO_Serial::CK_BAUD_14400 = 14400; | ||
| 74 | const t_CKUINT Chuck_IO_Serial::CK_BAUD_28800 = 28800; | ||
| 75 | const t_CKUINT Chuck_IO_Serial::CK_BAUD_57600 = 57600; | ||
| 76 | const t_CKUINT Chuck_IO_Serial::CK_BAUD_76800 = 76800; | ||
| 77 | const t_CKUINT Chuck_IO_Serial::CK_BAUD_115200 = 115200; | ||
| 78 | const t_CKUINT Chuck_IO_Serial::CK_BAUD_230400 = 230400; | ||
| 79 | |||
| 80 | const t_CKUINT Chuck_IO_Serial::TYPE_NONE = 0; | ||
| 81 | const t_CKUINT Chuck_IO_Serial::TYPE_BYTE = 1; | ||
| 82 | const t_CKUINT Chuck_IO_Serial::TYPE_WORD = 2; | ||
| 83 | const t_CKUINT Chuck_IO_Serial::TYPE_INT = 3; | ||
| 84 | const t_CKUINT Chuck_IO_Serial::TYPE_FLOAT = 4; | ||
| 85 | const t_CKUINT Chuck_IO_Serial::TYPE_STRING = 5; | ||
| 86 | const t_CKUINT Chuck_IO_Serial::TYPE_LINE = 6; | ||
| 87 | const t_CKUINT Chuck_IO_Serial::TYPE_WRITE = 100; | ||
| 88 | |||
| 89 | std::list<Chuck_IO_Serial *> Chuck_IO_Serial::s_serials; | ||
| 90 | |||
| 91 | // static const t_CKUINT TYPE_NONE = 0; | ||
| 92 | // static const t_CKUINT TYPE_BYTE = 1; | ||
| 93 | // static const t_CKUINT TYPE_WORD = 2; | ||
| 94 | // static const t_CKUINT TYPE_INT = 3; | ||
| 95 | // static const t_CKUINT TYPE_FLOAT = 4; | ||
| 96 | // static const t_CKUINT TYPE_STRING = 5; | ||
| 97 | // static const t_CKUINT TYPE_LINE = 6; | ||
| 98 | // static const t_CKUINT TYPE_WRITE = 100; | ||
| 99 | |||
| 100 | const t_CKUINT CHUCK_IO_DEFAULT_BUFSIZE = 1024; | ||
| 101 | const char * CHUCK_IO_SCANF_STRING = "%1024s"; | ||
| 102 | |||
| 103 | CK_DLL_MFUN(serialio_canWait); | ||
| 104 | |||
| 105 | void * Chuck_IO_Serial::shell_read_cb( void *_this ) | ||
| 106 | { | ||
| 107 | Chuck_IO_Serial *cereal = (Chuck_IO_Serial *) _this; | ||
| 108 | |||
| 109 | cereal->read_cb(); | ||
| 110 | |||
| 111 | return NULL; | ||
| 112 | } | ||
| 113 | |||
| 114 | void * Chuck_IO_Serial::shell_write_cb( void *_this ) | ||
| 115 | { | ||
| 116 | Chuck_IO_Serial *cereal = (Chuck_IO_Serial *) _this; | ||
| 117 | |||
| 118 | cereal->write_cb(); | ||
| 119 | |||
| 120 | return NULL; | ||
| 121 | } | ||
| 122 | |||
| 123 | void Chuck_IO_Serial::shutdown() | ||
| 124 | { | ||
| 125 | EM_log(CK_LOG_INFO, "shutting down serial devices"); | ||
| 126 | |||
| 127 | for(std::list<Chuck_IO_Serial *>::iterator i = s_serials.begin(); i != s_serials.end(); i++) | ||
| 128 | { | ||
| 129 | (*i)->close(); | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | |||
| 134 | Chuck_IO_Serial::Chuck_IO_Serial( Chuck_VM * vm ) : | ||
| 135 | m_asyncRequests(CircularBuffer<Request>(32)), | ||
| 136 | m_asyncResponses(CircularBuffer<Request>(32)), | ||
| 137 | m_asyncWriteRequests(CircularBuffer<Request>(32)), | ||
| 138 | m_writeBuffer(1024) | ||
| 139 | { | ||
| 140 | m_fd = -1; | ||
| 141 | m_cfd = NULL; | ||
| 142 | |||
| 143 | m_io_buf_max = CHUCK_IO_DEFAULT_BUFSIZE; | ||
| 144 | m_io_buf = new unsigned char[m_io_buf_max]; | ||
| 145 | m_io_buf_pos = m_io_buf_available = 0; | ||
| 146 | |||
| 147 | m_tmp_buf_max = CHUCK_IO_DEFAULT_BUFSIZE; | ||
| 148 | m_tmp_buf = new unsigned char[m_tmp_buf_max]; | ||
| 149 | |||
| 150 | m_read_thread = NULL; | ||
| 151 | m_event_buffer = NULL; | ||
| 152 | |||
| 153 | m_write_thread = NULL; | ||
| 154 | m_do_write_thread = TRUE; | ||
| 155 | |||
| 156 | m_do_exit = FALSE; | ||
| 157 | |||
| 158 | s_serials.push_back(this); | ||
| 159 | |||
| 160 | m_vmRef = vm; | ||
| 161 | } | ||
| 162 | |||
| 163 | Chuck_IO_Serial::~Chuck_IO_Serial() | ||
| 164 | { | ||
| 165 | m_do_read_thread = FALSE; | ||
| 166 | m_do_write_thread = FALSE; | ||
| 167 | SAFE_DELETE(m_read_thread); | ||
| 168 | if( m_event_buffer ) | ||
| 169 | m_vmRef->destroy_event_buffer( m_event_buffer ); | ||
| 170 | |||
| 171 | close(); | ||
| 172 | |||
| 173 | SAFE_DELETE(m_io_buf); | ||
| 174 | m_io_buf_max = 0; | ||
| 175 | m_io_buf_pos = m_io_buf_available = 0; | ||
| 176 | |||
| 177 | SAFE_DELETE(m_tmp_buf); | ||
| 178 | m_tmp_buf_max = 0; | ||
| 179 | |||
| 180 | s_serials.remove(this); | ||
| 181 | } | ||
| 182 | |||
| 183 | t_CKBOOL Chuck_IO_Serial::ready() | ||
| 184 | { | ||
| 185 | #ifndef __WINDOWS_DS__ | ||
| 186 | struct pollfd pollfds; | ||
| 187 | pollfds.fd = m_fd; | ||
| 188 | pollfds.events = POLLIN; | ||
| 189 | pollfds.revents = 0; | ||
| 190 | |||
| 191 | int result = poll(&pollfds, 1, 0); | ||
| 192 | |||
| 193 | if( result > 0 && (pollfds.revents & POLLIN) ) return TRUE; | ||
| 194 | else return FALSE; // TODO: error handling | ||
| 195 | #else | ||
| 196 | return FALSE; | ||
| 197 | #endif | ||
| 198 | } | ||
| 199 | |||
| 200 | t_CKBOOL Chuck_IO_Serial::open( const t_CKUINT i, t_CKINT flags, t_CKUINT baud ) | ||
| 201 | { | ||
| 202 | vector<string> ports = SerialIOManager::availableSerialDevices(); | ||
| 203 | |||
| 204 | if( i < ports.size() ) | ||
| 205 | { | ||
| 206 | const string &path = ports[i]; | ||
| 207 | |||
| 208 | open(path, flags, baud); | ||
| 209 | } | ||
| 210 | else | ||
| 211 | { | ||
| 212 | EM_log(CK_LOG_WARNING, "(Serial.open): error: invalid port number"); | ||
| 213 | return FALSE; | ||
| 214 | } | ||
| 215 | |||
| 216 | return TRUE; | ||
| 217 | } | ||
| 218 | |||
| 219 | |||
| 220 | t_CKBOOL Chuck_IO_Serial::open( const std::string & path, t_CKINT flags, t_CKUINT baud ) | ||
| 221 | { | ||
| 222 | if( flags & Chuck_IO_File::TYPE_BINARY ) | ||
| 223 | { | ||
| 224 | m_flags = Chuck_IO_File::TYPE_BINARY; | ||
| 225 | } | ||
| 226 | else if( flags & Chuck_IO_File::TYPE_ASCII ) | ||
| 227 | { | ||
| 228 | m_flags = Chuck_IO_File::TYPE_ASCII; | ||
| 229 | } | ||
| 230 | else | ||
| 231 | { | ||
| 232 | EM_log(CK_LOG_WARNING, "(Serial.open): warning: invalid binary/ASCII flag requested, defaulting to ASCII"); | ||
| 233 | m_flags = Chuck_IO_File::TYPE_ASCII; | ||
| 234 | } | ||
| 235 | |||
| 236 | int fd = ::open( path.c_str(), O_RDWR ); | ||
| 237 | if( fd < 0 ) | ||
| 238 | { | ||
| 239 | EM_log(CK_LOG_WARNING, "(Serial.open): error: unable to open file at '%s'", path.c_str()); | ||
| 240 | return FALSE; | ||
| 241 | } | ||
| 242 | |||
| 243 | m_fd = fd; | ||
| 244 | m_path = path; | ||
| 245 | |||
| 246 | // set default baud rate | ||
| 247 | setBaudRate(baud); | ||
| 248 | |||
| 249 | m_cfd = fdopen(fd, "a+"); | ||
| 250 | m_iomode = MODE_ASYNC; | ||
| 251 | #ifndef WIN32 | ||
| 252 | fcntl(m_fd, F_SETFL, O_NONBLOCK); | ||
| 253 | #endif | ||
| 254 | m_eof = FALSE; | ||
| 255 | |||
| 256 | return TRUE; | ||
| 257 | } | ||
| 258 | |||
| 259 | |||
| 260 | t_CKBOOL Chuck_IO_Serial::good() | ||
| 261 | { | ||
| 262 | return m_fd >= 0 && m_cfd != NULL; | ||
| 263 | } | ||
| 264 | |||
| 265 | void Chuck_IO_Serial::close() | ||
| 266 | { | ||
| 267 | if(m_iomode == MODE_SYNC) | ||
| 268 | { | ||
| 269 | close_int(); | ||
| 270 | } | ||
| 271 | else | ||
| 272 | { | ||
| 273 | m_do_exit = TRUE; | ||
| 274 | #ifdef WIN32 | ||
| 275 | m_read_thread->wait(-1, TRUE); | ||
| 276 | close_int(); | ||
| 277 | #else | ||
| 278 | m_read_thread->wait(-1, FALSE); | ||
| 279 | #endif | ||
| 280 | } | ||
| 281 | } | ||
| 282 | |||
| 283 | void Chuck_IO_Serial::close_int() | ||
| 284 | { | ||
| 285 | EM_log(CK_LOG_INFO, "(Serial.close): closing serial device '%s'", m_path.c_str()); | ||
| 286 | |||
| 287 | if(good()) | ||
| 288 | { | ||
| 289 | if(m_cfd) | ||
| 290 | fclose(m_cfd); | ||
| 291 | else | ||
| 292 | ::close(m_fd); | ||
| 293 | m_fd = -1; | ||
| 294 | m_cfd = NULL; | ||
| 295 | } | ||
| 296 | } | ||
| 297 | |||
| 298 | void Chuck_IO_Serial::flush() | ||
| 299 | { | ||
| 300 | if(good()) | ||
| 301 | { | ||
| 302 | if(m_iomode == MODE_SYNC) | ||
| 303 | fflush(m_cfd); | ||
| 304 | else | ||
| 305 | ; // TODO | ||
| 306 | } | ||
| 307 | } | ||
| 308 | |||
| 309 | t_CKBOOL Chuck_IO_Serial::can_wait() | ||
| 310 | { | ||
| 311 | return m_asyncResponses.numElements() == 0; | ||
| 312 | } | ||
| 313 | |||
| 314 | t_CKINT Chuck_IO_Serial::mode() | ||
| 315 | { | ||
| 316 | return m_iomode; | ||
| 317 | } | ||
| 318 | |||
| 319 | void Chuck_IO_Serial::mode( t_CKINT flag ) | ||
| 320 | { | ||
| 321 | if( flag == MODE_SYNC ) | ||
| 322 | m_iomode = MODE_SYNC; | ||
| 323 | else if( flag == MODE_ASYNC ) | ||
| 324 | m_iomode = MODE_ASYNC; | ||
| 325 | } | ||
| 326 | |||
| 327 | // reading | ||
| 328 | t_CKINT Chuck_IO_Serial::readInt( t_CKINT flags ) | ||
| 329 | { | ||
| 330 | if( !good() ) | ||
| 331 | { | ||
| 332 | EM_log(CK_LOG_WARNING, "(Serial.readInt): warning: file not open"); | ||
| 333 | return 0; | ||
| 334 | } | ||
| 335 | |||
| 336 | if( m_iomode == MODE_ASYNC ) | ||
| 337 | { | ||
| 338 | EM_log(CK_LOG_WARNING, "(Serial.readInt): warning: calling synchronous read function on asynchronous file"); | ||
| 339 | return 0; | ||
| 340 | } | ||
| 341 | |||
| 342 | t_CKINT i = 0; | ||
| 343 | |||
| 344 | if( m_flags & Chuck_IO_File::TYPE_BINARY ) | ||
| 345 | { | ||
| 346 | if( flags & INT8 ) | ||
| 347 | { | ||
| 348 | uint8_t byte = 0; | ||
| 349 | if(!fread(&byte, 1, 1, m_cfd)) | ||
| 350 | EM_log(CK_LOG_WARNING, "(Serial.readInt): error: read failed"); | ||
| 351 | |||
| 352 | i = byte; | ||
| 353 | } | ||
| 354 | else if( flags & INT16 ) | ||
| 355 | { | ||
| 356 | uint16_t word = 0; | ||
| 357 | if(!fread(&word, 2, 1, m_cfd)) | ||
| 358 | EM_log(CK_LOG_WARNING, "(Serial.readInt): error: read failed"); | ||
| 359 | |||
| 360 | i = word; | ||
| 361 | } | ||
| 362 | else if( flags & INT32 ) | ||
| 363 | { | ||
| 364 | uint32_t dword = 0; | ||
| 365 | if(!fread(&dword, 4, 1, m_cfd)) | ||
| 366 | EM_log(CK_LOG_WARNING, "(Serial.readInt): error: read failed"); | ||
| 367 | |||
| 368 | i = dword; | ||
| 369 | } | ||
| 370 | } | ||
| 371 | else | ||
| 372 | { | ||
| 373 | if(!fscanf(m_cfd, "%li", &i)) | ||
| 374 | EM_log(CK_LOG_WARNING, "(Serial.readInt): error: read failed"); | ||
| 375 | } | ||
| 376 | |||
| 377 | return i; | ||
| 378 | } | ||
| 379 | |||
| 380 | t_CKFLOAT Chuck_IO_Serial::readFloat() | ||
| 381 | { | ||
| 382 | if( !good() ) | ||
| 383 | { | ||
| 384 | EM_log(CK_LOG_WARNING, "(Serial.readFloat): warning: file not open"); | ||
| 385 | return 0; | ||
| 386 | } | ||
| 387 | |||
| 388 | if( m_iomode == MODE_ASYNC ) | ||
| 389 | { | ||
| 390 | EM_log(CK_LOG_WARNING, "(Serial.readFloat): warning: calling synchronous read function on asynchronous file"); | ||
| 391 | return 0; | ||
| 392 | } | ||
| 393 | |||
| 394 | t_CKFLOAT f = 0; | ||
| 395 | |||
| 396 | if( m_flags & Chuck_IO_File::TYPE_BINARY ) | ||
| 397 | { | ||
| 398 | if(!fread(&f, 4, 1, m_cfd)) | ||
| 399 | EM_log(CK_LOG_WARNING, "(Serial.readFloat): error: read failed"); | ||
| 400 | } | ||
| 401 | else | ||
| 402 | { | ||
| 403 | if(!fscanf(m_cfd, "%lf", &f)) | ||
| 404 | EM_log(CK_LOG_WARNING, "(Serial.readFloat): error: read failed"); | ||
| 405 | } | ||
| 406 | |||
| 407 | return f; | ||
| 408 | } | ||
| 409 | |||
| 410 | t_CKBOOL Chuck_IO_Serial::readString( std::string & str ) | ||
| 411 | { | ||
| 412 | if( !good() ) | ||
| 413 | { | ||
| 414 | EM_log(CK_LOG_WARNING, "(Serial.readString): warning: file not open"); | ||
| 415 | return FALSE; | ||
| 416 | } | ||
| 417 | |||
| 418 | if( m_iomode == MODE_ASYNC ) | ||
| 419 | { | ||
| 420 | EM_log(CK_LOG_WARNING, "(Serial.readString): warning: calling synchronous read function on asynchronous file"); | ||
| 421 | return FALSE; | ||
| 422 | } | ||
| 423 | |||
| 424 | if( m_flags & Chuck_IO_File::TYPE_BINARY ) | ||
| 425 | { | ||
| 426 | EM_log(CK_LOG_WARNING, "(Serial.readString): warning: cannot read string from binary file"); | ||
| 427 | return FALSE; | ||
| 428 | } | ||
| 429 | |||
| 430 | if(!fscanf(m_cfd, CHUCK_IO_SCANF_STRING, &m_tmp_buf)) | ||
| 431 | { | ||
| 432 | EM_log(CK_LOG_WARNING, "(Serial.readFloat): error: read failed"); | ||
| 433 | return FALSE; | ||
| 434 | } | ||
| 435 | |||
| 436 | str = (char *) m_tmp_buf; | ||
| 437 | |||
| 438 | return TRUE; | ||
| 439 | } | ||
| 440 | |||
| 441 | |||
| 442 | Chuck_String * Chuck_IO_Serial::readLine() | ||
| 443 | { | ||
| 444 | if( !good() ) | ||
| 445 | { | ||
| 446 | EM_log(CK_LOG_WARNING, "(Serial.readLine): warning: file not open"); | ||
| 447 | return NULL; | ||
| 448 | } | ||
| 449 | |||
| 450 | if( m_iomode == MODE_ASYNC ) | ||
| 451 | { | ||
| 452 | EM_log(CK_LOG_WARNING, "(Serial.readLine): warning: calling synchronous read function on asynchronous file"); | ||
| 453 | return NULL; | ||
| 454 | } | ||
| 455 | |||
| 456 | if( m_flags & Chuck_IO_File::TYPE_BINARY ) | ||
| 457 | { | ||
| 458 | EM_log(CK_LOG_WARNING, "(Serial.readLine): warning: cannot read line from binary file"); | ||
| 459 | return NULL; | ||
| 460 | } | ||
| 461 | |||
| 462 | |||
| 463 | if(!fgets((char *)m_tmp_buf, m_tmp_buf_max, m_cfd)) | ||
| 464 | { | ||
| 465 | EM_log(CK_LOG_WARNING, "(Serial.readLine): error: from fgets"); | ||
| 466 | return NULL; | ||
| 467 | } | ||
| 468 | |||
| 469 | Chuck_String * str = new Chuck_String; | ||
| 470 | initialize_object(str, m_vmRef->env()->t_string); | ||
| 471 | |||
| 472 | str->set( string((char *)m_tmp_buf) ); | ||
| 473 | |||
| 474 | return str; | ||
| 475 | } | ||
| 476 | |||
| 477 | |||
| 478 | t_CKBOOL Chuck_IO_Serial::eof() | ||
| 479 | { | ||
| 480 | if( !good() ) | ||
| 481 | { | ||
| 482 | EM_log(CK_LOG_WARNING, "(Serial.eof): warning: file not open"); | ||
| 483 | return FALSE; | ||
| 484 | } | ||
| 485 | |||
| 486 | if( MODE_SYNC ) | ||
| 487 | return (m_eof = feof( m_cfd )); | ||
| 488 | else | ||
| 489 | return m_eof; | ||
| 490 | } | ||
| 491 | |||
| 492 | |||
| 493 | // writing | ||
| 494 | void Chuck_IO_Serial::write( const std::string & val ) | ||
| 495 | { | ||
| 496 | if( !good() ) | ||
| 497 | { | ||
| 498 | EM_log(CK_LOG_WARNING, "(Serial.write): warning: file not open"); | ||
| 499 | return; | ||
| 500 | } | ||
| 501 | |||
| 502 | if( m_iomode == MODE_ASYNC ) | ||
| 503 | { | ||
| 504 | start_read_thread(); | ||
| 505 | |||
| 506 | int len = val.length(); | ||
| 507 | for(int i = 0; i < len; i++) | ||
| 508 | // TODO: efficiency | ||
| 509 | m_writeBuffer.put(val[i]); | ||
| 510 | |||
| 511 | Request r; | ||
| 512 | r.m_type = TYPE_WRITE; | ||
| 513 | r.m_val = 0; | ||
| 514 | r.m_num = 0; | ||
| 515 | r.m_status = Request::RQ_STATUS_PENDING; | ||
| 516 | |||
| 517 | m_asyncWriteRequests.put(r); | ||
| 518 | } | ||
| 519 | else if( m_iomode == MODE_SYNC ) | ||
| 520 | { | ||
| 521 | fprintf( m_cfd, "%s", val.c_str() ); | ||
| 522 | } | ||
| 523 | } | ||
| 524 | |||
| 525 | |||
| 526 | void Chuck_IO_Serial::write( t_CKINT val ) | ||
| 527 | { | ||
| 528 | write( val, 4 ); | ||
| 529 | } | ||
| 530 | |||
| 531 | |||
| 532 | void Chuck_IO_Serial::write( t_CKINT val, t_CKINT size ) | ||
| 533 | { | ||
| 534 | if( !good() ) | ||
| 535 | { | ||
| 536 | EM_log(CK_LOG_WARNING, "(Serial.write): warning: file not open"); | ||
| 537 | return; | ||
| 538 | } | ||
| 539 | |||
| 540 | if(!(size == 1 || size == 2 || size == 4 || size == 8)) | ||
| 541 | { | ||
| 542 | EM_log(CK_LOG_WARNING, "(Serial.write): warning: invalid int size %li, ignoring write request", size); | ||
| 543 | return; | ||
| 544 | } | ||
| 545 | |||
| 546 | if( m_iomode == MODE_ASYNC ) | ||
| 547 | { | ||
| 548 | start_read_thread(); | ||
| 549 | |||
| 550 | if( m_flags & Chuck_IO_File::TYPE_ASCII ) | ||
| 551 | { | ||
| 552 | // TODO: don't use m_tmp_buf (thread safety?) | ||
| 553 | #ifdef WIN32 | ||
| 554 | _snprintf((char *)m_tmp_buf, m_tmp_buf_max, "%li", val); | ||
| 555 | m_tmp_buf[m_tmp_buf_max - 1] = '\0'; // force NULL terminator -- see http://www.di-mgt.com.au/cprog.html#snprintf | ||
| 556 | #else | ||
| 557 | snprintf((char *)m_tmp_buf, m_tmp_buf_max, "%li", val); | ||
| 558 | #endif | ||
| 559 | int len = strlen((char *)m_tmp_buf); | ||
| 560 | for(int i = 0; i < len; i++) | ||
| 561 | // TODO: efficiency | ||
| 562 | m_writeBuffer.put(m_tmp_buf[i]); | ||
| 563 | |||
| 564 | Request r; | ||
| 565 | r.m_type = TYPE_WRITE; | ||
| 566 | r.m_val = 0; | ||
| 567 | r.m_num = 0; | ||
| 568 | r.m_status = Request::RQ_STATUS_PENDING; | ||
| 569 | |||
| 570 | m_asyncWriteRequests.put(r); | ||
| 571 | } | ||
| 572 | else | ||
| 573 | { | ||
| 574 | char * buf = (char *) &val; | ||
| 575 | |||
| 576 | // assume 4-byte int | ||
| 577 | for(int i = 0; i < size; i++) | ||
| 578 | m_writeBuffer.put(buf[i]); | ||
| 579 | |||
| 580 | Request r; | ||
| 581 | r.m_type = TYPE_WRITE; | ||
| 582 | r.m_val = 0; | ||
| 583 | r.m_num = 0; | ||
| 584 | r.m_status = Request::RQ_STATUS_PENDING; | ||
| 585 | |||
| 586 | m_asyncWriteRequests.put(r); | ||
| 587 | } | ||
| 588 | } | ||
| 589 | else if( m_iomode == MODE_SYNC ) | ||
| 590 | { | ||
| 591 | if( m_flags & Chuck_IO_File::TYPE_ASCII ) | ||
| 592 | { | ||
| 593 | fprintf( m_cfd, "%li", val ); | ||
| 594 | } | ||
| 595 | else | ||
| 596 | { | ||
| 597 | // assume 4-byte int | ||
| 598 | char * buf = (char *) &val; | ||
| 599 | fwrite(buf, 1, size, m_cfd); | ||
| 600 | } | ||
| 601 | } | ||
| 602 | } | ||
| 603 | |||
| 604 | void Chuck_IO_Serial::write( t_CKFLOAT val ) | ||
| 605 | { | ||
| 606 | if( !good() ) | ||
| 607 | { | ||
| 608 | EM_log(CK_LOG_WARNING, "(Serial.write): warning: file not open"); | ||
| 609 | return; | ||
| 610 | } | ||
| 611 | |||
| 612 | if( m_iomode == MODE_ASYNC ) | ||
| 613 | { | ||
| 614 | start_read_thread(); | ||
| 615 | |||
| 616 | if( m_flags & Chuck_IO_File::TYPE_ASCII ) | ||
| 617 | { | ||
| 618 | #ifdef WIN32 | ||
| 619 | _snprintf((char *)m_tmp_buf, m_tmp_buf_max, "%f", val); | ||
| 620 | m_tmp_buf[m_tmp_buf_max - 1] = '\0'; // force NULL terminator -- see http://www.di-mgt.com.au/cprog.html#snprintf | ||
| 621 | #else | ||
| 622 | snprintf((char *)m_tmp_buf, m_tmp_buf_max, "%f", val); | ||
| 623 | #endif | ||
| 624 | |||
| 625 | int len = strlen((char *)m_tmp_buf); | ||
| 626 | for(int i = 0; i < len; i++) | ||
| 627 | // TODO: efficiency | ||
| 628 | m_writeBuffer.put(m_tmp_buf[i]); | ||
| 629 | |||
| 630 | Request r; | ||
| 631 | r.m_type = TYPE_WRITE; | ||
| 632 | r.m_val = 0; | ||
| 633 | r.m_num = 0; | ||
| 634 | r.m_status = Request::RQ_STATUS_PENDING; | ||
| 635 | |||
| 636 | m_asyncWriteRequests.put(r); | ||
| 637 | } | ||
| 638 | else | ||
| 639 | { | ||
| 640 | char * buf = (char *) &val; | ||
| 641 | |||
| 642 | // assume 4-byte float | ||
| 643 | for(int i = 0; i < 4; i++) | ||
| 644 | m_writeBuffer.put(buf[i]); | ||
| 645 | |||
| 646 | Request r; | ||
| 647 | r.m_type = TYPE_WRITE; | ||
| 648 | r.m_val = 0; | ||
| 649 | r.m_num = 0; | ||
| 650 | r.m_status = Request::RQ_STATUS_PENDING; | ||
| 651 | |||
| 652 | m_asyncWriteRequests.put(r); | ||
| 653 | } | ||
| 654 | } | ||
| 655 | else if( m_iomode == MODE_SYNC ) | ||
| 656 | { | ||
| 657 | if( m_flags & Chuck_IO_File::TYPE_ASCII ) | ||
| 658 | { | ||
| 659 | fprintf( m_cfd, "%f", val ); | ||
| 660 | } | ||
| 661 | else | ||
| 662 | { | ||
| 663 | // assume 4-byte int | ||
| 664 | char * buf = (char *) &val; | ||
| 665 | fwrite(buf, 1, size, m_cfd); | ||
| 666 | } | ||
| 667 | } | ||
| 668 | } | ||
| 669 | |||
| 670 | |||
| 671 | void Chuck_IO_Serial::writeBytes( Chuck_Array4 * arr ) | ||
| 672 | { | ||
| 673 | if( !good() ) | ||
| 674 | { | ||
| 675 | EM_log(CK_LOG_WARNING, "(Serial.writeBytes): warning: file not open"); | ||
| 676 | return; | ||
| 677 | } | ||
| 678 | |||
| 679 | if( m_iomode == MODE_ASYNC ) | ||
| 680 | { | ||
| 681 | start_read_thread(); | ||
| 682 | |||
| 683 | int len = arr->size(); | ||
| 684 | for(int i = 0; i < len; i++) | ||
| 685 | { | ||
| 686 | // TODO: efficiency | ||
| 687 | t_CKUINT byte; | ||
| 688 | arr->get(i, &byte); | ||
| 689 | m_writeBuffer.put((char) byte); | ||
| 690 | } | ||
| 691 | |||
| 692 | Request r; | ||
| 693 | r.m_type = TYPE_WRITE; | ||
| 694 | r.m_val = 0; | ||
| 695 | r.m_num = 0; | ||
| 696 | r.m_status = Request::RQ_STATUS_PENDING; | ||
| 697 | |||
| 698 | m_asyncWriteRequests.put(r); | ||
| 699 | } | ||
| 700 | else if( m_iomode == MODE_SYNC ) | ||
| 701 | { | ||
| 702 | int len = arr->size(); | ||
| 703 | for(int i = 0; i < len; i++) | ||
| 704 | { | ||
| 705 | // TODO: efficiency | ||
| 706 | t_CKUINT byte; | ||
| 707 | arr->get(i, &byte); | ||
| 708 | fwrite(&byte, 1, 1, m_cfd); | ||
| 709 | } | ||
| 710 | } | ||
| 711 | } | ||
| 712 | |||
| 713 | void Chuck_IO_Serial::start_read_thread() | ||
| 714 | { | ||
| 715 | if(m_read_thread == NULL) | ||
| 716 | { | ||
| 717 | m_read_thread = new XThread(); | ||
| 718 | #ifdef WIN32 | ||
| 719 | m_read_thread->start((unsigned int (__stdcall *)(void*))shell_read_cb, this); | ||
| 720 | #else | ||
| 721 | m_read_thread->start(shell_read_cb, this); | ||
| 722 | #endif | ||
| 723 | assert(m_event_buffer == NULL); | ||
| 724 | m_event_buffer = m_vmRef->create_event_buffer(); | ||
| 725 | } | ||
| 726 | } | ||
| 727 | |||
| 728 | |||
| 729 | t_CKBOOL Chuck_IO_Serial::readAsync( t_CKUINT type, t_CKUINT num ) | ||
| 730 | { | ||
| 731 | if( !good() ) | ||
| 732 | { | ||
| 733 | EM_log(CK_LOG_WARNING, "(Serial.readAsync): warning: file not open"); | ||
| 734 | return FALSE; | ||
| 735 | } | ||
| 736 | |||
| 737 | start_read_thread(); | ||
| 738 | |||
| 739 | Request read; | ||
| 740 | read.m_type = type; | ||
| 741 | read.m_num = num; | ||
| 742 | read.m_val = 0; | ||
| 743 | read.m_status = Request::RQ_STATUS_PENDING; | ||
| 744 | |||
| 745 | if(!m_asyncRequests.atMaximum() ) | ||
| 746 | { | ||
| 747 | m_asyncRequests.put(read); | ||
| 748 | } | ||
| 749 | else | ||
| 750 | { | ||
| 751 | EM_log(CK_LOG_SEVERE, "(SerialIO.readAsync): warning: request buffer overflow, dropping read"); | ||
| 752 | return FALSE; | ||
| 753 | } | ||
| 754 | |||
| 755 | return TRUE; | ||
| 756 | } | ||
| 757 | |||
| 758 | Chuck_String * Chuck_IO_Serial::getLine() | ||
| 759 | { | ||
| 760 | if( !good() ) | ||
| 761 | { | ||
| 762 | EM_log(CK_LOG_WARNING, "(Serial.getLine): warning: file not open"); | ||
| 763 | return NULL; | ||
| 764 | } | ||
| 765 | |||
| 766 | Request r; | ||
| 767 | |||
| 768 | Chuck_String * str = NULL; | ||
| 769 | |||
| 770 | if(m_asyncResponses.peek(r, 1) && | ||
| 771 | r.m_type == TYPE_LINE && r.m_status == Request::RQ_STATUS_SUCCESS) | ||
| 772 | { | ||
| 773 | str = (Chuck_String *) r.m_val; | ||
| 774 | m_asyncResponses.get(r); | ||
| 775 | } | ||
| 776 | |||
| 777 | return str; | ||
| 778 | } | ||
| 779 | |||
| 780 | |||
| 781 | t_CKINT Chuck_IO_Serial::getByte() | ||
| 782 | { | ||
| 783 | if( !good() ) | ||
| 784 | { | ||
| 785 | EM_log(CK_LOG_WARNING, "(Serial.getByte): warning: file not open"); | ||
| 786 | return 0; | ||
| 787 | } | ||
| 788 | |||
| 789 | Request r; | ||
| 790 | |||
| 791 | t_CKINT i = 0; | ||
| 792 | |||
| 793 | if(m_asyncResponses.peek(r, 1) && | ||
| 794 | r.m_type == TYPE_BYTE && r.m_num == 1 && | ||
| 795 | r.m_status == Request::RQ_STATUS_SUCCESS) | ||
| 796 | { | ||
| 797 | i = (t_CKINT) r.m_val; | ||
| 798 | m_asyncResponses.get(r); | ||
| 799 | } | ||
| 800 | |||
| 801 | return i; | ||
| 802 | } | ||
| 803 | |||
| 804 | Chuck_Array * Chuck_IO_Serial::getBytes() | ||
| 805 | { | ||
| 806 | if( !good() ) | ||
| 807 | { | ||
| 808 | EM_log(CK_LOG_WARNING, "(Serial.getBytes): warning: file not open"); | ||
| 809 | return NULL; | ||
| 810 | } | ||
| 811 | |||
| 812 | Request r; | ||
| 813 | |||
| 814 | Chuck_Array * arr = NULL; | ||
| 815 | |||
| 816 | if(m_asyncResponses.peek(r, 1) && | ||
| 817 | r.m_type == TYPE_BYTE && r.m_num > 1 && | ||
| 818 | r.m_status == Request::RQ_STATUS_SUCCESS) | ||
| 819 | { | ||
| 820 | arr = (Chuck_Array *) r.m_val; | ||
| 821 | initialize_object(arr, m_vmRef->env()->t_array); | ||
| 822 | m_asyncResponses.get(r); | ||
| 823 | } | ||
| 824 | |||
| 825 | return arr; | ||
| 826 | } | ||
| 827 | |||
| 828 | Chuck_Array * Chuck_IO_Serial::getInts() | ||
| 829 | { | ||
| 830 | if( !good() ) | ||
| 831 | { | ||
| 832 | EM_log(CK_LOG_WARNING, "(Serial.getInts): warning: file not open"); | ||
| 833 | return NULL; | ||
| 834 | } | ||
| 835 | |||
| 836 | Request r; | ||
| 837 | |||
| 838 | Chuck_Array * arr = NULL; | ||
| 839 | |||
| 840 | if(m_asyncResponses.peek(r, 1) && | ||
| 841 | r.m_type == TYPE_INT && r.m_status == Request::RQ_STATUS_SUCCESS) | ||
| 842 | { | ||
| 843 | arr = (Chuck_Array *) r.m_val; | ||
| 844 | initialize_object(arr, m_vmRef->env()->t_array); | ||
| 845 | m_asyncResponses.get(r); | ||
| 846 | } | ||
| 847 | |||
| 848 | return arr; | ||
| 849 | } | ||
| 850 | |||
| 851 | Chuck_Array * Chuck_IO_Serial::getFloats() | ||
| 852 | { | ||
| 853 | if( !good() ) | ||
| 854 | { | ||
| 855 | EM_log(CK_LOG_WARNING, "(Serial.getFloats): warning: file not open"); | ||
| 856 | return NULL; | ||
| 857 | } | ||
| 858 | |||
| 859 | Request r; | ||
| 860 | |||
| 861 | Chuck_Array * arr = NULL; | ||
| 862 | |||
| 863 | if(m_asyncResponses.peek(r, 1) && | ||
| 864 | r.m_type == TYPE_FLOAT && r.m_status == Request::RQ_STATUS_SUCCESS) | ||
| 865 | { | ||
| 866 | arr = (Chuck_Array *) r.m_val; | ||
| 867 | initialize_object(arr, m_vmRef->env()->t_array); | ||
| 868 | m_asyncResponses.get(r); | ||
| 869 | } | ||
| 870 | |||
| 871 | return arr; | ||
| 872 | } | ||
| 873 | |||
| 874 | Chuck_String * Chuck_IO_Serial::getString() | ||
| 875 | { | ||
| 876 | if( !good() ) | ||
| 877 | { | ||
| 878 | EM_log(CK_LOG_WARNING, "(Serial.getString): warning: file not open"); | ||
| 879 | return NULL; | ||
| 880 | } | ||
| 881 | |||
| 882 | Request r; | ||
| 883 | |||
| 884 | Chuck_String * str = NULL; | ||
| 885 | |||
| 886 | if(m_asyncResponses.peek(r, 1) && | ||
| 887 | r.m_type == TYPE_STRING && r.m_status == Request::RQ_STATUS_SUCCESS) | ||
| 888 | { | ||
| 889 | str = (Chuck_String *) r.m_val; | ||
| 890 | m_asyncResponses.get(r); | ||
| 891 | } | ||
| 892 | |||
| 893 | return str; | ||
| 894 | } | ||
| 895 | |||
| 896 | |||
| 897 | t_CKBOOL Chuck_IO_Serial::get_buffer(t_CKINT timeout_ms) | ||
| 898 | { | ||
| 899 | #ifndef WIN32 | ||
| 900 | fd_set fds; | ||
| 901 | FD_ZERO(&fds); | ||
| 902 | FD_SET(m_fd, &fds); | ||
| 903 | |||
| 904 | timeval tv; | ||
| 905 | tv.tv_sec = timeout_ms/1000; | ||
| 906 | tv.tv_usec = 1000 * (timeout_ms%1000); | ||
| 907 | |||
| 908 | int result = select(m_fd+1, &fds, NULL, NULL, &tv); | ||
| 909 | |||
| 910 | if(result > 0 && FD_ISSET(m_fd, &fds)) | ||
| 911 | { | ||
| 912 | result = ::read(m_fd, m_io_buf, m_io_buf_max); | ||
| 913 | if(result > 0) | ||
| 914 | { | ||
| 915 | m_io_buf_available = result; | ||
| 916 | m_io_buf_pos = 0; | ||
| 917 | |||
| 918 | EM_log(CK_LOG_FINE, "(SerialIO::get_buffer): read() returned %i bytes", result); | ||
| 919 | |||
| 920 | return TRUE; | ||
| 921 | } | ||
| 922 | else | ||
| 923 | { | ||
| 924 | EM_log(CK_LOG_SEVERE, "(SerialIO::get_buffer): read() returned 0 bytes"); | ||
| 925 | } | ||
| 926 | } | ||
| 927 | else | ||
| 928 | { | ||
| 929 | EM_log(CK_LOG_FINE, "(SerialIO::get_buffer): select() timeout"); | ||
| 930 | } | ||
| 931 | |||
| 932 | return FALSE; | ||
| 933 | |||
| 934 | #else | ||
| 935 | |||
| 936 | int result = ::read(m_fd, m_io_buf, m_io_buf_max); | ||
| 937 | if(result > 0) | ||
| 938 | { | ||
| 939 | m_io_buf_available = result; | ||
| 940 | m_io_buf_pos = 0; | ||
| 941 | |||
| 942 | return TRUE; | ||
| 943 | } | ||
| 944 | |||
| 945 | Sleep(timeout_ms); | ||
| 946 | |||
| 947 | return FALSE; | ||
| 948 | |||
| 949 | #endif | ||
| 950 | } | ||
| 951 | |||
| 952 | // peek next byte | ||
| 953 | t_CKINT Chuck_IO_Serial::peek_buffer() | ||
| 954 | { | ||
| 955 | // CK_FPRINTF_STDERR( "Chuck_IO_Serial::peek_buffer %i/%i\n", m_io_buf_pos, m_io_buf_available); | ||
| 956 | |||
| 957 | if(m_io_buf_pos >= m_io_buf_available) | ||
| 958 | { | ||
| 959 | // refresh data | ||
| 960 | while(!m_do_exit && !m_eof && !get_buffer(5)) | ||
| 961 | ; | ||
| 962 | |||
| 963 | if(m_do_exit || m_eof) | ||
| 964 | return -1; | ||
| 965 | } | ||
| 966 | |||
| 967 | return m_io_buf[m_io_buf_pos]; | ||
| 968 | } | ||
| 969 | |||
| 970 | // consume next byte | ||
| 971 | // return -1 on error/exit condition | ||
| 972 | t_CKINT Chuck_IO_Serial::pull_buffer() | ||
| 973 | { | ||
| 974 | // CK_FPRINTF_STDERR( "Chuck_IO_Serial::pull_buffer %i/%i\n", m_io_buf_pos, m_io_buf_available); | ||
| 975 | |||
| 976 | if(m_io_buf_pos >= m_io_buf_available) | ||
| 977 | { | ||
| 978 | // refresh data | ||
| 979 | while(!m_do_exit && !m_eof && !get_buffer(5)) | ||
| 980 | ; | ||
| 981 | |||
| 982 | if(m_do_exit || m_eof) | ||
| 983 | return -1; | ||
| 984 | } | ||
| 985 | |||
| 986 | return m_io_buf[m_io_buf_pos++]; | ||
| 987 | } | ||
| 988 | |||
| 989 | |||
| 990 | t_CKINT Chuck_IO_Serial::buffer_bytes_to_tmp(t_CKINT num_bytes) | ||
| 991 | { | ||
| 992 | t_CKUINT len = 0; | ||
| 993 | while(len < num_bytes && !m_do_exit) | ||
| 994 | { | ||
| 995 | if(peek_buffer() == -1) | ||
| 996 | break; | ||
| 997 | |||
| 998 | m_tmp_buf[len++] = pull_buffer(); | ||
| 999 | } | ||
| 1000 | |||
| 1001 | return len; | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | |||
| 1005 | t_CKBOOL Chuck_IO_Serial::handle_line(Chuck_IO_Serial::Request &r) | ||
| 1006 | { | ||
| 1007 | t_CKUINT len = 0; | ||
| 1008 | Chuck_String * str; | ||
| 1009 | |||
| 1010 | while(!m_do_exit) | ||
| 1011 | { | ||
| 1012 | if(peek_buffer() == -1) | ||
| 1013 | break; | ||
| 1014 | |||
| 1015 | if(peek_buffer() == '\r') | ||
| 1016 | { | ||
| 1017 | // consume newline character | ||
| 1018 | pull_buffer(); | ||
| 1019 | if(peek_buffer() == '\n') pull_buffer(); // handle \r\n | ||
| 1020 | break; | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | if(peek_buffer() == '\n') | ||
| 1024 | { | ||
| 1025 | // consume newline character | ||
| 1026 | pull_buffer(); | ||
| 1027 | if(peek_buffer() == '\r') pull_buffer(); // handle \n\r (unlikely) | ||
| 1028 | break; | ||
| 1029 | } | ||
| 1030 | |||
| 1031 | m_tmp_buf[len++] = pull_buffer(); | ||
| 1032 | |||
| 1033 | if(len >= m_tmp_buf_max) | ||
| 1034 | { | ||
| 1035 | EM_log(CK_LOG_WARNING, "(Serial.handle_line): warning: line exceeds buffer length, truncating to %i characters", m_tmp_buf_max); | ||
| 1036 | break; | ||
| 1037 | } | ||
| 1038 | } | ||
| 1039 | |||
| 1040 | if(m_do_exit) | ||
| 1041 | goto error; | ||
| 1042 | // TODO: eof | ||
| 1043 | |||
| 1044 | str = new Chuck_String; | ||
| 1045 | str->set( std::string((char *)m_tmp_buf, len) ); | ||
| 1046 | |||
| 1047 | r.m_val = (t_CKUINT) str; | ||
| 1048 | r.m_status = Chuck_IO_Serial::Request::RQ_STATUS_SUCCESS; | ||
| 1049 | |||
| 1050 | return TRUE; | ||
| 1051 | |||
| 1052 | error: | ||
| 1053 | r.m_val = 0; | ||
| 1054 | r.m_status = Chuck_IO_Serial::Request::RQ_STATUS_FAILURE; | ||
| 1055 | |||
| 1056 | #ifdef WIN32 | ||
| 1057 | HANDLE hFile = (HANDLE) _get_osfhandle(m_fd); | ||
| 1058 | DWORD error; | ||
| 1059 | ClearCommError(hFile, &error, NULL); | ||
| 1060 | |||
| 1061 | PurgeComm(hFile, PURGE_RXCLEAR); | ||
| 1062 | #endif | ||
| 1063 | |||
| 1064 | return TRUE; | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | t_CKBOOL Chuck_IO_Serial::handle_string(Chuck_IO_Serial::Request & r) | ||
| 1068 | { | ||
| 1069 | return FALSE; | ||
| 1070 | } | ||
| 1071 | |||
| 1072 | t_CKBOOL Chuck_IO_Serial::handle_float_ascii(Chuck_IO_Serial::Request & r) | ||
| 1073 | { | ||
| 1074 | t_CKFLOAT val = 0; | ||
| 1075 | int numRead = 0; | ||
| 1076 | Chuck_Array8 * array = new Chuck_Array8(0); | ||
| 1077 | |||
| 1078 | for(int i = 0; i < r.m_num && !m_do_exit; i++) | ||
| 1079 | { | ||
| 1080 | t_CKUINT len = 0; | ||
| 1081 | |||
| 1082 | while(!m_do_exit) | ||
| 1083 | { | ||
| 1084 | if(peek_buffer() == -1) | ||
| 1085 | break; | ||
| 1086 | |||
| 1087 | // TODO: '\r'? | ||
| 1088 | int c = peek_buffer(); | ||
| 1089 | |||
| 1090 | if(isdigit(c) || c=='.' || (len==0 && (c=='-' || c=='+'))) | ||
| 1091 | { | ||
| 1092 | m_tmp_buf[len++] = pull_buffer(); | ||
| 1093 | } | ||
| 1094 | else if(len > 0) | ||
| 1095 | { | ||
| 1096 | m_tmp_buf[len++] = '\0'; | ||
| 1097 | val = strtod((char *)m_tmp_buf, NULL); | ||
| 1098 | |||
| 1099 | numRead++; | ||
| 1100 | array->push_back(val); | ||
| 1101 | |||
| 1102 | break; | ||
| 1103 | } | ||
| 1104 | } | ||
| 1105 | } | ||
| 1106 | |||
| 1107 | if(m_do_exit || m_eof) | ||
| 1108 | goto error; | ||
| 1109 | |||
| 1110 | r.m_num = numRead; | ||
| 1111 | r.m_val = (t_CKUINT) array; | ||
| 1112 | r.m_status = Request::RQ_STATUS_SUCCESS; | ||
| 1113 | |||
| 1114 | return TRUE; | ||
| 1115 | |||
| 1116 | error: | ||
| 1117 | SAFE_DELETE(array); | ||
| 1118 | r.m_val = 0; | ||
| 1119 | r.m_status = Chuck_IO_Serial::Request::RQ_STATUS_FAILURE; | ||
| 1120 | |||
| 1121 | return TRUE; | ||
| 1122 | } | ||
| 1123 | |||
| 1124 | t_CKBOOL Chuck_IO_Serial::handle_int_ascii(Chuck_IO_Serial::Request & r) | ||
| 1125 | { | ||
| 1126 | t_CKINT val = 0; | ||
| 1127 | int numRead = 0; | ||
| 1128 | Chuck_Array4 * array = new Chuck_Array4(FALSE, 0); | ||
| 1129 | for(int i = 0; i < r.m_num; i++) | ||
| 1130 | { | ||
| 1131 | t_CKUINT len = 0; | ||
| 1132 | |||
| 1133 | while(!m_do_exit) | ||
| 1134 | { | ||
| 1135 | if(peek_buffer() == -1) | ||
| 1136 | break; | ||
| 1137 | |||
| 1138 | int c = pull_buffer(); | ||
| 1139 | |||
| 1140 | if(isdigit(c) || (len==0 && (c=='-' || c=='+'))) | ||
| 1141 | { | ||
| 1142 | m_tmp_buf[len++] = c; | ||
| 1143 | } | ||
| 1144 | else if(len > 0) | ||
| 1145 | { | ||
| 1146 | m_tmp_buf[len++] = '\0'; | ||
| 1147 | val = strtol((char *)m_tmp_buf, NULL, 10); | ||
| 1148 | |||
| 1149 | numRead++; | ||
| 1150 | array->push_back(val); | ||
| 1151 | |||
| 1152 | break; | ||
| 1153 | } | ||
| 1154 | } | ||
| 1155 | } | ||
| 1156 | |||
| 1157 | if(m_do_exit || m_eof) | ||
| 1158 | goto error; | ||
| 1159 | |||
| 1160 | r.m_num = numRead; | ||
| 1161 | r.m_val = (t_CKUINT) array; | ||
| 1162 | r.m_status = Request::RQ_STATUS_SUCCESS; | ||
| 1163 | |||
| 1164 | return TRUE; | ||
| 1165 | |||
| 1166 | error: | ||
| 1167 | SAFE_DELETE(array); | ||
| 1168 | r.m_val = 0; | ||
| 1169 | r.m_status = Chuck_IO_Serial::Request::RQ_STATUS_FAILURE; | ||
| 1170 | |||
| 1171 | return TRUE; | ||
| 1172 | } | ||
| 1173 | |||
| 1174 | t_CKBOOL Chuck_IO_Serial::handle_byte(Chuck_IO_Serial::Request & r) | ||
| 1175 | { | ||
| 1176 | // binary | ||
| 1177 | int size = 1; | ||
| 1178 | int num = r.m_num; | ||
| 1179 | t_CKUINT val = 0; | ||
| 1180 | |||
| 1181 | if(size*num > m_tmp_buf_max) | ||
| 1182 | { | ||
| 1183 | int new_num = (int) floorf(((float)m_tmp_buf_max)/size); | ||
| 1184 | EM_log(CK_LOG_WARNING, "SerialIO.read_cb: error: request size %i too large (%i bytes), truncating to %i", | ||
| 1185 | num, size*num, new_num); | ||
| 1186 | num = new_num; | ||
| 1187 | } | ||
| 1188 | |||
| 1189 | t_CKINT len = buffer_bytes_to_tmp(num); | ||
| 1190 | |||
| 1191 | if(m_do_exit || m_eof) | ||
| 1192 | goto error; | ||
| 1193 | |||
| 1194 | r.m_num = len; | ||
| 1195 | |||
| 1196 | if(r.m_num == 1) | ||
| 1197 | val = m_tmp_buf[0]; | ||
| 1198 | else | ||
| 1199 | { | ||
| 1200 | Chuck_Array4 * array = new Chuck_Array4(FALSE, r.m_num); | ||
| 1201 | for(int i = 0; i < r.m_num; i++) | ||
| 1202 | { | ||
| 1203 | array->set(i, m_tmp_buf[i]); | ||
| 1204 | } | ||
| 1205 | |||
| 1206 | val = (t_CKUINT) array; | ||
| 1207 | } | ||
| 1208 | |||
| 1209 | r.m_val = val; | ||
| 1210 | r.m_status = Request::RQ_STATUS_SUCCESS; | ||
| 1211 | |||
| 1212 | return TRUE; | ||
| 1213 | |||
| 1214 | error: | ||
| 1215 | r.m_val = 0; | ||
| 1216 | r.m_status = Chuck_IO_Serial::Request::RQ_STATUS_FAILURE; | ||
| 1217 | |||
| 1218 | return TRUE; | ||
| 1219 | } | ||
| 1220 | |||
| 1221 | t_CKBOOL Chuck_IO_Serial::handle_float_binary(Chuck_IO_Serial::Request & r) | ||
| 1222 | { | ||
| 1223 | // binary | ||
| 1224 | int size = 4; // SPENCERTODO: should these be based on arch (64 bit)? | ||
| 1225 | assert(sizeof(t_CKSINGLE) == 4); | ||
| 1226 | |||
| 1227 | int num = r.m_num; | ||
| 1228 | |||
| 1229 | if(size*num > m_tmp_buf_max) | ||
| 1230 | { | ||
| 1231 | int new_num = (int) floorf(((float)m_tmp_buf_max)/size); | ||
| 1232 | EM_log(CK_LOG_WARNING, "(SerialIO.read_cb): error: request size %i too large (%i bytes), truncating to %i", | ||
| 1233 | num, size*num, new_num); | ||
| 1234 | num = new_num; | ||
| 1235 | } | ||
| 1236 | |||
| 1237 | r.m_num = buffer_bytes_to_tmp(size*num)/size; | ||
| 1238 | |||
| 1239 | t_CKUINT val = 0; | ||
| 1240 | t_CKSINGLE * m_floats = (t_CKSINGLE *) m_tmp_buf; | ||
| 1241 | |||
| 1242 | Chuck_Array8 * array = new Chuck_Array8(r.m_num); | ||
| 1243 | for(int i = 0; i < r.m_num; i++) | ||
| 1244 | { | ||
| 1245 | array->set(i, m_floats[i]); | ||
| 1246 | } | ||
| 1247 | |||
| 1248 | val = (t_CKUINT) array; | ||
| 1249 | |||
| 1250 | r.m_val = val; | ||
| 1251 | r.m_status = Request::RQ_STATUS_SUCCESS; | ||
| 1252 | |||
| 1253 | return TRUE; | ||
| 1254 | } | ||
| 1255 | |||
| 1256 | t_CKBOOL Chuck_IO_Serial::handle_int_binary(Chuck_IO_Serial::Request & r) | ||
| 1257 | { | ||
| 1258 | // binary | ||
| 1259 | int size = 4; // SPENCERTODO: should these be based on arch (64 bit)? | ||
| 1260 | |||
| 1261 | int num = r.m_num; | ||
| 1262 | |||
| 1263 | if(size*num > m_tmp_buf_max) | ||
| 1264 | { | ||
| 1265 | int new_num = (int) floorf(((float)m_tmp_buf_max)/size); | ||
| 1266 | EM_log(CK_LOG_WARNING, "SerialIO.read_cb: error: request size %i too large (%i bytes), truncating to %i", | ||
| 1267 | num, size*num, new_num); | ||
| 1268 | num = new_num; | ||
| 1269 | } | ||
| 1270 | |||
| 1271 | r.m_num = buffer_bytes_to_tmp(size*num)/size; | ||
| 1272 | |||
| 1273 | t_CKUINT val = 0; | ||
| 1274 | uint32_t * m_ints = (uint32_t *) m_tmp_buf; | ||
| 1275 | |||
| 1276 | Chuck_Array4 * array = new Chuck_Array4(FALSE, r.m_num); | ||
| 1277 | for(int i = 0; i < r.m_num; i++) | ||
| 1278 | { | ||
| 1279 | array->set(i, m_ints[i]); | ||
| 1280 | } | ||
| 1281 | |||
| 1282 | val = (t_CKUINT) array; | ||
| 1283 | |||
| 1284 | r.m_val = val; | ||
| 1285 | r.m_status = Request::RQ_STATUS_SUCCESS; | ||
| 1286 | |||
| 1287 | return TRUE; | ||
| 1288 | } | ||
| 1289 | |||
| 1290 | |||
| 1291 | void Chuck_IO_Serial::read_cb() | ||
| 1292 | { | ||
| 1293 | m_do_read_thread = TRUE; | ||
| 1294 | |||
| 1295 | m_write_thread = new XThread; | ||
| 1296 | #ifdef WIN32 | ||
| 1297 | m_read_thread->start((unsigned int (__stdcall *)(void*))shell_write_cb, this); | ||
| 1298 | #else | ||
| 1299 | m_write_thread->start(shell_write_cb, this); | ||
| 1300 | #endif | ||
| 1301 | |||
| 1302 | while(m_do_read_thread && !m_do_exit) | ||
| 1303 | { | ||
| 1304 | Request r; | ||
| 1305 | int num_responses = 0; | ||
| 1306 | |||
| 1307 | while(m_asyncRequests.get(r) && m_do_read_thread && !m_do_exit) | ||
| 1308 | { | ||
| 1309 | if( m_asyncResponses.atMaximum() ) | ||
| 1310 | { | ||
| 1311 | EM_log(CK_LOG_SEVERE, "SerialIO.read_cb: error: response buffer overflow, dropping read"); | ||
| 1312 | continue; | ||
| 1313 | } | ||
| 1314 | |||
| 1315 | if(m_flags & Chuck_IO_File::TYPE_ASCII) | ||
| 1316 | { | ||
| 1317 | switch(r.m_type) | ||
| 1318 | { | ||
| 1319 | case TYPE_LINE: | ||
| 1320 | handle_line(r); | ||
| 1321 | break; | ||
| 1322 | |||
| 1323 | case TYPE_STRING: | ||
| 1324 | handle_string(r); | ||
| 1325 | break; | ||
| 1326 | |||
| 1327 | case TYPE_INT: | ||
| 1328 | handle_int_ascii(r); | ||
| 1329 | break; | ||
| 1330 | |||
| 1331 | case TYPE_FLOAT: | ||
| 1332 | handle_float_ascii(r); | ||
| 1333 | break; | ||
| 1334 | |||
| 1335 | default: | ||
| 1336 | // this shouldnt happen | ||
| 1337 | r.m_type = TYPE_NONE; | ||
| 1338 | r.m_num = 0; | ||
| 1339 | r.m_status = Request::RQ_STATUS_INVALID; | ||
| 1340 | r.m_val = 0; | ||
| 1341 | EM_log(CK_LOG_WARNING, "SerialIO.read_cb: error: invalid request"); | ||
| 1342 | } | ||
| 1343 | } | ||
| 1344 | else | ||
| 1345 | { | ||
| 1346 | // binary | ||
| 1347 | switch(r.m_type) | ||
| 1348 | { | ||
| 1349 | case TYPE_BYTE: | ||
| 1350 | handle_byte(r); | ||
| 1351 | break; | ||
| 1352 | case TYPE_INT: | ||
| 1353 | handle_int_binary(r); | ||
| 1354 | break; | ||
| 1355 | case TYPE_FLOAT: | ||
| 1356 | handle_float_binary(r); | ||
| 1357 | break; | ||
| 1358 | |||
| 1359 | default: | ||
| 1360 | // this shouldnt happen | ||
| 1361 | r.m_type = TYPE_NONE; | ||
| 1362 | r.m_num = 0; | ||
| 1363 | r.m_status = Request::RQ_STATUS_INVALID; | ||
| 1364 | r.m_val = 0; | ||
| 1365 | EM_log(CK_LOG_WARNING, "SerialIO.read_cb: error: invalid request"); | ||
| 1366 | } | ||
| 1367 | } | ||
| 1368 | |||
| 1369 | m_asyncResponses.put(r); | ||
| 1370 | num_responses++; | ||
| 1371 | } | ||
| 1372 | |||
| 1373 | if(m_asyncResponses.numElements() > 0) | ||
| 1374 | queue_broadcast(m_event_buffer); | ||
| 1375 | |||
| 1376 | usleep(100); | ||
| 1377 | } | ||
| 1378 | |||
| 1379 | m_write_thread->wait(-1); | ||
| 1380 | |||
| 1381 | close_int(); | ||
| 1382 | } | ||
| 1383 | |||
| 1384 | void Chuck_IO_Serial::write_cb() | ||
| 1385 | { | ||
| 1386 | m_do_write_thread = TRUE; | ||
| 1387 | |||
| 1388 | char *tmp_writethread_buf = new char[CHUCK_IO_DEFAULT_BUFSIZE]; | ||
| 1389 | t_CKINT tmp_writethread_buf_max = CHUCK_IO_DEFAULT_BUFSIZE; | ||
| 1390 | |||
| 1391 | while(m_do_write_thread && !m_do_exit) | ||
| 1392 | { | ||
| 1393 | Request r; | ||
| 1394 | |||
| 1395 | while(m_asyncWriteRequests.get(r) && m_do_write_thread && !m_do_exit) | ||
| 1396 | { | ||
| 1397 | if(r.m_type == TYPE_WRITE) | ||
| 1398 | { | ||
| 1399 | int numBytes = 0; | ||
| 1400 | char c; | ||
| 1401 | while(m_writeBuffer.get(c)) | ||
| 1402 | { | ||
| 1403 | tmp_writethread_buf[numBytes] = c; | ||
| 1404 | numBytes++; | ||
| 1405 | } | ||
| 1406 | |||
| 1407 | assert(numBytes < tmp_writethread_buf_max); | ||
| 1408 | |||
| 1409 | if(numBytes) | ||
| 1410 | { | ||
| 1411 | fwrite(tmp_writethread_buf, 1, numBytes, m_cfd); | ||
| 1412 | fflush(m_cfd); | ||
| 1413 | } | ||
| 1414 | } | ||
| 1415 | } | ||
| 1416 | |||
| 1417 | // todo: replace with semaphore? | ||
| 1418 | usleep(100); | ||
| 1419 | } | ||
| 1420 | |||
| 1421 | delete[] tmp_writethread_buf; | ||
| 1422 | tmp_writethread_buf = NULL; | ||
| 1423 | } | ||
| 1424 | |||
| 1425 | |||
| 1426 | t_CKBOOL Chuck_IO_Serial::setBaudRate( t_CKUINT rate ) | ||
| 1427 | { | ||
| 1428 | #ifndef WIN32 | ||
| 1429 | // set serial IO baud rate | ||
| 1430 | struct termios tios; | ||
| 1431 | tcgetattr(m_fd, &tios); | ||
| 1432 | cfsetispeed(&tios, rate); | ||
| 1433 | cfsetospeed(&tios, rate); | ||
| 1434 | tcsetattr(m_fd, TCSAFLUSH, &tios); | ||
| 1435 | |||
| 1436 | return TRUE; | ||
| 1437 | #else | ||
| 1438 | DCB dcb; | ||
| 1439 | COMMTIMEOUTS timeouts; | ||
| 1440 | HANDLE hFile = (HANDLE) _get_osfhandle(m_fd); | ||
| 1441 | |||
| 1442 | bool was_error = false; | ||
| 1443 | DWORD error_flag = 0; | ||
| 1444 | |||
| 1445 | if(!hFile) | ||
| 1446 | { | ||
| 1447 | goto error; | ||
| 1448 | } | ||
| 1449 | |||
| 1450 | if(!GetCommTimeouts(hFile, &timeouts)) | ||
| 1451 | { | ||
| 1452 | goto error; | ||
| 1453 | } | ||
| 1454 | |||
| 1455 | timeouts.ReadIntervalTimeout = 10; | ||
| 1456 | timeouts.WriteTotalTimeoutConstant = 5000; | ||
| 1457 | |||
| 1458 | if(!SetCommTimeouts(hFile, &timeouts)) | ||
| 1459 | { | ||
| 1460 | goto error; | ||
| 1461 | } | ||
| 1462 | |||
| 1463 | if(!GetCommState(hFile, &dcb)) | ||
| 1464 | { | ||
| 1465 | goto error; | ||
| 1466 | } | ||
| 1467 | |||
| 1468 | // set baud rate | ||
| 1469 | dcb.BaudRate = rate; | ||
| 1470 | |||
| 1471 | // set important stuff | ||
| 1472 | dcb.ByteSize = 8; | ||
| 1473 | dcb.StopBits = ONESTOPBIT; | ||
| 1474 | |||
| 1475 | if(!SetCommState(hFile, &dcb)) | ||
| 1476 | { | ||
| 1477 | //goto error; | ||
| 1478 | was_error = true; | ||
| 1479 | ClearCommError(hFile, &error_flag, NULL); | ||
| 1480 | } | ||
| 1481 | |||
| 1482 | // set everything else | ||
| 1483 | if(!GetCommState(hFile, &dcb)) | ||
| 1484 | { | ||
| 1485 | goto error; | ||
| 1486 | } | ||
| 1487 | |||
| 1488 | dcb.fBinary = TRUE; | ||
| 1489 | dcb.fParity = FALSE; | ||
| 1490 | dcb.fOutxCtsFlow = FALSE; | ||
| 1491 | dcb.fOutxDsrFlow = FALSE; | ||
| 1492 | dcb.fDtrControl = DTR_CONTROL_ENABLE; | ||
| 1493 | dcb.fDsrSensitivity = FALSE; | ||
| 1494 | dcb.fTXContinueOnXoff = TRUE; | ||
| 1495 | dcb.fOutX = FALSE; | ||
| 1496 | dcb.fInX = FALSE; | ||
| 1497 | dcb.fErrorChar = FALSE; | ||
| 1498 | dcb.fNull = FALSE; | ||
| 1499 | dcb.fRtsControl = RTS_CONTROL_ENABLE; | ||
| 1500 | dcb.fAbortOnError = TRUE; | ||
| 1501 | dcb.Parity = NOPARITY; | ||
| 1502 | |||
| 1503 | if(!SetCommState(hFile, &dcb)) | ||
| 1504 | { | ||
| 1505 | //goto error; | ||
| 1506 | was_error = true; | ||
| 1507 | ClearCommError(hFile, &error_flag, NULL); | ||
| 1508 | } | ||
| 1509 | |||
| 1510 | if(!was_error) | ||
| 1511 | return TRUE; | ||
| 1512 | |||
| 1513 | error: | ||
| 1514 | |||
| 1515 | DWORD error = GetLastError(); | ||
| 1516 | |||
| 1517 | return FALSE; | ||
| 1518 | |||
| 1519 | #endif | ||
| 1520 | } | ||
| 1521 | |||
| 1522 | |||
| 1523 | t_CKUINT Chuck_IO_Serial::getBaudRate() | ||
| 1524 | { | ||
| 1525 | #ifndef WIN32 | ||
| 1526 | // set serial IO baud rate | ||
| 1527 | struct termios tios; | ||
| 1528 | tcgetattr(m_fd, &tios); | ||
| 1529 | speed_t rate = cfgetispeed(&tios); | ||
| 1530 | return rate; | ||
| 1531 | #else | ||
| 1532 | |||
| 1533 | DCB dcb; | ||
| 1534 | HANDLE hFile = (HANDLE) _get_osfhandle(m_fd); | ||
| 1535 | |||
| 1536 | if(!hFile) | ||
| 1537 | { | ||
| 1538 | goto error; | ||
| 1539 | } | ||
| 1540 | |||
| 1541 | if(!GetCommState(hFile, &dcb)) | ||
| 1542 | { | ||
| 1543 | goto error; | ||
| 1544 | } | ||
| 1545 | |||
| 1546 | return dcb.BaudRate; | ||
| 1547 | |||
| 1548 | error: | ||
| 1549 | return 0; | ||
| 1550 | |||
| 1551 | #endif | ||
| 1552 | } | ||
| 1553 | |||
| 1554 | |||
| 1555 | //----------------------------------------------------------------------------- | ||
| 1556 | // serialio API | ||
| 1557 | //----------------------------------------------------------------------------- | ||
| 1558 | CK_DLL_SFUN( serialio_list ); | ||
| 1559 | CK_DLL_ALLOC( serialio_alloc ); | ||
| 1560 | CK_DLL_CTOR( serialio_ctor ); | ||
| 1561 | CK_DLL_DTOR( serialio_dtor ); | ||
| 1562 | CK_DLL_MFUN( serialio_open ); | ||
| 1563 | CK_DLL_MFUN( serialio_close ); | ||
| 1564 | CK_DLL_MFUN( serialio_ready ); | ||
| 1565 | CK_DLL_MFUN( serialio_readLine ); | ||
| 1566 | CK_DLL_MFUN( serialio_onLine ); | ||
| 1567 | CK_DLL_MFUN( serialio_onByte ); | ||
| 1568 | CK_DLL_MFUN( serialio_onBytes ); | ||
| 1569 | CK_DLL_MFUN( serialio_onInts ); | ||
| 1570 | CK_DLL_MFUN( serialio_onFloats ); | ||
| 1571 | CK_DLL_MFUN( serialio_getLine ); | ||
| 1572 | CK_DLL_MFUN( serialio_getByte ); | ||
| 1573 | CK_DLL_MFUN( serialio_getBytes ); | ||
| 1574 | CK_DLL_MFUN( serialio_getInts ); | ||
| 1575 | CK_DLL_MFUN( serialio_setBaudRate ); | ||
| 1576 | CK_DLL_MFUN( serialio_getBaudRate ); | ||
| 1577 | CK_DLL_MFUN( serialio_writeByte ); | ||
| 1578 | CK_DLL_MFUN( serialio_writeBytes ); | ||
| 1579 | |||
| 1580 | CK_DLL_MFUN( serialio_flush ) | ||
| 1581 | { | ||
| 1582 | Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF; | ||
| 1583 | |||
| 1584 | cereal->flush(); | ||
| 1585 | } | ||
| 1586 | |||
| 1587 | |||
| 1588 | //----------------------------------------------------------------------------- | ||
| 1589 | // name: init_class_serialio() | ||
| 1590 | // desc: ... | ||
| 1591 | //----------------------------------------------------------------------------- | ||
| 1592 | t_CKBOOL init_class_serialio( Chuck_Env * env ) | ||
| 1593 | { | ||
| 1594 | // init as base class | ||
| 1595 | Chuck_DL_Func * func = NULL; | ||
| 1596 | |||
| 1597 | // log | ||
| 1598 | EM_log( CK_LOG_SEVERE, "class 'SerialIO'" ); | ||
| 1599 | |||
| 1600 | std::string doc = "Handles reading and writing for serial input/output devices, such as Arduino."; | ||
| 1601 | |||
| 1602 | Chuck_Type * type = type_engine_import_class_begin( env, "SerialIO", "IO", | ||
| 1603 | env->global(), serialio_ctor, serialio_dtor, doc.c_str() ); | ||
| 1604 | // TODO: ctor/dtor? | ||
| 1605 | if( !type ) | ||
| 1606 | return FALSE; | ||
| 1607 | |||
| 1608 | // HACK; SPENCERTODO: better way to set this | ||
| 1609 | type->allocator = serialio_alloc; | ||
| 1610 | |||
| 1611 | // add list() | ||
| 1612 | func = make_new_sfun( "string[]", "list", serialio_list ); | ||
| 1613 | func->doc = "Return list of available serial devices."; | ||
| 1614 | if( !type_engine_import_sfun( env, func ) ) goto error; | ||
| 1615 | |||
| 1616 | func = make_new_mfun("int", "open", serialio_open); | ||
| 1617 | func->add_arg("int", "i"); | ||
| 1618 | func->add_arg("int", "baud"); | ||
| 1619 | func->add_arg("int", "mode"); | ||
| 1620 | func->doc = "Open serial device i with specified baud rate and mode (binary or ASCII)."; | ||
| 1621 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1622 | |||
| 1623 | func = make_new_mfun("void", "close", serialio_close); | ||
| 1624 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1625 | |||
| 1626 | // add ready (data available) | ||
| 1627 | func = make_new_mfun("int", "dataAvailable", serialio_ready); | ||
| 1628 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1629 | |||
| 1630 | // add readLine | ||
| 1631 | func = make_new_mfun("string", "readLine", serialio_readLine); | ||
| 1632 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1633 | |||
| 1634 | // add onLine | ||
| 1635 | func = make_new_mfun("SerialIO", "onLine", serialio_onLine); | ||
| 1636 | func->doc = "Wait for one line (ASCII mode only)."; | ||
| 1637 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1638 | |||
| 1639 | // add onByte | ||
| 1640 | func = make_new_mfun("SerialIO", "onByte", serialio_onByte); | ||
| 1641 | func->doc = "Wait for one byte (binary mode only)."; | ||
| 1642 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1643 | |||
| 1644 | // add onBytes | ||
| 1645 | func = make_new_mfun("SerialIO", "onBytes", serialio_onBytes); | ||
| 1646 | func->add_arg("int", "num"); | ||
| 1647 | func->doc = "Wait for requested number of bytes (binary mode only)."; | ||
| 1648 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1649 | |||
| 1650 | // add onInts | ||
| 1651 | func = make_new_mfun("SerialIO", "onInts", serialio_onInts); | ||
| 1652 | func->add_arg("int", "num"); | ||
| 1653 | func->doc = "Wait for requested number of ints (ASCII or binary mode)."; | ||
| 1654 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1655 | |||
| 1656 | // add onInts | ||
| 1657 | func = make_new_mfun("SerialIO", "onFloats", serialio_onFloats); | ||
| 1658 | func->add_arg("int", "num"); | ||
| 1659 | func->doc = "Wait for requested number of floats (ASCII or binary mode)."; | ||
| 1660 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1661 | |||
| 1662 | // add getLine | ||
| 1663 | func = make_new_mfun("string", "getLine", serialio_getLine); | ||
| 1664 | func->doc = "Get next requested line."; | ||
| 1665 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1666 | |||
| 1667 | // add getByte | ||
| 1668 | func = make_new_mfun("int", "getByte", serialio_getByte); | ||
| 1669 | func->doc = "Get next requested byte. "; | ||
| 1670 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1671 | |||
| 1672 | // add getBytes | ||
| 1673 | func = make_new_mfun("int[]", "getBytes", serialio_getBytes); | ||
| 1674 | func->doc = "Get next requested number of bytes. "; | ||
| 1675 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1676 | |||
| 1677 | // add getInts | ||
| 1678 | func = make_new_mfun("int[]", "getInts", serialio_getInts); | ||
| 1679 | func->doc = "Get next requested number of integers. "; | ||
| 1680 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1681 | |||
| 1682 | // add writeByte | ||
| 1683 | func = make_new_mfun("void", "writeByte", serialio_writeByte); | ||
| 1684 | func->add_arg("int", "b"); | ||
| 1685 | func->doc = "Write a single byte."; | ||
| 1686 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1687 | |||
| 1688 | // add writeBytes | ||
| 1689 | func = make_new_mfun("void", "writeBytes", serialio_writeBytes); | ||
| 1690 | func->add_arg("int[]", "b"); | ||
| 1691 | func->doc = "Write array of bytes."; | ||
| 1692 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1693 | |||
| 1694 | // add setBaudRate | ||
| 1695 | func = make_new_mfun("int", "baudRate", serialio_setBaudRate); | ||
| 1696 | func->add_arg("int", "r"); | ||
| 1697 | func->doc = "Set baud rate."; | ||
| 1698 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1699 | |||
| 1700 | // add getBaudRate | ||
| 1701 | func = make_new_mfun("int", "baudRate", serialio_getBaudRate); | ||
| 1702 | func->doc = "Get current baud rate."; | ||
| 1703 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1704 | |||
| 1705 | // add getBaudRate | ||
| 1706 | func = make_new_mfun("void", "flush", serialio_flush); | ||
| 1707 | func->doc = "Flush the IO buffer."; | ||
| 1708 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1709 | |||
| 1710 | // add can_wait | ||
| 1711 | // func = make_new_mfun("int", "can_wait", serialio_canWait); | ||
| 1712 | // func->doc = ""; | ||
| 1713 | // if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1714 | |||
| 1715 | // add baud rate constants | ||
| 1716 | type_engine_import_svar(env, "int", "B2400", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_2400, "2400 baud"); | ||
| 1717 | type_engine_import_svar(env, "int", "B4800", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_4800, "4800 baud"); | ||
| 1718 | type_engine_import_svar(env, "int", "B9600", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_9600, "9600 baud"); | ||
| 1719 | type_engine_import_svar(env, "int", "B19200", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_19200, "19200 baud"); | ||
| 1720 | type_engine_import_svar(env, "int", "B38400", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_38400, "38400 baud"); | ||
| 1721 | type_engine_import_svar(env, "int", "B7200", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_7200, "7200 baud"); | ||
| 1722 | type_engine_import_svar(env, "int", "B14400", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_14400, "14400 baud"); | ||
| 1723 | type_engine_import_svar(env, "int", "B28800", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_28800, "28800 baud"); | ||
| 1724 | type_engine_import_svar(env, "int", "B57600", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_57600, "57600 baud"); | ||
| 1725 | type_engine_import_svar(env, "int", "B76800", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_76800, "76800 baud"); | ||
| 1726 | type_engine_import_svar(env, "int", "B115200", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_115200, "115200 baud"); | ||
| 1727 | type_engine_import_svar(env, "int", "B230400", TRUE, (t_CKUINT) &Chuck_IO_Serial::CK_BAUD_230400, "230400 baud"); | ||
| 1728 | |||
| 1729 | type_engine_import_svar(env, "int", "BINARY", TRUE, (t_CKUINT) &Chuck_IO_File::TYPE_BINARY, "Binary mode"); | ||
| 1730 | type_engine_import_svar(env, "int", "ASCII", TRUE, (t_CKUINT) &Chuck_IO_File::TYPE_ASCII, "ASCII mode"); | ||
| 1731 | |||
| 1732 | // add examples | ||
| 1733 | if( !type_engine_import_add_ex( env, "serial/byte.ck" ) ) goto error; | ||
| 1734 | if( !type_engine_import_add_ex( env, "serial/bytes.ck" ) ) goto error; | ||
| 1735 | if( !type_engine_import_add_ex( env, "serial/ints-bin.ck" ) ) goto error; | ||
| 1736 | if( !type_engine_import_add_ex( env, "serial/ints.ck" ) ) goto error; | ||
| 1737 | if( !type_engine_import_add_ex( env, "serial/lines.ck" ) ) goto error; | ||
| 1738 | if( !type_engine_import_add_ex( env, "serial/list.ck" ) ) goto error; | ||
| 1739 | if( !type_engine_import_add_ex( env, "serial/write-bytes.ck" ) ) goto error; | ||
| 1740 | if( !type_engine_import_add_ex( env, "serial/write.ck" ) ) goto error; | ||
| 1741 | |||
| 1742 | // end the class import | ||
| 1743 | type_engine_import_class_end( env ); | ||
| 1744 | |||
| 1745 | return TRUE; | ||
| 1746 | |||
| 1747 | error: | ||
| 1748 | |||
| 1749 | // end the class import | ||
| 1750 | type_engine_import_class_end( env ); | ||
| 1751 | |||
| 1752 | return FALSE; | ||
| 1753 | } | ||
| 1754 | |||
| 1755 | |||
| 1756 | |||
| 1757 | CK_DLL_SFUN( serialio_list ) | ||
| 1758 | { | ||
| 1759 | vector<string> devices = SerialIOManager::availableSerialDevices(); | ||
| 1760 | |||
| 1761 | // ISSUE: 64-bit | ||
| 1762 | Chuck_Array4 * array = new Chuck_Array4(TRUE, 0); | ||
| 1763 | initialize_object( array, SHRED->vm_ref->env()->t_array ); | ||
| 1764 | |||
| 1765 | for(vector<string>::iterator i = devices.begin(); i != devices.end(); i++) | ||
| 1766 | { | ||
| 1767 | Chuck_String * name = new Chuck_String(*i); | ||
| 1768 | initialize_object(name, SHRED->vm_ref->env()->t_string); | ||
| 1769 | array->push_back((t_CKUINT) name); | ||
| 1770 | } | ||
| 1771 | |||
| 1772 | RETURN->v_object = array; | ||
| 1773 | } | ||
| 1774 | |||
| 1775 | |||
| 1776 | CK_DLL_ALLOC( serialio_alloc ) | ||
| 1777 | { | ||
| 1778 | return new Chuck_IO_Serial( SHRED->vm_ref ); | ||
| 1779 | } | ||
| 1780 | |||
| 1781 | CK_DLL_CTOR( serialio_ctor ) | ||
| 1782 | { | ||
| 1783 | Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF; | ||
| 1784 | SHRED->add_serialio(cereal); | ||
| 1785 | } | ||
| 1786 | |||
| 1787 | CK_DLL_DTOR( serialio_dtor ) | ||
| 1788 | { | ||
| 1789 | Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF; | ||
| 1790 | if(cereal) | ||
| 1791 | { | ||
| 1792 | SHRED->remove_serialio(cereal); | ||
| 1793 | cereal->close(); | ||
| 1794 | } | ||
| 1795 | } | ||
| 1796 | |||
| 1797 | CK_DLL_MFUN( serialio_open ) | ||
| 1798 | { | ||
| 1799 | Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF; | ||
| 1800 | t_CKINT num = GET_NEXT_INT(ARGS); | ||
| 1801 | t_CKINT baud = GET_NEXT_INT(ARGS); | ||
| 1802 | t_CKINT mode = GET_NEXT_INT(ARGS); | ||
| 1803 | |||
| 1804 | RETURN->v_int = cereal->open(num, mode, baud); | ||
| 1805 | } | ||
| 1806 | |||
| 1807 | CK_DLL_MFUN( serialio_close ) | ||
| 1808 | { | ||
| 1809 | Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF; | ||
| 1810 | |||
| 1811 | cereal->close(); | ||
| 1812 | } | ||
| 1813 | |||
| 1814 | CK_DLL_MFUN( serialio_ready ) | ||
| 1815 | { | ||
| 1816 | Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF; | ||
| 1817 | |||
| 1818 | RETURN->v_int = cereal->ready(); | ||
| 1819 | } | ||
| 1820 | |||
| 1821 | CK_DLL_MFUN( serialio_readLine ) | ||
| 1822 | { | ||
| 1823 | Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF; | ||
| 1824 | |||
| 1825 | RETURN->v_string = cereal->readLine(); | ||
| 1826 | } | ||
| 1827 | |||
| 1828 | |||
| 1829 | CK_DLL_MFUN( serialio_onLine ) | ||
| 1830 | { | ||
| 1831 | Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF; | ||
| 1832 | |||
| 1833 | cereal->readAsync(Chuck_IO_Serial::TYPE_LINE, 1); | ||
| 1834 | |||
| 1835 | RETURN->v_object = cereal; | ||
| 1836 | } | ||
| 1837 | |||
| 1838 | |||
| 1839 | CK_DLL_MFUN( serialio_onByte ) | ||
| 1840 | { | ||
| 1841 | Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF; | ||
| 1842 | |||
| 1843 | cereal->readAsync(Chuck_IO_Serial::TYPE_BYTE, 1); | ||
| 1844 | |||
| 1845 | RETURN->v_object = cereal; | ||
| 1846 | } | ||
| 1847 | |||
| 1848 | |||
| 1849 | CK_DLL_MFUN( serialio_onBytes ) | ||
| 1850 | { | ||
| 1851 | Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF; | ||
| 1852 | |||
| 1853 | t_CKINT num = GET_NEXT_INT(ARGS); | ||
| 1854 | |||
| 1855 | cereal->readAsync(Chuck_IO_Serial::TYPE_BYTE, num); | ||
| 1856 | |||
| 1857 | RETURN->v_object = cereal; | ||
| 1858 | } | ||
| 1859 | |||
| 1860 | |||
| 1861 | CK_DLL_MFUN( serialio_onInts ) | ||
| 1862 | { | ||
| 1863 | Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF; | ||
| 1864 | |||
| 1865 | t_CKINT num = GET_NEXT_INT(ARGS); | ||
| 1866 | |||
| 1867 | cereal->readAsync(Chuck_IO_Serial::TYPE_INT, num); | ||
| 1868 | |||
| 1869 | RETURN->v_object = cereal; | ||
| 1870 | } | ||
| 1871 | |||
| 1872 | |||
| 1873 | CK_DLL_MFUN( serialio_onFloats ) | ||
| 1874 | { | ||
| 1875 | Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF; | ||
| 1876 | |||
| 1877 | t_CKINT num = GET_NEXT_INT(ARGS); | ||
| 1878 | |||
| 1879 | cereal->readAsync(Chuck_IO_Serial::TYPE_FLOAT, num); | ||
| 1880 | |||
| 1881 | RETURN->v_object = cereal; | ||
| 1882 | } | ||
| 1883 | |||
| 1884 | |||
| 1885 | CK_DLL_MFUN( serialio_getLine ) | ||
| 1886 | { | ||
| 1887 | Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF; | ||
| 1888 | RETURN->v_string = cereal->getLine(); | ||
| 1889 | } | ||
| 1890 | |||
| 1891 | |||
| 1892 | CK_DLL_MFUN( serialio_getByte ) | ||
| 1893 | { | ||
| 1894 | Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF; | ||
| 1895 | RETURN->v_int = cereal->getByte(); | ||
| 1896 | } | ||
| 1897 | |||
| 1898 | |||
| 1899 | CK_DLL_MFUN( serialio_getBytes ) | ||
| 1900 | { | ||
| 1901 | Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF; | ||
| 1902 | RETURN->v_object = cereal->getBytes(); | ||
| 1903 | } | ||
| 1904 | |||
| 1905 | |||
| 1906 | CK_DLL_MFUN( serialio_getInts ) | ||
| 1907 | { | ||
| 1908 | Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF; | ||
| 1909 | RETURN->v_object = cereal->getInts(); | ||
| 1910 | } | ||
| 1911 | |||
| 1912 | |||
| 1913 | CK_DLL_MFUN( serialio_setBaudRate ) | ||
| 1914 | { | ||
| 1915 | Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF; | ||
| 1916 | cereal->setBaudRate(GET_NEXT_INT(ARGS)); | ||
| 1917 | RETURN->v_int = cereal->getBaudRate(); | ||
| 1918 | } | ||
| 1919 | |||
| 1920 | |||
| 1921 | CK_DLL_MFUN( serialio_getBaudRate ) | ||
| 1922 | { | ||
| 1923 | Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF; | ||
| 1924 | RETURN->v_int = cereal->getBaudRate(); | ||
| 1925 | } | ||
| 1926 | |||
| 1927 | |||
| 1928 | CK_DLL_MFUN( serialio_writeByte ) | ||
| 1929 | { | ||
| 1930 | Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF; | ||
| 1931 | t_CKINT byte = GET_NEXT_INT(ARGS); | ||
| 1932 | cereal->write(byte, 1); | ||
| 1933 | } | ||
| 1934 | |||
| 1935 | |||
| 1936 | CK_DLL_MFUN( serialio_writeBytes ) | ||
| 1937 | { | ||
| 1938 | Chuck_IO_Serial * cereal = (Chuck_IO_Serial *) SELF; | ||
| 1939 | Chuck_Array4 * arr = (Chuck_Array4 *) GET_NEXT_OBJECT(ARGS); | ||
| 1940 | cereal->writeBytes(arr); | ||
| 1941 | } | ||
| 1942 | |||
| 1943 | CK_DLL_MFUN(serialio_canWait) | ||
| 1944 | { | ||
| 1945 | Chuck_IO_Serial *cereal = (Chuck_IO_Serial *) SELF; | ||
| 1946 | RETURN->v_int = cereal->can_wait(); | ||
| 1947 | } | ||
| 1948 | |||
| 1949 | |||
| 1950 | |||
| @@ -0,0 +1,204 @@ | |||
| 1 | /*---------------------------------------------------------------------------- | ||
| 2 | ChucK Concurrent, On-the-fly Audio Programming Language | ||
| 3 | Compiler and Virtual Machine | ||
| 4 | |||
| 5 | Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. | ||
| 6 | http://chuck.stanford.edu/ | ||
| 7 | http://chuck.cs.princeton.edu/ | ||
| 8 | |||
| 9 | This program is free software; you can redistribute it and/or modify | ||
| 10 | it under the terms of the GNU General Public License as published by | ||
| 11 | the Free Software Foundation; either version 2 of the License, or | ||
| 12 | (at your option) any later version. | ||
| 13 | |||
| 14 | This program is distributed in the hope that it will be useful, | ||
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | GNU General Public License for more details. | ||
| 18 | |||
| 19 | You should have received a copy of the GNU General Public License | ||
| 20 | along with this program; if not, write to the Free Software | ||
| 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
| 22 | U.S.A. | ||
| 23 | -----------------------------------------------------------------------------*/ | ||
| 24 | |||
| 25 | //----------------------------------------------------------------------------- | ||
| 26 | // name: chuck_io.h | ||
| 27 | // desc: chuck i/o | ||
| 28 | // | ||
| 29 | // authors: Spencer Salazar (spencer@ccrma.stanford.edu) | ||
| 30 | // date: Summer 2012 | ||
| 31 | //----------------------------------------------------------------------------- | ||
| 32 | #ifndef __CHUCK_IO_H__ | ||
| 33 | #define __CHUCK_IO_H__ | ||
| 34 | |||
| 35 | #include "chuck_oo.h" | ||
| 36 | #include "util_thread.h" | ||
| 37 | #include "util_buffers.h" | ||
| 38 | #include <list> | ||
| 39 | |||
| 40 | |||
| 41 | |||
| 42 | |||
| 43 | //----------------------------------------------------------------------------- | ||
| 44 | // name: struct Chuck_IO_Serial | ||
| 45 | // desc: chuck serial I/O | ||
| 46 | //----------------------------------------------------------------------------- | ||
| 47 | struct Chuck_IO_Serial : public Chuck_IO | ||
| 48 | { | ||
| 49 | public: | ||
| 50 | Chuck_IO_Serial( Chuck_VM * vm ); | ||
| 51 | virtual ~Chuck_IO_Serial(); | ||
| 52 | |||
| 53 | static void shutdown(); | ||
| 54 | |||
| 55 | public: | ||
| 56 | // meta | ||
| 57 | virtual t_CKBOOL open( const t_CKUINT i, t_CKINT flags, t_CKUINT baud = CK_BAUD_9600 ); | ||
| 58 | virtual t_CKBOOL open( const std::string & path, t_CKINT flags, t_CKUINT baud = CK_BAUD_9600 ); | ||
| 59 | |||
| 60 | virtual t_CKBOOL can_wait(); | ||
| 61 | |||
| 62 | virtual t_CKBOOL good(); | ||
| 63 | virtual void close(); | ||
| 64 | virtual void flush(); | ||
| 65 | virtual t_CKINT mode(); | ||
| 66 | virtual void mode( t_CKINT flag ); | ||
| 67 | |||
| 68 | // reading | ||
| 69 | virtual Chuck_String * readLine(); | ||
| 70 | virtual t_CKINT readInt( t_CKINT flags ); | ||
| 71 | virtual t_CKFLOAT readFloat(); | ||
| 72 | virtual t_CKBOOL readString( std::string & str ); | ||
| 73 | virtual t_CKBOOL eof(); | ||
| 74 | |||
| 75 | // writing | ||
| 76 | virtual void write( const std::string & val ); | ||
| 77 | virtual void write( t_CKINT val ); | ||
| 78 | virtual void write( t_CKINT val, t_CKINT size ); | ||
| 79 | virtual void writeBytes( Chuck_Array4 * arr ); | ||
| 80 | virtual void write( t_CKFLOAT val ); | ||
| 81 | |||
| 82 | // serial stuff | ||
| 83 | virtual t_CKBOOL setBaudRate( t_CKUINT rate ); | ||
| 84 | virtual t_CKUINT getBaudRate(); | ||
| 85 | |||
| 86 | // async reading | ||
| 87 | virtual t_CKBOOL readAsync( t_CKUINT type, t_CKUINT num ); | ||
| 88 | virtual Chuck_String * getLine(); | ||
| 89 | virtual t_CKINT getByte(); | ||
| 90 | virtual Chuck_Array * getBytes(); | ||
| 91 | virtual Chuck_Array * getInts(); | ||
| 92 | virtual Chuck_Array * getFloats(); | ||
| 93 | virtual Chuck_String * getString(); | ||
| 94 | |||
| 95 | static const t_CKUINT TYPE_NONE; | ||
| 96 | static const t_CKUINT TYPE_BYTE; | ||
| 97 | static const t_CKUINT TYPE_WORD; | ||
| 98 | static const t_CKUINT TYPE_INT; | ||
| 99 | static const t_CKUINT TYPE_FLOAT; | ||
| 100 | static const t_CKUINT TYPE_STRING; | ||
| 101 | static const t_CKUINT TYPE_LINE; | ||
| 102 | static const t_CKUINT TYPE_WRITE; | ||
| 103 | |||
| 104 | struct Request | ||
| 105 | { | ||
| 106 | t_CKUINT m_type; // type | ||
| 107 | t_CKUINT m_num; // how many | ||
| 108 | t_CKUINT m_status; | ||
| 109 | t_CKUINT m_val; // ISSUE: 64-bit | ||
| 110 | |||
| 111 | enum Status | ||
| 112 | { | ||
| 113 | RQ_STATUS_PENDING, | ||
| 114 | RQ_STATUS_SUCCESS, | ||
| 115 | RQ_STATUS_FAILURE, | ||
| 116 | RQ_STATUS_INVALID, | ||
| 117 | RQ_STATUS_EOF, | ||
| 118 | }; | ||
| 119 | }; | ||
| 120 | |||
| 121 | virtual t_CKBOOL ready(); | ||
| 122 | |||
| 123 | // available baud rates | ||
| 124 | static const t_CKUINT CK_BAUD_2400; | ||
| 125 | static const t_CKUINT CK_BAUD_4800; | ||
| 126 | static const t_CKUINT CK_BAUD_9600; | ||
| 127 | static const t_CKUINT CK_BAUD_19200; | ||
| 128 | static const t_CKUINT CK_BAUD_38400; | ||
| 129 | static const t_CKUINT CK_BAUD_7200; | ||
| 130 | static const t_CKUINT CK_BAUD_14400; | ||
| 131 | static const t_CKUINT CK_BAUD_28800; | ||
| 132 | static const t_CKUINT CK_BAUD_57600; | ||
| 133 | static const t_CKUINT CK_BAUD_76800; | ||
| 134 | static const t_CKUINT CK_BAUD_115200; | ||
| 135 | static const t_CKUINT CK_BAUD_230400; | ||
| 136 | |||
| 137 | protected: | ||
| 138 | |||
| 139 | void start_read_thread(); | ||
| 140 | XThread * m_read_thread; | ||
| 141 | static void *shell_read_cb(void *); | ||
| 142 | void read_cb(); | ||
| 143 | |||
| 144 | XThread * m_write_thread; | ||
| 145 | static void *shell_write_cb(void *); | ||
| 146 | void write_cb(); | ||
| 147 | |||
| 148 | void close_int(); | ||
| 149 | |||
| 150 | t_CKBOOL get_buffer(t_CKINT timeout_ms = 1); | ||
| 151 | t_CKINT peek_buffer(); | ||
| 152 | t_CKINT pull_buffer(); | ||
| 153 | t_CKINT buffer_bytes_to_tmp(t_CKINT num_bytes); | ||
| 154 | |||
| 155 | t_CKBOOL handle_line(Request &); | ||
| 156 | t_CKBOOL handle_string(Request &); | ||
| 157 | t_CKBOOL handle_float_ascii(Request &); | ||
| 158 | t_CKBOOL handle_int_ascii(Request &); | ||
| 159 | t_CKBOOL handle_byte(Request &); | ||
| 160 | t_CKBOOL handle_float_binary(Request &); | ||
| 161 | t_CKBOOL handle_int_binary(Request &); | ||
| 162 | |||
| 163 | bool m_do_read_thread; | ||
| 164 | bool m_do_write_thread; | ||
| 165 | |||
| 166 | CircularBuffer<Request> m_asyncRequests; | ||
| 167 | CircularBuffer<Request> m_asyncResponses; | ||
| 168 | CBufferSimple * m_event_buffer; | ||
| 169 | |||
| 170 | int m_fd; | ||
| 171 | FILE * m_cfd; | ||
| 172 | |||
| 173 | std::string m_path; | ||
| 174 | |||
| 175 | unsigned char * m_io_buf; | ||
| 176 | t_CKUINT m_io_buf_max; | ||
| 177 | t_CKUINT m_io_buf_available; | ||
| 178 | t_CKUINT m_io_buf_pos; | ||
| 179 | |||
| 180 | unsigned char * m_tmp_buf; | ||
| 181 | t_CKUINT m_tmp_buf_max; | ||
| 182 | |||
| 183 | CircularBuffer<Request> m_asyncWriteRequests; | ||
| 184 | CircularBuffer<char> m_writeBuffer; | ||
| 185 | |||
| 186 | t_CKINT m_flags; | ||
| 187 | t_CKINT m_iomode; // SYNC or ASYNC | ||
| 188 | t_CKBOOL m_eof; | ||
| 189 | |||
| 190 | t_CKBOOL m_do_exit; | ||
| 191 | |||
| 192 | static std::list<Chuck_IO_Serial *> s_serials; | ||
| 193 | |||
| 194 | Chuck_VM * m_vmRef; | ||
| 195 | }; | ||
| 196 | |||
| 197 | |||
| 198 | // initialize | ||
| 199 | t_CKBOOL init_class_serialio( Chuck_Env * env ); // added 1.3.1 | ||
| 200 | |||
| 201 | |||
| 202 | |||
| 203 | |||
| 204 | #endif // __CHUCK_IO_H__ | ||
| @@ -0,0 +1,4861 @@ | |||
| 1 | /*---------------------------------------------------------------------------- | ||
| 2 | ChucK Concurrent, On-the-fly Audio Programming Language | ||
| 3 | Compiler and Virtual Machine | ||
| 4 | |||
| 5 | Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. | ||
| 6 | http://chuck.stanford.edu/ | ||
| 7 | http://chuck.cs.princeton.edu/ | ||
| 8 | |||
| 9 | This program is free software; you can redistribute it and/or modify | ||
| 10 | it under the terms of the GNU General Public License as published by | ||
| 11 | the Free Software Foundation; either version 2 of the License, or | ||
| 12 | (at your option) any later version. | ||
| 13 | |||
| 14 | This program is distributed in the hope that it will be useful, | ||
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | GNU General Public License for more details. | ||
| 18 | |||
| 19 | You should have received a copy of the GNU General Public License | ||
| 20 | along with this program; if not, write to the Free Software | ||
| 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
| 22 | U.S.A. | ||
| 23 | -----------------------------------------------------------------------------*/ | ||
| 24 | |||
| 25 | //----------------------------------------------------------------------------- | ||
| 26 | // name: chuck_lang.cpp | ||
| 27 | // desc: chuck class library base | ||
| 28 | // | ||
| 29 | // authors: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) | ||
| 30 | // Spencer Salazar (spencer@ccrma.stanford.edu) | ||
| 31 | // Ananya Misra (amisra@cs.princeton.edu) | ||
| 32 | // Andrew Schran (aschran@princeton.edu) | ||
| 33 | // date: spring 2005 | ||
| 34 | //----------------------------------------------------------------------------- | ||
| 35 | #include "chuck_lang.h" | ||
| 36 | #include "chuck_type.h" | ||
| 37 | #include "chuck_instr.h" | ||
| 38 | #include "chuck_vm.h" | ||
| 39 | #include "chuck_errmsg.h" | ||
| 40 | #include "chuck_ugen.h" | ||
| 41 | #include "chuck_globals.h" | ||
| 42 | #include "hidio_sdl.h" | ||
| 43 | #include "util_string.h" | ||
| 44 | #include "util_serial.h" | ||
| 45 | |||
| 46 | #ifndef __DISABLE_MIDI__ | ||
| 47 | #include "midiio_rtmidi.h" | ||
| 48 | #endif | ||
| 49 | |||
| 50 | #include <math.h> | ||
| 51 | #include <iostream> | ||
| 52 | #include <iomanip> | ||
| 53 | #include <sstream> | ||
| 54 | using namespace std; | ||
| 55 | |||
| 56 | // dac tick | ||
| 57 | CK_DLL_TICK(__ugen_tick) { *out = in; return TRUE; } | ||
| 58 | // object string offset | ||
| 59 | static t_CKUINT Object_offset_string = 0; | ||
| 60 | |||
| 61 | // global | ||
| 62 | static Chuck_String * g_newline = new Chuck_String(); | ||
| 63 | |||
| 64 | |||
| 65 | |||
| 66 | |||
| 67 | |||
| 68 | |||
| 69 | |||
| 70 | //----------------------------------------------------------------------------- | ||
| 71 | // name: init_class_object() | ||
| 72 | // desc: ... | ||
| 73 | //----------------------------------------------------------------------------- | ||
| 74 | t_CKBOOL init_class_object( Chuck_Env * env, Chuck_Type * type ) | ||
| 75 | { | ||
| 76 | Chuck_DL_Func * func = NULL; | ||
| 77 | |||
| 78 | // log | ||
| 79 | EM_log( CK_LOG_SEVERE, "class 'object'" ); | ||
| 80 | |||
| 81 | const char * doc = "Base class for all class types in ChucK."; | ||
| 82 | |||
| 83 | // init as base class | ||
| 84 | if( !type_engine_import_class_begin( env, type, env->global(), object_ctor, object_dtor, doc ) ) | ||
| 85 | return FALSE; | ||
| 86 | |||
| 87 | // add member to hold string | ||
| 88 | Object_offset_string = type_engine_import_mvar( env, "string", "@string", FALSE ); | ||
| 89 | if( Object_offset_string == CK_INVALID_OFFSET ) goto error; | ||
| 90 | |||
| 91 | // add toString() | ||
| 92 | func = make_new_mfun( "string", "toString", object_toString ); | ||
| 93 | func->doc = "Return a textual description of this object."; | ||
| 94 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 95 | |||
| 96 | // end the class import | ||
| 97 | type_engine_import_class_end( env ); | ||
| 98 | |||
| 99 | return TRUE; | ||
| 100 | |||
| 101 | error: | ||
| 102 | |||
| 103 | // end the class import | ||
| 104 | type_engine_import_class_end( env ); | ||
| 105 | |||
| 106 | return FALSE; | ||
| 107 | } | ||
| 108 | |||
| 109 | |||
| 110 | |||
| 111 | |||
| 112 | //----------------------------------------------------------------------------- | ||
| 113 | // name: init_class_ugen() | ||
| 114 | // desc: ... | ||
| 115 | //----------------------------------------------------------------------------- | ||
| 116 | t_CKBOOL init_class_ugen( Chuck_Env * env, Chuck_Type * type ) | ||
| 117 | { | ||
| 118 | Chuck_DL_Func * func = NULL; | ||
| 119 | |||
| 120 | EM_log( CK_LOG_SEVERE, "class 'ugen'" ); | ||
| 121 | |||
| 122 | // add ugen info | ||
| 123 | type->ugen_info = new Chuck_UGen_Info; | ||
| 124 | type->ugen_info->add_ref(); | ||
| 125 | type->ugen_info->tick = __ugen_tick; | ||
| 126 | type->ugen_info->num_ins = 1; | ||
| 127 | type->ugen_info->num_outs = 1; | ||
| 128 | |||
| 129 | const char * doc = "Base class for all UGen types in ChucK."; | ||
| 130 | |||
| 131 | // init as base class | ||
| 132 | // TODO: ctor/dtor, ugen's sometimes created internally? | ||
| 133 | if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL, doc ) ) | ||
| 134 | return FALSE; | ||
| 135 | |||
| 136 | // gain | ||
| 137 | func = make_new_mfun( "float", "gain", ugen_gain ); | ||
| 138 | func->add_arg( "float", "val" ); | ||
| 139 | func->doc = "Set the gain of the ugen."; | ||
| 140 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 141 | func = make_new_mfun( "float", "gain", ugen_cget_gain ); | ||
| 142 | func->doc = "Return the gain of the ugen."; | ||
| 143 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 144 | |||
| 145 | /* // next | ||
| 146 | func = make_new_mfun( "float", "next", ugen_next ); | ||
| 147 | func->add_arg( "float", "val" ); | ||
| 148 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 149 | func = make_new_mfun( "float", "next", ugen_cget_next ); | ||
| 150 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 151 | */ | ||
| 152 | // last | ||
| 153 | func = make_new_mfun( "float", "last", ugen_last ); | ||
| 154 | func->doc = "Return the last sample value of the unit generator."; | ||
| 155 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 156 | |||
| 157 | // op | ||
| 158 | func = make_new_mfun( "int", "op", ugen_op ); | ||
| 159 | func->add_arg( "int", "val" ); | ||
| 160 | func->doc = "Set the ugen's operation mode. Accepted values are: 1 (sum inputs), 2 (take difference between first input and subsequent inputs), 3 (multiply inputs), 4 (divide first input by subsequent inputs), 0 (do not synthesize audio, output 0) or -1 (passthrough inputs to output)."; | ||
| 161 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 162 | func = make_new_mfun( "int", "op", ugen_cget_op ); | ||
| 163 | func->doc = "Return the ugen's operation mode."; | ||
| 164 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 165 | |||
| 166 | // add numChannels | ||
| 167 | func = make_new_mfun( "int", "channels", ugen_numChannels ); | ||
| 168 | func->add_arg( "int", "num" ); | ||
| 169 | func->doc = "Set number of channels. (Not currently supported.)"; | ||
| 170 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 171 | func = make_new_mfun( "int", "channels", ugen_cget_numChannels ); | ||
| 172 | func->doc = "Return number of channels."; | ||
| 173 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 174 | |||
| 175 | // add chan | ||
| 176 | func = make_new_mfun( "UGen", "chan", ugen_chan ); | ||
| 177 | func->add_arg( "int", "num" ); | ||
| 178 | func->doc = "Return channel at specified index."; | ||
| 179 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 180 | |||
| 181 | // add isConnectedTo | ||
| 182 | func = make_new_mfun( "int", "isConnectedTo", ugen_connected ); | ||
| 183 | func->add_arg( "UGen", "right" ); | ||
| 184 | func->doc = "Return true if this ugen's output is connected to the input of the argument. Return false otherwise. "; | ||
| 185 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 186 | |||
| 187 | // end | ||
| 188 | type_engine_import_class_end( env ); | ||
| 189 | |||
| 190 | return TRUE; | ||
| 191 | |||
| 192 | error: | ||
| 193 | |||
| 194 | // end the class import | ||
| 195 | type_engine_import_class_end( env ); | ||
| 196 | |||
| 197 | return FALSE; | ||
| 198 | } | ||
| 199 | |||
| 200 | |||
| 201 | |||
| 202 | |||
| 203 | // virtual table offset | ||
| 204 | static t_CKINT uana_offset_blob = 0; | ||
| 205 | //----------------------------------------------------------------------------- | ||
| 206 | // name: init_class_uana() | ||
| 207 | // desc: ... | ||
| 208 | //----------------------------------------------------------------------------- | ||
| 209 | t_CKBOOL init_class_uana( Chuck_Env * env, Chuck_Type * type ) | ||
| 210 | { | ||
| 211 | Chuck_DL_Func * func = NULL; | ||
| 212 | |||
| 213 | EM_log( CK_LOG_SEVERE, "class 'uana'" ); | ||
| 214 | |||
| 215 | // add uana info | ||
| 216 | type->ugen_info = new Chuck_UGen_Info; | ||
| 217 | type->ugen_info->add_ref(); | ||
| 218 | type->ugen_info->tick = __ugen_tick; | ||
| 219 | type->ugen_info->num_ins = 1; | ||
| 220 | type->ugen_info->num_outs = 1; | ||
| 221 | |||
| 222 | const char * doc = "Base class from which all unit analyzers (UAnae) inherit; UAnae (note plural form) can be interconnected via => (standard chuck operator) or via =^ (upchuck operator), specify the the types of and when data is passed between UAnae and UGens. When .upchuck() is invoked on a given UAna, the UAna-chain (UAnae connected via =^) is traversed backwards from the upchucked UAna, and analysis is performed at each UAna along the chain; the updated analysis results are stored in UAnaBlobs."; | ||
| 223 | |||
| 224 | // init as base class, type should already know the parent type | ||
| 225 | // TODO: ctor/dtor, ugen's sometimes created internally? | ||
| 226 | if( !type_engine_import_class_begin( env, type, env->global(), uana_ctor, uana_dtor, doc ) ) | ||
| 227 | return FALSE; | ||
| 228 | |||
| 229 | // add variables | ||
| 230 | uana_offset_blob = type_engine_import_mvar( env, "UAnaBlob", "m_blob", FALSE ); | ||
| 231 | if( uana_offset_blob == CK_INVALID_OFFSET ) goto error; | ||
| 232 | |||
| 233 | // add upchuck | ||
| 234 | func = make_new_mfun( "UAnaBlob", "upchuck", uana_upchuck ); | ||
| 235 | func->doc = "Initiate analysis at the UAna; returns result."; | ||
| 236 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 237 | |||
| 238 | // add fvals | ||
| 239 | func = make_new_mfun( "float[]", "fvals", uana_fvals ); | ||
| 240 | func->doc = "Get blob's float array."; | ||
| 241 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 242 | |||
| 243 | // add cvals | ||
| 244 | func = make_new_mfun( "complex[]", "cvals", uana_cvals ); | ||
| 245 | func->doc = "Get blob's complex array."; | ||
| 246 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 247 | |||
| 248 | // add fval | ||
| 249 | func = make_new_mfun( "float", "fval", uana_fval ); | ||
| 250 | func->add_arg( "int", "index" ); | ||
| 251 | func->doc = "Get blob's float value at index."; | ||
| 252 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 253 | |||
| 254 | // add cval | ||
| 255 | func = make_new_mfun( "complex", "cval", uana_cval ); | ||
| 256 | func->add_arg( "int", "index" ); | ||
| 257 | func->doc = "Get blob's complex value at index."; | ||
| 258 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 259 | |||
| 260 | // add isUpConnectedTo | ||
| 261 | func = make_new_mfun( "int", "isUpConnectedTo", uana_connected ); | ||
| 262 | func->add_arg( "UAna", "right" ); | ||
| 263 | func->doc = "Is connected to another uana via =^?"; | ||
| 264 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 265 | |||
| 266 | // TODO: add nonchuck | ||
| 267 | // func = make_new_mfun( "void", "nonchuck", uana_nonchuck ); | ||
| 268 | // if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 269 | |||
| 270 | // TODO: add event | ||
| 271 | // func = make_new_mfun( "Event", "event", uana_event ); | ||
| 272 | // if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 273 | |||
| 274 | // end | ||
| 275 | type_engine_import_class_end( env ); | ||
| 276 | |||
| 277 | return TRUE; | ||
| 278 | |||
| 279 | error: | ||
| 280 | |||
| 281 | // end the class import | ||
| 282 | type_engine_import_class_end( env ); | ||
| 283 | |||
| 284 | return FALSE; | ||
| 285 | } | ||
| 286 | |||
| 287 | |||
| 288 | |||
| 289 | |||
| 290 | // virtual table offset | ||
| 291 | static t_CKINT uanablob_offset_when = 0; | ||
| 292 | static t_CKINT uanablob_offset_fvals = 0; | ||
| 293 | static t_CKINT uanablob_offset_cvals = 0; | ||
| 294 | //----------------------------------------------------------------------------- | ||
| 295 | // name: init_class_blob() | ||
| 296 | // desc: ... | ||
| 297 | //----------------------------------------------------------------------------- | ||
| 298 | t_CKBOOL init_class_blob( Chuck_Env * env, Chuck_Type * type ) | ||
| 299 | { | ||
| 300 | Chuck_DL_Func * func = NULL; | ||
| 301 | // Chuck_Value * value = NULL; | ||
| 302 | |||
| 303 | // log | ||
| 304 | EM_log( CK_LOG_SEVERE, "class 'uanablob'" ); | ||
| 305 | |||
| 306 | const char * doc = "This object contains results associated with UAna analysis. There is a UAnaBlob associated with every UAna. As a UAna is upchucked, the result is stored in the UAnaBlob's floating point vector and/or complex vector. The intended interpretation of the results depends on the specific UAna."; | ||
| 307 | |||
| 308 | // init class | ||
| 309 | // TODO: ctor/dtor | ||
| 310 | if( !type_engine_import_class_begin( env, type, env->global(), uanablob_ctor, uanablob_dtor, doc ) ) | ||
| 311 | return FALSE; | ||
| 312 | |||
| 313 | // add variables | ||
| 314 | uanablob_offset_when = type_engine_import_mvar( env, "time", "m_when", FALSE ); | ||
| 315 | if( uanablob_offset_when == CK_INVALID_OFFSET ) goto error; | ||
| 316 | uanablob_offset_fvals = type_engine_import_mvar( env, "float[]", "m_fvals", FALSE ); | ||
| 317 | if( uanablob_offset_fvals == CK_INVALID_OFFSET ) goto error; | ||
| 318 | uanablob_offset_cvals = type_engine_import_mvar( env, "complex[]", "m_cvals", FALSE ); | ||
| 319 | if( uanablob_offset_cvals == CK_INVALID_OFFSET ) goto error; | ||
| 320 | |||
| 321 | // add when | ||
| 322 | func = make_new_mfun( "time", "when", uanablob_when ); | ||
| 323 | func->doc = "Get the time when blob was last upchucked."; | ||
| 324 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 325 | |||
| 326 | // add fvals | ||
| 327 | func = make_new_mfun( "float[]", "fvals", uanablob_fvals ); | ||
| 328 | func->doc = "Get blob's float array."; | ||
| 329 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 330 | |||
| 331 | // add cvals | ||
| 332 | func = make_new_mfun( "complex[]", "cvals", uanablob_cvals ); | ||
| 333 | func->doc = "Get blob's complex array."; | ||
| 334 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 335 | |||
| 336 | // add fval | ||
| 337 | func = make_new_mfun( "float", "fval", uanablob_fval ); | ||
| 338 | func->add_arg( "int", "index" ); | ||
| 339 | func->doc = "Get blob's float value at index."; | ||
| 340 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 341 | |||
| 342 | // add cval | ||
| 343 | func = make_new_mfun( "complex", "cval", uanablob_cval ); | ||
| 344 | func->add_arg( "int", "index" ); | ||
| 345 | func->doc = "Get blob's complex value at index."; | ||
| 346 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 347 | |||
| 348 | // end class import | ||
| 349 | type_engine_import_class_end( env ); | ||
| 350 | |||
| 351 | // done | ||
| 352 | return TRUE; | ||
| 353 | |||
| 354 | error: | ||
| 355 | |||
| 356 | // end class import | ||
| 357 | type_engine_import_class_end( env ); | ||
| 358 | |||
| 359 | // error | ||
| 360 | return FALSE; | ||
| 361 | } | ||
| 362 | |||
| 363 | |||
| 364 | |||
| 365 | |||
| 366 | // static t_CKUINT event_offset_data = 0; | ||
| 367 | //----------------------------------------------------------------------------- | ||
| 368 | // name: init_class_event() | ||
| 369 | // desc: ... | ||
| 370 | //----------------------------------------------------------------------------- | ||
| 371 | t_CKBOOL init_class_event( Chuck_Env * env, Chuck_Type * type ) | ||
| 372 | { | ||
| 373 | Chuck_DL_Func * func = NULL; | ||
| 374 | Chuck_Value * value = NULL; | ||
| 375 | |||
| 376 | // log | ||
| 377 | EM_log( CK_LOG_SEVERE, "class 'event'" ); | ||
| 378 | |||
| 379 | const char *doc = "The Event class allows exact synchronization across an arbitrary number of shreds."; | ||
| 380 | |||
| 381 | // init as base class | ||
| 382 | // TODO: ctor/dtor? | ||
| 383 | if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL, doc ) ) | ||
| 384 | return FALSE; | ||
| 385 | |||
| 386 | // add signal() | ||
| 387 | func = make_new_mfun( "void", "signal", event_signal ); | ||
| 388 | func->doc = "Signal one shred that is waiting on this event. "; | ||
| 389 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 390 | |||
| 391 | // add broadcast() | ||
| 392 | func = make_new_mfun( "void", "broadcast", event_broadcast ); | ||
| 393 | func->doc = "Signal all shreds that are waiting on this event."; | ||
| 394 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 395 | |||
| 396 | // add wait() | ||
| 397 | func = make_new_mfun( "void", "wait", event_wait ); | ||
| 398 | func->add_arg( "Shred", "me" ); | ||
| 399 | func->doc = "(Currently unsupported.)"; | ||
| 400 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 401 | |||
| 402 | // add can_wait() | ||
| 403 | func = make_new_mfun( "int", "can_wait", event_can_wait ); | ||
| 404 | func->doc = "Whether or not the event can be waited on. Currently always returns true."; | ||
| 405 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 406 | |||
| 407 | // end the class import | ||
| 408 | type_engine_import_class_end( env ); | ||
| 409 | |||
| 410 | // find the offset for can_wait | ||
| 411 | value = type_engine_find_value( type, "can_wait" ); | ||
| 412 | assert( value != NULL ); | ||
| 413 | assert( value->func_ref != NULL ); | ||
| 414 | // remember it | ||
| 415 | Chuck_Event::our_can_wait = value->func_ref->vt_index; | ||
| 416 | |||
| 417 | return TRUE; | ||
| 418 | |||
| 419 | error: | ||
| 420 | |||
| 421 | // end the class import | ||
| 422 | type_engine_import_class_end( env ); | ||
| 423 | |||
| 424 | return FALSE; | ||
| 425 | } | ||
| 426 | |||
| 427 | |||
| 428 | |||
| 429 | |||
| 430 | // static t_CKUINT shred_offset_args = 0; | ||
| 431 | //----------------------------------------------------------------------------- | ||
| 432 | // name: init_class_shred() | ||
| 433 | // desc: ... | ||
| 434 | //----------------------------------------------------------------------------- | ||
| 435 | t_CKBOOL init_class_shred( Chuck_Env * env, Chuck_Type * type ) | ||
| 436 | { | ||
| 437 | // init as base class | ||
| 438 | Chuck_DL_Func * func = NULL; | ||
| 439 | |||
| 440 | // log | ||
| 441 | EM_log( CK_LOG_SEVERE, "class 'shred'" ); | ||
| 442 | |||
| 443 | const char *doc = "Shred facilitates various operations and interactions with shreds running in the ChucK virtual machine."; | ||
| 444 | |||
| 445 | // init as base class | ||
| 446 | // TODO: ctor/dtor? | ||
| 447 | if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL, doc ) ) | ||
| 448 | return FALSE; | ||
| 449 | |||
| 450 | // add dtor | ||
| 451 | // not | ||
| 452 | |||
| 453 | // add fromId() | ||
| 454 | func = make_new_sfun( "Shred", "fromId", shred_fromId ); | ||
| 455 | func->add_arg( "int", "id" ); | ||
| 456 | func->doc = "Return a Shred object corresponding to the provided shred ID."; | ||
| 457 | if( !type_engine_import_sfun( env, func ) ) goto error; | ||
| 458 | |||
| 459 | // add clone() | ||
| 460 | func = make_new_mfun( "void", "clone", shred_clone ); | ||
| 461 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 462 | |||
| 463 | // add exit() | ||
| 464 | func = make_new_mfun( "void", "exit", shred_exit ); | ||
| 465 | func->doc = "Immediately halt the shred's operation and remove it from the virtual machine."; | ||
| 466 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 467 | |||
| 468 | // add id() | ||
| 469 | func = make_new_mfun( "int", "id", shred_id ); | ||
| 470 | func->doc = "Return the unique numeric id of the shred."; | ||
| 471 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 472 | |||
| 473 | // add yield() | ||
| 474 | func = make_new_mfun( "void", "yield", shred_yield ); | ||
| 475 | func->doc = "Cause the shred to temporarily stop processing, allowing other scheduled shreds to run as needed."; | ||
| 476 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 477 | |||
| 478 | // add running() | ||
| 479 | func = make_new_mfun( "int", "running", shred_running ); | ||
| 480 | func->doc = "Return true if the shred is currently running; false otherwise."; | ||
| 481 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 482 | |||
| 483 | // add done() | ||
| 484 | func = make_new_mfun( "int", "done", shred_done ); | ||
| 485 | func->doc = "Return true if the shred is done processing; false otherwise."; | ||
| 486 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 487 | |||
| 488 | // add nargs() | ||
| 489 | // func = make_new_mfun( "int", "numArgs", shred_numArgs ); | ||
| 490 | // if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 491 | |||
| 492 | // add nargs() | ||
| 493 | func = make_new_mfun( "int", "args", shred_numArgs ); | ||
| 494 | func->doc = "Return the number of arguments provided to the shred."; | ||
| 495 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 496 | |||
| 497 | // add arg() | ||
| 498 | // func = make_new_mfun( "string", "getArg", shred_getArg ); | ||
| 499 | // func->add_arg( "int", "index" ); | ||
| 500 | // if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 501 | |||
| 502 | // add arg() | ||
| 503 | func = make_new_mfun( "string", "arg", shred_getArg ); | ||
| 504 | func->add_arg( "int", "index" ); | ||
| 505 | func->doc = "Return the argument at the specified index."; | ||
| 506 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 507 | |||
| 508 | // add sourcePath() (added 1.3.0.0) | ||
| 509 | func = make_new_mfun( "string", "sourcePath", shred_sourcePath ); | ||
| 510 | func->doc = "Return the path of the source code file from which this shred's code is derived."; | ||
| 511 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 512 | |||
| 513 | // add path() (added 1.3.2.0) | ||
| 514 | func = make_new_mfun( "string", "path", shred_sourcePath ); | ||
| 515 | func->doc = "Return the file path of the source code file from which this shred's code is derived (same as .sourcePath())."; | ||
| 516 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 517 | |||
| 518 | // add sourceDir() (added 1.3.0.0) | ||
| 519 | func = make_new_mfun( "string", "sourceDir", shred_sourceDir ); | ||
| 520 | func->doc = "Return the enclosing directory of the source code file from which this shred's code is derived."; | ||
| 521 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 522 | |||
| 523 | // add dir() (added 1.3.2.0) | ||
| 524 | func = make_new_mfun( "string", "dir", shred_sourceDir ); | ||
| 525 | func->doc = "Return the enclosing directory of the source code file from which this shred's code is derived (same as .sourceDir())."; | ||
| 526 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 527 | |||
| 528 | // add dir() (added 1.3.2.0, ge) | ||
| 529 | func = make_new_mfun( "string", "dir", shred_sourceDir2 ); | ||
| 530 | func->add_arg( "int", "levelsUp" ); | ||
| 531 | func->doc = "Return the enclosing directory, the specified number of parent directories up."; | ||
| 532 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 533 | |||
| 534 | // end the class import | ||
| 535 | type_engine_import_class_end( env ); | ||
| 536 | |||
| 537 | return TRUE; | ||
| 538 | |||
| 539 | error: | ||
| 540 | |||
| 541 | // end the class import | ||
| 542 | type_engine_import_class_end( env ); | ||
| 543 | |||
| 544 | return FALSE; | ||
| 545 | } | ||
| 546 | |||
| 547 | |||
| 548 | |||
| 549 | |||
| 550 | //----------------------------------------------------------------------------- | ||
| 551 | // name: init_class_vec3() | ||
| 552 | // desc: initialize primitive type vec3 | ||
| 553 | //----------------------------------------------------------------------------- | ||
| 554 | t_CKBOOL init_class_vec3( Chuck_Env * env, Chuck_Type * type ) | ||
| 555 | { | ||
| 556 | // init as base class | ||
| 557 | Chuck_DL_Func * func = NULL; | ||
| 558 | |||
| 559 | // log | ||
| 560 | EM_log( CK_LOG_SEVERE, "class 'vec3' (primitive)" ); | ||
| 561 | |||
| 562 | // document | ||
| 563 | const char *doc = "vec3 is a primitive type for a 3-dimensional vector; potentially useful for 3D coordinates, RGB color, or as a value/goal/slew interpolator."; | ||
| 564 | |||
| 565 | // init as base class | ||
| 566 | if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL, doc ) ) | ||
| 567 | return FALSE; | ||
| 568 | |||
| 569 | // add set(float,float,float) | ||
| 570 | func = make_new_mfun( "void", "set", vec3_set ); | ||
| 571 | func->add_arg( "float", "x" ); | ||
| 572 | func->add_arg( "float", "y" ); | ||
| 573 | func->add_arg( "float", "z" ); | ||
| 574 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 575 | |||
| 576 | // add setAll(float) | ||
| 577 | func = make_new_mfun( "void", "setAll", vec3_setAll ); | ||
| 578 | func->add_arg( "float", "value" ); | ||
| 579 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 580 | |||
| 581 | // add magnitude() | ||
| 582 | func = make_new_mfun( "float", "magnitude", vec3_magnitude ); | ||
| 583 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 584 | |||
| 585 | // add normalize() | ||
| 586 | func = make_new_mfun( "void", "normalize", vec3_normalize ); | ||
| 587 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 588 | |||
| 589 | // add interp() | ||
| 590 | func = make_new_mfun( "float", "interp", vec3_interp ); | ||
| 591 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 592 | |||
| 593 | // add interp( float ) | ||
| 594 | func = make_new_mfun( "float", "interp", vec3_interp_delta_float ); | ||
| 595 | func->add_arg( "float", "delta" ); | ||
| 596 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 597 | |||
| 598 | // add interp( dur ) | ||
| 599 | func = make_new_mfun( "float", "interp", vec3_interp_delta_dur ); | ||
| 600 | func->add_arg( "dur", "delta" ); | ||
| 601 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 602 | |||
| 603 | // add update( float ) | ||
| 604 | func = make_new_mfun( "void", "update", vec3_update_goal ); | ||
| 605 | func->add_arg( "float", "goal" ); | ||
| 606 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 607 | |||
| 608 | // add update( float, float ) | ||
| 609 | func = make_new_mfun( "void", "update", vec3_update_goal_slew ); | ||
| 610 | func->add_arg( "float", "goal" ); | ||
| 611 | func->add_arg( "float", "slew" ); | ||
| 612 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 613 | |||
| 614 | // add update( float ) | ||
| 615 | func = make_new_mfun( "void", "updateSet", vec3_updateSet_goalAndValue ); | ||
| 616 | func->add_arg( "float", "goalAndValue" ); | ||
| 617 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 618 | |||
| 619 | // add update( float, float ) | ||
| 620 | func = make_new_mfun( "void", "updateSet", vec3_updateSet_goalAndValue_slew ); | ||
| 621 | func->add_arg( "float", "goal" ); | ||
| 622 | func->add_arg( "float", "slew" ); | ||
| 623 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 624 | |||
| 625 | // end the class import | ||
| 626 | type_engine_import_class_end( env ); | ||
| 627 | |||
| 628 | return TRUE; | ||
| 629 | |||
| 630 | error: | ||
| 631 | // end the class import | ||
| 632 | type_engine_import_class_end( env ); | ||
| 633 | |||
| 634 | return FALSE; | ||
| 635 | } | ||
| 636 | |||
| 637 | |||
| 638 | |||
| 639 | |||
| 640 | //----------------------------------------------------------------------------- | ||
| 641 | // name: init_class_vec4() | ||
| 642 | // desc: initialize primitive type vec4 | ||
| 643 | //----------------------------------------------------------------------------- | ||
| 644 | t_CKBOOL init_class_vec4( Chuck_Env * env, Chuck_Type * type ) | ||
| 645 | { | ||
| 646 | // init as base class | ||
| 647 | Chuck_DL_Func * func = NULL; | ||
| 648 | |||
| 649 | // log | ||
| 650 | EM_log( CK_LOG_SEVERE, "class 'vec4' (primitive)" ); | ||
| 651 | |||
| 652 | // document | ||
| 653 | const char *doc = "vec4 is a primitive type for a 4-dimensional vector; potentially useful for 4D coordinatesm and RGBA color."; | ||
| 654 | |||
| 655 | // init as base class | ||
| 656 | if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL, doc ) ) | ||
| 657 | return FALSE; | ||
| 658 | |||
| 659 | // add set(float,float,float) | ||
| 660 | func = make_new_mfun( "void", "set", vec4_set ); | ||
| 661 | func->add_arg( "float", "x" ); | ||
| 662 | func->add_arg( "float", "y" ); | ||
| 663 | func->add_arg( "float", "z" ); | ||
| 664 | func->add_arg( "float", "w" ); | ||
| 665 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 666 | |||
| 667 | // add setAll(float) | ||
| 668 | func = make_new_mfun( "void", "setAll", vec4_setAll ); | ||
| 669 | func->add_arg( "float", "value" ); | ||
| 670 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 671 | |||
| 672 | // add magnitude() | ||
| 673 | func = make_new_mfun( "float", "magnitude", vec4_magnitude ); | ||
| 674 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 675 | |||
| 676 | // add normalize() | ||
| 677 | func = make_new_mfun( "void", "normalize", vec4_normalize ); | ||
| 678 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 679 | |||
| 680 | // end the class import | ||
| 681 | type_engine_import_class_end( env ); | ||
| 682 | |||
| 683 | return TRUE; | ||
| 684 | |||
| 685 | error: | ||
| 686 | // end the class import | ||
| 687 | type_engine_import_class_end( env ); | ||
| 688 | |||
| 689 | return FALSE; | ||
| 690 | } | ||
| 691 | |||
| 692 | |||
| 693 | |||
| 694 | |||
| 695 | //----------------------------------------------------------------------------- | ||
| 696 | // name: init_class_io() | ||
| 697 | // desc: ... | ||
| 698 | //----------------------------------------------------------------------------- | ||
| 699 | t_CKBOOL init_class_io( Chuck_Env * env, Chuck_Type * type ) | ||
| 700 | { | ||
| 701 | // init as base class | ||
| 702 | Chuck_DL_Func * func = NULL; | ||
| 703 | |||
| 704 | // log | ||
| 705 | EM_log( CK_LOG_SEVERE, "class 'io'" ); | ||
| 706 | |||
| 707 | // init as base class | ||
| 708 | // TODO: ctor/dtor? | ||
| 709 | // TODO: replace dummy with pure function | ||
| 710 | if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL ) ) | ||
| 711 | return FALSE; | ||
| 712 | |||
| 713 | // add good() | ||
| 714 | func = make_new_mfun( "int", "good", io_dummy ); | ||
| 715 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 716 | |||
| 717 | // add close() | ||
| 718 | func = make_new_mfun( "void", "close", io_dummy ); | ||
| 719 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 720 | |||
| 721 | // add flush() | ||
| 722 | func = make_new_mfun( "void", "flush", io_dummy ); | ||
| 723 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 724 | |||
| 725 | // add mode(int) | ||
| 726 | func = make_new_mfun( "int", "mode", io_dummy ); | ||
| 727 | func->add_arg( "int", "flag" ); | ||
| 728 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 729 | |||
| 730 | // add mode() | ||
| 731 | func = make_new_mfun( "int", "mode", io_dummy ); | ||
| 732 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 733 | |||
| 734 | // TODO: add this later? | ||
| 735 | // add read() | ||
| 736 | // func = make_new_mfun( "string", "read", io_dummy ); | ||
| 737 | // func->add_arg( "int", "length" ); | ||
| 738 | // if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 739 | |||
| 740 | // add readLine() | ||
| 741 | func = make_new_mfun( "string", "readLine", io_dummy ); | ||
| 742 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 743 | |||
| 744 | // add readInt() | ||
| 745 | func = make_new_mfun( "int", "readInt", io_dummy ); | ||
| 746 | func->add_arg( "int", "flags" ); | ||
| 747 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 748 | |||
| 749 | // add readFloat() | ||
| 750 | // func = make_new_mfun( "float", "readFloat", io_dummy ); | ||
| 751 | // if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 752 | |||
| 753 | // add eof() | ||
| 754 | func = make_new_mfun( "int", "eof", io_dummy ); | ||
| 755 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 756 | |||
| 757 | // add more() | ||
| 758 | func = make_new_mfun( "int", "more", io_dummy ); | ||
| 759 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 760 | |||
| 761 | // add write(string) | ||
| 762 | func = make_new_mfun( "void", "write", io_dummy ); | ||
| 763 | func->add_arg( "string", "val" ); | ||
| 764 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 765 | |||
| 766 | // add write(int) | ||
| 767 | func = make_new_mfun( "void", "write", io_dummy ); | ||
| 768 | func->add_arg( "int", "val" ); | ||
| 769 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 770 | |||
| 771 | // add write(float) | ||
| 772 | func = make_new_mfun( "void", "write", io_dummy ); | ||
| 773 | func->add_arg( "float", "val" ); | ||
| 774 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 775 | |||
| 776 | // add newline | ||
| 777 | func = make_new_sfun( "string", "newline", io_newline ); | ||
| 778 | if( !type_engine_import_sfun( env, func ) ) goto error; | ||
| 779 | func = make_new_sfun( "string", "nl", io_newline ); | ||
| 780 | if( !type_engine_import_sfun( env, func ) ) goto error; | ||
| 781 | func = make_new_sfun( "string", "newlineEx2VistaHWNDVisualFoxProA", io_newline ); | ||
| 782 | if( !type_engine_import_sfun( env, func ) ) goto error; | ||
| 783 | initialize_object( g_newline, env->t_string ); | ||
| 784 | g_newline->set( "\n" ); | ||
| 785 | |||
| 786 | // add READ_INT32 | ||
| 787 | if( !type_engine_import_svar( env, "int", "READ_INT32", | ||
| 788 | TRUE, (t_CKUINT)&Chuck_IO::INT32 ) ) goto error; | ||
| 789 | |||
| 790 | // add READ_INT16 | ||
| 791 | if( !type_engine_import_svar( env, "int", "READ_INT16", | ||
| 792 | TRUE, (t_CKUINT)&Chuck_IO::INT16 ) ) goto error; | ||
| 793 | |||
| 794 | // add READ_INT8 | ||
| 795 | if( !type_engine_import_svar( env, "int", "READ_INT8", | ||
| 796 | TRUE, (t_CKUINT)&Chuck_IO::INT8 ) ) goto error; | ||
| 797 | |||
| 798 | // add INT32 | ||
| 799 | if( !type_engine_import_svar( env, "int", "INT32", | ||
| 800 | TRUE, (t_CKUINT)&Chuck_IO::INT32 ) ) goto error; | ||
| 801 | |||
| 802 | // add INT16 | ||
| 803 | if( !type_engine_import_svar( env, "int", "INT16", | ||
| 804 | TRUE, (t_CKUINT)&Chuck_IO::INT16 ) ) goto error; | ||
| 805 | |||
| 806 | // add INT8 | ||
| 807 | if( !type_engine_import_svar( env, "int", "INT8", | ||
| 808 | TRUE, (t_CKUINT)&Chuck_IO::INT8 ) ) goto error; | ||
| 809 | |||
| 810 | // add MODE_SYNC | ||
| 811 | if( !type_engine_import_svar( env, "int", "MODE_SYNC", | ||
| 812 | TRUE, (t_CKUINT)&Chuck_IO::MODE_SYNC ) ) goto error; | ||
| 813 | |||
| 814 | // add MODE_ASYNC | ||
| 815 | if( !type_engine_import_svar( env, "int", "MODE_ASYNC", | ||
| 816 | TRUE, (t_CKUINT)&Chuck_IO::MODE_ASYNC ) ) goto error; | ||
| 817 | |||
| 818 | // end the class import | ||
| 819 | type_engine_import_class_end( env ); | ||
| 820 | |||
| 821 | return TRUE; | ||
| 822 | |||
| 823 | error: | ||
| 824 | |||
| 825 | // end the class import | ||
| 826 | type_engine_import_class_end( env ); | ||
| 827 | |||
| 828 | return FALSE; | ||
| 829 | } | ||
| 830 | |||
| 831 | |||
| 832 | |||
| 833 | |||
| 834 | //----------------------------------------------------------------------------- | ||
| 835 | // name: init_class_fileio() | ||
| 836 | // desc: ... | ||
| 837 | //----------------------------------------------------------------------------- | ||
| 838 | t_CKBOOL init_class_fileio( Chuck_Env * env, Chuck_Type * type ) | ||
| 839 | { | ||
| 840 | // init as base class | ||
| 841 | Chuck_DL_Func * func = NULL; | ||
| 842 | |||
| 843 | // log | ||
| 844 | EM_log( CK_LOG_SEVERE, "class 'fileio'" ); | ||
| 845 | |||
| 846 | // init as base class | ||
| 847 | // TODO: ctor/dtor? | ||
| 848 | // TODO: replace dummy with pure function | ||
| 849 | if( !type_engine_import_class_begin( env, type, env->global(), fileio_ctor, fileio_dtor ) ) | ||
| 850 | return FALSE; | ||
| 851 | |||
| 852 | // add open(string) | ||
| 853 | func = make_new_mfun( "int", "open", fileio_open ); | ||
| 854 | func->add_arg( "string", "path" ); | ||
| 855 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 856 | |||
| 857 | // add open(string, flags) | ||
| 858 | func = make_new_mfun( "int", "open", fileio_openflags ); | ||
| 859 | func->add_arg( "string", "path" ); | ||
| 860 | func->add_arg( "int", "flags" ); | ||
| 861 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 862 | |||
| 863 | // add good() | ||
| 864 | func = make_new_mfun( "int", "good", fileio_good ); | ||
| 865 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 866 | |||
| 867 | // add close() | ||
| 868 | func = make_new_mfun( "void", "close", fileio_close ); | ||
| 869 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 870 | |||
| 871 | // add flush() | ||
| 872 | func = make_new_mfun( "void", "flush", fileio_flush ); | ||
| 873 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 874 | |||
| 875 | // add mode() | ||
| 876 | func = make_new_mfun( "int", "mode", fileio_getmode ); | ||
| 877 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 878 | |||
| 879 | // add mode(int) | ||
| 880 | func = make_new_mfun( "int", "mode", fileio_setmode ); | ||
| 881 | func->add_arg( "int", "flag" ); | ||
| 882 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 883 | |||
| 884 | // add size() | ||
| 885 | func = make_new_mfun( "int", "size", fileio_size ); | ||
| 886 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 887 | |||
| 888 | // add seek(int) | ||
| 889 | func = make_new_mfun( "void", "seek", fileio_seek ); | ||
| 890 | func->add_arg( "int", "pos" ); | ||
| 891 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 892 | |||
| 893 | // add tell() | ||
| 894 | func = make_new_mfun( "int", "tell", fileio_tell ); | ||
| 895 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 896 | |||
| 897 | // add isDir() | ||
| 898 | func = make_new_mfun( "int", "isDir", fileio_isdir ); | ||
| 899 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 900 | |||
| 901 | // add dirList() | ||
| 902 | func = make_new_mfun( "string[]", "dirList", fileio_dirlist ); | ||
| 903 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 904 | |||
| 905 | // add read() | ||
| 906 | // func = make_new_mfun( "string", "read", fileio_read ); | ||
| 907 | // func->add_arg( "int", "length" ); | ||
| 908 | // if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 909 | |||
| 910 | // add readLine() | ||
| 911 | func = make_new_mfun( "string", "readLine", fileio_readline ); | ||
| 912 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 913 | |||
| 914 | // add readInt() | ||
| 915 | // func = make_new_mfun( "int", "readInt", fileio_readint ); | ||
| 916 | // if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 917 | |||
| 918 | // add readInt(int) | ||
| 919 | func = make_new_mfun( "int", "readInt", fileio_readintflags ); | ||
| 920 | func->add_arg( "int", "flags" ); | ||
| 921 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 922 | |||
| 923 | // add readFloat() | ||
| 924 | // func = make_new_mfun( "float", "readFloat", fileio_readfloat ); | ||
| 925 | // if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 926 | |||
| 927 | // add eof() | ||
| 928 | func = make_new_mfun( "int", "eof", fileio_eof ); | ||
| 929 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 930 | |||
| 931 | // add more() | ||
| 932 | func = make_new_mfun( "int", "more", fileio_more ); | ||
| 933 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 934 | |||
| 935 | // add write(string) | ||
| 936 | func = make_new_mfun( "void", "write", fileio_writestring ); | ||
| 937 | func->add_arg( "string", "val" ); | ||
| 938 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 939 | |||
| 940 | // add write(int) | ||
| 941 | func = make_new_mfun( "void", "write", fileio_writeint ); | ||
| 942 | func->add_arg( "int", "val" ); | ||
| 943 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 944 | |||
| 945 | // add write(int,flags) | ||
| 946 | func = make_new_mfun( "void", "write", fileio_writeintflags ); | ||
| 947 | func->add_arg( "int", "val" ); | ||
| 948 | func->add_arg( "int", "flags" ); | ||
| 949 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 950 | |||
| 951 | // add write(float) | ||
| 952 | func = make_new_mfun( "void", "write", fileio_writefloat ); | ||
| 953 | func->add_arg( "float", "val" ); | ||
| 954 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 955 | |||
| 956 | // add FLAG_READ_WRITE | ||
| 957 | if( !type_engine_import_svar( env, "int", "READ_WRITE", | ||
| 958 | TRUE, (t_CKUINT)&Chuck_IO_File::FLAG_READ_WRITE ) ) goto error; | ||
| 959 | |||
| 960 | // add FLAG_READONLY | ||
| 961 | if( !type_engine_import_svar( env, "int", "READ", | ||
| 962 | TRUE, (t_CKUINT)&Chuck_IO_File::FLAG_READONLY ) ) goto error; | ||
| 963 | |||
| 964 | // add FLAG_WRITEONLY | ||
| 965 | if( !type_engine_import_svar( env, "int", "WRITE", | ||
| 966 | TRUE, (t_CKUINT)&Chuck_IO_File::FLAG_WRITEONLY ) ) goto error; | ||
| 967 | |||
| 968 | // add FLAG_APPEND | ||
| 969 | if( !type_engine_import_svar( env, "int", "APPEND", | ||
| 970 | TRUE, (t_CKUINT)&Chuck_IO_File::FLAG_APPEND ) ) goto error; | ||
| 971 | |||
| 972 | // add TYPE_ASCII | ||
| 973 | if( !type_engine_import_svar( env, "int", "ASCII", | ||
| 974 | TRUE, (t_CKUINT)&Chuck_IO_File::TYPE_ASCII ) ) goto error; | ||
| 975 | |||
| 976 | // add TYPE_BINARY | ||
| 977 | if( !type_engine_import_svar( env, "int", "BINARY", | ||
| 978 | TRUE, (t_CKUINT)&Chuck_IO_File::TYPE_BINARY ) ) goto error; | ||
| 979 | |||
| 980 | // end the class import | ||
| 981 | type_engine_import_class_end( env ); | ||
| 982 | |||
| 983 | return TRUE; | ||
| 984 | |||
| 985 | error: | ||
| 986 | |||
| 987 | // end the class import | ||
| 988 | type_engine_import_class_end( env ); | ||
| 989 | |||
| 990 | return FALSE; | ||
| 991 | } | ||
| 992 | |||
| 993 | |||
| 994 | |||
| 995 | |||
| 996 | //----------------------------------------------------------------------------- | ||
| 997 | // name: init_class_chout() | ||
| 998 | // desc: added 1.3.0.0 as full class | ||
| 999 | //----------------------------------------------------------------------------- | ||
| 1000 | t_CKBOOL init_class_chout( Chuck_Env * env, Chuck_Type * type ) | ||
| 1001 | { | ||
| 1002 | // init as base class | ||
| 1003 | Chuck_DL_Func * func = NULL; | ||
| 1004 | |||
| 1005 | // log | ||
| 1006 | EM_log( CK_LOG_SEVERE, "class 'chout'" ); | ||
| 1007 | |||
| 1008 | // TODO: ctor/dtor? | ||
| 1009 | if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL ) ) | ||
| 1010 | return FALSE; | ||
| 1011 | |||
| 1012 | // add good() | ||
| 1013 | func = make_new_mfun( "int", "good", chout_good ); | ||
| 1014 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1015 | |||
| 1016 | // add close() | ||
| 1017 | func = make_new_mfun( "void", "close", chout_close ); | ||
| 1018 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1019 | |||
| 1020 | // add flush() | ||
| 1021 | func = make_new_mfun( "void", "flush", chout_flush ); | ||
| 1022 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1023 | |||
| 1024 | // add mode() | ||
| 1025 | func = make_new_mfun( "int", "mode", chout_getmode ); | ||
| 1026 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1027 | |||
| 1028 | // add mode(int) | ||
| 1029 | func = make_new_mfun( "int", "mode", chout_setmode ); | ||
| 1030 | func->add_arg( "int", "flag" ); | ||
| 1031 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1032 | |||
| 1033 | // add readLine() | ||
| 1034 | func = make_new_mfun( "string", "readLine", chout_readline ); | ||
| 1035 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1036 | |||
| 1037 | // add readInt() | ||
| 1038 | // func = make_new_mfun( "int", "readInt", chout_readint ); | ||
| 1039 | // if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1040 | |||
| 1041 | // add readInt(int) | ||
| 1042 | func = make_new_mfun( "int", "readInt", chout_readintflags ); | ||
| 1043 | func->add_arg( "int", "flags" ); | ||
| 1044 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1045 | |||
| 1046 | // add readFloat() | ||
| 1047 | // func = make_new_mfun( "float", "readFloat", chout_readfloat ); | ||
| 1048 | // if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1049 | |||
| 1050 | // add eof() | ||
| 1051 | func = make_new_mfun( "int", "eof", chout_eof ); | ||
| 1052 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1053 | |||
| 1054 | // add more() | ||
| 1055 | func = make_new_mfun( "int", "more", chout_more ); | ||
| 1056 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1057 | |||
| 1058 | // add write(string) | ||
| 1059 | func = make_new_mfun( "void", "write", chout_writestring ); | ||
| 1060 | func->add_arg( "string", "val" ); | ||
| 1061 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1062 | |||
| 1063 | // add write(int) | ||
| 1064 | func = make_new_mfun( "void", "write", chout_writeint ); | ||
| 1065 | func->add_arg( "int", "val" ); | ||
| 1066 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1067 | |||
| 1068 | // add write(float) | ||
| 1069 | func = make_new_mfun( "void", "write", chout_writefloat ); | ||
| 1070 | func->add_arg( "float", "val" ); | ||
| 1071 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1072 | |||
| 1073 | // end the class import | ||
| 1074 | type_engine_import_class_end( env ); | ||
| 1075 | |||
| 1076 | return TRUE; | ||
| 1077 | |||
| 1078 | error: | ||
| 1079 | |||
| 1080 | // end the class import | ||
| 1081 | type_engine_import_class_end( env ); | ||
| 1082 | |||
| 1083 | return FALSE; | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | |||
| 1087 | |||
| 1088 | |||
| 1089 | //----------------------------------------------------------------------------- | ||
| 1090 | // name: init_class_cherr() | ||
| 1091 | // desc: added 1.3.0.0 -- as full class | ||
| 1092 | //----------------------------------------------------------------------------- | ||
| 1093 | t_CKBOOL init_class_cherr( Chuck_Env * env, Chuck_Type * type ) | ||
| 1094 | { | ||
| 1095 | // init as base class | ||
| 1096 | Chuck_DL_Func * func = NULL; | ||
| 1097 | |||
| 1098 | // log | ||
| 1099 | EM_log( CK_LOG_SEVERE, "class 'cherr'" ); | ||
| 1100 | |||
| 1101 | // TODO: ctor/dtor? | ||
| 1102 | if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL ) ) | ||
| 1103 | return FALSE; | ||
| 1104 | |||
| 1105 | // add good() | ||
| 1106 | func = make_new_mfun( "int", "good", cherr_good ); | ||
| 1107 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1108 | |||
| 1109 | // add close() | ||
| 1110 | func = make_new_mfun( "void", "close", cherr_close ); | ||
| 1111 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1112 | |||
| 1113 | // add flush() | ||
| 1114 | func = make_new_mfun( "void", "flush", cherr_flush ); | ||
| 1115 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1116 | |||
| 1117 | // add mode() | ||
| 1118 | func = make_new_mfun( "int", "mode", cherr_getmode ); | ||
| 1119 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1120 | |||
| 1121 | // add mode(int) | ||
| 1122 | func = make_new_mfun( "int", "mode", cherr_setmode ); | ||
| 1123 | func->add_arg( "int", "flag" ); | ||
| 1124 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1125 | |||
| 1126 | // add readLine() | ||
| 1127 | func = make_new_mfun( "string", "readLine", cherr_readline ); | ||
| 1128 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1129 | |||
| 1130 | // add readInt() | ||
| 1131 | // func = make_new_mfun( "int", "readInt", cherr_readint ); | ||
| 1132 | // if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1133 | |||
| 1134 | // add readInt(int) | ||
| 1135 | func = make_new_mfun( "int", "readInt", cherr_readintflags ); | ||
| 1136 | func->add_arg( "int", "flags" ); | ||
| 1137 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1138 | |||
| 1139 | // add readFloat() | ||
| 1140 | // func = make_new_mfun( "float", "readFloat", cherr_readfloat ); | ||
| 1141 | // if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1142 | |||
| 1143 | // add eof() | ||
| 1144 | func = make_new_mfun( "int", "eof", cherr_eof ); | ||
| 1145 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1146 | |||
| 1147 | // add more() | ||
| 1148 | func = make_new_mfun( "int", "more", cherr_more ); | ||
| 1149 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1150 | |||
| 1151 | // add write(string) | ||
| 1152 | func = make_new_mfun( "void", "write", cherr_writestring ); | ||
| 1153 | func->add_arg( "string", "val" ); | ||
| 1154 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1155 | |||
| 1156 | // add write(int) | ||
| 1157 | func = make_new_mfun( "void", "write", cherr_writeint ); | ||
| 1158 | func->add_arg( "int", "val" ); | ||
| 1159 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1160 | |||
| 1161 | // add write(float) | ||
| 1162 | func = make_new_mfun( "void", "write", cherr_writefloat ); | ||
| 1163 | func->add_arg( "float", "val" ); | ||
| 1164 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1165 | |||
| 1166 | // end the class import | ||
| 1167 | type_engine_import_class_end( env ); | ||
| 1168 | |||
| 1169 | return TRUE; | ||
| 1170 | |||
| 1171 | error: | ||
| 1172 | |||
| 1173 | // end the class import | ||
| 1174 | type_engine_import_class_end( env ); | ||
| 1175 | |||
| 1176 | return FALSE; | ||
| 1177 | } | ||
| 1178 | |||
| 1179 | |||
| 1180 | //----------------------------------------------------------------------------- | ||
| 1181 | // name: init_class_string() | ||
| 1182 | // desc: ... | ||
| 1183 | //----------------------------------------------------------------------------- | ||
| 1184 | t_CKBOOL init_class_string( Chuck_Env * env, Chuck_Type * type ) | ||
| 1185 | { | ||
| 1186 | // init as base class | ||
| 1187 | Chuck_DL_Func * func = NULL; | ||
| 1188 | |||
| 1189 | // log | ||
| 1190 | EM_log( CK_LOG_SEVERE, "class 'string'" ); | ||
| 1191 | |||
| 1192 | const char * doc = "The string class holds textual data as a sequence of characters, and provides a number of functions for manipulating text."; | ||
| 1193 | |||
| 1194 | // init as base class | ||
| 1195 | // TODO: ctor/dtor | ||
| 1196 | if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL, doc ) ) | ||
| 1197 | return FALSE; | ||
| 1198 | |||
| 1199 | // add length() | ||
| 1200 | func = make_new_mfun( "int", "length", string_length ); | ||
| 1201 | func->doc = "Return the number of characters of the string."; | ||
| 1202 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1203 | |||
| 1204 | // add upper() | ||
| 1205 | func = make_new_mfun( "string", "upper", string_upper ); | ||
| 1206 | func->doc = "Return a new string in which the lowercase characters of the original string have been converted to uppercase."; | ||
| 1207 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1208 | |||
| 1209 | // add lower() | ||
| 1210 | func = make_new_mfun( "string", "lower", string_lower ); | ||
| 1211 | func->doc = "Return a new string in which the uppercase characters of the original string have been converted to lowercase."; | ||
| 1212 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1213 | |||
| 1214 | // add ltrim() | ||
| 1215 | func = make_new_mfun( "string", "ltrim", string_ltrim ); | ||
| 1216 | func->doc = "Return a new string in which leading whitespace has been removed."; | ||
| 1217 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1218 | |||
| 1219 | // add rtrim() | ||
| 1220 | func = make_new_mfun( "string", "rtrim", string_rtrim ); | ||
| 1221 | func->doc = "Return a new string in which trailing whitespace has been removed."; | ||
| 1222 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1223 | |||
| 1224 | // add trim() | ||
| 1225 | func = make_new_mfun( "string", "trim", string_trim ); | ||
| 1226 | func->doc = "Return a new string in which leading and trailing whitespace has been removed."; | ||
| 1227 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1228 | |||
| 1229 | // add toString() | ||
| 1230 | func = make_new_mfun( "string", "toString", string_toString ); | ||
| 1231 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1232 | |||
| 1233 | // add charAt() | ||
| 1234 | func = make_new_mfun( "int", "charAt", string_charAt ); | ||
| 1235 | func->add_arg("int", "index"); | ||
| 1236 | func->doc = "Return a character at the specified index."; | ||
| 1237 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1238 | |||
| 1239 | // add setCharAt() | ||
| 1240 | func = make_new_mfun( "int", "setCharAt", string_setCharAt ); | ||
| 1241 | func->add_arg("int", "index"); | ||
| 1242 | func->add_arg("int", "theChar"); | ||
| 1243 | func->doc = "Set the character at the specified index."; | ||
| 1244 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1245 | |||
| 1246 | // add substring() | ||
| 1247 | func = make_new_mfun( "string", "substring", string_substring ); | ||
| 1248 | func->add_arg("int", "start"); | ||
| 1249 | func->doc = "Return a new string containing the substring from the start index to the end of the string."; | ||
| 1250 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1251 | |||
| 1252 | // add substring() | ||
| 1253 | func = make_new_mfun( "string", "substring", string_substringN ); | ||
| 1254 | func->add_arg("int", "start"); | ||
| 1255 | func->add_arg("int", "length"); | ||
| 1256 | func->doc = "Return a new string containing the substring from the start index of the specified length."; | ||
| 1257 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1258 | |||
| 1259 | // add insert() | ||
| 1260 | func = make_new_mfun( "void", "insert", string_insert ); | ||
| 1261 | func->add_arg("int", "position"); | ||
| 1262 | func->add_arg("string", "str"); | ||
| 1263 | func->doc = "Insert str at the specified position."; | ||
| 1264 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1265 | |||
| 1266 | // add replace() | ||
| 1267 | func = make_new_mfun( "void", "replace", string_replace ); | ||
| 1268 | func->add_arg( "int", "position" ); | ||
| 1269 | func->add_arg( "string", "str" ); | ||
| 1270 | func->doc = "Replace characters from the start position to the end of the string with str."; | ||
| 1271 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1272 | |||
| 1273 | // add replace() | ||
| 1274 | func = make_new_mfun( "void", "replace", string_replaceN ); | ||
| 1275 | func->add_arg( "int", "position" ); | ||
| 1276 | func->add_arg( "int", "length" ); | ||
| 1277 | func->add_arg( "string", "str" ); | ||
| 1278 | func->doc = "Replace length characters from the start position with str."; | ||
| 1279 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1280 | |||
| 1281 | // add find() | ||
| 1282 | func = make_new_mfun( "int", "find", string_find ); | ||
| 1283 | func->add_arg( "int", "theChar" ); | ||
| 1284 | func->doc = "Return the index of the first occurence of theChar, or -1 if theChar is not found."; | ||
| 1285 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1286 | |||
| 1287 | // add find() | ||
| 1288 | func = make_new_mfun( "int", "find", string_findStart ); | ||
| 1289 | func->add_arg( "int", "theChar" ); | ||
| 1290 | func->add_arg( "int", "start" ); | ||
| 1291 | func->doc = "Return the index of the first occurence of theChar at or after the start position, or -1 if theChar is not found."; | ||
| 1292 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1293 | |||
| 1294 | // add find() | ||
| 1295 | func = make_new_mfun( "int", "find", string_findStr ); | ||
| 1296 | func->add_arg( "string", "str" ); | ||
| 1297 | func->doc = "Return the index of the first occurence of str, or -1 if str is not found."; | ||
| 1298 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1299 | |||
| 1300 | // add find() | ||
| 1301 | func = make_new_mfun( "int", "find", string_findStrStart ); | ||
| 1302 | func->add_arg( "string", "str" ); | ||
| 1303 | func->add_arg( "int", "start" ); | ||
| 1304 | func->doc = "Return the index of the first occurence of str at or after the start position, or -1 if str is not found."; | ||
| 1305 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1306 | |||
| 1307 | // add rfind() | ||
| 1308 | func = make_new_mfun( "int", "rfind", string_rfind ); | ||
| 1309 | func->add_arg( "int", "theChar" ); | ||
| 1310 | func->doc = "Return the index of the last occurence of theChar, or -1 if theChar is not found."; | ||
| 1311 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1312 | |||
| 1313 | // add rfind() | ||
| 1314 | func = make_new_mfun( "int", "rfind", string_rfindStart ); | ||
| 1315 | func->add_arg( "int", "theChar" ); | ||
| 1316 | func->add_arg( "int", "start" ); | ||
| 1317 | func->doc = "Return the index of the last occurence of theChar at or before the start position, or -1 if theChar is not found."; | ||
| 1318 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1319 | |||
| 1320 | // add rfind() | ||
| 1321 | func = make_new_mfun( "int", "rfind", string_rfindStr ); | ||
| 1322 | func->add_arg( "string", "str" ); | ||
| 1323 | func->doc = "Return the index of the last occurence of str, or -1 if str is not found."; | ||
| 1324 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1325 | |||
| 1326 | // add rfind() | ||
| 1327 | func = make_new_mfun( "int", "rfind", string_rfindStrStart ); | ||
| 1328 | func->add_arg( "string", "str" ); | ||
| 1329 | func->add_arg( "int", "start" ); | ||
| 1330 | func->doc = "Return the index of the last occurence of str at or before the start position, or -1 if str is not found."; | ||
| 1331 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1332 | |||
| 1333 | // add erase() | ||
| 1334 | func = make_new_mfun( "void", "erase", string_erase ); | ||
| 1335 | func->add_arg( "int", "start" ); | ||
| 1336 | func->add_arg( "int", "length" ); | ||
| 1337 | func->doc = "Erase length characters of the string from start position."; | ||
| 1338 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1339 | |||
| 1340 | // add toInt() | ||
| 1341 | func = make_new_mfun( "int", "toInt", string_toInt ); | ||
| 1342 | func->doc = "Attempt to convert the contents of the string to an integer and return the result, or 0 if conversion failed."; | ||
| 1343 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1344 | |||
| 1345 | // add toFloat() | ||
| 1346 | func = make_new_mfun( "float", "toFloat", string_toFloat ); | ||
| 1347 | func->doc = "Attempt to convert the contents of the string to an float and return the result, or 0 if conversion failed."; | ||
| 1348 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1349 | |||
| 1350 | // add parent() | ||
| 1351 | // disable for now | ||
| 1352 | // func = make_new_mfun( "string", "parent", string_parent ); | ||
| 1353 | // if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1354 | |||
| 1355 | // // add toTime() | ||
| 1356 | // func = make_new_mfun( "float", "toTime", string_toFloat ); | ||
| 1357 | // if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1358 | // | ||
| 1359 | // // add toDur() | ||
| 1360 | // func = make_new_mfun( "float", "toDur", string_toFloat ); | ||
| 1361 | // if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1362 | |||
| 1363 | /* // add at() | ||
| 1364 | func = make_new_mfun( "int", "ch", string_set_at ); | ||
| 1365 | func->add_arg( "int", "index" ); | ||
| 1366 | func->add_arg( "int", "val" ); | ||
| 1367 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1368 | func = make_new_mfun( "int", "ch", string_get_at ); | ||
| 1369 | func->add_arg( "int", "index" ); | ||
| 1370 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1371 | */ | ||
| 1372 | // end the class import | ||
| 1373 | type_engine_import_class_end( env ); | ||
| 1374 | |||
| 1375 | return TRUE; | ||
| 1376 | |||
| 1377 | error: | ||
| 1378 | |||
| 1379 | // end the class import | ||
| 1380 | type_engine_import_class_end( env ); | ||
| 1381 | |||
| 1382 | return FALSE; | ||
| 1383 | } | ||
| 1384 | |||
| 1385 | |||
| 1386 | |||
| 1387 | |||
| 1388 | //----------------------------------------------------------------------------- | ||
| 1389 | // name: init_class_array() | ||
| 1390 | // desc: ... | ||
| 1391 | //----------------------------------------------------------------------------- | ||
| 1392 | t_CKBOOL init_class_array( Chuck_Env * env, Chuck_Type * type ) | ||
| 1393 | { | ||
| 1394 | // init as base class | ||
| 1395 | Chuck_DL_Func * func = NULL; | ||
| 1396 | |||
| 1397 | // log | ||
| 1398 | EM_log( CK_LOG_SEVERE, "class 'array'" ); | ||
| 1399 | |||
| 1400 | // init as base class | ||
| 1401 | // TODO: ctor/dtor? | ||
| 1402 | const char *doc = "The array class is used to store linear sequences of data, also providing capabilities for stack and map data structures."; | ||
| 1403 | if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL, doc ) ) | ||
| 1404 | return FALSE; | ||
| 1405 | |||
| 1406 | // add clear() | ||
| 1407 | func = make_new_mfun( "void", "clear", array_clear ); | ||
| 1408 | func->doc = "Clear the contents of the array."; | ||
| 1409 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1410 | |||
| 1411 | // add reset() | ||
| 1412 | func = make_new_mfun( "void", "reset", array_reset ); | ||
| 1413 | func->doc = "Reset array to original state; clears the array and sets capacity to 8."; | ||
| 1414 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1415 | |||
| 1416 | // add popBack() | ||
| 1417 | func = make_new_mfun( "void", "popBack", array_pop_back ); | ||
| 1418 | func->doc = "Remove the last item of the array"; | ||
| 1419 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1420 | |||
| 1421 | // add size() | ||
| 1422 | func = make_new_mfun( "int", "size", array_get_size ); | ||
| 1423 | func->doc = "Return the number of elements in the array."; | ||
| 1424 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1425 | // add size() | ||
| 1426 | func = make_new_mfun( "int", "size", array_set_size ); | ||
| 1427 | func->add_arg( "int", "newSize" ); | ||
| 1428 | func->doc = "Set the size of the array. If the new size is less than the current size, elements will be deleted from the end; if the new size is larger than the current size, 0 or null elements will be added to the end."; | ||
| 1429 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1430 | |||
| 1431 | // add cap() | ||
| 1432 | func = make_new_mfun( "int", "cap", array_get_capacity_hack ); | ||
| 1433 | func->doc = "Return current capacity of the array (number of elements that can be held without reallocating internal buffer). "; | ||
| 1434 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1435 | |||
| 1436 | // add capacity() | ||
| 1437 | // func = make_new_mfun( "int", "capacity", array_get_capacity ); | ||
| 1438 | // if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1439 | // func = make_new_mfun( "int", "capacity", array_set_capacity ); | ||
| 1440 | // func->add_arg( "int", "val" ); | ||
| 1441 | // if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1442 | |||
| 1443 | // add find() | ||
| 1444 | func = make_new_mfun( "int", "find", array_find ); | ||
| 1445 | func->add_arg( "string", "key" ); | ||
| 1446 | func->doc = "Return number of elements with the specified key. "; | ||
| 1447 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1448 | |||
| 1449 | // add erase() | ||
| 1450 | func = make_new_mfun( "int", "erase", array_erase ); | ||
| 1451 | func->add_arg( "string", "key" ); | ||
| 1452 | func->doc = "Erase all elements with the specified key. "; | ||
| 1453 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1454 | |||
| 1455 | // add examples | ||
| 1456 | if( !type_engine_import_add_ex( env, "array/array_argument.ck" ) ) goto error; | ||
| 1457 | if( !type_engine_import_add_ex( env, "array/array_assign.ck" ) ) goto error; | ||
| 1458 | if( !type_engine_import_add_ex( env, "array/array_dynamic.ck" ) ) goto error; | ||
| 1459 | if( !type_engine_import_add_ex( env, "array/array_mdim.ck" ) ) goto error; | ||
| 1460 | if( !type_engine_import_add_ex( env, "array/array_mmixed.ck" ) ) goto error; | ||
| 1461 | if( !type_engine_import_add_ex( env, "array/array_resize.ck" ) ) goto error; | ||
| 1462 | if( !type_engine_import_add_ex( env, "array/array_storage.ck" ) ) goto error; | ||
| 1463 | if( !type_engine_import_add_ex( env, "array/array_sub_assign.ck" ) ) goto error; | ||
| 1464 | |||
| 1465 | type_engine_import_class_end( env ); | ||
| 1466 | |||
| 1467 | return TRUE; | ||
| 1468 | |||
| 1469 | error: | ||
| 1470 | |||
| 1471 | // end the class import | ||
| 1472 | type_engine_import_class_end( env ); | ||
| 1473 | |||
| 1474 | return FALSE; | ||
| 1475 | } | ||
| 1476 | |||
| 1477 | |||
| 1478 | |||
| 1479 | // static | ||
| 1480 | static t_CKUINT MidiIn_offset_data = 0; | ||
| 1481 | t_CKUINT MidiMsg_offset_data1 = 0; | ||
| 1482 | t_CKUINT MidiMsg_offset_data2 = 0; | ||
| 1483 | t_CKUINT MidiMsg_offset_data3 = 0; | ||
| 1484 | t_CKUINT MidiMsg_offset_when = 0; | ||
| 1485 | static t_CKUINT MidiOut_offset_data = 0; | ||
| 1486 | |||
| 1487 | //----------------------------------------------------------------------------- | ||
| 1488 | // name: init_class_Midi() | ||
| 1489 | // desc: ... | ||
| 1490 | //----------------------------------------------------------------------------- | ||
| 1491 | t_CKBOOL init_class_Midi( Chuck_Env * env ) | ||
| 1492 | { | ||
| 1493 | Chuck_DL_Func * func = NULL; | ||
| 1494 | |||
| 1495 | // init base class | ||
| 1496 | // TODO: ctor/dtor? | ||
| 1497 | if( !type_engine_import_class_begin( env, "MidiMsg", "Object", | ||
| 1498 | env->global(), NULL, NULL ) ) | ||
| 1499 | return FALSE; | ||
| 1500 | |||
| 1501 | // add member variable | ||
| 1502 | MidiMsg_offset_data1 = type_engine_import_mvar( env, "int", "data1", FALSE ); | ||
| 1503 | if( MidiMsg_offset_data1 == CK_INVALID_OFFSET ) goto error; | ||
| 1504 | |||
| 1505 | // add member variable | ||
| 1506 | MidiMsg_offset_data2 = type_engine_import_mvar( env, "int", "data2", FALSE ); | ||
| 1507 | if( MidiMsg_offset_data2 == CK_INVALID_OFFSET ) goto error; | ||
| 1508 | |||
| 1509 | // add member variable | ||
| 1510 | MidiMsg_offset_data3 = type_engine_import_mvar( env, "int", "data3", FALSE ); | ||
| 1511 | if( MidiMsg_offset_data3 == CK_INVALID_OFFSET ) goto error; | ||
| 1512 | |||
| 1513 | // add member variable | ||
| 1514 | MidiMsg_offset_when = type_engine_import_mvar( env, "dur", "when", FALSE ); | ||
| 1515 | if( MidiMsg_offset_when == CK_INVALID_OFFSET ) goto error; | ||
| 1516 | |||
| 1517 | // end the class import | ||
| 1518 | type_engine_import_class_end( env ); | ||
| 1519 | |||
| 1520 | #ifndef __DISABLE_MIDI__ | ||
| 1521 | // init base class | ||
| 1522 | if( !type_engine_import_class_begin( env, "MidiIn", "Event", | ||
| 1523 | env->global(), MidiIn_ctor, MidiIn_dtor ) ) | ||
| 1524 | return FALSE; | ||
| 1525 | |||
| 1526 | // add open() | ||
| 1527 | func = make_new_mfun( "int", "open", MidiIn_open ); | ||
| 1528 | func->add_arg( "int", "port" ); | ||
| 1529 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1530 | |||
| 1531 | // add open() (added 1.3.0.0) | ||
| 1532 | func = make_new_mfun( "int", "open", MidiIn_open_named ); | ||
| 1533 | func->add_arg( "string", "name" ); | ||
| 1534 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1535 | |||
| 1536 | // add good() | ||
| 1537 | func = make_new_mfun( "int", "good", MidiIn_good ); | ||
| 1538 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1539 | |||
| 1540 | // add num() | ||
| 1541 | func = make_new_mfun( "int", "num", MidiIn_num ); | ||
| 1542 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1543 | |||
| 1544 | // add name() | ||
| 1545 | func = make_new_mfun( "string", "name", MidiIn_name ); | ||
| 1546 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1547 | |||
| 1548 | // add printerr() | ||
| 1549 | func = make_new_mfun( "void", "printerr", MidiIn_printerr ); | ||
| 1550 | func->add_arg( "int", "print_or_not" ); | ||
| 1551 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1552 | |||
| 1553 | // add recv() | ||
| 1554 | func = make_new_mfun( "int", "recv", MidiIn_recv ); | ||
| 1555 | func->add_arg( "MidiMsg", "msg" ); | ||
| 1556 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1557 | |||
| 1558 | // add can_wait() | ||
| 1559 | func = make_new_mfun( "int", "can_wait", MidiIn_can_wait ); | ||
| 1560 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1561 | |||
| 1562 | // add member variable | ||
| 1563 | MidiIn_offset_data = type_engine_import_mvar( env, "int", "@MidiIn_data", FALSE ); | ||
| 1564 | if( MidiIn_offset_data == CK_INVALID_OFFSET ) goto error; | ||
| 1565 | |||
| 1566 | // end the class import | ||
| 1567 | type_engine_import_class_end( env ); | ||
| 1568 | |||
| 1569 | // init base class | ||
| 1570 | if( !type_engine_import_class_begin( env, "MidiOut", "Object", | ||
| 1571 | env->global(), MidiOut_ctor, MidiOut_dtor ) ) | ||
| 1572 | return FALSE; | ||
| 1573 | |||
| 1574 | // add open() | ||
| 1575 | func = make_new_mfun( "int", "open", MidiOut_open ); | ||
| 1576 | func->add_arg( "int", "port" ); | ||
| 1577 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1578 | |||
| 1579 | // add open() (added 1.3.0.0) | ||
| 1580 | func = make_new_mfun( "int", "open", MidiOut_open_named ); | ||
| 1581 | func->add_arg( "string", "name" ); | ||
| 1582 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1583 | |||
| 1584 | // add good() | ||
| 1585 | func = make_new_mfun( "int", "good", MidiOut_good ); | ||
| 1586 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1587 | |||
| 1588 | // add num() | ||
| 1589 | func = make_new_mfun( "int", "num", MidiOut_num ); | ||
| 1590 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1591 | |||
| 1592 | // add name() | ||
| 1593 | func = make_new_mfun( "string", "name", MidiOut_name ); | ||
| 1594 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1595 | |||
| 1596 | // add printerr() | ||
| 1597 | func = make_new_mfun( "void", "printerr", MidiOut_printerr ); | ||
| 1598 | func->add_arg( "int", "print_or_not" ); | ||
| 1599 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1600 | |||
| 1601 | // add send() | ||
| 1602 | func = make_new_mfun( "int", "send", MidiOut_send ); | ||
| 1603 | func->add_arg( "MidiMsg", "msg" ); | ||
| 1604 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1605 | |||
| 1606 | // add member variable | ||
| 1607 | MidiOut_offset_data = type_engine_import_mvar( env, "int", "@MidiOut_data", FALSE ); | ||
| 1608 | if( MidiOut_offset_data == CK_INVALID_OFFSET ) goto error; | ||
| 1609 | |||
| 1610 | // end the class import | ||
| 1611 | type_engine_import_class_end( env ); | ||
| 1612 | |||
| 1613 | #endif // __DISABLE_MIDI__ | ||
| 1614 | |||
| 1615 | return TRUE; | ||
| 1616 | |||
| 1617 | error: | ||
| 1618 | |||
| 1619 | // end the class import | ||
| 1620 | type_engine_import_class_end( env ); | ||
| 1621 | |||
| 1622 | return FALSE; | ||
| 1623 | } | ||
| 1624 | |||
| 1625 | |||
| 1626 | |||
| 1627 | |||
| 1628 | // static | ||
| 1629 | static t_CKUINT HidIn_offset_data = 0; | ||
| 1630 | |||
| 1631 | static t_CKUINT HidMsg_offset_device_type = 0; | ||
| 1632 | static t_CKUINT HidMsg_offset_device_num = 0; | ||
| 1633 | static t_CKUINT HidMsg_offset_type = 0; | ||
| 1634 | static t_CKUINT HidMsg_offset_which = 0; | ||
| 1635 | static t_CKUINT HidMsg_offset_idata = 0; | ||
| 1636 | static t_CKUINT HidMsg_offset_fdata = 0; | ||
| 1637 | static t_CKUINT HidMsg_offset_when = 0; | ||
| 1638 | static t_CKUINT HidMsg_offset_deltax = 0; | ||
| 1639 | static t_CKUINT HidMsg_offset_deltay = 0; | ||
| 1640 | static t_CKUINT HidMsg_offset_axis_position = 0; // deprecated | ||
| 1641 | static t_CKUINT HidMsg_offset_axis_position2 = 0; | ||
| 1642 | static t_CKUINT HidMsg_offset_scaled_axis_position = 0; // deprecated | ||
| 1643 | static t_CKUINT HidMsg_offset_hat_position = 0; | ||
| 1644 | static t_CKUINT HidMsg_offset_cursorx = 0; | ||
| 1645 | static t_CKUINT HidMsg_offset_cursory = 0; | ||
| 1646 | static t_CKUINT HidMsg_offset_scaledcursorx = 0; | ||
| 1647 | static t_CKUINT HidMsg_offset_scaledcursory = 0; | ||
| 1648 | static t_CKUINT HidMsg_offset_x = 0; | ||
| 1649 | static t_CKUINT HidMsg_offset_y = 0; | ||
| 1650 | static t_CKUINT HidMsg_offset_z = 0; | ||
| 1651 | static t_CKUINT HidMsg_offset_touchx = 0; // added 1.3.0.0 | ||
| 1652 | static t_CKUINT HidMsg_offset_touchy = 0; // added 1.3.0.0 | ||
| 1653 | static t_CKUINT HidMsg_offset_touchsize = 0; // added 1.3.0.0 | ||
| 1654 | static t_CKUINT HidMsg_offset_ascii = 0; | ||
| 1655 | static t_CKUINT HidMsg_offset_key = 0; | ||
| 1656 | |||
| 1657 | static t_CKUINT HidOut_offset_data = 0; | ||
| 1658 | |||
| 1659 | //----------------------------------------------------------------------------- | ||
| 1660 | // name: init_class_HID() | ||
| 1661 | // desc: ... | ||
| 1662 | //----------------------------------------------------------------------------- | ||
| 1663 | t_CKBOOL init_class_HID( Chuck_Env * env ) | ||
| 1664 | { | ||
| 1665 | Chuck_DL_Func * func = NULL; | ||
| 1666 | |||
| 1667 | // init base class | ||
| 1668 | if( !type_engine_import_class_begin( env, "HidMsg", "Object", | ||
| 1669 | env->global(), NULL, NULL ) ) | ||
| 1670 | return FALSE; | ||
| 1671 | |||
| 1672 | // add member variable | ||
| 1673 | HidMsg_offset_device_type = type_engine_import_mvar( env, "int", "deviceType", FALSE ); | ||
| 1674 | if( HidMsg_offset_device_type == CK_INVALID_OFFSET ) goto error; | ||
| 1675 | |||
| 1676 | // add member variable | ||
| 1677 | HidMsg_offset_device_num = type_engine_import_mvar( env, "int", "deviceNum", FALSE ); | ||
| 1678 | if( HidMsg_offset_device_num == CK_INVALID_OFFSET ) goto error; | ||
| 1679 | |||
| 1680 | // add member variable | ||
| 1681 | HidMsg_offset_type = type_engine_import_mvar( env, "int", "type", FALSE ); | ||
| 1682 | if( HidMsg_offset_type == CK_INVALID_OFFSET ) goto error; | ||
| 1683 | |||
| 1684 | // add member variable | ||
| 1685 | HidMsg_offset_which = type_engine_import_mvar( env, "int", "which", FALSE ); | ||
| 1686 | if( HidMsg_offset_which == CK_INVALID_OFFSET ) goto error; | ||
| 1687 | |||
| 1688 | // add member variable | ||
| 1689 | HidMsg_offset_idata = type_engine_import_mvar( env, "int", "idata", FALSE ); | ||
| 1690 | if( HidMsg_offset_idata == CK_INVALID_OFFSET ) goto error; | ||
| 1691 | |||
| 1692 | // add member variable | ||
| 1693 | HidMsg_offset_fdata = type_engine_import_mvar( env, "float", "fdata", FALSE ); | ||
| 1694 | if( HidMsg_offset_fdata == CK_INVALID_OFFSET ) goto error; | ||
| 1695 | |||
| 1696 | // add member variable | ||
| 1697 | HidMsg_offset_when = type_engine_import_mvar( env, "time", "when", FALSE ); | ||
| 1698 | if( HidMsg_offset_when == CK_INVALID_OFFSET ) goto error; | ||
| 1699 | |||
| 1700 | // add member variable | ||
| 1701 | HidMsg_offset_deltax = type_engine_import_mvar( env, "int", "deltaX", FALSE ); | ||
| 1702 | if( HidMsg_offset_deltax == CK_INVALID_OFFSET ) goto error; | ||
| 1703 | |||
| 1704 | // add member variable | ||
| 1705 | HidMsg_offset_deltay = type_engine_import_mvar( env, "int", "deltaY", FALSE ); | ||
| 1706 | if( HidMsg_offset_deltay == CK_INVALID_OFFSET ) goto error; | ||
| 1707 | |||
| 1708 | // add member variable | ||
| 1709 | HidMsg_offset_cursorx = type_engine_import_mvar( env, "int", "cursorX", FALSE ); | ||
| 1710 | if( HidMsg_offset_cursorx == CK_INVALID_OFFSET ) goto error; | ||
| 1711 | |||
| 1712 | // add member variable | ||
| 1713 | HidMsg_offset_cursory = type_engine_import_mvar( env, "int", "cursorY", FALSE ); | ||
| 1714 | if( HidMsg_offset_cursory == CK_INVALID_OFFSET ) goto error; | ||
| 1715 | |||
| 1716 | // add member variable | ||
| 1717 | HidMsg_offset_scaledcursorx = type_engine_import_mvar( env, "float", "scaledCursorX", FALSE ); | ||
| 1718 | if( HidMsg_offset_scaledcursorx == CK_INVALID_OFFSET ) goto error; | ||
| 1719 | |||
| 1720 | // add member variable | ||
| 1721 | HidMsg_offset_scaledcursory = type_engine_import_mvar( env, "float", "scaledCursorY", FALSE ); | ||
| 1722 | if( HidMsg_offset_scaledcursory == CK_INVALID_OFFSET ) goto error; | ||
| 1723 | |||
| 1724 | // add member variable | ||
| 1725 | HidMsg_offset_x = type_engine_import_mvar( env, "int", "x", FALSE ); | ||
| 1726 | if( HidMsg_offset_x == CK_INVALID_OFFSET ) goto error; | ||
| 1727 | |||
| 1728 | // add member variable | ||
| 1729 | HidMsg_offset_y = type_engine_import_mvar( env, "int", "y", FALSE ); | ||
| 1730 | if( HidMsg_offset_y == CK_INVALID_OFFSET ) goto error; | ||
| 1731 | |||
| 1732 | // add member variable | ||
| 1733 | HidMsg_offset_z = type_engine_import_mvar( env, "int", "z", FALSE ); | ||
| 1734 | if( HidMsg_offset_z == CK_INVALID_OFFSET ) goto error; | ||
| 1735 | |||
| 1736 | // add member variable (added 1.3.0.0) | ||
| 1737 | HidMsg_offset_touchx = type_engine_import_mvar( env, "float", "touchX", FALSE ); | ||
| 1738 | if( HidMsg_offset_touchx == CK_INVALID_OFFSET ) goto error; | ||
| 1739 | |||
| 1740 | // add member variable (added 1.3.0.0) | ||
| 1741 | HidMsg_offset_touchy = type_engine_import_mvar( env, "float", "touchY", FALSE ); | ||
| 1742 | if( HidMsg_offset_touchy == CK_INVALID_OFFSET ) goto error; | ||
| 1743 | |||
| 1744 | // add member variable (added 1.3.0.0) | ||
| 1745 | HidMsg_offset_touchsize = type_engine_import_mvar( env, "float", "touchSize", FALSE ); | ||
| 1746 | if( HidMsg_offset_touchsize == CK_INVALID_OFFSET ) goto error; | ||
| 1747 | |||
| 1748 | // add member variable | ||
| 1749 | HidMsg_offset_axis_position = type_engine_import_mvar( env, "int", "axis_position", FALSE ); | ||
| 1750 | if( HidMsg_offset_axis_position == CK_INVALID_OFFSET ) goto error; | ||
| 1751 | |||
| 1752 | // add member variable | ||
| 1753 | HidMsg_offset_axis_position2 = type_engine_import_mvar( env, "float", "axisPosition", FALSE ); | ||
| 1754 | if( HidMsg_offset_axis_position2 == CK_INVALID_OFFSET ) goto error; | ||
| 1755 | |||
| 1756 | // add member variable | ||
| 1757 | HidMsg_offset_hat_position = type_engine_import_mvar( env, "int", "hatPosition", FALSE ); | ||
| 1758 | if( HidMsg_offset_hat_position == CK_INVALID_OFFSET ) goto error; | ||
| 1759 | |||
| 1760 | // add member variable | ||
| 1761 | HidMsg_offset_ascii = type_engine_import_mvar( env, "int", "ascii", FALSE ); | ||
| 1762 | if( HidMsg_offset_ascii == CK_INVALID_OFFSET ) goto error; | ||
| 1763 | |||
| 1764 | // add member variable | ||
| 1765 | HidMsg_offset_key = type_engine_import_mvar( env, "int", "key", FALSE ); | ||
| 1766 | if( HidMsg_offset_key == CK_INVALID_OFFSET ) goto error; | ||
| 1767 | |||
| 1768 | // add member variable | ||
| 1769 | HidMsg_offset_scaled_axis_position = type_engine_import_mvar( env, "float", "scaled_axis_position", FALSE ); | ||
| 1770 | if( HidMsg_offset_scaled_axis_position == CK_INVALID_OFFSET ) goto error; | ||
| 1771 | |||
| 1772 | // add is_axis_motion() | ||
| 1773 | func = make_new_mfun( "int", "is_axis_motion", HidMsg_is_axis_motion ); // deprecated | ||
| 1774 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1775 | |||
| 1776 | // add isAxisMotion() | ||
| 1777 | func = make_new_mfun( "int", "isAxisMotion", HidMsg_is_axis_motion ); | ||
| 1778 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1779 | |||
| 1780 | // add is_button_down() | ||
| 1781 | func = make_new_mfun( "int", "is_button_down", HidMsg_is_button_down ); // deprecated | ||
| 1782 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1783 | |||
| 1784 | // add isButtonDown() | ||
| 1785 | func = make_new_mfun( "int", "isButtonDown", HidMsg_is_button_down ); | ||
| 1786 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1787 | |||
| 1788 | // add is_button_up() | ||
| 1789 | func = make_new_mfun( "int", "is_button_up", HidMsg_is_button_up ); // deprecated | ||
| 1790 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1791 | |||
| 1792 | // add isButtonUp() | ||
| 1793 | func = make_new_mfun( "int", "isButtonUp", HidMsg_is_button_up ); | ||
| 1794 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1795 | |||
| 1796 | // add is_mouse_motion() | ||
| 1797 | func = make_new_mfun( "int", "is_mouse_motion", HidMsg_is_mouse_motion ); // deprecated | ||
| 1798 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1799 | |||
| 1800 | // add isMouseMotion() | ||
| 1801 | func = make_new_mfun( "int", "isMouseMotion", HidMsg_is_mouse_motion ); | ||
| 1802 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1803 | |||
| 1804 | // add is_hat_motion() | ||
| 1805 | func = make_new_mfun( "int", "is_hat_motion", HidMsg_is_hat_motion ); // deprecated | ||
| 1806 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1807 | |||
| 1808 | // add isHatMotion() | ||
| 1809 | func = make_new_mfun( "int", "isHatMotion", HidMsg_is_hat_motion ); | ||
| 1810 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1811 | |||
| 1812 | // add isWheelMotion() | ||
| 1813 | func = make_new_mfun( "int", "isWheelMotion", HidMsg_is_wheel_motion ); | ||
| 1814 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1815 | |||
| 1816 | // end the class import | ||
| 1817 | type_engine_import_class_end( env ); | ||
| 1818 | |||
| 1819 | |||
| 1820 | // register deprecate | ||
| 1821 | type_engine_register_deprecate( env, "HidIn", "Hid" ); | ||
| 1822 | |||
| 1823 | // init base class Hid (copy of HidIn + constants) | ||
| 1824 | if( !type_engine_import_class_begin( env, "Hid", "Event", | ||
| 1825 | env->global(), HidIn_ctor, HidIn_dtor ) ) | ||
| 1826 | return FALSE; | ||
| 1827 | |||
| 1828 | // add open() | ||
| 1829 | func = make_new_mfun( "int", "open", HidIn_open ); | ||
| 1830 | func->add_arg( "int", "type" ); | ||
| 1831 | func->add_arg( "int", "num" ); | ||
| 1832 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1833 | |||
| 1834 | // add open() | ||
| 1835 | func = make_new_mfun( "int", "open", HidIn_open_named ); | ||
| 1836 | func->add_arg( "string", "name" ); | ||
| 1837 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1838 | |||
| 1839 | // add openJoystick() | ||
| 1840 | func = make_new_mfun( "int", "openJoystick", HidIn_open_joystick ); | ||
| 1841 | func->add_arg( "int", "num" ); | ||
| 1842 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1843 | |||
| 1844 | // add openMouse() | ||
| 1845 | func = make_new_mfun( "int", "openMouse", HidIn_open_mouse ); | ||
| 1846 | func->add_arg( "int", "num" ); | ||
| 1847 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1848 | |||
| 1849 | // add openKeyboard() | ||
| 1850 | func = make_new_mfun( "int", "openKeyboard", HidIn_open_keyboard ); | ||
| 1851 | func->add_arg( "int", "num" ); | ||
| 1852 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1853 | |||
| 1854 | // add openTiltSensor() | ||
| 1855 | func = make_new_mfun( "int", "openTiltSensor", HidIn_open_tiltsensor ); | ||
| 1856 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1857 | |||
| 1858 | // add good() | ||
| 1859 | func = make_new_mfun( "int", "good", HidIn_good ); | ||
| 1860 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1861 | |||
| 1862 | // add num() | ||
| 1863 | func = make_new_mfun( "int", "num", HidIn_num ); | ||
| 1864 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1865 | |||
| 1866 | // add name() | ||
| 1867 | func = make_new_mfun( "string", "name", HidIn_name ); | ||
| 1868 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1869 | |||
| 1870 | // add printerr() | ||
| 1871 | func = make_new_mfun( "void", "printerr", HidIn_printerr ); | ||
| 1872 | func->add_arg( "int", "print_or_not" ); | ||
| 1873 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1874 | |||
| 1875 | // add recv() | ||
| 1876 | func = make_new_mfun( "int", "recv", HidIn_recv ); | ||
| 1877 | func->add_arg( "HidMsg", "msg" ); | ||
| 1878 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1879 | |||
| 1880 | // add read() | ||
| 1881 | func = make_new_mfun( "int", "read", HidIn_read ); | ||
| 1882 | func->add_arg( "int", "type" ); | ||
| 1883 | func->add_arg( "int", "which" ); | ||
| 1884 | func->add_arg( "HidMsg", "msg" ); | ||
| 1885 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1886 | |||
| 1887 | // add send() | ||
| 1888 | func = make_new_mfun( "int", "send", HidIn_send ); | ||
| 1889 | func->add_arg( "HidMsg", "msg" ); | ||
| 1890 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1891 | |||
| 1892 | // add can_wait() | ||
| 1893 | func = make_new_mfun( "int", "can_wait", HidIn_can_wait ); | ||
| 1894 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 1895 | |||
| 1896 | // add readTiltSensor() | ||
| 1897 | func = make_new_sfun( "int[]", "readTiltSensor", HidIn_read_tilt_sensor ); | ||
| 1898 | if( !type_engine_import_sfun( env, func ) ) goto error; | ||
| 1899 | |||
| 1900 | // add globalTiltPollRate() | ||
| 1901 | func = make_new_sfun( "dur", "globalTiltPollRate", HidIn_ctrl_tiltPollRate ); | ||
| 1902 | func->add_arg( "dur", "d" ); | ||
| 1903 | if( !type_engine_import_sfun( env, func ) ) goto error; | ||
| 1904 | |||
| 1905 | // add globalTiltPollRate() | ||
| 1906 | func = make_new_sfun( "dur", "globalTiltPollRate", HidIn_cget_tiltPollRate ); | ||
| 1907 | if( !type_engine_import_sfun( env, func ) ) goto error; | ||
| 1908 | |||
| 1909 | // add startCursorTrack() | ||
| 1910 | func = make_new_sfun( "int", "startCursorTrack", HidIn_start_cursor_track ); | ||
| 1911 | if( !type_engine_import_sfun( env, func ) ) goto error; | ||
| 1912 | |||
| 1913 | // add stopCursorTrack() | ||
| 1914 | func = make_new_sfun( "int", "stopCursorTrack", HidIn_stop_cursor_track ); | ||
| 1915 | if( !type_engine_import_sfun( env, func ) ) goto error; | ||
| 1916 | |||
| 1917 | // add member variable | ||
| 1918 | HidIn_offset_data = type_engine_import_mvar( env, "int", "@Hid_data", FALSE ); | ||
| 1919 | if( HidIn_offset_data == CK_INVALID_OFFSET ) goto error; | ||
| 1920 | |||
| 1921 | // add static member variable joystick | ||
| 1922 | if( type_engine_import_svar( env, "int", "JOYSTICK", TRUE, | ||
| 1923 | ( t_CKUINT ) &CK_HID_DEV_JOYSTICK ) == FALSE ) | ||
| 1924 | goto error; | ||
| 1925 | |||
| 1926 | // add static member variable keyboard | ||
| 1927 | if( type_engine_import_svar( env, "int", "KEYBOARD", TRUE, | ||
| 1928 | ( t_CKUINT ) &CK_HID_DEV_KEYBOARD ) == FALSE ) | ||
| 1929 | goto error; | ||
| 1930 | |||
| 1931 | // add static member variable mouse | ||
| 1932 | if( type_engine_import_svar( env, "int", "MOUSE", TRUE, | ||
| 1933 | ( t_CKUINT ) &CK_HID_DEV_MOUSE ) == FALSE ) | ||
| 1934 | goto error; | ||
| 1935 | |||
| 1936 | // add static member variable wii_remote | ||
| 1937 | if( type_engine_import_svar( env, "int", "WII_REMOTE", TRUE, | ||
| 1938 | ( t_CKUINT ) &CK_HID_DEV_WIIREMOTE ) == FALSE ) | ||
| 1939 | goto error; | ||
| 1940 | |||
| 1941 | // add static member variable wii_remote | ||
| 1942 | if( type_engine_import_svar( env, "int", "TILT_SENSOR", TRUE, | ||
| 1943 | ( t_CKUINT ) &CK_HID_DEV_TILTSENSOR ) == FALSE ) | ||
| 1944 | goto error; | ||
| 1945 | |||
| 1946 | // add static member variable tablet | ||
| 1947 | if( type_engine_import_svar( env, "int", "TABLET", TRUE, | ||
| 1948 | ( t_CKUINT ) &CK_HID_DEV_TABLET ) == FALSE ) | ||
| 1949 | goto error; | ||
| 1950 | |||
| 1951 | // add static member variable axisMotion | ||
| 1952 | if( type_engine_import_svar( env, "int", "AXIS_MOTION", TRUE, | ||
| 1953 | ( t_CKUINT ) &CK_HID_JOYSTICK_AXIS ) == FALSE ) | ||
| 1954 | goto error; | ||
| 1955 | |||
| 1956 | // add static member variable buttonDown | ||
| 1957 | if( type_engine_import_svar( env, "int", "BUTTON_DOWN", TRUE, | ||
| 1958 | ( t_CKUINT ) &CK_HID_BUTTON_DOWN ) == FALSE ) | ||
| 1959 | goto error; | ||
| 1960 | |||
| 1961 | // add static member variable buttonUp | ||
| 1962 | if( type_engine_import_svar( env, "int", "BUTTON_UP", TRUE, | ||
| 1963 | ( t_CKUINT ) &CK_HID_BUTTON_UP ) == FALSE ) | ||
| 1964 | goto error; | ||
| 1965 | |||
| 1966 | // add static member variable joystickHat | ||
| 1967 | if( type_engine_import_svar( env, "int", "JOYSTICK_HAT", TRUE, | ||
| 1968 | ( t_CKUINT ) &CK_HID_JOYSTICK_HAT ) == FALSE ) | ||
| 1969 | goto error; | ||
| 1970 | |||
| 1971 | // add static member variable JOYSTICK_BALL | ||
| 1972 | if( type_engine_import_svar( env, "int", "JOYSTICK_BALL", TRUE, | ||
| 1973 | ( t_CKUINT ) &CK_HID_JOYSTICK_BALL ) == FALSE ) | ||
| 1974 | goto error; | ||
| 1975 | |||
| 1976 | // add static member variable mouseMotion | ||
| 1977 | if( type_engine_import_svar( env, "int", "MOUSE_MOTION", TRUE, | ||
| 1978 | ( t_CKUINT ) &CK_HID_MOUSE_MOTION ) == FALSE ) | ||
| 1979 | goto error; | ||
| 1980 | |||
| 1981 | // add static member variable mouseWheel | ||
| 1982 | if( type_engine_import_svar( env, "int", "MOUSE_WHEEL", TRUE, | ||
| 1983 | ( t_CKUINT ) &CK_HID_MOUSE_WHEEL ) == FALSE ) | ||
| 1984 | goto error; | ||
| 1985 | |||
| 1986 | // add static member variable DEVICE_CONNECTED | ||
| 1987 | if( type_engine_import_svar( env, "int", "DEVICE_CONNECTED", TRUE, | ||
| 1988 | ( t_CKUINT ) &CK_HID_DEVICE_CONNECTED ) == FALSE ) | ||
| 1989 | goto error; | ||
| 1990 | |||
| 1991 | // add static member variable DEVICE_DISCONNECTED | ||
| 1992 | if( type_engine_import_svar( env, "int", "DEVICE_DISCONNECTED", TRUE, | ||
| 1993 | ( t_CKUINT ) &CK_HID_DEVICE_DISCONNECTED ) == FALSE ) | ||
| 1994 | goto error; | ||
| 1995 | |||
| 1996 | // add static member variable ACCELEROMETER | ||
| 1997 | if( type_engine_import_svar( env, "int", "ACCELEROMETER", TRUE, | ||
| 1998 | ( t_CKUINT ) &CK_HID_ACCELEROMETER ) == FALSE ) | ||
| 1999 | goto error; | ||
| 2000 | |||
| 2001 | // add static member variable LED | ||
| 2002 | if( type_engine_import_svar( env, "int", "LED", TRUE, | ||
| 2003 | ( t_CKUINT ) &CK_HID_LED ) == FALSE ) | ||
| 2004 | goto error; | ||
| 2005 | |||
| 2006 | // add static member variable LED | ||
| 2007 | if( type_engine_import_svar( env, "int", "FORCE_FEEDBACK", TRUE, | ||
| 2008 | ( t_CKUINT ) &CK_HID_FORCE_FEEDBACK ) == FALSE ) | ||
| 2009 | goto error; | ||
| 2010 | |||
| 2011 | // end the class import | ||
| 2012 | type_engine_import_class_end( env ); | ||
| 2013 | |||
| 2014 | /* | ||
| 2015 | // init base class | ||
| 2016 | if( !type_engine_import_class_begin( env, "HidOut", "Object", | ||
| 2017 | env->global(), HidOut_ctor ) ) | ||
| 2018 | return FALSE; | ||
| 2019 | |||
| 2020 | // add open() | ||
| 2021 | func = make_new_mfun( "int", "open", HidOut_open ); | ||
| 2022 | func->add_arg( "int", "port" ); | ||
| 2023 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 2024 | |||
| 2025 | // add good() | ||
| 2026 | func = make_new_mfun( "int", "good", HidOut_good ); | ||
| 2027 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 2028 | |||
| 2029 | // add num() | ||
| 2030 | func = make_new_mfun( "int", "num", HidOut_num ); | ||
| 2031 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 2032 | |||
| 2033 | // add name() | ||
| 2034 | func = make_new_mfun( "string", "name", HidOut_name ); | ||
| 2035 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 2036 | |||
| 2037 | // add printerr() | ||
| 2038 | func = make_new_mfun( "void", "printerr", HidOut_printerr ); | ||
| 2039 | func->add_arg( "int", "print_or_not" ); | ||
| 2040 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 2041 | |||
| 2042 | // add send() | ||
| 2043 | func = make_new_mfun( "int", "send", HidOut_send ); | ||
| 2044 | func->add_arg( "HidMsg", "msg" ); | ||
| 2045 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 2046 | |||
| 2047 | // add member variable | ||
| 2048 | HidOut_offset_data = type_engine_import_mvar( env, "int", "@HidOut_data", FALSE ); | ||
| 2049 | if( HidOut_offset_data == CK_INVALID_OFFSET ) goto error; | ||
| 2050 | |||
| 2051 | // end the class import | ||
| 2052 | type_engine_import_class_end( env ); | ||
| 2053 | */ | ||
| 2054 | return TRUE; | ||
| 2055 | |||
| 2056 | error: | ||
| 2057 | |||
| 2058 | // end the class import | ||
| 2059 | type_engine_import_class_end( env ); | ||
| 2060 | |||
| 2061 | return FALSE; | ||
| 2062 | } | ||
| 2063 | |||
| 2064 | |||
| 2065 | |||
| 2066 | |||
| 2067 | |||
| 2068 | // static | ||
| 2069 | static t_CKUINT MidiRW_offset_data = 0; | ||
| 2070 | static t_CKUINT MidiMsgOut_offset_data = 0; | ||
| 2071 | static t_CKUINT MidiMsgIn_offset_data = 0; | ||
| 2072 | //----------------------------------------------------------------------------- | ||
| 2073 | // name: init_class_MidiRW() | ||
| 2074 | // desc: ... | ||
| 2075 | //----------------------------------------------------------------------------- | ||
| 2076 | t_CKBOOL init_class_MidiRW( Chuck_Env * env ) | ||
| 2077 | { | ||
| 2078 | Chuck_DL_Func * func = NULL; | ||
| 2079 | |||
| 2080 | #ifndef __DISABLE_MIDI__ | ||
| 2081 | |||
| 2082 | // init base class | ||
| 2083 | if( !type_engine_import_class_begin( env, "MidiRW", "Object", | ||
| 2084 | env->global(), MidiRW_ctor, MidiRW_dtor ) ) | ||
| 2085 | return FALSE; | ||
| 2086 | |||
| 2087 | // add open() | ||
| 2088 | func = make_new_mfun( "int", "open", MidiRW_open ); | ||
| 2089 | func->add_arg( "string", "filename" ); | ||
| 2090 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 2091 | |||
| 2092 | // add close() | ||
| 2093 | func = make_new_mfun( "int", "close", MidiRW_close ); | ||
| 2094 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 2095 | |||
| 2096 | // add write() | ||
| 2097 | func = make_new_mfun( "int", "write", MidiRW_write ); | ||
| 2098 | func->add_arg( "MidiMsg", "msg" ); | ||
| 2099 | func->add_arg( "time", "t" ); | ||
| 2100 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 2101 | |||
| 2102 | // add read() | ||
| 2103 | func = make_new_mfun( "int", "read", MidiRW_read ); | ||
| 2104 | func->add_arg( "MidiMsg", "msg" ); | ||
| 2105 | //func->add_arg( "time", "t" ); | ||
| 2106 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 2107 | |||
| 2108 | // add member variable | ||
| 2109 | MidiRW_offset_data = type_engine_import_mvar( env, "int", "@MidiRW_data", FALSE ); | ||
| 2110 | if( MidiRW_offset_data == CK_INVALID_OFFSET ) goto error; | ||
| 2111 | |||
| 2112 | // end the class import | ||
| 2113 | type_engine_import_class_end( env ); | ||
| 2114 | |||
| 2115 | // init base class | ||
| 2116 | if( !type_engine_import_class_begin( env, "MidiMsgOut", "Object", | ||
| 2117 | env->global(), MidiMsgOut_ctor, MidiMsgOut_dtor ) ) | ||
| 2118 | return FALSE; | ||
| 2119 | |||
| 2120 | // add open() | ||
| 2121 | func = make_new_mfun( "int", "open", MidiMsgOut_open ); | ||
| 2122 | func->add_arg( "string", "filename" ); | ||
| 2123 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 2124 | |||
| 2125 | // add close() | ||
| 2126 | func = make_new_mfun( "int", "close", MidiMsgOut_close ); | ||
| 2127 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 2128 | |||
| 2129 | // add write() | ||
| 2130 | func = make_new_mfun( "int", "write", MidiMsgOut_write ); | ||
| 2131 | func->add_arg( "MidiMsg", "msg" ); | ||
| 2132 | func->add_arg( "time", "t" ); | ||
| 2133 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 2134 | |||
| 2135 | // add member variable | ||
| 2136 | MidiMsgOut_offset_data = type_engine_import_mvar( env, "int", "@MidiMsgOut_data", FALSE ); | ||
| 2137 | if( MidiMsgOut_offset_data == CK_INVALID_OFFSET ) goto error; | ||
| 2138 | |||
| 2139 | // end the class import | ||
| 2140 | type_engine_import_class_end( env ); | ||
| 2141 | |||
| 2142 | // init base class | ||
| 2143 | if( !type_engine_import_class_begin( env, "MidiMsgIn", "Object", | ||
| 2144 | env->global(), MidiMsgIn_ctor, MidiMsgIn_dtor ) ) | ||
| 2145 | return FALSE; | ||
| 2146 | |||
| 2147 | // add open() | ||
| 2148 | func = make_new_mfun( "int", "open", MidiMsgIn_open ); | ||
| 2149 | func->add_arg( "string", "filename" ); | ||
| 2150 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 2151 | |||
| 2152 | // add close() | ||
| 2153 | func = make_new_mfun( "int", "close", MidiMsgIn_close ); | ||
| 2154 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 2155 | |||
| 2156 | // add read() | ||
| 2157 | func = make_new_mfun( "int", "read", MidiMsgIn_read ); | ||
| 2158 | func->add_arg( "MidiMsg", "msg" ); | ||
| 2159 | //func->add_arg( "time", "t" ); | ||
| 2160 | if( !type_engine_import_mfun( env, func ) ) goto error; | ||
| 2161 | |||
| 2162 | // add member variable | ||
| 2163 | MidiMsgIn_offset_data = type_engine_import_mvar( env, "int", "@MidiMsgIn_data", FALSE ); | ||
| 2164 | if( MidiMsgIn_offset_data == CK_INVALID_OFFSET ) goto error; | ||
| 2165 | |||
| 2166 | // end the class import | ||
| 2167 | type_engine_import_class_end( env ); | ||
| 2168 | |||
| 2169 | #endif // __DISABLE_MIDI__ | ||
| 2170 | |||
| 2171 | // initialize | ||
| 2172 | // HidInManager::init(); | ||
| 2173 | |||
| 2174 | return TRUE; | ||
| 2175 | |||
| 2176 | error: | ||
| 2177 | |||
| 2178 | // end the class import | ||
| 2179 | type_engine_import_class_end( env ); | ||
| 2180 | |||
| 2181 | return FALSE; | ||
| 2182 | } | ||
| 2183 | |||
| 2184 | |||
| 2185 | |||
| 2186 | |||
| 2187 | |||
| 2188 | |||
| 2189 | // Object ctor | ||
| 2190 | CK_DLL_CTOR( object_ctor ) | ||
| 2191 | { | ||
| 2192 | // log | ||
| 2193 | // EM_log( CK_LOG_FINEST, "Object constructor..." ); | ||
| 2194 | |||
| 2195 | // initialize | ||
| 2196 | OBJ_MEMBER_UINT(SELF, Object_offset_string) = 0; | ||
| 2197 | } | ||
| 2198 | |||
| 2199 | |||
| 2200 | // Object dtor | ||
| 2201 | CK_DLL_DTOR( object_dtor ) | ||
| 2202 | { | ||
| 2203 | // log | ||
| 2204 | // EM_log( CK_LOG_FINEST, "Object destructor..." ); | ||
| 2205 | |||
| 2206 | // get the string | ||
| 2207 | Chuck_String * str = (Chuck_String *)OBJ_MEMBER_UINT(SELF, Object_offset_string); | ||
| 2208 | // release | ||
| 2209 | SAFE_RELEASE( str ); | ||
| 2210 | } | ||
| 2211 | |||
| 2212 | |||
| 2213 | // toString | ||
| 2214 | CK_DLL_MFUN( object_toString ) | ||
| 2215 | { | ||
| 2216 | // get the string | ||
| 2217 | Chuck_String * str = (Chuck_String *)OBJ_MEMBER_UINT(SELF, Object_offset_string); | ||
| 2218 | // allocate | ||
| 2219 | if( !str ) | ||
| 2220 | { | ||
| 2221 | // new it | ||
| 2222 | str = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED ); | ||
| 2223 | // check it | ||
| 2224 | if( !str ) | ||
| 2225 | { | ||
| 2226 | // TODO: make this exception | ||
| 2227 | CK_FPRINTF_STDERR( "[chuck]: Object.toString() out of memory!\n" ); | ||
| 2228 | RETURN->v_object = NULL; | ||
| 2229 | return; | ||
| 2230 | } | ||
| 2231 | // set it | ||
| 2232 | ostringstream strout( ostringstream::out ); | ||
| 2233 | // get the type | ||
| 2234 | Chuck_Type * type = SELF->type_ref; | ||
| 2235 | // write | ||
| 2236 | strout.setf( ios::hex, ios::basefield ); | ||
| 2237 | strout << ((type != NULL) ? type->c_name() : "[VOID]") << ":" << (t_CKUINT)SELF; | ||
| 2238 | strout.flush(); | ||
| 2239 | |||
| 2240 | // done | ||
| 2241 | str->set( strout.str() ); | ||
| 2242 | } | ||
| 2243 | |||
| 2244 | // set return | ||
| 2245 | RETURN->v_object = str; | ||
| 2246 | } | ||
| 2247 | |||
| 2248 | |||
| 2249 | // ctor | ||
| 2250 | CK_DLL_CTOR( ugen_ctor ) | ||
| 2251 | { | ||
| 2252 | } | ||
| 2253 | |||
| 2254 | CK_DLL_DTOR( ugen_dtor ) | ||
| 2255 | { | ||
| 2256 | // get as ugen | ||
| 2257 | // Chuck_UGen * ugen = (Chuck_UGen *)SELF; | ||
| 2258 | } | ||
| 2259 | |||
| 2260 | CK_DLL_MFUN( ugen_op ) | ||
| 2261 | { | ||
| 2262 | // get as ugen | ||
| 2263 | Chuck_UGen * ugen = (Chuck_UGen *)SELF; | ||
| 2264 | // get arg | ||
| 2265 | t_CKINT op = GET_CK_INT( ARGS ); | ||
| 2266 | // set op | ||
| 2267 | ugen->m_op = op; | ||
| 2268 | // set return | ||
| 2269 | RETURN->v_int = ugen->m_op; | ||
| 2270 | |||
| 2271 | // for multiple channels | ||
| 2272 | Chuck_DL_Return ret; | ||
| 2273 | // added 1.3.0.0 -- Chuck_DL_Api::Api::instance() | ||
| 2274 | for( t_CKUINT i = 0; i < ugen->m_multi_chan_size; i++ ) | ||
| 2275 | ugen_op( ugen->m_multi_chan[i], ARGS, &ret, SHRED, API ); | ||
| 2276 | // added 1.3.0.2 -- apply op to subgraph outlet | ||
| 2277 | if( ugen->inlet() ) | ||
| 2278 | ugen->inlet()->m_op = op; | ||
| 2279 | if( ugen->outlet() ) | ||
| 2280 | ugen->outlet()->m_op = op; | ||
| 2281 | } | ||
| 2282 | |||
| 2283 | CK_DLL_MFUN( ugen_cget_op ) | ||
| 2284 | { | ||
| 2285 | // get as ugen | ||
| 2286 | Chuck_UGen * ugen = (Chuck_UGen *)SELF; | ||
| 2287 | // set return | ||
| 2288 | RETURN->v_int = ugen->m_op; | ||
| 2289 | } | ||
| 2290 | |||
| 2291 | CK_DLL_MFUN( ugen_last ) | ||
| 2292 | { | ||
| 2293 | // get as ugen | ||
| 2294 | Chuck_UGen * ugen = (Chuck_UGen *)SELF; | ||
| 2295 | // set return | ||
| 2296 | // added 1.3.0.2 -- ugen outlet() last if subgraph | ||
| 2297 | if( ugen->outlet() ) | ||
| 2298 | RETURN->v_float = (t_CKFLOAT) ugen->outlet()->m_last; | ||
| 2299 | else | ||
| 2300 | RETURN->v_float = (t_CKFLOAT)ugen->m_last; | ||
| 2301 | } | ||
| 2302 | |||
| 2303 | CK_DLL_MFUN( ugen_next ) | ||
| 2304 | { | ||
| 2305 | // get as ugen | ||
| 2306 | Chuck_UGen * ugen = (Chuck_UGen *)SELF; | ||
| 2307 | // get arg | ||
| 2308 | t_CKFLOAT next = GET_CK_FLOAT( ARGS ); | ||
| 2309 | // set op | ||
| 2310 | ugen->m_next = (SAMPLE)next; | ||
| 2311 | ugen->m_use_next = TRUE; | ||
| 2312 | // set return | ||
| 2313 | RETURN->v_float = (t_CKFLOAT)ugen->m_next; | ||
| 2314 | |||
| 2315 | // for multiple channels | ||
| 2316 | Chuck_DL_Return ret; | ||
| 2317 | // added 1.3.0.0 -- Chuck_DL_Api::Api::instance() | ||
| 2318 | for( t_CKUINT i = 0; i < ugen->m_multi_chan_size; i++ ) | ||
| 2319 | ugen_next( ugen->m_multi_chan[i], ARGS, &ret, SHRED, API ); | ||
| 2320 | // added 1.3.0.2 -- apply op to subgraph outlet | ||
| 2321 | if( ugen->outlet() ) | ||
| 2322 | { | ||
| 2323 | ugen->outlet()->m_next = (SAMPLE) next; | ||
| 2324 | ugen->outlet()->m_use_next = TRUE; | ||
| 2325 | } | ||
| 2326 | } | ||
| 2327 | |||
| 2328 | CK_DLL_MFUN( ugen_cget_next ) | ||
| 2329 | { | ||
| 2330 | // get as ugen | ||
| 2331 | Chuck_UGen * ugen = (Chuck_UGen *)SELF; | ||
| 2332 | // set return | ||
| 2333 | RETURN->v_float = ugen->m_use_next ? (t_CKFLOAT)ugen->m_next : 0.0f; | ||
| 2334 | } | ||
| 2335 | |||
| 2336 | CK_DLL_MFUN( ugen_gain ) | ||
| 2337 | { | ||
| 2338 | // get as ugen | ||
| 2339 | Chuck_UGen * ugen = (Chuck_UGen *)SELF; | ||
| 2340 | // get arg | ||
| 2341 | t_CKFLOAT gain = GET_CK_FLOAT( ARGS ); | ||
| 2342 | // set op | ||
| 2343 | ugen->m_gain = (SAMPLE)gain; | ||
| 2344 | // set return | ||
| 2345 | RETURN->v_float = (t_CKFLOAT)ugen->m_gain; | ||
| 2346 | |||
| 2347 | // for multiple channels | ||
| 2348 | Chuck_DL_Return ret; | ||
| 2349 | // added 1.3.0.0 -- Chuck_DL_Api::Api::instance() | ||
| 2350 | for( t_CKUINT i = 0; i < ugen->m_multi_chan_size; i++ ) | ||
| 2351 | ugen_gain( ugen->m_multi_chan[i], ARGS, &ret, SHRED, API ); | ||
| 2352 | // added 1.3.0.2 -- apply gain to subgraph outlet | ||
| 2353 | if( ugen->outlet() ) | ||
| 2354 | ugen->outlet()->m_gain = (SAMPLE) gain; | ||
| 2355 | } | ||
| 2356 | |||
| 2357 | CK_DLL_MFUN( ugen_cget_gain ) | ||
| 2358 | { | ||
| 2359 | // get as ugen | ||
| 2360 | Chuck_UGen * ugen = (Chuck_UGen *)SELF; | ||
| 2361 | // set return | ||
| 2362 | RETURN->v_float = (t_CKFLOAT)ugen->m_gain; | ||
| 2363 | } | ||
| 2364 | |||
| 2365 | CK_DLL_CTRL( ugen_numChannels ) | ||
| 2366 | { | ||
| 2367 | // get ugen | ||
| 2368 | //Chuck_UGen * ugen = (Chuck_UGen *)SELF; | ||
| 2369 | // error | ||
| 2370 | EM_error3( "setting .numChannels is not yet supported (use the command line)..." ); | ||
| 2371 | } | ||
| 2372 | |||
| 2373 | CK_DLL_CGET( ugen_cget_numChannels ) | ||
| 2374 | { | ||
| 2375 | // get ugen | ||
| 2376 | Chuck_UGen * ugen = (Chuck_UGen *)SELF; | ||
| 2377 | // return | ||
| 2378 | RETURN->v_int = ugen->m_multi_chan_size == 0 ? 1 : ugen->m_multi_chan_size; | ||
| 2379 | } | ||
| 2380 | |||
| 2381 | CK_DLL_CTRL( ugen_chan ) | ||
| 2382 | { | ||
| 2383 | // get ugen | ||
| 2384 | Chuck_UGen * ugen = (Chuck_UGen *)SELF; | ||
| 2385 | t_CKINT num = GET_NEXT_INT(ARGS); | ||
| 2386 | // check | ||
| 2387 | if( !ugen->m_multi_chan_size && num == 0 ) | ||
| 2388 | RETURN->v_object = ugen; | ||
| 2389 | else if( num >= 0 && num < ugen->m_multi_chan_size ) | ||
| 2390 | RETURN->v_object = ugen->m_multi_chan[num]; | ||
| 2391 | else | ||
| 2392 | RETURN->v_object = NULL; | ||
| 2393 | } | ||
| 2394 | |||
| 2395 | CK_DLL_CTRL( ugen_connected ) | ||
| 2396 | { | ||
| 2397 | // get ugen | ||
| 2398 | Chuck_UGen * ugen = (Chuck_UGen *)SELF; | ||
| 2399 | Chuck_UGen * right = (Chuck_UGen *)GET_NEXT_OBJECT(ARGS); | ||
| 2400 | |||
| 2401 | // sanity | ||
| 2402 | t_CKINT ret = FALSE; | ||
| 2403 | if( !right ) | ||
| 2404 | { | ||
| 2405 | ret = FALSE; | ||
| 2406 | } | ||
| 2407 | else | ||
| 2408 | { | ||
| 2409 | ret = right->is_connected_from( ugen ); | ||
| 2410 | } | ||
| 2411 | |||
| 2412 | RETURN->v_int = ret; | ||
| 2413 | } | ||
| 2414 | |||
| 2415 | |||
| 2416 | // ctor | ||
| 2417 | CK_DLL_CTOR( uana_ctor ) | ||
| 2418 | { | ||
| 2419 | // make an actual blob | ||
| 2420 | Chuck_Object * blob = instantiate_and_initialize_object( SHRED->vm_ref->env()->t_uanablob, SHRED ); | ||
| 2421 | // TODO: check out of memory | ||
| 2422 | assert( blob != NULL ); | ||
| 2423 | // make a blob proxy | ||
| 2424 | Chuck_UAnaBlobProxy * proxy = new Chuck_UAnaBlobProxy( blob ); | ||
| 2425 | // remember it | ||
| 2426 | OBJ_MEMBER_INT(SELF, uana_offset_blob) = (t_CKINT)proxy; | ||
| 2427 | // HACK: DANGER: manually call blob's ctor (added 1.3.0.0 -- Chuck_DL_Api::Api::instance()) | ||
| 2428 | uanablob_ctor( blob, NULL, SHRED, API ); | ||
| 2429 | } | ||
| 2430 | |||
| 2431 | CK_DLL_DTOR( uana_dtor ) | ||
| 2432 | { | ||
| 2433 | // TODO: GC should release the blob! | ||
| 2434 | } | ||
| 2435 | |||
| 2436 | CK_DLL_MFUN( uana_upchuck ) | ||
| 2437 | { | ||
| 2438 | // get as uana | ||
| 2439 | Chuck_UAna * uana = (Chuck_UAna *)SELF; | ||
| 2440 | // get shred | ||
| 2441 | Chuck_VM_Shred * derhs = SHRED; | ||
| 2442 | // make sure it's not NULL | ||
| 2443 | if( !derhs ) | ||
| 2444 | { | ||
| 2445 | EM_error3( "UAna.upchuck() encountered NULL shred; operation aborting!" ); | ||
| 2446 | return; | ||
| 2447 | } | ||
| 2448 | |||
| 2449 | // get VM | ||
| 2450 | Chuck_VM * vm = derhs->vm_ref; | ||
| 2451 | // ensure | ||
| 2452 | if( !vm ) | ||
| 2453 | { | ||
| 2454 | EM_error3( "UAna.upchuck() encountered NULL VM ref; operation aborting!" ); | ||
| 2455 | return; | ||
| 2456 | } | ||
| 2457 | |||
| 2458 | // check if time | ||
| 2459 | if( uana->m_uana_time < vm->shreduler()->now_system ) | ||
| 2460 | { | ||
| 2461 | // for multiple channels | ||
| 2462 | Chuck_DL_Return ret; | ||
| 2463 | // added 1.3.0.0 -- Chuck_DL_Api::Api::instance() | ||
| 2464 | for( t_CKUINT i = 0; i < uana->m_multi_chan_size; i++ ) | ||
| 2465 | uana_upchuck( uana->m_multi_chan[i], ARGS, &ret, SHRED, API ); | ||
| 2466 | |||
| 2467 | // tock it (TODO: order relative to multiple channels?) | ||
| 2468 | uana->system_tock( vm->shreduler()->now_system ); | ||
| 2469 | } | ||
| 2470 | |||
| 2471 | // return | ||
| 2472 | RETURN->v_object = uana->blobProxy()->realblob(); | ||
| 2473 | } | ||
| 2474 | |||
| 2475 | /* CK_DLL_MFUN( uana_blob ) | ||
| 2476 | { | ||
| 2477 | // get as uana | ||
| 2478 | Chuck_UAna * uana = (Chuck_UAna *)SELF; | ||
| 2479 | |||
| 2480 | // TODO: return | ||
| 2481 | RETURN->v_object = NULL; | ||
| 2482 | } */ | ||
| 2483 | |||
| 2484 | CK_DLL_MFUN( uana_fvals ) | ||
| 2485 | { | ||
| 2486 | // get the fvals array | ||
| 2487 | Chuck_UAnaBlobProxy * blob = (Chuck_UAnaBlobProxy *)OBJ_MEMBER_INT(SELF, uana_offset_blob); | ||
| 2488 | RETURN->v_object = &blob->fvals(); | ||
| 2489 | } | ||
| 2490 | |||
| 2491 | CK_DLL_MFUN( uana_cvals ) | ||
| 2492 | { | ||
| 2493 | // get the fvals array | ||
| 2494 | Chuck_UAnaBlobProxy * blob = (Chuck_UAnaBlobProxy *)OBJ_MEMBER_INT(SELF, uana_offset_blob); | ||
| 2495 | RETURN->v_object = &blob->cvals(); | ||
| 2496 | } | ||
| 2497 | |||
| 2498 | CK_DLL_MFUN( uana_fval ) | ||
| 2499 | { | ||
| 2500 | // get index | ||
| 2501 | t_CKINT i = GET_NEXT_INT(ARGS); | ||
| 2502 | // get the fvals array | ||
| 2503 | Chuck_UAnaBlobProxy * blob = (Chuck_UAnaBlobProxy *)OBJ_MEMBER_INT(SELF, uana_offset_blob); | ||
| 2504 | Chuck_Array8 & fvals = blob->fvals(); | ||
| 2505 | // check caps | ||
| 2506 | if( i < 0 || fvals.size() <= i ) RETURN->v_float = 0; | ||
| 2507 | else | ||
| 2508 | { | ||
| 2509 | // get | ||
| 2510 | t_CKFLOAT val; | ||
| 2511 | fvals.get( i, &val ); | ||
| 2512 | RETURN->v_float = val; | ||
| 2513 | } | ||
| 2514 | } | ||
| 2515 | |||
| 2516 | CK_DLL_MFUN( uana_cval ) | ||
| 2517 | { | ||
| 2518 | // get index | ||
| 2519 | t_CKINT i = GET_NEXT_INT(ARGS); | ||
| 2520 | // get the fvals array | ||
| 2521 | Chuck_UAnaBlobProxy * blob = (Chuck_UAnaBlobProxy *)OBJ_MEMBER_INT(SELF, uana_offset_blob); | ||
| 2522 | Chuck_Array16 & cvals = blob->cvals(); | ||
| 2523 | // check caps | ||
| 2524 | if( i < 0 || cvals.size() <= i ) RETURN->v_complex.re = RETURN->v_complex.im = 0; | ||
| 2525 | else | ||
| 2526 | { | ||
| 2527 | // get | ||
| 2528 | t_CKCOMPLEX val; | ||
| 2529 | cvals.get( i, &val ); | ||
| 2530 | RETURN->v_complex = val; | ||
| 2531 | } | ||
| 2532 | } | ||
| 2533 | |||
| 2534 | CK_DLL_MFUN( uana_connected ) | ||
| 2535 | { | ||
| 2536 | // get ugen | ||
| 2537 | Chuck_UAna * uana = (Chuck_UAna *)SELF; | ||
| 2538 | Chuck_UAna * right = (Chuck_UAna *)GET_NEXT_OBJECT(ARGS); | ||
| 2539 | |||
| 2540 | // sanity | ||
| 2541 | t_CKINT ret = FALSE; | ||
| 2542 | if( !right ) | ||
| 2543 | { | ||
| 2544 | ret = FALSE; | ||
| 2545 | } | ||
| 2546 | else | ||
| 2547 | { | ||
| 2548 | ret = right->is_up_connected_from( uana ); | ||
| 2549 | } | ||
| 2550 | |||
| 2551 | RETURN->v_int = ret; | ||
| 2552 | } | ||
| 2553 | |||
| 2554 | |||
| 2555 | // blob proxy implementation | ||
| 2556 | Chuck_UAnaBlobProxy::Chuck_UAnaBlobProxy( Chuck_Object * blob ) | ||
| 2557 | { | ||
| 2558 | m_blob = blob; | ||
| 2559 | assert( m_blob != NULL ); | ||
| 2560 | // add reference | ||
| 2561 | m_blob->add_ref(); | ||
| 2562 | } | ||
| 2563 | |||
| 2564 | Chuck_UAnaBlobProxy::~Chuck_UAnaBlobProxy() | ||
| 2565 | { | ||
| 2566 | // release | ||
| 2567 | SAFE_RELEASE( m_blob ); | ||
| 2568 | } | ||
| 2569 | |||
| 2570 | t_CKTIME & Chuck_UAnaBlobProxy::when() | ||
| 2571 | { | ||
| 2572 | // TODO: DANGER: is this actually returning correct reference?! | ||
| 2573 | return OBJ_MEMBER_TIME(m_blob, uanablob_offset_when); | ||
| 2574 | } | ||
| 2575 | |||
| 2576 | Chuck_Array8 & Chuck_UAnaBlobProxy::fvals() | ||
| 2577 | { | ||
| 2578 | // TODO: DANGER: is this actually returning correct reference?! | ||
| 2579 | Chuck_Array8 * arr8 = (Chuck_Array8 *)OBJ_MEMBER_INT(m_blob, uanablob_offset_fvals); | ||
| 2580 | assert( arr8 != NULL ); | ||
| 2581 | return *arr8; | ||
| 2582 | } | ||
| 2583 | |||
| 2584 | Chuck_Array16 & Chuck_UAnaBlobProxy::cvals() | ||
| 2585 | { | ||
| 2586 | // TODO: DANGER: is this actually returning correct reference?! | ||
| 2587 | Chuck_Array16 * arr16 = (Chuck_Array16 *)OBJ_MEMBER_INT(m_blob, uanablob_offset_cvals); | ||
| 2588 | assert( arr16 != NULL ); | ||
| 2589 | return *arr16; | ||
| 2590 | } | ||
| 2591 | |||
| 2592 | // get proxy | ||
| 2593 | Chuck_UAnaBlobProxy * getBlobProxy( const Chuck_UAna * uana ) | ||
| 2594 | { | ||
| 2595 | return (Chuck_UAnaBlobProxy *)OBJ_MEMBER_INT(uana, uana_offset_blob); | ||
| 2596 | } | ||
| 2597 | |||
| 2598 | // ctor | ||
| 2599 | CK_DLL_CTOR( uanablob_ctor ) | ||
| 2600 | { | ||
| 2601 | // when | ||
| 2602 | OBJ_MEMBER_TIME(SELF, uanablob_offset_when) = 0; | ||
| 2603 | // fvals | ||
| 2604 | Chuck_Array8 * arr8 = new Chuck_Array8( 8 ); | ||
| 2605 | initialize_object( arr8, SHRED->vm_ref->env()->t_array ); | ||
| 2606 | // TODO: check out of memory | ||
| 2607 | arr8->add_ref(); | ||
| 2608 | OBJ_MEMBER_INT(SELF, uanablob_offset_fvals) = (t_CKINT)arr8; | ||
| 2609 | // cvals | ||
| 2610 | Chuck_Array16 * arr16 = new Chuck_Array16( 8 ); | ||
| 2611 | initialize_object( arr16, SHRED->vm_ref->env()->t_array ); | ||
| 2612 | // TODO: check out of memory | ||
| 2613 | arr16->add_ref(); | ||
| 2614 | OBJ_MEMBER_INT(SELF, uanablob_offset_cvals) = (t_CKINT)arr16; | ||
| 2615 | } | ||
| 2616 | |||
| 2617 | // dtor | ||
| 2618 | CK_DLL_DTOR( uanablob_dtor ) | ||
| 2619 | { | ||
| 2620 | // get array | ||
| 2621 | Chuck_Array8 * arr8 = (Chuck_Array8 *)OBJ_MEMBER_INT(SELF, uanablob_offset_fvals); | ||
| 2622 | // release it | ||
| 2623 | arr8->release(); | ||
| 2624 | OBJ_MEMBER_INT(SELF, uanablob_offset_fvals) = 0; | ||
| 2625 | |||
| 2626 | // get array | ||
| 2627 | Chuck_Array16 * arr16 = (Chuck_Array16 *)OBJ_MEMBER_INT(SELF, uanablob_offset_cvals); | ||
| 2628 | // release it | ||
| 2629 | arr16->release(); | ||
| 2630 | OBJ_MEMBER_INT(SELF, uanablob_offset_cvals) = 0; | ||
| 2631 | |||
| 2632 | OBJ_MEMBER_TIME(SELF, uanablob_offset_when) = 0; | ||
| 2633 | } | ||
| 2634 | |||
| 2635 | CK_DLL_MFUN( uanablob_when ) | ||
| 2636 | { | ||
| 2637 | // set return | ||
| 2638 | RETURN->v_time = OBJ_MEMBER_TIME(SELF, uanablob_offset_when); | ||
| 2639 | } | ||
| 2640 | |||
| 2641 | CK_DLL_MFUN( uanablob_fvals ) | ||
| 2642 | { | ||
| 2643 | // set return | ||
| 2644 | RETURN->v_object = (Chuck_Array8 *)OBJ_MEMBER_INT(SELF, uanablob_offset_fvals); | ||
| 2645 | } | ||
| 2646 | |||
| 2647 | CK_DLL_MFUN( uanablob_fval ) | ||
| 2648 | { | ||
| 2649 | // get index | ||
| 2650 | t_CKINT i = GET_NEXT_INT(ARGS); | ||
| 2651 | // get the fvals array | ||
| 2652 | Chuck_Array8 * fvals = (Chuck_Array8 *)OBJ_MEMBER_INT(SELF, uanablob_offset_fvals); | ||
| 2653 | // check caps | ||
| 2654 | if( i < 0 || fvals->size() <= i ) RETURN->v_float = 0; | ||
| 2655 | else | ||
| 2656 | { | ||
| 2657 | // get | ||
| 2658 | t_CKFLOAT val; | ||
| 2659 | fvals->get( i, &val ); | ||
| 2660 | RETURN->v_float = val; | ||
| 2661 | } | ||
| 2662 | } | ||
| 2663 | |||
| 2664 | CK_DLL_MFUN( uanablob_cval ) | ||
| 2665 | { | ||
| 2666 | // get index | ||
| 2667 | t_CKINT i = GET_NEXT_INT(ARGS); | ||
| 2668 | // get the fvals array | ||
| 2669 | Chuck_Array16 * cvals = (Chuck_Array16 *)OBJ_MEMBER_INT(SELF, uanablob_offset_cvals); | ||
| 2670 | // check caps | ||
| 2671 | if( i < 0 || cvals->size() <= i ) RETURN->v_complex.re = RETURN->v_complex.im = 0; | ||
| 2672 | else | ||
| 2673 | { | ||
| 2674 | // get | ||
| 2675 | t_CKCOMPLEX val; | ||
| 2676 | cvals->get( i, &val ); | ||
| 2677 | RETURN->v_complex = val; | ||
| 2678 | } | ||
| 2679 | } | ||
| 2680 | |||
| 2681 | CK_DLL_MFUN( uanablob_cvals ) | ||
| 2682 | { | ||
| 2683 | // set return | ||
| 2684 | RETURN->v_object = (Chuck_Array16 *)OBJ_MEMBER_INT(SELF, uanablob_offset_cvals); | ||
| 2685 | } | ||
| 2686 | |||
| 2687 | // ctor | ||
| 2688 | CK_DLL_CTOR( event_ctor ) | ||
| 2689 | { | ||
| 2690 | // OBJ_MEMBER_INT(SELF, event_offset_data) = (t_CKUINT)new Data_Event; | ||
| 2691 | // Chuck_Event * event = (Chuck_Event *)SELF; | ||
| 2692 | } | ||
| 2693 | |||
| 2694 | |||
| 2695 | CK_DLL_DTOR( event_dtor ) | ||
| 2696 | { | ||
| 2697 | // delete (Data_Event *)OBJ_MEMBER_INT(SELF, event_offset_data); | ||
| 2698 | } | ||
| 2699 | |||
| 2700 | CK_DLL_MFUN( event_signal ) | ||
| 2701 | { | ||
| 2702 | Chuck_Event * d = (Chuck_Event *)SELF; | ||
| 2703 | d->signal(); | ||
| 2704 | } | ||
| 2705 | |||
| 2706 | CK_DLL_MFUN( event_broadcast ) | ||
| 2707 | { | ||
| 2708 | Chuck_Event * d = (Chuck_Event *)SELF; | ||
| 2709 | d->broadcast(); | ||
| 2710 | } | ||
| 2711 | |||
| 2712 | CK_DLL_MFUN( event_wait ) | ||
| 2713 | { | ||
| 2714 | // Chuck_Event * d = (Chuck_Event *)SELF; | ||
| 2715 | assert( FALSE ); | ||
| 2716 | } | ||
| 2717 | |||
| 2718 | CK_DLL_MFUN( event_can_wait ) | ||
| 2719 | { | ||
| 2720 | RETURN->v_int = TRUE; | ||
| 2721 | } | ||
| 2722 | |||
| 2723 | |||
| 2724 | //----------------------------------------------------------------------------- | ||
| 2725 | // vec3 API | ||
| 2726 | //----------------------------------------------------------------------------- | ||
| 2727 | CK_DLL_MFUN( vec3_set ) | ||
| 2728 | { | ||
| 2729 | // HACK: this is a particularly horrid cast from (Chuck_Object *) | ||
| 2730 | // t_CKVEC3 is neither a super- or sub-class of Chuck_Object... | ||
| 2731 | t_CKVEC3 * vec3 = (t_CKVEC3 *)SELF; | ||
| 2732 | // get index | ||
| 2733 | vec3->x = GET_NEXT_FLOAT(ARGS); | ||
| 2734 | vec3->y = GET_NEXT_FLOAT(ARGS); | ||
| 2735 | vec3->z = GET_NEXT_FLOAT(ARGS); | ||
| 2736 | } | ||
| 2737 | |||
| 2738 | CK_DLL_MFUN( vec3_setAll ) | ||
| 2739 | { | ||
| 2740 | // get data pointer | ||
| 2741 | t_CKVEC3 * vec3 = (t_CKVEC3 *)SELF; | ||
| 2742 | // get index | ||
| 2743 | vec3->x = vec3->y = vec3->z = GET_NEXT_FLOAT(ARGS); | ||
| 2744 | } | ||
| 2745 | |||
| 2746 | CK_DLL_MFUN( vec3_magnitude ) | ||
| 2747 | { | ||
| 2748 | // get data pointer | ||
| 2749 | t_CKVEC3 * vec3 = (t_CKVEC3 *)SELF; | ||
| 2750 | // compute magnitude | ||
| 2751 | t_CKFLOAT mag = ::sqrt( vec3->x*vec3->x + vec3->y*vec3->y + vec3->z*vec3->z ); | ||
| 2752 | // return | ||
| 2753 | RETURN->v_float = mag; | ||
| 2754 | } | ||
| 2755 | |||
| 2756 | CK_DLL_MFUN( vec3_normalize ) | ||
| 2757 | { | ||
| 2758 | // get data pointer | ||
| 2759 | t_CKVEC3 * vec3 = (t_CKVEC3 *)SELF; | ||
| 2760 | // compute magnitude | ||
| 2761 | t_CKFLOAT mag = ::sqrt( vec3->x*vec3->x + vec3->y*vec3->y + vec3->z*vec3->z ); | ||
| 2762 | // check for zero | ||
| 2763 | if( mag > 0 ) | ||
| 2764 | { | ||
| 2765 | vec3->x /= mag; | ||
| 2766 | vec3->y /= mag; | ||
| 2767 | vec3->z /= mag; | ||
| 2768 | } | ||
| 2769 | } | ||
| 2770 | |||
| 2771 | CK_DLL_MFUN( vec3_interp ) | ||
| 2772 | { | ||
| 2773 | // get data pointer | ||
| 2774 | t_CKVEC3 * vec3 = (t_CKVEC3 *)SELF; | ||
| 2775 | // update value based on goal and slew | ||
| 2776 | vec3->x = (vec3->y - vec3->x) * vec3->z + vec3->x; | ||
| 2777 | // set return to value so it can used right after if desired | ||
| 2778 | RETURN->v_float = vec3->x; | ||
| 2779 | } | ||
| 2780 | |||
| 2781 | CK_DLL_MFUN( vec3_interp_delta_float ) | ||
| 2782 | { | ||
| 2783 | // get data pointer | ||
| 2784 | t_CKVEC3 * vec3 = (t_CKVEC3 *)SELF; | ||
| 2785 | // get index | ||
| 2786 | t_CKFLOAT delta = GET_NEXT_FLOAT(ARGS); | ||
| 2787 | // update value based on goal and slew | ||
| 2788 | vec3->x = (vec3->y - vec3->x) * vec3->z * delta + vec3->x; | ||
| 2789 | // set return to value so it can used right after if desired | ||
| 2790 | RETURN->v_float = vec3->x; | ||
| 2791 | } | ||
| 2792 | |||
| 2793 | CK_DLL_MFUN( vec3_interp_delta_dur ) | ||
| 2794 | { | ||
| 2795 | // get data pointer | ||
| 2796 | t_CKVEC3 * vec3 = (t_CKVEC3 *)SELF; | ||
| 2797 | // get index | ||
| 2798 | t_CKDUR delta = GET_NEXT_DUR(ARGS); | ||
| 2799 | // get srate | ||
| 2800 | t_CKFLOAT srate = SHRED->vm_ref->srate(); | ||
| 2801 | // update value based on goal and slew | ||
| 2802 | vec3->x = (vec3->y - vec3->x) * vec3->z * (delta / srate) + vec3->x; | ||
| 2803 | // set return to value so it can used right after if desired | ||
| 2804 | RETURN->v_float = vec3->x; | ||
| 2805 | } | ||
| 2806 | |||
| 2807 | CK_DLL_MFUN( vec3_update_goal ) | ||
| 2808 | { | ||
| 2809 | // get data pointer | ||
| 2810 | t_CKVEC3 * vec3 = (t_CKVEC3 *)SELF; | ||
| 2811 | // get index | ||
| 2812 | t_CKDUR goal = GET_NEXT_DUR(ARGS); | ||
| 2813 | // set goal | ||
| 2814 | vec3->y = goal; | ||
| 2815 | } | ||
| 2816 | |||
| 2817 | CK_DLL_MFUN( vec3_update_goal_slew ) | ||
| 2818 | { | ||
| 2819 | // get data pointer | ||
| 2820 | t_CKVEC3 * vec3 = (t_CKVEC3 *)SELF; | ||
| 2821 | // get goal | ||
| 2822 | t_CKDUR goal = GET_NEXT_DUR(ARGS); | ||
| 2823 | // get slew | ||
| 2824 | t_CKDUR slew = GET_NEXT_DUR(ARGS); | ||
| 2825 | // set goal | ||
| 2826 | vec3->y = goal; | ||
| 2827 | // set slew | ||
| 2828 | vec3->z = slew; | ||
| 2829 | } | ||
| 2830 | |||
| 2831 | CK_DLL_MFUN( vec3_updateSet_goalAndValue ) | ||
| 2832 | { | ||
| 2833 | // get data pointer | ||
| 2834 | t_CKVEC3 * vec3 = (t_CKVEC3 *)SELF; | ||
| 2835 | // get goal | ||
| 2836 | t_CKDUR goalAndValue = GET_NEXT_DUR(ARGS); | ||
| 2837 | // set goal and value | ||
| 2838 | vec3->y = vec3->x = goalAndValue; | ||
| 2839 | } | ||
| 2840 | |||
| 2841 | CK_DLL_MFUN( vec3_updateSet_goalAndValue_slew ) | ||
| 2842 | { | ||
| 2843 | // get data pointer | ||
| 2844 | t_CKVEC3 * vec3 = (t_CKVEC3 *)SELF; | ||
| 2845 | // get goal | ||
| 2846 | t_CKDUR goalAndValue = GET_NEXT_DUR(ARGS); | ||
| 2847 | // get slew | ||
| 2848 | t_CKDUR slew = GET_NEXT_DUR(ARGS); | ||
| 2849 | // set goal and value | ||
| 2850 | vec3->y = vec3->x = goalAndValue; | ||
| 2851 | // set slew | ||
| 2852 | vec3->z = slew; | ||
| 2853 | } | ||
| 2854 | |||
| 2855 | |||
| 2856 | //----------------------------------------------------------------------------- | ||
| 2857 | // vec4 API | ||
| 2858 | //----------------------------------------------------------------------------- | ||
| 2859 | CK_DLL_MFUN( vec4_set ) | ||
| 2860 | { | ||
| 2861 | // HACK: this is a particularly horrid cast from (Chuck_Object *) | ||
| 2862 | // t_CKVEC3 is neither a super- or sub-class of Chuck_Object... | ||
| 2863 | t_CKVEC4 * vec3 = (t_CKVEC4 *)SELF; | ||
| 2864 | // get index | ||
| 2865 | vec3->x = GET_NEXT_FLOAT(ARGS); | ||
| 2866 | vec3->y = GET_NEXT_FLOAT(ARGS); | ||
| 2867 | vec3->z = GET_NEXT_FLOAT(ARGS); | ||
| 2868 | vec3->w = GET_NEXT_FLOAT(ARGS); | ||
| 2869 | } | ||
| 2870 | |||
| 2871 | CK_DLL_MFUN( vec4_setAll ) | ||
| 2872 | { | ||
| 2873 | // get data pointer | ||
| 2874 | t_CKVEC4 * vec4 = (t_CKVEC4 *)SELF; | ||
| 2875 | // get index | ||
| 2876 | vec4->x = vec4->y = vec4->z = vec4->w = GET_NEXT_FLOAT(ARGS); | ||
| 2877 | } | ||
| 2878 | |||
| 2879 | CK_DLL_MFUN( vec4_magnitude ) | ||
| 2880 | { | ||
| 2881 | // get data pointer | ||
| 2882 | t_CKVEC4 * vec4 = (t_CKVEC4 *)SELF; | ||
| 2883 | // compute magnitude | ||
| 2884 | t_CKFLOAT mag = ::sqrt( vec4->x*vec4->x + vec4->y*vec4->y | ||
| 2885 | + vec4->z*vec4->z + vec4->w*vec4->w ); | ||
| 2886 | // return | ||
| 2887 | RETURN->v_float = mag; | ||
| 2888 | } | ||
| 2889 | |||
| 2890 | CK_DLL_MFUN( vec4_normalize ) | ||
| 2891 | { | ||
| 2892 | // get data pointer | ||
| 2893 | t_CKVEC4 * vec4 = (t_CKVEC4 *)SELF; | ||
| 2894 | // compute magnitude | ||
| 2895 | t_CKFLOAT mag = ::sqrt( vec4->x*vec4->x + vec4->y*vec4->y | ||
| 2896 | + vec4->z*vec4->z + vec4->w*vec4->w ); | ||
| 2897 | // check for zero | ||
| 2898 | if( mag > 0 ) | ||
| 2899 | { | ||
| 2900 | vec4->x /= mag; | ||
| 2901 | vec4->y /= mag; | ||
| 2902 | vec4->z /= mag; | ||
| 2903 | vec4->w /= mag; | ||
| 2904 | } | ||
| 2905 | } | ||
| 2906 | |||
| 2907 | |||
| 2908 | //----------------------------------------------------------------------------- | ||
| 2909 | // IO API | ||
| 2910 | //----------------------------------------------------------------------------- | ||
| 2911 | CK_DLL_MFUN( io_dummy ) | ||
| 2912 | { | ||
| 2913 | EM_error3( "(IO): internal error! inside an abstract function! help!" ); | ||
| 2914 | EM_error3( " note: please hunt down someone (e.g., Ge) to fix this..." ); | ||
| 2915 | assert( FALSE ); | ||
| 2916 | RETURN->v_int = 0; | ||
| 2917 | } | ||
| 2918 | |||
| 2919 | CK_DLL_SFUN( io_newline ) | ||
| 2920 | { | ||
| 2921 | RETURN->v_string = g_newline; | ||
| 2922 | } | ||
| 2923 | |||
| 2924 | |||
| 2925 | //----------------------------------------------------------------------------- | ||
| 2926 | // FileIO API | ||
| 2927 | //----------------------------------------------------------------------------- | ||
| 2928 | CK_DLL_CTOR( fileio_ctor ) | ||
| 2929 | { } | ||
| 2930 | |||
| 2931 | CK_DLL_DTOR( fileio_dtor ) | ||
| 2932 | { } | ||
| 2933 | |||
| 2934 | CK_DLL_MFUN( fileio_open ) | ||
| 2935 | { | ||
| 2936 | std::string filename = GET_NEXT_STRING(ARGS)->str(); | ||
| 2937 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 2938 | t_CKINT default_flags = | ||
| 2939 | Chuck_IO_File::FLAG_READ_WRITE | Chuck_IO_File::TYPE_ASCII; | ||
| 2940 | |||
| 2941 | RETURN->v_int = f->open(filename, default_flags); | ||
| 2942 | } | ||
| 2943 | |||
| 2944 | CK_DLL_MFUN( fileio_openflags ) | ||
| 2945 | { | ||
| 2946 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 2947 | std::string filename = GET_NEXT_STRING(ARGS)->str(); | ||
| 2948 | t_CKINT flags = GET_NEXT_INT(ARGS); | ||
| 2949 | |||
| 2950 | RETURN->v_int = f->open(filename, flags); | ||
| 2951 | } | ||
| 2952 | |||
| 2953 | CK_DLL_MFUN( fileio_close ) | ||
| 2954 | { | ||
| 2955 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 2956 | f->close(); | ||
| 2957 | } | ||
| 2958 | |||
| 2959 | CK_DLL_MFUN( fileio_good ) | ||
| 2960 | { | ||
| 2961 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 2962 | RETURN->v_int = f->good(); | ||
| 2963 | } | ||
| 2964 | |||
| 2965 | CK_DLL_MFUN( fileio_flush ) | ||
| 2966 | { | ||
| 2967 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 2968 | f->flush(); | ||
| 2969 | } | ||
| 2970 | |||
| 2971 | CK_DLL_MFUN( fileio_getmode ) | ||
| 2972 | { | ||
| 2973 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 2974 | RETURN->v_int = f->mode(); | ||
| 2975 | } | ||
| 2976 | |||
| 2977 | CK_DLL_MFUN( fileio_setmode ) | ||
| 2978 | { | ||
| 2979 | t_CKINT flag = GET_NEXT_INT(ARGS); | ||
| 2980 | |||
| 2981 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 2982 | f->mode( flag ); | ||
| 2983 | RETURN->v_int = 0; | ||
| 2984 | } | ||
| 2985 | |||
| 2986 | CK_DLL_MFUN( fileio_size ) | ||
| 2987 | { | ||
| 2988 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 2989 | RETURN->v_int = f->size(); | ||
| 2990 | } | ||
| 2991 | |||
| 2992 | CK_DLL_MFUN( fileio_seek ) | ||
| 2993 | { | ||
| 2994 | t_CKINT pos = GET_NEXT_INT(ARGS); | ||
| 2995 | |||
| 2996 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 2997 | f->seek(pos); | ||
| 2998 | } | ||
| 2999 | |||
| 3000 | CK_DLL_MFUN( fileio_tell ) | ||
| 3001 | { | ||
| 3002 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 3003 | RETURN->v_int = f->tell(); | ||
| 3004 | } | ||
| 3005 | |||
| 3006 | CK_DLL_MFUN( fileio_isdir ) | ||
| 3007 | { | ||
| 3008 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 3009 | RETURN->v_int = f->isDir(); | ||
| 3010 | } | ||
| 3011 | |||
| 3012 | CK_DLL_MFUN( fileio_dirlist ) | ||
| 3013 | { | ||
| 3014 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 3015 | Chuck_Array4 * a = f->dirList(); | ||
| 3016 | RETURN->v_object = a; | ||
| 3017 | } | ||
| 3018 | |||
| 3019 | /* | ||
| 3020 | CK_DLL_MFUN( fileio_read ) | ||
| 3021 | { | ||
| 3022 | t_CKINT len = GET_NEXT_INT(ARGS); | ||
| 3023 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 3024 | |||
| 3025 | Chuck_String * s = f->read( len ); | ||
| 3026 | RETURN->v_object = s; | ||
| 3027 | } | ||
| 3028 | */ | ||
| 3029 | |||
| 3030 | CK_DLL_MFUN( fileio_readline ) | ||
| 3031 | { | ||
| 3032 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 3033 | Chuck_String * ret = f->readLine(); | ||
| 3034 | RETURN->v_object = ret; | ||
| 3035 | } | ||
| 3036 | |||
| 3037 | CK_DLL_MFUN( fileio_readint ) | ||
| 3038 | { | ||
| 3039 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 3040 | t_CKINT defaultflags = Chuck_IO::INT32; | ||
| 3041 | |||
| 3042 | /* (ATODO: doesn't look like asynchronous reading will work) | ||
| 3043 | if (f->mode() == Chuck_IO::MODE_ASYNC) | ||
| 3044 | { | ||
| 3045 | // set up arguments | ||
| 3046 | Chuck_IO::async_args *args = new Chuck_IO::async_args; | ||
| 3047 | args->RETURN = (void *)RETURN; | ||
| 3048 | args->fileio_obj = f; | ||
| 3049 | args->intArg = defaultflags; | ||
| 3050 | // set shred to wait for I/O completion | ||
| 3051 | f->m_asyncEvent->wait( SHRED, SHRED->vm_ref ); | ||
| 3052 | // start thread | ||
| 3053 | bool ret = f->m_thread->start( f->readInt_thread, (void *)args ); | ||
| 3054 | if (!ret) { | ||
| 3055 | cerr << "m_thread->start failed; recreating m_thread" << endl; | ||
| 3056 | delete f->m_thread; | ||
| 3057 | f->m_thread = new XThread; | ||
| 3058 | ret = f->m_thread->start( f->readInt_thread, (void *)args ); | ||
| 3059 | if (!ret) { | ||
| 3060 | EM_error3( "(FileIO): failed to start thread for asynchronous mode I/O" ); | ||
| 3061 | } | ||
| 3062 | } | ||
| 3063 | } else {*/ | ||
| 3064 | t_CKINT ret = f->readInt( defaultflags ); | ||
| 3065 | RETURN->v_int = ret; | ||
| 3066 | //} | ||
| 3067 | // ATODO: Debug | ||
| 3068 | //sleep(1); | ||
| 3069 | //cerr << "fileio_readint exiting" << endl; | ||
| 3070 | } | ||
| 3071 | |||
| 3072 | CK_DLL_MFUN( fileio_readintflags ) | ||
| 3073 | { | ||
| 3074 | t_CKINT flags = GET_NEXT_INT(ARGS); | ||
| 3075 | |||
| 3076 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 3077 | t_CKINT ret = f->readInt( flags ); | ||
| 3078 | |||
| 3079 | RETURN->v_int = ret; | ||
| 3080 | } | ||
| 3081 | |||
| 3082 | CK_DLL_MFUN( fileio_readfloat ) | ||
| 3083 | { | ||
| 3084 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 3085 | t_CKFLOAT ret = f->readFloat(); | ||
| 3086 | RETURN->v_float = ret; | ||
| 3087 | } | ||
| 3088 | |||
| 3089 | CK_DLL_MFUN( fileio_eof ) | ||
| 3090 | { | ||
| 3091 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 3092 | t_CKBOOL ret = f->eof(); | ||
| 3093 | RETURN->v_int = ret; | ||
| 3094 | } | ||
| 3095 | |||
| 3096 | CK_DLL_MFUN( fileio_more ) | ||
| 3097 | { | ||
| 3098 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 3099 | t_CKBOOL ret = !f->eof(); | ||
| 3100 | RETURN->v_int = ret; | ||
| 3101 | } | ||
| 3102 | |||
| 3103 | CK_DLL_MFUN( fileio_writestring ) | ||
| 3104 | { | ||
| 3105 | std::string val = GET_NEXT_STRING(ARGS)->str(); | ||
| 3106 | |||
| 3107 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 3108 | if (f->mode() == Chuck_IO::MODE_ASYNC) | ||
| 3109 | { | ||
| 3110 | // set up arguments | ||
| 3111 | Chuck_IO::async_args *args = new Chuck_IO::async_args; | ||
| 3112 | args->RETURN = (void *)RETURN; | ||
| 3113 | args->fileio_obj = f; | ||
| 3114 | args->stringArg = std::string(val); | ||
| 3115 | // set shred to wait for I/O completion | ||
| 3116 | assert( SHRED != NULL ); | ||
| 3117 | f->m_asyncEvent->wait( SHRED, SHRED->vm_ref ); | ||
| 3118 | // start thread | ||
| 3119 | bool ret = f->m_thread->start( f->writeStr_thread, (void *)args ); | ||
| 3120 | if (!ret) { | ||
| 3121 | // for some reason, the XThread object needs to be | ||
| 3122 | // deleted and reconstructed every time after call #375 | ||
| 3123 | delete f->m_thread; | ||
| 3124 | f->m_thread = new XThread; | ||
| 3125 | ret = f->m_thread->start( f->writeStr_thread, (void *)args ); | ||
| 3126 | if (!ret) { | ||
| 3127 | EM_error3( "(FileIO): failed to start thread for asynchronous mode I/O" ); | ||
| 3128 | } | ||
| 3129 | } | ||
| 3130 | } else { | ||
| 3131 | f->write(val); | ||
| 3132 | } | ||
| 3133 | } | ||
| 3134 | |||
| 3135 | CK_DLL_MFUN( fileio_writeint ) | ||
| 3136 | { | ||
| 3137 | t_CKINT val = GET_NEXT_INT(ARGS); | ||
| 3138 | |||
| 3139 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 3140 | if (f->mode() == Chuck_IO::MODE_ASYNC) | ||
| 3141 | { | ||
| 3142 | // set up arguments | ||
| 3143 | Chuck_IO::async_args *args = new Chuck_IO::async_args; | ||
| 3144 | args->RETURN = (void *)RETURN; | ||
| 3145 | args->fileio_obj = f; | ||
| 3146 | args->intArg = val; | ||
| 3147 | // set shred to wait for I/O completion | ||
| 3148 | assert( SHRED != NULL ); | ||
| 3149 | f->m_asyncEvent->wait( SHRED, SHRED->vm_ref ); | ||
| 3150 | // start thread | ||
| 3151 | bool ret = f->m_thread->start( f->writeInt_thread, (void *)args ); | ||
| 3152 | if (!ret) { | ||
| 3153 | // for some reason, the XThread object needs to be | ||
| 3154 | // deleted and reconstructed every time after call #375 | ||
| 3155 | delete f->m_thread; | ||
| 3156 | f->m_thread = new XThread; | ||
| 3157 | ret = f->m_thread->start( f->writeInt_thread, (void *)args ); | ||
| 3158 | if (!ret) { | ||
| 3159 | EM_error3( "(FileIO): failed to start thread for asynchronous mode I/O" ); | ||
| 3160 | } | ||
| 3161 | } | ||
| 3162 | } else { | ||
| 3163 | f->write(val); | ||
| 3164 | } | ||
| 3165 | } | ||
| 3166 | |||
| 3167 | CK_DLL_MFUN( fileio_writeintflags ) | ||
| 3168 | { | ||
| 3169 | t_CKINT val = GET_NEXT_INT(ARGS); | ||
| 3170 | t_CKINT flags = GET_NEXT_INT(ARGS); | ||
| 3171 | |||
| 3172 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 3173 | if (f->mode() == Chuck_IO::MODE_ASYNC) | ||
| 3174 | { | ||
| 3175 | // TODO: pass flags in args | ||
| 3176 | // set up arguments | ||
| 3177 | Chuck_IO::async_args *args = new Chuck_IO::async_args; | ||
| 3178 | args->RETURN = (void *)RETURN; | ||
| 3179 | args->fileio_obj = f; | ||
| 3180 | args->intArg = val; | ||
| 3181 | // set shred to wait for I/O completion | ||
| 3182 | assert( SHRED != NULL ); | ||
| 3183 | f->m_asyncEvent->wait( SHRED, SHRED->vm_ref ); | ||
| 3184 | // start thread | ||
| 3185 | bool ret = f->m_thread->start( f->writeInt_thread, (void *)args ); | ||
| 3186 | if (!ret) { | ||
| 3187 | // for some reason, the XThread object needs to be | ||
| 3188 | // deleted and reconstructed every time after call #375 | ||
| 3189 | delete f->m_thread; | ||
| 3190 | f->m_thread = new XThread; | ||
| 3191 | ret = f->m_thread->start( f->writeInt_thread, (void *)args ); | ||
| 3192 | if (!ret) { | ||
| 3193 | EM_error3( "(FileIO): failed to start thread for asynchronous mode I/O" ); | ||
| 3194 | } | ||
| 3195 | } | ||
| 3196 | } else { | ||
| 3197 | f->write(val, flags); | ||
| 3198 | } | ||
| 3199 | } | ||
| 3200 | |||
| 3201 | CK_DLL_MFUN( fileio_writefloat ) | ||
| 3202 | { | ||
| 3203 | t_CKFLOAT val = GET_NEXT_FLOAT(ARGS); | ||
| 3204 | |||
| 3205 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 3206 | if (f->mode() == Chuck_IO::MODE_ASYNC) | ||
| 3207 | { | ||
| 3208 | // set up arguments | ||
| 3209 | Chuck_IO::async_args *args = new Chuck_IO::async_args; | ||
| 3210 | args->RETURN = (void *)RETURN; | ||
| 3211 | args->fileio_obj = f; | ||
| 3212 | args->floatArg = val; | ||
| 3213 | // set shred to wait for I/O completion | ||
| 3214 | assert( SHRED != NULL ); | ||
| 3215 | f->m_asyncEvent->wait( SHRED, SHRED->vm_ref ); | ||
| 3216 | // start thread | ||
| 3217 | bool ret = f->m_thread->start( f->writeFloat_thread, (void *)args ); | ||
| 3218 | if (!ret) { | ||
| 3219 | // for some reason, the XThread object needs to be | ||
| 3220 | // deleted and reconstructed every time after call #375 | ||
| 3221 | delete f->m_thread; | ||
| 3222 | f->m_thread = new XThread; | ||
| 3223 | ret = f->m_thread->start( f->writeFloat_thread, (void *)args ); | ||
| 3224 | if (!ret) { | ||
| 3225 | EM_error3( "(FileIO): failed to start thread for asynchronous mode I/O" ); | ||
| 3226 | } | ||
| 3227 | } | ||
| 3228 | } else { | ||
| 3229 | f->write(val); | ||
| 3230 | } | ||
| 3231 | } | ||
| 3232 | |||
| 3233 | |||
| 3234 | //----------------------------------------------------------------------------- | ||
| 3235 | // Chout API | ||
| 3236 | //----------------------------------------------------------------------------- | ||
| 3237 | CK_DLL_MFUN( chout_close ) | ||
| 3238 | { | ||
| 3239 | // problem | ||
| 3240 | CK_FPRINTF_STDERR( "[chuck]: cannot close 'chout'...\n" ); | ||
| 3241 | Chuck_IO_Chout * c = SHRED->vm_ref->chout(); | ||
| 3242 | c->close(); | ||
| 3243 | } | ||
| 3244 | |||
| 3245 | CK_DLL_MFUN( chout_good ) | ||
| 3246 | { | ||
| 3247 | Chuck_IO_Chout * c = SHRED->vm_ref->chout(); | ||
| 3248 | RETURN->v_int = c->good(); | ||
| 3249 | } | ||
| 3250 | |||
| 3251 | CK_DLL_MFUN( chout_flush ) | ||
| 3252 | { | ||
| 3253 | Chuck_IO_Chout * c = SHRED->vm_ref->chout(); | ||
| 3254 | c->flush(); | ||
| 3255 | } | ||
| 3256 | |||
| 3257 | CK_DLL_MFUN( chout_getmode ) | ||
| 3258 | { | ||
| 3259 | // problem | ||
| 3260 | Chuck_IO_Chout * c = SHRED->vm_ref->chout(); | ||
| 3261 | RETURN->v_int = c->mode(); | ||
| 3262 | } | ||
| 3263 | |||
| 3264 | CK_DLL_MFUN( chout_setmode ) | ||
| 3265 | { | ||
| 3266 | Chuck_IO_Chout * c = SHRED->vm_ref->chout(); | ||
| 3267 | c->mode( GET_NEXT_INT(ARGS) ); | ||
| 3268 | RETURN->v_int = c->mode(); | ||
| 3269 | } | ||
| 3270 | |||
| 3271 | /* | ||
| 3272 | CK_DLL_MFUN( chout_read ) | ||
| 3273 | { | ||
| 3274 | t_CKINT len = GET_NEXT_INT(ARGS); | ||
| 3275 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 3276 | |||
| 3277 | Chuck_String * s = f->read( len ); | ||
| 3278 | RETURN->v_object = s; | ||
| 3279 | } | ||
| 3280 | */ | ||
| 3281 | |||
| 3282 | CK_DLL_MFUN( chout_readline ) | ||
| 3283 | { | ||
| 3284 | Chuck_IO_Chout * c = SHRED->vm_ref->chout(); | ||
| 3285 | Chuck_String * ret = c->readLine(); | ||
| 3286 | RETURN->v_object = ret; | ||
| 3287 | } | ||
| 3288 | |||
| 3289 | CK_DLL_MFUN( chout_readint ) | ||
| 3290 | { | ||
| 3291 | Chuck_IO_Chout * c = SHRED->vm_ref->chout(); | ||
| 3292 | RETURN->v_int = c->readInt( Chuck_IO::INT32 ); | ||
| 3293 | } | ||
| 3294 | |||
| 3295 | CK_DLL_MFUN( chout_readintflags ) | ||
| 3296 | { | ||
| 3297 | t_CKINT flags = GET_NEXT_INT(ARGS); | ||
| 3298 | |||
| 3299 | Chuck_IO_Chout * c = SHRED->vm_ref->chout(); | ||
| 3300 | t_CKINT ret = c->readInt( flags ); | ||
| 3301 | |||
| 3302 | RETURN->v_int = ret; | ||
| 3303 | } | ||
| 3304 | |||
| 3305 | CK_DLL_MFUN( chout_readfloat ) | ||
| 3306 | { | ||
| 3307 | Chuck_IO_Chout * c = SHRED->vm_ref->chout(); | ||
| 3308 | t_CKFLOAT ret = c->readFloat(); | ||
| 3309 | RETURN->v_float = ret; | ||
| 3310 | } | ||
| 3311 | |||
| 3312 | CK_DLL_MFUN( chout_eof ) | ||
| 3313 | { | ||
| 3314 | Chuck_IO_Chout * c = SHRED->vm_ref->chout(); | ||
| 3315 | t_CKBOOL ret = c->eof(); | ||
| 3316 | RETURN->v_int = ret; | ||
| 3317 | } | ||
| 3318 | |||
| 3319 | CK_DLL_MFUN( chout_more ) | ||
| 3320 | { | ||
| 3321 | Chuck_IO_Chout * c = SHRED->vm_ref->chout(); | ||
| 3322 | t_CKBOOL ret = !c->eof(); | ||
| 3323 | RETURN->v_int = ret; | ||
| 3324 | } | ||
| 3325 | |||
| 3326 | CK_DLL_MFUN( chout_writestring ) | ||
| 3327 | { | ||
| 3328 | std::string val = GET_NEXT_STRING(ARGS)->str(); | ||
| 3329 | |||
| 3330 | Chuck_IO_Chout * c = SHRED->vm_ref->chout(); | ||
| 3331 | c->write( val ); | ||
| 3332 | } | ||
| 3333 | |||
| 3334 | CK_DLL_MFUN( chout_writeint ) | ||
| 3335 | { | ||
| 3336 | t_CKINT val = GET_NEXT_INT(ARGS); | ||
| 3337 | |||
| 3338 | Chuck_IO_Chout * c = SHRED->vm_ref->chout(); | ||
| 3339 | c->write(val); | ||
| 3340 | } | ||
| 3341 | |||
| 3342 | CK_DLL_MFUN( chout_writefloat ) | ||
| 3343 | { | ||
| 3344 | t_CKFLOAT val = GET_NEXT_FLOAT(ARGS); | ||
| 3345 | |||
| 3346 | Chuck_IO_Chout * c = SHRED->vm_ref->chout(); | ||
| 3347 | c->write(val); | ||
| 3348 | } | ||
| 3349 | |||
| 3350 | |||
| 3351 | |||
| 3352 | |||
| 3353 | //----------------------------------------------------------------------------- | ||
| 3354 | // Cherr API | ||
| 3355 | //----------------------------------------------------------------------------- | ||
| 3356 | CK_DLL_MFUN( cherr_close ) | ||
| 3357 | { | ||
| 3358 | // problem | ||
| 3359 | CK_FPRINTF_STDERR( "[chuck]: cannot close 'cherr'...\n" ); | ||
| 3360 | Chuck_IO_Cherr * c = SHRED->vm_ref->cherr(); | ||
| 3361 | c->close(); | ||
| 3362 | } | ||
| 3363 | |||
| 3364 | CK_DLL_MFUN( cherr_good ) | ||
| 3365 | { | ||
| 3366 | Chuck_IO_Cherr * c = SHRED->vm_ref->cherr(); | ||
| 3367 | RETURN->v_int = c->good(); | ||
| 3368 | } | ||
| 3369 | |||
| 3370 | CK_DLL_MFUN( cherr_flush ) | ||
| 3371 | { | ||
| 3372 | Chuck_IO_Cherr * c = SHRED->vm_ref->cherr(); | ||
| 3373 | c->flush(); | ||
| 3374 | } | ||
| 3375 | |||
| 3376 | CK_DLL_MFUN( cherr_getmode ) | ||
| 3377 | { | ||
| 3378 | // problem | ||
| 3379 | Chuck_IO_Cherr * c = SHRED->vm_ref->cherr(); | ||
| 3380 | RETURN->v_int = c->mode(); | ||
| 3381 | } | ||
| 3382 | |||
| 3383 | CK_DLL_MFUN( cherr_setmode ) | ||
| 3384 | { | ||
| 3385 | Chuck_IO_Cherr * c = SHRED->vm_ref->cherr(); | ||
| 3386 | c->mode( GET_NEXT_INT(ARGS) ); | ||
| 3387 | RETURN->v_int = c->mode(); | ||
| 3388 | } | ||
| 3389 | |||
| 3390 | /* | ||
| 3391 | CK_DLL_MFUN( cherr_read ) | ||
| 3392 | { | ||
| 3393 | t_CKINT len = GET_NEXT_INT(ARGS); | ||
| 3394 | Chuck_IO_File * f = (Chuck_IO_File *)SELF; | ||
| 3395 | |||
| 3396 | Chuck_String * s = f->read( len ); | ||
| 3397 | RETURN->v_object = s; | ||
| 3398 | } | ||
| 3399 | */ | ||
| 3400 | |||
| 3401 | CK_DLL_MFUN( cherr_readline ) | ||
| 3402 | { | ||
| 3403 | Chuck_IO_Cherr * c = SHRED->vm_ref->cherr(); | ||
| 3404 | Chuck_String * ret = c->readLine(); | ||
| 3405 | RETURN->v_object = ret; | ||
| 3406 | } | ||
| 3407 | |||
| 3408 | CK_DLL_MFUN( cherr_readint ) | ||
| 3409 | { | ||
| 3410 | Chuck_IO_Cherr * c = SHRED->vm_ref->cherr(); | ||
| 3411 | RETURN->v_int = c->readInt( Chuck_IO::INT32 ); | ||
| 3412 | } | ||
| 3413 | |||
| 3414 | CK_DLL_MFUN( cherr_readintflags ) | ||
| 3415 | { | ||
| 3416 | t_CKINT flags = GET_NEXT_INT(ARGS); | ||
| 3417 | |||
| 3418 | Chuck_IO_Cherr * c = SHRED->vm_ref->cherr(); | ||
| 3419 | t_CKINT ret = c->readInt( flags ); | ||
| 3420 | |||
| 3421 | RETURN->v_int = ret; | ||
| 3422 | } | ||
| 3423 | |||
| 3424 | CK_DLL_MFUN( cherr_readfloat ) | ||
| 3425 | { | ||
| 3426 | Chuck_IO_Cherr * c = SHRED->vm_ref->cherr(); | ||
| 3427 | t_CKFLOAT ret = c->readFloat(); | ||
| 3428 | RETURN->v_float = ret; | ||
| 3429 | } | ||
| 3430 | |||
| 3431 | CK_DLL_MFUN( cherr_eof ) | ||
| 3432 | { | ||
| 3433 | Chuck_IO_Cherr * c = SHRED->vm_ref->cherr(); | ||
| 3434 | t_CKBOOL ret = c->eof(); | ||
| 3435 | RETURN->v_int = ret; | ||
| 3436 | } | ||
| 3437 | |||
| 3438 | CK_DLL_MFUN( cherr_more ) | ||
| 3439 | { | ||
| 3440 | Chuck_IO_Cherr * c = SHRED->vm_ref->cherr(); | ||
| 3441 | t_CKBOOL ret = !c->eof(); | ||
| 3442 | RETURN->v_int = ret; | ||
| 3443 | } | ||
| 3444 | |||
| 3445 | CK_DLL_MFUN( cherr_writestring ) | ||
| 3446 | { | ||
| 3447 | std::string val = GET_NEXT_STRING(ARGS)->str(); | ||
| 3448 | |||
| 3449 | Chuck_IO_Cherr * c = SHRED->vm_ref->cherr(); | ||
| 3450 | c->write( val ); | ||
| 3451 | } | ||
| 3452 | |||
| 3453 | CK_DLL_MFUN( cherr_writeint ) | ||
| 3454 | { | ||
| 3455 | t_CKINT val = GET_NEXT_INT(ARGS); | ||
| 3456 | |||
| 3457 | Chuck_IO_Chout * c = SHRED->vm_ref->chout(); | ||
| 3458 | c->write(val); | ||
| 3459 | } | ||
| 3460 | |||
| 3461 | CK_DLL_MFUN( cherr_writefloat ) | ||
| 3462 | { | ||
| 3463 | t_CKFLOAT val = GET_NEXT_FLOAT(ARGS); | ||
| 3464 | |||
| 3465 | Chuck_IO_Cherr * c = SHRED->vm_ref->cherr(); | ||
| 3466 | c->write(val); | ||
| 3467 | } | ||
| 3468 | |||
| 3469 | |||
| 3470 | |||
| 3471 | |||
| 3472 | //----------------------------------------------------------------------------- | ||
| 3473 | // Shred API | ||
| 3474 | //----------------------------------------------------------------------------- | ||
| 3475 | |||
| 3476 | //CK_DLL_CTOR( shred_ctor ); | ||
| 3477 | //CK_DLL_DTOR( shred_dtor ); // | ||
| 3478 | |||
| 3479 | CK_DLL_MFUN( shred_exit ) | ||
| 3480 | { | ||
| 3481 | Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF; | ||
| 3482 | // end the shred | ||
| 3483 | derhs->is_done = TRUE; | ||
| 3484 | derhs->is_running = FALSE; | ||
| 3485 | } | ||
| 3486 | |||
| 3487 | CK_DLL_MFUN( shred_running ) | ||
| 3488 | { | ||
| 3489 | Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF; | ||
| 3490 | RETURN->v_int = derhs->is_running; | ||
| 3491 | } | ||
| 3492 | |||
| 3493 | CK_DLL_MFUN( shred_done ) | ||
| 3494 | { | ||
| 3495 | Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF; | ||
| 3496 | RETURN->v_int = derhs->is_done; | ||
| 3497 | } | ||
| 3498 | |||
| 3499 | CK_DLL_MFUN( shred_clone ) | ||
| 3500 | { | ||
| 3501 | } | ||
| 3502 | |||
| 3503 | CK_DLL_MFUN( shred_id ) | ||
| 3504 | { | ||
| 3505 | Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF; | ||
| 3506 | // return the id | ||
| 3507 | RETURN->v_int = derhs->xid; | ||
| 3508 | } | ||
| 3509 | |||
| 3510 | CK_DLL_MFUN( shred_yield ) | ||
| 3511 | { | ||
| 3512 | Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF; | ||
| 3513 | Chuck_VM * vm = derhs->vm_ref; | ||
| 3514 | |||
| 3515 | // suspend | ||
| 3516 | derhs->is_running = FALSE; | ||
| 3517 | // reshredule | ||
| 3518 | vm->shreduler()->shredule( derhs, derhs->now ); | ||
| 3519 | } | ||
| 3520 | |||
| 3521 | CK_DLL_MFUN( shred_numArgs ) | ||
| 3522 | { | ||
| 3523 | Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF; | ||
| 3524 | |||
| 3525 | // get the number of arguments | ||
| 3526 | RETURN->v_int = derhs->args.size(); | ||
| 3527 | } | ||
| 3528 | |||
| 3529 | CK_DLL_MFUN( shred_getArg ) | ||
| 3530 | { | ||
| 3531 | Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF; | ||
| 3532 | |||
| 3533 | // get index | ||
| 3534 | t_CKINT i = GET_NEXT_INT(ARGS); | ||
| 3535 | // total | ||
| 3536 | t_CKINT num = derhs->args.size(); | ||
| 3537 | |||
| 3538 | Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED ); | ||
| 3539 | str->set( ( i < num ? derhs->args[i] : "" ) ); | ||
| 3540 | RETURN->v_string = str; | ||
| 3541 | } | ||
| 3542 | |||
| 3543 | CK_DLL_MFUN( shred_sourcePath ) // added 1.3.0.0 | ||
| 3544 | { | ||
| 3545 | Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF; | ||
| 3546 | |||
| 3547 | Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED ); | ||
| 3548 | str->set( derhs->code->filename ); | ||
| 3549 | RETURN->v_string = str; | ||
| 3550 | } | ||
| 3551 | |||
| 3552 | CK_DLL_MFUN( shred_sourceDir ) // added 1.3.0.0 | ||
| 3553 | { | ||
| 3554 | Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF; | ||
| 3555 | |||
| 3556 | Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED ); | ||
| 3557 | |||
| 3558 | str->set( extract_filepath_dir(derhs->code->filename) ); | ||
| 3559 | |||
| 3560 | RETURN->v_string = str; | ||
| 3561 | } | ||
| 3562 | |||
| 3563 | CK_DLL_MFUN( shred_sourceDir2 ) // added 1.3.2.0 | ||
| 3564 | { | ||
| 3565 | Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF; | ||
| 3566 | // get num up | ||
| 3567 | t_CKINT i = GET_NEXT_INT(ARGS); | ||
| 3568 | // abs | ||
| 3569 | if( i < 0 ) i = -i; | ||
| 3570 | |||
| 3571 | // new chuck string | ||
| 3572 | Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED ); | ||
| 3573 | // set the content | ||
| 3574 | str->set( extract_filepath_dir(derhs->code->filename) ); | ||
| 3575 | // up | ||
| 3576 | str->set( dir_go_up( str->str(), i ) ); | ||
| 3577 | |||
| 3578 | RETURN->v_string = str; | ||
| 3579 | } | ||
| 3580 | |||
| 3581 | |||
| 3582 | CK_DLL_SFUN( shred_fromId ) // added 1.3.2.0 | ||
| 3583 | { | ||
| 3584 | t_CKINT shred_id = GET_NEXT_INT(ARGS); | ||
| 3585 | |||
| 3586 | Chuck_VM_Shred * derhs = SHRED->vm_ref->shreduler()->lookup(shred_id); | ||
| 3587 | |||
| 3588 | RETURN->v_object = derhs; | ||
| 3589 | } | ||
| 3590 | |||
| 3591 | |||
| 3592 | CK_DLL_MFUN( string_length ) | ||
| 3593 | { | ||
| 3594 | Chuck_String * s = (Chuck_String *)SELF; | ||
| 3595 | RETURN->v_int = s->str().length(); | ||
| 3596 | } | ||
| 3597 | |||
| 3598 | CK_DLL_MFUN( string_upper ) | ||
| 3599 | { | ||
| 3600 | Chuck_String * s = (Chuck_String *)SELF; | ||
| 3601 | Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED ); | ||
| 3602 | str->set( toupper( s->str() ) ); | ||
| 3603 | RETURN->v_string = str; | ||
| 3604 | } | ||
| 3605 | |||
| 3606 | CK_DLL_MFUN( string_lower ) | ||
| 3607 | { | ||
| 3608 | Chuck_String * s = (Chuck_String *)SELF; | ||
| 3609 | Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED ); | ||
| 3610 | str->set( tolower( s->str() ) ); | ||
| 3611 | RETURN->v_string = str; | ||
| 3612 | } | ||
| 3613 | |||
| 3614 | CK_DLL_MFUN( string_ltrim ) | ||
| 3615 | { | ||
| 3616 | Chuck_String * s = (Chuck_String *)SELF; | ||
| 3617 | Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED ); | ||
| 3618 | str->set( ltrim( s->str() ) ); | ||
| 3619 | RETURN->v_string = str; | ||
| 3620 | } | ||
| 3621 | |||
| 3622 | CK_DLL_MFUN( string_rtrim ) | ||
| 3623 | { | ||
| 3624 | Chuck_String * s = (Chuck_String *)SELF; | ||
| 3625 | Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED ); | ||
| 3626 | str->set( rtrim( s->str() ) ); | ||
| 3627 | RETURN->v_string = str; | ||
| 3628 | } | ||
| 3629 | |||
| 3630 | CK_DLL_MFUN( string_trim ) | ||
| 3631 | { | ||
| 3632 | Chuck_String * s = (Chuck_String *)SELF; | ||
| 3633 | Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED ); | ||
| 3634 | str->set( trim( s->str() ) ); | ||
| 3635 | RETURN->v_string = str; | ||
| 3636 | } | ||
| 3637 | |||
| 3638 | CK_DLL_MFUN( string_toString ) | ||
| 3639 | { | ||
| 3640 | Chuck_String * s = (Chuck_String *)SELF; | ||
| 3641 | RETURN->v_string = s; | ||
| 3642 | } | ||
| 3643 | |||
| 3644 | CK_DLL_MFUN(string_charAt) | ||
| 3645 | { | ||
| 3646 | Chuck_String * str = (Chuck_String *) SELF; | ||
| 3647 | t_CKINT index = GET_NEXT_INT(ARGS); | ||
| 3648 | |||
| 3649 | if(index < 0 || index >= str->str().length()) | ||
| 3650 | { | ||
| 3651 | throw_exception(SHRED, "IndexOutOfBoundsException", index); | ||
| 3652 | RETURN->v_int = -1; | ||
| 3653 | return; | ||
| 3654 | } | ||
| 3655 | |||
| 3656 | RETURN->v_int = str->str().at(index); | ||
| 3657 | } | ||
| 3658 | |||
| 3659 | CK_DLL_MFUN(string_setCharAt) | ||
| 3660 | { | ||
| 3661 | Chuck_String * str = (Chuck_String *) SELF; | ||
| 3662 | t_CKINT index = GET_NEXT_INT(ARGS); | ||
| 3663 | t_CKINT the_char = GET_NEXT_INT(ARGS); | ||
| 3664 | |||
| 3665 | if(index < 0 || index >= str->str().length()) | ||
| 3666 | { | ||
| 3667 | throw_exception(SHRED, "IndexOutOfBoundsException", index); | ||
| 3668 | RETURN->v_int = -1; | ||
| 3669 | return; | ||
| 3670 | } | ||
| 3671 | |||
| 3672 | // str->str.at(index) = the_char; | ||
| 3673 | std::string s = str->str(); | ||
| 3674 | s.at(index) = the_char; | ||
| 3675 | str->set( s ); | ||
| 3676 | RETURN->v_int = str->str().at(index); | ||
| 3677 | } | ||
| 3678 | |||
| 3679 | CK_DLL_MFUN(string_substring) | ||
| 3680 | { | ||
| 3681 | Chuck_String * str = (Chuck_String *) SELF; | ||
| 3682 | t_CKINT start = GET_NEXT_INT(ARGS); | ||
| 3683 | |||
| 3684 | if(start < 0 || start >= str->str().length()) | ||
| 3685 | { | ||
| 3686 | throw_exception(SHRED, "IndexOutOfBoundsException", start); | ||
| 3687 | RETURN->v_string = NULL; | ||
| 3688 | return; | ||
| 3689 | } | ||
| 3690 | |||
| 3691 | Chuck_String * ss = (Chuck_String *) instantiate_and_initialize_object(SHRED->vm_ref->env()->t_string, SHRED); | ||
| 3692 | ss->set( str->str().substr(start) ); | ||
| 3693 | |||
| 3694 | RETURN->v_string = ss; | ||
| 3695 | } | ||
| 3696 | |||
| 3697 | CK_DLL_MFUN(string_substringN) | ||
| 3698 | { | ||
| 3699 | Chuck_String * str = (Chuck_String *) SELF; | ||
| 3700 | t_CKINT start = GET_NEXT_INT(ARGS); | ||
| 3701 | t_CKINT length = GET_NEXT_INT(ARGS); | ||
| 3702 | |||
| 3703 | if(start < 0 || start >= str->str().length()) | ||
| 3704 | { | ||
| 3705 | throw_exception(SHRED, "IndexOutOfBoundsException", start); | ||
| 3706 | RETURN->v_string = NULL; | ||
| 3707 | return; | ||
| 3708 | } | ||
| 3709 | |||
| 3710 | if(length < 0 || start+length > str->str().length()) | ||
| 3711 | { | ||
| 3712 | throw_exception(SHRED, "IndexOutOfBoundsException", length); | ||
| 3713 | RETURN->v_string = NULL; | ||
| 3714 | return; | ||
| 3715 | } | ||
| 3716 | |||
| 3717 | Chuck_String * ss = (Chuck_String *) instantiate_and_initialize_object(SHRED->vm_ref->env()->t_string, SHRED); | ||
| 3718 | ss->set( str->str().substr(start, length) ); | ||
| 3719 | |||
| 3720 | RETURN->v_string = ss; | ||
| 3721 | } | ||
| 3722 | |||
| 3723 | CK_DLL_MFUN(string_insert) | ||
| 3724 | { | ||
| 3725 | Chuck_String * str = (Chuck_String *) SELF; | ||
| 3726 | t_CKINT position = GET_NEXT_INT(ARGS); | ||
| 3727 | Chuck_String * str2 = GET_NEXT_STRING(ARGS); | ||
| 3728 | |||
| 3729 | if(position < 0 || position >= str->str().length()) | ||
| 3730 | { | ||
| 3731 | throw_exception(SHRED, "IndexOutOfBoundsException", position); | ||
| 3732 | return; | ||
| 3733 | } | ||
| 3734 | if(str2 == NULL) | ||
| 3735 | { | ||
| 3736 | throw_exception(SHRED, "NullPointerException"); | ||
| 3737 | return; | ||
| 3738 | } | ||
| 3739 | |||
| 3740 | // str->str.insert(position, str2->str); | ||
| 3741 | std::string s = str->str(); | ||
| 3742 | s.insert( position, str2->str() ); | ||
| 3743 | str->set( s ); | ||
| 3744 | } | ||
| 3745 | |||
| 3746 | CK_DLL_MFUN(string_replace) | ||
| 3747 | { | ||
| 3748 | Chuck_String * str = (Chuck_String *) SELF; | ||
| 3749 | t_CKINT position = GET_NEXT_INT(ARGS); | ||
| 3750 | Chuck_String * str2 = GET_NEXT_STRING(ARGS); | ||
| 3751 | |||
| 3752 | if(position < 0 || position >= str->str().length()) | ||
| 3753 | { | ||
| 3754 | throw_exception(SHRED, "IndexOutOfBoundsException", position); | ||
| 3755 | return; | ||
| 3756 | } | ||
| 3757 | if(str2 == NULL) | ||
| 3758 | { | ||
| 3759 | throw_exception(SHRED, "NullPointerException"); | ||
| 3760 | return; | ||
| 3761 | } | ||
| 3762 | |||
| 3763 | string::size_type length; | ||
| 3764 | if(position + str2->str().length() > str->str().length()) | ||
| 3765 | length = str->str().length() - position; | ||
| 3766 | else | ||
| 3767 | length = str2->str().length(); | ||
| 3768 | |||
| 3769 | // str->str.replace(position, length, str2->str); | ||
| 3770 | std::string s = str->str(); | ||
| 3771 | s.replace( position, length, str2->str() ); | ||
| 3772 | str->set( s ); | ||
| 3773 | } | ||
| 3774 | |||
| 3775 | CK_DLL_MFUN(string_replaceN) | ||
| 3776 | { | ||
| 3777 | Chuck_String * str = (Chuck_String *) SELF; | ||
| 3778 | t_CKINT position = GET_NEXT_INT(ARGS); | ||
| 3779 | t_CKINT length = GET_NEXT_INT(ARGS); | ||
| 3780 | Chuck_String * str2 = GET_NEXT_STRING(ARGS); | ||
| 3781 | |||
| 3782 | if(position < 0 || position >= str->str().length()) | ||
| 3783 | { | ||
| 3784 | throw_exception(SHRED, "IndexOutOfBoundsException", position); | ||
| 3785 | return; | ||
| 3786 | } | ||
| 3787 | |||
| 3788 | if(length < 0 || position+length > str->str().length()) | ||
| 3789 | { | ||
| 3790 | throw_exception(SHRED, "IndexOutOfBoundsException", length); | ||
| 3791 | return; | ||
| 3792 | } | ||
| 3793 | |||
| 3794 | if(str2 == NULL) | ||
| 3795 | { | ||
| 3796 | throw_exception(SHRED, "NullPointerException"); | ||
| 3797 | return; | ||
| 3798 | } | ||
| 3799 | |||
| 3800 | // str->str.replace(position, length, str2->str); | ||
| 3801 | std::string s = str->str(); | ||
| 3802 | s.replace( position, length, str2->str() ); | ||
| 3803 | str->set( s ); | ||
| 3804 | } | ||
| 3805 | |||
| 3806 | CK_DLL_MFUN(string_find) | ||
| 3807 | { | ||
| 3808 | Chuck_String * str = (Chuck_String *) SELF; | ||
| 3809 | t_CKINT the_char = GET_NEXT_INT(ARGS); | ||
| 3810 | |||
| 3811 | string::size_type index = str->str().find(the_char); | ||
| 3812 | |||
| 3813 | if(index == string::npos) | ||
| 3814 | RETURN->v_int = -1; | ||
| 3815 | else | ||
| 3816 | RETURN->v_int = index; | ||
| 3817 | } | ||
| 3818 | |||
| 3819 | CK_DLL_MFUN(string_findStart) | ||
| 3820 | { | ||
| 3821 | Chuck_String * str = (Chuck_String *) SELF; | ||
| 3822 | t_CKINT the_char = GET_NEXT_INT(ARGS); | ||
| 3823 | t_CKINT start = GET_NEXT_INT(ARGS); | ||
| 3824 | |||
| 3825 | if(start < 0 || start >= str->str().length()) | ||
| 3826 | { | ||
| 3827 | throw_exception(SHRED, "IndexOutOfBoundsException", start); | ||
| 3828 | RETURN->v_int = -1; | ||
| 3829 | return; | ||
| 3830 | } | ||
| 3831 | |||
| 3832 | string::size_type index = str->str().find(the_char, start); | ||
| 3833 | |||
| 3834 | if(index == string::npos) | ||
| 3835 | RETURN->v_int = -1; | ||
| 3836 | else | ||
| 3837 | RETURN->v_int = index; | ||
| 3838 | } | ||
| 3839 | |||
| 3840 | CK_DLL_MFUN(string_findStr) | ||
| 3841 | { | ||
| 3842 | Chuck_String * str = (Chuck_String *) SELF; | ||
| 3843 | Chuck_String * the_str = GET_NEXT_STRING(ARGS); | ||
| 3844 | |||
| 3845 | string::size_type index = str->str().find(the_str->str()); | ||
| 3846 | |||
| 3847 | if(index == string::npos) | ||
| 3848 | RETURN->v_int = -1; | ||
| 3849 | else | ||
| 3850 | RETURN->v_int = index; | ||
| 3851 | } | ||
| 3852 | |||
| 3853 | CK_DLL_MFUN(string_findStrStart) | ||
| 3854 | { | ||
| 3855 | Chuck_String * str = (Chuck_String *) SELF; | ||
| 3856 | Chuck_String * the_str = GET_NEXT_STRING(ARGS); | ||
| 3857 | t_CKINT start = GET_NEXT_INT(ARGS); | ||
| 3858 | |||
| 3859 | if(start < 0 || start >= str->str().length()) | ||
| 3860 | { | ||
| 3861 | throw_exception(SHRED, "IndexOutOfBoundsException", start); | ||
| 3862 | RETURN->v_int = -1; | ||
| 3863 | return; | ||
| 3864 | } | ||
| 3865 | |||
| 3866 | string::size_type index = str->str().find(the_str->str(), start); | ||
| 3867 | |||
| 3868 | if(index == string::npos) | ||
| 3869 | RETURN->v_int = -1; | ||
| 3870 | else | ||
| 3871 | RETURN->v_int = index; | ||
| 3872 | } | ||
| 3873 | |||
| 3874 | CK_DLL_MFUN(string_rfind) | ||
| 3875 | { | ||
| 3876 | Chuck_String * str = (Chuck_String *) SELF; | ||
| 3877 | t_CKINT the_char = GET_NEXT_INT(ARGS); | ||
| 3878 | |||
| 3879 | string::size_type index = str->str().rfind(the_char); | ||
| 3880 | |||
| 3881 | if(index == string::npos) | ||
| 3882 | RETURN->v_int = -1; | ||
| 3883 | else | ||
| 3884 | RETURN->v_int = index; | ||
| 3885 | } | ||
| 3886 | |||
| 3887 | CK_DLL_MFUN(string_rfindStart) | ||
| 3888 | { | ||
| 3889 | Chuck_String * str = (Chuck_String *) SELF; | ||
| 3890 | t_CKINT the_char = GET_NEXT_INT(ARGS); | ||
| 3891 | t_CKINT start = GET_NEXT_INT(ARGS); | ||
| 3892 | |||
| 3893 | if(start < 0 || start >= str->str().length()) | ||
| 3894 | { | ||
| 3895 | throw_exception(SHRED, "IndexOutOfBoundsException", start); | ||
| 3896 | RETURN->v_int = -1; | ||
| 3897 | return; | ||
| 3898 | } | ||
| 3899 | |||
| 3900 | string::size_type index = str->str().rfind(the_char, start); | ||
| 3901 | |||
| 3902 | if(index == string::npos) | ||
| 3903 | RETURN->v_int = -1; | ||
| 3904 | else | ||
| 3905 | RETURN->v_int = index; | ||
| 3906 | } | ||
| 3907 | |||
| 3908 | CK_DLL_MFUN(string_rfindStr) | ||
| 3909 | { | ||
| 3910 | Chuck_String * str = (Chuck_String *) SELF; | ||
| 3911 | Chuck_String * the_str = GET_NEXT_STRING(ARGS); | ||
| 3912 | |||
| 3913 | string::size_type index = str->str().rfind(the_str->str()); | ||
| 3914 | |||
| 3915 | if(index == string::npos) | ||
| 3916 | RETURN->v_int = -1; | ||
| 3917 | else | ||
| 3918 | RETURN->v_int = index; | ||
| 3919 | } | ||
| 3920 | |||
| 3921 | CK_DLL_MFUN(string_rfindStrStart) | ||
| 3922 | { | ||
| 3923 | Chuck_String * str = (Chuck_String *) SELF; | ||
| 3924 | Chuck_String * the_str = GET_NEXT_STRING(ARGS); | ||
| 3925 | t_CKINT start = GET_NEXT_INT(ARGS); | ||
| 3926 | |||
| 3927 | if(start < 0 || start >= str->str().length()) | ||
| 3928 | { | ||
| 3929 | throw_exception(SHRED, "IndexOutOfBoundsException", start); | ||
| 3930 | RETURN->v_int = -1; | ||
| 3931 | return; | ||
| 3932 | } | ||
| 3933 | |||
| 3934 | string::size_type index = str->str().rfind(the_str->str(), start); | ||
| 3935 | |||
| 3936 | if(index == string::npos) | ||
| 3937 | RETURN->v_int = -1; | ||
| 3938 | else | ||
| 3939 | RETURN->v_int = index; | ||
| 3940 | } | ||
| 3941 | |||
| 3942 | CK_DLL_MFUN(string_erase) | ||
| 3943 | { | ||
| 3944 | Chuck_String * str = (Chuck_String *) SELF; | ||
| 3945 | t_CKINT start = GET_NEXT_INT(ARGS); | ||
| 3946 | t_CKINT length = GET_NEXT_INT(ARGS); | ||
| 3947 | |||
| 3948 | if(start < 0 || start >= str->str().length()) | ||
| 3949 | { | ||
| 3950 | throw_exception(SHRED, "IndexOutOfBoundsException", start); | ||
| 3951 | return; | ||
| 3952 | } | ||
| 3953 | |||
| 3954 | if(length < 0 || start+length > str->str().length()) | ||
| 3955 | { | ||
| 3956 | throw_exception(SHRED, "IndexOutOfBoundsException", length); | ||
| 3957 | return; | ||
| 3958 | } | ||
| 3959 | |||
| 3960 | // str->str.erase(start, length); | ||
| 3961 | std::string s = str->str(); | ||
| 3962 | s.erase( start, length ); | ||
| 3963 | str->set( s ); | ||
| 3964 | } | ||
| 3965 | |||
| 3966 | CK_DLL_MFUN( string_toInt ) | ||
| 3967 | { | ||
| 3968 | // get pointer to self | ||
| 3969 | Chuck_String * str = (Chuck_String *)SELF; | ||
| 3970 | // convert to int | ||
| 3971 | RETURN->v_int = ::atoi( str->str().c_str() ); | ||
| 3972 | } | ||
| 3973 | |||
| 3974 | CK_DLL_MFUN( string_toFloat ) | ||
| 3975 | { | ||
| 3976 | // get pointer to self | ||
| 3977 | Chuck_String * str = (Chuck_String *)SELF; | ||
| 3978 | // convert to int | ||
| 3979 | RETURN->v_float = (t_CKFLOAT)::atof( str->str().c_str() ); | ||
| 3980 | } | ||
| 3981 | |||
| 3982 | CK_DLL_MFUN( string_parent ) | ||
| 3983 | { | ||
| 3984 | Chuck_String * str = (Chuck_String *) SELF; | ||
| 3985 | |||
| 3986 | string::size_type i = str->str().rfind('/', str->str().length()-2); | ||
| 3987 | #ifdef WIN32 | ||
| 3988 | // SPENCERTODO: make this legit on windows | ||
| 3989 | if(i == string::npos) | ||
| 3990 | i = str->str().rfind('\\', str->str().length()-2); | ||
| 3991 | #endif // WIN32 | ||
| 3992 | |||
| 3993 | Chuck_String * parent = (Chuck_String *) instantiate_and_initialize_object(SHRED->vm_ref->env()->t_string, SHRED); | ||
| 3994 | |||
| 3995 | if(i != string::npos) | ||
| 3996 | { | ||
| 3997 | if(i == 0) | ||
| 3998 | parent->set( "/" ); | ||
| 3999 | else | ||
| 4000 | parent->set( str->str().substr(0, i) ); | ||
| 4001 | } | ||
| 4002 | |||
| 4003 | RETURN->v_string = parent; | ||
| 4004 | } | ||
| 4005 | |||
| 4006 | /* | ||
| 4007 | CK_DLL_MFUN( string_set_at ) | ||
| 4008 | { | ||
| 4009 | Chuck_String * s = (Chuck_String *)SELF; | ||
| 4010 | t_CKINT c = GET_CK_INT( | ||
| 4011 | RETURN->v_int = s->str.length(); | ||
| 4012 | } | ||
| 4013 | |||
| 4014 | CK_DLL_MFUN( string_get_at ) | ||
| 4015 | { | ||
| 4016 | Chuck_String * s = (Chuck_String *)SELF; | ||
| 4017 | RETURN->v_int = s->str.length(); | ||
| 4018 | } | ||
| 4019 | */ | ||
| 4020 | |||
| 4021 | |||
| 4022 | // array.size() | ||
| 4023 | CK_DLL_MFUN( array_get_size ) | ||
| 4024 | { | ||
| 4025 | Chuck_Array * array = (Chuck_Array *)SELF; | ||
| 4026 | RETURN->v_int = array->size(); | ||
| 4027 | } | ||
| 4028 | |||
| 4029 | // array.size() | ||
| 4030 | CK_DLL_MFUN( array_set_size ) | ||
| 4031 | { | ||
| 4032 | Chuck_Array * array = (Chuck_Array *)SELF; | ||
| 4033 | t_CKINT size = GET_NEXT_INT(ARGS); | ||
| 4034 | if( size < 0 ) | ||
| 4035 | { | ||
| 4036 | // TODO: make this exception | ||
| 4037 | CK_FPRINTF_STDERR( "[chuck](via array): attempt to set negative array size!\n" ); | ||
| 4038 | RETURN->v_int = 0; | ||
| 4039 | } | ||
| 4040 | else | ||
| 4041 | { | ||
| 4042 | array->set_size( size ); | ||
| 4043 | RETURN->v_int = array->size(); | ||
| 4044 | } | ||
| 4045 | RETURN->v_int = array->size(); | ||
| 4046 | } | ||
| 4047 | |||
| 4048 | // array.clear() | ||
| 4049 | CK_DLL_MFUN( array_clear ) | ||
| 4050 | { | ||
| 4051 | Chuck_Array * array = (Chuck_Array *)SELF; | ||
| 4052 | array->clear(); | ||
| 4053 | } | ||
| 4054 | |||
| 4055 | // array.reset() | ||
| 4056 | CK_DLL_MFUN( array_reset ) | ||
| 4057 | { | ||
| 4058 | Chuck_Array * array = (Chuck_Array *)SELF; | ||
| 4059 | array->clear(); | ||
| 4060 | // default capacity | ||
| 4061 | array->set_capacity( 8 ); | ||
| 4062 | } | ||
| 4063 | |||
| 4064 | // array.cap() | ||
| 4065 | CK_DLL_MFUN( array_set_capacity ) | ||
| 4066 | { | ||
| 4067 | Chuck_Array * array = (Chuck_Array *)SELF; | ||
| 4068 | t_CKINT capacity = GET_NEXT_INT(ARGS); | ||
| 4069 | if( capacity < 0 ) | ||
| 4070 | { | ||
| 4071 | // TODO: make this exception | ||
| 4072 | CK_FPRINTF_STDERR( "[chuck](via array): attempt to set negative array capacity!\n" ); | ||
| 4073 | RETURN->v_int = 0; | ||
| 4074 | } | ||
| 4075 | else | ||
| 4076 | { | ||
| 4077 | array->set_capacity( capacity ); | ||
| 4078 | RETURN->v_int = array->capacity(); | ||
| 4079 | } | ||
| 4080 | } | ||
| 4081 | |||
| 4082 | // array.cap() | ||
| 4083 | CK_DLL_MFUN( array_get_capacity_hack ) | ||
| 4084 | { | ||
| 4085 | Chuck_Array * array = (Chuck_Array *)SELF; | ||
| 4086 | RETURN->v_int = array->size(); | ||
| 4087 | } | ||
| 4088 | |||
| 4089 | // array.capacity() | ||
| 4090 | CK_DLL_MFUN( array_get_capacity ) | ||
| 4091 | { | ||
| 4092 | Chuck_Array * array = (Chuck_Array *)SELF; | ||
| 4093 | RETURN->v_int = array->capacity(); | ||
| 4094 | } | ||
| 4095 | |||
| 4096 | // array.find() | ||
| 4097 | CK_DLL_MFUN( array_find ) | ||
| 4098 | { | ||
| 4099 | Chuck_Array * array = (Chuck_Array *)SELF; | ||
| 4100 | Chuck_String * name = GET_NEXT_STRING( ARGS ); | ||
| 4101 | RETURN->v_int = array->find( name->str() ); | ||
| 4102 | } | ||
| 4103 | |||
| 4104 | // array.erase() | ||
| 4105 | CK_DLL_MFUN( array_erase ) | ||
| 4106 | { | ||
| 4107 | Chuck_Array * array = (Chuck_Array *)SELF; | ||
| 4108 | Chuck_String * name = GET_NEXT_STRING( ARGS ); | ||
| 4109 | RETURN->v_int = array->erase( name->str() ); | ||
| 4110 | } | ||
| 4111 | |||
| 4112 | // array.push_back() | ||
| 4113 | CK_DLL_MFUN( array_push_back ) | ||
| 4114 | { | ||
| 4115 | Chuck_Array * array = (Chuck_Array *)SELF; | ||
| 4116 | // ISSUE: 64-bit (fixed 1.3.1.0 using data kind) | ||
| 4117 | if( array->data_type_kind() == CHUCK_ARRAY4_DATAKIND ) | ||
| 4118 | RETURN->v_int = ((Chuck_Array4 *)array)->push_back( GET_NEXT_UINT( ARGS ) ); | ||
| 4119 | else if( array->data_type_kind() == CHUCK_ARRAY8_DATAKIND ) | ||
| 4120 | RETURN->v_int = ((Chuck_Array8 *)array)->push_back( GET_NEXT_FLOAT( ARGS ) ); | ||
| 4121 | else if( array->data_type_kind() == CHUCK_ARRAY16_DATAKIND ) | ||
| 4122 | RETURN->v_int = ((Chuck_Array16 *)array)->push_back( GET_NEXT_COMPLEX( ARGS ) ); | ||
| 4123 | else | ||
| 4124 | assert( FALSE ); | ||
| 4125 | } | ||
| 4126 | |||
| 4127 | // array.pop_back() | ||
| 4128 | CK_DLL_MFUN( array_pop_back ) | ||
| 4129 | { | ||
| 4130 | Chuck_Array * array = (Chuck_Array *)SELF; | ||
| 4131 | // ISSUE: 64-bit (fixed 1.3.1.0 using data kind) | ||
| 4132 | if( array->data_type_kind() == CHUCK_ARRAY4_DATAKIND ) | ||
| 4133 | RETURN->v_int = ((Chuck_Array4 *)array)->pop_back( ); | ||
| 4134 | else if( array->data_type_kind() == CHUCK_ARRAY8_DATAKIND ) | ||
| 4135 | RETURN->v_int = ((Chuck_Array8 *)array)->pop_back( ); | ||
| 4136 | else if( array->data_type_kind() == CHUCK_ARRAY16_DATAKIND ) | ||
| 4137 | RETURN->v_int = ((Chuck_Array16 *)array)->pop_back( ); | ||
| 4138 | else | ||
| 4139 | assert( FALSE ); | ||
| 4140 | } | ||
| 4141 | |||
| 4142 | |||
| 4143 | #ifndef __DISABLE_MIDI__ | ||
| 4144 | |||
| 4145 | //----------------------------------------------------------------------------- | ||
| 4146 | // MidiIn API | ||
| 4147 | //----------------------------------------------------------------------------- | ||
| 4148 | CK_DLL_CTOR( MidiIn_ctor ) | ||
| 4149 | { | ||
| 4150 | MidiIn * min = new MidiIn; | ||
| 4151 | min->SELF = SELF; | ||
| 4152 | OBJ_MEMBER_INT(SELF, MidiIn_offset_data) = (t_CKINT)min; | ||
| 4153 | } | ||
| 4154 | |||
| 4155 | CK_DLL_DTOR( MidiIn_dtor ) | ||
| 4156 | { | ||
| 4157 | delete (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data); | ||
| 4158 | OBJ_MEMBER_INT(SELF, MidiIn_offset_data) = 0; | ||
| 4159 | } | ||
| 4160 | |||
| 4161 | CK_DLL_MFUN( MidiIn_open ) | ||
| 4162 | { | ||
| 4163 | MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data); | ||
| 4164 | t_CKINT port = GET_CK_INT(ARGS); | ||
| 4165 | RETURN->v_int = min->open( SHRED->vm_ref, port ); | ||
| 4166 | } | ||
| 4167 | |||
| 4168 | CK_DLL_MFUN( MidiIn_open_named ) // added 1.3.0.0 | ||
| 4169 | { | ||
| 4170 | MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data); | ||
| 4171 | Chuck_String * name = GET_CK_STRING(ARGS); | ||
| 4172 | RETURN->v_int = min->open( SHRED->vm_ref, name->str() ); | ||
| 4173 | } | ||
| 4174 | |||
| 4175 | CK_DLL_MFUN( MidiIn_good ) | ||
| 4176 | { | ||
| 4177 | MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data); | ||
| 4178 | RETURN->v_int = (t_CKINT)min->good(); | ||
| 4179 | } | ||
| 4180 | |||
| 4181 | CK_DLL_MFUN( MidiIn_num ) | ||
| 4182 | { | ||
| 4183 | MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data); | ||
| 4184 | RETURN->v_int = min->num(); | ||
| 4185 | } | ||
| 4186 | |||
| 4187 | CK_DLL_MFUN( MidiIn_printerr ) | ||
| 4188 | { | ||
| 4189 | MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data); | ||
| 4190 | t_CKINT print_or_not = GET_CK_INT(ARGS); | ||
| 4191 | min->set_suppress( !print_or_not ); | ||
| 4192 | } | ||
| 4193 | |||
| 4194 | CK_DLL_MFUN( MidiIn_name ) | ||
| 4195 | { | ||
| 4196 | MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data); | ||
| 4197 | // TODO: memory leak, please fix, Thanks. | ||
| 4198 | Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED ); | ||
| 4199 | // only if valid | ||
| 4200 | if( min->good() ) | ||
| 4201 | a->set( min->min->getPortName( min->num() ) ); | ||
| 4202 | RETURN->v_string = a; | ||
| 4203 | } | ||
| 4204 | |||
| 4205 | CK_DLL_MFUN( MidiIn_recv ) | ||
| 4206 | { | ||
| 4207 | MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data); | ||
| 4208 | Chuck_Object * fake_msg = GET_CK_OBJECT(ARGS); | ||
| 4209 | MidiMsg the_msg; | ||
| 4210 | RETURN->v_int = min->recv( &the_msg ); | ||
| 4211 | if( RETURN->v_int ) | ||
| 4212 | { | ||
| 4213 | OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data1) = the_msg.data[0]; | ||
| 4214 | OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data2) = the_msg.data[1]; | ||
| 4215 | OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data3) = the_msg.data[2]; | ||
| 4216 | } | ||
| 4217 | } | ||
| 4218 | |||
| 4219 | |||
| 4220 | CK_DLL_MFUN( MidiIn_can_wait ) | ||
| 4221 | { | ||
| 4222 | MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data); | ||
| 4223 | RETURN->v_int = min->empty(); | ||
| 4224 | } | ||
| 4225 | |||
| 4226 | |||
| 4227 | //----------------------------------------------------------------------------- | ||
| 4228 | // MidiOut API | ||
| 4229 | //----------------------------------------------------------------------------- | ||
| 4230 | CK_DLL_CTOR( MidiOut_ctor ) | ||
| 4231 | { | ||
| 4232 | OBJ_MEMBER_INT(SELF, MidiOut_offset_data) = (t_CKUINT)new MidiOut; | ||
| 4233 | } | ||
| 4234 | |||
| 4235 | CK_DLL_DTOR( MidiOut_dtor ) | ||
| 4236 | { | ||
| 4237 | delete (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data); | ||
| 4238 | OBJ_MEMBER_INT(SELF, MidiOut_offset_data) = 0; | ||
| 4239 | } | ||
| 4240 | |||
| 4241 | CK_DLL_MFUN( MidiOut_open ) | ||
| 4242 | { | ||
| 4243 | MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data); | ||
| 4244 | t_CKINT port = GET_CK_INT(ARGS); | ||
| 4245 | RETURN->v_int = mout->open( port ); | ||
| 4246 | } | ||
| 4247 | |||
| 4248 | CK_DLL_MFUN( MidiOut_open_named ) // added 1.3.0.0 | ||
| 4249 | { | ||
| 4250 | MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data); | ||
| 4251 | Chuck_String * name = GET_CK_STRING(ARGS); | ||
| 4252 | RETURN->v_int = mout->open( name->str() ); | ||
| 4253 | } | ||
| 4254 | |||
| 4255 | CK_DLL_MFUN( MidiOut_good ) | ||
| 4256 | { | ||
| 4257 | MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data); | ||
| 4258 | RETURN->v_int = (t_CKINT)mout->good(); | ||
| 4259 | } | ||
| 4260 | |||
| 4261 | CK_DLL_MFUN( MidiOut_num ) | ||
| 4262 | { | ||
| 4263 | MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data); | ||
| 4264 | RETURN->v_int = mout->num(); | ||
| 4265 | } | ||
| 4266 | |||
| 4267 | CK_DLL_MFUN( MidiOut_name ) | ||
| 4268 | { | ||
| 4269 | MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data); | ||
| 4270 | // TODO: memory leak, please fix, Thanks. | ||
| 4271 | Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED ); | ||
| 4272 | // only if valid | ||
| 4273 | if( mout->good() ) | ||
| 4274 | a->set( mout->mout->getPortName( mout->num() ) ); | ||
| 4275 | RETURN->v_string = a; | ||
| 4276 | } | ||
| 4277 | |||
| 4278 | CK_DLL_MFUN( MidiOut_printerr ) | ||
| 4279 | { | ||
| 4280 | MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data); | ||
| 4281 | t_CKINT print_or_not = GET_CK_INT(ARGS); | ||
| 4282 | mout->set_suppress( !print_or_not ); | ||
| 4283 | } | ||
| 4284 | |||
| 4285 | CK_DLL_MFUN( MidiOut_send ) | ||
| 4286 | { | ||
| 4287 | MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data); | ||
| 4288 | Chuck_Object * fake_msg = GET_CK_OBJECT(ARGS); | ||
| 4289 | MidiMsg the_msg; | ||
| 4290 | the_msg.data[0] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data1); | ||
| 4291 | the_msg.data[1] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data2); | ||
| 4292 | the_msg.data[2] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data3); | ||
| 4293 | RETURN->v_int = mout->send( &the_msg ); | ||
| 4294 | } | ||
| 4295 | |||
| 4296 | #endif // __DISABLE_MIDI__ | ||
| 4297 | |||
| 4298 | |||
| 4299 | //----------------------------------------------------------------------------- | ||
| 4300 | // HidMsg API | ||
| 4301 | //----------------------------------------------------------------------------- | ||
| 4302 | CK_DLL_MFUN( HidMsg_is_axis_motion ) | ||
| 4303 | { | ||
| 4304 | RETURN->v_int = ( ( t_CKINT ) OBJ_MEMBER_INT( SELF, HidMsg_offset_type ) == | ||
| 4305 | CK_HID_JOYSTICK_AXIS ? 1 : 0 ); | ||
| 4306 | } | ||
| 4307 | |||
| 4308 | CK_DLL_MFUN( HidMsg_is_button_down ) | ||
| 4309 | { | ||
| 4310 | RETURN->v_int = ( ( t_CKINT ) OBJ_MEMBER_INT( SELF, HidMsg_offset_type ) == | ||
| 4311 | CK_HID_BUTTON_DOWN ? 1 : 0 ); | ||
| 4312 | } | ||
| 4313 | |||
| 4314 | CK_DLL_MFUN( HidMsg_is_button_up ) | ||
| 4315 | { | ||
| 4316 | RETURN->v_int = ( ( t_CKINT ) OBJ_MEMBER_INT( SELF, HidMsg_offset_type ) == | ||
| 4317 | CK_HID_BUTTON_UP ? 1 : 0 ); | ||
| 4318 | } | ||
| 4319 | |||
| 4320 | CK_DLL_MFUN( HidMsg_is_mouse_motion ) | ||
| 4321 | { | ||
| 4322 | RETURN->v_int = ( ( t_CKINT ) OBJ_MEMBER_INT( SELF, HidMsg_offset_type ) == | ||
| 4323 | CK_HID_MOUSE_MOTION ? 1 : 0 ); | ||
| 4324 | } | ||
| 4325 | |||
| 4326 | CK_DLL_MFUN( HidMsg_is_hat_motion ) | ||
| 4327 | { | ||
| 4328 | RETURN->v_int = ( ( t_CKINT ) OBJ_MEMBER_INT( SELF, HidMsg_offset_type ) == | ||
| 4329 | CK_HID_JOYSTICK_HAT ? 1 : 0 ); | ||
| 4330 | } | ||
| 4331 | |||
| 4332 | CK_DLL_MFUN( HidMsg_is_wheel_motion ) | ||
| 4333 | { | ||
| 4334 | RETURN->v_int = ( ( t_CKINT ) OBJ_MEMBER_INT( SELF, HidMsg_offset_type ) == | ||
| 4335 | CK_HID_MOUSE_WHEEL ? 1 : 0 ); | ||
| 4336 | } | ||
| 4337 | |||
| 4338 | //----------------------------------------------------------------------------- | ||
| 4339 | // HidIn API | ||
| 4340 | //----------------------------------------------------------------------------- | ||
| 4341 | CK_DLL_CTOR( HidIn_ctor ) | ||
| 4342 | { | ||
| 4343 | HidIn * min = new HidIn; | ||
| 4344 | min->SELF = SELF; | ||
| 4345 | OBJ_MEMBER_INT(SELF, HidIn_offset_data) = (t_CKINT)min; | ||
| 4346 | } | ||
| 4347 | |||
| 4348 | CK_DLL_DTOR( HidIn_dtor ) | ||
| 4349 | { | ||
| 4350 | delete (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); | ||
| 4351 | OBJ_MEMBER_INT(SELF, HidIn_offset_data) = 0; | ||
| 4352 | } | ||
| 4353 | |||
| 4354 | CK_DLL_MFUN( HidIn_open ) | ||
| 4355 | { | ||
| 4356 | HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); | ||
| 4357 | t_CKINT type = GET_NEXT_INT(ARGS); | ||
| 4358 | t_CKINT num = GET_NEXT_INT(ARGS); | ||
| 4359 | // CK_FPRINTF_STDERR( "HidIn_open %li %li\n", type, num ); | ||
| 4360 | RETURN->v_int = min->open( SHRED->vm_ref, type, num ); | ||
| 4361 | } | ||
| 4362 | |||
| 4363 | CK_DLL_MFUN( HidIn_open_named ) | ||
| 4364 | { | ||
| 4365 | HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); | ||
| 4366 | Chuck_String * name = GET_NEXT_STRING(ARGS); | ||
| 4367 | std::string s = name->str(); | ||
| 4368 | RETURN->v_int = min->open( SHRED->vm_ref, s ); | ||
| 4369 | } | ||
| 4370 | |||
| 4371 | CK_DLL_MFUN( HidIn_open_joystick ) | ||
| 4372 | { | ||
| 4373 | HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); | ||
| 4374 | t_CKINT num = GET_NEXT_INT(ARGS); | ||
| 4375 | RETURN->v_int = min->open( SHRED->vm_ref, CK_HID_DEV_JOYSTICK, num ); | ||
| 4376 | } | ||
| 4377 | |||
| 4378 | CK_DLL_MFUN( HidIn_open_mouse ) | ||
| 4379 | { | ||
| 4380 | HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); | ||
| 4381 | t_CKINT num = GET_NEXT_INT(ARGS); | ||
| 4382 | RETURN->v_int = min->open( SHRED->vm_ref, CK_HID_DEV_MOUSE, num ); | ||
| 4383 | } | ||
| 4384 | |||
| 4385 | CK_DLL_MFUN( HidIn_open_keyboard ) | ||
| 4386 | { | ||
| 4387 | HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); | ||
| 4388 | t_CKINT num = GET_NEXT_INT(ARGS); | ||
| 4389 | RETURN->v_int = min->open( SHRED->vm_ref, CK_HID_DEV_KEYBOARD, num ); | ||
| 4390 | } | ||
| 4391 | |||
| 4392 | CK_DLL_MFUN( HidIn_open_tiltsensor ) | ||
| 4393 | { | ||
| 4394 | HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); | ||
| 4395 | RETURN->v_int = min->open( SHRED->vm_ref, CK_HID_DEV_TILTSENSOR, 0 ); | ||
| 4396 | } | ||
| 4397 | |||
| 4398 | CK_DLL_MFUN( HidIn_good ) | ||
| 4399 | { | ||
| 4400 | HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); | ||
| 4401 | RETURN->v_int = (t_CKINT)min->good(); | ||
| 4402 | } | ||
| 4403 | |||
| 4404 | CK_DLL_MFUN( HidIn_num ) | ||
| 4405 | { | ||
| 4406 | HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); | ||
| 4407 | RETURN->v_int = min->num(); | ||
| 4408 | } | ||
| 4409 | |||
| 4410 | CK_DLL_MFUN( HidIn_printerr ) | ||
| 4411 | { | ||
| 4412 | HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); | ||
| 4413 | t_CKINT print_or_not = GET_CK_INT(ARGS); | ||
| 4414 | min->set_suppress( !print_or_not ); | ||
| 4415 | } | ||
| 4416 | |||
| 4417 | CK_DLL_MFUN( HidIn_name ) | ||
| 4418 | { | ||
| 4419 | HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); | ||
| 4420 | // TODO: memory leak, please fix, Thanks. | ||
| 4421 | // Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED ); | ||
| 4422 | // only if valid | ||
| 4423 | // if( min->good() ) | ||
| 4424 | // a->str = min->phin->getPortName( min->num() ); | ||
| 4425 | // TODO: is null problem? | ||
| 4426 | RETURN->v_string = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED ); | ||
| 4427 | RETURN->v_string->set( min->name() ); | ||
| 4428 | } | ||
| 4429 | |||
| 4430 | CK_DLL_MFUN( HidIn_recv ) | ||
| 4431 | { | ||
| 4432 | HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); | ||
| 4433 | Chuck_Object * fake_msg = GET_CK_OBJECT(ARGS); | ||
| 4434 | HidMsg the_msg; | ||
| 4435 | RETURN->v_int = min->recv( &the_msg ); | ||
| 4436 | if( RETURN->v_int ) | ||
| 4437 | { | ||
| 4438 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_device_type) = the_msg.device_type; | ||
| 4439 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_device_num) = the_msg.device_num; | ||
| 4440 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_type) = the_msg.type; | ||
| 4441 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_which) = the_msg.eid; | ||
| 4442 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_idata) = the_msg.idata[0]; | ||
| 4443 | OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_fdata) = the_msg.fdata[0]; | ||
| 4444 | |||
| 4445 | // mouse motion specific member variables | ||
| 4446 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_deltax) = the_msg.idata[0]; | ||
| 4447 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_deltay) = the_msg.idata[1]; | ||
| 4448 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_cursorx) = the_msg.idata[2]; | ||
| 4449 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_cursory) = the_msg.idata[3]; | ||
| 4450 | OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_scaledcursorx) = the_msg.fdata[0]; | ||
| 4451 | OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_scaledcursory) = the_msg.fdata[1]; | ||
| 4452 | |||
| 4453 | // axis motion specific member variables | ||
| 4454 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_axis_position) = the_msg.idata[0]; | ||
| 4455 | OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_scaled_axis_position) = the_msg.fdata[0]; | ||
| 4456 | OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_axis_position2) = the_msg.fdata[0]; | ||
| 4457 | |||
| 4458 | // hat motion specific variables | ||
| 4459 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_hat_position) = the_msg.idata[0]; | ||
| 4460 | |||
| 4461 | // keyboard specific variables | ||
| 4462 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_key) = the_msg.idata[1]; | ||
| 4463 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_ascii) = the_msg.idata[2]; | ||
| 4464 | |||
| 4465 | // accelerometer (tilt sensor, wii remote) specific members | ||
| 4466 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_x) = the_msg.idata[0]; | ||
| 4467 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_y) = the_msg.idata[1]; | ||
| 4468 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_z) = the_msg.idata[2]; | ||
| 4469 | |||
| 4470 | // multitouch stuff - added 1.3.0.0 | ||
| 4471 | OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_touchx) = the_msg.fdata[0]; | ||
| 4472 | OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_touchy) = the_msg.fdata[1]; | ||
| 4473 | OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_touchsize) = the_msg.fdata[2]; | ||
| 4474 | } | ||
| 4475 | } | ||
| 4476 | |||
| 4477 | CK_DLL_MFUN( HidIn_read ) | ||
| 4478 | { | ||
| 4479 | HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); | ||
| 4480 | t_CKINT type = GET_NEXT_INT(ARGS); | ||
| 4481 | t_CKINT num = GET_NEXT_INT(ARGS); | ||
| 4482 | Chuck_Object * fake_msg = GET_NEXT_OBJECT(ARGS); | ||
| 4483 | |||
| 4484 | HidMsg the_msg; | ||
| 4485 | |||
| 4486 | RETURN->v_int = min->read( type, num, &the_msg ); | ||
| 4487 | |||
| 4488 | if( RETURN->v_int ) | ||
| 4489 | { | ||
| 4490 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_device_type) = the_msg.device_type; | ||
| 4491 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_device_num) = the_msg.device_num; | ||
| 4492 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_type) = the_msg.type; | ||
| 4493 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_which) = the_msg.eid; | ||
| 4494 | |||
| 4495 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_idata) = the_msg.idata[0]; | ||
| 4496 | OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_fdata) = the_msg.fdata[0]; | ||
| 4497 | |||
| 4498 | // mouse motion specific member members | ||
| 4499 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_deltax) = the_msg.idata[0]; | ||
| 4500 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_deltay) = the_msg.idata[1]; | ||
| 4501 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_cursorx) = the_msg.idata[2]; | ||
| 4502 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_cursory) = the_msg.idata[3]; | ||
| 4503 | OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_scaledcursorx) = the_msg.fdata[0]; | ||
| 4504 | OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_scaledcursory) = the_msg.fdata[1]; | ||
| 4505 | |||
| 4506 | // joystick axis specific member members | ||
| 4507 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_axis_position) = the_msg.idata[0]; | ||
| 4508 | OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_scaled_axis_position) = the_msg.fdata[0]; | ||
| 4509 | OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_axis_position2) = the_msg.fdata[0]; | ||
| 4510 | |||
| 4511 | // joystick hat specific member members | ||
| 4512 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_hat_position) = the_msg.idata[0]; | ||
| 4513 | |||
| 4514 | // keyboard specific members | ||
| 4515 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_key) = the_msg.idata[1]; | ||
| 4516 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_ascii) = the_msg.idata[2]; | ||
| 4517 | |||
| 4518 | // accelerometer (tilt sensor, wii remote) specific members | ||
| 4519 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_x) = the_msg.idata[0]; | ||
| 4520 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_y) = the_msg.idata[1]; | ||
| 4521 | OBJ_MEMBER_INT(fake_msg, HidMsg_offset_z) = the_msg.idata[2]; | ||
| 4522 | } | ||
| 4523 | } | ||
| 4524 | |||
| 4525 | CK_DLL_MFUN( HidIn_send ) | ||
| 4526 | { | ||
| 4527 | HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); | ||
| 4528 | Chuck_Object * fake_msg = GET_NEXT_OBJECT(ARGS); | ||
| 4529 | |||
| 4530 | HidMsg the_msg; | ||
| 4531 | the_msg.device_type = OBJ_MEMBER_INT( fake_msg, HidMsg_offset_device_type ); | ||
| 4532 | the_msg.device_num = OBJ_MEMBER_INT( fake_msg, HidMsg_offset_device_num ); | ||
| 4533 | the_msg.type = OBJ_MEMBER_INT( fake_msg, HidMsg_offset_type ); | ||
| 4534 | the_msg.eid = OBJ_MEMBER_INT( fake_msg, HidMsg_offset_which ); | ||
| 4535 | the_msg.idata[0] = OBJ_MEMBER_INT( fake_msg, HidMsg_offset_idata ); | ||
| 4536 | |||
| 4537 | RETURN->v_int = min->send( &the_msg ); | ||
| 4538 | } | ||
| 4539 | |||
| 4540 | CK_DLL_MFUN( HidIn_can_wait ) | ||
| 4541 | { | ||
| 4542 | HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); | ||
| 4543 | RETURN->v_int = min->empty(); | ||
| 4544 | } | ||
| 4545 | |||
| 4546 | CK_DLL_SFUN( HidIn_read_tilt_sensor ) | ||
| 4547 | { | ||
| 4548 | static HidIn * hi; | ||
| 4549 | static t_CKBOOL hi_good = TRUE; | ||
| 4550 | |||
| 4551 | Chuck_Array4 * array = new Chuck_Array4( FALSE, 3 ); | ||
| 4552 | array->set( 0, 0 ); | ||
| 4553 | array->set( 1, 0 ); | ||
| 4554 | array->set( 2, 0 ); | ||
| 4555 | |||
| 4556 | // TODO: reference count? | ||
| 4557 | array->add_ref(); | ||
| 4558 | RETURN->v_object = array; | ||
| 4559 | |||
| 4560 | if( hi_good == FALSE ) | ||
| 4561 | return; | ||
| 4562 | |||
| 4563 | if( !hi ) | ||
| 4564 | { | ||
| 4565 | hi = new HidIn; | ||
| 4566 | if( !hi->open( SHRED->vm_ref, CK_HID_DEV_TILTSENSOR, 0 ) ) | ||
| 4567 | { | ||
| 4568 | hi_good = FALSE; | ||
| 4569 | return; | ||
| 4570 | } | ||
| 4571 | } | ||
| 4572 | |||
| 4573 | HidMsg msg; | ||
| 4574 | |||
| 4575 | if( !hi->read( CK_HID_ACCELEROMETER, 0, &msg ) ) | ||
| 4576 | { | ||
| 4577 | return; | ||
| 4578 | } | ||
| 4579 | |||
| 4580 | array->set( 0, msg.idata[0] ); | ||
| 4581 | array->set( 1, msg.idata[1] ); | ||
| 4582 | array->set( 2, msg.idata[2] ); | ||
| 4583 | } | ||
| 4584 | |||
| 4585 | CK_DLL_SFUN( HidIn_ctrl_tiltPollRate ) | ||
| 4586 | { | ||
| 4587 | // get srate | ||
| 4588 | if( !SHRED || !SHRED->vm_ref ) | ||
| 4589 | { | ||
| 4590 | // problem | ||
| 4591 | CK_FPRINTF_STDERR( "[chuck](via HID): can't set tiltPollRate on NULL shred/VM...\n" ); | ||
| 4592 | RETURN->v_dur = 0; | ||
| 4593 | return; | ||
| 4594 | } | ||
| 4595 | t_CKFLOAT srate = SHRED->vm_ref->srate(); | ||
| 4596 | |||
| 4597 | // get arg | ||
| 4598 | t_CKDUR v = GET_NEXT_DUR( ARGS ); | ||
| 4599 | |||
| 4600 | // get in microseconds | ||
| 4601 | t_CKINT usec = (t_CKINT)( v / srate * 1000000 ); | ||
| 4602 | |||
| 4603 | // make sure it's nonnegative | ||
| 4604 | if( usec < 0 ) usec = 0; | ||
| 4605 | |||
| 4606 | // go | ||
| 4607 | RETURN->v_dur = TiltSensor_setPollRate( usec ) * srate / 1000000; | ||
| 4608 | } | ||
| 4609 | |||
| 4610 | CK_DLL_SFUN( HidIn_cget_tiltPollRate ) | ||
| 4611 | { | ||
| 4612 | // get srate | ||
| 4613 | if( !SHRED || !SHRED->vm_ref ) | ||
| 4614 | { | ||
| 4615 | // problem | ||
| 4616 | CK_FPRINTF_STDERR( "[chuck](via HID): can't get tiltPollRate on NULL shred/VM...\n" ); | ||
| 4617 | RETURN->v_dur = 0; | ||
| 4618 | return; | ||
| 4619 | } | ||
| 4620 | t_CKFLOAT srate = SHRED->vm_ref->srate(); | ||
| 4621 | |||
| 4622 | RETURN->v_dur = TiltSensor_getPollRate() * srate / 1000000; | ||
| 4623 | } | ||
| 4624 | |||
| 4625 | CK_DLL_SFUN( HidIn_start_cursor_track ) | ||
| 4626 | { | ||
| 4627 | RETURN->v_int = !Mouse_start_cursor_track(); | ||
| 4628 | } | ||
| 4629 | |||
| 4630 | CK_DLL_SFUN( HidIn_stop_cursor_track ) | ||
| 4631 | { | ||
| 4632 | RETURN->v_int = !Mouse_stop_cursor_track(); | ||
| 4633 | } | ||
| 4634 | |||
| 4635 | //----------------------------------------------------------------------------- | ||
| 4636 | // HidOut API | ||
| 4637 | //----------------------------------------------------------------------------- | ||
| 4638 | CK_DLL_CTOR( HidOut_ctor ) | ||
| 4639 | { | ||
| 4640 | OBJ_MEMBER_INT(SELF, HidOut_offset_data) = (t_CKUINT)new HidOut; | ||
| 4641 | } | ||
| 4642 | |||
| 4643 | CK_DLL_DTOR( HidOut_dtor ) | ||
| 4644 | { | ||
| 4645 | delete (HidOut *)OBJ_MEMBER_INT(SELF, HidOut_offset_data); | ||
| 4646 | OBJ_MEMBER_INT(SELF, HidOut_offset_data) = 0; | ||
| 4647 | } | ||
| 4648 | |||
| 4649 | CK_DLL_MFUN( HidOut_open ) | ||
| 4650 | { | ||
| 4651 | HidOut * mout = (HidOut *)OBJ_MEMBER_INT(SELF, HidOut_offset_data); | ||
| 4652 | t_CKINT num = GET_CK_INT(ARGS); | ||
| 4653 | RETURN->v_int = mout->open( num ); | ||
| 4654 | } | ||
| 4655 | |||
| 4656 | CK_DLL_MFUN( HidOut_good ) | ||
| 4657 | { | ||
| 4658 | HidOut * mout = (HidOut *)OBJ_MEMBER_INT(SELF, HidOut_offset_data); | ||
| 4659 | RETURN->v_int = (t_CKINT)mout->good(); | ||
| 4660 | } | ||
| 4661 | |||
| 4662 | CK_DLL_MFUN( HidOut_num ) | ||
| 4663 | { | ||
| 4664 | HidOut * mout = (HidOut *)OBJ_MEMBER_INT(SELF, HidOut_offset_data); | ||
| 4665 | RETURN->v_int = mout->num(); | ||
| 4666 | } | ||
| 4667 | |||
| 4668 | CK_DLL_MFUN( HidOut_name ) | ||
| 4669 | { | ||
| 4670 | // HidOut * mout = (HidOut *)OBJ_MEMBER_INT(SELF, HidOut_offset_data); | ||
| 4671 | // TODO: memory leak, please fix, Thanks. | ||
| 4672 | Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( SHRED->vm_ref->env()->t_string, SHRED ); | ||
| 4673 | // only if valid | ||
| 4674 | // if( mout->good() ) | ||
| 4675 | // a->str = mout->mout->getPortName( mout->num() ); | ||
| 4676 | RETURN->v_string = a; | ||
| 4677 | } | ||
| 4678 | |||
| 4679 | CK_DLL_MFUN( HidOut_printerr ) | ||
| 4680 | { | ||
| 4681 | HidOut * mout = (HidOut *)OBJ_MEMBER_INT(SELF, HidOut_offset_data); | ||
| 4682 | t_CKINT print_or_not = GET_CK_INT(ARGS); | ||
| 4683 | mout->set_suppress( !print_or_not ); | ||
| 4684 | } | ||
| 4685 | |||
| 4686 | CK_DLL_MFUN( HidOut_send ) | ||
| 4687 | { | ||
| 4688 | HidOut * mout = (HidOut *)OBJ_MEMBER_INT(SELF, HidOut_offset_data); | ||
| 4689 | // Chuck_Object * fake_msg = GET_CK_OBJECT(ARGS); | ||
| 4690 | HidMsg the_msg; | ||
| 4691 | // the_msg.data[0] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, HidMsg_offset_data1); | ||
| 4692 | // the_msg.data[1] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, HidMsg_offset_data2); | ||
| 4693 | // the_msg.data[2] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, HidMsg_offset_data3); | ||
| 4694 | RETURN->v_int = mout->send( &the_msg ); | ||
| 4695 | } | ||
| 4696 | |||
| 4697 | |||
| 4698 | //----------------------------------------------------------------------------- | ||
| 4699 | // MidiRW API | ||
| 4700 | //----------------------------------------------------------------------------- | ||
| 4701 | CK_DLL_CTOR( MidiRW_ctor ) | ||
| 4702 | { | ||
| 4703 | #ifndef __DISABLE_MIDI__ | ||
| 4704 | OBJ_MEMBER_INT(SELF, MidiRW_offset_data) = (t_CKUINT)new MidiRW; | ||
| 4705 | #endif // __DISABLE_MIDI__ | ||
| 4706 | } | ||
| 4707 | |||
| 4708 | CK_DLL_DTOR( MidiRW_dtor ) | ||
| 4709 | { | ||
| 4710 | #ifndef __DISABLE_MIDI__ | ||
| 4711 | delete (MidiRW *)OBJ_MEMBER_INT(SELF, MidiRW_offset_data); | ||
| 4712 | OBJ_MEMBER_INT(SELF, MidiRW_offset_data) = 0; | ||
| 4713 | #endif // __DISABLE_MIDI__ | ||
| 4714 | } | ||
| 4715 | |||
| 4716 | CK_DLL_MFUN( MidiRW_open ) | ||
| 4717 | { | ||
| 4718 | #ifndef __DISABLE_MIDI__ | ||
| 4719 | MidiRW * mrw = (MidiRW *)OBJ_MEMBER_INT(SELF, MidiRW_offset_data); | ||
| 4720 | const char * filename = GET_CK_STRING(ARGS)->str().c_str(); | ||
| 4721 | RETURN->v_int = mrw->open( filename ); | ||
| 4722 | #endif // __DISABLE_MIDI__ | ||
| 4723 | } | ||
| 4724 | |||
| 4725 | CK_DLL_MFUN( MidiRW_close ) | ||
| 4726 | { | ||
| 4727 | #ifndef __DISABLE_MIDI__ | ||
| 4728 | MidiRW * mrw = (MidiRW *)OBJ_MEMBER_INT(SELF, MidiRW_offset_data); | ||
| 4729 | RETURN->v_int = mrw->close(); | ||
| 4730 | #endif // __DISABLE_MIDI__ | ||
| 4731 | } | ||
| 4732 | |||
| 4733 | CK_DLL_MFUN( MidiRW_read ) | ||
| 4734 | { | ||
| 4735 | #ifndef __DISABLE_MIDI__ | ||
| 4736 | MidiRW * mrw = (MidiRW *)OBJ_MEMBER_INT(SELF, MidiRW_offset_data); | ||
| 4737 | Chuck_Object * fake_msg = GET_NEXT_OBJECT(ARGS); | ||
| 4738 | MidiMsg the_msg; | ||
| 4739 | t_CKTIME time = 0.0; | ||
| 4740 | RETURN->v_int = mrw->read( &the_msg, &time ); | ||
| 4741 | OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data1) = the_msg.data[0]; | ||
| 4742 | OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data2) = the_msg.data[1]; | ||
| 4743 | OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data3) = the_msg.data[2]; | ||
| 4744 | OBJ_MEMBER_TIME(fake_msg, MidiMsg_offset_when) = time; | ||
| 4745 | #endif // __DISABLE_MIDI__ | ||
| 4746 | } | ||
| 4747 | |||
| 4748 | CK_DLL_MFUN( MidiRW_write ) | ||
| 4749 | { | ||
| 4750 | #ifndef __DISABLE_MIDI__ | ||
| 4751 | MidiRW * mrw = (MidiRW *)OBJ_MEMBER_INT(SELF, MidiRW_offset_data); | ||
| 4752 | Chuck_Object * fake_msg = GET_NEXT_OBJECT(ARGS); | ||
| 4753 | t_CKTIME time = GET_NEXT_TIME(ARGS); | ||
| 4754 | MidiMsg the_msg; | ||
| 4755 | the_msg.data[0] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data1); | ||
| 4756 | the_msg.data[1] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data2); | ||
| 4757 | the_msg.data[2] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data3); | ||
| 4758 | RETURN->v_int = mrw->write( &the_msg, &time ); | ||
| 4759 | #endif // __DISABLE_MIDI__ | ||
| 4760 | } | ||
| 4761 | |||
| 4762 | |||
| 4763 | //----------------------------------------------------------------------------- | ||
| 4764 | // MidiMsgOut API | ||
| 4765 | //----------------------------------------------------------------------------- | ||
| 4766 | CK_DLL_CTOR( MidiMsgOut_ctor ) | ||
| 4767 | { | ||
| 4768 | #ifndef __DISABLE_MIDI__ | ||
| 4769 | OBJ_MEMBER_INT(SELF, MidiMsgOut_offset_data) = (t_CKUINT)new MidiMsgOut; | ||
| 4770 | #endif // __DISABLE_MIDI__ | ||
| 4771 | } | ||
| 4772 | |||
| 4773 | CK_DLL_DTOR( MidiMsgOut_dtor ) | ||
| 4774 | { | ||
| 4775 | #ifndef __DISABLE_MIDI__ | ||
| 4776 | delete (MidiMsgOut *)OBJ_MEMBER_INT(SELF, MidiMsgOut_offset_data); | ||
| 4777 | OBJ_MEMBER_INT(SELF, MidiMsgOut_offset_data) = 0; | ||
| 4778 | #endif // __DISABLE_MIDI__ | ||
| 4779 | } | ||
| 4780 | |||
| 4781 | CK_DLL_MFUN( MidiMsgOut_open ) | ||
| 4782 | { | ||
| 4783 | #ifndef __DISABLE_MIDI__ | ||
| 4784 | MidiMsgOut * mrw = (MidiMsgOut *)OBJ_MEMBER_INT(SELF, MidiMsgOut_offset_data); | ||
| 4785 | const char * filename = GET_CK_STRING(ARGS)->str().c_str(); | ||
| 4786 | RETURN->v_int = mrw->open( filename ); | ||
| 4787 | #endif // __DISABLE_MIDI__ | ||
| 4788 | } | ||
| 4789 | |||
| 4790 | CK_DLL_MFUN( MidiMsgOut_close ) | ||
| 4791 | { | ||
| 4792 | #ifndef __DISABLE_MIDI__ | ||
| 4793 | MidiMsgOut * mrw = (MidiMsgOut *)OBJ_MEMBER_INT(SELF, MidiMsgOut_offset_data); | ||
| 4794 | RETURN->v_int = mrw->close(); | ||
| 4795 | #endif // __DISABLE_MIDI__ | ||
| 4796 | } | ||
| 4797 | |||
| 4798 | CK_DLL_MFUN( MidiMsgOut_write ) | ||
| 4799 | { | ||
| 4800 | #ifndef __DISABLE_MIDI__ | ||
| 4801 | MidiMsgOut * mrw = (MidiMsgOut *)OBJ_MEMBER_INT(SELF, MidiMsgOut_offset_data); | ||
| 4802 | Chuck_Object * fake_msg = GET_NEXT_OBJECT(ARGS); | ||
| 4803 | t_CKTIME time = GET_NEXT_TIME(ARGS); | ||
| 4804 | MidiMsg the_msg; | ||
| 4805 | the_msg.data[0] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data1); | ||
| 4806 | the_msg.data[1] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data2); | ||
| 4807 | the_msg.data[2] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data3); | ||
| 4808 | RETURN->v_int = mrw->write( &the_msg, &time ); | ||
| 4809 | #endif // __DISABLE_MIDI__ | ||
| 4810 | } | ||
| 4811 | |||
| 4812 | |||
| 4813 | //----------------------------------------------------------------------------- | ||
| 4814 | // MidiMsgIn API | ||
| 4815 | //----------------------------------------------------------------------------- | ||
| 4816 | CK_DLL_CTOR( MidiMsgIn_ctor ) | ||
| 4817 | { | ||
| 4818 | #ifndef __DISABLE_MIDI__ | ||
| 4819 | OBJ_MEMBER_INT(SELF, MidiMsgIn_offset_data) = (t_CKUINT)new MidiMsgIn; | ||
| 4820 | #endif // __DISABLE_MIDI__ | ||
| 4821 | } | ||
| 4822 | |||
| 4823 | CK_DLL_DTOR( MidiMsgIn_dtor ) | ||
| 4824 | { | ||
| 4825 | #ifndef __DISABLE_MIDI__ | ||
| 4826 | delete (MidiMsgIn *)OBJ_MEMBER_INT(SELF, MidiMsgIn_offset_data); | ||
| 4827 | OBJ_MEMBER_INT(SELF, MidiMsgIn_offset_data) = 0; | ||
| 4828 | #endif // __DISABLE_MIDI__ | ||
| 4829 | } | ||
| 4830 | |||
| 4831 | CK_DLL_MFUN( MidiMsgIn_open ) | ||
| 4832 | { | ||
| 4833 | #ifndef __DISABLE_MIDI__ | ||
| 4834 | MidiMsgIn * mrw = (MidiMsgIn *)OBJ_MEMBER_INT(SELF, MidiMsgIn_offset_data); | ||
| 4835 | const char * filename = GET_CK_STRING(ARGS)->str().c_str(); | ||
| 4836 | RETURN->v_int = mrw->open( filename ); | ||
| 4837 | #endif // __DISABLE_MIDI__ | ||
| 4838 | } | ||
| 4839 | |||
| 4840 | CK_DLL_MFUN( MidiMsgIn_close ) | ||
| 4841 | { | ||
| 4842 | #ifndef __DISABLE_MIDI__ | ||
| 4843 | MidiMsgIn * mrw = (MidiMsgIn *)OBJ_MEMBER_INT(SELF, MidiMsgIn_offset_data); | ||
| 4844 | RETURN->v_int = mrw->close(); | ||
| 4845 | #endif // __DISABLE_MIDI__ | ||
| 4846 | } | ||
| 4847 | |||
| 4848 | CK_DLL_MFUN( MidiMsgIn_read ) | ||
| 4849 | { | ||
| 4850 | #ifndef __DISABLE_MIDI__ | ||
| 4851 | MidiMsgIn * mrw = (MidiMsgIn *)OBJ_MEMBER_INT(SELF, MidiMsgIn_offset_data); | ||
| 4852 | Chuck_Object * fake_msg = GET_NEXT_OBJECT(ARGS); | ||
| 4853 | MidiMsg the_msg; | ||
| 4854 | t_CKTIME time = 0.0; | ||
| 4855 | RETURN->v_int = mrw->read( &the_msg, &time ); | ||
| 4856 | OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data1) = the_msg.data[0]; | ||
| 4857 | OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data2) = the_msg.data[1]; | ||
| 4858 | OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data3) = the_msg.data[2]; | ||
| 4859 | OBJ_MEMBER_TIME(fake_msg, MidiMsg_offset_when) = time; | ||
| 4860 | #endif // __DISABLE_MIDI__ | ||
| 4861 | } | ||
| @@ -0,0 +1,481 @@ | |||
| 1 | /*---------------------------------------------------------------------------- | ||
| 2 | ChucK Concurrent, On-the-fly Audio Programming Language | ||
| 3 | Compiler and Virtual Machine | ||
| 4 | |||
| 5 | Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. | ||
| 6 | http://chuck.stanford.edu/ | ||
| 7 | http://chuck.cs.princeton.edu/ | ||
| 8 | |||
| 9 | This program is free software; you can redistribute it and/or modify | ||
| 10 | it under the terms of the GNU General Public License as published by | ||
| 11 | the Free Software Foundation; either version 2 of the License, or | ||
| 12 | (at your option) any later version. | ||
| 13 | |||
| 14 | This program is distributed in the hope that it will be useful, | ||
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | GNU General Public License for more details. | ||
| 18 | |||
| 19 | You should have received a copy of the GNU General Public License | ||
| 20 | along with this program; if not, write to the Free Software | ||
| 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
| 22 | U.S.A. | ||
| 23 | -----------------------------------------------------------------------------*/ | ||
| 24 | |||
| 25 | //----------------------------------------------------------------------------- | ||
| 26 | // name: chuck_lang.h | ||
| 27 | // desc: chuck class library base | ||
| 28 | // | ||
| 29 | // authors: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) | ||
| 30 | // Spencer Salazar (spencer@ccrma.stanford.edu) | ||
| 31 | // Ananya Misra (amisra@cs.princeton.edu) | ||
| 32 | // Andrew Schran (aschran@princeton.edu) | ||
| 33 | // date: spring 2005 | ||
| 34 | //----------------------------------------------------------------------------- | ||
| 35 | #ifndef __CHUCK_LANG_H__ | ||
| 36 | #define __CHUCK_LANG_H__ | ||
| 37 | |||
| 38 | #include "chuck_def.h" | ||
| 39 | #include "chuck_oo.h" | ||
| 40 | #include "chuck_dl.h" | ||
| 41 | #include <queue> | ||
| 42 | |||
| 43 | |||
| 44 | // forward reference | ||
| 45 | struct Chuck_UAna; | ||
| 46 | |||
| 47 | // query | ||
| 48 | DLL_QUERY lang_query( Chuck_DL_Query * QUERY ); | ||
| 49 | |||
| 50 | // base class initialization | ||
| 51 | t_CKBOOL init_class_object( Chuck_Env * env, Chuck_Type * type ); | ||
| 52 | t_CKBOOL init_class_ugen( Chuck_Env * env, Chuck_Type * type ); | ||
| 53 | t_CKBOOL init_class_uana( Chuck_Env * env, Chuck_Type * type ); | ||
| 54 | t_CKBOOL init_class_blob( Chuck_Env * env, Chuck_Type * type ); | ||
| 55 | t_CKBOOL init_class_event( Chuck_Env * env, Chuck_Type * type ); | ||
| 56 | t_CKBOOL init_class_shred( Chuck_Env * env, Chuck_Type * type ); | ||
| 57 | t_CKBOOL init_class_string( Chuck_Env * env, Chuck_Type * type ); | ||
| 58 | t_CKBOOL init_class_array( Chuck_Env * env, Chuck_Type * type ); | ||
| 59 | t_CKBOOL init_class_vec3( Chuck_Env * env, Chuck_Type * type ); // 1.3.5.3 | ||
| 60 | t_CKBOOL init_class_vec4( Chuck_Env * env, Chuck_Type * type ); // 1.3.5.3 | ||
| 61 | |||
| 62 | t_CKBOOL init_class_Midi( Chuck_Env * env ); | ||
| 63 | t_CKBOOL init_class_MidiRW( Chuck_Env * env ); | ||
| 64 | t_CKBOOL init_class_HID( Chuck_Env * env ); | ||
| 65 | t_CKBOOL init_class_io( Chuck_Env * env, Chuck_Type * type ); | ||
| 66 | t_CKBOOL init_class_fileio( Chuck_Env * env, Chuck_Type * type ); | ||
| 67 | // added 1.3.0.0 -- moved to be full-fledged class | ||
| 68 | t_CKBOOL init_class_chout( Chuck_Env * env, Chuck_Type * type ); | ||
| 69 | // added 1.3.0.0 -- moved to be full-fledged class | ||
| 70 | t_CKBOOL init_class_cherr( Chuck_Env * env, Chuck_Type * type ); | ||
| 71 | |||
| 72 | |||
| 73 | |||
| 74 | |||
| 75 | //----------------------------------------------------------------------------- | ||
| 76 | // object API | ||
| 77 | //----------------------------------------------------------------------------- | ||
| 78 | CK_DLL_CTOR( object_ctor ); | ||
| 79 | CK_DLL_DTOR( object_dtor ); | ||
| 80 | CK_DLL_MFUN( object_equals ); | ||
| 81 | CK_DLL_MFUN( object_getType ); | ||
| 82 | CK_DLL_MFUN( object_hashCode ); | ||
| 83 | CK_DLL_MFUN( object_toString ); | ||
| 84 | |||
| 85 | |||
| 86 | //----------------------------------------------------------------------------- | ||
| 87 | // ugen API | ||
| 88 | //----------------------------------------------------------------------------- | ||
| 89 | CK_DLL_CTOR( ugen_ctor ); | ||
| 90 | CK_DLL_DTOR( ugen_dtor ); | ||
| 91 | CK_DLL_MFUN( ugen_op ); | ||
| 92 | CK_DLL_MFUN( ugen_cget_op ); | ||
| 93 | CK_DLL_MFUN( ugen_last ); | ||
| 94 | CK_DLL_MFUN( ugen_cget_last ); | ||
| 95 | CK_DLL_MFUN( ugen_next ); | ||
| 96 | CK_DLL_MFUN( ugen_cget_next ); | ||
| 97 | CK_DLL_MFUN( ugen_gain ); | ||
| 98 | CK_DLL_MFUN( ugen_cget_gain ); | ||
| 99 | CK_DLL_MFUN( ugen_numChannels ); | ||
| 100 | CK_DLL_MFUN( ugen_cget_numChannels ); | ||
| 101 | CK_DLL_MFUN( ugen_chan ); | ||
| 102 | CK_DLL_MFUN( ugen_connected ); | ||
| 103 | |||
| 104 | |||
| 105 | //----------------------------------------------------------------------------- | ||
| 106 | // uana API | ||
| 107 | //----------------------------------------------------------------------------- | ||
| 108 | CK_DLL_CTOR( uana_ctor ); | ||
| 109 | CK_DLL_DTOR( uana_dtor ); | ||
| 110 | CK_DLL_MFUN( uana_upchuck ); | ||
| 111 | CK_DLL_MFUN( uana_blob ); | ||
| 112 | CK_DLL_MFUN( uana_fvals ); | ||
| 113 | CK_DLL_MFUN( uana_cvals ); | ||
| 114 | CK_DLL_MFUN( uana_fval ); | ||
| 115 | CK_DLL_MFUN( uana_cval ); | ||
| 116 | CK_DLL_MFUN( uana_connected ); | ||
| 117 | |||
| 118 | |||
| 119 | //----------------------------------------------------------------------------- | ||
| 120 | // uanablob API | ||
| 121 | //----------------------------------------------------------------------------- | ||
| 122 | CK_DLL_CTOR( uanablob_ctor ); | ||
| 123 | CK_DLL_DTOR( uanablob_dtor ); | ||
| 124 | CK_DLL_MFUN( uanablob_fvals ); | ||
| 125 | CK_DLL_MFUN( uanablob_cvals ); | ||
| 126 | CK_DLL_MFUN( uanablob_fval ); | ||
| 127 | CK_DLL_MFUN( uanablob_cval ); | ||
| 128 | CK_DLL_MFUN( uanablob_when ); | ||
| 129 | |||
| 130 | |||
| 131 | //----------------------------------------------------------------------------- | ||
| 132 | // name: Chuck_UAnaBlobProxy | ||
| 133 | // desc: proxy for interfacing with UAnaBlob, which is a Chuck class | ||
| 134 | //----------------------------------------------------------------------------- | ||
| 135 | struct Chuck_UAnaBlobProxy | ||
| 136 | { | ||
| 137 | public: | ||
| 138 | Chuck_UAnaBlobProxy( Chuck_Object * blob ); | ||
| 139 | virtual ~Chuck_UAnaBlobProxy(); | ||
| 140 | |||
| 141 | public: | ||
| 142 | t_CKTIME & when(); | ||
| 143 | Chuck_Array8 & fvals(); | ||
| 144 | Chuck_Array16 & cvals(); | ||
| 145 | |||
| 146 | public: | ||
| 147 | Chuck_Object * realblob() { return m_blob; } | ||
| 148 | |||
| 149 | protected: | ||
| 150 | Chuck_Object * m_blob; | ||
| 151 | }; | ||
| 152 | |||
| 153 | // get proxy | ||
| 154 | Chuck_UAnaBlobProxy * getBlobProxy( const Chuck_UAna * uana ); | ||
| 155 | |||
| 156 | |||
| 157 | //----------------------------------------------------------------------------- | ||
| 158 | // shred API | ||
| 159 | //----------------------------------------------------------------------------- | ||
| 160 | CK_DLL_CTOR( shred_ctor ); | ||
| 161 | CK_DLL_DTOR( shred_dtor ); | ||
| 162 | CK_DLL_MFUN( shred_exit ); | ||
| 163 | CK_DLL_MFUN( shred_clone ); | ||
| 164 | CK_DLL_MFUN( shred_id ); | ||
| 165 | CK_DLL_MFUN( shred_yield ); | ||
| 166 | CK_DLL_MFUN( shred_running ); | ||
| 167 | CK_DLL_MFUN( shred_done ); | ||
| 168 | CK_DLL_MFUN( shred_numArgs ); | ||
| 169 | CK_DLL_MFUN( shred_getArg ); | ||
| 170 | CK_DLL_MFUN( shred_sourcePath ); // added 1.3.0.0 | ||
| 171 | CK_DLL_MFUN( shred_sourceDir ); // added 1.3.0.0 | ||
| 172 | CK_DLL_MFUN( shred_sourceDir2 ); // added 1.3.2.0 | ||
| 173 | CK_DLL_SFUN( shred_fromId ); // added 1.3.2.0 | ||
| 174 | |||
| 175 | |||
| 176 | //----------------------------------------------------------------------------- | ||
| 177 | // array API | ||
| 178 | //----------------------------------------------------------------------------- | ||
| 179 | CK_DLL_CTOR( array_ctor ); | ||
| 180 | CK_DLL_DTOR( array_dtor ); | ||
| 181 | CK_DLL_MFUN( array_set_capacity ); | ||
| 182 | CK_DLL_MFUN( array_get_capacity ); | ||
| 183 | CK_DLL_MFUN( array_get_capacity_hack ); | ||
| 184 | CK_DLL_MFUN( array_set_size ); | ||
| 185 | CK_DLL_MFUN( array_get_size ); | ||
| 186 | CK_DLL_MFUN( array_push_back ); | ||
| 187 | CK_DLL_MFUN( array_pop_back ); | ||
| 188 | CK_DLL_MFUN( array_push_front ); | ||
| 189 | CK_DLL_MFUN( array_pop_front ); | ||
| 190 | CK_DLL_MFUN( array_find ); | ||
| 191 | CK_DLL_MFUN( array_erase ); | ||
| 192 | CK_DLL_MFUN( array_clear ); | ||
| 193 | CK_DLL_MFUN( array_reset ); | ||
| 194 | |||
| 195 | |||
| 196 | //----------------------------------------------------------------------------- | ||
| 197 | // event API | ||
| 198 | //----------------------------------------------------------------------------- | ||
| 199 | CK_DLL_CTOR( event_ctor ); | ||
| 200 | CK_DLL_DTOR( event_dtor ); | ||
| 201 | CK_DLL_MFUN( event_signal ); | ||
| 202 | CK_DLL_MFUN( event_broadcast ); | ||
| 203 | CK_DLL_MFUN( event_wait ); | ||
| 204 | CK_DLL_MFUN( event_can_wait ); | ||
| 205 | |||
| 206 | |||
| 207 | //----------------------------------------------------------------------------- | ||
| 208 | // io API | ||
| 209 | //----------------------------------------------------------------------------- | ||
| 210 | CK_DLL_MFUN( io_dummy ); | ||
| 211 | CK_DLL_SFUN( io_newline ); | ||
| 212 | CK_DLL_SFUN( io_openfile ); | ||
| 213 | |||
| 214 | |||
| 215 | //----------------------------------------------------------------------------- | ||
| 216 | // fileio API | ||
| 217 | //----------------------------------------------------------------------------- | ||
| 218 | CK_DLL_CTOR( fileio_ctor ); | ||
| 219 | CK_DLL_DTOR( fileio_dtor ); | ||
| 220 | CK_DLL_MFUN( fileio_open ); | ||
| 221 | CK_DLL_MFUN( fileio_openflags ); | ||
| 222 | CK_DLL_MFUN( fileio_good ); | ||
| 223 | CK_DLL_MFUN( fileio_close ); | ||
| 224 | CK_DLL_MFUN( fileio_flush ); | ||
| 225 | CK_DLL_MFUN( fileio_getmode ); | ||
| 226 | CK_DLL_MFUN( fileio_setmode ); | ||
| 227 | CK_DLL_MFUN( fileio_size ); | ||
| 228 | CK_DLL_MFUN( fileio_seek ); | ||
| 229 | CK_DLL_MFUN( fileio_tell ); | ||
| 230 | CK_DLL_MFUN( fileio_isdir ); | ||
| 231 | CK_DLL_MFUN( fileio_dirlist ); | ||
| 232 | CK_DLL_MFUN( fileio_read ); | ||
| 233 | CK_DLL_MFUN( fileio_readline ); | ||
| 234 | CK_DLL_MFUN( fileio_readint ); | ||
| 235 | CK_DLL_MFUN( fileio_readintflags ); | ||
| 236 | CK_DLL_MFUN( fileio_readfloat ); | ||
| 237 | CK_DLL_MFUN( fileio_eof ); | ||
| 238 | CK_DLL_MFUN( fileio_more ); | ||
| 239 | CK_DLL_MFUN( fileio_writestring ); | ||
| 240 | CK_DLL_MFUN( fileio_writeint ); | ||
| 241 | CK_DLL_MFUN( fileio_writeintflags ); | ||
| 242 | CK_DLL_MFUN( fileio_writefloat ); | ||
| 243 | |||
| 244 | |||
| 245 | //----------------------------------------------------------------------------- | ||
| 246 | // chout API -- added 1.3.0.0 as full class | ||
| 247 | //----------------------------------------------------------------------------- | ||
| 248 | CK_DLL_MFUN( chout_good ); | ||
| 249 | CK_DLL_MFUN( chout_close ); | ||
| 250 | CK_DLL_MFUN( chout_flush ); | ||
| 251 | CK_DLL_MFUN( chout_getmode ); | ||
| 252 | CK_DLL_MFUN( chout_setmode ); | ||
| 253 | CK_DLL_MFUN( chout_read ); | ||
| 254 | CK_DLL_MFUN( chout_readline ); | ||
| 255 | CK_DLL_MFUN( chout_readint ); | ||
| 256 | CK_DLL_MFUN( chout_readintflags ); | ||
| 257 | CK_DLL_MFUN( chout_readfloat ); | ||
| 258 | CK_DLL_MFUN( chout_eof ); | ||
| 259 | CK_DLL_MFUN( chout_more ); | ||
| 260 | CK_DLL_MFUN( chout_writestring ); | ||
| 261 | CK_DLL_MFUN( chout_writeint ); | ||
| 262 | CK_DLL_MFUN( chout_writefloat ); | ||
| 263 | |||
| 264 | |||
| 265 | //----------------------------------------------------------------------------- | ||
| 266 | // cherr API -- added 1.3.0.0 as full class | ||
| 267 | //----------------------------------------------------------------------------- | ||
| 268 | CK_DLL_MFUN( cherr_good ); | ||
| 269 | CK_DLL_MFUN( cherr_close ); | ||
| 270 | CK_DLL_MFUN( cherr_flush ); | ||
| 271 | CK_DLL_MFUN( cherr_getmode ); | ||
| 272 | CK_DLL_MFUN( cherr_setmode ); | ||
| 273 | CK_DLL_MFUN( cherr_read ); | ||
| 274 | CK_DLL_MFUN( cherr_readline ); | ||
| 275 | CK_DLL_MFUN( cherr_readint ); | ||
| 276 | CK_DLL_MFUN( cherr_readintflags ); | ||
| 277 | CK_DLL_MFUN( cherr_readfloat ); | ||
| 278 | CK_DLL_MFUN( cherr_eof ); | ||
| 279 | CK_DLL_MFUN( cherr_more ); | ||
| 280 | CK_DLL_MFUN( cherr_writestring ); | ||
| 281 | CK_DLL_MFUN( cherr_writeint ); | ||
| 282 | CK_DLL_MFUN( cherr_writefloat ); | ||
| 283 | |||
| 284 | |||
| 285 | //----------------------------------------------------------------------------- | ||
| 286 | // string API | ||
| 287 | //----------------------------------------------------------------------------- | ||
| 288 | CK_DLL_CTOR( string_ctor ); | ||
| 289 | CK_DLL_DTOR( string_dtor ); | ||
| 290 | CK_DLL_MFUN( string_length ); | ||
| 291 | CK_DLL_MFUN( string_upper ); | ||
| 292 | CK_DLL_MFUN( string_lower ); | ||
| 293 | CK_DLL_MFUN( string_ltrim ); | ||
| 294 | CK_DLL_MFUN( string_rtrim ); | ||
| 295 | CK_DLL_MFUN( string_trim ); | ||
| 296 | CK_DLL_MFUN( string_toString ); | ||
| 297 | CK_DLL_MFUN( string_set_at ); | ||
| 298 | CK_DLL_MFUN( string_get_at ); | ||
| 299 | CK_DLL_MFUN( string_charAt); | ||
| 300 | CK_DLL_MFUN( string_setCharAt); | ||
| 301 | CK_DLL_MFUN( string_substring); | ||
| 302 | CK_DLL_MFUN( string_substringN); | ||
| 303 | CK_DLL_MFUN( string_insert); | ||
| 304 | CK_DLL_MFUN( string_replace); | ||
| 305 | CK_DLL_MFUN( string_replaceN); | ||
| 306 | CK_DLL_MFUN( string_find); | ||
| 307 | CK_DLL_MFUN( string_findStart); | ||
| 308 | CK_DLL_MFUN( string_findStr); | ||
| 309 | CK_DLL_MFUN( string_findStrStart); | ||
| 310 | CK_DLL_MFUN( string_rfind); | ||
| 311 | CK_DLL_MFUN( string_rfindStart); | ||
| 312 | CK_DLL_MFUN( string_rfindStr); | ||
| 313 | CK_DLL_MFUN( string_rfindStrStart); | ||
| 314 | CK_DLL_MFUN( string_erase); | ||
| 315 | CK_DLL_MFUN( string_toInt); | ||
| 316 | CK_DLL_MFUN( string_toFloat); | ||
| 317 | CK_DLL_MFUN( string_parent); | ||
| 318 | |||
| 319 | |||
| 320 | //----------------------------------------------------------------------------- | ||
| 321 | // vector API (vec3, vec4, eventually vector) ge: 1.3.5.3 | ||
| 322 | //----------------------------------------------------------------------------- | ||
| 323 | CK_DLL_MFUN( vec3_set ); | ||
| 324 | CK_DLL_MFUN( vec3_setAll ); | ||
| 325 | CK_DLL_MFUN( vec3_magnitude ); | ||
| 326 | CK_DLL_MFUN( vec3_normalize ); | ||
| 327 | CK_DLL_MFUN( vec3_interp ); | ||
| 328 | CK_DLL_MFUN( vec3_interp_delta_float ); | ||
| 329 | CK_DLL_MFUN( vec3_interp_delta_dur ); | ||
| 330 | CK_DLL_MFUN( vec3_update_goal ); | ||
| 331 | CK_DLL_MFUN( vec3_update_goal_slew ); | ||
| 332 | CK_DLL_MFUN( vec3_updateSet_goalAndValue ); | ||
| 333 | CK_DLL_MFUN( vec3_updateSet_goalAndValue_slew ); | ||
| 334 | CK_DLL_MFUN( vec4_set ); | ||
| 335 | CK_DLL_MFUN( vec4_setAll ); | ||
| 336 | CK_DLL_MFUN( vec4_magnitude ); | ||
| 337 | CK_DLL_MFUN( vec4_normalize ); | ||
| 338 | |||
| 339 | |||
| 340 | //----------------------------------------------------------------------------- | ||
| 341 | // name: Data_Exception | ||
| 342 | // desc: data for base Chuck Exception class | ||
| 343 | //----------------------------------------------------------------------------- | ||
| 344 | struct Data_Exception | ||
| 345 | { | ||
| 346 | public: | ||
| 347 | Data_Exception(); | ||
| 348 | ~Data_Exception(); | ||
| 349 | |||
| 350 | public: | ||
| 351 | }; | ||
| 352 | //----------------------------------------------------------------------------- | ||
| 353 | // exception API | ||
| 354 | //----------------------------------------------------------------------------- | ||
| 355 | |||
| 356 | |||
| 357 | //----------------------------------------------------------------------------- | ||
| 358 | // MidiMsg API | ||
| 359 | //----------------------------------------------------------------------------- | ||
| 360 | CK_DLL_CTOR( MidiMsg_ctor ); | ||
| 361 | |||
| 362 | extern t_CKUINT MidiMsg_offset_data1; | ||
| 363 | extern t_CKUINT MidiMsg_offset_data2; | ||
| 364 | extern t_CKUINT MidiMsg_offset_data3; | ||
| 365 | extern t_CKUINT MidiMsg_offset_when; | ||
| 366 | |||
| 367 | //----------------------------------------------------------------------------- | ||
| 368 | // MidiRW API | ||
| 369 | //----------------------------------------------------------------------------- | ||
| 370 | CK_DLL_CTOR( MidiRW_ctor ); | ||
| 371 | CK_DLL_DTOR( MidiRW_dtor ); | ||
| 372 | CK_DLL_MFUN( MidiRW_open ); | ||
| 373 | CK_DLL_MFUN( MidiRW_close ); | ||
| 374 | CK_DLL_MFUN( MidiRW_read ); | ||
| 375 | CK_DLL_MFUN( MidiRW_write ); | ||
| 376 | |||
| 377 | |||
| 378 | //----------------------------------------------------------------------------- | ||
| 379 | // MidiMsgOut API | ||
| 380 | //----------------------------------------------------------------------------- | ||
| 381 | CK_DLL_CTOR( MidiMsgOut_ctor ); | ||
| 382 | CK_DLL_DTOR( MidiMsgOut_dtor ); | ||
| 383 | CK_DLL_MFUN( MidiMsgOut_open ); | ||
| 384 | CK_DLL_MFUN( MidiMsgOut_close ); | ||
| 385 | CK_DLL_MFUN( MidiMsgOut_write ); | ||
| 386 | |||
| 387 | |||
| 388 | //----------------------------------------------------------------------------- | ||
| 389 | // MidiMsgIn API | ||
| 390 | //----------------------------------------------------------------------------- | ||
| 391 | CK_DLL_CTOR( MidiMsgIn_ctor ); | ||
| 392 | CK_DLL_DTOR( MidiMsgIn_dtor ); | ||
| 393 | CK_DLL_MFUN( MidiMsgIn_open ); | ||
| 394 | CK_DLL_MFUN( MidiMsgIn_close ); | ||
| 395 | CK_DLL_MFUN( MidiMsgIn_read ); | ||
| 396 | |||
| 397 | |||
| 398 | //----------------------------------------------------------------------------- | ||
| 399 | // MidiIn API | ||
| 400 | //----------------------------------------------------------------------------- | ||
| 401 | CK_DLL_CTOR( MidiIn_ctor ); | ||
| 402 | CK_DLL_DTOR( MidiIn_dtor ); | ||
| 403 | CK_DLL_MFUN( MidiIn_open ); | ||
| 404 | CK_DLL_MFUN( MidiIn_open_named ); // added 1.3.0.0 | ||
| 405 | CK_DLL_MFUN( MidiIn_open_named_i ); // added 1.3.0.0 | ||
| 406 | CK_DLL_MFUN( MidiIn_good ); | ||
| 407 | CK_DLL_MFUN( MidiIn_num ); | ||
| 408 | CK_DLL_MFUN( MidiIn_name ); | ||
| 409 | CK_DLL_MFUN( MidiIn_printerr ); | ||
| 410 | CK_DLL_MFUN( MidiIn_recv ); | ||
| 411 | CK_DLL_MFUN( MidiIn_can_wait ); | ||
| 412 | |||
| 413 | |||
| 414 | //----------------------------------------------------------------------------- | ||
| 415 | // MidiOut API | ||
| 416 | //----------------------------------------------------------------------------- | ||
| 417 | CK_DLL_CTOR( MidiOut_ctor ); | ||
| 418 | CK_DLL_DTOR( MidiOut_dtor ); | ||
| 419 | CK_DLL_MFUN( MidiOut_open ); | ||
| 420 | CK_DLL_MFUN( MidiOut_open_named ); // added 1.3.0.0 | ||
| 421 | CK_DLL_MFUN( MidiOut_open_named_i); // added 1.3.0.0 | ||
| 422 | CK_DLL_MFUN( MidiOut_good ); | ||
| 423 | CK_DLL_MFUN( MidiOut_num ); | ||
| 424 | CK_DLL_MFUN( MidiOut_name ); | ||
| 425 | CK_DLL_MFUN( MidiOut_printerr ); | ||
| 426 | CK_DLL_MFUN( MidiOut_send ); | ||
| 427 | |||
| 428 | |||
| 429 | //----------------------------------------------------------------------------- | ||
| 430 | // HidMsg API | ||
| 431 | //----------------------------------------------------------------------------- | ||
| 432 | CK_DLL_MFUN( HidMsg_is_axis_motion ); | ||
| 433 | CK_DLL_MFUN( HidMsg_is_button_down ); | ||
| 434 | CK_DLL_MFUN( HidMsg_is_button_up ); | ||
| 435 | CK_DLL_MFUN( HidMsg_is_mouse_motion ); | ||
| 436 | CK_DLL_MFUN( HidMsg_is_hat_motion ); | ||
| 437 | CK_DLL_MFUN( HidMsg_is_wheel_motion ); | ||
| 438 | |||
| 439 | //----------------------------------------------------------------------------- | ||
| 440 | // HidIn API | ||
| 441 | //----------------------------------------------------------------------------- | ||
| 442 | CK_DLL_CTOR( HidIn_ctor ); | ||
| 443 | CK_DLL_DTOR( HidIn_dtor ); | ||
| 444 | CK_DLL_MFUN( HidIn_open ); | ||
| 445 | CK_DLL_MFUN( HidIn_open_named ); | ||
| 446 | CK_DLL_MFUN( HidIn_open_named_i ); // added 1.3.0.0 | ||
| 447 | CK_DLL_MFUN( HidIn_open_joystick ); | ||
| 448 | CK_DLL_MFUN( HidIn_open_mouse ); | ||
| 449 | CK_DLL_MFUN( HidIn_open_keyboard ); | ||
| 450 | CK_DLL_MFUN( HidIn_open_tiltsensor ); | ||
| 451 | CK_DLL_MFUN( HidIn_good ); | ||
| 452 | CK_DLL_MFUN( HidIn_num ); | ||
| 453 | CK_DLL_MFUN( HidIn_name ); | ||
| 454 | CK_DLL_MFUN( HidIn_printerr ); | ||
| 455 | CK_DLL_MFUN( HidIn_recv ); | ||
| 456 | CK_DLL_MFUN( HidIn_read ); | ||
| 457 | CK_DLL_MFUN( HidIn_send ); | ||
| 458 | CK_DLL_MFUN( HidIn_can_wait ); | ||
| 459 | CK_DLL_SFUN( HidIn_read_tilt_sensor ); | ||
| 460 | CK_DLL_SFUN( HidIn_ctrl_tiltPollRate ); | ||
| 461 | CK_DLL_SFUN( HidIn_cget_tiltPollRate ); | ||
| 462 | CK_DLL_SFUN( HidIn_start_cursor_track ); | ||
| 463 | CK_DLL_SFUN( HidIn_stop_cursor_track ); | ||
| 464 | |||
| 465 | |||
| 466 | //----------------------------------------------------------------------------- | ||
| 467 | // HidOut API | ||
| 468 | //----------------------------------------------------------------------------- | ||
| 469 | CK_DLL_CTOR( HidOut_ctor ); | ||
| 470 | CK_DLL_DTOR( HidOut_dtor ); | ||
| 471 | CK_DLL_MFUN( HidOut_open ); | ||
| 472 | CK_DLL_MFUN( HidOut_good ); | ||
| 473 | CK_DLL_MFUN( HidOut_num ); | ||
| 474 | CK_DLL_MFUN( HidOut_name ); | ||
| 475 | CK_DLL_MFUN( HidOut_printerr ); | ||
| 476 | CK_DLL_MFUN( HidOut_send ); | ||
| 477 | |||
| 478 | |||
| 479 | |||
| 480 | |||
| 481 | #endif | ||
| @@ -0,0 +1,3285 @@ | |||
| 1 | /*---------------------------------------------------------------------------- | ||
| 2 | ChucK Concurrent, On-the-fly Audio Programming Language | ||
| 3 | Compiler and Virtual Machine | ||
| 4 | |||
| 5 | Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. | ||
| 6 | http://chuck.stanford.edu/ | ||
| 7 | http://chuck.cs.princeton.edu/ | ||
| 8 | |||
| 9 | This program is free software; you can redistribute it and/or modify | ||
| 10 | it under the terms of the GNU General Public License as published by | ||
| 11 | the Free Software Foundation; either version 2 of the License, or | ||
| 12 | (at your option) any later version. | ||
| 13 | |||
| 14 | This program is distributed in the hope that it will be useful, | ||
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | GNU General Public License for more details. | ||
| 18 | |||
| 19 | You should have received a copy of the GNU General Public License | ||
| 20 | along with this program; if not, write to the Free Software | ||
| 21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
| 22 | U.S.A. | ||
| 23 | -----------------------------------------------------------------------------*/ | ||
| 24 | |||
| 25 | //----------------------------------------------------------------------------- | ||
| 26 | // file: chuck_oo.cpp | ||
| 27 | // desc: chuck baes objects | ||
| 28 | // | ||
| 29 | // author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu) | ||
| 30 | // Ananya Misra (amisra@cs.princeton.edu) | ||
| 31 | // Andrew Schran (aschran@princeton.edu) - fileIO implementation | ||
| 32 | // date: Autumn 2004 | ||
| 33 | //----------------------------------------------------------------------------- | ||
| 34 | #include "chuck_oo.h" | ||
| 35 | #include "chuck_type.h" | ||
| 36 | #include "chuck_vm.h" | ||
| 37 | #include "chuck_instr.h" | ||
| 38 | #include "chuck_errmsg.h" | ||
| 39 | #include "chuck_dl.h" | ||
| 40 | |||
| 41 | #include <iostream> | ||
| 42 | #include <sstream> | ||
| 43 | #include <iomanip> | ||
| 44 | #include <typeinfo> | ||
| 45 | using namespace std; | ||
| 46 | |||
| 47 | #if defined(__PLATFORM_WIN32__) | ||
| 48 | #include "dirent_win32.h" | ||
| 49 | #endif | ||
| 50 | |||
| 51 | |||
| 52 | // initialize | ||
| 53 | t_CKBOOL Chuck_VM_Object::our_locks_in_effect = TRUE; | ||
| 54 | const t_CKINT Chuck_IO::INT32 = 0x1; | ||
| 55 | const t_CKINT Chuck_IO::INT16 = 0x2; | ||
| 56 | const t_CKINT Chuck_IO::INT8 = 0x4; | ||
| 57 | const t_CKINT Chuck_IO::MODE_SYNC = 0; | ||
| 58 | const t_CKINT Chuck_IO::MODE_ASYNC = 1; | ||
| 59 | const t_CKINT Chuck_IO_File::FLAG_READ_WRITE = 0x8; | ||
| 60 | const t_CKINT Chuck_IO_File::FLAG_READONLY = 0x10; | ||
| 61 | const t_CKINT Chuck_IO_File::FLAG_WRITEONLY = 0x20; | ||
| 62 | const t_CKINT Chuck_IO_File::FLAG_APPEND = 0x40; | ||
| 63 | const t_CKINT Chuck_IO_File::TYPE_ASCII = 0x80; | ||
| 64 | const t_CKINT Chuck_IO_File::TYPE_BINARY = 0x100; | ||
| 65 | void (* Chuck_IO_Chout::m_callback)(const char *) = NULL; | ||
| 66 | void (* Chuck_IO_Cherr::m_callback)(const char *) = NULL; | ||
| 67 | std::stringstream Chuck_IO_Chout::m_buffer; | ||
| 68 | std::stringstream Chuck_IO_Cherr::m_buffer; | ||
| 69 | |||
| 70 | |||
| 71 | |||
| 72 | |||
| 73 | //----------------------------------------------------------------------------- | ||
| 74 | // name: init_ref() | ||
| 75 | // desc: initialize vm object | ||
| 76 | //----------------------------------------------------------------------------- | ||
| 77 | void Chuck_VM_Object::init_ref() | ||
| 78 | { | ||
| 79 | // set reference count | ||
| 80 | m_ref_count = 0; | ||
| 81 | // set flag | ||
| 82 | m_pooled = FALSE; | ||
| 83 | // set to not locked | ||
| 84 | m_locked = FALSE; | ||
| 85 | // set v ref | ||
| 86 | m_v_ref = NULL; | ||
| 87 | // add to vm allocator | ||
| 88 | // Chuck_VM_Alloc::instance()->add_object( this ); | ||
| 89 | } | ||
| 90 | |||
| 91 | |||
| 92 | |||
| 93 | |||
| 94 | //----------------------------------------------------------------------------- | ||
| 95 | // name: add_ref() | ||
| 96 | // desc: add reference | ||
| 97 | //----------------------------------------------------------------------------- | ||
| 98 | void Chuck_VM_Object::add_ref() | ||
| 99 | { | ||
| 100 | // increment reference count | ||
| 101 | m_ref_count++; | ||
| 102 | |||
| 103 | // if going from 0 to 1 | ||
| 104 | if( m_ref_count == 1 ) | ||
| 105 | { | ||
| 106 | // add to vm allocator | ||
| 107 | Chuck_VM_Alloc::instance()->add_object( this ); | ||
| 108 | } | ||
| 109 | |||
| 110 | // added 1.3.0.0 | ||
| 111 | CK_MEMMGMT_TRACK(CK_FPRINTF_STDERR( "Chuck_VM_Object::add_ref() : 0x%08x, %s, %lu\n", this, typeid(*this).name(), m_ref_count)); | ||
| 112 | // string n = typeid(*this).name(); | ||
| 113 | // cerr << "ADDREF: " << dec << n << " " << m_ref_count << " 0x" << hex << (int)this << endl; | ||
| 114 | } | ||
| 115 | |||
| 116 | |||
| 117 | |||
| 118 | |||
| 119 | //----------------------------------------------------------------------------- | ||
| 120 | // name: release() | ||
| 121 | // desc: remove reference | ||
| 122 | //----------------------------------------------------------------------------- | ||
| 123 | void Chuck_VM_Object::release() | ||
| 124 | { | ||
| 125 | // make sure there is at least one reference | ||
| 126 | assert( m_ref_count > 0 ); | ||
| 127 | // decrement | ||
| 128 | m_ref_count--; | ||
| 129 | |||
| 130 | // added 1.3.0.0 | ||
| 131 | CK_MEMMGMT_TRACK(CK_FPRINTF_STDERR( "Chuck_VM_Object::release() : 0x%08x, %s, %ulu\n", this, typeid(*this).name(), m_ref_count)); | ||
| 132 | // string n = typeid(*this).name(); | ||
| 133 | // cerr << "RELEASE: " << dec << n << " " << m_ref_count << " 0x" << hex << (int)this << endl; | ||
| 134 | |||
| 135 | // if no more references | ||
| 136 | if( m_ref_count == 0 ) | ||
| 137 | { | ||
| 138 | // this is not good | ||
| 139 | if( our_locks_in_effect && m_locked ) | ||
| 140 | { | ||
| 141 | EM_error2( 0, "internal error: releasing locked VM object!" ); | ||
| 142 | // fail | ||
| 143 | assert( FALSE ); | ||
| 144 | // in case assert is disabled | ||
| 145 | *(int *)0 = 1; | ||
| 146 | } | ||
| 147 | |||
| 148 | // tell the object manager to set this free | ||
| 149 | Chuck_VM_Alloc::instance()->free_object( this ); | ||
| 150 | } | ||
| 151 | } | ||
| 152 | |||
| 153 | |||
| 154 | |||
| 155 | |||
| 156 | //----------------------------------------------------------------------------- | ||
| 157 | // name: lock() | ||
| 158 | // desc: lock to keep from deleted | ||
| 159 | //----------------------------------------------------------------------------- | ||
| 160 | void Chuck_VM_Object::lock() | ||
| 161 | { | ||
| 162 | m_locked = TRUE; | ||
| 163 | } | ||
| 164 | |||
| 165 | |||
| 166 | |||
| 167 | |||
| 168 | //----------------------------------------------------------------------------- | ||
| 169 | // name: lock_all() | ||
| 170 | // desc: disallow deletion of locked objects | ||
| 171 | //----------------------------------------------------------------------------- | ||
| 172 | void Chuck_VM_Object::lock_all() | ||
| 173 | { | ||
| 174 | // log | ||
| 175 | EM_log( CK_LOG_SYSTEM, "locking down special objects..." ); | ||
| 176 | // set flag | ||
| 177 | our_locks_in_effect = TRUE; | ||
| 178 | } | ||
| 179 | |||
| 180 | |||
| 181 | |||
| 182 | |||
| 183 | //----------------------------------------------------------------------------- | ||
| 184 | // name: unlock_all() | ||
| 185 | // desc: allow deletion of locked objects (USE WITH CAUTION!) | ||
| 186 | //----------------------------------------------------------------------------- | ||
| 187 | void Chuck_VM_Object::unlock_all() | ||
| 188 | { | ||
| 189 | // log | ||
| 190 | EM_log( CK_LOG_SYSTEM, "unprotecting special objects..." ); | ||
| 191 | // set flag | ||
| 192 | our_locks_in_effect = FALSE; | ||
| 193 | } | ||
| 194 | |||
| 195 | |||
| 196 | |||
| 197 | |||
| 198 | // static member | ||
| 199 | Chuck_VM_Alloc * Chuck_VM_Alloc::our_instance = NULL; | ||
| 200 | |||
| 201 | |||
| 202 | //----------------------------------------------------------------------------- | ||
| 203 | // name: instance() | ||
| 204 | // desc: return static instance | ||
| 205 | //----------------------------------------------------------------------------- | ||
| 206 | Chuck_VM_Alloc * Chuck_VM_Alloc::instance() | ||
| 207 | { | ||
| 208 | if( !our_instance ) | ||
| 209 | { | ||
| 210 | our_instance = new Chuck_VM_Alloc; | ||
| 211 | assert( our_instance != NULL ); | ||
| 212 | } | ||
| 213 | |||
| 214 | return our_instance; | ||
| 215 | } | ||
| 216 | |||
| 217 | |||
| 218 | |||
| 219 | |||
| 220 | //----------------------------------------------------------------------------- | ||
| 221 | // name: add_object() | ||
| 222 | // desc: add newly allocated vm object | ||
| 223 | //----------------------------------------------------------------------------- | ||
| 224 | void Chuck_VM_Alloc::add_object( Chuck_VM_Object * obj ) | ||
| 225 | { | ||
| 226 | // do log | ||
| 227 | if( DO_LOG( CK_LOG_CRAZY ) ) | ||
| 228 | { | ||
| 229 | // log it | ||
| 230 | EM_log( CK_LOG_CRAZY, "adding '%s' (0x%lx)...", | ||
| 231 | mini_type( typeid(*obj).name() ), obj ); | ||
| 232 | } | ||
| 233 | |||
| 234 | // add it to map | ||
| 235 | } | ||
| 236 | |||
| 237 | |||
| 238 | |||
| 239 | |||
| 240 | //----------------------------------------------------------------------------- | ||
| 241 | // name: free_object() | ||
| 242 | // desc: free vm object - reference count should be 0 | ||
| 243 | //----------------------------------------------------------------------------- | ||
| 244 | void Chuck_VM_Alloc::free_object( Chuck_VM_Object * obj ) | ||
| 245 | { | ||
| 246 | // make sure the ref count is 0 | ||
| 247 | assert( obj && obj->m_ref_count == 0 ); | ||
| 248 | |||
| 249 | // do log | ||
| 250 | if( DO_LOG( CK_LOG_FINEST ) ) | ||
| 251 | { | ||
| 252 | // log it | ||
| 253 | EM_log( CK_LOG_FINEST, "freeing '%s' (0x%lx)...", | ||
| 254 | mini_type( typeid(*obj).name() ), obj ); | ||
| 255 | } | ||
| 256 | |||
| 257 | // remove it from map | ||
| 258 | |||
| 259 | // delete it | ||
| 260 | delete obj; | ||
| 261 | } | ||
| 262 | |||
| 263 | |||
| 264 | |||
| 265 | |||
| 266 | //----------------------------------------------------------------------------- | ||
| 267 | // name: Chuck_VM_Alloc() | ||
| 268 | // desc: constructor | ||
| 269 | //----------------------------------------------------------------------------- | ||
| 270 | Chuck_VM_Alloc::Chuck_VM_Alloc() | ||
| 271 | { } | ||
| 272 | |||
| 273 | |||
| 274 | |||
| 275 | |||
| 276 | //----------------------------------------------------------------------------- | ||
| 277 | // name: ~Chuck_VM_Alloc() | ||
| 278 | // desc: destructor | ||
| 279 | //----------------------------------------------------------------------------- | ||
| 280 | Chuck_VM_Alloc::~Chuck_VM_Alloc() | ||
| 281 | { } | ||
| 282 | |||
| 283 | |||
| 284 | |||
| 285 | |||
| 286 | //----------------------------------------------------------------------------- | ||
| 287 | // name: Chuck_Object() | ||
| 288 | // desc: constructor | ||
| 289 | //----------------------------------------------------------------------------- | ||
| 290 | Chuck_Object::Chuck_Object() | ||
| 291 | { | ||
| 292 | // zero virtual table | ||
| 293 | vtable = NULL; | ||
| 294 | // zero type | ||
| 295 | type_ref = NULL; | ||
| 296 | // zero size | ||
| 297 | size = 0; | ||
| 298 | // zero data | ||
| 299 | data = NULL; | ||
| 300 | |||
| 301 | // add to vm allocator | ||
| 302 | Chuck_VM_Alloc::instance()->add_object( this ); | ||
| 303 | } | ||
| 304 | |||
| 305 | |||
| 306 | |||
| 307 | |||
| 308 | //----------------------------------------------------------------------------- | ||
| 309 | // name: Chuck_Object() | ||
| 310 | // desc: ... | ||
| 311 | //----------------------------------------------------------------------------- | ||
| 312 | Chuck_Object::~Chuck_Object() | ||
| 313 | { | ||
| 314 | // added 1.3.0.0: | ||
| 315 | // call destructors, from latest descended child to oldest parent | ||
| 316 | Chuck_Type * type = this->type_ref; | ||
| 317 | while( type != NULL ) | ||
| 318 | { | ||
| 319 | // SPENCERTODO: HACK! is there a better way to call the dtor? | ||
| 320 | if( type->has_destructor ) | ||
| 321 | { | ||
| 322 | // sanity check | ||
| 323 | assert( type->info->dtor && type->info->dtor->native_func ); | ||
| 324 | ((f_dtor)(type->info->dtor->native_func))( this, NULL, Chuck_DL_Api::Api::instance() ); | ||
| 325 | } | ||
| 326 | |||
| 327 | // go up the inheritance | ||
| 328 | type = type->parent; | ||
| 329 | } | ||
| 330 | |||
| 331 | // free | ||
| 332 | if( vtable ) { delete vtable; vtable = NULL; } | ||
| 333 | if( type_ref ) { type_ref->release(); type_ref = NULL; } | ||
| 334 | if( data ) { delete [] data; size = 0; data = NULL; } | ||
| 335 | } | ||
| 336 | |||
| 337 | |||
| 338 | |||
| 339 | |||
| 340 | //----------------------------------------------------------------------------- | ||
| 341 | // name: Chuck_Array4() | ||
| 342 | // desc: constructor | ||
| 343 | //----------------------------------------------------------------------------- | ||
| 344 | Chuck_Array4::Chuck_Array4( t_CKBOOL is_obj, t_CKINT capacity ) | ||
| 345 | { | ||
| 346 | // sanity check | ||
| 347 | assert( capacity >= 0 ); | ||
| 348 | // set size | ||
| 349 | m_vector.resize( capacity ); | ||
| 350 | // clear (as non-object, so no releases) | ||
| 351 | m_is_obj = FALSE; | ||
| 352 | this->zero( 0, m_vector.capacity() ); | ||
| 353 | // is object (set after clear) | ||
| 354 | m_is_obj = is_obj; | ||
| 355 | } | ||
| 356 | |||
| 357 | |||
| 358 | |||
| 359 | |||
| 360 | //----------------------------------------------------------------------------- | ||
| 361 | // name: ~Chuck_Array4() | ||
| 362 | // desc: destructor | ||
| 363 | //----------------------------------------------------------------------------- | ||
| 364 | Chuck_Array4::~Chuck_Array4() | ||
| 365 | { | ||
| 366 | // do nothing | ||
| 367 | } | ||
| 368 | |||
| 369 | |||
| 370 | |||
| 371 | |||
| 372 | //----------------------------------------------------------------------------- | ||
| 373 | // name: addr() | ||
| 374 | // desc: ... | ||
| 375 | //----------------------------------------------------------------------------- | ||
| 376 | t_CKUINT Chuck_Array4::addr( t_CKINT i ) | ||
| 377 | { | ||
| 378 | // bound check | ||
| 379 | if( i < 0 || i >= m_vector.capacity() ) | ||
| 380 | return 0; | ||
| 381 | |||
| 382 | // get the addr | ||
| 383 | return (t_CKUINT)(&m_vector[i]); | ||
| 384 | } | ||
| 385 | |||
| 386 | |||
| 387 | |||
| 388 | |||
| 389 | //----------------------------------------------------------------------------- | ||
| 390 | // name: addr() | ||
| 391 | // desc: ... | ||
| 392 | //----------------------------------------------------------------------------- | ||
| 393 | t_CKUINT Chuck_Array4::addr( const string & key ) | ||
| 394 | { | ||
| 395 | // get the addr | ||
| 396 | return (t_CKUINT)(&m_map[key]); | ||
| 397 | } | ||
| 398 | |||
| 399 | |||
| 400 | |||
| 401 | |||
| 402 | //----------------------------------------------------------------------------- | ||
| 403 | // name: get() | ||
| 404 | // desc: ... | ||
| 405 | //----------------------------------------------------------------------------- | ||
| 406 | t_CKINT Chuck_Array4::get( t_CKINT i, t_CKUINT * val ) | ||
| 407 | { | ||
| 408 | // bound check | ||
| 409 | if( i < 0 || i >= m_vector.capacity() ) | ||
| 410 | return 0; | ||
| 411 | |||
| 412 | // get the value | ||
| 413 | *val = m_vector[i]; | ||
| 414 | |||
| 415 | // return good | ||
| 416 | return 1; | ||
| 417 | } | ||
| 418 | |||
| 419 | |||
| 420 | |||
| 421 | |||
| 422 | //----------------------------------------------------------------------------- | ||
| 423 | // name: get() | ||
| 424 | // desc: ... | ||
| 425 | //----------------------------------------------------------------------------- | ||
| 426 | t_CKINT Chuck_Array4::get( const string & key, t_CKUINT * val ) | ||
| 427 | { | ||
| 428 | // set to zero | ||
| 429 | *val = 0; | ||
| 430 | // find | ||
| 431 | map<string, t_CKUINT>::iterator iter = m_map.find( key ); | ||
| 432 | // check | ||
| 433 | if( iter != m_map.end() ) *val = (*iter).second; | ||
| 434 | |||
| 435 | // return good | ||
| 436 | return 1; | ||
| 437 | } | ||
| 438 | |||
| 439 | |||
| 440 | |||
| 441 | |||
| 442 | //----------------------------------------------------------------------------- | ||
| 443 | // name: set() | ||
| 444 | // desc: include ref counting | ||
| 445 | //----------------------------------------------------------------------------- | ||
| 446 | t_CKINT Chuck_Array4::set( t_CKINT i, t_CKUINT val ) | ||
| 447 | { | ||
| 448 | // bound check | ||
| 449 | if( i < 0 || i >= m_vector.capacity() ) | ||
| 450 | return 0; | ||
| 451 | |||
| 452 | t_CKUINT v = m_vector[i]; | ||
| 453 | |||
| 454 | // if obj | ||
| 455 | if( m_is_obj && v ) ((Chuck_Object *)v)->release(); | ||
| 456 | |||
| 457 | // set the value | ||
| 458 | m_vector[i] = val; | ||
| 459 | |||
| 460 | // if obj | ||
| 461 | if( m_is_obj && val ) ((Chuck_Object *)val)->add_ref(); | ||
| 462 | |||
| 463 | // return good | ||
| 464 | return 1; | ||
| 465 | } | ||
| 466 | |||
| 467 | |||
| 468 | |||
| 469 | |||
| 470 | |||
| 471 | //----------------------------------------------------------------------------- | ||
| 472 | // name: set() | ||
| 473 | // desc: include ref counting | ||
| 474 | //----------------------------------------------------------------------------- | ||
| 475 | t_CKINT Chuck_Array4::set( const string & key, t_CKUINT val ) | ||
| 476 | { | ||
| 477 | map<string, t_CKUINT>::iterator iter = m_map.find( key ); | ||
| 478 | |||
| 479 | // if obj | ||
| 480 | if( m_is_obj && iter != m_map.end() ) | ||
| 481 | ((Chuck_Object *)(*iter).second)->release(); | ||
| 482 | |||
| 483 | if( !val ) m_map.erase( key ); | ||
| 484 | else m_map[key] = val; | ||
| 485 | |||
| 486 | // if obj | ||
| 487 | if( m_is_obj && val ) ((Chuck_Object *)val)->add_ref(); | ||
| 488 | |||
| 489 | // return good | ||
| 490 | return 1; | ||
| 491 | } | ||
| 492 | |||
| 493 | |||
| 494 | |||
| 495 | |||
| 496 | //----------------------------------------------------------------------------- | ||
| 497 | // name: find() | ||
| 498 | // desc: ... | ||
| 499 | //----------------------------------------------------------------------------- | ||
| 500 | t_CKINT Chuck_Array4::find( const string & key ) | ||
| 501 | { | ||
| 502 | return m_map.find( key ) != m_map.end(); | ||
| 503 | } | ||
| 504 | |||
| 505 | |||
| 506 | |||
| 507 | |||
| 508 | //----------------------------------------------------------------------------- | ||
| 509 | // name: erase() | ||
| 510 | // desc: ... | ||
| 511 | //----------------------------------------------------------------------------- | ||
| 512 | t_CKINT Chuck_Array4::erase( const string & key ) | ||
| 513 | { | ||
| 514 | map<string, t_CKUINT>::iterator iter = m_map.find( key ); | ||
| 515 | t_CKINT v = iter != m_map.end(); | ||
| 516 | |||
| 517 | // if obj | ||
| 518 | if( m_is_obj && iter != m_map.end() ) | ||
| 519 | ((Chuck_Object *)(*iter).second)->release(); | ||
| 520 | |||
| 521 | // erase | ||
| 522 | if( v ) m_map.erase( key ); | ||
| 523 | |||
| 524 | return v; | ||
| 525 | } | ||
| 526 | |||
| 527 | |||
| 528 | |||
| 529 | |||
| 530 | //----------------------------------------------------------------------------- | ||
| 531 | // name: push_back() | ||
| 532 | // desc: ... | ||
| 533 | //----------------------------------------------------------------------------- | ||
| 534 | t_CKINT Chuck_Array4::push_back( t_CKUINT val ) | ||
| 535 | { | ||
| 536 | // TODO: is this right? | ||
| 537 | |||
| 538 | // if obj, reference count it (added 1.3.0.0) | ||
| 539 | if( m_is_obj && val ) ((Chuck_Object *)val)->add_ref(); | ||
| 540 | |||
| 541 | // add to vector | ||
| 542 | m_vector.push_back( val ); | ||
| 543 | |||
| 544 | return 1; | ||
| 545 | } | ||
| 546 | |||
| 547 | |||
| 548 | |||
| 549 | |||
| 550 | //----------------------------------------------------------------------------- | ||
| 551 | // name: pop_back() | ||
| 552 | // desc: ... | ||
| 553 | //----------------------------------------------------------------------------- | ||
| 554 | t_CKINT Chuck_Array4::pop_back( ) | ||
| 555 | { | ||
| 556 | // check | ||
| 557 | if( m_vector.size() == 0 ) | ||
| 558 | return 0; | ||
| 559 | |||
| 560 | // if obj | ||
| 561 | if( m_is_obj ) | ||
| 562 | { | ||
| 563 | // get pointer | ||
| 564 | Chuck_Object * v = (Chuck_Object *)m_vector[m_vector.size()-1]; | ||
| 565 | // if not null, release | ||
| 566 | if( v ) v->release(); | ||
| 567 | } | ||
| 568 | |||
| 569 | // zero | ||
| 570 | m_vector[m_vector.size()-1] = 0; | ||
| 571 | // add to vector | ||
| 572 | m_vector.pop_back(); | ||
| 573 | |||
| 574 | return 1; | ||
| 575 | } | ||
| 576 | |||
| 577 | |||
| 578 | |||
| 579 | |||
| 580 | //----------------------------------------------------------------------------- | ||
| 581 | // name: back() | ||
| 582 | // desc: ... | ||
| 583 | //----------------------------------------------------------------------------- | ||
| 584 | t_CKINT Chuck_Array4::back( t_CKUINT * val ) const | ||
| 585 | { | ||
| 586 | // check | ||
| 587 | if( m_vector.size() == 0 ) | ||
| 588 | return 0; | ||
| 589 | |||
| 590 | // get | ||
| 591 | *val = m_vector.back(); | ||
| 592 | |||
| 593 | return 1; | ||
| 594 | } | ||
| 595 | |||
| 596 | |||
| 597 | |||
| 598 | |||
| 599 | //----------------------------------------------------------------------------- | ||
| 600 | // name: clear() | ||
| 601 | // desc: ... | ||
| 602 | //----------------------------------------------------------------------------- | ||
| 603 | void Chuck_Array4::clear( ) | ||
| 604 | { | ||
| 605 | // zero | ||
| 606 | zero( 0, m_vector.size() ); | ||
| 607 | |||
| 608 | // clear vector | ||
| 609 | m_vector.clear(); | ||
| 610 | } | ||
| 611 | |||
| 612 | |||
| 613 | |||
| 614 | |||
| 615 | //----------------------------------------------------------------------------- | ||
| 616 | // name: set_capacity() | ||
| 617 | // desc: ... | ||
| 618 | //----------------------------------------------------------------------------- | ||
| 619 | t_CKINT Chuck_Array4::set_capacity( t_CKINT capacity ) | ||
| 620 | { | ||
| 621 | // sanity check | ||
| 622 | assert( capacity >= 0 ); | ||
| 623 | |||
| 624 | // ensure size | ||
| 625 | set_size( capacity ); | ||
| 626 | |||
| 627 | return m_vector.capacity(); | ||
| 628 | } | ||
| 629 | |||
| 630 | |||
| 631 | |||
| 632 | |||
| 633 | //----------------------------------------------------------------------------- | ||
| 634 | // name: set_size() | ||
| 635 | // desc: ... | ||
| 636 | //----------------------------------------------------------------------------- | ||
| 637 | t_CKINT Chuck_Array4::set_size( t_CKINT size ) | ||
| 638 | { | ||
| 639 | // sanity check | ||
| 640 | assert( size >= 0 ); | ||
| 641 | |||
| 642 | // if clearing size | ||
| 643 | if( size < m_vector.size() ) | ||
| 644 | { | ||
| 645 | // zero out section | ||
| 646 | zero( size, m_vector.size() ); | ||
| 647 | } | ||
| 648 | |||
| 649 | // what the size was | ||
| 650 | t_CKINT size2 = m_vector.size(); | ||
| 651 | // resize vector | ||
| 652 | m_vector.resize( size ); | ||
| 653 | |||
| 654 | // if clearing size | ||
| 655 | if( m_vector.size() > size2 ) | ||
| 656 | { | ||
| 657 | // zero out section | ||
| 658 | zero( size2, m_vector.size() ); | ||
| 659 | } | ||
| 660 | |||
| 661 | return m_vector.size(); | ||
| 662 | } | ||
| 663 | |||
| 664 | |||
| 665 | |||
| 666 | |||
| 667 | //----------------------------------------------------------------------------- | ||
| 668 | // name: zero() | ||
| 669 | // desc: ... | ||
| 670 | //----------------------------------------------------------------------------- | ||
| 671 | void Chuck_Array4::zero( t_CKUINT start, t_CKUINT end ) | ||
| 672 | { | ||
| 673 | // sanity check | ||
| 674 | assert( start <= m_vector.capacity() && end <= m_vector.capacity() ); | ||
| 675 | |||
| 676 | // if contains objects | ||
| 677 | if( m_is_obj ) | ||
| 678 | { | ||
| 679 | Chuck_Object * v = NULL; | ||
| 680 | for( t_CKUINT i = start; i < end; i++ ) | ||
| 681 | { | ||
| 682 | // get it | ||
| 683 | v = (Chuck_Object *)m_vector[i]; | ||
| 684 | // release | ||
| 685 | if( v ) | ||
| 686 | { | ||
| 687 | v->release(); | ||
2598 more lines aren’t shown here.
This diff is large: its 729 lines aren’t shown here.
This diff is large: its 99 lines aren’t shown here.
This diff is large: its 231 lines aren’t shown here.
This diff is large: its 154 lines aren’t shown here.
This diff is large: its 2751 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 144 lines aren’t shown here.
This diff is large: its 89 lines aren’t shown here.
This diff is large: its 222 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 6484 lines aren’t shown here.
This diff is large: its 948 lines aren’t shown here.
This diff is large: its 78 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 235 lines aren’t shown here.
This diff is large: its 347 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 182 lines aren’t shown here.
This diff is large: its 201 lines aren’t shown here.
This diff is large: its 354 lines aren’t shown here.
This diff is large: its 257 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
This diff is large: its 861 lines aren’t shown here.
This diff is large: its 81 lines aren’t shown here.
This diff is large: its 146 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 144 lines aren’t shown here.
This diff is large: its 146 lines aren’t shown here.
This diff is large: its 1082 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 249 lines aren’t shown here.
This diff is large: its 492 lines aren’t shown here.
This diff is large: its 1401 lines aren’t shown here.
This diff is large: its 189 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 236 lines aren’t shown here.
This diff is large: its 185 lines aren’t shown here.
This diff is large: its 130 lines aren’t shown here.
This diff is large: its 84 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 349 lines aren’t shown here.
This diff is large: its 227 lines aren’t shown here.
This diff is large: its 129 lines aren’t shown here.
This diff is large: its 2297 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 288 lines aren’t shown here.
This diff is large: its 813 lines aren’t shown here.
This diff is large: its 667 lines aren’t shown here.
This diff is large: its 502 lines aren’t shown here.
This diff is large: its 216 lines aren’t shown here.
This diff is large: its 156 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 1740 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 126 lines aren’t shown here.
This diff is large: its 77 lines aren’t shown here.
This diff is large: its 277 lines aren’t shown here.
This diff is large: its 352 lines aren’t shown here.
This diff is large: its 78 lines aren’t shown here.
This diff is large: its 1527 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 3763 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 2695 lines aren’t shown here.
This diff is large: its 239 lines aren’t shown here.
This diff is large: its 1760 lines aren’t shown here.
This diff is large: its 113 lines aren’t shown here.
This diff is large: its 27017 lines aren’t shown here.
This diff is large: its 6623 lines aren’t shown here.
This diff is large: its 4966 lines aren’t shown here.
This diff is large: its 257 lines aren’t shown here.
This diff is large: its 222 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 778 lines aren’t shown here.
This diff is large: its 101 lines aren’t shown here.
This diff is large: its 1663 lines aren’t shown here.
This diff is large: its 80 lines aren’t shown here.
This diff is large: its 405 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 1972 lines aren’t shown here.
This diff is large: its 144 lines aren’t shown here.
This diff is large: its 211 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 8069 lines aren’t shown here.
This diff is large: its 222 lines aren’t shown here.
This diff is large: its 201 lines aren’t shown here.
This diff is large: its 76 lines aren’t shown here.
This diff is large: its 443 lines aren’t shown here.
This diff is large: its 106 lines aren’t shown here.
This diff is large: its 2542 lines aren’t shown here.
This diff is large: its 631 lines aren’t shown here.
This diff is large: its 4785 lines aren’t shown here.
This diff is large: its 101 lines aren’t shown here.
This diff is large: its 249 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 34324 lines aren’t shown here.
This diff is large: its 2707 lines aren’t shown here.
This diff is large: its 570 lines aren’t shown here.
This diff is large: its 88 lines aren’t shown here.
This diff is large: its 444 lines aren’t shown here.
This diff is large: its 214 lines aren’t shown here.
This diff is large: its 455 lines aren’t shown here.
This diff is large: its 90 lines aren’t shown here.