break/continue to outer loops, !!booleanize
[nedit-bw.git] / ternary-operator-GNU.patch
blobb1fe3ad895df822cad5f765e3f88afd9f46f3fba
1 ---
3 source/interpret.c | 30 ++++++++++++++++++++++++++++++
4 source/ops.h | 1 +
5 source/parse.y | 38 ++++++++++++++++++++++++++++++++++++--
6 3 files changed, 67 insertions(+), 2 deletions(-)
8 diff --quilt old/source/parse.y new/source/parse.y
9 --- old/source/parse.y
10 +++ new/source/parse.y
11 @@ -102,6 +102,7 @@ static int follow2(char expect1, int yes
12 static int follow_non_whitespace(char expect, int yes, int no);
13 static int eq_look_ahead(void);
14 static int comma_look_ahead(void);
15 +static int te_look_ahead(void);
16 static Symbol *matchesActionRoutine(char **inPtr);
17 static int scanString(void);
19 @@ -137,7 +138,7 @@ static int nextSymIsField = 0;
20 %type <num> lvlist
21 %type <inst> lventry
22 %token ARGSEP
23 -%type <inst> thenx elsex
24 +%type <inst> thenx elsex thenelsex
26 %nonassoc IF_NO_ELSE
27 %nonassoc ELSE
28 @@ -145,7 +146,7 @@ static int nextSymIsField = 0;
29 %nonassoc ';'
30 %nonassoc SYMBOL ARG_LOOKUP
31 %right '=' ADDEQ SUBEQ MULEQ DIVEQ MODEQ ANDEQ OREQ
32 -%right '?' ':'
33 +%right '?' ':' TE
34 %left CONCAT
35 %left OR
36 %left AND
37 @@ -686,6 +687,9 @@ numexpr: '(' blank expr blank ')'
38 SET_BR_OFF($2, $5 + 1); /* thenx limb ends at $5+1 */
39 SET_BR_OFF($5, GetPC()); /* elsex limb ends here */
41 + | numexpr thenelsex blank numexpr %prec '?' {
42 + SET_BR_OFF($2, GetPC());
43 + }
44 | incrdecr blank SYMBOL %prec INCR {
45 ADD_OP(OP_PUSH_SYM); ADD_SYM($3); ADD_OP($1);
46 ADD_OP(OP_DUP); ADD_OP(OP_ASSIGN); ADD_SYM($3);
47 @@ -748,13 +752,24 @@ or: OR {
50 thenx: '?' {
51 + ADD_OP(OP_BOOLEANIZE);
52 ADD_OP(OP_BRANCH_FALSE); $$ = GetPC();
53 ADD_BR_OFF(0);
55 + ;
56 elsex: ':' {
57 ADD_OP(OP_BRANCH); $$ = GetPC();
58 ADD_BR_OFF(0);
60 + ;
61 +thenelsex: TE {
62 + ADD_OP(OP_DUP);
63 + ADD_OP(OP_BOOLEANIZE);
64 + ADD_OP(OP_BRANCH_TRUE); $$ = GetPC();
65 + ADD_BR_OFF(0);
66 + ADD_OP(OP_POP);
67 + }
68 + ;
70 dot: '.' %prec '.' {
71 nextSymIsField = 1;
72 @@ -946,6 +961,7 @@ static int yylex(void)
73 return result; /* but return what we started with */
75 case ',': return comma_look_ahead();
76 + case '?': return te_look_ahead();
77 default: return *(InPtr-1);
80 @@ -1047,6 +1063,24 @@ static int comma_look_ahead(void)
81 return ',';
84 +/* look ahead fo ternary operator without second operand, ie ?: */
85 +static int te_look_ahead(void)
87 + char *savedInPtr = InPtr;
89 + /* skip any whitespace */
90 + skipWhitespace();
92 + if (*InPtr == ':') {
93 + /* eat this */
94 + InPtr++;
95 + return TE;
96 + }
98 + InPtr = savedInPtr;
99 + return '?';
103 ** Look (way) ahead for hyphenated routine names which begin at inPtr. A
104 ** hyphenated name is allowed if it is pre-defined in the global symbol
105 diff --quilt old/source/interpret.c new/source/interpret.c
106 --- old/source/interpret.c
107 +++ new/source/interpret.c
108 @@ -2466,6 +2466,36 @@ static int power(void)
109 return errCheck("exponentiation");
112 +static int booleanize(void)
114 + DataValue dv;
115 + int res;
117 + DISASM_RT();
118 + STACKDUMP(1, 3);
120 + POP(dv);
122 + switch (dv.tag) {
123 + case INT_TAG: res = !!dv.val.n; break;
124 + case STRING_TAG:
125 + if (StringToNum(dv.val.str.rep, &res)) {
126 + res = !!res;
128 + else {
129 + res = !!dv.val.str.len;
131 + break;
132 + case ARRAY_TAG: res = !!ArraySize(&dv); break;
133 + default: EXEC_ERROR("incompatible type in booleanize context: <%s>",
134 + tagToStr(dv.tag));
137 + PUSH_INT(res);
139 + return STAT_OK;
143 ** A helper routine used in concat(), and makeArrayKeyFromArgs(). Concatenate a
144 ** number of values from the stack and return the result as a character pointer
145 diff --quilt old/source/ops.h new/source/ops.h
146 --- old/source/ops.h
147 +++ new/source/ops.h
148 @@ -30,6 +30,7 @@ OP(BIT_OR, bitOr)
149 OP(AND, and) /* pop(v2,v1), push(v1 && v2) */
150 OP(OR, or) /* pop(v2,v1), push(v1 || v2) */
151 OP(NOT, not) /* pop(v), push(!v) */
152 +OP(BOOLEANIZE, booleanize) /* pop(v), push(!!v) */
153 OP(POWER, power) /* pop(v2,v1), push(v1 ** v2) */
154 OP(CONCAT, concat) /* pop(s2,s1), push(s1 s2) */
155 OP(ASSIGN, assign) /* sym */ /* pop(v), sym.v = v */