code: def on_functiondef(self, node):
          
          # ('name', 'args', 'body', 'decorator_list')
          if node.decorator_list:
              raise Warning("decorated procedures not supported!")
          kwargs = []
  
          if not valid_symbol_name(node.name) or node.name in self.readonly_symbols:
              errmsg = "invalid function name (reserved word?) %s" % node.name
              self.raise_exception(node, exc=NameError, msg=errmsg)
  
          offset = len(node.args.args) - len(node.args.defaults)
          for idef, defnode in enumerate(node.args.defaults):
              defval = self.run(defnode)
              keyval = self.run(node.args.args[idef+offset])
              kwargs.append((keyval, defval))
  
          if version_info[0] == 3:
              args = [tnode.arg for tnode in node.args.args[:offset]]
          else:
              args = [tnode.id for tnode in node.args.args[:offset]]
  
          doc = None
          nb0 = node.body[0]
          if isinstance(nb0, ast.Expr) and isinstance(nb0.value, ast.Str):
              doc = nb0.value.s
  
          varkws = node.args.kwarg
          vararg = node.args.vararg
          if version_info[0] == 3:
              if isinstance(vararg, ast.arg):
                  vararg = vararg.arg
              if isinstance(varkws, ast.arg):
                  varkws = varkws.arg
  
          self.symtable[node.name] = Procedure(node.name, self, doc=doc,
                                               lineno=self.lineno,
                                               body=node.body,
                                               args=args, kwargs=kwargs,
                                               vararg=vararg, varkws=varkws)
          if node.name in self.no_deepcopy:
              self.no_deepcopy.remove(node.name)
docs: Define procedures.