static bool runFunctionCall(ASTNode* node, MemoryStack* stack, Scope* scope, RuntimeError* error, Value* result) { assert(node->nodeType == AST_FUNCTION_CALL); bool stillWorking = true; // TODO: change this to temporary memory? Scope identifierScope = makeScope(nullptr); FunctionIdentifier identifier = {}; if (calcFunctionIdentifier(scope, &identifierScope, stack, error, node, &identifier)) { Function* funcToCall = getFunction(scope, identifier); if (funcToCall) { Scope functionScope = makeScope(scope); ListIterator<ASTNode> iterator = makeIterator(&node->functionCall.arguments); ListIterator<Argument> iterator2 = makeIterator(&funcToCall->identifier.arguments); while (stillWorking && hasNext(&iterator)) { ASTNode* node = getNext(&iterator); Argument* argFunctionRecieves = getNext(&iterator2); Variable* var = defineAVariable(argFunctionRecieves->identifier, argFunctionRecieves->type, stack, &functionScope); stillWorking = runExpression(node, stack, scope, error, &var->value); } if (stillWorking) { assert(!hasNext(&iterator) && !hasNext(&iterator2)); if (funcToCall->type == FT_INTERNAL) stillWorking = runStatement(funcToCall->body, stack, &functionScope, error); else funcToCall->func(funcToCall->identifier.name, &functionScope.variables, result); // TODO: externals error checking? } scopeFreeMemory(&functionScope, stack); } else { *error = RuntimeError{ RET_UNDEFINED_FUNCTION, identifier.name, node->functionCall.lineNumber }; stillWorking = false; } } else stillWorking = false; scopeFreeMemory(&identifierScope, stack); return stillWorking; }
static bool operator==(FunctionIdentifier left, FunctionIdentifier right) { bool argumentsEquality = true; ListIterator<Argument> leftIterator = makeIterator(&left.arguments); ListIterator<Argument> rightIterator = makeIterator(&right.arguments); while (hasNext(&leftIterator) && hasNext(&rightIterator)) { // checks only definitions. Reference types CAN be assigned to a non reference value. // Reference only mean that the memory of a 'Value' belongs to another 'Value' and shouldn't be freed if (getNext(&leftIterator)->type.definition != getNext(&rightIterator)->type.definition) { argumentsEquality = false; break; } } argumentsEquality = argumentsEquality && (!hasNext(&leftIterator) && !hasNext(&rightIterator)); return (left.name == right.name) && argumentsEquality; }
static bool calcFunctionIdentifier(Scope* mainScope, Scope* tmpScope, MemoryStack* stack, RuntimeError* error, ASTNode* node, FunctionIdentifier* result) { assert(node->nodeType == AST_FUNCTION_CALL); result->name = node->functionCall.identifier; result->arguments = {}; bool stillWorking = true; ListIterator<ASTNode> args = makeIterator(&node->functionCall.arguments); while (stillWorking && hasNext(&args)) { ASTNode* node = getNext(&args); Argument* arg = scopePushToList<Argument>(tmpScope, stack, &result->arguments); arg->identifier = {}; if (node->nodeType == AST_EXPRESSION_CONSTANT) { arg->type = Type{ getTypeDefinition(mainScope, makeSlice("s32")), false }; } else if (node->nodeType == AST_EXPRESSION_IDENTIFIER || node->nodeType == AST_EXPRESSION_DOT) { Value value; if (getValue(mainScope, node, error, &value)) { arg->type = value.type; } else { stillWorking = false; } } else if (node->nodeType == AST_FUNCTION_CALL) { FunctionIdentifier identifier = { }; if (calcFunctionIdentifier(mainScope, tmpScope, stack, error, node, &identifier)) { Function* func = getFunction(mainScope, identifier); if (func) arg->type = func->returnType; else { *error = RuntimeError{ RET_UNDEFINED_FUNCTION, identifier.name, node->functionCall.lineNumber }; stillWorking = false; } } else stillWorking = false; } } return stillWorking; }
static bool runStatements(LinkedList<ASTNode>* statements, MemoryStack* stack, Scope* scope, RuntimeError* error) { bool stillWorking = true; ListIterator<ASTNode> iterator = makeIterator(statements); while (stillWorking && hasNext(&iterator)) { stillWorking = runStatement(getNext(&iterator), stack, scope, error); } return stillWorking; }
String ScriptCollectionBase::toCode() const { String ret = _("["); bool first = true; ScriptValueP it = makeIterator(); while (ScriptValueP v = it->next()) { if (!first) ret += _(","); first = false; // todo: include keys ret += v->toCode(); } ret += _("]"); return ret; }
std::unique_ptr<TransactionHistoryIteratorBase> OplogInterfaceMock::makeTransactionHistoryIterator( const OpTime& startOpTime) const { return std::make_unique<TransactionHistoryIteratorMock>(startOpTime, makeIterator()); }
bool run(ASTNode* mainNode, RuntimeError* error, ExternalFunctions externals, char** libsToLoad, int libsCount) { assert(mainNode->nodeType == AST_MAIN); getValueFunc = getGetValueFuncPtr(); MemoryStack stack = makeMemoryStack(MEGABYTE(16)); Array<HINSTANCE> libraries = makeArray<HINSTANCE>(KILOBYTE(1)); Scope scalarTypesScope = makeScope(nullptr); Scope globalScope = makeScope(&scalarTypesScope); pushType(&scalarTypesScope, &stack, TypeDefinition{ makeSlice("s64"), {}, 8 }); pushType(&scalarTypesScope, &stack, TypeDefinition{ makeSlice("u64"), {}, 8 }); pushType(&scalarTypesScope, &stack, TypeDefinition{ makeSlice("f64"), {}, 8 }); pushType(&scalarTypesScope, &stack, TypeDefinition{ makeSlice("s32"), {}, 4 }); pushType(&scalarTypesScope, &stack, TypeDefinition{ makeSlice("u32"), {}, 4 }); pushType(&scalarTypesScope, &stack, TypeDefinition{ makeSlice("f32"), {}, 4 }); pushType(&scalarTypesScope, &stack, TypeDefinition{ makeSlice("s16"), {}, 2 }); pushType(&scalarTypesScope, &stack, TypeDefinition{ makeSlice("u16"), {}, 2 }); pushType(&scalarTypesScope, &stack, TypeDefinition{ makeSlice("s8"), {}, 1 }); pushType(&scalarTypesScope, &stack, TypeDefinition{ makeSlice("u8"), {}, 1 }); ExternalArgumentDefinition binarys32Args[] = { { "a", "s32" }, { "b", "s32" } }; ExternalArgumentDefinition binaryf32Args[] = { { "a", "f32" }, { "b", "f32" } }; ExternalDefinition buildInExternals[] = { { &scalarS32FuncsHandler, "opAdd", "s32", binarys32Args, ArrayCount(binarys32Args) }, { &scalarS32FuncsHandler, "opSub", "s32", binarys32Args, ArrayCount(binarys32Args) }, { &scalarS32FuncsHandler, "opEqualsOrLess", "s32", binarys32Args, ArrayCount(binarys32Args) }, { &scalarS32FuncsHandler, "opEqualsOrsGreater", "s32", binarys32Args, ArrayCount(binarys32Args) }, { &scalarS32FuncsHandler, "opLess", "s32", binarys32Args, ArrayCount(binarys32Args) }, { &scalarS32FuncsHandler, "opGreater", "s32", binarys32Args, ArrayCount(binarys32Args) }, { &scalarS32FuncsHandler, "opEquals", "s32", binarys32Args, ArrayCount(binarys32Args) }, { &scalarS32FuncsHandler, "opNot", "s32", binarys32Args, ArrayCount(binarys32Args) }, }; loadExternals(&scalarTypesScope, &stack, ExternalFunctions{ buildInExternals, ArrayCount(buildInExternals) }); loadExternals(&scalarTypesScope, &stack, externals); loadLibrariries(&libraries, &scalarTypesScope, &stack, libsToLoad, libsCount); bool stillWorking = true; // load all global function and type definitions ListIterator<ASTNode> iterator = makeIterator(&mainNode->main.statements); while (stillWorking && hasNext(&iterator)) { ASTNode* statement = getNext(&iterator); if (statement->nodeType == AST_STATEMENT_FUNCTION_DEFINITION || statement->nodeType == AST_STATEMENT_TYPE_DEFINITION) stillWorking = runStatement(statement, &stack, &globalScope, error); else { // TODO: illigal statement exception? Or do this on parsing stage? } } if (stillWorking) { FunctionIdentifier mainIdentifier = {}; mainIdentifier.name = makeSlice("main"); Function* func = getFunction(&globalScope, mainIdentifier); if (func != nullptr) stillWorking = runStatement(func->body, &stack, &globalScope, error); else { stillWorking = false; *error = RuntimeError{ RET_UNDEFINED_FUNCTION, mainIdentifier.name, 0 }; } } scopeFreeMemory(&globalScope, &stack); scopeFreeMemory(&scalarTypesScope, &stack); freeAllLibraries(&libraries); freeArray(&libraries); freeMemoryStack(&stack); return stillWorking; }
PropInfo * SimplePropStore::partialGet(FastEnvironment * f,const proposition * prop) const { return records.partialGet(makeIterator(f,prop->args->begin()), makeIterator(f,prop->args->end())); };
static bool runStatement(ASTNode* node, MemoryStack* stack, Scope* scope, RuntimeError* error) { switch (node->nodeType) { case AST_STATEMENT_TYPE_DEFINITION: { if (getTypeDefinition(scope, node->typeDefinition.identifier, false)) { *error = RuntimeError{ RET_TYPE_ALREADY_DEFINED, node->typeDefinition.identifier, node->typeDefinition.lineNumber }; return false; } else { TypeDefinition* typeDef = scopePushToList(scope, stack, &scope->types); typeDef->identifier = node->typeDefinition.identifier; typeDef->members = {}; ListIterator<ASTNode> iterator = makeIterator(&node->typeDefinition.definitions); int currOffsetInBytes = 0; while (hasNext(&iterator)) { ASTNode* node = getNext(&iterator); StructMember* member = scopePushToList(scope, stack, &typeDef->members); member->identifier = node->variableDeclaration.identifier; member->type = makeType(scope, node->variableDeclaration.typeIdentifier); member->offsetInBytes = currOffsetInBytes; currOffsetInBytes += member->type.definition->totalSizeInBytes; } typeDef->totalSizeInBytes = currOffsetInBytes; return true; } } break; case AST_STATEMENT_VARIABLE_DECLARATION: { if (getVariable(scope, node->variableDeclaration.identifier, false)) { *error = RuntimeError{ RET_VARIABLE_ALREADY_DEFINED, node->variableDeclaration.identifier, node->variableDeclaration.lineNumber }; return false; } else { Variable* var = defineAVariable( node->variableDeclaration.identifier, makeType(scope, node->variableDeclaration.typeIdentifier), stack, scope); if (node->variableDeclaration.expression) return runExpression(node->variableDeclaration.expression, stack, scope, error, &var->value); else return true; // TODO: set default value } } break; case AST_STATEMENT_FUNCTION_DEFINITION: { Function func; func.type = FT_INTERNAL; func.identifier.name = node->functionDefinition.identifier; func.identifier.arguments = {}; bool stillWorking = true; if (!node->functionDefinition.returnType) func.returnType = Type{ nullptr, 0 }; else { func.returnType = makeType(scope, node->functionDefinition.returnType); if (!func.returnType.definition) { *error = RuntimeError{ RET_UNDEFINED_TYPE, node->functionDefinition.returnType->typeIdentifier.name, node->functionDefinition.lineNumber }; stillWorking = false; } } ListIterator<ASTNode> args = makeIterator(&node->functionDefinition.arguments); while (stillWorking && hasNext(&args)) { ASTNode* arg = getNext(&args); Argument* argument = scopePushToList(scope, stack, &func.identifier.arguments); argument->identifier = arg->variableDeclaration.identifier; argument->type = makeType(scope, arg->variableDeclaration.typeIdentifier); if (!argument->type.definition) { *error = RuntimeError{ RET_UNDEFINED_TYPE, arg->variableDeclaration.typeIdentifier->typeIdentifier.name, arg->variableDeclaration.lineNumber }; stillWorking = false; } } func.body = node->functionDefinition.body; Function* hasFunc = getFunction(scope, func.identifier, false); if (hasFunc) { *error = RuntimeError{ RET_FUNCTION_ALREADY_DEFINED, node->functionDefinition.identifier, node->functionDefinition.lineNumber }; stillWorking = false; } else { *scopePushToList(scope, stack, &scope->functions) = func; } return stillWorking; } break; case AST_STATEMENT_IF: { Scope ifScope = makeScope(scope); Value conditionResult = pushValue(&ifScope, stack, Type{ getTypeDefinition(scope, makeSlice("s32")), false }); bool stillWorking = runExpression(node->ifStatement.condition, stack, scope, error, &conditionResult); if (stillWorking) { if (*(int*)conditionResult.memory != 0) { stillWorking = runStatement(node->ifStatement.ifCase, stack, &ifScope, error); } else if (node->ifStatement.elseCase != nullptr) { stillWorking = runStatement(node->ifStatement.elseCase, stack, &ifScope, error); } } scopeFreeMemory(&ifScope, stack); return stillWorking; } break; case AST_STATEMENT_WHILE: { Scope whileScope = makeScope(scope); Value conditionResult = pushValue(&whileScope, stack, Type{ getTypeDefinition(scope, makeSlice("s32")), false }); bool stillWorking = runExpression(node->whileStatement.condition, stack, scope, error, &conditionResult); if (stillWorking) { while (*(int*)conditionResult.memory != 0) { if (!(stillWorking = runStatement(node->whileStatement.body, stack, &whileScope, error))) break; if (!(stillWorking = runExpression(node->whileStatement.condition, stack, scope, error, &conditionResult))) break; } } scopeFreeMemory(&whileScope, stack); return stillWorking; } break; case AST_STATEMENT_ASSIGNMENT: { Value value; if (getValue(scope, node->assignment.lValue, error, &value)) { return runExpression(node->assignment.expression, stack, scope, error, &value); } else return false; } break; case AST_STATEMENTS_BLOCK: { Scope blockScope = makeScope(scope); bool result = runStatements(&node->statementsBlock.statements, stack, &blockScope, error); scopeFreeMemory(&blockScope, stack); return result; } break; case AST_FUNCTION_CALL: { return runFunctionCall(node, stack, scope, error, nullptr); } break; default: { assert(!"this is not a statement!"); return false; } break; } }