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 "fmt"
import "path/filepath"
import "git.tebibyte.media/arf/arf/file"
import "git.tebibyte.media/arf/arf/parser"
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
// explaining why.
func (analyzer *AnalysisOperation) typeCheck (
location file.Location,
source Argument,
destination Type,
) (
err error,
) {
if !source.canBePassedAs(destination) {
err = infoerr.NewError (
location,
err = source.NewError (
typeMismatchErrorMessage (
source.What(),
destination),

View File

@ -1,7 +1,8 @@
package analyzer
import "git.tebibyte.media/arf/arf/file"
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
// allows things like phrases being arguments to other phrases.
@ -16,6 +17,8 @@ type Argument interface {
// StringLiteral
What () (what Type)
Location () (location file.Location)
NewError (message string, kind infoerr.ErrorKind) (err error)
ToString (indent int) (output string)
canBePassedAs (what Type) (allowed bool)
}
@ -76,16 +79,36 @@ func (analyzer AnalysisOperation) analyzeArgument (
// TODO
case parser.ArgumentKindInt:
outputArgument = IntLiteral(inputArgument.Value().(int64))
outputArgument = IntLiteral {
value: inputArgument.Value().(int64),
locatable: locatable {
location: inputArgument.Location(),
},
}
case parser.ArgumentKindUInt:
outputArgument = UIntLiteral(inputArgument.Value().(uint64))
outputArgument = UIntLiteral {
value: inputArgument.Value().(uint64),
locatable: locatable {
location: inputArgument.Location(),
},
}
case parser.ArgumentKindFloat:
outputArgument = FloatLiteral(inputArgument.Value().(float64))
outputArgument = FloatLiteral {
value: inputArgument.Value().(float64),
locatable: locatable {
location: inputArgument.Location(),
},
}
case parser.ArgumentKindString:
outputArgument = StringLiteral(inputArgument.Value().(string))
outputArgument = StringLiteral {
value: inputArgument.Value().(string),
locatable: locatable {
location: inputArgument.Location(),
},
}
}
return
}

View File

@ -2,15 +2,34 @@ package analyzer
import "fmt"
type IntLiteral int64
type UIntLiteral uint64
type FloatLiteral float64
type StringLiteral string
type RuneLiteral rune
type IntLiteral struct {
locatable
value int64
}
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.
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
}
@ -46,7 +65,7 @@ func (literal IntLiteral) canBePassedAs (what Type) (allowed bool) {
// ToString outputs the data in the argument as a 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
}
@ -94,7 +113,7 @@ func (literal FloatLiteral) What () (what Type) {
// ToString outputs the data in the argument as a 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
}
@ -125,7 +144,7 @@ func (literal StringLiteral) What () (what Type) {
// ToString outputs the data in the argument as a 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
}
@ -170,7 +189,7 @@ func (literal StringLiteral) canBePassedAs (what Type) (allowed bool) {
// ToString outputs the data in the argument as a 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
}

View File

@ -1,13 +1,38 @@
package analyzer
import "path/filepath"
import "git.tebibyte.media/arf/arf/file"
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.
type sectionBase struct {
where locator
complete bool
permission types.Permission
locatable
}
// Name returns the name of the section.

View File

@ -3,7 +3,9 @@ package analyzer
import "os"
import "sort"
import "path/filepath"
import "git.tebibyte.media/arf/arf/file"
import "git.tebibyte.media/arf/arf/types"
import "git.tebibyte.media/arf/arf/infoerr"
// locator uniquely identifies a section in the section table.
type locator struct {
@ -79,6 +81,8 @@ type Section interface {
ModulePath () (path string)
ModuleName () (path string)
Permission () (permission types.Permission)
Location () (location file.Location)
NewError (message string, kind infoerr.ErrorKind) (err error)
locator () (where locator)
// Must be implemented by each individual section

View File

@ -64,6 +64,8 @@ func (analyzer AnalysisOperation) analyzeTypeSection () (
analyzer.addSection(section)
inputSection := analyzer.currentSection.(parser.TypeSection)
outputSection.location = analyzer.currentSection.Location()
if inputSection.Permission() == types.PermissionReadWrite {
err = inputSection.NewError (
"read-write (rw) permission not understood in this " +
@ -83,7 +85,6 @@ func (analyzer AnalysisOperation) analyzeTypeSection () (
// type check default value
err = analyzer.typeCheck (
inputSection.Argument().Location(),
outputSection.argument,
outputSection.what)
if err != nil { return }

View File

@ -21,6 +21,8 @@ const (
// Type represents a description of a type. It must eventually point to a
// TypeSection.
type Type struct {
locatable
// one of these must be nil.
actual *TypeSection
points *Type
@ -170,6 +172,7 @@ func (analyzer AnalysisOperation) analyzeType (
) {
outputType.mutable = inputType.Mutable()
outputType.length = inputType.Length()
outputType.location = inputType.Location()
if outputType.length < 1 {
err = inputType.NewError (
"cannot specify a length of zero",