Beispiel #1
0
def genVar(x):
    # assuming x is ST.Var, ST.Ref, ST.Const
    # for ST.Const: no code, x.val is constant
    # for ST.Var: x.reg is FP for local, 0 for global vars,
    #   x.adr is relative or absolute address
    # for ST.Ref: address is loaded into register
    # returns ST.Var, ST.Const
    if type(x) == Const: y = x
    else:
        if x.lev == 0: s = R0
        elif x.lev == curlev: s = FP
        else:
            mark('level!')
            s = R0
        y = Var(x.tp)
        y.lev = x.lev
        if type(x) == Ref:  # reference is loaded into register
            r = obtainReg()
            putM('lw', r, s, x.adr)
            y.reg, y.adr = r, 0
        elif type(x) == Var:
            y.reg, y.adr = s, x.adr
        else:
            y = x  # error, pass dummy item
    return y
Beispiel #2
0
def genVar(x):
    # assuming x is ST.Var, ST.Ref, ST.Const
    # for ST.Const: no code, x.val is constant
    # for ST.Var: x.reg is FP for local, 0 for global vars,
    #   x.adr is relative or absolute address
    # for ST.Ref: address is loaded into register
    # returns ST.Var, ST.Const
    if type(x) == Const:
        y = x
    else:
        if x.lev == 0:
            s = R0
        elif x.lev == curlev:
            s = FP
        else:
            mark("level!")
            s = R0
        y = Var(x.tp)
        y.lev = x.lev
        if type(x) == Ref:  # reference is loaded into register
            r = obtainReg()
            putM("lw", r, s, x.adr)
            y.reg, y.adr = r, 0
        elif type(x) == Var:
            y.reg, y.adr = s, x.adr
        else:
            y = x  # error, pass dummy item
    return y
Beispiel #3
0
def genRelation(op, x, y):
    loadItem(x)
    loadItem(y)
    asm.extend(['i32.eq'] if op == EQ else ['i32.ne'] if op ==
               NE else ['i32.lt_s'] if op == LT else ['i32.gt_s'] if op ==
               GT else ['i32.le_s'] if op == LE else ['i32.ge_s'] if op ==
               GE else ['i32.and'] if op ==
               ELEMENT else ['i32.and', 'i32.eq'] if op ==
               SUBSET else ['i32.or', 'i32.eq'] if op == SUPERSET else '?')
    x = Var(Bool)
    x.lev = Stack
    return x
Beispiel #4
0
def program():
    """
    Parses
        program = "program" ident ";" declarations compoundStatement.
    Generates code if no error is reported
    """
    newObj('boolean', Type(Bool))
    Bool.size = 8  # 64 bit sizes
    newObj('integer', Type(Int))
    Int.size = 8
    newObj('true', Const(Bool, 1))
    newObj('false', Const(Bool, 0))
    newObj('read', StdProc([Ref(Int)]))
    newObj('write', StdProc([Var(Int)]))
    newObj('writeln', StdProc([]))
    progStart()
    if SC.sym == PROGRAM: getSym()
    else: mark("'program' expected", 64)
    ident = SC.val
    if SC.sym == IDENT: getSym()
    else: mark('program name expected', 65)
    if SC.sym == SEMICOLON: getSym()
    else: mark('; expected', 66)
    declarations(genGlobalVars)
    progEntry(ident)
    x = compoundStatement()
    return progExit(x)
Beispiel #5
0
def program():
    newDecl('boolean', Type(CG.genBool(Bool)))
    newDecl('integer', Type(CG.genInt(Int)))
    newDecl('true', Const(Bool, 1))
    newDecl('false', Const(Bool, 0))
    newDecl('read', StdProc([Ref(Int)]))
    newDecl('write', StdProc([Var(Int)]))
    newDecl('writeln', StdProc([]))
    CG.genProgStart()
    if SC.sym == PROGRAM:
        getSym()
    else:
        mark("'program' expected")
    ident = SC.val
    if SC.sym == IDENT:
        getSym()
    else:
        mark('program name expected')
    if SC.sym == SEMICOLON:
        getSym()
    else:
        mark('; expected')
    declarations(CG.genGlobalVars)
    CG.genProgEntry(ident)
    x = compoundStatement()
    return CG.genProgExit(x)
Beispiel #6
0
def genVar(x):
    if x.lev == 0: s = R0  # global variable at x.adr
    elif x.lev == curlev: s = FP  # local variable, FP relative
    else:
        mark('level!')
        s = R0
    y = Var(x.tp)
    y.lev = x.lev
    if type(x) == Ref:  # reference is loaded into register
        r = obtainReg()
        putMemOp('lw', r, s, x.adr)
        y.reg, y.adr = r, 0  # variable at (y.reg)
    elif type(x) == Var:
        y.reg, y.adr = s, x.adr
    else:
        assert False
    return y
Beispiel #7
0
def program():
    newDecl('boolean', Type(CG.genBool(Bool)))
    newDecl('integer', Type(CG.genInt(Int)))
    newDecl('true', Const(Bool, 1))
    newDecl('false', Const(Bool, 0))
    newDecl('read', StdProc([], [Var(Int)]))
    newDecl('write', StdProc([Var(Int)], []))
    newDecl('writeln', StdProc([], []))
    CG.genProgStart()
    declarations(CG.genGlobalVars)
    if SC.sym == PROGRAM: getSym()
    else: mark("'program' expected")
    ident = SC.val
    if SC.sym == IDENT: getSym()
    else: mark('program name expected')
    openScope(); CG.genProgEntry(ident); x = body(ident, 0)
    closeScope(); x = CG.genProgExit(x)
    return x
Beispiel #8
0
def declarations(allocVar):
    while SC.sym == CONST:
        getSym()
        if SC.sym == IDENT: ident = SC.val; getSym()
        else: mark("constant name expected")
        if SC.sym == EQ: getSym()
        else: mark("= expected")
        x = expression()
        if type(x) == Const: newDecl(ident, x)
        else: mark('expression not constant')
    while SC.sym == TYPE:
        getSym()
        if SC.sym == IDENT: ident = SC.val; getSym()
        else: mark("type name expected")
        if SC.sym == EQ: getSym()
        else: mark("= expected")
        x = typ(); newDecl(ident, x)  #  x is of type ST.Type
    start = len(topScope())
    while SC.sym == VAR:
        getSym(); typedIds()
    var = allocVar(topScope(), start)
    while SC.sym == PROCEDURE:
        getSym()
        if SC.sym == LPAREN:
            getSym()
            if SC.sym == IDENT: r = SC.val; getSym()
            else: mark("identifier expected")
            if SC.sym == COLON: getSym()
            else: mark("':' expected")
            tp = typ().val
            if SC.sym == RPAREN: getSym()
            else: mark(") expected")
        else: r = None
        if SC.sym == IDENT: ident = SC.val; getSym()
        else: mark("procedure name expected")
        newDecl(ident, Proc([], [])) #  entered without parameters
        sc = topScope(); openScope() # new scope for parameters and body
        if r: newDecl(r, Var(tp))
        if SC.sym == LPAREN: getSym()
        else: mark("( expected")
        if SC.sym == IDENT: typedIds()
        fp = topScope()
        if SC.sym == RPAREN: getSym()
        else: mark(") expected")
        d = len(fp)
        if SC.sym == RARROW:
            getSym()
            if SC.sym == LPAREN: getSym()
            else: mark('( expected')
            typedIds()
            if SC.sym == RPAREN: getSym()
            else: mark(') expected')
        sc[-1].par, sc[-1].res = fp[:d], fp[d:] #  procedure parameters updated
        para = CG.genProcStart(ident, fp[:d], fp[d:])
        body(ident, para); closeScope() #  scope for parameters and body closed
    return var
Beispiel #9
0
def genVar(x): # version supporting parameters in registers
    if 0 < x.lev < curlev: mark('level!')
    if type(x) == Ref:
        y = Var(x.tp); y.lev = x.lev
        if x.reg in ('$a0', '$a1', '$a2', '$a3'): # reference already in register, use it
            y.reg, y.adr = x.reg, 0 # variable at M[y.reg]
        else: # reference is loaded into register
            y.reg, y.adr = obtainReg(), 0 # variable at M[y.reg]
            putMemOp('lw', y.reg, x.reg, x.adr)
    elif type(x) == Var:
        if x.reg in ('$a0', '$a1', '$a2', '$a3'): # value already in register, use it
            y = Reg(x.tp, x.reg) #; y.lev, x.adr = x.lev, x.adr
        else:
            y = Var(x.tp); y.lev, y.reg, y.adr = x.lev, x.reg, x.adr
    else: assert False
    return y
Beispiel #10
0
def genIndex(x, y):
    # x[y], assuming x.tp is Array and x is global Var, local Var
    # and y is Const, local Var, global Var, stack Var
    if x.lev == MemAbs and type(y) == Const:
        x.adr += (y.val - x.tp.lower) * x.tp.base.size
        x.tp = x.tp.base
    else:
        loadItem(y)
        if x.tp.lower != 0:
            asm.append('i32.const ' + str(x.tp.lower))
            asm.append('i32.sub')
        asm.append('i32.const ' + str(x.tp.base.size))
        asm.append('i32.mul')
        if x.lev > 0: asm.append('local.get $' + x.name)
        elif x.lev == MemAbs: asm.append('i32.const ' + str(x.adr))
        asm.append('i32.add')
        x = Var(x.tp.base)
        if x.tp in (Int, Bool) or type(x.tp) == Set: x.lev = MemInd
        else: x.lev = Stack
    return x
Beispiel #11
0
def typedIds():
    if SC.sym == IDENT: tid = [SC.val]; getSym()
    else: mark("identifier expected")
    while SC.sym == COMMA:
        getSym()
        if SC.sym == IDENT: tid.append(SC.val); getSym()
        else: mark('identifier expected')
    if SC.sym == COLON: getSym()
    else: mark("':' expected")
    tp = typ().val
    for i in tid: newDecl(i, Var(tp))
    while SC.sym == COMMA:
        getSym()
        if SC.sym == IDENT: tid = [SC.val]; getSym()
        else: mark("identifier expected")
        while SC.sym == COMMA:
            getSym()
            if SC.sym == IDENT: tid.append(SC.val); getSym()
            else: mark('identifier expected')
        if SC.sym == COLON: getSym()
        else: mark("':' expected")
        tp = typ().val
        for i in tid: newDecl(i, Var(tp))
Beispiel #12
0
def program():
    """
    Parses
        program = "program" «write('program ')» ident «write(ident)»
            ";" «write(';')» declarations compoundStatement(1).
    Generates code if no error is reported
    """
    newObj('boolean', Type(Bool))
    Bool.size = 4
    newObj('integer', Type(Int))
    Int.size = 4
    newObj('true', Const(Bool, 1))
    newObj('false', Const(Bool, 0))
    newObj('read', StdProc([Ref(Int)]))
    newObj('write', StdProc([Var(Int)]))
    newObj('writeln', StdProc([]))
    CG.progStart()
    if SC.sym == PROGRAM:
        #
        write('program ')
        writeHtml('program ')
        #
        getSym()
    else:
        mark("'program' expected")
    ident = SC.val
    if SC.sym == IDENT:
        #
        write(ident)
        writeHtml(ident, _class='ident')
        #
        getSym()
    else:
        mark('program name expected')
    if SC.sym == SEMICOLON:
        getSym()
        #
        write(';')
        writeln()
        writeHtml(';')
        writeHtmlLn()
        #
    else:
        mark('; expected')
    declarations(CG.genGlobalVars)
    CG.progEntry(ident)
    x = compoundStatement(1)
    return CG.progExit(x)
Beispiel #13
0
def genVar(x):
    if Global < x.lev < curlev: mark('WASM: level!')
    y = Var(x.tp)
    y.lev, y.name = x.lev, x.name
    if x.lev == MemAbs: y.adr = x.adr
    return y
Beispiel #14
0
def genUnaryOp(op, x):
    loadItem(x)
    if op == MINUS:
        asm.append('i32.const -1')
        asm.append('i32.mul')
        x = Var(Int)
        x.lev = Stack
    elif op == CARD:
        asm.append('i32.popcnt')
        x = Var(Int)
        x.lev = Stack
    elif op == COMPLEMENT:
        u = (1 << x.tp.length) - 1  # x.tp.length 1's
        u = u << x.tp.lower  # universe of base type
        asm.append('i32.const ' + hex(u))
        asm.append('i32.xor')
        x = Var(x.tp)
        x.lev = Stack
    elif op == SET:
        asm.append('local.set $0')
        asm.append('i32.const 1')
        asm.append('local.get $0')
        asm.append('i32.shl')
        x = Var(Set(0, 32))
        x.lev = Stack
    elif op == NOT:
        asm.append('i32.eqz')
        x = Var(Bool)
        x.lev = Stack
    elif op == AND:
        asm.append('if (result i32)')
        x = Var(Bool)
        x.lev = Stack
    elif op == OR:
        asm.append('if (result i32)')
        asm.append('i32.const 1')
        asm.append('else')
        x = Var(Bool)
        x.lev = Stack
    elif op == ELEMENT:
        asm.append('local.set $0')
        asm.append('i32.const 1')
        asm.append('local.get $0')
        asm.append('i32.shl')
        x = Var(Int)
        x.lev = Stack
    elif op in {SUBSET, SUPERSET}:
        asm.append('local.tee $0')
        asm.append('local.get $0')
        x.lev = Stack
    else:
        mark('WASM: unary operator?')
    return x
Beispiel #15
0
def genRead(x):
    asm.append('call $read')
    y = Var(Int)
    y.lev = Stack
    genAssign(x, y)
Beispiel #16
0
def genCall(rp, pr, ap):  # result (or None), procedure, actual parameters
    asm.append('call $' + pr.name)
    for r in reversed(rp):
        y = Var(Int)
        y.lev = Stack
        genAssign(r, y)
Beispiel #17
0
def genRightAssign(x):
    loadItem(x)
    y = Var(x.tp)
    y.lev = Stack
    return y
Beispiel #18
0
def genBinaryOp(op, x, y):
    if op in (PLUS, MINUS, TIMES, DIV, MOD):
        loadItem(x)
        loadItem(y)
        asm.append('i32.add' if op == PLUS else 'i32.sub' if op == MINUS else
                   'i32.mul' if op == TIMES else 'i32.div_s' if op ==
                   DIV else 'i32.rem_s' if op == MOD else '?')
        x = Var(Int)
        x.lev = Stack
    elif op in {UNION, INTERSECTION}:
        loadItem(x)
        loadItem(y)
        asm.append('i32.or' if op == UNION else 'i32.and' if op ==
                   INTERSECTION else '?')
        x = Var(x.tp)
        x.lev = Stack
    elif op == AND:
        loadItem(y)  # x is already on the stack
        asm.append('else')
        asm.append('i32.const 0')
        asm.append('end')
        x = Var(Bool)
        x.lev = Stack
    elif op == OR:
        loadItem(y)  # x is already on the stack
        asm.append('end')
        x = Var(Bool)
        x.lev = Stack
    else:
        mark('WASM: binary operator?')
    return x