added offsetof() to get the byte offset of struct members.

This commit is contained in:
Irmen de Jong 2021-01-23 23:11:57 +01:00
parent 975af4764d
commit 997bc21feb
4 changed files with 64 additions and 9 deletions

View File

@ -102,6 +102,7 @@ private val functionSignatures: List<FSignature> = listOf(
FSignature("abs" , true, listOf(FParam("value", NumericDatatypes)), null, ::builtinAbs), // type depends on argument
FSignature("len" , true, listOf(FParam("values", IterableDatatypes)), null, ::builtinLen), // type is UBYTE or UWORD depending on actual length
FSignature("sizeof" , true, listOf(FParam("object", DataType.values().toSet())), DataType.UBYTE, ::builtinSizeof),
FSignature("offsetof" , true, listOf(FParam("object", DataType.values().toSet())), DataType.UBYTE, ::builtinOffsetof),
// normal functions follow:
FSignature("sgn" , true, listOf(FParam("value", NumericDatatypes)), DataType.BYTE, ::builtinSgn ),
FSignature("sin" , true, listOf(FParam("rads", setOf(DataType.FLOAT))), DataType.FLOAT) { a, p, prg -> oneDoubleArg(a, p, prg, Math::sin) },
@ -278,6 +279,28 @@ private fun builtinAbs(args: List<Expression>, position: Position, program: Prog
}
}
private fun builtinOffsetof(args: List<Expression>, position: Position, program: Program): NumericLiteralValue {
// 1 arg, type = anything, result type = ubyte
if(args.size!=1)
throw SyntaxError("offsetof requires one argument", position)
val idref = args[0] as? IdentifierReference
?: throw SyntaxError("offsetof argument should be an identifier", position)
val vardecl = idref.targetVarDecl(program.namespace)!!
val struct = vardecl.struct
if (struct == null || vardecl.datatype == DataType.STRUCT)
throw SyntaxError("offsetof can only be used on struct members", position)
val membername = idref.nameInSource.last()
var offset = 0
for(member in struct.statements) {
if((member as VarDecl).name == membername)
return NumericLiteralValue(DataType.UBYTE, offset, position)
offset += member.datatype.memorySize()
}
throw SyntaxError("undefined struct member", position)
}
private fun builtinSizeof(args: List<Expression>, position: Position, program: Program): NumericLiteralValue {
// 1 arg, type = anything, result type = ubyte
if(args.size!=1)

View File

@ -843,6 +843,11 @@ sizeof(name)
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.
offsetof(membername)
Number of bytes from the start of a struct variable that this member variable is located.
For now, this only works on members of a declared struct variable and not yet on members
referenced from the struct type itself. This might be improved in a future version of the language.
swap(x, y)
Swap the values of numerical variables (or memory locations) x and y in a fast way.

View File

@ -2,7 +2,6 @@
TODO
====
- add offsetof() to get the byte offset of struct members.
- add any2(), all2(), max2(), min2(), reverse2(), sum2(), sort2() that take (array, startindex, length) arguments
- optimize for loop iterations better to allow proper inx, cpx #value, bne loop instructions (like repeat loop)
- why is there a beq _prog8_label_2_repeatend at the end of repeat loops? seems unused

View File

@ -1,6 +1,7 @@
%import textio
%import diskio
%import string
%import floats
%zeropage basicsafe
%option no_sysinit
@ -9,14 +10,41 @@ main {
sub start() {
diskio.directory(8)
diskio.save(8, "blabla", $2000, 1024)
diskio.directory(8)
diskio.rename(8, "blabla", "newname")
diskio.directory(8)
diskio.delete(8, "newname")
diskio.directory(8)
struct SaveData {
ubyte galaxy
ubyte planet
uword cash
float flt
ubyte fuel
}
SaveData data
txt.print("size of struct: ")
txt.print_ub(sizeof(SaveData))
txt.chrout(';')
txt.print_ub(sizeof(data))
txt.chrout('\n')
txt.print("offset of galaxy: ")
txt.print_ub(offsetof(data.galaxy))
txt.chrout('\n')
txt.print("offset of planet: ")
txt.print_ub(offsetof(data.planet))
txt.chrout('\n')
txt.print("offset of cash: ")
txt.print_ub(offsetof(data.cash))
txt.chrout('\n')
txt.print("offset of flt: ")
txt.print_ub(offsetof(data.flt))
txt.chrout('\n')
txt.print("offset of fuel: ")
txt.print_ub(offsetof(data.fuel))
txt.chrout('\n')
txt.print("---------------------------------\n")
}
}