29 const std::shared_ptr<yoi::IRModule> &irModule,
41 irModule->functionTable.put(L
"yoimiya_glob_initializer", globInitializer);
53 for (
auto &stmt :
module->stmts) {
114 }
catch (std::out_of_range &e) {
118 auto index = irModule->globalVariables.getIndex(
id);
119 auto valType = irModule->globalVariables[index];
127 }
catch (std::out_of_range &e) {
135 case primary::primaryKind::memberExpr:
138 case primary::primaryKind::basicLiterals:
141 case primary::primaryKind::rExpr:
144 case primary::primaryKind::typeIdExpression: {
148 case primary::primaryKind::dynCastExpression: {
152 case primary::primaryKind::newExpression: {
156 case primary::primaryKind::lambdaExpr: {
157 auto lambdaStructIndex = createLambdaUnnamedStruct(
primary->
lambda);
158 auto [lambdaCallableIndex, callableInterface] =
159 createCallableImplementationForLambda(irModule->structTable[lambdaStructIndex], lambdaStructIndex, currentModuleIndex);
164 case primary::primaryKind::funcExpr: {
168 case primary::primaryKind::bracedInitalizerList: {
189 yoi_assert(rhs.type == IRValueType::valueType::interfaceObject,
192 "RHS of 'impl' operator must be an interface type");
193 auto interfaceImplName = getInterfaceImplName({rhs.typeAffiliateModule, rhs.typeIndex}, lhs);
197 ->getImportedModule(lhs->typeAffiliateModule)
198 ->interfaceImplementationTable.contains(interfaceImplName)) {
204 yoi_assert(lhs->type == IRValueType::valueType::interfaceObject,
207 "LHS of 'interfaceof' operator must be an interface type");
209 auto key = std::make_tuple(rhs.type, rhs.typeAffiliateModule, rhs.typeIndex);
212 if (std::find(
vec.begin(),
vec.end(), key) !=
vec.end()) {
237 case lexer::token::tokenKind::incrementSign: {
241 if (lhs->isBasicType()) {
244 handleUnaryOperatorOverload(L
"operator++");
248 case lexer::token::tokenKind::decrementSign: {
251 if (lhs->isBasicType()) {
254 handleUnaryOperatorOverload(L
"operator--");
258 case lexer::token::tokenKind::binaryNot: {
261 if (lhs->isBasicType()) {
264 handleUnaryOperatorOverload(L
"operator~");
268 case lexer::token::tokenKind::minus: {
270 if (lhs->isBasicType()) {
273 handleUnaryOperatorOverload(L
"operator-");
277 case lexer::token::tokenKind::unknown: {
291 case lexer::token::tokenKind::assignSign: {
297 case lexer::token::tokenKind::directAssignSign: {
308 case lexer::token::tokenKind::additionAssignment: {
315 if (lhs->isBasicType() && rhs->isBasicType()) {
322 handleBinaryOperatorOverload(L
"operator+=",
leftExpr->
rhs);
326 case lexer::token::tokenKind::subtractionAssignment: {
332 if (lhs->isBasicType() && rhs->isBasicType()) {
339 handleBinaryOperatorOverload(L
"operator-=",
leftExpr->
rhs);
343 case lexer::token::tokenKind::multiplicationAssignment: {
349 if (lhs->isBasicType() && rhs->isBasicType()) {
356 handleBinaryOperatorOverload(L
"operator*=",
leftExpr->
rhs);
360 case lexer::token::tokenKind::divisionAssignment: {
366 if (lhs->isBasicType() && rhs->isBasicType()) {
373 handleBinaryOperatorOverload(L
"operator/=",
leftExpr->
rhs);
393 auto lhsPos = visit(*term);
396 auto rhsPos = visit(*++term);
400 if (lhsType->isBasicType() && rhsType->isBasicType()) {
402 case lexer::token::tokenKind::asterisk:
403 emitBasicCastInBasicArithOpByLhsAndRhs(lhsPos, rhsPos);
406 case lexer::token::tokenKind::slash:
407 emitBasicCastInBasicArithOpByLhsAndRhs(lhsPos, rhsPos);
410 case lexer::token::tokenKind::percentSign:
414 panic(op->line, op->col,
"Unexpected multiplication expression operator");
419 case lexer::token::tokenKind::asterisk:
420 handleBinaryOperatorOverload(L
"operator*", *term);
422 case lexer::token::tokenKind::slash:
423 handleBinaryOperatorOverload(L
"operator/", *term);
425 case lexer::token::tokenKind::percentSign:
426 handleBinaryOperatorOverload(L
"operator%", *term);
429 panic(op->line, op->col,
"Unexpected multiplication expression operator");
441 auto lhsPos = visit(*term);
444 auto rhsPos = visit(*++term);
448 if (lhsType->isBasicType() && rhsType->isBasicType()) {
450 case lexer::token::tokenKind::plus:
451 emitBasicCastInBasicArithOpByLhsAndRhs(lhsPos, rhsPos);
454 case lexer::token::tokenKind::minus:
455 emitBasicCastInBasicArithOpByLhsAndRhs(lhsPos, rhsPos);
459 panic(op->line, op->col,
"Unexpected addition expression operator");
464 case lexer::token::tokenKind::plus:
465 handleBinaryOperatorOverload(L
"operator+", *term);
467 case lexer::token::tokenKind::minus:
468 handleBinaryOperatorOverload(L
"operator-", *term);
471 panic(op->line, op->col,
"Unexpected addition expression operator");
495 if (lhsType->isBasicType() && rhsType->type == IRValueType::valueType::integerObject) {
497 case lexer::token::tokenKind::binaryShiftLeft:
500 case lexer::token::tokenKind::binaryShiftRight:
504 panic(op->line, op->col,
"Unexpected shift expression operator");
510 case lexer::token::tokenKind::binaryShiftLeft:
511 handleBinaryOperatorOverload(L
"operator<<", *term);
513 case lexer::token::tokenKind::binaryShiftRight:
514 handleBinaryOperatorOverload(L
"operator>>", *term);
517 panic(op->line, op->col,
"Unexpected shift expression operator");
528 auto lhsPos = visit(*term);
531 auto rhsPos = visit(*++term);
535 if (lhsType->isBasicType() && rhsType->isBasicType()) {
537 case lexer::token::tokenKind::lessThan:
538 emitBasicCastInBasicArithOpByLhsAndRhs(lhsPos, rhsPos);
541 case lexer::token::tokenKind::greaterThan:
542 emitBasicCastInBasicArithOpByLhsAndRhs(lhsPos, rhsPos);
545 case lexer::token::tokenKind::lessEqual:
546 emitBasicCastInBasicArithOpByLhsAndRhs(lhsPos, rhsPos);
549 case lexer::token::tokenKind::greaterEqual:
550 emitBasicCastInBasicArithOpByLhsAndRhs(lhsPos, rhsPos);
554 panic(op->line, op->col,
"Unexpected relational expression operator");
559 case lexer::token::tokenKind::lessThan:
560 handleBinaryOperatorOverload(L
"operator<", *term);
562 case lexer::token::tokenKind::greaterThan:
563 handleBinaryOperatorOverload(L
"operator>", *term);
565 case lexer::token::tokenKind::lessEqual:
566 handleBinaryOperatorOverload(L
"operator<=", *term);
568 case lexer::token::tokenKind::greaterEqual:
569 handleBinaryOperatorOverload(L
"operator>=", *term);
572 panic(op->line, op->col,
"Unexpected relational expression operator");
584 auto lhsPos = visit(*term);
587 auto rhsPos = visit(*++term);
591 if (lhsType->isBasicType() && rhsType->isBasicType() || lhsType->type == IRValueType::valueType::pointerObject ||
592 rhsType->type == IRValueType::valueType::pointerObject) {
594 case lexer::token::tokenKind::equal:
595 emitBasicCastInBasicArithOpByLhsAndRhs(lhsPos, rhsPos);
598 case lexer::token::tokenKind::notEqual:
599 emitBasicCastInBasicArithOpByLhsAndRhs(lhsPos, rhsPos);
603 panic(op->line, op->col,
"Unexpected equality expression operator");
609 case lexer::token::tokenKind::equal:
610 handleBinaryOperatorOverload(L
"operator==", *term);
612 case lexer::token::tokenKind::notEqual:
613 handleBinaryOperatorOverload(L
"operator!=", *term);
616 panic(op->line, op->col,
"Unexpected equality expression operator");
628 auto lhsPos = visit(*term);
631 auto rhsPos = visit(*++term);
635 if (lhsType->isBasicType() && rhsType->isBasicType()) {
637 case lexer::token::tokenKind::binaryAnd: {
638 if (lhsType->isBasicType() && lhsType->type != IRValueType::valueType::integerObject) {
641 if (rhsType->isBasicType() && rhsType->type != IRValueType::valueType::integerObject) {
649 panic(op->line, op->col,
"Unexpected and expression operator");
656 case lexer::token::tokenKind::binaryAnd: {
657 handleBinaryOperatorOverload(L
"operator&", *term);
661 panic(op->line, op->col,
"Unexpected and expression operator");
675 auto lhs = visit(*term);
678 auto rhs = visit(*++term);
682 if (lhsType->isBasicType() && rhsType->isBasicType()) {
684 case lexer::token::tokenKind::binaryXor: {
685 if (lhsType->isBasicType() && lhsType->type != IRValueType::valueType::integerObject) {
688 if (rhsType->isBasicType() && rhsType->type != IRValueType::valueType::integerObject) {
696 panic(op->line, op->col,
"Unexpected exclusive expression operator");
703 case lexer::token::tokenKind::binaryXor: {
704 handleBinaryOperatorOverload(L
"operator^", *term);
708 panic(op->line, op->col,
"Unexpected exclusive expression operator");
720 auto lhs = visit(*term);
722 auto rhs = visit(*++term);
726 if (lhsType->isBasicType() && rhsType->isBasicType()) {
728 case lexer::token::tokenKind::binaryOr: {
729 if (lhsType->isBasicType() && lhsType->type != IRValueType::valueType::integerObject) {
732 if (rhsType->isBasicType() && rhsType->type != IRValueType::valueType::integerObject) {
740 panic(op->line, op->col,
"Unexpected inclusive expression operator");
746 case lexer::token::tokenKind::binaryOr: {
747 handleBinaryOperatorOverload(L
"operator|", *term);
751 panic(op->line, op->col,
"Unexpected inclusive expression operator");
774 if (termType->type != IRValueType::valueType::booleanObject) {
788 if (termType->type != IRValueType::valueType::booleanObject) {
809 auto lhs = visit(*term);
825 .
insert({IR::Opcode::jump,
826 {
IROperand{IROperand::operandType::codeBlock, exitBlock}},
831 .
insert({IR::Opcode::push_boolean,
839 case lexer::token::tokenKind::logicOr: {
840 yoi_assert(lhsType->isBasicType(), op->line, op->col,
"Not basic type for logical or");
841 if (lhsType->type != IRValueType::valueType::booleanObject) {
851 auto rhs = visit(*++term);
853 yoi_assert(rhsType->isBasicType(), op->line, op->col,
"Not basic type for logical or");
854 if (rhsType->type != IRValueType::valueType::booleanObject) {
869 panic(op->line, op->col,
"Unexpected logical or expression operator");
888 if (!notEmitNewBlockInstruction) {
907 while (it + 1 !=
memberExpr->
getTerms().end() && (targetModule = isModuleName((*it)->id, lastModule)) != lastModule) {
909 lastModule = targetModule;
915 if ((*it)->isIdentifier() && !(*it)->id->hasTemplateArg() && (*(it + 1))->isIdentifier() && !(*(it + 1))->id->hasTemplateArg() &&
916 targetedModule->enumerationTable.contains((*it)->id->id->node.strVal)) {
918 auto v = targetedModule->enumerationTable[(*it)->id->id->node.strVal]->valueToIndexMap[(*(it + 1))->id->id->node.strVal];
921 switch (targetedModule->enumerationTable[(*it)->id->id->node.strVal]->getUnderlyingType()) {
922 case IREnumerationType::UnderlyingType::I8: {
923 op = IR::Opcode::push_character;
924 operand = {IROperand::operandType::character, (
yoi::wchar)v};
927 case IREnumerationType::UnderlyingType::I16: {
928 op = IR::Opcode::push_short;
929 operand = {IROperand::operandType::character, (short)v};
932 case IREnumerationType::UnderlyingType::I64: {
933 op = IR::Opcode::push_unsigned;
934 operand = {IROperand::operandType::unsignedInt, (
yoi::indexT)v};
942 }
catch (std::out_of_range &e) {
943 panic((*(it + 1))->getLine(),
944 (*(it + 1))->getColumn(),
952 std::shared_ptr<IRValueType> staticTypeBase{};
955 staticTypeBase =
managedPtr(parseTypeSpecExtern(*it, targetModule == -1 ? currentModuleIndex : targetModule));
957 }
catch (std::runtime_error &) {
959 }
catch (std::out_of_range &) {
963 if (staticTypeBase) {
964 auto memberNameNode = *(++it);
965 yoi_assert(!memberNameNode->getSubscript().empty() && memberNameNode->getSubscript().front()->isInvocation(),
966 memberNameNode->getLine(),
967 memberNameNode->getColumn(),
968 "Static member access must be a method call.");
969 auto &invocation = memberNameNode->getSubscript().front();
971 switch (staticTypeBase->type) {
972 case IRValueType::valueType::structObject: {
973 if (!handleInvocationExtern(
974 memberNameNode->id->getId().node.strVal, invocation->args, staticTypeBase->typeAffiliateModule, staticTypeBase,
true,
975 memberNameNode->id->hasTemplateArg() ? &memberNameNode->id->getArg() :
nullptr))
976 panic(memberNameNode->getLine(),
977 memberNameNode->getColumn(),
978 "No matching static method found for: " +
wstring2string(memberNameNode->id->getId().get().strVal));
982 case IRValueType::valueType::datastructObject: {
983 constructDataStruct(staticTypeBase->typeIndex, staticTypeBase->typeAffiliateModule, invocation->args);
987 panic(memberNameNode->getLine(),
988 memberNameNode->getColumn(),
989 "Static member access must be a method call.");
994 if (targetModule == -1) {
995 visit(*it, isStoreOp && isFinalTerm);
997 visitExtern(*it, targetModule, isStoreOp && isFinalTerm);
1008 auto currentTermNode = *it;
1017 if (currentTermNode->getSubscript().empty()) {
1019 if (objectType->isArrayType() || objectType->isDynamicArrayType()) {
1020 if (currentTermNode->id->getId().get().strVal == L
"length") {
1023 panic(currentTermNode->getLine(), currentTermNode->getColumn(),
"Only 'length' member is valid on array types.");
1025 }
else if (objectType->type == IRValueType::valueType::structObject) {
1028 auto &memberName = currentTermNode->id->getId().get().strVal;
1029 bool isResolved =
false;
1031 auto nameInfo = structDef->lookupName(memberName);
1032 if (nameInfo.type != IRStructDefinition::nameInfo::nameType::field) {
1033 panic(currentTermNode->getLine(),
1034 currentTermNode->getColumn(),
1035 "Cannot access method '" +
wstring2string(memberName) +
"' as a field.");
1037 auto fieldType = structDef->fieldTypes[nameInfo.index];
1040 if (isStoreOp && isFinalTerm) {
1042 tryCastTo(fieldType);
1049 }
catch (std::out_of_range &) {
1053 if (
auto methodName = structDef->name + L
"::" + memberName; !isResolved &&
moduleContext->
getCompilerContext()->getImportedModule(objectType->typeAffiliateModule)->functionOverloadIndexies.contains(methodName)) {
1056 yoi_assert(funcIndexies.size() == 1, (*it)->getLine(), (*it)->getColumn(),
"Multiple overloads found for method: " +
wstring2string(methodName));
1058 auto impl = createCallableImplementationForFunction(funcDef, funcIndexies.front(), objectType->typeAffiliateModule,
true);
1059 createCallableInstanceForFunction(impl.first, impl.second, objectType->typeAffiliateModule,
true);
1062 yoi_assert(isResolved, currentTermNode->getLine(), currentTermNode->getColumn(),
"Member access on unknown struct fields or methods: " +
wstring2string(currentTermNode->id->getId().get().strVal));
1063 }
else if (objectType->type == IRValueType::valueType::datastructObject) {
1065 yoi_assert(structDef->fields.contains(currentTermNode->id->getId().get().strVal), currentTermNode->getLine(), currentTermNode->getColumn(),
"Member access on unknown data struct fields or methods: " +
wstring2string(currentTermNode->id->getId().get().strVal));
1066 auto fieldIndex = structDef->fields[currentTermNode->id->getId().get().strVal];
1067 if (accessors.empty()) {
1073 accessors.emplace_back(IROperand::operandType::index, fieldIndex);
1080 tryCastTo(fieldType);
1090 currentTermNode->getLine(), currentTermNode->getColumn(),
"Member access on a non-struct or non-array type is not allowed.");
1095 auto firstOp = currentTermNode->getSubscript().front();
1096 bool isMethodCall = firstOp->isInvocation();
1099 if (objectType->type == IRValueType::valueType::structObject) {
1100 bool isResolved =
false;
1102 isResolved = handleInvocationExtern(
1103 currentTermNode->id->getId().get().strVal, firstOp->args, objectType->typeAffiliateModule, objectType,
false,
1104 currentTermNode->id->hasTemplateArg() ? ¤tTermNode->id->getArg() :
nullptr);
1108 ->getImportedModule(objectType->typeAffiliateModule)
1109 ->structTable[objectType->typeIndex];
1112 auto info = structDef->lookupName(currentTermNode->id->getId().get().strVal);
1114 structDef->fieldTypes[info.index]);
1116 yoi_assert(structDef->fieldTypes[info.index]->type == IRValueType::valueType::structObject ||
1117 structDef->fieldTypes[info.index]->type == IRValueType::valueType::interfaceObject,
1118 currentTermNode->getLine(),
1119 currentTermNode->getColumn(),
1120 "Cannot invoke basic types as methods: " +
wstring2string(currentTermNode->id->getId().get().strVal));
1121 if (!handleInvocationExtern(L
"operator()",
1123 structDef->fieldTypes[info.index]->typeAffiliateModule,
1124 structDef->fieldTypes[info.index]))
1125 panic(currentTermNode->getLine(),
1126 currentTermNode->getColumn(),
1127 "No matching method found for: " +
wstring2string(currentTermNode->id->getId().get().strVal) +
1131 }
catch (std::out_of_range &) {
1136 panic(currentTermNode->getLine(),
1137 currentTermNode->getColumn(),
1138 "No matching method found for: " +
wstring2string(currentTermNode->id->getId().get().strVal));
1140 }
else if (objectType->type == IRValueType::valueType::interfaceObject) {
1142 if (!handleInvocationExtern(
1143 currentTermNode->id->getId().get().strVal, firstOp->args, objectType->typeAffiliateModule, objectType))
1144 panic(currentTermNode->getLine(),
1145 currentTermNode->getColumn(),
1146 "No matching method found for: " +
wstring2string(currentTermNode->id->getId().get().strVal));
1151 if (objectType->type == IRValueType::valueType::structObject) {
1153 ->getImportedModule(objectType->typeAffiliateModule)
1154 ->structTable[objectType->typeIndex];
1155 auto &fieldName = currentTermNode->id->getId().get().strVal;
1157 auto nameInfo = structDef->lookupName(fieldName);
1158 if (nameInfo.type != IRStructDefinition::nameInfo::nameType::field) {
1159 panic(currentTermNode->getLine(),
1160 currentTermNode->getColumn(),
1163 auto fieldType = structDef->fieldTypes[nameInfo.index];
1165 }
catch (std::out_of_range &) {
1166 panic(currentTermNode->getLine(),
1167 currentTermNode->getColumn(),
1171 panic(currentTermNode->getLine(), currentTermNode->getColumn(),
"Member access on a non-struct type is not allowed here.");
1176 auto subIt = isMethodCall ? std::next(currentTermNode->getSubscript().begin()) : currentTermNode->getSubscript().begin();
1177 for (; subIt != currentTermNode->getSubscript().end(); ++subIt) {
1179 bool isFinalOperation = isFinalTerm && (std::next(subIt) == currentTermNode->getSubscript().end());
1182 if (sub->isInvocation()) {
1185 if (!handleInvocationExtern(L
"operator()", sub->args, currentObjectType->typeAffiliateModule, currentObjectType))
1186 panic(sub->getLine(),
1188 "No matching method found for: " +
wstring2string(currentTermNode->id->getId().get().strVal) +
".operator()");
1189 }
else if (sub->isSubscript()) {
1190 if (currentObjectType->isArrayType() || currentObjectType->isDynamicArrayType()) {
1194 yoi_assert(indexType->type == IRValueType::valueType::unsignedObject,
1197 "Array/subscript index must be an integer or unsigned integer.");
1199 if (isStoreOp && isFinalOperation) {
1208 if (isFinalOperation && isStoreOp) {
1219 if (array->type == IRValueType::valueType::structObject)
1220 overload = resolveOverloadExtern(L
"operator[]",
1221 {value, array, index},
1222 array->typeAffiliateModule,
1224 ->getImportedModule(array->typeAffiliateModule)
1225 ->structTable[array->typeIndex]);
1227 yoi_assert(overload.
found(), sub->getLine(), sub->getColumn(),
"No matching overload found for operator[].");
1229 !overload.
isVariadic, sub->getLine(), sub->getColumn(),
"Variadic operator[] overloading is not supported.");
1235 tryCastTo(overload.
function->argumentTypes.back());
1247 handleBinaryOperatorOverload(L
"operator[]", sub->expr);
1266 case inCodeBlockStmt::vKind::ifStmt:
1269 case inCodeBlockStmt::vKind::whileStmt:
1272 case inCodeBlockStmt::vKind::forStmt:
1275 case inCodeBlockStmt::vKind::forEachStmt:
1278 case inCodeBlockStmt::vKind::returnStmt:
1281 case inCodeBlockStmt::vKind::continueStmt:
1284 case inCodeBlockStmt::vKind::breakStmt:
1287 case inCodeBlockStmt::vKind::letStmt:
1290 case inCodeBlockStmt::vKind::codeBlock:
1293 case inCodeBlockStmt::vKind::yieldStmt:
1296 case inCodeBlockStmt::vKind::rExpr:
1316 auto &first_term = *it;
1318 bool isType =
false;
1319 std::shared_ptr<IRValueType> baseType;
1323 }
catch (
const std::runtime_error &) {
1327 bool firstTermHandled =
false;
1330 if (isType && first_term->isSubscript()) {
1334 while (dim_it != end && (*dim_it)->isSubscript()) {
1335 yoi_assert((*dim_it)->expr->getToken().kind == lexer::token::tokenKind::integer,
1336 (*dim_it)->expr->getLine(),
1337 (*dim_it)->expr->getColumn(),
1338 "Array dimension must be an integer.");
1339 dimensions.push_back((*dim_it)->expr->getToken().basicVal.vInt);
1340 size = size * dimensions.back();
1344 if (dim_it != end && (*dim_it)->isInvocation()) {
1345 for (
auto &val : (*dim_it)->args->get()) {
1347 tryCastTo(baseType);
1358 else if (first_term->isInvocation()) {
1359 firstTermHandled =
true;
1361 auto args = first_term->args;
1362 bool resolved =
false;
1367 if (irModule->funcTemplateAsts.contains(baseName)) {
1368 auto astNode = irModule->funcTemplateAsts.at(baseName);
1369 specializeFunctionTemplate(astNode, concreteTemplateArgs, currentModuleIndex);
1373 switch (baseType->type) {
1374 case IRValueType::valueType::structObject:
1376 ->getImportedModule(baseType->typeAffiliateModule)
1377 ->structTable.getKey(baseType->typeIndex);
1379 case IRValueType::valueType::interfaceObject:
1381 ->getImportedModule(baseType->typeAffiliateModule)
1382 ->interfaceTable.getKey(baseType->typeIndex);
1387 "Cannot specialize type: except structObject or interfaceObject but got: " +
1391 }
catch (
const std::runtime_error &e) {
1394 "Could not resolve template specialization for function '" +
wstring2string(baseName) +
": \n" + e.what());
1404 bool isAccessible =
false;
1407 isAccessible =
true;
1409 }
catch (
const std::runtime_error &) {
1414 if (
structObject->type == IRValueType::valueType::structObject ||
structObject->type == IRValueType::valueType::interfaceObject) {
1415 if (!handleInvocationExtern(L
"operator()", args, currentModuleIndex,
structObject))
1427 if (irModule->structTable.contains(baseName)) {
1428 auto structIndex = irModule->structTable.getIndex(baseName);
1429 auto structType = irModule->structTable[structIndex];
1432 if (handleInvocationExtern(L
"constructor", args, currentModuleIndex, rhs)) {
1438 "Could not resolve constructor for struct '" +
wstring2string(baseName) +
"'.");
1446 if (irModule->dataStructTable.contains(baseName)) {
1447 constructDataStruct(irModule->dataStructTable.getIndex(baseName), irModule->identifier, args);
1454 resolved = handleInvocationExtern(baseName, args, currentModuleIndex);
1459 if (irModule->interfaceTable.contains(baseName)) {
1462 auto interfaceIndex = irModule->interfaceTable.getIndex(baseName);
1463 auto argTypes = evaluateArguments(args);
1467 "Interface constructor expects exactly one argument.");
1469 auto interfaceImplName = getInterfaceImplName({currentModuleIndex, interfaceIndex}, argTypes[0]);
1471 auto interfaceImplIndex = targetModule->interfaceImplementationTable.getIndex(interfaceImplName);
1473 {currentModuleIndex, interfaceIndex}, interfaceImplIndex,
true, targetModule->identifier);
1476 }
catch (
const std::out_of_range &) {
1484 if (irModule->externTable.contains(baseName)) {
1487 auto importedFunctionIndex = irModule->externTable.getIndex(baseName);
1488 yoi_assert(irModule->externTable[importedFunctionIndex]->type == IRExternEntry::externType::importedFunction,
1491 "This is not an imported function.");
1494 ->importedLibraries[irModule->externTable[importedFunctionIndex]->affiliateModule]
1495 .importedFunctionTable[irModule->externTable[importedFunctionIndex]->itemIndex];
1497 auto desiredArgTypes = importedFunc->argumentTypes;
1498 yoi_assert(desiredArgTypes.size() == args->arg.size(),
1501 "Number of arguments does not match the function signature.");
1502 for (
yoi::indexT i = 0; i < args->arg.size(); i++) {
1503 visit(args->arg[i]);
1507 irModule->externTable[importedFunctionIndex]->itemIndex,
1508 desiredArgTypes.size(),
1509 importedFunc->returnType);
1512 }
catch (
const std::out_of_range &) {
1519 if (
auto it = irModule->typeAliases.find(baseName); it != irModule->typeAliases.end()) {
1520 if (it->second.type == IRValueType::valueType::structObject) {
1522 auto structIndex = it->second.typeIndex;
1523 auto structType = targetModule->structTable[structIndex];
1526 if (handleInvocationExtern(L
"constructor", args, targetModule->identifier, rhs)) {
1532 "Could not resolve constructor for struct '" +
wstring2string(baseName) +
"'.");
1534 }
else if (it->second.type == IRValueType::valueType::interfaceObject) {
1539 auto interfaceIndex = it->second.typeIndex;
1540 auto argTypes = evaluateArguments(args);
1544 "Interface constructor expects exactly one argument.");
1546 auto interfaceImplName = getInterfaceImplName({currentModuleIndex, interfaceIndex}, argTypes[0]);
1548 auto interfaceImplIndex = targetModule->interfaceImplementationTable.getIndex(interfaceImplName);
1550 {currentModuleIndex, interfaceIndex}, interfaceImplIndex,
true, targetModule->identifier);
1553 }
catch (
const std::out_of_range &) {
1557 panic(first_term->getLine(), first_term->getColumn(),
"invalid type alias type");
1565 "'. No matching function, constructor, or template found for the given arguments.");
1573 if (firstTermHandled) {
1579 auto currentTerm = *it;
1580 bool isLastTerm = (std::next(it) == end);
1583 if (currentTerm->isSubscript()) {
1584 if (handleSubscript(it, end, isStoreOp, isLastTerm))
1588 }
else if (currentTerm->isInvocation()) {
1589 if (objectOnStackType->type == IRValueType::valueType::structObject ||
1590 objectOnStackType->type == IRValueType::valueType::interfaceObject) {
1591 if (!handleInvocationExtern(L
"operator()", currentTerm->args, currentModuleIndex, objectOnStackType))
1592 panic(currentTerm->getLine(),
1593 currentTerm->getColumn(),
1596 panic(currentTerm->getLine(), currentTerm->getColumn(),
"Cannot call operator() on non-struct object or interface object.");
1615 auto &firstTerm = *it;
1619 bool isType =
false;
1620 std::shared_ptr<IRValueType> baseType;
1624 }
catch (
const std::out_of_range &) {
1628 bool firstTermHandled =
false;
1631 if (isType && firstTerm->isSubscript()) {
1635 while (dim_it != end && (*dim_it)->isSubscript()) {
1636 yoi_assert((*dim_it)->expr->getToken().kind == lexer::token::tokenKind::integer,
1637 (*dim_it)->expr->getLine(),
1638 (*dim_it)->expr->getColumn(),
1639 "Array dimension must be an integer.");
1640 dimensions.push_back((*dim_it)->expr->getToken().basicVal.vInt);
1641 size = size * dimensions.back();
1645 if (dim_it != end && (*dim_it)->isInvocation()) {
1646 for (
auto &val : (*dim_it)->args->get()) {
1648 tryCastTo(baseType);
1659 else if (firstTerm->isInvocation()) {
1660 firstTermHandled =
true;
1662 auto args = firstTerm->args;
1663 bool resolved =
false;
1668 if (targetedModule->funcTemplateAsts.contains(baseName)) {
1669 auto astNode = targetedModule->funcTemplateAsts.at(baseName);
1670 specializeFunctionTemplate(astNode, concreteTemplateArgs, targetModule);
1674 switch (baseType->type) {
1675 case IRValueType::valueType::structObject:
1677 ->getImportedModule(baseType->typeAffiliateModule)
1678 ->structTable.getKey(baseType->typeIndex);
1680 case IRValueType::valueType::interfaceObject:
1682 ->getImportedModule(baseType->typeAffiliateModule)
1683 ->interfaceTable.getKey(baseType->typeIndex);
1688 "Cannot specialize type: except structObject or interfaceObject but got: " +
1692 }
catch (
const std::runtime_error &e) {
1695 "Could not resolve template specialization for function '" +
wstring2string(baseName) +
"'" +
": \n" + e.what() +
"\n");
1696 }
catch (
const std::out_of_range &e) {
1703 if (targetedModule->structTable.contains(baseName)) {
1706 externStructEntry = getExternEntry(targetModule, baseName);
1707 }
catch (
const std::out_of_range &) {
1711 auto targetedStruct = targetedModule->structTable[baseName];
1715 if (handleInvocationExtern(L
"constructor", args, targetModule, rhs)) {
1724 if (targetedModule->dataStructTable.contains(baseName)) {
1725 constructDataStruct(targetedModule->dataStructTable.getIndex(baseName), targetedModule->identifier, args);
1732 resolved = handleInvocationExtern(baseName, args, targetModule);
1737 if (targetedModule->interfaceTable.contains(baseName)) {
1740 auto argTypes = evaluateArguments(args);
1744 "Interface constructor expects exactly one argument.");
1748 auto externInterface = getExternEntry(targetModule, baseName);
1751 auto interfaceImplName = getInterfaceImplName({externInterface.affiliateModule, externInterface.itemIndex}, argTypes[0]);
1753 ->getImportedModule(concreteThis->typeAffiliateModule)
1754 ->interfaceImplementationTable.getIndex(interfaceImplName);
1757 concreteThis->typeAffiliateModule != currentModuleIndex,
1758 concreteThis->typeAffiliateModule);
1762 }
catch (
const std::out_of_range &e) {
1765 "Could not find matched extern interface constructor for " +
wstring2string(baseName));
1775 if (targetedModule->externTable.contains(baseName)) {
1778 auto argTypes = evaluateArguments(args);
1779 auto externEntry = targetedModule->externTable[baseName];
1782 ->importedLibraries[externEntry->affiliateModule]
1783 .importedFunctionTable[externEntry->itemIndex];
1785 externEntry->affiliateModule, externEntry->itemIndex, argTypes.size(), externFunc->returnType);
1789 }
catch (
const std::exception &) {
1796 if (
auto it = targetedModule->typeAliases.find(baseName); it != targetedModule->typeAliases.end()) {
1797 if (it->second.type == IRValueType::valueType::structObject) {
1799 auto structIndex = it->second.typeIndex;
1800 auto structType = targetModule->structTable[structIndex];
1803 if (handleInvocationExtern(L
"constructor", args, targetModule->identifier, rhs)) {
1809 "Could not resolve constructor for struct '" +
wstring2string(baseName) +
"'.");
1811 }
else if (it->second.type == IRValueType::valueType::interfaceObject) {
1816 auto interfaceIndex = it->second.typeIndex;
1817 auto argTypes = evaluateArguments(args);
1821 "Interface constructor expects exactly one argument.");
1823 auto interfaceImplName = getInterfaceImplName({currentModuleIndex, interfaceIndex}, argTypes[0]);
1825 auto interfaceImplIndex = targetModule->interfaceImplementationTable.getIndex(interfaceImplName);
1827 {currentModuleIndex, interfaceIndex}, interfaceImplIndex,
true, targetModule->identifier);
1830 }
catch (
const std::exception &) {
1834 panic(firstTerm->getLine(), firstTerm->getColumn(),
"invalid type alias type: " +
wstring2string(baseName));
1841 "Could not find extern function, struct constructor, or interface in module: " +
wstring2string(baseName));
1847 if (firstTermHandled) {
1853 auto currentTerm = *it;
1854 bool isLastTerm = (std::next(it) == end);
1857 if (currentTerm->isSubscript()) {
1858 if (handleSubscript(it, end, isStoreOp, isLastTerm))
1862 }
else if (currentTerm->isInvocation()) {
1863 if (objectOnStackType->type == IRValueType::valueType::structObject ||
1864 objectOnStackType->type == IRValueType::valueType::interfaceObject) {
1865 handleInvocationExtern(L
"operator()", currentTerm->args, currentModuleIndex, objectOnStackType);
1867 panic(currentTerm->getLine(), currentTerm->getColumn(),
"Cannot call operator() on non-struct object or interface object.");
1896 return irModule->typeAliases.at(typeName);
1897 }
catch (std::out_of_range &e) {
1901 auto typeIndex = irModule->structTable.getIndex(typeName);
1902 return IRValueType{IRValueType::valueType::structObject,
static_cast<yoi::indexT>(currentModuleIndex), typeIndex};
1903 }
catch (std::out_of_range &e) {
1907 auto typeIndex = irModule->dataStructTable.getIndex(typeName);
1908 return IRValueType{IRValueType::valueType::datastructObject,
static_cast<yoi::indexT>(currentModuleIndex), typeIndex};
1909 }
catch (std::out_of_range &e) {
1913 auto typeIndex = irModule->interfaceTable.getIndex(typeName);
1914 return IRValueType{IRValueType::valueType::interfaceObject,
static_cast<yoi::indexT>(currentModuleIndex), typeIndex};
1915 }
catch (std::out_of_range &e) {
1919 auto incompleteType = getIncompleteType(typeName);
1920 return *incompleteType;
1921 }
catch (std::out_of_range &e) {
1924 if (typeName == L
"int") {
1926 }
else if (typeName == L
"bool") {
1928 }
else if (typeName == L
"deci") {
1930 }
else if (typeName == L
"string") {
1932 }
else if (typeName == L
"none") {
1934 }
else if (typeName == L
"char") {
1936 }
else if (typeName == L
"int32") {
1938 }
else if (typeName == L
"float") {
1940 }
else if (typeName == L
"ptr") {
1942 }
else if (typeName == L
"unsigned") {
1944 }
else if (typeName == L
"short") {
1954 if (funcName.hasDefTemplateArg()) {
1956 irModule->funcTemplateAsts[actualName] =
funcDefStmt;
1958 bool isVaridic =
false;
1967 std::vector<std::shared_ptr<IRValueType>> argTypes;
1969 if (&i == &
funcDefStmt->
getArgs().
get().back() && i->spec->kind == typeSpec::typeSpecKind::Elipsis ) {
1971 builder.
addAttr(IRFunctionDefinition::FunctionAttrs::Variadic);
1972 auto argName = i->getId().node.strVal;
1973 auto argType =
managedPtr(i->spec->elipsis ? parseTypeSpec(i->spec->elipsis).getDynamicArrayType()
1976 argTypes.push_back(argType);
1980 auto argName = i->getId().node.strVal;
1981 auto argType =
managedPtr(parseTypeSpec(i->spec));
1982 argTypes.push_back(argType);
1986 if (builder.
attrs.contains(IRFunctionDefinition::FunctionAttrs::Generator)) {
1988 std::to_wstring(irModule->identifier) + L
"_" + funcName.getId().node.strVal + getFuncUniqueNameStr(argTypes),
1995 builder.
setName(funcName.getId().node.strVal + getFuncUniqueNameStr(argTypes));
1997 auto func = builder.
yield();
1999 auto funcIndex = irModule->functionTable.put(builder.
name, func);
2000 irModule->functionOverloadIndexies[funcName.getId().node.strVal].push_back(funcIndex);
2003 if (builder.
attrs.contains(IRFunctionDefinition::FunctionAttrs::Generator)) {
2025 auto interfaceIndex = irModule->interfaceTable.put(interfaceName, {});
2028 builder.
setName(interfaceName);
2030 bool isVaridic =
false;
2031 yoi_assert(i->isMethod(), i->getLine(), i->getColumn(),
"Interface member must be a method");
2033 auto methodName = i->getMethod().getName().getId().get().strVal;
2034 auto methodResultType =
managedPtr(parseTypeSpec(i->getMethod().resultType));
2038 methodBuilder.
setDebugInfo({irModule->modulePath, i->getLine(), i->getColumn()});
2041 for (
auto &arg : i->getMethod().getArgs().get()) {
2042 if (&arg == &i->getMethod().getArgs().get().back() && arg->spec->kind == typeSpec::typeSpecKind::Elipsis ) {
2044 methodBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Variadic);
2045 auto argName = arg->getId().node.strVal;
2047 managedPtr(arg->spec->elipsis ? parseTypeSpec(arg->spec->elipsis).getDynamicArrayType()
2050 argTypes.push_back(argType);
2054 auto argName = arg->getId().get().strVal;
2055 auto argType =
managedPtr(parseTypeSpec(arg->spec));
2057 argTypes.push_back(argType);
2059 auto methodFuncName = L
"interface#" + interfaceName + L
"#" + methodName;
2060 auto uniq = getFuncUniqueNameStr(argTypes);
2061 methodBuilder.
setName(methodFuncName + uniq);
2063 auto func = methodBuilder.
yield();
2064 builder.
addMethod(methodName, methodName + uniq, func);
2066 auto interfaceType = builder.
yield();
2067 irModule->interfaceTable[interfaceIndex] = interfaceType;
2077 auto structIndex = irModule->structTable.put(structName, {});
2079 generateNullInterfaceImplementation(
managedPtr(
IRValueType{IRValueType::valueType::structObject, currentModuleIndex, structIndex}));
2086 auto memberName = i->getVar().getId().get().strVal;
2087 auto memberType =
managedPtr(parseTypeSpec(i->getVar().spec));
2088 if (i->modifier == structDefInnerPair::Modifier::DataField) {
2089 memberType->metadata.setMetadata(L
"STRUCT_DATAFIELD",
true);
2091 builder.
addField(memberName, memberType);
2095 bool isVaridic =
false;
2098 constructorBuilder.
setDebugInfo({irModule->modulePath, i->getLine(), i->getColumn()});
2099 constructorBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Constructor);
2102 auto thisType =
managedPtr(
IRValueType{IRValueType::valueType::structObject, currentModuleIndex, structIndex});
2104 constructorBuilder.
addArgument(L
"this", thisType);
2105 constructorBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Constructor);
2106 for (
auto &arg : i->getConstructor().getArgs().get()) {
2107 if (&arg == &i->getConstructor().getArgs().get().back() && arg->spec->kind == typeSpec::typeSpecKind::Elipsis) {
2109 constructorBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Variadic);
2110 auto argName = arg->getId().node.strVal;
2112 ? parseTypeSpec(arg->spec->elipsis).getDynamicArrayType()
2115 argTypes.push_back(argType);
2118 auto argName = arg->getId().get().strVal;
2119 auto argType =
managedPtr(parseTypeSpec(arg->spec));
2121 argTypes.push_back(argType);
2123 auto uniq = getFuncUniqueNameStr(argTypes);
2124 auto mangledName = L
"constructor" + uniq;
2125 constructorBuilder.
setName(structName + L
"::" + mangledName);
2127 auto func = constructorBuilder.
yield();
2128 auto funcIndex = irModule->functionTable.put_create(func->name, func);
2129 builder.
addMethod(mangledName, funcIndex);
2130 irModule->functionOverloadIndexies[structName + L
"::constructor"].push_back(funcIndex);
2134 bool isVaridic =
false;
2135 auto methodName = i->getMethod().getName().getId().get().strVal;
2137 if (i->getMethod().getName().hasDefTemplateArg()) {
2143 auto methodType =
managedPtr(parseTypeSpec(i->getMethod().resultType));
2146 methodBuilder.
attrs = getFunctionAttributes(i->getMethod().attrs);
2147 methodBuilder.
setDebugInfo({irModule->modulePath, i->getLine(), i->getColumn()});
2152 auto thisType =
managedPtr(
IRValueType{IRValueType::valueType::structObject, currentModuleIndex, structIndex});
2154 if (std::find(methodBuilder.
attrs.begin(), methodBuilder.
attrs.end(), IRFunctionDefinition::FunctionAttrs::Static) ==
2155 methodBuilder.
attrs.end())
2158 for (
auto &arg : i->getMethod().getArgs().get()) {
2159 if (&arg == &i->getMethod().getArgs().get().back() && arg->spec->kind == typeSpec::typeSpecKind::Elipsis) {
2161 methodBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Variadic);
2162 auto argName = arg->getId().node.strVal;
2164 ? parseTypeSpec(arg->spec->elipsis).getDynamicArrayType()
2167 argTypes.push_back(argType);
2170 auto argName = arg->getId().get().strVal;
2171 auto argType =
managedPtr(parseTypeSpec(arg->spec));
2173 argTypes.push_back(argType);
2176 auto uniq = getFuncUniqueNameStr(argTypes);
2177 auto mangledName = methodName + uniq;
2178 methodBuilder.
setName(structName + L
"::" + mangledName);
2179 auto func = methodBuilder.
yield();
2180 auto funcIndex = irModule->functionTable.put_create(func->name, func);
2181 builder.
addMethod(mangledName, funcIndex);
2182 irModule->functionOverloadIndexies[structName + L
"::" + methodName].push_back(funcIndex);
2188 finalizerBuilder.
setName(structName + L
"::finalizer");
2189 finalizerBuilder.
setDebugInfo({irModule->modulePath, i->getLine(), i->getColumn()});
2190 finalizerBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Finalizer);
2191 finalizerBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Preserve);
2192 auto thisType =
managedPtr(
IRValueType{IRValueType::valueType::structObject, currentModuleIndex, structIndex});
2195 auto func = finalizerBuilder.
yield();
2196 auto funcIndex = irModule->functionTable.put_create(structName + L
"::finalizer", func);
2197 builder.
addMethod(L
"finalizer", funcIndex);
2203 auto structType = builder.
yield();
2204 irModule->structTable[structIndex] = structType;
2212 auto it = structIdNode.
getTerms().begin();
2214 while (it + 1 != structIdNode.getTerms().end() && (targetModule = isModuleName(*it, targetModule)) != lastModule) {
2216 lastModule = targetModule;
2218 if (targetModule == -1) {
2219 targetModule = currentModuleIndex;
2221 yoi_assert(it + 1 == structIdNode.getTerms().end(), structIdNode.getLine(), structIdNode.getColumn(),
"Invalid interface name");
2224 auto structBaseName = (*it)->getId().get().strVal;
2226 if ((*it)->hasTemplateArg()) {
2228 yoi_assert(targetedModule->structTemplateAsts.contains(structBaseName),
2231 "Impl for undefined struct template: " +
wstring2string(structBaseName));
2237 if (concreteTemplateArgs.empty()) {
2238 targetedModule->templateInterfaceImplAsts[structBaseName].push_back(
implStmt);
2241 auto interfaceTemplateAst = targetedModule->templateInterfaceAsts[structBaseName];
2242 auto concreteStructName = getMangledTemplateName(structBaseName, concreteTemplateArgs);
2244 yoi_assert(concreteStructType->type == IRValueType::valueType::structObject,
2247 "Invalid struct name for struct specialization: " +
wstring2string(concreteStructName) +
2248 " (except structObject but got " +
wstring2string(concreteStructType->to_string()) +
")");
2250 specializeInterfaceImplementation(
implStmt, concreteStructType, concreteStructName, concreteTemplateArgs, targetModule);
2253 if (concreteTemplateArgs.empty()) {
2255 targetedModule->templateImplAsts[structBaseName] =
implStmt;
2258 auto structTemplateAst = targetedModule->structTemplateAsts[structBaseName];
2259 specializeStructTemplate(structBaseName, concreteTemplateArgs,
implStmt, targetModule);
2268 std::shared_ptr<IRValueType> srcType;
2271 targetModule = srcType->typeAffiliateModule;
2273 }
catch (std::runtime_error &e) {
2277 auto targetInterface =
2279 targetInterface->implementations.emplace_back(srcType->type, srcType->typeAffiliateModule, srcType->typeIndex);
2280 auto interfaceImplName = getInterfaceImplName(interfaceName.first, srcType);
2284 interfaceImplIndex = targetedModule->interfaceImplementationTable.getIndex(interfaceImplName);
2285 if (targetedModule->interfaceImplementationTable[interfaceImplIndex]) {
2289 }
catch (std::out_of_range &e) {
2290 interfaceImplIndex = targetedModule->interfaceImplementationTable.put(interfaceImplName, {});
2294 builder.
setName(interfaceImplName);
2295 builder.
setImplStructIndex({srcType->type, srcType->typeAffiliateModule, srcType->typeIndex});
2298 std::map<yoi::wstr, std::pair<yoi::wstr, std::shared_ptr<IRValueType>>> virtualMethodMap;
2304 "impl-for statement only allows method definition, not constructor or finalizer");
2306 bool isVaridic =
false;
2308 auto methodName = i->getMethod().getName().getId().get().strVal;
2311 methodBuilder.
setDebugInfo({irModule->modulePath, i->getLine(), i->getColumn()});
2312 methodBuilder.
attrs = getFunctionAttributes(i->getMethod().attrs);
2313 methodBuilder.
attrs.insert(IRFunctionDefinition::FunctionAttrs::Preserve);
2317 const auto &thisType = srcType;
2318 if (std::find(methodBuilder.
attrs.begin(), methodBuilder.
attrs.end(), IRFunctionDefinition::FunctionAttrs::Static) ==
2319 methodBuilder.
attrs.end())
2322 for (
auto &arg : i->getMethod().getArgs().get()) {
2323 if (&arg == &i->getMethod().getArgs().get().back() && arg->spec->kind == typeSpec::typeSpecKind::Elipsis) {
2325 methodBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Variadic);
2326 auto argName = arg->getId().node.strVal;
2328 managedPtr(arg->spec->elipsis ? parseTypeSpec(arg->spec->elipsis).getDynamicArrayType()
2331 argTypes.push_back(argType);
2334 auto argName = arg->getId().get().strVal;
2335 auto argType =
managedPtr(parseTypeSpec(arg->spec));
2337 argTypes.push_back(argType);
2339 auto uniq = getFuncUniqueNameStr(argTypes);
2341 methodBuilder.
setName(structBaseName + L
"::" + methodName + uniq + L
"interfaceImpl#" + interfaceImplName);
2343 auto func = methodBuilder.
yield();
2344 auto funcIndex = targetedModule->functionTable.put_create(func->name, func);
2345 targetedModule->functionOverloadIndexies[structBaseName + L
"::" + methodName + L
"interfaceImpl#" + interfaceImplName].push_back(
2350 virtualMethodMap[methodName + getFuncUniqueNameStr(argTypes,
true)] = {
2351 methodName + uniq,
managedPtr(
IRValueType{IRValueType::valueType::virtualMethod, targetModule, funcIndex})};
2356 visit(i->getMethod().block,
true);
2361 for (
auto &method : targetInterface->methodMap) {
2362 yoi_assert(virtualMethodMap.contains(method.first),
2365 "Method '" +
wstring2string(method.first) +
"' not implemented for interface '" +
2367 builder.
addVirtualMethod(virtualMethodMap[method.first].first, virtualMethodMap[method.first].second);
2370 targetedModule->interfaceImplementationTable[interfaceImplIndex] = builder.
yield();
2377 structIndex = targetedModule->structTable.getIndex(structBaseName);
2378 }
catch (std::runtime_error &e) {
2385 if (i->isConstructor()) {
2386 bool isVaridic =
false;
2388 for (
auto &arg : i->getConstructor().getArgs().get()) {
2389 if (&arg == &i->getConstructor().getArgs().get().back() && arg->spec->kind == typeSpec::typeSpecKind::Elipsis) {
2392 argTypes.push_back(argType);
2395 argTypes.push_back(
managedPtr(parseTypeSpec(arg->spec)));
2397 mangledName = structBaseName + L
"::constructor" + getFuncUniqueNameStr(argTypes);
2398 block = i->getConstructor().block;
2399 }
else if (i->isFinalizer()) {
2400 mangledName = structBaseName + L
"::finalizer";
2401 block = i->getFinalizer().block;
2403 if (i->getMethod().getName().hasTemplateArg()) {
2405 auto structDef = targetedModule->structTable[structIndex];
2406 structDef->templateMethodDefs[i->getMethod().getName().getId().get().strVal] = i;
2410 bool isVaridic =
false;
2412 for (
auto &arg : i->getMethod().getArgs().get()) {
2413 if (&arg == &i->getMethod().getArgs().get().back() && arg->spec->kind == typeSpec::typeSpecKind::Elipsis) {
2417 auto argType =
managedPtr(type.getDynamicArrayType());
2418 argTypes.push_back(argType);
2421 argTypes.push_back(
managedPtr(parseTypeSpec(arg->spec)));
2423 mangledName = structBaseName + L
"::" + i->getMethod().getName().getId().get().strVal + getFuncUniqueNameStr(argTypes);
2424 block = i->getMethod().block;
2428 auto funcIndex = targetedModule->functionTable.getIndex(mangledName);
2429 auto func = targetedModule->functionTable[funcIndex];
2436 }
catch (std::out_of_range &e) {
2438 i->getLine(), i->getColumn(),
"No matched constructor or method declaration found for impl: " +
wstring2string(mangledName));
2449 if (i->lhs->kind == letAssignmentPairLHS::vKind::identifier) {
2450 if (isVisitingGlobalScope()) {
2453 auto index = irModule->globalVariables.put(i->lhs->id->node.strVal, type);
2461 }
else if (i->lhs->kind == letAssignmentPairLHS::vKind::list) {
2463 if (type->isArrayType() || type->isDynamicArrayType()) {
2466 ? IRBuilder::ExtractType::First
2467 : IRBuilder::ExtractType::Last};
2468 bool isFull = i->lhs->list.back().kind != lexer::token::tokenKind::kThreeDots &&
2469 i->lhs->list.front().kind != lexer::token::tokenKind::kThreeDots;
2470 auto elementCount = i->lhs->list.size() - !isFull;
2472 auto bindType =
managedPtr(type->getElementType());
2473 for (
yoi::indexT curPos = extractType == IRBuilder::ExtractType::First && !isFull; curPos < elementCount; curPos++) {
2474 if (isVisitingGlobalScope()) {
2476 auto index = irModule->globalVariables.put(i->lhs->list[i->lhs->list.size() - 1 - curPos].strVal, bindType);
2481 i->lhs->list[i->lhs->list.size() - 1 - curPos].strVal, bindType);
2485 }
else if (type->type == IRValueType::valueType::structObject) {
2488 ? IRBuilder::ExtractType::First
2489 : IRBuilder::ExtractType::Last};
2490 bool isFull = i->lhs->list.back().kind != lexer::token::tokenKind::kThreeDots &&
2491 i->lhs->list.front().kind != lexer::token::tokenKind::kThreeDots;
2492 yoi::indexT elementCount = i->lhs->list.size() - !isFull;
2493 yoi::indexT startPos = extractType == IRBuilder::ExtractType::First ? elementCount - 1 : i->lhs->list.size() - 1;
2494 yoi::indexT endPos = extractType == IRBuilder::ExtractType::First ? -1 : 0 - isFull;
2496 for (
yoi::indexT curPos = startPos; curPos != endPos; curPos -= 1) {
2498 if (isVisitingGlobalScope()) {
2500 auto index = irModule->globalVariables.put(i->lhs->list[curPos].strVal, fieldType);
2501 tryCastTo(fieldType);
2507 tryCastTo(fieldType);
2512 panic(i->getLine(), i->getColumn(),
"Unsupported structured binding");
2523 case globalStmt::vKind::useStmt: {
2527 case globalStmt::vKind::implStmt: {
2531 case globalStmt::vKind::letStmt: {
2535 case globalStmt::vKind::funcDefStmt: {
2539 case globalStmt::vKind::structDefStmt: {
2543 case globalStmt::vKind::interfaceDefStmt: {
2547 case globalStmt::vKind::importDecl: {
2551 case globalStmt::vKind::exportDecl: {
2555 case globalStmt::vKind::typeAliasStmt: {
2559 case globalStmt::vKind::enumerationDef: {
2563 case globalStmt::vKind::dataStructDefStmt: {
2567 case globalStmt::vKind::conceptDef: {
2580 yoi_assert(condType->type == IRValueType::valueType::booleanObject,
2583 "The type in if-condition must be boolean");
2597 yoi_assert(elifCondType->type == IRValueType::valueType::booleanObject,
2599 i.cond->getColumn(),
2600 "The type in elif-condition must be boolean");
2605 visit(i.block,
true);
2631 yoi_assert(condType->type == IRValueType::valueType::booleanObject,
2634 "The type in while-condition must be boolean");
2669 yoi_assert(condType->type == IRValueType::valueType::booleanObject,
2672 "The type in for-condition must be boolean");
2703 "Generator function cannot return a value");
2707 tryCastTo(returnType);
2731 if (irModule->structTemplateAsts.contains(baseName)) {
2733 auto pureTemplateAst = irModule->templateImplAsts.at(baseName);
2734 auto specializedIndex = specializeStructTemplate(baseName, concreteTypes, pureTemplateAst, currentModuleIndex);
2735 return {IRValueType::valueType::structObject, currentModuleIndex, specializedIndex};
2736 }
catch (std::out_of_range &e) {
2739 "No implementation block found for struct template: " +
wstring2string(baseName));
2741 }
else if (irModule->templateInterfaceAsts.contains(baseName)) {
2742 auto specializedIndex = specializeInterfaceTemplate(baseName, concreteTypes, currentModuleIndex);
2743 return {IRValueType::valueType::interfaceObject, currentModuleIndex, specializedIndex};
2758 yoi_assert(sub->isSubscript() && sub->expr->getToken().kind == lexer::token::tokenKind::integer,
2761 "Expected dimension size for array type.");
2762 dimensions.push_back(sub->expr->getToken().basicVal.vInt);
2764 return baseType.getArrayType(dimensions);
2772 if (
auto it = mod->typeAliases.find(
identifier->
get().
strVal); it != mod->typeAliases.end()) {
2776 if (ex.
type == IRExternEntry::externType::structType)
2778 if (ex.
type == IRExternEntry::externType::datastructType)
2780 else if (ex.
type == IRExternEntry::externType::interfaceType)
2793 if (targetedModule->structTemplateAsts.contains(baseName)) {
2795 auto pureTemplateAst = targetedModule->templateImplAsts.at(baseName);
2796 auto specializedIndex = specializeStructTemplate(baseName, concreteTypes, pureTemplateAst, targetModule);
2797 return {IRValueType::valueType::structObject, targetModule, specializedIndex};
2798 }
catch (std::out_of_range &e) {
2801 "No implementation block found for struct template: " +
wstring2string(baseName));
2803 }
else if (targetedModule->templateInterfaceAsts.contains(baseName)) {
2804 auto specializedIndex = specializeInterfaceTemplate(baseName, concreteTypes, targetModule);
2805 return {IRValueType::valueType::interfaceObject, targetModule, specializedIndex};
2819 return {IRValueType::valueType::null};
2827 case typeSpec::typeSpecKind::Member: {
2831 while (it + 1 !=
typeSpec->
member->
getTerms().end() && (targetModule = isModuleName(*it, targetModule)) != lastModule) {
2833 lastModule = targetModule;
2836 IRValueType lhs{IRValueType::valueType::integerObject};
2838 if (targetModule == -1) {
2839 lhs = parseTypeSpec(*it);
2841 lhs = parseTypeSpecExtern(*it, targetModule);
2843 }
catch (std::out_of_range &e) {
2850 return lhs.getDynamicArrayType();
2858 case typeSpec::typeSpecKind::Func: {
2862 case typeSpec::typeSpecKind::Null: {
2864 return {IRValueType::valueType::null};
2866 case typeSpec::typeSpecKind::DecltypeExpr: {
2873 case typeSpec::typeSpecKind::Elipsis: {
2879 return {IRValueType::valueType::null};
2889 res += parseTypeSpec(i->spec).to_string();
2895 return std::move(res);
2898 yoi::wstr visitor::getInterfaceImplName(
const std::pair<yoi::indexT, yoi::indexT> &interfaceSrc,
const std::shared_ptr<IRValueType> &typeSrc) {
2899 return L
"interfaceImpl#" + std::to_wstring(interfaceSrc.first) + L
"#" + std::to_wstring(interfaceSrc.second) + L
"#" + typeSrc->to_string();
2902 std::pair<std::pair<yoi::indexT, yoi::indexT>, std::shared_ptr<IRInterfaceInstanceDefinition>>
2905 auto it = structDef->
getTerms().begin();
2907 while (it + 1 != structDef->
getTerms().end() && (targetModule = isModuleName(*it, targetModule)) != lastModule) {
2909 lastModule = targetModule;
2911 if (targetModule == -1) {
2912 targetModule = currentModuleIndex;
2915 auto interfaceName = parseIdentifierWithTemplateArg(*it);
2918 auto interfaceIndex = target->interfaceTable.getIndex(interfaceName);
2919 return std::make_pair(std::make_pair(targetModule, interfaceIndex), target->interfaceTable[interfaceIndex]);
2920 }
catch (std::out_of_range &) {
2927 return isModuleName(it->
id, currentModule);
2929 return currentModule;
2936 return {IRExternEntry::externType::globalVar,
identifier, moduleIndex, res};
2937 }
catch (std::out_of_range &) {
2941 return {IRExternEntry::externType::function,
identifier, moduleIndex, res};
2942 }
catch (std::out_of_range &) {
2946 return {IRExternEntry::externType::structType,
identifier, moduleIndex, res};
2947 }
catch (std::out_of_range &) {
2951 return {IRExternEntry::externType::datastructType,
identifier, moduleIndex, res};
2952 }
catch (std::out_of_range &) {
2956 return {IRExternEntry::externType::interfaceType,
identifier, moduleIndex, res};
2957 }
catch (std::out_of_range &) {
2961 return {IRExternEntry::externType::interfaceImplType,
identifier, moduleIndex, res};
2962 }
catch (std::out_of_range &) {
2965 throw std::out_of_range(
"undefined identifier: not known global variable, function, struct or interface type: " +
2969 bool visitor::isVisitingGlobalScope()
const {
2977 if (lhsType->isForeignBasicType()) {
2978 lhsType =
managedPtr(lhsType->getNormalizedForeignBasicType());
2980 if (rhsType->isForeignBasicType()) {
2981 rhsType =
managedPtr(rhsType->getNormalizedForeignBasicType());
2985 if (lhsType->is1ByteType() && !rhsType->is1ByteType()) {
2987 }
else if (!lhsType->is1ByteType() && rhsType->is1ByteType()) {
2991 if (lhsType->type == IRValueType::valueType::shortObject && rhsType->type != IRValueType::valueType::shortObject) {
2993 }
else if (lhsType->type != IRValueType::valueType::shortObject && rhsType->type == IRValueType::valueType::shortObject) {
2997 else if (lhsType->type == IRValueType::valueType::integerObject && rhsType->type == IRValueType::valueType::decimalObject) {
2999 }
else if (lhsType->type == IRValueType::valueType::decimalObject && rhsType->type == IRValueType::valueType::integerObject) {
3003 else if (lhsType->type == IRValueType::valueType::unsignedObject && rhsType->type == IRValueType::valueType::integerObject) {
3005 }
else if (lhsType->type == IRValueType::valueType::integerObject && rhsType->type == IRValueType::valueType::unsignedObject) {
3009 else if (lhsType->type == IRValueType::valueType::unsignedObject && rhsType->type == IRValueType::valueType::decimalObject) {
3011 }
else if (lhsType->type == IRValueType::valueType::decimalObject && rhsType->type == IRValueType::valueType::unsignedObject) {
3015 else if (lhsType->type == IRValueType::valueType::pointerObject) {
3017 }
else if (rhsType->type == IRValueType::valueType::pointerObject) {
3022 void visitor::emitBasicCastTo(
const std::shared_ptr<IRValueType> &toType) {
3025 if (rhs->type == toType->type) {
3032 yoi::wstr visitor::getInterfaceNameStr(
const std::pair<yoi::indexT, yoi::indexT> &interfaceSrc) {
3033 return L
"interface#" + std::to_wstring(interfaceSrc.first) + L
"#" + std::to_wstring(interfaceSrc.second);
3036 yoi::wstr visitor::getTypeSpecUniqueNameStr(
const std::shared_ptr<IRValueType> &type) {
3038 switch (type->type) {
3039 case IRValueType::valueType::integerObject:
3042 case IRValueType::valueType::decimalObject:
3045 case IRValueType::valueType::booleanObject:
3048 case IRValueType::valueType::stringObject:
3051 case IRValueType::valueType::characterObject:
3054 case IRValueType::valueType::shortObject:
3057 case IRValueType::valueType::unsignedObject:
3060 case IRValueType::valueType::structObject:
3061 res = L
"struct#" + std::to_wstring(type->typeAffiliateModule) + L
"#" + std::to_wstring(type->typeIndex);
3063 case IRValueType::valueType::null:
3066 case IRValueType::valueType::virtualMethod:
3067 res = L
"virtual_method#" + std::to_wstring(type->typeAffiliateModule) + L
"#" + std::to_wstring(type->typeIndex);
3069 case IRValueType::valueType::incompleteTemplateType:
3070 res = L
"incomplete_template_type#" + std::to_wstring(type->typeIndex);
3072 case IRValueType::valueType::interfaceObject:
3073 res = L
"interfaceObject#" + std::to_wstring(type->typeAffiliateModule) + L
"#" + std::to_wstring(type->typeIndex);
3075 case IRValueType::valueType::pointerObject:
3076 res = L
"pointerObject";
3078 case IRValueType::valueType::none:
3081 case IRValueType::valueType::datastructObject:
3082 res += L
"datastructObject#" + std::to_wstring(type->typeAffiliateModule) + L
"#" + std::to_wstring(type->typeIndex);
3090 if (type->isArrayType()) {
3092 for (
auto &dim : type->dimensions) {
3095 res += L
"[" + std::to_wstring(arraySize) + L
"]";
3096 }
else if (type->isDynamicArrayType()) {
3102 yoi::wstr visitor::getFuncUniqueNameStr(
const std::vector<std::shared_ptr<IRValueType>> &argumentTypes,
bool whetherIgnoreFirstParam) {
3105 for (
auto &arg : argumentTypes) {
3106 if (whetherIgnoreFirstParam && !first || !whetherIgnoreFirstParam)
3107 res += getTypeSpecUniqueNameStr(arg) + L
"#";
3111 if (!argumentTypes.empty()) {
3114 res.shrink_to_fit();
3124 "Invalid type specifier, expected global variable");
3136 }
catch (std::runtime_error &) {
3139 }
catch (std::out_of_range &) {
3155 std::shared_ptr<IRValueType> visitor::getIncompleteType(
const yoi::wstr &typeName)
const {
3158 throw std::out_of_range(
"No template builder found");
3161 auto res = templateBuilder.templateArguments[typeName];
3162 return res.templateType;
3163 }
catch (std::out_of_range &e) {
3170 for (
auto &arg : templateArgs.
spec) {
3171 yoi::wstr name = arg->getId().get().strVal;
3173 res[index].templateType =
managedPtr(
IRValueType{IRValueType::valueType::incompleteTemplateType, currentModuleIndex, index});
3180 for (
auto &arg : templateArgs.
spec) {
3181 res.push_back(
managedPtr(parseTypeSpec(arg->spec)));
3187 const yoi::vec<std::shared_ptr<IRValueType>> &concreteTemplateArgs,
3201 auto paramName = astNode->
id->
arg->
get()[i]->id->get().strVal;
3203 for (
auto &c : astNode->
id->
arg->
get()[i]->satisfyCondition->emaes) {
3204 checkConceptSatisfaction(c, paramName, concreteTemplateArgs[i]);
3210 pushModuleContext(moduleIndex);
3215 for (
const auto &argPair : astNode->
getArgs().
get()) {
3216 auto argName = argPair->getId().get().strVal;
3217 auto argType =
managedPtr(parseTypeSpec(&argPair->getSpec()));
3219 paramTypes.push_back(argType);
3222 if (targetedModule->functionTable.contains(specializedName + getFuncUniqueNameStr(paramTypes))) {
3223 auto result = targetedModule->functionTable.getIndex(specializedName + getFuncUniqueNameStr(paramTypes));
3230 builder.
setName(specializedName + getFuncUniqueNameStr(paramTypes));
3233 auto specializedFunc = builder.
yield();
3234 auto funcIndex = targetedModule->functionTable.put_create(specializedName + getFuncUniqueNameStr(paramTypes), specializedFunc);
3235 targetedModule->functionOverloadIndexies[specializedName].push_back(funcIndex);
3243 }
catch (std::runtime_error &e) {
3246 std::string(
"Exception occurred while specializing method: ") +
yoi::wstring2string(specializedName) +
": " + e.what());
3247 }
catch (std::exception &e) {
3250 std::string(
"Unknown exception occurred while specializing method: ") +
yoi::wstring2string(specializedName) +
": " + e.what());
3264 for (
size_t i = 0; i < templateArgs.size(); ++i) {
3265 mangled += getTypeSpecUniqueNameStr(templateArgs[i]);
3266 if (i < templateArgs.size() - 1) {
3278 for (
auto &spec : templateArgs->
get()) {
3283 if (!term->hasTemplateArg()) {
3284 params.push_back(term->id->get().strVal);
3289 panic(templateArgs->
getLine(), templateArgs->
getColumn(),
"Invalid template parameter definition. Expected identifier.");
3298 for (
auto &spec : templateArgs->
get()) {
3299 params.push_back(spec->getId().get().strVal);
3305 const yoi::vec<std::shared_ptr<IRValueType>> &concreteTemplateArgs,
3311 yoi::wstr specializedName = getMangledTemplateName(templateName, concreteTemplateArgs);
3313 if (targetedModule->structTable.contains(specializedName)) {
3314 return targetedModule->structTable.getIndex(specializedName);
3317 auto structAst = targetedModule->structTemplateAsts.at(templateName);
3320 yoi_assert(concreteTemplateArgs.size() == structAst->id->getArg().get().size(),
3323 "Template argument count mismatch for struct " +
wstring2string(templateName));
3324 for (
yoi::indexT i = 0; i < concreteTemplateArgs.size(); ++i) {
3325 auto paramName = structAst->id->getArg().get()[i]->getId().get().strVal;
3327 if (structAst->id->hasDefTemplateArg() && structAst->id->getArg().get()[i]->satisfyCondition) {
3328 for (
auto &c : structAst->id->getArg().get()[i]->satisfyCondition->emaes) {
3329 checkConceptSatisfaction(c, paramName, concreteTemplateArgs[i]);
3335 auto specializedStructIndex = targetedModule->structTable.put_create(specializedName,
nullptr);
3337 generateNullInterfaceImplementation(
managedPtr(
IRValueType{IRValueType::valueType::structObject, moduleIndex, specializedStructIndex}));
3338 auto selfType =
managedPtr(
IRValueType{IRValueType::valueType::structObject, moduleIndex, specializedStructIndex});
3341 pushModuleContext(moduleIndex);
3345 builder.
setName(specializedName);
3347 for (
yoi::indexT i = 0; i < structAst->id->getArg().get().size(); ++i) {
3348 paramNames.push_back(structAst->id->getArg().get()[i]->getId().get().strVal);
3351 for (
auto &field : structAst->getInner().getInner()) {
3352 if (field->kind == 0) {
3353 auto memberName = field->getVar().getId().get().strVal;
3354 auto memberType =
managedPtr(parseTypeSpec(field->getVar().spec));
3355 if (field->modifier == structDefInnerPair::Modifier::DataField) {
3356 memberType->metadata.setMetadata(L
"STRUCT_DATAFIELD",
true);
3358 builder.
addField(memberName, memberType);
3359 }
else if (field->kind == 2 && field->getMethod().getName().hasDefTemplateArg()) {
3363 auto [funcIndex, funcName] =
3364 specializeStructMethodDeclaration(specializationContext, field, specializedName, concreteTemplateArgs, moduleIndex);
3370 if (pureTemplateImplAst) {
3372 if (methodAst->isMethod() && methodAst->getMethod().getName().hasTemplateArg()) {
3373 builder.
addTemplateMethodDef(methodAst->getMethod().getName().getId().get().strVal, methodAst);
3378 auto specializedStruct = builder.
yield();
3379 targetedModule->structTable[specializedStructIndex] = specializedStruct;
3382 if (pureTemplateImplAst) {
3384 if (methodAst->isMethod() && methodAst->getMethod().getName().hasTemplateArg()) {
3388 specializeStructMethodDefinition(
3389 specializationContext, specializedStruct, methodAst, specializedName, concreteTemplateArgs, moduleIndex);
3394 if (targetedModule->templateInterfaceImplAsts.count(templateName)) {
3395 for (
auto &implAst : targetedModule->templateInterfaceImplAsts.at(templateName)) {
3396 specializeInterfaceImplementation(
3397 implAst, selfType, specializedName, concreteTemplateArgs, currentModuleIndex);
3404 return specializedStructIndex;
3407 yoi::indexT visitor::specializeStructMethodTemplate(
const std::shared_ptr<IRStructDefinition> &structDef,
3411 const yoi::vec<std::shared_ptr<IRValueType>> &methodTemplateArgs,
3418 for (
size_t i = 0; i < structDef->templateParamNames.size(); ++i) {
3419 combinedContext.
addTemplateArgument(structDef->templateParamNames[i], structDef->storedTemplateArgs[i]);
3430 yoi_assert(methodParams.size() == methodTemplateArgs.size(), 0, 0,
"Method template argument count mismatch");
3431 for (
size_t i = 0; i < methodParams.size(); ++i) {
3437 checkConceptSatisfaction(c, paramName, methodTemplateArgs[i]);
3443 yoi::wstr specializedMethodName = getMangledTemplateName(baseMethodName, methodTemplateArgs);
3445 pushModuleContext(moduleIndex);
3452 auto selfType =
managedPtr(
IRValueType{IRValueType::valueType::structObject, moduleIndex, targetedModule->structTable.getIndex(structDef->name)});
3458 if (std::find(funcBuilder.
attrs.begin(), funcBuilder.
attrs.end(), IRFunctionDefinition::FunctionAttrs::Static) == funcBuilder.
attrs.end()) {
3462 auto specializedType =
managedPtr(parseTypeSpec(&arg->getSpec()));
3463 funcBuilder.
addArgument(arg->getId().get().strVal, specializedType);
3464 specializedArgTypes.push_back(specializedType);
3470 if (std::find(funcBuilder.
attrs.begin(), funcBuilder.
attrs.end(), IRFunctionDefinition::FunctionAttrs::Static) == funcBuilder.
attrs.end()) {
3474 auto specializedType =
managedPtr(parseTypeSpec(&arg->getSpec()));
3475 funcBuilder.
addArgument(arg->getId().get().strVal, specializedType);
3476 specializedArgTypes.push_back(specializedType);
3481 yoi::wstr fullMangledName = structDef->
name + L
"::" + specializedMethodName + getFuncUniqueNameStr(specializedArgTypes);
3483 if (targetedModule->functionTable.contains(fullMangledName)) {
3484 auto res = targetedModule->functionTable.getIndex(fullMangledName);
3490 funcBuilder.
setName(fullMangledName);
3491 auto specializedFunc = funcBuilder.
yield();
3492 auto funcIndex = targetedModule->functionTable.put_create(fullMangledName, specializedFunc);
3493 targetedModule->functionOverloadIndexies[structDef->name + L
"::" + baseMethodName].push_back(funcIndex);
3502 }
catch (std::exception &e) {
3515 std::pair<yoi::indexT, yoi::wstr> visitor::specializeStructMethodDeclaration(
IRTemplateBuilder &structTemplate,
3518 const yoi::vec<std::shared_ptr<IRValueType>> &concreteTemplateArgs,
3534 if (methodAstNode->
kind == 1) {
3535 for (
yoi::indexT i = 0; i < concreteTemplateArgs.size(); ++i) {
3540 checkConceptSatisfaction(c, paramName, concreteTemplateArgs[i]);
3545 baseMethodName = L
"constructor";
3547 genericArgTypes.push_back(
managedPtr(parseTypeSpec(&arg->getSpec())));
3549 genericMethodKey = baseMethodName + getFuncUniqueNameStr(genericArgTypes);
3550 }
else if (methodAstNode->
kind == 2) {
3551 for (
yoi::indexT i = 0; i < concreteTemplateArgs.size(); ++i) {
3556 checkConceptSatisfaction(c, paramName, concreteTemplateArgs[i]);
3563 genericArgTypes.push_back(
managedPtr(parseTypeSpec(&arg->getSpec())));
3565 genericMethodKey = baseMethodName + getFuncUniqueNameStr(genericArgTypes);
3566 }
else if (methodAstNode->
kind == 3) {
3568 baseMethodName = L
"finalizer";
3569 genericMethodKey = baseMethodName;
3575 for (
size_t i = 0; i < concreteTemplateArgs.size(); ++i) {
3580 managedPtr(
IRValueType{IRValueType::valueType::structObject, moduleIndex, targetedModule->structTable.getIndex(specializedStructName)});
3590 if (methodAstNode->
kind == 1) {
3591 funcBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Constructor);
3594 auto specializedType =
managedPtr(parseTypeSpec(&arg->getSpec()));
3595 funcBuilder.
addArgument(arg->getId().get().strVal, specializedType);
3596 specializedArgTypes.push_back(specializedType);
3599 }
else if (methodAstNode->
kind == 2) {
3601 if (std::find(funcBuilder.
attrs.begin(), funcBuilder.
attrs.end(), IRFunctionDefinition::FunctionAttrs::Static) ==
3602 funcBuilder.
attrs.end()) {
3606 auto specializedType =
managedPtr(parseTypeSpec(&arg->getSpec()));
3607 funcBuilder.
addArgument(arg->getId().get().strVal, specializedType);
3608 specializedArgTypes.push_back(specializedType);
3611 }
else if (methodAstNode->
kind == 3) {
3612 funcBuilder.
setName(specializedStructName + L
"::finalizer");
3613 funcBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Finalizer);
3614 funcBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Preserve);
3619 yoi::wstr specializedMethodName = specializedStructName + L
"::" + baseMethodName;
3620 funcBuilder.
setName(specializedMethodName + getFuncUniqueNameStr(specializedArgTypes));
3622 auto specializedFunc = funcBuilder.
yield();
3623 auto funcIndex = targetedModule->functionTable.put_create(specializedMethodName + getFuncUniqueNameStr(specializedArgTypes), specializedFunc);
3624 targetedModule->functionOverloadIndexies[specializedMethodName].push_back(funcIndex);
3627 return {funcIndex, baseMethodName + getFuncUniqueNameStr(specializedArgTypes)};
3631 const std::shared_ptr<IRStructDefinition> &specializedStruct,
3634 const yoi::vec<std::shared_ptr<IRValueType>> &concreteTemplateArgs,
3651 baseMethodName = L
"constructor";
3653 genericArgTypes.push_back(
managedPtr(parseTypeSpec(&arg->getSpec())));
3655 genericMethodKey = baseMethodName + getFuncUniqueNameStr(genericArgTypes);
3657 baseMethodName = L
"finalizer";
3659 genericArgTypes.push_back(
managedPtr(parseTypeSpec(&arg->getSpec())));
3661 genericMethodKey = baseMethodName + getFuncUniqueNameStr(genericArgTypes);
3665 genericArgTypes.push_back(
managedPtr(parseTypeSpec(&arg->getSpec())));
3667 genericMethodKey = baseMethodName + getFuncUniqueNameStr(genericArgTypes);
3673 for (
size_t i = 0; i < concreteTemplateArgs.size(); ++i) {
3678 managedPtr(
IRValueType{IRValueType::valueType::structObject, moduleIndex, targetedModule->structTable.getIndex(specializedStructName)});
3686 auto specializedType =
managedPtr(parseTypeSpec(&arg->getSpec()));
3687 specializedArgTypes.push_back(specializedType);
3693 auto specializedType =
managedPtr(parseTypeSpec(&arg->getSpec()));
3694 specializedArgTypes.push_back(specializedType);
3698 yoi::wstr specializedMethodName = specializedStructName + L
"::" + baseMethodName + getFuncUniqueNameStr(specializedArgTypes);
3700 auto funcIndex = targetedModule->functionTable.getIndex(specializedMethodName);
3707 }
catch (std::exception &e) {
3708 set_current_file_path(moduleContextStack.top().first->getIRBuilder().getCurrentDebugInfo().sourceFile);
3709 panic(moduleContextStack.top().first->getIRBuilder().getCurrentDebugInfo().line,
3710 moduleContextStack.top().first->getIRBuilder().getCurrentDebugInfo().column,
3711 std::string(
"Exception occurred while specializing method: ") +
yoi::wstring2string(specializedMethodName) +
": " + e.what() +
3722 const yoi::vec<std::shared_ptr<IRValueType>> &specializedArgTypes) {
3723 auto res = baseMethodName;
3724 for (
yoi::indexT i = 0; i < specializedArgTypes.size(); ++i) {
3725 auto &arg = templateArgs[i];
3726 auto strRepl1 = templateArgs[i].templateType->to_string();
3727 auto strRepl2 = specializedArgTypes[i]->to_string();
3740 }
catch (std::runtime_error &e) {
3749 lastModule = targetModule;
3754 "Expected a identifier after modules but this is not the final term of expression.");
3755 targetModule = targetModule == -1 ? currentModuleIndex : targetModule;
3759 if (!(*it)->hasTemplateArg()) {
3763 if (funcIt->first.starts_with((*it)->id->get().strVal + L
"#")) {
3771 if (funcIndex != -1) {
3777 auto templateName = (*it)->id->get().strVal;
3779 throw std::out_of_range(
"Cannot find the template: " +
wstring2string(templateName));
3785 "Expected template arguments for template: " +
wstring2string(templateName));
3787 auto templateArgs = parseTemplateArgs((*it)->getArg());
3789 auto funcIndex = specializeFunctionTemplate(
3797 }
catch (std::out_of_range &e) {
3815 }
catch (std::runtime_error &e) {
3833 auto argType =
managedPtr(parseTypeSpec(&arg->getSpec()));
3834 builder.
addArgument(arg->getId().get().strVal, argType);
3837 auto importedFunc = builder.
yield();
3841 irModule->externTable.put_create(
3851 void visitor::tryCastTo(
const std::shared_ptr<IRValueType> &toType) {
3853 if (rhs->isForeignBasicType()) {
3854 rhs =
managedPtr(rhs->getNormalizedForeignBasicType());
3857 if (*rhs == *toType) {
3859 }
else if (rhs->type == IRValueType::valueType::pointerObject || rhs->type == IRValueType::valueType::pointer ||
3860 rhs->type == IRValueType::valueType::null || toType->type == IRValueType::valueType::pointerObject ||
3861 toType->type == IRValueType::valueType::pointer) {
3864 }
else if (rhs->isBasicType() && toType->isBasicType() && !rhs->isDynamicArrayType() && !toType->isDynamicArrayType() &&
3865 !rhs->isArrayType() && !toType->isArrayType() &&
3866 (rhs->type != IRValueType::valueType::stringObject || toType->type == IRValueType::valueType::pointerObject)) {
3867 emitBasicCastTo(toType);
3868 }
else if ((toType->isArrayType() || toType->isDynamicArrayType()) && rhs->type == IRValueType::valueType::bracedInitalizerList) {
3869 auto elementType =
managedPtr(toType->getElementType());
3870 auto elementCount = rhs->bracedTypes.size();
3871 if (toType->isArrayType()) {
3878 }
else if (toType->type == IRValueType::valueType::interfaceObject && !toType->isArrayType() && !toType->isDynamicArrayType()) {
3881 auto implName = getInterfaceImplName({toType->typeAffiliateModule, toType->typeIndex}, rhs);
3889 rhs->typeAffiliateModule != currentModuleIndex,
3890 rhs->typeAffiliateModule);
3891 }
catch (std::out_of_range &e) {
3895 ": no implementation found.");
3897 }
else if (toType->type == IRValueType::valueType::structObject && !toType->isArrayType() && !toType->isDynamicArrayType()) {
3900 auto result = resolveOverloadExtern(L
"constructor", {rhs}, toType->typeAffiliateModule, structType);
3901 if (result.found()) {
3902 if (result.isCastRequired) {
3903 tryCastTo(result.function->argumentTypes.back());
3907 result.functionIndex, 2, result.function->returnType,
true, toType->typeAffiliateModule);
3912 ": no viable conversion found.");
3918 ": no viable conversion found.");
3922 bool visitor::canCastTo(
const std::shared_ptr<IRValueType> &fromType,
const std::shared_ptr<IRValueType> &toType) {
3923 auto rhs = fromType;
3924 if (fromType->isForeignBasicType()) {
3925 rhs =
managedPtr(rhs->getNormalizedForeignBasicType());
3927 if (*rhs == *toType) {
3929 }
else if (rhs->isBasicType() && toType->isBasicType() && !rhs->isDynamicArrayType() && !toType->isDynamicArrayType() &&
3930 !rhs->isArrayType() && !toType->isArrayType() && (toType->type != IRValueType::valueType::stringObject) &&
3931 (rhs->type != IRValueType::valueType::stringObject || toType->type == IRValueType::valueType::pointerObject)) {
3933 }
else if ((toType->isArrayType() || toType->isDynamicArrayType()) && fromType->type == IRValueType::valueType::bracedInitalizerList) {
3934 auto e = toType->getElementType();
3935 for (
auto &i : fromType->bracedTypes) {
3941 }
else if (rhs->type == IRValueType::valueType::pointerObject) {
3944 }
else if (toType->type == IRValueType::valueType::interfaceObject && !toType->isArrayType() && !toType->isDynamicArrayType()) {
3947 auto implName = getInterfaceImplName({toType->typeAffiliateModule, toType->typeIndex}, rhs);
3951 }
catch (std::out_of_range &e) {
3954 }
else if (toType->type == IRValueType::valueType::structObject && !toType->isArrayType() && !toType->isDynamicArrayType()) {
3957 auto result = resolveOverloadExtern(L
"constructor", {rhs}, toType->typeAffiliateModule, structType);
3958 return result.found();
3982 yoi_assert(rhs->type == IRValueType::valueType::interfaceObject,
3985 "dynamic cast can only be applied to interface objects to struct objects. Type: " +
yoi::wstring2string(rhs->to_string()));
3990 if (
auto it = std::find(impls.begin(), impls.end(), std::make_tuple(toType->type, toType->typeAffiliateModule, toType->typeIndex));
3997 ": no implementation found.");
4002 yoi::indexT visitor::generateNullInterfaceImplementation(
const std::shared_ptr<IRValueType> &structType) {
4004 auto nullImplName = getInterfaceImplName(nullInterface, structType);
4007 ->getImportedModule(structType->typeAffiliateModule)
4008 ->interfaceImplementationTable.getIndex(nullImplName);
4009 }
catch (std::out_of_range &e) {
4013 ->implementations.emplace_back(structType->type, structType->typeAffiliateModule, structType->typeIndex);
4015 {structType->type, structType->typeAffiliateModule, structType->typeIndex},
4020 ->getImportedModule(structType->typeAffiliateModule)
4021 ->interfaceImplementationTable.put_create(nullImplName, nullImpl);
4026 std::set<IRFunctionDefinition::FunctionAttrs> res;
4027 for (
auto &attr : attrs) {
4028 switch (attr.kind) {
4029 case lexer::token::tokenKind::kAlwaysInline:
4030 res.insert(IRFunctionDefinition::FunctionAttrs::AlwaysInline);
4032 case lexer::token::tokenKind::kNoFFI:
4033 res.insert(IRFunctionDefinition::FunctionAttrs::NoFFI);
4035 case lexer::token::tokenKind::kStatic:
4036 res.insert(IRFunctionDefinition::FunctionAttrs::Static);
4038 case lexer::token::tokenKind::kIntrinsic:
4039 res.insert(IRFunctionDefinition::FunctionAttrs::Intrinsic);
4041 case lexer::token::tokenKind::kGenerator:
4042 res.insert(IRFunctionDefinition::FunctionAttrs::Generator);
4048 return std::move(res);
4067 std::shared_ptr<yoi::IRModule> target =
4069 if (
auto x = target->moduleImports.find(it->
node.
strVal); x != target->moduleImports.end()) {
4072 return currentModule;
4077 auto it = emaExpression->
getTerms().begin();
4079 while (it + 1 != emaExpression->
getTerms().end() && (targetModule = isModuleName((*it)->id, lastModule)) != lastModule) {
4081 lastModule = targetModule;
4084 bool whetherLastTerm = it + 1 == emaExpression->
getTerms().end();
4085 if (targetModule == -1 || targetModule == currentModuleIndex)
4086 return parseTypeSpec((*it));
4088 return parseTypeSpecExtern((*it), targetModule);
4091 bool visitor::OverloadResult::found()
const {
4092 return functionIndex != -1;
4097 for (
auto &arg : args->
get()) {
4105 const yoi::vec<std::shared_ptr<IRValueType>> &argTypes,
4107 const std::shared_ptr<IRStructDefinition> &structContext) {
4112 auto exactMangledName = baseName + getFuncUniqueNameStr(argTypes);
4113 yoi::wstr lookupName = structContext ? structContext->name + L
"::" + exactMangledName : exactMangledName;
4115 if (targetedModule->functionTable.contains(lookupName)) {
4116 result.
functionIndex = targetedModule->functionTable.getIndex(lookupName);
4119 if (std::find(result.
function->attrs.begin(), result.
function->attrs.end(), IRFunctionDefinition::FunctionAttrs::Variadic) !=
4129 auto findVariadicMatch = [&](
const yoi::wstr &funcKey,
bool skipFirstParam =
false) {
4130 auto func = targetedModule->functionTable[funcKey];
4131 const auto ¶mTypes = func->argumentTypes;
4132 size_t fixedParamCount = paramTypes.size() - 1 - (skipFirstParam && paramTypes.size() > 1 ? 1 : 0);
4133 if (std::find(func->attrs.begin(), func->attrs.end(), IRFunctionDefinition::FunctionAttrs::Variadic) != func->attrs.end()) {
4134 if (argTypes.size() >= fixedParamCount) {
4135 bool fixedMatch =
true;
4136 for (
size_t i = 0; i < fixedParamCount; ++i) {
4137 if (!canCastTo(argTypes[i], paramTypes[i + skipFirstParam])) {
4143 result.
functionIndex = targetedModule->functionTable.getIndex(funcKey);
4152 if (argTypes.size() != fixedParamCount + 1 ||
4153 paramTypes.size() != fixedParamCount + 1 + skipFirstParam)
4156 for (
size_t i = 0; i < fixedParamCount + 1; ++i) {
4157 if (!canCastTo(argTypes[i], paramTypes[i + skipFirstParam])) {
4162 result.
functionIndex = targetedModule->functionTable.getIndex(funcKey);
4173 yoi::wstr prefix = structContext ? structContext->name + L
"::" + baseName : baseName;
4174 for (
const auto it : targetedModule->functionOverloadIndexies[prefix]) {
4175 const auto &key = targetedModule->functionTable.getKey(it);
4176 if (key.starts_with(prefix)) {
4177 if (findVariadicMatch(key,
4178 structContext !=
nullptr &&
4179 !targetedModule->functionTable[it]->hasAttribute(IRFunctionDefinition::FunctionAttrs::Static)))
4184 if (!structContext && targetedModule->funcTemplateAsts.contains(baseName)) {
4186 auto astNode = targetedModule->funcTemplateAsts.at(baseName);
4187 auto templateArgs = getTemplateArgs(astNode->id->getArg());
4191 for (
yoi::indexT i = 0; i < argTypes.size(); i++) {
4192 if (i < templateArgs.size() && templateArgs[i].templateType->type == IRValueType::valueType::incompleteTemplateType) {
4193 auto &srcTypeToPlace = argTypes[i];
4194 auto incompleteTypeIndex = templateArgs[i].templateType->typeIndex;
4195 if (deducedArgs[incompleteTypeIndex] && *deducedArgs[incompleteTypeIndex] != *srcTypeToPlace) {
4196 throw std::runtime_error(
"Template argument type mismatch during deduction.");
4198 deducedArgs[incompleteTypeIndex] = srcTypeToPlace;
4201 for (
yoi::indexT i = 0; i < deducedArgs.size(); i++) {
4202 if (deducedArgs[i] ==
nullptr) {
4203 throw std::runtime_error(
"Cannot deduce all template arguments for: " +
yoi::wstring2string(baseName));
4207 auto specializedFuncIndex = specializeFunctionTemplate(astNode, deducedArgs, targetModule);
4209 result.
function = targetedModule->functionTable[specializedFuncIndex];
4212 if (std::find(result.
function->attrs.begin(), result.
function->attrs.end(), IRFunctionDefinition::FunctionAttrs::Variadic) !=
4219 }
catch (
const std::out_of_range &) {
4227 bool visitor::handleInvocationExtern(
const yoi::wstr &baseName,
4230 const std::shared_ptr<IRValueType> &structContext,
4234 auto argTypes = evaluateArguments(args);
4236 if (structContext && structContext->type == IRValueType::valueType::structObject) {
4239 overload = resolveOverloadExtern(baseName, argTypes, targetModule, structType);
4241 if (!overload.
found()) {
4243 if (structType->templateMethodDecls.contains(baseName) || structType->templateMethodDefs.contains(baseName)) {
4245 structType->templateMethodDecls.contains(baseName) ? structType->templateMethodDecls.at(baseName) :
nullptr;
4247 structType->templateMethodDefs.contains(baseName) ? structType->templateMethodDefs.at(baseName) :
nullptr;
4252 concreteMethodTemplateArgs = parseTemplateArgs(*templateArgs);
4261 concreteMethodTemplateArgs.resize(methodTemplateParams.size());
4263 for (
size_t i = 0; i < astArgs.size() && i < argTypes.size(); ++i) {
4264 auto &spec = *astArgs[i]->spec;
4265 if (spec.kind == typeSpec::typeSpecKind::Member && spec.member && spec.member->getTerms().size() == 1) {
4266 auto term = spec.member->getTerms()[0];
4267 yoi::wstr typeName = term->id->get().strVal;
4268 for (
size_t j = 0; j < methodTemplateParams.size(); ++j) {
4269 if (methodTemplateParams[j] == typeName) {
4270 concreteMethodTemplateArgs[j] = argTypes[i];
4278 bool allDeduced =
true;
4279 for (
auto &arg : concreteMethodTemplateArgs) {
4286 if (allDeduced && !concreteMethodTemplateArgs.empty()) {
4289 auto specializedFuncIndex =
4290 specializeStructMethodTemplate(structType, decl, def, baseName, concreteMethodTemplateArgs, targetModule);
4292 overload.
function = targetedModule->functionTable[specializedFuncIndex];
4296 }
else if (structContext && structContext->type == IRValueType::valueType::interfaceObject) {
4297 auto interfaceType =
4299 overload = resolveOverloadInterface(baseName, argTypes, targetModule, interfaceType);
4301 overload = resolveOverloadExtern(baseName, argTypes, targetModule,
nullptr);
4304 if (!overload.
found()) {
4309 auto fullMangledName = overload.
function->name;
4310 bool skipFirstParam = structContext !=
nullptr && !noThisCall && structContext->type != IRValueType::valueType::interfaceObject;
4315 visit(args->
get()[i]);
4316 tryCastTo(overload.
function->argumentTypes[i + skipFirstParam]);
4318 auto variadicArgCount = argTypes.size() - overload.
fixedArgCount;
4319 if (variadicArgCount > 0) {
4320 for (
size_t i = 0; i < variadicArgCount; ++i) {
4325 overload.
variadicElementType, {static_cast<yoi::indexT>(variadicArgCount)}, variadicArgCount);
4332 visit(args->
get()[i]);
4333 tryCastTo(overload.
function->argumentTypes[i + skipFirstParam]);
4339 size_t finalParamCount = overload.
function->argumentTypes.size();
4340 if (structContext && structContext->type == IRValueType::valueType::structObject) {
4341 IRExternEntry externEntry = getExternEntry(targetModule, fullMangledName);
4342 auto isStaticMethod =
4343 std::find(overload.
function->attrs.begin(), overload.
function->attrs.end(), IRFunctionDefinition::FunctionAttrs::Static) !=
4345 bool usePureStaticLogic = noThisCall && isStaticMethod;
4347 if (usePureStaticLogic) {
4352 finalParamCount - !isStaticMethod,
4358 }
else if (structContext && structContext->type == IRValueType::valueType::interfaceObject) {
4360 structContext->typeIndex,
4364 structContext->typeAffiliateModule);
4366 auto externEntry = getExternEntry(targetModule, fullMangledName);
4368 externEntry.itemIndex, finalParamCount, overload.
function->returnType,
true, externEntry.affiliateModule);
4373 template <
typename T>
yoi::indexT visitor::handleBinaryOperatorOverload(
const yoi::wstr &overloadName, T *rhsAST) {
4376 bool isResolved =
false;
4378 if (lhs->type == IRValueType::valueType::structObject) {
4380 resolveOverloadExtern(overloadName,
4382 lhs->typeAffiliateModule,
4384 if (resolved.found()) {
4385 yoi_assert(resolved.isVariadic ==
false, 0, 0,
"Binary operator overloading with variadic functions is not supported.");
4386 yoi_assert(std::find(resolved.function->attrs.begin(), resolved.function->attrs.end(), IRFunctionDefinition::FunctionAttrs::Static) !=
4387 resolved.function->attrs.end(),
4390 "Binary operator overloading with non-static functions is not supported.");
4392 if (resolved.isCastRequired) {
4394 tryCastTo(resolved.function->argumentTypes.front());
4396 tryCastTo(resolved.function->argumentTypes.back());
4403 resolved.functionIndex, 1, resolved.function->returnType,
false,
true, lhs->typeAffiliateModule);
4407 if (!isResolved && rhs->type == IRValueType::valueType::structObject) {
4409 resolveOverloadExtern(overloadName,
4411 rhs->typeAffiliateModule,
4413 if (resolved.found()) {
4417 "Binary operator overloading with variadic functions is not supported.");
4418 yoi_assert(std::find(resolved.function->attrs.begin(), resolved.function->attrs.end(), IRFunctionDefinition::FunctionAttrs::Static) !=
4419 resolved.function->attrs.end(),
4422 "Binary operator overloading with non-static functions is not supported.");
4424 if (resolved.isCastRequired) {
4426 tryCastTo(resolved.function->argumentTypes.front());
4428 tryCastTo(resolved.function->argumentTypes.back());
4438 resolved.functionIndex, 1, resolved.function->returnType,
false,
true, rhs->typeAffiliateModule);
4443 if (!isResolved && lhs->type == IRValueType::valueType::interfaceObject) {
4444 const auto &baseName = overloadName;
4445 auto mangledName = getFuncUniqueNameStr({rhs});
4447 auto resolved = resolveOverloadInterface(
4450 lhs->typeAffiliateModule,
4453 if (resolved.found()) {
4454 if (resolved.isCastRequired) {
4456 tryCastTo(resolved.function->argumentTypes.front());
4458 tryCastTo(resolved.function->argumentTypes.back());
4464 resolved.functionIndex, lhs->typeIndex, 1, resolved.function->returnType,
true, lhs->typeAffiliateModule);
4483 bool isResolved =
false;
4485 if (rhs->type == IRValueType::valueType::structObject) {
4487 resolveOverloadExtern(overloadName,
4489 rhs->typeAffiliateModule,
4491 if (resolved.found()) {
4495 "Unary operator overloading with variadic functions is not supported.");
4496 yoi_assert(std::find(resolved.function->attrs.begin(), resolved.function->attrs.end(), IRFunctionDefinition::FunctionAttrs::Static) !=
4497 resolved.function->attrs.end(),
4500 "Unary operator overloading with non-static functions is not supported.");
4503 resolved.functionIndex, 0, resolved.function->returnType,
false,
true, rhs->typeAffiliateModule);
4507 if (rhs->type == IRValueType::valueType::interfaceObject) {
4508 const auto &baseName = overloadName;
4509 auto mangledName = getFuncUniqueNameStr({});
4512 ->getImportedModule(rhs->typeAffiliateModule)
4513 ->interfaceTable[rhs->typeIndex]
4514 ->methodMap.getIndex(baseName + mangledName);
4516 ->getImportedModule(rhs->typeAffiliateModule)
4517 ->interfaceTable[rhs->typeIndex]
4518 ->methodMap[methodIdx];
4519 yoi_assert(method->argumentTypes.size() == 1,
4522 "Argument count does not match");
4535 const yoi::vec<std::shared_ptr<IRValueType>> &concreteTemplateArgs,
4538 yoi::wstr specializedName = getMangledTemplateName(templateName, concreteTemplateArgs);
4539 if (targetedModule->interfaceTable.contains(specializedName)) {
4540 return targetedModule->interfaceTable.getIndex(specializedName);
4543 yoi_assert(targetedModule->templateInterfaceAsts.contains(templateName), 0, 0,
"Unknown interface template: " +
wstring2string(templateName));
4545 auto interfaceAst = targetedModule->templateInterfaceAsts.at(templateName);
4548 yoi_assert(concreteTemplateArgs.size() == interfaceAst->id->arg->get().size(),
4551 "Template argument count mismatch for interface " +
wstring2string(templateName));
4552 for (
yoi::indexT i = 0; i < concreteTemplateArgs.size(); ++i) {
4553 auto paramName = interfaceAst->id->arg->get()[i]->getId().get().strVal;
4557 pushModuleContext(moduleIndex);
4561 builder.
setName(specializedName);
4563 for (
auto &i : interfaceAst->getInner().getInner()) {
4564 bool isVaridic =
false;
4565 yoi_assert(i->isMethod(), i->getLine(), i->getColumn(),
"Interface member must be a method");
4566 auto methodName = i->getMethod().getName().getId().get().strVal;
4567 auto methodResultType =
managedPtr(parseTypeSpec(i->getMethod().resultType));
4570 methodBuilder.
setDebugInfo({irModule->modulePath, i->getLine(), i->getColumn()});
4572 for (
auto &arg : i->getMethod().getArgs().get()) {
4573 if (&arg == &i->getMethod().getArgs().get().back() && arg->spec->kind == typeSpec::typeSpecKind::Elipsis) {
4575 methodBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Variadic);
4576 auto argName = arg->getId().node.strVal;
4578 managedPtr(arg->spec->elipsis ? parseTypeSpec(arg->spec->elipsis).getDynamicArrayType()
4581 argTypes.push_back(argType);
4584 auto argName = arg->getId().get().strVal;
4585 auto argType =
managedPtr(parseTypeSpec(arg->spec));
4587 argTypes.push_back(argType);
4589 auto uniq = getFuncUniqueNameStr(argTypes);
4590 methodBuilder.
setName(L
"interface#" + specializedName + L
"#" + methodName + uniq);
4591 builder.
addMethod(methodName, methodName + uniq, methodBuilder.
yield());
4594 auto specializedInterface = builder.
yield();
4595 auto interfaceIndex = irModule->interfaceTable.put_create(
4596 specializedName, specializedInterface);
4600 return interfaceIndex;
4604 const std::shared_ptr<IRValueType> &concreteStructType,
4606 const yoi::vec<std::shared_ptr<IRValueType>> &concreteTemplateArgs,
4612 "Expected 'impl for' AST node for interface implementation specialization.");
4618 yoi_assert(concreteInterfaceType->type == IRValueType::valueType::interfaceObject,
4621 "Expected an interface type.");
4625 auto interfaceSrcPair = std::make_pair(concreteInterfaceType->typeAffiliateModule, concreteInterfaceType->typeIndex);
4627 auto targetInterface =
4630 targetInterface->implementations.emplace_back(
4631 concreteStructType->type, concreteStructType->typeAffiliateModule, concreteStructType->typeIndex);
4633 auto implName = getInterfaceImplName(interfaceSrcPair, concreteStructType);
4634 if (irModule->interfaceImplementationTable.contains(implName)) {
4640 implIndex = targetedModule->interfaceImplementationTable.getIndex(implName);
4641 if (targetedModule->interfaceImplementationTable[implIndex]) {
4644 }
catch (std::out_of_range &e) {
4645 implIndex = targetedModule->interfaceImplementationTable.put_create(implName,
nullptr);
4648 if (implAst->
inner) {
4651 builder.
setImplStructIndex({concreteStructType->type, concreteStructType->typeAffiliateModule, concreteStructType->typeIndex});
4654 std::map<yoi::wstr, std::pair<yoi::wstr, std::shared_ptr<IRValueType>>> virtualMethodMap;
4658 methodNode->getLine(),
4659 methodNode->getColumn(),
4660 "Only methods are allowed in interface implementations.");
4661 auto &methodAst = methodNode->getMethod();
4664 methodBuilder.
setDebugInfo({irModule->modulePath, methodAst.getLine(), methodAst.getColumn()});
4665 methodBuilder.
attrs = getFunctionAttributes(methodAst.attrs);
4666 methodBuilder.
attrs.insert(IRFunctionDefinition::FunctionAttrs::Preserve);
4670 if (std::find(methodBuilder.
attrs.begin(), methodBuilder.
attrs.end(), IRFunctionDefinition::FunctionAttrs::Static) ==
4671 methodBuilder.
attrs.end()) {
4672 methodBuilder.
addArgument(L
"this", concreteStructType);
4675 for (
auto &arg : methodAst.getArgs().get()) {
4676 auto specializedArgType =
managedPtr(parseTypeSpec(arg->spec));
4677 methodBuilder.
addArgument(arg->getId().get().strVal, specializedArgType);
4678 specializedArgTypes.push_back(specializedArgType);
4681 auto uniq = getFuncUniqueNameStr(specializedArgTypes);
4682 auto baseMethodName = methodAst.getName().getId().get().strVal;
4685 methodBuilder.
setName(specializedStructName + L
"::" + baseMethodName + uniq);
4687 auto func = methodBuilder.
yield();
4688 auto funcIndex = irModule->functionTable.put_create(func->name, func);
4689 irModule->functionOverloadIndexies[specializedStructName + L
"::" + baseMethodName].emplace_back(funcIndex);
4694 visit(methodAst.block,
true);
4697 virtualMethodMap[baseMethodName + getFuncUniqueNameStr(specializedArgTypes,
true)] = {
4698 baseMethodName + uniq,
managedPtr(
IRValueType{IRValueType::valueType::virtualMethod, currentModuleIndex, funcIndex})};
4700 for (
auto &method : targetInterface->methodMap) {
4701 yoi_assert(virtualMethodMap.contains(method.first),
4704 "Interface method not found in implementation: " +
wstring2string(method.first));
4705 builder.
addVirtualMethod(virtualMethodMap[method.first].first, virtualMethodMap[method.first].second);
4710 targetedModule->interfaceImplementationTable[implIndex] = builder.
yield();
4717 const yoi::vec<std::shared_ptr<IRValueType>> &argTypes,
4719 const std::shared_ptr<IRInterfaceInstanceDefinition> &interfaceContext) {
4723 auto exactMangledName = baseName + getFuncUniqueNameStr(argTypes);
4725 if (interfaceContext->methodMap.contains(exactMangledName)) {
4727 result.
functionIndex = interfaceContext->methodMap.getIndex(exactMangledName);
4729 if (std::find(result.
function->attrs.begin(), result.
function->attrs.end(), IRFunctionDefinition::FunctionAttrs::Variadic) !=
4738 auto findVariadicMatch = [&](
const yoi::wstr &funcKey) {
4739 auto func = interfaceContext->methodMap[funcKey];
4740 const auto ¶mTypes = func->argumentTypes;
4741 size_t fixedParamCount = paramTypes.size() - 1;
4742 if (std::find(func->attrs.begin(), func->attrs.end(), IRFunctionDefinition::FunctionAttrs::Variadic) != func->attrs.end()) {
4743 if (argTypes.size() >= fixedParamCount) {
4744 bool fixedMatch =
true;
4745 for (
size_t i = 0; i < fixedParamCount; ++i) {
4746 if (*paramTypes[i] != *argTypes[i]) {
4752 result.
functionIndex = interfaceContext->methodMap.getIndex(funcKey);
4762 if (argTypes.size() != fixedParamCount + 1)
4765 for (
size_t i = 0; i < fixedParamCount; ++i) {
4766 if (!canCastTo(argTypes[i], paramTypes[i])) {
4771 result.
functionIndex = interfaceContext->methodMap.getIndex(funcKey);
4783 if (!interfaceContext->functionOverloadIndexies.contains(baseName))
4786 for (
const auto &it : interfaceContext->functionOverloadIndexies[baseName]) {
4787 if (findVariadicMatch(interfaceContext->methodMap.getKey(it)))
4796 moduleContextStack.emplace(
moduleContext, currentModuleIndex);
4799 currentModuleIndex = moduleIndex;
4802 void visitor::popModuleContext() {
4805 currentModuleIndex = moduleContextStack.top().second;
4807 moduleContextStack.pop();
4814 auto currentTerm = *it;
4816 if (objectOnStackType->isArrayType() || objectOnStackType->isDynamicArrayType()) {
4817 const auto &dimensions = objectOnStackType->dimensions;
4820 for (
long long i =
static_cast<long long>(dimensions.size()) - 2; i >= 0; --i) {
4821 strides[i] = strides[i + 1] * dimensions[i + 1];
4828 while (it != end && (*it)->isSubscript()) {
4829 yoi_assert(currentDim < dimensions.size(), (*it)->getLine(), (*it)->getColumn(),
"Too many indices for array dimension.");
4835 "Array subscript index must be an integer or unsigned integer.");
4843 yoi_assert(currentDim == dimensions.size() || (isStoreOp && isLastTerm),
4844 currentTerm->getLine(),
4845 currentTerm->getColumn(),
4846 "Partial array access is not a loadable value. Not enough indices provided.");
4848 if (isStoreOp && isLastTerm) {
4852 auto elementType =
managedPtr(objectOnStackType->getElementType());
4857 if (isLastTerm && isStoreOp) {
4862 visit(currentTerm->expr);
4866 if (array->type == IRValueType::valueType::structObject)
4867 overload = resolveOverloadExtern(
4869 {value, array, index},
4870 array->typeAffiliateModule,
4873 yoi_assert(overload.
found(), currentTerm->getLine(), currentTerm->getColumn(),
"No matching overload found for operator[].");
4875 !overload.
isVariadic, currentTerm->getLine(), currentTerm->getColumn(),
"Variadic operator[] overloading is not supported.");
4879 tryCastTo(overload.
function->argumentTypes.back());
4881 tryCastTo(overload.
function->argumentTypes.front());
4895 visit(currentTerm->expr);
4896 handleBinaryOperatorOverload(L
"operator[]", currentTerm->expr);
4904 for (
auto &arg :
typeSpec->args->types) {
4905 argTypes.push_back(
managedPtr(parseTypeSpec(arg)));
4913 const std::shared_ptr<IRValueType> &returnType) {
4914 auto callableInterfaceName = L
"callable" + getFuncUniqueNameStr(parameterTypes);
4915 callableInterfaceName += getTypeSpecUniqueNameStr(returnType);
4918 ->interfaceTable.contains(callableInterfaceName)) {
4921 ->interfaceTable.getIndex(callableInterfaceName);
4926 ->interfaceTable.put_create(callableInterfaceName, {});
4929 for (
auto &arg : parameterTypes) {
4930 argTypes.emplace_back(L
"arg", arg);
4933 builder.
setName(callableInterfaceName);
4935 L
"operator()" + getFuncUniqueNameStr(parameterTypes),
4940 return interfaceIndex;
4946 if (irModule->structTable.contains(structName)) {
4949 auto index = irModule->structTable.getIndex(structName);
4950 auto structType =
managedPtr(
IRValueType{IRValueType::valueType::structObject, currentModuleIndex, index});
4957 auto funcName = structName + L
"::constructor" + getFuncUniqueNameStr(argTypes);
4959 irModule->functionTable.getIndex(funcName), argTypes.size(), structType,
false,
true, currentModuleIndex);
4963 auto structIndex = irModule->structTable.put_create(structName,
nullptr);
4965 auto structType =
managedPtr(
IRValueType{IRValueType::valueType::structObject, currentModuleIndex, structIndex});
4974 callableBuilder.
attrs.insert(IRFunctionDefinition::FunctionAttrs::Preserve);
4977 auto argType =
managedPtr(parseTypeSpec(i->spec));
4978 callableBuilder.
addArgument(i->id->node.strVal, argType);
4979 argTypes.push_back(argType);
4983 callableBuilder.
setName(structName + L
"::operator()" + getFuncUniqueNameStr(argTypes));
4984 auto callableFunc = callableBuilder.
yield();
4985 auto callableFuncIndex = irModule->functionTable.put_create(callableFunc->name, callableFunc);
4986 irModule->functionOverloadIndexies[structName + L
"::operator()"].push_back(callableFuncIndex);
4987 builder.addMethod(L
"operator()" + getFuncUniqueNameStr(argTypes), callableFuncIndex);
4998 capturedVar->addAttribute(IRValueType::ValueAttr::Nullable);
4999 argTypes.push_back(
managedPtr(*capturedVar));
5000 builder.addField(i->node.strVal,
managedPtr(*capturedVar));
5005 constructorBuilder.
addArgument(L
"this", structType);
5006 constructorBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Constructor);
5007 constructorBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::NoRawAndNullOptimization);
5008 for (
yoi::indexT i = 0; i < argTypes.size(); ++i) {
5012 constructorBuilder.
setName(structName + L
"::constructor" + getFuncUniqueNameStr(argTypes));
5013 auto constructorFunc = constructorBuilder.
yield();
5014 auto constructorFuncIndex = irModule->functionTable.put_create(constructorFunc->name, constructorFunc);
5015 irModule->functionOverloadIndexies[structName + L
"::constructor"].push_back(constructorFuncIndex);
5016 builder.addMethod(L
"constructor" + getFuncUniqueNameStr(argTypes), constructorFuncIndex);
5019 irModule->structTable[structIndex] = builder.yield();
5039 {IROperand::operandType::localVar, i + 1},
5056 std::pair<yoi::indexT, std::pair<yoi::indexT, yoi::indexT>> visitor::createCallableImplementationForLambda(
5057 const std::shared_ptr<IRStructDefinition> &lambda,
yoi::indexT lambdaStructIndex,
yoi::indexT moduleIndex) {
5061 for (
auto &[key, value] : lambda->nameIndexMap) {
5062 if (key.starts_with(L
"operator()")) {
5064 callableIndex = value.index;
5070 for (
yoi::indexT i = 1; i < callableFunc->argumentTypes.size(); ++i) {
5071 argTypes.push_back(callableFunc->argumentTypes[i]);
5073 auto returnType = callableFunc->returnType;
5078 if (irModule->interfaceImplementationTable.contains(interfaceImpl)) {
5080 return {irModule->interfaceImplementationTable.getIndex(interfaceImpl), interfaceSrc};
5085 .
setImplStructIndex({IRValueType::valueType::structObject, moduleIndex, lambdaStructIndex})
5086 .setName(interfaceImpl)
5088 auto implIndex = irModule->interfaceImplementationTable.put_create(interfaceImpl, builder.
yield());
5090 return {implIndex, interfaceSrc};
5096 bool satisfied =
true;
5100 case lexer::token::tokenKind::integer:
5102 case lexer::token::tokenKind::integer:
5104 case lexer::token::tokenKind::decimal:
5107 panic(lhs.
line, lhs.
col,
"Cannot convert marco value to comparable type.");
5109 case lexer::token::tokenKind::decimal:
5111 case lexer::token::tokenKind::integer:
5112 return {lhs,
lexer::token{0, 0, lexer::token::tokenKind::decimal,
static_cast<double>(rhs.basicVal.vUint)}};
5113 case lexer::token::tokenKind::decimal:
5116 panic(lhs.
line, lhs.
col,
"Cannot convert marco value to comparable type.");
5118 case lexer::token::tokenKind::string:
5120 case lexer::token::tokenKind::string:
5122 case lexer::token::tokenKind::boolean:
5123 return {
lexer::token{0, 0, lexer::token::tokenKind::integer,
static_cast<uint64_t
>(lhs.
strVal == rhs.strVal)}, rhs};
5125 panic(lhs.
line, lhs.
col,
"Cannot convert marco value to comparable type.");
5127 case lexer::token::tokenKind::boolean:
5129 case lexer::token::tokenKind::string:
5130 return {
lexer::token{0, 0, lexer::token::tokenKind::integer,
static_cast<uint64_t
>(lhs.
strVal == rhs.strVal)}, rhs};
5131 case lexer::token::tokenKind::boolean:
5134 panic(lhs.
line, lhs.
col,
"Cannot convert marco value to comparable type.");
5141 auto [lhsTok, rhsTok] = convertToSameType(lhs, rhs);
5143 case lexer::token::tokenKind::equal:
5144 return lhsTok.basicVal.vUint == rhsTok.basicVal.vUint && lhsTok.strVal == rhsTok.strVal;
5145 case lexer::token::tokenKind::notEqual:
5146 return lhsTok.basicVal.vUint != rhsTok.basicVal.vUint || lhsTok.strVal != rhsTok.strVal;
5147 case lexer::token::tokenKind::greaterThan:
5148 switch (lhsTok.kind) {
5149 case lexer::token::tokenKind::integer:
5150 return lhsTok.basicVal.vUint > rhsTok.basicVal.vUint;
5151 case lexer::token::tokenKind::decimal:
5152 return lhsTok.basicVal.vDeci > rhsTok.basicVal.vDeci;
5154 panic(lhs.
line, lhs.
col,
"Cannot compare marco value.");
5156 case lexer::token::tokenKind::greaterEqual:
5157 switch (lhsTok.kind) {
5158 case lexer::token::tokenKind::integer:
5159 return lhsTok.basicVal.vUint >= rhsTok.basicVal.vUint;
5160 case lexer::token::tokenKind::decimal:
5161 return lhsTok.basicVal.vDeci >= rhsTok.basicVal.vDeci;
5163 panic(lhs.
line, lhs.
col,
"Cannot compare marco value.");
5165 case lexer::token::tokenKind::lessThan:
5166 switch (lhsTok.kind) {
5167 case lexer::token::tokenKind::integer:
5168 return lhsTok.basicVal.vUint < rhsTok.basicVal.vUint;
5169 case lexer::token::tokenKind::decimal:
5170 return lhsTok.basicVal.vDeci < rhsTok.basicVal.vDeci;
5172 panic(lhs.
line, lhs.
col,
"Cannot compare marco value.");
5174 case lexer::token::tokenKind::lessEqual:
5175 switch (lhsTok.kind) {
5176 case lexer::token::tokenKind::integer:
5177 return lhsTok.basicVal.vUint <= rhsTok.basicVal.vUint;
5178 case lexer::token::tokenKind::decimal:
5179 return lhsTok.basicVal.vDeci <= rhsTok.basicVal.vDeci;
5181 panic(lhs.
line, lhs.
col,
"Cannot compare marco value.");
5189 for (
auto &i : desc->
pairs) {
5190 bool currentSatisfied =
false;
5191 auto &marco = i->identifier.strVal;
5193 auto &value = marcos[marco];
5194 auto tok =
lexer(std::wstringstream(value)).
scan();
5195 tok.
kind = tok.kind == lexer::token::tokenKind::identifier ? lexer::token::tokenKind::string : tok.kind;
5197 auto &targetValue = i->rhs;
5198 switch (i->constraint.kind) {
5199 case lexer::token::tokenKind::equal: {
5200 currentSatisfied = tok.basicVal.vUint == targetValue.basicVal.vUint && tok.strVal == targetValue.strVal;
5203 case lexer::token::tokenKind::notEqual: {
5204 currentSatisfied = tok.basicVal.vUint != targetValue.basicVal.vUint || tok.strVal != targetValue.strVal;
5207 case lexer::token::tokenKind::greaterThan:
5208 case lexer::token::tokenKind::greaterEqual:
5209 case lexer::token::tokenKind::lessThan:
5210 case lexer::token::tokenKind::lessEqual: {
5211 currentSatisfied = compare(tok, targetValue, i->constraint.kind);
5217 "Unsupported marco constraint kind: " + std::string{magic_enum::enum_name(i->constraint.kind)});
5221 if (!currentSatisfied) {
5234 auto rhs = parseTypeSpec(typeAlias->
rhs);
5235 if (irModule->typeAliases.contains(aliasName)) {
5238 irModule->typeAliases[aliasName] = rhs;
5245 switch (enumDef->getUnderlyingType()) {
5246 case IREnumerationType::UnderlyingType::I8:
5248 case IREnumerationType::UnderlyingType::I16:
5250 case IREnumerationType::UnderlyingType::I64:
5262 idx = node->value.kind != lexer::token::tokenKind::unknown ? node->value.basicVal.vInt : idx;
5263 builder.
addValue(node->name->get().strVal, idx++);
5265 auto enumType = builder.
yield();
5266 auto enumIndex = irModule->enumerationTable.put_create(enumType->name, enumType);
5267 auto underlyingEnumType = mapEnumTypeToBasicType(currentModuleIndex, enumIndex);
5275 while (it + 1 != func->
name->
getTerms().end() && (targetModule = isModuleName((*it)->id, lastModule)) != lastModule) {
5277 lastModule = targetModule;
5281 enum class CreateStrategy { Plain, IncludeThis } strategy{CreateStrategy::Plain};
5286 auto nameNode = *(it);
5287 auto funcNameNode = *(it + 1);
5288 std::shared_ptr<IRStructDefinition> structType;
5290 if (nameNode->hasTemplateArg() && targetedModule->structTemplateAsts.contains(nameNode->getId().node.strVal)) {
5291 auto concreteTypes = parseTemplateArgs(nameNode->getArg());
5292 auto specializedIndex = specializeStructTemplate(
5293 nameNode->id->node.strVal, concreteTypes, targetedModule->templateImplAsts[nameNode->getId().node.strVal], targetModule);
5294 structType = targetedModule->structTable[specializedIndex];
5296 }
else if (targetedModule->structTable.contains(nameNode->getId().node.strVal)) {
5297 structType = targetedModule->structTable[nameNode->getId().node.strVal];
5299 panic(nameNode->getLine(), nameNode->getColumn(),
"Undefined struct: " +
yoi::wstring2string(nameNode->getId().node.strVal));
5302 yoi::wstr baseName = structType->name + L
"::" + funcNameNode->getId().node.strVal;
5304 yoi_assert(targetedModule->functionOverloadIndexies.contains(baseName),
5305 funcNameNode->getLine(),
5306 funcNameNode->getColumn(),
5313 argTypes.push_back(
managedPtr(parseTypeSpec(arg)));
5315 yoi::wstr fullFuncName = baseName + getFuncUniqueNameStr(argTypes);
5316 yoi_assert(targetedModule->functionTable.contains(fullFuncName),
5317 funcNameNode->getLine(),
5318 funcNameNode->getColumn(),
5319 "No matching function overload found with explicit param types: " +
yoi::wstring2string(fullFuncName));
5320 yoi_assert(targetedModule->functionTable[fullFuncName]->hasAttribute(IRFunctionDefinition::FunctionAttrs::Static),
5321 funcNameNode->getLine(),
5322 funcNameNode->getColumn(),
5324 funcIndex = targetedModule->functionTable.getIndex(fullFuncName);
5325 strategy = CreateStrategy::Plain;
5328 yoi_assert(targetedModule->functionOverloadIndexies[baseName].size() == 1,
5329 funcNameNode->getLine(),
5330 funcNameNode->getColumn(),
5331 "Inplicit specification on multiple overloads of method: " +
yoi::wstring2string(baseName));
5332 auto candidateIndex = targetedModule->functionOverloadIndexies[baseName][0];
5333 yoi_assert(targetedModule->functionTable[candidateIndex]->hasAttribute(IRFunctionDefinition::FunctionAttrs::Static),
5334 funcNameNode->getLine(),
5335 funcNameNode->getColumn(),
5337 funcIndex = candidateIndex;
5338 strategy = CreateStrategy::Plain;
5342 auto funcNameNode = *(it);
5343 yoi_assert(targetedModule->functionOverloadIndexies.contains(funcNameNode->getId().node.strVal),
5344 funcNameNode->getLine(),
5345 funcNameNode->getColumn(),
5351 argTypes.push_back(
managedPtr(parseTypeSpec(arg)));
5353 yoi::wstr fullFuncName = funcNameNode->getId().node.strVal + getFuncUniqueNameStr(argTypes);
5354 yoi_assert(targetedModule->functionTable.contains(fullFuncName),
5355 funcNameNode->getLine(),
5356 funcNameNode->getColumn(),
5357 "No matching function overload found with explicit param types: " +
yoi::wstring2string(fullFuncName));
5358 funcIndex = targetedModule->functionTable.getIndex(fullFuncName);
5359 strategy = CreateStrategy::Plain;
5362 yoi_assert(targetedModule->functionOverloadIndexies[funcNameNode->getId().node.strVal].size() == 1,
5363 funcNameNode->getLine(),
5364 funcNameNode->getColumn(),
5365 "Inplicit specification on multiple overloads of function: " +
yoi::wstring2string(funcNameNode->getId().node.strVal));
5366 funcIndex = targetedModule->functionOverloadIndexies[funcNameNode->getId().node.strVal][0];
5367 strategy = CreateStrategy::Plain;
5375 case CreateStrategy::Plain: {
5376 auto funcDef = targetedModule->functionTable[funcIndex];
5377 auto impl = createCallableImplementationForFunction(funcDef, funcIndex, targetModule == -1 ? currentModuleIndex : targetModule,
false);
5378 createCallableInstanceForFunction(impl.first, impl.second, targetModule == -1 ? currentModuleIndex : targetModule,
false);
5381 case CreateStrategy::IncludeThis: {
5394 std::pair<yoi::indexT, std::pair<yoi::indexT, yoi::indexT>> visitor::createCallableImplementationForFunction(
5395 const std::shared_ptr<IRFunctionDefinition> &func,
yoi::indexT funcIndex,
yoi::indexT moduleIndex,
bool hasThis) {
5397 auto objectType = hasThis ? func->argumentTypes[0] :
nullptr;
5400 for (
auto index = hasThis ? 1 : 0; index < func->argumentTypes.size(); index++) {
5401 argTypes.push_back(func->argumentTypes[index]);
5406 auto uniqueName = L
"callableWrapper#" + func->name + getFuncUniqueNameStr(argTypes);
5407 if (targetedModule->structTable.contains(uniqueName)) {
5408 auto interfaceImplName = getInterfaceImplName(
5410 managedPtr(
IRValueType{IRValueType::valueType::structObject, moduleIndex, targetedModule->structTable.getIndex(uniqueName)}));
5411 return {targetedModule->interfaceImplementationTable.getIndex(interfaceImplName), callableInterface};
5414 yoi::indexT structTypeIndex = targetedModule->structTable.put_create(uniqueName, {});
5415 yoi::wstr constructorName = hasThis ? uniqueName + L
"::constructor#" + getTypeSpecUniqueNameStr(objectType) : uniqueName + L
"::constructor#";
5416 yoi::indexT constructorIndex = targetedModule->functionTable.put_create(constructorName, {});
5417 yoi::wstr callableName = uniqueName + L
"::operator()" + getFuncUniqueNameStr(func->argumentTypes);
5418 yoi::indexT callableIndex = targetedModule->functionTable.put_create(callableName, {});
5423 builder.
addField(L
"object_this", objectType);
5426 auto constructorUniqueName = hasThis ? L
"constructor#" + getTypeSpecUniqueNameStr(objectType) : L
"constructor#";
5427 builder.
setName(uniqueName).
addMethod(constructorUniqueName, constructorIndex);
5428 builder.
setName(uniqueName).
addMethod(L
"operator()" + getFuncUniqueNameStr(func->argumentTypes), callableIndex);
5429 targetedModule->structTable[structTypeIndex] = builder.
yield();
5431 auto structType =
managedPtr(
IRValueType{IRValueType::valueType::structObject, moduleIndex, structTypeIndex});
5434 constructorBuilder.
setName(constructorName);
5435 constructorBuilder.
addArgument(L
"this", structType);
5437 constructorBuilder.
addArgument(L
"object_this", objectType);
5440 constructorBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::NoRawAndNullOptimization);
5441 constructorBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Preserve);
5443 targetedModule->functionTable[constructorIndex] = constructorBuilder.
yield();
5445 callableBuilder.
setName(callableName);
5447 for (
yoi::indexT argIndex = hasThis ? 1 : 0; argIndex < func->argumentTypes.size(); argIndex++) {
5449 callableBuilder.
addArgument(L
"param" + std::to_wstring(argIndex), arg);
5452 callableBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Preserve);
5454 targetedModule->functionTable[callableIndex] = callableBuilder.
yield();
5481 for (
yoi::indexT argIndex = hasThis ? 1 : 0; argIndex < func->argumentTypes.size(); argIndex++) {
5482 auto arg = func->argumentTypes[argIndex];
5484 IR::Opcode::load_local, {IROperand::operandType::index, (
yoi::indexT)(argIndex + 1)}, arg, moduleIndex);
5491 auto interfaceImplName = getInterfaceImplName(
5493 managedPtr(
IRValueType{IRValueType::valueType::structObject, moduleIndex, targetedModule->structTable.getIndex(uniqueName)}));
5495 auto interfaceImplIndex = targetedModule->interfaceImplementationTable.put_create(
5498 .setName(interfaceImplName)
5499 .addVirtualMethod(L
"operator()" + getFuncUniqueNameStr(func->argumentTypes),
5501 .setImplInterfaceIndex(callableInterface)
5502 .setImplStructIndex({IRValueType::valueType::structObject, moduleIndex, structTypeIndex})
5505 return {interfaceImplIndex, callableInterface};
5508 void visitor::createCallableInstanceForFunction(
yoi::indexT implIndex,
5509 std::pair<yoi::indexT, yoi::indexT> callableInterfaceIndex,
5512 auto implDef = targetedModule->interfaceImplementationTable[implIndex];
5513 auto structIndex = implDef->implStructIndex;
5519 auto constructorIndex = targetedModule->structTable[std::get<2>(structIndex)]->nameIndexMap.at(L
"constructor#" + getTypeSpecUniqueNameStr(objectPtrOnStack));
5545 auto &
id = i->getVar().id->get().strVal;
5546 auto spec = parseTypeSpec(i->getVar().spec);
5550 irModule->dataStructTable[placeholder] = builder.yield();
5556 auto datastructDef = targetedModule->dataStructTable[datastructIndex];
5560 if (args->
arg.empty()) {
5564 yoi_assert(args->
arg.size() == datastructDef->fieldTypes.size(), args->
getLine(), args->
getColumn(),
"expected " + std::to_string(datastructDef->fields.size()) +
" arguments to construct data struct " +
yoi::wstring2string(datastructDef->name) +
", got " + std::to_string(args->
arg.size()));
5566 visit(args->
arg[i]);
5567 tryCastTo(datastructDef->fieldTypes[i]);
5590 std::shared_ptr<IRValueType> visitor::getGeneratorContext(
const yoi::wstr &funcName,
const std::shared_ptr<IRValueType> &yieldType) {
5592 auto generatorContextName = L
"GeneratorContext#" + funcName;
5593 auto generatorContextIndex = builtinModule->structTable.put_create(generatorContextName, {});
5595 IRValueType::valueType::structObject,
5597 generatorContextIndex
5601 auto generatorConstructorIndex = builtinModule->functionTable.put_create(generatorContextName + L
"::" + generatorConstructorName, {});
5602 auto generatorNextName = L
"next#";
5603 auto generatorNextIndex = builtinModule->functionTable.put_create(generatorContextName + L
"::" + generatorNextName, {});
5606 unsignedDataField->metadata.setMetadata(L
"STRUCT_DATAFIELD",
true);
5609 .
setName(generatorContextName)
5610 .
addField(L
"raw_ctx", unsignedDataField)
5612 .
addMethod(generatorConstructorName, generatorConstructorIndex)
5613 .
addMethod(generatorNextName, generatorNextIndex);
5615 builtinModule->structTable[generatorContextIndex] = builder.
yield();
5618 .
setName(generatorContextName + L
"::" + generatorConstructorName)
5622 .
addAttr(IRFunctionDefinition::FunctionAttrs::Preserve)
5627 .
setName(generatorContextName + L
"::" + generatorNextName)
5630 .
addAttr(IRFunctionDefinition::FunctionAttrs::Preserve)
5634 builtinModule->functionOverloadIndexies[generatorContextName + L
"::constructor"].push_back(generatorConstructorIndex);
5635 builtinModule->functionOverloadIndexies[generatorContextName + L
"::next"].push_back(generatorNextIndex);
5640 builtinModule->functionTable[generatorConstructorIndex]
5654 builtinModule->functionTable[generatorNextIndex]
5674 irModule->identifier,
5679 void visitor::setupTemporaryConceptEvaluationEnvironment(
yoi::indexT moduleIndex,
const yoi::wstr &conceptName,
const std::vector<std::shared_ptr<IRValueType>> &args) {
5684 "Concept type parameter count does not match the number of arguments."
5688 for (
yoi::indexT i = 0; i < args.size(); i += 1) {
5701 node->id->node.strVal,
5721 void visitor::ejectTemporaryConceptEvaluationEnvironment() {
5727 switch (stmt->
kind) {
5735 }
catch (std::runtime_error &e) {
5736 panic(currentDebugInfo.
line, currentDebugInfo.
column,
"Constraint evaluation failed: " + std::string(e.what()));
5746 yoi::indexT currentModIndex = conceptName->
getTerms().size() > 1 ? -1 : currentModuleIndex;
5748 auto term = conceptName->
getTerms()[i];
5749 yoi_assert(!term->hasTemplateArg(), term->getLine(), term->getColumn(),
"template arguments is not allowed except in the last term");
5753 auto name = conceptName->
getTerms().back()->id->node.strVal;
5758 conceptName->
getTerms().back()->arg
5763 auto [conceptDef, parsedTemplateArg] = parseConceptName(stmt);
5767 for (
auto &i : parsedTemplateArg->spec) {
5768 args.push_back(
managedPtr(parseTypeSpec(i->spec)));
5771 setupTemporaryConceptEvaluationEnvironment(currentModuleIndex, conceptDef->name, args);
5773 for (
auto constraint : conceptDef->def->conceptBlock) {
5774 evaluateConstraint(constraint, {
5781 ejectTemporaryConceptEvaluationEnvironment();
5786 const std::shared_ptr<IRValueType> &args) {
5790 checkConceptSatisfaction(stmt);
#define HOSHI_COMPILER_CTX_GLOB_ID_CONST
void pushLoopContext(yoi::indexT breakTarget, yoi::indexT continueTarget)
void invokeOp(yoi::indexT funcIndex, yoi::indexT funcArgsCount, const std::shared_ptr< IRValueType > &returnType, bool externalInvocation=false, yoi::indexT moduleIndex=-1)
Invoke a function with the given arguments.
std::shared_ptr< IRValueType > & getLhsFromTempVarStack()
void newDataStructOp(yoi::indexT structIndex, bool isExternal=false, yoi::indexT moduleIndex=-1)
const IRDebugInfo & getCurrentDebugInfo()
void yieldOp(bool yieldNone=false)
void invokeVirtualOp(yoi::indexT funcIndex, yoi::indexT interfaceIndex, yoi::indexT methodArgsCount, const std::shared_ptr< IRValueType > &returnType, bool externalInvocation=false, yoi::indexT moduleIndex=-1)
void pushOp(IR::Opcode op, const yoi::IROperand &constV)
IRCodeBlock & getCodeBlock(yoi::indexT index)
void storeOp(IR::Opcode op, const yoi::IROperand &operand, yoi::indexT moduleIndex=-1)
void basicCast(const std::shared_ptr< IRValueType > &valType, yoi::indexT insertionPoint, bool lhs=false)
yoi::indexT createCodeBlock()
void constructInterfaceImplOp(const std::pair< yoi::indexT, yoi::indexT > &interfaceId, yoi::indexT interfaceImplIndex, bool isExternal=false, yoi::indexT moduleIndex=-1)
void loadFieldOp(yoi::vec< yoi::IROperand > &accessors, const std::shared_ptr< IRValueType > &expectedType)
std::shared_ptr< IRFunctionDefinition > irFuncDefinition()
void pushTempVar(const std::shared_ptr< IRValueType > &type)
void newArrayOp(const std::shared_ptr< IRValueType > &elementType, const yoi::vec< yoi::indexT > &dimensions, yoi::indexT onstackElementCount)
void loadOp(IR::Opcode op, const yoi::IROperand &source, const std::shared_ptr< IRValueType > &expectedType, yoi::indexT moduleIndex=-1)
void storeFieldOp(yoi::vec< yoi::IROperand > &accessors)
void typeIdOp(const std::shared_ptr< IRValueType > &type)
void invokeImportedOp(yoi::indexT libIndex, yoi::indexT funcIndex, yoi::indexT funcArgsCount, const std::shared_ptr< IRValueType > &returnType)
void newStructOp(yoi::indexT structIndex, bool isExternal=false, yoi::indexT moduleIndex=-1)
yoi::indexT switchCodeBlock(yoi::indexT index)
void discardStateUntil(yoi::indexT stateIndex)
void bindElementsOp(yoi::indexT extractElementCount, ExtractType extractType)
void insert(const IR &ir, yoi::indexT insertionPoint=0xffffffff)
void invokeMethodOp(yoi::indexT funcIndex, yoi::indexT methodArgsCount, const std::shared_ptr< IRValueType > &returnType, bool isStatic, bool externalInvocation=false, yoi::indexT moduleIndex=-1)
void uniqueArithmeticOp(IR::Opcode op)
void loadMemberOp(const yoi::IROperand &memberIndex, const std::shared_ptr< IRValueType > &memberType)
void initializeFieldsOp(yoi::indexT parameterCount)
void jumpOp(yoi::indexT target)
void bindFieldsOp(yoi::indexT extractFieldCount, ExtractType extractType)
void jumpIfOp(IR::Opcode op, yoi::indexT target)
yoi::indexT getCurrentInsertionPoint()
void restoreStateTemporarily()
void invokeDanglingOp(yoi::indexT funcIndex, yoi::indexT funcArgsCount, const std::shared_ptr< IRValueType > &returnType, bool externalInvocation=false, yoi::indexT moduleIndex=-1)
invoke a function with the given arguments, but the last param will be taken as the first param.
void newDynamicArrayOp(const std::shared_ptr< IRValueType > &elementType, yoi::indexT initializerSize=0)
void popFromTempVarStack()
void storeMemberOp(const yoi::IROperand &memberIndex)
void arithmeticOp(IR::Opcode op)
void dynCastOp(const std::shared_ptr< IRValueType > &type)
std::shared_ptr< IRValueType > & getRhsFromTempVarStack()
void retOp(bool returnWithNone=false)
void setDebugInfo(const IRDebugInfo &debugInfo)
void insert(const IR &ir)
Builder & addValue(const yoi::wstr &valueName, yoi::indexT valueIndex)
std::shared_ptr< IREnumerationType > yield()
Builder & setName(const yoi::wstr &name)
yoi::indexT affiliateModule
enum yoi::IRExternEntry::externType type
yoi::indexTable< yoi::wstr, Argument > templateArguments
IRTemplateBuilder & addTemplateArgument(const yoi::wstr &templateName, const std::shared_ptr< IRValueType > &templateType, const yoi::vec< externModuleAccessExpression * > &satisfyConditions={})
externModuleAccessExpression * rhs
vec< mulExpr * > & getTerms()
vec< lexer::token > & getOp()
vec< equalityExpr * > & getTerms()
vec< lexer::token > & getOp()
yoi::vec< yoi::rExpr * > exprs
vec< inCodeBlockStmt * > & getStmts()
union yoi::conceptStmt::ConceptStmtValue value
enum yoi::conceptStmt::Kind kind
defTemplateArg * tempArgs
definitionArguments & getArgs()
definitionArguments & getArgs()
structDefInner & getInner()
vec< defTemplateArgSpec * > & get()
vec< defTemplateArgSpec * > spec
vec< identifierWithTypeSpec * > spec
vec< identifierWithTypeSpec * > & get()
vec< enumerationPair * > values
vec< relationalExpr * > & getTerms()
vec< lexer::token > & getOp()
vec< andExpr * > & getTerms()
vec< lexer::token > & getOp()
yoi::vec< lexer::token > attrs
vec< identifierWithTemplateArg * > & getTerms()
inCodeBlockStmt * afterStmt
inCodeBlockStmt * initStmt
typeSpec & getResultType()
identifierWithDefTemplateArg * id
definitionArguments & getArgs()
identifierWithDefTemplateArg & getId()
yoi::vec< lexer::token > attrs
externModuleAccessExpression * name
unnamedDefinitionArguments * args
union yoi::globalStmt::vValue value
enum yoi::globalStmt::vKind kind
defTemplateArg & getArg() const
bool hasDefTemplateArg() const
identifier & getId() const
identifier & getId() const
bool hasTemplateArg() const
templateArg & getArg() const
bool hasElseBlock() const
innerMethodDef & getMethod()
constructorDef & getConstructor()
bool isConstructor() const
vec< implInnerPair * > & getInner()
externModuleAccessExpression & getStructId()
externModuleAccessExpression * structName
externModuleAccessExpression * interfaceName
vec< lexer::token > & getOp()
vec< exclusiveExpr * > & getTerms()
yoi::indexT put_create(const A &a, const B &b)
typeSpec & getResultType()
definitionArguments & getArgs()
yoi::vec< lexer::token > attrs
identifierWithDefTemplateArg * name
definitionArguments * args
identifierWithDefTemplateArg & getName()
typeSpec & getResultType()
identifierWithTemplateArg & getName()
definitionArguments & getArgs()
yoi::vec< lexer::token > attrs
vec< interfaceDefInnerPair * > & getInner()
identifierWithDefTemplateArg * id
interfaceDefInner & getInner()
vec< yoi::identifier * > captures
definitionArguments * args
vec< letAssignmentPair * > terms
vec< lexer::token > & getOp()
vec< inclusiveExpr * > & getTerms()
vec< logicalAndExpr * > & getTerms()
vec< lexer::token > & getOp()
yoi::vec< marcoPair * > pairs
vec< subscriptExpr * > & getTerms()
yoi::IRBuilder & getIRBuilder()
void pushIRBuilder(const yoi::IRBuilder &builder)
yoi::hoshiModule & getModuleAST()
void pushTemplateBuilder(IRTemplateBuilder &builder)
std::vector< IRTemplateBuilder > & getTemplateBuilders()
void popTemplateBuilder()
std::shared_ptr< yoi::compilerContext > getCompilerContext()
vec< lexer::token > & getOp()
vec< leftExpr * > & getTerms()
invocationArguments * args
externModuleAccessExpression * type
enum yoi::primary::primaryKind kind
bracedInitalizerList * bracedInitalizer
typeIdExpression * typeId
dynCastExpression * dynCast
logicalOrExpr & getExpr() const
vec< shiftExpr * > & getTerms()
vec< lexer::token > & getOp()
externModuleAccessExpression * emae
vec< lexer::token > & getOp()
vec< addExpr * > & getTerms()
innerMethodDecl & getMethod()
constructorDecl & getConstructor()
vec< structDefInnerPair * > & getInner()
identifierWithDefTemplateArg * id
identifierWithDefTemplateArg & getId()
structDefInner & getInner()
vec< subscript * > & getSubscript()
identifierWithTemplateArg * id
vec< templateArgSpec * > spec
vec< templateArgSpec * > & get()
yoi::identifierWithDefTemplateArg * lhs
decltypeExpr * decltypeExpression
yoi::vec< uint64_t > * arraySubscript
externModuleAccessExpression * member
enum yoi::typeSpec::typeSpecKind kind
std::shared_ptr< yoi::IRModule > visit()
visitor(const std::shared_ptr< yoi::moduleContext > &moduleContext, const std::shared_ptr< yoi::IRModule > &irModule, yoi::indexT moduleIndex)
std::shared_ptr< yoi::IRModule > irModule
std::string wstring2string(const std::wstring &v)
std::shared_ptr< T > managedPtr(const T &v)
yoi::wstr realpath(const std::wstring &path)
thread_local yoi::wstr __current_file_path
void yoi_assert(bool condition, yoi::indexT line, yoi::indexT col, const std::string &msg)
Asserts a condition that would be true and throws a runtime_error if it is false.
void set_current_file_path(const std::wstring &path)
void panic(yoi::indexT line, yoi::indexT col, const std::string &msg)
std::string replace_all(std::string str, const std::string &from, const std::string &to)
Builder & setName(const yoi::wstr &name)
Builder & setDebugInfo(const IRDebugInfo &debugInfo)
yoi::vec< std::pair< yoi::wstr, std::shared_ptr< IRValueType > > > argumentTypes
std::shared_ptr< IRFunctionDefinition > yield()
Builder & setName(const yoi::wstr &name)
Builder & addArgument(const yoi::wstr &argumentName, const std::shared_ptr< IRValueType > &argumentType)
Builder & setReturnType(const std::shared_ptr< IRValueType > &returnType)
Builder & addAttr(FunctionAttrs attr)
std::set< FunctionAttrs > attrs
std::shared_ptr< IRInterfaceImplementationDefinition > yield()
Builder & setImplStructIndex(std::tuple< IRValueType::valueType, yoi::indexT, yoi::indexT > implStructIndex)
Builder & setImplInterfaceIndex(const std::pair< yoi::indexT, yoi::indexT > &implInterfaceIndex)
Builder & addVirtualMethod(const yoi::wstr &methodName, const std::shared_ptr< IRValueType > &methodType)
Builder & setName(const yoi::wstr &name)
std::shared_ptr< IRInterfaceInstanceDefinition > yield()
Builder & setName(const yoi::wstr &name)
Builder & addMethod(const yoi::wstr &methodNameOri, const yoi::wstr &methodName, const std::shared_ptr< IRFunctionDefinition > &methodSignature)
std::shared_ptr< IRStructDefinition > yield()
Builder & setStoredTemplateArgs(const yoi::vec< yoi::wstr > ¶mNames, const yoi::vec< std::shared_ptr< IRValueType > > &args)
Builder & addMethod(const yoi::wstr &methodName, yoi::indexT index)
Builder & addTemplateMethodDef(const yoi::wstr &name, yoi::implInnerPair *def)
Builder & addField(const yoi::wstr &fieldName, const std::shared_ptr< IRValueType > &fieldType)
Builder & addTemplateMethodDecl(const yoi::wstr &name, yoi::structDefInnerPair *decl)
Builder & setName(const yoi::wstr &name)
enum yoi::lexer::token::tokenKind kind
union yoi::lexer::token::vBasicValue basicVal
yoi::indexT functionIndex
std::shared_ptr< IRValueType > variadicElementType
yoi::indexT fixedArgCount
std::shared_ptr< IRFunctionDefinition > function
satisfyStmt * satisfyStmt
dataStructDefStmt * dataStructDefStmtVal
enumerationDefinition * enumerationDefVal
interfaceDefStmt * interfaceDefStmtVal
conceptDefinition * conceptDefVal
funcDefStmt * funcDefStmtVal
typeAliasStmt * typeAliasStmtVal
exportDecl * exportDeclVal
structDefStmt * structDefStmtVal
importDecl * importDeclVal
forEachStmt * forEachStmtVal
returnStmt * returnStmtVal
continueStmt * continueStmtVal