1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/libxexpr/extension.c Wed Oct 10 22:58:21 2012 +0100
1.3 @@ -0,0 +1,209 @@
1.4 +#include <stdlib.h>
1.5 +#include <string.h>
1.6 +#include <math.h>
1.7 +#include <xexpr.h>
1.8 +#include "xexprprivate.h"
1.9 +
1.10 +static XexprConstant *xexpr_do_pi(Xexpr *xexpr,GSList *bindings,GSList *args,
1.11 + GError **err)
1.12 +{
1.13 + return xexpr_new_number(M_PI);
1.14 +}
1.15 +
1.16 +static XexprConstant *xexpr_do_sin(Xexpr *xexpr,GSList *bindings,GSList *args,
1.17 + GError **err)
1.18 +{
1.19 + XexprConstant *x;
1.20 + x=xexpr_bindings_get(bindings,"x");
1.21 + if (!x)
1.22 + {
1.23 + if (args)
1.24 + {
1.25 + x=args->data;
1.26 + args=args->next;
1.27 + }
1.28 + else
1.29 + {
1.30 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
1.31 + "Missing \"x\" argument to \"libxexpr:sin\"");
1.32 + return NULL;
1.33 + }
1.34 + }
1.35 + if (!xexpr_constant_cast(x,XEXPR_TYPE_NUMBER))
1.36 + return xexpr_new_number(0.0/0.0);
1.37 + if (!isfinite(x->u.number))
1.38 + return xexpr_new_number(0.0/0.0);
1.39 + else
1.40 + return xexpr_new_number(sin(x->u.number));
1.41 +}
1.42 +
1.43 +static XexprConstant *xexpr_do_atan(Xexpr *xexpr,GSList *bindings,GSList *args,
1.44 + GError **err)
1.45 +{
1.46 + XexprConstant *x,*y;
1.47 + x=xexpr_bindings_get(bindings,"x");
1.48 + if (!x)
1.49 + {
1.50 + if (args)
1.51 + {
1.52 + x=args->data;
1.53 + args=args->next;
1.54 + }
1.55 + else
1.56 + {
1.57 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
1.58 + "Missing \"x\" argument to \"libxexpr:atan\"");
1.59 + return NULL;
1.60 + }
1.61 + }
1.62 + if (!xexpr_constant_cast(x,XEXPR_TYPE_NUMBER))
1.63 + return xexpr_new_number(0.0/0.0);
1.64 + y=xexpr_bindings_get(bindings,"y");
1.65 + if (!y && args)
1.66 + {
1.67 + y=args->data;
1.68 + args=args->next;
1.69 + }
1.70 + if (y && !xexpr_constant_cast(y,XEXPR_TYPE_NUMBER))
1.71 + return xexpr_new_number(0.0/0.0);
1.72 + if (!isfinite(x->u.number) || y && !isfinite(y->u.number))
1.73 + return xexpr_new_number(0.0/0.0);
1.74 + else if (y)
1.75 + return xexpr_new_number(atan2(y->u.number,x->u.number));
1.76 + else
1.77 + return xexpr_new_number(atan(x->u.number));
1.78 +}
1.79 +
1.80 +static XexprConstant *xexpr_do_exp(Xexpr *xexpr,GSList *bindings,GSList *args,
1.81 + GError **err)
1.82 +{
1.83 + XexprConstant *x;
1.84 + x=xexpr_bindings_get(bindings,"x");
1.85 + if (!x && args)
1.86 + {
1.87 + x=args->data;
1.88 + args=args->next;
1.89 + }
1.90 + if (x && !xexpr_constant_cast(x,XEXPR_TYPE_NUMBER))
1.91 + return xexpr_new_number(0.0/0.0);
1.92 + if (x && !isfinite(x->u.number))
1.93 + return xexpr_new_number(0.0/0.0);
1.94 + else
1.95 + return xexpr_new_number(x?exp(x->u.number):exp(1.0));
1.96 +}
1.97 +
1.98 +static XexprConstant *xexpr_do_log(Xexpr *xexpr,GSList *bindings,GSList *args,
1.99 + GError **err)
1.100 +{
1.101 + XexprConstant *x;
1.102 + x=xexpr_bindings_get(bindings,"x");
1.103 + if (!x)
1.104 + {
1.105 + if (args)
1.106 + {
1.107 + x=args->data;
1.108 + args=args->next;
1.109 + }
1.110 + else
1.111 + {
1.112 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
1.113 + "Missing \"x\" argument to \"libxexpr:log\"");
1.114 + return NULL;
1.115 + }
1.116 + }
1.117 + if (!xexpr_constant_cast(x,XEXPR_TYPE_NUMBER))
1.118 + return xexpr_new_number(0.0/0.0);
1.119 + if (!isfinite(x->u.number))
1.120 + return xexpr_new_number(0.0/0.0);
1.121 + else
1.122 + return xexpr_new_number(log(x->u.number));
1.123 +}
1.124 +
1.125 +static XexprConstant *xexpr_do_pow(Xexpr *xexpr,GSList *bindings,GSList *args,
1.126 + GError **err)
1.127 +{
1.128 + XexprConstant *x,*y;
1.129 + x=xexpr_bindings_get(bindings,"x");
1.130 + if (!x)
1.131 + {
1.132 + if (args)
1.133 + {
1.134 + x=args->data;
1.135 + args=args->next;
1.136 + }
1.137 + else
1.138 + {
1.139 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
1.140 + "Missing \"x\" argument to \"libxexpr:atan\"");
1.141 + return NULL;
1.142 + }
1.143 + }
1.144 + if (!xexpr_constant_cast(x,XEXPR_TYPE_NUMBER))
1.145 + return xexpr_new_number(0.0/0.0);
1.146 + y=xexpr_bindings_get(bindings,"y");
1.147 + if (!y)
1.148 + {
1.149 + if (args)
1.150 + {
1.151 + y=args->data;
1.152 + args=args->next;
1.153 + }
1.154 + else
1.155 + {
1.156 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
1.157 + "Missing \"y\" argument to \"libxexpr:pow\"");
1.158 + return NULL;
1.159 + }
1.160 + }
1.161 + if (!xexpr_constant_cast(y,XEXPR_TYPE_NUMBER))
1.162 + return xexpr_new_number(0.0/0.0);
1.163 + if (x->u.number==1 || y->u.number==0)
1.164 + return xexpr_new_number(1.0);
1.165 + else if (!isfinite(x->u.number) || !isfinite(y->u.number))
1.166 + return xexpr_new_number(0.0/0.0);
1.167 + else
1.168 + return xexpr_new_number(pow(x->u.number,y->u.number));
1.169 +}
1.170 +
1.171 +static struct libxexpr_function {
1.172 + char *id;
1.173 + XexprConstant *(*func)(Xexpr *xexpr,GSList *bindings,GSList *args,
1.174 + GError **err);
1.175 +} libxexpr_functions[]={
1.176 + { "pi", xexpr_do_pi },
1.177 + { "sin", xexpr_do_sin },
1.178 + { "atan", xexpr_do_atan },
1.179 + { "exp", xexpr_do_exp },
1.180 + { "log", xexpr_do_log },
1.181 + { "pow", xexpr_do_pow },
1.182 +};
1.183 +
1.184 +XexprConstant *_xexpr_libxexpr_function_evaluate(Xexpr *xexpr,const char *ns,
1.185 + const char *id,GSList *bindings,GSList *args,GError **err)
1.186 +{
1.187 + int func;
1.188 + XexprConstant *value,*result;
1.189 + GSList *evaluated_args=NULL;
1.190 + for(func=0;func<G_N_ELEMENTS(libxexpr_functions);func++)
1.191 + if (!strcmp(libxexpr_functions[func].id,id))
1.192 + break;
1.193 + if (func==G_N_ELEMENTS(libxexpr_functions))
1.194 + {
1.195 + g_set_error(err,XEXPR_EVAL_ERROR,XEXPR_EVAL_ERROR_FAILED,
1.196 + "Undefined function: \"libxexpr:%s\"",id);
1.197 + return NULL;
1.198 + }
1.199 + while(args)
1.200 + {
1.201 + value=xexpr_constant_evaluate(xexpr,args->data,err);
1.202 + if (!value)
1.203 + return NULL;
1.204 + evaluated_args=g_slist_prepend(evaluated_args,value);
1.205 + args=args->next;
1.206 + }
1.207 + evaluated_args=g_slist_reverse(evaluated_args);
1.208 + result=libxexpr_functions[func].func(xexpr,bindings,evaluated_args,err);
1.209 + g_slist_foreach(evaluated_args,(GFunc)xexpr_constant_free,NULL);
1.210 + g_slist_free(evaluated_args);
1.211 + return result;
1.212 +}