Contents tagged with ASP Classic Compiler
-
ASP Classic Compiler is now available in NuGet
I know this is very, very late, but I hope it is better than never. To make it easy to experiment with ASP Classic Compiler, I made the .net 4.x binaries available in NuGet. So it is now extremely easy to try it:
- From the package console of any .NET 4.x web project, run “Install-Package Dlrsoft.Asp”.
- To switch from AspClassic to Asp Classic Compiler in the project, add the following section to the system.webServer handlers section:
<system.webServer> <handlers> <remove name="ASPClassic"/> <add name="ASPClassic" verb="*" path="*.asp" type="Dlrsoft.Asp.AspHandler, Dlrsoft.Asp"/> </handlers> </system.webServer>
Comment out the section to switch back. - Add a test page StringBuilder.asp:
<% imports system dim s = new system.text.stringbuilder() dim i s = s + "<table>" for i = 1 to 12 s = s + "<tr>" s = s + "<td>" + i + "</td>" s = s + "<td>" + MonthName(i) + "</td>" s = s + "</tr>" next s = s + "</table>" response.Write(s) %>
This code uses the .net extension so it will only work with Asp Classic Compiler.
Happy experimenting!
-
Converted ASP Classic Compiler project from Mercurial to Git
Like some other open source project developers, I picked the Mercurial as my version control system. Unfortunately, Git is winning in the Visual Studio echo systems. Fortunately, it is possible to contact Codeplex admin for manual conversion from Mercurial to Git. I have done exactly that for my open source ASP Classic Compiler project. Now I can add new examples in response to forum questions and check them in using my Visual Studio 2013. Now I am all happy.
-
Lessons from the ASP Classic Compiler project
I have not done much with my ASP Classic Compiler project for over a year now. The lack of additional work is due to both the economic and the technical reasons. I will try to document the reasons here both for myself and for would–be open source developers.
How the project got started?
I joint my current employer at the end of 2008. The company had a large amount of ASP classic code in its core product. The company was in talk with a major client on customization so that there was a period that the development team had fairly light load. I had a chance to put in a lot of thinking on how to convert the ASP classic code to ASP.NET. One of the ideas was to compile ASP Classic code into .net IL so that they can be executed within the ASP.NET runtime.
I do not have a formal education in computer science; my Ph.D. is in physics. I had been very fond of writing parsers by following the book “Writing Compilers & Interpreters” since 1996. I wrote a VBA like interpreter and a mini web-browser, all in Visual Basic, using the knowledge acquired. Nevertheless, a full-featured compiler is still a major undertaking. I spent several months of my spare-time working on the parser and compiler, and studied the theory behind. I was able to implement all the VBScript 3.0 features and the compiler was able to execute several Microsoft best-practice applications. The code runs about twice as fast as ASP Classic. I had lots of fun experimenting with ideas such as using StringBuilder for string concatenation to drastically improve the speed of rendering. I was awarded Microsoft ASP/ASP.NET MVP in 2010. In 2011, I donated the project to the community by opening the source code after consulting with my employer.
Since then, I faced challenges on two fronts: adding VBScript 5.0 support and solving a large number of compatibility issues in the real-world. After working for a few more months, I found it difficult to sustain the project.
Lesson 1: the economy and business issues
1. Sustainability of an open source project requires business arrangements. I am an employee. Technical activities outside the work are welcome as long as it benefits the employer. However, excess amount of activities not relating to the work could be a loyalty issue.
2. ASP Classic is a shrinking platform. So ASP Classic Compiler would not be a sound investment for most businesses except for Microsoft who has interest in bridging customers from older to newer platform painlessly.
Lesson 2: the technical issues
1. VBScript is a terrible language without a formal specification and test suites. The best “spec” outside of the users’ guide is probably Eric Lippert’s blog. It is not getting much maintenance and it is losing favor. As a result, few other developers with knowledge in compiler would have interest in VBScript.
2. Like the IronPython project and the Rhino projects, I started by writing a compiler. I was very shrilled that my first implementation without much optimization is about twice as fast as VBScript in my benchmark test. However, I had many obstacles on compatibility and adding the debug feature. If I would do it again, I would probably implement it as an interpreter with an incremental compiler. The interpreter would have a smaller start-up overhead. I can then have a background thread compiling the high usage code. The delayed compiling would allow me to employee more sophisticated data-flow analysis and construct larger call-site blocks. The current naïve implementation on DLR results in too many very small call-sites so that type-checking at call-sites is a significant overhead.
In summary, I had lots of fun with the project. I significantly improved my theoretical knowledge of algorithms in general, and of parsers and compilers. I had the honor of being awarded Microsoft ASP.NET/IIS MVP for the past 3 years and enjoyed my private copy of MSDN subscription at home. After a working prototype, the remaining work to take it to a production quality software is more a business problem than else. I am actively contemplating some new forward-looking ideas and wish I have some results to share soon.
-
Silverlight 4 version of VBScript.NET
I was asked whether my VBScript.NET compiler would run under Silverlight. I indeed updated my VBScript.NET compiler a month ago to support Silverlight 4. So besides Iron languages, VBScript.NET is another dynamic language that you can use in Silverlight. The May 3, 2011 or a later version supports Silverlight 4.
-
Passing managed objects to unmanaged methods as method argument
It is well documented how to expose a .net class as a COM object through the COM callable wrapper. However, it is not well documented how to pass a .net object to a COM method in an argument and have the COM method treat the .net object as COM. It turns out all we need to do is to add the [ComVisible(true)] to the classes that we need to pass to COM method; runtime would recognize that we are passing the object to COM and generate the COM callable wrapper automatically.
However, there are some impedance mismatches between COM and .NET. For example, .NET supports method overloading while COM does not. COM objects often uses optional arguments so that the client can pass variable number of arguments to the server. I used the following pattern to expose the Assert object to unmanaged VBScript engine in my VBScriptTest project in ASP Classic Compiler:
[ComVisible(false)] public void AreEqual(object expected, object actual) { Assert.AreEqual(expected, actual); } [ComVisible(false)] public void AreEqual(object expected, object actual, string message) { Assert.AreEqual(expected, actual, message); } [ComVisible(true)] public void AreEqual(object expected, object actual, [Optional]object message) { if (message == null || message == System.Type.Missing) AreEqual(expected, actual); else AreEqual(expected, actual, message.ToString()); }
Note that I marked the first two overloaded methods with [ComVisible(false)] so that they are only visible to other .net objects. Next, I created a COM callable method with an optional parameter. The optional parameter must have the object type; runtime will supply the System.Type.Missing object if a parameter is not supplied by the called. So in the body of the method, I just need to check whether the parameter equals to System.Type.Missing to determine whether the parameter is passed.
-
/Platform:AnyCPU, /Platform:x64, /Platform:x86, what do they mean
When we build a .net solution, we often see the Platform choice in the configuration manager:
Besides AnyCPU, other choices are x86 ,x64, and Itanium. What do they mean? According to MSDN, “Anycpu” compiles the assembly to run on any platform while the other 3 choices compiles the assembly for 32 bit, 64 bit x64 and 64bit Itanium respectively.
On a 64-bit Windows operating system:
-
Assemblies compiled with /platform:x86 will execute on the 32 bit CLR running under WOW64.
-
Executables compiled with the /platform:anycpu will execute on the 64 bit CLR.
-
DLLs compiled with the /platform:anycpu will execute on the same CLR as the process into which it is being loaded.
If a .net application uses any 32 bit ActiveX component, it will not be able to load the component in-process. We have two choices:
- Host the 32 bit component in an external process, such as COM+ Server Application, or
- Run the .NET application as a 32 bit application.
The VBScriptTest project in ASP Classic Compiler contains an unmanaged test. It hosts the msscript.ocx so that I can compare my .net implementation of VBScript against the original VBScript engine from Microsoft. In order to use the 32 bit msscript.ocx, I need to run my unit test in a 32 bit process. NUnit has a 32 bit version of the test runner call NUnit-x86.exe. To use the 32 bit runner, I registered new shell extension as shown below so that I can use the “Run 32 bit NUnit” context menu to invoke the 32 bit NUnit test:
Lastly, how to run ASP.NET in 32 bit? It turned out that this is controlled by the Application Pool. If I set the “Enabled 32 bit Application” to true in the Advance Property Setting of the application pool, the ASP.NET application will run in 32 bit.
-
-
ASP Classic Compiler: How to contribute
For the project to be viable, we need contributors of all technical levels, from writing simple test cases and examples, to working on the compiler. I have written a wiki page on my project site detailing how to contribute.
-
ASP Classic Compiler: the unit testing framework is released
In my previous post, I stressed the importance to have a unit testing framework to move forward with this project. I was facing the decision whether to use NUnit or MSTest. After some thoughts, I came to the conclusion that the choice of unit testing framework is not critical, at least for now. For a language project, unit testing usually falls into two categories: the testing of a parser and the testing of generated code. For parser testing, most of work lies in comparing AST generated by the parser with the expected AST. Paul Vick has an excellent framework in his VBParser work. For testing of the generated code, it is best to have a unit testing framework that is self-contained in the target language so that is can most accurately test the semantics of the language. For example, Javascript has the QUnit framework and ASP Classic has the ASPUnit framework.
So I went ahead to release my own unit testing framework for VBScript. I created an interface called IAssert that has the following methods:
void AreEqual(object expected, object actual);
void AreEqual(object expected, object actual, string message);
void AreNotEqual(object notExpected, object actual);
void AreNotEqual(object notExpected, object actual, string message);
void Fail();
void Fail(string message);
void IsFalse(bool condition);
void IsFalse(bool condition, string message);
void IsTrue(bool condition);
void IsTrue(bool condition, string message);
These are minimum set of method often found in most of unit testing frameworks. We can always add more when needed. Note that I did not have IsEmpty or IsNothing methods. That is because I believe we should use the language built-in method to best reflect the language semantics. For example, instead of having an IsEmpty method in the testing framework, we should use IsTrue(IsEmpty(myVar)) where we are using the VBScript built-in function.
In environments that we have control over the host, the host will supply an Assert object that can route the testing results to one of the existing unit testing framework, such as NUnit, so that we can reuse the test runners and report functionalities. In the environments that we do not have control of the host, we can supply an Assert class in VBScript itself, much like what ASPUnit does.
If you look at my VBScriptTest project, you will notice that it uses NUnit framework. It has a single NUnit test case that walks the entire hierarchy under the VBScripts folder. When we need to write a new test case, we just simply add a .vbs file under the VBScripts folder. The following is an example VBScript unit test case:
dim a Assert.IsTrue(IsEmpty(a), "Unassigned variable must be empty")
Because I have use a single NUnit test case to run all the VBScripts, the message parameter is an important parameter to distinguish the test case in the situation of failed test case.
-
ASP Classic Compiler: the next step
I opened the source code for my ASP Classic Compiler 2 days ago. As this project was started as a research project, proof of concepts has been a major goal. I have cut corners whenever possible to bring out features fast. Going forward, there are many things that need to be tighten up. The following are my top priorities:
- Unit testing: You eager downloaders may have noticed the my project is notoriously missing unit tests. I intentionally took out my unit tests when I upload because my previous unit tests were not well organized. I want to give us chance of a fresh start. Since we will have refactoring and re-architecture of the code generator, unit testing is going to carry this project. Like many open source projects, NUnit or MSTest is a decision to make. I have created this thread in my forum to solicit ideas. I don’t quite need StackOverflow style discussions as there are already plenty. But if you look at recent high profile switches in either directions, you would know this is not an easy decision.
- Making it easier for people diagnose problems. A debugger is not going to happen easily, as I have already tried twice. But with source code, it is still possible for people to diagnose problems. This will help reducing the frustration level and getting bug reported and fixed.
- VBScript 5.0 support. This is my real top goal since many people requested it, but I could not get there without 1 and 2. I want to take over the memory management since I have already pushed DLR to the limit. Controlling the memory management will open up the possibility for debugging. Details is going to be a blog by itself.
- Performance improvement when calling CLR static methods. The TypeModel used in VBScript.NET does not take advantage of call-site caching and is hence very slow. Fortunately, this can be corrected fairly easily.
- Optimize for multiple string concatenations. This has been a habit in many ASP projects. I can discover this in code analysis and generate the code behind the scene using StringBuilder. This is a pretty fun research project and it is not too hard.
- Type checking in many places can still be optimized for callsite-caching.
- Rewrite of the parser. Currently, my VBScript parser is modified from Paul Vick’s VBParser which was written in VB.NET. I have some concern on VB.NET’s timely availability in new platforms (remember Windows Phone 7?). However, since my code generator is tightly coupled to the abstract syntax tree (AST) in the parser project, this is going to be a messy work.
-
ASP Classic Compiler is now open source
After weeks of preparation, I have opened the source code for my ASP Classic Compiler under the Apache 2.0 license. I conceived the project in 2009 when I joint a company that had a large amount of ASP Classic code. The economy was very slow at the time so I had some energy left to start the work as a hobby. As the economy recovers, I was getting busier with my day-time job. We converted most of our ASP Classic code to .net so that this project would no longer be useful for my own use. However, I truly hope that this project will be useful to those who can still use it.
The project had gone a long way to implement most features in the VBScript 3.0 standard. It is capable of running the Microsoft FMStock 1.0 end to end sample application. I chose VBScript 3.0 in my initial implementation because VBScript 3.0 is a language with dynamic type and static membership. ASP Classic Compiler is faster than most of the Javascript implementations and is about 3 times faster than the IIS ASP interpreter in limited benchmark test. Many users have requested VBScript 5.0 features such as Class, Execute and Eval. VBScript 5.0 has dynamic membership like Javascript. To avoid the performance hit, I have done some research to optimize the performance for the mostly static scenariou, but have yet to find time to implement it.
For this project to be successful, I truly need community involvement. In the next few days, I will outline what need to be done. I will stay as the project lead until we find a suitable new leader.