| 2370 | } |
| 2371 | |
| 2372 | static void compile_parse( PARSE * parse, compiler * c, int result_location ) |
| 2373 | { |
| 2374 | if ( parse->type == PARSE_APPEND ) |
| 2375 | { |
| 2376 | compile_append_chain( parse, c ); |
| 2377 | adjust_result( c, RESULT_STACK, result_location ); |
| 2378 | } |
| 2379 | else if ( parse->type == PARSE_EVAL ) |
| 2380 | { |
| 2381 | /* FIXME: This is only needed because of the bizarre parsing of |
| 2382 | * conditions. |
| 2383 | */ |
| 2384 | if ( parse->num == EXPR_EXISTS ) |
| 2385 | compile_parse( parse->left, c, result_location ); |
| 2386 | else |
| 2387 | { |
| 2388 | int f = compile_new_label( c ); |
| 2389 | int end = compile_new_label( c ); |
| 2390 | |
| 2391 | printf( "%s:%d: Conditional used as list (check operator " |
| 2392 | "precedence).\n", object_str( parse->file ), parse->line ); |
| 2393 | |
| 2394 | /* Emit the condition */ |
| 2395 | compile_condition( parse, c, 0, f ); |
| 2396 | compile_emit( c, INSTR_PUSH_CONSTANT, compile_emit_constant( c, |
| 2397 | constant_true ) ); |
| 2398 | compile_emit_branch( c, INSTR_JUMP, end ); |
| 2399 | compile_set_label( c, f ); |
| 2400 | compile_emit( c, INSTR_PUSH_EMPTY, 0 ); |
| 2401 | compile_set_label( c, end ); |
| 2402 | adjust_result( c, RESULT_STACK, result_location ); |
| 2403 | } |
| 2404 | } |
| 2405 | else if ( parse->type == PARSE_FOREACH ) |
| 2406 | { |
| 2407 | int var = compile_emit_constant( c, parse->string ); |
| 2408 | int top = compile_new_label( c ); |
| 2409 | int end = compile_new_label( c ); |
| 2410 | |
| 2411 | /* |
| 2412 | * Evaluate the list. |
| 2413 | */ |
| 2414 | compile_parse( parse->left, c, RESULT_STACK ); |
| 2415 | |
| 2416 | /* Localize the loop variable */ |
| 2417 | if ( parse->num ) |
| 2418 | { |
| 2419 | compile_emit( c, INSTR_PUSH_EMPTY, 0 ); |
| 2420 | compile_emit( c, INSTR_PUSH_LOCAL, var ); |
| 2421 | compile_emit( c, INSTR_SWAP, 1 ); |
| 2422 | } |
| 2423 | |
| 2424 | compile_emit( c, INSTR_FOR_INIT, 0 ); |
| 2425 | compile_set_label( c, top ); |
| 2426 | compile_emit_branch( c, INSTR_FOR_LOOP, end ); |
| 2427 | compile_emit( c, INSTR_SET, var ); |
| 2428 | |
| 2429 | /* Run the loop body */ |
no test coverage detected