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) Location () (location file.Location)
NewError (message string, kind infoerr.ErrorKind) (err error) NewError (message string, kind infoerr.ErrorKind) (err error)
ToString (indent int) (output string) ToString (indent int) (output string)
Equals (value any) (equal bool)
Value () (value any)
canBePassedAs (what Type) (allowed bool) canBePassedAs (what Type) (allowed bool)
} }

View File

@ -69,6 +69,10 @@ func (analyzer analysisOperation) analyzeEnumSection () (
outputSection.what, err = analyzer.analyzeType(inputSection.Type()) outputSection.what, err = analyzer.analyzeType(inputSection.Type())
if err != nil { return } if err != nil { return }
isNumeric :=
outputSection.what.isNumeric() &&
outputSection.what.isSingular()
// enum sections are only allowed to inherit from type sections // enum sections are only allowed to inherit from type sections
_, inheritsFromTypeSection := outputSection.what.actual.(*TypeSection) _, inheritsFromTypeSection := outputSection.what.actual.(*TypeSection)
if !inheritsFromTypeSection { if !inheritsFromTypeSection {
@ -96,6 +100,33 @@ func (analyzer analysisOperation) analyzeEnumSection () (
outputMember.argument, outputMember.argument,
outputSection.what) outputSection.what)
if err != nil { return } 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 ( outputSection.members = append (

View File

@ -39,6 +39,18 @@ func (literal IntLiteral) What () (what Type) {
return 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 // canBePassedAs returns true if this literal can be implicitly cast to the
// specified type, and false if it can't. // specified type, and false if it can't.
func (literal IntLiteral) canBePassedAs (what Type) (allowed bool) { func (literal IntLiteral) canBePassedAs (what Type) (allowed bool) {
@ -63,6 +75,18 @@ func (literal UIntLiteral) What () (what Type) {
return 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 // canBePassedAs returns true if this literal can be implicitly cast to the
// specified type, and false if it can't. // specified type, and false if it can't.
func (literal UIntLiteral) canBePassedAs (what Type) (allowed bool) { func (literal UIntLiteral) canBePassedAs (what Type) (allowed bool) {
@ -86,6 +110,18 @@ func (literal FloatLiteral) ToString (indent int) (output string) {
return 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 // canBePassedAs returns true if this literal can be implicitly cast to the
// specified type, and false if it can't. // specified type, and false if it can't.
func (literal FloatLiteral) canBePassedAs (what Type) (allowed bool) { func (literal FloatLiteral) canBePassedAs (what Type) (allowed bool) {
@ -117,6 +153,18 @@ func (literal StringLiteral) ToString (indent int) (output string) {
return 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 // canBePassedAs returns true if this literal can be implicitly cast to the
// specified type, and false if it can't. // specified type, and false if it can't.
func (literal StringLiteral) canBePassedAs (what Type) (allowed bool) { func (literal StringLiteral) canBePassedAs (what Type) (allowed bool) {

View File

@ -47,3 +47,7 @@ func (location Location) Describe () (description string) {
" column ", location.column + 1, " column ", location.column + 1,
" width ", location.width) " 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 :arf
require '../typeSection'
--- ---
enum ro aWeekday:Int enum ro aWeekday:Int
@ -12,9 +13,7 @@ enum ro aWeekday:Int
type ro bColor:U32 type ro bColor:U32
enum ro cNamedColor:bColor # enum ro cNamedColor:bColor
- red 0xFF0000 # - red 0xFF0000
- green 0x00FF00 # - green 0x00FF00
- blue 0x0000FF # - blue 0x0000FF
type ro X:cNamedColor