gracelang / minigrace

Self-hosting compiler for the Grace programming language
39 stars 22 forks source link

Scope issues #260

Closed KimBruce closed 6 years ago

KimBruce commented 6 years ago

The order of declarations makes a difference in what is allowed in minigrace. The following code compiles and executes without error:

type SuperA = {
    type A = {a -> Number}
}

def myObject : SuperA = object {
    type A = {a -> Number}
    method m(z:Number) → Number {z+y}
    method n(y:String) → String {"hi"}
}

type A = Number

def y: Number = 2

print(myObject.m(12))

even though y is declared outside myObject and the method n of myObject uses y as a parameter name. This conflicts with the second paragraph of "Declarations" in the language spec: "It is a shadowing error to declare a parameter (but not a method or field) that has the same name as a lexically-enclosing field, method, or parameter."

However, if we change the order of declarations to:

def y: Number = 2

type SuperA = {
    type A = {a -> Number}
}

def myObject : SuperA = object {
    type A = {a -> Number}
    method m(z:Number) → Number {z+y}
    method n(y:String) → String {"hi"}
}

type A = Number

print(myObject.m(12))

we get the following error message:

Syntax error: 'y' cannot be redeclared because it is already declared in an enclosing module scope on line 1. Use a different name.

Similarly, if we move up the definition of type A:

type A = Number

type SuperA = {
    type A = {a -> Number}
}

def myObject : SuperA = object {
    type A = {a -> Number}
    method m(z:Number) → Number {z+y}
    method n(y:String) → String {"hi"}
}

def y: Number = 2

print(myObject.m(12))

we get an error: "Syntax error: 'A' cannot be redeclared because it is already declared in an enclosing module scope on line 1. Use a different name." In both cases, I believe the original code should have resulted in an error. I suspect, however, this will be tricky to fix.

apblack commented 6 years ago

Thanks for reporting this. I became aware of this while writing SmallGrace, which now does this check correctly. It's something else that needs to go into minigrace.

SmallGrace says something like:

GraceNamingError: You can't use y as the name of a parameter, because y is declared as a def on line in a surrounding scope; use a different name

apblack commented 6 years ago

I already reported this as #258. So I'm going to close this issue, to avoid duplication.