FoxPro syntax, Properties and fields

This forum is meant for questions about the Visual FoxPro Language support in X#.

atlopes
Posts: 83
Joined: Sat Sep 07, 2019 11:43 am
Location: Portugal

FoxPro syntax, Properties and fields

Post by atlopes »

Robert,

The list of VFP base classes can be found in https://docs.microsoft.com/en-us/previo ... d(v=vs.80) - I hope the link gets through correctly.
User avatar
lumberjack
Posts: 727
Joined: Fri Sep 25, 2015 3:11 pm
Location: South Africa

FoxPro syntax, Properties and fields

Post by lumberjack »

Takes some time, but I think in the same group THIS is also a good starting point to browse
______________________
Johan Nel
Boshof, South Africa
FoxProMatt

FoxPro syntax, Properties and fields

Post by FoxProMatt »

@atlopes -
The ADD OBJECT clause is fundamental to the definition of complex objects in non-visual code and may have nothing to do with UI. You can find a few examples of extensive use of this in VFPX.
Please give me a couple of example projects that you are referring to?
User avatar
robert
Posts: 4520
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

FoxPro syntax, Properties and fields

Post by robert »

Antonio,
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.

Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
FoxProMatt

FoxPro syntax, Properties and fields

Post by FoxProMatt »

I guess the easiest way to create such a diagram is to simply instantiate every class and query its ParentClass and BaseClass properties.
I tested this in VFP for you on about 10 classes:

As you can see, there is nothing exciting here... There is no magic low-level common base class underneath them all.

I give you the VFP code at the end in case you want to test further...

Code: Select all

Class: Textbox ParentClass: Textbox BaseClass: Textbox 
Class: Container ParentClass: Container BaseClass: Container 
Class: Form ParentClass: Form BaseClass: Form 
Class: Grid ParentClass: Grid BaseClass: Grid 
Class: Page ParentClass: Page BaseClass: Page
Class: Column ParentClass: Column BaseClass: Column
Class: Checkbox ParentClass: Checkbox BaseClass: Checkbox
Class: Collection ParentClass: Collection BaseClass: Collection
Class: Editbox ParentClass: Editbox BaseClass: Editbox
Class: Control ParentClass: Control BaseClass: Control
Class: Custom ParentClass: Custom BaseClass: Custom


Here's the VFP code:

Code: Select all

oClasses = CreateObject("Collection")

oClasses.Add('Textbox')
oClasses.Add('Container')
oClasses.Add('Form')
oClasses.Add('Grid')
oClasses.Add('Page')
oClasses.Add('Column')
oClasses.Add('Checkbox')
oClasses.Add('Collection')
oClasses.Add('Editbox')
oClasses.Add('Control')

oClasses.Add('Custom') 
oClasses.Add('Empty') &&Causes error accessing the .Class property

For Each cClass in oClasses
	
	oObject = CreateObject(cClass)
	? "Class: " + cClass + "   ParentClass: " + oObject.Class + "   BaseClass: " + oObject.BaseClass

EndFor

User avatar
robert
Posts: 4520
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

FoxPro syntax, Properties and fields

Post by robert »

Matt,
Thanks.
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

Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
atlopes
Posts: 83
Joined: Sat Sep 07, 2019 11:43 am
Location: Portugal

FoxPro syntax, Properties and fields

Post by atlopes »

Yes, Robert, all VFP base classes are at the top of the class hierarchy.

Another key aspect that will require specific "hidden" behavior is the containership rules for the classes that have the capability. The list of container-type classes and the containership rules can be found in https://docs.microsoft.com/en-us/previo ... 3dvs.71%29.
atlopes
Posts: 83
Joined: Sat Sep 07, 2019 11:43 am
Location: Portugal

FoxPro syntax, Properties and fields

Post by atlopes »

Matt,

On top of my head, all of the projects that I submitted to VFPX. I'll have to check if others, too.

You can find extensive use of the ADD OBJECT clause in overHere, a library of classes to access and operate with the Here.com location platform web services.
User avatar
lumberjack
Posts: 727
Joined: Fri Sep 25, 2015 3:11 pm
Location: South Africa

FoxPro syntax, Properties and fields

Post by lumberjack »

Hi Robert,

Post from the MS FoxPro forum by Tom Knauf:

Just some thoughts on that :

to my opinion the ultimate class is "empty". You can only use addproperty() to add propertys, optional with an initial value.

Here is a short example for an application object holding global variables :

oapp = newobject("empty") && new object (instance) of empty

addprop(oapp,"appname","Test") && adds a property of type char, value "Test"

addprop(oapp,"xversion",4711) && adds a property of type int, value 4711

addprop(oapp."activeuser","Tom")

Now this works

? oapp.xversion

oapp.activeuser = "Tim"

Unfortunately :-) this works, too : oapp.xversion = "Oh, now a char"

The value of a property can also be another object which has own propertys. So you can have an object of type form and use addprop() or GUI to add a property with another form and its propertys.

In foxpro terms fields are part of tables or cursors, propertys are propertys :-), this may confuse foxpro programmers and c# programmer

There is a commandpair scatter / gather which may cause confusion, too :

use adress

scatter memo name oadress && now you have an object oadress with all fieldnames as propertynames filled with the values of the fields

oadress.lastact = date() && set value of property lastact to current date

gather memo name oadress && write all values back to table

Sometimes we use addproperty to extend the "dataobject" built with scatter into a "businessobject" holding values not part of the table.

Regards

tom

BTW : scatter / gather is one of the commands I REALLY like and which I miss in .NET.

(yes I know LINQ, entity framework,... Thinks are getting better in .NET. Slowly.)
______________________
Johan Nel
Boshof, South Africa
mainhatten
Posts: 200
Joined: Wed Oct 09, 2019 6:51 pm

FoxPro syntax, Properties and fields

Post by mainhatten »

Hi Robert,

most of the questions already have been answered.
2) The FoxPro class syntax speaks of "Properties" and not of "Fields" or "Instance variables"

Code: Select all

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:

Code: Select all

DEFINE CLASS Animal as custom
Species    = "Animal"
ENDDEFINE

DEFINE CLASS Dog AS Animal
Species    = "Dog"
ENDDEFINE
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:

Code: Select all

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

Code: Select all

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:

Code: Select all

[[PROTECTED | HIDDEN] PropertyName1, PropertyName2 ...] [AS DataType]
I envision Foxpro "Classes" to work more like Javascript prototypal inheritance, only castrated insofar as you cannot access, redirect and/or monkeypatch the prototype hierarchy.
Consider:

Code: Select all

clear
=test(.f.)
=test(.t.)

? "Does not look unreasonable..."
clear ALL
release All
? "And Now for Something Completely Different"
? "Proof: Wolf reads prototype Mammal, Poodle reads prototype Dog"
=test(.t.)

FUNCTION test(tlFlag)
local laClassNames[1], lcClasses, lnCnt, lnRun
lcClasses = "mammal,canine,wolf,dog,poodle"
lnCnt = alines(laClassNames, m.lcClasses,5,",")
for lnRun = 1 to m.lnCnt
	= choir(laClassNames[IIF(m.tlFlag, m.lnRun, m.lnCnt+1-m.lnRun)])
next

FUNCTION choir(tcClass)
local loSinger, lcSound
loSinger = CREATEOBJECT(m.tcClass)
lcSound =loSinger.bark()
wait window m.lcSound timeout 2
? m.lcSound

define CLASS mammal as Custom
	cSound = "meeep"
	nProto = SECONDS()
	nInitM = 0

	FUNCTION Init()
		this.nInitM = SECONDS()
		
	FUNCTION bark()
		return STR(this.nProto, 12,3) ;
		+ STR(this.nInitM, 12,3) ;
		+ " : " + this.Class

ENDDEFINE

define CLASS canine as mammal
	cSound = "wuff"
ENDDEFINE

define CLASS wolf as canine 
	cSound = "hoooowl"
enddefine

define CLASS dog as canine 
	nProto = SECONDS()
enddefine

define CLASS poodle as dog
	cSound = "wack"
enddefine
As most of Javascript shenanigans like mixins, monkeypatching and so on are disabled in vfp so that classic inheritance is mirrored closely, go for the code compiling to the fastest IL
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 ?
Addproperty() function and method add a name to the NTI of the object, which can be filled with any vfp data type, including objects.
ADD OBJECT and .addobject() add an object to the name, set .parent property in the abject to be added (build a "container" hierarchy) and add the same object ot the .objects collection. I am 90% certain that there is only 1 such collection in each container class, which you can access via .objects in all containers and via another property, named after the "possible" class type ("Controls" for Form and container, "Buttons" in Commandgroup and Optiongroup, "Pages" in Pageframe and so on.
I have never checked if those 2 names point to the same collection or if I can tweak them differently - I saw never a real reason for having either 2 names/pointers and an identical collection or 2 different collections....
ADD OBJECT and .addobject() added objects get their destroy called automatically, objects added via addproperty needing their .destroy to be manually called to prevent memory leaks (if linked ito other structures...) must be handled in code.
The special containers for a single GUI class control the # of their children via special ????count properties having assign methods- increasing them calls .addobject on the .memberclass [ ¦ of .memberclasslibrary].
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

Code: Select all

DEFINE CLASS MyStack<T> WHERE T IS NEW()
- All types can be specified in the Namespace.Type syntax. For example

Code: Select all

CLASS MyTable as System.Data.DataTable
I saw in Johans code that in other dialects you can assign methods like

Code: Select all

CLASS MyFirstXSharpForm INHERIT Form 
  CONSTRUCTOR()
    SUPER()
    Size := Size{100, 100} // Check if it is not dimension, out of top of my head
    Text := "My first XSharp Form"
    VAR btn := Button{}
    btn:Text := "Close"
    btn:Location := Point{5,5}
    btn:Click := MyButtonClick  // what the click event will fire
    SELF:Controls:Add(btn)
  RETURN
  METHOD MyButtonClick(o AS OBJECT, e AS EventArgs) AS VOID
    SELF:Close()
  RETURN
END CLASS
Assigning functions/methods and perhaps passing the function itself, not the result as parameter are already things tempting me to switch - I see the benefit of such constructs in Javascriot and Python. Vfp as a language has grown only minimally and shows its age, although it gained at least some modern ideas in eventbinding and Cursoradapter. And it would be nice to tweak the speed without going down into C - I am too old for that. You already have quite a lot - but IMO the real test for the vfp runtime will be in the area of

-set("buffermode"), set("datasession"), sys(3054)
-functions tableupdate/tablerevert, getfldstate, cursorset/getprop, getcursoradapter, curval, oldval, sqlset/getprop
-objects session, cursor, datasession and cursoradapter (I prefer them to remote views)

-Solid SQL on disc-based tables(dbf, cursor, view)
-including basic optimizer able to create missing indices on temp results of multiple joins and bitmap speedup
-most of last decades SQL server in the SQL language scope except CTE and merge/upsert logic (- but no real Replication)

as that is IMO the special sauce in vfp not found in any other language - using client disc as SQL cache to minimize network calls.
Use ANY SQL server as RW datastore,
mix in RO data kept locally via SQL as biz layer with the ability to persist or throw away local changes
bind to any GUI with a well layered architecture but still without the need to employ ORM for your data

Also almost all tools make extensive use of local tables, often via SQL.

my 2.22€ (have thought about this for some time...)

thomas
Post Reply