/* --------------------------------------------------------- * * __________ 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;} }