Языки визуального программирования никогда не развивались, потому что никто еще не сделал это правильно. Точно так же, как C ++ / visual studio были подходящей технологией для людей во время их появления.
Однако, эра общения с нашими компьютерами (голосовая служба Alex) и программирование с использованием более приятных инструментов, чем текстовые редакторы, настали.
Вот начало того, над чем я работаю. Я пытаюсь запустить мой проект, так как, если вы создаете крутой инструмент программирования , почему бы сам инструмент не был в конечном итоге написан на языке ввода инструмента. Сначала я начал с рендеринга своих собственных графиков с помощью PyQt5 / QGraphicsScene, но отладка 2D-сцены на самом деле чрезвычайно сложна - если только у вас нет визуального графика для программирования! Таким образом, рендеринг моего собственного графика и написание редактора графиков наступают после того, как я смогу запустить базовые графики. Мой любимый редактор графиков общего назначения - YEd. Он выводит .graphml, что хорошо, потому что библиотека networkx для python уже может читать в .graphml (единственная проблема - загрузка в цветах графика + другие свойства, кроме позиции; так что функция будет ждать, пока мы будем делать наши собственные рисунки графика).
Вот пример входного графика:
Вот базовый код для его запуска:
import networkx as nx
from PyQt5.QtCore import QThread, QObject, pyqtSignal
from PyQt5.QtGui import QColor
from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton
import re
import sys
EDAT = 2
NDAT = 1
class CodeGraphThread(QThread):
ifRgx = r'^if\s+(.+)\s*$'
elseRgx = r'\s+|^$'
def __init__(self, graph, parent=None):
super(CodeGraphThread, self).__init__(parent)
self._nodes = {}
self.setGraph(graph)
self._retVal = None
self._locals = []
def setGraph(self, graph):
self._graph = graph
G = graph.G()
nodes = [x for x in G.nodes(data=True) if x[NDAT]['label'] == 'start']
if nodes: self._setStart(nodes[0][0])
def _setStart(self, nstr):
self._nodes['start'] = nstr
def start(self):
self._running = True
self._nodes['current'] = self._nodes['start']
QThread.start(self)
def _exec(self, codeText):
try:
exec('self._retVal=' + codeText)
except:
try:
exec(codeText)
except:
self.codeGraph().errorMessage.emit('Coudln\'t execute code: "' + codeText + '"')
def returnVal(self):
return self._retVal
def run(self):
while self._running:
cg = self.codeGraph()
G = cg.G()
current = self._nodes['current']
#TODO transfer over to regex system
data = [d for x,d in G.nodes(data=True) if x == current and 'label' in d and d['label'] not in ['start']]
if data:
codeText = data[0]['label']
self._exec(codeText)
rgx = self.ifRgx
edges = cg.edgesFr(current, rgx)
if edges:
e= edges[0]
ifArg = cg.matches(rgx).group(1)
self._exec(ifArg)
if self.returnVal():
self._nodes['current'] = e[1]
continue
rgx = self.elseRgx
edges = cg.edgesFr(current, rgx)
edges += cg.edgesFr(current, None)
if edges:
e = edges[0]
self._nodes['current'] = e[1]
continue
break
def codeGraph(self):
return self._graph
class CodeGraph(QObject):
errorMessage = pyqtSignal(str)
statusMessage = pyqtSignal(str)
_rgxMemo = {}
def __init__(self, gmlpath=None):
QObject.__init__(self)
if gmlpath != None:
self.loadGraphML(gmlpath)
else:
self._gmlpath = None
self._G = nx.MultiDiGraph()
self._thread = CodeGraphThread(self)
def G(self):
return self._G
def loadGraphML(self, gmlpath):
self._gmlpath = gmlpath
self._G = nx.read_graphml(gmlpath)
def saveGraphML(self, gmlpath):
self._gmlpath = gmlpath
nx.write_graphml(self._G, gmlpath)
def debugPrintNodes(self):
print(self._G.nodes(data=True))
def debugPrintEdges(self):
print(self._G.edges(data=True))
def matches(self, rgx):
if rgx in self._rgxMemo:
return self._rgxMemo[rgx][1]
return None
def rgx(self, rgx):
if rgx not in self._rgxMemo:
self._rgxMemo[rgx] = [re.compile(rgx), None]
return self._rgxMemo[rgx][0]
def rgxMatch(self, rgx, string):
if rgx not in self._rgxMemo:
rgx_ = self.rgx(rgx)
else:
rgx_ = self._rgxMemo[rgx][0]
match = self._rgxMemo[rgx][1] = rgx_.match(string)
return match
def edgesFr(self, n0, rgx):
if rgx != None:
return [(u,v,d) for u,v,d in self.G().edges(data=True) if u == n0 and 'label' in d and self.rgxMatch(rgx, d['label'])]
else:
return [(u,v,d) for u,v,d in self.G().edges(data=True) if u == n0 and 'label' not in d]
if __name__ == '__main__':
cg = CodeGraph('unnamed0.graphml')
cgthread = CodeGraphThread(cg)
def printError(errorMsg):
print(errorMsg)
cg.errorMessage.connect(printError)
# Qt application reqd for QThread testing
app = QApplication(sys.argv)
win = QMainWindow()
win.setWindowTitle('PyGraphML Practice 0')
button0 = QPushButton('Start thread running')
button0.clicked.connect(cgthread.start)
win.setCentralWidget(button0)
win.show()
sys.exit(app.exec_())
Текущие проблемы: Python 3 плохо обрабатывает exec / locals () (следовательно, использует self.x вместо просто x), поэтому подумайте об использовании стороннего интерпретатора python или просто статической модификации кода.
Не говорю, что мой инструмент еще что-то делает правильно. Для того, чтобы все было сделано правильно, также должны быть инструменты автоматического рефакторинга, отладки и т. Д.