Ejemplo n.º 1
0
void AstPrinter::printFunction(AstFunction *function) {
    print("function ");
    print(typeToName(function->returnType()));
    print(" ");
    print(function->name());
    print("(");
    for(uint32_t i  = 0; i < function->parametersNumber(); i++) {
        if (i != 0)
            print(", ");
        print(typeToName(function->parameterType(i)));
        print(" ");
        print(function->parameterName(i));
    }
    print(") ");
    BlockNode *block = function->node()->body();
    if (block->nodeAt(0) && block->nodeAt(0)->isNativeCallNode()) {
        block->nodeAt(0)->visit(this);
        print("\n");
    } else {
		function->node()->body()->visit(this);
    }
}
Ejemplo n.º 2
0
FunctionNode* Parser::parseFunction() {
    uint32_t tokenIndex = _currentTokenIndex;
    ensureKeyword("function");

    if (currentToken() != tIDENT) {
        error("identifier expected");
    }
    const string& returnTypeName = currentTokenValue();
    VarType returnType = nameToType(returnTypeName);
    if (returnType == VT_INVALID) {
      error("wrong return type");
    }
    consumeToken();

    if (currentToken() != tIDENT) {
        error("name expected");
    }
    const string& name = currentTokenValue();
    consumeToken();

    Signature signature;
    signature.push_back(SignatureElement(returnType, "return"));

    ensureToken(tLPAREN);
    while (currentToken() != tRPAREN) {
        const string& parameterTypeName = currentTokenValue();
        VarType parameterType = nameToType(parameterTypeName);
        if (parameterType == VT_INVALID) {
            error("wrong parameter type");
        }
        consumeToken();
        const string& parameterName = currentTokenValue();
        if (currentToken() != tIDENT) {
            error("identifier expected");
        }
        consumeToken();
        signature.push_back(SignatureElement(parameterType, parameterName));

        if (currentToken() == tCOMMA) {
            consumeToken();
        }
    }
    ensureToken(tRPAREN);

    BlockNode* body = 0;
    pushScope();
    for (uint32_t i = 1; i < signature.size(); i++) {
      const string& name = signature[i].second;
      VarType type = signature[i].first;
      if (!_currentScope->declareVariable(name, type)) {
          error("Formal \"%s\" already declared", name.c_str());
      }
    }
    if ((currentToken() == tIDENT) && currentTokenValue() == "native") {
      consumeToken();
      if (currentToken() != tSTRING) {
          error("Native name expected, got %s", tokenStr(currentToken()));
      }
      pushScope();
      body = new BlockNode(_currentTokenIndex, _currentScope);
      body->add(new NativeCallNode(tokenIndex, currentTokenValue(), signature));
      consumeToken();
      ensureToken(tSEMICOLON);
      body->add(new ReturnNode(0, 0));
      popScope();
    } else {
      body = parseBlock(true, false);
      if (body->nodes() == 0 ||
          !(body->nodeAt(body->nodes() - 1)->isReturnNode())) {
        body->add(new ReturnNode(0, defaultReturnExpr(returnType)));
      }
    }
    popScope();

    if (_currentScope->lookupFunction(name) != 0) {
        error("Function %s already defined", name.c_str());
    }
    FunctionNode* result = new FunctionNode(tokenIndex, name, signature, body);
    _currentScope->declareFunction(result);

    // We don't add function node into AST.
    return 0;
}