Skip to content

Commit c358dd5

Browse files
committed
Support bitfield declarations in BASIC
1 parent 8c2b59a commit c358dd5

4 files changed

Lines changed: 39 additions & 3 deletions

File tree

doc/basic.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,6 +1539,16 @@ Using Spin objects with `class using` is straightforward, but there are some thi
15391539
* Spin does not have any notion of types, so most Spin functions will return type `any` and take parameters of type `any`. This can cause problems if you expect them to return something special like a pointer or float and want to use them in the middle of an expression. You can either use explicit `cast` operations, or assign the results of Spin methods to a typed variable, and then use that variable in the expression instead.
15401540
* Spin treats strings differently than BASIC does. For example, in the Spin expression `ser.tx("A")`, `"A"` is an integer (a single element list). That would be written in BASIC as `ser.tx(asc("A"))`. Conversely, in Spin you have to write `ser.str(string("hello"))` where in BASIC you would write just `ser.str("hello")`.
15411541

1542+
#### Bitfields in classes
1543+
1544+
FlexBasic supports the FreeBasic syntax for declaring bitfields, which is similar to C syntax. For example, to declare a class with a 3 bit unsigned field `x` and a 4 bit signed field `y` do:
1545+
```
1546+
class bfield
1547+
x:3 as uinteger
1548+
y:4 as integer
1549+
end class
1550+
```
1551+
15421552
#### Interoperation with C
15431553

15441554
C files may be used as classes, but there are some restrictions. BASIC and Spin are both case insensitive languages, which means that the BASIC symbols `AVariable`, `avariable`, and `AVARIABLE` are all the same, and all are translated internally to `avariable`. In C the case of identifiers matters. This makes accessing C symbols from BASIC somewhat tricky: one must exactly match the case of the C identifier in order to access it.

expr.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3272,6 +3272,11 @@ ExprTypeRelative(SymbolTable *table, AST *expr, Module *P)
32723272
return typ;
32733273
}
32743274
return ExprTypeRelative(&subclass->objsyms, (AST *)sym->v.ptr, P);
3275+
case SYM_TEMPLATE:
3276+
{
3277+
/* HACK: we need to ignore this in some cases */
3278+
return NULL;
3279+
}
32753280
case SYM_LABEL:
32763281
{
32773282
Label *lref = (Label *)sym->v.ptr;

frontends/basic/basic.y

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ DeclareBASICMemberVariables(AST *ast)
221221
AST *idlist, *typ;
222222
AST *ident;
223223
int is_private = 0;
224+
BitFieldState bitfield = { 0 };
224225

225226
if (!ast) return;
226227
if (ast->kind == AST_SEQUENCE) {
@@ -253,11 +254,11 @@ DeclareBASICMemberVariables(AST *ast)
253254
bittyp = NewAST(AST_BITFIELD, typ, ident->right);
254255
ident = ident->left;
255256
}
256-
MaybeDeclareMemberVar(current, ident, bittyp, is_private, NORMAL_VAR, NULL);
257+
MaybeDeclareMemberVar(current, ident, bittyp, is_private, NORMAL_VAR, &bitfield);
257258
idlist = idlist->right;
258259
}
259260
} else {
260-
MaybeDeclareMemberVar(current, idlist, typ, is_private, NORMAL_VAR, NULL);
261+
MaybeDeclareMemberVar(current, idlist, typ, is_private, NORMAL_VAR, &bitfield);
261262
}
262263
return;
263264
}

frontends/basic/basiclang.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,17 @@ doBasicTransform(AST **astptr, bool transformFuncall)
905905
}
906906
doBasicTransform(&ast->left, transformFuncall);
907907
doBasicTransform(&ast->right, transformFuncall);
908+
#if 1
909+
// this seems pretty hacky but is needed to make new
910+
// struct bitfields work; note that the similar test above
911+
// is for older style bitfields like output(1) = ...
912+
if (ast->left && ast->left->kind == AST_CAST && ast->left->right && ast->left->right->kind == AST_RANGEREF) {
913+
ast->left = ast->left->right;
914+
}
915+
if (ast->left && ast->left->kind == AST_RANGEREF) {
916+
*astptr = ast = TransformRangeAssign(ast->left, ast->right, ast->d.ival, 1);
917+
}
918+
#endif
908919
break;
909920
case AST_CASE:
910921
case AST_CASETABLE:
@@ -998,7 +1009,16 @@ doBasicTransform(AST **astptr, bool transformFuncall)
9981009
doBasicTransform(&ast->left, transformFuncall);
9991010
doBasicTransform(&ast->right, transformFuncall);
10001011
{
1001-
AST *typ = ExprType(ast->left);
1012+
AST *typ = ExprType(ast);
1013+
if (typ && typ->kind == AST_USING) {
1014+
AST *replace = DupAST(typ->left);
1015+
if (replace && replace->right && replace->right->kind == AST_RANGEREF) {
1016+
ast->right = replace->right->left;
1017+
replace->right->left = DupAST(ast);
1018+
}
1019+
*ast = *replace;
1020+
}
1021+
typ = ExprType(ast->left);
10021022
if (IsPointerType(typ) && !IsRefType(typ)) {
10031023
// WARNING(ast, "Needs a pointer dereference");
10041024
ast->left = NewAST(AST_ARRAYREF, ast->left, AstInteger(0));

0 commit comments

Comments
 (0)