diff options
Diffstat (limited to 'src/main/stanza/widthsolver.stanza')
| -rw-r--r-- | src/main/stanza/widthsolver.stanza | 322 |
1 files changed, 0 insertions, 322 deletions
diff --git a/src/main/stanza/widthsolver.stanza b/src/main/stanza/widthsolver.stanza deleted file mode 100644 index b3f72f03..00000000 --- a/src/main/stanza/widthsolver.stanza +++ /dev/null @@ -1,322 +0,0 @@ -;Copyright (c) 2014 - 2016 The Regents of the University of -;California (Regents). All Rights Reserved. Redistribution and use in -;source and binary forms, with or without modification, are permitted -;provided that the following conditions are met: -; * Redistributions of source code must retain the above -; copyright notice, this list of conditions and the following -; two paragraphs of disclaimer. -; * Redistributions in binary form must reproduce the above -; copyright notice, this list of conditions and the following -; two paragraphs of disclaimer in the documentation and/or other materials -; provided with the distribution. -; * Neither the name of the Regents nor the names of its contributors -; may be used to endorse or promote products derived from this -; software without specific prior written permission. -;IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, -;SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, -;ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF -;REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -;REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT -;LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -;A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF -;ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION -;TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR -;MODIFICATIONS. -;Define the STANDALONE flag to run STANDALONE -#if-defined(STANDALONE) : - #include<"core/stringeater.stanza"> - #include<"compiler/lexer.stanza"> - -defpackage widthsolver : - import core - import verse - import stz/lexer - -;============= Language of Constraints ====================== -public definterface WConstraint -public defstruct WidthEqual <: WConstraint : - name: Symbol - value: Exp -public defstruct WidthGreater <: WConstraint : - name: Symbol - value: Exp - -defmethod print (o:OutputStream, c:WConstraint) : - print-all{o, _} $ - match(c) : - (c:WidthEqual) : [name(c) " = " value(c)] - (c:WidthGreater) : [name(c) " >= " value(c)] - -defn construct-eqns (cs: Streamable<WConstraint>) : - val eqns = HashTable<Symbol, False|Exp>(symbol-hash) - val lower-bounds = HashTable<Symbol, List<Exp>>(symbol-hash) - for c in cs do : - match(c) : - (c:WidthEqual) : - eqns[name(c)] = value(c) - (c:WidthGreater) : - lower-bounds[name(c)] = - List(value(c), - get?(lower-bounds, name(c), List())) - - ;Create minimum expressions for lower-bounds - for entry in lower-bounds do : - val v = key(entry) - val exps = value(entry) - if not key?(eqns, v) : - eqns[v] = reduce(EMax, ELit(0), exps) - - ;Return equations - eqns -;============================================================ - -;============= Language of Expressions ====================== -public definterface Exp -public defstruct EVar <: Exp : - name: Symbol -public defstruct EMax <: Exp : - a: Exp - b: Exp -public defstruct EPlus <: Exp : - a: Exp - b: Exp -public defstruct EMinus <: Exp : - a: Exp - b: Exp -public defstruct ELit <: Exp : - width: Int - -defmethod print (o:OutputStream, e:Exp) : - match(e) : - (e:EVar) : print(o, name(e)) - (e:EMax) : print-all(o, ["max(" a(e) ", " b(e) ")"]) - (e:EPlus) : print-all(o, [a(e) " + " b(e)]) - (e:EMinus) : print-all(o, [a(e) " - " b(e)]) - (e:ELit) : print(o, width(e)) - -defn map (f: (Exp) -> Exp, e: Exp) -> Exp : - match(e) : - (e:EMax) : EMax(f(a(e)), f(b(e))) - (e:EPlus) : EPlus(f(a(e)), f(b(e))) - (e:EMinus) : EMinus(f(a(e)), f(b(e))) - (e:Exp) : e - -defn children (e: Exp) -> List<Exp> : - match(e) : - (e:EMax) : list(a(e), b(e)) - (e:EPlus) : list(a(e), b(e)) - (e:EMinus) : list(a(e), b(e)) - (e:Exp) : list() -;============================================================ - -;================== Reading from File ======================= -defn read-exp (x) : - match(unwrap-token(x)) : - (x:Symbol) : - EVar(x) - (x:Int) : - ELit(x) - (x:List) : - val tag = unwrap-token(x[1]) - switch {tag == _} : - `plus : EPlus(read-exp(x[2]), read-exp(x[3])) - `minus : EMinus(read-exp(x[2]), read-exp(x[3])) - `max : EMax(read-exp(x[2]), read-exp(x[3])) - else : error $ string-join $ - ["Improper expression: " x] - -defn read (filename: String) : - var form:List = lex-file(filename) - val cs = Vector<WConstraint>() - while not empty?(form) : - val x = unwrap-token(form[0]) - val op = form[1] - val e = read-exp(form[2]) - form = tailn(form, 3) - add{cs, _} $ - switch {unwrap-token(op) == _} : - `= : WidthEqual(x, e) - `>= : WidthGreater(x, e) - else : error $ string-join $ ["Unsupported Operator: " op] - cs -;============================================================ - -;============ Operations on Expressions ===================== -defn occurs? (v: Symbol, exp: Exp) : - match(exp) : - (exp: EVar) : name(exp) == v - (exp: Exp) : any?(occurs?{v, _}, children(exp)) - -defn freevars (exp: Exp) : - to-list $ generate<Symbol> : - defn loop (exp: Exp) : - match(exp) : - (exp: EVar) : yield(name(exp)) - (exp: Exp) : do(loop, children(exp)) - loop(exp) - -defn contains-only-max? (exp: Exp) : - match(exp) : - (exp:EVar|EMax|ELit) : all?(contains-only-max?, children(exp)) - (exp) : false - -defn simplify (exp: Exp) : - match(map(simplify,exp)) : - (exp: EPlus) : - match(a(exp), b(exp)) : - (a: ELit, b: ELit) : - ELit(width(a) + width(b)) - (a: ELit, b) : - if width(a) == 0 : b - else : exp - (a, b: ELit) : - if width(b) == 0 : a - else : exp - (a, b) : - exp - (exp: EMinus) : - match(a(exp), b(exp)) : - (a: ELit, b: ELit) : - ELit(width(a) - width(b)) - (a, b: ELit) : - if width(b) == 0 : a - else : exp - (a, b) : - exp - (exp: EMax) : - match(a(exp), b(exp)) : - (a: ELit, b: ELit) : - ELit(max(width(a), width(b))) - (a: ELit, b) : - if width(a) == 0 : b - else : exp - (a, b: ELit) : - if width(b) == 0 : a - else : exp - (a, b) : - exp - (exp: Exp) : - exp - -defn eval (exp: Exp, state: HashTable<Symbol,Int>) -> Int : - defn loop (e: Exp) -> Int : - match(e) : - (e: EVar) : state[name(e)] - (e: EMax) : max(loop(a(e)), loop(b(e))) - (e: EPlus) : loop(a(e)) + loop(b(e)) - (e: EMinus) : loop(a(e)) - loop(b(e)) - (e: ELit) : width(e) - loop(exp) -;============================================================ - - -;================ Constraint Solver ========================= -defn substitute (solns: HashTable<Symbol, Exp>, exp: Exp) : - match(exp) : - (exp: EVar) : - match(get?(solns, name(exp), false)) : - (s:Exp) : substitute(solns, s) - (f:False) : exp - (exp) : - map(substitute{solns, _}, exp) - -defn dataflow (eqns: HashTable<Symbol, False|Exp>, solns: HashTable<Symbol,Exp>) : - var progress?:True|False = false - for entry in eqns do : - if value(entry) != false : - val v = key(entry) - val exp = simplify(substitute(solns, value(entry) as Exp)) - if occurs?(v, exp) : - eqns[v] = exp - else : - eqns[v] = false - solns[v] = exp - progress? = true - progress? - -defn fixpoint (eqns: HashTable<Symbol, False|Exp>, solns: HashTable<Symbol,Exp>) : - label<False|True> break : - for v in keys(eqns) do : - if eqns[v] != false : - val fix-eqns = fixpoint-eqns(v, eqns) - val has-fixpoint? = all?(contains-only-max?{value(_)}, fix-eqns) - if has-fixpoint? : - val soln = solve-fixpoint(fix-eqns) - for s in soln do : - solns[key(s)] = ELit(value(s)) - eqns[key(s)] = false - break(true) - false - -defn fixpoint-eqns (v: Symbol, eqns: HashTable<Symbol,False|Exp>) : - val vs = HashTable<Symbol,Exp>(symbol-hash) - defn loop (v: Symbol) : - if not key?(vs, v) : - val eqn = eqns[v] as Exp - vs[v] = eqn - do(loop, freevars(eqn)) - loop(v) - to-list(vs) - -defn solve-fixpoint (eqns: List<KeyValue<Symbol,Exp>>) : - ;Solve for fixpoint - val sol = HashTable<Symbol,Int>(symbol-hash) - do({sol[key(_)] = 0}, eqns) - defn loop () : - var progress?:True|False = false - for eqn in eqns do : - val v = key(eqn) - val x = eval(value(eqn), sol) - if x != sol[v] : - sol[v] = x - progress? = true - progress? - while loop() : false - - ;Return solutions - to-list(sol) - -defn backsubstitute (vs:Streamable<Symbol>, solns: HashTable<Symbol,Exp>) : - val widths = HashTable<Symbol,False|Int>(symbol-hash) - defn get-width (v:Symbol) : - if key?(solns, v) : - val vs = freevars(solns[v]) - ;Calculate dependencies - for v in vs do : - if not key?(widths, v) : - widths[v] = get-width(v) - ;Compute value - if none?({widths[_] == false}, vs) : - eval(solns[v], widths as HashTable<Symbol,Int>) - - ;Compute all widths - for v in vs do : - widths[v] = get-width(v) - - ;Return widths - to-list $ generate<WidthEqual> : - for entry in widths do : - if value(entry) != false : - yield $ WidthEqual(key(entry), ELit(value(entry) as Int)) - -public defn solve-widths (cs: Streamable<WConstraint>) : - ;Copy to new hashtable - val eqns = construct-eqns(cs) - val solns = HashTable<Symbol,Exp>(symbol-hash) - defn loop () : - dataflow(eqns, solns) or - fixpoint(eqns, solns) - while loop() : false - backsubstitute(keys(eqns), solns) - -;================= Main ===================================== -#if-defined(STANDALONE) : - defn main () : - val input = lex(commandline-arguments()) - error("No input file!") when length(input) < 2 - val cs = read(to-string(input[1])) - do(println, solve-widths(cs)) - - main() -;============================================================ - |
