flush
[m6w6/ext-psi] / src / compiler.c
diff --git a/src/compiler.c b/src/compiler.c
new file mode 100644 (file)
index 0000000..e075a39
--- /dev/null
@@ -0,0 +1,81 @@
+#include <stdlib.h>
+
+#include <jit/jit.h>
+
+#include <php.h>
+#include <Zend/Zend_API.h>
+
+#include "compiler.h"
+
+PSI_Compiler *PSI_CompilerInit(PSI_Compiler *C, PSI_Validator *V)
+{
+       if (!C) {
+               C = malloc(sizeof(*C));
+       }
+       memset(C, 0, sizeof(*C));
+
+       PSI_DataExchange((PSI_Data *) C, (PSI_Data *) V);
+       return C;
+}
+
+typedef struct PSI_ClosureData {
+       impl *impl;
+} PSI_ClosureData;
+
+static inline size_t impl_num_min_args(impl *impl) {
+       size_t i, n = impl->func->args->count;
+
+       for (i = 0; i < impl->func->args->count; ++i) {
+               if (impl->func->args->args[i]->def) {
+                       --n;
+               }
+       }
+       return n;
+}
+void PSI_Closure(jit_type_t signature, void *result, void **args, void *user_data)
+{
+       zend_execute_data *execute_data = args[0];
+       zval *return_value = args[1];
+       PSI_ClosureData *data = user_data;
+       impl_arg *iarg;
+
+       if (!data->impl->func->args->count) {
+               if (SUCCESS != zend_parse_parameters_none()) {
+                       return;
+               }
+       } else
+       ZEND_PARSE_PARAMETERS_START(impl_num_min_args(data->impl), data->impl->func->args->count)
+       nextarg:
+               iarg = data->impl->func->args->args[_i];
+               if (iarg->def) {
+                       Z_PARAM_OPTIONAL;
+               }
+               if (PSI_T_BOOL == iarg->type->type) {
+                       if (iarg->def) {
+                               iarg->val.bval = iarg->def->type == PSI_T_TRUE ? 1 : 0;
+                       }
+                       Z_PARAM_BOOL(iarg->val.bval);
+               } else if (PSI_T_INT == iarg->type->type) {
+                       if (iarg->def) {
+                               iarg->val.lval = atol(iarg->def->text);
+                       }
+                       Z_PARAM_LONG(iarg->val.lval);
+               } else if (PSI_T_FLOAT == iarg->type->type) {
+                       if (iarg->def) {
+                               iarg->val.dval = strtod(iarg->def->text, NULL);
+                       }
+                       Z_PARAM_DOUBLE(iarg->val.dval);
+               } else if (PSI_T_STRING == iarg->type->type) {
+                       if (iarg->def) {
+                               /* FIXME */
+                               iarg->val.str.len = strlen(iarg->def->text) - 2;
+                               iarg->val.str.val = &iarg->def->text[1];
+                       }
+                       Z_PARAM_STRING(iarg->val.str.val, iarg->val.str.len);
+               } else {
+                       error_code = ZPP_ERROR_FAILURE;
+                       break;
+               }
+               goto nextarg;
+       ZEND_PARSE_PARAMETERS_END();
+}