|
|
DataMuseum.dkPresents historical artifacts from the history of: RC3500 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about RC3500 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 79104 (0x13500)
Types: TextFileVerbose
Names: »pass4text«
└─⟦2c55ea56f⟧ Bits:30001844 SW-save af projekt 1000, Alarm-system
└─⟦6b41451d2⟧
└─⟦this⟧ »pass4text«
program pass4(output, pass3file='pass3code',
pass4file='pass4code');
(*$T+*)
const
versionpass4 = 301; (* 3.01 date : 81.xx.xx *)
versionpass3 = 2; (* pass 3 version must be 2.xx *)
versionz80 = false; (* true z80 version *)
(* false lambda version *)
(*std variable length, and max values *)
word_length=2; byte_length=1;
char_length=1;
set_const_length = 64; (* words *)
(*
pointer_length,
activation_record_length is variables
*)
array_template_size = 8;
sub_template_size = 6;
field_template_size = 2;
record_template_size = 2;
bits_pr_byte=8;
bits_pr_word=16;
min_fields_pr_word = 3;
max_byte_value = 255;
module_size = 65536; (* 2**16 *)
top_address = 65535; (* module size -1 *)
max_int = 32768;
min_int = -max_int;
(*div*)
shift8 = 256;
shift16 = 65536;
bit_0_8 = - shift16; (* bit 0 - 8 in rc8000 word *)
spsp = 8224; (* string with 2 spaces *)
print_limit = 15;
max_block_level = 20; (* >= max_levels in pass 3 *)
max_operand = 100;
max_name_index = 2000;
max_init_level = 10;
max_const_area = 3000;
max_stack =200;
pack = true;
non_pack = false;
this_pass = 4;
(* constants in pass 4 code *)
(* value of type_v in pass 4 code *)
byte_typ = 1; addr_typ = 5;
word_typ = 2; set_typ = 6;
field_typ= 3; dyn_typ = 7;
double_typ = 4;
(* values of type_o in pass 4 code *)
bool_typ = 1; int_typ = 2; real_typ = 3; setof_typ = 4;
pointer_typ = 5; sem_typ = 6; ref_typ = 7; shadow_typ = 8;
scalar_typ = 9;
(* compare function number in pass 4 code *)
zeq = 2; zne = 3; zlt = 4;
zgt = 5; zle = 6; zge = 7;
zeq_set = 8; zne_set = 9; zle_set = 10;
zge_set = 11; zin = 12; zeq_struc = 13;
zne_struc = 14;
(* std function number in pass 4 code *)
zord = 1; zsucc = 2; zpred = 3; zchr = 4;
(* mode for for statement *)
zup = 1; zdown = 2;
(* export name type *)
offset_type = 1; value_type = 2;
(* end pass 4 code constants *)
(* literal type *)
num_const = 1; string_const = 2; char_const = 3;
type
pass3codes =
(
xfirstcode,
xerror, xerrortext, xerrorno,
xoption,
xnewline,
xeom,
xendprelude,
xexternal, xforward, xsecprocid, xsecfuncid,
xprocessid, xprocid, xfuncid,
xconstid,
xvarid, xinitconst, xvarlist,
xlabelid,
xundeclid,
xblock, xexception, xinitblock, xendblock,
xbegincode, xcodeline, xendcode,
(* std types *)
xinteger, xreal, xniltype, xerrortype, xstringtype,
xboolean, xshadow, xreference, xsemaphore,
xchar,
(* std functions *)
xsucc, xpred, xord, xchr,
xtype,
xredeftype,
xscalarid, xscalardef,
xgetexpr, xsubdef,
xarraydef, xpackedarraydef,
xpackedrecord, xrecord, xfieldid, xfielddef, xrecdef,
xsetdef, xpooldef, xpointerdef, xfrozendef,
xtypedef,
xexportvalue, xexportsize, xexportdispl, xexportoffset, xexportaddr,
xendexport,
xparamid, xvalueparam, xvarparam,
xname,
xprefix,
xlabel,
xcasestat, xcase, xcaselabel, xcaserange, xotherwise, xendcase,
xendcaselist, xendcasestat,
xforstat, xfor, xup, xdown, xdo, xendfor,
xifstat, xifexpr, xelse, xif,
xrepeat, xuntil, xendrepeat,
xwhile, xwhileexpr, xendwhile,
xwith, xwithvar, xendwith,
xlockstat, xlockvar, xlock, xendlock,
xgoto,
xchannel, xchanvar, xendchannel,
xassignstat, xbecomes, xassign,
xexchangestat, xexchange,
xproccall, xendproc,
xfunccall, xfcall, xendfunccall,
xactual, xendactual,
xprocessparam,
xvarpointer, xtempointer, xarglistsize,
(* expressions *)
xexpr,
xgetvalue,
xne, xeq, xle, xge, xlt, xgt, xin,
xneg, xadd, xsub, xor,
xxor,
xdiv, xmul, xmod, xand,
xnot,
(* conversion operators *)
xrange,
xset, xinclude, xsetexpr, xincluderange, xendset,
xliteral,
xvar,
xstrucconst, xtimes, xnull, xstruc, xendstruc,
xindexexpr, xindex,
xarrow, xfield,
xlastcode
);
pass3codeindex = 0 .. 200; (* number of pass3codes *)
literalkinds = (lit_dummy, lit_integer, lit_string_or_empty, lit_char);
\f
(* end pass 3 codes *)
out_code =
(* pass4codes= *)
( zfirstcode,
zmodule, zeom,
zoption, znewline,
zprocess, zextprocess,
zblock, zlength, zendblock,
zbegincode, zcodeline, zendcode,
zsubdef,
zarray1template, zarray2template, zarray3template,
zrecordtemplate, zfieldsize, zdynfieldsize, zincfield,
zendtemplate,
zenddecl,
zallocdynvar,
zinitialize, zstrucinit, zsimpleinit, zsetinit,
zexception, zextexception,
zsysinit, zsysdyninit,
zfieldinit, zdynfieldinit,
zendinitfields,
zarrayinit, zarraydyninit,
zpoolinit,
zvarinit,
zexport,
zproc, zextproc,
zfunc, zextfunc,
zparamtype,
zdeflix,
zproccall, zendpcall,
zextproccall,
zprocessparam, zendprocessparam,
zvarpointer, ztempointer, zarglistsize,
zvarparam, zvalueparam,
zassignstat, zleft, zassign,
zcasestat, zcase, zendcaselist, zendcasestat, zendcase,
zcaserange, zcaselabel, zotherwise,
zforstat, zleftfor, zforstore, zdo, zendfor,
zgoto,
zifstat, zifexpr, zelse, zif,
zrepeat, zuntil, zendrepeat,
zwhile, zwhileexpr, zendwhile,
zwithstat, zwithvar, zendwith,
zlockstat, zlockvar, zlockdynvar, zendlock,
zchannel, zchanvar, zendchannel,
zexchstat, zexchange,
znot, zneg, zcompare, zcompstruc, zcompdynstruc, zdiv,
zmul, zmod, zor, zxor, zadd, zsub, zand, zrangetest,
zdynrangetest,
zconst, zlconst, zsetconst,
zset, zinclude, zsetexpr, zincludeint, zendset,
zinitconst,
zindvar,
zaddr, zcaddr, zindaddr,
zpackedarr,
zfield, zdynfield,
zindexexpr, zcindex, zindex,
zstdfunccall, zfcall, zendfunccall,
zfunccall, zextfunccall,
zerror, zerrorno, zerrortext,
zlastcode
);
pass4codeindex = 0..150; (* number of pass4codes *)
\f
(* end pass 4 codes *)
context_kind = ( not_used,
int_type, char_type, bool_type, sem_type,
shadow_type, ref_type, scalar_type, set_type,
pool_type, array_type, sys_array_type, pointer_type,
record_type, sys_record_type,label_type, routine_type,
dyn_subrange, undef_type,
field, dyn_field, variable, dyn_variable,
var_param, value_param,
sconst, lconst, set_const,
with_var, lock_var, func_result,
expr, struc_c );
error_types = (overflow, range_def_error, set_def_error,
pool_def_error, type_error,
addr_error, var_error, range_error,
literal_error, set_error, const_error,
for_error, input_error, scalar_error,
operand_overflow, name_overflow, block_overflow,
bit_count_error, const_overflow,prelude_error, address_overflow,
record_size_error, array_size_error,
field_export_error, exportvalue_error, exportaddr_error,
stack_error, version_error, not_implemented,
error_dyn, error_dyn_init, error_dyn_var);
name_index = 0..max_name_index;
location_index = integer;
display_index = 1..max_block_level;
addr_state = (direct, indirect, addr, expression, p_comp );
block_mode = (process_mode, proc_mode, func_mode, record_mode);
export_kind_type = (exportvalue, exportsize, exportdispl,
exportoffset, exportaddr );
name_rec = record
context: context_kind;
size: integer;
min: integer;
max: integer;
niv: integer;
offset: integer;
lix: location_index;
next_comp: name_index;
comp_type: name_index;
packed_comp:boolean;
dynamic : boolean;
end;
operand_rec = record
type_nix: integer;
var_nix: integer;
kind: context_kind;
niv: integer;
offset: integer;
size: integer;
context: context_kind;
lix: integer;
first: integer;
comp_size:integer;
field_packed : boolean;
array_packed : boolean;
dynamic: boolean;
state: addr_state;
temp_size: integer;
func_value: boolean;
end;
init_modes = (record_init, array_init, packed_array, error_init );
struc_level = record
times: integer;
current_index: integer;
top_index: integer;
first: integer;
displ: integer;
bits_pr_field: integer;
elem_pr_word: integer;
dope_lix: integer;
saved_nix: name_index;
saved_lix: integer;
saved_size: integer;
saved_stat_part: boolean;
init_mode: init_modes;
end;
display_rec = record
saved_mode: block_mode;
saved_offset: integer;
saved_niv: integer;
saved_part: boolean;
saved_pack: boolean;
saved_bit: integer;
saved_chain: integer;
saved_v_length: integer;
saved_idcount: integer;
saved_lix: integer;
saved_init: boolean;
saved_dyn: boolean;
saved_c_index: integer;
parameter_length: integer;
end;
var
source_line: integer;
convert_in_code: array [pass3codeindex] of pass3codes;
shift_to: array [0..15] of integer;
nametable: array [name_index] of name_rec;
nix: integer;
stack: array [0..max_stack] of integer;
t: integer;
ops: array [1..max_operand] of operand_rec;
os, ot, empty_stack: integer;
struc_init: array [1..max_init_level] of struc_level;
ss: integer;
c: array [1..max_const_area] of integer;
first_c_index, top_c_index: integer;
display: array [display_index] of display_rec;
this_level: integer;
array_types, index_types, indirects, init_types,
system_types,var_types, simple_types : set of context_kind;
program_ok, done, test, init_fields, dyn_fields, pack_record, prelude,
index_check, prefixed_name, waiting_with, line_number,
prefixed, stat_part, variable_init, export, test_survey : boolean;
mode: block_mode;
ext_name,
prefix_name: alfa;
export_kind: export_kind_type;
type_pointer,
pointer_length,
activation_record_length,
field_unite,
top_nix,
top_t,
top_ops,
top_ss,
top_c,
top_level,
top_lix,
process_offset,
current_bit,
current_lix,
current_niv,
current_offset,
record_offset,
name_key,
field_offset,
first_of_expr,
var_length,
idcount,
scalar_count,
param_number,
head_line,
process_param_length,
printed,
i,no,
undef_nix,
max_set_const_value,
semaphor_length,
chain : integer;
pass3file, pass4file: file of integer;
procedure error(ty: error_types); forward;
procedure load_expr; forward;
procedure get(var number: integer);
begin
read(pass3file,number);
end;
procedure print(op: out_code);
begin
if printed>=print_limit then begin
writeln; printed:=0;
end;
write(' *',ord(op):3);
printed:=printed+1;
end;
procedure print_arg(arg: integer);
begin
if printed>=print_limit then begin
writeln; printed:=0;
end;
write(arg:7);
printed:=printed+1;
end;
procedure put0(op: out_code);
begin
if line_number then begin
write(pass4file, ord(znewline), source_line);
line_number:=false;
end;
write(pass4file,ord(op));
if test then print(op);
end;
procedure put1(op: out_code; arg1: integer);
begin
if line_number then begin
write(pass4file, ord(znewline), source_line);
line_number:=false;
end;
write(pass4file,ord(op),arg1);
if test then begin
print(op); print_arg(arg1);
end;
end;
procedure put2(op: out_code; arg1,arg2: integer);
begin
if line_number then begin
write(pass4file, ord(znewline), source_line);
line_number:=false;
end;
write(pass4file,ord(op),arg1,arg2);
if test then begin
print(op); print_arg(arg1); print_arg(arg2);
end;
end;
procedure put3(op: out_code; arg1,arg2,arg3: integer);
begin
if line_number then begin
write(pass4file, ord(znewline), source_line);
line_number:=false;
end;
write(pass4file,ord(op),arg1,arg2,arg3);
if test then begin
print(op); print_arg(arg1); print_arg(arg2);
print_arg(arg3);
end;
end;
procedure put4(op: out_code; arg1,arg2,arg3,arg4: integer);
begin
if line_number then begin
write(pass4file, ord(znewline), source_line);
line_number:=false;
end;
write(pass4file,ord(op),arg1,arg2,arg3,arg4);
if test then begin
print(op); print_arg(arg1); print_arg(arg2);
print_arg(arg3); print_arg(arg4);
end;
end;
procedure put_arg1(arg1: integer);
begin
write(pass4file,arg1);
if test then print_arg(arg1);
end;
procedure put_arg2(arg1,arg2: integer);
begin
write(pass4file,arg1,arg2);
if test then begin
print_arg(arg1); print_arg(arg2);
end;
end;
procedure put_arg3(arg1,arg2,arg3: integer);
begin
write(pass4file,arg1,arg2,arg3);
if test then begin
print_arg(arg1); print_arg(arg2); print_arg(arg3);
end;
end;
procedure copy(op: out_code; no: integer);
var arg: integer;
begin
put0(op);
for i:=1 to no do begin
get(arg); put_arg1(arg);
end;
end;
procedure new_line;
begin
get(source_line);
line_number:=true;
end;
procedure out_name(name: alfa);
begin
for i:=1 to alfalength do put_arg1( ord(name[i] ) );
end;
procedure out_constant_area;
var first,p: integer;
begin
if top_c_index > top_c then top_c:=top_c_index;
first:=first_c_index;
while first<top_c_index do begin
if c[first+1]>0 then begin
put1(zdeflix,c[first+1]);
p:=c[first];
if c[first+2]>p then p:=c[first+2];
put1(zinitconst,p-3);
for i:=first+3 to first + c[first] -1 do put_arg1(c[i]);
if c[first+2] > c[first] then
for i:=1 to c[first+2] - c[first] do put_arg1(spsp);
end;
first:=first+c[first];
end;
end;
procedure out_formal_list;
var type_p,no,param_size: integer;
begin
for no:=param_number-1 downto 0 do
with nametable[stack[t-no]] do begin
with nametable[comp_type] do begin
param_size:=size;
case context of
pointer_type: type_p:=1;
sem_type: type_p:=2;
ref_type: type_p:=3;
shadow_type: type_p:=4;
pool_type: type_p:=5;
sys_record_type: type_p:=6;
sys_array_type: type_p:=7;
end
otherwise type_p:=8;
end;
if context=value_param then
type_p := type_p * 4 + 2
else
begin
if nametable[comp_type].dynamic then error(error_dyn);
type_p := type_p * 4 + 1;
end;
put2(zparamtype,type_p,param_size)
end;
end;
procedure printhead;
begin
if test then writeln;
write('*** pass 4 line ',source_line:4,', ');
end;
procedure eom; forward;
procedure compiler_error(e: error_types);
begin
printhead;
write('compiler error : ');
case e of
addr_error: writeln('addressing');
bit_count_error: writeln('bit count');
for_error: writeln('for error');
scalar_error: writeln('scalar error');
input_error: writeln('wrong input');
end
otherwise writeln(', error code = ',ord(e):1);
eom; eom;
end;
procedure pass4error(e: error_types);
begin
printhead;
case e of
overflow: writeln('overflow');
error_dyn: writeln('dynamic type not allowed');
error_dyn_init: writeln('initialize dynamic type not allowed');
error_dyn_var: writeln('dynamic variable not allowed');
not_implemented: writeln('dynamic types not implemented');
range_def_error: writeln('subrange def.');
set_def_error: writeln('set def.');
pool_def_error: writeln('pool def.');
type_error: writeln('constant value');
var_error: writeln('not constant');
range_error: writeln('case label range');
prelude_error: writeln('no init. or process in enviroment');
literal_error: writeln('constant');
set_error: writeln('set constant');
const_error: writeln('times');
address_overflow: writeln('stack');
record_size_error: writeln('record size');
array_size_error: writeln('array size');
exportvalue_error: writeln('export value error');
field_export_error: writeln('packed field export');
exportaddr_error: writeln('export offset error');
end
otherwise compiler_error(e);
end;
procedure eom;
begin
put0(zeom);
close(pass4file); close(pass3file);
done:=true;
end;
procedure error(ty: error_types);
begin
put2(zerror,this_pass,ord(ty));
program_ok:=false;
pass4error(ty);
end;
procedure abort(ty: error_types);
begin
printhead;
write('compilation terminated by ');
case ty of
operand_overflow: writeln('operand overflow');
name_overflow: writeln('name table overflow');
block_overflow: writeln('block level overflow');
const_overflow: writeln('constant area overflow');
stack_error: writeln('stack error');
version_error: writeln('wrong pass 4');
end
otherwise compiler_error(ty);
eom; eom;
end;
procedure write_nametable(top: integer);
var ch1,ch2: char;
begin
if top=0 then top:=max_name_index;
writeln;
writeln(' nix c s min max niv',
' offset lix n-c c-t pack dyn');
for i:=0 to top do
with nametable[i] do
if context<>not_used then begin
writeln('name',i:6,ord(context):4,size:5,
min,max,niv,offset,lix,next_comp:7,comp_type:7,
packed_comp:8, dynamic:8);
end;
end;
procedure write_operand_stack;
begin
writeln;
writeln('expr = ',first_of_expr:1);
writeln('ot = ',ot:1);
writeln('os = ',os:1);
if ot=empty_stack then writeln('operand stack empty')
else begin
writeln(' k niv offset size con',
' lix first f_sizepack_f pack_a state temp');
for i:=ot downto empty_stack+1 do
with ops[i] do
writeln('operand stack ',ord(kind):4,niv,offset,size,
ord(context),lix,first:7,comp_size:7,
field_packed:7,array_packed:7,ord(state):8,temp_size);
end;
end;
procedure write_name_stack;
var ch1,ch2: char; p: integer;
begin
writeln;
if t=0 then writeln('name stack empty') else
begin
writeln('name stack');
for i:=t downto 1 do begin
p:=stack[i];
writeln(i:4,' - ',p:4);
end;
end;
end;
procedure write_const_area;
var i : integer;
begin
writeln; write('const area', first_c_index, top_c_index);
for i:=1 to top_c_index do begin
if (i-1) mod 10 = 0 then begin
writeln;
write(i:6,'. ');
end;
write(c[i]:8);
end;
writeln;
end;
procedure set_option;
var p,a,b: integer;
begin
get(p); get(a); get(b);
if p=this_pass then
case a of
1: write_nametable(b);
2: write_operand_stack;
3: write_name_stack;
4: test:=b=1;
5: program_ok:=program_ok and (b=1);
6: write_const_area;
9: begin (* index check on,off *)
index_check:=b=1;
put3(zoption,5,a,b);
end;
10: test_survey:=b=1;
end
else
begin
if (p=0) and (a=3) then
if b div 100 <> versionpass3 then abort(version_error);
put3(zoption,p,a,b);
end;
end;
procedure initialize;
var code: pass3codes; p: integer; empty_name: name_rec;
empty_ops: operand_rec;
begin
for code:=xfirstcode to xlastcode do
convert_in_code[ord(code)]:=code;
(*shift_to[bit] is 2**(15-bit) *)
p:=1;
for i:=15 downto 0 do begin
shift_to[i]:=p; p:=p*2;
end;
(* all nametable entries empty *)
with empty_name do begin
context:=not_used;
size:=0; min:=0; max:=0;
niv:=0; offset:=0;lix:=0;
next_comp:=0;
comp_type:=0;
packed_comp:=false;
dynamic:=false;
end;
for i:=0 to max_name_index do nametable[i]:=empty_name;
(* init all operand stack entries to empty *)
with empty_ops do begin
kind:=not_used; niv:=0; offset:=0; size:=0;
context:=not_used;lix:=0; first:=0;
field_packed:=false;
array_packed:=false;
comp_size:=0;
state:=direct; temp_size:=0;
func_value:=false;
end;
for i:=1 to max_operand do ops[i]:=empty_ops;
reset(pass3file);
rewrite(pass4file);
source_line:=0;
line_number:=false;
top_nix:=0; top_t:=0; top_ops:=0; top_ss:=0;
top_c:=0; top_level:=0; top_lix:=0;
test_survey:=false;
index_check:=true; (* default index.yes *)
t:=0;
ss:=0;
empty_stack:=0;
os:=empty_stack;
ot:=empty_stack;
top_c_index:=1;
first_c_index:=1;
done:=false;
program_ok:=true;
test:=false;
prefixed:=false;
prefixed_name:=false;
prelude:=true;
variable_init:=false;
waiting_with:=false;
stat_part:=false;
export:=false;
mode:=process_mode;
this_level:=0;
printed:=0; idcount:=0; param_number:=0;
scalar_count:=0;
if (* **z80** *) versionz80 then begin
type_pointer:=word_typ;
activation_record_length:=12;
process_offset:=6;
current_offset:=0;
pointer_length:=word_length;
field_unite:=word_length;
end
else
begin (* **lambda** *)
type_pointer:=double_typ;
activation_record_length:=16;
process_offset:=0;
current_offset:=-1;
pointer_length:=2*word_length;
field_unite:=byte_length;
end;
process_param_length:=2*pointer_length + word_length;
current_bit:=0;
current_lix:=1;
current_niv:=0;
name_key:=1;
field_offset:=0;
first_of_expr:=ot;
max_set_const_value:=set_const_length*bits_pr_word - 1;
var_types:=[variable, var_param, value_param ];
array_types:=[array_type,sys_array_type];
index_types:=[int_type,char_type,bool_type,scalar_type];
simple_types:=[ int_type, char_type, bool_type, scalar_type, dyn_subrange ];
if (* **z80** *) versionz80 then
init_types:=[pool_type, sys_array_type, sys_record_type]
else
(* **lambda** *)
init_types:=[shadow_type,ref_type,pool_type,sem_type,
sys_array_type,sys_record_type,pointer_type];
system_types:=[shadow_type,ref_type,pool_type,sem_type,pointer_type];
indirects:=[var_param,with_var,lock_var,dyn_variable];
put3(zoption, 0, this_pass, versionpass4);
end;
procedure push;
begin
os:=ot; ot:=ot+1;
if ot > top_ops then top_ops:=ot;
if ot>max_operand then abort(operand_overflow);
ops[ot].temp_size:=source_line; (* test *)
end;
procedure pop;
begin
ot:=os;
if os>empty_stack then os:=os-1;
end;
procedure push_name(var nix: integer);
begin
get(nix);
if nix>max_name_index then abort(name_overflow);
t:=t+1;
if t > top_t then top_t:=t;
if t>max_stack then abort(name_overflow);
stack[t]:=nix;
end;
procedure push_old(nix: name_index);
begin
t:=t+1;
if t>max_stack then abort(name_overflow);
stack[t]:=nix;
end;
procedure new_name;
begin
push_name(nix);
idcount:=idcount+1;
end;
procedure new_scalar;
begin
push_name(nix);
scalar_count:=scalar_count+1;
end;
procedure word_allign; forward;
procedure push_level(m: block_mode);
begin
if this_level>=max_block_level then abort(block_overflow)
else this_level:=this_level+1;
if this_level > top_level then top_level:=this_level;
with display[this_level] do begin
saved_mode:=mode; mode:=m;
saved_niv:=current_niv;
saved_part:=stat_part; stat_part:=false;
if mode=record_mode then begin
saved_offset:=record_offset; record_offset:=0;
saved_pack:=pack_record; pack_record:=false;
saved_bit:=current_bit; current_bit:=0;
saved_chain:=chain; chain:=0;
saved_idcount:=idcount; idcount:=0;
saved_init:=init_fields; init_fields:=false;
saved_dyn:=dyn_fields; dyn_fields:=false;
end
else
begin
saved_offset:=current_offset;
if mode=process_mode then begin
current_niv:=0;
if (* **z80** *) versionz80 then
current_offset:= -process_offset
else
(* **lambda** *)
current_offset:=process_offset;
end else begin
current_niv:=current_niv+1;
if (* **z80** *) versionz80 then
current_offset:= -activation_record_length
else
(* **lambda** *)
current_offset:=activation_record_length-1;
end;
saved_v_length:=var_length; var_length:=0;
saved_c_index:=first_c_index;
first_c_index:=top_c_index;
saved_lix:=current_lix;
end;
end;
end;
procedure pop_level;
begin
with display[this_level] do begin
if mode=record_mode then begin
pack_record:=saved_pack;
current_bit:=saved_bit;
chain:=saved_chain;
idcount:=saved_idcount;
init_fields:=saved_init;
record_offset:=saved_offset;
dyn_fields:=saved_dyn;
end
else
begin
current_offset:=saved_offset;
top_c_index:=first_c_index;
first_c_index:=saved_c_index;
var_length:=saved_v_length;
if (* **z80** *) versionz80 then
current_lix:=saved_lix;
end;
mode:=saved_mode;
current_niv:=saved_niv;
stat_part:=saved_part;
end;
this_level:=this_level-1;
end;
function int_add(a,b: integer): integer;
begin
if a>=0 then begin
if max_int-a>=b then int_add:=a+b
else begin
error(overflow); int_add:=a;
end;
end else begin
if min_int-a<=b then int_add:=a+b
else begin
error(overflow); int_add:=a;
end;
end;
end;
function int_mul(a,b: integer): integer;
var s1,s2: integer;
begin
s1:=1; s2:=1;
if a<0 then begin a:=-a; s1:=-1; end;
if b<0 then begin b:=-b; s2:=-1; end;
if a<=max_int div b then int_mul:=a*b*s1*s2
else begin
error(overflow); int_mul:=a;
end;
end;
function alloc_var(size: integer): integer;
begin
if (* **z80** *) versionz80 then begin
(* current_offset <= 0 *)
if top_address + current_offset >= size then
current_offset := current_offset - size
else error(address_overflow);
alloc_var:=current_offset;
end
else
begin
(* **lambda** *)
alloc_var:=current_offset;
(* current_offset >= -1 *)
if top_address - current_offset >= size then
current_offset := current_offset + size
else error(address_overflow);
end;
end; (*alloc var*)
function address_add(a,b: integer): integer;
begin
if top_address - a >= b then address_add:=a+b
else
begin
error(address_overflow);
address_add:=a;
end;
end;
function field_add(a,b: integer): integer;
begin
if module_size - a >= b then field_add:=a+b
else
begin
error(record_size_error);
field_add:=a;
end;
end;
function take_expr: integer;
begin
with ops[ot] do begin
if context<>sconst then begin
error(var_error); take_expr:=0;
end
else
begin
if offset>max_int-1 then begin
take_expr:=max_int-1;
error(overflow);
end
else
take_expr:=offset;
end;
end;
pop;
end;
function bits(v: integer): integer;
var no,power: integer;
begin
if v<0 then no:=bits_pr_word else
if v<2 then no:=1 else
begin
power:=4; no:=2;
while v>power-1 do begin
power:=power*2;
no:=no+1;
end;
end;
if no>bits_pr_word then compiler_error(bit_count_error);
bits:=no;
end;
function var_size(min,max: integer): integer;
begin
if (min<0) or (bits(max) > bits_pr_byte) then
var_size:=word_length else
var_size:=byte_length;
end;
function check_type(ty: name_index; a,b: integer): boolean;
var bo: boolean;
begin
bo:=a<=b;
with nametable[ty] do
if (a<min) or (b>max) then bo:=false;
check_type:=bo;
end;
procedure word_allign;
begin
if not versionz80 then
(* **lambda** *)
if not odd(current_offset) then
current_offset:=address_add(current_offset,1);
end;
procedure field_allign;
begin
if not versionz80 then
(* **lambda** *)
if odd(record_offset) then
record_offset:=field_add(record_offset,1);
end;
function type_o(c: context_kind): integer;
begin
case c of
pointer_type: type_o:=pointer_typ;
sem_type: type_o:=sem_typ;
ref_type: type_o:=ref_typ;
shadow_type: type_o:=shadow_typ;
end;
end;
procedure alloc_constant(var lix: location_index;
var index: integer; bytes: integer);
var words: integer;
begin
words:=(bytes+1) div 2;
index:=top_c_index + 3;
top_c_index:=top_c_index+words+3;
if top_c < top_c_index then top_c:=top_c_index;
if top_c_index>max_const_area then abort(const_overflow);
lix:=-current_lix;
current_lix:=current_lix+1;
c[index-3]:=words + 3;
c[index-2]:=lix;
c[index-1]:=words+3;
for i:=index to top_c_index-1 do c[i]:=0;
end;
procedure cut_constant(c_index, new_words: integer);
var first: integer;
begin
first:=c_index - 3;
c[first]:=new_words+3;
top_c_index:=first+new_words+3;
c[first+2]:=c[first];
end;
procedure adjust_string(p,q: integer);
var words, i: integer;
begin
if ops[q].dynamic then error(error_dyn_var)
else
begin
ops[p].size:=ops[q].size;
words:=(ops[q].size + 1) div 2+3;
i:=ops[p].offset;
if words > c[i-1] then c[i-1]:=words;
end;
end;
procedure remove_constant(c_index: integer);
var first, q: integer;
begin
first:=c_index-3; q:=first;
if q+c[first] = top_c_index then
top_c_index:=first;
end;
procedure release_temp(s: integer);
begin
if (* **z80** *) versionz80 then
current_offset:=current_offset + s
else
(* **lambda** *)
current_offset:=current_offset - s;
end;
procedure constant_used(q: integer);
begin
with ops[q] do begin
niv:=-niv;
c[offset-2]:=niv;
if var_nix >= 0 then
nametable[var_nix].niv:=niv;
end;
end;
function alloc_temp(size: integer): integer;
begin
alloc_temp:=alloc_var(size);
if (* **z80** *) versionz80 then begin
if -current_offset > var_length then
var_length:= -current_offset;
end
else
(* **lambda** *)
if current_offset>var_length then
var_length:=current_offset;
end;
procedure alloc_dope(lix, lower, upper, elem: integer);
var index: integer;
begin
index:=top_c_index;
top_c_index:=top_c_index + 6;
if top_c_index>max_const_area then abort(const_overflow);
c[index]:=6;
c[index+1]:=lix;
c[index+2]:=6;
c[index+3]:=lower;
c[index+4]:=upper;
c[index+5]:=elem;
end;
procedure alloc_range_descr(lix, lower, upper: integer);
var index: integer;
begin
index:=top_c_index;
top_c_index:=top_c_index+5;
if top_c_index>max_const_area then abort(const_overflow);
c[index]:=5;
c[index+1]:=lix;
c[index+2]:=5;
c[index+3]:=lower;
c[index+4]:=upper;
end;
procedure std_name(ty: pass3codes);
begin
push_name(nix);
with nametable[nix] do begin
dynamic:=false;
case ty of
xinteger: begin
context:=int_type;
size:=word_length;
max:=max_int-1; min:=-max_int;
lix:=-current_lix;
current_lix:=current_lix+1;
end;
xchar: begin t:=t-1; context:=char_type; end;
xreal: ;(* not inplemented *)
xboolean: begin t:=t-1; context:=bool_type; end;
xstringtype: begin
t:=t-1;
context:=array_type;
lix:=0; size:=0;
packed_comp:=false;
end;
xsemaphore: begin
t:=t-1;
context:=sem_type;
semaphor_length:=size;
end;
xshadow: begin t:=t-1; context:=shadow_type; end;
xreference: begin
t:=t-1;
context:=ref_type;
if (* **lambda** *) not versionz80 then size:=2*pointer_length;
end;
xniltype: begin
context:=int_type;
size:=0;
end;
xerrortype: begin
t:=t-1;
undef_nix:=nix;
context:=undef_type;
size:=word_length;
end;
xundeclid: begin
t:=t-1;
nametable[nix]:=nametable[undef_nix];
end;
xchr: begin t:=t-1; niv:=-zchr-1; end;
xord: begin t:=t-1; niv:=-zord-1; end;
xpred: begin t:=t-1; niv:=-zpred-1; end;
xsucc: begin t:=t-1; niv:=-zsucc-1; end;
end;
end;
end;
procedure scalar_def;
var saved_size: integer;
begin
push_name(nix);
with nametable[nix] do begin
context:=scalar_type;
dynamic:=false;
min:=0; max:=scalar_count-1;
if max<0 then begin
compiler_error(scalar_error);
max:=0;
end;
size:=var_size(min,max);
saved_size:=size;
end;
for i:=scalar_count downto 1 do
with nametable[stack[t-i]] do begin
context:=sconst;
size:=saved_size;
offset:=scalar_count-i;
end;
t:=t-scalar_count-1;
scalar_count:=0;
push_old(nix);
end;
procedure sub_def;
var ty: integer;
begin
push_name(nix); get(ty);
if (ops[ot].context = sconst) and (ops[os].context = sconst) then
with nametable[nix] do begin
context:=nametable[ty].context;
max:=take_expr; min:=take_expr;
if not check_type(ty,min,max) then begin
error(range_def_error);
min:=0; max:=1;
end;
size:=var_size(min,max);
lix:=-current_lix; (* no range descr allocated *)
current_lix:=current_lix+1;
end
else
begin (* dynamic *)
load_expr; pop; pop;
with nametable[nix] do begin
context:=dyn_subrange;
size:=word_length;
min:=min_int; max:=max_int-1;
niv:=current_niv;
offset:=alloc_var(sub_template_size);
dynamic:=true;
put1(zsubdef, offset);
if (* **z80** *) versionz80 then begin
error(not_implemented);
dynamic:=false;
end;
end; (*with*)
end; (*dynamic*)
end;
procedure pointer_def;
begin
t:=t-1; (*skip type*)
push_name(nix);
with nametable[nix] do begin
context:=pointer_type;
size:=pointer_length;
dynamic:=false;
end;
end;
procedure redef_type;
begin
i:=stack[t]; t:=t-1;
push_name(nix);
nametable[nix]:=nametable[i];
with nametable[nix] do
if context in index_types then begin
lix:=-current_lix;
current_lix:=current_lix+1
end;
end;
procedure static_array_def(pack_array: boolean);
var lower,upper,span,array_size,bit_span,
comp_nix,fields_pr_word,elem_size: integer;
pack, init_type: boolean;
begin
pack:=pack_array;
with nametable[stack[t-1]] do begin
lower:=min; upper:=max;
span:=upper-lower+1;
end;
comp_nix:=stack[t];
with nametable[comp_nix] do begin
init_type:=context in init_types;
if (* **z80** *) versionz80 then
elem_size:=size
else
(* **lambda** *)
if odd(size) and init_type then
elem_size:=size+1 else elem_size:=size;
if pack then pack:=context in index_types;
if pack then begin
bit_span:=bits(max);
fields_pr_word:=bits_pr_word div bit_span;
if fields_pr_word>=min_fields_pr_word then begin
array_size:=(span div fields_pr_word)*2 +
((span mod fields_pr_word)*bit_span+7) div bits_pr_byte;
if (* **z80** *) versionz80 then
if odd(array_size) then array_size:=array_size + 1;
elem_size:=fields_pr_word*shift8+bit_span;
end
else pack:=false;
end;
if not pack then
begin
if elem_size<=module_size div span then array_size:=elem_size*span
else
begin
error(array_size_error);
array_size:=size;
end;
end;
end;
t:=t-2;
push_name(nix);
with nametable[nix] do begin
if init_type then
context:=sys_array_type else context:=array_type;
size:=array_size;
min:=lower; max:=upper; niv:=elem_size;
lix:=-current_lix; (* no dope vector allocated *)
current_lix:=current_lix+1;
next_comp:=comp_nix;
packed_comp:=pack;
dynamic:=false;
end;
end;
procedure array_def(pack_array: boolean);
var index_nix, comp_nix, dyn_case, bit_span, fields_pr_word,
comp_niv, comp_offset,
lower, upper, index_niv, index_offset,
allign, elem_size : integer;
pack, init_type: boolean;
begin
index_nix:=stack[t-1];
comp_nix:=stack[t];
if nametable[index_nix].dynamic then
dyn_case:=2 else dyn_case:=1;
if nametable[comp_nix].dynamic then
dyn_case:=dyn_case+2;
if nametable[comp_nix].context = dyn_subrange then
dyn_case:=dyn_case-2;
(*
index type comp type : dyn_case
static static 1
dynamic static 2
static dynamic 3
dynamic dynamic 4
*)
if dyn_case = 1 then
static_array_def(pack_array)
else
begin
pack:=false; fields_pr_word:=1; bit_span:=0;
with nametable[index_nix] do begin
lower:=min; upper:=max;
index_niv:=niv; index_offset:=offset;
end;
with nametable[comp_nix] do begin
init_type:=context in init_types;
if init_type then allign:=1 else allign:=0;
if dyn_case = 2 then begin
if (* **z80** *) versionz80 then
elem_size:=size
else
(* **lambda** *)
if odd(size) and init_type then
elem_size:=size+1 else elem_size:=size;
if pack_array then pack:=context in index_types;
if pack then begin
bit_span:=bits(max);
fields_pr_word:=bits_pr_word div bit_span;
if fields_pr_word < min_fields_pr_word then begin
fields_pr_word:=1;
pack:=false;
end;
end; (*if pack*)
end; (*dyn_case=2*)
comp_niv:=niv; comp_offset:=offset;
end; (*with*)
t:=t-2; (*pop pop namestack*)
push_name(nix);
with nametable[nix] do begin
if init_type then
context:=sys_array_type else context:=array_type;
niv:=current_niv;
offset:=alloc_var(array_template_size);
next_comp:=comp_nix;
packed_comp:=pack;
dynamic:=true;
size:=0; min:=0; max:=0; lix:=0;
case dyn_case of
2: begin
put4(zarray1template, offset,
index_niv, index_offset, elem_size);
put_arg2(fields_pr_word, bit_span);
end;
3: begin
put3(zarray2template, offset,
comp_niv, comp_offset);
put_arg3(lower, upper, allign);
end;
4: begin
put3(zarray3template, offset,
comp_niv, comp_offset);
put_arg3(index_niv, index_offset, allign);
end;
end; (*case*)
end; (*with*)
end; (*if*)
end; (*array def*)
procedure field_list;
var field_type_nix, field_size, field_nix, max_bits,
comp_niv, comp_offset, allign: integer;
allign_type, pack_field, init,dyn: boolean;
begin
pack_field:=false;
field_type_nix:=stack[t];
with nametable[field_type_nix] do begin
field_size:=size;
if pack_record and (context in index_types) then begin
if min>=0 then begin
max_bits:=bits(max);
if max_bits<bits_pr_word then
pack_field:=true;
end;
end;
init:=context in init_types;
allign_type:=init;
comp_niv:=niv; comp_offset:=offset;
dyn:=dynamic;
if context = dyn_subrange then dyn:=false;
if allign_type then allign:=1 else allign:=0;
end;
if pack_record and not pack_field then begin
if current_bit>0 then begin
record_offset:=field_add(record_offset,field_unite);
if dyn_fields then put0(zincfield);
end;
current_bit:=0;
end;
init_fields:=init_fields or init;
for i:=idcount downto 1 do begin
field_nix:=stack[t-i];
with nametable[field_nix] do begin
if pack_field then begin
if current_bit+max_bits>bits_pr_word then begin
record_offset:=field_add(record_offset,field_unite);
if dyn_fields then put0(zincfield);
current_bit:=0;
end;
size:=max_bits;
max:=max_bits;
min:=current_bit;
current_bit:=current_bit+max_bits;
if dyn_fields then begin
niv:=current_niv;
offset:=alloc_var(field_template_size);
put3(zfieldsize, 0, offset, 0);
end
else
offset:=record_offset;
if (* **lambda** *) not versionz80 then
if current_bit >= bits_pr_byte then begin
current_bit:=current_bit - bits_pr_byte;
record_offset:=field_add(record_offset,byte_length);
if dyn_fields then put0(zincfield);
end;
end else begin
if allign_type then field_allign;
if dyn_fields then begin
niv:=current_niv;
offset:=alloc_var(field_template_size);
if dyn then
put4(zdynfieldsize, allign, offset,
comp_niv, comp_offset)
else
put3(zfieldsize, allign, offset, field_size);
end
else
begin
size:=field_size; offset:=record_offset;
record_offset:=field_add(record_offset, field_size);
if dyn then
put3(zrecordtemplate, offset, comp_niv, comp_offset);
end;
end;
if dyn_fields then
context:=dyn_field else context:=field;
dyn_fields:=dyn_fields or dyn;
packed_comp:=pack_field;
if pack_field then
if size=bits_pr_byte then
if (min=0) or (min=8) then begin
packed_comp:=false;
size:=byte_length;
if (* **z80** *) versionz80 then begin
if min=0 then offset:=offset+1
end
else
(* **lambda** *)
if min=8 then offset:=offset+1
end;
if init then begin
next_comp:=chain; chain:=field_nix;
comp_type:=field_type_nix;
end;
end;
end;
t:=t-idcount-1; idcount:=0;
end;
procedure record_def;
begin
push_name(nix);
with nametable[nix] do begin
if pack_record then begin
if current_bit>0 then begin
record_offset:=field_add(record_offset,field_unite);
if dyn_fields then put0(zincfield);
end;
end;
dynamic:=dyn_fields;
if dyn_fields then begin
niv:=current_niv;
offset:=alloc_var(record_template_size);
put1(zendtemplate, offset);
size:=0;
end
else
size:=record_offset;
if init_fields then begin
context:=sys_record_type;
next_comp:=chain;
end else
context:=record_type;
end;
pop_level;
end;
procedure set_def;
var lower,upper,words: integer;
begin
with nametable[stack[t]] do begin
lower:=min; upper:=max;
if dynamic then begin
error(error_dyn);
lower:=0; upper:=1;
end;
words:=((upper+1+bits_pr_word-1) div bits_pr_word);
end;
t:=t-1;
if lower<0 then begin
error(set_def_error); lower:=0;
end;
if words=0 then words:=1;
push_name(nix);
with nametable[nix] do begin
context:=set_type;
min:=lower; max:=upper;
size:=words*2;
dynamic:=false;
end;
end;
procedure pool_def;
var data_size: integer;
begin
with nametable[stack[t]] do begin
data_size:=size;
if dynamic then begin
error(error_dyn);
data_size:=0;
end;
end;
t:=t-1;
push_name(nix);
with nametable[nix] do begin
context:=pool_type;
size:=semaphor_length;
min:=take_expr;
if min<=0 then begin
error(pool_def_error); min:=1;
end;
max:=data_size;
dynamic:=false;
end;
end;
procedure routine_def(m: block_mode);
begin
push_name(nix);
with nametable[nix] do begin
context:=routine_type;
niv:=current_niv;
lix:=current_lix;
current_lix:=current_lix+1;
end;
push_level(m);
idcount:=0; param_number:=0;
head_line:=source_line;
end;
procedure process_def;
var ty: integer;
begin
get(nix); (*skip nix*)
push_name(nix); get(ty);
with nametable[nix] do
begin
context:=variable;
offset:=alloc_var(nametable[ty].size);
niv:=current_niv;
end;
push_level(process_mode);
idcount:=0; param_number:=0;
head_line:=source_line;
end;
procedure exception_def;
begin
push_name(nix); t:=t-1;
if (* **lambda** *) not versionz80 then
with nametable[nix] do
if niv<0 then begin
put1(zextexception, offset); (* offset is name key *)
end else
put2(zexception,niv,lix);
end;
procedure formal_param(c: context_kind);
var type_nix, parm_size, byte_displ: integer;
begin
type_nix:=stack[t];
if c = value_param then
with nametable[type_nix]do begin
parm_size:=size;
if dynamic then begin
error(error_dyn);
parm_size:=0;
end;
end
else
parm_size:=pointer_length;
byte_displ:=0;
if (* **z80** *) versionz80 then begin
if parm_size=byte_length then parm_size:=word_length;
end else
begin
(* **lambda** *)
if nametable[type_nix].context in index_types then
if parm_size=byte_length then byte_displ:=1;
if odd(parm_size) then parm_size:=parm_size+1;
end;
for i:=idcount downto 1 do
with nametable[stack[t-i]] do begin
context:=c;
niv:=current_niv;
offset:=alloc_var(parm_size);
offset:=offset+byte_displ;
comp_type:=type_nix;
end;
param_number:=param_number+idcount;
idcount:=0; t:=t-1;
end;
procedure name;
var p,q,ch: integer; na: alfa;
begin
get(p); q:=0; na:=' ';
if p>alfalength then begin
q:=p; p:=alfalength;
end;
for i:=1 to p do begin
get(ch);
na[i]:=chr(ch);
end;
if q>0 then
for i:=p+1 to q do get(ch);
if prefixed_name then begin
prefix_name:=na;
prefixed_name:=false;
end
else
ext_name:=na;
end;
procedure new_block;
var op: out_code; parameter_length: integer;
begin
if (* **z80** *) versionz80 then
parameter_length:= - current_offset
else
(* **lambda** *)
parameter_length:=current_offset+1;
display[this_level].parameter_length:=parameter_length;
get(i); (*skip*)
case mode of
proc_mode, func_mode: begin
with nametable[stack[t-param_number]] do begin
if prefixed then begin
put0(zmodule); out_name(prefix_name);
put_arg1(param_number);
out_formal_list;
prefixed:=false;
end;
size:=parameter_length-activation_record_length;
if mode=proc_mode then op:=zproc else op:=zfunc;
put1(op,lix);
out_name(ext_name);
put_arg1(parameter_length);
put1(zblock,current_niv);
end;
end;
process_mode: begin
with nametable[stack[t-param_number]] do begin
put1(zprocess,offset); out_name(ext_name);
put_arg2(parameter_length,param_number);
end;
out_formal_list;
put1(zblock, 0);
end;
end;
t:=t-param_number-1; param_number:=0;
var_length:=0;
end;
procedure external_;
var op: out_code; not_std: boolean;
begin
not_std:=true;
case mode of
proc_mode, func_mode:
with nametable[stack[t-param_number]] do begin
not_std:=niv>=0;
if (* **z80** *) versionz80 then
size:= - current_offset - activation_record_length
else
(* **lambda** *)
size:=current_offset+1-activation_record_length;
if not_std then begin
niv:=-1;
if mode=proc_mode then op:=zextproc else op:=zextfunc;
put1(op, name_key); out_name(ext_name);
offset:=name_key;
name_key:=name_key+1;
end;
end;
process_mode:
if prelude then error(prelude_error)
else
with nametable[stack[t-param_number]] do
begin put1(zextprocess,offset); out_name(ext_name); end;
end;
if not_std then begin
put_arg1(param_number); out_formal_list;
end;
pop_level;
t:=t-param_number-1; param_number:=0;
end;
procedure forward_;
begin
with nametable[stack[t-param_number]] do
size:=current_offset;
pop_level;
t:=t-param_number-1; param_number:=0;
idcount:=0;
end;
procedure previous_forward(m: block_mode);
begin
push_level(m);
param_number:=0;
push_name(nix);
current_offset:=nametable[nix].size;
head_line:=source_line;
end;
procedure end_block;
var l,i: integer;
begin
if (* **z80** *) versionz80 then
var_length:=var_length - display[this_level].parameter_length
else
begin
(* **lambda** *)
var_length:=var_length+1-display[this_level].parameter_length;
end;
if odd(var_length) then var_length:=var_length+1;
put1(zlength,var_length);
out_constant_area;
l:=current_lix - 1;
if l > top_lix then top_lix:=l;
pop_level;
if this_level=0 then begin
out_constant_area;
if test_survey then begin
top_nix:=0;
for i:=0 to max_name_index do
if nametable[i].context<>not_used then top_nix:=top_nix+1;
writeln(' 4. ', top_nix:5, top_t:5, top_ops:5, top_ss:5,
top_c:5, top_level:5, top_lix:5);
end;
if (ot<>empty_stack) or (t<>0) or (ss<>0) then abort(stack_error);
for i:=0 to max_name_index do
with nametable[i] do
if lix > 0 then
lix:=-lix; (*mark the name as unused *)
end;
put2(zendblock, current_lix, l);
end;
procedure begin_code;
begin
if ops[ot].context <> sconst then error(var_error);
put1(zbegincode,ops[ot].offset);
pop;
end;
procedure code_line;
var i,no,ch: integer;
begin
get(no);
put1(zcodeline,no);
for i:=1 to no do begin
get(ch);
put_arg1(ch);
end;
end;
procedure init_values(nix,vniv,voffset: integer);
var varvalue,typ: integer;
begin
if prelude then error(prelude_error);
with ops[ot] do if context=struc_c then context:=lconst;
with nametable[nix] do
if context in simple_types then begin
if ops[ot].context<>sconst then
error(var_error) else
begin
varvalue:=ops[ot].offset;
if (varvalue<min) or (varvalue>max) then
error(type_error) else
begin
if varvalue>max_int-1 then error(overflow);
put0(zinitialize); put2(zaddr,vniv,voffset);
if context=bool_type then typ:=bool_typ
else if size=word_length then typ:=int_typ
else typ:=scalar_typ;
put2(zsimpleinit,typ,varvalue);
end
end;
end else
if ops[ot].context=lconst then begin
if ops[ot].niv<0 then constant_used(ot);
put0(zinitialize); put2(zaddr,vniv,voffset);
put2(zstrucinit,size,ops[ot].niv);
end else
if ops[ot].context=set_const then begin
if ops[ot].niv<0 then constant_used(ot);
put0(zinitialize); put2(zaddr,vniv,voffset);
put3(zsetinit,size,ops[ot].niv,ops[ot].size);
end
else error(var_error);
end;
procedure component_init(type_nix: integer);
var field_nix, w_offset,s: integer;
begin
with nametable[type_nix] do
if context = sys_record_type then begin
field_nix:=next_comp;
while field_nix <> 0 do
with nametable[field_nix] do begin
if context = field then
put1(zfieldinit, offset)
else
put2(zdynfieldinit, niv, offset);
component_init(comp_type);
field_nix:=next_comp;
end; (*with*)
put0(zendinitfields);
end (*record*)
else
if context = sys_array_type then begin
w_offset:=alloc_temp(word_length);
s:=nametable[next_comp].size;
if (* **lambda** *) not versionz80 then
if odd(s) then s:=s+1;
if dynamic then
put3(zarraydyninit, w_offset, niv, offset)
else
put4(zarrayinit, w_offset, min, max, s);
component_init(next_comp);
release_temp(word_length);
end (*array*)
else
if context = pool_type then
put2(zpoolinit, min, max)
else
if (* **z80** *) versionz80 then
compiler_error(addr_error)
else
(* **lambda** *)
put1(zvarinit, type_o(context));
end; (*component init*)
procedure system_init(type_nix, voffset: integer);
begin
with nametable[type_nix] do begin
if dynamic then
put1(zsysdyninit, voffset)
else
put1(zsysinit, voffset);
end;
component_init(type_nix);
end; (*system init*)
procedure var_list;
var type_nix, var_size, type_niv, type_offset: integer;
init, allign, dyn: boolean;
begin
type_nix:=stack[t];
with nametable[type_nix] do begin
var_size:=size;
allign:=context in init_types;
init:= allign and not prelude;
type_niv:=niv; type_offset:=offset;
dyn:=dynamic;
if context = dyn_subrange then dyn:=false;
end;
for i:=idcount downto 1 do
with nametable[stack[t-i]] do begin
if dyn then begin
context:=dyn_variable;
niv:=current_niv;
offset:=alloc_var(pointer_length);
put3(zallocdynvar, offset, type_niv, type_offset);
end
else
begin
if allign then word_allign;
context:=variable;
niv:=current_niv;
offset:=alloc_var(var_size);
end;
if variable_init then begin
if dyn then error(error_dyn_init)
else
init_values(type_nix, niv, offset);
end;
if init then system_init(type_nix, offset);
end;
t:=t-idcount-1; idcount:=0;
if variable_init then pop; (*init value*)
variable_init:=false;
end;
procedure end_export;
var typ, val: integer;
begin
with ops[ot] do begin
if field_packed then error(field_export_error);
case export_kind of
exportvalue: begin
if context<>sconst then error(exportvalue_error);
typ:=value_type;
val:=offset;
end;
exportsize: begin
typ:=value_type;
val:=size;
end;
exportdispl: begin
typ:=value_type;
val:=field_offset;
end;
exportaddr,
exportoffset: begin
if not ( context in var_types ) then error(exportaddr_error);
if export_kind=exportaddr then
typ:=offset_type else typ:=value_type;
val:=offset+field_offset;
end;
end;(*case*)
end;(*with*)
put0(zexport); out_name(ext_name);
put_arg2(typ, val);
pop;
export:=false;
field_offset:=0;
end;(*end export*)
procedure new_label;
begin
push_name(nix);
with nametable[nix] do begin
context:=label_type;
lix:=current_lix;
current_lix:=current_lix+1;
end;
t:=t-1;
end;
procedure const_def;
begin
push_name(nix);
with ops[ot] do begin
if context=struc_c then context:=lconst;
if (context<>sconst) and (context<>lconst) and (context<>set_const) then begin
error(var_error);
context:=sconst; size:=0; niv:=0;
offset:=0;
end;
end;
with nametable[nix] do begin
context:=ops[ot].context;
size:=ops[ot].size;
niv:=ops[ot].niv;
offset:=ops[ot].offset;
if offset>max_int-1 then begin
offset:=max_int-1;
error(overflow);
end;
end;
pop;
t:=t-1;
end;
procedure load_var(op: out_code);
var load_type: integer;
begin
with ops[ot] do begin
if kind in simple_types then begin
if field_packed then
put3(op, field_typ,first, comp_size)
else
begin
if size=byte_length then load_type:=byte_typ else
load_type:=word_typ;
put1(op,load_type);
end
end
else
if kind=pointer_type then put1(op,type_pointer)
else
if kind=set_type then begin
put2(op,set_typ,size);
end
else
begin
if dynamic then
with nametable[type_nix] do
put3(op, dyn_typ, niv, offset)
else
put2(op, addr_typ, size);
end;
end;
end;
procedure get_pushed_consts;
var p: integer; stop: boolean;
begin
p:=ot;
repeat
p:=p-1;
if p>first_of_expr then
begin
with ops[p] do if context=struc_c then context:=lconst;
stop:= (ops[p].context <> sconst) and (ops[p].context <> lconst)
end
else stop:=true;
until stop;
for i:=p+1 to ot-1 do
with ops[i] do begin
if context=sconst then begin
if offset>max_int-1 then error(overflow);
put1(zconst,offset);
if size=byte_length then size:=word_length;
end
else begin
if niv<0 then constant_used(i);
put2(zlconst,niv,size);
end;
state:=expression; context:=expr;
end;
end;
procedure address;
begin
get_pushed_consts;
with ops[ot] do if context=struc_c then context:=lconst;
with ops[ot] do begin
case state of
direct: if context=lconst then
begin
if niv<0 then constant_used(ot);
put1(zcaddr,niv);
end
else
if (context=sconst) or (context=set_const) then begin
compiler_error(addr_error);
put2(zaddr,0,0);
end else
put2(zaddr,niv,offset);
indirect: begin
put2(zaddr,niv,offset); put0(zindaddr);
end;
addr, p_comp: ;
expression: compiler_error(addr_error);
end;
state:=addr; context:=expr;
end;
end;
procedure load_operand;
begin
if ( ops[ot].context<>sconst ) and
( ops[ot].context<>struc_c) and
(ops[ot].context<>lconst ) then begin
get_pushed_consts;
with ops[ot] do begin
case state of
direct: if context=set_const then
begin
if niv<0 then constant_used(ot);
put2(zsetconst,niv,size);
end
else
begin put2(zaddr, niv, offset); load_var(zindvar); end;
indirect: begin
put2(zaddr,niv,offset); put0(zindaddr);
load_var(zindvar);
end;
addr: load_var(zindvar);
expression, p_comp: ;
end; (*case*)
if kind in index_types then
if size=byte_length then size:=word_length;
state:=expression; context:=expr;
end; (*with*)
end; (*if*)
end;
procedure load_expr;
begin
with ops[ot] do begin
if context=struc_c then context:=lconst;
if (context=lconst) or (context=set_const) then
if niv<0 then constant_used(ot);
if context=sconst then begin
if offset>max_int-1 then error(overflow);
put1(zconst,offset);
end
else
if context=lconst then put2(zlconst,niv,size)
else
if context=set_const then put2(zsetconst,niv,size)
else
load_operand;
if size=byte_length then size:=word_length;
state:=expression; context:=expr;
end;
end;
procedure pass_expr(op: out_code);
begin
load_expr; pop;
put0(op);
end;
procedure pass_addr(op: out_code);
begin
address; pop;
put0(op);
end;
procedure arithmetic(op: out_code);
var f,typ: integer;
begin
if ( ops[ot].context=sconst ) and
( ops[os].context=sconst ) then begin
f:=ops[ot].offset; pop;
with ops[ot] do begin
case op of
zand: if (offset=1) and (f=1) then offset:=1 else offset:=0;
zor: if (offset=0) and (f=0) then offset:=0 else offset:=1;
zxor: if offset = f then offset := 0 else offset := 1;
zadd: offset:=int_add(offset,f);
zsub: offset:=int_add(offset,-f);
zmul: offset:=int_mul(offset,f);
zdiv: offset:=offset div f;
zmod: offset:=offset mod f;
end;
end;
end
else
begin
load_expr;
pop;
with ops[ot] do begin
case kind of
bool_type: typ:=bool_typ;
set_type: typ:=setof_typ;
end
otherwise typ:=int_typ;
put0(op);
if (op=zmul) or (op=zadd) or (op=zsub) then
put_arg1(typ);
if size=byte_length then size:=word_length;
context:=expr; state:=expression;
end;
end;
end;
procedure neg_not(op: out_code);
var typ : integer;
begin
with ops[ot] do
if context=sconst then begin
case op of
zneg: offset:=-offset;
znot: if offset=0 then offset:=1 else offset:=0;
end;
end
else begin
load_operand;
with ops[ot] do begin
put0(op);
if op = znot then begin
if kind = bool_type then typ := bool_typ else typ:=int_typ;
put_arg1(typ);
end;
if size=byte_length then size:=word_length;
context:=expr; state:=expression;
end;
end;
end;
procedure equality(op: integer);
var f,q,n,op1,p,op1_size,op2_size,last,n1: integer;
bo, remove1, remove2: boolean;
begin
if (ops[ot].context=sconst) and
(ops[os].context=sconst) then begin
f:=ops[ot].offset; pop;
with ops[ot] do begin
case op of
zne: bo:=offset<>f;
zeq: bo:=offset=f;
zle: bo:=offset<=f;
zge: bo:=offset>=f;
zlt: bo:=offset<f;
zgt: bo:=offset>f;
end; (*case*)
if bo then offset:=1 else offset:=0;
kind:=bool_type; size:=word_length;
end; (*with*)
end
else
begin
remove1:=ops[ot].context=struc_c;
if remove1 then ops[ot].context:=lconst;
remove2:=ops[os].context=struc_c;
if remove2 then ops[os].context:=lconst;
if ((op=zne) or (op=zeq)) and
(ops[ot].context=lconst) and
(ops[os].context=lconst) then begin
op1_size:=ops[os].size;
op2_size:=ops[ot].size;
n:=op1_size;
if n>op2_size then n:=op2_size;
n1:=n;
p:=ops[ot].offset; pop;
with ops[ot] do begin
n:=(n+1) div 2 -1; q:=offset;
bo:=true;
for i:=0 to n do
bo:=bo and (c[i+p]=c[i+q]);
if op1_size>op2_size then begin
for i:=n to (op1_size+1)div 2 - 1 do bo:=bo and (c[i+q]=spsp);
end
else
if op2_size>op1_size then begin
for i:=n to (op2_size+1)div 2 - 1 do bo:=bo and (c[i+p]=spsp);
end;
case op of
zeq: if bo then offset:=1 else offset:=0;
zne: if bo then offset:=0 else offset:=1;
end;
kind:=bool_type; size:=word_length;
context:=sconst;
end; (*with*)
if remove1 then remove_constant(p);
if remove2 then remove_constant(q);
end
else begin
with ops[ot] do
if (kind=array_type) and (context=lconst) then adjust_string(ot,os);
with ops[os] do
if (kind=array_type) and (context=lconst) then adjust_string(os,ot);
load_expr; pop;
with ops[ot] do
case kind of
int_type,char_type,bool_type,scalar_type:
put1(zcompare,op);
pointer_type, array_type, record_type, sys_array_type, sys_record_type:
begin
if op=zeq then op1:=zeq_struc
else op1:=zne_struc;
if dynamic then
with nametable[type_nix] do
put3(zcompdynstruc, op1, niv, offset)
else
put2(zcompstruc,op1,size);
end;
set_type: begin
case op of
zeq: op1:=zeq_set;
zne: op1:=zne_set;
zle: op1:=zle_set;
zge: op1:=zge_set;
end;
put1(zcompare,op1);
end;
end otherwise compiler_error (var_error);
with ops[ot] do begin
kind:=bool_type; size:=word_length;
context:=expr; state:=expression;
end;
end;
end
end;
procedure inclusion;
begin
if stat_part then begin
load_expr; pop;
with ops[ot] do begin
put1(zcompare,zin);
kind:=bool_type; size:=word_length;
context:=expr; state:=expression;
end;
end else begin
error(var_error);
pop;
end;
end;
procedure range;
var a,b: integer; dyn : boolean;
begin
get(nix);
with nametable[nix] do begin
a:=min; b:=max; dyn:=dynamic;
end;
if dyn then begin
if ops[ot].context = sconst then begin
push; get_pushed_consts; pop;
end;
load_operand;
if index_check then
with nametable[nix] do
put2(zdynrangetest, niv, offset+2);
end
else
with ops[ot] do
if context=sconst then begin
if (offset<a) or (offset>b) then begin
error(type_error); offset:=a;
end;
end else begin
load_operand;
if index_check then
with nametable[nix] do begin
if lix<0 then begin
lix:=-lix;
alloc_range_descr(lix,min,max);
end;
put1(zrangetest,lix);
end;
end;
end;
procedure func_call;
var p,q,result_size,std,alloc_size: integer;
begin
push;
get_pushed_consts;
get(nix); std:=0;
with nametable[nix] do
if niv<0 then begin (*external or std function *)
std:=-niv-1;
if niv=-1 then begin
put1(zextfunccall, offset); (* offset = name key *)
end else put1(zstdfunccall, std );
end
else put2(zfunccall,niv,lix);
push_name(nix); t:=t-1;
get(p);
if std>0 then
begin
case std of
zsucc: put_arg1(nametable[p].max);
zpred: put_arg1(nametable[p].min);
end;
end;
with nametable[nix] do begin
with nametable[p] do begin
result_size:=size;
if dynamic and (context<>dyn_subrange) then error(error_dyn);
end;
context:=func_result;
niv:=current_niv;
if (* **z80** *) versionz80 then begin
if result_size=byte_length then
alloc_size:=result_size+1 else alloc_size:=result_size;
end
else
(* **lambda** *)
if odd(result_size) then
alloc_size:=result_size+1 else alloc_size:=result_size;
q:=alloc_temp(alloc_size);
offset:=q;
end;
with ops[ot] do begin
type_nix:=p;
var_nix:=nix;
kind:=nametable[p].context;
niv:=current_niv; context:=func_result;
offset:=q; size:=result_size;
lix:=nametable[p].lix;
array_packed:=nametable[p].packed_comp;
field_packed:=false;
func_value:=std=0;
state:=direct;
temp_size:=alloc_size;
dynamic:=false;
end;
end;
procedure end_func_call;
begin
if ops[ot].func_value then begin
load_operand;
end
else
with ops[ot] do begin
if size=byte_length then size:=word_length;
state:=expression; context:=expr;
end;
put0(zendfunccall);
release_temp(ops[ot].temp_size);
end;
procedure proc_call;
begin
get(nix);
with nametable[nix] do
if niv<0 then begin (* external *)
put1(zextproccall, offset); (* offset = name_key *)
end
else put2(zproccall,niv,lix);
end;
procedure actual;
begin
get(nix); push;
with nametable[nix] do begin
ops[ot].dynamic := false;
ops[ot].type_nix:=comp_type;
ops[ot].var_nix:=nix;
ops[ot].kind:=nametable[comp_type].context;
ops[ot].size:=nametable[comp_type].size;
ops[ot].context:=context; (*save parameter type*)
case context of
var_param: put0(zvarparam);
value_param: begin
put0(zvalueparam);
with nametable[comp_type] do
case context of
int_type, char_type, bool_type, scalar_type: put_arg1(word_typ);
pointer_type: put_arg1(type_pointer);
set_type: put_arg2(set_typ,size);
end
otherwise put_arg2(addr_typ,size);
end;
end;
end;
end;
procedure end_actual;
begin
with ops[ot] do begin
if context=struc_c then context:=lconst;
if (context=lconst) and (kind=array_type) then
if ops[os].size<>size then adjust_string(ot,os);
end;
with ops[os] do
case context of
value_param: load_expr;
var_param: address;
end;
pop; (* expr or addr *)
pop; (* saved parameter type *)
end;
procedure label_goto(op: out_code);
begin
get(nix);
with nametable[nix] do put1(op,lix);
end;
procedure becomes;
begin
address;
with ops[ot] do
if (kind=ref_type) or (kind=shadow_type) then
put1(zleft,type_pointer)
else
if field_packed then
put3(zleft,field_typ,first,comp_size)
else
load_var(zleft);
end;
procedure assign;
begin
with ops[ot] do begin
if context=struc_c then context:=lconst;
if (kind=array_type) and (context=lconst) then adjust_string(ot,os);
end;
load_expr; (* right hand side *)
pop; (*right hand side*)
pop; (*left hand side*)
put0(zassign);
end;
procedure case_label;
begin
with ops[ot] do
if context=sconst then begin
if offset>max_int-1 then error(overflow);
put1(zcaselabel,offset);
end
else begin
error(var_error); put1(zcaselabel,0);
end;
pop;
end;
procedure caserange;
var last,first: integer;
begin
if (ops[ot].context<>sconst) or (ops[os].context<>sconst) then
begin
error(var_error); last:=0; first:=0;
end else begin
first:=ops[os].offset;
last:=ops[ot].offset;
if last>max_int-1 then error(overflow);
end;
pop; pop;
if last<first then
begin first:=last; error(range_error); end;
put2(zcaserange,first,last);
end;
procedure for_;
var load_type,temp: integer;
begin
address; (*control var addr*)
with ops[ot] do begin (*push temp control var*)
if kind in simple_types then begin
if size=byte_length then load_type:=byte_typ
else load_type:=word_typ;
end
else compiler_error(for_error);
kind:=pointer_type;
context:=variable;
niv:=current_niv;
size:=pointer_length;
offset:=alloc_temp(size);
temp:=alloc_temp(word_length);
state:=indirect;
put3(zleftfor,offset,temp,load_type);
end;
end;
procedure up_down(mode: integer);
begin
load_expr; pop; (*load from expr value*)
ops[ot].lix:=mode; (*set mode in temp control var addr*)
put0(zforstore);
end;
procedure for_do;
var m:integer;
begin
load_expr; pop; (*load to expression value*)
with ops[ot] do begin
if lix=1 then m:=zup else m:=zdown;
end;
put1(zdo,m); pop;
end;
procedure end_for;
var m: integer;
begin
put0(zendfor);
release_temp(pointer_length+word_length);
end;
procedure with_;
begin
put0(zwithstat);
waiting_with:=false;
end;
procedure with_var_;
begin
if waiting_with then
with ops[ot] do begin
get(nix);
nametable[nix].context:=context;
nametable[nix].niv:=niv;
nametable[nix].offset:=offset;
waiting_with:=false;
end
else
begin
push_name(nix); t:=t-1;
with nametable[nix] do begin
context:=with_var;
niv:=current_niv;
offset:=alloc_temp(pointer_length);
put1(zwithvar,offset);
end;
end;
end;
procedure end_with;
begin
with ops[ot] do
if state=addr then begin
put0(zendwith);
release_temp(pointer_length);
end;
pop;
end;
procedure lock_var_;
begin
stat_part:=false;
push_name(nix);
address; pop;
end;
procedure lock_type;
var type_size, type_niv, type_offset : integer;
dyn : boolean;
begin
with nametable[ stack[t] ] do begin
type_size:=size;
dyn:=dynamic;
type_niv:=niv;
type_offset:=offset;
end;
t:=t-1;
with nametable[stack[t]] do begin
context:=lock_var;
niv:=current_niv;
offset:=alloc_temp(pointer_length);
if dyn then
put3(zlockdynvar, type_niv, type_offset, offset)
else
put2(zlockvar, type_size, offset);
end;
t:=t-1;
stat_part := true;
end;
procedure end_lock;
begin
put0(zendlock);
release_temp(pointer_length);
end;
procedure chan_var;
var temp: integer;
begin
address; pop;
put0(zchanvar);
end;
procedure end_channel;
begin
put0(zendchannel);
end;
procedure var_pointer;
begin
get(nix);
with nametable[nix] do
put2(zvarpointer,niv,offset);
push_name(nix);
with nametable[nix] do begin
context:=variable;
niv:=current_niv;
offset:=alloc_temp(pointer_length);
put_arg1(offset);
end;
end;
procedure tempointer;
var p: integer;
begin
p:=alloc_temp(pointer_length);
put1(ztempointer,p);
end;
procedure arglist_size;
var p: integer;
begin
p:=alloc_temp(word_length);
put1(zarglistsize,p);
if (* ***z80** *) versionz80 then
nametable[ stack[ t] ].offset:=p;
t:=t-1; (* pop name stack *)
end;
procedure end_proc;
var i,n: integer;
begin
put0(zendpcall);
get(n); (* number of process param lists*)
for i:=1 to n do begin
release_temp(process_param_length);
put0(zendprocessparam);
end;
end;
procedure end_func;
var i,n: integer;
begin
put0(zfcall);
get(n); (* number of process param lists *)
for i:=1 to n do
with ops[ot] do begin
temp_size:=temp_size + process_param_length;
put0(zendprocessparam);
end;
end;
procedure var_ref;
begin
get(nix);
with nametable[nix] do begin
ops[ot].var_nix:=nix;
ops[ot].context:=context;
if context=lconst then ops[ot].size:=size;
ops[ot].niv:=niv;
ops[ot].offset:=offset;
ops[ot].first:=min;
ops[ot].comp_size:=max;
if (context <> field) and (context <> dyn_field) then
ops[ot].field_packed:=false
else
ops[ot].field_packed:=packed_comp;
end;
end;
procedure type_ref;
begin
get(nix);
with nametable[nix] do begin
ops[ot].type_nix:=nix;
ops[ot].kind:=context;
ops[ot].lix:=lix;
if ops[ot].context<>lconst then
ops[ot].size:=size;
if context <> array_type then
ops[ot].array_packed:=false
else
ops[ot].array_packed:=packed_comp;
ops[ot].dynamic:=dynamic;
end;
end;
procedure var_;
begin
push;
var_ref; type_ref;
with ops[ot] do begin
if context in indirects then
state:=indirect else state:=direct;
end;
end;
procedure field_;
var c: context_kind; p: integer;
begin
if export then
with ops[ot] do begin
c:=context; p:=offset;
var_ref; type_ref;
if context <> field then error(error_dyn);
context:=c;
field_offset:=field_offset+offset;
offset:=p;
end
else
begin
if waiting_with then with_;
address;
var_ref; type_ref;
with ops[ot] do begin
if context = field then
put1(zfield, offset)
else
put2(zdynfield, niv, offset);
state:=addr;
end;
end;
end;
procedure arrow;
begin
if waiting_with then with_;
address;
put0(zindaddr);
ops[ot].state:=addr;
type_ref;
end;
procedure index_expr;
begin
if waiting_with then with_;
address;
with ops[ot] do
if array_packed then put0(zpackedarr)
else put0(zindexexpr);
end;
procedure index;
var nix, e: integer; pa : boolean;
begin
load_expr; (*load index value*)
pop; (*index value*)
get(nix); (* array type nix *)
with nametable[nix] do begin
if dynamic then
put2(zindex, niv, offset+2)
else
begin
if lix < 0 then begin (* alloc dope vector *)
lix:=-lix;
alloc_dope(lix, min, max, niv);
end;
put1(zcindex, lix);
end;
pa:=packed_comp;
end;
type_ref;
if pa then
with ops[ot] do begin
state:=p_comp; size:=word_length;
end;
end;
procedure literal;
var ty,l,clix,c_index,ch1,ch2,ch,val,base: integer;
begin
get(ty); get(l);
case ty of
string_const: begin
alloc_constant(clix,c_index,l);
for i:=c_index to c_index+l div 2-1 do begin
get(ch1); get(ch2);
if (* **z80** *) versionz80 then
c[i]:=ch2*shift8 + ch1
else
(* **lambda** *)
c[i]:=ch1*shift8+ch2;
end;
if l mod 2 <> 0 then begin
get(ch);
i:=c_index + l div 2;
if (* **z80** *) versionz80 then
c[i]:=ord(' ')*shift8 + ch
else
(* **lambda** *)
c[i]:=ch*shift8+ord(' ');
end;
push;
with ops[ot] do begin
var_nix:=-1;
type_nix:=-1;
kind:=array_type; niv:=clix;
offset:=c_index; size:=l;
context:=struc_c; state:=direct;
dynamic:=false;
end;
end;
char_const: begin
get(ch);
push;
with ops[ot] do begin
type_nix:=-1;
var_nix:=-1;
kind:=char_type;
offset:=ch; size:=char_length;
context:=sconst; state:=direct;
dynamic:=false;
end;
end;
num_const: begin
get(ch); val:=0; base:=10;
if ch=ord("#") then begin
get(ch); l:=l-2;
if ch=ord("b") then base:=2
else if ch=ord("o") then base:=8
else if ch=ord("h") then base:=16
else error(literal_error);
get(ch);
end;
for i:=1 to l do begin
if ch<=ord("9") then ch:=ch-ord("0")
else if ch>=ord("a") then ch:=ch-ord("a")+10;
if (ch<0) or (ch>=base) then begin
error(literal_error);
ch:=0;
end;
if base=10 then
val:=int_add(int_mul(val,base),ch)
else
begin
val:=val*base+ch;
if val div shift16 <> 0 then begin
error(literal_error);
val:=0;
end;
end;
if i<l then get(ch);
end;
if base<>10 then
if val>max_int then val:=val + bit_0_8;
push;
with ops[ot] do begin
type_nix:=-1;
var_nix:=-1;
kind:=int_type; offset:=val;
context:=sconst; state:=direct;
size:=word_length;
dynamic:=false;
end;
end;
end;
end;
procedure new_set;
begin
push;
get_pushed_consts;
if stat_part then begin
put0(zset);
with ops[ot] do begin
kind:=set_type; context:=expr;
size:=0;
state:=expression;
end
end
else
begin
with ops[ot] do begin
kind:=set_type;
size:=set_const_length*2;
alloc_constant(niv,offset,size);
context:=set_const; first:=0;
state:=direct;
dynamic:=false;
end;
end;
end;
procedure set_bit(no: integer); forward;
procedure set_expr;
begin
if stat_part then begin
load_expr; pop;
put0(zsetexpr);
end;
end;
procedure include_int;
var min,max: integer;
begin
if stat_part then begin
load_expr; pop;
put0(zincludeint);
end else begin
max:=take_expr; min:=take_expr;
if (min<0) or (min>max_set_const_value) then begin
error(set_error);
min:=0;
end;
if (max>max_set_const_value) then begin
error(set_error);
max:=min;
end;
for i:=min to max do set_bit(i);
end;
end;
procedure include;
var v: integer;
begin
if stat_part then begin
load_expr; pop;
put0(zinclude);
end else begin
v:=take_expr;
if (v<0) or (v>max_set_const_value) then begin
error(set_error);
v:=0;
end;
set_bit(v);
end;
end;
procedure set_bit(no: integer);
var bit,word: integer;
begin
bit:=no mod bits_pr_word;
word:=ops[ot].offset + no div bits_pr_word;
if ( c[word] div shift_to[bit] ) mod 2 = 0 then
c[word]:=c[word] + shift_to[bit];
with ops[ot] do
if first<no then first:=no;
end;
procedure end_set;
var words: integer;
begin
get(nix);
if stat_part then
put0(zendset)
else
with ops[ot] do begin
(* offset is index in c -- first is max value of expr *)
words:=(first + 1 + bits_pr_word - 1) div bits_pr_word;
if words=0 then words:=1;
size:=words*2;
cut_constant(offset,words);
with nametable[nix] do begin
context:=set_type;
size:=words*2;
min:=0; max:=ops[ot].first;
end;
end;
end;
procedure null;
begin
push;
with ops[ot] do begin
kind:=int_type; offset:=0;
size:=0; context:=sconst;
state:=direct;
end;
end;
procedure struc_const;
begin
ss:=ss+1; (* push const level *)
if ss > top_ss then top_ss:=ss;
get(nix);
with nametable[nix], struc_init[ss] do begin
saved_nix:=nix;
alloc_constant(saved_lix,first,size);
first:=first*2; displ:=first;
saved_size:=size;
saved_stat_part:=stat_part;
stat_part:=false;
dope_lix:=lix;
times:=1;
if context in array_types then begin
if packed_comp then begin
init_mode:=packed_array;
elem_pr_word:=niv div shift8;
bits_pr_field:=niv mod shift8;
end else
init_mode:=array_init;
current_index:=0; top_index:=max-min+1;
end else
init_mode:=record_init;
if dynamic then begin
error(error_dyn);
init_mode:=error_init;
end;
end;
end;
procedure end_struc;
begin
push;
with ops[ot], struc_init[ss] do begin
if init_mode=record_init then
kind:=record_type else kind:=array_type;
array_packed:=init_mode = packed_array;
field_packed:=false;
lix:=dope_lix;
size:=saved_size;
state:=direct;
offset:=first div 2;
niv:=saved_lix;
context:=struc_c;
var_nix:=-1;
type_nix:=saved_nix;
dynamic:=false;
if init_mode <> error_init then
if init_mode<>record_init then
begin
if current_index<>top_index then error(const_error);
end;
stat_part:=saved_stat_part;
end;
ss:=ss-1; (*pop const level*)
end;
procedure times_;
begin
with struc_init[ss] do begin
times:=take_expr;
if init_mode <> error_init then
if (times<0) or (current_index+times>top_index) then begin
error(const_error);
times:=top_index-current_index;
end;
end;
end;
procedure put_byte(val, addr: integer);
var sh, w: integer;
begin
if (* **z80** *) versionz80 then begin
if odd(addr) then sh:=shift8 else sh:=1
end
else
begin
(* **lambda** *)
if odd(addr) then sh:=1 else sh:=shift8
end;
w:=addr div 2;
c[w]:=c[w] + val*sh;
end; (*put byte*)
procedure put_word(val, addr: integer);
var w: integer;
begin
w:=addr div 2;
if (* **z80** *) versionz80 then begin
if odd(addr) then begin
c[w]:=c[w] + (val mod shift8) * shift8;
c[w+1]:=c[w+1] + val div shift8;
end
else c[w]:=val + c[w];
end
else
begin
(* **lambda** *)
if odd(addr) then begin
if val < 0 then val:=val + 65536;
c[w]:=c[w] + val div shift8;
c[w+1]:=c[w+1] + (val mod shift8) * shift8;
end
else
c[w]:=val+c[w];
end;
end;(*put word*)
procedure get_byte(var val: integer; addr: integer);
var q, w: integer;
begin
w:=addr div 2;
q:=c[w];
if (* **z80** *) versionz80 then begin
if odd(addr) then
val:=q div shift8
else
val:=q mod shift8;
end
else
begin
(* **lambda** *)
if odd(addr) then
val:=q mod shift8
else
val:=q div shift8
end;
end;(*get byte*)
procedure put_constant(var displ: integer; times,const_size: integer);
var dsize,val,p,c_index,sh,rest,q,v: integer; con: context_kind;
remove, fill: boolean;
begin
with ops[ot] do begin
dsize:=size; val:=offset;
con:=context;
end;
if con=struc_c then begin
c_index:=val;
remove:=true; con:=lconst;
end else remove:=false;
pop;
if (con<>sconst) and (con<>lconst) and (con<>set_const) then begin
error(var_error);
dsize:=0;
end;
for i:=1 to times do begin
if dsize=0 then (*null*) else
if (const_size=byte_length) and (con=sconst) then begin
if (val>max_byte_value) or (val<0) then begin
val:=0;
error(type_error);
end;
put_byte(val, displ);
end else
if (const_size=word_length) and (con=sconst) then
begin
if val>max_int-1 then error(overflow);
put_word(val, displ);
end
else
begin
rest:=const_size; q:=2*val;
if con=set_const then
begin (* adjust set-constants to demanded size *)
if dsize>const_size then error(type_error)
else
if dsize<const_size then
rest:=dsize;
end;
if dsize < rest then begin
rest:=dsize; fill:=true;
end else fill:=false;
p:=displ;
while rest>0 do begin
get_byte(v,q); put_byte(v,p);
p:=p+1; q:=q+1;
rest:=rest-1;
end;
if fill then begin
rest:=const_size - dsize;
while rest > 0 do begin
put_byte(32,p);
p:=p+1; rest:=rest-1;
end;
end;
end;
displ:=displ+const_size;
end; (*for times*)
if remove then remove_const(c_index);
end;
procedure struc;
var first_bit,val,w,q,r,s: integer;
begin
get(nix);
with struc_init[ss], nametable[nix] do begin
case init_mode of
array_init: begin
if current_index+times>top_index then begin
times:=0;
error(const_error);
end;
s:=size;
if (* **lambda** *) not versionz80 then
if size>2 then
if odd(size) and (context in init_types) then
s:=s+1;
put_constant(displ, times, s);
current_index:=current_index+times;
times:=1;
end;
record_init: begin
displ:=first+offset;
if packed_comp then begin
first_bit:=min; bits_pr_field:=max;
with ops[ot] do
if context=sconst then begin
val:=offset;
if bits(val)>bits_pr_field then begin
error(type_error);
val:=0;
end;
end else begin
error(var_error);
val:=0;
end;
pop;
q:=val*shift_to[first_bit+bits_pr_field-1];
put_word(q, displ);
end else
put_constant(displ,1,size);
end;
packed_array: begin
with ops[ot] do
if context=sconst then begin
val:=offset;
if bits(val)>bits_pr_field then begin
error(type_error);
val:=0;
end;
end else begin
error(var_error);
val:=0;
end;
pop;
if current_index+times>top_index then begin
times:=0;
error(const_error);
end;
for i:=1 to times do begin
q:=elem_pr_word;
first_bit:=(current_index mod q)*bits_pr_field;
w:=first + (current_index div q)*2;
r:=val*shift_to[first_bit+bits_pr_field-1];
put_word(r, w);
current_index:=current_index+1;
end; (*for*)
times:=1;
end; (*packed*)
error_init: begin
times:=1;
pop;
end;
end; (*case*)
end; (*with*)
end;
begin
initialize;
repeat
read(pass3file,no);
case convert_in_code[no] of
xactual: actual;
xadd: arithmetic(zadd);
xand: arithmetic(zand);
xarglistsize: arglist_size;
xarraydef: array_def(non_pack);
xarrow: arrow;
xassign: assign;
xassignstat: put0(zassignstat);
xbecomes: becomes;
xbegincode: begin_code;
xblock: new_block;
xboolean: std_name(xboolean);
xcase: begin stat_part:=false; pass_expr(zcase); end;
xcaselabel: case_label;
xcaserange: caserange;
xcasestat: put0(zcasestat);
xchannel: put0(zchannel);
xchanvar: chan_var;
xchar: std_name(xchar);
xchr: std_name(xchr);
xcodeline: code_line;
xconstid: const_def;
xdiv: arithmetic(zdiv);
xdo: for_do;
xdown: up_down(-1);
xelse: put0(zelse);
xendactual: end_actual;
xendblock: end_block;
xendcase: begin stat_part:=true; put0(zendcase); end;
xendcaselist: begin stat_part:=true;
put0(zendcaselist); end;
xendcasestat: begin stat_part:=false; put0(zendcasestat); end;
xendchannel: end_channel;
xendcode: begin put0(zendcode); put2(zendblock,2,1); pop_level; end;
xendexport: end_export;
xendfor: end_for;
xendfunccall: end_func_call;
xendlock: end_lock;
xendprelude: begin word_allign;
source_line:=0;
if (* **lambda** *) not versionz80 then
process_offset:=current_offset; prelude:=false; end;
xendproc: end_proc;
xendrepeat: pass_expr(zendrepeat);
xendset: end_set;
xendstruc: end_struc;
xendwhile: put0(zendwhile);
xendwith: end_with;
xeom: eom;
xeq: equality(zeq);
xerror: begin copy(zerror,2); program_ok:=false; end;
xerrorno: begin copy(zerrorno,1); program_ok:=false; end;
xerrortext: begin copy(zerrortext,1); program_ok:=false; end;
xexception: exception_def;
xexchange: begin pass_addr(zexchange); pop; end;
xexchangestat: put0(zexchstat);
xexportaddr: begin export:=true; export_kind:=exportaddr end;
xexportdispl: begin export:=true; export_kind:=exportdispl end;
xexportoffset:begin export:=true; export_kind:=exportoffset end;
xexportsize: begin export:=true; export_kind:=exportsize end;
xexportvalue: begin export:=true; export_kind:=exportvalue end;
xexpr: first_of_expr:=ot;
xexternal: external_;
xfcall: end_func;
xfield: field_;
xfielddef: field_list;
xfieldid: new_name;
xfor: for_;
xforstat: put0(zforstat);
xforward: forward_;
xfrozendef: redef_type;
xfunccall: func_call;
xfuncid: routine_def(func_mode);
xge: equality(zge);
xgetexpr: load_operand;
xgetvalue: load_operand;
xgoto: label_goto(zgoto);
xgt: equality(zgt);
xif: put0(zif);
xifexpr: pass_expr(zifexpr);
xifstat: put0(zifstat);
xin: inclusion;
xinclude: include;
xincluderange: include_int;
xindex: index;
xindexexpr: index_expr;
xinitblock: begin stat_part:=true; word_allign;
put0(zenddecl);
if (* **z80** *) versionz80 then
i:= - current_offset
else
(* **lambda** *)
i:=current_offset;
if i>var_length then var_length:=i;
end;
xinitconst: variable_init:=true;
xinteger: std_name(xinteger);
xlabel: label_goto(zdeflix);
xle: equality(zle);
xlabelid: new_label;
xliteral: literal;
xlock: lock_type;
xlockstat: put0(zlockstat);
xlockvar: lock_var_;
xlt: equality(zlt);
xmod: arithmetic(zmod);
xmul: arithmetic(zmul);
xname: name;
xne: equality(zne);
xneg: neg_not(zneg);
xnewline: new_line;
xniltype: std_name(xniltype);
xnot: neg_not(znot);
xnull: null;
xoption: set_option;
xor: arithmetic(zor);
xord: std_name(xord);
xotherwise: put0(zotherwise);
xparamid: new_name;
xpackedarraydef: array_def(pack);
xpointerdef: pointer_def;
xpooldef: pool_def;
xpred: std_name(xpred);
xpackedrecord: begin push_level(record_mode); pack_record:=pack end;
xprefix: begin prefixed:=true; prefixed_name:=true; end;
xprocessid: process_def;
xproccall: proc_call;
xprocessparam:begin push; get_pushed_consts; pop; put0(zprocessparam); end;
xprocid: routine_def(proc_mode);
xrange: range;
xreal: std_name(xreal);
xrecdef: record_def;
xrecord: push_level(record_mode);
xredeftype: redef_type;
xreference: std_name(xreference);
xrepeat: put0(zrepeat);
xscalardef: scalar_def;
xscalarid: new_scalar;
xsecfuncid: previous_forward(func_mode);
xsecprocid: previous_forward(proc_mode);
xsemaphore: std_name(xsemaphore);
xset: new_set;
xsetdef: set_def;
xsetexpr: set_expr;
xshadow: std_name(xshadow);
xstringtype: std_name(xstringtype);
xstruc: struc;
xstrucconst: struc_const;
xsub: arithmetic(zsub);
xsubdef: sub_def;
xsucc: std_name(xsucc);
xtempointer: tempointer;
xtimes: times_;
xtype: push_name(nix);
xtypedef: t:=t-1;
xerrortype: std_name(xerrortype);
xundeclid: std_name(xundeclid);
xuntil: put0(zuntil);
xup: up_down(+1);
xvalueparam: formal_param(value_param);
xvar: var_;
xvarparam: formal_param(var_param);
xvarid: new_name;
xvarlist: var_list;
xvarpointer: var_pointer;
xwhile: put0(zwhile);
xwhileexpr: pass_expr(zwhileexpr);
xwith: waiting_with:=true;
xwithvar: with_var_;
xxor: arithmetic(zxor);
end otherwise compiler_error(input_error);
until done;
if test then writeln;
if program_ok then
if (* **z80** *) versionz80 then replace('pass56z80')
else
(* **lambda** *)
replace('platonpass5')
else
writeln('*** compilation terminated after pass4');
end.
«eof»