flush
authorMichael Wallner <mike@php.net>
Fri, 16 Oct 2015 09:31:00 +0000 (11:31 +0200)
committerMichael Wallner <mike@php.net>
Fri, 16 Oct 2015 09:31:00 +0000 (11:31 +0200)
src/compiler.c
src/compiler.h
src/module.c
src/parser.h
src/parser.re
src/parser_proc.h
src/parser_proc.y
src/validator.c
src/validator.h

index 5e5ebde9e7e2b1073126ec321dc728b47603e19b..f2821ca5cc78ff4aed4a580b40dbf92edc62b054 100644 (file)
@@ -38,6 +38,8 @@ void PSI_Compiler_Free(PSI_Compiler **C)
 typedef struct PSI_ClosureData {
        void *context;
        impl *impl;
+       jit_type_t signature;
+       zval return_value;
 } PSI_ClosureData;
 
 static inline PSI_ClosureData *PSI_ClosureDataAlloc(void *context, impl *impl) {
@@ -60,12 +62,67 @@ static inline size_t impl_num_min_args(impl *impl) {
        return n;
 }
 
-static void psi_jit_closure_handler(jit_type_t signature, void *result, void **args, void *user_data)
+static inline jit_abi_t psi_jit_abi(const char *convention) {
+       return jit_abi_cdecl;
+}
+static inline jit_type_t psi_jit_type(token_t t) {
+       switch (t) {
+       case PSI_T_VOID:
+               return jit_type_void;
+       case PSI_T_SINT8:
+               return jit_type_sbyte;
+       case PSI_T_UINT8:
+               return jit_type_ubyte;
+       case PSI_T_SINT16:
+               return jit_type_short;
+       case PSI_T_UINT16:
+               return jit_type_ushort;
+       case PSI_T_SINT32:
+               return jit_type_int;
+       case PSI_T_UINT32:
+               return jit_type_uint;
+       case PSI_T_SINT64:
+               return jit_type_long;
+       case PSI_T_UINT64:
+               return jit_type_ulong;
+       case PSI_T_BOOL:
+               return jit_type_sys_bool;
+       case PSI_T_CHAR:
+               return jit_type_sys_char;
+       case PSI_T_SHORT:
+               return jit_type_sys_short;
+       case PSI_T_INT:
+               return jit_type_sys_int;
+       case PSI_T_LONG:
+               return jit_type_sys_long;
+       case PSI_T_FLOAT:
+               return jit_type_sys_float;
+       case PSI_T_DOUBLE:
+               return jit_type_sys_double;
+       default:
+               abort();
+       }
+}
+static inline jit_type_t psi_jit_decl_type(decl_type *type) {
+       return psi_jit_type(real_decl_type(type)->type);
+}
+static inline jit_type_t psi_jit_decl_arg_type(decl_arg *darg) {
+       if (darg->var->pointer_level) {
+               return jit_type_void_ptr;
+       } else {
+               return psi_jit_decl_type(darg->type);
+       }
+}
+static void psi_jit_closure_handler(jit_type_t _sig, void *result, void **_args, void *_data)
 {
-       zend_execute_data *execute_data = *(zend_execute_data **)args[0];
-       zval *return_value = *(zval **)args[1];
-       PSI_ClosureData *data = user_data;
+       zend_execute_data *execute_data = *(zend_execute_data **)_args[0];
+       zval *return_value = *(zval **)_args[1];
+       PSI_ClosureData *data = _data;
        impl_arg *iarg;
+       size_t i;
+       void **arg_ptr = NULL, **arg_prm = NULL;
+       impl_val ret_val, *arg_val = NULL;
+       jit_type_t signature, *sig_prm;
 
        if (!data->impl->func->args->count) {
                if (SUCCESS != zend_parse_parameters_none()) {
@@ -85,12 +142,12 @@ static void psi_jit_closure_handler(jit_type_t signature, void *result, void **a
                        Z_PARAM_BOOL(iarg->val.bval);
                } else if (PSI_T_INT == iarg->type->type) {
                        if (iarg->def) {
-                               iarg->val.lval = atol(iarg->def->text);
+                               iarg->val.lval = zend_atol(iarg->def->text, strlen(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);
+                               iarg->val.dval = zend_strtod(iarg->def->text, NULL);
                        }
                        Z_PARAM_DOUBLE(iarg->val.dval);
                } else if (PSI_T_STRING == iarg->type->type) {
@@ -104,8 +161,83 @@ static void psi_jit_closure_handler(jit_type_t signature, void *result, void **a
                        error_code = ZPP_ERROR_FAILURE;
                        break;
                }
-               goto nextarg;
+               iarg->_zv = _arg;
+               if (_i < _max_num_args) {
+                       goto nextarg;
+               }
        ZEND_PARSE_PARAMETERS_END();
+
+       if (data->impl->decl->args->count) {
+               arg_ptr = malloc(data->impl->decl->args->count * sizeof(*arg_ptr));
+               arg_prm = malloc(data->impl->decl->args->count * sizeof(*arg_prm));
+               arg_val = malloc(data->impl->decl->args->count * sizeof(*arg_val));
+               sig_prm = malloc(data->impl->decl->args->count * sizeof(*sig_prm));
+
+               for (i = 0; i < data->impl->decl->args->count; ++i) {
+                       decl_arg *darg = data->impl->decl->args->args[i];
+                       impl_arg *iarg = darg->let->arg;
+
+                       switch (darg->let->val->func->type) {
+                       case PSI_T_BOOLVAL:
+                               if (iarg->type->type == PSI_T_BOOL) {
+                                       arg_val[i].bval = iarg->val.bval;
+                               } else {
+                                       arg_val[i].bval = zend_is_true(iarg->_zv);
+                               }
+                               break;
+                       case PSI_T_INTVAL:
+                               if (iarg->type->type == PSI_T_INT) {
+                                       arg_val[i].lval = iarg->val.lval;
+                               } else {
+                                       arg_val[i].lval = zval_get_long(iarg->_zv);
+                               }
+                               break;
+                       case PSI_T_STRVAL:
+                               if (iarg->type->type == PSI_T_STRING) {
+                                       arg_val[i].str.val = estrndup(iarg->val.str.val, iarg->val.str.len);
+                               } else {
+                                       zend_string *zs = zval_get_string(iarg->_zv);
+                                       arg_val[i].str.val = estrndup(zs->val, zs->len);
+                                       zend_string_release(zs);
+                               }
+                               break;
+                       case PSI_T_STRLEN:
+                               if (iarg->type->type == PSI_T_STRING) {
+                                       arg_val[i].lval =iarg->val.str.len;
+                               } else {
+                                       zend_string *zs = zval_get_string(iarg->_zv);
+                                       arg_val[i].lval = zs->len;
+                                       zend_string_release(zs);
+                               }
+                               break;
+                       }
+                       arg_ptr[i] = &arg_val[i];
+                       arg_prm[i] = darg->let->val->is_reference ? &arg_ptr[i] : arg_ptr[i];
+                       sig_prm[i] = psi_jit_decl_arg_type(darg);
+               }
+       }
+
+       signature = jit_type_create_signature(
+                       psi_jit_abi(data->impl->decl->abi->convention),
+                       psi_jit_decl_arg_type(data->impl->decl->func),
+                       sig_prm,
+                       data->impl->decl->args->count,
+                       1);
+       jit_apply(signature, data->impl->decl->dlptr, arg_prm, data->impl->decl->args->count, &ret_val);
+
+       switch (data->impl->stmts->ret.list[0]->func->type) {
+       case PSI_T_TO_STRING:
+               if (data->impl->decl->func->var->pointer_level) {
+                       switch (real_decl_type(data->impl->decl->func->type)->type) {
+                       case PSI_T_CHAR:
+                       case PSI_T_SINT8:
+                       case PSI_T_UINT8:
+                               RETVAL_STRING(ret_val.str.val);
+                               break;
+                       }
+               }
+               break;
+       }
 }
 
 zend_function_entry *PSI_CompilerCompile(PSI_Compiler *C)
@@ -119,19 +251,17 @@ zend_function_entry *PSI_CompilerCompile(PSI_Compiler *C)
 
        for (i = 0; i < C->impls->count; ++i) {
                zend_function_entry *zf;
-               volatile PSI_ClosureData *data;
+               PSI_ClosureData *data;
 
                if (!C->impls->list[i]->decl) {
                        continue;
                }
-               signature = jit_type_create_signature(jit_abi_vararg, jit_type_void, params, 2, 1);
 
                zf = &zfe[j++];
                data = PSI_ClosureDataAlloc(C->context, C->impls->list[i]);
-               zf->fname = C->impls->list[i]->func->name;
+               signature = jit_type_create_signature(jit_abi_vararg, jit_type_void, params, 2, 1);
+               zf->fname = C->impls->list[i]->func->name + (C->impls->list[i]->func->name[0] == '\\');
                zf->handler = jit_closure_create(C->context, signature, &psi_jit_closure_handler, data);
-               fprintf(stderr, "Compiled closure for %s\n", zf->fname);
-               printf("Closuredata: %p of closure %p\n", data, zf->handler);
        }
 
        return zfe;
index 1374d39b776fa2124d44f6f89b8d0dfe157ef6cb..fcf2cf66781be0611c01dab248039598e9d6c75b 100644 (file)
@@ -4,11 +4,7 @@
 #include "validator.h"
 
 typedef struct PSI_Compiler {
-       decl_typedefs *defs;
-       decls *decls;
-       impls *impls;
-       char *lib;
-       char *fn;
+       PSI_DATA_MEMBERS;
        void *context;
 } PSI_Compiler;
 
index 90a838da0e849aef935d7ae4bd55b5e689eaca1c..69ec53d6b1d1d16bda64fd5fa23da779f62b231a 100644 (file)
@@ -24,6 +24,18 @@ PHP_INI_BEGIN()
        STD_PHP_INI_ENTRY("psi.directory", "psis", PHP_INI_ALL, OnUpdateString, directory, zend_psi_globals, psi_globals)
 PHP_INI_END();
 
+static void psi_error(int type, const char *msg, ...)
+{
+       char buf[0x1000];
+       va_list argv;
+
+       va_start(argv, msg);
+       vslprintf(buf, 0x1000, msg, argv);
+       va_end(argv);
+
+       php_error(type, buf);
+}
+
 static int psi_select_dirent(const struct dirent *entry)
 {
 #ifndef FNM_CASEFOLD
@@ -61,7 +73,7 @@ PHP_MINIT_FUNCTION(psi)
                        php_error(E_WARNING, "Path to PSI file too long: %s/%s",
                                PSI_G(directory), entries[i]->d_name);
                }
-               if (!PSI_ParserInit(&P, psi, 0)) {
+               if (!PSI_ParserInit(&P, psi, psi_error, 0)) {
                        php_error(E_WARNING, "Failed to init PSI parser (%s): %s",
                                psi, strerror(errno));
                        continue;
@@ -85,10 +97,8 @@ PHP_MINIT_FUNCTION(psi)
                        if (PSI_CompilerInit(&C, &V, ctx)) {
                                zend_function_entry *closures = PSI_CompilerCompile(&C);
 
-                               if (closures) {
-                                       if (SUCCESS != zend_register_functions(NULL, closures, NULL, MODULE_PERSISTENT)) {
-                                               fprintf(stderr, "Failed to register functions!\n");
-                                       }
+                               if (closures && SUCCESS != zend_register_functions(NULL, closures, NULL, MODULE_PERSISTENT)) {
+                                       psi_error(E_WARNING, "Failed to register functions!");
                                }
                                //PSI_CompilerDtor(&C);
                        }
index 2aaab31985ead22727f3d1f4ab3dd67cf2de3690..8506acde1d4a638b6040d941f1ac831fa32ddfb4 100644 (file)
@@ -35,6 +35,13 @@ static inline decl_type *init_decl_type(token_t type, char *name) {
        return t;
 }
 
+static inline decl_type *real_decl_type(decl_type *type) {
+       while (type->real) {
+               type = type->real;
+       }
+       return type;
+}
+
 static inline void free_decl_type(decl_type *type) {
        free(type->name);
        free(type);
@@ -102,12 +109,14 @@ static inline void free_decl_var(decl_var *var) {
 typedef struct decl_arg {
        decl_type *type;
        decl_var *var;
+       struct let_stmt *let;
 } decl_arg;
 
 static inline decl_arg *init_decl_arg(decl_type *type, decl_var *var) {
        decl_arg *arg = malloc(sizeof(*arg));
        arg->type = type;
        arg->var = var;
+       arg->let = NULL;
        return arg;
 }
 
@@ -288,19 +297,22 @@ static inline void free_impl_def_val(impl_def_val *def) {
        free(def);
 }
 
+typedef union impl_val {
+       unsigned char bval;
+       zend_long lval;
+       double dval;
+       struct {
+               char *val;
+               size_t len;
+       } str;
+} impl_val;
+
 typedef struct impl_arg {
        impl_type *type;
        impl_var *var;
        impl_def_val *def;
-       union {
-               unsigned char bval;
-               zend_long lval;
-               double dval;
-               struct {
-                       char *val;
-                       size_t len;
-               } str;
-       } val;
+       impl_val val;
+       zval *_zv;
 } impl_arg;
 
 static inline impl_arg *init_impl_arg(impl_type *type, impl_var *var, impl_def_val *def) {
@@ -395,12 +407,12 @@ static inline void free_let_func(let_func *func) {
 typedef struct let_value {
        let_func *func;
        impl_var *var;
-       unsigned null_pointer_ref:1;
+       unsigned is_reference:1;
 } let_value;
 
-static inline let_value *init_let_value(let_func *func, impl_var *var, int null_pointer_ref) {
+static inline let_value *init_let_value(let_func *func, impl_var *var, int is_reference) {
        let_value *val = malloc(sizeof(*val));
-       val->null_pointer_ref = null_pointer_ref;
+       val->is_reference = is_reference;
        val->func = func;
        val->var = var;
        return val;
@@ -419,12 +431,14 @@ static inline void free_let_value(let_value *val) {
 typedef struct let_stmt {
        decl_var *var;
        let_value *val;
+       impl_arg *arg;
 } let_stmt;
 
 static inline let_stmt *init_let_stmt(decl_var *var, let_value *val) {
        let_stmt *let = malloc(sizeof(*let));
        let->var = var;
        let->val = val;
+       let->arg = NULL;
        return let;
 }
 
@@ -639,12 +653,19 @@ static void free_impls(impls *impls) {
        free(impls);
 }
 
+#define PSI_ERROR 16
+#define PSI_WARNING 32
+typedef void (*psi_error_cb)(int type, const char *msg, ...);
+
 typedef struct PSI_Data {
-       decl_typedefs *defs;
-       decls *decls;
-       impls *impls;
-       char *lib;
-       char *fn;
+#define PSI_DATA_MEMBERS \
+       decl_typedefs *defs; \
+       decls *decls; \
+       impls *impls; \
+       char *lib; \
+       char *fn; \
+       psi_error_cb error
+       PSI_DATA_MEMBERS;
 } PSI_Data;
 
 static inline void PSI_DataExchange(PSI_Data *dest, PSI_Data *src) {
@@ -671,11 +692,7 @@ static inline void PSI_DataDtor(PSI_Data *data) {
 }
 
 typedef struct PSI_Parser {
-       decl_typedefs *defs;
-       decls *decls;
-       impls *impls;
-       char *lib;
-       char *fn;
+       PSI_DATA_MEMBERS;
        FILE *fp;
        unsigned flags;
        unsigned errors;
@@ -707,7 +724,7 @@ static inline PSI_Token *PSI_TokenAlloc(PSI_Parser *P) {
 
 #define PSI_PARSER_DEBUG 0x1
 
-PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, unsigned flags);
+PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, psi_error_cb error, unsigned flags);
 void PSI_ParserSyntaxError(PSI_Parser *P, const char *fn, size_t ln, const char *msg, ...);
 size_t PSI_ParserFill(PSI_Parser *P, size_t n);
 token_t PSI_ParserScan(PSI_Parser *P);
index 31ddfe16bfcc2304f1a3a592345bc182ee439a7c..4cabb45b07ea11e70dec321066db9947bd4576b3 100644 (file)
@@ -9,7 +9,7 @@ void PSI_ParserProcFree(void*, void(*)(void*));
 void PSI_ParserProc(void *, token_t, PSI_Token *, PSI_Parser *);
 void PSI_ParserProcTrace(FILE *, const char*);
 
-PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, unsigned flags)
+PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, psi_error_cb error, unsigned flags)
 {
        FILE *fp;
 
@@ -33,6 +33,7 @@ PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, unsigned flags)
        P->fp = fp;
        P->fn = strdup(filename);
        P->line = 1;
+       P->error = error;
        P->flags = flags;
 
        P->proc = PSI_ParserProcAlloc(malloc);
@@ -46,14 +47,16 @@ PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, unsigned flags)
 }
 
 void PSI_ParserSyntaxError(PSI_Parser *P, const char *fn, size_t ln, const char *msg, ...) {
-       fprintf(stderr, "WARNING: Syntax error on line %zu in '%s'%s", ln, fn, msg ? ": ": "\n");
-       if (msg) {
-               va_list argv;
+       char buf[0x1000] = {0};
+       va_list argv;
+
+       va_start(argv, msg);
+       vsnprintf(buf, 0x1000-1, msg, argv);
+       va_end(argv);
+
+       P->error(PSI_WARNING, "PSI syntax error on line %zu in '%s'%s%s",
+                       ln, fn, msg ? ": ": "", buf);
 
-               va_start(argv, msg);
-               vfprintf(stderr, msg, argv);
-               va_end(argv);
-       }
        ++P->errors;
 }
 
@@ -180,7 +183,10 @@ token_t PSI_ParserScan(PSI_Parser *P)
                MIXED = 'mixed';
                VOID = 'void';
                BOOL = 'bool';
+               CHAR = 'char';
+               SHORT = 'short';
                INT = 'int';
+               LONG = 'long';
                FLOAT = 'float';
                DOUBLE = 'double';
                SINT8 = 'sint8';
@@ -230,7 +236,10 @@ token_t PSI_ParserScan(PSI_Parser *P)
                MIXED {RETURN(PSI_T_MIXED);}
                VOID {RETURN(PSI_T_VOID);}
                BOOL {RETURN(PSI_T_BOOL);}
+               CHAR {RETURN(PSI_T_CHAR);}
+               SHORT {RETURN(PSI_T_SHORT);}
                INT {RETURN(PSI_T_INT);}
+               LONG {RETURN(PSI_T_LONG);}
                FLOAT {RETURN(PSI_T_FLOAT);}
                DOUBLE {RETURN(PSI_T_DOUBLE);}
                SINT8 {RETURN(PSI_T_SINT8);}
@@ -262,7 +271,7 @@ token_t PSI_ParserScan(PSI_Parser *P)
                NAME {RETURN(PSI_T_NAME);}
                NSNAME {RETURN(PSI_T_NSNAME);}
                QUOTED_STRING {RETURN(PSI_T_QUOTED_STRING);}
-               [^] {break;} 
+               [^] {break;}
                */
        }
        return -1;
index d8466df143a2d5dd45b9750f686a5d07544517d7..d1ba3cf18dde2f2db959ac2685ed27a59e215f80 100644 (file)
@@ -8,43 +8,46 @@
 #define PSI_T_RPAREN                           8
 #define PSI_T_COMMA                            9
 #define PSI_T_VOID                            10
-#define PSI_T_INT                             11
-#define PSI_T_FLOAT                           12
-#define PSI_T_DOUBLE                          13
-#define PSI_T_SINT8                           14
-#define PSI_T_UINT8                           15
-#define PSI_T_SINT16                          16
-#define PSI_T_UINT16                          17
-#define PSI_T_SINT32                          18
-#define PSI_T_UINT32                          19
-#define PSI_T_SINT64                          20
-#define PSI_T_UINT64                          21
-#define PSI_T_LBRACE                          22
-#define PSI_T_RBRACE                          23
-#define PSI_T_FUNCTION                        24
-#define PSI_T_NSNAME                          25
-#define PSI_T_COLON                           26
-#define PSI_T_NULL                            27
-#define PSI_T_NUMBER                          28
-#define PSI_T_TRUE                            29
-#define PSI_T_FALSE                           30
-#define PSI_T_DOLLAR                          31
-#define PSI_T_REFERENCE                       32
-#define PSI_T_EQUALS                          33
-#define PSI_T_LET                             34
-#define PSI_T_STRLEN                          35
-#define PSI_T_STRVAL                          36
-#define PSI_T_INTVAL                          37
-#define PSI_T_FLOATVAL                        38
-#define PSI_T_BOOLVAL                         39
-#define PSI_T_SET                             40
-#define PSI_T_TO_STRING                       41
-#define PSI_T_TO_INT                          42
-#define PSI_T_TO_FLOAT                        43
-#define PSI_T_TO_BOOL                         44
-#define PSI_T_RET                             45
-#define PSI_T_MIXED                           46
-#define PSI_T_BOOL                            47
-#define PSI_T_STRING                          48
-#define PSI_T_ARRAY                           49
-#define PSI_T_POINTER                         50
+#define PSI_T_CHAR                            11
+#define PSI_T_SHORT                           12
+#define PSI_T_INT                             13
+#define PSI_T_LONG                            14
+#define PSI_T_FLOAT                           15
+#define PSI_T_DOUBLE                          16
+#define PSI_T_SINT8                           17
+#define PSI_T_UINT8                           18
+#define PSI_T_SINT16                          19
+#define PSI_T_UINT16                          20
+#define PSI_T_SINT32                          21
+#define PSI_T_UINT32                          22
+#define PSI_T_SINT64                          23
+#define PSI_T_UINT64                          24
+#define PSI_T_LBRACE                          25
+#define PSI_T_RBRACE                          26
+#define PSI_T_FUNCTION                        27
+#define PSI_T_NSNAME                          28
+#define PSI_T_COLON                           29
+#define PSI_T_NULL                            30
+#define PSI_T_NUMBER                          31
+#define PSI_T_TRUE                            32
+#define PSI_T_FALSE                           33
+#define PSI_T_DOLLAR                          34
+#define PSI_T_REFERENCE                       35
+#define PSI_T_EQUALS                          36
+#define PSI_T_LET                             37
+#define PSI_T_STRLEN                          38
+#define PSI_T_STRVAL                          39
+#define PSI_T_INTVAL                          40
+#define PSI_T_FLOATVAL                        41
+#define PSI_T_BOOLVAL                         42
+#define PSI_T_SET                             43
+#define PSI_T_TO_STRING                       44
+#define PSI_T_TO_INT                          45
+#define PSI_T_TO_FLOAT                        46
+#define PSI_T_TO_BOOL                         47
+#define PSI_T_RET                             48
+#define PSI_T_MIXED                           49
+#define PSI_T_BOOL                            50
+#define PSI_T_STRING                          51
+#define PSI_T_ARRAY                           52
+#define PSI_T_POINTER                         53
index d99c96d482bb956966915960d6508631b621b622..c619e5542f4485237cc235266b7676cba5f0f7be 100644 (file)
@@ -14,7 +14,7 @@
 %extra_argument {PSI_Parser *P}
 /* TOKEN is defined inside syntax_error */
 %syntax_error {
-       PSI_ParserSyntaxError(P, P->fn, P->line, "Unexpected token '%s'.\n", TOKEN->text);
+       PSI_ParserSyntaxError(P, P->fn, P->line, "Unexpected token '%s'", TOKEN->text);
 }
 file ::= blocks.
 
@@ -25,7 +25,7 @@ block ::= COMMENT.
 
 block ::= LIB(T) QUOTED_STRING(libname) EOS. {
        if (P->lib) {
-               PSI_ParserSyntaxError(P, P->fn, T->line, "Extra 'lib %s' statement has no effect.\n", libname->text);
+               PSI_ParserSyntaxError(P, P->fn, T->line, "Extra 'lib %s' statement has no effect", libname->text);
        } else {
                P->lib = strndup(libname->text + 1, libname->size - 2);
        }
@@ -96,10 +96,22 @@ decl_type(type_) ::= VOID(T). {
        type_ = init_decl_type(T->type, T->text);
        free(T);
 }
+decl_type(type_) ::= CHAR(T). {
+       type_ = init_decl_type(T->type, T->text);
+       free(T);
+}
+decl_type(type_) ::= SHORT(T). {
+       type_ = init_decl_type(T->type, T->text);
+       free(T);
+}
 decl_type(type_) ::= INT(T). {
        type_ = init_decl_type(T->type, T->text);
        free(T);
 }
+decl_type(type_) ::= LONG(T). {
+       type_ = init_decl_type(T->type, T->text);
+       free(T);
+}
 decl_type(type_) ::= FLOAT(T). {
        type_ = init_decl_type(T->type, T->text);
        free(T);
@@ -231,6 +243,9 @@ let_stmt(let) ::= LET decl_var(var) EQUALS let_value(val) EOS. {
 let_value(val) ::= let_func(func) LPAREN impl_var(var) RPAREN. {
        val = init_let_value(func, var, 0);
 }
+let_value(val) ::= REFERENCE let_func(func) LPAREN impl_var(var) RPAREN. {
+       val = init_let_value(func, var, 1);
+}
 let_value(val) ::= REFERENCE NULL. {
        val = init_let_value(NULL, NULL, 1);
 }
index 5f6a6d36e73e81ec841cd047916a4d0efd119dd0..4e38929e1d42f9411468af53676f7b8b49233e9b 100644 (file)
@@ -43,8 +43,6 @@ static int validate_lib(PSI_Validator *V) {
        if (!ptr) {
                /* FIXME: assume stdlib */
                return 1;
-               fprintf(stderr, "No import library defined;"
-                       " use 'lib \"<libname>\";' statement.\n");
        } else if (!strchr(ptr, '/')) {
 #ifdef DARWIN
                len = snprintf(lib, MAXPATHLEN, "lib%s.dylib", ptr);
@@ -52,13 +50,13 @@ static int validate_lib(PSI_Validator *V) {
                len = snprintf(lib, MAXPATHLEN, "lib%s.so", ptr);
 #endif
                if (MAXPATHLEN == len) {
-                       fprintf(stderr, "Library name too long: '%s'\n", ptr);
+                       V->error(PSI_WARNING, "Library name too long: '%s'", ptr);
                }
                lib[len] = 0;
                ptr = lib;
        }
        if (!(V->dlopened = dlopen(ptr, RTLD_LAZY|RTLD_LOCAL))) {
-               fprintf(stderr, "Could not open library '%s': %s.\n", V->lib, dlerror());
+               V->error(PSI_WARNING, "Could not open library '%s': %s.", V->lib, dlerror());
                return 0;
        }
        return 1;
@@ -79,12 +77,11 @@ static inline int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) {
 }
 static inline int validate_decl_type(PSI_Validator *V, decl_arg *arg, decl_type *type) {
        if (type->type == PSI_T_NAME) {
-               size_t i;
-
                if (!V->defs || !locate_decl_type_alias(V->defs, type)) {
-                       fprintf(stderr, "Cannot use '%s' as type for '%s';"
-                               " Use 'typedef <type> <basic_type>;' statement.\n",
+                       V->error(PSI_WARNING, "Cannot use '%s' as type for '%s';"
+                               " Use 'typedef <type> <basic_type>;' statement",
                                type->name, arg->var->name);
+                       return 0;
                }
        }
        return 1;
@@ -92,7 +89,7 @@ static inline int validate_decl_type(PSI_Validator *V, decl_arg *arg, decl_type
 static inline int validate_typedef(PSI_Validator *V, decl_typedef *def) {
        /* FIXME: check def->alias */
        if (def->type->type == PSI_T_NAME) {
-               fprintf(stderr, "Type '%s' cannot be aliased to '%s'\n",
+               V->error(PSI_WARNING, "Type '%s' cannot be aliased to '%s'",
                        def->type->name, def->alias);
                return 0;
        }
@@ -111,10 +108,8 @@ static inline int validate_typedefs(PSI_Validator *V) {
 }
 static inline int validate_decl_func(PSI_Validator *V, decl *decl, decl_arg *func)
 {
-       void *dlptr;
-
        if (!strcmp(func->var->name, "dlsym")) {
-               fprintf(stderr, "Cannot dlsym dlsym (sic!)\n");
+               V->error(PSI_WARNING, "Cannot dlsym dlsym (sic!)");
                return 0;
        }
 
@@ -124,14 +119,14 @@ static inline int validate_decl_func(PSI_Validator *V, decl *decl, decl_arg *fun
 
        decl->dlptr = dlsym(V->dlopened, func->var->name);
        if (!decl->dlptr) {
-               fprintf(stderr, "Failed to located symbol '%s': %s\n",
+               V->error(PSI_WARNING, "Failed to located symbol '%s': %s",
                        func->var->name, dlerror());
        }
        return 1;
 }
 static inline int validate_decl_abi(PSI_Validator *V, decl_abi *abi) {
        if (strcasecmp(abi->convention, "default")) {
-               fprintf(stderr, "Invalid calling convention: '%s'\n", abi->convention);
+               V->error(PSI_WARNING, "Invalid calling convention: '%s'", abi->convention);
                return 0;
        }
        /* FIXME */
@@ -213,6 +208,7 @@ static inline decl *locate_impl_decl(decls *decls, ret_stmt *ret) {
        }
        return NULL;
 }
+
 static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts *stmts) {
        /* okay,
         * - we must have exactly one ret stmt delcaring the native func to call and which type cast to apply
@@ -222,18 +218,20 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts *
        size_t i, j;
        ret_stmt *ret;
        decl *decl;
-       int *check;
 
         if (!stmts) {
-               fprintf(stderr, "Missing body for implementation %s!\n", impl->func->name);
+               V->error(PSI_WARNING, "Missing body for implementation %s!",
+                               impl->func->name);
                return 0;
        }
        if (stmts->ret.count != 1) {
                if (stmts->ret.count > 1) {
-                       fprintf(stderr, "Too many `ret` statements for implmentation %s; found %zu, exactly one is needed.\n",
-                               impl->func->name, stmts->ret.count);
+                       V->error(PSI_WARNING, "Too many `ret` statements for implmentation %s;"
+                                       "found %zu, exactly one is needed",
+                                       impl->func->name, stmts->ret.count);
                } else {
-                       fprintf(stderr, "Missing `ret` statement for implementation %s.\n", impl->func->name);
+                       V->error(PSI_WARNING, "Missing `ret` statement for implementation %s",
+                                       impl->func->name);
                }
                return 0;
        }
@@ -241,31 +239,56 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts *
        ret = stmts->ret.list[0];
        decl = locate_impl_decl(V->decls, ret);
        if (!decl) {
-               fprintf(stderr, "Missing declaration for implementation %s.\n", impl->func->name);
+               V->error(PSI_WARNING, "Missing declaration for implementation %s",
+                               impl->func->name);
                return 0;
        }
 
        /* check that we have a let stmt for every decl arg */
-       check = calloc(decl->args->count, sizeof(int));
-       for (i = 0; i < stmts->let.count; ++i) {
-               let_stmt *let = stmts->let.list[i];
+       for (i = 0; i < decl->args->count; ++i) {
+               decl_arg *darg = decl->args->args[i];
+               int check = 0;
 
-               for (j = 0; j < decl->args->count; ++j) {
-                       if (!strcmp(decl->args->args[j]->var->name, let->var->name)) {
-                               check[j] = 1;
+               for (j = 0; j < stmts->let.count; ++j) {
+                       let_stmt *let = stmts->let.list[j];
+
+                       if (!strcmp(let->var->name, darg->var->name)) {
+                               darg->let = let;
+                               check = 1;
                                break;
                        }
                }
-       }
-       for (i = 0; i < decl->args->count; ++i) {
-               if (!check[i]) {
-                       fprintf(stderr, "Missing `let` statement for arg '%s %.*s%s' of declaration '%s' for implementation '%s'.\n",
-                               decl->args->args[i]->type->name, (int) decl->args->args[i]->var->pointer_level, "*****", decl->args->args[i]->var->name, decl->func->var->name, impl->func->name);
-                       free(check);
+               if (!check) {
+                       V->error(PSI_WARNING, "Missing `let` statement for arg '%s %.*s%s'"
+                                       "of declaration '%s' for implementation '%s'",
+                                       darg->type->name, (int) darg->var->pointer_level, "*****",
+                                       darg->var->name, decl->func->var->name, impl->func->name);
                        return 0;
                }
        }
-       free(check);
+       /* check that the let_value references a known variable or NULL */
+       for (i = 0; i < stmts->let.count; ++i) {
+               let_stmt *let = stmts->let.list[i];
+               int check = 0;
+
+               if (let->val->var) {
+                       for (j = 0; j < impl->func->args->count; ++j) {
+                               impl_arg *iarg = impl->func->args->args[j];
+
+                               if (!strcmp(let->val->var->name, iarg->var->name)) {
+                                       let->arg = iarg;
+                                       check = 1;
+                                       break;
+                               }
+                       }
+                       if (!check) {
+                               V->error(PSI_WARNING, "Unknown value '$%s' of `let` statement"
+                                               " for variable '%s' of implementation '%s'",
+                                               let->val->var->name, let->var->name, impl->func->name);
+                               return 0;
+                       }
+               }
+       }
 
        impl->decl = decl;
 
index f96111cb08ac2806403e6c1cda7348a576a481b8..8b373f652e05e4b8293cb7267128844137248b63 100644 (file)
@@ -4,11 +4,7 @@
 #include "parser.h"
 
 typedef struct PSI_Validator {
-       decl_typedefs *defs;
-       decls *decls;
-       impls *impls;
-       char *lib;
-       char *fn;
+       PSI_DATA_MEMBERS;
        void *dlopened;
 } PSI_Validator;