@@ -7,6 +7,8 @@ import { ResolverErrors } from "./errors";
77
88const levenshtein = require ( 'fast-levenshtein' ) ;
99
10+ const RedefineableTokenSentinel = new Token ( TokenType . AT , "" , 0 , 0 , 0 ) ;
11+
1012class Environment {
1113 source : string ;
1214 // The parent of this environment
@@ -72,7 +74,7 @@ class Environment {
7274 }
7375 declareName ( identifier : Token ) {
7476 const lookup = this . lookupNameCurrentEnv ( identifier ) ;
75- if ( lookup !== undefined ) {
77+ if ( lookup !== undefined && lookup !== RedefineableTokenSentinel ) {
7678 throw new ResolverErrors . NameReassignmentError ( identifier . line , identifier . col ,
7779 this . source ,
7880 identifier . indexInSource ,
@@ -82,6 +84,19 @@ class Environment {
8284 }
8385 this . names . set ( identifier . lexeme , identifier ) ;
8486 }
87+ // Same as declareName but allowed to re-declare later.
88+ declarePlaceholderName ( identifier : Token ) {
89+ const lookup = this . lookupNameCurrentEnv ( identifier ) ;
90+ if ( lookup !== undefined ) {
91+ throw new ResolverErrors . NameReassignmentError ( identifier . line , identifier . col ,
92+ this . source ,
93+ identifier . indexInSource ,
94+ identifier . indexInSource + identifier . lexeme . length ,
95+ lookup ) ;
96+
97+ }
98+ this . names . set ( identifier . lexeme , RedefineableTokenSentinel ) ;
99+ }
85100 suggestNameCurrentEnv ( identifier : Token ) : string | null {
86101 const name = identifier . lexeme ;
87102 let minDistance = Infinity ;
@@ -203,6 +218,13 @@ export class Resolver implements StmtNS.Visitor<void>, ExprNS.Visitor<void> {
203218 return ;
204219 }
205220 if ( stmt instanceof Array ) {
221+ // Resolve all top-level functions first. Python allows functions declared after
222+ // another function to be used in that function.
223+ for ( const st of stmt ) {
224+ if ( st instanceof StmtNS . FunctionDef ) {
225+ this . environment ?. declarePlaceholderName ( st . name ) ;
226+ }
227+ }
206228 for ( const st of stmt ) {
207229 st . accept ( this ) ;
208230 }
0 commit comments