Added a locatable node trait

This commit is contained in:
Sasha Koshka 2022-10-11 18:31:37 -04:00
parent cd670d05c5
commit 7581541ff5
7 changed files with 95 additions and 23 deletions

View File

@ -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),

View File

@ -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.
@ -16,6 +17,8 @@ type Argument interface {
// 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
} }

View File

@ -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
} }

View File

@ -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.

View File

@ -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

View File

@ -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 }

View File

@ -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
@ -170,6 +172,7 @@ func (analyzer AnalysisOperation) analyzeType (
) { ) {
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",