The first task of the analyzer is collation. This basically means going through all the source files and gluing them together. It also means that, from the analyzer's perspective, the data structures are in an irrelevant order- that is, the analyzer doesn't care if you used a function before defining it. The analyzer doesn't look at the *contents* of functions, etc. It just says "Wide.X is a variable.". Collation yields errors like "you said that Wide.X was a variable, but earlier you said it was a function".
The second stage will be compilation- the analyzer starts by looking in all entry points. That means Main(), obviously, and any exported symbols. Then it recursively compiles all functions and types used. This will yield things like "You tried to assign an int to a string, wtf you smoking?" and construct the semantic types for expressions, statements, that kind of useful thing.
The third is code generation. This will mean conversion to LLVM IR, and then ask LLVM to kindly make it into an executable of a useful format, such as PE. Then compilation will be complete.
Right now I'm working on collation. Specifically, I have observed that I give shitty errors. Not quite "You fucked up", but "You made X mistake." and it really needs to be "You made X mistake, and you should really take a look at Y locations to see wtf I'm talking about." This means that Y needs to be passed from the lexer through the parser to the analyzer, which means interacting with my old fun friend Bison.
Moving location data through the parser today so the semantic analyser can give meaningful errors. Right now, I can tell you that you made a mistake, but not the location, which is obviously not very helpful. Currently, AST nodes carry the beginning and end tokens that produced them. Some "container" nodes, like modules, contain only their own data, as each element is a separate node that should be considered separately.
ATM, the only mistakes you can make that I can pick up on are that you gave a module member two different access levels, and that you said a module was dynamic once and then not again. In addition, in theory, I can mention that there was already something else where you tried to put a module, but unfortunately, since modules are the only things I actually collate right now, there's not much to conflict with.
Friday, 23 December 2011
Tuesday, 20 December 2011
Move semantics
RARGH VISUAL STUDIO Y U SUCK :(
At least, soon, when I get an ICE, it'll be my own fault.
At least, soon, when I get an ICE, it'll be my own fault.
Monday, 5 December 2011
Impossible implementation
I've come to the conclusion that it may be physically impossible to implement WideC as I had planned. The simple problem is interoperation.
The compiler interops heavily with the generated code- for example, they must use the same string classes and data structures, the same exception handling, the same inheritance implementation, etc. This is going to be a big problem, because in order to write the compiler's internal data structures to interact with the WideC libraries, I'd have to compile the WideC libraries, which is obviously impossible, since I can't write the compiler's necessary data structures.
The only solution to this is going to be a C-style abstraction, I think.
The compiler interops heavily with the generated code- for example, they must use the same string classes and data structures, the same exception handling, the same inheritance implementation, etc. This is going to be a big problem, because in order to write the compiler's internal data structures to interact with the WideC libraries, I'd have to compile the WideC libraries, which is obviously impossible, since I can't write the compiler's necessary data structures.
The only solution to this is going to be a C-style abstraction, I think.
Sunday, 4 December 2011
ABI independence
The problem I'm currently focusing my non-trivial talents on is a specified ABI. I think that by simply delegating to the C ABI, this would be effectively achieved. Exceptions can already be converted relatively easy using the old error code mechanism, except that the language spec would enforce that it be checked and converted automatically, as it were.
Standard.String exported_func() throws(Standard.String) {
throw "harhar";
}
becomes, equivalently,
char buff[sizeof(Standard.String)];
void* result = &buff[0];
auto enumvalue = exported_func(&result);
if (result == &buff[0]) // buff contains a valid Standard.String
else {
if (enumvalue == 1)
// result points to Standard.String exception value
// do shit
__dll_free_exception(result);
else
// fuck
}
Not the cheapest conversion ever, but at least it should be fairly simple to automate.
The problem comes in the specification of Standard types. Logically, a custom type can only be built of only two things, ultimately:
Primitive C types, like fixed-width integers / doubles / pointers
Standard types
Obviously, every limitation placed on the implementation restricts the available implementations, which is not something I really want. On the other hand, totally unrestricted implementation means that no implementations can be compatible, which is unacceptable. This issue is partially solved because dynamic libraries are intended to be much rarer in WideC than in C++, but still needs further exploration.
Standard.String exported_func() throws(Standard.String) {
throw "harhar";
}
becomes, equivalently,
char buff[sizeof(Standard.String)];
void* result = &buff[0];
auto enumvalue = exported_func(&result);
if (result == &buff[0]) // buff contains a valid Standard.String
else {
if (enumvalue == 1)
// result points to Standard.String exception value
// do shit
__dll_free_exception(result);
else
// fuck
}
Not the cheapest conversion ever, but at least it should be fairly simple to automate.
The problem comes in the specification of Standard types. Logically, a custom type can only be built of only two things, ultimately:
Primitive C types, like fixed-width integers / doubles / pointers
Standard types
Obviously, every limitation placed on the implementation restricts the available implementations, which is not something I really want. On the other hand, totally unrestricted implementation means that no implementations can be compatible, which is unacceptable. This issue is partially solved because dynamic libraries are intended to be much rarer in WideC than in C++, but still needs further exploration.
Monday, 28 November 2011
Unicode
So, I've been attempting to patch up my Unicode support. The lexer's support for it was, well, kinda laughable. It really didn't deal with collating characters and other things properly. As such, I have been forced to retreat to ICU. Oh holy shit, have these guys ever even seen a reasonable quality C++ library? ewwwwwwww. I hate you, now and forever, Unicode.
On the plus side, my custom parser will be done really quite soon. I've been working on the expression handling and I finally managed to express them in such a way that Visual Studio would compile them. This is a significant advantage.
On the plus side, my custom parser will be done really quite soon. I've been working on the expression handling and I finally managed to express them in such a way that Visual Studio would compile them. This is a significant advantage.
Wednesday, 16 November 2011
My Parser
My parser is so awesome, Visual C++ can't compile it. It gives back a nice Internal Compiler Error :(
Oh wait, that's true of nearly *every* awesome program.
Oh wait, that's true of nearly *every* awesome program.
Tuesday, 8 November 2011
Exist
I do still exist! I am currently working on the first implementation. After the funcakes I had with Bison, you can fully expect that I've been working on the custom parser. My custom lexer is nice and high quality thanks to the fact that I ended up re-writing it about six billion times. At least when my parser throws an exception, I will have nice high quality error messages. That's my end goal, anyway.
Now, for a custom parser, I am obviously going to do the horrendously efficient thing and work without an explicit stack. I am going to instead simply increment/decrement the current element pointer through an existing vector. This should permit a ridiculously small performance improvement for a 1billion times increase in development time.
Seriously though, I just find it more natural.
Now, for a custom parser, I am obviously going to do the horrendously efficient thing and work without an explicit stack. I am going to instead simply increment/decrement the current element pointer through an existing vector. This should permit a ridiculously small performance improvement for a 1billion times increase in development time.
Seriously though, I just find it more natural.
Subscribe to:
Posts (Atom)