Пример #1
0
 def Index( self, xItem, yItem):
     'xItem = xItem[ yItem]'
     if yItem.mode == eClass.Const :
         if ( yItem.a < 0) or (yItem.a >= xItem.type.len) : mark("bad index") 
         if xItem.mode == eClass.Par : 
             self.Put2( Ldw, self.rh, item.r, item.a); 
             xItem.mode = RegI; 
             xItem.a = 0 
         xItem.a = xItem.a + yItem.a * xItem.type.base.size
     else: 
         size = xItem.type.base.size
         if yItem.mode != eClass.Reg : 
             self.load( yItem) 
             if size == 4 : self.Put1( Lsl, yItem.r, yItem.r, 2) 
             else: self.Put1( Mul, yItem.r, yItem.r, s) 
         if xItem.mode == Var :
             if xItem.r > 0 : self.Put0( Add, yItem.r, SP, yItem.r) 
             else: self.Put0( Add, yItem.r, BP, yItem.r) 
             xItem.mode = eClass.RegI; 
             xItem.r = yItem.r
         elif xItem.mode == eClass.Par :
             self.Put2( Ldw, self.rh, SP, xItem.a); 
             self.Put0( Add, yItem.r, self.rh, yItem.r); 
             xItem.mode = eClass.RegI; 
             xItem.r = yItem.r
         elif xItem.mode == eClass.RegI : 
             self.Put0( Add, xItem.r, xItem.r, yItem.r); 
             self.rh -= 1
Пример #2
0
 def DivOp(self, op, x, yItem): #( LONGINT; VAR x, yItem: Item);   #  x = x op yItem *)
     if op == Lexdiv :
         if (x.mode == eClass.Const) & (yItem.mode == eClass.Const) :
           if yItem.a > 0 : x.a = x.a / yItem.a 
           else: Lex.mark( 'bad divisor') 
         elif (yItem.mode == eClass.Const) & (yItem.a == 2) : 
             self.load( x); 
             self.Put1( Asr, x.r, x.r, 1)
         elif yItem.mode == eClass.Const :
             if yItem.a > 0 : 
                 self.load( x)
                 self.Put1( Div, x.r, x.r, yItem.a) 
             else: Lex.mark( 'bad divisor') 
         else: 
               self.load( yItem); self.load( x)
               self.Put0( Div, self.rh-2, x.r, yItem.r)
               self.rh -= 1; x.r = self.rh-1
     else:   # op = Lex.mod
         if (x.mode == Const) & (yItem.mode == Const) :
             if yItem.a > 0 : x.a = x.a % yItem.a 
             else: Lex.mark( 'bad modulus') 
         elif (yItem.mode == Const) & (yItem.a == 2) : 
             self.load( x)
             self.Put1( And, x.r, x.r, 1)
         elif yItem.mode == Const :
             if yItem.a > 0 : 
                   self.load( x); 
                   self.Put1( Div, x.r, x.r, yItem.a); 
                   self.Put0( Mov+U, x.r, 0, 0) 
             else: mark( 'bad modulus') 
         else: 
             self.load( yItem); self.load( x)
             self.Put0( Div, self.rh-2, x.r, yItem.r)
             self.Put0( Mov+U, self.rh-2, 0, 0)
             self.rh -= 1; x.r = self.rh-1
Пример #3
0
def find(ident):  # -> obj
    'search identifier in curren scope and above'
    for scope in universe:
        for i in scope.idents:
            if i.name == ident: return i
    else:
        mark('undefined')
        return dummy
Пример #4
0
def newObj(name, clss):  # -> objDesc
    scope = universe[0]
    for ident in scope.idents:
        if ident.name == name:
            mark('multiple definitions')
            return ident
    new = osg.ObjDesc(name, clss)
    scope.idents.append(new)
    return new
Пример #5
0
def identList(sym, idList, cl):
    'appends new identifiers to current scope with given class, returns them in a list'
    while sym == Lex.ident:
        idList.append(newObj(lex.value, cl))
        sym = lex.get()
        if sym == Lex.colon: break
        elif sym == Lex.comma: sym = lex.get()
        else: mark('no ,')
    if sym != Lex.colon: mark('no :')
    sym = lex.get()
    return sym
Пример #6
0
 def loadCond( self, item): 
     'emits load of a boolean item'
     if item.type.form == eForm.Boolean :
         if item.mode == eClass.Const : 
             item.r = 15 - item.a * 8 
         else: 
             self.load( item); 
             self.Put1( Cmp, item.r, item.r, 0)
             item.r = NE; self.rh -= 1
         item.mode = eClass.Cond; item.a = 0; item.b = 0
     else: mark( 'not Boolean')
Пример #7
0
def expression(sym, xItem):  # -> sym
    yItem = osg.Item()
    sym = simpleExpression(sym, xItem)
    if (sym >= Lex.eql) and (sym <= Lex.geq):
        op = sym
        sym = lex.get()
        sym = simpleExpression(sym, yItem)
        if xItem.type == yItem.type: gen.Relation(op, xItem, yItem)
        else: mark('incompatible types')
        xItem.type = boolType
    return sym
Пример #8
0
def parameter(sym, par):  # osg.Object
    xItem = osg.Item()
    sym = expression(sym, xItem)
    varpar = par.class_ == eClass.Par
    if compTypes(par.type, xItem.type):
        if not varpar: gen.ValueParam(xItem)
        else: gen.VarParam(xItem, par.type)
    elif ( xItem.type.form == eForm.Array) and (par.type.form == eForm.Array) and \
        ( xItem.type.base.form == par.type.base.form) and (par.type.len < 0) :
        gen.OpenArrayParam(xItem)
    else:
        mark('incompatible parameters')
    return sym
Пример #9
0
def sysProc(sym, pno):
    if sym == Lex.lparen:
        xItem = osg.Item()
        sym = lex.get()
        sym = expression(sym, xItem)
        if pno == 0: gem.ReadInt(xItem)
        elif pno == 1: gen.WriteInt(xItem)
        elif pno == 2: gen.WriteChar(xItem)
        elif pno == 3: gen.WriteLn()
    else:
        mark('no lparen')
    if sym == Lex.rparen: sym = lex.get()
    else: mark('no rparen')
    return sym
Пример #10
0
def procedureDecl(sym):
    global level
    marksize = 4
    sym = lex.get()
    if sym == Lex.ident:
        procid = lex.value
        proc = newObj(name=lex.value, clss=eClass.Proc)
        sym = lex.get()
        parblksize = marksize
        nofpar = 0
        openScope('function')
        level += 1
        proc.value = -1

        if sym == Lex.lparen:  # optional parameters list
            sym = lex.get()
            if sym == Lex.rparen: sym = lex.get()
            else:
                sym, parblksize, nofpar = formalParametersSection(
                    sym, parblksize, nofpar)
                while sym == Lex.semicolon:
                    sym = lex.get()
                    sym, parblksize, nofpar = formalParametersSection(
                        sym, parblksize, nofpar)
                if sym == Lex.rparen: sym = lex.get()
                else: mark(')?')
        locblksize = parblksize
        proc.type = None
        proc.nofpar = nofpar

        sym = check(sym, Lex.semicolon, '; expected')
        sym, locblksize = declarations(sym, locblksize)
        proc.params = universe[0].idents
        while sym == Lex.procedure:
            sym = procedureDecl(sym)
            sym = check(sym, Lex.semicolon, '; expected')
        proc.value = gen.pc
        gen.Enter(parblksize, locblksize)
        if sym == Lex.begin:
            sym = lex.get()
            sym = statSequence(sym)
        sym = check(sym, Lex.end, 'no END')
        if sym == Lex.ident:
            if procid != lex.value: mark('no match')
            sym = lex.get()
        gen.Return(locblksize)
        level -= 1
        closeScope()
    return sym
Пример #11
0
 def Store( self, x, yItem):  #  x <= yItem 
     self.load( yItem);
     if x.mode == eClass.Var :
         if x.r > 0 : # local
             self.Put2( Stw, yItem.r, SP, x.a) 
         else: 
             self.Put2( Stw, yItem.r, BP, x.a) 
     elif x.mode == eClass.Par : 
         self.Put2( Ldw, self.rh, SP, x.a); 
         self.Put2( Stw, yItem.r, self.rh, x.b)
     elif x.mode == eClass.RegI : 
         self.Put2( Stw, yItem.r, x.r, x.a)
         self.rh -= 1
     else: mark( 'illegal assignment')
     self.rh -= 1
Пример #12
0
def sysFunc(sym, xItem, fctno):
    'parse a builtin function'
    if sym == Lex.lparen:
        sym = lex.get()
        if fctno == 0:  # ORD
            sym = expression(sym, xItem)
            gen.Ord(xItem)
            xItem.type = intType
            xItem.type = intType
        elif fctno == 1:  # eot
            osg.eot(xItem)
        if sym == Lex.rparen: sym = lex.get()
        else: mark('rparen expected')
    else:
        mark('param missing')
        osg.MakeConstItem(xItem, intType, 0)
    return sym
Пример #13
0
 def loadAdr( self, item): 
     'emits load of the address of an item'
     if item.mode == eClass.Var :
         if item.r > 0 : # local
             self.Put1(Add, self.rh, SP, item.a); 
             item.r = self.rh 
         else:   # global
             self.Put1(Add, self.rh, BP, item.a) 
         self.incR()
     elif item.mode == eClass.Par: 
         self.Put2(Ldw, self.rh, SP, item.a); 
         self.Put1(Add, self.rh, self.rh, item.b); 
         item.r = self.rh; self.incR()
     elif (item.mode == eClass.RegI) & (item.a != 0) : 
         self.Put1(Add, item.r, item.r, item.a)
     else: mark( 'address error')         
     item.mode = eClass.Reg
Пример #14
0
def declarations(sym, varsize):  # -> sym, varsize
    # sync
    xItem = osg.Item()
    if (sym < Lex.const) and (sym != Lex.end):
        mark('declaration?')
        while True:
            sym = lex.get()
            if (sym >= Lex.const) or (sym == Lex.end): break
    if sym == Lex.const:
        sym = lex.get()
        while sym == Lex.ident:
            obj = newObj(lex.value, eClass.Const)
            sym = lex.get()
            if sym == Lex.eql: sym = lex.get()
            else: mark('=?')
            sym = expression(sym, xItem)
            if xItem.mode == eClass.Const:
                obj.value = xItem.a
                obj.type = xItem.type
            else:
                mark('expression not constant')
            sym = check(sym, Lex.semicolon, '; expected')
    if sym == Lex.type:
        sym = lex.get()
        while sym == Lex.ident:
            obj = newObj(lex.value, eClass.Type)
            sym = lex.get()
            if sym == Lex.eql: sym = lex.get()
            else: mark('=?')
            sym, obj.type = typeDef(sym)
            sym = check(sym, Lex.semicolon, '; expected')
    if sym == Lex.var:
        sym = lex.get()
        iList = []
        sym = identList(sym, iList, eClass.Var)
        sym, tp = typeDef(sym)
        for obj in iList:
            obj.type = tp
            obj.level = level
            obj.value = varsize  # address
            varsize += obj.type.size
        sym = check(sym, Lex.semicolon, '; expected')
    if (sym >= Lex.const) and (sym <= Lex.var):
        mark('declaration in bad order')
    return sym, varsize
Пример #15
0
def selector(sym, xItem):  # osg.Item
    yItem = osg.Item()
    while (sym == Lex.lbrak) or (sym == Lex.period):
        if sym == Lex.lbrak:
            sym = lex.get()
            sym = expression(sym, yItem)
            if xItem.type.form == eForm.Array:
                checkInt(yItem)
                gen.Index(xItem, yItem)
                xItem.type = xItem.type.base
            else:
                mark('not an array')
            sym = check(sym, Lex.rbrak, 'no ]')
        else:  # period
            sym = lex.get()
            if sym == Lex.ident:
                if xItem.type.form == eForm.Record:
                    obj = findField(lex.value, xItem.type.fields)
                    sym = lex.get()
                    gen.Field(xItem, obj)
                    xItem.type = obj.type
                else:
                    mark('not a record')
            else:
                mark('ident?')
    return sym
Пример #16
0
def formalParametersSection(sym, adr, nofpar):
    'parse a group of parameters i.e. ( ...; var a, b, c : int; ...'
    global level
    iList = []
    if sym == Lex.var:
        sym = lex.get()
        sym = identList(sym, iList, eClass.Par)
    else:
        sym = identList(sym, iList, eClass.Var)
    if sym == Lex.ident:
        obj = find(lex.value)
        sym = lex.get()
        if obj.class_ == eClass.Type: tp = obj.type
        else:
            mark('type?')
            tp = intType
    else:
        mark('ident?')
        tp = intType
    if iList[0].class_ == eClass.Var:
        parsize = tp.size
        if tp.form >= eForm.Array: mark('no struct params')
    else: parsize = WordSize  # var are references/pointers
    for obj in iList:
        nofpar += 1
        obj.type = tp
        obj.level = level
        obj.value = adr
        adr += parsize
    return sym, adr, nofpar
Пример #17
0
 def load( self, item): # 
     'emits load of an item in a register'
     if item.mode != eClass.Reg :
         if item.mode == eClass.Var :
             if item.r > 0 : # local
                 self.Put2( Ldw, self.rh, SP, item.a) 
             else:   # global 
                 self.Put2( Ldw, self.rh, BP, item.a) 
             item.r = self.rh; self.incR()
         elif item.mode == eClass.Par : 
             self.Put2( Ldw, self.rh, SP, item.a)   # item.r, item.a); 
             self.Put2( Ldw, self.rh, self.rh, 0); 
             item.r = self.rh; self.incR()
         elif item.mode == eClass.Const :
             if (item.a >= 0x10000) or (item.a < -0x10000) : mark( 'const too large') 
             self.Put1( Mov, self.rh, 0, item.a) 
             item.r = self.rh; self.incR()
         elif item.mode == eClass.RegI : self.Put2( Ldw, item.r, item.r, item.a)
         elif item.mode == eClass.Cond :
             self.Put3( 2, self.negated( item.r), 2);
             self.FixLink( item.b); self.self.Put1( Mov, self.rh, 0, 1); self.Put3(2, 7, 1);
             self.FixLink( item.a); self.self.Put1( Mov, self.rh, 0, 0); 
             item.r = self.rh; self.incR()        
         item.mode = eClass.Reg
Пример #18
0
def Module(sym):
    global level
    if sym == Lex.module_:
        sym = lex.get()
        if sym == Lex.times:
            tag = 1
            sym = lex.get()
        else:
            tag = 0
        gen.Open()
        openScope('module')
        dc = 0
        level = 0
        if sym == Lex.ident:
            modid = lex.value
            sym = lex.get()
            print 'Compiling module:', modid
        else:
            mark('ident?')
        sym = check(sym, Lex.semicolon, '; expected')
        sym, dc = declarations(sym, dc)
        while sym == Lex.procedure:
            sym = procedureDecl(sym)
            sym = check(sym, Lex.semicolon, '; expected')
        gen.Header(dc)
        if sym == Lex.begin:
            sym = lex.get()
            sym = statSequence(sym)
        sym = check(sym, Lex.end, 'no END')
        if sym == Lex.ident:
            if modid != lex.value: Lex.mark('no match')
            sym = lex.get()
        else:
            mark('ident?')
        if sym != Lex.period: mark('. ?')
        # universeView() # dbg
        closeScope()
        if getErrcnt() == 0:
            gen.Close()
            print '\r\nCode generated:', gen.pc, '\tdata:', dc
            return True
        else:
            mark('MODULE?')
            return False
Пример #19
0
def factor(sym, xItem):  # -> sym
    # sync
    if (sym < Lex.char_) or (sym > Lex.ident):
        mark('expression expected')
        while True:
            sym = lex.get()
            if (sym >= Lex.int_) and (sym <= Lex.ident): break
    if sym == Lex.ident:
        obj = find(lex.value)
        sym = lex.get()
        if obj.class_ == eClass.SFunc:
            if not obj.type:
                mark('not a function')
                obj.type = intType
            sym = sysFunc(sym, xItem, obj.value)
            xItem.type = obj.type
        else:
            gen.MakeItem(xItem, obj, level)
            sym = selector(sym, xItem)
    elif sym == Lex.int_:
        gen.MakeConstItem(xItem, intType, lex.value)
        sym = lex.get()
    elif sym == Lex.char_:
        gen.MakeConstItem(xItem, intType, lex.value)
        sym = lex.get()
    elif sym == Lex.lparen:
        sym = lex.get()
        if sym != Lex.rparen: sym = expression1(sym, xItem)
        check(Lex.rparen, 'no )')
    elif sym == Lex.not_:
        sym = lex.get()
        sym = factor(sym, xItem)
        checkBool(xItem)
        osg.Not(xItem)
    elif sym == Lex.false_:
        gen.MakeConstItem(xItem, boolType, 0)
        sym = lex.get()
    elif sym == Lex.true_:
        gen.MakeConstItem(xItem, boolType, 1)
        sym = lex.get()
    else:
        mark('factor?')
        gen.MakeItem(xItem, dummy, level)
    return sym
Пример #20
0
 def incR( self):
     if self.rh < BP : self.rh += 1 
     else: mark("register stack overflow") 
Пример #21
0
def checkBool(item):
    if item.type.form != eForm.Boolean: mark('not Boolean')
Пример #22
0
 def testRange( self, x): 
     '16-bit entity'
     if ( x > 0xFFFF) or (x < - 0x10000) : mark( "value too large")
Пример #23
0
def checkInt(item):
    if item.type.form != eForm.Integer: mark('not integer')
Пример #24
0
def check(sym, s, msg):  # -> sym
    if sym == s:
        sym = lex.get()
        return sym
    else:
        mark(msg)
Пример #25
0
def typeDef(sym):  #  -> sym, type
    if (sym != Lex.ident) and (sym < Lex.array):
        mark('type?')
        while True:
            sym = lex.get()
            if (sym == Lex.ident) or (sym >= Lex.array): break
    if sym == Lex.ident:
        obj = find(lex.value)
        sym = lex.get()
        if obj.class_ == eClass.Type: typed = obj.type
        else: mark('type?')
    elif sym == Lex.array:
        xItem = osg.Item()
        sym = lex.get()
        sym = expression(sym, xItem)
        if (xItem.mode != eClass.Const) or (xItem.a < 0): mark('bad index')
        if sym == Lex.of: sym = lex.get()
        else: mark('OF?')
        sym, tp = typeDef(sym)
        typed = osg.TypeDesc(form=eForm.Array)
        typed.base = tp
        typed.len = xItem.a
        typed.size = typed.len * tp.size
    elif sym == Lex.record:
        sym = lex.get()
        sym = check(sym, Lex.begin, 'expecting {')
        typed = osg.TypeDesc(form=eForm.Record, size=0)
        openScope('record')
        while True:
            if sym == Lex.ident:
                iList = []
                sym = identList(sym, iList, eClass.Field)
                sym, typef = typeDef(sym)
                for obj in iList:
                    obj.type = typef
                    obj.value = typed.size  # offset of the field
                    typed.size += obj.type.size  # grow record size
            if sym == Lex.semicolon: sym = lex.get()
            elif sym == Lex.ident: mark('; ?')
            if sym != Lex.ident: break
        typed.fields = universe[
            0].idents  # move list of fields to type descriptor
        closeScope()
        sym = check(sym, Lex.end, 'no END')
    else:
        mark('ident?')
    return sym, typed
Пример #26
0
 def MakeItem( self, item, obj, curlev): 
     'make an item out of an object'
     item.mode = obj.class_; item.type = obj.type; item.a = obj.value; item.r = obj.level;
     if obj.class_ == eClass.Par : item.b = 0 
     if (obj.level > 0) & (obj.level != curlev) & (obj.class_ != eClass.Const) : mark( 'level error') 
Пример #27
0
def statSequence(sym):
    global level
    xItem = osg.Item()
    yItem = osg.Item()
    while True:
        if not ((sym == Lex.ident) or (sym >= Lex.if_) and
                (sym <= Lex.repeat) or (sym >= Lex.semicolon)):
            mark('statement expected')
            while True:
                sym = lex.get()
                if (sym == Lex.ident) or (sym >= Lex.if_): break

        if sym == Lex.ident:
            obj = find(lex.value)
            sym = lex.get()
            if obj.class_ == eClass.SProc: sym = sysProc(sym, obj.value)
            else:
                gen.MakeItem(xItem, obj, level)
                sym = selector(sym, xItem)
                if sym == Lex.becomes:  # assignment
                    sym = lex.get()
                    sym = expression(sym, yItem)
                    if (xItem.type.form in [
                            eForm.Boolean, eForm.Integer
                    ]) and (xItem.type.form == yItem.type.form):
                        gen.Store(xItem, yItem)
                    else:
                        mark('incompatible assignment')
                elif sym == Lex.eql:
                    mark('should be ==')
                    sym = lex.get()
                    sym = expression(sym, yItem)
                elif sym == Lex.lparen:  # procedure call
                    sym = lex.get()
                    if (obj.class_ == eClass.Proc) and (obj.type == None):
                        sym = paramList(sym, obj)
                        gen.Call(obj)
                    else:
                        mark('not a procedure')
                elif obj.class_ == eClass.Proc:  # procedure call without parameters
                    if obj.nofpar > 0: mark('missing parameters')
                    if not obj.type: gen.Call(obj)
                    else: mark('not a procedure')
                elif (obj.class_ == eClass.SProc) and (obj.value == 3):
                    gen.WriteLn()
                elif obj.class_ == eClass.Type:
                    mark('illegal assignment')
                else:
                    mark('not a procedure')

        elif sym == Lex.if_:
            sym = lex.get()
            sym = expression(sym, xItem)
            checkBool(xItem)
            gen.CFJump(xItem)
            sym = check(sym, Lex.then, 'no :')
            sym = statSequence(sym)
            L = 0
            while sym == Lex.elsif:
                sym = lex.get()
                L = gen.FJump(L)
                gen.fixLink(xItem.a)
                sym = expression(sym, xItem)
                checkBool(xItem)
                gen.CFJump(xItem)
                if sym == Lex.then: sym = lex.get()
                else: mark(':?')
                statSequence
            if sym == Lex.else_:
                sym = lex.get()
                L = gen.FJump(L)
                gen.fixLink(xItem.a)
                sym = statSequence(sym)
            else:
                gen.fixLink(xItem.a)
            gen.fixLink(L)
            if sym == Lex.end: sym = lex.get()
            else: mark('END ?')

        elif sym == Lex.while_:
            sym = lex.get()
            L = gen.pc
            sym = expression(sym, xItem)
            checkBool(xItem)
            gen.CFJump(xItem)
            check(Lex.do, 'no :')
            sym = statSequence(sym)
            gen.BJump(L)
            gen.fixLink(xItem.a)
            check(Lex.end, 'no END')

        elif sym == Lex.repeat:
            sym = lex.get()
            L = gen.pc
            sym = statSequence(sym)
            if sym == Lex.until:
                sym = lex.get()
                sym = expression(sym, xItem)
                checkBool(xItem)
                gen.CBJump(xItem, L)
            else:
                mark('missing UNTIL')
                sym = lex.get()
        gen.checkRegs()
        if sym == Lex.semicolon: sym = lex.get()
        elif sym < Lex.semicolon: mark('missing semicolon?')
        if sym > Lex.semicolon: break
    return sym
Пример #28
0
 def checkRegs( self):
     if self.rh != 0 :
         mark( 'Reg Stack: %d' % self.rh); self.rh = 0