// $Id: Func.h,v 1.19 2002/11/29 05:28:23 vern Exp $
//
// Copyright (c) 1995, 1996, 1997, 1998, 1999, 2001, 2002
//      The Regents of the University of California.  All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that: (1) source code distributions
// retain the above copyright notice and this paragraph in its entirety, (2)
// distributions including binary code include the above copyright notice and
// this paragraph in its entirety in the documentation or other materials
// provided with the distribution, and (3) all advertising materials mentioning
// features or use of this software display the following acknowledgement:
// ``This product includes software developed by the University of California,
// Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
// the University nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

#ifndef func_h
#define func_h

#include "BroList.h"
#include "Obj.h"
#include "Debug.h"

class Val;
class ListExpr;
class FuncType;
class Stmt;
class Frame;
class ID;

class Func : public BroObj {
public:
	Func(FuncType* arg_t)
		{ t = arg_t; scope = 0; }

	virtual ~Func();

	virtual int IsPure() const = 0;
	int IsEvent() const	{ return t->IsEvent(); }

	virtual vector<Stmt*>& GetBodies() { return bodies; }

	// virtual Val* Call(ListExpr* args) const = 0;
	virtual Val* Call(val_list* args) const = 0;

	// Add a new event handler to an existing function (event).
	virtual void AddBody(Stmt* new_body, id_list* new_inits,
				int new_frame_size);

	virtual void SetScope(Scope* newscope)	{ scope = newscope; }
	virtual Scope* GetScope() const		{ return scope; }

	BroType* FType() const	{ return t; }

protected:
	vector<Stmt*> bodies;
	FuncType* t;
	Scope* scope;
};

class DebugFunc : public Func {
public:
	DebugFunc(FuncType* arg_t) : Func(arg_t) {};

	virtual void Describe(ODesc* d) const = 0;
	virtual void DescribeDebug(ODesc *d, const val_list *args) const;

	const ID* GetID() const { return id; }

protected:
	ID* id;
};

class BroFunc : public DebugFunc {
public:
	BroFunc(ID* id, Stmt* body, id_list* inits, int frame_size);
	~BroFunc();

	int IsPure() const;
	Val* Call(val_list* args) const;

	void AddBody(Stmt* new_body, id_list* new_inits, int new_frame_size);

	void Describe(ODesc* d) const;

protected:
	Stmt* AddInits(Stmt* body, id_list* inits);

	int frame_size;
};

typedef Val* (*built_in_func)(val_list* args);

class BuiltinFunc : public DebugFunc {
public:
	BuiltinFunc(built_in_func func, const char* name, int is_pure);
	~BuiltinFunc();

	int IsPure() const;
	Val* Call(val_list* args) const;

	void Describe(ODesc* d) const;

protected:
	built_in_func func;
	const char* name;
	int is_pure;
};


extern void builtin_run_time(const char* msg, BroObj* arg = 0);
extern void init_builtin_funcs();

// This global is set prior to the interpreter making a function call.
// It's there so that built-in functions can access the location information
// associated with a call when reporting error messages.
extern const Expr* calling_expr;

#endif
