Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion dub.sdl
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ subPackage {
"src/dmd/utf.d" \
"src/dmd/utils.d"

versions "CallbackAPI"

preGenerateCommands `
"$${DUB_EXE}" \
--arch=$${DUB_ARCH} \
Expand Down Expand Up @@ -60,6 +62,8 @@ subPackage {
"src/dmd/permissivevisitor.d" \
"src/dmd/strictvisitor.d"

versions "CallbackAPI"

dependency "dmd:lexer" version="*"
}

Expand All @@ -73,7 +77,8 @@ subPackage {
"NoBackend" \
"GC" \
"NoMain" \
"MARS"
"MARS" \
"CallbackAPI"

excludedSourceFiles "src/dmd/backend/*"
excludedSourceFiles "src/dmd/root/*"
Expand Down
21 changes: 21 additions & 0 deletions src/dmd/compiler.d
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import dmd.root.ctfloat;
import dmd.semantic2;
import dmd.semantic3;
import dmd.tokens;
import dmd.statement;

extern (C++) __gshared
{
Expand Down Expand Up @@ -152,6 +153,26 @@ extern (C++) struct Compiler
}
return false; // this import will not be compiled
}

version (CallbackAPI)
{
alias OnStatementSemanticStart = void function(Statement, Scope*);
alias OnStatementSemanticDone = void function(Statement, Scope*);

/**
* Used to insert functionality before the start of the
* semantic analysis of a statement when importing DMD as a library
*/
__gshared OnStatementSemanticStart onStatementSemanticStart
= function void(Statement s, Scope *sc) {};

/**
* Used to insert functionality after the end of the
* semantic analysis of a statement when importing DMD as a library
*/
__gshared OnStatementSemanticDone onStatementSemanticDone
= function void(Statement s, Scope *sc) {};
}
}

/******************************
Expand Down
220 changes: 124 additions & 96 deletions src/dmd/mars.d
Original file line number Diff line number Diff line change
Expand Up @@ -2613,6 +2613,125 @@ private void reconcileCommands(ref Param params, size_t numSrcFiles)
params.useDIP25 = false;
}

/**
Creates the module based on the file provided

The file is dispatched in one of the various arrays
(global.params.{ddocfiles,dllfiles,jsonfiles,etc...})
according to its extension.
If it is a binary file, it is added to libmodules.

Params:
file = File name to dispatch
libmodules = Array to which binaries (shared/static libs and object files)
will be appended

Returns:
A D module
*/
Module createModule(const(char)* file, ref Strings libmodules)
{
const(char)[] name;
version (Windows)
{
file = toWinPath(file);
}
const(char)[] p = file.toDString();
p = FileName.name(p); // strip path
const(char)[] ext = FileName.ext(p);
if (!ext)
{
if (!p.length)
{
error(Loc.initial, "invalid file name '%s'", file);
fatal();
}
auto id = Identifier.idPool(p);
return new Module(file.toDString, id, global.params.doDocComments, global.params.doHdrGeneration);
}

/* Deduce what to do with a file based on its extension
*/
if (FileName.equals(ext, global.obj_ext))
{
global.params.objfiles.push(file);
libmodules.push(file);
return null;
}
if (FileName.equals(ext, global.lib_ext))
{
global.params.libfiles.push(file);
libmodules.push(file);
return null;
}
static if (TARGET.Linux || TARGET.OSX || TARGET.FreeBSD || TARGET.OpenBSD || TARGET.Solaris || TARGET.DragonFlyBSD)
{
if (FileName.equals(ext, global.dll_ext))
{
global.params.dllfiles.push(file);
libmodules.push(file);
return null;
}
}
if (ext == global.ddoc_ext)
{
global.params.ddocfiles.push(file);
return null;
}
if (FileName.equals(ext, global.json_ext))
{
global.params.doJsonGeneration = true;
global.params.jsonfilename = file.toDString;
return null;
}
if (FileName.equals(ext, global.map_ext))
{
global.params.mapfile = file.toDString;
return null;
}
static if (TARGET.Windows)
{
if (FileName.equals(ext, "res"))
{
global.params.resfile = file.toDString;
return null;
}
if (FileName.equals(ext, "def"))
{
global.params.deffile = file.toDString;
return null;
}
if (FileName.equals(ext, "exe"))
{
assert(0); // should have already been handled
}
}
/* Examine extension to see if it is a valid
* D source file extension
*/
if (FileName.equals(ext, global.mars_ext) || FileName.equals(ext, global.hdr_ext) || FileName.equals(ext, "dd"))
{
name = FileName.removeExt(p);
if (!name.length || name == ".." || name == ".")
{
error(Loc.initial, "invalid file name '%s'", file);
fatal();
}
}
else
{
error(Loc.initial, "unrecognized file extension %.*s", cast(int)ext.length, ext.ptr);
fatal();
}

/* At this point, name is the D source file name stripped of
* its path and extension.
*/
auto id = Identifier.idPool(name);

return new Module(file.toDString, id, global.params.doDocComments, global.params.doHdrGeneration);
}

/**
Creates the list of modules based on the files provided

Expand All @@ -2636,102 +2755,11 @@ Modules createModules(ref Strings files, ref Strings libmodules)
bool firstmodule = true;
for (size_t i = 0; i < files.dim; i++)
{
const(char)[] name;
version (Windows)
{
files[i] = toWinPath(files[i]);
}
const(char)[] p = files[i].toDString();
p = FileName.name(p); // strip path
const(char)[] ext = FileName.ext(p);
if (ext)
{
/* Deduce what to do with a file based on its extension
*/
if (FileName.equals(ext, global.obj_ext))
{
global.params.objfiles.push(files[i]);
libmodules.push(files[i]);
continue;
}
if (FileName.equals(ext, global.lib_ext))
{
global.params.libfiles.push(files[i]);
libmodules.push(files[i]);
continue;
}
static if (TARGET.Linux || TARGET.OSX || TARGET.FreeBSD || TARGET.OpenBSD || TARGET.Solaris || TARGET.DragonFlyBSD)
{
if (FileName.equals(ext, global.dll_ext))
{
global.params.dllfiles.push(files[i]);
libmodules.push(files[i]);
continue;
}
}
if (ext == global.ddoc_ext)
{
global.params.ddocfiles.push(files[i]);
continue;
}
if (FileName.equals(ext, global.json_ext))
{
global.params.doJsonGeneration = true;
global.params.jsonfilename = files[i].toDString;
continue;
}
if (FileName.equals(ext, global.map_ext))
{
global.params.mapfile = files[i].toDString;
continue;
}
static if (TARGET.Windows)
{
if (FileName.equals(ext, "res"))
{
global.params.resfile = files[i].toDString;
continue;
}
if (FileName.equals(ext, "def"))
{
global.params.deffile = files[i].toDString;
continue;
}
if (FileName.equals(ext, "exe"))
{
assert(0); // should have already been handled
}
}
/* Examine extension to see if it is a valid
* D source file extension
*/
if (FileName.equals(ext, global.mars_ext) || FileName.equals(ext, global.hdr_ext) || FileName.equals(ext, "dd"))
{
name = FileName.removeExt(p);
if (!name.length || name == ".." || name == ".")
{
Linvalid:
error(Loc.initial, "invalid file name '%s'", files[i]);
fatal();
}
}
else
{
error(Loc.initial, "unrecognized file extension %.*s", cast(int)ext.length, ext.ptr);
fatal();
}
}
else
{
name = p;
if (!name.length)
goto Linvalid;
}
/* At this point, name is the D source file name stripped of
* its path and extension.
*/
auto id = Identifier.idPool(name);
auto m = new Module(files[i].toDString, id, global.params.doDocComments, global.params.doHdrGeneration);
auto m = createModule(files[i], libmodules);

if (m is null)
continue;

modules.push(m);
if (firstmodule)
{
Expand Down
8 changes: 8 additions & 0 deletions src/dmd/statementsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import dmd.target;
import dmd.tokens;
import dmd.typesem;
import dmd.visitor;
import dmd.compiler;

/*****************************************
* CTFE requires FuncDeclaration::labtab for the interpretation.
Expand Down Expand Up @@ -123,8 +124,15 @@ private Expression checkAssignmentAsCondition(Expression e)
// Performs semantic analysis in Statement AST nodes
extern(C++) Statement statementSemantic(Statement s, Scope* sc)
{
version (CallbackAPI)
Compiler.onStatementSemanticStart(s, sc);

scope v = new StatementSemanticVisitor(sc);
s.accept(v);

version (CallbackAPI)
Compiler.onStatementSemanticDone(s, sc);

return v.result;
}

Expand Down
Loading