Added a locatable node trait
This commit is contained in:
		
							parent
							
								
									cd670d05c5
								
							
						
					
					
						commit
						7581541ff5
					
				| @ -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), | ||||
|  | ||||
| @ -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 | ||||
| } | ||||
|  | ||||
| @ -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 | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -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. | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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 } | ||||
|  | ||||
| @ -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", | ||||
|  | ||||
		Reference in New Issue
	
	Block a user