From dbafe7e89cac14a11eb6cac93bdf42b051494bc8 Mon Sep 17 00:00:00 2001 From: Thomas Leonard Date: Sun, 19 Oct 2008 16:44:12 +0100 Subject: [PATCH] Modular handling of externals Instead of having the main module import the single dlt._externals file, it now imports files based on the type. For example, if you do: import dlt.io: Printer class Main: in Printer stdout Then it calls '_externals.dlt.io.stdout()' to get the object. This avoids creating dependencies on modules and symbols we don't need, and makes it easier to extend the library with new externals. A related change is that SystemExit is now part of object.d and handled by the normal D main invoker. This was being handled by a method on the old Externals object. --- dmd2/module.c | 3 -- dmd2/parse.c | 4 +-- dmd2/statement.c | 80 ++++++++++++++++++++++++++++++----------------- phobos2/internal/dmain2.d | 5 +++ phobos2/internal/object.d | 12 +++++++ phobos2/object.d | 9 +++++- 6 files changed, 78 insertions(+), 35 deletions(-) diff --git a/dmd2/module.c b/dmd2/module.c index b41d86a..1281451 100644 --- a/dmd2/module.c +++ b/dmd2/module.c @@ -711,9 +711,6 @@ void Module::semantic() return; members->push(mainFn); - Import *im = new Import(0, dlt_package, Id::_externals, NULL, true); - members->shift(im); - break; } } diff --git a/dmd2/parse.c b/dmd2/parse.c index e3ac86d..5abaa52 100644 --- a/dmd2/parse.c +++ b/dmd2/parse.c @@ -76,7 +76,7 @@ DltParser::DltParser(Module *module, unsigned char *base, unsigned length, int d { //printf("DltParser::DltParser(%s)\n", module->ident->string); startBlockTok = TOKcolon; - dltNormalMode = TRUE; // becomes false if we find a "module dlt.*" + dltNormalMode = TRUE; // becomes false if we find a "module dlt.*" or _externals } Array *Parser::parseModule() @@ -101,7 +101,7 @@ Array *Parser::parseModule() id = token.ident; - if (dltSyntax && id == Id::dlt) + if (dltSyntax && (id == Id::dlt || id == Id::_externals)) dltNormalMode = FALSE; while (nextToken() == TOKdot) diff --git a/dmd2/statement.c b/dmd2/statement.c index 98f4c2b..92ee192 100644 --- a/dmd2/statement.c +++ b/dmd2/statement.c @@ -356,10 +356,9 @@ void DeclarationStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) /******************************** InjectorMainBody ***************************/ -static Expressions *getAutoArgs(Loc loc, Arguments *arguments) { +static Expressions *getAutoArgs(Loc loc, Arguments *arguments, Scope *sc) { Expressions *args = new Expressions(); - Expression *externals = new IdentifierExp(loc, Id::externals); // Collect all the objects we need for the constructor's arguments for (int i = 0; i < arguments->dim; i++) { Argument *arg = (Argument *) arguments->data[i]; @@ -367,8 +366,50 @@ static Expressions *getAutoArgs(Loc loc, Arguments *arguments) { // For 'args', just pass through the string[] passed to main() args->push(new IdentifierExp(loc, arg->ident)); } else { - // For everything else, call a getter in the _externals module - Expression *getter = new DotIdExp(loc, externals, arg->ident); + // For everything else, call a getter in a dlt._externals.type module + Type *type = arg->type->semantic(loc, sc); + char* typeStr = strdup(type->toChars()); + + char* typeName = strrchr(typeStr, '.'); + if (typeName == NULL) { + error("Expected '.' in main-injected type %s", typeName); + return NULL; + } + *typeName = '\0'; + typeName++; + + Array *dlt_package = new Array(); + dlt_package->push(Id::_externals); + + Expression *getter = new IdentifierExp(loc, Id::_externals); + while (char *p = strchr(typeStr, '.')) { + *p = '\0'; + Identifier* component = new Identifier(typeStr, TOKidentifier); + dlt_package->push(component); + getter = new DotIdExp(loc, getter, component); + typeStr = p + 1; + } + Identifier* component = new Identifier(typeStr, TOKidentifier); + getter = new DotIdExp(loc, getter, component); + getter = new DotIdExp(loc, getter, arg->ident); + + Import *im = new Import(loc, dlt_package, component, NULL, true); + sc->module->members->shift(im); + im->addMember(NULL, sc->scopesym, 1); + im->semantic(sc); + + /* + HdrGenState hgs; + OutBuffer *buf = new OutBuffer(); + im->toCBuffer(buf, &hgs); + fprintf(stderr, "i: %s\n", buf->toChars()); + */ + + getter = new CallExp(loc, getter); + + //fprintf(stderr, "e: %s\n", getter->toChars()); + //fprintf(stderr, "type: %s\n", getter->type->toChars()); + args->push(getter); } } @@ -417,38 +458,19 @@ Statement *InjectorMainBody::semantic(Scope *sc) return NULL; } - // Externals externals = new _externals.Externals() - TypeIdentifier *extType = new TypeIdentifier(loc, Id::dlt); - extType->addIdent(Id::_externals); - extType->addIdent(Id::Externals); - - Expression *newExt = new NewExp(loc, NULL, NULL, extType, NULL); - VarDeclaration *v = new VarDeclaration(loc, extType, Id::externals, - new ExpInitializer(loc, newExt)); - Statement *assignExt = new DeclarationStatement(loc, v); Expression *newMain = new NewExp(loc, NULL, NULL, mainClass->getType(), - ctor ? getAutoArgs(ctor->loc, ctor->arguments) : NULL); + ctor ? getAutoArgs(ctor->loc, ctor->arguments, sc) : NULL); // Then invoke the main() method inside it // mainObject.main(...) Expression *mainMethod = new DotIdExp(mainDecl->loc, newMain, Id::main); Expression *mainCall = new CallExp(mainMethod->loc, mainMethod, getAutoArgs(mainDecl->loc, - ((TypeFunction *) mainDecl->type)->parameters)); - - Statement *s = new ExpStatement(loc, mainCall); - Statement *runMain = new CompoundStatement(loc, assignExt, s); - - // catch (SystemExit) - Array *catches = new Array(); - Statement *handler = new ExpStatement(loc, new CallExp(loc, - new DotIdExp(loc, - new IdentifierExp(loc, Id::externals), - Id::SystemExit), - new IdentifierExp(loc, Id::result))); - Catch *c = new Catch(loc, new TypeIdentifier(loc, Id::SystemExit), Id::result, handler); - catches->push(c); - Statement *body = new TryCatchStatement(loc, runMain, catches); + ((TypeFunction *) mainDecl->type)->parameters, + sc)); + + Statement *body = new ExpStatement(loc, mainCall); + return body->semantic(sc); } diff --git a/phobos2/internal/dmain2.d b/phobos2/internal/dmain2.d index 227520b..0030f41 100644 --- a/phobos2/internal/dmain2.d +++ b/phobos2/internal/dmain2.d @@ -94,6 +94,11 @@ extern (C) int main(size_t argc, char **argv) _moduleDtor(); gc_term(); } + catch (SystemExit ex) + { + fprintf(stderr, "%.*s\n", o.toString()); + exit(ex.exitCode); + } catch (Object o) { version (none) diff --git a/phobos2/internal/object.d b/phobos2/internal/object.d index 58f60ac..75e8fa0 100644 --- a/phobos2/internal/object.d +++ b/phobos2/internal/object.d @@ -1241,3 +1241,15 @@ class Error : Exception //extern (C) int nullext = 0; +/**If the top-level main throws this, the message will be printed to stderr + * and the program terminates with the given exit code. + */ +class SystemExit : Exception { + int exitCode; + + this(string msg, int exitCode = 1) + { + this.exitCode = exitCode; + super(msg); + } +} diff --git a/phobos2/object.d b/phobos2/object.d index 33c34d7..b95eac0 100644 --- a/phobos2/object.d +++ b/phobos2/object.d @@ -15,7 +15,6 @@ alias invariant(dchar)[] dstring; extern (C) { int printf(in char *, ...); - void trace_term(); } class Object @@ -222,3 +221,11 @@ class Error : Exception this(string msg, Error next); } +/** If the top-level main throws this, the message will be printed to stderr + * and the program terminates with the given exit code. + */ +class SystemExit : Exception { + int exitCode; + + this(string msg, int exitCode = 1); +} -- 2.11.4.GIT