From 7581541ff5ccc131602ce4acc55be45fb3d8e8c2 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Tue, 11 Oct 2022 18:31:37 -0400 Subject: [PATCH] Added a locatable node trait --- analyzer/analyzer.go | 5 +---- analyzer/argument.go | 35 +++++++++++++++++++++++++++++------ analyzer/literals.go | 39 +++++++++++++++++++++++++++++---------- analyzer/node-traits.go | 25 +++++++++++++++++++++++++ analyzer/table.go | 4 ++++ analyzer/type-section.go | 3 ++- analyzer/type.go | 7 +++++-- 7 files changed, 95 insertions(+), 23 deletions(-) diff --git a/analyzer/analyzer.go b/analyzer/analyzer.go index 208ade5..54e7af9 100644 --- a/analyzer/analyzer.go +++ b/analyzer/analyzer.go @@ -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), diff --git a/analyzer/argument.go b/analyzer/argument.go index 629f7ae..a62eafd 100644 --- a/analyzer/argument.go +++ b/analyzer/argument.go @@ -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. @@ -15,7 +16,9 @@ type Argument interface { // FloatLiteral // StringLiteral - What () (what Type) + 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 } diff --git a/analyzer/literals.go b/analyzer/literals.go index 3c34f1e..59649c9 100644 --- a/analyzer/literals.go +++ b/analyzer/literals.go @@ -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 } diff --git a/analyzer/node-traits.go b/analyzer/node-traits.go index e5ebf7e..ed70884 100644 --- a/analyzer/node-traits.go +++ b/analyzer/node-traits.go @@ -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. diff --git a/analyzer/table.go b/analyzer/table.go index bc5df27..c625917 100644 --- a/analyzer/table.go +++ b/analyzer/table.go @@ -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 diff --git a/analyzer/type-section.go b/analyzer/type-section.go index a52fba1..71c8a38 100644 --- a/analyzer/type-section.go +++ b/analyzer/type-section.go @@ -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 } diff --git a/analyzer/type.go b/analyzer/type.go index 96b71d7..f532b6b 100644 --- a/analyzer/type.go +++ b/analyzer/type.go @@ -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 @@ -168,8 +170,9 @@ func (analyzer AnalysisOperation) analyzeType ( outputType Type, err error, ) { - outputType.mutable = inputType.Mutable() - outputType.length = inputType.Length() + 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",