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) ToString (indent int) (output string)
Equals (value any) (equal bool) Equals (value any) (equal bool)
Value () (value any) Value () (value any)
Resolve () (constant Argument, err error)
canBePassedAs (what Type) (allowed bool) canBePassedAs (what Type) (allowed bool)
} }

View File

@ -69,6 +69,9 @@ 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 }
// 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 := isNumeric :=
outputSection.what.isNumeric() && outputSection.what.isNumeric() &&
outputSection.what.isSingular() outputSection.what.isSingular()
@ -94,8 +97,14 @@ func (analyzer analysisOperation) analyzeEnumSection () (
outputMember.argument, outputMember.argument,
err = analyzer.analyzeArgument(inputMember.Argument()) err = analyzer.analyzeArgument(inputMember.Argument())
if err != nil { return } 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 ( err = analyzer.typeCheck (
outputMember.argument, outputMember.argument,
outputSection.what) outputSection.what)
@ -117,7 +126,8 @@ func (analyzer analysisOperation) analyzeEnumSection () (
return return
} }
if outputMember.argument == nil { continue } if outputMember.argument == nil { continue }
if compareMember.argument == nil { continue }
if compareMember.argument.Equals ( if compareMember.argument.Equals (
outputMember.argument.Value(), outputMember.argument.Value(),
@ -134,8 +144,55 @@ func (analyzer analysisOperation) analyzeEnumSection () (
outputMember) outputMember)
} }
// TODO: fill in members that do not have values with incrementing // fill in members that do not have values
// values. take care to not duplicate them. 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 outputSection.complete = true
return return

View File

@ -51,6 +51,13 @@ func (literal IntLiteral) Value () (value any) {
return 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 // 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) {
@ -97,6 +104,13 @@ func (literal UIntLiteral) canBePassedAs (what Type) (allowed bool) {
return 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 // What returns the type of the argument
func (literal FloatLiteral) What () (what Type) { func (literal FloatLiteral) What () (what Type) {
what.actual = &PrimitiveF64 what.actual = &PrimitiveF64
@ -122,6 +136,13 @@ func (literal FloatLiteral) Value () (value any) {
return 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 // 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) {
@ -165,6 +186,13 @@ func (literal StringLiteral) Value () (value any) {
return 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 // 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

@ -5,7 +5,7 @@ require '../typeSection'
enum ro aWeekday:Int enum ro aWeekday:Int
- sunday - sunday
- monday - monday
- tuesday - tuesday 3
- wednesday - wednesday
- thursday - thursday
- friday - friday
@ -13,7 +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