Skip to content

Commit 684335d

Browse files
committed
implemented interfaces in Spin2
1 parent 12e7832 commit 684335d

File tree

3 files changed

+90
-1
lines changed

3 files changed

+90
-1
lines changed

Changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Version 7.3.0
44
- Make Spin2 structs actually packed
55
- Fix parsing of `[++]` and `[--]` as pre operators
66
- Fixed error reporting around __builtin_printf
7+
- Implemented `%interface` for Spin2
78
- Updated __builtin_printf to handle %X
89

910
Version 7.2.1

doc/spin.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ waits until CNT reaches "newcnt", and returns "newcnt + incr".
394394
395395
Note that unlike most Spin blocks, the `asm` block has to end with `endasm`. This is because indentation is not significant inside the assembly code. For example, labels typically start at the leftmost margin.
396396
397-
### Spin2 style inline assembly (org/end)
397+
#### Spin2 style inline assembly (org/end)
398398
399399
flexspin also accepts Spin2 style inline assembly, marked with `org` and `end` instead of `asm` and `endasm`. So the above example could be written as:
400400
```
@@ -422,6 +422,28 @@ Unlike the "official" Spin2 compiler, flexspin does not accept an address for th
422422
423423
(4) In PNut/PropTool only the first 16 local variables may be accessed in inline assembly; flexspin has this restriction only for bytecode output. For assembly output other locals may be accessed as well.
424424
425+
### Interfaces
426+
427+
Flexspin supports pointers to interfaces. An interface is like a struct, but instead of having only member variables it has only public functions (no variables are allowed). Any object which implements all of the methods declared in the interface may be passed to an interface pointer.
428+
429+
Interfaces are declared with the `%interface` keyword.
430+
431+
For example, if an object has a declaration like:
432+
```
433+
con
434+
%interface MyIface (
435+
pub getval(): r
436+
pub incr()
437+
)
438+
439+
pub myfunc(^MyIface i): ret
440+
i.incr()
441+
ret := i.getval()
442+
```
443+
Then any object having `incr` and `getval` methods may be passed
444+
as the parameter to `myfunc`, and it will first call the `incr`
445+
method for that object and then return the result of `getval`.
446+
425447
### Method pointers
426448
427449
Pointers to methods may be created with `@` and called using the normal calling syntax. For example:

frontends/spin/spin.y

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,50 @@ SpinDeclareStruct(AST *ident, AST *defs)
342342
PopCurrentModule();
343343
}
344344

345+
// declare a Spin structure
346+
static void
347+
SpinDeclareInterface(AST *ident, AST *defs)
348+
{
349+
const char *classname = GetUserIdentifierName(ident);
350+
Module *P = NewModule(classname, current->curLanguage);
351+
AST *newobj = NewAbstractObject(ident, NULL, 0);
352+
newobj->d.ptr = P;
353+
P->isInterface = 1;
354+
355+
AddSymbol(currentTypes, classname, SYM_TYPEDEF, newobj, NULL);
356+
357+
if (P != current) {
358+
P->Lptr = current->Lptr;
359+
P->subclasses = current->subclasses;
360+
current->subclasses = P;
361+
P->superclass = current;
362+
P->fullname = current->fullname; // for finding "class using"
363+
newobj->d.ptr = (void *)P;
364+
P->isPacked = 1;
365+
366+
/* import parent's symbols into P */
367+
P->objsyms.next = &current->objsyms;
368+
AddSymbol(&current->objsyms, classname, SYM_TYPEDEF, newobj, NULL);
369+
}
370+
371+
PushCurrentModule();
372+
current = P;
373+
AST *item;
374+
/* declare abstract methods */
375+
while (defs) {
376+
AST *rettype;
377+
AST *body = NULL;
378+
item = defs->left;
379+
defs = defs->right;
380+
while (item && item->kind == AST_COMMENTEDNODE) {
381+
item = item->left;
382+
}
383+
rettype = SpinRetType(item);
384+
DeclareFunction(current, rettype, 1, item, body, NULL, NULL);
385+
}
386+
PopCurrentModule();
387+
}
388+
345389
#define YYERROR_VERBOSE 1
346390
%}
347391

@@ -1180,6 +1224,14 @@ conline:
11801224
SpinDeclareStruct(name, defs);
11811225
$$ = NULL;
11821226
}
1227+
| SP_INTERFACE SP_IDENTIFIER '(' ifacelist ')' SP_EOLN
1228+
{
1229+
/* basically an inline object definition */
1230+
AST *defs = $4;
1231+
AST *name = $2;
1232+
SpinDeclareInterface(name, defs);
1233+
$$ = NULL;
1234+
}
11831235
| SP_STRUCT SP_IDENTIFIER '(' structlist ')' SP_EOLN
11841236
{
11851237
/* basically an inline object definition */
@@ -1256,6 +1308,20 @@ structitem:
12561308
}
12571309
;
12581310

1311+
ifacelist:
1312+
ifaceitem
1313+
{ $$ = CommentedListHolder($1); }
1314+
| ifacelist ifaceitem
1315+
{ $$ = AddToList($1, CommentedListHolder($2)); }
1316+
;
1317+
1318+
ifaceitem:
1319+
SP_EOLN /* empty */
1320+
{ $$ = NULL; }
1321+
| SP_PUB funcdef funcdef_end
1322+
{ $$ = $2; }
1323+
;
1324+
12591325
enumlist:
12601326
enumitem
12611327
{ $$ = CommentedListHolder($1); }

0 commit comments

Comments
 (0)