Updated analyzer

This commit is contained in:
Sasha Koshka 2024-03-14 03:18:46 -04:00
parent 4df7a8905e
commit f58c01be52
8 changed files with 106 additions and 106 deletions

View File

@ -381,54 +381,54 @@ func (this *Tree) isLocationExpression (expression entity.Expression) error {
case *entity.Declaration:
return nil
case *entity.Call:
return cannot(expression.Position, "function call")
return cannot(expression.Position(), "function call")
case *entity.MethodCall:
return cannot(expression.Position, "method call")
return cannot(expression.Position(), "method call")
case *entity.Subscript:
return this.isLocationExpression(expression.Slice)
case *entity.Slice:
return cannot(expression.Position, "slice operation")
return cannot(expression.Position(), "slice operation")
case *entity.Dereference:
return this.isLocationExpression(expression.Pointer)
case *entity.Reference:
return cannot(expression.Position, "reference operation")
return cannot(expression.Position(), "reference operation")
case *entity.ValueCast:
return cannot(expression.Position, "value cast")
return cannot(expression.Position(), "value cast")
case *entity.BitCast:
return cannot(expression.Position, "bit cast")
return cannot(expression.Position(), "bit cast")
case *entity.Operation:
return cannot(expression.Position, fmt.Sprintf (
return cannot(expression.Position(), fmt.Sprintf (
"cannot assign to %v operation",
expression.Operator))
case *entity.Block:
return cannot(expression.Position, "block")
return cannot(expression.Position(), "block")
case *entity.MemberAccess:
return this.isLocationExpression (
expression.Source)
case *entity.IfElse:
return cannot(expression.Position, "if/else")
return cannot(expression.Position(), "if/else")
case *entity.Match:
return cannot(expression.Position, "match")
return cannot(expression.Position(), "match")
case *entity.Loop:
return cannot(expression.Position, "loop")
return cannot(expression.Position(), "loop")
case *entity.Break:
return cannot(expression.Position, "break statement")
return cannot(expression.Position(), "break statement")
case *entity.Return:
return cannot(expression.Position, "return statement")
return cannot(expression.Position(), "return statement")
case *entity.LiteralInt:
return cannot(expression.Position, "integer literal")
return cannot(expression.Position(), "integer literal")
case *entity.LiteralFloat:
return cannot(expression.Position, "float literal")
return cannot(expression.Position(), "float literal")
case *entity.LiteralString:
return cannot(expression.Position, "string literal")
return cannot(expression.Position(), "string literal")
case *entity.LiteralArray:
return cannot(expression.Position, "array literal")
return cannot(expression.Position(), "array literal")
case *entity.LiteralStruct:
return cannot(expression.Position, "struct literal")
return cannot(expression.Position(), "struct literal")
case *entity.LiteralBoolean:
return cannot(expression.Position, "boolean literal")
return cannot(expression.Position(), "boolean literal")
case *entity.LiteralNil:
return cannot(expression.Position, "nil literal")
return cannot(expression.Position(), "nil literal")
default:
panic(fmt.Sprint (
"BUG: analyzer doesnt know about expression",

View File

@ -43,11 +43,11 @@ func (this *Tree) analyzeVariable (
declaration := this.variable(variable.Name)
if declaration == nil {
return nil, errors.Errorf (
variable.Position, "no variable named %s",
variable.Position(), "no variable named %s",
variable.Name)
}
err := this.canAssign(variable.Position, into, mode, declaration.Type())
err := this.canAssign(variable.Position(), into, mode, declaration.Type())
if err != nil { return nil, err }
variable.Declaration = declaration
@ -66,16 +66,16 @@ func (this *Tree) analyzeDeclaration (
existing := scope.Variable(declaration.Name)
if existing != nil {
return nil, errors.Errorf (
declaration.Position,
declaration.Position(),
"%s already declared in block at %v",
declaration.Name, existing.Position)
declaration.Name, existing.Position())
}
ty, err := this.analyzeType(declaration.Ty, false)
declaration.Ty = ty
if err != nil { return nil, err }
err = this.canAssign(declaration.Position, into, mode, declaration.Type())
err = this.canAssign(declaration.Position(), into, mode, declaration.Type())
if err != nil { return nil, err }
this.addVariable(declaration)
@ -91,35 +91,35 @@ func (this *Tree) analyzeCall (
error,
) {
// get function
unit, err := this.resolveNickname(call.Position, call.UnitNickname)
unit, err := this.resolveNickname(call.Position(), call.UnitNickname)
if err != nil { return nil, err }
function, err := this.analyzeFunction(call.Position, entity.Key {
function, err := this.analyzeFunction(call.Position(), entity.Key {
Unit: unit,
Name: call.Name,
})
if err != nil { return nil, err }
call.Function = function
call.Unit = function.Unit
call.Unit = function.Unit()
// check access permissions
if function.Acc == entity.AccessPrivate && function.Unit != this.unit {
if function.Acc == entity.AccessPrivate && function.Unit() != this.unit {
return nil, errors.Errorf (
call.Position, "function %v::[%v] is private",
call.Position(), "function %v::[%v] is private",
call.UnitNickname, call.Name)
}
// check return result
err = this.canAssign(call.Position, 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, errors.Errorf (
call.Position, "too many arguments in call to %s",
call.Position(), "too many arguments in call to %s",
call.Name)
} else if len(call.Arguments) < len(function.Signature.Arguments) {
return nil, errors.Errorf (
call.Position, "too few arguments in call to %s",
call.Position(), "too few arguments in call to %s",
call.Name)
}
@ -147,7 +147,7 @@ func (this *Tree) analyzeMethodCall (
source, err := this.analyzeExpression(nil, strict, call.Source)
if err != nil { return nil, err }
method, err := this.analyzeMethodOrBehavior (
call.Position, source.Type(), call.Name)
call.Position(), source.Type(), call.Name)
if err != nil { return nil, err }
// extract signature
@ -159,7 +159,7 @@ func (this *Tree) analyzeMethodCall (
// since this is a behavior, check access permissions of the
// interface
err = this.typeOpaque(call.Position, source.Type())
err = this.typeOpaque(call.Position(), source.Type())
if err != nil { return nil, err }
case *entity.Method:
@ -168,9 +168,9 @@ func (this *Tree) analyzeMethodCall (
// since this is a method, check access permissions of the
// method
if method.Acc == entity.AccessPrivate && method.Unit != this.unit {
if method.Acc == entity.AccessPrivate && method.Unit() != this.unit {
return nil, errors.Errorf (
call.Position, "method %v.[%v] is private",
call.Position(), "method %v.[%v] is private",
method.TypeName, method.Signature.Name)
}
@ -181,17 +181,17 @@ func (this *Tree) analyzeMethodCall (
}
// check return result
err = this.canAssign(call.Position, 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, errors.Errorf (
call.Position, "too many arguments in call to %s",
call.Position(), "too many arguments in call to %s",
call.Name)
} else if len(call.Arguments) < len(signature.Arguments) {
return nil, errors.Errorf (
call.Position, "too few arguments in call to %s",
call.Position(), "too few arguments in call to %s",
call.Name)
}
@ -216,7 +216,7 @@ func (this *Tree) analyzeSubscript (
) {
slice, err := this.analyzeExpression (
&entity.TypeSlice {
Pos: subscript.Position,
Pos: subscript.Position(),
Element: into,
}, weak,
subscript.Slice)
@ -225,7 +225,7 @@ func (this *Tree) analyzeSubscript (
subscript.Ty = into
// check permissions
err = this.typeOpaque(subscript.Position, slice.Type())
err = this.typeOpaque(subscript.Position(), slice.Type())
if err != nil { return nil, err }
offset, err := this.analyzeExpression (
@ -264,7 +264,7 @@ func (this *Tree) analyzeSlice (
slice.Slice = value
// check permissions
err = this.typeOpaque(slice.Position, value.Type())
err = this.typeOpaque(slice.Position(), value.Type())
if err != nil { return nil, err }
if slice.Start != nil {
@ -312,7 +312,7 @@ func (this *Tree) analyzeDereference (
) {
pointer, err := this.analyzeExpression (
&entity.TypePointer {
Pos: dereference.Position,
Pos: dereference.Position(),
Referenced: into,
}, weak,
dereference.Pointer)
@ -346,7 +346,7 @@ func (this *Tree) analyzeReference (
) {
referenced, ok := into.(*entity.TypePointer)
if !ok {
return nil, errors.Errorf(reference.Position, "expected %v", into)
return nil, errors.Errorf(reference.Position(), "expected %v", into)
}
value, err := this.analyzeExpression (
@ -373,7 +373,7 @@ func (this *Tree) analyzeValueCast (
if err != nil { return nil, err }
cast.Ty = ty
err = this.canAssign(cast.Position, 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)
@ -395,7 +395,7 @@ func (this *Tree) analyzeBitCast (
if err != nil { return nil, err }
cast.Ty = ty
err = this.canAssign(cast.Position, 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)
@ -414,26 +414,26 @@ func (this *Tree) analyzeOperation (
error,
) {
// check permissions
err := this.typeOpaque(operation.Position, into)
err := this.typeOpaque(operation.Position(), into)
if err != nil { return nil, err }
intoUntrustworthy := into == nil || mode == force || mode == coerce
undefined := func (ty entity.Type) (entity.Expression, error) {
return nil, errors.Errorf (
operation.Position, "operator %v undefined for %v",
operation.Position(), "operator %v undefined for %v",
operation.Operator, entity.FormatType(ty))
}
wrongInto := func () (entity.Expression, error) {
return nil, errors.Errorf (
operation.Position, "expected %v",
operation.Position(), "expected %v",
entity.FormatType(into))
}
wrongArgCount := func () (entity.Expression, error) {
return nil, errors.Errorf (
operation.Position, "wrong argument count for %v",
operation.Position(), "wrong argument count for %v",
operation.Operator)
}
@ -453,7 +453,7 @@ func (this *Tree) analyzeOperation (
}
if argumentType == nil {
return nil, -1, errors.Errorf (
operation.Position,
operation.Position(),
"operation arguments have ambiguous type")
}
return argumentType, boss, err
@ -594,7 +594,7 @@ func (this *Tree) analyzeBlock (
if len(block.Steps) == 0 && into != nil {
return nil, errors.Errorf (
block.Position, "block must have at least one statement")
block.Position(), "block must have at least one statement")
}
final := len(block.Steps) - 1
@ -603,7 +603,7 @@ func (this *Tree) analyzeBlock (
expression, ok := step.(entity.Expression)
if !ok {
return nil, errors.Errorf (
block.Position, "expected expression")
block.Position(), "expected expression")
}
step, err := this.analyzeExpression(into, strict, expression)
@ -642,30 +642,30 @@ func (this *Tree) analyzeMemberAccess (
referenced, ok := ReduceToBase(sourceTypeAny.Referenced).(*entity.TypeStruct)
if !ok {
return nil, errors.Errorf (
access.Position, "cannot access members of %v",
access.Position(), "cannot access members of %v",
source)
}
sourceType = referenced
qualifiedSourceType = sourceTypeAny.Referenced
default:
return nil, errors.Errorf (
access.Position, "cannot access members of %v",
access.Position(), "cannot access members of %v",
source)
}
// check permissions
err = this.typeOpaque(access.Position, qualifiedSourceType)
err = this.typeOpaque(access.Position(), qualifiedSourceType)
if err != nil { return nil, err }
// get member
member, ok := sourceType.MemberMap[access.Member]
if !ok {
return nil, errors.Errorf (
access.Position, "no member %v",
access.Position(), "no member %v",
access)
}
err = this.canAssign(access.Position, into, mode, member.Type())
err = this.canAssign(access.Position(), into, mode, member.Type())
if err != nil { return nil, err }
access.Ty = member.Type()
@ -696,7 +696,7 @@ func (this *Tree) analyzeIfElse (
if ifelse.False == nil {
if into != nil {
return nil, errors.Errorf (
ifelse.Position,
ifelse.Position(),
"else case required when using value of if")
}
} else {
@ -726,7 +726,7 @@ func (this *Tree) analyzeMatch (
// FIXME: add Position() method to Expression, then change this
// error message (and others) #53
return nil, errors.Errorf (
match.Position, "type %v is not a union",
match.Position(), "type %v is not a union",
value.Type())
}
@ -761,7 +761,7 @@ func (this *Tree) analyzeMatch (
if into != nil && len(match.Cases) < len(rawUnion.Allowed) {
return nil, errors.Errorf (
match.Position,
match.Position(),
"match does not cover all types within %v",
value.Type())
}
@ -819,14 +819,14 @@ func (this *Tree) analyzeBreak (
loop, ok := this.topLoop()
if !ok {
return nil, errors.Errorf (
brk.Position,
brk.Position(),
"break statement must be within loop")
}
brk.Loop = loop
if loop.Type() != nil && brk.Value == nil {
return nil, errors.Errorf (
brk.Position,
brk.Position(),
"break statement must have value")
}
@ -858,7 +858,7 @@ func (this *Tree) analyzeReturn (
if ty != nil && ret.Value == nil {
return nil, errors.Errorf (
ret.Position,
ret.Position(),
"break statement must have value")
}

View File

@ -24,7 +24,7 @@ func (this *Tree) analyzeFunction (
}
// set unit
function.Unit = key.Unit
function.Unt = key.Unit
// functions cannot be marked as opaque
if function.Acc == entity.AccessOpaque {

View File

@ -12,18 +12,18 @@ func (this *Tree) analyzeLiteralInt (
entity.Expression,
error,
) {
err := this.typeOpaque(literal.Position, into)
err := this.typeOpaque(literal.Position(), into)
if err != nil { return nil, err }
if !isNumeric(into) {
return nil, errors.Errorf (
literal.Position, "cannot use integer literal as %v",
literal.Position(), "cannot use integer literal as %v",
entity.FormatType(into))
}
if isInteger(into) && !inRange(into, int64(literal.Value)) {
return nil, errors.Errorf (
literal.Position, "integer literal out of range for type %v",
literal.Position(), "integer literal out of range for type %v",
entity.FormatType(into))
}
@ -39,12 +39,12 @@ func (this *Tree) analyzeLiteralFloat (
entity.Expression,
error,
) {
err := this.typeOpaque(literal.Position, into)
err := this.typeOpaque(literal.Position(), into)
if err != nil { return nil, err }
if !isFloat(into) {
return nil, errors.Errorf (
literal.Position, "cannot use float literal as %v",
literal.Position(), "cannot use float literal as %v",
entity.FormatType(into))
}
@ -60,14 +60,14 @@ func (this *Tree) analyzeLiteralString (
entity.Expression,
error,
) {
err := this.typeOpaque(literal.Position, into)
err := this.typeOpaque(literal.Position(), into)
if err != nil { return nil, err }
base := ReduceToBase(into)
errCantUse := func () error {
return errors.Errorf (
literal.Position, "cannot use string literal as %v",
literal.Position(), "cannot use string literal as %v",
entity.FormatType(into))
}
@ -92,13 +92,13 @@ func (this *Tree) analyzeLiteralString (
}
if length > 1 {
return nil, errors.Errorf (
literal.Position,
literal.Position(),
"cannot fit string literal of length " +
"%v into %v",
length, entity.FormatType(into))
} else if length < 1 {
return nil, errors.Errorf (
literal.Position,
literal.Position(),
"string literal must have data when " +
"assigning to %v",
entity.FormatType(into))
@ -118,7 +118,7 @@ func (this *Tree) analyzeLiteralString (
}
if length > base.Length {
return nil, errors.Errorf (
literal.Position,
literal.Position(),
"cannot fit string literal of length " +
"%v into array of length %v",
length, base.Length)
@ -163,7 +163,7 @@ func (this *Tree) analyzeLiteralArray (
entity.Expression,
error,
) {
err := this.typeOpaque(literal.Position, into)
err := this.typeOpaque(literal.Position(), into)
if err != nil { return nil, err }
base := ReduceToBase(into)
@ -173,7 +173,7 @@ func (this *Tree) analyzeLiteralArray (
base := base.(*entity.TypeArray)
if base.Length < len(literal.Elements) {
return nil, errors.Errorf (
literal.Position, "expected %v elements or less",
literal.Position(), "expected %v elements or less",
base.Length)
}
elementType = base.Element
@ -187,7 +187,7 @@ func (this *Tree) analyzeLiteralArray (
elementType = base.Referenced
default:
return nil, errors.Errorf (
literal.Position, "cannot use array literal as %v",
literal.Position(), "cannot use array literal as %v",
entity.FormatType(into))
}
@ -209,13 +209,13 @@ func (this *Tree) analyzeLiteralStruct (
entity.Expression,
error,
) {
err := this.typeOpaque(literal.Position, into)
err := this.typeOpaque(literal.Position(), into)
if err != nil { return nil, err }
base, ok := ReduceToBase(into).(*entity.TypeStruct)
if !ok {
return nil, errors.Errorf (
literal.Position, "cannot use struct literal as %v",
literal.Position(), "cannot use struct literal as %v",
entity.FormatType(into))
}
@ -226,7 +226,7 @@ func (this *Tree) analyzeLiteralStruct (
correct, ok := base.MemberMap[name]
if !ok {
return nil, errors.Errorf (
literal.Position, "no member %v.%s",
literal.Position(), "no member %v.%s",
into, name)
}
@ -247,12 +247,12 @@ func (this *Tree) analyzeLiteralBoolean (
entity.Expression,
error,
) {
err := this.typeOpaque(literal.Position, into)
err := this.typeOpaque(literal.Position(), into)
if err != nil { return nil, err }
if !isBoolean(into) {
return nil, errors.Errorf (
literal.Position, "cannot use boolean literal as %v",
literal.Position(), "cannot use boolean literal as %v",
entity.FormatType(into))
}
@ -268,7 +268,7 @@ func (this *Tree) analyzeLiteralNil (
entity.Expression,
error,
) {
err := this.typeOpaque(literal.Position, into)
err := this.typeOpaque(literal.Position(), into)
if err != nil { return nil, err }
literal.Ty = into
@ -286,8 +286,8 @@ func (this *Tree) assembleStructLiteralMap (
for index, member := range literal.Members {
if previous, exists := literal.MemberMap[member.Name]; exists {
return literal, errors.Errorf (
member.Position, "%s already listed in struct literal at %v",
member.Name, previous.Position)
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

@ -30,7 +30,7 @@ func (this *Tree) analyzeMethod (
}
// set method's unit, very important information yes
method.Unit = owner.Unit
method.Unt = owner.Unit()
// methods cannot be marked as opaque
if method.Acc == entity.AccessOpaque {
@ -58,12 +58,12 @@ func (this *Tree) analyzeMethod (
// add owner to method
method.This = &entity.Declaration {
Position: method.Position,
Name: "this",
Pos: method.Position(),
Name: "this",
Ty: &entity.TypePointer {
Pos: method.Position,
Pos: method.Position(),
Referenced: &entity.TypeNamed {
Pos: method.Position,
Pos: method.Position(),
Unt: key.Unit,
Name: key.Name,
Type: owner.Type,

View File

@ -9,8 +9,8 @@ func (this *Tree) assembleSignatureMap (signature *entity.Signature) (*entity.Si
for index, member := range signature.Arguments {
if previous, exists := signature.ArgumentMap[member.Name]; exists {
return signature, errors.Errorf (
member.Position, "%s already listed as argument at %v",
member.Name, previous.Position)
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

@ -47,7 +47,7 @@ func (this *Tree) assembleRawMaps () error {
Unit: this.unit,
Name: declaration.Name,
}
err := this.topLevelNameAvailable(declaration.Position, key)
err := this.topLevelNameAvailable(declaration.Position(), key)
if err != nil { return err }
declaration.Methods = make(map[string] *entity.Method)
this.rawTypes[key] = declaration
@ -57,7 +57,7 @@ func (this *Tree) assembleRawMaps () error {
Unit: this.unit,
Name: declaration.Signature.Name,
}
err := this.topLevelNameAvailable(declaration.Position, key)
err := this.topLevelNameAvailable(declaration.Position(), key)
if err != nil { return err }
this.rawFunctions[key] = declaration
@ -67,7 +67,7 @@ func (this *Tree) assembleRawMaps () error {
Name: declaration.TypeName,
Method: declaration.Signature.Name,
}
err := this.topLevelNameAvailable(declaration.Position, key)
err := this.topLevelNameAvailable(declaration.Position(), key)
if err != nil { return err }
this.rawMethods[key] = declaration
}
@ -89,34 +89,34 @@ func (this *Tree) topLevelNameAvailable (currentPos errors.Position, key entity.
if ty, isType := this.rawTypes[key]; isType {
return errors.Errorf (
currentPos, "%s already declared at %v",
key.Name, ty.Position)
key.Name, ty.Position())
}
if function, isFunction := this.rawFunctions[key]; isFunction {
return errors.Errorf (
currentPos, "%s already declared at %v",
key.Name, function.Position)
key.Name, function.Position())
}
if method, isMethod := this.rawMethods[key]; isMethod {
return errors.Errorf (
currentPos, "%s.%s already declared at %v",
key.Name, key.Method, method.Position)
key.Name, key.Method, method.Position())
}
return nil
}
func (this *Tree) analyzeDeclarations () error {
for key, rawType := range this.rawTypes {
ty, err := this.analyzeTypedef(rawType.Position, key, false)
ty, err := this.analyzeTypedef(rawType.Position(), key, false)
if err != nil { return err }
this.Types[key] = ty
}
for key, rawFunction := range this.rawFunctions {
_, err := this.analyzeFunction(rawFunction.Position, key)
_, err := this.analyzeFunction(rawFunction.Position(), key)
if err != nil { return err }
}
for _, rawMethod := range this.rawMethods {
_, err := this.analyzeMethod (
rawMethod.Position,
rawMethod.Position(),
entity.Key {
Unit: this.unit,
Name: rawMethod.TypeName,

View File

@ -36,7 +36,7 @@ func (this *Tree) analyzeTypedef (
// analyze if it still needs to be analyzed
if definition, exists := this.rawTypes[key]; exists {
// update unit
definition.Unit = key.Unit
definition.Unt = key.Unit
// analyze
var err error
@ -246,8 +246,8 @@ func (this *Tree) assembleStructMap (ty *entity.TypeStruct) (*entity.TypeStruct,
for index, member := range ty.Members {
if previous, exists := ty.MemberMap[member.Name]; exists {
return ty, errors.Errorf (
member.Position, "%s already listed in struct at %v",
member.Name, previous.Position)
member.Position(), "%s already listed in struct at %v",
member.Name, previous.Position())
}
ty.MemberMap [member.Name] = member
ty.MemberOrder[index] = member.Name