/* --------------------------------------------------------- * * __________ 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; import static com.sector91.delta.script.DScriptErr.*; import static com.sector91.util.StringTemplate.$; import java.io.*; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Scanner; import com.sector91.delta.script.annotations.*; import com.sector91.delta.script.module.ModuleLoader; import com.sector91.delta.script.objects.DS_AnonymousCallable; import com.sector91.delta.script.objects.DS_Array; import com.sector91.delta.script.objects.DS_Blank; import com.sector91.delta.script.objects.DS_Boolean; import com.sector91.delta.script.objects.DS_Callable; import com.sector91.delta.script.objects.DS_Decimal; import com.sector91.delta.script.objects.DS_Function; import com.sector91.delta.script.objects.DS_Integer; import com.sector91.delta.script.objects.DS_List; import com.sector91.delta.script.objects.DS_Map; import com.sector91.delta.script.objects.DS_Object; import com.sector91.delta.script.objects.DS_Range; import com.sector91.delta.script.objects.DS_Scalar; import com.sector91.delta.script.objects.DS_Scope; import com.sector91.delta.script.objects.DS_Sequence; import com.sector91.delta.script.objects.DS_Set; import com.sector91.delta.script.objects.DS_String; import com.sector91.delta.script.objects.DS_Tag; import com.sector91.delta.script.objects.DS_Vector; import com.sector91.delta.script.objects.ScalarFactory; import com.sector91.delta.script.objects.VectorFactory; import com.sector91.delta.script.objects.geom.DS_Path2DBuilder; import com.sector91.delta.script.objects.geom.DS_PathBuilder; import com.sector91.delta.script.objects.geom.DS_Shape; import com.sector91.delta.script.objects.geom.DS_Shape2D; import com.sector91.delta.script.objects.io.DS_ReadHandle; import com.sector91.delta.script.objects.reflect.DS_ForeignObject; import com.sector91.delta.script.objects.reflect.DS_JavaClass; import com.sector91.delta.script.parser.DScriptParserException; import com.sector91.geom.Box; import com.sector91.geom.Circle; import com.sector91.geom.Ellipse; import com.sector91.geom.Line; import com.sector91.geom.Rect; import com.sector91.util.Sector91Version; /** * <p>The DeltaScript Standard library, which can be accessed from any * DeltaScript scope with the special variable {@code $StdLib} or the {@code ..} * operator.</p> * * <p>Contains a collection of static Java methods that provide various basic * functions for DeltaScript, such as math operations, typecasting, and access * to system time.</p> * * <p>This class is designed to be wrapped in a {@link DS_JavaClass}, not used * on its own.</p> * * @author Adam R. Nelson * @version 4.13.11.0 */ public class DScriptStandardLibrary { static final DS_Decimal PI = ScalarFactory.fromDouble(Math.PI), E = ScalarFactory.fromDouble(Math.E), POS_INF = ScalarFactory.fromDouble(Double.POSITIVE_INFINITY), NEG_INF = ScalarFactory.fromDouble(Double.NEGATIVE_INFINITY); private DScriptStandardLibrary() {} // Basic Standard Library Methods // // These are the most basic methods needed for // DeltaScript to do anything interesting. // ---------------------------------------------------- /** * <p>Prints a message to the Java console.</p> * * @param message The message to print. */ @DSName("print") public static void print(DS_Object message) {System.out.println(message);} /** * <p>Prints a message to the Java console's error stream.</p> * * @param message The message to print. */ @DSName("printErr") public static void printErr(DS_Object message) {System.err.println(message);} /** * <p>Reads user input from the Java console. This will block until the * user presses Enter.</p> * * @return The input that the user typed. */ @DSName("userInput") public static String userInput() {return userInputTo("\n");} /** * <p>Reads user input from the Java console. This will block until the * user enters the given delimiter.</p> * * @param delimiter The delimiter to read up to. * @return The input that the user typed. */ @DSName("userInputTo") public static String userInputTo(String delimiter) { Scanner s = new Scanner(System.in); s.useDelimiter(delimiter); return s.next(); } /** * <p>Loads and executes a DeltaScript file or package in a new scope.</p> * * <p>This will load any file with a {@code .ds} or {@code .dsc} extension, * or any folder containing a {@code module.ds} file. It creates a new * scope and executes the contents of the file(s) inside that scope; if a * module is loaded, each file in the module becomes a subscope.</p> * * @param filename The path (relative or absolute) of the file to load. * Relative paths are treated as relative to the * @return A new scope, containing any variables, functions or scopes * defined in the executed file(s). Its name will be the same as * the name of the file/package, with any extension removed and any * non-alphanumeric characters replaced with underscores. * @throws DScriptErr If the file cannot be found or loaded, or if an * error occurs while parsing or executing the contents of the * file. */ @DSName("load") public static DS_Scope load(String filename) { if (DScriptContext.get() == null) throw new DScriptErr("No DeltaScript context is loaded."); final File f = new File(filename); try { return (DS_Scope)DeltaScript.execFile(f,DScriptContext.get(),true); } catch (FileNotFoundException ex) { throw new DScriptErr("Could not find script file: " + filename, ex); } catch (IOException ex) { throw new DScriptErr("Error reading script file: " + filename, ex); } catch (DScriptParserException ex) { String line; try { final StringBuilder source = new StringBuilder(); final BufferedReader br = new BufferedReader(new FileReader(f)); while (br.ready()) { source.append(br.readLine()); source.append('\n'); } br.close(); line = "line " + DScriptErr.locateInSource(source.toString(), ex.getLocation())._2._1; } catch (Exception ex2) {line = "(unknown line)";} throw new DScriptErr($("Error parsing file '{}' on {}: {}", filename, line, ex.getMessage())); } } /** * <p>Loads a module as a new scope/object, using the current {@link * ModuleLoader}. A module may be a folder of DeltaScript files, a Java * library, or any other DeltaScript object. All modules should only ever * be loaded once; if a module with the same name has been loaded before, * then the already-loaded instance of the module will be returned.</p> * * @param moduleName The name of the module. Depending on the {@link * ModuleLoader} implementation, this may be treated as a * path, a class name, etc. All {@code ModuleLoader}s * resolve names differently. * @throws DScriptErr If no module with the given name exists, if the * script context does not have permission to load the * module, or if an error occurs while loading the module. */ @DSName("module") public static DS_Object module(String moduleName) { // TODO: Support module loading. throw new UnsupportedOperationException(); // TODO: Add proper tags to the thrown exceptions. /*if (DScriptContext.get() == null) throw new DScriptException("No DeltaScript context is loaded."); ModuleLoader loader = DScriptContext.get().getModuleLoader(); if (loader == null) throw new DScriptException("No module loader is available in" + " this context."); DS_Object module = loader.loadModule(moduleName); if (module == null) throw new DScriptException("No module named \"" + moduleName + "\" is available."); return module; */ } /** * <p>Opens and returns a handle to a resource in the current DeltaScript * package or directory structure. The path will be considered relative to * {@link DeltaScript#getCurrentWorkingDirectory()} of the current * scope's {@link DeltaScript}, or, if the current script is being run * from a package file, will be loaded from a path within the package file * relative to the location of the currently executing script file.</p> * * @param path The path to the resource. Should be a relative path, using * forward slashes as separators and containing no up-directory * ({@code ..}) entries. * @return A {@link DS_ReadHandle} to the resource at the given path. * @throws DScriptErr If the given path is invalid, no resource exists * at the given path, or an error occurs while reading the * resource file. */ @DSName("resource") public static DS_ReadHandle resource(String path) { // TODO: Add this. throw new UnsupportedOperationException(); } @DSName("foreign") public static DS_JavaClass foreign(String fullClassName) { try {return DS_JavaClass.fromClass(Class.forName(fullClassName));} catch (Exception ex) {throw new DScriptErr(ex.getMessage(), ex);} } /** * <p>Throws a {@link DScriptErr} with the given message and tags. The * equivalent of a Java {@code throw} statement.</p> * * @param message The message that the thrown {@link DScriptErr} will * display. * @param tags An array of {@link DS_Tag}s to tag the error with. * @throws DScriptErr Always throws this error, with the given message * and tags. */ @DSName("error") public static void error(String message, DS_Tag... tags) {throw new DScriptErr(message, tags);} /** * <p>Throws a {@link DScriptErr} if the {@link * DS_Object#booleanValue()} method of the given object does not evaluate to * {@code true}. The error thrown will always have the message "Assertion * failed." and the tag {@code 'Assertion}.</p> * * <p>This is the equivalent of a Java {@code assert} statement, but * named differently because {@code assert} is a reserved word in * Java. In DeltaScript, it is still called {@code assert}.</p> * * @param value The object (usually the result of an expression) to assert * the truth value of. * @throws DScriptErr If the given object does not evaluate to * {@code true}. */ @DSName("assert") public static void _assert(DS_Object value) { if (!value.booleanValue()) throw new DScriptErr("Assertion failed.", T_ASSERTION); } /** * <p>Returns a new callable that adds the given tag to a {@link * DScriptErr} and then rethrows the error. Intended to be used as the * {@code error} method of a scope.</p> * * @param tag The tag to add to any errors passed to the returned callable. * @return A new callable that adds the given tag to any error passed to it * and then rethrows the error. */ @DSName("tagAndRelease") public static DS_Callable tagAndRelease(final DS_Tag tag) { return new DS_AnonymousCallable(1) { public DS_Object call(DS_Object... args) { DS_String message = (DS_String)args[0]; DS_Object[] tagObjs = ((DS_Array)args[1]).unbox(); final DS_Tag[] tags = new DS_Tag[tagObjs.length+1]; System.arraycopy(tagObjs, 0, tags, 0, tagObjs.length); tags[tagObjs.length] = tag; throw new DScriptErr(message.unbox(), tags); } }; } @DSName("clone") public static DS_Object clone(DS_Object obj) { try {return obj.clone();} catch (CloneNotSupportedException ex) { throw new DScriptErr("Cannot clone an object of type " + obj.getTypeName() + ".", ex); } } /** * <p>Returns a string representing the type of the given {@link DS_Object}. * This string is retrieved using {@link DS_Object#getTypeName()}.</p> * * @param var The object to get the type of. * @return A string representing the type of the object. */ @DSName("typeName") public static String typeName(DS_Object var) {return var.getTypeName();} /** * <p>Returns a set containing the names of all of the members of the * given object. This set represents all of the valid values for * {@link DS_Object#dotGet(DS_Tag)} for the given object.</p> * * @param var The object to get the members of. * @return A set of the names of the object's members. */ @DSName("members") public static DS_Set members(DS_Object var) {return new DS_Set(var.getMembers());} // Math // // As a game scripting language, DeltaScript is very // math-focused. Most math-related functions are // available both here and as member functions of the // Integer, Decimal, Range and Vector types. // ---------------------------------------------------- /** * <p>Calculates the sine of the given angle.</p> * * @param radians The angle to take the sine of, in radians. * @return The sine of the given angle. */ @DSName("sin") public static DS_Decimal sin(DS_Scalar radians) {return radians.sin();} /** * <p>Calculates the cosine of the given angle.</p> * * @param radians The angle to take the cosine of, in radians. * @return The cosine of the given angle. */ @DSName("cos") public static DS_Decimal cos(DS_Scalar radians) {return radians.cos();} /** * <p>Calculates the tangent of the given angle.</p> * * @param radians The angle to take the tangent of, in radians. * @return The tangent of the given angle. */ @DSName("tan") public static DS_Decimal tan(DS_Scalar radians) {return radians.tan();} /** * <p>Calculates the inverse sine of the given value.</p> * * @param value The sine value to take the inverse of. * @return The angle with a sine of {@code value}, in radians. */ @DSName("asin") public static DS_Decimal asin(DS_Scalar value) {return value.asin();} /** * <p>Calculates the inverse cosine of the given value.</p> * * @param value The cosine value to take the inverse of. * @return The angle with a cosine of {@code value}, in radians. */ @DSName("acos") public static DS_Decimal acos(DS_Scalar value) {return value.acos();} /** * <p>Calculates the inverse tangent of the given value.</p> * * @param value The tangent value to take the inverse of. * @return The angle with a tangent of {@code value}, in radians. */ @DSName("atan") public static DS_Decimal atan(DS_Scalar value) {return value.atan();} /** * <p>Calculates the inverse tangent of {@code y/x}.</p> * * @param y The numerator of the fraction to take the inverse tangent of. * @param x The denominator of the fraction to take the inverse tangent of. * @return The angle with a tangent of {@code y/x}, in radians. */ @DSName("atan2") public static DS_Decimal atan2(DS_Scalar y, DS_Scalar x) { return ScalarFactory.fromDouble(Math.atan2(y.doubleValue(), x.doubleValue())); } /** * <p>Returns a number (1, 0, or -1) representing the sign of the given * number.</p> * * @param num The number to get the sign of. * @return 1 if the given number is positive, 0 if the given number is 0, * or -1 if the given number is negative. */ @DSName({"sgn", "signum"}) public static long sgn(DS_Scalar num) {return num.signum();} /** * <p>Returns the smallest item in the given sequence, based on the items' * {@link DS_Object#compareTo(DS_Object)} methods.</p> * * @param seq The sequence to evaluate. * @return The smallest item in the sequence, the first item if they * evaluate as equivalent, or {@link DS_Blank#BLANK} if the * sequence is empty. * @see #max(DS_Sequence) */ @DSName("min") public static DS_Object min(DS_Object... seq) { DS_Object smallest = DS_Blank.BLANK; for (DS_Object o : seq) { if (smallest == DS_Blank.BLANK || o.compare(smallest) < 0) smallest = o; } return smallest; } /** * <p>Returns the largest item in the given sequence, based on the items' * {@link DS_Object#compareTo(DS_Object)} methods.</p> * * @param seq The sequence to evaluate. * @return The largest item in the sequence, the first item if they * evaluate as equivalent, or {@link DS_Blank#BLANK} if the * sequence is empty. * @see #min(DS_Sequence) */ @DSName("max") public static DS_Object max(DS_Object... seq) { DS_Object largest = DS_Blank.BLANK; for (DS_Object o : seq) { if (largest == DS_Blank.BLANK || o.compare(largest) > 0) largest = o; } return largest; } /** * <p>Calculates a 2-dimensional determinant, which is equal to the * following:</p> * * <p>{@code a*d - b*c}</p> * * @param a The top left entry in the determinant. * @param b The top right entry in the determinant. * @param c The bottom left entry in the determinant. * @param d The bottom right entry in the determinant. * @return {@code a*d - b*c} * @since 3.12.2.0 */ @DSName("det2") public static DS_Scalar det2(DS_Scalar a, DS_Scalar b, DS_Scalar c, DS_Scalar d) { final int nType = a.getNumberType() | b.getNumberType() | c.getNumberType() | d.getNumberType(); return ScalarFactory.sub(ScalarFactory.mul(a, d, nType), ScalarFactory.mul(b, c, nType), nType); } /** * <p>Calculates an <i>N</i>-dimensional determinant, by using the array * of {@link DS_Vector}s passed to the method as the rows of a determinant * matrix. Note that, if you are calculating a 2-dimensional determinant, * {@link #det2(DS_Scalar, DS_Scalar, DS_Scalar, DS_Scalar)} is * <em>significantly</em> faster!</p> * * @param rowVectors An array of {@link DS_Vector}s representing the rows * of the determinant. This array must contain only * vectors, and the number of dimensions of each vector * must be equal to the size of this array. * @return The result of the determinant calculation. * @since 3.12.2.0 */ @DSName({"det", "determinant"}) public static DS_Scalar determinant(DS_Vector... rowVectors) { int size = rowVectors.length; DS_Scalar[][] matrix = new DS_Scalar[size][size]; int nType = 0; for (int y=0; y<rowVectors.length; y++) { DS_Vector v = rowVectors[y]; if (v.dimensions() != size) throw new IllegalArgumentException("The number of dimensions" + " of each vector passed to ..determinant must be the" + " same as the number of vectors."); nType |= v.getNumberType(); for (int x=0; x<size; x++) matrix[x][y] = v.scalarComponent(x); } return determinant(matrix, nType); } @DSInaccessible public static DS_Scalar determinant(DS_Scalar[][] matrix, int nType) { int size = matrix.length; if (size == 2) return det2(matrix[0][0],matrix[1][0],matrix[0][1],matrix[1][1]); DS_Scalar total = ScalarFactory.fromNumber(0, nType); boolean pos = true; for (int dim=0; dim<size; dim++) { DS_Scalar[][] subMatrix = new DS_Scalar[size-1][size-1]; int realx = 0; for (int x=0; x<size-1; x++) { if (realx == dim) realx++; for (int y=0; y<size-1; y++) subMatrix[x][y] = matrix[realx][y+1]; realx++; } total = ScalarFactory.mul( pos ? matrix[dim][0] : matrix[dim][0].negate(), determinant(subMatrix, nType), nType); pos = !pos; } return total; } @DSName("hash") public static DS_Integer hash(DS_Object obj) {return ScalarFactory.fromInt(obj.hashCode());} // Fields and Constants // // These are a combination of mathematical constants // and non-constant values (such as system time) that // make more sense as a property than as a function. // ---------------------------------------------------- @DSName("version") @DSDynamicField public static DS_Array version() { Sector91Version v = DeltaScript.VERSION; if (v.letterSuffix() != null && !v.letterSuffix().isEmpty()) { return new DS_Array(new DS_Object[] { ScalarFactory.fromInt(v.majorVersion()), ScalarFactory.fromInt(v.year()), ScalarFactory.fromInt(v.month()), ScalarFactory.fromInt(v.minorVersion()), new DS_String(v.letterSuffix()) }); } else { return new DS_Array(new DS_Object[] { ScalarFactory.fromInt(v.majorVersion()), ScalarFactory.fromInt(v.year()), ScalarFactory.fromInt(v.month()), ScalarFactory.fromInt(v.minorVersion()) }); } } @DSName("time") @DSDynamicField public static DS_Integer time() {return ScalarFactory.fromLong(System.currentTimeMillis());} @DSName("pi") @DSDynamicField public static DS_Decimal pi() {return PI;} @DSName("e") @DSDynamicField public static DS_Decimal e() {return E;} @DSName({"infinity", "inf"}) @DSDynamicField public static DS_Decimal infinity() {return POS_INF;} @DSName({"negativeInfinity", "neginf"}) @DSDynamicField public static DS_Decimal negativeInfinity() {return NEG_INF;} // Casts // // DeltaScript is dynamically typed, but all objects // still have static Java types under the hood. Because // of this, casts are still sometimes necessary. // ---------------------------------------------------- private static DS_Integer intCast(DS_Object var, int nType) { if (var instanceof DS_String) { try { return (DS_Integer)ScalarFactory.fromString( (String)var.unbox(), nType); } catch (NumberFormatException ex) {throw new DScriptErr(ex.getMessage(), ex);} } else if (var instanceof DS_Scalar) {return (DS_Integer)((DS_Scalar)var).castTo(nType);} else throw new DScriptErr($("Cannot convert {} to {}.", var.getTypeName(), DS_Integer.TYPE_NAME), T_INVALID_TYPE); } /** * <p>Casts the given object to a {@link DS_Integer} with the number type * {@link NumberTypes#SHORT_INT}.</p> * * @param var The object to cast. * @return A {@link DS_Integer} that best represents the given object. * @throws DScriptErr If no cast exists for the given object's type. */ @DSName({"to" + NumberTypes.SUFFIX_SHORT_INT}) public static DS_Integer toShortInt(DS_Object var) {return intCast(var, NumberTypes.SHORT_INT);} /** * <p>Casts the given object to a {@link DS_Integer} with the number type * {@link NumberTypes#LONG_INT}.</p> * * @param var The object to cast. * @return A {@link DS_Integer} that best represents the given object. * @throws DScriptErr If no cast exists for the given object's type. */ @DSName({"to" + NumberTypes.SUFFIX_LONG_INT}) public static DS_Integer toLongInt(DS_Object var) {return intCast(var, NumberTypes.LONG_INT);} /** * <p>Casts the given object to a {@link DS_Integer} with the number type * {@link NumberTypes#REAL_INT}.</p> * * @param var The object to cast. * @return A {@link DS_Integer} that best represents the given object. * @throws DScriptErr If no cast exists for the given object's type. */ @DSName({"to" + NumberTypes.SUFFIX_REAL_INT}) public static DS_Integer toRealInt(DS_Object var) {return intCast(var, NumberTypes.REAL_INT);} private static DS_Decimal decCast(DS_Object var, int nType) { if (var instanceof DS_String) { try { return (DS_Decimal)ScalarFactory.fromString( (String)var.unbox(), nType); } catch (NumberFormatException ex) {throw new DScriptErr(ex.getMessage(), ex);} } else if (var instanceof DS_Scalar) {return (DS_Decimal)((DS_Scalar)var).castTo(nType);} else throw new DScriptErr($("Cannot convert {} to {}.", var.getTypeName(), DS_Scalar.TYPE_NAME), T_INVALID_TYPE); } /** * <p>Casts the given object to a {@link DS_Decimal} with the number type * {@link NumberTypes#SHORT_FLOAT}.</p> * * @param var The object to cast. * @return A {@link DS_Decimal} that best represents the given object. * @throws DScriptErr If no cast exists for the given object's type. */ @DSName({"to" + NumberTypes.SUFFIX_SHORT_FLOAT}) public static DS_Decimal toShortFloat(DS_Object var) {return decCast(var, NumberTypes.SHORT_FLOAT);} /** * <p>Casts the given object to a {@link DS_Decimal} with the number type * {@link NumberTypes#LONG_FLOAT}.</p> * * @param var The object to cast. * @return A {@link DS_Decimal} that best represents the given object. * @throws DScriptErr If no cast exists for the given object's type. */ @DSName({"to" + NumberTypes.SUFFIX_LONG_FLOAT}) public static DS_Decimal toLongFloat(DS_Object var) {return decCast(var, NumberTypes.LONG_FLOAT);} /** * <p>Casts the given object to a {@link DS_Decimal} with the number type * {@link NumberTypes#REAL_DECIMAL}.</p> * * @param var The object to cast. * @return A {@link DS_Decimal} that best represents the given object. * @throws DScriptErr If no cast exists for the given object's type. */ @DSName({"to" + NumberTypes.SUFFIX_REAL_DECIMAL}) public static DS_Decimal toRealDecimal(DS_Object var) {return decCast(var, NumberTypes.REAL_DECIMAL);} @DSName("str") public static DS_String toStr(DS_Object obj) {return new DS_String(obj.toString());} @DSName("tag") public static DS_Tag toTag(DS_Object obj) { if (obj instanceof DS_Tag) return (DS_Tag)obj; return DS_Tag.tag(obj.toString()); } @DSName("int") public static DS_Integer toInt(DS_Object o) { if (o instanceof DS_Scalar) return ((DS_Scalar)o).floor(); else if (o instanceof DS_String) try {return ScalarFactory.fromLong(Long.parseLong(o.toString()));} catch (NumberFormatException ex) {return ScalarFactory.fromBigInteger(new BigInteger(o.toString()));} else throw new DScriptErr("Cannot convert object of type " + o.getTypeName() + " to type Integer."); } @DSName("dec") public static DS_Decimal toDec(DS_Object o) { if (o instanceof DS_Scalar) { final DS_Scalar s = (DS_Scalar)o; if (s instanceof DS_Decimal) return ((DS_Decimal)s); else return (DS_Decimal)s.castTo(s.getNumberType() | NumberTypes.SHORT_FLOAT); } else if (o instanceof DS_String) try {return ScalarFactory.fromDouble(Double.parseDouble(o.toString()));} catch (NumberFormatException ex) {return ScalarFactory.fromBigDecimal(new BigDecimal(o.toString()));} else throw new DScriptErr("Cannot convert object of type " + o.getTypeName() + " to type Decimal."); } @DSName({"array", "arrayOfSize"}) public static DS_Array arrayOfSize(int size) {return new DS_Array(size);} @DSName("list") public static DS_List list(DS_Object... items) {return new DS_List(items);} @DSName("set") public static DS_Set set(DS_Object... items) {return new DS_Set(items);} @DSName("map") public static DS_Map map(DS_Sequence... items) { final DS_Map newMap = new DS_Map(); for (DS_Sequence seq : items) newMap.put(seq.get(0), seq.get(1)); return newMap; } // Type Objects // // Objects that represent the core DeltaScript types. // Used exclusively for typechecking with the 'is' // operator. // ---------------------------------------------------- /** DeltaScript class for {@link DS_String}. */ @DSName(DS_String.TYPE_NAME) @DSDynamicField public static DS_JavaClass stringClass() {return DS_JavaClass.fromClass(DS_String.class);} /** DeltaScript class for {@link DS_Tag}. */ @DSName(DS_Tag.TYPE_NAME) @DSDynamicField public static DS_JavaClass tagClass() {return DS_JavaClass.fromClass(DS_Tag.class);} /** DeltaScript class for {@link DS_Scalar}. */ @DSName(DS_Scalar.TYPE_NAME) @DSDynamicField public static DS_JavaClass scalarClass() {return DS_JavaClass.fromClass(DS_Scalar.class);} /** DeltaScript class for {@link DS_Boolean}. */ @DSName(DS_Boolean.TYPE_NAME) @DSDynamicField public static DS_JavaClass booleanClass() {return DS_JavaClass.fromClass(DS_Boolean.class);} /** DeltaScript class for {@link DS_Integer}. */ @DSName(DS_Integer.TYPE_NAME) @DSDynamicField public static DS_JavaClass integerClass() {return DS_JavaClass.fromClass(DS_Integer.class);} /** DeltaScript class for {@link DS_Decimal}. */ @DSName(DS_Decimal.TYPE_NAME) @DSDynamicField public static DS_JavaClass decimalClass() {return DS_JavaClass.fromClass(DS_Decimal.class);} /** DeltaScript class for {@link DS_Vector}. */ @DSName(DS_Vector.TYPE_NAME) @DSDynamicField public static DS_JavaClass vectorClass() {return DS_JavaClass.fromClass(DS_Vector.class);} /** DeltaScript class for {@link DS_Range}. */ @DSName(DS_Range.TYPE_NAME) @DSDynamicField public static DS_JavaClass rangeClass() {return DS_JavaClass.fromClass(DS_Range.class);} /** DeltaScript class for {@link DS_Array}. */ @DSName(DS_Array.TYPE_NAME) @DSDynamicField public static DS_JavaClass arrayClass() {return DS_JavaClass.fromClass(DS_Array.class);} /** DeltaScript class for {@link DS_List}. */ @DSName(DS_List.TYPE_NAME) @DSDynamicField public static DS_JavaClass listClass() {return DS_JavaClass.fromClass(DS_List.class);} /** DeltaScript class for {@link DS_Set}. */ @DSName(DS_Set.TYPE_NAME) @DSDynamicField public static DS_JavaClass setClass() {return DS_JavaClass.fromClass(DS_Set.class);} /** DeltaScript class for {@link DS_Map}. */ @DSName(DS_Map.TYPE_NAME) @DSDynamicField public static DS_JavaClass mapClass() {return DS_JavaClass.fromClass(DS_Map.class);} /** DeltaScript class for {@link DS_Function}. */ @DSName(DS_Function.TYPE_NAME) @DSDynamicField public static DS_JavaClass functionClass() {return DS_JavaClass.fromClass(DS_Function.class);} /** DeltaScript class for {@link DS_Scope}. */ @DSName(DS_Scope.TYPE_NAME) @DSDynamicField public static DS_JavaClass scopeClass() {return DS_JavaClass.fromClass(DS_Scope.class);} /** DeltaScript class for {@link DS_ForeignObject}. */ @DSName("ForeignObject") @DSDynamicField public static DS_JavaClass foreignObjectClass() {return DS_JavaClass.fromClass(DS_ForeignObject.class);} // TODO: Geometric shape classes. // Fun with Iterators // // Utility methods that use DeltaScript's varargs and // comprehension features to perform powerful iteration // operations. // ---------------------------------------------------- @DSName("count") public static DS_Integer count(DS_Object... items) {return ScalarFactory.fromInt(items.length);} @DSName("fold") public static DS_Object fold(DS_Callable func, DS_Object... items) { if (items.length == 0) return DS_Blank.BLANK; DS_Object result = items[0]; for (int i=1; i<items.length; i++) result = func.call(result, items[i]); return result; } @DSName("sum") public static DS_Object sum(DS_Object... items) { if (items.length == 0) return DS_Blank.BLANK; DS_Object result = items[0]; for (int i=1; i<items.length; i++) result = result.operator(Operator.ADD, items[i]); return result; } // Geometry and Shapes // // Because DeltaScript is primarily a game scripting // language, the geometry module is built in. These // methods are constructors for a variety of geometric // shapes. The geometry library is independent of AWT, // so as to function on any platform. // ---------------------------------------------------- @DSName("line") public static Line line(DS_Vector p1, DS_Vector p2) {return DScriptContext.getContextGeometry().line(p1, p2);} @DSName("box") public static Box box(DS_Vector origin, DS_Vector span) {return DScriptContext.getContextGeometry().box(origin, span);} @DSName("obox") public static Box obox(DS_Vector span) { return box(VectorFactory.zero( NumberTypes.SHORT_FLOAT, span.dimensions()), span); } @DSName("vbox") public static Box vbox(DS_Vector p1, DS_Vector p2) {return box(p1, p2.sub(p1));} @DSName("rect") public static Rect rect(DS_Vector origin, DS_Vector span) {return DScriptContext.getContextGeometry().rect(origin, span);} @DSName("orect") public static Rect orect(DS_Vector span) {return rect(VectorFactory.zero(NumberTypes.SHORT_FLOAT, 2), span);} @DSName("vrect") public static Rect vrect(DS_Vector p1, DS_Vector p2) {return rect(p1, p2.sub(p1));} @DSName("circle") public static Circle circle(DS_Vector pos, DS_Scalar r) {return DScriptContext.getContextGeometry().circle(pos, r.floatValue());} @DSName("ocircle") public static Circle ocircle(DS_Scalar r) {return circle(VectorFactory.zero(NumberTypes.SHORT_FLOAT, 2), r);} @DSName("vcircle") public static Circle vcircle(DS_Vector p1, DS_Vector p2) {return circle(p1, p2.sub(p1).scalarMagnitude());} @DSName("ellipse") public static Ellipse ellipse(DS_Vector pos, DS_Scalar rx, DS_Scalar ry) { return DScriptContext.getContextGeometry().ellipse(pos, rx.floatValue(), ry.floatValue()); } @DSName("oellipse") public static Ellipse oellipse(DS_Scalar rx, DS_Scalar ry) {return ellipse(VectorFactory.zero(NumberTypes.SHORT_FLOAT, 2), rx, ry);} @DSName("vellipse") public static Ellipse vellipse(DS_Vector p1, DS_Vector p2) { DS_Vector diff = p2.sub(p1); return ellipse(p1, diff.scalarComponent(0), diff.scalarComponent(1)); } @DSName("polygon") public static DS_Shape2D polygon(DS_Vector... pts) {return DScriptContext.getContextGeometry().polygon(pts);} @DSName("polyline") public static DS_Shape2D polyline(DS_Vector... pts) {return DScriptContext.getContextGeometry().polyline(pts);} // TODO: Constructor methods for QuadCurve, CubicCurve, CurveND @DSName("path") public static DS_Path2DBuilder path() {return DScriptContext.getContextGeometry().path();} @DSName("path") public static DS_PathBuilder<?> path(DS_Integer dimensions) {return DScriptContext.getContextGeometry().path(dimensions.intValue());} public static DS_Shape emptyShape(DS_Integer dimensions) { return DScriptContext.getContextGeometry().emptyShape( dimensions.intValue()); } }