/* --------------------------------------------------------- *
* __________ 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.DScriptContext;
import com.sector91.delta.script.DScriptErr;
import com.sector91.delta.script.DScriptExecutor;
import com.sector91.delta.script.NumberTypes;
import com.sector91.delta.script.objects.DS_Array;
import com.sector91.delta.script.objects.DS_Blank;
import com.sector91.delta.script.objects.DS_Function;
import com.sector91.delta.script.objects.DS_Iterable;
import com.sector91.delta.script.objects.DS_Map;
import com.sector91.delta.script.objects.DS_Object;
import com.sector91.delta.script.objects.DS_Scalar;
import com.sector91.delta.script.objects.DS_Scope;
import com.sector91.delta.script.objects.DS_String;
import com.sector91.delta.script.objects.DS_Tag;
import com.sector91.delta.script.objects.ScalarFactory;
import com.sector91.delta.script.objects.VectorFactory;
final class NoneInstr extends DSInstr
{
NoneInstr(int start, short len, String head, DSInstr[] tail)
{super(start, len, head, tail);}
public DS_Object exec(DS_Scope scope, DScriptExecutor executor)
{return DS_Blank.BLANK;}
public InstrType type()
{return InstrType.NONE;}
}
final class ScalarInstr extends DSInstr
{
public final DS_Scalar constValue;
ScalarInstr(int start, short len, DScriptContext context, String head,
DSInstr[] tail)
{
super(start, len, head, tail);
constValue = parseConst(context);
}
public DS_Scalar exec(DS_Scope scope, DScriptExecutor executor)
{return constValue;}
public InstrType type()
{return InstrType.SCALAR;}
private final DS_Scalar parseConst(DScriptContext context)
{
if (tail.length > 0)
{
String suffix = tail[0].head;
int nType = NumberTypes.typeForSuffix(suffix);
if (nType < 0)
throw new IllegalStateException("'" + suffix +
"' is not a valid number type suffix.");
return ScalarFactory.fromString(head, nType);
}
else
return ScalarFactory.fromString(head, context);
}
}
final class TagInstr extends DSInstr
{
public final DS_Tag tagValue;
TagInstr(int start, short len, String car, DSInstr[] cdr)
{
super(start, len, car, cdr);
tagValue = DS_Tag.tag(car);
}
public DS_Tag exec(DS_Scope scope, DScriptExecutor executor)
{return tagValue;}
public InstrType type()
{return InstrType.TAG;}
}
final class StringInstr extends DSInstr
{
public final DS_String stringValue;
StringInstr(int start, short len, String car, DSInstr[] cdr)
{
super(start, len, car, cdr);
stringValue = new DS_String(car);
}
public DS_String exec(DS_Scope scope, DScriptExecutor executor)
{return stringValue;}
public InstrType type()
{return InstrType.STRING;}
}
final class ArrayInstr extends DSInstr
{
private final int numItems;
ArrayInstr(int start, short len, String head, DSInstr[] tail)
{
super(start, len, head, tail);
boolean expand = false;
for (DSInstr instr : tail)
if (instr instanceof ExpandInstr)
expand = true;
numItems = expand ? -1 : tail.length;
}
public DS_Object exec(DS_Scope scope, DScriptExecutor executor)
{
DS_Object[] items;
if (numItems < 0)
{
final List<DS_Object> itemsList = new ArrayList<DS_Object>();
for (DSInstr instr : tail)
{
if (instr instanceof ExpandInstr)
{
final DS_Iterable iterable = ((ExpandInstr)instr).exec(
scope, executor);
for (DS_Object obj : iterable)
itemsList.add(obj);
}
else
itemsList.add(instr.exec(scope, executor));
}
items = itemsList.toArray(new DS_Object[itemsList.size()]);
}
else
{
items = new DS_Object[numItems];
for (int i=0; i<numItems; i++)
items[i] = tail[i].exec(scope, executor);
}
return new DS_Array(items);
}
public InstrType type()
{return InstrType.ARRAY;}
}
final class MapInstr extends DSInstr
{
MapInstr(int start, short len, String head, DSInstr[] tail)
{super(start, len, head, tail);}
public DS_Map exec(DS_Scope scope, DScriptExecutor executor)
{
DS_Object[] items = new DS_Object[tail.length];
for (int i=0; i<tail.length; i++)
items[i] = tail[i].exec(scope, executor);
return new DS_Map(items);
}
public InstrType type()
{return InstrType.MAP;}
}
final class VectorInstr extends DSInstr
{
private final int numItems;
VectorInstr(int start, short len, String car, DSInstr[] cdr)
{
super(start, len, car, cdr);
boolean expand = false;
for (DSInstr instr : tail)
if (instr instanceof ExpandInstr)
expand = true;
numItems = expand ? -1 : tail.length;
}
public DS_Object exec(DS_Scope scope, DScriptExecutor executor)
{
try
{
final DS_Object[] components;
if (numItems < 0)
{
final List<DS_Object> itemsList = new ArrayList<DS_Object>();
for (DSInstr instr : tail)
{
if (instr instanceof ExpandInstr)
{
final DS_Iterable iterable = ((ExpandInstr)instr).exec(
scope, executor);
for (DS_Object obj : iterable)
itemsList.add(obj);
}
else
itemsList.add(instr.exec(scope, executor));
}
components = itemsList.toArray(new DS_Object[itemsList.size()]);
}
else
{
components = new DS_Scalar[tail.length];
for (int i=0; i<tail.length; i++)
components[i] = tail[i].exec(scope, executor);
}
final DS_Scalar[] scalars = new DS_Scalar[components.length];
try
{System.arraycopy(components, 0, scalars, 0, components.length);}
catch (ClassCastException ex)
{
throw new DScriptErr("The components of a" +
" Vector must be Scalars.", DScriptErr.T_INVALID_TYPE,
DScriptErr.T_NOT_NUMBER);
}
switch (scalars.length)
{
case 0:
return DS_Blank.BLANK;
case 1:
return scalars[0];
default:
return VectorFactory.fromScalars(scalars);
}
}
catch (DScriptErr ex)
{throw rethrow(ex);}
catch (RuntimeException ex)
{throw rethrow(ex);}
}
public InstrType type()
{return InstrType.VECTOR;}
}
final class ScopeInstr extends DSInstr
{
private final int varCount;
ScopeInstr(int start, short len, String head, DSInstr[] tail)
{
super(start, len, head, tail);
final VarCountVisitor visitor = new VarCountVisitor();
tail[0].accept(visitor);
varCount = visitor.getVariableCount();
}
public DS_Object exec(DS_Scope scope, DScriptExecutor executor)
{
final DS_Scope newScope = scope.createSubscope(varCount);
try
{tail()[0].exec(newScope, executor);}
catch (Exception ex)
{return executor.tryToHandleError(newScope, this, ex);}
return newScope;
}
public InstrType type()
{return InstrType.SCOPE;}
}
final class FuncInstr extends DSInstr
{
private final int varCount;
private final DS_Tag[] args;
FuncInstr(int start, short len, String head, DSInstr[] tail)
{
super(start, len, head, tail);
final DSInstr argsInstr = tail[0];
args = new DS_Tag[argsInstr.tail().length];
for (int i=0;i<argsInstr.tail().length;i++)
args[i] = ((GetInstr)argsInstr.tail()[i]).cachedTag;
final VarCountVisitor visitor = new VarCountVisitor(args);
tail[0].accept(visitor);
tail[1].accept(visitor);
varCount = visitor.getVariableCount();
}
public DS_Object exec(DS_Scope scope, DScriptExecutor executor)
{
try
{
if (tail[1].type() == InstrType.DO)
return new DS_Function(head, tail[1], scope,varCount, args);
else
return new DS_Function(head, tail[1], scope, varCount, args);
}
catch (RuntimeException ex)
{throw rethrow(ex);}
}
public InstrType type()
{return InstrType.FUNC;}
}