// $Source$ // $Revision$ // $Date$ $use Arithm Box Class Convert Dos List StdIO Table; $use "rfp_helper"; $use "rfpc"; Var? (s.tag t.name), s.tag : \{ SVAR; TVAR; VVAR; EVAR; VAR; Len-Var; }; //***************************** Free indices. ****************************** // //$table Free-Indices; // // //$func Free-Index e.key = s.idx; // //Free-Index e.key, { // : s.idx = s.idx; // 1; //}; // // //$func Set-Index (e.key) s.idx = ; // //Set-Index (e.key) s.idx = ; *************** Functions to deal with sets of variables. **************** $box State; Vars-Copy-State = >; Vars-Set-State s.state = >; Init-Vars = ; // ; $func Normalize-Info e.info t.var = ; Normalize-Info e.info t.var = /* * Если дана длина, приравнять к ней минимум и максимум. */ { e.info : e (Length e.len) e = { e.info : e1 (Min e.min) e2 = { e.min : e.len = e.info; (Min e.len) e1 e2; }; (Min e.len) e.info; } :: e.info, { e.info : e1 (Max e.max) e2 = { e.max : e.len = e.info; e1 e2 (Max e.len); }; e.info (Max e.len); }; e.info; } :: e.info, /* * Если минимум не установлен, установить его, исходя из типа переменной. */ { e.info : e (Min e) e = e.info; t.var : { (SVAR e) = 1; (TVAR e) = 1; (VVAR e) = 1; (EVAR e) = 0; ( VAR e) = 0; } :: s.min = e.info (Min s.min); } :: e.info, /* * Для s- и t-переменных установить максимум, если не установлен. */ { t.var : \{ (SVAR e); (TVAR e); } = { e.info : e (Max e) e = e.info; e.info (Max 1); }; e.info; } :: e.info, /* * Если минимум совпадает с максимумом, то установить длину. * FIXME: не нужно ли здесь упрощать выражения для минимума и максимума? */ { e.info : e (Length e) e = e.info; e.info : e (Max s.max) e, e.info : e (Min s.max) e = e.info (Length s.max); e.info; } :: e.info, /* * Если переменная получила значение, а длина её не была известна, значит * она будет считаться функцией LENGTH в ран-тайм. */ { e.info : e (Length e) e = e.info; e.info : e (Instantiated? True) e = e.info (Length (LENGTH t.var)); e.info; } :: e.info, ; Set-Var e.info t.var, { : $r e1 (t.var e.old-info) e2 = e.old-info (e.info) (/*e.new-info*/) $iter { e.old-info : (t.key e.val) e.rest, { e.info : e3 (t.key e.new-val) e4 = e3 e4 (t.key e.new-val); e.info (t.key e.val); } :: e.info t.item = e.rest (e.info) (e.new-info t.item); } :: e.old-info (e.info) (e.new-info), e.old-info : /*empty*/ = , e.info e.new-info t.var; e.info t.var; } :: e.info t.var = ; Get-Var t.key t.var, : $r e1 (t.var e.info) e2 = { e.info : e (t.key e.val) e = e.val; /*empty*/; }; $func Reset-Var e = e; Vars-Reset e.vars = : e; Reset-Var t.var = { : $r e1 (t.var e.info) e2 = , e.info; /*empty*/; } : { e (Decl s.decl) e = (Decl s.decl); e = /*empty*/; } :: e.decl, ; Gener-Len-Var t.var = : $r e1 (t.var e.info) e2, , (Len-Var t.var); $func Print-Var e = e; //Vars-Print e.vars = ; Vars-Print e.vars = e.vars; Print-Var { t1 = t1; // (s.tag (e.name)) = (s.tag ()); (s.tag s.box) = (s.tag s.box); }; $func Decl-Var e = e; Vars-Decl s.type e.vars = ; Decl-Var s.type t.var, { : s.box; )> :: s.decl, , (Declare s.decl); //! : $r e1 (t.var tag t.min t.max s.decl e.rest) e2 = //! { //! = s.decl; //! )> :: s.decl, //! , //! s.decl; //! } :: s.decl, //! (Declare s.decl); //! //! : e, ; }; Create-Int-Var (e.prefix) t.var e.expr, { t.var : Aux = (VAR ); (VAR ); } :: t.int-var = t.int-var (INT t.int-var e.expr); /* */ Gener-Vars (e.format) e.prefix = { e.format : (s.tag) e.Fe, { s.tag : \{ EVAR; VVAR; TVAR; SVAR; } = (s.tag ) ; (s.tag ) ; }; e.format : (PAREN v1) e2 = (PAREN ) ; e.format : t.Ft e.Fe = t.Ft ; /*empty*/; }; Gener-Err-Var = (EVAR ); Gener-Subst-Vars (e.format) e.prefix = ; Substitutable-Var? (s.tag s.box) = s.tag : \{ EVAR; VVAR; TVAR; SVAR; }, : 0 (Subst) e; /* * (s.tag s.box) -- сгенерированная ранее переменная. * Вместо того, чтобы присвоить её значение переменной t.var, мы подставляем * t.var во все места, гда была использована (s.tag s.box). Таким образом, * t.var получит нужное значение в тот момент, когда выполняется присваивание в * (s.tag s.box). * Если переменная t.var уже была ранее декларирована, чтобы избежать повторной * декларации, делаем декларацию для (s.tag s.box) пустой. * Если же переменная t.var -- новая, то её декларацией становится декларация * (s.tag s.box). */ Gener-Var-Assign t.var (s.tag s.box) = >, { : s = : s.decl-box, ; ) t.var>; }; $box Var-Names; $table Var-Indices; $func Boxes-To-Vars e.expr-with-boxes = e.expr-with-var-names; $func Gener-Name s.form-one? s.name = s.unique-name; Gener-Var-Names expr = , , ; Boxes-To-Vars { (s.tag s.box) expr, s.tag : \{ EVAR; VVAR; TVAR; SVAR; VAR; } = : { 0 e.name = { e.name : (Subst) e.n = e.n; e.name; } :: e.name, (VAR (>)) :: t.var, , t.var ; 1 e.prefix t.var = : { (REF (e s.name)) = s.name; (s (e.name)) = e.name; } :: e.name, (VAR (>)) :: t.var, , t.var ; 2 = ERROR-EXPR ; t.var = ; }; (Declare s.decl) expr = expr>; (e1) e2 = () ; term expr = term ; /*empty*/ = /*empty*/; }; Gener-Name s.form-one? s.name = { ; 0; } : s.idx, <"+" s.idx 1> :: s.idx, , { # \{ s.form-one? : From-One; }, s.idx : 1 = /*empty*/; s.idx; } :: e.idx, :: s.n, { : $r e s.n e = ; , s.n; }; /* * Generates indexes for all variables in e.Format and returns e.Format with all * (?VAR) changed to (?VAR (e.Name)) and s.max. * e.Name is all words from e.prefix plus unical number. Numbers are generated * sequentially starting with s.num. * s.max is the maximum of all generated numbers plus one. * All normal variables from e.Format are returned as they are. */ Gener-Var-Indices s.num (e.Format) e.prefix, { e.Format : t.Ft e.rest, t.Ft : { s.ObjectSymbol = t.Ft ; (REF e) = t.Ft ; (PAREN e.Fe) = :: expr s.num, (PAREN expr) ; (s.VariableTag) = (s.VariableTag (PRAGMA) (e.prefix s.num)) :: t.var, <"+" s.num 1> :: s.num, t.var ; (s.VariableTag e.Name) = t.Ft ; }; /* * e.Format is empty, so return s.num -- the last term in the answer. */ s.num; }; Vars e.expr = e.expr () $iter { e.expr : t.first e.rest, t.first : { s.ObjectSymbol = /*empty*/; (REF t.Name) = /*empty*/; (STATIC t.Name) = /*empty*/; (PAREN e.ResultExpression) = ; (CALL (PRAGMA (e) e) t.Fname e.ResultExpression) = ; (CALL t.Fname e.ResultExpression) = ; t.var = t.var; // t.var ::= (EVAR t.Name) | (VVAR t.Name) // | (TVAR t.Name) | (SVAR t.Name) } :: e.var = e.rest (e.vars e.var); } :: e.expr (e.vars), e.expr : /*empty*/ = e.vars;