/* --------------------------------------------------------- *
* __________ 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.Iterator;
import com.sector91.delta.script.DScriptErr;
import com.sector91.delta.script.DScriptExecutor;
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_List;
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 DoInstr extends DSInstr
{
DoInstr(int start, short len, String head, DSInstr[] tail)
{super(start, len, head, tail);}
@Override public DS_Object exec(DS_Scope scope, DScriptExecutor executor)
throws DScriptErr
{
try
{
DS_Object lastVal = null;
for (DSInstr instr : tail)
{
lastVal = instr.exec(scope, executor);
if (executor.returnBreak || executor.loopBreak ||
executor.loopContinue)
break;
}
return lastVal;
}
catch (DScriptErr ex)
{throw rethrow(ex);}
catch (RuntimeException ex)
{throw rethrow(ex);}
}
@Override public InstrType type()
{return InstrType.DO;}
}
final class IfInstr extends DSInstr
{
IfInstr(int start, short len, String car, DSInstr[] cdr)
{super(start, len, car, cdr);}
@Override public DS_Object exec(DS_Scope scope, DScriptExecutor executor)
throws DScriptErr
{
try
{
if (tail[0].exec(scope, executor).booleanValue())
return tail[1].exec(scope, executor);
return DS_Blank.BLANK;
}
catch (DScriptErr ex)
{throw rethrow(ex);}
catch (RuntimeException ex)
{throw rethrow(ex);}
}
@Override public InstrType type()
{return InstrType.IF;}
}
final class CondInstr extends DSInstr
{
CondInstr(int start, short len, String head, DSInstr[] tail)
{super(start, len, head, tail);}
@Override public DS_Object exec(DS_Scope scope, DScriptExecutor executor)
throws DScriptErr
{
try
{
for (int i=0; i<tail.length; i++)
{
final DSInstr branch = tail[i];
if (branch.tail()[0].exec(scope, executor).booleanValue())
return branch.tail()[1].exec(scope, executor);
}
return DS_Blank.BLANK;
}
catch (DScriptErr ex)
{throw rethrow(ex);}
catch (RuntimeException ex)
{throw rethrow(ex);}
}
@Override public InstrType type()
{return InstrType.COND;}
}
final class BranchInstr extends DSInstr
{
BranchInstr(int start, short len, String head, DSInstr[] tail)
{super(start, len, head, tail);}
@Override public DS_Object exec(DS_Scope scope, DScriptExecutor executor)
throws DScriptErr
{
try
{
final DS_Object var = tail[0].exec(scope, executor);
if (var instanceof DS_Callable)
{
final DS_Callable callable = (DS_Callable)var;
for (int i=1; i<tail.length; i++)
{
final DSInstr branch = tail[i];
final DS_Object arg=branch.tail()[0].exec(scope, executor);
if (branch.tail().length == 1)
return arg;
else if (callable.call(arg).booleanValue())
return branch.tail()[1].exec(scope, executor);
}
}
else
{
for (int i=1; i<tail.length; i++)
{
final DSInstr branch = tail[i];
final DS_Object arg=branch.tail()[0].exec(scope, executor);
if (branch.tail().length == 1)
return arg;
else if (var.equals(arg))
return branch.tail()[1].exec(scope, executor);
}
}
return DS_Blank.BLANK;
}
catch (DScriptErr ex)
{throw rethrow(ex);}
catch (RuntimeException ex)
{throw rethrow(ex);}
}
@Override public InstrType type()
{return InstrType.BRANCH;}
}
final class LoopInstr extends DSInstr
{
LoopInstr(int start, short len, String head, DSInstr[] tail)
{super(start, len, head, tail);}
@Override public DS_Object exec(DS_Scope scope, DScriptExecutor executor)
throws DScriptErr
{
try
{
DS_Object lastVal = DS_Blank.BLANK;
final DSInstr loopInstr = tail[0];
while (true)
{
lastVal = loopInstr.exec(scope, executor);
if (executor.returnBreak || executor.loopBreak)
{executor.loopBreak = false; break;}
if (executor.loopContinue)
{executor.loopContinue = false; continue;}
}
return lastVal;
}
catch (DScriptErr ex)
{throw rethrow(ex);}
catch (RuntimeException ex)
{throw rethrow(ex);}
}
@Override public InstrType type()
{return InstrType.LOOP;}
}
final class ForInstr extends DSInstr
{
public final DS_Tag cachedTag;
ForInstr(int start, short len, String head, DSInstr[] tail)
{
super(start, len, head, tail);
cachedTag = DS_Tag.tag(head);
}
@Override public DS_Object exec(DS_Scope scope, DScriptExecutor executor)
throws DScriptErr
{
try
{
DS_Object lastVal = DS_Blank.BLANK;
final DS_Object seq = tail[0].exec(scope, executor);
if (seq instanceof DS_Iterable)
{
final Iterator<DS_Object> iter = ((DS_Iterable)seq).iterator();
final DSInstr loopInstr = tail[1];
while (iter.hasNext())
{
scope.setLocal(cachedTag, iter.next());
lastVal = loopInstr.exec(scope, executor);
if (executor.returnBreak || executor.loopBreak)
{executor.loopBreak = false; break;}
if (executor.loopContinue)
{executor.loopContinue = false; continue;}
}
}
else throw new DScriptErr("Expected Iterable for loop;" +
" got " + seq.getTypeName() + " instead.",
DScriptErr.T_INVALID_TYPE,
DScriptErr.T_NOT_ITERABLE);
return lastVal;
}
catch (DScriptErr ex)
{throw rethrow(ex);}
catch (RuntimeException ex)
{throw rethrow(ex);}
}
@Override public InstrType type()
{return InstrType.FOR;}
}
final class ReturnInstr extends DSInstr
{
ReturnInstr(int start, short len, String head, DSInstr[] tail)
{super(start, len, head, tail);}
@Override public DS_Object exec(DS_Scope scope, DScriptExecutor executor)
throws DScriptErr
{
try
{
if (executor.functionCall)
{
executor.returnBreak = true;
return tail[0].exec(scope, executor);
}
else
throw new DScriptErr("Cannot return outside of a" +
" function.");
}
catch (DScriptErr ex)
{throw rethrow(ex);}
catch (RuntimeException ex)
{throw rethrow(ex);}
}
@Override public InstrType type()
{return InstrType.RETURN;}
}
final class BreakInstr extends DSInstr
{
BreakInstr(int start, short len, String head, DSInstr[] tail)
{super(start, len, head, tail);}
@Override public DS_Blank exec(DS_Scope scope, DScriptExecutor executor)
{
executor.loopBreak = true;
return DS_Blank.BLANK;
}
@Override public InstrType type()
{return InstrType.BREAK;}
}
final class ContinueInstr extends DSInstr
{
ContinueInstr(int start, short len, String head, DSInstr[] tail)
{super(start, len, head, tail);}
@Override public DS_Blank exec(DS_Scope scope, DScriptExecutor executor)
{
executor.loopContinue = true;
return DS_Blank.BLANK;
}
@Override public InstrType type()
{return InstrType.CONTINUE;}
}
final class ExpandInstr extends DSInstr
{
ExpandInstr(int start, short len, String head, DSInstr[] tail)
{super(start, len, head, tail);}
@Override public DS_Iterable exec(DS_Scope scope, DScriptExecutor executor)
throws DScriptErr
{
try
{
final DS_Object obj = tail[0].exec(scope, executor);
if (obj instanceof DS_Iterable)
return (DS_Iterable)obj;
throw new DScriptErr("Only iterable objects may be expanded" +
" with '...'; failed to expand object of type " +
obj.getTypeName() + ".", this);
}
catch (DScriptErr ex)
{throw rethrow(ex);}
catch (RuntimeException ex)
{throw rethrow(ex);}
}
@Override public InstrType type()
{return InstrType.EXPAND;}
}
final class ComprehensionInstr extends DSInstr
{
public final DS_Tag cachedTag;
ComprehensionInstr(int start, short len, String head, DSInstr[] tail)
{
super(start, len, head, tail);
cachedTag = DS_Tag.tag(head);
}
@Override public DS_Iterable exec(DS_Scope scope, DScriptExecutor executor)
throws DScriptErr
{
final DS_List iterable = new DS_List();
try
{
final DS_Object seq = tail[0].exec(scope, executor);
if (seq instanceof DS_Iterable)
{
final Iterator<DS_Object> iter = ((DS_Iterable)seq).iterator();
final DSInstr loopInstr = tail[1];
while (iter.hasNext())
{
scope.setLocal(cachedTag, iter.next());
DS_Object result = loopInstr.exec(scope, executor);
if (executor.returnBreak || executor.loopBreak)
{executor.loopBreak = false; break;}
if (executor.loopContinue)
{executor.loopContinue = false; continue;}
iterable.add(result);
}
}
else throw new DScriptErr("Expected Iterable for" +
" comprehension; got " + seq.getTypeName() + " instead.",
DScriptErr.T_INVALID_TYPE,
DScriptErr.T_NOT_ITERABLE);
}
catch (DScriptErr ex)
{throw rethrow(ex);}
catch (RuntimeException ex)
{throw rethrow(ex);}
return iterable;
}
@Override public InstrType type()
{return InstrType.COMPRH;}
}