ソースを参照

Improved declarations code

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@7050 8c9fc860-2736-0410-a75d-ab315db34111
felixf 8 年 前
コミット
41cfc1629d
1 ファイル変更85 行追加111 行削除
  1. 85 111
      source/FoxSemanticChecker.Mod

+ 85 - 111
source/FoxSemanticChecker.Mod

@@ -1035,11 +1035,11 @@ TYPE
 						Error(position, "invalid inheritance of disposable types");
 					END;
 				END;
-				Declarations(x.recordScope, FALSE, FALSE, TRUE);
+				Declarations(x.recordScope, FALSE, {0});
 				
 				x.SetState(SyntaxTree.Resolved);
 				
-				Declarations(x.recordScope, FALSE, TRUE, FALSE);
+				Declarations(x.recordScope, FALSE, {1});
 
 				ResolveArrayStructure(x);
 
@@ -1211,7 +1211,7 @@ TYPE
 					END;
 				CheckModifiers(modifier, FALSE);
 
-				Declarations(x.cellScope, SkipImplementation(x),TRUE,TRUE);
+				Declarations(x.cellScope, SkipImplementation(x),{0,1});
 				
 				(* process parameters *)
 				prev := currentScope;
@@ -6996,7 +6996,7 @@ TYPE
 				ELSIF procedure.isConstructor THEN
 					Error(procedure.position,"procedure illegaly marked as initializer - not in object scope");
 				END;
-				Declarations(procedure.procedureScope, FALSE, TRUE,TRUE);
+				Declarations(procedure.procedureScope, FALSE, {0,1});
 				(* body resolution part done as late fix of the procedure type *)
 				procedure.SetState(SyntaxTree.Resolved);
 				currentIsRealtime := recentIsRealtime;
@@ -8310,8 +8310,11 @@ TYPE
 			after declaration check, bodies are entered into the global list of implementations that remain to be resolved after all declarations.
 
 			Declarations depend on other declarations, this procedure is neither thread safe not would it be wise to try concurrency here
+			phases : 
+				0 = before procedures
+				1 = procedures and later
 		**)
-		PROCEDURE Declarations(scope: SyntaxTree.Scope; skipImplementation: BOOLEAN; procedures, nonProcedures: BOOLEAN);
+		PROCEDURE Declarations(scope: SyntaxTree.Scope; skipImplementation: BOOLEAN; phases: SET);
 		VAR
 			constant: SyntaxTree.Constant;
 			typeDeclaration: SyntaxTree.TypeDeclaration;
@@ -8382,134 +8385,105 @@ TYPE
 			currentScope := scope;
 			error := FALSE;
 			
-			IF nonProcedures THEN
-			(* first enter all symbols in scope *)
-			IF scope IS SyntaxTree.ModuleScope THEN
-				(* treat imports first for a module scope, , set default context if necessary *)
-				import := scope(SyntaxTree.ModuleScope).firstImport;
-				WHILE(import # NIL) DO
-					IF import.context = SyntaxTree.invalidIdentifier THEN import.SetContext(scope.ownerModule.context) END;
-					Register(import, currentScope, FALSE);
-					import := import.nextImport;
-				END;
-				import := scope(SyntaxTree.ModuleScope).firstImport;
-				WHILE(import # NIL) DO (* 2nd stage to avoid duplicate symbol *)
-					ResolveSymbol(import);
-					import := import.nextImport;
-				END;
-			ELSIF scope IS SyntaxTree.ProcedureScope THEN
-				(* enter parameters for a procedure scope *)
-				procedureType := scope(SyntaxTree.ProcedureScope).ownerProcedure.type.resolved(SyntaxTree.ProcedureType);
-				parameter := procedureType.firstParameter;
-				WHILE(parameter # NIL) DO
-					Register(parameter,currentScope, FALSE); parameter := parameter.nextParameter;
-				END;
-				parameter := procedureType.returnParameter;
-				IF parameter # NIL THEN Register(parameter, currentScope, FALSE); END;
-				parameter := procedureType.selfParameter;
-				IF parameter # NIL THEN 
-					Register(parameter, currentScope, FALSE); 
-					parameter.SetState(SyntaxTree.Resolved); (* would lead to cycles, otherwise *)
-				END;
-			ELSIF scope IS SyntaxTree.CellScope THEN
-				DeclareCell(scope(SyntaxTree.CellScope).ownerCell);
-				IF~skipImplementation THEN
-					import := scope(SyntaxTree.CellScope).firstImport;
+			IF 0 IN phases THEN
+				(* first enter all symbols in scope *)
+				IF scope IS SyntaxTree.ModuleScope THEN
+					(* treat imports first for a module scope, , set default context if necessary *)
+					import := scope(SyntaxTree.ModuleScope).firstImport;
 					WHILE(import # NIL) DO
 						IF import.context = SyntaxTree.invalidIdentifier THEN import.SetContext(scope.ownerModule.context) END;
 						Register(import, currentScope, FALSE);
 						import := import.nextImport;
 					END;
-					import := scope(SyntaxTree.CellScope).firstImport;
+					import := scope(SyntaxTree.ModuleScope).firstImport;
 					WHILE(import # NIL) DO (* 2nd stage to avoid duplicate symbol *)
 						ResolveSymbol(import);
 						import := import.nextImport;
 					END;
-				END;
-			END;
-			IF error THEN RETURN END;
-
-			IF skipImplementation THEN
-				scope.Clear;
-			END;
-		
-			(* constants *)
-			constant := scope.firstConstant;
-			WHILE (constant # NIL) DO
-				Register(constant, currentScope, FALSE); constant := constant.nextConstant;
-			END;
-			(* type declarations *)
-			typeDeclaration := scope.firstTypeDeclaration;
-			WHILE (typeDeclaration # NIL) DO
-				Register(typeDeclaration, currentScope, FALSE); typeDeclaration := typeDeclaration.nextTypeDeclaration;
-			END;
-			(* variables *)
-			variable := scope.firstVariable;
-			WHILE (variable # NIL) DO
-				Register(variable, currentScope, FALSE); variable := variable.nextVariable;
-			END;
-			(* procedures *)
-			IF scope.procedures # NIL THEN
-				FOR i := 0 TO scope.procedures.Length()-1 DO
-					procedure := scope.procedures.GetProcedure(i);
-					procedureType := procedure.type.resolved(SyntaxTree.ProcedureType);
-					IF procedureType.selfParameter = NIL THEN
-						scope.AddProcedure(procedure);
-						Register(procedure, currentScope, procedure IS SyntaxTree.Operator);
-					ELSE
-						typeDeclaration := currentScope.FindTypeDeclaration(procedureType.selfParameter.type(SyntaxTree.QualifiedType).qualifiedIdentifier.suffix);
-						IF typeDeclaration = NIL THEN 
-							Error(procedureType.selfParameter.position, "No such type declaration");
-						ELSE
-							procedureType.selfParameter.type(SyntaxTree.QualifiedType).SetResolved(typeDeclaration.declaredType.resolved);
-							procedureType.selfParameter.SetState(SyntaxTree.Resolved);
-							typeDeclaration.declaredType(SyntaxTree.RecordType).recordScope.AddProcedure(procedure);
-							Register(procedure, typeDeclaration.declaredType(SyntaxTree.RecordType).recordScope, procedure IS SyntaxTree.Operator);
+				ELSIF scope IS SyntaxTree.ProcedureScope THEN
+					(* enter parameters for a procedure scope *)
+					procedureType := scope(SyntaxTree.ProcedureScope).ownerProcedure.type.resolved(SyntaxTree.ProcedureType);
+					parameter := procedureType.firstParameter;
+					WHILE(parameter # NIL) DO
+						Register(parameter,currentScope, FALSE); parameter := parameter.nextParameter;
+					END;
+					parameter := procedureType.returnParameter;
+					IF parameter # NIL THEN Register(parameter, currentScope, FALSE); END;
+					parameter := procedureType.selfParameter;
+					IF parameter # NIL THEN 
+						Register(parameter, currentScope, FALSE); 
+						parameter.SetState(SyntaxTree.Resolved); (* would lead to cycles, otherwise *)
+					END;
+				ELSIF scope IS SyntaxTree.CellScope THEN
+					DeclareCell(scope(SyntaxTree.CellScope).ownerCell);
+					IF~skipImplementation THEN
+						import := scope(SyntaxTree.CellScope).firstImport;
+						WHILE(import # NIL) DO
+							IF import.context = SyntaxTree.invalidIdentifier THEN import.SetContext(scope.ownerModule.context) END;
+							Register(import, currentScope, FALSE);
+							import := import.nextImport;
+						END;
+						import := scope(SyntaxTree.CellScope).firstImport;
+						WHILE(import # NIL) DO (* 2nd stage to avoid duplicate symbol *)
+							ResolveSymbol(import);
+							import := import.nextImport;
 						END;
 					END;
 				END;
-			END;
-			END;
-			(*
-			procedure := scope.firstProcedure;
-			WHILE (procedure # NIL) DO
-				procedureType := procedure.type.resolved(SyntaxTree.ProcedureType);
-				IF procedureType.selfParameter = NIL THEN
-					Register(procedure, currentScope, procedure IS SyntaxTree.Operator);
-				END;
-				procedure := procedure.nextProcedure;
-			END;
-			*)
+				IF error THEN RETURN END;
 
-			(* type bound procedures *)
-			(*
-			procedure := scope.firstProcedure;
-			WHILE (procedure # NIL) DO
-				procedureType := procedure.type.resolved(SyntaxTree.ProcedureType);
-				IF procedureType.selfParameter # NIL THEN
-					typeDeclaration := currentScope.FindTypeDeclaration(procedureType.selfParameter.type(SyntaxTree.QualifiedType).qualifiedIdentifier.suffix);
-					IF typeDeclaration = NIL THEN 
-						Error(procedureType.selfParameter.position, "No such type declaration");
-					ELSE
-						procedureType.selfParameter.type(SyntaxTree.QualifiedType).SetResolved(typeDeclaration.declaredType.resolved);
-						procedureType.selfParameter.SetState(SyntaxTree.Resolved);
+				IF skipImplementation THEN
+					scope.Clear;
+				END;
+			
+				(* constants *)
+				constant := scope.firstConstant;
+				WHILE (constant # NIL) DO
+					Register(constant, currentScope, FALSE); constant := constant.nextConstant;
+				END;
+				(* type declarations *)
+				typeDeclaration := scope.firstTypeDeclaration;
+				WHILE (typeDeclaration # NIL) DO
+					Register(typeDeclaration, currentScope, FALSE); typeDeclaration := typeDeclaration.nextTypeDeclaration;
+				END;
+				(* variables *)
+				variable := scope.firstVariable;
+				WHILE (variable # NIL) DO
+					Register(variable, currentScope, FALSE); variable := variable.nextVariable;
+				END;
+				(* procedures *)
+				IF scope.procedures # NIL THEN
+					FOR i := 0 TO scope.procedures.Length()-1 DO
+						procedure := scope.procedures.GetProcedure(i);
+						procedureType := procedure.type.resolved(SyntaxTree.ProcedureType);
+						IF procedureType.selfParameter = NIL THEN
+							scope.AddProcedure(procedure);
+							Register(procedure, currentScope, procedure IS SyntaxTree.Operator);
+						ELSE
+							typeDeclaration := currentScope.FindTypeDeclaration(procedureType.selfParameter.type(SyntaxTree.QualifiedType).qualifiedIdentifier.suffix);
+							IF typeDeclaration = NIL THEN 
+								Error(procedureType.selfParameter.position, "No such type declaration");
+							ELSE
+								procedureType.selfParameter.type(SyntaxTree.QualifiedType).SetResolved(typeDeclaration.declaredType.resolved);
+								procedureType.selfParameter.SetState(SyntaxTree.Resolved);
+								typeDeclaration.declaredType(SyntaxTree.RecordType).recordScope.AddProcedure(procedure);
+								Register(procedure, typeDeclaration.declaredType(SyntaxTree.RecordType).recordScope, procedure IS SyntaxTree.Operator);
+							END;
+						END;
 					END;
-					Register(procedure, typeDeclaration.declaredType(SyntaxTree.RecordType).recordScope, procedure IS SyntaxTree.Operator);
 				END;
-				procedure := procedure.nextProcedure;
 			END;
-			*)
 
 			(* now process all symbols without any presumption on the order *)
 			symbol := scope.firstSymbol;
 			WHILE(symbol # NIL) DO
 				IF ~(symbol IS SyntaxTree.Parameter) OR (symbol(SyntaxTree.Parameter).ownerType IS SyntaxTree.CellType) THEN
 					IF (symbol IS SyntaxTree.Procedure) THEN
-						IF procedures THEN
+						IF 1 IN phases THEN
 							ResolveSymbol(symbol);
 						END;
 					ELSE
-						IF nonProcedures THEN
+						IF 0 IN phases THEN
 							ResolveSymbol(symbol);
 						END;
 					END;
@@ -8534,11 +8508,11 @@ TYPE
 				END;
 			END;
 
-			IF ~error & procedures & ~system.GenerateVariableOffsets(scope) THEN
+			IF ~error & (1 IN phases) & ~system.GenerateVariableOffsets(scope) THEN
 				Error(Basic.invalidPosition,"problems during offset computation in module");
 			END;
 
-			IF  (scope.ownerModule # NIL) & procedures   THEN
+			IF  (scope.ownerModule # NIL) & (1 IN phases)   THEN
 				(* add scope to global list of all scopes, very handy for code generation and for checking implementations *)
 				scope.ownerModule.AddScope(scope);
 			END;
@@ -8651,7 +8625,7 @@ TYPE
 			IF (x.name = Global.SystemName) OR (x.name = Global.systemName) THEN Error(x.position,"name reserved") END;
 			IF x.context = SyntaxTree.invalidIdentifier THEN x.SetContext(Global.A2Name) END;
 			RemoveModuleFromCache(importCache,x);
-			Declarations(x.moduleScope, FALSE, TRUE, TRUE);
+			Declarations(x.moduleScope, FALSE, {0,1});
 			FixTypes();
 
 			IF module.isCellNet THEN