Example #1
0
Type ASTSuperMethod::analyse(SemanticAnalyser *analyser, const TypeExpectation &expectation) {
    if (analyser->function()->functionType() != FunctionType::ObjectMethod) {
        throw CompilerError(position(), "Not within an object-context.");
    }

    Class *superclass = analyser->typeContext().calleeType().eclass()->superclass();

    if (superclass == nullptr) {
        throw CompilerError(position(), "Class has no superclass.");
    }

    Function *method = superclass->getMethod(name_, Type(superclass, false), analyser->typeContext(), position());
    calleeType_ = Type(superclass, true);
    return analyser->analyseFunctionCall(&args_, calleeType_, method);
}
Example #2
0
void Application::analyse(Package *underscorePackage) {
    underscorePackage->analyse();

    if (!hasStartFlagFunction()) {
        throw CompilerError(underscorePackage->position(), "No 🏁 block was found.");
    }
}
Example #3
0
void GLShader::compile(Type shaderType, IByteArray const &source)
{
#ifndef LIBGUI_GLES2
    // With non-ES OpenGL, ignore the precision attributes.
    static QByteArray prefix("#ifndef GL_ES\n#define lowp\n#define mediump\n#define highp\n#endif\n");
#endif

    DENG2_ASSERT(shaderType == Vertex || shaderType == Fragment);

    setState(NotReady);

    // Keep a copy of the source for possible recompilation.
    d->compiledSource = source;

    d->type = shaderType;
    d->alloc();

    // Additional predefined symbols for the shader.
    QByteArray predefs;
    if (shaderType == Vertex)
    {
        predefs = QByteArray("#define DENG_VERTEX_SHADER\n");
    }
    else
    {
        predefs = QByteArray("#define DENG_FRAGMENT_SHADER\n");
    }

    // Prepare the shader source. This would be the time to substitute any
    // remaining symbols in the shader source.
    Block src = prefixToSource(source, prefix + predefs);

    char const *srcPtr = src.constData();
    LIBGUI_GL.glShaderSource(d->name, 1, &srcPtr, 0);

    LIBGUI_GL.glCompileShader(d->name);

    // Check the compilation status.
    GLint status;
    LIBGUI_GL.glGetShaderiv(d->name, GL_COMPILE_STATUS, &status);
    if (!status)
    {
        dint32 logSize = 0;
        dint32 count = 0;
        LIBGUI_GL.glGetShaderiv(d->name, GL_INFO_LOG_LENGTH, &logSize);

        Block log(logSize);
        LIBGUI_GL.glGetShaderInfoLog(d->name, logSize, &count, reinterpret_cast<GLchar *>(log.data()));

        throw CompilerError("GLShader::compile",
                            "Compilation of " + String(d->type == Fragment? "fragment" : "vertex") +
                            " shader failed:\n" + log);
    }

    setState(Ready);
}
Example #4
0
Type ASTCallableCall::analyse(SemanticAnalyser *analyser, const TypeExpectation &expectation) {
    Type type = analyser->expect(TypeExpectation(false, false, false), &callable_);
    if (type.type() != TypeType::Callable) {
        throw CompilerError(position(), "Given value is not callable.");
    }
    for (size_t i = 1; i < type.genericArguments().size(); i++) {
        analyser->expectType(type.genericArguments()[i], &args_.arguments()[i - 1]);
    }
    return type.genericArguments()[0];
}
Example #5
0
void ASTRaise::analyse(SemanticAnalyser *analyser) {
    analyser->pathAnalyser().recordIncident(PathAnalyserIncident::Returned);
    if (isOnlyNothingnessReturnAllowed(analyser->function()->functionType())) {
        auto *initializer = dynamic_cast<Initializer *>(analyser->function());
        if (!initializer->errorProne()) {
            throw CompilerError(position(), "Initializer is not declared error-prone.");
        }
        analyser->expectType(initializer->errorType(), &value_);
        return;
    }

    if (analyser->function()->returnType.type() != TypeType::Error) {
        throw CompilerError(position(), "Function is not declared to return a 🚨.");
    }

    boxed_ = analyser->function()->returnType.storageType() == StorageType::Box;

    analyser->expectType(analyser->function()->returnType.genericArguments()[0], &value_);
}
Example #6
0
void Token::validate() const {
    switch (type()) {
        case TokenType::Integer:
            if (value().back() == 'x') {
                throw CompilerError(position(), "Expected a digit after integer literal prefix.");
            }
            break;
        case TokenType::Double:
            if (value().back() == '.') {
                throw CompilerError(position(), "Expected a digit after decimal seperator.");
            }
            break;
        case TokenType::Identifier:
            if (!isValidEmoji(value())) {
                throw CompilerError(position(), "Invalid emoji.");
            }
        default:
            break;
    }
}
Example #7
0
	const uint32_t *stream(const Instruction &instr) const
	{
		// If we're not going to use any arguments, just return nullptr.
		// We want to avoid case where we return an out of range pointer
		// that trips debug assertions on some platforms.
		if (!instr.length)
			return nullptr;

		if (instr.offset + instr.length > spirv.size())
			throw CompilerError("Compiler::stream() out of range.");
		return &spirv[instr.offset];
	}
Example #8
0
void ASTReturn::analyse(SemanticAnalyser *analyser) {
    analyser->pathAnalyser().recordIncident(PathAnalyserIncident::Returned);
    if (analyser->function()->returnType.type() == TypeType::NoReturn) {
        return;
    }

    if (isOnlyNothingnessReturnAllowed(analyser->function()->functionType())) {
        throw CompilerError(position(), "🍎 cannot be used inside an initializer.");
    }

    analyser->expectType(analyser->function()->returnType, &value_);
}
Example #9
0
void ASTSuperinitializer::analyse(SemanticAnalyser *analyser) {
    if (!isSuperconstructorRequired(analyser->function()->functionType())) {
        throw CompilerError(position(), "🐐 can only be used inside initializers.");
    }
    if (analyser->typeContext().calleeType().eclass()->superclass() == nullptr) {
        throw CompilerError(position(), "🐐 can only be used if the class inherits from another.");
    }
    if (analyser->pathAnalyser().hasPotentially(PathAnalyserIncident::CalledSuperInitializer)) {
        analyser->app()->error(CompilerError(position(), "Superinitializer might have already been called."));
    }

    analyser->scoper().instanceScope()->unintializedVariablesCheck(position(), "Instance variable \"", "\" must be "
                                                                   "initialized before calling the superinitializer.");

    Class *eclass = analyser->typeContext().calleeType().eclass();
    auto initializer = eclass->superclass()->getInitializer(name_, Type(eclass, false),
                                                            analyser->typeContext(), position());
    superType_ = Type(eclass->superclass(), false);
    analyser->analyseFunctionCall(&arguments_, superType_, initializer);

    analyser->pathAnalyser().recordIncident(PathAnalyserIncident::CalledSuperInitializer);
}
Example #10
0
Type ASTConditionalAssignment::analyse(SemanticAnalyser *analyser, const TypeExpectation &expectation) {
    Type t = analyser->expect(TypeExpectation(false, false), &expr_);
    if (!t.optional()) {
        throw CompilerError(position(), "Condition assignment can only be used with optionals.");
    }

    t.setReference(false);
    t.setOptional(false);

    auto &variable = analyser->scoper().currentScope().declareVariable(varName_, t, true, position());
    variable.initialize();
    varId_ = variable.id();

    return Type::boolean();
}
Example #11
0
Package* Application::loadPackage(const std::string &name, const SourcePosition &p, Package *requestor) {
    if (auto package = findPackage(name)) {
        if (!package->finishedLoading()) {
            throw CompilerError(p, "Circular dependency detected: ", requestor->name(), " and ", name,
                                " depend on each other.");
        }
        return package;
    }

    auto path = packageDirectory_ + "/" + name + "/header.emojic";
    auto package = std::make_unique<Package>(name, path, this);
    auto rawPtr = package.get();
    packages_.emplace(name, rawPtr);
    packagesLoadingOrder_.emplace_back(std::move(package));
    rawPtr->parse();
    rawPtr->analyse();
    return rawPtr;
}
void CompilerContext::appendInlineAssembly(
	string const& _assembly,
	vector<string> const& _localVariables,
	map<string, string> const& _replacements
)
{
	string replacedAssembly;
	string const* assembly = &_assembly;
	if (!_replacements.empty())
	{
		replacedAssembly = _assembly;
		for (auto const& replacement: _replacements)
			replacedAssembly = boost::algorithm::replace_all_copy(replacedAssembly, replacement.first, replacement.second);
		assembly = &replacedAssembly;
	}

	unsigned startStackHeight = stackHeight();
	auto identifierAccess = [&](
		assembly::Identifier const& _identifier,
		eth::Assembly& _assembly,
		assembly::CodeGenerator::IdentifierContext _context
	) {
		auto it = std::find(_localVariables.begin(), _localVariables.end(), _identifier.name);
		if (it == _localVariables.end())
			return false;
		unsigned stackDepth = _localVariables.end() - it;
		int stackDiff = _assembly.deposit() - startStackHeight + stackDepth;
		if (stackDiff < 1 || stackDiff > 16)
			BOOST_THROW_EXCEPTION(
				CompilerError() <<
				errinfo_comment("Stack too deep, try removing local variables.")
			);
		if (_context == assembly::CodeGenerator::IdentifierContext::RValue)
			_assembly.append(dupInstruction(stackDiff));
		else
		{
			_assembly.append(swapInstruction(stackDiff));
			_assembly.append(Instruction::POP);
		}
		return true;
	};

	solAssert(assembly::InlineAssemblyStack().parseAndAssemble(*assembly, m_asm, identifierAccess), "");
}
Example #13
0
Type ASTCast::analyse(SemanticAnalyser *analyser, const TypeExpectation &expectation) {
    auto type = analyser->analyseTypeExpr(typeExpr_, expectation);

    Type originalType = value_->analyse(analyser, expectation);
    if (originalType.compatibleTo(type, analyser->typeContext())) {
        analyser->app()->error(CompilerError(position(), "Unnecessary cast."));
    }
    else if (!type.compatibleTo(originalType, analyser->typeContext())) {
        auto typeString = type.toString(analyser->typeContext());
        analyser->app()->error(CompilerError(position(), "Cast to unrelated type ", typeString," will always fail."));
    }

    if (type.type() == TypeType::Class) {
        if (!type.genericArguments().empty()) {
            analyser->app()->error(CompilerError(position(), "Class casts with generic arguments are not available."));
        }

        if (originalType.type() == TypeType::Someobject || originalType.type() == TypeType::Class) {
            if (originalType.optional()) {
                throw CompilerError(position(), "Downcast on classes with optionals not possible.");
            }
            castType_ = CastType::ClassDowncast;
            assert(originalType.storageType() == StorageType::Simple && originalType.size() == 1);
        }
        else {
            castType_ = CastType::ToClass;
            assert(originalType.storageType() == StorageType::Box);
        }
    }
    else if (type.type() == TypeType::Protocol && isStatic(typeExpr_->availability())) {
        if (!type.genericArguments().empty()) {
            analyser->app()->error(CompilerError(position(), "Cannot cast to generic protocols."));
        }
        castType_ = CastType::ToProtocol;
        assert(originalType.storageType() == StorageType::Box);
    }
    else if ((type.type() == TypeType::ValueType || type.type() == TypeType::Enum)
             && isStatic(typeExpr_->availability())) {
        castType_ = CastType::ToValueType;
        assert(originalType.storageType() == StorageType::Box);
        type.forceBox();
    }
    else {
        auto typeString = type.toString(analyser->typeContext());
        throw CompilerError(position(), "You cannot cast to ", typeString, ".");
    }

    type.setOptional(true);
    return type;
}
Example #14
0
Type ASTTypeMethod::analyse(SemanticAnalyser *analyser, const TypeExpectation &expectation) {
    auto type = analyser->analyseTypeExpr(callee_, expectation);

    if (type.optional()) {
        analyser->app()->warn(position(), "You cannot call optionals on 🍬.");
    }

    Function *method;
    if (type.type() == TypeType::Class) {
        method = type.typeDefinition()->getTypeMethod(name_, type, analyser->typeContext(), position());
    }
    else if ((type.type() == TypeType::ValueType || type.type() == TypeType::Enum)
             && isStatic(callee_->availability())) {
        method = type.typeDefinition()->getTypeMethod(name_, type, analyser->typeContext(), position());
        valueType_ = true;
    }
    else {
        throw CompilerError(position(), "You can’t call type methods on ", type.toString(analyser->typeContext()), ".");
    }
    return analyser->analyseFunctionCall(&args_, type, method);
}
Example #15
0
void ASTErrorHandler::analyse(SemanticAnalyser *analyser) {
    Type type = analyser->expect(TypeExpectation(false, false), &value_);

    if (type.type() != TypeType::Error) {
        throw CompilerError(position(), "🥑 can only be used with 🚨.");
    }

    analyser->scoper().pushScope();

    auto &var = analyser->scoper().currentScope().declareInternalVariable(type, position());

    analyser->pathAnalyser().beginBranch();
    analyser->scoper().pushScope();

    valueIsBoxed_ = type.storageType() == StorageType::Box;
    valueType_ = type.genericArguments()[1];
    if (valueIsBoxed_) {
        valueType_.forceBox();
    }
    analyser->scoper().currentScope().declareVariableWithId(valueVarName_, valueType_, true, var.id(),
                                                            position()).initialize();
    var.initialize();
    varId_ = var.id();
    valueBlock_.analyse(analyser);
    analyser->scoper().popScope(analyser->app());
    analyser->pathAnalyser().endBranch();

    analyser->pathAnalyser().beginBranch();
    analyser->scoper().pushScope();
    analyser->scoper().currentScope().declareVariableWithId(errorVarName_, type.genericArguments()[0], true, var.id(),
                                                            position()).initialize();

    errorBlock_.analyse(analyser);
    analyser->scoper().popScope(analyser->app());
    analyser->pathAnalyser().endBranch();
    analyser->pathAnalyser().endMutualExclusiveBranches();
    analyser->scoper().popScope(analyser->app());
}
Example #16
0
void ASTForIn::analyse(SemanticAnalyser *analyser) {
    analyser->scoper().pushScope();

    Type iteratee = analyser->expect(TypeExpectation(true, true, false), &iteratee_);
    analyser->popTemporaryScope(iteratee_);

    elementType_ = Type::noReturn();
    if (!analyser->typeIsEnumerable(iteratee, &elementType_)) {
        auto iterateeString = iteratee.toString(analyser->typeContext());
        throw CompilerError(position(), iterateeString, " does not conform to s🔂.");
    }

    iteratee_->setExpressionType(Type(PR_ENUMERATEABLE, false));

    analyser->pathAnalyser().beginBranch();
    iteratorVar_ = analyser->scoper().currentScope().declareInternalVariable(elementType_, position()).id();
    auto &elVar = analyser->scoper().currentScope().declareVariable(varName_, elementType_, true, position());
    elVar.initialize();
    elementVar_ = elVar.id();
    block_.analyse(analyser);
    analyser->scoper().popScope(analyser->app());
    analyser->pathAnalyser().endBranch();
    analyser->pathAnalyser().endUncertainBranches();
}
Example #17
0
 void disallow() const {
     if (found_) {
         throw CompilerError(position_, "Misplaced documentation token.");
     }
 }