mirror of
https://github.com/irmen/prog8.git
synced 2024-12-25 08:29:25 +00:00
added sizeof() function
This commit is contained in:
parent
774897260e
commit
edfd9d55ba
@ -58,7 +58,7 @@ enum class DataType {
|
||||
in ByteDatatypes -> 1
|
||||
in WordDatatypes -> 2
|
||||
FLOAT -> CompilationTarget.machine.FLOAT_MEM_SIZE
|
||||
in PassByReferenceDatatypes -> 2
|
||||
in PassByReferenceDatatypes -> CompilationTarget.machine.POINTER_MEM_SIZE
|
||||
else -> -9999999
|
||||
}
|
||||
}
|
||||
|
@ -716,11 +716,10 @@ data class IdentifierReference(val nameInSource: List<String>, override val posi
|
||||
override fun referencesIdentifiers(vararg name: String): Boolean = nameInSource.last() in name
|
||||
|
||||
override fun inferType(program: Program): InferredTypes.InferredType {
|
||||
val targetStmt = targetStatement(program.namespace)
|
||||
return if(targetStmt is VarDecl) {
|
||||
InferredTypes.knownFor(targetStmt.datatype)
|
||||
} else {
|
||||
InferredTypes.InferredType.unknown()
|
||||
return when (val targetStmt = targetStatement(program.namespace)) {
|
||||
is VarDecl -> InferredTypes.knownFor(targetStmt.datatype)
|
||||
is StructDecl -> InferredTypes.knownFor(DataType.STRUCT)
|
||||
else -> InferredTypes.InferredType.unknown()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ interface IMachineDefinition {
|
||||
val FLOAT_MAX_NEGATIVE: Double
|
||||
val FLOAT_MAX_POSITIVE: Double
|
||||
val FLOAT_MEM_SIZE: Int
|
||||
val POINTER_MEM_SIZE: Int
|
||||
|
||||
val opcodeNames: Set<String>
|
||||
|
||||
|
@ -14,6 +14,7 @@ object C64MachineDefinition: IMachineDefinition {
|
||||
override val FLOAT_MAX_POSITIVE = 1.7014118345e+38 // bytes: 255,127,255,255,255
|
||||
override val FLOAT_MAX_NEGATIVE = -1.7014118345e+38 // bytes: 255,255,255,255,255
|
||||
override val FLOAT_MEM_SIZE = 5
|
||||
override val POINTER_MEM_SIZE = 2
|
||||
const val BASIC_LOAD_ADDRESS = 0x0801
|
||||
const val RAW_LOAD_ADDRESS = 0xc000
|
||||
|
||||
|
@ -3,6 +3,8 @@ package prog8.functions
|
||||
import prog8.ast.Program
|
||||
import prog8.ast.base.*
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.StructDecl
|
||||
import prog8.ast.statements.VarDecl
|
||||
import prog8.compiler.CompilerException
|
||||
import kotlin.math.*
|
||||
|
||||
@ -35,6 +37,7 @@ val BuiltinFunctions = mapOf(
|
||||
"sum" to FSignature(true, listOf(FParam("values", ArrayDatatypes)), null) { a, p, prg -> collectionArg(a, p, prg, ::builtinSum) }, // type depends on args
|
||||
"abs" to FSignature(true, listOf(FParam("value", NumericDatatypes)), null, ::builtinAbs), // type depends on argument
|
||||
"len" to FSignature(true, listOf(FParam("values", IterableDatatypes)), null, ::builtinLen), // type is UBYTE or UWORD depending on actual length
|
||||
"sizeof" to FSignature(true, listOf(FParam("object", DataType.values().toSet())), DataType.UBYTE, ::builtinSizeof),
|
||||
// normal functions follow:
|
||||
"sgn" to FSignature(true, listOf(FParam("value", NumericDatatypes)), DataType.BYTE, ::builtinSgn ),
|
||||
"sin" to FSignature(true, listOf(FParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::sin) },
|
||||
@ -240,6 +243,42 @@ private fun builtinAbs(args: List<Expression>, position: Position, program: Prog
|
||||
}
|
||||
}
|
||||
|
||||
private fun builtinSizeof(args: List<Expression>, position: Position, program: Program): NumericLiteralValue {
|
||||
// 1 arg, type = anything, result type = ubyte
|
||||
if(args.size!=1)
|
||||
throw SyntaxError("sizeof requires one argument", position)
|
||||
if(args[0] !is IdentifierReference)
|
||||
throw SyntaxError("sizeof argument should be an identifier", position)
|
||||
|
||||
val dt = args[0].inferType(program)
|
||||
if(dt.isKnown) {
|
||||
val target = (args[0] as IdentifierReference).targetStatement(program.namespace)
|
||||
?: throw CannotEvaluateException("sizeof", "no target")
|
||||
|
||||
fun structSize(target: StructDecl) =
|
||||
NumericLiteralValue(DataType.UBYTE, target.statements.map { (it as VarDecl).datatype.memorySize() }.sum(), position)
|
||||
|
||||
return when {
|
||||
dt.typeOrElse(DataType.STRUCT) in ArrayDatatypes -> {
|
||||
val length = (target as VarDecl).arraysize!!.size() ?: throw CannotEvaluateException("sizeof", "unknown array size")
|
||||
val elementDt = ArrayElementTypes.getValue(dt.typeOrElse(DataType.STRUCT))
|
||||
numericLiteral(elementDt.memorySize() * length, position)
|
||||
}
|
||||
dt.istype(DataType.STRUCT) -> {
|
||||
when (target) {
|
||||
is VarDecl -> structSize(target.struct!!)
|
||||
is StructDecl -> structSize(target)
|
||||
else -> throw CompilerException("weird struct type $target")
|
||||
}
|
||||
}
|
||||
dt.istype(DataType.STR) -> throw SyntaxError("sizeof str is undefined, did you mean len?", position)
|
||||
else -> NumericLiteralValue(DataType.UBYTE, dt.typeOrElse(DataType.STRUCT).memorySize(), position)
|
||||
}
|
||||
} else {
|
||||
throw SyntaxError("sizeof invalid argument type", position)
|
||||
}
|
||||
}
|
||||
|
||||
private fun builtinStrlen(args: List<Expression>, position: Position, program: Program): NumericLiteralValue {
|
||||
if (args.size != 1)
|
||||
throw SyntaxError("strlen requires one argument", position)
|
||||
@ -262,18 +301,12 @@ private fun builtinLen(args: List<Expression>, position: Position, program: Prog
|
||||
if(args[0] is ArrayLiteralValue)
|
||||
return NumericLiteralValue.optimalInteger((args[0] as ArrayLiteralValue).value.size, position)
|
||||
if(args[0] !is IdentifierReference)
|
||||
throw SyntaxError("len argument should be an identifier, but is ${args[0]}", position)
|
||||
throw SyntaxError("len argument should be an identifier", position)
|
||||
val target = (args[0] as IdentifierReference).targetVarDecl(program.namespace)
|
||||
?: throw CannotEvaluateException("len", "no target vardecl")
|
||||
|
||||
return when(target.datatype) {
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W -> {
|
||||
arraySize = target.arraysize?.size()
|
||||
if(arraySize==null)
|
||||
throw CannotEvaluateException("len", "arraysize unknown")
|
||||
NumericLiteralValue.optimalInteger(arraySize, args[0].position)
|
||||
}
|
||||
DataType.ARRAY_F -> {
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W, DataType.ARRAY_F -> {
|
||||
arraySize = target.arraysize?.size()
|
||||
if(arraySize==null)
|
||||
throw CannotEvaluateException("len", "arraysize unknown")
|
||||
|
@ -724,11 +724,17 @@ reverse(array)
|
||||
|
||||
len(x)
|
||||
Number of values in the array value x, or the number of characters in a string (excluding the size or 0-byte).
|
||||
Note: this can be different from the number of *bytes* in memory if the datatype isn't a byte.
|
||||
Note: this can be different from the number of *bytes* in memory if the datatype isn't a byte. See sizeof().
|
||||
Note: lengths of strings and arrays are determined at compile-time! If your program modifies the actual
|
||||
length of the string during execution, the value of len(string) may no longer be correct!
|
||||
(use strlen function if you want to dynamically determine the length)
|
||||
|
||||
sizeof(name)
|
||||
Number of bytes that the object 'name' occupies in memory. This is a constant determined by the data type of
|
||||
the object. For instance, for a variable of type uword, the sizeof is 2.
|
||||
For an 10 element array of floats, it is 50 (on the C-64, where a float is 5 bytes).
|
||||
Note: usually you will be interested in the number of elements in an array, use len() for that.
|
||||
|
||||
strlen(str)
|
||||
Number of bytes in the string. This value is determined during runtime and counts upto
|
||||
the first terminating 0 byte in the string, regardless of the size of the string during compilation time.
|
||||
|
@ -15,44 +15,45 @@ main {
|
||||
|
||||
Color c = [11,22222,3.1234]
|
||||
|
||||
; c64scr.print_ub(c.red)
|
||||
; c64.CHROUT('\n')
|
||||
; c64scr.print_uw(c.green)
|
||||
; c64.CHROUT('\n')
|
||||
; c64flt.print_f(c.blue)
|
||||
; c64.CHROUT('\n')
|
||||
str string = "irmen"
|
||||
byte[] ab = [1,2,3]
|
||||
ubyte[] aub = [1,2,3]
|
||||
word[] aw = [11,22,33]
|
||||
uword[] auw = [11,22,33]
|
||||
float[] af = [1.1,2.2,3.3]
|
||||
|
||||
uword xx = 4.5678
|
||||
ubyte bb = 33
|
||||
float ff = 1.234
|
||||
c64scr.print_ub(sizeof(ab))
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print_ub(sizeof(aub))
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print_ub(sizeof(aw))
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print_ub(sizeof(auw))
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print_ub(sizeof(af))
|
||||
c64.CHROUT('\n')
|
||||
c64.CHROUT('\n')
|
||||
c64.CHROUT('\n')
|
||||
|
||||
foo(1.234, 4.456) ; TODO truncation warning
|
||||
foo2(2.3456) ; TODO truncation warning
|
||||
foo2(bb)
|
||||
foo2(4.55) ; TODO truncation warning
|
||||
c64scr.print_ub(c.red)
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print_uw(c.green)
|
||||
c64.CHROUT('\n')
|
||||
c64flt.print_f(c.blue)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
;foo("zzz", 8.777)
|
||||
;len(13)
|
||||
|
||||
; uword size = len(Color)
|
||||
; c64scr.print_uw(size)
|
||||
; c64.CHROUT('\n')
|
||||
|
||||
; c64scr.print_ub(len(Color))
|
||||
; c64.CHROUT('\n')
|
||||
; c64scr.print_ub(len(c))
|
||||
; c64.CHROUT('\n')
|
||||
; c64scr.print_ub(len(c.green))
|
||||
; c64.CHROUT('\n')
|
||||
}
|
||||
|
||||
sub foo(ubyte aa, word ww) {
|
||||
ww += aa
|
||||
}
|
||||
|
||||
asmsub foo2(ubyte aa @Pc) {
|
||||
%asm {{
|
||||
rts
|
||||
}}
|
||||
ubyte size = sizeof(Color)
|
||||
c64scr.print_ub(size)
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print_ub(sizeof(Color))
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print_ub(sizeof(c))
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print_ub(sizeof(c.red))
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print_ub(sizeof(c.green))
|
||||
c64.CHROUT('\n')
|
||||
c64scr.print_ub(sizeof(c.blue))
|
||||
c64.CHROUT('\n')
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user