Can now assign array directly to slice

This commit is contained in:
Sasha Koshka 2023-10-31 01:46:18 -04:00
parent fa60f8c814
commit dd9f866165
9 changed files with 57 additions and 20 deletions

View File

@ -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.

View File

@ -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
}
`)
}

View File

@ -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 { }

View File

@ -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 ",

View File

@ -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,

View File

@ -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))
}
`)
}

View File

@ -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 () {

View File

@ -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 + ")"

View File

@ -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))
`)
}