Oxygene/Pascal questions, coming from FPC

Greetings, RemObjects community! I’ve been doing a lot of research, and Oxygene seems like a really promising language/compiler setup. I’m currently using the trial version to see if Oxygene can be part of our solution moving forward. One of the tricks, though, is that I need a good portion of the code to be able to be compiled via either FPC or Oxygene. One reason (among others) is that our Mac Developers still prefer to directly compile on XCode rather than having to use Visual Studio via a PC or VM. Anyway, assuming that we still need fpc compatibility, here are some of my questions/issues:

  1. I’ve seen it already mentioned (http://connect.remobjects.com/discussion/4010/bug-leading-to-miss-leading-message-code-after-final-end-dot-ignored) that Oxygene doesn’t currently support TYPE specifically declared within a class or method, but that its been marked as a feature request. This is a pretty fundamental part of ‘classic’ Pascal, so out of curiosity, does anyone know the demand/timeframe for this improvement? There are some issues that can be worked around, but this one is potentially a deal-killer, or at least a “We can’t move to Oxygene until its implemented” issue.

  2. Is there any replacement for the old pascal Str255 type? It was also optionally declared as a STRING[255] type. Such a declaration fails (“semicolon expected, got open square bracket”), and Str255 is unknown. I could define it as an ARRAY, but then the LENGTH(), POS, CONCAT, etc. calls wouldn’t work right. Also, defining it as an ARRAY means that I can’t declare a CONST using SIZEOF. e.g.:

TYPE
{Str255 = STRING[15]} { This fails! }
Str255 = PACKED ARRAY [1…255] OF Byte;
CONST
StrLen = SIZEOF(Str255) { This fails! }

  1. I’m having an issue where RECORDS declared in another Unit are not recognized elsewhere, with the error <<(E382) Type “TestType” cannot be used as a type for public member “TestVar” of type “TestUnit2”, because it is not public>>. This can be reproduced with a simple project setup:

namespace TestUnit1
interface
type
TestType = RECORD
END;
implementation
end.


namespace TestUnit2
interface
uses
TestUnit1;
var
TestVar: TestType;
implementation
end.

  1. Is there any native string type that is single-byte encoded? Our code uses a variety of multibyte strings (Which I can use the default String type for), but also singlebyte strings (Which I haven’t found a replacement for yet). Why this matters is simply when reading/writing out of files, copying around memory, etc. I’ve seen that the RemObjects SDK supports an AnsiString type, but I wasn’t sure how well it ‘played with’ Oxygene, and if it supports the traditional methods (Delete, Pos, Insert, Copy, Length, etc.).

I appreciate any help that can be provided! Or, is it safe to say that my goal is too lofty? Is it unreasonable to think that parts of our codebase can be compiled in either fpc (delphi mode or otherwise) and Oxygene?

Many thanks!

Hello,

  1. We do not support String[255] but you can use Array of chars instead and use compiler magic functions (Length, etc.) The full list of that functions you can find at http://wiki.oxygenelanguage.com/en/Compiler_Magic_Functions

  2. You should use public modifier for your record.

  3. There is no single-byte string type. You can write a class that implicit operators and another stuff for such strings but better would be to use regular strings and have the read/write methods deal with how it’s stored on disk.

I’ll get back to the first question later today. Also sure you can’t use the same code for fpc and Oxygene. There will be some changes but you can use IFDEF logic to separate them and that will let you to keep the major part of the code in the same files.

Best regards.

is there really a good use case where a type would NEED to be defined inside a method — and a global type (maybe with unit visibility, and/or defined in the implementation section) would not suffice? The latter would compile fine in FPC as well.

Getting back to the first question. We are considering the necessity to implement that feature.

Thanks for the replies, I really appreciate your attentiveness. Discussing each issue:

  1. Supporting a method-defined TYPE is more of a coding practice/cleanliness issue, than one of bugs/compile errors. Aside from the hassle of changing the many instances in our codebase, we mainly use them to keep things simple and clean. If I need a custom type just for one method, why define it in such a way that potentially conflicts with all of my other methods? Being able to choose how to scope the TYPE (method, unit, global, etc.) using the same scoping rules as my CONST and VAR leads to cleaner (and more logical, at least to me!) code-writing.

  2. How would I use the ARRAY of CHAR? Isn’t a char a widechar by default (thus requiring me to use a Byte instead)? Also, would it be assignable (e.g. myString := ‘Test’;), or sizeable (e.g. mySize := SIZEOF(Str255))? Finally, I didn’t see some of the string functions listed on the magic functions, such as Pos, Delete, Insert, or Copy.

  3. Defining the record as a ‘Public Record’ works for Oxygene compilation, but fails in fpc. Is there any other way around this, or would I need to $IFDEF every global record type?

  4. I was afraid there wasn’t any single byte type. Though more of a hassle, it does seem like custom read/write types when we need single byte characters may be the only solution. What about the Ansistring type in the RemObjects SDK? If we included the sdk, would it be a fully functioning single-byte string (supporting all the usual string methods)?

Thanks again!

ROSDK/.NET exposes all strings as regular .NET Strings. Only how the string is encoded on the wire is defined by the string type define din the RODL.

.NET has no Ansi string or char type. It does of course have Byte.

(and it’s 2013, so using AnsiStrings for anything is really a bad idea, especially with remote services. All you need to a different codepage being active on one of tour client machines, and all goes belly-up. You really want to use Utf8String or WideString for tour RO servicies).

I appreciate the feedback on the AnsiStrings. Sounds like a wrapper + in/out is our best bet. Our use of Ansistrings is steadily declining, but at a bare minimum, to support legacy files, we need regular manipulation of them.

Does anyone have a solution for the Record public issue? Since fpc doesn’t understand the ‘public’ keyword in this context, will I have to IFDEF every single global record type declaration?

For reading/writing AnsiStrings to files, you will want to use “array of byte” along with the string encoding classes.

eg:

var lBytes := Encoding.UTF8.GetBytes(myString);

similar to UTF8, you could pick any different encoding of course, to match what exactly your files are spec’ed to contain.

Sounds great, mh, thanks!

Is there any word on the ‘public record’ issue? Is there no other (fpc-compatible :)) way to make my global record types available throughout the code?

Hello,

You need to IFDEF all your public records type. I’m afraid there is no other solution in that case.

Best regards.

Hello,
you could made a solution-wide replace, replacing “= RECORD” with “= {$ifdef oxygene} public {$endif} record”. You will then to define the conditional compilation symbol oxygene, in all of your configurations (debug and release).
Just make sure to make a backup of the solution before, just in case of.
Patrick

OXYGENE should be defined by default. See wiki.oxygenelanguage.com/en/Conditional_Defines