Can now assign array directly to slice
This commit is contained in:
parent
fa60f8c814
commit
dd9f866165
@ -31,7 +31,7 @@ func (this *Tree) canAssign (
|
||||
// short circuit if force is selected
|
||||
if mode == force { return nil }
|
||||
|
||||
// do structural equivalence if force is selected
|
||||
// do structural equivalence if structural is selected
|
||||
if mode == structural {
|
||||
if this.areStructurallyEquivalent(destination, source) {
|
||||
return nil
|
||||
@ -45,6 +45,12 @@ func (this *Tree) canAssign (
|
||||
return this.canAssignInterface(pos, destination, source)
|
||||
}
|
||||
|
||||
// then, check for array to slice assignment
|
||||
if destination, ok := this.reduceToBase(destination).(*entity.TypeSlice); ok {
|
||||
if source, ok := this.reduceToBase(source). (*entity.TypeArray); ok {
|
||||
return this.canAssignSliceArray(pos, destination, source)
|
||||
}}
|
||||
|
||||
// if weak, only compare the first base types
|
||||
if mode == weak {
|
||||
destination = this.reduceToBase(destination)
|
||||
@ -85,6 +91,21 @@ func (this *Tree) canAssign (
|
||||
return nil
|
||||
}
|
||||
|
||||
// canAssignSliceArray takes in an analyzed slice type and an analyzed array
|
||||
// type, and determines whether the array can be assigned to the slice.
|
||||
func (this *Tree) canAssignSliceArray (
|
||||
pos lexer.Position,
|
||||
destination *entity.TypeSlice,
|
||||
source *entity.TypeArray,
|
||||
) error {
|
||||
err := this.canAssign(pos, destination.Element, strict, source.Element)
|
||||
if err != nil {
|
||||
return participle.Errorf(pos, "expected %v", destination)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// canAssignInterface takes in an analyzed interface destination type and an
|
||||
// analyzed source type, and determines whether source can be assigned to
|
||||
// destination.
|
||||
|
@ -185,8 +185,8 @@ testStringErr (test,
|
||||
`
|
||||
Bird: ([fly distance:F64] [land])
|
||||
BlueJay: Int
|
||||
BlueJay::[fly] = { }
|
||||
BlueJay::[land] = { }
|
||||
BlueJay.[fly] = { }
|
||||
BlueJay.[land] = { }
|
||||
[main] = {
|
||||
b:Bird = [@a:BlueJay]
|
||||
}
|
||||
@ -198,8 +198,8 @@ testString (test,
|
||||
`
|
||||
Bird: ([fly distance:F64] [land])
|
||||
BlueJay: Int
|
||||
BlueJay::[fly distance:F64] = { }
|
||||
BlueJay::[land] = { }
|
||||
BlueJay.[fly distance:F64] = { }
|
||||
BlueJay.[land] = { }
|
||||
[main] = {
|
||||
a:BlueJay
|
||||
b:Bird = [@a]
|
||||
@ -213,23 +213,24 @@ testString (test,
|
||||
`
|
||||
[f]:Byte = 5
|
||||
A:Int
|
||||
A::[g]:Int = 2
|
||||
A.[g]:Int = 2
|
||||
B:([g]:Int)
|
||||
[main] = {
|
||||
a:Int
|
||||
b:Int = a
|
||||
c:Int = d:Int
|
||||
d:Int = { a:F64 b }
|
||||
d = { a:F64 b }
|
||||
e:Byte = [f]
|
||||
g:(x:Int y:(w:F64 z:F64)) = (x: 1 y: (w: 1.2 z: 78.5))
|
||||
gx:(w:F64 z:F64) = g.x
|
||||
gx:(w:F64 z:F64) = g.y
|
||||
h:F64 = gx.z
|
||||
i:A
|
||||
j:Int = [i::g]
|
||||
j:Int = i.[g]
|
||||
k:B = i
|
||||
l:Int = [k::g]
|
||||
l:Int = k.[g]
|
||||
m:5:Int = (* 0 1 2 3 4)
|
||||
n:Int = [. m 3]
|
||||
o:*:Int = m
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ var primitiveTypes = map[string] entity.Type {
|
||||
"U32": &entity.TypeInt { Signed: false, Width: 32 },
|
||||
"U64": &entity.TypeInt { Signed: false, Width: 64 },
|
||||
"F32": &entity.TypeFloat { Width: 32 },
|
||||
"F64": &entity.TypeFloat { Width: 32 },
|
||||
"F64": &entity.TypeFloat { Width: 64 },
|
||||
}
|
||||
|
||||
var builtinTypes = map[string] entity.Type { }
|
||||
|
@ -74,7 +74,8 @@ func (this *Tree) analyzeStatement (
|
||||
return this.analyzeAssignment(assignment)
|
||||
} else if expression, ok := statement.(entity.Expression); ok {
|
||||
expression, err := this.analyzeExpression(nil, strict, expression)
|
||||
return expression.(entity.Statement), err
|
||||
if err != nil { return nil, err }
|
||||
return expression.(entity.Statement), nil
|
||||
} else {
|
||||
panic(fmt.Sprint (
|
||||
"BUG: analyzer doesnt know about statement ",
|
||||
|
@ -39,7 +39,8 @@ func (this *Tree) analyzeDeclaration (
|
||||
entity.Expression,
|
||||
error,
|
||||
) {
|
||||
existing := this.variable(declaration.Name)
|
||||
scope, _ := this.topScope()
|
||||
existing := scope.Variable(declaration.Name)
|
||||
if existing != nil {
|
||||
return nil, participle.Errorf (
|
||||
declaration.Pos,
|
||||
|
@ -4,7 +4,7 @@ import "testing"
|
||||
|
||||
func TestLiteralStructMemberUniqueErr (test *testing.T) {
|
||||
testStringErr (test,
|
||||
"x already listed in struct literal at stream0.fspl:5:2", 7, 2,
|
||||
"x already listed in struct literal at stream0.fspl:5:3", 7, 3,
|
||||
`
|
||||
Point: (x:Int y:Int z:Int)
|
||||
[main] = {
|
||||
@ -28,3 +28,16 @@ Point: (x:Int y:Int z:Int)
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
func TestLiteralStructNested (test *testing.T) {
|
||||
testString (test,
|
||||
`
|
||||
[main] = {
|
||||
g:(x:Int y:(w:F64 z:F64)) = (
|
||||
x: 1
|
||||
y: (
|
||||
w: 1.2
|
||||
z: 78.5))
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
@ -53,14 +53,12 @@ func (this *scopeContextManager) topScope () (entity.Scoped, bool) {
|
||||
|
||||
func (this *scopeContextManager) variable (name string) *entity.Declaration {
|
||||
this.assertPopulated()
|
||||
scope, _ := this.topScope()
|
||||
return scope.Variable(name)
|
||||
return (*this)[len(*this) - 1].variable(name)
|
||||
}
|
||||
|
||||
func (this *scopeContextManager) addVariable (declaration *entity.Declaration) {
|
||||
this.assertPopulated()
|
||||
scope, _ := this.topScope()
|
||||
scope.AddVariable(declaration)
|
||||
(*this)[len(*this) - 1].addVariable(declaration)
|
||||
}
|
||||
|
||||
func (this *scopeContextManager) assertPopulated () {
|
||||
|
@ -91,7 +91,7 @@ func (this *LiteralStruct) Type () Type { return this.Ty }
|
||||
func (this *LiteralStruct) String () string {
|
||||
out := "("
|
||||
for index, member := range this.Members {
|
||||
if index > 1 { out += " " }
|
||||
if index > 0 { out += " " }
|
||||
out += fmt.Sprint(member)
|
||||
}
|
||||
return out + ")"
|
||||
|
@ -34,13 +34,15 @@ testString (test,
|
||||
`[int]:Int = 5
|
||||
[float]:F64 = 324.23409
|
||||
[boolean]:Bool = true
|
||||
[boolean2]:Bool = false`,
|
||||
[boolean2]:Bool = false
|
||||
[struct]:(x:Int y:(w:F64 z:F64)) = (x:1 y:(w:1.2 z:78.5))`,
|
||||
// input
|
||||
`
|
||||
[int]:Int = 5
|
||||
[float]:F64 = 324.23409
|
||||
[boolean]:Bool = true
|
||||
[boolean2]:Bool = false
|
||||
[struct]:(x:Int y:(w:F64 z:F64)) = (x: 1 y: (w: 1.2 z: 78.5))
|
||||
`)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user