mirror of
https://github.com/zekexiao/pocketlang.git
synced 2025-02-05 20:26:53 +08:00
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:
parent
000f4c4fe4
commit
64bf27674a
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
12
src/pk_vm.c
12
src/pk_vm.c
@ -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):
|
||||
{
|
||||
|
@ -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')
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user