crystal-lang / crystal

The Crystal Programming Language
https://crystal-lang.org
Apache License 2.0
19.49k stars 1.62k forks source link

Ability to type-annotate class vars #1838

Closed waterlink closed 8 years ago

waterlink commented 9 years ago

Example:

module Example
  @@stuff :: String
  @@counter :: Int64
end

Currently it produces error unexpected token ::: http://carc.in/#/r/l5x

jhass commented 9 years ago

But :: isn't for type annotations, at least atm., it's for preallocations.

asterite commented 9 years ago

@jhass Not quite (scroll to the bottom). I think that's the main confusion: at a class level they determine the type, but inside a method they just declare the data without zero-initializing it.

For the next compiler we'll need these annotations, and we'll need them for global variables too:

$x :: Int32
asterite commented 9 years ago

@jhass For example: http://play.crystal-lang.org/#/r/l9g

jhass commented 9 years ago

Well, that sucks tbh. and is really confusing indeed. We really do need to find a better distinction between allocation and annotation then. I would argue that at the class level they don't annotate the type then, or rather that it's the wrong term. They do restrict it, so consistency would be achieved by using : instead, like in method definitions.

That the AST node is still called DeclareVar doesn't help anything either. http://play.crystal-lang.org/#/r/l9p

asterite commented 9 years ago

You are right in every point :-)

And yes, because they'll be more common we'll probably use : instead of ::.

What name would you use instead of DeclareVar? Maybe TypeAnnotation? The current one should probably be renamed to UnsafeDeclareVar or something like that.

jhass commented 9 years ago

Well, we call them restriction in method definitions, right? Why not keep that term, TypeRestriction. Doesn't fit well into them being mandatory I guess, but you know I'll hate that fact anyhow.

waterlink commented 9 years ago

Just some ideas to put on the table:

ozra commented 9 years ago

I like the connotation of TypeAnnotation. The deeper semantic meaning could stay out of AST-Node-naming since it might be sleaker in AST-mutating macros. But that's a weak argument for it, I admit.

And on the allocation issue, I still feel that in methods, the type annotation should be just that - restriction annotation - not allocating in any way. @jhass had some ideas in an issue - was it #1824? I'd take any idea over just seeing a type annotated var as being allocated before that has been explicitly expressed (assign is implicitly allocation of course, but could be just allocating space for a reference).

Distinguishing between "needing a copy, not a reference" and the actual storage allocation method would be desirable. That's a compiler optimization detail (stack or GC? or even another scope-based method..), while the distinction between having a copy or a reference is important in program semantics.

asterite commented 8 years ago

In 8ae45d56088b48ff8f5531942ad21258d5ab840d (and the previous commit) the name of the AST node was changed to TypeDeclaration, and a new node UninitializedVar was introduced, so at least now names and syntax are more consistent and their meaning is more clear.

We still miss type annotations for class and global variables, these will come soon.