1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
8 * Shapes is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2008, 2013, 2014 Henrik Tidefelt
21 #include "shapestypes.h"
22 #include "shapesexceptions.h"
25 #include "angleselect.h"
28 #include "elementarycoords.h"
30 #include "singlelistrange.h"
31 #include "continuations.h"
32 #include "methodbase.h"
37 using namespace Shapes
;
41 Lang::Symbol::NameTableType
Lang::Symbol::nameTable
;
42 Lang::Symbol::ReverseTableType
Lang::Symbol::reverseTable
;
43 int Lang::Symbol::nextUnique
= -1;
45 /* The following global variables used to be in globals.cc, but now they are here to ensure they get initialized after the static variables in Lang::Symbol.
47 RefCountPtr
< const Lang::Symbol
> Kernel::THE_NAVIGATION_SYMBOL( ".navigation" ); /* Note that the leading dot puts this symbol aside all user-symbols. */
48 RefCountPtr
< const Lang::Symbol
> Kernel::THE_ANNOTATION_SYMBOL( ".annotation" ); /* Note that the leading dot puts this symbol aside all user-symbols. */
50 Lang::Symbol::Symbol( )
56 DISPATCHIMPL( Symbol
);
58 Lang::Symbol::Symbol( int key
)
62 throw Exceptions::InternalError( "Only the key 0 may be used when creating symbols with a given key." );
67 Lang::Symbol::Symbol( const char * name
)
69 NameTableType::const_iterator i
= nameTable
.find( name
);
70 if( i
!= nameTable
.end( ) )
76 const char * nameCopy
= strdup( name
);
77 key_
= nameTable
.size( ) + 1;
78 nameTable
[ nameCopy
] = key_
;
79 reverseTable
.insert( ReverseTableType::value_type( key_
, RefCountPtr
< const char >( nameCopy
) ) );
84 Lang::Symbol::operator == ( const Symbol
& other
) const
86 return key_
== other
.key_
;
90 Lang::Symbol::operator != ( const Symbol
& other
) const
92 return key_
!= other
.key_
;
96 Lang::Symbol::operator < ( const Symbol
& other
) const
98 return key_
< other
.key_
;
102 Lang::Symbol::operator > ( const Symbol
& other
) const
104 return key_
> other
.key_
;
108 Lang::Symbol::operator <= ( const Symbol
& other
) const
110 return key_
<= other
.key_
;
114 Lang::Symbol::operator >= ( const Symbol
& other
) const
116 return key_
>= other
.key_
;
120 Lang::Symbol::isUnique( ) const
125 RefCountPtr
< const char >
126 Lang::Symbol::name( ) const
130 ReverseTableType::const_iterator i
= reverseTable
.find( key_
);
131 if( i
== reverseTable
.end( ) )
133 throw Exceptions::InternalError( "The reverse symbol table did not include the sought key." );
139 return strrefdup( "<unique>" );
141 return strrefdup( "<dummy>" );
144 RefCountPtr
< const char >
145 Lang::Symbol::nameFromKey( KeyType key
)
149 throw Exceptions::MiscellaneousRequirement( "It is forbidden to ask for the name of a unique symbol." );
151 ReverseTableType::const_iterator i
= reverseTable
.find( key
);
152 if( i
== reverseTable
.end( ) )
154 throw Exceptions::InternalError( "The reverse symbol table did not include the sought key." );
160 RefCountPtr
< const Lang::Class
> Lang::Symbol::TypeID( new Lang::SystemFinalClass( strrefdup( "Symbol" ) ) );
161 TYPEINFOIMPL( Symbol
);
164 Lang::Symbol::show( std::ostream
& os
) const
172 os
<< "'" << name( ) ;
177 DISPATCHIMPL( Float
);
179 RefCountPtr
< const Lang::Class
> Lang::Float::TypeID( new Lang::SystemFinalClass( strrefdup( "Float" ) ) );
180 TYPEINFOIMPL( Float
);
183 Lang::Float::show( std::ostream
& os
) const
193 DISPATCHIMPL( Integer
);
195 RefCountPtr
< const Lang::Class
> Lang::Integer::TypeID( new Lang::SystemFinalClass( strrefdup( "Integer" ) ) );
196 TYPEINFOIMPL( Integer
);
199 Lang::Integer::operator == ( const Integer
& other
) const
201 return val_
== other
.val_
;
205 Lang::Integer::operator != ( const Integer
& other
) const
207 return val_
!= other
.val_
;
211 Lang::Integer::operator < ( const Integer
& other
) const
213 return val_
< other
.val_
;
217 Lang::Integer::operator > ( const Integer
& other
) const
219 return val_
> other
.val_
;
223 Lang::Integer::operator <= ( const Integer
& other
) const
225 return val_
<= other
.val_
;
229 Lang::Integer::operator >= ( const Integer
& other
) const
231 return val_
>= other
.val_
;
234 Kernel::VariableHandle
235 Lang::Integer::getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const
237 if( strcmp( fieldID
, "hex" ) == 0 )
239 std::ostringstream oss
;
240 ValueType tmp
= val_
;
246 oss
<< std::hex
<< tmp
;
247 return Helpers::newValHandle( new Lang::String( strrefdup( oss
) ) );
249 if( strcmp( fieldID
, "oct" ) == 0 )
251 std::ostringstream oss
;
252 ValueType tmp
= val_
;
258 oss
<< std::oct
<< tmp
;
259 return Helpers::newValHandle( new Lang::String( strrefdup( oss
) ) );
261 if( strcmp( fieldID
, "bin" ) == 0 )
263 std::ostringstream oss
;
264 ValueType tmp
= val_
;
270 char buf
[ 8 * sizeof( ValueType
) ]; /* Since ValueType is signed, there is enough memory to hold the terminating null character. */
272 ValueType twopow
= 1;
273 while( twopow
< tmp
)
277 for( ; twopow
> 0; twopow
/= 2, ++dst
)
291 return Helpers::newValHandle( new Lang::String( strrefdup( oss
) ) );
293 if( strcmp( fieldID
, "bits_bin" ) == 0 )
295 std::ostringstream oss
;
296 ValueType_unsigned tmp
= *reinterpret_cast< const ValueType_unsigned
* >( & val_
);
297 char buf
[ 8 * sizeof( ValueType
) + 1];
298 char * dst
= buf
+ 8 * sizeof( ValueType
);
303 *dst
= ( ( tmp
% 2 ) != 0 ) ? '1': '0';
307 return Helpers::newValHandle( new Lang::String( strrefdup( oss
) ) );
309 if( strcmp( fieldID
, "bits_hex" ) == 0 )
311 std::ostringstream oss
;
312 ValueType_unsigned tmp
= *reinterpret_cast< const ValueType_unsigned
* >( & val_
);
313 char buf
[ 2 * sizeof( ValueType
) + 1];
314 char * dst
= buf
+ 2 * sizeof( ValueType
);
319 unsigned char d
= tmp
% 0x10;
326 *dst
= 'A' + ( d
- 10 );
331 return Helpers::newValHandle( new Lang::String( strrefdup( oss
) ) );
333 if( strcmp( fieldID
, "dec" ) == 0 )
335 std::ostringstream oss
;
336 ValueType tmp
= val_
;
342 oss
<< std::dec
<< tmp
;
343 return Helpers::newValHandle( new Lang::String( strrefdup( oss
) ) );
346 throw Exceptions::NonExistentMember( getTypeName( ), fieldID
);
350 Lang::Integer::show( std::ostream
& os
) const
355 os
<< "'~" << -val_
;
359 DISPATCHIMPL( Character
);
361 RefCountPtr
< const Lang::Class
> Lang::Character::TypeID( new Lang::SystemFinalClass( strrefdup( "Character" ) ) );
362 TYPEINFOIMPL( Character
);
365 Lang::Character::show( std::ostream
& os
) const
367 const size_t bufSize
= 8;
370 size_t out_avail
= bufSize
- 1;
371 val_
.encode_UTF8( & dst
, & out_avail
);
376 Kernel::VariableHandle
377 Lang::Character::getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const
379 if( strcmp( fieldID
, "code" ) == 0 )
381 return Helpers::newValHandle( new Lang::Integer( val_
.get_UCS4( ) ) );
384 throw Exceptions::NonExistentMember( getTypeName( ), fieldID
);
388 //Lang::Length::Length( double val )
389 // : isOffset_( false ), val_( val )
392 //Lang::Length::Length( bool isOffset, double val )
393 // : isOffset_( _isOffset ), val_( _val )
396 DISPATCHIMPL( Length
);
399 Lang::Length::get( Concrete::Length baseLength
) const
403 return baseLength
+ val_
;
409 Lang::Length::get( ) const
413 throw Exceptions::MiscellaneousRequirement( "Offset lengths are not allowed here." );
419 Lang::Length::getScalar( Concrete::Length baseLength
) const
423 return ( baseLength
+ val_
).offtype
< 1, 0 >( );
425 return val_
.offtype
< 1, 0 >( );
429 Lang::Length::getScalar( ) const
433 throw Exceptions::MiscellaneousRequirement( "Offset lengths are not allowed here." );
435 return val_
.offtype
< 1, 0 >( );
439 Lang::Length::operator + ( const Lang::Length
& term
) const
443 throw Exceptions::MiscellaneousRequirement( "The right term in a length addition must not be offset." );
445 return Lang::Length( isOffset_
, val_
+ term
.val_
);
449 Lang::Length::operator - ( const Lang::Length
& term
) const
453 throw Exceptions::MiscellaneousRequirement( "The right term in a length subtraction must not be offset." );
455 return Lang::Length( isOffset_
, val_
- term
.val_
);
458 RefCountPtr
< const Lang::Class
> Lang::Length::TypeID( new Lang::SystemFinalClass( strrefdup( "Length" ) ) );
459 TYPEINFOIMPL( Length
);
462 Lang::Length::show( std::ostream
& os
) const
469 Lang::operator << ( std::ostream
& os
, const Lang::Length
& self
)
475 double lengthVal
= static_cast< double >( self
.val_
/ Interaction::displayUnit
);
476 if( lengthVal
>= 0 ){
479 os
<< "~" << -lengthVal
;
481 os
<< Interaction::displayUnitName
;
490 DISPATCHIMPL( Boolean
);
492 RefCountPtr
< const Lang::Class
> Lang::Boolean::TypeID( new Lang::SystemFinalClass( strrefdup( "Boolean" ) ) );
493 TYPEINFOIMPL( Boolean
);
496 Lang::Boolean::show( std::ostream
& os
) const
515 class StringMethod_byteselect
: public Lang::MethodBase
< Lang::String
>
518 StringMethod_byteselect( RefCountPtr
< const Lang::String
> _self
, const Ast::FileID
* fullMethodID
);
519 virtual ~StringMethod_byteselect( );
520 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const;
521 static const char * staticFieldID( ) { return "byteselect"; }
524 class StringMethod_UTF8select
: public Lang::MethodBase
< Lang::String
>
527 StringMethod_UTF8select( RefCountPtr
< const Lang::String
> _self
, const Ast::FileID
* fullMethodID
);
528 virtual ~StringMethod_UTF8select( );
529 virtual void call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const;
530 static const char * staticFieldID( ) { return "UTF8select"; }
537 String_register_methods( Lang::SystemFinalClass
* dstClass
)
539 dstClass
->registerMethod( new Kernel::MethodFactory
< Lang::String
, Lang::StringMethod_byteselect
>( ) );
540 dstClass
->registerMethod( new Kernel::MethodFactory
< Lang::String
, Lang::StringMethod_UTF8select
>( ) );
543 Lang::String::~String( )
546 DISPATCHIMPL( String
);
548 RefCountPtr
< const Lang::Class
> Lang::String::TypeID( new Lang::SystemFinalClass( strrefdup( "String" ), String_register_methods
) );
549 TYPEINFOIMPL( String
);
551 Kernel::VariableHandle
552 Lang::String::getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const
554 if( strcmp( fieldID
, "bytecount" ) == 0 )
556 return Helpers::newValHandle( new Lang::Integer( bytecount_
) );
558 if( strcmp( fieldID
, "UTF8count" ) == 0 )
560 return Helpers::newValHandle( new Lang::Integer( UTF8count( ) ) );
562 if( strcmp( fieldID
, "UTF8?" ) == 0 )
564 const unsigned char * src
= reinterpret_cast< const unsigned char * >( val_
.getPtr( ) );
565 const unsigned char * end
= src
+ bytecount_
;
567 for( ; src
< end
; ++src
)
569 if( ( ( *src
^ 0x00 ) & 0x80 ) == 0 )
573 if( ( ( *src
^ 0xC0 ) & 0xE0 ) == 0 )
576 if( ( ( *src
^ 0x80 ) & 0xC0 ) != 0 )
583 if( ( ( *src
^ 0xE0 ) & 0xF0 ) == 0 )
586 if( ( ( *src
^ 0x80 ) & 0xC0 ) != 0 )
592 if( ( ( *src
^ 0x80 ) & 0xC0 ) != 0 )
599 if( ( ( *src
^ 0xE0 ) & 0xF8 ) == 0 )
602 if( ( ( *src
^ 0x80 ) & 0xC0 ) != 0 )
608 if( ( ( *src
^ 0x80 ) & 0xC0 ) != 0 )
614 if( ( ( *src
^ 0x80 ) & 0xC0 ) != 0 )
624 if( src
!= end
|| *src
!= '\0' )
628 return Helpers::newValHandle( new Lang::Boolean( res
) );
631 return TypeID
->getMethod( selfRef
, fieldID
); /* This will throw if there is no such method. */
635 Lang::String::UTF8count( ) const
637 const char * src
= val_
.getPtr( );
638 const char * end
= src
+ bytecount_
;
640 const char * ASCIIstart
= src
;
649 count
+= src
- ASCIIstart
;
650 while( *src
!= 0 && src
< end
)
659 switch( 0xF0 & *src
)
661 case 0xE0: src
+= 3; break;
662 case 0xF0: src
+= 4; break;
663 default: src
+= 2; break;
668 if( *src
!= 0 || src
!= end
)
670 throw Exceptions::MiscellaneousRequirement( "The string is not valid UTF-8, so the number of UTF-8 characters could not be counted." );
677 Lang::String::show( std::ostream
& os
) const
679 os
<< val_
.getPtr( ) ;
683 Lang::Continuation::Continuation( const Kernel::ContRef
& cont
)
687 Lang::Continuation::~Continuation( )
690 RefCountPtr
< const Lang::Class
> Lang::Continuation::TypeID( new Lang::SystemFinalClass( strrefdup( "Backtrace" ) ) );
691 TYPEINFOIMPL( Continuation
);
693 Kernel::VariableHandle
694 Lang::Continuation::getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const
696 if( strcmp( fieldID
, "up" ) == 0 )
698 Kernel::ContRef res
= cont_
->up( );
699 if( res
== NullPtr
< Kernel::Continuation
>( ) )
701 throw Exceptions::MiscellaneousRequirement( "The top continuation has no parent." );
703 return Helpers::newValHandle( new Lang::Continuation( res
) );
705 else if( strcmp( fieldID
, "top?" ) == 0 )
707 Kernel::ContRef res
= cont_
->up( );
708 return ( res
== NullPtr
< Kernel::Continuation
>( ) ) ? Kernel::THE_TRUE_VARIABLE
: Kernel::THE_FALSE_VARIABLE
;
710 throw Exceptions::NonExistentMember( getTypeName( ), fieldID
);
714 Lang::Continuation::show( std::ostream
& os
) const
716 os
<< "( backtrace to use in error messages )" ;
720 Lang::Continuation::gcMark( Kernel::GCMarkedSet
& marked
)
722 cont_
->gcMark( marked
);
726 Lang::Exception::Exception( const Ast::SourceLocation
& loc
, const RefCountPtr
< const Lang::Symbol
> & kind
, const RefCountPtr
< const Lang::String
> & source
, const RefCountPtr
< const Lang::Value
> & details
, const RefCountPtr
< const char > & message
, const Kernel::ContRef
& cont
, Interaction::ExitCode exitCode
)
727 : loc_( loc
), kind_( kind
), source_( source
), details_( details
), message_( message
), cont_( cont
), exitCode_( exitCode
)
730 Lang::Exception::Exception( const RefCountPtr
< const Lang::Symbol
> & kind
, const RefCountPtr
< const Lang::String
> & source
, const RefCountPtr
< const Lang::Value
> & details
, const RefCountPtr
< const char > & message
, const Kernel::ContRef
& cont
, Interaction::ExitCode exitCode
)
731 : loc_( cont
->traceLoc( ) ), kind_( kind
), source_( source
), details_( details
), message_( message
), cont_( cont
), exitCode_( exitCode
)
734 Lang::Exception::~Exception( )
737 RefCountPtr
< const Lang::Class
> Lang::Exception::TypeID( new Lang::SystemFinalClass( strrefdup( "Exception" ) ) );
738 TYPEINFOIMPL( Exception
);
740 Kernel::VariableHandle
741 Lang::Exception::getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const
743 if( strcmp( fieldID
, "kind" ) == 0 )
745 return Kernel::VariableHandle( new Kernel::Variable( kind_
) );
747 else if( strcmp( fieldID
, "source" ) == 0 )
749 return Kernel::VariableHandle( new Kernel::Variable( source_
) );
751 else if( strcmp( fieldID
, "details" ) == 0 )
753 return Kernel::VariableHandle( new Kernel::Variable( details_
) );
755 else if( strcmp( fieldID
, "backtrace" ) == 0 )
757 return Helpers::newValHandle( new Lang::Continuation( cont_
) );
759 throw Exceptions::NonExistentMember( getTypeName( ), fieldID
);
763 Lang::Exception::show( std::ostream
& os
) const
769 Lang::Exception::gcMark( Kernel::GCMarkedSet
& marked
)
771 const_cast< Lang::Value
* >( details_
.getPtr( ) )->gcMark( marked
);
772 const_cast< Kernel::Continuation
* >( cont_
.getPtr( ) )->gcMark( marked
);
776 Lang::FloatPair::FloatPair( const Concrete::UnitFloatPair
& orig
)
777 : x_( orig
.x_
), y_( orig
.y_
)
781 DISPATCHIMPL( FloatPair
);
783 Kernel::VariableHandle
784 Lang::FloatPair::getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const
786 if( strcmp( fieldID
, "x" ) == 0 )
788 return Helpers::newValHandle( new Lang::Float( x_
) );
790 if( strcmp( fieldID
, "y" ) == 0 )
792 return Helpers::newValHandle( new Lang::Float( y_
) );
794 throw Exceptions::NonExistentMember( getTypeName( ), fieldID
);
797 RefCountPtr
< const Lang::Class
> Lang::FloatPair::TypeID( new Lang::SystemFinalClass( strrefdup( "FloatPair" ) ) );
798 TYPEINFOIMPL( FloatPair
);
800 RefCountPtr
< const Lang::FloatPair
>
801 Lang::FloatPair::transformed( const Lang::Transform2D
& tf
) const
803 return RefCountPtr
< const Lang::FloatPair
>
804 ( new Lang::FloatPair( tf
.xx_
* x_
+ tf
.xy_
* y_
, tf
.yx_
* x_
+ tf
.yy_
* y_
) );
808 Lang::FloatPair::show( std::ostream
& os
) const
810 os
<< "( " << x_
<< ", " << y_
<< " )" ;
813 Lang::FloatTriple::FloatTriple( const Concrete::UnitFloatTriple
& orig
)
814 : x_( orig
.x_
), y_( orig
.y_
), z_( orig
.z_
)
817 DISPATCHIMPL( FloatTriple
);
819 Kernel::VariableHandle
820 Lang::FloatTriple::getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const
822 if( strcmp( fieldID
, "x" ) == 0 )
824 return Helpers::newValHandle( new Lang::Float( x_
) );
826 if( strcmp( fieldID
, "y" ) == 0 )
828 return Helpers::newValHandle( new Lang::Float( y_
) );
830 if( strcmp( fieldID
, "z" ) == 0 )
832 return Helpers::newValHandle( new Lang::Float( z_
) );
834 throw Exceptions::NonExistentMember( getTypeName( ), fieldID
);
837 RefCountPtr
< const Lang::Class
> Lang::FloatTriple::TypeID( new Lang::SystemFinalClass( strrefdup( "FloatTriple" ) ) );
838 TYPEINFOIMPL( FloatTriple
);
840 RefCountPtr
< const Lang::FloatTriple
>
841 Lang::FloatTriple::transformed( const Lang::Transform3D
& tf
) const
843 return RefCountPtr
< const Lang::FloatTriple
>
844 ( new Lang::FloatTriple( tf
.xx_
* x_
+ tf
.xy_
* y_
+ tf
.xz_
* z_
,
845 tf
.yx_
* x_
+ tf
.yy_
* y_
+ tf
.yz_
* z_
,
846 tf
.zx_
* x_
+ tf
.zy_
* y_
+ tf
.zz_
* z_
) );
850 Lang::FloatTriple::show( std::ostream
& os
) const
852 os
<< "( " << x_
<< ", " << y_
<< ", " << z_
<< " )" ;
856 Lang::Coords2D::Coords2D( const Lang::Coords2D
& orig
)
857 : x_( orig
.x_
), y_( orig
.y_
)
860 Lang::Coords2D::Coords2D( const Lang::Length
& x
, const Lang::Length
& y
)
864 Lang::Coords2D::Coords2D( const Concrete::Length
& x
, const Concrete::Length
& y
)
868 DISPATCHIMPL( Coords2D
);
870 Kernel::VariableHandle
871 Lang::Coords2D::getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const
873 if( strcmp( fieldID
, "x" ) == 0 )
875 return Helpers::newValHandle( new Lang::Length( x_
) );
877 if( strcmp( fieldID
, "y" ) == 0 )
879 return Helpers::newValHandle( new Lang::Length( y_
) );
881 throw Exceptions::NonExistentMember( getTypeName( ), fieldID
);
885 Lang::Coords2D::transformedPtr( const Lang::Transform2D
& tf
) const
887 Concrete::Length tmpx
= x_
.get( );
888 Concrete::Length tmpy
= y_
.get( );
889 return new Lang::Coords2D( tf
.xx_
* tmpx
+ tf
.xy_
* tmpy
+ tf
.xt_
, tf
.yx_
* tmpx
+ tf
.yy_
* tmpy
+ tf
.yt_
);
892 RefCountPtr
< const Lang::Geometric2D
>
893 Lang::Coords2D::transformed( const Lang::Transform2D
& tf
, const RefCountPtr
< const Lang::Geometric2D
> & self
) const
895 return RefCountPtr
< const Lang::Geometric2D
>( transformedPtr( tf
) );
898 RefCountPtr
< const Lang::Geometric3D
>
899 Lang::Coords2D::to3D( const RefCountPtr
< const Lang::Geometric2D
> & self
) const
901 return RefCountPtr
< const Lang::Coords3D
>( new Lang::Coords3D( x_
, y_
, Lang::Length( Concrete::Length( 0 ) ) ) );
904 RefCountPtr
< const Lang::Class
> Lang::Coords2D::TypeID( new Lang::SystemFinalClass( strrefdup( "Coords2D" ) ) );
905 TYPEINFOIMPL( Coords2D
);
908 Lang::Coords2D::show( std::ostream
& os
) const
910 os
<< "( " << x_
<< ", " << y_
<< " )" ;
914 Lang::operator << ( std::ostream
& os
, const Lang::Coords2D
& self
)
916 os
<< "( " << self
.x_
<< ", " << self
.y_
<< " )" ;
921 Lang::CornerCoords2D::CornerCoords2D( const Lang::Length
& x
, const Lang::Length
& y
, double a
)
922 : Lang::Coords2D( x
, y
), a_( a
)
925 Lang::CornerCoords2D::CornerCoords2D( const Concrete::Length
& x
, const Concrete::Length
& y
, double a
)
926 : Lang::Coords2D( x
, y
), a_( a
)
929 RefCountPtr
< const Lang::Class
> Lang::CornerCoords2D::TypeID( new Lang::SystemFinalClass( strrefdup( "CornerCoords2D" ) ) );
930 DISPATCHIMPL( CornerCoords2D
);
932 Kernel::VariableHandle
933 Lang::CornerCoords2D::getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const
935 if( strcmp( fieldID
, "x" ) == 0 )
937 return Helpers::newValHandle( new Lang::Length( x_
) );
939 if( strcmp( fieldID
, "y" ) == 0 )
941 return Helpers::newValHandle( new Lang::Length( y_
) );
943 if( strcmp( fieldID
, "a" ) == 0 )
945 return Helpers::newValHandle( new Lang::Float( a_
) );
947 throw Exceptions::NonExistentMember( getTypeName( ), fieldID
);
950 Lang::CornerCoords2D
*
951 Lang::CornerCoords2D::transformedPtr( const Lang::Transform2D
& tf
) const
953 Concrete::Length tmpx
= x_
.get( );
954 Concrete::Length tmpy
= y_
.get( );
955 return new Lang::CornerCoords2D( tf
.xx_
* tmpx
+ tf
.xy_
* tmpy
+ tf
.xt_
, tf
.yx_
* tmpx
+ tf
.yy_
* tmpy
+ tf
.yt_
, a_
);
958 RefCountPtr
< const Lang::Geometric2D
>
959 Lang::CornerCoords2D::transformed( const Lang::Transform2D
& tf
, const RefCountPtr
< const Lang::Geometric2D
> & self
) const
961 return RefCountPtr
< const Lang::Geometric2D
>( transformedPtr( tf
) );
964 RefCountPtr
< const Lang::Geometric3D
>
965 Lang::CornerCoords2D::to3D( const RefCountPtr
< const Lang::Geometric2D
> & self
) const
967 throw Exceptions::MiscellaneousRequirement( "Corner coordinates cannot move into 3D space." );
970 TYPEINFOIMPL( CornerCoords2D
);
973 Lang::Coords3D::Coords3D( const Lang::Coords3D
& orig
)
974 : x_( orig
.x_
), y_( orig
.y_
), z_( orig
.z_
)
977 Lang::Coords3D::Coords3D( const Lang::Length
& x
, const Lang::Length
& y
, const Lang::Length
& z
)
978 : x_( x
), y_( y
), z_( z
)
981 Lang::Coords3D::Coords3D( const Concrete::Length
& x
, const Concrete::Length
& y
, const Concrete::Length
& z
)
982 : x_( x
), y_( y
), z_( z
)
985 DISPATCHIMPL( Coords3D
);
987 Kernel::VariableHandle
988 Lang::Coords3D::getField( const char * fieldID
, const RefCountPtr
< const Lang::Value
> & selfRef
) const
990 if( strcmp( fieldID
, "x" ) == 0 )
992 return Helpers::newValHandle( new Lang::Length( x_
) );
994 if( strcmp( fieldID
, "y" ) == 0 )
996 return Helpers::newValHandle( new Lang::Length( y_
) );
998 if( strcmp( fieldID
, "z" ) == 0 )
1000 return Helpers::newValHandle( new Lang::Length( z_
) );
1002 throw Exceptions::NonExistentMember( getTypeName( ), fieldID
);
1006 Lang::Coords3D::transformedPtr( const Lang::Transform3D
& tf
) const
1008 Concrete::Length tmpx
= x_
.get( );
1009 Concrete::Length tmpy
= y_
.get( );
1010 Concrete::Length tmpz
= z_
.get( );
1011 return new Lang::Coords3D( tf
.xx_
* tmpx
+ tf
.xy_
* tmpy
+ tf
.xz_
* tmpz
+ tf
.xt_
,
1012 tf
.yx_
* tmpx
+ tf
.yy_
* tmpy
+ tf
.yz_
* tmpz
+ tf
.yt_
,
1013 tf
.zx_
* tmpx
+ tf
.zy_
* tmpy
+ tf
.zz_
* tmpz
+ tf
.zt_
);
1016 RefCountPtr
< const Lang::Geometric3D
>
1017 Lang::Coords3D::transformed( const Lang::Transform3D
& tf
, const RefCountPtr
< const Lang::Geometric3D
> & self
) const
1019 return RefCountPtr
< const Lang::Geometric3D
>( transformedPtr( tf
) );
1022 RefCountPtr
< const Lang::Coords2D
>
1023 Lang::Coords3D::make2D( Concrete::Length eyez
) const
1025 if( eyez
< Concrete::HUGE_LENGTH
)
1027 return RefCountPtr
< const Lang::Coords2D
>( new Lang::Coords2D( x_
.get( ) * ( eyez
/ ( eyez
- z_
.get( ) ) ),
1028 y_
.get( ) * ( eyez
/ ( eyez
- z_
.get( ) ) ) ) );
1030 return RefCountPtr
< const Lang::Coords2D
>( new Lang::Coords2D( x_
.get( ),
1035 RefCountPtr
< const Lang::Geometric2D
>
1036 Lang::Coords3D::to2D( const Kernel::PassedDyn
& dyn
, const RefCountPtr
< const Lang::Geometric3D
> & self
) const
1038 return make2D( dyn
->getEyeZ( ) );
1041 RefCountPtr
< const Lang::Class
> Lang::Coords3D::TypeID( new Lang::SystemFinalClass( strrefdup( "Coords3D" ) ) );
1042 TYPEINFOIMPL( Coords3D
);
1045 Lang::Coords3D::show( std::ostream
& os
) const
1047 os
<< "( " << x_
<< ", " << y_
<< ", " << z_
<< " )" ;
1051 Lang::operator << ( std::ostream
& os
, const Lang::Coords3D
& self
)
1053 os
<< "( " << self
.x_
<< ", " << self
.y_
<< ", " << self
.z_
<< " )" ;
1062 class StringMethod_select_cont
: public Kernel::Continuation
1064 RefCountPtr
< const Lang::String
> self_
;
1066 Kernel::ContRef cont_
;
1068 StringMethod_select_cont( const RefCountPtr
< const Lang::String
> & self
, bool UTF8select
, Kernel::ContRef cont
, const Ast::SourceLocation
& traceLoc
)
1069 : Kernel::Continuation( traceLoc
), self_( self
), UTF8select_( UTF8select
), cont_( cont
)
1071 virtual ~StringMethod_select_cont( ) { }
1072 virtual void takeValue( const RefCountPtr
< const Lang::Value
> & posUntyped
, Kernel::EvalState
* evalState
, bool dummy
) const
1074 RefCountPtr
< const Lang::SingleList
> pos
= posUntyped
.down_cast
< const Lang::SingleList
>( );
1075 if( pos
== NullPtr
< const Lang::SingleList
>( ) )
1076 throw Exceptions::InternalError( "StringMethod_select_cont::takeValue did not get a SingleList value." );
1078 Lang::Integer::ValueType posEnd
= UTF8select_
? self_
->UTF8count( ) : self_
->bytecount_
;
1080 typedef std::vector
< Lang::Integer::ValueType
> PosVecType
;
1081 PosVecType posTyped
;
1083 RefCountPtr
< const Lang::SingleList
> src
= pos
;
1084 while( ! src
->isNull( ) )
1088 typedef const Lang::SingleListPair ArgType
;
1089 RefCountPtr
< ArgType
> p
= Helpers::try_cast_CoreArgument
< ArgType
>( src
);
1090 posTyped
.push_back( p
->car_
->getVal
< const Lang::Integer
>( traceLoc_
)->val_
);
1094 catch( const NonLocalExit::NotThisType
& ball
)
1096 /* Wrong type; never mind!.. but see below!
1101 typedef const Lang::SingleListRange
< const Lang::Integer
> ArgType
;
1102 RefCountPtr
< ArgType
> p
= Helpers::try_cast_CoreArgument
< ArgType
>( src
);
1103 p
->expand( & posTyped
);
1106 catch( const NonLocalExit::NotThisType
& ball
)
1108 /* Wrong type; never mind!.. but see below!
1112 std::ostringstream msg
;
1113 msg
<< "When selecting bytes/characters in a string, all positions must be of type " << Lang::Integer::staticTypeName( ) << "." ;
1114 throw Exceptions::MiscellaneousRequirement( strrefdup( msg
) );
1118 for( PosVecType::const_iterator i
= posTyped
.begin( ); i
!= posTyped
.end( ); ++i
)
1122 throw Exceptions::OutOfRange( "A negative position was encountered." );
1126 throw Exceptions::OutOfRange( "A position beyond the end of the string was encountered." );
1130 RefCountPtr
< const char > resMem
= RefCountPtr
< const char >( NullPtr
< const char >( ) );
1135 std::vector
< Kernel::UnicodeCodePoint
> selfChars
;
1136 selfChars
.reserve( posEnd
);
1137 /* Compare String::UTF8count! */
1139 Kernel::UnicodeCodePoint c
;
1140 const char * src
= self_
->val_
.getPtr( );
1141 const char * end
= src
+ self_
->bytecount_
;
1147 c
.decode_UTF8( & src
, & avail
);
1148 selfChars
.push_back( c
);
1151 while( *src
!= 0 && src
< end
)
1159 switch( 0xF0 & *src
)
1164 c
.decode_UTF8( & src
, & avail
);
1165 selfChars
.push_back( c
);
1171 c
.decode_UTF8( & src
, & avail
);
1172 selfChars
.push_back( c
);
1178 c
.decode_UTF8( & src
, & avail
);
1179 selfChars
.push_back( c
);
1185 if( *src
!= 0 || src
!= end
)
1187 throw Exceptions::InternalError( "The string is not valid UTF-8, but this should have been detected when the characters were counted." );
1191 std::ostringstream dst
;
1192 const size_t bufSize
= 10;
1193 char buf
[ bufSize
];
1194 for( PosVecType::const_iterator i
= posTyped
.begin( ); i
!= posTyped
.end( ); ++i
)
1196 char * tmpBuf
= buf
;
1197 size_t outAvail
= bufSize
;
1198 selfChars
[ *i
].encode_UTF8( & tmpBuf
, & outAvail
);
1202 resMem
= strrefdup( dst
);
1203 resSize
= dst
.str( ).size( );
1208 char * dst
= new char[ resSize
+ 1 ];
1209 resMem
= RefCountPtr
< const char >( dst
);
1210 const char * srcBegin
= self_
->val_
.getPtr( );
1211 for( PosVecType::const_iterator i
= posTyped
.begin( ); i
!= posTyped
.end( ); ++i
, ++dst
)
1213 *dst
= *( srcBegin
+ *i
);
1218 evalState
->cont_
= cont_
;
1219 cont_
->takeValue( RefCountPtr
< const Lang::String
>( new Lang::String( resMem
, resSize
) ), evalState
);
1221 virtual Kernel::ContRef
up( ) const
1225 virtual RefCountPtr
< const char > description( ) const
1227 return strrefdup( "Select bytes/characters from String, after forcing positions." );
1229 virtual void gcMark( Kernel::GCMarkedSet
& marked
)
1231 const_cast< Lang::String
* >( self_
.getPtr( ) )->gcMark( marked
);
1232 cont_
->gcMark( marked
);
1236 class StringMethod_select_span_cont
: public Kernel::Continuation
1238 RefCountPtr
< const Lang::String
> self_
;
1240 Kernel::ContRef cont_
;
1242 StringMethod_select_span_cont( const RefCountPtr
< const Lang::String
> & self
, bool UTF8select
, Kernel::ContRef cont
, const Ast::SourceLocation
& traceLoc
)
1243 : Kernel::Continuation( traceLoc
), self_( self
), UTF8select_( UTF8select
), cont_( cont
)
1245 virtual ~StringMethod_select_span_cont( ) { }
1246 virtual void takeValue( const RefCountPtr
< const Lang::Value
> & val
, Kernel::EvalState
* evalState
, bool dummy
) const
1248 typedef const Lang::SingleList ArgType
;
1249 RefCountPtr
< ArgType
> pos( Helpers::down_cast_ContinuationArgument
< ArgType
>( val
, this ) );
1251 evalState
->cont_
= Kernel::ContRef( new Kernel::ForcingListContinuation( Kernel::ContRef( new Kernel::StringMethod_select_cont( self_
, UTF8select_
, cont_
, traceLoc_
) ), traceLoc_
) );
1252 Kernel::ContRef cont
= evalState
->cont_
;
1253 cont
->takeValue( pos
, evalState
);
1255 virtual Kernel::ContRef
up( ) const
1259 virtual RefCountPtr
< const char > description( ) const
1261 return strrefdup( "Select bytes/characters from String, expand span." );
1263 virtual void gcMark( Kernel::GCMarkedSet
& marked
)
1265 const_cast< Lang::String
* >( self_
.getPtr( ) )->gcMark( marked
);
1266 cont_
->gcMark( marked
);
1274 Lang::StringMethod_byteselect::StringMethod_byteselect( RefCountPtr
< const Lang::String
> self
, const Ast::FileID
* fullMethodID
)
1275 : Lang::MethodBase
< class_type
>( self
, fullMethodID
, false, true )
1277 formals_
->appendEvaluatedCoreFormal( "pos", Kernel::THE_SLOT_VARIABLE
);
1280 Lang::StringMethod_byteselect::~StringMethod_byteselect( )
1284 Lang::StringMethod_byteselect::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1286 args
.applyDefaults( callLoc
);
1291 typedef const Lang::SingleList ArgType
;
1292 RefCountPtr
< ArgType
> pos
= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( argsi
) );
1294 evalState
->cont_
= Kernel::ContRef( new Kernel::ForcingListContinuation( Kernel::ContRef( new Kernel::StringMethod_select_cont( self_
, false, evalState
->cont_
, callLoc
) ), callLoc
) );
1295 Kernel::ContRef cont
= evalState
->cont_
;
1296 cont
->takeValue( pos
, evalState
);
1299 catch( const NonLocalExit::NotThisType
& ball
)
1301 /* Wrong type; never mind!.. but see below!
1307 typedef const Lang::Span ArgType
;
1308 RefCountPtr
< ArgType
> pos
= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( argsi
) );
1310 evalState
->cont_
= Kernel::ContRef( new Kernel::StringMethod_select_span_cont( self_
, false, evalState
->cont_
, callLoc
) );
1311 pos
->Lang::Function::call( evalState
, RefCountPtr
< const Lang::Value
>( new Lang::Integer( self_
->bytecount_
- 1 ) ), callLoc
);
1314 catch( const NonLocalExit::NotThisType
& ball
)
1316 /* Wrong type; never mind!.. but see below!
1322 typedef const Lang::Integer ArgType
;
1323 ArgType::ValueType pos
= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( argsi
) )->val_
;
1326 throw Exceptions::CoreOutOfRange( coreLoc_
, args
, argsi
, "The position is negative." );
1329 if( upos
>= self_
->bytecount_
)
1331 throw Exceptions::CoreOutOfRange( coreLoc_
, args
, argsi
, "The position is beyond the end of the string." );
1333 Kernel::ContRef cont
= evalState
->cont_
;
1334 cont
->takeValue( Kernel::ValueRef( new Lang::Integer( *reinterpret_cast< const unsigned char * >( self_
->val_
.getPtr( ) + upos
) ) ),
1338 catch( const NonLocalExit::NotThisType
& ball
)
1340 /* Wrong type; never mind!.. but see below!
1344 throw Exceptions::CoreTypeMismatch( callLoc
, coreLoc_
, args
, argsi
, Helpers::typeSetString( Lang::SingleList::staticTypeName( ), Lang::Span::staticTypeName( ) ) );
1347 Lang::StringMethod_UTF8select::StringMethod_UTF8select( RefCountPtr
< const Lang::String
> self
, const Ast::FileID
* fullMethodID
)
1348 : Lang::MethodBase
< class_type
>( self
, fullMethodID
, false, true )
1350 formals_
->appendEvaluatedCoreFormal( "pos", Kernel::THE_SLOT_VARIABLE
);
1353 Lang::StringMethod_UTF8select::~StringMethod_UTF8select( )
1357 Lang::StringMethod_UTF8select::call( Kernel::EvalState
* evalState
, Kernel::Arguments
& args
, const Ast::SourceLocation
& callLoc
) const
1359 args
.applyDefaults( callLoc
);
1364 typedef const Lang::SingleList ArgType
;
1365 RefCountPtr
< ArgType
> pos
= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( argsi
) );
1367 evalState
->cont_
= Kernel::ContRef( new Kernel::ForcingListContinuation( Kernel::ContRef( new Kernel::StringMethod_select_cont( self_
, true, evalState
->cont_
, callLoc
) ), callLoc
) );
1368 Kernel::ContRef cont
= evalState
->cont_
;
1369 cont
->takeValue( pos
, evalState
);
1372 catch( const NonLocalExit::NotThisType
& ball
)
1374 /* Wrong type; never mind!.. but see below!
1380 typedef const Lang::Span ArgType
;
1381 RefCountPtr
< ArgType
> pos
= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( argsi
) );
1383 evalState
->cont_
= Kernel::ContRef( new Kernel::StringMethod_select_span_cont( self_
, true, evalState
->cont_
, callLoc
) );
1384 pos
->Lang::Function::call( evalState
, RefCountPtr
< const Lang::Value
>( new Lang::Integer( self_
->UTF8count( ) - 1 ) ), callLoc
);
1387 catch( const NonLocalExit::NotThisType
& ball
)
1389 /* Wrong type; never mind!.. but see below!
1395 typedef const Lang::Integer ArgType
;
1396 ArgType::ValueType pos
= Helpers::try_cast_CoreArgument
< ArgType
>( args
.getValue( argsi
) )->val_
;
1399 throw Exceptions::CoreOutOfRange( coreLoc_
, args
, argsi
, "The position is negative." );
1402 if( upos
>= self_
->UTF8count( ) )
1404 throw Exceptions::CoreOutOfRange( coreLoc_
, args
, argsi
, "The position is beyond the end of the string." );
1407 /* Compare String::UTF8count ! */
1409 const char * src
= self_
->val_
.getPtr( );
1410 const char * end
= src
+ self_
->bytecount_
;
1412 const char * ASCIIstart
= src
;
1423 count
+= src
- ASCIIstart
;
1426 src
-= ( count
- upos
);
1429 while( *src
!= 0 && src
< end
)
1438 switch( 0xF0 & *src
)
1440 case 0xE0: src
+= 3; break;
1441 case 0xF0: src
+= 4; break;
1442 default: src
+= 2; break;
1451 if( *src
!= 0 || src
!= end
)
1453 throw Exceptions::InternalError( "Failed to located character at given position in string." );
1457 Kernel::UnicodeCodePoint c
;
1458 c
.decode_UTF8( src
);
1459 Kernel::ContRef cont
= evalState
->cont_
;
1460 cont
->takeValue( Kernel::ValueRef( new Lang::Character( c
) ),
1464 catch( const NonLocalExit::NotThisType
& ball
)
1466 /* Wrong type; never mind!.. but see below!
1470 throw Exceptions::CoreTypeMismatch( callLoc
, coreLoc_
, args
, argsi
, Helpers::typeSetString( Lang::SingleList::staticTypeName( ), Lang::Span::staticTypeName( ) ) );