zOs/REXX/O

/* copy o begin *******************************************************
    an object is register for a class in o2c
    a class has a list of parents in cParent
    a class has a methodTable cMet with lazy initialization
             a method generator
        otherwise an existing method is simply copied
**********************************************************************/
classInheritsOf: procedure expose m.
parse arg cl, sup
    cl = class4name(cl)
    sup = class4name(sup)
    if m.cl.inheritsOf \== 1 then do
        m.cl.inheritsOf = 1
        call classInheritsOfAdd cl, cl'.INHERITSOF'
        end
    return m.cl.inheritsOf.sup == 1
endProcedure classInheritsOf

classInheritsOfAdd: procedure expose m.
parse arg cl, trg, pa
    pa = classCycle(cl, pa)
    m.trg.cl = 1
    call assert "m.cl == 'u'"
    do cx=1 to m.cl.0
        c1 = m.cl.cx
        if m.c1 == 'u' then
            call classInheritsOfAdd c1, trg, pa
        end
    return
endProcedure classInheritsOf

classClear: procedure expose m.
parse arg cl, m
    do fx=1 to m.cl.fldd.0
        f1 = m || m.cl.fldd.fx
        m.f1 = ''
        end
    return classClearStems(cl, m)
endProcedure classClear

classClearStems: procedure expose m.
parse arg cl, m
    do sx=1 to m.cl.stmD.0
        s1 = m || m.cl.stmD.sx
        m.s1.0 = 0
        end
    return m
endProcedure classClearStems

classCopy: procedure expose m.
parse arg cl, m, t
    do fx=1 to m.cl.fldd.0
        ff = m || m.cl.fldd.fx
        tf = t || m.cl.fldd.fx
        m.tf = m.ff
        end
    do sx=1 to m.cl.stmD.0
        call classCopyStem m.cl.stmD.sx.class,
             , m || m.cl.stmD.sx, t || m.cl.stmD.sx
        end
    return t
endProcedure classCopy

classCopyStem: procedure expose m.
parse arg cl, m, t
    m.t.0 = m.m.0
    do sx=1 to m.t.0
        call classCopy cl, m'.'sx, t'.'sx
        end
    return 0
endProcedure classCopyStem

/*--- return true if src is a rexxVariable a, m.a.c etc. ------------*/
rxIsVar: procedure expose m.
parse arg src
    if pos(left(src, 1), m.ut_rxN1) > 0 then
        return 0
    else
        return verify(src, m.ut_rxId) = 0
endProcedure rxIsVar

/*--- return true if src is a rexxConstant rerpresenting its value --*/
rxIsConst: procedure expose m.
parse arg src, vars                                                   c
    if \ rxIsVar(src) then
        return 0
    srU = translate(src)
    if srU \== src then
        return 0
    srU = '.'srU'.'
    if pos('.GG', srU) > 0 then
        return 0
    if vars == '' then
        return 1
    upper vars
    do vx=1 to words(vars)
        if pos('.'word(vars, vx)'.', vars) > 0 then
            return 0
        end
    return 1
endProcedure rxIsConst

/*--- return rexx code m.cc or mGet('cc') ---------------------------*/
rxMGet: procedure expose m.
parse arg v1, cc, vars
    if cc == '' then
        return 'm.'v1
    else if rxIsConst(cc, vars) then
        return 'm.'v1'.'cc
    else
        return 'mGet('v1 || quote('.'cc, "'")')'
endProcedure rxMGet

/*--- print object --------------------------------------------------*/
objOut: procedure expose m.
parse m, pr, p1
    return classOutDone(m.class_O, m, pr, p1)

/*--- recursively output (with outX:) object a with class t ---------*/
classOut: procedure expose m.
parse arg t, a, pr, p1
    return classOutDone(if(t=='',m.class_O, t), a, pr, p1)

/*--- ouput object a with class t and stopper done ------------------*/
classOutDone: procedure expose m. done.
parse arg t, a, pr, p1
    if p1 == '' then
        p1 = pr
    if right(p1, 1) \== ' ' then
        p1 = p1' '
    if done.ini \== 1 then do
        done.ini = 1
        t = class4Name(t, t)
        p1 = p1'@'a' '
        end
    if done.t.a == 1 then do;
        if t = m.class_o then
             t = objClass(a)
        return outX(p1'done :'className(t) '@'a)
        end
    done.t.a = 1
    if t = m.class_O then do
        if a == '' then
            return outX(p1'obj null')
        t = objClass(a)
        if t = m.class_N | t = m.class_S then
            return outX(p1'obj has no class @'m.a)
        else
            return classOutDone(t, a, pr, p1'isA')
        end

    if t == m.class_V then
        return outX(p1'=' m.a)
    if t == m.class_W == 'w' then
        return outX(p1'}' substr(a, 2))
    if m.t == 'f' then
        return classOutDone(m.t.1, a'.'m.t.name, pr, p1'.'m.t.name)
    if m.t == 'r' then do
        if m.a == '' then
            return outX(p1'refTo :'className(m.t.1) '@null@')
        else
            return classOutDone(m.t.1, m.a, pr,
                    , p1'refTo @'m.a)
        end
    if m.t = 'u' then do
        t1 = m.t.1
        vv = m.t.0 > 0 & m.t.1 == m.class_V
        call outX p1 || if(m.t.name == '', 'union', ':'m.t.name),
             || copies(' =' m.a, vv)
        do ux=1+vv to m.t.0
            call classOutDone m.t.ux, a, pr' '
            end
        return 0
        end
    if m.t = 's' then do
        call outX p1'stem' m.a.0
        do ux=1 to m.a.0
            call classOutDone m.t.1, a'.'ux, pr' ', pr' .'ux
            end
        return 0
        end
    if m.t = 'c' then do
        if m.t.name = m.a then
            call classOutDone m.t.1, a, pr, p1'choice' m.a
        return 0
        end
    if m.t = 'm' then
        return 0
    return err('bad class type' m.t)
endProcedure classOutDone

/*--- mutate and reset an object for a class -----------------------*/
oReset: procedure expose m.
parse arg m, cl, arg, arg2
    interpret classMet(class4name(cl), 'oReset')
    return m
endProcedure oReset

/*--- create an an object of the class cl and reset it --------------*/
oNew: procedure expose m.
parse arg cl, arg, arg2
    interpret classMet(class4name(cl), 'new')
    return m
endProcedure oNew

/*--- return the class of object obj --------------------------------*/
objClass: procedure expose m.
parse arg m
    if arg() > 1 then
        return err('old objClass') / 0
    if symbol('m.o.o2c.m') == 'VAR' then
        return m.o.o2c.m
    else if abbrev(m, m.o_escW) then
        return m.class_w
    else if m \== '' then
        return m.class_S
    else
        return m.class_N
endProcedure objClass

oKindOf: procedure expose m.
parse arg obj, sup
    return classInheritsOf(objClass(obj), sup)

/*--- return the code of method met of object m ---------------------*/
objMet: procedure expose m.
parse arg m, met
    if symbol('m.o.o2c.m') == 'VAR' then
        cl = m.o.o2c.m
    else if abbrev(m, m.o_escW) then
        cl = m.class_w
    else if m \== '' then
        cl = m.class_S
    else
        cl = m.class_N
    if symbol('m.cl.method.met') == 'VAR' then
        return m.cl.method.met
    else
        return classMet(cl, met)    /* will do lazy initialisation */
endProcedure objMet

/*--- return true if obj is kind of string  -------------------------*/
oKindOfString: procedure expose m.
parse arg obj
     return objMet(obj, 'oKindOfString')

/*--- if obj is kindOfString return string
          otherwise return arg(2) or fail ---------------------------*/
oAsString: procedure expose m.
parse arg m
     interpret objMet(m, 'oAsString')

/*--- return the stem of fieldnames of object m ---------------------*/
oFlds: procedure expose m.
parse arg m
    return objMet(m, 'oFlds')
endProcedure oFlds

oFldD: procedure expose m.
parse arg m
    return objMet(m, 'oFldD')
endProcedure oFlds

oClear: procedure expose m.
parse arg m
    interpret objMet(m, 'oClear')
    return m
endProcedure oClear

/*--- copy object m of class cl to t --------------------------------*/
oClaCopy: procedure expose m.
parse arg cl, m, t
    interpret "drop cl;" classMet(cl, 'oCopy')
endProcedure oClaCopy

/*--- copy object m to t / create a new object if t=='' -------------*/
oCopy: procedure expose m.
parse arg m, t
    interpret objMet(m, 'oCopy')
endProcedure oCopy

oCopyGen: procedure expose m.
parse arg cl
    if cl == m.class_N | cl == m.class_S | cl == m.class_W then
        return 'return m'
    call classMet cl, 'new'
    do sx=1 to m.cl.stms.0
        s1 = m.cl.stms.sx
        call classMet m.cl.s2c.s1, 'oCopy'
        end
    return "if t=='' then t = mNew('"cl"');" ,
           "call oMutate t, '"cl"';" ,
           "return classCopy('"cl"', m, t)"
endProcedure oCopyGen

/*--- return a new instance of a subclass of Run
        with code code in method oRun -------------------------------*/
oRunner: procedure expose m.
parse arg code
    return oNew(classNew('n* ORun u ORun, m oRun' code))
endProcedure oRunner

/*--- run method oRun of object m -----------------------------------*/
oRun: procedure expose m.
parse arg m, arg, arg2
    interpret objMet(m, 'oRun')
    return
endProcedure oRun

/*--- run method oRun of object m No Procedure:
        ??? optimize: class only run ???
         use from caller unprotected---------------------------------*/
oRunNP: procedure expose m.
    interpret objMet(arg(1), 'oRun')
    return
endProcedure oRunNP

/*--- run method oRun and return output in new JBuf -----------------*/
oRun2File: procedure expose m.
parse arg rn
    b = jBuf()
    call pipe '+F' , b
    call oRun rn
    call pipe '-'
    return b
endProcedure oRun2File

/*--- cast the object to a file -------------------------------------*/
o2File: procedure expose m.
parse arg m
    interpret objMet(m, 'o2File')
    call err 'o2file did not return'  / 0
endProcedure o2File

/*--- cast the object to a String -----------------------------------*/
o2String: procedure expose m.
parse arg m, fmt
    if arg() = 1 then
        fmt = ' '
    interpret objMet(m, 'o2String')
    return err('o2String did not return')
endProcedure o2String

/*--- return a short string representation of an object o=[...] -----*/
o2Text: procedure expose m.
parse arg m, maxL, fmt
    if maxL == '' then
        maxL = 75
    interpret objMet(m, 'o2Text')
endProcedure o2Text

/*--- return a short string representation of the fields of an obj --*/
o2TexLR: procedure expose m.
parse arg m, maxL, le, ri
    if maxL == '' then
        maxL = 75
    interpret objMet(m, 'o2TexLR')
endProcedure o2TexLR

o2TextFlds: procedure expose m.
parse arg m, cl, maxL
    maxL = maxL - 3
    r = ''
    do fx=1 to m.cl.fldd.0
        c1 = m.cl.fldd.fx.class
        r = r || left(' ', fx > 1)substr(m.cl.fldd.fx, 2)
        if c1 = m.class_V then
            r = r'='
        else if m.c1 == 'r' then
            r = r'=>'
        else
            r = r'=?'c1'?'
        a1 = m || m.cl.fldd.fx
        r = r || m.a1
        if length(r) > maxL then
            return left(r, maxL)'...'
        end
    return r
endProcedure o2TextFlds

o2TextGen: procedure expose m.
parse arg cl, le, ri
    m1 = classMet(cl, 'o2String', '-')
    if m1 \== '-' then do
        if translate(word(m1, 1)) \== 'RETURN' then
            call err 'o2TextGen' className(cl)'#o2String return?:' m1
        return '__r = strip('subword(m1, 2)', "t");',
             'if length(__r) <= maxL then return __r;' ,
             'else return left(__r, maxL-3)"..."'
        end
    call classMet cl, 'oFlds'
    if le = '' & ri = '' then
        return "return o2TextFlds(m, '"cl"', maxL)"
    else
        return "return" le "|| o2TextFlds(m, '"cl"'" ,
              ", maxL - length("le") - length("ri")) || "ri
endProcedure o2TextGen

o2TextStem: procedure expose m.
parse arg st, to, maxL
     do sx=1 to m.st.0
         m.to.sx = o2Text(m.st.sx, maxL)
         end
     m.to.0 = m.st.0
     return to
endProcedure o2TextStem

/*--- cast a String to an object -----------------------------------*/
s2o: procedure expose m.
parse arg str
    return m.o_escW || str
endProcedure s2o
/* copy o end ********************************************************/