public void visit(FunctionExpression that) { // let the arguments resolve their types foreach (Expression argument in that.Arguments) { argument.visit(this); } // mangle the parameter list so as to be able to look up the mangled symbol System.Text.StringBuilder mangled = new System.Text.StringBuilder(64); that.Encode(mangled); string name = mangled.ToString(); // look up the function declaration Declaration declaration = _symbols.Lookup(name); if (declaration == null) { throw new CheckerError(that.Position, "Unknown function name '" + Demangler.Decode(name) + "' in function call"); } // check that the symbol is actually a function switch (declaration.Kind) { case SymbolKind.Constant: throw new CheckerError(that.Position, "Cannot call constant"); case SymbolKind.Function: break; case SymbolKind.Parameter: throw new CheckerError(that.Position, "Cannot call parameter"); case SymbolKind.Variable: throw new CheckerError(that.Position, "Cannot call variable"); default: throw new CheckerError(declaration.Position, "Unknown symbol kind: " + declaration.Kind.ToString()); } // check that the number of arguments match the number of parameters FunctionDeclaration function = (FunctionDeclaration)declaration; if (that.Arguments.Length != function.Parameters.Length) { throw new CheckerError(that.Position, "Incorrect number of parameters in function call"); } // check that the argument types match the parameter types for (int i = 0; i < that.Arguments.Length; i++) { if (that.Arguments[i].Type.Kind != function.Parameters[i].Type.Kind) { throw new CheckerError(that.Arguments[i].Position, "Type mismatch in argument to function"); } } that.Type = declaration.Type; }