Esempio n. 1
0
    def processInheritances(self, inheritances):
        # process each inheritance, stores a dict with each subclass as the key
        # and a list of tuples (superclass, priority) as the value. The priority
        # tells us which class to inherit from first for multiple inheritance. Gives
        # a WARNING with a given inheritance order if two priorities are the same

        for i in inheritances :
            self.super_classes.append((i.get("class",""),i.get("priority",1)))

        try:
            self.super_classes.sort(lambda a, b: cmp(b[1], a[1])) # sort from high priority to low priority
        except TypeError:
            self.super_classes = sorted(self.super_classes, key=lambda x: x[1], reverse = True)

        priorityChecker = {}
        for super_class, priority in self.super_classes:
            if priority in priorityChecker:
                checkIt = priorityChecker[priority]
            else:
                checkIt = []
            if super_class not in checkIt:
                checkIt.append(super_class)
            priorityChecker[priority] = checkIt

        for priority, checkIt in list(priorityChecker.items()):
            if len(checkIt) > 1:
                Logger.showWarning("Class <" + self.name + "> inherits from classes <" + ", ".join(checkIt) + "> with same priority <" + str(priority) + ">. Document inheritance order is used.")

        self.super_classes = [entry[0] for entry in self.super_classes]
Esempio n. 2
0
    def visit_Class(self, c):
        # replace super class names by super class objects
        for s in c.super_classes:
            super_class = None
            for clas in c.class_diagram.classes:
                if clas.name == s:
                    super_class = clas
            if super_class == None:
                Logger.showWarning("Class <" + c.name +
                                   "> has undefined super class <" + s + ">.")
            else:
                c.super_class_objs[s] = super_class

        # calculate list of abstract methods
        c.abstract_method_names = getClassAbstractMethodNames(c)

        # check if <super> tags exist for all inherited classes
        for name, obj in list(c.super_class_objs.items()):
            if obj:
                if name not in c.constructors[0].super_class_parameters:
                    num_params = len(obj.constructors[0].parameters)
                    if num_params > 0:
                        raise CompilerException(
                            "Class <" + c.name + "> inherits <" + name +
                            "> and <" + name + ">'s constructor has " +
                            str(num_params) +
                            " parameter(s), but there's no <super> entry for that class in <"
                            + c.name + ">'s constructor.")
Esempio n. 3
0
def sccdToGeneric(sccd, platform):
    succesfull_generation = False
    generator = GenericGenerator(platform)
    sccd.accept(generator)
    generic = generator.get()
    Logger.showInfo("Classes <" + ", ".join(sccd.class_names) +
                    "> have been converted to generic language constructs.")
    return generic
Esempio n. 4
0
def genericToTarget(generic, target_language, output_file):
    try:
        f = FileWriter(output_file)
        if target_language == "javascript":
            writer = JavascriptWriter(f)
        elif target_language == "python":
            writer = PythonWriter(f)
        else:
            raise Exception("Language not supported")
        generic.accept(writer)
        Logger.showInfo(
            "Generic language constructs have been converted to target language constructs and have been written to file '"
            + output_file + "'.")
    finally:
        f.close()
Esempio n. 5
0
 def __init__(self, xml_element):
     self.event = xml_element.get("event","").strip()
     scope_string = xml_element.get("scope","").strip().lower()
     self.target = xml_element.get("target","").strip()
     self.port = xml_element.get("port","").strip()
     
     if scope_string == "local" :
         self.scope = self.LOCAL_SCOPE
     elif scope_string == "broad" :
         self.scope = self.BROAD_SCOPE
     elif scope_string == "output" :
         self.scope = self.OUTPUT_SCOPE
     elif scope_string == "narrow" :
         self.scope = self.NARROW_SCOPE
     elif scope_string == "cd" :
         self.scope = self.CD_SCOPE
     elif scope_string == "" :
         #Calculate scope depending on present attributes
         if self.target and self.port :
             raise CompilerException("Both target and port attribute detected without a scope defined.")
         elif self.port :
             self.scope = self.OUTPUT_SCOPE
         elif self.target :
             self.scope = self.NARROW_SCOPE
         else :
             self.scope = self.LOCAL_SCOPE  
         
     else :
         raise CompilerException("Illegal scope attribute; needs to be one of the following : local, broad, narrow, output, cd or nothing.");  
             
     if self.scope == self.LOCAL_SCOPE or self.scope == self.BROAD_SCOPE or self.scope == self.CD_SCOPE:
         if self.target :
             Logger.showWarning("Raise event target detected, not matching with scope. Ignored.")
             self.target = ""
         if self.port :
             Logger.showWarning("Raise event port detected, not matching with scope. Ignored.")
             self.port = ""
     if self.scope == self.NARROW_SCOPE and self.port :
         Logger.showWarning("Raise event port detected, not matching with scope. Ignored.")
         self.port = ""
     if self.scope == self.OUTPUT_SCOPE and self.target :
         Logger.showWarning("Raise event target detected, not matching with scope. Ignored.")
         self.target = ""
             
     self.params = []
     parameters = xml_element.findall('parameter')    
     for p in parameters :
         value = p.get("expr","")
         if not value :
             raise CompilerException("Parameter without value detected.")
         self.params.append(Expression(value))
Esempio n. 6
0
def generate(input_file, output_file, target_language, platform):
    sccd = xmlToSccd(input_file)

    if not target_language:
        if sccd.language:
            target_language = sccd.language
        else:
            target_language = "python"  # default
    elif sccd.language and target_language != sccd.language:
        Logger.showError(
            "Diagram specifies target language as \"" + sccd.language +
            "\", but language option of compiler has been set to \"" +
            target_language + "\". No output has been generated.")
        return

    if target_language == "python" and not output_file.endswith(".py"):
        output_file += ".py"
    elif target_language == "javascript" and not output_file.endswith(".js"):
        output_file += ".js"

    generic = sccdToGeneric(sccd, platform)
    genericToTarget(generic, target_language, output_file)
Esempio n. 7
0
    def __init__(self, class_obj, statechart_xml):
        """ Gives the module information on the statechart by listing its basic, orthogonal,
            composite and history states as well as mapping triggers to names making the
            appropriate conversion from AFTER() triggers to event names
        """
        
        self.class_obj = class_obj
        self.root = StateChartNode(self, statechart_xml); #creates the whole statechart structure recursively

        self.states = []
        self.basics = []
        self.composites = []
        self.histories = []
        self.nr_of_after_transitions = 0

        def getSemanticOption(name, allowed_values, default_value):
            result = statechart_xml.get(name, default_value)
            if result not in allowed_values:
                raise CompilerException("Illegal value for semantic option " + name + ": '" + result + "'. Allowed values are ['" + "', '".join(allowed_values) + "'], default value is '" + default_value + "'.")
            return result

        self.big_step_maximality = getSemanticOption("big_step_maximality", ["take_one", "take_many"], "take_many")
        self.internal_event_lifeline = getSemanticOption("internal_event_lifeline", ["next_small_step", "next_combo_step", "queue"], "queue")
        self.input_event_lifeline = getSemanticOption("input_event_lifeline", ["first_small_step", "first_combo_step", "whole"], "first_combo_step")
        self.priority = getSemanticOption("priority", ["source_parent", "source_child"], "source_parent")
        self.concurrency = getSemanticOption("concurrency", ["single", "many"], "single")

        if self.internal_event_lifeline == "next_combo_step":
            if self.big_step_maximality == "take_one":
                Logger.showWarning("Using 'Next Combo Step' internal event lifeline semantics and 'Take One' big step maximality semantics simultaneously doesn't make sense.")

        self.extractFromHierarchy(self.root) # recursively extracts the basics, composites, histories and nr_of_after_transitions
            
        # Calculate the history that needs to be taken care of.
        self.shallow_history_parents = []
        self.deep_history_parents = []
        self.combined_history_parents = [] #All nodes that need state saved on leaving
        for node in self.histories:
            self.calculateHistory(node.parent, node.is_history_deep)
Esempio n. 8
0
def main():
    parser = argparse.ArgumentParser(prog="python -m sccd.compiler.sccdc")
    parser.add_argument('input',
                        help='The path to the XML file to be compiled.')
    parser.add_argument(
        '-o',
        '--output',
        type=str,
        help=
        'The path to the generated code. Defaults to the same name as the input file but with matching extension.'
    )
    parser.add_argument(
        '-v',
        '--verbose',
        type=int,
        help=
        '2 = all output; 1 = only warnings and errors; 0 = only errors; -1 = no output.  Defaults to 2.',
        default=2)
    parser.add_argument(
        '-p',
        '--platform',
        type=str,
        help=
        "Let the compiled code run on top of threads, gameloop or eventloop. The default is eventloop."
    )
    parser.add_argument(
        '-l',
        '--language',
        type=str,
        help=
        'Target language, either "javascript" or "python". Defaults to the latter.'
    )

    args = vars(parser.parse_args())
    #Set verbose
    if args['verbose'] is not None:
        if args['verbose'] in [-1, 0, 1, 2]:
            Logger.verbose = args['verbose']
        else:
            Logger.showError("Invalid verbose argument.")
    else:
        Logger.verbose = 2

    #Set source file
    source = args['input']
    if not source.endswith(".xml"):
        Logger.showError("Input file not valid.")
        return

    #Set target language
    if args['language']:
        target_language = args['language']
    else:
        target_language = ""

    #Set output file
    if args['output']:
        output = args['output']
    else:
        output = os.path.splitext(os.path.split(source)[1])[0]

    #Set platform
    if args['platform']:
        args['platform'] = args['platform'].lower()
        if args['platform'] == "threads":
            platform = Platforms.Threads
        elif args['platform'] == "gameloop":
            platform = Platforms.GameLoop
        elif args['platform'] == "eventloop":
            platform = Platforms.EventLoop
        else:
            Logger.showError("Invalid platform.")
            return
    else:
        platform = Platforms.EventLoop

    #Compile
    try:
        generate(source, output, target_language, platform)
    except CompilerException as exception:
        Logger.showError(str(exception))
        return 1

    return 0
Esempio n. 9
0
    def __init__(self, input_file):
        diagram_dir = os.path.dirname(input_file)
        tree = ET.parse(input_file)
        self.root = tree.getroot()
        self.name = self.root.get("name", "")
        self.author = self.root.get("author", "")
        descriptions = self.root.findall("description")
        self.language = self.root.get("language", "")
        if descriptions : 
            self.description = descriptions[0].text
        else :
            self.description = ""

        xml_classes = self.root.findall("class")
        # make sure at least one class is given
        if not xml_classes :
            raise CompilerException("Found no classes to compile.")

        # check if class diagram is valid
        # unique class names
        self.class_names = []
        substituted_xml_classes = []
        default_substituted_xml_classes = []
        for xml_class in xml_classes :
            class_src = xml_class.get("src", "")
            class_default = xml_class.get("default", "")
            if class_src != "":
                if not os.path.isabs(class_src):
                    class_src = os.path.join(diagram_dir, class_src)
                substituted_xml_class = ET.parse(class_src).getroot()
            else:
                substituted_xml_class = xml_class

            if class_default.lower() == "true":
                default_substituted_xml_classes.append(substituted_xml_class)

            name = substituted_xml_class.get("name", "")
            if name == "" :
                raise CompilerException("Missing or emtpy class name.")
            if name in self.class_names :
                raise CompilerException("Found 2 classes with the same name : " + name + ".")
            self.class_names.append(name)
            substituted_xml_classes.append(substituted_xml_class)
    
        # process in and output ports
        inports = self.root.findall("inport")
        names = []
        for xml_inport in inports :
            name = xml_inport.get("name", "")
            if name in names :
                raise CompilerException("Found 2 INPorts with the same name : " + name + ".")
            names.append(name)
        self.inports = names
        
        outports = self.root.findall("outport")
        names = []
        for xml_outport in outports :
            name = xml_outport.get("name", "")
            if name in names :
                raise CompilerException("Found 2 OUTPorts with the same name : " + name + ".")
            names.append(name)
        self.outports = names
            
        
        # any inital import code that has to come at the top of the generate file
        tops = self.root.findall("top")
        self.includes = []
        if len(tops) == 1 :
            self.top = tops[0].text
        elif len(tops) > 1 : 
            raise CompilerException("Class diagram can only have one <top> element.")
        else :
            self.top = ""
        
        # process each class in diagram
        self.classes = []
        default_classes = []
    
        for xml_class in substituted_xml_classes:
            processed_class = None
            try :
                processed_class = Class(xml_class, self)
            except CompilerException as e :
                e.message = "Class <" + xml_class.get("name", "") + "> failed compilation. " + e.message
                raise e
    
            # let user know this class was successfully loaded
            Logger.showInfo("Class <" + processed_class.name + "> has been successfully loaded.")
            self.classes.append(processed_class)

            if xml_class in default_substituted_xml_classes:
                default_classes.append(processed_class)
            
        if not default_classes or len(default_classes) > 1:
            if len(self.classes) == 1 :
                Logger.showInfo("Only one class given. Using <" + self.classes[0].getName() + "> as the default class.")
                default_classes.append(self.classes[0])
            else :
                raise CompilerException("Provide one and only one default class to instantiate on start up.")
        self.default_class = default_classes[0]

        # check if there's a test
        self.test = None
        test_nodes = self.root.findall("test")
        if test_nodes:
            test_node = test_nodes[0]

            input_nodes = test_node.findall("input")
            if input_nodes:
                input_node = input_nodes[0]
                test_input = DiagramTestInput(input_node)
            else:
                test_input = None

            expected_nodes = test_node.findall("expected")
            if expected_nodes:
                expected_node = expected_nodes[0]
                test_expected = DiagramTestExpected(expected_node)
            else:
                test_expected = None

            self.test = DiagramTest(test_input, test_expected)
Esempio n. 10
0
 def generic_visit(self, node):
     Logger.showWarning(
         "GenericGenerator has no visit method for node of type '" +
         str(type(node)) + "'.")
Esempio n. 11
0
def main():
    mapper = SCCD_ASG_Mapper()

    parser = argparse.ArgumentParser()
    parser.add_argument('input',
                        help='The path to the XML file to be compiled.')
    parser.add_argument(
        '-o',
        '--output',
        type=str,
        help=
        'The path to the generated code. Defaults to the same name as the input file but with matching extension.'
    )
    parser.add_argument(
        '-v',
        '--verbose',
        type=int,
        help=
        '2 = all output; 1 = only warnings and errors; 0 = only errors; -1 = no output.  Defaults to 2.',
        default=2)
    parser.add_argument(
        '-p',
        '--platform',
        type=str,
        help=
        "Let the compiled code run on top of threads, gameloop or eventloop. The default is eventloop."
    )
    parser.add_argument(
        '-l',
        '--language',
        type=str,
        help=
        'Target language, either "javascript" or "python". Defaults to the latter.'
    )
    #parser.add_argument('-m', '--mvklocation', type=str, help='Location in the Modelverse. After compilation the modelverse shell is opened.')
    parser.add_argument('-justxml', dest='justxml', action='store_true')
    parser.set_defaults(justxml=False)

    args = vars(parser.parse_args())

    #Set verbose
    if args['verbose'] is not None:
        if args['verbose'] in [-1, 0, 1, 2]:
            Logger.verbose = args['verbose']
        else:
            Logger.showError("Invalid verbose argument.")
    else:
        Logger.verbose = 2

    #Set source file
    source = args['input'].lower()
    if not source.endswith(".sccd"):
        Logger.showError("Input file not valid.")
        return

    #Set target language
    if args['language']:
        target_language = args['language']
    else:
        target_language = ""

    #Set output file
    if args['output']:
        output = args['output']
    else:
        output = os.path.splitext(os.path.split(source)[1])[0]

    #Set platform
    if args['platform']:
        args['platform'] = args['platform'].lower()
        if args['platform'] == "threads":
            platform = Platforms.Threads
        elif args['platform'] == "gameloop":
            platform = Platforms.GameLoop
        elif args['platform'] == "eventloop":
            platform = Platforms.EventLoop
        else:
            Logger.showError("Invalid platform.")
            return
    else:
        platform = Platforms.Threads

    mvklocation = 'unused_location'
    """
    if args['mvklocation'] :
        mvklocation = args['mvklocation']
        modelverseshell = True
    else:
        mvklocation = 'temporaryLocation'
        modelverseshell = False
    """

    if args['justxml']:
        try:
            generate(output + '.xml', output, target_language, platform)
        except CompilerException as exception:
            Logger.showError(str(exception))
        return

    context = MvKLoader(mapper.rules, mapper.metamodel_location,
                        mapper.metamodel_path, mvklocation).load(source)
    if (target_language == "javascript"):
        compiler = SCCD_to_XML(XML2JavaScriptRules().rules, context.mvk)
    else:
        compiler = SCCD_to_XML(XML2PythonRules().rules, context.mvk)
    compiler.compile(context.target + '.' + context.modelname)

    if os.path.exists(output + '.xml'):
        os.remove(output + '.xml')
    compiler.outputTo(output + '.xml')

    #Compile
    try:
        generate(output + '.xml', output, target_language, platform)
    except CompilerException as exception:
        Logger.showError(str(exception))
    """