Commit 0519ff0a authored by Maxime Perrotin's avatar Maxime Perrotin
Browse files

Fixed issues with NOT/OP_MINUS and Ternary operators

parent 41ed2885
......@@ -317,7 +317,7 @@ package {process_name} is'''.format(process_name=process_name,
for timer in process.timers:
ads_template.append(
u'-- Timer {} SET and RESET functions'.format(timer))
ads_template.append(u'procedure SET_{}(val: access asn1SccT_UInt32);'
ads_template.append(u'procedure SET_{}(val: access Asn1Int);'
.format(timer))
ads_template.append(
u'pragma import(C, SET_{timer}, "{proc}_RI_set_{timer}");'
......@@ -435,7 +435,7 @@ def write_statement(param, newline):
'BooleanType', 'Integer32Type'):
code, string, local = expression(param)
if type_kind == 'IntegerType':
cast = "Interfaces.Integer_64"
cast = "Asn1Int"
elif type_kind == 'RealType':
cast = 'Long_Float'
elif type_kind == 'BooleanType':
......@@ -501,7 +501,9 @@ def _call_external_function(output):
local_decl.extend(p_local)
# Use a temporary variable to store the timer value
tmp_id = 'tmp' + str(out['tmpVars'][0])
local_decl.append('{} : aliased asn1SccT_Uint32;'.format(tmp_id))
local_decl.append('{} : aliased Asn1Int;'
.format(tmp_id))
#local_decl.append('{} : aliased Interfaces.Integer_64' asn1SccT_Uint32;'.format(tmp_id))
code.append('{tmp} := {val};'.format(tmp=tmp_id, val=t_val))
code.append("SET_{timer}({value}'access);"
.format(timer=p_id, value=tmp_id))
......@@ -706,7 +708,7 @@ def _primary_variable(prim):
ada_string = '(-{})'.format(ada_string)
if prim.exprType.__name__ == 'for_range':
# Ada iterator in FOR loops is an Integer - we must cast to 64 bits
ada_string = u'Interfaces.Integer_64({})'.format(ada_string)
ada_string = u'Asn1Int({})'.format(ada_string)
return [], ada_string, []
......@@ -810,7 +812,7 @@ def _prim_path(primary_id):
ada_string += '{op}({param})'.format(
param=param_str,
op='abs' if special_op == 'Abs' else
'Interfaces.Integer_64' if special_op == 'CastInt'
'Asn1Int' if special_op == 'CastInt'
else 'adaasn1rtl.Asn1Real'
if special_op == 'CastReal' else 'ERROR')
elif special_op == 'Power':
......@@ -839,7 +841,7 @@ def _prim_path(primary_id):
if min_length == max_length:
ada_string += min_length
else:
ada_string += ('Interfaces.Integer_64({e}.Length)'
ada_string += ('Asn1Int({e}.Length)'
.format(e=param_str))
elif special_op == 'ChoiceKind':
# User wants to know what CHOICE element is present
......@@ -874,6 +876,10 @@ def _prim_path(primary_id):
ada_string += ', '.join(list_of_params)
ada_string += ')'
sep = '.'
if primary_id.op_not:
ada_string = 'not {}'.format(ada_string)
elif primary_id.op_minus:
ada_string = '(-{})'.format(ada_string)
return stmts, ada_string, local_decl
......@@ -1076,8 +1082,11 @@ def _integer(primary):
@expression.register(ogAST.PrimBoolean)
def _integer(primary):
''' Generate code for a raw integer/real/boolean value '''
return [], primary.value[0], []
''' Generate code for a raw boolean value '''
ada_string = primary.value[0]
if primary.op_not:
ada_string = 'not {}'.format(ada_string)
return [], ada_string, []
@expression.register(ogAST.PrimEmptyString)
......@@ -1125,25 +1134,41 @@ def _if_then_else(ifThenElse):
''' Return string and statements for ternary operator '''
resType = ifThenElse.exprType
stmts = []
local_decl = ['tmp{idx} : asn1Scc{resType};'.format(
idx=ifThenElse.value['tmpVar'],
resType=resType.ReferencedTypeName.replace('-', '_'))]
if resType.kind.startswith('Integer'):
tmp_type = 'Asn1Int'
elif resType.kind == 'StandardStringType':
then_str = ifThenElse.value['then'].value.replace("'", '"')
else_str = ifThenElse.value['else'].value.replace("'", '"')
lens = [len(then_str), len(else_str)]
tmp_type = 'String(1 .. {})'.format(max(lens) - 2)
# Ada require fixed-length strings, adjust with spaces
if lens[0] < lens[1]:
then_str = then_str[0:-1] + ' '* (lens[1] - lens[0]) + '"'
elif lens[1] < lens[0]:
else_str = else_str[0:-1] + ' '* (lens[0] - lens[1]) + '"'
else:
tmp_type = 'asn1Scc' + resType.ReferencedTypeName.replace('-', '_')
local_decl = ['tmp{idx} : {tmpType};'.format(
idx=ifThenElse.value['tmpVar'],
tmpType=tmp_type)]
if_stmts, if_str, if_local = expression(ifThenElse.value['if'])
then_stmts, then_str, then_local = expression(ifThenElse.value['then'])
else_stmts, else_str, else_local = expression(ifThenElse.value['else'])
stmts.extend(if_stmts)
stmts.extend(then_stmts)
stmts.extend(else_stmts)
local_decl.extend(if_local)
local_decl.extend(then_local)
local_decl.extend(else_local)
stmts.append(u'if {if_str} then'.format(
if_str=if_str))
if resType.kind != 'StandardStringType':
then_stmts, then_str, then_local = expression(ifThenElse.value['then'])
else_stmts, else_str, else_local = expression(ifThenElse.value['else'])
stmts.extend(then_stmts)
stmts.extend(else_stmts)
local_decl.extend(then_local)
local_decl.extend(else_local)
stmts.append(u'if {if_str} then'.format(if_str=if_str))
stmts.append(u'tmp{idx} := {then_str};'.format(
idx=ifThenElse.value['tmpVar'], then_str=then_str))
idx=ifThenElse.value['tmpVar'],
then_str=then_str))
stmts.append('else')
stmts.append(u'tmp{idx} := {else_str};'.format(
idx=ifThenElse.value['tmpVar'], else_str=else_str))
idx=ifThenElse.value['tmpVar'],
else_str=else_str))
stmts.append('end if;')
ada_string = u'tmp{idx}'.format(idx=ifThenElse.value['tmpVar'])
return stmts, ada_string, local_decl
......
......@@ -74,17 +74,22 @@ DV = None
TMPVAR = 0
# ASN.1 types used to support the signature of special operators
INTEGER = type('IntegerType', (object,), {'kind': 'IntegerType'})
INTEGER = type('IntegerType', (object,), {'kind': 'IntegerType',
'Min': str(-(2 ** 63)),
'Max': str(2 ** 63 - 1)})
INT32 = type('Integer32Type', (object,), {'kind': 'Integer32Type',
'Min':'-2147483648',
'Max':'2147483647'})
NUMERICAL = type('NumericalType', (object,), {'kind': 'Numerical'})
TIMER = type('TimerType', (object,), {'kind': 'TimerType'})
REAL = type('RealType', (object,), {'kind': 'RealType'})
REAL = type('RealType', (object,), {'kind': 'RealType',
'Min': str(1e-308),
'Max': str(1e308)})
LIST = type('ListType', (object,), {'kind': 'ListType'})
ANY_TYPE = type('AnyType', (object,), {'kind': 'AnyType'})
CHOICE = type('ChoiceType', (object,), {'kind': 'ChoiceType'})
BOOLEAN = type('BooleanType', (object,), {'kind': 'BooleanType'})
RAWSTRING = type('RawString', (object,), {'kind': 'StandardStringType'})
UNKNOWN_TYPE = type('UnknownType', (object,), {'kind': 'UnknownType'})
......@@ -303,8 +308,7 @@ def fix_special_operators(op_name, expr_list, context):
.format(op_name))
expr = expr_list[0]
if expr.exprType is UNKNOWN_TYPE:
expr.exprType = find_variable(expr.inputString, context)
# XXX don't use inputString, there can be brackets
expr.exprType = find_variable(expr.value[0], context)
# XXX should change type to PrimVariable
basic = find_basic_type(expr.exprType)
if op_name.lower() == 'length' and basic.kind != 'SequenceOfType' \
......@@ -322,8 +326,7 @@ def fix_special_operators(op_name, expr_list, context):
types = {}
for idx, expr in enumerate(expr_list):
if expr.exprType is UNKNOWN_TYPE:
expr.exprType = find_variable(expr.inputString, context)
# XXX don't use inputString, there can be brackets
expr.exprType = find_variable(expr.value[0], context)
# XXX should change type to PrimVariable
if idx == 0 and not find_basic_type(expr.exprType).kind in (
'IntegerType', 'Integer32Type', 'Numerical', 'RealType'):
......@@ -334,7 +337,21 @@ def fix_special_operators(op_name, expr_list, context):
elif op_name.lower() in ('write', 'writeln'):
for param in expr_list:
if param.exprType is UNKNOWN_TYPE:
param.exprType = find_variable(param.inputString, context)
for each in (INTEGER, REAL, BOOLEAN, RAWSTRING):
try:
check_type_compatibility(param, each, context)
param.exprType = each
break
except TypeError:
continue
else:
# Type not found among supported types
# Has to be a variable...otherwise, error!
try:
param.exprType = find_variable(param.value[0], context)
except KeyError, AttributeError:
raise TypeError('Could not determine type of argument'
' "{}"'.format(param.inputString))
basic = find_basic_type(param.exprType)
if basic.kind not in ('IntegerType', 'Integer32Type',
'RealType', 'BooleanType') \
......@@ -490,6 +507,12 @@ def check_type_compatibility(primary, typeRef, context):
check_type_compatibility(expr, typeRef, context)
# compare the types for semantic equivalence:
else:
if expr.exprType is UNKNOWN_TYPE:
# If it was not resolved before, it must be a variable
# this can happen in the context of a special operator
# (write), where at no point before where the type
# could be compared to another type
expr.exprType = find_variable(expr.value[0], context)
compare_types(expr.exprType, typeRef)
return
elif isinstance(primary, ogAST.PrimVariable):
......@@ -602,14 +625,18 @@ def check_type_compatibility(primary, typeRef, context):
elif isinstance(primary, ogAST.PrimStringLiteral):
# Octet strings
basic_type = find_basic_type(typeRef)
if(basic_type.kind.endswith('StringType') and
int(basic_type.Min) <= len(
primary.value[1:-1]) <= int(basic_type.Max)):
if basic_type.kind == 'StandardStringType':
return
else:
raise TypeError('Invalid string literal - check that lenght is'
'within the bound limits {Min}..{Max}'.format
elif basic_type.kind.endswith('StringType'):
if int(basic_type.Min) <= len(
primary.value[1:-1]) <= int(basic_type.Max):
return
else:
raise TypeError('Invalid string literal - check that length is'
'within the bound limits {Min}..{Max}'.format
(Min=str(basic_type.Min), Max=str(basic_type.Max)))
else:
raise TypeError('String literal not expected')
elif (isinstance(primary, ogAST.PrimMantissaBaseExp) and
actual_type.kind == 'RealType'):
LOG.debug('PROBABLY (it is a float but I did not check'
......@@ -1182,6 +1209,7 @@ def primary_value(root, context=None):
check_and_fix_op_params(
prim.value[0].lower(), expr_list, context)
except (AttributeError, TypeError) as err:
LOG.debug(traceback.format_exc())
errors.append(str(err) + '- ' + get_input_string(root))
prim.value.append({'procParams': expr_list})
else:
......
......@@ -10,7 +10,6 @@ test-ada:
gcc -c test.c
gnatbind -n myfunction.ali
gnatlink -o testcase test.o myfunction.ali -lgnat
./testcase
./testcase | diff expected -
coverage:
......
......@@ -23,6 +23,7 @@ IMPORTS T-Int32, T-UInt32, T-Int8, T-UInt8, T-Boolean FROM TASTE-BasicTypes;
MyInteger ::= T-UInt8
MyReal ::= REAL (0.0 .. 1000.0)
LargerReal ::= REAL (0.0 .. 1000000000)
MyEnum ::= ENUMERATED { hello, world, howareyou }
......@@ -37,7 +38,7 @@ MyChoice ::= CHOICE {
}
MySeqOf ::= SEQUENCE (SIZE (2)) OF MyEnum
SeqInt ::= SEQUENCE (SIZE(1..2)) OF T-UInt8
MyOctStr ::= OCTET STRING (SIZE (3))
-- You can also declare variables (they will be visible in C, Ada and SDL)
......
[C Code] Running test
-2 is FALSE
2 2 1
FALSE TRUE
OK
[C] result_data: 6
Hello Toto 5
[C] SET MyTimer: 1000
1.50000000000000E+00 ** 2 == 2.25000000000000E+00 (should be 2.25 )
timer expired
/* CIF PROCESS (148, 150), (150, 75) */
PROCESS myfunction;
/* CIF TEXT (0, 17), (271, 323) */
/* CIF TEXT (0, 17), (296, 368) */
-- Timers defined in the interface view
-- Use SET_TIMER (value, timer name)
-- and RESET_TIMER (timer name) in a
......@@ -17,14 +17,17 @@ DCL def_val MySeq := { a 3, b taste };
-- To test power, fix, float
dcl someReal MyReal := 1.5;
dcl largeReal LargerReal := 0.0;
dcl someInt t_uInt8 := 2;
-- To test 'op_not'
dcl opnot T_boolean := not true;
dcl bar SeqInt := { 1,1 };
/* CIF ENDTEXT */
/* CIF PROCEDURE (982, 490), (91, 35) */
PROCEDURE factorial;
/* CIF TEXT (29, 42), (215, 48) */
/* CIF TEXT (29, 42), (215, 53) */
fpar in N MyInteger,
in/out result MyInteger;
/* CIF ENDTEXT */
......@@ -41,61 +44,73 @@ endfor;
ENDPROCEDURE;
/* CIF START (591, 0), (100, 50) */
START;
/* CIF TASK (586, 65), (110, 35) */
TASK someInt := 0;
/* CIF DECISION (504, 115), (273, 87) */
/* CIF PROCEDURECALL (430, 65), (421, 35) */
CALL writeln(-someint, if someint>0 then ' is ' else 'Foo' fi, not true);
/* CIF PROCEDURECALL (514, 115), (254, 35) */
CALL write(if someint>0 then 2 else 1 fi);
/* CIF PROCEDURECALL (496, 165), (289, 35) */
CALL write(if someint>0 then someint else 1 fi);
/* CIF PROCEDURECALL (577, 215), (128, 35) */
CALL writeln(bar(1));
/* CIF PROCEDURECALL (532, 265), (217, 35) */
CALL writeln(opnot, ' ', not opnot);
/* CIF TASK (480, 315), (321, 35) */
TASK someInt := if someint = 0 then someint else 0 fi;
/* CIF DECISION (504, 365), (273, 87) */
DECISION someint /=0 and then (10 / someInt > 0)
or else someint = 0
/* CIF COMMENT (793, 124), (179, 68) */
/* CIF COMMENT (793, 374), (179, 68) */
COMMENT 'Using "and else" is the
short-circuit form. The
second part should not
be evaluated.';
/* CIF ANSWER (561, 222), (70, 23) */
/* CIF ANSWER (561, 472), (70, 23) */
(true):
/* CIF TASK (541, 260), (110, 35) */
TASK someInt := 5;
/* CIF PROCEDURECALL (537, 310), (117, 38) */
/* CIF TASK (541, 510), (110, 35) */
TASK someInt := 2;
/* CIF PROCEDURECALL (537, 560), (117, 38) */
CALL writeln('OK');
/* CIF ANSWER (664, 222), (70, 23) */
/* CIF ANSWER (664, 472), (70, 23) */
(false):
ENDDECISION;
/* CIF NEXTSTATE (591, 363), (100, 50) */
/* CIF NEXTSTATE (608, 613), (65, 33) */
NEXTSTATE Wait;
/* CIF STATE (591, 363), (100, 50) */
/* CIF STATE (608, 613), (65, 33) */
STATE Wait;
/* CIF INPUT (810, 433), (100, 50) */
/* CIF INPUT (865, 666), (89, 33) */
INPUT mytimer;
/* CIF PROCEDURECALL (769, 498), (182, 50) */
/* CIF PROCEDURECALL (818, 714), (182, 33) */
CALL writeln('timer expired');
/* CIF PROCEDURECALL (780, 563), (160, 35) */
/* CIF PROCEDURECALL (829, 762), (160, 33) */
CALL factorial(3, someint);
/* CIF NEXTSTATE (810, 613), (100, 50) */
/* CIF NEXTSTATE (877, 810), (65, 33) */
NEXTSTATE Wait;
/* CIF INPUT (450, 433), (198, 50) */
/* CIF INPUT (421, 666), (181, 33) */
INPUT start_something (toto);
/* CIF OUTPUT (414, 498), (270, 50) */
/* CIF OUTPUT (376, 714), (270, 33) */
OUTPUT result_data((toto+1) mod 2147483647);
/* CIF PROCEDURECALL (474, 563), (150, 50) */
/* CIF PROCEDURECALL (436, 762), (150, 48) */
CALL writeln
('Hello Toto', toto);
/* CIF PROCEDURECALL (451, 628), (196, 50) */
/* CIF PROCEDURECALL (413, 825), (196, 33) */
CALL set_timer(1000, myTimer);
/* CIF TASK (391, 693), (316, 35) */
TASK someReal := power(someReal, someInt mod 1);
/* CIF PROCEDURECALL (379, 743), (340, 35) */
CALL writeln('1.5 ** 2 == ', someReal, ' (should be 2.25 )');
/* CIF TASK (448, 793), (201, 35) */
/* CIF TASK (346, 873), (330, 35) */
TASK largeReal := power(someReal, 2);
/* CIF PROCEDURECALL (282, 923), (458, 35) */
CALL writeln(someReal, ' ** 2' , ' == ', largeReal, ' (should be 2.25 )');
/* CIF TASK (411, 973), (201, 35) */
TASK someReal := float(someInt);
/* CIF TASK (428, 843), (241, 35) */
/* CIF TASK (391, 1023), (241, 35) */
TASK someInt := fix(someReal) mod 255;
/* CIF TASK (473, 893), (152, 35) */
/* CIF TASK (435, 1073), (152, 35) */
TASK opnot := not opnot;
/* CIF TASK (470, 943), (157, 35) */
TASK someint := -someint;
/* CIF TASK (467, 993), (164, 35) */
/* CIF TASK (430, 1123), (163, 35) */
TASK 'someint := -someint'
/* CIF COMMENT (613, 1123), (196, 35) */
COMMENT 'XXX should raise an error!';
/* CIF TASK (429, 1173), (164, 35) */
TASK someint := (-8) mod 5;
/* CIF NEXTSTATE (498, 1043), (102, 50) */
/* CIF NEXTSTATE (480, 1223), (63, 33) */
NEXTSTATE wait;
ENDSTATE;
ENDPROCESS myfunction;
\ No newline at end of file
#include <math.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
extern void adainit();
extern void myfunction_start_something(long long *);
extern void myfunction_mytimer();
volatile sig_atomic_t keep_going = 1;
void myfunction_RI_result_data(long long *val)
{
......@@ -12,8 +17,17 @@ void myfunction_RI_result_data(long long *val)
void myfunction_RI_set_mytimer(long long *val)
{
printf("[C] SET MyTimer: %lld\n", *val);
alarm(((int)*val) / 1000);
}
void timer_expired()
{
myfunction_mytimer();
keep_going = 0;
}
void myfunction_RI_reset_mytimer()
{
printf("RESET MyTimer\n");
......@@ -21,9 +35,13 @@ void myfunction_RI_reset_mytimer()
int main()
{
long long test = 5;
signal(SIGALRM, timer_expired);
printf("[C Code] Running test\n");
adainit();
myfunction_start_something(&test);
while (keep_going);
return 0;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment