Added some useful type checking thigns to literals
This commit is contained in:
parent
e2947eab8c
commit
5c286cf955
@ -19,6 +19,7 @@ type Argument interface {
|
||||
// RuneLiteral
|
||||
|
||||
ToString (indent int) (output string)
|
||||
canBePassedAs (what Type) (allowed bool)
|
||||
}
|
||||
|
||||
// analyzeArgument analyzes an argument
|
||||
|
@ -14,24 +14,118 @@ func (literal IntLiteral) ToString (indent int) (output string) {
|
||||
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) {
|
||||
// must be a singlular value
|
||||
if what.length != 1 { return }
|
||||
|
||||
// can be passed to types that are signed numbers at a primitive level.
|
||||
primitive := what.underlyingPrimitive()
|
||||
switch primitive {
|
||||
case
|
||||
&PrimitiveF64,
|
||||
&PrimitiveF32,
|
||||
&PrimitiveI64,
|
||||
&PrimitiveI32,
|
||||
&PrimitiveI16,
|
||||
&PrimitiveI8,
|
||||
&PrimitiveInt:
|
||||
|
||||
allowed = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 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"))
|
||||
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) {
|
||||
// must be a singlular value
|
||||
if what.length != 1 { return }
|
||||
|
||||
// can be passed to types that are numbers at a primitive level.
|
||||
primitive := what.underlyingPrimitive()
|
||||
switch primitive {
|
||||
case
|
||||
&PrimitiveF64,
|
||||
&PrimitiveF32,
|
||||
&PrimitiveI64,
|
||||
&PrimitiveI32,
|
||||
&PrimitiveI16,
|
||||
&PrimitiveI8,
|
||||
&PrimitiveInt,
|
||||
&PrimitiveU64,
|
||||
&PrimitiveU32,
|
||||
&PrimitiveU16,
|
||||
&PrimitiveU8,
|
||||
&PrimitiveUInt:
|
||||
|
||||
allowed = true
|
||||
}
|
||||
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"))
|
||||
return
|
||||
}
|
||||
|
||||
// canBePassedAs returns true if this literal can be implicitly cast to the
|
||||
// specified type, and false if it can't.
|
||||
func (literal FloatLiteral) canBePassedAs (what Type) (allowed bool) {
|
||||
// must be a singlular value
|
||||
if what.length != 1 { return }
|
||||
|
||||
// can be passed to types that are floats at a primitive level.
|
||||
primitive := what.underlyingPrimitive()
|
||||
switch primitive {
|
||||
case
|
||||
&PrimitiveF64,
|
||||
&PrimitiveF32:
|
||||
|
||||
allowed = true
|
||||
}
|
||||
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"))
|
||||
return
|
||||
}
|
||||
|
||||
// canBePassedAs returns true if this literal can be implicitly cast to the
|
||||
// specified type, and false if it can't.
|
||||
func (literal StringLiteral) canBePassedAs (what Type) (allowed bool) {
|
||||
// can be passed to types that are numbers at a primitive level.
|
||||
primitive := what.underlyingPrimitive()
|
||||
switch primitive {
|
||||
case
|
||||
&PrimitiveF64,
|
||||
&PrimitiveF32,
|
||||
&PrimitiveI64,
|
||||
&PrimitiveI32,
|
||||
&PrimitiveI16,
|
||||
&PrimitiveI8,
|
||||
&PrimitiveInt,
|
||||
&PrimitiveU64,
|
||||
&PrimitiveU32,
|
||||
&PrimitiveU16,
|
||||
&PrimitiveU8,
|
||||
&PrimitiveUInt:
|
||||
|
||||
allowed = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 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"))
|
||||
|
@ -2,6 +2,8 @@ package analyzer
|
||||
|
||||
// This is a global, cannonical list of primitive and built-in types.
|
||||
|
||||
var PrimitiveF32 = createPrimitive("Int", Type {})
|
||||
var PrimitiveF64 = createPrimitive("Int", Type {})
|
||||
var PrimitiveInt = createPrimitive("Int", Type {})
|
||||
var PrimitiveUInt = createPrimitive("UInt", Type {})
|
||||
var PrimitiveI8 = createPrimitive("I8", Type {})
|
||||
|
@ -16,21 +16,20 @@ const (
|
||||
|
||||
// TypeKindVariableArray means it's an array of variable length.
|
||||
TypeKindVariableArray
|
||||
|
||||
// TypeKindObject means it's a structured type with members.
|
||||
TypeKindObject
|
||||
)
|
||||
|
||||
// Type represents a description of a type. It must eventually point to a
|
||||
// TypeSection.
|
||||
type Type struct {
|
||||
// one of these must be nil.
|
||||
actual Section
|
||||
actual *TypeSection
|
||||
points *Type
|
||||
|
||||
mutable bool
|
||||
kind TypeKind
|
||||
|
||||
primitiveCache *TypeSection
|
||||
|
||||
// if this is greater than 1, it means that this is a fixed-length array
|
||||
// of whatever the type is. even if the type is a variable length array.
|
||||
// because literally why not.
|
||||
@ -52,8 +51,6 @@ func (what Type) ToString (indent int) (output string) {
|
||||
output += " pointer"
|
||||
case TypeKindVariableArray:
|
||||
output += " variableArray"
|
||||
case TypeKindObject:
|
||||
output += " object"
|
||||
}
|
||||
|
||||
if what.points != nil {
|
||||
@ -70,6 +67,78 @@ func (what Type) ToString (indent int) (output string) {
|
||||
return
|
||||
}
|
||||
|
||||
// underlyingPrimitive returns the primitive that this type eventually inherits
|
||||
// from.
|
||||
func (what Type) underlyingPrimitive () (underlying *TypeSection) {
|
||||
// if we have already done this operation, return the cahced result.
|
||||
if what.primitiveCache != nil {
|
||||
underlying = what.primitiveCache
|
||||
return
|
||||
}
|
||||
|
||||
if what.kind != TypeKindBasic {
|
||||
// if we point to something, return nil because there is no void
|
||||
// pointer bullshit in this language
|
||||
return
|
||||
}
|
||||
|
||||
actual := what.actual
|
||||
switch actual {
|
||||
case
|
||||
&PrimitiveF32,
|
||||
&PrimitiveF64,
|
||||
&PrimitiveFunc,
|
||||
&PrimitiveFace,
|
||||
&PrimitiveObj,
|
||||
&PrimitiveU64,
|
||||
&PrimitiveU32,
|
||||
&PrimitiveU16,
|
||||
&PrimitiveU8,
|
||||
&PrimitiveI64,
|
||||
&PrimitiveI32,
|
||||
&PrimitiveI16,
|
||||
&PrimitiveI8,
|
||||
&PrimitiveUInt,
|
||||
&PrimitiveInt:
|
||||
|
||||
underlying = actual
|
||||
return
|
||||
|
||||
case nil:
|
||||
panic("invalid state: Type.actual is nil")
|
||||
|
||||
default:
|
||||
// if none of the primitives matched, recurse.
|
||||
underlying = actual.what.underlyingPrimitive()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// reduce ascends up the inheritence chain and gets the first type it finds that
|
||||
// isn't basic. If the type has a clear path of inheritence to a simple
|
||||
// primitive, there will be no non-basic types in the chain and this method will
|
||||
// return false for reducible. If the type this method is called on is not
|
||||
// basic, it itself is returned.
|
||||
func (what Type) reduce () (reduced Type, reducible bool) {
|
||||
reducible = true
|
||||
|
||||
// returns itself if it is not basic (cannot be reduced further)
|
||||
if what.kind != TypeKindBasic {
|
||||
reduced = what
|
||||
return
|
||||
}
|
||||
|
||||
// if we can't recurse, return false for reducible
|
||||
if what.actual == nil {
|
||||
reducible = false
|
||||
return
|
||||
}
|
||||
|
||||
// otherwise, recurse
|
||||
reduced, reducible = what.actual.what.reduce()
|
||||
return
|
||||
}
|
||||
|
||||
// analyzeType analyzes a type specifier.
|
||||
func (analyzer AnalysisOperation) analyzeType (
|
||||
inputType parser.Type,
|
||||
@ -93,9 +162,13 @@ func (analyzer AnalysisOperation) analyzeType (
|
||||
outputType.points = &points
|
||||
} else {
|
||||
var bitten parser.Identifier
|
||||
outputType.actual,
|
||||
var actual Section
|
||||
actual,
|
||||
bitten,
|
||||
err = analyzer.fetchSectionFromIdentifier(inputType.Name())
|
||||
|
||||
outputType.actual = actual.(*TypeSection)
|
||||
// TODO: produce an error if this doesnt work
|
||||
|
||||
if bitten.Length() > 0 {
|
||||
err = bitten.NewError(
|
||||
|
Reference in New Issue
Block a user