@@ -21,12 +21,14 @@ class Environment {
2121 // This only set at the top level environment. Child environments do not
2222 // copy this field.
2323 moduleBindings : Set < string > ;
24+ definedNames : Set < string > ;
2425 constructor ( source : string , enclosing : Environment | null , names : Map < string , Token > ) {
2526 this . source = source ;
2627 this . enclosing = enclosing ;
2728 this . names = names ;
2829 this . functions = new Set ( ) ;
2930 this . moduleBindings = new Set ( ) ;
31+ this . definedNames = new Set ( ) ;
3032 }
3133
3234 /*
@@ -64,6 +66,7 @@ class Environment {
6466 lookupNameParentEnvWithError ( identifier : Token ) {
6567 const name = identifier . lexeme ;
6668 let parent = this . enclosing ;
69+
6770 if ( parent === null || ! parent . names . has ( name ) ) {
6871 throw new ResolverErrors . NameNotFoundError ( identifier . line , identifier . col ,
6972 this . source ,
@@ -75,6 +78,13 @@ class Environment {
7578 }
7679 declareName ( identifier : Token ) {
7780 const lookup = this . lookupNameCurrentEnv ( identifier ) ;
81+ if ( lookup !== undefined && this . definedNames . has ( identifier . lexeme ) ) {
82+ throw new ResolverErrors . NameReassignmentError ( identifier . line , identifier . col ,
83+ this . source ,
84+ identifier . indexInSource ,
85+ identifier . indexInSource + identifier . lexeme . length ,
86+ lookup ) ;
87+ }
7888 if ( lookup !== undefined && lookup !== RedefineableTokenSentinel ) {
7989 throw new ResolverErrors . NameReassignmentError ( identifier . line , identifier . col ,
8090 this . source ,
@@ -84,6 +94,7 @@ class Environment {
8494
8595 }
8696 this . names . set ( identifier . lexeme , identifier ) ;
97+ this . definedNames . add ( identifier . lexeme ) ;
8798 }
8899 // Same as declareName but allowed to re-declare later.
89100 declarePlaceholderName ( identifier : Token ) {
@@ -304,8 +315,9 @@ export class Resolver implements StmtNS.Visitor<void>, ExprNS.Visitor<void> {
304315 visitFunctionDefStmt ( stmt : StmtNS . FunctionDef ) {
305316 this . environment ?. declareName ( stmt . name ) ;
306317 this . environment ?. functions . add ( stmt . name . lexeme ) ;
318+
307319 // Create a new environment.
308- // const oldEnv = this.environment;
320+ const oldEnv = this . environment ;
309321 // Assign the parameters to the new environment.
310322 const newEnv = new Map (
311323 stmt . parameters . map ( param => [ param . lexeme , param ] )
@@ -322,7 +334,8 @@ export class Resolver implements StmtNS.Visitor<void>, ExprNS.Visitor<void> {
322334 // Grab identifiers from that new environment. That are NOT functions.
323335 // stmt.varDecls = this.varDeclNames(this.environment.names)
324336 // Restore old environment
325- // this.environment = oldEnv;
337+ this . functionScope = null ;
338+ this . environment = oldEnv ;
326339 }
327340
328341 visitAnnAssignStmt ( stmt : StmtNS . AnnAssign ) : void {
0 commit comments