Ticket #34 (assigned defect)

Opened 4 months ago

Last modified 4 weeks ago

Compile error with both isnames and assignment on class var

Reported by: hopscc Owned by: Chuck
Priority: medium Milestone:
Component: Cobra Compiler Version: 0.8.0
Keywords: Cc:

Description

lines of this form cause a compile error

var name = 'xxx' is public # or any isname

Heres a sample program

class VarIsNameAssign
	var myVal0 is shared
	var myVal1	 = 'works'
	var myValBroke = "now not broke" is shared # 
	
	def main is shared
		assert not .myVal0 
		v = VarIsNameAssign()
		assert v.myVal1 == 'works'		
		a = v
		b = VarIsNameAssign()
		assert a is v
		assert .myValBroke == 'now not broke'	# compile error here when broken
# error: Expecting an expression. "shared" is a reserved keyword that is not expected here.		
		assert a is v
		assert a is not b

Due to use of full expr when parsing the assignment - it sucks up the 'is isnameValue' thinking its an 'isRef' check.

The compiler has code to support this (assignment and isnames) but theres no test case for it.

Attachments

var-isnames-assign.patch (2.6 kB) - added by hopscc 4 months ago.
var-is-ambig-wkround.patch (4.3 kB) - added by hopscc 7 weeks ago.

Change History

Changed 4 months ago by hopscc

  • summary changed from Compile error with both isnames and assinment on class var to Compile error with both isnames and assignment on class var

Changed 4 months ago by hopscc

Changed 4 months ago by hopscc

  • owner set to Chuck
  • status changed from new to assigned

ANd heres the patch for it
Code mods + new testfile + rel notes update

Changed 4 months ago by Chuck

"is" really is a binary boolean operator. I suppose it's unlikely to be used in initialization code, but it looks weird to me. Currently, Cobra let's you put it on a separate line which makes it more obvious what's going on:

class Foo

    # works now
    var y = 5
        is public

    # another idea
    var y = 5, is public

    # also this will eventually work:
    public
        var y = -1
        var x = -1

Also, public vars are fairly rare.

I want to think about this some more. Feel free to add comments.

Changed 4 months ago by hopscc

The problem is the use of 'is' as a binop in expressions (fine) and the use
in var decls for specifying/leadin to isNames attribs(also fine) - but given
var decl syntax mandates assignment before isnames setting theres a possible conflict in the meaning (resolved currently and wrongly now by taking the 'is' as part of the expression).

Could remove ambiguity by changing syntax to specifying isnames before assignment
i.e var decl form becomes

var <name> [as type] [is isnamelist] [ = expression]

though thats perhaps less
visually attractive (??) and possible problems with parsing rest of clauses (docstring, attribs, ??) ? - need to look at that.

Desire/Use for 'is' as part of expression in a var decl is only likely if the var decl is for a bool

var otherVarIsX as bool = anothervar is X # is private

I thought that use probability was low enough to suppress it entirely for var decls
though its not totally unlikely...

If the meaning can be disambiguated by breaking the line before the isnames setting
and its thought the is-in-assignment-expr is needed (in var decls) then perhaps its enough to trap the error caused by use of is <keyword> treated as an expression (for var decls) and change the error to mention the ambiguity and
mention the availability of the broken line (before 'is') syntax form.

I dont like the , form at all - smacks of bandaid syntax hackery .

  var y = 5, is public, shared
           ^ Huh?
                      ^ OK expected these are a poss list of isnames

I'm not fond of the broken line form either(nl+indent sometimes allowed and significant at special places (undoc) in decls) but can probably live with it
(needs doccing).

Changed 3 months ago by Chuck

The approach I want to take is:

  • make public, private, etc. keywords
  • give an informative error for "var y = 5 is public"
  • add support for saying "public" and indenting like one can do with "shared"

Changed 2 months ago by hopscc

Well thats fine as far as it goes but it still doesn't address the problem which is to allow the seemingly valid simple single line var form ( dcl var, with assignment and access modifier )....

the (single) keyword indenting clause described may be fine for multiple single isnames but wont cleanly address combinations ( shared, {public,protected,private} ... and it gets worse if const, readonly and volatile are ever supported...)

Thinking about it some more I think the patch I supplied is wrong
(disallowing 'is' completely in var assignment initialisation)
A better solution is to either change the (less common) use of 'is' in an expression for testing equivalence/aliasing

var avarEq = avar is anotherVar
var ynil = y is nil
...
  if z is nil, ...

to something else - I'd suggest 'issame'

var avarEq = avar issame anotherVar
var ynil  = y issame nil
if z issame nil, ....

( thats probably non optimal due existing use/code(!))

OR
allow a synonym for the 'is' keyword in var decls (at least, perhaps elsewhere for all isnames for consistancy) - and modify the error message when using 'is' pointing to the more verbose keyword

here I'd suggest a longer form with an is suffix e.g. 'isdecl' or 'ismade'

var y = 5 ismade public
var z = 5 isdecl shared, public

Changed 2 months ago by hopscc

  • owner changed from Chuck to hopscc

working on patch for change as described

Changed 7 weeks ago by hopscc

Changed 7 weeks ago by hopscc

  • owner changed from hopscc to Chuck

patch file for making 'isdecl' a synonym for 'is' (or vice versa) for declaring modifiers working around the ambiguity/impossibility of having a single line boxvar with both assignment and modifier specification

var x = 'defaultValue' isdecl shared, public

Test files to show original problem and highlight workaround

Changed 5 weeks ago by Chuck

I reviewed this today from top to bottom.

Recall that in Cobra visibility can be done with underscores:

    var foo   # is public
    var _foo  # is protected
    var __foo # is private

So there's one way to specify the visibility.

Additionally, "is <modifier>" can be put on the next line, the same as with types (class, struct, interface) and members (method, property, indexer). So there's another way, and it covers all modifiers.

Additionally, we'll add:

class X
    public, shared
        var x = 0

That would make for three ways.

Additionally, we'll give an informative error for "var y = 5 is public".

Overall, I didn't like the keyword synonym idea. But more importantly, the "public, shared" section idea is going to be implemented anyway, so might as well try that first.

Changed 4 weeks ago by hopscc

The problem is not (just visibility/modifiers/isnames) its specifying both that and assignment (and in a single line)

The most obvious syntax just doesnt work.

var mine = 99 is protected,shared # assignment and explicit modifier specified

Yes you can break it across lines ( if you realise thats supported - thats not obvious)
yes you can/will use modifier/visibility sections - a little baroque for a single
entry though and may get interesting for permutations.
Yes you can use the '_' syntax for some (the visibility) modifiers. Not ideal if you want to expose the visibility explicitly in code though.

Wouldnt it be better than rather than giving an informative message saying 'you cant do that that way, you have to do it this way' you just support it? (especially as to my mind its the most obvious expansion of the syntax;

var with assign, var with isnames,
var with isnames and assigned is just appending clauses together)

Is there any syntax that supports both assignment and isnames on a single line that
avoids a keyword synonym (beyond disallowing 'is' in assignment as the first patch)?
I couldnt come up with one but ...?

Is it yet possible to swap the order of the isname and assignment clauses (as mentioned above).

var xVar  as <type> is <modifiers> = <initValue> # change

That seems a little more reasonable cos the isnames binds to the variable not the
assignment value which is the impression from the current ordering

var xVar  as int = 99 is private, shared  # currently
# vs
var xVar as int is private, shared = 99
Note: See TracTickets for help on using tickets.