D Compiler as a Library
Bernard Helyer
b.helyer at gmail.com
Mon Apr 16 05:16:56 PDT 2012
On Monday, 16 April 2012 at 02:34:29 UTC, Ary Manzana wrote:
> On 4/13/12 9:10 PM, deadalnix wrote:
>> Le 13/04/2012 11:58, Ary Manzana a écrit :
>>> Having a D compiler available as a library will (at least)
>>> give these
>>> benefits:
>>>
>>> 1. Can be used by an IDE: D is statically typed and so an IDE
>>> can
>>> benefit a lot from this. The features Descent had, as far as
>>> I remember,
>>> were:
>>> 1.1. Outline
>>> 1.2. Autocompletion
>>> 1.3. Type Hierarchy
>>> 1.4. Syntax and semantic errors, showing not only the line
>>> number but
>>> also column numbers if it makes sense
>>> 1.5. Automatic import inclusion (say, typing writefln and
>>> getting a list
>>> of modules that provide that symbol)
>>> 1.6. Compile-time view: replace auto with the inferred type,
>>> insert
>>> mixins into scope, rewrite operator overloads and other
>>> lowerings (but
>>> I'm not sure this point is really useful)
>>> 1.7. Determine, given a set of versions and flags, which
>>> branches of
>>> static ifs are used/unused
>>> 1.8. Open declaration
>>> 1.9. Show implementations (of an interface, of interface's
>>> method or,
>>> abstract methods, or method overrides).
>>> 1.10. Propose to override a method (you type some letters and
>>> then hit
>>> some key combination and get a list of methods to override)
>>> 1.11. Get the code of a template when instantiated.
>>> 2. Can be used to build better doc generators: one that shows
>>> known
>>> subclasses or interface implementation, shows inherited
>>> methods, type
>>> hierarchy.
>>> 3. Can be used for lints and other such tools.
>>>
>>> As you can see, a simple lexer/parser built into an IDE, doc
>>> generator
>>> or lint will just give basic features but will never achieve
>>> something
>>> exceptionally good if it lacks the full semantic knowledge of
>>> the code.
>>>
>>> I'll write a list of things I'd like this compiler-as-library
>>> to have,
>>> but please help me make it bigger :-)
>>>
>>> * Don't use global variables (DMD is just thought to be run
>>> once, so
>>> when used as a library it can just be used, well, once)
>>> * Provide a lexer which gives line numbers and column numbers
>>> (beginning, end)
>>> * Provide a parser with the same features
>>> * The semantic phase should not discard any information found
>>> while
>>> parsing. For example when DMD resolves a type it recursively
>>> resolves
>>> aliasing and keeps the last one. An example:
>>>
>>> alias int foo;
>>> alias foo* bar;
>>>
>>> bar something() { ... }
>>>
>>> It would be nice if "bar", after semantic analysis is done,
>>> carries the
>>> information that bar is "foo*" and that "foo" is "int". Also
>>> that
>>> something's return type is "bar", not "int*".
>>> * Provide errors and warnings that have line numbers as well
>>> as column
>>> numbers.
>>> * Allow to parse the top-level definitions of a module. Whit
>>> this I mean
>>> skipping function bodies. At least Descent first built a the
>>> outline of
>>> the whole project by doing this. This mode should also allow
>>> specifying
>>> a location as a target, and if that location falls inside a
>>> function
>>> body then it's contents are returned (useful when editing a
>>> file, so you
>>> can get the outline as well as semantic info of the function
>>> currently
>>> being edited, which will never affect semantic in other parts
>>> of the
>>> module). This will dramatically speed up the editor.
>>> * Don't stop parsing on errors (I think DMD already does
>>> this).
>>> * Provide a visitor class. If possible, use visitors to
>>> implement
>>> semantic analysis. The visitor will make it super easy to
>>> implement
>>> lints and to generate documentation.
>>
>> SDC have a lot of theses, and I proposed a similar stuff for
>> its
>> evolution. I think it is easier for SDC than it is for dmd
>> considering
>> the codebase of both.
>
> Cool! SDC is the way to go. Let's focus our efforts on that
> project. :-)
>
> One thing I saw in the code is that global variables are used
> in it (specially in the sdc.aglobal module).
>
> Also, the lexer returns a TokenStream which contains the full
> array of tokens. This is very slow compared to returning them
> as they are scanned, when requested. But I guess this is easy
> to fix as it's hidden behind the TokenStream interface.
>
> I tried to compile a simple file:
>
> void main() {}
>
> > ./bin/sdc main.d
> core.exception.AssertError at sdc.gen.sdcmodule(560): Assertion
> failure
> ----------------
> 5 sdc 0x000000010b87aa2a
> _d_assertm + 42
> 6 sdc 0x000000010b4e2daa void
> sdc.gen.sdcmodule.__assert(int) + 26
> 7 sdc 0x000000010b55d19c void
> sdc.gen.sdcmodule.Store.addFunction(sdc.gen.sdcfunction.Function)
> + 92
> 8 sdc 0x000000010b55d75b void
> sdc.gen.sdcmodule.Scope.add(immutable(char)[],
> sdc.gen.sdcfunction.Function) + 123
> 9 sdc 0x000000010b54ee36 void
> sdc.gen.declaration.declareFunctionDeclaration(sdc.ast.declaration.FunctionDeclaration,
> sdc.ast.sdcmodule.DeclarationDefinition,
> sdc.gen.sdcmodule.Module) + 1278
> 10 sdc 0x000000010b54e4b2 void
> sdc.gen.declaration.declareDeclaration(sdc.ast.declaration.Declaration,
> sdc.ast.sdcmodule.DeclarationDefinition,
> sdc.gen.sdcmodule.Module) + 146
> 11 sdc 0x000000010b54d12e void
> sdc.gen.base.genDeclarationDefinition(sdc.ast.sdcmodule.DeclarationDefinition,
> sdc.gen.sdcmodule.Module, ulong) + 374
> 12 sdc 0x000000010b54c8d0 void
> sdc.gen.base.resolveDeclarationDefinitionList(sdc.ast.sdcmodule.DeclarationDefinition[],
> sdc.gen.sdcmodule.Module, sdc.gen.type.Type) + 564
> 13 sdc 0x000000010b54c439
> sdc.gen.sdcmodule.Module
> sdc.gen.base.genModule(sdc.ast.sdcmodule.Module,
> sdc.aglobal.TranslationUnit) + 157
> 14 sdc 0x000000010b53432d int
> sdc.sdc.realmain(immutable(char)[][]) + 3081
> 15 sdc 0x000000010b4e283e
> _Dmain + 54
> 16 sdc 0x000000010b87b415
> extern (C) int rt.dmain2.main(int, char**).void runMain() + 29
> 17 sdc 0x000000010b87adc5
> extern (C) int rt.dmain2.main(int, char**).void tryExec(scope
> void delegate()) + 45
> 18 sdc 0x000000010b87b467
> extern (C) int rt.dmain2.main(int, char**).void runAll() + 63
> 19 sdc 0x000000010b87adc5
> extern (C) int rt.dmain2.main(int, char**).void tryExec(scope
> void delegate()) + 45
> 20 sdc 0x000000010b87ad48 main
> + 232
> 21 sdc 0x000000010b4e2694
> start + 52
> 22 ??? 0x0000000000000002 0x0
> + 2
> ----------------
https://github.com/bhelyer/SDC/issues/30
Rename main.d to something else and it should work. Gotta fix
that. >_<
More information about the Digitalmars-d
mailing list