dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
18.98k stars 4.03k forks source link

Interactive Design Meeting Notes - 1/23/15 #122

Closed kuhlenh closed 9 years ago

kuhlenh commented 9 years ago

Interactive Design Meeting Notes - 1/23/15

Definitions

The following individuals are members of the dream team: Anthony D. Green Chuck Stoner Dustin Campbell Kasey Uhlenhuth Kevin Halverson Kevin Pilch-Bisson Lincoln Atkinson Manish Jayaswal Matt Warren Tomas Matousek

Special Guests: Mads Torgersen Neal Gafter

About the Design Process

We meet for 2 hours a week to sketch final designs and experiences for Interactive. It is usually up to Kasey to determine the topic for discussion.

Meeting notes will be shared publicly on the dotnet/roslyn GitHub so that the community can respond and give input on our thoughts. Notes will be posted as issues thus allowing the community to comment on the thread. We will take comments into consideration for the next meeting.

Ultimately, the Interactive Design team is still in charge of the interactive intiative. This is not a democratic process; the team will make the final decisions. That said, we will look at UserVoice, comments on notes, and feature requests.


Agenda: Interactive Language Semantics

Happy New Year! This meeting focused on design-time language semantics and experiences for the REPL and Scripting.

LANGUAGE FEATURES

Note: The REPL and scripts contain top-level code. This means a user should feel like he/she is typing at the namespace, class, and/or method-body level.

  • Async/await:
  • REPL: We determined to always use “await” as a keyword. In the scenario “await x; await y;” it is confusing to determine if this is happening concurrently.
  • Solution: We will block the execution thread until the await returns (the user can still scroll but will not get the next prompt. AKA the REPL will not take any more input until the await is complete).
  • Scripting: We considered having scripts always be in the async context. We also considered making async/await illegal in scripts or only allowing it outside the top-level.
  • Solution: Because the REPL uses the Scripting API, we have to support async/await everywhere.
  • Other recent language features: There should be no special circumstances for the use of string interpolation, null-conditional operators, index intializers, exception filters, expression-bodied function members, using static, and other C# 6.0 language features.

    OTHER FEATURES

  • Variables/fields: We will allow top-level fields in the REPL and scripts. Static variables WILL NOT be allowed. Read-only variables WILL be allowed.
  • Hiding/shadowing definitions: The following code snippet (in a C# REPL) demonstrates definition shadowing. The latter definition of x "hides" the previous one but does not replace previous instances.
    c#> int x = 4;
    c#> int y = x+3;
    c#> y
    7
    c#> int x = 5;
    c#> y
    7
    c#> x
    5
    
  • New Directives:
  • #r : Allows a developer to reference a .dll or NuGet package
  • #load : Allows a developer to set context with source or script files. It essentially acts as if the developer copy/pasted the file into the script or REPL session. Order for #loads is critical in script files because of their linear execution.

Note: A developer will not be allowed to #load a .cs file because we do not allow namespaces in Interactive semantics. If we have time, we can write an API to allow this functionality.

  • #r! : Allows a developer to reference a .dll with access to its internals.

Problem: We believe developers should be able to load a .dll with access to internals (this is how you can “seed from a project”). Top scenarios for “seeding” are writing a unit test script and testing/interacting with a project in the REPL. However, we believe only some .dlls should be accepted by the host. A developer should only be able to load a .dll with internal access on personal projects (there are no scenarios that we want this support for that do not involve the user’s source). TODO: Write a proposal for a policy for when our host will load a .dll with internals

Next time we will discuss incorporating F# directives: #l (adds “some path” to assembly and script resolution search path) and #time (turns on simple perf stats--Real, CPU, GC--for each evaluated command)

RichiCoder1 commented 9 years ago

It might be worth looking @ cake-build/cake to see an example of C# scripts in the wild.

glennblock commented 9 years ago

Great to see this! Loving the openness, and we're really excited to see the scripting APIs back under development and as OSS! We're anxiously ready to get scriptcs to use this.....

Can I assume these apply to both inside and outside of the REPL?

async/await

One word, YES!!!. Having the script run in an async context, or at least a way to trigger this would be really useful. For example imagine I am using HttpClient, it would be really nice if I can just do

var client = new HttpClient();
var response = await client.GetAsync(...);

As so many of the framework libs have moved to async, this becomes very practical imo.

r packages

I see you have #r adding support for NuGet packages. How will this work?

Having inline specification for packages will be really useful. It would be nice though it it also supported externalizing the dependencies i.e. like in packages.config or packages.json. Was this considered?

load

We need this outside the REPL as a general scripting feature. For script "programs" this is really needed. It would be great to see this support both relative and absolute paths with relative being to the executing script.

glennblock commented 9 years ago

Something else that would be really useful is to be able to define extension methods WITHIN script. We see this request commonly for scriptcs. You can load a binary with extensions, but no way to inline them in a script. I understand why as everything runs within the submission, but maybe there's a way to break outside of that somehow, or have code lifted at compile time to be an extension method.

tmat commented 9 years ago

The compiler doesn't actually do anything specific for #r's. It's all up to the host. The compiler asks the script host to resolve the string given in #r directive and expects back an array of MetadataReferences that are gonna be added to the compilation. It's up to the host to distinguish between a NuGet package name and a .dll name, find the library and get the metadata content.

All references are loaded at script compile time, just before the script code itself is compiled. At that point we need to load all metadata in order to bind identifiers in the source.

glennblock commented 9 years ago

@tmat Interesting, I did not know that. Is there a virtual method or something that the host implements? Or is this something that is handled through the AssemblyResolve event?

tmat commented 9 years ago

https://github.com/dotnet/roslyn/blob/master/src/Compilers/Core/Portable/MetadataReference/MetadataReferenceResolver.cs

It's probably not exposed via the hosting APIs yet.