Skip to content

Commit 7a7971a

Browse files
committed
Add implements operator
1 parent 507b2ad commit 7a7971a

File tree

5 files changed

+44
-2
lines changed

5 files changed

+44
-2
lines changed

src/vm/wren_compiler.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1719,7 +1719,7 @@ typedef enum
17191719
PREC_LOGICAL_OR, // ||
17201720
PREC_LOGICAL_AND, // &&
17211721
PREC_EQUALITY, // == !=
1722-
PREC_IS, // is
1722+
PREC_IS, // implements is
17231723
PREC_COMPARISON, // < > <= >=
17241724
PREC_BITWISE_OR, // |
17251725
PREC_BITWISE_XOR, // ^
@@ -2793,7 +2793,7 @@ GrammarRule rules[] =
27932793
/* TOKEN_FOR */ UNUSED,
27942794
/* TOKEN_FOREIGN */ UNUSED,
27952795
/* TOKEN_IF */ UNUSED,
2796-
/* TOKEN_IMPLEMENTS */ UNUSED,
2796+
/* TOKEN_IMPLEMENTS */ INFIX_OPERATOR(PREC_IS, "implements"),
27972797
/* TOKEN_IMPORT */ UNUSED,
27982798
/* TOKEN_AS */ UNUSED,
27992799
/* TOKEN_IN */ UNUSED,

src/vm/wren_core.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,16 @@ DEF_PRIMITIVE(object_bangeq)
863863
RETURN_BOOL(!wrenValuesEqual(args[0], args[1]));
864864
}
865865

866+
DEF_PRIMITIVE(object_implements)
867+
{
868+
if (!IS_CLASS(args[1]))
869+
{
870+
RETURN_ERROR("Right operand must be a class.");
871+
}
872+
873+
RETURN_BOOL(wrenObjectImplements(vm, args[0], args[1]));
874+
}
875+
866876
DEF_PRIMITIVE(object_is)
867877
{
868878
if (!IS_CLASS(args[1]))
@@ -1247,6 +1257,7 @@ void wrenInitializeCore(WrenVM* vm)
12471257
PRIMITIVE(vm->objectClass, "!", object_not);
12481258
PRIMITIVE(vm->objectClass, "==(_)", object_eqeq);
12491259
PRIMITIVE(vm->objectClass, "!=(_)", object_bangeq);
1260+
PRIMITIVE(vm->objectClass, "implements(_)", object_implements);
12501261
PRIMITIVE(vm->objectClass, "is(_)", object_is);
12511262
PRIMITIVE(vm->objectClass, "toString", object_toString);
12521263
PRIMITIVE(vm->objectClass, "type", object_type);

src/vm/wren_value.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,35 @@ static void initObj(WrenVM* vm, Obj* obj, ObjType type, ObjClass* classObj)
4343
vm->first = obj;
4444
}
4545

46+
bool wrenObjectImplements(WrenVM* vm, Value obj, Value interface)
47+
{
48+
const ObjClass *classObj = wrenGetClass(vm, obj);
49+
50+
if (IS_CLASS(interface))
51+
{
52+
const ObjClass *interfaceObj = AS_CLASS(interface);
53+
54+
// The following shortpath can't be added because, constructors and static
55+
// method should be ignored.
56+
// if (classObj->methods.count < interfaceObj->methods.count) return false;
57+
58+
const Method* methods = interfaceObj->methods.data;
59+
for (size_t i = 0; i < interfaceObj->methods.count; i++)
60+
{
61+
if (interfaceObj->methods.data[i].type == METHOD_NONE) continue;
62+
63+
// Check if it is a constructor initializer
64+
if (strncmp(vm->methodNames.data[i]->value, "init ", 5) == 0) continue;
65+
66+
if (i >= classObj->methods.count ||
67+
classObj->methods.data[i].type == METHOD_NONE) return false;
68+
}
69+
return true;
70+
}
71+
72+
return false;
73+
}
74+
4675
ObjClass* wrenNewSingleClass(WrenVM* vm, int numFields, ObjString* name)
4776
{
4877
ObjClass* classObj = ALLOCATE(vm, ObjClass);

src/vm/wren_value.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,8 @@ typedef struct
617617

618618
#endif
619619

620+
bool wrenObjectImplements(WrenVM* vm, Value obj, Value interface);
621+
620622
// Creates a new "raw" class. It has no metaclass or superclass whatsoever.
621623
// This is only used for bootstrapping the initial Object and Class classes,
622624
// which are a little special.

test/core/object/implements.wren

Whitespace-only changes.

0 commit comments

Comments
 (0)