/* Copyright (c) 1979 Regents of the University of California */
* pi - Pascal interpreter code translator
* Charles Haley, Bill Joy UCB
* Version 1.2 January 1979
for (sl
=r
; sl
!= NIL
; sl
=sl
[2])
register struct nl
*snlp
;
error("Unreachable statement");
* Free the temporary name list entries defined in
* expressions, e.g. STRs, and WITHPTRs from withs.
for (p
= gotos
[cbn
]; p
!= NIL
; p
= p
->chain
)
if ((p
->nl_flags
& NFORWD
) != 0) {
if (p
->value
[NL_GOLEV
] != NOTYET
)
if (p
->value
[NL_GOLEV
] > level
)
p
->value
[NL_GOLEV
] = level
;
if (p
->value
[NL_GOLEV
] != DEAD
)
if (p
->value
[NL_GOLEV
] > level
)
p
->value
[NL_GOLEV
] = DEAD
;
* With statement requires an extra word
* in automatic storage for each level of withing.
* These indirect pointers are initialized here, and
* the scoping effect of the with statement occurs
* because lookup examines the field names of the records
* associated with the WITHPTRs on the withlist.
soffset
= sizes
[cbn
].om_off
;
for (p
= s
[2]; p
!= NIL
; p
= p
[2]) {
put2(O_LV
| cbn
<<9, i
= sizes
[cbn
].om_off
);
if (r
->class != RECORD
) {
error("Variable in with statement refers to %s, not to a record", nameof(r
));
r
= defnl(0, WITHPTR
, r
, i
);
if (sizes
[cbn
].om_off
< sizes
[cbn
].om_max
)
sizes
[cbn
].om_max
= sizes
[cbn
].om_off
;
sizes
[cbn
].om_off
= soffset
;
* Asgnop's only function is
* to handle function variable
* assignments. All other assignment
* stuff is handled by asgnop1.
if (av
!= NIL
&& av
[0] == T_VAR
&& av
[3] == NIL
) {
if (p
!= NIL
&& p
->class == FVAR
) {
p
->nl_flags
=| NUSED
|NMOD
;
put2(O_LV
| bn
<< 9, p
->value
[NL_OFFS
]);
if (isa(p
->type
, "i") && width(p
->type
) == 1)
* Asgnop1 handles all assignments.
* If p is not nil then we are assigning
* to a function variable, otherwise
* we look the variable up ourselves.
p
= lvalue(r
[2], MOD
|ASGN
|NOUSE
);
if (incompat(p1
, p
, r
[3])) {
cerror("Type of expression clashed with type of variable in assignment");
gen(O_AS2
, O_AS2
, width(p
), width(p1
));
return (p
); /* Used by for statement */
* for var := expr [down]to expr do stat
register struct nl
*t1
, *t2
;
int limitrv
= (hp21mx
? O_RV2
: O_RV4
) | cbn
<< 9;
int limitsz
= (hp21mx
? 2 : 4);
* space for limit variable
sizes
[cbn
].om_off
=- limitsz
;
if (sizes
[cbn
].om_off
< sizes
[cbn
].om_max
)
sizes
[cbn
].om_max
= sizes
[cbn
].om_off
;
* Initialize the limit variable
put1(width(t2
) <= 2 ? O_AS24
: O_AS4
);
put1(width(t2
) <= 2 ? O_AS24
: O_AS4
);
* Assignment of initial value to for variable
rr
= r
[2]; /* Assignment */
rr
= rr
[2]; /* Lhs variable */
error("For variable must be unqualified");
error("For variables cannot be %ss", nameof(t1
));
if (incompat(t2
, t1
, r
[3])) {
cerror("Limit type clashed with index type in 'for' statement");
* See if we can skip the loop altogether
gen(NIL
, r
[0] == T_FORU
? T_LE
: T_GE
, width(t1
), 4);
gen(NIL
, r
[0] == T_FORU
? T_LE
: T_GE
, width(t1
), limitsz
);
* L1 will be patched to skip the body of the loop.
* L2 marks the top of the loop when we go around.
put2(O_IF
, (l1
= getlab()));
* now we see if we get to go again
* Easy if we dont have to test
put2((r
[0] == T_FORU
? O_FOR1U
: O_FOR1D
) + (width(t1
) >> 1), l2
);
put2(O_RV4
| cbn
<< 9, i
);
gen(NIL
, (r
[0] == T_FORU
? T_LT
: T_GT
), width(t1
), 4);
gen(NIL
, (r
[0] == T_FORU
? T_LT
: T_GT
), width(t1
), limitsz
);
l3
= put2(O_IF
, getlab());
t2
= gen(NIL
, r
[0] == T_FORU
? T_ADD
: T_SUB
, width(t1
), 2);
rangechk(t1
, t2
); /* The point of all this */
gen(O_AS2
, O_AS2
, width(t1
), width(t2
));
sizes
[cbn
].om_off
=+ limitsz
;
* if expr then stat [ else stat ]
error("Type of expression in if statement must be Boolean, not %s", nameof(p
));
l1
= put2(O_IF
, getlab());
l2
= put2(O_TRA
, getlab());
error("Type of expression in while statement must be Boolean, not %s", nameof(p
));
put2(O_IF
, (l2
= getlab()));
* repeat stat* until expr
error("Until expression type must be Boolean, not %s, in repeat statement", nameof(p
));
error("Assert statement is non-standard");
error("Assert expression must be Boolean, not %ss", nameof(q
));