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.
|
// ObjectMember is a member of an object type.
|
||||||
type ObjectMember struct {
|
type ObjectMember struct {
|
||||||
|
locatable
|
||||||
name string
|
name string
|
||||||
|
|
||||||
// even if there is a private permission in another module, we still
|
// even if there is a private permission in another module, we still
|
||||||
@ -27,6 +28,7 @@ type ObjectMember struct {
|
|||||||
permission types.Permission
|
permission types.Permission
|
||||||
|
|
||||||
what Type
|
what Type
|
||||||
|
argument Argument
|
||||||
}
|
}
|
||||||
|
|
||||||
func (member ObjectMember) ToString (indent int) (output string) {
|
func (member ObjectMember) ToString (indent int) (output string) {
|
||||||
@ -98,12 +100,13 @@ func (analyzer analysisOperation) analyzeTypeSection () (
|
|||||||
|
|
||||||
inputSection := analyzer.currentSection.(parser.TypeSection)
|
inputSection := analyzer.currentSection.(parser.TypeSection)
|
||||||
outputSection.location = analyzer.currentSection.Location()
|
outputSection.location = analyzer.currentSection.Location()
|
||||||
|
|
||||||
if inputSection.Permission() == types.PermissionReadWrite {
|
if inputSection.Permission() == types.PermissionReadWrite {
|
||||||
err = inputSection.NewError (
|
err = inputSection.NewError (
|
||||||
"read-write (rw) permission not understood in this " +
|
"read-write (rw) permission not understood in this " +
|
||||||
"context, try read-only (ro)",
|
"context, try read-only (ro)",
|
||||||
infoerr.ErrorKindError)
|
infoerr.ErrorKindError)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
outputSection.permission = inputSection.Permission()
|
outputSection.permission = inputSection.Permission()
|
||||||
@ -126,12 +129,10 @@ func (analyzer analysisOperation) analyzeTypeSection () (
|
|||||||
// analyze members
|
// analyze members
|
||||||
isObj := outputSection.what.underlyingPrimitive() == &PrimitiveObj
|
isObj := outputSection.what.underlyingPrimitive() == &PrimitiveObj
|
||||||
if isObj {
|
if isObj {
|
||||||
// use the Member method on the inherited type to type check and
|
err = analyzer.analyzeObjectMembers (
|
||||||
// permission check default value overrides.
|
&outputSection,
|
||||||
for index := 0; index < inputSection.MembersLength(); index ++ {
|
inputSection)
|
||||||
// inputMember := inputSection.Member(index)
|
if err != nil { return }
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if inputSection.MembersLength() > 0 {
|
} else if inputSection.MembersLength() > 0 {
|
||||||
// if there are members, and the inherited type does not have
|
// 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 " +
|
"members can only be defined on types descending " +
|
||||||
"from Obj",
|
"from Obj",
|
||||||
infoerr.ErrorKindError)
|
infoerr.ErrorKindError)
|
||||||
|
if err != nil { return }
|
||||||
}
|
}
|
||||||
|
|
||||||
outputSection.complete = true
|
outputSection.complete = true
|
||||||
return
|
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) {
|
func TestTypeSection (test *testing.T) {
|
||||||
checkTree ("../tests/analyzer/typeSection", false,
|
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
|
type 1 basic Int
|
||||||
arg uint 5
|
arg uint 5
|
||||||
typeSection ro ../tests/analyzer/typeSection.bOnBasicInt
|
typeSection ro ../tests/analyzer/typeSection.bOnBasicInt
|
||||||
@ -15,5 +17,7 @@ typeSection ro ../tests/analyzer/typeSection.cBasicObject
|
|||||||
type 1 basic Int
|
type 1 basic Int
|
||||||
member ro this
|
member ro this
|
||||||
type 1 basic Int
|
type 1 basic Int
|
||||||
|
typeSection ro ../tests/analyzer/typeSection.dInheritedFromOther
|
||||||
|
type 1 basic Thing
|
||||||
`, test)
|
`, test)
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,12 @@ func (what Type) Kind () (kind TypeKind) {
|
|||||||
return
|
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.
|
// Mutable returns whether or not the type's data is mutable.
|
||||||
func (what Type) Mutable () (mutable bool) {
|
func (what Type) Mutable () (mutable bool) {
|
||||||
mutable = what.mutable
|
mutable = what.mutable
|
||||||
|
Reference in New Issue
Block a user