Пример #1
0
TEST(TestDeclaration, testLet)
{
    PARSE_STATEMENT(L"let a : Int[] = [1, 2, 3]");
    ValueBindingsPtr c;
    IdentifierPtr id;
    ValueBindingPtr a;
    ArrayLiteralPtr value;
    ArrayTypePtr type;
    TypeIdentifierPtr Int;
    ASSERT_NOT_NULL(c = std::dynamic_pointer_cast<ValueBindings>(root));
    ASSERT_TRUE(c->isReadOnly());
    ASSERT_EQ(1, c->numBindings());
    ASSERT_NOT_NULL(a = c->get(0));
    ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(a->getName()));
    ASSERT_EQ(L"a", id->getIdentifier());
    ASSERT_NOT_NULL(type = std::dynamic_pointer_cast<ArrayType>(a->getDeclaredType()));
    ASSERT_NOT_NULL(Int = std::dynamic_pointer_cast<TypeIdentifier>(type->getInnerType()));
    ASSERT_EQ(L"Int", Int->getName());

    ASSERT_NOT_NULL(value = std::dynamic_pointer_cast<ArrayLiteral>(c->get(0)->getInitializer()));
    ASSERT_EQ(3, value->numElements());
    ASSERT_EQ(L"1", std::dynamic_pointer_cast<IntegerLiteral>(value->getElement(0))->valueAsString);
    ASSERT_EQ(L"2", std::dynamic_pointer_cast<IntegerLiteral>(value->getElement(1))->valueAsString);
    ASSERT_EQ(L"3", std::dynamic_pointer_cast<IntegerLiteral>(value->getElement(2))->valueAsString);

}
Пример #2
0
TEST(TestDeclaration, testVar_Multiple)
{
    PARSE_STATEMENT(L"var x = 0.0, y = 0.0, z = 0.0");
    ValueBindingsPtr vars;
    ValueBindingPtr var;
    IdentifierPtr id;
    FloatLiteralPtr f;

    ASSERT_NOT_NULL(vars = std::dynamic_pointer_cast<ValueBindings>(root));
    ASSERT_TRUE(!vars->isReadOnly());
    ASSERT_EQ(3, vars->numBindings());

    ASSERT_NOT_NULL(var = std::dynamic_pointer_cast<ValueBinding>(vars->get(0)));
    ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(var->getName()));
    ASSERT_EQ(L"x", id->getIdentifier());
    ASSERT_NOT_NULL(f = std::dynamic_pointer_cast<FloatLiteral>(var->getInitializer()));
    ASSERT_EQ(L"0.0", f->valueAsString);


    ASSERT_NOT_NULL(var = std::dynamic_pointer_cast<ValueBinding>(vars->get(1)));
    ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(var->getName()));
    ASSERT_EQ(L"y", id->getIdentifier());
    ASSERT_NOT_NULL(f = std::dynamic_pointer_cast<FloatLiteral>(var->getInitializer()));
    ASSERT_EQ(L"0.0", f->valueAsString);


    ASSERT_NOT_NULL(var = std::dynamic_pointer_cast<ValueBinding>(vars->get(2)));
    ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(var->getName()));
    ASSERT_EQ(L"z", id->getIdentifier());
    ASSERT_NOT_NULL(f = std::dynamic_pointer_cast<FloatLiteral>(var->getInitializer()));
    ASSERT_EQ(L"0.0", f->valueAsString);


}
Пример #3
0
	IdentifierPtr CNodeManager::create(const string& name) {
		auto pos = identMap.find(name);
		if(pos != identMap.end()) { return pos->second; }

		IdentifierPtr res = new Identifier(name);
		res->setManager(this);
		identMap.insert(std::make_pair(name, res));
		return res;
	}
Пример #4
0
void loadDependent(ModulePtr m, vector<string> *sourceFiles, ImportPtr dependent, bool verbose) {
    ImportPtr x = dependent;
    x->module = loadModuleByName(x->dottedName, sourceFiles, verbose);
    switch (x->importKind) {
    case IMPORT_MODULE : {
            ImportModule *im = (ImportModule *)x.ptr();
            IdentifierPtr name = NULL;
            if (im->alias.ptr()) {
                name = im->alias;
                m->importedModuleNames[im->alias->str].module = x->module;
            } else {
                llvm::ArrayRef<IdentifierPtr> parts = im->dottedName->parts;
                if (parts.size() == 1)
                    name = parts[0];
                else if (x->visibility == PUBLIC)
                    error(x->location,
                          "public imports of dotted module paths must have an \"as <name>\" alias");
                llvm::StringMap<ModuleLookup> *node = &m->importedModuleNames;
                for (size_t i = parts.size() - 1; i >= 1; --i) {
                    node = &(*node)[parts[i]->str].parents;
                }
                (*node)[parts[0]->str].module = x->module;
            }
            
            if (name.ptr()) {
                string nameStr(name->str.begin(), name->str.end());
                if (m->importedNames.count(nameStr))
                    error(name, "name imported already: " + nameStr);
                m->importedNames.insert(nameStr);
                m->allSymbols[nameStr].insert(x->module.ptr());
                if (x->visibility == PUBLIC)
                    m->publicSymbols[nameStr].insert(x->module.ptr());
            }
            
            break;
        }
    case IMPORT_STAR :
        break;
    case IMPORT_MEMBERS : {
            ImportMembers *y = (ImportMembers *)x.ptr();
            for (unsigned i = 0; i < y->members.size(); ++i) {
                ImportedMember &z = y->members[i];
                IdentifierPtr alias = z.alias.ptr() ? z.alias : z.name;
                string aliasStr(alias->str.begin(), alias->str.end());
                if (m->importedNames.count(aliasStr))
                    error(alias, "name imported already: " + aliasStr);
                assert(y->aliasMap.count(aliasStr) == 0);
                m->importedNames.insert(aliasStr);
                y->aliasMap[aliasStr] = z.name;
            }
            break;
        }
    default :
            assert(false);
}
}
Пример #5
0
        void Union::
        type (IdentifierPtr const& id)
        {
          if (ctx.trace ()) cerr << "type " << id << endl;

          type_ = 0;

          Name name (id->lexeme ());
          ScopedName from (ctx.scope ().scoped_name ());

          try
          {
            try
            {
              type_ = &resolve<Type> (from, name);

              if (!(dynamic_cast<Enum*> (type_) ||
                    dynamic_cast<Boolean*> (type_) ||
                    dynamic_cast<Char*> (type_) ||
                    dynamic_cast<Wchar*> (type_) ||
                    dynamic_cast<Short*> (type_) ||
                    dynamic_cast<UnsignedShort*> (type_) ||
                    dynamic_cast<Long*> (type_) ||
                    dynamic_cast<UnsignedLong*> (type_) ||
                    dynamic_cast<LongLong*> (type_) ||
                    dynamic_cast<UnsignedLongLong*> (type_)))
              {
                throw WrongType (type_->scoped_name ());
              }

              ctx.tu ().new_edge<ArgumentsWithType> (*type_, now ());
            }
            catch (Resolve const&)
            {
              cerr << ctx.file () << ":" << id->line () << ": error: "
                   << "invalid union declaration" << endl;
              throw;
            }
          }
          catch (NotFound const&)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "no type with name \'" << name
                 << "\' visible from scope \'" << from << "\'" << endl;
          }
          catch (WrongType const&)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "declaration with name \'" << name
                 << "\' visible from scope \'" << from
                 << "\' is not a valid discriminant type" << endl;
          }
        }
Пример #6
0
void Typedef::
begin_unbounded_seq (IdentifierPtr const& id)
{
    if (ctx.trace ())
        cerr << "typedef u-sequence<" << id << ">" << endl;

    define_ = true;
    type_ = 0;
    array_type_ = 0;

    Name name (id->lexeme ());
    ScopedName from (ctx.scope ().scoped_name ());

    try
    {
        try
        {
            Type& t (resolve<Type> (from, name));

            UnboundedSequence& s (
                ctx.tu ().new_node<UnboundedSequence> (
                    ctx.file (), line_));

            ctx.tu ().new_edge<ArgumentsWithType> (t, s);

            type_ = &s;
        }
        catch (Resolve const&)
        {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "invalid sequence declaration" << endl;
            throw;
        }
    }
    catch (NotFound const&)
    {
        cerr << ctx.file () << ":" << id->line () << ": error: "
             << "no type with name \'" << name
             << "\' visible from scope \'" << from << "\'" << endl;
    }
    catch (WrongType const&)
    {
        cerr << ctx.file () << ":" << id->line () << ": error: "
             << "declaration with name \'" << name
             << "\' visible from scope \'" << from
             << "\' is not a type declaration" << endl;

        cerr << ctx.file () << ":" << id->line () << ": error: "
             << "using non-type in sequence specialization is illegal"
             << endl;
    }
}
Пример #7
0
void convertFreeVars(LambdaPtr x, EnvPtr env,
                     const string &closureDataName,
                     vector<string> &freeVars)
{
    EnvPtr env2 = new Env(env);
    for (unsigned i = 0; i < x->formalArgs.size(); ++i) {
        IdentifierPtr name = x->formalArgs[i];
        addLocal(env2, name, name.ptr());
    }
    if (x->formalVarArg.ptr()) {
        addLocal(env2, x->formalVarArg, x->formalVarArg.ptr());
    }
    LambdaContext ctx(x->captureByRef, env, closureDataName, freeVars);
    convertFreeVars(x->body, env2, ctx);
}
Пример #8
0
TEST(TestFunc, testFunc)
{
    PARSE_STATEMENT(L"func stepForward(input: Int) -> Int {"
                       L"return input + 1"
                       L"}");
    FunctionDefPtr func;
    ParametersNodePtr params;
    ParameterNodePtr param;
    TypeIdentifierPtr type;
    CodeBlockPtr cb;
    ReturnStatementPtr ret;
    BinaryOperatorPtr add;
    IdentifierPtr id;
    IntegerLiteralPtr i;
    ASSERT_NOT_NULL(func = std::dynamic_pointer_cast<FunctionDef>(root));
    ASSERT_EQ(L"stepForward", func->getName());
    ASSERT_EQ(1, func->numParameters());
    ASSERT_NOT_NULL(params = func->getParameters(0));
    ASSERT_EQ(1, params->numParameters());
    ASSERT_NOT_NULL(param = params->getParameter(0));
    ASSERT_EQ(ParameterNode::None, param->getAccessibility());
    ASSERT_FALSE(param->isShorthandExternalName());
    ASSERT_FALSE(param->isInout());
    ASSERT_NULL(param->getDefaultValue());
    ASSERT_EQ(L"", param->getExternalName());
    ASSERT_EQ(L"input", param->getLocalName());
    ASSERT_NOT_NULL(type = std::dynamic_pointer_cast<TypeIdentifier>(param->getDeclaredType()));
    ASSERT_EQ(L"Int", type->getName());

    ASSERT_NOT_NULL(type = std::dynamic_pointer_cast<TypeIdentifier>(func->getReturnType()));
    ASSERT_EQ(L"Int", type->getName());

    ASSERT_NOT_NULL(cb = func->getBody());
    ASSERT_EQ(1, cb->numStatements());

    ASSERT_NOT_NULL(ret = std::dynamic_pointer_cast<ReturnStatement>(cb->getStatement(0)));
    ASSERT_NOT_NULL(add = std::dynamic_pointer_cast<BinaryOperator>(ret->getExpression()));
    ASSERT_EQ(L"+", add->getOperator());

    ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(add->getLHS()));
    ASSERT_NOT_NULL(i = std::dynamic_pointer_cast<IntegerLiteral>(add->getRHS()));

    ASSERT_EQ(L"input", id->getIdentifier());
    ASSERT_EQ(L"1", i->valueAsString);


}
Пример #9
0
        void EventTypeFactory::
        raises (IdentifierPtr const& id)
        {
          if (ctx.trace ()) cerr << "raises " << id << endl;

          if (f_ == 0) return;

          Name name (id->lexeme ());
          ScopedName from (ctx.scope ().scoped_name ());

          try
          {
            try
            {
              SemanticGraph::Exception& e (
                resolve<SemanticGraph::Exception> (from, name));

              ctx.tu ().new_edge<Raises> (*f_, e);
            }
            catch (Resolve const&)
            {
              cerr << ctx.file () << ":" << id->line () << ": error: "
                   << "invalid raises declaration" << endl;
              throw;
            }
          }
          catch (NotFound const&)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "no exception with name \'" << name
                 << "\' visible from scope \'" << from << "\'" << endl;
          }
          catch (WrongType const&)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "declaration with name \'" << name
                 << "\' visible from scope \'" << from
                 << "\' is not an exception declaration" << endl;

            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "using non-exception type in raises declaration is "
                 << "illegal" << endl;
          }
        }
Пример #10
0
void Typedef::
begin (IdentifierPtr const& id)
{
    if (ctx.trace ())
        cerr << "typedef " << id << endl;

    define_ = false;
    type_ = 0;
    array_type_ = 0;

    Name name (id->lexeme ());
    ScopedName from (ctx.scope ().scoped_name ());

    try
    {
        try
        {
            type_ = &resolve<Type> (from, name);
        }
        catch (Resolve const&)
        {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "invalid typedef declaration" << endl;
            throw;
        }
    }
    catch (NotFound const&)
    {
        cerr << ctx.file () << ":" << id->line () << ": error: "
             << "no type with name \'" << name
             << "\' visible from scope \'" << from << "\'" << endl;
    }
    catch (WrongType const&)
    {
        cerr << ctx.file () << ":" << id->line () << ": error: "
             << "declaration with name \'" << name
             << "\' visible from scope \'" << from
             << "\' is not a type declaration" << endl;

        cerr << ctx.file () << ":" << id->line () << ": error: "
             << "using non-type in typedef is illegal" << endl;
    }
}
Пример #11
0
        void Component::
        supports (IdentifierPtr const& id)
        {
          if (ctx.trace ()) cerr << " supports " << id << endl;

          Name name (id->lexeme ());
          ScopedName from (ctx.scope ().scoped_name ());

          try
          {
            try
            {
              SemanticGraph::Interface& i (
                resolve<SemanticGraph::Interface> (from, name, Flags::defined));

              check_support (now ().supports_begin (),
                             now ().supports_end (),
                             i);

              ctx.tu ().new_edge<Supports> (now (), i);
              ctx.tu ().new_edge<Extends> (now (), i);
            }
            catch (Resolve const&)
            {
              cerr << ctx.file () << ":" << id->line () << ": error: "
                   << "invalid supports specification" << endl;
              throw;
            }
          }
          catch (NotFound const&)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "no interface with name \'" << name
                 << "\' visible from scope \'" << from << "\'" << endl;
          }
          catch (WrongType const&)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "incompatible type in supports specification" << endl;
          }
          catch (NotDefined const& e)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "attempt to support forward-declared interface "
                 << e.name () << endl;

            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "support of forward-declared interface is illegal"
                 << endl;
          }
          catch (AlreadySupported const& e)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "directly supporting interface \'" << e.name ()
                 << "\' more than once is illegal" << endl;
          }
        }
Пример #12
0
TEST(TestDeclaration, testVar)
{
    PARSE_STATEMENT(L"var currentLoginAttempt = 0");
    ValueBindingsPtr vars;
    ValueBindingPtr var;
    IdentifierPtr id;
    IntegerLiteralPtr i;

    ASSERT_NOT_NULL(vars = std::dynamic_pointer_cast<ValueBindings>(root));
    ASSERT_TRUE(!vars->isReadOnly());
    ASSERT_EQ(1, vars->numBindings());
    ASSERT_NOT_NULL(var = std::dynamic_pointer_cast<ValueBinding>(vars->get(0)));
    ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(var->getName()));
    ASSERT_EQ(L"currentLoginAttempt", id->getIdentifier());

    ASSERT_NOT_NULL(i = std::dynamic_pointer_cast<IntegerLiteral>(var->getInitializer()));
    ASSERT_EQ(L"0", i->valueAsString);


}
Пример #13
0
TEST(TestDeclaration, testVar_Typed)
{
    PARSE_STATEMENT(L"var welcomeMessage: String");
    ValueBindingsPtr vars;
    ValueBindingPtr var;
    IdentifierPtr id;
    TypeIdentifierPtr t;

    ASSERT_NOT_NULL(vars = std::dynamic_pointer_cast<ValueBindings>(root));
    ASSERT_TRUE(!vars->isReadOnly());
    ASSERT_EQ(1, vars->numBindings());
    ASSERT_NOT_NULL(var = std::dynamic_pointer_cast<ValueBinding>(vars->get(0)));
    ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(var->getName()));
    ASSERT_EQ(L"welcomeMessage", id->getIdentifier());

    ASSERT_NOT_NULL(t = std::dynamic_pointer_cast<TypeIdentifier>(var->getDeclaredType()));
    ASSERT_EQ(L"String", t->getName());


}
Пример #14
0
        void Publishes::
        type (IdentifierPtr const& id)
        {
          if (ctx.trace ()) cerr << "publishes " << id;

          type_ = 0;

          Name name (id->lexeme ());
          ScopedName from (ctx.scope ().scoped_name ());

          try
          {
            try
            {
              type_ = &resolve<EventType> (from, name);
            }
            catch (Resolve const&)
            {
              cerr << ctx.file () << ":" << id->line () << ": error: "
                   << "invalid publishes declaration" << endl;
              throw;
            }
          }
          catch (NotFound const&)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "no eventtype with name \'" << name
                 << "\' visible from scope \'" << from << "\'" << endl;
          }
          catch (WrongType const&)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "declaration with name \'" << name
                 << "\' visible from scope \'" << from
                 << "\' is not an eventtype declaration" << endl;

            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "using non-eventtype in publishes declaration is illegal"
                 << endl;
          }
        }
Пример #15
0
TEST(TestDeclaration, testLet_Multiple)
{
    PARSE_STATEMENT(L"let a=[k1 : 1, k2 : 2], b : Int = 2");
    ValueBindingsPtr c;
    ValueBindingPtr b;
    IdentifierPtr id;
    TypeIdentifierPtr Int;
    DictionaryLiteralPtr dict;
    ASSERT_NOT_NULL(c = std::dynamic_pointer_cast<ValueBindings>(root));
    ASSERT_TRUE(c->isReadOnly());
    ASSERT_EQ(2, c->numBindings());
    ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(c->get(0)->getName()));
    ASSERT_EQ(L"a", id->getIdentifier());
    ASSERT_NOT_NULL(dict = std::dynamic_pointer_cast<DictionaryLiteral>(c->get(0)->getInitializer()));
    ASSERT_EQ(2, dict->numElements());

    ASSERT_NOT_NULL(b = c->get(1));
    ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(b->getName()));
    ASSERT_EQ(L"b", id->getIdentifier());
    ASSERT_NOT_NULL(Int = std::dynamic_pointer_cast<TypeIdentifier>(b->getDeclaredType()));
    ASSERT_EQ(L"Int", Int->getName());

}
Пример #16
0
        void EventTypeFactory::
        parameter (IdentifierPtr const& type_id,
                   SimpleIdentifierPtr const& name_id)
        {
          if (ctx.trace ()) cerr << "parameter in " << " "
                                 << type_id << " " << name_id << endl;

          if (f_ == 0) return;

          Name name (type_id->lexeme ());
          ScopedName from (ctx.scope ().scoped_name ());

          try
          {
            try
            {
              Type& t (resolve<Type> (from, name, Flags::complete));

              Parameter& p (
                ctx.tu ().new_node<InParameter> (
                  ctx.file (), name_id->line (), name_id->lexeme ()));

              ctx.tu ().new_edge<Belongs> (p, t);
              ctx.tu ().new_edge<Receives> (*f_, p);
            }
            catch (Resolve const&)
            {
              cerr << ctx.file () << ":" << type_id->line () << ": error: "
                   << "invalid parameter declaration" << endl;
              throw;
            }
          }
          catch (NotFound const&)
          {
            cerr << ctx.file () << ":" << type_id->line () << ": error: "
                 << "no type with name \'" << name
                 << "\' visible from scope \'" << from << "\'" << endl;
          }
          catch (WrongType const&)
          {
            cerr << ctx.file () << ":" << type_id->line () << ": error: "
                 << "declaration with name \'" << name
                 << "\' visible from scope \'" << from
                 << "\' is not a type declaration" << endl;

            cerr << ctx.file () << ":" << type_id->line () << ": error: "
                 << "using non-type as an factory parameter type is "
                 << "illegal" << endl;
          }
          catch (NotComplete const& e)
          {
            cerr << ctx.file () << ":" << type_id->line () << ": error: "
                 << "type \'" << e.name () << "\' is not complete" << endl;
          }
        }
Пример #17
0
        void Member::
        type (IdentifierPtr const& id)
        {
          if (ctx.trace ()) cerr << "member " << id << endl;

          type_ = 0;

          Name name (id->lexeme ());
          ScopedName from (ctx.scope ().scoped_name ());

          try
          {
            try
            {
              // With introduction of CORBA 3.1 we have a new beast:
              // struct with incoplete members which itself becomes
              // incomplete.
              //
              type_ = &resolve<Type> (from, name/*, Flags::complete*/);
            }
            catch (Resolve const&)
            {
              cerr << ctx.file () << ":" << id->line () << ": error: "
                   << "invalid member declaration" << endl;
              throw;
            }

            //@@ I am not handling NotUnique here. For example if
            //   I provide module name as type then the compiler
            //   will ICE. Think about other places it may happen
            //   (attribute, value memebr, typeded, others?).
            //
          }
          catch (NotFound const&)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "no type with name \'" << name
                 << "\' visible from scope \'" << from << "\'" << endl;
          }
          catch (WrongType const&)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "declaration with name \'" << name
                 << "\' visible from scope \'" << from
                 << "\' is not a type declaration" << endl;

            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "using non-type as a member type is illegal" << endl;
          }
          catch (NotComplete const& e)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "type \'" << e.name () << "\' is not complete" << endl;
          }
        }
Пример #18
0
        void Operation::
        raises (IdentifierPtr const& id)
        {
          if (ctx.trace ()) cerr << "raises " << id << endl;

          Name name (id->lexeme ());
          ScopedName from (ctx.scope ().scoped_name ());

          struct OneWay : Resolve {};

          try
          {
            try
            {
              if (one_way_)
                throw OneWay ();

              SemanticGraph::Exception& e (
                resolve<SemanticGraph::Exception> (from, name));

              ctx.tu ().new_edge<Raises> (*op_, e);
            }
            catch (Resolve const&)
            {
              cerr << ctx.file () << ":" << id->line () << ": error: "
                   << "invalid raises declaration" << endl;
              throw;
            }
          }
          catch (NotFound const&)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "no exception with name \'" << name
                 << "\' visible from scope \'" << from << "\'" << endl;
          }
          catch (WrongType const&)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "declaration with name \'" << name
                 << "\' visible from scope \'" << from
                 << "\' is not an exception declaration" << endl;

            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "using non-exception type in raises declaration is "
                 << "illegal" << endl;
          }
          catch (OneWay const&)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "oneway operation may not raise exceptions" << endl;
          }
        }
Пример #19
0
        void Component::
        inherits (IdentifierPtr const& id)
        {
          if (ctx.trace ()) cerr << " inherits " << id << endl;

          Name name (id->lexeme ());
          ScopedName from (ctx.scope ().scoped_name ());

          try
          {
            try
            {
              SemanticGraph::Component& c (
                resolve<SemanticGraph::Component> (from, name, Flags::defined));

              ctx.tu ().new_edge<Inherits> (now (), c);
              ctx.tu ().new_edge<Extends> (now (), c);
            }
            catch (Resolve const&)
            {
              cerr << ctx.file () << ":" << id->line () << ": error: "
                   << "invalid inheritance specification" << endl;
              throw;
            }
          }
          catch (NotFound const&)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "no component with name \'" << name
                 << "\' visible from scope \'" << from << "\'" << endl;
          }
          catch (WrongType const&)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "incompatible type in inheritance specification" << endl;
          }
          catch (NotDefined const& e)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "attempt to inherit from forward-declared component "
                 << e.name () << endl;

            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "inheritance from forward-declared component is illegal"
                 << endl;
          }
        }
Пример #20
0
        void Operation::
        type (IdentifierPtr const& id)
        {
          if (ctx.trace ()) cerr << "operation " << id;

          type_ = 0;

          Name name (id->lexeme ());
          ScopedName from (ctx.scope ().scoped_name ());

          try
          {
            try
            {
              type_ = &resolve<Type> (from, name, Flags::complete);
            }
            catch (Resolve const&)
            {
              cerr << ctx.file () << ":" << id->line () << ": error: "
                   << "invalid operation declaration" << endl;
              throw;
            }
          }
          catch (NotFound const&)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "no type with name \'" << name
                 << "\' visible from scope \'" << from << "\'" << endl;
          }
          catch (WrongType const&)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "declaration with name \'" << name
                 << "\' visible from scope \'" << from
                 << "\' is not a type declaration" << endl;

            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "using non-type as an operation return type is illegal"
                 << endl;
          }
          catch (NotComplete const& e)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "type \'" << e.name () << "\' is not complete" << endl;
          }
        }
Пример #21
0
void SemanticAnalyzer::visitValueBinding(const ValueBindingPtr& node)
{
    PatternPtr name = node->getName();
    //tuple was already exploded in declaration analyzer
    if(name->getNodeType() == NodeType::Tuple)
    {
        validateTupleTypeDeclaration(node);
    }
    if (name->getNodeType() != NodeType::Identifier)
        return;
    if(node->getOwner()->isReadOnly() && !node->getInitializer() && ctx->currentType == nullptr)
    {
        error(node, Errors::E_LET_REQUIRES_INITIALIZER);
        return;
    }
    //handle type inference for temporary variable
    if(node->isTemporary() && node->getInitializer())
    {
        //temporary variable always has an initializer
        TypePtr initializerType;
        TypePtr declaredType = node->getType();

        SCOPED_SET(ctx->contextualType, declaredType);
        node->getInitializer()->accept(this);
        initializerType = node->getInitializer()->getType();
        assert(initializerType != nullptr);

        if(declaredType)
        {
            //it has both type definition and initializer, then we need to check if the initializer expression matches the type annotation
            if(!initializerType->canAssignTo(declaredType))
            {
                error(node, Errors::E_CANNOT_CONVERT_EXPRESSION_TYPE_2, initializerType->toString(), declaredType->toString());
                return;
            }
        }
        else
        {
            node->setType(initializerType);
        }
    }
    

    //add implicitly constructor for Optional
    IdentifierPtr id = static_pointer_cast<Identifier>(node->getName());
    SymbolScope* currentScope = symbolRegistry->getCurrentScope();


    TypePtr declaredType = node->getType() ? node->getType() : lookupType(node->getDeclaredType());
    SCOPED_SET(ctx->contextualType, declaredType);
    if(!declaredType && !node->getInitializer())
    {
        error(node, Errors::E_TYPE_ANNOTATION_MISSING_IN_PATTERN);
        return;
    }
    SymbolPtr sym = currentScope->lookup(id->getIdentifier());
    assert(sym != nullptr);
    SymbolPlaceHolderPtr placeholder = std::dynamic_pointer_cast<SymbolPlaceHolder>(sym);
    assert(placeholder != nullptr);
    if(declaredType)
    {
        placeholder->setType(declaredType);
    }
    ExpressionPtr initializer = node->getInitializer();
    if(initializer)
    {
        placeholder->setFlags(SymbolFlagInitializing, true);
        ExpressionPtr initializer = transformExpression(declaredType, node->getInitializer());
        node->setInitializer(initializer);
        TypePtr actualType = initializer->getType();
        assert(actualType != nullptr);
        if(declaredType)
        {
            if(!Type::equals(actualType, declaredType) && !canConvertTo(initializer, declaredType))
            {
                error(initializer, Errors::E_CANNOT_CONVERT_EXPRESSION_TYPE_2, actualType->toString(), declaredType->toString());
                return;
            }
        }

        if(!declaredType)
            placeholder->setType(actualType);
    }
    assert(placeholder->getType() != nullptr);
    placeholder->setFlags(SymbolFlagInitializing, false);
    //optional type always considered initialized, compiler will make it has a default value nil
    TypePtr symbolType = sym->getType();
    GlobalScope* global = symbolRegistry->getGlobalScope();
    if(initializer || global->isOptional(symbolType) || global->isImplicitlyUnwrappedOptional(symbolType))
        markInitialized(placeholder);

    if (initializer)
        placeholder->setFlags(SymbolFlagHasInitializer, true);
    if(node->isTemporary())
    {
        placeholder->setFlags(SymbolFlagTemporary, true);
        markInitialized(placeholder);
    }

    if(!node->isTemporary())
    {
        //check access control level
        DeclarationType decl = ctx->currentType ? DeclarationTypeProperty : DeclarationTypeVariable;
        declarationAnalyzer->verifyAccessLevel(node->getOwner(), placeholder->getType(), decl, ComponentTypeType);
    }
    if(ctx->currentType && ctx->currentType->getCategory() == Type::Protocol)
    {
        error(node, Errors::E_PROTOCOL_VAR_MUST_BE_COMPUTED_PROPERTY_1);
    }
}
Пример #22
0
static void initializeVariantType(VariantTypePtr t) {
    assert(!t->initialized);

    EnvPtr variantEnv = new Env(t->variant->env);
    {
        const vector<IdentifierPtr> &params = t->variant->params;
        IdentifierPtr varParam = t->variant->varParam;
        assert(params.size() <= t->params.size());
        for (unsigned j = 0; j < params.size(); ++j)
            addLocal(variantEnv, params[j], t->params[j]);
        if (varParam.ptr()) {
            MultiStaticPtr ms = new MultiStatic();
            for (unsigned j = params.size(); j < t->params.size(); ++j)
                ms->add(t->params[j]);
            addLocal(variantEnv, varParam, ms.ptr());
        }
        else {
            assert(params.size() == t->params.size());
        }
    }
    ExprListPtr defaultInstances = t->variant->defaultInstances;
    for (unsigned i = 0; i < defaultInstances->size(); ++i) {
        ExprPtr x = defaultInstances->exprs[i];
        TypePtr memberType = evaluateType(x, variantEnv);
        t->memberTypes.push_back(memberType);
    }

    const vector<InstancePtr> &instances = t->variant->instances;
    for (unsigned i = 0; i < instances.size(); ++i) {
        InstancePtr x = instances[i];
        vector<PatternCellPtr> cells;
        vector<MultiPatternCellPtr> multiCells;
        const vector<PatternVar> &pvars = x->patternVars;
        EnvPtr patternEnv = new Env(x->env);
        for (unsigned j = 0; j < pvars.size(); ++j) {
            if (pvars[j].isMulti) {
                MultiPatternCellPtr multiCell = new MultiPatternCell(NULL);
                multiCells.push_back(multiCell);
                cells.push_back(NULL);
                addLocal(patternEnv, pvars[j].name, multiCell.ptr());
            }
            else {
                PatternCellPtr cell = new PatternCell(NULL);
                cells.push_back(cell);
                multiCells.push_back(NULL);
                addLocal(patternEnv, pvars[j].name, cell.ptr());
            }
        }
        PatternPtr pattern = evaluateOnePattern(x->target, patternEnv);
        if (!unifyPatternObj(pattern, t.ptr()))
            continue;
        EnvPtr staticEnv = new Env(x->env);
        for (unsigned j = 0; j < pvars.size(); ++j) {
            if (pvars[j].isMulti) {
                MultiStaticPtr ms = derefDeep(multiCells[j].ptr());
                if (!ms)
                    error(pvars[j].name, "unbound pattern variable");
                addLocal(staticEnv, pvars[j].name, ms.ptr());
            }
            else {
                ObjectPtr v = derefDeep(cells[j].ptr());
                if (!v)
                    error(pvars[j].name, "unbound pattern variable");
                addLocal(staticEnv, pvars[j].name, v.ptr());
            }
        }
        if (x->predicate.ptr())
            if (!evaluateBool(x->predicate, staticEnv))
                continue;
        TypePtr memberType = evaluateType(x->member, staticEnv);
        t->memberTypes.push_back(memberType);
    }

    RecordPtr reprRecord = getVariantReprRecord();
    vector<ObjectPtr> params;
    for (unsigned i = 0; i < t->memberTypes.size(); ++i)
        params.push_back(t->memberTypes[i].ptr());
    t->reprType = recordType(reprRecord, params);

    t->initialized = true;
}
Пример #23
0
/*
  GRAMMAR OF A PATTERN
 
 ‌ pattern → wildcard-pattern type-annotation opt
 ‌ pattern → identifier-pattern type-annotation opt
 ‌ pattern → value-binding-pattern
 ‌ pattern → tuple-pattern type-annotation opt
 ‌ pattern → enum-case-pattern
 ‌ pattern → type-casting-pattern
 ‌ pattern → expression-pattern
*/
PatternPtr Parser::parsePattern()
{
    Token token;
    expect_next(token);
    if(token.type == TokenType::Identifier)
    {
        switch(token.identifier.keyword)
        {
            //‌ pattern → wildcard-pattern type-annotationopt
            // pattern → identifier-pattern type-annotationopt
            case Keyword::_:
            {
                IdentifierPtr id = nodeFactory->createIdentifier(token.state);
                id->setIdentifier(token.token);
                if((flags & UNDER_CASE) == 0)//type annotation is not parsed when it's inside a let/var
                {
                    if(match(L":"))
                    {
                        TypedPatternPtr ret = nodeFactory->createTypedPattern(*id->getSourceInfo());
                        TypeNodePtr type = parseTypeAnnotation();
                        ret->setDeclaredType(type);
                        ret->setPattern(id);
                        return ret;
                    }
                }
                return id;
            }
            // pattern → value-binding-pattern
            case Keyword::Var:
            case Keyword::Let:
            {
                ValueBindingPatternPtr ret = nodeFactory->createValueBindingPattern(token.state);
                PatternPtr binding = parsePattern();
                if(TypedPatternPtr p = std::dynamic_pointer_cast<TypedPattern>(binding))
                {
                    ret->setBinding(p->getPattern());
                    ret->setDeclaredType(p->getDeclaredType());
                }
                else
                {
                    ret->setBinding(binding);
                }
                ret->setReadOnly(token.identifier.keyword == Keyword::Let);

                return ret;
            }
            default:
                break;
        }
    }
    
    restore(token);
    if(token.type == TokenType::OpenParen)
    {
        //pattern → tuple-pattern type-annotation opt
        TuplePtr ret = std::static_pointer_cast<Tuple>(parseTuple());
        if(flags & (UNDER_LET | UNDER_VAR))
        {
            //type-annotation only exists under let/var statement
            if(match(L":"))
            {
                TypeNodePtr type = parseTypeAnnotation();
                TypedPatternPtr pattern = nodeFactory->createTypedPattern(*ret->getSourceInfo());
                pattern->setDeclaredType(type);
                pattern->setPattern(ret);
                return pattern;
            }
        }
        return ret;
    }
    if(this->flags & UNDER_SWITCH_CASE)
    {
        //the following patterns are only exists in switch/case statement
        // pattern → enum-case-pattern
        if(token.type == TokenType::Attribute || token == L".")
        {
            return parseEnumPattern();
        }
        // pattern → type-casting-pattern
        if(token.getKeyword() == Keyword::Is)
        {
            return parseTypeCastingPattern();
        }
    }
    //‌ pattern → expression-pattern
    PatternPtr ret = parseExpression();
    if(this->flags & UNDER_SWITCH_CASE)
    {
        if(predicate(L"as"))
        {
            restore(token);
            ret = NULL;
            return parseTypeCastingPattern();
        }
    }
    return ret;
}
Пример #24
0
void NodeSerializer::visitIdentifier(const IdentifierPtr& node)
{
    append(node->getIdentifier());
}
Пример #25
0
/*
  GRAMMAR OF A VARIABLE DECLARATION
 
 ‌ variable-declaration → variable-declaration-head pattern-initializer-list
 ‌ variable-declaration → variable-declaration-head variable-name type-annotation code-block
 ‌ variable-declaration → variable-declaration-head variable-name type-annotation getter-setter-block
  variable-declaration → variable-declaration-head variable-name type-annotation getter-setter-keyword-block
 ‌ variable-declaration → variable-declaration-head variable-name type-annotation initializer opt willSet-didSet-block
 ‌ variable-declaration-head → attributes opt declaration-specifiers opt var
 ‌ variable-name → identifier
*/
DeclarationPtr Parser::parseVar(const std::vector<AttributePtr>& attrs, int specifiers)
{

    Token token;
    expect(Keyword::Var, token);
    Flags flags(this, UNDER_VAR);
    //try read it as pattern-initializer-list
    ValueBindingsPtr ret = nodeFactory->createValueBindings(token.state);
    ret->setReadOnly(false);
    ret->setAttributes(attrs);
    ret->setSpecifiers(specifiers);
    ValueBindingPtr var = parseVariableDeclaration();
    var->setSpecifiers(specifiers);
    ret->add(var);
    if(predicate(L","))
    {
        while(match(L","))
        {
            var = parseVariableDeclaration();
            var->setSpecifiers(specifiers);
            ret->add(var);
        }
        return ret;
    }

    if(!match(L"{"))
        return ret;
    peek(token);
    IdentifierPtr name = std::dynamic_pointer_cast<Identifier>(var->getName());
    tassert(token, name != nullptr, Errors::E_GETTER_SETTER_CAN_ONLY_BE_DEFINED_FOR_A_SINGLE_VARIABLE, L"");


    ComputedPropertyPtr prop = nodeFactory->createComputedProperty(*var->getSourceInfo());
    prop->setAttributes(attrs);
    prop->setSpecifiers(specifiers);
    prop->setTypeAttributes(var->getTypeAttributes());
    prop->setName(name->getIdentifier());
    prop->setDeclaredType(var->getDeclaredType());
    prop->setInitializer(var->getInitializer());
    var = nullptr;
    ret = nullptr;

    if(token.type != TokenType::CloseBrace)
    {
        Flags flags(this, SUPPRESS_TRAILING_CLOSURE);
        switch(token.getKeyword())
        {
            case Keyword::Get:
            case Keyword::Set:
                if(this->flags & UNDER_PROTOCOL)
                {
                    // variable-declaration → variable-declaration-head variable-name type-annotation getter-setter-keyword-block
                    //no code block for getter/setter for protocol
                    std::pair<CodeBlockPtr, CodeBlockPtr> r = parseGetterSetterKeywordBlock();
                    prop->setGetter(r.first);
                    prop->setSetter(r.second);
                }
                else
                {
                    //  variable-declaration → variable-declaration-head variable-name type-annotation getter-setter-block
                    std::pair<CodeBlockPtr, std::pair<std::wstring, CodeBlockPtr> > r = parseGetterSetterBlock();
                    prop->setGetter(r.first);
                    prop->setSetterName(r.second.first);
                    prop->setSetter(r.second.second);
                }
                break;
            case Keyword::WillSet:
            case Keyword::DidSet:
                //  variable-declaration → variable-declaration-head variable-name type-annotation initializer opt willSet-didSet-block
                parseWillSetDidSetBlock(prop);
                break;
            default:
                //‌ variable-declaration → variable-declaration-head variable-name type-annotation code-block
                CodeBlockPtr getter = nodeFactory->createCodeBlock(token.state);
                prop->setGetter(getter);
                do
                {
                    StatementPtr st = parseStatement();
                    getter->addStatement(st);
                }while(!predicate(L"}"));
                break;
        }
        
    }
    expect(L"}");
    return prop;
}
Пример #26
0
        void Interface::
        inherits (IdentifierPtr const& id)
        {
          if (ctx.trace ()) cerr << " inherits " << id << endl;

          Name name (id->lexeme ());
          ScopedName from (ctx.scope ().scoped_name ());

          try
          {
            try
            {
              SemanticGraph::Interface& i (
                resolve<SemanticGraph::Interface> (from, name, Flags::defined));

              switch (qualifier_)
              {
              case Qualifier::abstract:
                {
                  if (dynamic_cast<AbstractInterface*> (&i)) break;

                  throw WrongType (i.scoped_name ());
                }
              case Qualifier::unconstrained:
                {
                  if (dynamic_cast<UnconstrainedInterface*> (&i) ||
                      dynamic_cast<AbstractInterface*> (&i)) break;

                  throw WrongType (i.scoped_name ());
                }
              default: break;
              }

              check_inheritance (now ().inherits_begin (),
                                 now ().inherits_end (),
                                 i);

              ctx.tu ().new_edge<Inherits> (now (), i);
              ctx.tu ().new_edge<Extends> (now (), i);
            }
            catch (Resolve const&)
            {
              cerr << ctx.file () << ":" << id->line () << ": error: "
                   << "invalid inheritance specification" << endl;
              throw;
            }
          }
          catch (NotFound const&)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "no interface with name \'" << name
                 << "\' visible from scope \'" << from << "\'" << endl;
          }
          catch (WrongType const&)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "incompatible type in inheritance specification" << endl;
          }
          catch (NotDefined const& e)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "attempt to inherit from forward-declared interface "
                 << e.name () << endl;

            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "inheritance from forward-declared interface is illegal"
                 << endl;
          }
          catch (AlreadyInherited const& e)
          {
            cerr << ctx.file () << ":" << id->line () << ": error: "
                 << "directly inheriting from interface \'" << e.name ()
                 << "\' more than once is illegal" << endl;
          }
        }
Пример #27
0
        void Operation::
        parameter (Direction::Value direction,
                   IdentifierPtr const& type_id,
                   SimpleIdentifierPtr const& name_id)
        {
          if (ctx.trace ()) cerr << "parameter " << direction << " "
                                 << type_id << " " << name_id << endl;

          Name name (type_id->lexeme ());
          ScopedName from (ctx.scope ().scoped_name ());

          struct NotIn : Resolve {};

          try
          {
            try
            {
              if (one_way_ && direction != Direction::in)
                throw NotIn ();

              Type& t (resolve<Type> (from, name, Flags::complete));

              Parameter* p (0);

              switch (direction)
              {
              case Direction::in:
                {
                  p = &ctx.tu ().new_node<InParameter> (
                    ctx.file (), name_id->line (), name_id->lexeme ());
                  break;
                }
              case Direction::out:
                {
                  p = &ctx.tu ().new_node<OutParameter> (
                    ctx.file (), name_id->line (), name_id->lexeme ());
                  break;
                }
              case Direction::inout:
                {
                  p = &ctx.tu ().new_node<InOutParameter> (
                    ctx.file (), name_id->line (), name_id->lexeme ());
                  break;
                }
              }

              ctx.tu ().new_edge<Belongs> (*p, t);
              ctx.tu ().new_edge<Receives> (*op_, *p);
            }
            catch (Resolve const&)
            {
              cerr << ctx.file () << ":" << type_id->line () << ": error: "
                   << "invalid parameter declaration" << endl;
              throw;
            }
          }
          catch (NotFound const&)
          {
            cerr << ctx.file () << ":" << type_id->line () << ": error: "
                 << "no type with name \'" << name
                 << "\' visible from scope \'" << from << "\'" << endl;
          }
          catch (WrongType const&)
          {
            cerr << ctx.file () << ":" << type_id->line () << ": error: "
                 << "declaration with name \'" << name
                 << "\' visible from scope \'" << from
                 << "\' is not a type declaration" << endl;

            cerr << ctx.file () << ":" << type_id->line () << ": error: "
                 << "using non-type as an operation parameter type is "
                 << "illegal" << endl;
          }
          catch (NotComplete const& e)
          {
            cerr << ctx.file () << ":" << type_id->line () << ": error: "
                 << "type \'" << e.name () << "\' is not complete" << endl;
          }
          catch (NotIn const&)
          {
            cerr << ctx.file () << ":" << type_id->line () << ": error: "
                 << "parameter of oneway operation should have \'in\' "
                 << "direction" << endl;
          }
        }