Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - ckaygusu

Pages: [1]
1
General Discussion / Re: Light-weight classes
« on: May 03, 2016, 06:11:08 PM »
I've thought about this issue.

Implementing "lightweight classes" by just sugaring syntax seems doable. Only obstacle seems to be struct field shadowing, as demonstrated in the following;

Code: [Select]
type MyStruct struct {
    int foo;
}

func void foo(MyStruct* mstr {
    printf("I have calleth");
}

MyStruct mstr = { 10 };
mstr.foo()  // foo resolves to both the method and the field.

In my opinion, this is trivial and it could be easily detected at compile-time.

About inheritance though, it implies resolving method calls at runtime which I think is unacceptable.

Code: [Select]

type IMyInterface struct {

}

func void foo(*IMyInterface myint) {
     // show message and terminate program
}


type MyStruct_1 struct {
     int bar;
}

func void foo(MyStruct_1 *mystr1 {
    printf("Number ONE reporting");
}


type MyStruct_2 struct {
    int barrer;
}

func void foo(MyStruct_2 *mystr2) {
    printf("Number TWO reporting");
}

void test_1() {
     IMyInterface *myint;
     MyStruct_1 mystr = { 10 };
     myint = (*MyInterface) &mystr;
     myint.foo();  // This call can be resolved at compile-
}

void test_2(int flag) {
    IMyInterface *myint;
    if (flag) {
         MyStruct_1 mystr = { 10 };
         myint = (*IMyInterface) &mystr;
    } else {
        MyStruct_2 mystr = { 10 };
        myint = (*IMyInterface) &mystr;
    }
    myint.foo();  // This call CANNOT be resolved at compile time. Implicit code must run on runtime.
}


My final conclusion is, we can proceed with lightweight class syntax I described in the previous post. But for the time being, let's not implement inheritance.

2
General Discussion / Re: Light-weight classes
« on: April 30, 2016, 10:03:48 PM »
"Lightweight class" concept can be realized without introducing any new syntax, but for inheritance and interfaces to be convenient, I believe we need to come up with something new.

I'll briefly explain a quick and dirty little design I come up with:

Functions that is declared with the signature having it's first element a reference (pointer or not) to a structure that is defined in the same module or file are allowed to be called with the dot operator.

Code: [Select]
type Person struct {
     int age;
     char* name;
}

func void sayname(Person* person) {
     io.printf("My name is %s", person.name);
}

// Which then allows a call like this:
Person* p = { 10, "Cengiz" };
p.sayname();

Inheritance is as follows, assuming we allow anonymous nested structs (refer http://stackoverflow.com/a/1237302).

Code: [Select]
type Creature struct {
     int age;
}

func void sayAge(Creature* creature) {
    io.printf("My age is %s", creature.age);
}


type Person struct {
    struct Creature;  // anonymous struct
    char* name;
}

Person* p = { 10, "Cengiz" };
p.sayage();  // prints "My age is 10"

io.printf("Person with name %s is %d years old.", p.name, p.age);
// And no, I'm not 10 years old :)


With this scheme, even multiple inheritance should be possible.

Interfaces can be realized by using empty structs.

Code: [Select]
type IMyInterface struct {

}

func void foo(IMyInterface* intf) {
    // Call a builtin function that says this method should be overridden and halts the program.
}


type MyStruct struct {
    struct IMyInterface;
    int bar;
}

func void foo(MyStruct* strc) {
    io.printf("I have proudly implemented the interface");
}

MyStruct* strc = { 10 };
IMyInterface* intf = strc;
intf.foo();  // prints "I have proudly implemented the interface"

Regarding the last bit, we may introduce new syntax that allows anonymously allocating structs.

Code: [Select]
IMyInterface* intf = <MyStruct> { 10 };
intf.foo();

I'll later post what can go wrong with this design.

Pages: [1]