dia r4316 - in trunk: . plug-ins/python
- From: hans svn gnome org
- To: svn-commits-list gnome org
- Subject: dia r4316 - in trunk: . plug-ins/python
- Date: Mon, 9 Mar 2009 23:19:30 +0000 (UTC)
Author: hans
Date: Mon Mar 9 23:19:30 2009
New Revision: 4316
URL: http://svn.gnome.org/viewvc/dia?rev=4316&view=rev
Log:
2009-03-09 Hans Breuer <hans breuer org>
* plug-ins/python/codegen.py : PascalRenderer by Johann Glaser and
some adjustments to (Cxx/Py/Java)Renderer to almost get on par
(now really commited)
Modified:
trunk/ChangeLog
trunk/plug-ins/python/codegen.py
Modified: trunk/plug-ins/python/codegen.py
==============================================================================
--- trunk/plug-ins/python/codegen.py (original)
+++ trunk/plug-ins/python/codegen.py Mon Mar 9 23:19:30 2009
@@ -20,6 +20,7 @@
class Klass :
def __init__ (self, name) :
self.name = name
+ # use a list to preserve the order
self.attributes = []
# a list, as java/c++ support multiple methods with the same name
self.operations = []
@@ -27,8 +28,8 @@
self.parents = []
self.templates = []
self.inheritance_type = ""
- def AddAttribute(self, name, type, visibility, value) :
- self.attributes.append ((name, (type, visibility, value)))
+ def AddAttribute(self, name, type, visibility, value, comment) :
+ self.attributes.append ((name, (type, visibility, value, comment)))
def AddOperation(self, name, type, visibility, params, inheritance_type, comment, class_scope) :
self.operations.append((name,(type, visibility, params, inheritance_type, comment, class_scope)))
def SetComment(self, s) :
@@ -70,13 +71,15 @@
params = []
for par in op[8] :
# par : again fixed placement, see objects/UML/umlparameter.c:umlparameter_props
- params.append((par[0], par[1]))
+ # (name, type, value, comment, kind)
+ params.append((par[0], par[1], par[2], par[3], par[4]))
k.AddOperation (op[0], op[1], op[4], params, op[5], op[2], op[7])
#print o.properties["attributes"].value
for attr in o.properties["attributes"].value :
# see objects/UML/umlattributes.c:umlattribute_props
#print "\t", attr[0], attr[1], attr[4]
- k.AddAttribute(attr[0], attr[1], attr[4], attr[2])
+ # name, type, value, comment, visibility, abstract, class_scope
+ k.AddAttribute(attr[0], attr[1], attr[4], attr[2], attr[3])
self.klasses[o.properties["name"].value] = k
#Connections
elif o.type.name == "UML - Association" :
@@ -123,13 +126,16 @@
f.write ("class %s :\n" % (sk,))
else:
f.write ("class %s (%s) :\n" % (sk,", ".join(parents)))
+ k = self.klasses[sk]
+ if len(k.comment) > 0 :
+ f.write ("\t'''" + k.comment + "'''\n")
f.write ("\tdef __init__(self) :\n")
- for sa, attr in self.klasses[sk].attributes :
+ for sa, attr in k.attributes :
value = attr[2] == "" and "None" or attr[2]
f.write("\t\tself.%s = %s # %s\n" % (sa, value, attr[0]))
else :
f.write("\t\tpass\n")
- for so, op in self.klasses[sk].operations :
+ for so, op in k.operations :
# we only need the parameter names
pars = "self"
for p in op[2] :
@@ -149,14 +155,20 @@
f.write("/* generated by dia/codegen.py */\n")
# declaration
for sk in self.klasses.keys() :
- f.write ("class %s \n{\n" % (sk,))
k = self.klasses[sk]
+ if len(k.comment) > 0 :
+ f.write ("/*" + k.comment + "*/\n")
+ if len(k.parents) > 0 :
+ f.write ("class %s : %s \n{\n" % (sk, ", ".join(k.parents)))
+ else :
+ f.write ("class %s \n{\n" % (sk,))
# first sort by visibility
ops = [[], [], [], []]
for so, (t, v, p, i, c, s) in k.operations :
ops[v].append((t,so,p))
vars = [[], [], [], []]
- for sa, (t, vi, va) in k.attributes :
+ for sa, (t, vi, va, vc) in k.attributes :
+ #TODO: use 'va'=value 'vc'=comment
vars[vi].append((t, sa))
visibilities = ("public:", "private:", "protected:", "/* implementation: */")
for v in [0,2,1,3] :
@@ -190,6 +202,183 @@
f.close()
ObjRenderer.end_render(self)
+# #############################################################################
+# PascalRenderer: export Dia UML diagram to Object Pascal (Free Pascal, Delphi)
+#
+# Please follow some "drawing guidelines" and "naming conventions" so that the
+# exporter can do its job.
+# - Use "UML - Generalization" arrows for class inheritance.
+# - Use "UML - Realizes" arrows when implementing an interface.
+# - Set a class to be "abstract" to denote it is an interface definition.
+# - Set Inheritance Type to "abstract" for 'virtual; abstract;' methods, set
+# it to "virtual" for 'virtual;' methods.
+# - Array fields are automatically recognized. If the name ends with "[]"
+# an 'Array of' is used. If the name uses a number with "[1234]", an
+# 'Array[0..1233] of' is used. If the name uses a constant with
+# "[MaxEntries]" an 'Array[0..MaxEntries-1] of' is written.
+# - To inherit from classes which are not drawn (e.g. LCL/VCL classes),
+# name then class with the parent class in paranthesis (e.g.
+# "TMainWin(TForm)"
+#
+# Features
+# - Inheriting from one class and implementing multiple interfaces is
+# supported.
+# - Comments for classes, attributes and operations are supported. They are
+# put in the line before the method declaration with a '///' style comment
+# (Doxygen-like).
+# - Method parameter directions are supported (-> 'Var', 'Out').
+# - Method parameter default values are supported.
+# - 'Function' and 'Procedure' are automatically recognized by whether a
+# return type exists or not.
+# - order of classes is alphabetically
+# - the order of attributes and operations is preserved
+# - Prints a list of forward declarations of all classes at the beginning
+# to avoid declaration order problems.
+#
+# TODO:
+# - Automatically use the keyword "override" instead of "virtual" in
+# descendant classes.
+# - Automatically define 'Properties'. Unfortunately the UML standard
+# doesn't support this and so the Dia dialog has no option to specify
+# this. So a "code" has to be used.
+# - Mark/recognize Constructors and Destructors
+# - Write comments for method parameters (e.g. by using a big doxygen
+# comment '(** ... *)' before the method)
+# - Use "Packages" to split the classes in separate 'Unit's.
+# - Beautify and comment the export code. Using arrays with "magic number
+# indexes" for certain fields is bad and tedious to work with.
+# - Support defining global constants.
+# - Support defining global types (especially for enums, arrays,
+# records, ...).
+# - Apply some sanity checks to the UML diagram:
+# - multiple inheritance is forbidded
+# - if implementing an interface, all required methods must be
+# implemented; alternative: just put all methods there, so the UML
+# drawer doesn't have to write them twice
+# - visibility for all methods of an interfaces must be "public"
+# - don't write the visibility specifier 'public' for interfaces
+# - no "Attributes" for interface definitions, but properties are
+# allowed
+# - default values for method parameters must be the last parameters
+
+class PascalRenderer(ObjRenderer) :
+ def __init__(self) :
+ ObjRenderer.__init__(self)
+ def end_render(self) :
+ f = open(self.filename, "w")
+ f.write("/* generated by dia/codegen.py */\n")
+ f.write("Type\n")
+ # classes
+ class_names = self.klasses.keys()
+ class_names.sort()
+ # forward declarations of all classes
+ for sk in class_names :
+ k = self.klasses[sk]
+ # class declaration
+ if k.inheritance_type == "abstract" :
+ f.write (" %s = interface;\n" % (sk))
+ else :
+ f.write (" %s = class;\n" % (sk))
+ f.write("\n");
+ # class declarations
+ for sk in class_names :
+ k = self.klasses[sk]
+ # comment
+ if len(k.comment) > 0 :
+ f.write(" /// %s\n" % (k.comment))
+ # class declaration
+ if k.inheritance_type == "abstract" :
+ f.write (" %s = interface" % (sk))
+ else :
+ f.write (" %s = class %s" % (sk, k.inheritance_type))
+ # inherited classes / implemented interfaces
+ p = []
+ if k.parents :
+ p.append(k.parents[0])
+ if k.templates :
+ p.append(",".join(k.templates))
+ if len(p) > 0 :
+ f.write("(%s)" % ",".join(p))
+ f.write ("\n")
+ # first sort by visibility
+ ops = [[], [], [], [], [], []]
+ for op_name, (op_type, op_visibility, op_params, op_inheritance, op_comment, op_class_scope) in k.operations :
+ ops[op_visibility].append((op_type, op_name, op_params, op_comment, op_inheritance))
+ vars = [[], [], [], []]
+ for var_name, (var_type, var_visibility, var_value, var_comment) in k.attributes : # name, type, visibility, value, comment
+ vars[var_visibility].append((var_type, var_name, var_value, var_comment))
+ visibilities = ("public", "private", "protected", "/* implementation */")
+ for v in [1,2,0,3] :
+ if len(ops[v]) == 0 and len(vars[v]) == 0 :
+ continue
+ # visibility prefix
+ f.write (" %s\n" % visibilities[v])
+ # variables
+ for var in vars[v] :
+ # comment
+ if len(var[3]) > 0 :
+ f.write (" /// %s\n" % var[3])
+ if var[1].endswith("]") :
+ # array; check if this is dynamic or with defined size
+ i = var[1].find("[")
+ varname = var[1]
+ arraysize = varname[i+1:-1]
+ varname = varname[:i]
+ if len(arraysize) > 0 :
+ # array with defined size
+ if arraysize.find("..") > 0 :
+ f.write(" %s : Array[%s] of %s;\n" % (varname, arraysize, var[0]))
+ elif arraysize.isdigit() :
+ arraysize = int(arraysize)-1
+ f.write(" %s : Array[0..%d] of %s;\n" % (varname, arraysize, var[0]))
+ else :
+ f.write(" %s : Array[0..%s-1] of %s;\n" % (varname, arraysize, var[0]))
+ else :
+ # dynamic size
+ f.write(" %s : Array of %s;\n" % (varname, var[0]))
+ else :
+ # normal variable
+ f.write(" %s : %s;\n" % (var[1], var[0]))
+ # operations
+ for op in ops[v] :
+ if len(op[3]) > 0 :
+ f.write (" /// %s\n" % op[3])
+ if len(op[0]) == 0 :
+ f.write (" Procedure %s" % op[1])
+ else :
+ f.write (" Function %s" % op[1])
+ if len(op[2]) > 0 :
+ f.write ("(")
+ i = 0
+ m = len(op[2]) - 1
+ for p in op[2] :
+ if p[4] == 2 :
+ f.write ("Out ")
+ elif p[4] == 3 :
+ f.write ("Var ")
+ f.write ("%s:%s" % (p[0], p[1]))
+ if len(p[2]) > 0 :
+ f.write (":=%s" % p[2])
+ if i != m :
+ f.write(";")
+ i = i + 1
+ f.write (")")
+ if len(op[0]) == 0 :
+ f.write(";")
+ else :
+ f.write (" : %s;" % op[0])
+ # inheritance type
+ if op[4] == 0 :
+ f.write (" virtual; abstract;");
+ elif op[4] == 1 :
+ f.write (" virtual;");
+ f.write ("\n")
+ f.write (" End;\n\n")
+ # implementation
+ # ...
+ f.close()
+ ObjRenderer.end_render(self)
+
class JavaRenderer(ObjRenderer) :
def __init__(self) :
ObjRenderer.__init__(self)
@@ -200,6 +389,8 @@
visibilities = {0:"public", 2:"private", 1:"protected"}
for name, klass in self.klasses.iteritems() :
+ if len(klass.comment) > 0 :
+ f.write ("/*" + klass.comment + "*/\n")
if klass.inheritance_type == "template": classtype = "interface"
elif klass.inheritance_type == "abstract": classtype = "abstract class"
else: classtype = "class"
@@ -210,7 +401,8 @@
f.write (" implements %s" % ", ".join(klass.templates))
f.write(" {\n")
- for attrname, (type, visibility, value) in klass.attributes :
+ for attrname, (type, visibility, value, comment) in klass.attributes :
+ #TODO: use comment
if visibility in visibilities:
vis = visibilities[visibility]+" "
else: vis = ""
@@ -243,7 +435,8 @@
# if there are no parameter names, something else should appear
pars = []
v = ord("a")
- for name, type in method[2]:
+ for name, type, value, comment, kind in method[2]:
+ #TODO: also use: value, comment, kind
if not name:
pars.append((type,chr(v)))
v += 1
@@ -265,4 +458,5 @@
# dia-python keeps a reference to the renderer class and uses it on demand
dia.register_export ("PyDia Code Generation (Python)", "py", PyRenderer())
dia.register_export ("PyDia Code Generation (C++)", "cxx", CxxRenderer())
+dia.register_export ("PyDia Code Generation (Pascal)", "pas", PascalRenderer())
dia.register_export ("PyDia Code Generation (Java)", "java", JavaRenderer())
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]