diff --git a/analyzer/argument.go b/analyzer/argument.go index aa333df..629f7ae 100644 --- a/analyzer/argument.go +++ b/analyzer/argument.go @@ -15,6 +15,7 @@ type Argument interface { // FloatLiteral // StringLiteral + What () (what Type) ToString (indent int) (output string) canBePassedAs (what Type) (allowed bool) } diff --git a/analyzer/common-errors.go b/analyzer/common-errors.go new file mode 100644 index 0000000..c8c5581 --- /dev/null +++ b/analyzer/common-errors.go @@ -0,0 +1,8 @@ +package analyzer + +func typeMismatchErrorMessage (source Type, destination Type) (message string) { + message += source.Describe() + message += " cannot be used as " + message += destination.Describe() + return +} diff --git a/analyzer/literals.go b/analyzer/literals.go index d4156d7..50a1f15 100644 --- a/analyzer/literals.go +++ b/analyzer/literals.go @@ -14,6 +14,13 @@ func (literal IntLiteral) ToString (indent int) (output string) { return } +// What returns the type of the argument +func (literal IntLiteral) What () (what Type) { + what.actual = &PrimitiveI64 + what.length = 1 + return +} + // canBePassedAs returns true if this literal can be implicitly cast to the // specified type, and false if it can't. func (literal IntLiteral) canBePassedAs (what Type) (allowed bool) { @@ -43,6 +50,13 @@ func (literal UIntLiteral) ToString (indent int) (output string) { return } +// What returns the type of the argument +func (literal UIntLiteral) What () (what Type) { + what.actual = &PrimitiveU64 + what.length = 1 + return +} + // canBePassedAs returns true if this literal can be implicitly cast to the // specified type, and false if it can't. func (literal UIntLiteral) canBePassedAs (what Type) (allowed bool) { @@ -71,6 +85,13 @@ func (literal UIntLiteral) canBePassedAs (what Type) (allowed bool) { return } +// What returns the type of the argument +func (literal FloatLiteral) What () (what Type) { + what.actual = &PrimitiveF64 + what.length = 1 + return +} + // 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")) @@ -95,6 +116,13 @@ func (literal FloatLiteral) canBePassedAs (what Type) (allowed bool) { return } +// What returns the type of the argument +func (literal StringLiteral) What () (what Type) { + what.actual = &BuiltInString + what.length = 1 + return +} + // 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")) diff --git a/analyzer/type-section.go b/analyzer/type-section.go index eaa09b0..2bc7854 100644 --- a/analyzer/type-section.go +++ b/analyzer/type-section.go @@ -80,12 +80,16 @@ func (analyzer AnalysisOperation) analyzeTypeSection () ( outputSection.argument, err = analyzer.analyzeArgument(inputSection.Argument()) if err != nil { return } + + // type check default value if !outputSection.argument.canBePassedAs(outputSection.what) { - + err = inputSection.Argument().NewError ( + typeMismatchErrorMessage ( + outputSection.argument.What(), + outputSection.what), + infoerr.ErrorKindError) + return } - // TODO: type check default value. possibly add a method to - // Argument that takes in a type and determines whether the - // argument can fit to it. } // TODO: analyze members diff --git a/analyzer/type.go b/analyzer/type.go index 70d1530..ebdf641 100644 --- a/analyzer/type.go +++ b/analyzer/type.go @@ -1,6 +1,7 @@ package analyzer -// import "git.tebibyte.media/arf/arf/types" +import "fmt" +import "path/filepath" import "git.tebibyte.media/arf/arf/parser" import "git.tebibyte.media/arf/arf/infoerr" @@ -204,3 +205,63 @@ func (analyzer AnalysisOperation) analyzeType ( return } + +// Describe provides a human readable description of the type. The value of this +// should not be computationally analyzed. +func (what Type) Describe () (description string) { + if what.kind == TypeKindBasic { + actual := what.actual + switch actual { + case &PrimitiveF32: + description += "F32" + case &PrimitiveF64: + description += "F64" + case &PrimitiveFunc: + description += "Func" + case &PrimitiveFace: + description += "Face" + case &PrimitiveObj: + description += "Obj" + case &PrimitiveU64: + description += "U64" + case &PrimitiveU32: + description += "U32" + case &PrimitiveU16: + description += "U16" + case &PrimitiveU8: + description += "U8" + case &PrimitiveI64: + description += "I64" + case &PrimitiveI32: + description += "I32" + case &PrimitiveI16: + description += "I16" + case &PrimitiveI8: + description += "I8" + case &PrimitiveUInt: + description += "UInt" + case &PrimitiveInt: + description += "Int" + + case nil: + panic("invalid state: Type.actual is nil") + + default: + locator := actual.locator() + description += + filepath.Base(locator.modulePath) + + "." + locator.name + return + } + } else { + description += "{" + description += what.points.Describe() + description += "}" + } + + if what.length > 0 { + description += fmt.Sprint(":", what.length) + } + + return +}