Mercurial > lcfOS
changeset 249:e41e4109addd
Added current position arrow
author | Windel Bouwman |
---|---|
date | Fri, 26 Jul 2013 20:26:05 +0200 |
parents | b10d46e5c8dd |
children | f5fba5b554d7 |
files | python/c3/analyse.py python/c3/astnodes.py python/c3/codegenerator.py python/codeedit.py python/codegenarm.py python/icons/arrow.png python/ide.py python/ir/builder.py python/outstream.py python/ppci/common.py python/target.py python/testc3.py python/zcc.py |
diffstat | 13 files changed, 200 insertions(+), 88 deletions(-) [+] |
line wrap: on
line diff
--- a/python/c3/analyse.py Fri Jul 26 16:46:02 2013 +0200 +++ b/python/c3/analyse.py Fri Jul 26 20:26:05 2013 +0200 @@ -89,7 +89,8 @@ return t elif type(t) is Designator: t = self.resolveDesignator(t, scope) - return self.resolveType(t, scope) + if t: + return self.resolveType(t, scope) elif isinstance(t, Type): # Already resolved?? return t
--- a/python/c3/astnodes.py Fri Jul 26 16:46:02 2013 +0200 +++ b/python/c3/astnodes.py Fri Jul 26 20:26:05 2013 +0200 @@ -242,6 +242,7 @@ class CompoundStatement(Statement): def __init__(self, statements): + super().__init__(None) self.statements = statements for s in self.statements: assert isinstance(s, Statement)
--- a/python/c3/codegenerator.py Fri Jul 26 16:46:02 2013 +0200 +++ b/python/c3/codegenerator.py Fri Jul 26 20:26:05 2013 +0200 @@ -55,6 +55,7 @@ def genCode(self, code): assert isinstance(code, astnodes.Statement) + self.builder.setLoc(code.loc) if type(code) is astnodes.CompoundStatement: for s in code.statements: self.genCode(s)
--- a/python/codeedit.py Fri Jul 26 16:46:02 2013 +0200 +++ b/python/codeedit.py Fri Jul 26 20:26:05 2013 +0200 @@ -13,8 +13,8 @@ return v class InnerCode(QWidget): - textChanged = pyqtSignal() - def __init__(self, scrollArea): + textChanged = pyqtSignal() + def __init__(self, scrollArea): super().__init__(scrollArea) self.scrollArea = scrollArea self.setFont(QFont('Courier', 12)) @@ -23,8 +23,10 @@ self.setCursor(Qt.IBeamCursor) h = QFontMetrics(self.font()).height() self.errorPixmap = QPixmap('icons/error.png').scaled(h, h) + self.arrowPixmap = QPixmap('icons/arrow.png').scaled(h, h) self.blinkcursor = False self.errorlist = [] + self.arrow = None # Initial values: self.setSource('') self.CursorPosition = 0 @@ -32,74 +34,86 @@ t.timeout.connect(self.updateCursor) t.setInterval(500) t.start() - def updateCursor(self): + def updateCursor(self): self.blinkcursor = not self.blinkcursor self.update() #self.update(self.cursorX, self.cursorY, self.charWidth, self.charHeight) - def setSource(self, src): + + def setSource(self, src): self.src = src self.adjust() - def getSource(self): + + def getSource(self): return self.src - def setErrors(self, el): + + def setErrors(self, el): self.errorlist = el self.update() - def setCursorPosition(self, c): + + def setCursorPosition(self, c): self.cursorPosition = clipVal(c, 0, len(self.src)) self.update() - CursorPosition = property(lambda self: self.cursorPosition, setCursorPosition) - @property - def Rows(self): - # Make this nicer: - return self.src.split('\n') - @property - def CursorRow(self): - # TODO: make this nice. - txt = self.src[0:self.cursorPosition] - return len(txt.split('\n')) - @property - def CursorCol(self): - txt = self.src[0:self.cursorPosition] - curLine = txt.split('\n')[-1] - return len(curLine) + 1 - @property - def CurrentLine(self): - return self.getRow(self.CursorRow) - def setRowCol(self, r, c): + + CursorPosition = property(lambda self: self.cursorPosition, setCursorPosition) + + @property + def Rows(self): + # Make this nicer: + return self.src.split('\n') + + @property + def CursorRow(self): + # TODO: make this nice. + txt = self.src[0:self.cursorPosition] + return len(txt.split('\n')) + + @property + def CursorCol(self): + txt = self.src[0:self.cursorPosition] + curLine = txt.split('\n')[-1] + return len(curLine) + 1 + + @property + def CurrentLine(self): + return self.getRow(self.CursorRow) + + def setRowCol(self, r, c): prevRows = self.Rows[:r-1] txt = '\n'.join(prevRows) c = clipVal(c, 1, len(self.getRow(r))) self.CursorPosition = len(txt) + c + 1 self.showRow(self.CursorRow) - def getRow(self, r): + + def getRow(self, r): rows = self.Rows r = r - 1 if r < 0 or r > len(rows) - 1: return '' else: return rows[r] - def showRow(self, r): + + def showRow(self, r): self.scrollArea.ensureVisible(self.xposTXT, r * self.charHeight, 4, self.charHeight) - # Annotations: - def addAnnotation(self, row, col, ln, msg): + # Annotations: + def addAnnotation(self, row, col, ln, msg): pass - # Text modification: - def getChar(self, pos): + # Text modification: + def getChar(self, pos): pass - def insertText(self, txt): + def insertText(self, txt): self.setSource(self.src[0:self.CursorPosition] + txt + self.src[self.CursorPosition:]) self.CursorPosition += len(txt) self.textChanged.emit() - def deleteChar(self): + def deleteChar(self): self.setSource(self.src[0:self.CursorPosition] + self.src[self.CursorPosition+1:]) self.textChanged.emit() - def GotoNextChar(self): + def GotoNextChar(self): if self.src[self.CursorPosition] != '\n': self.CursorPosition += 1 - def GotoPrevChar(self): + def GotoPrevChar(self): if self.src[self.CursorPosition - 1] != '\n': self.CursorPosition -= 1 - def GotoNextLine(self): + def GotoNextLine(self): curLine = self.CurrentLine c = self.CursorCol - 1 # go to zero based self.CursorPosition += len(curLine) - c + 1 # line break char! @@ -109,14 +123,14 @@ else: self.CursorPosition += c self.showRow(self.CursorRow) - def GotoPrevLine(self): + def GotoPrevLine(self): c = self.CursorCol - 1 # go to zero based self.CursorPosition -= c + 1 # line break char! curLine = self.CurrentLine if len(curLine) > c: self.CursorPosition -= len(curLine) - c self.showRow(self.CursorRow) - def paintEvent(self, event): + def paintEvent(self, event): # Helper variables: er = event.rect() chw, chh = self.charWidth, self.charHeight @@ -144,6 +158,8 @@ painter.drawText(self.xposLNA, ypos, '{0}'.format(row)) xpos = self.xposTXT painter.drawText(xpos, ypos, self.getRow(row)) + if self.arrow and self.arrow.row == row: + painter.drawPixmap(self.xposERR, ypos + ydt, self.arrowPixmap) curErrors = [e for e in self.errorlist if e.loc.row == row] for e in curErrors: painter.drawPixmap(self.xposERR, ypos + ydt, self.errorPixmap) @@ -157,9 +173,9 @@ #painter.drawText(x, ypos + chh, e.msg) #if len(curErrors) > 0: # ypos += chh + ypos += chh - ypos += chh - def keyPressEvent(self, event): + def keyPressEvent(self, event): if event.matches(QKeySequence.MoveToNextChar): self.GotoNextChar() elif event.matches(QKeySequence.MoveToPreviousChar): @@ -190,13 +206,15 @@ if char: self.insertText(char) self.update() - def mousePressEvent(self, event): + + def mousePressEvent(self, event): pos = event.pos() if pos.x() > self.xposTXT and pos.x(): c = round((pos.x() - self.xposTXT) / self.charWidth) r = int(pos.y() / self.charHeight) + 1 self.setRowCol(r, c) - def adjust(self): + + def adjust(self): metrics = self.fontMetrics() self.charHeight = metrics.height() self.charWidth = metrics.width('x') @@ -223,6 +241,7 @@ self.setRowCol = self.ic.setRowCol self.FileName = None Source = property(lambda s: s.ic.getSource(), lambda s, v: s.ic.setSource(v)) + def setErrors(self, el): self.ic.setErrors(el) @@ -234,18 +253,18 @@ if not fn: fn = 'Untitled' self.setWindowTitle(fn) + def getFileName(self): return self.filename FileName = property(getFileName, setFileName) if __name__ == '__main__': - app = QApplication(sys.argv) - ce = CodeEdit() - ce.show() - src = ''.join(inspect.getsourcelines(InnerCode)[0]) - ce.Source = src - print(ce.Source) - ce.resize(600, 800) - app.exec() + app = QApplication(sys.argv) + ce = CodeEdit() + ce.show() + src = ''.join(inspect.getsourcelines(InnerCode)[0]) + ce.Source = src + ce.resize(600, 800) + app.exec()
--- a/python/codegenarm.py Fri Jul 26 16:46:02 2013 +0200 +++ b/python/codegenarm.py Fri Jul 26 20:26:05 2013 +0200 @@ -1,5 +1,5 @@ import ir -from target import Label, Comment, Alignment, LabelRef, Imm32 +from target import Label, Comment, Alignment, LabelRef, Imm32, DebugInfo import cortexm3 as arm from ppci import CompilerError @@ -62,23 +62,34 @@ def align(self): self.outs.emit(Alignment(4)) + # Helper functions: def getStack(self, v): off = self.stack_frame.index(v) return off * 4 + def addStack(self, v): self.stack_frame.append(v) return self.getStack(v) + def getGlobal(self, r, g): _global_address = g.name + '__global' self.emit(arm.ldr_pcrel(r, LabelRef(_global_address))) + def loadStack(self, reg, val): self.emit(arm.ldr_sprel(reg, arm.MemSpRel(self.getStack(val)))) + def comment(self, txt): self.emit(Comment(txt)) + def debugInfo(self, loc): + if loc: + self.emit(DebugInfo(loc)) + def generateInstruction(self, ins): self.comment(str(ins)) + if hasattr(ins, 'debugLoc'): + self.debugInfo(ins.debugLoc) if type(ins) is ir.Branch: tgt = LabelRef(ins.target.name) self.emit(arm.b_ins(tgt))
--- a/python/ide.py Fri Jul 26 16:46:02 2013 +0200 +++ b/python/ide.py Fri Jul 26 20:26:05 2013 +0200 @@ -12,6 +12,8 @@ from codeedit import CodeEdit stutil = __import__('st-util') import c3 +import zcc +import outstream class BuildOutput(QTextEdit): @@ -91,6 +93,7 @@ # Create mdi area: self.mdiArea = QMdiArea() self.mdiArea.setViewMode(QMdiArea.TabbedView) + self.mdiArea.setTabsClosable(True) self.setCentralWidget(self.mdiArea) # Create components: @@ -178,9 +181,10 @@ # MDI: def newCodeEdit(self): ce = CodeEdit() - ce.textChanged.connect(self.buildFile) + ce.textChanged.connect(self.parseFile) w = self.mdiArea.addSubWindow(ce) - ce.show() + self.mdiArea.setActiveSubWindow(w) + ce.showMaximized() return ce def activeMdiChild(self): @@ -233,16 +237,26 @@ ce.clearErrors() def pointCode(self, p): - print('PC', p) + # Lookup pc in debug infos: + loc = None + if hasattr(self, 'debugInfo'): + for di in self.debugInfo: + if di.address > p: + loc = di.info + break + if loc: + ce = self.activeMdiChild() + if ce: + ce.ic.arrow = loc + self.showLoc(loc) # Build recepy: - def buildFile(self): + def parseFile(self): ce = self.activeMdiChild() if not ce: return - self.buildOutput.clear() self.diag.clear() - self.buildOutput.append('Starting build') + self.buildOutput.append('Starting parse') ir = self.c3front.build(ce.Source) # Set errors: @@ -254,6 +268,27 @@ self.astViewer.setAst(ast) self.buildOutput.append("Done!") + def buildFile(self): + ce = self.activeMdiChild() + if not ce: + return + self.diag.clear() + self.buildOutput.append('Starting build') + outs = outstream.TextOutputStream() + if not zcc.zcc(ce.Source, outs, self.diag): + # Set errors: + for err in self.diag.diags: + self.buildOutput.append(str(err)) + self.builderrors.setErrorList(self.diag.diags) + ce.setErrors(self.diag.diags) + return + + self.buildOutput.append("Flashing stm32f4 discovery") + code_s = outs.getSection('code') + self.debugInfo = code_s.debugInfos() + + self.buildOutput.append("Done!") + if __name__ == '__main__': app = QApplication(sys.argv) ide = Ide()
--- a/python/ir/builder.py Fri Jul 26 16:46:02 2013 +0200 +++ b/python/ir/builder.py Fri Jul 26 20:26:05 2013 +0200 @@ -29,40 +29,45 @@ return v class Builder: - def __init__(self): + def __init__(self): self.newTmp = ValueGenerator().gen self.newBBint = BBGenerator().gen self.bb = None self.m = None self.fn = None + self.loc = None - # Helpers: - def newBB(self): + # Helpers: + def newBB(self): bb = self.newBBint() self.fn.addBB(bb) return bb - def setModule(self, m): + def setModule(self, m): self.m = m - def newFunction(self, name): + def newFunction(self, name): f = Function(name) self.m.addFunc(f) return f - def newVariable(self, name): + def newVariable(self, name): v = Variable(name) self.m.addVariable(v) return v - def setFunction(self, f): + def setFunction(self, f): self.fn = f - def setBB(self, bb): + def setBB(self, bb): self.bb = bb - def addIns(self, i): - if not self.bb: + def setLoc(self, l): + self.loc = l + + def addIns(self, i): + i.debugLoc = self.loc + if not self.bb: raise Exception('No basic block') - self.bb.addInstruction(i) + self.bb.addInstruction(i)
--- a/python/outstream.py Fri Jul 26 16:46:02 2013 +0200 +++ b/python/outstream.py Fri Jul 26 20:26:05 2013 +0200 @@ -1,5 +1,5 @@ import binascii -from target import Instruction, Label +from target import Instruction, Label, DebugInfo """ The output stream is a stream of instructions that can be output @@ -24,6 +24,10 @@ d.extend(insword) return bytes(d) + def debugInfos(self): + di = [i for i in self.instructions if isinstance(i, DebugInfo)] + return di + class OutputStream: def __init__(self): self.sections = {} @@ -35,8 +39,7 @@ def selectSection(self, s): self.currentSection = s - if not s in self.sections: - self.sections[s] = Section() + self.getSection(s) def getLabelAddress(self, lname): assert isinstance(lname, str) @@ -47,6 +50,11 @@ return i.address return 0 + def getSection(self, name): + if not name in self.sections: + self.sections[name] = Section() + return self.sections[name] + def backpatch(self): """ Fixup references to other parts in the assembler """ for s in self.sections:
--- a/python/ppci/common.py Fri Jul 26 16:46:02 2013 +0200 +++ b/python/ppci/common.py Fri Jul 26 20:26:05 2013 +0200 @@ -13,10 +13,14 @@ return 'Token({0}, {1})'.format(self.typ, self.val) class SourceLocation: - def __init__(self, row, col, ln): - self.row = row - self.col = col - self.length = ln + def __init__(self, row, col, ln): + self.row = row + self.col = col + self.length = ln + self.filename = '' + + def __repr__(self): + return '{}, {}'.format(self.row, self.col) SourceRange = namedtuple('SourceRange', ['p1', 'p2'])
--- a/python/target.py Fri Jul 26 16:46:02 2013 +0200 +++ b/python/target.py Fri Jul 26 20:26:05 2013 +0200 @@ -86,8 +86,10 @@ class Comment(PseudoInstruction): def __init__(self, txt): self.txt = txt + def encode(self): return bytes() + def __repr__(self): return '; {}'.format(self.txt) @@ -107,6 +109,15 @@ pad.append(0) return bytes(pad) +class DebugInfo(PseudoInstruction): + def __init__(self, i): + self.info = i + + def __repr__(self): + return 'DebugInfo: {}'.format(self.info) + + def encode(self): + return bytes() class Register(Operand): def __init__(self, name):
--- a/python/testc3.py Fri Jul 26 16:46:02 2013 +0200 +++ b/python/testc3.py Fri Jul 26 20:26:05 2013 +0200 @@ -284,6 +284,15 @@ ret """ self.expectIR(snippet, block_code) + def testUnknownType(self): + snippet = """package testlocalvar; + function void t() + { + var int2 a; + } + """ + self.expectErrors(snippet, [4]) + def testStruct1(self): snippet = """ package teststruct1;
--- a/python/zcc.py Fri Jul 26 16:46:02 2013 +0200 +++ b/python/zcc.py Fri Jul 26 20:26:05 2013 +0200 @@ -15,17 +15,12 @@ parser.add_argument('-o', '--output', help='Output file', metavar='filename') parser.add_argument('--hexfile', help='Output hexfile', type=argparse.FileType('w')) -def main(args): +def zcc(src, outs, diag, dumpir=False): # Front end: - src = args.source.read() - args.source.close() - diag = ppci.DiagnosticsManager() c3b = c3.Builder(diag) - ircode = c3b.build(src) if not ircode: - diag.printErrors(src) - sys.exit(1) + return # Optimization passes: ircode.check() @@ -36,14 +31,25 @@ sidp.run(ircode) ircode.check() - if args.dumpir: + if dumpir: ircode.dump() + # Code generation: - - #cg = codegen.CodeGenerator(arm_cm3.armtarget) - outs = outstream.TextOutputStream() cg = codegenarm.ArmCodeGenerator(outs) obj = cg.generate(ircode) + return True + +def main(args): + src = args.source.read() + args.source.close() + diag = ppci.DiagnosticsManager() + outs = outstream.TextOutputStream() + + # Invoke compiler: + res = zcc(src, outs, diag, dumpir=args.dumpir) + if not res: + diag.printErrors(src) + sys.exit(1) if args.dumpir: outs.dump() @@ -54,6 +60,7 @@ output_filename = args.output else: output_filename = 'b.output' + with open(output_filename, 'wb') as f: f.write(code_bytes)