Location expressions
This commit is contained in:
parent
bec91323b9
commit
2a5ffb12a1
@ -127,3 +127,77 @@ func (this *Tree) reduceToBase (ty entity.Type) entity.Type {
|
||||
return ty
|
||||
}
|
||||
}
|
||||
|
||||
// isLocationExpression returns whether or not an expression is a valid location
|
||||
// expression.
|
||||
func (this *Tree) isLocationExpression (expression entity.Expression) error {
|
||||
switch expression.(type) {
|
||||
case *entity.Variable:
|
||||
return nil
|
||||
case *entity.Declaration:
|
||||
return nil
|
||||
case *entity.Call:
|
||||
return participle.Errorf (
|
||||
expression.(*entity.Call).Pos,
|
||||
"cannot assign to function call")
|
||||
case *entity.MethodCall:
|
||||
return participle.Errorf (
|
||||
expression.(*entity.MethodCall).Pos,
|
||||
"cannot assign to method call")
|
||||
case *entity.Subscript:
|
||||
return this.isLocationExpression (
|
||||
expression.(*entity.Subscript).Slice)
|
||||
case *entity.Slice:
|
||||
return participle.Errorf (
|
||||
expression.(*entity.MethodCall).Pos,
|
||||
"cannot assign to slice operation")
|
||||
case *entity.Dereference:
|
||||
return this.isLocationExpression (
|
||||
expression.(*entity.Dereference).Pointer)
|
||||
case *entity.Reference:
|
||||
return participle.Errorf (
|
||||
expression.(*entity.Reference).Pos,
|
||||
"cannot assign to reference operation")
|
||||
case *entity.ValueCast:
|
||||
return participle.Errorf (
|
||||
expression.(*entity.ValueCast).Pos,
|
||||
"cannot assign to value cast")
|
||||
case *entity.BitCast:
|
||||
return participle.Errorf (
|
||||
expression.(*entity.BitCast).Pos,
|
||||
"cannot assign to bit cast")
|
||||
case *entity.Operation:
|
||||
expression := expression.(*entity.Operation)
|
||||
return participle.Errorf (
|
||||
expression.Pos,
|
||||
"cannot assign to %v operation",
|
||||
expression.Operator)
|
||||
case *entity.Block:
|
||||
return participle.Errorf (
|
||||
expression.(*entity.Block).Pos,
|
||||
"cannot assign to block")
|
||||
case *entity.MemberAccess:
|
||||
return this.isLocationExpression (
|
||||
expression.(*entity.MemberAccess).Source)
|
||||
case *entity.IfElse:
|
||||
return participle.Errorf (
|
||||
expression.(*entity.Block).Pos,
|
||||
"cannot assign to if/else")
|
||||
case *entity.Loop:
|
||||
return participle.Errorf (
|
||||
expression.(*entity.Block).Pos,
|
||||
"cannot assign to loop")
|
||||
case *entity.Break:
|
||||
return participle.Errorf (
|
||||
expression.(*entity.Block).Pos,
|
||||
"cannot assign to break statement")
|
||||
case *entity.Return:
|
||||
return participle.Errorf (
|
||||
expression.(*entity.Block).Pos,
|
||||
"cannot assign to return statement")
|
||||
default:
|
||||
panic(fmt.Sprint (
|
||||
"BUG: analyzer doesnt know about expression ",
|
||||
expression))
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ func (this *Tree) analyzeVariable (
|
||||
variable.Name)
|
||||
}
|
||||
|
||||
err := this.canAssign(variable.Pos, into, mode, declaration.Type)
|
||||
err := this.canAssign(variable.Pos, into, mode, declaration.Type())
|
||||
if err != nil { return nil, err }
|
||||
|
||||
variable.Declaration = declaration
|
||||
@ -47,11 +47,11 @@ func (this *Tree) analyzeDeclaration (
|
||||
declaration.Name, existing.Pos)
|
||||
}
|
||||
|
||||
ty, err := this.analyzeType(declaration.Type, false)
|
||||
declaration.Type = ty
|
||||
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.Pos, into, mode, declaration.Type())
|
||||
if err != nil { return nil, err }
|
||||
|
||||
this.AddVariable(declaration)
|
||||
@ -94,7 +94,7 @@ func (this *Tree) analyzeCall (
|
||||
for index, argument := range call.Arguments {
|
||||
signature := function.Signature
|
||||
correct := signature.ArgumentMap[signature.ArgumentOrder[index]]
|
||||
argument, err := this.analyzeExpression(correct.Type, strict, argument)
|
||||
argument, err := this.analyzeExpression(correct.Type(), strict, argument)
|
||||
if err != nil { return nil, err }
|
||||
call.Arguments[index] = argument
|
||||
}
|
||||
@ -115,7 +115,7 @@ func (this *Tree) analyzeMethodCall (
|
||||
source := sourceExpr.(*entity.Variable)
|
||||
if err != nil { return nil, err }
|
||||
method, err := this.analyzeMethodOrBehavior (
|
||||
call.Pos, source.Declaration.Type, call.Name)
|
||||
call.Pos, source.Declaration.Type(), call.Name)
|
||||
|
||||
// extract signature
|
||||
var signature *entity.Signature
|
||||
@ -150,7 +150,7 @@ func (this *Tree) analyzeMethodCall (
|
||||
// check arg types
|
||||
for index, argument := range call.Arguments {
|
||||
correct := signature.ArgumentMap[signature.ArgumentOrder[index]]
|
||||
argument, err := this.analyzeExpression(correct.Type, strict, argument)
|
||||
argument, err := this.analyzeExpression(correct.Type(), strict, argument)
|
||||
if err != nil { return nil, err }
|
||||
call.Arguments[index] = argument
|
||||
}
|
||||
@ -174,6 +174,7 @@ func (this *Tree) analyzeSubscript (
|
||||
subscript.Slice)
|
||||
if err != nil { return nil, err }
|
||||
subscript.Slice = slice
|
||||
subscript.Ty = into
|
||||
|
||||
offset, err := this.analyzeExpression (
|
||||
builtinType("index"), weak,
|
||||
@ -192,9 +193,9 @@ func (this *Tree) analyzeSlice (
|
||||
entity.Expression,
|
||||
error,
|
||||
) {
|
||||
slice, err := this.analyzeExpression(into, weak, slice.Slice)
|
||||
value, err := this.analyzeExpression(into, weak, slice.Slice)
|
||||
if err != nil { return nil, err }
|
||||
slice.Slice = slice
|
||||
slice.Slice = value
|
||||
|
||||
if slice.Start != nil {
|
||||
start, err := this.analyzeExpression (
|
||||
@ -225,12 +226,13 @@ func (this *Tree) analyzeDereference (
|
||||
) {
|
||||
pointer, err := this.analyzeExpression (
|
||||
&entity.TypePointer {
|
||||
Pos: subscript.Pos,
|
||||
Pos: dereference.Pos,
|
||||
Referenced: into,
|
||||
}, weak,
|
||||
dereference.Pointer)
|
||||
if err != nil { return nil, err }
|
||||
dereference.Pointer = pointer
|
||||
dereference.Ty = into
|
||||
|
||||
return pointer, nil
|
||||
}
|
||||
@ -243,15 +245,19 @@ func (this *Tree) analyzeReference (
|
||||
entity.Expression,
|
||||
error,
|
||||
) {
|
||||
reference, ok := into.(*entity.TypePointer)
|
||||
if !ok { return nil, participle.Errorf(pos, "expected %v", into) }
|
||||
referenced, ok := into.(*entity.TypePointer)
|
||||
if !ok {
|
||||
return nil, participle.Errorf(reference.Pos, "expected %v", into)
|
||||
}
|
||||
|
||||
value, err := this.analyzeExpression (
|
||||
referenced.Referenced,
|
||||
reference.Pointer)
|
||||
referenced.Referenced, weak,
|
||||
reference.Value)
|
||||
if err != nil { return nil, err }
|
||||
err = this.isLocationExpression(reference.Value)
|
||||
if err != nil { return nil, err }
|
||||
// TODO error if value is not a location expression
|
||||
reference.Value = value
|
||||
reference.Ty = into
|
||||
|
||||
return pointer, nil
|
||||
return reference, nil
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ func (this *Tree) analyzeFunction (
|
||||
function.Signature, err = this.assembleSignatureMap(function.Signature)
|
||||
if err != nil { return function, err }
|
||||
for name, argument := range function.Signature.ArgumentMap {
|
||||
argument.Type, err = this.analyzeType(argument.Type, false)
|
||||
argument.Ty, err = this.analyzeType(argument.Ty, false)
|
||||
this.AddVariable(argument)
|
||||
function.Signature.ArgumentMap[name] = argument
|
||||
if err != nil { return function, err }
|
||||
|
@ -41,7 +41,7 @@ func (this *Tree) analyzeMethod (
|
||||
method.Signature, err = this.assembleSignatureMap(method.Signature)
|
||||
if err != nil { return method, err }
|
||||
for name, argument := range method.Signature.ArgumentMap {
|
||||
argument.Type, err = this.analyzeType(argument.Type, false)
|
||||
argument.Ty, err = this.analyzeType(argument.Ty, false)
|
||||
this.AddVariable(argument)
|
||||
method.Signature.ArgumentMap[name] = argument
|
||||
if err != nil { return method, err }
|
||||
|
@ -5,15 +5,24 @@ package analyzer
|
||||
import "git.tebibyte.media/sashakoshka/fspl/entity"
|
||||
|
||||
func (this *Tree) analyzeAssignment (
|
||||
variable *entity.Assignment,
|
||||
assignment *entity.Assignment,
|
||||
) (
|
||||
entity.Statement,
|
||||
error,
|
||||
) {
|
||||
// TODO
|
||||
// 1. analyze location
|
||||
// 2. ensure location is location expression
|
||||
// 3. analyze value
|
||||
return nil, nil
|
||||
}
|
||||
// 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
|
||||
}
|
||||
|
@ -123,8 +123,8 @@ func (this *Tree) analyzeTypeInternal (
|
||||
updateIncompleteInfo()
|
||||
if err != nil { return ty, err }
|
||||
for name, member := range ty.MemberMap {
|
||||
ty.MemberMap[name].Type,
|
||||
err = this.analyzeType(member.Type, false)
|
||||
ty.MemberMap[name].Ty,
|
||||
err = this.analyzeType(member.Ty, false)
|
||||
if err != nil { return ty, err }
|
||||
}
|
||||
return ty, nil
|
||||
@ -195,7 +195,7 @@ func (this *Tree) analyzeBehavior (behavior *entity.Signature) (*entity.Signatur
|
||||
behavior, err := this.assembleSignatureMap(behavior)
|
||||
if err != nil { return behavior, nil }
|
||||
for name, argument := range behavior.ArgumentMap {
|
||||
behavior.ArgumentMap[name].Type, err = this.analyzeType(argument.Type, false)
|
||||
behavior.ArgumentMap[name].Ty, err = this.analyzeType(argument.Ty, false)
|
||||
if err != nil { return behavior, err }
|
||||
}
|
||||
behavior.Return, err = this.analyzeType(behavior.Return, false)
|
||||
|
@ -5,8 +5,10 @@ import "github.com/alecthomas/participle/v2/lexer"
|
||||
|
||||
// Expression is any construct that can be evaluated.
|
||||
type Expression interface {
|
||||
expression ()
|
||||
Statement
|
||||
Type () Type
|
||||
|
||||
expression ()
|
||||
}
|
||||
|
||||
// Statement is any construct that can be placed inside of a block expression.
|
||||
@ -28,6 +30,7 @@ type Variable struct {
|
||||
}
|
||||
func (*Variable) expression(){}
|
||||
func (*Variable) statement(){}
|
||||
func (this *Variable) Type () Type { return this.Declaration.Type() }
|
||||
func (this *Variable) String () string {
|
||||
return this.Name
|
||||
}
|
||||
@ -40,10 +43,11 @@ func (this *Variable) String () string {
|
||||
type Declaration struct {
|
||||
Pos lexer.Position
|
||||
Name string `parser:" @Ident "`
|
||||
Type Type `parser:" ':' @@ "`
|
||||
Ty Type `parser:" ':' @@ "`
|
||||
}
|
||||
func (*Declaration) expression(){}
|
||||
func (*Declaration) statement(){}
|
||||
func (this *Declaration) Type () Type { return this.Ty }
|
||||
func (this *Declaration) String () string {
|
||||
return fmt.Sprint(this.Name, ":", this.Type)
|
||||
}
|
||||
@ -56,7 +60,7 @@ func (this *Declaration) String () string {
|
||||
// expression.
|
||||
type Call struct {
|
||||
// Syntax
|
||||
Pos lexer.Position
|
||||
Pos lexer.Position
|
||||
Name string `parser:" '[' @Ident "`
|
||||
Arguments []Expression `parser:" @@* ']' "`
|
||||
|
||||
@ -65,6 +69,7 @@ type Call struct {
|
||||
}
|
||||
func (*Call) expression(){}
|
||||
func (*Call) statement(){}
|
||||
func (this *Call) Type () Type { return this.Function.Signature.Return }
|
||||
func (this *Call) String () string {
|
||||
out := fmt.Sprint("[", this.Name)
|
||||
for _, argument := range this.Arguments {
|
||||
@ -81,7 +86,7 @@ func (this *Call) String () string {
|
||||
// A method call is never a valid location expression.
|
||||
type MethodCall struct {
|
||||
// Syntax
|
||||
Pos lexer.Position
|
||||
Pos lexer.Position
|
||||
Source *Variable `parser:" @@ '.' "`
|
||||
Name string `parser:" '[' @Ident "`
|
||||
Arguments []Expression `parser:" @@* ']' "`
|
||||
@ -89,9 +94,17 @@ type MethodCall struct {
|
||||
// Semantics
|
||||
Method *Method
|
||||
Behavior *Signature
|
||||
Ty Type
|
||||
}
|
||||
func (*MethodCall) expression(){}
|
||||
func (*MethodCall) statement(){}
|
||||
func (this *MethodCall) Type () Type {
|
||||
if this.Method != nil {
|
||||
return this.Method.Signature.Return
|
||||
} else {
|
||||
return this.Behavior.Return
|
||||
}
|
||||
}
|
||||
func (this *MethodCall) String () string {
|
||||
out := fmt.Sprint(this.Source, ".[", this.Name)
|
||||
for _, argument := range this.Arguments {
|
||||
@ -106,12 +119,17 @@ func (this *MethodCall) String () string {
|
||||
// information, it may be directly assigned to an interface. A subscript is a
|
||||
// valid location expression only if the array being subscripted is.
|
||||
type Subscript struct {
|
||||
Pos lexer.Position
|
||||
Slice Expression `parser:" '[' '.' @@ "`
|
||||
Offset Expression `parser:" @@ ']' "`
|
||||
// Syntax
|
||||
Pos lexer.Position
|
||||
Slice Expression `parser:" '[' '.' @@ "`
|
||||
Offset Expression `parser:" @@ ']' "`
|
||||
|
||||
// Semantics
|
||||
Ty Type
|
||||
}
|
||||
func (*Subscript) expression(){}
|
||||
func (*Subscript) statement(){}
|
||||
func (this *Subscript) Type () Type { return this.Ty }
|
||||
func (this *Subscript) String () string {
|
||||
return fmt.Sprint("[.", this.Slice, " ", this.Offset, "]")
|
||||
}
|
||||
@ -121,13 +139,15 @@ func (this *Subscript) String () string {
|
||||
// assignment rules of this expression are equivalent to those of the slice it
|
||||
// is operating on. A slice is never a valid location expression.
|
||||
type Slice struct {
|
||||
Pos lexer.Position
|
||||
// Syntax
|
||||
Pos lexer.Position
|
||||
Slice Expression `parser:" '[' '\\\\' @@ "`
|
||||
Start Expression `parser:" @@? "`
|
||||
End Expression `parser:" ':' @@? ']' "`
|
||||
}
|
||||
func (*Slice) expression(){}
|
||||
func (*Slice) statement(){}
|
||||
func (this *Slice) Type () Type { return this.Slice.Type() }
|
||||
func (this *Slice) String () string {
|
||||
out := fmt.Sprint("[\\", this.Slice, " ")
|
||||
if this.Start != nil {
|
||||
@ -146,11 +166,16 @@ func (this *Slice) String () string {
|
||||
// assigned to an interface. A dereference is a valid location expression only
|
||||
// if the pointer being dereferenced is.
|
||||
type Dereference struct {
|
||||
Pos lexer.Position
|
||||
// Syntax
|
||||
Pos lexer.Position
|
||||
Pointer Expression `parser:" '[' '.' @@ ']' "`
|
||||
|
||||
// Semantics
|
||||
Ty Type
|
||||
}
|
||||
func (*Dereference) expression(){}
|
||||
func (*Dereference) statement(){}
|
||||
func (this *Dereference) Type () Type { return this.Ty }
|
||||
func (this *Dereference) String () string {
|
||||
return fmt.Sprint("[.", this.Pointer, "]")
|
||||
}
|
||||
@ -163,11 +188,16 @@ func (this *Dereference) String () string {
|
||||
// automatically references it anyway. A reference is never a valid location
|
||||
// expression.
|
||||
type Reference struct {
|
||||
Pos lexer.Position
|
||||
// Syntax
|
||||
Pos lexer.Position
|
||||
Value Expression `parser:" '[' '@' @@ ']' "`
|
||||
|
||||
// Semantics
|
||||
Ty Type
|
||||
}
|
||||
func (*Reference) expression(){}
|
||||
func (*Reference) statement(){}
|
||||
func (this *Reference) Type () Type { return this.Ty }
|
||||
func (this *Reference) String () string {
|
||||
return fmt.Sprint("[@", this.Value, "]")
|
||||
}
|
||||
@ -176,12 +206,13 @@ func (this *Reference) String () string {
|
||||
// contains inherent type information, it may be directly assigned to an
|
||||
// interface. A value cast is never a valid location expression.
|
||||
type ValueCast struct {
|
||||
Pos lexer.Position
|
||||
Type Type `parser:" '[' '~' @@ "`
|
||||
Pos lexer.Position
|
||||
Ty Type `parser:" '[' '~' @@ "`
|
||||
Value Expression `parser:" @@ ']' "`
|
||||
}
|
||||
func (*ValueCast) expression(){}
|
||||
func (*ValueCast) statement(){}
|
||||
func (this *ValueCast) Type () Type { return this.Ty }
|
||||
func (this *ValueCast) String () string {
|
||||
return fmt.Sprint("[~ ", this.Type, this.Value, "]")
|
||||
}
|
||||
@ -191,12 +222,13 @@ func (this *ValueCast) String () string {
|
||||
// it may be directly assigned to an interface. A bit cast is never a valid
|
||||
// location expression.
|
||||
type BitCast struct {
|
||||
Pos lexer.Position
|
||||
Type Type `parser:" '[' '~~' @@ "`
|
||||
Pos lexer.Position
|
||||
Ty Type `parser:" '[' '~~' @@ "`
|
||||
Value Expression `parser:" @@ ']' "`
|
||||
}
|
||||
func (*BitCast) expression(){}
|
||||
func (*BitCast) statement(){}
|
||||
func (this *BitCast) Type () Type { return this.Ty }
|
||||
func (this *BitCast) String () string {
|
||||
return fmt.Sprint("[~~ ", this.Type, this.Value, "]")
|
||||
}
|
||||
@ -206,12 +238,17 @@ func (this *BitCast) String () string {
|
||||
// special cases. Since they contain no inherent type information, they may not
|
||||
// be assigned to interfaces. An operation is never a valid location expression.
|
||||
type Operation struct {
|
||||
// Syntax
|
||||
Pos lexer.Position
|
||||
Operator Operator `parser:" '[' @('++' | '+' | '--' | '-' | '*' | '/' | '%' | '!!' | '||' | '&&' | '^^' | '!' | '|' | '&' | '^' | '<<' | '>>' | '<' | '>' | '<=' | '>=' | '=') "`
|
||||
Arguments []Expression `parser:" @@+ ']' "`
|
||||
|
||||
// Semantics
|
||||
Ty Type
|
||||
}
|
||||
func (*Operation) expression(){}
|
||||
func (*Operation) statement(){}
|
||||
func (this *Operation) Type () Type { return this.Ty }
|
||||
func (this *Operation) String () string {
|
||||
out := fmt.Sprint("[", this.Operator)
|
||||
for _, argument := range this.Arguments {
|
||||
@ -231,10 +268,12 @@ type Block struct {
|
||||
Steps []Statement `parser:" '{' @@* '}' "`
|
||||
|
||||
// Semantics
|
||||
Ty Type
|
||||
Scope
|
||||
}
|
||||
func (*Block) expression(){}
|
||||
func (*Block) statement(){}
|
||||
func (this *Block) Type () Type { return this.Ty }
|
||||
func (this *Block) String () string {
|
||||
out := "{"
|
||||
for index, step := range this.Steps {
|
||||
@ -251,12 +290,17 @@ func (this *Block) String () string {
|
||||
// an interface. A member access is a valid location expression only when the
|
||||
// struct being accessed is.
|
||||
type MemberAccess struct {
|
||||
// Syntax
|
||||
Pos lexer.Position
|
||||
Source *Variable `parser:" @@ "`
|
||||
Member string `parser:" '.' @Ident "`
|
||||
|
||||
// Semantics
|
||||
Ty Type
|
||||
}
|
||||
func (*MemberAccess) expression(){}
|
||||
func (*MemberAccess) statement(){}
|
||||
func (this *MemberAccess) Type () Type { return this.Ty }
|
||||
func (this *MemberAccess) String () string {
|
||||
return fmt.Sprint(this.Source, ".", this.Member)
|
||||
}
|
||||
@ -267,13 +311,18 @@ func (this *MemberAccess) String () string {
|
||||
// type that satisfies the assignment rules of both the true and false
|
||||
// expressions. An If/else is never a valid location expression.
|
||||
type IfElse struct {
|
||||
// Syntax
|
||||
Pos lexer.Position
|
||||
Condition Expression `parser:" 'if' @@ "`
|
||||
True Expression `parser:" 'then' @@ "`
|
||||
False Expression `parser:" ('else' @@)? "`
|
||||
|
||||
// Semantics
|
||||
Ty Type
|
||||
}
|
||||
func (*IfElse) expression(){}
|
||||
func (*IfElse) statement(){}
|
||||
func (this *IfElse) Type () Type { return this.Ty }
|
||||
func (this *IfElse) String () string {
|
||||
out := fmt.Sprint("if ", this.Condition, " then ", this.True)
|
||||
if this.False != nil {
|
||||
@ -290,11 +339,16 @@ func (this *IfElse) String () string {
|
||||
// break statements only apply to the closest containing loop. The value of the
|
||||
// loop's expression is never used. A loop is never a valid location expression.
|
||||
type Loop struct {
|
||||
// Syntax
|
||||
Pos lexer.Position
|
||||
Body Expression `parser:" 'loop' @@ "`
|
||||
|
||||
// Semantics
|
||||
Ty Type
|
||||
}
|
||||
func (*Loop) expression(){}
|
||||
func (*Loop) statement(){}
|
||||
func (this *Loop) Type () Type { return this.Ty }
|
||||
func (this *Loop) String () string {
|
||||
return fmt.Sprint("loop ", this.Body)
|
||||
}
|
||||
@ -307,6 +361,7 @@ type Break struct {
|
||||
}
|
||||
func (*Break) expression(){}
|
||||
func (*Break) statement(){}
|
||||
func (this *Break) Type () Type { return &TypeVoid { } }
|
||||
func (this *Break) String () string {
|
||||
if this.Value == nil {
|
||||
return "[break]"
|
||||
@ -325,6 +380,7 @@ type Return struct {
|
||||
}
|
||||
func (*Return) expression(){}
|
||||
func (*Return) statement(){}
|
||||
func (this *Return) Type () Type { return &TypeVoid { } }
|
||||
func (this *Return) String () string {
|
||||
if this.Value == nil {
|
||||
return "[return]"
|
||||
|
@ -8,11 +8,16 @@ import "github.com/alecthomas/participle/v2/lexer"
|
||||
// interface because it contains no inherent type information. A value cast may
|
||||
// be used for this purpose.
|
||||
type LiteralInt struct {
|
||||
// Syntax
|
||||
Pos lexer.Position
|
||||
Value int `parser:" @Int "`
|
||||
|
||||
// Semantics
|
||||
Ty Type
|
||||
}
|
||||
func (*LiteralInt) expression(){}
|
||||
func (*LiteralInt) statement(){}
|
||||
func (this *LiteralInt) Type () Type { return this.Ty }
|
||||
func (this *LiteralInt) String () string {
|
||||
return fmt.Sprint(this.Value)
|
||||
}
|
||||
@ -22,11 +27,16 @@ func (this *LiteralInt) String () string {
|
||||
// because it contains no inherent type information. A value cast may be used
|
||||
// for this purpose.
|
||||
type LiteralFloat struct {
|
||||
// Syntax
|
||||
Pos lexer.Position
|
||||
Value float64 `parser:" @Float "`
|
||||
|
||||
// Semantics
|
||||
Ty Type
|
||||
}
|
||||
func (*LiteralFloat) expression(){}
|
||||
func (*LiteralFloat) statement(){}
|
||||
func (this *LiteralFloat) Type () Type { return this.Ty }
|
||||
func (this *LiteralFloat) String () string {
|
||||
return fmt.Sprint(this.Value)
|
||||
}
|
||||
@ -39,11 +49,16 @@ func (this *LiteralFloat) String () string {
|
||||
// It cannot be directly assigned to an interface because it contains no
|
||||
// inherent type information. A value cast may be used for this purpose.
|
||||
type LiteralArray struct {
|
||||
// Syntax
|
||||
Pos lexer.Position
|
||||
Elements []Expression `parser:" '(' '*' @@* ')' "`
|
||||
|
||||
// Semantics
|
||||
Ty Type
|
||||
}
|
||||
func (*LiteralArray) expression(){}
|
||||
func (*LiteralArray) statement(){}
|
||||
func (this *LiteralArray) Type () Type { return this.Ty }
|
||||
func (this *LiteralArray) String () string {
|
||||
out := "(*"
|
||||
for _, element := range this.Elements {
|
||||
@ -60,11 +75,16 @@ func (this *LiteralArray) String () string {
|
||||
// It cannot be directly assigned to an interface because it contains no
|
||||
// inherent type information. A value cast may be used for this purpose.
|
||||
type LiteralStruct struct {
|
||||
// Syntax
|
||||
Pos lexer.Position
|
||||
Members []Member `parser:" '(' @@* ')' "`
|
||||
|
||||
// Semantics
|
||||
Ty Type
|
||||
}
|
||||
func (*LiteralStruct) expression(){}
|
||||
func (*LiteralStruct) statement(){}
|
||||
func (this *LiteralStruct) Type () Type { return this.Ty }
|
||||
func (this *LiteralStruct) String () string {
|
||||
out := "("
|
||||
for index, member := range this.Members {
|
||||
@ -79,11 +99,16 @@ func (this *LiteralStruct) String () string {
|
||||
// an interface because it contains no inherent type information. A value cast
|
||||
// may be used for this purpose.
|
||||
type LiteralBoolean struct {
|
||||
// Syntax
|
||||
Pos lexer.Position
|
||||
Value *Boolean `parser:" @('true' | 'false') "`
|
||||
|
||||
// Semantics
|
||||
Ty Type
|
||||
}
|
||||
func (*LiteralBoolean) expression(){}
|
||||
func (*LiteralBoolean) statement(){}
|
||||
func (this *LiteralBoolean) Type () Type { return this.Ty }
|
||||
func (this *LiteralBoolean) String () string {
|
||||
if *this.Value {
|
||||
return "true"
|
||||
|
@ -38,7 +38,7 @@ func (this *Signature) Equals (ty Type) bool {
|
||||
real.Name != this.Name { return false }
|
||||
|
||||
for index, argument := range this.Arguments {
|
||||
if !argument.Type.Equals(real.Arguments[index].Type) {
|
||||
if !argument.Type().Equals(real.Arguments[index].Type()) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ func (this *TypeStruct) Equals (ty Type) bool {
|
||||
if !ok || len(real.Members) != len(this.Members) { return false }
|
||||
|
||||
for index, member := range this.Members {
|
||||
if !member.Type.Equals(real.Members[index].Type) {
|
||||
if !member.Type().Equals(real.Members[index].Type()) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user