Commit fde0cc9d authored by dbarbera's avatar dbarbera
Browse files

Merge remote-tracking branch 'upstream/master' into llvm

Conflicts:
	tests/regression/test-substrings/Makefile
parents 099a8918 f37272a2
......@@ -1024,20 +1024,20 @@ def _append(expr):
# If right or left is raw, declare a temporary variable for it, too
for sexp, sid in zip((expr.right, expr.left), (right_str, left_str)):
if sexp.is_raw:
local_decl.append('tmp{idx} : aliased asn1Scc{eType};'.format(
local_decl.append(u'tmp{idx} : aliased asn1Scc{eType};'.format(
idx=sexp.tmpVar,
eType=sexp.exprType.ReferencedTypeName
.replace('-', '_')))
stmts.append('tmp{idx} := {s_id};'.format(
stmts.append(u'tmp{idx} := {s_id};'.format(
idx=sexp.tmpVar, s_id=sid))
sexp.sid = 'tmp' + str(sexp.tmpVar)
sexp.sid = u'tmp' + unicode(sexp.tmpVar)
# Length of raw string - update for sequence of
if isinstance(sexp, ogAST.PrimStringLiteral):
sexp.slen = len(sexp.value[1:-1])
sexp.slen = unicode(len(sexp.value[1:-1]))
elif isinstance(sexp, ogAST.PrimEmptyString):
sexp.slen = 0
sexp.slen = u'0'
elif isinstance(sexp, ogAST.PrimSequenceOf):
sexp.slen = len(sexp.value)
sexp.slen = unicode(len(sexp.value))
else:
raise TypeError('Not a string/Sequence in APPEND')
else:
......@@ -1045,7 +1045,7 @@ def _append(expr):
basic = find_basic_type(sexp.exprType)
if basic.Min == basic.Max:
# Fixed-size string
sexp.slen = basic.Max
sexp.slen = unicode(basic.Max)
else:
# Variable-size types have a Length field
if isinstance(sexp, ogAST.PrimSubstring):
......@@ -1058,8 +1058,8 @@ def _append(expr):
and unicode.isnumeric(expr.right.slen):
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};'
length = u'{} + {}'.format(expr.left.slen, expr.right.slen)
stmts.append(u'{res}.Data(1 .. {length}) := {lid} & {rid};'
.format(length=length,
res=ada_string,
lid=left_payload,
......@@ -1067,7 +1067,7 @@ def _append(expr):
basic_tmp = find_basic_type(expr.exprType)
if basic_tmp.Min != basic_tmp.Max:
# Update lenght field of resulting variable (if variable size)
stmts.append('{}.Length := {};'.format(ada_string, length))
stmts.append(u'{}.Length := {};'.format(ada_string, length))
return stmts, unicode(ada_string), local_decl
......
......@@ -32,7 +32,8 @@ import re
import fnmatch
import logging
import traceback
from itertools import chain, permutations
from itertools import chain, permutations, combinations
from collections import defaultdict
import antlr3
import antlr3.tree
......@@ -2956,7 +2957,8 @@ def decision(root, parent, context):
warnings.append(['Unsupported DECISION child type: ' +
str(child.type), [dec.pos_x, dec.pos_y]])
# Make type checks to be sure that question and answers are compatible
covered_ranges = []
covered_ranges = defaultdict(list)
qmin, qmax = 0, 0
need_else = False
for ans in dec.answers:
if ans.kind in ('constant', 'open_range'):
......@@ -2977,54 +2979,54 @@ def decision(root, parent, context):
# Not a constant or a raw number, range is not fix
need_else = True
continue
val_a = int(a_basic.Min)
val_a = int(float(a_basic.Min))
qmin, qmax = int(float(q_basic.Min)), int(float(q_basic.Max))
# Check the operator to compute the range
reachable = True
if ans.openRangeOp == ogAST.ExprLe:
if qmin <= val_a:
covered_ranges.append([qmin, val_a])
covered_ranges[ans].append((qmin, val_a))
else:
warnings.append('Unreachable branch - '
+ ans.inputString)
reachable = False
elif ans.openRangeOp == ogAST.ExprLt:
if qmin < val_a:
covered_ranges.append([qmin, val_a - 1])
covered_ranges[ans].append((qmin, val_a - 1))
else:
warnings.append('Unreachable branch - '
+ ans.inputString)
reachable = False
elif ans.openRangeOp == ogAST.ExprGt:
if qmax > val_a:
covered_ranges.append([val_a + 1, qmax])
covered_ranges[ans].append((val_a + 1, qmax))
else:
warnings.append('Unreachable branch - '
+ ans.inputString)
reachable = False
elif ans.openRangeOp == ogAST.ExprGe:
if qmax >= val_a:
covered_ranges.append([val_a, qmax])
covered_ranges[ans].append((val_a, qmax))
else:
warnings.append('Unreachable branch - '
+ ans.inputString)
reachable = False
elif ans.openRangeOp == ogAST.ExprEq:
if qmin <= val_a <= qmax:
covered_ranges.append([val_a, val_a])
covered_ranges[ans].append((val_a, val_a))
else:
warnings.append('Unreachable branch - '
+ ans.inputString)
reachable = False
elif ans.openRangeOp == ogAST.ExprNeq:
if qmin == val_a:
covered_ranges.append([qmin + 1, qmax])
covered_ranges[ans].append((qmin + 1, qmax))
elif qmax == val_a:
covered_ranges.append([qmin, qmax - 1])
elif q_basic.Min < a_basic.Max < q_basic.Max:
covered_ranges.append([q_basic.Min, a_basic.Max - 1])
covered_ranges.append([a_basic.Max + 1, q_basic.Max])
covered_ranges[ans].append((qmin, qmax - 1))
elif qmin < val_a < qmax:
covered_ranges[ans].append((qmin, val_a - 1))
covered_ranges[ans].append((val_a + 1, qmax))
else:
warnings.append('Condition is always true: {} /= {}'
.format(dec.inputString,
ans.inputString))
else:
warnings.append('Unsupported range expression')
print 'RANGE OF QUESTION: [{} .. {}]'.format(qmin, qmax)
if not reachable:
warnings.append('Decision "{}": '
'Unreachable branch "{}"'
.format(dec.inputString,
ans.inputString))
except (AttributeError, TypeError) as err:
errors.append('Types are incompatible in DECISION: '
'question (' + expr.left.inputString + ', type= ' +
......@@ -3060,12 +3062,77 @@ def decision(root, parent, context):
# Not a constant or a raw number, range is not fix
need_else = True
continue
covered_ranges.append([int(float(a0_basic.Min)),
int(float(a1_basic.Max))])
for each in covered_ranges:
print each
if need_else and not has_else:
warnings.append('Missing ELSE branch in decision')
qmin, qmax = int(float(q_basic.Min)), int(float(q_basic.Max))
a0_val = int(float(a0_basic.Min))
a1_val = int(float(a1_basic.Max))
if a0_val < qmin:
warnings.append('Decision "{dec}": '
'Range [{a0} .. {qmin}] is unreachable'
.format(a0=a0_val, qmin=qmin - 1,
dec=dec.inputString))
if a1_val > qmax:
warnings.append('Decision "{dec}": '
'Range [{qmax} .. {a1}] is unreachable'
.format(qmax=qmax + 1, a1=a1_val,
dec=dec.inputString))
if (a0_val < qmin and a1_val < qmin) or (a0_val > qmax and
a1_val > qmax):
warnings.append('Decision "{dec}": Unreachable branch {l}:{h}'
.format(dec=dec.inputString,
l=a0_val, h=a1_val))
covered_ranges[ans].append((int(float(a0_basic.Min)),
int(float(a1_basic.Max))))
# Check the following:
# (1) no overlap between covered ranges in decision answers
# (2) no gap in the coverage of the decision possible values
# (3) ELSE branch, if present, can be reached
# (4) if an answer uses a non-ground expression an ELSE is there
q_ranges = [(qmin, qmax)] if is_numeric(dec.question.exprType) else []
for each in combinations(covered_ranges.viewitems(), 2):
for comb in combinations(
chain.from_iterable(val[1] for val in each), 2):
comb_overlap = (max(comb[0][0], comb[1][0]),
min(comb[0][1], comb[1][1]))
if comb_overlap[0] <= comb_overlap[1]:
# (1) - check for overlaps
errors.append('Decision "{d}": answers {a1} and {a2} '
'are overlapping in range [{o1} .. {o2}]'
.format(d=dec.inputString,
a1=each[0][0].inputString,
a2=each[1][0].inputString,
o1=comb_overlap[0],
o2=comb_overlap[1]))
new_q_ranges = []
# for minq, maxq in q_ranges:
# (2) Check that decision range is fully covered
for ans_ref, ranges in covered_ranges.viewitems():
for mina, maxa in ranges:
for minq, maxq in q_ranges:
left = (minq, min(maxq, mina - 1))
right = (max(minq, maxa + 1), maxq)
if mina > minq and maxa < maxq:
new_q_ranges.extend([left, right])
elif mina <= minq and maxa >= maxq:
pass
elif mina <= minq:
new_q_ranges.append(right)
elif maxa >= maxq:
new_q_ranges.append(left)
q_ranges, new_q_ranges = new_q_ranges, []
if not has_else:
for minq, maxq in q_ranges:
errors.append('Decision "{}": No answer to cover range [{} .. {}]'
.format(dec.inputString, minq, maxq))
elif has_else and is_numeric(dec.question.exprType) and not q_ranges:
# (3) Check that ELSE branch is reachable
warnings.append('Decision "{}": ELSE branch is unreachable'
.format(dec.inputString))
if need_else and not has_else:
# (4) Answers use non-ground expression -> there should be an ELSE
warnings.append('Decision "{}": Missing ELSE branch'
.format(dec.inputString))
return dec, errors, warnings
......
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 2>&1 | diff expected - || exit 0
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 testcase
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
SeqBool ::= SEQUENCE (SIZE(2)) OF BOOLEAN
SeqBool2 ::= SEQUENCE (SIZE(1..2)) OF BOOLEAN
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
[INFO] Checking ['myfunction.pr', 'system_structure.pr']
[INFO] Parsing complete. Summary, found 6 warnings and 6 errors
[WARNING] Decision "var2": Unreachable branch "<0"
[WARNING] Decision "var2": Unreachable branch ">300"
[WARNING] Decision "var2": Range [-10 .. -1] is unreachable
[WARNING] Decision "var2": Unreachable branch
[WARNING] Decision "var2": Range [256 .. 300] is unreachable
[WARNING] Decision "var2": Unreachable branch
[ERROR] Non-determinism in decision "var1": answers -500:500 and >0 are overlapping in range [1 .. 500]
[ERROR] Non-determinism in decision "var1": answers -500:500 and /=1 are overlapping in range [-500 .. 0]
[ERROR] Non-determinism in decision "var1": answers -500:500 and /=1 are overlapping in range [2 .. 500]
[ERROR] Non-determinism in decision "var1": answers -500:500 and =0 are overlapping in range [0 .. 0]
[ERROR] Non-determinism in decision "var1": answers >0 and /=1 are overlapping in range [2 .. 2147483647]
[ERROR] Non-determinism in decision "var1": answers /=1 and =0 are overlapping in range [0 .. 0]
[ERROR] Too many errors, cannot generate code
/* CIF PROCESS (200, 143), (150, 75) */
PROCESS myfunction;
/* CIF TEXT (0, 142), (282, 128) */
dcl var1 t_Int32 := 0;
dcl var2 t_uint8 := 0;
dcl var3 t_uInt8 := 0;
/* CIF ENDTEXT */
/* CIF TEXT (36, 43), (360, 41) */
-- Test the branch coverage checker in decision answers
/* CIF ENDTEXT */
/* CIF START (243, 292), (70, 35) */
START;
/* CIF DECISION (243, 342), (70, 50) */
DECISION var1
/* CIF COMMENT (333, 349), (191, 35) */
COMMENT 'Check range overlapping';
/* CIF ANSWER (96, 412), (90, 24) */
(-500:500):
/* CIF ANSWER (198, 412), (70, 24) */
(=0):
/* CIF ANSWER (288, 412), (70, 24) */
(/=1):
/* CIF ANSWER (378, 412), (70, 24) */
(>0):
ENDDECISION;
/* CIF DECISION (243, 470), (70, 50) */
DECISION var2
/* CIF COMMENT (333, 477), (241, 35) */
COMMENT 'Check unreachable branch check';
/* CIF ANSWER (115, 540), (53, 33) */
(<0):
/* CIF ANSWER (197, 540), (68, 33) */
(>300):
/* CIF ANSWER (286, 540), (72, 33) */
(-10:-5):
/* CIF ANSWER (369, 540), (86, 24) */
(256:300):
ENDDECISION;
/* CIF DECISION (242, 602), (71, 50) */
DECISION var3;
/* CIF ANSWER (196, 672), (71, 24) */
(10:20):
/* CIF ANSWER (288, 672), (70, 24) */
(/=50):
ENDDECISION;
/* CIF NEXTSTATE (243, 716), (70, 35) */
NEXTSTATE wait;
/* CIF STATE (868, 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
......@@ -35,3 +35,4 @@ coverage:
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 *.ll *.s testcase
......@@ -39,6 +39,8 @@ MyChoice ::= CHOICE {
MySeqOf ::= SEQUENCE (SIZE (2)) OF MyEnum
SeqInt ::= SEQUENCE (SIZE(1..2)) OF T-UInt8
SeqBool ::= SEQUENCE (SIZE(2)) OF BOOLEAN
SeqBool2 ::= SEQUENCE (SIZE(1..2)) OF BOOLEAN
MyOctStr ::= OCTET STRING (SIZE (3))
String ::= OCTET STRING (SIZE(0..100))
......
/* 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) */
/* CIF TEXT (0, 133), (282, 128) */
dcl str MyOctStr := 'abc';
dcl variable_str String := 'Hello!';
dcl seqof MySeqOf := {hello, world};
dcl seqint seqInt := {1};
dcl seqbool seqBool := { true, false};
dcl seqbool2 seqBool2 := { true, false};
/* CIF ENDTEXT */
/* CIF TEXT (7, 43), (327, 41) */
-- Test substrings in various contexts and operators
/* CIF ENDTEXT */
/* CIF PROCEDURE (1416, 490), (91, 35) */
PROCEDURE factorial;
......@@ -28,132 +30,138 @@ endfor;
/* CIF RETURN (315, 201), (35, 35) */
RETURN ;
ENDPROCEDURE;
/* CIF START (114, 247), (65, 37) */
/* CIF START (104, 273), (65, 37) */
START;
/* CIF DECISION (85, 299), (123, 50) */
/* CIF DECISION (75, 325), (123, 50) */
DECISION hello in seqof
/* CIF COMMENT (228, 300), (179, 53) */
/* CIF COMMENT (218, 326), (179, 53) */
COMMENT 'Check IN operator with
enumerated type';
/* CIF ANSWER (14, 369), (70, 23) */
/* CIF ANSWER (4, 395), (70, 23) */
(true):
/* CIF PROCEDURECALL (-39, 407), (177, 35) */
/* CIF PROCEDURECALL (-49, 433), (177, 35) */
CALL writeln(hello in seqof)
/* CIF COMMENT (158, 407), (111, 35) */
/* CIF COMMENT (148, 433), (111, 35) */
COMMENT 'print "TRUE"';
/* CIF ANSWER (279, 369), (70, 23) */
/* CIF ANSWER (269, 395), (70, 23) */
(false):
ENDDECISION;
/* CIF DECISION (69, 457), (155, 50) */
/* CIF DECISION (59, 483), (155, 50) */
DECISION hello in seqof(0,0)
/* CIF COMMENT (252, 458), (236, 53) */
/* CIF COMMENT (242, 466), (236, 53) */
COMMENT 'Check IN operator with
list substring - first element only
should go to branch TRUE';
/* CIF ANSWER (18, 518), (66, 33) */
/* CIF ANSWER (8, 526), (66, 33) */
(true):
/* CIF PROCEDURECALL (-49, 566), (201, 35) */
/* CIF PROCEDURECALL (-59, 574), (201, 35) */
CALL writeln(hello in seqof(0,1))
/* CIF COMMENT (172, 566), (111, 35) */
/* CIF COMMENT (162, 574), (111, 35) */
COMMENT 'print "TRUE"';
/* CIF ANSWER (296, 519), (70, 23) */
/* CIF ANSWER (286, 527), (70, 23) */
(false):
ENDDECISION;
/* CIF PROCEDURECALL (51, 616), (190, 35) */
/* CIF PROCEDURECALL (41, 624), (190, 35) */
CALL writeln(variable_str(0,4))
/* CIF COMMENT (253, 589), (113, 35) */
/* CIF COMMENT (243, 579), (113, 35) */
COMMENT 'print "Hello"';
/* CIF TASK (58, 666), (176, 53) */
/* CIF TASK (48, 674), (176, 53) */
TASK for x in seqof:
call writeln(num(x));
endfor
/* CIF COMMENT (252, 646), (96, 53) */
/* CIF COMMENT (242, 636), (96, 53) */
COMMENT 'print:
12
13';
/* CIF TASK (57, 734), (178, 53) */
/* CIF TASK (47, 742), (178, 53) */
TASK for x in seqof(0,1):
call writeln(-num(x));
endfor
/* CIF COMMENT (253, 707), (96, 53) */
/* CIF COMMENT (243, 697), (96, 53) */
COMMENT 'print:
-12
-13';
/* CIF PROCEDURECALL (56, 802), (180, 35) */
/* CIF PROCEDURECALL (46, 810), (180, 35) */
CALL writeln(length(seqof))
/* CIF COMMENT (256, 790), (77, 35) */
/* CIF COMMENT (246, 780), (77, 35) */
COMMENT 'print 2';
/* CIF PROCEDURECALL (42, 852), (209, 35) */
/* CIF PROCEDURECALL (32, 860), (209, 35) */
CALL writeln(length(seqof(0,1)))
/* CIF COMMENT (271, 840), (77, 35) */
/* CIF COMMENT (261, 830), (77, 35) */
COMMENT 'print 2';
/* CIF LABEL (65, 902), (162, 35) */
/* CIF LABEL (55, 910), (162, 35) */
variable_length_seq:
/* CIF TASK (75, 952), (142, 53) */
/* CIF TASK (65, 960), (142, 53) */
TASK for x in seqint:
call writeln(x);
endfor
/* CIF COMMENT (237, 925), (96, 53) */
/* CIF COMMENT (227, 915), (96, 53) */
COMMENT 'print:
1';
/* CIF TASK (71, 1020), (150, 53) */
/* CIF TASK (61, 1028), (150, 53) */
TASK for x in seqint(0,0):
call writeln(x);
endfor
/* CIF COMMENT (241, 993), (96, 53) */
/* CIF COMMENT (231, 983), (96, 53) */
COMMENT 'print:
1';
/* CIF DECISION (85, 1088), (123, 50) */
/* CIF DECISION (75, 1096), (123, 50) */
DECISION 1 in seqint
/* CIF COMMENT (227, 1066), (179, 53) */
/* CIF COMMENT (217, 1056), (179, 53) */
COMMENT 'Check IN operator with
variable-length seqOf';
/* CIF ANSWER (17, 1158), (66, 33) */
/* CIF ANSWER (7, 1148), (66, 33) */
(true):
/* CIF PROCEDURECALL (-38, 1206), (177, 35) */
/* CIF PROCEDURECALL (-48, 1196), (177, 35) */
CALL writeln(1 in seqint)
/* CIF COMMENT (159, 1206), (111, 35) */
/* CIF COMMENT (149, 1196), (111, 35) */
COMMENT 'print "TRUE"';
/* CIF ANSWER (277, 1158), (70, 23) */
/* CIF ANSWER (267, 1148), (70, 23) */
(false):
ENDDECISION;
/* CIF DECISION (83, 1256), (126, 50) */
/* CIF DECISION (73, 1246), (126, 50) */
DECISION 1 in seqint(0,0)
/* CIF COMMENT (228, 1234), (179, 53) */
/* CIF COMMENT (218, 1206), (179, 53) */
COMMENT 'Check IN operator with
variable-length seqOf';
/* CIF ANSWER (15, 1326), (70, 23) */
/* CIF ANSWER (5, 1298), (70, 23) */
(true):
/* CIF PROCEDURECALL (-39, 1364), (179, 35) */
/* CIF PROCEDURECALL (-49, 1336), (179, 35) */
CALL writeln(1 in seqint(0,0))
/* CIF COMMENT (160, 1364), (111, 35) */
/* CIF COMMENT (150, 1336), (111, 35) */
COMMENT 'print "TRUE"';
/* CIF ANSWER (278, 1326), (70, 23) */
/* CIF ANSWER (268, 1298), (70, 23) */
(false):
ENDDECISION;
/* CIF PROCEDURECALL (56, 1414), (180, 35) */
/* CIF PROCEDURECALL (46, 1386), (180, 35) */
CALL writeln(length(seqint))
/* CIF COMMENT (256, 1402), (77, 35) */
/* CIF COMMENT (246, 1356), (77, 35) */
COMMENT 'print 1';
/* CIF PROCEDURECALL (40, 1464), (212, 35) */
/* CIF PROCEDURECALL (30, 1436), (212, 35) */
CALL writeln(length(seqint(0,0)))
/* CIF COMMENT (272, 1452), (77, 35) */
/* CIF COMMENT (262, 1406), (77, 35) */
COMMENT 'print 1';
/* CIF TASK (66, 1514), (161, 35) */
/* CIF TASK (56, 1486), (161, 35) */