Added a locatable node trait
This commit is contained in:
parent
cd670d05c5
commit
7581541ff5
@ -3,7 +3,6 @@ package analyzer
|
|||||||
import "os"
|
import "os"
|
||||||
import "fmt"
|
import "fmt"
|
||||||
import "path/filepath"
|
import "path/filepath"
|
||||||
import "git.tebibyte.media/arf/arf/file"
|
|
||||||
import "git.tebibyte.media/arf/arf/parser"
|
import "git.tebibyte.media/arf/arf/parser"
|
||||||
import "git.tebibyte.media/arf/arf/infoerr"
|
import "git.tebibyte.media/arf/arf/infoerr"
|
||||||
|
|
||||||
@ -217,15 +216,13 @@ func (analyzer *AnalysisOperation) addSection (section Section) {
|
|||||||
// destination. If it can, it retunrs nil. If it can't, it returns an error
|
// destination. If it can, it retunrs nil. If it can't, it returns an error
|
||||||
// explaining why.
|
// explaining why.
|
||||||
func (analyzer *AnalysisOperation) typeCheck (
|
func (analyzer *AnalysisOperation) typeCheck (
|
||||||
location file.Location,
|
|
||||||
source Argument,
|
source Argument,
|
||||||
destination Type,
|
destination Type,
|
||||||
) (
|
) (
|
||||||
err error,
|
err error,
|
||||||
) {
|
) {
|
||||||
if !source.canBePassedAs(destination) {
|
if !source.canBePassedAs(destination) {
|
||||||
err = infoerr.NewError (
|
err = source.NewError (
|
||||||
location,
|
|
||||||
typeMismatchErrorMessage (
|
typeMismatchErrorMessage (
|
||||||
source.What(),
|
source.What(),
|
||||||
destination),
|
destination),
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
package analyzer
|
package analyzer
|
||||||
|
|
||||||
|
import "git.tebibyte.media/arf/arf/file"
|
||||||
import "git.tebibyte.media/arf/arf/parser"
|
import "git.tebibyte.media/arf/arf/parser"
|
||||||
// import "git.tebibyte.media/arf/arf/infoerr"
|
import "git.tebibyte.media/arf/arf/infoerr"
|
||||||
|
|
||||||
// Argument represents a value that can be placed anywhere a value goes. This
|
// Argument represents a value that can be placed anywhere a value goes. This
|
||||||
// allows things like phrases being arguments to other phrases.
|
// allows things like phrases being arguments to other phrases.
|
||||||
@ -15,7 +16,9 @@ type Argument interface {
|
|||||||
// FloatLiteral
|
// FloatLiteral
|
||||||
// StringLiteral
|
// StringLiteral
|
||||||
|
|
||||||
What () (what Type)
|
What () (what Type)
|
||||||
|
Location () (location file.Location)
|
||||||
|
NewError (message string, kind infoerr.ErrorKind) (err error)
|
||||||
ToString (indent int) (output string)
|
ToString (indent int) (output string)
|
||||||
canBePassedAs (what Type) (allowed bool)
|
canBePassedAs (what Type) (allowed bool)
|
||||||
}
|
}
|
||||||
@ -76,16 +79,36 @@ func (analyzer AnalysisOperation) analyzeArgument (
|
|||||||
// TODO
|
// TODO
|
||||||
|
|
||||||
case parser.ArgumentKindInt:
|
case parser.ArgumentKindInt:
|
||||||
outputArgument = IntLiteral(inputArgument.Value().(int64))
|
outputArgument = IntLiteral {
|
||||||
|
value: inputArgument.Value().(int64),
|
||||||
|
locatable: locatable {
|
||||||
|
location: inputArgument.Location(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
case parser.ArgumentKindUInt:
|
case parser.ArgumentKindUInt:
|
||||||
outputArgument = UIntLiteral(inputArgument.Value().(uint64))
|
outputArgument = UIntLiteral {
|
||||||
|
value: inputArgument.Value().(uint64),
|
||||||
|
locatable: locatable {
|
||||||
|
location: inputArgument.Location(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
case parser.ArgumentKindFloat:
|
case parser.ArgumentKindFloat:
|
||||||
outputArgument = FloatLiteral(inputArgument.Value().(float64))
|
outputArgument = FloatLiteral {
|
||||||
|
value: inputArgument.Value().(float64),
|
||||||
|
locatable: locatable {
|
||||||
|
location: inputArgument.Location(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
case parser.ArgumentKindString:
|
case parser.ArgumentKindString:
|
||||||
outputArgument = StringLiteral(inputArgument.Value().(string))
|
outputArgument = StringLiteral {
|
||||||
|
value: inputArgument.Value().(string),
|
||||||
|
locatable: locatable {
|
||||||
|
location: inputArgument.Location(),
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -2,15 +2,34 @@ package analyzer
|
|||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
type IntLiteral int64
|
type IntLiteral struct {
|
||||||
type UIntLiteral uint64
|
locatable
|
||||||
type FloatLiteral float64
|
value int64
|
||||||
type StringLiteral string
|
}
|
||||||
type RuneLiteral rune
|
|
||||||
|
type UIntLiteral struct {
|
||||||
|
locatable
|
||||||
|
value uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
type FloatLiteral struct {
|
||||||
|
locatable
|
||||||
|
value float64
|
||||||
|
}
|
||||||
|
|
||||||
|
type StringLiteral struct {
|
||||||
|
locatable
|
||||||
|
value string
|
||||||
|
}
|
||||||
|
|
||||||
|
type RuneLiteral struct {
|
||||||
|
locatable
|
||||||
|
value rune
|
||||||
|
}
|
||||||
|
|
||||||
// ToString outputs the data in the argument as a string.
|
// ToString outputs the data in the argument as a string.
|
||||||
func (literal IntLiteral) ToString (indent int) (output string) {
|
func (literal IntLiteral) ToString (indent int) (output string) {
|
||||||
output += doIndent(indent, fmt.Sprint("arg int ", literal, "\n"))
|
output += doIndent(indent, fmt.Sprint("arg int ", literal.value, "\n"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +65,7 @@ func (literal IntLiteral) canBePassedAs (what Type) (allowed bool) {
|
|||||||
|
|
||||||
// ToString outputs the data in the argument as a string.
|
// ToString outputs the data in the argument as a string.
|
||||||
func (literal UIntLiteral) ToString (indent int) (output string) {
|
func (literal UIntLiteral) ToString (indent int) (output string) {
|
||||||
output += doIndent(indent, fmt.Sprint("arg uint ", literal, "\n"))
|
output += doIndent(indent, fmt.Sprint("arg uint ", literal.value, "\n"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +113,7 @@ func (literal FloatLiteral) What () (what Type) {
|
|||||||
|
|
||||||
// ToString outputs the data in the argument as a string.
|
// ToString outputs the data in the argument as a string.
|
||||||
func (literal FloatLiteral) ToString (indent int) (output string) {
|
func (literal FloatLiteral) ToString (indent int) (output string) {
|
||||||
output += doIndent(indent, fmt.Sprint("arg float ", literal, "\n"))
|
output += doIndent(indent, fmt.Sprint("arg float ", literal.value, "\n"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +144,7 @@ func (literal StringLiteral) What () (what Type) {
|
|||||||
|
|
||||||
// ToString outputs the data in the argument as a string.
|
// ToString outputs the data in the argument as a string.
|
||||||
func (literal StringLiteral) ToString (indent int) (output string) {
|
func (literal StringLiteral) ToString (indent int) (output string) {
|
||||||
output += doIndent(indent, fmt.Sprint("arg string \"", literal, "\"\n"))
|
output += doIndent(indent, fmt.Sprint("arg string '", literal.value, "'\n"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +189,7 @@ func (literal StringLiteral) canBePassedAs (what Type) (allowed bool) {
|
|||||||
|
|
||||||
// ToString outputs the data in the argument as a string.
|
// ToString outputs the data in the argument as a string.
|
||||||
func (literal RuneLiteral) ToString (indent int) (output string) {
|
func (literal RuneLiteral) ToString (indent int) (output string) {
|
||||||
output += doIndent(indent, fmt.Sprint("arg rune '", literal, "'\n"))
|
output += doIndent(indent, fmt.Sprint("arg rune '", literal.value, "'\n"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,38 @@
|
|||||||
package analyzer
|
package analyzer
|
||||||
|
|
||||||
import "path/filepath"
|
import "path/filepath"
|
||||||
|
import "git.tebibyte.media/arf/arf/file"
|
||||||
import "git.tebibyte.media/arf/arf/types"
|
import "git.tebibyte.media/arf/arf/types"
|
||||||
|
import "git.tebibyte.media/arf/arf/infoerr"
|
||||||
|
|
||||||
|
// locatable allows a tree node to have a location.
|
||||||
|
type locatable struct {
|
||||||
|
location file.Location
|
||||||
|
}
|
||||||
|
|
||||||
|
// Location returns the location of the node.
|
||||||
|
func (node locatable) Location () (location file.Location) {
|
||||||
|
location = node.location
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewError creates a new error at the node's location.
|
||||||
|
func (node locatable) NewError (
|
||||||
|
message string,
|
||||||
|
kind infoerr.ErrorKind,
|
||||||
|
) (
|
||||||
|
err error,
|
||||||
|
) {
|
||||||
|
err = infoerr.NewError(node.location, message, kind)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// sectionBase is a struct that all sections must embed.
|
// sectionBase is a struct that all sections must embed.
|
||||||
type sectionBase struct {
|
type sectionBase struct {
|
||||||
where locator
|
where locator
|
||||||
complete bool
|
complete bool
|
||||||
permission types.Permission
|
permission types.Permission
|
||||||
|
locatable
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name returns the name of the section.
|
// Name returns the name of the section.
|
||||||
|
@ -3,7 +3,9 @@ package analyzer
|
|||||||
import "os"
|
import "os"
|
||||||
import "sort"
|
import "sort"
|
||||||
import "path/filepath"
|
import "path/filepath"
|
||||||
|
import "git.tebibyte.media/arf/arf/file"
|
||||||
import "git.tebibyte.media/arf/arf/types"
|
import "git.tebibyte.media/arf/arf/types"
|
||||||
|
import "git.tebibyte.media/arf/arf/infoerr"
|
||||||
|
|
||||||
// locator uniquely identifies a section in the section table.
|
// locator uniquely identifies a section in the section table.
|
||||||
type locator struct {
|
type locator struct {
|
||||||
@ -79,6 +81,8 @@ type Section interface {
|
|||||||
ModulePath () (path string)
|
ModulePath () (path string)
|
||||||
ModuleName () (path string)
|
ModuleName () (path string)
|
||||||
Permission () (permission types.Permission)
|
Permission () (permission types.Permission)
|
||||||
|
Location () (location file.Location)
|
||||||
|
NewError (message string, kind infoerr.ErrorKind) (err error)
|
||||||
locator () (where locator)
|
locator () (where locator)
|
||||||
|
|
||||||
// Must be implemented by each individual section
|
// Must be implemented by each individual section
|
||||||
|
@ -64,6 +64,8 @@ func (analyzer AnalysisOperation) analyzeTypeSection () (
|
|||||||
analyzer.addSection(section)
|
analyzer.addSection(section)
|
||||||
|
|
||||||
inputSection := analyzer.currentSection.(parser.TypeSection)
|
inputSection := analyzer.currentSection.(parser.TypeSection)
|
||||||
|
outputSection.location = analyzer.currentSection.Location()
|
||||||
|
|
||||||
if inputSection.Permission() == types.PermissionReadWrite {
|
if inputSection.Permission() == types.PermissionReadWrite {
|
||||||
err = inputSection.NewError (
|
err = inputSection.NewError (
|
||||||
"read-write (rw) permission not understood in this " +
|
"read-write (rw) permission not understood in this " +
|
||||||
@ -83,7 +85,6 @@ func (analyzer AnalysisOperation) analyzeTypeSection () (
|
|||||||
|
|
||||||
// type check default value
|
// type check default value
|
||||||
err = analyzer.typeCheck (
|
err = analyzer.typeCheck (
|
||||||
inputSection.Argument().Location(),
|
|
||||||
outputSection.argument,
|
outputSection.argument,
|
||||||
outputSection.what)
|
outputSection.what)
|
||||||
if err != nil { return }
|
if err != nil { return }
|
||||||
|
@ -21,6 +21,8 @@ const (
|
|||||||
// Type represents a description of a type. It must eventually point to a
|
// Type represents a description of a type. It must eventually point to a
|
||||||
// TypeSection.
|
// TypeSection.
|
||||||
type Type struct {
|
type Type struct {
|
||||||
|
locatable
|
||||||
|
|
||||||
// one of these must be nil.
|
// one of these must be nil.
|
||||||
actual *TypeSection
|
actual *TypeSection
|
||||||
points *Type
|
points *Type
|
||||||
@ -168,8 +170,9 @@ func (analyzer AnalysisOperation) analyzeType (
|
|||||||
outputType Type,
|
outputType Type,
|
||||||
err error,
|
err error,
|
||||||
) {
|
) {
|
||||||
outputType.mutable = inputType.Mutable()
|
outputType.mutable = inputType.Mutable()
|
||||||
outputType.length = inputType.Length()
|
outputType.length = inputType.Length()
|
||||||
|
outputType.location = inputType.Location()
|
||||||
if outputType.length < 1 {
|
if outputType.length < 1 {
|
||||||
err = inputType.NewError (
|
err = inputType.NewError (
|
||||||
"cannot specify a length of zero",
|
"cannot specify a length of zero",
|
||||||
|
Reference in New Issue
Block a user