lib Library API Documentation

koscript_value.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 1998, 1999, 2000 Torben Weis <weis@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017    Boston, MA 02111-1307, USA.
00018 */
00019 
00020 #include "koscript_value.h"
00021 #include "koscript_func.h"
00022 #include "koscript_context.h"
00023 #include "koscript_struct.h"
00024 #include "koscript_property.h"
00025 #include "koscript_method.h"
00026 
00027 #include <klocale.h>
00028 
00029 // Imported from scanner.ll
00030 extern KLocale* s_koscript_locale;
00031 
00032 KSValue* KSValue::s_null = 0;
00033 
00034 KSValue::KSValue()
00035 {
00036   typ = Empty;
00037   m_mode = Temp;
00038 }
00039 
00040 KSValue::KSValue( Type _type )
00041 {
00042   typ = _type;
00043   m_mode = Temp;
00044 
00045   switch( typ )
00046     {
00047     case DateType:
00048       val.ptr = new QDate;
00049       break;
00050     case TimeType:
00051       val.ptr = new QTime;
00052       break;
00053     case StringType:
00054       val.ptr = new QString;
00055       break;
00056     case ListType:
00057       val.ptr = new QValueList<Ptr>;
00058       break;
00059     case MapType:
00060       val.ptr = new QMap<QString,Ptr>;
00061       break;
00062     case CharRefType:
00063       val.ptr = new KScript::CharRef( 0, 0 );
00064       break;
00065     case CharType:
00066       val.c = 0;
00067       break;
00068     case FunctionType:
00069     case MethodType:
00070     case PropertyType:
00071     case ModuleType:
00072     case StructType:
00073     case StructClassType:
00074       val.ptr = 0;
00075       break;
00076     case StructBuiltinMethodType:
00077       val.sm = 0;
00078       break;
00079     case IntType:
00080     case BoolType:
00081     case DoubleType:
00082     case Empty:
00083       // Do nothing
00084       break;
00085     case NTypes:
00086       Q_ASSERT( 0 );
00087     }
00088 }
00089 
00090 KSValue::KSValue( const KSValue& p ) : QShared()
00091 {
00092   typ = Empty;
00093   *this = p;
00094 }
00095 
00096 KSValue::~KSValue()
00097 {
00098     clear();
00099 }
00100 
00101 KSValue& KSValue::operator= ( const KSValue& p )
00102 {
00103   clear();
00104 
00105   switch( p.type() )
00106     {
00107     case Empty:
00108       break;
00109     case DateType:
00110       val.ptr = new QDate( p.dateValue() );
00111       break;
00112     case TimeType:
00113       val.ptr = new QTime( p.timeValue() );
00114       break;
00115     case StringType:
00116       val.ptr = new QString( p.stringValue() );
00117       break;
00118     case ListType:
00119       val.ptr = new QValueList<Ptr>( p.listValue() );
00120       break;
00121     case MapType:
00122       val.ptr = new QMap<QString,Ptr>( p.mapValue() );
00123       break;
00124     case IntType:
00125       val.i = p.intValue();
00126       break;
00127     case BoolType:
00128       val.b = p.boolValue();
00129       break;
00130     case DoubleType:
00131       val.d = p.doubleValue();
00132       break;
00133     case CharType:
00134       val.c = p.charValue().unicode();
00135       break;
00136     case CharRefType:
00137       val.ptr = new KScript::CharRef( p.charRefValue() );
00138       break;
00139     case StructBuiltinMethodType:
00140       val.sm = p.val.sm;
00141       break;
00142     case FunctionType:
00143     case MethodType:
00144     case PropertyType:
00145     case ModuleType:
00146     case StructClassType:
00147       val.ptr = p.val.ptr;
00148       ((QShared*)val.ptr)->ref();
00149       break;
00150     case StructType:
00151       val.ptr = ((KSStruct*)p.val.ptr)->clone();
00152       break;
00153     case NTypes:
00154       Q_ASSERT( 0 );
00155     }
00156 
00157   typ = p.type();
00158   m_mode = p.mode();
00159 
00160   return *this;
00161 }
00162 
00163 QString KSValue::typeName() const
00164 {
00165   return typeToName( typ );
00166 }
00167 
00168 void KSValue::setValue( const QDate& _value )
00169 {
00170   clear();
00171   typ = DateType;
00172   val.ptr = new QDate( _value );
00173 }
00174 
00175 void KSValue::setValue( const QTime& _value )
00176 {
00177   clear();
00178   typ = TimeType;
00179   val.ptr = new QTime( _value );
00180 }
00181 
00182 void KSValue::setValue( const QString& _value )
00183 {
00184   clear();
00185   typ = StringType;
00186   val.ptr = new QString( _value );
00187 }
00188 
00189 void KSValue::setValue( const QValueList<Ptr>& _value )
00190 {
00191   clear();
00192   typ = ListType;
00193   val.ptr = new QValueList<Ptr>( _value );
00194 }
00195 
00196 void KSValue::setValue( const QMap<QString,Ptr>& _value )
00197 {
00198   clear();
00199   typ = MapType;
00200   val.ptr = new QMap<QString,Ptr>( _value );
00201 }
00202 
00203 void KSValue::setValue( KScript::Long _value )
00204 {
00205   clear();
00206   typ = IntType;
00207   val.i = _value;
00208 }
00209 
00210 void KSValue::setValue( KScript::Boolean _value )
00211 {
00212   clear();
00213   typ = BoolType;
00214   val.b = _value;
00215 }
00216 
00217 void KSValue::setValue( KScript::Double _value )
00218 {
00219   clear();
00220   typ = DoubleType;
00221   val.d = _value;
00222 }
00223 
00224 void KSValue::setValue( const KScript::Char& _value )
00225 {
00226   clear();
00227   typ = CharType;
00228   val.c = _value.unicode();
00229 }
00230 
00231 void KSValue::setValue( const KScript::CharRef& _value )
00232 {
00233   clear();
00234   typ = CharRefType;
00235   val.ptr = new KScript::CharRef( _value );
00236 }
00237 
00238 void KSValue::setValue( KSFunction* _value )
00239 {
00240   clear();
00241   typ = FunctionType;
00242   // Do not call ref() since we take over ownership
00243   val.ptr = _value;
00244 }
00245 
00246 void KSValue::setValue( KSMethod* _value )
00247 {
00248   clear();
00249   typ = MethodType;
00250   // Do not call ref() since we take over ownership
00251   val.ptr = _value;
00252 }
00253 
00254 void KSValue::setValue( KSProperty* _value )
00255 {
00256   clear();
00257   typ = PropertyType;
00258   // Do not call ref() since we take over ownership
00259   val.ptr = _value;
00260 }
00261 
00262 void KSValue::setValue( KSModule* _value )
00263 {
00264   clear();
00265   typ = ModuleType;
00266   // Do not call ref() since we take over ownership
00267   val.ptr = _value;
00268 }
00269 
00270 void KSValue::setValue( KSStruct* _value )
00271 {
00272   clear();
00273   typ = StructType;
00274   // Do not call ref() since we take over ownership
00275   val.ptr = _value;
00276 }
00277 
00278 void KSValue::setValue( KSStructClass* _value )
00279 {
00280   clear();
00281   typ = StructClassType;
00282   // Do not call ref() since we take over ownership
00283   val.ptr = _value;
00284 }
00285 
00286 void KSValue::setValue( KSStructBuiltinMethod _value )
00287 {
00288   clear();
00289   typ = StructBuiltinMethodType;
00290   val.sm = _value;
00291 }
00292 
00293 void KSValue::clear()
00294 {
00295   switch( typ )
00296     {
00297     case Empty:
00298     case IntType:
00299     case BoolType:
00300     case DoubleType:
00301     case CharType:
00302     case StructBuiltinMethodType:
00303       break;
00304     case FunctionType:
00305       if ( val.ptr )
00306     if ( functionValue()->deref() )
00307       delete ((KSFunction*)val.ptr);
00308       break;
00309     case PropertyType:
00310       if ( val.ptr )
00311     if ( propertyValue()->deref() )
00312       delete ((KSProperty*)val.ptr);
00313       break;
00314     case MethodType:
00315       if ( val.ptr )
00316     if ( methodValue()->deref() )
00317       delete ((KSMethod*)val.ptr);
00318       break;
00319     case ModuleType:
00320       if ( val.ptr )
00321     if ( moduleValue()->deref() )
00322       delete ((KSModule*)val.ptr);
00323       break;
00324     case StructType:
00325       if ( val.ptr )
00326     if ( structValue()->deref() )
00327       delete ((KSStruct*)val.ptr);
00328       break;
00329     case StructClassType:
00330       if ( val.ptr )
00331     if ( structClassValue()->deref() )
00332       delete ((KSStructClass*)val.ptr);
00333       break;
00334     case StringType:
00335       delete (QString*)val.ptr;
00336       break;
00337     case DateType:
00338       delete (QDate*)val.ptr;
00339       break;
00340     case TimeType:
00341       delete (QTime*)val.ptr;
00342       break;
00343     case ListType:
00344       delete (QValueList<Ptr>*)val.ptr;
00345       break;
00346     case MapType:
00347       delete (QMap<QString,Ptr>*)val.ptr;
00348       break;
00349     case CharRefType:
00350       delete (KScript::CharRef*)val.ptr;
00351       break;
00352     case NTypes:
00353       Q_ASSERT(0);
00354       break;
00355     }
00356 
00357   typ = Empty;
00358 }
00359 
00360 static QString *typ_to_name = 0;
00361 
00362 void KSValue::initTypeNameMap()
00363 {
00364     if ( typ_to_name ) return;
00365 
00366     typ_to_name = new QString[(int)NTypes];
00367 
00368     typ_to_name[(int)Empty] = QString::fromLatin1("<none>");
00369     typ_to_name[(int)StringType] = QString::fromLatin1("String");
00370     typ_to_name[(int)IntType] = QString::fromLatin1("Integer");
00371     typ_to_name[(int)BoolType] = QString::fromLatin1("Boolean");
00372     typ_to_name[(int)DoubleType] = QString::fromLatin1("Double");
00373     typ_to_name[(int)ListType] = QString::fromLatin1("List");
00374     typ_to_name[(int)MapType] = QString::fromLatin1("Map");
00375     typ_to_name[(int)CharType] = QString::fromLatin1("Char");
00376     typ_to_name[(int)CharRefType] = QString::fromLatin1("Char");
00377     typ_to_name[(int)FunctionType] = QString::fromLatin1("Function");
00378     typ_to_name[(int)MethodType] = QString::fromLatin1("Method");
00379     typ_to_name[(int)PropertyType] = QString::fromLatin1("Property");
00380     typ_to_name[(int)ModuleType] = QString::fromLatin1("Module");
00381     typ_to_name[(int)StructType] = QString::fromLatin1("Struct");
00382     typ_to_name[(int)StructClassType] = QString::fromLatin1("StructClass");
00383     typ_to_name[(int)StructBuiltinMethodType] = QString::fromLatin1("StructBuiltinMethod");
00384     typ_to_name[(int)DateType] = QString::fromLatin1("Date");
00385     typ_to_name[(int)TimeType] = QString::fromLatin1("Time");
00386 }
00387 
00388 QString KSValue::typeToName( KSValue::Type _typ )
00389 {
00390     initTypeNameMap();
00391     return typ_to_name[_typ];
00392 }
00393 
00394 KSValue::Type KSValue::nameToType( const QString& _name )
00395 {
00396     initTypeNameMap();
00397 
00398     int t = (int)NTypes;
00399     while ( t > (int)Empty && typ_to_name[(int)--t] != _name )
00400     ;
00401     return Type(t);
00402 }
00403 
00404 bool KSValue::cast( Type _typ )
00405 {
00406   if ( typ == _typ )
00407     return true;
00408 
00409   switch( typ )
00410     {
00411     case Empty:
00412       return false;
00413     case IntType:
00414       if ( _typ == DoubleType )
00415       {
00416     KScript::Double d = (KScript::Double)val.i;
00417     val.d = d;
00418     typ = _typ;
00419     return true;
00420       }
00421       return false;
00422     case BoolType:
00423       if ( _typ == StringType )
00424       {
00425     KScript::Boolean b = val.b;
00426     if ( b )
00427       setValue( "TRUE" );
00428     else
00429       setValue( "FALSE" );
00430     typ = _typ;
00431     return true;
00432       }
00433       else if ( _typ == IntType )
00434       {
00435         KScript::Boolean b = val.b;
00436         setValue( b ? 1 : 0 );
00437         typ = _typ;
00438       }
00439       return false;
00440       break;
00441     case DoubleType:
00442       if ( _typ == IntType )
00443       {
00444     KScript::Long i = (KScript::Long)val.d;
00445     val.i = i;
00446     typ = _typ;
00447     return true;
00448       }
00449       return false;
00450     case StringType:
00451       if ( _typ == BoolType )
00452       {
00453       setValue( !stringValue().isEmpty() );
00454       return TRUE;
00455       }
00456       return false;
00457     case CharRefType:
00458       if ( _typ != CharType )
00459     return false;
00460       typ = _typ;
00461       return true;
00462     case PropertyType:
00463       /* {
00464     KSValue* v = propertyValue()->object()->member( propertyValue()->name(), FALSE );
00465     if ( !v )
00466       return false;
00467     if ( !v->cast( _typ ) )
00468       return false;
00469     *this = *v;
00470       }
00471       break; */
00472     case DateType:
00473     case TimeType:
00474     case ListType:
00475     case MapType:
00476     case CharType:
00477     case FunctionType:
00478     case MethodType:
00479     case StructBuiltinMethodType:
00480     case StructType:
00481     case StructClassType:
00482     case ModuleType:
00483       // They can be casted to nothing
00484       return false;
00485     case NTypes:
00486       Q_ASSERT(0);
00487       break;
00488     }
00489 
00490   typ = _typ;
00491 
00492   return true;
00493 }
00494 
00495 QString KSValue::toString( KSContext& context )
00496 {
00497   switch( typ )
00498     {
00499     case Empty:
00500       return QString( "<none>" );
00501       break;
00502     case FunctionType:
00503       return QString( "<function>" );
00504       break;
00505     case PropertyType:
00506       return QString( "<property>" );
00507       break;
00508     case TimeType:
00509     return s_koscript_locale->formatTime( timeValue(), true );
00510     case DateType:
00511     return s_koscript_locale->formatDate( dateValue(), true );
00512     case StructClassType:
00513       return ( QString( "<struct class " ) + structClassValue()->name() + ">" );
00514       break;
00515     case ModuleType:
00516       return ( QString( "<module " ) + moduleValue()->name() + ">" );
00517       break;
00518     case StructType:
00519       {
00520     QString tmp( "{ Struct %1 { " );
00521     tmp = tmp.arg( structValue()->getClass()->name() );
00522     const QStringList& lst = structValue()->getClass()->vars();
00523     QStringList::ConstIterator it2 = lst.begin();
00524     for( ; it2 != lst.end(); ++it2 )
00525     {
00526       QString s("( %1, %2 ), ");
00527       KSValue::Ptr ptr = ((KSStruct*)val.ptr)->member( context, *it2 );
00528       s = s.arg( *it2 ).arg( ptr->toString( context ) );
00529       tmp += s;
00530     }
00531     tmp += "} }";
00532     return tmp;
00533       }
00534       break;
00535     case MethodType:
00536       return QString( "<method>" );
00537       break;
00538     case StructBuiltinMethodType:
00539       return QString( "<struct builtin method>" );
00540       break;
00541     case IntType:
00542       {
00543     QString tmp;
00544     tmp.setNum( val.i );
00545     return tmp;
00546       }
00547       break;
00548     case BoolType:
00549       {
00550     if ( val.b )
00551       return QString( "TRUE" );
00552     else
00553       return QString( "FALSE" );
00554       }
00555       break;
00556     case DoubleType:
00557       {
00558     QString tmp;
00559     tmp.setNum( val.d );
00560     return tmp;
00561       }
00562       break;
00563     case StringType:
00564       return *((QString*)val.ptr);
00565       break;
00566     case ListType:
00567       {
00568     QString tmp( "[ " );
00569     QValueList<Ptr>* lst = (QValueList<Ptr>*)val.ptr;
00570     QValueList<Ptr>::Iterator it = lst->begin();
00571     QValueList<Ptr>::Iterator end = lst->end();
00572     for( ; it != end; ++it )
00573     {
00574       tmp += (*it)->toString( context );
00575       tmp += ", ";
00576     }
00577     tmp.truncate( tmp.length() - 1 );
00578     tmp[ tmp.length() - 1 ] = ' ';
00579     tmp += "]";
00580     return tmp;
00581       }
00582       break;
00583     case MapType:
00584       {
00585     QString tmp( "{ " );
00586     QMap<QString,Ptr>* lst = (QMap<QString,Ptr>*)val.ptr;
00587     QMap<QString,Ptr>::Iterator it = lst->begin();
00588     QMap<QString,Ptr>::Iterator end = lst->end();
00589     for( ; it != end; ++it )
00590     {
00591       tmp += "( ";
00592       tmp += it.key();
00593       tmp += ", ";
00594       tmp += it.data()->toString( context );
00595       tmp += " ), ";
00596     }
00597     tmp.truncate( tmp.length() - 1 );
00598     tmp[ tmp.length() - 1 ] = ' ';
00599     tmp += "}";
00600     return tmp;
00601       }
00602       break;
00603     case CharRefType:
00604     case CharType:
00605       {
00606     QString tmp( "'%1'" );
00607     return tmp.arg( charValue() );
00608       }
00609       break;
00610     case NTypes:
00611       Q_ASSERT(0);
00612       break;
00613     }
00614 
00615   // Never reached
00616   return QString::null;
00617 }
00618 
00619 void KSValue::suck( KSValue* v )
00620 {
00621   if ( v->mode() != Temp )
00622   {
00623     *this = *v;
00624     return;
00625   }
00626 
00627   clear();
00628 
00629   typ = v->type();
00630   val = v->val;
00631 
00632   v->typ = Empty;
00633 }
00634 
00635 bool KSValue::operator==( const KSValue& v ) const
00636 {
00637   return ( val.ptr == v.val.ptr && typ == v.typ );
00638 }
00639 
00640 bool KSValue::cmp( const KSValue& v ) const
00641 {
00642   if ( typ != v.typ )
00643     return false;
00644 
00645   switch( typ )
00646     {
00647     case Empty:
00648       return true;
00649     case StringType:
00650       return ( stringValue() == v.stringValue() );
00651     case DateType:
00652       return ( dateValue() == v.dateValue() );
00653     case TimeType:
00654       return ( timeValue() == v.timeValue() );
00655     case KSValue::IntType:
00656       return ( val.i == v.val.i );
00657     case BoolType:
00658       return ( val.b == v.val.b );
00659     case DoubleType:
00660       return ( val.d == v.val.d );
00661     case ListType:
00662       return ( listValue() == v.listValue() );
00663     case MapType:
00664       {
00665     QMap<QString,KSValue::Ptr>::ConstIterator it, it2, end, end2;
00666     it = mapValue().begin();
00667     it2 = v.mapValue().begin();
00668     end = mapValue().end();
00669     end2 = v.mapValue().end();
00670     while( it != end && it2 != end2 )
00671     {
00672       if ( it.key() != it2.key() || !it2.data()->cmp( *it.data() ) )
00673         return false;
00674       ++it;
00675       ++it2;
00676     }
00677     return ( it == end && it2 == end2 );
00678       }
00679     case CharType:
00680       return ( val.c == v.val.c );
00681     case CharRefType:
00682       return ( ((KScript::Char)charRefValue()) == ((KScript::Char)v.charRefValue()) );
00683     case FunctionType:
00684     case MethodType:
00685     case PropertyType:
00686     case ModuleType:
00687     case StructType:
00688     case StructClassType:
00689       return ( val.ptr == v.val.ptr );
00690     case StructBuiltinMethodType:
00691       return ( val.sm == v.val.sm );
00692     case NTypes:
00693       Q_ASSERT( 0 );
00694     }
00695 
00696   // Never reached
00697   return false;
00698 }
00699 
00700 bool KSValue::implicitCast( Type _typ ) const
00701 {
00702     if ( typ == _typ )
00703     return true;
00704 
00705     switch( typ )
00706     {
00707     case Empty:
00708     return false;
00709     case IntType:
00710     if ( _typ == BoolType )
00711         return TRUE;
00712     if ( _typ == DoubleType )
00713         return TRUE;
00714     return false;
00715     case BoolType:
00716     return FALSE;
00717     case DoubleType:
00718     if ( _typ == IntType )
00719         return TRUE;
00720     if ( _typ == BoolType )
00721         return TRUE;
00722       return false;
00723     case StringType:
00724     if ( _typ == BoolType )
00725         return TRUE;
00726     return false;
00727     case CharRefType:
00728     if ( _typ == CharType )
00729         return TRUE;
00730     case DateType:
00731     case TimeType:
00732     case PropertyType:
00733     case ListType:
00734     case MapType:
00735     case CharType:
00736     case FunctionType:
00737     case MethodType:
00738     case StructBuiltinMethodType:
00739     case StructType:
00740     case StructClassType:
00741     case ModuleType:
00742       // They can be casted to nothing
00743       return false;
00744     case NTypes:
00745       Q_ASSERT(0);
00746       break;
00747     }
00748 
00749     return FALSE;
00750 }
KDE Logo
This file is part of the documentation for lib Library Version 1.3.5.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sun Mar 20 14:25:26 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003