* pemalloc
* unions
* callbacks and function pointers
+* let impl_Var point to impl_arg, just like decl_var?
\ No newline at end of file
}
free(C->structs);
}
+ if (C->unions) {
+ if (C->unions->list) {
+ free(C->unions->list);
+ }
+ free(C->unions);
+ }
if (C->enums) {
if (C->enums->list) {
free(C->enums->list);
#include "php_psi_macros.h"
#include "php_psi_redirs.h"
+#include "parser.h"
#include "calc.h"
#include "marshal.h"
#include "engine.h"
return 0;
}
+static inline int locate_decl_type_decl(decls *decls, decl_type *type) {
+ size_t i;
+
+ if (type->func) {
+ return 1;
+ }
+ if (decls) for (i = 0; i < decls->count; ++i) {
+ if (!strcmp(decls->list[i]->func->var->name, type->name)) {
+ type->func = decls->list[i];
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
static inline int validate_decl_struct(PSI_Data *data, decl_struct *s);
static inline int validate_decl_union(PSI_Data *data, decl_union *u);
static inline int validate_decl_enum(PSI_Data *data, decl_enum *e);
if (!locate_decl_type_enum(data->enums, type)) {
return 0;
}
+ break;
+ case PSI_T_FUNCTION:
+ if (!locate_decl_type_decl(data->decls, type)) {
+ return 0;
+ }
+ break;
}
return 1;
}
}
}
- if (ref_type->type == PSI_T_STRUCT) {
+ if (set->inner && ref_type->type == PSI_T_STRUCT) {
/* to_array(struct, to_...) */
if (!set->outer.set || set->outer.set->inner->vals != set->inner->vals) {
for (i = 0; i < set->inner->count; ++i) {
return 0;
}
- impl->decl->impl = impl;
+ //impl->decl->impl = impl;
return 1;
}
-static inline int validate_let_func(PSI_Data *data, let_func *func, impl *impl) {
- int check = 0;
- size_t j;
+static inline impl_arg *locate_impl_var_arg(impl_var *var, impl_args *args) {
+ size_t i;
- if (impl->func->args) {
- for (j = 0; j < impl->func->args->count; ++j) {
- impl_arg *iarg = impl->func->args->args[j];
+ for (i = 0; i < args->count; ++i) {
+ impl_arg *iarg = args->args[i];
- if (!strcmp(func->var->name, iarg->var->name)) {
- func->arg = iarg;
- check = 1;
- break;
- }
+ if (!strcmp(var->name, iarg->var->name)) {
+ return var->arg = iarg;
}
}
- if (!check) {
- data->error(data, func->var->token, PSI_WARNING, "Unknown value '$%s' of `let` statement"
- " for cast '%s' of implementation '%s'",
- func->var->name, func->name, impl->func->name);
- return 0;
+
+ return NULL;
+}
+
+static inline int validate_let_func(PSI_Data *data, let_func *func, impl *impl) {
+ if (impl->func->args) {
+ if (!locate_impl_var_arg(func->var, impl->func->args)) {
+ data->error(data, func->var->token, PSI_WARNING,
+ "Unknown variable '$%s' of `let` statement"
+ " for cast '%s' of implementation '%s'",
+ func->var->name, func->name, impl->func->name);
+ return 0;
+ }
+ }
+ switch (func->type) {
+ case PSI_T_BOOLVAL: func->handler = psi_let_boolval; break;
+ case PSI_T_INTVAL: func->handler = psi_let_intval; break;
+ case PSI_T_FLOATVAL: func->handler = psi_let_floatval; break;
+ case PSI_T_STRVAL: func->handler = psi_let_strval; break;
+ case PSI_T_STRLEN: func->handler = psi_let_strlen; break;
+ case PSI_T_PATHVAL: func->handler = psi_let_pathval; break;
+ case PSI_T_ARRVAL: func->handler = psi_let_arrval; break;
+ case PSI_T_OBJVAL: func->handler = psi_let_objval; break;
+ EMPTY_SWITCH_DEFAULT_CASE();
}
return 1;
}
-static inline int validate_let_callback(PSI_Data *data, decl_var *let_var, let_callback *cb, impl *impl) {
- decl_type *cb_type;
- decl *cb_func;
+static inline int validate_let_callback(PSI_Data *data, decl_var *cb_var, let_callback *cb, impl *impl) {
size_t i;
+ decl *cb_func;
+ decl_type *cb_type = real_decl_type(cb_var->arg->type);
if (!validate_let_func(data, cb->func, impl)) {
return 0;
}
- cb_type = real_decl_type(let_var->arg->type);
if (cb_type->type != PSI_T_FUNCTION) {
- data->error(data, let_var->token, PSI_WARNING, "Not a function: %s", let_var->name);
+ data->error(data, cb_var->token, PSI_WARNING, "Not a function: %s", cb_var->name);
return 0;
}
cb_func = cb_type->func;
return 0;
}
}
+
+ if (!validate_decl(data, NULL, cb_func)) {
+ return 0;
+ }
+
+ cb->decl = cb_func;
+
+ return 1;
}
static inline int validate_impl_let_stmts(PSI_Data *data, impl *impl) {
for (i = 0; i < impl->stmts->let.count; ++i) {
let_stmt *let = impl->stmts->let.list[i];
decl_var *let_var;
- int check = 0;
if (let->val && let->val->kind == PSI_LET_TMP) {
let_var = let->val->data.var;
static inline impl_val *psi_let_val(token_t let_func, impl_arg *iarg, impl_val *arg_val, decl_struct *strct, void **to_free)
{
- switch (let_func) {
- case PSI_T_BOOLVAL:
- break;
- case PSI_T_INTVAL:
- break;
- case PSI_T_FLOATVAL:
- break;
- case PSI_T_PATHVAL:
- case PSI_T_STRVAL:
- if (PSI_T_PATHVAL == let_func) {
-
- }
- break;
- case PSI_T_STRLEN:
- break;
- case PSI_T_ARRVAL:
- if (iarg->type->type == PSI_T_ARRAY) {
- arg_val = psi_array_to_struct(strct, HASH_OF(iarg->_zv));
- *to_free = arg_val;
- }
- break;
- case PSI_T_OBJVAL:
- if (iarg->type->type == PSI_T_OBJECT) {
- psi_object *obj;
-
- if (!instanceof_function(Z_OBJCE_P(iarg->_zv), psi_object_get_class_entry())) {
- return NULL;
- }
-
- obj = PSI_OBJ(iarg->_zv, NULL);
- arg_val->ptr = obj->data;
- }
- break;
- case PSI_T_CALLBACK:
- if (iarg->type->type == PSI_T_CALLABLE) {
-
- }
- break;
- EMPTY_SWITCH_DEFAULT_CASE();
- }
+ abort();
return arg_val;
}
static inline impl_val *psi_let_func(let_func *func, decl_arg *darg) {
- return darg->ptr = func->handler(darg->ptr, darg->type, func->arg, &darg->mem);
+ return darg->ptr = func->handler(darg->ptr, darg->type, func->var->arg, &darg->mem);
}
static inline void *psi_do_let(let_stmt *let)
{
decl_arg *darg = let->var->arg;
impl_val *arg_val = darg->ptr;
- impl_arg *iarg;
switch (let->val ? let->val->kind : PSI_LET_NULL) {
case PSI_LET_TMP:
darg->mem = arg_val->ptr;
break;
case PSI_LET_CALLBACK:
- arg_val->ptr = 0 /* callback closure */;
+ arg_val->ptr = let->val->data.callback->decl->call.sym;
break;
case PSI_LET_NUMEXP:
arg_val->zend.lval = psi_long_num_exp(let->val->data.num, NULL);
if (!psi_let_func(let->val->data.func, darg)) {
return NULL;
}
-
- iarg = let->val->data.func->arg;
-
- if (!(darg->ptr = psi_let_val(let->val->data.func->type, iarg, darg->ptr, real_decl_type(darg->type)->strct, &darg->mem))) {
- return NULL;
- }
+ break;
}
if (let->val && let->val->flags.one.is_reference) {
static void psi_ffi_callback(ffi_cif *_sig, void *_result, void **_args, void *_data)
{
+ size_t i;
unsigned argc = _sig->nargs;
void **argv = _args;
- ffi_arg *res = _result;
- let_stmt *let;
- decl_arg *darg = let->var->arg;
- decl *decl_cb = darg->type->func;
- let_callback *cb = let->val->data.callback;
- impl_arg *iarg = cb->func->arg;
- size_t i, argc = cb->args->count;
- zval return_value, *argv = calloc(argc, sizeof(*argv));
-
- // prepare args for the userland call
- for (i = 0; i < decl_cb->args->count; ++i) {
+ let_callback *cb = _data;
+ decl *decl_cb = cb->decl;
+ impl_arg *iarg = cb->func->var->arg;
+ zval return_value, *zargv = calloc(argc, sizeof(*zargv));
+ void *result, *to_free = NULL;
+
+ ZEND_ASSERT(argc == cb->decl->args->count);
+ /* prepare args for the userland call */
+ for (i = 0; i < argc; ++i) {
+ cb->decl->args->args[i]->ptr = argv[i];
}
for (i = 0; i < cb->args->count; ++i) {
- psi_do_set(&argv[i], cb->args->vals[i]);
+ psi_do_set(&zargv[i], cb->args->vals[i]);
}
- zend_fcall_info_argp(iarg->val.zend.cb->fci, argc, argv);
- zend_fcall_info_call(&iarg->val.zend.cb->fci, &iarg->val.zend.cb->fcc,
- &return_value, NULL);
- // marshal return value of the userland call
- switch (cb->func->type) {
- case PSI_T_BOOLVAL:
- break;
- case PSI_T_INTVAL:
- break;
- case PSI_T_FLOATVAL:
- break;
- case PSI_T_PATHVAL:
- case PSI_T_STRVAL:
- break;
- case PSI_T_STRLEN:
- break;
- case PSI_T_ARRVAL:
- break;
- case PSI_T_OBJVAL:
- break;
- case PSI_T_CALLBACK:
- break;
- EMPTY_SWITCH_DEFAULT_CASE();
+ zend_fcall_info_argp(&iarg->val.zend.cb->fci, cb->args->count, zargv);
+
+ /* callback into userland */
+ ZVAL_UNDEF(&return_value);
+ iarg->_zv = &return_value;
+ zend_fcall_info_call(&iarg->val.zend.cb->fci, &iarg->val.zend.cb->fcc, iarg->_zv, NULL);
+
+ /* marshal return value of the userland call */
+ switch (iarg->type->type) {
+ case PSI_T_BOOL: zend_parse_arg_bool(iarg->_zv, &iarg->val.zend.bval, NULL, 0); break;
+ case PSI_T_LONG: zend_parse_arg_long(iarg->_zv, &iarg->val.zend.lval, NULL, 0, 1); break;
+ case PSI_T_FLOAT:
+ case PSI_T_DOUBLE: zend_parse_arg_double(iarg->_zv, &iarg->val.dval, NULL, 0); break;
+ case PSI_T_STRING: zend_parse_arg_str(iarg->_zv, &iarg->val.zend.str, 0); break;
+ }
+ result = cb->func->handler(_result, decl_cb->func->type, iarg, &to_free);
+
+ if (result != _result) {
+ *(void **)_result = result;
}
- darg->ptr = psi_let_val(cb->func->type, iarg, darg->ptr, real_decl_type(darg->type)->strct, &darg->mem);
}
static inline ffi_type *psi_ffi_decl_arg_type(decl_arg *darg);
return call;
}
-static inline void PSI_LibffiCallInitClosure(PSI_Context *C, PSI_LibffiCall *call, impl *impl) {
+static inline ffi_status PSI_LibffiCallInitClosure(PSI_Context *C, PSI_LibffiCall *call, impl *impl) {
PSI_LibffiContext *context = C->context;
- ffi_status rc;
- rc = psi_ffi_prep_closure(&call->closure, &call->code, &context->signature, psi_ffi_handler, impl);
- ZEND_ASSERT(FFI_OK == rc);
+ return psi_ffi_prep_closure(&call->closure, &call->code, &context->signature, psi_ffi_handler, impl);
+}
+
+static inline ffi_status PSI_LibffiCallInitCallbackClosure(PSI_Context *C, PSI_LibffiCall *call, let_callback *cb) {
+ return psi_ffi_prep_closure(&call->closure, &call->code, &call->signature, psi_ffi_callback, cb);
}
static inline void PSI_LibffiCallFree(PSI_LibffiCall *call) {
switch (real->type) {
case PSI_T_FUNCTION:
- if (!real->func->call.sym) {
- PSI_LibffiCall *call = PSI_LibffiCallAlloc(&PSI_G(context), real->func);
- ffi_status rc;
-
- rc = psi_ffi_prep_closure(
- (void *) &real->func->call.closure.data,
- &real->func->call.sym, &call->signature, psi_ffi_handler, NULL);
- if (FFI_OK == rc) {
- real->func->call.info = call;
- real->func->call.closure.dtor = psi_ffi_closure_free;
- }
- }
return &ffi_type_pointer;
case PSI_T_STRUCT:
static zend_function_entry *psi_ffi_compile(PSI_Context *C)
{
- size_t i, j = 0;
+ size_t c, i, j = 0;
zend_function_entry *zfe;
if (!C->impls) {
}
call = PSI_LibffiCallAlloc(C, impl->decl);
- PSI_LibffiCallInitClosure(C, call, impl);
+ if (FFI_OK != PSI_LibffiCallInitClosure(C, call, impl)) {
+ PSI_LibffiCallFree(call);
+ continue;
+ }
zf->fname = impl->func->name + (impl->func->name[0] == '\\');
zf->num_args = impl->func->args->count;
zf->handler = call->code;
zf->arg_info = psi_internal_arginfo(impl);
++j;
+
+ for (c = 0; c < impl->stmts->let.count; ++c) {
+ let_stmt *let = impl->stmts->let.list[c];
+
+ if (let->val->kind == PSI_LET_CALLBACK) {
+ let_callback *cb = let->val->data.callback;
+
+ call = PSI_LibffiCallAlloc(C, cb->decl);
+ if (FFI_OK != PSI_LibffiCallInitCallbackClosure(C, call, cb)) {
+ PSI_LibffiCallFree(call);
+ continue;
+ }
+
+ cb->decl->call.sym = call->code;
+ }
+ }
}
for (i = 0; i < C->decls->count; ++i) {
decl *decl = C->decls->list[i];
- if (decl->impl) {
+// if (decl->impl) {
+// continue;
+// }
+ if (decl->call.info) {
continue;
}
}
static inline impl_val *psi_val_intval(impl_val *tmp, token_t real_type, zend_long intval) {
- switch (real_decl_type(type)->type) {
+ switch (real_type) {
case PSI_T_INT8: tmp->i8 = intval; break;
case PSI_T_UINT8: tmp->u8 = intval; break;
case PSI_T_INT16: tmp->i16 = intval; break;
}
static inline impl_val *psi_val_floatval(impl_val *tmp, token_t real_type, double floatval) {
- switch (real_decl_type(type)->type) {
+ switch (real_type) {
case PSI_T_INT8: tmp->i8 = floatval; break;
case PSI_T_UINT8: tmp->u8 = floatval; break;
case PSI_T_INT16: tmp->i16 = floatval; break;
impl_val *psi_let_floatval(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free)
{
double floatval;
- token_t real_type = type ? real_decl_type(type)->real : PSI_T_DOUBLE;
+ token_t real_type = type ? real_decl_type(type)->type : PSI_T_DOUBLE;
if (iarg->type->type == PSI_T_FLOAT || iarg->type->type == PSI_T_DOUBLE) {
floatval = iarg->val.dval;
}
}
-impl_val *psi_arrval(impl_val *tmp, decl_type *type, void *val, void **to_free)
+impl_val *psi_let_arrval(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free)
{
- HashTable *arr = (HashTable *) val;
- decl_type *real = type ? real_decl_type(type) : NULL;
+ decl_type *real = real_decl_type(type);
+ HashTable *arr;
+
+ if (iarg->type->type != PSI_T_ARRAY) {
+ SEPARATE_ARG_IF_REF(iarg->_zv);
+ convert_to_array(iarg->_zv);
+ }
+ arr = HASH_OF(iarg->_zv);
- ZEND_ASSERT(real && real->type == PSI_T_STRUCT);
- return *to_free = psi_array_to_struct(real->strct, arr);
+ switch (real->type) {
+ case PSI_T_STRUCT:
+ *to_free = tmp = psi_array_to_struct(real->strct, arr);
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE();
+ }
+
+ return tmp;
}
void psi_to_object(zval *return_value, set_value *set, impl_val *r_val)
}
}
-impl_val *psi_objval(impl_val *tmp, decl_type *type, void *val, void **to_free)
+impl_val *psi_let_objval(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free)
{
- zval *zv = (zval *) val;
psi_object *obj;
- if (!instanceof_function(Z_OBJCE_P(zv), psi_object_get_class_entry())) {
+ if (Z_TYPE_P(iarg->_zv) != IS_OBJECT
+ || !instanceof_function(Z_OBJCE_P(iarg->_zv), psi_object_get_class_entry())) {
return NULL;
}
- obj = PSI_OBJ(zv, NULL);
+ obj = PSI_OBJ(iarg->_zv, NULL);
tmp->ptr = obj->data;
return tmp;
void *psi_array_to_struct(decl_struct *s, HashTable *arr);
void psi_from_zval(impl_val *mem, decl_arg *spec, zval *zv, void **tmp);
+impl_val *psi_let_boolval(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free);
+impl_val *psi_let_intval(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free);
+impl_val *psi_let_floatval(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free);
+impl_val *psi_let_strval(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free);
+impl_val *psi_let_pathval(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free);
+impl_val *psi_let_strlen(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free);
+impl_val *psi_let_arrval(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free);
+impl_val *psi_let_objval(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free);
+
#endif
decl_type *type;
decl_var *var;
decl_struct_layout *layout;
- struct let_stmt *let;
+ struct let_stmt *let; /* FIXME: decls must not point to impls !!! */
impl_val val;
void *ptr;
void *mem;
size_t argc;
void **args;
void **rval;
- struct {
- void *data;
- void (*dtor)(void *data);
- } closure;
} decl_callinfo;
typedef struct decl {
typedef struct impl_var {
PSI_Token *token;
char *name;
+ struct impl_arg *arg;
unsigned reference:1;
} impl_var;
impl_arg *arg = calloc(1, sizeof(*arg));
arg->type = type;
arg->var = var;
+ arg->var->arg = arg;
arg->def = def;
return arg;
}
typedef struct let_callback {
struct let_func *func;
struct set_values *args;
+ decl *decl;
} let_callback;
static inline void free_let_func(struct let_func *func);
token_t type;
char *name;
impl_var *var;
- impl_arg *arg;
- impl_val *(*handler)(impl_val *tmp, decl_type *type, void *val, void **to_free);
+ impl_val *(*handler)(impl_val *tmp, decl_type *type, impl_arg *iarg, void **to_free);
} let_func;
static inline let_func *init_let_func(token_t type, const char *name, impl_var *var) {
val->vars = vars;
return val;
}
+
+static inline set_values *add_set_value(set_values *vals, set_value *val);
static inline set_value *add_inner_set_value(set_value *val, set_value *inner) {
- val->inner->vals = realloc(val->inner->vals, ++val->inner->count * sizeof(*val->inner->vals));
- val->inner->vals[val->inner->count-1] = inner;
+ val->inner = add_set_value(val->inner, inner);
inner->outer.set = val;
return val;
}
free_decl_vars(val->vars);
}
if (val->inner && (!val->outer.set || val->outer.set->inner != val->inner)) {
- size_t i;
- for (i = 0; i < val->inner->count; ++i) {
- free_set_value(val->inner->vals[i]);
- }
- free(val->inner->vals);
+ free_set_values(val->inner);
}
if (val->num) {
free_num_exp(val->num);
}
static inline set_values *add_set_value(set_values *vals, set_value *val) {
+ if (!vals) {
+ vals = calloc(1, sizeof(*vals));
+ }
vals->vals = realloc(vals->vals, ++vals->count * sizeof(val));
vals->vals[vals->count-1] = val;
return vals;
static inline void free_set_values(set_values *vals) {
if (vals->vals) {
+ size_t i;
+
+ for (i = 0; i < vals->count; ++i) {
+ free_set_value(vals->vals[i]);
+ }
free(vals->vals);
}
free(vals);
#define PSI_T_LET 9
#define PSI_T_RETURN 10
#define PSI_T_CALLOC 11
-#define PSI_T_LIB 12
-#define PSI_T_STRING 13
-#define PSI_T_EOF 14
-#define PSI_T_EOS 15
-#define PSI_T_QUOTED_STRING 16
-#define PSI_T_ENUM 17
-#define PSI_T_LBRACE 18
-#define PSI_T_RBRACE 19
-#define PSI_T_COMMA 20
-#define PSI_T_EQUALS 21
-#define PSI_T_UNION 22
-#define PSI_T_STRUCT 23
-#define PSI_T_COLON 24
-#define PSI_T_LPAREN 25
-#define PSI_T_NUMBER 26
-#define PSI_T_RPAREN 27
-#define PSI_T_BOOL 28
-#define PSI_T_INT 29
-#define PSI_T_FLOAT 30
-#define PSI_T_CONST 31
-#define PSI_T_NSNAME 32
-#define PSI_T_TYPEDEF 33
-#define PSI_T_VOID 34
-#define PSI_T_LBRACKET 35
-#define PSI_T_RBRACKET 36
-#define PSI_T_ELLIPSIS 37
-#define PSI_T_CHAR 38
-#define PSI_T_SHORT 39
-#define PSI_T_LONG 40
-#define PSI_T_DOUBLE 41
-#define PSI_T_UNSIGNED 42
-#define PSI_T_SIGNED 43
-#define PSI_T_INT8 44
-#define PSI_T_UINT8 45
-#define PSI_T_INT16 46
-#define PSI_T_UINT16 47
-#define PSI_T_INT32 48
-#define PSI_T_UINT32 49
-#define PSI_T_INT64 50
-#define PSI_T_UINT64 51
-#define PSI_T_FUNCTION 52
-#define PSI_T_NULL 53
-#define PSI_T_TRUE 54
-#define PSI_T_FALSE 55
-#define PSI_T_DOLLAR_NAME 56
-#define PSI_T_OBJVAL 57
-#define PSI_T_ARRVAL 58
-#define PSI_T_PATHVAL 59
-#define PSI_T_STRLEN 60
-#define PSI_T_STRVAL 61
-#define PSI_T_FLOATVAL 62
-#define PSI_T_INTVAL 63
-#define PSI_T_BOOLVAL 64
-#define PSI_T_CALLBACK 65
+#define PSI_T_CALLBACK 12
+#define PSI_T_LIB 13
+#define PSI_T_STRING 14
+#define PSI_T_EOF 15
+#define PSI_T_EOS 16
+#define PSI_T_QUOTED_STRING 17
+#define PSI_T_ENUM 18
+#define PSI_T_LBRACE 19
+#define PSI_T_RBRACE 20
+#define PSI_T_COMMA 21
+#define PSI_T_EQUALS 22
+#define PSI_T_UNION 23
+#define PSI_T_STRUCT 24
+#define PSI_T_COLON 25
+#define PSI_T_LPAREN 26
+#define PSI_T_NUMBER 27
+#define PSI_T_RPAREN 28
+#define PSI_T_BOOL 29
+#define PSI_T_INT 30
+#define PSI_T_FLOAT 31
+#define PSI_T_CONST 32
+#define PSI_T_NSNAME 33
+#define PSI_T_TYPEDEF 34
+#define PSI_T_VOID 35
+#define PSI_T_LBRACKET 36
+#define PSI_T_RBRACKET 37
+#define PSI_T_ELLIPSIS 38
+#define PSI_T_CHAR 39
+#define PSI_T_SHORT 40
+#define PSI_T_LONG 41
+#define PSI_T_DOUBLE 42
+#define PSI_T_UNSIGNED 43
+#define PSI_T_SIGNED 44
+#define PSI_T_INT8 45
+#define PSI_T_UINT8 46
+#define PSI_T_INT16 47
+#define PSI_T_UINT16 48
+#define PSI_T_INT32 49
+#define PSI_T_UINT32 50
+#define PSI_T_INT64 51
+#define PSI_T_UINT64 52
+#define PSI_T_FUNCTION 53
+#define PSI_T_NULL 54
+#define PSI_T_TRUE 55
+#define PSI_T_FALSE 56
+#define PSI_T_DOLLAR_NAME 57
+#define PSI_T_OBJVAL 58
+#define PSI_T_ARRVAL 59
+#define PSI_T_PATHVAL 60
+#define PSI_T_STRLEN 61
+#define PSI_T_STRVAL 62
+#define PSI_T_FLOATVAL 63
+#define PSI_T_INTVAL 64
+#define PSI_T_BOOLVAL 65
#define PSI_T_TO_OBJECT 66
#define PSI_T_TO_ARRAY 67
#define PSI_T_TO_STRING 68
%nonassoc NAME.
%left PLUS MINUS.
%left SLASH ASTERISK.
-%fallback NAME TEMP FREE SET LET RETURN CALLOC LIB STRING.
+%fallback NAME TEMP FREE SET LET RETURN CALLOC CALLBACK LIB STRING.
file ::= blocks.
%type callback_arg_list {set_values *}
%destructor callback_arg_list {free_set_values($$);}
callback_arg_list ::= .
-callback_arg_list(args) ::= COMMA callback_args(args_). {
+callback_arg_list(args) ::= callback_args(args_). {
args = args_;
}
let_val(val) ::= let_func(func). {
val = init_let_val(PSI_LET_FUNC, func);
}
-let_val(val) ::= CALLBACK let_func_token(F) LPAREN impl_var(var) callback_arg_list(args_) RPAREN. {
+let_val(val) ::= CALLBACK let_func_token(F) LPAREN impl_var(var) LPAREN callback_arg_list(args_) RPAREN RPAREN. {
val = init_let_val(PSI_LET_CALLBACK, init_let_callback(
init_let_func(F->type, F->text, var), args_));
free(F);