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
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
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
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)
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)
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
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
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
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
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
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))
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)
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
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
def genRead(x): asm.append('call $read') y = Var(Int) y.lev = Stack genAssign(x, y)
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)
def genRightAssign(x): loadItem(x) y = Var(x.tp) y.lev = Stack return y
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