00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <stdio.h>
00020 #include <string.h>
00021 #include "urlan.h"
00022 #include "urlan_atoms.h"
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 int calc_eval( UThread* ut, UCell* cell, double* res )
00034 {
00035 switch( ur_type(cell) )
00036 {
00037 case UT_WORD:
00038 {
00039 const UCell* val = ur_wordCell( ut, cell );
00040 if( ! val )
00041 return UR_THROW;
00042 if( ur_is(val, UT_DECIMAL) )
00043 *res = ur_decimal(val);
00044 else if( ur_is(val, UT_INT) || ur_is(val, UT_CHAR) )
00045 *res = (double) ur_int(val);
00046 else
00047 {
00048 return ur_error( ut, UR_ERR_SCRIPT, "Invalid word '%s",
00049 ur_wordCStr( cell ) );
00050 }
00051 }
00052 break;
00053
00054 case UT_DECIMAL:
00055 *res = ur_decimal(cell);
00056 break;
00057
00058 case UT_INT:
00059 case UT_CHAR:
00060 *res = (double) ur_int(cell);
00061 break;
00062
00063 case UT_BLOCK:
00064 case UT_PAREN:
00065 {
00066 UBlockIterM bi;
00067 double num = 0.0;
00068 double right;
00069
00070 #define RIGHT_VAL \
00071 if( ++bi.it == bi.end ) \
00072 return ur_error( ut, UR_ERR_SCRIPT, "Expected operator r-value" ); \
00073 if( ! calc_eval( ut, bi.it, &right ) ) \
00074 return UR_THROW;
00075
00076 if( ! ur_blkSliceM( ut, &bi, cell ) )
00077 return UR_THROW;
00078 ur_foreach( bi )
00079 {
00080 if( ur_is(bi.it, UT_WORD) )
00081 {
00082 switch( ur_atom(bi.it) )
00083 {
00084 case UR_ATOM_PLUS:
00085 RIGHT_VAL
00086 num += right;
00087 break;
00088
00089 case UR_ATOM_MINUS:
00090 RIGHT_VAL
00091 num -= right;
00092 break;
00093
00094 case UR_ATOM_ASTERISK:
00095 RIGHT_VAL
00096 num *= right;
00097 break;
00098
00099 case UR_ATOM_SLASH:
00100 RIGHT_VAL
00101 num /= right;
00102 break;
00103
00104 default:
00105 if( ! calc_eval( ut, bi.it, &num ) )
00106 return UR_THROW;
00107 }
00108 }
00109 else if( ur_is(bi.it, UT_SETWORD) )
00110 {
00111 cell = ur_wordCellM( ut, bi.it );
00112 if( ! cell )
00113 return UR_THROW;
00114 ur_setId( cell, UT_DECIMAL );
00115 ur_decimal(cell) = num;
00116 }
00117 else
00118 {
00119 if( ! calc_eval( ut, bi.it, &num ) )
00120 return UR_THROW;
00121 }
00122 }
00123 *res = num;
00124 }
00125 break;
00126
00127 default:
00128 *res = 0.0;
00129 break;
00130 }
00131 return UR_OK;
00132 }
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 int calc_evalCStr( UThread* ut, const char* cmd, double* result )
00143 {
00144 UCell cell;
00145 UIndex blkN;
00146 UIndex hold;
00147 int ok;
00148 int len = strlen( cmd );
00149 if( len )
00150 {
00151 blkN = ur_tokenize( ut, cmd, cmd + len, &cell );
00152 if( blkN )
00153 {
00154 ur_bind(ut, ur_buffer(blkN), ur_threadContext(ut), UR_BIND_THREAD);
00155
00156
00157
00158 hold = ur_hold( blkN );
00159 ok = calc_eval( ut, &cell, result );
00160 ur_release( hold );
00161
00162 return ok;
00163 }
00164 return UR_THROW;
00165 }
00166 return UR_OK;
00167 }
00168
00169
00170
00171
00172
00173 void defineWords( UThread* ut )
00174 {
00175 static double constants[2] = { 3.14159265358979, 2.71828182845904 };
00176 UAtom atoms[2];
00177 UBuffer* ctx;
00178 UCell* cell;
00179 int i;
00180
00181 ur_internAtoms( ut, "pi e", atoms );
00182
00183 ctx = ur_threadContext( ut );
00184 for( i = 0; i < 2; ++i )
00185 {
00186 cell = ur_ctxAddWord( ctx, atoms[i] );
00187 ur_setId( cell, UT_DECIMAL );
00188 ur_decimal(cell) = constants[i];
00189 }
00190 ur_ctxSort( ctx );
00191 }
00192
00193
00194 int main( int argc, char** argv )
00195 {
00196 UThread* ut;
00197 char cmd[ 2048 ];
00198 double result;
00199 (void) argc;
00200 (void) argv;
00201
00202
00203 printf( "Urlan Calculator Example %s (%s)\n", UR_VERSION_STR, __DATE__ );
00204
00205 ut = ur_makeEnv( 256, 0, 0, 0, 0 );
00206 if( ! ut )
00207 {
00208 printf( "ur_makeEnv failed\n" );
00209 return 255;
00210 }
00211
00212 defineWords( ut );
00213
00214 while( 1 )
00215 {
00216 printf( ")> " );
00217 fflush( stdout );
00218 fgets( cmd, sizeof(cmd), stdin );
00219
00220 if( cmd[0] < ' ' )
00221 {
00222 printf( "\n" );
00223 }
00224 else if( cmd[0] == 'q' )
00225 {
00226 break;
00227 }
00228 else
00229 {
00230 if( calc_evalCStr( ut, cmd, &result ) )
00231 {
00232 printf( "= %f\n", result );
00233 }
00234 else
00235 {
00236 UBuffer* blk = ur_errorBlock(ut);
00237 if( blk->used )
00238 {
00239 UBuffer str;
00240
00241 ur_strInit( &str, UR_ENC_UTF8, 0 );
00242 ur_toStr( ut, blk->ptr.cell, &str, 0 );
00243 ur_strTermNull( &str );
00244 printf( "%s\n", str.ptr.c );
00245 ur_strFree( &str );
00246
00247 blk->used = 0;
00248 }
00249 else
00250 break;
00251 }
00252 }
00253 }
00254
00255 ur_freeEnv( ut );
00256 return 0;
00257 }
00258
00259
00260