Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Discussion / proposal: usage of any installed programming language #211

Open
ghost opened this issue Dec 1, 2017 · 94 comments
Open

Discussion / proposal: usage of any installed programming language #211

ghost opened this issue Dec 1, 2017 · 94 comments

Comments

@ghost
Copy link

ghost commented Dec 1, 2017

As @TrendyTim mentioned in #46:

Public Class TestClass
    Private vbVar as String
#Language CS
    public static void Main()
    {
        bVar = "From C#";
        MoreVBCode();
    }
#End Language
    Sub MoreVBCode()
    End Sub
End Class

I think this would be a very nice construct to use the language of choice (for us here VB) and still be able to use any installed language in the cases where another language better fits the job without resorting to different projects in different languages.

Syntax as proposed by @TrendyTim
#Language CS
#Language C
#Language C++
#Language F#
#Language IL
etc, any installed language should be usable.

Implementation: The #language/#End Language functions should be compiled into a separate assembly using the specific language compiler.

ADDED
In the example above, the call to MoreVBCode would cause a circular reference; The main VB assembly references the C# assembly where Main is defined, and this function needs a reference to the main VB assembly.
To fix this, the call to MoreVBCode should be implemented as a delegate,Invoke.
In the generated C# code, all references needed in the VB Assembly must be available in the generated function call.

The c# function above would get the following signature:
void TestClass_Main(Delegate MoreVBCode, out string vbVar);

@TrendyTim
Copy link

I’m glad you like the idea, although it would be problematic to compile to separate assemblies, as you would lose access to the private members without using reflection (unless the compiler can sneak around that limitation)

As nice as that syntax is, and how powerful it could be, now I think about it, I’m not sure how one could solve the issue of cyclic dependency if the VB code needs the c# code and the c# needs the vb code how would it be able to reconcile it. Maybe someone a lot smarter than me would know a way, but I am far from qualified for that, just the thought of it make my brain meltdown..

@ghost
Copy link
Author

ghost commented Dec 1, 2017

@TrendyTim
Just added that part.

@ghost
Copy link
Author

ghost commented Dec 1, 2017

AS I think of it, the out string vbVar would not work, bacause it updates the var after the call to MoreVBCode.

So it should be implemented as "fieldInfo vbVar" and updated using reflection.

@Bill-McC
Copy link

Bill-McC commented Dec 1, 2017

When you consider compiler directives, imports/using statements, etc, partial classes and one language per partial class code file is probably more functional.

@ghost
Copy link
Author

ghost commented Dec 1, 2017

@Bill-McC
I think the inline idea is much more readable then a separate project.
Also, a separate project could be overkill (in form of maintainability) when you have to create a complete C# project for one or 2 functions.

@TrendyTim
I implemented your idea:

VBCode:

'In VB project: MultiProgrammingLanguageTest
Public Class TestClass
    Private vbVar as String = "From VB"
#Language CS
    public void Main()
    {
       string CsString ="From C#";
        vbVar =CsString ;
        MoreVBCode();
    }
#End Language
    Sub MoreVBCode()
        Msgbox(vbVar)
    End Sub
End Class

The following CS code is generated:

//Auto created CS Project: CSMultiProgrammingLanguageTest

//Auto generated code:
using System.Reflection;

namespace CSMultiProgrammingLanguage
{
    public class TestClass
    {
        //Every field referenced in the VB Code gets a getter and a setter.
        static void SetvbVar(object Instance, FieldInfo vbVar, string value)
        {
            vbVar.SetValue(Instance, value);
        }
        static string GetbVar(object Instance, FieldInfo vbVar)
        {
            return (string)vbVar.GetValue(Instance);
        }

        //a delegate for every VB function that is called
        public delegate void Action();
       //instance and fieldinfo for every instance and field that is used, delegate for every call made
        public static void CSMain(object Instance, FieldInfo vbVar, Action MoreVBCode)
        {
            string CsString ="From C#"; //plain CS, not converted
            SetbvVar(Instance, vbVar, CsString); //var= value is converted because var is a VB var
            MoreVBCode.DynamicInvoke(); //VB Function call is converted to an invoke
        }
    }
}

The CS code in the VB file is converted to the following generated code:

    'Reference to the generated CSMultiProgrammingLanguage is automatic added
    Public Sub Main()
        CSMultiProgrammingLanguage.TestClass.CSMain(Me, Me.GetType.GetField("vbVar", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance), AddressOf MoreVBCode)
    End Sub

A call to (new Test).Main() now shows a messagebox with the text "From C#"

@Bill-McC
Copy link

Bill-McC commented Dec 1, 2017 via email

@ghost
Copy link
Author

ghost commented Dec 1, 2017

@Bill-McC
I can live with that, but that takes a second change; multi-language projects.
And I do not think that will be easy given the differences in the project files, especially with languages as C++ combined with languages as VB.

@Bill-McC
Copy link

Bill-McC commented Dec 1, 2017 via email

@ghost
Copy link
Author

ghost commented Dec 1, 2017

Either way is acceptable for me, inline or language by code file (I would prefer the possibility to use both).

The bottom line is that I think we should be able to mix the capability several languages, to be able to use the right language for the right job; for example using unsafe methods in C#, functional programming in F# and that all while building the bulk code in VB.

@paul1956
Copy link

paul1956 commented Dec 2, 2017

I love the idea of mixing languages in a project, I don't need in a file. Virtually every real VB project I work on has a C# Project to handle some Unsafe Code. Maybe Span(Of T) someday will fix this. Today VSIX projects seem to be able to compile C++ code in the vsct file. One specific example is the Hash Class from Roslyn, which I need to use in one of my refactoring's and it is marked Friend. It is extremely difficult to if not impossible to implement in VB. So I had to create a project, rename the namespace and class to avoid conflicts, and track changes in the Roslyn version, all extra work.

@TrendyTim
Copy link

@tverweij Not bad, it probably comes at a little performance hit, but generally its probably not going to be a big deal, would still be nice if it could be in the same assembly for lower overhead/ and fewer files for deployment (perhaps if it did an IL merge or something). Its not quite as nice as just compiling each block to IL and having it render out one class in IL that came from two languages (if thats even remotely possible), but it gets the job done.

@Bill-McC Both methods have their pros and cons the biggest pro of inline is you don't have to context switch, if it was in a separate file and we could do partials have to ensure case sensitivity of class names and translate the access modifiers correctly which may be a little tricky for people not well versed in both languages to keep them in sync, if partials weren't supported its another helper class that's required, and you lose easy access to private members.

If you have C# files in the project you might end up with some confusing assumptions like folders in c# give you automatic namespaces (something i WISH vb .net did, the number of times i forget to add namespaces because of that (even though i do almost all my work in VB i suppose i live in denial that C# has a lazy programmer feature that VB doesn't). You also have the context switch of going to another file to work on the same class and you may also find yourself going back and forth a lot.

Sometimes i want to have one method in C# because it offers features that for some reason VB doesnt (like dynamic types or unsafe code, but only wanted it in one method, other times a whole file might be useful to be in C# like back when webapi was almost impossible to use in vb)

So long story short, both would be awesome, and technically if inline was done, separate files would be as well by association (just that it could allow for the default language from the file type). Though i image a new project type would be required to be able to configure language specific options (but hopefully most things can be unified, C# projects have some things that would be nice in VB projs and vice versa if i recall)

Either way i would still be a happy camper, and all .Net languages could work together in perfect harmony.

@AdamSpeight2008
Copy link
Contributor

@tverweij There is an implicit assumption here that #Language ... and #End Language means the same across all languages, that could be untrue.

@TrendyTim
Copy link

TrendyTim commented Dec 2, 2017

Actually how’s this, a combination of both methods, building off of what @tverweij did, what if when support for multiple language files in same project is added, the #Language directive region generates a language file of the same name but that language ext (either virtually, temporarily or as a “subordinate” file like the .designer files, perhaps as filename.generated.cs or filename.mixedlang.cs).

If the language directive is inside a class it could automatically generate the partial class (and any needed namespace) as appropriate (also means to enable #Language inside a class you need to make it partial).

If it’s outside a class it just “moves it” verbatim though ensuring the namespace (assuming one would want to support that modality).

Any imports/using would need to get converted into the auto generated file as well and of course I don’t think supporting it inside a method is valid (nor modules because you can’t have partial modules as far as I know).

That way we get best of both worlds, with little extra work.

Edit: just to clarify that’s not to say that anyone can’t add te other language file themselves, this would just builds on that as an added ease of use. But as i said before it would be nice but not necessary for inline, I’d take what I can get.

@AdamSpeight2008 not really, here #Language is assumingly talking about vb, it can of course be whatever the default language (ie file type) defines it to be, c# or f# may just want is as #lang VB

@AnthonyDGreen
Copy link
Contributor

Why do people hate managing two projects and two DLLs so badly?

@AdamSpeight2008
Copy link
Contributor

@TrendyTim #Language CS would switch the parsing in be parse as CSharp, so the #End Language also has be parsed in C# not VB. Thus has to able to be parse in all languages.

@TrendyTim
Copy link

@AnthonyDGreen I guess if you don’t hate already you won’t understand, seems overkill to add a new assembly for 30lines of code.

@AdamSpeight2008 I’m not so sure that’s true, as the default language of the file (in this case VB) is what parses the directives and would extract the whole C# block and C# would never see that directive (start or end)

@Bill-McC
Copy link

Bill-McC commented Dec 2, 2017 via email

@paul1956
Copy link

paul1956 commented Dec 3, 2017

@AnthonyDGreen try recreating Hash from Roslyn in VB and you will see the frustration. There are Namespace issues that I don't know how to solve, name conflicts, Unsafe Code, private functions.., The code is marked Friend so I can't access it directly from my project (why it isn't public is another question because it is called from all over Roslyn and many thing can't be easy implemented without it). It seems that VB integration keeps getting 99% of the way there and a minor issue breaks everything (and I am forced into C#) being able to do this at least gives an easy workaround.

@ghost
Copy link
Author

ghost commented Dec 4, 2017

@AnthonyDGreen wrote;

Why do people hate managing two projects and two DLLs so badly?

It's all about manageability and readability. A complete project for one or two methods is overkill.
It would be less necessary if VB supported pointers, unsafe code and if it was supported for all new technologies. But because VB became a second class language, we regularly have to use c# code.

@ghost
Copy link
Author

ghost commented Dec 4, 2017

Offtopic: @paul1956

The code is marked Friend so I can't access it directly from my project (why it isn't public is another question because it is called from all over Roslyn and many thing can't be easy implemented without it).

Just use reflection for it - solves all those problems; I have standard CallMethod, SetProperty, GetProperty, SetField and Getfield methods to get around all unnecessary encapsulation (the .Net framework is full of it).

@reduckted
Copy link
Contributor

Just use reflection for it

Only if you don't care about performance.

being able to do this at least gives an easy workaround.

Once this is implemented, yes, it might be an "easy" workaround. But actually implementing the ability to use multiple languages in one project is a long way from being simple. This would be an enormously complex feature that Roslyn doesn't really seem built to support.

@ghost
Copy link
Author

ghost commented Dec 4, 2017

@reduckted
I care about productivity; getting things done - that's why I used VB for the last 20 years.
If I really cared about performance, I would code in C or C++ (as I did before).

@Bill-McC
Copy link

Bill-McC commented Dec 4, 2017

I must have missed something. How is resorting to reflection, dealing with various security implications more productive than just having the code there in thge language it was written?
Productivity to me is if I find a routine, a small framework, a utility method, being able to use it with as little fuss as possible.

@ghost
Copy link
Author

ghost commented Dec 4, 2017

@Bill-McC
What I meant is that if you can solve a problem by simply calling a friend function in another assembly - the I prefer this over rebuilding the needed functionality (which would execute faster).

But all of this is off-topic.

The topic is the wish of having multi- language support in one project.
@reduckted
I understand fully that this is not an easy task to do.
But I do not think that mankind would ever accomplish anything if we don't do it simply because it is difficult to do.

@rskar-git
Copy link

@AnthonyDGreen asks: "Why do people hate managing two projects and two DLLs so badly?"

This is not about hating on multi-project solutions. It's about being forced into the use of a DLL as a work-around for what should be a trivial matter if only the language of choice was able to achieve the desired effect (efficiently) on its own.

At that point where one is forced into another DLL, one must be resigned to making various somethings Public (so that your main assembly can make use of the now-necessary satellite DLL) that you otherwise would prefer not to, and the possibility of missing out on whatever optimizations the compiler might have done if all the desired functionality was in the same assembly.

Probably the top two frustrations on this front are: (1) mixed use of checked and unchecked integer arithmetic; and (2) access/usage of C# libraries when there are issues of case-sensitivity and method signatures. I'd bet if these two items were (thoroughly) addressed, this idea of multi-language DLL-free mix-ins would be so less compelling.

But, for the record, if there was a way found to knit another language into a VB project, the only one I'd care about would be F#.

@AdamSpeight2008
Copy link
Contributor

AdamSpeight2008 commented Dec 4, 2017

@rskar-git / @tverweij My point is this how do you work out which is the correct #End Language to end at?

'In VB project: MultiProgrammingLanguageTest
Public Class TestClass
    Private vbVar as String = "From VB"
#Language CS
    public void Main()
    {
       string CsString ="
#If foo_enable Them
#End Language
#EndIf
";
        vbVar =CsString ;
        MoreVBCode();
    }
#End Language
    Sub MoreVBCode()
        Msgbox(vbVar)
    End Sub
End Class

Also what about #If and #Endif cross language?

@TrendyTim
Copy link

@AdamSpeight2008 that’s the easy part, the same way #if and #region work the directives have to be at the start of the line. To prevent any cross language parsing issues I’d assume you can’t have nested #language directives, I think a .net terducken (turkey stuffed with a duck stuffed with a chicken) would be going too far anyway, 2 levels would be fine if you ask me.

@AdamSpeight2008
Copy link
Contributor

@TrendyTim Easy? Are you sure? I've updated the example.

@TrendyTim
Copy link

@AdamSpeight2008 Ok good point, frankly I’d be happy to concede that limitation that I can’t start a line with a #End Langauge as part of a multi line string in the foreign language as an inline block (need to use foreign language file for that if it’s that important)

Maybe at some point the feature could advance enough to support it (like having the foreign parser communicating back to the host language parser) but that is an extreme corner case, and I can’t imagine many people complaining they can’t do that, so it really worth the effort, unless someone has a genius and yet simple idea)

@paul1956
Copy link

paul1956 commented Dec 5, 2017

@TrendyTim how about we just get project to work first and then file then worry about nested, because I am sure I will be 100% retired before then and I think mixed projects solves 99% of the issues. I am surprised that with the new project system more wasn't done to enable mixed languages.

@ocdtrekkie
Copy link

ocdtrekkie commented Feb 7, 2018

@bandleader Speaking for myself: Yes. I use Telerik's converter quite often, because I want to use code samples or libraries documented solely in C#. An example is Quartz.NET, an excellent package. I used Telerik's site to convert their sample code into something I could work with in VB. There were some hiccups but it saved me a lot of frustration and time dealing with C#, which I am... fairly rusty at interpreting.

Quartz.NET's Quick Start: https://www.quartz-scheduler.net/documentation/quartz-3.x/quick-start.html

My savior: http://converter.telerik.com/

@Bill-McC
Copy link

Bill-McC commented Feb 7, 2018

@ocdtrekkie I've found the problems with that translation approach are there are often bits that don't get translated properly, so a fair bit of time has to be spent testing the translation and fixing parts. It's not just plug in and go. And the second part is when the libraries get updated you have to go through step 1 all over again.. and that can add up to days of lost work really quickly.

@bandleader
Copy link

@ocdtrekkie @rskar-git It's very interesting to hear that some VB users use a C# translator on a regular basis! Hard for me to relate, but I guess we're not all the same after all! 😃
@ocdtrekkie If it helps you, I believe this translator works much better.

@gafter Step 3 is where much of the complexity of the compilers reside. We'd have to revise many of the internal and external APIs such as INamedTypeSymbol..GetMembers(string name), since it has to be case-sensitive when handling C# source code, and case-insensitive when handling VB source code. Since the compilers (name lookup in particular) are built on these APIs, it would all need to be rewritten.

I had assumed so, unfortunately. (In my compiler design, this is done in one place.) However, instead of re-implementing everything, couldn't you just make the GetMembers implementation(s) search two ASTs instead of just one?

@ocdtrekkie
Copy link

@Bill-McC I definitely usually have something to fix coming off the translator, but it's a lot better than starting from scratch.

@bandleader Will give it a try next time!

@gafter
Copy link
Member

gafter commented Feb 8, 2018

We would love if you/the rest of the Roslyn team could have your own brainstorming sessions and, with your knowledge of the compiler internals, figure out a way to do this -- whether within Roslyn or otherwise.

That is exactly what we did at the inception of the Roslyn project way back in 2009. We took this very question as one of the key design points that had to be decided right at the start of the Roslyn project, because it has an immense impact on the shape of the compiler internals. We thought about it over the course of a few weeks and discussed it in meetings for hours. In the end we decided not to do it because it would have added a large implementation cost (and uncertainty of success) to the project. The Roslyn code base was written under the assumption that we would not be mixing languages within a single project.

However, instead of re-implementing everything, couldn't you just make the GetMembers implementation(s) search two ASTs instead of just one?

The INamedTypeSymbol.GetMembers(string name) does not "search" any syntax trees. It acts upon the symbol table and returns results that have already been computed for the members of the containing type. But that answer would be wrong for either C# or VB due to case mapping; an API like INamedTypeSymbol.GetMembers(string name) would not be correct for a "merged" compiler; it would require an extra parameter telling whether or not to case map (or two different entry points, one which does case mapping and one that does not).

@rskar-git
Copy link

@bandleader I've personally not made much use of translators; my C# knowlege is pretty good, and hand-coding C# examples into VB is something I consider as part of my own self-education.

There are others who want to do things in VB, and don't know much C#, yet are eager to learn new things and get going with their own VB coding. Since so many .NET examples are done in C#, they make use of translators to get VB examples. This came to my attention via StackOverflow (e.g. https://stackoverflow.com/questions/45552216/bitcoin-blockchain-parser-c-sharp-snippet-to-vb/).

My own hand-coding efforts involve maybe a few pages or less of code. However, if it were my job to regularly transform C# code into VB, you can be assured that I would be using a translator a lot then.

...newer code designers are emitting C# directly (instead of using CodeDOM)...

That would mean that they translate their C# project templates using a translator. I can't really see them doing that.

...as regards the C# emitter problem...

They probably wouldn't necessarily do the translations themselves, but a lot of these open source projects do welcome volunteers. I'd bet a VB'er who also knows C# could refactor the emitter issue; and utilizing a translator, quickly churn out VB templates. There are only two pain-points I can see here. The first (where they haven't a care or concern for the Common Language Specification) is employing some sort of case-sensitive naming scheme to their public and protected identifiers. But then that could be addressed by giving VB a way around that (perhaps with square brackets and @? e.g. C# protected foo and public Foo can be distinguished in VB as [@foo] and [@Foo]? - just to throw out an idea). The second is commingled checked/unchecked integer ops. All the rest - such as operators not in VB, and unsafe code - may be addressed via extending the library/framework and refactoring.

I don't know what to say about closed source and commercial projects, or the apparent wavering at MS. But I wouldn't hang hopes on MS embarking on this multi-language mix-in.

@KathleenDollard
Copy link
Contributor

This is a hard discussion.

I believe the decisions made at the start of the Roslyn project were not only to help ensure the success of Roslyn, but also to ensure that VB could implement the things best for VB (and C#) in the future, because that was the language strategy of the day.

It's easy to forget how amazing the Roslyn conversion was - they switched out our compiler and we barely noticed - from an incomprehensible one.

We spent more time discussing mixed language in yesterday's VBLDM. We looked around the issue again - which has been looked at many times - and we have no reason to think the previous assessment (summarized by @gafter ) has or will change.

I'm going to leave this open for now for clarification on this specific issue. But I would like to shift conversation to doable things that can provide value to VB developers - including some of the mitigating features discussed in this thread. Things blocking C# interop, wider understanding of "InternalsVisibleTo" and patterns to avoid circularity when projects are used to isolate languages are all discussions that may bear useful fruit. I anticipate closing it as "won't fix" in a few weeks. If something changes, we'll start over.

Most are all of the folks on the language team, including myself, wish this were different, but it just isn't a feasible change.

@ocdtrekkie
Copy link

@rskar-git In the above Quartz.NET example, I did offer that if they added a tabbed code preview to their website, like Microsoft's docs, I'd be happy to contribute working VB sample code.

@TrendyTim
Copy link

@KathleenDollard That is bittersweet, its upsetting we will never get a nice unified language, but hopefully the fact that we want it so much will help drive VB to being more respected by the .net team.

I know complete language parity will also never happen, but perhaps

  • If some of the classes in the framework were not needlessly private (perhaps just hidden from intellisense) as was mentioned somewhere it required decompilation but was not innately VB compatible.

  • Maybe support Unsafe code (maybe poll for it, i've managed to avoid it but some may need it)

  • When new things are released support VB properly (i remember i think it was when ASP.net MVC or WebAPI was released it was either not supported by VB or it was a painful kludge because the extension methods didn't work correctly under VB. Also VB was a late comer to .Net Core, this delays uptake for us, perhaps changing direction of entire projects)

  • Don't be afraid to muddy the syntax a bit, steal some niceties from C# at the expense of tradition, like how C# can have () => for shorthand anonymous methods in particular for use in lambdas and (type)variable casting instead of having to ctype/directcast, forcing us to use modules instead of shared classes (modules can pollute intellisense when their namespace is imported), and support automatic namespacing for folders like C# (this would have to be added at the project level and at the folder level for compatibility). Whilst i can read VB 5x faster than C# and write it 10x faster (im sure i could speed up my C# if i spent the time on it) but still prefer VB despite the 2nd class citizen status. I know this thread isnt the place to request those but they are the partly to blame for us wanting to write C# snippits without needing a whole assembly to do it.

@Bill-McC
Copy link

Bill-McC commented Feb 9, 2018

@KathleenDollard ; @gafter . If the only issue is case sensitivity, would an option to make VB case sensitive address that hurdle?

@gafter
Copy link
Member

gafter commented Feb 9, 2018

That is not the only issue, only the easiest to explain.

@AdamSpeight2008
Copy link
Contributor

Case Insensitive removes a lot of potential sources of bugs and errors.

@gafter
Copy link
Member

gafter commented Feb 9, 2018

@AdamSpeight2008 Can you please elaborate on that? What class of program errors are removed by case insensitive?

@AdamSpeight2008
Copy link
Contributor

User-ability problems, I'm dyslexic, so spelling can be a bit a chore, add in case-sensibility into the mix that my productivity down the drain. Imagine an identifier with my username it us 15 characters, or 1 in 32768 chance of picking the right one with case sensitivity, each time I need to type it. Case Insensitivity make it virtually certain I get the write one.

@rskar-git
Copy link

@AdamSpeight2008 @gafter More food-for-thought at https://blog.codinghorror.com/the-case-for-case-insensitivity/, http://lambda-the-ultimate.org/node/1114, https://softwareengineering.stackexchange.com/questions/9965/why-is-there-still-case-sensitivity-in-some-programming-languages.

I'm OK with either, and can see the advantages and challenges to both.

In VB, I'd like to see:

(1) A compiler option to enable/disable case-sensitivity for the entire project. This would affect how references into libraries work too.

(2) A syntax (particularly for when case-insensitivity is the mode) that indicates a case-sensitive match (I had suggested something like [@foo] [@Foo], but whatever).

@Bill-McC
Copy link

@gafter what are the other issues?
Are there any notes from the meetings you have that have looked at this in detail, and that you can share with the VB community ?

@gafter
Copy link
Member

gafter commented Feb 10, 2018

Are there any notes from the meetings you have that have looked at this in detail, and that you can share with the VB community ?

@Bill-McC Even if I could locate them, I cannot share meeting notes from inside a private company (that were not undertaken as part of an open-source project at the time) without extensive review and legal clearance. I'm not motivated to devote a couple of months and lawyers to answering this question.

what are the other issues?

I cannot enumerate all of the other issues without doing the design work. But just to give you some idea: since we're writing a single compiler for both languages, we'd have to pick an implementation language, as we cannot implement it using mixed languages (if we did there would be no way for us to compile the new compiler). So we'd have to start by throwing away all of the VB code implementing the VB compiler. Also, all of the symbol table implementation code would have to be revised from scratch to have support for the semantics of both C# and VB. Instead of each type containing a single map from name to the members of that name, there would have to be two maps (one case-mapped, and one not). There are other things that are needed on one side or the other, but the result of this is that the symbol table would be significantly larger than it is today, even if you're only compiling one language. That means the compiler would consume more memory and be slower than it is today. Also, since the symbol table API is being overhauled, all of its implementation would need to be overhauled as well, as well as anything that uses it (i.e. most of the compiler).

This could be done with a couple of years and the current compiler team devoted to the project. We'd have to stop adding any compiler or language features during this time because (a) we need the engineers doing this so it doesn't take longer, and (b) any new features would have to be added to both the existing Roslyn compiler and this new Roslyn2 compiler.

So the question is: does this "feature" rise so high in value that we'd be willing to delay everything else by 2-3 years, and are we willing to slow down the compiler by 20% to accomplish it? Are we willing to have the VB compiler fully written in C# so that Roslyn2 can be compiled the first time by an existing compiler? Are we willing to have the compiler team less invested in VB by virtue of no longer using it in their day-to-day work?

Those are some of the considerations, and on balance we decided it wasn't worth it.

@Bill-McC
Copy link

@gafter okay I give up. Looks like this isn't going anywhere even if it is feasible. Regards the symbol table being twice the size, does not make sense to me if one of the constraints was VB was to forgo case insensitivity.
I also still don't get why you say there has to be one compiler, I would have had thought it could be merged post compile.
Anyway, this seems as fruitless as asking for full support for VB .

@bandleader
Copy link

@gafter does this "feature" rise so high in value [...]

If indeed it requires a major rewrite and the 2-3 years you estimate -- of course not. But assuming we do find a more viable way to do this (which is the goal of this thread) please also make sure you consider the following.

  1. I am not sure that the metric of VB Razor not being used is sufficient proof that VB sees little use outside its main domain. Isn't in MS's best interest to do a bit more research? (Not to mention -- could they engage more with the VB community to help them become more invested in new technologies such as Core and Xamarin?)
  2. Also, the flipside -- not finding a way to do this -- is basically forcing MS to invest more on having each of these new platforms/project types support VB directly (or else, shut out VB users from the new platforms).
  3. Also, consider that this is not just for VB users, but for every other .NET language -- F# and any others. (I think this is very significant in 2018; more about this later.)

since we're writing a single compiler for both languages, we'd have to pick an implementation language, as we cannot implement it using mixed languages (if we did there would be no way for us to compile the new compiler). So we'd have to start by throwing away all of the VB code implementing the VB compiler.

  1. Roslyn is already written in two languages today, and compiles fine (using separate assemblies IIUC). I wouldn't think anything would have to change there.
  2. Correct me if I'm wrong, but even the existing VB/C# parsers wouldn't have to be changed at all. The part that has to change is what I believe MS calls the "binder" (symbols to declarations), and related table lookup code.
  3. I understand from you that VB's case insensitivity presents a major problem. The truth is that when mixing VB code into a C# project, the user can easily forego this, since this is essentially a C# project with VB code files mixed in. Consider also that it is rare for this to be a problem practically, because even in pure C#, the Intellisense popup corrects case.
  4. If case-insensitive symbol lookup is nevertheless required, it seems (to me) easy enough to generate a case-insensitive symbol table that points to same results (maps) as the main one. Added memory consumption would therefore be minimal. (Not that vbc uses much anyway...) Even this would only be required when mixed code requires it, so no performance loss in "regular" C# projects. (It can be lazily loaded, as plenty of Roslyn is already IIUC.)

Let me just be clear and say that I'm not trying to preach to the hardworking Roslyn team, nor demand PR explanations of "Explain why you can't do this!" I just want to make sure this idea is not abandoned for lack of thought or fleshing it out with the right amount of mindpower. (As a project leader, many a time I've thought "we could never implement feature X," and then after a comment by someone -- sometimes even a nontechnical client! -- I'd realize that it is not only possible but the right way to go.)

I would be very glad if other members of the Roslyn team could chime in with their thoughts, and/or brainstorm other ways we could accomplish what we're looking to do. Thanks! @KathleenDollard

@KathleenDollard
Copy link
Contributor

We talked about this in last week's LDM (I know, I do not have a streamlined way to do notes, they aren't up, that's a problem, I get that). These folks have been thinking about these problems for years, and agree that if it was free, it might be desirable.

I say might, because if it was suddenly free, we would then have a very long discussion of a few key issues. It isn't that case sensitivity is an issue in a few places, unless we have a third compiler, it's that every VB project would have to be considered. Symbols being evaluated differently in two scenarios would be bad, and worse in VB if Option Strict is off (runtime or logic errors, not compiler errors),

Then, we'd come to the resulting Frankenstein. Whose overloads rules would win? Will VB have C# impact interfaces in that context? There are hundreds or thousands of small differences between the two, created via 2 decades of independent development. The result would either not really be VB or not really be C#.

If we could do this, we could create translators. All the problems with translators would be happening in your compiler.

I hope we can soon put our conversations into things that can improve VB itself.

@gafter
Copy link
Member

gafter commented Feb 12, 2018

Roslyn is already written in two languages today, and compiles fine (using separate assemblies IIUC). I wouldn't think anything would have to change there.

The dependencies between assemblies is one-way only. In the hypothetical two-language compiler, declaration binding has to handle declarations in two languages, which means binding a C# declaration has to perform binding of VB symbols as a subroutine (to bind types that we can then look up) and vice versa. It is problematic to organize code across assemblies in which recursion needs to happen in both directions between assemblies. Could we build firewalls between the language implementations using interfaces? Possibly, but at the expense of making a huge number of compiler-internal APIs public and paying a performance penalty. Could we hide those interfaces in a private assembly? Possibly, but we'd be shipping a fair number of separate assemblies to do this. Shims in cross-language scenarios don't work well because the symbol table is immutable and contains cycles. Even if we could do all these things, the symbol table (and all of its clients) would have to be overhauled, and that is a huge fraction of Roslyn. I'm not saying it cannot be done. I'm saying the price is high.

I agree that the parsers can be kept in separate languages. Same thing for lowering and emit, and binding executable code. But they'd have to be overhauled because of symbol table API changes.

I agree that we could reduce memory requirements in non-mixed-language environments by having C#-specific, VB-specific, and mixed language implementations. However, that would be a huge amount of duplicated code and a support nightmare. No, we cannot share common code through base classes because none of the .NET languages support multiple inheritance. Could we use the "default interface implementation" feature to get the effect of multiple-inheritance to make this easier? Sure, if and when that becomes widely available on .Net platforms, but we'd stiff pay the interface performance penalty.

Case-insensitive is required for VB code for compatibility. We're not going to break compatibility, so it is a hard requirement, even for "VB code in a C# project". I don't see any reason to distinguish VB and C# projects in this hypothetical world.

@bandleader
Copy link

bandleader commented Feb 20, 2018

Found this (albeit a bit more general) in Roslyn: dotnet/roslyn#13735
And then moved to csharplang: dotnet/csharplang#226
(I read recently that things common to both languages could/should be discussed on csharplang anyway)

@ghost ghost closed this as completed Mar 6, 2018
@KathleenDollard
Copy link
Contributor

I am reopening this because I do not want to end an active conversation because the original poster chose to exit and closed on their way out.

While I am very skeptical that this could ever be done, the conversation should not be squashed.

@paul1956
Copy link

paul1956 commented Mar 7, 2018

I can't find the reference (on GitHub) right now but the idea to use the C# scripting engine so VB can execute C# code inline is promising. It may not be fast but in the posted sample example it did work. I have not does extensive work on this solution but if it could be generalized I think it would address a large number of use cases and currently it is less than a page of code. Right now it looks to me like a new script would have to be generate for each usage and that is better suited to the compiler. That said it is more important to me for VB to get missing native functionality, and I will deal with a few modules of C# code to maintain.

@tverweij
Copy link

Solved in project Mercury

@TrendyTim
Copy link

@tverweij
It was solved in the first human spaceflight program of the United States back in 1958 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests