in test (ie. elem in container) implemented. (#117)

in keyword will invoke varContains(), the for now the list contains
implemented.
This commit is contained in:
Thakee Nathees 2021-06-23 15:51:59 +05:30 committed by GitHub
parent 000f4c4fe4
commit 64bf27674a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 63 additions and 11 deletions

View File

@ -218,10 +218,8 @@ typedef enum {
PREC_LOWEST,
PREC_LOGICAL_OR, // or
PREC_LOGICAL_AND, // and
PREC_LOGICAL_NOT, // not
PREC_EQUALITY, // == !=
PREC_IN, // in
PREC_IS, // is
PREC_TEST, // in is
PREC_COMPARISION, // < > <= >=
PREC_BITWISE_OR, // |
PREC_BITWISE_XOR, // ^
@ -230,7 +228,7 @@ typedef enum {
PREC_RANGE, // ..
PREC_TERM, // + -
PREC_FACTOR, // * / %
PREC_UNARY, // - ! ~
PREC_UNARY, // - ! ~ not
PREC_CHAIN_CALL, // ->
PREC_CALL, // ()
PREC_SUBSCRIPT, // []
@ -1192,10 +1190,10 @@ GrammarRule rules[] = { // Prefix Infix Infix Precedence
/* TK_FUNC */ { exprFunc, NULL, NO_INFIX },
/* TK_END */ NO_RULE,
/* TK_NULL */ { exprValue, NULL, NO_INFIX },
/* TK_IN */ { NULL, exprBinaryOp, PREC_IN },
/* TK_IN */ { NULL, exprBinaryOp, PREC_TEST },
/* TK_AND */ { NULL, exprAnd, PREC_LOGICAL_AND },
/* TK_OR */ { NULL, exprOr, PREC_LOGICAL_OR },
/* TK_NOT */ { exprUnaryOp, NULL, PREC_LOGICAL_NOT },
/* TK_NOT */ { exprUnaryOp, NULL, PREC_UNARY },
/* TK_TRUE */ { exprValue, NULL, NO_INFIX },
/* TK_FALSE */ { exprValue, NULL, NO_INFIX },
/* TK_DO */ NO_RULE,

View File

@ -1243,9 +1243,7 @@ Var varBitRshift(PKVM* vm, Var v1, Var v2) {
Var varBitNot(PKVM* vm, Var v) {
int64_t i;
if (!validateInteger(vm, v, &i, "Unary operand")) return VAR_NULL;
return VAR_NUM((double)(~i));
}
@ -1274,6 +1272,48 @@ bool varLesser(Var v1, Var v2) {
#undef RIGHT_OPERAND
#undef UNSUPPORTED_OPERAND_TYPES
bool varContains(PKVM* vm, Var elem, Var container) {
if (!IS_OBJ(container)) {
VM_SET_ERROR(vm, stringFormat(vm, "'$' is not iterable.",
varTypeName(container)));
}
Object* obj = AS_OBJ(container);
switch (obj->type) {
case OBJ_STRING: {
if (!IS_OBJ_TYPE(elem, OBJ_STRING)) {
VM_SET_ERROR(vm, stringFormat(vm, "Expected a string operand."));
return false;
}
String* sub = (String*)AS_OBJ(elem);
String* str = (String*)AS_OBJ(container);
if (sub->length > str->length) return false;
TODO;
} break;
case OBJ_LIST: {
List* list = (List*)AS_OBJ(container);
for (uint32_t i = 0; i < list->elements.count; i++) {
if (isValuesEqual(elem, list->elements.data[i])) return true;
}
return false;
} break;
case OBJ_MAP:
case OBJ_RANGE:
case OBJ_SCRIPT:
case OBJ_FUNC:
case OBJ_FIBER:
case OBJ_CLASS:
case OBJ_INST:
TODO;
}
}
// Here we're switching the FNV-1a hash value of the name (cstring). Which is
// an efficient way than having multiple if (attrib == "name"). From O(n) * k
// to O(1) where n is the length of the string and k is the number of string

View File

@ -46,6 +46,9 @@ Var varBitNot(PKVM* vm, Var v); // Returns ~v.
bool varGreater(Var v1, Var v2); // Returns v1 > v2.
bool varLesser(Var v1, Var v2); // Returns v1 < v2.
// Returns elem in container.
bool varContains(PKVM* vm, Var elem, Var container);
// Returns the attribute named [attrib] on the variable [on].
Var varGetAttrib(PKVM* vm, Var on, String* attrib);

View File

@ -1477,9 +1477,15 @@ static PkResult runFiber(PKVM* vm, Fiber* fiber) {
}
OPCODE(IN):
// TODO: Implement bool varContaines(vm, on, value);
TODO;
UNREACHABLE();
{
// Don't pop yet, we need the reference for gc.
Var container = PEEK(-1), elem = PEEK(-2);
bool contains = varContains(vm, elem, container);
DROP(); DROP(); // container, elem
PUSH(VAR_BOOL(contains));
CHECK_ERROR();
DISPATCH();
}
OPCODE(REPL_PRINT):
{

View File

@ -27,6 +27,11 @@ l1 = [1] + []; assert(l1.length == 1); assert(l1[0] == 1)
l2 = l1 + [1,2,3]; assert(l2.length == 4); assert(l2 == [1,1,2,3])
l3 = l2 + l1 + l2; assert(l3 == [1,1,2,3,1,1,1,2,3])
## in tests.
assert(!('abc' in 'a'))
assert(42 in [12, 42, 3.14])
assert(!('a' in ['abc']))
## Builtin functions tests.
assert(to_string(42) == '42')