Rework analyzer code to fit new parser

This commit is contained in:
Sasha Koshka 2024-02-08 03:51:21 -05:00
parent 090d52b8f8
commit 5bb9508a76
10 changed files with 194 additions and 222 deletions

View File

@ -2,8 +2,7 @@ package analyzer
import "fmt"
import "math"
import "github.com/alecthomas/participle/v2"
import "github.com/alecthomas/participle/v2/lexer"
import "git.tebibyte.media/sashakoshka/fspl/errors"
import "git.tebibyte.media/sashakoshka/fspl/entity"
import "git.tebibyte.media/sashakoshka/fspl/integer"
@ -24,7 +23,7 @@ type strictness int; const (
// canAssign takes in an analyzed destination type and an analyzed source type,
// and determines whether source can be assigned to destination.
func (this *Tree) canAssign (
pos lexer.Position,
pos errors.Position,
// assuming both are analyzed already
destination entity.Type,
mode strictness,
@ -33,13 +32,13 @@ func (this *Tree) canAssign (
fail := func () error {
switch mode {
case strict:
return participle.Errorf(pos, "expected %v", destination)
return errors.Errorf(pos, "expected %v", destination)
case weak:
return participle.Errorf (
return errors.Errorf (
pos, "cannot use %v as %v",
source, destination)
case structural:
return participle.Errorf (
return errors.Errorf (
pos, "cannot convert from %v to %v",
source, destination)
default:
@ -142,12 +141,12 @@ func (this *Tree) canAssign (
// canAssignCoerce determines if data of an analyzed source type can be
// converted into data of an analyzed destination type.
func (this *Tree) canAssignCoerce (
pos lexer.Position,
pos errors.Position,
destination entity.Type,
source entity.Type,
) error {
fail := func () error {
return participle.Errorf (
return errors.Errorf (
pos, "cannot convert from %v to %v",
source, destination)
}
@ -213,13 +212,13 @@ func (this *Tree) canAssignCoerce (
// 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,
pos errors.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)
return errors.Errorf(pos, "expected %v", destination)
} else {
return nil
}
@ -229,7 +228,7 @@ func (this *Tree) canAssignSliceArray (
// analyzed source type, and determines whether source can be assigned to
// destination.
func (this *Tree) canAssignInterface (
pos lexer.Position,
pos errors.Position,
destination *entity.TypeInterface,
source entity.Type,
) error {
@ -254,7 +253,7 @@ func (this *Tree) canAssignInterface (
// check equivalence
if !signature.Equals(behavior) {
return participle.Errorf (
return errors.Errorf (
pos, "%v has wrong signature for method %v",
source, name)
}
@ -326,60 +325,60 @@ func (this *Tree) isLocationExpression (expression entity.Expression) error {
case *entity.Declaration:
return nil
case *entity.Call:
return participle.Errorf (
expression.Pos,
return errors.Errorf (
expression.Position,
"cannot assign to function call")
case *entity.MethodCall:
return participle.Errorf (
expression.Pos,
return errors.Errorf (
expression.Position,
"cannot assign to method call")
case *entity.Subscript:
return this.isLocationExpression(expression.Slice)
case *entity.Slice:
return participle.Errorf (
expression.Pos,
return errors.Errorf (
expression.Position,
"cannot assign to slice operation")
case *entity.Dereference:
return this.isLocationExpression(expression.Pointer)
case *entity.Reference:
return participle.Errorf (
expression.Pos,
return errors.Errorf (
expression.Position,
"cannot assign to reference operation")
case *entity.ValueCast:
return participle.Errorf (
expression.Pos,
return errors.Errorf (
expression.Position,
"cannot assign to value cast")
case *entity.BitCast:
return participle.Errorf (
expression.Pos,
return errors.Errorf (
expression.Position,
"cannot assign to bit cast")
case *entity.Operation:
return participle.Errorf (
expression.Pos,
return errors.Errorf (
expression.Position,
"cannot assign to %v operation",
expression.Operator)
case *entity.Block:
return participle.Errorf (
expression.Pos,
return errors.Errorf (
expression.Position,
"cannot assign to block")
case *entity.MemberAccess:
return this.isLocationExpression (
expression.Source)
case *entity.IfElse:
return participle.Errorf (
expression.Pos,
return errors.Errorf (
expression.Position,
"cannot assign to if/else")
case *entity.Loop:
return participle.Errorf (
expression.Pos,
return errors.Errorf (
expression.Position,
"cannot assign to loop")
case *entity.Break:
return participle.Errorf (
expression.Pos,
return errors.Errorf (
expression.Position,
"cannot assign to break statement")
case *entity.Return:
return participle.Errorf (
expression.Pos,
return errors.Errorf (
expression.Position,
"cannot assign to return statement")
default:
panic(fmt.Sprint (

View File

@ -12,6 +12,8 @@ func (this *Tree) analyzeExpression (
error,
) {
switch expression := expression.(type) {
case *entity.Assignment:
return this.analyzeAssignment(expression)
case *entity.Variable:
return this.analyzeVariable(into, mode, expression)
case *entity.Declaration:
@ -69,22 +71,3 @@ func (this *Tree) analyzeExpression (
expression, expression))
}
}
func (this *Tree) analyzeStatement (
statement entity.Statement,
) (
entity.Statement,
error,
) {
if assignment, ok := statement.(*entity.Assignment); ok {
return this.analyzeAssignment(assignment)
} else if expression, ok := statement.(entity.Expression); ok {
expression, err := this.analyzeExpression(nil, strict, expression)
if err != nil { return nil, err }
return expression.(entity.Statement), nil
} else {
panic(fmt.Sprintf (
"BUG: analyzer doesnt know about statement %v, ty: %T",
statement, statement))
}
}

View File

@ -1,7 +1,7 @@
package analyzer
import "fmt"
import "github.com/alecthomas/participle/v2"
import "git.tebibyte.media/sashakoshka/fspl/errors"
import "git.tebibyte.media/sashakoshka/fspl/entity"
// All expression analysis routines must take in the type they are being
@ -9,6 +9,29 @@ import "git.tebibyte.media/sashakoshka/fspl/entity"
// is nil, the expression must ignore it unless it can do upwards type
// inference.
func (this *Tree) analyzeAssignment (
assignment *entity.Assignment,
) (
entity.Expression,
error,
) {
// analyze location
location, err := this.analyzeExpression(nil, strict, assignment.Location)
if err != nil { return nil, err }
assignment.Location = location
// ensure location is location expression
err = this.isLocationExpression(location)
if err != nil { return nil, err }
// analyze value
value, err := this.analyzeExpression(location.Type(), strict, assignment.Value)
if err != nil { return nil, err }
assignment.Value = value
return assignment, nil
}
func (this *Tree) analyzeVariable (
into entity.Type,
mode strictness,
@ -19,12 +42,12 @@ func (this *Tree) analyzeVariable (
) {
declaration := this.variable(variable.Name)
if declaration == nil {
return nil, participle.Errorf (
variable.Pos, "no variable named %s",
return nil, errors.Errorf (
variable.Position, "no variable named %s",
variable.Name)
}
err := this.canAssign(variable.Pos, into, mode, declaration.Type())
err := this.canAssign(variable.Position, into, mode, declaration.Type())
if err != nil { return nil, err }
variable.Declaration = declaration
@ -42,17 +65,17 @@ func (this *Tree) analyzeDeclaration (
scope, _ := this.topScope()
existing := scope.Variable(declaration.Name)
if existing != nil {
return nil, participle.Errorf (
declaration.Pos,
return nil, errors.Errorf (
declaration.Position,
"%s already declared in block at %v",
declaration.Name, existing.Pos)
declaration.Name, existing.Position)
}
ty, err := this.analyzeType(declaration.Ty, false)
declaration.Ty = ty
if err != nil { return nil, err }
err = this.canAssign(declaration.Pos, into, mode, declaration.Type())
err = this.canAssign(declaration.Position, into, mode, declaration.Type())
if err != nil { return nil, err }
this.addVariable(declaration)
@ -68,22 +91,22 @@ func (this *Tree) analyzeCall (
error,
) {
// get function
function, err := this.analyzeFunction(call.Pos, call.Name)
function, err := this.analyzeFunction(call.Position, call.Name)
call.Function = function
if err != nil { return nil, err }
// check return result
err = this.canAssign(call.Pos, into, mode, function.Signature.Return)
err = this.canAssign(call.Position, into, mode, function.Signature.Return)
if err != nil { return nil, err }
// check arg count
if len(call.Arguments) > len(function.Signature.Arguments) {
return nil, participle.Errorf (
call.Pos, "too many arguments in call to %s",
return nil, errors.Errorf (
call.Position, "too many arguments in call to %s",
call.Name)
} else if len(call.Arguments) < len(function.Signature.Arguments) {
return nil, participle.Errorf (
call.Pos, "too few arguments in call to %s",
return nil, errors.Errorf (
call.Position, "too few arguments in call to %s",
call.Name)
}
@ -108,11 +131,11 @@ func (this *Tree) analyzeMethodCall (
error,
) {
// get method
sourceExpr, err := this.analyzeVariable(nil, strict, call.Source)
sourceExpr, err := this.analyzeExpression(nil, strict, call.Source)
source := sourceExpr.(*entity.Variable)
if err != nil { return nil, err }
method, err := this.analyzeMethodOrBehavior (
call.Pos, source.Declaration.Type(), call.Name)
call.Position, source.Declaration.Type(), call.Name)
if err != nil { return nil, err }
// extract signature
@ -131,17 +154,17 @@ func (this *Tree) analyzeMethodCall (
}
// check return result
err = this.canAssign(call.Pos, into, mode, signature.Return)
err = this.canAssign(call.Position, into, mode, signature.Return)
if err != nil { return nil, err }
// check arg count
if len(call.Arguments) > len(signature.Arguments) {
return nil, participle.Errorf (
call.Pos, "too many arguments in call to %s",
return nil, errors.Errorf (
call.Position, "too many arguments in call to %s",
call.Name)
} else if len(call.Arguments) < len(signature.Arguments) {
return nil, participle.Errorf (
call.Pos, "too few arguments in call to %s",
return nil, errors.Errorf (
call.Position, "too few arguments in call to %s",
call.Name)
}
@ -166,8 +189,8 @@ func (this *Tree) analyzeSubscript (
) {
slice, err := this.analyzeExpression (
&entity.TypeSlice {
Pos: subscript.Pos,
Element: into,
Position: subscript.Position,
Element: into,
}, weak,
subscript.Slice)
if err != nil { return nil, err }
@ -254,7 +277,7 @@ func (this *Tree) analyzeDereference (
) {
pointer, err := this.analyzeExpression (
&entity.TypePointer {
Pos: dereference.Pos,
Position: dereference.Position,
Referenced: into,
}, weak,
dereference.Pointer)
@ -288,7 +311,7 @@ func (this *Tree) analyzeReference (
) {
referenced, ok := into.(*entity.TypePointer)
if !ok {
return nil, participle.Errorf(reference.Pos, "expected %v", into)
return nil, errors.Errorf(reference.Position, "expected %v", into)
}
value, err := this.analyzeExpression (
@ -315,7 +338,7 @@ func (this *Tree) analyzeValueCast (
if err != nil { return nil, err }
cast.Ty = ty
err = this.canAssign(cast.Pos, into, mode, cast.Type())
err = this.canAssign(cast.Position, into, mode, cast.Type())
if err != nil { return nil, err }
value, err := this.analyzeExpression(cast.Ty, coerce, cast.Value)
@ -337,7 +360,7 @@ func (this *Tree) analyzeBitCast (
if err != nil { return nil, err }
cast.Ty = ty
err = this.canAssign(cast.Pos, into, mode, cast.Type())
err = this.canAssign(cast.Position, into, mode, cast.Type())
if err != nil { return nil, err }
value, err := this.analyzeExpression(cast.Ty, force, cast.Value)
@ -356,12 +379,12 @@ func (this *Tree) analyzeOperation (
error,
) {
wrongInto := func () (entity.Expression, error) {
return nil, participle.Errorf(operation.Pos, "expected %v", into)
return nil, errors.Errorf(operation.Position, "expected %v", into)
}
wrongArgCount := func () (entity.Expression, error) {
return nil, participle.Errorf (
operation.Pos, "wrong argument count for %v",
return nil, errors.Errorf (
operation.Position, "wrong argument count for %v",
operation.Operator)
}
@ -413,8 +436,8 @@ func (this *Tree) analyzeOperation (
}
}
if argumentType == nil {
return nil, participle.Errorf (
operation.Pos,
return nil, errors.Errorf (
operation.Position,
"operation arguments have ambiguous type")
}
@ -510,8 +533,8 @@ func (this *Tree) analyzeBlock (
defer this.popScope()
if len(block.Steps) == 0 && into != nil {
return nil, participle.Errorf (
block.Pos, "block must have at least one statement")
return nil, errors.Errorf (
block.Position, "block must have at least one statement")
}
final := len(block.Steps) - 1
@ -519,8 +542,8 @@ func (this *Tree) analyzeBlock (
if index == final && into != nil {
expression, ok := step.(entity.Expression)
if !ok {
return nil, participle.Errorf (
block.Pos, "expected expression")
return nil, errors.Errorf (
block.Position, "expected expression")
}
step, err := this.analyzeExpression(into, strict, expression)
@ -528,7 +551,7 @@ func (this *Tree) analyzeBlock (
block.Steps[index] = step
block.Ty = step.Type()
} else {
step, err := this.analyzeStatement(step)
step, err := this.analyzeExpression(nil, strict, step)
if err != nil { return nil, err }
block.Steps[index] = step
}
@ -555,22 +578,22 @@ func (this *Tree) analyzeMemberAccess (
case *entity.TypePointer:
referenced, ok := ReduceToBase(sourceTypeAny.Referenced).(*entity.TypeStruct)
if !ok {
return nil, participle.Errorf (
access.Pos, "cannot access members of %v", source)
return nil, errors.Errorf (
access.Position, "cannot access members of %v", source)
}
sourceType = referenced
default:
return nil, participle.Errorf (
access.Pos, "cannot access members of %v", source)
return nil, errors.Errorf (
access.Position, "cannot access members of %v", source)
}
member, ok := sourceType.MemberMap[access.Member]
if !ok {
return nil, participle.Errorf (
access.Pos, "no member %v", access)
return nil, errors.Errorf (
access.Position, "no member %v", access)
}
err = this.canAssign(access.Pos, into, mode, member.Type())
err = this.canAssign(access.Position, into, mode, member.Type())
if err != nil { return nil, err }
access.Ty = member.Type()
@ -600,8 +623,8 @@ func (this *Tree) analyzeIfElse (
if ifelse.False == nil {
if into != nil {
return nil, participle.Errorf (
ifelse.Pos,
return nil, errors.Errorf (
ifelse.Position,
"else case required when using value of if ")
}
} else {
@ -643,20 +666,20 @@ func (this *Tree) analyzeBreak (
error,
) {
if into != nil {
return nil, participle.Errorf(brk.Pos, "expected %v", into)
return nil, errors.Errorf(brk.Position, "expected %v", into)
}
loop, ok := this.topLoop()
if !ok {
return nil, participle.Errorf (
brk.Pos,
return nil, errors.Errorf (
brk.Position,
"break statement must be within loop")
}
brk.Loop = loop
if loop.Type() != nil && brk.Value == nil {
return nil, participle.Errorf (
brk.Pos,
return nil, errors.Errorf (
brk.Position,
"break statement must have value")
}
@ -678,7 +701,7 @@ func (this *Tree) analyzeReturn (
error,
) {
if into != nil {
return nil, participle.Errorf(ret.Pos, "expected %v", into)
return nil, errors.Errorf(ret.Position, "expected %v", into)
}
ret.Declaration, _ = this.topDeclaration()
@ -691,8 +714,8 @@ func (this *Tree) analyzeReturn (
}
if ty != nil && ret.Value == nil {
return nil, participle.Errorf (
ret.Pos,
return nil, errors.Errorf (
ret.Position,
"break statement must have value")
}

View File

@ -1,11 +1,10 @@
package analyzer
import "github.com/alecthomas/participle/v2"
import "github.com/alecthomas/participle/v2/lexer"
import "git.tebibyte.media/sashakoshka/fspl/errors"
import "git.tebibyte.media/sashakoshka/fspl/entity"
func (this *Tree) analyzeFunction (
pos lexer.Position,
pos errors.Position,
name string,
) (
*entity.Function,
@ -21,7 +20,7 @@ func (this *Tree) analyzeFunction (
// error if function is missing
function, exists := this.rawFunctions[name]
if !exists {
return nil, participle.Errorf(pos, "no function named %s", name)
return nil, errors.Errorf(pos, "no function named %s", name)
}
// create a new scope context for this function

View File

@ -1,7 +1,7 @@
package analyzer
import "unicode/utf16"
import "github.com/alecthomas/participle/v2"
import "git.tebibyte.media/sashakoshka/fspl/errors"
import "git.tebibyte.media/sashakoshka/fspl/entity"
func (this *Tree) analyzeLiteralInt (
@ -13,14 +13,14 @@ func (this *Tree) analyzeLiteralInt (
error,
) {
if !isNumeric(into) {
return nil, participle.Errorf (
literal.Pos, "cannot use integer literal as %v",
return nil, errors.Errorf (
literal.Position, "cannot use integer literal as %v",
into)
}
if isInteger(into) && !inRange(into, int64(literal.Value)) {
return nil, participle.Errorf (
literal.Pos, "integer literal out of range for type %v",
return nil, errors.Errorf (
literal.Position, "integer literal out of range for type %v",
into)
}
@ -37,8 +37,8 @@ func (this *Tree) analyzeLiteralFloat (
error,
) {
if !isFloat(into) {
return nil, participle.Errorf (
literal.Pos, "cannot use float literal as %v",
return nil, errors.Errorf (
literal.Position, "cannot use float literal as %v",
into)
}
@ -57,8 +57,8 @@ func (this *Tree) analyzeLiteralString (
base := ReduceToBase(into)
errCantUse := func () error {
return participle.Errorf (
literal.Pos, "cannot use string literal as %v",
return errors.Errorf (
literal.Position, "cannot use string literal as %v",
into)
}
@ -82,14 +82,14 @@ func (this *Tree) analyzeLiteralString (
length = len(literal.ValueUTF8)
}
if length > 1 {
return nil, participle.Errorf (
literal.Pos,
return nil, errors.Errorf (
literal.Position,
"cannot fit string literal of length " +
"%v into %v",
length, into)
} else if length < 1 {
return nil, participle.Errorf (
literal.Pos,
return nil, errors.Errorf (
literal.Position,
"string literal must have data when " +
"assigning to %v",
into)
@ -108,8 +108,8 @@ func (this *Tree) analyzeLiteralString (
length = len(literal.ValueUTF8)
}
if length > base.Length {
return nil, participle.Errorf (
literal.Pos,
return nil, errors.Errorf (
literal.Position,
"cannot fit string literal of length " +
"%v into array of length %v",
length, base.Length)
@ -160,8 +160,8 @@ func (this *Tree) analyzeLiteralArray (
case *entity.TypeArray:
base := base.(*entity.TypeArray)
if base.Length < len(literal.Elements) {
return nil, participle.Errorf (
literal.Pos, "expected %v elements or less",
return nil, errors.Errorf (
literal.Position, "expected %v elements or less",
base.Length)
}
elementType = base.Element
@ -174,8 +174,8 @@ func (this *Tree) analyzeLiteralArray (
base := base.(*entity.TypePointer)
elementType = base.Referenced
default:
return nil, participle.Errorf (
literal.Pos, "cannot use array literal as %v",
return nil, errors.Errorf (
literal.Position, "cannot use array literal as %v",
into)
}
@ -199,8 +199,8 @@ func (this *Tree) analyzeLiteralStruct (
) {
base, ok := ReduceToBase(into).(*entity.TypeStruct)
if !ok {
return nil, participle.Errorf (
literal.Pos, "cannot use struct literal as %v",
return nil, errors.Errorf (
literal.Position, "cannot use struct literal as %v",
into)
}
@ -210,8 +210,8 @@ func (this *Tree) analyzeLiteralStruct (
for name, member := range literal.MemberMap {
correct, ok := base.MemberMap[name]
if !ok {
return nil, participle.Errorf (
literal.Pos, "no member %v.%s",
return nil, errors.Errorf (
literal.Position, "no member %v.%s",
into, name)
}
@ -233,8 +233,8 @@ func (this *Tree) analyzeLiteralBoolean (
error,
) {
if !isBoolean(into) {
return nil, participle.Errorf (
literal.Pos, "cannot use boolean literal as %v",
return nil, errors.Errorf (
literal.Position, "cannot use boolean literal as %v",
into)
}
@ -264,9 +264,9 @@ func (this *Tree) assembleStructLiteralMap (
literal.MemberOrder = make([]string, len(literal.Members))
for index, member := range literal.Members {
if previous, exists := literal.MemberMap[member.Name]; exists {
return literal, participle.Errorf (
member.Pos, "%s already listed in struct literal at %v",
member.Name, previous.Pos)
return literal, errors.Errorf (
member.Position, "%s already listed in struct literal at %v",
member.Name, previous.Position)
}
literal.MemberMap [member.Name] = member
literal.MemberOrder[index] = member.Name

View File

@ -1,13 +1,12 @@
package analyzer
import "fmt"
import "github.com/alecthomas/participle/v2"
import "github.com/alecthomas/participle/v2/lexer"
import "git.tebibyte.media/sashakoshka/fspl/errors"
import "git.tebibyte.media/sashakoshka/fspl/entity"
// analyzeMethod analyzes a method that is directly owned by the specified type.
func (this *Tree) analyzeMethod (
pos lexer.Position,
pos errors.Position,
typeName string,
name string,
) (
@ -26,7 +25,7 @@ func (this *Tree) analyzeMethod (
// error if method is missing
method, exists := this.rawMethods[typeName + "." + name]
if !exists {
return nil, participle.Errorf (
return nil, errors.Errorf (
pos, "no method named %s.%s",
typeName, name)
}
@ -52,12 +51,12 @@ func (this *Tree) analyzeMethod (
// add owner to method
method.This = &entity.Declaration {
Pos: method.Pos,
Name: "this",
Ty: &entity.TypePointer {
Pos: method.Pos,
Position: method.Position,
Name: "this",
Ty: &entity.TypePointer {
Position: method.Position,
Referenced: &entity.TypeNamed {
Pos: method.Pos,
Position: method.Position,
Name: typeName,
Type: owner.Type,
},
@ -88,7 +87,7 @@ func (this *Tree) methodExists (typeName, name string) bool {
// analyzeMethodOrBehavior returns *entity.Signature if it found an interface
// behavior, and *entity.Method if it found a method.
func (this *Tree) analyzeMethodOrBehavior (
pos lexer.Position,
pos errors.Position,
ty entity.Type,
name string,
) (
@ -99,7 +98,7 @@ func (this *Tree) analyzeMethodOrBehavior (
}
func (this *Tree) analyzeMethodOrBehaviorInternal (
pos lexer.Position,
pos errors.Position,
ty entity.Type,
name string,
pierceReference bool,
@ -124,7 +123,7 @@ func (this *Tree) analyzeMethodOrBehaviorInternal (
if behavior, ok := ty.BehaviorMap[name]; ok {
return behavior, nil
} else {
return nil, participle.Errorf (
return nil, errors.Errorf (
pos, "no behavior or method named %s",
name)
}
@ -135,7 +134,7 @@ func (this *Tree) analyzeMethodOrBehaviorInternal (
return this.analyzeMethodOrBehaviorInternal (
pos, ty.Referenced, name, false)
} else {
return nil, participle.Errorf (
return nil, errors.Errorf (
pos, "no method named %s defined on this type",
name)
}
@ -147,7 +146,7 @@ func (this *Tree) analyzeMethodOrBehaviorInternal (
*entity.TypeFloat,
*entity.TypeWord:
return nil, participle.Errorf (
return nil, errors.Errorf (
pos, "no method named %s defined on this type",
name)

View File

@ -1,6 +1,6 @@
package analyzer
import "github.com/alecthomas/participle/v2"
import "git.tebibyte.media/sashakoshka/fspl/errors"
import "git.tebibyte.media/sashakoshka/fspl/entity"
func (this *Tree) assembleSignatureMap (signature *entity.Signature) (*entity.Signature, error) {
@ -8,9 +8,9 @@ func (this *Tree) assembleSignatureMap (signature *entity.Signature) (*entity.Si
signature.ArgumentOrder = make([]string, len(signature.Arguments))
for index, member := range signature.Arguments {
if previous, exists := signature.ArgumentMap[member.Name]; exists {
return signature, participle.Errorf (
member.Pos, "%s already listed as argument at %v",
member.Name, previous.Pos)
return signature, errors.Errorf (
member.Position, "%s already listed as argument at %v",
member.Name, previous.Position)
}
signature.ArgumentMap [member.Name] = member
signature.ArgumentOrder[index] = member.Name

View File

@ -1,28 +0,0 @@
package analyzer
// import "fmt"
//import "github.com/alecthomas/participle/v2"
import "git.tebibyte.media/sashakoshka/fspl/entity"
func (this *Tree) analyzeAssignment (
assignment *entity.Assignment,
) (
entity.Statement,
error,
) {
// analyze location
location, err := this.analyzeExpression(nil, strict, assignment.Location)
if err != nil { return nil, err }
assignment.Location = location
// ensure location is location expression
err = this.isLocationExpression(location)
if err != nil { return nil, err }
// analyze value
value, err := this.analyzeExpression(location.Type(), strict, assignment.Value)
if err != nil { return nil, err }
assignment.Value = value
return assignment, nil
}

View File

@ -1,7 +1,6 @@
package analyzer
import "github.com/alecthomas/participle/v2"
import "github.com/alecthomas/participle/v2/lexer"
import "git.tebibyte.media/sashakoshka/fspl/errors"
import "git.tebibyte.media/sashakoshka/fspl/entity"
import "git.tebibyte.media/sashakoshka/fspl/parser"
@ -36,21 +35,21 @@ func (this *Tree) assembleRawMaps () error {
switch declaration.(type) {
case *entity.Typedef:
ty := declaration.(*entity.Typedef)
err := this.topLevelNameAvailable(ty.Pos, ty.Name)
err := this.topLevelNameAvailable(ty.Position, ty.Name)
if err != nil { return err }
ty.Methods = make(map[string] *entity.Method)
this.rawTypes[ty.Name] = ty
case *entity.Function:
function := declaration.(*entity.Function)
err := this.topLevelNameAvailable (
function.Pos,
function.Position,
function.Signature.Name)
if err != nil { return err }
this.rawFunctions[function.Signature.Name] = function
case *entity.Method:
method := declaration.(*entity.Method)
name := method.TypeName + "." + method.Signature.Name
err := this.topLevelNameAvailable(method.Pos, name)
err := this.topLevelNameAvailable(method.Position, name)
if err != nil { return err }
this.rawMethods[name] = method
}
@ -58,48 +57,48 @@ func (this *Tree) assembleRawMaps () error {
return nil
}
func (this *Tree) topLevelNameAvailable (currentPos lexer.Position, name string) error {
func (this *Tree) topLevelNameAvailable (currentPos errors.Position, name string) error {
if _, isPrimitive := primitiveTypes[name]; isPrimitive {
return participle.Errorf (
return errors.Errorf (
currentPos, "cannot shadow primitive %s",
name)
}
if _, isBuiltin := builtinTypes[name]; isBuiltin {
return participle.Errorf (
return errors.Errorf (
currentPos, "cannot shadow builtin %s",
name)
}
if ty, isType := this.rawTypes[name]; isType {
return participle.Errorf (
return errors.Errorf (
currentPos, "%s already declared at %v",
name, ty.Pos)
name, ty.Position)
}
if function, isFunction := this.rawFunctions[name]; isFunction {
return participle.Errorf (
return errors.Errorf (
currentPos, "%s already declared at %v",
name, function.Pos)
name, function.Position)
}
if method, isMethod := this.rawMethods[name]; isMethod {
return participle.Errorf (
return errors.Errorf (
currentPos, "%s already declared at %v",
name, method.Pos)
name, method.Position)
}
return nil
}
func (this *Tree) analyzeDeclarations () error {
for name, rawType := range this.rawTypes {
ty, err := this.analyzeTypedef(rawType.Pos, name, false)
ty, err := this.analyzeTypedef(rawType.Position, name, false)
if err != nil { return err }
this.Types[name] = ty
}
for name, rawFunction := range this.rawFunctions {
_, err := this.analyzeFunction(rawFunction.Pos, name)
_, err := this.analyzeFunction(rawFunction.Position, name)
if err != nil { return err }
}
for _, rawMethod := range this.rawMethods {
_, err := this.analyzeMethod (
rawMethod.Pos,
rawMethod.Position,
rawMethod.TypeName,
rawMethod.Signature.Name)
if err != nil { return err }
@ -117,9 +116,8 @@ func (this *Tree) ensure () {
this.Functions = make(map[string] *entity.Function)
for name, ty := range builtinTypes {
access := entity.AccessPublic
this.Types[name] = &entity.Typedef {
Acc: &access,
Acc: entity.AccessPublic,
Name: name,
Type: ty,
}

View File

@ -1,12 +1,11 @@
package analyzer
import "fmt"
import "github.com/alecthomas/participle/v2"
import "github.com/alecthomas/participle/v2/lexer"
import "git.tebibyte.media/sashakoshka/fspl/errors"
import "git.tebibyte.media/sashakoshka/fspl/entity"
func (this *Tree) analyzeTypedef (
pos lexer.Position,
pos errors.Position,
name string,
acceptIncomplete bool,
) (
@ -23,7 +22,7 @@ func (this *Tree) analyzeTypedef (
if acceptIncomplete {
return definition, nil
} else {
return nil, participle.Errorf (
return nil, errors.Errorf (
pos, "type %s cannot be used in this context",
name)
}
@ -32,7 +31,7 @@ func (this *Tree) analyzeTypedef (
// error if type is missing
definition, exists := this.rawTypes[name]
if !exists {
return nil, participle.Errorf(pos, "no type named %s", name)
return nil, errors.Errorf(pos, "no type named %s", name)
}
var err error
@ -83,7 +82,7 @@ func (this *Tree) analyzeTypeInternal (
return primitive, nil
}
var def *entity.Typedef
def, err = this.analyzeTypedef(ty.Pos, ty.Name, acceptIncomplete)
def, err = this.analyzeTypedef(ty.Position, ty.Name, acceptIncomplete)
if err == nil {
ty.Type = def.Type
}
@ -108,8 +107,8 @@ func (this *Tree) analyzeTypeInternal (
ty := ty.(*entity.TypeArray)
updateIncompleteInfo()
if ty.Length < 1 {
return ty, participle.Errorf (
ty.Pos, "array length must be > 0")
return ty, errors.Errorf (
ty.Position, "array length must be > 0")
}
ty.Element, err = this.analyzeType(ty.Element, false)
return ty, err
@ -144,8 +143,8 @@ func (this *Tree) analyzeTypeInternal (
ty := ty.(*entity.TypeInt)
updateIncompleteInfo()
if ty.Width < 1 {
return ty, participle.Errorf (
ty.Pos, "integer width must be > 0")
return ty, errors.Errorf (
ty.Position, "integer width must be > 0")
}
return ty, nil
@ -162,9 +161,9 @@ func (this *Tree) assembleStructMap (ty *entity.TypeStruct) (*entity.TypeStruct,
ty.MemberOrder = make([]string, len(ty.Members))
for index, member := range ty.Members {
if previous, exists := ty.MemberMap[member.Name]; exists {
return ty, participle.Errorf (
member.Pos, "%s already listed in struct at %v",
member.Name, previous.Pos)
return ty, errors.Errorf (
member.Position, "%s already listed in struct at %v",
member.Name, previous.Position)
}
ty.MemberMap [member.Name] = member
ty.MemberOrder[index] = member.Name
@ -178,9 +177,9 @@ func (this *Tree) assembleInterfaceMap (ty *entity.TypeInterface) (*entity.TypeI
ty.BehaviorOrder = make([]string, len(ty.Behaviors))
for index, method := range ty.Behaviors {
if previous, exists := ty.BehaviorMap[method.Name]; exists {
return ty, participle.Errorf (
method.Pos, "%s already listed in interface at %v",
method.Name, previous.Pos)
return ty, errors.Errorf (
method.Position, "%s already listed in interface at %v",
method.Name, previous.Position)
}
ty.BehaviorMap [method.Name] = method
ty.BehaviorOrder[index] = method.Name