2015-12-09 21:01:04 +01:00
//
// Created by Axel Naumann on 09/12/15.
//
2015-12-10 15:20:01 +01:00
//#include "cling/Interpreter/Jupyter/Kernel.h"
2015-12-09 21:01:04 +01:00
# include "cling/Interpreter/Interpreter.h"
# include "cling/Interpreter/Value.h"
2015-12-10 15:20:01 +01:00
# include <map>
# include <string>
namespace cling {
namespace Jupyter {
struct MIMEDataRef {
const char * m_Data ;
const long m_Size ;
MIMEDataRef ( const std : : string & str ) :
m_Data ( str . c_str ( ) ) , m_Size ( ( long ) str . length ( ) + 1 ) { }
MIMEDataRef ( const char * str ) :
MIMEDataRef ( std : : string ( str ) ) { }
MIMEDataRef ( const char * data , long size ) :
m_Data ( data ) , m_Size ( size ) { }
} ;
/// Push MIME stuff to Jupyter. To be called from user code.
///\param contentDict - dictionary of MIME type versus content. E.g.
/// {{"text/html", {"<div></div>", }}
void pushOutput ( const std : : map < std : : string , MIMEDataRef > contentDict ) {
FILE * outpipe = popen ( " ??? " , " w " ) ;
// Pipe sees (all numbers are longs, except for the first:
// - num bytes in a long (sent as a single unsigned char!)
// - num elements of the MIME dictionary; Jupyter selects one to display.
// For each MIME dictionary element:
// - MIME type as 0-terminated string
// - size of MIME data buffer (including the terminating 0 for
// 0-terminated strings)
// - MIME data buffer
// Write number of dictionary elements (and the size of that number in a
// char)
unsigned char sizeLong = sizeof ( long ) ;
fwrite ( & sizeLong , 1 , 1 , outpipe ) ;
long dictSize = contentDict . size ( ) ;
fwrite ( & dictSize , sizeof ( long ) , 1 , outpipe ) ;
for ( auto iContent : contentDict ) {
const std : : string & mimeType = iContent . first ;
fwrite ( mimeType . c_str ( ) , mimeType . size ( ) + 1 , 1 , outpipe ) ;
const MIMEDataRef & mimeData = iContent . second ;
fwrite ( & mimeData . m_Size , sizeof ( long ) , 1 , outpipe ) ;
fwrite ( mimeData . m_Data , mimeData . m_Size , 1 , outpipe ) ;
}
pclose ( outpipe ) ;
}
} // namespace Jupyter
} // namespace cling
2015-12-09 21:01:04 +01:00
extern " C " {
///\{
///\name Cling4CTypes
/// The Python compatible view of cling
/// The Interpreter object cast to void*
using TheInterpreter = void ;
/// Create an interpreter object.
2015-12-10 15:20:01 +01:00
TheInterpreter *
cling_create ( int argc , const char * argv [ ] , const char * llvmdir ) {
2015-12-10 10:36:55 +01:00
auto interp = new cling : : Interpreter ( argc , argv , llvmdir ) ;
return interp ;
2015-12-09 21:01:04 +01:00
}
2015-12-10 14:13:56 +01:00
/// Destroy the interpreter.
void cling_destroy ( TheInterpreter * interpVP ) {
cling : : Interpreter * interp = ( cling : : Interpreter * ) interpVP ;
delete interp ;
}
2015-12-09 21:01:04 +01:00
/// Evaluate a string of code. Returns 0 on success.
int cling_eval ( TheInterpreter * interpVP , const char * code ) {
cling : : Interpreter * interp = ( cling : : Interpreter * ) interpVP ;
2015-12-10 14:09:09 +01:00
//cling::Value V;
cling : : Interpreter : : CompilationResult Res = interp - > process ( code /*, V*/ ) ;
2015-12-09 21:01:04 +01:00
if ( Res ! = cling : : Interpreter : : kSuccess )
return 1 ;
2015-12-10 15:20:01 +01:00
cling : : Jupyter : : pushOutput ( { { " text/html " , " You just executed C++ code! " } } ) ;
2015-12-09 21:01:04 +01:00
return 0 ;
}
2015-12-10 15:20:01 +01:00
2015-12-10 16:00:46 +01:00
/// Code completion interfaces.
/// Start completion of code. Returns a handle to be passed to
/// cling_complete_next() to iterate over the completion options. Returns nulptr
/// if no completions are known.
void * cling_complete_start ( const char * code ) {
return new int ( 42 ) ;
}
/// Grab the next completion of some code. Returns nullptr if none is left.
const char * cling_complete_next ( void * completionHandle ) {
int * counter = * ( int * ) completionHandle ;
if ( + + ( * counter ) > 43 ) {
delete counter ;
return nullptr ;
}
return " COMPLETE! " ;
}
2015-12-09 21:01:04 +01:00
///\}
2015-12-10 14:09:09 +01:00
} // extern "C"