fspl/entity/misc.go

255 lines
5.6 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 + "'"
}