I have been working on the FoxPro language support yesterday and have the following questions:
1) In FoxPro all classes (have to) inherit from a base class. The ultimate base class is Custom. This is not just an empty class, because it also provides quite a few properties, events and methods. For example properties like name, left, right, Events like Init, Error and Destroy and methods like AddObject, AddProperty etc.
What do you think, should we allow classes (declared with the FoxPro class definition syntax) to inherit from 'nothing' (i.o.w. from System.Object), which also means that these objects will only have the normal .Net methods such as GetType() GetHashCode() and ToString().
We could also add a compiler option that determines that when no base class is defined your class either inherits from System.Object or from XSharp.FoxPro.Custom.
2) The FoxPro class syntax speaks of "Properties" and not of "Fields" or "Instance variables"
DEFINE CLASS ClassName1 AS ParentClass
[[PROTECTED | HIDDEN] PropertyName1, PropertyName2 ...]
[[.]Object.]PropertyName = eExpression ...]
What would you expect that happens when this is compiled to .Net. Should PropertyName1 etc. become a 'real property' (with a getter and setter) or should they be compiled into a Field.
The problem with compiling it to a field is that we sometimes see a syntax like this:
DEFINE CLASS Animal as custom
Species = "Animal"
DEFINE CLASS Dog AS Animal
Species = "Dog"
If we compile "Species" to a field then the Dog class will try to redefine the field in the parent class.
Our compiler will then produce the warning:
warning XS0108: 'Dog.Species' hides inherited member 'Animal.Species'. Use the new keyword if hiding was intended.
From what I have seen FoxPro declares everything as "real" properties and somehow stores name/value pairs in an invisible collection inside each object and both Species in the Animal class and in the Dog class read/write from the same collection. So all these properties are virtual as well
So my current thinking is to generate .Net properties from this and make these virtual so they can be overwritten in a child class. We can also add a collection, but we can also create a backing field. In case of a property that overrides a parent property we can change the getter and setter and redirect the call to the parent property.
But that would mean that you can't create fields with the current FoxPro syntax.
I see a couple of solutions:
a) with a special compiler option you can tell the compiler to generate fields or properties. When you generate fields you will get a warning when you redefine a field in subclass
b) we always generate properties but add a special syntax to declare fields, something like
DEFINE CLASS ClassName1 AS ParentClass
[[PROTECTED | HIDDEN] FIELD Field1, Field2 ...]
FIELD FieldName = eExpression ...]
Btw: our current definition allows you to specify the types for Fields/Properties:
3) All methods inside FoxPro seem to be virtual. This was also the case for Visual Objects. We have a compiler option that does this automatically.
4) The ADD OBJECT syntax creates a property (field?) and sets the value of the property to a new object of the specified type and allows to set initial values for some properties of this new object. What is not clear to me is if this object is also automatically added to a collection of children (controls) in the class ?
5) Now that we move FoxPro to .Net we will also be able add new functionality. So far we have added the following (for free because it is there in our compiler already)
- The ability to declare attributes on a type, property method etc
- The ability to add more (visibility) modifiers then just PROTECTED and HIDDEN. For example also INTERNAL,ABSTRACT, STATIC and SEALED
- The ability to define Generic types and methods
DEFINE CLASS MyStack<T> WHERE T IS NEW()
- All types can be specified in the Namespace.Type syntax. For example
CLASS MyTable as System.Data.DataTable
I have more questions but these can be handled later
I would value your input on this.
I realise this is posted in the Private forum, but would it not be better to make it public? Seeing your comments on GitHub is in the public domain which I have already shared on some VFP forums. If this is in the public forum I can share on ProFox/Foxite/MS VFP Forum and hopefully get a better response from a broader audience.
Will wait for your feedback, or maybe Matt can also share his thoughts?
In principle I don't see an issue with your approach as with Antlr, but we probably need more input from VFP gurus.
George, South Africa
Local loContainer as Container
Local loTextbox as TextBox
loContainer = CreateObject("Container")
* Prints 0
* Prints 1
For Each loControl In loContainer.Controls FOXOBJECT
* Prints "MYTEXTBOX" (For some reason VFP changes the name to uppercase)
Note that the FOXOBJECT clause at the end of the For Each loop is not *required*, but is something that can tell VFP it is processing a native FoxPro collection type. This make it run a little faster than in cases where you are iterating over a COM object collection or some other non-VFP type and it's a little slower as it probably requires different handling underneath the covers.
Thanks for the example but that is not what I meant, but you helped me anyway:
What I meant was something like this
DEFINE CLASS MyContainer AS Container
ADD OBJECT MyTextBox as TextBox
I tested this code and I see that it does indeed add the control to the collection
oObject = CREATEOBJECT("MyContainer")
FOR EACH oControl IN oObject.Controls
This shows that there is one control with the name MYTEXTBOX, and it does not matter if that control was added in the class definition or in code (like in your example)
So the ADD OBJECT clause in a class definition also seems to call the AddObject method.
And since that method is declared in the custom class this will work in all classes.
And this also has effect on my question 1): to support 'ADD OBJECT' the class needs to inherit from Custom or from another class with a similar AddObject() method.
If we allow classes to inherit from System.Object then we can't support this.
The ADD OBJECT clause and the AddObject() method also set the Parent property of the added object to a reference to the container. In other cases in which the object is instantiated without being added to a container, the value of the Parent property will be undefined.
They are not completely equivalent because the ADD OBJECT clause can inhibit the Init event of the added object, while the AddObject() method can't.
Some containers can add objects by setting specific properties. For instance, the second line in
m.Pgf = CREATEOBJECT("PageFrame")
m.Pgf.Pages = 2
creates two contained pages in Pgf and name them Page1 and Page2.
Base classes in VFP do not have a common ancestor, and they don't derive from Custom or any other class. Therefore, all base classes are at the top of the class hierarchy.
There is an Empty class, that does not have properties or methods at first, and that cannot be subclassed. Properties can be added to an Empty object via the ADDPROPERTY() function - not to be confused with the AddProperty() method.
You can also create objects that are not instantiations of any class by SCATTER an open cursor into an object with properties that represents the fields of the cursor.
Just some extra info here... ADD OBJECT is mostly (perhaps always) used to add a UI control to a UI class that is a container, like a Container, Form, Page, etc.
It seems to me that 99% of the code I've ever seen that has ADD OBJECT code is *generated* code from SCX or VCX assets, using an export-to-prg tool. It's often just done to create or show demo code so people can see code that works, or perhaps paste it into a prg file to run it for learning or testing purpose.
You will see a lot of example code like this in the VFP Help file, but only because that's about the only way they can show you other info about an Function or demo some other features of VFP.
In my entire app, I don't think I have a single line of ADD OBJECT code on a class in a prg. Some people may have that, but I don't think it is very common.
Of course, X# needs to handle it, I'm just trying to give you insight, that generally not many people really write UI code this way, to any large degree.
Do you know if there is an overview somewhere of the different bases classes , or better of the complete class hierarchy ?
Anyway, this thread confirms to me that FoxPro classes are like the .Net ExpandObject in the System.Dynamic namespace.
This type allows you to dynamically add and remove properties at runtime. It is like a collection Key-Value pairs: docs.microsoft.com/en-us/dotnet/api/syst...iew=netframework-4.8
So our compiler should not created fields for the properties declared in the class definition but create properties that write to the backing collection of the object.
I do know this list, but what I have not found is a diagram that shows which classes inherit from which and what the base classes in the hierarchy are. On this page everything is called "Base Classes" but I am sure that there is hierarchy in this list as well. Most likely all UI control classes inherit from Control.
I guess the easiest way to create such a diagram is to simply instantiate every class and query its ParentClass and BaseClass properties.
As you can see, there is nothing exciting here... There is no magic low-level common base class underneath them all.
This is weird.
In all UI class hierarchies that I have worked with so far there is a control class as base class for textboxes, editboxes, checkboxes etc., so the form class can iterate its controls collection and work with the common properties. This is the case in MFC, Delphi, Visual Objects, various Java environments, .Net etc. Depending on the platform this class is called CControl, TControl, Control or something like that.
I am sure that under the hood something like this is also the case for FoxPro, but apparently the FoxPro devteam has decided to hide that for their users..
In Guineu there is a class ObjectBase which is the base class of all objects