File size: 27,736 Bytes
985c397 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 | # SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2011-2012, Thomas Paviot (tpaviot@gmail.com)
# All rights reserved.
# This file is part of the StepClassLibrary (SCL).
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# Neither the name of the <ORGANIZATION> nor the names of its contributors may
# be used to endorse or promote products derived from this software without
# specific prior written permission.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
__doc__ = "This module defines EXPRESS built in constants and functions"
import math
from SimpleDataTypes import *
from BaseType import Aggregate
from AggregationDataTypes import *
SCL_float_epsilon = 1e-7
# Builtin constants
# EXPRESS definition:
# ===================
# 14.1 CONST_E is a REAL constant representing the mathematical value e, the base of the natural
# logarithm function (ln).
CONST_E = REAL(math.pi)
# EXPRESS definition:
# ===================
# 14.2 Indeterminate
# The indeterminate symbol (?) stands for an ambiguous value. It is compatible with all data
# types.
# NOTE - The most common use of indeterminate (?) is as the upper bound specification of a bag,
# list or set. This usage represents the notion that the size of the aggregate value defined by the
# aggregation data type is unbounded.
# python note: indeterminate value is mapped to None in aggregate bounds
# EXPRESS definition:
# ===================
# 14.3 False
# false is a logical constant representing the logical notion of falsehood. It is compatible with
# the boolean and logical data types.
FALSE = False
# EXPRESS definition:
# ===================
# 14.4 Pi
# PI is a REAL constant representing the mathematical value π, the ratio of a circle's circumference
# to its diameter.
PI = REAL(math.pi)
# EXPRESS definition:
# ===================
# 14.5 Self
# SELF refers to the current entity instance or type value. self may appear within an entity
# declaration, a type declaration or an entity constructor.
# NOTE - SELF is not a constant, but behaves as one in every context in which it can appear.
# python note: SELF is not mapped to any constant, but is mapper to self
# EXPRESS definition:
# ===================
# 14.6 True
# true is a logical constant representing the logical notion of truth. It is compatible with the
# boolean and logical data types.
TRUE = True
# EXPRESS definition:
# ===================
# 14.7 Unknown
# unknown is a logical constant representing that there is insufficient information available to
# be able to evaluate a logical condition. It is compatible with the logical data type, but not
# with the boolean data type.
# @TODO: define UNKNOWN in python
#
# Builtin Functions
# 15 Built-in functions
# All functions (and mathematical operations in general) are assumed to evaluate to exact results.
# The prototype for each of the built-in functions is given to show the type of the formal parameters
# and the result.
#
# EXPRESS definition:
# ===================
# 15.1 Abs - arithmetic function
# FUNCTION ABS ( V:NUMBER ) : NUMBER;
# The abs function returns the absolute value of a number.
# Parameters : V is a number.
# Result : The absolute value of V. The returned data type is identical to the data type of V.
# EXAMPLE 125 { ABS ( -10 ) --> 10
# Python definition:
# ==================
# ABS is mapped to python abs builtin function
def ABS(V):
if not isinstance(V, NUMBER):
raise TypeError("ABS function takes a NUMBER parameter")
return type(V)(abs(V))
# EXPRESS definition:
# ===================
# 15.2 ACos - arithmetic function
# FUNCTION ACOS ( V:NUMBER ) : REAL;
# The acos function returns the angle given a cosine value.
# Parameters : V is a number which is the cosine of an angle.
# Result : The angle in radians (0 <= result <= pi) whose cosine is V.
# Conditions : -1.0=<V<=1.0
# EXAMPLE 126 { ACOS ( 0.3 ) --> 1.266103...
# Python definition:
# ==================
# ACOS is mapped to python math.acos builtin function
def ACOS(V):
if not isinstance(V, NUMBER):
raise TypeError("ACOS function takes a NUMBER parameter")
return REAL(math.acos(V))
# it's the same for ASIN and ATAN
def ASIN(V):
if not isinstance(V, NUMBER):
raise TypeError("ASIN function takes a NUMBER parameter")
return REAL(math.asin(V))
# EXPRESS definition:
# ===================
# 15.3 ATan - arithmetic function
# FUNCTION ATAN ( V1:NUMBER; V2:NUMBER ) : REAL;
# The atan function returns the angle given a tangent value of V , where V is given by the
# expression V = V1/V2.
# Parameters :
# a) V1 is a number.
# b) V2 is a number.
# Result : The angle in radians (-pi/2<=result<=pi/2) whose tangent is V. If V2 is zero, the result
# is pi/2 or -pi/2 depending on the sign of V1.
# Conditions : Both V1 and V2 shall not be zero.
# EXAMPLE 128 { ATAN ( -5.5, 3.0 ) --> -1.071449...
def ATAN(V1, V2):
if not isinstance(V1, NUMBER) and not isinstance(V2, NUMBER):
raise TypeError("ATAN function takes 2 NUMBER parameters")
if V2 == 0:
if V1 > 0:
return REAL(math.pi / 2)
elif V1 < 0:
return REAL(-math.pi / 2)
else:
raise ValueError("ATAN parameters can be both equal to zero")
else:
return REAL(math.atan(float(V1) / float(V2)))
# EXPRESS definition:
# ===================
# 15.5 BLength - binary function
# FUNCTION BLENGTH ( V:BINARY ) : INTEGER;
# The blength function returns the number of bits in a binary.
# Parameters : V is a binary value.
# Result : The returned value is the actual number of bits in the binary value passed.
# EXAMPLE 129
# LOCAL
# n : NUMBER;
# x : BINARY := %01010010 ;
# END_LOCAL;
# ...
# n := BLENGTH ( x ); -- n is assigned the value 8
def BLENGTH(V):
if not isinstance(V, BINARY):
raise TypeError("BLENGTH function takes one BINARY parameter")
return INTEGER(len(V))
# EXPRESS definition:
# ===================
# 15.6 Cos - arithmetic function
# FUNCTION COS ( V:NUMBER ) : REAL;
# The cos function returns the cosine of an angle.
# Parameters : V is a number which is an angle in radians.
# Result : The cosine of V (-1.0<=result<=1.0).
# EXAMPLE 130 { COS ( 0.5 ) --> 8.77582...E-1
#
# 15.21 Sin - arithmetic function
# FUNCTION SIN ( V:NUMBER ) : REAL;
# The sin function returns the sine of an angle.
# Parameters : V is a number representing an angle expressed in radians.
# Result : The sine of V (-1.0 <= result <= 1.0).
# EXAMPLE 144 { SIN ( PI ) --> 0.0
#
def COS(V):
if not isinstance(V, NUMBER):
raise TypeError("COS function takes a NUMBER parameter")
return REAL(math.cos(V))
def SIN(V):
if not isinstance(V, NUMBER):
raise TypeError("SIN function takes a NUMBER parameter")
return REAL(math.sin(V))
# EXPRESS definition:
# ===================
# 15.7 Exists - general function
# FUNCTION EXISTS ( V:GENERIC ) : BOOLEAN;
# The exists function returns true if a value exists for the input parameter, or false if no value
# exists for it. The exists function is useful for checking if values have been given to optional
# attributes, or if variables have been initialized.
# Parameters : V is an expression which results in any type.
# Result : true or false depending on whether V has an actual or indeterminate (?) value.
# EXAMPLE 131 { IF EXISTS ( a ) THEN ...
def EXISTS(V):
if V == None:
return False
else:
return True
# EXPRESS definition:
# ===================
# 15.8 Exp - arithmetic function
# FUNCTION EXP ( V:NUMBER ) : REAL;
# The exp function returns e (the base of the natural logarithm system) raised to the power V.
# Parameters : V is a number.
# Result : The value eV .
# EXAMPLE 132 { EXP ( 10 ) --> 2.202646...E+4
def EXP(V):
if not isinstance(V, NUMBER):
raise TypeError("EXP function takes a NUMBER parameter")
return REAL(math.exp(V))
# EXPRESS definition:
# ===================
# 15.9 Format - general function
# FUNCTION FORMAT(N:NUMBER; F:STRING):STRING;
# The format returns a formatted string representation of a number.
# Parameters :
# a) N is a number (integer or real).
# b) F is a string containing formatting commands.
# Result : A string representation of N formatted according to F. Rounding is applied to the
# string representation if necessary.
# The formatting string contains special characters to indicate the appearance of the result. The
# formatting string can be written in three ways:
# a) The formatting string can give a symbolic description of the output representation.
# b) The formatting string can give a picture description of the output representation.
# c) When the formatting string is empty, a standard output representation is produced.
# Table 20:
# Number Format Display Comment
# 10 +7I ' +10' Zero suppression
# 10 +07I '+000010' Zeros not suppressed
# 10 10.3E ' 1.000E+01'
# 123.456789 8.2F ' 123.46'
# 123.456789 8.2E '1.23E+02'
# 123.456789 08.2E '0.12E+02' Preceding zero forced
# 9.876E123 8.2E '9.88E+123' Exponent part is 3 characters
# and width ignored
# 32.777 6I ' 33' Rounded
# Python definition
# =================
# python string formatting is obtained from the val function
# @TODO: implement a safe eval or provide another implementation
# that avoids unsafe eval python builtin function.
def FORMAT(N, F):
if not isinstance(N, NUMBER):
raise TypeError("FORMAT function takes a NUMBER parameter")
if not isinstance(F, STRING):
raise TypeError("FORMAT function takes a NUMBER parameter")
py_formatting = F.lower()
string_to_evaluate = "'%"
string_to_evaluate += "%s'" % py_formatting
string_to_evaluate += "%"
string_to_evaluate += "%s" % N
result = eval(string_to_evaluate).upper()
return STRING(result)
# EXPRESS definition:
# ===================
# 15.10 HiBound - arithmetic function
# FUNCTION HIBOUND ( V:AGGREGATE OF GENERIC ) : INTEGER;
# The hibound function returns the declared upper index of an array or the declared upper
# bound of a bag, list or set.
# Parameters : V is an aggregate value.
# Result :
# a) When V is an array the returned value is the declared upper index.
# b) When V is a bag, list or set the returned value is the declared upper bound; if there
# are no bounds declared or the upper bound is declared to be indeterminate (?) indeterminate
# (?) is returned.
# EXAMPLE 133 { Usage of hibound function on nested aggregate values.
# LOCAL
# a : ARRAY[-3:19] OF SET[2:4] OF LIST[0:?] OF INTEGER;
# h1, h2, h3 : INTEGER;
# END_LOCAL;
# ...
# a[-3][1][1] := 2; -- places a value in the list
# ...
# h1 := HIBOUND(a); -- =19 (upper bound of array)
# h2 := HIBOUND(a[-3]); -- = 4 (upper bound of set)
# h3 := HIBOUND(a[-3][1]); -- = ? (upper bound of list (unbounded))
def HIBOUND(V):
if not isinstance(V, Aggregate):
raise TypeError("HIBOUND takes an aggregate of generic")
return V.get_hibound()
# EXPRESS definition:
# ===================
# 15.11 HiIndex - arithmetic function
# FUNCTION HIINDEX ( V:AGGREGATE OF GENERIC ) : INTEGER;
# The hiindex function returns the upper index of an array or the number of elements in a bag,
# list or set
# Parameters : V is an aggregate value.
# Result :
# a) When V is an array, the returned value is the declared upper index.
# b) When V is a bag, list or set, the returned value is the actual number of elements in
# the aggregate value.
# EXAMPLE 134 { Usage of hiindex function on nested aggregate values.
# LOCAL
# a : ARRAY[-3:19] OF SET[2:4] OF LIST[0:?] OF INTEGER;
# h1, h2, h3 : INTEGER;
# END_LOCAL;
# a[-3][1][1] := 2; -- places a value in the list
# h1 := HIINDEX(a); -- = 19 (upper bound of array)
# h2 := HIINDEX(a[-3]); -- = 1 (size of set) -- this is invalid with respect
# -- to the bounds on the SET
# h3 := HIINDEX(a[-3][1]); -- = 1 (size of list)
def HIINDEX(V):
if not isinstance(V, Aggregate):
raise TypeError("HIINDEX takes an aggregate of generic")
return V.get_hiindex()
# EXPRESS definition:
# ===================
# 15.12 Length - string function
# FUNCTION LENGTH ( V:STRING ) : INTEGER;
# The length function returns the number of characters in a string.
# Parameters : V is a string value.
# Result : The returned value is the number of characters in the string and shall be greater than
# or equal to zero.
# EXAMPLE 135 - Usage of the length function.
# LOCAL
# n : NUMBER;
# x1 : STRING := 'abc';
# x2 : STRING := "000025FF000101B5;
# END_LOCAL;
# ...
# n := LENGTH ( x1 ); -- n is assigned the value 3
# n := LENGTH ( x2 ); -- n is assigned the value 2
def LENGTH(V):
if not isinstance(V, STRING):
raise TypeError("LENGTH take a STRING parameter")
return INTEGER(len(V))
# EXPRESS definition:
# ===================
# 15.13 LoBound - arithmetic function
# FUNCTION LOBOUND ( V:AGGREGATE OF GENERIC ) : INTEGER;
# The lobound function returns the declared lower index of an array, or the declared lower
# bound of a bag, list or set.
# Parameters : V is an aggregate value.
# Result :
# a) When V is an array the returned value is the declared lower index.
# b) When V is a bag, list or set the returned value is the declared lower bound; if no
# lower bound is declared, zero (0) is returned.
# EXAMPLE 136 { Usage of lobound function on nested aggregate values.
# LOCAL
# a : ARRAY[-3:19] OF SET[2:4] OF LIST[0:?] OF INTEGER;
# h1, h2, h3 : INTEGER;
# END_LOCAL;
# ...
# h1 := LOBOUND(a); -- =-3 (lower index of array)
# h2 := LOBOUND(a[-3]); -- = 2 (lower bound of set)
# h3 := LOBOUND(a[-3][1]); -- = 0 (lower bound of list)
def LOBOUND(V):
if not isinstance(V, Aggregate):
raise TypeError("HIBOUND takes an aggregate of generic")
return V.get_lobound()
# EXPRESS definition:
# ===================
# 15.14 Log - arithmetic function
# FUNCTION LOG ( V:NUMBER ) : REAL;
# The log function returns the natural logarithm of a number.
# Parameters : V is a number.
# Result : A real number which is the natural logarithm of V.
# Conditions : V > 0:0
# EXAMPLE 137 { LOG ( 4.5 ) --> 1.504077...E0
# 15.15 Log2 - arithmetic function
# FUNCTION LOG2 ( V:NUMBER ) : REAL;
# The log2 function returns the base two logarithm of a number.
# Parameters : V is a number.
# Result : A real number which is the base two logarithm of V.
# Conditions : V > 0:0
# EXAMPLE 138 { LOG2 ( 8 ) --> 3.00...E0
# 15.16 Log10 - arithmetic function
# FUNCTION LOG10 ( V:NUMBER ) : REAL;
# The log10 function returns the base ten logarithm of a number.
# Parameters : V is a number.
# Result : A real number which is the base ten logarithm of V.
# Conditions : V > 0:0
# EXAMPLE 139 { LOG10 ( 10 ) --> 1.00...E0
def LOG(V):
if not isinstance(V, NUMBER):
raise TypeError("LOG function takes a NUMBER parameter")
return REAL(math.log(V))
def LOG2(V):
if not isinstance(V, NUMBER):
raise TypeError("LOG2 function takes a NUMBER parameter")
return REAL(math.log(V, 2))
def LOG10(V):
if not isinstance(V, NUMBER):
raise TypeError("LOG10 function takes a NUMBER parameter")
return REAL(math.log10(V))
# EXPRESS definition:
# ===================
# 15.17 LoIndex - arithmetic function
# FUNCTION LOINDEX ( V:AGGREGATE OF GENERIC ) : INTEGER;
# The loindex function returns the lower index of an aggregate value.
# Parameters : V is an aggregate value.
# Result :
# a) When V is an array the returned value is the declared lower index.
# b) When V is a bag, list or set, the returned value is 1 (one).
# EXAMPLE 140 { Usage of loindex function on nested aggregate values.
# LOCAL
# a : ARRAY[-3:19] OF SET[2:4] OF LIST[0:?] OF INTEGER;
# h1, h2, h3 : INTEGER;
# END_LOCAL;
# ...
# h1 := LOINDEX(a); -- =-3 (lower bound of array)
# h2 := LOINDEX(a[-3]); -- = 1 (for set)
# h3 := LOINDEX(a[-3][1]); -- = 1 (for list)
def LOINDEX(V):
if not isinstance(V, Aggregate):
raise TypeError("LOINDEX takes an aggregate of generic")
return V.get_loindex()
# EXPRESS definition:
# ===================
# 15.18 NVL - null value function
# FUNCTION NVL(V:GENERIC:GEN1; SUBSTITUTE:GENERIC:GEN1):GENERIC:GEN1;
# The nvl function returns either the input value or an alternate value in the case where the input
# has a indeterminate (?) value.
# Parameters :
# a) V is an expression which is of any type.
# b) SUBSTITUTE is an expression which shall not evaluate to indeterminate (?).
# Result : When V is not indeterminate (?) that value is returned. Otherwise, SUBSTITUTE is
# returned.
# EXAMPLE 141 { ENTITY unit_vector;
# x, y : REAL;
# z : OPTIONAL REAL;
# WHERE
# x**2 + y**2 + NVL(z, 0.0)**2 = 1.0;
# END_ENTITY;
# The nvl function is used to supply zero (0.0) as the value of Z when Z is indeterminate (?).
def NVL(V, SUBSTITUTE):
if V is not None:
return V
else:
return SUBSTITUTE
# EXPRESS definition:
# ===================
# 15.19 Odd - arithmetic function
# FUNCTION ODD ( V:INTEGER ) : LOGICAL;
# The odd function returns true or false depending on whether a number is odd or even.
# Parameters : V is an integer number.
# Result : When V MOD 2 = 1 true is returned; otherwise false is returned.
# Conditions : Zero is not odd.
# EXAMPLE 142 { ODD ( 121 ) --> TRUE
def ODD(V):
if not isinstance(V, INTEGER):
raise TypeError("ODD takes an INTEGER")
if V % 2 == 0:
return False
else:
return True
# EXPRESS definition:
# ===================
# 15.20 RolesOf - general function
# FUNCTION ROLESOF ( V:GENERIC ) : SET OF STRING;
# The rolesof function returns a set of strings containing the fully qualified names of the roles
# played by the specified entity instance. A fully qualified name is defined to be the name of the
# attribute qualified by the name of the schema and entity in which this attribute is declared (i.e.
#'SCHEMA.ENTITY.ATTRIBUTE').
# Parameters : V is any instance of an entity data type.
# Result : A set of string values (in upper case) containing the fully qualified names of the
# attributes of the entity instances which use the instance V.
# When a named data type is used or referenced, the schema and the name in that schema,
# if renamed, are also returned. Since use statements may be chained, all the chained schema
# names and the name in each schema are returned.
# EXAMPLE 143 { This example shows that a point might be used as the centre of a circle. The
# rolesof function determines what roles an entity instance actually plays.
# SCHEMA that_schema;
# ENTITY point;
# x, y, z : REAL;
# END_ENTITY;
# ENTITY line;
# start,
# end : point;
# END_ENTITY;
# END_SCHEMA;
# SCHEMA this_schema;
# USE FROM that_schema (point,line);
# CONSTANT
# origin : point := point(0.0, 0.0, 0.0);
# END_CONSTANT;
# ENTITY circle;
# centre : point;
# axis : vector;
# radius : REAL;
# END_ENTITY;
# ...
# LOCAL
# p : point := point(1.0, 0.0, 0.0);
# c : circle := circle(p, vector(1,1,1), 1.0);
# l : line := line(p, origin);
# END_LOCAL;
# ...
# IF 'THIS_SCHEMA.CIRCLE.CENTRE' IN ROLESOF(p) THEN -- true
# ...
# IF 'THIS_SCHEMA.LINE.START' IN ROLESOF(p) THEN -- true
# ...
# IF 'THAT_SCHEMA.LINE.START' IN ROLESOF(p) THEN -- true
# ...
# IF 'THIS_SCHEMA.LINE.END' IN ROLESOF(p) THEN -- false
#
# Python note:
# @TODO: implement the ROLESOF function
def ROLESOF(V):
raise NotImplemented("Function ROLESOF not implemented")
# EXPRESS definition:
# ===================
# 15.22 SizeOf - aggregate function
# FUNCTION SIZEOF ( V:AGGREGATE OF GENERIC ) : INTEGER;
# The sizeof function returns the number of elements in an aggregate value.
# Parameters : V is an aggregate value.
# Result :
# a) When V is an array the returned value is its declared number of elements in the
# aggregation data type.
# b) When V is a bag, list or set, the returned value is the actual number of elements in
# the aggregate value.
# EXAMPLE 145 { LOCAL
# n : NUMBER;
# y : ARRAY[2:5] OF b;
# END_LOCAL;
# ...
# n := SIZEOF (y); -- n is assigned the value 4
def SIZEOF(V):
if not isinstance(V, Aggregate):
raise TypeError("SIZEOF takes an aggregate of generic")
return V.get_size()
# EXPRESS definition:
# ===================
# 15.23 Sqrt - arithmetic function
# FUNCTION SQRT ( V:NUMBER ) : REAL;
# The sqrt function returns the non-negative square root of a number.
# Parameters : V is any non-negative number.
# Result : The non-negative square root of V.
# Conditions : V >= 0:0
# EXAMPLE 146 - SQRT ( 121 ) --> 11.0
def SQRT(V):
if not isinstance(V, NUMBER):
raise TypeError("SQRT function takes a NUMBER parameter")
if V < 0.0:
raise ValueError("SQRT takes a non-negative parameter")
return REAL(math.sqrt(V))
# EXPRESS definition:
# ===================
# 15.24 Tan - arithmetic function
# FUNCTION TAN ( V:NUMBER ) : REAL;
# The tan function returns the tangent of an angle.
# Parameters : V is a number representing an angle expressed in radians.
# Result : The tangent of the angle. If the angle is npi/2, where n is an odd integer, indeterminate
# (?) is returned.
# EXAMPLE 147 - TAN ( 0.0 ) --> 0.0
def TAN(V):
if not isinstance(V, NUMBER):
raise TypeError("TAN function takes a NUMBER parameter")
# check if angle is npi/2 where n is an odd integer
a = V / (PI / 2)
if abs(a % 2 - 1.0) < SCL_float_epsilon:
return None
else:
return REAL(math.tan(V))
# EXPRESS definition:
# ===================
# 15.25 TypeOf - general function
# FUNCTION TYPEOF ( V:GENERIC ) : SET OF STRING;
# The typeof function returns a set of strings that contains the names of all the data types
# of which the parameter is a member. Except for the simple data types (binary, boolean,
# integer, logical, number, real, and string) and the aggregation data types (array, bag,
# list, set) these names are qualified by the name of the schema which contains the definition of
# the type.
# NOTE 1 { The primary purpose of this function is to check whether a given value (variable, at-
# tribute value) can be used for a certain purpose, e.g. to ensure assignment compatibility between
# two values. It may also be used if different subtypes or specializations of a given type have to be
# treated differently in some context.
# Parameters : V is a value of any type.
# Result : The contents of the returned set of string values are the names (in upper case) of all
# types the value V is a member of. Such names are qualified by the name of the schema which
# contains the definition of the type ('SCHEMA.TYPE') if it is neither a simple data type nor an
# aggregation data type. It may be derived by the following algorithm (which is given here for
# specification purposes rather than to prescribe any particular type of implementation)
def TYPEOF(V):
# Create the set to return
v_types = set()
# append the type of V to the set
try: # it's a class
to_add = V.__name__.upper()
except AttributeError: # it's an instance, first retrieve the type
to_add = type(V).__name__.upper()
if not to_add in ["FLOAT", "INT", "AGGREGATE"]:
v_types.add(to_add)
# recursively adds the base class names
for base_type in type(V).__bases__:
# print base_type
if not base_type == object:
v_types = v_types.union(TYPEOF(base_type))
# finally, converts the v_types set to SET
return v_types
# EXPRESS definition:
# ===================
# 15.26 UsedIn - general function
# FUNCTION USEDIN ( T:GENERIC; R:STRING) : BAG OF GENERIC;
# The usedin function returns each entity instance that uses a specified entity instance in a
# specified role.
def USEDIN(T, R):
raise NotImplemented("USEDIN function not yet implemented.")
# EXPRESS definition:
# ===================
# 15.27 Value - arithmetic function
# FUNCTION VALUE ( V:STRING ) : NUMBER;
# The value function returns the numeric representation of a string.
# Parameters : V is a string containing either a real or integer literal.
# Result : A number corresponding to the string representation. If it is not possible to interpret
# the string as either a real or integer literal, indeterminate (?) is returned.
# EXAMPLE 151 { VALUE ( '1.234' ) --> 1.234 (REAL)
# VALUE ( '20' ) --> 20 (INTEGER)
# VALUE ( 'abc' ) --> ? null
def VALUE(V):
if not isinstance(V, STRING):
raise TypeError("VALUE function takes a NUMBER parameter")
# first try to instantiate an INTEGER from the string:
try:
return INTEGER(V)
except Exception:
pass # not possible, try to cast to REAL
try:
return REAL(V)
except Exception:
pass
# else return None
return None
# EXPRESS definition:
# ===================
# 15.28 Value in - membership function
# FUNCTION VALUE_IN ( C:AGGREGATE OF GENERIC:GEN; V:GENERIC:GEN ) : LOGICAL;
# The value in function returns a logical value depending on whether or not a particular value
# is a member of an aggregation.
# Parameters :
# a) C is an aggregation of any type.
# b) V is an expression which is assignment compatible with the base type of C.
# Result :
# a) If either V or C is indeterminate (?), unknown is returned.
# b) If any element of C has a value equal to the value of V, true is returned.
# c) If any element of C is indeterminate (?), unknown is returned.
# d) Otherwise false is returned.
# EXAMPLE 152 { The following test ensures that there is at least one point which is positioned at
# the origin.
# LOCAL
# points : SET OF point;
# END_LOCAL;
# ...
# IF VALUE_IN(points, point(0.0, 0.0, 0.0)) THEN ...
def VALUE_IN(C, V):
if not isinstance(C, Aggregate):
raise TypeError("VALUE_IN method takes an aggregate as first parameter")
raise NotImplemented("VALUE_IN function not yet implemented")
# EXPRESS definition:
# ===================
# 15.29 Value unique - uniqueness function
# FUNCTION VALUE UNIQUE ( V:AGGREGATE OF GENERIC) : LOGICAL;
# The value unique function returns a logical value depending on whether or not the elements
# of an aggregation are value unique.
# Parameters : V is an aggregation of any type.
# Result :
# a) If V is indeterminate (?), unknown is returned.
# b) If any any two elements of V are value equal, false is returned.
# c) If any element of V is indeterminate (?), unknown is returned.
# d) Otherwise true is returned.
# EXAMPLE 153 { The following test ensures that each point is placed at a different position, (by
# definition they are distinct, i.e., instance unique).
# IF VALUE_UNIQUE(points) THEN ...
def VALUE_UNIQUE(V):
if not isinstance(V, Aggregate):
raise TypeError("VALUE_UNIQUE method takes an aggregate as first parameter")
return V.get_value_unique()
|