add SCL python files
This commit is contained in:
parent
3648912e24
commit
e17090fadd
|
@ -31,9 +31,39 @@ SET(Import_SRCS
|
|||
PreCompiled.h
|
||||
)
|
||||
|
||||
SET(SCL_Resources
|
||||
SCL/__init__.py
|
||||
SCL/AggregationDataTypes.py
|
||||
SCL/BaseType.py
|
||||
SCL/Builtin.py
|
||||
SCL/ConstructedDataTypes.py
|
||||
SCL/essa_par.py
|
||||
SCL/Model.py
|
||||
SCL/Part21.py
|
||||
SCL/Rules.py
|
||||
SCL/SCLBase.py
|
||||
SCL/SimpleDataTypes.py
|
||||
SCL/TypeChecker.py
|
||||
SCL/Utils.py
|
||||
automotive_design.py # AP214e3
|
||||
ifc2x3.py # IFC
|
||||
ifc4.py # IFC 4
|
||||
)
|
||||
SOURCE_GROUP("SCL" FILES ${SCL_Resources})
|
||||
|
||||
add_library(Import SHARED ${Import_SRCS})
|
||||
target_link_libraries(Import ${Import_LIBS})
|
||||
|
||||
ADD_CUSTOM_TARGET(ImportPy ALL
|
||||
SOURCES ${SCL_Resources}
|
||||
)
|
||||
|
||||
fc_target_copy_resource(ImportPy
|
||||
${CMAKE_SOURCE_DIR}/src/Mod/Import/App
|
||||
${CMAKE_BINARY_DIR}/Mod/Import
|
||||
${SCL_Resources})
|
||||
|
||||
|
||||
if(MSVC)
|
||||
set_target_properties(Import PROPERTIES SUFFIX ".pyd")
|
||||
set_target_properties(Import PROPERTIES DEBUG_OUTPUT_NAME "Import_d")
|
||||
|
|
602
src/Mod/Import/App/SCL/AggregationDataTypes.py
Normal file
602
src/Mod/Import/App/SCL/AggregationDataTypes.py
Normal file
|
@ -0,0 +1,602 @@
|
|||
# Copyright (c) 2011, 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.
|
||||
|
||||
from SimpleDataTypes import *
|
||||
from TypeChecker import check_type
|
||||
import BaseType
|
||||
|
||||
class BaseAggregate(object):
|
||||
""" A class that define common properties to ARRAY, LIST, SET and BAG.
|
||||
"""
|
||||
def __init__( self , bound1 , bound2 , base_type ):
|
||||
# check that bound1<bound2
|
||||
if (bound1!=None and bound2!=None):
|
||||
if bound1>bound2:
|
||||
raise AssertionError("bound1 shall be less than or equal to bound2")
|
||||
self._bound1 = bound1
|
||||
self._bound2 = bound2
|
||||
self._base_type = base_type
|
||||
|
||||
def __getitem__(self, index):
|
||||
if index<self._bound1:
|
||||
raise IndexError("ARRAY index out of bound (lower bound is %i, passed %i)"%(self._bound1,index))
|
||||
elif(self._bound2!=None and index>self._bound2):
|
||||
raise IndexError("ARRAY index out of bound (upper bound is %i, passed %i)"%(self._bound2,index))
|
||||
else:
|
||||
return list.__getitem__(self,index)
|
||||
|
||||
def __setitem__(self,index,value):
|
||||
if index<self._bound1:
|
||||
raise IndexError("ARRAY index out of bound (lower bound is %i, passed %i)"%(self._bound1,index))
|
||||
elif (self._bound2!=None and index>self._bound2):
|
||||
raise IndexError("ARRAY index out of bound (upper bound is %i, passed %i)"%(self._bound2,index))
|
||||
elif not isinstance(value,self._base_type):
|
||||
raise TypeError("%s type expected, passed %s."%(self._base_type, type(value)))
|
||||
else:
|
||||
# first find the length of the list, and extend it if ever
|
||||
# the index is
|
||||
list.__setitem__(self,index,value)
|
||||
|
||||
class ARRAY(BaseType.Type, BaseType.Aggregate):
|
||||
"""
|
||||
EXPRESS definition:
|
||||
==================
|
||||
An array data type has as its domain indexed, fixed-size collections of like elements. The lower
|
||||
and upper bounds, which are integer-valued expressions, define the range of index values, and
|
||||
thus the size of each array collection.
|
||||
An array data type definition may optionally specify
|
||||
that an array value cannot contain duplicate elements.
|
||||
It may also specify that an array value
|
||||
need not contain an element at every index position.
|
||||
|
||||
Given that m is the lower bound and n is the upper bound, there are exactly n-m+1 elements
|
||||
in the array. These elements are indexed by subscripts from m to n, inclusive (see 12.6.1).
|
||||
NOTE 1 { The bounds may be positive, negative or zero, but may not be indeterminate (?) (see
|
||||
14.2).
|
||||
|
||||
Syntax:
|
||||
165 array_type = ARRAY bound_spec OF [ OPTIONAL ] [ UNIQUE ] base_type .
|
||||
176 bound_spec = '[' bound_1 ':' bound_2 ']' .
|
||||
174 bound_1 = numeric_expression .
|
||||
175 bound_2 = numeric_expression .
|
||||
171 base_type = aggregation_types | simple_types | named_types .
|
||||
Given that m is the lower bound and n is the upper bound, there are exactly n-m+1 elements
|
||||
in the array. These elements are indexed by subscripts from m to n, inclusive (see 12.6.1).
|
||||
NOTE 1 { The bounds may be positive, negative or zero, but may not be indeterminate (?) (see
|
||||
14.2).
|
||||
Rules and restrictions:
|
||||
a) Both expressions in the bound specication, bound_1 and bound_2, shall evaluate to
|
||||
integer values. Neither shall evaluate to the indeterminate (?) value.
|
||||
b) bound_1 gives the lower bound of the array. This shall be the lowest index which is
|
||||
valid for an array value of this data type.
|
||||
c) bound_2 gives the upper bound of the array. This shall be the highest index which is
|
||||
valid for an array value of this data type.
|
||||
d) bound_1 shall be less than or equal to bound_2.
|
||||
e) If the optional keyword is specied, an array value of this data type may have the
|
||||
indeterminate (?) value at one or more index positions.
|
||||
f) If the optional keyword is not specied, an array value of this data type shall not
|
||||
contain an indeterminate (?) value at any index position.
|
||||
g) If the unique keyword is specied, each element in an array value of this data type
|
||||
shall be dierent from (i.e., not instance equal to) every other element in the same array
|
||||
value.
|
||||
NOTE 2 : Both optional and unique may be specied in the same array data type definition.
|
||||
This does not preclude multiple indeterminate (?) values from occurring in a single array value.
|
||||
This is because comparisons between indeterminate (?) values result in unknown so the uniqueness
|
||||
constraint is not violated.
|
||||
EXAMPLE 27 : This example shows how a multi-dimensioned array is declared.
|
||||
sectors : ARRAY [ 1 : 10 ] OF -- first dimension
|
||||
ARRAY [ 11 : 14 ] OF -- second dimension
|
||||
UNIQUE something;
|
||||
The first array has 10 elements of data type ARRAY[11:14] OF UNIQUE something. There is
|
||||
a total of 40 elements of data type something in the attribute named sectors. Within each
|
||||
ARRAY[11:14], no duplicates may occur; however, the same something instance may occur in two
|
||||
different ARRAY[11:14] values within a single value for the attribute named sectors.
|
||||
|
||||
Python definition:
|
||||
==================
|
||||
@TODO
|
||||
"""
|
||||
def __init__( self , bound_1 , bound_2 , base_type , UNIQUE = False, OPTIONAL=False, scope = None):
|
||||
BaseType.Type.__init__(self, base_type, scope)
|
||||
if not type(bound_1)==int:
|
||||
raise TypeError("ARRAY lower bound must be an integer")
|
||||
if not type(bound_2)==int:
|
||||
raise TypeError("ARRAY upper bound must be an integer")
|
||||
if not (bound_1 <= bound_2):
|
||||
raise AssertionError("ARRAY lower bound must be less than or equal to upper bound")
|
||||
# set up class attributes
|
||||
self._bound_1 = bound_1
|
||||
self._bound_2 = bound_2
|
||||
self._unique = UNIQUE
|
||||
self._optional = OPTIONAL
|
||||
# preallocate list elements
|
||||
list_size = bound_2 - bound_1 + 1
|
||||
self._container = list_size*[None]
|
||||
|
||||
def bound_1(self):
|
||||
return self._bound_1
|
||||
|
||||
def bound_2(self):
|
||||
return self._bound_2
|
||||
|
||||
def get_hiindex(self):
|
||||
return INTEGER(self._bound_2)
|
||||
|
||||
def get_loindex(self):
|
||||
return INTEGER(self._bound_1)
|
||||
|
||||
def get_hibound(self):
|
||||
return INTEGER(self._bound_2)
|
||||
|
||||
def get_lobound(self):
|
||||
return INTEGER(self._bound_1)
|
||||
|
||||
def get_size(self):
|
||||
return INTEGER(self._bound_2 - self._bound_1 +1)
|
||||
|
||||
def get_value_unique(self):
|
||||
''' Return True if all items are different in the container, UNKNOWN if some items are
|
||||
indeterminate, or False otherwise'''
|
||||
if None in self._container:
|
||||
return Unknown
|
||||
if self.get_size()-len(set(self._container))>0: #some items are repeated
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def __getitem__(self, index):
|
||||
if index<self._bound_1:
|
||||
raise IndexError("ARRAY index out of bound (lower bound is %i, passed %i)"%(self._bound_1,index))
|
||||
elif(index>self._bound_2):
|
||||
raise IndexError("ARRAY index out of bound (upper bound is %i, passed %i)"%(self._bound_2,index))
|
||||
else:
|
||||
value = self._container[index-self._bound_1]
|
||||
if not self._optional and value==None:
|
||||
raise AssertionError("Not OPTIONAL prevent the value with index %i from being None (default). Please set the value first."%index)
|
||||
return value
|
||||
|
||||
def __setitem__(self, index, value):
|
||||
if index<self._bound_1:
|
||||
raise IndexError("ARRAY index out of bound (lower bound is %i, passed %i)"%(self._bound_1,index))
|
||||
elif(index>self._bound_2):
|
||||
raise IndexError("ARRAY index out of bound (upper bound is %i, passed %i)"%(self._bound_2,index))
|
||||
else:
|
||||
# first check the type of the value
|
||||
check_type(value,self.get_type())
|
||||
# then check if the value is already in the array
|
||||
if self._unique:
|
||||
if value in self._container:
|
||||
raise AssertionError("UNIQUE keyword prevents inserting this instance.")
|
||||
self._container[index-self._bound_1] = value
|
||||
|
||||
class LIST(BaseType.Type, BaseType.Aggregate):
|
||||
"""
|
||||
EXPRESS definition:
|
||||
==================
|
||||
A list data type has as its domain sequences of like elements. The optional lower and upper
|
||||
bounds, which are integer-valued expressions, define the minimum and maximum number of
|
||||
elements that can be held in the collection defined by a list data type.
|
||||
A list data type
|
||||
definition may optionally specify that a list value cannot contain duplicate elements.
|
||||
|
||||
Syntax:
|
||||
237 list_type = LIST [ bound_spec ] OF [ UNIQUE ] base_type .
|
||||
176 bound_spec = '[' bound_1 ':' bound_2 ']' .
|
||||
174 bound_1 = numeric_expression .
|
||||
175 bound_2 = numeric_expression .
|
||||
171 base_type = aggregation_types | simple_types | named_types .
|
||||
Rules and restrictions:
|
||||
a) The bound_1 expression shall evaluate to an integer value greater than or equal to
|
||||
zero. It gives the lower bound, which is the minimum number of elements that can be in a
|
||||
list value of this data type. bound_1 shall not produce the indeterminate (?) value.
|
||||
b) The bound_2 expression shall evaluate to an integer value greater than or equal to
|
||||
bound_1, or an indeterminate (?) value. It gives the upper bound, which is the maximum
|
||||
number of elements that can be in a list value of this data type.
|
||||
If this value is indeterminate (?) the number of elements in a list value of this data type is
|
||||
not bounded from above.
|
||||
c) If the bound_spec is omitted, the limits are [0:?].
|
||||
d) If the unique keyword is specied, each element in a list value of this data type shall
|
||||
be dierent from (i.e., not instance equal to) every other element in the same list value.
|
||||
EXAMPLE 28 { This example denes a list of arrays. The list can contain zero to ten arrays. Each
|
||||
array of ten integers shall be dierent from all other arrays in a particular list.
|
||||
complex_list : LIST[0:10] OF UNIQUE ARRAY[1:10] OF INTEGER;
|
||||
|
||||
Python definition:
|
||||
==================
|
||||
@TODO
|
||||
"""
|
||||
def __init__( self , bound_1 , bound_2 , base_type , UNIQUE = False, scope = None):
|
||||
BaseType.Type.__init__(self, base_type, scope)
|
||||
if not type(bound_1)==int:
|
||||
raise TypeError("LIST lower bound must be an integer")
|
||||
# bound_2 can be set to None
|
||||
self._unbounded = False
|
||||
if bound_2 == None:
|
||||
self._unbounded = True
|
||||
elif not type(bound_2)==int:
|
||||
raise TypeError("LIST upper bound must be an integer")
|
||||
if not bound_1>=0:
|
||||
raise AssertionError("LIST lower bound must be greater of equal to 0")
|
||||
if (type(bound_2)==int and not (bound_1 <= bound_2)):
|
||||
raise AssertionError("ARRAY lower bound must be less than or equal to upper bound")
|
||||
# set up class attributes
|
||||
self._bound_1 = bound_1
|
||||
self._bound_2 = bound_2
|
||||
self._unique = UNIQUE
|
||||
# preallocate list elements if bounds are both integers
|
||||
if not self._unbounded:
|
||||
list_size = bound_2 - bound_1 + 1
|
||||
self._container = list_size*[None]
|
||||
# for unbounded list, this will come after
|
||||
else:
|
||||
self._container = [None]
|
||||
|
||||
def bound_1(self):
|
||||
return self._bound_1
|
||||
|
||||
def bound_2(self):
|
||||
return self._bound_2
|
||||
|
||||
def get_size(self):
|
||||
number_of_indeterminates = self._container.count(None)
|
||||
hiindex = len(self._container) - number_of_indeterminates
|
||||
return INTEGER(hiindex)
|
||||
|
||||
def get_hiindex(self):
|
||||
''' When V is a bag, list or set, the returned value is the actual number of elements in
|
||||
the aggregate value.'''
|
||||
number_of_indeterminates = self._container.count(None)
|
||||
hiindex = len(self._container) - number_of_indeterminates
|
||||
return INTEGER(hiindex)
|
||||
|
||||
def get_loindex(self):
|
||||
return INTEGER(1)
|
||||
|
||||
def get_hibound(self):
|
||||
hibound = self._bound_2
|
||||
if type(hibound)==int:
|
||||
return INTEGER(hibound)
|
||||
else:
|
||||
return hibound
|
||||
|
||||
def get_lobound(self):
|
||||
lobound = self._bound_1
|
||||
if type(lobound)==int:
|
||||
return INTEGER(lobound)
|
||||
else:
|
||||
return lobound
|
||||
|
||||
def get_value_unique(self):
|
||||
''' Return True if all items are different in the container, UNKNOWN if some items are
|
||||
indeterminate, or False otherwise'''
|
||||
if None in self._container:
|
||||
return Unknown
|
||||
if self.get_size()-len(set(self._container))>0: #some items are repeated
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def __getitem__(self, index):
|
||||
# case bounded
|
||||
if not self._unbounded:
|
||||
if index<self._bound_1:
|
||||
raise IndexError("ARRAY index out of bound (lower bound is %i, passed %i)"%(self._bound_1,index))
|
||||
elif(index>self._bound_2):
|
||||
raise IndexError("ARRAY index out of bound (upper bound is %i, passed %i)"%(self._bound_2,index))
|
||||
else:
|
||||
value = self._container[index-self._bound_1]
|
||||
if value == None:
|
||||
raise AssertionError("Value with index %i not defined. Please set the value first."%index)
|
||||
return value
|
||||
#case unbounded
|
||||
else:
|
||||
if index-self._bound_1>len(self._container):
|
||||
raise AssertionError("Value with index %i not defined. Please set the value first."%index)
|
||||
else:
|
||||
value = self._container[index-self._bound_1]
|
||||
if value == None:
|
||||
raise AssertionError("Value with index %i not defined. Please set the value first."%index)
|
||||
return value
|
||||
|
||||
def __setitem__(self, index, value):
|
||||
# case bounded
|
||||
if not self._unbounded:
|
||||
if index<self._bound_1:
|
||||
raise IndexError("ARRAY index out of bound (lower bound is %i, passed %i)"%(self._bound_1,index))
|
||||
elif(index>self._bound_2):
|
||||
raise IndexError("ARRAY index out of bound (upper bound is %i, passed %i)"%(self._bound_2,index))
|
||||
else:
|
||||
# first check the type of the value
|
||||
check_type(value,self.get_type())
|
||||
# then check if the value is already in the array
|
||||
if self._unique:
|
||||
if value in self._container:
|
||||
raise AssertionError("UNIQUE keyword prevent inserting this instance.")
|
||||
self._container[index-self._bound_1] = value
|
||||
# case unbounded
|
||||
else:
|
||||
if index<self._bound_1:
|
||||
raise IndexError("ARRAY index out of bound (lower bound is %i, passed %i)"%(self._bound_1,index))
|
||||
# if the _container list is of good size, just do like the bounded case
|
||||
if (index-self._bound_1<len(self._container)):
|
||||
# first check the type of the value
|
||||
check_type(value,self.get_type)
|
||||
# then check if the value is already in the array
|
||||
if self._unique:
|
||||
if value in self._container:
|
||||
raise AssertionError("UNIQUE keyword prevent inserting this instance.")
|
||||
self._container[index-self._bound_1] = value
|
||||
# in the other case, we have to extend the base _container list
|
||||
else:
|
||||
delta_size = (index-self._bound_1) - len(self._container) + 1
|
||||
#create a list of None, and extend the list
|
||||
list_extension = delta_size*[None]
|
||||
self._container.extend(list_extension)
|
||||
# first check the type of the value
|
||||
check_type(value,self.get_type())
|
||||
# then check if the value is already in the array
|
||||
if self._unique:
|
||||
if value in self._container:
|
||||
raise AssertionError("UNIQUE keyword prevent inserting this instance.")
|
||||
self._container[index-self._bound_1] = value
|
||||
|
||||
class BAG(BaseType.Type, BaseType.Aggregate):
|
||||
"""
|
||||
EXPRESS definition:
|
||||
==================
|
||||
A bag data type has as its domain unordered collections of like elements. The optional lower
|
||||
and upper bounds, which are integer-valued expressions, define the minimum and maximum
|
||||
number of elements that can be held in the collection dened by a bag data type.
|
||||
|
||||
Syntax:
|
||||
170 bag_type = BAG [ bound_spec ] OF base_type .
|
||||
176 bound_spec = '[' bound_1 ':' bound_2 ']' .
|
||||
174 bound_1 = numeric_expression .
|
||||
175 bound_2 = numeric_expression .
|
||||
171 base_type = aggregation_types | simple_types | named_types .
|
||||
|
||||
Rules and restrictions:
|
||||
a) The bound_1 expression shall evaluate to an integer value greater than or equal to
|
||||
zero. It gives the lower bound, which is the minimum number of elements that can be in a
|
||||
bag value of this data type. bound_1 shall not produce the indeterminate (?) value.
|
||||
b) The bound_2 expression shall evaluate to an integer value greater than or equal to
|
||||
bound_1, or an indeterminate (?) value. It gives the upper bound, which is the maximum
|
||||
number of elements that can be in a bag value of this data type.
|
||||
If this value is indeterminate (?) the number of elements in a bag value of this data type is
|
||||
not be bounded from above.
|
||||
c) If the bound_spec is omitted, the limits are [0:?].
|
||||
EXAMPLE 29 (This example defines an attribute as a bag of point (where point is a named data
|
||||
type assumed to have been declared elsewhere).
|
||||
a_bag_of_points : BAG OF point;
|
||||
The value of the attribute named a_bag_of_points can contain zero or more points. The same
|
||||
point instance may appear more than once in the value of a_bag_of_points.
|
||||
If the value is required to contain at least one element, the specification can provide a lower bound,
|
||||
as in:
|
||||
a_bag_of_points : BAG [1:?] OF point;
|
||||
The value of the attribute named a_bag_of_points now must contain at least one point.
|
||||
|
||||
Python definition:
|
||||
==================
|
||||
@TODO
|
||||
"""
|
||||
def __init__( self , bound_1 , bound_2 , base_type , scope = None):
|
||||
BaseType.Type.__init__(self, base_type, scope)
|
||||
if not type(bound_1)==int:
|
||||
raise TypeError("LIST lower bound must be an integer")
|
||||
# bound_2 can be set to None
|
||||
self._unbounded = False
|
||||
if bound_2 == None:
|
||||
self._unbounded = True
|
||||
elif not type(bound_2)==int:
|
||||
raise TypeError("LIST upper bound must be an integer")
|
||||
if not bound_1>=0:
|
||||
raise AssertionError("LIST lower bound must be greater of equal to 0")
|
||||
if (type(bound_2)==int and not (bound_1 <= bound_2)):
|
||||
raise AssertionError("ARRAY lower bound must be less than or equal to upper bound")
|
||||
# set up class attributes
|
||||
self._bound_1 = bound_1
|
||||
self._bound_2 = bound_2
|
||||
self._container = []
|
||||
|
||||
def bound_1(self):
|
||||
return self._bound_1
|
||||
|
||||
def bound_2(self):
|
||||
return self._bound_2
|
||||
|
||||
def add(self,value):
|
||||
'''
|
||||
Adds a value to the bag
|
||||
'''
|
||||
if self._unbounded:
|
||||
check_type(value,self.get_type())
|
||||
self._container.append(value)
|
||||
else:
|
||||
# first ensure that the bag is not full
|
||||
if len(self._container) == self._bound_2 - self._bound_1 + 1:
|
||||
raise AssertionError('BAG is full. Impossible to add any more item')
|
||||
else:
|
||||
check_type(value,self.get_type())
|
||||
self._container.append(value)
|
||||
|
||||
def get_size(self):
|
||||
''' When V is a bag, list or set, the returned value is the actual number of elements in
|
||||
the aggregate value.'''
|
||||
return INTEGER(len(self._container))
|
||||
|
||||
def get_hiindex(self):
|
||||
''' When V is a bag, list or set, the returned value is the actual number of elements in
|
||||
the aggregate value.'''
|
||||
return INTEGER(len(self._container))
|
||||
|
||||
def get_loindex(self):
|
||||
return INTEGER(1)
|
||||
|
||||
def get_hibound(self):
|
||||
hibound = self._bound_2
|
||||
if type(hibound)==int:
|
||||
return INTEGER(hibound)
|
||||
else:
|
||||
return hibound
|
||||
|
||||
def get_lobound(self):
|
||||
lobound = self._bound_1
|
||||
if type(lobound)==int:
|
||||
return INTEGER(lobound)
|
||||
else:
|
||||
return lobound
|
||||
def get_value_unique(self):
|
||||
''' Return True if all items are different in the container, UNKNOWN if some items are
|
||||
indeterminate, or False otherwise'''
|
||||
if None in self._container:
|
||||
return Unknown
|
||||
if self.get_size()-len(set(self._container))>0: #some items are repeated
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
class SET(BaseType.Type, BaseType.Aggregate):
|
||||
"""
|
||||
EXPRESS definition:
|
||||
==================
|
||||
A set data type has as its domain unordered collections of like elements. The set data type is
|
||||
a specialization of the bag data type. The optional lower and upper bounds, which are integer-
|
||||
valued expressions, dene the minimum and maximum number of elements that can be held in
|
||||
the collection dened by a set data type. The collection dened by set data type shall not
|
||||
contain two or more elements which are instance equal.
|
||||
Syntax:
|
||||
285 set_type = SET [ bound_spec ] OF base_type .
|
||||
176 bound_spec = '[' bound_1 ':' bound_2 ']' .
|
||||
174 bound_1 = numeric_expression .
|
||||
175 bound_2 = numeric_expression .
|
||||
171 base_type = aggregation_types | simple_types | named_types .
|
||||
Rules and restrictions:
|
||||
a) The bound_1 expression shall evaluate to an integer value greater than or equal to
|
||||
zero. It gives the lower bound, which is the minimum number of elements that can be in a
|
||||
set value of this data type. bound_1 shall not produce the indeterminate (?) value.
|
||||
b) The bound_2 expression shall evaluate to an integer value greater than or equal to
|
||||
bound_1, or an indeterminate (?) value. It gives the upper bound, which is the maximum
|
||||
number of elements that can be in a set value of this data type.
|
||||
If this value is indeterminate (?) the number of elements in a set value of this data type is
|
||||
not be bounded from above.
|
||||
c) If the bound_spec is omitted, the limits are [0:?].
|
||||
d) Each element in an occurrence of a set data type shall be dierent from (i.e., not
|
||||
instance equal to) every other element in the same set value.
|
||||
EXAMPLE 30 { This example denes an attribute as a set of points (a named data type assumed
|
||||
to have been declared elsewhere).
|
||||
a_set_of_points : SET OF point;
|
||||
The attribute named a_set_of_points can contain zero or more points. Each point instance (in
|
||||
the set value) is required to be dierent from every other point in the set.
|
||||
If the value is required to have no more than 15 points, the specication can provide an upper bound,
|
||||
as in:
|
||||
a_set_of_points : SET [0:15] OF point;
|
||||
The value of the attribute named a_set_of_points now may contain no more than 15 points.
|
||||
|
||||
Python definition:
|
||||
==================
|
||||
The difference with the BAG class is that the base container for SET is a set object.
|
||||
"""
|
||||
def __init__( self , bound_1 , bound_2 , base_type , scope = None):
|
||||
BaseType.Type.__init__(self, base_type, scope)
|
||||
if not type(bound_1)==int:
|
||||
raise TypeError("LIST lower bound must be an integer")
|
||||
# bound_2 can be set to None
|
||||
self._unbounded = False
|
||||
if bound_2 == None:
|
||||
self._unbounded = True
|
||||
elif not type(bound_2)==int:
|
||||
raise TypeError("LIST upper bound must be an integer")
|
||||
if not bound_1>=0:
|
||||
raise AssertionError("LIST lower bound must be greater of equal to 0")
|
||||
if (type(bound_2)==int and not (bound_1 <= bound_2)):
|
||||
raise AssertionError("ARRAY lower bound must be less than or equal to upper bound")
|
||||
# set up class attributes
|
||||
self._bound_1 = bound_1
|
||||
self._bound_2 = bound_2
|
||||
self._container = set()
|
||||
|
||||
def bound_1(self):
|
||||
return self._bound_1
|
||||
|
||||
def bound_2(self):
|
||||
return self._bound_2
|
||||
|
||||
def add(self,value):
|
||||
'''
|
||||
Adds a value to the bag
|
||||
'''
|
||||
if self._unbounded:
|
||||
check_type(value,self.get_type())
|
||||
self._container.add(value)
|
||||
else:
|
||||
# first ensure that the bag is not full
|
||||
if len(self._container) == self._bound_2 - self._bound_1 + 1:
|
||||
if not value in self._container:
|
||||
raise AssertionError('SET is full. Impossible to add any more item')
|
||||
else:
|
||||
check_type(value,self.get_type())
|
||||
self._container.add(value)
|
||||
|
||||
def get_size(self):
|
||||
''' When V is a bag, list or set, the returned value is the actual number of elements in
|
||||
the aggregate value.'''
|
||||
return INTEGER(len(self._container))
|
||||
|
||||
def get_hiindex(self):
|
||||
''' When V is a bag, list or set, the returned value is the actual number of elements in
|
||||
the aggregate value.'''
|
||||
return INTEGER(len(self._container))
|
||||
|
||||
def get_loindex(self):
|
||||
return INTEGER(1)
|
||||
|
||||
def get_hibound(self):
|
||||
hibound = self._bound_2
|
||||
if type(hibound)==int:
|
||||
return INTEGER(hibound)
|
||||
else:
|
||||
return hibound
|
||||
|
||||
def get_lobound(self):
|
||||
lobound = self._bound_1
|
||||
if type(lobound)==int:
|
||||
return INTEGER(lobound)
|
||||
else:
|
||||
return lobound
|
||||
|
||||
def get_value_unique(self):
|
||||
''' Return True if all items are different in the container, UNKNOWN if some items are
|
||||
indeterminate, or False otherwise'''
|
||||
if None in self._container:
|
||||
return Unknown
|
||||
else:
|
||||
return True
|
69
src/Mod/Import/App/SCL/BaseType.py
Normal file
69
src/Mod/Import/App/SCL/BaseType.py
Normal file
|
@ -0,0 +1,69 @@
|
|||
# Copyright (c) 2011, 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.
|
||||
|
||||
class Type(object):
|
||||
'''
|
||||
A type can be defined from its name and scope
|
||||
Looking into the scope dict returns the python type class.
|
||||
This is the base class for aggregated data types or constructed data types
|
||||
'''
|
||||
def __init__(self, typedef, scope):
|
||||
self._scope = scope
|
||||
self._typedef = typedef
|
||||
|
||||
def get_scope(self):
|
||||
return self._scope
|
||||
|
||||
def get_type(self):
|
||||
if type(self._typedef) == str:
|
||||
if self._scope == None:
|
||||
raise AssertionError('No scope defined for this type')
|
||||
elif vars(self._scope).has_key(self._typedef):
|
||||
return vars(self._scope)[self._typedef]
|
||||
else:
|
||||
raise TypeError("Type '%s' is not defined in given scope"%self._typedef)
|
||||
else:
|
||||
return self._typedef
|
||||
|
||||
class Aggregate:
|
||||
'''
|
||||
This is an abstract class. ARRAY, LIST, SET and BAG inherit from this class
|
||||
'''
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
scp = sys.modules[__name__]
|
||||
class line:
|
||||
pass
|
||||
new_type = Type('lie',scp)
|
||||
print new_type.get_type()
|
||||
|
716
src/Mod/Import/App/SCL/Builtin.py
Normal file
716
src/Mod/Import/App/SCL/Builtin.py
Normal file
|
@ -0,0 +1,716 @@
|
|||
# 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 specication of a bag,
|
||||
#list or set. This usage represents the notion that the size of the aggregate value dened 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 - sSELF 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 insucient 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 ) 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 qualied names of the roles
|
||||
#played by the specied entity instance. A fully qualied name is dened to be the name of the
|
||||
#attribute qualied 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 qualied names of the
|
||||
#attributes of the entity instances which use the instance V.
|
||||
#When a named data type is use'd or reference'd, 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 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.) < 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 qualied by the name of the schema which contains the denition 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 dierent subtypes or specializations of a given type have to be
|
||||
#treated dierently 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 qualied by the name of the schema which
|
||||
#contains the denition 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 specied entity instance in a
|
||||
#specied 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("VALULE function takes a NUMBER parameter")
|
||||
# first try to instanciate an INTEGER from the string:
|
||||
try:
|
||||
return INTEGER(V)
|
||||
except:
|
||||
pass #not possible, try to cast to REAL
|
||||
try:
|
||||
return REAL(V)
|
||||
except:
|
||||
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 et 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 tht each point is a set is at a dierent position, (by
|
||||
#denition 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()
|
||||
|
||||
|
139
src/Mod/Import/App/SCL/ConstructedDataTypes.py
Normal file
139
src/Mod/Import/App/SCL/ConstructedDataTypes.py
Normal file
|
@ -0,0 +1,139 @@
|
|||
# Copyright (c) 2011, 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.
|
||||
|
||||
import sys
|
||||
import BaseType
|
||||
|
||||
class EnumerationId(object):
|
||||
"""
|
||||
EXPRESS definition:
|
||||
===================
|
||||
An enumeration data type has as its domain an ordered set of names. The names represent
|
||||
values of the enumeration data type. These names are designated by enumeration_ids and are
|
||||
referred to as enumeration items.
|
||||
"""
|
||||
pass
|
||||
|
||||
class ENUMERATION(object):
|
||||
"""
|
||||
EXPRESS definition:
|
||||
===================
|
||||
An ENUMERATION data type has as its domain an ordered set of names. The names represent
|
||||
values of the enumeration data type.
|
||||
|
||||
Python implementation:
|
||||
======================
|
||||
An enumeration is initialized from strings defining the types.
|
||||
For instance, some EXPRESS definition:
|
||||
TYPE ahead_or_behind = ENUMERATION OF
|
||||
(ahead,
|
||||
behind);
|
||||
END_TYPE; -- ahead_or_behind
|
||||
|
||||
is implemented in python with the line:
|
||||
>>> ahead_of_behind = ENUMERATION('ahead','behind', the_current_scope)
|
||||
>>> ahead_or_behind.ahead
|
||||
>>> ahead_of_behind.behind
|
||||
|
||||
And, if and only if ahead and/or behind are not in scope (e.g. they are not entity names,
|
||||
and/or many enums define the same enumeration identifier):
|
||||
>>> ahead
|
||||
>>> behind
|
||||
"""
|
||||
def __init__(self,*kargs,**args):
|
||||
# first defining the scope
|
||||
if args.has_key('scope'):
|
||||
self._scope = args['scope']
|
||||
else:
|
||||
self._scope = None
|
||||
# store passed enum identifiers
|
||||
self._enum_id_names = list(kargs)
|
||||
self._enum_ids = []
|
||||
# we create enums id from names, and create attributes
|
||||
# for instance, from the identifier name 'ahead',
|
||||
# we create an attribute ahead with which is a new
|
||||
# instance of EnumerationId
|
||||
for enum_id_name in self._enum_id_names:
|
||||
setattr(self,enum_id_name,EnumerationId())
|
||||
# we store this new attributes to the enum_ids list, which
|
||||
# will be accessed by the type checker with the get_enum_ids method
|
||||
self._enum_ids.append(self.__getattribute__(enum_id_name))
|
||||
#
|
||||
# Then we check if the enums names can be added to the current scope:
|
||||
# if the name is already in the scope, then another enums id or select
|
||||
# has the same name -> we do nothing, enums will be called
|
||||
# with ahead_of_behind.ahead or ahead_or_behind.behind.
|
||||
# otherwise, they can be called as only ahead or behind
|
||||
# Note: since ENUMERATIONS are defined *before* entities, if an entity
|
||||
# has the same name as an enum id, it will replace it in the current scope.
|
||||
#
|
||||
for enum_id_name in self._enum_id_names:
|
||||
if not vars(self._scope).has_key(enum_id_name):
|
||||
vars(self._scope)[enum_id_name] = self.__getattribute__(enum_id_name)
|
||||
|
||||
def get_enum_ids(self):
|
||||
return self._enum_ids
|
||||
|
||||
class SELECT(object):
|
||||
""" A select data type has as its domain the union of the domains of the named data types in
|
||||
its select list. The select data type is a generalization of each of the named data types in its
|
||||
select list.
|
||||
"""
|
||||
def __init__(self,*kargs,**args):
|
||||
# first defining the scope
|
||||
if args.has_key('scope'):
|
||||
self._scope = args['scope']
|
||||
else:
|
||||
self._scope = None
|
||||
# create the types from the list of arguments
|
||||
self._base_types = []
|
||||
for types in list(kargs):
|
||||
new_type = BaseType.Type(types,self._scope)
|
||||
self._base_types.append(new_type)
|
||||
|
||||
def get_allowed_types(self):
|
||||
_auth_types = []
|
||||
for types in self._base_types:
|
||||
_auth_types.append(types.get_type())
|
||||
return _auth_types
|
||||
|
||||
def get_allowed_basic_types(self):
|
||||
''' if a select contains some subselect, goes down through the different
|
||||
sublayers untill there is no more '''
|
||||
b = []
|
||||
_auth_types = self.get_allowed_types()
|
||||
for _auth_type in _auth_types:
|
||||
if isinstance(_auth_type,SELECT) or isinstance(_auth_type,ENUMERATION):
|
||||
h = _auth_type.get_allowed_types()
|
||||
b.extend(h)
|
||||
else:
|
||||
b = _auth_types
|
||||
return b
|
55
src/Mod/Import/App/SCL/Model.py
Normal file
55
src/Mod/Import/App/SCL/Model.py
Normal file
|
@ -0,0 +1,55 @@
|
|||
# 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.
|
||||
|
||||
class Model(objet):
|
||||
""" The container for entity instances
|
||||
"""
|
||||
def __init_(self):
|
||||
print "Model initialized"
|
||||
self._instances = []
|
||||
|
||||
def add_instance(self, entity_instance):
|
||||
self._instances.append(entity_instance)
|
||||
|
||||
def remove_instance(self, entity_instance):
|
||||
self._instances.remove(entity_instance)
|
||||
|
||||
def get_instances(self):
|
||||
return self._instances
|
||||
|
||||
def export_to_p21file(self, filename):
|
||||
raise AssertionError("Not implemented")
|
||||
|
||||
def export_to_p28file(self, filename):
|
||||
raise AssertionError("Not implemented")
|
||||
|
||||
|
||||
|
209
src/Mod/Import/App/SCL/Part21.py
Normal file
209
src/Mod/Import/App/SCL/Part21.py
Normal file
|
@ -0,0 +1,209 @@
|
|||
# Copyright (c) 2011, 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.
|
||||
|
||||
import re
|
||||
import Utils
|
||||
import time
|
||||
|
||||
|
||||
INSTANCE_DEFINITION_RE = re.compile("#(\d+)[^\S\n]?=[^\S\n]?(.*?)\((.*)\)[^\S\n]?;[\\r]?$")
|
||||
|
||||
def map_string_to_num(stri):
|
||||
""" Take a string, check wether it is an integer, a float or not
|
||||
"""
|
||||
if ('.' in stri) or ('E' in stri): #it's definitely a float
|
||||
return REAL(stri)
|
||||
else:
|
||||
return INTEGER(stri)
|
||||
|
||||
class Model:
|
||||
"""
|
||||
A model contains a list of instances
|
||||
"""
|
||||
def __init__(self,name):
|
||||
self._name = name
|
||||
# a dict of instances
|
||||
# each time an instance is added to the model, count is incremented
|
||||
self._instances = {}
|
||||
self._number_of_instances = 0
|
||||
|
||||
def add_instance(self, instance):
|
||||
'''
|
||||
Adds an instance to the model
|
||||
'''
|
||||
self._number_of_instances += 1
|
||||
self._instances[self._number_of_instances-1] = instance
|
||||
|
||||
def print_instances(self):
|
||||
'''
|
||||
Dump instances to stdout
|
||||
'''
|
||||
for idx in range(self._number_of_instances):
|
||||
"=========="
|
||||
print "Instance #%i"%(idx+1)
|
||||
print self._instances[idx]
|
||||
|
||||
class Part21EntityInstance:
|
||||
"""
|
||||
A class to represent a Part21 instance as defined in one Part21 file
|
||||
A Part21EntityInstance is defined by the following arguments:
|
||||
entity_name: a string
|
||||
entity_attributes: a list of strings to represent an attribute.
|
||||
For instance, the following expression:
|
||||
#4 = PRODUCT_DEFINITION_SHAPE('$','$',#5);
|
||||
will result in :
|
||||
entity : <class 'config_control_design.product_definition_shape'>
|
||||
entity_instance_attributes: ['$','$','#5']
|
||||
"""
|
||||
def __init__(self,entity_name,attributes):
|
||||
self._entity
|
||||
self._attributes_definition = attributes
|
||||
print self._entity_name
|
||||
print self._attributes_definition
|
||||
|
||||
|
||||
class Part21Parser:
|
||||
"""
|
||||
Loads all instances definition of a Part21 file into memory.
|
||||
Two dicts are created:
|
||||
self._instance_definition : stores attibutes, key is the instance integer id
|
||||
self._number_of_ancestors : stores the number of ancestors of entity id. This enables
|
||||
to define the order of instances creation.
|
||||
"""
|
||||
def __init__(self, filename):
|
||||
self._filename = filename
|
||||
# the schema
|
||||
self._schema_name = ""
|
||||
# the dict self._instances contain instance definition
|
||||
self._instances_definition = {}
|
||||
# this dict contains lists of 0 ancestors, 1 ancestor, etc.
|
||||
# initializes this dict
|
||||
self._number_of_ancestors = {}
|
||||
for i in range(2000):
|
||||
self._number_of_ancestors[i]=[]
|
||||
self.parse_file()
|
||||
# reduce number_of_ancestors dict
|
||||
for item in self._number_of_ancestors.keys():
|
||||
if len(self._number_of_ancestors[item])==0:
|
||||
del self._number_of_ancestors[item]
|
||||
|
||||
def get_schema_name(self):
|
||||
return self._schema_name
|
||||
print schema_name
|
||||
|
||||
def get_number_of_instances(self):
|
||||
return len(self._instances_definition.keys())
|
||||
|
||||
def parse_file(self):
|
||||
init_time = time.time()
|
||||
print "Parsing file %s..."%self._filename,
|
||||
fp = open(self._filename)
|
||||
while True:
|
||||
line = fp.readline()
|
||||
if not line:
|
||||
break
|
||||
# there may be a multline definition. In this case, we read lines untill we found
|
||||
# a ;
|
||||
#while (not line.endswith(";\r\n")): #its a multiline
|
||||
# line = line.replace("\r\n","") + fp.readline()
|
||||
# parse line
|
||||
match_instance_definition = INSTANCE_DEFINITION_RE.search(line) # id,name,attrs
|
||||
if match_instance_definition:
|
||||
instance_id, entity_name, entity_attrs = match_instance_definition.groups()
|
||||
instance_int_id = int(instance_id)
|
||||
# find number of ancestors
|
||||
number_of_ancestors = entity_attrs.count('#')
|
||||
# fill number of ancestors dict
|
||||
self._number_of_ancestors[number_of_ancestors].append(instance_int_id)
|
||||
# parse attributes string
|
||||
entity_attrs_list, str_len = Utils.process_nested_parent_str(entity_attrs)
|
||||
# then finally append this instance to the disct instance
|
||||
self._instances_definition[instance_int_id] = (entity_name,entity_attrs_list)
|
||||
else: #does not match with entity instance definition, parse the header
|
||||
if line.startswith('FILE_SCHEMA'):
|
||||
#identify the schema name
|
||||
self._schema_name = line.split("'")[1].split("'")[0].split(" ")[0].lower()
|
||||
fp.close()
|
||||
print 'done in %fs.'%(time.time()-init_time)
|
||||
print 'schema: - %s entities %i'%(self._schema_name,len(self._instances_definition.keys()))
|
||||
|
||||
class EntityInstancesFactory(object):
|
||||
'''
|
||||
This class creates entity instances from the str definition
|
||||
For instance, the definition:
|
||||
20: ('CARTESIAN_POINT', ["''", '(5.,125.,20.)'])
|
||||
will result in:
|
||||
p = ARRAY(1,3,REAL)
|
||||
p.[1] = REAL(5)
|
||||
p.[2] = REAL(125)
|
||||
p.[3] = REAL(20)
|
||||
new_instance = cartesian_point(STRING(''),p)
|
||||
'''
|
||||
def __init__(self, schema_name, instance_definition):
|
||||
# First try to import the schema module
|
||||
pass
|
||||
|
||||
class Part21Population(object):
|
||||
def __init__(self, part21_loader):
|
||||
""" Take a part21_loader a tries to create entities
|
||||
"""
|
||||
self._part21_loader = part21_loader
|
||||
self._aggregate_scope = []
|
||||
self._aggr_scope = False
|
||||
self.create_entity_instances()
|
||||
|
||||
def create_entity_instances(self):
|
||||
""" Starts entity instances creation
|
||||
"""
|
||||
for number_of_ancestor in self._part21_loader._number_of_ancestors.keys():
|
||||
for entity_definition_id in self._part21_loader._number_of_ancestors[number_of_ancestor]:
|
||||
self.create_entity_instance(entity_definition_id)
|
||||
|
||||
def create_entity_instance(self, instance_id):
|
||||
instance_definition = self._part21_loader._instances_definition[instance_id]
|
||||
print "Instance definition to process",instance_definition
|
||||
# first find class name
|
||||
class_name = instance_definition[0].lower()
|
||||
print "Class name:%s"%class_name
|
||||
object_ = globals()[class_name]
|
||||
# then attributes
|
||||
#print object_.__doc__
|
||||
instance_attributes = instance_definition[1]
|
||||
print "instance_attributes:",instance_attributes
|
||||
a = object_(*instance_attributes)
|
||||
|
||||
if __name__ == "__main__":
|
||||
import time
|
||||
import sys
|
||||
from config_control_design import *
|
||||
p21loader = Part21Parser("gasket1.p21")
|
||||
print "Creating instances"
|
||||
p21population = Part21Population(p21loader)
|
39
src/Mod/Import/App/SCL/Rules.py
Normal file
39
src/Mod/Import/App/SCL/Rules.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
# 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 rules"
|
||||
|
||||
class Rule(object):
|
||||
'''
|
||||
This class describes a RULE
|
||||
@TODO: to be implemented
|
||||
'''
|
||||
pass
|
44
src/Mod/Import/App/SCL/SCLBase.py
Normal file
44
src/Mod/Import/App/SCL/SCLBase.py
Normal file
|
@ -0,0 +1,44 @@
|
|||
# Copyright (c) 2011, 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.
|
||||
|
||||
class BaseEntityClass(object):
|
||||
""" A class that allows advanced __repr__ features for entity instances
|
||||
"""
|
||||
def __repr__(self):
|
||||
""" Displays attribute with their values
|
||||
"""
|
||||
doc_string = "# %s class description:\n%s\n# Instance attributes:\n"%(self.__class__,self.__doc__)
|
||||
# write each argument with its value
|
||||
properties = dir(self)
|
||||
for elem in properties:
|
||||
if not elem.startswith("_"):
|
||||
doc_string += "\t%s:%s\n"%(elem,self.__getattribute__(elem))
|
||||
return doc_string
|
216
src/Mod/Import/App/SCL/SimpleDataTypes.py
Normal file
216
src/Mod/Import/App/SCL/SimpleDataTypes.py
Normal file
|
@ -0,0 +1,216 @@
|
|||
# Copyright (c) 2011, 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.
|
||||
|
||||
"""
|
||||
Docstrings are courtesy of ISO 10303-11:1994(E)
|
||||
"""
|
||||
|
||||
class NUMBER:
|
||||
"""
|
||||
EXPRESS definition:
|
||||
===================
|
||||
The number data type has as its domain all numeric values in the language. The number data
|
||||
type shall be used when a more specic numeric representation is not important.
|
||||
Syntax:
|
||||
248 number_type = NUMBER .
|
||||
EXAMPLE 15 - Since we may not know the context of size we do not know how to correctly
|
||||
represent it, e.g. the size of the crowd at a football game would be an integer, whereas the area
|
||||
of the pitch would be a real.
|
||||
size : NUMBER ;
|
||||
|
||||
Python definition:
|
||||
==================
|
||||
class NUMBER is an abstract class, aimed at being specialized.
|
||||
"""
|
||||
pass
|
||||
|
||||
class REAL(float,NUMBER):
|
||||
"""
|
||||
EXPRESS definition:
|
||||
===================
|
||||
The real data type has as its domain all rational, irrational and scientfic real numbers. It is
|
||||
a specialization of the number data type.
|
||||
Syntax:
|
||||
265 real_type = REAL [ '(' precision_spec ')' ] .
|
||||
255 precision_spec = numeric_expression .
|
||||
Rational and irrational numbers have infnite resolution and are exact. Scientific numbers rep-
|
||||
resent quantities which are known only to a specified precision. The precision_spec is stated
|
||||
in terms of significant digits.
|
||||
A real number literal is represented by a mantissa and optional exponent. The number of digits
|
||||
making up the mantissa when all leading zeros have been removed is the number of significant
|
||||
digits. The known precision of a value is the number of leading digits that are necessary to the
|
||||
application.
|
||||
Rules and restrictions:
|
||||
a) The precision_spec gives the minimum number of digits of resolution that are re-
|
||||
quired. This expression shall evaluate to a positive integer value.
|
||||
b) When no resolution specification is given the precision of the real number is uncon-
|
||||
strained.
|
||||
|
||||
Note 9.2.6:
|
||||
integer and real are both specializations of number;
|
||||
|
||||
Python definition:
|
||||
==================
|
||||
REAL both inherits from float and NUMBER
|
||||
"""
|
||||
pass
|
||||
|
||||
class INTEGER(int,NUMBER):
|
||||
"""
|
||||
EXPRESS definition:
|
||||
===================
|
||||
The integer data type has as its domain all integer numbers. It is a specialization of the real
|
||||
data type.
|
||||
Syntax:
|
||||
227 integer_type = INTEGER .
|
||||
EXAMPLE 16 - This example uses an integer data type to represent an attribute named nodes.
|
||||
The domain of this attribute is all integers, with no further constraint.
|
||||
ENTITY foo;
|
||||
nodes : INTEGER;
|
||||
END_ENTITY;
|
||||
|
||||
Note 9.2.6: integer and real are both specializations of number;
|
||||
|
||||
Python definition:
|
||||
==================
|
||||
INTEGER both inherits from int and NUMBER
|
||||
|
||||
@TODO: note 9.2.6 tells that integer is a specialization of real
|
||||
"""
|
||||
pass
|
||||
|
||||
class STRING(str):
|
||||
"""
|
||||
The string data type has as its domain sequences of characters. The characters which are
|
||||
permitted to form part of a string value are dened in ISO 10646.
|
||||
Syntax:
|
||||
293 string_type = STRING [ width_spec ] .
|
||||
318 width_spec = '(' width ')' [ FIXED ] .
|
||||
317 width = numeric_expression .
|
||||
A string data type may be dened as either xed or varying width (number of characters). If
|
||||
it is not specfically defined as fixed width (by using the fixed reserved word in the dfinition)
|
||||
the string has varying width.
|
||||
|
||||
The domain of a xed width string data type is the set of all character sequences of exactly
|
||||
the width specied in the type denition.
|
||||
The domain of a varying width string data type is the set of all character sequences of width
|
||||
less than or equal to the maximum width specied in the type denition.
|
||||
If no width is specied, the domain is the set of all character sequences, with no constraint on
|
||||
the width of these sequences.
|
||||
Substrings and individual characters may be addressed using subscripts as described in 12.5.
|
||||
The case (upper or lower) of letters within a string is signicant.
|
||||
|
||||
Python mapping: INTEGER is mapped the 'str' type. An additional width_spec parameter can be passed
|
||||
to handle the FIXED length constraint
|
||||
"""
|
||||
pass
|
||||
|
||||
class LOGICAL:
|
||||
"""
|
||||
The logical data type has as its domain the three literals true, false and unknown.
|
||||
Syntax:
|
||||
243 logical_type = LOGICAL .
|
||||
The following ordering holds for the values of the logical data type: false < unknown <
|
||||
true. The logical data type is compatible with the boolean data type, except that the value
|
||||
unknown cannot be assigned to a boolean variable.
|
||||
"""
|
||||
pass
|
||||
Unknown = LOGICAL()
|
||||
|
||||
#
|
||||
#The boolean data type has as its domain the two literals true and false. The boolean data
|
||||
#type is a specialization of the logical data type.
|
||||
#
|
||||
#Python mapping: BOOLEAN is mapped to 'bool' type
|
||||
#
|
||||
# The bool data type can't however be subclassed in Python (see
|
||||
# See http://mail.python.org/pipermail/python-dev/2002-March/020822.html)
|
||||
# so it is just set to bool
|
||||
BOOLEAN = bool
|
||||
|
||||
class BINARY(str):
|
||||
"""
|
||||
The binary data type has as its domain sequences of bits, each bit being represented by 0 or 1.
|
||||
Syntax:
|
||||
172 binary_type = BINARY [ width_spec ] .
|
||||
318 width_spec = '(' width ')' [ FIXED ] .
|
||||
317 width = numeric_expression .
|
||||
A binary data type may be defined as either fixed or varying width (number of bits). If it is
|
||||
not specifically defined as fixed width (by using the fixed reserved word in the definition) the
|
||||
binary data type has varying width.
|
||||
The domain of a fixed width binary data type is the set of all bit sequences of exactly the width
|
||||
specied in the type definition.
|
||||
The domain of a varying width binary data type is the set of all bit sequences of width less
|
||||
than or equal to the maximum width specied in the type denition. If no width is specified,
|
||||
the domain is the set of all bit sequences, with no constraint on the width of these sequences.
|
||||
Subbinaries and individual bits may be addressed using subscripts as described in 12.3.
|
||||
|
||||
Python mapping: BINARY is mapped to the 'str' type. A check is performed to validate it is a binary
|
||||
string representing a number.
|
||||
"""
|
||||
def __new__(self, value, width=-1, fixed=False):
|
||||
return str.__new__(self, value)
|
||||
|
||||
def __init__(self, value, width=-1, fixed=False):
|
||||
""" By default, lenght is set to None"""
|
||||
self._specified_width = width
|
||||
self._fixed = fixed
|
||||
# Check implicit width
|
||||
if (width!=-1) and not fixed:
|
||||
raise ValueError("The 'width' parameter is passed but 'fixed' is still false. Please explicitely set 'fixed' to True to avoid implicit declaration")
|
||||
# First check the string length if 'fixed' is set to True
|
||||
if fixed:
|
||||
if len(value) != width:
|
||||
raise ValueError("The BINARY width %i is not consistent with the 'width' declaration(%i)"%(len(value),width))
|
||||
# Check that the value passed is actually a binary
|
||||
try:
|
||||
int(value,2)
|
||||
except ValueError:
|
||||
raise ValueError("%s is not a binary"%value)
|
||||
|
||||
|
||||
if __name__=="__main__":
|
||||
print "Creating REAL from float value"
|
||||
a = REAL(1.5)
|
||||
print a*2
|
||||
print "Creating REAL from string value"
|
||||
a = REAL("1.2")
|
||||
print a*3
|
||||
print "Creating INTEGER from int value"
|
||||
b = INTEGER(2)
|
||||
c = INTEGER(3)
|
||||
print b+c
|
||||
print "Creating INTEGER from string value"
|
||||
e = INTEGER("5")
|
||||
f = INTEGER("8")
|
||||
print e*f
|
||||
|
||||
|
101
src/Mod/Import/App/SCL/TypeChecker.py
Normal file
101
src/Mod/Import/App/SCL/TypeChecker.py
Normal file
|
@ -0,0 +1,101 @@
|
|||
# Copyright (c) 2011, 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.
|
||||
|
||||
from ConstructedDataTypes import ENUMERATION, SELECT
|
||||
import BaseType
|
||||
|
||||
RAISE_EXCEPTION_IF_TYPE_DOES_NOT_MATCH = True
|
||||
DEBUG = False
|
||||
|
||||
def cast_python_object_to_aggregate(obj, aggregate):
|
||||
""" This function casts a python object to an aggregate type. For instance:
|
||||
[1.,2.,3.]-> ARRAY(1,3,REAL)"""
|
||||
aggregate_lower_bound = aggregate.bound_1()
|
||||
aggregate_upper_bound = aggregate.bound_2()
|
||||
if type(obj)==list:
|
||||
for idx in range(aggregate_lower_bound,aggregate_upper_bound+1):
|
||||
aggregate[idx] = obj[idx-aggregate_lower_bound]
|
||||
return aggregate
|
||||
|
||||
def check_type(instance, expected_type):
|
||||
""" This function checks wether an object is an instance of a given class
|
||||
returns False or True
|
||||
"""
|
||||
type_match = False #by default, will be set to True if any match
|
||||
if DEBUG:
|
||||
print "==="
|
||||
print "Instance passed: ",instance
|
||||
print "Expected type: ", expected_type
|
||||
# in the case of an enumeration, we have to check if the instance is in the list
|
||||
if (isinstance(expected_type,ENUMERATION)):
|
||||
allowed_ids = expected_type.get_enum_ids()
|
||||
if instance in allowed_ids:
|
||||
type_match = True
|
||||
else:
|
||||
raise TypeError('Enumeration ids must be %s ( passed %s)'%(allowed_ids,type(instance)))
|
||||
elif (isinstance(expected_type,SELECT)):
|
||||
# we check if the instance is of the type of any of the types that are in the SELECT
|
||||
allowed_types = expected_type.get_allowed_basic_types()
|
||||
for allowed_type in allowed_types:
|
||||
if isinstance(instance,allowed_type):
|
||||
type_match = True
|
||||
if not type_match:
|
||||
if RAISE_EXCEPTION_IF_TYPE_DOES_NOT_MATCH:
|
||||
raise TypeError('Argument type must be %s (you passed %s)'%(allowed_types,type(instance)))
|
||||
else:
|
||||
print "WARNING: expected '%s' but passed a '%s', casting from python value to EXPRESS type"%(allowed_types, type(instance))
|
||||
return False
|
||||
elif (isinstance(expected_type, BaseType.Aggregate)):
|
||||
# first check that they are instance of the same class
|
||||
if not (type(instance) == type(expected_type)):
|
||||
raise TypeError('Expected %s but passed %s'%(type(expected_type),type(instance)))
|
||||
# then check that the base type is the same
|
||||
elif not (instance.get_type() == expected_type.get_type()):
|
||||
#print instance.get_type()
|
||||
#print expected_type.get_type()
|
||||
raise TypeError('Expected %s:%s base type but passed %s:%s base type'%(type(expected_type),expected_type.get_type(),type(instance), instance.get_type()))
|
||||
# check optional and unique attributes
|
||||
#elif not (instance._unique == expected_type._unique):
|
||||
# raise TypeError('Aggregate expects UNIQUE:%s property but passed UNIQUE:%s'%(expected_type._unique, instance._unique))
|
||||
#elif not (instance._optional == expected_type._optional):
|
||||
# raise TypeError('Aggregate expects OPTIONAL:%s property but passed OPTIONAL:%s'%(expected_type._optional, instance._optional))
|
||||
# @TODO: check aggregate bounds
|
||||
else:
|
||||
type_match = True
|
||||
else: # simple data types
|
||||
type_match = isinstance(instance,expected_type)
|
||||
if not type_match:
|
||||
if RAISE_EXCEPTION_IF_TYPE_DOES_NOT_MATCH:
|
||||
raise TypeError('Argument type must be %s (you passed %s)'%(expected_type,type(instance)))
|
||||
else:
|
||||
print "WARNING: expected '%s' but passed a '%s', casting from python value to EXPRESS type"%(expected_type, type(instance))
|
||||
return False
|
||||
return True
|
70
src/Mod/Import/App/SCL/Utils.py
Normal file
70
src/Mod/Import/App/SCL/Utils.py
Normal file
|
@ -0,0 +1,70 @@
|
|||
# Copyright (c) 2011, 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.
|
||||
|
||||
''' This module provide string utils'''
|
||||
|
||||
def process_nested_parent_str(attr_str,idx=0):
|
||||
'''
|
||||
The first letter should be a parenthesis
|
||||
input string: "(1,4,(5,6),7)"
|
||||
output: ['1','4',['5','6'],'7']
|
||||
'''
|
||||
params = []
|
||||
current_param = ''
|
||||
k = 0
|
||||
while (k<len(attr_str)):
|
||||
ch = attr_str[k]
|
||||
k += 1
|
||||
if ch==',':
|
||||
params.append(current_param)
|
||||
current_param = ''
|
||||
elif ch=='(':
|
||||
nv = attr_str[k:]
|
||||
current_param, progress = process_nested_parent_str(nv)
|
||||
params.append(current_param)
|
||||
current_param = ''
|
||||
k += progress+1
|
||||
elif ch==')':
|
||||
params.append(current_param)
|
||||
return params,k
|
||||
else:
|
||||
current_param += ch
|
||||
params.append(current_param)
|
||||
return params,k
|
||||
|
||||
if __name__=="__main__":
|
||||
print process_nested_parent_str2("'A'")[0]
|
||||
print process_nested_parent_str2("30.0,0.0,5.0")[0]
|
||||
print process_nested_parent_str2("1,2,(3,4,5),6,7,8")[0]
|
||||
print process_nested_parent_str2("(#9149,#9166),#9142,.T.")[0]
|
||||
|
||||
|
||||
|
1
src/Mod/Import/App/SCL/__init__.py
Normal file
1
src/Mod/Import/App/SCL/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
__all__ = ['SCLBase','SimpleDataTypes','AggregationDataTypes','TypeChecker','ConstructedDataTypes','Expr','Part21']
|
74
src/Mod/Import/App/SCL/essa_par.py
Normal file
74
src/Mod/Import/App/SCL/essa_par.py
Normal file
|
@ -0,0 +1,74 @@
|
|||
def process_nested_parent_str(attr_str):
|
||||
'''
|
||||
The first letter should be a parenthesis
|
||||
input string: "(1,4,(5,6),7)"
|
||||
output: tuple (1,4,(4,6),7)
|
||||
'''
|
||||
params = []
|
||||
agg_scope_level = 0
|
||||
current_param = ''
|
||||
for i,ch in enumerate(attr_str):
|
||||
if ch==',':
|
||||
params.append(current_param)
|
||||
current_param = ''
|
||||
elif ch=='(':
|
||||
agg_scope_level +=1
|
||||
elif ch==')':
|
||||
agg_scope_level = 0
|
||||
elif agg_scope_level == 0:
|
||||
current_param += ch
|
||||
return params
|
||||
|
||||
def process_nested_parent_str2(attr_str,idx=0):
|
||||
'''
|
||||
The first letter should be a parenthesis
|
||||
input string: "(1,4,(5,6),7)"
|
||||
output: ['1','4',['5','6'],'7']
|
||||
'''
|
||||
#print 'Entering function with string %s'%(attr_str)
|
||||
params = []
|
||||
current_param = ''
|
||||
k = 0
|
||||
while (k<len(attr_str)):
|
||||
#print 'k in this function:%i'%k
|
||||
ch = attr_str[k]
|
||||
k += 1
|
||||
if ch==',':
|
||||
#print "Add param:",current_param
|
||||
params.append(current_param)
|
||||
current_param = ''
|
||||
elif ch=='(':
|
||||
nv = attr_str[k:]
|
||||
#print "Up one level parenthesis:%s"%(nv)
|
||||
current_param, progress = process_nested_parent_str2(nv)
|
||||
#print "Adding the list returned from nested",current_param
|
||||
params.append(current_param)
|
||||
current_param = ''
|
||||
k += progress+1
|
||||
elif ch==')':
|
||||
#print "Down one level parenthesis: %i caracters parsed"%k
|
||||
params.append(current_param)
|
||||
#print "Current params:",params#k -= acc-2
|
||||
return params,k
|
||||
else:
|
||||
current_param += ch
|
||||
#print "Ch:",ch
|
||||
#print "k:",k
|
||||
|
||||
#raw_input("")
|
||||
#idx += 1
|
||||
|
||||
params.append(current_param)
|
||||
return params,k
|
||||
#print process_nested_parent_str2('1,2,3,4,5,6')
|
||||
#idx=0
|
||||
#print process_nested_parent_str2("'A','B','C'")
|
||||
print process_nested_parent_str2("'A'")[0]
|
||||
print process_nested_parent_str2("30.0,0.0,5.0")[0]
|
||||
print process_nested_parent_str2("(Thomas)")[0]
|
||||
print process_nested_parent_str2("Thomas, Paviot, ouais")[0]
|
||||
print process_nested_parent_str2("1,2,(3,4,5),6,7,8")[0]
|
||||
print process_nested_parent_str2("(#9149,#9166),#9142,.T.")[0]
|
||||
|
||||
|
||||
|
44542
src/Mod/Import/App/automotive_design.py
Normal file
44542
src/Mod/Import/App/automotive_design.py
Normal file
File diff suppressed because it is too large
Load Diff
37012
src/Mod/Import/App/ifc2x3.py
Normal file
37012
src/Mod/Import/App/ifc2x3.py
Normal file
File diff suppressed because it is too large
Load Diff
43883
src/Mod/Import/App/ifc4.py
Normal file
43883
src/Mod/Import/App/ifc4.py
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -25,8 +25,12 @@ ADD_CUSTOM_TARGET(Material ALL
|
|||
SOURCES ${all_files}
|
||||
)
|
||||
|
||||
fc_copy_sources(Material "${CMAKE_BINARY_DIR}/Mod/Material" ${all_files})
|
||||
#fc_copy_sources(Material "${CMAKE_BINARY_DIR}/Mod/Material" ${Material_SRCS})
|
||||
|
||||
fc_target_copy_resource(Material
|
||||
${CMAKE_SOURCE_DIR}/src/Mod/Material
|
||||
${CMAKE_BINARY_DIR}/Mod/Material
|
||||
${Material_SRCS})
|
||||
|
||||
fc_target_copy_resource(Material
|
||||
${CMAKE_SOURCE_DIR}/src/Mod/Material
|
||||
|
|
Loading…
Reference in New Issue
Block a user