Commit 8d8927b6 authored by Maxime Perrotin's avatar Maxime Perrotin
Browse files

Bugfixes in substring handling

parent 0eb4f5a1
......@@ -430,23 +430,19 @@ def write_statement(param, newline):
localstr = u'tmp{}{}str'.format(str(param.tmpVar), sep)
local.append(u'{} : String(1 .. {});'
.format(localstr, basic_type.Max))
range_len = u"{}.Data'Range".format(string) \
if basic_type.Min == basic_type.Max \
else "1 .. {}.Length".format(string)
code.extend([u"for i in {} loop".format(range_len),
u"{tmp}(i) := Character'Val({st}.Data(i));"
if isinstance(param, ogAST.PrimSubstring):
range_str = u"{}'Range".format(string)
elif basic_type.Min == basic_type.Max:
range_str = u"{}.Data'Range".format(string)
string += u".Data"
else:
range_str = u"1 .. {}.Length".format(string)
string += u".Data"
code.extend([u"for i in {} loop".format(range_str),
u"{tmp}(i) := Character'Val({st}(i));"
.format(tmp=localstr, st=string, sep=sep),
u"end loop;"])
# if basic_type.Min != basic_type.Max:
# code.extend(["if {string}.Length < {to} then"
# .format(string=string, to=basic_type.Max),
# u"{tmp}({string}.Length + 1 .. {to}) "
# u":= (others=>Character'Val(0));"
# .format(tmp=localstr,
# string=string,
# to=basic_type.Max),
# "end if;"])
string = u'{}({})'.format(localstr, range_len)
string = u'{}({})'.format(localstr, range_str)
elif type_kind in ('IntegerType', 'RealType',
'BooleanType', 'Integer32Type'):
code, string, local = expression(param)
......@@ -664,9 +660,11 @@ def _task_forloop(task):
list_stmt, list_str, list_local = expression(loop['list'])
basic_type = find_basic_type(loop['list'].exprType)
list_payload = list_str + string_payload(loop['list'], list_str)
range_cond = "{}'Range".format(list_payload)\
if basic_type.Min == basic_type.Max\
else "1..{}.Length".format(list_str)
if isinstance(loop['list'], ogAST.PrimSubstring) or \
basic_type.Min == basic_type.Max:
range_str = u"{}'Range".format(list_payload)
else:
range_str = u"1 .. {}.Length".format(list_str)
stmt.extend(list_stmt)
local_decl.extend(list_local)
stmt.extend(['declare',
......@@ -675,7 +673,7 @@ def _task_forloop(task):
'',
'begin',
'for {it}_idx in {rc} loop'.format(it=loop['var'],
rc=range_cond),
rc=range_str),
'{it} := {var}({it}_idx);'.format(it=loop['var'],
var=list_payload)])
try:
......@@ -764,7 +762,11 @@ def _prim_call(prim):
if min_length == max_length:
ada_string += min_length
else:
ada_string += ('Asn1Int({e}.Length)'.format(e=param_str))
if isinstance(exp, ogAST.PrimSubstring):
range_str = u"{}'Length".format(param_str)
else:
range_str = u"{}.Length".format(param_str)
ada_string += ('Asn1Int({})'.format(range_str))
elif ident == 'present':
# User wants to know what CHOICE element is present
exp = params[0]
......@@ -869,31 +871,6 @@ def _prim_substring(prim):
local_decl.extend(r1_local)
local_decl.extend(r2_local)
# # should we add 1 in case of numerical values? (see index)
# ada_string += '.Data({r1}..{r2})'.format(r1=r1_string, r2=r2_string)
# stmts.extend(r1_stmts)
# stmts.extend(r2_stmts)
# local_decl.extend(r1_local)
# local_decl.extend(r2_local)
#
# local_decl.append('tmp{idx} : aliased asn1Scc{parent_type};'.format(
# idx=prim.value[1]['tmpVar'], parent_type=receiver_ty_name))
#
# # XXX types with fixed length: substrings will not work
# if unicode.isnumeric(r1_string) and unicode.isnumeric(r2_string):
# length = int(r2_string) - int(r1_string) + 1
# else:
# length = ('{r2} - {r1} + 1'.format(r2=r2_string, r1=r1_string))
#
# prim_basic = find_basic_type(prim.exprType)
# if int(prim_basic.Min) != int(prim_basic.Max):
# stmts.append('tmp{idx}.Length := {length};'.format(
# idx=prim.value[1]['tmpVar'], length=length))
#
# stmts.append('tmp{idx}.Data(1..{length}) := {data};'.format(
# idx=prim.value[1]['tmpVar'], length=length, data=ada_string))
# ada_string = 'tmp{idx}'.format(idx=prim.value[1]['tmpVar'])
return stmts, unicode(ada_string), local_decl
......@@ -1082,7 +1059,7 @@ def _append(expr):
length = unicode(int(expr.left.slen) + int(expr.right.slen))
else:
length = '{} + {}'.format(expr.left.slen, expr.right.slen)
stmts.append('{res}.Data(1..{length}) := {lid} & {rid};'
stmts.append('{res}.Data(1 .. {length}) := {lid} & {rid};'
.format(length=length,
res=ada_string,
lid=left_payload,
......@@ -1110,12 +1087,16 @@ def _expr_in(expr):
local_decl.extend(right_local)
stmts.append("in_loop_{}:".format(ada_string))
left_type = find_basic_type(expr.left.exprType)
if isinstance(expr.left, ogAST.PrimSubstring):
len_str = u"{}'Length".format(left_str)
else:
len_str = u"{}.Length".format(left_str)
left_str += u".Data"
if left_type.Min != left_type.Max:
stmts.append("for elem in 1..Integer({}.Length) loop"
.format(left_str))
stmts.append("for elem in 1..{} loop".format(len_str))
else:
stmts.append("for elem in {}.Data'Range loop".format(left_str))
stmts.append("if {container}.Data(elem) = {pattern} then".format
stmts.append("for elem in {}'Range loop".format(left_str))
stmts.append("if {container}(elem) = {pattern} then".format
(container=left_str, pattern=right_str))
stmts.append("{} := True;".format(ada_string))
stmts.append("end if;")
......@@ -1210,6 +1191,7 @@ def _if_then_else(ifThenElse):
if resType.kind.startswith('Integer'):
tmp_type = 'Asn1Int'
elif resType.kind == 'StandardStringType':
print ifThenElse.value['then'].value
then_str = ifThenElse.value['then'].value.replace("'", '"')
else_str = ifThenElse.value['else'].value.replace("'", '"')
lens = [len(then_str), len(else_str)]
......
......@@ -2,7 +2,7 @@
 
# Resource object code
#
# Created: Thu Jul 17 20:45:57 2014
# Created: Tue Jul 22 16:47:55 2014
# by: The Resource Compiler for PySide (Qt v4.8.6)
#
# WARNING! All changes made in this file will be lost!
......@@ -533,7 +533,7 @@ def check_type_compatibility(primary, typeRef, context):
return
actual_type = find_basic_type(typeRef)
LOG.debug("[check_type_compatibility] "
"checking if {value} is of type {typeref}: "
"checking if {value} is of type {typeref}"
.format(value=primary.inputString, typeref=type_name(typeRef)))
if (isinstance(primary, ogAST.PrimEnumeratedValue)
......@@ -785,23 +785,44 @@ def find_variable(var, context):
raise AttributeError('Variable {var} not defined'.format(var=var))
def fix_enumerated_and_choice(expr_enum, context):
''' If left side of the expression is of Enumerated or Choice type,
check if right side is a literal of that sort, and update type '''
kind = find_basic_type(expr_enum.left.exprType).kind
if kind == 'EnumeratedType':
prim = ogAST.PrimEnumeratedValue(primary=expr_enum.right)
elif kind == 'ChoiceEnumeratedType':
prim = ogAST.PrimChoiceDeterminant(primary=expr_enum.right)
try:
check_type_compatibility(prim, expr_enum.left.exprType, context)
expr_enum.right = prim
expr_enum.right.exprType = expr_enum.left.exprType
except (UnboundLocalError, AttributeError, TypeError):
pass
else:
LOG.debug('Fixed enumerated/choice: {}'.format(expr_enum.inputString))
def fix_expression_types(expr, context):
''' Check/ensure type consistency in binary expressions '''
# If a side of the expression is of Enumerated or Choice type, check if
# the other side is a literal of that sort, and change type accordingly
for side in permutations(('left', 'right')):
side_type = find_basic_type(getattr(expr, side[0]).exprType).kind
if side_type == 'EnumeratedType':
prim = ogAST.PrimEnumeratedValue(primary=getattr(expr, side[1]))
elif side_type == 'ChoiceEnumeratedType':
prim = ogAST.PrimChoiceDeterminant(primary=getattr(expr, side[1]))
try:
check_type_compatibility(prim, getattr(expr, side[0]).exprType,
context)
setattr(expr, side[1], prim)
getattr(expr, side[1]).exprType = getattr(expr, side[0]).exprType
except (UnboundLocalError, AttributeError, TypeError):
pass
for _ in range(2):
# Check if an raw enumerated value is of a reference type
fix_enumerated_and_choice(expr, context)
expr.right, expr.left = expr.left, expr.right
# for side in permutations(('left', 'right')):
# side_type = find_basic_type(getattr(expr, side[0]).exprType).kind
# if side_type == 'EnumeratedType':
# prim = ogAST.PrimEnumeratedValue(primary=getattr(expr, side[1]))
# elif side_type == 'ChoiceEnumeratedType':
# prim = ogAST.PrimChoiceDeterminant(primary=getattr(expr, side[1]))
# try:
# check_type_compatibility(prim, getattr(expr, side[0]).exprType,
# context)
# setattr(expr, side[1], prim)
# getattr(expr, side[1]).exprType = getattr(expr, side[0]).exprType
# except (UnboundLocalError, AttributeError, TypeError):
# pass
# If a side type remains unknown, check if it is an ASN.1 constant
for side in permutations(('left', 'right')):
......@@ -845,6 +866,7 @@ def fix_expression_types(expr, context):
unknown = [uk_expr for uk_expr in expr.right, expr.left
if uk_expr.exprType == UNKNOWN_TYPE]
if unknown:
#print traceback.print_stack()
raise TypeError('Cannot resolve type of "{}"'
.format(unknown[0].inputString))
......@@ -950,7 +972,7 @@ def primary_variable(root, context):
def binary_expression(root, context):
''' Binary expression analysys '''
''' Binary expression analysis '''
errors, warnings = [], []
ExprNode = EXPR_NODE[root.type]
......@@ -1140,6 +1162,7 @@ def in_expression(root, context):
expr.exprType = BOOLEAN
# check that left part is a SEQUENCE OF or a string
left_type = expr.left.exprType
container_basic_type = find_basic_type(expr.left.exprType)
if container_basic_type.kind == 'SequenceOfType':
ref_type = container_basic_type.type
......@@ -1149,8 +1172,18 @@ def in_expression(root, context):
msg = 'IN expression: right part must be a list'
errors.append(error(root, msg))
return expr, errors, warnings
expr.left.exprType = ref_type
if find_basic_type(ref_type).kind == 'EnumeratedType':
fix_enumerated_and_choice(expr, context)
expr.left.exprType = left_type
try:
compare_types(expr.right.exprType, ref_type)
except TypeError as err:
errors.append(error(root, str(err)))
compare_types(expr.right.exprType, ref_type)
if expr.right.is_raw and expr.left.is_raw:
# If both sides are raw (e.g. "3 in {1,2,3}"), evaluate expression
bool_expr = ogAST.PrimBoolean()
......@@ -1175,7 +1208,8 @@ def append_expression(root, context):
''' Append expression analysis '''
expr, errors, warnings = binary_expression(root, context)
for bty in (find_basic_type(expr.left.exprType), find_basic_type(expr.right.exprType)):
for bty in (find_basic_type(expr.left.exprType),
find_basic_type(expr.right.exprType)):
if bty.kind != 'SequenceOfType' and not is_string(bty):
msg = 'Append can only be applied to types SequenceOf or String'
errors.append(error(root, msg))
......
# $ANTLR 3.1.3 Mar 17, 2009 19:23:44 sdl92.g 2014-07-21 13:25:47
# $ANTLR 3.1.3 Mar 17, 2009 19:23:44 sdl92.g 2014-07-22 16:47:59
import sys
from antlr3 import *
......
# $ANTLR 3.1.3 Mar 17, 2009 19:23:44 sdl92.g 2014-07-21 13:25:45
# $ANTLR 3.1.3 Mar 17, 2009 19:23:44 sdl92.g 2014-07-22 16:47:58
 
import sys
from antlr3 import *
......
EXAMPLES=test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 test11 test12 test13
EXAMPLES=test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 test11 test12 test13 test-substrings
coverage:
for v in $(EXAMPLES) ; do make -C $$v coverage && mv $$v/.coverage* . || exit 1 ; done ; coverage combine
......
all: test-ada
edit:
../../../opengeode.py myfunction.pr system_structure.pr
check:
../../../opengeode.py myfunction.pr system_structure.pr --check
test-parse:
../../../opengeode.py myfunction.pr system_structure.pr --check
test-ada:
../../../opengeode.py --toAda myfunction.pr system_structure.pr || exit 1
asn1.exe -Ada dataview-uniq.asn -typePrefix asn1Scc -equal
asn1.exe -c dataview-uniq.asn -typePrefix asn1Scc
gnatmake -c myfunction.adb
gcc -c test.c
gnatbind -n myfunction.ali
gnatlink -o testcase test.o myfunction.ali -lgnat
./testcase | diff expected -
coverage:
coverage run -p ../../../opengeode.py myfunction.pr system_structure.pr --toAda
clean:
rm -rf *.adb *.ads *.pyc runSpark.sh spark.idx *.o *.ali gnat.cfg examiner bin *.wrn *.gpr datav*.? ber.c xer.c asn1crt.? acn.c real.c
TASTE-BasicTypes DEFINITIONS ::=
BEGIN
-- Set of TASTE predefined basic types
T-Int32 ::= INTEGER (-2147483648 .. 2147483647)
T-UInt32 ::= INTEGER (0 .. 4294967295)
T-Int8 ::= INTEGER (-128 .. 127)
T-UInt8 ::= INTEGER (0 .. 255)
T-Boolean ::= BOOLEAN
END
TASTE-Dataview DEFINITIONS ::=
BEGIN
IMPORTS T-Int32, T-UInt32, T-Int8, T-UInt8, T-Boolean FROM TASTE-BasicTypes;
-- A few simple types to start with ASN.1
MyInteger ::= T-UInt8
MyReal ::= REAL (0.0 .. 1000.0)
LargerReal ::= REAL (0.0 .. 1000000000)
MyEnum ::= ENUMERATED { hello(12), world(13), howareyou(111) }
MySeq ::= SEQUENCE {
a MyInteger,
b ENUMERATED { taste(1), welcomes(2), you(3) }
}
MyChoice ::= CHOICE {
a BOOLEAN,
b MySeq
}
MySeqOf ::= SEQUENCE (SIZE (2)) OF MyEnum
SeqInt ::= SEQUENCE (SIZE(1..2)) OF T-UInt8
MyOctStr ::= OCTET STRING (SIZE (3))
String ::= OCTET STRING (SIZE(0..100))
-- You can also declare variables (they will be visible in C, Ada and SDL)
myVar MySeqOf ::= { hello, world }
END
[C Code] Running test
TRUE
TRUE
Hello
12
13
-12
-13
2
2
1
1
TRUE
TRUE
1
1
1
5
/* CIF PROCESS (200, 143), (150, 75) */
PROCESS myfunction;
/* CIF TEXT (7, 43), (327, 41) */
-- Test substrings in various contexts and operators
/* CIF ENDTEXT */
/* CIF TEXT (0, 133), (282, 108) */
dcl str MyOctStr := 'abc';
dcl variable_str String := 'Hello!';
dcl seqof MySeqOf := {hello, world};
dcl seqint seqInt := {1};
/* CIF ENDTEXT */
/* CIF PROCEDURE (1416, 490), (91, 35) */
PROCEDURE factorial;
/* CIF TEXT (29, 42), (215, 53) */
fpar in N MyInteger,
in/out result MyInteger;
/* CIF ENDTEXT */
/* CIF START (298, 33), (70, 35) */
START;
/* CIF TASK (284, 83), (97, 35) */
TASK result := 1;
/* CIF TASK (223, 133), (220, 53) */
TASK for x in range(1, n+1):
result := (result * x) mod 255
endfor;
/* CIF RETURN (315, 201), (35, 35) */
RETURN ;
ENDPROCEDURE;
/* CIF START (114, 247), (65, 37) */
START;
/* CIF DECISION (85, 299), (123, 50) */
DECISION hello in seqof
/* CIF COMMENT (228, 300), (179, 53) */
COMMENT 'Check IN operator with
enumerated type';
/* CIF ANSWER (14, 369), (70, 23) */
(true):
/* CIF PROCEDURECALL (-39, 407), (177, 35) */
CALL writeln(hello in seqof)
/* CIF COMMENT (158, 407), (111, 35) */
COMMENT 'print "TRUE"';
/* CIF ANSWER (279, 369), (70, 23) */
(false):
ENDDECISION;
/* CIF DECISION (69, 457), (155, 50) */
DECISION hello in seqof(0,0)
/* CIF COMMENT (252, 458), (236, 53) */
COMMENT 'Check IN operator with
list substring - first element only
should go to branch TRUE';
/* CIF ANSWER (18, 518), (66, 33) */
(true):
/* CIF PROCEDURECALL (-49, 566), (201, 35) */
CALL writeln(hello in seqof(0,1))
/* CIF COMMENT (172, 566), (111, 35) */
COMMENT 'print "TRUE"';
/* CIF ANSWER (296, 519), (70, 23) */
(false):
ENDDECISION;
/* CIF PROCEDURECALL (51, 616), (190, 35) */
CALL writeln(variable_str(0,4))
/* CIF COMMENT (253, 589), (113, 35) */
COMMENT 'print "Hello"';
/* CIF TASK (58, 666), (176, 53) */
TASK for x in seqof:
call writeln(num(x));
endfor
/* CIF COMMENT (252, 646), (96, 53) */
COMMENT 'print:
12
13';
/* CIF TASK (57, 734), (178, 53) */
TASK for x in seqof(0,1):
call writeln(-num(x));
endfor
/* CIF COMMENT (253, 707), (96, 53) */
COMMENT 'print:
-12
-13';
/* CIF PROCEDURECALL (56, 802), (180, 35) */
CALL writeln(length(seqof))
/* CIF COMMENT (256, 790), (77, 35) */
COMMENT 'print 2';
/* CIF PROCEDURECALL (42, 852), (209, 35) */
CALL writeln(length(seqof(0,1)))
/* CIF COMMENT (271, 840), (77, 35) */
COMMENT 'print 2';
/* CIF LABEL (65, 902), (162, 35) */
variable_length_seq:
/* CIF TASK (75, 952), (142, 53) */
TASK for x in seqint:
call writeln(x);
endfor
/* CIF COMMENT (237, 925), (96, 53) */
COMMENT 'print:
1';
/* CIF TASK (71, 1020), (150, 53) */
TASK for x in seqint(0,0):
call writeln(x);
endfor
/* CIF COMMENT (241, 993), (96, 53) */
COMMENT 'print:
1';
/* CIF DECISION (85, 1088), (123, 50) */
DECISION 1 in seqint
/* CIF COMMENT (227, 1066), (179, 53) */
COMMENT 'Check IN operator with
variable-length seqOf';
/* CIF ANSWER (17, 1158), (66, 33) */
(true):
/* CIF PROCEDURECALL (-38, 1206), (177, 35) */
CALL writeln(1 in seqint)
/* CIF COMMENT (159, 1206), (111, 35) */
COMMENT 'print "TRUE"';
/* CIF ANSWER (277, 1158), (70, 23) */
(false):
ENDDECISION;
/* CIF DECISION (83, 1256), (126, 50) */
DECISION 1 in seqint(0,0)
/* CIF COMMENT (228, 1234), (179, 53) */
COMMENT 'Check IN operator with
variable-length seqOf';
/* CIF ANSWER (15, 1326), (70, 23) */
(true):
/* CIF PROCEDURECALL (-39, 1364), (179, 35) */
CALL writeln(1 in seqint(0,0))
/* CIF COMMENT (160, 1364), (111, 35) */
COMMENT 'print "TRUE"';
/* CIF ANSWER (278, 1326), (70, 23) */
(false):
ENDDECISION;
/* CIF PROCEDURECALL (56, 1414), (180, 35) */
CALL writeln(length(seqint))
/* CIF COMMENT (256, 1402), (77, 35) */
COMMENT 'print 1';
/* CIF PROCEDURECALL (40, 1464), (212, 35) */
CALL writeln(length(seqint(0,0)))
/* CIF COMMENT (272, 1452), (77, 35) */
COMMENT 'print 1';
/* CIF TASK (66, 1514), (161, 35) */
TASK seqint := seqint // {2};
/* CIF TASK (53, 1564), (186, 35) */
TASK seqint := seqint(0,0) // {5};
/* CIF TASK (75, 1614), (142, 53) */
TASK for x in seqint:
call writeln(x);
endfor
/* CIF COMMENT (239, 1611), (96, 53) */
COMMENT 'print:
1
5';
/* CIF NEXTSTATE (114, 1682), (65, 33) */
NEXTSTATE Wait;
/* CIF STATE (418, 313), (70, 35) */
STATE wait;
ENDSTATE;
ENDPROCESS myfunction;
\ No newline at end of file
/* CIF Keep Specific Geode ASNFilename 'dataview-uniq.asn' */
USE Datamodel;
SYSTEM myfunction;
/* CIF Keep Specific Geode PARAMNAMES tutu */
SIGNAL start_something (T_Int32);
/* CIF Keep Specific Geode PARAMNAMES titi */
SIGNAL result_data (T_Int32);
CHANNEL c
FROM ENV TO myfunction WITH start_something;
FROM myfunction TO ENV WITH result_data;
ENDCHANNEL;
BLOCK myfunction;
SIGNALROUTE r
FROM ENV TO myfunction WITH start_something;
FROM myfunction TO ENV WITH result_data;
CONNECT c and r;
PROCESS myfunction REFERENCED;
ENDBLOCK;
ENDSYSTEM;
\ No newline at end of file
#include <math.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include "dataview-uniq.h"
extern void adainit();
extern void myfunction_start_something(asn1SccT_Int32 *);
extern void myfunction_mytimer();
void myfunction_RI_result_data(long long *val)
{
printf("[C] result_data: %lld\n", *val);
}
int main()
{
asn1SccT_Int32 test = 5;
printf("[C Code] Running test\n");
adainit();
myfunction_start_something(&test);
return 0;
}
......@@ -20,6 +20,7 @@ paths = [
'regression/test11',
'regression/test12',
'regression/test13',
'regression/test-substrings',
]
......
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