This repository has been archived on 2024-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
arf/analyzer/type-section.go

286 lines
7.0 KiB
Go
Raw Normal View History

package analyzer
2022-10-12 22:01:49 -06:00
import "fmt"
2022-09-18 00:41:06 -06:00
import "git.tebibyte.media/arf/arf/types"
import "git.tebibyte.media/arf/arf/parser"
import "git.tebibyte.media/arf/arf/infoerr"
// TypeSection represents a type definition section.
type TypeSection struct {
sectionBase
2022-09-18 00:41:06 -06:00
what Type
complete bool
argument Argument
2022-09-29 15:34:51 -06:00
members []ObjectMember
}
// ObjectMember is a member of an object type.
type ObjectMember struct {
2022-10-12 21:25:21 -06:00
locatable
2022-09-29 15:34:51 -06:00
name string
2022-10-12 22:01:49 -06:00
bitWidth uint64
2022-09-29 15:34:51 -06:00
// even if there is a private permission in another module, we still
// need to include it in the semantic analysis because we need to know
2022-10-01 15:12:43 -06:00
// what members objects have.
2022-09-29 15:34:51 -06:00
permission types.Permission
what Type
2022-10-12 21:25:21 -06:00
argument Argument
2022-09-29 15:34:51 -06:00
}
2022-10-12 22:01:49 -06:00
// ToString returns all data stored within the member, in string form.
2022-09-29 15:34:51 -06:00
func (member ObjectMember) ToString (indent int) (output string) {
output += doIndent (
2022-10-12 22:01:49 -06:00
indent, "member ",
member.permission.ToString(), " ",
member.name)
if member.bitWidth > 0 {
output += fmt.Sprint(" width ", member.bitWidth)
}
output += "\n"
2022-10-12 22:18:32 -06:00
2022-09-29 15:34:51 -06:00
output += member.what.ToString(indent + 1)
2022-10-12 22:18:32 -06:00
if member.argument != nil {
output += member.argument.ToString(indent + 1)
}
2022-09-29 15:34:51 -06:00
return
}
// ToString returns all data stored within the type section, in string form.
func (section TypeSection) ToString (indent int) (output string) {
2022-10-01 15:21:17 -06:00
output += doIndent(indent, "typeSection ")
output += section.permission.ToString() + " "
output += section.where.ToString()
output += "\n"
2022-09-18 00:41:06 -06:00
output += section.what.ToString(indent + 1)
if section.argument != nil {
output += section.argument.ToString(indent + 1)
}
2022-10-12 22:01:49 -06:00
for _, member := range section.members {
output += member.ToString(indent + 1)
}
2022-09-18 00:41:06 -06:00
return
}
// Member returns the membrs ksdn ,mn ,mxc lkzxjclkjxzc l,mnzc .,zxmn.,zxmc
// IT RECURSES!
func (section TypeSection) Member (
name string,
) (
member ObjectMember,
exists bool,
) {
switch section.what.kind {
case TypeKindBasic:
for _, currentMember := range section.members {
if currentMember.name == name {
member = currentMember
exists = true
break
}
}
if !exists {
if section.what.actual == nil { return }
actual, isTypeSection := section.what.actual.(*TypeSection)
if !isTypeSection { return }
member, exists = actual.Member(name)
}
case TypeKindPointer:
points := section.what.points
if points == nil { return }
actual, isTypeSection := points.actual.(*TypeSection)
if !isTypeSection { return }
member, exists = actual.Member(name)
}
return
}
2022-09-18 00:41:06 -06:00
// analyzeTypeSection analyzes a type section.
2022-10-11 21:53:38 -06:00
func (analyzer analysisOperation) analyzeTypeSection () (
2022-09-18 00:41:06 -06:00
section Section,
err error,
) {
2022-09-29 16:09:52 -06:00
outputSection := TypeSection { }
outputSection.where = analyzer.currentPosition
section = &outputSection
2022-09-29 16:09:52 -06:00
analyzer.addSection(section)
2022-09-18 00:41:06 -06:00
inputSection := analyzer.currentSection.(parser.TypeSection)
2022-10-11 16:31:37 -06:00
outputSection.location = analyzer.currentSection.Location()
2022-10-12 21:25:21 -06:00
2022-09-18 00:41:06 -06:00
if inputSection.Permission() == types.PermissionReadWrite {
err = inputSection.NewError (
2022-09-29 15:34:51 -06:00
"read-write (rw) permission not understood in this " +
"context, try read-only (ro)",
2022-09-18 00:41:06 -06:00
infoerr.ErrorKindError)
2022-10-12 21:25:21 -06:00
return
2022-09-18 00:41:06 -06:00
}
2022-10-01 15:21:17 -06:00
outputSection.permission = inputSection.Permission()
2022-09-18 00:41:06 -06:00
outputSection.what, err = analyzer.analyzeType(inputSection.Type())
2022-09-20 09:01:56 -06:00
if err != nil { return }
if !inputSection.Argument().Nil() {
outputSection.argument,
err = analyzer.analyzeArgument(inputSection.Argument())
if err != nil { return }
// type check default value
err = analyzer.typeCheck (
outputSection.argument,
outputSection.what)
if err != nil { return }
}
2022-10-12 11:05:19 -06:00
// analyze members
isObj := outputSection.what.underlyingPrimitive() == &PrimitiveObj
if isObj {
2022-10-12 21:25:21 -06:00
err = analyzer.analyzeObjectMembers (
&outputSection,
inputSection)
if err != nil { return }
2022-10-12 11:05:19 -06:00
} else if inputSection.MembersLength() > 0 {
// if there are members, and the inherited type does not have
// Obj as a primitive, throw an error.
err = inputSection.Member(0).NewError (
"members can only be defined on types descending " +
"from Obj",
infoerr.ErrorKindError)
2022-10-12 21:25:21 -06:00
if err != nil { return }
2022-10-12 11:05:19 -06:00
}
2022-09-18 00:41:06 -06:00
outputSection.complete = true
return
}
2022-10-12 21:25:21 -06:00
func (analyzer *analysisOperation) analyzeObjectMembers (
into *TypeSection,
from parser.TypeSection,
) (
err error,
) {
inheritedSection := into.what.actual.(*TypeSection)
2022-10-13 00:20:47 -06:00
inheritsFromSameModule := analyzer.inCurrentModule(inheritedSection)
2022-10-12 21:25:21 -06:00
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()
2022-10-12 22:01:49 -06:00
outputMember.bitWidth = inputMember.BitWidth()
2022-10-12 21:25:21 -06:00
inheritedMember, exists :=
inheritedSection.Member(inputMember.Name())
if exists {
// modifying default value/permissions of an
// inherited member
2022-10-13 00:20:47 -06:00
canAccessMember :=
inheritsFromSameModule ||
inheritedMember.permission !=
types.PermissionPrivate
if !canAccessMember {
err = inputMember.NewError (
"inherited member is private (pv) in " +
"parent type, and cannot be modified " +
"here",
infoerr.ErrorKindError)
return
}
2022-10-12 21:25:21 -06:00
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
}
2022-10-13 00:20:47 -06:00
canOverwriteMember :=
inheritsFromSameModule ||
inheritedMember.permission ==
types.PermissionReadWrite
2022-10-12 21:25:21 -06:00
// apply default value
if inputMember.Argument().Nil() {
// if it is unspecified, inherit it
outputMember.argument = inheritedMember.argument
} else {
2022-10-13 00:20:47 -06:00
if !canOverwriteMember {
err = inputMember.Argument().NewError (
"member is read-only (ro) in " +
"parent type, its default " +
"value cannot be overridden",
infoerr.ErrorKindError)
return
}
2022-10-12 21:25:21 -06:00
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
}
2022-10-12 22:01:49 -06:00
outputMember.what, err = analyzer.analyzeType (
inputMember.Type())
if err != nil { return }
2022-10-12 21:25:21 -06:00
// 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
}