

DriverCodeType() <-- "c++";
DriverExportCode():=
[
  ToFile("plugin.cc") PatchLoad("plugin.cc.in");
];


DriverDeclareSymbols():=
[
 ForEach(item,predefSymbols) Echo({"LispPtr ",item[2][1],";"});
  // dump local function calls.
 ForEach(item,predefFuncs)
 [
   Local(name);
   Set(name,Clobber(item[1]));
   ForEach(a,item[2])
   [
     Echo({"static void plugin_native_":name:"_":a[1]:"(LispEnvironment& aEnvironment);"});
   ];
 ];
 True;
];

DriverInitializeSymbols():=
[
 ForEach(item,predefSymbols)
   Echo({item[2][1],".Set(",item[2][2],");"});
];

DriverDefineFunctions():=
[
  ForEach(item,predefFuncs)
  [

//Echo({item});
/* */
    Local(name);
    Set(name,Clobber(item[1]));
    ForEach(a,item[2])
    [
     Echo({"static void plugin_native_":name:"_":a[1]:"(LispEnvironment& aEnvironment){"});
      Local(body);
      body:=a[2][3][1][3];
      DriverDumpAsmList(body);
      Echo({"}"});
    ];

    Echo({"
static void plugin_":Clobber(item[1]):"(LispEnvironment& aEnvironment, LispPtr& aResult, LispPtr& aArguments)
PROLOG();
PUSH();
LispInt nr = MakePushArguments(aEnvironment, aArguments);
switch(nr)
{"});

    ForEach(a,item[2])
    [
      Echo({"
case ",a[1],":
	plugin_native_":name:"_":a[1]:"(aEnvironment);
        break;
"});
    ];

Echo({"
default: //TODO return original expression!
  SETTRUE(TOP(0));
  break;
}
COPY(aResult,TOP(0));
POP();
EPILOG();

"});



/* */

/*   
    Echo({"static void plugin_":Clobber(item[1]):"(LispEnvironment& aEnvironment, LispPtr& aResult, LispPtr& aArguments)"});
    Local(body);
//Echo({item[2]});
//Echo({item[2][1]});
//Echo({item[2][1][2][3][1][3]});
    body:=item[2][1][2][3][1][3];
    DriverDumpAsmList(body);

    Echo({""});
*/
  ];
];
DriverDefineFunctionPrototypes():=
[
];


DriverLinkFunctions():=
[
  ForEach(item,predefFuncs)
  [
    Echo({"aEnvironment.SetCommand(plugin_":Clobber(item[1]):", ":String(item[1]):");"});
  ];
  DriverDumpAsmList(initSection);
];

10 # ClobberChar(".") <-- "_dot_";
20 # ClobberChar(_n) <-- n;
Clobber(s_IsString) <--
[
  Local(i,result);
  Set(result,"");
  For(i:=1,i<=Length(s),i++)
    Set(result,result:ClobberChar(s[i]));
  result;
];

//TODO!!! This needs to be written in c++ code!!!
10 # CEscChar("\"") <-- "\\\"";
10 # CEscChar("\\") <-- "\\\\";
10 # CEscChar(
"
") <-- "\\\n";
20 # CEscChar(_n) <-- n;

CEscape(s_IsString) <--
[
  Local(i,result);
  Set(result,"");
  For(i:=1,i<=Length(s),i++)
    Set(result,result:CEscChar(s[i]));
  result;
];


10 # DumpAsmCode(SET(_var,_val)) <--
[
  Echo({"SET(",var,",",val,");"});
];

/* Support for native function call types. */
10 # TypeIsNative("GetPrecision") <-- True;
10 # TypeIsNative("Precision") <-- True;

10 # DumpAsmCode(NATIVE(_native)) <--
[
  Echo({"native.",native,"(aEnvironment);"});
];

10 # DumpAsmCode(NATIVEDEFINED(_native)) <--
[
 Echo({"plugin_native_":native:"(aEnvironment);"});
];



100 # DumpAsmCode(_item) <--
[
  Write(item);
  WriteString(";");
  NewLine();
];

DriverDumpAsmList(list):=
[
  list:=Optimize(list);
  ForEach(item,list)
  [
    DumpAsmCode(item);
  ];
];


// Target-specific optimizations
9 # Compile(Repeat(_nr,_body)) <--
[
  Compile(nr);
  AddAsm(EnterRepeat());
  Compile(body);
  AddAsm(POP());
  AddAsm(LeaveRepeat());
];

10 # DumpAsmCode(EnterRepeat()) <--
[
  Echo({
"
{
  int i;
  int nr=MakeGetInteger(TOP(0));
  for (i=0;i<nr;i++)
  {
"});

];
10 # DumpAsmCode(LeaveRepeat()) <--
[
  Echo({
"
  }
}
SETTRUE(TOP(0));
"});
];

