Exemple #1
0
def test_attr_formula1():
    text = r"""
    package example
    struct Image {
      scalar w: built_in.uint32  (.defaultValue=1, .maxValue=1000)
      scalar h: built_in.uint32  (.defaultValue=1, .maxValue=1000)
      array pixel : built_in.float[w*h]
    }
    """
    mm = metamodel_for_language("item")
    assert mm is not None
    model = mm.model_from_str(text)
    assert model is not None
    items = get_children_of_type("Struct", model)
    assert len(items) == 1

    model._tx_filename = "example.item"
    path = os.path.join(os.path.abspath(os.path.dirname(__file__)), "src-gen")
    gen1 = generator_for_language_target("item", "cpp")
    gen2 = generator_for_language_target("item", "python")

    if os.path.exists(path):
        shutil.rmtree(path)
    os.mkdir(path)
    gen1(mm, model, output_path=path, overwrite=True, debug=False)
    gen2(mm, model, output_path=path, overwrite=True, debug=False)

    cpp_code = open(os.path.join(path, "example", "Image.h")).read()
    print(cpp_code)
    assert "struct Image" in cpp_code
    assert "s.w*s.h" in cpp_code
Exemple #2
0
def pytest_configure(config):
    this_folder = abspath(dirname(__file__))

    mm = metamodel_for_language("item")
    assert mm is not None
    inpath = join(this_folder, "tests/model/*.item")

    outpath = join(this_folder, "src-gen")
    sys.path.append(outpath)  # add generated code to python path

    mm2 = metamodel_for_language("algo")
    assert mm2 is not None
    inpath2 = join(this_folder, "tests/model/*.algo")

    if exists(outpath):
        rmtree(outpath)
    mkdir(outpath)

    for f in glob(inpath, recursive=True):
        model = mm.model_from_file(f)
        assert model is not None
        gen = generator_for_language_target("item", "python")
        gen(mm, model, output_path=outpath, overwrite=True, debug=False)

    for f in glob(inpath2, recursive=True):
        model = mm2.model_from_file(f)
        assert model is not None
        gen = generator_for_language_target("algo", "python")
        gen(mm2, model, output_path=outpath, overwrite=True, debug=False)
Exemple #3
0
def main(debug = False):
    metamodel_export(data_dsl_mm, join(this_folder, 'family-tree_meta.dot'))
    family_tree_model = data_dsl_mm.model_from_file(join(this_folder, "miljkovic.family"))
    model_export(family_tree_model, join(this_folder, 'family-tree.dot'))
    family_tree_to_txt = generator_for_language_target('family_tree_dsl', 'txt')
    family_tree_to_txt(data_dsl_mm, family_tree_model,this_folder,True)
    family_tree_to_html = generator_for_language_target('family_tree_dsl', 'html')
    family_tree_to_html(data_dsl_mm, family_tree_model,this_folder,True)
Exemple #4
0
def test_big_example():
    mm = metamodel_for_language("item")
    assert mm is not None

    inpath = join(this_folder, "model")

    model = mm.model_from_file(join(inpath, "big_example.item"))
    assert model is not None

    outpath = join(this_folder, "src-gen")
    gen = generator_for_language_target("item", "cpp_v2")

    if exists(outpath):
        rmtree(outpath)
    mkdir(outpath)
    gen(mm, model, output_path=outpath, overwrite=True, debug=False)

    refpath = join(inpath, "ref")

    structs = get_children_of_type("Struct", model)
    enums = get_children_of_type("Enum", model)
    constants = get_children_of_type("Constants", model)

    for s in structs + enums + constants:
        outputfile = output_filename(refpath, s, "regex_ref")
        if exists(outputfile):
            check_file(
                filename=output_filename(outpath, s),
                regex_reference_filename=outputfile,
            )
Exemple #5
0
def test_props_load_and_import():
    mm = metamodel_for_language("item")
    assert mm is not None
    model = mm.model_from_file(
        os.path.join(
            os.path.abspath(os.path.dirname(__file__)), "model", "props_example.item"
        )
    )
    assert model is not None

    model._tx_filename = "example.item"
    path = os.path.join(os.path.abspath(os.path.dirname(__file__)), "src-gen")
    gen1 = generator_for_language_target("item", "cpp")

    if os.path.exists(path):
        shutil.rmtree(path)
    os.mkdir(path)
    gen1(mm, model, output_path=path, overwrite=True, debug=False)

    cpp_code = open(os.path.join(path, "example", "X.h")).read()
    print(cpp_code)
    assert "minValue" in cpp_code
    assert "maxValue" in cpp_code
    assert "myprop1" in cpp_code
    assert "myprop2" in cpp_code
    assert "myprop3" not in cpp_code
Exemple #6
0
def test_example2():
    text = r"""
    package example
    struct Point {
      scalar x : built_in.float
      scalar y : built_in.float
    }
    struct Line {
      scalar p1 : Point
      scalar p2 : Point
    }
    struct Circle {
      scalar center : Point
      scalar radius : built_in.float
    }
    struct VariantExample {
        scalar selector: built_in.uint32
        variant payload: selector -> {
            10: Point
            11: Line
            12: Circle
        }
    }
    """
    mm = metamodel_for_language("item")
    assert mm is not None
    model = mm.model_from_str(text)
    assert model is not None

    model._tx_filename = "example.item"
    path = os.path.join(os.path.abspath(os.path.dirname(__file__)), "src-gen")
    gen1 = generator_for_language_target("item", "cpp")
    gen2 = generator_for_language_target("item", "python")

    if os.path.exists(path):
        shutil.rmtree(path)
    os.mkdir(path)
    gen1(mm, model, output_path=path, overwrite=True, debug=False)
    gen2(mm, model, output_path=path, overwrite=True, debug=False)

    cpp_code = open(os.path.join(path, "example", "VariantExample.h")).read()
    print(cpp_code)
    assert "switch(s.selector)" in cpp_code
    assert "std::variant" in cpp_code
Exemple #7
0
def generate_extension(target: str, dest_dir: str,
                       **cmd_args: Optional[dict]) -> None:
    """Generates client installable extension.

    Args:
        target: target (client) to generate extension for (e.g. `vscode`)
        dest_dir: destination directory where extension will be written
        cmd_args: other optional arguments
    Returns:
        None
    Raises:
        GenerateExtensionError: if generator does not exists (`TextXRegistrationError`)
                                or any other error that happened while generating
                                the extension

    """
    try:
        extension_gen = generator_for_language_target("textX", target)
        extension_gen(None, None, dest_dir, **cmd_args)
    except Exception as e:
        raise GenerateExtensionError(target, cmd_args) from e
Exemple #8
0
def test_codegen():
    path = os.path.join(os.path.abspath(os.path.dirname(__file__)), "basic",
                        "mean_algo2.algo")
    mm = metamodel_for_language("algo")
    assert mm is not None
    model = mm.model_from_file(path)
    assert model is not None

    path = os.path.join(os.path.abspath(os.path.dirname(__file__)), "src-gen")
    gen = generator_for_language_target("algo", "cpp")

    if os.path.exists(path):
        shutil.rmtree(path)
    os.mkdir(path)
    gen(mm, model, output_path=path, overwrite=True, debug=False)

    cpp_code = open(os.path.join(path, "P1", "P2", "MeanAlgo.h")).read()
    print(cpp_code)
    assert "struct MeanAlgo" in cpp_code
    assert "shared_ptr<const Items::MeanAlgo" not in cpp_code
    assert "shared_ptr<Items::MeanAlgo" not in cpp_code
Exemple #9
0
def test_codegen_python():
    path = os.path.join(
        os.path.abspath(os.path.dirname(__file__)),
        "basic",
        "mean_algo_with_shared_ptr.algo",
    )
    mm = metamodel_for_language("algo")
    assert mm is not None
    model = mm.model_from_file(path)
    assert model is not None

    path = os.path.join(os.path.abspath(os.path.dirname(__file__)), "src-gen")
    gen = generator_for_language_target("algo", "python")

    if os.path.exists(path):
        shutil.rmtree(path)
    os.mkdir(path)
    gen(mm, model, output_path=path, overwrite=True, debug=False)

    py_code = open(os.path.join(path, "P1", "MeanAlgo.py")).read()
    print(py_code)
    assert "class MeanAlgo" in py_code
    assert "i:Items.MeanAlgoInput.MeanAlgoInput" in py_code
Exemple #10
0
def generate_syntaxes(project_name: str, target: str,
                      **cmd_args: Optional[dict]) -> Mapping[str, Any]:
    """Generates syntax highlighting files for all project languages.

    NOTE: This is called on grammar changes and it collects new language keywords.
    (project must be installed in editable mode)

    Args:
        project_name: project for which to generate syntax highlightings
        target: syntax highlight file type (e.g. `vscode`)
        cmd_args: other optional arguments
    Returns:
        A map where keys are language names and values are corresponding syntax
        highlighting files
    Raises:
        GenerateSyntaxHighlightError: if generator does not exists (`TextXRegistrationError`)
                                      or any other error that happened while generating
                                      syntax highlighting files

    """
    try:
        syntax_gen = generator_for_language_target("textX", target)

        lang_syntax_map = {}
        for lang in get_languages_by_project_name(project_name):
            lang_name = lang.name.lower()
            lang_desc = get_language_desc(lang_name)
            syntax_file = syntax_gen(None, lang_desc.metamodel(), **{
                "name": lang_name,
                **cmd_args
            })
            if syntax_file:
                lang_syntax_map[lang_name] = syntax_file
        return lang_syntax_map
    except Exception as e:
        raise GenerateSyntaxHighlightError(project_name, target) from e
Exemple #11
0
def test_constants_with_formulas():
    text = """
    package abc {
        constants MyConstants (.description = "example")
        {
            constant c1: built_in.uint32 = 1 (.description = "constant")
            constant c2: built_in.float = 3.4 (.description = "constant")
            constant c3: built_in.uint32 = MyConstants.c1 (.description = "constant")
            constant c4: built_in.uint32 = c1 (.description = "constant")
        }
        struct A {
            array a: built_in.uint32[2*abc.MyConstants.c1]
            array b: built_in.uint32[3*MyConstants.c1]
            array c: built_in.uint32[4*CONST MyConstants.c1]
        }
    }
    """
    mm = metamodel_for_language("item")
    assert mm is not None
    model = mm.model_from_str(text)
    assert model is not None

    model._tx_filename = os.path.join(
        os.path.abspath(os.path.dirname(__file__)), "mymodel.txt"
    )
    path = os.path.join(os.path.abspath(os.path.dirname(__file__)), "src-gen")
    gen1 = generator_for_language_target("item", "cpp")
    if os.path.exists(path):
        shutil.rmtree(path)
    os.mkdir(path)
    gen1(mm, model, output_path=path, overwrite=True, debug=False)
    cpp_code = open(os.path.join(path, "abc", "A.h")).read()
    print(cpp_code)
    assert "2*abc::MyConstants::c1" in cpp_code
    assert "3*abc::MyConstants::c1" in cpp_code
    assert "4*abc::MyConstants::c1" in cpp_code
Exemple #12
0
    def generate(ctx,
                 model_files,
                 output_path,
                 language,
                 target,
                 overwrite,
                 grammar=None,
                 ignore_case=False):
        """
        Run code generator on a provided model(s).

        For example::

        \b
        # Generate PlantUML output from .flow models
        textx generate mymodel.flow --target PlantUML

        \b
        # or with defined output folder
        textx generate mymodel.flow -o rendered_model/ --target PlantUML

        \b
        # To chose language by name and not by file pattern use --language
        textx generate *.flow --language flow --target PlantUML

        \b
        # Use --overwrite to overwrite target files
        textx generate mymodel.flow --target PlantUML --overwrite

        \b
        # In all above cases PlantUML generator must be registered, i.e.:
        $ textx list-generators
        flow-dsl -> PlantUML  Generating PlantUML visualization from flow-dsl

        \b
        # If the source language is not registered you can use the .tx grammar
        # file for parsing but the language name used will be `any`.
        textx generate --grammar Flow.tx --target dot mymodel.flow


        """

        debug = ctx.obj['debug']
        click.echo('Generating {} target from models:'.format(target))

        try:
            per_file_metamodel = False
            if grammar:
                metamodel = metamodel_from_file(grammar,
                                                debug=debug,
                                                ignore_case=ignore_case)
                language = 'any'
            elif language:
                metamodel = metamodel_for_language(language)
            else:
                per_file_metamodel = True

            # Find all custom arguments
            model_files = list(model_files)
            model_files_without_args = []
            custom_args = {}
            while model_files:
                m = model_files.pop(0)
                if m.startswith('--'):
                    arg_name = m[2:]
                    if not model_files or model_files[0].startswith('--'):
                        # Boolean argument
                        custom_args[arg_name] = True
                    else:
                        custom_args[arg_name] = model_files.pop(0).strip('"\'')
                else:
                    model_files_without_args.append(m)

            # Call generator for each model file
            for model_file in model_files_without_args:

                click.echo(os.path.abspath(model_file))

                if per_file_metamodel:
                    language = language_for_file(model_file).name
                    metamodel = metamodel_for_file(model_file)

                # Get custom args that match defined model parameters and pass
                # them in to be available to model processors.
                model_params = {
                    k: v
                    for k, v in custom_args.items()
                    if k in metamodel.model_param_defs
                }

                model = metamodel.model_from_file(model_file, **model_params)
                generator = generator_for_language_target(
                    language, target, any_permitted=per_file_metamodel)

                generator(metamodel, model, output_path, overwrite, debug,
                          **custom_args)

        except TextXRegistrationError as e:
            raise click.ClickException(e.message)

        except TextXError as e:
            raise click.ClickException(str(e))
Exemple #13
0
    def generate(ctx, model_files, output_path, language, target, overwrite,
                 grammar=None, ignore_case=False):
        """
        Run code generator on a provided model(s).

        For example::

        \b
        # Generate PlantUML output from .flow models
        textx generate mymodel.flow --target PlantUML

        \b
        # or with defined output folder
        textx generate mymodel.flow -o rendered_model/ --target PlantUML

        \b
        # To chose language by name and not by file pattern use --language
        textx generate *.flow --language flow --target PlantUML

        \b
        # Use --overwrite to overwrite target files
        textx generate mymodel.flow --target PlantUML --overwrite

        \b
        # In all above cases PlantUML generator must be registered, i.e.:
        $ textx list-generators
        flow-dsl -> PlantUML  Generating PlantUML visualization from flow-dsl

        \b
        # If the source language is not registered you can use the .tx grammar
        # file for parsing but the language name used will be `any`.
        textx generate --grammar Flow.tx --target dot mymodel.flow


        """

        debug = ctx.obj['debug']
        click.echo('Generating {} target from models:'.format(target))

        try:
            per_file_metamodel = False
            if grammar:
                metamodel = metamodel_from_file(grammar, debug=debug,
                                                ignore_case=ignore_case)
                language = 'any'
            elif language:
                metamodel = metamodel_for_language(language)
            else:
                per_file_metamodel = True

            # Find all custom arguments
            model_files = list(model_files)
            model_files_without_args = []
            custom_args = {}
            while model_files:
                m = model_files.pop(0)
                if m.startswith('--'):
                    custom_args[m[2:]] = model_files.pop(0).strip('"\'')
                else:
                    model_files_without_args.append(m)

            # Call generator for each model file
            for model_file in model_files_without_args:

                click.echo(os.path.abspath(model_file))

                if per_file_metamodel:
                    language = language_for_file(model_file).name
                    metamodel = metamodel_for_file(model_file)
                model = metamodel.model_from_file(model_file)
                generator = generator_for_language_target(
                    language, target, any_permitted=per_file_metamodel)

                generator(metamodel, model, output_path, overwrite, debug,
                          **custom_args)

        except TextXRegistrationError as e:
            click.echo(e.message)

        except TextXError as e:
            click.echo(e)