Reference one RoslynPad script from another - roslynpad

What I'd like to do is reference one script from another.
One way to make this happen might be using assemblies. RoslynPad allows compiling a script into an assembly. Here is what I have tried so far.
Script A, which is compiled to SOME_PATH\thing.dll
class Thing
{
public string Name { get; set; }
}
Script B
#r "SOME_PATH\thing.dll"
using static Program;
var t = new Thing();
t.Name = "TEST";
t.Name.Dump();
This gives the error "The type or namespace 'Thing' could not be found..." so I tried the following.
#r "SOME_PATH\thing.dll"
var t = new Program.Thing();
t.Name = "TEST";
t.Name.Dump();
This gave the following error "The type name 'Thing' does not exist in the type 'Program'".
Is there a way to "Compile and Save assembly" and then reference it from another script? Or, is there a more direct way to cross reference between scripts?

What you're looking for is the #load directive:
#load "Path\To\ScriptA.csx"
var t = new Thing();
You can read more about the C# script variant in the Roslyn wiki. Note that not everything there is relevant to RoslynPad, which unlike the C# Interactive window, is not a REPL.

Related

TDirectory::GetFiles listing ignoring case on iOS (FMX, C++)

The code below lists files that have extension .cfg and it works fine on Win32. But, on iOS if i have a file that a user named with caps for the extension (e.g. test.CFG) then i miss it. I found this post using Delphi that might work using TDirectory::TFilterPredicate but i don't know how to implement in C++Builder.
TStringDynArray list;
TSearchOption searchOption;
UnicodeString DocsPath;
int lenDocsFolder;
DocsPath = System::Ioutils::TPath::GetDocumentsPath();
lenDocsFolder = DocsPath.Length();
searchOption = TSearchOption::soTopDirectoryOnly;
try
{
list = TDirectory::GetFiles(DocsPath, "*.cfg", searchOption);
}
catch (...)
{
ShowMessage("Incorrect path or search mask");
return;
}
I suppose i can just run a *.cfg block of code followed by a *.CFG but i'm hoping there is a cleaner approach.
Sorry, but I'm not used to C++. But this applies to both C++ and Delphi.
You are calling:
TDirectory.GetFiles(
const Path, SearchPattern: string;
const SearchOption: TSearchOption): TStringDynArray;
If you instead call this overloaded version:
TDirectory.GetFiles(
const Path, SearchPattern: string;
const SearchOption: TSearchOption;
const Predicate: TFilterPredicate): TStringDynArray;
you should be able to get what you need.
The TFilterPredicate type is defined as:
TFilterPredicate = reference to function(
const Path: string;
const SearchRec: TSearchRec): Boolean;
and should be the correct way to override the way files are matched.
I tried the Using a Lambda Expression from the link Remy posted in comment. I got an E2188 Expression syntaxerror until i disabled the classic Borland compiler. The code works great for simple predicate (on both Win32 and iOS).
String ext(".cfg");
files = TDirectory::GetFiles(CalcPath,
[ext](const String Path, const System::Sysutils::TSearchRec &SearchRec) -> bool
{
return ExtractFileExt(SearchRec.Name) == ext;
});
Now, how do i modify the extension string to return results for both .cfg and .CFG at same time?
String ext(".cfg"); // works fine
String ext(".cfg;.CFG"); // finds nothing

Alternate syntax on introspecting modules/classes/etc

I'm rewriting a framework from Perl5 to Perl6 for my work purposes. At some place I need to collect information from other modules/classes by executing a public sub they might provide; or they may not. So, it necessary to find out if the sub is present. This is not a big deal when a module is referenced directly (Foo::<&my-sub>) or by a symbolic name in a string (&::("Foo")::my-sub). But for the simplicity of it I would like to allow to pass module names as-is (lets say collector is the method collecting the info):
self.collector( Foo );
Where Foo could be the following:
module Foo {
use Bar;
use Baz;
our sub my-sub { Bar, 'Baz' }
}
And this is where I'm missing something important from Perl6 syntax because the following:
method collector ( $mod ) {
my $mod-name = $mod.WHO;
my #mods;
with &::($mod-name)::my-sub {
#mods.push: &$_();
}
}
is currently the only way I can perform the task.
I didn't try a type capture yet though. Should work as expected, I guess. So, the question is more about extending my knowelge of the syntax.
The final solution from the exchange with Vadim in the comments on their question. It's arguably insane. They think it's beautiful. And who am I to argue? .oO( Haha, hoho, heehee... )
my $pkg-arg = (Int, 'Int').pick;
my \pkg-sym = $pkg-arg && ::($pkg-arg);
my \sub-ref = &pkg-sym::($subname);
There are two obviously useful ways to refer to a package:
Its symbolic name. Int is the symbolic name of the Int class.
Its string name. 'Int' is the string name of the Int class.
Vadim, reasonably enough, wants a solution for both.
In the solution in this answer I simulate the two types of argument by randomly picking one and assigning it to $pkg-arg:
my $pkg-arg = (Int, 'Int').pick;
Now we need to normalize. If we've got a symbolic name we're good to go. But if it's a string name, we need to turn that into the symbolic name.
Vadim showed a couple ways to do this in the comments on their question. This solution uses a third option:
my \pkg-sym = $pkg-arg && ::($pkg-arg);
If $pkg-arg is a symbolic name, it'll be False. With a False LHS the && short-circuits and returns its LHS. If $pkg-arg is a string name, then the && will instead return its RHS, which is ::($pkg-arg) which is a symbol lookup using $pkg-arg as a string name.
The upshot is that pkg-sym ends up containing a package symbolic name (or a Failure if the lookup failed to find a matching symbolic name).
Which leaves the last line. That looks for a sub named $subname in the package pkg-sym:
my \sub-ref = &pkg-sym::($subname);
The & is needed to ensure the RHS is treated as a reference rather than as an attempt to call a routine. And pkg-sym has to be a sigilless identifier otherwise the code won't work.
At the end of these three lines of code sub-ref contains either a Failure or a reference to the wanted sub.

How to parse Ruby Code using IronRuby?

I am new to IronRuby. I am trying to integrate it with C#.
I have created following example and it is working fine.
string rubyCode = #"
def function_111(test)
print 1
end
";
ScriptEngine engine = Ruby.CreateEngine();
ScriptScope scope = engine.CreateScope();
engine.Execute(rubyCode, scope);
dynamic sayHelloFun = scope.GetVariable("function_111");
sayHelloFun("test");
If you look at above code then I am using execute method that compile and execute code but instead of that I only want to parse code it means its syntax are correct or not.
How can that possible ?
The link posted appears dead, and the search engine cache copies appear to be rotting, so I'm going to scrape what is left of the post and interpret it below.
You can use IronRuby along with the Dynamic Language Runtime (DLR) to parse the Ruby code. The steps are to: create a Ruby engine instance, create a script source and unit, create a parser and parse to an AST, and walk the AST with a Walker.
Create the Engine
var runtime = IronRuby.Ruby.CreateRuntime();
var engine = runtime.GetEngine("rb");
Create the Source Unit
var src = engine.CreateScriptSourceFromString(#"puts 'hello'"); // also: engine.CreateScriptSourceFromFile
var srcUnit = HostingHelpers.GetSourceUnit(src);
Parse
var parser = new Parser();
var srcTreeUnit = parser.Parse(srcUnit, new RubyCompilerOptions(), ErrorSink.Default);
Walk the AST
var walker = new MyWalker();
walker.Walk(srcTreeUnit);
You'll need to subclass the Walker class, which has numerous virtual methods to handle visiting various nodes in the AST. The one used in the LinqPad Query looks like so:
public class MyWalker : Walker
{
protected override void Walk(MethodCall node)
{
Console.WriteLine("Method call: " + node.MethodName);
base.Walk(node);
}
protected override void Walk(StringLiteral node)
{
Console.WriteLine("String Literal: " + node.GetMutableString().ToString());
base.Walk(node);
}
}
When you run this walker on the AST generated above, you get the following:
Method call: puts
String Literal: hello
I used LinqPad and added the IronRuby 1.1.3 nuget package and created a LinqPad Query with the above.

Unit testing with generics

I have something like:
class BackupList : List<Backup> {}
and the tests that VS2010 has generated for me look somewhat like:
[TestMethod()]
[DeploymentItem("[...].exe")]
public void AddBackupNormal()
{
SqlServer_Accessor.BackupList ls = new SqlServer_Accessor.BackupList("", "");
SqlServer_Accessor.Backup bk = new SqlServer_Accessor.Backup();
ls.Add(bk);
Assert.IsTrue(ls.Count == 0); // won't compile
List<SqlServer_Accessor.Backup> x = new List<SqlServer_Accessor.Backup>();
Assert.IsTrue(x.Count == 1); // compiles fine
}
however, in the above, the .Count reference fails to compile with:
Error 1 'xxx.SqlServer_Accessor.BackupList'
does not contain a definition for 'Count' and no extension method
'Count' accepting a first argument of type
'xxx.SqlServer_Accessor.BackupList'
could be found (are you missing a using directive or an assembly
reference?) C:[...]Tests\SqlServer_BackupListTest.cs
interestingly, a reference to the original type seems to contain a .Count property as I would expect... so the issue is that the _accessor seems to be casting to something other than a List<>.
how does one approach this?
TIA - e!
My first guess would be that your test class needs a reference...
using System.Collections.Generic;

Addin for enumerating source files

I've been asked to develop an addin that goes through a C# solution and extracts all the documentation from the source files and export them to an HTML file. We can't use normal document generators since the export needs to be in a specific format.
I know how to create a basic addin but have no clue as to how to go about enumerating through the source files.
Any ideas/resources on how to go about starting this project?
Thanks.
Here is some code I'm using to search for a file that ends with a given string.
The structure is like the Solution Explorer in Visual Studio:
Solution -> ProjectItems -> (Nested ProjectItems) -> FileNames
Wherever your code is executing, you can pull up the Projects in the Solution, and then the ProjectItems in those Projects.
var typeFileName = #"\MyClassName.cs";
// Search each Project in the Solution, exclude Unit Test Projects
foreach (Project item in _applicationObject.Solution.Projects.OfType<Project>().Where(p => !p.Name.EndsWith(".Tests")))
{
// Search each ProjectItem recursively
foreach (ProjectItem projectItem in item.ProjectItems)
{
RecursiveProjectItemSearch(projectItem, typeFileName);
}
}
asdasd
private void RecursiveProjectItemSearch(ProjectItem projectItem, string typeFileName)
{
for (short i = 0; i < projectItem.FileCount; i++)
{
var fileName = projectItem.FileNames[i];
if (fileName.EndsWith(typeFileName))
{
// In my case, I want to open the file that I'm searching for
_applicationObject.ItemOperations.OpenFile(fileName);
}
foreach(ProjectItem childProjectItem in projectItem.ProjectItems)
{
RecursiveProjectItemSearch(childProjectItem, typeFileName);
}
}
}
I don't know if this is the most optimal way to do this, but it should work. Given the code above you can change it to do a File.Open() and read the contents or something similar.

Resources