Skip to content

Commit

Permalink
WIP: Alternative Translation method using table-driven approach
Browse files Browse the repository at this point in the history
Signed-off-by: Gunnar Andersson <[email protected]>
  • Loading branch information
gunnar-mb committed Oct 11, 2024
1 parent 6d28965 commit a4ade0e
Show file tree
Hide file tree
Showing 6 changed files with 605 additions and 0 deletions.
1 change: 1 addition & 0 deletions ifex/model/ifex_ast_construction.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ def ifex_ast_to_dict(node, debug_context="") -> OrderedDict:
# Optional, otherwise the type-checking constructor would have caught the
# error.

#print(f"node is: {node}\n")
for f in fields(node):
item = getattr(node, f.name)
if not is_empty(item):
Expand Down
Empty file added other/franca/__init__.py
Empty file.
281 changes: 281 additions & 0 deletions other/franca/franca_to_ifex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,281 @@
# SPDX-FileCopyrightText: Copyright (c) 2024 MBition GmbH.
# SPDX-License-Identifier: MPL-2.0

# This file is part of the IFEX project
# vim: tw=120 ts=4 et

# Have to define a search path to submodule to make this work (might be rearranged later)
import os
import sys
mydir = os.path.dirname(__file__)
for p in ['pyfranca', 'pyfranca/pyfranca']:
if p not in sys.path:
sys.path.append(os.path.join(mydir,p))

import ifex.model.ifex_ast as ifex
import other.franca.pyfranca.pyfranca as pyfranca
import other.franca.rule_translator as m2m
import pyfranca.ast as franca
import re

from ifex.model.ifex_ast_construction import add_constructors_to_ifex_ast_model, ifex_ast_as_yaml
from other.franca.rule_translator import Initialize, Constant, ListOf, Unsupported

def array_type_name(francaitem):
return translate_type_name(francaitem) + '[]' # Unbounded arrays for now

def translate_type_name(francaitem):
return translate_type(francaitem)

def concat_comments(list):
return "\n".join(list)

# If enumerator values are not given, we must use auto-generated values.
# IFEX model requires all enumerators to be given values.
enum_count = -1
def reset_enumerator_counter(_ignored):
print("***Resetting enum counter")
global enum_count
enum_count = -1

def translate_enumerator_value(franca_int_value):
if franca_int_value is None:
global enum_count
enum_count = enum_count + 1
return enum_count
return translate_integer_constant(franca_int_value)

# Integer value is represented by an instance of IntegerValue class type, which has a "value" member
def translate_integer_constant(franca_int_value):
return franca_int_value.value

# Tip: This translation table format is described in more detail in rule_translator.py
franca_to_ifex_mapping = {

'global_attribute_map': {
# Franca-name : IFEX-name
'comments' : 'description', # FIXME allow transform also here, e.g. concat comments
'extends' : None, # TODO
'flags' : None
},

'type_map': {
(franca.Interface, ifex.Interface) : [],
(franca.Package, ifex.Namespace) : [
# TEMPORARY: Translates only the first interface
('interfaces', 'interface', lambda x: x[0]),
('typecollections', 'namespaces') ],
(franca.Method, ifex.Method) : [
('in_args', 'input'),
('out_args', 'output'),
('namespace', None) ],
(franca.Argument, ifex.Argument) : [
('type', 'datatype', translate_type_name), ],
(franca.Enumeration, ifex.Enumeration) : [
(Initialize(reset_enumerator_counter), None),
('enumerators', 'options'),
('extends', Unsupported),

# Franca only knows integer-based Enumerations so we hard-code the enumeration datatype to be
# int32 in the corresponding IFEX representation
(Constant('int32'), 'datatype')
],

(franca.Enumerator, ifex.Option) : [
('value', 'value', translate_enumerator_value)
],
(franca.TypeCollection, ifex.Namespace) : [
('structs', 'structs'),
('unions', None), # TODO - use the variant type on IFEX side, need to check its implementation first
('arrays', 'typedefs'),
('typedefs', 'typedefs')
],
(franca.Struct, ifex.Struct) : [
('fields', 'members')
],
(franca.StructField, ifex.Member) : [
('type', 'datatype', translate_type_name)
] ,
(franca.Array, ifex.Typedef) : [
('type', 'datatype', array_type_name)
],
(franca.Attribute, ifex.Property) : [],
(franca.Import, ifex.Include) : [],
# TODO: More mapping to do, much is not yet defined here
(franca.Package, ifex.Enumeration) : [],
(franca.Package, ifex.Struct) : [],
}
}

# Reminders of cases to be handled from previous implementation approach:
# Structs_in_TypeCollection(franca_typecollection):
# Structs_in_Interface(franca_interface):
# Structs_in_Package(franca_package):
# Enumerator_Value(v):
# Enumerators_to_Options(enumerators, enumeration_name):
# Enumerations_in_Interface(franca_interface):
# Enumerations_in_Typecollection(franca_typecollection):
# Enumerations_in_Package(franca_package):
# Arguments_to_Arguments(franca_arguments):
# Methods_to_Methods(franca_methods):
# Attributes_to_Properties(franca_attributes):
# Typedefs_from_TypeCollection(franca_typecollection):
# Typedefs_from_TypeCollections(franca_typecollections):
# Imports_to_Includes(franca_imports):
# translate_type(t):
# flatmap(function, input_array):
# combined_name(parent, item):
# getValue(intype, outtype):

# Concepts to be covered (from francatypes User Guide 0.12.0.1)
# 5 francatypes IDL Reference ......................................... 27
# 5.1 Data types 27
# 5.1.1 Primitivetypes ....................................................27
# OK -> covered in type_translation
# 5.1.2 Integerwithoptionalrange ............................................29
# TODO: -> Equivalent concept in IFEX - but not yet supported in translator
# 5.1.3 Arrays ..........................................................29
# TODO: -> To be tested/evaluated
# 5.1.4 Enumerations .....................................................30
# OK (Supported in translator)
# 5.1.5 Structures .......................................................31
# TODO: -> To be tested/evaluated
# 5.1.6 Unions(akavariants)................................................32
# TODO: -> Equivalent concept in IFEX (variant) - but not yet supported in translator
# 5.1.7 Maps(akadictionaries) ..............................................33
# TODO: -> Equivalent concept in IFEX (map) - but not yet supported in translator
# 5.1.8 Typedefinitions(akaaliases) ..........................................33
# OK (Supported in translator)
# 5.2 Constant definitions 33
# 5.1.4 Enumerations .....................................................30
# OK (Supported in translator)
# 5.2.1 Primitiveconstants .................................................34
# TODO: -> To be tested/evaluated
# 5.2.2 Complexconstants .................................................34
# TODO: -> To be tested/evaluated
# 5.3 Expressions 35
# 5.3.1 Typesystem ......................................................35
# 5.3.2 Constantvalues....................................................36
# 5.3.3 Comparisonoperators ...............................................36
# 5.3.4 Arithmeticoperations ...............................................36
# 5.3.5 Booleanoperations .................................................36
# Expressions NOT SUPPORTED - Not formally defined in current IFEX spec
# version. Their use seem not very clear (it seems also to be an unfinished
# area also in francatypes specification.
# 5.4 TypeCollection definition 36
# OK Supported in translator
# 5.5 Interface definition 37
# 5.5.1 Basicinterfacedefinition .............................................37
# OK Supported in translator
# 5.5.2 Attributes........................................................38
# OK Supported in translator (IFEX:Property)
# 5.5.3 Methods.........................................................40
# OK Supported in translator
# 5.5.4 Broadcasts .......................................................44
# OK Supported in translator (IFEX:Event)
# TODO: -> To be tested/evaluated
# (In IFEX we would rather
# 5.5.5 Interfacesmanaginginterfaces .........................................45
# WIP: Exact translation is being evaluated. Basically it would add a
# namespace to the "inner" definitions
# 5.6 Contracts 45
# Contracts/PSM enforcement is not part of IFEX specification or project.
# This is a potential extension, or simply use the francatypes IDL development
# environment if this feature is desired.
# 5.7 Comments 48
# 5.7.1 Unstructuredcomments ..............................................48
# TODO: -> Equivalent concept in IFEX - but not yet supported in translator
# 5.7.2 Structuredcomments................................................48
# TODO: -> Equivalent concept in IFEX - but not yet supported in translator

# Part Two
#
# 5.8 Fully qualified names, packages, and multiple files 48
# 5.8.1 Fullyqualifiednames ................................................48
# 5.8.2 Packagedeclarations ................................................48
# 5.8.3 Importsandnamespaceresolution .......................................50
# 6 francatypes Deployment Models .................................... 51
# -> Equivalent concept in IFEX - but not yet supported in translator
# Every deployment model is bespoke, and therefore developing translations
# for them, must also be on a case-by-case basis.
# Out of scope here.

# --- Map fundamental/built-in types ---

type_translation = {
franca.Boolean : "boolean",
franca.ByteBuffer : "uint8[]",
franca.ComplexType : "opaque", # FIXME this is actually a struct reference?
franca.Double : "double",
franca.Float : "float",
franca.Int8 : "int8",
franca.Int16 : "int16",
franca.Int16 : "int16",
franca.Int32 : "int32",
franca.Int64 : "int64",
franca.String : "string",
franca.UInt8 : "uint8",
franca.UInt16 : "uint16",
franca.UInt32 : "uint32",
franca.UInt64 : "uint64",
}

# ----------------------------------------------------------------------------
# HELPER FUNCTIONS
# ----------------------------------------------------------------------------

def translate_type(t):
if type(t) is franca.Enumeration:
return t.name # FIXME use qualified name <InterfaceName>_<EnumerationName>, or change in the other place
if type(t) is franca.Reference:
return t.name
if type(t) is franca.Array:
# FIXME is size of array defined in FRANCA?
converted_type = translate_type(t.type)
converted_type = converted_type + '[]'
return converted_type
else:
t2 = type_translation.get(type(t))
return t2 if t2 is not None else t

# Rename fidl to ifex, for imports
def ifex_import_ref_from_fidl(fidl_file):
return re.sub('.fidl$', '.ifex', fidl_file)

# ----------------------------------------------------------------------------
# --- MAIN conversion function ---
# ----------------------------------------------------------------------------

# Build the Franca AST
def parse_franca(fidl_file):
processor = pyfranca.Processor()
return processor.import_file(fidl_file) # This returns the top level package

# --- Script entry point ---

if __name__ == '__main__':

if len(sys.argv) != 2:
print(f"Usage: python {os.path.basename(__file__)} <filename>")
sys.exit(1)

# Add the type-checking constructor mixin
# FIXME Add this back later for strict checking
#add_constructors_to_ifex_ast_model()

try:
# Parse franca input and create franca AST (top node is the Package definition)
franca_ast = parse_franca(sys.argv[1])

# Convert Franca AST to IFEX AST
ifex_ast = m2m.transform(franca_to_ifex_mapping, franca_ast)

# Output as YAML
print(ifex_ast_as_yaml(ifex_ast))

except FileNotFoundError:
log("ERROR: File not found")
except Exception as e:
raise(e)
log("ERROR: An unexpected error occurred: {}".format(e))

1 change: 1 addition & 0 deletions other/franca/pyfranca
Submodule pyfranca added at e847ef
Loading

0 comments on commit a4ade0e

Please sign in to comment.