This is a test program for mruby mirb. Currently, I'm sure the only work in "Renesas GR-PEACH".

Dependencies:   mbed-src mruby-mbed

Committer:
mzta
Date:
Mon Apr 13 05:24:00 2015 +0000
Revision:
1:340b448861c1
Parent:
0:e7eb8eab3aa9
- update mbed-src.; - code refactoring.; - add SPI, SPISlave, I2C class to mruby-mbed (Incomplete).

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mzta 0:e7eb8eab3aa9 1 /*
mzta 0:e7eb8eab3aa9 2 ** mirb - Embeddable Interactive Ruby Shell
mzta 0:e7eb8eab3aa9 3 **
mzta 0:e7eb8eab3aa9 4 ** This program takes code from the user in
mzta 0:e7eb8eab3aa9 5 ** an interactive way and executes it
mzta 0:e7eb8eab3aa9 6 ** immediately. It's a REPL...
mzta 0:e7eb8eab3aa9 7 */
mzta 0:e7eb8eab3aa9 8
mzta 0:e7eb8eab3aa9 9 #include "mbed.h"
mzta 0:e7eb8eab3aa9 10
mzta 0:e7eb8eab3aa9 11 Serial pc(USBTX, USBRX);
mzta 0:e7eb8eab3aa9 12
mzta 0:e7eb8eab3aa9 13 #include <stdlib.h>
mzta 0:e7eb8eab3aa9 14 #include <string.h>
mzta 0:e7eb8eab3aa9 15 #include <stdio.h>
mzta 0:e7eb8eab3aa9 16 #include <ctype.h>
mzta 0:e7eb8eab3aa9 17
mzta 0:e7eb8eab3aa9 18 #ifdef ENABLE_READLINE
mzta 0:e7eb8eab3aa9 19 #include <readline/readline.h>
mzta 0:e7eb8eab3aa9 20 #include <readline/history.h>
mzta 0:e7eb8eab3aa9 21 #define MIRB_ADD_HISTORY(line) add_history(line)
mzta 0:e7eb8eab3aa9 22 #define MIRB_READLINE(ch) readline(ch)
mzta 0:e7eb8eab3aa9 23 #define MIRB_WRITE_HISTORY(path) write_history(path)
mzta 0:e7eb8eab3aa9 24 #define MIRB_READ_HISTORY(path) read_history(path)
mzta 0:e7eb8eab3aa9 25 #define MIRB_USING_HISTORY() using_history()
mzta 0:e7eb8eab3aa9 26 #elif defined(ENABLE_LINENOISE)
mzta 0:e7eb8eab3aa9 27 #define ENABLE_READLINE
mzta 0:e7eb8eab3aa9 28 #include <linenoise.h>
mzta 0:e7eb8eab3aa9 29 #define MIRB_ADD_HISTORY(line) linenoiseHistoryAdd(line)
mzta 0:e7eb8eab3aa9 30 #define MIRB_READLINE(ch) linenoise(ch)
mzta 0:e7eb8eab3aa9 31 #define MIRB_WRITE_HISTORY(path) linenoiseHistorySave(path)
mzta 0:e7eb8eab3aa9 32 #define MIRB_READ_HISTORY(path) linenoiseHistoryLoad(history_path)
mzta 0:e7eb8eab3aa9 33 #define MIRB_USING_HISTORY()
mzta 0:e7eb8eab3aa9 34 #endif
mzta 0:e7eb8eab3aa9 35
mzta 0:e7eb8eab3aa9 36 #include "mruby.h"
mzta 0:e7eb8eab3aa9 37 #include "mruby/array.h"
mzta 0:e7eb8eab3aa9 38 #include "mruby/proc.h"
mzta 0:e7eb8eab3aa9 39 #include "mruby/compile.h"
mzta 0:e7eb8eab3aa9 40 #include "mruby/string.h"
mzta 0:e7eb8eab3aa9 41
mzta 0:e7eb8eab3aa9 42 #ifdef ENABLE_READLINE
mzta 0:e7eb8eab3aa9 43
mzta 0:e7eb8eab3aa9 44 static const char history_file_name[] = ".mirb_history";
mzta 0:e7eb8eab3aa9 45
mzta 0:e7eb8eab3aa9 46 static char *
mzta 0:e7eb8eab3aa9 47 get_history_path(mrb_state *mrb)
mzta 0:e7eb8eab3aa9 48 {
mzta 0:e7eb8eab3aa9 49 char *path = NULL;
mzta 0:e7eb8eab3aa9 50 const char *home = getenv("HOME");
mzta 0:e7eb8eab3aa9 51
mzta 0:e7eb8eab3aa9 52 #ifdef _WIN32
mzta 0:e7eb8eab3aa9 53 if (home != NULL) {
mzta 0:e7eb8eab3aa9 54 home = getenv("USERPROFILE");
mzta 0:e7eb8eab3aa9 55 }
mzta 0:e7eb8eab3aa9 56 #endif
mzta 0:e7eb8eab3aa9 57
mzta 0:e7eb8eab3aa9 58 if (home != NULL) {
mzta 0:e7eb8eab3aa9 59 int len = snprintf(NULL, 0, "%s/%s", home, history_file_name);
mzta 0:e7eb8eab3aa9 60 if (len >= 0) {
mzta 0:e7eb8eab3aa9 61 size_t size = len + 1;
mzta 0:e7eb8eab3aa9 62 path = (char *)mrb_malloc_simple(mrb, size);
mzta 0:e7eb8eab3aa9 63 if (path != NULL) {
mzta 0:e7eb8eab3aa9 64 int n = snprintf(path, size, "%s/%s", home, history_file_name);
mzta 0:e7eb8eab3aa9 65 if (n != len) {
mzta 0:e7eb8eab3aa9 66 mrb_free(mrb, path);
mzta 0:e7eb8eab3aa9 67 path = NULL;
mzta 0:e7eb8eab3aa9 68 }
mzta 0:e7eb8eab3aa9 69 }
mzta 0:e7eb8eab3aa9 70 }
mzta 0:e7eb8eab3aa9 71 }
mzta 0:e7eb8eab3aa9 72
mzta 0:e7eb8eab3aa9 73 return path;
mzta 0:e7eb8eab3aa9 74 }
mzta 0:e7eb8eab3aa9 75
mzta 0:e7eb8eab3aa9 76 #endif
mzta 0:e7eb8eab3aa9 77
mzta 0:e7eb8eab3aa9 78 static void
mzta 0:e7eb8eab3aa9 79 p(mrb_state *mrb, mrb_value obj, int prompt)
mzta 0:e7eb8eab3aa9 80 {
mzta 0:e7eb8eab3aa9 81 obj = mrb_funcall(mrb, obj, "inspect", 0);
mzta 0:e7eb8eab3aa9 82 if (prompt) {
mzta 0:e7eb8eab3aa9 83 if (!mrb->exc) {
mzta 0:e7eb8eab3aa9 84 pc.printf(" => ");
mzta 0:e7eb8eab3aa9 85 }
mzta 0:e7eb8eab3aa9 86 else {
mzta 0:e7eb8eab3aa9 87 obj = mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0);
mzta 0:e7eb8eab3aa9 88 }
mzta 0:e7eb8eab3aa9 89 }
mzta 0:e7eb8eab3aa9 90 fwrite(RSTRING_PTR(obj), RSTRING_LEN(obj), 1, stdout);
mzta 0:e7eb8eab3aa9 91 putc('\n', stdout);
mzta 0:e7eb8eab3aa9 92 }
mzta 0:e7eb8eab3aa9 93
mzta 0:e7eb8eab3aa9 94 /* Guess if the user might want to enter more
mzta 0:e7eb8eab3aa9 95 * or if he wants an evaluation of his code now */
mzta 0:e7eb8eab3aa9 96 static mrb_bool
mzta 0:e7eb8eab3aa9 97 is_code_block_open(struct mrb_parser_state *parser)
mzta 0:e7eb8eab3aa9 98 {
mzta 0:e7eb8eab3aa9 99 mrb_bool code_block_open = FALSE;
mzta 0:e7eb8eab3aa9 100
mzta 0:e7eb8eab3aa9 101 /* check for heredoc */
mzta 0:e7eb8eab3aa9 102 if (parser->parsing_heredoc != NULL) return TRUE;
mzta 0:e7eb8eab3aa9 103 if (parser->heredoc_end_now) {
mzta 0:e7eb8eab3aa9 104 parser->heredoc_end_now = FALSE;
mzta 0:e7eb8eab3aa9 105 return FALSE;
mzta 0:e7eb8eab3aa9 106 }
mzta 0:e7eb8eab3aa9 107
mzta 0:e7eb8eab3aa9 108 /* check for unterminated string */
mzta 0:e7eb8eab3aa9 109 if (parser->lex_strterm) return TRUE;
mzta 0:e7eb8eab3aa9 110
mzta 0:e7eb8eab3aa9 111 /* check if parser error are available */
mzta 0:e7eb8eab3aa9 112 if (0 < parser->nerr) {
mzta 0:e7eb8eab3aa9 113 const char unexpected_end[] = "syntax error, unexpected $end";
mzta 0:e7eb8eab3aa9 114 const char *message = parser->error_buffer[0].message;
mzta 0:e7eb8eab3aa9 115
mzta 0:e7eb8eab3aa9 116 /* a parser error occur, we have to check if */
mzta 0:e7eb8eab3aa9 117 /* we need to read one more line or if there is */
mzta 0:e7eb8eab3aa9 118 /* a different issue which we have to show to */
mzta 0:e7eb8eab3aa9 119 /* the user */
mzta 0:e7eb8eab3aa9 120
mzta 0:e7eb8eab3aa9 121 if (strncmp(message, unexpected_end, sizeof(unexpected_end) - 1) == 0) {
mzta 0:e7eb8eab3aa9 122 code_block_open = TRUE;
mzta 0:e7eb8eab3aa9 123 }
mzta 0:e7eb8eab3aa9 124 else if (strcmp(message, "syntax error, unexpected keyword_end") == 0) {
mzta 0:e7eb8eab3aa9 125 code_block_open = FALSE;
mzta 0:e7eb8eab3aa9 126 }
mzta 0:e7eb8eab3aa9 127 else if (strcmp(message, "syntax error, unexpected tREGEXP_BEG") == 0) {
mzta 0:e7eb8eab3aa9 128 code_block_open = FALSE;
mzta 0:e7eb8eab3aa9 129 }
mzta 0:e7eb8eab3aa9 130 return code_block_open;
mzta 0:e7eb8eab3aa9 131 }
mzta 0:e7eb8eab3aa9 132
mzta 0:e7eb8eab3aa9 133 switch (parser->lstate) {
mzta 0:e7eb8eab3aa9 134
mzta 0:e7eb8eab3aa9 135 /* all states which need more code */
mzta 0:e7eb8eab3aa9 136
mzta 0:e7eb8eab3aa9 137 case EXPR_BEG:
mzta 0:e7eb8eab3aa9 138 /* beginning of a statement, */
mzta 0:e7eb8eab3aa9 139 /* that means previous line ended */
mzta 0:e7eb8eab3aa9 140 code_block_open = FALSE;
mzta 0:e7eb8eab3aa9 141 break;
mzta 0:e7eb8eab3aa9 142 case EXPR_DOT:
mzta 0:e7eb8eab3aa9 143 /* a message dot was the last token, */
mzta 0:e7eb8eab3aa9 144 /* there has to come more */
mzta 0:e7eb8eab3aa9 145 code_block_open = TRUE;
mzta 0:e7eb8eab3aa9 146 break;
mzta 0:e7eb8eab3aa9 147 case EXPR_CLASS:
mzta 0:e7eb8eab3aa9 148 /* a class keyword is not enough! */
mzta 0:e7eb8eab3aa9 149 /* we need also a name of the class */
mzta 0:e7eb8eab3aa9 150 code_block_open = TRUE;
mzta 0:e7eb8eab3aa9 151 break;
mzta 0:e7eb8eab3aa9 152 case EXPR_FNAME:
mzta 0:e7eb8eab3aa9 153 /* a method name is necessary */
mzta 0:e7eb8eab3aa9 154 code_block_open = TRUE;
mzta 0:e7eb8eab3aa9 155 break;
mzta 0:e7eb8eab3aa9 156 case EXPR_VALUE:
mzta 0:e7eb8eab3aa9 157 /* if, elsif, etc. without condition */
mzta 0:e7eb8eab3aa9 158 code_block_open = TRUE;
mzta 0:e7eb8eab3aa9 159 break;
mzta 0:e7eb8eab3aa9 160
mzta 0:e7eb8eab3aa9 161 /* now all the states which are closed */
mzta 0:e7eb8eab3aa9 162
mzta 0:e7eb8eab3aa9 163 case EXPR_ARG:
mzta 0:e7eb8eab3aa9 164 /* an argument is the last token */
mzta 0:e7eb8eab3aa9 165 code_block_open = FALSE;
mzta 0:e7eb8eab3aa9 166 break;
mzta 0:e7eb8eab3aa9 167
mzta 0:e7eb8eab3aa9 168 /* all states which are unsure */
mzta 0:e7eb8eab3aa9 169
mzta 0:e7eb8eab3aa9 170 case EXPR_CMDARG:
mzta 0:e7eb8eab3aa9 171 break;
mzta 0:e7eb8eab3aa9 172 case EXPR_END:
mzta 0:e7eb8eab3aa9 173 /* an expression was ended */
mzta 0:e7eb8eab3aa9 174 break;
mzta 0:e7eb8eab3aa9 175 case EXPR_ENDARG:
mzta 0:e7eb8eab3aa9 176 /* closing parenthese */
mzta 0:e7eb8eab3aa9 177 break;
mzta 0:e7eb8eab3aa9 178 case EXPR_ENDFN:
mzta 0:e7eb8eab3aa9 179 /* definition end */
mzta 0:e7eb8eab3aa9 180 break;
mzta 0:e7eb8eab3aa9 181 case EXPR_MID:
mzta 0:e7eb8eab3aa9 182 /* jump keyword like break, return, ... */
mzta 0:e7eb8eab3aa9 183 break;
mzta 0:e7eb8eab3aa9 184 case EXPR_MAX_STATE:
mzta 0:e7eb8eab3aa9 185 /* don't know what to do with this token */
mzta 0:e7eb8eab3aa9 186 break;
mzta 0:e7eb8eab3aa9 187 default:
mzta 0:e7eb8eab3aa9 188 /* this state is unexpected! */
mzta 0:e7eb8eab3aa9 189 break;
mzta 0:e7eb8eab3aa9 190 }
mzta 0:e7eb8eab3aa9 191
mzta 0:e7eb8eab3aa9 192 return code_block_open;
mzta 0:e7eb8eab3aa9 193 }
mzta 0:e7eb8eab3aa9 194
mzta 0:e7eb8eab3aa9 195
mzta 0:e7eb8eab3aa9 196 #if defined(__cplusplus)
mzta 0:e7eb8eab3aa9 197 extern "C" {
mzta 0:e7eb8eab3aa9 198 #endif
mzta 0:e7eb8eab3aa9 199 void mrb_show_version(mrb_state *);
mzta 0:e7eb8eab3aa9 200 void mrb_show_copyright(mrb_state *);
mzta 0:e7eb8eab3aa9 201 #if defined(__cplusplus)
mzta 0:e7eb8eab3aa9 202 }
mzta 0:e7eb8eab3aa9 203 #endif
mzta 0:e7eb8eab3aa9 204
mzta 0:e7eb8eab3aa9 205 struct _args {
mzta 0:e7eb8eab3aa9 206 mrb_bool verbose : 1;
mzta 0:e7eb8eab3aa9 207 int argc;
mzta 0:e7eb8eab3aa9 208 char** argv;
mzta 0:e7eb8eab3aa9 209 };
mzta 0:e7eb8eab3aa9 210
mzta 0:e7eb8eab3aa9 211 static void
mzta 0:e7eb8eab3aa9 212 usage(const char *name)
mzta 0:e7eb8eab3aa9 213 {
mzta 0:e7eb8eab3aa9 214 static const char *const usage_msg[] = {
mzta 0:e7eb8eab3aa9 215 "switches:",
mzta 0:e7eb8eab3aa9 216 "-v print version number, then run in verbose mode",
mzta 0:e7eb8eab3aa9 217 "--verbose run in verbose mode",
mzta 0:e7eb8eab3aa9 218 "--version print the version",
mzta 0:e7eb8eab3aa9 219 "--copyright print the copyright",
mzta 0:e7eb8eab3aa9 220 NULL
mzta 0:e7eb8eab3aa9 221 };
mzta 0:e7eb8eab3aa9 222 const char *const *p = usage_msg;
mzta 0:e7eb8eab3aa9 223
mzta 0:e7eb8eab3aa9 224 pc.printf("Usage: %s [switches]\n", name);
mzta 0:e7eb8eab3aa9 225 while (*p)
mzta 0:e7eb8eab3aa9 226 pc.printf(" %s\n", *p++);
mzta 0:e7eb8eab3aa9 227 }
mzta 0:e7eb8eab3aa9 228
mzta 0:e7eb8eab3aa9 229 static int
mzta 0:e7eb8eab3aa9 230 parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
mzta 0:e7eb8eab3aa9 231 {
mzta 0:e7eb8eab3aa9 232 static const struct _args args_zero = { 0 };
mzta 0:e7eb8eab3aa9 233
mzta 0:e7eb8eab3aa9 234 *args = args_zero;
mzta 0:e7eb8eab3aa9 235
mzta 0:e7eb8eab3aa9 236 for (argc--,argv++; argc > 0; argc--,argv++) {
mzta 0:e7eb8eab3aa9 237 char *item;
mzta 0:e7eb8eab3aa9 238 if (argv[0][0] != '-') break;
mzta 0:e7eb8eab3aa9 239
mzta 0:e7eb8eab3aa9 240 item = argv[0] + 1;
mzta 0:e7eb8eab3aa9 241 switch (*item++) {
mzta 0:e7eb8eab3aa9 242 case 'v':
mzta 0:e7eb8eab3aa9 243 if (!args->verbose) mrb_show_version(mrb);
mzta 0:e7eb8eab3aa9 244 args->verbose = TRUE;
mzta 0:e7eb8eab3aa9 245 break;
mzta 0:e7eb8eab3aa9 246 case '-':
mzta 0:e7eb8eab3aa9 247 if (strcmp((*argv) + 2, "version") == 0) {
mzta 0:e7eb8eab3aa9 248 mrb_show_version(mrb);
mzta 0:e7eb8eab3aa9 249 exit(EXIT_SUCCESS);
mzta 0:e7eb8eab3aa9 250 }
mzta 0:e7eb8eab3aa9 251 else if (strcmp((*argv) + 2, "verbose") == 0) {
mzta 0:e7eb8eab3aa9 252 args->verbose = TRUE;
mzta 0:e7eb8eab3aa9 253 break;
mzta 0:e7eb8eab3aa9 254 }
mzta 0:e7eb8eab3aa9 255 else if (strcmp((*argv) + 2, "copyright") == 0) {
mzta 0:e7eb8eab3aa9 256 mrb_show_copyright(mrb);
mzta 0:e7eb8eab3aa9 257 exit(EXIT_SUCCESS);
mzta 0:e7eb8eab3aa9 258 }
mzta 0:e7eb8eab3aa9 259 default:
mzta 0:e7eb8eab3aa9 260 return EXIT_FAILURE;
mzta 0:e7eb8eab3aa9 261 }
mzta 0:e7eb8eab3aa9 262 }
mzta 0:e7eb8eab3aa9 263 return EXIT_SUCCESS;
mzta 0:e7eb8eab3aa9 264 }
mzta 0:e7eb8eab3aa9 265
mzta 0:e7eb8eab3aa9 266 static void
mzta 0:e7eb8eab3aa9 267 cleanup(mrb_state *mrb, struct _args *args)
mzta 0:e7eb8eab3aa9 268 {
mzta 0:e7eb8eab3aa9 269 mrb_close(mrb);
mzta 0:e7eb8eab3aa9 270 }
mzta 0:e7eb8eab3aa9 271
mzta 0:e7eb8eab3aa9 272 /* Print a short remark for the user */
mzta 0:e7eb8eab3aa9 273 static void
mzta 0:e7eb8eab3aa9 274 print_hint(void)
mzta 0:e7eb8eab3aa9 275 {
mzta 0:e7eb8eab3aa9 276 pc.printf("mirb - Embeddable Interactive Ruby Shell\n\n");
mzta 0:e7eb8eab3aa9 277 }
mzta 0:e7eb8eab3aa9 278
mzta 0:e7eb8eab3aa9 279 #ifndef ENABLE_READLINE
mzta 0:e7eb8eab3aa9 280 /* Print the command line prompt of the REPL */
mzta 0:e7eb8eab3aa9 281 static void
mzta 0:e7eb8eab3aa9 282 print_cmdline(int code_block_open)
mzta 0:e7eb8eab3aa9 283 {
mzta 0:e7eb8eab3aa9 284 if (code_block_open) {
mzta 0:e7eb8eab3aa9 285 pc.printf("* ");
mzta 0:e7eb8eab3aa9 286 }
mzta 0:e7eb8eab3aa9 287 else {
mzta 0:e7eb8eab3aa9 288 pc.printf("> ");
mzta 0:e7eb8eab3aa9 289 }
mzta 0:e7eb8eab3aa9 290 }
mzta 0:e7eb8eab3aa9 291 #endif
mzta 0:e7eb8eab3aa9 292
mzta 0:e7eb8eab3aa9 293 #if defined(__cplusplus)
mzta 0:e7eb8eab3aa9 294 extern "C" {
mzta 0:e7eb8eab3aa9 295 #endif
mzta 0:e7eb8eab3aa9 296 void mrb_codedump_all(mrb_state*, struct RProc*);
mzta 0:e7eb8eab3aa9 297 #if defined(__cplusplus)
mzta 0:e7eb8eab3aa9 298 }
mzta 0:e7eb8eab3aa9 299 #endif
mzta 0:e7eb8eab3aa9 300
mzta 0:e7eb8eab3aa9 301 static int
mzta 0:e7eb8eab3aa9 302 check_keyword(const char *buf, const char *word)
mzta 0:e7eb8eab3aa9 303 {
mzta 0:e7eb8eab3aa9 304 const char *p = buf;
mzta 0:e7eb8eab3aa9 305 size_t len = strlen(word);
mzta 0:e7eb8eab3aa9 306
mzta 0:e7eb8eab3aa9 307 /* skip preceding spaces */
mzta 0:e7eb8eab3aa9 308 while (*p && isspace((unsigned char)*p)) {
mzta 0:e7eb8eab3aa9 309 p++;
mzta 0:e7eb8eab3aa9 310 }
mzta 0:e7eb8eab3aa9 311 /* check keyword */
mzta 0:e7eb8eab3aa9 312 if (strncmp(p, word, len) != 0) {
mzta 0:e7eb8eab3aa9 313 return 0;
mzta 0:e7eb8eab3aa9 314 }
mzta 0:e7eb8eab3aa9 315 p += len;
mzta 0:e7eb8eab3aa9 316 /* skip trailing spaces */
mzta 0:e7eb8eab3aa9 317 while (*p) {
mzta 0:e7eb8eab3aa9 318 if (!isspace((unsigned char)*p)) return 0;
mzta 0:e7eb8eab3aa9 319 p++;
mzta 0:e7eb8eab3aa9 320 }
mzta 0:e7eb8eab3aa9 321 return 1;
mzta 0:e7eb8eab3aa9 322 }
mzta 0:e7eb8eab3aa9 323
mzta 0:e7eb8eab3aa9 324 char *mirb_argv[] = {
mzta 0:e7eb8eab3aa9 325 "mirb"
mzta 0:e7eb8eab3aa9 326 };
mzta 0:e7eb8eab3aa9 327
mzta 0:e7eb8eab3aa9 328 int
mzta 0:e7eb8eab3aa9 329 main(void)
mzta 0:e7eb8eab3aa9 330 {
mzta 0:e7eb8eab3aa9 331 int argc = 1;
mzta 0:e7eb8eab3aa9 332 char **argv = mirb_argv;
mzta 0:e7eb8eab3aa9 333 char ruby_code[1024] = { 0 };
mzta 0:e7eb8eab3aa9 334 char last_code_line[1024] = { 0 };
mzta 0:e7eb8eab3aa9 335 #ifndef ENABLE_READLINE
mzta 0:e7eb8eab3aa9 336 int last_char;
mzta 0:e7eb8eab3aa9 337 int char_index;
mzta 0:e7eb8eab3aa9 338 #else
mzta 0:e7eb8eab3aa9 339 char *history_path;
mzta 0:e7eb8eab3aa9 340 #endif
mzta 0:e7eb8eab3aa9 341 mrbc_context *cxt;
mzta 0:e7eb8eab3aa9 342 struct mrb_parser_state *parser;
mzta 0:e7eb8eab3aa9 343 mrb_state *mrb;
mzta 0:e7eb8eab3aa9 344 mrb_value result;
mzta 0:e7eb8eab3aa9 345 struct _args args;
mzta 0:e7eb8eab3aa9 346 int n;
mzta 0:e7eb8eab3aa9 347 mrb_bool code_block_open = FALSE;
mzta 0:e7eb8eab3aa9 348 int ai;
mzta 0:e7eb8eab3aa9 349 unsigned int stack_keep = 0;
mzta 0:e7eb8eab3aa9 350
mzta 0:e7eb8eab3aa9 351 /* new interpreter instance */
mzta 0:e7eb8eab3aa9 352 mrb = mrb_open();
mzta 0:e7eb8eab3aa9 353 if (mrb == NULL) {
mzta 0:e7eb8eab3aa9 354 pc.printf("Invalid mrb interpreter, exiting mirb\n");
mzta 0:e7eb8eab3aa9 355 return EXIT_FAILURE;
mzta 0:e7eb8eab3aa9 356 }
mzta 0:e7eb8eab3aa9 357 mrb_define_global_const(mrb, "ARGV", mrb_ary_new_capa(mrb, 0));
mzta 0:e7eb8eab3aa9 358
mzta 0:e7eb8eab3aa9 359 n = parse_args(mrb, argc, argv, &args);
mzta 0:e7eb8eab3aa9 360 if (n == EXIT_FAILURE) {
mzta 0:e7eb8eab3aa9 361 cleanup(mrb, &args);
mzta 0:e7eb8eab3aa9 362 usage(argv[0]);
mzta 0:e7eb8eab3aa9 363 return n;
mzta 0:e7eb8eab3aa9 364 }
mzta 0:e7eb8eab3aa9 365
mzta 0:e7eb8eab3aa9 366 #ifdef ENABLE_READLINE
mzta 0:e7eb8eab3aa9 367 history_path = get_history_path(mrb);
mzta 0:e7eb8eab3aa9 368 if (history_path == NULL) {
mzta 0:e7eb8eab3aa9 369 pc.printf("failed to get history path\n");
mzta 0:e7eb8eab3aa9 370 mrb_close(mrb);
mzta 0:e7eb8eab3aa9 371 return EXIT_FAILURE;
mzta 0:e7eb8eab3aa9 372 }
mzta 0:e7eb8eab3aa9 373
mzta 0:e7eb8eab3aa9 374 MIRB_USING_HISTORY();
mzta 0:e7eb8eab3aa9 375 MIRB_READ_HISTORY(history_path);
mzta 0:e7eb8eab3aa9 376 #endif
mzta 0:e7eb8eab3aa9 377
mzta 0:e7eb8eab3aa9 378 print_hint();
mzta 0:e7eb8eab3aa9 379
mzta 0:e7eb8eab3aa9 380 cxt = mrbc_context_new(mrb);
mzta 0:e7eb8eab3aa9 381 cxt->capture_errors = TRUE;
mzta 0:e7eb8eab3aa9 382 cxt->lineno = 1;
mzta 0:e7eb8eab3aa9 383 mrbc_filename(mrb, cxt, "(mirb)");
mzta 0:e7eb8eab3aa9 384 if (args.verbose) cxt->dump_result = TRUE;
mzta 0:e7eb8eab3aa9 385
mzta 0:e7eb8eab3aa9 386 ai = mrb_gc_arena_save(mrb);
mzta 0:e7eb8eab3aa9 387
mzta 0:e7eb8eab3aa9 388 while (TRUE) {
mzta 0:e7eb8eab3aa9 389 #ifndef ENABLE_READLINE
mzta 0:e7eb8eab3aa9 390 print_cmdline(code_block_open);
mzta 0:e7eb8eab3aa9 391
mzta 0:e7eb8eab3aa9 392 char_index = 0;
mzta 0:e7eb8eab3aa9 393 while ((last_char = pc.getc()) != '\n') {
mzta 0:e7eb8eab3aa9 394 pc.printf("%c", last_char);
mzta 0:e7eb8eab3aa9 395 if (last_char == EOF) break;
mzta 0:e7eb8eab3aa9 396 if (char_index > sizeof(last_code_line)-2) {
mzta 0:e7eb8eab3aa9 397 pc.printf("input string too long\n");
mzta 0:e7eb8eab3aa9 398 continue;
mzta 0:e7eb8eab3aa9 399 }
mzta 0:e7eb8eab3aa9 400 if (last_char == '\x08') {
mzta 0:e7eb8eab3aa9 401 if (char_index > 0) char_index--;
mzta 0:e7eb8eab3aa9 402 continue;
mzta 0:e7eb8eab3aa9 403 } else {
mzta 0:e7eb8eab3aa9 404 last_code_line[char_index++] = last_char;
mzta 0:e7eb8eab3aa9 405 }
mzta 0:e7eb8eab3aa9 406 }
mzta 0:e7eb8eab3aa9 407 pc.printf("\n");
mzta 0:e7eb8eab3aa9 408
mzta 0:e7eb8eab3aa9 409 if (last_char == EOF) {
mzta 0:e7eb8eab3aa9 410 pc.printf("\n");
mzta 0:e7eb8eab3aa9 411 break;
mzta 0:e7eb8eab3aa9 412 }
mzta 0:e7eb8eab3aa9 413
mzta 0:e7eb8eab3aa9 414 last_code_line[char_index++] = '\n';
mzta 0:e7eb8eab3aa9 415 last_code_line[char_index] = '\0';
mzta 0:e7eb8eab3aa9 416 #else
mzta 0:e7eb8eab3aa9 417 char* line = MIRB_READLINE(code_block_open ? "* " : "> ");
mzta 0:e7eb8eab3aa9 418 if (line == NULL) {
mzta 0:e7eb8eab3aa9 419 printf("\n");
mzta 0:e7eb8eab3aa9 420 break;
mzta 0:e7eb8eab3aa9 421 }
mzta 0:e7eb8eab3aa9 422 if (strlen(line) > sizeof(last_code_line)-2) {
mzta 0:e7eb8eab3aa9 423 pc.printf("input string too long\n");
mzta 0:e7eb8eab3aa9 424 continue;
mzta 0:e7eb8eab3aa9 425 }
mzta 0:e7eb8eab3aa9 426 strcpy(last_code_line, line);
mzta 0:e7eb8eab3aa9 427 strcat(last_code_line, "\n");
mzta 0:e7eb8eab3aa9 428 MIRB_ADD_HISTORY(line);
mzta 0:e7eb8eab3aa9 429 free(line);
mzta 0:e7eb8eab3aa9 430 #endif
mzta 0:e7eb8eab3aa9 431
mzta 0:e7eb8eab3aa9 432 if (code_block_open) {
mzta 0:e7eb8eab3aa9 433 if (strlen(ruby_code)+strlen(last_code_line) > sizeof(ruby_code)-1) {
mzta 0:e7eb8eab3aa9 434 pc.printf("concatenated input string too long\n");
mzta 0:e7eb8eab3aa9 435 continue;
mzta 0:e7eb8eab3aa9 436 }
mzta 0:e7eb8eab3aa9 437 strcat(ruby_code, last_code_line);
mzta 0:e7eb8eab3aa9 438 }
mzta 0:e7eb8eab3aa9 439 else {
mzta 0:e7eb8eab3aa9 440 if (check_keyword(last_code_line, "quit") || check_keyword(last_code_line, "exit")) {
mzta 0:e7eb8eab3aa9 441 break;
mzta 0:e7eb8eab3aa9 442 }
mzta 0:e7eb8eab3aa9 443 strcpy(ruby_code, last_code_line);
mzta 0:e7eb8eab3aa9 444 }
mzta 0:e7eb8eab3aa9 445
mzta 0:e7eb8eab3aa9 446 /* parse code */
mzta 0:e7eb8eab3aa9 447 parser = mrb_parser_new(mrb);
mzta 0:e7eb8eab3aa9 448 if (parser == NULL) {
mzta 0:e7eb8eab3aa9 449 pc.printf("create parser state error\n");
mzta 0:e7eb8eab3aa9 450 break;
mzta 0:e7eb8eab3aa9 451 }
mzta 0:e7eb8eab3aa9 452 parser->s = ruby_code;
mzta 0:e7eb8eab3aa9 453 parser->send = ruby_code + strlen(ruby_code);
mzta 0:e7eb8eab3aa9 454 parser->lineno = cxt->lineno;
mzta 0:e7eb8eab3aa9 455 mrb_parser_parse(parser, cxt);
mzta 0:e7eb8eab3aa9 456 code_block_open = is_code_block_open(parser);
mzta 0:e7eb8eab3aa9 457
mzta 0:e7eb8eab3aa9 458 if (code_block_open) {
mzta 0:e7eb8eab3aa9 459 /* no evaluation of code */
mzta 0:e7eb8eab3aa9 460 }
mzta 0:e7eb8eab3aa9 461 else {
mzta 0:e7eb8eab3aa9 462 if (0 < parser->nerr) {
mzta 0:e7eb8eab3aa9 463 /* syntax error */
mzta 0:e7eb8eab3aa9 464 pc.printf("line %d: %s\n", parser->error_buffer[0].lineno, parser->error_buffer[0].message);
mzta 0:e7eb8eab3aa9 465 }
mzta 0:e7eb8eab3aa9 466 else {
mzta 0:e7eb8eab3aa9 467 /* generate bytecode */
mzta 0:e7eb8eab3aa9 468 struct RProc *proc = mrb_generate_code(mrb, parser);
mzta 0:e7eb8eab3aa9 469 if (proc == NULL) {
mzta 0:e7eb8eab3aa9 470 pc.printf("codegen error\n");
mzta 0:e7eb8eab3aa9 471 mrb_parser_free(parser);
mzta 0:e7eb8eab3aa9 472 break;
mzta 0:e7eb8eab3aa9 473 }
mzta 0:e7eb8eab3aa9 474
mzta 0:e7eb8eab3aa9 475 if (args.verbose) {
mzta 0:e7eb8eab3aa9 476 mrb_codedump_all(mrb, proc);
mzta 0:e7eb8eab3aa9 477 }
mzta 0:e7eb8eab3aa9 478 /* pass a proc for evaulation */
mzta 0:e7eb8eab3aa9 479 /* evaluate the bytecode */
mzta 0:e7eb8eab3aa9 480 result = mrb_context_run(mrb,
mzta 0:e7eb8eab3aa9 481 proc,
mzta 0:e7eb8eab3aa9 482 mrb_top_self(mrb),
mzta 0:e7eb8eab3aa9 483 stack_keep);
mzta 0:e7eb8eab3aa9 484 stack_keep = proc->body.irep->nlocals;
mzta 0:e7eb8eab3aa9 485 /* did an exception occur? */
mzta 0:e7eb8eab3aa9 486 if (mrb->exc) {
mzta 0:e7eb8eab3aa9 487 p(mrb, mrb_obj_value(mrb->exc), 0);
mzta 0:e7eb8eab3aa9 488 mrb->exc = 0;
mzta 0:e7eb8eab3aa9 489 }
mzta 0:e7eb8eab3aa9 490 else {
mzta 0:e7eb8eab3aa9 491 /* no */
mzta 0:e7eb8eab3aa9 492 if (!mrb_respond_to(mrb, result, mrb_intern_lit(mrb, "inspect"))){
mzta 0:e7eb8eab3aa9 493 result = mrb_any_to_s(mrb, result);
mzta 0:e7eb8eab3aa9 494 }
mzta 0:e7eb8eab3aa9 495 p(mrb, result, 1);
mzta 0:e7eb8eab3aa9 496 }
mzta 0:e7eb8eab3aa9 497 }
mzta 0:e7eb8eab3aa9 498 ruby_code[0] = '\0';
mzta 0:e7eb8eab3aa9 499 last_code_line[0] = '\0';
mzta 0:e7eb8eab3aa9 500 mrb_gc_arena_restore(mrb, ai);
mzta 0:e7eb8eab3aa9 501 }
mzta 0:e7eb8eab3aa9 502 mrb_parser_free(parser);
mzta 0:e7eb8eab3aa9 503 cxt->lineno++;
mzta 0:e7eb8eab3aa9 504 }
mzta 0:e7eb8eab3aa9 505
mzta 0:e7eb8eab3aa9 506 #ifdef ENABLE_READLINE
mzta 0:e7eb8eab3aa9 507 MIRB_WRITE_HISTORY(history_path);
mzta 0:e7eb8eab3aa9 508 mrb_free(mrb, history_path);
mzta 0:e7eb8eab3aa9 509 #endif
mzta 0:e7eb8eab3aa9 510
mzta 0:e7eb8eab3aa9 511 mrbc_context_free(mrb, cxt);
mzta 0:e7eb8eab3aa9 512 mrb_close(mrb);
mzta 0:e7eb8eab3aa9 513
mzta 0:e7eb8eab3aa9 514 return 0;
mzta 0:e7eb8eab3aa9 515 }