token checkTypeInSymbolTable(char* name,int lineNum, int charNum) { STable entry = stList->table; STList readList = stList; if(entry->data == NULL) { if(readList->parentList == NULL) { typeError(2,name,lineNum,charNum); return INVALID; } entry = readList->parentList->table; readList = readList->parentList; } while(strcmp(entry->data->value,name)) { entry = entry->nextEntry; if(entry->data == NULL) { // All entries in current scope over. Check above scope. if(readList->parentList == NULL) { typeError(2,name,lineNum,charNum); entry = NULL; return INVALID; } entry = readList->parentList->table; readList = readList->parentList; } } return convertToType(entry->data->type); }
int referInsert(TreeNode *t, ErrorObj errObj) { if (st_lookup(t->attr.name) == -1) { /* not yet in table, variable using without definition error */ switch(errObj) { case TYPE: typeError(t, "Type not defined"); break; case VAR: typeError(t, "Variable not defined"); break; case FUNC: typeError(t, "Function not defined"); break; default: typeError(t, "Unknown not defined error"); break; } return -1; } else { /* already in table, so ignore location, add line number of use only */ st_insert(t->attr.name, NULL, t->lineno, 0); return 0; } }
bool RegExpObject::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow) { VM& vm = exec->vm(); auto scope = DECLARE_THROW_SCOPE(vm); if (propertyName == vm.propertyNames->lastIndex) { RegExpObject* regExp = asRegExpObject(object); if (descriptor.configurablePresent() && descriptor.configurable()) return typeError(exec, scope, shouldThrow, ASCIILiteral(UnconfigurablePropertyChangeConfigurabilityError)); if (descriptor.enumerablePresent() && descriptor.enumerable()) return typeError(exec, scope, shouldThrow, ASCIILiteral(UnconfigurablePropertyChangeEnumerabilityError)); if (descriptor.isAccessorDescriptor()) return typeError(exec, scope, shouldThrow, ASCIILiteral(UnconfigurablePropertyChangeAccessMechanismError)); if (!regExp->m_lastIndexIsWritable) { if (descriptor.writablePresent() && descriptor.writable()) return typeError(exec, scope, shouldThrow, ASCIILiteral(UnconfigurablePropertyChangeWritabilityError)); if (!sameValue(exec, regExp->getLastIndex(), descriptor.value())) return typeError(exec, scope, shouldThrow, ASCIILiteral(ReadonlyPropertyChangeError)); return true; } if (descriptor.value()) { regExp->setLastIndex(exec, descriptor.value(), false); RETURN_IF_EXCEPTION(scope, false); } if (descriptor.writablePresent() && !descriptor.writable()) regExp->m_lastIndexIsWritable = false; return true; } scope.release(); return Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow); }
static Value* eval_map(Context* ctx, ArgList* arglist) { if(arglist->count != 2) { return ValErr(builtinArgs("map", 2, arglist->count)); } Value* func = Value_copy(arglist->args[0]); if(func->type != VAL_VAR) { Value* val = Value_eval(func, ctx); Value_free(func); if(val->type == VAL_ERR) return val; if(val->type != VAL_VAR) { Value_free(val); return ValErr(typeError("Builtin 'map' expects a callable as its first argument.")); } func = val; } Value* vec = Value_eval(arglist->args[1], ctx); if(vec->type == VAL_ERR) { Value_free(func); return vec; } if(func->type != VAL_VAR) { Value_free(func); Value_free(vec); return ValErr(typeError("Builtin 'map' expects a callable as its first argument.")); } if(vec->type != VAL_VEC) { Value_free(func); Value_free(vec); return ValErr(typeError("Builtin 'map' expects a vector as its second argument.")); } ArgList* mapping = ArgList_new(vec->vec->vals->count); /* Don't evaluate the call now. Let Builtin_eval do this for us */ unsigned i; for(i = 0; i < mapping->count; i++) { ArgList* arg = ArgList_create(1, Value_copy(vec->vec->vals->args[i])); Value* call = ValCall(FuncCall_new(func->name, arg)); mapping->args[i] = call; } Value_free(func); Value_free(vec); return ValVec(Vector_new(mapping)); }
/* // Check the size expression in assignment type stmt // and report any type errors appropriately. */ void checkSizeExpression(token type, astTree nodes) { astTree childID = nodes->childNode->childNode; char* idName = childID->data.token_data; token typeOfSize = checkTypeInSymbolTable(idName,childID->data.lineNumber,childID->data.charNumber); if(typeOfSize != STR) { typeError(0,idName,childID->data.lineNumber,childID->data.charNumber); } else { if(type != NUM) typeError(1,idName,childID->data.lineNumber,childID->data.charNumber); } }
// ECMA 8.7.2 bool JSValue::putToPrimitive(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) { VM& vm = exec->vm(); auto scope = DECLARE_THROW_SCOPE(vm); if (std::optional<uint32_t> index = parseIndex(propertyName)) return putToPrimitiveByIndex(exec, index.value(), value, slot.isStrictMode()); // Check if there are any setters or getters in the prototype chain JSObject* obj = synthesizePrototype(exec); if (UNLIKELY(!obj)) return false; JSValue prototype; if (propertyName != vm.propertyNames->underscoreProto) { for (; !obj->structure()->hasReadOnlyOrGetterSetterPropertiesExcludingProto(); obj = asObject(prototype)) { prototype = obj->getPrototypeDirect(); if (prototype.isNull()) return typeError(exec, scope, slot.isStrictMode(), ASCIILiteral(ReadonlyPropertyWriteError)); } } for (; ; obj = asObject(prototype)) { unsigned attributes; PropertyOffset offset = obj->structure()->get(vm, propertyName, attributes); if (offset != invalidOffset) { if (attributes & ReadOnly) return typeError(exec, scope, slot.isStrictMode(), ASCIILiteral(ReadonlyPropertyWriteError)); JSValue gs = obj->getDirect(offset); if (gs.isGetterSetter()) return callSetter(exec, *this, gs, value, slot.isStrictMode() ? StrictMode : NotStrictMode); if (gs.isCustomGetterSetter()) return callCustomSetter(exec, gs, attributes & CustomAccessor, obj, slot.thisValue(), value); // If there's an existing property on the object or one of its // prototypes it should be replaced, so break here. break; } prototype = obj->getPrototype(vm, exec); RETURN_IF_EXCEPTION(scope, false); if (prototype.isNull()) break; } return typeError(exec, scope, slot.isStrictMode(), ASCIILiteral(ReadonlyPropertyWriteError)); }
bool StringObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow) { VM& vm = exec->vm(); auto scope = DECLARE_THROW_SCOPE(vm); StringObject* thisObject = jsCast<StringObject*>(cell); if (thisObject->internalValue()->canGetIndex(propertyName)) return typeError(exec, scope, shouldThrow, ASCIILiteral(ReadonlyPropertyWriteError)); return JSObject::putByIndex(cell, exec, propertyName, value, shouldThrow); }
/* Procedure checkNode performs * type checking at a single tree node */ static void checkNode(TreeNode * t) { switch (t->nodekind) { case ExpK: switch (t->kind.exp) { case OpK: if ((t->child[0]->type != Integer) || (t->child[1]->type != Integer)) typeError(t,"Op applied to non-integer"); if ((t->attr.op == EQ) || (t->attr.op == LT)) t->type = Boolean; else t->type = Integer; break; case ConstK: case IdK: t->type = Integer; break; default: break; } break; case StmtK: switch (t->kind.stmt) { case ForsK: if (t->child[0]->type == Integer) typeError(t->child[0],"for test is not Boolean"); break; case IfK: if (t->child[0]->type == Integer) typeError(t->child[0],"if test is not Boolean"); break; case AssignK: if (t->child[0]->type != Integer) typeError(t->child[0],"assignment of non-integer value"); break; case WriteK: if (t->child[0]->type != Integer) typeError(t->child[0],"write of non-integer value"); break; case WritelnK: if (t->child[0]->type != Integer) typeError(t->child[0],"writeln of non-integer value"); break; case RepeatK: if (t->child[1]->type == Integer) typeError(t->child[1],"repeat test is not Boolean"); break; default: break; } break; default: break; } }
Value* Expression_eval(Expression* expr, Context* ctx) { Value* ret; Variable* var = expr->var; if(var->type == VAR_VALUE) { /* Evaluate right side */ ret = Value_eval(var->val, ctx); /* If an error occurred, bail */ if(ret->type == VAL_ERR) return ret; /* Variable assignment? */ if(ret->type == VAL_VAR) { /* This means ret must be a function */ Variable* func = Variable_get(ctx, ret->name); if(func == NULL) { Value* err = ValErr(varNotFound(ret->name)); Value_free(ret); return err; } if(func->type == VAR_BUILTIN) { Value_free(ret); return ValErr(typeError("Cannot assign a variable to a builtin value.")); } if(var->name != NULL) { Context_setGlobal(ctx, var->name, Variable_copy(func)); } } else { /* This means ret must be a Value */ Value_free(var->val); var->val = Value_copy(ret); /* Update ans */ Context_setGlobal(ctx, "ans", Variable_copy(var)); /* Save the newly evaluated variable */ if(var->name != NULL) Context_setGlobal(ctx, var->name, Variable_copy(var)); } } else if(var->type == VAR_FUNC) { ret = ValVar(var->name); Context_setGlobal(ctx, var->name, Variable_copy(var)); } else { badVarType(var->type); } return ret; }
static bool getBooleanResult(const RtlFieldInfo *field, const MYSQL_BIND &bound) { if (*bound.is_null) { NullFieldProcessor p(field); return p.boolResult; } if (!isInteger(bound.buffer_type)) typeError("boolean", field); return rtlReadUInt(bound.buffer, *bound.length) != 0; }
static Value* unop_fact(const Context* ctx, const Value* a) { if(a->type != VAL_INT) { return ValErr(typeError("Factorial operand must be an integer.")); } if(a->ival > 20) { return ValErr(mathError("Factorial operand too large (%lld > 20).", a->ival)); } return ValInt(fact(a->ival)); }
void declInsert(TreeNode *t, char *varType, ErrorObj errObj) { if (st_lookup(t->attr.name) == -1) { /* not yet in table, so safely insert */ if(errObj==FUNC) { st_insert(t->attr.name, varType, t->lineno, funcAmt++); } else { st_insert(t->attr.name, varType, t->lineno, location[a_curFuncNum]++); } } else { /* already in table, redefinition error */ switch(errObj) { case TYPE: typeError(t, "Type redeclaration"); break; case VAR: typeError(t, "Variable redeclaration"); break; case FUNC: typeError(t, "Function redeclaration"); break; case CONST: typeError(t, "Constant variable redeclaration"); break; default: typeError(t, "Unknown redeclaration error"); break; } } }
static double getRealResult(const RtlFieldInfo *field, sqlite3_value *val) { assertex(val); if (isNull(val)) { NullFieldProcessor p(field); return p.doubleResult; } if (sqlite3_value_type(val) != SQLITE_FLOAT) typeError("real", field); return sqlite3_value_double(val); }
static unsigned __int64 getUnsignedResult(const RtlFieldInfo *field, sqlite3_value *val) { assertex(val); if (isNull(val)) { NullFieldProcessor p(field); return p.uintResult; } if (sqlite3_value_type(val) != SQLITE_INTEGER) typeError("integer", field); return (unsigned __int64) sqlite3_value_int64(val); }
static bool getBooleanResult(const RtlFieldInfo *field, sqlite3_value *val) { assertex(val); if (isNull(val)) { NullFieldProcessor p(field); return p.boolResult; } if (sqlite3_value_type(val) != SQLITE_INTEGER) typeError("boolean", field); return sqlite3_value_int64(val) != 0; }
Value* Value_copy(const Value* val) { Value* ret; switch(val->type) { case VAL_INT: ret = ValInt(val->ival); break; case VAL_REAL: ret = ValReal(val->rval); break; case VAL_FRAC: ret = ValFrac(Fraction_copy(val->frac)); break; case VAL_EXPR: ret = ValExpr(BinOp_copy(val->expr)); break; case VAL_CALL: ret = ValCall(FuncCall_copy(val->call)); break; case VAL_UNARY: ret = ValUnary(UnOp_copy(val->term)); break; case VAL_VAR: ret = ValVar(val->name); break; case VAL_VEC: ret = ValVec(Vector_copy(val->vec)); break; case VAL_NEG: /* Shouldn't be reached, but so easy to code */ ret = ValNeg(); break; case VAL_ERR: ret = ValErr(Error_copy(val->err)); break; default: typeError("Unknown value type: %d.", val->type); ret = NULL; break; } return ret; }
static void getDataResult(const RtlFieldInfo *field, const MYSQL_BIND &bound, size32_t &chars, void * &result) { if (*bound.is_null) { NullFieldProcessor p(field); rtlStrToDataX(chars, result, p.resultChars, p.stringResult); return; } if (isString(bound.buffer_type)) rtlStrToDataX(chars, result, *bound.length, bound.buffer); // This feels like it may not work to me - will preallocate rather larger than we want else typeError("blob", field); }
/** * Gets the size of a particular string from symbol table. * @param name * @param lineNum * @param charNum * @param list * @param flag * @return */ int getSize(char* name,int lineNum,int charNum,STList list,int flag) { STList readList = list; if(list->stringTable->stringName != NULL) { stringSizes strings = readList->stringTable; while(strings->stringName != NULL) { if(strcmp(strings->stringName,name)) strings = strings->nextEntry; else return strings->length; if(strings->stringName == NULL) { int length = 0; if(readList->parentList != NULL) { readList = readList->parentList; length = getSize(name,lineNum,charNum,readList,1); } if(length == 0 && flag) { if(readList->sisterList != NULL) { length = getSize(name,lineNum,charNum,readList->sisterList,1); } } if(length == 0 && !flag) { typeError(3,name,lineNum,charNum); } return length; } } } typeError(3,name,lineNum,charNum); return 0; }
/** * Checks assignmenttype2 statements for type errors. */ void checkAssignmentType2() { astTree stmtNode = currentASTNode->childNode->childNode; astTree idNodes = stmtNode; astTree rhsNodes = stmtNode->sisterNode; if(rhsNodes->ruleNum == 29) { // It is a size expression for matrix. astTree matrixNode = rhsNodes->childNode->childNode; token type = checkTypeInSymbolTable(matrixNode->data.token_data,matrixNode->data.lineNumber,matrixNode->data.charNumber); if(type == INVALID) return; if(type != MATRIX) { // It is something other than matrix. error. typeError(4,matrixNode->data.token_data,matrixNode->data.lineNumber,matrixNode->data.charNumber); } astTree idNode = idNodes->childNode->childNode; token type1 = checkTypeInSymbolTable(idNode->data.token_data,idNode->data.lineNumber,idNode->data.charNumber); if(type1 == INVALID) return; idNodes = idNodes->childNode->childNode->sisterNode; if(idNodes->ruleNum == 33) { typeError(10,idNode->data.token_data,idNode->data.lineNumber,idNode->data.charNumber); } idNode = idNodes->childNode->childNode; token type2 = checkTypeInSymbolTable(idNode->data.token_data,idNode->data.lineNumber,idNode->data.charNumber); if(type2 == INVALID) return; idNodes = idNode->sisterNode; if(!(type1 == NUM && type2 == NUM && idNodes->ruleNum == 33)) { // Either the types or not correct or there are one too many identifiers. typeError(9,idNodes->childNode->data.token_data,idNodes->childNode->data.lineNumber,idNodes->childNode->data.charNumber); } } }
static void getUnicodeResult(const RtlFieldInfo *field, const MYSQL_BIND &bound, size32_t &chars, UChar * &result) { if (*bound.is_null) { NullFieldProcessor p(field); rtlUnicodeToUnicodeX(chars, result, p.resultChars, p.unicodeResult); return; } if (bound.buffer_type != MYSQL_TYPE_STRING && bound.buffer_type != MYSQL_TYPE_VAR_STRING) typeError("string", field); const char *text = (const char *) bound.buffer; unsigned long bytes = *bound.length; unsigned numchars = rtlUtf8Length(bytes, text); // MORE - is it a good assumption that it is utf8 ? Depends how the database is configured I think rtlUtf8ToUnicodeX(chars, result, numchars, text); }
void checkCondExp(TreeNode *t, TreeNode *expNode) { switch(expNode->kind.exp) { case OpK: //variable declaration checking: getExpExpKind(expNode->child[0], NULL, 1); getExpExpKind(expNode->child[1], NULL, 1); //check wether the expression is boolean //EQ,NE,GE, GT,LE,LT,PLUS,MINUS,MUL,DIV,OR,AND,MOD,NOT switch(expNode->attr.op) { case EQ: case NE: case GE: case GT: case LE: case LT: case OR: case AND: case NOT: break; default: typeError(t, "Type of conditional expression is not boolean"); break; } break; default: typeError(t, "Type of conditional expression is not boolean"); break; } }
static void getDataResult(const RtlFieldInfo *field, sqlite3_value *val, size32_t &chars, void * &result) { assertex(val); if (isNull(val)) { NullFieldProcessor p(field); rtlStrToDataX(chars, result, p.resultChars, p.stringResult); return; } if (sqlite3_value_type(val) != SQLITE_BLOB && sqlite3_value_type(val) != SQLITE_TEXT) typeError("blob", field); const void *blob = sqlite3_value_blob(val); int bytes = sqlite3_value_bytes(val); rtlStrToDataX(chars, result, bytes, blob); }
static unsigned __int64 getUnsignedResult(const RtlFieldInfo *field, const MYSQL_BIND &bound) { if (*bound.is_null) { NullFieldProcessor p(field); return p.uintResult; } if (isDateTime(bound.buffer_type)) return getDateTimeValue(bound); if (!isInteger(bound.buffer_type)) typeError("integer", field); if (bound.is_unsigned) return rtlReadUInt(bound.buffer, *bound.length); else return (unsigned __int64) rtlReadInt(bound.buffer, *bound.length); }
size32_t CouchbaseEmbedFunctionContext::getTransformResult(ARowBuilder & rowBuilder) { execute(); auto resultrow = nextResultRowTree(); if (!resultrow) fail("Failed to read row"); if (resultrow->getCount("./*") != 1) typeError("row", ""); CouchbaseRowBuilder couchbaseRowBuilder(resultrow); const RtlTypeInfo *typeInfo = rowBuilder.queryAllocator()->queryOutputMeta()->queryTypeInfo(); assertex(typeInfo); RtlFieldStrInfo dummyField("<row>", NULL, typeInfo); return typeInfo->build(rowBuilder, 0, &dummyField, couchbaseRowBuilder); }
static void getUnicodeResult(const RtlFieldInfo *field, sqlite3_value *val, size32_t &chars, UChar * &result) { assertex(val); if (isNull(val)) { NullFieldProcessor p(field); rtlUnicodeToUnicodeX(chars, result, p.resultChars, p.unicodeResult); return; } if (sqlite3_value_type(val) != SQLITE_TEXT) typeError("string", field); const UChar *text = (const UChar *) sqlite3_value_text16(val); int bytes = sqlite3_value_bytes16(val); unsigned numchars = bytes / sizeof(UChar); rtlUnicodeToUnicodeX(chars, result, numchars, text); }
static void getUTF8Result(const RtlFieldInfo *field, sqlite3_value *val, size32_t &chars, char * &result) { assertex(val); if (isNull(val)) { NullFieldProcessor p(field); rtlUtf8ToUtf8X(chars, result, p.resultChars, p.stringResult); return; } if (sqlite3_value_type(val) != SQLITE_TEXT) typeError("string", field); const char *text = (const char *) sqlite3_value_text(val); int bytes = sqlite3_value_bytes(val); unsigned numchars = rtlUtf8Length(bytes, text); rtlUtf8ToUtf8X(chars, result, numchars, text); }
bool StringObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) { VM& vm = exec->vm(); auto scope = DECLARE_THROW_SCOPE(vm); StringObject* thisObject = jsCast<StringObject*>(cell); if (UNLIKELY(isThisValueAltered(slot, thisObject))) return ordinarySetSlow(exec, thisObject, propertyName, value, slot.thisValue(), slot.isStrictMode()); if (propertyName == vm.propertyNames->length) return typeError(exec, scope, slot.isStrictMode(), ASCIILiteral(ReadonlyPropertyWriteError)); if (Optional<uint32_t> index = parseIndex(propertyName)) return putByIndex(cell, exec, index.value(), value, slot.isStrictMode()); return JSObject::put(cell, exec, propertyName, value, slot); }
static Value* eval_dot(Context* ctx, ArgList* arglist) { if(arglist->count != 2) { /* Two vectors are required for a dot product */ return ValErr(builtinArgs("dot", 2, arglist->count)); } Value* vector1 = Value_eval(arglist->args[0], ctx); if(vector1->type == VAL_ERR) { return vector1; } Value* vector2 = Value_eval(arglist->args[1], ctx); if(vector2->type == VAL_ERR) { Value_free(vector1); return vector2; } if(vector1->type != VAL_VEC || vector2->type != VAL_VEC) { /* Both values must be vectors */ return ValErr(typeError("Builtin dot expects two vectors.")); } unsigned count = vector1->vec->vals->count; if(count != vector2->vec->vals->count) { /* Both vectors must have the same number of values */ return ValErr(mathError("Vectors must have the same dimensions for dot product.")); } Value* total = ValInt(0); // store the total value of the dot product unsigned i; for(i = 0; i < count; i++) { /* Multiply v1[i] and v2[i] */ BinOp* mul = BinOp_new(BIN_MUL, Value_copy(vector1->vec->vals->args[i]), Value_copy(vector2->vec->vals->args[i])); Value* part = BinOp_eval(mul, ctx); BinOp_free(mul); /* Accumulate the sum for all products */ BinOp* add = BinOp_new(BIN_ADD, part, total); total = BinOp_eval(add, ctx); BinOp_free(add); } return total; }
bool JSValue::putToPrimitiveByIndex(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow) { VM& vm = exec->vm(); auto scope = DECLARE_THROW_SCOPE(vm); if (propertyName > MAX_ARRAY_INDEX) { PutPropertySlot slot(*this, shouldThrow); return putToPrimitive(exec, Identifier::from(exec, propertyName), value, slot); } JSObject* prototype = synthesizePrototype(exec); if (UNLIKELY(!prototype)) { ASSERT(scope.exception()); return false; } bool putResult = false; if (prototype->attemptToInterceptPutByIndexOnHoleForPrototype(exec, *this, propertyName, value, shouldThrow, putResult)) return putResult; return typeError(exec, scope, shouldThrow, ASCIILiteral(ReadonlyPropertyWriteError)); }
const char * CouchbaseEmbedFunctionContext::nextResultScalar() { auto resultrow = nextResultRowIterator(); if (resultrow) { resultrow->first(); if(resultrow->isValid() == true) { if (resultrow->query().hasChildren()) typeError("scalar", ""); return resultrow->query().queryProp(""); } else failx("Could not fetch next result column."); } else failx("Could not fetch next result row."); return nullptr; }