FUNCTION simplify_generic_expression
(* SCHEMA mathematical_functions_schema; *)
FUNCTION simplify_generic_expression(expr : generic_expression) : maths_value;
FUNCTION restore_unary(expr : unary_generic_expression;
opnd : generic_expression) : generic_expression;
expr.operand := opnd;
RETURN (expr);
END_FUNCTION; -- restore_unary
FUNCTION restore_binary(expr : binary_generic_expression;
opd1, opd2 : generic_expression) : generic_expression;
expr.operands[1] := opd1;
expr.operands[2] := opd2;
RETURN (expr);
END_FUNCTION; -- restore_binary
FUNCTION restore_mulary(expr : multiple_arity_generic_expression;
ops : LIST OF generic_expression) : generic_expression;
expr.operands := ops;
RETURN (expr);
END_FUNCTION; -- restore_mulary
FUNCTION make_number_literal(nmb : NUMBER) : generic_literal;
IF 'INTEGER' IN TYPEOF (nmb) THEN RETURN (make_int_literal(nmb)); END_IF;
RETURN (make_real_literal(nmb));
END_FUNCTION; -- make_number_literal;
LOCAL
types : SET OF STRING := stripped_typeof (expr);
v1, v2 : maths_value;
vlist : LIST OF maths_value := [];
op1, op2 : generic_expression;
oplist : LIST OF generic_expression := [];
opnds : LIST [2:?] OF generic_expression;
n, m : INTEGER;
finfun : maths_function_select;
boo : BOOLEAN;
str : STRING;
nmb : NUMBER;
END_LOCAL;
-- Unwrap the elementary kinds of literals
IF 'INT_LITERAL' IN types THEN
RETURN (convert_to_maths_value (expr\int_literal.the_value));
END_IF;
IF 'REAL_LITERAL' IN types THEN
RETURN (convert_to_maths_value (expr\real_literal.the_value));
END_IF;
IF 'BOOLEAN_LITERAL' IN types THEN
RETURN (convert_to_maths_value (expr\boolean_literal.the_value));
END_IF;
IF 'STRING_LITERAL' IN types THEN
RETURN (convert_to_maths_value (expr\string_literal.the_value));
END_IF;
IF 'COMPLEX_NUMBER_LITERAL' IN types THEN
RETURN (expr); -- No simpler expression available
END_IF;
IF 'LOGICAL_LITERAL' IN types THEN
RETURN (convert_to_maths_value (expr\logical_literal.lit_value));
END_IF;
IF 'BINARY_LITERAL' IN types THEN
RETURN (convert_to_maths_value (expr\binary_literal.lit_value));
END_IF;
IF 'MATHS_ENUM_LITERAL' IN types THEN
RETURN (expr\maths_enum_literal.lit_value);
END_IF;
IF 'REAL_TUPLE_LITERAL' IN types THEN
RETURN (convert_to_maths_value (expr\real_tuple_literal.lit_value));
END_IF;
IF 'INTEGER_TUPLE_LITERAL' IN types THEN
RETURN (convert_to_maths_value (expr\integer_tuple_literal.lit_value));
END_IF;
IF 'ATOM_BASED_LITERAL' IN types THEN
RETURN (expr\atom_based_literal.lit_value);
END_IF;
IF 'MATHS_TUPLE_LITERAL' IN types THEN
RETURN (convert_to_maths_value (expr\maths_tuple_literal.lit_value));
END_IF;
-- Simplify one special class of literals
IF 'MATHS_SPACE' IN types THEN
RETURN (simplify_maths_space(expr));
END_IF;
-- Simplify one special kind of expression
IF 'FUNCTION_APPLICATION' IN types THEN
RETURN (simplify_function_application(expr));
END_IF;
-- Separate and simplify the operands
IF 'UNARY_GENERIC_EXPRESSION' IN types THEN
v1 := simplify_generic_expression(expr\unary_generic_expression.operand);
op1 := convert_to_operand(v1);
END_IF;
IF 'BINARY_GENERIC_EXPRESSION' IN types THEN
v1 := simplify_generic_expression(expr\binary_generic_expression.operands[1]);
op1 := convert_to_operand(v1);
v2 := simplify_generic_expression(expr\binary_generic_expression.operands[2]);
op2 := convert_to_operand(v2);
END_IF;
IF 'MULTIPLE_ARITY_GENERIC_EXPRESSION' IN types THEN
opnds := expr\multiple_arity_generic_expression.operands;
REPEAT i := 1 TO SIZEOF (opnds);
v1 := simplify_generic_expression(opnds[i]);
INSERT (vlist, v1, i-1);
INSERT (oplist, convert_to_operand(v1), i-1);
END_REPEAT;
END_IF;
-- Simplify the one kind of maths_function which derives its operands.
IF 'PARALLEL_COMPOSED_FUNCTION' IN types THEN
v1 := vlist[1];
n := SIZEOF (vlist);
finfun := vlist[n];
REMOVE (vlist, n);
REMOVE (vlist, 1);
RETURN (make_parallel_composed_function(v1,vlist,finfun));
END_IF;
-- Simplify individual kinds of expressions. It is not necessary to cover all cases.
IF ('ABS_EXPRESSION' IN types) AND ('NUMBER' IN TYPEOF (v1)) THEN
RETURN (convert_to_maths_value (ABS(v1)));
END_IF;
IF ('ACOS_EXPRESSION' IN types) AND ('NUMBER' IN TYPEOF (v1)) THEN
RETURN (convert_to_maths_value (ACOS(v1)));
END_IF;
IF 'AND_EXPRESSION' IN types THEN
REPEAT i := SIZEOF (vlist) TO 1 BY -1;
IF 'BOOLEAN' IN TYPEOF (vlist[i]) THEN
boo := vlist[i];
IF NOT boo THEN RETURN (convert_to_maths_value(FALSE)); END_IF;
REMOVE (oplist, i);
END_IF;
END_REPEAT;
IF SIZEOF (oplist) = 0 THEN RETURN (convert_to_maths_value(TRUE)); END_IF;
IF SIZEOF (oplist) = 1 THEN RETURN (oplist[1]); END_IF;
END_IF;
IF ('ASIN_EXPRESSION' IN types) AND ('NUMBER' IN TYPEOF (v1)) THEN
RETURN (convert_to_maths_value (ASIN(v1)));
END_IF;
IF ('ATAN_EXPRESSION' IN types) AND
('NUMBER' IN TYPEOF (v1)) AND ('NUMBER' IN TYPEOF (v2)) THEN
RETURN (convert_to_maths_value (ATAN(v1,v2)));
END_IF;
IF ('COMPARISON_EXPRESSION' IN types) AND (
(('NUMBER' IN TYPEOF (v1)) AND ('NUMBER' IN TYPEOF (v2))) OR
(('STRING' IN TYPEOF (v1)) AND ('STRING' IN TYPEOF (v2))) OR
(('BOOLEAN' IN TYPEOF (v1)) AND ('BOOLEAN' IN TYPEOF (v2))) ) THEN
IF 'COMPARISON_EQUAL' IN types THEN boo := bool(v1 = v2);
ELSE IF 'COMPARISON_GREATER' IN types THEN boo := bool(v1 > v2);
ELSE IF 'COMPARISON_GREATER_EQUAL' IN types THEN boo := bool(v1 >= v2);
ELSE IF 'COMPARISON_LESS' IN types THEN boo := bool(v1 < v2);
ELSE IF 'COMPARISON_LESS_EQUAL' IN types THEN boo := bool(v1 <= v2);
ELSE IF 'COMPARISON_NOT_EQUAL' IN types THEN boo := bool(v1 <> v2);
ELSE IF 'LIKE_EXPRESSION' IN types THEN boo := bool(v1 LIKE v2);
ELSE RETURN (?); -- Unreachable
END_IF; END_IF; END_IF; END_IF; END_IF; END_IF; END_IF;
RETURN (convert_to_maths_value (boo));
END_IF;
IF 'CONCAT_EXPRESSION' IN types THEN
str := '';
REPEAT i := SIZEOF (vlist) TO 1 BY -1;
IF 'STRING' IN TYPEOF (vlist[i]) THEN
str := vlist[i] + str;
REMOVE (oplist, i);
ELSE IF LENGTH(str) > 0 THEN
INSERT (oplist, make_string_literal(str), i);
str := '';
END_IF; END_IF;
END_REPEAT;
IF SIZEOF (oplist) = 0 THEN RETURN (convert_to_maths_value(str)); END_IF;
IF LENGTH(str) > 0 THEN INSERT (oplist, make_string_literal(str), 0); END_IF;
IF SIZEOF (oplist) = 1 THEN RETURN (oplist[1]); END_IF;
END_IF;
IF ('COS_EXPRESSION' IN types) AND ('NUMBER' IN TYPEOF (v1)) THEN
RETURN (convert_to_maths_value (COS(v1)));
END_IF;
IF ('DIV_EXPRESSION' IN types) AND
('NUMBER' IN TYPEOF (v1)) AND ('NUMBER' IN TYPEOF (v2)) THEN
RETURN (convert_to_maths_value (v1 DIV v2));
END_IF;
IF 'EQUALS_EXPRESSION' IN types THEN
opnds := expr\binary_generic_expression.operands;
RETURN (convert_to_maths_value (opnds[1] :=: opnds[2]));
END_IF;
IF ('EXP_EXPRESSION' IN types) AND ('NUMBER' IN TYPEOF (v1)) THEN
RETURN (convert_to_maths_value (EXP(v1)));
END_IF;
IF ('FORMAT_EXPRESSION' IN types) AND
('NUMBER' IN TYPEOF (v1)) AND ('STRING' IN TYPEOF (v2)) THEN
RETURN (convert_to_maths_value (FORMAT(v1,v2)));
END_IF;
IF ('INDEX_EXPRESSION' IN types) AND
('STRING' IN TYPEOF (v1)) AND ('NUMBER' IN TYPEOF (v2)) THEN
str := v1; n := v2;
RETURN (convert_to_maths_value (str[n]));
END_IF;
IF ('INT_VALUE_EXPRESSION' IN types) AND ('STRING' IN TYPEOF (v1)) THEN
RETURN (convert_to_maths_value (VALUE(v1)));
END_IF;
IF 'INTERVAL_EXPRESSION' IN types THEN
str := '';
IF 'NUMBER' IN TYPEOF (vlist[1]) THEN str := 'NUMBER'; END_IF;
IF 'STRING' IN TYPEOF (vlist[1]) THEN str := 'STRING'; END_IF;
IF 'BOOLEAN' IN TYPEOF (vlist[1]) THEN str := 'BOOLEAN'; END_IF;
IF (LENGTH (str) > 0) AND (str IN TYPEOF (vlist[2])) AND
(str IN TYPEOF (vlist[3])) THEN
RETURN (convert_to_maths_value ({vlist[1] <= vlist[2] <= vlist[3]}));
END_IF;
END_IF;
IF ('LENGTH_EXPRESSION' IN types) AND ('STRING' IN TYPEOF (v1)) THEN
RETURN (convert_to_maths_value (LENGTH(v1)));
END_IF;
IF ('LOG_EXPRESSION' IN types) AND ('NUMBER' IN TYPEOF (v1)) THEN
RETURN (convert_to_maths_value (LOG(v1)));
END_IF;
IF ('LOG10_EXPRESSION' IN types) AND ('NUMBER' IN TYPEOF (v1)) THEN
RETURN (convert_to_maths_value (LOG10(v1)));
END_IF;
IF ('LOG2_EXPRESSION' IN types) AND ('NUMBER' IN TYPEOF (v1)) THEN
RETURN (convert_to_maths_value (LOG2(v1)));
END_IF;
IF 'MAXIMUM_EXPRESSION' IN types THEN
boo := FALSE;
REPEAT i := SIZEOF (vlist) TO 1 BY -1;
IF 'NUMBER' IN TYPEOF (vlist[i]) THEN
IF boo THEN
IF nmb < vlist[i] THEN nmb := vlist[i]; END_IF;
ELSE
nmb := vlist[i]; boo := TRUE;
END_IF;
REMOVE (oplist, i);
END_IF;
END_REPEAT;
IF SIZEOF (oplist) = 0 THEN RETURN (convert_to_maths_value(nmb)); END_IF;
IF boo THEN INSERT (oplist, make_number_literal(nmb), 0); END_IF;
END_IF;
IF 'MINIMUM_EXPRESSION' IN types THEN
boo := FALSE;
REPEAT i := SIZEOF (vlist) TO 1 BY -1;
IF 'NUMBER' IN TYPEOF (vlist[i]) THEN
IF boo THEN
IF nmb > vlist[i] THEN nmb := vlist[i]; END_IF;
ELSE
nmb := vlist[i]; boo := TRUE;
END_IF;
REMOVE (oplist, i);
END_IF;
END_REPEAT;
IF SIZEOF (oplist) = 0 THEN RETURN (convert_to_maths_value(nmb)); END_IF;
IF boo THEN INSERT (oplist, make_number_literal(nmb), 0); END_IF;
END_IF;
IF ('MINUS_EXPRESSION' IN types) AND
('NUMBER' IN TYPEOF (v1)) AND ('NUMBER' IN TYPEOF (v2)) THEN
RETURN (convert_to_maths_value (v1 - v2));
END_IF;
IF ('MOD_EXPRESSION' IN types) AND
('NUMBER' IN TYPEOF (v1)) AND ('NUMBER' IN TYPEOF (v2)) THEN
RETURN (convert_to_maths_value (v1 MOD v2));
END_IF;
IF 'MULT_EXPRESSION' IN types THEN
nmb := 1;
REPEAT i := SIZEOF (vlist) TO 1 BY -1;
IF 'NUMBER' IN TYPEOF (vlist[i]) THEN
nmb := nmb * vlist[i];
REMOVE (oplist, i);
END_IF;
END_REPEAT;
IF SIZEOF (oplist) = 0 THEN RETURN (convert_to_maths_value(nmb)); END_IF;
IF nmb <> 1 THEN INSERT (oplist, make_number_literal(nmb), 0); END_IF;
IF SIZEOF (oplist) = 1 THEN RETURN (oplist[1]); END_IF;
END_IF;
IF ('NOT_EXPRESSION' IN types) AND ('BOOLEAN' IN TYPEOF (v1)) THEN
boo := v1;
RETURN (convert_to_maths_value (NOT(boo)));
END_IF;
IF ('ODD_EXPRESSION' IN types) AND ('INTEGER' IN TYPEOF (v1)) THEN
RETURN (convert_to_maths_value (ODD(v1)));
END_IF;
IF 'OR_EXPRESSION' IN types THEN
REPEAT i := SIZEOF (vlist) TO 1 BY -1;
IF 'BOOLEAN' IN TYPEOF (vlist[i]) THEN
boo := vlist[i];
IF boo THEN RETURN (convert_to_maths_value(TRUE)); END_IF;
REMOVE (oplist, i);
END_IF;
END_REPEAT;
IF SIZEOF (oplist) = 0 THEN RETURN (convert_to_maths_value(FALSE)); END_IF;
IF SIZEOF (oplist) = 1 THEN RETURN (oplist[1]); END_IF;
END_IF;
IF 'PLUS_EXPRESSION' IN types THEN
nmb := 0;
REPEAT i := SIZEOF (vlist) TO 1 BY -1;
IF 'NUMBER' IN TYPEOF (vlist[i]) THEN
nmb := nmb + vlist[i];
REMOVE (oplist, i);
END_IF;
END_REPEAT;
IF SIZEOF (oplist) = 0 THEN RETURN (convert_to_maths_value(nmb)); END_IF;
IF nmb <> 0 THEN INSERT (oplist, make_number_literal(nmb), 0); END_IF;
IF SIZEOF (oplist) = 1 THEN RETURN (oplist[1]); END_IF;
END_IF;
IF ('POWER_EXPRESSION' IN types) AND
('NUMBER' IN TYPEOF (v1)) AND ('NUMBER' IN TYPEOF (v2)) THEN
RETURN (convert_to_maths_value (v1 ** v2));
END_IF;
IF ('SIN_EXPRESSION' IN types) AND ('NUMBER' IN TYPEOF (v1)) THEN
RETURN (convert_to_maths_value (SIN(v1)));
END_IF;
IF ('SLASH_EXPRESSION' IN types) AND
('NUMBER' IN TYPEOF (v1)) AND ('NUMBER' IN TYPEOF (v2)) THEN
RETURN (convert_to_maths_value (v1 / v2));
END_IF;
IF ('SQUARE_ROOT_EXPRESSION' IN types) AND ('NUMBER' IN TYPEOF (v1)) THEN
RETURN (convert_to_maths_value (SQRT(v1)));
END_IF;
IF ('SUBSTRING_EXPRESSION' IN types) AND
('STRING' IN TYPEOF (vlist[1])) AND ('NUMBER' IN TYPEOF (vlist[2])) AND
('NUMBER' IN TYPEOF (vlist[3])) THEN
str := vlist[1]; n := vlist[2]; m := vlist[3];
RETURN (convert_to_maths_value (str[n:m]));
END_IF;
IF ('TAN_EXPRESSION' IN types) AND ('NUMBER' IN TYPEOF (v1)) THEN
RETURN (convert_to_maths_value (TAN(v1)));
END_IF;
IF ('UNARY_MINUS_EXPRESSION' IN types) AND ('NUMBER' IN TYPEOF (v1)) THEN
nmb := v1;
RETURN (convert_to_maths_value (-nmb));
END_IF;
IF ('VALUE_EXPRESSION' IN types) AND ('STRING' IN TYPEOF (v1)) THEN
RETURN (convert_to_maths_value (VALUE(v1)));
END_IF;
IF ('XOR_EXPRESSION' IN types) AND
('BOOLEAN' IN TYPEOF (v1)) AND ('BOOLEAN' IN TYPEOF (v2)) THEN
RETURN (convert_to_maths_value (v1 XOR v2));
END_IF;
-- No special simplification defined, return same with simplified operands.
IF 'UNARY_GENERIC_EXPRESSION' IN types THEN
RETURN (restore_unary(expr,op1));
END_IF;
IF 'BINARY_GENERIC_EXPRESSION' IN types THEN
RETURN (restore_binary(expr,op1,op2));
END_IF;
IF 'MULTIPLE_ARITY_GENERIC_EXPRESSION' IN types THEN
RETURN (restore_mulary(expr,oplist));
END_IF;
-- Should be unreachable, but for safety, return unsimplified expression.
RETURN (expr);
END_FUNCTION; -- simplify_generic_expression
Referenced By
Defintion simplify_generic_expression is references by the following definitions:
[Top Level Definitions] [Exit]Generated by STEP Tools® EXPRESS to HTML Converter
2012-03-27T17:13:59-04:00