/*----------------------------------------------------------------------------
  ChucK Strongly-timed Audio Programming Language
    Compiler and Virtual Machine

  Copyright (c) 2003 Ge Wang and Perry R. Cook. All rights reserved.
    http://chuck.stanford.edu/
    http://chuck.cs.princeton.edu/

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  U.S.A.
-----------------------------------------------------------------------------*/

//-----------------------------------------------------------------------------
// file: chugin.h
// desc: unified header for creating chugins, including the following
//
//   * chuck c++ typedefs and #defines such as t_CKINT, t_CKFLOAT, etc.
//   * macros for chugin components, e.g., member/static variables & functions,
//     contructors, destructors, and operator overloads
//   * chugin DL query API for adding new types to the ChucK type system
//   * chugin DL runtime API for accessing host functionalities across
//     shared-library boundaries
//   * header version string CHUCK_VERSION_STRING
//     (associated with a particular chuck language version)
//   * host/chugin compatibility version
//     (used when a chugin loads to determine chugin:host compatibility)
//
// NOTE: please see the chugins page and the chugins repository for examples
//       https://chuck.stanford.edu/extend/
//       https://github.com/ccrma/chugins/
//
// ALSO: check out the 'chuginate' utility (for generating chugin starter code)
//       available in the chugins repository.
//
// FYI: this file was generated by chuck-o-matic/scripts/chugin-gen-header.sh
//      & combines four minimally needed chuck headers for compiling chugins:
//
//   * chuck_def.h
//   * chuck_symbol.h
//   * chuck_absyn.h
//   * chuck_dl.h
//-----------------------------------------------------------------------------


// all chugins must define __CHUCK_CHUGIN__
#ifndef __CHUCK_CHUGIN__
#define __CHUCK_CHUGIN__
#endif // #ifndef __CHUCK_CHUGIN__

// use CHUGIN_API_VERSION_MAJOR for chugin API major version (as an integer)
#define CHUGIN_API_VERSION_MAJOR CK_DLL_VERSION_MAJOR
// use CHUGIN_API_VERSION_MINOR for chugin API minor version (as an integer)
#define CHUGIN_API_VERSION_MINOR CK_DLL_VERSION_MINOR


/*----------------------------------------------------------------------------
  ChucK Strongly-timed Audio Programming Language
    Compiler, Virtual Machine, and Synthesis Engine

  Copyright (c) 2003 Ge Wang and Perry R. Cook. All rights reserved.
    http://chuck.stanford.edu/
    http://chuck.cs.princeton.edu/

  This program is free software; you can redistribute it and/or modify
  it under the dual-license terms of EITHER the MIT License OR the GNU
  General Public License (the latter as published by the Free Software
  Foundation; either version 2 of the License or, at your option, any
  later version).

  This program is distributed in the hope that it will be useful and/or
  interesting, but WITHOUT ANY WARRANTY; without even the implied warranty
  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  MIT Licence and/or the GNU General Public License for details.

  You should have received a copy of the MIT License and the GNU General
  Public License (GPL) along with this program; a copy of the GPL can also
  be obtained by writing to the Free Software Foundation, Inc., 59 Temple
  Place, Suite 330, Boston, MA 02111-1307 U.S.A.
-----------------------------------------------------------------------------*/

//-----------------------------------------------------------------------------
// file: chuck_def.h
// desc: ChucK defines for the system
//
// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
//         Perry R. Cook (prc@cs.princeton.edu)
// date: Autumn 2002
//-----------------------------------------------------------------------------
#ifndef __CHUCK_DEF_H__
#define __CHUCK_DEF_H__

#include <stdlib.h>
#include <memory.h>
#include <assert.h>




//-----------------------------------------------------------------------------
// ChucK version string
//-----------------------------------------------------------------------------
// from host (non-chugin) -- can retrieve using ChucK::version()
// from chugin -- can access directly as CHUCK_VERSION_STRING
// 1.5.0.0 (ge) | moved to chuck.h for at-a-glance visibility
// 1.5.2.0 (ge) | moved to chuck_def.h for chugins headers streamlining
//-----------------------------------------------------------------------------
#define CHUCK_VERSION_STRING        "1.5.5.0 (chai)"
//-----------------------------------------------------------------------------




//-------------------------------------------
// chuck types
//-------------------------------------------
#ifndef __EMSCRIPTEN__
//-------------------------------------------
#define t_CKTIME                    double
#define t_CKDUR                     double
#define t_CKSINGLE                  float
#define t_CKDOUBLE                  double
#define t_CKFLOAT                   double
#define CK_FLT_MAX                  DBL_MAX
#define CK_FLT_MIN                  DBL_MIN
#ifdef _WIN64                       // REFACTOR-2017
#define t_CKINT                     long long // REFACTOR-2017
#define CK_INT_MAX                  LLONG_MAX
#else
#define t_CKINT                     long
#define CK_INT_MAX                  LONG_MAX
#endif
//-------------------------------------------
#else // below is for __EMSCRIPTEN__
//-------------------------------------------
#define t_CKTIME                    double
#define t_CKDUR                     double
#define t_CKFLOAT                   double
#define t_CKDOUBLE                  double
#define t_CKSINGLE                  float
#define t_CKINT                     int // REFACTOR-2017
#define CK_FLT_MAX                  DBL_MAX
#define CK_FLT_MIN                  DBL_MIN
#define CK_INT_MAX                  INT_MAX
//-------------------------------------------
#endif
//-------------------------------------------

// additional types
#define t_CKUINT                    unsigned t_CKINT
#define t_CKBOOL                    unsigned t_CKINT
#define t_CKBYTE                    unsigned char
#define t_CKVOID                    void
#define t_CKVOIDPTR                 void *

// complex type
typedef struct { t_CKFLOAT re ; t_CKFLOAT im ; } t_CKCOMPLEX;
// polar type
typedef struct { t_CKFLOAT modulus ; t_CKFLOAT phase ; } t_CKPOLAR;

// vector types
typedef struct { t_CKFLOAT x ; t_CKFLOAT y ; } t_CKVEC2;
typedef struct { t_CKFLOAT x ; t_CKFLOAT y ; t_CKFLOAT z ; } t_CKVEC3;
typedef struct { t_CKFLOAT x ; t_CKFLOAT y ; t_CKFLOAT z ; t_CKFLOAT w ; } t_CKVEC4;
typedef struct { t_CKUINT N ; t_CKFLOAT * values ; } t_CKVECTOR;

// size of types
#define sz_TIME                     sizeof(t_CKTIME)
#define sz_DUR                      sizeof(t_CKDUR)
#define sz_FLOAT                    sizeof(t_CKFLOAT)
#define sz_DOUBLE                   sizeof(t_CKDOUBLE)
#define sz_SINGLE                   sizeof(t_CKSINGLE)
#define sz_INT                      sizeof(t_CKINT)
#define sz_UINT                     sizeof(t_CKUINT)
#define sz_BOOL                     sizeof(t_CKBOOL)
#define sz_BYTE                     sizeof(t_CKBYTE)
#define sz_VOIDPTR                  sizeof(t_CKVOIDPTR)
#define sz_COMPLEX                  sizeof(t_CKCOMPLEX)
#define sz_POLAR                    sizeof(t_CKPOLAR)
#define sz_VEC2                     sizeof(t_CKVEC2)
#define sz_VEC3                     sizeof(t_CKVEC3)
#define sz_VEC4                     sizeof(t_CKVEC4)
#define sz_VECTOR                   sizeof(t_CKVECTOR)
#define sz_VOID                     0
#define sz_WORD                     4

// kinds (added 1.3.1.0 to faciliate 64-bit support)
// to differentiate in case int and float have same size
enum te_KindOf
{
    kindof_VOID = 0,
    kindof_INT,
    kindof_FLOAT,
    kindof_VEC2, // 1.5.1.7 (ge) was kindof_COMPLEX
    kindof_VEC3,
    kindof_VEC4
};

typedef char *                      c_str;
typedef const char *                c_constr;

// use 64-bit samples in the audio engine
// #define __CHUCK_USE_64_BIT_SAMPLE__

// type for audio sample
//-------------------------------------------
#ifdef __CHUCK_USE_64_BIT_SAMPLE__
//-------------------------------------------
#define SAMPLE                      double
#define CK_SILENCE                  0.0
#define CK_DDN                      CK_DDN_DOUBLE
//-------------------------------------------
#else
//-------------------------------------------
#define SAMPLE                      float
#define CK_SILENCE                  0.0f
#define CK_DDN                      CK_DDN_SINGLE
//-------------------------------------------
#endif
//-------------------------------------------
#define t_CKSAMPLE                  SAMPLE

// sample complex
typedef struct { SAMPLE re ; SAMPLE im ; } t_CKCOMPLEX_SAMPLE;

// bool
#ifndef TRUE
#define TRUE                        1
#define FALSE                       0
#endif

// special non-zero value to denote "no value" | added 1.4.2.0 (ge)
#define CK_NO_VALUE                 0xffffffff

// 3.1415926535897932384626433832795028841971693993751058209749445...
#define CK_ONE_PI                   (3.14159265358979323846)
#define CK_TWO_PI                   (2.0 * CK_ONE_PI)
#define CK_SQRT2                    (1.41421356237309504880)

// macro for cleaning up: tests for NULL before and sets to NULL after
#define CK_SAFE_DELETE(x)           do { if(x){ delete (x); (x) = NULL; } } while(0)
#define CK_SAFE_DELETE_ARRAY(x)     do { if(x){ delete [] (x); (x) = NULL; } } while(0)
#define CK_SAFE_RELEASE(x)          do { if(x){ (x)->release(); (x) = NULL; } } while(0)
#define CK_SAFE_ADD_REF(x)          do { if(x){ (x)->add_ref(); } } while(0)
// NOTE the ref assign accounts for the case that lhs == rhs and the reference==1: add BEFORE release
#define CK_SAFE_REF_ASSIGN(lhs,rhs) do { Chuck_VM_Object * temp = (lhs); (lhs) = (rhs); CK_SAFE_ADD_REF(lhs); CK_SAFE_RELEASE(temp); } while(0)
#define CK_SAFE_FREE(x)             do { if(x){ free(x); (x) = NULL; } } while(0)
#define CK_SAFE_UNLOCK_DELETE(x)    do { if(x){ (x)->unlock(); delete (x); (x) = NULL; } } while(0)
#define CK_SAFE_UNLOCK_RELEASE(x)   do { if(x){ (x)->unlock(); (x)->release(); (x) = NULL; } } while(0)

// max + min
#define ck_max(x,y)                 ( (x) >= (y) ? (x) : (y) )
#define ck_min(x,y)                 ( (x) <= (y) ? (x) : (y) )

#ifndef __arm__
// dedenormal
#define CK_DDN_SINGLE(f)            f = ( f >= 0 ? \
        ( ( f > (t_CKSINGLE)1e-15 && f < (t_CKSINGLE)1e15 ) ? f : (t_CKSINGLE)0.0 ) : \
        ( ( f < (t_CKSINGLE)-1e-15 && f > (t_CKSINGLE)-1e15 ) ? f : (t_CKSINGLE)0.0 ) )
#define CK_DDN_DOUBLE(f)            f = ( f >= 0 ? \
        ( ( f > (t_CKDOUBLE)1e-15 && f < (t_CKDOUBLE)1e15 ) ? f : 0.0 ) : \
        ( ( f < (t_CKDOUBLE)-1e-15 && f > (t_CKDOUBLE)-1e15 ) ? f : 0.0 ) )
#else
#define CK_DDN_SINGLE(f) (f)
#define CK_DDN_DOUBLE(f) (f)
#endif // __arm__

// stats tracking
#if defined(__CHUCK_STAT_TRACK__)
#define CK_TRACK( stmt ) stmt
#else
#define CK_TRACK( stmt )
#endif


//-------------------------------------------
// operating system identification
// https://sourceforge.net/p/predef/wiki/OperatingSystems/
// http://web.archive.org/web/20191012035921/http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system
//-------------------------------------------

//-------------------------------------------
// platform: Apple
// related macros: __MACOSX_CORE__ __CHIP_MODE__
// NOTE: __CHIP_MODE__ is ChucK for iPhone; implies iOS
//-------------------------------------------
#if defined(__APPLE__) // && defined(__MACH__)
//-------------------------------------------
  #ifndef __PLATFORM_APPLE__
  #define __PLATFORM_APPLE__
  #endif

  // get information about the target sub-platform
  #include <TargetConditionals.h>
  #if TARGET_OS_MAC == 1
    #if TARGET_OS_IPHONE != 1
      #define __PLATFORM_MACOS__ // macOS
    #else // TARGET_OS_IPHONE not 0
      #define __PLATFORM_IOS__ // iOS, tvOS, or watchOS device
      // even more information within iOS
      #if TARGET_OS_EMBEDDED == 1
        #define __PLATFORM_IOS_DEVICE__ // device actual
      #else // TARGET_OS_EMBEDDED not 1
        #define __PLATFORM_IOS_SIMULATOR__ // simulator
      #endif
    #endif
  #else // TARGET_OS_MAC not 1
    // apparently on Apple; but cannot determine platform target
    // #error "[chuck build]: unknown Apple platform target"
  #endif
//-------------------------------------------
#endif // defined(__APPLE__) && defined(__MACH__)
//-------------------------------------------


//-------------------------------------------
// platform: linux
// related macros: __LINUX_ALSA__ __LINUX_PULSE__ __LINUX_OSS__ __LINUX_JACK__ __UNIX_JACK__
//-------------------------------------------
#if defined(__linux__) || defined(__FreeBSD__)
//-------------------------------------------
  #ifndef __PLATFORM_LINUX__
  #define __PLATFORM_LINUX__
  #endif
//-------------------------------------------
#endif // defined(__linux__) || defined(__FreeBSD__)
//-------------------------------------------


//-------------------------------------------
// platform: windows
// related macros: __WINDOWS_DS__ __WINDOWS_WASAPI__ __WINDOWS_ASIO__
// NOTE: Windows defines _WIN32 for both 32-bit and 64-bit
//-------------------------------------------
#if defined(_WIN32) || defined(_WIN64)
//-------------------------------------------
  #ifndef __PLATFORM_WINDOWS__
  #define __PLATFORM_WINDOWS__
  #endif

  // legacy; new code should use __PLATFORM_WINDOWS__
  #ifndef __PLATFORM_WIN32__
  #define __PLATFORM_WIN32__
  #endif
//-------------------------------------------
#endif // defined(_WIN32) || defined(_WIN64)
//-------------------------------------------


//-------------------------------------------
// platform: Cygwin (on Windows)
//-------------------------------------------
#if defined(__CYGWIN__)
//-------------------------------------------
  #ifndef __PLATFORM_CYGWIN__
  #define __PLATFORM_CYGWIN__
  #endif
  #ifndef __WINDOWS_PTHREAD__
  #define __WINDOWS_PTHREAD__
  #endif
//-------------------------------------------
#endif // defined(__CYGWIN__)
//-------------------------------------------


//-------------------------------------------
// platform: web assembly
//-------------------------------------------
#if defined(__EMSCRIPTEN__)
//-------------------------------------------
  #ifndef __PLATFORM_EMSCRIPTEN__
  #define __PLATFORM_EMSCRIPTEN__
  #endif
//-------------------------------------------
#endif // defined(__EMSCRIPTEN__)
//-------------------------------------------


//-------------------------------------------
// platform: android
// NOTE: android is based on linux; linux macros are also defined
//-------------------------------------------
#if defined(__ANDROID__)
//-------------------------------------------
  #ifndef __PLATFORM_ANDROID__
  #define __PLATFORM_ANDROID__
  #endif
//-------------------------------------------
#endif // defined(__ANDROID__)
//-------------------------------------------


#ifdef __PLATFORM_WINDOWS__
// 1.4.2.0 (ge and spencer) added for legacy windows, as part of switch to snprintf
// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
#if defined(_MSC_VER) && _MSC_VER < 1900
  #define snprintf(buf,len, format,...) _snprintf_s(buf, len,len, format, __VA_ARGS__)
#endif
#pragma warning (disable : 4996)  // stdio deprecation
#pragma warning (disable : 4786)  // stl debug info
#pragma warning (disable : 4312)  // type casts from void*
#pragma warning (disable : 4311)  // type casts to void*
#pragma warning (disable : 4244)  // truncation
#pragma warning (disable : 4068)  // unknown pragma
#pragma warning (disable : 4018)  // signed/unsigned mismatch
#endif // #ifdef __PLATFORM_WINDOWS__

#ifdef __CHIP_MODE__
#define __DISABLE_MIDI__
//#define __DISABLE_SNDBUF__
#define __DISABLE_WATCHDOG__
#define __DISABLE_RAW__
#define __DISABLE_KBHIT__
#define __DISABLE_PROMPTER__
#define __DISABLE_OTF_SERVER__
#define __ALTER_HID__
#define __ALTER_ENTRY_POINT__
#define __STK_USE_SINGLE_PRECISION__
#endif

#ifdef __arm__
// enable additional optimization
#define __STK_USE_SINGLE_PRECISION__
#endif // __arm__

#endif
/*----------------------------------------------------------------------------
  ChucK Strongly-timed Audio Programming Language
    Compiler, Virtual Machine, and Synthesis Engine

  Copyright (c) 2003 Ge Wang and Perry R. Cook. All rights reserved.
    http://chuck.stanford.edu/
    http://chuck.cs.princeton.edu/

  This program is free software; you can redistribute it and/or modify
  it under the dual-license terms of EITHER the MIT License OR the GNU
  General Public License (the latter as published by the Free Software
  Foundation; either version 2 of the License or, at your option, any
  later version).

  This program is distributed in the hope that it will be useful and/or
  interesting, but WITHOUT ANY WARRANTY; without even the implied warranty
  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  MIT Licence and/or the GNU General Public License for details.

  You should have received a copy of the MIT License and the GNU General
  Public License (GPL) along with this program; a copy of the GPL can also
  be obtained by writing to the Free Software Foundation, Inc., 59 Temple
  Place, Suite 330, Boston, MA 02111-1307 U.S.A.
-----------------------------------------------------------------------------*/

//-----------------------------------------------------------------------------
// file: chuck_symbol.h
// desc: symbols in the syntax, adapted from Tiger compiler by Appel Appel
//
// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
// adapted from: Andrew Appel (appel@cs.princeton.edu)
// date: Autumn 2002
//-----------------------------------------------------------------------------
#ifndef __CHUCK_SYMBOL_H__
#define __CHUCK_SYMBOL_H__



#if defined(_cplusplus) || defined(__cplusplus)
extern "C" {
#endif


typedef struct S_Symbol_ * S_Symbol;

/* Make a unique symbol from a given c_str.
 *  Different calls to make_symbol("foo") will yield the same S_Symbol
 *  value, even if the "foo" c_str are at different locations. */
S_Symbol insert_symbol( c_constr );

/* Extract the underlying c_str from a symbol */
c_str S_name(S_Symbol);

/* S_table is a mapping from S_Symbol->any, where "any" is represented
 *     here by void*  */
typedef struct TAB_table_ *S_table;

/* Make a new table */
S_table S_empty(void);
S_table S_empty2(unsigned int size);

/* Enter a binding "sym->value" into "t", shadowing but not deleting
 *    any previous binding of "sym". */
void S_enter(S_table t, S_Symbol sym, void * value);
void S_enter2(S_table t, c_constr str, void * value);

/* Look up the most recent binding of "sym" in "t", or return NULL
 *    if sym is unbound. */
void * S_look(S_table t, S_Symbol sym);
void * S_look2(S_table t, c_constr str);

/* Start a new "scope" in "t".  Scopes are nested. */
void S_beginScope(S_table t);

/* Remove any bindings entered since the current scope began,
   and end the current scope. */
void S_endScope(S_table t);
void S_pop(S_table t);


#if defined(_cplusplus) || defined(__cplusplus)
}
#endif




// moved here from archaic chuck_utils.h | 1.5.2.0 (ge)
#if defined(_cplusplus) || defined(__cplusplus)
extern "C" {
#endif


typedef struct U_boolList_ * U_boolList;
struct U_boolList_
{
    t_CKBOOL head;
    U_boolList tail;
};


void * checked_malloc( t_CKINT size );
c_str cc_str( char * );
U_boolList U_BoolList( t_CKBOOL head, U_boolList tail );


#if defined(_cplusplus) || defined(__cplusplus)
}
#endif



#endif
/*----------------------------------------------------------------------------
  ChucK Strongly-timed Audio Programming Language
    Compiler, Virtual Machine, and Synthesis Engine

  Copyright (c) 2003 Ge Wang and Perry R. Cook. All rights reserved.
    http://chuck.stanford.edu/
    http://chuck.cs.princeton.edu/

  This program is free software; you can redistribute it and/or modify
  it under the dual-license terms of EITHER the MIT License OR the GNU
  General Public License (the latter as published by the Free Software
  Foundation; either version 2 of the License or, at your option, any
  later version).

  This program is distributed in the hope that it will be useful and/or
  interesting, but WITHOUT ANY WARRANTY; without even the implied warranty
  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  MIT Licence and/or the GNU General Public License for details.

  You should have received a copy of the MIT License and the GNU General
  Public License (GPL) along with this program; a copy of the GPL can also
  be obtained by writing to the Free Software Foundation, Inc., 59 Temple
  Place, Suite 330, Boston, MA 02111-1307 U.S.A.
-----------------------------------------------------------------------------*/

//-----------------------------------------------------------------------------
// file: chuck_absyn.h
// desc: chuck abstract syntax
//
// author: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
// date: Autumn 2002
//-----------------------------------------------------------------------------
#ifndef __CHUCK_ABSYN_H__
#define __CHUCK_ABSYN_H__

#include <stdint.h> // for uint32_t; c++11




#if defined(_cplusplus) || defined(__cplusplus)
extern "C" {
#endif

// pos
typedef int a_Pos;

// 1.5.0.5 (ge) flex/bison's location struct
// typedef struct YYLTYPE YYLTYPE;

// enum oper
typedef enum {
    ae_op_none = 0,
    ae_op_plus, ae_op_minus, ae_op_times, ae_op_divide,
    ae_op_eq, ae_op_neq, ae_op_lt, ae_op_le, ae_op_gt,
    ae_op_ge, ae_op_and, ae_op_or, ae_op_s_or, ae_op_s_and,
    ae_op_shift_left, ae_op_shift_right, ae_op_percent,
    ae_op_s_xor, ae_op_chuck, ae_op_plus_chuck, ae_op_minus_chuck,
    ae_op_times_chuck, ae_op_divide_chuck, ae_op_s_and_chuck,
    ae_op_s_or_chuck, ae_op_s_xor_chuck, ae_op_shift_right_chuck,
    ae_op_shift_left_chuck, ae_op_percent_chuck,
    ae_op_plusplus, ae_op_minusminus, ae_op_tilda, ae_op_exclamation,
    ae_op_at_chuck, ae_op_unchuck, ae_op_upchuck, ae_op_downchuck,
    ae_op_assign, ae_op_dollar, ae_op_at_at, ae_op_coloncolon,
    ae_op_spork, ae_op_typeof, ae_op_sizeof, ae_op_new,
    ae_op_arrow_left, ae_op_arrow_right, ae_op_gruck_left, ae_op_gruck_right,
    ae_op_ungruck_left, ae_op_ungruck_right,
    // keep this last
    ae_op_count
} ae_Operator;

// convert op by enum to str
const char * op2str( ae_Operator op );
// convert op by str to enum
ae_Operator str2op( const char * str );

// enum key words
typedef enum {
    ae_key_this, ae_key_me, ae_key_func, ae_key_public, ae_key_protected,
    ae_key_private, ae_key_static, ae_key_instance, ae_key_abstract
} ae_Keyword;

// enumeration for kinds of function pointers | 1.5.2.0 (ge) added
typedef enum
{
    ae_fp_unknown = 0,
    ae_fp_ctor,
    ae_fp_dtor,
    ae_fp_mfun,
    ae_fp_sfun,
    ae_fp_gfun,
    ae_fp_addr,
    // keep this last
    ae_fp_count
} ae_FuncPointerKind;

// convert fp kind by enum to str | 1.5.2.0 (ge) added
const char * fpkind2str( ae_FuncPointerKind kind );




//-----------------------------------------------------------------------------
// pointer types
//-----------------------------------------------------------------------------
typedef struct a_Program_ * a_Program;
typedef struct a_Section_ * a_Section;
typedef struct a_Stmt_List_ * a_Stmt_List;
typedef struct a_Class_Def_ * a_Class_Def;
typedef struct a_Func_Def_ * a_Func_Def;
typedef struct a_Code_Segment_ * a_Code_Segment;
typedef struct a_Stmt_ * a_Stmt;
typedef struct a_Exp_ * a_Exp;
typedef struct a_Exp_Chuck_ * a_Exp_Chuck;
typedef struct a_Exp_Binary_ * a_Exp_Binary;
typedef struct a_Exp_Cast_ * a_Exp_Cast;
typedef struct a_Exp_Unary_ * a_Exp_Unary;
typedef struct a_Exp_Postfix_ * a_Exp_Postfix;
typedef struct a_Exp_Primary_ * a_Exp_Primary;
typedef struct a_Exp_Dur_ * a_Exp_Dur;
typedef struct a_Exp_Array_ * a_Exp_Array;
typedef struct a_Exp_Func_Call_ * a_Exp_Func_Call;
typedef struct a_Exp_Dot_Member_ * a_Exp_Dot_Member;
typedef struct a_Exp_If_ * a_Exp_If;
typedef struct a_Exp_Decl_ * a_Exp_Decl;
typedef struct a_Exp_Hack_ * a_Exp_Hack;
typedef struct a_Stmt_Code_ * a_Stmt_Code;
typedef struct a_Stmt_If_ * a_Stmt_If;
typedef struct a_Stmt_While_ * a_Stmt_While;
typedef struct a_Stmt_Until_ * a_Stmt_Until;
typedef struct a_Stmt_For_ * a_Stmt_For;
typedef struct a_Stmt_ForEach_ * a_Stmt_ForEach;
typedef struct a_Stmt_Loop_ * a_Stmt_Loop;
typedef struct a_Stmt_Switch_ * a_Stmt_Switch;
typedef struct a_Stmt_Break_ * a_Stmt_Break;
typedef struct a_Stmt_Continue_ * a_Stmt_Continue;
typedef struct a_Stmt_Return_ * a_Stmt_Return;
typedef struct a_Stmt_Case_ * a_Stmt_Case;
typedef struct a_Stmt_GotoLabel_ * a_Stmt_GotoLabel;
typedef struct a_Stmt_Import_ * a_Stmt_Import;
typedef struct a_Stmt_Doc_ * a_Stmt_Doc;
typedef struct a_Decl_ * a_Decl;
typedef struct a_Var_Decl_ * a_Var_Decl;
typedef struct a_Var_Decl_List_ * a_Var_Decl_List;
typedef struct a_Type_Decl_ * a_Type_Decl;
typedef struct a_Arg_List_ * a_Arg_List;
typedef struct a_Id_List_ * a_Id_List;
typedef struct a_Class_Ext_ * a_Class_Ext;
typedef struct a_Class_Body_ * a_Class_Body;
typedef struct a_Array_Sub_ * a_Array_Sub;
typedef struct a_Ctor_Call_ * a_Ctor_Call; // 1.5.2.0 (ge) added
typedef struct a_Complex_ * a_Complex;
typedef struct a_Polar_ * a_Polar;
typedef struct a_Vec_ * a_Vec; // ge: added 1.3.5.3
typedef struct a_Import_ * a_Import; // 1.5.4.0 (ge) added
typedef struct a_Doc_ * a_Doc; // 1.5.4.4 (ge) added


// forward reference for type
typedef struct Chuck_Type * t_CKTYPE;
typedef struct Chuck_Value * t_CKVALUE;
typedef struct Chuck_Func * t_CKFUNC;
typedef struct Chuck_Namespace * t_CKNSPC;
typedef struct Chuck_VM_Code * t_CKVMCODE;




//------------------------------------------------------------------------------
// functions
//------------------------------------------------------------------------------
a_Program new_program( a_Section section, uint32_t line, uint32_t where );
a_Program append_program( a_Program program, a_Section section, uint32_t line, uint32_t where );
a_Section new_section_stmt( a_Stmt_List stmt_list, uint32_t line, uint32_t where );
a_Section new_section_func_def( a_Func_Def func_def, uint32_t line, uint32_t where );
a_Section new_section_class_def( a_Class_Def class_def, uint32_t line, uint32_t where );
a_Stmt_List new_stmt_list( a_Stmt stmt, uint32_t line, uint32_t where );
a_Stmt_List append_stmt_list( a_Stmt_List stmt_list, a_Stmt stmt, uint32_t line, uint32_t where );
a_Stmt new_stmt_from_expression( a_Exp exp, uint32_t line, uint32_t where );
a_Stmt new_stmt_from_code( a_Stmt_List code, uint32_t line, uint32_t where );
a_Stmt new_stmt_from_while( a_Exp cond, a_Stmt body, uint32_t line, uint32_t where );
a_Stmt new_stmt_from_do_while( a_Exp cond, a_Stmt body, uint32_t line, uint32_t where );
a_Stmt new_stmt_from_until( a_Exp cond, a_Stmt body, uint32_t line, uint32_t where );
a_Stmt new_stmt_from_do_until( a_Exp cond, a_Stmt body, uint32_t line, uint32_t where );
a_Stmt new_stmt_from_for( a_Stmt c1, a_Stmt c2, a_Exp c3, a_Stmt body, uint32_t line, uint32_t where );
a_Stmt new_stmt_from_foreach( a_Exp iter, a_Exp array, a_Stmt body, uint32_t line, uint32_t where );
a_Stmt new_stmt_from_loop( a_Exp cond, a_Stmt body, uint32_t line, uint32_t where );
a_Stmt new_stmt_from_if( a_Exp cond, a_Stmt if_body, a_Stmt else_body, uint32_t line, uint32_t where );
a_Stmt new_stmt_from_switch( a_Exp exp, uint32_t line, uint32_t where );
a_Stmt new_stmt_from_break( uint32_t line, uint32_t where );
a_Stmt new_stmt_from_continue( uint32_t line, uint32_t where );
a_Stmt new_stmt_from_return( a_Exp exp, uint32_t line, uint32_t where );
a_Stmt new_stmt_from_label( c_str xid, uint32_t line, uint32_t where );
a_Stmt new_stmt_from_case( a_Exp exp, uint32_t line, uint32_t where );
a_Stmt new_stmt_from_import( a_Import target, uint32_t line, uint32_t where );
a_Stmt new_stmt_from_doc( a_Doc target, uint32_t line, uint32_t where );
a_Exp append_expression( a_Exp list, a_Exp exp, uint32_t line, uint32_t where );
a_Exp new_exp_from_binary( a_Exp lhs, ae_Operator oper, a_Exp rhs, uint32_t line, uint32_t where );
a_Exp new_exp_from_unary( ae_Operator oper, a_Exp exp, uint32_t line, uint32_t where );
a_Exp new_exp_from_unary2( ae_Operator oper, a_Type_Decl type, int ctor_invoked, a_Exp ctor_args, a_Array_Sub array, uint32_t line, uint32_t where );
a_Exp new_exp_from_unary3( ae_Operator oper, a_Stmt code, uint32_t line, uint32_t where );
a_Exp new_exp_from_cast( a_Type_Decl type, a_Exp exp, uint32_t line, uint32_t where, uint32_t castPos );
a_Exp new_exp_from_array( a_Exp base, a_Array_Sub indices, uint32_t line, uint32_t where );
a_Exp new_exp_from_array_lit( a_Array_Sub exp_list, uint32_t line, uint32_t where );
a_Exp new_exp_from_func_call( a_Exp base, a_Exp args, uint32_t line, uint32_t where );
a_Exp new_exp_from_member_dot( a_Exp base, c_str member, uint32_t line, uint32_t where, uint32_t memberPos );
a_Exp new_exp_from_postfix( a_Exp base, ae_Operator op, uint32_t line, uint32_t where );
a_Exp new_exp_from_dur( a_Exp base, a_Exp unit, uint32_t line, uint32_t where );
a_Exp new_exp_from_id( c_str xid, uint32_t line, uint32_t where );
a_Exp new_exp_from_int( t_CKINT num, uint32_t line, uint32_t where );
a_Exp new_exp_from_float( t_CKFLOAT num, uint32_t line, uint32_t where );
a_Exp new_exp_from_str( c_str str, uint32_t line, uint32_t where );
a_Exp new_exp_from_char( c_str chr, uint32_t line, uint32_t where );
a_Exp new_exp_from_if( a_Exp cond, a_Exp lhs, a_Exp rhs, uint32_t line, uint32_t where );
a_Exp new_exp_from_complex( a_Complex, uint32_t line, uint32_t where );
a_Exp new_exp_from_polar( a_Polar, uint32_t line, uint32_t where );
a_Exp new_exp_from_vec( a_Vec, uint32_t line, uint32_t where ); // ge: added 1.3.5.3
a_Exp new_exp_decl_external( a_Type_Decl type_decl, a_Var_Decl_List var_decl_list, int is_static, int is_const, uint32_t line, uint32_t where );
a_Exp new_exp_decl_global( a_Type_Decl type_decl, a_Var_Decl_List var_decl_list, int is_static, int is_const, uint32_t line, uint32_t where );
a_Exp new_exp_decl( a_Type_Decl type_decl, a_Var_Decl_List var_decl_list, int is_static, int is_const, uint32_t line, uint32_t where );
a_Exp new_exp_from_hack( a_Exp exp, uint32_t line, uint32_t where );
a_Exp new_exp_from_nil( uint32_t line, uint32_t where );
a_Var_Decl_List new_var_decl_list( a_Var_Decl var_decl, uint32_t line, uint32_t where );
a_Var_Decl_List prepend_var_decl_list( a_Var_Decl var_decl, a_Var_Decl_List list, uint32_t line, uint32_t where );
a_Var_Decl new_var_decl( c_constr xid, int ctor_invoked, a_Exp ctor_args, a_Array_Sub array, uint32_t line, uint32_t where );
a_Type_Decl new_type_decl( a_Id_List xid, int ref, uint32_t line, uint32_t where );
a_Type_Decl add_type_decl_array( a_Type_Decl type_decl, a_Array_Sub array, uint32_t line, uint32_t where );
a_Arg_List new_arg_list( a_Type_Decl type_decl, a_Var_Decl var_decl, uint32_t line, uint32_t where );
a_Arg_List prepend_arg_list( a_Type_Decl type_decl, a_Var_Decl var_decl, a_Arg_List arg_list, uint32_t line, uint32_t where );
a_Array_Sub new_array_sub( a_Exp exp, uint32_t line, uint32_t where );
a_Array_Sub prepend_array_sub( a_Array_Sub array, a_Exp exp, uint32_t line, uint32_t where );
a_Complex new_complex( a_Exp re, uint32_t line, uint32_t where );
a_Polar new_polar( a_Exp mod, uint32_t line, uint32_t where ); // ge: added 1.3.5.3
a_Vec new_vec( a_Exp e, uint32_t line, uint32_t where );
a_Import new_import( c_str str, a_Id_List id_list, uint32_t line, uint32_t where ); // 1.5.4.0 (ge) added
a_Import prepend_import( a_Import target, a_Import list, uint32_t line, uint32_t where ); // 1.5.4.0 (ge) added
a_Doc new_doc( c_str str, uint32_t line, uint32_t where ); // 1.5.4.4 (ge) added
a_Doc prepend_doc( a_Doc target, a_Doc list, uint32_t line, uint32_t where ); // 1.5.4.4 (ge) added

a_Class_Def new_class_def( ae_Keyword class_decl, a_Id_List xid, a_Class_Ext ext, a_Class_Body body, uint32_t line, uint32_t where );
a_Class_Body new_class_body( a_Section section, uint32_t line, uint32_t where );
a_Class_Body prepend_class_body( a_Section section, a_Class_Body body, uint32_t line, uint32_t where );
a_Class_Ext new_class_ext( a_Id_List extend_id, a_Id_List impl_list, uint32_t line, uint32_t where );
a_Class_Def new_iface_def( ae_Keyword class_decl, a_Id_List xid, a_Class_Ext ext, a_Class_Body body, uint32_t line, uint32_t where );
a_Id_List new_id_list( c_constr xid, uint32_t line, uint32_t where /*, YYLTYPE * loc*/ );
a_Id_List prepend_id_list( c_constr xid, a_Id_List list, uint32_t line, uint32_t where /*, YYLTYPE * loc*/ );
a_Func_Def new_func_def( ae_Keyword func_decl, ae_Keyword static_decl,
                         a_Type_Decl type_decl, c_str name,
                         a_Arg_List arg_list, a_Stmt code, uint32_t is_from_ast,
                         uint32_t line, uint32_t where );
a_Func_Def new_op_overload( ae_Keyword func_decl, ae_Keyword static_decl,
                            a_Type_Decl type_decl, ae_Operator oper,
                            a_Arg_List arg_list, a_Stmt code, uint32_t is_from_ast,
                            uint32_t overload_post, uint32_t line, uint32_t where,
                            uint32_t operPos );


//------------------------------------------------------------------------------
// utility functions including memory management
//------------------------------------------------------------------------------
// delete program and sections
void delete_program( a_Program program );
void delete_section( a_Section section );

// delete stmt list
void delete_stmt_list( a_Stmt_List list );
// delete class_def
void delete_class_def( a_Class_Def def );
void delete_class_body( a_Class_Body body );
void delete_class_ext( a_Class_Ext ext );
void delete_iface_def( a_Class_Def def );
// delete func def
void delete_func_def( a_Func_Def def );
// delete id list
void delete_id_list( a_Id_List list );

// delete stmt
void delete_stmt( a_Stmt stmt );
void delete_stmt_from_code( a_Stmt stmt );
void delete_stmt_from_while( a_Stmt stmt );
void delete_stmt_from_until( a_Stmt stmt );
void delete_stmt_from_for( a_Stmt stmt );
void delete_stmt_from_foreach( a_Stmt stmt );
void delete_stmt_from_loop( a_Stmt stmt );
void delete_stmt_from_if( a_Stmt stmt );
void delete_stmt_from_switch( a_Stmt stmt );
void delete_stmt_from_break( a_Stmt stmt );
void delete_stmt_from_continue( a_Stmt stmt );
void delete_stmt_from_return( a_Stmt stmt );
void delete_stmt_from_label( a_Stmt stmt );
void delete_stmt_from_import( a_Stmt stmt );
void delete_stmt_from_doc( a_Stmt stmt );

// delete an exp
void delete_exp( a_Exp exp );
void delete_exp_from_binary( a_Exp e );
void delete_exp_from_unary( a_Exp e );
void delete_exp_from_cast( a_Exp e );
void delete_exp_from_array( a_Exp e );
void delete_exp_from_func_call( a_Exp e );
void delete_exp_from_member_dot( a_Exp e );
void delete_exp_from_postfix( a_Exp e );
void delete_exp_from_dur( a_Exp e );
void delete_exp_from_if( a_Exp e );
void delete_exp_from_id( a_Exp_Primary e );
void delete_exp_from_str( a_Exp_Primary e );
void delete_exp_from_char( a_Exp_Primary e );
void delete_exp_from_array_lit( a_Exp_Primary et );
void delete_exp_from_complex( a_Exp_Primary e );
void delete_exp_from_polar( a_Exp_Primary e );
void delete_exp_from_vec( a_Exp_Primary e );
void delete_exp_from_hack( a_Exp_Primary e );
void delete_exp_decl( a_Exp e );
void delete_var_decl_list( a_Var_Decl_List list );
void delete_var_decl( a_Var_Decl decl );
void delete_type_decl( a_Type_Decl decl );
void delete_arg_list( a_Arg_List list );
void delete_array_sub( a_Array_Sub sub );
void delete_complex( a_Complex c );
void delete_polar( a_Polar p );
void delete_vec( a_Vec v );





//------------------------------------------------------------------------------
// helper structs
//------------------------------------------------------------------------------
// 1.5.2.0 (ge) added constructor support
struct a_Ctor_Call_ { int invoked; a_Exp args; t_CKFUNC func; int primitive; };
//------------------------------------------------------------------------------
// abstract syntax tree | structs
//------------------------------------------------------------------------------
struct a_Exp_Binary_ { a_Exp lhs; ae_Operator op; a_Exp rhs; t_CKFUNC ck_func; t_CKFUNC ck_overload_func; uint32_t line; uint32_t where; a_Exp self; };
struct a_Exp_Cast_ { a_Type_Decl type; a_Exp exp; uint32_t line; uint32_t where; a_Exp self; };
struct a_Exp_Unary_ { ae_Operator op; a_Exp exp; a_Type_Decl type; struct a_Ctor_Call_ ctor; a_Array_Sub array;
                      a_Stmt code; t_CKFUNC ck_overload_func; uint32_t line; uint32_t where; a_Exp self; };
struct a_Exp_Postfix_ { a_Exp exp; ae_Operator op; t_CKFUNC ck_overload_func; uint32_t line; uint32_t where; a_Exp self; };
struct a_Exp_Dur_ { a_Exp base; a_Exp unit; uint32_t line; uint32_t where; a_Exp self; };
struct a_Exp_Array_ { a_Exp base; a_Array_Sub indices; uint32_t line; uint32_t where; a_Exp self; };
struct a_Exp_Func_Call_ { a_Exp func; a_Exp args; t_CKTYPE ret_type;
                          t_CKFUNC ck_func; t_CKVMCODE ck_vm_code; uint32_t line; uint32_t where; a_Exp self; };
struct a_Exp_Dot_Member_ { a_Exp base; t_CKTYPE t_base; S_Symbol xid; t_CKBOOL isSpecialPrimitiveFunc; uint32_t line; uint32_t where; a_Exp self; };
struct a_Exp_If_ { a_Exp cond; a_Exp if_exp; a_Exp else_exp; uint32_t line; uint32_t where; a_Exp self; };
struct a_Exp_Decl_ { a_Type_Decl type; a_Var_Decl_List var_decl_list; int num_var_decls; int is_static; int is_global;
                     int is_const; t_CKTYPE ck_type; int is_auto; uint32_t line; uint32_t where; a_Exp self; };
struct a_Exp_Hack_ { a_Exp exp; uint32_t line; uint32_t where; a_Exp self; };
struct a_Var_Decl_List_ { a_Var_Decl var_decl; a_Var_Decl_List next; uint32_t line; uint32_t where; a_Exp self; };
// 1.4.2.0 (ge) added ck_type and ref, to handle multiple array decl (e.g., int x, y[], z[1];)
struct a_Var_Decl_ { S_Symbol xid; struct a_Ctor_Call_ ctor;
                     a_Array_Sub array; t_CKVALUE value; void * addr; t_CKTYPE ck_type;
                     /* int is_auto; */ int ref; int force_ref;
                     uint32_t line; uint32_t where; a_Exp self; };
struct a_Type_Decl_ { a_Id_List xid; a_Array_Sub array; int ref; uint32_t line; uint32_t where; /*a_Exp self;*/ };
struct a_Array_Sub_ { t_CKUINT depth; a_Exp exp_list; uint32_t line; uint32_t where; a_Exp self;
                      int err_num; int err_pos; };
struct a_Arg_List_ { a_Type_Decl type_decl; a_Var_Decl var_decl; t_CKTYPE type;
                     a_Arg_List next; uint32_t line; uint32_t where; a_Exp self; };
struct a_Complex_ { a_Exp re; a_Exp im; uint32_t line; uint32_t where; a_Exp self; };
struct a_Polar_ { a_Exp mod; a_Exp phase; uint32_t line; uint32_t where; a_Exp self; };
struct a_Vec_ { a_Exp args; int numdims; uint32_t line; uint32_t where; a_Exp self; }; // ge: added 1.3.5.3
struct a_Import_ { c_str what; a_Import next; uint32_t line; uint32_t where; }; // 1.5.4.0 (ge) added
struct a_Doc_ { c_str desc; a_Doc next; uint32_t line; uint32_t where; }; // 1.5.4.4(ge) added

// enum primary exp type
typedef enum { ae_primary_var, ae_primary_num, ae_primary_float,
               ae_primary_str, ae_primary_array, ae_primary_exp,
               ae_primary_hack, ae_primary_complex, ae_primary_polar,
               ae_primary_vec, ae_primary_char, ae_primary_nil
             } ae_Exp_Primary_Type;

struct a_Exp_Primary_
{
    ae_Exp_Primary_Type s_type;
    t_CKVALUE value;
    // 1.5.4.4 (ge) added to alias a contructor to this() #2024-ctor-this
    t_CKFUNC func_alias;

    union
    {
        S_Symbol var;
        t_CKINT num;
        t_CKFLOAT fnum;
        c_str str;
        c_str chr;
        a_Array_Sub array;
        a_Exp exp;
        a_Complex complex;
        a_Polar polar;
        a_Vec vec; // ge: added 1.3.5.3
    };

    uint32_t line; uint32_t where;
    a_Exp self;
};

// enum exp type
typedef enum { ae_exp_binary = 0, ae_exp_unary, ae_exp_cast, ae_exp_postfix,
               ae_exp_dur, ae_exp_primary, ae_exp_array, ae_exp_func_call,
               ae_exp_dot_member, ae_exp_if, ae_exp_decl
             } ae_Exp_Type;
// type meta data
typedef enum { ae_meta_value = 0, ae_meta_var } ae_Exp_Meta;

struct a_Exp_
{
    ae_Exp_Type s_type;
    ae_Exp_Meta s_meta;
    t_CKTYPE type;
    t_CKNSPC owner;
    a_Exp next;

    t_CKUINT group_size;
    t_CKTYPE cast_to;
    t_CKUINT emit_var; // 1 = emit var, 2 = emit var and value

    // assuming this Exp is a func, this will properly
    // emit in preparation to be called | 1.5.4.3 (ge) added
    // #2024-func-call-update
    t_CKBOOL emit_as_funccall;

    union
    {
        struct a_Exp_Binary_ binary;
        struct a_Exp_Unary_ unary;
        struct a_Exp_Cast_ cast;
        struct a_Exp_Postfix_ postfix;
        struct a_Exp_Dur_ dur;
        struct a_Exp_Primary_ primary;
        struct a_Exp_Array_ array;
        struct a_Exp_Func_Call_ func_call;
        struct a_Exp_Dot_Member_ dot_member;
        struct a_Exp_If_ exp_if;
        struct a_Exp_Decl_ decl;
    };

    uint32_t line; uint32_t where;
};

struct a_Stmt_While_ { int is_do; a_Exp cond; a_Stmt body; uint32_t line; uint32_t where; a_Stmt self; };
struct a_Stmt_Until_ { int is_do; a_Exp cond; a_Stmt body; uint32_t line; uint32_t where; a_Stmt self; };
struct a_Stmt_For_ { a_Stmt c1; a_Stmt c2; a_Exp c3; a_Stmt body; uint32_t line; uint32_t where; a_Stmt self; };
struct a_Stmt_ForEach_ { a_Exp theIter; a_Exp theArray; a_Stmt body; uint32_t line; uint32_t where; a_Stmt self; };
struct a_Stmt_Loop_ { a_Exp cond; a_Stmt body; uint32_t line; uint32_t where; a_Stmt self; };
struct a_Stmt_If_ { a_Exp cond; a_Stmt if_body; a_Stmt else_body; uint32_t line; uint32_t where; a_Stmt self; };
struct a_Stmt_Switch_ { a_Exp val; uint32_t line; uint32_t where; a_Stmt self; };
struct a_Stmt_Break_ { uint32_t line; uint32_t where; a_Stmt self; };
struct a_Stmt_Continue_ { uint32_t line; uint32_t where; a_Stmt self; };
struct a_Stmt_Return_ { a_Exp val; uint32_t line; uint32_t where; a_Stmt self; };
struct a_Stmt_Case_ { a_Exp exp; uint32_t line; uint32_t where; a_Stmt self; };
struct a_Stmt_GotoLabel_ { S_Symbol name; uint32_t line; uint32_t where; a_Stmt self; };
struct a_Stmt_Import_ { a_Import list; uint32_t line; uint32_t where; a_Stmt self; };
struct a_Stmt_Doc_ { a_Doc list; uint32_t line; uint32_t where; a_Stmt self; };
struct a_Stmt_Code_
{
    // statement list
    a_Stmt_List stmt_list;
    // used to track control paths in non-void functions
    t_CKBOOL allControlPathsReturn; // 1.5.1.0 (ge) added
    // code position
    uint32_t line; uint32_t where; a_Stmt self;
};

// enum values for stmt type
typedef enum { ae_stmt_exp, ae_stmt_while, ae_stmt_until, ae_stmt_for, ae_stmt_foreach,
               ae_stmt_loop, ae_stmt_if, ae_stmt_code, ae_stmt_switch, ae_stmt_break,
               ae_stmt_continue, ae_stmt_return, ae_stmt_case, ae_stmt_gotolabel,
               ae_stmt_import, ae_stmt_doc
             } ae_Stmt_Type;

// a statement
struct a_Stmt_
{
    // type of the statement
    ae_Stmt_Type s_type;
    // used to track control paths in non-void functions
    t_CKBOOL allControlPathsReturn; // 1.5.1.0 (ge) added
    // number of obj refs that needs releasing after | 1.5.1.7 (ge) added
    t_CKUINT numObjsToRelease;
    // does stmt have a static variable declaration | 1.5.4.3 (ge) added for #2024-static-init
    // (used to mark a statement as part of static initializer for a class)
    t_CKBOOL hasStaticDecl;

    // mushed into one!
    union
    {
        a_Exp stmt_exp;
        struct a_Stmt_Code_ stmt_code;
        struct a_Stmt_While_ stmt_while;
        struct a_Stmt_Until_ stmt_until;
        struct a_Stmt_Loop_ stmt_loop;
        struct a_Stmt_For_ stmt_for;
        struct a_Stmt_ForEach_ stmt_foreach;
        struct a_Stmt_If_ stmt_if;
        struct a_Stmt_Switch_ stmt_switch;
        struct a_Stmt_Break_ stmt_break;
        struct a_Stmt_Continue_ stmt_continue;
        struct a_Stmt_Return_ stmt_return;
        struct a_Stmt_Case_ stmt_case;
        struct a_Stmt_GotoLabel_ stmt_gotolabel;
        struct a_Stmt_Import_ stmt_import;
        struct a_Stmt_Doc_ stmt_doc;
    };

    // code position
    uint32_t line; uint32_t where;
};

// list of statements, e.g., as enclosed by { }
struct a_Stmt_List_
{
    // a statement
    a_Stmt stmt;
    // next in list
    a_Stmt_List next;
    // code position
    uint32_t line; uint32_t where;
};

// class definition AST node
struct a_Class_Def_ { ae_Keyword decl; a_Id_List name; a_Class_Ext ext;
                      a_Class_Body body; t_CKTYPE type; int iface; t_CKNSPC home;
                      uint32_t line; uint32_t where; };
struct a_Class_Ext_ { a_Id_List extend_id; a_Id_List impl_list; uint32_t line; uint32_t where; };
struct a_Class_Body_ { a_Section section; a_Class_Body next; uint32_t line; uint32_t where; };
struct a_Id_List_ { S_Symbol xid; a_Id_List next; uint32_t line; uint32_t where; };

typedef enum { ae_func_user, ae_func_builtin } ae_Func_Type;
// struct t_Func_User_ { uint32_t line; uint32_t where; };
// typedef unsigned int (* builtin_func_ptr)( unsigned int arg );
// struct t_Func_BuiltIn_ { builtin_func_ptr func_ptr; uint32_t line; uint32_t where; };
struct a_Func_Def_ {
    ae_Keyword func_decl;
    ae_Keyword static_decl;
    a_Type_Decl type_decl;
    t_CKTYPE ret_type;
    S_Symbol name;
    ae_Operator op2overload; // 1.5.1.5 (ge) added
    a_Arg_List arg_list;
    a_Stmt code;
    t_CKFUNC ck_func;
    unsigned int global;
    unsigned int s_type;
    unsigned int stack_depth;
    void * dl_func_ptr; // should be not NULL iff s_type == ae_func_builtin
    ae_FuncPointerKind dl_fp_kind; // kind of func_ptr | 1.5.2.0 (ge) added
    uint32_t ast_owned; // 1.5.0.5 (ge) maintained by AST?
    uint32_t overload_post; // 1.5.1.5 (ge) overload as post? e.g., @operator(args) ++ (unary only)
    uint32_t vm_refs; // 1.5.0.5 (ge) # of VM references
    uint32_t line; uint32_t where; uint32_t operWhere;
};

// enum values for section types
typedef enum { ae_section_stmt, ae_section_class, ae_section_func } ae_Section_Type;

struct a_Section_
{
    ae_Section_Type s_type;

    union
    {
        a_Stmt_List stmt_list;
        a_Class_Def class_def;
        a_Func_Def func_def;
    };

    uint32_t line; uint32_t where;
};

struct a_Program_ { a_Section section; a_Program next; uint32_t line; uint32_t where; };


#if defined(_cplusplus) || defined(__cplusplus)
}
#endif



#endif
/*----------------------------------------------------------------------------
  ChucK Strongly-timed Audio Programming Language
    Compiler, Virtual Machine, and Synthesis Engine

  Copyright (c) 2003 Ge Wang and Perry R. Cook. All rights reserved.
    http://chuck.stanford.edu/
    http://chuck.cs.princeton.edu/

  This program is free software; you can redistribute it and/or modify
  it under the dual-license terms of EITHER the MIT License OR the GNU
  General Public License (the latter as published by the Free Software
  Foundation; either version 2 of the License or, at your option, any
  later version).

  This program is distributed in the hope that it will be useful and/or
  interesting, but WITHOUT ANY WARRANTY; without even the implied warranty
  of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  MIT Licence and/or the GNU General Public License for details.

  You should have received a copy of the MIT License and the GNU General
  Public License (GPL) along with this program; a copy of the GPL can also
  be obtained by writing to the Free Software Foundation, Inc., 59 Temple
  Place, Suite 330, Boston, MA 02111-1307 U.S.A.
-----------------------------------------------------------------------------*/

//-----------------------------------------------------------------------------
// name: chuck_dl.h
// desc: chuck dynamic linking header
//
// NOTE: this file is shared by two perspectives: 1) chuck hosts, as well
//       as 2) chugins -- determined by the __CHUCK_CHUGIN__ macro:
//       __CHUCK_CHUGIN__ is NOT defined: assume chuck host perspective
//       __CHUCK_CHUGIN__ is defined: assume chugin perspective
//
//       (ALL chugins must define __CHUCK_CHUGIN__
//        conversely, NO host should define __CHUCK_CHUGIN__)
//
// authors: Ge Wang (ge@ccrma.stanford.edu | gewang@cs.princeton.edu)
//          Ari Lazier (alazier@cs.princeton.edu)
//          Spencer Salazar (spencer@ccrma.stanford.edu)
//          macOS code based on apple's open source
//
// date: spring 2004 - 1.1 - internal modules interface
//       spring 2005 - 1.2
//       ...
//        circa 2013 - support for chugins
//       ...
//       summer 2023 - chugins DL api v9
//         fall 2023 - transition to single-header `chugin.h` | 1.5.2.0
//         fall 2023 - chugins DL api v10
//-----------------------------------------------------------------------------
#ifndef __CHUCK_DL_H__
#define __CHUCK_DL_H__

#include <string>
#include <vector>
#include <map>


// major API version: significant semantic and/or API update
// major API version must be the same between chuck:chugin
#define CK_DLL_VERSION_MAJOR (10)
// minor API version: revisions
// minor API version of chuck must >= API version of chugin
#define CK_DLL_VERSION_MINOR (2)
#define CK_DLL_VERSION_MAKE(maj,min) ((t_CKUINT)(((maj) << 16) | (min)))
#define CK_DLL_VERSION_GETMAJOR(v) (((v) >> 16) & 0xFFFF)
#define CK_DLL_VERSION_GETMINOR(v) ((v) & 0xFFFF)
#define CK_DLL_VERSION (CK_DLL_VERSION_MAKE(CK_DLL_VERSION_MAJOR, CK_DLL_VERSION_MINOR))

// string literal containing default chugin paths (platform-specific)
extern char g_default_path_system[];
extern char g_default_path_packages[];
extern char g_default_path_user[];
// string literal containing environment variable names for import search path
extern char g_envvar_path_system[];
extern char g_envvar_path_packages[];
extern char g_envvar_path_user[];
// contains deprecated env var name
extern char g_envvar_path_deprecated[];


// DL forward references
struct Chuck_DL_Query;
struct Chuck_DL_Class;
struct Chuck_DL_Func;
struct Chuck_DL_Value;
struct Chuck_DL_Ctrl;
union  Chuck_DL_Return;
struct Chuck_DL_MainThreadHook;
struct Chuck_DLL;
struct Chuck_DL_Api;
// un-namespaced Chuck_DL_Api | 1.5.1.5 (ge)
// namespace Chuck_DL_Api { struct Api; }

// object forward references
struct Chuck_VM;
struct Chuck_VM_Object;
struct Chuck_VM_Shred;
struct Chuck_Env;
struct Chuck_Compiler;
struct Chuck_Carrier;
struct Chuck_Object;
struct Chuck_Event;
struct Chuck_String;
struct Chuck_ArrayInt;
struct Chuck_ArrayFloat;
struct Chuck_ArrayVec2;
struct Chuck_ArrayVec3;
struct Chuck_ArrayVec4;
struct Chuck_UGen;
struct Chuck_UAna;
struct Chuck_UAnaBlobProxy;

// utility for references
class CBufferSimple;


// param conversion - to extract values from ARGS to functions
#define GET_CK_FLOAT(ptr)      (*(t_CKFLOAT *)ptr)
#define GET_CK_SINGLE(ptr)     (*(float *)ptr)
#define GET_CK_DOUBLE(ptr)     (*(double *)ptr)
#define GET_CK_INT(ptr)        (*(t_CKINT *)ptr)
#define GET_CK_UINT(ptr)       (*(t_CKUINT *)ptr)
#define GET_CK_TIME(ptr)       (*(t_CKTIME *)ptr)
#define GET_CK_DUR(ptr)        (*(t_CKDUR *)ptr)
#define GET_CK_COMPLEX(ptr)    (*(t_CKCOMPLEX *)ptr)
#define GET_CK_POLAR(ptr)      (*(t_CKPOLAR *)ptr)
#define GET_CK_VEC2(ptr)       (*(t_CKVEC2 *)ptr)
#define GET_CK_VEC3(ptr)       (*(t_CKVEC3 *)ptr)
#define GET_CK_VEC4(ptr)       (*(t_CKVEC4 *)ptr)
#define GET_CK_VECTOR(ptr)     (*(t_CKVECTOR *)ptr)
#define GET_CK_OBJECT(ptr)     (*(Chuck_Object **)ptr)
#define GET_CK_STRING(ptr)     (*(Chuck_String **)ptr)

// param conversion with pointer advance
#define GET_NEXT_FLOAT(ptr)    (*((t_CKFLOAT *&)ptr)++)
#define GET_NEXT_SINGLE(ptr)   (*((float *&)ptr)++)
#define GET_NEXT_DOUBLE(ptr)   (*((double *&)ptr)++)
#define GET_NEXT_INT(ptr)      (*((t_CKINT *&)ptr)++)
#define GET_NEXT_UINT(ptr)     (*((t_CKUINT *&)ptr)++)
#define GET_NEXT_TIME(ptr)     (*((t_CKTIME *&)ptr)++)
#define GET_NEXT_DUR(ptr)      (*((t_CKDUR *&)ptr)++)
#define GET_NEXT_COMPLEX(ptr)  (*((t_CKCOMPLEX *&)ptr)++)
#define GET_NEXT_POLAR(ptr)    (*((t_CKPOLAR *&)ptr)++)
#define GET_NEXT_VEC2(ptr)     (*((t_CKVEC2 *&)ptr)++)
#define GET_NEXT_VEC3(ptr)     (*((t_CKVEC3 *&)ptr)++)
#define GET_NEXT_VEC4(ptr)     (*((t_CKVEC4 *&)ptr)++)
#define GET_NEXT_VECTOR(ptr)   (*((t_CKVECTOR *&)ptr)++)
#define GET_NEXT_OBJECT(ptr)   (*((Chuck_Object **&)ptr)++)
#define GET_NEXT_STRING(ptr)   (*((Chuck_String **&)ptr)++)

// string-specific operations
#ifndef __CHUCK_CHUGIN__ // CHUGIN flag NOT present
// assume macro used from host
#define GET_CK_STRING_SAFE(ptr) std::string( GET_CK_STRING(ptr)->c_str() )
#define GET_NEXT_STRING_SAFE(ptr) std::string( GET_NEXT_STRING(ptr)->c_str() )
#else // CHUGIN flag is present
// assume macro used from chugin; use chugins runtime API for portability
#define GET_CK_STRING_SAFE(ptr) std::string( API->object->str((Chuck_String *)ptr) )
#define GET_NEXT_STRING_SAFE(ptr) std::string( API->object->str(GET_NEXT_STRING(ptr) ) )
#endif

// param conversion
#define SET_CK_FLOAT(ptr,v)      (*(t_CKFLOAT *&)ptr=v)
#define SET_CK_SINGLE(ptr,v)     (*(float *&)ptr=v)
#define SET_CK_DOUBLE(ptr,v)     (*(double *&)ptr=v)
#define SET_CK_INT(ptr,v)        (*(t_CKINT *&)ptr=v)
#define SET_CK_UINT(ptr,v)       (*(t_CKUINT *&)ptr=v)
#define SET_CK_TIME(ptr,v)       (*(t_CKTIME *&)ptr=v)
#define SET_CK_DUR(ptr,v)        (*(t_CKDUR *&)ptr=v)
#define SET_CK_VEC2(ptr,v)       (*(t_CKVEC2 *&)ptr=v)
#define SET_CK_VEC3(ptr,v)       (*(t_CKVEC3 *&)ptr=v)
#define SET_CK_VEC4(ptr,v)       (*(t_CKVEC4 *&)ptr=v)
#define SET_CK_VECTOR(ptr,v)     (*(t_CKVECTOR *&)ptr=v)
#define SET_CK_STRING(ptr,v)     (*(Chuck_String **&)ptr=v)

// param conversion with pointer advance
#define SET_NEXT_FLOAT(ptr,v)    (*((t_CKFLOAT *&)ptr)++=v)
#define SET_NEXT_SINGLE(ptr,v)   (*((float *&)ptr)++=v)
#define SET_NEXT_DOUBLE(ptr,v)   (*((double *&)ptr)++=v)
#define SET_NEXT_INT(ptr,v)      (*((t_CKINT *&)ptr)++=v)
#define SET_NEXT_UINT(ptr,v)     (*((t_CKUINT *&)ptr)++=v)
#define SET_NEXT_TIME(ptr,v)     (*((t_CKTIME *&)ptr)++=v)
#define SET_NEXT_DUR(ptr,v)      (*((t_CKDUR *&)ptr)++=v)
#define SET_NEXT_VEC2(ptr,v)     (*((t_CKVEC2 *&)ptr)++=v)
#define SET_NEXT_VEC3(ptr,v)     (*((t_CKVEC3 *&)ptr)++=v)
#define SET_NEXT_VEC4(ptr,v)     (*((t_CKVEC4 *&)ptr)++=v)
#define SET_NEXT_VECTOR(ptr,v)   (*((t_CKVECTOR *&)ptr)++=v)
#define SET_NEXT_STRING(ptr,v)   (*((Chuck_String **&)ptr)++=v)

// param conversion - to access values from an Object's data segment
//-----------------------------------------------------------------------------
// take action depending on where the macro is used, and as determined by the
// presence or absence of the __CHUCK_CHUGIN__ preprocessor macro:
// -- 1) macro NOT present: assume macro is used from within a chuck host
// (CLI chuck, miniAudicle, or any c++ system that integrates the ChucK system
// (compiler, VM, synthesis engine), then directly access obj->data
// -- 2) macro is present: assume macro is used from within a chugin;
// access Object data using the chugin runtime DL API
//-----------------------------------------------------------------------------
#ifndef __CHUCK_CHUGIN__ // CHUGIN flag NOT present
// assume macro used from chuck host
#define OBJ_MEMBER_DATA(obj,offset)     (obj->data + offset)
#else // CHUGIN flag is present
// assume macro used from chugin
#define OBJ_MEMBER_DATA(obj,offset)     (API->object->data(obj,offset))
#endif // #ifndef __CHUCK_CHUGIN__
//-----------------------------------------------------------------------------
// param conversion - to extract values from object's data segment
#define OBJ_MEMBER_FLOAT(obj,offset)    (*(t_CKFLOAT *)OBJ_MEMBER_DATA(obj,offset))
#define OBJ_MEMBER_SINGLE(obj,offset)   (*(float *)OBJ_MEMBER_DATA(obj,offset))
#define OBJ_MEMBER_DOUBLE(obj,offset)   (*(double *)OBJ_MEMBER_DATA(obj,offset))
#define OBJ_MEMBER_INT(obj,offset)      (*(t_CKINT *)OBJ_MEMBER_DATA(obj,offset))
#define OBJ_MEMBER_UINT(obj,offset)     (*(t_CKUINT *)OBJ_MEMBER_DATA(obj,offset))
#define OBJ_MEMBER_TIME(obj,offset)     (*(t_CKTIME *)OBJ_MEMBER_DATA(obj,offset))
#define OBJ_MEMBER_DUR(obj,offset)      (*(t_CKDUR *)OBJ_MEMBER_DATA(obj,offset))
#define OBJ_MEMBER_VEC2(obj,offset)     (*(t_CKVEC2 *)OBJ_MEMBER_DATA(obj,offset))
#define OBJ_MEMBER_VEC3(obj,offset)     (*(t_CKVEC3 *)OBJ_MEMBER_DATA(obj,offset))
#define OBJ_MEMBER_VEC4(obj,offset)     (*(t_CKVEC4 *)OBJ_MEMBER_DATA(obj,offset))
#define OBJ_MEMBER_VECTOR(obj,offset)   (*(t_CKVECTOR *)OBJ_MEMBER_DATA(obj,offset))
#define OBJ_MEMBER_OBJECT(obj,offset)   (*(Chuck_Object **)OBJ_MEMBER_DATA(obj,offset))
#define OBJ_MEMBER_STRING(obj,offset)   (*(Chuck_String **)OBJ_MEMBER_DATA(obj,offset))


// chuck dll export linkage and calling convention
#if defined (__PLATFORM_WINDOWS__)
  #define CK_DLL_LINKAGE extern "C" __declspec( dllexport )
#else
  #define CK_DLL_LINKAGE extern "C"
#endif

// calling convention of functions provided by chuck to the dll
#if defined(__PLATFORM_WINDOWS__)
  #define CK_DLL_CALL    _cdecl
#else
  #define CK_DLL_CALL
#endif

// DL api pointer
typedef const Chuck_DL_Api * CK_DL_API;

// macro for defining ChucK DLL export functions
// example: CK_DLL_EXPORT(int) foo() { return 1; }
#define CK_DLL_EXPORT(type) CK_DLL_LINKAGE type CK_DLL_CALL
// macro for declaring version of ChucK DL a given DLL links to
// example: CK_DLL_DECLVERSION
#define CK_DLL_DECLVERSION CK_DLL_EXPORT(t_CKUINT) ck_version() { return CK_DLL_VERSION; }
// macro for defining a DLL info func
#define CK_DLL_INFO(name) CK_DLL_EXPORT(void) ck_info( Chuck_DL_Query * QUERY )
// naming convention for static query functions
#define CK_DLL_QUERY_STATIC_NAME(name) ck_##name##_query
// macro for defining ChucK DLL export query-functions (static version)
#define CK_DLL_QUERY_STATIC(name) CK_DLL_EXPORT(t_CKBOOL) CK_DLL_QUERY_STATIC_NAME(name)( Chuck_DL_Query * QUERY )
// macro for defining ChucK DLL export query-functions | example: CK_DLL_QUERY(Foo) { ... }
#ifndef __CK_DLL_STATIC__
#define CK_DLL_QUERY(name) CK_DLL_DECLVERSION CK_DLL_EXPORT(t_CKBOOL) ck_query( Chuck_DL_Query * QUERY )
#else
#define CK_DLL_QUERY(name) CK_DLL_QUERY_STATIC(name)
#endif // __CK_DLL_STATIC__
// macro for defining ChucK DLL export allocator
// example: CK_DLL_ALLOC(foo)
#define CK_DLL_ALLOC(name) CK_DLL_EXPORT(Chuck_Object *) name( Chuck_VM * VM, Chuck_VM_Shred * SHRED, CK_DL_API API )
// macro for defining ChucK DLL export constructors
// example: CK_DLL_CTOR(foo)
#define CK_DLL_CTOR(name) CK_DLL_EXPORT(void) name( Chuck_Object * SELF, void * ARGS, Chuck_VM * VM, Chuck_VM_Shred * SHRED, CK_DL_API API )
// macro for defining ChucK DLL export destructors
// example: CK_DLL_DTOR(foo)
#define CK_DLL_DTOR(name) CK_DLL_EXPORT(void) name( Chuck_Object * SELF, Chuck_VM * VM, Chuck_VM_Shred * SHRED, CK_DL_API API )
// macro for defining ChucK DLL export member functions
// example: CK_DLL_MFUN(foo)
#define CK_DLL_MFUN(name) CK_DLL_EXPORT(void) name( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM * VM, Chuck_VM_Shred * SHRED, CK_DL_API API )
// macro for defining ChucK DLL export static functions
// example: CK_DLL_SFUN(foo) | 1.4.1.0 (ge) added TYPE to static prototype
#define CK_DLL_SFUN(name) CK_DLL_EXPORT(void) name( Chuck_Type * TYPE, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM * VM, Chuck_VM_Shred * SHRED, CK_DL_API API )
// example: CK_DLL_GFUN(foo) | 1.5.1.5 (ge & andrew) added for global-scope function, e.g., for op overloads
#define CK_DLL_GFUN(name) CK_DLL_EXPORT(void) name( void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM * VM, Chuck_VM_Shred * SHRED, CK_DL_API API )
// macro for defining ChucK DLL export ugen tick functions
// example: CK_DLL_TICK(foo)
#define CK_DLL_TICK(name) CK_DLL_EXPORT(t_CKBOOL) name( Chuck_Object * SELF, SAMPLE in, SAMPLE * out, CK_DL_API API )
// macro for defining ChucK DLL export ugen multi-channel tick functions
// example: CK_DLL_TICKF(foo)
#define CK_DLL_TICKF(name) CK_DLL_EXPORT(t_CKBOOL) name( Chuck_Object * SELF, SAMPLE * in, SAMPLE * out, t_CKUINT nframes, CK_DL_API API )
// macro for defining ChucK DLL export ugen ctrl functions
// example: CK_DLL_CTRL(foo)
#define CK_DLL_CTRL(name) CK_DLL_EXPORT(void) name( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM * VM, Chuck_VM_Shred * SHRED, CK_DL_API API )
// macro for defining ChucK DLL export ugen cget functions
// example: CK_DLL_CGET(foo)
#define CK_DLL_CGET(name) CK_DLL_EXPORT(void) name( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM * VM, Chuck_VM_Shred * SHRED, CK_DL_API API )
// macro for defining ChucK DLL export ugen pmsg functions
// example: CK_DLL_PMSG(foo)
#define CK_DLL_PMSG(name) CK_DLL_EXPORT(t_CKBOOL) name( Chuck_Object * SELF, const char * MSG, void * ARGS, Chuck_VM * VM, Chuck_VM_Shred * SHRED, CK_DL_API API )
// macro for defining ChucK DLL export uana tock functions
// example: CK_DLL_TOCK(foo)
#define CK_DLL_TOCK(name) CK_DLL_EXPORT(t_CKBOOL) name( Chuck_Object * SELF, Chuck_UAna * UANA, Chuck_UAnaBlobProxy * BLOB, CK_DL_API API )
// macro for defining Chuck DLL export shreds watcher functions
// example: CK_DLL_SHREDS_WATCHER(foo)
#define CK_DLL_SHREDS_WATCHER(name) CK_DLL_EXPORT(void) name( Chuck_VM_Shred * SHRED, t_CKINT CODE, t_CKINT PARAM, Chuck_VM * VM, void * BINDLE )
// macro for defining Chuck DLL export type on instantiate functions
// example: CK_DLL_TYPE_ON_INSTANTIATE(foo)
#define CK_DLL_TYPE_ON_INSTANTIATE(name) CK_DLL_EXPORT(void) name( Chuck_Object * OBJECT, Chuck_Type * TYPE, Chuck_VM_Shred * SHRED, Chuck_VM * VM )

// macros for DLL exports
// example: DLL_QUERY  query( Chuck_DL_Query * QUERY )
// example: DLL_FUNC   foo( void * ARGS, Chuck_DL_Return * RETURN )
// example: DLL_UGEN_F foo_tick( Chuck_UGen * SELF, SAMPLE, SAMPLE * out );
#define DLL_QUERY   CK_DLL_EXPORT(t_CKBOOL)
#define DLL_FUNC    CK_DLL_EXPORT(void)
#define UGEN_CTOR   CK_DLL_EXPORT(void *)
#define UGEN_DTOR   CK_DLL_EXPORT(void)
#define UGEN_TICK   CK_DLL_EXPORT(t_CKBOOL)
#define UGEN_PMSG   CK_DLL_EXPORT(t_CKBOOL)
#define UGEN_CTRL   CK_DLL_EXPORT(t_CKVOID)
#define UGEN_CGET   CK_DLL_EXPORT(t_CKVOID)
#define UANA_TOCK   CK_DLL_EXPORT(t_CKBOOL)


//-----------------------------------------------------------------------------
// dynamic linking class interface prototypes
//-----------------------------------------------------------------------------
extern "C" {
// query
typedef t_CKUINT (CK_DLL_CALL * f_ck_declversion)();
typedef t_CKVOID (CK_DLL_CALL * f_ck_info)( Chuck_DL_Query * QUERY );
typedef t_CKBOOL (CK_DLL_CALL * f_ck_query)( Chuck_DL_Query * QUERY );
// object
typedef Chuck_Object * (CK_DLL_CALL * f_alloc)( Chuck_VM * VM, Chuck_VM_Shred * SHRED, CK_DL_API API );
typedef t_CKVOID (CK_DLL_CALL * f_ctor)( Chuck_Object * SELF, void * ARGS, Chuck_VM * VM, Chuck_VM_Shred * SHRED, CK_DL_API API );
typedef t_CKVOID (CK_DLL_CALL * f_dtor)( Chuck_Object * SELF, Chuck_VM * VM, Chuck_VM_Shred * SHRED, CK_DL_API API );
typedef t_CKVOID (CK_DLL_CALL * f_mfun)( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM * VM, Chuck_VM_Shred * SHRED, CK_DL_API API );
// 1.4.1.0 (ge) added TYPE to static prototype
typedef t_CKVOID (CK_DLL_CALL * f_sfun)( Chuck_Type * TYPE, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM * VM, Chuck_VM_Shred * SHRED, CK_DL_API API );
// 1.5.1.5 (ge & andrew) added for global-scope function, e.g., for op overloads
typedef t_CKVOID (CK_DLL_CALL * f_gfun)( void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM * VM, Chuck_VM_Shred * SHRED, CK_DL_API API );
// ugen specific
typedef t_CKBOOL (CK_DLL_CALL * f_tick)( Chuck_Object * SELF, SAMPLE in, SAMPLE * out, CK_DL_API API );
typedef t_CKBOOL (CK_DLL_CALL * f_tickf)( Chuck_Object * SELF, SAMPLE * in, SAMPLE * out, t_CKUINT nframes, CK_DL_API API );
typedef t_CKVOID (CK_DLL_CALL * f_ctrl)( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM * VM, Chuck_VM_Shred * SHRED, CK_DL_API API );
typedef t_CKVOID (CK_DLL_CALL * f_cget)( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM * VM, Chuck_VM_Shred * SHRED, CK_DL_API API );
typedef t_CKBOOL (CK_DLL_CALL * f_pmsg)( Chuck_Object * SELF, const char * MSG, void * ARGS, Chuck_VM * VM, Chuck_VM_Shred * SHRED, CK_DL_API API );
// uana specific
typedef t_CKBOOL (CK_DLL_CALL * f_tock)( Chuck_Object * SELF, Chuck_UAna * UANA, Chuck_UAnaBlobProxy * BLOB, CK_DL_API API );
// "main thread" hook
typedef t_CKBOOL (CK_DLL_CALL * f_mainthreadhook)( void * bindle );
// "main thread" quit (stop running hook)
typedef t_CKBOOL (CK_DLL_CALL * f_mainthreadquit)( void * bindle );
// callback function, called on host shutdown
typedef void (CK_DLL_CALL * f_callback_on_shutdown)( void * bindle );
// sample rate update callback | 1.5.4.2 (ge) added
typedef void (CK_DLL_CALL * f_callback_on_srate_update)( t_CKUINT srate, void * bindle );
// shreds watcher callback
typedef void (CK_DLL_CALL * f_shreds_watcher)( Chuck_VM_Shred * SHRED, t_CKINT CODE, t_CKINT PARAM, Chuck_VM * VM, void * BINDLE );
// type instantiation callback
typedef void (CK_DLL_CALL * f_callback_on_instantiate)( Chuck_Object * OBJECT, Chuck_Type * TYPE, Chuck_VM_Shred * originShred, Chuck_VM * VM );
}


// default name in DLL/ckx to look for host/chugin compatibility version func
#define CK_DECLVERSION_FUNC "ck_version"
// default name in DLL/ckx to look for info func
#define CK_INFO_FUNC        "ck_info"
// default name in DLL/ckx to look for for query func
#define CK_QUERY_FUNC       "ck_query"
// bad object data offset
#define CK_INVALID_OFFSET    0xffffffff


//-----------------------------------------------------------------------------
// chuck DLL query functions, implemented on chuck side for portability
//-----------------------------------------------------------------------------
extern "C" {
// get handles: opaque references to VM, API etc.
typedef Chuck_VM * (CK_DLL_CALL * f_get_vm)( Chuck_DL_Query * query );
typedef CK_DL_API (CK_DLL_CALL * f_get_api)( Chuck_DL_Query * query );
typedef Chuck_Env * (CK_DLL_CALL * f_get_env)( Chuck_DL_Query * query );
typedef Chuck_Compiler * (CK_DLL_CALL * f_get_compiler)( Chuck_DL_Query * query );
typedef Chuck_Carrier * (CK_DLL_CALL * f_get_carrier)( Chuck_DL_Query * query );

// set name of module / chugin
typedef void (CK_DLL_CALL * f_setname)( Chuck_DL_Query * query, const char * name );
// set info of module / chugin by (key,value)
typedef void (CK_DLL_CALL * f_setinfo)( Chuck_DL_Query * query, const char * key, const char * value );
// set info of module / chugin by (key,value)
typedef const char * (CK_DLL_CALL * f_getinfo)( Chuck_DL_Query * query, const char * key );

// begin class/namespace, can be nested
typedef void (CK_DLL_CALL * f_begin_class)( Chuck_DL_Query * query, const char * name, const char * parent );
// add constructor, must be betwen begin/end_class : use f_add_arg to add arguments immediately after
typedef void (CK_DLL_CALL * f_add_ctor)( Chuck_DL_Query * query, f_ctor ctor );
// add destructor - cannot have args
typedef void (CK_DLL_CALL * f_add_dtor)( Chuck_DL_Query * query, f_dtor dtor );
// add member function - args to follow
typedef void (CK_DLL_CALL * f_add_mfun)( Chuck_DL_Query * query, f_mfun mfun, const char * type, const char * name );
// add static function - args to follow
typedef void (CK_DLL_CALL * f_add_sfun)( Chuck_DL_Query * query, f_sfun sfun, const char * type, const char * name );
// add binary operator overload - args included
typedef void (CK_DLL_CALL * f_add_op_overload_binary)( Chuck_DL_Query * query, f_gfun gfun, const char * type, const char * op,
                                                       const char * lhsType, const char * lhsName, const char * rhsType, const char * rhsName );
// add unary (prefix) operator overload - arg included
typedef void (CK_DLL_CALL * f_add_op_overload_prefix)( Chuck_DL_Query * query, f_gfun gfun, const char * type, const char * op,
                                                       const char * argType, const char * argName );
// add unary (postfix) operator overload - args included
typedef void (CK_DLL_CALL * f_add_op_overload_postfix)( Chuck_DL_Query * query, f_gfun gfun, const char * type, const char * op,
                                                       const char * argType, const char * argName );
// add member variable
typedef t_CKUINT (CK_DLL_CALL * f_add_mvar)( Chuck_DL_Query * query,
             const char * type, const char * name, t_CKBOOL is_const ); // TODO: public/protected/private
// add static variable
typedef void (CK_DLL_CALL * f_add_svar)( Chuck_DL_Query * query,
             const char * type, const char * name,
             t_CKBOOL is_const, void * static_addr ); // TODO: public/protected/private
// add arg - follows ctor mfun sfun
typedef void (CK_DLL_CALL * f_add_arg)( Chuck_DL_Query * query, const char * type, const char * name );
// ** functions for adding unit generators, must extend ugen
typedef void (CK_DLL_CALL * f_add_ugen_func)( Chuck_DL_Query * query, f_tick tick, f_pmsg pmsg, t_CKUINT num_in, t_CKUINT num_out );
typedef void (CK_DLL_CALL * f_add_ugen_funcf)( Chuck_DL_Query * query, f_tickf tickf, f_pmsg pmsg, t_CKUINT num_in, t_CKUINT num_out );
typedef void (CK_DLL_CALL * f_add_ugen_funcf_auto_num_channels)( Chuck_DL_Query * query, f_tickf tickf, f_pmsg psmg );
// ** add a ugen control (not used) | 1.4.1.0 removed
//typedef void (CK_DLL_CALL * f_add_ugen_ctrl)( Chuck_DL_Query * query, f_ctrl ctrl, f_cget cget,
//                                              const char * type, const char * name );
// end class/namespace - must correspondent with begin_class.  returns false on error
typedef t_CKBOOL (CK_DLL_CALL * f_end_class)( Chuck_DL_Query * query );
// create main thread hook- used for executing a "hook" function in the main thread of a primary chuck instance
typedef Chuck_DL_MainThreadHook * (CK_DLL_CALL * f_create_main_thread_hook)( Chuck_DL_Query * query, f_mainthreadhook hook, f_mainthreadquit quit, void * bindle );
// register a callback to be called on host shutdown, e.g., for chugin cleanup
typedef void (CK_DLL_CALL * f_register_callback_on_shutdown)( Chuck_DL_Query * query, f_callback_on_shutdown cb, void * bindle );
// register a callback to be called on sample rate change
typedef void (CK_DLL_CALL * f_register_callback_on_srate_update)( Chuck_DL_Query * query, f_callback_on_srate_update cb, void * bindle );
// register a callback function to receive notification from the VM about shreds (add, remove, etc.)
typedef void (CK_DLL_CALL * f_register_shreds_watcher)( Chuck_DL_Query * query, f_shreds_watcher cb, t_CKUINT options, void * bindle );
// unregister a shreds notification callback
typedef void (CK_DLL_CALL * f_unregister_shreds_watcher)( Chuck_DL_Query * query, f_shreds_watcher cb );

// documentation
// set current class documentation
typedef t_CKBOOL (CK_DLL_CALL * f_doc_class)( Chuck_DL_Query * query, const char * doc );
// add example of current class
typedef t_CKBOOL (CK_DLL_CALL * f_add_example)( Chuck_DL_Query * query, const char * ex );
// set current function documentation
typedef t_CKBOOL (CK_DLL_CALL * f_doc_func)( Chuck_DL_Query * query, const char * doc );
// set last mvar documentation
typedef t_CKBOOL (CK_DLL_CALL * f_doc_var)( Chuck_DL_Query * query, const char * doc );

} // end extern "C"




//-----------------------------------------------------------------------------
// name: enum ckvm_ShredsWatcherFlag | 1.5.1.5 (ge & andrew) added
// desc: shreds watcher flags; meant to bitwise-OR together in options
//       these will also be passed back to the callback...
//-----------------------------------------------------------------------------
typedef enum {
    ckvm_shreds_watch_NONE = 0,
    ckvm_shreds_watch_SPORK = 1,
    ckvm_shreds_watch_REMOVE = 2,
    ckvm_shreds_watch_SUSPEND = 4,
    ckvm_shreds_watch_ACTIVATE = 8,
    ckvm_shreds_watch_ALL = 0x7fffffff
} ckvm_ShredsWatcherFlag;

//-----------------------------------------------------------------------------
// name: enum ckte_Origin | 1.5.0.0 (ge) added
// desc: where something (e.g., a Type) originates
//-----------------------------------------------------------------------------
typedef enum {
    ckte_origin_UNKNOWN = 0,
    ckte_origin_BUILTIN,     // in core
    ckte_origin_CHUGIN,      // in imported chugin
    ckte_origin_IMPORT,      // library CK code
    ckte_origin_USERDEFINED, // in user chuck code
    ckte_origin_GENERATED    // generated (e.g., array types like int[][][][])
} ckte_Origin;

//-----------------------------------------------------------------------------
// name: enum ckte_Op_OverloadKind | 1.5.1.5 (ge) added
// desc: enumeration for kinds of operator overload
//-----------------------------------------------------------------------------
typedef enum
{
    ckte_op_overload_NONE,
    ckte_op_overload_BINARY,    // LHS op RHS
    ckte_op_overload_UNARY_PRE, //     op RHS
    ckte_op_overload_UNARY_POST // LHS op
} ckte_Op_OverloadKind;

//-----------------------------------------------------------------------------
// key strings for QUERY->setname(...) and QUERY->getinfo(...)
//-----------------------------------------------------------------------------
#define CHUGIN_INFO_NAME           "CHUGIN_INFO_NAME" // same as QUERY->setname()
#define CHUGIN_INFO_AUTHORS        "CHUGIN_INFO_AUTHORS"
#define CHUGIN_INFO_CHUGIN_VERSION "CHUGIN_INFO_CHUGIN_VERSION"
#define CHUGIN_INFO_DESCRIPTION    "CHUGIN_INFO_DESCRIPTION"
#define CHUGIN_INFO_URL            "CHUGIN_INFO_URL"
#define CHUGIN_INFO_EMAIL          "CHUGIN_INFO_EMAIL"
#define CHUGIN_INFO_ID             "CHUGIN_INFO_ID"
// enclosing directory (without the filename) | 1.5.4.5 (ge)
#define CHUGIN_INFO_INSTALL_DIR    "CHUGIN_INFO_INSTALL_DIR"
// filename (without the enclosing directory) |  1.5.4.5 (ge)
#define CHUGIN_INFO_INSTALL_FILE   "CHUGIN_INFO_INSTALL_FILE"
// reserved
#define CHUGIN_INFO_EXTRA          "CHUGIN_INFO_EXTRA"




//-----------------------------------------------------------------------------
// name: struct Chuck_DL_Query
// desc: data structure passed from chuck host to chugin to query its contents:
//       include 1) chugin/module info; 2) classes and operator-overloadings
//       to add to chuck's type system; 3) the chugin can also use the query
//       to get data from from the host, including VM / host sample rate, and
//       a Chuck_DL_Api handle for accessing the chugin-to-host runtime DL API
//-----------------------------------------------------------------------------
struct Chuck_DL_Query
{
//-------------------------------------------------------------------------
// function pointers: to be called from CHUGIN / module
//-------------------------------------------------------------------------
public:
    // -------------
    // functions for accessing useful host-side objects
    // -------------
    // get Chuck_DL_Api for accessing chugin DL runtime API
    // CK_DL_API api = QUERY->ck_api( QUERY );
    f_get_api ck_api;
    // get a handle to host's VM
    // Chuck_VM * vm = QUERY->ck_vm( QUERY );
    f_get_vm ck_vm;

public:
    // -------------
    // functions for registering chugin info such as name, author, URL, etc.
    // -------------
    // set the name of the module, typically the name of the Chugin
    // QUERY->setname( QUERY, "TheChuginName" );
    f_setname setname;
    // set additional info by key | 1.5.2.0 (ge) added
    // see CHUGIN_INFO_* above for info keys
    // QUERY->setinfo( QUERY, key_cstring, value_cstring );
    f_setinfo setinfo;
    // get info by key (do not keep returned pointer; always make a copy):
    // see CHUGIN_INFO_* above for info keys
    // std::string str = QUERY->setinfo( QUERY, key_cstring, value_cstring );
    f_getinfo getinfo;

public:
    // -------------
    // functions for creating new types in chuck's type system, from a chugin
    // -------------
    // begin class/namespace, can be nested
    f_begin_class begin_class;
    // add constructor, can be followed by add_arg
    f_add_ctor add_ctor;
    // add destructor, no args allowed
    f_add_dtor add_dtor;
    // add member function, can be followed by add_arg
    f_add_mfun add_mfun;
    // add static function, can be followed by add_arg
    f_add_sfun add_sfun;
    // add member variable
    f_add_mvar add_mvar;
    // add static variable
    f_add_svar add_svar;
    // add argument to function
    f_add_arg add_arg;
    // (ugen only) add tick and pmsg functions
    f_add_ugen_func add_ugen_func;
    // (ugen only) add tick and pmsg functions
    f_add_ugen_funcf add_ugen_funcf;
    // (ugen only) add tick and pmsg functions, specify channels by vm
    f_add_ugen_funcf_auto_num_channels add_ugen_funcf_auto_num_channels;
    // (ugen only) add ctrl parameters
    // f_add_ugen_ctrl add_ugen_ctrl;  // not used but needed for import for now
    // end class/namespace; compile it
    f_end_class end_class;

public:
    // -------------
    // functions for overloading operators in the type system, from a chugin
    // -------------
    // add binary operator overload; args included | 1.5.1.5 (ge & andrew)
    f_add_op_overload_binary add_op_overload_binary;
    // add unary (prefix) operator overload; arg included
    f_add_op_overload_prefix add_op_overload_prefix;
    // add unary (postfix) operator overload; arg included
    f_add_op_overload_postfix add_op_overload_postfix;

public:
    // -------------
    // these are used to document functions and variables added above
    // the are used for ckdoc generations and .help runtime help
    // -------------
    f_doc_class doc_class;
    f_doc_func doc_func;
    f_doc_var doc_var;
    f_add_example add_ex;

public:
    // -------------
    // register a function to be run on the main thread of chuck host
    // * no more than ONE main thread hooks can be active
    // * typically used by special chugins such as ChuGL or MAUI that
    // deals with graphics or windowing | re-added 1.4.0.1
    // -------------
    f_create_main_thread_hook create_main_thread_hook;

public:
    // -------------
    // register a function to be run on host shutdown; this can be used
    // for chugin cleanup when the host (chuck, miniAudicle, etc.) exits
    // including on SIGINT (ctrl-c termination) | added 1.5.2.5 (ge)
    // -------------
    f_register_callback_on_shutdown register_callback_on_shutdown;

public:
    // -------------
    // register callback to be invoked by chuck host at various
    // stages of a shred's operation | 1.5.1.5 (ge & andrew) added
    // * see `ckvm_ShredsWatcherFlag` enums
    // -------------
    // register shred notifcations
    f_register_shreds_watcher register_shreds_watcher;
    // un-register shred notifcations
    f_unregister_shreds_watcher unregister_shreds_watcher;

public:
    // -------------
    // register callback to be invoked by chuck host on
    // sample rate changes | 1.5.4.2 (ge) added
    // -------------
    f_register_callback_on_srate_update register_callback_on_srate_update;




//-------------------------------------------------------------------------
// HOST ONLY beyond this point...
//-------------------------------------------------------------------------
public:
    //-------------------------------------------------------------------------
    // NOTE: everything below std::anything cannot be reliably accessed by
    // offset across DLL/shared-library boundaries, since std::anything could
    // be variable size; *** chugins should never access anything below ***
    //-------------------------------------------------------------------------
    // *** put everything to be accessed from chugins ABOVE this point! ***
    //-------------------------------------------------------------------------
    // * discovered by the vigilant and forever traumatized Jack Atherton,
    // * fixed during REFACTOR-2017; warning by guilt-ridden Ge Wang
    //-------------------------------------------------------------------------
    // DLL reference
    Chuck_DLL * dll_ref;
    // name of dll
    std::string dll_name;
    // DL API reference | 1.5.1.5
    CK_DL_API m_api;
    // info map | 1.5.2.0
    std::map<std::string, std::string> dll_info;

    // current class
    Chuck_DL_Class * curr_class;
    // current function
    Chuck_DL_Func * curr_func;
    // current variable | added 1.3.5.0
    Chuck_DL_Value * curr_var;
    // collection of classes
    std::vector<Chuck_DL_Class *> classes;
    // stack of classes
    std::vector<Chuck_DL_Class * > stack;
    // collection of operator overloads
    std::vector<Chuck_DL_Func *> op_overloads;

public: // host-side functions (not to be called from chugins)
    // constructor
    Chuck_DL_Query( Chuck_Carrier * the_carrier, Chuck_DLL * dll = NULL );
    // desctructor
    ~Chuck_DL_Query() { this->clear(); }
    // clear
    void clear();

public:
    // access to various functions: called from host
    Chuck_VM * vm() const;
    CK_DL_API api() const;
    Chuck_Env * env() const;
    Chuck_Compiler * compiler() const;
    Chuck_Carrier * carrier() const;

public:
    // get sample rate; to be called by host only; (chugins use API->vm->srate)
    t_CKUINT srate();
    // flag any error encountered during the query | 1.5.0.5 (ge) added
    t_CKBOOL errorEncountered;

protected:
    // REFACTOR-2017: carrier ref
    Chuck_Carrier * m_carrier;
    // host sample rate
    t_CKUINT m_srate;
};




//-----------------------------------------------------------------------------
// name: struct Chuck_DL_Class
// desc: class built from module
//-----------------------------------------------------------------------------
struct Chuck_DL_Class
{
    // the name of the class
    std::string name;
    // the name of the parent
    std::string parent;
    // ctor
    std::vector<Chuck_DL_Func *> ctors;
    // dtor
    Chuck_DL_Func * dtor;
    // mfun
    std::vector<Chuck_DL_Func *> mfuns;
    // sfun
    std::vector<Chuck_DL_Func *> sfuns;
    // mdata
    std::vector<Chuck_DL_Value *> mvars;
    // sdata
    std::vector<Chuck_DL_Value *> svars;
    // ugen_tick
    f_tick ugen_tick;
    // ugen_tickf
    f_tickf ugen_tickf;
    // ugen_pmsg
    f_pmsg ugen_pmsg;
    // ugen_ctrl/cget
    std::vector<Chuck_DL_Ctrl *> ugen_ctrl;
    // uana_tock
    f_tock uana_tock;
    // collection of recursive classes
    std::vector<Chuck_DL_Class *> classes;
    // current mvar offset
    t_CKUINT current_mvar_offset;
    // # of ugen input and output channels
    t_CKUINT ugen_num_in, ugen_num_out;
    // ckdoc: class description
    std::string doc;
    // ckdoc: examples
    std::vector<std::string> examples;
    // origin string (e.g., filepath if coming from chugin DLL)
    std::string hint_dll_filepath;

    // constructor
    Chuck_DL_Class() { dtor = NULL; ugen_tick = NULL; ugen_tickf = NULL; ugen_pmsg = NULL; uana_tock = NULL; ugen_pmsg = NULL; current_mvar_offset = 0; ugen_num_in = ugen_num_out = 0; }
    // destructor
    ~Chuck_DL_Class();
};




//-----------------------------------------------------------------------------
// name: struct Chuck_DL_Value
// desc: value from module
//-----------------------------------------------------------------------------
struct Chuck_DL_Value
{
    // the name of the value
    std::string name;
    // the type of the value
    std::string type;
    // is const
    t_CKBOOL is_const;
    // addr static
    void * static_addr;
    // description
    std::string doc;

    // constructor
    Chuck_DL_Value() { is_const = FALSE; static_addr = NULL; }
    Chuck_DL_Value( const char * t, const char * n, t_CKBOOL c = FALSE, void * a = NULL )
    { name = n; type = t; is_const = c; static_addr = a; }
};




//-----------------------------------------------------------------------------
// name: struct Chuck_DL_Func
// desc: function from module
//-----------------------------------------------------------------------------
struct Chuck_DL_Func
{
    // the name of the function
    std::string name;
    // the return type
    std::string type;
    // the function pointer
    union { f_ctor ctor; f_dtor dtor; f_mfun mfun; f_sfun sfun; f_gfun gfun; t_CKUINT addr; };
    // the kind of the function pointer
    ae_FuncPointerKind fpKind;
    // arguments
    std::vector<Chuck_DL_Value *> args;
    // description
    std::string doc;
    // is this an operator overload? if so, which kind? | 1.5.1.5
    ckte_Op_OverloadKind opOverloadKind;
    // operator to overload | 1.5.1.5
    ae_Operator op2overload;

    // constructor
    Chuck_DL_Func() { ctor = NULL; fpKind = ae_fp_unknown; opOverloadKind = ckte_op_overload_NONE; op2overload = ae_op_none; }
    Chuck_DL_Func( const char * t, const char * n, t_CKUINT a, ae_FuncPointerKind kind )
    { name = n?n:""; type = t?t:""; addr = a; fpKind = kind; opOverloadKind = ckte_op_overload_NONE; op2overload = ae_op_none; }
    // destructor
    ~Chuck_DL_Func();
    // add arg
    void add_arg( const char * t, const char * n )
    { args.push_back( new Chuck_DL_Value( t, n ) ); }
};




//-----------------------------------------------------------------------------
// name: struct Chuck_DL_Ctrl
// desc: ctrl for ugen
//-----------------------------------------------------------------------------
struct Chuck_DL_Ctrl
{
    // the name of the ctrl
    std::string name;
    // the first type
    std::string type;
    // the types of the value
    std::vector<std::string> types;
    // ctrl
    f_ctrl ctrl;
    // cget
    f_cget cget;
};




//------------------------------------------------------------------------------
// name: union Chuck_DL_Return
// desc: dynamic link return function return struct
//------------------------------------------------------------------------------
union Chuck_DL_Return
{
    t_CKINT v_int;
    t_CKUINT v_uint;
    t_CKFLOAT v_float;
    t_CKDUR v_dur;
    t_CKTIME v_time;
    t_CKCOMPLEX v_complex;
    t_CKPOLAR v_polar;
    t_CKVEC2 v_vec2; // ge: added 1.5.1.7
    t_CKVEC3 v_vec3; // ge: added 1.3.5.3
    t_CKVEC4 v_vec4; // ge: added 1.3.5.3
    Chuck_Object * v_object;
    Chuck_String * v_string;

    Chuck_DL_Return() { v_vec4.x = v_vec4.y = v_vec4.z = v_vec4.w = 0; }
};




//------------------------------------------------------------------------------
// name: struct Chuck_DL_Arg
// desc: import / dynamic link function argument | 1.5.1.5
//------------------------------------------------------------------------------
struct Chuck_DL_Arg
{
    // which kind of data (e.g., int and object * are both kinds of ints)
    te_KindOf kind;
    // the data in a union; re-using DL_Return for this
    Chuck_DL_Return value;

    // constructor
    Chuck_DL_Arg() { kind = kindof_VOID; }
    // size in bytes
    t_CKUINT sizeInBytes()
    {
        // check data kind
        switch( kind )
        {
            case kindof_INT: return sz_INT;
            case kindof_FLOAT: return sz_FLOAT;
            case kindof_VEC2: return sz_VEC2;
            case kindof_VEC3: return sz_VEC3;
            case kindof_VEC4: return sz_VEC4;
            case kindof_VOID: return sz_VOID;
        }
        // unhandled
        return 0;
    }
};




//------------------------------------------------------------------------------
// alternative functions to make stuff`
//------------------------------------------------------------------------------
Chuck_DL_Func * make_new_ctor( f_ctor ctor );
Chuck_DL_Func * make_new_mfun( const char * t, const char * n, f_mfun mfun );
Chuck_DL_Func * make_new_sfun( const char * t, const char * n, f_sfun sfun );
Chuck_DL_Func * make_new_op_binary( const char * t, ae_Operator op, f_gfun gfun );
Chuck_DL_Func * make_new_op_prefix( const char * t, ae_Operator op, f_gfun gfun );
Chuck_DL_Func * make_new_op_postfix( const char * t, ae_Operator op, f_gfun gfun );
Chuck_DL_Value * make_new_arg( const char * t, const char * n );
Chuck_DL_Value * make_new_mvar( const char * t, const char * n, t_CKBOOL c = FALSE );
Chuck_DL_Value * make_new_svar( const char * t, const char * n, t_CKBOOL c, void * a );




//------------------------------------------------------------------------------
// name: struct Chuck_DL_MainThreadHook
// desc: mechanism for chugins to provide a hook to run code on host main thread
//------------------------------------------------------------------------------
struct Chuck_DL_MainThreadHook
{
public:
    Chuck_DL_MainThreadHook(f_mainthreadhook hook, f_mainthreadquit quit,
                            void * bindle, Chuck_Carrier * carrier);
    t_CKBOOL (CK_DLL_CALL * const activate)(Chuck_DL_MainThreadHook *);
    t_CKBOOL (CK_DLL_CALL * const deactivate)(Chuck_DL_MainThreadHook *);

public:
    Chuck_Carrier * const m_carrier;
    f_mainthreadhook const m_hook;
    f_mainthreadquit const m_quit;
    void * const m_bindle;
    t_CKBOOL m_active;
};




//-----------------------------------------------------------------------------
// instantiating a chuck string
//-----------------------------------------------------------------------------
Chuck_String * CK_DLL_CALL ck_create_string( Chuck_VM * vm, const char * cstr, t_CKBOOL addRef );
//-----------------------------------------------------------------------------
// invoking chuck functions from c++
//-----------------------------------------------------------------------------
// directly invoke a chuck member function's native implementation from c++
// using object + vtable offset | 1.5.1.5 (ge & andrew)
// NOTE this will call the member function in IMMEDIATE MODE,
// marking it as a time-critical function when called in this manner;
// any time/event operations therein will throw an exception
Chuck_DL_Return CK_DLL_CALL ck_invoke_mfun_immediate_mode( Chuck_Object * obj, t_CKUINT func_vt_offset,
                                               Chuck_VM * vm, Chuck_VM_Shred * shred,
                                               Chuck_DL_Arg * ARGS, t_CKUINT numArgs );




//-----------------------------------------------------------------------------
// dynamic linking callable API to ChucK's innards
//-----------------------------------------------------------------------------
struct Chuck_DL_Api
{
    typedef Chuck_Object * Object;
    typedef Chuck_Type * Type;
    typedef Chuck_String * String;
    typedef Chuck_ArrayInt * ArrayInt; // 1.5.0.1 (ge) added
    typedef Chuck_ArrayFloat * ArrayFloat; // 1.5.1.8 (nshaheed) added
    typedef Chuck_ArrayVec2 * ArrayVec2; // 1.5.2.0 (ge) added
    typedef Chuck_ArrayVec3 * ArrayVec3; // 1.5.2.0 (ge) added
    typedef Chuck_ArrayVec4 * ArrayVec4; // 1.5.2.0 (ge) added

public:
    static Chuck_DL_Api g_api;
    static inline const Chuck_DL_Api * instance() { return &g_api; }

    // api to access host-side ChucK virtual machine
    struct VMApi
    {
        VMApi();
        // get sample rate | 1.5.1.5
        t_CKUINT (CK_DLL_CALL * const srate)( Chuck_VM * vm );
        // get chuck now | 1.5.1.5
        t_CKTIME (CK_DLL_CALL * const now)( Chuck_VM * vm );
        // create a new lock-free one-producer, one-consumer buffer | 1.5.1.5
        CBufferSimple * (CK_DLL_CALL * const create_event_buffer)( Chuck_VM * vm );
        // queue an event; num_msg must be 1; buffer should be created using create_event_buffer() above | 1.5.1.5
        t_CKBOOL (CK_DLL_CALL * const queue_event)( Chuck_VM * vm, Chuck_Event * event, t_CKINT num_msg, CBufferSimple * buffer );
        // invoke Chuck_Object member function (defined either in chuck or c++) | 1.5.1.5 (ge & andrew)
        // NOTE this will call the member function in IMMEDIATE MODE,
        // marking it as a time-critical function when called in this manner;
        // any time/event operations therein will throw an exception
        Chuck_DL_Return (CK_DLL_CALL * const invoke_mfun_immediate_mode)( Chuck_Object * obj, t_CKUINT func_vt_offset,
                                                                          Chuck_VM * vm, Chuck_VM_Shred * shred, Chuck_DL_Arg * ARGS, t_CKUINT numArgs );
        // throw an exception; if shred is passed in, it will be halted
        void (CK_DLL_CALL * const throw_exception)( const char * exception, const char * desc, Chuck_VM_Shred * shred );
        // log a message in the chuck logging system
        void (CK_DLL_CALL * const em_log)( t_CKINT level, const char * text );
        // system function: remove all shreds in VM; use with care
        void (CK_DLL_CALL * const remove_all_shreds)( Chuck_VM * vm );
    } * const vm;

    // api to access host-side ChucK objects
    struct ObjectApi
    {
        ObjectApi();

    // 1.5.0.0 (nshaheed and ge and anonymous pr-lab member) | changed from private to public
    // also changed all std::string & in this section to const char *
    // intent: this allows for chugins to access member variables and create chuck strings
    public:
        // function pointer get_type()
        Type (CK_DLL_CALL * const get_type)( Object object );
        // add reference count
        void (CK_DLL_CALL * const add_ref)( Object object );
        // release reference count
        void (CK_DLL_CALL * const release)( Object object );
        // get reference count
        t_CKUINT (CK_DLL_CALL * const refcount)( Object object );
        // instantiating and initializing a ChucK object by type
        // if addRef == TRUE the newly created object will have a reference count of 1; otherwise 0
        // NOTE set addRef to TRUE if you intend to keep a reference of the newly created object around (e.g., in the chugin)
        // NOTE set addRef to FALSE if the created object is to be returned without keeping a reference around
        Object (CK_DLL_CALL * const create)( Chuck_VM_Shred *, Type type, t_CKBOOL addRef );
        // instantiating and initializing a ChucK object by type, using a VM instead of a shred
        Object (CK_DLL_CALL * const create_without_shred)( Chuck_VM *, Type type, t_CKBOOL addRef );
        // instantiate and initialize a ChucK string by type (without ref to a parent shred)
        String (CK_DLL_CALL * const create_string)( Chuck_VM *, const char * value, t_CKBOOL addRef );
        // compute pointer to data segment + offset; use for member variable access | 1.5.2.0
        void * (CK_DLL_CALL * const data)( Object object, t_CKUINT byteOffset );
        // get the origin shred
        Chuck_VM_Shred * (CK_DLL_CALL * const get_origin_shred)( Object object );
        // set the origin shred; this should only be invoked by system-level chugins; use with care
        void (CK_DLL_CALL * const set_origin_shred)( Object object, Chuck_VM_Shred * shred );
        // function pointers for get_mvar_*()
        t_CKBOOL (CK_DLL_CALL * const get_mvar_int)( Object object, const char * name, t_CKINT & value );
        t_CKBOOL (CK_DLL_CALL * const get_mvar_float)( Object object, const char * name, t_CKFLOAT & value );
        t_CKBOOL (CK_DLL_CALL * const get_mvar_dur)( Object object, const char * name, t_CKDUR & value );
        t_CKBOOL (CK_DLL_CALL * const get_mvar_time)( Object object, const char * name, t_CKTIME & value );
        t_CKBOOL (CK_DLL_CALL * const get_mvar_vec2)( Object object, const char * name, t_CKVEC2 & value ); // 1.5.2.0 | vec2/complex/polar
        t_CKBOOL (CK_DLL_CALL * const get_mvar_vec3)( Object object, const char * name, t_CKVEC3 & value ); // 1.5.2.0 | vec3
        t_CKBOOL (CK_DLL_CALL * const get_mvar_vec4)( Object object, const char * name, t_CKVEC4 & value ); // 1.5.2.0 | vec4
        t_CKBOOL (CK_DLL_CALL * const get_mvar_string)( Object object, const char * name, String & value );
        t_CKBOOL (CK_DLL_CALL * const get_mvar_object)( Object object, const char * name, Object & value );
        // function pointer for set_string()
        t_CKBOOL (CK_DLL_CALL * const set_string)( String string, const char * value );
        // get a chuck string's internal c-string (NOTE do not save a reference to the return value; make a copy if needed) | 1.5.2.0
        const char * (CK_DLL_CALL * const str)( Chuck_String * str );
        // array_int operations
        t_CKINT (CK_DLL_CALL * const array_int_size)( ArrayInt array );
        t_CKINT (CK_DLL_CALL * const array_int_get_idx)( ArrayInt array, t_CKINT idx );
        void (CK_DLL_CALL *const array_int_set_idx)( ArrayInt array, t_CKINT idx, t_CKINT value );
        t_CKBOOL (CK_DLL_CALL * const array_int_get_key)( ArrayInt array, const char * key, t_CKINT & value  );
        void (CK_DLL_CALL *const array_int_set_key)( ArrayInt array, const char *key, t_CKINT value );
        t_CKBOOL (CK_DLL_CALL * const array_int_push_back)( ArrayInt array, t_CKINT value );
        void (CK_DLL_CALL * const array_int_clear)( ArrayInt array );
        // array_float operations
        t_CKINT (CK_DLL_CALL * const array_float_size)( ArrayFloat array );
        t_CKFLOAT (CK_DLL_CALL * const array_float_get_idx)( ArrayFloat array, t_CKINT idx );
        void (CK_DLL_CALL *const array_float_set_idx)( ArrayFloat array, t_CKINT idx, t_CKFLOAT value );
        t_CKBOOL (CK_DLL_CALL * const array_float_get_key)( ArrayFloat array, const char * key, t_CKFLOAT & value );
        void (CK_DLL_CALL *const array_float_set_key)( ArrayFloat array, const char *key, t_CKFLOAT value );
        t_CKBOOL (CK_DLL_CALL * const array_float_push_back)( ArrayFloat array, t_CKFLOAT value );
        void (CK_DLL_CALL * const array_float_clear)(ArrayFloat array);
        // array_vec2/complex/polar/16 operations | 1.5.2.0 (ge) added
        t_CKINT (CK_DLL_CALL * const array_vec2_size)( ArrayVec2 array );
        t_CKVEC2 (CK_DLL_CALL * const array_vec2_get_idx)( ArrayVec2 array, t_CKINT idx );
        void (CK_DLL_CALL *const array_vec2_set_idx)( ArrayVec2 array, t_CKINT idx, t_CKVEC2 value );
        t_CKBOOL (CK_DLL_CALL * const array_vec2_get_key)( ArrayVec2 array, const char * key, t_CKVEC2 & value );
        void (CK_DLL_CALL *const array_vec2_set_key)( ArrayVec2 array, const char *key, t_CKVEC2 value );
        t_CKBOOL (CK_DLL_CALL * const array_vec2_push_back)( ArrayVec2 array, const t_CKVEC2 & value );
        void (CK_DLL_CALL * const array_vec2_clear)(ArrayVec2 array);
        // array_vec3/24 operations | 1.5.2.0 (ge) added
        t_CKINT (CK_DLL_CALL * const array_vec3_size)( ArrayVec3 array );
        t_CKVEC3 (CK_DLL_CALL * const array_vec3_get_idx)( ArrayVec3 array, t_CKINT idx );
        void (CK_DLL_CALL *const array_vec3_set_idx)( ArrayVec3 array, t_CKINT idx, t_CKVEC3 value );
        t_CKBOOL (CK_DLL_CALL * const array_vec3_get_key)( ArrayVec3 array, const char * key, t_CKVEC3 & value );
        void (CK_DLL_CALL *const array_vec3_set_key)( ArrayVec3 array, const char *key, t_CKVEC3 value );
        t_CKBOOL (CK_DLL_CALL * const array_vec3_push_back)( ArrayVec3 array, const t_CKVEC3 & value );
        void (CK_DLL_CALL * const array_vec3_clear)(ArrayVec3 array);
        // array_vec4/32 operations | 1.5.2.0 (ge) added
        t_CKINT (CK_DLL_CALL * const array_vec4_size)( ArrayVec4 array );
        t_CKVEC4 (CK_DLL_CALL * const array_vec4_get_idx)( ArrayVec4 array, t_CKINT idx );
        void (CK_DLL_CALL *const array_vec4_set_idx)( ArrayVec4 array, t_CKINT idx, t_CKVEC4 value );
        t_CKBOOL (CK_DLL_CALL * const array_vec4_get_key)( ArrayVec4 array, const char * key, t_CKVEC4 & value );
        void (CK_DLL_CALL *const array_vec4_set_key)( ArrayVec4 array, const char *key, t_CKVEC4 value );
        t_CKBOOL (CK_DLL_CALL * const array_vec4_push_back)( ArrayVec4 array, const t_CKVEC4 & value );
        void (CK_DLL_CALL * const array_vec4_clear)(ArrayVec4 array);
        // (UNSAFE) get c++ vector pointers from chuck arrays | 1.5.2.0
        // std::vector<t_CKUINT> * (CK_DLL_CALL * const array_int_vector)( ArrayInt array );
        // std::vector<t_CKFLOAT> * (CK_DLL_CALL * const array_float_vector)( ArrayFloat array );
        // std::vector<t_CKVEC2> * (CK_DLL_CALL * const array_vec2_vector)( ArrayVec2 array );
        // std::vector<t_CKVEC3> * (CK_DLL_CALL * const array_vec3_vector)( ArrayVec3 array );
        // std::vector<t_CKVEC4> * (CK_DLL_CALL * const array_vec4_vector)( ArrayVec4 array );
    } * const object;

    // access to host-side chuck types
    struct TypeApi
    {
        TypeApi();
        // look up type by name
        Type (CK_DLL_CALL * const lookup)( Chuck_VM *, const char * name );
        // get vtable offset for named function (if overloaded, returns first one); returns < 0 if not found
        t_CKINT (CK_DLL_CALL * const get_vtable_offset)( Chuck_VM *, Type type, const char * funcName );
        // test if two chuck types are equal
        t_CKBOOL (CK_DLL_CALL * const is_equal)(Type lhs, Type rhs);
        // test if lhs is a type of rhs (e.g., SinOsc is a type of UGen)
        t_CKBOOL (CK_DLL_CALL * const isa)(Type lhs, Type rhs);
        // register a callback to be invoked whenever a base-type (or its subclass) is instantiated, with option for type system to auto-set shred origin if available
        void (CK_DLL_CALL * const callback_on_instantiate)( f_callback_on_instantiate callback, Type base_type, Chuck_VM * vm, t_CKBOOL shouldSetShredOrigin );
        // get origin hint ("where did this type originate?")
        ckte_Origin (CK_DLL_CALL * const origin_hint)(Type type);
        // get type name (full, with decorations) (NOTE do not save a reference to the return value; make a copy if needed) | 1.5.2.0
        const char * (CK_DLL_CALL * const name)(Type type);
        // get type base name (no decorations) (NOTE do not save a reference to the return value; make a copy if needed) | 1.5.2.0
        const char * (CK_DLL_CALL * const base_name)(Type type);
    } * const type;

    // api to access host-side shreds | 1.5.2.0
    struct ShredApi
    {
        ShredApi();
        // get shred parent
        Chuck_VM_Shred * (CK_DLL_CALL * const parent)( Chuck_VM_Shred * shred );
    } * const shred;

    // constructor
    Chuck_DL_Api() :
        vm(new VMApi),
        object(new ObjectApi),
        type(new TypeApi),
        shred(new ShredApi)
    { }

private:
    // make this object un-copy-able
    Chuck_DL_Api( Chuck_DL_Api & a ) :
        vm(a.vm),
        object(a.object),
        type(a.type),
        shred(a.shred)
    { assert(0); };
    // make this object un-copy-able, part 2
    Chuck_DL_Api & operator=( Chuck_DL_Api & a ) { assert(0); return a; }
};




//-----------------------------------------------------------------------------
// name: struct Chuck_DLL
// desc: dynamic link library
//-----------------------------------------------------------------------------
struct Chuck_DLL /* : public Chuck_VM_Object */
{
public:
    // load module (chugin/dll) from filename
    t_CKBOOL load( const char * filename,
                   const char * func = CK_QUERY_FUNC,
                   t_CKBOOL lazy = FALSE );
    // load module (internal) from query func
    t_CKBOOL load( f_ck_query query_func, t_CKBOOL lazy = FALSE );
    // get address in loaded ckx
    void * get_addr( const char * symbol );
    // get last error
    const char * last_error() const;
    // unload the ckx
    t_CKBOOL unload();
    // query the content of the dll
    const Chuck_DL_Query * query();
    // probe information about dll without fully loading it
    t_CKBOOL probe();
    // is good
    t_CKBOOL good() const;
    // name
    const char * name() const;
    // full path
    const char * filepath() const;
    // get version major
    t_CKUINT versionMajor();
    // get version minor
    t_CKUINT versionMinor();
    // is version compatible between dll and host
    // major version must be same between chugin and host
    // chugin minor version must less than or equal host minor version
    t_CKBOOL compatible();

public:
    // get info from query
    std::string getinfo( const std::string & key );

public:
    // constructor
    Chuck_DLL( Chuck_Carrier * carrier, const char * xid = NULL )
        : m_handle(NULL), m_id(xid ? xid : ""),
        m_done_query(FALSE), m_api_version_func(NULL), m_info_func(NULL), m_query_func(NULL),
        m_query( carrier, this ), m_apiVersionMajor(0), m_apiVersionMinor(0)
    { }
    // destructor
    ~Chuck_DLL() { this->unload(); }

protected:
    // data
    void * m_handle;
    std::string m_last_error;
    std::string m_filename;
    std::string m_id;
    std::string m_func;
    t_CKBOOL m_done_query;

    // host/client api version
    f_ck_declversion m_api_version_func;
    // chugin info func
    f_ck_info m_info_func;
    // the query func
    f_ck_query m_query_func;
    // the query shuttle object
    Chuck_DL_Query m_query;

protected: // addition info 1.5.0.4 (ge) added
    t_CKUINT m_apiVersionMajor;
    t_CKUINT m_apiVersionMinor;
};




// dlfcn interface
#if defined(__PLATFORM_APPLE__)
#include <AvailabilityMacros.h>
#endif

// dlfcn interface, panther or below
#if defined(__PLATFORM_APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED <= 1030

#error ChucK not support on Mac OS X 10.3 or lower

#elif defined(__PLATFORM_WINDOWS__)

          #ifdef __cplusplus
          extern "C" {
          #endif

          #define RTLD_LAZY         0x1
          #define RTLD_NOW          0x2
          #define RTLD_LOCAL        0x4
          #define RTLD_GLOBAL       0x8
          #define RTLD_NOLOAD       0x10
          #define RTLD_SHARED       0x20    /* not used, the default */
          #define RTLD_UNSHARED     0x40
          #define RTLD_NODELETE     0x80
          #define RTLD_LAZY_UNDEF   0x100

          void * dlopen( const char * path, int mode );
          void * dlsym( void * handle, const char * symbol );
          const char * dlerror( void );
          int dlclose( void * handle );
          // 1.4.2.0 (ge) added DLERROR_BUFFER_LENGTH
          // 1.5.1.5 (ge) increased DLERROR_BUFFER_LENGTH from 128 to 512
          #define DLERROR_BUFFER_LENGTH 512
          static char dlerror_buffer[DLERROR_BUFFER_LENGTH];

          #ifdef __cplusplus
          }
          #endif

#else
  #include "dlfcn.h"
#endif



#endif
