Enum member names and values must be unique

This commit is contained in:
Sasha Koshka 2022-10-14 04:00:05 -04:00
parent dd29f69213
commit 2669a04857
5 changed files with 90 additions and 6 deletions

View File

@ -20,6 +20,8 @@ type Argument interface {
Location () (location file.Location)
NewError (message string, kind infoerr.ErrorKind) (err error)
ToString (indent int) (output string)
Equals (value any) (equal bool)
Value () (value any)
canBePassedAs (what Type) (allowed bool)
}

View File

@ -69,6 +69,10 @@ func (analyzer analysisOperation) analyzeEnumSection () (
outputSection.what, err = analyzer.analyzeType(inputSection.Type())
if err != nil { return }
isNumeric :=
outputSection.what.isNumeric() &&
outputSection.what.isSingular()
// enum sections are only allowed to inherit from type sections
_, inheritsFromTypeSection := outputSection.what.actual.(*TypeSection)
if !inheritsFromTypeSection {
@ -96,6 +100,33 @@ func (analyzer analysisOperation) analyzeEnumSection () (
outputMember.argument,
outputSection.what)
if err != nil { return }
} else if !isNumeric {
// non-numeric enums must have filled in values
err = inputMember.NewError (
"member value must be specified manually for " +
"non-numeric enums",
infoerr.ErrorKindError)
return
}
for _, compareMember := range outputSection.members {
if compareMember.name == outputMember.name {
err = inputMember.NewError (
"enum member names must be unique",
infoerr.ErrorKindError)
return
}
if outputMember.argument == nil { continue }
if compareMember.argument.Equals (
outputMember.argument.Value(),
) {
err = inputMember.NewError (
"enum member values must be unique",
infoerr.ErrorKindError)
return
}
}
outputSection.members = append (

View File

@ -39,6 +39,18 @@ func (literal IntLiteral) What () (what Type) {
return
}
// Equals returns whether the literal is equal to the specified value.
func (literal IntLiteral) Equals (value any) (equal bool) {
equal = literal.value == value
return
}
// Value returns the literal's value
func (literal IntLiteral) Value () (value any) {
value = literal.value
return
}
// canBePassedAs returns true if this literal can be implicitly cast to the
// specified type, and false if it can't.
func (literal IntLiteral) canBePassedAs (what Type) (allowed bool) {
@ -63,6 +75,18 @@ func (literal UIntLiteral) What () (what Type) {
return
}
// Equals returns whether the literal is equal to the specified value.
func (literal UIntLiteral) Equals (value any) (equal bool) {
equal = literal.value == value
return
}
// Value returns the literal's value
func (literal UIntLiteral) Value () (value any) {
value = literal.value
return
}
// canBePassedAs returns true if this literal can be implicitly cast to the
// specified type, and false if it can't.
func (literal UIntLiteral) canBePassedAs (what Type) (allowed bool) {
@ -86,6 +110,18 @@ func (literal FloatLiteral) ToString (indent int) (output string) {
return
}
// Equals returns whether the literal is equal to the specified value.
func (literal FloatLiteral) Equals (value any) (equal bool) {
equal = literal.value == value
return
}
// Value returns the literal's value
func (literal FloatLiteral) Value () (value any) {
value = literal.value
return
}
// canBePassedAs returns true if this literal can be implicitly cast to the
// specified type, and false if it can't.
func (literal FloatLiteral) canBePassedAs (what Type) (allowed bool) {
@ -117,6 +153,18 @@ func (literal StringLiteral) ToString (indent int) (output string) {
return
}
// Equals returns whether the literal is equal to the specified value.
func (literal StringLiteral) Equals (value any) (equal bool) {
equal = literal.value == value
return
}
// Value returns the literal's value
func (literal StringLiteral) Value () (value any) {
value = literal.value
return
}
// canBePassedAs returns true if this literal can be implicitly cast to the
// specified type, and false if it can't.
func (literal StringLiteral) canBePassedAs (what Type) (allowed bool) {

View File

@ -47,3 +47,7 @@ func (location Location) Describe () (description string) {
" column ", location.column + 1,
" width ", location.width)
}
// TODO: add extend method that extends that takes in another location, and
// returns a new location that spans the two. then, use it in the parser to
// properly locate an entire tree node.

View File

@ -1,4 +1,5 @@
:arf
require '../typeSection'
---
enum ro aWeekday:Int
@ -12,9 +13,7 @@ enum ro aWeekday:Int
type ro bColor:U32
enum ro cNamedColor:bColor
- red 0xFF0000
- green 0x00FF00
- blue 0x0000FF
type ro X:cNamedColor
# enum ro cNamedColor:bColor
# - red 0xFF0000
# - green 0x00FF00
# - blue 0x0000FF