[pure-lang-svn] SF.net SVN: pure-lang: [296] pure/trunk
Status: Beta
Brought to you by:
agraef
From: <ag...@us...> - 2008-06-24 12:41:28
|
Revision: 296 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=296&view=rev Author: agraef Date: 2008-06-24 05:41:37 -0700 (Tue, 24 Jun 2008) Log Message: ----------- Finish off public runtime API with some operations to create standalone interpreters. Modified Paths: -------------- pure/trunk/runtime.cc pure/trunk/runtime.h Modified: pure/trunk/runtime.cc =================================================================== --- pure/trunk/runtime.cc 2008-06-24 10:38:29 UTC (rev 295) +++ pure/trunk/runtime.cc 2008-06-24 12:41:37 UTC (rev 296) @@ -801,6 +801,144 @@ pure_unref_internal(x); } +#ifndef HOST +#define HOST "unknown" +#endif +#ifndef PACKAGE_VERSION +#define PACKAGE_VERSION "0.0" +#endif +#ifndef PURELIB +#define PURELIB "/usr/local/lib/pure-" PACKAGE_VERSION +#endif + +#include <llvm/Target/TargetOptions.h> + +extern "C" +pure_interp *pure_create_interp(int argc, const char *argv[]) +{ + // This is pretty much the same as pure.cc:main(), except that some options + // are ignored and there's no user interaction. + char base; + interpreter *_interp = new interpreter, &interp = *_interp; + int count = 0; + bool want_prelude = true, have_prelude = false; + // This is used in advisory stack checks. + if (!interpreter::baseptr) interpreter::baseptr = &base; + // get some settings from the environment + const char *env; + if ((env = getenv("HOME"))) + interp.histfile = string(env)+"/.pure_history"; + if ((env = getenv("PURE_PS"))) + interp.ps = string(env); + if ((env = getenv("PURE_STACK"))) { + char *end; + size_t n = strtoul(env, &end, 0); + if (!*end) interpreter::stackmax = n*1024; + } + if ((env = getenv("PURELIB"))) + interp.lib = string(env)+"/"; + else + interp.lib = string(PURELIB)+"/"; + string prelude = interp.lib+string("prelude.pure"); +#if USE_FASTCC + // This global option is needed to get tail call optimization (you'll also + // need to have USE_FASTCC in interpreter.hh enabled). + llvm::PerformTailCallOpt = true; +#endif + // scan the command line options + list<string> myargs; + for (const char **args = ++argv; *args; ++args) + if (*args == string("-h")) + /* ignored */; + else if (*args == string("-i")) + /* ignored */; + else if (*args == string("-n")) + want_prelude = false; + else if (*args == string("-q")) + /* ignored */; + else if (string(*args).substr(0,2) == "-v") { + string s = string(*args).substr(2); + if (s.empty()) continue; + char *end; + strtoul(s.c_str(), &end, 0); + if (*end) { + cerr << "pure_create_interp: invalid option " << *args << endl; + delete _interp; + return 0; + } + } else if (*args == string("-x")) { + while (*++args) myargs.push_back(*args); + break; + } else if (*args == string("--")) { + while (*++args) myargs.push_back(*args); + break; + } else if (**args == '-') { + cerr << "pure_create_interp: invalid option " << *args << endl; + delete _interp; + return 0; + } + interp.init_sys_vars(PACKAGE_VERSION, HOST, myargs); + if (want_prelude) { + // load the prelude if we can find it + FILE *fp = fopen("prelude.pure", "r"); + if (fp) + prelude = "prelude.pure"; + else + // try again in the PURELIB directory + fp = fopen(prelude.c_str(), "r"); + if (fp) { + fclose(fp); + have_prelude = true; + interp.run(prelude); + interp.compile(); + } + } + // load scripts specified on the command line + for (; *argv; ++argv) + if (string(*argv).substr(0,2) == "-v") { + uint8_t level = 1; + string s = string(*argv).substr(2); + if (!s.empty()) level = (uint8_t)strtoul(s.c_str(), 0, 0); + interp.verbose = level; + } else if (*argv == string("-x")) { + if (*++argv) { + count++; interp.modname = *argv; + interp.run(*argv); + } else { + cerr << "pure_create_interp: missing script name\n"; + delete _interp; + return 0; + } + break; + } else if (*argv == string("--")) + break; + else if (**argv == '-') + ; + else if (**argv) { + if (count++ == 0) interp.modname = *argv; + interp.run(*argv); + } + interp.symtab.init_builtins(); + return (pure_interp*)_interp; +} + +extern "C" +void pure_delete_interp(pure_interp *interp) +{ + assert(interp); + interpreter *_interp = (interpreter*)interp; + if (interpreter::g_interp == _interp) + interpreter::g_interp = 0; + delete _interp; +} + +extern "C" +void pure_switch_interp(pure_interp *interp) +{ + assert(interp); + interpreter::g_interp = (interpreter*)interp; +} + /* END OF PUBLIC API. *******************************************************/ extern "C" Modified: pure/trunk/runtime.h =================================================================== --- pure/trunk/runtime.h 2008-06-24 10:38:29 UTC (rev 295) +++ pure/trunk/runtime.h 2008-06-24 12:41:37 UTC (rev 296) @@ -221,6 +221,41 @@ void pure_ref(pure_expr *x); void pure_unref(pure_expr *x); +/* The following routines provide standalone C/C++ applications with fully + initialized interpreter instances which can be used together with the + operations listed above. This is only needed for modules which are not to + be loaded by the command line version of the interpreter. + + The argc, argv parameters passed to pure_create_interp specify the command + line arguments of the interpreter instance. This includes any scripts that + are to be loaded on startup as well as any other options understood by the + command line version of the interpreter (options like -i and -q won't have + any effect, though, and the interpreter will always be in non-interactive + mode). The argv vector must be NULL-terminated, and argv[0] should be set + to the name of the hosting application (usually the main program of the + application). + + An application may use multiple interpreter instances, but only a single + instance can be active at any one time. By default, the first created + instance will be active, but you can switch between different instances + with the pure_switch_interp function. The pure_delete_interp routine + destroys an interpreter instance; if the destroyed instance is currently + active, the active instance will be undefined afterwards, so you'll have to + either create or switch to another instance before calling any other + operations. + + Note that when using different interpreter instances in concert, it is + *not* possible to pass pure_expr* values created with one interpreter + instance to another. Instead, you can use the str and eval functions from + the library API (see below) to first unparse the expression in the source + interpreter and then reparse it in the target interpreter. */ + +typedef struct pure_interp; // Pure interpreter handles (opaque). + +pure_interp *pure_create_interp(int argc, const char *argv[]); +void pure_delete_interp(pure_interp *interp); +void pure_switch_interp(pure_interp *interp); + /* END OF PUBLIC API. *******************************************************/ /* Stuff below this line is for internal use by the Pure interpreter. Don't This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |