/* --------------------------------------------------------- *
* __________ D E L T A S C R I P T *
* (_________() *
* / === / - A fast, dynamic scripting language *
* | == | - Version 4.13.11.0 *
* / === / - Developed by Adam R. Nelson *
* | = = | - 2011-2013 *
* / === / - Distributed under GNU LGPL v3 *
* (________() - http://github.com/ar-nelson/deltascript *
* *
* --------------------------------------------------------- */
package com.sector91.delta.script.instrs;
import java.util.ArrayList;
import java.util.List;
import com.sector91.delta.script.DScriptErr;
import com.sector91.delta.script.DScriptExecutor;
import com.sector91.delta.script.DeltaScript;
import com.sector91.delta.script.objects.DS_Blank;
import com.sector91.delta.script.objects.DS_Callable;
import com.sector91.delta.script.objects.DS_Iterable;
import com.sector91.delta.script.objects.DS_Object;
import com.sector91.delta.script.objects.DS_Scope;
import com.sector91.delta.script.objects.DS_Tag;
final class CallInstr extends DSInstr
{
private final int numArgs;
protected CallInstr(int start, short len, String head, DSInstr[] tail)
{
super(start, len, head, tail);
boolean expand = false;
for (DSInstr instr : tail[1].tail())
if (instr instanceof ExpandInstr)
expand = true;
numArgs = expand ? -1 : tail[1].tail().length;
}
public DS_Object exec(DS_Scope scope, DScriptExecutor executor)
throws DScriptErr
{
try
{
DS_Object[] args;
if (numArgs < 0)
{
final List<DS_Object> argsList = new ArrayList<DS_Object>();
for (DSInstr instr : tail[1].tail())
{
if (instr instanceof ExpandInstr)
{
final DS_Iterable iterable = ((ExpandInstr)instr).exec(
scope, executor);
for (DS_Object obj : iterable)
argsList.add(obj);
}
else
argsList.add(instr.exec(scope, executor));
}
args = argsList.toArray(new DS_Object[argsList.size()]);
}
else
{
args = new DS_Object[numArgs];
for (int i=0; i<numArgs; i++)
args[i] = tail[1].tail()[i].exec(scope, executor);
}
DS_Object callable = tail[0].exec(scope, executor);
try {
return ((DS_Callable)callable).call(args);
} catch (ClassCastException ex) {
throw new DScriptErr("Attempted to call object of type " +
callable.getTypeName() +", which is not callable.",
DScriptErr.T_INVALID_TYPE,
DScriptErr.T_NOT_CALLABLE);
}
}
catch (DScriptErr ex)
{throw rethrow(ex);}
catch (RuntimeException ex)
{throw rethrow(ex);}
}
public InstrType type()
{return InstrType.CALL;}
}
final class StdLibInstr extends DSInstr
{
public final DS_Tag cachedTag;
protected StdLibInstr(int start, short len, String car, DSInstr[] cdr)
{
super(start, len, car, cdr);
cachedTag = DS_Tag.tag(car);
}
public DS_Object exec(DS_Scope scope, DScriptExecutor executor)
throws DScriptErr
{
try
{return DeltaScript.STDLIB.dotGet(cachedTag);}
catch (DScriptErr ex)
{throw rethrow(ex);}
catch (RuntimeException ex)
{throw rethrow(ex);}
}
public InstrType type()
{return InstrType.STDLIB;}
}
final class IncludeInstr extends DSInstr
{
protected IncludeInstr(int start, short len, String head, DSInstr[] tail)
{super(start, len, head, tail);}
public DS_Object exec(DS_Scope scope, DScriptExecutor executor)
throws DScriptErr
{
final DS_Scope scopeToInclude;
final DS_Object toInclude = tail[0].exec(scope, executor);
try
{scopeToInclude = (DS_Scope)toInclude;}
catch (ClassCastException ex)
{
throw new DScriptErr("The 'include' statement can only" +
" include scopes. Got object of type '" +
toInclude.getTypeName() + "' instead.",
DScriptErr.T_INVALID_TYPE);
}
scope.include(scopeToInclude);
return DS_Blank.BLANK;
}
public InstrType type()
{return InstrType.INCLUDE;}
}
final class MetaInstr extends DSInstr
{
protected MetaInstr(int start, short len, String head, DSInstr[] tail)
{super(start, len, head, tail);}
public DS_Object exec(DS_Scope scope, DScriptExecutor executor)
throws DScriptErr
{
// Does nothing.
return DS_Blank.BLANK;
}
public InstrType type()
{return InstrType.META;}
}