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); } }
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; }