Event assignment syntax in different Object Pascal dialects - syntax-error

I'm working on a component that should be shared between Delphi and C++Builder, so I'm using Pascal as the lingua franca. Because I don't have Delphi on my computer at home, I first created the component in the Lazarus IDE. Now I "ported" it to Delphi and found an astonishing syntax problem:
This compiles with FPC (but not Delphi):
FSync.FSyncMethod := #SyncCheckInput;
This compiles with Delphi (but not FPC):
FSync.FSyncMethod := SyncCheckInput;
How can I share a unit between Lazarus and Delphi despite this syntactic divergence?

Insert this at the beginning of your units:
{$IFDEF FPC}{$MODE DELPHI}{$ENDIF}
This will instruct FreePascal to use the Delphi dialect to compile the unit. Delphi will ignore the {$MODE DELPHI} directive because FPC is not defined.
You can then use this
FSync.FSyncMethod := SyncCheckInput;
for setting events dynamically.

Related

How to get process id in Ada?

I want to make a method returning the calling process id, but can't seem to find how to do that in Ada. Must be looking in the wrong places.
How to get process id on windows and POSIX platforms?
The Florist binding to POSIX should work, but it is quite a sizeable library. Here is a simpler binding example, tested on Mac OS-X:
with Ada.Text_IO;
with Interfaces.C;
procedure My_Pid
is
function Get_Pid return Interfaces.C.int
with Import, Convention => C, External_Name => "getpid";
begin
Ada.Text_IO.Put_Line (
"My PID is" & Interfaces.C.int'Image (Get_Pid));
end My_Pid;
This assumes that the POSIX type pid_t, defined in <unistd.h>, is compatible with Interfaces.C.int, which may not hold on all POSIX platforms; the alternative AIUI is Interfaces.C.long.
I don't have access to a Windows system to test, but it seems there is a _getpid function (https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/getpid?view=msvc-170), with getpid (no leading underscore) as a deprecated alias (https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/posix-getpid?view=msvc-170).
There is also an extensive binding to the Win32 API, similar in scope to Florist, at https://github.com/AdaCore/win32ada.

Roslyn Only Compiler Error with Lambda Statements: Expression cannot be converted into an expression tree

Question
How can I rewrite the below Moq tests so they work again in Roslyn? Obviously I could remove the Lambda, but I was hoping to avoid that.
Also, for interest sake: did the Roslyn compiler fix a bug that allowed these invalid statements to work previously or is this a compiler bug that now breaks these statements?
Details
I'm trying to move my mostly VB.NET solution to Visual Studio 2015, from Visual Studio 2013. All projects in the solution are targeting .NET 4.5. I am currently using Moq 4.0 for these tests. I have several Moq based Lambda unit tests that fail to compile in Visual Studio 2015, but compile and run fine in Visual Studio 2013. These tests have worked in Visual Studio 2010 and Visual Studio 2012 as well.
Most of the tests are very simple and look something like this:
Private _view As Mock(Of Views.ICreateSecurityUserView)
<Test>
Public Sub ValidateSave_CallWithBlankLogin_SetsViewToolError()
_view = New Mock(Of Views.ICreateSecurityUserView)()
_view.SetupGet(Of String)(Function(x) x.Login).Returns("")
_view.SetupGet(Of String)(Function(x) x.LoginName).Returns(loginNameValue)
_subject.ValidateSave()
_view.Verify(Sub(x) x.LoginFieldError = It.Is(Of String)(Function(s) Not String.IsNullOrEmpty(s)), Times.Once)
End Sub
The offending line will be this one: _view.Verify(Sub(x) x.LoginFieldError = It.Is(Of String)(Function(s) Not String.IsNullOrEmpty(s)), Times.Once)
The build error I get (as in the title) is:
Error BC36534 Expression cannot be converted into an expression tree.
I've fiddled with the expression a bit, seeing if the compiler would be happier if it was multi-line:
_view.Verify(Sub(x)
x.LoginFieldError = It.Is(Of String)(Function(s)
Return Not String.IsNullOrEmpty(s)
End Function)
End Sub, Times.Once)
But to no avail, since this just adds these extra errors (the Visual Studio 2013 compiler also doesn't like the multi-line version):
Error BC36675 Statement lambdas cannot be converted to expression trees.
Bad "Solution"
I am able to get this compiling if I change the test line to:
_view.Verify(Sub(x) VerifyFunctionNameError(x), Times.Once)
Which then calls the new, pointless, function:
Private Sub VerifyFunctionNameError(x As Views.ICreateSecurityFunctionView)
x.FunctionNameError = It.Is(Of String)(Function(s) Not String.IsNullOrEmpty(s))
End Sub
Your question is hard to answer, I can't get a decent repro for this without knowing the declarations. Nevertheless, there is certainly a hint why this should not compile from the VB.NET Language Specification. Find a copy of it on your machine in C:\Program Files (x86)\Microsoft Visual Studio 14.0\VB\Specifications\1033\Visual Basic Language Specification.docx
Navigate to chapter 11.1.1 and scroll down a bit to arrive at the Annotation block. I'll quote the most relevant part:
The exact translation between lambda methods and expression trees may not be fixed between versions of the compiler and is beyond the scope of this specification. For Microsoft Visual Basic 11.0, all lambda expressions may be converted to expression trees subject to the following restrictions:
1. Only single-line lambda expressions without ByRef parameters may be converted to expression trees. Of the single-line Sub lambdas, only invocation statements may be converted to expression trees.
First noteworthy detail is that Microsoft does not want to nail down the exact rules and that the specification is dated. Why they didn't want to nail is fairly visible, the restrictions are quite crippling and they would have wanted to leave room for improvement.
It does otherwise state explicitly why neither compiler version can convert your multi-line lambda method, only single-line is supported. Next part of the sentence explains why you can't make it work on VS2015, you are using an assignment statement and not a method invocation.
So this strongly hints that VS2013 was at fault, it should not have accepted your lambda method. It is a given that the very drastic Roslyn parser rewrite would tighten-up the syntax rules and avoid replicating bugs in previous versions. Also plenty of room to worry that the VS2013 code did not actually work correctly. Non-zero odds that it incorrectly parsed the lambda as an expression instead of a statement. In other words, getting a comparison expression instead of an assignment statement. VB.NET does open the door to this kind of ambiguity, the = operator is used both in expressions and assignment statements. This is a guess I cannot verify without a repro.
Best to bounce this off the guys that actually wrote the compiler. You can file a feedback report at connect.microsoft.com. Be sure to include a minimum repro that they can compile or they'll quickly give up. Beware that there are good odds that they will close it as "By design". That's what it looks like.
My above "Bad Solution" in my question, doesn't actually even work anyway. This fails when the test runs because it obviously can't determine anything from the sub.
The actual answer to my question is to use Mock.VerifySet, instead of Mock.Verify. We are actually doing this in most places, so I'm not sure why we used the other method here. A rewritten test that will work in 2013 and 2015 will look like this:
_view.VerifySet(Sub(x) x.LoginFieldError = It.Is(Of String)(Function(s) Not String.IsNullOrEmpty(s)), Times.Once)
This compiles and the tests are passing as well.
I was poking around in the Moq source code today and the reason for the different result is seen below:
Verify
public void Verify(Expression<Action<T>> expression, Times times)
{
Mock.Verify(this, expression, times, null);
}
VerifySet
public void VerifySet(Action<T> setterExpression, Times times)
{
Mock.VerifySet(this, setterExpression, times, null);
}
The Expression<Action<T>> has apparently had its handling changed, while the Action<T> doesn't appear to have had its changed.

FORTRAN DLL calling convention from MapleSim / Modelica

Modelica modeling language supports calling functions from external FORTRAN DLLs, however, MapleSim only includes the support of calling functions from C DLLs even though it says it has full support for the Modelica language, and I have no choice but to use this FORTRAN DLL (I can't reprogram it in C nor I can use other Modelica evironments than MapleSim), so I'm not in the undocumented features realm.
I tried forcing MapleSim to include the FORTRAN DLL and created a custom component but its not working. This is the code I got when I opened the custom component: [relevant portion only]
model ExternalCode
function GETPSAT
input Real TC;
output Real PC;
external "C" PC = GETPSAT(TC)
annotation (
Library = "C:/Path/To/My/DLL/FORTRAN.dll", __Maplesoft_callconv = "stdcall");
end GETPSAT;
equation
(PC) = GETPSAT(TC);
annotation (
experiment(__Maplesoft_engine = 2));
end ExternalCode;
I know I should change external "C" to external "FORTRAN", but what should I should I do with __Maplesoft_callconv = "stdcall"? ie: what is the call convention for FORTRAN functions? (I know nothing on the subject of calling conventions).
Note the parent evnironment of MapleSim 6.1 (Maple 17) supports importing external functions from FORTRAN so I think there is a possibility MapleSim will support it despite it being undocumented.
edit: By the way, the DLL was compiled with Compaq visual fortran (I don't remember the version)
edit2: The function in the FORTRAN DLL is exported as follows:
FUNCTION GETPSAT(TC)
!DEC$ ATTRIBUTES ALIAS:'GETPSAT' :: GETPSAT
!DEC$ ATTRIBUTES DLLEXPORT :: GETPSAT
!DEC$ ATTRIBUTES VALUE :: TC
GETPSAT=PSAT11(TC)
RETURN
END
edit3: I don't know it this helps, but the same function can be called from C# like this:
[DllImport("C:\\Path\\To\\My\\DLL\\FORTRAN.dll")]
static extern float GETPSAT(float T);
This particular Fortran function should behave like a completely normal C function because of the attributes it has. Do not add any external(FORTRAN) or similar. Its name should be GETPSAT and it accepts 1 float TC by value.
Use the same "stdcal" attribute, it is default for the DEC, Compaq and Intel Fortran https://software.intel.com/sites/products/documentation/hpc/mkl/mkl_userguide_win/GUID-E74229B0-7389-46A6-9FCF-91CD6CD5B0E4.htm

DllImport vs Declare in VB.NET

I notice in the MSDN documentation that there are multiple ways to declare a reference to a function in an external DLL from within a VB.NET program.
The confusing thing is that MSDN claims that you can only use the DllImportAttribute class with Shared Function prototypes "in rare cases", but I couldn't find the explanation for this statement, while you can simply use the Declare keyword instead.
Why are these different, and where would I appropriately use each case?
Apparently the Declare and DllImport statements are basically the same. You can use whichever you prefer.
Following is a discussion of the few points that may work a little differently in each, which may influence a preference for one over the other:
I started with an article from MSDN regarding Visual Studio 2003 titled Using the DllImport Attribute. (A bit old, but since the DllImport statement seems to have originated in .NET, it seemed appropriate to go back to the beginning.)
Given an example DllImport statement of:
[DllImport("user32.dll", EntryPoint = "MessageBox", CharSet = Unicode)]
int MessageBox(void* hWnd, wchar_t* lpText, wchar_t* lpCaption, unsigned int uType);
It says that if the EntryPoint value is left out, the CLR will look for the name of the function (MessageBox, in this case) as a default. However, in this instance, since a CharSet of Unicode was specified, the CLR would FIRST look for a function called "MessageBoxW" - the 'W' indicating a Unicode return type. (The ANSI return type version would be "MessageBoxA".) If no "MessageBoxW" were found, THEN the CLR would look for an API function actually called "MessageBox".
Current specifics about the DllImportAttribute class can be found here, where I viewed the .NET Framework 4 version: DLLImportAttribute Class
A key comment in the Remarks section of this .NET Framework 4 page is that:
You apply this attribute directly to C# and C++ method definitions; however, the Visual Basic compiler emits this attribute when you use the Declare statement.
So, in VB.NET, using the Declare statement causes the compiler to generate a DLLImportAttribute.
There is also an important note in this page:
The DllImportAttribute does not support marshaling of generic types.
So, it would appear that if you want to use a generic type, you'd have to use a Declare statement.
Next, I headed to the Declare statement information. A Visual Studio 2010 version (Visual Basic statement info) was here: Declare Statement
A key item here was this note:
You can use Declare only at module level. This means the declaration context for an external reference must be a class, structure, or module, and cannot be a source file, namespace, interface, procedure, or block.
Apparently, if you want to set up an API call outside of a class, structure, or module, you'll have to use the DllImport statement instead of the Declare.
The example Declare statement on this page is:
Declare Function getUserName Lib "advapi32.dll" Alias "GetUserNameA" (
ByVal lpBuffer As String, ByRef nSize As Integer) As Integer
Following that example is this little tidbit of information:
The DllImportAttribute provides an alternative way of using functions in unmanaged code. The following example declares an imported function without using a Declare statement.
followed by, of course, an example of DllImport usage.
Regarding Unicode vs ANSI results, according to this Declare page, if you specify a CharSet value (available in Declare, but not shown in the example above) the CLR will do the same type of automatic name search that DllImport does - for either Unicode or ANSI.
If you do not specify a CharSet value in the Declare statement, then you must make sure that your function name in the Declare is the same as the function name in the actual API function's header file, OR you must specifiy an Alias value that matches the actual function name in the header file (as shown in the example above).
I was not able to find any specific Microsoft documentation stating that either DllImport or Declare were preferred, or even recommended, over one another in any situation other than those noted above.
My conclusion, therefore, is:
Unless you need to place your definition in one of the places a Declare statement cannot be used, either technique will work fine,
and
if you're using DllImport, make sure you specify the CharSet value you want (Unicode or ANSI), or you may get unexpected results.
Declare is really an attempt to maintain a P/Invoke syntax which would be more familiar to Visual Basic 6.0 users converting to VB.NET. It has many of the same features as P/Invoke but the marshalling of certain types, in particular strings, are very different and can cause a bit of confusion to people more familiar with DllImport rules.
I'm not entirely sure what the documentation is alluding to with the "rare" distinction. I use DllImport in my code frequently from both VB.NET and C# without issue.
In general, I would use DllImport over Declare unless you come from a Visual Basic 6.0 background. The documentation and samples for DllImport are much better and there are many tools aimed at generating DllImport declarations.
In my opinion, since this keyword doesn't look deprected, etc. from what I searched, simply use compile-time keywords rather than attributes.
Also, when you use the Declare, you don't need to write the End Function. The advantage of that is that you can create a whole module of declarations of function imports line by line, with no need to pulute your code with DllImports and End Functions.
When you declare using the Declare keyword, the compiler treats this function as Shared anyway, so it can be accessed via other extenal objects.
But I think in the current VB.NET they're both addressed to the same target and no performance difference - no warranty on this one.
So my conclusion is: Do use the Declare instead of DllImport, especially reading what you quoted that Microsoft stated that it should be used in rare cases.
If you need to set one of the following options, then use DllImportAttribute attribute, else use Declare. From https://msdn.microsoft.com/en-us/library/w4byd5y4.aspx
To apply the BestFitMapping, CallingConvention, ExactSpelling,
PreserveSig, SetLastError, or ThrowOnUnmappableChar fields to a
Microsoft Visual Basic 2005 declaration, you must use the
DllImportAttribute attribute instead of the Declare statement.
It is unclear from the above reference only whether this applies to only "Visual Basic 2005" or not, as the above reference is from a .NET 4.5 article. However, I also found this article (https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute(v=vs.110).aspx ) which is specific to the DllImportAttribute class in .NET 4.5 :
the Visual Basic compiler emits this attribute when you use the
Declare statement. For complex method definitions that include
BestFitMapping, CallingConvention, ExactSpelling, PreserveSig,
SetLastError, or ThrowOnUnmappableChar fields, you apply this
attribute directly to Visual Basic method definitions.
This tells you that the Declare option is VB.net syntactical sugar which is converted to DllImportAttribute at compile time, and outlines the exact scenarios when using DllImportAttribute directly is recommended.

What is the use of the := syntax?

I'm a C# developer working on a VB.NET project, and VS keeps trying to get me to use the := thingie when I call a function with a ByRef parameter like so:
While reader.Read()
HydrateBookFromReader(reader:=???)
the HydrateBookFromReader function has the following signature:
Public Function HydrateBookFromReader(ByRef reader As SqlDataReader) As Book
Why does intellisense keep insisting that I use that := construction, and what is it for?
In VB, the := is used in specifying named parameters.
Contact(Address:="2020 Palm Ave", Name:="Peter Evans")
This is especially useful for specifying optional parameters.
Why does intellisense keep insisting that I use that := construction, and what is it for?
It's important to note that IntelliSense doesn't insist, it proposes. Using it in your case wouldn't make sense … this feature is primarily used for very long parameter lists with many optional parameters, of which you only want to pass, say, the last one. It's useful when working with Microsoft Office Interop.
Also (since you mention it in your tags): this has got nothing to do with ByRef. ByRef is equivalent to ref and out in C#, i.e. it allows the method to manipulate the parameter itself.
Intellisense may be suggesting the := syntax, but I suspect that it will compile without it.
HydrateBookFromReader(myReader);
In future versions of C# where optional parameters are allowed, named parameters will allow you to specify some parameters but not others, and to specify parameters in a different order than they were declared. Named parameters will also allow you to optionally clarify the purpose of the parameter being passed in, making the code more readable in some cases.
Named parameters will be especially important in c# 4.0 for COM Interop, where many superfluous parameters can be eliminated.
Anders Hejlsberg has an excellent discussion about the future of C# on Channel 9 at http://channel9.msdn.com/pdc2008/TL16/. His discussion about named parameters is at 40 minutes and 45 seconds into the talk.