Compare commits
4 Commits
6313992c10
...
0fd35343c1
Author | SHA1 | Date |
---|---|---|
Sasha Koshka | 0fd35343c1 | |
Sasha Koshka | d88a34d638 | |
Sasha Koshka | fc930fa3d4 | |
Sasha Koshka | 40d500b705 |
|
@ -369,70 +369,29 @@ func (this *Tree) areStructurallyEquivalent (left, right entity.Type) bool {
|
|||
// isLocationExpression returns whether or not an expression is a valid location
|
||||
// expression.
|
||||
func (this *Tree) isLocationExpression (expression entity.Expression) error {
|
||||
// TODO: have some Name() method of Expression so we can use it in a
|
||||
// default case here. this will prevent crashes when new features are
|
||||
// added.
|
||||
cannot := func (pos errors.Position, kind string) error {
|
||||
return errors.Errorf(pos, "cannot assign to %s", kind)
|
||||
}
|
||||
switch expression := expression.(type) {
|
||||
case *entity.Variable:
|
||||
return nil
|
||||
case *entity.Declaration:
|
||||
return nil
|
||||
case *entity.Call:
|
||||
return cannot(expression.Position(), "function call")
|
||||
case *entity.MethodCall:
|
||||
return cannot(expression.Position(), "method call")
|
||||
case *entity.Subscript:
|
||||
return this.isLocationExpression(expression.Slice)
|
||||
case *entity.Slice:
|
||||
return cannot(expression.Position(), "slice operation")
|
||||
case *entity.Dereference:
|
||||
return this.isLocationExpression(expression.Pointer)
|
||||
case *entity.Reference:
|
||||
return cannot(expression.Position(), "reference operation")
|
||||
case *entity.ValueCast:
|
||||
return cannot(expression.Position(), "value cast")
|
||||
case *entity.BitCast:
|
||||
return cannot(expression.Position(), "bit cast")
|
||||
case *entity.Operation:
|
||||
return cannot(expression.Position(), fmt.Sprintf (
|
||||
"cannot assign to %v operation",
|
||||
expression.Operator))
|
||||
case *entity.Block:
|
||||
return cannot(expression.Position(), "block")
|
||||
case *entity.MemberAccess:
|
||||
return this.isLocationExpression (
|
||||
expression.Source)
|
||||
case *entity.IfElse:
|
||||
return cannot(expression.Position(), "if/else")
|
||||
case *entity.Match:
|
||||
return cannot(expression.Position(), "match")
|
||||
case *entity.Loop:
|
||||
return cannot(expression.Position(), "loop")
|
||||
case *entity.Break:
|
||||
return cannot(expression.Position(), "break statement")
|
||||
case *entity.Return:
|
||||
return cannot(expression.Position(), "return statement")
|
||||
case *entity.LiteralInt:
|
||||
return cannot(expression.Position(), "integer literal")
|
||||
case *entity.LiteralFloat:
|
||||
return cannot(expression.Position(), "float literal")
|
||||
case *entity.LiteralString:
|
||||
return cannot(expression.Position(), "string literal")
|
||||
case *entity.LiteralArray:
|
||||
return cannot(expression.Position(), "array literal")
|
||||
case *entity.LiteralStruct:
|
||||
return cannot(expression.Position(), "struct literal")
|
||||
case *entity.LiteralBoolean:
|
||||
return cannot(expression.Position(), "boolean literal")
|
||||
case *entity.LiteralNil:
|
||||
return cannot(expression.Position(), "nil literal")
|
||||
return this.isLocationExpression(expression.Source)
|
||||
default:
|
||||
panic(fmt.Sprint (
|
||||
"BUG: analyzer doesnt know about expression",
|
||||
expression))
|
||||
return errors.Errorf(expression.Position(), "cannot assign to %s", expression.Description())
|
||||
}
|
||||
}
|
||||
|
||||
// isConstant returns whether or not an expression can be evaluated at compile
|
||||
// time.
|
||||
func (this *Tree) isConstant (expression entity.Expression) error {
|
||||
if expression.IsConstant() {
|
||||
return nil
|
||||
} else {
|
||||
return errors.Errorf(expression.Position(), "can not use %s as constant", expression.Description())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ Weekday: String
|
|||
// name?
|
||||
func TestErrConstantStringUnspecified (test *testing.T) {
|
||||
testStringErr (test,
|
||||
"cannot fill in constant values for non-numeric type Weekday", 5, 11
|
||||
"cannot fill in constant values for non-numeric type Weekday", 5, 11,
|
||||
`
|
||||
Weekday: String
|
||||
| sunday
|
||||
|
|
|
@ -363,6 +363,7 @@ func (this *Tree) analyzeReference (
|
|||
if err != nil { return nil, err }
|
||||
err = this.isLocationExpression(reference.Value)
|
||||
if err != nil { return nil, err }
|
||||
// TODO: only allow constants to be referenced as immutable data
|
||||
reference.Value = value
|
||||
reference.Ty = referenced.Referenced
|
||||
|
||||
|
@ -1015,13 +1016,15 @@ func (this *Tree) analyzeReturn (
|
|||
entity.Expression,
|
||||
error,
|
||||
) {
|
||||
ret.Declaration, _ = this.topDeclaration()
|
||||
declaration, _ := this.topDeclaration()
|
||||
var ty entity.Type
|
||||
switch ret.Declaration.(type) {
|
||||
switch declaration := declaration.(type) {
|
||||
case *entity.Function:
|
||||
ty = ret.Declaration.(*entity.Function).Signature.Return
|
||||
ret.Declaration = declaration
|
||||
ty = declaration.Signature.Return
|
||||
case *entity.Method:
|
||||
ty = ret.Declaration.(*entity.Method).Signature.Return
|
||||
ret.Declaration = declaration
|
||||
ty = declaration.Signature.Return
|
||||
}
|
||||
|
||||
if ty != nil && ret.Value == nil {
|
||||
|
|
|
@ -7,7 +7,7 @@ import "git.tebibyte.media/fspl/fspl/entity"
|
|||
// entity causes the analysis of another.
|
||||
type scopeContextManager []scopeContext
|
||||
|
||||
func (this *scopeContextManager) pushScopeContext (declaration entity.TopLevel) {
|
||||
func (this *scopeContextManager) pushScopeContext (declaration any) {
|
||||
*this = append(*this, scopeContext { declaration: declaration })
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ func (this *scopeContextManager) topLoop () (entity.Breakable, bool) {
|
|||
return (*this)[len(*this) - 1].topLoop()
|
||||
}
|
||||
|
||||
func (this *scopeContextManager) topDeclaration () (entity.TopLevel, bool) {
|
||||
func (this *scopeContextManager) topDeclaration () (any, bool) {
|
||||
if len(*this) < 1 { return nil, false }
|
||||
return (*this)[len(*this) - 1].declaration, true
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ func (this *scopeContextManager) assertPopulated () {
|
|||
type scopeContext struct {
|
||||
scopes []entity.Scoped
|
||||
loops []entity.Breakable
|
||||
declaration entity.TopLevel
|
||||
declaration any // TODO rename to "origin" or smth
|
||||
}
|
||||
|
||||
func (this *scopeContext) pushLoop (loop entity.Breakable) {
|
||||
|
|
104
analyzer/type.go
104
analyzer/type.go
|
@ -33,22 +33,81 @@ func (this *Tree) analyzeTypedef (
|
|||
}
|
||||
}
|
||||
|
||||
// analyze if it still needs to be analyzed
|
||||
if definition, exists := this.rawTypes[key]; exists {
|
||||
// update unit
|
||||
definition.Unt = key.Unit
|
||||
|
||||
// analyze
|
||||
var err error
|
||||
definition.Type, err = this.analyzeTypeInternal (
|
||||
definition.Type, definition, false)
|
||||
return definition, err
|
||||
// check if it is even real
|
||||
definition, exists := this.rawTypes[key]
|
||||
if !exists {
|
||||
return nil, errors.Errorf(pos, "no type named %s", key.Name)
|
||||
}
|
||||
|
||||
// update unit
|
||||
definition.Unt = key.Unit
|
||||
|
||||
// if we couldn't get the type, error
|
||||
return nil, errors.Errorf(pos, "no type named %s", key.Name)
|
||||
// analyze
|
||||
var err error
|
||||
definition.Type, err = this.analyzeTypeInternal (
|
||||
definition.Type, definition, false)
|
||||
|
||||
// assemble constant map
|
||||
definition, err = this.assembleTypedefConstantMap(definition)
|
||||
if err != nil { return nil, err }
|
||||
|
||||
// analyze constants
|
||||
fillerValue := 0
|
||||
for index, constant := range definition.Constants {
|
||||
constant, err := this.analyzeConstantDeclaration(constant, definition.Type)
|
||||
if err != nil { return nil, err }
|
||||
if constant.Value == nil {
|
||||
if !isNumeric(definition.Type) {
|
||||
return nil, errors.Errorf (
|
||||
pos, "cannot fill in constant values for non-numeric type %v",
|
||||
definition.Type)
|
||||
}
|
||||
constant.Value = &entity.LiteralInt {
|
||||
Pos: pos,
|
||||
Value: fillerValue,
|
||||
Ty: definition.Type,
|
||||
}
|
||||
fillerValue ++
|
||||
}
|
||||
|
||||
definition.ConstantMap[constant.Name] = constant
|
||||
definition.ConstantOrder[index] = constant.Name
|
||||
definition.Constants[index] = constant
|
||||
}
|
||||
|
||||
return definition, err
|
||||
}
|
||||
|
||||
func (this *Tree) analyzeConstantDeclaration (
|
||||
constant *entity.ConstantDeclaration,
|
||||
into entity.Type,
|
||||
) (
|
||||
*entity.ConstantDeclaration,
|
||||
error,
|
||||
) {
|
||||
constant.Ty = into
|
||||
|
||||
// analyze the value, if given
|
||||
if constant.Value != nil {
|
||||
// create new scope context for this constant
|
||||
this.pushScopeContext(constant)
|
||||
this.pushScope(constant)
|
||||
defer this.popScopeContext()
|
||||
defer this.popScope()
|
||||
|
||||
// analyze value
|
||||
value, err := this.analyzeExpression(into, strict, constant.Value)
|
||||
if err != nil { return nil, err }
|
||||
|
||||
// only allow values that can be used as constants
|
||||
err = this.isConstant(value)
|
||||
if err != nil { return nil, err }
|
||||
}
|
||||
|
||||
// TODO after analysis, check if constant
|
||||
return constant, nil
|
||||
}
|
||||
|
||||
func (this *Tree) analyzeType (
|
||||
ty entity.Type,
|
||||
acceptIncomplete bool,
|
||||
|
@ -303,3 +362,24 @@ func (this *Tree) analyzeBehavior (behavior *entity.Signature) (*entity.Signatur
|
|||
behavior.Return, err = this.analyzeType(behavior.Return, false)
|
||||
return behavior, err
|
||||
}
|
||||
|
||||
func (this *Tree) assembleTypedefConstantMap (
|
||||
typedef *entity.Typedef,
|
||||
) (
|
||||
*entity.Typedef,
|
||||
error,
|
||||
) {
|
||||
typedef.ConstantMap = make(map[string] *entity.ConstantDeclaration)
|
||||
typedef.ConstantOrder = make([]string, len(typedef.Constants))
|
||||
for index, constant := range typedef.Constants {
|
||||
if previous, exists := typedef.ConstantMap[constant.Name]; exists {
|
||||
return nil, errors.Errorf (
|
||||
constant.Position(), "%s already defined at %v",
|
||||
constant.Name, previous.Position())
|
||||
}
|
||||
typedef.ConstantMap [constant.Name] = constant
|
||||
typedef.ConstantOrder[index] = constant.Name
|
||||
typedef.Constants [index] = constant
|
||||
}
|
||||
return typedef, nil
|
||||
}
|
||||
|
|
|
@ -22,6 +22,13 @@ type Expression interface {
|
|||
// to conform to. The value of this does not depend on semantic
|
||||
// information fields.
|
||||
HasExplicitType () bool
|
||||
|
||||
// Constant returns true if the expression's value can be computed at
|
||||
// compile time.
|
||||
IsConstant () bool
|
||||
|
||||
// Description returns a human-readable description of the expression.
|
||||
Description () string
|
||||
|
||||
expression ()
|
||||
}
|
||||
|
@ -43,6 +50,8 @@ func (*Variable) expression(){}
|
|||
func (this *Variable) Position () errors.Position { return this.Pos }
|
||||
func (this *Variable) Type () Type { return this.Declaration.Type() }
|
||||
func (this *Variable) HasExplicitType () bool { return true }
|
||||
func (this *Variable) IsConstant () bool { return false }
|
||||
func (this *Variable) Description () string { return "variable" }
|
||||
func (this *Variable) String () string {
|
||||
return this.Name
|
||||
}
|
||||
|
@ -62,6 +71,8 @@ func (*Declaration) expression(){}
|
|||
func (this *Declaration) Position () errors.Position { return this.Pos }
|
||||
func (this *Declaration) Type () Type { return this.Ty }
|
||||
func (this *Declaration) HasExplicitType () bool { return true }
|
||||
func (this *Declaration) IsConstant () bool { return false }
|
||||
func (this *Declaration) Description () string { return "declaration" }
|
||||
func (this *Declaration) String () string {
|
||||
return fmt.Sprint(this.Name, ":", this.Ty)
|
||||
}
|
||||
|
@ -88,6 +99,8 @@ func (*Call) expression(){}
|
|||
func (this *Call) Position () errors.Position { return this.Pos }
|
||||
func (this *Call) Type () Type { return this.Function.Signature.Return }
|
||||
func (this *Call) HasExplicitType () bool { return true }
|
||||
func (this *Call) IsConstant () bool { return false }
|
||||
func (this *Call) Description () string { return "function call" }
|
||||
func (this *Call) String () string {
|
||||
out := ""
|
||||
if this.UnitNickname != "" {
|
||||
|
@ -129,6 +142,8 @@ func (this *MethodCall) Type () Type {
|
|||
}
|
||||
}
|
||||
func (this *MethodCall) HasExplicitType () bool { return true }
|
||||
func (this *MethodCall) IsConstant () bool { return false }
|
||||
func (this *MethodCall) Description () string { return "method call" }
|
||||
func (this *MethodCall) String () string {
|
||||
out := fmt.Sprint(this.Source, ".[", this.Name)
|
||||
for _, argument := range this.Arguments {
|
||||
|
@ -156,6 +171,8 @@ func (*Subscript) expression(){}
|
|||
func (this *Subscript) Position () errors.Position { return this.Pos }
|
||||
func (this *Subscript) Type () Type { return this.Ty }
|
||||
func (this *Subscript) HasExplicitType () bool { return true }
|
||||
func (this *Subscript) IsConstant () bool { return false }
|
||||
func (this *Subscript) Description () string { return "subscript operation" }
|
||||
func (this *Subscript) String () string {
|
||||
return fmt.Sprint("[.", this.Slice, " ", this.Offset, "]")
|
||||
}
|
||||
|
@ -176,6 +193,12 @@ func (*Slice) expression(){}
|
|||
func (this *Slice) Position () errors.Position { return this.Pos }
|
||||
func (this *Slice) Type () Type { return this.Slice.Type() }
|
||||
func (this *Slice) HasExplicitType () bool { return true }
|
||||
func (this *Slice) IsConstant () bool {
|
||||
return this.Slice.IsConstant() &&
|
||||
this.Start.IsConstant() &&
|
||||
this.End.IsConstant()
|
||||
}
|
||||
func (this *Slice) Description () string { return "slice operation" }
|
||||
func (this *Slice) String () string {
|
||||
out := fmt.Sprint("[\\", this.Slice, " ")
|
||||
if this.Start != nil {
|
||||
|
@ -203,6 +226,8 @@ func (*Length) expression(){}
|
|||
func (this *Length) Position () errors.Position { return this.Pos }
|
||||
func (this *Length) Type () Type { return this.Ty }
|
||||
func (this *Length) HasExplicitType () bool { return true }
|
||||
func (this *Length) IsConstant () bool { return this.Slice.IsConstant() }
|
||||
func (this *Length) Description () string { return "length operation" }
|
||||
func (this *Length) String () string {
|
||||
return fmt.Sprint("[#", this.Slice, "]")
|
||||
}
|
||||
|
@ -225,6 +250,8 @@ func (*Dereference) expression(){}
|
|||
func (this *Dereference) Position () errors.Position { return this.Pos }
|
||||
func (this *Dereference) Type () Type { return this.Ty }
|
||||
func (this *Dereference) HasExplicitType () bool { return true }
|
||||
func (this *Dereference) IsConstant () bool { return false }
|
||||
func (this *Dereference) Description () string { return "dereference operation" }
|
||||
func (this *Dereference) String () string {
|
||||
return fmt.Sprint("[.", this.Pointer, "]")
|
||||
}
|
||||
|
@ -249,6 +276,8 @@ func (*Reference) expression(){}
|
|||
func (this *Reference) Position () errors.Position { return this.Pos }
|
||||
func (this *Reference) Type () Type { return this.Ty }
|
||||
func (this *Reference) HasExplicitType () bool { return true }
|
||||
func (this *Reference) IsConstant () bool { return false }
|
||||
func (this *Reference) Description () string { return "reference operation" }
|
||||
func (this *Reference) String () string {
|
||||
return fmt.Sprint("[@", this.Value, "]")
|
||||
}
|
||||
|
@ -266,6 +295,8 @@ func (*ValueCast) expression(){}
|
|||
func (this *ValueCast) Position () errors.Position { return this.Pos }
|
||||
func (this *ValueCast) Type () Type { return this.Ty }
|
||||
func (this *ValueCast) HasExplicitType () bool { return true }
|
||||
func (this *ValueCast) IsConstant () bool { return this.Value.IsConstant() }
|
||||
func (this *ValueCast) Description () string { return "value cast" }
|
||||
func (this *ValueCast) String () string {
|
||||
return fmt.Sprint("[~ ", this.Ty, this.Value, "]")
|
||||
}
|
||||
|
@ -284,6 +315,8 @@ func (*BitCast) expression(){}
|
|||
func (this *BitCast) Position () errors.Position { return this.Pos }
|
||||
func (this *BitCast) Type () Type { return this.Ty }
|
||||
func (this *BitCast) HasExplicitType () bool { return true }
|
||||
func (this *BitCast) IsConstant () bool { return this.Value.IsConstant() }
|
||||
func (this *BitCast) Description () string { return "bit cast" }
|
||||
func (this *BitCast) String () string {
|
||||
return fmt.Sprint("[~~ ", this.Ty, this.Value, "]")
|
||||
}
|
||||
|
@ -308,6 +341,15 @@ func (this *Operation) Type () Type { return this.Ty }
|
|||
func (this *Operation) HasExplicitType () bool {
|
||||
return this.Operator.ResultsInBoolean()
|
||||
}
|
||||
func (this *Operation) IsConstant () bool {
|
||||
for _, argument := range this.Arguments {
|
||||
if !argument.IsConstant() { return false }
|
||||
}
|
||||
return true
|
||||
}
|
||||
func (this *Operation) Description () string {
|
||||
return fmt.Sprintf("%v operation", this.Operator)
|
||||
}
|
||||
func (this *Operation) String () string {
|
||||
out := fmt.Sprint("[", this.Operator)
|
||||
for _, argument := range this.Arguments {
|
||||
|
@ -338,6 +380,11 @@ func (this *Block) HasExplicitType () bool {
|
|||
if len(this.Steps) == 0 { return false }
|
||||
return this.Steps[len(this.Steps) - 1].HasExplicitType()
|
||||
}
|
||||
func (this *Block) IsConstant () bool {
|
||||
if len(this.Steps) == 0 { return false }
|
||||
return this.Steps[len(this.Steps) - 1].IsConstant()
|
||||
}
|
||||
func (this *Block) Description () string { return "block" }
|
||||
func (this *Block) String () string {
|
||||
out := "{"
|
||||
for index, step := range this.Steps {
|
||||
|
@ -367,6 +414,8 @@ func (*MemberAccess) expression(){}
|
|||
func (this *MemberAccess) Position () errors.Position { return this.Pos }
|
||||
func (this *MemberAccess) Type () Type { return this.Ty }
|
||||
func (this *MemberAccess) HasExplicitType () bool { return true }
|
||||
func (this *MemberAccess) IsConstant () bool { return this.Source.IsConstant() }
|
||||
func (this *MemberAccess) Description () string { return "member access" }
|
||||
func (this *MemberAccess) String () string {
|
||||
return fmt.Sprint(this.Source, ".", this.Member)
|
||||
}
|
||||
|
@ -393,6 +442,12 @@ func (this *IfElse) Type () Type { return this.Ty }
|
|||
func (this *IfElse) HasExplicitType () bool {
|
||||
return this.True.HasExplicitType()
|
||||
}
|
||||
func (this *IfElse) IsConstant () bool {
|
||||
return this.Condition.IsConstant() &&
|
||||
this.True.IsConstant() &&
|
||||
this.False.IsConstant()
|
||||
}
|
||||
func (this *IfElse) Description () string { return "if/else" }
|
||||
func (this *IfElse) String () string {
|
||||
out := fmt.Sprint("if ", this.Condition, " then ", this.True)
|
||||
if this.False != nil {
|
||||
|
@ -432,6 +487,15 @@ func (this *Match) HasExplicitType () bool {
|
|||
return this.Cases[0].HasExplicitType()
|
||||
}
|
||||
}
|
||||
func (this *Match) IsConstant () bool {
|
||||
if !this.Value.IsConstant() { return false }
|
||||
if !this.Default.IsConstant() { return false }
|
||||
for _, cas := range this.Cases {
|
||||
if !cas.IsConstant () { return false }
|
||||
}
|
||||
return true
|
||||
}
|
||||
func (this *Match) Description () string { return "match" }
|
||||
func (this *Match) String () string {
|
||||
out := fmt.Sprint("match ", this.Value)
|
||||
for _, cas := range this.Cases {
|
||||
|
@ -471,6 +535,15 @@ func (this *Switch) HasExplicitType () bool {
|
|||
return this.Cases[0].HasExplicitType()
|
||||
}
|
||||
}
|
||||
func (this *Switch) IsConstant () bool {
|
||||
if !this.Value.IsConstant() { return false }
|
||||
if !this.Default.IsConstant() { return false }
|
||||
for _, cas := range this.Cases {
|
||||
if !cas.IsConstant () { return false }
|
||||
}
|
||||
return true
|
||||
}
|
||||
func (this *Switch) Description () string { return "switch" }
|
||||
func (this *Switch) String () string {
|
||||
out := fmt.Sprint("switch ", this.Value)
|
||||
for _, cas := range this.Cases {
|
||||
|
@ -514,6 +587,8 @@ func (this *Loop) HasExplicitType () bool {
|
|||
// loop
|
||||
return false
|
||||
}
|
||||
func (this *Loop) IsConstant () bool { return false /* TODO this may be decidable */ }
|
||||
func (this *Loop) Description () string { return "loop" }
|
||||
func (this *Loop) String () string {
|
||||
return fmt.Sprint("loop ", this.Body)
|
||||
}
|
||||
|
@ -547,6 +622,8 @@ func (this *For) HasExplicitType () bool {
|
|||
// loop
|
||||
return false
|
||||
}
|
||||
func (this *For) IsConstant () bool { return false /* TODO this may be decidable */ }
|
||||
func (this *For) Description () string { return "for loop" }
|
||||
func (this *For) String () string {
|
||||
out := "for"
|
||||
if this.Index != nil {
|
||||
|
@ -571,6 +648,8 @@ func (*Break) expression(){}
|
|||
func (this *Break) Position () errors.Position { return this.Pos }
|
||||
func (this *Break) Type () Type { return nil }
|
||||
func (this *Break) HasExplicitType () bool { return false }
|
||||
func (this *Break) IsConstant () bool { return false }
|
||||
func (this *Break) Description () string { return "break" }
|
||||
func (this *Break) String () string {
|
||||
if this.Value == nil {
|
||||
return "[break]"
|
||||
|
@ -597,6 +676,8 @@ func (*Return) expression(){}
|
|||
func (this *Return) Position () errors.Position { return this.Pos }
|
||||
func (this *Return) Type () Type { return nil }
|
||||
func (this *Return) HasExplicitType () bool { return false }
|
||||
func (this *Return) IsConstant () bool { return false }
|
||||
func (this *Return) Description () string { return "return" }
|
||||
func (this *Return) String () string {
|
||||
if this.Value == nil {
|
||||
return "[return]"
|
||||
|
@ -619,6 +700,8 @@ func (*Assignment) expression(){}
|
|||
func (this *Assignment) Position () errors.Position { return this.Pos }
|
||||
func (this *Assignment) Type () Type { return nil }
|
||||
func (this *Assignment) HasExplicitType () bool { return false }
|
||||
func (this *Assignment) IsConstant () bool { return false }
|
||||
func (this *Assignment) Description () string { return "assignment" }
|
||||
func (this *Assignment) String () string {
|
||||
return fmt.Sprint(this.Location, "=", this.Value)
|
||||
}
|
||||
|
@ -643,6 +726,8 @@ func (*Constant) expression(){}
|
|||
func (this *Constant) Position () errors.Position { return this.Pos }
|
||||
func (this *Constant) Type () Type { return this.Ty }
|
||||
func (this *Constant) HasExplicitType () bool { return true }
|
||||
func (this *Constant) IsConstant () bool { return true }
|
||||
func (this *Constant) Description () string { return "constant" }
|
||||
func (this *Constant) String () string {
|
||||
output := ""
|
||||
if this.UnitNickname != "" {
|
||||
|
|
|
@ -21,6 +21,8 @@ func (*LiteralInt) expression(){}
|
|||
func (this *LiteralInt) Position () errors.Position { return this.Pos }
|
||||
func (this *LiteralInt) Type () Type { return this.Ty }
|
||||
func (this *LiteralInt) HasExplicitType () bool { return false }
|
||||
func (this *LiteralInt) IsConstant () bool { return true }
|
||||
func (this *LiteralInt) Description () string { return "integer literal" }
|
||||
func (this *LiteralInt) String () string {
|
||||
return fmt.Sprint(this.Value)
|
||||
}
|
||||
|
@ -42,6 +44,8 @@ func (*LiteralFloat) expression(){}
|
|||
func (this *LiteralFloat) Position () errors.Position { return this.Pos }
|
||||
func (this *LiteralFloat) Type () Type { return this.Ty }
|
||||
func (this *LiteralFloat) HasExplicitType () bool { return false }
|
||||
func (this *LiteralFloat) Description () string { return "floating point literal" }
|
||||
func (this *LiteralFloat) IsConstant () bool { return true }
|
||||
func (this *LiteralFloat) String () string {
|
||||
return fmt.Sprint(this.Value)
|
||||
}
|
||||
|
@ -76,6 +80,8 @@ func (*LiteralString) expression(){}
|
|||
func (this *LiteralString) Position () errors.Position { return this.Pos }
|
||||
func (this *LiteralString) Type () Type { return this.Ty }
|
||||
func (this *LiteralString) HasExplicitType () bool { return false }
|
||||
func (this *LiteralString) Description () string { return "sring literal" }
|
||||
func (this *LiteralString) IsConstant () bool { return true }
|
||||
func (this *LiteralString) String () string {
|
||||
return Quote(this.ValueUTF8)
|
||||
}
|
||||
|
@ -100,6 +106,13 @@ func (*LiteralArray) expression(){}
|
|||
func (this *LiteralArray) Position () errors.Position { return this.Pos }
|
||||
func (this *LiteralArray) Type () Type { return this.Ty }
|
||||
func (this *LiteralArray) HasExplicitType () bool { return false }
|
||||
func (this *LiteralArray) Description () string { return "array literal" }
|
||||
func (this *LiteralArray) IsConstant () bool {
|
||||
for _, element := range this.Elements {
|
||||
if !element.IsConstant() { return false }
|
||||
}
|
||||
return true
|
||||
}
|
||||
func (this *LiteralArray) String () string {
|
||||
out := "("
|
||||
for index, element := range this.Elements {
|
||||
|
@ -131,6 +144,13 @@ func (*LiteralStruct) expression(){}
|
|||
func (this *LiteralStruct) Position () errors.Position { return this.Pos }
|
||||
func (this *LiteralStruct) Type () Type { return this.Ty }
|
||||
func (this *LiteralStruct) HasExplicitType () bool { return false }
|
||||
func (this *LiteralStruct) Description () string { return "struct literal" }
|
||||
func (this *LiteralStruct) IsConstant () bool {
|
||||
for _, member := range this.Members {
|
||||
if !member.Value.IsConstant() { return false }
|
||||
}
|
||||
return true
|
||||
}
|
||||
func (this *LiteralStruct) String () string {
|
||||
out := "(."
|
||||
for _, member := range this.Members {
|
||||
|
@ -156,6 +176,8 @@ func (*LiteralBoolean) expression(){}
|
|||
func (this *LiteralBoolean) Position () errors.Position { return this.Pos }
|
||||
func (this *LiteralBoolean) Type () Type { return this.Ty }
|
||||
func (this *LiteralBoolean) HasExplicitType () bool { return false }
|
||||
func (this *LiteralBoolean) Description () string { return "boolean literal" }
|
||||
func (this *LiteralBoolean) IsConstant () bool { return true }
|
||||
func (this *LiteralBoolean) String () string {
|
||||
if this.Value {
|
||||
return "true"
|
||||
|
@ -177,4 +199,6 @@ func (*LiteralNil) expression(){}
|
|||
func (this *LiteralNil) Position () errors.Position { return this.Pos }
|
||||
func (this *LiteralNil) Type () Type { return this.Ty }
|
||||
func (this *LiteralNil) HasExplicitType () bool { return false }
|
||||
func (this *LiteralNil) Description () string { return "nil" }
|
||||
func (this *LiteralNil) IsConstant () bool { return true }
|
||||
func (this *LiteralNil) String () string { return "nil" }
|
||||
|
|
|
@ -262,6 +262,7 @@ type ConstantDeclaration struct {
|
|||
|
||||
// Semantics
|
||||
Ty Type
|
||||
Scope
|
||||
}
|
||||
func (this *ConstantDeclaration) Position () errors.Position { return this.Pos }
|
||||
func (this *ConstantDeclaration) Type () Type { return this.Ty }
|
||||
|
|
|
@ -31,9 +31,10 @@ type Typedef struct {
|
|||
Constants []*ConstantDeclaration
|
||||
|
||||
// Semantics
|
||||
Unt uuid.UUID
|
||||
Methods map[string] *Method
|
||||
ConstantsMap map[string] *ConstantDeclaration
|
||||
Unt uuid.UUID
|
||||
Methods map[string] *Method
|
||||
ConstantOrder []string
|
||||
ConstantMap map[string] *ConstantDeclaration
|
||||
}
|
||||
func (*Typedef) topLevel(){}
|
||||
func (this *Typedef) Position () errors.Position { return this.Pos }
|
||||
|
|
Loading…
Reference in New Issue