From 8e298f98c3026ea0dee192827626775719ed1218 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Mon, 3 Mar 2014 20:58:21 +0400 Subject: [PATCH] Added gtest for dsdlc (not fully implemented yet); dropped support for inf and nan constants in DSDL as this functionality is not portable --- .gitignore | 3 +- libuavcan/CMakeLists.txt | 6 ++-- .../dsdl_compiler/data_type_template.hpp | 10 +++--- libuavcan/dsdl_compiler/dsdlc.py | 36 +++++++++---------- libuavcan/test/dsdl_test/dsdl_test.cpp | 17 +++++++++ .../root_ns_a/3.ReportBackSoldier.uavcan | 8 +++++ .../dsdl_test/root_ns_a/8.EmptyMessage.uavcan | 1 + .../dsdl_test/root_ns_a/NestedMessage.uavcan | 5 +++ .../SuperIntelligentShadeOfBlue.uavcan | 2 ++ pyuavcan/pyuavcan/dsdl/parser.py | 4 +-- 10 files changed, 61 insertions(+), 31 deletions(-) create mode 100644 libuavcan/test/dsdl_test/dsdl_test.cpp create mode 100644 libuavcan/test/dsdl_test/root_ns_a/3.ReportBackSoldier.uavcan create mode 100644 libuavcan/test/dsdl_test/root_ns_a/8.EmptyMessage.uavcan create mode 100644 libuavcan/test/dsdl_test/root_ns_a/NestedMessage.uavcan create mode 100644 libuavcan/test/dsdl_test/root_ns_b/SuperIntelligentShadeOfBlue.uavcan diff --git a/.gitignore b/.gitignore index 7578e9d0b7..5ff5285bdf 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ lib*.so.* *.a */build .dep +__pycache__ # Eclipse .metadata/* @@ -14,4 +15,4 @@ lib*.so.* .pydevproject # libuavcan DSDL compiler default output directory -*dsdlc_output +dsdlc_output diff --git a/libuavcan/CMakeLists.txt b/libuavcan/CMakeLists.txt index 524abbe1fe..03be475cef 100644 --- a/libuavcan/CMakeLists.txt +++ b/libuavcan/CMakeLists.txt @@ -52,11 +52,11 @@ if (GTEST_FOUND) # DSDL compiler invocation add_custom_target(dsdlc dsdl_compiler/dsdlc.py -v - test/dsdl_test/root_ns_a # Input - -Otest/dsdlc_output # Output - -Itest/dsdl_test/root_ns_b # Include + test/dsdl_test/root_ns_a test/dsdl_test/root_ns_b # Inputs + -Otest/dsdlc_output # Output WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) add_dependencies(libuavcan_test dsdlc) + include_directories(${CMAKE_SOURCE_DIR}/test/dsdlc_output) # Tests run automatically upon successful build # If failing tests need to be investigated with debugger, use 'make --ignore-errors' diff --git a/libuavcan/dsdl_compiler/data_type_template.hpp b/libuavcan/dsdl_compiler/data_type_template.hpp index 709ceebd5f..0719c11424 100644 --- a/libuavcan/dsdl_compiler/data_type_template.hpp +++ b/libuavcan/dsdl_compiler/data_type_template.hpp @@ -84,14 +84,14 @@ struct ${t.short_name} % if a.cpp_use_enum: enum { ${a.name} = ${a.cpp_value} }; // ${a.init_expression} % else: - static UAVCAN_CONSTEXPR typename ::uavcan::StorageType::Type + static UAVCAN_CONSTEXPR typename ::uavcan::StorageType< ConstantTypes::${a.name} >::Type ${a.name} = ${a.cpp_value}; // ${a.init_expression} %endif % endfor // Fields % for a in fields: - typename ::uavcan::StorageType::Type ${a.name}; + typename ::uavcan::StorageType< FieldTypes::${a.name} >::Type ${a.name}; % endfor ${type_name}() @@ -129,12 +129,12 @@ ${'::uavcan::TailArrayOptDisabled' if (idx + 1) < len(fields) else 'tao_mode'}); % if t.kind == t.KIND_SERVICE: struct Request { - ${generate_primary_body(t.short_name, t.get_max_bitlen_request(), t.request_fields, t.request_constants) | indent} + ${generate_primary_body('Request', t.get_max_bitlen_request(), t.request_fields, t.request_constants) | indent} }; struct Response { - ${generate_primary_body(t.short_name, t.get_max_bitlen_response(), t.response_fields, t.response_constants) | indent} + ${generate_primary_body('Response', t.get_max_bitlen_response(), t.response_fields, t.response_constants) | indent} }; % else: ${generate_primary_body(t.short_name, t.get_max_bitlen(), t.fields, t.constants)} @@ -187,7 +187,7 @@ UAVCAN_PACKED_END % if t.has_default_dtid: namespace { -::uavcan::DefaultDataTypeRegistrator<${t.short_name}> _uavcan_gdtr_registrator_${t.short_name}; +::uavcan::DefaultDataTypeRegistrator< ${t.short_name} > _uavcan_gdtr_registrator_${t.short_name}; } % else: // No default registration diff --git a/libuavcan/dsdl_compiler/dsdlc.py b/libuavcan/dsdl_compiler/dsdlc.py index 76acf73308..03ed19cf74 100755 --- a/libuavcan/dsdl_compiler/dsdlc.py +++ b/libuavcan/dsdl_compiler/dsdlc.py @@ -50,7 +50,6 @@ def run_parser(source_dir, search_dirs): except dsdl.DsdlException as ex: errtext = str(ex) # TODO: gcc-style formatting die(errtext) - logging.info('%d types from [%s]', len(types), source_dir) return types def run_generator(types, dest_dir): @@ -79,6 +78,8 @@ def write_generated_data(filename, data): return logging.info('Rewriting [%s]', pretty_filename(filename)) os.remove(filename) + else: + logging.info('Creating [%s]', pretty_filename(filename)) # Full rewrite with open(filename, 'w') as f: @@ -95,21 +96,21 @@ def type_to_cpp_type(t): t.CAST_MODE_TRUNCATED: '::uavcan::CastModeTruncate', }[t.cast_mode] if t.kind == t.KIND_FLOAT: - return '::uavcan::FloatSpec<%d, %s>' % (t.bitlen, cast_mode) + return '::uavcan::FloatSpec< %d, %s >' % (t.bitlen, cast_mode) else: signedness = { t.KIND_BOOLEAN: '::uavcan::SignednessUnsigned', t.KIND_UNSIGNED_INT: '::uavcan::SignednessUnsigned', t.KIND_SIGNED_INT: '::uavcan::SignednessSigned', }[t.kind] - return '::uavcan::IntegerSpec<%d, %s, %s>' % (t.bitlen, signedness, cast_mode) + return '::uavcan::IntegerSpec< %d, %s, %s >' % (t.bitlen, signedness, cast_mode) elif t.category == t.CATEGORY_ARRAY: value_type = type_to_cpp_type(t.value_type) mode = { t.MODE_STATIC: '::uavcan::ArrayModeStatic', t.MODE_DYNAMIC: '::uavcan::ArrayModeDynamic', }[t.mode] - return '::uavcan::Array<%s, %s, %d>' % (value_type, mode, t.max_size) + return '::uavcan::Array< %s, %s, %d >' % (value_type, mode, t.max_size) elif t.category == t.CATEGORY_COMPOUND: return '::' + t.full_name.replace('.', '::') else: @@ -149,22 +150,14 @@ def generate_one_type(t): for c in constants: if c.type.kind == c.type.KIND_FLOAT: c.cpp_use_enum = False - numeric_limits = '::std::numeric_limits::Type>' % c.name - numeric_limits_inf = numeric_limits + '::infinity()' - special_values = { - 'inf': numeric_limits_inf, - '+inf': numeric_limits_inf, - '-inf': '-' + numeric_limits_inf, - 'nan': numeric_limits + '::quiet_NaN()', - } - if c.string_value in special_values: - c.cpp_value = special_values[c.string_value] - else: - float(c.string_value) # making sure that this is a valid float literal - c.cpp_value = c.string_value + float(c.string_value) # Making sure that this is a valid float literal + c.cpp_value = c.string_value else: + int(c.string_value) # Making sure that this is a valid integer literal c.cpp_use_enum = c.value >= 0 and c.type.bitlen <= MAX_BITLEN_FOR_ENUM c.cpp_value = c.string_value + if c.type.kind == c.type.KIND_UNSIGNED_INT: + c.cpp_value += 'U' if t.kind == t.KIND_MESSAGE: inject_constant_info(t.constants) @@ -194,7 +187,7 @@ definitions and converts it into compatible hierarchy of C++ types for libuavcan DEFAULT_OUTDIR = './dsdlc_output' argparser = argparse.ArgumentParser(description=DESCRIPTION) -argparser.add_argument('source_dir', help='source directory with DSDL definitions') +argparser.add_argument('source_dir', nargs='+', help='source directory with DSDL definitions') argparser.add_argument('--verbose', '-v', action='count', help='verbosity level (-v, -vv)') argparser.add_argument('--outdir', '-O', default=DEFAULT_OUTDIR, help='output directory, default %s' % DEFAULT_OUTDIR) argparser.add_argument('--incdir', '-I', default=[], action='append', help='nested type namespaces') @@ -202,7 +195,12 @@ args = argparser.parse_args() configure_logging(args.verbose) -types = run_parser(args.source_dir, args.incdir) +types = [] +for srcdir in args.source_dir: + new_types = run_parser(srcdir, args.incdir + args.source_dir) + types += new_types + logging.info('%d types from [%s]', len(new_types), srcdir) + if not types: die('No type definitions were found') diff --git a/libuavcan/test/dsdl_test/dsdl_test.cpp b/libuavcan/test/dsdl_test/dsdl_test.cpp new file mode 100644 index 0000000000..f808b45ec0 --- /dev/null +++ b/libuavcan/test/dsdl_test/dsdl_test.cpp @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2014 Pavel Kirienko + */ + +#include +#include +#include +#include +#include + + +TEST(Dsdl, Basic) +{ + uavcan::StaticTransferBuffer<100> buf; + uavcan::BitStream bs_wr(buf); + uavcan::ScalarCodec sc_wr(bs_wr); +} diff --git a/libuavcan/test/dsdl_test/root_ns_a/3.ReportBackSoldier.uavcan b/libuavcan/test/dsdl_test/root_ns_a/3.ReportBackSoldier.uavcan new file mode 100644 index 0000000000..bab4623c2d --- /dev/null +++ b/libuavcan/test/dsdl_test/root_ns_a/3.ReportBackSoldier.uavcan @@ -0,0 +1,8 @@ +bool TRUE = true +bool NOT_TRUE = false * true +uint64 BIG = (1 << 64) - 1 +uint8[<128] string_request +--- +float64 FLOAT_CONSTANT = 1.79769313486231570815e+308 +root_ns_b.SuperIntelligentShadeOfBlue blue +uint8[<128] string_response diff --git a/libuavcan/test/dsdl_test/root_ns_a/8.EmptyMessage.uavcan b/libuavcan/test/dsdl_test/root_ns_a/8.EmptyMessage.uavcan new file mode 100644 index 0000000000..8d1c8b69c3 --- /dev/null +++ b/libuavcan/test/dsdl_test/root_ns_a/8.EmptyMessage.uavcan @@ -0,0 +1 @@ + diff --git a/libuavcan/test/dsdl_test/root_ns_a/NestedMessage.uavcan b/libuavcan/test/dsdl_test/root_ns_a/NestedMessage.uavcan new file mode 100644 index 0000000000..d4875f15f2 --- /dev/null +++ b/libuavcan/test/dsdl_test/root_ns_a/NestedMessage.uavcan @@ -0,0 +1,5 @@ + +float32 VALUE = 2 +( 2 *2) +bool BOOLEAN = true + false +int2 field +EmptyMessage empty diff --git a/libuavcan/test/dsdl_test/root_ns_b/SuperIntelligentShadeOfBlue.uavcan b/libuavcan/test/dsdl_test/root_ns_b/SuperIntelligentShadeOfBlue.uavcan new file mode 100644 index 0000000000..2badbc9ee2 --- /dev/null +++ b/libuavcan/test/dsdl_test/root_ns_b/SuperIntelligentShadeOfBlue.uavcan @@ -0,0 +1,2 @@ +float16[<32] array_f16 +root_ns_a.NestedMessage[3] nested_message diff --git a/pyuavcan/pyuavcan/dsdl/parser.py b/pyuavcan/pyuavcan/dsdl/parser.py index ae822a41d8..a446d1af02 100644 --- a/pyuavcan/pyuavcan/dsdl/parser.py +++ b/pyuavcan/pyuavcan/dsdl/parser.py @@ -430,9 +430,7 @@ def evaluate_expression(expression): 'globals': None, '__builtins__': None, 'true': 1, - 'false': 0, - 'inf': float('+inf'), - 'nan': float('nan') + 'false': 0 } return eval(expression, env) except Exception as ex: