// $Source$ // $Revision$ // $Date$ $use "rfpc"; $use "rfp_err"; $use "rfp_list"; $use "rfp_helper"; $use "rfp_check"; $use "rfp_as2as"; $use "rfp_format"; $use StdIO; $use Table; $use Box; $use Arithm; $use Access; $use Compare; $use Convert; $use Class; $use Apply; $use Dos; /* * Tables for storing $const'ant values and their lengthes. */ $table Const-Len; /* * Table for storing object names. */ $table Objects; /* * Table for storing referenced functions. */ $table Ref-To-Funcs; /* * Box for storing function out format */ $box Out-Format; /* * Box for storing names for function result variables */ $box Res-Vars; /* * Following table is used by Gener-Label function for obtaining unical (for * certain function) label name. * e.Key ::= e.QualifiedName (parameter given to Gener-Label) * e.Val ::= [Int] (last index used with such e.QualifiedName) */ $table Labels; //$box Var-Stack; $table Vars-Tab; $box Last-Re; $box Greater-Ineqs; $box Less-Ineqs; $const New-Clash-Tags = Unknown-length Ties Check-symbols Dereference Compare; $table Static-Exprs; $func Compile (e.targets) (e.headers) e.Items = e.Compiled-Items (INTERFACE e.headers); $func Del-Pragmas e.Sentence = e.Sentence; $func Print-Pragma s.channel t.Pragma = ; $func AS-To-Ref e.AS-Expr = e.Refal-Expr; $func Length-of e.Re = e.length; $func Ref-Len t.name = s.length; $func? Hard-Exp? e.expr = ; $func Comp-Func-Stubs = e.asail-funcs; $func Parenthesize-Operators e.Snt = e.Snt; //$func Paren-Op t.Op = t.Op; $func Paren-Op e = e; //$func Get-Hard ... = (e.hard) e.matchings; $func Comp-Func s.tag t.name e.params-and-body = e.compiled-func; $func Post-Comp (e.used-vars) e.comp-func = (e.used-vars) e.result-func; $func Set-Drops (e.declared-exprs) e.comp-func = (e.declared-exprs) e.result-func; $func Comp-Sentence e.Sentence = e.asail-sentence; //$func? Not-Ref? t.var = ; $func? Not-Ref? e = e; //$func? Contents-First? e.list (t.item e) = ; $func? Contents-First? e = e; //$func Zip-With-Vars e.col-vars (t.var (e.Re)) = // (t.var (e.Re) (e.all-collapsed-vars-from-Re)); $func Zip-With-Vars e = e; $func Comp-Ready-Formats e.collapses = e.compiled-assignments (e.rest-collapses) (e.used-aux-vars); //$func? Empty-Varlist? (t.var t.Re (/*empty-var-list*/)) = ; $func? Empty-Varlist? e = e; //$func Remove-Independ e.independ (t.var t.Re (e.var-list)) = // (t.var t.Re (e.new-var-list)); $func Remove-Independ e = e; //$func Get-Aux-Indexes (t (e.Re) t) = e.list-of-lists-of-aux-indexes; $func Get-Aux-Indexes e = e; //$func Get-Var-Index t.var = e.aux-index-or-empty; $func Get-Var-Index e = e; //$func Longest-Re e.collapses (t.var t.Re t.col-vars) = (t.var t.Re t.col-vars s.num); $func Longest-Re e = e; //$func Longest-Re-Value t.var (t.var1 t.Re (e.col-vars)) s.value = s.new-value; $func Longest-Re-Value e = e; //$func Next-Collaps e.collapses (t.var t.Re (e.col-vars) s.len) (t.sel-var t t s.sel-len) = // (t.new-sel-var t t s.new-sel-len); $func Next-Collaps e = e; //$func Var-To-Len e.collapses t.var = s.len; $func Var-To-Len e = e; //$func Create-Aux t.var t.aux-var (t.var1 (e.Re) (e.col-vars) s.num) = e.collaps-or-empty; $func Create-Aux e = e; //$func Del-Checks s.Vars t.var = ; $func Del-Checks e = e; $func Comp-Pattern t.Pattern e.Snt = e.asail-Snt; $func? Without-Calls? e.Re = ; $func Norm-Vars (e.vars) e.Snt = (e.vars) e.Snt; //$func Old-Vars e.expr = e.expr; //$func Find-Known-Lengths e.clashes = (e.known-len-clashes) e.clashes; //$func? Known-Vars? e.vars = ; $func Comp-Clashes (e.clashes) (e.Current-Snt) e.Other-Snts = e.asail-Snt; $func? Find-Var-Length e.clashes = e.cond (e.clashes); $func Update-Ties t.var e.clashes = e.clashes; $func Known-Length-of e.expr = e.known-length (e.unknown-vars); $func? Cyclic-Restrictions e.clashes = e.cond (e.clashes); $func Cyclic-Min t.var = e.min; $func? Cyclic-Max t.var = e.max; $func? Check-Symbols e.clashes = e.cond (e.clashes) s.new?; $func? Check-Ft t.Ft (e.pos) (e.right-pos) t.name s.dir = e.Ft-cond s.stop?; $func? Dereference-Subexpr e.clashes = e.cond (e.clashes); $func Compare-Subexpr e.clashes = e.cond (e.asserts) (e.clashes) s.new?; $func Compare-Ft t.Ft = e.Ft-cond s; $func? Get-Source e.clashes = e.cond (e.clashes); $func Compose-Expr e.expr = e.compose (e.not-instantiated-vars) s.flat?; $func? Comp-Cyclic e.clashes = e.cond (e.clashes) (e.fail); $func Get-Subexprs e.vars = e.asail-decls; $func Unknown-Vars e.expr = e.known-expr (e.unknown-vars); $func Split-Hard-Left e.expr = e.hard; $func Split-Hard-Right e.expr = e.hard; $func Gener-Label e.QualifiedName = t.label; $func Comp-Re e.Re (e.Snt) = e.asail-Snt; //$func? Second-Empty? (t.var ()) = ; $func? Second-Empty? e = e; //$func? Good-Res-Var? (t.var (t.F-var)) = ; $func? Good-Res-Var? e = e; $func Comp-Calls e.Re = e.calls; $func Store-Vars e.vars = e.vars; $func Declare-Vars s.type e.vars = e.decls; $func Instantiate-Vars e.vars = ; $func Comp-Assigns (e.vars) e.expressions = e.assignments; $func Get-Static-Exprs e.expr = e.expr (e.decls); $func Get-Static-Var e.expr = e.var (e.decl); $func Strip-STVE expr = expr; $func Set-Var t.name (e.key) (e.val) = ; RFP-Compile e.Items = { ;; } :: e.targets, :: e.Items t.Interface, t.Interface (MODULE e.Items); Compile (e.targets) (e.headers) e.Items, { e.Items : e t.item e.rest, { e.targets : v = e.targets : e t.name e, t.item : (t t t t.name e);; }, \{ t.item : (s.link s.tag t.pragma t.name (e.in) (e.out) (BRANCH t.p e.branch)) = { s.link : EXPORT = (DECL-FUNC t.name);; } :: e.decl, (e.decl) >; t.item : (s.link CONST t.pragma (e.QualifiedName) e.expr) = (CONSTEXPR ("r" e.QualifiedName) ) :: t.const-decl, { s.link : EXPORT = (t.const-decl) /*empty*/; () t.const-decl; }; } :: (e.decl) e.item = e.item ; /**/ (INTERFACE e.headers); }; Del-Pragmas { eL t.Item eR, t.Item : \{ (PRAGMA e) = eL ; (expr) = eL () ; }; e1 = e1; }; /* * For each referenced function generate a stub one with format e = e. */ Comp-Func-Stubs = () $iter { e.funcs : ((e.QualifiedName)) e.rest, (e.QualifiedName 0) :: t.Fname, // , // { // = // ;; // }, // , // , :: s.linkage s.tag t.pragma (e.Fin) (e.Fout), :: e.He s, :: e.asail, e.rest (e.asail-funcs e.asail); } :: e.funcs (e.asail-funcs), e.funcs : /*empty*/ = // Here is place to define expressions - references to stub functions. // Use &Ref-To-Funcs for that. e.asail-funcs; Comp-Func s.tag t.name (e.in) (e.out) e.Sentence = , , , , , , :: e.Sentence, > :: e.res-vars, , >, ) e.Sentence> :: (e.arg-vars) e.Sentence, : e, , , s.tag : { FUNC = (Comp Fatal); FUNC? = (Comp Retfail); } :: t.retfail, (FUNC t.name (e.arg-vars) (e.res-vars) ) :: e.comp-func, :: t e.comp-func, :: t e.result, e.result; // :: (e.func-decl) e.func-body, // () $iter { // e.vars : (t.var) e.rest-vars, // (e.var-decls (DECL t.var)) e.rest-vars; // } :: (e.var-decls) e.vars, // e.vars : /*empty*/, // (e.func-decl e.var-decls e.func-body); Ref-To-Var e.Snt = () e.Snt $iter { e.Snt : t.Statement e.rest, t.Statement : { (REF (e.QualifiedName)) = ("r" e.QualifiedName) :: t.name, :: s.tab, , )>, , , , , , , (e.new-Snt (VAR t.name)) e.rest; (e.expr) = (e.new-Snt ()) e.rest; t = (e.new-Snt t.Statement) e.rest; }; } :: (e.new-Snt) e.Snt, e.Snt : /*empty*/ = e.new-Snt; Post-Comp (e.used-vars) e.comp-func, e.comp-func : { /* * As well as "Used" shouldn't be "Declare" statements added? */ e.something (Used e.vars) = ; e.something (If-used (e.vars) e.statements), { : (v.true-used) (e.yet-not-used) = ; ; }; e.something (e.expr) = :: (e.expr-vars) e.expr, ) e.something> (e.expr); e.something s.symbol = s.symbol; /*empty*/ = (e.used-vars); }; Set-Drops (e.declared) e.comp-func = e.comp-func () (e.declared) $iter { e.comp-func : t.first e.rest, { t.first : \{ (EXPR t.var e) = (DROP t.var) (t.first) t.var Init; (DEREF t.var e) = (DROP t.var) (t.first) t.var Init; (SUBEXPR t.var e) = (DROP t.var) (t.first) t.var Init; (DECL Expr t.var) = (DROP t.var) () t.var Decl; (DECL "int" t.var) = /*empty*/ () t.var Decl; } :: e.drop (e.constr) t.var s.init, { e.declared : e1 t.var s.old-init e2, s.old-init : { Init, { t.var : (VAR ("const" e)) = e.rest (e.result-func) (e.declared); e.rest (e.result-func e.drop e.constr) (e.declared); }; Decl, s.init : { Decl = e.rest (e.result-func) (e.declared); Init = t.first : (s.method t.var e.args), e.rest (e.result-func (ASSIGN t.var (s.method e.args))) (e1 e2 t.var s.init); }; }; e.rest (e.result-func t.first) (e.declared t.var s.init); }; t.first : (LABEL t.label e.expr) = :: (e.declared) e.expr, e.rest (e.result-func (LABEL t.label e.expr)) (e.declared); t.first : (e.expr) = :: t e.expr, e.rest (e.result-func (e.expr)) (e.declared); t.first : s.symbol = e.rest (e.result-func s.symbol) (e.declared); }; } :: e.comp-func (e.result-func) (e.declared), e.comp-func : /*empty*/ = (e.declared) e.result-func; Comp-Sentence (e.cuts) e.Sentence = // , // >, // >, // { // : e (t.name) e, // , // { // : s.tab, // , // : e (e.field) e, // >, // $fail;; // }, $fail;; // }, // >, // >, // >, // >, // , e.Sentence : { (Comp Cut) e.Snt = ; t.Statement e.Snt = \{ e.cuts : /*empty*/ = t.Statement : \{ (Comp Empty) = /*empty*/; (Comp Used e.vars) = (Used e.vars) ; (Comp Notail) = ; (Comp Trap) = ; (Comp Vars e.Preserve-Re? s.Vars-Tab s.Static (e.greater) (e.less)) = , , :: s.tmp-Tab, { e.Preserve-Re? : Preserve-Re = >> $iter { e.vars : (VAR t.name) e.rest, : s.tab, :: s.new-tab, , e.rest; } :: e.vars, e.vars : /*empty*/;; }, , , ; (Comp Re e.Re) = , ; (Comp Fatal) = FATAL; (Comp Retfail) = RETFAIL; (Comp Sentence) = RETURN; (Comp Not) = e.Snt : (Comp Sentence) e.Current (Comp Sentence) e.Others = ; (Comp Continue t.label) = (CONTINUE t.label); (Comp Break t.label) = (BREAK t.label); (Comp Error) = > :: e.Re (e.decls), e.decls (ERROR e.Re); (Comp Remove-next-sentence) = e.Snt : e.Curr-Snt (Comp Sentence) e.Next-Snt (Comp Sentence) e.Other-Snts, ; (Comp Cutall) = e.Snt : { e.Snt1 (Comp Not) e (Comp Sentence) e.Rest, { e.Snt1 : e (Comp Notail) e (Comp Sentence) e (Comp Sentence) e.Rest1 = e.Rest1; e.Rest; } :: e.Rest = ; e (Comp Notail) e (Comp Sentence) e (Comp Sentence) e.Rest = ; e t.retfail = ; }; (Comp Stake) = ; (RESULT e.Re) = ; (FORMAT e.Hard) = >) e.Snt> :: (e.vars) e.Snt, :: e.vars, :: e.Re, ) e.Re> :: e.splited-Re, ()> :: (e.collapses) (e.normals), /* Each var in e.collapses is presented in at least one * of Re from e.collapses and e.normals. And any var * from e.normals isn't contented in any Re at all. So * we can compute e.normals in the end - we can't get * much use of them anyway. */ :: e.collaps-vars, :: e.collapses, /* * Now each "collaps" has the following structure: * t.var (e.Re) (e.all-collapsed-vars-from-Re) * And e.all-collapsed-vars-from-Re does NOT contain t.var. */ $iter { :: e.collapses, /* * Now each "collaps" has the following structure: * t.var (e.Re) (e.vars) s.num * where s.num is maximum number of callapsed * vars which including t.var are needed for * computing some variable. * Next function chooses t.var with minimized * maximum of all used in it variable's s.num. */ : (t.next-var (e.next-Re) e), /* * Choose free number for auxiliary variable index. */ 1 e.aux $iter { e.aux : e s.ind e = <"+" s.ind 1> e.aux; s.ind /*empty*/; } :: s.ind e.aux, e.aux : /*empty*/ = : t.aux-var, /* * Create-Aux changes all t.var to t.aux-var and * removes s.num from the end of collaps. */ e.comp-formats >; } :: e.comp-formats (e.collapses) (e.aux), e.collapses : /*empty*/ = :: e.normal-vars, e.comp-formats /* * Wouldn't be constructor in the form Expr(const_expr) * better? */ > ; (STAKE) = e.Snt : e.Current (Comp Sentence) e.Others = ; (CUT) = e.Snt : e.Current (Comp Sentence) e.Others = ; (CUTALL) = e.Snt : e.Current (Comp Sentence) e.Others = { e.Current : e1 (Comp Remove-next-sentence) e2 (Comp Notail) e3 = e.Others : e (Comp Sentence) e.rest, e1 e2 (Comp Notail) e3 :: e.Current, e.Current (Comp Sentence) e.rest; e.Current (Comp Sentence) (Comp Cutall) e.Others; } :: e.Snt, ; (FAIL) = e.Snt : e.Current (Comp Sentence) e.Others = ; (NOT (BRANCH e.Snt1)) = :: s.Vars-Tab, :: s.Static, :: e.greater, :: e.less, ; // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ????????? (LEFT e.Pattern) = ; (RIGHT e.Pattern) = ; (Comp Source s.Vars-Tab s.Static t.NOFAIL e.next-terms) = e.Snt : { (BLOCK) e.Snt1 = { t.NOFAIL : (Nofail) = FATAL; e.Snt : e.Current (Comp Sentence) e.Others = ; }; (BLOCK (BRANCH e.Branch) e.Branches) e.Snt1 = :: e.Re, :: e.greater, :: e.less, :: t.label, (LABEL t.label ) ; }; NOFAIL = e.Snt : (BLOCK e.Branches) e.rest-Snt, ; (BLOCK) = ; (BLOCK (BRANCH e.Branch) e.Branches) = ; (BLOCK t.NOFAIL e.Branches) = /* * First of all remove form the begining of e.Snt * auxiliary terms (Comp...). */ () e.Snt $iter { e.Snt : t.first e.rest = (e.comp-terms t.first) e.rest; } :: (e.comp-terms) e.Snt, # \{ e.Snt : (Comp Vars e) e; e.Snt : (Comp Remove-next-sentence) e; } = // { // e.Snt : /*empty*/ = () e.comp-terms; // (e.comp-terms) e.Snt; // } :: (e.comp-terms) e.Snt, { e.Snt : (ITER t.body t.format t.cond) e.rest = t.format (ITER Comp t.body t.format t.cond) e.rest; e.Snt; } :: e.Snt, e.Snt : t.first e.rest, { t.first : \{ (LEFT e.pattern) = e.pattern; (RIGHT e.pattern) = e.pattern; (FORMAT e.format) = e.format; } :: e.expr = ) e.Snt> : (e.vars) t.f e.r, () (t.f) e.r; () () e.Snt; } :: (e.decls) (e.next-term) e.Snt, e.Snt : e.Curr-Snt (Comp Sentence) e = { e.next-term : t1, { e.comp-terms : /*empty*/ = t1 (Comp Notail) (Preserve-Re); t1 (Preserve-Re); }; e.Curr-Snt : e t.item e, # \{ t.item : (Comp e); } = (Comp Notail) (Preserve-Re); /*empty*/ (); } :: e.next-terms (e.pres-Re), { e.next-term : (s e.nt) = e.nt; /*empty*/; } :: e.next-term, :: s.Vars-Tab, // ????????? :: s.Static, { e.comp-terms : /*empty*/ = :: e.greater, :: e.less, (Comp Vars e.pres-Re s.Vars-Tab s.Static (e.greater) (e.less)) (Comp Remove-next-sentence) e.next-terms; e.comp-terms e.next-terms; } :: e.next-terms, :: t.label, e.decls (LABEL t.label ) :: e.tmp-Snt, >)> : e = e.tmp-Snt ; (ITER e.Comp t (FORMAT e.Hard) t) = ) t.Statement e.Snt> : (e.vars) (ITER e (BRANCH e.IterBody) t.Format (BRANCH e.IterCondition)) e.Current-Snt (Comp Sentence) e.Other-Snts, { e.Comp : Comp = /*empty*/; ; } :: e.init, :: t.label, >, : e, , :: s.Vars-Tab, :: e.cond, , :: e.body, e.init (FOR () () () (LABEL t.label e.cond) e.body); (TRY (BRANCH e.TrySnt) e.CatchBlock) = :: s.Vars-Tab, e.Snt : e.Current-Snt (Comp Sentence) e, e.Current-Snt : { e1 (Comp Remove-next-sentence) e2 = e1 e2; e.Current-Snt; } :: e.Current-Snt, :: e.try, , : t.err, : e, , :: e.catch, (TRY e.try) (CATCH-ERROR e.catch); t.error, t.error : (ERROR) = // Due to the bug in ver. 1.8.7 e.Snt : e.Current-Snt (Comp Sentence) e, e.Current-Snt : $r e.CurrSnt (RESULT e.Re) e, ; }; e.cuts : e.cuts1 Cut = \{ t.Statement : (Comp Stake) = ; ; }; }; }; Not-Ref? (VAR t.name) = # \{ : (REF e); }; Contents-First? e.list (t.item e) = e.list : e t.item e; Zip-With-Vars e.col-vars (t.var (e.Re)) = (t.var (e.Re) (>)>) t.var>)); /* * Finds all vars independent from collapsed ones and computes assignments to * them. Also returns new list of collapsed varibles and indexes of binded * auxiliary variables. */ Comp-Ready-Formats e.collapses = :: (e.independ) (e.collapses), :: e.indep-vars, :: e.collapses, > (e.collapses) (>); Empty-Varlist? (t.var t.Re (/*empty-var-list*/)) = ; Remove-Independ e.independ (t.var t.Re (e.var-list)) = (t.var t.Re ()); Get-Aux-Indexes (t (e.Re) t) = >)>; Get-Var-Index { (VAR ("aux" s.ind)) = s.ind; t.var = /*empty*/; }; Longest-Re e.collapses (t.var t.Re t.col-vars) = (t.var t.Re t.col-vars ); Longest-Re-Value t.var (t.var1 t.Re (e.col-vars)) s.value, { :: s.len, <">" (s.len) (s.value)>, e.col-vars : e t.var e = s.len; s.value; }; Next-Collaps e.collapses (t.var t.Re (e.col-vars) s.len) (t.sel-var t.sel-Re t s.sel-len) = )> : s.new-len, { <"<" (s.new-len) (s.sel-len)> = (t.var t.Re () s.new-len); (t.sel-var t.sel-Re () s.sel-len); }; Var-To-Len e.collapses t.var = e.collapses : e (t.var t t s.len) e = s.len; Create-Aux t.var t.aux-var (t.var1 (e.Re) (e.col-vars) s), { t.var : t.var1 = /*empty*/; (t.var1 () ()); }; Del-Checks s.Vars (VAR t.name), { : s.tab = { Left-compare Right-compare Left-checks Right-checks : e s.field e, )>, $fail;; }; , { Left-compare Right-compare Left-checks Right-checks : e s.field e, , $fail;; }; }; Comp-Pattern (s.dir e.PatternExp) e.Sentence = ) (s.dir e.PatternExp) e.Sentence> : t t.Pattern e.Snt, // (Unwatched () t.Pattern) e.Snt $iter { /* * Uncomment previous line and delete next one to activate Split-Clashes * function */ (() t.Pattern) e.Snt $iter { e.Snt : (RESULT e.Re) (s.d e.Pe) e = // , ) e.Snt> : t t.R t.P e.rest, // (e.clashes Unwatched (e.Re) t.P) e.rest; /* * Uncomment previous line and delete next one to activate * Split-Clashes function */ (e.clashes (e.Re) t.P) e.rest; } :: (e.clashes) e.Snt, # \{ e.Snt : \{ (RESULT e.Re) (LEFT e) e = e.Re; (RESULT e.Re) (RIGHT e) e = e.Re; } :: e.Re, ; } = e.Snt : e.Current-Snt (Comp Sentence) e.Other-Snts = :: e.asail-Others, { // // :: (e.greater) (e.less) (e.hards) (e.clashes) e.Current-Snt = // , // , // , // , :: e.asail-Clashes, // e.asail-Clashes (e.greater) $iter { // e.greater : (e.vars s.num) e.rest, // :: e.vars, // temporary step // (IF ((INFIX ">=" ((LENGTH e.vars)) (s.num))) // e.asail-Clashes // ) (e.rest); // } :: e.asail-Clashes (e.greater), // e.greater : /*empty*/ = // e.asail-Clashes (e.less) $iter { // e.less : (e.vars s.num) e.rest, // :: e.vars, // temporary step // (IF ((INFIX "<=" ((LENGTH e.vars)) (s.num))) // e.asail-Clashes // ) (e.rest); // } :: e.asail-Clashes (e.less), // e.less : /*empty*/ = // e.asail-Clashes (e.hards) $iter { // e.hards : (e.Re) (e.Pe) e.rest, // :: e.Re, // temporary step // :: e.Pe, // temporary step // (IF ((INFIX "==" (e.Re) (e.Pe))) e.asail-Clashes) (e.rest); // } :: e.asail-Clashes (e.hards), // e.hards : /*empty*/ = e.asail-Clashes e.asail-Others; e.asail-Others; // ; }; Without-Calls? e.Re = e.Re $iter \{ e.Re : t.Rt e.rest, t.Rt : \{ (CALL e) = $fail; (BLOCK e) = $fail; (PAREN e.Re1) = ; t.symbol-or-var = /*empty*/; }, e.rest; } :: e.Re, e.Re : /*empty*/; Norm-Vars (e.vars) e.Snt = /* * Store all new variables in the &Vars-Tab table and return the list with * all variables in the (VAR t.name) form. */ :: e.new-vars, /* * Rename all new variables in e.Snt. Never mind multiple occurences. */ (e.vars) (e.new-vars) e.Snt $iter { e.vars : t.var e.rest, e.tmp-vars : t.new-var e.new-rest, { t.var : t.new-var = (e.rest) (e.new-rest) e.Snt; t.var : (s.tag e), , (e.rest) (e.new-rest) ; }; } :: (e.vars) (e.tmp-vars) e.Snt, e.vars : /*empty*/ = (e.new-vars) e.Snt; //Comp-Clashes (e.clashes) (e.Current-Snt) e.Other-Snts = // , //// /* //// * Collect in e.vars all varibles from all clashes. //// */ //// () e.clashes $iter { //// e.not-watched : (e.expr) e.rest = (e.vars ) e.rest; //// } :: (e.vars) e.not-watched, //// e.not-watched : /*empty*/ = //// /* //// * Rename all collected variables in all clashes. Never mind multiple //// * occurences. //// */ //// (e.clashes) e.vars $iter { //// e.vars : (s.var-tag s.m (e.n) e.var-id) e.rest, { //// = //// e.var-id : e.NEW (e.QualifiedName), //// ; //// s.m : e.n = //// ; //// } :: e.clashes, //// (e.clashes) e.rest; //// } :: (e.clashes) e.vars, //// e.vars : /*empty*/ = //// /* //// * Now all variables with known length have ref. term after s.var-tag. //// * Well, lets see if there are closed variables and compute their lengthes //// * too. //// */ //// e.clashes (e.clashes) () $iter { //// e.not-watched : (e.Re) (s.dir e.Pe) e.rest, { //// :: t.old-var t.new-var e.new-cond, //// :: e.clashes, //// e.clashes (e.clashes) (e.cond e.new-cond); //// e.rest (e.clashes) (e.cond); //// }; //// } :: e.not-watched (e.clashes) (e.cond), //// e.not-watched : /*empty*/ = // // /* // * Parenthesize each clash, so from now on they can be seen as a sequence // * of such terms: (e.temp-tags (e.Re) t.P) // */ // e.clashes () $iter { // e.old-clashes : t.R t.P e.rest = // e.rest (e.clashes (t.R t.P)); // } :: e.old-clashes e.clashes, // e.old-clashes : /*empty*/ = // // :: (e.known-len-clashes) e.clashes, // { // e.known-len-clashes : /*empty*/ = // :: (e.sym-check-clashes) e.clashes, // { // e.sym-check-clashes : /*empty*/ = // e.clashes : { // (e.Re) (s.dir e.Pe) e.rest = // :: t.label, // // :: e.asail-Snt, // (FOR t.label () () () // e.asail-Snt // ) // ; // /*empty*/ = // ; // }; // :: e.asail-Snt, // (e.sym-check-clashes) e.asail-Snt $iter { // e.sym-check-clashes : e.something (e (e.Re) (s.dir e.Pe)), // // :: e.asail-Snt, // (e.known-len-clashes) e.asail-Snt $iter { // e.known-len-clashes : e.something (e.tags (e.Re) (s.dir e.Pe)), // (e.something) // (IF ((INFIX "==" () ())) // e.asail-Snt // ); // } :: (e.known-len-clashes) e.asail-Snt, // e.known-len-clashes : /*empty*/ = // e.asail-Snt // ; // }; // //Find-Known-Lengths e.clashes = // e.clashes () () $iter { // e.old-clashes : t.first e.rest, t.first : { // (e1 Known-length e2) = // e.rest (e.known) (e.clashes t.first); // (e.tags (e.Re) (s.dir e.Pe)) = //// Known $iter { //// e.vars : (VAR t.name) e.rest-vars, { //// : e = Known; //// : True = Known; //// Unknown; //// } :: s.known? = //// s.known? e.rest-vars; //// } :: s.known? e.vars, //// \{ //// s.known? : Unknown = //// e.rest (e.known) (e.clashes t.first); //// e.vars : /*empty*/ = //// e.rest (e.known t.first) //// (e.clashes (e.tags Known-length (e.Re) (s.dir e.Pe))); //// }; // { // > = // e.rest (e.known t.first) // (e.clashes (e.tags Known-length (e.Re) (s.dir e.Pe))); // e.rest (e.known) (e.clashes t.first); // }; // }; // } :: e.old-clashes (e.known) (e.clashes), // e.old-clashes : /*empty*/ = // (e.known) e.clashes; // //Known-Vars? e.vars = // :: e.known-vars, // e.vars $iter { // e.vars : t.var e.rest = // e.known-vars : e t.var e, // e.rest; // } :: e.vars, // e.vars : /*empty*/; Comp-Clashes (e.clashes) (e.Current-Snt) e.Other-Snts = // , /* * Parenthesize each clash, so from now on they can be seen as a sequence * of such terms: (e.temp-tags (e.Re) t.P) */ e.clashes () $iter { e.old-clashes : t.R t.P e.rest = e.rest (e.clashes ( &New-Clash-Tags t.R t.P)); } :: e.old-clashes (e.clashes), e.old-clashes : /*empty*/ = /*empty*/ (e.clashes) () $iter { /* * First of all see if we have a clash with all variables of known length * and without length conditions written out. */ e.clashes : e1 (e.t1 Known-length e.t2 (e.Re) (s.dir e.Pe)) e2, = e.cond (Cond IF ((INFIX "==" () ()))) (e1 (e.t1 Checked-length e.t2 (e.Re) (s.dir e.Pe)) e2) (e.fail); /* * Next see if we can compute length of some variable. */ e.cond (e.fail); /* * Write out restrictions for the cyclic variables. */ e.cond (e.fail); // :: e.new-cond (e.clashes), // { // e.fail : v = e.cond e.new-cond (Clear-Restricted) (e.clashes) (e.fail); // e.cond e.new-cond (e.clashes) (e.fail); // }; /* * After checking all possible lengthes at the upper level change * <>. */ e.fail : v = (Contin e.fail) e.cond (Fail e.fail) (Clear-Restricted) (e.clashes) (); /* * For all clashes with known left part check unwatched terms whether they * are symbols or reference terms or not any. */ \? { : { v.new-cond (e.new-clashes) s = e.cond (Cond IF (v.new-cond)) (e.new-clashes) (); (e.new-clashes) New = e.cond (e.new-clashes) (); e \! $fail; }; , $fail; }; /* * And then try to compose new clash by dereferencing a part of some one. */ e.cond (); /* * If previous doesn't work then compare recursively all known * subexpressions and all unknown repeated subexpressions with * corresponding parts of source. */ :: e.new-cond (e.asserts) (e.new-clashes) s.new?, \{ e.new-cond : v, { e.asserts : v = e.cond (Assert e.asserts) (Cond IF (e.new-cond)) (e.new-clashes) (); e.cond (Cond IF (e.new-cond)) (e.new-clashes) (); }; e.asserts : v = e.cond (Assert e.asserts) (e.new-clashes) (); s.new? : New = e.cond (e.new-clashes) (); }; /* * Then get first uncatenated source and bring it to the normal * form, i.e. concatenate and parenthesize until it became single * known expression. */ e.cond (); /* * Now it's time to deal with cycles. */ e.cond ; /* * At last initialize all new subexpressions from all clashes. */ e.clashes () $iter { e.clashes : (e t.Re (s.dir e.Pe)) e.rest, e.rest (e.new-cond >); } :: e.clashes (e.new-cond), e.clashes : /*empty*/ = { e.new-cond : /*empty*/ = e.cond () (); e.cond (Assert e.new-cond) () (); }; } :: e.cond (e.clashes) (e.fail), // , // , e.clashes : /*empty*/ = e.cond () 0 $iter { e.cond : (Contin (CONTINUE t.label)) e.rest = e.rest (e.contin (Comp Continue t.label)) 0; e.cond (e.contin) 1; } :: e.cond (e.contin) s.stop?, s.stop? : 1 = :: e.asail-Snt, e.cond (e.asail-Snt) () $iter { e.cond : e.some (e.last), e.last : { Cond e.condition = e.some ((e.condition e.asail-Snt)) (e.vars); Assert e.assertion = e.some (e.assertion e.asail-Snt) (e.vars); Fail e.fail1 = e.some (e.asail-Snt e.fail1) (e.vars); Restricted t.var = e.some (e.asail-Snt) (e.vars t.var); If-not-restricted t.var e.restr-cond, { e.vars : e t.var e = e.some (e.asail-Snt) (e.vars); e.some e.restr-cond (e.asail-Snt) (e.vars); }; Clear-Restricted = e.some (e.asail-Snt) (); }; } :: e.cond (e.asail-Snt) (e.vars), e.cond : /*empty*/ = e.asail-Snt/* */; Find-Var-Length e.clashes = // , e.clashes : e1 (e.t1 Unknown-length e.t2 (e.Re) (s.dir e.Pe)) e2 \? :: e.new-Pe (e.Pe-unknown), :: e.new-Re (e.Re-unknown), // , , , e.Re-unknown e.Pe-unknown : { /*empty*/ = (e1 (e.t1 Known-length e.t2 (e.Re) (s.dir e.Pe)) e2); (VAR t.name) e.rest, e.rest $iter \{ e.unknown : (VAR t.name) e.rest1 = e.rest1; } :: e.unknown, e.unknown : /*empty*/, <"-" > : { 0 \! $fail; s.diff, { <"<" (s.diff) (0)> = <"*" s.diff -1> (INFIX "-" () ()); <">" (s.diff) (0)> = s.diff (INFIX "-" () ()); } :: s.mult e.diff, t.name : (e.QualifiedName), (VAR ("len" e.QualifiedName)) :: t.len-var, { :: e.max = (INFIX "<=" (t.len-var) ((INFIX "*" (s.mult) (e.max))) ); /*empty*/; } :: e.cond, e.cond (INFIX ">=" (t.len-var) ((INFIX "*" (s.mult) ())) ) (NOT (INFIX "%" (t.len-var) (s.mult) )) :: e.cond, , )>, )>, // = (Restricted (VAR t.name)) (Assert (ASSIGN t.len-var e.diff) ) (Cond IF (e.cond)) ( (e.t1 Checked-length e.t2 (e.Re) (s.dir e.Pe)) ); }; e.unknown \! e.t1 Unknown-length e.t2 : e.t3 Ties e.t4 = e.t1 : t.id e, e.unknown () $iter { e.unknown : (VAR t.name) e.rest, { e.tied : e (VAR t.name) e = e.rest (e.tied); :: s.Re-ent e.new-Re, :: s.Pe-ent e.new-Pe, <"-" s.Re-ent s.Pe-ent> :: s.diff, { s.diff : 0 = e.rest (e.tied (VAR t.name)); { <"<" (s.diff) (0)> = <"*" s.diff -1> (e.new-Re) (e.new-Pe); s.diff (e.new-Pe) (e.new-Re); } :: s.diff (e.plus) (e.minus), ( t.id () () s.diff ) :: t.tie, { : { e.c1 (t.id e) e.c2 = e.c1 e.c2; e.ties = e.ties; }; /*empty*/; } :: e.ties, { e.ties : e t.tie e; ; }, e.rest (e.tied (VAR t.name)); }; }; } :: e.unknown (e.tied), e.unknown : /*empty*/ = { e.t3 e.t4 : e Cyclic e = e.t3 e.t4; e.t3 e.t4 Cyclic; } :: e.tags, (e1 (e.tags (e.Re) (s.dir e.Pe)) e2); }; Known-Length-of e.expr = :: e.expr (e.vars), (e.vars); Update-Ties t.var e.clashes = e.clashes () $iter { e.clashes : t.clash e.rest, t.clash : (e.tags (e.Re) (s.dir e.Pe)), { e.tags : e Ties e = e.rest (e.new-clashes t.clash); e.Re e.Pe : e t.var e = e.rest (e.new-clashes (e.tags Ties (e.Re) (s.dir e.Pe))); e.rest (e.new-clashes t.clash); }; } :: e.clashes (e.new-clashes), e.clashes : /*empty*/ = e.new-clashes; Cyclic-Restrictions e.clashes = e.clashes : e1 (e.t1 Cyclic e.t2 (e.Re) (s.dir e.Pe)) e2 = :: e (e.unknown), e.unknown () $iter { e.unknown : t.var e.rest, t.var : (VAR (e.QualifiedName)), (VAR ("min" e.QualifiedName)) :: t.min-var, :: e.min, { :: e.max = e.rest (e.cond (Restricted t.var) (If-not-restricted t.var (Assert (ASSIGN t.min-var e.min) ) (Cond IF ((INFIX "<=" (t.min-var) (e.max)))) )); e.rest (e.cond); }; } :: e.unknown (e.cond), e.unknown : /*empty*/ = e.cond (e1 (e.t1 e.t2 (e.Re) (s.dir e.Pe)) e2); Cyclic-Min (VAR t.name) = () $iter { e.ties : (t (e.plus (e.plus-vars)) (e.minus (e.minus-vars)) s.mult) e.rest, { e.minus-vars () $iter \{ e.minus-vars : t.var e.vars-rest, e.vars-rest (e.minus-maxes ); } :: e.minus-vars (e.minus-maxes), e.minus-vars : /*empty*/ = e.plus-vars () $iter { e.plus-vars : (VAR t.var-name) e.vars-rest = e.vars-rest (e.plus-mins ); } :: e.plus-vars (e.plus-mins), e.plus-vars : /*empty*/ = e.rest (e.mins ((INFIX "/" ((INFIX "-" (e.plus e.plus-mins) (e.minus e.minus-maxes))) (s.mult) ))); e.rest (e.mins); }; } :: e.ties (e.mins), e.ties : /*empty*/ = () e.mins :: e.mins, { e.mins : (e.min) = e.min; (MAX e.mins); }; Cyclic-Max (VAR t.name) = () $iter { e.ties : (t (e.plus (e.plus-vars)) (e.minus (e.minus-vars)) s.mult) e.rest, { e.plus-vars () $iter \{ e.plus-vars : (VAR t.var-name) e.vars-rest, e.vars-rest (e.plus-maxes ); } :: e.plus-vars (e.plus-maxes), e.plus-vars : /*empty*/ = e.minus-vars () $iter { e.minus-vars : (VAR t.var-name) e.vars-rest = e.vars-rest (e.minus-mins ); } :: e.minus-vars (e.minus-mins), e.minus-vars : /*empty*/ = e.rest (e.maxes ((INFIX "/" ((INFIX "-" (e.plus e.plus-maxes) (e.minus e.minus-mins))) (s.mult) ))); e.rest (e.maxes); }; } :: e.ties (e.maxes), e.ties : /*empty*/ = { () e.maxes; e.maxes; } :: e.maxes, { e.maxes : /*empty*/ = $fail; e.maxes : (e.max) = e.max; (MIN e.maxes); }; Check-Symbols e.clashes = e.clashes () () Old $iter { e.clashes : t.clash e.rest, { t.clash : (e.t1 Check-symbols e.t2 (e.Re) (s.dir e.Pe)), e.Re : (VAR t.name), : True = // () () Continue $iter { e.Pe () () Continue $iter { e.format : t.Ft e.Fe = :: e.pos, ) t.name Left-checks> : { /*empty*/ s.stop??? = /*empty*/ s.stop???; Sym s.stop??? = (Used e.Re) (SYMBOL? e.Re (e.pos)) s.stop???; Ref s.stop??? = (Used e.Re) (NOT (SYMBOL? e.Re (e.pos))) s.stop???; Flat e.len s.stop??? = (Used e.Re) (FLAT-SUBEXPR? e.Re (e.pos) (e.len)) s.stop???; } :: e.Ft-cond s.stop? = e.Fe (e.left t.Ft) (e.new-cond e.Ft-cond) s.stop?; } :: e.format (e.left) (e.new-cond) s.stop?, \{ e.format : /*empty*/ = e.rest (e.cond e.new-cond) (e.new-clashes (e.t1 e.t2 (e.Re) (s.dir e.Pe))) New; s.stop? : Stop = e.format () (e.new-cond) Continue $iter { e.format : e.Fe t.Ft = 1 :: e.pos, :: e.Ft-cond s.stop?, e.Ft-cond : { /*empty*/ = /*empty*/; Sym = (Used e.Re) (SYMBOL? e.Re ( (INFIX "-" () (e.pos)) )); Ref = (Used e.Re) (NOT (SYMBOL? e.Re ( (INFIX "-" () (e.pos)) ))); Flat e.len s.stop??? = (Used e.Re) (FLAT-SUBEXPR? e.Re ( (INFIX "-" () (e.pos)) ) e.len) s.stop???; } :: e.Ft-cond, e.Fe (t.Ft e.right) (e.new-cond e.Ft-cond) s.stop?; } :: e.format (e.right) (e.new-cond) s.stop?, s.stop? : Stop = e.rest (e.cond e.new-cond) (e.new-clashes t.clash) s.new?; }; e.rest (e.cond) (e.new-clashes t.clash) s.new?; }; } :: e.clashes (e.cond) (e.new-clashes) s.new?, // , e.clashes : /*empty*/ = e.cond (e.new-clashes) s.new?; Check-Ft t.Ft (e.pos) (e.right-pos) t.name s.dir, t.Ft : { s.ObjectSymbol, { : \{ e (e.pos Sym) e = /*empty*/ Continue; e (e.pos (Ref e)) e = $fail; }; s.dir : Left-checks, : \{ e (e.right-pos Sym) e = /*empty*/ Continue; e (e.right-pos (Ref e)) e = $fail; }; (e.pos Sym))> = Sym Continue; }; (PAREN e.expr), { : \{ e (e.pos (Ref e)) e = /*empty*/ Continue; e (e.pos Sym) e = $fail; }; s.dir : Left-checks, : \{ e (e.right-pos (Ref e)) e = /*empty*/ Continue; e (e.right-pos Sym) e = $fail; }; s.dir : { Left-checks = "lderef"; Right-checks = "rderef"; } :: s.name-dir, t.name : (e.QualifiedName), :: t.ref-name, // : e, (e.pos (Ref t.ref-name)))> = Ref Continue; }; (VAR t.Ft-name), { , { : True, { : 1, { : \{ e (e.pos Sym) e = /*empty*/ Continue; e (e.pos (Ref e)) e = $fail; }; s.dir : Left-checks, : \{ e (e.right-pos Sym) e = /*empty*/ Continue; e (e.right-pos (Ref e)) e = $fail; }; // : True = // /*empty*/ Continue; (e.pos Sym))> = Sym Continue; }; (e.pos Flat))> = Flat Continue; }; /*empty*/ Continue; }; /*empty*/ Stop; }; }; Dereference-Subexpr e.clashes = e.clashes : e1 (e.t1 Dereference e.t2 (e.Re) (s.dir e.Pe)) e2 \? e.Re : (VAR t.name), : True, // >, // : e.f1 t.Ft e.f2 \? e.Pe : e.f1 t.Ft e.f2 \? \{ t.Ft : (PAREN e.expr), :: e.pos, { : e (e.pos (Ref t.ref-name)) e \! # \{ : True; } = : e, , (Assert (DEREF (VAR t.ref-name) e.Re (e.pos))) :: e.cond, (e.t1 Dereference e.t2 (e.Re) (s.dir e.Pe)) :: t.old-clash, { e.t1 e.t2 : e Without-object-symbols e = Without-object-symbols; /*empty*/; } :: e.wos, ( &New-Clash-Tags e.wos ((VAR t.ref-name)) (s.dir e.expr) ) :: t.new-clash, s.dir : { LEFT = e.cond (e1 t.new-clash t.old-clash e2); RIGHT = e.cond (e1 t.old-clash t.new-clash e2); }; t.Ft e.f2 : $r e.f3 (PAREN e.expr1) e.f4 \? 1 :: e.pos, { : e (e.pos (Ref t.ref-name)) e \! # \{ : True; } = : e, , (Assert (DEREF (VAR t.ref-name) e.Re ( (INFIX "-" () (e.pos)) )) ) :: e.cond, (e.t1 Dereference e.t2 (e.Re) (s.dir e.Pe)) :: t.old-clash, { e.t1 e.t2 : e Without-object-symbols e = Without-object-symbols; /*empty*/; } :: e.wos, ( &New-Clash-Tags e.wos ((VAR t.ref-name)) (s.dir e.expr1) ) :: t.new-clash, s.dir : { RIGHT = e.cond (e1 t.new-clash t.old-clash e2); LEFT = e.cond (e1 t.old-clash t.new-clash e2); }; \!\!\! $fail; }; \!\! $fail; }; e.f2 : /*empty*/ = (e1 (e.t1 e.t2 (e.Re) (s.dir e.Pe)) e2); }; Compare-Subexpr e.clashes = e.clashes () () () Old $iter e.clashes : { (e.t1 Compare e.t2 (e.Re) (s.dir e.Pe)) e.rest, e.Re : (VAR t.name), : True = { e.t1 e.t2 : e Without-object-symbols e = /*empty*/ (e.t2) (e.Re) (e.Pe); :: e.Re (e.Re-decls), :: e.Pe (e.Pe-decls) = e.Re-decls e.Pe-decls (e.t2 Without-object-symbols) (e.Re) (e.Pe); } :: e.new-asserts (e.t2) (e.Re) (e.Pe), e.Pe () () Continue $iter { e.format : t.Ft e.Fe, :: e.pos, :: e.len, :: e.right-pos, { \{ : e (t.Ft Left (0) (e.pos) e.len) e; : e (t.Ft Left (0) (e.right-pos) e.len) e; } = /*empty*/ Continue; : { /*empty*/ s.stop??? = /*empty*/ s.stop???; e.compare s.eq = // , t.Ft : (VAR t.Ft-name), (t.Ft Left (0) (e.pos) e.len))>, (e.Re Left (e.pos) (0) e.len))>, e.compare : { Empty = /*empty*/ Continue; Instantiated = (t.Ft) (0) (e.len) :: e.sub1, (e.Re) (e.pos) (e.len) :: e.sub2, { s.eq : EQ = 0; 1; } :: s.R, (Used t.Ft e.Re) (s.eq e.sub2) Continue; // (s.eq ((FIRST t.Ft)) ((LAST t.Ft)) // ((FIRST e.Re) e.pos) ((FIRST e.Re) e.pos e.len) // ) Continue; (t.var s.dir1 (e.pos1) (0) e.len), s.dir1 : { Left = (t.var) (e.pos1) (e.len) :: e.sub1, (e.Re) (e.pos) (e.len) :: e.sub2, { s.eq : EQ = 0; 1; } :: s.R, (Used t.var e.Re) (s.eq e.sub2) Continue; // (s.eq ((FIRST t.var) e.pos1) // ((FIRST t.var) e.pos1 e.len) // ((FIRST e.Re) e.pos) // ((FIRST e.Re) e.pos e.len) // ) Continue; Right = (t.var) ((INFIX "-" ((LENGTH t.var)) (e.pos1) (e.len))) (e.len) :: e.sub1, (e.Re) (e.pos) (e.len) :: e.sub2, { s.eq : EQ = 0; 1; } :: s.R, (Used t.var e.Re) (s.eq e.sub2) Continue; // (s.eq // ((INFIX "-" // ((LAST t.var)) (e.pos1) (e.len)) // ) // ((INFIX "-" ((LAST t.var)) (e.pos1))) // ((FIRST e.Re) e.pos) // ((FIRST e.Re) e.pos e.len) // ) Continue; // // (t.name1 s.dir (e.pos1) (e.pos) e.len) }; }; }; } :: e.Ft-cond s.stop? = e.Fe (e.left t.Ft) (e.new-cond e.Ft-cond) s.stop?; } :: e.format (e.left) (e.new-cond) s.stop?, \{ e.format : /*empty*/ = e.rest (e.cond e.new-cond) (e.new-asserts) (e.new-clashes (e.t1 e.t2 (e.Re) (s.dir e.Pe))) New; s.stop? : Stop = e.format () (e.new-cond) Continue $iter { e.format : e.Fe t.Ft, :: e.pos, :: e.len, { : e (t.Ft Left (0) (e.pos) e.len) e = /*empty*/ Continue; : { /*empty*/ s.stop??? = /*empty*/ s.stop???; e.compare s.eq = t.Ft : (VAR t.Ft-name), (t.Ft Left (0) (e.pos) e.len))>, (e.Re Right (e.pos) (0) e.len))>, e.compare : { Empty = /*empty*/ Continue; Instantiated = (t.Ft) (0) (e.len) :: e.sub1, (e.Re) ((INFIX "-" ((LENGTH e.Re)) (e.pos) (e.len))) (e.len) :: e.sub2, { s.eq : EQ = 0; 1; } :: s.R, (Used t.Ft e.Re) (s.eq e.sub2) Continue; // (s.eq ((FIRST t.Ft)) ((LAST t.Ft)) // ((INFIX "-" ((LAST e.Re)) (e.pos) (e.len))) // ((INFIX "-" ((LAST e.Re)) (e.pos))) // ) Continue; (t.var s.dir1 (e.pos1) (0) e.len), s.dir1 : { Left = (t.var) (e.pos1) (e.len) :: e.sub1, (e.Re) ((INFIX "-" ((LENGTH e.Re)) (e.pos) (e.len) )) (e.len) :: e.sub2, { s.eq : EQ = 0; 1; } :: s.R, (Used t.var e.Re) (s.eq e.sub2) Continue; // (s.eq ((FIRST t.var) e.pos1) // ((FIRST t.var) e.pos1 e.len) // ((INFIX "-" // ((LAST e.Re)) (e.pos) (e.len) // )) // ((INFIX "-" ((LAST e.Re)) (e.pos))) // ) Continue; Right = (t.var) ((INFIX "-" ((LENGTH t.var)) (e.pos1) (e.len) )) (e.len) :: e.sub1, (e.Re) ((INFIX "-" ((LENGTH e.Re)) (e.pos) (e.len) )) (e.len) :: e.sub2, { s.eq : EQ = 0; 1; } :: s.R, (Used t.var e.Re) (s.eq e.sub2) Continue; // (s.eq // ((INFIX "-" // ((LAST t.var)) (e.pos1) (e.len) // )) // ((INFIX "-" ((LAST t.var)) (e.pos1))) // ((INFIX "-" // ((LAST e.Re)) (e.pos) (e.len) // )) // ((INFIX "-" ((LAST e.Re)) (e.pos))) // ) Continue; }; }; }; } :: e.Ft-cond s.stop? = e.Fe (t.Ft e.right) (e.new-cond e.Ft-cond) s.stop?; } :: e.format (e.right) (e.new-cond) s.stop?, s.stop? : Stop = e.rest (e.cond e.new-cond) (e.new-asserts) (e.new-clashes (e.t1 Compare e.t2 (e.Re) (s.dir e.Pe))) s.new?; }; t.clash e.rest = e.rest (e.cond) (e.asserts) (e.new-clashes t.clash) s.new?; } :: e.clashes (e.cond) (e.asserts) (e.new-clashes) s.new?, // , e.clashes : /*empty*/ = e.cond (e.asserts) (e.new-clashes) s.new?; Compare-Ft { s.ObjectSymbol = , $fail; (PAREN e.expr) = /*empty*/ Continue; (VAR t.name), { , { : True = Instantiated; : { t.compare e = t.compare; /*empty*/ = Empty; }; } :: e.compare, { : True, : 1 = FLAT-EQ; EQ; } :: s.eq = e.compare s.eq; /*empty*/ Stop; }; }; Get-Source e.clashes = e.clashes : e1 (e.tags (e.Re) (s.dir e.Pe)) e2, \{ /* * If source is an instantiated variable then go to the next clash. */ e.Re : (VAR t.name), : True = $fail; /* * If in source there is unknown variable then we can't compute it, so * go to the next clash. */ e.Re $iter e.Re : { (VAR t.name) e.rest = \{ : True; : v; }, e.rest; t e.rest = e.rest; } :: e.Re, e.Re : /*empty*/; } = // , { e.Re : /*empty*/ = : t.empty, , () () (e.tags (t.empty) (s.dir e.Pe)); e.Re : (VAR t.name) = (e.Re) () (e.tags (e.Re) (s.dir e.Pe)); { e.tags : e Without-object-symbols e = /*empty*/ (e.tags (e.Re) (s.dir e.Pe)); :: e.Re (e.Re-decls), :: e.Pe (e.Pe-decls) = e.Re-decls e.Pe-decls (e.tags Without-object-symbols (e.Re) (s.dir e.Pe)); } :: e.asserts (e.tags (e.Re) (s.dir e.Pe)), { e.Re : (VAR t.name) = () (e.asserts) (e.tags (e.Re) (s.dir e.Pe)); :: e.compose (e.not-inst) s.flat?, :: t.name, :: e.decl, , { s.flat? : 0 = ;; }, )>, )> = (e.not-inst) (e.asserts e.decl (ASSIGN (VAR t.name) e.compose)) (e.tags ((VAR t.name)) (s.dir e.Pe)); }; } :: (e.not-inst) (e.decl) t.clash, (Assert e.decl) (e1 t.clash e2); Compose-Expr e.Re = e.Re () () 0 $iter { e.Re : t.Rt e.rest, t.Rt : { s.ObjectSymbol = , $fail; (PAREN e.expr) = :: e.expr (e.new-not-inst) s, (PAREN e.expr) (e.new-not-inst) 1; (VAR t.name) = { : True = /*empty*/; t.Rt; } :: e.new-not-inst, { : True = 0; 1; } :: s.new-flat?, (Used t.Rt) t.Rt (e.new-not-inst) s.new-flat?; } :: e.new-compose (e.new-not-inst) s.new-flat? = e.rest (e.compose e.new-compose) (e.not-inst e.new-not-inst) <"+" s.flat? s.new-flat?>; } :: e.Re (e.compose) (e.not-inst) s.flat?, e.Re : /*empty*/ = e.compose (e.not-inst) s.flat?; Comp-Cyclic e.clashes = e.clashes : e1 (e.t1 Unknown-length e.t2 (e.Re) (s.dir e.Pe)) e2 = e.Re : (VAR (e.QualifiedName)), :: e.left-hard, :: e.right-hard, e.Pe : e.left-hard e.Cycle e.right-hard, { e.left-hard e.right-hard : /*empty*/ = /*empty*/ (e.QualifiedName) (); :: t.name, t.name : (e.CycleName), : e, , )>, (INFIX "-" () ()) :: e.len, (Used e.Re) (SUBEXPR (VAR t.name) e.Re () (e.len)) :: e.decl, ) (0) ))>, ) ))> = (e.t1 Checked-length e.t2 (e.Re) (s.dir e.left-hard (VAR t.name) e.right-hard)) (e.CycleName) (e.decl); } :: e.old-clash (e.CycleName) (e.decl), (VAR (e.CycleName)) :: t.var, :: t.break-label, :: t.cont-label, s.dir : { LEFT = e.Cycle : t.var-e1 e.rest, t.var-e1 : (VAR (e.SplitName)), { // e.rest : t.var-e2 = t.var-e2; (VAR ); } :: t.var-e2, : e, (Assert e.decl (LSPLIT t.var ((VAR ("min" e.SplitName))) t.var-e1 t.var-e2) ) (Cond LABEL t.break-label) (Cond FOR (t.cont-label) () ((INC-ITER t.var))) (Fail (BREAK t.break-label)) (Clear-Restricted) (> e.old-clash ( &New-Clash-Tags (t.var-e2) (s.dir e.rest)) >) ((CONTINUE t.cont-label)); RIGHT = e.Cycle : e.rest t.var-e2, t.var-e2 : (VAR (e.SplitName)), { // e.rest : t.var-e2 = t.var-e2; (VAR ); } :: t.var-e1, : e, (Assert e.decl (RSPLIT t.var ((VAR ("min" e.SplitName))) t.var-e1 t.var-e2) ) (Cond LABEL t.break-label) (Cond FOR (t.cont-label) () ((INC-ITER t.var))) (Fail (BREAK t.break-label)) (Clear-Restricted) (> e.old-clash ( &New-Clash-Tags (t.var-e1) (s.dir e.rest)) >) ((CONTINUE t.cont-label)); }; Get-Subexprs e.vars = // , e.vars () $iter { e.vars : (VAR t.name) e.rest, # \{ : True; }, : (t.var s.dir (e.pos) (0) e.len) e = , : e, { s.dir : Right = (INFIX "-" () (e.pos e.len)); e.pos; } :: e.pos, e.rest (e.decls (Used t.var) (SUBEXPR (VAR t.name) t.var (e.pos) (e.len))); // STUB: e.vars : t e.rest = e.rest (e.decls); } :: e.vars (e.decls), e.vars : /*empty*/ = e.decls; /* * Returns those parts of e.expr which lengthes are known. Also returns a list * of variables with unknown lengthes. */ Unknown-Vars e.expr = e.expr () () $iter { e.expr : t.first e.rest, { t.first : (VAR t.name), { : True = e.new-expr t.first (e.unknown); :: e.max, : e.max = e.new-expr t.first (e.unknown); e.new-expr (e.unknown t.first); }; e.new-expr t.first (e.unknown); } :: e.new-expr (e.unknown) = e.rest (e.new-expr) (e.unknown); } :: e.expr (e.new-expr) (e.unknown), e.expr : /*empty*/ = e.new-expr (e.unknown); Split-Hard-Left e.expr = e.expr () $iter { e.expr : t.Pt e.rest, { = e.rest (e.hard t.Pt); (e.hard); }; } :: e.expr (e.hard), e.expr : /*empty*/ = e.hard; Split-Hard-Right e.expr = e.expr () $iter { e.expr : e.some t.Pt, { = e.some (t.Pt e.hard); (e.hard); }; } :: e.expr (e.hard), e.expr : /*empty*/ = e.hard; Gener-Label e.QualifiedName = { : s.num, <"+" s.num 1>; 1; } :: s.num, , (e.QualifiedName s.num); Comp-Re e.Re (e.Snt) = // , \{ e.Snt : e.rest-Snt (Comp Sentence) e.other-Snts \? { /* * e.Re is NOT the last if in the e.Snt there is any term which * differs form (Comp e) or we are inside a negation. */ e.rest-Snt : e t.item e, # \{ t.item : (Comp e); } \! $fail; e.Snt : \{ e (Comp Not) e; e (Comp Error) e; e (Comp Notail) e; // ????????????? } \! $fail; /* * If we can reach here then our Re is the last action in the * current path. So we should do TAILCALL or simply assign * values to the function output variables. We can get $fail in * the following block only in the case of an error. So we send * this $fail to the upper sentence. */ { e.Re : (CALL t.Fname e.arg-Re) \? { \? \{ /* * If the sentence doesn't end with * (Comp Retfail) then we can't do tailcall. */ # \{ e.Snt : e (Comp Retfail); } \!\! $fail; /* * Else, if there was '=' after all '\!' and we * are not inside a source block then CAN do * tailcall. */ e.other-Snts : (Comp Cutall) e.rest, # \{ e.rest : e (Comp Notail) e; } \! $fail; /* Else, we CAN do tailcall if we are on the * last branch and there weren't any cuts or * NOFAIL blocks. */ e.other-Snts : e t.item1 e, \{ # t.item1 : \{ (Comp s); } \!\! $fail; t.item1 : \{ (Comp Cut); (Comp Source (Nofail)); } \!\! $fail; }; }; \! # \{ e.rest-Snt : e (Comp Trap) e; }, :: s s.tag t (e.Fin) (e.Fout), ) e.Fout> :: e.out, ) (e.out)>)> :: (e.empty) (e.res-vars), : e = :: e.calls, > :: e.comp-Re (e.decls), :: e.sp-Re, (e.calls) e.decls ) > (Used ) (TAILCALL t.Fname (e.sp-Re) ()); }; :: e.calls, > :: e.comp-Re (e.decls), ) e.comp-Re> :: e.splited-Re, (e.calls) e.decls ) e.splited-Re> RETURN; }; }; :: e.calls, // , (e.calls) ; } :: (e.calls) e.asail-Snt, // , // , \{ e.calls : e (Roll-back t) e = e.Snt : e.Current-Snt (Comp Sentence) e.Other-Snts = // :: e.asail-Others, e.asail-Snt (e.calls) $iter { e.calls : { e.first-calls (Roll-back t.call) = (IF (t.call) e.asail-Snt) (e.first-calls); e.first-calls t.call, { // t.call : (CALL t.Fname t.args (e.ress)), // = // (If-used (e.ress) t.call); t.call; } :: t.call = t.call e.asail-Snt (e.first-calls); }; } :: e.asail-Snt (e.calls), e.calls : /*empty*/ = e.asail-Snt // e.asail-Others; ; e.calls e.asail-Snt; }; Second-Empty? (t.var ()) = ; Good-Res-Var? (t.var (t.F-var)) = ; Comp-Calls e.Re = // , e.Re () () $iter e.Re : { (CALL t.Fname e.arg-Re) e.rest-Re = :: s s.tag t (e.Fin) (e.Fout), (Used ) :: e.used, :: e.arg-calls, > :: e.splited-Re, // , :: e.splited-Re (e.decls), t.Fname : (e.QualifiedName), e.QualifiedName "res" :: e.prefix, /* * We want to generate variables with the names * (e.QualifiedName "res" s.num). * Find maximum s.num used with such prefix. */ 0 $iter { e.vars : e1 ((e.prefix s.n)) e2 = : s.max, s.max e2; s.num; } :: s.num e.vars, e.vars : /*empty*/ = > : e.res-Re s, > :: e.ress, , > :: e.res-Re, e.decls :: e.decls, { s.tag : FUNC? = (Roll-back (CALL t.Fname (e.splited-Re) (e.ress))); (CALL t.Fname (e.splited-Re) (e.ress)); } :: t.call, e.rest-Re (e.calls e.arg-calls e.decls e.used t.call) (e.comp-Re e.res-Re); (PAREN e.paren-Re) e.rest-Re = :: e.paren-calls, :: e.comp-paren-Re, e.rest-Re (e.calls e.paren-calls) (e.comp-Re (PAREN e.comp-paren-Re)); // (REF e) e.rest-Re = // e.rest-Re (e.calls) (e.comp-Re); t.Rt e.rest-Re = e.rest-Re (e.calls) (e.comp-Re t.Rt); } :: e.Re (e.calls) (e.comp-Re), e.Re : /*empty*/, , e.calls; /* * For the future... */ //Norm-Vars e.Sentence = // e.Sentence () $iter { // e.Sentence : t.Statement e.rest, { // t.Statement : \{ // (SVAR e.var) = "s" e.var; // (TVAR e.var) = "v" e.var; // (EVAR e.var) = "e" e.var; // (VVAR e.var) = "t" e.var; // } : s.var-sym e.NEW (e.QualifiedName), // { // e.NEW : NEW = (e.QualifiedName); // (s.var-sym e.QualifiedName); // } :: t.name, Store-Vars e.vars = // , e.vars () $iter { e.vars : (s.var-tag (e.QualifiedName s.last)) e.rest, { s.last : 0 = (e.QualifiedName); = (e.QualifiedName s.last); /*empty*/ = s.var-tag : { SVAR = "s"; TVAR = "t"; VVAR = "v"; EVAR = "e"; VAR = /*empty*/; } :: e.var-sym, (e.var-sym e.QualifiedName s.last); } :: t.name, { ; // do nothing
:: s.tab, , { s.var-tag : VAR = ; s.var-tag; } : { SVAR = , , , ; TVAR = , , ; VVAR = ; // ; EVAR = ; // ; }, , , , , ; }, e.rest (e.new-vars (VAR t.name)); } :: e.vars (e.new-vars), e.vars : /*empty*/ = e.new-vars; Declare-Vars s.type e.vars = e.vars () $iter { e.vars : (VAR t.name) e.rest, { : True; // do nothing { ; // do nothing
:: s.tab, , , , , , , ; }, , (DECL s.type (VAR t.name)); } :: e.new-decl, e.rest (e.decls e.new-decl); } :: e.vars (e.decls), e.vars : /*empty*/ = e.decls; Instantiate-Vars e.vars = e.vars $iter { e.vars : (VAR t.name) e.rest, , e.rest; } :: e.vars, e.vars : /*empty*/; Comp-Assigns (e.vars) e.splited-Re = // ' e.splited-Re>, , e.vars (e.splited-Re) () $iter { e.vars : t.var e.rest-vars, e.splited-Re : (e.Re) e.rest-Re, t.var : (VAR t.name), )>, :: e.Re (e.decls), e.rest-vars (e.rest-Re) (e.assignments e.decls (If-used (t.var) (Used ) (ASSIGN t.var e.Re)) ); } :: e.vars (e.splited-Re) (e.assignments), e.vars : /*empty*/, e.assignments; Get-Static-Exprs e.Re = e.Re () () () $iter { e.Re : t.Rt e.rest, t.Rt : { s.ObjectSymbol, { = e.rest (e.new-Re) (e.decls) (e.expr t.Rt); :: e.expr-var (e.expr-decl), { = "int"; = "word"; } :: s.prefix, :: e.Rt-var (e.Rt-decl) = e.rest (e.new-Re e.expr-var e.Rt-var) (e.decls e.expr-decl e.Rt-decl) (); }; (PAREN e.paren-Re) = :: e.new-paren-Re (e.paren-decls), :: e.expr-var (e.expr-decl), e.rest (e.new-Re e.expr-var (PAREN e.new-paren-Re)) (e.decls e.expr-decl e.paren-decls) (); t.var = :: e.expr-var (e.expr-decl), e.rest (e.new-Re e.expr-var t.var) (e.decls e.expr-decl) (); }; } :: e.Re (e.new-Re) (e.decls) (e.expr), // , e.Re : /*empty*/ = :: e.expr-var (e.expr-decl), e.new-Re e.expr-var (e.decls e.expr-decl); Get-Static-Var s.prefix e.expr, { e.expr : /*empty*/ = /*empty*/ (); { : t.var = t.var (); ("const" s.prefix e.expr) :: t.name, , : e, , , :: s.len, , , , = (VAR t.name) ((EXPR (VAR t.name) e.expr)); }; }; /* * Generates indexes for all varibles 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. */ Gener-Vars 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.num 1> :: s.num, (s.VariableTag (PRAGMA) (e.prefix s.num)) ; }; /* * e.Format is empty, so return s.num -- the last term in the answer. */ s.num; }; Strip-STVE expr = ; Vars e.expr = e.expr () $iter { e.expr : t.first e.rest, t.first : { s.ObjectSymbol = /*empty*/; (REF t.Name) = /*empty*/; (PAREN e.ResultExpression) = ; (CALL (PRAGMA (e) e) t.Fname e.ResultExpression) = ; (CALL t.Fname e.ResultExpression) = ; /* * Next line is needed for obtaining a list of known variables * from &Var-Stack. Function Vars is never called for abstract * syntax's block. */ // (BLOCK e.vars1) = ; 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; Length-of { /*empty*/ = 0; e.Re = e.Re () $iter { e.Re : t.Rt e.rest, t.Rt : { s.ObjectSymbol = 1; (PAREN e) = 1; (REF t.name) = ; (VAR t.name), { ; (Used t.Rt) (LENGTH t.Rt); }; } :: e.new-len, e.rest (e.Length e.new-len); } :: e.Re (e.Length), e.Re : /*empty*/ = // (INFIX "+" e.Length); // , e.Length; }; Ref-Len t.name = { >; >> :: s.len = , s.len; }; /* * Ends good if lengths of all variables in e.expr can be calculated. */ Hard-Exp? e.expr = e.expr $iter { e.expr : t.first e.rest = { t.first : (VAR t.name), { : True; :: e.max, : e.max; = $fail; };; }, e.rest; } :: e.expr, e.expr : /*empty*/; Parenthesize-Operators e.Snt = ; Paren-Op t.Op, { t.Op : (s.tag e), RESULT LEFT RIGHT HARD : e s.tag e = t.Op; NOFAIL FAIL CUTALL CUT STAKE ERROR : e t.Op e = (t.Op); t.Op : (e.expr) = (); t.Op; }; ///* // * Add "VAR" before each SVAR, TVAR, VVAR, and EVAR. // */ //Norm-Vars e.Snt = // () e.Snt $iter { // e.Snt : t.Statement e.rest, { // t.Statement : \{ (SVAR e); (TVAR e); (VVAR e); (EVAR e); } = // t.Statement : (e.var), // (e.new-Snt (VAR e.var)) e.rest; // t.Statement : (e.expr) = // (e.new-Snt ()) e.rest; // /* // * Else we have symbol. So proceed with the rest. // */ // (e.new-Snt t.Statement) e.rest; // }; // } :: (e.new-Snt) e.Snt, // e.Snt : /*empty*/ = // e.new-Snt; Print-Error s.WE e.Descrip t.Pragma = : s.n, >, , , s.WE e.Descrip : { Error! Re = ; Error! Call = ; Error! Pattern = ; Warning! Pattern = ; Error! Var-Re t.var = "' in result expression">; Error! Var-Hard t.var = "' in hard expression">; Error! Var-Type t.var s.type = "' of the variable '" "'">; Error! Cut = ; }; Print-Pragma s.channel (PRAGMA e.pragmas), e.pragmas : { e (FILE e.file-name) e, , $fail; e (LINE s.line s.col) e, , $fail; e = ; }; AS-To-Ref { SVAR = 's'; TVAR = 't'; VVAR = 'v'; EVAR = 'e'; (s.tag t (e.name)) = '.' ; }; ?? t.name e.key = : s.tab, ; Set-Var t.name (e.key) (e.val) = // , : s.tab, ; Lookup-Func t.Fname, \{ ; ; } : s.linkage s.tag t.pragma (e.Fin) (e.Fout) = s.linkage s.tag t.pragma (e.Fin) (e.Fout);