Commit 5acdf98e authored by Maxime Perrotin's avatar Maxime Perrotin
Browse files

Added support for sdl operators fix, float, and power

parent 1ea3a2bb
......@@ -731,6 +731,15 @@ def _prim_path(primary_id):
elif pr_id.lower() == 'abs':
special_op = 'Abs'
continue
elif pr_id.lower() == 'fix':
special_op = 'CastInt'
continue
elif pr_id.lower() == 'float':
special_op = 'CastReal'
continue
elif pr_id.lower() == 'power':
special_op = 'Power'
continue
special_op = ''
parent_kind, parent_typename = path_type(sub_id)
sub_id.append(pr_id)
......@@ -784,20 +793,26 @@ def _prim_path(primary_id):
stmts.extend(idx_stmts)
local_decl.extend(local_var)
elif 'procParams' in pr_id:
if special_op == 'Abs':
if special_op in ('Abs', 'CastInt', 'CastReal'):
# Return absolute value of a number
exp, = pr_id['procParams']
exp_type = find_basic_type(exp.exprType)
if exp_type.kind not in ('IntegerType', 'RealType'):
error = ('{} must be a number to return absolute value'
.format(exp.inputString))
LOG.error(error)
raise TypeError(error)
param_stmts, param_str, local_var = expression(exp)
stmts.extend(param_stmts)
local_decl.extend(local_var)
ada_string += 'abs(' + param_str + ')'
ada_string += '{op}({param})'.format(
param=param_str,
op='abs' if special_op == 'Abs' else
'Interfaces.Integer_64' if special_op == 'CastInt'
else 'adaasn1rtl.Asn1Real'
if special_op == 'CastReal' else 'ERROR')
elif special_op == 'Power':
operands = [None, None]
for idx, param in enumerate(pr_id['procParams']):
stmt, operands[idx], local = expression(param)
stmts.extend(stmt)
local_decl.extend(local)
ada_string += '{op[0]} ** Natural({op[1]})'.format(
op=operands)
elif special_op == 'Length':
# Length of sequence of: take only the first parameter
exp, = pr_id['procParams']
......
......@@ -3,6 +3,10 @@ all: compile-all
regression:
make -C tests/regression all
flake8:
@echo Generating flake8_report file
flake8 opengeode.py sdlSymbols.py genericSymbols.py ogParser.py AdaGenerator.py Renderer.py Clipboard.py Lander.py ogAST.py undoCommands.py Connectors.py Asn1scc.py Helper.py Statechart.py >flake8_report
coverage:
make -C tests/regression coverage
......
......@@ -94,7 +94,10 @@ SPECIAL_OPERATORS = {'length': [LIST],
'present': [CHOICE],
'set_timer': [INTEGER, TIMER],
'reset_timer': [TIMER],
'abs': [NUMERICAL]}
'abs': [NUMERICAL],
'float': [NUMERICAL],
'fix': [NUMERICAL],
'power': [NUMERICAL, INTEGER]}
# Container to keep a list of types mapped from ANTLR Tokens
# (Used with singledispatch/visitor pattern)
......@@ -292,7 +295,7 @@ def is_constant(var):
def fix_special_operators(op_name, expr_list, context):
''' Verify/fix type of special operators parameters '''
if op_name.lower() in ('length', 'present', 'abs'):
if op_name.lower() in ('length', 'present', 'abs', 'float', 'fix'):
if len(expr_list) != 1:
raise AttributeError('Only one parameter for the {} operator'
.format(op_name))
......@@ -307,6 +310,25 @@ def fix_special_operators(op_name, expr_list, context):
raise TypeError('Length operator works only on strings/lists')
elif op_name.lower() == 'present' and basic.kind != 'ChoiceType':
raise TypeError('Present operator works only on CHOICE types')
elif op_name.lower() in ('abs', 'float', 'fix') and not basic.kind in (
'IntegerType', 'Integer32Type', 'RealType', 'NumericalType'):
raise TypeError('"{}" operator needs a numerical parameter'.format(
op_name))
elif op_name.lower() == 'power':
if len(expr_list) != 2:
raise AttributeError('The "power" operator takes two parameters')
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
# XXX should change type to PrimVariable
if idx == 0 and not find_basic_type(expr.exprType).kind in (
'IntegerType', 'Integer32Type', 'Numerical', 'RealType'):
raise TypeError('First parameter of power must be numerical')
elif idx == 1 and not find_basic_type(expr.exprType).kind in (
'IntegerType', 'Integer32Type'):
raise TypeError('Second parameter of power must be integer')
elif op_name.lower() in ('write', 'writeln'):
for param in expr_list:
if param.exprType is UNKNOWN_TYPE:
......@@ -695,10 +717,20 @@ def find_type(path, context):
' must be a CHOICE type:' + str(path))
else:
result.EnumValues = param_type.Children
elif main.lower() in ('length', 'abs'):
elif main.lower() in ('length', 'abs', 'fix'):
# XXX length et abs: we must set Min and Max
# and abs may return a RealType, not always integer
result = type('lenabs', (object,), {'kind': 'IntegerType'})
result = INTEGER
# type('lenabs', (object,), {'kind': 'IntegerType'})
elif main.lower() == 'float':
result = REAL
elif main.lower() == 'power':
# Result can be int or real, depending on first param
param = path[1].get('procParams')[0]
check_type = find_variable(param.inputString, context) \
if param.exprType == UNKNOWN_TYPE else \
param.exprType
result = find_basic_type(check_type)
else: # write and writeln return void
pass
if result.kind == 'ReferenceType':
......
......@@ -26,6 +26,7 @@ import pprint
from functools import partial
from collections import deque
from itertools import chain
import stringtemplate3
# Added to please py2exe - NOQA makes flake8 ignore the following lines:
# pylint: disable=W0611
......@@ -1726,7 +1727,9 @@ def opengeode():
handler_console.setFormatter(terminal_formatter)
LOG.addHandler(handler_console)
app = QtGui.QApplication(sys.argv)
app = QtGui.QApplication.instance()
if app is None:
app = QtGui.QApplication(sys.argv)
app.setApplicationName('OpenGEODE')
app.setWindowIcon(QtGui.QIcon(':icons/input.png'))
......
/* CIF PROCESS (150, 150), (150, 75) */
PROCESS myfunction;
/* CIF TEXT (-336, -82), (271, 250) */
/* CIF TEXT (-336, -82), (271, 263) */
-- Timers defined in the interface view
-- Use SET_TIMER (value, timer name)
-- and RESET_TIMER (timer name) in a
......@@ -13,6 +14,10 @@ TIMER myTimer;
-- Test default value for a complex type
DCL def_val MySeq := { a 3, b taste };
-- To test power, fix, float
dcl someReal MyReal := 1.5;
dcl someInt MyInteger := 2;
/* CIF ENDTEXT */
/* CIF START (58, -99), (100, 50) */
START;
......@@ -33,14 +38,24 @@ CALL writeln
/* CIF PROCEDURECALL (-38, 231), (132, 50) */
CALL set_timer
(1000, myTimer);
/* CIF NEXTSTATE (-23, 296), (102, 50) */
/* CIF TASK (-113, 296), (282, 35) */
TASK someReal := power(someReal, someInt);
/* CIF PROCEDURECALL (-142, 346), (340, 35) */
CALL writeln('1.5 ** 2 == ', someReal, ' (should be 2.25 )');
/* CIF TASK (-65, 396), (186, 35) */
TASK someInt := fix(someReal);
/* CIF TASK (-73, 446), (201, 35) */
TASK someReal := float(someInt);
/* CIF TASK (-86, 496), (227, 35) */
TASK someInt := fix(someReal) mod 5;
/* CIF NEXTSTATE (-23, 546), (102, 50) */
NEXTSTATE wait;
/* CIF INPUT (137, 36), (100, 50) */
/* CIF INPUT (225, 36), (100, 50) */
INPUT mytimer;
/* CIF PROCEDURECALL (119, 101), (135, 50) */
/* CIF PROCEDURECALL (207, 101), (135, 50) */
CALL writeln
('timer expired');
/* CIF NEXTSTATE (137, 166), (100, 50) */
/* CIF NEXTSTATE (225, 166), (100, 50) */
NEXTSTATE Wait;
ENDSTATE;
ENDPROCESS myfunction;
\ No newline at end of file
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