Added untested object member analysis
This commit is contained in:
		
							parent
							
								
									aaf268d0d1
								
							
						
					
					
						commit
						f817894b49
					
				| @ -19,6 +19,7 @@ type TypeSection struct { | ||||
| 
 | ||||
| // ObjectMember is a member of an object type.  | ||||
| type ObjectMember struct { | ||||
| 	locatable | ||||
| 	name string | ||||
| 	 | ||||
| 	// even if there is a private permission in another module, we still | ||||
| @ -27,6 +28,7 @@ type ObjectMember struct { | ||||
| 	permission types.Permission | ||||
| 
 | ||||
| 	what Type | ||||
| 	argument Argument | ||||
| } | ||||
| 
 | ||||
| func (member ObjectMember) ToString (indent int) (output string) { | ||||
| @ -98,12 +100,13 @@ func (analyzer analysisOperation) analyzeTypeSection () ( | ||||
| 
 | ||||
| 	inputSection := analyzer.currentSection.(parser.TypeSection) | ||||
| 	outputSection.location = analyzer.currentSection.Location() | ||||
| 	 | ||||
| 
 | ||||
| 	if inputSection.Permission() == types.PermissionReadWrite { | ||||
| 		err = inputSection.NewError ( | ||||
| 			"read-write (rw) permission not understood in this " + | ||||
| 			"context, try read-only (ro)", | ||||
| 			infoerr.ErrorKindError) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	outputSection.permission = inputSection.Permission() | ||||
| @ -126,12 +129,10 @@ func (analyzer analysisOperation) analyzeTypeSection () ( | ||||
| 	// analyze members | ||||
| 	isObj := outputSection.what.underlyingPrimitive() == &PrimitiveObj | ||||
| 	if isObj { | ||||
| 		// use the Member method on the inherited type to type check and | ||||
| 		// permission check default value overrides. | ||||
| 		for index := 0; index < inputSection.MembersLength(); index ++ { | ||||
| 			// inputMember := inputSection.Member(index) | ||||
| 			// TODO | ||||
| 		} | ||||
| 		err = analyzer.analyzeObjectMembers ( | ||||
| 			&outputSection, | ||||
| 			inputSection) | ||||
| 		if err != nil { return } | ||||
| 		 | ||||
| 	} else if inputSection.MembersLength() > 0 { | ||||
| 		// if there are members, and the inherited type does not have | ||||
| @ -140,8 +141,95 @@ func (analyzer analysisOperation) analyzeTypeSection () ( | ||||
| 			"members can only be defined on types descending " + | ||||
| 			"from Obj", | ||||
| 			infoerr.ErrorKindError) | ||||
| 		if err != nil { return } | ||||
| 	} | ||||
| 
 | ||||
| 	outputSection.complete = true | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (analyzer *analysisOperation) analyzeObjectMembers ( | ||||
| 	into *TypeSection, | ||||
| 	from parser.TypeSection, | ||||
| ) ( | ||||
| 	err error, | ||||
| ) { | ||||
| 	inheritedSection := into.what.actual | ||||
| 	for index := 0; index < from.MembersLength(); index ++ { | ||||
| 		inputMember := from.Member(index) | ||||
| 
 | ||||
| 		outputMember := ObjectMember { } | ||||
| 		outputMember.location   = inputMember.Location() | ||||
| 		outputMember.name       = inputMember.Name() | ||||
| 		outputMember.permission = inputMember.Permission() | ||||
| 		 | ||||
| 		inheritedMember, exists := | ||||
| 			inheritedSection.Member(inputMember.Name()) | ||||
| 
 | ||||
| 		if exists { | ||||
| 			// modifying default value/permissions of an | ||||
| 			// inherited member | ||||
| 
 | ||||
| 			outputMember.what = inheritedMember.what | ||||
| 			if !inputMember.Type().Nil() { | ||||
| 				err = inputMember.NewError ( | ||||
| 					"cannot override type of " + | ||||
| 					"inherited member", | ||||
| 					infoerr.ErrorKindError) | ||||
| 				return | ||||
| 			} | ||||
| 			 | ||||
| 			if outputMember.permission > inheritedMember.permission { | ||||
| 				err = inputMember.NewError ( | ||||
| 					"cannot relax permission of " + | ||||
| 					"inherited member", | ||||
| 					infoerr.ErrorKindError) | ||||
| 				return | ||||
| 			} | ||||
| 
 | ||||
| 			// apply default value | ||||
| 			if inputMember.Argument().Nil() { | ||||
| 				// if it is unspecified, inherit it | ||||
| 				outputMember.argument = inheritedMember.argument | ||||
| 			} else { | ||||
| 				outputMember.argument, | ||||
| 				err = analyzer.analyzeArgument(inputMember.Argument()) | ||||
| 				if err != nil { return } | ||||
| 
 | ||||
| 				// type check default value | ||||
| 				err = analyzer.typeCheck ( | ||||
| 					outputMember.argument, | ||||
| 					outputMember.what) | ||||
| 				if err != nil { return } | ||||
| 			} | ||||
| 			 | ||||
| 		} else { | ||||
| 			// defining a new member | ||||
| 			if inputMember.Type().Nil() { | ||||
| 				err = inputMember.NewError ( | ||||
| 					"new members must be given a " + | ||||
| 					"type", | ||||
| 					infoerr.ErrorKindError) | ||||
| 				return | ||||
| 			} | ||||
| 			 | ||||
| 			// apply default value | ||||
| 			if !inputMember.Argument().Nil() { | ||||
| 				outputMember.argument, | ||||
| 				err = analyzer.analyzeArgument(inputMember.Argument()) | ||||
| 				if err != nil { return } | ||||
| 
 | ||||
| 				// type check default value | ||||
| 				err = analyzer.typeCheck ( | ||||
| 					outputMember.argument, | ||||
| 					outputMember.what) | ||||
| 				if err != nil { return } | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		into.members = append ( | ||||
| 			into.members, | ||||
| 			outputMember) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
|  | ||||
| @ -4,7 +4,9 @@ import "testing" | ||||
| 
 | ||||
| func TestTypeSection (test *testing.T) { | ||||
| 	checkTree ("../tests/analyzer/typeSection", false, | ||||
| `typeSection ro ../tests/analyzer/typeSection.aBasicInt | ||||
| `typeSection ro ../tests/analyzer/typeSection/something.Thing | ||||
| 	type 1 basic Int | ||||
| typeSection ro ../tests/analyzer/typeSection.aBasicInt | ||||
| 	type 1 basic Int | ||||
| 	arg uint 5 | ||||
| typeSection ro ../tests/analyzer/typeSection.bOnBasicInt | ||||
| @ -15,5 +17,7 @@ typeSection ro ../tests/analyzer/typeSection.cBasicObject | ||||
| 		type 1 basic Int | ||||
| 	member ro this | ||||
| 		type 1 basic Int | ||||
| typeSection ro ../tests/analyzer/typeSection.dInheritedFromOther | ||||
| 	type 1 basic Thing | ||||
| `, test) | ||||
| } | ||||
|  | ||||
| @ -55,6 +55,12 @@ func (what Type) Kind () (kind TypeKind) { | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // Nil returns true if the type is nil, and false if it isn't. | ||||
| func (what Type) Nil () (isNil bool) { | ||||
| 	isNil = what.kind == TypeKindNil | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // Mutable returns whether or not the type's data is mutable. | ||||
| func (what Type) Mutable () (mutable bool) { | ||||
| 	mutable = what.mutable | ||||
|  | ||||
		Reference in New Issue
	
	Block a user