← Back to team overview

ooc-dev team mailing list archive

[ooc-dev] "Implicit As"

 

Hey there,

I'd like to suggest some possibilities to the so-called "implicit-as". Background is the migration to a String-class from plain `Char*`.
However, since C is our core backend language, interoperability is an important factor.
rofl0r wanted to have an automatic translation when one passes a String-class object to an external C function
expecting a Char*.
(The actual implementation of String is not important right now.)

In code (ooc):
    String: class {size: SizeT; data: Char*} // or whatever
    a := "hello, world" // Of type "String"
    puts: extern func(Char*) 
    puts(a)

What's the matter? Well, String won't be a 'Cover' anymore, so one can't pass a String when a Char*'s expected.

The translation process itself would consist of a simple replacement:
    puts(a)
becomes
    puts(a data)

As you can see, the user would not have to do this manually.
Issue's now how to achieve this goal. First, there was the idea to do it as an operator.
    operator implicit as (s: String) -> Char* { s data }

Well, that doesn't make much sense. It's not an action where a operator takes place. In fact, you can't see it at all, it'd be invisible. 
In my opinion, an operator is always some sort of literal as in "+, -, ++, ..." 

Another alternative would be the introduction of a new keyword, e.g. "otherwise" (don't get me on the naming).
    String: class { size: SizeT; otherwise data : Char* } // more pseudo code, yes...

The problem right here is to figure out when to fall back to the "otherwise"-case. 
"Just when an extern function expects a Char*" you might think. But that's a special case then. We'd introduce new syntax pollution for a very special case. That's wasted grammar, it needs to be more general.

There has to be a way to clearly say on which context a translation should take place.
    String: class { size: SizeT; data: Char*; context { String: this; Char*: data }}

(Yes, context is a very bad keyword, it's just used for this presentation.)
Harhar, now let's destroy this one. 
First, it works around rock's type-system. Kay, we often do in rock itself, but never in user-code.
Q: Why this?
A: Simply because the `context` section is not translated to C. It's not checked during runtime but all handled
during the process of compilation. It's an annotation.

By itself, not a too bad idea, but it makes the language and larger sources a lot more difficult to understand.
"Yay, we're passing an object of type A to a function which expects a... oh wtf - it wants to have type Z"
You can imagine the rest, and some very clever people already wrote a lot about this case. They called that source of evil C++.

Automatic transformation into another type is a ***very***, ******very******* sharp sword. Too dangerous to be given 
to the user.
"But didn't you say the "implicit-as" has to be general?" Yep, I did. And I'm coming to the conclusion that this not 
completely right. FFI is the magic word. We don't need the transformation in pure ooc-code but just when interfacing
foreign code. 
My suggestion is to introduce some sort of API which handles these cases - just for cases when interfacing with C.
It'd be done as a way of compiler annotation.

I don't give any source here because I have no idea what's the best way to do this. That's why I'm asking YOU, (yes I'm lookign right at you)
to put your opinion on the ML.

Does "implicit-as" makes sense at all?
Should it be used in everyday ooc?
Are annotation the right way to do this?
Do we need a special FFI to C?

BTW: This is not my work alone, I tried to summarize rofl0r's main idea and added suggestions on how to achieve it.

Cheers,

Yannic (showstopper)








Follow ups