272 lines
6.1 KiB
Go
272 lines
6.1 KiB
Go
package entity
|
|
|
|
import "fmt"
|
|
import "strings"
|
|
import "unicode"
|
|
import "github.com/google/uuid"
|
|
import "git.tebibyte.media/fspl/fspl/errors"
|
|
|
|
// Access determines the external access control mode for a top-level entity.
|
|
type Access int; const (
|
|
// AccessPublic allows other modules to access an entity normally.
|
|
AccessPublic Access = iota
|
|
|
|
// AccessOpaque causes a top-level entity to appear opaque to other
|
|
// units. Values of opaque types can be passed around, assigned to each-
|
|
// other, and their methods can be called, but the implementation of the
|
|
// type is entirely hidden. This access mode cannot be applied to
|
|
// functions or methods.
|
|
AccessOpaque
|
|
|
|
// AccessPrivate disallows other modules from accessing a top-level
|
|
// entity.
|
|
AccessPrivate
|
|
)
|
|
func (this Access) String () string {
|
|
switch this {
|
|
case AccessPrivate: return "-"
|
|
case AccessOpaque: return "#"
|
|
case AccessPublic: return "+"
|
|
default: return fmt.Sprintf("entity.Access(%d)", this)
|
|
}
|
|
}
|
|
|
|
// Signature is a function or method signature that is used in functions,
|
|
// methods, and specifying interface behaviors. It defines the type of a
|
|
// function.
|
|
type Signature struct {
|
|
// Syntax
|
|
Pos errors.Position
|
|
Name string
|
|
Arguments []*Declaration
|
|
Return Type
|
|
|
|
// Semantics
|
|
Acc Access
|
|
Unt uuid.UUID
|
|
ArgumentOrder []string
|
|
ArgumentMap map[string] *Declaration
|
|
}
|
|
func (*Signature) ty(){}
|
|
func (this *Signature) Position () errors.Position { return this.Pos }
|
|
func (this *Signature) Access () Access { return this.Acc }
|
|
func (this *Signature) Unit () uuid.UUID { return this.Unt }
|
|
func (this *Signature) String () string {
|
|
out := "[" + this.Name
|
|
for _, argument := range this.Arguments {
|
|
out += fmt.Sprint(" ", argument)
|
|
}
|
|
out += "]"
|
|
if this.Return != nil {
|
|
out += fmt.Sprint(":", this.Return)
|
|
}
|
|
return out
|
|
}
|
|
func (this *Signature) Hash () Hash {
|
|
data := new(strings.Builder)
|
|
data.WriteString("Signature:")
|
|
for _, argument := range this.Arguments {
|
|
argumentHash := HashType(argument.Type())
|
|
data.Write(argumentHash[:])
|
|
}
|
|
data.WriteString(":")
|
|
returnHash := HashType(this.Return)
|
|
data.Write(returnHash[:])
|
|
return NewHash([]byte(data.String()))
|
|
}
|
|
func (this *Signature) Equals (ty Type) bool {
|
|
real, ok := ty.(*Signature)
|
|
if !ok ||
|
|
len(real.Arguments) != len(this.Arguments) ||
|
|
!TypesEqual(real.Return, this.Return) ||
|
|
real.Name != this.Name { return false }
|
|
|
|
for index, argument := range this.Arguments {
|
|
if !argument.Type().Equals(real.Arguments[index].Type()) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// Member is a syntactical construct that is used to list members in struct
|
|
// literals.
|
|
type Member struct {
|
|
Pos errors.Position
|
|
Name string
|
|
Value Expression
|
|
}
|
|
func (this *Member) Position () errors.Position { return this.Pos }
|
|
func (this *Member) String () string {
|
|
return fmt.Sprint(this.Name, ":", this.Value)
|
|
}
|
|
|
|
// MatchCase represents a case in a match expression.
|
|
type MatchCase struct {
|
|
Pos errors.Position
|
|
Declaration *Declaration
|
|
Expression
|
|
Scope
|
|
}
|
|
func (this *MatchCase) Position () errors.Position { return this.Pos }
|
|
func (this *MatchCase) String () string {
|
|
return fmt.Sprint("| ", this.Declaration, this.Expression)
|
|
}
|
|
|
|
// SwitchCase represents a case in a switch expression.
|
|
type SwitchCase struct {
|
|
Pos errors.Position
|
|
Key Expression
|
|
Expression
|
|
Scope
|
|
}
|
|
func (this *SwitchCase) Position () errors.Position { return this.Pos }
|
|
func (this *SwitchCase) String () string {
|
|
return fmt.Sprint("| ", this.Key, this.Expression)
|
|
}
|
|
|
|
// DefaultCase represents the default case in a switch or match expression.
|
|
type DefaultCase struct {
|
|
Pos errors.Position
|
|
Expression
|
|
Scope
|
|
}
|
|
func (this *DefaultCase) Position () errors.Position { return this.Pos }
|
|
func (this *DefaultCase) String () string {
|
|
return fmt.Sprint("* ", this.Expression)
|
|
}
|
|
|
|
// Operator determines which operation to apply to a value in an operation
|
|
// expression.
|
|
type Operator int; const (
|
|
// Math
|
|
OperatorAdd Operator = iota
|
|
OperatorIncrement
|
|
OperatorSubtract
|
|
OperatorDecrement
|
|
OperatorMultiply
|
|
OperatorDivide
|
|
OperatorModulo
|
|
|
|
// Logic
|
|
OperatorLogicalNot
|
|
OperatorLogicalOr
|
|
OperatorLogicalAnd
|
|
OperatorLogicalXor
|
|
|
|
// Bit manipulation
|
|
OperatorNot
|
|
OperatorOr
|
|
OperatorAnd
|
|
OperatorXor
|
|
OperatorLeftShift
|
|
OperatorRightShift
|
|
|
|
// Comparison
|
|
OperatorLess
|
|
OperatorGreater
|
|
OperatorLessEqual
|
|
OperatorGreaterEqual
|
|
OperatorEqual
|
|
)
|
|
|
|
// ResultsInBoolean determines whether or not this operation will always result
|
|
// in a boolean value.
|
|
func (operator Operator) ResultsInBoolean () bool {
|
|
switch operator {
|
|
case OperatorLogicalNot,
|
|
OperatorLogicalOr,
|
|
OperatorLogicalAnd,
|
|
OperatorLogicalXor,
|
|
OperatorLess,
|
|
OperatorGreater,
|
|
OperatorLessEqual,
|
|
OperatorGreaterEqual,
|
|
OperatorEqual:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
var operatorToString = []string {
|
|
// Math
|
|
"+",
|
|
"++",
|
|
"-",
|
|
"--",
|
|
"*",
|
|
"/",
|
|
"%",
|
|
|
|
// Logic
|
|
"!",
|
|
"|",
|
|
"&",
|
|
"^",
|
|
|
|
// Bit manipulation
|
|
"!!",
|
|
"||",
|
|
"&&",
|
|
"^^",
|
|
"<<",
|
|
">>",
|
|
|
|
// Comparison
|
|
"<",
|
|
">",
|
|
"<=",
|
|
">=",
|
|
"=",
|
|
}
|
|
|
|
var stringToOperator map[string] Operator
|
|
|
|
func init () {
|
|
stringToOperator = make(map[string] Operator)
|
|
for index, str := range operatorToString {
|
|
stringToOperator[str] = Operator(index)
|
|
}
|
|
}
|
|
|
|
func OperatorFromString (str string) Operator {
|
|
return stringToOperator[str]
|
|
}
|
|
|
|
func (this Operator) String () string {
|
|
return operatorToString[this]
|
|
}
|
|
|
|
// Quote puts quotes around a string to turn it into a string literal.
|
|
func Quote (in string) string {
|
|
out := "'"
|
|
for _, char := range in {
|
|
if char == '\'' {
|
|
out += "\\'"
|
|
} else if unicode.IsPrint(char) {
|
|
out += string(char)
|
|
} else {
|
|
out += fmt.Sprintf("\\%03o", char)
|
|
}
|
|
}
|
|
return out + "'"
|
|
}
|
|
|
|
// ConstantDeclaration declares an enumerated constant as part of a Typedef.
|
|
type ConstantDeclaration struct {
|
|
// Syntax
|
|
Pos errors.Position
|
|
Name string
|
|
Value Expression
|
|
|
|
// Semantics
|
|
Ty Type
|
|
Scope
|
|
}
|
|
func (this *ConstantDeclaration) Position () errors.Position { return this.Pos }
|
|
func (this *ConstantDeclaration) Type () Type { return this.Ty }
|
|
func (this *ConstantDeclaration) String () string {
|
|
return fmt.Sprint("| ", this.Name, " ", this.Value)
|
|
}
|