Language Extension Through Preprocessing

General discussion for topics related to the FreeBASIC project or its community.
agamemnus
Posts: 1842
Joined: Jun 02, 2005 4:48

Post by agamemnus »

TJF wrote:IMO the 'extents'/'inherits' question should be seen from a practice point of view. Which one makes it easier to translate code from the most used other languages (C/C++ ATM).

When FB can support all C/C++ features in an UDT it makes sense to have the same keyword. When an FB UDT has to get reviewed after the translation it makes sense to use another keyword.
The "basic" issue I have with that is that FB is not C/C++. It syntax style is BASIC... It's even easier to translate from/to FB/C++ if the syntax was exactly the same. :P



marcov wrote:Well, I'm biased of course, but if you recycle class, you can use parentheses:
Descendant = class(parentclass)
or
Descendant = interface(parentinterface)

abstract and similar keywords (sealed, deprecated,platform,abstract) appear before class/interface kw.
There is no specific use for either class or interface yet... can't call it recycled quite yet! Anyway, where exactly would you implement this? Like this?

Code: Select all

type mytype = class(myparenttype)
...
end type
It wouldn't look pretty with both that and a "FIELD=" statement.
angros47
Posts: 2323
Joined: Jun 21, 2005 19:04

Post by angros47 »

I, too, voe for EXTENDS: it will make porting code from RapidQ easier.

In RapidQ, OOP features were very well done: powerful enough, but much easier to use than c++.

I'm glad to see that FreeBasic is going on the same path.

Thank you, V1ctor!
marcov
Posts: 3462
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Post by marcov »

agamemnus wrote:
marcov wrote:Well, I'm biased of course, but if you recycle class, you can use parentheses:
Descendant = class(parentclass)
or
Descendant = interface(parentinterface)

abstract and similar keywords (sealed, deprecated,platform,abstract) appear before class/interface kw.
There is no specific use for either class or interface yet... can't call it recycled quite yet! Anyway, where exactly would you implement this? Like this?

Code: Select all

type mytype = class(myparenttype)
...
end type
It wouldn't look pretty with both that and a "FIELD=" statement.
Field= ?
agamemnus
Posts: 1842
Joined: Jun 02, 2005 4:48

Post by agamemnus »

Type typename [ Field = alignment ]

http://www.freebasic.net/wiki/wikka.php ... KeyPgField
marcov
Posts: 3462
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Post by marcov »

agamemnus wrote:Type typename [ Field = alignment ]

http://www.freebasic.net/wiki/wikka.php ... KeyPgField
That's a problem either way IMHO. From keywords to name-value pairs.

I don't see why it would be worse in the class (xx) then in the extends case.
qbworker
Posts: 73
Joined: Jan 14, 2011 2:34

Post by qbworker »

I downloaded the svn daily build from freebasic.de and v1ctor's example won't work on it. It throw these errors:
  • type.bas(13) error 18: Syntax error, found 'extends' in 'type TBase extends TObject'
    type.bas(32) error 18: Syntax error, found 'extends' in 'type TDerived extends TBase'
    type.bas(36) error 208: An ENUM, TYPE or UNION cannot be empty, found 'end' in 'end type'
    type.bas(40) error 41: Variable not declared, base in 'base.value = v'
    type.bas(41) error 41: Variable not declared, value in 'value = v '' --- also works, base symbols were imported'
    type.bas(46) error 213: Symbol not a CLASS, ENUM, TYPE or UNION type, before '.' in 'base.thing()'
    type.bas(47) error 213: Symbol not a CLASS, ENUM, TYPE or UNION type, before '.' in 'base.base.thing()'
    type.bas(60) error 21: Type mismatch, before ')' in 'cast( TBase, d ).thing()'
It may be that the daily build doesn't work, IDK. Keep up the good work.
MOD
Posts: 555
Joined: Jun 11, 2009 20:15

Post by MOD »

The daily svn build on FreeBASIC-Portal.de does not compile branches. It have to be merged first. So long you have to merge and compile it by yourself.
agamemnus
Posts: 1842
Joined: Jun 02, 2005 4:48

Post by agamemnus »

Here is another issue with "extends" that I couldn't articulate till I saw another example of its usage:

cat extends animal

In English, when you "extend" something, you build onto it in some fashion.

The cat UDT does not extend the animal UDT -- the animal UDT remains unchanged -- the cat UDT only extends the animal UDT in the scope of the cat UDT. That's silly though... it's simpler to say that it "inherits" the animal UDT functions and variables. :-)
AGS
Posts: 1284
Joined: Sep 25, 2007 0:26
Location: the Netherlands

Post by AGS »

OOP can be done using the Gobject library. The programming language Vala uses GObject to implement OOP.

The Vala compiler turns Vala code into C (and gcc turns the generated C code into an executable).

I'll give an example of Vala code and the C code generated by the Vala compiler.

Input (Vala)

Code: Select all

class Person : Object {
    private int _age = 32;  // underscore prefix to avoid name clash with property

    /* Property */
    public int age {
        get { return _age; }
        set { _age = value; }
    }
}

void main()
{
  
  var my_person = new Person();
  my_person.age = 23;
}
  
Output (C)

Code: Select all

/* class.c generated by valac, the Vala compiler
 * generated from class.vala, do not modify */


#include <glib.h>
#include <glib-object.h>


#define TYPE_PERSON (person_get_type ())
#define PERSON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PERSON, Person))
#define PERSON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PERSON, PersonClass))
#define IS_PERSON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PERSON))
#define IS_PERSON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PERSON))
#define PERSON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PERSON, PersonClass))

typedef struct _Person Person;
typedef struct _PersonClass PersonClass;
typedef struct _PersonPrivate PersonPrivate;
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))

struct _Person {
	GObject parent_instance;
	PersonPrivate * priv;
};

struct _PersonClass {
	GObjectClass parent_class;
};

struct _PersonPrivate {
	gint _age;
};


static gpointer person_parent_class = NULL;

GType person_get_type (void) G_GNUC_CONST;
#define PERSON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_PERSON, PersonPrivate))
enum  {
	PERSON_DUMMY_PROPERTY,
	PERSON_AGE
};
Person* person_new (void);
Person* person_construct (GType object_type);
gint person_get_age (Person* self);
void person_set_age (Person* self, gint value);
static void person_finalize (GObject* obj);
static void person_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec);
static void person_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec);
void _vala_main (void);



Person* person_construct (GType object_type) {
	Person * self;
	self = (Person*) g_object_new (object_type, NULL);
	return self;
}


Person* person_new (void) {
	return person_construct (TYPE_PERSON);
}


gint person_get_age (Person* self) {
	gint result;
	g_return_val_if_fail (self != NULL, 0);
	result = self->priv->_age;
	return result;
}


void person_set_age (Person* self, gint value) {
	g_return_if_fail (self != NULL);
	self->priv->_age = value;
	g_object_notify ((GObject *) self, "age");
}


static void person_class_init (PersonClass * klass) {
	person_parent_class = g_type_class_peek_parent (klass);
	g_type_class_add_private (klass, sizeof (PersonPrivate));
	G_OBJECT_CLASS (klass)->get_property = person_get_property;
	G_OBJECT_CLASS (klass)->set_property = person_set_property;
	G_OBJECT_CLASS (klass)->finalize = person_finalize;
	g_object_class_install_property (G_OBJECT_CLASS (klass), PERSON_AGE, g_param_spec_int ("age", "age", "age", G_MININT, G_MAXINT, 0, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE));
}


static void person_instance_init (Person * self) {
	self->priv = PERSON_GET_PRIVATE (self);
	self->priv->_age = 32;
}


static void person_finalize (GObject* obj) {
	Person * self;
	self = PERSON (obj);
	G_OBJECT_CLASS (person_parent_class)->finalize (obj);
}


GType person_get_type (void) {
	static volatile gsize person_type_id__volatile = 0;
	if (g_once_init_enter (&person_type_id__volatile)) {
		static const GTypeInfo g_define_type_info = { sizeof (PersonClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) person_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Person), 0, (GInstanceInitFunc) person_instance_init, NULL };
		GType person_type_id;
		person_type_id = g_type_register_static (G_TYPE_OBJECT, "Person", &g_define_type_info, 0);
		g_once_init_leave (&person_type_id__volatile, person_type_id);
	}
	return person_type_id__volatile;
}


static void person_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) {
	Person * self;
	self = PERSON (object);
	switch (property_id) {
		case PERSON_AGE:
		g_value_set_int (value, person_get_age (self));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}


static void person_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) {
	Person * self;
	self = PERSON (object);
	switch (property_id) {
		case PERSON_AGE:
		person_set_age (self, g_value_get_int (value));
		break;
		default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
		break;
	}
}


void _vala_main (void) {
	Person* my_person;
	my_person = person_new ();
	person_set_age (my_person, 23);
	_g_object_unref0 (my_person);
}


int main (int argc, char ** argv) {
	g_type_init ();
	_vala_main ();
	return 0;
}
That's 15 lines of code written in a language that looks a bit like C translated into over 150 lines of C code.

You could use FreeBASIC in combination with the GObject library to get some kind of OOP going.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Post by fxm »

agamemnus wrote:Here is another issue with "extends" that I couldn't articulate till I saw another example of its usage:

cat extends animal

In English, when you "extend" something, you build onto it in some fashion.

The cat UDT does not extend the animal UDT -- the animal UDT remains unchanged -- the cat UDT only extends the animal UDT in the scope of the cat UDT. That's silly though... it's simpler to say that it "inherits" the animal UDT functions and variables. :-)
- Some ideas of syntax (my favorite in bold):
'cat extends animal' from Java
'cat : animal' from C#
'cat inherits animal' from VB
'cat(animal)' from Python
'cat < animal' from Ruby
marcov
Posts: 3462
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Post by marcov »

fxm wrote:
The cat UDT does not extend the animal UDT -- the animal UDT remains unchanged -- the cat UDT only extends the animal UDT in the scope of the cat UDT. That's silly though... it's simpler to say that it "inherits" the animal UDT functions and variables. :-)
- Some ideas of syntax (my favorite in bold):
'cat extends animal' from Java
'cat : animal' from C#
'cat inherits animal' from VB
'cat(animal)' from Python
'cat < animal' from Ruby
(it would be nice to see how this set of languages deals with multiple inheritance (interface based or straight)

Delphi adds interfaces after the class

cat = class(animal, furrything)

where animal will be the ancestor, and furrything an interface(=+/- abstract class) implemented by cat,
Last edited by marcov on Apr 02, 2011 19:18, edited 2 times in total.
fxm
Moderator
Posts: 12107
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Post by fxm »

Anyway, this is no big deal, because if 'extends' is finally chosen (probably), the fiercest partisans of 'inherits' can always insert at the top of their source:
#define inherits extends
marcov
Posts: 3462
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Post by marcov »

fxm wrote:Anyway, this is no big deal, because if 'extends' is finally chosen (probably), the fiercest partisans of 'inherits' can always insert at the top of their source:
#define inherits extends
If it is no big deal, we can go with inherits :-)
sir_mud
Posts: 1401
Joined: Jul 29, 2006 3:00
Location: US
Contact:

Post by sir_mud »

The extends syntax better describes what should be happening, in my opinion. The whole point is a more specialized version of the base class.
TheMG
Posts: 376
Joined: Feb 08, 2006 16:58

Post by TheMG »

I agree with agamemnus. Extend sounds like you are modifying the original in some way, inherit makes it clear that there is a new class that takes on the properties of the old one.
Post Reply