|
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»