Untested analysis of switch statements
This commit is contained in:
parent
6916b3b7b1
commit
a50a5febb9
@ -483,6 +483,14 @@ func isInteger (ty entity.Type) bool {
|
||||
}
|
||||
}
|
||||
|
||||
// isPointer returns whether or not the specified type is a pointer.
|
||||
func isPointer (ty entity.Type) bool {
|
||||
switch ReduceToBase(ty).(type) {
|
||||
case *entity.TypePointer: return true
|
||||
default: return false
|
||||
}
|
||||
}
|
||||
|
||||
// isOrdered returns whether or not the values of the specified type can be
|
||||
// ordered.
|
||||
func isOrdered (ty entity.Type) bool {
|
||||
@ -515,6 +523,15 @@ func IsUnsigned (ty entity.Type) bool {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// integerWidth returns the width of the type, if it is an integer.
|
||||
func integerWidth (ty entity.Type) (int, bool) {
|
||||
switch ty := ReduceToBase(ty).(type) {
|
||||
case *entity.TypeInt: return ty.Width, true
|
||||
default: return 0, false
|
||||
}
|
||||
}
|
||||
|
||||
// inRange returns whether the specified value can fit within the given integer
|
||||
// type.
|
||||
func inRange (ty entity.Type, value int64) bool {
|
||||
|
@ -46,6 +46,8 @@ func (this *Tree) analyzeExpression (
|
||||
return this.analyzeIfElse(into, mode, expression)
|
||||
case *entity.Match:
|
||||
return this.analyzeMatch(into, mode, expression)
|
||||
case *entity.Switch:
|
||||
return this.analyzeSwitch(into, mode, expression)
|
||||
case *entity.Loop:
|
||||
return this.analyzeLoop(into, mode, expression)
|
||||
case *entity.For:
|
||||
|
@ -803,6 +803,87 @@ func (this *Tree) assembleMatchMap (match *entity.Match) (*entity.Match, error)
|
||||
return match, nil
|
||||
}
|
||||
|
||||
func (this *Tree) analyzeSwitch (
|
||||
into entity.Type,
|
||||
mode strictness,
|
||||
switc *entity.Switch,
|
||||
) (
|
||||
entity.Expression,
|
||||
error,
|
||||
) {
|
||||
value, err := this.analyzeExpression(nil, strict, switc.Value)
|
||||
if err != nil { return nil, err }
|
||||
switc.Value = value
|
||||
width, integerOk := integerWidth(value.Type())
|
||||
if !integerOk {
|
||||
return nil, errors.Errorf (
|
||||
value.Position(), "cannot switch on type %v",
|
||||
value.Type())
|
||||
}
|
||||
|
||||
switc.CaseOrder = make([]int64, len(switc.Cases))
|
||||
switc.CaseMap = make(map[int64] *entity.SwitchCase)
|
||||
for index, cas := range switc.Cases {
|
||||
|
||||
this.pushScope(cas)
|
||||
key, err := this.analyzeExpression (
|
||||
value.Type(), strict,
|
||||
cas.Key)
|
||||
if err != nil { this.popScope(); return nil, err }
|
||||
cas.Key = key
|
||||
expression, err := this.analyzeExpression (
|
||||
into, mode,
|
||||
cas.Expression)
|
||||
if err != nil { this.popScope(); return nil, err }
|
||||
cas.Expression = expression
|
||||
this.popScope()
|
||||
|
||||
var keyInt int64
|
||||
switch key := key.(type) {
|
||||
case *entity.LiteralInt:
|
||||
keyInt = int64(key.Value)
|
||||
case *entity.LiteralString:
|
||||
switch {
|
||||
case width >= 32:
|
||||
keyInt = int64(key.ValueUTF32[0])
|
||||
case width >= 16:
|
||||
keyInt = int64(key.ValueUTF16[0])
|
||||
default:
|
||||
keyInt = int64(key.ValueUTF8[0])
|
||||
}
|
||||
default:
|
||||
return nil, errors.Errorf (
|
||||
key.Position(), "%v cannot represent a constant integer",
|
||||
key)
|
||||
}
|
||||
|
||||
switc.Cases[index] = cas
|
||||
switc.CaseMap[keyInt] = cas
|
||||
switc.CaseOrder[index] = keyInt
|
||||
}
|
||||
|
||||
if switc.Default != nil {
|
||||
this.pushScope(switc.Default)
|
||||
expression, err := this.analyzeExpression (
|
||||
into, mode,
|
||||
switc.Default.Expression)
|
||||
this.popScope()
|
||||
|
||||
if err != nil { return nil, err }
|
||||
switc.Default.Expression = expression
|
||||
}
|
||||
|
||||
if into != nil && switc.Default != nil {
|
||||
return nil, errors.Errorf (
|
||||
switc.Position(),
|
||||
"switch must have a default case")
|
||||
}
|
||||
|
||||
switc.Ty = into
|
||||
|
||||
return switc, nil
|
||||
}
|
||||
|
||||
func (this *Tree) analyzeLoop (
|
||||
into entity.Type,
|
||||
mode strictness,
|
||||
|
@ -459,7 +459,7 @@ type Switch struct {
|
||||
// Semantics
|
||||
Ty Type
|
||||
CaseOrder []int64
|
||||
CaseMap map[uint64] *MatchCase
|
||||
CaseMap map[int64] *SwitchCase
|
||||
}
|
||||
func (*Switch) expression(){}
|
||||
func (this *Switch) Position () errors.Position { return this.Pos }
|
||||
|
Loading…
Reference in New Issue
Block a user