[pure-lang-svn] SF.net SVN: pure-lang: [291] pure/trunk
Status: Beta
Brought to you by:
agraef
From: <ag...@us...> - 2008-06-23 23:38:42
|
Revision: 291 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=291&view=rev Author: agraef Date: 2008-06-23 16:38:50 -0700 (Mon, 23 Jun 2008) Log Message: ----------- Start refactoring the runtime library in order to provide a sensible public API to external modules which need access to Pure expression data. Modified Paths: -------------- pure/trunk/runtime.cc pure/trunk/runtime.h Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-06-23 13:07:26 UTC (rev 290) +++ pure/trunk/runtime.cc 2008-06-23 23:38:50 UTC (rev 291) @@ -298,51 +298,17 @@ return pure_const(interpreter::g_interp->symtab.segfault_sym().f); } -extern "C" -pure_expr *pure_clos(bool local, bool thunked, int32_t tag, uint32_t n, - void *f, void *e, uint32_t m, /* m x pure_expr* */ ...) -{ - // Parameterless closures are always thunked, otherwise they would already - // have been executed. - if (n==0) thunked = true; - pure_expr *x = new_expr(); - x->tag = tag; - x->data.clos = new pure_closure; - x->data.clos->local = local; - x->data.clos->thunked = thunked; - x->data.clos->n = n; - x->data.clos->m = m; - x->data.clos->fp = f; - x->data.clos->ep = e; - if (e) ((Env*)e)->refc++; - if (m == 0) - x->data.clos->env = 0; - else { - x->data.clos->env = new pure_expr*[m]; - va_list ap; - va_start(ap, m); - for (size_t i = 0; i < m; i++) { - x->data.clos->env[i] = va_arg(ap, pure_expr*); - assert(x->data.clos->env[i]->refc > 0); - } - va_end(ap); - } - MEMDEBUG_NEW(x) - return x; -} +/* PUBLIC API. **************************************************************/ -extern "C" -pure_expr *pure_const(int32_t tag) -{ - // XXXFIXME: We should cache these on a per interpreter basis, so that only - // a single expression node exists for each symbol. - pure_expr *x = new_expr(); - x->tag = tag; - x->data.clos = 0; - MEMDEBUG_NEW(x) - return x; -} +// XXXTODO +int32_t pure_sym(const char *s); +int32_t pure_getsym(const char *s); +const char *pure_sym_pname(int32_t sym); +int8_t pure_sym_nprec(int32_t sym); + +pure_expr *pure_symbol(int32_t sym); + extern "C" pure_expr *pure_int(int32_t i) { @@ -369,7 +335,7 @@ } } -static void make_bigint(mpz_t z, int32_t size, limb_t *limbs) +static void make_bigint(mpz_t z, int32_t size, const limb_t *limbs) { // FIXME: For efficiency, we poke directly into the mpz struct here, this // might need to be reviewed for future GMP revisions. @@ -385,7 +351,7 @@ } extern "C" -pure_expr *pure_bigint(int32_t size, limb_t *limbs) +pure_expr *pure_bigint(int32_t size, const limb_t *limbs) { pure_expr *x = new_expr(); x->tag = EXPR::BIGINT; @@ -395,7 +361,7 @@ } extern "C" -pure_expr *pure_mpz(mpz_t z) +pure_expr *pure_mpz(const mpz_t z) { pure_expr *x = new_expr(); x->tag = EXPR::BIGINT; @@ -466,9 +432,113 @@ return x; } +// XXXTODO + +pure_expr *pure_app(pure_expr *fun, pure_expr *arg); + +pure_expr *pure_listl(size_t size, ...); +pure_expr *pure_listv(size_t size, pure_expr **elems); +pure_expr *pure_tuplel(size_t size, ...); +pure_expr *pure_tuplev(size_t size, pure_expr **elems); + +bool pure_is_symbol(const pure_expr *x, int32_t *sym); +bool pure_is_int(const pure_expr *x, int32_t *i); +bool pure_is_long(const pure_expr *x, int64_t *l); +bool pure_is_bigint(const pure_expr *x, int32_t *size, limb_t **limbs); +bool pure_is_mpz(const pure_expr *x, mpz_t *z); +bool pure_is_double(const pure_expr *x, double *d); +bool pure_is_pointer(const pure_expr *x, void **p); + +bool pure_is_string(const pure_expr *x, const char **sym); +bool pure_is_string_dup(const pure_expr *x, char **sym); +bool pure_is_cstring_dup(const pure_expr *x, char **sym); + +bool pure_is_app(const pure_expr *x, pure_expr **fun, pure_expr **arg); + +bool pure_is_listv(const pure_expr *x, size_t *size, pure_expr ***elems); +bool pure_is_tuplev(const pure_expr *x, size_t *size, pure_expr ***elems); + extern "C" -int32_t pure_cmp_bigint(pure_expr *x, int32_t size, limb_t *limbs) +pure_expr *pure_new(pure_expr *x) { + return pure_new_internal(x); +} + +extern "C" +void pure_free(pure_expr *x) +{ + pure_free_internal(x); +} + +extern "C" +void pure_freenew(pure_expr *x) +{ + if (x->refc == 0) + pure_free_internal(pure_new_internal(x)); +} + +extern "C" +void pure_ref(pure_expr *x) +{ + x->refc++; +} + +extern "C" +void pure_unref(pure_expr *x) +{ + pure_unref_internal(x); +} + +/* END OF PUBLIC API. *******************************************************/ + +extern "C" +pure_expr *pure_const(int32_t tag) +{ + // XXXFIXME: We should cache these on a per interpreter basis, so that only + // a single expression node exists for each symbol. + pure_expr *x = new_expr(); + x->tag = tag; + x->data.clos = 0; + MEMDEBUG_NEW(x) + return x; +} + +extern "C" +pure_expr *pure_clos(bool local, bool thunked, int32_t tag, uint32_t n, + void *f, void *e, uint32_t m, /* m x pure_expr* */ ...) +{ + // Parameterless closures are always thunked, otherwise they would already + // have been executed. + if (n==0) thunked = true; + pure_expr *x = new_expr(); + x->tag = tag; + x->data.clos = new pure_closure; + x->data.clos->local = local; + x->data.clos->thunked = thunked; + x->data.clos->n = n; + x->data.clos->m = m; + x->data.clos->fp = f; + x->data.clos->ep = e; + if (e) ((Env*)e)->refc++; + if (m == 0) + x->data.clos->env = 0; + else { + x->data.clos->env = new pure_expr*[m]; + va_list ap; + va_start(ap, m); + for (size_t i = 0; i < m; i++) { + x->data.clos->env[i] = va_arg(ap, pure_expr*); + assert(x->data.clos->env[i]->refc > 0); + } + va_end(ap); + } + MEMDEBUG_NEW(x) + return x; +} + +extern "C" +int32_t pure_cmp_bigint(pure_expr *x, int32_t size, const limb_t *limbs) +{ assert(x && x->tag == EXPR::BIGINT); mpz_t z; make_bigint(z, size, limbs); @@ -812,37 +882,6 @@ } extern "C" -pure_expr *pure_new(pure_expr *x) -{ - return pure_new_internal(x); -} - -extern "C" -void pure_free(pure_expr *x) -{ - pure_free_internal(x); -} - -extern "C" -void pure_freenew(pure_expr *x) -{ - if (x->refc == 0) - pure_free_internal(pure_new_internal(x)); -} - -extern "C" -void pure_ref(pure_expr *x) -{ - x->refc++; -} - -extern "C" -void pure_unref(pure_expr *x) -{ - pure_unref_internal(x); -} - -extern "C" void pure_new_args(uint32_t n, ...) { va_list ap; @@ -1067,6 +1106,8 @@ if (bail_out) exit(0); } +/* LIBRARY API. *************************************************************/ + extern "C" pure_expr *pure_byte_string(const char *s) { Modified: pure/trunk/runtime.h =================================================================== --- pure/trunk/runtime.h 2008-06-23 13:07:26 UTC (rev 290) +++ pure/trunk/runtime.h 2008-06-23 23:38:50 UTC (rev 291) @@ -15,6 +15,9 @@ /* Our "limb" type. Used to pass bigint constants to the runtime. */ typedef mp_limb_t limb_t; +/* The following data structures should be considered opaque by + applications. */ + /* Closure data. This is a bit on the heavy side, so expressions which need it (i.e., functions) refer to this extra data via an allocated pointer. */ @@ -57,35 +60,178 @@ pure_expr x[MEMSIZE]; // expression data } pure_mem; -/* Expression constructors. */ +/* PUBLIC API. **************************************************************/ -pure_expr *pure_clos(bool local, bool thunked, int32_t tag, uint32_t n, - void *f, void *e, uint32_t m, /* m x pure_expr* */ ...); -pure_expr *pure_const(int32_t tag); +/* The following routines are meant to be used by external C modules and other + applications which need direct access to Pure expression data. */ + +/* Symbol table access. pure_sym returns the integer code of a (function or + variable) symbol given by its print name; if the symbol doesn't exist yet, + it is created (as an ordinary function or variable symbol). pure_getsym is + like pure_sym, but returns 0 if the symbol doesn't exist. + + Given the (positive) symbol number, pure_sym_pname returns its print name + and pure_sym_nprec its "normalized" precedence. The latter is a small + integer value defined as nprec = 10*prec+fix, where prec is the precedence + level of the symbol and fix its fixity. For operators, the combined value + ranges from 0 (weakest infix operator on level 0) to 94 (strongest postfix + operator on level 9). Applications have nprec=95, ordinary function and + variable symbols nprec=100. */ + +int32_t pure_sym(const char *s); +int32_t pure_getsym(const char *s); +const char *pure_sym_pname(int32_t sym); +int8_t pure_sym_nprec(int32_t sym); + +/* Expression constructors. Atomic objects are constructed with the following + routines: + + - pure_symbol: Takes the integer code of a symbol and returns that symbol + as a Pure value. If the symbol is a global variable or parameterless + function then it is evaluated, giving the value of the variable or the + return value of the function as the result. + + - pure_int: Constructs a Pure machine int from a 32 bit integer value. + + - pure_long: Constructs a Pure bigint from a 64 bit integer value. + + - pure_bigint: Constructs a Pure bigint from a vector of limbs. The size + argument may be negative to denote a negative number, its absolute value + is the number of elements in the limbs vector (the vector is owned by the + caller and won't be be freed). + + - pure_mpz: Constructs a Pure bigint from a (copy of a) GMP mpz_t. + + - pure_double: Constructs a Pure floating point number from a double value. + + - pure_pointer: Constructs a Pure pointer from a C pointer (void*). */ + +pure_expr *pure_symbol(int32_t sym); pure_expr *pure_int(int32_t i); pure_expr *pure_long(int64_t l); -pure_expr *pure_bigint(int32_t size, limb_t *limbs); -pure_expr *pure_mpz(mpz_t z); +pure_expr *pure_bigint(int32_t size, const limb_t *limbs); +pure_expr *pure_mpz(const mpz_t z); pure_expr *pure_double(double d); pure_expr *pure_pointer(void *p); /* String constructors. There are four variations of these, depending on whether the original string is already in utf-8 (_string routines) or in the system encoding (_cstring), and whether the string should be copied - (_dup suffix) or whether Pure takes ownership of the string (no _dup - suffix). All these routines also handle the case that the given string is a - null pointer and will then return the appropriate Pure pointer expression - instead. */ + (_dup suffix) or whether Pure takes ownership of the string. All four + routines handle the case that the given string is a null pointer and will + then return the appropriate Pure pointer expression instead. */ pure_expr *pure_string_dup(const char *s); pure_expr *pure_cstring_dup(const char *s); pure_expr *pure_string(char *s); pure_expr *pure_cstring(char *s); +/* Function applications. pure_app applies the given function to the given + argument. The result is evaluated if possible (i.e., if it is a saturated + function call). Otherwise, the result is a literal application and + references on function and argument are counted automatically. */ + +pure_expr *pure_app(pure_expr *fun, pure_expr *arg); + +/* Convenience functions to construct Pure list and tuple values from a vector + or a varargs list of element expressions. (Internally these are actually + represented as function applications.) The vectors are owned by the caller + and won't be freed. References on the element expressions are counted + automatically. */ + +pure_expr *pure_listl(size_t size, ...); +pure_expr *pure_listv(size_t size, pure_expr **elems); +pure_expr *pure_tuplel(size_t size, ...); +pure_expr *pure_tuplev(size_t size, pure_expr **elems); + +/* Expression deconstructors for all the expression types above. These all + return a bool value indicating whether the given expression is of the + corresponding type and, if so, set the remaining parameter pointers to the + corresponding values. Parameter pointers may be NULL in which case they are + not set and only the result of the type check is returned. + + NOTES: pure_is_symbol will return true not only for constant and unbound + variable symbols, but also for arbitrary closures including local and + anonymous functions. In the case of an anonymous closure, the returned + symbol will be 0. You can check whether an expression actually represents a + named or anonymous closure using the funp and lambdap predicates from the + library API (see below). + + pure_is_long checks whether the result actually fits into a 64 bit integer. + pure_is_bigint mallocs the returned limb vector (if limbs!=NULL); the + caller is responsible for freeing it. */ + +bool pure_is_symbol(const pure_expr *x, int32_t *sym); +bool pure_is_int(const pure_expr *x, int32_t *i); +bool pure_is_long(const pure_expr *x, int64_t *l); +bool pure_is_bigint(const pure_expr *x, int32_t *size, limb_t **limbs); +bool pure_is_mpz(const pure_expr *x, mpz_t *z); +bool pure_is_double(const pure_expr *x, double *d); +bool pure_is_pointer(const pure_expr *x, void **p); + +/* String results are copied with the _dup routines (it is then the caller's + responsibility to free them when appropriate). pure_is_cstring_dup also + converts the string to the system encoding. The string value returned by + pure_is_string points directly to the string data in the Pure expression + and must not be changed by the caller. */ + +bool pure_is_string(const pure_expr *x, const char **sym); +bool pure_is_string_dup(const pure_expr *x, char **sym); +bool pure_is_cstring_dup(const pure_expr *x, char **sym); + +/* Deconstruct literal applications. */ + +bool pure_is_app(const pure_expr *x, pure_expr **fun, pure_expr **arg); + +/* Convenience functions to deconstruct lists and tuples. Returned element + vectors are malloc'd and must be freed by the caller. Note that + pure_is_tuplev will always return true, since a singleton expression, which + is not either a pair or (), is considered a tuple of size 1. */ + +bool pure_is_listv(const pure_expr *x, size_t *size, pure_expr ***elems); +bool pure_is_tuplev(const pure_expr *x, size_t *size, pure_expr ***elems); + +/* Memory management. */ + +/* Count a new reference to an expression. This should be called whenever you + want to store an expression somewhere, in order to prevent it from being + garbage-collected. */ + +pure_expr *pure_new(pure_expr *x); + +/* Drop a reference to an expression. This will cause the expression to be + garbage-collected when it is no longer needed. */ + +void pure_free(pure_expr *x); + +/* Count a reference and then immediately drop it. This is useful to collect + temporaries which are not referenced yet. */ + +void pure_freenew(pure_expr *x); + +/* Increment and decrement the reference counter of an expression. This can be + used to temporarily protect an expression from being garbage-collected. It + doesn't actually change the status of the expression and does not collect + it. */ + +void pure_ref(pure_expr *x); +void pure_unref(pure_expr *x); + +/* END OF PUBLIC API. *******************************************************/ + +/* Stuff below this line is for internal use by the Pure interpreter. Don't + call these directly, unless you know what you are doing. */ + +/* Construct constant symbols and closures. */ + +pure_expr *pure_const(int32_t tag); +pure_expr *pure_clos(bool local, bool thunked, int32_t tag, uint32_t n, + void *f, void *e, uint32_t m, /* m x pure_expr* */ ...); + /* Compare a bigint or string expression against a constant value. This is used by the pattern matching code. */ -int32_t pure_cmp_bigint(pure_expr *x, int32_t size, limb_t *limbs); +int32_t pure_cmp_bigint(pure_expr *x, int32_t size, const limb_t *limbs); int32_t pure_cmp_string(pure_expr *x, const char *s); /* Get the string value of a string expression in the system encoding. Each @@ -127,33 +273,10 @@ /* Run a Pure function and catch exceptions. If everything goes normal, pure_invoke returns the return value of the executed function. Otherwise it returns 0 and sets e to the exception value, as given by pure_throw(). - XXXFIXME: This only supports parameterless functions right now. */ + FIXME: This only supports parameterless functions right now. */ pure_expr *pure_invoke(void *f, pure_expr** e); -/* Count a new reference to an expression. This should be called whenever you - want to store an expression somewhere, in order to prevent it from being - garbage-collected. */ - -pure_expr *pure_new(pure_expr *x); - -/* Drop a reference to an expression. This will cause the expression to be - garbage-collected when it is no longer needed. */ - -void pure_free(pure_expr *x); - -/* Count a reference and then immediately drop it. This is useful to collect - temporaries which are not referenced yet. */ - -void pure_freenew(pure_expr *x); - -/* Increment and decrement the reference counter. This can be used to - temporarily protect an expression from being garbage-collected. It doesn't - actually change the status of the expression and does not collect it. */ - -void pure_ref(pure_expr *x); -void pure_unref(pure_expr *x); - /* Manage arguments of a function call. pure_new_args counts references on a given collection of arguments in preparation for a function call, while pure_free_args collects the arguments of a function call. In both cases the @@ -199,8 +322,12 @@ void pure_debug(int32_t tag, const char *format, ...); -/* Supplementary routines. These are used in the standard library. */ +/* LIBRARY API. *************************************************************/ +/* Add any stuff that is needed in the standard library here. Applications and + external C modules may call these, but be warned that these APIs are + subject to change without further notice. */ + /* Conversions between numeric and pointer types. The input argument must be an expression denoting an int, double, bigint or pointer value. The numeric value of a pointer is its address, cast to a suitably large integer type, @@ -272,7 +399,8 @@ /* Convert a Pure expression to a string and vice versa. Note that eval() will actually parse and execute any Pure source, so it can be used, e.g., to add - new rules to the executing program at runtime. */ + new rules to the executing program at runtime. The result of eval() is the + last computed expression (NULL if none). */ pure_expr *str(const pure_expr *x); pure_expr *eval(const char *s); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |