Enum values are auto-filled

This commit is contained in:
Sasha Koshka 2022-10-14 20:06:11 -04:00
parent 2669a04857
commit 500184c4ab
4 changed files with 95 additions and 9 deletions

View File

@ -22,6 +22,7 @@ type Argument interface {
ToString (indent int) (output string)
Equals (value any) (equal bool)
Value () (value any)
Resolve () (constant Argument, err error)
canBePassedAs (what Type) (allowed bool)
}

View File

@ -69,6 +69,9 @@ func (analyzer analysisOperation) analyzeEnumSection () (
outputSection.what, err = analyzer.analyzeType(inputSection.Type())
if err != nil { return }
// if the inherited type is a single number, we take note of that here
// because it will allow us to do things like automatically fill in
// member values if they are not specified.
isNumeric :=
outputSection.what.isNumeric() &&
outputSection.what.isSingular()
@ -94,8 +97,14 @@ func (analyzer analysisOperation) analyzeEnumSection () (
outputMember.argument,
err = analyzer.analyzeArgument(inputMember.Argument())
if err != nil { return }
// attempt to resolve the argument to a single constant
// literal
outputMember.argument, err =
outputMember.argument.Resolve()
if err != nil { return }
// type check default value
// type check value
err = analyzer.typeCheck (
outputMember.argument,
outputSection.what)
@ -117,7 +126,8 @@ func (analyzer analysisOperation) analyzeEnumSection () (
return
}
if outputMember.argument == nil { continue }
if outputMember.argument == nil { continue }
if compareMember.argument == nil { continue }
if compareMember.argument.Equals (
outputMember.argument.Value(),
@ -134,8 +144,55 @@ func (analyzer analysisOperation) analyzeEnumSection () (
outputMember)
}
// TODO: fill in members that do not have values with incrementing
// values. take care to not duplicate them.
// fill in members that do not have values
if isNumeric {
for index, fillInMember := range outputSection.members {
if fillInMember.argument != nil { continue }
max := uint64(0)
for _, compareMember := range outputSection.members {
compareValue := compareMember.argument
switch compareValue.(type) {
case IntLiteral:
number := uint64 (
compareValue.(IntLiteral).value)
if number > max {
max = number
}
case UIntLiteral:
number := uint64 (
compareValue.(UIntLiteral).value)
if number > max {
max = number
}
case FloatLiteral:
number := uint64 (
compareValue.(FloatLiteral).value)
if number > max {
max = number
}
case nil:
// do nothing
default:
panic (
"invalid state: illegal " +
"argument type while " +
"attempting to fill in enum " +
"member value for " +
fillInMember.name + " in " +
outputSection.location.Describe())
}
}
// fill in
fillInMember.argument = UIntLiteral {
locatable: fillInMember.locatable,
value: max + 1,
}
outputSection.members[index] = fillInMember
}
}
outputSection.complete = true
return

View File

@ -51,6 +51,13 @@ func (literal IntLiteral) Value () (value any) {
return
}
// Resolve resolves the argument to a constant literal, which in this case is
// trivial because the literal is already constant.
func (literal IntLiteral) Resolve () (constant Argument, err error) {
constant = literal
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) {
@ -97,6 +104,13 @@ func (literal UIntLiteral) canBePassedAs (what Type) (allowed bool) {
return
}
// Resolve resolves the argument to a constant literal, which in this case is
// trivial because the literal is already constant.
func (literal UIntLiteral) Resolve () (constant Argument, err error) {
constant = literal
return
}
// What returns the type of the argument
func (literal FloatLiteral) What () (what Type) {
what.actual = &PrimitiveF64
@ -122,6 +136,13 @@ func (literal FloatLiteral) Value () (value any) {
return
}
// Resolve resolves the argument to a constant literal, which in this case is
// trivial because the literal is already constant.
func (literal FloatLiteral) Resolve () (constant Argument, err error) {
constant = literal
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) {
@ -165,6 +186,13 @@ func (literal StringLiteral) Value () (value any) {
return
}
// Resolve resolves the argument to a constant literal, which in this case is
// trivial because the literal is already constant.
func (literal StringLiteral) Resolve () (constant Argument, err error) {
constant = literal
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

@ -5,7 +5,7 @@ require '../typeSection'
enum ro aWeekday:Int
- sunday
- monday
- tuesday
- tuesday 3
- wednesday
- thursday
- friday
@ -13,7 +13,7 @@ enum ro aWeekday:Int
type ro bColor:U32
# enum ro cNamedColor:bColor
# - red 0xFF0000
# - green 0x00FF00
# - blue 0x0000FF
enum ro cNamedColor:bColor
- red 0xFF0000
- green 0x00FF00
- blue 0x0000FF