int CIEC_ANY_ELEMENTARY::checkTypeSpec(const char *pa_pacValue, const char *pa_pacHashPos){ int nRetVal = -1; CStringDictionary::TStringId nTypeNameId = parseTypeName(pa_pacValue, pa_pacHashPos); if((CStringDictionary::scm_nInvalidStringId != nTypeNameId) && (scm_anTypeNameStringIds[getDataTypeID()] == nTypeNameId)){ nRetVal = static_cast<int>(pa_pacHashPos - pa_pacValue); } return nRetVal; }
const Token& PackageParser::parseAndValidateNewTypeName(EmojicodeChar *name, EmojicodeChar *ns) { bool optional; auto &nameToken = parseTypeName(name, ns, &optional); if (optional) { throw CompilerErrorException(nameToken, "🍬 cannot be declared as type."); } Type type = typeNothingness; if (package_->fetchRawType(*name, *ns, optional, nameToken, &type)) { auto str = type.toString(typeNothingness, true); throw CompilerErrorException(nameToken, "Type %s is already defined.", str.c_str()); } return nameToken; }
Type Type::parseAndFetchType(Type contextType, EmojicodeChar theNamespace, TypeDynamism dynamism, bool *dynamicType){ if (dynamicType) { *dynamicType = false; } if (dynamism & AllowGenericTypeVariables && contextType.type == TT_CLASS && (nextToken()->type == VARIABLE || (nextToken()->value[0] == E_CANDY && nextToken()->nextToken->type == VARIABLE))) { if (dynamicType) { *dynamicType = true; } bool optional = false; const Token *variableToken = consumeToken(); if (variableToken->value[0] == E_CANDY) { variableToken = consumeToken(); optional = true; } auto it = contextType.eclass->ownGenericArgumentVariables.find(variableToken->value); if (it != contextType.eclass->ownGenericArgumentVariables.end()){ Type type = it->second; type.optional = optional; return type; } else { compilerError(variableToken, "No such generic type variable \"%s\".", variableToken->value.utf8CString()); } } else if (nextToken()->value[0] == E_RAT) { const Token *token = consumeToken(); if(!(dynamism & AllowDynamicClassType)){ compilerError(token, "🐀 not allowed here."); } if (dynamicType) { *dynamicType = true; } return contextType; } else if (nextToken()->value[0] == E_GRAPES || (nextToken()->value[0] == E_CANDY && nextToken()->nextToken->type == VARIABLE)) { bool optional = false; if (nextToken()->value[0] == E_CANDY) { consumeToken(); optional = true; } consumeToken(); Type t(TT_CALLABLE, optional); t.arguments = 0; t.genericArguments.push_back(typeNothingness); while (!(nextToken()->type == IDENTIFIER && (nextToken()->value[0] == E_WATERMELON || nextToken()->value[0] == E_RIGHTWARDS_ARROW))) { t.arguments++; t.genericArguments.push_back(parseAndFetchType(contextType, theNamespace, dynamism, nullptr)); } if(nextToken()->type == IDENTIFIER && nextToken()->value[0] == E_RIGHTWARDS_ARROW){ consumeToken(); t.genericArguments[0] = parseAndFetchType(contextType, theNamespace, dynamism, nullptr); } const Token *token = consumeToken(IDENTIFIER); if (token->value[0] != E_WATERMELON) { compilerError(token, "Expected 🍉."); } return t; } else { EmojicodeChar typeName, typeNamespace; bool optional, existent; const Token *token = parseTypeName(&typeName, &typeNamespace, &optional, theNamespace); Type type = fetchRawType(typeName, typeNamespace, optional, token, &existent); if (!existent) { ecCharToCharStack(typeName, nameString); ecCharToCharStack(typeNamespace, namespaceString); compilerError(token, "Could not find type %s in enamespace %s.", nameString, namespaceString); } type.parseGenericArguments(contextType, theNamespace, dynamism, token); return type; } }
void PackageParser::parse() { while (stream_.hasMoreTokens()) { auto documentation = parseDocumentationToken(); auto exported = Attribute<E_EARTH_GLOBE_EUROPE_AFRICA>().parse(&stream_); auto theToken = stream_.consumeToken(IDENTIFIER); switch (theToken.value[0]) { case E_PACKAGE: { exported.disallow(); auto nameToken = stream_.consumeToken(VARIABLE); auto namespaceToken = stream_.consumeToken(IDENTIFIER); auto name = nameToken.value.utf8CString(); package_->loadPackage(name, namespaceToken.value[0], theToken); continue; } case E_CROCODILE: parseProtocol(documentation, theToken, exported.set()); continue; case E_TURKEY: parseEnum(documentation, exported.set()); continue; case E_RADIO: exported.disallow(); package_->setRequiresBinary(); if (strcmp(package_->name(), "_") == 0) { throw CompilerErrorException(theToken, "You may not set 📻 for the _ package."); } continue; case E_CRYSTAL_BALL: { exported.disallow(); if (package_->validVersion()) { throw CompilerErrorException(theToken, "Package version already declared."); } auto major = stream_.consumeToken(INTEGER).value.utf8CString(); auto minor = stream_.consumeToken(INTEGER).value.utf8CString(); uint16_t majori = strtol(major, nullptr, 0); uint16_t minori = strtol(minor, nullptr, 0); delete [] major; delete [] minor; package_->setPackageVersion(PackageVersion(majori, minori)); if (!package_->validVersion()) { throw CompilerErrorException(theToken, "The provided package version is not valid."); } continue; } case E_WALE: { exported.disallow(); EmojicodeChar className, enamespace; bool optional; auto &classNameToken = parseTypeName(&className, &enamespace, &optional); if (optional) { throw CompilerErrorException(classNameToken, "Optional types are not extendable."); } Type type = typeNothingness; if (!package_->fetchRawType(className, enamespace, optional, theToken, &type)) { throw CompilerErrorException(classNameToken, "Class does not exist."); } if (type.type() != TT_CLASS) { throw CompilerErrorException(classNameToken, "Only classes are extendable."); } // Native extensions are allowed if the class was defined in this package. parseClassBody(type.eclass, nullptr, type.eclass->package() == package_); continue; } case E_RABBIT: parseClass(documentation, theToken, exported.set()); continue; case E_SCROLL: { exported.disallow(); auto pathString = stream_.consumeToken(STRING); auto relativePath = pathString.position().file; auto fileString = pathString.value.utf8CString(); char *str = fileString; const char *lastSlash = strrchr(relativePath, '/'); if (lastSlash != nullptr) { const char *directory = strndup(relativePath, lastSlash - relativePath); asprintf(&str, "%s/%s", directory, fileString); delete [] fileString; delete [] directory; } PackageParser(package_, lex(str)).parse(); delete [] str; continue; } default: ecCharToCharStack(theToken.value[0], f); throw CompilerErrorException(theToken, "Unexpected identifier %s", f); break; } } }