5 * Copyright (C) 2007-2008, The Perl Foundation.
12 pir.y - Bison specification for the PIR assembly language parser.
16 This file implements the parser for the PIR assembly language. During the
17 parsing phase, data structures are created that represent the input. These
18 data structures are defined in C<pircompunit.h>.
20 The parser implements strength reduction and constant folding. Strength
21 reduction refers to the selection of instructions that have the same
22 effect as the instruction written by the PIR programmer, but are more
23 efficient. For instance:
31 as C<$P0> was an IN/OUT operand.
33 Constant folding refers to the compile-time evaluation of expressions,
34 if possible. For instance:
42 as we can evaluate this result during compile time. Likewise, conditional
43 branch instructions may become unconditional branch instructions (if the
44 condition evaluates to I<true> during compile time) or it may become a C<noop>
45 (no op) instruction (if the condition evaluates to I<false> during compile time).
50 1. improve memory management (free it!)
52 3. generate PBC, using Parrot_PackFile (and related) data structures.
53 4. handle branch/invoke instructions to calculate offsets etc.
54 5. handle freezing of PMC constants (representing subs)
63 #include "pirparser.h"
64 #include "pircompiler.h"
65 #include "pircompunit.h"
66 #include "pirsymbol.h"
69 /* prevent inclusion of <unistd.h> on windows */
70 #define YY_NO_UNISTD_H
72 /* define YY_DECL, so that in "pirlexer.h" it won't be defined */
73 #define YY_DECL int yylex(YYSTYPE *yylval, yyscan_t yyscanner)
75 /* include "pirlexer.h" before "piryy.h" */
79 /* declare yylex(); do this I<after> including "pirlexer.h" */
84 /* Enumeration of mathematical operator types; these are used to index the opnames array. */
85 typedef
enum pir_math_operators
{
86 OP_ADD
= 0, /* make sure counting starts at 0 */
87 OP_INC
, /* special case for OP_ADD; must be 1 position after OP_ADD */
89 OP_DEC
, /* special case for OP_DEC; must be 1 position after OP_SUB */
114 /* relational operator types */
115 typedef
enum pir_rel_operators
{
116 OP_NE
= OP_ISNE
+ 1, /* continue after OP_ISNE in pir_math_operator. */
125 /* names of the binary operators */
126 static char * const opnames
[] = {
128 "inc", /* use this when "add"ing 1 */
130 "dec", /* use this when "sub"ing 1 */
152 /* note that from here on it's rel. ops; see pir_rel_operator enumeration */
161 /* prototypes for constant folding and compile-time evaluation functions */
162 static constant
*fold_i_i
(yyscan_t yyscanner
, int a
, pir_math_operator op
, int b
);
163 static constant
*fold_n_i
(yyscan_t yyscanner
, double a
, pir_math_operator op
, int b
);
164 static constant
*fold_i_n
(yyscan_t yyscanner
, int a
, pir_math_operator op
, double b
);
165 static constant
*fold_n_n
(yyscan_t yyscanner
, double a
, pir_math_operator op
, double b
);
166 static constant
*fold_s_s
(yyscan_t yyscanner
, char *a
, pir_math_operator op
, char *b
);
168 static int evaluate_i_i
(int a
, pir_rel_operator op
, int b
);
169 static int evaluate_n_n
(double a
, pir_rel_operator op
, double b
);
170 static int evaluate_i_n
(int a
, pir_rel_operator op
, double b
);
171 static int evaluate_n_i
(double a
, pir_rel_operator op
, int b
);
172 static int evaluate_s_s
(char * const a
, pir_rel_operator op
, char * const b
);
174 static int evaluate_s
(char * const s
);
175 static int evaluate_c
(constant
* const c
);
177 static char *concat_strings
(char *a
, char *b
);
179 static void create_if_instr
(yyscan_t yyscanner
, lexer_state
* const lexer
, int invert
,
180 int hasnull
, char * const name
, char * const label
);
182 static void do_strength_reduction
(lexer_state
* const lexer
);
183 static int check_value
(constant
* const c
, int val
);
186 /* enable debugging of generated parser */
189 /* enable slightly more helpful error messages */
190 #define YYERROR_VERBOSE 1
192 /* keep MSVC happy */
194 # define YYENABLE_NLS 0
197 /* keep MSVC happy */
198 #ifndef YYLTYPE_IS_TRIVIAL
199 # define YYLTYPE_IS_TRIVIAL 0
203 /* the parser aborts if there are more than 10 errors */
204 #define MAX_NUM_ERRORS 10
209 /* list all types that can be moved from lexer to parser, or from
210 * rule to rule in the parser only.
216 struct constant
*cval
;
217 struct instruction
*instr
;
218 struct expression
*expr
;
220 struct argument
*argm
;
221 struct invocation
*invo
;
230 TK_HLL_MAP
".HLL_map"
231 TK_LOADLIB
".loadlib"
238 TK_NAMESPACE
".namespace"
239 TK_INVOCANT
".invocant"
240 TK_METH_CALL
".meth_call"
241 TK_GLOBALCONST
".globalconst"
245 TK_SET_YIELD
".set_yield"
246 TK_SET_RETURN
".set_return"
247 TK_BEGIN_YIELD
".begin_yield"
248 TK_END_YIELD
".end_yield"
249 TK_BEGIN_RETURN
".begin_return"
250 TK_END_RETURN
".end_return"
251 TK_BEGIN_CALL
".begin_call"
252 TK_END_CALL
".end_call"
253 TK_GET_RESULTS
".get_results"
255 TK_SET_ARG
".set_arg"
256 TK_GET_RESULT
".get_result"
257 TK_NCI_CALL
".nci_call"
258 TK_TAILCALL
".tailcall"
260 %token
<sval
> TK_LABEL
"label"
261 <sval
> TK_IDENT
"identifier"
265 <sval
> TK_STRING
"string"
267 <sval
> TK_UNLESS
"unless"
268 <sval
> TK_NULL
"null"
269 <sval
> TK_GOTO
"goto"
271 <sval
> TK_STRINGC
"string constant"
272 <ival
> TK_INTC
"integer constant"
273 <dval
> TK_NUMC
"number constant"
274 <ival
> TK_PREG
"PMC register"
275 <ival
> TK_NREG
"number register"
276 <ival
> TK_SREG
"string register"
277 <ival
> TK_IREG
"integer register"
295 TK_ASSIGN_USHIFT
">>>="
296 TK_ASSIGN_RSHIFT
">>="
297 TK_ASSIGN_LSHIFT
"<<="
299 %token TK_ASSIGN_INC
"+="
311 %token TK_FLAG_INIT
":init"
315 TK_FLAG_METHOD
":method"
316 TK_FLAG_OUTER
":outer"
317 TK_FLAG_VTABLE
":vtable"
319 TK_FLAG_MULTI
":multi"
320 TK_FLAG_POSTCOMP
":postcomp"
321 TK_FLAG_IMMEDIATE
":immediate"
322 TK_FLAG_LEXID
":lexid"
323 TK_INSTANCEOF
":instanceof"
325 %token TK_FLAG_UNIQUE_REG
":unique_reg"
326 TK_FLAG_NAMED
":named"
327 TK_FLAG_SLURPY
":slurpy"
329 TK_FLAG_OPTIONAL
":optional"
330 TK_FLAG_OPT_FLAG
":opt_flag"
331 TK_FLAG_INVOCANT
":invocant"
359 %type
<symb
> local_id
362 %type
<argm
> named_arg
369 opt_yield_expressions
372 opt_return_expressions
379 %type
<expr
> expression
387 %type
<ival
> has_unique_reg
403 %type
<invo
> long_invocation
405 short_invocation_stat
417 %type
<cval
> const_tail
421 /* needed for reentrancy */
424 /* name of generated parser */
425 %output
="pirparser.c"
427 /* move around a yyscan_t object */
428 %parse
-param
{yyscan_t yyscanner
}
429 %lex
-param
{yyscan_t yyscanner
}
431 /* The parser is invoked with this extra parameter */
432 %parse
-param
{struct lexer_state
* const lexer
}
434 /* Note: don't declare the lexer_state argument as a %lex-param,
435 * this object is stored in the yyscan_t structure, and can be
436 * accessed through yy{set,get}_extra().
440 /* A note on the layout of the grammar rules.
442 * All actions should be written on the next line, with a fixed indention
443 * w.r.t. colon (':'). This is true for all rules, except:
445 * 1: simple actions that return a flag. For instance, the <has_unique_reg> rule.
446 * 2: simple rules that have only single tokens as alternatives. See the operators
449 * + Do not write embedded actions; instead, refactor the grammar by adding
450 * a new rule, so that the previously-embedded action becomes a 'normal'
461 /* Top-level rules */
472 pir_chunks
: pir_chunk
473 | pir_chunks
"\n" pir_chunk
484 loadlib
: ".loadlib" TK_STRINGC
485 { load_library
(lexer
, $2); }
490 hll_specifier
: ".HLL" TK_STRINGC
491 { set_hll
(lexer
, $2); }
494 hll_mapping
: ".HLL_map" TK_STRINGC
'=' TK_STRINGC
495 { set_hll_map
(lexer
, $2, $4); }
498 namespace_decl
: ".namespace" '[' opt_namespace
']'
499 { set_namespace
(lexer
, $3); }
502 opt_namespace
: /* empty */
508 namespace
: namespace_slice
509 { $$
= new_key
($1); }
510 | namespace
';' namespace_slice
511 { $$
= add_key
($1, $3); }
514 namespace_slice
: TK_STRINGC
515 { $$
= expr_from_const
(new_const
(STRING_TYPE
, $1)); }
518 sub_def
: sub_head sub_flags
"\n"
524 sub_head
: ".sub" sub_id
525 { new_subr
(lexer
, $2); }
532 sub_flags
: /* empty */
537 { set_sub_flag
(lexer
, SUB_FLAG_ANON
);}
539 { set_sub_flag
(lexer
, SUB_FLAG_INIT
); }
541 { set_sub_flag
(lexer
, SUB_FLAG_LOAD
); }
543 { set_sub_flag
(lexer
, SUB_FLAG_MAIN
); }
545 { set_sub_flag
(lexer
, SUB_FLAG_METHOD
); }
547 { set_sub_flag
(lexer
, SUB_FLAG_LEX
); }
549 { set_sub_flag
(lexer
, SUB_FLAG_POSTCOMP
); }
551 { set_sub_flag
(lexer
, SUB_FLAG_IMMEDIATE
); }
553 { set_sub_flag
(lexer
, SUB_FLAG_MULTI
); }
554 |
":outer" '(' sub_id
')'
555 { set_sub_outer
(lexer
, $3); }
556 |
":vtable" opt_paren_string
557 { set_sub_vtable
(lexer
, $2); }
558 |
":lexid" paren_string
559 { set_sub_lexid
(lexer
, $2); }
560 |
":instanceof" paren_string
561 { set_sub_instanceof
(lexer
, $2); }
564 multi_type
: identifier
569 parameters
: /* empty */
570 | parameters parameter
573 parameter
: ".param" param param_flags
"\n"
574 { set_param_flag
(lexer
, $2, $3); }
577 param
: type identifier
578 { $$
= add_param
(lexer
, $1, $2); }
581 param_flags
: /* empty */
583 | param_flags param_flag
584 { SET_FLAG
($$
, $2); }
587 param_flag
: target_flag
592 invocant_param
: ":invocant" '(' multi_type
')'
593 { $$
= TARGET_FLAG_INVOCANT
; /* XXX handle multi_type */}
596 unique_reg_flag
: ":unique_reg"
597 { $$
= TARGET_FLAG_UNIQUE_REG
; }
602 instructions
: /* empty */
603 | instructions instruction
606 instruction
: TK_LABEL
"\n"
607 { set_label
(lexer
, $1); }
609 { set_label
(lexer
, $1); }
613 statement
: conditional_stat
627 /* "error" is a built-in rule; used for trying to recover. */
628 error_stat
: error "\n"
630 if
(lexer
->parse_errors
> MAX_NUM_ERRORS
) {
631 fprintf
(stderr
, "Too many errors. Compilation aborted.\n");
632 exit
(EXIT_FAILURE
); /* fix: bail out and free() all memory */
638 null_stat
: "null" target
"\n"
639 { set_instrf
(lexer
, "null", "%T", $2); }
642 getresults_stat
: ".get_results" opt_target_list
"\n"
643 { set_instrf
(lexer
, "get_results", "%T", $2); }
646 parrot_stat
: parrot_instruction
"\n"
649 parrot_instruction: parrot_op opt_op_args
653 { /* at this point, TK_IDENT may in fact be a symbol identifier,
654 * not an op, so don't do any checks like is_parrot_op() just yet.
656 set_instr
(lexer
, $1);
661 opt_op_args
: op_args
662 { /* when this rule is activated, the initial identifier must
663 * be a parrot op. Check that, and if not, emit an error message.
665 char * const instr
= get_instr
(lexer
);
666 if
(!is_parrot_op
(lexer
, instr
))
667 yyerror(yyscanner
, lexer
, "'%s' is not a parrot instruction", instr
);
669 do_strength_reduction
(lexer
);
674 op_args
: /* empty */
678 parrot_op_args
: op_arg
679 | parrot_op_args
',' op_arg
682 keylist_assignment: keylist
'=' expression
684 /* the "instruction" that was set now appears to be
685 * an identifier; get the name, and check its type.
687 char * const instr
= get_instr
(lexer
);
688 symbol
*sym
= find_symbol
(lexer
, instr
);
691 /* find the symbol for the object being indexed;
692 * it must have been declared
695 yyerror(yyscanner
, lexer
, "indexed object '%s' not declared", instr
);
696 sym
= new_symbol
(instr
, PMC_TYPE
);
698 else if
(sym
->type
!= PMC_TYPE
) /* found symbol, now check it's a PMC */
699 yyerror(yyscanner
, lexer
,
700 "indexed object '%s' must be of type 'pmc'", instr
);
702 /* convert the symbol into a target */
703 obj
= target_from_symbol
(sym
);
705 /* set the key on the target */
706 set_target_key
(obj
, $1);
707 /* indexed operation is a "set" opcode */
708 set_instrf
(lexer
, "set", "%T%E", obj
, $3);
713 { push_operand
(lexer
, $1); }
715 { push_operand
(lexer
, expr_from_key
($1)); }
717 { push_operand
(lexer
, expr_from_target
($1)); }
720 keyaccess
: pmc_object keylist
722 /* if $1 is a register, just return that */
723 if
(TEST_FLAG
($1->flags
, TARGET_FLAG_IS_REG
))
725 else
{ /* it's not a register, so it must be a declared symbol */
726 symbol
*sym
= find_symbol
(lexer
, target_name
($1));
728 yyerror(yyscanner
, lexer
,
729 "indexed object '%s' not declared", target_name
($1));
730 /* make sure sym is a valid pointer */
731 sym
= new_symbol
(target_name
($1), PMC_TYPE
);
733 else if
(sym
->type
!= PMC_TYPE
)
734 yyerror(yyscanner
, lexer
,
735 "indexed object '%s' is not of type 'pmc'",
738 /* create a target node based on the symbol node;
739 * sym already has a PASM register, so through
740 * this the target will get that too.
742 $$
= target_from_symbol
(sym
);
745 /* in both cases (register or symbol), set the key on this target */
746 set_target_key
($$
, $2);
750 keylist
: '[' keys
']'
755 { $$
= new_key
($1); }
756 | keys
';' expression
757 { $$
= add_key
($1, $3); }
761 assignment_stat
: assignment
"\n"
764 assignment
: target
'=' TK_INTC
767 set_instrf
(lexer
, "null", "%T", $1);
769 set_instrf
(lexer
, "set", "%T%i", $1, $3);
774 set_instrf
(lexer
, "null", "%T", $1);
776 set_instrf
(lexer
, "set", "%T%n", $1, $3);
778 | target
'=' TK_STRINGC
779 { set_instrf
(lexer
, "set", "%T%s", $1, $3); }
780 | target
'=' binary_expr
781 { unshift_operand
(lexer
, expr_from_target
($1)); }
782 | target
'=' parrot_op
784 symbol
*sym
= find_symbol
(lexer
, $3);
786 if
(!is_parrot_op
(lexer
, $3))
787 yyerror(yyscanner
, lexer
, "'%s' is neither a declared symbol "
788 "nor a parrot opcode", $3);
789 else
/* handle it as an op */
790 unshift_operand
(lexer
, expr_from_target
($1));
792 else
/* handle it as a symbol */
793 set_instrf
(lexer
, "set", "%T%T", $1, target_from_symbol
(sym
));
796 | target
'=' parrot_op expression
',' parrot_op_args
798 if
(!is_parrot_op
(lexer
, $3))
799 yyerror(yyscanner
, lexer
, "'%s' is not a parrot op", $3);
801 unshift_operand
(lexer
, $4);
802 unshift_operand
(lexer
, expr_from_target
($1));
803 do_strength_reduction
(lexer
);
806 | target
'=' parrot_op expression
808 if
(!is_parrot_op
(lexer
, $3))
809 yyerror(yyscanner
, lexer
, "'%s' is not a parrot op", $3);
811 set_instrf
(lexer
, $3, "%T%E", $1, $4);
812 do_strength_reduction
(lexer
);
815 | target
'=' parrot_op keylist
817 symbol
*sym
= find_symbol
(lexer
, $3);
820 if
(is_parrot_op
(lexer
, $3))
821 set_instrf
(lexer
, $3, "%T%E", $1, expr_from_key
($4));
823 yyerror(yyscanner
, lexer
, "indexed object '%s' not declared", $3);
825 /* create a symbol node anyway, so we can continue with instr. gen. */
826 sym
= new_symbol
($3, PMC_TYPE
);
828 /* at this point, sym is not NULL, even if there was an error */
829 if
(sym
->type
!= PMC_TYPE
)
830 yyerror(yyscanner
, lexer
,
831 "indexed object '%s' must be of type 'pmc'", $3);
833 t
= target_from_symbol
(sym
);
834 set_target_key
(t
, $4);
835 set_instrf
(lexer
, "set", "%T%T", $1, t
);
838 | target
'=' parrot_op keylist
',' parrot_op_args
840 unshift_operand
(lexer
, expr_from_key
($4));
841 unshift_operand
(lexer
, expr_from_target
($1));
843 | target
'=' keyword keylist
845 symbol
*sym
= find_symbol
(lexer
, $3);
849 yyerror(yyscanner
, lexer
, "indexed object '%s' not declared", $3);
850 sym
= new_symbol
($3, PMC_TYPE
);
852 else if
(sym
->type
!= PMC_TYPE
)
853 yyerror(yyscanner
, lexer
,
854 "indexed object '%s' must be of type 'pmc'", $3);
856 t
= target_from_symbol
(sym
);
857 set_target_key
(t
, $4);
858 set_instrf
(lexer
, "set", "%T%T", $1, t
);
860 | target
'=' TK_PREG keylist
862 target
*preg
= new_reg
(lexer
, PMC_TYPE
, $3);
863 set_target_key
(preg
, $4);
864 set_instrf
(lexer
, "set", "%T%T", $1, preg
);
866 | target augmented_op expression
867 { set_instrf
(lexer
, opnames
[$2], "%T%E", $1, $3); }
868 | target
"+=" TK_INTC
871 set_instrf
(lexer
, "inc", "%T", $1);
873 set_instr
(lexer
, "noop");
875 set_instrf
(lexer
, "add", "%T%i", $1, $3);
877 | target
"+=" TK_NUMC
880 set_instrf
(lexer
, "inc", "%T", $1);
882 set_instr
(lexer
, "noop");
884 set_instrf
(lexer
, "add", "%T%n", $1, $3);
886 | target
"-=" TK_INTC
889 set_instrf
(lexer
, "dec", "%T", $1);
891 set_instr
(lexer
, "noop");
893 set_instrf
(lexer
, "sub", "%T%i", $1, $3);
895 | target
"-=" TK_NUMC
898 set_instrf
(lexer
, "dec", "%T", $1);
900 set_instr
(lexer
, "noop");
902 set_instrf
(lexer
, "sub", "%T%n", $1, $3);
905 { set_instrf
(lexer
, "add", "%T%T", $1, $3); }
907 { set_instrf
(lexer
, "sub", "%T%T", $1, $3); }
908 | target
'=' unop expression
909 { set_instrf
(lexer
, $3, "%T%E", $1, $4); }
910 | target
'=' target binop target
912 if
(targets_equal
($1, $3)) /* $P0 = $P0 + $P1 ==> $P0 += $P1 */
913 set_instrf
(lexer
, opnames
[$4], "%T%T", $1, $5);
915 set_instrf
(lexer
, opnames
[$4], "%T%T%T", $1, $3, $5);
917 | keyword keylist
'=' expression
919 symbol
*sym
= find_symbol
(lexer
, $1);
923 yyerror(yyscanner
, lexer
, "indexed object '%s' not declared", $1);
924 /* create a dummy symbol so we can continue without seg. faults */
925 sym
= new_symbol
($1, PMC_TYPE
);
927 else if
(sym
->type
!= PMC_TYPE
)
928 yyerror(yyscanner
, lexer
,
929 "indexed object '%s' must be of type 'pmc'", $1);
930 /* at this point sym is a valid (possibly dummy) object for sure */
931 t
= target_from_symbol
(sym
);
932 set_target_key
(t
, $2);
933 set_instrf
(lexer
, "set", "%T%E", t
, $4);
935 | TK_PREG keylist
'=' expression
937 target
*preg
= new_reg
(lexer
, PMC_TYPE
, $1);
938 set_target_key
(preg
, $2);
939 set_instrf
(lexer
, "set", "%T%E", preg
, $4);
946 =head1 CONSTANT FOLDING
948 A binary expression consists of two expressions, separated by a binary
949 operator. An expression can be a C<target> or a literal value. Such a
950 value can be an C<integer>, C<floating-point> or C<string> literal.
952 In the case that both operands are constants, we can pre-evaluate
953 the result of these constants, effectively preventing any calculation
954 during runtime. For instance:
958 can be pre-evaluated as
962 which will be assembled using the C<set> opcode. Likewise, concatenation
963 of two strings is done during compile time.
968 binary_expr
: TK_INTC binop target
969 { set_instrf
(lexer
, opnames
[$2], "%i%T", $1, $3); }
970 | TK_NUMC binop target
971 { set_instrf
(lexer
, opnames
[$2], "%n%T", $1, $3); }
972 | TK_STRINGC binop target
973 { set_instrf
(lexer
, opnames
[$2], "%s%T", $1, $3); }
974 | TK_STRINGC binop TK_STRINGC
975 { set_instrf
(lexer
, "set", "%C", fold_s_s
(yyscanner
, $1, $2, $3)); }
976 | TK_INTC binop TK_INTC
977 { set_instrf
(lexer
, "set", "%C", fold_i_i
(yyscanner
, $1, $2, $3)); }
978 | TK_NUMC binop TK_NUMC
979 { set_instrf
(lexer
, "set", "%C", fold_n_n
(yyscanner
, $1, $2, $3)); }
980 | TK_INTC binop TK_NUMC
981 { set_instrf
(lexer
, "set", "%C", fold_i_n
(yyscanner
, $1, $2, $3)); }
982 | TK_NUMC binop TK_INTC
983 { set_instrf
(lexer
, "set", "%C", fold_n_i
(yyscanner
, $1, $2, $3)); }
987 conditional_stat
: conditional_instr
"\n"
991 /* In order to allow all keywords (data type names and words such as "if", "null", etc.
992 * a lot of special cases must be distinguished; this is necessary in order to
993 * do a correct parse and prevent shift/reduce conflicts.
995 conditional_instr
: if_unless
"null" TK_IDENT
"goto" identifier
996 { create_if_instr
(yyscanner
, lexer
, $1, 1, $3, $4); }
997 | if_unless
"null" "int" "goto" identifier
998 { create_if_instr
(yyscanner
, lexer
, $1, 1, "int", $4); }
999 | if_unless
"null" "num" "goto" identifier
1000 { create_if_instr
(yyscanner
, lexer
, $1, 1, "num", $4); }
1001 | if_unless
"null" "pmc" "goto" identifier
1002 { create_if_instr
(yyscanner
, lexer
, $1, 1, "pmc", $4); }
1003 | if_unless
"null" "string" "goto" identifier
1004 { create_if_instr
(yyscanner
, lexer
, $1, 1, "string", $4); }
1005 | if_unless
"null" "if" "goto" identifier
1006 { create_if_instr
(yyscanner
, lexer
, $1, 1, "if", $4); }
1007 | if_unless
"null" "unless" "goto" identifier
1008 { create_if_instr
(yyscanner
, lexer
, $1, 1, "unless", $4); }
1009 | if_unless
"null" "goto" "goto" identifier
1010 { create_if_instr
(yyscanner
, lexer
, $1, 1, "goto", $4); }
1011 | if_unless
"null" "null" "goto" identifier
1012 { create_if_instr
(yyscanner
, lexer
, $1, 1, "null", $4); }
1013 | if_unless constant then identifier
1015 int istrue
= evaluate_c
($2);
1016 /* if "unless", invert the true-ness */
1017 istrue
= $1 ?
!istrue
: istrue
;
1019 set_instrf
(lexer
, "branch", "%I", $4);
1021 set_instr
(lexer
, "noop");
1023 | if_unless TK_IDENT then identifier
1024 { create_if_instr
(yyscanner
, lexer
, $1, 0, $2, $4); }
1025 | if_unless
"int" then identifier
1026 { create_if_instr
(yyscanner
, lexer
, $1, 0, "int", $4); }
1027 | if_unless
"num" then identifier
1028 { create_if_instr
(yyscanner
, lexer
, $1, 0, "num", $4); }
1029 | if_unless
"pmc" then identifier
1030 { create_if_instr
(yyscanner
, lexer
, $1, 0, "pmc", $4); }
1031 | if_unless
"string" then identifier
1032 { create_if_instr
(yyscanner
, lexer
, $1, 0, "string", $4); }
1033 | if_unless
"if" then identifier
1034 { create_if_instr
(yyscanner
, lexer
, $1, 0, "if", $4); }
1035 | if_unless
"unless" then identifier
1036 { create_if_instr
(yyscanner
, lexer
, $1, 0, "unless", $4); }
1037 | if_unless
"goto" "goto" identifier
1038 { create_if_instr
(yyscanner
, lexer
, $1, 0, "goto", $4); }
1039 | if_unless
"goto" ',' identifier
1040 { create_if_instr
(yyscanner
, lexer
, $1, 0, "goto", $4); }
1041 | if_unless
"null" "goto" identifier
1042 { create_if_instr
(yyscanner
, lexer
, $1, 0, "null", $4); }
1043 | if_unless
"null" ',' identifier
1044 { create_if_instr
(yyscanner
, lexer
, $1, 0, "null", $4); }
1045 | if_unless condition
"goto" identifier
1047 if
($2 == -1) { /* -1 means the condition is evaluated during runtime */
1048 if
($1) /* "unless"? if so, invert the instruction. */
1049 invert_instr
(lexer
);
1051 push_operand
(lexer
, expr_from_ident
($4));
1053 else
{ /* evaluation during compile time */
1054 /* if the result was false but the instr. was "unless", or,
1055 * if the result was true and the instr. was "if",
1056 * do an unconditional jump.
1058 if
( (($2 == 0) && $1) ||
(($2 == 1) && !$1) )
1059 set_instrf
(lexer
, "branch", "%I", $4);
1061 set_instr
(lexer
, "noop");
1067 /* the condition rule returns -1 if the condition can't be evaluated yet, so
1068 * it must be done during runtime. Otherwise, if the condition evaluates to
1069 * "false", 0 is returned, and if true, 1 is returned.
1071 condition
: target rel_op expression
1073 set_instrf
(lexer
, opnames
[$2], "%T%E", $1, $3);
1074 $$
= -1; /* -1 indicates this is evaluated at runtime */
1076 | TK_INTC rel_op target
1078 set_instrf
(lexer
, opnames
[$2], "%i%T", $1, $3);
1081 | TK_NUMC rel_op target
1083 set_instrf
(lexer
, opnames
[$2], "%n%T", $1, $3);
1086 | TK_STRINGC rel_op target
1088 set_instrf
(lexer
, opnames
[$2], "%s%T", $1, $3);
1091 | TK_INTC rel_op TK_INTC
1092 { $$
= evaluate_i_i
($1, $2, $3); }
1093 | TK_INTC rel_op TK_NUMC
1094 { $$
= evaluate_i_n
($1, $2, $3); }
1095 | TK_NUMC rel_op TK_INTC
1096 { $$
= evaluate_n_i
($1, $2, $3); }
1097 | TK_NUMC rel_op TK_NUMC
1098 { $$
= evaluate_n_n
($1, $2, $3); }
1099 | TK_STRINGC rel_op TK_STRINGC
1100 { $$
= evaluate_s_s
($1, $2, $3); }
1103 if_unless
: "if" { $$
= 0; /* no need to invert */ }
1104 |
"unless" { $$
= 1; /* yes, invert opname */ }
1107 then
: "goto" /* PIR mode */
1108 |
',' /* PASM mode*/
1111 goto_stat
: "goto" identifier
"\n"
1112 { set_instrf
(lexer
, "branch", "%I", $2); }
1115 local_decl
: ".local" type local_id_list
"\n"
1116 { declare_local
(lexer
, $2, $3); }
1119 local_id_list
: local_id
1121 | local_id_list
',' local_id
1122 { $$
= add_local
($1, $3); }
1125 local_id
: local_var_name has_unique_reg
1126 { $$
= new_local
($1, $2); }
1129 local_var_name
: identifier
1130 { /* try to find symbol for this id; if found, it was already declared */
1131 symbol
*sym
= find_symbol
(lexer
, $1);
1133 yyerror(yyscanner
, lexer
, "symbol '%s' is already declared", $1);
1138 has_unique_reg
: /* empty */ { $$
= 0; }
1139 |
":unique_reg" { $$
= 1; }
1142 lex_decl
: ".lex" TK_STRINGC
',' pmc_object
"\n"
1143 { /* if $4 is not a register, it must be a declared symbol */
1144 if
(!TEST_FLAG
($4->flags
, TARGET_FLAG_IS_REG
)) {
1145 symbol
*sym
= find_symbol
(lexer
, target_name
($4));
1147 if
(sym
== NULL
) /* check declaration */
1148 yyerror(yyscanner
, lexer
, "lexical '%s' is not declared",
1150 else if
(sym
->type
!= PMC_TYPE
) /* a .lex must be a PMC */
1151 yyerror(yyscanner
, lexer
, "lexical '%s' must be of type 'pmc'",
1154 set_lex_flag
($4, $2);
1158 /* Sub/method invocation */
1161 invocation_stat
: invocation
1162 { convert_inv_to_instr
(lexer
, $1); }
1165 invocation
: long_invocation_stat
1166 | short_invocation_stat
1169 long_invocation_stat
: ".begin_call" "\n"
1171 long_invocation
"\n"
1174 { /* $4 contains an invocation object */
1175 set_invocation_args
($4, $3);
1176 set_invocation_results
($4, $6);
1181 opt_long_arguments
: /* empty */
1187 long_arguments
: long_argument
1189 | long_arguments long_argument
1190 { $$
= add_arg
($1, $2); }
1193 long_argument
: ".set_arg" short_arg
"\n"
1197 long_invocation
: ".call" pmc_object opt_ret_cont
1198 { $$
= invoke
(lexer
, CALL_PCC
, $2, $3); }
1199 |
".nci_call" pmc_object
1200 { $$
= invoke
(lexer
, CALL_NCI
, $2); }
1201 |
".invocant" pmc_object
"\n"
1203 { $$
= invoke
(lexer
, CALL_METHOD
, $2, $5); }
1206 opt_ret_cont
: /* empty */
1212 opt_long_results
: /* empty */
1218 long_results
: long_result
1220 | long_results long_result
1221 { $$
= add_target
(lexer
, $1, $2); }
1224 long_result
: ".get_result" result_target
"\n"
1230 short_invocation_stat: short_invocation
"\n"
1234 short_invocation
: opt_target_list
'=' simple_invocation
1235 { set_invocation_results
($3, $1);
1238 | target
'=' simple_invocation
1239 { set_invocation_results
($3, $1);
1243 { set_invocation_results
($1, NULL
);
1248 simple_invocation
: subcall
1252 methodcall
: pmc_object
'.' method arguments
1254 /* if $1 is not a register, check whether the symbol was declared */
1255 if
(!TEST_FLAG
($1->flags
, TARGET_FLAG_IS_REG
)) {
1256 symbol
*sym
= find_symbol
(lexer
, target_name
($1));
1258 yyerror(yyscanner
, lexer
, "object '%s' not declared",
1261 else if
(sym
->type
!= PMC_TYPE
)
1262 yyerror(yyscanner
, lexer
,
1263 "cannot invoke method: '%s' is not of type 'pmc'",
1267 $$
= invoke
(lexer
, CALL_METHOD
, $1, $3);
1268 set_invocation_args
($$
, $4);
1272 subcall
: sub arguments
1274 $$
= invoke
(lexer
, CALL_PCC
, $1, NULL
);
1275 set_invocation_args
($$
, $2);
1282 { $$
= target_from_string
($1); }
1286 { /* check that this identifier was declared */
1287 symbol
*sym
= find_symbol
(lexer
, $1);
1290 yyerror(yyscanner
, lexer
,
1291 "method identifier '%s' not declared", $1);
1292 /* make sure sym is not NULL */
1293 sym
= new_symbol
($1, PMC_TYPE
);
1295 else if
(sym
->type
!= PMC_TYPE
&& sym
->type
!= STRING_TYPE
)
1296 yyerror(yyscanner
, lexer
,
1297 "method '%s' must be of type 'pmc' or 'string'", $1);
1299 $$
= target_from_symbol
(sym
);
1302 { $$
= new_reg
(lexer
, PMC_TYPE
, $1); }
1304 { $$
= new_reg
(lexer
, STRING_TYPE
, $1); }
1306 { $$
= target_from_string
($1); }
1309 pmc_object
: identifier
1310 { $$
= target_from_ident
(PMC_TYPE
, $1); }
1312 { $$
= new_reg
(lexer
, PMC_TYPE
, $1); }
1316 opt_target_list
: '(' opt_list
')'
1320 opt_list
: /* empty */
1326 target_list
: result_target
1328 | target_list
',' result_target
1329 { $$
= add_target
(lexer
, $1, $3); }
1332 result_target
: target target_flags
1333 { $$
= set_param_flag
(lexer
, $1, $2); }
1336 target_flags
: /* empty */
1338 | target_flags target_flag
1339 { SET_FLAG
($$
, $2); }
1342 target_flag
: ":optional"
1343 { $$
= TARGET_FLAG_OPTIONAL
; }
1345 { $$
= TARGET_FLAG_OPT_FLAG
; }
1347 { $$
= TARGET_FLAG_SLURPY
; }
1348 |
":named" opt_paren_string
1350 $$
= TARGET_FLAG_NAMED
;
1351 set_param_alias
(lexer
, $2);
1355 /* Returning and Yielding */
1358 return_stat
: return_instr
1359 { convert_inv_to_instr
(lexer
, $1); }
1362 return_instr
: short_return_stat
1368 short_return_stat
: ".return" arguments
"\n"
1370 $$
= invoke
(lexer
, CALL_RETURN
);
1371 set_invocation_args
($$
, $2);
1373 |
".tailcall" simple_invocation
"\n"
1374 { /* was the invocation a method call? then it becomes a method tail
1375 * call, otherwise it's just a normal (sub) tail call.
1377 set_invocation_type
($2, ($2->type
== CALL_METHOD
)
1378 ? CALL_METHOD_TAILCALL
1384 short_yield_stat
: ".yield" arguments
"\n"
1386 $$
= invoke
(lexer
, CALL_YIELD
);
1387 set_invocation_args
($$
, $2);
1391 arguments
: '(' opt_arguments_list
')'
1395 opt_arguments_list
: /* empty */
1401 arguments_list
: argument
1403 | arguments_list
',' argument
1404 { $$
= add_arg
($1, $3); }
1407 argument
: short_arg
1411 named_arg
: TK_STRINGC
"=>" arg
1412 { $$
= set_arg_alias
(lexer
, $1); }
1415 short_arg
: arg arg_flags
1416 { $$
= set_arg_flag
($$
, $2); }
1420 { $$
= set_curarg
(lexer
, new_argument
($1)); }
1423 long_return_stat
: ".begin_return" "\n"
1424 opt_return_expressions
1427 $$
= invoke
(lexer
, CALL_RETURN
);
1428 set_invocation_args
($$
, $3);
1432 long_yield_stat
: ".begin_yield" "\n"
1433 opt_yield_expressions
1436 $$
= invoke
(lexer
, CALL_YIELD
);
1437 set_invocation_args
($$
, $3);
1441 opt_yield_expressions
: /* empty */
1448 yield_expressions
: yield_expression
1450 | yield_expressions yield_expression
1451 { $$
= add_arg
($1, $2); }
1455 yield_expression
: ".set_yield" short_arg
"\n"
1459 opt_return_expressions: /* empty */
1461 | return_expressions
1465 return_expressions
: return_expression
1467 | return_expressions return_expression
1468 { $$
= add_arg
($1, $2); }
1471 return_expression
: ".set_return" short_arg
"\n"
1476 arg_flags
: /* empty */
1478 | arg_flags arg_flag
1479 { SET_FLAG
($$
, $2); }
1483 { $$
= ARG_FLAG_FLAT
; }
1484 |
":named" opt_paren_string
1486 $$
= ARG_FLAG_NAMED
;
1487 set_arg_alias
(lexer
, $2);
1491 opt_paren_string
: /* empty */
1497 paren_string
: '(' TK_STRINGC
')'
1501 const_decl_stat
: const_stat
"\n"
1504 const_stat
: const_decl
1508 const_decl
: ".const" const_tail
1509 { store_global_const
(lexer
, $2); }
1512 globalconst_decl
: ".globalconst" const_tail
1513 { /* XXX is .globalconst to be kept? */ }
1516 const_tail
: "int" identifier
'=' TK_INTC
1517 { $$
= new_named_const
(INT_TYPE
, $2, $4); }
1518 |
"num" identifier
'=' TK_NUMC
1519 { $$
= new_named_const
(NUM_TYPE
, $2, $4); }
1520 |
"string" identifier
'=' TK_STRINGC
1521 { $$
= new_named_const
(STRING_TYPE
, $2, $4); }
1522 |
"pmc" identifier
'=' TK_STRINGC
1523 { $$
= new_named_const
(PMC_TYPE
, $2, $4); }
1525 | "Sub" identifier '=' TK_STRINGC
1526 | "Coroutine" identifier '=' TK_STRINGC
1529 /* this might be useful, for:
1530 .const "Sub" foo = "foo" # make a Sub PMC of subr. "foo"
1531 .const "Float" PI = 3.14 # make a Float PMC for 3.14
1533 Is: .const pmc x = 'foo' any useful? Type of x is not clear.
1535 | TK_STRINGC identifier '=' constant
1536 { $$ = new_pmc_const($1, $2, $4); }
1542 /* Expressions, variables and operators */
1544 expression
: target
{ $$
= expr_from_target
($1); }
1545 | constant
{ $$
= expr_from_const
($1); }
1549 constant
: TK_STRINGC
{ $$
= new_const
(STRING_TYPE
, $1); }
1550 | TK_INTC
{ $$
= new_const
(INT_TYPE
, $1); }
1551 | TK_NUMC
{ $$
= new_const
(NUM_TYPE
, $1); }
1554 rel_op
: "!=" { $$
= OP_NE
; }
1555 |
"==" { $$
= OP_EQ
; }
1556 |
"<" { $$
= OP_LT
; }
1557 |
"<=" { $$
= OP_LE
; }
1558 |
">=" { $$
= OP_GE
; }
1559 |
">" { $$
= OP_GT
; }
1562 type
: "int" { $$
= INT_TYPE
; }
1563 |
"num" { $$
= NUM_TYPE
; }
1564 |
"pmc" { $$
= PMC_TYPE
; }
1565 |
"string" { $$
= STRING_TYPE
; }
1568 /* helper rule to set the symbol's target node as the "current"; this is needed for
1569 * setting flags etc. Instead of duplicating this code for each register type and
1570 * also for symbols, use this extra rule to do it once.
1573 target
: symbol
{ set_curtarget
(lexer
, $1); }
1576 symbol
: TK_PREG
{ $$
= new_reg
(lexer
, PMC_TYPE
, $1); }
1577 | TK_NREG
{ $$
= new_reg
(lexer
, NUM_TYPE
, $1); }
1578 | TK_IREG
{ $$
= new_reg
(lexer
, INT_TYPE
, $1); }
1579 | TK_SREG
{ $$
= new_reg
(lexer
, STRING_TYPE
, $1); }
1580 | identifier
{ /* a symbol must have been declared; check that at this point. */
1581 symbol
*sym
= find_symbol
(lexer
, $1);
1583 yyerror(yyscanner
, lexer
, "symbol '%s' not declared", $1);
1585 /* make sure sym is not NULL */
1586 sym
= new_symbol
($1, UNKNOWN_TYPE
);
1588 $$
= target_from_symbol
(sym
);
1593 /* an identifier can be any sequence of characters or one of the keywords */
1594 identifier
: TK_IDENT
1598 keyword
: "if" { $$
= dupstr
(lexer
, "if"); }
1599 |
"unless" { $$
= dupstr
(lexer
, "unless"); }
1600 |
"goto" { $$
= dupstr
(lexer
, "goto"); }
1601 |
"int" { $$
= dupstr
(lexer
, "int"); }
1602 |
"num" { $$
= dupstr
(lexer
, "num"); }
1603 |
"string" { $$
= dupstr
(lexer
, "string"); }
1604 |
"pmc" { $$
= dupstr
(lexer
, "pmc"); }
1605 |
"null" { $$
= dupstr
(lexer
, "null"); }
1608 unop
: '-' { $$
= "neg"; }
1609 |
'!' { $$
= "not"; }
1610 |
'~' { $$
= "bnot"; }
1613 binop
: '+' { $$
= OP_ADD
; }
1614 |
'-' { $$
= OP_SUB
; }
1615 |
'/' { $$
= OP_DIV
; }
1616 |
'*' { $$
= OP_MUL
; }
1617 |
'%' { $$
= OP_MOD
; }
1618 |
'|' { $$
= OP_BOR
; }
1619 |
'&' { $$
= OP_BAND
; }
1620 |
'~' { $$
= OP_BXOR
; }
1621 |
"**" { $$
= OP_POW
; }
1622 |
"." { $$
= OP_CONCAT
; }
1623 |
">>>" { $$
= OP_LSR
; }
1624 |
">>" { $$
= OP_SHR
; }
1625 |
"<<" { $$
= OP_SHL
; }
1626 |
"||" { $$
= OP_OR
; }
1627 |
"&&" { $$
= OP_AND
; }
1628 |
"//" { $$
= OP_FDIV
; }
1629 |
"~~" { $$
= OP_XOR
; }
1630 |
"==" { $$
= OP_ISEQ
; }
1631 |
"<=" { $$
= OP_ISLE
; }
1632 |
"<" { $$
= OP_ISLT
; }
1633 |
">=" { $$
= OP_ISGE
; }
1634 |
">" { $$
= OP_ISGT
; }
1635 |
"!=" { $$
= OP_ISNE
; }
1638 /* note that += and -= are separated, because when adding/subtracting 1,
1639 * this is optimized by using the "inc"/"dec" instructions.
1641 augmented_op: "*=" { $$
= OP_MUL
; }
1642 |
"%=" { $$
= OP_MOD
; }
1643 |
"**=" { $$
= OP_POW
; }
1644 |
"/=" { $$
= OP_DIV
; }
1645 |
"//=" { $$
= OP_FDIV
; }
1646 |
"|=" { $$
= OP_BOR
; }
1647 |
"&=" { $$
= OP_BAND
; }
1648 |
"~=" { $$
= OP_BXOR
; }
1649 |
".=" { $$
= OP_CONCAT
; }
1650 |
">>=" { $$
= OP_SHR
; }
1651 |
"<<=" { $$
= OP_SHL
; }
1652 |
">>>=" { $$
= OP_LSR
; }
1666 =item C<static constant *
1667 fold_i_i(yyscan_t yyscanner, int a, pir_math_operator op, int b)>
1669 Evaluates the expression C<a op b> and returns a constant node
1670 containing the result value. Both C<a> and C<b> are integer values.
1676 fold_i_i
(yyscan_t yyscanner
, int a
, pir_math_operator op
, int b
) {
1688 yyerror(yyscanner
, yyget_extra
(yyscanner
), "cannot divide by 0!");
1711 yyerror(yyscanner
, yyget_extra
(yyscanner
),
1712 "cannot concatenate operands of type 'int' and 'int'");
1715 /* from bits.ops: $1 = (INTVAL)((UINTVAL)$2 >> $3); */
1716 result
= (int)((unsigned)a
>> b
);
1731 /* 7 // 2 -> 3, this is what integer division does (rounding down to whole integers) */
1756 /* OP_INC and OP_DEC are here only to keep the C compiler happy */
1759 panic
("detected 'inc' or 'dec' in fold_i_i()");
1762 return new_const
(INT_TYPE
, result
);
1767 =item C<static constant *
1768 fold_n_i(yyscan_t yyscanner, double a, pir_math_operator op, int b)>
1770 Same as C<fold_i_i>, except C<a> is of type double.
1776 fold_n_i
(yyscan_t yyscanner
, double a
, pir_math_operator op
, int b
) {
1787 yyerror(yyscanner
, yyget_extra
(yyscanner
), "cannot divide by 0!");
1803 yyerror(yyscanner
, yyget_extra
(yyscanner
),
1804 "cannot apply binary operator '%s' to types 'num' and 'int'", opnames
[op
]);
1816 result
= floor
(a
/ b
);
1837 /* OP_INC and OP_DEC are here only to keep the C compiler happy */
1840 panic
("detected 'inc' or 'dec' in fold_n_i()");
1843 return new_const
(NUM_TYPE
, result
);
1848 =item C<static constant *
1849 fold_i_n(yyscan_t yyscanner, int a, pir_math_operator op, double b)>
1851 Same as C<fold_i_i>, except C<b> is of type double.
1857 fold_i_n
(yyscan_t yyscanner
, int a
, pir_math_operator op
, double b
) {
1869 yyerror(yyscanner
, yyget_extra
(yyscanner
), "cannot divide by 0!");
1885 yyerror(yyscanner
, yyget_extra
(yyscanner
),
1886 "cannot apply binary operator '%s' to types 'int' and 'num'", opnames
[op
]);
1898 result
= floor
(a
/ b
);
1919 /* OP_INC and OP_DEC are here only to keep the C compiler happy */
1922 panic
("detected 'inc' or 'dec' in fold_i_n()");
1925 return new_const
(NUM_TYPE
, result
);
1930 =item C<static constant *
1931 fold_n_n(yyscan_t yyscanner, double a, pir_math_operator op, double b)>
1933 Same as C<fold_i_i>, except that both C<a> and C<b> are of type double.
1939 fold_n_n
(yyscan_t yyscanner
, double a
, pir_math_operator op
, double b
) {
1949 if
(b
== 0) /* throw exception ? */
1950 yyerror(yyscanner
, yyget_extra
(yyscanner
), "cannot divide by 0");
1969 yyerror(yyscanner
, yyget_extra
(yyscanner
),
1970 "cannot apply binary operator '%s' to arguments of type number", opnames
[op
]);
1980 yyerror(yyscanner
, yyget_extra
(yyscanner
), "cannot divide by 0");
1982 result
= floor
(a
/ b
);
2003 /* OP_INC and OP_DEC are here only to keep the C compiler happy */
2008 return new_const
(NUM_TYPE
, result
);
2013 =item C<static constant *
2014 fold_s_s(yyscan_t yyscanner, char *a, pir_math_operator op, char *b)>
2016 Evaluate the expression C<a op b>, where both C<a> and C<b> are
2017 strings. Only the concatenation and comparison operators are implemented;
2018 other operators will result in an error.
2024 fold_s_s
(yyscan_t yyscanner
, char *a
, pir_math_operator op
, char *b
) {
2027 return new_const
(STRING_TYPE
, concat_strings
(a
, b
));
2045 yyerror(yyscanner
, yyget_extra
(yyscanner
),
2046 "cannot apply binary operator '%s' to arguments of type number", opnames
[op
]);
2047 return new_const
(STRING_TYPE
, a
);
2055 return new_const
(INT_TYPE
, (1 == evaluate_s_s
(a
, op
, b
)));
2058 /* OP_INC and OP_DEC are here only to keep the C compiler happy */
2061 panic
("detected 'inc' or 'dec' in fold_s_s()");
2070 evaluate_i_i(int a, pir_rel_operator op, double b)>
2072 Compare C<a> with C<b> according to the relational operator C<op>.
2073 Wrapper for C<evaluate_n_n>, which takes arguments of type double.
2079 evaluate_i_i
(int a
, pir_rel_operator op
, int b
) {
2080 return evaluate_n_n
(a
, op
, b
);
2086 evaluate_n_i(int a, pir_rel_operator op, double b)>
2088 Compare C<a> with C<b> according to the relational operator C<op>.
2089 Wrapper for C<evaluate_n_n>, which takes arguments of type double.
2095 evaluate_n_i
(double a
, pir_rel_operator op
, int b
) {
2096 return evaluate_n_n
(a
, op
, b
);
2102 evaluate_i_n(int a, pir_rel_operator op, double b)>
2104 Compare C<a> with C<b> according to the relational operator C<op>.
2105 Wrapper for C<evaluate_n_n>, which takes arguments of type double.
2111 evaluate_i_n
(int a
, pir_rel_operator op
, double b
) {
2112 return evaluate_n_n
(a
, op
, b
);
2118 evaluate_n_n(double a, pir_rel_operator op, double b)>
2120 Compare C<a> with C<b> according to the relational operator C<op>.
2121 C<op> can be C<<!=>>, C<<==>>, C<< < >>, C<< <= >>, C<< > >> or C<< >= >>.
2127 evaluate_n_n
(double a
, pir_rel_operator op
, double b
) {
2149 evaluate_s_s(char *a, pir_rel_operator op, char *b)>
2151 Compare string C<a> with string C<b> using the operator C<op>.
2152 The function uses C's C<strcmp> function. Based on that result,
2153 which can be -1 (smaller), 0 (equal) or 1 (larger), a boolean
2160 evaluate_s_s
(char * const a
, pir_rel_operator op
, char * const b
) {
2161 int result
= strcmp
(a
, b
);
2165 return
(result
!= 0);
2167 return
(result
== 0);
2169 return
(result
< 0);
2171 return
(result
<= 0);
2173 return
(result
> 0);
2175 return
(result
>= 0);
2184 evaluate_s(char * const s)>
2186 Evaluate a string in boolean context; if the string's length is 0, it's false.
2187 If the string equals "0", ".0", "0." or "0.0", it's false.
2188 Otherwise, it's true.
2194 evaluate_s
(char * const s
) {
2195 int strlen_s
= strlen
(s
);
2198 if
(strlen_s
<= 3) { /* if strlen > 3, (max. nr of characters to represent "0")
2199 no need to do expensive string comparison; it must be true. */
2200 if
((strcmp
(s
, "0") == 0) ||
(strcmp
(s
, ".0") == 0)
2201 ||
(strcmp
(s
, "0.") == 0) ||
(strcmp
(s
, "0.0") == 0)) {
2204 else
/* short string but not equal to "0.0" or a variant */
2207 else
/* strlen > 3, so does not contain "0.0" or a variant */
2210 return
0; /* strlen is not larger than 0 */
2216 evaluate_c(constant * const c)>
2218 Evaluate a constant node in boolean context; if the constant is numeric,
2219 it must be non-zero to be true; if it's a string, C<evaluate_s> is invoked
2220 to evaluate the string.
2226 evaluate_c
(constant
* const c
) {
2229 return
(c
->val.ival
!= 0);
2231 return
(c
->val.nval
!= 0);
2233 return evaluate_s
(c
->val.sval
);
2236 panic
("impossible constant type in evaluate_c()");
2239 return
0; /* keep compiler happy; will never happen. */
2244 =item C<static char *
2245 concat_strings(char *a, char *b)>
2247 Concatenates two strings into a new buffer; frees all memory
2248 of the old strings. The new string is returned.
2254 concat_strings
(char *a
, char *b
) {
2255 int strlen_a
= strlen
(a
);
2256 char *newstr
= (char *)calloc
(strlen_a
+ strlen
(b
) + 1, sizeof
(char));
2257 assert
(newstr
!= NULL
);
2259 strcpy
(newstr
+ strlen_a
, b
);
2269 is_parrot_op(lexer_state * const lexer, char const * const spelling)>
2276 is_parrot_op(lexer_state * const lexer, char const * const spelling)
2278 char const * ops[] = {
2295 char const **iter = ops;
2297 while (*iter != NULL) {
2298 if (strcmp(spelling, *iter) == 0)
2310 create_if_instr(yyscan_t yyscanner, lexer_state *lexer, int invert, int hasnull,
2311 char * const name, char * const label)>
2313 Create an C<if> or C<unless> instruction; if C<invert> is non-zero (true), the
2314 C<if> instruction is inverted, effectively becoming C<unless>.
2316 If C<hasnull> is non-zero (true), the C<if> instruction becomes C<if_null>; again,
2317 if C<invert> is non-zero, the instruction becomes C<unless_null>.
2319 C<name> is the name of the variable that is checked during this instruction
2325 create_if_instr
(yyscan_t yyscanner
, lexer_state
* const lexer
, int invert
, int hasnull
,
2329 /* try to find the symbol; if it was declared it will be found; otherwise emit an error. */
2330 symbol
*sym
= find_symbol
(lexer
, name
);
2332 sym
= new_symbol
(name
, UNKNOWN_TYPE
);
2333 yyerror(yyscanner
, lexer
, "symbol '%s' not declared'", name
);
2335 /* if there was a keyword "null", use the if/unless_null instruction variants. */
2337 set_instrf
(lexer
, invert ?
"unless_null" : "if_null", "%T%I", target_from_symbol
(sym
),
2340 set_instrf
(lexer
, invert ?
"unless" : "if", "%T%I", target_from_symbol
(sym
), label
);
2346 check_value(constant * const c, int val)>
2348 Check whether the current value of the constant C<c> equals C<val>.
2349 For our purposes, it is sufficient to check for integer values (including
2350 a check against 1.0 or 0.0). If the values are indeed equal, true is returned,
2351 false otherwise. If the constant is not numeric, it returns always false.
2357 check_value
(constant
* const c
, int val
) {
2360 return
(c
->val.ival
== val
);
2362 return
(c
->val.nval
== val
);
2372 do_strength_reduction(lexer_state * const lexer)>
2374 Implement strength reduction for the math operators C<add>, C<sub>, C<mul>, C<div> and C<fdiv>.
2375 If the current instruction is any of these, then the first two operands are checked; if both
2376 are targets and are equal, the second operand is removed; this means that the first operand
2377 will be an IN/OUT operand. For instance:
2397 do_strength_reduction
(lexer_state
* const lexer
) {
2398 char * const instr
= get_instr
(lexer
);
2401 expression
*arg1
, *arg2
;
2403 /* if the instruction is "add", "sub", "mul", "div" or "fdiv", do continue... */
2404 if
(strcmp
(instr
, "add") == 0)
2406 else if
(strcmp
(instr
, "sub") == 0)
2408 else if
(strcmp
(instr
, "mul") == 0)
2410 else if
(strcmp
(instr
, "div") == 0)
2412 else if
(strcmp
(instr
, "fdiv") == 0)
2417 num_operands
= get_operand_count
(lexer
);
2418 if
(num_operands
> 2) {
2419 /* get the operands */
2420 expression
*op1
, *op2
;
2421 get_operands
(lexer
, 2, &op1
, &op2
);
2423 /* check whether operands are in fact targets */
2424 if
((op1
->type
== EXPR_TARGET
) && (op2
->type
== EXPR_TARGET
)) {
2426 /* check whether targets are equal */
2427 if
(targets_equal
(op1
->expr.t
, op2
->expr.t
)) {
2428 /* in that case, remove the second one */
2429 remove_operand
(lexer
, 2);
2436 /* don't even try to change "add $I0, 1" into "inc $I0" if number of operands is not 2 */
2437 if
(num_operands
!= 2)
2441 get_operands
(lexer
, 2, &arg1
, &arg2
);
2448 if
(arg2
->type
== EXPR_CONSTANT
) {
2449 if
(check_value
(arg2
->expr.c
, 0)) {
2450 update_instr
(lexer
, "noop");
2451 remove_all_operands
(lexer
);
2453 else if
(check_value
(arg2
->expr.c
, 1)) {
2454 update_instr
(lexer
, opnames
[op
+ 1]);
2455 remove_operand
(lexer
, 2);
2460 if
(arg2
->type
== EXPR_CONSTANT
) {
2461 if
(check_value
(arg2
->expr.c
, 0)) {
2462 update_instr
(lexer
, "null");
2463 remove_operand
(lexer
, 2);
2465 else if
(check_value
(arg2
->expr.c
, 1)) {
2466 update_instr
(lexer
, "noop");
2467 remove_all_operands
(lexer
);
2473 if
(arg2
->type
== EXPR_CONSTANT
) {
2474 if
(check_value
(arg2
->expr.c
, 0))
2475 pirerror
(lexer
, "cannot divide by 0");
2476 else if
(check_value
(arg2
->expr.c
, 1)) {
2477 update_instr
(lexer
, "noop");
2478 remove_all_operands
(lexer
);
2500 * c-file-style: "parrot"
2502 * vim: expandtab shiftwidth=4: